From b671e1703394d77163130c91f53b075db1c446bf Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 16 Aug 2017 10:24:32 +0530 Subject: [PATCH 0001/2898] PNP: ide: constify pnp_device_id pnp_device_id are not supposed to change at runtime. All functions working with pnp_device_id provided by work with const pnp_device_id. So mark the non-const structs as const. Signed-off-by: Arvind Yadav Signed-off-by: David S. Miller --- drivers/ide/ide-pnp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index f5f2b62471da..859ddab9448f 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -22,7 +22,7 @@ #define DRV_NAME "ide-pnp" /* Add your devices here :)) */ -static struct pnp_device_id idepnp_devices[] = { +static const struct pnp_device_id idepnp_devices[] = { /* Generic ESDI/IDE/ATA compatible hard disk controller */ {.id = "PNP0600", .driver_data = 0}, {.id = ""} -- GitLab From 9a34b45397e5a389e25a0c5d39983300d040e5e2 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:04:59 +0200 Subject: [PATCH 0002/2898] clk: Add support for runtime PM Registers for some clocks might be located in the SOC area, which are under the power domain. To enable access to those registers respective domain has to be turned on. Additionally, registers for such clocks will usually loose its contents when power domain is turned off, so additional saving and restoring of them might be needed in the clock controller driver. This patch adds basic infrastructure in the clocks core to allow implementing driver for such clocks under power domains. Clock provider can supply a struct device pointer, which is the used by clock core for tracking and managing clock's controller runtime pm state. Each clk_prepare() operation will first call pm_runtime_get_sync() on the supplied device, while clk_unprepare() will do pm_runtime_put_sync() at the end. Additional calls to pm_runtime_get/put functions are required to ensure that any register access (like calculating/changing clock rates and unpreparing/disabling unused clocks on boot) will be done with clock controller in runtime resumend state. When one wants to register clock controller, which make use of this feature, he has to: 1. Provide a struct device to the core when registering the provider. 2. Ensure to enable runtime PM for that device before registering clocks. 3. Make sure that the runtime PM status of the controller device reflects the HW state. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Acked-by: Krzysztof Kozlowski Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-2-git-send-email-m.szyprowski@samsung.com --- drivers/clk/clk.c | 126 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 112 insertions(+), 14 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fc58c52a26b4..5bb6308fbf0d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,7 @@ struct clk_core { const struct clk_ops *ops; struct clk_hw *hw; struct module *owner; + struct device *dev; struct clk_core *parent; const char **parent_names; struct clk_core **parents; @@ -87,6 +89,26 @@ struct clk { struct hlist_node clks_node; }; +/*** runtime pm ***/ +static int clk_pm_runtime_get(struct clk_core *core) +{ + int ret = 0; + + if (!core->dev) + return 0; + + ret = pm_runtime_get_sync(core->dev); + return ret < 0 ? ret : 0; +} + +static void clk_pm_runtime_put(struct clk_core *core) +{ + if (!core->dev) + return; + + pm_runtime_put_sync(core->dev); +} + /*** locking ***/ static void clk_prepare_lock(void) { @@ -150,6 +172,8 @@ static void clk_enable_unlock(unsigned long flags) static bool clk_core_is_prepared(struct clk_core *core) { + bool ret = false; + /* * .is_prepared is optional for clocks that can prepare * fall back to software usage counter if it is missing @@ -157,11 +181,18 @@ static bool clk_core_is_prepared(struct clk_core *core) if (!core->ops->is_prepared) return core->prepare_count; - return core->ops->is_prepared(core->hw); + if (!clk_pm_runtime_get(core)) { + ret = core->ops->is_prepared(core->hw); + clk_pm_runtime_put(core); + } + + return ret; } static bool clk_core_is_enabled(struct clk_core *core) { + bool ret = false; + /* * .is_enabled is only mandatory for clocks that gate * fall back to software usage counter if .is_enabled is missing @@ -169,7 +200,29 @@ static bool clk_core_is_enabled(struct clk_core *core) if (!core->ops->is_enabled) return core->enable_count; - return core->ops->is_enabled(core->hw); + /* + * Check if clock controller's device is runtime active before + * calling .is_enabled callback. If not, assume that clock is + * disabled, because we might be called from atomic context, from + * which pm_runtime_get() is not allowed. + * This function is called mainly from clk_disable_unused_subtree, + * which ensures proper runtime pm activation of controller before + * taking enable spinlock, but the below check is needed if one tries + * to call it from other places. + */ + if (core->dev) { + pm_runtime_get_noresume(core->dev); + if (!pm_runtime_active(core->dev)) { + ret = false; + goto done; + } + } + + ret = core->ops->is_enabled(core->hw); +done: + clk_pm_runtime_put(core); + + return ret; } /*** helper functions ***/ @@ -489,6 +542,8 @@ static void clk_core_unprepare(struct clk_core *core) if (core->ops->unprepare) core->ops->unprepare(core->hw); + clk_pm_runtime_put(core); + trace_clk_unprepare_complete(core); clk_core_unprepare(core->parent); } @@ -530,10 +585,14 @@ static int clk_core_prepare(struct clk_core *core) return 0; if (core->prepare_count == 0) { - ret = clk_core_prepare(core->parent); + ret = clk_pm_runtime_get(core); if (ret) return ret; + ret = clk_core_prepare(core->parent); + if (ret) + goto runtime_put; + trace_clk_prepare(core); if (core->ops->prepare) @@ -541,15 +600,18 @@ static int clk_core_prepare(struct clk_core *core) trace_clk_prepare_complete(core); - if (ret) { - clk_core_unprepare(core->parent); - return ret; - } + if (ret) + goto unprepare; } core->prepare_count++; return 0; +unprepare: + clk_core_unprepare(core->parent); +runtime_put: + clk_pm_runtime_put(core); + return ret; } static int clk_core_prepare_lock(struct clk_core *core) @@ -745,6 +807,9 @@ static void clk_unprepare_unused_subtree(struct clk_core *core) if (core->flags & CLK_IGNORE_UNUSED) return; + if (clk_pm_runtime_get(core)) + return; + if (clk_core_is_prepared(core)) { trace_clk_unprepare(core); if (core->ops->unprepare_unused) @@ -753,6 +818,8 @@ static void clk_unprepare_unused_subtree(struct clk_core *core) core->ops->unprepare(core->hw); trace_clk_unprepare_complete(core); } + + clk_pm_runtime_put(core); } static void clk_disable_unused_subtree(struct clk_core *core) @@ -768,6 +835,9 @@ static void clk_disable_unused_subtree(struct clk_core *core) if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_prepare_enable(core->parent); + if (clk_pm_runtime_get(core)) + goto unprepare_out; + flags = clk_enable_lock(); if (core->enable_count) @@ -792,6 +862,8 @@ static void clk_disable_unused_subtree(struct clk_core *core) unlock_out: clk_enable_unlock(flags); + clk_pm_runtime_put(core); +unprepare_out: if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_disable_unprepare(core->parent); } @@ -1038,9 +1110,13 @@ EXPORT_SYMBOL_GPL(clk_get_accuracy); static unsigned long clk_recalc(struct clk_core *core, unsigned long parent_rate) { - if (core->ops->recalc_rate) - return core->ops->recalc_rate(core->hw, parent_rate); - return parent_rate; + unsigned long rate = parent_rate; + + if (core->ops->recalc_rate && !clk_pm_runtime_get(core)) { + rate = core->ops->recalc_rate(core->hw, parent_rate); + clk_pm_runtime_put(core); + } + return rate; } /** @@ -1565,6 +1641,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core, { struct clk_core *top, *fail_clk; unsigned long rate = req_rate; + int ret = 0; if (!core) return 0; @@ -1581,21 +1658,28 @@ static int clk_core_set_rate_nolock(struct clk_core *core, if (!top) return -EINVAL; + ret = clk_pm_runtime_get(core); + if (ret) + return ret; + /* notify that we are about to change rates */ fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE); if (fail_clk) { pr_debug("%s: failed to set %s rate\n", __func__, fail_clk->name); clk_propagate_rate_change(top, ABORT_RATE_CHANGE); - return -EBUSY; + ret = -EBUSY; + goto err; } /* change the rates */ clk_change_rate(top); core->req_rate = req_rate; +err: + clk_pm_runtime_put(core); - return 0; + return ret; } /** @@ -1826,12 +1910,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent) p_rate = parent->rate; } + ret = clk_pm_runtime_get(core); + if (ret) + goto out; + /* propagate PRE_RATE_CHANGE notifications */ ret = __clk_speculate_rates(core, p_rate); /* abort if a driver objects */ if (ret & NOTIFY_STOP_MASK) - goto out; + goto runtime_put; /* do the re-parent */ ret = __clk_set_parent(core, parent, p_index); @@ -1844,6 +1932,8 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent) __clk_recalc_accuracies(core); } +runtime_put: + clk_pm_runtime_put(core); out: clk_prepare_unlock(); @@ -2350,7 +2440,7 @@ static inline void clk_debug_unregister(struct clk_core *core) */ static int __clk_core_init(struct clk_core *core) { - int i, ret = 0; + int i, ret; struct clk_core *orphan; struct hlist_node *tmp2; unsigned long rate; @@ -2360,6 +2450,10 @@ static int __clk_core_init(struct clk_core *core) clk_prepare_lock(); + ret = clk_pm_runtime_get(core); + if (ret) + goto unlock; + /* check to see if a clock with this name is already registered */ if (clk_core_lookup(core->name)) { pr_debug("%s: clk %s already initialized\n", @@ -2512,6 +2606,8 @@ static int __clk_core_init(struct clk_core *core) kref_init(&core->ref); out: + clk_pm_runtime_put(core); +unlock: clk_prepare_unlock(); if (!ret) @@ -2583,6 +2679,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) goto fail_name; } core->ops = hw->init->ops; + if (dev && pm_runtime_enabled(dev)) + core->dev = dev; if (dev && dev->driver) core->owner = dev->driver->owner; core->hw = hw; -- GitLab From d2f18d7e200b8714beffd4eae7f27335b311b2d5 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:05:00 +0200 Subject: [PATCH 0003/2898] clk: samsung: Add support for runtime PM This patch adds struct device pointer to samsung_clk_provider and forwarding it to clk_register_* functions, so drivers can register clocks, which use runtime pm feature. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Reviewed-by: Chanwoo Choi Tested-by: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-3-git-send-email-m.szyprowski@samsung.com --- drivers/clk/samsung/clk-pll.c | 2 +- drivers/clk/samsung/clk.c | 12 ++++++------ drivers/clk/samsung/clk.h | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 037c61484098..41ebb94d2855 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -1388,7 +1388,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, pll->lock_reg = base + pll_clk->lock_offset; pll->con_reg = base + pll_clk->con_offset; - ret = clk_hw_register(NULL, &pll->hw); + ret = clk_hw_register(ctx->dev, &pll->hw); if (ret) { pr_err("%s: failed to register pll clock %s : %d\n", __func__, pll_clk->name, ret); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 7ce0fa86c5ff..aef97b091b50 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -134,7 +134,7 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx, unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { - clk_hw = clk_hw_register_fixed_rate(NULL, list->name, + clk_hw = clk_hw_register_fixed_rate(ctx->dev, list->name, list->parent_name, list->flags, list->fixed_rate); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, @@ -163,7 +163,7 @@ void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx, unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { - clk_hw = clk_hw_register_fixed_factor(NULL, list->name, + clk_hw = clk_hw_register_fixed_factor(ctx->dev, list->name, list->parent_name, list->flags, list->mult, list->div); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, @@ -184,7 +184,7 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { - clk_hw = clk_hw_register_mux(NULL, list->name, + clk_hw = clk_hw_register_mux(ctx->dev, list->name, list->parent_names, list->num_parents, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->mux_flags, &ctx->lock); @@ -217,13 +217,13 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, for (idx = 0; idx < nr_clk; idx++, list++) { if (list->table) - clk_hw = clk_hw_register_divider_table(NULL, + clk_hw = clk_hw_register_divider_table(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->div_flags, list->table, &ctx->lock); else - clk_hw = clk_hw_register_divider(NULL, list->name, + clk_hw = clk_hw_register_divider(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->div_flags, &ctx->lock); @@ -255,7 +255,7 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { - clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name, + clk_hw = clk_hw_register_gate(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->bit_idx, list->gate_flags, &ctx->lock); if (IS_ERR(clk_hw)) { diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index b8ca0dd3a38b..f0acae4f5d1b 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -24,6 +24,7 @@ */ struct samsung_clk_provider { void __iomem *reg_base; + struct device *dev; spinlock_t lock; /* clk_data must be the last entry due to variable lenght 'hws' array */ struct clk_hw_onecell_data clk_data; -- GitLab From 523d3de41f02141f6f6cd497d07946a2837432cf Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:05:01 +0200 Subject: [PATCH 0004/2898] clk: samsung: exynos5433: Add support for runtime PM Add runtime pm support for all clock controller units (CMU), which belong to power domains and require special handling during on/off operations. Typically special values has to be written to MUX registers to change internal clocks parents to OSC clock before turning power off. During such operation all clocks, which enter CMU has to be enabled to let MUX to stabilize. Also for each CMU there is one special parent clock, which has to be enabled all the time when any access to CMU registers is being done. This patch solves most of the mysterious external abort and freeze issues caused by a lack of proper parent CMU clock enabled or incorrect turn off procedure. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Reviewed-by: Chanwoo Choi Tested-by: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-4-git-send-email-m.szyprowski@samsung.com --- .../bindings/clock/exynos5433-clock.txt | 16 + drivers/clk/samsung/clk-exynos5433.c | 409 ++++++++++++++---- drivers/clk/samsung/clk.h | 6 + 3 files changed, 346 insertions(+), 85 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt index 1dc80f8811fe..5c7dd12e667a 100644 --- a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt @@ -168,6 +168,11 @@ Required Properties: - aclk_cam1_400 - aclk_cam1_552 +Optional properties: + - power-domains: a phandle to respective power domain node as described by + generic PM domain bindings (see power/power_domain.txt for more + information). + Each clock is assigned an identifier and client nodes can use this identifier to specify the clock which they consume. @@ -270,6 +275,7 @@ Example 2: Examples of clock controller nodes are listed below. clocks = <&xxti>, <&cmu_top CLK_ACLK_G2D_266>, <&cmu_top CLK_ACLK_G2D_400>; + power-domains = <&pd_g2d>; }; cmu_disp: clock-controller@13b90000 { @@ -295,6 +301,7 @@ Example 2: Examples of clock controller nodes are listed below. <&cmu_mif CLK_SCLK_DECON_ECLK_DISP>, <&cmu_mif CLK_SCLK_DECON_TV_VCLK_DISP>, <&cmu_mif CLK_ACLK_DISP_333>; + power-domains = <&pd_disp>; }; cmu_aud: clock-controller@114c0000 { @@ -304,6 +311,7 @@ Example 2: Examples of clock controller nodes are listed below. clock-names = "oscclk", "fout_aud_pll"; clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>; + power-domains = <&pd_aud>; }; cmu_bus0: clock-controller@13600000 { @@ -340,6 +348,7 @@ Example 2: Examples of clock controller nodes are listed below. clock-names = "oscclk", "aclk_g3d_400"; clocks = <&xxti>, <&cmu_top CLK_ACLK_G3D_400>; + power-domains = <&pd_g3d>; }; cmu_gscl: clock-controller@13cf0000 { @@ -353,6 +362,7 @@ Example 2: Examples of clock controller nodes are listed below. clocks = <&xxti>, <&cmu_top CLK_ACLK_GSCL_111>, <&cmu_top CLK_ACLK_GSCL_333>; + power-domains = <&pd_gscl>; }; cmu_apollo: clock-controller@11900000 { @@ -384,6 +394,7 @@ Example 2: Examples of clock controller nodes are listed below. clocks = <&xxti>, <&cmu_top CLK_SCLK_JPEG_MSCL>, <&cmu_top CLK_ACLK_MSCL_400>; + power-domains = <&pd_mscl>; }; cmu_mfc: clock-controller@15280000 { @@ -393,6 +404,7 @@ Example 2: Examples of clock controller nodes are listed below. clock-names = "oscclk", "aclk_mfc_400"; clocks = <&xxti>, <&cmu_top CLK_ACLK_MFC_400>; + power-domains = <&pd_mfc>; }; cmu_hevc: clock-controller@14f80000 { @@ -402,6 +414,7 @@ Example 2: Examples of clock controller nodes are listed below. clock-names = "oscclk", "aclk_hevc_400"; clocks = <&xxti>, <&cmu_top CLK_ACLK_HEVC_400>; + power-domains = <&pd_hevc>; }; cmu_isp: clock-controller@146d0000 { @@ -415,6 +428,7 @@ Example 2: Examples of clock controller nodes are listed below. clocks = <&xxti>, <&cmu_top CLK_ACLK_ISP_DIS_400>, <&cmu_top CLK_ACLK_ISP_400>; + power-domains = <&pd_isp>; }; cmu_cam0: clock-controller@120d0000 { @@ -430,6 +444,7 @@ Example 2: Examples of clock controller nodes are listed below. <&cmu_top CLK_ACLK_CAM0_333>, <&cmu_top CLK_ACLK_CAM0_400>, <&cmu_top CLK_ACLK_CAM0_552>; + power-domains = <&pd_cam0>; }; cmu_cam1: clock-controller@145d0000 { @@ -451,6 +466,7 @@ Example 2: Examples of clock controller nodes are listed below. <&cmu_top CLK_ACLK_CAM1_333>, <&cmu_top CLK_ACLK_CAM1_400>, <&cmu_top CLK_ACLK_CAM1_552>; + power-domains = <&pd_cam1>; }; Example 3: UART controller node that consumes the clock generated by the clock diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 11343a597093..cd9337613dd8 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -9,9 +9,13 @@ * Common Clock Framework support for Exynos5433 SoC. */ +#include #include #include #include +#include +#include +#include #include @@ -1991,6 +1995,14 @@ static const unsigned long fsys_clk_regs[] __initconst = { ENABLE_IP_FSYS1, }; +static const struct samsung_clk_reg_dump fsys_suspend_regs[] = { + { MUX_SEL_FSYS0, 0 }, + { MUX_SEL_FSYS1, 0 }, + { MUX_SEL_FSYS2, 0 }, + { MUX_SEL_FSYS3, 0 }, + { MUX_SEL_FSYS4, 0 }, +}; + static const struct samsung_fixed_rate_clock fsys_fixed_clks[] __initconst = { /* PHY clocks from USBDRD30_PHY */ FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY, @@ -2296,16 +2308,11 @@ static const struct samsung_cmu_info fsys_cmu_info __initconst = { .nr_clk_ids = FSYS_NR_CLK, .clk_regs = fsys_clk_regs, .nr_clk_regs = ARRAY_SIZE(fsys_clk_regs), + .suspend_regs = fsys_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(fsys_suspend_regs), + .clk_name = "aclk_fsys_200", }; -static void __init exynos5433_cmu_fsys_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &fsys_cmu_info); -} - -CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys", - exynos5433_cmu_fsys_init); - /* * Register offset definitions for CMU_G2D */ @@ -2335,6 +2342,10 @@ static const unsigned long g2d_clk_regs[] __initconst = { DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D, }; +static const struct samsung_clk_reg_dump g2d_suspend_regs[] = { + { MUX_SEL_G2D0, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_aclk_g2d_266_user_p) = { "oscclk", "aclk_g2d_266", }; PNAME(mout_aclk_g2d_400_user_p) = { "oscclk", "aclk_g2d_400", }; @@ -2420,16 +2431,11 @@ static const struct samsung_cmu_info g2d_cmu_info __initconst = { .nr_clk_ids = G2D_NR_CLK, .clk_regs = g2d_clk_regs, .nr_clk_regs = ARRAY_SIZE(g2d_clk_regs), + .suspend_regs = g2d_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(g2d_suspend_regs), + .clk_name = "aclk_g2d_400", }; -static void __init exynos5433_cmu_g2d_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &g2d_cmu_info); -} - -CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d", - exynos5433_cmu_g2d_init); - /* * Register offset definitions for CMU_DISP */ @@ -2494,6 +2500,18 @@ static const unsigned long disp_clk_regs[] __initconst = { CLKOUT_CMU_DISP_DIV_STAT, }; +static const struct samsung_clk_reg_dump disp_suspend_regs[] = { + /* PLL has to be enabled for suspend */ + { DISP_PLL_CON0, 0x85f40502 }, + /* ignore status of external PHY muxes during suspend to avoid hangs */ + { MUX_IGNORE_DISP2, 0x00111111 }, + { MUX_SEL_DISP0, 0 }, + { MUX_SEL_DISP1, 0 }, + { MUX_SEL_DISP2, 0 }, + { MUX_SEL_DISP3, 0 }, + { MUX_SEL_DISP4, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_disp_pll_p) = { "oscclk", "fout_disp_pll", }; PNAME(mout_sclk_dsim1_user_p) = { "oscclk", "sclk_dsim1_disp", }; @@ -2841,16 +2859,11 @@ static const struct samsung_cmu_info disp_cmu_info __initconst = { .nr_clk_ids = DISP_NR_CLK, .clk_regs = disp_clk_regs, .nr_clk_regs = ARRAY_SIZE(disp_clk_regs), + .suspend_regs = disp_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(disp_suspend_regs), + .clk_name = "aclk_disp_333", }; -static void __init exynos5433_cmu_disp_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &disp_cmu_info); -} - -CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp", - exynos5433_cmu_disp_init); - /* * Register offset definitions for CMU_AUD */ @@ -2885,6 +2898,11 @@ static const unsigned long aud_clk_regs[] __initconst = { ENABLE_IP_AUD1, }; +static const struct samsung_clk_reg_dump aud_suspend_regs[] = { + { MUX_SEL_AUD0, 0 }, + { MUX_SEL_AUD1, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_aud_pll_user_aud_p) = { "oscclk", "fout_aud_pll", }; PNAME(mout_sclk_aud_pcm_p) = { "mout_aud_pll_user", "ioclk_audiocdclk0",}; @@ -3011,16 +3029,11 @@ static const struct samsung_cmu_info aud_cmu_info __initconst = { .nr_clk_ids = AUD_NR_CLK, .clk_regs = aud_clk_regs, .nr_clk_regs = ARRAY_SIZE(aud_clk_regs), + .suspend_regs = aud_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(aud_suspend_regs), + .clk_name = "fout_aud_pll", }; -static void __init exynos5433_cmu_aud_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &aud_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_aud, "samsung,exynos5433-cmu-aud", - exynos5433_cmu_aud_init); - - /* * Register offset definitions for CMU_BUS{0|1|2} */ @@ -3222,6 +3235,10 @@ static const unsigned long g3d_clk_regs[] __initconst = { CLK_STOPCTRL, }; +static const struct samsung_clk_reg_dump g3d_suspend_regs[] = { + { MUX_SEL_G3D, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_aclk_g3d_400_p) = { "mout_g3d_pll", "aclk_g3d_400", }; PNAME(mout_g3d_pll_p) = { "oscclk", "fout_g3d_pll", }; @@ -3295,15 +3312,11 @@ static const struct samsung_cmu_info g3d_cmu_info __initconst = { .nr_clk_ids = G3D_NR_CLK, .clk_regs = g3d_clk_regs, .nr_clk_regs = ARRAY_SIZE(g3d_clk_regs), + .suspend_regs = g3d_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(g3d_suspend_regs), + .clk_name = "aclk_g3d_400", }; -static void __init exynos5433_cmu_g3d_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &g3d_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d", - exynos5433_cmu_g3d_init); - /* * Register offset definitions for CMU_GSCL */ @@ -3342,6 +3355,12 @@ static const unsigned long gscl_clk_regs[] __initconst = { ENABLE_IP_GSCL_SECURE_SMMU_GSCL2, }; +static const struct samsung_clk_reg_dump gscl_suspend_regs[] = { + { MUX_SEL_GSCL, 0 }, + { ENABLE_ACLK_GSCL, 0xfff }, + { ENABLE_PCLK_GSCL, 0xff }, +}; + /* list of all parent clock list */ PNAME(aclk_gscl_111_user_p) = { "oscclk", "aclk_gscl_111", }; PNAME(aclk_gscl_333_user_p) = { "oscclk", "aclk_gscl_333", }; @@ -3436,15 +3455,11 @@ static const struct samsung_cmu_info gscl_cmu_info __initconst = { .nr_clk_ids = GSCL_NR_CLK, .clk_regs = gscl_clk_regs, .nr_clk_regs = ARRAY_SIZE(gscl_clk_regs), + .suspend_regs = gscl_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(gscl_suspend_regs), + .clk_name = "aclk_gscl_111", }; -static void __init exynos5433_cmu_gscl_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &gscl_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl", - exynos5433_cmu_gscl_init); - /* * Register offset definitions for CMU_APOLLO */ @@ -3970,6 +3985,11 @@ static const unsigned long mscl_clk_regs[] __initconst = { ENABLE_IP_MSCL_SECURE_SMMU_JPEG, }; +static const struct samsung_clk_reg_dump mscl_suspend_regs[] = { + { MUX_SEL_MSCL0, 0 }, + { MUX_SEL_MSCL1, 0 }, +}; + /* list of all parent clock list */ PNAME(mout_sclk_jpeg_user_p) = { "oscclk", "sclk_jpeg_mscl", }; PNAME(mout_aclk_mscl_400_user_p) = { "oscclk", "aclk_mscl_400", }; @@ -4082,15 +4102,11 @@ static const struct samsung_cmu_info mscl_cmu_info __initconst = { .nr_clk_ids = MSCL_NR_CLK, .clk_regs = mscl_clk_regs, .nr_clk_regs = ARRAY_SIZE(mscl_clk_regs), + .suspend_regs = mscl_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(mscl_suspend_regs), + .clk_name = "aclk_mscl_400", }; -static void __init exynos5433_cmu_mscl_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &mscl_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl", - exynos5433_cmu_mscl_init); - /* * Register offset definitions for CMU_MFC */ @@ -4120,6 +4136,10 @@ static const unsigned long mfc_clk_regs[] __initconst = { ENABLE_IP_MFC_SECURE_SMMU_MFC, }; +static const struct samsung_clk_reg_dump mfc_suspend_regs[] = { + { MUX_SEL_MFC, 0 }, +}; + PNAME(mout_aclk_mfc_400_user_p) = { "oscclk", "aclk_mfc_400", }; static const struct samsung_mux_clock mfc_mux_clks[] __initconst = { @@ -4190,15 +4210,11 @@ static const struct samsung_cmu_info mfc_cmu_info __initconst = { .nr_clk_ids = MFC_NR_CLK, .clk_regs = mfc_clk_regs, .nr_clk_regs = ARRAY_SIZE(mfc_clk_regs), + .suspend_regs = mfc_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(mfc_suspend_regs), + .clk_name = "aclk_mfc_400", }; -static void __init exynos5433_cmu_mfc_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &mfc_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc", - exynos5433_cmu_mfc_init); - /* * Register offset definitions for CMU_HEVC */ @@ -4228,6 +4244,10 @@ static const unsigned long hevc_clk_regs[] __initconst = { ENABLE_IP_HEVC_SECURE_SMMU_HEVC, }; +static const struct samsung_clk_reg_dump hevc_suspend_regs[] = { + { MUX_SEL_HEVC, 0 }, +}; + PNAME(mout_aclk_hevc_400_user_p) = { "oscclk", "aclk_hevc_400", }; static const struct samsung_mux_clock hevc_mux_clks[] __initconst = { @@ -4300,15 +4320,11 @@ static const struct samsung_cmu_info hevc_cmu_info __initconst = { .nr_clk_ids = HEVC_NR_CLK, .clk_regs = hevc_clk_regs, .nr_clk_regs = ARRAY_SIZE(hevc_clk_regs), + .suspend_regs = hevc_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(hevc_suspend_regs), + .clk_name = "aclk_hevc_400", }; -static void __init exynos5433_cmu_hevc_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &hevc_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc", - exynos5433_cmu_hevc_init); - /* * Register offset definitions for CMU_ISP */ @@ -4342,6 +4358,10 @@ static const unsigned long isp_clk_regs[] __initconst = { ENABLE_IP_ISP3, }; +static const struct samsung_clk_reg_dump isp_suspend_regs[] = { + { MUX_SEL_ISP, 0 }, +}; + PNAME(mout_aclk_isp_dis_400_user_p) = { "oscclk", "aclk_isp_dis_400", }; PNAME(mout_aclk_isp_400_user_p) = { "oscclk", "aclk_isp_400", }; @@ -4553,15 +4573,11 @@ static const struct samsung_cmu_info isp_cmu_info __initconst = { .nr_clk_ids = ISP_NR_CLK, .clk_regs = isp_clk_regs, .nr_clk_regs = ARRAY_SIZE(isp_clk_regs), + .suspend_regs = isp_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(isp_suspend_regs), + .clk_name = "aclk_isp_400", }; -static void __init exynos5433_cmu_isp_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &isp_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp", - exynos5433_cmu_isp_init); - /* * Register offset definitions for CMU_CAM0 */ @@ -4625,6 +4641,15 @@ static const unsigned long cam0_clk_regs[] __initconst = { ENABLE_IP_CAM02, ENABLE_IP_CAM03, }; + +static const struct samsung_clk_reg_dump cam0_suspend_regs[] = { + { MUX_SEL_CAM00, 0 }, + { MUX_SEL_CAM01, 0 }, + { MUX_SEL_CAM02, 0 }, + { MUX_SEL_CAM03, 0 }, + { MUX_SEL_CAM04, 0 }, +}; + PNAME(mout_aclk_cam0_333_user_p) = { "oscclk", "aclk_cam0_333", }; PNAME(mout_aclk_cam0_400_user_p) = { "oscclk", "aclk_cam0_400", }; PNAME(mout_aclk_cam0_552_user_p) = { "oscclk", "aclk_cam0_552", }; @@ -5030,15 +5055,11 @@ static const struct samsung_cmu_info cam0_cmu_info __initconst = { .nr_clk_ids = CAM0_NR_CLK, .clk_regs = cam0_clk_regs, .nr_clk_regs = ARRAY_SIZE(cam0_clk_regs), + .suspend_regs = cam0_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(cam0_suspend_regs), + .clk_name = "aclk_cam0_400", }; -static void __init exynos5433_cmu_cam0_init(struct device_node *np) -{ - samsung_cmu_register_one(np, &cam0_cmu_info); -} -CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0", - exynos5433_cmu_cam0_init); - /* * Register offset definitions for CMU_CAM1 */ @@ -5085,6 +5106,12 @@ static const unsigned long cam1_clk_regs[] __initconst = { ENABLE_IP_CAM12, }; +static const struct samsung_clk_reg_dump cam1_suspend_regs[] = { + { MUX_SEL_CAM10, 0 }, + { MUX_SEL_CAM11, 0 }, + { MUX_SEL_CAM12, 0 }, +}; + PNAME(mout_sclk_isp_uart_user_p) = { "oscclk", "sclk_isp_uart_cam1", }; PNAME(mout_sclk_isp_spi1_user_p) = { "oscclk", "sclk_isp_spi1_cam1", }; PNAME(mout_sclk_isp_spi0_user_p) = { "oscclk", "sclk_isp_spi0_cam1", }; @@ -5403,11 +5430,223 @@ static const struct samsung_cmu_info cam1_cmu_info __initconst = { .nr_clk_ids = CAM1_NR_CLK, .clk_regs = cam1_clk_regs, .nr_clk_regs = ARRAY_SIZE(cam1_clk_regs), + .suspend_regs = cam1_suspend_regs, + .nr_suspend_regs = ARRAY_SIZE(cam1_suspend_regs), + .clk_name = "aclk_cam1_400", +}; + + +struct exynos5433_cmu_data { + struct samsung_clk_reg_dump *clk_save; + unsigned int nr_clk_save; + const struct samsung_clk_reg_dump *clk_suspend; + unsigned int nr_clk_suspend; + + struct clk *clk; + struct clk **pclks; + int nr_pclks; + + /* must be the last entry */ + struct samsung_clk_provider ctx; +}; + +static int exynos5433_cmu_suspend(struct device *dev) +{ + struct exynos5433_cmu_data *data = dev_get_drvdata(dev); + int i; + + samsung_clk_save(data->ctx.reg_base, data->clk_save, + data->nr_clk_save); + + for (i = 0; i < data->nr_pclks; i++) + clk_prepare_enable(data->pclks[i]); + + /* for suspend some registers have to be set to certain values */ + samsung_clk_restore(data->ctx.reg_base, data->clk_suspend, + data->nr_clk_suspend); + + for (i = 0; i < data->nr_pclks; i++) + clk_disable_unprepare(data->pclks[i]); + + clk_disable_unprepare(data->clk); + + return 0; +} + +static int exynos5433_cmu_resume(struct device *dev) +{ + struct exynos5433_cmu_data *data = dev_get_drvdata(dev); + int i; + + clk_prepare_enable(data->clk); + + for (i = 0; i < data->nr_pclks; i++) + clk_prepare_enable(data->pclks[i]); + + samsung_clk_restore(data->ctx.reg_base, data->clk_save, + data->nr_clk_save); + + for (i = 0; i < data->nr_pclks; i++) + clk_disable_unprepare(data->pclks[i]); + + return 0; +} + +static int __init exynos5433_cmu_probe(struct platform_device *pdev) +{ + const struct samsung_cmu_info *info; + struct exynos5433_cmu_data *data; + struct samsung_clk_provider *ctx; + struct device *dev = &pdev->dev; + struct resource *res; + void __iomem *reg_base; + int i; + + info = of_device_get_match_data(dev); + + data = devm_kzalloc(dev, sizeof(*data) + + sizeof(*data->ctx.clk_data.hws) * info->nr_clk_ids, + GFP_KERNEL); + if (!data) + return -ENOMEM; + ctx = &data->ctx; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(reg_base)) { + dev_err(dev, "failed to map registers\n"); + return PTR_ERR(reg_base); + } + + for (i = 0; i < info->nr_clk_ids; ++i) + ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); + + ctx->clk_data.num = info->nr_clk_ids; + ctx->reg_base = reg_base; + ctx->dev = dev; + spin_lock_init(&ctx->lock); + + data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs, + info->nr_clk_regs); + data->nr_clk_save = info->nr_clk_regs; + data->clk_suspend = info->suspend_regs; + data->nr_clk_suspend = info->nr_suspend_regs; + data->nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks", + "#clock-cells"); + if (data->nr_pclks > 0) { + data->pclks = devm_kcalloc(dev, sizeof(struct clk *), + data->nr_pclks, GFP_KERNEL); + + for (i = 0; i < data->nr_pclks; i++) { + struct clk *clk = of_clk_get(dev->of_node, i); + + if (IS_ERR(clk)) + return PTR_ERR(clk); + data->pclks[i] = clk; + } + } + + if (info->clk_name) + data->clk = clk_get(dev, info->clk_name); + clk_prepare_enable(data->clk); + + platform_set_drvdata(pdev, data); + + /* + * Enable runtime PM here to allow the clock core using runtime PM + * for the registered clocks. Additionally, we increase the runtime + * PM usage count before registering the clocks, to prevent the + * clock core from runtime suspending the device. + */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + if (info->pll_clks) + samsung_clk_register_pll(ctx, info->pll_clks, info->nr_pll_clks, + reg_base); + if (info->mux_clks) + samsung_clk_register_mux(ctx, info->mux_clks, + info->nr_mux_clks); + if (info->div_clks) + samsung_clk_register_div(ctx, info->div_clks, + info->nr_div_clks); + if (info->gate_clks) + samsung_clk_register_gate(ctx, info->gate_clks, + info->nr_gate_clks); + if (info->fixed_clks) + samsung_clk_register_fixed_rate(ctx, info->fixed_clks, + info->nr_fixed_clks); + if (info->fixed_factor_clks) + samsung_clk_register_fixed_factor(ctx, info->fixed_factor_clks, + info->nr_fixed_factor_clks); + + samsung_clk_of_add_provider(dev->of_node, ctx); + pm_runtime_put_sync(dev); + + return 0; +} + +static const struct of_device_id exynos5433_cmu_of_match[] = { + { + .compatible = "samsung,exynos5433-cmu-aud", + .data = &aud_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-cam0", + .data = &cam0_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-cam1", + .data = &cam1_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-disp", + .data = &disp_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-g2d", + .data = &g2d_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-g3d", + .data = &g3d_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-fsys", + .data = &fsys_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-gscl", + .data = &gscl_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-mfc", + .data = &mfc_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-hevc", + .data = &hevc_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-isp", + .data = &isp_cmu_info, + }, { + .compatible = "samsung,exynos5433-cmu-mscl", + .data = &mscl_cmu_info, + }, { + }, +}; + +static const struct dev_pm_ops exynos5433_cmu_pm_ops = { + SET_RUNTIME_PM_OPS(exynos5433_cmu_suspend, exynos5433_cmu_resume, + NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver exynos5433_cmu_driver __refdata = { + .driver = { + .name = "exynos5433-cmu", + .of_match_table = exynos5433_cmu_of_match, + .suppress_bind_attrs = true, + .pm = &exynos5433_cmu_pm_ops, + }, + .probe = exynos5433_cmu_probe, }; -static void __init exynos5433_cmu_cam1_init(struct device_node *np) +static int __init exynos5433_cmu_init(void) { - samsung_cmu_register_one(np, &cam1_cmu_info); + return platform_driver_register(&exynos5433_cmu_driver); } -CLK_OF_DECLARE(exynos5433_cmu_cam1, "samsung,exynos5433-cmu-cam1", - exynos5433_cmu_cam1_init); +core_initcall(exynos5433_cmu_init); diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index f0acae4f5d1b..d93031e94387 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -353,6 +353,12 @@ struct samsung_cmu_info { /* list and number of clocks registers */ const unsigned long *clk_regs; unsigned int nr_clk_regs; + + /* list and number of clocks registers to set before suspend */ + const struct samsung_clk_reg_dump *suspend_regs; + unsigned int nr_suspend_regs; + /* name of the parent clock needed for CMU register access */ + const char *clk_name; }; extern struct samsung_clk_provider *__init samsung_clk_init( -- GitLab From 232d7e4792f4c3f8ebb5e348a0795b6a71d0e7d8 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:05:02 +0200 Subject: [PATCH 0005/2898] clk: samsung: exynos-audss: Use local variable for controller's device Store pointer to the controller's device in local variable to avoid extracting it from platform device in each call. This will also simplify code in the future, when runtime PM support is added. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-5-git-send-email-m.szyprowski@samsung.com --- drivers/clk/samsung/clk-exynos-audss.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 1fab56f396d4..6be52fb46ff3 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -135,6 +135,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) const struct exynos_audss_clk_drvdata *variant; struct clk_hw **clk_table; struct resource *res; + struct device *dev = &pdev->dev; int i, ret = 0; variant = of_device_get_match_data(&pdev->dev); @@ -142,15 +143,15 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(&pdev->dev, res); + reg_base = devm_ioremap_resource(dev, res); if (IS_ERR(reg_base)) { - dev_err(&pdev->dev, "failed to map audss registers\n"); + dev_err(dev, "failed to map audss registers\n"); return PTR_ERR(reg_base); } epll = ERR_PTR(-ENODEV); - clk_data = devm_kzalloc(&pdev->dev, + clk_data = devm_kzalloc(dev, sizeof(*clk_data) + sizeof(*clk_data->hws) * EXYNOS_AUDSS_MAX_CLKS, GFP_KERNEL); @@ -160,8 +161,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) clk_data->num = variant->num_clks; clk_table = clk_data->hws; - pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); - pll_in = devm_clk_get(&pdev->dev, "pll_in"); + pll_ref = devm_clk_get(dev, "pll_ref"); + pll_in = devm_clk_get(dev, "pll_in"); if (!IS_ERR(pll_ref)) mout_audss_p[0] = __clk_get_name(pll_ref); if (!IS_ERR(pll_in)) { @@ -172,7 +173,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) ret = clk_prepare_enable(epll); if (ret) { - dev_err(&pdev->dev, + dev_err(dev, "failed to prepare the epll clock\n"); return ret; } @@ -183,8 +184,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); - cdclk = devm_clk_get(&pdev->dev, "cdclk"); - sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio"); + cdclk = devm_clk_get(dev, "cdclk"); + sclk_audio = devm_clk_get(dev, "sclk_audio"); if (!IS_ERR(cdclk)) mout_i2s_p[1] = __clk_get_name(cdclk); if (!IS_ERR(sclk_audio)) @@ -222,7 +223,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) "sclk_pcm", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 4, 0, &lock); - sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in"); + sclk_pcm_in = devm_clk_get(dev, "sclk_pcm_in"); if (!IS_ERR(sclk_pcm_in)) sclk_pcm_p = __clk_get_name(sclk_pcm_in); clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(NULL, "sclk_pcm", @@ -237,16 +238,16 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) for (i = 0; i < clk_data->num; i++) { if (IS_ERR(clk_table[i])) { - dev_err(&pdev->dev, "failed to register clock %d\n", i); + dev_err(dev, "failed to register clock %d\n", i); ret = PTR_ERR(clk_table[i]); goto unregister; } } - ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get, + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, clk_data); if (ret) { - dev_err(&pdev->dev, "failed to add clock provider\n"); + dev_err(dev, "failed to add clock provider\n"); goto unregister; } -- GitLab From ae432a9b314e07d486acfadc4df2f922721e6757 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 21 Aug 2017 10:05:03 +0200 Subject: [PATCH 0006/2898] clk: samsung: exynos-audss: Add support for runtime PM This patch adds support for runtime PM to Exynos Audio SubSystem driver to enable full support for audio power domain on Exynos5 SoCs. The main change is moving register saving and restoring code from system sleep PM ops to runtime PM ops and implementing system sleep PM ops with generic pm_runtime_force_suspend/resume helpers. Runtime PM of the Exynos AudSS device is managed from clock core depending on the preparation status of the provided clocks. Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson Reviewed-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1503302703-13801-6-git-send-email-m.szyprowski@samsung.com --- .../bindings/clock/clk-exynos-audss.txt | 6 +++ drivers/clk/samsung/clk-exynos-audss.c | 51 ++++++++++++------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt index 0c3d6015868d..f3635d5aeba4 100644 --- a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt +++ b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt @@ -33,6 +33,12 @@ Required Properties: - clock-names: Aliases for the above clocks. They should be "pll_ref", "pll_in", "cdclk", "sclk_audio", and "sclk_pcm_in" respectively. +Optional Properties: + + - power-domains: a phandle to respective power domain node as described by + generic PM domain bindings (see power/power_domain.txt for more + information). + The following is the list of clocks generated by the controller. Each clock is assigned an identifier and client nodes use this identifier to specify the clock which they consume. Some of the clocks are available only on a particular diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 6be52fb46ff3..ab494c104ce6 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -36,14 +37,13 @@ static struct clk *epll; #define ASS_CLK_DIV 0x4 #define ASS_CLK_GATE 0x8 -#ifdef CONFIG_PM_SLEEP static unsigned long reg_save[][2] = { { ASS_CLK_SRC, 0 }, { ASS_CLK_DIV, 0 }, { ASS_CLK_GATE, 0 }, }; -static int exynos_audss_clk_suspend(struct device *dev) +static int __maybe_unused exynos_audss_clk_suspend(struct device *dev) { int i; @@ -53,7 +53,7 @@ static int exynos_audss_clk_suspend(struct device *dev) return 0; } -static int exynos_audss_clk_resume(struct device *dev) +static int __maybe_unused exynos_audss_clk_resume(struct device *dev) { int i; @@ -62,7 +62,6 @@ static int exynos_audss_clk_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ struct exynos_audss_clk_drvdata { unsigned int has_adma_clk:1; @@ -179,7 +178,18 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) } } } - clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss", + + /* + * Enable runtime PM here to allow the clock core using runtime PM + * for the registered clocks. Additionally, we increase the runtime + * PM usage count before registering the clocks, to prevent the + * clock core from runtime suspending the device. + */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(dev, "mout_audss", mout_audss_p, ARRAY_SIZE(mout_audss_p), CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); @@ -190,48 +200,48 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) mout_i2s_p[1] = __clk_get_name(cdclk); if (!IS_ERR(sclk_audio)) mout_i2s_p[2] = __clk_get_name(sclk_audio); - clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(NULL, "mout_i2s", + clk_table[EXYNOS_MOUT_I2S] = clk_hw_register_mux(dev, "mout_i2s", mout_i2s_p, ARRAY_SIZE(mout_i2s_p), CLK_SET_RATE_NO_REPARENT, reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); - clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp", + clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(dev, "dout_srp", "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4, 0, &lock); - clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL, + clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(dev, "dout_aud_bus", "dout_srp", 0, reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); - clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s", + clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(dev, "dout_i2s", "mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0, &lock); - clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(NULL, "srp_clk", + clk_table[EXYNOS_SRP_CLK] = clk_hw_register_gate(dev, "srp_clk", "dout_srp", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 0, 0, &lock); - clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(NULL, "i2s_bus", + clk_table[EXYNOS_I2S_BUS] = clk_hw_register_gate(dev, "i2s_bus", "dout_aud_bus", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 2, 0, &lock); - clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(NULL, "sclk_i2s", + clk_table[EXYNOS_SCLK_I2S] = clk_hw_register_gate(dev, "sclk_i2s", "dout_i2s", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 3, 0, &lock); - clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(NULL, "pcm_bus", + clk_table[EXYNOS_PCM_BUS] = clk_hw_register_gate(dev, "pcm_bus", "sclk_pcm", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 4, 0, &lock); sclk_pcm_in = devm_clk_get(dev, "sclk_pcm_in"); if (!IS_ERR(sclk_pcm_in)) sclk_pcm_p = __clk_get_name(sclk_pcm_in); - clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(NULL, "sclk_pcm", + clk_table[EXYNOS_SCLK_PCM] = clk_hw_register_gate(dev, "sclk_pcm", sclk_pcm_p, CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 5, 0, &lock); if (variant->has_adma_clk) { - clk_table[EXYNOS_ADMA] = clk_hw_register_gate(NULL, "adma", + clk_table[EXYNOS_ADMA] = clk_hw_register_gate(dev, "adma", "dout_srp", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 9, 0, &lock); } @@ -251,10 +261,14 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) goto unregister; } + pm_runtime_put_sync(dev); + return 0; unregister: exynos_audss_clk_teardown(); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); if (!IS_ERR(epll)) clk_disable_unprepare(epll); @@ -267,6 +281,7 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) of_clk_del_provider(pdev->dev.of_node); exynos_audss_clk_teardown(); + pm_runtime_disable(&pdev->dev); if (!IS_ERR(epll)) clk_disable_unprepare(epll); @@ -275,8 +290,10 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) } static const struct dev_pm_ops exynos_audss_clk_pm_ops = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(exynos_audss_clk_suspend, - exynos_audss_clk_resume) + SET_RUNTIME_PM_OPS(exynos_audss_clk_suspend, exynos_audss_clk_resume, + NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static struct platform_driver exynos_audss_clk_driver = { -- GitLab From 62d212bdb022deeb875f92f6e376c799e3f35eca Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Sun, 10 Sep 2017 20:40:05 +0800 Subject: [PATCH 0007/2898] clk: sunxi-ng: add CLK_SET_RATE_UNGATE to all H3 PLLs The PLLs on H3 have a lock bit, which will only be set to 1 when the PLL is really working. Add CLK_SET_RATE_UNGATE to the PLLs, otherwise it will timeout when trying to set PLL clock frequency without enabling it. Fixes: 0577e4853bfb ("clk: sunxi-ng: Add H3 clocks") Signed-off-by: Icenowy Zheng Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 1729ff6a5aae..7a81c4885836 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -37,7 +37,7 @@ static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux", 16, 2, /* P */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); /* * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from @@ -55,7 +55,7 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", 0, 5, /* M */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", "osc24M", 0x0010, @@ -67,7 +67,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", "osc24M", 0x0018, @@ -79,7 +79,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr", "osc24M", 0x020, @@ -88,7 +88,7 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr", 0, 2, /* M */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0", "osc24M", 0x028, @@ -97,7 +97,7 @@ static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0", BIT(31), /* gate */ BIT(28), /* lock */ 2, /* post-div */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", "osc24M", 0x0038, @@ -109,7 +109,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1", "osc24M", 0x044, @@ -118,7 +118,7 @@ static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1", BIT(31), /* gate */ BIT(28), /* lock */ 2, /* post-div */ - 0); + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", "osc24M", 0x0048, @@ -130,7 +130,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", 297000000, /* frac rate 1 */ BIT(31), /* gate */ BIT(28), /* lock */ - 0); + CLK_SET_RATE_UNGATE); static const char * const cpux_parents[] = { "osc32k", "osc24M", "pll-cpux" , "pll-cpux" }; -- GitLab From 70641ccad7d19b8229bf1cac33f5b8e03fdc7c5a Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Sun, 10 Sep 2017 20:40:06 +0800 Subject: [PATCH 0008/2898] clk: sunxi-ng: add CLK_SET_RATE_PARENT flag to H3 GPU clock The GPU clock on H3 has only one parent, PLL-GPU, and the PLL is only the parent of the GPU clock. The GPU clock can be tweaked by tweaking the PLL-GPU clock. Add CLK_SET_RATE_PARENT flag to allow tweaking the GPU clock via tweaking PLL-CPU. Fixes: 0577e4853bfb ("clk: sunxi-ng: Add H3 clocks") Signed-off-by: Icenowy Zheng Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 7a81c4885836..543c46d0e045 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -484,7 +484,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL); static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", - 0x1a0, 0, 3, BIT(31), 0); + 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); static struct ccu_common *sun8i_h3_ccu_clks[] = { &pll_cpux_clk.common, -- GitLab From a894990ac994a53bc5a0cc694eb12f3c064c18c5 Mon Sep 17 00:00:00 2001 From: Alexander Syring Date: Thu, 14 Sep 2017 14:05:19 +0200 Subject: [PATCH 0009/2898] clk: sunxi-ng: Fix missing CLK_SET_RATE_PARENT in ccu-sun4i-a10.c When using cpufreq-dt with default govenor other than "performance" system freezes while booting. Adding CLK_SET_RATE_PARENT | CLK_IS_CRITICAL to clk_cpu fixes the problem. Tested on Cubietruck (A20). Fixes: c84f5683f6E ("clk: sunxi-ng: Add sun4i/sun7i CCU driver") Acked-by: Chen-Yu Tsai Signed-off-by: Alexander Syring Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun4i-a10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c index 286b0049b7b6..a48fde191c0a 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c @@ -223,7 +223,7 @@ static struct ccu_mux cpu_clk = { .hw.init = CLK_HW_INIT_PARENTS("cpu", cpu_parents, &ccu_mux_ops, - CLK_IS_CRITICAL), + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), } }; -- GitLab From 882fd1577cbe7812ae3a48988180c5f0fda475ca Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Sat, 26 Aug 2017 17:19:15 +0200 Subject: [PATCH 0010/2898] mtd: nand: Use standard large page OOB layout when using NAND_ECC_NONE Use the core's large page OOB layout functions when not reserving any space for ECC bytes in the OOB layout. Fix ->nand_ooblayout_ecc_lp() to return -ERANGE instead of a zero length in this case. Signed-off-by: Miquel Raynal Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index bcc8cef1c615..fae28ec56277 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -115,7 +115,7 @@ static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section, struct nand_chip *chip = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &chip->ecc; - if (section) + if (section || !ecc->total) return -ERANGE; oobregion->length = ecc->total; @@ -4701,6 +4701,19 @@ int nand_scan_tail(struct mtd_info *mtd) mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops); break; default: + /* + * Expose the whole OOB area to users if ECC_NONE + * is passed. We could do that for all kind of + * ->oobsize, but we must keep the old large/small + * page with ECC layout when ->oobsize <= 128 for + * compatibility reasons. + */ + if (ecc->mode == NAND_ECC_NONE) { + mtd_set_ooblayout(mtd, + &nand_ooblayout_lp_ops); + break; + } + WARN(1, "No oob scheme defined for oobsize %d\n", mtd->oobsize); ret = -EINVAL; -- GitLab From 14157f861437ebe2d624b0a845b91bbdf8ca9a2d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 13 Sep 2017 11:05:50 +0900 Subject: [PATCH 0011/2898] mtd: nand: introduce NAND_ROW_ADDR_3 flag Several drivers check ->chipsize to see if the third row address cycle is needed. Instead of embedding magic sizes such as 32MB, 128MB in drivers, introduce a new flag NAND_ROW_ADDR_3 for clean-up. Since nand_scan_ident() knows well about the device, it can handle this properly. The flag is set if the row address bit width is greater than 16. Delete comments such as "One more address cycle for ..." because intention is now clear enough from the code. Signed-off-by: Masahiro Yamada Acked-by: Wenyou Yang Signed-off-by: Boris Brezillon --- drivers/mtd/nand/atmel/nand-controller.c | 3 +-- drivers/mtd/nand/au1550nd.c | 3 +-- drivers/mtd/nand/diskonchip.c | 3 +-- drivers/mtd/nand/hisi504_nand.c | 3 +-- drivers/mtd/nand/mxc_nand.c | 3 +-- drivers/mtd/nand/nand_base.c | 9 +++++---- drivers/mtd/nand/nuc900_nand.c | 2 +- include/linux/mtd/rawnand.h | 3 +++ 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c index f25eca79f4e5..7bc8d20ed885 100644 --- a/drivers/mtd/nand/atmel/nand-controller.c +++ b/drivers/mtd/nand/atmel/nand-controller.c @@ -718,8 +718,7 @@ static void atmel_nfc_set_op_addr(struct nand_chip *chip, int page, int column) nc->op.addrs[nc->op.naddrs++] = page; nc->op.addrs[nc->op.naddrs++] = page >> 8; - if ((mtd->writesize > 512 && chip->chipsize > SZ_128M) || - (mtd->writesize <= 512 && chip->chipsize > SZ_32M)) + if (chip->options & NAND_ROW_ADDR_3) nc->op.addrs[nc->op.naddrs++] = page >> 16; } } diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 9d4a28fa6b73..8ab827edf94e 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -331,8 +331,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i ctx->write_byte(mtd, (u8)(page_addr >> 8)); - /* One more address cycle for devices > 32MiB */ - if (this->chipsize > (32 << 20)) + if (this->options & NAND_ROW_ADDR_3) ctx->write_byte(mtd, ((page_addr >> 16) & 0x0f)); } diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index c3aa53caab5c..72671dc52e2e 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -705,8 +705,7 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu if (page_addr != -1) { WriteDOC((unsigned char)(page_addr & 0xff), docptr, Mplus_FlashAddress); WriteDOC((unsigned char)((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); - /* One more address cycle for higher density devices */ - if (this->chipsize & 0x0c000000) { + if (this->options & NAND_ROW_ADDR_3) { WriteDOC((unsigned char)((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); printk("high density\n"); } diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c index d9ee1a7e6956..0897261c3e17 100644 --- a/drivers/mtd/nand/hisi504_nand.c +++ b/drivers/mtd/nand/hisi504_nand.c @@ -432,8 +432,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr) host->addr_value[0] |= (page_addr & 0xffff) << (host->addr_cycle * 8); host->addr_cycle += 2; - /* One more address cycle for devices > 128MiB */ - if (chip->chipsize > (128 << 20)) { + if (chip->options & NAND_ROW_ADDR_3) { host->addr_cycle += 1; if (host->command == NAND_CMD_ERASE1) host->addr_value[0] |= ((page_addr >> 16) & 0xff) << 16; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 53e5e0337c3e..bacdd04e765b 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -859,8 +859,7 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) host->devtype_data->send_addr(host, (page_addr >> 8) & 0xff, true); } else { - /* One more address cycle for higher density devices */ - if (mtd->size >= 0x4000000) { + if (nand_chip->options & NAND_ROW_ADDR_3) { /* paddr_8 - paddr_15 */ host->devtype_data->send_addr(host, (page_addr >> 8) & 0xff, diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index fae28ec56277..c63e4a88a653 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -727,8 +727,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, chip->cmd_ctrl(mtd, page_addr, ctrl); ctrl &= ~NAND_CTRL_CHANGE; chip->cmd_ctrl(mtd, page_addr >> 8, ctrl); - /* One more address cycle for devices > 32MiB */ - if (chip->chipsize > (32 << 20)) + if (chip->options & NAND_ROW_ADDR_3) chip->cmd_ctrl(mtd, page_addr >> 16, ctrl); } chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); @@ -854,8 +853,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, chip->cmd_ctrl(mtd, page_addr, ctrl); chip->cmd_ctrl(mtd, page_addr >> 8, NAND_NCE | NAND_ALE); - /* One more address cycle for devices > 128MiB */ - if (chip->chipsize > (128 << 20)) + if (chip->options & NAND_ROW_ADDR_3) chip->cmd_ctrl(mtd, page_addr >> 16, NAND_NCE | NAND_ALE); } @@ -4000,6 +3998,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->chip_shift += 32 - 1; } + if (chip->chip_shift - chip->page_shift > 16) + chip->options |= NAND_ROW_ADDR_3; + chip->badblockbits = 8; chip->erase = single_erase; diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 7bb4d2ea9342..af5b32c9a791 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -154,7 +154,7 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command, if (page_addr != -1) { write_addr_reg(nand, page_addr); - if (chip->chipsize > (128 << 20)) { + if (chip->options & NAND_ROW_ADDR_3) { write_addr_reg(nand, page_addr >> 8); write_addr_reg(nand, page_addr >> 16 | ENDADDR); } else { diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 2b05f4273bab..749bb08c4772 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -177,6 +177,9 @@ enum nand_ecc_algo { */ #define NAND_NEED_SCRAMBLING 0x00002000 +/* Device needs 3rd row address cycle */ +#define NAND_ROW_ADDR_3 0x00004000 + /* Options valid for Samsung large page devices */ #define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG -- GitLab From a3750a6422a7112740fe69a596bcd5eb62577aed Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 13 Sep 2017 11:05:51 +0900 Subject: [PATCH 0012/2898] mtd: nand: denali: support two row address cycle devices The register TWO_ROW_ADDR_CYCLES specifies the number of row address cycles of the device, but it is fixed to 0 in the driver init code (i.e. always 3 row address cycles). Reflect the result of nand_scan_ident() to the register setting in order to support 2 row address cycle devices. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 3087b0ba7b7f..aefdc83bdab0 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1137,8 +1137,6 @@ static void denali_hw_init(struct denali_nand_info *denali) iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); - /* Should set value for these registers when init */ - iowrite32(0, denali->reg + TWO_ROW_ADDR_CYCLES); iowrite32(1, denali->reg + ECC_ENABLE); } @@ -1379,6 +1377,8 @@ int denali_init(struct denali_nand_info *denali) denali->reg + PAGES_PER_BLOCK); iowrite32(chip->options & NAND_BUSWIDTH_16 ? 1 : 0, denali->reg + DEVICE_WIDTH); + iowrite32(chip->options & NAND_ROW_ADDR_3 ? 0 : TWO_ROW_ADDR_CYCLES__FLAG, + denali->reg + TWO_ROW_ADDR_CYCLES); iowrite32(mtd->writesize, denali->reg + DEVICE_MAIN_AREA_SIZE); iowrite32(mtd->oobsize, denali->reg + DEVICE_SPARE_AREA_SIZE); -- GitLab From ecadea00f588d7047572a878072c766c75725d1f Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 9 Sep 2017 00:34:19 +0300 Subject: [PATCH 0013/2898] dt-bindings: clock: Add R8A77970 CPG core clock definitions Add macros usable by the device tree sources to reference the R8A77970 CPG core clocks by index. The data come from the table 8.2c of R-Car Series, 3rd Generation User's Manual: Hardware (Rev. 0.55, Jun. 30, 2017). Based on the original (and large) patch by Daisuke Matsushita . Signed-off-by: Vladimir Barinov Signed-off-by: Sergei Shtylyov Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/r8a77970-cpg-mssr.h | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 include/dt-bindings/clock/r8a77970-cpg-mssr.h diff --git a/include/dt-bindings/clock/r8a77970-cpg-mssr.h b/include/dt-bindings/clock/r8a77970-cpg-mssr.h new file mode 100644 index 000000000000..4146395595b1 --- /dev/null +++ b/include/dt-bindings/clock/r8a77970-cpg-mssr.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016 Renesas Electronics Corp. + * Copyright (C) 2017 Cogent Embedded, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __DT_BINDINGS_CLOCK_R8A77970_CPG_MSSR_H__ +#define __DT_BINDINGS_CLOCK_R8A77970_CPG_MSSR_H__ + +#include + +/* r8a77970 CPG Core Clocks */ +#define R8A77970_CLK_Z2 0 +#define R8A77970_CLK_ZR 1 +#define R8A77970_CLK_ZTR 2 +#define R8A77970_CLK_ZTRD2 3 +#define R8A77970_CLK_ZT 4 +#define R8A77970_CLK_ZX 5 +#define R8A77970_CLK_S1D1 6 +#define R8A77970_CLK_S1D2 7 +#define R8A77970_CLK_S1D4 8 +#define R8A77970_CLK_S2D1 9 +#define R8A77970_CLK_S2D2 10 +#define R8A77970_CLK_S2D4 11 +#define R8A77970_CLK_LB 12 +#define R8A77970_CLK_CL 13 +#define R8A77970_CLK_ZB3 14 +#define R8A77970_CLK_ZB3D2 15 +#define R8A77970_CLK_DDR 16 +#define R8A77970_CLK_CR 17 +#define R8A77970_CLK_CRD2 18 +#define R8A77970_CLK_SD0H 19 +#define R8A77970_CLK_SD0 20 +#define R8A77970_CLK_RPC 21 +#define R8A77970_CLK_RPCD2 22 +#define R8A77970_CLK_MSO 23 +#define R8A77970_CLK_CANFD 24 +#define R8A77970_CLK_CSI0 25 +#define R8A77970_CLK_FRAY 26 +#define R8A77970_CLK_CP 27 +#define R8A77970_CLK_CPEX 28 +#define R8A77970_CLK_R 29 +#define R8A77970_CLK_OSC 30 + +#endif /* __DT_BINDINGS_CLOCK_R8A77970_CPG_MSSR_H__ */ -- GitLab From 8d46e28fb5081b49c5b24c814ad464fb99359d58 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 9 Sep 2017 00:34:20 +0300 Subject: [PATCH 0014/2898] clk: renesas: cpg-mssr: Add R8A77970 support Add R-Car V3M (R8A77970) Clock Pulse Generator / Module Standby and Software Reset support, using the CPG/MSSR driver core and the common R-Car Gen3 code. Based on the original (and large) patch by Daisuke Matsushita . Signed-off-by: Vladimir Barinov Signed-off-by: Sergei Shtylyov Signed-off-by: Geert Uytterhoeven --- .../bindings/clock/renesas,cpg-mssr.txt | 5 +- drivers/clk/renesas/Kconfig | 5 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a77970-cpg-mssr.c | 199 ++++++++++++++++++ drivers/clk/renesas/renesas-cpg-mssr.c | 6 + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + 6 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 drivers/clk/renesas/r8a77970-cpg-mssr.c diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt index 316e13686568..f1890d0777a6 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt @@ -22,6 +22,7 @@ Required Properties: - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2) - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3) - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W) + - "renesas,r8a77970-cpg-mssr" for the r8a77970 SoC (R-Car V3M) - "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3) - reg: Base address and length of the memory resource used by the CPG/MSSR @@ -31,8 +32,8 @@ Required Properties: clock-names - clock-names: List of external parent clock names. Valid names are: - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794, - r8a7795, r8a7796, r8a77995) - - "extalr" (r8a7795, r8a7796) + r8a7795, r8a7796, r8a77970, r8a77995) + - "extalr" (r8a7795, r8a7796, r8a77970) - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794) - #clock-cells: Must be 2 diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index acbb38151ba1..43b5a89c4b28 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -15,6 +15,7 @@ config CLK_RENESAS select CLK_R8A7794 if ARCH_R8A7794 select CLK_R8A7795 if ARCH_R8A7795 select CLK_R8A7796 if ARCH_R8A7796 + select CLK_R8A77970 if ARCH_R8A77970 select CLK_R8A77995 if ARCH_R8A77995 select CLK_SH73A0 if ARCH_SH73A0 @@ -95,6 +96,10 @@ config CLK_R8A7796 bool "R-Car M3-W clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG +config CLK_R8A77970 + bool "R-Car V3M clock support" if COMPILE_TEST + select CLK_RCAR_GEN3_CPG + config CLK_R8A77995 bool "R-Car D3 clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 9bda3ec5b199..306861c74a87 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o +obj-$(CONFIG_CLK_R8A77970) += r8a77970-cpg-mssr.o obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c new file mode 100644 index 000000000000..72f98527473a --- /dev/null +++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c @@ -0,0 +1,199 @@ +/* + * r8a77970 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2017 Cogent Embedded Inc. + * + * Based on r8a7795-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include +#include +#include + +#include + +#include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A77970_CLK_OSC, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_EXTALR, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL0, + CLK_PLL1, + CLK_PLL3, + CLK_PLL1_DIV2, + CLK_PLL1_DIV4, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), + DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), + + /* Core Clock Outputs */ + DEF_FIXED("ztr", R8A77970_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("ztrd2", R8A77970_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("zt", R8A77970_CLK_ZT, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED("zx", R8A77970_CLK_ZX, CLK_PLL1_DIV2, 3, 1), + DEF_FIXED("s1d1", R8A77970_CLK_S1D1, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED("s1d2", R8A77970_CLK_S1D2, CLK_PLL1_DIV2, 8, 1), + DEF_FIXED("s1d4", R8A77970_CLK_S1D4, CLK_PLL1_DIV2, 16, 1), + DEF_FIXED("s2d1", R8A77970_CLK_S2D1, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("s2d2", R8A77970_CLK_S2D2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("s2d4", R8A77970_CLK_S2D4, CLK_PLL1_DIV2, 24, 1), + + DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1), + + DEF_DIV6P1("canfd", R8A77970_CLK_CANFD, CLK_PLL1_DIV4, 0x244), + DEF_DIV6P1("mso", R8A77970_CLK_MSO, CLK_PLL1_DIV4, 0x014), + DEF_DIV6P1("csi0", R8A77970_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), + + DEF_FIXED("osc", R8A77970_CLK_OSC, CLK_PLL1_DIV2, 12*1024, 1), + DEF_FIXED("r", R8A77970_CLK_R, CLK_EXTALR, 1, 1), +}; + +static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("ivcp1e", 127, R8A77970_CLK_S2D1), + DEF_MOD("scif4", 203, R8A77970_CLK_S2D4), + DEF_MOD("scif3", 204, R8A77970_CLK_S2D4), + DEF_MOD("scif1", 206, R8A77970_CLK_S2D4), + DEF_MOD("scif0", 207, R8A77970_CLK_S2D4), + DEF_MOD("msiof3", 208, R8A77970_CLK_MSO), + DEF_MOD("msiof2", 209, R8A77970_CLK_MSO), + DEF_MOD("msiof1", 210, R8A77970_CLK_MSO), + DEF_MOD("msiof0", 211, R8A77970_CLK_MSO), + DEF_MOD("mfis", 213, R8A77970_CLK_S2D2), + DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1), + DEF_MOD("sys-dmac1", 218, R8A77970_CLK_S2D1), + DEF_MOD("rwdt", 402, R8A77970_CLK_R), + DEF_MOD("intc-ex", 407, R8A77970_CLK_CP), + DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1), + DEF_MOD("hscif3", 517, R8A77970_CLK_S2D1), + DEF_MOD("hscif2", 518, R8A77970_CLK_S2D1), + DEF_MOD("hscif1", 519, R8A77970_CLK_S2D1), + DEF_MOD("hscif0", 520, R8A77970_CLK_S2D1), + DEF_MOD("thermal", 522, R8A77970_CLK_CP), + DEF_MOD("pwm", 523, R8A77970_CLK_S2D4), + DEF_MOD("fcpvd0", 603, R8A77970_CLK_S2D1), + DEF_MOD("vspd0", 623, R8A77970_CLK_S2D1), + DEF_MOD("csi40", 716, R8A77970_CLK_CSI0), + DEF_MOD("du0", 724, R8A77970_CLK_S2D1), + DEF_MOD("vin3", 808, R8A77970_CLK_S2D1), + DEF_MOD("vin2", 809, R8A77970_CLK_S2D1), + DEF_MOD("vin1", 810, R8A77970_CLK_S2D1), + DEF_MOD("vin0", 811, R8A77970_CLK_S2D1), + DEF_MOD("etheravb", 812, R8A77970_CLK_S2D2), + DEF_MOD("gpio5", 907, R8A77970_CLK_CP), + DEF_MOD("gpio4", 908, R8A77970_CLK_CP), + DEF_MOD("gpio3", 909, R8A77970_CLK_CP), + DEF_MOD("gpio2", 910, R8A77970_CLK_CP), + DEF_MOD("gpio1", 911, R8A77970_CLK_CP), + DEF_MOD("gpio0", 912, R8A77970_CLK_CP), + DEF_MOD("can-fd", 914, R8A77970_CLK_S2D2), + DEF_MOD("i2c4", 927, R8A77970_CLK_S2D2), + DEF_MOD("i2c3", 928, R8A77970_CLK_S2D2), + DEF_MOD("i2c2", 929, R8A77970_CLK_S2D2), + DEF_MOD("i2c1", 930, R8A77970_CLK_S2D2), + DEF_MOD("i2c0", 931, R8A77970_CLK_S2D2), +}; + +static const unsigned int r8a77970_crit_mod_clks[] __initconst = { + MOD_CLK_ID(408), /* INTC-AP (GIC) */ +}; + + +/* + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL3 + * 14 13 19 (MHz) + *------------------------------------------------- + * 0 0 0 16.66 x 1 x192 x192 x96 + * 0 0 1 16.66 x 1 x192 x192 x80 + * 0 1 0 20 x 1 x160 x160 x80 + * 0 1 1 20 x 1 x160 x160 x66 + * 1 0 0 27 / 2 x236 x236 x118 + * 1 0 1 27 / 2 x236 x236 x98 + * 1 1 0 33.33 / 2 x192 x192 x96 + * 1 1 1 33.33 / 2 x192 x192 x80 + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ + (((md) & BIT(13)) >> 12) | \ + (((md) & BIT(19)) >> 19)) + +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = { + /* EXTAL div PLL1 mult/div PLL3 mult/div */ + { 1, 192, 1, 96, 1, }, + { 1, 192, 1, 80, 1, }, + { 1, 160, 1, 80, 1, }, + { 1, 160, 1, 66, 1, }, + { 2, 236, 1, 118, 1, }, + { 2, 236, 1, 98, 1, }, + { 2, 192, 1, 96, 1, }, + { 2, 192, 1, 80, 1, }, +}; + +static int __init r8a77970_cpg_mssr_init(struct device *dev) +{ + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; + u32 cpg_mode; + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); +} + +const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a77970_core_clks, + .num_core_clks = ARRAY_SIZE(r8a77970_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a77970_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a77970_mod_clks), + .num_hw_mod_clks = 12 * 32, + + /* Critical Module Clocks */ + .crit_mod_clks = r8a77970_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a77970_crit_mod_clks), + + /* Callbacks */ + .init = r8a77970_cpg_mssr_init, + .cpg_clk_register = rcar_gen3_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index e580a5e6346c..1779b0cc7a2a 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -680,6 +680,12 @@ static const struct of_device_id cpg_mssr_match[] = { .data = &r8a7796_cpg_mssr_info, }, #endif +#ifdef CONFIG_CLK_R8A77970 + { + .compatible = "renesas,r8a77970-cpg-mssr", + .data = &r8a77970_cpg_mssr_info, + }, +#endif #ifdef CONFIG_CLK_R8A77995 { .compatible = "renesas,r8a77995-cpg-mssr", diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 94b9071d1061..66528ce3eb37 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -138,6 +138,7 @@ extern const struct cpg_mssr_info r8a7792_cpg_mssr_info; extern const struct cpg_mssr_info r8a7794_cpg_mssr_info; extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; +extern const struct cpg_mssr_info r8a77970_cpg_mssr_info; extern const struct cpg_mssr_info r8a77995_cpg_mssr_info; -- GitLab From f454322efbf6faee695f517c6b52c4dc03cacd3e Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Tue, 22 Aug 2017 02:16:11 +0300 Subject: [PATCH 0015/2898] signal: replace sigset_to_compat() with put_compat_sigset() There are 4 callers of sigset_to_compat() in the entire kernel. One is in sparc compat rt_sigaction(2), the rest are in kernel/signal.c itself. All are followed by copy_to_user(), and all but the sparc one are under "if it's big-endian..." ifdefs. Let's transform sigset_to_compat() into put_compat_sigset() that also calls copy_to_user(). Suggested-by: Al Viro Signed-off-by: Dmitry V. Levin Signed-off-by: Al Viro --- arch/sparc/kernel/sys_sparc32.c | 6 +++--- include/linux/compat.h | 3 ++- kernel/compat.c | 20 ++++++++++++++------ kernel/signal.c | 27 ++++++--------------------- 4 files changed, 25 insertions(+), 31 deletions(-) diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index bca44f3e6b86..5e2bec9e41b2 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -159,7 +159,6 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig, { struct k_sigaction new_ka, old_ka; int ret; - compat_sigset_t set32; /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(compat_sigset_t)) @@ -167,6 +166,7 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig, if (act) { u32 u_handler, u_restorer; + compat_sigset_t set32; new_ka.ka_restorer = restorer; ret = get_user(u_handler, &act->sa_handler); @@ -183,9 +183,9 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - sigset_to_compat(&set32, &old_ka.sa.sa_mask); ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); - ret |= copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t)); + ret |= put_compat_sigset(&oact->sa_mask, &old_ka.sa.sa_mask, + sizeof(oact->sa_mask)); ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer); if (ret) diff --git a/include/linux/compat.h b/include/linux/compat.h index a5619de3437d..ab1baa79abe8 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -456,7 +456,8 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); extern void sigset_from_compat(sigset_t *set, const compat_sigset_t *compat); -extern void sigset_to_compat(compat_sigset_t *compat, const sigset_t *set); +extern int put_compat_sigset(compat_sigset_t __user *compat, + const sigset_t *set, unsigned int size); asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, diff --git a/kernel/compat.c b/kernel/compat.c index 772e038d04d9..18dd902c9052 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -497,15 +497,23 @@ sigset_from_compat(sigset_t *set, const compat_sigset_t *compat) } EXPORT_SYMBOL_GPL(sigset_from_compat); -void -sigset_to_compat(compat_sigset_t *compat, const sigset_t *set) +int +put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set, + unsigned int size) { + /* size <= sizeof(compat_sigset_t) <= sizeof(sigset_t) */ +#ifdef __BIG_ENDIAN + compat_sigset_t v; switch (_NSIG_WORDS) { - case 4: compat->sig[7] = (set->sig[3] >> 32); compat->sig[6] = set->sig[3]; - case 3: compat->sig[5] = (set->sig[2] >> 32); compat->sig[4] = set->sig[2]; - case 2: compat->sig[3] = (set->sig[1] >> 32); compat->sig[2] = set->sig[1]; - case 1: compat->sig[1] = (set->sig[0] >> 32); compat->sig[0] = set->sig[0]; + case 4: v.sig[7] = (set->sig[3] >> 32); v.sig[6] = set->sig[3]; + case 3: v.sig[5] = (set->sig[2] >> 32); v.sig[4] = set->sig[2]; + case 2: v.sig[3] = (set->sig[1] >> 32); v.sig[2] = set->sig[1]; + case 1: v.sig[1] = (set->sig[0] >> 32); v.sig[0] = set->sig[0]; } + return copy_to_user(compat, &v, size) ? -EFAULT : 0; +#else + return copy_to_user(compat, set, size) ? -EFAULT : 0; +#endif } #ifdef CONFIG_NUMA diff --git a/kernel/signal.c b/kernel/signal.c index 800a18f77732..14ad6bb90dad 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2621,13 +2621,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, if (error) return error; } - if (oset) { - compat_sigset_t old32; - sigset_to_compat(&old32, &old_set); - if (copy_to_user(oset, &old32, sizeof(compat_sigset_t))) - return -EFAULT; - } - return 0; + return oset ? put_compat_sigset(oset, &old_set, sizeof(*oset)) : 0; #else return sys_rt_sigprocmask(how, (sigset_t __user *)nset, (sigset_t __user *)oset, sigsetsize); @@ -2669,20 +2663,11 @@ SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, compat_size_t, sigsetsize) { -#ifdef __BIG_ENDIAN sigset_t set; int err = do_sigpending(&set, sigsetsize); - if (!err) { - compat_sigset_t set32; - sigset_to_compat(&set32, &set); - /* we can get here only if sigsetsize <= sizeof(set) */ - if (copy_to_user(uset, &set32, sigsetsize)) - err = -EFAULT; - } + if (!err) + err = put_compat_sigset(uset, &set, sigsetsize); return err; -#else - return sys_rt_sigpending((sigset_t __user *)uset, sigsetsize); -#endif } #endif @@ -3451,7 +3436,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, compat_size_t, sigsetsize) { struct k_sigaction new_ka, old_ka; - compat_sigset_t mask; #ifdef __ARCH_HAS_SA_RESTORER compat_uptr_t restorer; #endif @@ -3463,6 +3447,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, if (act) { compat_uptr_t handler; + compat_sigset_t mask; ret = get_user(handler, &act->sa_handler); new_ka.sa.sa_handler = compat_ptr(handler); #ifdef __ARCH_HAS_SA_RESTORER @@ -3478,10 +3463,10 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - sigset_to_compat(&mask, &old_ka.sa.sa_mask); ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); - ret |= copy_to_user(&oact->sa_mask, &mask, sizeof(mask)); + ret |= put_compat_sigset(&oact->sa_mask, &old_ka.sa.sa_mask, + sizeof(oact->sa_mask)); ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); #ifdef __ARCH_HAS_SA_RESTORER ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), -- GitLab From 1681634b8c70353d8ca211b9b3443889a16dafeb Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Tue, 22 Aug 2017 02:16:29 +0300 Subject: [PATCH 0016/2898] signal: simplify compat_sigpending() Remove "if it's big-endian..." ifdef in compat_sigpending(), use the endian-agnostic variant. Suggested-by: Al Viro Signed-off-by: Dmitry V. Levin Signed-off-by: Al Viro --- kernel/signal.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c index 14ad6bb90dad..f59c05fc374a 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3330,15 +3330,11 @@ SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set) #ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32) { -#ifdef __BIG_ENDIAN sigset_t set; int err = do_sigpending(&set, sizeof(set.sig[0])); if (!err) err = put_user(set.sig[0], set32); return err; -#else - return sys_rt_sigpending((sigset_t __user *)set32, sizeof(*set32)); -#endif } #endif -- GitLab From 176826af03666758c656dd27f098cc889b71638b Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Tue, 22 Aug 2017 02:16:43 +0300 Subject: [PATCH 0017/2898] signal: lift sigset size check out of do_sigpending() As sigsetsize argument of do_sigpending() is not used anywhere else in that function after the check, remove this argument and move the check out of do_sigpending() into rt_sigpending() and its compat analog. Suggested-by: Al Viro Signed-off-by: Dmitry V. Levin Signed-off-by: Al Viro --- kernel/signal.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c index f59c05fc374a..9fbc574ced10 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2629,11 +2629,8 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, } #endif -static int do_sigpending(void *set, unsigned long sigsetsize) +static int do_sigpending(sigset_t *set) { - if (sigsetsize > sizeof(sigset_t)) - return -EINVAL; - spin_lock_irq(¤t->sighand->siglock); sigorsets(set, ¤t->pending.signal, ¤t->signal->shared_pending.signal); @@ -2653,7 +2650,12 @@ static int do_sigpending(void *set, unsigned long sigsetsize) SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) { sigset_t set; - int err = do_sigpending(&set, sigsetsize); + int err; + + if (sigsetsize > sizeof(*uset)) + return -EINVAL; + + err = do_sigpending(&set); if (!err && copy_to_user(uset, &set, sigsetsize)) err = -EFAULT; return err; @@ -2664,7 +2666,12 @@ COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, compat_size_t, sigsetsize) { sigset_t set; - int err = do_sigpending(&set, sigsetsize); + int err; + + if (sigsetsize > sizeof(*uset)) + return -EINVAL; + + err = do_sigpending(&set); if (!err) err = put_compat_sigset(uset, &set, sigsetsize); return err; @@ -3331,7 +3338,7 @@ SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set) COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32) { sigset_t set; - int err = do_sigpending(&set, sizeof(set.sig[0])); + int err = do_sigpending(&set); if (!err) err = put_user(set.sig[0], set32); return err; -- GitLab From 36819ad093e16a4b06c53f98d4a5afc55530bbcb Mon Sep 17 00:00:00 2001 From: Deepa Dinamani Date: Fri, 4 Aug 2017 21:12:31 -0700 Subject: [PATCH 0018/2898] select: Use get/put_timespec64 Usage of these apis and their compat versions makes the syscalls: select family of syscalls and their compat implementations simpler. This is a preparatory patch to isolate data conversions to struct timespec64 at userspace boundaries. This helps contain the changes needed to transition to new y2038 safe types. Signed-off-by: Deepa Dinamani Signed-off-by: Al Viro --- fs/select.c | 60 +++++++++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/fs/select.c b/fs/select.c index c6362e38ae92..20a7d061904f 100644 --- a/fs/select.c +++ b/fs/select.c @@ -291,8 +291,7 @@ static int poll_select_copy_remaining(struct timespec64 *end_time, void __user *p, int timeval, int ret) { - struct timespec64 rts64; - struct timespec rts; + struct timespec64 rts; struct timeval rtv; if (!p) @@ -305,23 +304,22 @@ static int poll_select_copy_remaining(struct timespec64 *end_time, if (!end_time->tv_sec && !end_time->tv_nsec) return ret; - ktime_get_ts64(&rts64); - rts64 = timespec64_sub(*end_time, rts64); - if (rts64.tv_sec < 0) - rts64.tv_sec = rts64.tv_nsec = 0; + ktime_get_ts64(&rts); + rts = timespec64_sub(*end_time, rts); + if (rts.tv_sec < 0) + rts.tv_sec = rts.tv_nsec = 0; - rts = timespec64_to_timespec(rts64); if (timeval) { if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec)) memset(&rtv, 0, sizeof(rtv)); - rtv.tv_sec = rts64.tv_sec; - rtv.tv_usec = rts64.tv_nsec / NSEC_PER_USEC; + rtv.tv_sec = rts.tv_sec; + rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC; if (!copy_to_user(p, &rtv, sizeof(rtv))) return ret; - } else if (!copy_to_user(p, &rts, sizeof(rts))) + } else if (!put_timespec64(&rts, p)) return ret; /* @@ -704,17 +702,15 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp, const sigset_t __user *sigmask, size_t sigsetsize) { sigset_t ksigmask, sigsaved; - struct timespec ts; - struct timespec64 ts64, end_time, *to = NULL; + struct timespec64 ts, end_time, *to = NULL; int ret; if (tsp) { - if (copy_from_user(&ts, tsp, sizeof(ts))) + if (get_timespec64(&ts, tsp)) return -EFAULT; - ts64 = timespec_to_timespec64(ts); to = &end_time; - if (poll_select_set_timeout(to, ts64.tv_sec, ts64.tv_nsec)) + if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) return -EINVAL; } @@ -1051,12 +1047,11 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, size_t, sigsetsize) { sigset_t ksigmask, sigsaved; - struct timespec ts; - struct timespec64 end_time, *to = NULL; + struct timespec64 ts, end_time, *to = NULL; int ret; if (tsp) { - if (copy_from_user(&ts, tsp, sizeof(ts))) + if (get_timespec64(&ts, tsp)) return -EFAULT; to = &end_time; @@ -1102,10 +1097,10 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) static -int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, +int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user *p, int timeval, int ret) { - struct timespec ts; + struct timespec64 ts; if (!p) return ret; @@ -1117,8 +1112,8 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, if (!end_time->tv_sec && !end_time->tv_nsec) return ret; - ktime_get_ts(&ts); - ts = timespec_sub(*end_time, ts); + ktime_get_ts64(&ts); + ts = timespec64_sub(*end_time, ts); if (ts.tv_sec < 0) ts.tv_sec = ts.tv_nsec = 0; @@ -1131,12 +1126,7 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, if (!copy_to_user(p, &rtv, sizeof(rtv))) return ret; } else { - struct compat_timespec rts; - - rts.tv_sec = ts.tv_sec; - rts.tv_nsec = ts.tv_nsec; - - if (!copy_to_user(p, &rts, sizeof(rts))) + if (!compat_put_timespec64(&ts, p)) return ret; } /* @@ -1194,7 +1184,7 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, */ static int compat_core_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, - struct timespec *end_time) + struct timespec64 *end_time) { fd_set_bits fds; void *bits; @@ -1267,7 +1257,7 @@ COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp, compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, struct compat_timeval __user *, tvp) { - struct timespec end_time, *to = NULL; + struct timespec64 end_time, *to = NULL; struct compat_timeval tv; int ret; @@ -1313,12 +1303,11 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, { compat_sigset_t ss32; sigset_t ksigmask, sigsaved; - struct compat_timespec ts; - struct timespec end_time, *to = NULL; + struct timespec64 ts, end_time, *to = NULL; int ret; if (tsp) { - if (copy_from_user(&ts, tsp, sizeof(ts))) + if (compat_get_timespec64(&ts, tsp)) return -EFAULT; to = &end_time; @@ -1382,12 +1371,11 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, { compat_sigset_t ss32; sigset_t ksigmask, sigsaved; - struct compat_timespec ts; - struct timespec end_time, *to = NULL; + struct timespec64 ts, end_time, *to = NULL; int ret; if (tsp) { - if (copy_from_user(&ts, tsp, sizeof(ts))) + if (compat_get_timespec64(&ts, tsp)) return -EFAULT; to = &end_time; -- GitLab From fa2e62a54003419b06f1de7836dca51b368d0872 Mon Sep 17 00:00:00 2001 From: Deepa Dinamani Date: Fri, 4 Aug 2017 21:12:32 -0700 Subject: [PATCH 0019/2898] io_getevents: Use timespec64 to represent timeouts struct timespec is not y2038 safe. Use y2038 safe struct timespec64 to represent timeouts. The system call interface itself will be changed as part of different series. Timeouts will not really need more than 32 bits. But, replacing these with timespec64 helps verification of a y2038 safe kernel by getting rid of timespec internally. Signed-off-by: Deepa Dinamani Cc: linux-aio@kvack.org Signed-off-by: Al Viro --- fs/aio.c | 55 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 5a2487217072..91624905024f 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1297,20 +1297,10 @@ static bool aio_read_events(struct kioctx *ctx, long min_nr, long nr, static long read_events(struct kioctx *ctx, long min_nr, long nr, struct io_event __user *event, - struct timespec __user *timeout) + ktime_t until) { - ktime_t until = KTIME_MAX; long ret = 0; - if (timeout) { - struct timespec ts; - - if (unlikely(copy_from_user(&ts, timeout, sizeof(ts)))) - return -EFAULT; - - until = timespec_to_ktime(ts); - } - /* * Note that aio_read_events() is being called as the conditional - i.e. * we're calling it after prepare_to_wait() has set task state to @@ -1826,6 +1816,25 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, return ret; } +static long do_io_getevents(aio_context_t ctx_id, + long min_nr, + long nr, + struct io_event __user *events, + struct timespec64 *ts) +{ + ktime_t until = ts ? timespec64_to_ktime(*ts) : KTIME_MAX; + struct kioctx *ioctx = lookup_ioctx(ctx_id); + long ret = -EINVAL; + + if (likely(ioctx)) { + if (likely(min_nr <= nr && min_nr >= 0)) + ret = read_events(ioctx, min_nr, nr, events, until); + percpu_ref_put(&ioctx->users); + } + + return ret; +} + /* io_getevents: * Attempts to read at least min_nr events and up to nr events from * the completion queue for the aio_context specified by ctx_id. If @@ -1844,15 +1853,14 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id, struct io_event __user *, events, struct timespec __user *, timeout) { - struct kioctx *ioctx = lookup_ioctx(ctx_id); - long ret = -EINVAL; + struct timespec64 ts; - if (likely(ioctx)) { - if (likely(min_nr <= nr && min_nr >= 0)) - ret = read_events(ioctx, min_nr, nr, events, timeout); - percpu_ref_put(&ioctx->users); + if (timeout) { + if (unlikely(get_timespec64(&ts, timeout))) + return -EFAULT; } - return ret; + + return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL); } #ifdef CONFIG_COMPAT @@ -1862,17 +1870,14 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id, struct io_event __user *, events, struct compat_timespec __user *, timeout) { - struct timespec t; - struct timespec __user *ut = NULL; + struct timespec64 t; if (timeout) { - if (compat_get_timespec(&t, timeout)) + if (compat_get_timespec64(&t, timeout)) return -EFAULT; - ut = compat_alloc_user_space(sizeof(*ut)); - if (copy_to_user(ut, &t, sizeof(t))) - return -EFAULT; } - return sys_io_getevents(ctx_id, min_nr, nr, events, ut); + + return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL); } #endif -- GitLab From b8e8e1aa9f14110da180569908bbe538c9e9dc63 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 3 Sep 2017 20:42:54 -0400 Subject: [PATCH 0020/2898] get rid of {get,put}_compat_itimerspec() no users left Signed-off-by: Al Viro --- include/linux/compat.h | 5 ----- kernel/compat.c | 18 ------------------ 2 files changed, 23 deletions(-) diff --git a/include/linux/compat.h b/include/linux/compat.h index ab1baa79abe8..21d30be5c0a5 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -443,11 +443,6 @@ static inline int compat_timespec_compare(struct compat_timespec *lhs, return lhs->tv_nsec - rhs->tv_nsec; } -extern int get_compat_itimerspec(struct itimerspec *dst, - const struct compat_itimerspec __user *src); -extern int put_compat_itimerspec(struct compat_itimerspec __user *dst, - const struct itimerspec *src); - asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz); asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, diff --git a/kernel/compat.c b/kernel/compat.c index 18dd902c9052..d43b18031116 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -367,24 +367,6 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t, pid, unsigned int, len, return ret; } -int get_compat_itimerspec(struct itimerspec *dst, - const struct compat_itimerspec __user *src) -{ - if (__compat_get_timespec(&dst->it_interval, &src->it_interval) || - __compat_get_timespec(&dst->it_value, &src->it_value)) - return -EFAULT; - return 0; -} - -int put_compat_itimerspec(struct compat_itimerspec __user *dst, - const struct itimerspec *src) -{ - if (__compat_put_timespec(&src->it_interval, &dst->it_interval) || - __compat_put_timespec(&src->it_value, &dst->it_value)) - return -EFAULT; - return 0; -} - int get_compat_itimerspec64(struct itimerspec64 *its, const struct compat_itimerspec __user *uits) { -- GitLab From 3968cf623892d710e651070243fd16af312a9797 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 3 Sep 2017 21:45:17 -0400 Subject: [PATCH 0021/2898] get_compat_sigset() similar to put_compat_sigset() Signed-off-by: Al Viro --- arch/sparc/kernel/sys_sparc32.c | 4 +--- fs/eventpoll.c | 4 +--- fs/select.c | 8 ++------ fs/signalfd.c | 4 +--- include/linux/compat.h | 2 +- kernel/compat.c | 23 ++++++++++++++++------- kernel/signal.c | 27 ++++----------------------- virt/kvm/kvm_main.c | 7 ++----- 8 files changed, 28 insertions(+), 51 deletions(-) diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index 5e2bec9e41b2..34ece61ee970 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -166,13 +166,11 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig, if (act) { u32 u_handler, u_restorer; - compat_sigset_t set32; new_ka.ka_restorer = restorer; ret = get_user(u_handler, &act->sa_handler); new_ka.sa.sa_handler = compat_ptr(u_handler); - ret |= copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t)); - sigset_from_compat(&new_ka.sa.sa_mask, &set32); + ret |= get_compat_sigset(&new_ka.sa.sa_mask, &act->sa_mask); ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); ret |= get_user(u_restorer, &act->sa_restorer); new_ka.sa.sa_restorer = compat_ptr(u_restorer); diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 2fabd19cdeea..396a3c075fd4 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -2259,7 +2259,6 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd, compat_size_t, sigsetsize) { long err; - compat_sigset_t csigmask; sigset_t ksigmask, sigsaved; /* @@ -2269,9 +2268,8 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd, if (sigmask) { if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; - if (copy_from_user(&csigmask, sigmask, sizeof(csigmask))) + if (get_compat_sigset(&ksigmask, sigmask)) return -EFAULT; - sigset_from_compat(&ksigmask, &csigmask); sigsaved = current->blocked; set_current_blocked(&ksigmask); } diff --git a/fs/select.c b/fs/select.c index 20a7d061904f..9c980162c9fe 100644 --- a/fs/select.c +++ b/fs/select.c @@ -1301,7 +1301,6 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, compat_size_t sigsetsize) { - compat_sigset_t ss32; sigset_t ksigmask, sigsaved; struct timespec64 ts, end_time, *to = NULL; int ret; @@ -1318,9 +1317,8 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, if (sigmask) { if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; - if (copy_from_user(&ss32, sigmask, sizeof(ss32))) + if (get_compat_sigset(&ksigmask, sigmask)) return -EFAULT; - sigset_from_compat(&ksigmask, &ss32); sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); @@ -1369,7 +1367,6 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, struct compat_timespec __user *, tsp, const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize) { - compat_sigset_t ss32; sigset_t ksigmask, sigsaved; struct timespec64 ts, end_time, *to = NULL; int ret; @@ -1386,9 +1383,8 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, if (sigmask) { if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; - if (copy_from_user(&ss32, sigmask, sizeof(ss32))) + if (get_compat_sigset(&ksigmask, sigmask)) return -EFAULT; - sigset_from_compat(&ksigmask, &ss32); sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); diff --git a/fs/signalfd.c b/fs/signalfd.c index d2c434112f42..9de5beeb771d 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -312,15 +312,13 @@ COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd, compat_size_t, sigsetsize, int, flags) { - compat_sigset_t ss32; sigset_t tmp; sigset_t __user *ksigmask; if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; - if (copy_from_user(&ss32, sigmask, sizeof(ss32))) + if (get_compat_sigset(&tmp, sigmask)) return -EFAULT; - sigset_from_compat(&tmp, &ss32); ksigmask = compat_alloc_user_space(sizeof(sigset_t)); if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t))) return -EFAULT; diff --git a/include/linux/compat.h b/include/linux/compat.h index 21d30be5c0a5..57cb6ecafa86 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -450,7 +450,7 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); -extern void sigset_from_compat(sigset_t *set, const compat_sigset_t *compat); +extern int get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat); extern int put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set, unsigned int size); diff --git a/kernel/compat.c b/kernel/compat.c index d43b18031116..a46a4a40bb8b 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -467,17 +467,26 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, return -EFAULT; } -void -sigset_from_compat(sigset_t *set, const compat_sigset_t *compat) +int +get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat) { +#ifdef __BIG_ENDIAN + compat_sigset_t v; + if (copy_from_user(&v, compat, sizeof(compat_sigset_t))) + return -EFAULT; switch (_NSIG_WORDS) { - case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); - case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 ); - case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 ); - case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 ); + case 4: set->sig[3] = v.sig[6] | (((long)v.sig[7]) << 32 ); + case 3: set->sig[2] = v.sig[4] | (((long)v.sig[5]) << 32 ); + case 2: set->sig[1] = v.sig[2] | (((long)v.sig[3]) << 32 ); + case 1: set->sig[0] = v.sig[0] | (((long)v.sig[1]) << 32 ); } +#else + if (copy_from_user(set, compat, sizeof(compat_sigset_t))) + return -EFAULT; +#endif + return 0; } -EXPORT_SYMBOL_GPL(sigset_from_compat); +EXPORT_SYMBOL_GPL(get_compat_sigset); int put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set, diff --git a/kernel/signal.c b/kernel/signal.c index 9fbc574ced10..36a523640894 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2600,7 +2600,6 @@ SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, nset, COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, compat_sigset_t __user *, oset, compat_size_t, sigsetsize) { -#ifdef __BIG_ENDIAN sigset_t old_set = current->blocked; /* XXX: Don't preclude handling different sized sigset_t's. */ @@ -2608,13 +2607,10 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, return -EINVAL; if (nset) { - compat_sigset_t new32; sigset_t new_set; int error; - if (copy_from_user(&new32, nset, sizeof(compat_sigset_t))) + if (get_compat_sigset(&new_set, nset)) return -EFAULT; - - sigset_from_compat(&new_set, &new32); sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); error = sigprocmask(how, &new_set, NULL); @@ -2622,10 +2618,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, return error; } return oset ? put_compat_sigset(oset, &old_set, sizeof(*oset)) : 0; -#else - return sys_rt_sigprocmask(how, (sigset_t __user *)nset, - (sigset_t __user *)oset, sigsetsize); -#endif } #endif @@ -2908,7 +2900,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, struct compat_siginfo __user *, uinfo, struct compat_timespec __user *, uts, compat_size_t, sigsetsize) { - compat_sigset_t s32; sigset_t s; struct timespec t; siginfo_t info; @@ -2917,9 +2908,8 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, if (sigsetsize != sizeof(sigset_t)) return -EINVAL; - if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) + if (get_compat_sigset(&s, uthese)) return -EFAULT; - sigset_from_compat(&s, &s32); if (uts) { if (compat_get_timespec(&t, uts)) @@ -3450,18 +3440,16 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, if (act) { compat_uptr_t handler; - compat_sigset_t mask; ret = get_user(handler, &act->sa_handler); new_ka.sa.sa_handler = compat_ptr(handler); #ifdef __ARCH_HAS_SA_RESTORER ret |= get_user(restorer, &act->sa_restorer); new_ka.sa.sa_restorer = compat_ptr(restorer); #endif - ret |= copy_from_user(&mask, &act->sa_mask, sizeof(mask)); + ret |= get_compat_sigset(&new_ka.sa.sa_mask, &act->sa_mask); ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); if (ret) return -EFAULT; - sigset_from_compat(&new_ka.sa.sa_mask, &mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); @@ -3649,22 +3637,15 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize) #ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE2(rt_sigsuspend, compat_sigset_t __user *, unewset, compat_size_t, sigsetsize) { -#ifdef __BIG_ENDIAN sigset_t newset; - compat_sigset_t newset32; /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(sigset_t)) return -EINVAL; - if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) + if (get_compat_sigset(&newset, unewset)) return -EFAULT; - sigset_from_compat(&newset, &newset32); return sigsuspend(&newset); -#else - /* on little-endian bitmaps don't care about granularity */ - return sys_rt_sigsuspend((sigset_t __user *)unewset, sigsetsize); -#endif } #endif diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 9deb5a245b83..99bfe50a0589 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2724,7 +2724,6 @@ static long kvm_vcpu_compat_ioctl(struct file *filp, case KVM_SET_SIGNAL_MASK: { struct kvm_signal_mask __user *sigmask_arg = argp; struct kvm_signal_mask kvm_sigmask; - compat_sigset_t csigset; sigset_t sigset; if (argp) { @@ -2733,13 +2732,11 @@ static long kvm_vcpu_compat_ioctl(struct file *filp, sizeof(kvm_sigmask))) goto out; r = -EINVAL; - if (kvm_sigmask.len != sizeof(csigset)) + if (kvm_sigmask.len != sizeof(compat_sigset_t)) goto out; r = -EFAULT; - if (copy_from_user(&csigset, sigmask_arg->sigset, - sizeof(csigset))) + if (get_compat_sigset(&sigset, (void *)sigmask_arg->sigset)) goto out; - sigset_from_compat(&sigset, &csigset); r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset); } else r = kvm_vcpu_ioctl_set_sigmask(vcpu, NULL); -- GitLab From d74f0f47e2787837598c6ff6f75d44cbc3753689 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 4 Sep 2017 12:14:28 -0400 Subject: [PATCH 0022/2898] parisc: switch to {get,put}_compat_sigset() Signed-off-by: Al Viro --- arch/parisc/kernel/signal.c | 9 +++------ arch/parisc/kernel/signal32.c | 13 ------------- arch/parisc/kernel/signal32.h | 2 -- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 26f12f45b4bb..fdd82e87b340 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -92,7 +92,6 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) unsigned long usp = (regs->gr[30] & ~(0x01UL)); unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE; #ifdef CONFIG_64BIT - compat_sigset_t compat_set; struct compat_rt_sigframe __user * compat_frame; if (is_compat_task()) @@ -113,9 +112,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) if (is_compat_task()) { DBG(2,"sys_rt_sigreturn: ELF32 process.\n"); - if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set))) + if (get_compat_sigset(&set, &compat_frame->uc.uc_sigmask)) goto give_sigsegv; - sigset_32to64(&set,&compat_set); } else #endif { @@ -237,7 +235,6 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, int err = 0; #ifdef CONFIG_64BIT struct compat_rt_sigframe __user * compat_frame; - compat_sigset_t compat_set; #endif usp = (regs->gr[30] & ~(0x01UL)); @@ -260,8 +257,8 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext); err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext, &compat_frame->regs, regs, in_syscall); - sigset_64to32(&compat_set,set); - err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set)); + err |= put_compat_sigset(&compat_frame->uc.uc_sigmask, set, + sizeof(compat_sigset_t)); } else #endif { diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index 9e0cb6a577d6..41afa9cd1f55 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -46,19 +46,6 @@ #define DBG(LEVEL, ...) #endif -inline void -sigset_32to64(sigset_t *s64, compat_sigset_t *s32) -{ - s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32); -} - -inline void -sigset_64to32(compat_sigset_t *s32, sigset_t *s64) -{ - s32->sig[0] = s64->sig[0] & 0xffffffffUL; - s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL; -} - long restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, struct pt_regs *regs) diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h index af51d4ccee42..719e7417732c 100644 --- a/arch/parisc/kernel/signal32.h +++ b/arch/parisc/kernel/signal32.h @@ -79,8 +79,6 @@ struct compat_rt_sigframe { #define FUNCTIONCALLFRAME32 48 #define PARISC_RT_SIGFRAME_SIZE32 (((sizeof(struct compat_rt_sigframe) + FUNCTIONCALLFRAME32) + SIGFRAME32) & -SIGFRAME32) -void sigset_32to64(sigset_t *s64, compat_sigset_t *s32); -void sigset_64to32(compat_sigset_t *s32, sigset_t *s64); long restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user *rf, struct pt_regs *regs); -- GitLab From a5ae754a3de9c1ad970d3690d03929f8b6553389 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 4 Sep 2017 12:17:38 -0400 Subject: [PATCH 0023/2898] ppc: switch to {get,put}_compat_sigset() Signed-off-by: Al Viro --- arch/powerpc/kernel/signal_32.c | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 92fb1c8dbbd8..1a969925bf80 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -94,40 +94,13 @@ */ static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set) { - compat_sigset_t cset; - - switch (_NSIG_WORDS) { - case 4: cset.sig[6] = set->sig[3] & 0xffffffffull; - cset.sig[7] = set->sig[3] >> 32; - case 3: cset.sig[4] = set->sig[2] & 0xffffffffull; - cset.sig[5] = set->sig[2] >> 32; - case 2: cset.sig[2] = set->sig[1] & 0xffffffffull; - cset.sig[3] = set->sig[1] >> 32; - case 1: cset.sig[0] = set->sig[0] & 0xffffffffull; - cset.sig[1] = set->sig[0] >> 32; - } - return copy_to_user(uset, &cset, sizeof(*uset)); + return put_compat_sigset(uset, set, sizeof(*uset)); } static inline int get_sigset_t(sigset_t *set, const compat_sigset_t __user *uset) { - compat_sigset_t s32; - - if (copy_from_user(&s32, uset, sizeof(*uset))) - return -EFAULT; - - /* - * Swap the 2 words of the 64-bit sigset_t (they are stored - * in the "wrong" endian in 32-bit user storage). - */ - switch (_NSIG_WORDS) { - case 4: set->sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); - case 3: set->sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); - case 2: set->sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); - case 1: set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); - } - return 0; + return get_compat_sigset(set, uset); } #define to_user_ptr(p) ptr_to_compat(p) -- GitLab From c60a03fee0e5d5c124befe041696228c8c665eaa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 4 Sep 2017 12:24:17 -0400 Subject: [PATCH 0024/2898] s390: switch to {get,put}_compat_sigset() Signed-off-by: Al Viro --- arch/s390/kernel/compat_signal.c | 33 +++++++------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index f549c4657376..b4327a28060a 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -49,19 +49,6 @@ typedef struct struct ucontext32 uc; } rt_sigframe32; -static inline void sigset_to_sigset32(unsigned long *set64, - compat_sigset_word *set32) -{ - set32[0] = (compat_sigset_word) set64[0]; - set32[1] = (compat_sigset_word)(set64[0] >> 32); -} - -static inline void sigset32_to_sigset(compat_sigset_word *set32, - unsigned long *set64) -{ - set64[0] = (unsigned long) set32[0] | ((unsigned long) set32[1] << 32); -} - int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) { int err; @@ -293,12 +280,10 @@ COMPAT_SYSCALL_DEFINE0(sigreturn) { struct pt_regs *regs = task_pt_regs(current); sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; - compat_sigset_t cset; sigset_t set; - if (__copy_from_user(&cset.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32)) + if (get_compat_sigset(&set, (compat_sigset_t __user *)frame->sc.oldmask)) goto badframe; - sigset32_to_sigset(cset.sig, set.sig); set_current_blocked(&set); save_fpu_regs(); if (restore_sigregs32(regs, &frame->sregs)) @@ -316,12 +301,10 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn) { struct pt_regs *regs = task_pt_regs(current); rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; - compat_sigset_t cset; sigset_t set; - if (__copy_from_user(&cset, &frame->uc.uc_sigmask, sizeof(cset))) + if (get_compat_sigset(&set, &frame->uc.uc_sigmask)) goto badframe; - sigset32_to_sigset(cset.sig, set.sig); set_current_blocked(&set); if (compat_restore_altstack(&frame->uc.uc_stack)) goto badframe; @@ -371,7 +354,6 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set, { int sig = ksig->sig; sigframe32 __user *frame; - struct sigcontext32 sc; unsigned long restorer; size_t frame_size; @@ -393,9 +375,10 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set, return -EFAULT; /* Create struct sigcontext32 on the signal stack */ - sigset_to_sigset32(set->sig, sc.oldmask); - sc.sregs = (__u32)(unsigned long __force) &frame->sregs; - if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc))) + if (put_compat_sigset((compat_sigset_t __user *)frame->sc.oldmask, + set, sizeof(compat_sigset_t))) + return -EFAULT; + if (__put_user(ptr_to_compat(&frame->sc), &frame->sc.sregs)) return -EFAULT; /* Store registers needed to create the signal frame */ @@ -454,7 +437,6 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set, static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { - compat_sigset_t cset; rt_sigframe32 __user *frame; unsigned long restorer; size_t frame_size; @@ -501,12 +483,11 @@ static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set, store_sigregs(); /* Create ucontext on the signal stack. */ - sigset_to_sigset32(set->sig, cset.sig); if (__put_user(uc_flags, &frame->uc.uc_flags) || __put_user(0, &frame->uc.uc_link) || __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) || save_sigregs32(regs, &frame->uc.uc_mcontext) || - __copy_to_user(&frame->uc.uc_sigmask, &cset, sizeof(cset)) || + put_compat_sigset(&frame->uc.uc_sigmask, set, sizeof(compat_sigset_t)) || save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext)) return -EFAULT; -- GitLab From 68c38fb6acb12f007785c53a7367fc9de8e34745 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 4 Sep 2017 12:28:06 -0400 Subject: [PATCH 0025/2898] sparc: switch to {get,put}_compat_sigset() slightly more complicated than usual, since old sigframe layout on sparc keeps the first 32 bits of mask away from the rest Signed-off-by: Al Viro --- arch/sparc/kernel/signal32.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 0e4c08c45a37..36ad8301fb4c 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -248,7 +248,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) compat_uptr_t fpu_save; compat_uptr_t rwin_save; sigset_t set; - compat_sigset_t seta; int err, i; /* Always make any pending restarted system calls return -EINTR */ @@ -311,7 +310,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) err |= __get_user(fpu_save, &sf->fpu_save); if (!err && fpu_save) err |= restore_fpu_state(regs, compat_ptr(fpu_save)); - err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t)); + err |= get_compat_sigset(&set, &sf->mask); err |= compat_restore_altstack(&sf->stack); if (err) goto segv; @@ -322,7 +321,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) goto segv; } - set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); set_current_blocked(&set); return; segv: @@ -554,7 +552,6 @@ static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs, void __user *tail; int sigframe_size; u32 psr; - compat_sigset_t seta; /* 1. Make sure everything is clean */ synchronize_user_stack(); @@ -624,9 +621,7 @@ static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs, /* Setup sigaltstack */ err |= __compat_save_altstack(&sf->stack, regs->u_regs[UREG_FP]); - seta.sig[1] = (oldset->sig[0] >> 32); - seta.sig[0] = oldset->sig[0]; - err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t)); + err |= put_compat_sigset(&sf->mask, oldset, sizeof(compat_sigset_t)); if (!wsaved) { err |= copy_in_user((u32 __user *)sf, -- GitLab From 7bea578b5f0c44c974a585bfbe6422065b9f6b6d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 4 Sep 2017 12:37:53 -0400 Subject: [PATCH 0026/2898] mips: switch to {get,put}_compat_sigset() Signed-off-by: Al Viro --- arch/mips/include/asm/compat-signal.h | 37 +++------------------------ 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/arch/mips/include/asm/compat-signal.h b/arch/mips/include/asm/compat-signal.h index 4c6176467146..1705b7769f75 100644 --- a/arch/mips/include/asm/compat-signal.h +++ b/arch/mips/include/asm/compat-signal.h @@ -13,45 +13,16 @@ static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d, const sigset_t *s) { - int err; + BUILD_BUG_ON(sizeof(*d) != sizeof(*s)); + BUILD_BUG_ON(_NSIG_WORDS != 2); - BUG_ON(sizeof(*d) != sizeof(*s)); - BUG_ON(_NSIG_WORDS != 2); - - err = __put_user(s->sig[0], &d->sig[0]); - err |= __put_user(s->sig[0] >> 32, &d->sig[1]); - err |= __put_user(s->sig[1], &d->sig[2]); - err |= __put_user(s->sig[1] >> 32, &d->sig[3]); - - return err; + return put_compat_sigset(d, s, sizeof(*d)); } static inline int __copy_conv_sigset_from_user(sigset_t *d, const compat_sigset_t __user *s) { - int err; - union sigset_u { - sigset_t s; - compat_sigset_t c; - } *u = (union sigset_u *) d; - - BUG_ON(sizeof(*d) != sizeof(*s)); - BUG_ON(_NSIG_WORDS != 2); - -#ifdef CONFIG_CPU_BIG_ENDIAN - err = __get_user(u->c.sig[1], &s->sig[0]); - err |= __get_user(u->c.sig[0], &s->sig[1]); - err |= __get_user(u->c.sig[3], &s->sig[2]); - err |= __get_user(u->c.sig[2], &s->sig[3]); -#endif -#ifdef CONFIG_CPU_LITTLE_ENDIAN - err = __get_user(u->c.sig[0], &s->sig[0]); - err |= __get_user(u->c.sig[1], &s->sig[1]); - err |= __get_user(u->c.sig[2], &s->sig[2]); - err |= __get_user(u->c.sig[3], &s->sig[3]); -#endif - - return err; + return get_compat_sigset(d, s); } #endif /* __ASM_COMPAT_SIGNAL_H */ -- GitLab From 4633f7a156bf41003b1527f88ddf843ce0bb7d68 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Fri, 14 Jul 2017 17:11:06 +0300 Subject: [PATCH 0027/2898] thermal: imx: Add nvmem-cells alternate binding for OCOTP access On newer imx SOCs accessing OCOTP directly is wrong because the ocotp clock needs to be enabled first. Add a binding for accessing the same values through the imx-ocotp nvmem driver using nvmem-cells. This is similar to other thermal drivers. The old binding is preserved for compatibility and because it still works fine on imx6qdl series chips. In theory this problem could be solved by adding a reference to the OCOTP clock instead but it is better to hide such details in a specific nvmem driver. Signed-off-by: Leonard Crestez Acked-by: Rob Herring Signed-off-by: Zhang Rui --- Documentation/devicetree/bindings/thermal/imx-thermal.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/imx-thermal.txt b/Documentation/devicetree/bindings/thermal/imx-thermal.txt index 3c67bd50aa10..28be51afdb6a 100644 --- a/Documentation/devicetree/bindings/thermal/imx-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/imx-thermal.txt @@ -7,10 +7,17 @@ Required properties: is higher than panic threshold, system will auto reboot by SRC module. - fsl,tempmon : phandle pointer to system controller that contains TEMPMON control registers, e.g. ANATOP on imx6q. +- nvmem-cells: A phandle to the calibration cells provided by ocotp. +- nvmem-cell-names: Should be "calib", "temp_grade". + +Deprecated properties: - fsl,tempmon-data : phandle pointer to fuse controller that contains TEMPMON calibration data, e.g. OCOTP on imx6q. The details about calibration data can be found in SoC Reference Manual. +Direct access to OCOTP via fsl,tempmon-data is incorrect on some newer chips +because it does not handle OCOTP clock requirements. + Optional properties: - clocks : thermal sensor's clock source. -- GitLab From ae6215576d6b2251ab8c6bbeaf1c4cea99f0481b Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Fri, 14 Jul 2017 17:11:08 +0300 Subject: [PATCH 0028/2898] thermal: imx: Add support for reading OCOTP through nvmem On newer imx SOCs accessing OCOTP directly is wrong because the ocotp clock needs to be enabled first. Add support for reading those same values through the nvmem API instead. The older path is preserved for compatibility with older dts and because it works correctly on imx6qdl chips. Signed-off-by: Leonard Crestez Acked-by: Shawn Guo Signed-off-by: Zhang Rui --- drivers/thermal/imx_thermal.c | 104 ++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 4798b4b1fd77..e7d4ffc3de7f 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -25,6 +25,7 @@ #include #include #include +#include #define REG_SET 0x4 #define REG_CLR 0x8 @@ -94,7 +95,7 @@ struct imx_thermal_data { struct thermal_cooling_device *cdev; enum thermal_device_mode mode; struct regmap *tempmon; - u32 c1, c2; /* See formula in imx_get_sensor_data() */ + u32 c1, c2; /* See formula in imx_init_calib() */ int temp_passive; int temp_critical; int temp_max; @@ -177,7 +178,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT; - /* See imx_get_sensor_data() for formula derivation */ + /* See imx_init_calib() for formula derivation */ *temp = data->c2 - n_meas * data->c1; /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */ @@ -346,29 +347,12 @@ static struct thermal_zone_device_ops imx_tz_ops = { .set_trip_temp = imx_set_trip_temp, }; -static int imx_get_sensor_data(struct platform_device *pdev) +static int imx_init_calib(struct platform_device *pdev, u32 val) { struct imx_thermal_data *data = platform_get_drvdata(pdev); - struct regmap *map; int t1, n1; - int ret; - u32 val; u64 temp64; - map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "fsl,tempmon-data"); - if (IS_ERR(map)) { - ret = PTR_ERR(map); - dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret); - return ret; - } - - ret = regmap_read(map, OCOTP_ANA1, &val); - if (ret) { - dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret); - return ret; - } - if (val == 0 || val == ~0) { dev_err(&pdev->dev, "invalid sensor calibration data\n"); return -EINVAL; @@ -405,12 +389,12 @@ static int imx_get_sensor_data(struct platform_device *pdev) data->c1 = temp64; data->c2 = n1 * data->c1 + 1000 * t1; - /* use OTP for thermal grade */ - ret = regmap_read(map, OCOTP_MEM0, &val); - if (ret) { - dev_err(&pdev->dev, "failed to read temp grade: %d\n", ret); - return ret; - } + return 0; +} + +static void imx_init_temp_grade(struct platform_device *pdev, u32 val) +{ + struct imx_thermal_data *data = platform_get_drvdata(pdev); /* The maximum die temp is specified by the Temperature Grade */ switch ((val >> 6) & 0x3) { @@ -438,6 +422,55 @@ static int imx_get_sensor_data(struct platform_device *pdev) */ data->temp_critical = data->temp_max - (1000 * 5); data->temp_passive = data->temp_max - (1000 * 10); +} + +static int imx_init_from_tempmon_data(struct platform_device *pdev) +{ + struct regmap *map; + int ret; + u32 val; + + map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "fsl,tempmon-data"); + if (IS_ERR(map)) { + ret = PTR_ERR(map); + dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret); + return ret; + } + + ret = regmap_read(map, OCOTP_ANA1, &val); + if (ret) { + dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret); + return ret; + } + ret = imx_init_calib(pdev, val); + if (ret) + return ret; + + ret = regmap_read(map, OCOTP_MEM0, &val); + if (ret) { + dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret); + return ret; + } + imx_init_temp_grade(pdev, val); + + return 0; +} + +static int imx_init_from_nvmem_cells(struct platform_device *pdev) +{ + int ret; + u32 val; + + ret = nvmem_cell_read_u32(&pdev->dev, "calib", &val); + if (ret) + return ret; + imx_init_calib(pdev, val); + + ret = nvmem_cell_read_u32(&pdev->dev, "temp_grade", &val); + if (ret) + return ret; + imx_init_temp_grade(pdev, val); return 0; } @@ -514,10 +547,21 @@ static int imx_thermal_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); - ret = imx_get_sensor_data(pdev); - if (ret) { - dev_err(&pdev->dev, "failed to get sensor data\n"); - return ret; + if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) { + ret = imx_init_from_nvmem_cells(pdev); + if (ret == -EPROBE_DEFER) + return ret; + if (ret) { + dev_err(&pdev->dev, "failed to init from nvmem: %d\n", + ret); + return ret; + } + } else { + ret = imx_init_from_tempmon_data(pdev); + if (ret) { + dev_err(&pdev->dev, "failed to init from from fsl,tempmon-data\n"); + return ret; + } } /* Make sure sensor is in known good state for measurements */ -- GitLab From abca5fc535a3ee0f36fb6d4468a453eaae769921 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 19 Sep 2017 18:17:46 -0400 Subject: [PATCH 0029/2898] sched_rr_get_interval(): move compat to native, get rid of set_fs() switch to using timespec64 internally, while we are at it Signed-off-by: Al Viro --- kernel/compat.c | 16 ---------------- kernel/sched/core.c | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/kernel/compat.c b/kernel/compat.c index a46a4a40bb8b..d1cee656a7ed 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -562,22 +562,6 @@ COMPAT_SYSCALL_DEFINE4(migrate_pages, compat_pid_t, pid, } #endif -COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval, - compat_pid_t, pid, - struct compat_timespec __user *, interval) -{ - struct timespec t; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); - set_fs(old_fs); - if (compat_put_timespec(&t, interval)) - return -EFAULT; - return ret; -} - /* * Allocate user-space memory for the duration of a single system call, * in order to marshall parameters inside a compat thunk. diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 18a6966567da..e74f0a5a8647 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -5098,13 +5099,11 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy) * Return: On success, 0 and the timeslice is in @interval. Otherwise, * an error code. */ -SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, - struct timespec __user *, interval) +static int sched_rr_get_interval(pid_t pid, struct timespec64 *t) { struct task_struct *p; unsigned int time_slice; struct rq_flags rf; - struct timespec t; struct rq *rq; int retval; @@ -5128,15 +5127,40 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, task_rq_unlock(rq, p, &rf); rcu_read_unlock(); - jiffies_to_timespec(time_slice, &t); - retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0; - return retval; + jiffies_to_timespec64(time_slice, t); + return 0; out_unlock: rcu_read_unlock(); return retval; } +SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, + struct timespec __user *, interval) +{ + struct timespec64 t; + int retval = sched_rr_get_interval(pid, &t); + + if (retval == 0) + retval = put_timespec64(&t, interval); + + return retval; +} + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval, + compat_pid_t, pid, + struct compat_timespec __user *, interval) +{ + struct timespec64 t; + int retval = sched_rr_get_interval(pid, &t); + + if (retval == 0) + retval = compat_put_timespec64(&t, interval); + return retval; +} +#endif + void sched_show_task(struct task_struct *p) { unsigned long free = 0; -- GitLab From 7d5cb45655f2e9e37ef75d18f50c0072ef14a38b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 20 Sep 2017 01:02:27 -0400 Subject: [PATCH 0030/2898] i2c compat ioctls: move to ->compat_ioctl() Signed-off-by: Al Viro --- drivers/i2c/i2c-dev.c | 268 ++++++++++++++++++++++++++++-------------- fs/compat_ioctl.c | 122 ------------------- 2 files changed, 180 insertions(+), 210 deletions(-) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 6f638bbc922d..2cab27a68479 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a @@ -238,46 +239,29 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) } static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, - unsigned long arg) + unsigned nmsgs, struct i2c_msg *msgs) { - struct i2c_rdwr_ioctl_data rdwr_arg; - struct i2c_msg *rdwr_pa; u8 __user **data_ptrs; int i, res; - if (copy_from_user(&rdwr_arg, - (struct i2c_rdwr_ioctl_data __user *)arg, - sizeof(rdwr_arg))) - return -EFAULT; - - /* Put an arbitrary limit on the number of messages that can - * be sent at once */ - if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) - return -EINVAL; - - rdwr_pa = memdup_user(rdwr_arg.msgs, - rdwr_arg.nmsgs * sizeof(struct i2c_msg)); - if (IS_ERR(rdwr_pa)) - return PTR_ERR(rdwr_pa); - - data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); + data_ptrs = kmalloc(nmsgs * sizeof(u8 __user *), GFP_KERNEL); if (data_ptrs == NULL) { - kfree(rdwr_pa); + kfree(msgs); return -ENOMEM; } res = 0; - for (i = 0; i < rdwr_arg.nmsgs; i++) { + for (i = 0; i < nmsgs; i++) { /* Limit the size of the message to a sane amount */ - if (rdwr_pa[i].len > 8192) { + if (msgs[i].len > 8192) { res = -EINVAL; break; } - data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; - rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); - if (IS_ERR(rdwr_pa[i].buf)) { - res = PTR_ERR(rdwr_pa[i].buf); + data_ptrs[i] = (u8 __user *)msgs[i].buf; + msgs[i].buf = memdup_user(data_ptrs[i], msgs[i].len); + if (IS_ERR(msgs[i].buf)) { + res = PTR_ERR(msgs[i].buf); break; } @@ -292,121 +276,117 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, * greater (for example to account for a checksum byte at * the end of the message.) */ - if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { - if (!(rdwr_pa[i].flags & I2C_M_RD) || - rdwr_pa[i].buf[0] < 1 || - rdwr_pa[i].len < rdwr_pa[i].buf[0] + + if (msgs[i].flags & I2C_M_RECV_LEN) { + if (!(msgs[i].flags & I2C_M_RD) || + msgs[i].buf[0] < 1 || + msgs[i].len < msgs[i].buf[0] + I2C_SMBUS_BLOCK_MAX) { res = -EINVAL; break; } - rdwr_pa[i].len = rdwr_pa[i].buf[0]; + msgs[i].len = msgs[i].buf[0]; } } if (res < 0) { int j; for (j = 0; j < i; ++j) - kfree(rdwr_pa[j].buf); + kfree(msgs[j].buf); kfree(data_ptrs); - kfree(rdwr_pa); + kfree(msgs); return res; } - res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); + res = i2c_transfer(client->adapter, msgs, nmsgs); while (i-- > 0) { - if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) { - if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, - rdwr_pa[i].len)) + if (res >= 0 && (msgs[i].flags & I2C_M_RD)) { + if (copy_to_user(data_ptrs[i], msgs[i].buf, + msgs[i].len)) res = -EFAULT; } - kfree(rdwr_pa[i].buf); + kfree(msgs[i].buf); } kfree(data_ptrs); - kfree(rdwr_pa); + kfree(msgs); return res; } static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, - unsigned long arg) + u8 read_write, u8 command, u32 size, + union i2c_smbus_data __user *data) { - struct i2c_smbus_ioctl_data data_arg; union i2c_smbus_data temp = {}; int datasize, res; - if (copy_from_user(&data_arg, - (struct i2c_smbus_ioctl_data __user *) arg, - sizeof(struct i2c_smbus_ioctl_data))) - return -EFAULT; - if ((data_arg.size != I2C_SMBUS_BYTE) && - (data_arg.size != I2C_SMBUS_QUICK) && - (data_arg.size != I2C_SMBUS_BYTE_DATA) && - (data_arg.size != I2C_SMBUS_WORD_DATA) && - (data_arg.size != I2C_SMBUS_PROC_CALL) && - (data_arg.size != I2C_SMBUS_BLOCK_DATA) && - (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) && - (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && - (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { + if ((size != I2C_SMBUS_BYTE) && + (size != I2C_SMBUS_QUICK) && + (size != I2C_SMBUS_BYTE_DATA) && + (size != I2C_SMBUS_WORD_DATA) && + (size != I2C_SMBUS_PROC_CALL) && + (size != I2C_SMBUS_BLOCK_DATA) && + (size != I2C_SMBUS_I2C_BLOCK_BROKEN) && + (size != I2C_SMBUS_I2C_BLOCK_DATA) && + (size != I2C_SMBUS_BLOCK_PROC_CALL)) { dev_dbg(&client->adapter->dev, "size out of range (%x) in ioctl I2C_SMBUS.\n", - data_arg.size); + size); return -EINVAL; } /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, so the check is valid if size==I2C_SMBUS_QUICK too. */ - if ((data_arg.read_write != I2C_SMBUS_READ) && - (data_arg.read_write != I2C_SMBUS_WRITE)) { + if ((read_write != I2C_SMBUS_READ) && + (read_write != I2C_SMBUS_WRITE)) { dev_dbg(&client->adapter->dev, "read_write out of range (%x) in ioctl I2C_SMBUS.\n", - data_arg.read_write); + read_write); return -EINVAL; } /* Note that command values are always valid! */ - if ((data_arg.size == I2C_SMBUS_QUICK) || - ((data_arg.size == I2C_SMBUS_BYTE) && - (data_arg.read_write == I2C_SMBUS_WRITE))) + if ((size == I2C_SMBUS_QUICK) || + ((size == I2C_SMBUS_BYTE) && + (read_write == I2C_SMBUS_WRITE))) /* These are special: we do not use data */ return i2c_smbus_xfer(client->adapter, client->addr, - client->flags, data_arg.read_write, - data_arg.command, data_arg.size, NULL); + client->flags, read_write, + command, size, NULL); - if (data_arg.data == NULL) { + if (data == NULL) { dev_dbg(&client->adapter->dev, "data is NULL pointer in ioctl I2C_SMBUS.\n"); return -EINVAL; } - if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || - (data_arg.size == I2C_SMBUS_BYTE)) - datasize = sizeof(data_arg.data->byte); - else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || - (data_arg.size == I2C_SMBUS_PROC_CALL)) - datasize = sizeof(data_arg.data->word); + if ((size == I2C_SMBUS_BYTE_DATA) || + (size == I2C_SMBUS_BYTE)) + datasize = sizeof(data->byte); + else if ((size == I2C_SMBUS_WORD_DATA) || + (size == I2C_SMBUS_PROC_CALL)) + datasize = sizeof(data->word); else /* size == smbus block, i2c block, or block proc. call */ - datasize = sizeof(data_arg.data->block); + datasize = sizeof(data->block); - if ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) || - (data_arg.read_write == I2C_SMBUS_WRITE)) { - if (copy_from_user(&temp, data_arg.data, datasize)) + if ((size == I2C_SMBUS_PROC_CALL) || + (size == I2C_SMBUS_BLOCK_PROC_CALL) || + (size == I2C_SMBUS_I2C_BLOCK_DATA) || + (read_write == I2C_SMBUS_WRITE)) { + if (copy_from_user(&temp, data, datasize)) return -EFAULT; } - if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) { + if (size == I2C_SMBUS_I2C_BLOCK_BROKEN) { /* Convert old I2C block commands to the new convention. This preserves binary compatibility. */ - data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA; - if (data_arg.read_write == I2C_SMBUS_READ) + size = I2C_SMBUS_I2C_BLOCK_DATA; + if (read_write == I2C_SMBUS_READ) temp.block[0] = I2C_SMBUS_BLOCK_MAX; } res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - data_arg.read_write, data_arg.command, data_arg.size, &temp); - if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.read_write == I2C_SMBUS_READ))) { - if (copy_to_user(data_arg.data, &temp, datasize)) + read_write, command, size, &temp); + if (!res && ((size == I2C_SMBUS_PROC_CALL) || + (size == I2C_SMBUS_BLOCK_PROC_CALL) || + (read_write == I2C_SMBUS_READ))) { + if (copy_to_user(data, &temp, datasize)) return -EFAULT; } return res; @@ -454,12 +434,39 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) funcs = i2c_get_functionality(client->adapter); return put_user(funcs, (unsigned long __user *)arg); - case I2C_RDWR: - return i2cdev_ioctl_rdwr(client, arg); + case I2C_RDWR: { + struct i2c_rdwr_ioctl_data rdwr_arg; + struct i2c_msg *rdwr_pa; + + if (copy_from_user(&rdwr_arg, + (struct i2c_rdwr_ioctl_data __user *)arg, + sizeof(rdwr_arg))) + return -EFAULT; + + /* Put an arbitrary limit on the number of messages that can + * be sent at once */ + if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) + return -EINVAL; - case I2C_SMBUS: - return i2cdev_ioctl_smbus(client, arg); + rdwr_pa = memdup_user(rdwr_arg.msgs, + rdwr_arg.nmsgs * sizeof(struct i2c_msg)); + if (IS_ERR(rdwr_pa)) + return PTR_ERR(rdwr_pa); + + return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); + } + case I2C_SMBUS: { + struct i2c_smbus_ioctl_data data_arg; + if (copy_from_user(&data_arg, + (struct i2c_smbus_ioctl_data __user *) arg, + sizeof(struct i2c_smbus_ioctl_data))) + return -EFAULT; + return i2cdev_ioctl_smbus(client, data_arg.read_write, + data_arg.command, + data_arg.size, + data_arg.data); + } case I2C_RETRIES: client->adapter->retries = arg; break; @@ -480,6 +487,90 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } +#ifdef CONFIG_COMPAT + +struct i2c_smbus_ioctl_data32 { + u8 read_write; + u8 command; + u32 size; + compat_caddr_t data; /* union i2c_smbus_data *data */ +}; + +struct i2c_msg32 { + u16 addr; + u16 flags; + u16 len; + compat_caddr_t buf; +}; + +struct i2c_rdwr_ioctl_data32 { + compat_caddr_t msgs; /* struct i2c_msg __user *msgs */ + u32 nmsgs; +}; + +static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct i2c_client *client = file->private_data; + unsigned long funcs; + switch (cmd) { + case I2C_FUNCS: + funcs = i2c_get_functionality(client->adapter); + return put_user(funcs, (compat_ulong_t __user *)arg); + case I2C_RDWR: { + struct i2c_rdwr_ioctl_data32 rdwr_arg; + struct i2c_msg32 *p; + struct i2c_msg *rdwr_pa; + int i; + + if (copy_from_user(&rdwr_arg, + (struct i2c_rdwr_ioctl_data32 __user *)arg, + sizeof(rdwr_arg))) + return -EFAULT; + + if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) + return -EINVAL; + + rdwr_pa = kmalloc_array(rdwr_arg.nmsgs, sizeof(struct i2c_msg), + GFP_KERNEL); + if (!rdwr_pa) + return -ENOMEM; + + p = compat_ptr(rdwr_arg.msgs); + for (i = 0; i < rdwr_arg.nmsgs; i++) { + struct i2c_msg32 umsg; + if (copy_from_user(&umsg, p + i, sizeof(umsg))) { + kfree(rdwr_pa); + return -EFAULT; + } + rdwr_pa[i] = (struct i2c_msg) { + .addr = umsg.addr, + .flags = umsg.flags, + .len = umsg.len, + .buf = compat_ptr(umsg.buf) + }; + } + + return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); + } + case I2C_SMBUS: { + struct i2c_smbus_ioctl_data32 data32; + if (copy_from_user(&data32, + (void __user *) arg, + sizeof(data32))) + return -EFAULT; + return i2cdev_ioctl_smbus(client, data32.read_write, + data32.command, + data32.size, + compat_ptr(data32.data)); + } + default: + return i2cdev_ioctl(file, cmd, arg); + } +} +#else +#define compat_i2cdev_ioctl NULL +#endif + static int i2cdev_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); @@ -527,6 +618,7 @@ static const struct file_operations i2cdev_fops = { .read = i2cdev_read, .write = i2cdev_write, .unlocked_ioctl = i2cdev_ioctl, + .compat_ioctl = compat_i2cdev_ioctl, .open = i2cdev_open, .release = i2cdev_release, }; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index d27b326d96f4..a545deeeaff5 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -53,8 +53,6 @@ #include #include #include -#include -#include #include #include #include @@ -136,22 +134,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return vfs_ioctl(file, cmd, arg); } -static int w_long(struct file *file, - unsigned int cmd, compat_ulong_t __user *argp) -{ - int err; - unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp)); - - if (valp == NULL) - return -EFAULT; - err = do_ioctl(file, cmd, (unsigned long)valp); - if (err) - return err; - if (convert_in_user(valp, argp)) - return -EFAULT; - return 0; -} - struct compat_video_event { int32_t type; compat_time_t timestamp; @@ -670,96 +652,6 @@ static int serial_struct_ioctl(struct file *file, return err; } -/* - * I2C layer ioctls - */ - -struct i2c_msg32 { - u16 addr; - u16 flags; - u16 len; - compat_caddr_t buf; -}; - -struct i2c_rdwr_ioctl_data32 { - compat_caddr_t msgs; /* struct i2c_msg __user *msgs */ - u32 nmsgs; -}; - -struct i2c_smbus_ioctl_data32 { - u8 read_write; - u8 command; - u32 size; - compat_caddr_t data; /* union i2c_smbus_data *data */ -}; - -struct i2c_rdwr_aligned { - struct i2c_rdwr_ioctl_data cmd; - struct i2c_msg msgs[0]; -}; - -static int do_i2c_rdwr_ioctl(struct file *file, - unsigned int cmd, struct i2c_rdwr_ioctl_data32 __user *udata) -{ - struct i2c_rdwr_aligned __user *tdata; - struct i2c_msg __user *tmsgs; - struct i2c_msg32 __user *umsgs; - compat_caddr_t datap; - u32 nmsgs; - int i; - - if (get_user(nmsgs, &udata->nmsgs)) - return -EFAULT; - if (nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) - return -EINVAL; - - if (get_user(datap, &udata->msgs)) - return -EFAULT; - umsgs = compat_ptr(datap); - - tdata = compat_alloc_user_space(sizeof(*tdata) + - nmsgs * sizeof(struct i2c_msg)); - tmsgs = &tdata->msgs[0]; - - if (put_user(nmsgs, &tdata->cmd.nmsgs) || - put_user(tmsgs, &tdata->cmd.msgs)) - return -EFAULT; - - for (i = 0; i < nmsgs; i++) { - if (copy_in_user(&tmsgs[i].addr, &umsgs[i].addr, 3*sizeof(u16))) - return -EFAULT; - if (get_user(datap, &umsgs[i].buf) || - put_user(compat_ptr(datap), &tmsgs[i].buf)) - return -EFAULT; - } - return do_ioctl(file, cmd, (unsigned long)tdata); -} - -static int do_i2c_smbus_ioctl(struct file *file, - unsigned int cmd, struct i2c_smbus_ioctl_data32 __user *udata) -{ - struct i2c_smbus_ioctl_data __user *tdata; - union { - /* beginnings of those have identical layouts */ - struct i2c_smbus_ioctl_data32 data32; - struct i2c_smbus_ioctl_data data; - } v; - - tdata = compat_alloc_user_space(sizeof(*tdata)); - if (tdata == NULL) - return -ENOMEM; - - memset(&v, 0, sizeof(v)); - if (copy_from_user(&v.data32, udata, sizeof(v.data32))) - return -EFAULT; - v.data.data = compat_ptr(v.data32.data); - - if (copy_to_user(tdata, &v.data, sizeof(v.data))) - return -EFAULT; - - return do_ioctl(file, cmd, (unsigned long)tdata); -} - #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) @@ -1282,13 +1174,6 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) -/* i2c */ -COMPATIBLE_IOCTL(I2C_SLAVE) -COMPATIBLE_IOCTL(I2C_SLAVE_FORCE) -COMPATIBLE_IOCTL(I2C_TENBIT) -COMPATIBLE_IOCTL(I2C_PEC) -COMPATIBLE_IOCTL(I2C_RETRIES) -COMPATIBLE_IOCTL(I2C_TIMEOUT) /* hiddev */ COMPATIBLE_IOCTL(HIDIOCGVERSION) COMPATIBLE_IOCTL(HIDIOCAPPLICATION) @@ -1463,13 +1348,6 @@ static long do_ioctl_trans(unsigned int cmd, case TIOCGSERIAL: case TIOCSSERIAL: return serial_struct_ioctl(file, cmd, argp); - /* i2c */ - case I2C_FUNCS: - return w_long(file, cmd, argp); - case I2C_RDWR: - return do_i2c_rdwr_ioctl(file, cmd, argp); - case I2C_SMBUS: - return do_i2c_smbus_ioctl(file, cmd, argp); /* Not implemented in the native kernel */ case RTC_IRQP_READ32: case RTC_IRQP_SET32: -- GitLab From ce6a90027c10f970f872de5db0294f9e3e969f1c Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 8 Sep 2017 10:23:11 -0500 Subject: [PATCH 0031/2898] platform/x86: Add driver to force WMI Thunderbolt controller power status Current implementations of Intel Thunderbolt controllers will go into a low power mode when not in use. Many machines containing these controllers also have a GPIO wired up that can force the controller awake. This is offered via a ACPI-WMI interface intended to be manipulated by a userspace utility. This mechanism is provided by Intel to OEMs to include in BIOS. It uses an industry wide GUID that is populated in a separate _WDG entry with no binary MOF. This interface allows software such as fwupd to wake up thunderbolt controllers to query the firmware version or flash new firmware. Signed-off-by: Mario Limonciello Reviewed-by: Mika Westerberg Reviewed-by: Yehezkel Bernat Signed-off-by: Darren Hart (VMware) [andy fixed merge conflicts and bump kernel version for ABI] Signed-off-by: Andy Shevchenko --- .../sysfs-platform-intel-wmi-thunderbolt | 11 ++ Documentation/admin-guide/thunderbolt.rst | 15 +++ MAINTAINERS | 5 + drivers/platform/x86/Kconfig | 13 +++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel-wmi-thunderbolt.c | 101 ++++++++++++++++++ 6 files changed, 146 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt create mode 100644 drivers/platform/x86/intel-wmi-thunderbolt.c diff --git a/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt b/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt new file mode 100644 index 000000000000..8af65059d519 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt @@ -0,0 +1,11 @@ +What: /sys/devices/platform//force_power +Date: September 2017 +KernelVersion: 4.15 +Contact: "Mario Limonciello" +Description: + Modify the platform force power state, influencing + Thunderbolt controllers to turn on or off when no + devices are connected (write-only) + There are two available states: + * 0 -> Force power disabled + * 1 -> Force power enabled diff --git a/Documentation/admin-guide/thunderbolt.rst b/Documentation/admin-guide/thunderbolt.rst index 6a4cd1f159ca..dadcd66ee12f 100644 --- a/Documentation/admin-guide/thunderbolt.rst +++ b/Documentation/admin-guide/thunderbolt.rst @@ -197,3 +197,18 @@ information is missing. To recover from this mode, one needs to flash a valid NVM image to the host host controller in the same way it is done in the previous chapter. + +Forcing power +------------- +Many OEMs include a method that can be used to force the power of a +thunderbolt controller to an "On" state even if nothing is connected. +If supported by your machine this will be exposed by the WMI bus with +a sysfs attribute called "force_power". + +For example the intel-wmi-thunderbolt driver exposes this attribute in: + /sys/devices/platform/PNP0C14:00/wmi_bus/wmi_bus-PNP0C14:00/86CCFD48-205E-4A77-9C48-2021CBEDE341/force_power + + To force the power to on, write 1 to this attribute file. + To disable force power, write 0 to this attribute file. + +Note: it's currently not possible to query the force power state of a platform. diff --git a/MAINTAINERS b/MAINTAINERS index 2281af4b41b6..a6a5746ced9d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7092,6 +7092,11 @@ F: Documentation/wimax/README.i2400m F: drivers/net/wimax/i2400m/ F: include/uapi/linux/wimax/i2400m.h +INTEL WMI THUNDERBOLT FORCE POWER DRIVER +M: Mario Limonciello +S: Maintained +F: drivers/platform/x86/intel-wmi-thunderbolt.c + INTEL(R) TRACE HUB M: Alexander Shishkin S: Supported diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 80b87954f6dd..f401ae463e9b 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -658,6 +658,19 @@ config WMI_BMOF To compile this driver as a module, choose M here: the module will be called wmi-bmof. +config INTEL_WMI_THUNDERBOLT + tristate "Intel WMI thunderbolt force power driver" + depends on ACPI_WMI + default ACPI_WMI + ---help--- + Say Y here if you want to be able to use the WMI interface on select + systems to force the power control of Intel Thunderbolt controllers. + This is useful for updating the firmware when devices are not plugged + into the controller. + + To compile this driver as a module, choose M here: the module will + be called intel-wmi-thunderbolt. + config MSI_WMI tristate "MSI WMI extras" depends on ACPI_WMI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 91cec1751461..2b315d0df3b7 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_PEAQ_WMI) += peaq-wmi.o obj-$(CONFIG_SURFACE3_WMI) += surface3-wmi.o obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o obj-$(CONFIG_WMI_BMOF) += wmi-bmof.o +obj-$(CONFIG_INTEL_WMI_THUNDERBOLT) += intel-wmi-thunderbolt.o # toshiba_acpi must link after wmi to ensure that wmi devices are found # before toshiba_acpi initializes diff --git a/drivers/platform/x86/intel-wmi-thunderbolt.c b/drivers/platform/x86/intel-wmi-thunderbolt.c new file mode 100644 index 000000000000..32fb6cc33d72 --- /dev/null +++ b/drivers/platform/x86/intel-wmi-thunderbolt.c @@ -0,0 +1,101 @@ +/* + * WMI Thunderbolt driver + * + * Copyright (C) 2017 Dell Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INTEL_WMI_THUNDERBOLT_GUID "86CCFD48-205E-4A77-9C48-2021CBEDE341" + +static ssize_t force_power_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_buffer input; + acpi_status status; + u8 mode; + + input.length = sizeof(u8); + input.pointer = &mode; + mode = hex_to_bin(buf[0]); + if (mode == 0 || mode == 1) { + status = wmi_evaluate_method(INTEL_WMI_THUNDERBOLT_GUID, 0, 1, + &input, NULL); + if (ACPI_FAILURE(status)) { + pr_err("intel-wmi-thunderbolt: failed setting %s\n", + buf); + return -ENODEV; + } + } else { + pr_err("intel-wmi-thunderbolt: unsupported mode: %d", mode); + } + return count; +} + +static DEVICE_ATTR_WO(force_power); + +static struct attribute *tbt_attrs[] = { + &dev_attr_force_power.attr, + NULL +}; + +static const struct attribute_group tbt_attribute_group = { + .attrs = tbt_attrs, +}; + +static int intel_wmi_thunderbolt_probe(struct wmi_device *wdev) +{ + int ret; + + ret = sysfs_create_group(&wdev->dev.kobj, &tbt_attribute_group); + kobject_uevent(&wdev->dev.kobj, KOBJ_CHANGE); + return ret; +} + +static int intel_wmi_thunderbolt_remove(struct wmi_device *wdev) +{ + sysfs_remove_group(&wdev->dev.kobj, &tbt_attribute_group); + kobject_uevent(&wdev->dev.kobj, KOBJ_CHANGE); + return 0; +} + +static const struct wmi_device_id intel_wmi_thunderbolt_id_table[] = { + { .guid_string = INTEL_WMI_THUNDERBOLT_GUID }, + { }, +}; + +static struct wmi_driver intel_wmi_thunderbolt_driver = { + .driver = { + .name = "intel-wmi-thunderbolt", + }, + .probe = intel_wmi_thunderbolt_probe, + .remove = intel_wmi_thunderbolt_remove, + .id_table = intel_wmi_thunderbolt_id_table, +}; + +module_wmi_driver(intel_wmi_thunderbolt_driver); + +MODULE_ALIAS("wmi:" INTEL_WMI_THUNDERBOLT_GUID); +MODULE_AUTHOR("Mario Limonciello "); +MODULE_DESCRIPTION("Intel WMI Thunderbolt force power driver"); +MODULE_LICENSE("GPL"); -- GitLab From 5c003458db40cf3c89aeddd22c6e934c28b5a565 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 2 Sep 2017 18:20:40 +0200 Subject: [PATCH 0032/2898] platform/x86: intel_cht_int33fe: Work around BIOS bug on some devices At least one BIOS enumerates the max17047 both through the INT33FE ACPI device (it is right there in the resources table) as well as through a separate MAX17047 device. This commit checks for the max17047 already being enumerated through a separate MAX17047 ACPI device and if so it uses the i2c-client instantiated for this and attaches the device-props for the max17047 to that i2c-client. Signed-off-by: Hans de Goede Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_cht_int33fe.c | 70 +++++++++++++++++++++--- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index da706e2c4232..94716b2fbc00 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c @@ -34,6 +34,42 @@ struct cht_int33fe_data { struct i2c_client *pi3usb30532; }; +/* + * Grrr I severly dislike buggy BIOS-es. At least one BIOS enumerates + * the max17047 both through the INT33FE ACPI device (it is right there + * in the resources table) as well as through a separate MAX17047 device. + * + * These helpers are used to work around this by checking if an i2c-client + * for the max17047 has already been registered. + */ +int cht_int33fe_check_for_max17047(struct device *dev, void *data) +{ + struct i2c_client **max17047 = data; + struct acpi_device *adev; + const char *hid; + + adev = ACPI_COMPANION(dev); + if (!adev) + return 0; + + hid = acpi_device_hid(adev); + + /* The MAX17047 ACPI node doesn't have an UID, so we don't check that */ + if (strcmp(hid, "MAX17047")) + return 0; + + *max17047 = to_i2c_client(dev); + return 1; +} + +struct i2c_client *cht_int33fe_find_max17047(void) +{ + struct i2c_client *max17047 = NULL; + + i2c_for_each_dev(&max17047, cht_int33fe_check_for_max17047); + return max17047; +} + static const char * const max17047_suppliers[] = { "bq24190-charger" }; static const struct property_entry max17047_props[] = { @@ -46,9 +82,11 @@ static int cht_int33fe_probe(struct i2c_client *client) struct device *dev = &client->dev; struct i2c_board_info board_info; struct cht_int33fe_data *data; + struct i2c_client *max17047; unsigned long long ptyp; acpi_status status; int fusb302_irq; + int ret; status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp); if (ACPI_FAILURE(status)) { @@ -75,13 +113,25 @@ static int cht_int33fe_probe(struct i2c_client *client) if (!data) return -ENOMEM; - memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "max17047", I2C_NAME_SIZE); - board_info.properties = max17047_props; - - data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); - if (!data->max17047) - return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ + /* Work around BIOS bug, see comment on cht_int33fe_find_max17047 */ + max17047 = cht_int33fe_find_max17047(); + if (max17047) { + /* Pre-existing i2c-client for the max17047, add device-props */ + ret = device_add_properties(&max17047->dev, max17047_props); + if (ret) + return ret; + /* And re-probe to get the new device-props applied. */ + ret = device_reprobe(&max17047->dev); + if (ret) + dev_warn(dev, "Reprobing max17047 error: %d\n", ret); + } else { + memset(&board_info, 0, sizeof(board_info)); + strlcpy(board_info.type, "max17047", I2C_NAME_SIZE); + board_info.properties = max17047_props; + data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); + if (!data->max17047) + return -EPROBE_DEFER; /* Wait for i2c-adapter to load */ + } memset(&board_info, 0, sizeof(board_info)); strlcpy(board_info.type, "fusb302", I2C_NAME_SIZE); @@ -106,7 +156,8 @@ static int cht_int33fe_probe(struct i2c_client *client) i2c_unregister_device(data->fusb302); out_unregister_max17047: - i2c_unregister_device(data->max17047); + if (data->max17047) + i2c_unregister_device(data->max17047); return -EPROBE_DEFER; /* Wait for the i2c-adapter to load */ } @@ -117,7 +168,8 @@ static int cht_int33fe_remove(struct i2c_client *i2c) i2c_unregister_device(data->pi3usb30532); i2c_unregister_device(data->fusb302); - i2c_unregister_device(data->max17047); + if (data->max17047) + i2c_unregister_device(data->max17047); return 0; } -- GitLab From 100f7fbe9c25bdac334039b389453f219a6819c5 Mon Sep 17 00:00:00 2001 From: Arun Nagendran Date: Fri, 15 Sep 2017 12:30:32 -0400 Subject: [PATCH 0033/2898] staging: mt29f_spinand: Enable the read ECC before program the page Current program_page function did following operation: 1. read page (with ECC OFF) 2. modify the page 3. write the page (with ECC ON) For some case(buggy flash Chip), while read the page without ECC ON, we may read the page with bit flip error and modify that bad page without knowing the bit flip error on that page. also we re-calculate the hash for bad page and write it. This could bring potential in-consistency problem with Flash data. Verify this logic with GIGA DEVICE Part(GD5F2GQ4RCFIG): we see this in-conststency problem wit Giga Device and fix on this patch resovle that issue. Signed-off-by: Arun Nagendran Signed-off-by: Boris Brezillon --- drivers/staging/mt29f_spinand/mt29f_spinand.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 13eaf16ecd16..87595c594b12 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -496,8 +496,12 @@ static int spinand_program_page(struct spi_device *spi_nand, if (!wbuf) return -ENOMEM; - enable_read_hw_ecc = 0; - spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf); + enable_read_hw_ecc = 1; + retval = spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf); + if (retval < 0) { + dev_err(&spi_nand->dev, "ecc error on read page!!!\n"); + return retval; + } for (i = offset, j = 0; i < len; i++, j++) wbuf[i] &= buf[j]; -- GitLab From ee0ae6a38d7acf0ec68ac8bb043a7e7cdbd002c8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:38 +0900 Subject: [PATCH 0034/2898] mtd: nand: denali: squash setup_ecc_for_xfer() helper into caller The setup_ecc_for_xfer() is only called from denali_data_xfer(). This helper is small enough, so squash it into the caller. This looks cleaner to me. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index aefdc83bdab0..d847ae48267d 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -208,24 +208,6 @@ static uint32_t denali_check_irq(struct denali_nand_info *denali) return irq_status; } -/* - * This helper function setups the registers for ECC and whether or not - * the spare area will be transferred. - */ -static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en, - bool transfer_spare) -{ - int ecc_en_flag, transfer_spare_flag; - - /* set ECC, transfer spare bits if needed */ - ecc_en_flag = ecc_en ? ECC_ENABLE__FLAG : 0; - transfer_spare_flag = transfer_spare ? TRANSFER_SPARE_REG__FLAG : 0; - - /* Enable spare area/ECC per user's request. */ - iowrite32(ecc_en_flag, denali->reg + ECC_ENABLE); - iowrite32(transfer_spare_flag, denali->reg + TRANSFER_SPARE_REG); -} - static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct denali_nand_info *denali = mtd_to_denali(mtd); @@ -659,7 +641,9 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, static int denali_data_xfer(struct denali_nand_info *denali, void *buf, size_t size, int page, int raw, int write) { - setup_ecc_for_xfer(denali, !raw, raw); + iowrite32(raw ? 0 : ECC_ENABLE__FLAG, denali->reg + ECC_ENABLE); + iowrite32(raw ? TRANSFER_SPARE_REG__FLAG : 0, + denali->reg + TRANSFER_SPARE_REG); if (denali->dma_avail) return denali_dma_xfer(denali, buf, size, page, raw, write); -- GitLab From 3ac6c7166396060c2b427668470e2e626c358a39 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:39 +0900 Subject: [PATCH 0035/2898] mtd: nand: denali: prefix detect_max_banks() with denali_ All functions in this driver are prefixed with denali_ except detect_max_banks(). Rename it for consistency. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index d847ae48267d..48193f946220 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -81,7 +81,7 @@ static void denali_host_write(struct denali_nand_info *denali, * Use the configuration feature register to determine the maximum number of * banks that the hardware supports. */ -static void detect_max_banks(struct denali_nand_info *denali) +static void denali_detect_max_banks(struct denali_nand_info *denali) { uint32_t features = ioread32(denali->reg + FEATURES); @@ -1115,7 +1115,7 @@ static void denali_hw_init(struct denali_nand_info *denali) * if this value is 0, just let it be. */ denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); - detect_max_banks(denali); + denali_detect_max_banks(denali); iowrite32(0x0F, denali->reg + RB_PIN_ENABLED); iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); -- GitLab From da4734be238341b873a94027fe24101b3e7c5c53 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:40 +0900 Subject: [PATCH 0036/2898] mtd: nand: denali: consolidate include directives Include necessary headers explicitly without relying on indirect header inclusion. Also, sort them alphabetically. , , turned out bogus, so removed. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 12 +++++++----- drivers/mtd/nand/denali.h | 3 +++ drivers/mtd/nand/denali_dt.c | 3 ++- drivers/mtd/nand/denali_pci.c | 3 +++ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 48193f946220..4daeb7fa9eec 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -16,14 +16,16 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * */ -#include -#include + +#include #include -#include -#include -#include +#include +#include #include +#include +#include #include +#include #include "denali.h" diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 9239e6793e6e..dc3f970feae5 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -21,7 +21,10 @@ #define __DENALI_H__ #include +#include #include +#include +#include #define DEVICE_RESET 0x0 #define DEVICE_RESET__BANK(bank) BIT(bank) diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index 56e2e177644d..01e0100ed2e7 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -12,15 +12,16 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ + #include #include #include #include #include #include -#include #include #include +#include #include "denali.h" diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c index 81370c79aa48..7d5600b6d07c 100644 --- a/drivers/mtd/nand/denali_pci.c +++ b/drivers/mtd/nand/denali_pci.c @@ -11,6 +11,9 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ + +#include +#include #include #include #include -- GitLab From 586a2c52909df453ed1b6239283744b0851ccf81 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:41 +0900 Subject: [PATCH 0037/2898] mtd: nand: denali: squash denali_enable_dma() helper into caller This helper just sets/clears a flag of DMA_ENABLE register (with register read-back, I do not know why it is necessary). Move the register write code to the caller, and remove the helper. It works for me without the register read-back. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 4daeb7fa9eec..e7b25de2e579 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -465,13 +465,6 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd, return max_bitflips; } -/* programs the controller to either enable/disable DMA transfers */ -static void denali_enable_dma(struct denali_nand_info *denali, bool en) -{ - iowrite32(en ? DMA_ENABLE__FLAG : 0, denali->reg + DMA_ENABLE); - ioread32(denali->reg + DMA_ENABLE); -} - static void denali_setup_dma64(struct denali_nand_info *denali, dma_addr_t dma_addr, int page, int write) { @@ -619,7 +612,7 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, ecc_err_mask = INTR__ECC_ERR; } - denali_enable_dma(denali, true); + iowrite32(DMA_ENABLE__FLAG, denali->reg + DMA_ENABLE); denali_reset_irq(denali); denali_setup_dma(denali, dma_addr, page, write); @@ -631,7 +624,8 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, else if (irq_status & ecc_err_mask) ret = -EBADMSG; - denali_enable_dma(denali, false); + iowrite32(0, denali->reg + DMA_ENABLE); + dma_unmap_single(denali->dev, dma_addr, size, dir); if (irq_status & INTR__ERASED_PAGE) -- GitLab From fdd4d0836bdb0dd6a4e7e588d7dce2de37f8531d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:42 +0900 Subject: [PATCH 0038/2898] mtd: nand: denali: slight clean up of denali_wait_for_irq() This function has a local variable "irq_mask" and its value is the same as denali->irq_mask. Clean up the code a little. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index e7b25de2e579..3cc56decbadb 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -191,7 +191,7 @@ static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, msecs_to_jiffies(1000)); if (!time_left) { dev_err(denali->dev, "timeout while waiting for irq 0x%x\n", - denali->irq_mask); + irq_mask); return 0; } -- GitLab From e0d53b3f8ed2b14dab54a04a4589fa72b0827fa5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:43 +0900 Subject: [PATCH 0039/2898] mtd: nand: denali: clean up macros with All the register offsets and bitfield masks are defined in denali.h, but the driver code ended up with additional crappy macros such as MAKE_ECC_CORRECTION(), ECC_SECTOR(), etc. The reason is apparent - accessing a register field requires mask and shift pair. The denali.h only provides mask. However, defining both is tedious. provides a convenient way to get register fields only with a single shifted mask. Now use it. While I am here, I shortened some macros. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 25 +++++++++++-------------- drivers/mtd/nand/denali.h | 13 +++++-------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 3cc56decbadb..1525c4e61c80 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -17,6 +17,7 @@ * */ +#include #include #include #include @@ -386,13 +387,6 @@ static int denali_hw_ecc_fixup(struct mtd_info *mtd, return max_bitflips; } -#define ECC_SECTOR(x) (((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12) -#define ECC_BYTE(x) (((x) & ECC_ERROR_ADDRESS__OFFSET)) -#define ECC_CORRECTION_VALUE(x) ((x) & ERR_CORRECTION_INFO__BYTEMASK) -#define ECC_ERROR_UNCORRECTABLE(x) ((x) & ERR_CORRECTION_INFO__ERROR_TYPE) -#define ECC_ERR_DEVICE(x) (((x) & ERR_CORRECTION_INFO__DEVICE_NR) >> 8) -#define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) - static int denali_sw_ecc_fixup(struct mtd_info *mtd, struct denali_nand_info *denali, unsigned long *uncor_ecc_flags, uint8_t *buf) @@ -410,18 +404,20 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd, do { err_addr = ioread32(denali->reg + ECC_ERROR_ADDRESS); - err_sector = ECC_SECTOR(err_addr); - err_byte = ECC_BYTE(err_addr); + err_sector = FIELD_GET(ECC_ERROR_ADDRESS__SECTOR, err_addr); + err_byte = FIELD_GET(ECC_ERROR_ADDRESS__OFFSET, err_addr); err_cor_info = ioread32(denali->reg + ERR_CORRECTION_INFO); - err_cor_value = ECC_CORRECTION_VALUE(err_cor_info); - err_device = ECC_ERR_DEVICE(err_cor_info); + err_cor_value = FIELD_GET(ERR_CORRECTION_INFO__BYTE, + err_cor_info); + err_device = FIELD_GET(ERR_CORRECTION_INFO__DEVICE, + err_cor_info); /* reset the bitflip counter when crossing ECC sector */ if (err_sector != prev_sector) bitflips = 0; - if (ECC_ERROR_UNCORRECTABLE(err_cor_info)) { + if (err_cor_info & ERR_CORRECTION_INFO__UNCOR) { /* * Check later if this is a real ECC error, or * an erased sector. @@ -451,7 +447,7 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd, } prev_sector = err_sector; - } while (!ECC_LAST_ERR(err_cor_info)); + } while (!(err_cor_info & ERR_CORRECTION_INFO__LAST_ERR)); /* * Once handle all ecc errors, controller will trigger a @@ -1351,7 +1347,8 @@ int denali_init(struct denali_nand_info *denali) "chosen ECC settings: step=%d, strength=%d, bytes=%d\n", chip->ecc.size, chip->ecc.strength, chip->ecc.bytes); - iowrite32(MAKE_ECC_CORRECTION(chip->ecc.strength, 1), + iowrite32(FIELD_PREP(ECC_CORRECTION__ERASE_THRESHOLD, 1) | + FIELD_PREP(ECC_CORRECTION__VALUE, chip->ecc.strength), denali->reg + ECC_CORRECTION); iowrite32(mtd->erasesize / mtd->writesize, denali->reg + PAGES_PER_BLOCK); diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index dc3f970feae5..73aad3ac4577 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -114,9 +114,6 @@ #define ECC_CORRECTION 0x1b0 #define ECC_CORRECTION__VALUE GENMASK(4, 0) #define ECC_CORRECTION__ERASE_THRESHOLD GENMASK(31, 16) -#define MAKE_ECC_CORRECTION(val, thresh) \ - (((val) & (ECC_CORRECTION__VALUE)) | \ - (((thresh) << 16) & (ECC_CORRECTION__ERASE_THRESHOLD))) #define READ_MODE 0x1c0 #define READ_MODE__VALUE GENMASK(3, 0) @@ -258,13 +255,13 @@ #define ECC_ERROR_ADDRESS 0x630 #define ECC_ERROR_ADDRESS__OFFSET GENMASK(11, 0) -#define ECC_ERROR_ADDRESS__SECTOR_NR GENMASK(15, 12) +#define ECC_ERROR_ADDRESS__SECTOR GENMASK(15, 12) #define ERR_CORRECTION_INFO 0x640 -#define ERR_CORRECTION_INFO__BYTEMASK GENMASK(7, 0) -#define ERR_CORRECTION_INFO__DEVICE_NR GENMASK(11, 8) -#define ERR_CORRECTION_INFO__ERROR_TYPE BIT(14) -#define ERR_CORRECTION_INFO__LAST_ERR_INFO BIT(15) +#define ERR_CORRECTION_INFO__BYTE GENMASK(7, 0) +#define ERR_CORRECTION_INFO__DEVICE GENMASK(11, 8) +#define ERR_CORRECTION_INFO__UNCOR BIT(14) +#define ERR_CORRECTION_INFO__LAST_ERR BIT(15) #define ECC_COR_INFO(bank) (0x650 + (bank) / 2 * 0x10) #define ECC_COR_INFO__SHIFT(bank) ((bank) % 2 * 8) -- GitLab From 8e4cbf7f0a55a235fdd8c088da1259b9fe8e9393 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:44 +0900 Subject: [PATCH 0040/2898] mtd: nand: denali: use more FIELD_PREP / FIELD_GET where appropriate In several places in this driver, the register fields are retrieved as follows: val = reg & FOO_MASK; Then, modified as follows: reg &= ~FOO_MASK; reg |= val; This code relies on its shift is 0, which we will never know until we check the definition of FOO_MASK. Use FIELD_PREP / FIELD_GET where appropriate. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 1525c4e61c80..ca98015b9e6d 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -88,7 +88,7 @@ static void denali_detect_max_banks(struct denali_nand_info *denali) { uint32_t features = ioread32(denali->reg + FEATURES); - denali->max_banks = 1 << (features & FEATURES__N_BANKS); + denali->max_banks = 1 << FIELD_GET(FEATURES__N_BANKS, features); /* the encoding changed from rev 5.0 to 5.1 */ if (denali->revision < 0x0501) @@ -374,7 +374,7 @@ static int denali_hw_ecc_fixup(struct mtd_info *mtd, return 0; } - max_bitflips = ecc_cor & ECC_COR_INFO__MAX_ERRORS; + max_bitflips = FIELD_GET(ECC_COR_INFO__MAX_ERRORS, ecc_cor); /* * The register holds the maximum of per-sector corrected bitflips. @@ -985,7 +985,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, tmp = ioread32(denali->reg + ACC_CLKS); tmp &= ~ACC_CLKS__VALUE; - tmp |= acc_clks; + tmp |= FIELD_PREP(ACC_CLKS__VALUE, acc_clks); iowrite32(tmp, denali->reg + ACC_CLKS); /* tRWH -> RE_2_WE */ @@ -994,7 +994,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, tmp = ioread32(denali->reg + RE_2_WE); tmp &= ~RE_2_WE__VALUE; - tmp |= re_2_we; + tmp |= FIELD_PREP(RE_2_WE__VALUE, re_2_we); iowrite32(tmp, denali->reg + RE_2_WE); /* tRHZ -> RE_2_RE */ @@ -1003,7 +1003,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, tmp = ioread32(denali->reg + RE_2_RE); tmp &= ~RE_2_RE__VALUE; - tmp |= re_2_re; + tmp |= FIELD_PREP(RE_2_RE__VALUE, re_2_re); iowrite32(tmp, denali->reg + RE_2_RE); /* tWHR -> WE_2_RE */ @@ -1012,7 +1012,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE); tmp &= ~TWHR2_AND_WE_2_RE__WE_2_RE; - tmp |= we_2_re; + tmp |= FIELD_PREP(TWHR2_AND_WE_2_RE__WE_2_RE, we_2_re); iowrite32(tmp, denali->reg + TWHR2_AND_WE_2_RE); /* tADL -> ADDR_2_DATA */ @@ -1026,8 +1026,8 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, addr_2_data = min_t(int, addr_2_data, addr_2_data_mask); tmp = ioread32(denali->reg + TCWAW_AND_ADDR_2_DATA); - tmp &= ~addr_2_data_mask; - tmp |= addr_2_data; + tmp &= ~TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA; + tmp |= FIELD_PREP(TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA, addr_2_data); iowrite32(tmp, denali->reg + TCWAW_AND_ADDR_2_DATA); /* tREH, tWH -> RDWR_EN_HI_CNT */ @@ -1037,7 +1037,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, tmp = ioread32(denali->reg + RDWR_EN_HI_CNT); tmp &= ~RDWR_EN_HI_CNT__VALUE; - tmp |= rdwr_en_hi; + tmp |= FIELD_PREP(RDWR_EN_HI_CNT__VALUE, rdwr_en_hi); iowrite32(tmp, denali->reg + RDWR_EN_HI_CNT); /* tRP, tWP -> RDWR_EN_LO_CNT */ @@ -1051,7 +1051,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, tmp = ioread32(denali->reg + RDWR_EN_LO_CNT); tmp &= ~RDWR_EN_LO_CNT__VALUE; - tmp |= rdwr_en_lo; + tmp |= FIELD_PREP(RDWR_EN_LO_CNT__VALUE, rdwr_en_lo); iowrite32(tmp, denali->reg + RDWR_EN_LO_CNT); /* tCS, tCEA -> CS_SETUP_CNT */ @@ -1062,7 +1062,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, tmp = ioread32(denali->reg + CS_SETUP_CNT); tmp &= ~CS_SETUP_CNT__VALUE; - tmp |= cs_setup; + tmp |= FIELD_PREP(CS_SETUP_CNT__VALUE, cs_setup); iowrite32(tmp, denali->reg + CS_SETUP_CNT); return 0; -- GitLab From 8582a03e028f666d15acc651e0491c02941d13e7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:45 +0900 Subject: [PATCH 0041/2898] mtd: nand: denali: clean up comments This driver explains too much about what is apparent from the code. Comments around basic APIs such as init_completion(), spin_lock_init(), etc. seem unneeded lessons to kernel developers. (With those comments dropped, denali_drv_init() is small enough, so it has been merged into the probe function.) Also, NAND driver developers should know the NAND init procedure, so there is no need to explain nand_scan_ident/tail. I removed FSF's address from the license blocks, and added simple comments to struct members. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 52 ++++------------------------------- drivers/mtd/nand/denali.h | 24 ++++++---------- drivers/mtd/nand/denali_dt.c | 1 - drivers/mtd/nand/denali_pci.c | 2 -- 4 files changed, 13 insertions(+), 66 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index ca98015b9e6d..02ce310f44e4 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -10,11 +10,6 @@ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * */ #include @@ -64,10 +59,6 @@ MODULE_LICENSE("GPL"); */ #define DENALI_CLK_X_MULT 6 -/* - * this macro allows us to convert from an MTD structure to our own - * device context (denali) structure. - */ static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) { return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand); @@ -450,9 +441,8 @@ static int denali_sw_ecc_fixup(struct mtd_info *mtd, } while (!(err_cor_info & ERR_CORRECTION_INFO__LAST_ERR)); /* - * Once handle all ecc errors, controller will trigger a - * ECC_TRANSACTION_DONE interrupt, so here just wait for - * a while for this interrupt + * Once handle all ECC errors, controller will trigger an + * ECC_TRANSACTION_DONE interrupt. */ irq_status = denali_wait_for_irq(denali, INTR__ECC_TRANSACTION_DONE); if (!(irq_status & INTR__ECC_TRANSACTION_DONE)) @@ -613,7 +603,6 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, denali_reset_irq(denali); denali_setup_dma(denali, dma_addr, page, write); - /* wait for operation to complete */ irq_status = denali_wait_for_irq(denali, irq_mask); if (!(irq_status & INTR__DMA_CMD_COMP)) ret = -EIO; @@ -1185,22 +1174,6 @@ static const struct mtd_ooblayout_ops denali_ooblayout_ops = { .free = denali_ooblayout_free, }; -/* initialize driver data structures */ -static void denali_drv_init(struct denali_nand_info *denali) -{ - /* - * the completion object will be used to notify - * the callee that the interrupt is done - */ - init_completion(&denali->complete); - - /* - * the spinlock will be used to synchronize the ISR with any - * element that might be access shared data (interrupt status) - */ - spin_lock_init(&denali->irq_lock); -} - static int denali_multidev_fixup(struct denali_nand_info *denali) { struct nand_chip *chip = &denali->nand; @@ -1260,11 +1233,12 @@ int denali_init(struct denali_nand_info *denali) mtd->dev.parent = denali->dev; denali_hw_init(denali); - denali_drv_init(denali); + + init_completion(&denali->complete); + spin_lock_init(&denali->irq_lock); denali_clear_irq_all(denali); - /* Request IRQ after all the hardware initialization is finished */ ret = devm_request_irq(denali->dev, denali->irq, denali_isr, IRQF_SHARED, DENALI_NAND_NAME, denali); if (ret) { @@ -1282,7 +1256,6 @@ int denali_init(struct denali_nand_info *denali) if (!mtd->name) mtd->name = "denali-nand"; - /* register the driver with the NAND core subsystem */ chip->select_chip = denali_select_chip; chip->read_byte = denali_read_byte; chip->write_byte = denali_write_byte; @@ -1295,11 +1268,6 @@ int denali_init(struct denali_nand_info *denali) if (denali->clk_x_rate) chip->setup_data_interface = denali_setup_data_interface; - /* - * scan for NAND devices attached to the controller - * this is the first stage in a two step process to register - * with the nand subsystem - */ ret = nand_scan_ident(mtd, denali->max_banks, NULL); if (ret) goto disable_irq; @@ -1323,18 +1291,9 @@ int denali_init(struct denali_nand_info *denali) chip->buf_align = 16; } - /* - * second stage of the NAND scan - * this stage requires information regarding ECC and - * bad block management. - */ - chip->bbt_options |= NAND_BBT_USE_FLASH; chip->bbt_options |= NAND_BBT_NO_OOB; - chip->ecc.mode = NAND_ECC_HW_SYNDROME; - - /* no subpage writes on denali */ chip->options |= NAND_NO_SUBPAGE_WRITE; ret = denali_ecc_setup(mtd, chip, denali); @@ -1418,7 +1377,6 @@ int denali_init(struct denali_nand_info *denali) } EXPORT_SYMBOL(denali_init); -/* driver exit point */ void denali_remove(struct denali_nand_info *denali) { struct mtd_info *mtd = nand_to_mtd(&denali->nand); diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 73aad3ac4577..f55ee10724c2 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -10,11 +10,6 @@ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * */ #ifndef __DENALI_H__ @@ -310,22 +305,19 @@ struct denali_nand_info { struct device *dev; void __iomem *reg; /* Register Interface */ void __iomem *host; /* Host Data/Command Interface */ - - /* elements used by ISR */ struct completion complete; - spinlock_t irq_lock; - uint32_t irq_mask; - uint32_t irq_status; + spinlock_t irq_lock; /* protect irq_mask and irq_status */ + u32 irq_mask; /* interrupts we are waiting for */ + u32 irq_status; /* interrupts that have happened */ int irq; - - void *buf; + void *buf; /* for syndrome layout conversion */ dma_addr_t dma_addr; - int dma_avail; + int dma_avail; /* can support DMA? */ int devs_per_cs; /* devices connected in parallel */ - int oob_skip_bytes; + int oob_skip_bytes; /* number of bytes reserved for BBM */ int max_banks; - unsigned int revision; - unsigned int caps; + unsigned int revision; /* IP revision */ + unsigned int caps; /* IP capability (or quirk) */ const struct nand_ecc_caps *ecc_caps; }; diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index 01e0100ed2e7..cfd33e6ca77f 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -156,7 +156,6 @@ static struct platform_driver denali_dt_driver = { .of_match_table = denali_nand_dt_ids, }, }; - module_platform_driver(denali_dt_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c index 7d5600b6d07c..57fb7ae31412 100644 --- a/drivers/mtd/nand/denali_pci.c +++ b/drivers/mtd/nand/denali_pci.c @@ -109,7 +109,6 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return ret; } -/* driver exit point */ static void denali_pci_remove(struct pci_dev *dev) { struct denali_nand_info *denali = pci_get_drvdata(dev); @@ -125,5 +124,4 @@ static struct pci_driver denali_pci_driver = { .probe = denali_pci_probe, .remove = denali_pci_remove, }; - module_pci_driver(denali_pci_driver); -- GitLab From 5f2baae00542b2203e6d0fa77890f64ff741aaf3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:46 +0900 Subject: [PATCH 0042/2898] mtd: nand: denali: use upper/lower_32_bits() macro for clean-up I used (uint64_t) cast to avoid "right shift count >= width of type" warning. provides nice helpers to cater to it. The code will be cleaner, and easier to understand. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 02ce310f44e4..e567ad9a4ef3 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -469,10 +469,10 @@ static void denali_setup_dma64(struct denali_nand_info *denali, 0x01002000 | (64 << 16) | (write << 8) | page_count); /* 2. set memory low address */ - denali_host_write(denali, mode, dma_addr); + denali_host_write(denali, mode, lower_32_bits(dma_addr)); /* 3. set memory high address */ - denali_host_write(denali, mode, (uint64_t)dma_addr >> 32); + denali_host_write(denali, mode, upper_32_bits(dma_addr)); } static void denali_setup_dma32(struct denali_nand_info *denali, -- GitLab From c70b5eb20a5dd9b3e4f68e041ad7526c94a2945e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:47 +0900 Subject: [PATCH 0043/2898] mtd: nand: denali: remove unneeded init of ECC_ENABLE register The ECC correction is properly enabled/disabled before the page read/write. There is no need to set up this at the beginning of the probe. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index e567ad9a4ef3..ee688e0042a8 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1101,8 +1101,6 @@ static void denali_hw_init(struct denali_nand_info *denali) iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); - - iowrite32(1, denali->reg + ECC_ENABLE); } int denali_calc_ecc_bytes(int step_size, int strength) -- GitLab From 29c4dd928735d5668b3108d350c30be7d0dc68fb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:48 +0900 Subject: [PATCH 0044/2898] mtd: nand: denali: support direct addressing mode The Denali NAND IP core decodes the lower 28 bits of the slave address to get the control information; bit[27:26]=mode, bit[25:24]=bank, etc. This means 256MB address range must be allocated for this IP. (Direct Addressing) For systems with address space limitation, the Denali IP provides an optional module that translates the addressing - address and data are latched by the registers in the translation module. (Indexed Addressing) The addressing mode can be selected when the delivered RTL is configured, and it can be read out from the FEATURES register. Most of SoC vendors would choose Indexed Addressing to save the address space, but Direct Addressing is possible as well, and it can be easily supported by adding ->host_{read,write} hooks. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 109 ++++++++++++++++++++++++-------------- drivers/mtd/nand/denali.h | 2 + 2 files changed, 70 insertions(+), 41 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index ee688e0042a8..7c24983012a1 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -29,9 +29,9 @@ MODULE_LICENSE("GPL"); #define DENALI_NAND_NAME "denali-nand" -/* Host Data/Command Interface */ -#define DENALI_HOST_ADDR 0x00 -#define DENALI_HOST_DATA 0x10 +/* for Indexed Addressing */ +#define DENALI_INDEXED_CTRL 0x00 +#define DENALI_INDEXED_DATA 0x10 #define DENALI_MAP00 (0 << 26) /* direct access to buffer */ #define DENALI_MAP01 (1 << 26) /* read/write pages in PIO */ @@ -64,11 +64,39 @@ static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand); } -static void denali_host_write(struct denali_nand_info *denali, - uint32_t addr, uint32_t data) +/* + * Direct Addressing - the slave address forms the control information (command + * type, bank, block, and page address). The slave data is the actual data to + * be transferred. This mode requires 28 bits of address region allocated. + */ +static u32 denali_direct_read(struct denali_nand_info *denali, u32 addr) +{ + return ioread32(denali->host + addr); +} + +static void denali_direct_write(struct denali_nand_info *denali, u32 addr, + u32 data) +{ + iowrite32(data, denali->host + addr); +} + +/* + * Indexed Addressing - address translation module intervenes in passing the + * control information. This mode reduces the required address range. The + * control information and transferred data are latched by the registers in + * the translation module. + */ +static u32 denali_indexed_read(struct denali_nand_info *denali, u32 addr) { - iowrite32(addr, denali->host + DENALI_HOST_ADDR); - iowrite32(data, denali->host + DENALI_HOST_DATA); + iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); + return ioread32(denali->host + DENALI_INDEXED_DATA); +} + +static void denali_indexed_write(struct denali_nand_info *denali, u32 addr, + u32 data) +{ + iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); + iowrite32(data, denali->host + DENALI_INDEXED_DATA); } /* @@ -205,52 +233,44 @@ static uint32_t denali_check_irq(struct denali_nand_info *denali) static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct denali_nand_info *denali = mtd_to_denali(mtd); + u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); int i; - iowrite32(DENALI_MAP11_DATA | DENALI_BANK(denali), - denali->host + DENALI_HOST_ADDR); - for (i = 0; i < len; i++) - buf[i] = ioread32(denali->host + DENALI_HOST_DATA); + buf[i] = denali->host_read(denali, addr); } static void denali_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { struct denali_nand_info *denali = mtd_to_denali(mtd); + u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); int i; - iowrite32(DENALI_MAP11_DATA | DENALI_BANK(denali), - denali->host + DENALI_HOST_ADDR); - for (i = 0; i < len; i++) - iowrite32(buf[i], denali->host + DENALI_HOST_DATA); + denali->host_write(denali, addr, buf[i]); } static void denali_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) { struct denali_nand_info *denali = mtd_to_denali(mtd); + u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); uint16_t *buf16 = (uint16_t *)buf; int i; - iowrite32(DENALI_MAP11_DATA | DENALI_BANK(denali), - denali->host + DENALI_HOST_ADDR); - for (i = 0; i < len / 2; i++) - buf16[i] = ioread32(denali->host + DENALI_HOST_DATA); + buf16[i] = denali->host_read(denali, addr); } static void denali_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) { struct denali_nand_info *denali = mtd_to_denali(mtd); + u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); const uint16_t *buf16 = (const uint16_t *)buf; int i; - iowrite32(DENALI_MAP11_DATA | DENALI_BANK(denali), - denali->host + DENALI_HOST_ADDR); - for (i = 0; i < len / 2; i++) - iowrite32(buf16[i], denali->host + DENALI_HOST_DATA); + denali->host_write(denali, addr, buf16[i]); } static uint8_t denali_read_byte(struct mtd_info *mtd) @@ -295,7 +315,7 @@ static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) if (ctrl & NAND_CTRL_CHANGE) denali_reset_irq(denali); - denali_host_write(denali, DENALI_BANK(denali) | type, dat); + denali->host_write(denali, DENALI_BANK(denali) | type, dat); } static int denali_dev_ready(struct mtd_info *mtd) @@ -465,14 +485,14 @@ static void denali_setup_dma64(struct denali_nand_info *denali, * 1. setup transfer type, interrupt when complete, * burst len = 64 bytes, the number of pages */ - denali_host_write(denali, mode, - 0x01002000 | (64 << 16) | (write << 8) | page_count); + denali->host_write(denali, mode, + 0x01002000 | (64 << 16) | (write << 8) | page_count); /* 2. set memory low address */ - denali_host_write(denali, mode, lower_32_bits(dma_addr)); + denali->host_write(denali, mode, lower_32_bits(dma_addr)); /* 3. set memory high address */ - denali_host_write(denali, mode, upper_32_bits(dma_addr)); + denali->host_write(denali, mode, upper_32_bits(dma_addr)); } static void denali_setup_dma32(struct denali_nand_info *denali, @@ -486,17 +506,17 @@ static void denali_setup_dma32(struct denali_nand_info *denali, /* DMA is a four step process */ /* 1. setup transfer type and # of pages */ - denali_host_write(denali, mode | page, - 0x2000 | (write << 8) | page_count); + denali->host_write(denali, mode | page, + 0x2000 | (write << 8) | page_count); /* 2. set memory high address bits 23:8 */ - denali_host_write(denali, mode | ((dma_addr >> 16) << 8), 0x2200); + denali->host_write(denali, mode | ((dma_addr >> 16) << 8), 0x2200); /* 3. set memory low address bits 23:8 */ - denali_host_write(denali, mode | ((dma_addr & 0xffff) << 8), 0x2300); + denali->host_write(denali, mode | ((dma_addr & 0xffff) << 8), 0x2300); /* 4. interrupt when complete, burst len = 64 bytes */ - denali_host_write(denali, mode | 0x14000, 0x2400); + denali->host_write(denali, mode | 0x14000, 0x2400); } static void denali_setup_dma(struct denali_nand_info *denali, @@ -511,7 +531,7 @@ static void denali_setup_dma(struct denali_nand_info *denali, static int denali_pio_read(struct denali_nand_info *denali, void *buf, size_t size, int page, int raw) { - uint32_t addr = DENALI_BANK(denali) | page; + u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; uint32_t *buf32 = (uint32_t *)buf; uint32_t irq_status, ecc_err_mask; int i; @@ -523,9 +543,8 @@ static int denali_pio_read(struct denali_nand_info *denali, void *buf, denali_reset_irq(denali); - iowrite32(DENALI_MAP01 | addr, denali->host + DENALI_HOST_ADDR); for (i = 0; i < size / 4; i++) - *buf32++ = ioread32(denali->host + DENALI_HOST_DATA); + *buf32++ = denali->host_read(denali, addr); irq_status = denali_wait_for_irq(denali, INTR__PAGE_XFER_INC); if (!(irq_status & INTR__PAGE_XFER_INC)) @@ -540,16 +559,15 @@ static int denali_pio_read(struct denali_nand_info *denali, void *buf, static int denali_pio_write(struct denali_nand_info *denali, const void *buf, size_t size, int page, int raw) { - uint32_t addr = DENALI_BANK(denali) | page; + u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; const uint32_t *buf32 = (uint32_t *)buf; uint32_t irq_status; int i; denali_reset_irq(denali); - iowrite32(DENALI_MAP01 | addr, denali->host + DENALI_HOST_ADDR); for (i = 0; i < size / 4; i++) - iowrite32(*buf32++, denali->host + DENALI_HOST_DATA); + denali->host_write(denali, addr, *buf32++); irq_status = denali_wait_for_irq(denali, INTR__PROGRAM_COMP | INTR__PROGRAM_FAIL); @@ -935,8 +953,8 @@ static int denali_erase(struct mtd_info *mtd, int page) denali_reset_irq(denali); - denali_host_write(denali, DENALI_MAP10 | DENALI_BANK(denali) | page, - DENALI_ERASE); + denali->host_write(denali, DENALI_MAP10 | DENALI_BANK(denali) | page, + DENALI_ERASE); /* wait for erase to complete or failure to occur */ irq_status = denali_wait_for_irq(denali, @@ -1227,6 +1245,7 @@ int denali_init(struct denali_nand_info *denali) { struct nand_chip *chip = &denali->nand; struct mtd_info *mtd = nand_to_mtd(chip); + u32 features = ioread32(denali->reg + FEATURES); int ret; mtd->dev.parent = denali->dev; @@ -1262,6 +1281,14 @@ int denali_init(struct denali_nand_info *denali) chip->dev_ready = denali_dev_ready; chip->waitfunc = denali_waitfunc; + if (features & FEATURES__INDEX_ADDR) { + denali->host_read = denali_indexed_read; + denali->host_write = denali_indexed_write; + } else { + denali->host_read = denali_direct_read; + denali->host_write = denali_direct_write; + } + /* clk rate info is needed for setup_data_interface */ if (denali->clk_x_rate) chip->setup_data_interface = denali_setup_data_interface; diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index f55ee10724c2..3aeb272d7a07 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -319,6 +319,8 @@ struct denali_nand_info { unsigned int revision; /* IP revision */ unsigned int caps; /* IP capability (or quirk) */ const struct nand_ecc_caps *ecc_caps; + u32 (*host_read)(struct denali_nand_info *denali, u32 addr); + void (*host_write)(struct denali_nand_info *denali, u32 addr, u32 data); }; #define DENALI_CAP_HW_ECC_FIXUP BIT(0) -- GitLab From 89dcb27b09fdcc8b585791815be07413d0487102 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 12:46:49 +0900 Subject: [PATCH 0045/2898] mtd: nand: denali: change the setup_dma choice into hook The previous commit added some hooks into struct denali_nand_info, so here is one more for clean-up. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 15 +++++---------- drivers/mtd/nand/denali.h | 2 ++ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 7c24983012a1..0b268ec88435 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -519,15 +519,6 @@ static void denali_setup_dma32(struct denali_nand_info *denali, denali->host_write(denali, mode | 0x14000, 0x2400); } -static void denali_setup_dma(struct denali_nand_info *denali, - dma_addr_t dma_addr, int page, int write) -{ - if (denali->caps & DENALI_CAP_DMA_64BIT) - denali_setup_dma64(denali, dma_addr, page, write); - else - denali_setup_dma32(denali, dma_addr, page, write); -} - static int denali_pio_read(struct denali_nand_info *denali, void *buf, size_t size, int page, int raw) { @@ -619,7 +610,7 @@ static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, iowrite32(DMA_ENABLE__FLAG, denali->reg + DMA_ENABLE); denali_reset_irq(denali); - denali_setup_dma(denali, dma_addr, page, write); + denali->setup_dma(denali, dma_addr, page, write); irq_status = denali_wait_for_irq(denali, irq_mask); if (!(irq_status & INTR__DMA_CMD_COMP)) @@ -1314,6 +1305,10 @@ int denali_init(struct denali_nand_info *denali) if (denali->dma_avail) { chip->options |= NAND_USE_BOUNCE_BUFFER; chip->buf_align = 16; + if (denali->caps & DENALI_CAP_DMA_64BIT) + denali->setup_dma = denali_setup_dma64; + else + denali->setup_dma = denali_setup_dma32; } chip->bbt_options |= NAND_BBT_USE_FLASH; diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index 3aeb272d7a07..2911066dacac 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -321,6 +321,8 @@ struct denali_nand_info { const struct nand_ecc_caps *ecc_caps; u32 (*host_read)(struct denali_nand_info *denali, u32 addr); void (*host_write)(struct denali_nand_info *denali, u32 addr, u32 data); + void (*setup_dma)(struct denali_nand_info *denali, dma_addr_t dma_addr, + int page, int write); }; #define DENALI_CAP_HW_ECC_FIXUP BIT(0) -- GitLab From e8901f3ab5b5c2ce75abdcd182b07d00fd6746fe Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 14:58:23 +0900 Subject: [PATCH 0046/2898] dt-bindings: nand: denali: reduce the register space in the example This example allocates much more than needed for address regions. As for "denali_reg", as you see in drivers/mtd/nand/denali.h, all registers fit in 0x1000. As for "nand_data", this IP is generally configured to use Indexed Addressing mode, where there are only two registers in the address translation module (CTRL: 0x00, DATA: 0x10). Altera SOCFPGA is also this case. So, 0x20 is enough. Signed-off-by: Masahiro Yamada Acked-by: Rob Herring Signed-off-by: Boris Brezillon --- Documentation/devicetree/bindings/mtd/denali-nand.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt index 504291d2e5c2..0ee8edb60efc 100644 --- a/Documentation/devicetree/bindings/mtd/denali-nand.txt +++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt @@ -29,7 +29,7 @@ nand: nand@ff900000 { #address-cells = <1>; #size-cells = <1>; compatible = "altr,socfpga-denali-nand"; - reg = <0xff900000 0x100000>, <0xffb80000 0x10000>; + reg = <0xff900000 0x20>, <0xffb80000 0x1000>; reg-names = "nand_data", "denali_reg"; interrupts = <0 144 4>; }; -- GitLab From ae11c5b2c2dfe8768b51f73f491869ba2cd9d4f9 Mon Sep 17 00:00:00 2001 From: Allen Pais Date: Wed, 13 Sep 2017 16:29:31 +0530 Subject: [PATCH 0047/2898] platform/x86: intel_telemetry_debugfs: Use standard ARRAY_SIZE() macro Use the standard ARRAY_SIZE() macro instead of the custom TELEM_EVT_LEN(). Signed-off-by: Allen Pais Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/intel_telemetry_debugfs.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c index d4fc42b4cbeb..74e518dd237c 100644 --- a/drivers/platform/x86/intel_telemetry_debugfs.c +++ b/drivers/platform/x86/intel_telemetry_debugfs.c @@ -76,8 +76,6 @@ #define TELEM_IOSS_DX_D0IX_EVTS 25 #define TELEM_IOSS_PG_EVTS 30 -#define TELEM_EVT_LEN(x) (sizeof(x)/sizeof((x)[0])) - #define TELEM_DEBUGFS_CPU(model, data) \ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&data} @@ -304,13 +302,13 @@ static struct telemetry_debugfs_conf telem_apl_debugfs_conf = { .ioss_d0ix_data = telem_apl_ioss_d0ix_data, .ioss_pg_data = telem_apl_ioss_pg_data, - .pss_idle_evts = TELEM_EVT_LEN(telem_apl_pss_idle_data), - .pcs_idle_blkd_evts = TELEM_EVT_LEN(telem_apl_pcs_idle_blkd_data), - .pcs_s0ix_blkd_evts = TELEM_EVT_LEN(telem_apl_pcs_s0ix_blkd_data), - .pss_ltr_evts = TELEM_EVT_LEN(telem_apl_pss_ltr_data), - .pss_wakeup_evts = TELEM_EVT_LEN(telem_apl_pss_wakeup), - .ioss_d0ix_evts = TELEM_EVT_LEN(telem_apl_ioss_d0ix_data), - .ioss_pg_evts = TELEM_EVT_LEN(telem_apl_ioss_pg_data), + .pss_idle_evts = ARRAY_SIZE(telem_apl_pss_idle_data), + .pcs_idle_blkd_evts = ARRAY_SIZE(telem_apl_pcs_idle_blkd_data), + .pcs_s0ix_blkd_evts = ARRAY_SIZE(telem_apl_pcs_s0ix_blkd_data), + .pss_ltr_evts = ARRAY_SIZE(telem_apl_pss_ltr_data), + .pss_wakeup_evts = ARRAY_SIZE(telem_apl_pss_wakeup), + .ioss_d0ix_evts = ARRAY_SIZE(telem_apl_ioss_d0ix_data), + .ioss_pg_evts = ARRAY_SIZE(telem_apl_ioss_pg_data), .pstates_id = TELEM_APL_PSS_PSTATES_ID, .pss_idle_id = TELEM_APL_PSS_IDLE_ID, -- GitLab From 12933ea2b8c1e1f87a5dfece947325ee9e6d65b0 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 14 Sep 2017 01:41:55 -0500 Subject: [PATCH 0048/2898] platform/x86: intel-wmi-thunderbolt: Silence error cases These were raised by Lukas Wunner as potential DOS attacks against the system log by passing bad data to sysfs. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/intel-wmi-thunderbolt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/intel-wmi-thunderbolt.c b/drivers/platform/x86/intel-wmi-thunderbolt.c index 32fb6cc33d72..c2257bd06f18 100644 --- a/drivers/platform/x86/intel-wmi-thunderbolt.c +++ b/drivers/platform/x86/intel-wmi-thunderbolt.c @@ -41,13 +41,10 @@ static ssize_t force_power_store(struct device *dev, if (mode == 0 || mode == 1) { status = wmi_evaluate_method(INTEL_WMI_THUNDERBOLT_GUID, 0, 1, &input, NULL); - if (ACPI_FAILURE(status)) { - pr_err("intel-wmi-thunderbolt: failed setting %s\n", - buf); + if (ACPI_FAILURE(status)) return -ENODEV; - } } else { - pr_err("intel-wmi-thunderbolt: unsupported mode: %d", mode); + return -EINVAL; } return count; } -- GitLab From 821b85366284542e00dd834062144c637e818ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20de=20Bretagne?= Date: Mon, 18 Sep 2017 00:57:12 +0200 Subject: [PATCH 0049/2898] platform/x86: intel-hid: Power button suspend on Dell Latitude 7275 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Dell Latitude 7275 the 5-button array is not exposed in the ACPI tables, but notififies are still sent to the Intel HID device object (device ID INT33D5) in response to power button actions. They were ignored as the intel-hid driver was not prepared to take care of them until recently. Power button wakeup from suspend-to-idle was added in: commit 635173a17b03 ("intel-hid: Wake up Dell Latitude 7275 from suspend-to-idle") However power button suspend doesn't work yet on this platform so it would be good to add it also. On the affected platform (for which priv->array is NULL), add a new upfront check against the power button press notification (0xCE) to notify_handler(), outside the wakeup mode this time, which allows reporting the power button press event and triggers the suspend. Also catch and ignore the corresponding power button release notification (0xCF) to stop it from being reported as an "unknown event" in the logs. Link: https://bugzilla.kernel.org/show_bug.cgi?id=196115 Tested-by: Jérôme de Bretagne Signed-off-by: Jérôme de Bretagne Acked-By: Mario Limonciello [dvhart: minor coding style and commit message format fix] Signed-off-by: Darren Hart (VMware) Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/intel-hid.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index e34fd70b67af..f470279c4c10 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -226,6 +226,24 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) return; } + /* + * Needed for suspend to work on some platforms that don't expose + * the 5-button array, but still send notifies with power button + * event code to this device object on power button actions. + * + * Report the power button press; catch and ignore the button release. + */ + if (!priv->array) { + if (event == 0xce) { + input_report_key(priv->input_dev, KEY_POWER, 1); + input_sync(priv->input_dev); + return; + } + + if (event == 0xcf) + return; + } + /* 0xC0 is for HID events, other values are for 5 button array */ if (event != 0xc0) { if (!priv->array || -- GitLab From 6ed2288ca93479f801f49daf9b6d674701f4c28e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 30 Jan 2017 22:28:31 -0500 Subject: [PATCH 0050/2898] vchiq_2835_arm: switch to get_user_pages_fast() Signed-off-by: Al Viro --- .../interface/vchiq_arm/vchiq_2835_arm.c | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 0159ca4407d8..cd2b19f335d8 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -92,8 +92,7 @@ static irqreturn_t vchiq_doorbell_irq(int irq, void *dev_id); static struct vchiq_pagelist_info * -create_pagelist(char __user *buf, size_t count, unsigned short type, - struct task_struct *task); +create_pagelist(char __user *buf, size_t count, unsigned short type); static void free_pagelist(struct vchiq_pagelist_info *pagelistinfo, @@ -251,8 +250,7 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, pagelistinfo = create_pagelist((char __user *)offset, size, (dir == VCHIQ_BULK_RECEIVE) ? PAGELIST_READ - : PAGELIST_WRITE, - current); + : PAGELIST_WRITE); if (!pagelistinfo) return VCHIQ_ERROR; @@ -391,8 +389,7 @@ cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo) */ static struct vchiq_pagelist_info * -create_pagelist(char __user *buf, size_t count, unsigned short type, - struct task_struct *task) +create_pagelist(char __user *buf, size_t count, unsigned short type) { PAGELIST_T *pagelist; struct vchiq_pagelist_info *pagelistinfo; @@ -472,14 +469,11 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, } /* do not try and release vmalloc pages */ } else { - down_read(&task->mm->mmap_sem); - actual_pages = get_user_pages( - (unsigned long)buf & PAGE_MASK, + actual_pages = get_user_pages_fast( + (unsigned long)buf & PAGE_MASK, num_pages, - (type == PAGELIST_READ) ? FOLL_WRITE : 0, - pages, - NULL /*vmas */); - up_read(&task->mm->mmap_sem); + type == PAGELIST_READ, + pages); if (actual_pages != num_pages) { vchiq_log_info(vchiq_arm_log_level, -- GitLab From 0ca36a6bbd85bad72596a15e1505483352333c88 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 29 Jan 2017 03:12:00 -0500 Subject: [PATCH 0051/2898] rapidio: switch to get_user_pages_fast() Signed-off-by: Al Viro --- drivers/rapidio/devices/rio_mport_cdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index 5beb0c361076..cf8e4ec2fd48 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -889,11 +889,9 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode, goto err_req; } - pinned = get_user_pages_unlocked( + pinned = get_user_pages_fast( (unsigned long)xfer->loc_addr & PAGE_MASK, - nr_pages, - page_list, - dir == DMA_FROM_DEVICE ? FOLL_WRITE : 0); + nr_pages, dir == DMA_FROM_DEVICE, page_list); if (pinned != nr_pages) { if (pinned < 0) { -- GitLab From 1aaa09caedc1d999fb324b4b77a88167bdfc531a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 30 Jan 2017 02:45:08 -0500 Subject: [PATCH 0052/2898] fsl_hypervisor: switch to get_user_pages_fast() Signed-off-by: Al Viro --- drivers/virt/fsl_hypervisor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c index d993df5586c0..d70ad6d38879 100644 --- a/drivers/virt/fsl_hypervisor.c +++ b/drivers/virt/fsl_hypervisor.c @@ -243,8 +243,8 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p) sg_list = PTR_ALIGN(sg_list_unaligned, sizeof(struct fh_sg_list)); /* Get the physical addresses of the source buffer */ - num_pinned = get_user_pages_unlocked(param.local_vaddr - lb_offset, - num_pages, pages, (param.source == -1) ? 0 : FOLL_WRITE); + num_pinned = get_user_pages_fast(param.local_vaddr - lb_offset, + num_pages, param.source != -1, pages); if (num_pinned != num_pages) { /* get_user_pages() failed */ -- GitLab From a6e0d12fc6fa6e48b51858f4ef1c0469f8036985 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 22 Sep 2017 18:16:11 -0400 Subject: [PATCH 0053/2898] via_dmablit(): use get_user_pages_fast() Signed-off-by: Al Viro --- drivers/gpu/drm/via/via_dmablit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c index 98aae9809249..32c9938e1e1e 100644 --- a/drivers/gpu/drm/via/via_dmablit.c +++ b/drivers/gpu/drm/via/via_dmablit.c @@ -238,9 +238,9 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) vsg->pages = vzalloc(sizeof(struct page *) * vsg->num_pages); if (NULL == vsg->pages) return -ENOMEM; - ret = get_user_pages_unlocked((unsigned long)xfer->mem_addr, - vsg->num_pages, vsg->pages, - (vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0); + ret = get_user_pages_fast((unsigned long)xfer->mem_addr, + vsg->num_pages, vsg->direction == DMA_FROM_DEVICE, + vsg->pages); if (ret != vsg->num_pages) { if (ret < 0) return ret; -- GitLab From 43bfe7bc3c2817f42548f650e82aa506d605c0a3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 22 Sep 2017 18:18:55 -0400 Subject: [PATCH 0054/2898] st: use get_user_pages_fast() Signed-off-by: Al Viro --- drivers/scsi/st.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 94e402ed30f6..b141d7641a2e 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4920,11 +4920,7 @@ static int sgl_map_user_pages(struct st_buffer *STbp, /* Try to fault in all of the necessary pages */ /* rw==READ means read from drive, write into memory area */ - res = get_user_pages_unlocked( - uaddr, - nr_pages, - pages, - rw == READ ? FOLL_WRITE : 0); /* don't force */ + res = get_user_pages_fast(uaddr, nr_pages, rw == READ, pages); /* Errors and no page mapped should return here */ if (res < nr_pages) -- GitLab From e1a58a5421c6a9f4ab74810d6ecbbdb6b1b2e2c7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 22 Sep 2017 18:21:11 -0400 Subject: [PATCH 0055/2898] atomisp: use get_user_pages_fast() Signed-off-by: Al Viro --- drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c b/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c index 11162f595fc7..2052f8d2f137 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c +++ b/drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c @@ -1029,10 +1029,8 @@ static int alloc_user_pages(struct hmm_buffer_object *bo, } else { /*Handle frame buffer allocated in user space*/ mutex_unlock(&bo->mutex); - down_read(¤t->mm->mmap_sem); - page_nr = get_user_pages((unsigned long)userptr, - (int)(bo->pgnr), 1, pages, NULL); - up_read(¤t->mm->mmap_sem); + page_nr = get_user_pages_fast((unsigned long)userptr, + (int)(bo->pgnr), 1, pages); mutex_lock(&bo->mutex); bo->mem_type = HMM_BO_MEM_TYPE_USER; } -- GitLab From 8dcf932d541487307fc7388ebfad5955f5fae098 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 22 Sep 2017 18:22:05 -0400 Subject: [PATCH 0056/2898] pvr2fs: use get_user_pages_fast() Signed-off-by: Al Viro --- drivers/video/fbdev/pvr2fb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c index 867c5218968f..a582d3ae7ac1 100644 --- a/drivers/video/fbdev/pvr2fb.c +++ b/drivers/video/fbdev/pvr2fb.c @@ -686,9 +686,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, if (!pages) return -ENOMEM; - ret = get_user_pages_unlocked((unsigned long)buf, nr_pages, pages, - FOLL_WRITE); - + ret = get_user_pages_fast((unsigned long)buf, nr_pages, true, pages); if (ret < nr_pages) { nr_pages = ret; ret = -EINVAL; -- GitLab From 77478715ba9242017976fd01de189e77fa072f51 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 22 Sep 2017 18:23:17 -0400 Subject: [PATCH 0057/2898] ceph: use get_user_pages_fast() Signed-off-by: Al Viro --- net/ceph/pagevec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index 1a7c9a79a53c..4098b17d0812 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c @@ -24,9 +24,9 @@ struct page **ceph_get_direct_page_vector(const void __user *data, return ERR_PTR(-ENOMEM); while (got < num_pages) { - rc = get_user_pages_unlocked( + rc = get_user_pages_fast( (unsigned long)data + ((unsigned long)got * PAGE_SIZE), - num_pages - got, pages + got, write_page ? FOLL_WRITE : 0); + num_pages - got, write_page, pages + got); if (rc < 0) break; BUG_ON(rc == 0); -- GitLab From 5da672cff03d3ffa36476e91943af50e3151db2a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 26 Sep 2017 10:36:20 +0800 Subject: [PATCH 0058/2898] clk: sunxi-ng: Implement reset control status readback Until now we were not providing a way to read back the status of our reset controls. Consumers had no real way to be certain whether a peripheral was held in reset or not. Implement the status callback to complete the API support. Fixes: 1d80c14248d6 ("clk: sunxi-ng: Add common infrastructure") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu_reset.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c index 1dc4e98ea802..b67149143554 100644 --- a/drivers/clk/sunxi-ng/ccu_reset.c +++ b/drivers/clk/sunxi-ng/ccu_reset.c @@ -60,8 +60,22 @@ static int ccu_reset_reset(struct reset_controller_dev *rcdev, return 0; } +static int ccu_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev); + const struct ccu_reset_map *map = &ccu->reset_map[id]; + + /* + * The reset control API expects 0 if reset is not asserted, + * which is the opposite of what our hardware uses. + */ + return !(map->bit & readl(ccu->base + map->reg)); +} + const struct reset_control_ops ccu_reset_ops = { .assert = ccu_reset_assert, .deassert = ccu_reset_deassert, .reset = ccu_reset_reset, + .status = ccu_reset_status, }; -- GitLab From 033c006e5fe08233014d449715171f07e68a4a3a Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Tue, 26 Sep 2017 09:14:05 +0200 Subject: [PATCH 0059/2898] nfs_common: fix build warning in grace.c This fix the following warning fs/nfs_common/grace.c:66:1: warning: no previous prototype for function '__state_in_grace' [-Wmissing-prototypes] by adding the missing static. Signed-off-by: Corentin Labbe Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/nfs_common/grace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs_common/grace.c b/fs/nfs_common/grace.c index 420d3a0ab258..519396967e79 100644 --- a/fs/nfs_common/grace.c +++ b/fs/nfs_common/grace.c @@ -62,7 +62,7 @@ EXPORT_SYMBOL_GPL(locks_end_grace); * to answer ordinary lock requests, and when they should accept only * lock reclaims. */ -int +static int __state_in_grace(struct net *net, bool open) { struct list_head *grace_list = net_generic(net, grace_net_id); -- GitLab From 809d4fcf9dd593af6d11ab1e6f0efc9fcfefb682 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Tue, 26 Sep 2017 09:14:06 +0200 Subject: [PATCH 0060/2898] nfs_common: move locks_in_grace comment at the right place Commit c87fb4a378f9 ("lockd: NLM grace period shouldn't block NFSv4 opens") made the locks_in_grace() comment be in the wrong place. This patch move this comment just at the right place. Signed-off-by: Corentin Labbe Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/nfs_common/grace.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/nfs_common/grace.c b/fs/nfs_common/grace.c index 519396967e79..c030cd618b99 100644 --- a/fs/nfs_common/grace.c +++ b/fs/nfs_common/grace.c @@ -55,13 +55,6 @@ locks_end_grace(struct lock_manager *lm) } EXPORT_SYMBOL_GPL(locks_end_grace); -/** - * locks_in_grace - * - * Lock managers call this function to determine when it is OK for them - * to answer ordinary lock requests, and when they should accept only - * lock reclaims. - */ static int __state_in_grace(struct net *net, bool open) { @@ -78,6 +71,13 @@ __state_in_grace(struct net *net, bool open) return false; } +/** + * locks_in_grace + * + * Lock managers call this function to determine when it is OK for them + * to answer ordinary lock requests, and when they should accept only + * lock reclaims. + */ int locks_in_grace(struct net *net) { return __state_in_grace(net, 0); -- GitLab From 003278e431bffa4070d18c821eff1d95867f24db Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Tue, 26 Sep 2017 09:14:07 +0200 Subject: [PATCH 0061/2898] nfs_common: convert int to bool Since __state_in_grace return only true/false, make it return bool instead of int. Same change for the two user of it, locks_in_grace/opens_in_grace Signed-off-by: Corentin Labbe Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/nfs_common/grace.c | 10 +++++----- include/linux/fs.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/nfs_common/grace.c b/fs/nfs_common/grace.c index c030cd618b99..897b299db55e 100644 --- a/fs/nfs_common/grace.c +++ b/fs/nfs_common/grace.c @@ -55,7 +55,7 @@ locks_end_grace(struct lock_manager *lm) } EXPORT_SYMBOL_GPL(locks_end_grace); -static int +static bool __state_in_grace(struct net *net, bool open) { struct list_head *grace_list = net_generic(net, grace_net_id); @@ -78,15 +78,15 @@ __state_in_grace(struct net *net, bool open) * to answer ordinary lock requests, and when they should accept only * lock reclaims. */ -int locks_in_grace(struct net *net) +bool locks_in_grace(struct net *net) { - return __state_in_grace(net, 0); + return __state_in_grace(net, false); } EXPORT_SYMBOL_GPL(locks_in_grace); -int opens_in_grace(struct net *net) +bool opens_in_grace(struct net *net) { - return __state_in_grace(net, 1); + return __state_in_grace(net, true); } EXPORT_SYMBOL_GPL(opens_in_grace); diff --git a/include/linux/fs.h b/include/linux/fs.h index 339e73742e73..8cc0493c7c39 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -970,8 +970,8 @@ struct lock_manager { struct net; void locks_start_grace(struct net *, struct lock_manager *); void locks_end_grace(struct lock_manager *); -int locks_in_grace(struct net *); -int opens_in_grace(struct net *); +bool locks_in_grace(struct net *); +bool opens_in_grace(struct net *); /* that will die - we need it for nfs_lock_info */ #include -- GitLab From 45b611c896faf29e235d9de6c7a8ceb3393c2b9c Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 15 Sep 2017 04:00:02 +0200 Subject: [PATCH 0062/2898] rtc: rv3029: fix vendor string The vendor string for Microcrystal is microcrystal. Acked-by: Rob Herring Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/trivial-devices.txt | 2 +- drivers/rtc/rtc-rv3029c2.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/trivial-devices.txt b/Documentation/devicetree/bindings/trivial-devices.txt index af284fbd4d23..aae37352c574 100644 --- a/Documentation/devicetree/bindings/trivial-devices.txt +++ b/Documentation/devicetree/bindings/trivial-devices.txt @@ -72,7 +72,6 @@ isil,isl29030 Intersil ISL29030 Ambient Light and Proximity Sensor maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface -mc,rv3029c2 Real Time Clock Module with I2C-Bus mcube,mc3230 mCube 3-axis 8-bit digital accelerometer memsic,mxc6225 MEMSIC 2-axis 8-bit digital accelerometer microchip,mcp4531-502 Microchip 7-bit Single I2C Digital Potentiometer (5k) @@ -141,6 +140,7 @@ microchip,mcp4662-503 Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem microchip,mcp4662-104 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k) microchip,tc654 PWM Fan Speed Controller With Fan Fault Detection microchip,tc655 PWM Fan Speed Controller With Fan Fault Detection +microcrystal,rv3029 Real Time Clock Module with I2C-Bus miramems,da226 MiraMEMS DA226 2-axis 14-bit digital accelerometer miramems,da280 MiraMEMS DA280 3-axis 14-bit digital accelerometer miramems,da311 MiraMEMS DA311 3-axis 12-bit digital accelerometer diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index aa09771de04f..cfe3aece51d1 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -876,6 +876,8 @@ static const struct i2c_device_id rv3029_id[] = { MODULE_DEVICE_TABLE(i2c, rv3029_id); static const struct of_device_id rv3029_of_match[] = { + { .compatible = "microcrystal,rv3029" }, + /* Backward compatibility only, do not use compatibles below: */ { .compatible = "rv3029" }, { .compatible = "rv3029c2" }, { .compatible = "mc,rv3029c2" }, -- GitLab From 9c5b2b0d409304c2e3c1f4d1c9bb4958e1d46f8f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 13 Sep 2017 10:03:31 -0400 Subject: [PATCH 0063/2898] drm/amdgpu: Pulling old prepare and submit for flip back This is needed to ensure every single DC commit builds. Reverting this again when it's no longer needed by DC. This reverts commit 98da65d5e32583d89a1b1c760293b601816a98d3. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 138 ++++++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 15 +++ 2 files changed, 124 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 6ad243293a78..e23b89cc6636 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -138,11 +138,52 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) kfree(work); } -int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, uint32_t target, - struct drm_modeset_acquire_ctx *ctx) + +static void amdgpu_flip_work_cleanup(struct amdgpu_flip_work *work) +{ + int i; + + amdgpu_bo_unref(&work->old_abo); + dma_fence_put(work->excl); + for (i = 0; i < work->shared_count; ++i) + dma_fence_put(work->shared[i]); + kfree(work->shared); + kfree(work); +} + +static void amdgpu_flip_cleanup_unreserve(struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo) +{ + amdgpu_bo_unreserve(new_abo); + amdgpu_flip_work_cleanup(work); +} + +static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo) +{ + if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) + DRM_ERROR("failed to unpin new abo in error path\n"); + amdgpu_flip_cleanup_unreserve(work, new_abo); +} + +void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo) +{ + if (unlikely(amdgpu_bo_reserve(new_abo, true) != 0)) { + DRM_ERROR("failed to reserve new abo in error path\n"); + amdgpu_flip_work_cleanup(work); + return; + } + amdgpu_flip_cleanup_unpin(work, new_abo); +} + +int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, + uint32_t target, + struct amdgpu_flip_work **work_p, + struct amdgpu_bo **new_abo_p) { struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; @@ -155,7 +196,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, unsigned long flags; u64 tiling_flags; u64 base; - int i, r; + int r; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) @@ -216,41 +257,80 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); r = -EBUSY; goto pflip_cleanup; + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + *work_p = work; + *new_abo_p = new_abo; + + return 0; + +pflip_cleanup: + amdgpu_crtc_cleanup_flip_ctx(work, new_abo); + return r; + +unpin: + amdgpu_flip_cleanup_unpin(work, new_abo); + return r; + +unreserve: + amdgpu_flip_cleanup_unreserve(work, new_abo); + return r; +cleanup: + amdgpu_flip_work_cleanup(work); + return r; + +} + +void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo) +{ + unsigned long flags; + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + spin_lock_irqsave(&crtc->dev->event_lock, flags); amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING; amdgpu_crtc->pflip_works = work; - - DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", - amdgpu_crtc->crtc_id, amdgpu_crtc, work); /* update crtc fb */ crtc->primary->fb = fb; spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + DRM_DEBUG_DRIVER( + "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", + amdgpu_crtc->crtc_id, amdgpu_crtc, work); + amdgpu_flip_work_func(&work->flip_work.work); - return 0; +} -pflip_cleanup: - if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) { - DRM_ERROR("failed to reserve new abo in error path\n"); - goto cleanup; - } -unpin: - if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) { - DRM_ERROR("failed to unpin new abo in error path\n"); - } -unreserve: - amdgpu_bo_unreserve(new_abo); +int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, + uint32_t target, + struct drm_modeset_acquire_ctx *ctx) +{ + struct amdgpu_bo *new_abo; + struct amdgpu_flip_work *work; + int r; -cleanup: - amdgpu_bo_unref(&work->old_abo); - dma_fence_put(work->excl); - for (i = 0; i < work->shared_count; ++i) - dma_fence_put(work->shared[i]); - kfree(work->shared); - kfree(work); + r = amdgpu_crtc_prepare_flip(crtc, + fb, + event, + page_flip_flags, + target, + &work, + &new_abo); + if (r) + return r; - return r; + amdgpu_crtc_submit_flip(crtc, fb, work, new_abo); + + return 0; } int amdgpu_crtc_set_config(struct drm_mode_set *set, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 2af2678ddaf6..109a3833c3a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -587,6 +587,21 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx); +void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo); +int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, + uint32_t target, + struct amdgpu_flip_work **work, + struct amdgpu_bo **new_abo); + +void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct amdgpu_flip_work *work, + struct amdgpu_bo *new_abo); + extern const struct drm_mode_config_funcs amdgpu_mode_funcs; #endif -- GitLab From 4562236b3bc0a28aeb6ee93b2d8a849a4c4e1c7c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 15:58:20 -0400 Subject: [PATCH 0064/2898] drm/amd/dc: Add dc display driver (v2) Supported DCE versions: 8.0, 10.0, 11.0, 11.2 v2: rebase against 4.11 Signed-off-by: Harry Wentland Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Kconfig | 1 + drivers/gpu/drm/amd/amdgpu/Makefile | 17 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 15 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 93 +- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 5 - drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 29 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 85 +- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 2 +- drivers/gpu/drm/amd/amdgpu/cik.c | 9 + drivers/gpu/drm/amd/amdgpu/vi.c | 21 + drivers/gpu/drm/amd/display/Kconfig | 28 + drivers/gpu/drm/amd/display/Makefile | 22 + .../gpu/drm/amd/display/amdgpu_dm/Makefile | 17 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1564 ++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 171 + .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 484 ++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 829 ++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 122 + .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 443 ++ .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 36 + .../display/amdgpu_dm/amdgpu_dm_services.c | 463 ++ .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 3150 ++++++++++++ .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 101 + drivers/gpu/drm/amd/display/dc/Makefile | 28 + .../gpu/drm/amd/display/dc/basics/Makefile | 11 + .../drm/amd/display/dc/basics/conversion.c | 223 + .../drm/amd/display/dc/basics/conversion.h | 51 + .../drm/amd/display/dc/basics/fixpt31_32.c | 691 +++ .../drm/amd/display/dc/basics/fixpt32_32.c | 221 + .../amd/display/dc/basics/grph_object_id.c | 134 + .../drm/amd/display/dc/basics/log_helpers.c | 100 + .../gpu/drm/amd/display/dc/basics/logger.c | 457 ++ .../gpu/drm/amd/display/dc/basics/logger.h | 67 + .../amd/display/dc/basics/register_logger.c | 197 + .../drm/amd/display/dc/basics/signal_types.c | 116 + .../gpu/drm/amd/display/dc/basics/vector.c | 307 ++ drivers/gpu/drm/amd/display/dc/bios/Makefile | 24 + .../gpu/drm/amd/display/dc/bios/bios_parser.c | 4220 +++++++++++++++++ .../gpu/drm/amd/display/dc/bios/bios_parser.h | 33 + .../amd/display/dc/bios/bios_parser_helper.c | 82 + .../amd/display/dc/bios/bios_parser_helper.h | 40 + .../display/dc/bios/bios_parser_interface.c | 50 + .../dc/bios/bios_parser_types_internal.h | 72 + .../drm/amd/display/dc/bios/command_table.c | 2609 ++++++++++ .../drm/amd/display/dc/bios/command_table.h | 112 + .../display/dc/bios/command_table_helper.c | 288 ++ .../display/dc/bios/command_table_helper.h | 90 + .../bios/dce110/command_table_helper_dce110.c | 364 ++ .../bios/dce110/command_table_helper_dce110.h | 34 + .../bios/dce112/command_table_helper_dce112.c | 418 ++ .../bios/dce112/command_table_helper_dce112.h | 34 + .../bios/dce80/command_table_helper_dce80.c | 354 ++ .../bios/dce80/command_table_helper_dce80.h | 33 + drivers/gpu/drm/amd/display/dc/calcs/Makefile | 10 + .../amd/display/dc/calcs/bandwidth_calcs.c | 3108 ++++++++++++ .../gpu/drm/amd/display/dc/calcs/bw_fixed.c | 299 ++ .../drm/amd/display/dc/calcs/gamma_calcs.c | 1382 ++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 1846 +++++++ .../gpu/drm/amd/display/dc/core/dc_debug.c | 270 ++ .../drm/amd/display/dc/core/dc_hw_sequencer.c | 93 + drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1899 ++++++++ .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 1098 +++++ .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 2462 ++++++++++ .../drm/amd/display/dc/core/dc_link_hwss.c | 222 + .../gpu/drm/amd/display/dc/core/dc_resource.c | 1934 ++++++++ drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 113 + .../gpu/drm/amd/display/dc/core/dc_stream.c | 141 + .../gpu/drm/amd/display/dc/core/dc_surface.c | 213 + .../gpu/drm/amd/display/dc/core/dc_target.c | 334 ++ drivers/gpu/drm/amd/display/dc/dc.h | 780 +++ .../gpu/drm/amd/display/dc/dc_bios_types.h | 224 + drivers/gpu/drm/amd/display/dc/dc_ddc_types.h | 115 + drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 105 + drivers/gpu/drm/amd/display/dc/dc_helper.c | 144 + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 588 +++ drivers/gpu/drm/amd/display/dc/dc_types.h | 493 ++ drivers/gpu/drm/amd/display/dc/dce/Makefile | 14 + .../gpu/drm/amd/display/dc/dce/dce_audio.c | 920 ++++ .../gpu/drm/amd/display/dc/dce/dce_audio.h | 145 + .../drm/amd/display/dc/dce/dce_clock_source.c | 1264 +++++ .../drm/amd/display/dc/dce/dce_clock_source.h | 109 + .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 195 + .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 250 + .../drm/amd/display/dc/dce/dce_link_encoder.c | 2176 +++++++++ .../drm/amd/display/dc/dce/dce_link_encoder.h | 363 ++ .../drm/amd/display/dc/dce/dce_mem_input.c | 384 ++ .../drm/amd/display/dc/dce/dce_mem_input.h | 217 + .../drm/amd/display/dc/dce/dce_scl_filters.c | 501 ++ .../amd/display/dc/dce/dce_stream_encoder.c | 1302 +++++ .../amd/display/dc/dce/dce_stream_encoder.h | 564 +++ .../drm/amd/display/dc/dce/dce_transform.c | 1002 ++++ .../drm/amd/display/dc/dce/dce_transform.h | 313 ++ .../gpu/drm/amd/display/dc/dce100/Makefile | 23 + .../display/dc/dce100/dce100_hw_sequencer.c | 140 + .../display/dc/dce100/dce100_hw_sequencer.h | 36 + .../amd/display/dc/dce100/dce100_resource.c | 1085 +++++ .../amd/display/dc/dce100/dce100_resource.h | 19 + .../gpu/drm/amd/display/dc/dce110/Makefile | 15 + .../amd/display/dc/dce110/dce110_compressor.c | 859 ++++ .../amd/display/dc/dce110/dce110_compressor.h | 78 + .../display/dc/dce110/dce110_hw_sequencer.c | 1978 ++++++++ .../display/dc/dce110/dce110_hw_sequencer.h | 62 + .../drm/amd/display/dc/dce110/dce110_ipp.c | 62 + .../drm/amd/display/dc/dce110/dce110_ipp.h | 76 + .../amd/display/dc/dce110/dce110_ipp_cursor.c | 253 + .../amd/display/dc/dce110/dce110_ipp_gamma.c | 303 ++ .../amd/display/dc/dce110/dce110_mem_input.c | 535 +++ .../amd/display/dc/dce110/dce110_mem_input.h | 131 + .../display/dc/dce110/dce110_mem_input_v.c | 1081 +++++ .../display/dc/dce110/dce110_mem_input_v.h | 94 + .../drm/amd/display/dc/dce110/dce110_opp.c | 77 + .../drm/amd/display/dc/dce110/dce110_opp.h | 149 + .../amd/display/dc/dce110/dce110_opp_csc.c | 363 ++ .../amd/display/dc/dce110/dce110_opp_csc_v.c | 738 +++ .../display/dc/dce110/dce110_opp_formatter.c | 627 +++ .../display/dc/dce110/dce110_opp_regamma.c | 537 +++ .../display/dc/dce110/dce110_opp_regamma_v.c | 551 +++ .../drm/amd/display/dc/dce110/dce110_opp_v.c | 63 + .../drm/amd/display/dc/dce110/dce110_opp_v.h | 56 + .../amd/display/dc/dce110/dce110_resource.c | 1413 ++++++ .../amd/display/dc/dce110/dce110_resource.h | 56 + .../dc/dce110/dce110_timing_generator.c | 1953 ++++++++ .../dc/dce110/dce110_timing_generator.h | 273 ++ .../dc/dce110/dce110_timing_generator_v.c | 743 +++ .../dc/dce110/dce110_timing_generator_v.h | 33 + .../display/dc/dce110/dce110_transform_v.c | 704 +++ .../display/dc/dce110/dce110_transform_v.h | 37 + .../drm/amd/display/dc/dce110/dce110_types.h | 30 + .../gpu/drm/amd/display/dc/dce112/Makefile | 11 + .../amd/display/dc/dce112/dce112_compressor.c | 859 ++++ .../amd/display/dc/dce112/dce112_compressor.h | 78 + .../display/dc/dce112/dce112_hw_sequencer.c | 166 + .../display/dc/dce112/dce112_hw_sequencer.h | 36 + .../amd/display/dc/dce112/dce112_mem_input.c | 54 + .../amd/display/dc/dce112/dce112_mem_input.h | 38 + .../drm/amd/display/dc/dce112/dce112_opp.c | 72 + .../drm/amd/display/dc/dce112/dce112_opp.h | 48 + .../display/dc/dce112/dce112_opp_formatter.c | 215 + .../amd/display/dc/dce112/dce112_resource.c | 1418 ++++++ .../amd/display/dc/dce112/dce112_resource.h | 55 + drivers/gpu/drm/amd/display/dc/dce80/Makefile | 16 + .../amd/display/dc/dce80/dce80_compressor.c | 839 ++++ .../amd/display/dc/dce80/dce80_compressor.h | 78 + .../amd/display/dc/dce80/dce80_hw_sequencer.c | 141 + .../amd/display/dc/dce80/dce80_hw_sequencer.h | 36 + .../gpu/drm/amd/display/dc/dce80/dce80_ipp.c | 64 + .../gpu/drm/amd/display/dc/dce80/dce80_ipp.h | 47 + .../amd/display/dc/dce80/dce80_ipp_gamma.c | 76 + .../amd/display/dc/dce80/dce80_mem_input.c | 83 + .../amd/display/dc/dce80/dce80_mem_input.h | 36 + .../gpu/drm/amd/display/dc/dce80/dce80_opp.c | 136 + .../gpu/drm/amd/display/dc/dce80/dce80_opp.h | 130 + .../drm/amd/display/dc/dce80/dce80_opp_csc.c | 363 ++ .../display/dc/dce80/dce80_opp_formatter.c | 577 +++ .../amd/display/dc/dce80/dce80_opp_regamma.c | 543 +++ .../drm/amd/display/dc/dce80/dce80_resource.c | 1063 +++++ .../drm/amd/display/dc/dce80/dce80_resource.h | 39 + .../display/dc/dce80/dce80_timing_generator.c | 241 + .../display/dc/dce80/dce80_timing_generator.h | 45 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 101 + drivers/gpu/drm/amd/display/dc/dm_services.h | 424 ++ .../drm/amd/display/dc/dm_services_types.h | 242 + drivers/gpu/drm/amd/display/dc/gpio/Makefile | 38 + .../dc/gpio/dce110/hw_factory_dce110.c | 178 + .../dc/gpio/dce110/hw_factory_dce110.h | 32 + .../dc/gpio/dce110/hw_translate_dce110.c | 387 ++ .../dc/gpio/dce110/hw_translate_dce110.h | 34 + .../display/dc/gpio/dce80/hw_factory_dce80.c | 173 + .../display/dc/gpio/dce80/hw_factory_dce80.h | 32 + .../dc/gpio/dce80/hw_translate_dce80.c | 411 ++ .../dc/gpio/dce80/hw_translate_dce80.h | 32 + .../gpu/drm/amd/display/dc/gpio/ddc_regs.h | 150 + .../dc/gpio/diagnostics/hw_factory_diag.c | 63 + .../dc/gpio/diagnostics/hw_factory_diag.h | 32 + .../dc/gpio/diagnostics/hw_translate_diag.c | 40 + .../dc/gpio/diagnostics/hw_translate_diag.h | 34 + .../gpu/drm/amd/display/dc/gpio/gpio_base.c | 272 ++ .../gpu/drm/amd/display/dc/gpio/gpio_regs.h | 45 + .../drm/amd/display/dc/gpio/gpio_service.c | 592 +++ .../drm/amd/display/dc/gpio/gpio_service.h | 56 + .../gpu/drm/amd/display/dc/gpio/hpd_regs.h | 79 + drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 243 + drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h | 46 + .../gpu/drm/amd/display/dc/gpio/hw_factory.c | 93 + .../gpu/drm/amd/display/dc/gpio/hw_factory.h | 74 + drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c | 205 + drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h | 144 + drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c | 175 + drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h | 46 + .../drm/amd/display/dc/gpio/hw_translate.c | 75 + .../drm/amd/display/dc/gpio/hw_translate.h | 50 + drivers/gpu/drm/amd/display/dc/gpu/Makefile | 36 + .../dc/gpu/dce110/display_clock_dce110.c | 1035 ++++ .../dc/gpu/dce110/display_clock_dce110.h | 53 + .../dc/gpu/dce112/display_clock_dce112.c | 964 ++++ .../dc/gpu/dce112/display_clock_dce112.h | 114 + .../dc/gpu/dce80/display_clock_dce80.c | 934 ++++ .../dc/gpu/dce80/display_clock_dce80.h | 57 + .../drm/amd/display/dc/gpu/display_clock.c | 217 + .../drm/amd/display/dc/gpu/display_clock.h | 89 + .../drm/amd/display/dc/gpu/divider_range.c | 127 + .../drm/amd/display/dc/gpu/divider_range.h | 62 + .../gpu/drm/amd/display/dc/i2caux/Makefile | 58 + .../drm/amd/display/dc/i2caux/aux_engine.c | 567 +++ .../drm/amd/display/dc/i2caux/aux_engine.h | 117 + .../display/dc/i2caux/dce100/i2caux_dce100.c | 112 + .../display/dc/i2caux/dce100/i2caux_dce100.h | 32 + .../dc/i2caux/dce110/aux_engine_dce110.c | 456 ++ .../dc/i2caux/dce110/aux_engine_dce110.h | 78 + .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 577 +++ .../dc/i2caux/dce110/i2c_hw_engine_dce110.h | 214 + .../dc/i2caux/dce110/i2c_sw_engine_dce110.c | 171 + .../dc/i2caux/dce110/i2c_sw_engine_dce110.h | 43 + .../display/dc/i2caux/dce110/i2caux_dce110.c | 323 ++ .../display/dc/i2caux/dce110/i2caux_dce110.h | 53 + .../display/dc/i2caux/dce112/i2caux_dce112.c | 140 + .../display/dc/i2caux/dce112/i2caux_dce112.h | 32 + .../dc/i2caux/dce80/i2c_hw_engine_dce80.c | 885 ++++ .../dc/i2caux/dce80/i2c_hw_engine_dce80.h | 54 + .../dc/i2caux/dce80/i2c_sw_engine_dce80.c | 184 + .../dc/i2caux/dce80/i2c_sw_engine_dce80.h | 43 + .../display/dc/i2caux/dce80/i2caux_dce80.c | 295 ++ .../display/dc/i2caux/dce80/i2caux_dce80.h | 38 + .../dc/i2caux/diagnostics/i2caux_diag.c | 108 + .../dc/i2caux/diagnostics/i2caux_diag.h | 32 + .../gpu/drm/amd/display/dc/i2caux/engine.h | 120 + .../drm/amd/display/dc/i2caux/engine_base.c | 53 + .../drm/amd/display/dc/i2caux/i2c_engine.c | 121 + .../drm/amd/display/dc/i2caux/i2c_engine.h | 113 + .../display/dc/i2caux/i2c_generic_hw_engine.c | 286 ++ .../display/dc/i2caux/i2c_generic_hw_engine.h | 77 + .../drm/amd/display/dc/i2caux/i2c_hw_engine.c | 246 + .../drm/amd/display/dc/i2caux/i2c_hw_engine.h | 80 + .../drm/amd/display/dc/i2caux/i2c_sw_engine.c | 610 +++ .../drm/amd/display/dc/i2caux/i2c_sw_engine.h | 81 + .../gpu/drm/amd/display/dc/i2caux/i2caux.c | 459 ++ .../gpu/drm/amd/display/dc/i2caux/i2caux.h | 122 + .../drm/amd/display/dc/inc/bandwidth_calcs.h | 503 ++ drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h | 63 + .../gpu/drm/amd/display/dc/inc/clock_source.h | 178 + .../gpu/drm/amd/display/dc/inc/compressor.h | 93 + drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 50 + .../gpu/drm/amd/display/dc/inc/core_status.h | 47 + .../gpu/drm/amd/display/dc/inc/core_types.h | 319 ++ .../gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 145 + .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 60 + .../gpu/drm/amd/display/dc/inc/gamma_calcs.h | 19 + .../gpu/drm/amd/display/dc/inc/gamma_types.h | 38 + drivers/gpu/drm/amd/display/dc/inc/hw/audio.h | 62 + drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h | 86 + .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 74 + drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 121 + .../drm/amd/display/dc/inc/hw/link_encoder.h | 263 + .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 106 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 322 ++ .../amd/display/dc/inc/hw/stream_encoder.h | 121 + .../amd/display/dc/inc/hw/timing_generator.h | 162 + .../gpu/drm/amd/display/dc/inc/hw/transform.h | 179 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 156 + .../gpu/drm/amd/display/dc/inc/link_hwss.h | 73 + .../gpu/drm/amd/display/dc/inc/reg_helper.h | 290 ++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 164 + drivers/gpu/drm/amd/display/dc/irq/Makefile | 28 + .../dc/irq/dce110/irq_service_dce110.c | 367 ++ .../dc/irq/dce110/irq_service_dce110.h | 48 + .../display/dc/irq/dce80/irq_service_dce80.c | 283 ++ .../display/dc/irq/dce80/irq_service_dce80.h | 35 + .../gpu/drm/amd/display/dc/irq/irq_service.c | 163 + .../gpu/drm/amd/display/dc/irq/irq_service.h | 85 + drivers/gpu/drm/amd/display/dc/irq_types.h | 185 + drivers/gpu/drm/amd/display/dc/os_types.h | 61 + .../gpu/drm/amd/display/dc/virtual/Makefile | 9 + .../display/dc/virtual/virtual_link_encoder.c | 150 + .../display/dc/virtual/virtual_link_encoder.h | 34 + .../dc/virtual/virtual_stream_encoder.c | 132 + .../dc/virtual/virtual_stream_encoder.h | 39 + .../include/asic_capability_interface.h | 55 + .../display/include/asic_capability_types.h | 116 + .../gpu/drm/amd/display/include/audio_types.h | 106 + .../display/include/bios_parser_interface.h | 44 + .../amd/display/include/bios_parser_types.h | 338 ++ .../gpu/drm/amd/display/include/dal_asic_id.h | 125 + .../amd/display/include/dal_register_logger.h | 42 + .../gpu/drm/amd/display/include/dal_types.h | 44 + .../amd/display/include/ddc_service_types.h | 189 + .../display/include/display_clock_interface.h | 175 + .../gpu/drm/amd/display/include/dpcd_defs.h | 742 +++ .../gpu/drm/amd/display/include/fixed31_32.h | 390 ++ .../gpu/drm/amd/display/include/fixed32_32.h | 83 + .../drm/amd/display/include/gpio_interface.h | 92 + .../display/include/gpio_service_interface.h | 105 + .../gpu/drm/amd/display/include/gpio_types.h | 332 ++ .../display/include/grph_object_ctrl_defs.h | 407 ++ .../amd/display/include/grph_object_defs.h | 140 + .../drm/amd/display/include/grph_object_id.h | 256 + .../amd/display/include/hw_sequencer_types.h | 105 + .../amd/display/include/i2caux_interface.h | 89 + .../drm/amd/display/include/irq_interface.h | 31 + .../display/include/irq_service_interface.h | 51 + .../amd/display/include/link_service_types.h | 232 + .../amd/display/include/logger_interface.h | 140 + .../drm/amd/display/include/logger_types.h | 95 + .../drm/amd/display/include/set_mode_types.h | 127 + .../drm/amd/display/include/signal_types.h | 59 + drivers/gpu/drm/amd/display/include/vector.h | 150 + .../gpu/drm/amd/display/modules/color/color.c | 2094 ++++++++ .../drm/amd/display/modules/freesync/Makefile | 10 + .../amd/display/modules/freesync/freesync.c | 1158 +++++ .../drm/amd/display/modules/inc/mod_color.h | 179 + .../amd/display/modules/inc/mod_freesync.h | 149 + .../drm/amd/display/modules/inc/mod_power.h | 112 + .../gpu/drm/amd/display/modules/power/power.c | 784 +++ 315 files changed, 99491 insertions(+), 37 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/Kconfig create mode 100644 drivers/gpu/drm/amd/display/Makefile create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/Makefile create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/basics/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/basics/conversion.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/conversion.h create mode 100644 drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/log_helpers.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/logger.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/logger.h create mode 100644 drivers/gpu/drm/amd/display/dc/basics/register_logger.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/signal_types.c create mode 100644 drivers/gpu/drm/amd/display/dc/basics/vector.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_debug.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_sink.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_stream.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_surface.c create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_target.c create mode 100644 drivers/gpu/drm/amd/display/dc/dc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_bios_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_ddc_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_dp_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_helper.c create mode 100644 drivers/gpu/drm/amd/display/dc/dc_hw_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dc_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_audio.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_audio.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_transform.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_transform.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h create mode 100644 drivers/gpu/drm/amd/display/dc/dm_helpers.h create mode 100644 drivers/gpu/drm/amd/display/dc/dm_services.h create mode 100644 drivers/gpu/drm/amd/display/dc/dm_services_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/clock_source.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/compressor.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_dc.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_status.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/audio.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/transform.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/link_hwss.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/reg_helper.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/irq/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h create mode 100644 drivers/gpu/drm/amd/display/dc/irq/irq_service.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/irq_service.h create mode 100644 drivers/gpu/drm/amd/display/dc/irq_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/os_types.h create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h create mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_types.h create mode 100644 drivers/gpu/drm/amd/display/include/audio_types.h create mode 100644 drivers/gpu/drm/amd/display/include/bios_parser_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/bios_parser_types.h create mode 100644 drivers/gpu/drm/amd/display/include/dal_asic_id.h create mode 100644 drivers/gpu/drm/amd/display/include/dal_register_logger.h create mode 100644 drivers/gpu/drm/amd/display/include/dal_types.h create mode 100644 drivers/gpu/drm/amd/display/include/ddc_service_types.h create mode 100644 drivers/gpu/drm/amd/display/include/display_clock_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/dpcd_defs.h create mode 100644 drivers/gpu/drm/amd/display/include/fixed31_32.h create mode 100644 drivers/gpu/drm/amd/display/include/fixed32_32.h create mode 100644 drivers/gpu/drm/amd/display/include/gpio_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/gpio_service_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/gpio_types.h create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_defs.h create mode 100644 drivers/gpu/drm/amd/display/include/grph_object_id.h create mode 100644 drivers/gpu/drm/amd/display/include/hw_sequencer_types.h create mode 100644 drivers/gpu/drm/amd/display/include/i2caux_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/irq_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/irq_service_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/link_service_types.h create mode 100644 drivers/gpu/drm/amd/display/include/logger_interface.h create mode 100644 drivers/gpu/drm/amd/display/include/logger_types.h create mode 100644 drivers/gpu/drm/amd/display/include/set_mode_types.h create mode 100644 drivers/gpu/drm/amd/display/include/signal_types.h create mode 100644 drivers/gpu/drm/amd/display/include/vector.h create mode 100644 drivers/gpu/drm/amd/display/modules/color/color.c create mode 100644 drivers/gpu/drm/amd/display/modules/freesync/Makefile create mode 100644 drivers/gpu/drm/amd/display/modules/freesync/freesync.c create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_color.h create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h create mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_power.h create mode 100644 drivers/gpu/drm/amd/display/modules/power/power.c diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index 26682454a446..e8af1f5e8a79 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig @@ -41,3 +41,4 @@ config DRM_AMDGPU_GART_DEBUGFS pages. Uses more memory for housekeeping, enable only for debugging. source "drivers/gpu/drm/amd/acp/Kconfig" +source "drivers/gpu/drm/amd/display/Kconfig" diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 25a95c95df14..454e6efeb5cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -3,13 +3,19 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. FULL_AMD_PATH=$(src)/.. +DISPLAY_FOLDER_NAME=display +FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME) ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/include \ -I$(FULL_AMD_PATH)/amdgpu \ -I$(FULL_AMD_PATH)/scheduler \ -I$(FULL_AMD_PATH)/powerplay/inc \ - -I$(FULL_AMD_PATH)/acp/include + -I$(FULL_AMD_PATH)/acp/include \ + -I$(FULL_AMD_DISPLAY_PATH) \ + -I$(FULL_AMD_DISPLAY_PATH)/include \ + -I$(FULL_AMD_DISPLAY_PATH)/dc \ + -I$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm amdgpu-y := amdgpu_drv.o @@ -132,4 +138,13 @@ include $(FULL_AMD_PATH)/powerplay/Makefile amdgpu-y += $(AMD_POWERPLAY_FILES) +ifneq ($(CONFIG_DRM_AMD_DC),) + +RELATIVE_AMD_DISPLAY_PATH = ../$(DISPLAY_FOLDER_NAME) +include $(FULL_AMD_DISPLAY_PATH)/Makefile + +amdgpu-y += $(AMD_DISPLAY_FILES) + +endif + obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ebfc267467ee..2c88dd07e1bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -66,6 +66,7 @@ #include "amdgpu_vce.h" #include "amdgpu_vcn.h" #include "amdgpu_mn.h" +#include "amdgpu_dm.h" #include "gpu_scheduler.h" #include "amdgpu_virt.h" @@ -101,6 +102,7 @@ extern int amdgpu_vm_fragment_size; extern int amdgpu_vm_fault_stop; extern int amdgpu_vm_debug; extern int amdgpu_vm_update_mode; +extern int amdgpu_dc; extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern int amdgpu_no_evict; @@ -1507,6 +1509,7 @@ struct amdgpu_device { /* display */ bool enable_virtual_display; struct amdgpu_mode_info mode_info; + /* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */ struct work_struct hotplug_work; struct amdgpu_irq_src crtc_irq; struct amdgpu_irq_src pageflip_irq; @@ -1563,6 +1566,9 @@ struct amdgpu_device { /* GDS */ struct amdgpu_gds gds; + /* display related functionality */ + struct amdgpu_display_manager dm; + struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM]; int num_ip_blocks; struct mutex mn_lock; @@ -1624,6 +1630,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v); u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index); void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v); +bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type); +bool amdgpu_device_has_dc_support(struct amdgpu_device *adev); + /* * Registers read & write functions. */ @@ -1884,5 +1893,11 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, uint64_t addr, struct amdgpu_bo **bo, struct amdgpu_bo_va_mapping **mapping); +#if defined(CONFIG_DRM_AMD_DC) +int amdgpu_dm_display_resume(struct amdgpu_device *adev ); +#else +static inline int amdgpu_dm_display_resume(struct amdgpu_device *adev) { return 0; } +#endif + #include "amdgpu_object.h" #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 3e84ddf9e3b5..226d10f288a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1973,6 +1974,41 @@ static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev) } } +bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) +{ + switch (asic_type) { +#if defined(CONFIG_DRM_AMD_DC) + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_CARRIZO: + case CHIP_STONEY: + case CHIP_POLARIS11: + case CHIP_POLARIS10: + case CHIP_TONGA: + case CHIP_FIJI: +#if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) + return amdgpu_dc != 0; +#else + return amdgpu_dc > 0; +#endif +#endif + default: + return false; + } +} + +/** + * amdgpu_device_has_dc_support - check if dc is supported + * + * @adev: amdgpu_device_pointer + * + * Returns true for supported, false for not supported + */ +bool amdgpu_device_has_dc_support(struct amdgpu_device *adev) +{ + return amdgpu_device_asic_has_dc_support(adev->asic_type); +} + /** * amdgpu_device_init - initialize the driver * @@ -2168,7 +2204,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, goto failed; } /* init i2c buses */ - amdgpu_atombios_i2c_init(adev); + if (!amdgpu_device_has_dc_support(adev)) + amdgpu_atombios_i2c_init(adev); } /* Fence driver */ @@ -2296,7 +2333,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) adev->accel_working = false; cancel_delayed_work_sync(&adev->late_init_work); /* free i2c buses */ - amdgpu_i2c_fini(adev); + if (!amdgpu_device_has_dc_support(adev)) + amdgpu_i2c_fini(adev); amdgpu_atombios_fini(adev); kfree(adev->bios); adev->bios = NULL; @@ -2346,12 +2384,14 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) drm_kms_helper_poll_disable(dev); - /* turn off display hw */ - drm_modeset_lock_all(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + if (!amdgpu_device_has_dc_support(adev)) { + /* turn off display hw */ + drm_modeset_lock_all(dev); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } + drm_modeset_unlock_all(dev); } - drm_modeset_unlock_all(dev); amdgpu_amdkfd_suspend(adev); @@ -2494,13 +2534,25 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) /* blat the mode back in */ if (fbcon) { - drm_helper_resume_force_mode(dev); - /* turn on display hw */ - drm_modeset_lock_all(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + if (!amdgpu_device_has_dc_support(adev)) { + /* pre DCE11 */ + drm_helper_resume_force_mode(dev); + + /* turn on display hw */ + drm_modeset_lock_all(dev); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } + drm_modeset_unlock_all(dev); + } else { + /* + * There is no equivalent atomic helper to turn on + * display, so we defined our own function for this, + * once suspend resume is supported by the atomic + * framework this will be reworked + */ + amdgpu_dm_display_resume(adev); } - drm_modeset_unlock_all(dev); } drm_kms_helper_poll_enable(dev); @@ -2517,7 +2569,10 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) #ifdef CONFIG_PM dev->dev->power.disable_depth++; #endif - drm_helper_hpd_irq_event(dev); + if (!amdgpu_device_has_dc_support(adev)) + drm_helper_hpd_irq_event(dev); + else + drm_kms_helper_hotplug_event(dev); #ifdef CONFIG_PM dev->dev->power.disable_depth--; #endif @@ -2814,6 +2869,7 @@ int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, struct amdgpu_job *job) */ int amdgpu_gpu_reset(struct amdgpu_device *adev) { + struct drm_atomic_state *state = NULL; int i, r; int resched; bool need_full_reset, vram_lost = false; @@ -2827,6 +2883,9 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) /* block TTM */ resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); + /* store modesetting */ + if (amdgpu_device_has_dc_support(adev)) + state = drm_atomic_helper_suspend(adev->ddev); /* block scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { @@ -2944,7 +3003,11 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) } } - drm_helper_resume_force_mode(adev->ddev); + if (amdgpu_device_has_dc_support(adev)) { + r = drm_atomic_helper_resume(adev->ddev, state); + amdgpu_dm_display_resume(adev); + } else + drm_helper_resume_force_mode(adev->ddev); ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index f79f9ea58b17..0d22259c6d02 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -429,7 +429,7 @@ struct amdgpu_pm { uint32_t fw_version; uint32_t pcie_gen_mask; uint32_t pcie_mlw_mask; - struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */ + struct amd_pp_display_configuration pm_display_cfg;/* set by dc */ }; #define R600_SSTU_DFLT 0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 4f98960e47f9..13cd35b70c51 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -103,6 +103,7 @@ int amdgpu_vm_debug = 0; int amdgpu_vram_page_split = 512; int amdgpu_vm_update_mode = -1; int amdgpu_exp_hw_support = 0; +int amdgpu_dc = -1; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_no_evict = 0; @@ -207,6 +208,9 @@ module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444); MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))"); module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444); +MODULE_PARM_DESC(dc, "Display Core driver (1 = enable, 0 = disable, -1 = auto (default))"); +module_param_named(dc, amdgpu_dc, int, 0444); + MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 32)"); module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 562930b17a6d..2484dac08050 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -42,11 +42,6 @@ this contains a helper + a amdgpu fb the helper contains a pointer to amdgpu framebuffer baseclass. */ -struct amdgpu_fbdev { - struct drm_fb_helper helper; - struct amdgpu_framebuffer rfb; - struct amdgpu_device *adev; -}; static int amdgpufb_open(struct fb_info *info, int user) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 538e5f27d120..47c5ce9807db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -37,6 +37,10 @@ #include +#ifdef CONFIG_DRM_AMD_DC +#include "amdgpu_dm_irq.h" +#endif + #define AMDGPU_WAIT_IDLE_TIMEOUT 200 /* @@ -221,15 +225,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev) spin_lock_init(&adev->irq.lock); - if (!adev->enable_virtual_display) - /* Disable vblank irqs aggressively for power-saving */ - adev->ddev->vblank_disable_immediate = true; - - r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc); - if (r) { - return r; - } - /* enable msi */ adev->irq.msi_enabled = false; @@ -241,7 +236,21 @@ int amdgpu_irq_init(struct amdgpu_device *adev) } } - INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func); + if (!amdgpu_device_has_dc_support(adev)) { + if (!adev->enable_virtual_display) + /* Disable vblank irqs aggressively for power-saving */ + /* XXX: can this be enabled for DC? */ + adev->ddev->vblank_disable_immediate = true; + + r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc); + if (r) + return r; + + /* pre DCE11 */ + INIT_WORK(&adev->hotplug_work, + amdgpu_hotplug_work_func); + } + INIT_WORK(&adev->reset_work, amdgpu_irq_reset_work_func); adev->irq.installed = true; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 4fd06f8d9768..7b9ae1d58c72 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1034,7 +1034,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW) }; const int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 109a3833c3a8..3a3adfa16ada 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -38,11 +38,15 @@ #include #include #include +#include #include #include #include #include "amdgpu_irq.h" +#include +#include "modules/inc/mod_freesync.h" + struct amdgpu_bo; struct amdgpu_device; struct amdgpu_encoder; @@ -292,6 +296,27 @@ struct amdgpu_display_funcs { uint16_t connector_object_id, struct amdgpu_hpd *hpd, struct amdgpu_router *router); + /* it is used to enter or exit into free sync mode */ + int (*notify_freesync)(struct drm_device *dev, void *data, + struct drm_file *filp); + /* it is used to allow enablement of freesync mode */ + int (*set_freesync_property)(struct drm_connector *connector, + struct drm_property *property, + uint64_t val); + + +}; + +struct amdgpu_framebuffer { + struct drm_framebuffer base; + struct drm_gem_object *obj; +}; + +struct amdgpu_fbdev { + struct drm_fb_helper helper; + struct amdgpu_framebuffer rfb; + struct list_head fbdev_list; + struct amdgpu_device *adev; }; struct amdgpu_mode_info { @@ -400,6 +425,11 @@ struct amdgpu_crtc { /* for virtual dce */ struct hrtimer vblank_timer; enum amdgpu_interrupt_state vsync_timer_enabled; + + int otg_inst; + uint32_t flip_flags; + /* After Set Mode target will be non-NULL */ + struct dc_target *target; }; struct amdgpu_encoder_atom_dig { @@ -489,6 +519,19 @@ enum amdgpu_connector_dither { AMDGPU_FMT_DITHER_ENABLE = 1, }; +struct amdgpu_dm_dp_aux { + struct drm_dp_aux aux; + uint32_t link_index; +}; + +struct amdgpu_i2c_adapter { + struct i2c_adapter base; + struct amdgpu_display_manager *dm; + uint32_t link_index; +}; + +#define TO_DM_AUX(x) container_of((x), struct amdgpu_dm_dp_aux, aux) + struct amdgpu_connector { struct drm_connector base; uint32_t connector_id; @@ -500,6 +543,14 @@ struct amdgpu_connector { /* we need to mind the EDID between detect and get modes due to analog/digital/tvencoder */ struct edid *edid; + /* number of modes generated from EDID at 'dc_sink' */ + int num_modes; + /* The 'old' sink - before an HPD. + * The 'current' sink is in dc_link->sink. */ + const struct dc_sink *dc_sink; + const struct dc_link *dc_link; + const struct dc_sink *dc_em_sink; + const struct dc_target *target; void *con_priv; bool dac_load_detect; bool detected_by_load; /* if the connection status was determined by load */ @@ -510,11 +561,39 @@ struct amdgpu_connector { enum amdgpu_connector_audio audio; enum amdgpu_connector_dither dither; unsigned pixelclock_for_modeset; + + struct drm_dp_mst_topology_mgr mst_mgr; + struct amdgpu_dm_dp_aux dm_dp_aux; + struct drm_dp_mst_port *port; + struct amdgpu_connector *mst_port; + struct amdgpu_encoder *mst_encoder; + struct semaphore mst_sem; + + /* TODO see if we can merge with ddc_bus or make a dm_connector */ + struct amdgpu_i2c_adapter *i2c; + + /* Monitor range limits */ + int min_vfreq ; + int max_vfreq ; + int pixel_clock_mhz; + + /*freesync caps*/ + struct mod_freesync_caps caps; + + struct mutex hpd_lock; + }; -struct amdgpu_framebuffer { - struct drm_framebuffer base; - struct drm_gem_object *obj; +/* TODO: start to use this struct and remove same field from base one */ +struct amdgpu_mst_connector { + struct amdgpu_connector base; + + struct drm_dp_mst_topology_mgr mst_mgr; + struct amdgpu_dm_dp_aux dm_dp_aux; + struct drm_dp_mst_port *port; + struct amdgpu_connector *mst_port; + bool is_mst_connector; + struct amdgpu_encoder *mst_encoder; }; #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index f6ce52956e6d..375c47767ae8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1467,7 +1467,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled) { + if (amdgpu_crtc->enabled) { adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); adev->pm.dpm.new_active_crtc_count++; } diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 567c4a5cf90c..af3b66f6f47c 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -65,6 +65,7 @@ #include "oss/oss_2_0_d.h" #include "oss/oss_2_0_sh_mask.h" +#include "amdgpu_dm.h" #include "amdgpu_amdkfd.h" #include "amdgpu_powerplay.h" #include "dce_virtual.h" @@ -1900,6 +1901,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v8_2_ip_block); amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block); @@ -1914,6 +1919,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v8_5_ip_block); amdgpu_ip_block_add(adev, &gfx_v7_3_ip_block); diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 9ff69b90df36..2ac5b84eee20 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -77,6 +77,7 @@ #endif #include "dce_virtual.h" #include "mxgpu_vi.h" +#include "amdgpu_dm.h" /* * Indirect registers accessor @@ -1496,6 +1497,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v10_1_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); @@ -1512,6 +1517,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v10_0_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); @@ -1530,6 +1539,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v11_2_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); @@ -1544,6 +1557,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v11_0_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block); @@ -1561,6 +1578,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v11_0_ip_block); amdgpu_ip_block_add(adev, &gfx_v8_1_ip_block); diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig new file mode 100644 index 000000000000..47c8e2940a91 --- /dev/null +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -0,0 +1,28 @@ +menu "Display Engine Configuration" + depends on DRM && DRM_AMDGPU + +config DRM_AMD_DC + bool "AMD DC - Enable new display engine" + default y + help + Choose this option if you want to use the new display engine + support for AMDGPU. This adds required support for Vega and + Raven ASICs. + +config DRM_AMD_DC_PRE_VEGA + bool "DC support for Polaris and older ASICs" + default n + help + Choose this option to enable the new DC support for older asics + by default. This includes Polaris, Carrizo, Tonga, Bonaire, + and Hawaii. + +config DEBUG_KERNEL_DC + bool "Enable kgdb break in DC" + depends on DRM_AMD_DC + help + Choose this option + if you want to hit + kdgb_break in assert. + +endmenu diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile new file mode 100644 index 000000000000..8ba37dd9cf7f --- /dev/null +++ b/drivers/gpu/drm/amd/display/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for the DAL (Display Abstract Layer), which is a sub-component +# of the AMDGPU drm driver. +# It provides the HW control for display related functionalities. + +AMDDALPATH = $(RELATIVE_AMD_DISPLAY_PATH) + +subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include + +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/ +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/hw +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync + +#TODO: remove when Timing Sync feature is complete +subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0 + +DAL_LIBS = amdgpu_dm dc modules/freesync + +AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS))) + +include $(AMD_DAL) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile new file mode 100644 index 000000000000..698b1d4f83f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile @@ -0,0 +1,17 @@ +# +# Makefile for the 'dm' sub-component of DAL. +# It provides the control and status of dm blocks. + + + +AMDGPUDM = amdgpu_dm_types.o amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o + +ifneq ($(CONFIG_DRM_AMD_DC),) +AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o +endif + +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc + +AMDGPU_DM = $(addprefix $(AMDDALPATH)/amdgpu_dm/,$(AMDGPUDM)) + +AMD_DISPLAY_FILES += $(AMDGPU_DM) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c new file mode 100644 index 000000000000..ae4ba7777839 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -0,0 +1,1564 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services_types.h" +#include "dc.h" + +#include "vid.h" +#include "amdgpu.h" +#include "atom.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_types.h" + +#include "amd_shared.h" +#include "amdgpu_dm_irq.h" +#include "dm_helpers.h" + +#include "ivsrcid/ivsrcid_vislands30.h" + +#include +#include +#include + +#include +#include +#include + +#include "modules/inc/mod_freesync.h" + +/* Debug facilities */ +#define AMDGPU_DM_NOT_IMPL(fmt, ...) \ + DRM_INFO("DM_NOT_IMPL: " fmt, ##__VA_ARGS__) + +/* + * dm_vblank_get_counter + * + * @brief + * Get counter for number of vertical blanks + * + * @param + * struct amdgpu_device *adev - [in] desired amdgpu device + * int disp_idx - [in] which CRTC to get the counter from + * + * @return + * Counter for vertical blanks + */ +static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) +{ + if (crtc >= adev->mode_info.num_crtc) + return 0; + else { + struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; + + if (NULL == acrtc->target) { + DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc); + return 0; + } + + return dc_target_get_vblank_counter(acrtc->target); + } +} + +static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, + u32 *vbl, u32 *position) +{ + if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc)) + return -EINVAL; + else { + struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; + + if (NULL == acrtc->target) { + DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc); + return 0; + } + + return dc_target_get_scanoutpos(acrtc->target, vbl, position); + } + + return 0; +} + +static bool dm_is_idle(void *handle) +{ + /* XXX todo */ + return true; +} + +static int dm_wait_for_idle(void *handle) +{ + /* XXX todo */ + return 0; +} + +static bool dm_check_soft_reset(void *handle) +{ + return false; +} + +static int dm_soft_reset(void *handle) +{ + /* XXX todo */ + return 0; +} + +static struct amdgpu_crtc *get_crtc_by_otg_inst( + struct amdgpu_device *adev, + int otg_inst) +{ + struct drm_device *dev = adev->ddev; + struct drm_crtc *crtc; + struct amdgpu_crtc *amdgpu_crtc; + + /* + * following if is check inherited from both functions where this one is + * used now. Need to be checked why it could happen. + */ + if (otg_inst == -1) { + WARN_ON(1); + return adev->mode_info.crtcs[0]; + } + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + + if (amdgpu_crtc->otg_inst == otg_inst) + return amdgpu_crtc; + } + + return NULL; +} + +static void dm_pflip_high_irq(void *interrupt_params) +{ + struct amdgpu_flip_work *works; + struct amdgpu_crtc *amdgpu_crtc; + struct common_irq_params *irq_params = interrupt_params; + struct amdgpu_device *adev = irq_params->adev; + unsigned long flags; + + amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP); + + /* IRQ could occur when in initial stage */ + /*TODO work and BO cleanup */ + if (amdgpu_crtc == NULL) { + DRM_DEBUG_DRIVER("CRTC is null, returning.\n"); + return; + } + + spin_lock_irqsave(&adev->ddev->event_lock, flags); + works = amdgpu_crtc->pflip_works; + + if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ + DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n", + amdgpu_crtc->pflip_status, + AMDGPU_FLIP_SUBMITTED, + amdgpu_crtc->crtc_id, + amdgpu_crtc); + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + return; + } + + /* page flip completed. clean up */ + amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; + amdgpu_crtc->pflip_works = NULL; + + /* wakeup usersapce */ + if (works->event) + drm_crtc_send_vblank_event(&amdgpu_crtc->base, + works->event); + + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + + DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE, work: %p,\n", + __func__, amdgpu_crtc->crtc_id, amdgpu_crtc, works); + + drm_crtc_vblank_put(&amdgpu_crtc->base); + schedule_work(&works->unpin_work); +} + +static void dm_crtc_high_irq(void *interrupt_params) +{ + struct common_irq_params *irq_params = interrupt_params; + struct amdgpu_device *adev = irq_params->adev; + uint8_t crtc_index = 0; + struct amdgpu_crtc *acrtc; + + acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE); + + if (acrtc) + crtc_index = acrtc->crtc_id; + + drm_handle_vblank(adev->ddev, crtc_index); +} + +static int dm_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int dm_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +/* Prototypes of private functions */ +static int dm_early_init(void* handle); + +static void hotplug_notify_work_func(struct work_struct *work) +{ + struct amdgpu_display_manager *dm = container_of(work, struct amdgpu_display_manager, mst_hotplug_work); + struct drm_device *dev = dm->ddev; + + drm_kms_helper_hotplug_event(dev); +} + +/* Init display KMS + * + * Returns 0 on success + */ +int amdgpu_dm_init(struct amdgpu_device *adev) +{ + struct dc_init_data init_data; + adev->dm.ddev = adev->ddev; + adev->dm.adev = adev; + + DRM_INFO("DAL is enabled\n"); + /* Zero all the fields */ + memset(&init_data, 0, sizeof(init_data)); + + /* initialize DAL's lock (for SYNC context use) */ + spin_lock_init(&adev->dm.dal_lock); + + /* initialize DAL's mutex */ + mutex_init(&adev->dm.dal_mutex); + + if(amdgpu_dm_irq_init(adev)) { + DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); + goto error; + } + + init_data.asic_id.chip_family = adev->family; + + init_data.asic_id.pci_revision_id = adev->rev_id; + init_data.asic_id.hw_internal_rev = adev->external_rev_id; + + init_data.asic_id.vram_width = adev->mc.vram_width; + /* TODO: initialize init_data.asic_id.vram_type here!!!! */ + init_data.asic_id.atombios_base_address = + adev->mode_info.atom_context->bios; + + init_data.driver = adev; + + adev->dm.cgs_device = amdgpu_cgs_create_device(adev); + + if (!adev->dm.cgs_device) { + DRM_ERROR("amdgpu: failed to create cgs device.\n"); + goto error; + } + + init_data.cgs_device = adev->dm.cgs_device; + + adev->dm.dal = NULL; + + init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; + + /* Display Core create. */ + adev->dm.dc = dc_create(&init_data); + + if (!adev->dm.dc) + DRM_INFO("Display Core failed to initialize!\n"); + + INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func); + + adev->dm.freesync_module = mod_freesync_create(adev->dm.dc); + if (!adev->dm.freesync_module) { + DRM_ERROR( + "amdgpu: failed to initialize freesync_module.\n"); + } else + DRM_INFO("amdgpu: freesync_module init done %p.\n", + adev->dm.freesync_module); + + if (amdgpu_dm_initialize_drm_device(adev)) { + DRM_ERROR( + "amdgpu: failed to initialize sw for display support.\n"); + goto error; + } + + /* Update the actual used number of crtc */ + adev->mode_info.num_crtc = adev->dm.display_indexes_num; + + /* TODO: Add_display_info? */ + + /* TODO use dynamic cursor width */ + adev->ddev->mode_config.cursor_width = 128; + adev->ddev->mode_config.cursor_height = 128; + + if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) { + DRM_ERROR( + "amdgpu: failed to initialize sw for display support.\n"); + goto error; + } + + DRM_INFO("KMS initialized.\n"); + + return 0; +error: + amdgpu_dm_fini(adev); + + return -1; +} + +void amdgpu_dm_fini(struct amdgpu_device *adev) +{ + amdgpu_dm_destroy_drm_device(&adev->dm); + /* + * TODO: pageflip, vlank interrupt + * + * amdgpu_dm_irq_fini(adev); + */ + + if (adev->dm.cgs_device) { + amdgpu_cgs_destroy_device(adev->dm.cgs_device); + adev->dm.cgs_device = NULL; + } + if (adev->dm.freesync_module) { + mod_freesync_destroy(adev->dm.freesync_module); + adev->dm.freesync_module = NULL; + } + /* DC Destroy TODO: Replace destroy DAL */ + { + dc_destroy(&adev->dm.dc); + } + return; +} + +/* moved from amdgpu_dm_kms.c */ +void amdgpu_dm_destroy() +{ +} + +static int dm_sw_init(void *handle) +{ + return 0; +} + +static int dm_sw_fini(void *handle) +{ + return 0; +} + +static void detect_link_for_all_connectors(struct drm_device *dev) +{ + struct amdgpu_connector *aconnector; + struct drm_connector *connector; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + if (aconnector->dc_link->type == dc_connection_mst_branch) { + DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + + if (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) < 0) { + DRM_ERROR("DM_MST: Failed to start MST\n"); + ((struct dc_link *)aconnector->dc_link)->type = dc_connection_single; + } + } + } + + drm_modeset_unlock(&dev->mode_config.connection_mutex); +} + +static void s3_handle_mst(struct drm_device *dev, bool suspend) +{ + struct amdgpu_connector *aconnector; + struct drm_connector *connector; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + if (aconnector->dc_link->type == dc_connection_mst_branch && + !aconnector->mst_port) { + + if (suspend) + drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr); + else + drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr); + } + } + + drm_modeset_unlock(&dev->mode_config.connection_mutex); +} + +static int dm_hw_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* Create DAL display manager */ + amdgpu_dm_init(adev); + + amdgpu_dm_hpd_init(adev); + + detect_link_for_all_connectors(adev->ddev); + + return 0; +} + +static int dm_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_dm_hpd_fini(adev); + + amdgpu_dm_irq_fini(adev); + + return 0; +} + +static int dm_suspend(void *handle) +{ + struct amdgpu_device *adev = handle; + struct amdgpu_display_manager *dm = &adev->dm; + int ret = 0; + struct drm_crtc *crtc; + + s3_handle_mst(adev->ddev, true); + + /* flash all pending vblank events and turn interrupt off + * before disabling CRTCs. They will be enabled back in + * dm_display_resume + */ + drm_modeset_lock_all(adev->ddev); + list_for_each_entry(crtc, &adev->ddev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + if (acrtc->target) + drm_crtc_vblank_off(crtc); + } + drm_modeset_unlock_all(adev->ddev); + + amdgpu_dm_irq_suspend(adev); + + dc_set_power_state( + dm->dc, + DC_ACPI_CM_POWER_STATE_D3, + DC_VIDEO_POWER_SUSPEND); + + return ret; +} + +struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( + struct drm_atomic_state *state, + struct drm_crtc *crtc, + bool from_state_var) +{ + uint32_t i; + struct drm_connector_state *conn_state; + struct drm_connector *connector; + struct drm_crtc *crtc_from_state; + + for_each_connector_in_state( + state, + connector, + conn_state, + i) { + crtc_from_state = + from_state_var ? + conn_state->crtc : + connector->state->crtc; + + if (crtc_from_state == crtc) + return to_amdgpu_connector(connector); + } + + return NULL; +} + +static int dm_display_resume(struct drm_device *ddev) +{ + int ret = 0; + struct drm_connector *connector; + + struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); + struct drm_plane *plane; + struct drm_crtc *crtc; + struct amdgpu_connector *aconnector; + struct drm_connector_state *conn_state; + + if (!state) + return ENOMEM; + + state->acquire_ctx = ddev->mode_config.acquire_ctx; + + /* Construct an atomic state to restore previous display setting */ + + /* + * Attach connectors to drm_atomic_state + * Should be done in the first place in order to make connectors + * available in state during crtc state processing. It is used for + * making decision if crtc should be disabled in case sink got + * disconnected. + * + * Connectors state crtc with NULL dc_sink should be cleared, because it + * will fail validation during commit + */ + list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + conn_state = drm_atomic_get_connector_state(state, connector); + + ret = PTR_ERR_OR_ZERO(conn_state); + if (ret) + goto err; + } + + /* Attach crtcs to drm_atomic_state*/ + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + struct drm_crtc_state *crtc_state = + drm_atomic_get_crtc_state(state, crtc); + + ret = PTR_ERR_OR_ZERO(crtc_state); + if (ret) + goto err; + + /* force a restore */ + crtc_state->mode_changed = true; + } + + + /* Attach planes to drm_atomic_state */ + list_for_each_entry(plane, &ddev->mode_config.plane_list, head) { + + struct drm_crtc *crtc; + struct drm_gem_object *obj; + struct drm_framebuffer *fb; + struct amdgpu_framebuffer *afb; + struct amdgpu_bo *rbo; + int r; + struct drm_plane_state *plane_state = drm_atomic_get_plane_state(state, plane); + + ret = PTR_ERR_OR_ZERO(plane_state); + if (ret) + goto err; + + crtc = plane_state->crtc; + fb = plane_state->fb; + + if (!crtc || !crtc->state || !crtc->state->active) + continue; + + if (!fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + /* + * Pin back the front buffers, cursor buffer was already pinned + * back in amdgpu_resume_kms + */ + + afb = to_amdgpu_framebuffer(fb); + + obj = afb->obj; + rbo = gem_to_amdgpu_bo(obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL); + + amdgpu_bo_unreserve(rbo); + + if (unlikely(r != 0)) { + DRM_ERROR("Failed to pin framebuffer\n"); + return r; + } + + } + + + /* Call commit internally with the state we just constructed */ + ret = drm_atomic_commit(state); + if (!ret) + return 0; + +err: + DRM_ERROR("Restoring old state failed with %i\n", ret); + drm_atomic_state_put(state); + + return ret; +} + +static int dm_resume(void *handle) +{ + struct amdgpu_device *adev = handle; + struct amdgpu_display_manager *dm = &adev->dm; + + /* power on hardware */ + dc_set_power_state( + dm->dc, + DC_ACPI_CM_POWER_STATE_D0, + DC_VIDEO_POWER_ON); + + return 0; +} + +int amdgpu_dm_display_resume(struct amdgpu_device *adev ) +{ + struct drm_device *ddev = adev->ddev; + struct amdgpu_display_manager *dm = &adev->dm; + struct amdgpu_connector *aconnector; + struct drm_connector *connector; + int ret = 0; + struct drm_crtc *crtc; + + /* program HPD filter */ + dc_resume(dm->dc); + + /* On resume we need to rewrite the MSTM control bits to enamble MST*/ + s3_handle_mst(ddev, false); + + /* + * early enable HPD Rx IRQ, should be done before set mode as short + * pulse interrupts are used for MST + */ + amdgpu_dm_irq_resume_early(adev); + + drm_modeset_lock_all(ddev); + list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + if (acrtc->target) + drm_crtc_vblank_on(crtc); + } + drm_modeset_unlock_all(ddev); + + /* Do detection*/ + list_for_each_entry(connector, + &ddev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + + /* + * this is the case when traversing through already created + * MST connectors, should be skipped + */ + if (aconnector->mst_port) + continue; + + dc_link_detect(aconnector->dc_link, false); + aconnector->dc_sink = NULL; + amdgpu_dm_update_connector_after_detect(aconnector); + } + + drm_modeset_lock_all(ddev); + ret = dm_display_resume(ddev); + drm_modeset_unlock_all(ddev); + + amdgpu_dm_irq_resume(adev); + + return ret; +} + +static const struct amd_ip_funcs amdgpu_dm_funcs = { + .name = "dm", + .early_init = dm_early_init, + .late_init = NULL, + .sw_init = dm_sw_init, + .sw_fini = dm_sw_fini, + .hw_init = dm_hw_init, + .hw_fini = dm_hw_fini, + .suspend = dm_suspend, + .resume = dm_resume, + .is_idle = dm_is_idle, + .wait_for_idle = dm_wait_for_idle, + .check_soft_reset = dm_check_soft_reset, + .soft_reset = dm_soft_reset, + .set_clockgating_state = dm_set_clockgating_state, + .set_powergating_state = dm_set_powergating_state, +}; + +const struct amdgpu_ip_block_version dm_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_DCE, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &amdgpu_dm_funcs, +}; + +/* TODO: it is temporary non-const, should fixed later */ +static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { + .atomic_check = amdgpu_dm_atomic_check, + .atomic_commit = amdgpu_dm_atomic_commit +}; + +void amdgpu_dm_update_connector_after_detect( + struct amdgpu_connector *aconnector) +{ + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + const struct dc_sink *sink; + + /* MST handled by drm_mst framework */ + if (aconnector->mst_mgr.mst_state == true) + return; + + + sink = aconnector->dc_link->local_sink; + + /* Edid mgmt connector gets first update only in mode_valid hook and then + * the connector sink is set to either fake or physical sink depends on link status. + * don't do it here if u are during boot + */ + if (aconnector->base.force != DRM_FORCE_UNSPECIFIED + && aconnector->dc_em_sink) { + + /* For S3 resume with headless use eml_sink to fake target + * because on resume connecotr->sink is set ti NULL + */ + mutex_lock(&dev->mode_config.mutex); + + if (sink) { + if (aconnector->dc_sink) + amdgpu_dm_remove_sink_from_freesync_module( + connector); + aconnector->dc_sink = sink; + amdgpu_dm_add_sink_to_freesync_module( + connector, aconnector->edid); + } else { + amdgpu_dm_remove_sink_from_freesync_module(connector); + if (!aconnector->dc_sink) + aconnector->dc_sink = aconnector->dc_em_sink; + } + + mutex_unlock(&dev->mode_config.mutex); + return; + } + + /* + * TODO: temporary guard to look for proper fix + * if this sink is MST sink, we should not do anything + */ + if (sink && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + return; + + if (aconnector->dc_sink == sink) { + /* We got a DP short pulse (Link Loss, DP CTS, etc...). + * Do nothing!! */ + DRM_INFO("DCHPD: connector_id=%d: dc_sink didn't change.\n", + aconnector->connector_id); + return; + } + + DRM_INFO("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n", + aconnector->connector_id, aconnector->dc_sink, sink); + + mutex_lock(&dev->mode_config.mutex); + + /* 1. Update status of the drm connector + * 2. Send an event and let userspace tell us what to do */ + if (sink) { + /* TODO: check if we still need the S3 mode update workaround. + * If yes, put it here. */ + if (aconnector->dc_sink) + amdgpu_dm_remove_sink_from_freesync_module( + connector); + + aconnector->dc_sink = sink; + if (sink->dc_edid.length == 0) + aconnector->edid = NULL; + else { + aconnector->edid = + (struct edid *) sink->dc_edid.raw_edid; + + + drm_mode_connector_update_edid_property(connector, + aconnector->edid); + } + amdgpu_dm_add_sink_to_freesync_module(connector, aconnector->edid); + + } else { + amdgpu_dm_remove_sink_from_freesync_module(connector); + drm_mode_connector_update_edid_property(connector, NULL); + aconnector->num_modes = 0; + aconnector->dc_sink = NULL; + } + + mutex_unlock(&dev->mode_config.mutex); +} + +static void handle_hpd_irq(void *param) +{ + struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param; + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + + /* In case of failure or MST no need to update connector status or notify the OS + * since (for MST case) MST does this in it's own context. + */ + mutex_lock(&aconnector->hpd_lock); + if (dc_link_detect(aconnector->dc_link, false)) { + amdgpu_dm_update_connector_after_detect(aconnector); + + + drm_modeset_lock_all(dev); + dm_restore_drm_connector_state(dev, connector); + drm_modeset_unlock_all(dev); + + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + drm_kms_helper_hotplug_event(dev); + } + mutex_unlock(&aconnector->hpd_lock); + +} + +static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector) +{ + uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 }; + uint8_t dret; + bool new_irq_handled = false; + int dpcd_addr; + int dpcd_bytes_to_read; + + const int max_process_count = 30; + int process_count = 0; + + const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link); + + if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) { + dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT; + /* DPCD 0x200 - 0x201 for downstream IRQ */ + dpcd_addr = DP_SINK_COUNT; + } else { + dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI; + /* DPCD 0x2002 - 0x2005 for downstream IRQ */ + dpcd_addr = DP_SINK_COUNT_ESI; + } + + dret = drm_dp_dpcd_read( + &aconnector->dm_dp_aux.aux, + dpcd_addr, + esi, + dpcd_bytes_to_read); + + while (dret == dpcd_bytes_to_read && + process_count < max_process_count) { + uint8_t retry; + dret = 0; + + process_count++; + + DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) + /* handle HPD short pulse irq */ + if (aconnector->mst_mgr.mst_state) + drm_dp_mst_hpd_irq( + &aconnector->mst_mgr, + esi, + &new_irq_handled); +#endif + + if (new_irq_handled) { + /* ACK at DPCD to notify down stream */ + const int ack_dpcd_bytes_to_write = + dpcd_bytes_to_read - 1; + + for (retry = 0; retry < 3; retry++) { + uint8_t wret; + + wret = drm_dp_dpcd_write( + &aconnector->dm_dp_aux.aux, + dpcd_addr + 1, + &esi[1], + ack_dpcd_bytes_to_write); + if (wret == ack_dpcd_bytes_to_write) + break; + } + + /* check if there is new irq to be handle */ + dret = drm_dp_dpcd_read( + &aconnector->dm_dp_aux.aux, + dpcd_addr, + esi, + dpcd_bytes_to_read); + + new_irq_handled = false; + } else + break; + } + + if (process_count == max_process_count) + DRM_DEBUG_KMS("Loop exceeded max iterations\n"); +} + +static void handle_hpd_rx_irq(void *param) +{ + struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param; + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + const struct dc_link *dc_link = aconnector->dc_link; + bool is_mst_root_connector = aconnector->mst_mgr.mst_state; + + /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio + * conflict, after implement i2c helper, this mutex should be + * retired. + */ + if (aconnector->dc_link->type != dc_connection_mst_branch) + mutex_lock(&aconnector->hpd_lock); + + if (dc_link_handle_hpd_rx_irq(aconnector->dc_link) && + !is_mst_root_connector) { + /* Downstream Port status changed. */ + if (dc_link_detect(aconnector->dc_link, false)) { + amdgpu_dm_update_connector_after_detect(aconnector); + + + drm_modeset_lock_all(dev); + dm_restore_drm_connector_state(dev, connector); + drm_modeset_unlock_all(dev); + + drm_kms_helper_hotplug_event(dev); + } + } + if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || + (dc_link->type == dc_connection_mst_branch)) + dm_handle_hpd_rx_irq(aconnector); + + if (aconnector->dc_link->type != dc_connection_mst_branch) + mutex_unlock(&aconnector->hpd_lock); +} + +static void register_hpd_handlers(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_connector *connector; + struct amdgpu_connector *aconnector; + const struct dc_link *dc_link; + struct dc_interrupt_params int_params = {0}; + + int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; + int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + + aconnector = to_amdgpu_connector(connector); + dc_link = aconnector->dc_link; + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) { + int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT; + int_params.irq_source = dc_link->irq_source_hpd; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + handle_hpd_irq, + (void *) aconnector); + } + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) { + + /* Also register for DP short pulse (hpd_rx). */ + int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT; + int_params.irq_source = dc_link->irq_source_hpd_rx; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + handle_hpd_rx_irq, + (void *) aconnector); + } + } +} + +/* Register IRQ sources and initialize IRQ callbacks */ +static int dce110_register_irq_handlers(struct amdgpu_device *adev) +{ + struct dc *dc = adev->dm.dc; + struct common_irq_params *c_irq_params; + struct dc_interrupt_params int_params = {0}; + int r; + int i; + + int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; + int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; + + /* Actions of amdgpu_irq_add_id(): + * 1. Register a set() function with base driver. + * Base driver will call set() function to enable/disable an + * interrupt in DC hardware. + * 2. Register amdgpu_dm_irq_handler(). + * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts + * coming from DC hardware. + * amdgpu_dm_irq_handler() will re-direct the interrupt to DC + * for acknowledging and handling. */ + + for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; + i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->crtc_irq); + if (r) { + DRM_ERROR("Failed to add crtc irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_crtc_high_irq, c_irq_params); + } + + for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; + i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->pageflip_irq); + if (r) { + DRM_ERROR("Failed to add page flip irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_pflip_high_irq, c_irq_params); + + } + + /* HPD */ + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, + &adev->hpd_irq); + if (r) { + DRM_ERROR("Failed to add hpd irq id!\n"); + return r; + } + + register_hpd_handlers(adev); + + return 0; +} + +static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) +{ + int r; + + adev->mode_info.mode_config_initialized = true; + + amdgpu_dm_mode_funcs.fb_create = + amdgpu_mode_funcs.fb_create; + amdgpu_dm_mode_funcs.output_poll_changed = + amdgpu_mode_funcs.output_poll_changed; + + adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; + + adev->ddev->mode_config.max_width = 16384; + adev->ddev->mode_config.max_height = 16384; + + adev->ddev->mode_config.preferred_depth = 24; + adev->ddev->mode_config.prefer_shadow = 1; + /* indicate support of immediate flip */ + adev->ddev->mode_config.async_page_flip = true; + + adev->ddev->mode_config.fb_base = adev->mc.aper_base; + + r = amdgpu_modeset_create_props(adev); + if (r) + return r; + + return 0; +} + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + +static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) +{ + struct amdgpu_display_manager *dm = bl_get_data(bd); + + if (dc_link_set_backlight_level(dm->backlight_link, + bd->props.brightness, 0, 0)) + return 0; + else + return 1; +} + +static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) +{ + return bd->props.brightness; +} + +static const struct backlight_ops amdgpu_dm_backlight_ops = { + .get_brightness = amdgpu_dm_backlight_get_brightness, + .update_status = amdgpu_dm_backlight_update_status, +}; + +void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) +{ + char bl_name[16]; + struct backlight_properties props = { 0 }; + + props.max_brightness = AMDGPU_MAX_BL_LEVEL; + props.type = BACKLIGHT_RAW; + + snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", + dm->adev->ddev->primary->index); + + dm->backlight_dev = backlight_device_register(bl_name, + dm->adev->ddev->dev, + dm, + &amdgpu_dm_backlight_ops, + &props); + + if (NULL == dm->backlight_dev) + DRM_ERROR("DM: Backlight registration failed!\n"); + else + DRM_INFO("DM: Registered Backlight device: %s\n", bl_name); +} + +#endif + +/* In this architecture, the association + * connector -> encoder -> crtc + * id not really requried. The crtc and connector will hold the + * display_index as an abstraction to use with DAL component + * + * Returns 0 on success + */ +int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) +{ + struct amdgpu_display_manager *dm = &adev->dm; + uint32_t i; + struct amdgpu_connector *aconnector; + struct amdgpu_encoder *aencoder; + struct amdgpu_crtc *acrtc; + uint32_t link_cnt; + + link_cnt = dm->dc->caps.max_links; + + if (amdgpu_dm_mode_config_init(dm->adev)) { + DRM_ERROR("DM: Failed to initialize mode config\n"); + return -1; + } + + for (i = 0; i < dm->dc->caps.max_targets; i++) { + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); + if (!acrtc) + goto fail; + + if (amdgpu_dm_crtc_init( + dm, + acrtc, + i)) { + DRM_ERROR("KMS: Failed to initialize crtc\n"); + kfree(acrtc); + goto fail; + } + } + + dm->display_indexes_num = dm->dc->caps.max_targets; + + /* loops over all connectors on the board */ + for (i = 0; i < link_cnt; i++) { + + if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) { + DRM_ERROR( + "KMS: Cannot support more than %d display indexes\n", + AMDGPU_DM_MAX_DISPLAY_INDEX); + continue; + } + + aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); + if (!aconnector) + goto fail; + + aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); + if (!aencoder) { + goto fail_free_connector; + } + + if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { + DRM_ERROR("KMS: Failed to initialize encoder\n"); + goto fail_free_encoder; + } + + if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) { + DRM_ERROR("KMS: Failed to initialize connector\n"); + goto fail_free_connector; + } + + if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true)) + amdgpu_dm_update_connector_after_detect(aconnector); + } + + /* Software is initialized. Now we can register interrupt handlers. */ + switch (adev->asic_type) { + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_TONGA: + case CHIP_FIJI: + case CHIP_CARRIZO: + case CHIP_STONEY: + case CHIP_POLARIS11: + case CHIP_POLARIS10: + if (dce110_register_irq_handlers(dm->adev)) { + DRM_ERROR("DM: Failed to initialize IRQ\n"); + return -1; + } + break; + default: + DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); + return -1; + } + + drm_mode_config_reset(dm->ddev); + + return 0; +fail_free_encoder: + kfree(aencoder); +fail_free_connector: + kfree(aconnector); +fail: + return -1; +} + +void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) +{ + drm_mode_config_cleanup(dm->ddev); + return; +} + +/****************************************************************************** + * amdgpu_display_funcs functions + *****************************************************************************/ + +/** + * dm_bandwidth_update - program display watermarks + * + * @adev: amdgpu_device pointer + * + * Calculate and program the display watermarks and line buffer allocation. + */ +static void dm_bandwidth_update(struct amdgpu_device *adev) +{ + AMDGPU_DM_NOT_IMPL("%s\n", __func__); +} + +static void dm_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder, + u8 level) +{ + /* TODO: translate amdgpu_encoder to display_index and call DAL */ + AMDGPU_DM_NOT_IMPL("%s\n", __func__); +} + +static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder) +{ + /* TODO: translate amdgpu_encoder to display_index and call DAL */ + AMDGPU_DM_NOT_IMPL("%s\n", __func__); + return 0; +} + +/****************************************************************************** + * Page Flip functions + ******************************************************************************/ + +/** + * dm_page_flip - called by amdgpu_flip_work_func(), which is triggered + * via DRM IOCTL, by user mode. + * + * @adev: amdgpu_device pointer + * @crtc_id: crtc to cleanup pageflip on + * @crtc_base: new address of the crtc (GPU MC address) + * + * Does the actual pageflip (surface address update). + */ +static void dm_page_flip(struct amdgpu_device *adev, + int crtc_id, u64 crtc_base, bool async) +{ + struct amdgpu_crtc *acrtc; + struct dc_target *target; + struct dc_flip_addrs addr = { {0} }; + + /* + * TODO risk of concurrency issues + * + * This should guarded by the dal_mutex but we can't do this since the + * caller uses a spin_lock on event_lock. + * + * If we wait on the dal_mutex a second page flip interrupt might come, + * spin on the event_lock, disabling interrupts while it does so. At + * this point the core can no longer be pre-empted and return to the + * thread that waited on the dal_mutex and we're deadlocked. + * + * With multiple cores the same essentially happens but might just take + * a little longer to lock up all cores. + * + * The reason we should lock on dal_mutex is so that we can be sure + * nobody messes with acrtc->target after we read and check its value. + * + * We might be able to fix our concurrency issues with a work queue + * where we schedule all work items (mode_set, page_flip, etc.) and + * execute them one by one. Care needs to be taken to still deal with + * any potential concurrency issues arising from interrupt calls. + */ + + acrtc = adev->mode_info.crtcs[crtc_id]; + target = acrtc->target; + + /* + * Received a page flip call after the display has been reset. + * Just return in this case. Everything should be clean-up on reset. + */ + + if (!target) { + WARN_ON(1); + return; + } + + addr.address.grph.addr.low_part = lower_32_bits(crtc_base); + addr.address.grph.addr.high_part = upper_32_bits(crtc_base); + addr.flip_immediate = async; + + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", + __func__, + addr.address.grph.addr.high_part, + addr.address.grph.addr.low_part); + + dc_flip_surface_addrs( + adev->dm.dc, + dc_target_get_status(target)->surfaces, + &addr, 1); +} + +static int amdgpu_notify_freesync(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct mod_freesync_params freesync_params; + uint8_t num_targets; + uint8_t i; + struct dc_target *target; + + struct amdgpu_device *adev = dev->dev_private; + int r = 0; + + /* Get freesync enable flag from DRM */ + + num_targets = dc_get_current_target_count(adev->dm.dc); + + for (i = 0; i < num_targets; i++) { + + target = dc_get_target_at_index(adev->dm.dc, i); + + mod_freesync_update_state(adev->dm.freesync_module, + target->streams, + target->stream_count, + &freesync_params); + } + + return r; +} + +#ifdef CONFIG_DRM_AMDGPU_CIK +static const struct amdgpu_display_funcs dm_dce_v8_0_display_funcs = { + .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ + .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ + .vblank_wait = NULL, + .backlight_set_level = + dm_set_backlight_level,/* called unconditionally */ + .backlight_get_level = + dm_get_backlight_level,/* called unconditionally */ + .hpd_sense = NULL,/* called unconditionally */ + .hpd_set_polarity = NULL, /* called unconditionally */ + .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ + .page_flip = dm_page_flip, /* called unconditionally */ + .page_flip_get_scanoutpos = + dm_crtc_get_scanoutpos,/* called unconditionally */ + .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ + .add_connector = NULL, /* VBIOS parsing. DAL does it. */ + .notify_freesync = amdgpu_notify_freesync, +}; +#endif + +static const struct amdgpu_display_funcs dm_dce_v10_0_display_funcs = { + .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ + .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ + .vblank_wait = NULL, + .backlight_set_level = + dm_set_backlight_level,/* called unconditionally */ + .backlight_get_level = + dm_get_backlight_level,/* called unconditionally */ + .hpd_sense = NULL,/* called unconditionally */ + .hpd_set_polarity = NULL, /* called unconditionally */ + .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ + .page_flip = dm_page_flip, /* called unconditionally */ + .page_flip_get_scanoutpos = + dm_crtc_get_scanoutpos,/* called unconditionally */ + .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ + .add_connector = NULL, /* VBIOS parsing. DAL does it. */ + .notify_freesync = amdgpu_notify_freesync, + +}; + +static const struct amdgpu_display_funcs dm_dce_v11_0_display_funcs = { + .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ + .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ + .vblank_wait = NULL, + .backlight_set_level = + dm_set_backlight_level,/* called unconditionally */ + .backlight_get_level = + dm_get_backlight_level,/* called unconditionally */ + .hpd_sense = NULL,/* called unconditionally */ + .hpd_set_polarity = NULL, /* called unconditionally */ + .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ + .page_flip = dm_page_flip, /* called unconditionally */ + .page_flip_get_scanoutpos = + dm_crtc_get_scanoutpos,/* called unconditionally */ + .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ + .add_connector = NULL, /* VBIOS parsing. DAL does it. */ + .notify_freesync = amdgpu_notify_freesync, + +}; + +#if defined(CONFIG_DEBUG_KERNEL_DC) + +static ssize_t s3_debug_store( + struct device *device, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + int ret; + int s3_state; + struct pci_dev *pdev = to_pci_dev(device); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_dev->dev_private; + + ret = kstrtoint(buf, 0, &s3_state); + + if (ret == 0) { + if (s3_state) { + dm_resume(adev); + amdgpu_dm_display_resume(adev); + drm_kms_helper_hotplug_event(adev->ddev); + } else + dm_suspend(adev); + } + + return ret == 0 ? count : 0; +} + +DEVICE_ATTR_WO(s3_debug); + +#endif + +static int dm_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_dm_set_irq_funcs(adev); + + switch (adev->asic_type) { + case CHIP_BONAIRE: + case CHIP_HAWAII: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; +#ifdef CONFIG_DRM_AMDGPU_CIK + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v8_0_display_funcs; +#endif + break; + case CHIP_FIJI: + case CHIP_TONGA: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 7; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v10_0_display_funcs; + break; + case CHIP_CARRIZO: + adev->mode_info.num_crtc = 3; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 9; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; + break; + case CHIP_STONEY: + adev->mode_info.num_crtc = 2; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 9; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; + break; + case CHIP_POLARIS11: + adev->mode_info.num_crtc = 5; + adev->mode_info.num_hpd = 5; + adev->mode_info.num_dig = 5; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; + break; + case CHIP_POLARIS10: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; + break; + default: + DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); + return -EINVAL; + } + + /* Note: Do NOT change adev->audio_endpt_rreg and + * adev->audio_endpt_wreg because they are initialised in + * amdgpu_device_init() */ +#if defined(CONFIG_DEBUG_KERNEL_DC) + device_create_file( + adev->ddev->dev, + &dev_attr_s3_debug); +#endif + + return 0; +} + +bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) +{ + /* TODO */ + return true; +} + +bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) +{ + /* TODO */ + return true; +} + + diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h new file mode 100644 index 000000000000..1b54566f5da1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -0,0 +1,171 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AMDGPU_DM_H__ +#define __AMDGPU_DM_H__ + +/* +#include "linux/switch.h" +*/ + +/* + * This file contains the definition for amdgpu_display_manager + * and its API for amdgpu driver's use. + * This component provides all the display related functionality + * and this is the only component that calls DAL API. + * The API contained here intended for amdgpu driver use. + * The API that is called directly from KMS framework is located + * in amdgpu_dm_kms.h file + */ + +#define AMDGPU_DM_MAX_DISPLAY_INDEX 31 +/* +#include "include/amdgpu_dal_power_if.h" +#include "amdgpu_dm_irq.h" +*/ + +#include "irq_types.h" +#include "signal_types.h" + +/* Forward declarations */ +struct amdgpu_device; +struct drm_device; +struct amdgpu_dm_irq_handler_data; + +struct amdgpu_dm_prev_state { + struct drm_framebuffer *fb; + int32_t x; + int32_t y; + struct drm_display_mode mode; +}; + +struct common_irq_params { + struct amdgpu_device *adev; + enum dc_irq_source irq_src; +}; + +struct irq_list_head { + struct list_head head; + /* In case this interrupt needs post-processing, 'work' will be queued*/ + struct work_struct work; +}; + +struct amdgpu_display_manager { + struct dal *dal; + struct dc *dc; + struct cgs_device *cgs_device; + /* lock to be used when DAL is called from SYNC IRQ context */ + spinlock_t dal_lock; + + struct amdgpu_device *adev; /*AMD base driver*/ + struct drm_device *ddev; /*DRM base driver*/ + u16 display_indexes_num; + + struct amdgpu_dm_prev_state prev_state; + + /* + * 'irq_source_handler_table' holds a list of handlers + * per (DAL) IRQ source. + * + * Each IRQ source may need to be handled at different contexts. + * By 'context' we mean, for example: + * - The ISR context, which is the direct interrupt handler. + * - The 'deferred' context - this is the post-processing of the + * interrupt, but at a lower priority. + * + * Note that handlers are called in the same order as they were + * registered (FIFO). + */ + struct irq_list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER]; + struct list_head irq_handler_list_high_tab[DAL_IRQ_SOURCES_NUMBER]; + + struct common_irq_params + pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1]; + + struct common_irq_params + vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1]; + + /* this spin lock synchronizes access to 'irq_handler_list_table' */ + spinlock_t irq_handler_list_table_lock; + + /* Timer-related data. */ + struct list_head timer_handler_list; + struct workqueue_struct *timer_workqueue; + + /* Use dal_mutex for any activity which is NOT syncronized by + * DRM mode setting locks. + * For example: amdgpu_dm_hpd_low_irq() calls into DAL *without* + * DRM mode setting locks being acquired. This is where dal_mutex + * is acquired before calling into DAL. */ + struct mutex dal_mutex; + + struct backlight_device *backlight_dev; + + const struct dc_link *backlight_link; + + struct work_struct mst_hotplug_work; + + struct mod_freesync *freesync_module; +}; + +/* basic init/fini API */ +int amdgpu_dm_init(struct amdgpu_device *adev); + +void amdgpu_dm_fini(struct amdgpu_device *adev); + +void amdgpu_dm_destroy(void); + +/* initializes drm_device display related structures, based on the information + * provided by DAL. The drm strcutures are: drm_crtc, drm_connector, + * drm_encoder, drm_mode_config + * + * Returns 0 on success + */ +int amdgpu_dm_initialize_drm_device( + struct amdgpu_device *adev); + +/* removes and deallocates the drm structures, created by the above function */ +void amdgpu_dm_destroy_drm_device( + struct amdgpu_display_manager *dm); + +/* Locking/Mutex */ +bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm); + +bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm); + +/* Register "Backlight device" accessible by user-mode. */ +void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm); + +extern const struct amdgpu_ip_block_version dm_ip_block; + +void amdgpu_dm_update_connector_after_detect( + struct amdgpu_connector *aconnector); + +struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( + struct drm_atomic_state *state, + struct drm_crtc *crtc, + bool from_state_var); + +#endif /* __AMDGPU_DM_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c new file mode 100644 index 000000000000..d4e01b51f949 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -0,0 +1,484 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dm_services.h" +#include "amdgpu.h" +#include "dc.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_irq.h" +#include "amdgpu_dm_types.h" + +#include "dm_helpers.h" + +/* dm_helpers_parse_edid_caps + * + * Parse edid caps + * + * @edid: [in] pointer to edid + * edid_caps: [in] pointer to edid caps + * @return + * void + * */ +enum dc_edid_status dm_helpers_parse_edid_caps( + struct dc_context *ctx, + const struct dc_edid *edid, + struct dc_edid_caps *edid_caps) +{ + struct edid *edid_buf = (struct edid *) edid->raw_edid; + struct cea_sad *sads; + int sad_count = -1; + int sadb_count = -1; + int i = 0; + int j = 0; + uint8_t *sadb = NULL; + + enum dc_edid_status result = EDID_OK; + + if (!edid_caps || !edid) + return EDID_BAD_INPUT; + + if (!drm_edid_is_valid(edid_buf)) + result = EDID_BAD_CHECKSUM; + + edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] | + ((uint16_t) edid_buf->mfg_id[1])<<8; + edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] | + ((uint16_t) edid_buf->prod_code[1])<<8; + edid_caps->serial_number = edid_buf->serial; + edid_caps->manufacture_week = edid_buf->mfg_week; + edid_caps->manufacture_year = edid_buf->mfg_year; + + /* One of the four detailed_timings stores the monitor name. It's + * stored in an array of length 13. */ + for (i = 0; i < 4; i++) { + if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) { + while (j < 13 && edid_buf->detailed_timings[i].data.other_data.data.str.str[j]) { + if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n') + break; + + edid_caps->display_name[j] = + edid_buf->detailed_timings[i].data.other_data.data.str.str[j]; + j++; + } + } + } + + edid_caps->edid_hdmi = drm_detect_hdmi_monitor( + (struct edid *) edid->raw_edid); + + sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads); + if (sad_count <= 0) { + DRM_INFO("SADs count is: %d, don't need to read it\n", + sad_count); + return result; + } + + edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT; + for (i = 0; i < edid_caps->audio_mode_count; ++i) { + struct cea_sad *sad = &sads[i]; + + edid_caps->audio_modes[i].format_code = sad->format; + edid_caps->audio_modes[i].channel_count = sad->channels; + edid_caps->audio_modes[i].sample_rate = sad->freq; + edid_caps->audio_modes[i].sample_size = sad->byte2; + } + + sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb); + + if (sadb_count < 0) { + DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count); + sadb_count = 0; + } + + if (sadb_count) + edid_caps->speaker_flags = sadb[0]; + else + edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION; + + kfree(sads); + kfree(sadb); + + return result; +} + +static struct amdgpu_connector *get_connector_for_sink( + struct drm_device *dev, + const struct dc_sink *sink) +{ + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + if (aconnector->dc_sink == sink) + return aconnector; + } + + return NULL; +} + +static struct amdgpu_connector *get_connector_for_link( + struct drm_device *dev, + const struct dc_link *link) +{ + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + if (aconnector->dc_link == link) + return aconnector; + } + + return NULL; +} + +static void get_payload_table( + struct amdgpu_connector *aconnector, + struct dp_mst_stream_allocation_table *proposed_table) +{ + int i; + struct drm_dp_mst_topology_mgr *mst_mgr = + &aconnector->mst_port->mst_mgr; + + mutex_lock(&mst_mgr->payload_lock); + + proposed_table->stream_count = 0; + + /* number of active streams */ + for (i = 0; i < mst_mgr->max_payloads; i++) { + if (mst_mgr->payloads[i].num_slots == 0) + break; /* end of vcp_id table */ + + ASSERT(mst_mgr->payloads[i].payload_state != + DP_PAYLOAD_DELETE_LOCAL); + + if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL || + mst_mgr->payloads[i].payload_state == + DP_PAYLOAD_REMOTE) { + + struct dp_mst_stream_allocation *sa = + &proposed_table->stream_allocations[ + proposed_table->stream_count]; + + sa->slot_count = mst_mgr->payloads[i].num_slots; + sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi; + proposed_table->stream_count++; + } + } + + mutex_unlock(&mst_mgr->payload_lock); +} + +/* + * Writes payload allocation table in immediate downstream device. + */ +bool dm_helpers_dp_mst_write_payload_allocation_table( + struct dc_context *ctx, + const struct dc_stream *stream, + struct dp_mst_stream_allocation_table *proposed_table, + bool enable) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector; + struct drm_dp_mst_topology_mgr *mst_mgr; + struct drm_dp_mst_port *mst_port; + int slots = 0; + bool ret; + int clock; + int bpp = 0; + int pbn = 0; + + aconnector = get_connector_for_sink(dev, stream->sink); + + if (!aconnector || !aconnector->mst_port) + return false; + + mst_mgr = &aconnector->mst_port->mst_mgr; + + if (!mst_mgr->mst_state) + return false; + + mst_port = aconnector->port; + + if (enable) { + clock = stream->timing.pix_clk_khz; + + switch (stream->timing.display_color_depth) { + + case COLOR_DEPTH_666: + bpp = 6; + break; + case COLOR_DEPTH_888: + bpp = 8; + break; + case COLOR_DEPTH_101010: + bpp = 10; + break; + case COLOR_DEPTH_121212: + bpp = 12; + break; + case COLOR_DEPTH_141414: + bpp = 14; + break; + case COLOR_DEPTH_161616: + bpp = 16; + break; + default: + ASSERT(bpp != 0); + break; + } + + bpp = bpp * 3; + + /* TODO need to know link rate */ + + pbn = drm_dp_calc_pbn_mode(clock, bpp); + + slots = drm_dp_find_vcpi_slots(mst_mgr, pbn); + ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots); + + if (!ret) + return false; + + } else { + drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port); + } + + ret = drm_dp_update_payload_part1(mst_mgr); + + /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or + * AUX message. The sequence is slot 1-63 allocated sequence for each + * stream. AMD ASIC stream slot allocation should follow the same + * sequence. copy DRM MST allocation to dc */ + + get_payload_table(aconnector, proposed_table); + + if (ret) + return false; + + return true; +} + +/* + * Polls for ACT (allocation change trigger) handled and sends + * ALLOCATE_PAYLOAD message. + */ +bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( + struct dc_context *ctx, + const struct dc_stream *stream) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector; + struct drm_dp_mst_topology_mgr *mst_mgr; + int ret; + + aconnector = get_connector_for_sink(dev, stream->sink); + + if (!aconnector || !aconnector->mst_port) + return false; + + mst_mgr = &aconnector->mst_port->mst_mgr; + + if (!mst_mgr->mst_state) + return false; + + ret = drm_dp_check_act_status(mst_mgr); + + if (ret) + return false; + + return true; +} + +bool dm_helpers_dp_mst_send_payload_allocation( + struct dc_context *ctx, + const struct dc_stream *stream, + bool enable) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector; + struct drm_dp_mst_topology_mgr *mst_mgr; + struct drm_dp_mst_port *mst_port; + int ret; + + aconnector = get_connector_for_sink(dev, stream->sink); + + if (!aconnector || !aconnector->mst_port) + return false; + + mst_port = aconnector->port; + + mst_mgr = &aconnector->mst_port->mst_mgr; + + if (!mst_mgr->mst_state) + return false; + + ret = drm_dp_update_payload_part2(mst_mgr); + + if (ret) + return false; + + if (!enable) + drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port); + + return true; +} + +bool dm_helpers_dp_mst_start_top_mgr( + struct dc_context *ctx, + const struct dc_link *link, + bool boot) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return false; + } + + if (boot) { + DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + return true; + } + + DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + + return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0); +} + +void dm_helpers_dp_mst_stop_top_mgr( + struct dc_context *ctx, + const struct dc_link *link) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return; + } + + DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + + if (aconnector->mst_mgr.mst_state == true) + drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false); +} + +bool dm_helpers_dp_read_dpcd( + struct dc_context *ctx, + const struct dc_link *link, + uint32_t address, + uint8_t *data, + uint32_t size) +{ + + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return false; + } + + return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address, + data, size) > 0; +} + +bool dm_helpers_dp_write_dpcd( + struct dc_context *ctx, + const struct dc_link *link, + uint32_t address, + const uint8_t *data, + uint32_t size) +{ + + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return false; + } + + return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux, + address, (uint8_t *)data, size) > 0; +} + +bool dm_helpers_submit_i2c( + struct dc_context *ctx, + const struct dc_link *link, + struct i2c_command *cmd) +{ + struct amdgpu_device *adev = ctx->driver_context; + struct drm_device *dev = adev->ddev; + struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct i2c_msg *msgs; + int i = 0; + int num = cmd->number_of_payloads; + bool result; + + if (!aconnector) { + DRM_ERROR("Failed to found connector for link!"); + return false; + } + + msgs = kzalloc(num * sizeof(struct i2c_msg), GFP_KERNEL); + + if (!msgs) + return false; + + for (i = 0; i < num; i++) { + msgs[i].flags = cmd->payloads[i].write ? I2C_M_RD : 0; + msgs[i].addr = cmd->payloads[i].address; + msgs[i].len = cmd->payloads[i].length; + msgs[i].buf = cmd->payloads[i].data; + } + + result = i2c_transfer(&aconnector->i2c->base, msgs, num) == num; + + kfree(msgs); + + return result; +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c new file mode 100644 index 000000000000..20e074971bff --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -0,0 +1,829 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include + +#include "dm_services_types.h" +#include "dc.h" + +#include "amdgpu.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_irq.h" + +/****************************************************************************** + * Private declarations. + *****************************************************************************/ + +struct handler_common_data { + struct list_head list; + interrupt_handler handler; + void *handler_arg; + + /* DM which this handler belongs to */ + struct amdgpu_display_manager *dm; +}; + +struct amdgpu_dm_irq_handler_data { + struct handler_common_data hcd; + /* DAL irq source which registered for this interrupt. */ + enum dc_irq_source irq_source; +}; + +struct amdgpu_dm_timer_handler_data { + struct handler_common_data hcd; + struct delayed_work d_work; +}; + +#define DM_IRQ_TABLE_LOCK(adev, flags) \ + spin_lock_irqsave(&adev->dm.irq_handler_list_table_lock, flags) + +#define DM_IRQ_TABLE_UNLOCK(adev, flags) \ + spin_unlock_irqrestore(&adev->dm.irq_handler_list_table_lock, flags) + +/****************************************************************************** + * Private functions. + *****************************************************************************/ + +static void init_handler_common_data( + struct handler_common_data *hcd, + void (*ih)(void *), + void *args, + struct amdgpu_display_manager *dm) +{ + hcd->handler = ih; + hcd->handler_arg = args; + hcd->dm = dm; +} + +/** + * dm_irq_work_func - Handle an IRQ outside of the interrupt handler proper. + * + * @work: work struct + */ +static void dm_irq_work_func(struct work_struct *work) +{ + struct list_head *entry; + struct irq_list_head *irq_list_head = + container_of(work, struct irq_list_head, work); + struct list_head *handler_list = &irq_list_head->head; + struct amdgpu_dm_irq_handler_data *handler_data; + + list_for_each(entry, handler_list) { + handler_data = + list_entry( + entry, + struct amdgpu_dm_irq_handler_data, + hcd.list); + + DRM_DEBUG_KMS("DM_IRQ: work_func: for dal_src=%d\n", + handler_data->irq_source); + + DRM_DEBUG_KMS("DM_IRQ: schedule_work: for dal_src=%d\n", + handler_data->irq_source); + + handler_data->hcd.handler(handler_data->hcd.handler_arg); + } + + /* Call a DAL subcomponent which registered for interrupt notification + * at INTERRUPT_LOW_IRQ_CONTEXT. + * (The most common use is HPD interrupt) */ +} + +/** + * Remove a handler and return a pointer to hander list from which the + * handler was removed. + */ +static struct list_head *remove_irq_handler( + struct amdgpu_device *adev, + void *ih, + const struct dc_interrupt_params *int_params) +{ + struct list_head *hnd_list; + struct list_head *entry, *tmp; + struct amdgpu_dm_irq_handler_data *handler; + unsigned long irq_table_flags; + bool handler_removed = false; + enum dc_irq_source irq_source; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + irq_source = int_params->irq_source; + + switch (int_params->int_context) { + case INTERRUPT_HIGH_IRQ_CONTEXT: + hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source]; + break; + case INTERRUPT_LOW_IRQ_CONTEXT: + default: + hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head; + break; + } + + list_for_each_safe(entry, tmp, hnd_list) { + + handler = list_entry(entry, struct amdgpu_dm_irq_handler_data, + hcd.list); + + if (ih == handler) { + /* Found our handler. Remove it from the list. */ + list_del(&handler->hcd.list); + handler_removed = true; + break; + } + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + if (handler_removed == false) { + /* Not necessarily an error - caller may not + * know the context. */ + return NULL; + } + + kfree(handler); + + DRM_DEBUG_KMS( + "DM_IRQ: removed irq handler: %p for: dal_src=%d, irq context=%d\n", + ih, int_params->irq_source, int_params->int_context); + + return hnd_list; +} + +/* If 'handler_in == NULL' then remove ALL handlers. */ +static void remove_timer_handler( + struct amdgpu_device *adev, + struct amdgpu_dm_timer_handler_data *handler_in) +{ + struct amdgpu_dm_timer_handler_data *handler_temp; + struct list_head *handler_list; + struct list_head *entry, *tmp; + unsigned long irq_table_flags; + bool handler_removed = false; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + handler_list = &adev->dm.timer_handler_list; + + list_for_each_safe(entry, tmp, handler_list) { + /* Note that list_for_each_safe() guarantees that + * handler_temp is NOT null. */ + handler_temp = list_entry(entry, + struct amdgpu_dm_timer_handler_data, hcd.list); + + if (handler_in == NULL || handler_in == handler_temp) { + list_del(&handler_temp->hcd.list); + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + DRM_DEBUG_KMS("DM_IRQ: removing timer handler: %p\n", + handler_temp); + + if (handler_in == NULL) { + /* Since it is still in the queue, it must + * be cancelled. */ + cancel_delayed_work_sync(&handler_temp->d_work); + } + + kfree(handler_temp); + handler_removed = true; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + } + + if (handler_in == NULL) { + /* Remove ALL handlers. */ + continue; + } + + if (handler_in == handler_temp) { + /* Remove a SPECIFIC handler. + * Found our handler - we can stop here. */ + break; + } + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + if (handler_in != NULL && handler_removed == false) { + DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n", + handler_in); + } +} + +/** + * dm_timer_work_func - Handle a timer. + * + * @work: work struct + */ +static void dm_timer_work_func( + struct work_struct *work) +{ + struct amdgpu_dm_timer_handler_data *handler_data = + container_of(work, struct amdgpu_dm_timer_handler_data, + d_work.work); + + DRM_DEBUG_KMS("DM_IRQ: work_func: handler_data=%p\n", handler_data); + + /* Call a DAL subcomponent which registered for timer notification. */ + handler_data->hcd.handler(handler_data->hcd.handler_arg); + + /* We support only "single shot" timers. That means we must delete + * the handler after it was called. */ + remove_timer_handler(handler_data->hcd.dm->adev, handler_data); +} + +static bool validate_irq_registration_params( + struct dc_interrupt_params *int_params, + void (*ih)(void *)) +{ + if (NULL == int_params || NULL == ih) { + DRM_ERROR("DM_IRQ: invalid input!\n"); + return false; + } + + if (int_params->int_context >= INTERRUPT_CONTEXT_NUMBER) { + DRM_ERROR("DM_IRQ: invalid context: %d!\n", + int_params->int_context); + return false; + } + + if (!DAL_VALID_IRQ_SRC_NUM(int_params->irq_source)) { + DRM_ERROR("DM_IRQ: invalid irq_source: %d!\n", + int_params->irq_source); + return false; + } + + return true; +} + +static bool validate_irq_unregistration_params( + enum dc_irq_source irq_source, + irq_handler_idx handler_idx) +{ + if (DAL_INVALID_IRQ_HANDLER_IDX == handler_idx) { + DRM_ERROR("DM_IRQ: invalid handler_idx==NULL!\n"); + return false; + } + + if (!DAL_VALID_IRQ_SRC_NUM(irq_source)) { + DRM_ERROR("DM_IRQ: invalid irq_source:%d!\n", irq_source); + return false; + } + + return true; +} +/****************************************************************************** + * Public functions. + * + * Note: caller is responsible for input validation. + *****************************************************************************/ + +void *amdgpu_dm_irq_register_interrupt( + struct amdgpu_device *adev, + struct dc_interrupt_params *int_params, + void (*ih)(void *), + void *handler_args) +{ + struct list_head *hnd_list; + struct amdgpu_dm_irq_handler_data *handler_data; + unsigned long irq_table_flags; + enum dc_irq_source irq_source; + + if (false == validate_irq_registration_params(int_params, ih)) + return DAL_INVALID_IRQ_HANDLER_IDX; + + handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL); + if (!handler_data) { + DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n"); + return DAL_INVALID_IRQ_HANDLER_IDX; + } + + memset(handler_data, 0, sizeof(*handler_data)); + + init_handler_common_data(&handler_data->hcd, ih, handler_args, + &adev->dm); + + irq_source = int_params->irq_source; + + handler_data->irq_source = irq_source; + + /* Lock the list, add the handler. */ + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + switch (int_params->int_context) { + case INTERRUPT_HIGH_IRQ_CONTEXT: + hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source]; + break; + case INTERRUPT_LOW_IRQ_CONTEXT: + default: + hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head; + break; + } + + list_add_tail(&handler_data->hcd.list, hnd_list); + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + /* This pointer will be stored by code which requested interrupt + * registration. + * The same pointer will be needed in order to unregister the + * interrupt. */ + + DRM_DEBUG_KMS( + "DM_IRQ: added irq handler: %p for: dal_src=%d, irq context=%d\n", + handler_data, + irq_source, + int_params->int_context); + + return handler_data; +} + +void amdgpu_dm_irq_unregister_interrupt( + struct amdgpu_device *adev, + enum dc_irq_source irq_source, + void *ih) +{ + struct list_head *handler_list; + struct dc_interrupt_params int_params; + int i; + + if (false == validate_irq_unregistration_params(irq_source, ih)) + return; + + memset(&int_params, 0, sizeof(int_params)); + + int_params.irq_source = irq_source; + + for (i = 0; i < INTERRUPT_CONTEXT_NUMBER; i++) { + + int_params.int_context = i; + + handler_list = remove_irq_handler(adev, ih, &int_params); + + if (handler_list != NULL) + break; + } + + if (handler_list == NULL) { + /* If we got here, it means we searched all irq contexts + * for this irq source, but the handler was not found. */ + DRM_ERROR( + "DM_IRQ: failed to find irq handler:%p for irq_source:%d!\n", + ih, irq_source); + } +} + +int amdgpu_dm_irq_init( + struct amdgpu_device *adev) +{ + int src; + struct irq_list_head *lh; + + DRM_DEBUG_KMS("DM_IRQ\n"); + + spin_lock_init(&adev->dm.irq_handler_list_table_lock); + + for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) { + /* low context handler list init */ + lh = &adev->dm.irq_handler_list_low_tab[src]; + INIT_LIST_HEAD(&lh->head); + INIT_WORK(&lh->work, dm_irq_work_func); + + /* high context handler init */ + INIT_LIST_HEAD(&adev->dm.irq_handler_list_high_tab[src]); + } + + INIT_LIST_HEAD(&adev->dm.timer_handler_list); + + /* allocate and initialize the workqueue for DM timer */ + adev->dm.timer_workqueue = create_singlethread_workqueue( + "dm_timer_queue"); + if (adev->dm.timer_workqueue == NULL) { + DRM_ERROR("DM_IRQ: unable to create timer queue!\n"); + return -1; + } + + return 0; +} + +void amdgpu_dm_irq_register_timer( + struct amdgpu_device *adev, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args) +{ + unsigned long jf_delay; + struct list_head *handler_list; + struct amdgpu_dm_timer_handler_data *handler_data; + unsigned long irq_table_flags; + + handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL); + if (!handler_data) { + DRM_ERROR("DM_IRQ: failed to allocate timer handler!\n"); + return; + } + + memset(handler_data, 0, sizeof(*handler_data)); + + init_handler_common_data(&handler_data->hcd, ih, args, &adev->dm); + + INIT_DELAYED_WORK(&handler_data->d_work, dm_timer_work_func); + + /* Lock the list, add the handler. */ + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + handler_list = &adev->dm.timer_handler_list; + + list_add_tail(&handler_data->hcd.list, handler_list); + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + jf_delay = usecs_to_jiffies(int_params->micro_sec_interval); + + queue_delayed_work(adev->dm.timer_workqueue, &handler_data->d_work, + jf_delay); + + DRM_DEBUG_KMS("DM_IRQ: added handler:%p with micro_sec_interval=%u\n", + handler_data, int_params->micro_sec_interval); + return; +} + +/* DM IRQ and timer resource release */ +void amdgpu_dm_irq_fini( + struct amdgpu_device *adev) +{ + int src; + struct irq_list_head *lh; + DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n"); + + for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) { + + /* The handler was removed from the table, + * it means it is safe to flush all the 'work' + * (because no code can schedule a new one). */ + lh = &adev->dm.irq_handler_list_low_tab[src]; + flush_work(&lh->work); + } + + /* Cancel ALL timers and release handlers (if any). */ + remove_timer_handler(adev, NULL); + /* Release the queue itself. */ + destroy_workqueue(adev->dm.timer_workqueue); +} + +int amdgpu_dm_irq_suspend( + struct amdgpu_device *adev) +{ + int src; + struct list_head *hnd_list_h; + struct list_head *hnd_list_l; + unsigned long irq_table_flags; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + DRM_DEBUG_KMS("DM_IRQ: suspend\n"); + + /* disable HW interrupt */ + for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) { + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; + if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) + dc_interrupt_set(adev->dm.dc, src, false); + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + flush_work(&adev->dm.irq_handler_list_low_tab[src].work); + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + return 0; +} + +int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) +{ + int src; + struct list_head *hnd_list_h, *hnd_list_l; + unsigned long irq_table_flags; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + DRM_DEBUG_KMS("DM_IRQ: early resume\n"); + + /* re-enable short pulse interrupts HW interrupt */ + for (src = DC_IRQ_SOURCE_HPD1RX; src < DC_IRQ_SOURCE_HPD6RX + 1; src++) { + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; + if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) + dc_interrupt_set(adev->dm.dc, src, true); + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + return 0; +} + +int amdgpu_dm_irq_resume(struct amdgpu_device *adev) +{ + int src; + struct list_head *hnd_list_h, *hnd_list_l; + unsigned long irq_table_flags; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + DRM_DEBUG_KMS("DM_IRQ: resume\n"); + + /* re-enable HW interrupt */ + for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) { + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; + if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) + dc_interrupt_set(adev->dm.dc, src, true); + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + return 0; +} + +/** + * amdgpu_dm_irq_schedule_work - schedule all work items registered for the + * "irq_source". + */ +static void amdgpu_dm_irq_schedule_work( + struct amdgpu_device *adev, + enum dc_irq_source irq_source) +{ + unsigned long irq_table_flags; + struct work_struct *work = NULL; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + if (!list_empty(&adev->dm.irq_handler_list_low_tab[irq_source].head)) + work = &adev->dm.irq_handler_list_low_tab[irq_source].work; + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + + if (work) { + if (!schedule_work(work)) + DRM_INFO("amdgpu_dm_irq_schedule_work FAILED src %d\n", + irq_source); + } + +} + +/** amdgpu_dm_irq_immediate_work + * Callback high irq work immediately, don't send to work queue + */ +static void amdgpu_dm_irq_immediate_work( + struct amdgpu_device *adev, + enum dc_irq_source irq_source) +{ + struct amdgpu_dm_irq_handler_data *handler_data; + struct list_head *entry; + unsigned long irq_table_flags; + + DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + + list_for_each( + entry, + &adev->dm.irq_handler_list_high_tab[irq_source]) { + + handler_data = + list_entry( + entry, + struct amdgpu_dm_irq_handler_data, + hcd.list); + + /* Call a subcomponent which registered for immediate + * interrupt notification */ + handler_data->hcd.handler(handler_data->hcd.handler_arg); + } + + DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); +} + +/* + * amdgpu_dm_irq_handler + * + * Generic IRQ handler, calls all registered high irq work immediately, and + * schedules work for low irq + */ +int amdgpu_dm_irq_handler( + struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + + enum dc_irq_source src = + dc_interrupt_to_irq_source( + adev->dm.dc, + entry->src_id, + entry->src_data[0]); + + dc_interrupt_ack(adev->dm.dc, src); + + /* Call high irq work immediately */ + amdgpu_dm_irq_immediate_work(adev, src); + /*Schedule low_irq work */ + amdgpu_dm_irq_schedule_work(adev, src); + + return 0; +} + +static enum dc_irq_source amdgpu_dm_hpd_to_dal_irq_source(unsigned type) +{ + switch (type) { + case AMDGPU_HPD_1: + return DC_IRQ_SOURCE_HPD1; + case AMDGPU_HPD_2: + return DC_IRQ_SOURCE_HPD2; + case AMDGPU_HPD_3: + return DC_IRQ_SOURCE_HPD3; + case AMDGPU_HPD_4: + return DC_IRQ_SOURCE_HPD4; + case AMDGPU_HPD_5: + return DC_IRQ_SOURCE_HPD5; + case AMDGPU_HPD_6: + return DC_IRQ_SOURCE_HPD6; + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned type, + enum amdgpu_interrupt_state state) +{ + enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type); + bool st = (state == AMDGPU_IRQ_STATE_ENABLE); + + dc_interrupt_set(adev->dm.dc, src, st); + return 0; +} + +static inline int dm_irq_state( + struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state, + const enum irq_type dal_irq_type, + const char *func) +{ + bool st; + enum dc_irq_source irq_source; + + struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id]; + + if (!acrtc) { + DRM_ERROR( + "%s: crtc is NULL at id :%d\n", + func, + crtc_id); + return 0; + } + + irq_source = dal_irq_type + acrtc->otg_inst; + + st = (state == AMDGPU_IRQ_STATE_ENABLE); + + dc_interrupt_set(adev->dm.dc, irq_source, st); + return 0; +} + +static int amdgpu_dm_set_pflip_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state) +{ + return dm_irq_state( + adev, + source, + crtc_id, + state, + IRQ_TYPE_PFLIP, + __func__); +} + +static int amdgpu_dm_set_crtc_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state) +{ + return dm_irq_state( + adev, + source, + crtc_id, + state, + IRQ_TYPE_VUPDATE, + __func__); +} + +static const struct amdgpu_irq_src_funcs dm_crtc_irq_funcs = { + .set = amdgpu_dm_set_crtc_irq_state, + .process = amdgpu_dm_irq_handler, +}; + +static const struct amdgpu_irq_src_funcs dm_pageflip_irq_funcs = { + .set = amdgpu_dm_set_pflip_irq_state, + .process = amdgpu_dm_irq_handler, +}; + +static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = { + .set = amdgpu_dm_set_hpd_irq_state, + .process = amdgpu_dm_irq_handler, +}; + +void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST; + adev->crtc_irq.funcs = &dm_crtc_irq_funcs; + + adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST; + adev->pageflip_irq.funcs = &dm_pageflip_irq_funcs; + + adev->hpd_irq.num_types = AMDGPU_HPD_LAST; + adev->hpd_irq.funcs = &dm_hpd_irq_funcs; +} + +/* + * amdgpu_dm_hpd_init - hpd setup callback. + * + * @adev: amdgpu_device pointer + * + * Setup the hpd pins used by the card (evergreen+). + * Enable the pin, set the polarity, and enable the hpd interrupts. + */ +void amdgpu_dm_hpd_init(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + const struct dc_link *dc_link = amdgpu_connector->dc_link; + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) { + dc_interrupt_set(adev->dm.dc, + dc_link->irq_source_hpd, + true); + } + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) { + dc_interrupt_set(adev->dm.dc, + dc_link->irq_source_hpd_rx, + true); + } + } +} + +/** + * amdgpu_dm_hpd_fini - hpd tear down callback. + * + * @adev: amdgpu_device pointer + * + * Tear down the hpd pins used by the card (evergreen+). + * Disable the hpd interrupts. + */ +void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + const struct dc_link *dc_link = amdgpu_connector->dc_link; + + dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false); + + if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) { + dc_interrupt_set(adev->dm.dc, + dc_link->irq_source_hpd_rx, + false); + } + } +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h new file mode 100644 index 000000000000..9339861c8897 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -0,0 +1,122 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __AMDGPU_DM_IRQ_H__ +#define __AMDGPU_DM_IRQ_H__ + +#include "irq_types.h" /* DAL irq definitions */ + +/* + * Display Manager IRQ-related interfaces (for use by DAL). + */ + +/** + * amdgpu_dm_irq_init - Initialize internal structures of 'amdgpu_dm_irq'. + * + * This function should be called exactly once - during DM initialization. + * + * Returns: + * 0 - success + * non-zero - error + */ +int amdgpu_dm_irq_init( + struct amdgpu_device *adev); + +/** + * amdgpu_dm_irq_fini - deallocate internal structures of 'amdgpu_dm_irq'. + * + * This function should be called exactly once - during DM destruction. + * + */ +void amdgpu_dm_irq_fini( + struct amdgpu_device *adev); + +/** + * amdgpu_dm_irq_register_interrupt - register irq handler for Display block. + * + * @adev: AMD DRM device + * @int_params: parameters for the irq + * @ih: pointer to the irq hander function + * @handler_args: arguments which will be passed to ih + * + * Returns: + * IRQ Handler Index on success. + * NULL on failure. + * + * Cannot be called from an interrupt handler. + */ +void *amdgpu_dm_irq_register_interrupt( + struct amdgpu_device *adev, + struct dc_interrupt_params *int_params, + void (*ih)(void *), + void *handler_args); + +/** + * amdgpu_dm_irq_unregister_interrupt - unregister handler which was registered + * by amdgpu_dm_irq_register_interrupt(). + * + * @adev: AMD DRM device. + * @ih_index: irq handler index which was returned by + * amdgpu_dm_irq_register_interrupt + */ +void amdgpu_dm_irq_unregister_interrupt( + struct amdgpu_device *adev, + enum dc_irq_source irq_source, + void *ih_index); + +void amdgpu_dm_irq_register_timer( + struct amdgpu_device *adev, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args); + +/** + * amdgpu_dm_irq_handler + * Generic IRQ handler, calls all registered high irq work immediately, and + * schedules work for low irq + */ +int amdgpu_dm_irq_handler( + struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry); + +void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev); + +void amdgpu_dm_hpd_init(struct amdgpu_device *adev); +void amdgpu_dm_hpd_fini(struct amdgpu_device *adev); + +/** + * amdgpu_dm_irq_suspend - disable ASIC interrupt during suspend. + * + */ +int amdgpu_dm_irq_suspend(struct amdgpu_device *adev); + +/** + * amdgpu_dm_irq_resume_early - enable HPDRX ASIC interrupts during resume. + * amdgpu_dm_irq_resume - enable ASIC interrupt during resume. + * + */ +int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev); +int amdgpu_dm_irq_resume(struct amdgpu_device *adev); + +#endif /* __AMDGPU_DM_IRQ_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c new file mode 100644 index 000000000000..e4d94d4c215d --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -0,0 +1,443 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include +#include +#include "dm_services.h" +#include "amdgpu.h" +#include "amdgpu_dm_types.h" +#include "amdgpu_dm_mst_types.h" + +#include "dc.h" +#include "dm_helpers.h" + +/* #define TRACE_DPCD */ + +#ifdef TRACE_DPCD +#define SIDE_BAND_MSG(address) (address >= DP_SIDEBAND_MSG_DOWN_REQ_BASE && address < DP_SINK_COUNT_ESI) + +static inline char *side_band_msg_type_to_str(uint32_t address) +{ + static char str[10] = {0}; + + if (address < DP_SIDEBAND_MSG_UP_REP_BASE) + strcpy(str, "DOWN_REQ"); + else if (address < DP_SIDEBAND_MSG_DOWN_REP_BASE) + strcpy(str, "UP_REP"); + else if (address < DP_SIDEBAND_MSG_UP_REQ_BASE) + strcpy(str, "DOWN_REP"); + else + strcpy(str, "UP_REQ"); + + return str; +} + +void log_dpcd(uint8_t type, + uint32_t address, + uint8_t *data, + uint32_t size, + bool res) +{ + DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n", + (type == DP_AUX_NATIVE_READ) || + (type == DP_AUX_I2C_READ) ? + "Read" : "Write", + address, + SIDE_BAND_MSG(address) ? + side_band_msg_type_to_str(address) : "Nop", + res ? "OK" : "Fail"); + + if (res) { + print_hex_dump(KERN_INFO, "Body: ", DUMP_PREFIX_NONE, 16, 1, data, size, false); + } +} +#endif + +static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) +{ + struct pci_dev *pdev = to_pci_dev(aux->dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_dev->dev_private; + struct dc *dc = adev->dm.dc; + bool res; + + switch (msg->request) { + case DP_AUX_NATIVE_READ: + res = dc_read_dpcd( + dc, + TO_DM_AUX(aux)->link_index, + msg->address, + msg->buffer, + msg->size); + break; + case DP_AUX_NATIVE_WRITE: + res = dc_write_dpcd( + dc, + TO_DM_AUX(aux)->link_index, + msg->address, + msg->buffer, + msg->size); + break; + default: + return 0; + } + +#ifdef TRACE_DPCD + log_dpcd(msg->request, + msg->address, + msg->buffer, + msg->size, + res); +#endif + + return msg->size; +} + +static enum drm_connector_status +dm_dp_mst_detect(struct drm_connector *connector, bool force) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_connector *master = aconnector->mst_port; + + enum drm_connector_status status = + drm_dp_mst_detect_port( + connector, + &master->mst_mgr, + aconnector->port); + + /* + * we do not want to make this connector connected until we have edid on + * it + */ + if (status == connector_status_connected && + !aconnector->port->cached_edid) + status = connector_status_disconnected; + + return status; +} + +static void +dm_dp_mst_connector_destroy(struct drm_connector *connector) +{ + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + struct amdgpu_encoder *amdgpu_encoder = amdgpu_connector->mst_encoder; + + drm_encoder_cleanup(&amdgpu_encoder->base); + kfree(amdgpu_encoder); + drm_connector_cleanup(connector); + kfree(amdgpu_connector); +} + +static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { + .detect = dm_dp_mst_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = dm_dp_mst_connector_destroy, + .reset = amdgpu_dm_connector_funcs_reset, + .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_set_property = amdgpu_dm_connector_atomic_set_property +}; + +static int dm_dp_mst_get_modes(struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + int ret = 0; + + ret = drm_add_edid_modes(&aconnector->base, aconnector->edid); + + drm_edid_to_eld(&aconnector->base, aconnector->edid); + + return ret; +} + +static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector) +{ + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + + return &amdgpu_connector->mst_encoder->base; +} + +static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = { + .get_modes = dm_dp_mst_get_modes, + .mode_valid = amdgpu_dm_connector_mode_valid, + .best_encoder = dm_mst_best_encoder, +}; + +static struct amdgpu_encoder * +dm_dp_create_fake_mst_encoder(struct amdgpu_connector *connector) +{ + struct drm_device *dev = connector->base.dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_encoder *amdgpu_encoder; + struct drm_encoder *encoder; + const struct drm_connector_helper_funcs *connector_funcs = + connector->base.helper_private; + struct drm_encoder *enc_master = + connector_funcs->best_encoder(&connector->base); + + DRM_DEBUG_KMS("enc master is %p\n", enc_master); + amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL); + if (!amdgpu_encoder) + return NULL; + + encoder = &amdgpu_encoder->base; + encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); + + drm_encoder_init( + dev, + &amdgpu_encoder->base, + NULL, + DRM_MODE_ENCODER_DPMST, + NULL); + + drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs); + + return amdgpu_encoder; +} + +static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + const char *pathprop) +{ + struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr); + struct drm_device *dev = master->base.dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_connector *aconnector; + struct drm_connector *connector; + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + if (aconnector->mst_port == master + && !aconnector->port) { + DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n", + aconnector, connector->base.id, aconnector->mst_port); + + aconnector->port = port; + drm_mode_connector_set_path_property(connector, pathprop); + + drm_modeset_unlock(&dev->mode_config.connection_mutex); + return &aconnector->base; + } + } + drm_modeset_unlock(&dev->mode_config.connection_mutex); + + aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); + if (!aconnector) + return NULL; + + connector = &aconnector->base; + aconnector->port = port; + aconnector->mst_port = master; + + if (drm_connector_init( + dev, + connector, + &dm_dp_mst_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort)) { + kfree(aconnector); + return NULL; + } + drm_connector_helper_add(connector, &dm_dp_mst_connector_helper_funcs); + + amdgpu_dm_connector_init_helper( + &adev->dm, + aconnector, + DRM_MODE_CONNECTOR_DisplayPort, + master->dc_link, + master->connector_id); + + aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master); + + /* + * TODO: understand why this one is needed + */ + drm_object_attach_property( + &connector->base, + dev->mode_config.path_property, + 0); + drm_object_attach_property( + &connector->base, + dev->mode_config.tile_property, + 0); + + drm_mode_connector_set_path_property(connector, pathprop); + + /* + * Initialize connector state before adding the connectror to drm and + * framebuffer lists + */ + amdgpu_dm_connector_funcs_reset(connector); + + DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n", + aconnector, connector->base.id, aconnector->mst_port); + + DRM_DEBUG_KMS(":%d\n", connector->base.id); + + return connector; +} + +static void dm_dp_destroy_mst_connector( + struct drm_dp_mst_topology_mgr *mgr, + struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n", + aconnector, connector->base.id, aconnector->mst_port); + + aconnector->port = NULL; + if (aconnector->dc_sink) { + amdgpu_dm_remove_sink_from_freesync_module(connector); + dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink); + dc_sink_release(aconnector->dc_sink); + aconnector->dc_sink = NULL; + } + if (aconnector->edid) { + kfree(aconnector->edid); + aconnector->edid = NULL; + } + + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); +} + +static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) +{ + struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr); + struct drm_device *dev = master->base.dev; + struct amdgpu_device *adev = dev->dev_private; + struct drm_connector *connector; + struct amdgpu_connector *aconnector; + struct edid *edid; + + drm_modeset_lock_all(dev); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + aconnector = to_amdgpu_connector(connector); + if (aconnector->port && + aconnector->port->pdt != DP_PEER_DEVICE_NONE && + aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING && + !aconnector->dc_sink) { + /* + * This is plug in case, where port has been created but + * sink hasn't been created yet + */ + if (!aconnector->edid) { + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST}; + edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); + + if (!edid) { + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); + continue; + } + + aconnector->edid = edid; + + aconnector->dc_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + if (aconnector->dc_sink) + amdgpu_dm_add_sink_to_freesync_module( + connector, + edid); + + dm_restore_drm_connector_state(connector->dev, connector); + } else + edid = aconnector->edid; + + DRM_DEBUG_KMS("edid retrieved %p\n", edid); + + drm_mode_connector_update_edid_property( + &aconnector->base, + aconnector->edid); + } + } + drm_modeset_unlock_all(dev); + + schedule_work(&adev->dm.mst_hotplug_work); +} + +static void dm_dp_mst_register_connector(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + int i; + + drm_modeset_lock_all(dev); + if (adev->mode_info.rfbdev) { + /*Do not add if already registered in past*/ + for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) { + if (adev->mode_info.rfbdev->helper.connector_info[i]->connector + == connector) { + drm_modeset_unlock_all(dev); + return; + } + } + + drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); + } + else + DRM_ERROR("adev->mode_info.rfbdev is NULL\n"); + + drm_modeset_unlock_all(dev); + + drm_connector_register(connector); + +} + +static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { + .add_connector = dm_dp_add_mst_connector, + .destroy_connector = dm_dp_destroy_mst_connector, + .hotplug = dm_dp_mst_hotplug, + .register_connector = dm_dp_mst_register_connector +}; + +void amdgpu_dm_initialize_mst_connector( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector) +{ + aconnector->dm_dp_aux.aux.name = "dmdc"; + aconnector->dm_dp_aux.aux.dev = dm->adev->dev; + aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer; + aconnector->dm_dp_aux.link_index = aconnector->connector_id; + + drm_dp_aux_register(&aconnector->dm_dp_aux.aux); + aconnector->mst_mgr.cbs = &dm_mst_cbs; + drm_dp_mst_topology_mgr_init( + &aconnector->mst_mgr, + dm->adev->ddev, + &aconnector->dm_dp_aux.aux, + 16, + 4, + aconnector->connector_id); +} + diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h new file mode 100644 index 000000000000..6130d62ac65c --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -0,0 +1,36 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_AMDGPU_DM_MST_TYPES_H__ +#define __DAL_AMDGPU_DM_MST_TYPES_H__ + +struct amdgpu_display_manager; +struct amdgpu_connector; + +void amdgpu_dm_initialize_mst_connector( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector); + +#endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c new file mode 100644 index 000000000000..9d5125951acd --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -0,0 +1,463 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include +#include + +#include +#include +#include +#include "dm_services.h" +#include "amdgpu.h" +#include "amdgpu_dm.h" +#include "amdgpu_dm_irq.h" +#include "amdgpu_dm_types.h" +#include "amdgpu_pm.h" + +#define dm_alloc(size) kzalloc(size, GFP_KERNEL) +#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) +#define dm_free(ptr) kfree(ptr) + +/****************************************************************************** + * IRQ Interfaces. + *****************************************************************************/ + +void dal_register_timer_interrupt( + struct dc_context *ctx, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args) +{ + struct amdgpu_device *adev = ctx->driver_context; + + if (!adev || !int_params) { + DRM_ERROR("DM_IRQ: invalid input!\n"); + return; + } + + if (int_params->int_context != INTERRUPT_LOW_IRQ_CONTEXT) { + /* only low irq ctx is supported. */ + DRM_ERROR("DM_IRQ: invalid context: %d!\n", + int_params->int_context); + return; + } + + amdgpu_dm_irq_register_timer(adev, int_params, ih, args); +} + +void dal_isr_acquire_lock(struct dc_context *ctx) +{ + /*TODO*/ +} + +void dal_isr_release_lock(struct dc_context *ctx) +{ + /*TODO*/ +} + +/****************************************************************************** + * End-of-IRQ Interfaces. + *****************************************************************************/ + +bool dm_get_platform_info(struct dc_context *ctx, + struct platform_info_params *params) +{ + /*TODO*/ + return false; +} + +bool dm_write_persistent_data(struct dc_context *ctx, + const struct dc_sink *sink, + const char *module_name, + const char *key_name, + void *params, + unsigned int size, + struct persistent_data_flag *flag) +{ + /*TODO implement*/ + return false; +} + +bool dm_read_persistent_data(struct dc_context *ctx, + const struct dc_sink *sink, + const char *module_name, + const char *key_name, + void *params, + unsigned int size, + struct persistent_data_flag *flag) +{ + /*TODO implement*/ + return false; +} + +void dm_delay_in_microseconds(struct dc_context *ctx, + unsigned int microSeconds) +{ + /*TODO implement*/ + return; +} + +/**** power component interfaces ****/ + +bool dm_pp_pre_dce_clock_change( + struct dc_context *ctx, + struct dm_pp_gpu_clock_range *requested_state, + struct dm_pp_gpu_clock_range *actual_state) +{ + /*TODO*/ + return false; +} + +bool dm_pp_apply_safe_state( + const struct dc_context *ctx) +{ + struct amdgpu_device *adev = ctx->driver_context; + + if (adev->pm.dpm_enabled) { + /* TODO: Does this require PreModeChange event to PPLIB? */ + } + + return true; +} + +bool dm_pp_apply_display_requirements( + const struct dc_context *ctx, + const struct dm_pp_display_configuration *pp_display_cfg) +{ + struct amdgpu_device *adev = ctx->driver_context; + + if (adev->pm.dpm_enabled) { + + memset(&adev->pm.pm_display_cfg, 0, + sizeof(adev->pm.pm_display_cfg)); + + adev->pm.pm_display_cfg.cpu_cc6_disable = + pp_display_cfg->cpu_cc6_disable; + + adev->pm.pm_display_cfg.cpu_pstate_disable = + pp_display_cfg->cpu_pstate_disable; + + adev->pm.pm_display_cfg.cpu_pstate_separation_time = + pp_display_cfg->cpu_pstate_separation_time; + + adev->pm.pm_display_cfg.nb_pstate_switch_disable = + pp_display_cfg->nb_pstate_switch_disable; + + adev->pm.pm_display_cfg.num_display = + pp_display_cfg->display_count; + adev->pm.pm_display_cfg.num_path_including_non_display = + pp_display_cfg->display_count; + + adev->pm.pm_display_cfg.min_core_set_clock = + pp_display_cfg->min_engine_clock_khz/10; + adev->pm.pm_display_cfg.min_core_set_clock_in_sr = + pp_display_cfg->min_engine_clock_deep_sleep_khz/10; + adev->pm.pm_display_cfg.min_mem_set_clock = + pp_display_cfg->min_memory_clock_khz/10; + + adev->pm.pm_display_cfg.multi_monitor_in_sync = + pp_display_cfg->all_displays_in_sync; + adev->pm.pm_display_cfg.min_vblank_time = + pp_display_cfg->avail_mclk_switch_time_us; + + adev->pm.pm_display_cfg.display_clk = + pp_display_cfg->disp_clk_khz/10; + + adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency = + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us; + + adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index; + adev->pm.pm_display_cfg.line_time_in_us = + pp_display_cfg->line_time_in_us; + + adev->pm.pm_display_cfg.vrefresh = pp_display_cfg->disp_configs[0].v_refresh; + adev->pm.pm_display_cfg.crossfire_display_index = -1; + adev->pm.pm_display_cfg.min_bus_bandwidth = 0; + + /* TODO: complete implementation of + * amd_powerplay_display_configuration_change(). + * Follow example of: + * PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c + * PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */ + amd_powerplay_display_configuration_change( + adev->powerplay.pp_handle, + &adev->pm.pm_display_cfg); + + /* TODO: replace by a separate call to 'apply display cfg'? */ + amdgpu_pm_compute_clocks(adev); + } + + return true; +} + +bool dc_service_get_system_clocks_range( + const struct dc_context *ctx, + struct dm_pp_gpu_clock_range *sys_clks) +{ + struct amdgpu_device *adev = ctx->driver_context; + + /* Default values, in case PPLib is not compiled-in. */ + sys_clks->mclk.max_khz = 800000; + sys_clks->mclk.min_khz = 800000; + + sys_clks->sclk.max_khz = 600000; + sys_clks->sclk.min_khz = 300000; + + if (adev->pm.dpm_enabled) { + sys_clks->mclk.max_khz = amdgpu_dpm_get_mclk(adev, false); + sys_clks->mclk.min_khz = amdgpu_dpm_get_mclk(adev, true); + + sys_clks->sclk.max_khz = amdgpu_dpm_get_sclk(adev, false); + sys_clks->sclk.min_khz = amdgpu_dpm_get_sclk(adev, true); + } + + return true; +} + +static void get_default_clock_levels( + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels *clks) +{ + uint32_t disp_clks_in_khz[6] = { + 300000, 400000, 496560, 626090, 685720, 757900 }; + uint32_t sclks_in_khz[6] = { + 300000, 360000, 423530, 514290, 626090, 720000 }; + uint32_t mclks_in_khz[2] = { 333000, 800000 }; + + switch (clk_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + clks->num_levels = 6; + memmove(clks->clocks_in_khz, disp_clks_in_khz, + sizeof(disp_clks_in_khz)); + break; + case DM_PP_CLOCK_TYPE_ENGINE_CLK: + clks->num_levels = 6; + memmove(clks->clocks_in_khz, sclks_in_khz, + sizeof(sclks_in_khz)); + break; + case DM_PP_CLOCK_TYPE_MEMORY_CLK: + clks->num_levels = 2; + memmove(clks->clocks_in_khz, mclks_in_khz, + sizeof(mclks_in_khz)); + break; + default: + clks->num_levels = 0; + break; + } +} + +static enum amd_pp_clock_type dc_to_pp_clock_type( + enum dm_pp_clock_type dm_pp_clk_type) +{ + enum amd_pp_clock_type amd_pp_clk_type = 0; + + switch (dm_pp_clk_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + amd_pp_clk_type = amd_pp_disp_clock; + break; + case DM_PP_CLOCK_TYPE_ENGINE_CLK: + amd_pp_clk_type = amd_pp_sys_clock; + break; + case DM_PP_CLOCK_TYPE_MEMORY_CLK: + amd_pp_clk_type = amd_pp_mem_clock; + break; + default: + DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n", + dm_pp_clk_type); + break; + } + + return amd_pp_clk_type; +} + +static void pp_to_dc_clock_levels( + const struct amd_pp_clocks *pp_clks, + struct dm_pp_clock_levels *dc_clks, + enum dm_pp_clock_type dc_clk_type) +{ + uint32_t i; + + if (pp_clks->count > DM_PP_MAX_CLOCK_LEVELS) { + DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n", + DC_DECODE_PP_CLOCK_TYPE(dc_clk_type), + pp_clks->count, + DM_PP_MAX_CLOCK_LEVELS); + + dc_clks->num_levels = DM_PP_MAX_CLOCK_LEVELS; + } else + dc_clks->num_levels = pp_clks->count; + + DRM_INFO("DM_PPLIB: values for %s clock\n", + DC_DECODE_PP_CLOCK_TYPE(dc_clk_type)); + + for (i = 0; i < dc_clks->num_levels; i++) { + DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]); + /* translate 10kHz to kHz */ + dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10; + } +} + +bool dm_pp_get_clock_levels_by_type( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels *dc_clks) +{ + struct amdgpu_device *adev = ctx->driver_context; + void *pp_handle = adev->powerplay.pp_handle; + struct amd_pp_clocks pp_clks = { 0 }; + struct amd_pp_simple_clock_info validation_clks = { 0 }; + uint32_t i; + + if (amd_powerplay_get_clock_by_type(pp_handle, + dc_to_pp_clock_type(clk_type), &pp_clks)) { + /* Error in pplib. Provide default values. */ + get_default_clock_levels(clk_type, dc_clks); + return true; + } + + pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type); + + if (amd_powerplay_get_display_mode_validation_clocks(pp_handle, + &validation_clks)) { + /* Error in pplib. Provide default values. */ + DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n"); + validation_clks.engine_max_clock = 72000; + validation_clks.memory_max_clock = 80000; + validation_clks.level = 0; + } + + DRM_INFO("DM_PPLIB: Validation clocks:\n"); + DRM_INFO("DM_PPLIB: engine_max_clock: %d\n", + validation_clks.engine_max_clock); + DRM_INFO("DM_PPLIB: memory_max_clock: %d\n", + validation_clks.memory_max_clock); + DRM_INFO("DM_PPLIB: level : %d\n", + validation_clks.level); + + /* Translate 10 kHz to kHz. */ + validation_clks.engine_max_clock *= 10; + validation_clks.memory_max_clock *= 10; + + /* Determine the highest non-boosted level from the Validation Clocks */ + if (clk_type == DM_PP_CLOCK_TYPE_ENGINE_CLK) { + for (i = 0; i < dc_clks->num_levels; i++) { + if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) { + /* This clock is higher the validation clock. + * Than means the previous one is the highest + * non-boosted one. */ + DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n", + dc_clks->num_levels, i + 1); + dc_clks->num_levels = i; + break; + } + } + } else if (clk_type == DM_PP_CLOCK_TYPE_MEMORY_CLK) { + for (i = 0; i < dc_clks->num_levels; i++) { + if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) { + DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n", + dc_clks->num_levels, i + 1); + dc_clks->num_levels = i; + break; + } + } + } + + return true; +} + +bool dm_pp_get_clock_levels_by_type_with_latency( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels_with_latency *clk_level_info) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_get_clock_levels_by_type_with_voltage( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels_with_voltage *clk_level_info) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_notify_wm_clock_changes( + const struct dc_context *ctx, + struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_apply_power_level_change_request( + const struct dc_context *ctx, + struct dm_pp_power_level_change_request *level_change_req) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_apply_clock_for_voltage_request( + const struct dc_context *ctx, + struct dm_pp_clock_for_voltage_req *clock_for_voltage_req) +{ + /* TODO: to be implemented */ + return false; +} + +bool dm_pp_get_static_clocks( + const struct dc_context *ctx, + struct dm_pp_static_clock_info *static_clk_info) +{ + /* TODO: to be implemented */ + return false; +} + +/**** end of power component interfaces ****/ + +/* Calls to notification */ + +void dal_notify_setmode_complete(struct dc_context *ctx, + uint32_t h_total, + uint32_t v_total, + uint32_t h_active, + uint32_t v_active, + uint32_t pix_clk_in_khz) +{ + /*TODO*/ +} +/* End of calls to notification */ + +long dm_get_pid(void) +{ + return current->pid; +} + +long dm_get_tgid(void) +{ + return current->tgid; +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c new file mode 100644 index 000000000000..c073f4558cf4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -0,0 +1,3150 @@ +/* + * Copyright 2012-13 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "amdgpu.h" +#include "amdgpu_pm.h" +#include "dm_services_types.h" + +// We need to #undef FRAME_SIZE and DEPRECATED because they conflict +// with ptrace-abi.h's #define's of them. +#undef FRAME_SIZE +#undef DEPRECATED + +#include "dc.h" + +#include "amdgpu_dm_types.h" +#include "amdgpu_dm_mst_types.h" + +#include "modules/inc/mod_freesync.h" + +struct dm_connector_state { + struct drm_connector_state base; + + enum amdgpu_rmx_type scaling; + uint8_t underscan_vborder; + uint8_t underscan_hborder; + bool underscan_enable; +}; + +#define to_dm_connector_state(x)\ + container_of((x), struct dm_connector_state, base) + + +void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); + kfree(encoder); +} + +static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { + .destroy = amdgpu_dm_encoder_destroy, +}; + +static void dm_set_cursor( + struct amdgpu_crtc *amdgpu_crtc, + uint64_t gpu_addr, + uint32_t width, + uint32_t height) +{ + struct dc_cursor_attributes attributes; + amdgpu_crtc->cursor_width = width; + amdgpu_crtc->cursor_height = height; + + attributes.address.high_part = upper_32_bits(gpu_addr); + attributes.address.low_part = lower_32_bits(gpu_addr); + attributes.width = width; + attributes.height = height; + attributes.x_hot = 0; + attributes.y_hot = 0; + attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; + attributes.rotation_angle = 0; + attributes.attribute_flags.value = 0; + + if (!dc_target_set_cursor_attributes( + amdgpu_crtc->target, + &attributes)) { + DRM_ERROR("DC failed to set cursor attributes\n"); + } +} + +static int dm_crtc_unpin_cursor_bo_old( + struct amdgpu_crtc *amdgpu_crtc) +{ + struct amdgpu_bo *robj; + int ret = 0; + + if (NULL != amdgpu_crtc && NULL != amdgpu_crtc->cursor_bo) { + robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); + + ret = amdgpu_bo_reserve(robj, false); + + if (likely(ret == 0)) { + ret = amdgpu_bo_unpin(robj); + + if (unlikely(ret != 0)) { + DRM_ERROR( + "%s: unpin failed (ret=%d), bo %p\n", + __func__, + ret, + amdgpu_crtc->cursor_bo); + } + + amdgpu_bo_unreserve(robj); + } else { + DRM_ERROR( + "%s: reserve failed (ret=%d), bo %p\n", + __func__, + ret, + amdgpu_crtc->cursor_bo); + } + + drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo); + amdgpu_crtc->cursor_bo = NULL; + } + + return ret; +} + +static int dm_crtc_pin_cursor_bo_new( + struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + struct amdgpu_bo **ret_obj) +{ + struct amdgpu_crtc *amdgpu_crtc; + struct amdgpu_bo *robj; + struct drm_gem_object *obj; + int ret = -EINVAL; + + if (NULL != crtc) { + struct drm_device *dev = crtc->dev; + struct amdgpu_device *adev = dev->dev_private; + uint64_t gpu_addr; + + amdgpu_crtc = to_amdgpu_crtc(crtc); + + obj = drm_gem_object_lookup(file_priv, handle); + + if (!obj) { + DRM_ERROR( + "Cannot find cursor object %x for crtc %d\n", + handle, + amdgpu_crtc->crtc_id); + goto release; + } + robj = gem_to_amdgpu_bo(obj); + + ret = amdgpu_bo_reserve(robj, false); + + if (unlikely(ret != 0)) { + drm_gem_object_unreference_unlocked(obj); + DRM_ERROR("dm_crtc_pin_cursor_bo_new ret %x, handle %x\n", + ret, handle); + goto release; + } + + ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, 0, + adev->mc.visible_vram_size, + &gpu_addr); + + if (ret == 0) { + amdgpu_crtc->cursor_addr = gpu_addr; + *ret_obj = robj; + } + amdgpu_bo_unreserve(robj); + if (ret) + drm_gem_object_unreference_unlocked(obj); + + } +release: + + return ret; +} + +static int dm_crtc_cursor_set( + struct drm_crtc *crtc, + struct drm_file *file_priv, + uint32_t handle, + uint32_t width, + uint32_t height) +{ + struct amdgpu_bo *new_cursor_bo; + struct dc_cursor_position position; + + int ret; + + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + ret = EINVAL; + new_cursor_bo = NULL; + + DRM_DEBUG_KMS( + "%s: crtc_id=%d with handle %d and size %d to %d, bo_object %p\n", + __func__, + amdgpu_crtc->crtc_id, + handle, + width, + height, + amdgpu_crtc->cursor_bo); + + if (!handle) { + /* turn off cursor */ + position.enable = false; + position.x = 0; + position.y = 0; + position.hot_spot_enable = false; + + if (amdgpu_crtc->target) { + /*set cursor visible false*/ + dc_target_set_cursor_position( + amdgpu_crtc->target, + &position); + } + /*unpin old cursor buffer and update cache*/ + ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); + goto release; + + } + + if ((width > amdgpu_crtc->max_cursor_width) || + (height > amdgpu_crtc->max_cursor_height)) { + DRM_ERROR( + "%s: bad cursor width or height %d x %d\n", + __func__, + width, + height); + goto release; + } + /*try to pin new cursor bo*/ + ret = dm_crtc_pin_cursor_bo_new(crtc, file_priv, handle, &new_cursor_bo); + /*if map not successful then return an error*/ + if (ret) + goto release; + + /*program new cursor bo to hardware*/ + dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height); + + /*un map old, not used anymore cursor bo , + * return memory and mapping back */ + dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); + + /*assign new cursor bo to our internal cache*/ + amdgpu_crtc->cursor_bo = &new_cursor_bo->gem_base; + +release: + return ret; + +} + +static int dm_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + int xorigin = 0, yorigin = 0; + struct dc_cursor_position position; + + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + + /* + * TODO: for cursor debugging unguard the following + */ +#if 0 + DRM_DEBUG_KMS( + "%s: x %d y %d c->x %d c->y %d\n", + __func__, + x, + y, + crtc->x, + crtc->y); +#endif + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + position.enable = true; + position.x = x; + position.y = y; + + position.hot_spot_enable = true; + position.x_hotspot = xorigin; + position.y_hotspot = yorigin; + + if (amdgpu_crtc->target) { + if (!dc_target_set_cursor_position( + amdgpu_crtc->target, + &position)) { + DRM_ERROR("DC failed to set cursor position\n"); + return -EINVAL; + } + } + + return 0; +} + +static void dm_crtc_cursor_reset(struct drm_crtc *crtc) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + + DRM_DEBUG_KMS( + "%s: with cursor_bo %p\n", + __func__, + amdgpu_crtc->cursor_bo); + + if (amdgpu_crtc->cursor_bo && amdgpu_crtc->target) { + dm_set_cursor( + amdgpu_crtc, + amdgpu_crtc->cursor_addr, + amdgpu_crtc->cursor_width, + amdgpu_crtc->cursor_height); + } +} +static bool fill_rects_from_plane_state( + const struct drm_plane_state *state, + struct dc_surface *surface) +{ + surface->src_rect.x = state->src_x >> 16; + surface->src_rect.y = state->src_y >> 16; + /*we ignore for now mantissa and do not to deal with floating pixels :(*/ + surface->src_rect.width = state->src_w >> 16; + + if (surface->src_rect.width == 0) + return false; + + surface->src_rect.height = state->src_h >> 16; + if (surface->src_rect.height == 0) + return false; + + surface->dst_rect.x = state->crtc_x; + surface->dst_rect.y = state->crtc_y; + + if (state->crtc_w == 0) + return false; + + surface->dst_rect.width = state->crtc_w; + + if (state->crtc_h == 0) + return false; + + surface->dst_rect.height = state->crtc_h; + + surface->clip_rect = surface->dst_rect; + + switch (state->rotation & DRM_MODE_ROTATE_MASK) { + case DRM_MODE_ROTATE_0: + surface->rotation = ROTATION_ANGLE_0; + break; + case DRM_MODE_ROTATE_90: + surface->rotation = ROTATION_ANGLE_90; + break; + case DRM_MODE_ROTATE_180: + surface->rotation = ROTATION_ANGLE_180; + break; + case DRM_MODE_ROTATE_270: + surface->rotation = ROTATION_ANGLE_270; + break; + default: + surface->rotation = ROTATION_ANGLE_0; + break; + } + + return true; +} +static bool get_fb_info( + const struct amdgpu_framebuffer *amdgpu_fb, + uint64_t *tiling_flags, + uint64_t *fb_location) +{ + struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); + int r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)){ + DRM_ERROR("Unable to reserve buffer\n"); + return false; + } + + if (fb_location) + *fb_location = amdgpu_bo_gpu_offset(rbo); + + if (tiling_flags) + amdgpu_bo_get_tiling_flags(rbo, tiling_flags); + + amdgpu_bo_unreserve(rbo); + + return true; +} +static void fill_plane_attributes_from_fb( + struct dc_surface *surface, + const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) +{ + uint64_t tiling_flags; + uint64_t fb_location = 0; + const struct drm_framebuffer *fb = &amdgpu_fb->base; + struct drm_format_name_buf format_name; + + get_fb_info( + amdgpu_fb, + &tiling_flags, + addReq == true ? &fb_location:NULL); + + surface->address.type = PLN_ADDR_TYPE_GRAPHICS; + surface->address.grph.addr.low_part = lower_32_bits(fb_location); + surface->address.grph.addr.high_part = upper_32_bits(fb_location); + + switch (fb->format->format) { + case DRM_FORMAT_C8: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; + break; + case DRM_FORMAT_RGB565: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; + break; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; + break; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; + break; + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; + break; + default: + DRM_ERROR("Unsupported screen format %s\n", + drm_get_format_name(fb->format->format, &format_name)); + return; + } + + memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); + + if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) + { + unsigned bankw, bankh, mtaspect, tile_split, num_banks; + + bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); + bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); + mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); + tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); + num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); + + /* XXX fix me for VI */ + surface->tiling_info.gfx8.num_banks = num_banks; + surface->tiling_info.gfx8.array_mode = + DC_ARRAY_2D_TILED_THIN1; + surface->tiling_info.gfx8.tile_split = tile_split; + surface->tiling_info.gfx8.bank_width = bankw; + surface->tiling_info.gfx8.bank_height = bankh; + surface->tiling_info.gfx8.tile_aspect = mtaspect; + surface->tiling_info.gfx8.tile_mode = + DC_ADDR_SURF_MICRO_TILING_DISPLAY; + } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) + == DC_ARRAY_1D_TILED_THIN1) { + surface->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; + } + + surface->tiling_info.gfx8.pipe_config = + AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); + + surface->plane_size.grph.surface_size.x = 0; + surface->plane_size.grph.surface_size.y = 0; + surface->plane_size.grph.surface_size.width = fb->width; + surface->plane_size.grph.surface_size.height = fb->height; + surface->plane_size.grph.surface_pitch = + fb->pitches[0] / fb->format->cpp[0]; + + surface->visible = true; + surface->scaling_quality.h_taps_c = 0; + surface->scaling_quality.v_taps_c = 0; + + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_SRGB; + /* is this needed? is surface zeroed at allocation? */ + surface->scaling_quality.h_taps = 0; + surface->scaling_quality.v_taps = 0; + surface->stereo_format = PLANE_STEREO_FORMAT_NONE; + +} + +#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 + +static void fill_gamma_from_crtc( + const struct drm_crtc *crtc, + struct dc_surface *dc_surface) +{ + int i; + struct dc_gamma *gamma; + struct drm_crtc_state *state = crtc->state; + struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; + + gamma = dc_create_gamma(); + + if (gamma == NULL) + return; + + for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { + gamma->gamma_ramp_rgb256x3x16.red[i] = lut[i].red; + gamma->gamma_ramp_rgb256x3x16.green[i] = lut[i].green; + gamma->gamma_ramp_rgb256x3x16.blue[i] = lut[i].blue; + } + + gamma->type = GAMMA_RAMP_RBG256X3X16; + gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); + + dc_surface->gamma_correction = gamma; +} + +static void fill_plane_attributes( + struct dc_surface *surface, + struct drm_plane_state *state, bool addrReq) +{ + const struct amdgpu_framebuffer *amdgpu_fb = + to_amdgpu_framebuffer(state->fb); + const struct drm_crtc *crtc = state->crtc; + + fill_rects_from_plane_state(state, surface); + fill_plane_attributes_from_fb( + surface, + amdgpu_fb, + addrReq); + + /* In case of gamma set, update gamma value */ + if (state->crtc->state->gamma_lut) { + fill_gamma_from_crtc(crtc, surface); + } +} + +/*****************************************************************************/ + +struct amdgpu_connector *aconnector_from_drm_crtc_id( + const struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_connector *connector; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_connector *aconnector; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + + aconnector = to_amdgpu_connector(connector); + + if (aconnector->base.state->crtc != &acrtc->base) + continue; + + /* Found the connector */ + return aconnector; + } + + /* If we get here, not found. */ + return NULL; +} + +static void update_stream_scaling_settings( + const struct drm_display_mode *mode, + const struct dm_connector_state *dm_state, + const struct dc_stream *stream) +{ + struct amdgpu_device *adev = dm_state->base.crtc->dev->dev_private; + enum amdgpu_rmx_type rmx_type; + + struct rect src = { 0 }; /* viewport in target space*/ + struct rect dst = { 0 }; /* stream addressable area */ + + /* Full screen scaling by default */ + src.width = mode->hdisplay; + src.height = mode->vdisplay; + dst.width = stream->timing.h_addressable; + dst.height = stream->timing.v_addressable; + + rmx_type = dm_state->scaling; + if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { + if (src.width * dst.height < + src.height * dst.width) { + /* height needs less upscaling/more downscaling */ + dst.width = src.width * + dst.height / src.height; + } else { + /* width needs less upscaling/more downscaling */ + dst.height = src.height * + dst.width / src.width; + } + } else if (rmx_type == RMX_CENTER) { + dst = src; + } + + dst.x = (stream->timing.h_addressable - dst.width) / 2; + dst.y = (stream->timing.v_addressable - dst.height) / 2; + + if (dm_state->underscan_enable) { + dst.x += dm_state->underscan_hborder / 2; + dst.y += dm_state->underscan_vborder / 2; + dst.width -= dm_state->underscan_hborder; + dst.height -= dm_state->underscan_vborder; + } + + adev->dm.dc->stream_funcs.stream_update_scaling(adev->dm.dc, stream, &src, &dst); + + DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", + dst.x, dst.y, dst.width, dst.height); + +} + +static void dm_dc_surface_commit( + struct dc *dc, + struct drm_crtc *crtc) +{ + struct dc_surface *dc_surface; + const struct dc_surface *dc_surfaces[1]; + const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct dc_target *dc_target = acrtc->target; + + if (!dc_target) { + dm_error( + "%s: Failed to obtain target on crtc (%d)!\n", + __func__, + acrtc->crtc_id); + goto fail; + } + + dc_surface = dc_create_surface(dc); + + if (!dc_surface) { + dm_error( + "%s: Failed to create a surface!\n", + __func__); + goto fail; + } + + /* Surface programming */ + fill_plane_attributes(dc_surface, crtc->primary->state, true); + + dc_surfaces[0] = dc_surface; + + if (false == dc_commit_surfaces_to_target( + dc, + dc_surfaces, + 1, + dc_target)) { + dm_error( + "%s: Failed to attach surface!\n", + __func__); + } + + dc_surface_release(dc_surface); +fail: + return; +} + +static enum dc_color_depth convert_color_depth_from_display_info( + const struct drm_connector *connector) +{ + uint32_t bpc = connector->display_info.bpc; + + /* Limited color depth to 8bit + * TODO: Still need to handle deep color*/ + if (bpc > 8) + bpc = 8; + + switch (bpc) { + case 0: + /* Temporary Work around, DRM don't parse color depth for + * EDID revision before 1.4 + * TODO: Fix edid parsing + */ + return COLOR_DEPTH_888; + case 6: + return COLOR_DEPTH_666; + case 8: + return COLOR_DEPTH_888; + case 10: + return COLOR_DEPTH_101010; + case 12: + return COLOR_DEPTH_121212; + case 14: + return COLOR_DEPTH_141414; + case 16: + return COLOR_DEPTH_161616; + default: + return COLOR_DEPTH_UNDEFINED; + } +} + +static enum dc_aspect_ratio get_aspect_ratio( + const struct drm_display_mode *mode_in) +{ + int32_t width = mode_in->crtc_hdisplay * 9; + int32_t height = mode_in->crtc_vdisplay * 16; + if ((width - height) < 10 && (width - height) > -10) + return ASPECT_RATIO_16_9; + else + return ASPECT_RATIO_4_3; +} + +static enum dc_color_space get_output_color_space( + const struct dc_crtc_timing *dc_crtc_timing) +{ + enum dc_color_space color_space = COLOR_SPACE_SRGB; + + switch (dc_crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + case PIXEL_ENCODING_YCBCR444: + case PIXEL_ENCODING_YCBCR420: + { + /* + * 27030khz is the separation point between HDTV and SDTV + * according to HDMI spec, we use YCbCr709 and YCbCr601 + * respectively + */ + if (dc_crtc_timing->pix_clk_khz > 27030) { + if (dc_crtc_timing->flags.Y_ONLY) + color_space = + COLOR_SPACE_YCBCR709_LIMITED; + else + color_space = COLOR_SPACE_YCBCR709; + } else { + if (dc_crtc_timing->flags.Y_ONLY) + color_space = + COLOR_SPACE_YCBCR601_LIMITED; + else + color_space = COLOR_SPACE_YCBCR601; + } + + } + break; + case PIXEL_ENCODING_RGB: + color_space = COLOR_SPACE_SRGB; + break; + + default: + WARN_ON(1); + break; + } + + return color_space; +} + +/*****************************************************************************/ + +static void fill_stream_properties_from_drm_display_mode( + struct dc_stream *stream, + const struct drm_display_mode *mode_in, + const struct drm_connector *connector) +{ + struct dc_crtc_timing *timing_out = &stream->timing; + memset(timing_out, 0, sizeof(struct dc_crtc_timing)); + + timing_out->h_border_left = 0; + timing_out->h_border_right = 0; + timing_out->v_border_top = 0; + timing_out->v_border_bottom = 0; + /* TODO: un-hardcode */ + + if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) + && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) + timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; + else + timing_out->pixel_encoding = PIXEL_ENCODING_RGB; + + timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE; + timing_out->display_color_depth = convert_color_depth_from_display_info( + connector); + timing_out->scan_type = SCANNING_TYPE_NODATA; + timing_out->hdmi_vic = 0; + timing_out->vic = drm_match_cea_mode(mode_in); + + timing_out->h_addressable = mode_in->crtc_hdisplay; + timing_out->h_total = mode_in->crtc_htotal; + timing_out->h_sync_width = + mode_in->crtc_hsync_end - mode_in->crtc_hsync_start; + timing_out->h_front_porch = + mode_in->crtc_hsync_start - mode_in->crtc_hdisplay; + timing_out->v_total = mode_in->crtc_vtotal; + timing_out->v_addressable = mode_in->crtc_vdisplay; + timing_out->v_front_porch = + mode_in->crtc_vsync_start - mode_in->crtc_vdisplay; + timing_out->v_sync_width = + mode_in->crtc_vsync_end - mode_in->crtc_vsync_start; + timing_out->pix_clk_khz = mode_in->crtc_clock; + timing_out->aspect_ratio = get_aspect_ratio(mode_in); + if (mode_in->flags & DRM_MODE_FLAG_PHSYNC) + timing_out->flags.HSYNC_POSITIVE_POLARITY = 1; + if (mode_in->flags & DRM_MODE_FLAG_PVSYNC) + timing_out->flags.VSYNC_POSITIVE_POLARITY = 1; + + stream->output_color_space = get_output_color_space(timing_out); + +} + +static void fill_audio_info( + struct audio_info *audio_info, + const struct drm_connector *drm_connector, + const struct dc_sink *dc_sink) +{ + int i = 0; + int cea_revision = 0; + const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps; + + audio_info->manufacture_id = edid_caps->manufacturer_id; + audio_info->product_id = edid_caps->product_id; + + cea_revision = drm_connector->display_info.cea_rev; + + while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && + edid_caps->display_name[i]) { + audio_info->display_name[i] = edid_caps->display_name[i]; + i++; + } + + if(cea_revision >= 3) { + audio_info->mode_count = edid_caps->audio_mode_count; + + for (i = 0; i < audio_info->mode_count; ++i) { + audio_info->modes[i].format_code = + (enum audio_format_code) + (edid_caps->audio_modes[i].format_code); + audio_info->modes[i].channel_count = + edid_caps->audio_modes[i].channel_count; + audio_info->modes[i].sample_rates.all = + edid_caps->audio_modes[i].sample_rate; + audio_info->modes[i].sample_size = + edid_caps->audio_modes[i].sample_size; + } + } + + audio_info->flags.all = edid_caps->speaker_flags; + + /* TODO: We only check for the progressive mode, check for interlace mode too */ + if(drm_connector->latency_present[0]) { + audio_info->video_latency = drm_connector->video_latency[0]; + audio_info->audio_latency = drm_connector->audio_latency[0]; + } + + /* TODO: For DP, video and audio latency should be calculated from DPCD caps */ + +} + +static void copy_crtc_timing_for_drm_display_mode( + const struct drm_display_mode *src_mode, + struct drm_display_mode *dst_mode) +{ + dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay; + dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay; + dst_mode->crtc_clock = src_mode->crtc_clock; + dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start; + dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end; + dst_mode->crtc_hsync_start= src_mode->crtc_hsync_start; + dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; + dst_mode->crtc_htotal = src_mode->crtc_htotal; + dst_mode->crtc_hskew = src_mode->crtc_hskew; + dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start;; + dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end;; + dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start;; + dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end;; + dst_mode->crtc_vtotal = src_mode->crtc_vtotal;; +} + +static void decide_crtc_timing_for_drm_display_mode( + struct drm_display_mode *drm_mode, + const struct drm_display_mode *native_mode, + bool scale_enabled) +{ + if (scale_enabled) { + copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); + } else if (native_mode->clock == drm_mode->clock && + native_mode->htotal == drm_mode->htotal && + native_mode->vtotal == drm_mode->vtotal) { + copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); + } else { + /* no scaling nor amdgpu inserted, no need to patch */ + } +} + +static struct dc_target *create_target_for_sink( + const struct amdgpu_connector *aconnector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state) +{ + struct drm_display_mode *preferred_mode = NULL; + const struct drm_connector *drm_connector; + struct dc_target *target = NULL; + struct dc_stream *stream; + struct drm_display_mode mode = *drm_mode; + bool native_mode_found = false; + + if (NULL == aconnector) { + DRM_ERROR("aconnector is NULL!\n"); + goto drm_connector_null; + } + + if (NULL == dm_state) { + DRM_ERROR("dm_state is NULL!\n"); + goto dm_state_null; + } + + drm_connector = &aconnector->base; + stream = dc_create_stream_for_sink(aconnector->dc_sink); + + if (NULL == stream) { + DRM_ERROR("Failed to create stream for sink!\n"); + goto stream_create_fail; + } + + list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { + /* Search for preferred mode */ + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { + native_mode_found = true; + break; + } + } + if (!native_mode_found) + preferred_mode = list_first_entry_or_null( + &aconnector->base.modes, + struct drm_display_mode, + head); + + if (NULL == preferred_mode) { + /* This may not be an error, the use case is when we we have no + * usermode calls to reset and set mode upon hotplug. In this + * case, we call set mode ourselves to restore the previous mode + * and the modelist may not be filled in in time. + */ + DRM_INFO("No preferred mode found\n"); + } else { + decide_crtc_timing_for_drm_display_mode( + &mode, preferred_mode, + dm_state->scaling != RMX_OFF); + } + + fill_stream_properties_from_drm_display_mode(stream, + &mode, &aconnector->base); + update_stream_scaling_settings(&mode, dm_state, stream); + + fill_audio_info( + &stream->audio_info, + drm_connector, + aconnector->dc_sink); + + target = dc_create_target_for_streams(&stream, 1); + dc_stream_release(stream); + + if (NULL == target) { + DRM_ERROR("Failed to create target with streams!\n"); + goto target_create_fail; + } + +dm_state_null: +drm_connector_null: +target_create_fail: +stream_create_fail: + return target; +} + +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) +{ + drm_crtc_cleanup(crtc); + kfree(crtc); +} + +/* Implemented only the options currently availible for the driver */ +static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .cursor_set = dm_crtc_cursor_set, + .cursor_move = dm_crtc_cursor_move, + .destroy = amdgpu_dm_crtc_destroy, + .gamma_set = drm_atomic_helper_legacy_gamma_set, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; + +static enum drm_connector_status +amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) +{ + bool connected; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + /* Notes: + * 1. This interface is NOT called in context of HPD irq. + * 2. This interface *is called* in context of user-mode ioctl. Which + * makes it a bad place for *any* MST-related activit. */ + + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + connected = (aconnector->dc_sink != NULL); + else + connected = (aconnector->base.force == DRM_FORCE_ON); + + return (connected ? connector_status_connected : + connector_status_disconnected); +} + +int amdgpu_dm_connector_atomic_set_property( + struct drm_connector *connector, + struct drm_connector_state *connector_state, + struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct dm_connector_state *dm_old_state = + to_dm_connector_state(connector->state); + struct dm_connector_state *dm_new_state = + to_dm_connector_state(connector_state); + + struct drm_crtc_state *new_crtc_state; + struct drm_crtc *crtc; + int i; + int ret = -EINVAL; + + if (property == dev->mode_config.scaling_mode_property) { + enum amdgpu_rmx_type rmx_type; + + switch (val) { + case DRM_MODE_SCALE_CENTER: + rmx_type = RMX_CENTER; + break; + case DRM_MODE_SCALE_ASPECT: + rmx_type = RMX_ASPECT; + break; + case DRM_MODE_SCALE_FULLSCREEN: + rmx_type = RMX_FULL; + break; + case DRM_MODE_SCALE_NONE: + default: + rmx_type = RMX_OFF; + break; + } + + if (dm_old_state->scaling == rmx_type) + return 0; + + dm_new_state->scaling = rmx_type; + ret = 0; + } else if (property == adev->mode_info.underscan_hborder_property) { + dm_new_state->underscan_hborder = val; + ret = 0; + } else if (property == adev->mode_info.underscan_vborder_property) { + dm_new_state->underscan_vborder = val; + ret = 0; + } else if (property == adev->mode_info.underscan_property) { + dm_new_state->underscan_enable = val; + ret = 0; + } + + for_each_crtc_in_state( + connector_state->state, + crtc, + new_crtc_state, + i) { + + if (crtc == connector_state->crtc) { + struct drm_plane_state *plane_state; + + /* + * Bit of magic done here. We need to ensure + * that planes get update after mode is set. + * So, we need to add primary plane to state, + * and this way atomic_update would be called + * for it + */ + plane_state = + drm_atomic_get_plane_state( + connector_state->state, + crtc->primary); + + if (!plane_state) + return -EINVAL; + } + } + + return ret; +} + +void amdgpu_dm_connector_destroy(struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + const struct dc_link *link = aconnector->dc_link; + struct amdgpu_device *adev = connector->dev->dev_private; + struct amdgpu_display_manager *dm = &adev->dm; +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) { + backlight_device_unregister(dm->backlight_dev); + dm->backlight_dev = NULL; + } + + } +#endif + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) +{ + struct dm_connector_state *state = + to_dm_connector_state(connector->state); + + kfree(state); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + + if (state) { + state->scaling = RMX_OFF; + state->underscan_enable = false; + state->underscan_hborder = 0; + state->underscan_vborder = 0; + + connector->state = &state->base; + connector->state->connector = connector; + } +} + +struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( + struct drm_connector *connector) +{ + struct dm_connector_state *state = + to_dm_connector_state(connector->state); + + struct dm_connector_state *new_state = + kmemdup(state, sizeof(*state), GFP_KERNEL); + + if (new_state) { + __drm_atomic_helper_connector_duplicate_state(connector, + &new_state->base); + return &new_state->base; + } + + return NULL; +} + +static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { + .reset = amdgpu_dm_connector_funcs_reset, + .detect = amdgpu_dm_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = amdgpu_dm_connector_destroy, + .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_set_property = amdgpu_dm_connector_atomic_set_property +}; + +static struct drm_encoder *best_encoder(struct drm_connector *connector) +{ + int enc_id = connector->encoder_ids[0]; + struct drm_mode_object *obj; + struct drm_encoder *encoder; + + DRM_DEBUG_KMS("Finding the best encoder\n"); + + /* pick the encoder ids */ + if (enc_id) { + obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); + if (!obj) { + DRM_ERROR("Couldn't find a matching encoder for our connector\n"); + return NULL; + } + encoder = obj_to_encoder(obj); + return encoder; + } + DRM_ERROR("No encoder id\n"); + return NULL; +} + +static int get_modes(struct drm_connector *connector) +{ + return amdgpu_dm_connector_get_modes(connector); +} + +static void create_eml_sink(struct amdgpu_connector *aconnector) +{ + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_VIRTUAL + }; + struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data; + + if (!aconnector->base.edid_blob_ptr || + !aconnector->base.edid_blob_ptr->data) { + DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", + aconnector->base.name); + + aconnector->base.force = DRM_FORCE_OFF; + aconnector->base.override_edid = false; + return; + } + + aconnector->edid = edid; + + aconnector->dc_em_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + + if (aconnector->base.force + == DRM_FORCE_ON) + aconnector->dc_sink = aconnector->dc_link->local_sink ? + aconnector->dc_link->local_sink : + aconnector->dc_em_sink; +} + +static void handle_edid_mgmt(struct amdgpu_connector *aconnector) +{ + struct dc_link *link = (struct dc_link *)aconnector->dc_link; + + /* In case of headless boot with force on for DP managed connector + * Those settings have to be != 0 to get initial modeset + */ + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) { + link->verified_link_cap.lane_count = LANE_COUNT_FOUR; + link->verified_link_cap.link_rate = LINK_RATE_HIGH2; + } + + + aconnector->base.override_edid = true; + create_eml_sink(aconnector); +} + +int amdgpu_dm_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode) +{ + int result = MODE_ERROR; + const struct dc_sink *dc_sink; + struct amdgpu_device *adev = connector->dev->dev_private; + struct dc_validation_set val_set = { 0 }; + /* TODO: Unhardcode stream count */ + struct dc_stream *streams[1]; + struct dc_target *target; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || + (mode->flags & DRM_MODE_FLAG_DBLSCAN)) + return result; + + /* Only run this the first time mode_valid is called to initilialize + * EDID mgmt + */ + if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && + !aconnector->dc_em_sink) + handle_edid_mgmt(aconnector); + + dc_sink = to_amdgpu_connector(connector)->dc_sink; + + if (NULL == dc_sink) { + DRM_ERROR("dc_sink is NULL!\n"); + goto stream_create_fail; + } + + streams[0] = dc_create_stream_for_sink(dc_sink); + + if (NULL == streams[0]) { + DRM_ERROR("Failed to create stream for sink!\n"); + goto stream_create_fail; + } + + drm_mode_set_crtcinfo(mode, 0); + fill_stream_properties_from_drm_display_mode(streams[0], mode, connector); + + target = dc_create_target_for_streams(streams, 1); + val_set.target = target; + + if (NULL == val_set.target) { + DRM_ERROR("Failed to create target with stream!\n"); + goto target_create_fail; + } + + val_set.surface_count = 0; + streams[0]->src.width = mode->hdisplay; + streams[0]->src.height = mode->vdisplay; + streams[0]->dst = streams[0]->src; + + if (dc_validate_resources(adev->dm.dc, &val_set, 1)) + result = MODE_OK; + + dc_target_release(target); +target_create_fail: + dc_stream_release(streams[0]); +stream_create_fail: + /* TODO: error handling*/ + return result; +} + +static const struct drm_connector_helper_funcs +amdgpu_dm_connector_helper_funcs = { + /* + * If hotplug a second bigger display in FB Con mode, bigger resolution + * modes will be filtered by drm_mode_validate_size(), and those modes + * is missing after user start lightdm. So we need to renew modes list. + * in get_modes call back, not just return the modes count + */ + .get_modes = get_modes, + .mode_valid = amdgpu_dm_connector_mode_valid, + .best_encoder = best_encoder +}; + +static void dm_crtc_helper_disable(struct drm_crtc *crtc) +{ +} + +static int dm_crtc_helper_atomic_check( + struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + return 0; +} + +static bool dm_crtc_helper_mode_fixup( + struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = { + .disable = dm_crtc_helper_disable, + .atomic_check = dm_crtc_helper_atomic_check, + .mode_fixup = dm_crtc_helper_mode_fixup +}; + +static void dm_encoder_helper_disable(struct drm_encoder *encoder) +{ + +} + +static int dm_encoder_helper_atomic_check( + struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + return 0; +} + +const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { + .disable = dm_encoder_helper_disable, + .atomic_check = dm_encoder_helper_atomic_check +}; + +static const struct drm_plane_funcs dm_plane_funcs = { + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state +}; + +static void clear_unrelated_fields(struct drm_plane_state *state) +{ + state->crtc = NULL; + state->fb = NULL; + state->state = NULL; + state->fence = NULL; +} + +static bool page_flip_needed( + const struct drm_plane_state *new_state, + const struct drm_plane_state *old_state, + struct drm_pending_vblank_event *event, + bool commit_surface_required) +{ + struct drm_plane_state old_state_tmp; + struct drm_plane_state new_state_tmp; + + struct amdgpu_framebuffer *amdgpu_fb_old; + struct amdgpu_framebuffer *amdgpu_fb_new; + struct amdgpu_crtc *acrtc_new; + + uint64_t old_tiling_flags; + uint64_t new_tiling_flags; + + bool page_flip_required; + + if (!old_state) + return false; + + if (!old_state->fb) + return false; + + if (!new_state) + return false; + + if (!new_state->fb) + return false; + + old_state_tmp = *old_state; + new_state_tmp = *new_state; + + if (!event) + return false; + + amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb); + amdgpu_fb_new = to_amdgpu_framebuffer(new_state->fb); + + if (!get_fb_info(amdgpu_fb_old, &old_tiling_flags, NULL)) + return false; + + if (!get_fb_info(amdgpu_fb_new, &new_tiling_flags, NULL)) + return false; + + if (commit_surface_required == true && + old_tiling_flags != new_tiling_flags) + return false; + + clear_unrelated_fields(&old_state_tmp); + clear_unrelated_fields(&new_state_tmp); + + page_flip_required = memcmp(&old_state_tmp, + &new_state_tmp, + sizeof(old_state_tmp)) == 0 ? true:false; + if (new_state->crtc && page_flip_required == false) { + acrtc_new = to_amdgpu_crtc(new_state->crtc); + if (acrtc_new->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) + page_flip_required = true; + } + return page_flip_required; +} + +static int dm_plane_helper_prepare_fb( + struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct amdgpu_framebuffer *afb; + struct drm_gem_object *obj; + struct amdgpu_bo *rbo; + int r; + + if (!new_state->fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + afb = to_amdgpu_framebuffer(new_state->fb); + + obj = afb->obj; + rbo = gem_to_amdgpu_bo(obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL); + + amdgpu_bo_unreserve(rbo); + + if (unlikely(r != 0)) { + DRM_ERROR("Failed to pin framebuffer\n"); + return r; + } + + return 0; +} + +static void dm_plane_helper_cleanup_fb( + struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct amdgpu_bo *rbo; + struct amdgpu_framebuffer *afb; + int r; + + if (!old_state->fb) + return; + + afb = to_amdgpu_framebuffer(old_state->fb); + rbo = gem_to_amdgpu_bo(afb->obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) { + DRM_ERROR("failed to reserve rbo before unpin\n"); + return; + } else { + amdgpu_bo_unpin(rbo); + amdgpu_bo_unreserve(rbo); + } +} + +int dm_create_validation_set_for_target(struct drm_connector *connector, + struct drm_display_mode *mode, struct dc_validation_set *val_set) +{ + int result = MODE_ERROR; + const struct dc_sink *dc_sink = + to_amdgpu_connector(connector)->dc_sink; + /* TODO: Unhardcode stream count */ + struct dc_stream *streams[1]; + struct dc_target *target; + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || + (mode->flags & DRM_MODE_FLAG_DBLSCAN)) + return result; + + if (NULL == dc_sink) { + DRM_ERROR("dc_sink is NULL!\n"); + return result; + } + + streams[0] = dc_create_stream_for_sink(dc_sink); + + if (NULL == streams[0]) { + DRM_ERROR("Failed to create stream for sink!\n"); + return result; + } + + drm_mode_set_crtcinfo(mode, 0); + + fill_stream_properties_from_drm_display_mode(streams[0], mode, connector); + + target = dc_create_target_for_streams(streams, 1); + val_set->target = target; + + if (NULL == val_set->target) { + DRM_ERROR("Failed to create target with stream!\n"); + goto fail; + } + + streams[0]->src.width = mode->hdisplay; + streams[0]->src.height = mode->vdisplay; + streams[0]->dst = streams[0]->src; + + return MODE_OK; + +fail: + dc_stream_release(streams[0]); + return result; + +} + +static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { + .prepare_fb = dm_plane_helper_prepare_fb, + .cleanup_fb = dm_plane_helper_cleanup_fb, +}; + +/* + * TODO: these are currently initialized to rgb formats only. + * For future use cases we should either initialize them dynamically based on + * plane capabilities, or initialize this array to all formats, so internal drm + * check will succeed, and let DC to implement proper check + */ +static uint32_t rgb_formats[] = { + DRM_FORMAT_XRGB4444, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_RGBA4444, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, +}; + +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct amdgpu_crtc *acrtc, + uint32_t crtc_index) +{ + int res = -ENOMEM; + + struct drm_plane *primary_plane = + kzalloc(sizeof(*primary_plane), GFP_KERNEL); + + if (!primary_plane) + goto fail_plane; + + primary_plane->format_default = true; + + res = drm_universal_plane_init( + dm->adev->ddev, + primary_plane, + 0, + &dm_plane_funcs, + rgb_formats, + ARRAY_SIZE(rgb_formats), + NULL, + DRM_PLANE_TYPE_PRIMARY, NULL); + + primary_plane->crtc = &acrtc->base; + + drm_plane_helper_add(primary_plane, &dm_plane_helper_funcs); + + res = drm_crtc_init_with_planes( + dm->ddev, + &acrtc->base, + primary_plane, + NULL, + &amdgpu_dm_crtc_funcs, NULL); + + if (res) + goto fail; + + drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); + + acrtc->max_cursor_width = 128; + acrtc->max_cursor_height = 128; + + acrtc->crtc_id = crtc_index; + acrtc->base.enabled = false; + + dm->adev->mode_info.crtcs[crtc_index] = acrtc; + drm_mode_crtc_set_gamma_size(&acrtc->base, 256); + + return 0; +fail: + kfree(primary_plane); +fail_plane: + acrtc->crtc_id = -1; + return res; +} + +static int to_drm_connector_type(enum signal_type st) +{ + switch (st) { + case SIGNAL_TYPE_HDMI_TYPE_A: + return DRM_MODE_CONNECTOR_HDMIA; + case SIGNAL_TYPE_EDP: + return DRM_MODE_CONNECTOR_eDP; + case SIGNAL_TYPE_RGB: + return DRM_MODE_CONNECTOR_VGA; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + return DRM_MODE_CONNECTOR_DisplayPort; + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_DVI_SINGLE_LINK: + return DRM_MODE_CONNECTOR_DVID; + case SIGNAL_TYPE_VIRTUAL: + return DRM_MODE_CONNECTOR_VIRTUAL; + + default: + return DRM_MODE_CONNECTOR_Unknown; + } +} + +static void amdgpu_dm_get_native_mode(struct drm_connector *connector) +{ + const struct drm_connector_helper_funcs *helper = + connector->helper_private; + struct drm_encoder *encoder; + struct amdgpu_encoder *amdgpu_encoder; + + encoder = helper->best_encoder(connector); + + if (encoder == NULL) + return; + + amdgpu_encoder = to_amdgpu_encoder(encoder); + + amdgpu_encoder->native_mode.clock = 0; + + if (!list_empty(&connector->probed_modes)) { + struct drm_display_mode *preferred_mode = NULL; + list_for_each_entry(preferred_mode, + &connector->probed_modes, + head) { + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { + amdgpu_encoder->native_mode = *preferred_mode; + } + break; + } + + } +} + +static struct drm_display_mode *amdgpu_dm_create_common_mode( + struct drm_encoder *encoder, char *name, + int hdisplay, int vdisplay) +{ + struct drm_device *dev = encoder->dev; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; + + mode = drm_mode_duplicate(dev, native_mode); + + if(mode == NULL) + return NULL; + + mode->hdisplay = hdisplay; + mode->vdisplay = vdisplay; + mode->type &= ~DRM_MODE_TYPE_PREFERRED; + strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN); + + return mode; + +} + +static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + int i; + int n; + struct mode_size { + char name[DRM_DISPLAY_MODE_LEN]; + int w; + int h; + }common_modes[] = { + { "640x480", 640, 480}, + { "800x600", 800, 600}, + { "1024x768", 1024, 768}, + { "1280x720", 1280, 720}, + { "1280x800", 1280, 800}, + {"1280x1024", 1280, 1024}, + { "1440x900", 1440, 900}, + {"1680x1050", 1680, 1050}, + {"1600x1200", 1600, 1200}, + {"1920x1080", 1920, 1080}, + {"1920x1200", 1920, 1200} + }; + + n = sizeof(common_modes) / sizeof(common_modes[0]); + + for (i = 0; i < n; i++) { + struct drm_display_mode *curmode = NULL; + bool mode_existed = false; + + if (common_modes[i].w > native_mode->hdisplay || + common_modes[i].h > native_mode->vdisplay || + (common_modes[i].w == native_mode->hdisplay && + common_modes[i].h == native_mode->vdisplay)) + continue; + + list_for_each_entry(curmode, &connector->probed_modes, head) { + if (common_modes[i].w == curmode->hdisplay && + common_modes[i].h == curmode->vdisplay) { + mode_existed = true; + break; + } + } + + if (mode_existed) + continue; + + mode = amdgpu_dm_create_common_mode(encoder, + common_modes[i].name, common_modes[i].w, + common_modes[i].h); + drm_mode_probed_add(connector, mode); + amdgpu_connector->num_modes++; + } +} + +static void amdgpu_dm_connector_ddc_get_modes( + struct drm_connector *connector, + struct edid *edid) +{ + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + if (edid) { + /* empty probed_modes */ + INIT_LIST_HEAD(&connector->probed_modes); + amdgpu_connector->num_modes = + drm_add_edid_modes(connector, edid); + + drm_edid_to_eld(connector, edid); + + amdgpu_dm_get_native_mode(connector); + } else + amdgpu_connector->num_modes = 0; +} + +int amdgpu_dm_connector_get_modes(struct drm_connector *connector) +{ + const struct drm_connector_helper_funcs *helper = + connector->helper_private; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + struct drm_encoder *encoder; + struct edid *edid = amdgpu_connector->edid; + + encoder = helper->best_encoder(connector); + + amdgpu_dm_connector_ddc_get_modes(connector, edid); + amdgpu_dm_connector_add_common_modes(encoder, connector); + return amdgpu_connector->num_modes; +} + +void amdgpu_dm_connector_init_helper( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + int connector_type, + const struct dc_link *link, + int link_index) +{ + struct amdgpu_device *adev = dm->ddev->dev_private; + + aconnector->connector_id = link_index; + aconnector->dc_link = link; + aconnector->base.interlace_allowed = true; + aconnector->base.doublescan_allowed = true; + aconnector->base.dpms = DRM_MODE_DPMS_OFF; + aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ + + mutex_init(&aconnector->hpd_lock); + + /*configure suport HPD hot plug connector_>polled default value is 0 + * which means HPD hot plug not supported*/ + switch (connector_type) { + case DRM_MODE_CONNECTOR_HDMIA: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + case DRM_MODE_CONNECTOR_DisplayPort: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + case DRM_MODE_CONNECTOR_DVID: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + default: + break; + } + + drm_object_attach_property(&aconnector->base.base, + dm->ddev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_NONE); + + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_hborder_property, + 0); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_vborder_property, + 0); + +} + +int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); + struct i2c_command cmd; + int i; + int result = -EIO; + + cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL); + + if (!cmd.payloads) + return result; + + cmd.number_of_payloads = num; + cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; + cmd.speed = 100; + + for (i = 0; i < num; i++) { + cmd.payloads[i].write = (msgs[i].flags & I2C_M_RD); + cmd.payloads[i].address = msgs[i].addr; + cmd.payloads[i].length = msgs[i].len; + cmd.payloads[i].data = msgs[i].buf; + } + + if (dc_submit_i2c(i2c->dm->dc, i2c->link_index, &cmd)) + result = num; + + kfree(cmd.payloads); + + return result; +} + +u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm amdgpu_dm_i2c_algo = { + .master_xfer = amdgpu_dm_i2c_xfer, + .functionality = amdgpu_dm_i2c_func, +}; + +struct amdgpu_i2c_adapter *create_i2c(unsigned int link_index, struct amdgpu_display_manager *dm, int *res) +{ + struct amdgpu_i2c_adapter *i2c; + + i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); + i2c->dm = dm; + i2c->base.owner = THIS_MODULE; + i2c->base.class = I2C_CLASS_DDC; + i2c->base.dev.parent = &dm->adev->pdev->dev; + i2c->base.algo = &amdgpu_dm_i2c_algo; + snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); + i2c->link_index = link_index; + i2c_set_adapdata(&i2c->base, i2c); + + return i2c; +} + +/* Note: this function assumes that dc_link_detect() was called for the + * dc_link which will be represented by this aconnector. */ +int amdgpu_dm_connector_init( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + uint32_t link_index, + struct amdgpu_encoder *aencoder) +{ + int res = 0; + int connector_type; + struct dc *dc = dm->dc; + const struct dc_link *link = dc_get_link_at_index(dc, link_index); + struct amdgpu_i2c_adapter *i2c; + + DRM_DEBUG_KMS("%s()\n", __func__); + + i2c = create_i2c(link->link_index, dm, &res); + aconnector->i2c = i2c; + res = i2c_add_adapter(&i2c->base); + + if (res) { + DRM_ERROR("Failed to register hw i2c %d\n", link->link_index); + goto out_free; + } + + connector_type = to_drm_connector_type(link->connector_signal); + + res = drm_connector_init( + dm->ddev, + &aconnector->base, + &amdgpu_dm_connector_funcs, + connector_type); + + if (res) { + DRM_ERROR("connector_init failed\n"); + aconnector->connector_id = -1; + goto out_free; + } + + drm_connector_helper_add( + &aconnector->base, + &amdgpu_dm_connector_helper_funcs); + + amdgpu_dm_connector_init_helper( + dm, + aconnector, + connector_type, + link, + link_index); + + drm_mode_connector_attach_encoder( + &aconnector->base, &aencoder->base); + + drm_connector_register(&aconnector->base); + + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort + || connector_type == DRM_MODE_CONNECTOR_eDP) + amdgpu_dm_initialize_mst_connector(dm, aconnector); + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + /* NOTE: this currently will create backlight device even if a panel + * is not connected to the eDP/LVDS connector. + * + * This is less than ideal but we don't have sink information at this + * stage since detection happens after. We can't do detection earlier + * since MST detection needs connectors to be created first. + */ + if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + /* Event if registration failed, we should continue with + * DM initialization because not having a backlight control + * is better then a black screen. */ + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) + dm->backlight_link = link; + } +#endif + +out_free: + if (res) { + kfree(i2c); + aconnector->i2c = NULL; + } + return res; +} + +int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) +{ + switch (adev->mode_info.num_crtc) { + case 1: + return 0x1; + case 2: + return 0x3; + case 3: + return 0x7; + case 4: + return 0xf; + case 5: + return 0x1f; + case 6: + default: + return 0x3f; + } +} + +int amdgpu_dm_encoder_init( + struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index) +{ + struct amdgpu_device *adev = dev->dev_private; + + int res = drm_encoder_init(dev, + &aencoder->base, + &amdgpu_dm_encoder_funcs, + DRM_MODE_ENCODER_TMDS, + NULL); + + aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); + + if (!res) + aencoder->encoder_id = link_index; + else + aencoder->encoder_id = -1; + + drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs); + + return res; +} + +enum dm_commit_action { + DM_COMMIT_ACTION_NOTHING, + DM_COMMIT_ACTION_RESET, + DM_COMMIT_ACTION_DPMS_ON, + DM_COMMIT_ACTION_DPMS_OFF, + DM_COMMIT_ACTION_SET +}; + +static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state) +{ + /* mode changed means either actually mode changed or enabled changed */ + /* active changed means dpms changed */ + + DRM_DEBUG_KMS("crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n", + state->enable, + state->active, + state->planes_changed, + state->mode_changed, + state->active_changed, + state->connectors_changed); + + if (state->mode_changed) { + /* if it is got disabled - call reset mode */ + if (!state->enable) + return DM_COMMIT_ACTION_RESET; + + if (state->active) + return DM_COMMIT_ACTION_SET; + else + return DM_COMMIT_ACTION_RESET; + } else { + /* ! mode_changed */ + + /* if it is remain disable - skip it */ + if (!state->enable) + return DM_COMMIT_ACTION_NOTHING; + + if (state->active && state->connectors_changed) + return DM_COMMIT_ACTION_SET; + + if (state->active_changed) { + if (state->active) { + return DM_COMMIT_ACTION_DPMS_ON; + } else { + return DM_COMMIT_ACTION_DPMS_OFF; + } + } else { + /* ! active_changed */ + return DM_COMMIT_ACTION_NOTHING; + } + } +} + + +typedef bool (*predicate)(struct amdgpu_crtc *acrtc); + +static void wait_while_pflip_status(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, predicate f) { + int count = 0; + while (f(acrtc)) { + /* Spin Wait*/ + msleep(1); + count++; + if (count == 1000) { + DRM_ERROR("%s - crtc:%d[%p], pflip_stat:%d, probable hang!\n", + __func__, acrtc->crtc_id, + acrtc, + acrtc->pflip_status); + + /* we do not expect to hit this case except on Polaris with PHY PLL + * 1. DP to HDMI passive dongle connected + * 2. unplug (headless) + * 3. plug in DP + * 3a. on plug in, DP will try verify link by training, and training + * would disable PHY PLL which HDMI rely on to drive TG + * 3b. this will cause flip interrupt cannot be generated, and we + * exit when timeout expired. however we do not have code to clean + * up flip, flip clean up will happen when the address is written + * with the restore mode change + */ + WARN_ON(1); + break; + } + } + + DRM_DEBUG_DRIVER("%s - Finished waiting for:%d msec, crtc:%d[%p], pflip_stat:%d \n", + __func__, + count, + acrtc->crtc_id, + acrtc, + acrtc->pflip_status); +} + +static bool pflip_in_progress_predicate(struct amdgpu_crtc *acrtc) +{ + return acrtc->pflip_status != AMDGPU_FLIP_NONE; +} + +static void manage_dm_interrupts( + struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + bool enable) +{ + /* + * this is not correct translation but will work as soon as VBLANK + * constant is the same as PFLIP + */ + int irq_type = + amdgpu_crtc_idx_to_irq_type( + adev, + acrtc->crtc_id); + + if (enable) { + drm_crtc_vblank_on(&acrtc->base); + amdgpu_irq_get( + adev, + &adev->pageflip_irq, + irq_type); + } else { + wait_while_pflip_status(adev, acrtc, + pflip_in_progress_predicate); + + amdgpu_irq_put( + adev, + &adev->pageflip_irq, + irq_type); + drm_crtc_vblank_off(&acrtc->base); + } +} + + +static bool pflip_pending_predicate(struct amdgpu_crtc *acrtc) +{ + return acrtc->pflip_status == AMDGPU_FLIP_PENDING; +} + +static bool is_scaling_state_different( + const struct dm_connector_state *dm_state, + const struct dm_connector_state *old_dm_state) +{ + if (dm_state->scaling != old_dm_state->scaling) + return true; + if (!dm_state->underscan_enable && old_dm_state->underscan_enable) { + if (old_dm_state->underscan_hborder != 0 && old_dm_state->underscan_vborder != 0) + return true; + } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) { + if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0) + return true; + } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder + || dm_state->underscan_vborder != old_dm_state->underscan_vborder) + return true; + return false; +} + +static void remove_target(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) +{ + int i; + + /* + * we evade vblanks and pflips on crtc that + * should be changed + */ + manage_dm_interrupts(adev, acrtc, false); + /* this is the update mode case */ + if (adev->dm.freesync_module) + for (i = 0; i < acrtc->target->stream_count; i++) + mod_freesync_remove_stream( + adev->dm.freesync_module, + acrtc->target->streams[i]); + dc_target_release(acrtc->target); + acrtc->target = NULL; + acrtc->otg_inst = -1; + acrtc->enabled = false; +} + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool async) +{ + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_display_manager *dm = &adev->dm; + struct drm_plane *plane; + struct drm_plane_state *new_plane_state; + struct drm_plane_state *old_plane_state; + uint32_t i, j; + int32_t ret = 0; + uint32_t commit_targets_count = 0; + uint32_t new_crtcs_count = 0; + uint32_t flip_crtcs_count = 0; + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + + struct dc_target *commit_targets[MAX_TARGETS]; + struct amdgpu_crtc *new_crtcs[MAX_TARGETS]; + struct dc_target *new_target; + struct drm_crtc *flip_crtcs[MAX_TARGETS]; + struct amdgpu_flip_work *work[MAX_TARGETS] = {0}; + struct amdgpu_bo *new_abo[MAX_TARGETS] = {0}; + + /* In this step all new fb would be pinned */ + + /* + * TODO: Revisit when we support true asynchronous commit. + * Right now we receive async commit only from pageflip, in which case + * we should not pin/unpin the fb here, it should be done in + * amdgpu_crtc_flip and from the vblank irq handler. + */ + if (!async) { + ret = drm_atomic_helper_prepare_planes(dev, state); + if (ret) + return ret; + } + + /* Page flip if needed */ + for_each_plane_in_state(state, plane, new_plane_state, i) { + struct drm_plane_state *old_plane_state = plane->state; + struct drm_crtc *crtc = new_plane_state->crtc; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_framebuffer *fb = new_plane_state->fb; + struct drm_crtc_state *crtc_state; + + if (!fb || !crtc) + continue; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + + if (!crtc_state->planes_changed || !crtc_state->active) + continue; + + if (page_flip_needed( + new_plane_state, + old_plane_state, + crtc_state->event, + false)) { + ret = amdgpu_crtc_prepare_flip(crtc, + fb, + crtc_state->event, + acrtc->flip_flags, + drm_crtc_vblank_count(crtc), + &work[flip_crtcs_count], + &new_abo[flip_crtcs_count]); + + if (ret) { + /* According to atomic_commit hook API, EINVAL is not allowed */ + if (unlikely(ret == -EINVAL)) + ret = -ENOMEM; + + DRM_ERROR("Atomic commit: Flip for crtc id %d: [%p], " + "failed, errno = %d\n", + acrtc->crtc_id, + acrtc, + ret); + /* cleanup all flip configurations which + * succeeded in this commit + */ + for (i = 0; i < flip_crtcs_count; i++) + amdgpu_crtc_cleanup_flip_ctx( + work[i], + new_abo[i]); + + return ret; + } + + flip_crtcs[flip_crtcs_count] = crtc; + flip_crtcs_count++; + } + } + + /* + * This is the point of no return - everything below never fails except + * when the hw goes bonghits. Which means we can commit the new state on + * the software side now. + */ + + drm_atomic_helper_swap_state(state, true); + + /* + * From this point state become old state really. New state is + * initialized to appropriate objects and could be accessed from there + */ + + /* + * there is no fences usage yet in state. We can skip the following line + * wait_for_fences(dev, state); + */ + + drm_atomic_helper_update_legacy_modeset_state(dev, state); + + /* update changed items */ + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc; + struct amdgpu_connector *aconnector = NULL; + enum dm_commit_action action; + struct drm_crtc_state *new_state = crtc->state; + + acrtc = to_amdgpu_crtc(crtc); + + aconnector = + amdgpu_dm_find_first_crct_matching_connector( + state, + crtc, + false); + + /* handles headless hotplug case, updating new_state and + * aconnector as needed + */ + + action = get_dm_commit_action(new_state); + + switch (action) { + case DM_COMMIT_ACTION_DPMS_ON: + case DM_COMMIT_ACTION_SET: { + struct dm_connector_state *dm_state = NULL; + new_target = NULL; + + if (aconnector) + dm_state = to_dm_connector_state(aconnector->base.state); + + new_target = create_target_for_sink( + aconnector, + &crtc->state->mode, + dm_state); + + DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); + + if (!new_target) { + /* + * this could happen because of issues with + * userspace notifications delivery. + * In this case userspace tries to set mode on + * display which is disconnect in fact. + * dc_sink in NULL in this case on aconnector. + * We expect reset mode will come soon. + * + * This can also happen when unplug is done + * during resume sequence ended + * + * In this case, we want to pretend we still + * have a sink to keep the pipe running so that + * hw state is consistent with the sw state + */ + DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + if (acrtc->target) + remove_target(adev, acrtc); + + /* + * this loop saves set mode crtcs + * we needed to enable vblanks once all + * resources acquired in dc after dc_commit_targets + */ + new_crtcs[new_crtcs_count] = acrtc; + new_crtcs_count++; + + acrtc->target = new_target; + acrtc->enabled = true; + acrtc->hw_mode = crtc->state->mode; + crtc->hwmode = crtc->state->mode; + + break; + } + + case DM_COMMIT_ACTION_NOTHING: { + struct dm_connector_state *dm_state = NULL; + + if (!aconnector) + break; + + dm_state = to_dm_connector_state(aconnector->base.state); + + /* Scaling update */ + update_stream_scaling_settings( + &crtc->state->mode, + dm_state, + acrtc->target->streams[0]); + + break; + } + case DM_COMMIT_ACTION_DPMS_OFF: + case DM_COMMIT_ACTION_RESET: + DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); + /* i.e. reset mode */ + if (acrtc->target) + remove_target(adev, acrtc); + break; + } /* switch() */ + } /* for_each_crtc_in_state() */ + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target) { + commit_targets[commit_targets_count] = acrtc->target; + ++commit_targets_count; + } + } + + /* + * Add streams after required streams from new and replaced targets + * are removed from freesync module + */ + if (adev->dm.freesync_module) { + for (i = 0; i < new_crtcs_count; i++) { + struct amdgpu_connector *aconnector = NULL; + new_target = new_crtcs[i]->target; + aconnector = + amdgpu_dm_find_first_crct_matching_connector( + state, + &new_crtcs[i]->base, + false); + if (!aconnector) { + DRM_INFO( + "Atomic commit: Failed to find connector for acrtc id:%d " + "skipping freesync init\n", + new_crtcs[i]->crtc_id); + continue; + } + + for (j = 0; j < new_target->stream_count; j++) + mod_freesync_add_stream( + adev->dm.freesync_module, + new_target->streams[j], &aconnector->caps); + } + } + + /* DC is optimized not to do anything if 'targets' didn't change. */ + dc_commit_targets(dm->dc, commit_targets, commit_targets_count); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target != NULL) + acrtc->otg_inst = + dc_target_get_status(acrtc->target)->primary_otg_inst; + } + + /* update planes when needed */ + for_each_plane_in_state(state, plane, old_plane_state, i) { + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_framebuffer *fb = plane_state->fb; + struct drm_connector *connector; + struct dm_connector_state *dm_state = NULL; + enum dm_commit_action action; + + if (!fb || !crtc || !crtc->state->active) + continue; + + action = get_dm_commit_action(crtc->state); + + /* Surfaces are created under two scenarios: + * 1. This commit is not a page flip. + * 2. This commit is a page flip, and targets are created. + */ + if (!page_flip_needed( + plane_state, + old_plane_state, + crtc->state->event, true) || + action == DM_COMMIT_ACTION_DPMS_ON || + action == DM_COMMIT_ACTION_SET) { + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + if (connector->state->crtc == crtc) { + dm_state = to_dm_connector_state( + connector->state); + break; + } + } + + /* + * This situation happens in the following case: + * we are about to get set mode for connector who's only + * possible crtc (in encoder crtc mask) is used by + * another connector, that is why it will try to + * re-assing crtcs in order to make configuration + * supported. For our implementation we need to make all + * encoders support all crtcs, then this issue will + * never arise again. But to guard code from this issue + * check is left. + * + * Also it should be needed when used with actual + * drm_atomic_commit ioctl in future + */ + if (!dm_state) + continue; + + /* + * if flip is pending (ie, still waiting for fence to return + * before address is submitted) here, we cannot commit_surface + * as commit_surface will pre-maturely write out the future + * address. wait until flip is submitted before proceeding. + */ + wait_while_pflip_status(adev, acrtc, pflip_pending_predicate); + + dm_dc_surface_commit(dm->dc, crtc); + } + } + + for (i = 0; i < new_crtcs_count; i++) { + /* + * loop to enable interrupts on newly arrived crtc + */ + struct amdgpu_crtc *acrtc = new_crtcs[i]; + + if (adev->dm.freesync_module) { + for (j = 0; j < acrtc->target->stream_count; j++) + mod_freesync_notify_mode_change( + adev->dm.freesync_module, + acrtc->target->streams, + acrtc->target->stream_count); + } + + manage_dm_interrupts(adev, acrtc, true); + dm_crtc_cursor_reset(&acrtc->base); + + } + + /* Do actual flip */ + flip_crtcs_count = 0; + for_each_plane_in_state(state, plane, old_plane_state, i) { + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_framebuffer *fb = plane_state->fb; + + if (!fb || !crtc || !crtc->state->planes_changed || + !crtc->state->active) + continue; + + if (page_flip_needed( + plane_state, + old_plane_state, + crtc->state->event, + false)) { + amdgpu_crtc_submit_flip( + crtc, + fb, + work[flip_crtcs_count], + new_abo[i]); + flip_crtcs_count++; + /*clean up the flags for next usage*/ + acrtc->flip_flags = 0; + } + } + + /* In this state all old framebuffers would be unpinned */ + + /* TODO: Revisit when we support true asynchronous commit.*/ + if (!async) + drm_atomic_helper_cleanup_planes(dev, state); + + drm_atomic_state_put(state); + + return ret; +} +/* + * This functions handle all cases when set mode does not come upon hotplug. + * This include when the same display is unplugged then plugged back into the + * same port and when we are running without usermode desktop manager supprot + */ +void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) +{ + struct drm_crtc *crtc; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_crtc *disconnected_acrtc; + const struct dc_sink *sink; + struct dc_target *commit_targets[6]; + struct dc_target *current_target; + uint32_t commit_targets_count = 0; + int i; + + if (!aconnector->dc_sink || !connector->state || !connector->encoder) + return; + + disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + + if (!disconnected_acrtc || !disconnected_acrtc->target) + return; + + sink = disconnected_acrtc->target->streams[0]->sink; + + /* + * If the previous sink is not released and different from the current, + * we deduce we are in a state where we can not rely on usermode call + * to turn on the display, so we do it here + */ + if (sink != aconnector->dc_sink) { + struct dm_connector_state *dm_state = + to_dm_connector_state(aconnector->base.state); + + struct dc_target *new_target = + create_target_for_sink( + aconnector, + &disconnected_acrtc->base.state->mode, + dm_state); + + DRM_INFO("Headless hotplug, restoring connector state\n"); + /* + * we evade vblanks and pflips on crtc that + * should be changed + */ + manage_dm_interrupts(adev, disconnected_acrtc, false); + /* this is the update mode case */ + + current_target = disconnected_acrtc->target; + + disconnected_acrtc->target = new_target; + disconnected_acrtc->enabled = true; + disconnected_acrtc->hw_mode = disconnected_acrtc->base.state->mode; + + commit_targets_count = 0; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target) { + commit_targets[commit_targets_count] = acrtc->target; + ++commit_targets_count; + } + } + + /* DC is optimized not to do anything if 'targets' didn't change. */ + if (!dc_commit_targets(dc, commit_targets, + commit_targets_count)) { + DRM_INFO("Failed to restore connector state!\n"); + dc_target_release(disconnected_acrtc->target); + disconnected_acrtc->target = current_target; + manage_dm_interrupts(adev, disconnected_acrtc, true); + return; + } + + if (adev->dm.freesync_module) { + + for (i = 0; i < current_target->stream_count; i++) + mod_freesync_remove_stream( + adev->dm.freesync_module, + current_target->streams[i]); + + for (i = 0; i < new_target->stream_count; i++) + mod_freesync_add_stream( + adev->dm.freesync_module, + new_target->streams[i], + &aconnector->caps); + } + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target != NULL) { + acrtc->otg_inst = + dc_target_get_status(acrtc->target)->primary_otg_inst; + } + } + + dc_target_release(current_target); + + dm_dc_surface_commit(dc, &disconnected_acrtc->base); + + manage_dm_interrupts(adev, disconnected_acrtc, true); + dm_crtc_cursor_reset(&disconnected_acrtc->base); + + } +} + +static uint32_t add_val_sets_surface( + struct dc_validation_set *val_sets, + uint32_t set_count, + const struct dc_target *target, + const struct dc_surface *surface) +{ + uint32_t i = 0; + + while (i < set_count) { + if (val_sets[i].target == target) + break; + ++i; + } + + val_sets[i].surfaces[val_sets[i].surface_count] = surface; + val_sets[i].surface_count++; + + return val_sets[i].surface_count; +} + +static uint32_t update_in_val_sets_target( + struct dc_validation_set *val_sets, + struct drm_crtc **crtcs, + uint32_t set_count, + const struct dc_target *old_target, + const struct dc_target *new_target, + struct drm_crtc *crtc) +{ + uint32_t i = 0; + + while (i < set_count) { + if (val_sets[i].target == old_target) + break; + ++i; + } + + val_sets[i].target = new_target; + crtcs[i] = crtc; + + if (i == set_count) { + /* nothing found. add new one to the end */ + return set_count + 1; + } + + return set_count; +} + +static uint32_t remove_from_val_sets( + struct dc_validation_set *val_sets, + uint32_t set_count, + const struct dc_target *target) +{ + int i; + + for (i = 0; i < set_count; i++) + if (val_sets[i].target == target) + break; + + if (i == set_count) { + /* nothing found */ + return set_count; + } + + set_count--; + + for (; i < set_count; i++) { + val_sets[i] = val_sets[i + 1]; + } + + return set_count; +} + +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + int i, j; + int ret; + int set_count; + int new_target_count; + struct dc_validation_set set[MAX_TARGETS] = {{ 0 }}; + struct dc_target *new_targets[MAX_TARGETS] = { 0 }; + struct drm_crtc *crtc_set[MAX_TARGETS] = { 0 }; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + bool need_to_validate = false; + + ret = drm_atomic_helper_check(dev, state); + + if (ret) { + DRM_ERROR("Atomic state validation failed with error :%d !\n", + ret); + return ret; + } + + ret = -EINVAL; + + /* copy existing configuration */ + new_target_count = 0; + set_count = 0; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->target) { + set[set_count].target = acrtc->target; + crtc_set[set_count] = crtc; + ++set_count; + } + } + + /* update changed items */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_connector *aconnector = NULL; + enum dm_commit_action action; + + acrtc = to_amdgpu_crtc(crtc); + + aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); + + action = get_dm_commit_action(crtc_state); + + switch (action) { + case DM_COMMIT_ACTION_DPMS_ON: + case DM_COMMIT_ACTION_SET: { + struct dc_target *new_target = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_state = NULL; + + if (aconnector) { + conn_state = drm_atomic_get_connector_state(state, &aconnector->base); + if (IS_ERR(conn_state)) + return ret; + dm_state = to_dm_connector_state(conn_state); + } + + new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state); + + /* + * we can have no target on ACTION_SET if a display + * was disconnected during S3, in this case it not and + * error, the OS will be updated after detection, and + * do the right thing on next atomic commit + */ + if (!new_target) { + DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + new_targets[new_target_count] = new_target; + set_count = update_in_val_sets_target( + set, + crtc_set, + set_count, + acrtc->target, + new_target, + crtc); + + new_target_count++; + need_to_validate = true; + break; + } + + case DM_COMMIT_ACTION_NOTHING: { + const struct drm_connector *drm_connector = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_state = NULL; + struct dm_connector_state *old_dm_state = NULL; + struct dc_target *new_target; + + if (!aconnector) + break; + + for_each_connector_in_state( + state, drm_connector, conn_state, j) { + if (&aconnector->base == drm_connector) + break; + } + + old_dm_state = to_dm_connector_state(drm_connector->state); + dm_state = to_dm_connector_state(conn_state); + + /* Support underscan adjustment*/ + if (!is_scaling_state_different(dm_state, old_dm_state)) + break; + + new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state); + + if (!new_target) { + DRM_ERROR("%s: Failed to create new target for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + new_targets[new_target_count] = new_target; + set_count = update_in_val_sets_target( + set, + crtc_set, + set_count, + acrtc->target, + new_target, + crtc); + + new_target_count++; + need_to_validate = true; + + break; + } + case DM_COMMIT_ACTION_DPMS_OFF: + case DM_COMMIT_ACTION_RESET: + /* i.e. reset mode */ + if (acrtc->target) { + set_count = remove_from_val_sets( + set, + set_count, + acrtc->target); + } + break; + } + + /* + * TODO revisit when removing commit action + * and looking at atomic flags directly + */ + + /* commit needs planes right now (for gamma, eg.) */ + /* TODO rework commit to chack crtc for gamma change */ + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + return ret; + } + + for (i = 0; i < set_count; i++) { + for_each_plane_in_state(state, plane, plane_state, j) { + struct drm_plane_state *old_plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct drm_framebuffer *fb = plane_state->fb; + struct drm_connector *connector; + struct dm_connector_state *dm_state = NULL; + enum dm_commit_action action; + struct drm_crtc_state *crtc_state; + + + if (!fb || !crtc || crtc_set[i] != crtc || + !crtc->state->planes_changed || !crtc->state->active) + continue; + + action = get_dm_commit_action(crtc->state); + + /* Surfaces are created under two scenarios: + * 1. This commit is not a page flip. + * 2. This commit is a page flip, and targets are created. + */ + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (!page_flip_needed(plane_state, old_plane_state, + crtc_state->event, true) || + action == DM_COMMIT_ACTION_DPMS_ON || + action == DM_COMMIT_ACTION_SET) { + struct dc_surface *surface; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + if (connector->state->crtc == crtc) { + dm_state = to_dm_connector_state( + connector->state); + break; + } + } + + /* + * This situation happens in the following case: + * we are about to get set mode for connector who's only + * possible crtc (in encoder crtc mask) is used by + * another connector, that is why it will try to + * re-assing crtcs in order to make configuration + * supported. For our implementation we need to make all + * encoders support all crtcs, then this issue will + * never arise again. But to guard code from this issue + * check is left. + * + * Also it should be needed when used with actual + * drm_atomic_commit ioctl in future + */ + if (!dm_state) + continue; + + surface = dc_create_surface(dc); + fill_plane_attributes( + surface, + plane_state, + false); + + add_val_sets_surface( + set, + set_count, + set[i].target, + surface); + + need_to_validate = true; + } + } + } + + if (need_to_validate == false || set_count == 0 || + dc_validate_resources(dc, set, set_count)) + ret = 0; + + for (i = 0; i < set_count; i++) { + for (j = 0; j < set[i].surface_count; j++) { + dc_surface_release(set[i].surfaces[j]); + } + } + for (i = 0; i < new_target_count; i++) + dc_target_release(new_targets[i]); + + if (ret != 0) + DRM_ERROR("Atomic check failed.\n"); + + return ret; +} + +static bool is_dp_capable_without_timing_msa( + struct dc *dc, + struct amdgpu_connector *amdgpu_connector) +{ + uint8_t dpcd_data; + bool capable = false; + if (amdgpu_connector->dc_link && + dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index, + DP_DOWN_STREAM_PORT_COUNT, + &dpcd_data, sizeof(dpcd_data)) ) + capable = dpcd_data & DP_MSA_TIMING_PAR_IGNORED? true:false; + + return capable; +} +void amdgpu_dm_add_sink_to_freesync_module( + struct drm_connector *connector, + struct edid *edid) +{ + int i; + uint64_t val_capable; + bool edid_check_required; + struct detailed_timing *timing; + struct detailed_non_pixel *data; + struct detailed_data_monitor_range *range; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + edid_check_required = false; + if (!amdgpu_connector->dc_sink) { + DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); + return; + } + if (!adev->dm.freesync_module) + return; + /* + * if edid non zero restrict freesync only for dp and edp + */ + if (edid) { + if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT + || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { + edid_check_required = is_dp_capable_without_timing_msa( + adev->dm.dc, + amdgpu_connector); + } + } + val_capable = 0; + if (edid_check_required == true && (edid->version > 1 || + (edid->version == 1 && edid->revision > 1))) { + for (i = 0; i < 4; i++) { + + timing = &edid->detailed_timings[i]; + data = &timing->data.other_data; + range = &data->data.range; + /* + * Check if monitor has continuous frequency mode + */ + if (data->type != EDID_DETAIL_MONITOR_RANGE) + continue; + /* + * Check for flag range limits only. If flag == 1 then + * no additional timing information provided. + * Default GTF, GTF Secondary curve and CVT are not + * supported + */ + if (range->flags != 1) + continue; + + amdgpu_connector->min_vfreq = range->min_vfreq; + amdgpu_connector->max_vfreq = range->max_vfreq; + amdgpu_connector->pixel_clock_mhz = + range->pixel_clock_mhz * 10; + break; + } + + if (amdgpu_connector->max_vfreq - + amdgpu_connector->min_vfreq > 10) { + amdgpu_connector->caps.supported = true; + amdgpu_connector->caps.min_refresh_in_micro_hz = + amdgpu_connector->min_vfreq * 1000000; + amdgpu_connector->caps.max_refresh_in_micro_hz = + amdgpu_connector->max_vfreq * 1000000; + val_capable = 1; + } + } + + /* + * TODO figure out how to notify user-mode or DRM of freesync caps + * once we figure out how to deal with freesync in an upstreamable + * fashion + */ + +} + +void amdgpu_dm_remove_sink_from_freesync_module( + struct drm_connector *connector) +{ + /* + * TODO fill in once we figure out how to deal with freesync in + * an upstreamable fashion + */ +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h new file mode 100644 index 000000000000..4f7bd3bae44e --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -0,0 +1,101 @@ +/* + * Copyright 2012-13 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AMDGPU_DM_TYPES_H__ +#define __AMDGPU_DM_TYPES_H__ + +#include + +struct amdgpu_framebuffer; +struct amdgpu_display_manager; +struct dc_validation_set; +struct dc_surface; + +/*TODO Jodan Hersen use the one in amdgpu_dm*/ +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct amdgpu_crtc *amdgpu_crtc, + uint32_t link_index); +int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_connector *amdgpu_connector, + uint32_t link_index, + struct amdgpu_encoder *amdgpu_encoder); +int amdgpu_dm_encoder_init( + struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index); + +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); +void amdgpu_dm_connector_destroy(struct drm_connector *connector); +void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); + +int amdgpu_dm_connector_get_modes(struct drm_connector *connector); + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool async); +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state); + +int dm_create_validation_set_for_target( + struct drm_connector *connector, + struct drm_display_mode *mode, + struct dc_validation_set *val_set); + +void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); +struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( + struct drm_connector *connector); + +int amdgpu_dm_connector_atomic_set_property( + struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val); + +int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); + +void amdgpu_dm_connector_init_helper( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + int connector_type, + const struct dc_link *link, + int link_index); + +int amdgpu_dm_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode); + +void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); + +void amdgpu_dm_add_sink_to_freesync_module( + struct drm_connector *connector, + struct edid *edid); + +void amdgpu_dm_remove_sink_from_freesync_module( + struct drm_connector *connector); + +extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; + +#endif /* __AMDGPU_DM_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile new file mode 100644 index 000000000000..5fac034093e9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -0,0 +1,28 @@ +# +# Makefile for Display Core (dc) component. +# + +DC_LIBS = basics bios calcs dce \ +gpio gpu i2caux irq virtual + +DC_LIBS += dce112 +DC_LIBS += dce110 +DC_LIBS += dce100 +DC_LIBS += dce80 + +AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS))) + +include $(AMD_DC) + +DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o dc_stream.o \ +dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o + +AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) + +AMD_DM_REG_UPDATE = $(addprefix $(AMDDALPATH)/dc/,dc_helper.o) + +AMD_DISPLAY_FILES += $(AMD_DISPLAY_CORE) +AMD_DISPLAY_FILES += $(AMD_DM_REG_UPDATE) + + + diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile new file mode 100644 index 000000000000..a263cadcc0df --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the 'utils' sub-component of DAL. +# It provides the general basic services required by other DAL +# subcomponents. + +BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \ + logger.o log_helpers.o register_logger.o signal_types.o vector.o + +AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) + +AMD_DISPLAY_FILES += $(AMD_DAL_BASICS) diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c new file mode 100644 index 000000000000..ebe14e17cc2e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -0,0 +1,223 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#define DIVIDER 10000 + +/* S2D13 value in [-3.00...0.9999] */ +#define S2D13_MIN (-3 * DIVIDER) +#define S2D13_MAX (3 * DIVIDER) + +uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits) +{ + int32_t numerator; + int32_t divisor = 1 << fractional_bits; + + uint16_t result; + + uint16_t d = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_abs( + arg)); + + if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) + numerator = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_mul_int( + arg, + divisor)); + else { + numerator = dal_fixed31_32_floor( + dal_fixed31_32_sub( + dal_fixed31_32_from_int( + 1LL << integer_bits), + dal_fixed31_32_recip( + dal_fixed31_32_from_int( + divisor)))); + } + + if (numerator >= 0) + result = (uint16_t)numerator; + else + result = (uint16_t)( + (1 << (integer_bits + fractional_bits + 1)) + numerator); + + if ((result != 0) && dal_fixed31_32_lt( + arg, dal_fixed31_32_zero)) + result |= 1 << (integer_bits + fractional_bits); + + return result; +} +/** +* convert_float_matrix +* This converts a double into HW register spec defined format S2D13. +* @param : +* @return None +*/ +void convert_float_matrix( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size) +{ + const struct fixed31_32 min_2_13 = + dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); + const struct fixed31_32 max_2_13 = + dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); + uint32_t i; + + for (i = 0; i < buffer_size; ++i) { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_2_13, + max_2_13), + 2, + 13); + + matrix[i] = (uint16_t)reg_value; + } +} + +static void calculate_adjustments_common( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + const struct fixed31_32 sin_hue = + dal_fixed31_32_sin(adjustments->hue); + const struct fixed31_32 cos_hue = + dal_fixed31_32_cos(adjustments->hue); + + const struct fixed31_32 multiplier = + dal_fixed31_32_mul( + adjustments->contrast, + adjustments->saturation); + + matrix[0] = dal_fixed31_32_mul( + ideal_matrix[0], + adjustments->contrast); + + matrix[1] = dal_fixed31_32_mul( + ideal_matrix[1], + adjustments->contrast); + + matrix[2] = dal_fixed31_32_mul( + ideal_matrix[2], + adjustments->contrast); + + matrix[4] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[8], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[4], + cos_hue))); + + matrix[5] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[9], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[5], + cos_hue))); + + matrix[6] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal_matrix[10], + sin_hue), + dal_fixed31_32_mul( + ideal_matrix[6], + cos_hue))); + + matrix[7] = ideal_matrix[7]; + + matrix[8] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[8], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[4], + sin_hue))); + + matrix[9] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[9], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[5], + sin_hue))); + + matrix[10] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal_matrix[10], + cos_hue), + dal_fixed31_32_mul( + ideal_matrix[6], + sin_hue))); + + matrix[11] = ideal_matrix[11]; +} + +void calculate_adjustments( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + calculate_adjustments_common(ideal_matrix, adjustments, matrix); + + matrix[3] = dal_fixed31_32_add( + ideal_matrix[3], + dal_fixed31_32_mul( + adjustments->brightness, + dal_fixed31_32_from_fraction(86, 100))); +} + +void calculate_adjustments_y_only( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix) +{ + calculate_adjustments_common(ideal_matrix, adjustments, matrix); + + matrix[3] = dal_fixed31_32_add( + ideal_matrix[3], + adjustments->brightness); +} + diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h new file mode 100644 index 000000000000..18cbe41e80ff --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -0,0 +1,51 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_CONVERSION_H__ +#define __DAL_CONVERSION_H__ + +#include "include/fixed31_32.h" + +uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits); + +void convert_float_matrix( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size); + +void calculate_adjustments( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix); + +void calculate_adjustments_y_only( + const struct fixed31_32 *ideal_matrix, + const struct dc_csc_adjustments *adjustments, + struct fixed31_32 *matrix); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c new file mode 100644 index 000000000000..5a6e46843502 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -0,0 +1,691 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/fixed31_32.h" + +static inline uint64_t abs_i64( + int64_t arg) +{ + if (arg > 0) + return (uint64_t)arg; + else + return (uint64_t)(-arg); +} + +/* + * @brief + * result = dividend / divisor + * *remainder = dividend % divisor + */ +static inline uint64_t complete_integer_division_u64( + uint64_t dividend, + uint64_t divisor, + uint64_t *remainder) +{ + uint64_t result; + + ASSERT(divisor); + + result = div64_u64_rem(dividend, divisor, remainder); + + return result; +} + +#define BITS_PER_FRACTIONAL_PART \ + 32 + +#define FRACTIONAL_PART_MASK \ + ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) + +#define GET_INTEGER_PART(x) \ + ((x) >> BITS_PER_FRACTIONAL_PART) + +#define GET_FRACTIONAL_PART(x) \ + (FRACTIONAL_PART_MASK & (x)) + +struct fixed31_32 dal_fixed31_32_from_fraction( + int64_t numerator, + int64_t denominator) +{ + struct fixed31_32 res; + + bool arg1_negative = numerator < 0; + bool arg2_negative = denominator < 0; + + uint64_t arg1_value = arg1_negative ? -numerator : numerator; + uint64_t arg2_value = arg2_negative ? -denominator : denominator; + + uint64_t remainder; + + /* determine integer part */ + + uint64_t res_value = complete_integer_division_u64( + arg1_value, arg2_value, &remainder); + + ASSERT(res_value <= LONG_MAX); + + /* determine fractional part */ + { + uint32_t i = BITS_PER_FRACTIONAL_PART; + + do { + remainder <<= 1; + + res_value <<= 1; + + if (remainder >= arg2_value) { + res_value |= 1; + remainder -= arg2_value; + } + } while (--i != 0); + } + + /* round up LSB */ + { + uint64_t summand = (remainder << 1) >= arg2_value; + + ASSERT(res_value <= LLONG_MAX - summand); + + res_value += summand; + } + + res.value = (int64_t)res_value; + + if (arg1_negative ^ arg2_negative) + res.value = -res.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_from_int( + int64_t arg) +{ + struct fixed31_32 res; + + ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX)); + + res.value = arg << BITS_PER_FRACTIONAL_PART; + + return res; +} + +struct fixed31_32 dal_fixed31_32_neg( + struct fixed31_32 arg) +{ + struct fixed31_32 res; + + res.value = -arg.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_abs( + struct fixed31_32 arg) +{ + if (arg.value < 0) + return dal_fixed31_32_neg(arg); + else + return arg; +} + +bool dal_fixed31_32_lt( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value < arg2.value; +} + +bool dal_fixed31_32_le( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value <= arg2.value; +} + +bool dal_fixed31_32_eq( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value == arg2.value; +} + +struct fixed31_32 dal_fixed31_32_min( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + if (arg1.value <= arg2.value) + return arg1; + else + return arg2; +} + +struct fixed31_32 dal_fixed31_32_max( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + if (arg1.value <= arg2.value) + return arg2; + else + return arg1; +} + +struct fixed31_32 dal_fixed31_32_clamp( + struct fixed31_32 arg, + struct fixed31_32 min_value, + struct fixed31_32 max_value) +{ + if (dal_fixed31_32_le(arg, min_value)) + return min_value; + else if (dal_fixed31_32_le(max_value, arg)) + return max_value; + else + return arg; +} + +struct fixed31_32 dal_fixed31_32_shl( + struct fixed31_32 arg, + uint8_t shift) +{ + struct fixed31_32 res; + + ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) || + ((arg.value < 0) && (arg.value >= LLONG_MIN >> shift))); + + res.value = arg.value << shift; + + return res; +} + +struct fixed31_32 dal_fixed31_32_shr( + struct fixed31_32 arg, + uint8_t shift) +{ + struct fixed31_32 res; + + ASSERT(shift < 64); + + res.value = arg.value >> shift; + + return res; +} + +struct fixed31_32 dal_fixed31_32_add( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + struct fixed31_32 res; + + ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) || + ((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value))); + + res.value = arg1.value + arg2.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_sub_int( + struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_sub( + arg1, + dal_fixed31_32_from_int(arg2)); +} + +struct fixed31_32 dal_fixed31_32_sub( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + struct fixed31_32 res; + + ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) || + ((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value))); + + res.value = arg1.value - arg2.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_mul_int( + struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_mul( + arg1, + dal_fixed31_32_from_int(arg2)); +} + +struct fixed31_32 dal_fixed31_32_mul( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + struct fixed31_32 res; + + bool arg1_negative = arg1.value < 0; + bool arg2_negative = arg2.value < 0; + + uint64_t arg1_value = arg1_negative ? -arg1.value : arg1.value; + uint64_t arg2_value = arg2_negative ? -arg2.value : arg2.value; + + uint64_t arg1_int = GET_INTEGER_PART(arg1_value); + uint64_t arg2_int = GET_INTEGER_PART(arg2_value); + + uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value); + uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value); + + uint64_t tmp; + + res.value = arg1_int * arg2_int; + + ASSERT(res.value <= LONG_MAX); + + res.value <<= BITS_PER_FRACTIONAL_PART; + + tmp = arg1_int * arg2_fra; + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + tmp = arg2_int * arg1_fra; + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + tmp = arg1_fra * arg2_fra; + + tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + (tmp >= (uint64_t)dal_fixed31_32_half.value); + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + if (arg1_negative ^ arg2_negative) + res.value = -res.value; + + return res; +} + +struct fixed31_32 dal_fixed31_32_sqr( + struct fixed31_32 arg) +{ + struct fixed31_32 res; + + uint64_t arg_value = abs_i64(arg.value); + + uint64_t arg_int = GET_INTEGER_PART(arg_value); + + uint64_t arg_fra = GET_FRACTIONAL_PART(arg_value); + + uint64_t tmp; + + res.value = arg_int * arg_int; + + ASSERT(res.value <= LONG_MAX); + + res.value <<= BITS_PER_FRACTIONAL_PART; + + tmp = arg_int * arg_fra; + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + tmp = arg_fra * arg_fra; + + tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + (tmp >= (uint64_t)dal_fixed31_32_half.value); + + ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); + + res.value += tmp; + + return res; +} + +struct fixed31_32 dal_fixed31_32_div_int( + struct fixed31_32 arg1, + int64_t arg2) +{ + return dal_fixed31_32_from_fraction( + arg1.value, + dal_fixed31_32_from_int(arg2).value); +} + +struct fixed31_32 dal_fixed31_32_div( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return dal_fixed31_32_from_fraction( + arg1.value, + arg2.value); +} + +struct fixed31_32 dal_fixed31_32_recip( + struct fixed31_32 arg) +{ + /* + * @note + * Good idea to use Newton's method + */ + + ASSERT(arg.value); + + return dal_fixed31_32_from_fraction( + dal_fixed31_32_one.value, + arg.value); +} + +struct fixed31_32 dal_fixed31_32_sinc( + struct fixed31_32 arg) +{ + struct fixed31_32 square; + + struct fixed31_32 res = dal_fixed31_32_one; + + int32_t n = 27; + + struct fixed31_32 arg_norm = arg; + + if (dal_fixed31_32_le( + dal_fixed31_32_two_pi, + dal_fixed31_32_abs(arg))) { + arg_norm = dal_fixed31_32_sub( + arg_norm, + dal_fixed31_32_mul_int( + dal_fixed31_32_two_pi, + (int32_t)div64_s64( + arg_norm.value, + dal_fixed31_32_two_pi.value))); + } + + square = dal_fixed31_32_sqr(arg_norm); + + do { + res = dal_fixed31_32_sub( + dal_fixed31_32_one, + dal_fixed31_32_div_int( + dal_fixed31_32_mul( + square, + res), + n * (n - 1))); + + n -= 2; + } while (n > 2); + + if (arg.value != arg_norm.value) + res = dal_fixed31_32_div( + dal_fixed31_32_mul(res, arg_norm), + arg); + + return res; +} + +struct fixed31_32 dal_fixed31_32_sin( + struct fixed31_32 arg) +{ + return dal_fixed31_32_mul( + arg, + dal_fixed31_32_sinc(arg)); +} + +struct fixed31_32 dal_fixed31_32_cos( + struct fixed31_32 arg) +{ + /* TODO implement argument normalization */ + + const struct fixed31_32 square = dal_fixed31_32_sqr(arg); + + struct fixed31_32 res = dal_fixed31_32_one; + + int32_t n = 26; + + do { + res = dal_fixed31_32_sub( + dal_fixed31_32_one, + dal_fixed31_32_div_int( + dal_fixed31_32_mul( + square, + res), + n * (n - 1))); + + n -= 2; + } while (n != 0); + + return res; +} + +/* + * @brief + * result = exp(arg), + * where abs(arg) < 1 + * + * Calculated as Taylor series. + */ +static struct fixed31_32 fixed31_32_exp_from_taylor_series( + struct fixed31_32 arg) +{ + uint32_t n = 9; + + struct fixed31_32 res = dal_fixed31_32_from_fraction( + n + 2, + n + 1); + /* TODO find correct res */ + + ASSERT(dal_fixed31_32_lt(arg, dal_fixed31_32_one)); + + do + res = dal_fixed31_32_add( + dal_fixed31_32_one, + dal_fixed31_32_div_int( + dal_fixed31_32_mul( + arg, + res), + n)); + while (--n != 1); + + return dal_fixed31_32_add( + dal_fixed31_32_one, + dal_fixed31_32_mul( + arg, + res)); +} + +struct fixed31_32 dal_fixed31_32_exp( + struct fixed31_32 arg) +{ + /* + * @brief + * Main equation is: + * exp(x) = exp(r + m * ln(2)) = (1 << m) * exp(r), + * where m = round(x / ln(2)), r = x - m * ln(2) + */ + + if (dal_fixed31_32_le( + dal_fixed31_32_ln2_div_2, + dal_fixed31_32_abs(arg))) { + int32_t m = dal_fixed31_32_round( + dal_fixed31_32_div( + arg, + dal_fixed31_32_ln2)); + + struct fixed31_32 r = dal_fixed31_32_sub( + arg, + dal_fixed31_32_mul_int( + dal_fixed31_32_ln2, + m)); + + ASSERT(m != 0); + + ASSERT(dal_fixed31_32_lt( + dal_fixed31_32_abs(r), + dal_fixed31_32_one)); + + if (m > 0) + return dal_fixed31_32_shl( + fixed31_32_exp_from_taylor_series(r), + (uint8_t)m); + else + return dal_fixed31_32_div_int( + fixed31_32_exp_from_taylor_series(r), + 1LL << -m); + } else if (arg.value != 0) + return fixed31_32_exp_from_taylor_series(arg); + else + return dal_fixed31_32_one; +} + +struct fixed31_32 dal_fixed31_32_log( + struct fixed31_32 arg) +{ + struct fixed31_32 res = dal_fixed31_32_neg(dal_fixed31_32_one); + /* TODO improve 1st estimation */ + + struct fixed31_32 error; + + ASSERT(arg.value > 0); + /* TODO if arg is negative, return NaN */ + /* TODO if arg is zero, return -INF */ + + do { + struct fixed31_32 res1 = dal_fixed31_32_add( + dal_fixed31_32_sub( + res, + dal_fixed31_32_one), + dal_fixed31_32_div( + arg, + dal_fixed31_32_exp(res))); + + error = dal_fixed31_32_sub( + res, + res1); + + res = res1; + /* TODO determine max_allowed_error based on quality of exp() */ + } while (abs_i64(error.value) > 100ULL); + + return res; +} + +struct fixed31_32 dal_fixed31_32_pow( + struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return dal_fixed31_32_exp( + dal_fixed31_32_mul( + dal_fixed31_32_log(arg1), + arg2)); +} + +int32_t dal_fixed31_32_floor( + struct fixed31_32 arg) +{ + uint64_t arg_value = abs_i64(arg.value); + + if (arg.value >= 0) + return (int32_t)GET_INTEGER_PART(arg_value); + else + return -(int32_t)GET_INTEGER_PART(arg_value); +} + +int32_t dal_fixed31_32_round( + struct fixed31_32 arg) +{ + uint64_t arg_value = abs_i64(arg.value); + + const int64_t summand = dal_fixed31_32_half.value; + + ASSERT(LLONG_MAX - (int64_t)arg_value >= summand); + + arg_value += summand; + + if (arg.value >= 0) + return (int32_t)GET_INTEGER_PART(arg_value); + else + return -(int32_t)GET_INTEGER_PART(arg_value); +} + +int32_t dal_fixed31_32_ceil( + struct fixed31_32 arg) +{ + uint64_t arg_value = abs_i64(arg.value); + + const int64_t summand = dal_fixed31_32_one.value - + dal_fixed31_32_epsilon.value; + + ASSERT(LLONG_MAX - (int64_t)arg_value >= summand); + + arg_value += summand; + + if (arg.value >= 0) + return (int32_t)GET_INTEGER_PART(arg_value); + else + return -(int32_t)GET_INTEGER_PART(arg_value); +} + +/* this function is a generic helper to translate fixed point value to + * specified integer format that will consist of integer_bits integer part and + * fractional_bits fractional part. For example it is used in + * dal_fixed31_32_u2d19 to receive 2 bits integer part and 19 bits fractional + * part in 32 bits. It is used in hw programming (scaler) + */ + +static inline uint32_t ux_dy( + int64_t value, + uint32_t integer_bits, + uint32_t fractional_bits) +{ + /* 1. create mask of integer part */ + uint32_t result = (1 << integer_bits) - 1; + /* 2. mask out fractional part */ + uint32_t fractional_part = FRACTIONAL_PART_MASK & value; + /* 3. shrink fixed point integer part to be of integer_bits width*/ + result &= GET_INTEGER_PART(value); + /* 4. make space for fractional part to be filled in after integer */ + result <<= fractional_bits; + /* 5. shrink fixed point fractional part to of fractional_bits width*/ + fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits; + /* 6. merge the result */ + return result | fractional_part; +} + +uint32_t dal_fixed31_32_u2d19( + struct fixed31_32 arg) +{ + return ux_dy(arg.value, 2, 19); +} + +uint32_t dal_fixed31_32_u0d19( + struct fixed31_32 arg) +{ + return ux_dy(arg.value, 0, 19); +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c new file mode 100644 index 000000000000..911e90bb1b5c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c @@ -0,0 +1,221 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/fixed32_32.h" + +static uint64_t u64_div(uint64_t n, uint64_t d) +{ + uint32_t i = 0; + uint64_t r; + uint64_t q = div64_u64_rem(n, d, &r); + + for (i = 0; i < 32; ++i) { + uint64_t sbit = q & (1ULL<<63); + + r <<= 1; + r |= sbit ? 1 : 0; + q <<= 1; + if (r >= d) { + r -= d; + q |= 1; + } + } + + if (2*r >= d) + q += 1; + return q; +} + +struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d) +{ + struct fixed32_32 fx; + + fx.value = u64_div((uint64_t)n << 32, (uint64_t)d << 32); + return fx; +} + +struct fixed32_32 dal_fixed32_32_from_int(uint32_t value) +{ + struct fixed32_32 fx; + + fx.value = (uint64_t)value<<32; + return fx; +} + +struct fixed32_32 dal_fixed32_32_add( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + struct fixed32_32 fx = {lhs.value + rhs.value}; + + ASSERT(fx.value >= rhs.value); + return fx; +} + +struct fixed32_32 dal_fixed32_32_add_int(struct fixed32_32 lhs, uint32_t rhs) +{ + struct fixed32_32 fx = {lhs.value + ((uint64_t)rhs << 32)}; + + ASSERT(fx.value >= (uint64_t)rhs << 32); + return fx; + +} +struct fixed32_32 dal_fixed32_32_sub( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + struct fixed32_32 fx; + + ASSERT(lhs.value >= rhs.value); + fx.value = lhs.value - rhs.value; + return fx; +} + +struct fixed32_32 dal_fixed32_32_sub_int(struct fixed32_32 lhs, uint32_t rhs) +{ + struct fixed32_32 fx; + + ASSERT(lhs.value >= ((uint64_t)rhs<<32)); + fx.value = lhs.value - ((uint64_t)rhs<<32); + return fx; +} + +struct fixed32_32 dal_fixed32_32_mul( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + struct fixed32_32 fx; + uint64_t lhs_int = lhs.value>>32; + uint64_t lhs_frac = (uint32_t)lhs.value; + uint64_t rhs_int = rhs.value>>32; + uint64_t rhs_frac = (uint32_t)rhs.value; + uint64_t ahbh = lhs_int * rhs_int; + uint64_t ahbl = lhs_int * rhs_frac; + uint64_t albh = lhs_frac * rhs_int; + uint64_t albl = lhs_frac * rhs_frac; + + ASSERT((ahbh>>32) == 0); + + fx.value = (ahbh<<32) + ahbl + albh + (albl>>32); + return fx; + +} + +struct fixed32_32 dal_fixed32_32_mul_int(struct fixed32_32 lhs, uint32_t rhs) +{ + struct fixed32_32 fx; + uint64_t lhsi = (lhs.value>>32) * (uint64_t)rhs; + uint64_t lhsf; + + ASSERT((lhsi>>32) == 0); + lhsf = ((uint32_t)lhs.value) * (uint64_t)rhs; + ASSERT((lhsi<<32) + lhsf >= lhsf); + fx.value = (lhsi<<32) + lhsf; + return fx; +} + +struct fixed32_32 dal_fixed32_32_div( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + struct fixed32_32 fx; + + fx.value = u64_div(lhs.value, rhs.value); + return fx; +} + +struct fixed32_32 dal_fixed32_32_div_int(struct fixed32_32 lhs, uint32_t rhs) +{ + struct fixed32_32 fx; + + fx.value = u64_div(lhs.value, (uint64_t)rhs << 32); + return fx; +} + +struct fixed32_32 dal_fixed32_32_min( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + return (lhs.value < rhs.value) ? lhs : rhs; +} + +struct fixed32_32 dal_fixed32_32_max( + struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + return (lhs.value > rhs.value) ? lhs : rhs; +} + +bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value > rhs.value; +} +bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value > ((uint64_t)rhs<<32); +} + +bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value < rhs.value; +} + +bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value <= rhs.value; +} + +bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value < ((uint64_t)rhs<<32); +} + +bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value <= ((uint64_t)rhs<<32); +} + +uint32_t dal_fixed32_32_ceil(struct fixed32_32 v) +{ + ASSERT((uint32_t)v.value ? (v.value >> 32) + 1 >= 1 : true); + return (v.value>>32) + ((uint32_t)v.value ? 1 : 0); +} + +uint32_t dal_fixed32_32_floor(struct fixed32_32 v) +{ + return v.value>>32; +} + +uint32_t dal_fixed32_32_round(struct fixed32_32 v) +{ + ASSERT(v.value + (1ULL<<31) >= (1ULL<<31)); + return (v.value + (1ULL<<31))>>32; +} + +bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value == rhs.value; +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c new file mode 100644 index 000000000000..9c80847d03a9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c @@ -0,0 +1,134 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/grph_object_id.h" + +bool dal_graphics_object_id_is_valid(struct graphics_object_id id) +{ + bool rc = true; + + switch (id.type) { + case OBJECT_TYPE_UNKNOWN: + rc = false; + break; + case OBJECT_TYPE_GPU: + case OBJECT_TYPE_ENGINE: + /* do NOT check for id.id == 0 */ + if (id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + default: + if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) + rc = false; + break; + } + + return rc; +} + +bool dal_graphics_object_id_is_equal( + struct graphics_object_id id1, + struct graphics_object_id id2) +{ + if (false == dal_graphics_object_id_is_valid(id1)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id1'!\n", __func__); + return false; + } + + if (false == dal_graphics_object_id_is_valid(id2)) { + dm_output_to_console( + "%s: Warning: comparing invalid object 'id2'!\n", __func__); + return false; + } + + if (id1.id == id2.id && id1.enum_id == id2.enum_id + && id1.type == id2.type) + return true; + + return false; +} + +/* Based on internal data members memory layout */ +uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id) +{ + uint32_t object_id = 0; + + object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc); + return object_id; +} + +/* + * ******* get specific ID - internal safe cast into specific type ******* + */ + +enum controller_id dal_graphics_object_id_get_controller_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONTROLLER) + return id.id; + return CONTROLLER_ID_UNDEFINED; +} + +enum clock_source_id dal_graphics_object_id_get_clock_source_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CLOCK_SOURCE) + return id.id; + return CLOCK_SOURCE_ID_UNDEFINED; +} + +enum encoder_id dal_graphics_object_id_get_encoder_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENCODER) + return id.id; + return ENCODER_ID_UNKNOWN; +} + +enum connector_id dal_graphics_object_id_get_connector_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONNECTOR) + return id.id; + return CONNECTOR_ID_UNKNOWN; +} + +enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_AUDIO) + return id.id; + return AUDIO_ID_UNKNOWN; +} + +enum engine_id dal_graphics_object_id_get_engine_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENGINE) + return id.id; + return ENGINE_ID_UNKNOWN; +} + diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c new file mode 100644 index 000000000000..61f36a7f322b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -0,0 +1,100 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "core_types.h" +#include "logger.h" +#include "include/logger_interface.h" + +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + +struct dc_signal_type_info { + enum signal_type type; + char name[MAX_NAME_LEN]; +}; + +static const struct dc_signal_type_info signal_type_info_tbl[] = { + {SIGNAL_TYPE_NONE, "NC"}, + {SIGNAL_TYPE_DVI_SINGLE_LINK, "DVI"}, + {SIGNAL_TYPE_DVI_DUAL_LINK, "DDVI"}, + {SIGNAL_TYPE_HDMI_TYPE_A, "HDMIA"}, + {SIGNAL_TYPE_LVDS, "LVDS"}, + {SIGNAL_TYPE_RGB, "VGA"}, + {SIGNAL_TYPE_DISPLAY_PORT, "DP"}, + {SIGNAL_TYPE_DISPLAY_PORT_MST, "MST"}, + {SIGNAL_TYPE_EDP, "eDP"}, + {SIGNAL_TYPE_WIRELESS, "Wireless"}, + {SIGNAL_TYPE_VIRTUAL, "Virtual"} +}; + +void dc_conn_log(struct dc_context *ctx, + const struct dc_link *link, + uint8_t *hex_data, + int hex_data_count, + enum dc_log_type event, + const char *msg, + ...) +{ + int i; + va_list args; + struct log_entry entry = { 0 }; + enum signal_type signal; + + if (link->local_sink) + signal = link->local_sink->sink_signal; + else + signal = link->connector_signal; + + if (link->type == dc_connection_mst_branch) + signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + + dm_logger_open(ctx->logger, &entry, event); + + for (i = 0; i < NUM_ELEMENTS(signal_type_info_tbl); i++) + if (signal == signal_type_info_tbl[i].type) + break; + + dm_logger_append(&entry, "[%s][ConnIdx:%d] ", + signal_type_info_tbl[i].name, + link->link_index); + + va_start(args, msg); + entry.buf_offset += dm_log_to_buffer( + &entry.buf[entry.buf_offset], + LOG_MAX_LINE_SIZE - entry.buf_offset, + msg, args); + + if (entry.buf[strlen(entry.buf) - 1] == '\n') { + entry.buf[strlen(entry.buf) - 1] = '\0'; + entry.buf_offset--; + } + + if (hex_data) + for (i = 0; i < hex_data_count; i++) + dm_logger_append(&entry, "%2.2X ", hex_data[i]); + + dm_logger_append(&entry, "^\n"); + dm_logger_close(&entry); + va_end(args); +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c new file mode 100644 index 000000000000..a5625a3badab --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -0,0 +1,457 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "include/logger_interface.h" +#include "logger.h" + + +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + +static const struct dc_log_type_info log_type_info_tbl[] = { + {LOG_ERROR, "Error"}, + {LOG_WARNING, "Warning"}, + {LOG_DC, "DC_Interface"}, + {LOG_SURFACE, "Surface"}, + {LOG_HW_HOTPLUG, "HW_Hotplug"}, + {LOG_HW_LINK_TRAINING, "HW_LKTN"}, + {LOG_HW_SET_MODE, "HW_Mode"}, + {LOG_HW_RESUME_S3, "HW_Resume"}, + {LOG_HW_AUDIO, "HW_Audio"}, + {LOG_HW_HPD_IRQ, "HW_HPDIRQ"}, + {LOG_MST, "MST"}, + {LOG_SCALER, "Scaler"}, + {LOG_BIOS, "BIOS"}, + {LOG_BANDWIDTH_CALCS, "BWCalcs"}, + {LOG_BANDWIDTH_VALIDATION, "BWValidation"}, + {LOG_I2C_AUX, "I2C_AUX"}, + {LOG_SYNC, "Sync"}, + {LOG_BACKLIGHT, "Backlight"}, + {LOG_FEATURE_OVERRIDE, "Override"}, + {LOG_DETECTION_EDID_PARSER, "Edid"}, + {LOG_DETECTION_DP_CAPS, "DP_Caps"}, + {LOG_RESOURCE, "Resource"}, + {LOG_DML, "DML"}, + {LOG_EVENT_MODE_SET, "Mode"}, + {LOG_EVENT_DETECTION, "Detect"}, + {LOG_EVENT_LINK_TRAINING, "LKTN"}, + {LOG_EVENT_LINK_LOSS, "LinkLoss"}, + {LOG_EVENT_UNDERFLOW, "Underflow"}, + {LOG_IF_TRACE, "InterfaceTrace"} +}; + + +#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \ + (1 << LOG_WARNING) | \ + (1 << LOG_EVENT_MODE_SET) | \ + (1 << LOG_EVENT_DETECTION) | \ + (1 << LOG_EVENT_LINK_TRAINING) | \ + (1 << LOG_EVENT_LINK_LOSS) | \ + (1 << LOG_EVENT_UNDERFLOW) | \ + (1 << LOG_RESOURCE) | \ + (1 << LOG_FEATURE_OVERRIDE) | \ + (1 << LOG_DETECTION_EDID_PARSER) | \ + (1 << LOG_DC) | \ + (1 << LOG_HW_HOTPLUG) | \ + (1 << LOG_HW_SET_MODE) | \ + (1 << LOG_HW_RESUME_S3) | \ + (1 << LOG_HW_HPD_IRQ) | \ + (1 << LOG_SYNC) | \ + (1 << LOG_BANDWIDTH_VALIDATION) | \ + (1 << LOG_MST) | \ + (1 << LOG_BIOS) | \ + (1 << LOG_DETECTION_EDID_PARSER) | \ + (1 << LOG_DETECTION_DP_CAPS) | \ + (1 << LOG_BACKLIGHT)) | \ + (1 << LOG_I2C_AUX) | \ + (1 << LOG_IF_TRACE) /* | \ + (1 << LOG_SURFACE) | \ + (1 << LOG_SCALER) | \ + (1 << LOG_DML) | \ + (1 << LOG_HW_LINK_TRAINING) | \ + (1 << LOG_HW_AUDIO)| \ + (1 << LOG_BANDWIDTH_CALCS)*/ + +/* ----------- Object init and destruction ----------- */ +static bool construct(struct dc_context *ctx, struct dal_logger *logger) +{ + /* malloc buffer and init offsets */ + logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; + logger->log_buffer = (char *)dm_alloc(logger->log_buffer_size * + sizeof(char)); + + if (!logger->log_buffer) + return false; + + /* Initialize both offsets to start of buffer (empty) */ + logger->buffer_read_offset = 0; + logger->buffer_write_offset = 0; + + logger->write_wrap_count = 0; + logger->read_wrap_count = 0; + logger->open_count = 0; + + logger->flags.bits.ENABLE_CONSOLE = 1; + logger->flags.bits.ENABLE_BUFFER = 0; + + logger->ctx = ctx; + + logger->mask = DC_DEFAULT_LOG_MASK; + + return true; +} + +static void destruct(struct dal_logger *logger) +{ + if (logger->log_buffer) { + dm_free(logger->log_buffer); + logger->log_buffer = NULL; + } +} + +struct dal_logger *dal_logger_create(struct dc_context *ctx) +{ + /* malloc struct */ + struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger)); + + if (!logger) + return NULL; + if (!construct(ctx, logger)) { + dm_free(logger); + return NULL; + } + + return logger; +} + +uint32_t dal_logger_destroy(struct dal_logger **logger) +{ + if (logger == NULL || *logger == NULL) + return 1; + destruct(*logger); + dm_free(*logger); + *logger = NULL; + + return 0; +} + +/* ------------------------------------------------------------------------ */ + + +static bool dal_logger_should_log( + struct dal_logger *logger, + enum dc_log_type log_type) +{ + if (logger->mask & (1 << log_type)) + return true; + + return false; +} + +static void log_to_debug_console(struct log_entry *entry) +{ + struct dal_logger *logger = entry->logger; + + if (logger->flags.bits.ENABLE_CONSOLE == 0) + return; + + if (entry->buf_offset) { + switch (entry->type) { + case LOG_ERROR: + dm_error("%s", entry->buf); + break; + default: + dm_output_to_console("%s", entry->buf); + break; + } + } +} + +/* Print everything unread existing in log_buffer to debug console*/ +static void flush_to_debug_console(struct dal_logger *logger) +{ + int i = logger->buffer_read_offset; + char *string_start = &logger->log_buffer[i]; + + dm_output_to_console( + "---------------- FLUSHING LOG BUFFER ----------------\n"); + while (i < logger->buffer_write_offset) { + + if (logger->log_buffer[i] == '\0') { + dm_output_to_console("%s", string_start); + string_start = (char *)logger->log_buffer + i + 1; + } + i++; + } + dm_output_to_console( + "-------------- END FLUSHING LOG BUFFER --------------\n\n"); +} + +static void log_to_internal_buffer(struct log_entry *entry) +{ + + uint32_t size = entry->buf_offset; + struct dal_logger *logger = entry->logger; + + if (logger->flags.bits.ENABLE_BUFFER == 0) + return; + + if (logger->log_buffer == NULL) + return; + + if (size > 0 && size < logger->log_buffer_size) { + + int total_free_space = 0; + int space_before_wrap = 0; + + if (logger->buffer_write_offset > logger->buffer_read_offset) { + total_free_space = logger->log_buffer_size - + logger->buffer_write_offset + + logger->buffer_read_offset; + space_before_wrap = logger->log_buffer_size - + logger->buffer_write_offset; + } else if (logger->buffer_write_offset < + logger->buffer_read_offset) { + total_free_space = logger->log_buffer_size - + logger->buffer_read_offset + + logger->buffer_write_offset; + space_before_wrap = total_free_space; + } else if (logger->write_wrap_count != + logger->read_wrap_count) { + /* Buffer is completely full already */ + total_free_space = 0; + space_before_wrap = 0; + } else { + /* Buffer is empty, start writing at beginning */ + total_free_space = logger->log_buffer_size; + space_before_wrap = logger->log_buffer_size; + logger->buffer_write_offset = 0; + logger->buffer_read_offset = 0; + } + + if (space_before_wrap > size) { + /* No wrap around, copy 'size' bytes + * from 'entry->buf' to 'log_buffer' + */ + memmove(logger->log_buffer + + logger->buffer_write_offset, + entry->buf, size); + logger->buffer_write_offset += size; + + } else if (total_free_space > size) { + /* We have enough room without flushing, + * but need to wrap around */ + + int space_after_wrap = total_free_space - + space_before_wrap; + + memmove(logger->log_buffer + + logger->buffer_write_offset, + entry->buf, space_before_wrap); + memmove(logger->log_buffer, entry->buf + + space_before_wrap, space_after_wrap); + + logger->buffer_write_offset = space_after_wrap; + logger->write_wrap_count++; + + } else { + /* Not enough room remaining, we should flush + * existing logs */ + + /* Flush existing unread logs to console */ + flush_to_debug_console(logger); + + /* Start writing to beginning of buffer */ + memmove(logger->log_buffer, entry->buf, size); + logger->buffer_write_offset = size; + logger->buffer_read_offset = 0; + } + + } +} + +static void log_heading(struct log_entry *entry) +{ + int j; + + for (j = 0; j < NUM_ELEMENTS(log_type_info_tbl); j++) { + + const struct dc_log_type_info *info = &log_type_info_tbl[j]; + + if (info->type == entry->type) + dm_logger_append(entry, "[%s]\t", info->name); + } +} + +static void append_entry( + struct log_entry *entry, + char *buffer, + uint32_t buf_size) +{ + if (!entry->buf || + entry->buf_offset + buf_size > entry->max_buf_bytes + ) { + BREAK_TO_DEBUGGER(); + return; + } + + /* Todo: check if off by 1 byte due to \0 anywhere */ + memmove(entry->buf + entry->buf_offset, buffer, buf_size); + entry->buf_offset += buf_size; +} + +/* ------------------------------------------------------------------------ */ + +/* Warning: Be careful that 'msg' is null terminated and the total size is + * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0' + */ +void dm_logger_write( + struct dal_logger *logger, + enum dc_log_type log_type, + const char *msg, + ...) +{ + if (logger && dal_logger_should_log(logger, log_type)) { + uint32_t size; + va_list args; + char buffer[LOG_MAX_LINE_SIZE]; + struct log_entry entry; + + va_start(args, msg); + + entry.logger = logger; + + entry.buf = buffer; + + entry.buf_offset = 0; + entry.max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char); + + entry.type = log_type; + + log_heading(&entry); + + size = dm_log_to_buffer( + buffer, LOG_MAX_LINE_SIZE, msg, args); + + entry.buf_offset += size; + + /* --Flush log_entry buffer-- */ + /* print to kernel console */ + log_to_debug_console(&entry); + /* log internally for dsat */ + log_to_internal_buffer(&entry); + + va_end(args); + } +} + +/* Same as dm_logger_write, except without open() and close(), which must + * be done separately. + */ +void dm_logger_append( + struct log_entry *entry, + const char *msg, + ...) +{ + struct dal_logger *logger; + + if (!entry) { + BREAK_TO_DEBUGGER(); + return; + } + + logger = entry->logger; + + if (logger && logger->open_count > 0 && + dal_logger_should_log(logger, entry->type)) { + + uint32_t size; + va_list args; + char buffer[LOG_MAX_LINE_SIZE]; + + va_start(args, msg); + + size = dm_log_to_buffer( + buffer, LOG_MAX_LINE_SIZE, msg, args); + + if (size < LOG_MAX_LINE_SIZE - 1) { + append_entry(entry, buffer, size); + } else { + append_entry(entry, "LOG_ERROR, line too long\n", 27); + } + + va_end(args); + } +} + +void dm_logger_open( + struct dal_logger *logger, + struct log_entry *entry, /* out */ + enum dc_log_type log_type) +{ + if (!entry) { + BREAK_TO_DEBUGGER(); + return; + } + + entry->type = log_type; + entry->logger = logger; + + entry->buf = dm_alloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char)); + + entry->buf_offset = 0; + entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char); + + logger->open_count++; + + log_heading(entry); +} + +void dm_logger_close(struct log_entry *entry) +{ + struct dal_logger *logger = entry->logger; + + if (logger && logger->open_count > 0) { + logger->open_count--; + } else { + BREAK_TO_DEBUGGER(); + goto cleanup; + } + + /* --Flush log_entry buffer-- */ + /* print to kernel console */ + log_to_debug_console(entry); + /* log internally for dsat */ + log_to_internal_buffer(entry); + + /* TODO: Write end heading */ + +cleanup: + if (entry->buf) { + dm_free(entry->buf); + entry->buf = NULL; + entry->buf_offset = 0; + entry->max_buf_bytes = 0; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.h b/drivers/gpu/drm/amd/display/dc/basics/logger.h new file mode 100644 index 000000000000..2f7a5df4c811 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.h @@ -0,0 +1,67 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_LOGGER_H__ +#define __DAL_LOGGER_H__ + +/* Structure for keeping track of offsets, buffer, etc */ + +#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 + +/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes, + * change log line size to 896 to meet the request. + */ +#define LOG_MAX_LINE_SIZE 896 + +#include "include/logger_types.h" + +struct dal_logger { + + /* How far into the circular buffer has been read by dsat + * Read offset should never cross write offset. Write \0's to + * read data just to be sure? + */ + uint32_t buffer_read_offset; + + /* How far into the circular buffer we have written + * Write offset should never cross read offset + */ + uint32_t buffer_write_offset; + + uint32_t write_wrap_count; + uint32_t read_wrap_count; + + uint32_t open_count; + + char *log_buffer; /* Pointer to malloc'ed buffer */ + uint32_t log_buffer_size; /* Size of circular buffer */ + + uint32_t mask; /*array of masks for major elements*/ + + union logger_flags flags; + struct dc_context *ctx; +}; + +#endif /* __DAL_LOGGER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/basics/register_logger.c b/drivers/gpu/drm/amd/display/dc/basics/register_logger.c new file mode 100644 index 000000000000..b8d57d919fe4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/register_logger.c @@ -0,0 +1,197 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/dal_types.h" +#include "include/logger_interface.h" +#include "logger.h" + +/****************************************************************************** + * Register Logger. + * A facility to create register R/W logs. + * Currently used for DAL Test. + *****************************************************************************/ + +/****************************************************************************** + * Private structures + *****************************************************************************/ +struct dal_reg_dump_stack_location { + const char *current_caller_func; + long current_pid; + long current_tgid; + uint32_t rw_count;/* register access counter for current function. */ +}; + +/* This the maximum number of nested calls to the 'reg_dump' facility. */ +#define DAL_REG_DUMP_STACK_MAX_SIZE 32 + +struct dal_reg_dump_stack { + int32_t stack_pointer; + struct dal_reg_dump_stack_location + stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE]; + uint32_t total_rw_count; /* Total count for *all* functions. */ +}; + +static struct dal_reg_dump_stack reg_dump_stack = {0}; + +/****************************************************************************** + * Private functions + *****************************************************************************/ + +/* Check if current process is the one which requested register dump. + * The reason for the check: + * mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter(). + * Which runs all the time when at least one display is connected. + * (Triggered by drm_mode_page_flip_ioctl()). */ +static bool is_reg_dump_process(void) +{ + uint32_t i; + + /* walk the list of our processes */ + for (i = 0; i < reg_dump_stack.stack_pointer; i++) { + struct dal_reg_dump_stack_location *stack_location + = ®_dump_stack.stack_locations[i]; + + if (stack_location->current_pid == dm_get_pid() + && stack_location->current_tgid == dm_get_tgid()) + return true; + } + + return false; +} + +static bool dal_reg_dump_stack_is_empty(void) +{ + if (reg_dump_stack.stack_pointer <= 0) + return true; + else + return false; +} + +static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void) +{ + struct dal_reg_dump_stack_location *current_location = NULL; + + if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) { + /* stack is full */ + dm_output_to_console("[REG_DUMP]: %s: stack is full!\n", + __func__); + } else { + current_location = + ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; + ++reg_dump_stack.stack_pointer; + } + + return current_location; +} + +static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void) +{ + struct dal_reg_dump_stack_location *current_location = NULL; + + if (dal_reg_dump_stack_is_empty()) { + /* stack is empty */ + dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n", + __func__); + } else { + --reg_dump_stack.stack_pointer; + current_location = + ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; + } + + return current_location; +} + +/****************************************************************************** + * Public functions + *****************************************************************************/ + +void dal_reg_logger_push(const char *caller_func) +{ + struct dal_reg_dump_stack_location *free_stack_location; + + free_stack_location = dal_reg_dump_stack_push(); + + if (NULL == free_stack_location) + return; + + memset(free_stack_location, 0, sizeof(*free_stack_location)); + + free_stack_location->current_caller_func = caller_func; + free_stack_location->current_pid = dm_get_pid(); + free_stack_location->current_tgid = dm_get_tgid(); + + dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n", + caller_func, + free_stack_location->current_pid, + free_stack_location->current_tgid); +} + +void dal_reg_logger_pop(void) +{ + struct dal_reg_dump_stack_location *top_stack_location; + + top_stack_location = dal_reg_dump_stack_pop(); + + if (NULL == top_stack_location) { + dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n", + __func__); + return; + } + + dm_output_to_console( + "[REG_DUMP]:%s - end."\ + " Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n", + top_stack_location->current_caller_func, + reg_dump_stack.total_rw_count, + top_stack_location->rw_count, + dm_get_pid(), + dm_get_tgid()); + + memset(top_stack_location, 0, sizeof(*top_stack_location)); +} + +void dal_reg_logger_rw_count_increment(void) +{ + ++reg_dump_stack.total_rw_count; + + ++reg_dump_stack.stack_locations + [reg_dump_stack.stack_pointer - 1].rw_count; +} + +bool dal_reg_logger_should_dump_register(void) +{ + if (true == dal_reg_dump_stack_is_empty()) + return false; + + if (false == is_reg_dump_process()) + return false; + + return true; +} + +/****************************************************************************** + * End of File. + *****************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c new file mode 100644 index 000000000000..44447e07803a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c @@ -0,0 +1,116 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/signal_types.h" + +bool dc_is_hdmi_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_HDMI_TYPE_A); +} + +bool dc_is_dp_sst_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP); +} + +bool dc_is_dp_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST); +} + +bool dc_is_dp_external_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST); +} + +bool dc_is_analog_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_RGB: + return true; + break; + default: + return false; + } +} + +bool dc_is_embedded_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); +} + +bool dc_is_dvi_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return true; + break; + default: + return false; + } +} + +bool dc_is_dvi_single_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); +} + +bool dc_is_dual_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_DUAL_LINK); +} + +bool dc_is_audio_capable_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + dc_is_hdmi_signal(signal) || + signal == SIGNAL_TYPE_WIRELESS); +} + +/* + * @brief + * Returns whether the signal is compatible + * with other digital encoder signal types. + * This is true for DVI, LVDS, and HDMI signal types. + */ +bool dc_is_digital_encoder_compatible_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + case SIGNAL_TYPE_LVDS: + return true; + default: + return false; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c new file mode 100644 index 000000000000..bb72a1857160 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -0,0 +1,307 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/vector.h" + +bool dal_vector_construct( + struct vector *vector, + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size) +{ + vector->container = NULL; + + if (!struct_size || !capacity) { + /* Container must be non-zero size*/ + BREAK_TO_DEBUGGER(); + return false; + } + + vector->container = dm_alloc(struct_size * capacity); + if (vector->container == NULL) + return false; + vector->capacity = capacity; + vector->struct_size = struct_size; + vector->count = 0; + vector->ctx = ctx; + return true; +} + +bool dal_vector_presized_costruct( + struct vector *vector, + struct dc_context *ctx, + uint32_t count, + void *initial_value, + uint32_t struct_size) +{ + uint32_t i; + + vector->container = NULL; + + if (!struct_size || !count) { + /* Container must be non-zero size*/ + BREAK_TO_DEBUGGER(); + return false; + } + + vector->container = dm_alloc(struct_size * count); + + if (vector->container == NULL) + return false; + + /* If caller didn't supply initial value then the default + * of all zeros is expected, which is exactly what dal_alloc() + * initialises the memory to. */ + if (NULL != initial_value) { + for (i = 0; i < count; ++i) + memmove( + vector->container + i * struct_size, + initial_value, + struct_size); + } + + vector->capacity = count; + vector->struct_size = struct_size; + vector->count = count; + return true; +} + +struct vector *dal_vector_presized_create( + struct dc_context *ctx, + uint32_t size, + void *initial_value, + uint32_t struct_size) +{ + struct vector *vector = dm_alloc(sizeof(struct vector)); + + if (vector == NULL) + return NULL; + + if (dal_vector_presized_costruct( + vector, ctx, size, initial_value, struct_size)) + return vector; + + BREAK_TO_DEBUGGER(); + dm_free(vector); + return NULL; +} + +struct vector *dal_vector_create( + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size) +{ + struct vector *vector = dm_alloc(sizeof(struct vector)); + + if (vector == NULL) + return NULL; + + if (dal_vector_construct(vector, ctx, capacity, struct_size)) + return vector; + + BREAK_TO_DEBUGGER(); + dm_free(vector); + return NULL; +} + +void dal_vector_destruct( + struct vector *vector) +{ + if (vector->container != NULL) + dm_free(vector->container); + vector->count = 0; + vector->capacity = 0; +} + +void dal_vector_destroy( + struct vector **vector) +{ + if (vector == NULL || *vector == NULL) + return; + dal_vector_destruct(*vector); + dm_free(*vector); + *vector = NULL; +} + +uint32_t dal_vector_get_count( + const struct vector *vector) +{ + return vector->count; +} + +void *dal_vector_at_index( + const struct vector *vector, + uint32_t index) +{ + if (vector->container == NULL || index >= vector->count) + return NULL; + return vector->container + (index * vector->struct_size); +} + +bool dal_vector_remove_at_index( + struct vector *vector, + uint32_t index) +{ + if (index >= vector->count) + return false; + + if (index != vector->count - 1) + memmove( + vector->container + (index * vector->struct_size), + vector->container + ((index + 1) * vector->struct_size), + (vector->count - index - 1) * vector->struct_size); + vector->count -= 1; + + return true; +} + +void dal_vector_set_at_index( + const struct vector *vector, + const void *what, + uint32_t index) +{ + void *where = dal_vector_at_index(vector, index); + + if (!where) { + BREAK_TO_DEBUGGER(); + return; + } + memmove( + where, + what, + vector->struct_size); +} + +static inline uint32_t calc_increased_capacity( + uint32_t old_capacity) +{ + return old_capacity * 2; +} + +bool dal_vector_insert_at( + struct vector *vector, + const void *what, + uint32_t position) +{ + uint8_t *insert_address; + + if (vector->count == vector->capacity) { + if (!dal_vector_reserve( + vector, + calc_increased_capacity(vector->capacity))) + return false; + } + + insert_address = vector->container + (vector->struct_size * position); + + if (vector->count && position < vector->count) + memmove( + insert_address + vector->struct_size, + insert_address, + vector->struct_size * (vector->count - position)); + + memmove( + insert_address, + what, + vector->struct_size); + + vector->count++; + + return true; +} + +bool dal_vector_append( + struct vector *vector, + const void *item) +{ + return dal_vector_insert_at(vector, item, vector->count); +} + +struct vector *dal_vector_clone( + const struct vector *vector) +{ + struct vector *vec_cloned; + uint32_t count; + + /* create new vector */ + count = dal_vector_get_count(vector); + + if (count == 0) + /* when count is 0 we still want to create clone of the vector + */ + vec_cloned = dal_vector_create( + vector->ctx, + vector->capacity, + vector->struct_size); + else + /* Call "presized create" version, independently of how the + * original vector was created. + * The owner of original vector must know how to treat the new + * vector - as "presized" or as "regular". + * But from vector point of view it doesn't matter. */ + vec_cloned = dal_vector_presized_create(vector->ctx, count, + NULL,/* no initial value */ + vector->struct_size); + + if (NULL == vec_cloned) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + /* copy vector's data */ + memmove(vec_cloned->container, vector->container, + vec_cloned->struct_size * vec_cloned->capacity); + + return vec_cloned; +} + +uint32_t dal_vector_capacity(const struct vector *vector) +{ + return vector->capacity; +} + +bool dal_vector_reserve(struct vector *vector, uint32_t capacity) +{ + void *new_container; + + if (capacity <= vector->capacity) + return true; + + new_container = dm_realloc(vector->container, capacity * vector->struct_size); + + if (new_container) { + vector->container = new_container; + vector->capacity = capacity; + return true; + } + + return false; +} + +void dal_vector_clear(struct vector *vector) +{ + vector->count = 0; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile new file mode 100644 index 000000000000..9ba677f0ff01 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -0,0 +1,24 @@ +# +# Makefile for the 'bios' sub-component of DAL. +# It provides the parsing and executing controls for atom bios image. + +BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o + +AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS)) + +AMD_DISPLAY_FILES += $(AMD_DAL_BIOS) + +############################################################################### +# DCE 8x +############################################################################### +# All DCE8.x are derived from DCE8.0, so 8.0 MUST be defined if ANY of +# DCE8.x is compiled. +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce80/command_table_helper_dce80.o + +############################################################################### +# DCE 11x +############################################################################### +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o + +ccflags-y += -DLATEST_ATOM_BIOS_SUPPORT +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c new file mode 100644 index 000000000000..ebd2e419f8f2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -0,0 +1,4220 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "dc_bios_types.h" +#include "include/gpio_service_interface.h" +#include "include/grph_object_ctrl_defs.h" +#include "include/bios_parser_interface.h" +#include "include/i2caux_interface.h" +#include "include/logger_interface.h" + +#include "command_table.h" +#include "bios_parser_helper.h" +#include "command_table_helper.h" +#include "bios_parser.h" +#include "bios_parser_types_internal.h" +#include "bios_parser_interface.h" + +/* TODO remove - only needed for default i2c speed */ +#include "dc.h" + +#define THREE_PERCENT_OF_10000 300 + +#define LAST_RECORD_TYPE 0xff + +/* GUID to validate external display connection info table (aka OPM module) */ +static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = { + 0x91, 0x6E, 0x57, 0x09, + 0x3F, 0x6D, 0xD2, 0x11, + 0x39, 0x8E, 0x00, 0xA0, + 0xC9, 0x69, 0x72, 0x3B}; + +#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table) + +static enum object_type object_type_from_bios_object_id( + uint32_t bios_object_id); +static struct graphics_object_id object_id_from_bios_object_id( + uint32_t bios_object_id); +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id); +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id); +static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); +static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); +static void get_atom_data_table_revision( + ATOM_COMMON_TABLE_HEADER *atom_data_tbl, + struct atom_data_revision *tbl_revision); +static uint32_t get_dst_number_from_object(struct bios_parser *bp, + ATOM_OBJECT *object); +static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, + uint16_t **id_list); +static uint32_t get_dest_obj_list(struct bios_parser *bp, + ATOM_OBJECT *object, uint16_t **id_list); +static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, + struct graphics_object_id id); +static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, + ATOM_I2C_RECORD *record, + struct graphics_object_i2c_info *info); +static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, + ATOM_OBJECT *object); +static struct device_id device_type_from_device_id(uint16_t device_id); +static uint32_t signal_to_ss_id(enum as_signal_type signal); +static uint32_t get_support_mask_for_device_id(struct device_id device_id); +static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( + struct bios_parser *bp, + ATOM_OBJECT *object); + +#define BIOS_IMAGE_SIZE_OFFSET 2 +#define BIOS_IMAGE_SIZE_UNIT 512 + +/*****************************************************************************/ +static bool bios_parser_construct( + struct bios_parser *bp, + struct bp_init_data *init, + enum dce_version dce_version); + +static uint8_t bios_parser_get_connectors_number( + struct dc_bios *dcb); + +static enum bp_result bios_parser_get_embedded_panel_info( + struct dc_bios *dcb, + struct embedded_panel_info *info); + +/*****************************************************************************/ + +struct dc_bios *bios_parser_create( + struct bp_init_data *init, + enum dce_version dce_version) +{ + struct bios_parser *bp = NULL; + + bp = dm_alloc(sizeof(struct bios_parser)); + if (!bp) + return NULL; + + if (bios_parser_construct(bp, init, dce_version)) + return &bp->base; + + dm_free(bp); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void destruct(struct bios_parser *bp) +{ + if (bp->base.bios_local_image) + dm_free(bp->base.bios_local_image); + + if (bp->base.integrated_info) + dm_free(bp->base.integrated_info); +} + +static void bios_parser_destroy(struct dc_bios **dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(*dcb); + + if (!bp) { + BREAK_TO_DEBUGGER(); + return; + } + + destruct(bp); + + dm_free(bp); + *dcb = NULL; +} + +static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset) +{ + ATOM_OBJECT_TABLE *table; + + uint32_t object_table_offset = bp->object_info_tbl_offset + offset; + + table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset); + + if (!table) + return 0; + else + return table->ucNumberOfObjects; +} + +static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + return get_number_of_objects(bp, + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset)); +} + +static struct graphics_object_id bios_parser_get_encoder_id( + struct dc_bios *dcb, + uint32_t i) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct graphics_object_id object_id = dal_graphics_object_id_init( + 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + + uint32_t encoder_table_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); + + ATOM_OBJECT_TABLE *tbl = + GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); + + if (tbl && tbl->ucNumberOfObjects > i) { + const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID); + + object_id = object_id_from_bios_object_id(id); + } + + return object_id; +} + +static struct graphics_object_id bios_parser_get_connector_id( + struct dc_bios *dcb, + uint8_t i) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct graphics_object_id object_id = dal_graphics_object_id_init( + 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + + uint32_t connector_table_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + + ATOM_OBJECT_TABLE *tbl = + GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset); + + if (tbl && tbl->ucNumberOfObjects > i) { + const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID); + + object_id = object_id_from_bios_object_id(id); + } + + return object_id; +} + +static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb, + struct graphics_object_id id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_OBJECT *object = get_bios_object(bp, id); + + return get_dst_number_from_object(bp, object); +} + +static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *src_object_id) +{ + uint32_t number; + uint16_t *id; + ATOM_OBJECT *object; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!src_object_id) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return BP_RESULT_BADINPUT; + } + + number = get_src_obj_list(bp, object, &id); + + if (number <= index) + return BP_RESULT_BADINPUT; + + *src_object_id = object_id_from_bios_object_id(id[index]); + + return BP_RESULT_OK; +} + +static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *dest_object_id) +{ + uint32_t number; + uint16_t *id; + ATOM_OBJECT *object; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!dest_object_id) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + number = get_dest_obj_list(bp, object, &id); + + if (number <= index) + return BP_RESULT_BADINPUT; + + *dest_object_id = object_id_from_bios_object_id(id[index]); + + return BP_RESULT_OK; +} + +static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_i2c_info *info) +{ + uint32_t offset; + ATOM_OBJECT *object; + ATOM_COMMON_RECORD_HEADER *header; + ATOM_I2C_RECORD *record; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_I2C_RECORD_TYPE == header->ucRecordType + && sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) { + /* get the I2C info */ + record = (ATOM_I2C_RECORD *) header; + + if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK) + return BP_RESULT_OK; + } + + offset += header->ucRecordSize; + } + + return BP_RESULT_NORECORD; +} + +static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line, + ATOM_COMMON_TABLE_HEADER *header, + uint8_t *address) +{ + enum bp_result result = BP_RESULT_NORECORD; + ATOM_VOLTAGE_OBJECT_INFO *info = + (ATOM_VOLTAGE_OBJECT_INFO *) address; + + uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0]; + + while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) { + ATOM_VOLTAGE_OBJECT *object = + (ATOM_VOLTAGE_OBJECT *) voltage_current_object; + + if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) && + (object->ucVoltageType & + VOLTAGE_CONTROLLED_BY_I2C_MASK)) { + + *i2c_line = object->asControl.ucVoltageControlI2cLine + ^ 0x90; + result = BP_RESULT_OK; + break; + } + + voltage_current_object += object->ucSize; + } + return result; +} + +static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line, + uint32_t index, + ATOM_COMMON_TABLE_HEADER *header, + uint8_t *address) +{ + enum bp_result result = BP_RESULT_NORECORD; + ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info = + (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address; + + uint8_t *voltage_current_object = + (uint8_t *) (&(info->asVoltageObj[0])); + + while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) { + ATOM_I2C_VOLTAGE_OBJECT_V3 *object = + (ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object; + + if (object->sHeader.ucVoltageMode == + ATOM_INIT_VOLTAGE_REGULATOR) { + if (object->sHeader.ucVoltageType == index) { + *i2c_line = object->ucVoltageControlI2cLine + ^ 0x90; + result = BP_RESULT_OK; + break; + } + } + + voltage_current_object += le16_to_cpu(object->sHeader.usSize); + } + return result; +} + +static enum bp_result bios_parser_get_thermal_ddc_info( + struct dc_bios *dcb, + uint32_t i2c_channel_id, + struct graphics_object_i2c_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_I2C_ID_CONFIG_ACCESS *config; + ATOM_I2C_RECORD record; + + if (!info) + return BP_RESULT_BADINPUT; + + config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id; + + record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable; + record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux; + record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID; + + return get_gpio_i2c_info(bp, &record, info); +} + +static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, + uint32_t index, + struct graphics_object_i2c_info *info) +{ + uint8_t i2c_line = 0; + enum bp_result result = BP_RESULT_NORECORD; + uint8_t *voltage_info_address; + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision revision = {0}; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!DATA_TABLES(VoltageObjectInfo)) + return result; + + voltage_info_address = get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER)); + + header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address; + + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 1: + case 2: + result = get_voltage_ddc_info_v1(&i2c_line, header, + voltage_info_address); + break; + case 3: + if (revision.minor != 1) + break; + result = get_voltage_ddc_info_v3(&i2c_line, index, header, + voltage_info_address); + break; + } + + if (result == BP_RESULT_OK) + result = bios_parser_get_thermal_ddc_info(dcb, + i2c_line, info); + + return result; +} + +/* TODO: temporary commented out to suppress 'defined but not used' warning */ +#if 0 +static enum bp_result bios_parser_get_ddc_info_for_i2c_line( + struct bios_parser *bp, + uint8_t i2c_line, struct graphics_object_i2c_info *info) +{ + uint32_t offset; + ATOM_OBJECT *object; + ATOM_OBJECT_TABLE *table; + uint32_t i; + + if (!info) + return BP_RESULT_BADINPUT; + + offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + + offset += bp->object_info_tbl_offset; + + table = GET_IMAGE(ATOM_OBJECT_TABLE, offset); + + if (!table) + return BP_RESULT_BADBIOSTABLE; + + for (i = 0; i < table->ucNumberOfObjects; i++) { + object = &table->asObjects[i]; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return BP_RESULT_BADINPUT; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + ATOM_COMMON_RECORD_HEADER *header = + GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + offset += header->ucRecordSize; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_I2C_RECORD_TYPE == header->ucRecordType + && sizeof(ATOM_I2C_RECORD) <= + header->ucRecordSize) { + ATOM_I2C_RECORD *record = + (ATOM_I2C_RECORD *) header; + + if (i2c_line != record->sucI2cId.bfI2C_LineMux) + continue; + + /* get the I2C info */ + if (get_gpio_i2c_info(bp, record, info) == + BP_RESULT_OK) + return BP_RESULT_OK; + } + } + } + + return BP_RESULT_NORECORD; +} +#endif + +static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_hpd_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_OBJECT *object; + ATOM_HPD_INT_RECORD *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_hpd_record(bp, object); + + if (record != NULL) { + info->hpd_int_gpio_uid = record->ucHPDIntGPIOID; + info->hpd_active = record->ucPlugged_PinState; + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static uint32_t bios_parser_get_gpio_record( + struct dc_bios *dcb, + struct graphics_object_id id, + struct bp_gpio_cntl_info *gpio_record, + uint32_t record_size) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_COMMON_RECORD_HEADER *header = NULL; + ATOM_OBJECT_GPIO_CNTL_RECORD *record = NULL; + ATOM_OBJECT *object = get_bios_object(bp, id); + uint32_t offset; + uint32_t pins_number; + uint32_t i; + + if (!object) + return 0; + + /* Initialise offset */ + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + /* Get record header */ + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + if (!header || header->ucRecordType == LAST_RECORD_TYPE || + !header->ucRecordSize) + break; + + /* If this is gpio control record - stop. We found the record */ + if (header->ucRecordType == ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE + && header->ucRecordSize + >= sizeof(ATOM_OBJECT_GPIO_CNTL_RECORD)) { + record = (ATOM_OBJECT_GPIO_CNTL_RECORD *) header; + break; + } + + /* Advance to next record */ + offset += header->ucRecordSize; + } + + /* If we did not find a record - return */ + if (!record) + return 0; + + /* Extract gpio IDs from bios record (make sure we do not exceed passed + * array size) */ + pins_number = (record->ucNumberOfPins < record_size ? + record->ucNumberOfPins : record_size); + for (i = 0; i < pins_number; i++) { + uint8_t output_state = ((record->asGpio[i].ucGPIO_PinState + & GPIO_PIN_OUTPUT_STATE_MASK) + >> GPIO_PIN_OUTPUT_STATE_SHIFT); + gpio_record[i].id = record->asGpio[i].ucGPIOID; + + switch (output_state) { + case GPIO_PIN_STATE_ACTIVE_LOW: + gpio_record[i].state = + GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW; + break; + + case GPIO_PIN_STATE_ACTIVE_HIGH: + gpio_record[i].state = + GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH; + break; + + default: + BREAK_TO_DEBUGGER(); /* Invalid Pin Output State */ + break; + } + } + + return pins_number; +} + +enum bp_result bios_parser_get_device_tag_record( + struct bios_parser *bp, + ATOM_OBJECT *object, + ATOM_CONNECTOR_DEVICE_TAG_RECORD **record) +{ + ATOM_COMMON_RECORD_HEADER *header; + uint32_t offset; + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + offset += header->ucRecordSize; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE != + header->ucRecordType) + continue; + + if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize) + continue; + + *record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header; + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static enum bp_result bios_parser_get_device_tag( + struct dc_bios *dcb, + struct graphics_object_id connector_object_id, + uint32_t device_tag_index, + struct connector_device_tag_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_OBJECT *object; + ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL; + ATOM_CONNECTOR_DEVICE_TAG *device_tag; + + if (!info) + return BP_RESULT_BADINPUT; + + /* getBiosObject will return MXM object */ + object = get_bios_object(bp, connector_object_id); + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return BP_RESULT_BADINPUT; + } + + if (bios_parser_get_device_tag_record(bp, object, &record) + != BP_RESULT_OK) + return BP_RESULT_NORECORD; + + if (device_tag_index >= record->ucNumberOfDevice) + return BP_RESULT_NORECORD; + + device_tag = &record->asDeviceTag[device_tag_index]; + + info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum); + info->dev_id = + device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID)); + + return BP_RESULT_OK; +} + +static enum bp_result get_firmware_info_v1_4( + struct bios_parser *bp, + struct firmware_info *info); +static enum bp_result get_firmware_info_v2_1( + struct bios_parser *bp, + struct firmware_info *info); +static enum bp_result get_firmware_info_v2_2( + struct bios_parser *bp, + struct firmware_info *info); + +static enum bp_result bios_parser_get_firmware_info( + struct dc_bios *dcb, + struct firmware_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_BADBIOSTABLE; + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision revision; + + if (info && DATA_TABLES(FirmwareInfo)) { + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + DATA_TABLES(FirmwareInfo)); + get_atom_data_table_revision(header, &revision); + switch (revision.major) { + case 1: + switch (revision.minor) { + case 4: + result = get_firmware_info_v1_4(bp, info); + break; + default: + break; + } + break; + + case 2: + switch (revision.minor) { + case 1: + result = get_firmware_info_v2_1(bp, info); + break; + case 2: + result = get_firmware_info_v2_2(bp, info); + break; + default: + break; + } + break; + default: + break; + } + } + + return result; +} + +static enum bp_result get_firmware_info_v1_4( + struct bios_parser *bp, + struct firmware_info *info) +{ + ATOM_FIRMWARE_INFO_V1_4 *firmware_info = + GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4, + DATA_TABLES(FirmwareInfo)); + + if (!info) + return BP_RESULT_BADINPUT; + + if (!firmware_info) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + /* Pixel clock pll information. We need to convert from 10KHz units into + * KHz units */ + info->pll_info.crystal_frequency = + le16_to_cpu(firmware_info->usReferenceClock) * 10; + info->pll_info.min_input_pxl_clk_pll_frequency = + le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10; + info->pll_info.max_input_pxl_clk_pll_frequency = + le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10; + info->pll_info.min_output_pxl_clk_pll_frequency = + le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; + info->pll_info.max_output_pxl_clk_pll_frequency = + le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; + + if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) + /* Since there is no information on the SS, report conservative + * value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; + + if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support) + /* Since there is no information on the SS,report conservative + * value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; + + return BP_RESULT_OK; +} + +static enum bp_result get_ss_info_v3_1( + struct bios_parser *bp, + uint32_t id, + uint32_t index, + struct spread_spectrum_info *ss_info); + +static enum bp_result get_firmware_info_v2_1( + struct bios_parser *bp, + struct firmware_info *info) +{ + ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo = + GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo)); + struct spread_spectrum_info internalSS; + uint32_t index; + + if (!info) + return BP_RESULT_BADINPUT; + + if (!firmwareInfo) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + /* Pixel clock pll information. We need to convert from 10KHz units into + * KHz units */ + info->pll_info.crystal_frequency = + le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10; + info->pll_info.min_input_pxl_clk_pll_frequency = + le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10; + info->pll_info.max_input_pxl_clk_pll_frequency = + le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10; + info->pll_info.min_output_pxl_clk_pll_frequency = + le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10; + info->pll_info.max_output_pxl_clk_pll_frequency = + le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10; + info->default_display_engine_pll_frequency = + le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10; + info->external_clock_source_frequency_for_dp = + le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10; + info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level; + + /* There should be only one entry in the SS info table for Memory Clock + */ + index = 0; + if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) + /* Since there is no information for external SS, report + * conservative value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; + else if (get_ss_info_v3_1(bp, + ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) { + if (internalSS.spread_spectrum_percentage) { + info->feature.memory_clk_ss_percentage = + internalSS.spread_spectrum_percentage; + if (internalSS.type.CENTER_MODE) { + /* if it is centermode, the exact SS Percentage + * will be round up of half of the percentage + * reported in the SS table */ + ++info->feature.memory_clk_ss_percentage; + info->feature.memory_clk_ss_percentage /= 2; + } + } + } + + /* There should be only one entry in the SS info table for Engine Clock + */ + index = 1; + if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support) + /* Since there is no information for external SS, report + * conservative value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; + else if (get_ss_info_v3_1(bp, + ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) { + if (internalSS.spread_spectrum_percentage) { + info->feature.engine_clk_ss_percentage = + internalSS.spread_spectrum_percentage; + if (internalSS.type.CENTER_MODE) { + /* if it is centermode, the exact SS Percentage + * will be round up of half of the percentage + * reported in the SS table */ + ++info->feature.engine_clk_ss_percentage; + info->feature.engine_clk_ss_percentage /= 2; + } + } + } + + return BP_RESULT_OK; +} + +static enum bp_result get_firmware_info_v2_2( + struct bios_parser *bp, + struct firmware_info *info) +{ + ATOM_FIRMWARE_INFO_V2_2 *firmware_info; + struct spread_spectrum_info internal_ss; + uint32_t index; + + if (!info) + return BP_RESULT_BADINPUT; + + firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2, + DATA_TABLES(FirmwareInfo)); + + if (!firmware_info) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + /* Pixel clock pll information. We need to convert from 10KHz units into + * KHz units */ + info->pll_info.crystal_frequency = + le16_to_cpu(firmware_info->usCoreReferenceClock) * 10; + info->pll_info.min_input_pxl_clk_pll_frequency = + le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10; + info->pll_info.max_input_pxl_clk_pll_frequency = + le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10; + info->pll_info.min_output_pxl_clk_pll_frequency = + le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; + info->pll_info.max_output_pxl_clk_pll_frequency = + le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; + info->default_display_engine_pll_frequency = + le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10; + info->external_clock_source_frequency_for_dp = + le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10; + + /* There should be only one entry in the SS info table for Memory Clock + */ + index = 0; + if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) + /* Since there is no information for external SS, report + * conservative value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; + else if (get_ss_info_v3_1(bp, + ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) { + if (internal_ss.spread_spectrum_percentage) { + info->feature.memory_clk_ss_percentage = + internal_ss.spread_spectrum_percentage; + if (internal_ss.type.CENTER_MODE) { + /* if it is centermode, the exact SS Percentage + * will be round up of half of the percentage + * reported in the SS table */ + ++info->feature.memory_clk_ss_percentage; + info->feature.memory_clk_ss_percentage /= 2; + } + } + } + + /* There should be only one entry in the SS info table for Engine Clock + */ + index = 1; + if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support) + /* Since there is no information for external SS, report + * conservative value 3% for bandwidth calculation */ + /* unit of 0.01% */ + info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; + else if (get_ss_info_v3_1(bp, + ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) { + if (internal_ss.spread_spectrum_percentage) { + info->feature.engine_clk_ss_percentage = + internal_ss.spread_spectrum_percentage; + if (internal_ss.type.CENTER_MODE) { + /* if it is centermode, the exact SS Percentage + * will be round up of half of the percentage + * reported in the SS table */ + ++info->feature.engine_clk_ss_percentage; + info->feature.engine_clk_ss_percentage /= 2; + } + } + } + + /* Remote Display */ + info->remote_display_config = firmware_info->ucRemoteDisplayConfig; + + /* Is allowed minimum BL level */ + info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level; + /* Used starting from CI */ + info->smu_gpu_pll_output_freq = + (uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10); + + return BP_RESULT_OK; +} + +static enum bp_result get_ss_info_v3_1( + struct bios_parser *bp, + uint32_t id, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include; + ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; + uint32_t table_size; + uint32_t i; + uint32_t table_index = 0; + + if (!ss_info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return BP_RESULT_UNSUPPORTED; + + ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3, + DATA_TABLES(ASIC_InternalSS_Info)); + table_size = + (le16_to_cpu(ss_table_header_include->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); + + tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) + &ss_table_header_include->asSpreadSpectrum[0]; + + memset(ss_info, 0, sizeof(struct spread_spectrum_info)); + + for (i = 0; i < table_size; i++) { + if (tbl[i].ucClockIndication != (uint8_t) id) + continue; + + if (table_index != index) { + table_index++; + continue; + } + /* VBIOS introduced new defines for Version 3, same values as + * before, so now use these new ones for Version 3. + * Shouldn't affect field VBIOS's V3 as define values are still + * same. + * #define SS_MODE_V3_CENTRE_SPREAD_MASK 0x01 + * #define SS_MODE_V3_EXTERNAL_SS_MASK 0x02 + + * Old VBIOS defines: + * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001 + * #define ATOM_EXTERNAL_SS_MASK 0x00000002 + */ + + if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode) + ss_info->type.EXTERNAL = true; + + if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode) + ss_info->type.CENTER_MODE = true; + + /* Older VBIOS (in field) always provides SS percentage in 0.01% + * units set Divider to 100 */ + ss_info->spread_percentage_divider = 100; + + /* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */ + if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK + & tbl[i].ucSpreadSpectrumMode) + ss_info->spread_percentage_divider = 1000; + + ss_info->type.STEP_AND_DELAY_INFO = false; + /* convert [10KHz] into [KHz] */ + ss_info->target_clock_range = + le32_to_cpu(tbl[i].ulTargetClockRange) * 10; + ss_info->spread_spectrum_percentage = + (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); + ss_info->spread_spectrum_range = + (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); + + return BP_RESULT_OK; + } + return BP_RESULT_NORECORD; +} + +static enum bp_result bios_parser_transmitter_control( + struct dc_bios *dcb, + struct bp_transmitter_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.transmitter_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.transmitter_control(bp, cntl); +} + +static enum bp_result bios_parser_encoder_control( + struct dc_bios *dcb, + struct bp_encoder_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.dig_encoder_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.dig_encoder_control(bp, cntl); +} + +static enum bp_result bios_parser_adjust_pixel_clock( + struct dc_bios *dcb, + struct bp_adjust_pixel_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.adjust_display_pll) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.adjust_display_pll(bp, bp_params); +} + +static enum bp_result bios_parser_set_pixel_clock( + struct dc_bios *dcb, + struct bp_pixel_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_pixel_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_pixel_clock(bp, bp_params); +} + +static enum bp_result bios_parser_set_dce_clock( + struct dc_bios *dcb, + struct bp_set_dce_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_dce_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_dce_clock(bp, bp_params); +} + +static enum bp_result bios_parser_enable_spread_spectrum_on_ppll( + struct dc_bios *dcb, + struct bp_spread_spectrum_parameters *bp_params, + bool enable) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_spread_spectrum_on_ppll( + bp, bp_params, enable); + +} + +static enum bp_result bios_parser_program_crtc_timing( + struct dc_bios *dcb, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_crtc_timing) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_crtc_timing(bp, bp_params); +} + +static enum bp_result bios_parser_program_display_engine_pll( + struct dc_bios *dcb, + struct bp_pixel_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.program_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.program_clock(bp, bp_params); + +} + + +static enum bp_result bios_parser_enable_crtc( + struct dc_bios *dcb, + enum controller_id id, + bool enable) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_crtc) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_crtc(bp, id, enable); +} + +static enum bp_result bios_parser_crtc_source_select( + struct dc_bios *dcb, + struct bp_crtc_source_select *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.select_crtc_source) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.select_crtc_source(bp, bp_params); +} + +static enum bp_result bios_parser_enable_disp_power_gating( + struct dc_bios *dcb, + enum controller_id controller_id, + enum bp_pipe_control_action action) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_disp_power_gating) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id, + action); +} + +static bool bios_parser_is_device_id_supported( + struct dc_bios *dcb, + struct device_id id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + uint32_t mask = get_support_mask_for_device_id(id); + + return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0; +} + +static enum bp_result bios_parser_crt_control( + struct dc_bios *dcb, + enum engine_id engine_id, + bool enable, + uint32_t pixel_clock) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + uint8_t standard; + + if (!bp->cmd_tbl.dac1_encoder_control && + engine_id == ENGINE_ID_DACA) + return BP_RESULT_FAILURE; + if (!bp->cmd_tbl.dac2_encoder_control && + engine_id == ENGINE_ID_DACB) + return BP_RESULT_FAILURE; + /* validate params */ + switch (engine_id) { + case ENGINE_ID_DACA: + case ENGINE_ID_DACB: + break; + default: + /* unsupported engine */ + return BP_RESULT_FAILURE; + } + + standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */ + + if (enable) { + if (engine_id == ENGINE_ID_DACA) { + bp->cmd_tbl.dac1_encoder_control(bp, enable, + pixel_clock, standard); + if (bp->cmd_tbl.dac1_output_control != NULL) + bp->cmd_tbl.dac1_output_control(bp, enable); + } else { + bp->cmd_tbl.dac2_encoder_control(bp, enable, + pixel_clock, standard); + if (bp->cmd_tbl.dac2_output_control != NULL) + bp->cmd_tbl.dac2_output_control(bp, enable); + } + } else { + if (engine_id == ENGINE_ID_DACA) { + if (bp->cmd_tbl.dac1_output_control != NULL) + bp->cmd_tbl.dac1_output_control(bp, enable); + bp->cmd_tbl.dac1_encoder_control(bp, enable, + pixel_clock, standard); + } else { + if (bp->cmd_tbl.dac2_output_control != NULL) + bp->cmd_tbl.dac2_output_control(bp, enable); + bp->cmd_tbl.dac2_encoder_control(bp, enable, + pixel_clock, standard); + } + } + + return BP_RESULT_OK; +} + +static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, + ATOM_OBJECT *object) +{ + ATOM_COMMON_RECORD_HEADER *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return NULL; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType + && sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize) + return (ATOM_HPD_INT_RECORD *) header; + + offset += header->ucRecordSize; + } + + return NULL; +} + +/** + * Get I2C information of input object id + * + * search all records to find the ATOM_I2C_RECORD_TYPE record IR + */ +static ATOM_I2C_RECORD *get_i2c_record( + struct bios_parser *bp, + ATOM_OBJECT *object) +{ + uint32_t offset; + ATOM_COMMON_RECORD_HEADER *record_header; + + if (!object) { + BREAK_TO_DEBUGGER(); + /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!record_header) + return NULL; + + if (LAST_RECORD_TYPE == record_header->ucRecordType || + 0 == record_header->ucRecordSize) + break; + + if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType && + sizeof(ATOM_I2C_RECORD) <= + record_header->ucRecordSize) { + return (ATOM_I2C_RECORD *)record_header; + } + + offset += record_header->ucRecordSize; + } + + return NULL; +} + +static enum bp_result get_ss_info_from_ss_info_table( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *ss_info); +static enum bp_result get_ss_info_from_tbl( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *ss_info); +/** + * bios_parser_get_spread_spectrum_info + * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or + * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info + * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1, + * there is only one entry for each signal /ss id. However, there is + * no planning of supporting multiple spread Sprectum entry for EverGreen + * @param [in] this + * @param [in] signal, ASSignalType to be converted to info index + * @param [in] index, number of entries that match the converted info index + * @param [out] ss_info, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result bios_parser_get_spread_spectrum_info( + struct dc_bios *dcb, + enum as_signal_type signal, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_UNSUPPORTED; + uint32_t clk_id_ss = 0; + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision tbl_revision; + + if (!ss_info) /* check for bad input */ + return BP_RESULT_BADINPUT; + /* signal translation */ + clk_id_ss = signal_to_ss_id(signal); + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + if (!index) + return get_ss_info_from_ss_info_table(bp, clk_id_ss, + ss_info); + + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + DATA_TABLES(ASIC_InternalSS_Info)); + get_atom_data_table_revision(header, &tbl_revision); + + switch (tbl_revision.major) { + case 2: + switch (tbl_revision.minor) { + case 1: + /* there can not be more then one entry for Internal + * SS Info table version 2.1 */ + if (!index) + return get_ss_info_from_tbl(bp, clk_id_ss, + ss_info); + break; + default: + break; + } + break; + + case 3: + switch (tbl_revision.minor) { + case 1: + return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info); + default: + break; + } + break; + default: + break; + } + /* there can not be more then one entry for SS Info table */ + return result; +} + +static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *info); + +/** + * get_ss_info_from_table + * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or + * SS_Info table from the VBIOS + * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or + * SS_Info. + * + * @param this + * @param id, spread sprectrum info index + * @param pSSinfo, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result get_ss_info_from_tbl( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *ss_info) +{ + if (!ss_info) /* check for bad input, if ss_info is not NULL */ + return BP_RESULT_BADINPUT; + /* for SS_Info table only support DP and LVDS */ + if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) + return get_ss_info_from_ss_info_table(bp, id, ss_info); + else + return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id, + ss_info); +} + +/** + * get_ss_info_from_internal_ss_info_tbl_V2_1 + * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1 + * from the VBIOS + * There will not be multiple entry for Ver 2.1 + * + * @param id, spread sprectrum info index + * @param pSSinfo, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *info) +{ + enum bp_result result = BP_RESULT_UNSUPPORTED; + ATOM_ASIC_INTERNAL_SS_INFO_V2 *header; + ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; + uint32_t tbl_size, i; + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return result; + + header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2, + DATA_TABLES(ASIC_InternalSS_Info)); + + memset(info, 0, sizeof(struct spread_spectrum_info)); + + tbl_size = (le16_to_cpu(header->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); + + tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) + &(header->asSpreadSpectrum[0]); + for (i = 0; i < tbl_size; i++) { + result = BP_RESULT_NORECORD; + + if (tbl[i].ucClockIndication != (uint8_t)id) + continue; + + if (ATOM_EXTERNAL_SS_MASK + & tbl[i].ucSpreadSpectrumMode) { + info->type.EXTERNAL = true; + } + if (ATOM_SS_CENTRE_SPREAD_MODE_MASK + & tbl[i].ucSpreadSpectrumMode) { + info->type.CENTER_MODE = true; + } + info->type.STEP_AND_DELAY_INFO = false; + /* convert [10KHz] into [KHz] */ + info->target_clock_range = + le32_to_cpu(tbl[i].ulTargetClockRange) * 10; + info->spread_spectrum_percentage = + (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); + info->spread_spectrum_range = + (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); + result = BP_RESULT_OK; + break; + } + + return result; + +} + +/** + * get_ss_info_from_ss_info_table + * Get spread sprectrum information from the SS_Info table from the VBIOS + * if the pointer to info is NULL, indicate the caller what to know the number + * of entries that matches the id + * for, the SS_Info table, there should not be more than 1 entry match. + * + * @param [in] id, spread sprectrum id + * @param [out] pSSinfo, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result get_ss_info_from_ss_info_table( + struct bios_parser *bp, + uint32_t id, + struct spread_spectrum_info *ss_info) +{ + enum bp_result result = BP_RESULT_UNSUPPORTED; + ATOM_SPREAD_SPECTRUM_INFO *tbl; + ATOM_COMMON_TABLE_HEADER *header; + uint32_t table_size; + uint32_t i; + uint32_t id_local = SS_ID_UNKNOWN; + struct atom_data_revision revision; + + /* exist of the SS_Info table */ + /* check for bad input, pSSinfo can not be NULL */ + if (!DATA_TABLES(SS_Info) || !ss_info) + return result; + + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info)); + get_atom_data_table_revision(header, &revision); + + tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info)); + + if (1 != revision.major || 2 > revision.minor) + return result; + + /* have to convert from Internal_SS format to SS_Info format */ + switch (id) { + case ASIC_INTERNAL_SS_ON_DP: + id_local = SS_ID_DP1; + break; + case ASIC_INTERNAL_SS_ON_LVDS: + { + struct embedded_panel_info panel_info; + + if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) + == BP_RESULT_OK) + id_local = panel_info.ss_id; + break; + } + default: + break; + } + + if (id_local == SS_ID_UNKNOWN) + return result; + + table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - + sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); + + for (i = 0; i < table_size; i++) { + if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id) + continue; + + memset(ss_info, 0, sizeof(struct spread_spectrum_info)); + + if (ATOM_EXTERNAL_SS_MASK & + tbl->asSS_Info[i].ucSpreadSpectrumType) + ss_info->type.EXTERNAL = true; + + if (ATOM_SS_CENTRE_SPREAD_MODE_MASK & + tbl->asSS_Info[i].ucSpreadSpectrumType) + ss_info->type.CENTER_MODE = true; + + ss_info->type.STEP_AND_DELAY_INFO = true; + ss_info->spread_spectrum_percentage = + (uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage); + ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step; + ss_info->step_and_delay_info.delay = + tbl->asSS_Info[i].ucSS_Delay; + ss_info->step_and_delay_info.recommended_ref_div = + tbl->asSS_Info[i].ucRecommendedRef_Div; + ss_info->spread_spectrum_range = + (uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000; + + /* there will be only one entry for each display type in SS_info + * table */ + result = BP_RESULT_OK; + break; + } + + return result; +} +static enum bp_result get_embedded_panel_info_v1_2( + struct bios_parser *bp, + struct embedded_panel_info *info); +static enum bp_result get_embedded_panel_info_v1_3( + struct bios_parser *bp, + struct embedded_panel_info *info); + +static enum bp_result bios_parser_get_embedded_panel_info( + struct dc_bios *dcb, + struct embedded_panel_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_COMMON_TABLE_HEADER *hdr; + + if (!DATA_TABLES(LCD_Info)) + return BP_RESULT_FAILURE; + + hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info)); + + if (!hdr) + return BP_RESULT_BADBIOSTABLE; + + switch (hdr->ucTableFormatRevision) { + case 1: + switch (hdr->ucTableContentRevision) { + case 0: + case 1: + case 2: + return get_embedded_panel_info_v1_2(bp, info); + case 3: + return get_embedded_panel_info_v1_3(bp, info); + default: + break; + } + default: + break; + } + + return BP_RESULT_FAILURE; +} + +static enum bp_result get_embedded_panel_info_v1_2( + struct bios_parser *bp, + struct embedded_panel_info *info) +{ + ATOM_LVDS_INFO_V12 *lvds; + + if (!info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(LVDS_Info)) + return BP_RESULT_UNSUPPORTED; + + lvds = + GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info)); + + if (!lvds) + return BP_RESULT_BADBIOSTABLE; + + if (1 != lvds->sHeader.ucTableFormatRevision + || 2 > lvds->sHeader.ucTableContentRevision) + return BP_RESULT_UNSUPPORTED; + + memset(info, 0, sizeof(struct embedded_panel_info)); + + /* We need to convert from 10KHz units into KHz units*/ + info->lcd_timing.pixel_clk = + le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; + /* usHActive does not include borders, according to VBIOS team*/ + info->lcd_timing.horizontal_addressable = + le16_to_cpu(lvds->sLCDTiming.usHActive); + /* usHBlanking_Time includes borders, so we should really be subtracting + * borders duing this translation, but LVDS generally*/ + /* doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders*/ + info->lcd_timing.horizontal_blanking_time = + le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); + /* usVActive does not include borders, according to VBIOS team*/ + info->lcd_timing.vertical_addressable = + le16_to_cpu(lvds->sLCDTiming.usVActive); + /* usVBlanking_Time includes borders, so we should really be subtracting + * borders duing this translation, but LVDS generally*/ + /* doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders*/ + info->lcd_timing.vertical_blanking_time = + le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); + info->lcd_timing.horizontal_sync_offset = + le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); + info->lcd_timing.horizontal_sync_width = + le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); + info->lcd_timing.vertical_sync_offset = + le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); + info->lcd_timing.vertical_sync_width = + le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); + info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; + info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; + info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; + info->lcd_timing.misc_info.H_SYNC_POLARITY = + ~(uint32_t) + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; + info->lcd_timing.misc_info.V_SYNC_POLARITY = + ~(uint32_t) + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; + info->lcd_timing.misc_info.VERTICAL_CUT_OFF = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; + info->lcd_timing.misc_info.H_REPLICATION_BY2 = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; + info->lcd_timing.misc_info.V_REPLICATION_BY2 = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; + info->lcd_timing.misc_info.COMPOSITE_SYNC = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; + info->lcd_timing.misc_info.INTERLACE = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; + info->lcd_timing.misc_info.DOUBLE_CLOCK = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; + info->ss_id = lvds->ucSS_Id; + + { + uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate); + /* Get minimum supported refresh rate*/ + if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) + info->supported_rr.REFRESH_RATE_30HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) + info->supported_rr.REFRESH_RATE_40HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) + info->supported_rr.REFRESH_RATE_48HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) + info->supported_rr.REFRESH_RATE_50HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) + info->supported_rr.REFRESH_RATE_60HZ = 1; + } + + /*Drr panel support can be reported by VBIOS*/ + if (LCDPANEL_CAP_DRR_SUPPORTED + & lvds->ucLCDPanel_SpecialHandlingCap) + info->drr_enabled = 1; + + if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.DOUBLE_CLOCK = true; + + if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.RGB888 = true; + + info->lcd_timing.misc_info.GREY_LEVEL = + (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL & + lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT; + + if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.SPATIAL = true; + + if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.TEMPORAL = true; + + if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc) + info->lcd_timing.misc_info.API_ENABLED = true; + + return BP_RESULT_OK; +} + +static enum bp_result get_embedded_panel_info_v1_3( + struct bios_parser *bp, + struct embedded_panel_info *info) +{ + ATOM_LCD_INFO_V13 *lvds; + + if (!info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(LCD_Info)) + return BP_RESULT_UNSUPPORTED; + + lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info)); + + if (!lvds) + return BP_RESULT_BADBIOSTABLE; + + if (!((1 == lvds->sHeader.ucTableFormatRevision) + && (3 <= lvds->sHeader.ucTableContentRevision))) + return BP_RESULT_UNSUPPORTED; + + memset(info, 0, sizeof(struct embedded_panel_info)); + + /* We need to convert from 10KHz units into KHz units */ + info->lcd_timing.pixel_clk = + le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; + /* usHActive does not include borders, according to VBIOS team */ + info->lcd_timing.horizontal_addressable = + le16_to_cpu(lvds->sLCDTiming.usHActive); + /* usHBlanking_Time includes borders, so we should really be subtracting + * borders duing this translation, but LVDS generally*/ + /* doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders*/ + info->lcd_timing.horizontal_blanking_time = + le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); + /* usVActive does not include borders, according to VBIOS team*/ + info->lcd_timing.vertical_addressable = + le16_to_cpu(lvds->sLCDTiming.usVActive); + /* usVBlanking_Time includes borders, so we should really be subtracting + * borders duing this translation, but LVDS generally*/ + /* doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders*/ + info->lcd_timing.vertical_blanking_time = + le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); + info->lcd_timing.horizontal_sync_offset = + le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); + info->lcd_timing.horizontal_sync_width = + le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); + info->lcd_timing.vertical_sync_offset = + le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); + info->lcd_timing.vertical_sync_width = + le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); + info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; + info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; + info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; + info->lcd_timing.misc_info.H_SYNC_POLARITY = + ~(uint32_t) + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; + info->lcd_timing.misc_info.V_SYNC_POLARITY = + ~(uint32_t) + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; + info->lcd_timing.misc_info.VERTICAL_CUT_OFF = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; + info->lcd_timing.misc_info.H_REPLICATION_BY2 = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; + info->lcd_timing.misc_info.V_REPLICATION_BY2 = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; + info->lcd_timing.misc_info.COMPOSITE_SYNC = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; + info->lcd_timing.misc_info.INTERLACE = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; + info->lcd_timing.misc_info.DOUBLE_CLOCK = + lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; + info->ss_id = lvds->ucSS_Id; + + /* Drr panel support can be reported by VBIOS*/ + if (LCDPANEL_CAP_V13_DRR_SUPPORTED + & lvds->ucLCDPanel_SpecialHandlingCap) + info->drr_enabled = 1; + + /* Get supported refresh rate*/ + if (info->drr_enabled == 1) { + uint8_t min_rr = + lvds->sRefreshRateSupport.ucMinRefreshRateForDRR; + uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate; + + if (min_rr != 0) { + if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr) + info->supported_rr.REFRESH_RATE_30HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr) + info->supported_rr.REFRESH_RATE_40HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr) + info->supported_rr.REFRESH_RATE_48HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr) + info->supported_rr.REFRESH_RATE_50HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr) + info->supported_rr.REFRESH_RATE_60HZ = 1; + } else { + if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) + info->supported_rr.REFRESH_RATE_30HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) + info->supported_rr.REFRESH_RATE_40HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) + info->supported_rr.REFRESH_RATE_48HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) + info->supported_rr.REFRESH_RATE_50HZ = 1; + else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) + info->supported_rr.REFRESH_RATE_60HZ = 1; + } + } + + if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc) + info->lcd_timing.misc_info.DOUBLE_CLOCK = true; + + if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc) + info->lcd_timing.misc_info.RGB888 = true; + + info->lcd_timing.misc_info.GREY_LEVEL = + (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL & + lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT; + + return BP_RESULT_OK; +} + +/** + * bios_parser_get_encoder_cap_info + * + * @brief + * Get encoder capability information of input object id + * + * @param object_id, Object id + * @param object_id, encoder cap information structure + * + * @return Bios parser result code + * + */ +static enum bp_result bios_parser_get_encoder_cap_info( + struct dc_bios *dcb, + struct graphics_object_id object_id, + struct bp_encoder_cap_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_OBJECT *object; + ATOM_ENCODER_CAP_RECORD *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_encoder_cap_record(bp, object); + if (!record) + return BP_RESULT_NORECORD; + + info->DP_HBR2_CAP = record->usHBR2Cap; + info->DP_HBR2_EN = record->usHBR2En; + return BP_RESULT_OK; +} + +/** + * get_encoder_cap_record + * + * @brief + * Get encoder cap record for the object + * + * @param object, ATOM object + * + * @return atom encoder cap record + * + * @note + * search all records to find the ATOM_ENCODER_CAP_RECORD record + */ +static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( + struct bios_parser *bp, + ATOM_OBJECT *object) +{ + ATOM_COMMON_RECORD_HEADER *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return NULL; + + offset += header->ucRecordSize; + + if (LAST_RECORD_TYPE == header->ucRecordType || + !header->ucRecordSize) + break; + + if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType) + continue; + + if (sizeof(ATOM_ENCODER_CAP_RECORD) <= header->ucRecordSize) + return (ATOM_ENCODER_CAP_RECORD *)header; + } + + return NULL; +} + +static uint32_t get_ss_entry_number( + struct bios_parser *bp, + uint32_t id); +static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( + struct bios_parser *bp, + uint32_t id); +static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( + struct bios_parser *bp, + uint32_t id); +static uint32_t get_ss_entry_number_from_ss_info_tbl( + struct bios_parser *bp, + uint32_t id); + +/** + * BiosParserObject::GetNumberofSpreadSpectrumEntry + * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from + * the VBIOS that match the SSid (to be converted from signal) + * + * @param[in] signal, ASSignalType to be converted to SSid + * @return number of SS Entry that match the signal + */ +static uint32_t bios_parser_get_ss_entry_number( + struct dc_bios *dcb, + enum as_signal_type signal) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + uint32_t ss_id = 0; + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision revision; + + ss_id = signal_to_ss_id(signal); + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return get_ss_entry_number_from_ss_info_tbl(bp, ss_id); + + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + DATA_TABLES(ASIC_InternalSS_Info)); + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 2: + switch (revision.minor) { + case 1: + return get_ss_entry_number(bp, ss_id); + default: + break; + } + break; + case 3: + switch (revision.minor) { + case 1: + return + get_ss_entry_number_from_internal_ss_info_tbl_V3_1( + bp, ss_id); + default: + break; + } + break; + default: + break; + } + + return 0; +} + +/** + * get_ss_entry_number_from_ss_info_tbl + * Get Number of spread spectrum entry from the SS_Info table from the VBIOS. + * + * @note There can only be one entry for each id for SS_Info Table + * + * @param [in] id, spread spectrum id + * @return number of SS Entry that match the id + */ +static uint32_t get_ss_entry_number_from_ss_info_tbl( + struct bios_parser *bp, + uint32_t id) +{ + ATOM_SPREAD_SPECTRUM_INFO *tbl; + ATOM_COMMON_TABLE_HEADER *header; + uint32_t table_size; + uint32_t i; + uint32_t number = 0; + uint32_t id_local = SS_ID_UNKNOWN; + struct atom_data_revision revision; + + /* SS_Info table exist */ + if (!DATA_TABLES(SS_Info)) + return number; + + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + DATA_TABLES(SS_Info)); + get_atom_data_table_revision(header, &revision); + + tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, + DATA_TABLES(SS_Info)); + + if (1 != revision.major || 2 > revision.minor) + return number; + + /* have to convert from Internal_SS format to SS_Info format */ + switch (id) { + case ASIC_INTERNAL_SS_ON_DP: + id_local = SS_ID_DP1; + break; + case ASIC_INTERNAL_SS_ON_LVDS: { + struct embedded_panel_info panel_info; + + if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) + == BP_RESULT_OK) + id_local = panel_info.ss_id; + break; + } + default: + break; + } + + if (id_local == SS_ID_UNKNOWN) + return number; + + table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - + sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); + + for (i = 0; i < table_size; i++) + if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) { + number = 1; + break; + } + + return number; +} + +/** + * get_ss_entry_number + * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or + * SS_Info table from the VBIOS + * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or + * SS_Info. + * + * @param id, spread sprectrum info index + * @return Bios parser result code + */ +static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id) +{ + if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) + return get_ss_entry_number_from_ss_info_tbl(bp, id); + + return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id); +} + +/** + * get_ss_entry_number_from_internal_ss_info_tbl_v2_1 + * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table + * Ver 2.1 from the VBIOS + * There will not be multiple entry for Ver 2.1 + * + * @param id, spread sprectrum info index + * @return number of SS Entry that match the id + */ +static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( + struct bios_parser *bp, + uint32_t id) +{ + ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include; + ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; + uint32_t size; + uint32_t i; + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return 0; + + header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2, + DATA_TABLES(ASIC_InternalSS_Info)); + + size = (le16_to_cpu(header_include->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); + + tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) + &header_include->asSpreadSpectrum[0]; + for (i = 0; i < size; i++) + if (tbl[i].ucClockIndication == (uint8_t)id) + return 1; + + return 0; +} +/** + * get_ss_entry_number_from_internal_ss_info_table_V3_1 + * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of + * the VBIOS that matches id + * + * @param[in] id, spread sprectrum id + * @return number of SS Entry that match the id + */ +static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( + struct bios_parser *bp, + uint32_t id) +{ + uint32_t number = 0; + ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include; + ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; + uint32_t size; + uint32_t i; + + if (!DATA_TABLES(ASIC_InternalSS_Info)) + return number; + + header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3, + DATA_TABLES(ASIC_InternalSS_Info)); + size = (le16_to_cpu(header_include->sHeader.usStructureSize) - + sizeof(ATOM_COMMON_TABLE_HEADER)) / + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); + + tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) + &header_include->asSpreadSpectrum[0]; + + for (i = 0; i < size; i++) + if (tbl[i].ucClockIndication == (uint8_t)id) + number++; + + return number; +} + +/** + * bios_parser_get_gpio_pin_info + * Get GpioPin information of input gpio id + * + * @param gpio_id, GPIO ID + * @param info, GpioPin information structure + * @return Bios parser result code + * @note + * to get the GPIO PIN INFO, we need: + * 1. get the GPIO_ID from other object table, see GetHPDInfo() + * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA + * offset/mask + */ +static enum bp_result bios_parser_get_gpio_pin_info( + struct dc_bios *dcb, + uint32_t gpio_id, + struct gpio_pin_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + ATOM_GPIO_PIN_LUT *header; + uint32_t count = 0; + uint32_t i = 0; + + if (!DATA_TABLES(GPIO_Pin_LUT)) + return BP_RESULT_BADBIOSTABLE; + + header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT)); + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT) + > le16_to_cpu(header->sHeader.usStructureSize)) + return BP_RESULT_BADBIOSTABLE; + + if (1 != header->sHeader.ucTableContentRevision) + return BP_RESULT_UNSUPPORTED; + + count = (le16_to_cpu(header->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); + for (i = 0; i < count; ++i) { + if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id) + continue; + + info->offset = + (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex); + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask = (uint32_t) (1 << + header->asGPIO_Pin[i].ucGpioPinBitShift); + info->mask_y = info->mask + 2; + info->mask_en = info->mask + 1; + info->mask_mask = info->mask - 1; + + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, + ATOM_I2C_RECORD *record, + struct graphics_object_i2c_info *info) +{ + ATOM_GPIO_I2C_INFO *header; + uint32_t count = 0; + + if (!info) + return BP_RESULT_BADINPUT; + + /* get the GPIO_I2C info */ + if (!DATA_TABLES(GPIO_I2C_Info)) + return BP_RESULT_BADBIOSTABLE; + + header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info)); + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT) + > le16_to_cpu(header->sHeader.usStructureSize)) + return BP_RESULT_BADBIOSTABLE; + + if (1 != header->sHeader.ucTableContentRevision) + return BP_RESULT_UNSUPPORTED; + + /* get data count */ + count = (le16_to_cpu(header->sHeader.usStructureSize) + - sizeof(ATOM_COMMON_TABLE_HEADER)) + / sizeof(ATOM_GPIO_I2C_ASSIGMENT); + if (count < record->sucI2cId.bfI2C_LineMux) + return BP_RESULT_BADBIOSTABLE; + + /* get the GPIO_I2C_INFO */ + info->i2c_hw_assist = record->sucI2cId.bfHW_Capable; + info->i2c_line = record->sucI2cId.bfI2C_LineMux; + info->i2c_engine_id = record->sucI2cId.bfHW_EngineID; + info->i2c_slave_address = record->ucI2CAddr; + + info->gpio_info.clk_mask_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex); + info->gpio_info.clk_en_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex); + info->gpio_info.clk_y_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex); + info->gpio_info.clk_a_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex); + info->gpio_info.data_mask_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex); + info->gpio_info.data_en_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex); + info->gpio_info.data_y_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex); + info->gpio_info.data_a_register_index = + le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex); + + info->gpio_info.clk_mask_shift = + header->asGPIO_Info[info->i2c_line].ucClkMaskShift; + info->gpio_info.clk_en_shift = + header->asGPIO_Info[info->i2c_line].ucClkEnShift; + info->gpio_info.clk_y_shift = + header->asGPIO_Info[info->i2c_line].ucClkY_Shift; + info->gpio_info.clk_a_shift = + header->asGPIO_Info[info->i2c_line].ucClkA_Shift; + info->gpio_info.data_mask_shift = + header->asGPIO_Info[info->i2c_line].ucDataMaskShift; + info->gpio_info.data_en_shift = + header->asGPIO_Info[info->i2c_line].ucDataEnShift; + info->gpio_info.data_y_shift = + header->asGPIO_Info[info->i2c_line].ucDataY_Shift; + info->gpio_info.data_a_shift = + header->asGPIO_Info[info->i2c_line].ucDataA_Shift; + + return BP_RESULT_OK; +} + +static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, + struct graphics_object_id id) +{ + uint32_t offset; + ATOM_OBJECT_TABLE *tbl; + uint32_t i; + + switch (id.type) { + case OBJECT_TYPE_ENCODER: + offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); + break; + + case OBJECT_TYPE_CONNECTOR: + offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + break; + + case OBJECT_TYPE_ROUTER: + offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset); + break; + + case OBJECT_TYPE_GENERIC: + if (bp->object_info_tbl.revision.minor < 3) + return NULL; + offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset); + break; + + default: + return NULL; + } + + offset += bp->object_info_tbl_offset; + + tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset); + if (!tbl) + return NULL; + + for (i = 0; i < tbl->ucNumberOfObjects; i++) + if (dal_graphics_object_id_is_equal(id, + object_id_from_bios_object_id( + le16_to_cpu(tbl->asObjects[i].usObjectID)))) + return &tbl->asObjects[i]; + + return NULL; +} + +static uint32_t get_dest_obj_list(struct bios_parser *bp, + ATOM_OBJECT *object, uint16_t **id_list) +{ + uint32_t offset; + uint8_t *number; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return 0; + } + + offset = le16_to_cpu(object->usSrcDstTableOffset) + + bp->object_info_tbl_offset; + + number = GET_IMAGE(uint8_t, offset); + if (!number) + return 0; + + offset += sizeof(uint8_t); + offset += sizeof(uint16_t) * (*number); + + number = GET_IMAGE(uint8_t, offset); + if ((!number) || (!*number)) + return 0; + + offset += sizeof(uint8_t); + *id_list = (uint16_t *)get_image(&bp->base, offset, *number * sizeof(uint16_t)); + + if (!*id_list) + return 0; + + return *number; +} + +static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, + uint16_t **id_list) +{ + uint32_t offset; + uint8_t *number; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return 0; + } + + offset = le16_to_cpu(object->usSrcDstTableOffset) + + bp->object_info_tbl_offset; + + number = GET_IMAGE(uint8_t, offset); + if (!number) + return 0; + + offset += sizeof(uint8_t); + *id_list = (uint16_t *)get_image(&bp->base, offset, *number * sizeof(uint16_t)); + + if (!*id_list) + return 0; + + return *number; +} + +static uint32_t get_dst_number_from_object(struct bios_parser *bp, + ATOM_OBJECT *object) +{ + uint32_t offset; + uint8_t *number; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/ + return 0; + } + + offset = le16_to_cpu(object->usSrcDstTableOffset) + + bp->object_info_tbl_offset; + + number = GET_IMAGE(uint8_t, offset); + if (!number) + return 0; + + offset += sizeof(uint8_t); + offset += sizeof(uint16_t) * (*number); + + number = GET_IMAGE(uint8_t, offset); + + if (!number) + return 0; + + return *number; +} + + +static struct graphics_object_id object_id_from_bios_object_id( + uint32_t bios_object_id) +{ + enum object_type type; + enum object_enum_id enum_id; + struct graphics_object_id go_id = { 0 }; + + type = object_type_from_bios_object_id(bios_object_id); + + if (OBJECT_TYPE_UNKNOWN == type) + return go_id; + + enum_id = enum_id_from_bios_object_id(bios_object_id); + + if (ENUM_ID_UNKNOWN == enum_id) + return go_id; + + go_id = dal_graphics_object_id_init( + id_from_bios_object_id(type, bios_object_id), enum_id, type); + + return go_id; +} + +static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) + >> OBJECT_TYPE_SHIFT; + enum object_type object_type; + + switch (bios_object_type) { + case GRAPH_OBJECT_TYPE_GPU: + object_type = OBJECT_TYPE_GPU; + break; + case GRAPH_OBJECT_TYPE_ENCODER: + object_type = OBJECT_TYPE_ENCODER; + break; + case GRAPH_OBJECT_TYPE_CONNECTOR: + object_type = OBJECT_TYPE_CONNECTOR; + break; + case GRAPH_OBJECT_TYPE_ROUTER: + object_type = OBJECT_TYPE_ROUTER; + break; + case GRAPH_OBJECT_TYPE_GENERIC: + object_type = OBJECT_TYPE_GENERIC; + break; + default: + object_type = OBJECT_TYPE_UNKNOWN; + break; + } + + return object_type; +} + +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_enum_id = + (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + enum object_enum_id id; + + switch (bios_enum_id) { + case GRAPH_OBJECT_ENUM_ID1: + id = ENUM_ID_1; + break; + case GRAPH_OBJECT_ENUM_ID2: + id = ENUM_ID_2; + break; + case GRAPH_OBJECT_ENUM_ID3: + id = ENUM_ID_3; + break; + case GRAPH_OBJECT_ENUM_ID4: + id = ENUM_ID_4; + break; + case GRAPH_OBJECT_ENUM_ID5: + id = ENUM_ID_5; + break; + case GRAPH_OBJECT_ENUM_ID6: + id = ENUM_ID_6; + break; + case GRAPH_OBJECT_ENUM_ID7: + id = ENUM_ID_7; + break; + default: + id = ENUM_ID_UNKNOWN; + break; + } + + return id; +} + +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id) +{ + switch (type) { + case OBJECT_TYPE_GPU: + return gpu_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_ENCODER: + return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_CONNECTOR: + return (uint32_t)connector_id_from_bios_object_id( + bios_object_id); + case OBJECT_TYPE_GENERIC: + return generic_id_from_bios_object_id(bios_object_id); + default: + return 0; + } +} + +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id) +{ + uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); + + enum connector_id id; + + switch (bios_connector_id) { + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: + id = CONNECTOR_ID_SINGLE_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: + id = CONNECTOR_ID_DUAL_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: + id = CONNECTOR_ID_SINGLE_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: + id = CONNECTOR_ID_DUAL_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_VGA: + id = CONNECTOR_ID_VGA; + break; + case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: + id = CONNECTOR_ID_HDMI_TYPE_A; + break; + case CONNECTOR_OBJECT_ID_LVDS: + id = CONNECTOR_ID_LVDS; + break; + case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: + id = CONNECTOR_ID_PCIE; + break; + case CONNECTOR_OBJECT_ID_HARDCODE_DVI: + id = CONNECTOR_ID_HARDCODE_DVI; + break; + case CONNECTOR_OBJECT_ID_DISPLAYPORT: + id = CONNECTOR_ID_DISPLAY_PORT; + break; + case CONNECTOR_OBJECT_ID_eDP: + id = CONNECTOR_ID_EDP; + break; + case CONNECTOR_OBJECT_ID_MXM: + id = CONNECTOR_ID_MXM; + break; + default: + id = CONNECTOR_ID_UNKNOWN; + break; + } + + return id; +} + +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); + enum encoder_id id; + + switch (bios_encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + id = ENCODER_ID_INTERNAL_LVDS; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + id = ENCODER_ID_INTERNAL_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS2: + id = ENCODER_ID_INTERNAL_TMDS2; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + id = ENCODER_ID_INTERNAL_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + id = ENCODER_ID_INTERNAL_DAC2; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + id = ENCODER_ID_INTERNAL_LVTM1; + break; + case ENCODER_OBJECT_ID_HDMI_INTERNAL: + id = ENCODER_ID_INTERNAL_HDMI; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; + break; + case ENCODER_OBJECT_ID_MVPU_FPGA: + id = ENCODER_ID_EXTERNAL_MVPU_FPGA; + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + id = ENCODER_ID_INTERNAL_DDI; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + id = ENCODER_ID_INTERNAL_UNIPHY; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + id = ENCODER_ID_INTERNAL_UNIPHY1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + id = ENCODER_ID_INTERNAL_UNIPHY2; + break; + case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ + id = ENCODER_ID_EXTERNAL_NUTMEG; + break; + case ENCODER_OBJECT_ID_TRAVIS: + id = ENCODER_ID_EXTERNAL_TRAVIS; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + id = ENCODER_ID_INTERNAL_UNIPHY3; + break; + default: + id = ENCODER_ID_UNKNOWN; + ASSERT(0); + break; + } + + return id; +} + +uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) +{ + return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; +} + +enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); + + enum generic_id id; + + switch (bios_generic_id) { + case GENERIC_OBJECT_ID_MXM_OPM: + id = GENERIC_ID_MXM_OPM; + break; + case GENERIC_OBJECT_ID_GLSYNC: + id = GENERIC_ID_GLSYNC; + break; + case GENERIC_OBJECT_ID_STEREO_PIN: + id = GENERIC_ID_STEREO; + break; + default: + id = GENERIC_ID_UNKNOWN; + break; + } + + return id; +} + +static struct device_id device_type_from_device_id(uint16_t device_id) +{ + + struct device_id result_device_id; + + switch (device_id) { + case ATOM_DEVICE_LCD1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_LCD; + result_device_id.enum_id = 1; + break; + + case ATOM_DEVICE_LCD2_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_LCD; + result_device_id.enum_id = 2; + break; + + case ATOM_DEVICE_CRT1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_CRT; + result_device_id.enum_id = 1; + break; + + case ATOM_DEVICE_CRT2_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_CRT; + result_device_id.enum_id = 2; + break; + + case ATOM_DEVICE_DFP1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 1; + break; + + case ATOM_DEVICE_DFP2_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 2; + break; + + case ATOM_DEVICE_DFP3_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 3; + break; + + case ATOM_DEVICE_DFP4_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 4; + break; + + case ATOM_DEVICE_DFP5_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 5; + break; + + case ATOM_DEVICE_DFP6_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 6; + break; + + default: + BREAK_TO_DEBUGGER(); /* Invalid device Id */ + result_device_id.device_type = DEVICE_TYPE_UNKNOWN; + result_device_id.enum_id = 0; + } + return result_device_id; +} + +static void get_atom_data_table_revision( + ATOM_COMMON_TABLE_HEADER *atom_data_tbl, + struct atom_data_revision *tbl_revision) +{ + if (!tbl_revision) + return; + + /* initialize the revision to 0 which is invalid revision */ + tbl_revision->major = 0; + tbl_revision->minor = 0; + + if (!atom_data_tbl) + return; + + tbl_revision->major = + (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl); + tbl_revision->minor = + (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl); +} + +static uint32_t signal_to_ss_id(enum as_signal_type signal) +{ + uint32_t clk_id_ss = 0; + + switch (signal) { + case AS_SIGNAL_TYPE_DVI: + clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS; + break; + case AS_SIGNAL_TYPE_HDMI: + clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI; + break; + case AS_SIGNAL_TYPE_LVDS: + clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS; + break; + case AS_SIGNAL_TYPE_DISPLAY_PORT: + clk_id_ss = ASIC_INTERNAL_SS_ON_DP; + break; + case AS_SIGNAL_TYPE_GPU_PLL: + clk_id_ss = ASIC_INTERNAL_GPUPLL_SS; + break; + default: + break; + } + return clk_id_ss; +} + +static uint32_t get_support_mask_for_device_id(struct device_id device_id) +{ + enum dal_device_type device_type = device_id.device_type; + uint32_t enum_id = device_id.enum_id; + + switch (device_type) { + case DEVICE_TYPE_LCD: + switch (enum_id) { + case 1: + return ATOM_DEVICE_LCD1_SUPPORT; + case 2: + return ATOM_DEVICE_LCD2_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_CRT: + switch (enum_id) { + case 1: + return ATOM_DEVICE_CRT1_SUPPORT; + case 2: + return ATOM_DEVICE_CRT2_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_DFP: + switch (enum_id) { + case 1: + return ATOM_DEVICE_DFP1_SUPPORT; + case 2: + return ATOM_DEVICE_DFP2_SUPPORT; + case 3: + return ATOM_DEVICE_DFP3_SUPPORT; + case 4: + return ATOM_DEVICE_DFP4_SUPPORT; + case 5: + return ATOM_DEVICE_DFP5_SUPPORT; + case 6: + return ATOM_DEVICE_DFP6_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_CV: + switch (enum_id) { + case 1: + return ATOM_DEVICE_CV_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_TV: + switch (enum_id) { + case 1: + return ATOM_DEVICE_TV1_SUPPORT; + default: + break; + } + break; + default: + break; + }; + + /* Unidentified device ID, return empty support mask. */ + return 0; +} + +/** + * HwContext interface for writing MM registers + */ + +static bool i2c_read( + struct bios_parser *bp, + struct graphics_object_i2c_info *i2c_info, + uint8_t *buffer, + uint32_t length) +{ + struct ddc *ddc; + uint8_t offset[2] = { 0, 0 }; + bool result = false; + struct i2c_command cmd; + struct gpio_ddc_hw_info hw_info = { + i2c_info->i2c_hw_assist, + i2c_info->i2c_line }; + + ddc = dal_gpio_create_ddc(bp->base.ctx->gpio_service, + i2c_info->gpio_info.clk_a_register_index, + (1 << i2c_info->gpio_info.clk_a_shift), &hw_info); + + if (!ddc) + return result; + + /*Using SW engine */ + cmd.engine = I2C_COMMAND_ENGINE_SW; + cmd.speed = ddc->ctx->dc->caps.i2c_speed_in_khz; + + { + struct i2c_payload payloads[] = { + { + .address = i2c_info->i2c_slave_address >> 1, + .data = offset, + .length = sizeof(offset), + .write = true + }, + { + .address = i2c_info->i2c_slave_address >> 1, + .data = buffer, + .length = length, + .write = false + } + }; + + cmd.payloads = payloads; + cmd.number_of_payloads = ARRAY_SIZE(payloads); + + /* TODO route this through drm i2c_adapter */ + result = dal_i2caux_submit_i2c_command( + ddc->ctx->i2caux, + ddc, + &cmd); + } + + dal_gpio_destroy_ddc(&ddc); + + return result; +} + +/** + * Read external display connection info table through i2c. + * validate the GUID and checksum. + * + * @return enum bp_result whether all data was sucessfully read + */ +static enum bp_result get_ext_display_connection_info( + struct bios_parser *bp, + ATOM_OBJECT *opm_object, + ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl) +{ + bool config_tbl_present = false; + ATOM_I2C_RECORD *i2c_record = NULL; + uint32_t i = 0; + + if (opm_object == NULL) + return BP_RESULT_BADINPUT; + + i2c_record = get_i2c_record(bp, opm_object); + + if (i2c_record != NULL) { + ATOM_GPIO_I2C_INFO *gpio_i2c_header; + struct graphics_object_i2c_info i2c_info; + + gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO, + bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info); + + if (NULL == gpio_i2c_header) + return BP_RESULT_BADBIOSTABLE; + + if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) != + BP_RESULT_OK) + return BP_RESULT_BADBIOSTABLE; + + if (i2c_read(bp, + &i2c_info, + (uint8_t *)ext_display_connection_info_tbl, + sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) { + config_tbl_present = true; + } + } + + /* Validate GUID */ + if (config_tbl_present) + for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) { + if (ext_display_connection_info_tbl->ucGuid[i] + != ext_display_connection_guid[i]) { + config_tbl_present = false; + break; + } + } + + /* Validate checksum */ + if (config_tbl_present) { + uint8_t check_sum = 0; + uint8_t *buf = + (uint8_t *)ext_display_connection_info_tbl; + + for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO); + i++) { + check_sum += buf[i]; + } + + if (check_sum != 0) + config_tbl_present = false; + } + + if (config_tbl_present) + return BP_RESULT_OK; + else + return BP_RESULT_FAILURE; +} + +/* + * Gets the first device ID in the same group as the given ID for enumerating. + * For instance, if any DFP device ID is passed, returns the device ID for DFP1. + * + * The first device ID in the same group as the passed device ID, or 0 if no + * matching device group found. + */ +static uint32_t enum_first_device_id(uint32_t dev_id) +{ + /* Return the first in the group that this ID belongs to. */ + if (dev_id & ATOM_DEVICE_CRT_SUPPORT) + return ATOM_DEVICE_CRT1_SUPPORT; + else if (dev_id & ATOM_DEVICE_DFP_SUPPORT) + return ATOM_DEVICE_DFP1_SUPPORT; + else if (dev_id & ATOM_DEVICE_LCD_SUPPORT) + return ATOM_DEVICE_LCD1_SUPPORT; + else if (dev_id & ATOM_DEVICE_TV_SUPPORT) + return ATOM_DEVICE_TV1_SUPPORT; + else if (dev_id & ATOM_DEVICE_CV_SUPPORT) + return ATOM_DEVICE_CV_SUPPORT; + + /* No group found for this device ID. */ + + dm_error("%s: incorrect input %d\n", __func__, dev_id); + /* No matching support flag for given device ID */ + return 0; +} + +/* + * Gets the next device ID in the group for a given device ID. + * + * The current device ID being enumerated on. + * + * The next device ID in the group, or 0 if no device exists. + */ +static uint32_t enum_next_dev_id(uint32_t dev_id) +{ + /* Get next device ID in the group. */ + switch (dev_id) { + case ATOM_DEVICE_CRT1_SUPPORT: + return ATOM_DEVICE_CRT2_SUPPORT; + case ATOM_DEVICE_LCD1_SUPPORT: + return ATOM_DEVICE_LCD2_SUPPORT; + case ATOM_DEVICE_DFP1_SUPPORT: + return ATOM_DEVICE_DFP2_SUPPORT; + case ATOM_DEVICE_DFP2_SUPPORT: + return ATOM_DEVICE_DFP3_SUPPORT; + case ATOM_DEVICE_DFP3_SUPPORT: + return ATOM_DEVICE_DFP4_SUPPORT; + case ATOM_DEVICE_DFP4_SUPPORT: + return ATOM_DEVICE_DFP5_SUPPORT; + case ATOM_DEVICE_DFP5_SUPPORT: + return ATOM_DEVICE_DFP6_SUPPORT; + } + + /* Done enumerating through devices. */ + return 0; +} + +/* + * Returns the new device tag record for patched BIOS object. + * + * [IN] pExtDisplayPath - External display path to copy device tag from. + * [IN] deviceSupport - Bit vector for device ID support flags. + * [OUT] pDeviceTag - Device tag structure to fill with patched data. + * + * True if a compatible device ID was found, false otherwise. + */ +static bool get_patched_device_tag( + struct bios_parser *bp, + EXT_DISPLAY_PATH *ext_display_path, + uint32_t device_support, + ATOM_CONNECTOR_DEVICE_TAG *device_tag) +{ + uint32_t dev_id; + /* Use fallback behaviour if not supported. */ + if (!bp->remap_device_tags) { + device_tag->ulACPIDeviceEnum = + cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum)); + device_tag->usDeviceID = + cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag)); + return true; + } + + /* Find the first unused in the same group. */ + dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag)); + while (dev_id != 0) { + /* Assign this device ID if supported. */ + if ((device_support & dev_id) != 0) { + device_tag->ulACPIDeviceEnum = + cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum)); + device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id); + return true; + } + + dev_id = enum_next_dev_id(dev_id); + } + + /* No compatible device ID found. */ + return false; +} + +/* + * Adds a device tag to a BIOS object's device tag record if there is + * matching device ID supported. + * + * pObject - Pointer to the BIOS object to add the device tag to. + * pExtDisplayPath - Display path to retrieve base device ID from. + * pDeviceSupport - Pointer to bit vector for supported device IDs. + */ +static void add_device_tag_from_ext_display_path( + struct bios_parser *bp, + ATOM_OBJECT *object, + EXT_DISPLAY_PATH *ext_display_path, + uint32_t *device_support) +{ + /* Get device tag record for object. */ + ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL; + ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL; + enum bp_result result = + bios_parser_get_device_tag_record( + bp, object, &device_tag_record); + + if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE) + && (result == BP_RESULT_OK)) { + uint8_t index; + + if ((device_tag_record->ucNumberOfDevice == 1) && + (le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) { + /*Workaround bug in current VBIOS releases where + * ucNumberOfDevice = 1 but there is no actual device + * tag data. This w/a is temporary until the updated + * VBIOS is distributed. */ + device_tag_record->ucNumberOfDevice = + device_tag_record->ucNumberOfDevice - 1; + } + + /* Attempt to find a matching device ID. */ + index = device_tag_record->ucNumberOfDevice; + device_tag = &device_tag_record->asDeviceTag[index]; + if (get_patched_device_tag( + bp, + ext_display_path, + *device_support, + device_tag)) { + /* Update cached device support to remove assigned ID. + */ + *device_support &= ~le16_to_cpu(device_tag->usDeviceID); + device_tag_record->ucNumberOfDevice++; + } + } +} + +/* + * Read out a single EXT_DISPLAY_PATH from the external display connection info + * table. The specific entry in the table is determined by the enum_id passed + * in. + * + * EXT_DISPLAY_PATH describing a single Configuration table entry + */ + +#define INVALID_CONNECTOR 0xffff + +static EXT_DISPLAY_PATH *get_ext_display_path_entry( + ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table, + uint32_t bios_object_id) +{ + EXT_DISPLAY_PATH *ext_display_path; + uint32_t ext_display_path_index = + ((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1; + + if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH) + return NULL; + + ext_display_path = &config_table->sPath[ext_display_path_index]; + + if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR) + ext_display_path->usDeviceConnector = cpu_to_le16(0); + + return ext_display_path; +} + +/* + * Get AUX/DDC information of input object id + * + * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record + * IR + */ +static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record( + struct bios_parser *bp, + ATOM_OBJECT *object) +{ + uint32_t offset; + ATOM_COMMON_RECORD_HEADER *header; + + if (!object) { + BREAK_TO_DEBUGGER(); + /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return NULL; + + if (LAST_RECORD_TYPE == header->ucRecordType || + 0 == header->ucRecordSize) + break; + + if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE == + header->ucRecordType && + sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <= + header->ucRecordSize) + return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header); + + offset += header->ucRecordSize; + } + + return NULL; +} + +/* + * Get AUX/DDC information of input object id + * + * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record + * IR + */ +static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record( + struct bios_parser *bp, + ATOM_OBJECT *object) +{ + uint32_t offset; + ATOM_COMMON_RECORD_HEADER *header; + + if (!object) { + BREAK_TO_DEBUGGER(); + /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->usRecordOffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); + + if (!header) + return NULL; + + if (LAST_RECORD_TYPE == header->ucRecordType || + 0 == header->ucRecordSize) + break; + + if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE == + header->ucRecordType && + sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <= + header->ucRecordSize) + return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header; + + offset += header->ucRecordSize; + } + + return NULL; +} + +/* + * Check whether we need to patch the VBIOS connector info table with + * data from an external display connection info table. This is + * necessary to support MXM boards with an OPM (output personality + * module). With these designs, the VBIOS connector info table + * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves + * the external connection info table through i2c and then looks up the + * connector ID to find the real connector type (e.g. DFP1). + * + */ +static enum bp_result patch_bios_image_from_ext_display_connection_info( + struct bios_parser *bp) +{ + ATOM_OBJECT_TABLE *connector_tbl; + uint32_t connector_tbl_offset; + struct graphics_object_id object_id; + ATOM_OBJECT *object; + ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl; + EXT_DISPLAY_PATH *ext_display_path; + ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL; + ATOM_I2C_RECORD *i2c_record = NULL; + ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL; + ATOM_HPD_INT_RECORD *hpd_record = NULL; + ATOM_OBJECT_TABLE *encoder_table; + uint32_t encoder_table_offset; + ATOM_OBJECT *opm_object = NULL; + uint32_t i = 0; + struct graphics_object_id opm_object_id = + dal_graphics_object_id_init( + GENERIC_ID_MXM_OPM, + ENUM_ID_1, + OBJECT_TYPE_GENERIC); + ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record; + uint32_t cached_device_support = + le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport); + + uint32_t dst_number; + uint16_t *dst_object_id_list; + + opm_object = get_bios_object(bp, opm_object_id); + if (!opm_object) + return BP_RESULT_UNSUPPORTED; + + memset(&ext_display_connection_info_tbl, 0, + sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO)); + + connector_tbl_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); + + /* Read Connector info table from EEPROM through i2c */ + if (get_ext_display_connection_info(bp, + opm_object, + &ext_display_connection_info_tbl) != BP_RESULT_OK) { + + dm_logger_write(bp->base.ctx->logger, LOG_BIOS, + "%s: Failed to read Connection Info Table", __func__); + return BP_RESULT_UNSUPPORTED; + } + + /* Get pointer to AUX/DDC and HPD LUTs */ + aux_ddc_lut_record = + get_ext_connector_aux_ddc_lut_record(bp, opm_object); + hpd_pin_lut_record = + get_ext_connector_hpd_pin_lut_record(bp, opm_object); + + if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL)) + return BP_RESULT_UNSUPPORTED; + + /* Cache support bits for currently unmapped device types. */ + if (bp->remap_device_tags) { + for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) { + uint32_t j; + /* Remove support for all non-MXM connectors. */ + object = &connector_tbl->asObjects[i]; + object_id = object_id_from_bios_object_id( + le16_to_cpu(object->usObjectID)); + if ((OBJECT_TYPE_CONNECTOR != object_id.type) || + (CONNECTOR_ID_MXM == object_id.id)) + continue; + + /* Remove support for all device tags. */ + if (bios_parser_get_device_tag_record( + bp, object, &dev_tag_record) != BP_RESULT_OK) + continue; + + for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) { + ATOM_CONNECTOR_DEVICE_TAG *device_tag = + &dev_tag_record->asDeviceTag[j]; + cached_device_support &= + ~le16_to_cpu(device_tag->usDeviceID); + } + } + } + + /* Find all MXM connector objects and patch them with connector info + * from the external display connection info table. */ + for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { + uint32_t j; + + object = &connector_tbl->asObjects[i]; + object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); + if ((OBJECT_TYPE_CONNECTOR != object_id.type) || + (CONNECTOR_ID_MXM != object_id.id)) + continue; + + /* Get the correct connection info table entry based on the enum + * id. */ + ext_display_path = get_ext_display_path_entry( + &ext_display_connection_info_tbl, + le16_to_cpu(object->usObjectID)); + if (!ext_display_path) + return BP_RESULT_FAILURE; + + /* Patch device connector ID */ + object->usObjectID = + cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector)); + + /* Patch device tag, ulACPIDeviceEnum. */ + add_device_tag_from_ext_display_path( + bp, + object, + ext_display_path, + &cached_device_support); + + /* Patch HPD info */ + if (ext_display_path->ucExtHPDPINLutIndex < + MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) { + hpd_record = get_hpd_record(bp, object); + if (hpd_record) { + uint8_t index = + ext_display_path->ucExtHPDPINLutIndex; + hpd_record->ucHPDIntGPIOID = + hpd_pin_lut_record->ucHPDPINMap[index]; + } else { + BREAK_TO_DEBUGGER(); + /* Invalid hpd record */ + return BP_RESULT_FAILURE; + } + } + + /* Patch I2C/AUX info */ + if (ext_display_path->ucExtHPDPINLutIndex < + MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) { + i2c_record = get_i2c_record(bp, object); + if (i2c_record) { + uint8_t index = + ext_display_path->ucExtAUXDDCLutIndex; + i2c_record->sucI2cId = + aux_ddc_lut_record->ucAUXDDCMap[index]; + } else { + BREAK_TO_DEBUGGER(); + /* Invalid I2C record */ + return BP_RESULT_FAILURE; + } + } + + /* Merge with other MXM connectors that map to the same physical + * connector. */ + for (j = i + 1; + j < connector_tbl->ucNumberOfObjects; j++) { + ATOM_OBJECT *next_object; + struct graphics_object_id next_object_id; + EXT_DISPLAY_PATH *next_ext_display_path; + + next_object = &connector_tbl->asObjects[j]; + next_object_id = object_id_from_bios_object_id( + le16_to_cpu(next_object->usObjectID)); + + if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) && + (CONNECTOR_ID_MXM == next_object_id.id)) + continue; + + next_ext_display_path = get_ext_display_path_entry( + &ext_display_connection_info_tbl, + le16_to_cpu(next_object->usObjectID)); + + if (next_ext_display_path == NULL) + return BP_RESULT_FAILURE; + + /* Merge if using same connector. */ + if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) == + le16_to_cpu(ext_display_path->usDeviceConnector)) && + (le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) { + /* Clear duplicate connector from table. */ + next_object->usObjectID = cpu_to_le16(0); + add_device_tag_from_ext_display_path( + bp, + object, + ext_display_path, + &cached_device_support); + } + } + } + + /* Find all encoders which have an MXM object as their destination. + * Replace the MXM object with the real connector Id from the external + * display connection info table */ + + encoder_table_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); + encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); + + for (i = 0; i < encoder_table->ucNumberOfObjects; i++) { + uint32_t j; + + object = &encoder_table->asObjects[i]; + + dst_number = get_dest_obj_list(bp, object, &dst_object_id_list); + + for (j = 0; j < dst_number; j++) { + object_id = object_id_from_bios_object_id( + dst_object_id_list[j]); + + if ((OBJECT_TYPE_CONNECTOR != object_id.type) || + (CONNECTOR_ID_MXM != object_id.id)) + continue; + + /* Get the correct connection info table entry based on + * the enum id. */ + ext_display_path = + get_ext_display_path_entry( + &ext_display_connection_info_tbl, + dst_object_id_list[j]); + + if (ext_display_path == NULL) + return BP_RESULT_FAILURE; + + dst_object_id_list[j] = + le16_to_cpu(ext_display_path->usDeviceConnector); + } + } + + return BP_RESULT_OK; +} + +/* + * Check whether we need to patch the VBIOS connector info table with + * data from an external display connection info table. This is + * necessary to support MXM boards with an OPM (output personality + * module). With these designs, the VBIOS connector info table + * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves + * the external connection info table through i2c and then looks up the + * connector ID to find the real connector type (e.g. DFP1). + * + */ + +static void process_ext_display_connection_info(struct bios_parser *bp) +{ + ATOM_OBJECT_TABLE *connector_tbl; + uint32_t connector_tbl_offset; + struct graphics_object_id object_id; + ATOM_OBJECT *object; + bool mxm_connector_found = false; + bool null_entry_found = false; + uint32_t i = 0; + + connector_tbl_offset = bp->object_info_tbl_offset + + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); + connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); + + /* Look for MXM connectors to determine whether we need patch the VBIOS + * connector info table. Look for null entries to determine whether we + * need to compact connector table. */ + for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { + object = &connector_tbl->asObjects[i]; + object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); + + if ((OBJECT_TYPE_CONNECTOR == object_id.type) && + (CONNECTOR_ID_MXM == object_id.id)) { + /* Once we found MXM connector - we can break */ + mxm_connector_found = true; + break; + } else if (OBJECT_TYPE_CONNECTOR != object_id.type) { + /* We need to continue looping - to check if MXM + * connector present */ + null_entry_found = true; + } + } + + /* Patch BIOS image */ + if (mxm_connector_found || null_entry_found) { + uint32_t connectors_num = 0; + uint8_t *original_bios; + /* Step 1: Replace bios image with the new copy which will be + * patched */ + bp->base.bios_local_image = dm_alloc(bp->base.bios_size); + if (bp->base.bios_local_image == NULL) { + BREAK_TO_DEBUGGER(); + /* Failed to alloc bp->base.bios_local_image */ + return; + } + + memmove(bp->base.bios_local_image, bp->base.bios, bp->base.bios_size); + original_bios = bp->base.bios; + bp->base.bios = bp->base.bios_local_image; + connector_tbl = + GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); + + /* Step 2: (only if MXM connector found) Patch BIOS image with + * info from external module */ + if (mxm_connector_found && + patch_bios_image_from_ext_display_connection_info(bp) != + BP_RESULT_OK) { + /* Patching the bios image has failed. We will copy + * again original image provided and afterwards + * only remove null entries */ + memmove( + bp->base.bios_local_image, + original_bios, + bp->base.bios_size); + } + + /* Step 3: Compact connector table (remove null entries, valid + * entries moved to beginning) */ + for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { + object = &connector_tbl->asObjects[i]; + object_id = object_id_from_bios_object_id( + le16_to_cpu(object->usObjectID)); + + if (OBJECT_TYPE_CONNECTOR != object_id.type) + continue; + + if (i != connectors_num) { + memmove( + &connector_tbl-> + asObjects[connectors_num], + object, + sizeof(ATOM_OBJECT)); + } + ++connectors_num; + } + connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num; + } +} + +static void bios_parser_post_init(struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + process_ext_display_connection_info(bp); +} + +/** + * bios_parser_set_scratch_critical_state + * + * @brief + * update critical state bit in VBIOS scratch register + * + * @param + * bool - to set or reset state + */ +static void bios_parser_set_scratch_critical_state( + struct dc_bios *dcb, + bool state) +{ + bios_set_scratch_critical_state(dcb, state); +} + +/* + * get_integrated_info_v8 + * + * @brief + * Get V8 integrated BIOS information + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result get_integrated_info_v8( + struct bios_parser *bp, + struct integrated_info *info) +{ + ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8; + uint32_t i; + + info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8, + bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); + + if (info_v8 == NULL) + return BP_RESULT_BADBIOSTABLE; + info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10; + info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10; + info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; + + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + /* Convert [10KHz] into [KHz] */ + info->disp_clk_voltage[i].max_supported_clk = + le32_to_cpu(info_v8->sDISPCLK_Voltage[i]. + ulMaximumSupportedCLK) * 10; + info->disp_clk_voltage[i].voltage_index = + le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex); + } + + info->boot_up_req_display_vector = + le32_to_cpu(info_v8->ulBootUpReqDisplayVector); + info->gpu_cap_info = + le32_to_cpu(info_v8->ulGPUCapInfo); + + /* + * system_config: Bit[0] = 0 : PCIE power gating disabled + * = 1 : PCIE power gating enabled + * Bit[1] = 0 : DDR-PLL shut down disabled + * = 1 : DDR-PLL shut down enabled + * Bit[2] = 0 : DDR-PLL power down disabled + * = 1 : DDR-PLL power down enabled + */ + info->system_config = le32_to_cpu(info_v8->ulSystemConfig); + info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo); + info->boot_up_nb_voltage = + le16_to_cpu(info_v8->usBootUpNBVoltage); + info->ext_disp_conn_info_offset = + le16_to_cpu(info_v8->usExtDispConnInfoOffset); + info->memory_type = info_v8->ucMemoryType; + info->ma_channel_number = info_v8->ucUMAChannelNumber; + info->gmc_restore_reset_time = + le32_to_cpu(info_v8->ulGMCRestoreResetTime); + + info->minimum_n_clk = + le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]); + for (i = 1; i < 4; ++i) + info->minimum_n_clk = + info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ? + info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]); + + info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk); + info->ddr_dll_power_up_time = + le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime); + info->ddr_pll_power_up_time = + le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime); + info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType); + info->lvds_ss_percentage = + le16_to_cpu(info_v8->usLvdsSSPercentage); + info->lvds_sspread_rate_in_10hz = + le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz); + info->hdmi_ss_percentage = + le16_to_cpu(info_v8->usHDMISSPercentage); + info->hdmi_sspread_rate_in_10hz = + le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz); + info->dvi_ss_percentage = + le16_to_cpu(info_v8->usDVISSPercentage); + info->dvi_sspread_rate_in_10_hz = + le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz); + + info->max_lvds_pclk_freq_in_single_link = + le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink); + info->lvds_misc = info_v8->ucLvdsMisc; + info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = + info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; + info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = + info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; + info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = + info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; + info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = + info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; + info->lvds_pwr_off_seq_de_to_dig_on_in4ms = + info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; + info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = + info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; + info->lvds_off_to_on_delay_in_4ms = + info_v8->ucLVDSOffToOnDelay_in4Ms; + info->lvds_bit_depth_control_val = + le32_to_cpu(info_v8->ulLCDBitDepthControlVal); + + for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { + /* Convert [10KHz] into [KHz] */ + info->avail_s_clk[i].supported_s_clk = + le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10; + info->avail_s_clk[i].voltage_index = + le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex); + info->avail_s_clk[i].voltage_id = + le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID); + } + + for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { + info->ext_disp_conn_info.gu_id[i] = + info_v8->sExtDispConnInfo.ucGuid[i]; + } + + for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { + info->ext_disp_conn_info.path[i].device_connector_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector)); + + info->ext_disp_conn_info.path[i].ext_encoder_obj_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); + + info->ext_disp_conn_info.path[i].device_tag = + le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag); + info->ext_disp_conn_info.path[i].device_acpi_enum = + le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); + info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = + info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; + info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = + info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; + info->ext_disp_conn_info.path[i].channel_mapping.raw = + info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping; + } + info->ext_disp_conn_info.checksum = + info_v8->sExtDispConnInfo.ucChecksum; + + return BP_RESULT_OK; +} + +/* + * get_integrated_info_v8 + * + * @brief + * Get V8 integrated BIOS information + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result get_integrated_info_v9( + struct bios_parser *bp, + struct integrated_info *info) +{ + ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9; + uint32_t i; + + info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9, + bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); + + if (!info_v9) + return BP_RESULT_BADBIOSTABLE; + + info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10; + info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10; + info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10; + + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + /* Convert [10KHz] into [KHz] */ + info->disp_clk_voltage[i].max_supported_clk = + le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10; + info->disp_clk_voltage[i].voltage_index = + le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex); + } + + info->boot_up_req_display_vector = + le32_to_cpu(info_v9->ulBootUpReqDisplayVector); + info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo); + + /* + * system_config: Bit[0] = 0 : PCIE power gating disabled + * = 1 : PCIE power gating enabled + * Bit[1] = 0 : DDR-PLL shut down disabled + * = 1 : DDR-PLL shut down enabled + * Bit[2] = 0 : DDR-PLL power down disabled + * = 1 : DDR-PLL power down enabled + */ + info->system_config = le32_to_cpu(info_v9->ulSystemConfig); + info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo); + info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage); + info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset); + info->memory_type = info_v9->ucMemoryType; + info->ma_channel_number = info_v9->ucUMAChannelNumber; + info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime); + + info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]); + for (i = 1; i < 4; ++i) + info->minimum_n_clk = + info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ? + info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]); + + info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk); + info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime); + info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime); + info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType); + info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage); + info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz); + info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage); + info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz); + info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage); + info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz); + + info->max_lvds_pclk_freq_in_single_link = + le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink); + info->lvds_misc = info_v9->ucLvdsMisc; + info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = + info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; + info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = + info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; + info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = + info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; + info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = + info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; + info->lvds_pwr_off_seq_de_to_dig_on_in4ms = + info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; + info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = + info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; + info->lvds_off_to_on_delay_in_4ms = + info_v9->ucLVDSOffToOnDelay_in4Ms; + info->lvds_bit_depth_control_val = + le32_to_cpu(info_v9->ulLCDBitDepthControlVal); + + for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { + /* Convert [10KHz] into [KHz] */ + info->avail_s_clk[i].supported_s_clk = + le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10; + info->avail_s_clk[i].voltage_index = + le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex); + info->avail_s_clk[i].voltage_id = + le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID); + } + + for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { + info->ext_disp_conn_info.gu_id[i] = + info_v9->sExtDispConnInfo.ucGuid[i]; + } + + for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { + info->ext_disp_conn_info.path[i].device_connector_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector)); + + info->ext_disp_conn_info.path[i].ext_encoder_obj_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); + + info->ext_disp_conn_info.path[i].device_tag = + le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag); + info->ext_disp_conn_info.path[i].device_acpi_enum = + le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); + info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = + info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; + info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = + info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; + info->ext_disp_conn_info.path[i].channel_mapping.raw = + info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping; + } + info->ext_disp_conn_info.checksum = + info_v9->sExtDispConnInfo.ucChecksum; + + return BP_RESULT_OK; +} + +/* + * construct_integrated_info + * + * @brief + * Get integrated BIOS information based on table revision + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result construct_integrated_info( + struct bios_parser *bp, + struct integrated_info *info) +{ + enum bp_result result = BP_RESULT_BADBIOSTABLE; + + ATOM_COMMON_TABLE_HEADER *header; + struct atom_data_revision revision; + + if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) { + header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, + bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); + + get_atom_data_table_revision(header, &revision); + + /* Don't need to check major revision as they are all 1 */ + switch (revision.minor) { + case 8: + result = get_integrated_info_v8(bp, info); + break; + case 9: + result = get_integrated_info_v9(bp, info); + break; + default: + return result; + + } + } + + /* Sort voltage table from low to high*/ + if (result == BP_RESULT_OK) { + struct clock_voltage_caps temp = {0, 0}; + uint32_t i; + uint32_t j; + + for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + for (j = i; j > 0; --j) { + if ( + info->disp_clk_voltage[j].max_supported_clk < + info->disp_clk_voltage[j-1].max_supported_clk) { + /* swap j and j - 1*/ + temp = info->disp_clk_voltage[j-1]; + info->disp_clk_voltage[j-1] = + info->disp_clk_voltage[j]; + info->disp_clk_voltage[j] = temp; + } + } + } + + } + + return result; +} + +static struct integrated_info *bios_parser_create_integrated_info( + struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct integrated_info *info = NULL; + + info = dm_alloc(sizeof(struct integrated_info)); + + if (info == NULL) { + ASSERT_CRITICAL(0); + return NULL; + } + + if (construct_integrated_info(bp, info) == BP_RESULT_OK) + return info; + + dm_free(info); + + return NULL; +} + +/******************************************************************************/ + +static const struct dc_vbios_funcs vbios_funcs = { + .get_connectors_number = bios_parser_get_connectors_number, + + .get_encoder_id = bios_parser_get_encoder_id, + + .get_connector_id = bios_parser_get_connector_id, + + .get_dst_number = bios_parser_get_dst_number, + + .get_gpio_record = bios_parser_get_gpio_record, + + .get_src_obj = bios_parser_get_src_obj, + + .get_dst_obj = bios_parser_get_dst_obj, + + .get_i2c_info = bios_parser_get_i2c_info, + + .get_voltage_ddc_info = bios_parser_get_voltage_ddc_info, + + .get_thermal_ddc_info = bios_parser_get_thermal_ddc_info, + + .get_hpd_info = bios_parser_get_hpd_info, + + .get_device_tag = bios_parser_get_device_tag, + + .get_firmware_info = bios_parser_get_firmware_info, + + .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info, + + .get_ss_entry_number = bios_parser_get_ss_entry_number, + + .get_embedded_panel_info = bios_parser_get_embedded_panel_info, + + .get_gpio_pin_info = bios_parser_get_gpio_pin_info, + + .get_embedded_panel_info = bios_parser_get_embedded_panel_info, + + .get_gpio_pin_info = bios_parser_get_gpio_pin_info, + + .get_encoder_cap_info = bios_parser_get_encoder_cap_info, + + /* bios scratch register communication */ + .is_accelerated_mode = bios_is_accelerated_mode, + + .set_scratch_critical_state = bios_parser_set_scratch_critical_state, + + .is_device_id_supported = bios_parser_is_device_id_supported, + + /* COMMANDS */ + .encoder_control = bios_parser_encoder_control, + + .transmitter_control = bios_parser_transmitter_control, + + .crt_control = bios_parser_crt_control, /* not used in DAL3. keep for now in case we need to support VGA on Bonaire */ + + .enable_crtc = bios_parser_enable_crtc, + + .adjust_pixel_clock = bios_parser_adjust_pixel_clock, + + .set_pixel_clock = bios_parser_set_pixel_clock, + + .set_dce_clock = bios_parser_set_dce_clock, + + .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll, + + .program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */ + + .crtc_source_select = bios_parser_crtc_source_select, /* still use. should probably retire and program directly */ + + .program_display_engine_pll = bios_parser_program_display_engine_pll, + + .enable_disp_power_gating = bios_parser_enable_disp_power_gating, + + /* SW init and patch */ + .post_init = bios_parser_post_init, /* patch vbios table for mxm module by reading i2c */ + + .bios_parser_destroy = bios_parser_destroy, +}; + +static bool bios_parser_construct( + struct bios_parser *bp, + struct bp_init_data *init, + enum dce_version dce_version) +{ + uint16_t *rom_header_offset = NULL; + ATOM_ROM_HEADER *rom_header = NULL; + ATOM_OBJECT_HEADER *object_info_tbl; + struct atom_data_revision tbl_rev = {0}; + + if (!init) + return false; + + if (!init->bios) + return false; + + bp->base.funcs = &vbios_funcs; + bp->base.bios = init->bios; + bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT; + + bp->base.ctx = init->ctx; + bp->base.bios_local_image = NULL; + + rom_header_offset = + GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER); + + if (!rom_header_offset) + return false; + + rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset); + + if (!rom_header) + return false; + + get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev); + if (tbl_rev.major >= 2 && tbl_rev.minor >= 2) + return false; + + bp->master_data_tbl = + GET_IMAGE(ATOM_MASTER_DATA_TABLE, + rom_header->usMasterDataTableOffset); + + if (!bp->master_data_tbl) + return false; + + bp->object_info_tbl_offset = DATA_TABLES(Object_Header); + + if (!bp->object_info_tbl_offset) + return false; + + object_info_tbl = + GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset); + + if (!object_info_tbl) + return false; + + get_atom_data_table_revision(&object_info_tbl->sHeader, + &bp->object_info_tbl.revision); + + if (bp->object_info_tbl.revision.major == 1 + && bp->object_info_tbl.revision.minor >= 3) { + ATOM_OBJECT_HEADER_V3 *tbl_v3; + + tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3, + bp->object_info_tbl_offset); + if (!tbl_v3) + return false; + + bp->object_info_tbl.v1_3 = tbl_v3; + } else if (bp->object_info_tbl.revision.major == 1 + && bp->object_info_tbl.revision.minor >= 1) + bp->object_info_tbl.v1_1 = object_info_tbl; + else + return false; + + dal_bios_parser_init_cmd_tbl(bp); + dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version); + + bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); + + return true; +} + +/******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.h new file mode 100644 index 000000000000..d6f16275048f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_H__ +#define __DAL_BIOS_PARSER_H__ + +struct dc_bios *bios_parser_create( + struct bp_init_data *init, + enum dce_version dce_version); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c new file mode 100644 index 000000000000..8e56d2f25dea --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c @@ -0,0 +1,82 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" +#include "bios_parser_helper.h" +#include "command_table_helper.h" +#include "command_table.h" +#include "bios_parser_types_internal.h" + +uint8_t *get_image(struct dc_bios *bp, + uint32_t offset, + uint32_t size) +{ + if (bp->bios && offset + size < bp->bios_size) + return bp->bios + offset; + else + return NULL; +} + +#include "reg_helper.h" + +#define CTX \ + bios->ctx +#define REG(reg)\ + (bios->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + ATOM_ ## field_name ## _SHIFT, ATOM_ ## field_name + +bool bios_is_accelerated_mode( + struct dc_bios *bios) +{ + uint32_t acc_mode; + REG_GET(BIOS_SCRATCH_6, S6_ACC_MODE, &acc_mode); + return (acc_mode == 1); +} + + +void bios_set_scratch_acc_mode_change( + struct dc_bios *bios) +{ + REG_UPDATE(BIOS_SCRATCH_6, S6_ACC_MODE, 1); +} + + +void bios_set_scratch_critical_state( + struct dc_bios *bios, + bool state) +{ + uint32_t critial_state = state ? 1 : 0; + REG_UPDATE(BIOS_SCRATCH_6, S6_CRITICAL_STATE, critial_state); +} + + + diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h new file mode 100644 index 000000000000..a8fbb82b8c8e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h @@ -0,0 +1,40 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_HELPER_H__ +#define __DAL_BIOS_PARSER_HELPER_H__ + +struct bios_parser; + +uint8_t *get_image(struct dc_bios *bp, uint32_t offset, + uint32_t size); + +bool bios_is_accelerated_mode(struct dc_bios *bios); +void bios_set_scratch_acc_mode_change(struct dc_bios *bios); +void bios_set_scratch_critical_state(struct dc_bios *bios, bool state); + +#define GET_IMAGE(type, offset) ((type *) get_image(&bp->base, offset, sizeof(type))) + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c new file mode 100644 index 000000000000..42272c35df2d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c @@ -0,0 +1,50 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "bios_parser_interface.h" +#include "bios_parser.h" + + +struct dc_bios *dal_bios_parser_create( + struct bp_init_data *init, + enum dce_version dce_version) +{ + struct dc_bios *bios = NULL; + + bios = bios_parser_create(init, dce_version); + + return bios; +} + +void dal_bios_parser_destroy(struct dc_bios **dcb) +{ + struct dc_bios *bios = *dcb; + + bios->funcs->bios_parser_destroy(dcb); +} + diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h new file mode 100644 index 000000000000..5918923bfb93 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal.h @@ -0,0 +1,72 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_TYPES_BIOS_H__ +#define __DAL_BIOS_PARSER_TYPES_BIOS_H__ + +#include "dc_bios_types.h" +#include "bios_parser_helper.h" + +struct atom_data_revision { + uint32_t major; + uint32_t minor; +}; + +struct object_info_table { + struct atom_data_revision revision; + union { + ATOM_OBJECT_HEADER *v1_1; + ATOM_OBJECT_HEADER_V3 *v1_3; + }; +}; + +enum spread_spectrum_id { + SS_ID_UNKNOWN = 0, + SS_ID_DP1 = 0xf1, + SS_ID_DP2 = 0xf2, + SS_ID_LVLINK_2700MHZ = 0xf3, + SS_ID_LVLINK_1620MHZ = 0xf4 +}; + +struct bios_parser { + struct dc_bios base; + + struct object_info_table object_info_tbl; + uint32_t object_info_tbl_offset; + ATOM_MASTER_DATA_TABLE *master_data_tbl; + + const struct bios_parser_helper *bios_helper; + + const struct command_table_helper *cmd_helper; + struct cmd_tbl cmd_tbl; + + bool remap_device_tags; +}; + +/* Bios Parser from DC Bios */ +#define BP_FROM_DCB(dc_bios) \ + container_of(dc_bios, struct bios_parser, base) + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c new file mode 100644 index 000000000000..51f6052eac96 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -0,0 +1,2609 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_interface.h" + +#include "command_table.h" +#include "command_table_helper.h" +#include "bios_parser_helper.h" +#include "bios_parser_types_internal.h" + +#define EXEC_BIOS_CMD_TABLE(command, params)\ + (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \ + GetIndexIntoMasterTable(COMMAND, command), \ + ¶ms) == 0) + +#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\ + cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \ + GetIndexIntoMasterTable(COMMAND, command), &frev, &crev) + +#define BIOS_CMD_TABLE_PARA_REVISION(command)\ + bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \ + GetIndexIntoMasterTable(COMMAND, command)) + +static void init_dig_encoder_control(struct bios_parser *bp); +static void init_transmitter_control(struct bios_parser *bp); +static void init_set_pixel_clock(struct bios_parser *bp); +static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp); +static void init_adjust_display_pll(struct bios_parser *bp); +static void init_dac_encoder_control(struct bios_parser *bp); +static void init_dac_output_control(struct bios_parser *bp); +static void init_blank_crtc(struct bios_parser *bp); +static void init_set_crtc_timing(struct bios_parser *bp); +static void init_set_crtc_overscan(struct bios_parser *bp); +static void init_select_crtc_source(struct bios_parser *bp); +static void init_enable_crtc(struct bios_parser *bp); +static void init_enable_crtc_mem_req(struct bios_parser *bp); +static void init_compute_memore_engine_pll(struct bios_parser *bp); +static void init_external_encoder_control(struct bios_parser *bp); +static void init_enable_disp_power_gating(struct bios_parser *bp); +static void init_program_clock(struct bios_parser *bp); +static void init_set_dce_clock(struct bios_parser *bp); + +void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) +{ + init_dig_encoder_control(bp); + init_transmitter_control(bp); + init_set_pixel_clock(bp); + init_enable_spread_spectrum_on_ppll(bp); + init_adjust_display_pll(bp); + init_dac_encoder_control(bp); + init_dac_output_control(bp); + init_blank_crtc(bp); + init_set_crtc_timing(bp); + init_set_crtc_overscan(bp); + init_select_crtc_source(bp); + init_enable_crtc(bp); + init_enable_crtc_mem_req(bp); + init_program_clock(bp); + init_compute_memore_engine_pll(bp); + init_external_encoder_control(bp); + init_enable_disp_power_gating(bp); + init_set_dce_clock(bp); +} + +static uint32_t bios_cmd_table_para_revision(void *cgs_device, + uint32_t index) +{ + uint8_t frev, crev; + + if (cgs_atom_get_cmd_table_revs(cgs_device, + index, + &frev, &crev) != 0) + return 0; + return crev; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** D I G E N C O D E R C O N T R O L + ** + ******************************************************************************** + *******************************************************************************/ +static enum bp_result encoder_control_digx_v3( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +static enum bp_result encoder_control_digx_v4( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +#ifdef LATEST_ATOM_BIOS_SUPPORT +static enum bp_result encoder_control_digx_v5( + struct bios_parser *bp, + struct bp_encoder_control *cntl); +#endif + +static void init_encoder_control_dig_v1(struct bios_parser *bp); + +static void init_dig_encoder_control(struct bios_parser *bp) +{ + uint32_t version = + BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl); + + switch (version) { + case 2: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3; + break; + case 4: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4; + break; + +#ifdef LATEST_ATOM_BIOS_SUPPORT + case 5: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5; + break; +#endif + + default: + init_encoder_control_dig_v1(bp); + break; + } +} + +static enum bp_result encoder_control_dig_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl); +static enum bp_result encoder_control_dig1_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl); +static enum bp_result encoder_control_dig2_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +static void init_encoder_control_dig_v1(struct bios_parser *bp) +{ + struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; + + if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl)) + cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1; + else + cmd_tbl->encoder_control_dig1 = NULL; + + if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl)) + cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1; + else + cmd_tbl->encoder_control_dig2 = NULL; + + cmd_tbl->dig_encoder_control = encoder_control_dig_v1; +} + +static enum bp_result encoder_control_dig_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; + + if (cntl != NULL) + switch (cntl->engine_id) { + case ENGINE_ID_DIGA: + if (cmd_tbl->encoder_control_dig1 != NULL) + result = + cmd_tbl->encoder_control_dig1(bp, cntl); + break; + case ENGINE_ID_DIGB: + if (cmd_tbl->encoder_control_dig2 != NULL) + result = + cmd_tbl->encoder_control_dig2(bp, cntl); + break; + + default: + break; + } + + return result; +} + +static enum bp_result encoder_control_dig1_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; + + bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); + + if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result encoder_control_dig2_v1( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; + + bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, ¶ms); + + if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result encoder_control_digx_v3( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0}; + + if (LANE_COUNT_FOUR < cntl->lanes_number) + params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ + else + params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ + + params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); + + /* We need to convert from KHz units into 10KHz units */ + params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); + params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + params.ucEncoderMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio); + params.ucLaneNum = (uint8_t)(cntl->lanes_number); + + if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result encoder_control_digx_v4( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0}; + + if (LANE_COUNT_FOUR < cntl->lanes_number) + params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */ + else + params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ + + params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); + + /* We need to convert from KHz units into 10KHz units */ + params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); + params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + params.ucEncoderMode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio)); + params.ucLaneNum = (uint8_t)(cntl->lanes_number); + + if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +#ifdef LATEST_ATOM_BIOS_SUPPORT +static enum bp_result encoder_control_digx_v5( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0}; + + params.ucDigId = (uint8_t)(cntl->engine_id); + params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); + + params.ulPixelClock = cntl->pixel_clock / 10; + params.ucDigMode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio)); + params.ucLaneNum = (uint8_t)(cntl->lanes_number); + + switch (cntl->color_depth) { + case COLOR_DEPTH_888: + params.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; + case COLOR_DEPTH_101010: + params.ucBitPerColor = PANEL_10BIT_PER_COLOR; + break; + case COLOR_DEPTH_121212: + params.ucBitPerColor = PANEL_12BIT_PER_COLOR; + break; + case COLOR_DEPTH_161616: + params.ucBitPerColor = PANEL_16BIT_PER_COLOR; + break; + default: + break; + } + + if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) + switch (cntl->color_depth) { + case COLOR_DEPTH_101010: + params.ulPixelClock = + (params.ulPixelClock * 30) / 24; + break; + case COLOR_DEPTH_121212: + params.ulPixelClock = + (params.ulPixelClock * 36) / 24; + break; + case COLOR_DEPTH_161616: + params.ulPixelClock = + (params.ulPixelClock * 48) / 24; + break; + default: + break; + } + + if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} +#endif + +/******************************************************************************* + ******************************************************************************** + ** + ** TRANSMITTER CONTROL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result transmitter_control_v2( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); +static enum bp_result transmitter_control_v3( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); +static enum bp_result transmitter_control_v4( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); +static enum bp_result transmitter_control_v1_5( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); + +static void init_transmitter_control(struct bios_parser *bp) +{ + uint8_t frev; + uint8_t crev; + + if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl, + frev, crev) != 0) + BREAK_TO_DEBUGGER(); + switch (crev) { + case 2: + bp->cmd_tbl.transmitter_control = transmitter_control_v2; + break; + case 3: + bp->cmd_tbl.transmitter_control = transmitter_control_v3; + break; + case 4: + bp->cmd_tbl.transmitter_control = transmitter_control_v4; + break; + case 5: + bp->cmd_tbl.transmitter_control = transmitter_control_v1_5; + break; + case 6: + bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; + break; + default: + bp->cmd_tbl.transmitter_control = NULL; + break; + } +} + +static enum bp_result transmitter_control_v2( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params; + enum connector_id connector_id = + dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); + + memset(¶ms, 0, sizeof(params)); + + switch (cntl->transmitter) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + case TRANSMITTER_TRAVIS_LCD: + break; + default: + return BP_RESULT_BADINPUT; + } + + switch (cntl->action) { + case TRANSMITTER_CONTROL_INIT: + if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) || + (CONNECTOR_ID_DUAL_LINK_DVID == connector_id)) + /* on INIT this bit should be set according to the + * phisycal connector + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* connector object id */ + params.usInitInfo = + cpu_to_le16((uint8_t)cntl->connector_obj_id.id); + break; + case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: + /* votage swing and pre-emphsis */ + params.asMode.ucLaneSel = (uint8_t)cntl->lane_select; + params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings; + break; + default: + /* if dual-link */ + if (LANE_COUNT_FOUR < cntl->lanes_number) { + /* on ENABLE/DISABLE this bit should be set according to + * actual timing (number of lanes) + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* link rate, half for dual link + * We need to convert from KHz units into 20KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); + } else + /* link rate, half for dual link + * We need to convert from KHz units into 10KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + break; + } + + /* 00 - coherent mode + * 01 - incoherent mode + */ + + params.acConfig.fCoherentMode = cntl->coherent; + + if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) + || (TRANSMITTER_UNIPHY_D == cntl->transmitter) + || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) + /* Bit2: Transmitter Link selection + * =0 when bit0=0, single link A/C/E, when bit0=1, + * master link A/C/E + * =1 when bit0=0, single link B/D/F, when bit0=1, + * master link B/D/F + */ + params.acConfig.ucLinkSel = 1; + + if (ENGINE_ID_DIGB == cntl->engine_id) + /* Bit3: Transmitter data source selection + * =0 DIGA is data source. + * =1 DIGB is data source. + * This bit is only useful when ucAction= ATOM_ENABLE + */ + params.acConfig.ucEncoderSel = 1; + + if (CONNECTOR_ID_DISPLAY_PORT == connector_id) + /* Bit4: DP connector flag + * =0 connector is none-DP connector + * =1 connector is DP connector + */ + params.acConfig.fDPConnector = 1; + + /* Bit[7:6]: Transmitter selection + * =0 UNIPHY_ENCODER: UNIPHYA/B + * =1 UNIPHY1_ENCODER: UNIPHYC/D + * =2 UNIPHY2_ENCODER: UNIPHYE/F + * =3 reserved + */ + params.acConfig.ucTransmitterSel = + (uint8_t)bp->cmd_helper->transmitter_bp_to_atom( + cntl->transmitter); + + params.ucAction = (uint8_t)cntl->action; + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result transmitter_control_v3( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params; + uint32_t pll_id; + enum connector_id conn_id = + dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); + const struct command_table_helper *cmd = bp->cmd_helper; + bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id) + || (CONNECTOR_ID_DUAL_LINK_DVID == conn_id); + + memset(¶ms, 0, sizeof(params)); + + switch (cntl->transmitter) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + case TRANSMITTER_TRAVIS_LCD: + break; + default: + return BP_RESULT_BADINPUT; + } + + if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id)) + return BP_RESULT_BADINPUT; + + /* fill information based on the action */ + switch (cntl->action) { + case TRANSMITTER_CONTROL_INIT: + if (dual_link_conn) { + /* on INIT this bit should be set according to the + * phisycal connector + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + } + + /* connector object id */ + params.usInitInfo = + cpu_to_le16((uint8_t)(cntl->connector_obj_id.id)); + break; + case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: + /* votage swing and pre-emphsis */ + params.asMode.ucLaneSel = (uint8_t)cntl->lane_select; + params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings; + break; + default: + if (dual_link_conn && cntl->multi_path) + /* on ENABLE/DISABLE this bit should be set according to + * actual timing (number of lanes) + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* if dual-link */ + if (LANE_COUNT_FOUR < cntl->lanes_number) { + /* on ENABLE/DISABLE this bit should be set according to + * actual timing (number of lanes) + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* link rate, half for dual link + * We need to convert from KHz units into 20KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); + } else { + /* link rate, half for dual link + * We need to convert from KHz units into 10KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + } + break; + } + + /* 00 - coherent mode + * 01 - incoherent mode + */ + + params.acConfig.fCoherentMode = cntl->coherent; + + if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) + || (TRANSMITTER_UNIPHY_D == cntl->transmitter) + || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) + /* Bit2: Transmitter Link selection + * =0 when bit0=0, single link A/C/E, when bit0=1, + * master link A/C/E + * =1 when bit0=0, single link B/D/F, when bit0=1, + * master link B/D/F + */ + params.acConfig.ucLinkSel = 1; + + if (ENGINE_ID_DIGB == cntl->engine_id) + /* Bit3: Transmitter data source selection + * =0 DIGA is data source. + * =1 DIGB is data source. + * This bit is only useful when ucAction= ATOM_ENABLE + */ + params.acConfig.ucEncoderSel = 1; + + /* Bit[7:6]: Transmitter selection + * =0 UNIPHY_ENCODER: UNIPHYA/B + * =1 UNIPHY1_ENCODER: UNIPHYC/D + * =2 UNIPHY2_ENCODER: UNIPHYE/F + * =3 reserved + */ + params.acConfig.ucTransmitterSel = + (uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter); + + params.ucLaneNum = (uint8_t)cntl->lanes_number; + + params.acConfig.ucRefClkSource = (uint8_t)pll_id; + + params.ucAction = (uint8_t)cntl->action; + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result transmitter_control_v4( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params; + uint32_t ref_clk_src_id; + enum connector_id conn_id = + dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); + const struct command_table_helper *cmd = bp->cmd_helper; + + memset(¶ms, 0, sizeof(params)); + + switch (cntl->transmitter) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + case TRANSMITTER_TRAVIS_LCD: + break; + default: + return BP_RESULT_BADINPUT; + } + + if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id)) + return BP_RESULT_BADINPUT; + + switch (cntl->action) { + case TRANSMITTER_CONTROL_INIT: + { + if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) || + (CONNECTOR_ID_DUAL_LINK_DVID == conn_id)) + /* on INIT this bit should be set according to the + * phisycal connector + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* connector object id */ + params.usInitInfo = + cpu_to_le16((uint8_t)(cntl->connector_obj_id.id)); + } + break; + case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS: + /* votage swing and pre-emphsis */ + params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select); + params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings); + break; + default: + if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) || + (CONNECTOR_ID_DUAL_LINK_DVID == conn_id)) + /* on ENABLE/DISABLE this bit should be set according to + * actual timing (number of lanes) + * Bit0: dual link connector flag + * =0 connector is single link connector + * =1 connector is dual link connector + */ + params.acConfig.fDualLinkConnector = 1; + + /* if dual-link */ + if (LANE_COUNT_FOUR < cntl->lanes_number) + /* link rate, half for dual link + * We need to convert from KHz units into 20KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 20)); + else { + /* link rate, half for dual link + * We need to convert from KHz units into 10KHz units + */ + params.usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + } + break; + } + + /* 00 - coherent mode + * 01 - incoherent mode + */ + + params.acConfig.fCoherentMode = cntl->coherent; + + if ((TRANSMITTER_UNIPHY_B == cntl->transmitter) + || (TRANSMITTER_UNIPHY_D == cntl->transmitter) + || (TRANSMITTER_UNIPHY_F == cntl->transmitter)) + /* Bit2: Transmitter Link selection + * =0 when bit0=0, single link A/C/E, when bit0=1, + * master link A/C/E + * =1 when bit0=0, single link B/D/F, when bit0=1, + * master link B/D/F + */ + params.acConfig.ucLinkSel = 1; + + if (ENGINE_ID_DIGB == cntl->engine_id) + /* Bit3: Transmitter data source selection + * =0 DIGA is data source. + * =1 DIGB is data source. + * This bit is only useful when ucAction= ATOM_ENABLE + */ + params.acConfig.ucEncoderSel = 1; + + /* Bit[7:6]: Transmitter selection + * =0 UNIPHY_ENCODER: UNIPHYA/B + * =1 UNIPHY1_ENCODER: UNIPHYC/D + * =2 UNIPHY2_ENCODER: UNIPHYE/F + * =3 reserved + */ + params.acConfig.ucTransmitterSel = + (uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter)); + params.ucLaneNum = (uint8_t)(cntl->lanes_number); + params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id); + params.ucAction = (uint8_t)(cntl->action); + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result transmitter_control_v1_5( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + const struct command_table_helper *cmd = bp->cmd_helper; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params; + + memset(¶ms, 0, sizeof(params)); + params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter); + params.ucAction = (uint8_t)cntl->action; + params.ucLaneNum = (uint8_t)cntl->lanes_number; + params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id; + + params.ucDigMode = + cmd->signal_type_to_atom_dig_mode(cntl->signal); + params.asConfig.ucPhyClkSrcId = + cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id); + /* 00 - coherent mode */ + params.asConfig.ucCoherentMode = cntl->coherent; + params.asConfig.ucHPDSel = + cmd->hpd_sel_to_atom(cntl->hpd_sel); + params.ucDigEncoderSel = + cmd->dig_encoder_sel_to_atom(cntl->engine_id); + params.ucDPLaneSet = (uint8_t) cntl->lane_settings; + params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10)); + /* + * In SI/TN case, caller have to set usPixelClock as following: + * DP mode: usPixelClock = DP_LINK_CLOCK/10 + * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz) + * DVI single link mode: usPixelClock = pixel clock + * DVI dual link mode: usPixelClock = pixel clock + * HDMI mode: usPixelClock = pixel clock * deep_color_ratio + * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp) + * LVDS mode: usPixelClock = pixel clock + */ + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; +#ifdef LATEST_ATOM_BIOS_SUPPORT + const struct command_table_helper *cmd = bp->cmd_helper; + DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params; + + memset(¶ms, 0, sizeof(params)); + params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter); + params.ucAction = (uint8_t)cntl->action; + + if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) + params.ucDPLaneSet = (uint8_t)cntl->lane_settings; + else + params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal); + + params.ucLaneNum = (uint8_t)cntl->lanes_number; + params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel); + params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); + params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id; + params.ulSymClock = cntl->pixel_clock/10; + + /* + * In SI/TN case, caller have to set usPixelClock as following: + * DP mode: usPixelClock = DP_LINK_CLOCK/10 + * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz) + * DVI single link mode: usPixelClock = pixel clock + * DVI dual link mode: usPixelClock = pixel clock + * HDMI mode: usPixelClock = pixel clock * deep_color_ratio + * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp) + * LVDS mode: usPixelClock = pixel clock + */ + switch (cntl->signal) { + case SIGNAL_TYPE_HDMI_TYPE_A: + switch (cntl->color_depth) { + case COLOR_DEPTH_101010: + params.ulSymClock = + cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24); + break; + case COLOR_DEPTH_121212: + params.ulSymClock = + cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24); + break; + case COLOR_DEPTH_161616: + params.ulSymClock = + cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24); + break; + default: + break; + } + break; + default: + break; + } + + if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) + result = BP_RESULT_OK; +#endif + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SET PIXEL CLOCK + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result set_pixel_clock_v3( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); +static enum bp_result set_pixel_clock_v5( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); +static enum bp_result set_pixel_clock_v6( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + +static void init_set_pixel_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) { + case 3: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3; + break; + case 5: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5; + break; + case 6: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6; + break; + case 7: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; + break; + default: + bp->cmd_tbl.set_pixel_clock = NULL; + break; + } +} + +static enum bp_result set_pixel_clock_v3( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + PIXEL_CLOCK_PARAMETERS_V3 *params; + SET_PIXEL_CLOCK_PS_ALLOCATION allocation; + + memset(&allocation, 0, sizeof(allocation)); + + if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id) + allocation.sPCLKInput.ucPpll = ATOM_PPLL1; + else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id) + allocation.sPCLKInput.ucPpll = ATOM_PPLL2; + else + return BP_RESULT_BADINPUT; + + allocation.sPCLKInput.usRefDiv = + cpu_to_le16((uint16_t)bp_params->reference_divider); + allocation.sPCLKInput.usFbDiv = + cpu_to_le16((uint16_t)bp_params->feedback_divider); + allocation.sPCLKInput.ucFracFbDiv = + (uint8_t)bp_params->fractional_feedback_divider; + allocation.sPCLKInput.ucPostDiv = + (uint8_t)bp_params->pixel_clock_post_divider; + + /* We need to convert from KHz units into 10KHz units */ + allocation.sPCLKInput.usPixelClock = + cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10)); + + params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput; + params->ucTransmitterId = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + params->ucEncoderMode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false)); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK) + params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK; + + if (CONTROLLER_ID_D1 != bp_params->controller_id) + params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2; + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation)) + result = BP_RESULT_OK; + + return result; +} + +#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5 +/* video bios did not define this: */ +typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 { + PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput; + /* Caller doesn't need to init this portion */ + ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved; +} SET_PIXEL_CLOCK_PS_ALLOCATION_V5; +#endif + +#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6 +/* video bios did not define this: */ +typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 { + PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput; + /* Caller doesn't need to init this portion */ + ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved; +} SET_PIXEL_CLOCK_PS_ALLOCATION_V6; +#endif + +static enum bp_result set_pixel_clock_v5( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &controller_id)) { + clk.sPCLKInput.ucCRTC = controller_id; + clk.sPCLKInput.ucPpll = (uint8_t)pll_id; + clk.sPCLKInput.ucRefDiv = + (uint8_t)(bp_params->reference_divider); + clk.sPCLKInput.usFbDiv = + cpu_to_le16((uint16_t)(bp_params->feedback_divider)); + clk.sPCLKInput.ulFbDivDecFrac = + cpu_to_le32(bp_params->fractional_feedback_divider); + clk.sPCLKInput.ucPostDiv = + (uint8_t)(bp_params->pixel_clock_post_divider); + clk.sPCLKInput.ucTransmitterID = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + clk.sPCLKInput.ucEncoderMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.sPCLKInput.usPixelClock = + cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10)); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + clk.sPCLKInput.ucMiscInfo |= + PIXEL_CLOCK_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) + clk.sPCLKInput.ucMiscInfo |= + PIXEL_CLOCK_MISC_REF_DIV_SRC; + + /* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp + * =1:30bpp, =2:32bpp + * driver choose program it itself, i.e. here we program it + * to 888 by default. + */ + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) + result = BP_RESULT_OK; + } + + return result; +} + +static enum bp_result set_pixel_clock_v6( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &controller_id)) { + /* Note: VBIOS still wants to use ucCRTC name which is now + * 1 byte in ULONG + *typedef struct _CRTC_PIXEL_CLOCK_FREQ + *{ + * target the pixel clock to drive the CRTC timing. + * ULONG ulPixelClock:24; + * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to + * previous version. + * ATOM_CRTC1~6, indicate the CRTC controller to + * ULONG ucCRTC:8; + * drive the pixel clock. not used for DCPLL case. + *}CRTC_PIXEL_CLOCK_FREQ; + *union + *{ + * pixel clock and CRTC id frequency + * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; + * ULONG ulDispEngClkFreq; dispclk frequency + *}; + */ + clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id; + clk.sPCLKInput.ucPpll = (uint8_t) pll_id; + clk.sPCLKInput.ucRefDiv = + (uint8_t) bp_params->reference_divider; + clk.sPCLKInput.usFbDiv = + cpu_to_le16((uint16_t) bp_params->feedback_divider); + clk.sPCLKInput.ulFbDivDecFrac = + cpu_to_le32(bp_params->fractional_feedback_divider); + clk.sPCLKInput.ucPostDiv = + (uint8_t) bp_params->pixel_clock_post_divider; + clk.sPCLKInput.ucTransmitterID = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + clk.sPCLKInput.ucEncoderMode = + (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock = + cpu_to_le32(bp_params->target_pixel_clock / 10); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) { + clk.sPCLKInput.ucMiscInfo |= + PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL; + } + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) { + clk.sPCLKInput.ucMiscInfo |= + PIXEL_CLOCK_V6_MISC_REF_DIV_SRC; + } + + /* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: + * 24bpp =1:30bpp, =2:32bpp + * driver choose program it itself, i.e. here we pass required + * target rate that includes deep color. + */ + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) + result = BP_RESULT_OK; + } + + return result; +} + +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; +#ifdef LATEST_ATOM_BIOS_SUPPORT + PIXEL_CLOCK_PARAMETERS_V7 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) { + /* Note: VBIOS still wants to use ucCRTC name which is now + * 1 byte in ULONG + *typedef struct _CRTC_PIXEL_CLOCK_FREQ + *{ + * target the pixel clock to drive the CRTC timing. + * ULONG ulPixelClock:24; + * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to + * previous version. + * ATOM_CRTC1~6, indicate the CRTC controller to + * ULONG ucCRTC:8; + * drive the pixel clock. not used for DCPLL case. + *}CRTC_PIXEL_CLOCK_FREQ; + *union + *{ + * pixel clock and CRTC id frequency + * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; + * ULONG ulDispEngClkFreq; dispclk frequency + *}; + */ + clk.ucCRTC = controller_id; + clk.ucPpll = (uint8_t) pll_id; + clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id)); + clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10); + + clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC; + + if (bp_params->flags.PROGRAM_PHY_PLL_ONLY) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL; + + if (bp_params->flags.SUPPORT_YUV_420) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE; + + if (bp_params->flags.SET_XTALIN_REF_SRC) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN; + + if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK; + + if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) + clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN; + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) + result = BP_RESULT_OK; + } +#endif + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ENABLE PIXEL CLOCK SS + ** + ******************************************************************************** + *******************************************************************************/ +static enum bp_result enable_spread_spectrum_on_ppll_v1( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); +static enum bp_result enable_spread_spectrum_on_ppll_v2( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); +static enum bp_result enable_spread_spectrum_on_ppll_v3( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); + +static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) { + case 1: + bp->cmd_tbl.enable_spread_spectrum_on_ppll = + enable_spread_spectrum_on_ppll_v1; + break; + case 2: + bp->cmd_tbl.enable_spread_spectrum_on_ppll = + enable_spread_spectrum_on_ppll_v2; + break; + case 3: + bp->cmd_tbl.enable_spread_spectrum_on_ppll = + enable_spread_spectrum_on_ppll_v3; + break; + default: + bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL; + break; + } +} + +static enum bp_result enable_spread_spectrum_on_ppll_v1( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + ENABLE_SPREAD_SPECTRUM_ON_PPLL params; + + memset(¶ms, 0, sizeof(params)); + + if ((enable == true) && (bp_params->percentage > 0)) + params.ucEnable = ATOM_ENABLE; + else + params.ucEnable = ATOM_DISABLE; + + params.usSpreadSpectrumPercentage = + cpu_to_le16((uint16_t)bp_params->percentage); + params.ucSpreadSpectrumStep = + (uint8_t)bp_params->ver1.step; + params.ucSpreadSpectrumDelay = + (uint8_t)bp_params->ver1.delay; + /* convert back to unit of 10KHz */ + params.ucSpreadSpectrumRange = + (uint8_t)(bp_params->ver1.range / 10000); + + if (bp_params->flags.EXTERNAL_SS) + params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK; + + if (bp_params->flags.CENTER_SPREAD) + params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE; + + if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1) + params.ucPpll = ATOM_PPLL1; + else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2) + params.ucPpll = ATOM_PPLL2; + else + BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */ + + if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result enable_spread_spectrum_on_ppll_v2( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params; + + memset(¶ms, 0, sizeof(params)); + + if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1) + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL; + else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2) + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL; + else + BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */ + + if ((enable == true) && (bp_params->percentage > 0)) { + params.ucEnable = ATOM_ENABLE; + + params.usSpreadSpectrumPercentage = + cpu_to_le16((uint16_t)(bp_params->percentage)); + params.usSpreadSpectrumStep = + cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size)); + + if (bp_params->flags.EXTERNAL_SS) + params.ucSpreadSpectrumType |= + ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD; + + if (bp_params->flags.CENTER_SPREAD) + params.ucSpreadSpectrumType |= + ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD; + + /* Both amounts need to be left shifted first before bit + * comparison. Otherwise, the result will always be zero here + */ + params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)( + ((bp_params->ds.feedback_amount << + ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) | + ((bp_params->ds.nfrac_amount << + ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK))); + } else + params.ucEnable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result enable_spread_spectrum_on_ppll_v3( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params; + + memset(¶ms, 0, sizeof(params)); + + switch (bp_params->pll_id) { + case CLOCK_SOURCE_ID_PLL0: + /* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only, + * not for SI display clock. + */ + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL; + break; + case CLOCK_SOURCE_ID_PLL1: + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL; + break; + + case CLOCK_SOURCE_ID_PLL2: + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL; + break; + + case CLOCK_SOURCE_ID_DCPLL: + params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL; + break; + + default: + BREAK_TO_DEBUGGER(); + /* Unexpected PLL value!! */ + return result; + } + + if (enable == true) { + params.ucEnable = ATOM_ENABLE; + + params.usSpreadSpectrumAmountFrac = + cpu_to_le16((uint16_t)(bp_params->ds_frac_amount)); + params.usSpreadSpectrumStep = + cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size)); + + if (bp_params->flags.EXTERNAL_SS) + params.ucSpreadSpectrumType |= + ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD; + if (bp_params->flags.CENTER_SPREAD) + params.ucSpreadSpectrumType |= + ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD; + + /* Both amounts need to be left shifted first before bit + * comparison. Otherwise, the result will always be zero here + */ + params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)( + ((bp_params->ds.feedback_amount << + ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) | + ((bp_params->ds.nfrac_amount << + ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) & + ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK))); + } else + params.ucEnable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ADJUST DISPLAY PLL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result adjust_display_pll_v2( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params); +static enum bp_result adjust_display_pll_v3( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params); + +static void init_adjust_display_pll(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) { + case 2: + bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2; + break; + case 3: + bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3; + break; + default: + bp->cmd_tbl.adjust_display_pll = NULL; + break; + } +} + +static enum bp_result adjust_display_pll_v2( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 }; + + /* We need to convert from KHz units into 10KHz units and then convert + * output pixel clock back 10KHz-->KHz */ + uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10; + + params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in)); + params.ucTransmitterID = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + params.ucEncodeMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + return result; +} + +static enum bp_result adjust_display_pll_v3( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params; + uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10; + + memset(¶ms, 0, sizeof(params)); + + /* We need to convert from KHz units into 10KHz units and then convert + * output pixel clock back 10KHz-->KHz */ + params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in); + params.sInput.ucTransmitterID = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + params.sInput.ucEncodeMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + if (bp_params->ss_enable == true) + params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE; + + if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) + params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK; + + if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) { + /* Convert output pixel clock back 10KHz-->KHz: multiply + * original pixel clock in KHz by ratio + * [output pxlClk/input pxlClk] */ + uint64_t pixel_clk_10_khz_out = + (uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq); + uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock; + + if (pixel_clk_10_kHz_in != 0) { + bp_params->adjusted_pixel_clock = + div_u64(pixel_clk * pixel_clk_10_khz_out, + pixel_clk_10_kHz_in); + } else { + bp_params->adjusted_pixel_clock = 0; + BREAK_TO_DEBUGGER(); + } + + bp_params->reference_divider = params.sOutput.ucRefDiv; + bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv; + + result = BP_RESULT_OK; + } + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** DAC ENCODER CONTROL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result dac1_encoder_control_v1( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); +static enum bp_result dac2_encoder_control_v1( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + +static void init_dac_encoder_control(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) { + case 1: + bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1; + break; + default: + bp->cmd_tbl.dac1_encoder_control = NULL; + break; + } + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) { + case 1: + bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1; + break; + default: + bp->cmd_tbl.dac2_encoder_control = NULL; + break; + } +} + +static void dac_encoder_control_prepare_params( + DAC_ENCODER_CONTROL_PS_ALLOCATION *params, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard) +{ + params->ucDacStandard = dac_standard; + if (enable) + params->ucAction = ATOM_ENABLE; + else + params->ucAction = ATOM_DISABLE; + + /* We need to convert from KHz units into 10KHz units + * it looks as if the TvControl do not care about pixel clock + */ + params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10)); +} + +static enum bp_result dac1_encoder_control_v1( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard) +{ + enum bp_result result = BP_RESULT_FAILURE; + DAC_ENCODER_CONTROL_PS_ALLOCATION params; + + dac_encoder_control_prepare_params( + ¶ms, + enable, + pixel_clock, + dac_standard); + + if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result dac2_encoder_control_v1( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard) +{ + enum bp_result result = BP_RESULT_FAILURE; + DAC_ENCODER_CONTROL_PS_ALLOCATION params; + + dac_encoder_control_prepare_params( + ¶ms, + enable, + pixel_clock, + dac_standard); + + if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** DAC OUTPUT CONTROL + ** + ******************************************************************************** + *******************************************************************************/ +static enum bp_result dac1_output_control_v1( + struct bios_parser *bp, + bool enable); +static enum bp_result dac2_output_control_v1( + struct bios_parser *bp, + bool enable); + +static void init_dac_output_control(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) { + case 1: + bp->cmd_tbl.dac1_output_control = dac1_output_control_v1; + break; + default: + bp->cmd_tbl.dac1_output_control = NULL; + break; + } + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) { + case 1: + bp->cmd_tbl.dac2_output_control = dac2_output_control_v1; + break; + default: + bp->cmd_tbl.dac2_output_control = NULL; + break; + } +} + +static enum bp_result dac1_output_control_v1( + struct bios_parser *bp, bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params; + + if (enable) + params.ucAction = ATOM_ENABLE; + else + params.ucAction = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result dac2_output_control_v1( + struct bios_parser *bp, bool enable) +{ + enum bp_result result = BP_RESULT_FAILURE; + DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params; + + if (enable) + params.ucAction = ATOM_ENABLE; + else + params.ucAction = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** BLANK CRTC + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result blank_crtc_v1( + struct bios_parser *bp, + struct bp_blank_crtc_parameters *bp_params, + bool blank); + +static void init_blank_crtc(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(BlankCRTC)) { + case 1: + bp->cmd_tbl.blank_crtc = blank_crtc_v1; + break; + default: + bp->cmd_tbl.blank_crtc = NULL; + break; + } +} + +static enum bp_result blank_crtc_v1( + struct bios_parser *bp, + struct bp_blank_crtc_parameters *bp_params, + bool blank) +{ + enum bp_result result = BP_RESULT_FAILURE; + BLANK_CRTC_PARAMETERS params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, + &atom_controller_id)) { + params.ucCRTC = (uint8_t)atom_controller_id; + + if (blank) + params.ucBlanking = ATOM_BLANKING; + else + params.ucBlanking = ATOM_BLANKING_OFF; + params.usBlackColorRCr = + cpu_to_le16((uint16_t)bp_params->black_color_rcr); + params.usBlackColorGY = + cpu_to_le16((uint16_t)bp_params->black_color_gy); + params.usBlackColorBCb = + cpu_to_le16((uint16_t)bp_params->black_color_bcb); + + if (EXEC_BIOS_CMD_TABLE(BlankCRTC, params)) + result = BP_RESULT_OK; + } else + /* Not support more than two CRTC as current ASIC, update this + * if needed. + */ + result = BP_RESULT_BADINPUT; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SET CRTC TIMING + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); +static enum bp_result set_crtc_timing_v1( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + +static void init_set_crtc_timing(struct bios_parser *bp) +{ + uint32_t dtd_version = + BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming); + if (dtd_version > 2) + switch (dtd_version) { + case 3: + bp->cmd_tbl.set_crtc_timing = + set_crtc_using_dtd_timing_v3; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } + else + switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) { + case 1: + bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } +} + +static enum bp_result set_crtc_timing_v1( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.ucCRTC = atom_controller_id; + + params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total)); + params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable)); + params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start)); + params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width)); + params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total)); + params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable)); + params.usV_SyncStart = + cpu_to_le16((uint16_t)(bp_params->v_sync_start)); + params.usV_SyncWidth = + cpu_to_le16((uint16_t)(bp_params->v_sync_width)); + + /* VBIOS does not expect any value except zero into this call, for + * underscan use another entry ProgramOverscan call but when mode + * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok, + * but when same ,but 60 Hz there is corruption + * DAL1 does not allow the mode 1776x1000@60 + */ + params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right; + params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left; + params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom; + params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top; + + if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY); + + if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY); + + if (bp_params->flags.INTERLACE) { + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE); + + /* original DAL code has this condition to apply tis for + * non-TV/CV only due to complex MV testing for possible + * impact + * if (pACParameters->signal != SignalType_YPbPr && + * pACParameters->signal != SignalType_Composite && + * pACParameters->signal != SignalType_SVideo) + */ + /* HW will deduct 0.5 line from 2nd feild. + * i.e. for 1080i, it is 2 lines for 1st field, 2.5 + * lines for the 2nd feild. we need input as 5 instead + * of 4, but it is 4 either from Edid data + * (spec CEA 861) or CEA timing table. + */ + params.usV_SyncStart = + cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1)); + } + + if (bp_params->flags.HORZ_COUNT_BY_TWO) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE); + + if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.ucCRTC = atom_controller_id; + + /* bios usH_Size wants h addressable size */ + params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable); + /* bios usH_Blanking_Time wants borders included in blanking */ + params.usH_Blanking_Time = + cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable)); + /* bios usV_Size wants v addressable size */ + params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable); + /* bios usV_Blanking_Time wants borders included in blanking */ + params.usV_Blanking_Time = + cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable)); + /* bios usHSyncOffset is the offset from the end of h addressable, + * our horizontalSyncStart is the offset from the beginning + * of h addressable */ + params.usH_SyncOffset = + cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable)); + params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); + /* bios usHSyncOffset is the offset from the end of v addressable, + * our verticalSyncStart is the offset from the beginning of + * v addressable */ + params.usV_SyncOffset = + cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable)); + params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); + + /* we assume that overscan from original timing does not get bigger + * than 255 + * we will program all the borders in the Set CRTC Overscan call below + */ + + if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY); + + if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY); + + if (bp_params->flags.INTERLACE) { + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE); + + /* original DAL code has this condition to apply this + * for non-TV/CV only + * due to complex MV testing for possible impact + * if ( pACParameters->signal != SignalType_YPbPr && + * pACParameters->signal != SignalType_Composite && + * pACParameters->signal != SignalType_SVideo) + */ + { + /* HW will deduct 0.5 line from 2nd feild. + * i.e. for 1080i, it is 2 lines for 1st field, + * 2.5 lines for the 2nd feild. we need input as 5 + * instead of 4. + * but it is 4 either from Edid data (spec CEA 861) + * or CEA timing table. + */ + params.usV_SyncOffset = + cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1); + + } + } + + if (bp_params->flags.HORZ_COUNT_BY_TWO) + params.susModeMiscInfo.usAccess = + cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE); + + if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SET CRTC OVERSCAN + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result set_crtc_overscan_v1( + struct bios_parser *bp, + struct bp_hw_crtc_overscan_parameters *bp_params); + +static void init_set_crtc_overscan(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_OverScan)) { + case 1: + bp->cmd_tbl.set_crtc_overscan = set_crtc_overscan_v1; + break; + default: + bp->cmd_tbl.set_crtc_overscan = NULL; + break; + } +} + +static enum bp_result set_crtc_overscan_v1( + struct bios_parser *bp, + struct bp_hw_crtc_overscan_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SET_CRTC_OVERSCAN_PARAMETERS params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.ucCRTC = atom_controller_id; + else + return BP_RESULT_BADINPUT; + + params.usOverscanRight = + cpu_to_le16((uint16_t)bp_params->h_overscan_right); + params.usOverscanLeft = + cpu_to_le16((uint16_t)bp_params->h_overscan_left); + params.usOverscanBottom = + cpu_to_le16((uint16_t)bp_params->v_overscan_bottom); + params.usOverscanTop = + cpu_to_le16((uint16_t)bp_params->v_overscan_top); + + if (EXEC_BIOS_CMD_TABLE(SetCRTC_OverScan, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SELECT CRTC SOURCE + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result select_crtc_source_v2( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + +static void init_select_crtc_source(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) { + case 2: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v2; + break; + case 3: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; + break; + default: + bp->cmd_tbl.select_crtc_source = NULL; + break; + } +} + +static enum bp_result select_crtc_source_v2( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SELECT_CRTC_SOURCE_PARAMETERS_V2 params; + uint8_t atom_controller_id; + uint32_t atom_engine_id; + enum signal_type s = bp_params->signal; + + memset(¶ms, 0, sizeof(params)); + + /* set controller id */ + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.ucCRTC = atom_controller_id; + else + return BP_RESULT_FAILURE; + + /* set encoder id */ + if (bp->cmd_helper->engine_bp_to_atom( + bp_params->engine_id, &atom_engine_id)) + params.ucEncoderID = (uint8_t)atom_engine_id; + else + return BP_RESULT_FAILURE; + + if (SIGNAL_TYPE_EDP == s || + (SIGNAL_TYPE_DISPLAY_PORT == s && + SIGNAL_TYPE_LVDS == bp_params->sink_signal)) + s = SIGNAL_TYPE_LVDS; + + params.ucEncodeMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + s, bp_params->enable_dp_audio); + + if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + bool result = BP_RESULT_FAILURE; + SELECT_CRTC_SOURCE_PARAMETERS_V3 params; + uint8_t atom_controller_id; + uint32_t atom_engine_id; + enum signal_type s = bp_params->signal; + + memset(¶ms, 0, sizeof(params)); + + if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, + &atom_controller_id)) + params.ucCRTC = atom_controller_id; + else + return result; + + if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, + &atom_engine_id)) + params.ucEncoderID = (uint8_t)atom_engine_id; + else + return result; + + if (SIGNAL_TYPE_EDP == s || + (SIGNAL_TYPE_DISPLAY_PORT == s && + SIGNAL_TYPE_LVDS == bp_params->sink_signal)) + s = SIGNAL_TYPE_LVDS; + + params.ucEncodeMode = + bp->cmd_helper->encoder_mode_bp_to_atom( + s, bp_params->enable_dp_audio); + /* Needed for VBIOS Random Spatial Dithering feature */ + params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth); + + if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ENABLE CRTC + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + +static void init_enable_crtc(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) { + case 1: + bp->cmd_tbl.enable_crtc = enable_crtc_v1; + break; + default: + bp->cmd_tbl.enable_crtc = NULL; + break; + } +} + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable) +{ + bool result = BP_RESULT_FAILURE; + ENABLE_CRTC_PARAMETERS params = {0}; + uint8_t id; + + if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) + params.ucCRTC = id; + else + return BP_RESULT_BADINPUT; + + if (enable) + params.ucEnable = ATOM_ENABLE; + else + params.ucEnable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ENABLE CRTC MEM REQ + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result enable_crtc_mem_req_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + +static void init_enable_crtc_mem_req(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) { + case 1: + bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1; + break; + default: + bp->cmd_tbl.enable_crtc_mem_req = NULL; + break; + } +} + +static enum bp_result enable_crtc_mem_req_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable) +{ + bool result = BP_RESULT_BADINPUT; + ENABLE_CRTC_PARAMETERS params = {0}; + uint8_t id; + + if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) { + params.ucCRTC = id; + + if (enable) + params.ucEnable = ATOM_ENABLE; + else + params.ucEnable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params)) + result = BP_RESULT_OK; + else + result = BP_RESULT_FAILURE; + } + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** DISPLAY PLL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result program_clock_v5( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); +static enum bp_result program_clock_v6( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + +static void init_program_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) { + case 5: + bp->cmd_tbl.program_clock = program_clock_v5; + break; + case 6: + bp->cmd_tbl.program_clock = program_clock_v6; + break; + default: + bp->cmd_tbl.program_clock = NULL; + break; + } +} + +static enum bp_result program_clock_v5( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params; + uint32_t atom_pll_id; + + memset(¶ms, 0, sizeof(params)); + if (!bp->cmd_helper->clock_source_id_to_atom( + bp_params->pll_id, &atom_pll_id)) { + BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */ + return BP_RESULT_BADINPUT; + } + + /* We need to convert from KHz units into 10KHz units */ + params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id; + params.sPCLKInput.usPixelClock = + cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10)); + params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID; + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) + params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result program_clock_v6( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params; + uint32_t atom_pll_id; + + memset(¶ms, 0, sizeof(params)); + + if (!bp->cmd_helper->clock_source_id_to_atom( + bp_params->pll_id, &atom_pll_id)) { + BREAK_TO_DEBUGGER(); /*Invalid Input!!*/ + return BP_RESULT_BADINPUT; + } + + /* We need to convert from KHz units into 10KHz units */ + params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id; + params.sPCLKInput.ulDispEngClkFreq = + cpu_to_le32(bp_params->target_pixel_clock / 10); + + if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) + params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC; + + if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) { + /* True display clock is returned by VBIOS if DFS bypass + * is enabled. */ + bp_params->dfs_bypass_display_clock = + (uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10); + result = BP_RESULT_OK; + } + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** COMPUTE MEMORY ENGINE PLL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result compute_memore_engine_pll_v4( + struct bios_parser *bp, + struct bp_display_clock_parameters *bp_params); + +static void init_compute_memore_engine_pll(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(ComputeMemoryEnginePLL)) { + case 4: + bp->cmd_tbl.compute_memore_engine_pll = + compute_memore_engine_pll_v4; + break; + default: + bp->cmd_tbl.compute_memore_engine_pll = NULL; + break; + } +} + +static enum bp_result compute_memore_engine_pll_v4( + struct bios_parser *bp, + struct bp_display_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 params; + + memset(¶ms, 0, sizeof(params)); + + params.ulClock = cpu_to_le32(bp_params->target_display_clock / 10); + + /* Initialize this to the target clock in case this call fails */ + bp_params->actual_display_clock = bp_params->target_display_clock; + + if (EXEC_BIOS_CMD_TABLE(ComputeMemoryEnginePLL, params)) { + /* Convert from 10KHz units back to KHz */ + bp_params->actual_display_clock = + le32_to_cpu(params.ulClock) * 10; + bp_params->actual_post_divider_id = params.ucPostDiv; + result = BP_RESULT_OK; + } + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** EXTERNAL ENCODER CONTROL + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + +static void init_external_encoder_control( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) { + case 3: + bp->cmd_tbl.external_encoder_control = + external_encoder_control_v3; + break; + default: + bp->cmd_tbl.external_encoder_control = NULL; + break; + } +} + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + + /* we need use _PS_Alloc struct */ + EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params; + EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params; + struct graphics_object_id encoder; + bool is_input_signal_dp = false; + + memset(¶ms, 0, sizeof(params)); + + cntl_params = ¶ms.sExtEncoder; + + encoder = cntl->encoder_id; + + /* check if encoder supports external encoder control table */ + switch (dal_graphics_object_id_get_encoder_id(encoder)) { + case ENCODER_ID_EXTERNAL_NUTMEG: + case ENCODER_ID_EXTERNAL_TRAVIS: + is_input_signal_dp = true; + break; + + default: + BREAK_TO_DEBUGGER(); + return BP_RESULT_BADINPUT; + } + + /* Fill information based on the action + * + * Bit[6:4]: indicate external encoder, applied to all functions. + * =0: external encoder1, mapped to external encoder enum id1 + * =1: external encoder2, mapped to external encoder enum id2 + * + * enum ObjectEnumId + * { + * EnumId_Unknown = 0, + * EnumId_1, + * EnumId_2, + * }; + */ + cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4); + + switch (cntl->action) { + case EXTERNAL_ENCODER_CONTROL_INIT: + /* output display connector type. Only valid in encoder + * initialization */ + cntl_params->usConnectorId = + cpu_to_le16((uint16_t)cntl->connector_obj_id.id); + break; + case EXTERNAL_ENCODER_CONTROL_SETUP: + /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in + * 10KHz + * output display device pixel clock frequency in unit of 10KHz. + * Only valid in setup and enableoutput + */ + cntl_params->usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + /* Indicate display output signal type drive by external + * encoder, only valid in setup and enableoutput */ + cntl_params->ucEncoderMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, false); + + if (is_input_signal_dp) { + /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz, + * only valid in encoder setup with DP mode. */ + if (LINK_RATE_HIGH == cntl->link_rate) + cntl_params->ucConfig |= 1; + /* output color depth Indicate encoder data bpc format + * in DP mode, only valid in encoder setup in DP mode. + */ + cntl_params->ucBitPerColor = + (uint8_t)(cntl->color_depth); + } + /* Indicate how many lanes used by external encoder, only valid + * in encoder setup and enableoutput. */ + cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number); + break; + case EXTERNAL_ENCODER_CONTROL_ENABLE: + cntl_params->usPixelClock = + cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); + cntl_params->ucEncoderMode = + (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, false); + cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number; + break; + default: + break; + } + + cntl_params->ucAction = (uint8_t)cntl->action; + + if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** ENABLE DISPLAY POWER GATING + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + +static void init_enable_disp_power_gating( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) { + case 1: + bp->cmd_tbl.enable_disp_power_gating = + enable_disp_power_gating_v2_1; + break; + default: + bp->cmd_tbl.enable_disp_power_gating = NULL; + break; + } +} + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action) +{ + enum bp_result result = BP_RESULT_FAILURE; + + ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0}; + uint8_t atom_crtc_id; + + if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) + params.ucDispPipeId = atom_crtc_id; + else + return BP_RESULT_BADINPUT; + + params.ucEnable = + bp->cmd_helper->disp_power_gating_action_to_atom(action); + + if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** + ** SET DCE CLOCK + ** + ******************************************************************************** + *******************************************************************************/ +#ifdef LATEST_ATOM_BIOS_SUPPORT +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); +#endif + +static void init_set_dce_clock(struct bios_parser *bp) +{ +#ifdef LATEST_ATOM_BIOS_SUPPORT + switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) { + case 1: + bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; + break; + default: + bp->cmd_tbl.set_dce_clock = NULL; + break; + } +#endif +} + +#ifdef LATEST_ATOM_BIOS_SUPPORT +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params; + uint32_t atom_pll_id; + uint32_t atom_clock_type; + const struct command_table_helper *cmd = bp->cmd_helper; + + memset(¶ms, 0, sizeof(params)); + + if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) || + !cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type)) + return BP_RESULT_BADINPUT; + + params.asParam.ucDCEClkSrc = atom_pll_id; + params.asParam.ucDCEClkType = atom_clock_type; + + if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { + if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) + params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK; + + if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK) + params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE; + + if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK) + params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN; + + if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK) + params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA; + } + else + /* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */ + /* We need to convert from KHz units into 10KHz units */ + params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10); + + if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) { + /* Convert from 10KHz units back to KHz */ + bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10; + result = BP_RESULT_OK; + } + + return result; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h new file mode 100644 index 000000000000..e1cd21b6e968 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h @@ -0,0 +1,112 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_H__ +#define __DAL_COMMAND_TABLE_H__ + +struct bios_parser; +struct bp_encoder_control; + +struct cmd_tbl { + enum bp_result (*dig_encoder_control)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*encoder_control_dig1)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*encoder_control_dig2)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*transmitter_control)( + struct bios_parser *bp, + struct bp_transmitter_control *control); + enum bp_result (*set_pixel_clock)( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*enable_spread_spectrum_on_ppll)( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); + enum bp_result (*adjust_display_pll)( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params); + enum bp_result (*dac1_encoder_control)( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + enum bp_result (*dac2_encoder_control)( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + enum bp_result (*dac1_output_control)( + struct bios_parser *bp, + bool enable); + enum bp_result (*dac2_output_control)( + struct bios_parser *bp, + bool enable); + enum bp_result (*blank_crtc)( + struct bios_parser *bp, + struct bp_blank_crtc_parameters *bp_params, + bool blank); + enum bp_result (*set_crtc_timing)( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + enum bp_result (*set_crtc_overscan)( + struct bios_parser *bp, + struct bp_hw_crtc_overscan_parameters *bp_params); + enum bp_result (*select_crtc_source)( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + enum bp_result (*enable_crtc)( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + enum bp_result (*enable_crtc_mem_req)( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + enum bp_result (*program_clock)( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*compute_memore_engine_pll)( + struct bios_parser *bp, + struct bp_display_clock_parameters *bp_params); + enum bp_result (*external_encoder_control)( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + enum bp_result (*enable_disp_power_gating)( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + enum bp_result (*set_dce_clock)( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); +}; + +void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c new file mode 100644 index 000000000000..40d9a9921c45 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c @@ -0,0 +1,288 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" + +#include "command_table_helper.h" + +bool dal_bios_parser_init_cmd_tbl_helper( + const struct command_table_helper **h, + enum dce_version dce) +{ + switch (dce) { + case DCE_VERSION_8_0: + *h = dal_cmd_tbl_helper_dce80_get_table(); + return true; + + case DCE_VERSION_10_0: + *h = dal_cmd_tbl_helper_dce110_get_table(); + return true; + + case DCE_VERSION_11_0: + *h = dal_cmd_tbl_helper_dce110_get_table(); + return true; + + case DCE_VERSION_11_2: + *h = dal_cmd_tbl_helper_dce112_get_table(); + return true; + + default: + /* Unsupported DCE */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +/* real implementations */ + +bool dal_cmd_table_helper_controller_id_to_atom( + enum controller_id id, + uint8_t *atom_id) +{ + if (atom_id == NULL) { + BREAK_TO_DEBUGGER(); + return false; + } + + switch (id) { + case CONTROLLER_ID_D0: + *atom_id = ATOM_CRTC1; + return true; + case CONTROLLER_ID_D1: + *atom_id = ATOM_CRTC2; + return true; + case CONTROLLER_ID_D2: + *atom_id = ATOM_CRTC3; + return true; + case CONTROLLER_ID_D3: + *atom_id = ATOM_CRTC4; + return true; + case CONTROLLER_ID_D4: + *atom_id = ATOM_CRTC5; + return true; + case CONTROLLER_ID_D5: + *atom_id = ATOM_CRTC6; + return true; + case CONTROLLER_ID_UNDERLAY0: + *atom_id = ATOM_UNDERLAY_PIPE0; + return true; + case CONTROLLER_ID_UNDEFINED: + *atom_id = ATOM_CRTC_INVALID; + return true; + default: + /* Wrong controller id */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +/** +* translate_transmitter_bp_to_atom +* +* @brief +* Translate the Transmitter to the corresponding ATOM BIOS value +* +* @param +* input transmitter +* output digitalTransmitter +* // =00: Digital Transmitter1 ( UNIPHY linkAB ) +* // =01: Digital Transmitter2 ( UNIPHY linkCD ) +* // =02: Digital Transmitter3 ( UNIPHY linkEF ) +*/ +uint8_t dal_cmd_table_helper_transmitter_bp_to_atom( + enum transmitter t) +{ + switch (t) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_TRAVIS_LCD: + return 0; + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + return 1; + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + return 2; + default: + /* Invalid Transmitter Type! */ + BREAK_TO_DEBUGGER(); + return 0; + } +} + +uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom( + enum signal_type s, + bool enable_dp_audio) +{ + switch (s) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return ATOM_ENCODER_MODE_DVI; + case SIGNAL_TYPE_HDMI_TYPE_A: + return ATOM_ENCODER_MODE_HDMI; + case SIGNAL_TYPE_LVDS: + return ATOM_ENCODER_MODE_LVDS; + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_VIRTUAL: + if (enable_dp_audio) + return ATOM_ENCODER_MODE_DP_AUDIO; + else + return ATOM_ENCODER_MODE_DP; + case SIGNAL_TYPE_RGB: + return ATOM_ENCODER_MODE_CRT; + default: + return ATOM_ENCODER_MODE_CRT; + } +} + +void dal_cmd_table_helper_assign_control_parameter( + const struct command_table_helper *h, + struct bp_encoder_control *control, + DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param) +{ + /* there are three transmitter blocks, each one has two links 4-lanes + * each, A+B, C+D, E+F, Uniphy A, C and E are enumerated as link 0 in + * each transmitter block B, D and F as link 1, third transmitter block + * has non splitable links (UniphyE and UniphyF can not be configured + * separately to drive two different streams) + */ + if ((control->transmitter == TRANSMITTER_UNIPHY_B) || + (control->transmitter == TRANSMITTER_UNIPHY_D) || + (control->transmitter == TRANSMITTER_UNIPHY_F)) { + /* Bit2: Link Select + * =0: PHY linkA/C/E + * =1: PHY linkB/D/F + */ + ctrl_param->acConfig.ucLinkSel = 1; + } + + /* Bit[4:3]: Transmitter Selection + * =00: Digital Transmitter1 ( UNIPHY linkAB ) + * =01: Digital Transmitter2 ( UNIPHY linkCD ) + * =02: Digital Transmitter3 ( UNIPHY linkEF ) + * =03: Reserved + */ + ctrl_param->acConfig.ucTransmitterSel = + (uint8_t)(h->transmitter_bp_to_atom(control->transmitter)); + + /* We need to convert from KHz units into 10KHz units */ + ctrl_param->ucAction = h->encoder_action_to_atom(control->action); + ctrl_param->usPixelClock = cpu_to_le16((uint16_t)(control->pixel_clock / 10)); + ctrl_param->ucEncoderMode = + (uint8_t)(h->encoder_mode_bp_to_atom( + control->signal, control->enable_dp_audio)); + ctrl_param->ucLaneNum = (uint8_t)(control->lanes_number); +} + +bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src( + enum clock_source_id id, + uint32_t *ref_clk_src_id) +{ + if (ref_clk_src_id == NULL) { + BREAK_TO_DEBUGGER(); + return false; + } + + switch (id) { + case CLOCK_SOURCE_ID_PLL1: + *ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL; + return true; + case CLOCK_SOURCE_ID_PLL2: + *ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL; + return true; + case CLOCK_SOURCE_ID_DCPLL: + *ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL; + return true; + case CLOCK_SOURCE_ID_EXTERNAL: + *ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK; + return true; + case CLOCK_SOURCE_ID_UNDEFINED: + *ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID; + return true; + default: + /* Unsupported clock source id */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +uint8_t dal_cmd_table_helper_encoder_id_to_atom( + enum encoder_id id) +{ + switch (id) { + case ENCODER_ID_INTERNAL_LVDS: + return ENCODER_OBJECT_ID_INTERNAL_LVDS; + case ENCODER_ID_INTERNAL_TMDS1: + return ENCODER_OBJECT_ID_INTERNAL_TMDS1; + case ENCODER_ID_INTERNAL_TMDS2: + return ENCODER_OBJECT_ID_INTERNAL_TMDS2; + case ENCODER_ID_INTERNAL_DAC1: + return ENCODER_OBJECT_ID_INTERNAL_DAC1; + case ENCODER_ID_INTERNAL_DAC2: + return ENCODER_OBJECT_ID_INTERNAL_DAC2; + case ENCODER_ID_INTERNAL_LVTM1: + return ENCODER_OBJECT_ID_INTERNAL_LVTM1; + case ENCODER_ID_INTERNAL_HDMI: + return ENCODER_OBJECT_ID_HDMI_INTERNAL; + case ENCODER_ID_EXTERNAL_TRAVIS: + return ENCODER_OBJECT_ID_TRAVIS; + case ENCODER_ID_EXTERNAL_NUTMEG: + return ENCODER_OBJECT_ID_NUTMEG; + case ENCODER_ID_INTERNAL_KLDSCP_TMDS1: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; + case ENCODER_ID_INTERNAL_KLDSCP_DAC1: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; + case ENCODER_ID_INTERNAL_KLDSCP_DAC2: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; + case ENCODER_ID_EXTERNAL_MVPU_FPGA: + return ENCODER_OBJECT_ID_MVPU_FPGA; + case ENCODER_ID_INTERNAL_DDI: + return ENCODER_OBJECT_ID_INTERNAL_DDI; + case ENCODER_ID_INTERNAL_UNIPHY: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY; + case ENCODER_ID_INTERNAL_KLDSCP_LVTMA: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA; + case ENCODER_ID_INTERNAL_UNIPHY1: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1; + case ENCODER_ID_INTERNAL_UNIPHY2: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2; + case ENCODER_ID_INTERNAL_UNIPHY3: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3; + case ENCODER_ID_INTERNAL_WIRELESS: + return ENCODER_OBJECT_ID_INTERNAL_VCE; + case ENCODER_ID_UNKNOWN: + return ENCODER_OBJECT_ID_NONE; + default: + /* Invalid encoder id */ + BREAK_TO_DEBUGGER(); + return ENCODER_OBJECT_ID_NONE; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h new file mode 100644 index 000000000000..1fab634b66be --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h @@ -0,0 +1,90 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_H__ +#define __DAL_COMMAND_TABLE_HELPER_H__ + +#include "dce80/command_table_helper_dce80.h" +#include "dce110/command_table_helper_dce110.h" +#include "dce112/command_table_helper_dce112.h" + +struct command_table_helper { + bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id); + uint8_t (*encoder_action_to_atom)( + enum bp_encoder_control_action action); + uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s, + bool enable_dp_audio); + bool (*engine_bp_to_atom)(enum engine_id engine_id, + uint32_t *atom_engine_id); + void (*assign_control_parameter)( + const struct command_table_helper *h, + struct bp_encoder_control *control, + DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param); + bool (*clock_source_id_to_atom)(enum clock_source_id id, + uint32_t *atom_pll_id); + bool (*clock_source_id_to_ref_clk_src)( + enum clock_source_id id, + uint32_t *ref_clk_src_id); + uint8_t (*transmitter_bp_to_atom)(enum transmitter t); + uint8_t (*encoder_id_to_atom)(enum encoder_id id); + uint8_t (*clock_source_id_to_atom_phy_clk_src_id)( + enum clock_source_id id); + uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s); + uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id); + uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id); + uint8_t (*phy_id_to_atom)(enum transmitter t); + uint8_t (*disp_power_gating_action_to_atom)( + enum bp_pipe_control_action action); + bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id, + uint32_t *atom_clock_type); + uint8_t (*transmitter_color_depth_to_atom)(enum transmitter_color_depth id); +}; + +bool dal_bios_parser_init_cmd_tbl_helper(const struct command_table_helper **h, + enum dce_version dce); + +bool dal_cmd_table_helper_controller_id_to_atom( + enum controller_id id, + uint8_t *atom_id); + +uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom( + enum signal_type s, + bool enable_dp_audio); + +void dal_cmd_table_helper_assign_control_parameter( + const struct command_table_helper *h, + struct bp_encoder_control *control, +DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param); + +bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src( + enum clock_source_id id, + uint32_t *ref_clk_src_id); + +uint8_t dal_cmd_table_helper_transmitter_bp_to_atom( + enum transmitter t); + +uint8_t dal_cmd_table_helper_encoder_id_to_atom( + enum encoder_id id); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c new file mode 100644 index 000000000000..dff82dd11721 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -0,0 +1,364 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" + +#include "../command_table_helper.h" + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + break; + case SIGNAL_TYPE_LVDS: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel >> 4; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL; + break; + case ENGINE_ID_UNKNOWN: + /* No DIG_FRONT is associated to DIG_BACKEND */ + atom_dig_encoder_sel = 0; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + } + + return atom_dig_encoder_sel; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_PLL1: + *atom_pll_id = ATOM_PPLL1; + break; + case CLOCK_SOURCE_ID_PLL2: + *atom_pll_id = ATOM_PPLL2; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_EXT_PLL1; + break; + case CLOCK_SOURCE_ID_VCE: + /* for VCE encoding, + * we need to pass in ATOM_PPLL_INVALID + */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DP_DTO: + /* When programming DP DTO PLL ID should be invalid */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + /* Should not happen */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +/* function table */ +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .assign_control_parameter = NULL, + .clock_source_id_to_ref_clk_src = NULL, + .transmitter_bp_to_atom = NULL, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, + .encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom, +}; + +/* + * dal_cmd_tbl_helper_dce110_get_table + * + * @brief + * Initialize command table helper functions + * + * @param + * const struct command_table_helper **h - [out] struct of functions + * + */ +const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table() +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h new file mode 100644 index 000000000000..eb60c2ead992 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_DCE110_H__ +#define __DAL_COMMAND_TABLE_HELPER_DCE110_H__ + +struct command_table_helper; + +/* Initialize command table helper functions */ +const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void); + +#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c new file mode 100644 index 000000000000..8b72aa588b86 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -0,0 +1,418 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" + +#include "../command_table_helper.h" + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGG_SEL; + break; + case ENGINE_ID_UNKNOWN: + /* No DIG_FRONT is associated to DIG_BACKEND */ + atom_dig_encoder_sel = 0; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; + break; + } + + return atom_dig_encoder_sel; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_COMBO_PHY_PLL0: + *atom_pll_id = ATOM_COMBOPHY_PLL0; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL1: + *atom_pll_id = ATOM_COMBOPHY_PLL1; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL2: + *atom_pll_id = ATOM_COMBOPHY_PLL2; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL3: + *atom_pll_id = ATOM_COMBOPHY_PLL3; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL4: + *atom_pll_id = ATOM_COMBOPHY_PLL4; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL5: + *atom_pll_id = ATOM_COMBOPHY_PLL5; + break; + case CLOCK_SOURCE_COMBO_DISPLAY_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_GCK_DFS; + break; + case CLOCK_SOURCE_ID_VCE: + *atom_pll_id = ATOM_DP_DTO; + break; + case CLOCK_SOURCE_ID_DP_DTO: + *atom_pll_id = ATOM_DP_DTO; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + /* Should not happen */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_STREAM_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +static bool dc_clock_type_to_atom( + enum bp_dce_clock_type id, + uint32_t *atom_clock_type) +{ + bool retCode = true; + + if (atom_clock_type != NULL) { + switch (id) { + case DCECLOCK_TYPE_DISPLAY_CLOCK: + *atom_clock_type = DCE_CLOCK_TYPE_DISPCLK; + break; + + case DCECLOCK_TYPE_DPREFCLK: + *atom_clock_type = DCE_CLOCK_TYPE_DPREFCLK; + break; + + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + } + + return retCode; +} + +static uint8_t transmitter_color_depth_to_atom(enum transmitter_color_depth id) +{ + uint8_t atomColorDepth = 0; + + switch (id) { + case TRANSMITTER_COLOR_DEPTH_24: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS; + break; + case TRANSMITTER_COLOR_DEPTH_30: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4; + break; + case TRANSMITTER_COLOR_DEPTH_36: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2; + break; + case TRANSMITTER_COLOR_DEPTH_48: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atomColorDepth; +} + +/* function table */ +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .assign_control_parameter = NULL, + .clock_source_id_to_ref_clk_src = NULL, + .transmitter_bp_to_atom = NULL, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, + .encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom, + .dc_clock_type_to_atom = dc_clock_type_to_atom, + .transmitter_color_depth_to_atom = transmitter_color_depth_to_atom, +}; + +/* + * dal_cmd_tbl_helper_dce110_get_table + * + * @brief + * Initialize command table helper functions + * + * @param + * const struct command_table_helper **h - [out] struct of functions + * + */ +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table() +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h new file mode 100644 index 000000000000..dc3660951355 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_DCE112_H__ +#define __DAL_COMMAND_TABLE_HELPER_DCE112_H__ + +struct command_table_helper; + +/* Initialize command table helper functions */ +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table(void); + +#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c new file mode 100644 index 000000000000..295e16ef3f73 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c @@ -0,0 +1,354 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/grph_object_id.h" +#include "include/grph_object_defs.h" +#include "include/bios_parser_types.h" + +#include "../command_table_helper.h" + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_PLL1: + *atom_pll_id = ATOM_PPLL1; + break; + case CLOCK_SOURCE_ID_PLL2: + *atom_pll_id = ATOM_PPLL2; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_EXT_PLL1; + break; + case CLOCK_SOURCE_ID_VCE: + /* for VCE encoding, + * we need to pass in ATOM_PPLL_INVALID + */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DP_DTO: + /* When programming DP DTO PLL ID should be invalid */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + BREAK_TO_DEBUGGER(); /* check when this will happen! */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + break; + case SIGNAL_TYPE_LVDS: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel >> 4; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + } + + return atom_dig_encoder_sel; +} + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .assign_control_parameter = + dal_cmd_table_helper_assign_control_parameter, + .clock_source_id_to_ref_clk_src = + dal_cmd_table_helper_clock_source_id_to_ref_clk_src, + .transmitter_bp_to_atom = dal_cmd_table_helper_transmitter_bp_to_atom, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, + .encoder_mode_bp_to_atom = + dal_cmd_table_helper_encoder_mode_bp_to_atom, +}; + +const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table() +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h new file mode 100644 index 000000000000..e675c359e306 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_DCE80_H__ +#define __DAL_COMMAND_TABLE_HELPER_DCE80_H__ + +struct command_table_helper; + +const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table(void); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile new file mode 100644 index 000000000000..4001933e7808 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the 'calcs' sub-component of DAL. +# It calculates Bandwidth and Watermarks values for HW programming +# + +BW_CALCS = bandwidth_calcs.o bw_fixed.o gamma_calcs.o + +AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) + +AMD_DISPLAY_FILES += $(AMD_DAL_BW_CALCS) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c new file mode 100644 index 000000000000..0b2bb3992f1a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -0,0 +1,3108 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "bandwidth_calcs.h" +#include "dc.h" +#include "core_types.h" + +/******************************************************************************* + * Private Functions + ******************************************************************************/ + +static void calculate_bandwidth( + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + struct bw_calcs_data *data) + +{ + const int32_t pixels_per_chunk = 512; + const int32_t high = 2; + const int32_t mid = 1; + const int32_t low = 0; + const uint32_t s_low = 0; + const uint32_t s_mid1 = 1; + const uint32_t s_mid2 = 2; + const uint32_t s_mid3 = 3; + const uint32_t s_mid4 = 4; + const uint32_t s_mid5 = 5; + const uint32_t s_mid6 = 6; + const uint32_t s_high = 7; + const uint32_t bus_efficiency = 1; + const uint32_t dmif_chunk_buff_margin = 1; + + uint32_t max_chunks_fbc_mode; + int32_t num_cursor_lines; + + int32_t i, j, k; + struct bw_fixed yclk[3]; + struct bw_fixed sclk[8]; + bool d0_underlay_enable; + bool d1_underlay_enable; + bool fbc_enabled; + bool lpt_enabled; + enum bw_defines sclk_message; + enum bw_defines yclk_message; + enum bw_defines v_filter_init_mode[maximum_number_of_surfaces]; + enum bw_defines tiling_mode[maximum_number_of_surfaces]; + enum bw_defines surface_type[maximum_number_of_surfaces]; + enum bw_defines voltage; + enum bw_defines pipe_check; + enum bw_defines hsr_check; + enum bw_defines vsr_check; + enum bw_defines lb_size_check; + enum bw_defines fbc_check; + enum bw_defines rotation_check; + enum bw_defines mode_check; + enum bw_defines nbp_state_change_enable_blank; + /*initialize variables*/ + int32_t number_of_displays_enabled = 0; + int32_t number_of_displays_enabled_with_margin = 0; + int32_t number_of_aligned_displays_with_no_margin = 0; + + yclk[low] = vbios->low_yclk; + yclk[mid] = vbios->mid_yclk; + yclk[high] = vbios->high_yclk; + sclk[s_low] = vbios->low_sclk; + sclk[s_mid1] = vbios->mid1_sclk; + sclk[s_mid2] = vbios->mid2_sclk; + sclk[s_mid3] = vbios->mid3_sclk; + sclk[s_mid4] = vbios->mid4_sclk; + sclk[s_mid5] = vbios->mid5_sclk; + sclk[s_mid6] = vbios->mid6_sclk; + sclk[s_high] = vbios->high_sclk; + /*''''''''''''''''''*/ + /* surface assignment:*/ + /* 0: d0 underlay or underlay luma*/ + /* 1: d0 underlay chroma*/ + /* 2: d1 underlay or underlay luma*/ + /* 3: d1 underlay chroma*/ + /* 4: d0 graphics*/ + /* 5: d1 graphics*/ + /* 6: d2 graphics*/ + /* 7: d3 graphics, same mode as d2*/ + /* 8: d4 graphics, same mode as d2*/ + /* 9: d5 graphics, same mode as d2*/ + /* ...*/ + /* maximum_number_of_surfaces-2: d1 display_write_back420 luma*/ + /* maximum_number_of_surfaces-1: d1 display_write_back420 chroma*/ + /* underlay luma and chroma surface parameters from spreadsheet*/ + + + + + if (data->d0_underlay_mode == bw_def_none) { d0_underlay_enable = 0; } + else { + d0_underlay_enable = 1; + } + if (data->d1_underlay_mode == bw_def_none) { d1_underlay_enable = 0; } + else { + d1_underlay_enable = 1; + } + data->number_of_underlay_surfaces = d0_underlay_enable + d1_underlay_enable; + switch (data->underlay_surface_type) { + case bw_def_420: + surface_type[0] = bw_def_underlay420_luma; + surface_type[2] = bw_def_underlay420_luma; + data->bytes_per_pixel[0] = 1; + data->bytes_per_pixel[2] = 1; + surface_type[1] = bw_def_underlay420_chroma; + surface_type[3] = bw_def_underlay420_chroma; + data->bytes_per_pixel[1] = 2; + data->bytes_per_pixel[3] = 2; + data->lb_size_per_component[0] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[1] = dceip->underlay420_chroma_lb_size_per_component; + data->lb_size_per_component[2] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[3] = dceip->underlay420_chroma_lb_size_per_component; + break; + case bw_def_422: + surface_type[0] = bw_def_underlay422; + surface_type[2] = bw_def_underlay422; + data->bytes_per_pixel[0] = 2; + data->bytes_per_pixel[2] = 2; + data->lb_size_per_component[0] = dceip->underlay422_lb_size_per_component; + data->lb_size_per_component[2] = dceip->underlay422_lb_size_per_component; + break; + default: + surface_type[0] = bw_def_underlay444; + surface_type[2] = bw_def_underlay444; + data->bytes_per_pixel[0] = 4; + data->bytes_per_pixel[2] = 4; + data->lb_size_per_component[0] = dceip->lb_size_per_component444; + data->lb_size_per_component[2] = dceip->lb_size_per_component444; + break; + } + if (d0_underlay_enable) { + switch (data->underlay_surface_type) { + case bw_def_420: + data->enable[0] = 1; + data->enable[1] = 1; + break; + default: + data->enable[0] = 1; + data->enable[1] = 0; + break; + } + } + else { + data->enable[0] = 0; + data->enable[1] = 0; + } + if (d1_underlay_enable) { + switch (data->underlay_surface_type) { + case bw_def_420: + data->enable[2] = 1; + data->enable[3] = 1; + break; + default: + data->enable[2] = 1; + data->enable[3] = 0; + break; + } + } + else { + data->enable[2] = 0; + data->enable[3] = 0; + } + data->use_alpha[0] = 0; + data->use_alpha[1] = 0; + data->use_alpha[2] = 0; + data->use_alpha[3] = 0; + data->scatter_gather_enable_for_pipe[0] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[1] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[2] = vbios->scatter_gather_enable; + data->scatter_gather_enable_for_pipe[3] = vbios->scatter_gather_enable; + /*underlay0 same and graphics display pipe0*/ + data->interlace_mode[0] = data->interlace_mode[4]; + data->interlace_mode[1] = data->interlace_mode[4]; + /*underlay1 same and graphics display pipe1*/ + data->interlace_mode[2] = data->interlace_mode[5]; + data->interlace_mode[3] = data->interlace_mode[5]; + /*underlay0 same and graphics display pipe0*/ + data->h_total[0] = data->h_total[4]; + data->v_total[0] = data->v_total[4]; + data->h_total[1] = data->h_total[4]; + data->v_total[1] = data->v_total[4]; + /*underlay1 same and graphics display pipe1*/ + data->h_total[2] = data->h_total[5]; + data->v_total[2] = data->v_total[5]; + data->h_total[3] = data->h_total[5]; + data->v_total[3] = data->v_total[5]; + /*underlay0 same and graphics display pipe0*/ + data->pixel_rate[0] = data->pixel_rate[4]; + data->pixel_rate[1] = data->pixel_rate[4]; + /*underlay1 same and graphics display pipe1*/ + data->pixel_rate[2] = data->pixel_rate[5]; + data->pixel_rate[3] = data->pixel_rate[5]; + if ((data->underlay_tiling_mode == bw_def_array_linear_general || data->underlay_tiling_mode == bw_def_array_linear_aligned)) { + tiling_mode[0] = bw_def_linear; + tiling_mode[1] = bw_def_linear; + tiling_mode[2] = bw_def_linear; + tiling_mode[3] = bw_def_linear; + } + else { + tiling_mode[0] = bw_def_landscape; + tiling_mode[1] = bw_def_landscape; + tiling_mode[2] = bw_def_landscape; + tiling_mode[3] = bw_def_landscape; + } + data->lb_bpc[0] = data->underlay_lb_bpc; + data->lb_bpc[1] = data->underlay_lb_bpc; + data->lb_bpc[2] = data->underlay_lb_bpc; + data->lb_bpc[3] = data->underlay_lb_bpc; + data->compression_rate[0] = bw_int_to_fixed(1); + data->compression_rate[1] = bw_int_to_fixed(1); + data->compression_rate[2] = bw_int_to_fixed(1); + data->compression_rate[3] = bw_int_to_fixed(1); + data->access_one_channel_only[0] = 0; + data->access_one_channel_only[1] = 0; + data->access_one_channel_only[2] = 0; + data->access_one_channel_only[3] = 0; + data->cursor_width_pixels[0] = bw_int_to_fixed(0); + data->cursor_width_pixels[1] = bw_int_to_fixed(0); + data->cursor_width_pixels[2] = bw_int_to_fixed(0); + data->cursor_width_pixels[3] = bw_int_to_fixed(0); + /* graphics surface parameters from spreadsheet*/ + fbc_enabled = 0; + lpt_enabled = 0; + for (i = 4; i <= maximum_number_of_surfaces - 3; i++) { + if (i < data->number_of_displays + 4) { + if (i == 4 && data->d0_underlay_mode == bw_def_underlay_only) { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + else if (i == 4 && data->d0_underlay_mode == bw_def_blend) { + data->enable[i] = 1; + data->use_alpha[i] = 1; + } + else if (i == 4) { + data->enable[i] = 1; + data->use_alpha[i] = 0; + } + else if (i == 5 && data->d1_underlay_mode == bw_def_underlay_only) { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + else if (i == 5 && data->d1_underlay_mode == bw_def_blend) { + data->enable[i] = 1; + data->use_alpha[i] = 1; + } + else { + data->enable[i] = 1; + data->use_alpha[i] = 0; + } + } + else { + data->enable[i] = 0; + data->use_alpha[i] = 0; + } + data->scatter_gather_enable_for_pipe[i] = vbios->scatter_gather_enable; + surface_type[i] = bw_def_graphics; + data->lb_size_per_component[i] = dceip->lb_size_per_component444; + if (data->graphics_tiling_mode == bw_def_array_linear_general || data->graphics_tiling_mode == bw_def_array_linear_aligned) { + tiling_mode[i] = bw_def_linear; + } + else { + tiling_mode[i] = bw_def_tiled; + } + data->lb_bpc[i] = data->graphics_lb_bpc; + if ((data->fbc_en[i] == 1 && (dceip->argb_compression_support || data->d0_underlay_mode != bw_def_blended))) { + data->compression_rate[i] = bw_int_to_fixed(vbios->average_compression_rate); + data->access_one_channel_only[i] = data->lpt_en[i]; + } + else { + data->compression_rate[i] = bw_int_to_fixed(1); + data->access_one_channel_only[i] = 0; + } + if (data->fbc_en[i] == 1) { + fbc_enabled = 1; + if (data->lpt_en[i] == 1) { + lpt_enabled = 1; + } + } + data->cursor_width_pixels[i] = bw_int_to_fixed(vbios->cursor_width); + } + /* display_write_back420*/ + data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] = 0; + data->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] = 0; + if (data->d1_display_write_back_dwb_enable == 1) { + data->enable[maximum_number_of_surfaces - 2] = 1; + data->enable[maximum_number_of_surfaces - 1] = 1; + } + else { + data->enable[maximum_number_of_surfaces - 2] = 0; + data->enable[maximum_number_of_surfaces - 1] = 0; + } + surface_type[maximum_number_of_surfaces - 2] = bw_def_display_write_back420_luma; + surface_type[maximum_number_of_surfaces - 1] = bw_def_display_write_back420_chroma; + data->lb_size_per_component[maximum_number_of_surfaces - 2] = dceip->underlay420_luma_lb_size_per_component; + data->lb_size_per_component[maximum_number_of_surfaces - 1] = dceip->underlay420_chroma_lb_size_per_component; + data->bytes_per_pixel[maximum_number_of_surfaces - 2] = 1; + data->bytes_per_pixel[maximum_number_of_surfaces - 1] = 2; + data->interlace_mode[maximum_number_of_surfaces - 2] = data->interlace_mode[5]; + data->interlace_mode[maximum_number_of_surfaces - 1] = data->interlace_mode[5]; + data->h_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->h_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->v_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->v_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->rotation_angle[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0); + data->rotation_angle[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0); + tiling_mode[maximum_number_of_surfaces - 2] = bw_def_linear; + tiling_mode[maximum_number_of_surfaces - 1] = bw_def_linear; + data->lb_bpc[maximum_number_of_surfaces - 2] = 8; + data->lb_bpc[maximum_number_of_surfaces - 1] = 8; + data->compression_rate[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->compression_rate[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->access_one_channel_only[maximum_number_of_surfaces - 2] = 0; + data->access_one_channel_only[maximum_number_of_surfaces - 1] = 0; + /*assume display pipe1 has dwb enabled*/ + data->h_total[maximum_number_of_surfaces - 2] = data->h_total[5]; + data->h_total[maximum_number_of_surfaces - 1] = data->h_total[5]; + data->v_total[maximum_number_of_surfaces - 2] = data->v_total[5]; + data->v_total[maximum_number_of_surfaces - 1] = data->v_total[5]; + data->pixel_rate[maximum_number_of_surfaces - 2] = data->pixel_rate[5]; + data->pixel_rate[maximum_number_of_surfaces - 1] = data->pixel_rate[5]; + data->src_width[maximum_number_of_surfaces - 2] = data->src_width[5]; + data->src_width[maximum_number_of_surfaces - 1] = data->src_width[5]; + data->src_height[maximum_number_of_surfaces - 2] = data->src_height[5]; + data->src_height[maximum_number_of_surfaces - 1] = data->src_height[5]; + data->pitch_in_pixels[maximum_number_of_surfaces - 2] = data->src_width[5]; + data->pitch_in_pixels[maximum_number_of_surfaces - 1] = data->src_width[5]; + data->h_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->h_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->v_scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1); + data->v_scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1); + data->stereo_mode[maximum_number_of_surfaces - 2] = bw_def_mono; + data->stereo_mode[maximum_number_of_surfaces - 1] = bw_def_mono; + data->cursor_width_pixels[maximum_number_of_surfaces - 2] = bw_int_to_fixed(0); + data->cursor_width_pixels[maximum_number_of_surfaces - 1] = bw_int_to_fixed(0); + data->use_alpha[maximum_number_of_surfaces - 2] = 0; + data->use_alpha[maximum_number_of_surfaces - 1] = 0; + /*mode check calculations:*/ + /* mode within dce ip capabilities*/ + /* fbc*/ + /* hsr*/ + /* vsr*/ + /* lb size*/ + /*effective scaling source and ratios:*/ + /*for graphics, non-stereo, non-interlace surfaces when the size of the source and destination are the same, only one tap is used*/ + /*420 chroma has half the width, height, horizontal and vertical scaling ratios than luma*/ + /*rotating a graphic or underlay surface swaps the width, height, horizontal and vertical scaling ratios*/ + /*in top-bottom stereo mode there is 2:1 vertical downscaling for each eye*/ + /*in side-by-side stereo mode there is 2:1 horizontal downscaling for each eye*/ + /*in interlace mode there is 2:1 vertical downscaling for each field*/ + /*in panning or bezel adjustment mode the source width has an extra 128 pixels*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_equ(data->h_scale_ratio[i], bw_int_to_fixed(1)) && bw_equ(data->v_scale_ratio[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics && data->stereo_mode[i] == bw_def_mono && data->interlace_mode[i] == 0) { + data->h_taps[i] = bw_int_to_fixed(1); + data->v_taps[i] = bw_int_to_fixed(1); + } + if (surface_type[i] == bw_def_display_write_back420_chroma || surface_type[i] == bw_def_underlay420_chroma) { + data->pitch_in_pixels_after_surface_type[i] = bw_div(data->pitch_in_pixels[i], bw_int_to_fixed(2)); + data->src_width_after_surface_type = bw_div(data->src_width[i], bw_int_to_fixed(2)); + data->src_height_after_surface_type = bw_div(data->src_height[i], bw_int_to_fixed(2)); + data->hsr_after_surface_type = bw_div(data->h_scale_ratio[i], bw_int_to_fixed(2)); + data->vsr_after_surface_type = bw_div(data->v_scale_ratio[i], bw_int_to_fixed(2)); + } + else { + data->pitch_in_pixels_after_surface_type[i] = data->pitch_in_pixels[i]; + data->src_width_after_surface_type = data->src_width[i]; + data->src_height_after_surface_type = data->src_height[i]; + data->hsr_after_surface_type = data->h_scale_ratio[i]; + data->vsr_after_surface_type = data->v_scale_ratio[i]; + } + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->src_width_after_rotation = data->src_height_after_surface_type; + data->src_height_after_rotation = data->src_width_after_surface_type; + data->hsr_after_rotation = data->vsr_after_surface_type; + data->vsr_after_rotation = data->hsr_after_surface_type; + } + else { + data->src_width_after_rotation = data->src_width_after_surface_type; + data->src_height_after_rotation = data->src_height_after_surface_type; + data->hsr_after_rotation = data->hsr_after_surface_type; + data->vsr_after_rotation = data->vsr_after_surface_type; + } + switch (data->stereo_mode[i]) { + case bw_def_top_bottom: + data->source_width_pixels[i] = data->src_width_after_rotation; + data->source_height_pixels = bw_mul(bw_int_to_fixed(2), data->src_height_after_rotation); + data->hsr_after_stereo = data->hsr_after_rotation; + data->vsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->vsr_after_rotation); + break; + case bw_def_side_by_side: + data->source_width_pixels[i] = bw_mul(bw_int_to_fixed(2), data->src_width_after_rotation); + data->source_height_pixels = data->src_height_after_rotation; + data->hsr_after_stereo = bw_mul(bw_int_to_fixed(1), data->hsr_after_rotation); + data->vsr_after_stereo = data->vsr_after_rotation; + break; + default: + data->source_width_pixels[i] = data->src_width_after_rotation; + data->source_height_pixels = data->src_height_after_rotation; + data->hsr_after_stereo = data->hsr_after_rotation; + data->vsr_after_stereo = data->vsr_after_rotation; + break; + } + data->hsr[i] = data->hsr_after_stereo; + if (data->interlace_mode[i]) { + data->vsr[i] = bw_mul(data->vsr_after_stereo, bw_int_to_fixed(2)); + } + else { + data->vsr[i] = data->vsr_after_stereo; + } + if (data->panning_and_bezel_adjustment != bw_def_none) { + data->source_width_rounded_up_to_chunks[i] = bw_add(bw_floor2(bw_sub(data->source_width_pixels[i], bw_int_to_fixed(1)), bw_int_to_fixed(128)), bw_int_to_fixed(256)); + } + else { + data->source_width_rounded_up_to_chunks[i] = bw_ceil2(data->source_width_pixels[i], bw_int_to_fixed(128)); + } + data->source_height_rounded_up_to_chunks[i] = data->source_height_pixels; + } + } + /*mode support checks:*/ + /*the number of graphics and underlay pipes is limited by the ip support*/ + /*maximum horizontal and vertical scale ratio is 4, and should not exceed the number of taps*/ + /*for downscaling with the pre-downscaler, the horizontal scale ratio must be more than the ceiling of one quarter of the number of taps*/ + /*the pre-downscaler reduces the line buffer source by the horizontal scale ratio*/ + /*the number of lines in the line buffer has to exceed the number of vertical taps*/ + /*the size of the line in the line buffer is the product of the source width and the bits per component, rounded up to a multiple of 48*/ + /*the size of the line in the line buffer in the case of 10 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/ + /*the size of the line in the line buffer in the case of 8 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/ + /*frame buffer compression is not supported with stereo mode, rotation, or non- 888 formats*/ + /*rotation is not supported with linear of stereo modes*/ + if (dceip->number_of_graphics_pipes >= data->number_of_displays && dceip->number_of_underlay_pipes >= data->number_of_underlay_surfaces && !(dceip->display_write_back_supported == 0 && data->d1_display_write_back_dwb_enable == 1)) { + pipe_check = bw_def_ok; + } + else { + pipe_check = bw_def_notok; + } + hsr_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_neq(data->hsr[i], bw_int_to_fixed(1))) { + if (bw_mtn(data->hsr[i], bw_int_to_fixed(4))) { + hsr_check = bw_def_hsr_mtn_4; + } + else { + if (bw_mtn(data->hsr[i], data->h_taps[i])) { + hsr_check = bw_def_hsr_mtn_h_taps; + } + else { + if (dceip->pre_downscaler_enabled == 1 && bw_mtn(data->hsr[i], bw_int_to_fixed(1)) && bw_leq(data->hsr[i], bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)))) { + hsr_check = bw_def_ceiling__h_taps_div_4___meq_hsr; + } + } + } + } + } + } + vsr_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_neq(data->vsr[i], bw_int_to_fixed(1))) { + if (bw_mtn(data->vsr[i], bw_int_to_fixed(4))) { + vsr_check = bw_def_vsr_mtn_4; + } + else { + if (bw_mtn(data->vsr[i], data->v_taps[i])) { + vsr_check = bw_def_vsr_mtn_v_taps; + } + } + } + } + } + lb_size_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1)))) { + data->source_width_in_lb = bw_div(data->source_width_pixels[i], data->hsr[i]); + } + else { + data->source_width_in_lb = data->source_width_pixels[i]; + } + switch (data->lb_bpc[i]) { + case 8: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); + break; + case 10: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(300234375, 10000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); + break; + default: + data->lb_line_pitch = bw_ceil2(bw_mul(bw_int_to_fixed(data->lb_bpc[i]), data->source_width_in_lb), bw_int_to_fixed(48)); + break; + } + data->lb_partitions[i] = bw_floor2(bw_div(data->lb_size_per_component[i], data->lb_line_pitch), bw_int_to_fixed(1)); + /*clamp the partitions to the maxium number supported by the lb*/ + if ((surface_type[i] != bw_def_graphics || dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) { + data->lb_partitions_max[i] = bw_int_to_fixed(10); + } + else { + data->lb_partitions_max[i] = bw_int_to_fixed(7); + } + data->lb_partitions[i] = bw_min2(data->lb_partitions_max[i], data->lb_partitions[i]); + if (bw_mtn(bw_add(data->v_taps[i], bw_int_to_fixed(1)), data->lb_partitions[i])) { + lb_size_check = bw_def_notok; + } + } + } + fbc_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->fbc_en[i] == 1 && (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)) || data->stereo_mode[i] != bw_def_mono || data->bytes_per_pixel[i] != 4)) { + fbc_check = bw_def_invalid_rotation_or_bpp_or_stereo; + } + } + rotation_check = bw_def_ok; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) && (tiling_mode[i] == bw_def_linear || data->stereo_mode[i] != bw_def_mono)) { + rotation_check = bw_def_invalid_linear_or_stereo_mode; + } + } + } + if (pipe_check == bw_def_ok && hsr_check == bw_def_ok && vsr_check == bw_def_ok && lb_size_check == bw_def_ok && fbc_check == bw_def_ok && rotation_check == bw_def_ok) { + mode_check = bw_def_ok; + } + else { + mode_check = bw_def_notok; + } + /*number of memory channels for write-back client*/ + data->number_of_dram_wrchannels = vbios->number_of_dram_channels; + data->number_of_dram_channels = vbios->number_of_dram_channels; + /*modify number of memory channels if lpt mode is enabled*/ + /* low power tiling mode register*/ + /* 0 = use channel 0*/ + /* 1 = use channel 0 and 1*/ + /* 2 = use channel 0,1,2,3*/ + if ((fbc_enabled == 1 && lpt_enabled == 1)) { + data->dram_efficiency = bw_int_to_fixed(1); + if (dceip->low_power_tiling_mode == 0) { + data->number_of_dram_channels = 1; + } + else if (dceip->low_power_tiling_mode == 1) { + data->number_of_dram_channels = 2; + } + else if (dceip->low_power_tiling_mode == 2) { + data->number_of_dram_channels = 4; + } + else { + data->number_of_dram_channels = 1; + } + } + else { + data->dram_efficiency = bw_frc_to_fixed(8, 10); + } + /*memory request size and latency hiding:*/ + /*request size is normally 64 byte, 2-line interleaved, with full latency hiding*/ + /*the display write-back requests are single line*/ + /*for tiled graphics surfaces, or undelay surfaces with width higher than the maximum size for full efficiency, request size is 32 byte in 8 and 16 bpp or if the rotation is orthogonal to the tiling grain. only half is useful of the bytes in the request size in 8 bpp or in 32 bpp if the rotation is orthogonal to the tiling grain.*/ + /*for undelay surfaces with width lower than the maximum size for full efficiency, requests are 4-line interleaved in 16bpp if the rotation is parallel to the tiling grain, and 8-line interleaved with 4-line latency hiding in 8bpp or if the rotation is orthogonal to the tiling grain.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270)))) { + if ((i < 4)) { + /*underlay portrait tiling mode is not supported*/ + data->orthogonal_rotation[i] = 1; + } + else { + /*graphics portrait tiling mode*/ + if ((data->graphics_micro_tile_mode == bw_def_rotated_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + } + else { + if ((i < 4)) { + /*underlay landscape tiling mode is only supported*/ + if ((data->underlay_micro_tile_mode == bw_def_display_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + else { + /*graphics landscape tiling mode*/ + if ((data->graphics_micro_tile_mode == bw_def_display_micro_tiling)) { + data->orthogonal_rotation[i] = 0; + } + else { + data->orthogonal_rotation[i] = 1; + } + } + } + if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(90)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(270))) { + data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_height_efficient_for_tiling; + } + else { + data->underlay_maximum_source_efficient_for_tiling = dceip->underlay_maximum_width_efficient_for_tiling; + } + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(1); + data->latency_hiding_lines[i] = bw_int_to_fixed(1); + } + else if (tiling_mode[i] == bw_def_linear) { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + } + else { + if (surface_type[i] == bw_def_graphics || (bw_mtn(data->source_width_rounded_up_to_chunks[i], bw_ceil2(data->underlay_maximum_source_efficient_for_tiling, bw_int_to_fixed(256))))) { + switch (data->bytes_per_pixel[i]) { + case 8: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + if (data->orthogonal_rotation[i]) { + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(32); + } + else { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + } + break; + case 4: + if (data->orthogonal_rotation[i]) { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(16); + } + else { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + } + break; + case 2: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(32); + break; + default: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + data->bytes_per_request[i] = bw_int_to_fixed(32); + data->useful_bytes_per_request[i] = bw_int_to_fixed(16); + break; + } + } + else { + data->bytes_per_request[i] = bw_int_to_fixed(64); + data->useful_bytes_per_request[i] = bw_int_to_fixed(64); + if (data->orthogonal_rotation[i]) { + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + } + else { + switch (data->bytes_per_pixel[i]) { + case 4: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(2); + data->latency_hiding_lines[i] = bw_int_to_fixed(2); + break; + case 2: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(4); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + break; + default: + data->lines_interleaved_in_mem_access[i] = bw_int_to_fixed(8); + data->latency_hiding_lines[i] = bw_int_to_fixed(4); + break; + } + } + } + } + } + } + /*requested peak bandwidth:*/ + /*the peak request-per-second bandwidth is the product of the maximum source lines in per line out in the beginning*/ + /*and in the middle of the frame, the ratio of the source width to the line time, the ratio of line interleaving*/ + /*in memory to lines of latency hiding, and the ratio of bytes per pixel to useful bytes per request.*/ + /**/ + /*if the dmif data buffer size holds more than vta_ps worth of source lines, then only vsr is used.*/ + /*the peak bandwidth is the peak request-per-second bandwidth times the request size.*/ + /**/ + /*the line buffer lines in per line out in the beginning of the frame is the vertical filter initialization value*/ + /*rounded up to even and divided by the line times for initialization, which is normally three.*/ + /*the line buffer lines in per line out in the middle of the frame is at least one, or the vertical scale ratio,*/ + /*rounded up to line pairs if not doing line buffer prefetching.*/ + /**/ + /*the non-prefetching rounding up of the vertical scale ratio can also be done up to 1 (for a 0,2 pattern), 4/3 (for a 0,2,2 pattern),*/ + /*6/4 (for a 0,2,2,2 pattern), or 3 (for a 2,4 pattern).*/ + /**/ + /*the scaler vertical filter initialization value is calculated by the hardware as the floor of the average of the*/ + /*vertical scale ratio and the number of vertical taps increased by one. add one more for possible odd line*/ + /*panning/bezel adjustment mode.*/ + /**/ + /*for the bottom interlace field an extra 50% of the vertical scale ratio is considered for this calculation.*/ + /*in top-bottom stereo mode software has to set the filter initialization value manually and explicitly limit it to 4.*/ + /*furthermore, there is only one line time for initialization.*/ + /**/ + /*line buffer prefetching is done when the number of lines in the line buffer exceeds the number of taps plus*/ + /*the ceiling of the vertical scale ratio.*/ + /**/ + /*multi-line buffer prefetching is only done in the graphics pipe when the scaler is disabled or when upscaling and the vsr <= 0.8.'*/ + /**/ + /*the horizontal blank and chunk granularity factor is indirectly used indicate the interval of time required to transfer the source pixels.*/ + /*the denominator of this term represents the total number of destination output pixels required for the input source pixels.*/ + /*it applies when the lines in per line out is not 2 or 4. it does not apply when there is a line buffer between the scl and blnd.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->v_filter_init[i] = bw_floor2(bw_div((bw_add(bw_add(bw_add(bw_int_to_fixed(1), data->v_taps[i]), data->vsr[i]), bw_mul(bw_mul(bw_int_to_fixed(data->interlace_mode[i]), bw_frc_to_fixed(5, 10)), data->vsr[i]))), bw_int_to_fixed(2)), bw_int_to_fixed(1)); + if (data->panning_and_bezel_adjustment == bw_def_any_lines) { + data->v_filter_init[i] = bw_add(data->v_filter_init[i], bw_int_to_fixed(1)); + } + if (data->stereo_mode[i] == bw_def_top_bottom) { + v_filter_init_mode[i] = bw_def_manual; + data->v_filter_init[i] = bw_min2(data->v_filter_init[i], bw_int_to_fixed(4)); + } + else { + v_filter_init_mode[i] = bw_def_auto; + } + if (data->stereo_mode[i] == bw_def_top_bottom) { + data->num_lines_at_frame_start = bw_int_to_fixed(1); + } + else { + data->num_lines_at_frame_start = bw_int_to_fixed(3); + } + if ((bw_mtn(data->vsr[i], bw_int_to_fixed(1)) && surface_type[i] == bw_def_graphics) || data->panning_and_bezel_adjustment == bw_def_any_lines) { + data->line_buffer_prefetch[i] = 0; + } + else if ((((dceip->underlay_downscale_prefetch_enabled == 1 && surface_type[i] != bw_def_graphics) || surface_type[i] == bw_def_graphics) && (bw_mtn(data->lb_partitions[i], bw_add(data->v_taps[i], bw_ceil2(data->vsr[i], bw_int_to_fixed(1))))))) { + data->line_buffer_prefetch[i] = 1; + } + else { + data->line_buffer_prefetch[i] = 0; + } + data->lb_lines_in_per_line_out_in_beginning_of_frame[i] = bw_div(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->num_lines_at_frame_start); + if (data->line_buffer_prefetch[i] == 1) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_max2(bw_int_to_fixed(1), data->vsr[i]); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(1))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(1); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(4 / 3))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(4), bw_int_to_fixed(3)); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(6 / 4))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(6), bw_int_to_fixed(4)); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(2))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(2); + } + else if (bw_leq(data->vsr[i], bw_int_to_fixed(3))) { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(3); + } + else { + data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(4); + } + if (data->line_buffer_prefetch[i] == 1 || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(2)) || bw_equ(data->lb_lines_in_per_line_out_in_middle_of_frame[i], bw_int_to_fixed(4))) { + data->horizontal_blank_and_chunk_granularity_factor[i] = bw_int_to_fixed(1); + } + else { + data->horizontal_blank_and_chunk_granularity_factor[i] = bw_div(data->h_total[i], (bw_div((bw_add(data->h_total[i], bw_div((bw_sub(data->source_width_pixels[i], bw_int_to_fixed(dceip->chunk_width))), data->hsr[i]))), bw_int_to_fixed(2)))); + } + data->request_bandwidth[i] = bw_div(bw_mul(bw_div(bw_mul(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], data->lb_lines_in_per_line_out_in_middle_of_frame[i]), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), bw_int_to_fixed(data->bytes_per_pixel[i])), data->useful_bytes_per_request[i]), data->lines_interleaved_in_mem_access[i]), data->latency_hiding_lines[i]); + data->display_bandwidth[i] = bw_mul(data->request_bandwidth[i], data->bytes_per_request[i]); + } + } + /*outstanding chunk request limit*/ + /*if underlay buffer sharing is enabled, the data buffer size for underlay in 422 or 444 is the sum of the luma and chroma data buffer sizes.*/ + /*underlay buffer sharing mode is only permitted in orthogonal rotation modes.*/ + /**/ + /*if there is only one display enabled, the dmif data buffer size for the graphics surface is increased by concatenating the adjacent buffers.*/ + /**/ + /*the memory chunk size in bytes is 1024 for the writeback, and 256 times the memory line interleaving and the bytes per pixel for graphics*/ + /*and underlay.*/ + /**/ + /*the pipe chunk size uses 2 for line interleaving, except for the write back, in which case it is 1.*/ + /*graphics and underlay data buffer size is adjusted (limited) using the outstanding chunk request limit if there is more than one*/ + /*display enabled or if the dmif request buffer is not large enough for the total data buffer size.*/ + /*the outstanding chunk request limit is the ceiling of the adjusted data buffer size divided by the chunk size in bytes*/ + /*the adjusted data buffer size is the product of the display bandwidth and the minimum effective data buffer size in terms of time,*/ + /*rounded up to the chunk size in bytes, but should not exceed the original data buffer size*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->dmif_pipe_en_fbc_chunk_tracker + 3 == i && fbc_enabled == 0 && tiling_mode[i] != bw_def_linear)) { + data->max_chunks_non_fbc_mode[i] = 128 - dmif_chunk_buff_margin; + } + else { + data->max_chunks_non_fbc_mode[i] = 16 - dmif_chunk_buff_margin; + } + } + if (data->fbc_en[i] == 1) { + max_chunks_fbc_mode = 128 - dmif_chunk_buff_margin; + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + switch (surface_type[i]) { + case bw_def_display_write_back420_luma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_luma_mcifwr_buffer_size); + break; + case bw_def_display_write_back420_chroma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->display_write_back420_chroma_mcifwr_buffer_size); + break; + case bw_def_underlay420_luma: + data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size); + break; + case bw_def_underlay420_chroma: + data->data_buffer_size[i] = bw_div(bw_int_to_fixed(dceip->underlay_chroma_dmif_size), bw_int_to_fixed(2)); + break; + case bw_def_underlay422:case bw_def_underlay444: + if (data->orthogonal_rotation[i] == 0) { + data->data_buffer_size[i] = bw_int_to_fixed(dceip->underlay_luma_dmif_size); + } + else { + data->data_buffer_size[i] = bw_add(bw_int_to_fixed(dceip->underlay_luma_dmif_size), bw_int_to_fixed(dceip->underlay_chroma_dmif_size)); + } + break; + default: + if (data->fbc_en[i] == 1) { + /*data_buffer_size(i) = max_dmif_buffer_allocated * graphics_dmif_size*/ + if (data->number_of_displays == 1) { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size))); + } + else { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(max_chunks_fbc_mode), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_int_to_fixed(dceip->graphics_dmif_size)); + } + } + else { + /*the effective dmif buffer size in non-fbc mode is limited by the 16 entry chunk tracker*/ + if (data->number_of_displays == 1) { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_mul(bw_int_to_fixed(dceip->max_dmif_buffer_allocated), bw_int_to_fixed(dceip->graphics_dmif_size))); + } + else { + data->data_buffer_size[i] = bw_min2(bw_mul(bw_mul(bw_int_to_fixed(data->max_chunks_non_fbc_mode[i]), bw_int_to_fixed(pixels_per_chunk)), bw_int_to_fixed(data->bytes_per_pixel[i])), bw_int_to_fixed(dceip->graphics_dmif_size)); + } + } + break; + } + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->memory_chunk_size_in_bytes[i] = bw_int_to_fixed(1024); + data->pipe_chunk_size_in_bytes[i] = bw_int_to_fixed(1024); + } + else { + data->memory_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), data->lines_interleaved_in_mem_access[i]), bw_int_to_fixed(data->bytes_per_pixel[i])); + data->pipe_chunk_size_in_bytes[i] = bw_mul(bw_mul(bw_int_to_fixed(dceip->chunk_width), bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + } + } + data->min_dmif_size_in_time = bw_int_to_fixed(9999); + data->min_mcifwr_size_in_time = bw_int_to_fixed(9999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_dmif_size_in_time)) { + data->min_dmif_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]); + } + } + else { + if (bw_ltn(bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]), data->min_mcifwr_size_in_time)) { + data->min_mcifwr_size_in_time = bw_div(bw_div(bw_mul(data->data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]), data->display_bandwidth[i]); + } + } + } + } + data->total_requests_for_dmif_size = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_requests_for_dmif_size = bw_add(data->total_requests_for_dmif_size, bw_div(data->data_buffer_size[i], data->useful_bytes_per_request[i])); + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma && dceip->limit_excessive_outstanding_dmif_requests && (data->number_of_displays > 1 || bw_mtn(data->total_requests_for_dmif_size, dceip->dmif_request_buffer_size))) { + data->adjusted_data_buffer_size[i] = bw_min2(data->data_buffer_size[i], bw_ceil2(bw_mul(data->min_dmif_size_in_time, data->display_bandwidth[i]), data->memory_chunk_size_in_bytes[i])); + } + else { + data->adjusted_data_buffer_size[i] = data->data_buffer_size[i]; + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((data->number_of_displays == 1 && data->number_of_underlay_surfaces == 0)) { + /*set maximum chunk limit if only one graphic pipe is enabled*/ + data->outstanding_chunk_request_limit[i] = bw_int_to_fixed(127); + } + else { + data->outstanding_chunk_request_limit[i] = bw_ceil2(bw_div(data->adjusted_data_buffer_size[i], data->pipe_chunk_size_in_bytes[i]), bw_int_to_fixed(1)); + /*clamp maximum chunk limit in the graphic display pipe*/ + if ((i >= 4)) { + data->outstanding_chunk_request_limit[i] = bw_max2(bw_int_to_fixed(127), data->outstanding_chunk_request_limit[i]); + } + } + } + } + /*outstanding pte request limit*/ + /*in tiling mode with no rotation the sg pte requests are 8 useful pt_es, the sg row height is the page height and the sg page width x height is 64x64 for 8bpp, 64x32 for 16 bpp, 32x32 for 32 bpp*/ + /*in tiling mode with rotation the sg pte requests are only one useful pte, and the sg row height is also the page height, but the sg page width and height are swapped*/ + /*in linear mode the pte requests are 8 useful pt_es, the sg page width is 4096 divided by the bytes per pixel, the sg page height is 1, but there is just one row whose height is the lines of pte prefetching*/ + /*the outstanding pte request limit is obtained by multiplying the outstanding chunk request limit by the peak pte request to eviction limiting ratio, rounding up to integer, multiplying by the pte requests per chunk, and rounding up to integer again*/ + /*if not using peak pte request to eviction limiting, the outstanding pte request limit is the pte requests in the vblank*/ + /*the pte requests in the vblank is the product of the number of pte request rows times the number of pte requests in a row*/ + /*the number of pte requests in a row is the quotient of the source width divided by 256, multiplied by the pte requests per chunk, rounded up to even, multiplied by the scatter-gather row height and divided by the scatter-gather page height*/ + /*the pte requests per chunk is 256 divided by the scatter-gather page width and the useful pt_es per pte request*/ + if (data->number_of_displays > 1 || (bw_neq(data->rotation_angle[4], bw_int_to_fixed(0)) && bw_neq(data->rotation_angle[4], bw_int_to_fixed(180)))) { + data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; + } + else { + data->peak_pte_request_to_eviction_ratio_limiting = dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) { + if (tiling_mode[i] == bw_def_linear) { + data->useful_pte_per_pte_request = bw_int_to_fixed(8); + data->scatter_gather_page_width[i] = bw_div(bw_int_to_fixed(4096), bw_int_to_fixed(data->bytes_per_pixel[i])); + data->scatter_gather_page_height[i] = bw_int_to_fixed(1); + data->scatter_gather_pte_request_rows = bw_int_to_fixed(1); + data->scatter_gather_row_height = bw_int_to_fixed(dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode); + } + else if (bw_equ(data->rotation_angle[i], bw_int_to_fixed(0)) || bw_equ(data->rotation_angle[i], bw_int_to_fixed(180))) { + data->useful_pte_per_pte_request = bw_int_to_fixed(8); + switch (data->bytes_per_pixel[i]) { + case 4: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + case 2: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + default: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + } + data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode); + data->scatter_gather_row_height = data->scatter_gather_page_height[i]; + } + else { + data->useful_pte_per_pte_request = bw_int_to_fixed(1); + switch (data->bytes_per_pixel[i]) { + case 4: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(32); + break; + case 2: + data->scatter_gather_page_width[i] = bw_int_to_fixed(32); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + default: + data->scatter_gather_page_width[i] = bw_int_to_fixed(64); + data->scatter_gather_page_height[i] = bw_int_to_fixed(64); + break; + } + data->scatter_gather_pte_request_rows = bw_int_to_fixed(dceip->scatter_gather_pte_request_rows_in_tiling_mode); + data->scatter_gather_row_height = data->scatter_gather_page_height[i]; + } + data->pte_request_per_chunk[i] = bw_div(bw_div(bw_int_to_fixed(dceip->chunk_width), data->scatter_gather_page_width[i]), data->useful_pte_per_pte_request); + data->scatter_gather_pte_requests_in_row[i] = bw_div(bw_mul(bw_ceil2(bw_mul(bw_div(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(dceip->chunk_width)), data->pte_request_per_chunk[i]), bw_int_to_fixed(1)), data->scatter_gather_row_height), data->scatter_gather_page_height[i]); + data->scatter_gather_pte_requests_in_vblank = bw_mul(data->scatter_gather_pte_request_rows, data->scatter_gather_pte_requests_in_row[i]); + if (bw_equ(data->peak_pte_request_to_eviction_ratio_limiting, bw_int_to_fixed(0))) { + data->scatter_gather_pte_request_limit[i] = data->scatter_gather_pte_requests_in_vblank; + } + else { + data->scatter_gather_pte_request_limit[i] = bw_max2(dceip->minimum_outstanding_pte_request_limit, bw_min2(data->scatter_gather_pte_requests_in_vblank, bw_ceil2(bw_mul(bw_mul(bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->memory_chunk_size_in_bytes[i]), data->pte_request_per_chunk[i]), data->peak_pte_request_to_eviction_ratio_limiting), bw_int_to_fixed(1)))); + } + } + } + /*pitch padding recommended for efficiency in linear mode*/ + /*in linear mode graphics or underlay with scatter gather, a pitch that is a multiple of the channel interleave (256 bytes) times the channel-bank rotation is not efficient*/ + /*if that is the case it is recommended to pad the pitch by at least 256 pixels*/ + data->inefficient_linear_pitch_in_bytes = bw_mul(bw_mul(bw_int_to_fixed(256), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)); + + /*pixel transfer time*/ + /*the dmif and mcifwr yclk(pclk) required is the one that allows the transfer of all pipe's data buffer size in memory in the time for data transfer*/ + /*for dmif, pte and cursor requests have to be included.*/ + /*the dram data requirement is doubled when the data request size in bytes is less than the dram channel width times the burst size (8)*/ + /*the dram data requirement is also multiplied by the number of channels in the case of low power tiling*/ + /*the page close-open time is determined by trc and the number of page close-opens*/ + /*in tiled mode graphics or underlay with scatter-gather enabled the bytes per page close-open is the product of the memory line interleave times the maximum of the scatter-gather page width and the product of the tile width (8 pixels) times the number of channels times the number of banks.*/ + /*in linear mode graphics or underlay with scatter-gather enabled and inefficient pitch, the bytes per page close-open is the line request alternation slice, because different lines are in completely different 4k address bases.*/ + /*otherwise, the bytes page close-open is the chunk size because that is the arbitration slice.*/ + /*pte requests are grouped by pte requests per chunk if that is more than 1. each group costs a page close-open time for dmif reads*/ + /*cursor requests outstanding are limited to a group of two source lines. each group costs a page close-open time for dmif reads*/ + /*the display reads and writes time for data transfer is the minimum data or cursor buffer size in time minus the mc urgent latency*/ + /*the mc urgent latency is experienced more than one time if the number of dmif requests in the data buffer exceeds the request buffer size plus the request slots reserved for dmif in the dram channel arbiter queues*/ + /*the dispclk required is the maximum for all surfaces of the maximum of the source pixels for first output pixel times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, and the source pixels for last output pixel, times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, plus the active time.*/ + /*the data burst time is the maximum of the total page close-open time, total dmif/mcifwr buffer size in memory divided by the dram bandwidth, and the total dmif/mcifwr buffer size in memory divided by the 32 byte sclk data bus bandwidth, each multiplied by its efficiency.*/ + /*the source line transfer time is the maximum for all surfaces of the maximum of the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the fist pixel, and the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the last pixel plus the active time.*/ + /*the source pixels for the first output pixel is 512 if the scaler vertical filter initialization value is greater than 2, and it is 4 times the source width if it is greater than 4.*/ + /*the source pixels for the last output pixel is the source width times the scaler vertical filter initialization value rounded up to even*/ + /*the source data for these pixels is the number of pixels times the bytes per pixel times the bytes per request divided by the useful bytes per request.*/ + data->cursor_total_data = bw_int_to_fixed(0); + data->cursor_total_request_groups = bw_int_to_fixed(0); + data->scatter_gather_total_pte_requests = bw_int_to_fixed(0); + data->scatter_gather_total_pte_request_groups = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->cursor_total_data = bw_add(data->cursor_total_data, bw_mul(bw_mul(bw_int_to_fixed(2), data->cursor_width_pixels[i]), bw_int_to_fixed(4))); + if (dceip->large_cursor == 1) { + data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_int_to_fixed((dceip->cursor_max_outstanding_group_num + 1))); + } + else { + data->cursor_total_request_groups = bw_add(data->cursor_total_request_groups, bw_ceil2(bw_div(data->cursor_width_pixels[i], dceip->cursor_chunk_width), bw_int_to_fixed(1))); + } + if (data->scatter_gather_enable_for_pipe[i]) { + data->scatter_gather_total_pte_requests = bw_add(data->scatter_gather_total_pte_requests, data->scatter_gather_pte_request_limit[i]); + data->scatter_gather_total_pte_request_groups = bw_add(data->scatter_gather_total_pte_request_groups, bw_ceil2(bw_div(data->scatter_gather_pte_request_limit[i], bw_ceil2(data->pte_request_per_chunk[i], bw_int_to_fixed(1))), bw_int_to_fixed(1))); + } + } + } + data->tile_width_in_pixels = bw_int_to_fixed(8); + data->dmif_total_number_of_data_request_page_close_open = bw_int_to_fixed(0); + data->mcifwr_total_number_of_data_request_page_close_open = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] != bw_def_linear) { + data->bytes_per_page_close_open = bw_mul(data->lines_interleaved_in_mem_access[i], bw_max2(bw_mul(bw_mul(bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->tile_width_in_pixels), bw_int_to_fixed(vbios->number_of_dram_banks)), bw_int_to_fixed(data->number_of_dram_channels)), bw_mul(bw_int_to_fixed(data->bytes_per_pixel[i]), data->scatter_gather_page_width[i]))); + } + else if (data->scatter_gather_enable_for_pipe[i] == 1 && tiling_mode[i] == bw_def_linear && bw_equ(bw_mod((bw_mul(data->pitch_in_pixels_after_surface_type[i], bw_int_to_fixed(data->bytes_per_pixel[i]))), data->inefficient_linear_pitch_in_bytes), bw_int_to_fixed(0))) { + data->bytes_per_page_close_open = dceip->linear_mode_line_request_alternation_slice; + } + else { + data->bytes_per_page_close_open = data->memory_chunk_size_in_bytes[i]; + } + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->dmif_total_number_of_data_request_page_close_open = bw_add(data->dmif_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open)); + } + else { + data->mcifwr_total_number_of_data_request_page_close_open = bw_add(data->mcifwr_total_number_of_data_request_page_close_open, bw_div(bw_ceil2(data->adjusted_data_buffer_size[i], data->memory_chunk_size_in_bytes[i]), data->bytes_per_page_close_open)); + } + } + } + data->dmif_total_page_close_open_time = bw_div(bw_mul((bw_add(bw_add(data->dmif_total_number_of_data_request_page_close_open, data->scatter_gather_total_pte_request_groups), data->cursor_total_request_groups)), vbios->trc), bw_int_to_fixed(1000)); + data->mcifwr_total_page_close_open_time = bw_div(bw_mul(data->mcifwr_total_number_of_data_request_page_close_open, vbios->trc), bw_int_to_fixed(1000)); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->adjusted_data_buffer_size_in_memory[i] = bw_div(bw_mul(data->adjusted_data_buffer_size[i], data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + } + } + data->total_requests_for_adjusted_dmif_size = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_requests_for_adjusted_dmif_size = bw_add(data->total_requests_for_adjusted_dmif_size, bw_div(data->adjusted_data_buffer_size[i], data->useful_bytes_per_request[i])); + } + } + } + data->total_dmifmc_urgent_trips = bw_ceil2(bw_div(data->total_requests_for_adjusted_dmif_size, (bw_add(dceip->dmif_request_buffer_size, bw_int_to_fixed(vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel * data->number_of_dram_channels)))), bw_int_to_fixed(1)); + data->total_dmifmc_urgent_latency = bw_mul(vbios->dmifmc_urgent_latency, data->total_dmifmc_urgent_trips); + data->total_display_reads_required_data = bw_int_to_fixed(0); + data->total_display_reads_required_dram_access_data = bw_int_to_fixed(0); + data->total_display_writes_required_data = bw_int_to_fixed(0); + data->total_display_writes_required_dram_access_data = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->display_reads_required_data = data->adjusted_data_buffer_size_in_memory[i]; + /*for hbm memories, each channel is split into 2 pseudo-channels that are each 64 bits in width. each*/ + /*pseudo-channel may be read independently of one another.*/ + /*the read burst length (bl) for hbm memories is 4, so each read command will access 32 bytes of data.*/ + /*the 64 or 32 byte sized data is stored in one pseudo-channel.*/ + /*it will take 4 memclk cycles or 8 yclk cycles to fetch 64 bytes of data from the hbm memory (2 read commands).*/ + /*it will take 2 memclk cycles or 4 yclk cycles to fetch 32 bytes of data from the hbm memory (1 read command).*/ + /*for gddr5/ddr4 memories, there is additional overhead if the size of the request is smaller than 64 bytes.*/ + /*the read burst length (bl) for gddr5/ddr4 memories is 8, regardless of the size of the data request.*/ + /*therefore it will require 8 cycles to fetch 64 or 32 bytes of data from the memory.*/ + /*the memory efficiency will be 50% for the 32 byte sized data.*/ + if (vbios->memory_type == bw_def_hbm) { + data->display_reads_required_dram_access_data = data->adjusted_data_buffer_size_in_memory[i]; + } + else { + data->display_reads_required_dram_access_data = bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed((8 * vbios->dram_channel_width_in_bits / 8)), data->bytes_per_request[i]), bw_int_to_fixed(1))); + } + data->total_display_reads_required_data = bw_add(data->total_display_reads_required_data, data->display_reads_required_data); + data->total_display_reads_required_dram_access_data = bw_add(data->total_display_reads_required_dram_access_data, data->display_reads_required_dram_access_data); + } + else { + data->total_display_writes_required_data = bw_add(data->total_display_writes_required_data, data->adjusted_data_buffer_size_in_memory[i]); + data->total_display_writes_required_dram_access_data = bw_add(data->total_display_writes_required_dram_access_data, bw_mul(data->adjusted_data_buffer_size_in_memory[i], bw_ceil2(bw_div(bw_int_to_fixed(vbios->dram_channel_width_in_bits), data->bytes_per_request[i]), bw_int_to_fixed(1)))); + } + } + } + data->total_display_reads_required_data = bw_add(bw_add(data->total_display_reads_required_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64))); + data->total_display_reads_required_dram_access_data = bw_add(bw_add(data->total_display_reads_required_dram_access_data, data->cursor_total_data), bw_mul(data->scatter_gather_total_pte_requests, bw_int_to_fixed(64))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(4))) { + data->src_pixels_for_first_output_pixel[i] = bw_mul(bw_int_to_fixed(4), data->source_width_rounded_up_to_chunks[i]); + } + else { + if (bw_mtn(data->v_filter_init[i], bw_int_to_fixed(2))) { + data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(512); + } + else { + data->src_pixels_for_first_output_pixel[i] = bw_int_to_fixed(0); + } + } + data->src_data_for_first_output_pixel[i] = bw_div(bw_mul(bw_mul(data->src_pixels_for_first_output_pixel[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->src_pixels_for_last_output_pixel[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), bw_mul(bw_ceil2(data->vsr[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->horizontal_blank_and_chunk_granularity_factor[i]))); + data->src_data_for_last_output_pixel[i] = bw_div(bw_mul(bw_mul(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_max2(bw_ceil2(data->v_filter_init[i], bw_int_to_fixed(dceip->lines_interleaved_into_lb)), data->lines_interleaved_in_mem_access[i])), bw_int_to_fixed(data->bytes_per_pixel[i])), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->active_time[i] = bw_div(bw_div(data->source_width_rounded_up_to_chunks[i], data->hsr[i]), data->pixel_rate[i]); + } + } + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->dmif_burst_time[i][j] = bw_max3(data->dmif_total_page_close_open_time, bw_div(data->total_display_reads_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))), bw_div(data->total_display_reads_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency))))); + if (data->d1_display_write_back_dwb_enable == 1) { + data->mcifwr_burst_time[i][j] = bw_max3(data->mcifwr_total_page_close_open_time, bw_div(data->total_display_writes_required_dram_access_data, (bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[i]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_wrchannels)))), bw_div(data->total_display_writes_required_data, (bw_mul(bw_mul(sclk[j], vbios->data_return_bus_width), bw_int_to_fixed(bus_efficiency))))); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + for (j = 0; j <= 2; j++) { + for (k = 0; k <= 7; k++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + /*time to transfer data from the dmif buffer to the lb. since the mc to dmif transfer time overlaps*/ + /*with the dmif to lb transfer time, only time to transfer the last chunk is considered.*/ + data->dmif_buffer_transfer_time[i] = bw_mul(data->source_width_rounded_up_to_chunks[i], (bw_div(dceip->lb_write_pixels_per_dispclk, (bw_div(vbios->low_voltage_max_dispclk, dceip->display_pipe_throughput_factor))))); + data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_add(bw_mul((bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->dmif_buffer_transfer_time[i]), data->active_time[i])); + /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/ + /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/ + /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/ + /*immediately serviced without a gap in the urgent requests.*/ + /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/ + if (surface_type[i] == bw_def_graphics) { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component; + break; + } + if (data->use_alpha[i] == 1) { + data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency); + } + } + else { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = bw_int_to_fixed(3); + break; + } + } + if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) { + data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i])); + } + else { + data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1)))); + } + data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_mul(bw_int_to_fixed(2), bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(bw_mul(data->bytes_per_request[i], data->pixel_rate[i]), data->scaler_limits_factor), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->dmif_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i])))))); + } + else { + data->line_source_transfer_time[i][j][k] = bw_max2(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), bw_sub(bw_mul((bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[j][k])), bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i])); + /*during an mclk switch the requests from the dce ip are stored in the gmc/arb. these requests should be serviced immediately*/ + /*after the mclk switch sequence and not incur an urgent latency penalty. it is assumed that the gmc/arb can hold up to 256 requests*/ + /*per memory channel. if the dce ip is urgent after the mclk switch sequence, all pending requests and subsequent requests should be*/ + /*immediately serviced without a gap in the urgent requests.*/ + /*the latency incurred would be the time to issue the requests and return the data for the first or last output pixel.*/ + data->dram_speed_change_line_source_transfer_time[i][j][k] = bw_max2((bw_add((bw_div(data->src_data_for_first_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_first_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1)))))), (bw_add((bw_div(data->src_data_for_last_output_pixel[i], bw_min2(bw_mul(data->bytes_per_request[i], sclk[k]), bw_div(bw_mul(data->bytes_per_request[i], vbios->low_voltage_max_dispclk), bw_int_to_fixed(2))))), (bw_sub(bw_mul(data->mcifwr_burst_time[j][k], bw_floor2(bw_div(data->src_data_for_last_output_pixel[i], data->adjusted_data_buffer_size_in_memory[i]), bw_int_to_fixed(1))), data->active_time[i]))))); + } + } + } + } + } + /*cpu c-state and p-state change enable*/ + /*for cpu p-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration*/ + /*for cpu c-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration and recovery*/ + /*condition for the blackout duration:*/ + /* minimum latency hiding > blackout duration + dmif burst time + line source transfer time*/ + /*condition for the blackout recovery:*/ + /* recovery time > dmif burst time + 2 * urgent latency*/ + /* recovery time > (display bw * blackout duration + (2 * urgent latency + dmif burst time)*dispclk - dmif size )*/ + /* / (dispclk - display bw)*/ + /*the minimum latency hiding is the minimum for all pipes of one screen line time, plus one more line time if doing lb prefetch, plus the dmif data buffer size equivalent in time, minus the urgent latency.*/ + /*the minimum latency hiding is further limited by the cursor. the cursor latency hiding is the number of lines of the cursor buffer, minus one if the downscaling is less than two, or minus three if it is more*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_equ(dceip->stutter_and_dram_clock_state_change_gated_before_cursor, bw_int_to_fixed(0)) && bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0)))) { + if (bw_ltn(data->vsr[i], bw_int_to_fixed(2))) { + data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(1))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]); + } + else { + data->cursor_latency_hiding[i] = bw_div(bw_div(bw_mul((bw_sub(dceip->cursor_dcp_buffer_lines, bw_int_to_fixed(3))), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]); + } + } + else { + data->cursor_latency_hiding[i] = bw_int_to_fixed(9999); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1 && (bw_equ(data->vsr[i], bw_int_to_fixed(1)) || (bw_leq(data->vsr[i], bw_frc_to_fixed(8, 10)) && bw_leq(data->v_taps[i], bw_int_to_fixed(2)) && data->lb_bpc[i] == 8)) && surface_type[i] == bw_def_graphics) { + data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_sub(data->lb_partitions[i], bw_int_to_fixed(1)), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency); + } + else { + data->minimum_latency_hiding[i] = bw_sub(bw_div(bw_mul((bw_div((bw_add(bw_int_to_fixed(1 + data->line_buffer_prefetch[i]), bw_div(bw_div(data->data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_pixels[i]))), data->vsr[i])), data->h_total[i]), data->pixel_rate[i]), data->total_dmifmc_urgent_latency); + } + data->minimum_latency_hiding_with_cursor[i] = bw_min2(data->minimum_latency_hiding[i], data->cursor_latency_hiding[i]); + } + } + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->blackout_duration_margin[i][j] = bw_int_to_fixed(9999); + data->dispclk_required_for_blackout_duration[i][j] = bw_int_to_fixed(0); + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(0); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0))) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->line_source_transfer_time[k][i][j])); + data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->active_time[k])))); + if (bw_leq(vbios->maximum_blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999); + } + else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, bw_sub(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k])); + } + } + else { + data->blackout_duration_margin[i][j] = bw_min2(data->blackout_duration_margin[i][j], bw_sub(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->line_source_transfer_time[k][i][j])); + data->dispclk_required_for_blackout_duration[i][j] = bw_max3(data->dispclk_required_for_blackout_duration[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->minimum_latency_hiding_with_cursor[k], vbios->blackout_duration), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k])))); + if (bw_ltn(vbios->maximum_blackout_recovery_time, bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_int_to_fixed(9999); + } + else if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j])))))) { + data->dispclk_required_for_blackout_recovery[i][j] = bw_max2(data->dispclk_required_for_blackout_recovery[i][j], bw_div(bw_mul(bw_div(bw_div((bw_sub(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, vbios->maximum_blackout_recovery_time))), data->adjusted_data_buffer_size[k])), bw_int_to_fixed(data->bytes_per_pixel[k])), (bw_sub(vbios->maximum_blackout_recovery_time, (bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[i][j]))))), data->latency_hiding_lines[k]), data->lines_interleaved_in_mem_access[k])); + } + } + } + } + } + } + if (bw_mtn(data->blackout_duration_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[high][s_high], vbios->high_voltage_max_dispclk)) { + data->cpup_state_change_enable = bw_def_yes; + if (bw_ltn(data->dispclk_required_for_blackout_recovery[high][s_high], vbios->high_voltage_max_dispclk)) { + data->cpuc_state_change_enable = bw_def_yes; + } + else { + data->cpuc_state_change_enable = bw_def_no; + } + } + else { + data->cpup_state_change_enable = bw_def_no; + data->cpuc_state_change_enable = bw_def_no; + } + /*nb p-state change enable*/ + /*for dram speed/p-state change to be possible for a yclk(pclk) and sclk level there has to be positive margin and the dispclk required has to be*/ + /*below the maximum.*/ + /*the dram speed/p-state change margin is the minimum for all surfaces of the maximum latency hiding minus the dram speed/p-state change latency,*/ + /*minus the dmif burst time, minus the source line transfer time*/ + /*the maximum latency hiding is the minimum latency hiding plus one source line used for de-tiling in the line buffer, plus half the urgent latency*/ + /*if stutter and dram clock state change are gated before cursor then the cursor latency hiding does not limit stutter or dram clock state change*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((dceip->graphics_lb_nodownscaling_multi_line_prefetching == 1)) { + data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency)); + } + else { + /*maximum_latency_hiding(i) = minimum_latency_hiding(i) + 1 / vsr(i) * h_total(i) / pixel_rate(i) + 0.5 * total_dmifmc_urgent_latency*/ + data->maximum_latency_hiding[i] = bw_add(data->minimum_latency_hiding[i], bw_mul(bw_frc_to_fixed(8, 10), data->total_dmifmc_urgent_latency)); + } + data->maximum_latency_hiding_with_cursor[i] = bw_min2(data->maximum_latency_hiding[i], data->cursor_latency_hiding[i]); + } + } + /*initialize variables*/ + number_of_displays_enabled = 0; + number_of_displays_enabled_with_margin = 0; + for (k = 0; k < maximum_number_of_surfaces; k++) { + if (data->enable[k]) { + number_of_displays_enabled = number_of_displays_enabled + 1; + } + } + data->display_pstate_change_enable[maximum_number_of_surfaces - 1] = 0; + for (i = 0; i <= 2; i++) { + for (j = 0; j <= 7; j++) { + data->min_dram_speed_change_margin[i][j] = bw_int_to_fixed(9999); + data->dram_speed_change_margin = bw_int_to_fixed(9999); + data->dispclk_required_for_dram_speed_change[i][j] = bw_int_to_fixed(0); + data->num_displays_with_margin[i][j] = 0; + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k]) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]); + if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) { + /*determine the minimum dram clock change margin for each set of clock frequencies*/ + data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin); + /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/ + data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->active_time[k])))); + if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) { + data->display_pstate_change_enable[k] = 1; + data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1; + } + } + } + else { + data->dram_speed_change_margin = bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]); + if ((bw_mtn(data->dram_speed_change_margin, bw_int_to_fixed(0)) && bw_ltn(data->dram_speed_change_margin, bw_int_to_fixed(9999)))) { + /*determine the minimum dram clock change margin for each display pipe*/ + data->min_dram_speed_change_margin[i][j] = bw_min2(data->min_dram_speed_change_margin[i][j], data->dram_speed_change_margin); + /*compute the maximum clock frequuency required for the dram clock change at each set of clock frequencies*/ + data->dispclk_required_for_dram_speed_change[i][j] = bw_max3(data->dispclk_required_for_dram_speed_change[i][j], bw_div(bw_div(bw_mul(data->src_pixels_for_first_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]))), bw_div(bw_div(bw_mul(data->src_pixels_for_last_output_pixel[k], dceip->display_pipe_throughput_factor), dceip->lb_write_pixels_per_dispclk), (bw_add(bw_sub(bw_sub(bw_sub(bw_sub(data->maximum_latency_hiding_with_cursor[k], vbios->nbp_state_change_latency), data->dmif_burst_time[i][j]), data->dram_speed_change_line_source_transfer_time[k][i][j]), data->mcifwr_burst_time[i][j]), data->active_time[k])))); + if ((bw_ltn(data->dispclk_required_for_dram_speed_change[i][j], vbios->high_voltage_max_dispclk))) { + data->display_pstate_change_enable[k] = 1; + data->num_displays_with_margin[i][j] = data->num_displays_with_margin[i][j] + 1; + } + } + } + } + } + } + } + /*determine the number of displays with margin to switch in the v_active region*/ + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if ((data->enable[k] == 1 && data->display_pstate_change_enable[k] == 1)) { + number_of_displays_enabled_with_margin = number_of_displays_enabled_with_margin + 1; + } + } + /*determine the number of displays that don't have any dram clock change margin, but*/ + /*have the same resolution. these displays can switch in a common vblank region if*/ + /*their frames are aligned.*/ + data->min_vblank_dram_speed_change_margin = bw_int_to_fixed(9999); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k]) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]); + data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]); + } + else { + data->v_blank_dram_speed_change_margin[k] = bw_sub(bw_sub(bw_sub(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[k], bw_sub(bw_div(data->src_height[k], data->v_scale_ratio[k]), bw_int_to_fixed(4)))), data->h_total[k]), data->pixel_rate[k]), vbios->nbp_state_change_latency), data->dmif_burst_time[low][s_low]), data->mcifwr_burst_time[low][s_low]), data->dram_speed_change_line_source_transfer_time[k][low][s_low]); + data->min_vblank_dram_speed_change_margin = bw_min2(data->min_vblank_dram_speed_change_margin, data->v_blank_dram_speed_change_margin[k]); + } + } + } + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + data->displays_with_same_mode[i] = bw_int_to_fixed(0); + if (data->enable[i] == 1 && data->display_pstate_change_enable[i] == 0 && bw_mtn(data->v_blank_dram_speed_change_margin[i], bw_int_to_fixed(0))) { + for (j = 0; j <= maximum_number_of_surfaces - 1; j++) { + if ((data->enable[j] == 1 && bw_equ(data->source_width_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[j]) && bw_equ(data->source_height_rounded_up_to_chunks[i], data->source_height_rounded_up_to_chunks[j]) && bw_equ(data->vsr[i], data->vsr[j]) && bw_equ(data->hsr[i], data->hsr[j]) && bw_equ(data->pixel_rate[i], data->pixel_rate[j]))) { + data->displays_with_same_mode[i] = bw_add(data->displays_with_same_mode[i], bw_int_to_fixed(1)); + } + } + } + } + /*compute the maximum number of aligned displays with no margin*/ + number_of_aligned_displays_with_no_margin = 0; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + number_of_aligned_displays_with_no_margin = bw_fixed_to_int(bw_max2(bw_int_to_fixed(number_of_aligned_displays_with_no_margin), data->displays_with_same_mode[i])); + } + /*dram clock change is possible, if all displays have positive margin except for one display or a group of*/ + /*aligned displays with the same timing.*/ + /*the display(s) with the negative margin can be switched in the v_blank region while the other*/ + /*displays are in v_blank or v_active.*/ + if ((number_of_displays_enabled_with_margin + number_of_aligned_displays_with_no_margin == number_of_displays_enabled && bw_mtn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[high][s_high], bw_int_to_fixed(9999)) && bw_ltn(data->dispclk_required_for_dram_speed_change[high][s_high], vbios->high_voltage_max_dispclk))) { + data->nbp_state_change_enable = bw_def_yes; + } + else { + data->nbp_state_change_enable = bw_def_no; + } + /*dram clock change is possible only in vblank if all displays are aligned and have no margin*/ + if ((number_of_aligned_displays_with_no_margin == number_of_displays_enabled)) { + nbp_state_change_enable_blank = bw_def_yes; + } + else { + nbp_state_change_enable_blank = bw_def_no; + } + /*required yclk(pclk)*/ + /*yclk requirement only makes sense if the dmif and mcifwr data total page close-open time is less than the time for data transfer and the total pte requests fit in the scatter-gather saw queque size*/ + /*if that is the case, the yclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/low yclk(pclk) is chosen accordingly*/ + /*high yclk(pclk) has to be selected when dram speed/p-state change is not possible.*/ + data->min_cursor_memory_interface_buffer_size_in_time = bw_int_to_fixed(9999); + /* number of cursor lines stored in the cursor data return buffer*/ + num_cursor_lines = 0; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->cursor_width_pixels[i], bw_int_to_fixed(0))) { + /*compute number of cursor lines stored in data return buffer*/ + if (bw_leq(data->cursor_width_pixels[i], bw_int_to_fixed(64)) && dceip->large_cursor == 1) { + num_cursor_lines = 4; + } + else { + num_cursor_lines = 2; + } + data->min_cursor_memory_interface_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, bw_div(bw_mul(bw_div(bw_int_to_fixed(num_cursor_lines), data->vsr[i]), data->h_total[i]), data->pixel_rate[i])); + } + } + } + /*compute minimum time to read one chunk from the dmif buffer*/ + if ((number_of_displays_enabled > 2)) { + data->chunk_request_delay = 0; + } + else { + data->chunk_request_delay = bw_fixed_to_int(bw_div(bw_int_to_fixed(512), vbios->high_voltage_max_dispclk)); + } + data->min_read_buffer_size_in_time = bw_min2(data->min_cursor_memory_interface_buffer_size_in_time, data->min_dmif_size_in_time); + data->display_reads_time_for_data_transfer = bw_sub(bw_sub(data->min_read_buffer_size_in_time, data->total_dmifmc_urgent_latency), bw_int_to_fixed(data->chunk_request_delay)); + data->display_writes_time_for_data_transfer = bw_sub(data->min_mcifwr_size_in_time, vbios->mcifwrmc_urgent_latency); + data->dmif_required_dram_bandwidth = bw_div(data->total_display_reads_required_dram_access_data, data->display_reads_time_for_data_transfer); + data->mcifwr_required_dram_bandwidth = bw_div(data->total_display_writes_required_dram_access_data, data->display_writes_time_for_data_transfer); + data->required_dmifmc_urgent_latency_for_page_close_open = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_total_page_close_open_time)), data->total_dmifmc_urgent_trips); + data->required_mcifmcwr_urgent_latency = bw_sub(data->min_mcifwr_size_in_time, data->mcifwr_total_page_close_open_time); + if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { + data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999); + yclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) { + data->required_dram_bandwidth_gbyte_per_second = bw_int_to_fixed(9999); + yclk_message = bw_def_exceeded_allowed_page_close_open; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else { + data->required_dram_bandwidth_gbyte_per_second = bw_div(bw_max2(data->dmif_required_dram_bandwidth, data->mcifwr_required_dram_bandwidth), bw_int_to_fixed(1000)); + if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[low][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[low][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[low][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[low][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[low][s_high] == number_of_displays_enabled_with_margin))) { + yclk_message = bw_fixed_to_int(vbios->low_yclk); + data->y_clk_level = low; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[low]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels))) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[mid][s_high], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[mid][s_high], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[mid][s_high], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[mid][s_high], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[mid][s_high] == number_of_displays_enabled_with_margin))) { + yclk_message = bw_fixed_to_int(vbios->mid_yclk); + data->y_clk_level = mid; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[mid]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else if (bw_ltn(bw_mul(data->required_dram_bandwidth_gbyte_per_second, bw_int_to_fixed(1000)), bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)))) { + yclk_message = bw_fixed_to_int(vbios->high_yclk); + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + else { + yclk_message = bw_def_exceeded_allowed_maximum_bw; + data->y_clk_level = high; + data->dram_bandwidth = bw_mul(bw_div(bw_mul(bw_mul(data->dram_efficiency, yclk[high]), bw_int_to_fixed(vbios->dram_channel_width_in_bits)), bw_int_to_fixed(8)), bw_int_to_fixed(data->number_of_dram_channels)); + } + } + /*required sclk*/ + /*sclk requirement only makes sense if the total pte requests fit in the scatter-gather saw queque size*/ + /*if that is the case, the sclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/mid/low sclk is chosen accordingly, unless that choice results in foresaking dram speed/nb p-state change.*/ + /*the dmif and mcifwr sclk required is the one that allows the transfer of all pipe's data buffer size through the sclk bus in the time for data transfer*/ + /*for dmif, pte and cursor requests have to be included.*/ + data->dmif_required_sclk = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + data->mcifwr_required_sclk = bw_div(bw_div(data->total_display_writes_required_data, data->display_writes_time_for_data_transfer), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + if (bw_mtn(data->scatter_gather_total_pte_requests, dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) { + data->required_sclk = bw_int_to_fixed(9999); + sclk_message = bw_def_exceeded_allowed_outstanding_pte_req_queue_size; + data->sclk_level = s_high; + } + else if (bw_mtn(vbios->dmifmc_urgent_latency, data->required_dmifmc_urgent_latency_for_page_close_open) || bw_mtn(vbios->mcifwrmc_urgent_latency, data->required_mcifmcwr_urgent_latency)) { + data->required_sclk = bw_int_to_fixed(9999); + sclk_message = bw_def_exceeded_allowed_page_close_open; + data->sclk_level = s_high; + } + else { + data->required_sclk = bw_max2(data->dmif_required_sclk, data->mcifwr_required_sclk); + if (bw_ltn(data->required_sclk, sclk[s_low]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_low], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_low], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_low], vbios->low_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_low] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_low; + data->sclk_level = s_low; + data->required_sclk = vbios->low_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid1]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid1], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid1], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid1], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid1] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid1; + data->required_sclk = vbios->mid1_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid2]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid2], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid2], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid2], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid2] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid2; + data->required_sclk = vbios->mid2_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid3]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid3], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid3], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid3], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid3] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid3; + data->required_sclk = vbios->mid3_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid4]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid4], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid4], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid4], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid4] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid4; + data->required_sclk = vbios->mid4_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid5]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid5], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid5], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid5], vbios->mid_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid5] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid5; + data->required_sclk = vbios->mid5_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_mid6]) && (data->cpup_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->cpuc_state_change_enable == bw_def_no || (bw_mtn(data->blackout_duration_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->dispclk_required_for_blackout_duration[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && bw_ltn(data->dispclk_required_for_blackout_recovery[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk))) && (data->nbp_state_change_enable == bw_def_no || (bw_mtn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(0)) && bw_ltn(data->min_dram_speed_change_margin[data->y_clk_level][s_mid6], bw_int_to_fixed(9999)) && bw_leq(data->dispclk_required_for_dram_speed_change[data->y_clk_level][s_mid6], vbios->high_voltage_max_dispclk) && data->num_displays_with_margin[data->y_clk_level][s_mid6] == number_of_displays_enabled_with_margin))) { + sclk_message = bw_def_mid; + data->sclk_level = s_mid6; + data->required_sclk = vbios->mid6_sclk; + } + else if (bw_ltn(data->required_sclk, sclk[s_high])) { + sclk_message = bw_def_high; + data->sclk_level = s_high; + data->required_sclk = vbios->high_sclk; + } + else { + sclk_message = bw_def_exceeded_allowed_maximum_sclk; + data->sclk_level = s_high; + /*required_sclk = high_sclk*/ + } + } + /*dispclk*/ + /*if dispclk is set to the maximum, ramping is not required. dispclk required without ramping is less than the dispclk required with ramping.*/ + /*if dispclk required without ramping is more than the maximum dispclk, that is the dispclk required, and the mode is not supported*/ + /*if that does not happen, but dispclk required with ramping is more than the maximum dispclk, dispclk required is just the maximum dispclk*/ + /*if that does not happen either, dispclk required is the dispclk required with ramping.*/ + /*dispclk required without ramping is the maximum of the one required for display pipe pixel throughput, for scaler throughput, for total read request thrrougput and for dram/np p-state change if enabled.*/ + /*the display pipe pixel throughput is the maximum of lines in per line out in the beginning of the frame and lines in per line out in the middle of the frame multiplied by the horizontal blank and chunk granularity factor, altogether multiplied by the ratio of the source width to the line time, divided by the line buffer pixels per dispclk throughput, and multiplied by the display pipe throughput factor.*/ + /*the horizontal blank and chunk granularity factor is the ratio of the line time divided by the line time minus half the horizontal blank and chunk time. it applies when the lines in per line out is not 2 or 4.*/ + /*the dispclk required for scaler throughput is the product of the pixel rate and the scaling limits factor.*/ + /*the dispclk required for total read request throughput is the product of the peak request-per-second bandwidth and the dispclk cycles per request, divided by the request efficiency.*/ + /*for the dispclk required with ramping, instead of multiplying just the pipe throughput by the display pipe throughput factor, we multiply the scaler and pipe throughput by the ramping factor.*/ + /*the scaling limits factor is the product of the horizontal scale ratio, and the ratio of the vertical taps divided by the scaler efficiency clamped to at least 1.*/ + /*the scaling limits factor itself it also clamped to at least 1*/ + /*if doing downscaling with the pre-downscaler enabled, the horizontal scale ratio should not be considered above (use "1")*/ + data->downspread_factor = bw_add(bw_int_to_fixed(1), bw_div(vbios->down_spread_percentage, bw_int_to_fixed(100))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] == bw_def_graphics) { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->graphics_vscaler_efficiency12_bit_per_component; + break; + } + if (data->use_alpha[i] == 1) { + data->v_scaler_efficiency = bw_min2(data->v_scaler_efficiency, dceip->alpha_vscaler_efficiency); + } + } + else { + switch (data->lb_bpc[i]) { + case 6: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency6_bit_per_component; + break; + case 8: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency8_bit_per_component; + break; + case 10: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency10_bit_per_component; + break; + default: + data->v_scaler_efficiency = dceip->underlay_vscaler_efficiency12_bit_per_component; + break; + } + } + if (dceip->pre_downscaler_enabled && bw_mtn(data->hsr[i], bw_int_to_fixed(1))) { + data->scaler_limits_factor = bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_div(data->source_width_rounded_up_to_chunks[i], data->h_total[i])); + } + else { + data->scaler_limits_factor = bw_max3(bw_int_to_fixed(1), bw_ceil2(bw_div(data->h_taps[i], bw_int_to_fixed(4)), bw_int_to_fixed(1)), bw_mul(data->hsr[i], bw_max2(bw_div(data->v_taps[i], data->v_scaler_efficiency), bw_int_to_fixed(1)))); + } + data->display_pipe_pixel_throughput = bw_div(bw_div(bw_mul(bw_max2(data->lb_lines_in_per_line_out_in_beginning_of_frame[i], bw_mul(data->lb_lines_in_per_line_out_in_middle_of_frame[i], data->horizontal_blank_and_chunk_granularity_factor[i])), data->source_width_rounded_up_to_chunks[i]), (bw_div(data->h_total[i], data->pixel_rate[i]))), dceip->lb_write_pixels_per_dispclk); + data->dispclk_required_without_ramping[i] = bw_mul(data->downspread_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), bw_mul(dceip->display_pipe_throughput_factor, data->display_pipe_pixel_throughput))); + data->dispclk_required_with_ramping[i] = bw_mul(dceip->dispclk_ramping_factor, bw_max2(bw_mul(data->pixel_rate[i], data->scaler_limits_factor), data->display_pipe_pixel_throughput)); + } + } + data->total_dispclk_required_with_ramping = bw_int_to_fixed(0); + data->total_dispclk_required_without_ramping = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_ltn(data->total_dispclk_required_with_ramping, data->dispclk_required_with_ramping[i])) { + data->total_dispclk_required_with_ramping = data->dispclk_required_with_ramping[i]; + } + if (bw_ltn(data->total_dispclk_required_without_ramping, data->dispclk_required_without_ramping[i])) { + data->total_dispclk_required_without_ramping = data->dispclk_required_without_ramping[i]; + } + } + } + data->total_read_request_bandwidth = bw_int_to_fixed(0); + data->total_write_request_bandwidth = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->total_read_request_bandwidth = bw_add(data->total_read_request_bandwidth, data->request_bandwidth[i]); + } + else { + data->total_write_request_bandwidth = bw_add(data->total_write_request_bandwidth, data->request_bandwidth[i]); + } + } + } + data->dispclk_required_for_total_read_request_bandwidth = bw_div(bw_mul(data->total_read_request_bandwidth, dceip->dispclk_per_request), dceip->request_efficiency); + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping, data->dispclk_required_for_total_read_request_bandwidth); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping, data->dispclk_required_for_total_read_request_bandwidth); + if (data->cpuc_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max3(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level], data->dispclk_required_for_blackout_recovery[data->y_clk_level][data->sclk_level]); + } + if (data->cpup_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_blackout_duration[data->y_clk_level][data->sclk_level]); + } + if (data->nbp_state_change_enable == bw_def_yes) { + data->total_dispclk_required_with_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_with_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]); + data->total_dispclk_required_without_ramping_with_request_bandwidth = bw_max2(data->total_dispclk_required_without_ramping_with_request_bandwidth, data->dispclk_required_for_dram_speed_change[data->y_clk_level][data->sclk_level]); + } + if (bw_ltn(data->total_dispclk_required_with_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) { + data->dispclk = data->total_dispclk_required_with_ramping_with_request_bandwidth; + } + else if (bw_ltn(data->total_dispclk_required_without_ramping_with_request_bandwidth, vbios->high_voltage_max_dispclk)) { + data->dispclk = vbios->high_voltage_max_dispclk; + } + else { + data->dispclk = data->total_dispclk_required_without_ramping_with_request_bandwidth; + } + /* required core voltage*/ + /* the core voltage required is low if sclk, yclk(pclk)and dispclk are within the low limits*/ + /* otherwise, the core voltage required is medium if yclk (pclk) is within the low limit and sclk and dispclk are within the medium limit*/ + /* otherwise, the core voltage required is high if the three clocks are within the high limits*/ + /* otherwise, or if the mode is not supported, core voltage requirement is not applicable*/ + if (pipe_check == bw_def_notok) { + voltage = bw_def_na; + } + else if (mode_check == bw_def_notok) { + voltage = bw_def_notok; + } + else if (bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) && sclk_message == bw_def_low && bw_ltn(data->dispclk, vbios->low_voltage_max_dispclk)) { + voltage = bw_def_0_72; + } + else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid) && bw_ltn(data->dispclk, vbios->mid_voltage_max_dispclk)) { + voltage = bw_def_0_8; + } + else if ((bw_equ(bw_int_to_fixed(yclk_message), vbios->low_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->mid_yclk) || bw_equ(bw_int_to_fixed(yclk_message), vbios->high_yclk)) && (sclk_message == bw_def_low || sclk_message == bw_def_mid || sclk_message == bw_def_high) && bw_leq(data->dispclk, vbios->high_voltage_max_dispclk)) { + if ((data->nbp_state_change_enable == bw_def_no && nbp_state_change_enable_blank == bw_def_no)) { + voltage = bw_def_high_no_nbp_state_change; + } + else { + voltage = bw_def_0_9; + } + } + else { + voltage = bw_def_notok; + } + if (voltage == bw_def_0_72) { + data->max_phyclk = vbios->low_voltage_max_phyclk; + } + else if (voltage == bw_def_0_8) { + data->max_phyclk = vbios->mid_voltage_max_phyclk; + } + else { + data->max_phyclk = vbios->high_voltage_max_phyclk; + } + /*required blackout recovery time*/ + data->blackout_recovery_time = bw_int_to_fixed(0); + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + if (data->enable[k] && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0)) && data->cpup_state_change_enable == bw_def_yes) { + if (surface_type[k] != bw_def_display_write_back420_luma && surface_type[k] != bw_def_display_write_back420_chroma) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])); + if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])))))) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_mul(bw_int_to_fixed(2), data->total_dmifmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); + } + } + else { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])); + if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])))))) { + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); + } + } + } + } + /*sclk deep sleep*/ + /*during self-refresh, sclk can be reduced to dispclk divided by the minimum pixels in the data fifo entry, with 15% margin, but shoudl not be set to less than the request bandwidth.*/ + /*the data fifo entry is 16 pixels for the writeback, 64 bytes/bytes_per_pixel for the graphics, 16 pixels for the parallel rotation underlay,*/ + /*and 16 bytes/bytes_per_pixel for the orthogonal rotation underlay.*/ + /*in parallel mode (underlay pipe), the data read from the dmifv buffer is variable and based on the pixel depth (8bbp - 16 bytes, 16 bpp - 32 bytes, 32 bpp - 64 bytes)*/ + /*in orthogonal mode (underlay pipe), the data read from the dmifv buffer is fixed at 16 bytes.*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (surface_type[i] == bw_def_display_write_back420_luma || surface_type[i] == bw_def_display_write_back420_chroma) { + data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16); + } + else if (surface_type[i] == bw_def_graphics) { + data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(64), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + else if (data->orthogonal_rotation[i] == 0) { + data->pixels_per_data_fifo_entry[i] = bw_int_to_fixed(16); + } + else { + data->pixels_per_data_fifo_entry[i] = bw_div(bw_int_to_fixed(16), bw_int_to_fixed(data->bytes_per_pixel[i])); + } + } + } + data->min_pixels_per_data_fifo_entry = bw_int_to_fixed(9999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->min_pixels_per_data_fifo_entry, data->pixels_per_data_fifo_entry[i])) { + data->min_pixels_per_data_fifo_entry = data->pixels_per_data_fifo_entry[i]; + } + } + } + data->sclk_deep_sleep = bw_max2(bw_div(bw_mul(data->dispclk, bw_frc_to_fixed(115, 100)), data->min_pixels_per_data_fifo_entry), data->total_read_request_bandwidth); + /*urgent, stutter and nb-p_state watermark*/ + /*the urgent watermark is the maximum of the urgent trip time plus the pixel transfer time, the urgent trip times to get data for the first pixel, and the urgent trip times to get data for the last pixel.*/ + /*the stutter exit watermark is the self refresh exit time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel. it does not apply to the writeback.*/ + /*the nb p-state change watermark is the dram speed/p-state change time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel.*/ + /*the pixel transfer time is the maximum of the time to transfer the source pixels required for the first output pixel, and the time to transfer the pixels for the last output pixel minus the active line time.*/ + /*blackout_duration is added to the urgent watermark*/ + data->chunk_request_time = bw_int_to_fixed(0); + data->cursor_request_time = bw_int_to_fixed(0); + /*compute total time to request one chunk from each active display pipe*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->chunk_request_time = bw_add(data->chunk_request_time, (bw_div((bw_div(bw_int_to_fixed(pixels_per_chunk * data->bytes_per_pixel[i]), data->useful_bytes_per_request[i])), bw_min2(sclk[data->sclk_level], bw_div(data->dispclk, bw_int_to_fixed(2)))))); + } + } + /*compute total time to request cursor data*/ + data->cursor_request_time = (bw_div(data->cursor_total_data, (bw_mul(bw_int_to_fixed(32), sclk[data->sclk_level])))); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->line_source_pixels_transfer_time = bw_max2(bw_div(bw_div(data->src_pixels_for_first_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), bw_sub(bw_div(bw_div(data->src_pixels_for_last_output_pixel[i], dceip->lb_write_pixels_per_dispclk), (bw_div(data->dispclk, dceip->display_pipe_throughput_factor))), data->active_time[i])); + if (surface_type[i] != bw_def_display_write_back420_luma && surface_type[i] != bw_def_display_write_back420_chroma) { + data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time); + data->stutter_exit_watermark[i] = bw_add(bw_sub(vbios->stutter_self_refresh_exit_latency, data->total_dmifmc_urgent_latency), data->urgent_watermark[i]); + data->stutter_entry_watermark[i] = bw_add(bw_sub(bw_add(vbios->stutter_self_refresh_exit_latency, vbios->stutter_self_refresh_entry_latency), data->total_dmifmc_urgent_latency), data->urgent_watermark[i]); + /*unconditionally remove black out time from the nb p_state watermark*/ + if ((data->display_pstate_change_enable[i] == 1)) { + data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level])); + } + else { + /*maximize the watermark to force the switch in the vb_lank region of the frame*/ + data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000); + } + } + else { + data->urgent_watermark[i] = bw_add(bw_add(bw_add(bw_add(bw_add(vbios->mcifwrmc_urgent_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->line_source_transfer_time[i][data->y_clk_level][data->sclk_level])), vbios->blackout_duration), data->chunk_request_time), data->cursor_request_time); + data->stutter_exit_watermark[i] = bw_int_to_fixed(0); + data->stutter_entry_watermark[i] = bw_int_to_fixed(0); + if ((data->display_pstate_change_enable[i] == 1)) { + data->nbp_state_change_watermark[i] = bw_add(bw_add(vbios->nbp_state_change_latency, data->mcifwr_burst_time[data->y_clk_level][data->sclk_level]), bw_max2(data->line_source_pixels_transfer_time, data->dram_speed_change_line_source_transfer_time[i][data->y_clk_level][data->sclk_level])); + } + else { + /*maximize the watermark to force the switch in the vb_lank region of the frame*/ + data->nbp_state_change_watermark[i] = bw_int_to_fixed(131000); + } + } + } + } + /*stutter mode enable*/ + /*in the multi-display case the stutter exit or entry watermark cannot exceed the minimum latency hiding capabilities of the*/ + /*display pipe.*/ + data->stutter_mode_enable = data->cpuc_state_change_enable; + if (data->number_of_displays > 1) { + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if ((bw_mtn(data->stutter_exit_watermark[i], data->minimum_latency_hiding[i]) || bw_mtn(data->stutter_entry_watermark[i], data->minimum_latency_hiding[i]))) { + data->stutter_mode_enable = bw_def_no; + } + } + } + } + /*performance metrics*/ + /* display read access efficiency (%)*/ + /* display write back access efficiency (%)*/ + /* stutter efficiency (%)*/ + /* extra underlay pitch recommended for efficiency (pixels)*/ + /* immediate flip time (us)*/ + /* latency for other clients due to urgent display read (us)*/ + /* latency for other clients due to urgent display write (us)*/ + /* average bandwidth consumed by display (no compression) (gb/s)*/ + /* required dram bandwidth (gb/s)*/ + /* required sclk (m_hz)*/ + /* required rd urgent latency (us)*/ + /* nb p-state change margin (us)*/ + /*dmif and mcifwr dram access efficiency*/ + /*is the ratio between the ideal dram access time (which is the data buffer size in memory divided by the dram bandwidth), and the actual time which is the total page close-open time. but it cannot exceed the dram efficiency provided by the memory subsystem*/ + data->dmifdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_reads_required_dram_access_data, data->dram_bandwidth), data->dmif_total_page_close_open_time), bw_int_to_fixed(1)); + if (bw_mtn(data->total_display_writes_required_dram_access_data, bw_int_to_fixed(0))) { + data->mcifwrdram_access_efficiency = bw_min2(bw_div(bw_div(data->total_display_writes_required_dram_access_data, data->dram_bandwidth), data->mcifwr_total_page_close_open_time), bw_int_to_fixed(1)); + } + else { + data->mcifwrdram_access_efficiency = bw_int_to_fixed(0); + } + /*average bandwidth*/ + /*the average bandwidth with no compression is the vertical active time is the source width times the bytes per pixel divided by the line time, multiplied by the vertical scale ratio and the ratio of bytes per request divided by the useful bytes per request.*/ + /*the average bandwidth with compression is the same, divided by the compression ratio*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->average_bandwidth_no_compression[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(data->source_width_rounded_up_to_chunks[i], bw_int_to_fixed(data->bytes_per_pixel[i])), (bw_div(data->h_total[i], data->pixel_rate[i]))), data->vsr[i]), data->bytes_per_request[i]), data->useful_bytes_per_request[i]); + data->average_bandwidth[i] = bw_div(data->average_bandwidth_no_compression[i], data->compression_rate[i]); + } + } + data->total_average_bandwidth_no_compression = bw_int_to_fixed(0); + data->total_average_bandwidth = bw_int_to_fixed(0); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->total_average_bandwidth_no_compression = bw_add(data->total_average_bandwidth_no_compression, data->average_bandwidth_no_compression[i]); + data->total_average_bandwidth = bw_add(data->total_average_bandwidth, data->average_bandwidth[i]); + } + } + /*stutter efficiency*/ + /*the stutter efficiency is the frame-average time in self-refresh divided by the frame-average stutter cycle duration. only applies if the display write-back is not enabled.*/ + /*the frame-average stutter cycle used is the minimum for all pipes of the frame-average data buffer size in time, times the compression rate*/ + /*the frame-average time in self-refresh is the stutter cycle minus the self refresh exit latency and the burst time*/ + /*the stutter cycle is the dmif buffer size reduced by the excess of the stutter exit watermark over the lb size in time.*/ + /*the burst time is the data needed during the stutter cycle divided by the available bandwidth*/ + /*compute the time read all the data from the dmif buffer to the lb (dram refresh period)*/ + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->stutter_refresh_duration[i] = bw_sub(bw_mul(bw_div(bw_div(bw_mul(bw_div(bw_div(data->adjusted_data_buffer_size[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]), bw_max2(bw_int_to_fixed(0), bw_sub(data->stutter_exit_watermark[i], bw_div(bw_mul((bw_sub(data->lb_partitions[i], bw_int_to_fixed(1))), data->h_total[i]), data->pixel_rate[i])))); + data->stutter_dmif_buffer_size[i] = bw_div(bw_mul(bw_mul(bw_div(bw_mul(bw_mul(data->stutter_refresh_duration[i], bw_int_to_fixed(data->bytes_per_pixel[i])), data->source_width_rounded_up_to_chunks[i]), data->h_total[i]), data->vsr[i]), data->pixel_rate[i]), data->compression_rate[i]); + } + } + data->min_stutter_refresh_duration = bw_int_to_fixed(9999); + data->total_stutter_dmif_buffer_size = 0; + data->total_bytes_requested = 0; + data->min_stutter_dmif_buffer_size = 9999; + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + if (bw_mtn(data->min_stutter_refresh_duration, data->stutter_refresh_duration[i])) { + data->min_stutter_refresh_duration = data->stutter_refresh_duration[i]; + data->total_bytes_requested = bw_fixed_to_int(bw_add(bw_int_to_fixed(data->total_bytes_requested), (bw_mul(bw_mul(data->source_height_rounded_up_to_chunks[i], data->source_width_rounded_up_to_chunks[i]), bw_int_to_fixed(data->bytes_per_pixel[i]))))); + data->min_stutter_dmif_buffer_size = bw_fixed_to_int(data->stutter_dmif_buffer_size[i]); + } + data->total_stutter_dmif_buffer_size = bw_fixed_to_int(bw_add(data->stutter_dmif_buffer_size[i], bw_int_to_fixed(data->total_stutter_dmif_buffer_size))); + } + } + data->stutter_burst_time = bw_div(bw_int_to_fixed(data->total_stutter_dmif_buffer_size), bw_min2(bw_mul(data->dram_bandwidth, data->dmifdram_access_efficiency), bw_mul(sclk[data->sclk_level], bw_int_to_fixed(32)))); + data->num_stutter_bursts = data->total_bytes_requested / data->min_stutter_dmif_buffer_size; + data->total_stutter_cycle_duration = bw_add(bw_add(data->min_stutter_refresh_duration, vbios->stutter_self_refresh_exit_latency), data->stutter_burst_time); + data->time_in_self_refresh = data->min_stutter_refresh_duration; + if (data->d1_display_write_back_dwb_enable == 1) { + data->stutter_efficiency = bw_int_to_fixed(0); + } + else if (bw_ltn(data->time_in_self_refresh, bw_int_to_fixed(0))) { + data->stutter_efficiency = bw_int_to_fixed(0); + } + else { + /*compute stutter efficiency assuming 60 hz refresh rate*/ + data->stutter_efficiency = bw_max2(bw_int_to_fixed(0), bw_mul((bw_sub(bw_int_to_fixed(1), (bw_div(bw_mul((bw_add(vbios->stutter_self_refresh_exit_latency, data->stutter_burst_time)), bw_int_to_fixed(data->num_stutter_bursts)), bw_frc_to_fixed(166666667, 10000))))), bw_int_to_fixed(100))); + } + /*immediate flip time*/ + /*if scatter gather is enabled, the immediate flip takes a number of urgent memory trips equivalent to the pte requests in a row divided by the pte request limit.*/ + /*otherwise, it may take just one urgenr memory trip*/ + data->worst_number_of_trips_to_memory = bw_int_to_fixed(1); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i] && data->scatter_gather_enable_for_pipe[i] == 1) { + data->number_of_trips_to_memory_for_getting_apte_row[i] = bw_ceil2(bw_div(data->scatter_gather_pte_requests_in_row[i], data->scatter_gather_pte_request_limit[i]), bw_int_to_fixed(1)); + if (bw_ltn(data->worst_number_of_trips_to_memory, data->number_of_trips_to_memory_for_getting_apte_row[i])) { + data->worst_number_of_trips_to_memory = data->number_of_trips_to_memory_for_getting_apte_row[i]; + } + } + } + data->immediate_flip_time = bw_mul(data->worst_number_of_trips_to_memory, data->total_dmifmc_urgent_latency); + /*worst latency for other clients*/ + /*it is the urgent latency plus the urgent burst time*/ + data->latency_for_non_dmif_clients = bw_add(data->total_dmifmc_urgent_latency, data->dmif_burst_time[data->y_clk_level][data->sclk_level]); + if (data->d1_display_write_back_dwb_enable == 1) { + data->latency_for_non_mcifwr_clients = bw_add(vbios->mcifwrmc_urgent_latency, dceip->mcifwr_all_surfaces_burst_time); + } + else { + data->latency_for_non_mcifwr_clients = bw_int_to_fixed(0); + } + /*dmif mc urgent latency suppported in high sclk and yclk*/ + data->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div((bw_sub(data->min_read_buffer_size_in_time, data->dmif_burst_time[high][s_high])), data->total_dmifmc_urgent_trips); + /*dram speed/p-state change margin*/ + /*in the multi-display case the nb p-state change watermark cannot exceed the average lb size plus the dmif size or the cursor dcp buffer size*/ + data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999); + data->nbp_state_dram_speed_change_latency_supported = bw_int_to_fixed(99999); + for (i = 0; i <= maximum_number_of_surfaces - 1; i++) { + if (data->enable[i]) { + data->nbp_state_dram_speed_change_latency_supported = bw_min2(data->nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(data->maximum_latency_hiding_with_cursor[i], data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency)); + data->v_blank_nbp_state_dram_speed_change_latency_supported = bw_min2(data->v_blank_nbp_state_dram_speed_change_latency_supported, bw_add(bw_sub(bw_div(bw_mul((bw_sub(data->v_total[i], bw_sub(bw_div(data->src_height[i], data->v_scale_ratio[i]), bw_int_to_fixed(4)))), data->h_total[i]), data->pixel_rate[i]), data->nbp_state_change_watermark[i]), vbios->nbp_state_change_latency)); + } + } + /*sclk required vs urgent latency*/ + for (i = 1; i <= 5; i++) { + data->display_reads_time_for_data_transfer_and_urgent_latency = bw_sub(data->min_read_buffer_size_in_time, bw_mul(data->total_dmifmc_urgent_trips, bw_int_to_fixed(i))); + if (pipe_check == bw_def_ok && (bw_mtn(data->display_reads_time_for_data_transfer_and_urgent_latency, data->dmif_total_page_close_open_time))) { + data->dmif_required_sclk_for_urgent_latency[i] = bw_div(bw_div(data->total_display_reads_required_data, data->display_reads_time_for_data_transfer_and_urgent_latency), (bw_mul(vbios->data_return_bus_width, bw_int_to_fixed(bus_efficiency)))); + } + else { + data->dmif_required_sclk_for_urgent_latency[i] = bw_int_to_fixed(bw_def_na); + } + } + /*output link bit per pixel supported*/ + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { + data->output_bpphdmi[k] = bw_def_na; + data->output_bppdp4_lane_hbr[k] = bw_def_na; + data->output_bppdp4_lane_hbr2[k] = bw_def_na; + data->output_bppdp4_lane_hbr3[k] = bw_def_na; + if (data->enable[k]) { + data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24))); + if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) { + data->output_bppdp4_lane_hbr[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(270), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + if (bw_meq(data->max_phyclk, bw_int_to_fixed(540))) { + data->output_bppdp4_lane_hbr2[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(540), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + if (bw_meq(data->max_phyclk, bw_int_to_fixed(810))) { + data->output_bppdp4_lane_hbr3[k] = bw_fixed_to_int(bw_mul(bw_div(bw_mul(bw_int_to_fixed(810), bw_int_to_fixed(4)), data->pixel_rate[k]), bw_int_to_fixed(8))); + } + } + } +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, + struct bw_calcs_vbios *bw_vbios, + enum bw_calcs_version version) +{ + struct bw_calcs_dceip dceip = { 0 }; + struct bw_calcs_vbios vbios = { 0 }; + + dceip.version = version; + + switch (version) { + case BW_CALCS_VERSION_CARRIZO: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 64; + vbios.number_of_dram_channels = 2; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(1600); + vbios.mid_yclk = bw_int_to_fixed(1600); + vbios.low_yclk = bw_frc_to_fixed(66666, 100); + vbios.low_sclk = bw_int_to_fixed(200); + vbios.mid1_sclk = bw_int_to_fixed(300); + vbios.mid2_sclk = bw_int_to_fixed(300); + vbios.mid3_sclk = bw_int_to_fixed(300); + vbios.mid4_sclk = bw_int_to_fixed(300); + vbios.mid5_sclk = bw_int_to_fixed(300); + vbios.mid6_sclk = bw_int_to_fixed(300); + vbios.high_sclk = bw_frc_to_fixed(62609, 100); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(50); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_frc_to_fixed(19649, 1000); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(18); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 3; + dceip.number_of_underlay_pipes = 1; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = false; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 2; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(82176); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(0); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/ + break; + case BW_CALCS_VERSION_POLARIS10: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 32; + vbios.number_of_dram_channels = 8; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(6000); + vbios.mid_yclk = bw_int_to_fixed(3200); + vbios.low_yclk = bw_int_to_fixed(1000); + vbios.low_sclk = bw_int_to_fixed(300); + vbios.mid1_sclk = bw_int_to_fixed(400); + vbios.mid2_sclk = bw_int_to_fixed(500); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(700); + vbios.mid5_sclk = bw_int_to_fixed(800); + vbios.mid6_sclk = bw_int_to_fixed(974); + vbios.high_sclk = bw_int_to_fixed(1154); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(48); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_int_to_fixed(45); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(0); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 6; + dceip.number_of_underlay_pipes = 0; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 4; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(245952); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(1); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + case BW_CALCS_VERSION_POLARIS11: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 32; + vbios.number_of_dram_channels = 4; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(6000); + vbios.mid_yclk = bw_int_to_fixed(3200); + vbios.low_yclk = bw_int_to_fixed(1000); + vbios.low_sclk = bw_int_to_fixed(300); + vbios.mid1_sclk = bw_int_to_fixed(400); + vbios.mid2_sclk = bw_int_to_fixed(500); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(700); + vbios.mid5_sclk = bw_int_to_fixed(800); + vbios.mid6_sclk = bw_int_to_fixed(974); + vbios.high_sclk = bw_int_to_fixed(1154); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(48); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_int_to_fixed(45); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(0); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 5; + dceip.number_of_underlay_pipes = 0; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 4; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(245952); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(1); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + case BW_CALCS_VERSION_STONEY: + vbios.memory_type = bw_def_gddr5; + vbios.dram_channel_width_in_bits = 64; + vbios.number_of_dram_channels = 1; + vbios.number_of_dram_banks = 8; + vbios.high_yclk = bw_int_to_fixed(1866); + vbios.mid_yclk = bw_int_to_fixed(1866); + vbios.low_yclk = bw_int_to_fixed(1333); + vbios.low_sclk = bw_int_to_fixed(200); + vbios.mid1_sclk = bw_int_to_fixed(600); + vbios.mid2_sclk = bw_int_to_fixed(600); + vbios.mid3_sclk = bw_int_to_fixed(600); + vbios.mid4_sclk = bw_int_to_fixed(600); + vbios.mid5_sclk = bw_int_to_fixed(600); + vbios.mid6_sclk = bw_int_to_fixed(600); + vbios.high_sclk = bw_int_to_fixed(800); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(50); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(158, 10); + vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios.nbp_state_change_latency = bw_frc_to_fixed(2008, 100); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = true; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios.blackout_duration = bw_int_to_fixed(18); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(768); + dceip.dmif_pipe_en_fbc_chunk_tracker = false; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 2; + dceip.number_of_underlay_pipes = 1; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = false; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 2; + dceip.graphics_dmif_size = 12288; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = true; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(82176); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(0); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; + default: + break; + } + *bw_dceip = dceip; + *bw_vbios = vbios; + +} + +/** + * Compare calculated (required) clocks against the clocks available at + * maximum voltage (max Performance Level). + */ +static bool is_display_configuration_supported( + const struct bw_calcs_vbios *vbios, + const struct bw_calcs_output *calcs_output) +{ + uint32_t int_max_clk; + + int_max_clk = bw_fixed_to_int(vbios->high_voltage_max_dispclk); + int_max_clk *= 1000; /* MHz to kHz */ + if (calcs_output->dispclk_khz > int_max_clk) + return false; + + int_max_clk = bw_fixed_to_int(vbios->high_sclk); + int_max_clk *= 1000; /* MHz to kHz */ + if (calcs_output->required_sclk > int_max_clk) + return false; + + return true; +} + +static void populate_initial_data( + const struct pipe_ctx pipe[], int pipe_count, struct bw_calcs_data *data) +{ + int i, j; + int num_displays = 0; + + data->underlay_surface_type = bw_def_420; + data->panning_and_bezel_adjustment = bw_def_none; + data->graphics_lb_bpc = 10; + data->underlay_lb_bpc = 8; + data->underlay_tiling_mode = bw_def_tiled; + data->graphics_tiling_mode = bw_def_tiled; + data->underlay_micro_tile_mode = bw_def_display_micro_tiling; + data->graphics_micro_tile_mode = bw_def_display_micro_tiling; + + /* Pipes with underlay first */ + for (i = 0; i < pipe_count; i++) { + if (!pipe[i].stream || !pipe[i].bottom_pipe) + continue; + + ASSERT(pipe[i].surface); + + if (num_displays == 0) { + if (!pipe[i].surface->public.visible) + data->d0_underlay_mode = bw_def_underlay_only; + else + data->d0_underlay_mode = bw_def_blend; + } else { + if (!pipe[i].surface->public.visible) + data->d1_underlay_mode = bw_def_underlay_only; + else + data->d1_underlay_mode = bw_def_blend; + } + + data->fbc_en[num_displays + 4] = false; + data->lpt_en[num_displays + 4] = false; + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + switch (pipe[i].surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270); + break; + default: + break; + } + switch (pipe[i].surface->public.format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + data->bytes_per_pixel[num_displays + 4] = 2; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + data->bytes_per_pixel[num_displays + 4] = 8; + break; + default: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + } + data->interlace_mode[num_displays + 4] = false; + data->stereo_mode[num_displays + 4] = bw_def_mono; + + + for (j = 0; j < 2; j++) { + data->fbc_en[num_displays * 2 + j] = false; + data->lpt_en[num_displays * 2 + j] = false; + + data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); + data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); + data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( + pipe[i].bottom_pipe->surface->public.plane_size.grph.surface_pitch); + data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); + data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); + data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( + pipe[i].bottom_pipe->scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( + pipe[i].bottom_pipe->scl_data.ratios.vert.value); + switch (pipe[i].bottom_pipe->surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(270); + break; + default: + break; + } + data->stereo_mode[num_displays * 2 + j] = bw_def_mono; + } + + num_displays++; + } + + /* Pipes without underlay after */ + for (i = 0; i < pipe_count; i++) { + if (!pipe[i].stream || pipe[i].bottom_pipe) + continue; + + + data->fbc_en[num_displays + 4] = false; + data->lpt_en[num_displays + 4] = false; + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + if (pipe[i].surface) { + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + switch (pipe[i].surface->public.rotation) { + case ROTATION_ANGLE_0: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + break; + case ROTATION_ANGLE_90: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(90); + break; + case ROTATION_ANGLE_180: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(180); + break; + case ROTATION_ANGLE_270: + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(270); + break; + default: + break; + } + switch (pipe[i].surface->public.format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + data->bytes_per_pixel[num_displays + 4] = 2; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + data->bytes_per_pixel[num_displays + 4] = 8; + break; + default: + data->bytes_per_pixel[num_displays + 4] = 4; + break; + } + } else { + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_addressable); + data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_addressable); + data->h_taps[num_displays + 4] = bw_int_to_fixed(1); + data->v_taps[num_displays + 4] = bw_int_to_fixed(1); + data->h_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); + data->v_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); + data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); + data->bytes_per_pixel[num_displays + 4] = 4; + } + + data->interlace_mode[num_displays + 4] = false; + data->stereo_mode[num_displays + 4] = bw_def_mono; + num_displays++; + } + + data->number_of_displays = num_displays; +} + +/** + * Return: + * true - Display(s) configuration supported. + * In this case 'calcs_output' contains data for HW programming + * false - Display(s) configuration not supported (not enough bandwidth). + */ + +bool bw_calcs(struct dc_context *ctx, + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + const struct pipe_ctx pipe[], + int pipe_count, + struct bw_calcs_output *calcs_output) +{ + struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data)); + + populate_initial_data(pipe, pipe_count, data); + + /*TODO: this should be taken out calcs output and assigned during timing sync for pplib use*/ + calcs_output->all_displays_in_sync = false; + + if (data->number_of_displays != 0) { + uint8_t yclk_lvl, sclk_lvl; + struct bw_fixed high_sclk = vbios->high_sclk; + struct bw_fixed mid1_sclk = vbios->mid1_sclk; + struct bw_fixed mid2_sclk = vbios->mid2_sclk; + struct bw_fixed mid3_sclk = vbios->mid3_sclk; + struct bw_fixed mid4_sclk = vbios->mid4_sclk; + struct bw_fixed mid5_sclk = vbios->mid5_sclk; + struct bw_fixed mid6_sclk = vbios->mid6_sclk; + struct bw_fixed low_sclk = vbios->low_sclk; + struct bw_fixed high_yclk = vbios->high_yclk; + struct bw_fixed mid_yclk = vbios->mid_yclk; + struct bw_fixed low_yclk = vbios->low_yclk; + + calculate_bandwidth(dceip, vbios, data); + + yclk_lvl = data->y_clk_level; + sclk_lvl = data->sclk_level; + + calcs_output->nbp_state_change_enable = + data->nbp_state_change_enable; + calcs_output->cpuc_state_change_enable = + data->cpuc_state_change_enable; + calcs_output->cpup_state_change_enable = + data->cpup_state_change_enable; + calcs_output->stutter_mode_enable = + data->stutter_mode_enable; + calcs_output->dispclk_khz = + bw_fixed_to_int(bw_mul(data->dispclk, + bw_int_to_fixed(1000))); + calcs_output->blackout_recovery_time_us = + bw_fixed_to_int(data->blackout_recovery_time); + calcs_output->required_sclk = + bw_fixed_to_int(bw_mul(data->required_sclk, + bw_int_to_fixed(1000))); + calcs_output->required_sclk_deep_sleep = + bw_fixed_to_int(bw_mul(data->sclk_deep_sleep, + bw_int_to_fixed(1000))); + if (yclk_lvl == 0) + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(low_yclk, bw_int_to_fixed(1000))); + else if (yclk_lvl == 1) + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(mid_yclk, bw_int_to_fixed(1000))); + else + calcs_output->required_yclk = bw_fixed_to_int( + bw_mul(high_yclk, bw_int_to_fixed(1000))); + + /* units: nanosecond, 16bit storage. */ + + calcs_output->nbp_state_change_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->stutter_exit_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->urgent_wm_ns[0].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].a_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + if (dceip->version != BW_CALCS_VERSION_CARRIZO) { + ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk; + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4],bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->stutter_exit_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + + calcs_output->urgent_wm_ns[0].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].b_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk; + ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk; + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + + calcs_output->stutter_exit_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + calcs_output->urgent_wm_ns[0].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].c_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + } + + if (dceip->version == BW_CALCS_VERSION_CARRIZO) { + ((struct bw_calcs_vbios *)vbios)->low_yclk = high_yclk; + ((struct bw_calcs_vbios *)vbios)->mid_yclk = high_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid3_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid4_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid5_sclk = high_sclk; + ((struct bw_calcs_vbios *)vbios)->mid6_sclk = high_sclk; + } else { + ((struct bw_calcs_vbios *)vbios)->low_yclk = mid_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid3_sclk; + } + + calculate_bandwidth(dceip, vbios, data); + + calcs_output->nbp_state_change_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[4], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[5], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->nbp_state_change_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[0], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->nbp_state_change_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[7], bw_int_to_fixed(1000))); + calcs_output->nbp_state_change_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->nbp_state_change_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + nbp_state_change_watermark[9], bw_int_to_fixed(1000))); + + calcs_output->stutter_exit_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_exit_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[0], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_exit_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[7], bw_int_to_fixed(1000))); + calcs_output->stutter_exit_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->stutter_exit_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + stutter_exit_watermark[9], bw_int_to_fixed(1000))); + + + calcs_output->urgent_wm_ns[0].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[4], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[1].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[5], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[2].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->urgent_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[0], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[1], bw_int_to_fixed(1000))); + } else { + calcs_output->urgent_wm_ns[3].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[7], bw_int_to_fixed(1000))); + calcs_output->urgent_wm_ns[4].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[8], bw_int_to_fixed(1000))); + } + calcs_output->urgent_wm_ns[5].d_mark = + bw_fixed_to_int(bw_mul(data-> + urgent_watermark[9], bw_int_to_fixed(1000))); + + ((struct bw_calcs_vbios *)vbios)->low_yclk = low_yclk; + ((struct bw_calcs_vbios *)vbios)->mid_yclk = mid_yclk; + ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk; + ((struct bw_calcs_vbios *)vbios)->mid1_sclk = mid1_sclk; + ((struct bw_calcs_vbios *)vbios)->mid2_sclk = mid2_sclk; + ((struct bw_calcs_vbios *)vbios)->mid3_sclk = mid3_sclk; + ((struct bw_calcs_vbios *)vbios)->mid4_sclk = mid4_sclk; + ((struct bw_calcs_vbios *)vbios)->mid5_sclk = mid5_sclk; + ((struct bw_calcs_vbios *)vbios)->mid6_sclk = mid6_sclk; + ((struct bw_calcs_vbios *)vbios)->high_sclk = high_sclk; + } else { + calcs_output->nbp_state_change_enable = true; + calcs_output->cpuc_state_change_enable = true; + calcs_output->cpup_state_change_enable = true; + calcs_output->stutter_mode_enable = true; + calcs_output->dispclk_khz = 0; + calcs_output->required_sclk = 0; + } + + dm_free(data); + + return is_display_configuration_supported(vbios, calcs_output); +} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c new file mode 100644 index 000000000000..fbf2adcc5ff8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c @@ -0,0 +1,299 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "bw_fixed.h" + +#define BITS_PER_FRACTIONAL_PART 24 + +#define MIN_I32 \ + (int64_t)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART))) + +#define MAX_I32 \ + (int64_t)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1) + +#define MIN_I64 \ + (int64_t)(-(1LL << 63)) + +#define MAX_I64 \ + (int64_t)((1ULL << 63) - 1) + +#define FRACTIONAL_PART_MASK \ + ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) + +#define GET_INTEGER_PART(x) \ + ((x) >> BITS_PER_FRACTIONAL_PART) + +#define GET_FRACTIONAL_PART(x) \ + (FRACTIONAL_PART_MASK & (x)) + +static uint64_t abs_i64(int64_t arg) +{ + if (arg >= 0) + return (uint64_t)(arg); + else + return (uint64_t)(-arg); +} + +struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) +{ + return bw_min2(bw_min2(v1, v2), v3); +} + +struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) +{ + return bw_max2(bw_max2(v1, v2), v3); +} + +struct bw_fixed bw_int_to_fixed(int64_t value) +{ + struct bw_fixed res; + ASSERT(value < MAX_I32 && value > MIN_I32); + res.value = value << BITS_PER_FRACTIONAL_PART; + return res; +} + +int32_t bw_fixed_to_int(struct bw_fixed value) +{ + return GET_INTEGER_PART(value.value); +} + +struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) +{ + struct bw_fixed res; + bool arg1_negative = numerator < 0; + bool arg2_negative = denominator < 0; + uint64_t arg1_value; + uint64_t arg2_value; + uint64_t remainder; + + /* determine integer part */ + uint64_t res_value; + + ASSERT(denominator != 0); + + arg1_value = abs_i64(numerator); + arg2_value = abs_i64(denominator); + res_value = div64_u64_rem(arg1_value, arg2_value, &remainder); + + ASSERT(res_value <= MAX_I32); + + /* determine fractional part */ + { + uint32_t i = BITS_PER_FRACTIONAL_PART; + + do + { + remainder <<= 1; + + res_value <<= 1; + + if (remainder >= arg2_value) + { + res_value |= 1; + remainder -= arg2_value; + } + } while (--i != 0); + } + + /* round up LSB */ + { + uint64_t summand = (remainder << 1) >= arg2_value; + + ASSERT(res_value <= MAX_I64 - summand); + + res_value += summand; + } + + res.value = (int64_t)(res_value); + + if (arg1_negative ^ arg2_negative) + res.value = -res.value; + return res; +} + +struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return (arg1.value <= arg2.value) ? arg1 : arg2; +} + +struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return (arg2.value <= arg1.value) ? arg1 : arg2; +} + +struct bw_fixed bw_floor2( + const struct bw_fixed arg, + const struct bw_fixed significance) +{ + struct bw_fixed result; + int64_t multiplicand; + + multiplicand = div64_s64(arg.value, abs_i64(significance.value)); + result.value = abs_i64(significance.value) * multiplicand; + ASSERT(abs_i64(result.value) <= abs_i64(arg.value)); + return result; +} + +struct bw_fixed bw_ceil2( + const struct bw_fixed arg, + const struct bw_fixed significance) +{ + struct bw_fixed result; + int64_t multiplicand; + + multiplicand = div64_s64(arg.value, abs_i64(significance.value)); + result.value = abs_i64(significance.value) * multiplicand; + if (abs_i64(result.value) < abs_i64(arg.value)) { + if (arg.value < 0) + result.value -= abs_i64(significance.value); + else + result.value += abs_i64(significance.value); + } + return result; +} + +struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + + res.value = arg1.value + arg2.value; + + return res; +} + +struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + + res.value = arg1.value - arg2.value; + + return res; +} + +struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + + bool arg1_negative = arg1.value < 0; + bool arg2_negative = arg2.value < 0; + + uint64_t arg1_value = abs_i64(arg1.value); + uint64_t arg2_value = abs_i64(arg2.value); + + uint64_t arg1_int = GET_INTEGER_PART(arg1_value); + uint64_t arg2_int = GET_INTEGER_PART(arg2_value); + + uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value); + uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value); + + uint64_t tmp; + + res.value = arg1_int * arg2_int; + + ASSERT(res.value <= MAX_I32); + + res.value <<= BITS_PER_FRACTIONAL_PART; + + tmp = arg1_int * arg2_fra; + + ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value)); + + res.value += tmp; + + tmp = arg2_int * arg1_fra; + + ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value)); + + res.value += tmp; + + tmp = arg1_fra * arg2_fra; + + tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + (tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value)); + + ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value)); + + res.value += tmp; + + if (arg1_negative ^ arg2_negative) + res.value = -res.value; + return res; +} + +struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res = bw_frc_to_fixed(arg1.value, arg2.value); + return res; +} + +struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + div64_u64_rem(arg1.value, arg2.value, &res.value); + return res; +} +struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw) +{ + struct bw_fixed result = { 0 }; + + if (raw < 0) { + raw = -raw; + result.value = -(raw >> (32 - BITS_PER_FRACTIONAL_PART)); + } else { + result.value = raw >> (32 - BITS_PER_FRACTIONAL_PART); + } + + return result; +} + +bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value == arg2.value; +} + +bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value != arg2.value; +} + +bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value <= arg2.value; +} + +bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value >= arg2.value; +} + +bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value < arg2.value; +} + +bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value > arg2.value; +} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c new file mode 100644 index 000000000000..854796aa0c71 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -0,0 +1,1382 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "gamma_calcs.h" + +struct curve_config { + uint32_t offset; + int8_t segments[16]; + int8_t begin; +}; + +static bool build_custom_float( + struct fixed31_32 value, + const struct custom_float_format *format, + bool *negative, + uint32_t *mantissa, + uint32_t *exponenta) +{ + uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; + + const struct fixed31_32 mantissa_constant_plus_max_fraction = + dal_fixed31_32_from_fraction( + (1LL << (format->mantissa_bits + 1)) - 1, + 1LL << format->mantissa_bits); + + struct fixed31_32 mantiss; + + if (dal_fixed31_32_eq( + value, + dal_fixed31_32_zero)) { + *negative = false; + *mantissa = 0; + *exponenta = 0; + return true; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_zero)) { + *negative = format->sign; + value = dal_fixed31_32_neg(value); + } else { + *negative = false; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shl(value, 1); + ++i; + } while (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)); + + --i; + + if (exp_offset <= i) { + *mantissa = 0; + *exponenta = 0; + return true; + } + + *exponenta = exp_offset - i; + } else if (dal_fixed31_32_le( + mantissa_constant_plus_max_fraction, + value)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shr(value, 1); + ++i; + } while (dal_fixed31_32_lt( + mantissa_constant_plus_max_fraction, + value)); + + *exponenta = exp_offset + i - 1; + } else { + *exponenta = exp_offset; + } + + mantiss = dal_fixed31_32_sub( + value, + dal_fixed31_32_one); + + if (dal_fixed31_32_lt( + mantiss, + dal_fixed31_32_zero) || + dal_fixed31_32_lt( + dal_fixed31_32_one, + mantiss)) + mantiss = dal_fixed31_32_zero; + else + mantiss = dal_fixed31_32_shl( + mantiss, + format->mantissa_bits); + + *mantissa = dal_fixed31_32_floor(mantiss); + + return true; +} + +static bool setup_custom_float( + const struct custom_float_format *format, + bool negative, + uint32_t mantissa, + uint32_t exponenta, + uint32_t *result) +{ + uint32_t i = 0; + uint32_t j = 0; + + uint32_t value = 0; + + /* verification code: + * once calculation is ok we can remove it + */ + + const uint32_t mantissa_mask = + (1 << (format->mantissa_bits + 1)) - 1; + + const uint32_t exponenta_mask = + (1 << (format->exponenta_bits + 1)) - 1; + + if (mantissa & ~mantissa_mask) { + BREAK_TO_DEBUGGER(); + mantissa = mantissa_mask; + } + + if (exponenta & ~exponenta_mask) { + BREAK_TO_DEBUGGER(); + exponenta = exponenta_mask; + } + + /* end of verification code */ + + while (i < format->mantissa_bits) { + uint32_t mask = 1 << i; + + if (mantissa & mask) + value |= mask; + + ++i; + } + + while (j < format->exponenta_bits) { + uint32_t mask = 1 << j; + + if (exponenta & mask) + value |= mask << i; + + ++j; + } + + if (negative && format->sign) + value |= 1 << (i + j); + + *result = value; + + return true; +} + +static bool convert_to_custom_float_format_ex( + struct fixed31_32 value, + const struct custom_float_format *format, + struct custom_float_value *result) +{ + return build_custom_float( + value, format, + &result->negative, &result->mantissa, &result->exponenta) && + setup_custom_float( + format, result->negative, result->mantissa, result->exponenta, + &result->value); +} + +static bool round_custom_float_6_12( + struct hw_x_point *x) +{ + struct custom_float_format fmt; + + struct custom_float_value value; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = true; + + if (!convert_to_custom_float_format_ex( + x->x, &fmt, &value)) + return false; + + x->adjusted_x = x->x; + + if (value.mantissa) { + BREAK_TO_DEBUGGER(); + + return false; + } + + return true; +} + +static bool build_hw_curve_configuration( + const struct curve_config *curve_config, + struct gamma_curve *gamma_curve, + struct curve_points *curve_points, + struct hw_x_point *points, + uint32_t *number_of_points) +{ + const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments); + + int8_t i; + + uint8_t segments_calculation[8] = { 0 }; + + struct fixed31_32 region1 = dal_fixed31_32_zero; + struct fixed31_32 region2; + struct fixed31_32 increment; + + uint32_t index = 0; + uint32_t segments = 0; + uint32_t max_number; + + bool result = false; + + if (!number_of_points) { + BREAK_TO_DEBUGGER(); + return false; + } + + max_number = *number_of_points; + + i = 0; + + while (i != max_regions_number) { + gamma_curve[i].offset = 0; + gamma_curve[i].segments_num = 0; + + ++i; + } + + i = 0; + + while (i != max_regions_number) { + /* number should go in uninterruptible sequence */ + if (curve_config->segments[i] == -1) + break; + + ASSERT(curve_config->segments[i] >= 0); + + segments += (1 << curve_config->segments[i]); + + ++i; + } + + if (segments > max_number) { + BREAK_TO_DEBUGGER(); + } else { + int32_t divisor; + uint32_t offset = 0; + int8_t begin = curve_config->begin; + int32_t region_number = 0; + + i = begin; + + while ((index < max_number) && + (region_number < max_regions_number) && + (i <= 1)) { + int32_t j = 0; + + segments = curve_config->segments[region_number]; + divisor = 1 << segments; + + if (segments == -1) { + if (i > 0) { + region1 = dal_fixed31_32_shl( + dal_fixed31_32_one, + i - 1); + region2 = dal_fixed31_32_shl( + dal_fixed31_32_one, + i); + } else { + region1 = dal_fixed31_32_shr( + dal_fixed31_32_one, + -(i - 1)); + region2 = dal_fixed31_32_shr( + dal_fixed31_32_one, + -i); + } + + break; + } + + if (i > -1) { + region1 = dal_fixed31_32_shl( + dal_fixed31_32_one, + i); + region2 = dal_fixed31_32_shl( + dal_fixed31_32_one, + i + 1); + } else { + region1 = dal_fixed31_32_shr( + dal_fixed31_32_one, + -i); + region2 = dal_fixed31_32_shr( + dal_fixed31_32_one, + -(i + 1)); + } + + gamma_curve[region_number].offset = offset; + gamma_curve[region_number].segments_num = segments; + + offset += divisor; + + ++segments_calculation[segments]; + + increment = dal_fixed31_32_div_int( + dal_fixed31_32_sub( + region2, + region1), + divisor); + + points[index].x = region1; + + round_custom_float_6_12(points + index); + + ++index; + ++region_number; + + while ((index < max_number) && (j < divisor - 1)) { + region1 = dal_fixed31_32_add( + region1, + increment); + + points[index].x = region1; + points[index].adjusted_x = region1; + + ++index; + ++j; + } + + ++i; + } + + points[index].x = region1; + + round_custom_float_6_12(points + index); + + *number_of_points = index; + + result = true; + } + + curve_points[0].x = points[0].adjusted_x; + curve_points[0].offset = dal_fixed31_32_zero; + + curve_points[1].x = points[index - 1].adjusted_x; + curve_points[1].offset = dal_fixed31_32_zero; + + curve_points[2].x = points[index].adjusted_x; + curve_points[2].offset = dal_fixed31_32_zero; + + return result; +} + +static bool setup_distribution_points( + struct gamma_curve *arr_curve_points, + struct curve_points *arr_points, + uint32_t *hw_points_num, + struct hw_x_point *coordinates_x) +{ + struct curve_config cfg; + + cfg.offset = 0; + cfg.segments[0] = 3; + cfg.segments[1] = 4; + cfg.segments[2] = 4; + cfg.segments[3] = 4; + cfg.segments[4] = 4; + cfg.segments[5] = 4; + cfg.segments[6] = 4; + cfg.segments[7] = 4; + cfg.segments[8] = 5; + cfg.segments[9] = 5; + cfg.segments[10] = 0; + cfg.segments[11] = -1; + cfg.segments[12] = -1; + cfg.segments[13] = -1; + cfg.segments[14] = -1; + cfg.segments[15] = -1; + + cfg.begin = -10; + + if (!build_hw_curve_configuration( + &cfg, arr_curve_points, + arr_points, + coordinates_x, hw_points_num)) { + ASSERT_CRITICAL(false); + return false; + } + return true; +} + +struct dividers { + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; +}; + +static void build_regamma_coefficients(struct gamma_coefficients *coefficients) +{ + /* sRGB should apply 2.4 */ + static const int32_t numerator01[3] = { 31308, 31308, 31308 }; + static const int32_t numerator02[3] = { 12920, 12920, 12920 }; + static const int32_t numerator03[3] = { 55, 55, 55 }; + static const int32_t numerator04[3] = { 55, 55, 55 }; + static const int32_t numerator05[3] = { 2400, 2400, 2400 }; + + const int32_t *numerator1; + const int32_t *numerator2; + const int32_t *numerator3; + const int32_t *numerator4; + const int32_t *numerator5; + + uint32_t i = 0; + + numerator1 = numerator01; + numerator2 = numerator02; + numerator3 = numerator03; + numerator4 = numerator04; + numerator5 = numerator05; + + do { + coefficients->a0[i] = dal_fixed31_32_from_fraction( + numerator1[i], 10000000); + coefficients->a1[i] = dal_fixed31_32_from_fraction( + numerator2[i], 1000); + coefficients->a2[i] = dal_fixed31_32_from_fraction( + numerator3[i], 1000); + coefficients->a3[i] = dal_fixed31_32_from_fraction( + numerator4[i], 1000); + coefficients->user_gamma[i] = dal_fixed31_32_from_fraction( + numerator5[i], 1000); + + ++i; + } while (i != ARRAY_SIZE(coefficients->a0)); +} + +static struct fixed31_32 translate_from_linear_space( + struct fixed31_32 arg, + struct fixed31_32 a0, + struct fixed31_32 a1, + struct fixed31_32 a2, + struct fixed31_32 a3, + struct fixed31_32 gamma) +{ + const struct fixed31_32 one = dal_fixed31_32_from_int(1); + + if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0))) + return dal_fixed31_32_sub( + a2, + dal_fixed31_32_mul( + dal_fixed31_32_add( + one, + a3), + dal_fixed31_32_pow( + dal_fixed31_32_neg(arg), + dal_fixed31_32_recip(gamma)))); + else if (dal_fixed31_32_le(a0, arg)) + return dal_fixed31_32_sub( + dal_fixed31_32_mul( + dal_fixed31_32_add( + one, + a3), + dal_fixed31_32_pow( + arg, + dal_fixed31_32_recip(gamma))), + a2); + else + return dal_fixed31_32_mul( + arg, + a1); +} + +static inline struct fixed31_32 translate_from_linear_space_ex( + struct fixed31_32 arg, + struct gamma_coefficients *coeff, + uint32_t color_index) +{ + return translate_from_linear_space( + arg, + coeff->a0[color_index], + coeff->a1[color_index], + coeff->a2[color_index], + coeff->a3[color_index], + coeff->user_gamma[color_index]); +} + +static bool find_software_points( + const struct gamma_pixel *axis_x_256, + struct fixed31_32 hw_point, + enum channel_name channel, + uint32_t *index_to_start, + uint32_t *index_left, + uint32_t *index_right, + enum hw_point_position *pos) +{ + const uint32_t max_number = RGB_256X3X16 + 3; + + struct fixed31_32 left, right; + + uint32_t i = *index_to_start; + + while (i < max_number) { + if (channel == CHANNEL_NAME_RED) { + left = axis_x_256[i].r; + + if (i < max_number - 1) + right = axis_x_256[i + 1].r; + else + right = axis_x_256[max_number - 1].r; + } else if (channel == CHANNEL_NAME_GREEN) { + left = axis_x_256[i].g; + + if (i < max_number - 1) + right = axis_x_256[i + 1].g; + else + right = axis_x_256[max_number - 1].g; + } else { + left = axis_x_256[i].b; + + if (i < max_number - 1) + right = axis_x_256[i + 1].b; + else + right = axis_x_256[max_number - 1].b; + } + + if (dal_fixed31_32_le(left, hw_point) && + dal_fixed31_32_le(hw_point, right)) { + *index_to_start = i; + *index_left = i; + + if (i < max_number - 1) + *index_right = i + 1; + else + *index_right = max_number - 1; + + *pos = HW_POINT_POSITION_MIDDLE; + + return true; + } else if ((i == *index_to_start) && + dal_fixed31_32_le(hw_point, left)) { + *index_to_start = i; + *index_left = i; + *index_right = i; + + *pos = HW_POINT_POSITION_LEFT; + + return true; + } else if ((i == max_number - 1) && + dal_fixed31_32_le(right, hw_point)) { + *index_to_start = i; + *index_left = i; + *index_right = i; + + *pos = HW_POINT_POSITION_RIGHT; + + return true; + } + + ++i; + } + + return false; +} + +static bool build_custom_gamma_mapping_coefficients_worker( + struct pixel_gamma_point *coeff, + const struct hw_x_point *coordinates_x, + const struct gamma_pixel *axis_x_256, + enum channel_name channel, + uint32_t number_of_points, + enum surface_pixel_format pixel_format) +{ + uint32_t i = 0; + + while (i <= number_of_points) { + struct fixed31_32 coord_x; + + uint32_t index_to_start = 0; + uint32_t index_left = 0; + uint32_t index_right = 0; + + enum hw_point_position hw_pos; + + struct gamma_point *point; + + struct fixed31_32 left_pos; + struct fixed31_32 right_pos; + + /* + * TODO: confirm enum in surface_pixel_format + * if (pixel_format == PIXEL_FORMAT_FP16) + *coord_x = coordinates_x[i].adjusted_x; + *else + */ + if (channel == CHANNEL_NAME_RED) + coord_x = coordinates_x[i].regamma_y_red; + else if (channel == CHANNEL_NAME_GREEN) + coord_x = coordinates_x[i].regamma_y_green; + else + coord_x = coordinates_x[i].regamma_y_blue; + + if (!find_software_points( + axis_x_256, coord_x, channel, + &index_to_start, &index_left, &index_right, &hw_pos)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (index_left >= RGB_256X3X16 + 3) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (index_right >= RGB_256X3X16 + 3) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (channel == CHANNEL_NAME_RED) { + point = &coeff[i].r; + + left_pos = axis_x_256[index_left].r; + right_pos = axis_x_256[index_right].r; + } else if (channel == CHANNEL_NAME_GREEN) { + point = &coeff[i].g; + + left_pos = axis_x_256[index_left].g; + right_pos = axis_x_256[index_right].g; + } else { + point = &coeff[i].b; + + left_pos = axis_x_256[index_left].b; + right_pos = axis_x_256[index_right].b; + } + + if (hw_pos == HW_POINT_POSITION_MIDDLE) + point->coeff = dal_fixed31_32_div( + dal_fixed31_32_sub( + coord_x, + left_pos), + dal_fixed31_32_sub( + right_pos, + left_pos)); + else if (hw_pos == HW_POINT_POSITION_LEFT) + point->coeff = dal_fixed31_32_zero; + else if (hw_pos == HW_POINT_POSITION_RIGHT) + point->coeff = dal_fixed31_32_from_int(2); + else { + BREAK_TO_DEBUGGER(); + return false; + } + + point->left_index = index_left; + point->right_index = index_right; + point->pos = hw_pos; + + ++i; + } + + return true; +} + +static inline bool build_oem_custom_gamma_mapping_coefficients( + struct pixel_gamma_point *coeff128_oem, + const struct hw_x_point *coordinates_x, + const struct gamma_pixel *axis_x_256, + uint32_t number_of_points, + enum surface_pixel_format pixel_format) +{ + int i; + + for (i = 0; i < 3; i++) { + if (!build_custom_gamma_mapping_coefficients_worker( + coeff128_oem, coordinates_x, axis_x_256, i, + number_of_points, pixel_format)) + return false; + } + return true; +} + +static struct fixed31_32 calculate_mapped_value( + struct pwl_float_data *rgb, + const struct pixel_gamma_point *coeff, + enum channel_name channel, + uint32_t max_index) +{ + const struct gamma_point *point; + + struct fixed31_32 result; + + if (channel == CHANNEL_NAME_RED) + point = &coeff->r; + else if (channel == CHANNEL_NAME_GREEN) + point = &coeff->g; + else + point = &coeff->b; + + if ((point->left_index < 0) || (point->left_index > max_index)) { + BREAK_TO_DEBUGGER(); + return dal_fixed31_32_zero; + } + + if ((point->right_index < 0) || (point->right_index > max_index)) { + BREAK_TO_DEBUGGER(); + return dal_fixed31_32_zero; + } + + if (point->pos == HW_POINT_POSITION_MIDDLE) + if (channel == CHANNEL_NAME_RED) + result = dal_fixed31_32_add( + dal_fixed31_32_mul( + point->coeff, + dal_fixed31_32_sub( + rgb[point->right_index].r, + rgb[point->left_index].r)), + rgb[point->left_index].r); + else if (channel == CHANNEL_NAME_GREEN) + result = dal_fixed31_32_add( + dal_fixed31_32_mul( + point->coeff, + dal_fixed31_32_sub( + rgb[point->right_index].g, + rgb[point->left_index].g)), + rgb[point->left_index].g); + else + result = dal_fixed31_32_add( + dal_fixed31_32_mul( + point->coeff, + dal_fixed31_32_sub( + rgb[point->right_index].b, + rgb[point->left_index].b)), + rgb[point->left_index].b); + else if (point->pos == HW_POINT_POSITION_LEFT) { + BREAK_TO_DEBUGGER(); + result = dal_fixed31_32_zero; + } else { + BREAK_TO_DEBUGGER(); + result = dal_fixed31_32_one; + } + + return result; +} + +static inline struct fixed31_32 calculate_oem_mapped_value( + struct pwl_float_data *rgb_oem, + const struct pixel_gamma_point *coeff, + uint32_t index, + enum channel_name channel, + uint32_t max_index) +{ + return calculate_mapped_value( + rgb_oem, + coeff + index, + channel, + max_index); +} + +static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, + struct pwl_float_data *rgb_oem, + struct pixel_gamma_point *coeff128_oem, + const struct core_gamma *ramp, + const struct core_surface *surface, + uint32_t hw_points_num, + const struct hw_x_point *coordinate_x, + const struct gamma_pixel *axis_x, + struct dividers dividers) +{ + uint32_t i; + + struct gamma_coefficients coeff; + struct pwl_float_data_ex *rgb = rgb_regamma; + const struct hw_x_point *coord_x = coordinate_x; + + build_regamma_coefficients(&coeff); + + /* Use opp110->regamma.coordinates_x to retrieve + * coordinates chosen base on given user curve (future task). + * The x values are exponentially distributed and currently + * it is hard-coded, the user curve shape is ignored. + * The future task is to recalculate opp110- + * regamma.coordinates_x based on input/user curve, + * translation from 256/1025 to 128 pwl points. + */ + + i = 0; + + while (i != hw_points_num + 1) { + rgb->r = translate_from_linear_space_ex( + coord_x->adjusted_x, &coeff, 0); + rgb->g = translate_from_linear_space_ex( + coord_x->adjusted_x, &coeff, 1); + rgb->b = translate_from_linear_space_ex( + coord_x->adjusted_x, &coeff, 2); + + ++coord_x; + ++rgb; + ++i; + } +} + +static bool scale_gamma(struct pwl_float_data *pwl_rgb, + const struct core_gamma *ramp, + struct dividers dividers) +{ + const struct dc_gamma_ramp_rgb256x3x16 *gamma; + const uint16_t max_driver = 0xFFFF; + const uint16_t max_os = 0xFF00; + uint16_t scaler = max_os; + uint32_t i; + struct pwl_float_data *rgb = pwl_rgb; + struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; + + if (ramp->public.type == GAMMA_RAMP_RBG256X3X16) + gamma = &ramp->public.gamma_ramp_rgb256x3x16; + else + return false; /* invalid option */ + + i = 0; + + do { + if ((gamma->red[i] > max_os) || + (gamma->green[i] > max_os) || + (gamma->blue[i] > max_os)) { + scaler = max_driver; + break; + } + ++i; + } while (i != RGB_256X3X16); + + i = 0; + + do { + rgb->r = dal_fixed31_32_from_fraction( + gamma->red[i], scaler); + rgb->g = dal_fixed31_32_from_fraction( + gamma->green[i], scaler); + rgb->b = dal_fixed31_32_from_fraction( + gamma->blue[i], scaler); + + ++rgb; + ++i; + } while (i != RGB_256X3X16); + + rgb->r = dal_fixed31_32_mul(rgb_last->r, + dividers.divider1); + rgb->g = dal_fixed31_32_mul(rgb_last->g, + dividers.divider1); + rgb->b = dal_fixed31_32_mul(rgb_last->b, + dividers.divider1); + + ++rgb; + + rgb->r = dal_fixed31_32_mul(rgb_last->r, + dividers.divider2); + rgb->g = dal_fixed31_32_mul(rgb_last->g, + dividers.divider2); + rgb->b = dal_fixed31_32_mul(rgb_last->b, + dividers.divider2); + + ++rgb; + + rgb->r = dal_fixed31_32_mul(rgb_last->r, + dividers.divider3); + rgb->g = dal_fixed31_32_mul(rgb_last->g, + dividers.divider3); + rgb->b = dal_fixed31_32_mul(rgb_last->b, + dividers.divider3); + + return true; +} + +static void build_evenly_distributed_points( + struct gamma_pixel *points, + uint32_t numberof_points, + struct fixed31_32 max_value, + struct dividers dividers) +{ + struct gamma_pixel *p = points; + struct gamma_pixel *p_last = p + numberof_points - 1; + + uint32_t i = 0; + + do { + struct fixed31_32 value = dal_fixed31_32_div_int( + dal_fixed31_32_mul_int(max_value, i), + numberof_points - 1); + + p->r = value; + p->g = value; + p->b = value; + + ++p; + ++i; + } while (i != numberof_points); + + p->r = dal_fixed31_32_div(p_last->r, dividers.divider1); + p->g = dal_fixed31_32_div(p_last->g, dividers.divider1); + p->b = dal_fixed31_32_div(p_last->b, dividers.divider1); + + ++p; + + p->r = dal_fixed31_32_div(p_last->r, dividers.divider2); + p->g = dal_fixed31_32_div(p_last->g, dividers.divider2); + p->b = dal_fixed31_32_div(p_last->b, dividers.divider2); + + ++p; + + p->r = dal_fixed31_32_div(p_last->r, dividers.divider3); + p->g = dal_fixed31_32_div(p_last->g, dividers.divider3); + p->b = dal_fixed31_32_div(p_last->b, dividers.divider3); +} + +static inline void copy_rgb_regamma_to_coordinates_x( + struct hw_x_point *coordinates_x, + uint32_t hw_points_num, + const struct pwl_float_data_ex *rgb_ex) +{ + struct hw_x_point *coords = coordinates_x; + uint32_t i = 0; + const struct pwl_float_data_ex *rgb_regamma = rgb_ex; + + while (i <= hw_points_num) { + coords->regamma_y_red = rgb_regamma->r; + coords->regamma_y_green = rgb_regamma->g; + coords->regamma_y_blue = rgb_regamma->b; + + ++coords; + ++rgb_regamma; + ++i; + } +} + +static bool calculate_interpolated_hardware_curve( + struct pwl_result_data *rgb, + struct pixel_gamma_point *coeff128, + struct pwl_float_data *rgb_user, + const struct hw_x_point *coordinates_x, + const struct gamma_pixel *axis_x_256, + uint32_t number_of_points, + enum surface_pixel_format pixel_format) +{ + + const struct pixel_gamma_point *coeff; + struct pixel_gamma_point *coeff_128 = coeff128; + uint32_t max_entries = 3 - 1; + struct pwl_result_data *rgb_resulted = rgb; + + uint32_t i = 0; + + if (!build_oem_custom_gamma_mapping_coefficients( + coeff_128, coordinates_x, axis_x_256, + number_of_points, + pixel_format)) + return false; + + coeff = coeff128; + max_entries += RGB_256X3X16; + + /* TODO: float point case */ + + while (i <= number_of_points) { + rgb_resulted->red = calculate_mapped_value( + rgb_user, coeff, CHANNEL_NAME_RED, max_entries); + rgb_resulted->green = calculate_mapped_value( + rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries); + rgb_resulted->blue = calculate_mapped_value( + rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries); + + ++coeff; + ++rgb_resulted; + ++i; + } + + return true; +} + +static bool map_regamma_hw_to_x_user( + struct pixel_gamma_point *coeff128, + struct pwl_float_data *rgb_oem, + struct pwl_result_data *rgb_resulted, + struct pwl_float_data *rgb_user, + struct hw_x_point *coords_x, + const struct gamma_pixel *axis_x, + const struct dc_gamma *gamma, + const struct pwl_float_data_ex *rgb_regamma, + struct dividers dividers, + uint32_t hw_points_num, + const struct core_surface *surface) +{ + /* setup to spare calculated ideal regamma values */ + + struct pixel_gamma_point *coeff = coeff128; + + struct hw_x_point *coords = coords_x; + + copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma); + + return calculate_interpolated_hardware_curve( + rgb_resulted, coeff, rgb_user, coords, axis_x, + hw_points_num, surface->public.format); +} + +static void build_new_custom_resulted_curve( + struct pwl_result_data *rgb_resulted, + uint32_t hw_points_num) +{ + struct pwl_result_data *rgb = rgb_resulted; + struct pwl_result_data *rgb_plus_1 = rgb + 1; + + uint32_t i; + + i = 0; + + while (i != hw_points_num + 1) { + rgb->red = dal_fixed31_32_clamp( + rgb->red, dal_fixed31_32_zero, + dal_fixed31_32_one); + rgb->green = dal_fixed31_32_clamp( + rgb->green, dal_fixed31_32_zero, + dal_fixed31_32_one); + rgb->blue = dal_fixed31_32_clamp( + rgb->blue, dal_fixed31_32_zero, + dal_fixed31_32_one); + + ++rgb; + ++i; + } + + rgb = rgb_resulted; + + i = 1; + + while (i != hw_points_num + 1) { + if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dal_fixed31_32_sub( + rgb_plus_1->red, + rgb->red); + rgb->delta_green = dal_fixed31_32_sub( + rgb_plus_1->green, + rgb->green); + rgb->delta_blue = dal_fixed31_32_sub( + rgb_plus_1->blue, + rgb->blue); + + ++rgb_plus_1; + ++rgb; + ++i; + } +} + +static void rebuild_curve_configuration_magic( + struct curve_points *arr_points, + struct pwl_result_data *rgb_resulted, + const struct hw_x_point *coordinates_x, + uint32_t hw_points_num) +{ + const struct fixed31_32 magic_number = + dal_fixed31_32_from_fraction(249, 1000); + + struct fixed31_32 y_r; + struct fixed31_32 y_g; + struct fixed31_32 y_b; + + struct fixed31_32 y1_min; + struct fixed31_32 y2_max; + struct fixed31_32 y3_max; + + y_r = rgb_resulted[0].red; + y_g = rgb_resulted[0].green; + y_b = rgb_resulted[0].blue; + + y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); + + arr_points[0].x = coordinates_x[0].adjusted_x; + arr_points[0].y = y1_min; + arr_points[0].slope = dal_fixed31_32_div( + arr_points[0].y, + arr_points[0].x); + + arr_points[1].x = dal_fixed31_32_add( + coordinates_x[hw_points_num - 1].adjusted_x, + magic_number); + + arr_points[2].x = arr_points[1].x; + + y_r = rgb_resulted[hw_points_num - 1].red; + y_g = rgb_resulted[hw_points_num - 1].green; + y_b = rgb_resulted[hw_points_num - 1].blue; + + y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[1].y = y2_max; + + y_r = rgb_resulted[hw_points_num].red; + y_g = rgb_resulted[hw_points_num].green; + y_b = rgb_resulted[hw_points_num].blue; + + y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[2].y = y3_max; + + arr_points[2].slope = dal_fixed31_32_one; +} + +static bool convert_to_custom_float_format( + struct fixed31_32 value, + const struct custom_float_format *format, + uint32_t *result) +{ + uint32_t mantissa; + uint32_t exponenta; + bool negative; + + return build_custom_float( + value, format, &negative, &mantissa, &exponenta) && + setup_custom_float( + format, negative, mantissa, exponenta, result); +} + +static bool convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = true; + + if (!convert_to_custom_float_format( + arr_points[0].x, + &fmt, + &arr_points[0].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].offset, + &fmt, + &arr_points[0].custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].slope, + &fmt, + &arr_points[0].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format( + arr_points[1].x, + &fmt, + &arr_points[1].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[1].y, + &fmt, + &arr_points[1].custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[2].slope, + &fmt, + &arr_points[2].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 12; + fmt.sign = true; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format( + rgb->red, + &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->green, + &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->blue, + &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_red, + &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_green, + &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_blue, + &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} + +bool calculate_regamma_params(struct pwl_params *params, + const struct core_gamma *ramp, + const struct core_surface *surface) +{ + struct gamma_curve *arr_curve_points = params->arr_curve_points; + struct curve_points *arr_points = params->arr_points; + struct pwl_result_data *rgb_resulted = params->rgb_resulted; + struct dividers dividers; + + struct hw_x_point *coordinates_x = NULL; + struct pwl_float_data *rgb_user = NULL ; + struct pwl_float_data_ex *rgb_regamma = NULL; + struct pwl_float_data *rgb_oem = NULL; + struct gamma_pixel *axix_x_256 = NULL; + struct pixel_gamma_point *coeff128_oem = NULL; + struct pixel_gamma_point *coeff128 = NULL; + + + bool ret = false; + + coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); + if (!coordinates_x) + goto coordinates_x_alloc_fail; + rgb_user = dm_alloc(sizeof(*rgb_user) * (FLOAT_GAMMA_RAMP_MAX + 3)); + if (!rgb_user) + goto rgb_user_alloc_fail; + rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3)); + if (!rgb_regamma) + goto rgb_regamma_alloc_fail; + rgb_oem = dm_alloc(sizeof(*rgb_oem) * (FLOAT_GAMMA_RAMP_MAX + 3)); + if (!rgb_oem) + goto rgb_oem_alloc_fail; + axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3)); + if (!axix_x_256) + goto axix_x_256_alloc_fail; + coeff128_oem = dm_alloc(sizeof(*coeff128_oem) * (256 + 3)); + if (!coeff128_oem) + goto coeff128_oem_alloc_fail; + coeff128 = dm_alloc(sizeof(*coeff128) * (256 + 3)); + if (!coeff128) + goto coeff128_alloc_fail; + + dividers.divider1 = dal_fixed31_32_from_fraction(3, 2); + dividers.divider2 = dal_fixed31_32_from_int(2); + dividers.divider3 = dal_fixed31_32_from_fraction(5, 2); + + build_evenly_distributed_points( + axix_x_256, + 256, + dal_fixed31_32_one, + dividers); + + scale_gamma(rgb_user, ramp, dividers); + + setup_distribution_points(arr_curve_points, arr_points, + ¶ms->hw_points_num, coordinates_x); + + build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, + ramp, surface, params->hw_points_num, + coordinates_x, axix_x_256, dividers); + + map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user, + coordinates_x, axix_x_256, &ramp->public, rgb_regamma, + dividers, params->hw_points_num, surface); + + build_new_custom_resulted_curve(rgb_resulted, params->hw_points_num); + + rebuild_curve_configuration_magic( + arr_points, + rgb_resulted, + coordinates_x, + params->hw_points_num); + + convert_to_custom_float(rgb_resulted, arr_points, + params->hw_points_num); + + ret = true; + + dm_free(coeff128); +coeff128_alloc_fail: + dm_free(coeff128_oem); +coeff128_oem_alloc_fail: + dm_free(axix_x_256); +axix_x_256_alloc_fail: + dm_free(rgb_oem); +rgb_oem_alloc_fail: + dm_free(rgb_regamma); +rgb_regamma_alloc_fail: + dm_free(rgb_user); +rgb_user_alloc_fail: + dm_free(coordinates_x); +coordinates_x_alloc_fail: + return ret; + +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c new file mode 100644 index 000000000000..f7638f84421b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -0,0 +1,1846 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + */ + +#include "dm_services.h" + +#include "dc.h" + +#include "core_status.h" +#include "core_types.h" +#include "hw_sequencer.h" + +#include "resource.h" + +#include "clock_source.h" +#include "dc_bios_types.h" + +#include "bandwidth_calcs.h" +#include "bios_parser_interface.h" +#include "include/irq_service_interface.h" +#include "transform.h" +#include "timing_generator.h" +#include "virtual/virtual_link_encoder.h" + +#include "link_hwss.h" +#include "link_encoder.h" + +#include "dc_link_ddc.h" +#include "dm_helpers.h" +#include "mem_input.h" + +/******************************************************************************* + * Private structures + ******************************************************************************/ + +struct dc_target_sync_report { + uint32_t h_count; + uint32_t v_count; +}; + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static void destroy_links(struct core_dc *dc) +{ + uint32_t i; + + for (i = 0; i < dc->link_count; i++) { + if (NULL != dc->links[i]) + link_destroy(&dc->links[i]); + } +} + +static bool create_links( + struct core_dc *dc, + uint32_t num_virtual_links) +{ + int i; + int connectors_num; + struct dc_bios *bios = dc->ctx->dc_bios; + + dc->link_count = 0; + + connectors_num = bios->funcs->get_connectors_number(bios); + + if (connectors_num > ENUM_ID_COUNT) { + dm_error( + "DC: Number of connectors %d exceeds maximum of %d!\n", + connectors_num, + ENUM_ID_COUNT); + return false; + } + + if (connectors_num == 0 && num_virtual_links == 0) { + dm_error("DC: Number of connectors is zero!\n"); + } + + dm_output_to_console( + "DC: %s: connectors_num: physical:%d, virtual:%d\n", + __func__, + connectors_num, + num_virtual_links); + + for (i = 0; i < connectors_num; i++) { + struct link_init_data link_init_params = {0}; + struct core_link *link; + + link_init_params.ctx = dc->ctx; + link_init_params.connector_index = i; + link_init_params.link_index = dc->link_count; + link_init_params.dc = dc; + link = link_create(&link_init_params); + + if (link) { + dc->links[dc->link_count] = link; + link->dc = dc; + ++dc->link_count; + } else { + dm_error("DC: failed to create link!\n"); + } + } + + for (i = 0; i < num_virtual_links; i++) { + struct core_link *link = dm_alloc(sizeof(*link)); + struct encoder_init_data enc_init = {0}; + + if (link == NULL) { + BREAK_TO_DEBUGGER(); + goto failed_alloc; + } + + link->ctx = dc->ctx; + link->dc = dc; + link->public.connector_signal = SIGNAL_TYPE_VIRTUAL; + link->link_id.type = OBJECT_TYPE_CONNECTOR; + link->link_id.id = CONNECTOR_ID_VIRTUAL; + link->link_id.enum_id = ENUM_ID_1; + link->link_enc = dm_alloc(sizeof(*link->link_enc)); + + enc_init.ctx = dc->ctx; + enc_init.channel = CHANNEL_ID_UNKNOWN; + enc_init.hpd_source = HPD_SOURCEID_UNKNOWN; + enc_init.transmitter = TRANSMITTER_UNKNOWN; + enc_init.connector = link->link_id; + enc_init.encoder.type = OBJECT_TYPE_ENCODER; + enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL; + enc_init.encoder.enum_id = ENUM_ID_1; + virtual_link_encoder_construct(link->link_enc, &enc_init); + + link->public.link_index = dc->link_count; + dc->links[dc->link_count] = link; + dc->link_count++; + } + + return true; + +failed_alloc: + return false; +} + +static bool stream_adjust_vmin_vmax(struct dc *dc, + const struct dc_stream **stream, int num_streams, + int vmin, int vmax) +{ + /* TODO: Support multiple streams */ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + int i = 0; + bool ret = false; + struct pipe_ctx *pipes; + unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == core_stream + && i != underlay_idx) { + + pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; + core_dc->hwss.set_drr(&pipes, 1, vmin, vmax); + + /* build and update the info frame */ + resource_build_info_frame(pipes); + core_dc->hwss.update_info_frame(pipes); + + ret = true; + } + } + + return ret; +} + + +static bool set_gamut_remap(struct dc *dc, + const struct dc_stream **stream, int num_streams) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + int i = 0; + bool ret = false; + struct pipe_ctx *pipes; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) { + + pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; + core_dc->hwss.set_plane_config(core_dc, pipes, + &core_dc->current_context->res_ctx); + ret = true; + } + } + + return ret; +} + +/* This function is not expected to fail, proper implementation of + * validation will prevent this from ever being called for unsupported + * configurations. + */ +static void stream_update_scaling( + const struct dc *dc, + const struct dc_stream *dc_stream, + const struct rect *src, + const struct rect *dst) +{ + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_dc *core_dc = DC_TO_CORE(dc); + struct validate_context *cur_ctx = core_dc->current_context; + int i, j; + + if (src) + stream->public.src = *src; + + if (dst) + stream->public.dst = *dst; + + for (i = 0; i < cur_ctx->target_count; i++) { + struct core_target *target = cur_ctx->targets[i]; + struct dc_target_status *status = &cur_ctx->target_status[i]; + + for (j = 0; j < target->public.stream_count; j++) { + if (target->public.streams[j] != dc_stream) + continue; + + if (status->surface_count) + if (!dc_commit_surfaces_to_target( + &core_dc->public, + status->surfaces, + status->surface_count, + &target->public)) + /* Need to debug validation */ + BREAK_TO_DEBUGGER(); + + return; + } + } +} + +static bool set_backlight(struct dc *dc, unsigned int backlight_level, + unsigned int frame_ramp, const struct dc_stream *stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) { + for (i = 0; i < core_dc->link_count; i++) + dc_link_set_backlight_level(&core_dc->links[i]->public, + backlight_level, frame_ramp, stream); + } + + return true; + +} + +static bool init_dmcu_backlight_settings(struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_init_dmcu_backlight_settings + (&core_dc->links[i]->public); + + return true; +} + + +static bool set_abm_level(struct dc *dc, unsigned int abm_level) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_set_abm_level(&core_dc->links[i]->public, + abm_level); + + return true; +} + +static bool set_psr_enable(struct dc *dc, bool enable) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_set_psr_enable(&core_dc->links[i]->public, + enable); + + return true; +} + + +static bool setup_psr(struct dc *dc, const struct dc_stream *stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct pipe_ctx *pipes; + int i; + unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; + + for (i = 0; i < core_dc->link_count; i++) { + if (core_stream->sink->link == core_dc->links[i]) + dc_link_setup_psr(&core_dc->links[i]->public, + stream); + } + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream && i != underlay_idx) { + pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; + core_dc->hwss.set_static_screen_control(&pipes, 1, + 0x182); + } + } + + return true; +} + +static void set_drive_settings(struct dc *dc, + struct link_training_settings *lt_settings) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_dp_set_drive_settings(&core_dc->links[i]->public, + lt_settings); +} + +static void perform_link_training(struct dc *dc, + struct dc_link_settings *link_setting, + bool skip_video_pattern) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) + dc_link_dp_perform_link_training( + &core_dc->links[i]->public, + link_setting, + skip_video_pattern); +} + +static void set_preferred_link_settings(struct dc *dc, + struct dc_link_settings *link_setting) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + for (i = 0; i < core_dc->link_count; i++) { + core_dc->links[i]->public.verified_link_cap.lane_count = + link_setting->lane_count; + core_dc->links[i]->public.verified_link_cap.link_rate = + link_setting->link_rate; + } +} + +static void enable_hpd(const struct dc_link *link) +{ + dc_link_dp_enable_hpd(link); +} + +static void disable_hpd(const struct dc_link *link) +{ + dc_link_dp_disable_hpd(link); +} + + +static void set_test_pattern( + const struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size) +{ + if (link != NULL) + dc_link_dp_set_test_pattern( + link, + test_pattern, + p_link_settings, + p_custom_pattern, + cust_pattern_size); +} + +static void allocate_dc_stream_funcs(struct core_dc *core_dc) +{ + core_dc->public.stream_funcs.stream_update_scaling = stream_update_scaling; + if (core_dc->hwss.set_drr != NULL) { + core_dc->public.stream_funcs.adjust_vmin_vmax = + stream_adjust_vmin_vmax; + } + + core_dc->public.stream_funcs.set_gamut_remap = + set_gamut_remap; + + core_dc->public.stream_funcs.set_backlight = + set_backlight; + + core_dc->public.stream_funcs.init_dmcu_backlight_settings = + init_dmcu_backlight_settings; + + core_dc->public.stream_funcs.set_abm_level = + set_abm_level; + + core_dc->public.stream_funcs.set_psr_enable = + set_psr_enable; + + core_dc->public.stream_funcs.setup_psr = + setup_psr; + + core_dc->public.link_funcs.set_drive_settings = + set_drive_settings; + + core_dc->public.link_funcs.perform_link_training = + perform_link_training; + + core_dc->public.link_funcs.set_preferred_link_settings = + set_preferred_link_settings; + + core_dc->public.link_funcs.enable_hpd = + enable_hpd; + + core_dc->public.link_funcs.disable_hpd = + disable_hpd; + + core_dc->public.link_funcs.set_test_pattern = + set_test_pattern; +} + +static void destruct(struct core_dc *dc) +{ + resource_validate_ctx_destruct(dc->current_context); + + dm_free(dc->temp_flip_context); + dc->temp_flip_context = NULL; + + destroy_links(dc); + + dc_destroy_resource_pool(dc); + + if (dc->ctx->gpio_service) + dal_gpio_service_destroy(&dc->ctx->gpio_service); + + if (dc->ctx->i2caux) + dal_i2caux_destroy(&dc->ctx->i2caux); + + if (dc->ctx->created_bios) + dal_bios_parser_destroy(&dc->ctx->dc_bios); + + if (dc->ctx->logger) + dal_logger_destroy(&dc->ctx->logger); + + dm_free(dc->current_context); + dc->current_context = NULL; + + dm_free(dc->ctx); + dc->ctx = NULL; +} + +static bool construct(struct core_dc *dc, + const struct dc_init_data *init_params) +{ + struct dal_logger *logger; + struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx)); + enum dce_version dc_version = DCE_VERSION_UNKNOWN; + + if (!dc_ctx) { + dm_error("%s: failed to create ctx\n", __func__); + goto ctx_fail; + } + + dc->current_context = dm_alloc(sizeof(*dc->current_context)); + dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); + + if (!dc->current_context || !dc->temp_flip_context) { + dm_error("%s: failed to create validate ctx\n", __func__); + goto val_ctx_fail; + } + + dc_ctx->cgs_device = init_params->cgs_device; + dc_ctx->driver_context = init_params->driver; + dc_ctx->dc = &dc->public; + dc_ctx->asic_id = init_params->asic_id; + + /* Create logger */ + logger = dal_logger_create(dc_ctx); + + if (!logger) { + /* can *not* call logger. call base driver 'print error' */ + dm_error("%s: failed to create Logger!\n", __func__); + goto logger_fail; + } + dc_ctx->logger = logger; + dc->ctx = dc_ctx; + dc->ctx->dce_environment = init_params->dce_environment; + + dc_version = resource_parse_asic_id(init_params->asic_id); + dc->ctx->dce_version = dc_version; + + /* Resource should construct all asic specific resources. + * This should be the only place where we need to parse the asic id + */ + if (init_params->vbios_override) + dc_ctx->dc_bios = init_params->vbios_override; + else { + /* Create BIOS parser */ + struct bp_init_data bp_init_data; + bp_init_data.ctx = dc_ctx; + bp_init_data.bios = init_params->asic_id.atombios_base_address; + + dc_ctx->dc_bios = dal_bios_parser_create( + &bp_init_data, dc_version); + + if (!dc_ctx->dc_bios) { + ASSERT_CRITICAL(false); + goto bios_fail; + } + + dc_ctx->created_bios = true; + } + + /* Create I2C AUX */ + dc_ctx->i2caux = dal_i2caux_create(dc_ctx); + + if (!dc_ctx->i2caux) { + ASSERT_CRITICAL(false); + goto failed_to_create_i2caux; + } + + /* Create GPIO service */ + dc_ctx->gpio_service = dal_gpio_service_create( + dc_version, + dc_ctx->dce_environment, + dc_ctx); + + if (!dc_ctx->gpio_service) { + ASSERT_CRITICAL(false); + goto gpio_fail; + } + + dc->res_pool = dc_create_resource_pool( + dc, + init_params->num_virtual_links, + dc_version, + init_params->asic_id); + if (!dc->res_pool) + goto create_resource_fail; + + if (!create_links(dc, init_params->num_virtual_links)) + goto create_links_fail; + + allocate_dc_stream_funcs(dc); + + return true; + + /**** error handling here ****/ +create_links_fail: +create_resource_fail: +gpio_fail: +failed_to_create_i2caux: +bios_fail: +logger_fail: +val_ctx_fail: +ctx_fail: + destruct(dc); + return false; +} + +/* +void ProgramPixelDurationV(unsigned int pixelClockInKHz ) +{ + fixed31_32 pixel_duration = Fixed31_32(100000000, pixelClockInKHz) * 10; + unsigned int pixDurationInPico = round(pixel_duration); + + DPG_PIPE_ARBITRATION_CONTROL1 arb_control; + + arb_control.u32All = ReadReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1); + arb_control.bits.PIXEL_DURATION = pixDurationInPico; + WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1, arb_control.u32All); + + arb_control.u32All = ReadReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1); + arb_control.bits.PIXEL_DURATION = pixDurationInPico; + WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1, arb_control.u32All); + + WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL2, 0x4000800); + WriteReg (mmDPGV0_REPEATER_PROGRAM, 0x11); + + WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL2, 0x4000800); + WriteReg (mmDPGV1_REPEATER_PROGRAM, 0x11); +} +*/ + +/******************************************************************************* + * Public functions + ******************************************************************************/ + +struct dc *dc_create(const struct dc_init_data *init_params) + { + struct core_dc *core_dc = dm_alloc(sizeof(*core_dc)); + unsigned int full_pipe_count; + + if (NULL == core_dc) + goto alloc_fail; + + if (false == construct(core_dc, init_params)) + goto construct_fail; + + /*TODO: separate HW and SW initialization*/ + core_dc->hwss.init_hw(core_dc); + + full_pipe_count = core_dc->res_pool->pipe_count; + if (core_dc->res_pool->underlay_pipe_index >= 0) + full_pipe_count--; + core_dc->public.caps.max_targets = dm_min( + full_pipe_count, + core_dc->res_pool->stream_enc_count); + + core_dc->public.caps.max_links = core_dc->link_count; + core_dc->public.caps.max_audios = core_dc->res_pool->audio_count; + + core_dc->public.config = init_params->flags; + + dm_logger_write(core_dc->ctx->logger, LOG_DC, + "Display Core initialized\n"); + + + /* TODO: missing feature to be enabled */ + core_dc->public.debug.disable_dfs_bypass = true; + + return &core_dc->public; + +construct_fail: + dm_free(core_dc); + +alloc_fail: + return NULL; +} + +void dc_destroy(struct dc **dc) +{ + struct core_dc *core_dc = DC_TO_CORE(*dc); + destruct(core_dc); + dm_free(core_dc); + *dc = NULL; +} + +static bool is_validation_required( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count) +{ + const struct validate_context *context = dc->current_context; + int i, j; + + if (context->target_count != set_count) + return true; + + for (i = 0; i < set_count; i++) { + + if (set[i].surface_count != context->target_status[i].surface_count) + return true; + if (!is_target_unchanged(DC_TARGET_TO_CORE(set[i].target), context->targets[i])) + return true; + + for (j = 0; j < set[i].surface_count; j++) { + struct dc_surface temp_surf = { 0 }; + + temp_surf = *context->target_status[i].surfaces[j]; + temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; + temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; + temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; + + if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0) + return true; + } + } + + return false; +} + +bool dc_validate_resources( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; + + if (!is_validation_required(core_dc, set, set_count)) + return true; + + context = dm_alloc(sizeof(struct validate_context)); + if(context == NULL) + goto context_alloc_fail; + + result = core_dc->res_pool->funcs->validate_with_context( + core_dc, set, set_count, context); + + resource_validate_ctx_destruct(context); + dm_free(context); + +context_alloc_fail: + if (result != DC_OK) { + dm_logger_write(core_dc->ctx->logger, LOG_WARNING, + "%s:resource validation failed, dc_status:%d\n", + __func__, + result); + } + + return (result == DC_OK); + +} + +bool dc_validate_guaranteed( + const struct dc *dc, + const struct dc_target *dc_target) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; + + context = dm_alloc(sizeof(struct validate_context)); + if (context == NULL) + goto context_alloc_fail; + + result = core_dc->res_pool->funcs->validate_guaranteed( + core_dc, dc_target, context); + + resource_validate_ctx_destruct(context); + dm_free(context); + +context_alloc_fail: + if (result != DC_OK) { + dm_logger_write(core_dc->ctx->logger, LOG_WARNING, + "%s:guaranteed validation failed, dc_status:%d\n", + __func__, + result); + } + + return (result == DC_OK); +} + +static void program_timing_sync( + struct core_dc *core_dc, + struct validate_context *ctx) +{ + int i, j; + int group_index = 0; + int pipe_count = ctx->res_ctx.pool->pipe_count; + struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; + + for (i = 0; i < pipe_count; i++) { + if (!ctx->res_ctx.pipe_ctx[i].stream || ctx->res_ctx.pipe_ctx[i].top_pipe) + continue; + + unsynced_pipes[i] = &ctx->res_ctx.pipe_ctx[i]; + } + + for (i = 0; i < pipe_count; i++) { + int group_size = 1; + struct pipe_ctx *pipe_set[MAX_PIPES]; + + if (!unsynced_pipes[i]) + continue; + + pipe_set[0] = unsynced_pipes[i]; + unsynced_pipes[i] = NULL; + + /* Add tg to the set, search rest of the tg's for ones with + * same timing, add all tgs with same timing to the group + */ + for (j = i + 1; j < pipe_count; j++) { + if (!unsynced_pipes[j]) + continue; + + if (resource_are_streams_timing_synchronizable( + unsynced_pipes[j]->stream, + pipe_set[0]->stream)) { + pipe_set[group_size] = unsynced_pipes[j]; + unsynced_pipes[j] = NULL; + group_size++; + } + } + + /* set first unblanked pipe as master */ + for (j = 0; j < group_size; j++) { + struct pipe_ctx *temp; + + if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) { + if (j == 0) + break; + + temp = pipe_set[0]; + pipe_set[0] = pipe_set[j]; + pipe_set[j] = temp; + break; + } + } + + /* remove any other unblanked pipes as they have already been synced */ + for (j = j + 1; j < group_size; j++) { + if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) { + group_size--; + pipe_set[j] = pipe_set[group_size]; + j--; + } + } + + if (group_size > 1) { + core_dc->hwss.enable_timing_synchronization( + core_dc, group_index, group_size, pipe_set); + group_index++; + } + } +} + +static bool targets_changed( + struct core_dc *dc, + struct dc_target *targets[], + uint8_t target_count) +{ + uint8_t i; + + if (target_count != dc->current_context->target_count) + return true; + + for (i = 0; i < dc->current_context->target_count; i++) { + if (&dc->current_context->targets[i]->public != targets[i]) + return true; + } + + return false; +} + +static void fill_display_configs( + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg) +{ + uint8_t i, j, k; + uint8_t num_cfgs = 0; + + for (i = 0; i < context->target_count; i++) { + const struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + const struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct dm_pp_single_disp_config *cfg = + &pp_display_cfg->disp_configs[num_cfgs]; + const struct pipe_ctx *pipe_ctx = NULL; + + for (k = 0; k < MAX_PIPES; k++) + if (stream == + context->res_ctx.pipe_ctx[k].stream) { + pipe_ctx = &context->res_ctx.pipe_ctx[k]; + break; + } + + ASSERT(pipe_ctx != NULL); + + num_cfgs++; + cfg->signal = pipe_ctx->stream->signal; + cfg->pipe_idx = pipe_ctx->pipe_idx; + cfg->src_height = stream->public.src.height; + cfg->src_width = stream->public.src.width; + cfg->ddi_channel_mapping = + stream->sink->link->ddi_channel_mapping.raw; + cfg->transmitter = + stream->sink->link->link_enc->transmitter; + cfg->link_settings.lane_count = stream->sink->link->public.cur_link_settings.lane_count; + cfg->link_settings.link_rate = stream->sink->link->public.cur_link_settings.link_rate; + cfg->link_settings.link_spread = stream->sink->link->public.cur_link_settings.link_spread; + cfg->sym_clock = stream->phy_pix_clk; + /* Round v_refresh*/ + cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; + cfg->v_refresh /= stream->public.timing.h_total; + cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) + / stream->public.timing.v_total; + } + } + pp_display_cfg->display_count = num_cfgs; +} + +static uint32_t get_min_vblank_time_us(const struct validate_context *context) +{ + uint8_t i, j; + uint32_t min_vertical_blank_time = -1; + + for (i = 0; i < context->target_count; i++) { + const struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + const struct dc_stream *stream = + target->public.streams[j]; + uint32_t vertical_blank_in_pixels = 0; + uint32_t vertical_blank_time = 0; + + vertical_blank_in_pixels = stream->timing.h_total * + (stream->timing.v_total + - stream->timing.v_addressable); + vertical_blank_time = vertical_blank_in_pixels + * 1000 / stream->timing.pix_clk_khz; + if (min_vertical_blank_time > vertical_blank_time) + min_vertical_blank_time = vertical_blank_time; + } + } + return min_vertical_blank_time; +} + +static int determine_sclk_from_bounding_box( + const struct core_dc *dc, + int required_sclk) +{ + int i; + + /* + * Some asics do not give us sclk levels, so we just report the actual + * required sclk + */ + if (dc->sclk_lvls.num_levels == 0) + return required_sclk; + + for (i = 0; i < dc->sclk_lvls.num_levels; i++) { + if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) + return dc->sclk_lvls.clocks_in_khz[i]; + } + /* + * even maximum level could not satisfy requirement, this + * is unexpected at this stage, should have been caught at + * validation time + */ + ASSERT(0); + return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; +} + +void pplib_apply_display_requirements( + struct core_dc *dc, + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg) +{ + pp_display_cfg->all_displays_in_sync = + context->bw_results.all_displays_in_sync; + pp_display_cfg->nb_pstate_switch_disable = + context->bw_results.nbp_state_change_enable == false; + pp_display_cfg->cpu_cc6_disable = + context->bw_results.cpuc_state_change_enable == false; + pp_display_cfg->cpu_pstate_disable = + context->bw_results.cpup_state_change_enable == false; + pp_display_cfg->cpu_pstate_separation_time = + context->bw_results.blackout_recovery_time_us; + + pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + / MEMORY_TYPE_MULTIPLIER; + + pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( + dc, + context->bw_results.required_sclk); + + pp_display_cfg->min_engine_clock_deep_sleep_khz + = context->bw_results.required_sclk_deep_sleep; + + pp_display_cfg->avail_mclk_switch_time_us = + get_min_vblank_time_us(context); + /* TODO: dce11.2*/ + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; + + pp_display_cfg->disp_clk_khz = context->bw_results.dispclk_khz; + + fill_display_configs(context, pp_display_cfg); + + /* TODO: is this still applicable?*/ + if (pp_display_cfg->display_count == 1) { + const struct dc_crtc_timing *timing = + &context->targets[0]->public.streams[0]->timing; + + pp_display_cfg->crtc_index = + pp_display_cfg->disp_configs[0].pipe_idx; + pp_display_cfg->line_time_in_us = timing->h_total * 1000 + / timing->pix_clk_khz; + } + + if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( + struct dm_pp_display_configuration)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + + dc->prev_display_config = *pp_display_cfg; + +} + +bool dc_commit_targets( + struct dc *dc, + struct dc_target *targets[], + uint8_t target_count) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc_bios *dcb = core_dc->ctx->dc_bios; + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; + struct dc_validation_set set[MAX_TARGETS]; + int i, j, k; + + if (false == targets_changed(core_dc, targets, target_count)) + return DC_OK; + + dm_logger_write(core_dc->ctx->logger, LOG_DC, + "%s: %d targets\n", + __func__, + target_count); + + for (i = 0; i < target_count; i++) { + struct dc_target *target = targets[i]; + + dc_target_log(target, + core_dc->ctx->logger, + LOG_DC); + + set[i].target = targets[i]; + set[i].surface_count = 0; + + } + + context = dm_alloc(sizeof(struct validate_context)); + if (context == NULL) + goto context_alloc_fail; + + result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, target_count, context); + if (result != DC_OK){ + dm_logger_write(core_dc->ctx->logger, LOG_ERROR, + "%s: Context validation failed! dc_status:%d\n", + __func__, + result); + BREAK_TO_DEBUGGER(); + resource_validate_ctx_destruct(context); + goto fail; + } + + if (!dcb->funcs->is_accelerated_mode(dcb)) { + core_dc->hwss.enable_accelerated_mode(core_dc); + } + + if (result == DC_OK) { + result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); + } + + program_timing_sync(core_dc, context); + + for (i = 0; i < context->target_count; i++) { + struct dc_target *dc_target = &context->targets[i]->public; + struct core_sink *sink = DC_SINK_TO_CORE(dc_target->streams[0]->sink); + + for (j = 0; j < context->target_status[i].surface_count; j++) { + const struct dc_surface *dc_surface = + context->target_status[i].surfaces[j]; + + for (k = 0; k < context->res_ctx.pool->pipe_count; k++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[k]; + + if (dc_surface != &pipe->surface->public + || !dc_surface->visible) + continue; + + pipe->tg->funcs->set_blank(pipe->tg, false); + } + } + + CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", + dc_target->streams[0]->timing.h_addressable, + dc_target->streams[0]->timing.v_addressable, + dc_target->streams[0]->timing.h_total, + dc_target->streams[0]->timing.v_total, + dc_target->streams[0]->timing.pix_clk_khz); + } + + pplib_apply_display_requirements(core_dc, + context, &context->pp_display_cfg); + + resource_validate_ctx_destruct(core_dc->current_context); + + dm_free(core_dc->current_context); + core_dc->current_context = context; + + return (result == DC_OK); + +fail: + dm_free(context); + +context_alloc_fail: + return (result == DC_OK); +} + +bool dc_pre_update_surfaces_to_target( + struct dc *dc, + const struct dc_surface *const *new_surfaces, + uint8_t new_surface_count, + struct dc_target *dc_target) +{ + int i, j; + struct core_dc *core_dc = DC_TO_CORE(dc); + uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct dc_target_status *target_status = NULL; + struct validate_context *context; + struct validate_context *temp_context; + bool ret = true; + + pre_surface_trace(dc, new_surfaces, new_surface_count); + + if (core_dc->current_context->target_count == 0) + return false; + + /* Cannot commit surface to a target that is not commited */ + for (i = 0; i < core_dc->current_context->target_count; i++) + if (target == core_dc->current_context->targets[i]) + break; + + if (i == core_dc->current_context->target_count) + return false; + + target_status = &core_dc->current_context->target_status[i]; + + if (new_surface_count == target_status->surface_count) { + bool skip_pre = true; + + for (i = 0; i < target_status->surface_count; i++) { + struct dc_surface temp_surf = { 0 }; + + temp_surf = *target_status->surfaces[i]; + temp_surf.clip_rect = new_surfaces[i]->clip_rect; + temp_surf.dst_rect.x = new_surfaces[i]->dst_rect.x; + temp_surf.dst_rect.y = new_surfaces[i]->dst_rect.y; + + if (memcmp(&temp_surf, new_surfaces[i], sizeof(temp_surf)) != 0) { + skip_pre = false; + break; + } + } + + if (skip_pre) + return true; + } + + context = dm_alloc(sizeof(struct validate_context)); + + if (!context) { + dm_error("%s: failed to create validate ctx\n", __func__); + ret = false; + goto val_ctx_fail; + } + + resource_validate_ctx_copy_construct(core_dc->current_context, context); + + dm_logger_write(core_dc->ctx->logger, LOG_DC, + "%s: commit %d surfaces to target 0x%x\n", + __func__, + new_surface_count, + dc_target); + + if (!resource_attach_surfaces_to_context( + new_surfaces, new_surface_count, dc_target, context)) { + BREAK_TO_DEBUGGER(); + ret = false; + goto unexpected_fail; + } + + for (i = 0; i < new_surface_count; i++) + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + if (context->res_ctx.pipe_ctx[j].surface != + DC_SURFACE_TO_CORE(new_surfaces[i])) + continue; + + resource_build_scaling_params( + new_surfaces[i], &context->res_ctx.pipe_ctx[j]); + + if (dc->debug.surface_visual_confirm) { + context->res_ctx.pipe_ctx[j].scl_data.recout.height -= 2; + context->res_ctx.pipe_ctx[j].scl_data.recout.width -= 2; + } + } + + if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) { + BREAK_TO_DEBUGGER(); + ret = false; + goto unexpected_fail; + } + + if (core_dc->res_pool->funcs->apply_clk_constraints) { + temp_context = core_dc->res_pool->funcs->apply_clk_constraints( + core_dc, + context); + if (!temp_context) { + dm_error("%s:failed apply clk constraints\n", __func__); + ret = false; + goto unexpected_fail; + } + resource_validate_ctx_destruct(context); + dm_free(context); + context = temp_context; + } + + if (prev_disp_clk < context->bw_results.dispclk_khz) { + pplib_apply_display_requirements(core_dc, context, + &context->pp_display_cfg); + core_dc->hwss.set_display_clock(context); + core_dc->current_context->bw_results.dispclk_khz = + context->bw_results.dispclk_khz; + } + + for (i = 0; i < new_surface_count; i++) + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + if (context->res_ctx.pipe_ctx[j].surface != + DC_SURFACE_TO_CORE(new_surfaces[i])) + continue; + + core_dc->hwss.prepare_pipe_for_context( + core_dc, + &context->res_ctx.pipe_ctx[j], + context); + + if (!new_surfaces[i]->visible) + context->res_ctx.pipe_ctx[j].tg->funcs->set_blank( + context->res_ctx.pipe_ctx[j].tg, true); + } + +unexpected_fail: + resource_validate_ctx_destruct(context); + dm_free(context); +val_ctx_fail: + + return ret; +} + +bool dc_post_update_surfaces_to_target(struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + post_surface_trace(dc); + + for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; i++) + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) + core_dc->hwss.power_down_front_end( + core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + + if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, core_dc->current_context) + != DC_OK) { + BREAK_TO_DEBUGGER(); + return false; + } + + core_dc->hwss.set_bandwidth(core_dc); + + pplib_apply_display_requirements( + core_dc, core_dc->current_context, &core_dc->current_context->pp_display_cfg); + + return true; +} + +bool dc_commit_surfaces_to_target( + struct dc *dc, + const struct dc_surface **new_surfaces, + uint8_t new_surface_count, + struct dc_target *dc_target) +{ + struct dc_surface_update updates[MAX_SURFACES] = { 0 }; + struct dc_flip_addrs flip_addr[MAX_SURFACES] = { 0 }; + struct dc_plane_info plane_info[MAX_SURFACES] = { 0 }; + struct dc_scaling_info scaling_info[MAX_SURFACES] = { 0 }; + int i; + + if (!dc_pre_update_surfaces_to_target( + dc, new_surfaces, new_surface_count, dc_target)) + return false; + + for (i = 0; i < new_surface_count; i++) { + updates[i].surface = new_surfaces[i]; + updates[i].gamma = (struct dc_gamma *)new_surfaces[i]->gamma_correction; + + flip_addr[i].address = new_surfaces[i]->address; + flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; + plane_info[i].color_space = new_surfaces[i]->color_space; + plane_info[i].format = new_surfaces[i]->format; + plane_info[i].plane_size = new_surfaces[i]->plane_size; + plane_info[i].rotation = new_surfaces[i]->rotation; + plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror; + plane_info[i].stereo_format = new_surfaces[i]->stereo_format; + plane_info[i].tiling_info = new_surfaces[i]->tiling_info; + plane_info[i].visible = new_surfaces[i]->visible; + scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; + scaling_info[i].src_rect = new_surfaces[i]->src_rect; + scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; + scaling_info[i].clip_rect = new_surfaces[i]->clip_rect; + + updates[i].flip_addr = &flip_addr[i]; + updates[i].plane_info = &plane_info[i]; + updates[i].scaling_info = &scaling_info[i]; + } + dc_update_surfaces_for_target(dc, updates, new_surface_count, dc_target); + + return dc_post_update_surfaces_to_target(dc); +} + +void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates, + int surface_count, struct dc_target *dc_target) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct validate_context *context = core_dc->temp_flip_context; + int i, j; + bool is_new_pipe_surface[MAX_SURFACES]; + const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + + update_surface_trace(dc, updates, surface_count); + + *context = *core_dc->current_context; + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; + + if (cur_pipe->top_pipe) + cur_pipe->top_pipe = + &context->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; + + if (cur_pipe->bottom_pipe) + cur_pipe->bottom_pipe = + &context->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; + } + + for (j = 0; j < MAX_SURFACES; j++) + is_new_pipe_surface[j] = true; + + for (i = 0 ; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + + new_surfaces[i] = updates[i].surface; + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (surface == pipe_ctx->surface) + is_new_pipe_surface[i] = false; + } + } + + if (dc_target) { + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + + if (core_dc->current_context->target_count == 0) + return; + + /* Cannot commit surface to a target that is not commited */ + for (i = 0; i < core_dc->current_context->target_count; i++) + if (target == core_dc->current_context->targets[i]) + break; + if (i == core_dc->current_context->target_count) + return; + + if (!resource_attach_surfaces_to_context( + new_surfaces, surface_count, dc_target, context)) { + BREAK_TO_DEBUGGER(); + return; + } + } + + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + if (updates[i].flip_addr) { + surface->public.address = updates[i].flip_addr->address; + surface->public.flip_immediate = + updates[i].flip_addr->flip_immediate; + } + + if (updates[i].plane_info || updates[i].scaling_info + || is_new_pipe_surface[j]) { + + if (updates[i].plane_info) { + surface->public.color_space = + updates[i].plane_info->color_space; + surface->public.format = + updates[i].plane_info->format; + surface->public.plane_size = + updates[i].plane_info->plane_size; + surface->public.rotation = + updates[i].plane_info->rotation; + surface->public.horizontal_mirror = + updates[i].plane_info->horizontal_mirror; + surface->public.stereo_format = + updates[i].plane_info->stereo_format; + surface->public.tiling_info = + updates[i].plane_info->tiling_info; + surface->public.visible = + updates[i].plane_info->visible; + } + + if (updates[i].scaling_info) { + surface->public.scaling_quality = + updates[i].scaling_info->scaling_quality; + surface->public.dst_rect = + updates[i].scaling_info->dst_rect; + surface->public.src_rect = + updates[i].scaling_info->src_rect; + surface->public.clip_rect = + updates[i].scaling_info->clip_rect; + } + + resource_build_scaling_params(updates[i].surface, pipe_ctx); + if (dc->debug.surface_visual_confirm) { + pipe_ctx->scl_data.recout.height -= 2; + pipe_ctx->scl_data.recout.width -= 2; + } + } + } + } + + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + bool apply_ctx = false; + + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + if (updates[i].flip_addr) { + core_dc->hwss.pipe_control_lock( + core_dc->hwseq, + pipe_ctx->pipe_idx, + PIPE_LOCK_CONTROL_SURFACE, + true); + core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); + } + + if (updates[i].plane_info || updates[i].scaling_info + || is_new_pipe_surface[j]) { + + apply_ctx = true; + + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + core_dc->hwss.pipe_control_lock( + core_dc->hwseq, + pipe_ctx->pipe_idx, + PIPE_LOCK_CONTROL_SURFACE | + PIPE_LOCK_CONTROL_GRAPHICS | + PIPE_LOCK_CONTROL_SCL | + PIPE_LOCK_CONTROL_BLENDER | + PIPE_LOCK_CONTROL_MODE, + true); + } + } + + if (updates[i].gamma) + core_dc->hwss.prepare_pipe_for_context( + core_dc, pipe_ctx, context); + } + if (apply_ctx) + core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + } + + for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + for (j = 0; j < surface_count; j++) { + if (updates[j].surface == &pipe_ctx->surface->public) { + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + core_dc->hwss.pipe_control_lock( + core_dc->hwseq, + pipe_ctx->pipe_idx, + PIPE_LOCK_CONTROL_GRAPHICS | + PIPE_LOCK_CONTROL_SCL | + PIPE_LOCK_CONTROL_BLENDER | + PIPE_LOCK_CONTROL_SURFACE, + false); + } + break; + } + } + } + + core_dc->temp_flip_context = core_dc->current_context; + core_dc->current_context = context; +} + +uint8_t dc_get_current_target_count(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return core_dc->current_context->target_count; +} + +struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + if (i < core_dc->current_context->target_count) + return &(core_dc->current_context->targets[i]->public); + return NULL; +} + +const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return &core_dc->links[link_index]->public; +} + +const struct graphics_object_id dc_get_link_id_at_index( + struct dc *dc, uint32_t link_index) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return core_dc->links[link_index]->link_id; +} + +const struct ddc_service *dc_get_ddc_at_index( + struct dc *dc, uint32_t link_index) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return core_dc->links[link_index]->ddc; +} + +enum dc_irq_source dc_get_hpd_irq_source_at_index( + struct dc *dc, uint32_t link_index) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return core_dc->links[link_index]->public.irq_source_hpd; +} + +const struct audio **dc_get_audios(struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return (const struct audio **)core_dc->res_pool->audios; +} + +void dc_flip_surface_addrs( + struct dc *dc, + const struct dc_surface *const surfaces[], + struct dc_flip_addrs flip_addrs[], + uint32_t count) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i, j; + + for (i = 0; i < count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); + + surface->public.address = flip_addrs[i].address; + surface->public.flip_immediate = flip_addrs[i].flip_immediate; + + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); + } + } +} + +enum dc_irq_source dc_interrupt_to_irq_source( + struct dc *dc, + uint32_t src_id, + uint32_t ext_id) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id); +} + +void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + dal_irq_service_set(core_dc->res_pool->irqs, src, enable); +} + +void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + dal_irq_service_ack(core_dc->res_pool->irqs, src); +} + +void dc_set_power_state( + struct dc *dc, + enum dc_acpi_cm_power_state power_state, + enum dc_video_power_state video_power_state) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + core_dc->previous_power_state = core_dc->current_power_state; + core_dc->current_power_state = video_power_state; + + switch (power_state) { + case DC_ACPI_CM_POWER_STATE_D0: + core_dc->hwss.init_hw(core_dc); + break; + default: + /* NULL means "reset/release all DC targets" */ + dc_commit_targets(dc, NULL, 0); + + core_dc->hwss.power_down(core_dc); + + /* Zero out the current context so that on resume we start with + * clean state, and dc hw programming optimizations will not + * cause any trouble. + */ + memset(core_dc->current_context, 0, + sizeof(*core_dc->current_context)); + + core_dc->current_context->res_ctx.pool = core_dc->res_pool; + + break; + } + +} + +void dc_resume(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + uint32_t i; + + for (i = 0; i < core_dc->link_count; i++) + core_link_resume(core_dc->links[i]); +} + +bool dc_read_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *data, + uint32_t size) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + enum ddc_result r = dal_ddc_service_read_dpcd_data( + link->ddc, + address, + data, + size); + return r == DDC_RESULT_SUCESSFULL; +} + +bool dc_write_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + const uint8_t *data, + uint32_t size) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + + enum ddc_result r = dal_ddc_service_write_dpcd_data( + link->ddc, + address, + data, + size); + return r == DDC_RESULT_SUCESSFULL; +} + +bool dc_submit_i2c( + struct dc *dc, + uint32_t link_index, + struct i2c_command *cmd) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + struct ddc_service *ddc = link->ddc; + + return dal_i2caux_submit_i2c_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + cmd); +} + +static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_sink *sink) +{ + struct dc_link *dc_link = &core_link->public; + + if (dc_link->sink_count >= MAX_SINKS_PER_LINK) { + BREAK_TO_DEBUGGER(); + return false; + } + + dc_sink_retain(sink); + + dc_link->remote_sinks[dc_link->sink_count] = sink; + dc_link->sink_count++; + + return true; +} + +struct dc_sink *dc_link_add_remote_sink( + const struct dc_link *link, + const uint8_t *edid, + int len, + struct dc_sink_init_data *init_data) +{ + struct dc_sink *dc_sink; + enum dc_edid_status edid_status; + struct core_link *core_link = DC_LINK_TO_LINK(link); + + if (len > MAX_EDID_BUFFER_SIZE) { + dm_error("Max EDID buffer size breached!\n"); + return NULL; + } + + if (!init_data) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (!init_data->link) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dc_sink = dc_sink_create(init_data); + + if (!dc_sink) + return NULL; + + memmove(dc_sink->dc_edid.raw_edid, edid, len); + dc_sink->dc_edid.length = len; + + if (!link_add_remote_sink_helper( + core_link, + dc_sink)) + goto fail_add_sink; + + edid_status = dm_helpers_parse_edid_caps( + core_link->ctx, + &dc_sink->dc_edid, + &dc_sink->edid_caps); + + if (edid_status != EDID_OK) + goto fail; + + return dc_sink; +fail: + dc_link_remove_remote_sink(link, dc_sink); +fail_add_sink: + dc_sink_release(dc_sink); + return NULL; +} + +void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink) +{ + struct core_link *core_link = DC_LINK_TO_LINK(link); + struct dc_link *dc_link = &core_link->public; + + dc_link->local_sink = sink; + + if (sink == NULL) { + dc_link->type = dc_connection_none; + } else { + dc_link->type = dc_connection_single; + } +} + +void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink) +{ + int i; + struct core_link *core_link = DC_LINK_TO_LINK(link); + struct dc_link *dc_link = &core_link->public; + + if (!link->sink_count) { + BREAK_TO_DEBUGGER(); + return; + } + + for (i = 0; i < dc_link->sink_count; i++) { + if (dc_link->remote_sinks[i] == sink) { + dc_sink_release(sink); + dc_link->remote_sinks[i] = NULL; + + /* shrink array to remove empty place */ + while (i < dc_link->sink_count - 1) { + dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1]; + i++; + } + + dc_link->sink_count--; + return; + } + } +} + +const struct dc_stream_status *dc_stream_get_status( + const struct dc_stream *dc_stream) +{ + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + + return &stream->status; +} + +bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct mem_input *mi = NULL; + + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + if (core_dc->res_pool->mis[i] != NULL) { + mi = core_dc->res_pool->mis[i]; + break; + } + } + if (mi == NULL) { + dm_error("no mem_input!\n"); + return false; + } + + if (mi->funcs->mem_input_update_dchub) + mi->funcs->mem_input_update_dchub(mi, dh_data); + else + ASSERT(mi->funcs->mem_input_update_dchub); + + + return true; + +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c new file mode 100644 index 000000000000..8ca0f1e0369a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -0,0 +1,270 @@ +/* + * dc_debug.c + * + * Created on: Nov 3, 2016 + * Author: yonsun + */ + +#include "dm_services.h" + +#include "dc.h" + +#include "core_status.h" +#include "core_types.h" +#include "hw_sequencer.h" + +#include "resource.h" + +#define SURFACE_TRACE(...) do {\ + if (dc->debug.surface_trace) \ + dm_logger_write(logger, \ + LOG_IF_TRACE, \ + ##__VA_ARGS__); \ +} while (0) + +void pre_surface_trace( + const struct dc *dc, + const struct dc_surface *const *surfaces, + int surface_count) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + for (i = 0; i < surface_count; i++) { + const struct dc_surface *surface = surfaces[i]; + + SURFACE_TRACE("Surface %d:\n", i); + + SURFACE_TRACE( + "surface->visible = %d;\n" + "surface->flip_immediate = %d;\n" + "surface->address.type = %d;\n" + "surface->address.grph.addr.quad_part = 0x%X;\n" + "surface->address.grph.meta_addr.quad_part = 0x%X;\n" + "surface->scaling_quality.h_taps = %d;\n" + "surface->scaling_quality.v_taps = %d;\n" + "surface->scaling_quality.h_taps_c = %d;\n" + "surface->scaling_quality.v_taps_c = %d;\n", + surface->visible, + surface->flip_immediate, + surface->address.type, + surface->address.grph.addr.quad_part, + surface->address.grph.meta_addr.quad_part, + surface->scaling_quality.h_taps, + surface->scaling_quality.v_taps, + surface->scaling_quality.h_taps_c, + surface->scaling_quality.v_taps_c); + + SURFACE_TRACE( + "surface->src_rect.x = %d;\n" + "surface->src_rect.y = %d;\n" + "surface->src_rect.width = %d;\n" + "surface->src_rect.height = %d;\n" + "surface->dst_rect.x = %d;\n" + "surface->dst_rect.y = %d;\n" + "surface->dst_rect.width = %d;\n" + "surface->dst_rect.height = %d;\n" + "surface->clip_rect.x = %d;\n" + "surface->clip_rect.y = %d;\n" + "surface->clip_rect.width = %d;\n" + "surface->clip_rect.height = %d;\n", + surface->src_rect.x, + surface->src_rect.y, + surface->src_rect.width, + surface->src_rect.height, + surface->dst_rect.x, + surface->dst_rect.y, + surface->dst_rect.width, + surface->dst_rect.height, + surface->clip_rect.x, + surface->clip_rect.y, + surface->clip_rect.width, + surface->clip_rect.height); + + SURFACE_TRACE( + "surface->plane_size.grph.surface_size.x = %d;\n" + "surface->plane_size.grph.surface_size.y = %d;\n" + "surface->plane_size.grph.surface_size.width = %d;\n" + "surface->plane_size.grph.surface_size.height = %d;\n" + "surface->plane_size.grph.surface_pitch = %d;\n" + "surface->plane_size.grph.meta_pitch = %d;\n", + surface->plane_size.grph.surface_size.x, + surface->plane_size.grph.surface_size.y, + surface->plane_size.grph.surface_size.width, + surface->plane_size.grph.surface_size.height, + surface->plane_size.grph.surface_pitch, + surface->plane_size.grph.meta_pitch); + + + SURFACE_TRACE( + "surface->tiling_info.gfx8.num_banks = %d;\n" + "surface->tiling_info.gfx8.bank_width = %d;\n" + "surface->tiling_info.gfx8.bank_width_c = %d;\n" + "surface->tiling_info.gfx8.bank_height = %d;\n" + "surface->tiling_info.gfx8.bank_height_c = %d;\n" + "surface->tiling_info.gfx8.tile_aspect = %d;\n" + "surface->tiling_info.gfx8.tile_aspect_c = %d;\n" + "surface->tiling_info.gfx8.tile_split = %d;\n" + "surface->tiling_info.gfx8.tile_split_c = %d;\n" + "surface->tiling_info.gfx8.tile_mode = %d;\n" + "surface->tiling_info.gfx8.tile_mode_c = %d;\n", + surface->tiling_info.gfx8.num_banks, + surface->tiling_info.gfx8.bank_width, + surface->tiling_info.gfx8.bank_width_c, + surface->tiling_info.gfx8.bank_height, + surface->tiling_info.gfx8.bank_height_c, + surface->tiling_info.gfx8.tile_aspect, + surface->tiling_info.gfx8.tile_aspect_c, + surface->tiling_info.gfx8.tile_split, + surface->tiling_info.gfx8.tile_split_c, + surface->tiling_info.gfx8.tile_mode, + surface->tiling_info.gfx8.tile_mode_c); + + SURFACE_TRACE( + "surface->tiling_info.gfx8.pipe_config = %d;\n" + "surface->tiling_info.gfx8.array_mode = %d;\n" + "surface->color_space = %d;\n" + "surface->dcc.enable = %d;\n" + "surface->format = %d;\n" + "surface->rotation = %d;\n" + "surface->stereo_format = %d;\n", + surface->tiling_info.gfx8.pipe_config, + surface->tiling_info.gfx8.array_mode, + surface->color_space, + surface->dcc.enable, + surface->format, + surface->rotation, + surface->stereo_format); + SURFACE_TRACE("\n"); + } + SURFACE_TRACE("\n"); +} + +void update_surface_trace( + const struct dc *dc, + const struct dc_surface_update *updates, + int surface_count) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + for (i = 0; i < surface_count; i++) { + const struct dc_surface_update *update = &updates[i]; + + SURFACE_TRACE("Update %d\n", i); + if (update->flip_addr) { + SURFACE_TRACE("flip_addr->address.type = %d;\n" + "flip_addr->address.grph.addr.quad_part = 0x%X;\n" + "flip_addr->address.grph.meta_addr.quad_part = 0x%X;\n" + "flip_addr->flip_immediate = %d;\n", + update->flip_addr->address.type, + update->flip_addr->address.grph.addr.quad_part, + update->flip_addr->address.grph.meta_addr.quad_part, + update->flip_addr->flip_immediate); + } + + if (update->plane_info) { + SURFACE_TRACE( + "plane_info->color_space = %d;\n" + "plane_info->format = %d;\n" + "plane_info->plane_size.grph.meta_pitch = %d;\n" + "plane_info->plane_size.grph.surface_pitch = %d;\n" + "plane_info->plane_size.grph.surface_size.height = %d;\n" + "plane_info->plane_size.grph.surface_size.width = %d;\n" + "plane_info->plane_size.grph.surface_size.x = %d;\n" + "plane_info->plane_size.grph.surface_size.y = %d;\n" + "plane_info->rotation = %d;\n", + update->plane_info->color_space, + update->plane_info->format, + update->plane_info->plane_size.grph.meta_pitch, + update->plane_info->plane_size.grph.surface_pitch, + update->plane_info->plane_size.grph.surface_size.height, + update->plane_info->plane_size.grph.surface_size.width, + update->plane_info->plane_size.grph.surface_size.x, + update->plane_info->plane_size.grph.surface_size.y, + update->plane_info->rotation, + update->plane_info->stereo_format); + + SURFACE_TRACE( + "plane_info->tiling_info.gfx8.num_banks = %d;\n" + "plane_info->tiling_info.gfx8.bank_width = %d;\n" + "plane_info->tiling_info.gfx8.bank_width_c = %d;\n" + "plane_info->tiling_info.gfx8.bank_height = %d;\n" + "plane_info->tiling_info.gfx8.bank_height_c = %d;\n" + "plane_info->tiling_info.gfx8.tile_aspect = %d;\n" + "plane_info->tiling_info.gfx8.tile_aspect_c = %d;\n" + "plane_info->tiling_info.gfx8.tile_split = %d;\n" + "plane_info->tiling_info.gfx8.tile_split_c = %d;\n" + "plane_info->tiling_info.gfx8.tile_mode = %d;\n" + "plane_info->tiling_info.gfx8.tile_mode_c = %d;\n", + update->plane_info->tiling_info.gfx8.num_banks, + update->plane_info->tiling_info.gfx8.bank_width, + update->plane_info->tiling_info.gfx8.bank_width_c, + update->plane_info->tiling_info.gfx8.bank_height, + update->plane_info->tiling_info.gfx8.bank_height_c, + update->plane_info->tiling_info.gfx8.tile_aspect, + update->plane_info->tiling_info.gfx8.tile_aspect_c, + update->plane_info->tiling_info.gfx8.tile_split, + update->plane_info->tiling_info.gfx8.tile_split_c, + update->plane_info->tiling_info.gfx8.tile_mode, + update->plane_info->tiling_info.gfx8.tile_mode_c); + + SURFACE_TRACE( + "plane_info->tiling_info.gfx8.pipe_config = %d;\n" + "plane_info->tiling_info.gfx8.array_mode = %d;\n" + "plane_info->visible = %d;\n", + update->plane_info->tiling_info.gfx8.pipe_config, + update->plane_info->tiling_info.gfx8.array_mode, + update->plane_info->visible); + } + + if (update->scaling_info) { + SURFACE_TRACE( + "scaling_info->src_rect.x = %d;\n" + "scaling_info->src_rect.y = %d;\n" + "scaling_info->src_rect.width = %d;\n" + "scaling_info->src_rect.height = %d;\n" + "scaling_info->dst_rect.x = %d;\n" + "scaling_info->dst_rect.y = %d;\n" + "scaling_info->dst_rect.width = %d;\n" + "scaling_info->dst_rect.height = %d;\n" + "scaling_info->clip_rect.x = %d;\n" + "scaling_info->clip_rect.y = %d;\n" + "scaling_info->clip_rect.width = %d;\n" + "scaling_info->clip_rect.height = %d;\n" + "scaling_info->scaling_quality.h_taps = %d;\n" + "scaling_info->scaling_quality.v_taps = %d;\n" + "scaling_info->scaling_quality.h_taps_c = %d;\n" + "scaling_info->scaling_quality.v_taps_c = %d;\n", + update->scaling_info->src_rect.x, + update->scaling_info->src_rect.y, + update->scaling_info->src_rect.width, + update->scaling_info->src_rect.height, + update->scaling_info->dst_rect.x, + update->scaling_info->dst_rect.y, + update->scaling_info->dst_rect.width, + update->scaling_info->dst_rect.height, + update->scaling_info->clip_rect.x, + update->scaling_info->clip_rect.y, + update->scaling_info->clip_rect.width, + update->scaling_info->clip_rect.height, + update->scaling_info->scaling_quality.h_taps, + update->scaling_info->scaling_quality.v_taps, + update->scaling_info->scaling_quality.h_taps_c, + update->scaling_info->scaling_quality.v_taps_c); + } + SURFACE_TRACE("\n"); + } + SURFACE_TRACE("\n"); +} + +void post_surface_trace(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + SURFACE_TRACE("post surface process.\n"); + +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c new file mode 100644 index 000000000000..d5cffa51ca96 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -0,0 +1,93 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "core_types.h" +#include "core_dc.h" +#include "timing_generator.h" +#include "hw_sequencer.h" + +/* used as index in array of black_color_format */ +enum black_color_format { + BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, + BLACK_COLOR_FORMAT_RGB_LIMITED, + BLACK_COLOR_FORMAT_YUV_TV, + BLACK_COLOR_FORMAT_YUV_CV, + BLACK_COLOR_FORMAT_YUV_SUPER_AA, + BLACK_COLOR_FORMAT_DEBUG, +}; + +static const struct tg_color black_color_format[] = { + /* BlackColorFormat_RGB_FullRange */ + {0, 0, 0}, + /* BlackColorFormat_RGB_Limited */ + {0x40, 0x40, 0x40}, + /* BlackColorFormat_YUV_TV */ + {0x200, 0x40, 0x200}, + /* BlackColorFormat_YUV_CV */ + {0x1f4, 0x40, 0x1f4}, + /* BlackColorFormat_YUV_SuperAA */ + {0x1a2, 0x20, 0x1a2}, + /* visual confirm debug */ + {0xff, 0xff, 0}, +}; + +void color_space_to_black_color( + const struct core_dc *dc, + enum dc_color_space colorspace, + struct tg_color *black_color) +{ + if (dc->public.debug.surface_visual_confirm) { + *black_color = + black_color_format[BLACK_COLOR_FORMAT_DEBUG]; + return; + } + + switch (colorspace) { + case COLOR_SPACE_YPBPR601: + *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_TV]; + break; + + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV]; + break; + + case COLOR_SPACE_SRGB_LIMITED: + *black_color = + black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED]; + break; + + default: + /* fefault is sRGB black (full range). */ + *black_color = + black_color_format[BLACK_COLOR_FORMAT_RGB_FULLRANGE]; + /* default is sRGB black 0. */ + break; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c new file mode 100644 index 000000000000..70a25546de1e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -0,0 +1,1899 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dm_helpers.h" +#include "dc.h" +#include "core_dc.h" +#include "grph_object_id.h" +#include "gpio_service_interface.h" +#include "core_status.h" +#include "dc_link_dp.h" +#include "dc_link_ddc.h" +#include "link_hwss.h" +#include "stream_encoder.h" +#include "link_encoder.h" +#include "hw_sequencer.h" +#include "resource.h" +#include "fixed31_32.h" +#include "include/asic_capability_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_enum.h" +#include "dce/dce_11_0_sh_mask.h" + +#ifndef mmDMCU_STATUS__UC_IN_RESET__SHIFT +#define mmDMCU_STATUS__UC_IN_RESET__SHIFT 0x0 +#endif + +#ifndef mmDMCU_STATUS__UC_IN_RESET_MASK +#define mmDMCU_STATUS__UC_IN_RESET_MASK 0x00000001L +#endif + +#define LINK_INFO(...) \ + dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ + __VA_ARGS__) + +/******************************************************************************* + * Private structures + ******************************************************************************/ + +enum { + LINK_RATE_REF_FREQ_IN_MHZ = 27, + PEAK_FACTOR_X1000 = 1006 +}; + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static void destruct(struct core_link *link) +{ + int i; + + if (link->ddc) + dal_ddc_service_destroy(&link->ddc); + + if(link->link_enc) + link->link_enc->funcs->destroy(&link->link_enc); + + if (link->public.local_sink) + dc_sink_release(link->public.local_sink); + + for (i = 0; i < link->public.sink_count; ++i) + dc_sink_release(link->public.remote_sinks[i]); +} + +static struct gpio *get_hpd_gpio(const struct core_link *link) +{ + enum bp_result bp_result; + struct dc_bios *dcb = link->ctx->dc_bios; + struct graphics_object_hpd_info hpd_info; + struct gpio_pin_info pin_info; + + if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK) + return NULL; + + bp_result = dcb->funcs->get_gpio_pin_info(dcb, + hpd_info.hpd_int_gpio_uid, &pin_info); + + if (bp_result != BP_RESULT_OK) { + ASSERT(bp_result == BP_RESULT_NORECORD); + return NULL; + } + + return dal_gpio_service_create_irq( + link->ctx->gpio_service, + pin_info.offset, + pin_info.mask); +} + +/* + * Function: program_hpd_filter + * + * @brief + * Programs HPD filter on associated HPD line + * + * @param [in] delay_on_connect_in_ms: Connect filter timeout + * @param [in] delay_on_disconnect_in_ms: Disconnect filter timeout + * + * @return + * true on success, false otherwise + */ +static bool program_hpd_filter( + const struct core_link *link) +{ + bool result = false; + + struct gpio *hpd; + + int delay_on_connect_in_ms = 0; + int delay_on_disconnect_in_ms = 0; + + /* Verify feature is supported */ + switch (link->public.connector_signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + /* Program hpd filter */ + delay_on_connect_in_ms = 500; + delay_on_disconnect_in_ms = 100; + break; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* Program hpd filter to allow DP signal to settle */ + /* 500: not able to detect MST <-> SST switch as HPD is low for + * only 100ms on DELL U2413 + * 0: some passive dongle still show aux mode instead of i2c + * 20-50:not enough to hide bouncing HPD with passive dongle. + * also see intermittent i2c read issues. + */ + delay_on_connect_in_ms = 80; + delay_on_disconnect_in_ms = 0; + break; + case SIGNAL_TYPE_LVDS: + case SIGNAL_TYPE_EDP: + default: + /* Don't program hpd filter */ + return false; + } + + /* Obtain HPD handle */ + hpd = get_hpd_gpio(link); + + if (!hpd) + return result; + + /* Setup HPD filtering */ + if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) { + struct gpio_hpd_config config; + + config.delay_on_connect = delay_on_connect_in_ms; + config.delay_on_disconnect = delay_on_disconnect_in_ms; + + dal_irq_setup_hpd_filter(hpd, &config); + + dal_gpio_close(hpd); + + result = true; + } else { + ASSERT_CRITICAL(false); + } + + /* Release HPD handle */ + dal_gpio_destroy_irq(&hpd); + + return result; +} + +static bool detect_sink(struct core_link *link, enum dc_connection_type *type) +{ + uint32_t is_hpd_high = 0; + struct gpio *hpd_pin; + + /* todo: may need to lock gpio access */ + hpd_pin = get_hpd_gpio(link); + if (hpd_pin == NULL) + goto hpd_gpio_failure; + + dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT); + dal_gpio_get_value(hpd_pin, &is_hpd_high); + dal_gpio_close(hpd_pin); + dal_gpio_destroy_irq(&hpd_pin); + + if (is_hpd_high) { + *type = dc_connection_single; + /* TODO: need to do the actual detection */ + } else { + *type = dc_connection_none; + } + + return true; + +hpd_gpio_failure: + return false; +} + +enum ddc_transaction_type get_ddc_transaction_type( + enum signal_type sink_signal) +{ + enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE; + + switch (sink_signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + case SIGNAL_TYPE_LVDS: + case SIGNAL_TYPE_RGB: + transaction_type = DDC_TRANSACTION_TYPE_I2C; + break; + + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; + break; + + case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* MST does not use I2COverAux, but there is the + * SPECIAL use case for "immediate dwnstrm device + * access" (EPR#370830). */ + transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; + break; + + default: + break; + } + + return transaction_type; +} + +static enum signal_type get_basic_signal_type( + struct graphics_object_id encoder, + struct graphics_object_id downstream) +{ + if (downstream.type == OBJECT_TYPE_CONNECTOR) { + switch (downstream.id) { + case CONNECTOR_ID_SINGLE_LINK_DVII: + switch (encoder.id) { + case ENCODER_ID_INTERNAL_DAC1: + case ENCODER_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_ID_INTERNAL_DAC2: + case ENCODER_ID_INTERNAL_KLDSCP_DAC2: + return SIGNAL_TYPE_RGB; + default: + return SIGNAL_TYPE_DVI_SINGLE_LINK; + } + break; + case CONNECTOR_ID_DUAL_LINK_DVII: + { + switch (encoder.id) { + case ENCODER_ID_INTERNAL_DAC1: + case ENCODER_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_ID_INTERNAL_DAC2: + case ENCODER_ID_INTERNAL_KLDSCP_DAC2: + return SIGNAL_TYPE_RGB; + default: + return SIGNAL_TYPE_DVI_DUAL_LINK; + } + } + break; + case CONNECTOR_ID_SINGLE_LINK_DVID: + return SIGNAL_TYPE_DVI_SINGLE_LINK; + case CONNECTOR_ID_DUAL_LINK_DVID: + return SIGNAL_TYPE_DVI_DUAL_LINK; + case CONNECTOR_ID_VGA: + return SIGNAL_TYPE_RGB; + case CONNECTOR_ID_HDMI_TYPE_A: + return SIGNAL_TYPE_HDMI_TYPE_A; + case CONNECTOR_ID_LVDS: + return SIGNAL_TYPE_LVDS; + case CONNECTOR_ID_DISPLAY_PORT: + return SIGNAL_TYPE_DISPLAY_PORT; + case CONNECTOR_ID_EDP: + return SIGNAL_TYPE_EDP; + default: + return SIGNAL_TYPE_NONE; + } + } else if (downstream.type == OBJECT_TYPE_ENCODER) { + switch (downstream.id) { + case ENCODER_ID_EXTERNAL_NUTMEG: + case ENCODER_ID_EXTERNAL_TRAVIS: + return SIGNAL_TYPE_DISPLAY_PORT; + default: + return SIGNAL_TYPE_NONE; + } + } + + return SIGNAL_TYPE_NONE; +} + +/* + * @brief + * Check whether there is a dongle on DP connector + */ +static bool is_dp_sink_present(struct core_link *link) +{ + enum gpio_result gpio_result; + uint32_t clock_pin = 0; + uint32_t data_pin = 0; + + struct ddc *ddc; + + enum connector_id connector_id = + dal_graphics_object_id_get_connector_id(link->link_id); + + bool present = + ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || + (connector_id == CONNECTOR_ID_EDP)); + + ddc = dal_ddc_service_get_ddc_pin(link->ddc); + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return present; + } + + /* Open GPIO and set it to I2C mode */ + /* Note: this GpioMode_Input will be converted + * to GpioConfigType_I2cAuxDualMode in GPIO component, + * which indicates we need additional delay */ + + if (GPIO_RESULT_OK != dal_ddc_open( + ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) { + dal_gpio_destroy_ddc(&ddc); + + return present; + } + + /* Read GPIO: DP sink is present if both clock and data pins are zero */ + /* [anaumov] in DAL2, there was no check for GPIO failure */ + + gpio_result = dal_gpio_get_value(ddc->pin_clock, &clock_pin); + ASSERT(gpio_result == GPIO_RESULT_OK); + + if (gpio_result == GPIO_RESULT_OK) + if (link->link_enc->features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN) + gpio_result = dal_gpio_get_value(ddc->pin_data, &data_pin); + + present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin); + + dal_ddc_close(ddc); + + return present; +} + +/* + * @brief + * Detect output sink type + */ +static enum signal_type link_detect_sink(struct core_link *link) +{ + enum signal_type result = get_basic_signal_type( + link->link_enc->id, link->link_id); + + /* Internal digital encoder will detect only dongles + * that require digital signal */ + + /* Detection mechanism is different + * for different native connectors. + * LVDS connector supports only LVDS signal; + * PCIE is a bus slot, the actual connector needs to be detected first; + * eDP connector supports only eDP signal; + * HDMI should check straps for audio */ + + /* PCIE detects the actual connector on add-on board */ + + if (link->link_id.id == CONNECTOR_ID_PCIE) { + /* ZAZTODO implement PCIE add-on card detection */ + } + + switch (link->link_id.id) { + case CONNECTOR_ID_HDMI_TYPE_A: { + /* check audio support: + * if native HDMI is not supported, switch to DVI */ + struct audio_support *aud_support = &link->dc->res_pool->audio_support; + + if (!aud_support->hdmi_audio_native) + if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A) + result = SIGNAL_TYPE_DVI_SINGLE_LINK; + } + break; + case CONNECTOR_ID_DISPLAY_PORT: { + + /* Check whether DP signal detected: if not - + * we assume signal is DVI; it could be corrected + * to HDMI after dongle detection */ + if (!is_dp_sink_present(link)) + result = SIGNAL_TYPE_DVI_SINGLE_LINK; + } + break; + default: + break; + } + + return result; +} + +static enum signal_type decide_signal_from_strap_and_dongle_type( + enum display_dongle_type dongle_type, + struct audio_support *audio_support) +{ + enum signal_type signal = SIGNAL_TYPE_NONE; + + switch (dongle_type) { + case DISPLAY_DONGLE_DP_HDMI_DONGLE: + if (audio_support->hdmi_audio_on_dongle) + signal = SIGNAL_TYPE_HDMI_TYPE_A; + else + signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + case DISPLAY_DONGLE_DP_DVI_DONGLE: + signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE: + if (audio_support->hdmi_audio_native) + signal = SIGNAL_TYPE_HDMI_TYPE_A; + else + signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + default: + signal = SIGNAL_TYPE_NONE; + break; + } + + return signal; +} + +static enum signal_type dp_passive_dongle_detection( + struct ddc_service *ddc, + struct display_sink_capability *sink_cap, + struct audio_support *audio_support) +{ + dal_ddc_service_i2c_query_dp_dual_mode_adaptor( + ddc, sink_cap); + return decide_signal_from_strap_and_dongle_type( + sink_cap->dongle_type, + audio_support); +} + +static void link_disconnect_sink(struct core_link *link) +{ + if (link->public.local_sink) { + dc_sink_release(link->public.local_sink); + link->public.local_sink = NULL; + } + + link->dpcd_sink_count = 0; +} + +static enum dc_edid_status read_edid( + struct core_link *link, + struct core_sink *sink) +{ + uint32_t edid_retry = 3; + enum dc_edid_status edid_status; + + /* some dongles read edid incorrectly the first time, + * do check sum and retry to make sure read correct edid. + */ + do { + sink->public.dc_edid.length = + dal_ddc_service_edid_query(link->ddc); + + if (0 == sink->public.dc_edid.length) + return EDID_NO_RESPONSE; + + dal_ddc_service_get_edid_buf(link->ddc, + sink->public.dc_edid.raw_edid); + edid_status = dm_helpers_parse_edid_caps( + sink->ctx, + &sink->public.dc_edid, + &sink->public.edid_caps); + --edid_retry; + if (edid_status == EDID_BAD_CHECKSUM) + dm_logger_write(link->ctx->logger, LOG_WARNING, + "Bad EDID checksum, retry remain: %d\n", + edid_retry); + } while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0); + + return edid_status; +} + +static void detect_dp( + struct core_link *link, + struct display_sink_capability *sink_caps, + bool *converter_disable_audio, + struct audio_support *audio_support, + bool boot) +{ + sink_caps->signal = link_detect_sink(link); + sink_caps->transaction_type = + get_ddc_transaction_type(sink_caps->signal); + + if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) { + sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; + detect_dp_sink_caps(link); + + /* DP active dongles */ + if (is_dp_active_dongle(link)) { + link->public.type = dc_connection_active_dongle; + if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) { + /* + * active dongle unplug processing for short irq + */ + link_disconnect_sink(link); + return; + } + + if (link->dpcd_caps.dongle_type != + DISPLAY_DONGLE_DP_HDMI_CONVERTER) { + *converter_disable_audio = true; + } + } + if (is_mst_supported(link)) { + sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + + /* + * This call will initiate MST topology discovery. Which + * will detect MST ports and add new DRM connector DRM + * framework. Then read EDID via remote i2c over aux. In + * the end, will notify DRM detect result and save EDID + * into DRM framework. + * + * .detect is called by .fill_modes. + * .fill_modes is called by user mode ioctl + * DRM_IOCTL_MODE_GETCONNECTOR. + * + * .get_modes is called by .fill_modes. + * + * call .get_modes, AMDGPU DM implementation will create + * new dc_sink and add to dc_link. For long HPD plug + * in/out, MST has its own handle. + * + * Therefore, just after dc_create, link->sink is not + * created for MST until user mode app calls + * DRM_IOCTL_MODE_GETCONNECTOR. + * + * Need check ->sink usages in case ->sink = NULL + * TODO: s3 resume check + */ + + if (dm_helpers_dp_mst_start_top_mgr( + link->ctx, + &link->public, boot)) { + link->public.type = dc_connection_mst_branch; + } else { + /* MST not supported */ + sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; + } + } + } else { + /* DP passive dongles */ + sink_caps->signal = dp_passive_dongle_detection(link->ddc, + sink_caps, + audio_support); + } +} + +bool dc_link_detect(const struct dc_link *dc_link, bool boot) +{ + struct core_link *link = DC_LINK_TO_LINK(dc_link); + struct dc_sink_init_data sink_init_data = { 0 }; + struct display_sink_capability sink_caps = { 0 }; + uint8_t i; + bool converter_disable_audio = false; + struct audio_support *aud_support = &link->dc->res_pool->audio_support; + enum dc_edid_status edid_status; + struct dc_context *dc_ctx = link->ctx; + struct dc_sink *dc_sink; + struct core_sink *sink = NULL; + enum dc_connection_type new_connection_type = dc_connection_none; + + if (link->public.connector_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + if (false == detect_sink(link, &new_connection_type)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (link->public.connector_signal == SIGNAL_TYPE_EDP && + link->public.local_sink) + return true; + + link_disconnect_sink(link); + + if (new_connection_type != dc_connection_none) { + link->public.type = new_connection_type; + + /* From Disconnected-to-Connected. */ + switch (link->public.connector_signal) { + case SIGNAL_TYPE_HDMI_TYPE_A: { + sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; + if (aud_support->hdmi_audio_native) + sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A; + else + sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + } + + case SIGNAL_TYPE_DVI_SINGLE_LINK: { + sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; + sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + } + + case SIGNAL_TYPE_DVI_DUAL_LINK: { + sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; + sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK; + break; + } + + case SIGNAL_TYPE_EDP: { + detect_dp_sink_caps(link); + sink_caps.transaction_type = + DDC_TRANSACTION_TYPE_I2C_OVER_AUX; + sink_caps.signal = SIGNAL_TYPE_EDP; + break; + } + + case SIGNAL_TYPE_DISPLAY_PORT: { + detect_dp( + link, + &sink_caps, + &converter_disable_audio, + aud_support, boot); + + /* Active dongle downstream unplug */ + if (link->public.type == dc_connection_active_dongle + && link->dpcd_caps.sink_count. + bits.SINK_COUNT == 0) + return true; + + if (link->public.type == dc_connection_mst_branch) { + LINK_INFO("link=%d, mst branch is now Connected\n", + link->public.link_index); + return false; + } + + break; + } + + default: + DC_ERROR("Invalid connector type! signal:%d\n", + link->public.connector_signal); + return false; + } /* switch() */ + + if (link->dpcd_caps.sink_count.bits.SINK_COUNT) + link->dpcd_sink_count = link->dpcd_caps.sink_count. + bits.SINK_COUNT; + else + link->dpcd_sink_count = 1; + + dal_ddc_service_set_transaction_type( + link->ddc, + sink_caps.transaction_type); + + sink_init_data.link = &link->public; + sink_init_data.sink_signal = sink_caps.signal; + sink_init_data.dongle_max_pix_clk = + sink_caps.max_hdmi_pixel_clock; + sink_init_data.converter_disable_audio = + converter_disable_audio; + + dc_sink = dc_sink_create(&sink_init_data); + if (!dc_sink) { + DC_ERROR("Failed to create sink!\n"); + return false; + } + + sink = DC_SINK_TO_CORE(dc_sink); + link->public.local_sink = &sink->public; + + edid_status = read_edid(link, sink); + + switch (edid_status) { + case EDID_BAD_CHECKSUM: + dm_logger_write(link->ctx->logger, LOG_ERROR, + "EDID checksum invalid.\n"); + break; + case EDID_NO_RESPONSE: + dm_logger_write(link->ctx->logger, LOG_ERROR, + "No EDID read.\n"); + return false; + + default: + break; + } + + /* HDMI-DVI Dongle */ + if (dc_sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && + !dc_sink->edid_caps.edid_hdmi) + dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + + /* Connectivity log: detection */ + for (i = 0; i < sink->public.dc_edid.length / EDID_BLOCK_SIZE; i++) { + CONN_DATA_DETECT(link, + &sink->public.dc_edid.raw_edid[i * EDID_BLOCK_SIZE], + EDID_BLOCK_SIZE, + "%s: [Block %d] ", sink->public.edid_caps.display_name, i); + } + + dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER, + "%s: " + "manufacturer_id = %X, " + "product_id = %X, " + "serial_number = %X, " + "manufacture_week = %d, " + "manufacture_year = %d, " + "display_name = %s, " + "speaker_flag = %d, " + "audio_mode_count = %d\n", + __func__, + sink->public.edid_caps.manufacturer_id, + sink->public.edid_caps.product_id, + sink->public.edid_caps.serial_number, + sink->public.edid_caps.manufacture_week, + sink->public.edid_caps.manufacture_year, + sink->public.edid_caps.display_name, + sink->public.edid_caps.speaker_flags, + sink->public.edid_caps.audio_mode_count); + + for (i = 0; i < sink->public.edid_caps.audio_mode_count; i++) { + dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER, + "%s: mode number = %d, " + "format_code = %d, " + "channel_count = %d, " + "sample_rate = %d, " + "sample_size = %d\n", + __func__, + i, + sink->public.edid_caps.audio_modes[i].format_code, + sink->public.edid_caps.audio_modes[i].channel_count, + sink->public.edid_caps.audio_modes[i].sample_rate, + sink->public.edid_caps.audio_modes[i].sample_size); + } + + } else { + /* From Connected-to-Disconnected. */ + if (link->public.type == dc_connection_mst_branch) { + LINK_INFO("link=%d, mst branch is now Disconnected\n", + link->public.link_index); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public); + + link->mst_stream_alloc_table.stream_count = 0; + memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); + } + + link->public.type = dc_connection_none; + sink_caps.signal = SIGNAL_TYPE_NONE; + } + + LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", + link->public.link_index, &sink->public, + (sink_caps.signal == SIGNAL_TYPE_NONE ? + "Disconnected":"Connected")); + + return true; +} + +static enum hpd_source_id get_hpd_line( + struct core_link *link) +{ + struct gpio *hpd; + enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN; + + hpd = get_hpd_gpio(link); + + if (hpd) { + switch (dal_irq_get_source(hpd)) { + case DC_IRQ_SOURCE_HPD1: + hpd_id = HPD_SOURCEID1; + break; + case DC_IRQ_SOURCE_HPD2: + hpd_id = HPD_SOURCEID2; + break; + case DC_IRQ_SOURCE_HPD3: + hpd_id = HPD_SOURCEID3; + break; + case DC_IRQ_SOURCE_HPD4: + hpd_id = HPD_SOURCEID4; + break; + case DC_IRQ_SOURCE_HPD5: + hpd_id = HPD_SOURCEID5; + break; + case DC_IRQ_SOURCE_HPD6: + hpd_id = HPD_SOURCEID6; + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + dal_gpio_destroy_irq(&hpd); + } + + return hpd_id; +} + +static enum channel_id get_ddc_line(struct core_link *link) +{ + struct ddc *ddc; + enum channel_id channel = CHANNEL_ID_UNKNOWN; + + ddc = dal_ddc_service_get_ddc_pin(link->ddc); + + if (ddc) { + switch (dal_ddc_get_line(ddc)) { + case GPIO_DDC_LINE_DDC1: + channel = CHANNEL_ID_DDC1; + break; + case GPIO_DDC_LINE_DDC2: + channel = CHANNEL_ID_DDC2; + break; + case GPIO_DDC_LINE_DDC3: + channel = CHANNEL_ID_DDC3; + break; + case GPIO_DDC_LINE_DDC4: + channel = CHANNEL_ID_DDC4; + break; + case GPIO_DDC_LINE_DDC5: + channel = CHANNEL_ID_DDC5; + break; + case GPIO_DDC_LINE_DDC6: + channel = CHANNEL_ID_DDC6; + break; + case GPIO_DDC_LINE_DDC_VGA: + channel = CHANNEL_ID_DDC_VGA; + break; + case GPIO_DDC_LINE_I2C_PAD: + channel = CHANNEL_ID_I2C_PAD; + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + } + + return channel; +} + +static enum transmitter translate_encoder_to_transmitter( + struct graphics_object_id encoder) +{ + switch (encoder.id) { + case ENCODER_ID_INTERNAL_UNIPHY: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_UNIPHY_A; + case ENUM_ID_2: + return TRANSMITTER_UNIPHY_B; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_INTERNAL_UNIPHY1: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_UNIPHY_C; + case ENUM_ID_2: + return TRANSMITTER_UNIPHY_D; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_INTERNAL_UNIPHY2: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_UNIPHY_E; + case ENUM_ID_2: + return TRANSMITTER_UNIPHY_F; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_INTERNAL_UNIPHY3: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_UNIPHY_G; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_EXTERNAL_NUTMEG: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_NUTMEG_CRT; + default: + return TRANSMITTER_UNKNOWN; + } + break; + case ENCODER_ID_EXTERNAL_TRAVIS: + switch (encoder.enum_id) { + case ENUM_ID_1: + return TRANSMITTER_TRAVIS_CRT; + case ENUM_ID_2: + return TRANSMITTER_TRAVIS_LCD; + default: + return TRANSMITTER_UNKNOWN; + } + break; + default: + return TRANSMITTER_UNKNOWN; + } +} + +static bool construct( + struct core_link *link, + const struct link_init_data *init_params) +{ + uint8_t i; + struct gpio *hpd_gpio = NULL; + struct ddc_service_init_data ddc_service_init_data = { 0 }; + struct dc_context *dc_ctx = init_params->ctx; + struct encoder_init_data enc_init_data = { 0 }; + struct integrated_info info = {{{ 0 }}}; + struct dc_bios *bios = init_params->dc->ctx->dc_bios; + const struct dc_vbios_funcs *bp_funcs = bios->funcs; + + link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID; + link->public.irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; + + link->link_status.dpcd_caps = &link->dpcd_caps; + + link->dc = init_params->dc; + link->ctx = dc_ctx; + link->public.link_index = init_params->link_index; + + link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); + + if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { + dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n", + __func__, init_params->connector_index); + goto create_fail; + } + + hpd_gpio = get_hpd_gpio(link); + + if (hpd_gpio != NULL) + link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio); + + switch (link->link_id.id) { + case CONNECTOR_ID_HDMI_TYPE_A: + link->public.connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; + + break; + case CONNECTOR_ID_SINGLE_LINK_DVID: + case CONNECTOR_ID_SINGLE_LINK_DVII: + link->public.connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + break; + case CONNECTOR_ID_DUAL_LINK_DVID: + case CONNECTOR_ID_DUAL_LINK_DVII: + link->public.connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; + break; + case CONNECTOR_ID_DISPLAY_PORT: + link->public.connector_signal = SIGNAL_TYPE_DISPLAY_PORT; + + if (hpd_gpio != NULL) + link->public.irq_source_hpd_rx = + dal_irq_get_rx_source(hpd_gpio); + + break; + case CONNECTOR_ID_EDP: + link->public.connector_signal = SIGNAL_TYPE_EDP; + + if (hpd_gpio != NULL) { + link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID; + link->public.irq_source_hpd_rx = + dal_irq_get_rx_source(hpd_gpio); + } + break; + default: + dm_logger_write(dc_ctx->logger, LOG_WARNING, + "Unsupported Connector type:%d!\n", link->link_id.id); + goto create_fail; + } + + if (hpd_gpio != NULL) { + dal_gpio_destroy_irq(&hpd_gpio); + hpd_gpio = NULL; + } + + /* TODO: #DAL3 Implement id to str function.*/ + LINK_INFO("Connector[%d] description:" + "signal %d\n", + init_params->connector_index, + link->public.connector_signal); + + ddc_service_init_data.ctx = link->ctx; + ddc_service_init_data.id = link->link_id; + ddc_service_init_data.link = link; + link->ddc = dal_ddc_service_create(&ddc_service_init_data); + + if (NULL == link->ddc) { + DC_ERROR("Failed to create ddc_service!\n"); + goto ddc_create_fail; + } + + link->public.ddc_hw_inst = + dal_ddc_get_line( + dal_ddc_service_get_ddc_pin(link->ddc)); + + enc_init_data.ctx = dc_ctx; + bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder); + enc_init_data.connector = link->link_id; + enc_init_data.channel = get_ddc_line(link); + enc_init_data.hpd_source = get_hpd_line(link); + enc_init_data.transmitter = + translate_encoder_to_transmitter(enc_init_data.encoder); + link->link_enc = link->dc->res_pool->funcs->link_enc_create( + &enc_init_data); + + if( link->link_enc == NULL) { + DC_ERROR("Failed to create link encoder!\n"); + goto link_enc_create_fail; + } + + link->public.link_enc_hw_inst = link->link_enc->transmitter; + + for (i = 0; i < 4; i++) { + if (BP_RESULT_OK != + bp_funcs->get_device_tag(dc_ctx->dc_bios, link->link_id, i, &link->device_tag)) { + DC_ERROR("Failed to find device tag!\n"); + goto device_tag_fail; + } + + /* Look for device tag that matches connector signal, + * CRT for rgb, LCD for other supported signal tyes + */ + if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, link->device_tag.dev_id)) + continue; + if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT + && link->public.connector_signal != SIGNAL_TYPE_RGB) + continue; + if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD + && link->public.connector_signal == SIGNAL_TYPE_RGB) + continue; + if (link->device_tag.dev_id.device_type == DEVICE_TYPE_WIRELESS + && link->public.connector_signal != SIGNAL_TYPE_WIRELESS) + continue; + break; + } + + if (bios->integrated_info) + info = *bios->integrated_info; + + /* Look for channel mapping corresponding to connector and device tag */ + for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) { + struct external_display_path *path = + &info.ext_disp_conn_info.path[i]; + if (path->device_connector_id.enum_id == link->link_id.enum_id + && path->device_connector_id.id == link->link_id.id + && path->device_connector_id.type == link->link_id.type + && path->device_acpi_enum + == link->device_tag.acpi_device) { + link->ddi_channel_mapping = path->channel_mapping; + break; + } + } + + /* + * TODO check if GPIO programmed correctly + * + * If GPIO isn't programmed correctly HPD might not rise or drain + * fast enough, leading to bounces. + */ + program_hpd_filter(link); + + return true; +device_tag_fail: + link->link_enc->funcs->destroy(&link->link_enc); +link_enc_create_fail: + dal_ddc_service_destroy(&link->ddc); +ddc_create_fail: +create_fail: + + if (hpd_gpio != NULL) { + dal_gpio_destroy_irq(&hpd_gpio); + } + + return false; +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +struct core_link *link_create(const struct link_init_data *init_params) +{ + struct core_link *link = + dm_alloc(sizeof(*link)); + + if (NULL == link) + goto alloc_fail; + + if (false == construct(link, init_params)) + goto construct_fail; + + return link; + +construct_fail: + dm_free(link); + +alloc_fail: + return NULL; +} + +void link_destroy(struct core_link **link) +{ + destruct(*link); + dm_free(*link); + *link = NULL; +} + +static void dpcd_configure_panel_mode( + struct core_link *link, + enum dp_panel_mode panel_mode) +{ + union dpcd_edp_config edp_config_set; + bool panel_mode_edp = false; + + memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config)); + + if (DP_PANEL_MODE_DEFAULT != panel_mode) { + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + case DP_PANEL_MODE_SPECIAL: + panel_mode_edp = true; + break; + + default: + break; + } + + /*set edp panel mode in receiver*/ + core_link_read_dpcd( + link, + DPCD_ADDRESS_EDP_CONFIG_SET, + &edp_config_set.raw, + sizeof(edp_config_set.raw)); + + if (edp_config_set.bits.PANEL_MODE_EDP + != panel_mode_edp) { + enum ddc_result result = DDC_RESULT_UNKNOWN; + + edp_config_set.bits.PANEL_MODE_EDP = + panel_mode_edp; + result = core_link_write_dpcd( + link, + DPCD_ADDRESS_EDP_CONFIG_SET, + &edp_config_set.raw, + sizeof(edp_config_set.raw)); + + ASSERT(result == DDC_RESULT_SUCESSFULL); + } + } + dm_logger_write(link->ctx->logger, LOG_DETECTION_DP_CAPS, + "Link: %d eDP panel mode supported: %d " + "eDP panel mode enabled: %d \n", + link->public.link_index, + link->dpcd_caps.panel_mode_edp, + panel_mode_edp); +} + +static void enable_stream_features(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + union down_spread_ctrl downspread; + + core_link_read_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + &downspread.raw, sizeof(downspread)); + + downspread.bits.IGNORE_MSA_TIMING_PARAM = + (stream->public.ignore_msa_timing_param) ? 1 : 0; + + core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + &downspread.raw, sizeof(downspread)); +} + +static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + enum dc_status status; + bool skip_video_pattern; + struct core_link *link = stream->sink->link; + struct dc_link_settings link_settings = {0}; + enum dp_panel_mode panel_mode; + enum clocks_state cur_min_clock_state; + enum dc_link_rate max_link_rate = LINK_RATE_HIGH2; + + /* get link settings for video mode timing */ + decide_link_settings(stream, &link_settings); + + /* raise clock state for HBR3 if required. Confirmed with HW DCE/DPCS + * logic for HBR3 still needs Nominal (0.8V) on VDDC rail + */ + if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE) + max_link_rate = LINK_RATE_HIGH3; + + if (link_settings.link_rate == max_link_rate) { + cur_min_clock_state = CLOCKS_STATE_INVALID; + + if (dal_display_clock_get_min_clocks_state( + pipe_ctx->dis_clk, &cur_min_clock_state)) { + if (cur_min_clock_state < CLOCKS_STATE_NOMINAL) + dal_display_clock_set_min_clocks_state( + pipe_ctx->dis_clk, + CLOCKS_STATE_NOMINAL); + } else { + } + } + + dp_enable_link_phy( + link, + pipe_ctx->stream->signal, + pipe_ctx->clock_source->id, + &link_settings); + + panel_mode = dp_get_panel_mode(link); + dpcd_configure_panel_mode(link, panel_mode); + + skip_video_pattern = true; + + if (link_settings.link_rate == LINK_RATE_LOW) + skip_video_pattern = false; + + if (perform_link_training_with_retries( + link, + &link_settings, + skip_video_pattern, + LINK_TRAINING_ATTEMPTS)) { + link->public.cur_link_settings = link_settings; + status = DC_OK; + } + else + status = DC_ERROR_UNEXPECTED; + + enable_stream_features(pipe_ctx); + + return status; +} + +static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) +{ + struct core_link *link = pipe_ctx->stream->sink->link; + + /* sink signal type after MST branch is MST. Multiple MST sinks + * share one link. Link DP PHY is enable or training only once. + */ + if (link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) + return DC_OK; + + return enable_link_dp(pipe_ctx); +} + +static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + dal_ddc_service_write_scdc_data( + stream->sink->link->ddc, + stream->phy_pix_clk, + stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); + + memset(&stream->sink->link->public.cur_link_settings, 0, + sizeof(struct dc_link_settings)); + + link->link_enc->funcs->enable_tmds_output( + link->link_enc, + pipe_ctx->clock_source->id, + stream->public.timing.display_color_depth, + pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A, + pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK, + stream->phy_pix_clk); + + if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) + dal_ddc_service_read_scdc_data(link->ddc); +} + +/****************************enable_link***********************************/ +static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) +{ + enum dc_status status = DC_ERROR_UNEXPECTED; + switch (pipe_ctx->stream->signal) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + status = enable_link_dp(pipe_ctx); + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + status = enable_link_dp_mst(pipe_ctx); + msleep(200); + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + enable_link_hdmi(pipe_ctx); + status = DC_OK; + break; + case SIGNAL_TYPE_VIRTUAL: + status = DC_OK; + break; + default: + break; + } + + if (pipe_ctx->audio && status == DC_OK) { + /* notify audio driver for audio modes of monitor */ + pipe_ctx->audio->funcs->az_enable(pipe_ctx->audio); + + /* un-mute audio */ + /* TODO: audio should be per stream rather than per link */ + pipe_ctx->stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_enc, false); + } + + return status; +} + +static void disable_link(struct core_link *link, enum signal_type signal) +{ + /* + * TODO: implement call for dp_set_hw_test_pattern + * it is needed for compliance testing + */ + + /* here we need to specify that encoder output settings + * need to be calculated as for the set mode, + * it will lead to querying dynamic link capabilities + * which should be done before enable output */ + + if (dc_is_dp_signal(signal)) { + /* SST DP, eDP */ + if (dc_is_dp_sst_signal(signal)) + dp_disable_link_phy(link, signal); + else + dp_disable_link_phy_mst(link, signal); + } else + link->link_enc->funcs->disable_output(link->link_enc, signal); +} + +enum dc_status dc_link_validate_mode_timing( + const struct core_stream *stream, + struct core_link *link, + const struct dc_crtc_timing *timing) +{ + uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; + + /* A hack to avoid failing any modes for EDID override feature on + * topology change such as lower quality cable for DP or different dongle + */ + if (link->public.remote_sinks[0]) + return DC_OK; + + if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk) + return DC_EXCEED_DONGLE_MAX_CLK; + + switch (stream->signal) { + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + if (!dp_validate_mode_timing( + link, + timing)) + return DC_NO_DP_LINK_BANDWIDTH; + break; + + default: + break; + } + + return DC_OK; +} + + +bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, + uint32_t frame_ramp, const struct dc_stream *stream) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + unsigned int controller_id = 0; + int i; + uint32_t dmcu_status; + + dm_logger_write(ctx->logger, LOG_BACKLIGHT, + "New Backlight level: %d (0x%X)\n", level, level); + + dmcu_status = dm_read_reg(ctx, mmDMCU_STATUS); + + /* If DMCU is in reset state, DMCU is uninitialized */ + if (get_reg_field_value(dmcu_status, mmDMCU_STATUS, UC_IN_RESET)) { + link->link_enc->funcs->set_lcd_backlight_level(link->link_enc, + level); + } else { + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) + /* dmcu -1 for all controller id values, + * therefore +1 here + */ + controller_id = core_dc->current_context->res_ctx. + pipe_ctx[i].tg->inst + 1; + } + + link->link_enc->funcs->set_dmcu_backlight_level + (link->link_enc, level, + frame_ramp, controller_id); + } + return true; +} + + +bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + + if (link->link_enc->funcs->init_dmcu_backlight_settings != NULL) + link->link_enc->funcs-> + init_dmcu_backlight_settings(link->link_enc); + + return true; +} + +bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + + dm_logger_write(ctx->logger, LOG_BACKLIGHT, + "New abm level: %d (0x%X)\n", level, level); + + link->link_enc->funcs->set_dmcu_abm_level(link->link_enc, level); + return true; +} + +bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + + if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) + link->link_enc->funcs->set_dmcu_psr_enable(link->link_enc, + enable); + return true; +} + +bool dc_link_setup_psr(const struct dc_link *dc_link, + const struct dc_stream *stream) +{ + + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct psr_dmcu_context psr_context = {0}; + int i; + + psr_context.controllerId = CONTROLLER_ID_UNDEFINED; + + + if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) { + /* updateSinkPsrDpcdConfig*/ + union dpcd_psr_configuration psr_configuration; + + memset(&psr_configuration, 0, sizeof(psr_configuration)); + + psr_configuration.bits.ENABLE = 1; + psr_configuration.bits.CRC_VERIFICATION = 1; + psr_configuration.bits.FRAME_CAPTURE_INDICATION = + dc_link->psr_caps.psr_frame_capture_indication_req; + + /* Check for PSR v2*/ + if (dc_link->psr_caps.psr_version == 0x2) { + /* For PSR v2 selective update. + * Indicates whether sink should start capturing + * immediately following active scan line, + * or starting with the 2nd active scan line. + */ + psr_configuration.bits.LINE_CAPTURE_INDICATION = 0; + /*For PSR v2, determines whether Sink should generate + * IRQ_HPD when CRC mismatch is detected. + */ + psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; + } + dal_ddc_service_write_dpcd_data( + link->ddc, + 368, + &psr_configuration.raw, + sizeof(psr_configuration.raw)); + + psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; + if (psr_context.channel == 0) + psr_context.channel = 1; + psr_context.transmitterId = link->link_enc->transmitter; + psr_context.engineId = link->link_enc->preferred_engine; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) { + /* dmcu -1 for all controller id values, + * therefore +1 here + */ + psr_context.controllerId = + core_dc->current_context->res_ctx. + pipe_ctx[i].tg->inst + 1; + break; + } + } + + /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ + psr_context.phyType = PHY_TYPE_UNIPHY; + /*PhyId is associated with the transmitter id*/ + psr_context.smuPhyId = link->link_enc->transmitter; + + psr_context.crtcTimingVerticalTotal = stream->timing.v_total; + psr_context.vsyncRateHz = div64_u64(div64_u64((stream-> + timing.pix_clk_khz * 1000), + stream->timing.v_total), + stream->timing.h_total); + + psr_context.psrSupportedDisplayConfig = + (dc_link->psr_caps.psr_version > 0) ? true : false; + psr_context.psrExitLinkTrainingRequired = + dc_link->psr_caps.psr_exit_link_training_required; + psr_context.sdpTransmitLineNumDeadline = + dc_link->psr_caps.psr_sdp_transmit_line_num_deadline; + psr_context.psrFrameCaptureIndicationReq = + dc_link->psr_caps.psr_frame_capture_indication_req; + + psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */ + + psr_context.numberOfControllers = + link->dc->res_pool->res_cap->num_timing_generator; + + psr_context.rfb_update_auto_en = true; + + /* 2 frames before enter PSR. */ + psr_context.timehyst_frames = 2; + /* half a frame + * (units in 100 lines, i.e. a value of 1 represents 100 lines) + */ + psr_context.hyst_lines = stream->timing.v_total / 2 / 100; + psr_context.aux_repeats = 10; + + psr_context.psr_level.u32all = 0; + + /* SMU will perform additional powerdown sequence. + * For unsupported ASICs, set psr_level flag to skip PSR + * static screen notification to SMU. + * (Always set for DAL2, did not check ASIC) + */ + psr_context.psr_level.bits.SKIP_SMU_NOTIFICATION = 1; + + /* Controls additional delay after remote frame capture before + * continuing power down, default = 0 + */ + psr_context.frame_delay = 0; + + link->link_enc->funcs->setup_dmcu_psr + (link->link_enc, &psr_context); + return true; + } else + return false; + +} + +const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + + return &link->link_status; +} + +void core_link_resume(struct core_link *link) +{ + if (link->public.connector_signal != SIGNAL_TYPE_VIRTUAL) + program_hpd_filter(link); +} + +static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream) +{ + struct dc_link_settings *link_settings = + &stream->sink->link->public.cur_link_settings; + uint32_t link_rate_in_mbps = + link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ; + struct fixed31_32 mbps = dal_fixed31_32_from_int( + link_rate_in_mbps * link_settings->lane_count); + + return dal_fixed31_32_div_int(mbps, 54); +} + +static int get_color_depth(enum dc_color_depth color_depth) +{ + switch (color_depth) { + case COLOR_DEPTH_666: return 6; + case COLOR_DEPTH_888: return 8; + case COLOR_DEPTH_101010: return 10; + case COLOR_DEPTH_121212: return 12; + case COLOR_DEPTH_141414: return 14; + case COLOR_DEPTH_161616: return 16; + default: return 0; + } +} + +static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) +{ + uint32_t bpc; + uint64_t kbps; + struct fixed31_32 peak_kbps; + uint32_t numerator; + uint32_t denominator; + + bpc = get_color_depth(pipe_ctx->pix_clk_params.color_depth); + kbps = pipe_ctx->pix_clk_params.requested_pix_clk * bpc * 3; + + /* + * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 + * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on + * common multiplier to render an integer PBN for all link rate/lane + * counts combinations + * calculate + * peak_kbps *= (1006/1000) + * peak_kbps *= (64/54) + * peak_kbps *= 8 convert to bytes + */ + + numerator = 64 * PEAK_FACTOR_X1000; + denominator = 54 * 8 * 1000 * 1000; + kbps *= numerator; + peak_kbps = dal_fixed31_32_from_fraction(kbps, denominator); + + return peak_kbps; +} + +static void update_mst_stream_alloc_table( + struct core_link *link, + struct stream_encoder *stream_enc, + const struct dp_mst_stream_allocation_table *proposed_table) +{ + struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { + { 0 } }; + struct link_mst_stream_allocation *dc_alloc; + + int i; + int j; + + /* if DRM proposed_table has more than one new payload */ + ASSERT(proposed_table->stream_count - + link->mst_stream_alloc_table.stream_count < 2); + + /* copy proposed_table to core_link, add stream encoder */ + for (i = 0; i < proposed_table->stream_count; i++) { + + for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) { + dc_alloc = + &link->mst_stream_alloc_table.stream_allocations[j]; + + if (dc_alloc->vcp_id == + proposed_table->stream_allocations[i].vcp_id) { + + work_table[i] = *dc_alloc; + break; /* exit j loop */ + } + } + + /* new vcp_id */ + if (j == link->mst_stream_alloc_table.stream_count) { + work_table[i].vcp_id = + proposed_table->stream_allocations[i].vcp_id; + work_table[i].slot_count = + proposed_table->stream_allocations[i].slot_count; + work_table[i].stream_enc = stream_enc; + } + } + + /* update link->mst_stream_alloc_table with work_table */ + link->mst_stream_alloc_table.stream_count = + proposed_table->stream_count; + for (i = 0; i < MAX_CONTROLLER_NUM; i++) + link->mst_stream_alloc_table.stream_allocations[i] = + work_table[i]; +} + +/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table + * because stream_encoder is not exposed to dm + */ +static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + struct link_encoder *link_encoder = link->link_enc; + struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; + struct dp_mst_stream_allocation_table proposed_table = {0}; + struct fixed31_32 avg_time_slots_per_mtp; + struct fixed31_32 pbn; + struct fixed31_32 pbn_per_slot; + uint8_t i; + + /* enable_link_dp_mst already check link->enabled_stream_count + * and stream is in link->stream[]. This is called during set mode, + * stream_enc is available. + */ + + /* get calculate VC payload for stream: stream_alloc */ + if (dm_helpers_dp_mst_write_payload_allocation_table( + stream->ctx, + &stream->public, + &proposed_table, + true)) { + update_mst_stream_alloc_table( + link, pipe_ctx->stream_enc, &proposed_table); + } + else + dm_logger_write(link->ctx->logger, LOG_WARNING, + "Failed to update" + "MST allocation table for" + "pipe idx:%d\n", + pipe_ctx->pipe_idx); + + dm_logger_write(link->ctx->logger, LOG_MST, + "%s " + "stream_count: %d: \n ", + __func__, + link->mst_stream_alloc_table.stream_count); + + for (i = 0; i < MAX_CONTROLLER_NUM; i++) { + dm_logger_write(link->ctx->logger, LOG_MST, + "stream_enc[%d]: 0x%x " + "stream[%d].vcp_id: %d " + "stream[%d].slot_count: %d\n", + i, + link->mst_stream_alloc_table.stream_allocations[i].stream_enc, + i, + link->mst_stream_alloc_table.stream_allocations[i].vcp_id, + i, + link->mst_stream_alloc_table.stream_allocations[i].slot_count); + } + + ASSERT(proposed_table.stream_count > 0); + + /* program DP source TX for payload */ + link_encoder->funcs->update_mst_stream_allocation_table( + link_encoder, + &link->mst_stream_alloc_table); + + /* send down message */ + dm_helpers_dp_mst_poll_for_allocation_change_trigger( + stream->ctx, + &stream->public); + + dm_helpers_dp_mst_send_payload_allocation( + stream->ctx, + &stream->public, + true); + + /* slot X.Y for only current stream */ + pbn_per_slot = get_pbn_per_slot(stream); + pbn = get_pbn_from_timing(pipe_ctx); + avg_time_slots_per_mtp = dal_fixed31_32_div(pbn, pbn_per_slot); + + stream_encoder->funcs->set_mst_bandwidth( + stream_encoder, + avg_time_slots_per_mtp); + + return DC_OK; + +} + +static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + struct link_encoder *link_encoder = link->link_enc; + struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; + struct dp_mst_stream_allocation_table proposed_table = {0}; + struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0); + uint8_t i; + bool mst_mode = (link->public.type == dc_connection_mst_branch); + + /* deallocate_mst_payload is called before disable link. When mode or + * disable/enable monitor, new stream is created which is not in link + * stream[] yet. For this, payload is not allocated yet, so de-alloc + * should not done. For new mode set, map_resources will get engine + * for new stream, so stream_enc->id should be validated until here. + */ + + /* slot X.Y */ + stream_encoder->funcs->set_mst_bandwidth( + stream_encoder, + avg_time_slots_per_mtp); + + /* TODO: which component is responsible for remove payload table? */ + if (mst_mode) { + if (dm_helpers_dp_mst_write_payload_allocation_table( + stream->ctx, + &stream->public, + &proposed_table, + false)) { + + update_mst_stream_alloc_table( + link, pipe_ctx->stream_enc, &proposed_table); + } + else { + dm_logger_write(link->ctx->logger, LOG_WARNING, + "Failed to update" + "MST allocation table for" + "pipe idx:%d\n", + pipe_ctx->pipe_idx); + } + } + + dm_logger_write(link->ctx->logger, LOG_MST, + "%s" + "stream_count: %d: ", + __func__, + link->mst_stream_alloc_table.stream_count); + + for (i = 0; i < MAX_CONTROLLER_NUM; i++) { + dm_logger_write(link->ctx->logger, LOG_MST, + "stream_enc[%d]: 0x%x " + "stream[%d].vcp_id: %d " + "stream[%d].slot_count: %d\n", + i, + link->mst_stream_alloc_table.stream_allocations[i].stream_enc, + i, + link->mst_stream_alloc_table.stream_allocations[i].vcp_id, + i, + link->mst_stream_alloc_table.stream_allocations[i].slot_count); + } + + link_encoder->funcs->update_mst_stream_allocation_table( + link_encoder, + &link->mst_stream_alloc_table); + + if (mst_mode) { + dm_helpers_dp_mst_poll_for_allocation_change_trigger( + stream->ctx, + &stream->public); + + dm_helpers_dp_mst_send_payload_allocation( + stream->ctx, + &stream->public, + false); + } + + return DC_OK; +} + +void core_link_enable_stream(struct pipe_ctx *pipe_ctx) +{ + struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + + if (DC_OK != enable_link(pipe_ctx)) { + BREAK_TO_DEBUGGER(); + return; + } + + core_dc->hwss.enable_stream(pipe_ctx); + + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + allocate_mst_payload(pipe_ctx); +} + +void core_link_disable_stream(struct pipe_ctx *pipe_ctx) +{ + struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + deallocate_mst_payload(pipe_ctx); + + core_dc->hwss.disable_stream(pipe_ctx); + + disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c new file mode 100644 index 000000000000..6379ccfdb06e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -0,0 +1,1098 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dm_helpers.h" +#include "gpio_service_interface.h" +#include "include/ddc_service_types.h" +#include "include/grph_object_id.h" +#include "include/dpcd_defs.h" +#include "include/logger_interface.h" +#include "include/vector.h" +#include "core_types.h" +#include "dc_link_ddc.h" + +#define AUX_POWER_UP_WA_DELAY 500 +#define I2C_OVER_AUX_DEFER_WA_DELAY 70 + +/* CV smart dongle slave address for retrieving supported HDTV modes*/ +#define CV_SMART_DONGLE_ADDRESS 0x20 +/* DVI-HDMI dongle slave address for retrieving dongle signature*/ +#define DVI_HDMI_DONGLE_ADDRESS 0x68 +static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G"; +struct dvi_hdmi_dongle_signature_data { + int8_t vendor[3];/* "AMD" */ + uint8_t version[2]; + uint8_t size; + int8_t id[11];/* "6140063500G"*/ +}; +/* DP-HDMI dongle slave address for retrieving dongle signature*/ +#define DP_HDMI_DONGLE_ADDRESS 0x40 +static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR"; +#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04 + +struct dp_hdmi_dongle_signature_data { + int8_t id[15];/* "DP-HDMI ADAPTOR"*/ + uint8_t eot;/* end of transmition '\x4' */ +}; + +/* Address range from 0x00 to 0x1F.*/ +#define DP_ADAPTOR_TYPE2_SIZE 0x20 +#define DP_ADAPTOR_TYPE2_REG_ID 0x10 +#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D +/* Identifies adaptor as Dual-mode adaptor */ +#define DP_ADAPTOR_TYPE2_ID 0xA0 +/* MHz*/ +#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 +/* MHz*/ +#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 +/* kHZ*/ +#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 +/* kHZ*/ +#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 + +#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW + +enum edid_read_result { + EDID_READ_RESULT_EDID_MATCH = 0, + EDID_READ_RESULT_EDID_MISMATCH, + EDID_READ_RESULT_CHECKSUM_READ_ERR, + EDID_READ_RESULT_VENDOR_READ_ERR +}; + +/* SCDC Address defines (HDMI 2.0)*/ +#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3 +#define HDMI_SCDC_ADDRESS 0x54 +#define HDMI_SCDC_SINK_VERSION 0x01 +#define HDMI_SCDC_SOURCE_VERSION 0x02 +#define HDMI_SCDC_UPDATE_0 0x10 +#define HDMI_SCDC_TMDS_CONFIG 0x20 +#define HDMI_SCDC_SCRAMBLER_STATUS 0x21 +#define HDMI_SCDC_CONFIG_0 0x30 +#define HDMI_SCDC_STATUS_FLAGS 0x40 +#define HDMI_SCDC_ERR_DETECT 0x50 +#define HDMI_SCDC_TEST_CONFIG 0xC0 + +union hdmi_scdc_update_read_data { + uint8_t byte[2]; + struct { + uint8_t STATUS_UPDATE:1; + uint8_t CED_UPDATE:1; + uint8_t RR_TEST:1; + uint8_t RESERVED:5; + uint8_t RESERVED2:8; + } fields; +}; + +union hdmi_scdc_status_flags_data { + uint8_t byte[2]; + struct { + uint8_t CLOCK_DETECTED:1; + uint8_t CH0_LOCKED:1; + uint8_t CH1_LOCKED:1; + uint8_t CH2_LOCKED:1; + uint8_t RESERVED:4; + uint8_t RESERVED2:8; + } fields; +}; + +union hdmi_scdc_ced_data { + uint8_t byte[7]; + struct { + uint8_t CH0_8LOW:8; + uint8_t CH0_7HIGH:7; + uint8_t CH0_VALID:1; + uint8_t CH1_8LOW:8; + uint8_t CH1_7HIGH:7; + uint8_t CH1_VALID:1; + uint8_t CH2_8LOW:8; + uint8_t CH2_7HIGH:7; + uint8_t CH2_VALID:1; + uint8_t CHECKSUM:8; + } fields; +}; + +union hdmi_scdc_test_config_Data { + uint8_t byte; + struct { + uint8_t TEST_READ_REQUEST_DELAY:7; + uint8_t TEST_READ_REQUEST: 1; + } fields; +}; + +struct i2c_payloads { + struct vector payloads; +}; + +struct aux_payloads { + struct vector payloads; +}; + +struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) +{ + struct i2c_payloads *payloads; + + payloads = dm_alloc(sizeof(struct i2c_payloads)); + + if (!payloads) + return NULL; + + if (dal_vector_construct( + &payloads->payloads, ctx, count, sizeof(struct i2c_payload))) + return payloads; + + dm_free(payloads); + return NULL; + +} + +struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) +{ + return (struct i2c_payload *)p->payloads.container; +} + +uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) +{ + return p->payloads.count; +} + +void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) +{ + if (!p || !*p) + return; + dal_vector_destruct(&(*p)->payloads); + dm_free(*p); + *p = NULL; + +} + +struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) +{ + struct aux_payloads *payloads; + + payloads = dm_alloc(sizeof(struct aux_payloads)); + + if (!payloads) + return NULL; + + if (dal_vector_construct( + &payloads->payloads, ctx, count, sizeof(struct aux_payloads))) + return payloads; + + dm_free(payloads); + return NULL; +} + +struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) +{ + return (struct aux_payload *)p->payloads.container; +} + +uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) +{ + return p->payloads.count; +} + +void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) +{ + if (!p || !*p) + return; + + dal_vector_destruct(&(*p)->payloads); + dm_free(*p); + *p = NULL; +} + +#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +void dal_ddc_i2c_payloads_add( + struct i2c_payloads *payloads, + uint32_t address, + uint32_t len, + uint8_t *data, + bool write) +{ + uint32_t payload_size = EDID_SEGMENT_SIZE; + uint32_t pos; + + for (pos = 0; pos < len; pos += payload_size) { + struct i2c_payload payload = { + .write = write, + .address = address, + .length = DDC_MIN(payload_size, len - pos), + .data = data + pos }; + dal_vector_append(&payloads->payloads, &payload); + } + +} + +void dal_ddc_aux_payloads_add( + struct aux_payloads *payloads, + uint32_t address, + uint32_t len, + uint8_t *data, + bool write) +{ + uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE; + uint32_t pos; + + for (pos = 0; pos < len; pos += payload_size) { + struct aux_payload payload = { + .i2c_over_aux = true, + .write = write, + .address = address, + .length = DDC_MIN(payload_size, len - pos), + .data = data + pos }; + dal_vector_append(&payloads->payloads, &payload); + } +} + +static bool construct( + struct ddc_service *ddc_service, + struct ddc_service_init_data *init_data) +{ + enum connector_id connector_id = + dal_graphics_object_id_get_connector_id(init_data->id); + + struct gpio_service *gpio_service = init_data->ctx->gpio_service; + struct graphics_object_i2c_info i2c_info; + struct gpio_ddc_hw_info hw_info; + struct dc_bios *dcb = init_data->ctx->dc_bios; + + ddc_service->link = init_data->link; + ddc_service->ctx = init_data->ctx; + + if (BP_RESULT_OK != dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info)) { + ddc_service->ddc_pin = NULL; + } else { + hw_info.ddc_channel = i2c_info.i2c_line; + hw_info.hw_supported = i2c_info.i2c_hw_assist; + + ddc_service->ddc_pin = dal_gpio_create_ddc( + gpio_service, + i2c_info.gpio_info.clk_a_register_index, + 1 << i2c_info.gpio_info.clk_a_shift, + &hw_info); + } + + ddc_service->flags.EDID_QUERY_DONE_ONCE = false; + ddc_service->flags.FORCE_READ_REPEATED_START = false; + ddc_service->flags.EDID_STRESS_READ = false; + + ddc_service->flags.IS_INTERNAL_DISPLAY = + connector_id == CONNECTOR_ID_EDP || + connector_id == CONNECTOR_ID_LVDS; + + ddc_service->wa.raw = 0; + return true; +} + +struct ddc_service *dal_ddc_service_create( + struct ddc_service_init_data *init_data) +{ + struct ddc_service *ddc_service; + + ddc_service = dm_alloc(sizeof(struct ddc_service)); + + if (!ddc_service) + return NULL; + + if (construct(ddc_service, init_data)) + return ddc_service; + + dm_free(ddc_service); + return NULL; +} + +static void destruct(struct ddc_service *ddc) +{ + if (ddc->ddc_pin) + dal_gpio_destroy_ddc(&ddc->ddc_pin); +} + +void dal_ddc_service_destroy(struct ddc_service **ddc) +{ + if (!ddc || !*ddc) { + BREAK_TO_DEBUGGER(); + return; + } + destruct(*ddc); + dm_free(*ddc); + *ddc = NULL; +} + +enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc) +{ + return DDC_SERVICE_TYPE_CONNECTOR; +} + +void dal_ddc_service_set_transaction_type( + struct ddc_service *ddc, + enum ddc_transaction_type type) +{ + ddc->transaction_type = type; +} + +bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc) +{ + switch (ddc->transaction_type) { + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER: + return true; + default: + break; + } + return false; +} + +void ddc_service_set_dongle_type(struct ddc_service *ddc, + enum display_dongle_type dongle_type) +{ + ddc->dongle_type = dongle_type; +} + +static uint32_t defer_delay_converter_wa( + struct ddc_service *ddc, + uint32_t defer_delay) +{ + struct core_link *link = ddc->link; + + if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_4 && + !memcmp(link->dpcd_caps.branch_dev_name, + DP_DVI_CONVERTER_ID_4, + sizeof(link->dpcd_caps.branch_dev_name))) + return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ? + defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY; + + return defer_delay; +} + +#define DP_TRANSLATOR_DELAY 5 + +static uint32_t get_defer_delay(struct ddc_service *ddc) +{ + uint32_t defer_delay = 0; + + switch (ddc->transaction_type) { + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: + if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) || + (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) || + (DISPLAY_DONGLE_DP_HDMI_CONVERTER == + ddc->dongle_type)) { + + defer_delay = DP_TRANSLATOR_DELAY; + + defer_delay = + defer_delay_converter_wa(ddc, defer_delay); + + } else /*sink has a delay different from an Active Converter*/ + defer_delay = 0; + break; + case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: + defer_delay = DP_TRANSLATOR_DELAY; + break; + default: + break; + } + return defer_delay; +} + +static bool i2c_read( + struct ddc_service *ddc, + uint32_t address, + uint8_t *buffer, + uint32_t len) +{ + uint8_t offs_data = 0; + struct i2c_payload payloads[2] = { + { + .write = true, + .address = address, + .length = 1, + .data = &offs_data }, + { + .write = false, + .address = address, + .length = len, + .data = buffer } }; + + struct i2c_command command = { + .payloads = payloads, + .number_of_payloads = 2, + .engine = DDC_I2C_COMMAND_ENGINE, + .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; + + return dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &command); +} + +static uint8_t aux_read_edid_block( + struct ddc_service *ddc, + uint8_t address, + uint8_t index, + uint8_t *buf) +{ + struct aux_command cmd = { + .payloads = NULL, + .number_of_payloads = 0, + .defer_delay = get_defer_delay(ddc), + .max_defer_write_retry = 0 }; + + uint8_t retrieved = 0; + uint8_t base_offset = + (index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE; + uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; + + for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE; + retrieved += DEFAULT_AUX_MAX_DATA_SIZE) { + + uint8_t offset = base_offset + retrieved; + + struct aux_payload payloads[3] = { + { + .i2c_over_aux = true, + .write = true, + .address = DDC_EDID_SEGMENT_ADDRESS, + .length = 1, + .data = &segment }, + { + .i2c_over_aux = true, + .write = true, + .address = address, + .length = 1, + .data = &offset }, + { + .i2c_over_aux = true, + .write = false, + .address = address, + .length = DEFAULT_AUX_MAX_DATA_SIZE, + .data = &buf[retrieved] } }; + + if (segment == 0) { + cmd.payloads = &payloads[1]; + cmd.number_of_payloads = 2; + } else { + cmd.payloads = payloads; + cmd.number_of_payloads = 3; + } + + if (!dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &cmd)) + /* cannot read, break*/ + break; + } + + /* Reset segment to 0. Needed by some panels */ + if (0 != segment) { + struct aux_payload payloads[1] = { { + .i2c_over_aux = true, + .write = true, + .address = DDC_EDID_SEGMENT_ADDRESS, + .length = 1, + .data = &segment } }; + bool result = false; + + segment = 0; + + cmd.number_of_payloads = ARRAY_SIZE(payloads); + cmd.payloads = payloads; + + result = dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &cmd); + + if (false == result) + dm_logger_write( + ddc->ctx->logger, LOG_ERROR, + "%s: Writing of EDID Segment (0x30) failed!\n", + __func__); + } + + return retrieved; +} + +static uint8_t i2c_read_edid_block( + struct ddc_service *ddc, + uint8_t address, + uint8_t index, + uint8_t *buf) +{ + bool ret = false; + uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) * + DDC_EDID_BLOCK_SIZE; + uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; + + struct i2c_command cmd = { + .payloads = NULL, + .number_of_payloads = 0, + .engine = DDC_I2C_COMMAND_ENGINE, + .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; + + struct i2c_payload payloads[3] = { + { + .write = true, + .address = DDC_EDID_SEGMENT_ADDRESS, + .length = 1, + .data = &segment }, + { + .write = true, + .address = address, + .length = 1, + .data = &offset }, + { + .write = false, + .address = address, + .length = DDC_EDID_BLOCK_SIZE, + .data = buf } }; +/* + * Some I2C engines don't handle stop/start between write-offset and read-data + * commands properly. For those displays, we have to force the newer E-DDC + * behavior of repeated-start which can be enabled by runtime parameter. */ +/* Originally implemented for OnLive using NXP receiver chip */ + + if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) { + /* base block, use use DDC2B, submit as 2 commands */ + cmd.payloads = &payloads[1]; + cmd.number_of_payloads = 1; + + if (dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &cmd)) { + + cmd.payloads = &payloads[2]; + cmd.number_of_payloads = 1; + + ret = dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &cmd); + } + + } else { + /* + * extension block use E-DDC, submit as 1 command + * or if repeated-start is forced by runtime parameter + */ + if (segment != 0) { + /* include segment offset in command*/ + cmd.payloads = payloads; + cmd.number_of_payloads = 3; + } else { + /* we are reading first segment, + * segment offset is not required */ + cmd.payloads = &payloads[1]; + cmd.number_of_payloads = 2; + } + + ret = dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &cmd); + } + + return ret ? DDC_EDID_BLOCK_SIZE : 0; +} + +static uint32_t query_edid_block( + struct ddc_service *ddc, + uint8_t address, + uint8_t index, + uint8_t *buf, + uint32_t size) +{ + uint32_t size_retrieved = 0; + + if (size < DDC_EDID_BLOCK_SIZE) + return 0; + + if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { + size_retrieved = + aux_read_edid_block(ddc, address, index, buf); + } else { + size_retrieved = + i2c_read_edid_block(ddc, address, index, buf); + } + + return size_retrieved; +} + +#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261 +#define DDC_TEST_ACK_ADDRESS 0x260 +#define DDC_DPCD_EDID_TEST_ACK 0x04 +#define DDC_DPCD_EDID_TEST_MASK 0x04 +#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218 + +/* AG TODO GO throug DM callback here like for DPCD */ + +static void write_dp_edid_checksum( + struct ddc_service *ddc, + uint8_t checksum) +{ + uint8_t dpcd_data; + + dal_ddc_service_read_dpcd_data( + ddc, + DDC_DPCD_TEST_REQUEST_ADDRESS, + &dpcd_data, + 1); + + if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) { + + dal_ddc_service_write_dpcd_data( + ddc, + DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS, + &checksum, + 1); + + dpcd_data = DDC_DPCD_EDID_TEST_ACK; + + dal_ddc_service_write_dpcd_data( + ddc, + DDC_TEST_ACK_ADDRESS, + &dpcd_data, + 1); + } +} + +uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc) +{ + uint32_t bytes_read = 0; + uint32_t ext_cnt = 0; + + uint8_t address; + uint32_t i; + + for (address = DDC_EDID_ADDRESS_START; + address <= DDC_EDID_ADDRESS_END; ++address) { + + bytes_read = query_edid_block( + ddc, + address, + 0, + ddc->edid_buf, + sizeof(ddc->edid_buf) - bytes_read); + + if (bytes_read != DDC_EDID_BLOCK_SIZE) + continue; + + /* get the number of ext blocks*/ + ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET]; + + /* EDID 2.0, need to read 1 more block because EDID2.0 is + * 256 byte in size*/ + if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] == + DDC_EDID_20_SIGNATURE) + ext_cnt = 1; + + for (i = 0; i < ext_cnt; i++) { + /* read additional ext blocks accordingly */ + bytes_read += query_edid_block( + ddc, + address, + i+1, + &ddc->edid_buf[bytes_read], + sizeof(ddc->edid_buf) - bytes_read); + } + + /*this is special code path for DP compliance*/ + if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type) + write_dp_edid_checksum( + ddc, + ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) + + DDC_EDID1X_CHECKSUM_OFFSET]); + + /*remembers the address where we fetch the EDID from + * for later signature check use */ + ddc->address = address; + + break;/* already read edid, done*/ + } + + ddc->edid_buf_len = bytes_read; + return bytes_read; +} + +uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc) +{ + return ddc->edid_buf_len; +} + +void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf) +{ + memmove(edid_buf, + ddc->edid_buf, ddc->edid_buf_len); +} + +void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( + struct ddc_service *ddc, + struct display_sink_capability *sink_cap) +{ + uint8_t i; + bool is_valid_hdmi_signature; + enum display_dongle_type *dongle = &sink_cap->dongle_type; + uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE]; + bool is_type2_dongle = false; + struct dp_hdmi_dongle_signature_data *dongle_signature; + + /* Assume we have no valid DP passive dongle connected */ + *dongle = DISPLAY_DONGLE_NONE; + sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK; + + /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/ + if (!i2c_read( + ddc, + DP_HDMI_DONGLE_ADDRESS, + type2_dongle_buf, + sizeof(type2_dongle_buf))) { + *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; + sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf), + "DP-DVI passive dongle %dMhz: ", + DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000); + return; + } + + /* Check if Type 2 dongle.*/ + if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID) + is_type2_dongle = true; + + dongle_signature = + (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf; + + is_valid_hdmi_signature = true; + + /* Check EOT */ + if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) { + is_valid_hdmi_signature = false; + } + + /* Check signature */ + for (i = 0; i < sizeof(dongle_signature->id); ++i) { + /* If its not the right signature, + * skip mismatch in subversion byte.*/ + if (dongle_signature->id[i] != + dp_hdmi_dongle_signature_str[i] && i != 3) { + + if (is_type2_dongle) { + is_valid_hdmi_signature = false; + break; + } + + } + } + + if (is_type2_dongle) { + uint32_t max_tmds_clk = + type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK]; + + max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2; + + if (0 == max_tmds_clk || + max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK || + max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) { + *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "DP-DVI passive dongle %dMhz: ", + DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000); + } else { + if (is_valid_hdmi_signature == true) { + *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "Type 2 DP-HDMI passive dongle %dMhz: ", + max_tmds_clk); + } else { + *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "Type 2 DP-HDMI passive dongle (no signature) %dMhz: ", + max_tmds_clk); + + } + + /* Multiply by 1000 to convert to kHz. */ + sink_cap->max_hdmi_pixel_clock = + max_tmds_clk * 1000; + } + + } else { + if (is_valid_hdmi_signature == true) { + *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "Type 1 DP-HDMI passive dongle %dMhz: ", + sink_cap->max_hdmi_pixel_clock / 1000); + } else { + *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; + + CONN_DATA_DETECT(ddc->link, type2_dongle_buf, + sizeof(type2_dongle_buf), + "Type 1 DP-HDMI passive dongle (no signature) %dMhz: ", + sink_cap->max_hdmi_pixel_clock / 1000); + } + } + + return; +} + +enum { + DP_SINK_CAP_SIZE = + DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1 +}; + +bool dal_ddc_service_query_ddc_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size) +{ + bool ret; + uint32_t payload_size = + dal_ddc_service_is_in_aux_transaction_mode(ddc) ? + DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE; + + uint32_t write_payloads = + (write_size + payload_size - 1) / payload_size; + + uint32_t read_payloads = + (read_size + payload_size - 1) / payload_size; + + uint32_t payloads_num = write_payloads + read_payloads; + + if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE) + return false; + + /*TODO: len of payload data for i2c and aux is uint8!!!!, + * but we want to read 256 over i2c!!!!*/ + if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { + + struct aux_payloads *payloads = + dal_ddc_aux_payloads_create(ddc->ctx, payloads_num); + + struct aux_command command = { + .payloads = dal_ddc_aux_payloads_get(payloads), + .number_of_payloads = 0, + .defer_delay = get_defer_delay(ddc), + .max_defer_write_retry = 0 }; + + dal_ddc_aux_payloads_add( + payloads, address, write_size, write_buf, true); + + dal_ddc_aux_payloads_add( + payloads, address, read_size, read_buf, false); + + command.number_of_payloads = + dal_ddc_aux_payloads_get_count(payloads); + + ret = dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &command); + + dal_ddc_aux_payloads_destroy(&payloads); + + } else { + struct i2c_payloads *payloads = + dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num); + + struct i2c_command command = { + .payloads = dal_ddc_i2c_payloads_get(payloads), + .number_of_payloads = 0, + .engine = DDC_I2C_COMMAND_ENGINE, + .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; + + dal_ddc_i2c_payloads_add( + payloads, address, write_size, write_buf, true); + + dal_ddc_i2c_payloads_add( + payloads, address, read_size, read_buf, false); + + command.number_of_payloads = + dal_ddc_i2c_payloads_get_count(payloads); + + ret = dm_helpers_submit_i2c( + ddc->ctx, + &ddc->link->public, + &command); + + dal_ddc_i2c_payloads_destroy(&payloads); + } + + return ret; +} + +enum ddc_result dal_ddc_service_read_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *data, + uint32_t len) +{ + struct aux_payload read_payload = { + .i2c_over_aux = false, + .write = false, + .address = address, + .length = len, + .data = data, + }; + struct aux_command command = { + .payloads = &read_payload, + .number_of_payloads = 1, + .defer_delay = 0, + .max_defer_write_retry = 0, + }; + + if (len > DEFAULT_AUX_MAX_DATA_SIZE) { + BREAK_TO_DEBUGGER(); + return DDC_RESULT_FAILED_INVALID_OPERATION; + } + + if (dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &command)) + return DDC_RESULT_SUCESSFULL; + + return DDC_RESULT_FAILED_OPERATION; +} + +enum ddc_result dal_ddc_service_write_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + const uint8_t *data, + uint32_t len) +{ + struct aux_payload write_payload = { + .i2c_over_aux = false, + .write = true, + .address = address, + .length = len, + .data = (uint8_t *)data, + }; + struct aux_command command = { + .payloads = &write_payload, + .number_of_payloads = 1, + .defer_delay = 0, + .max_defer_write_retry = 0, + }; + + if (len > DEFAULT_AUX_MAX_DATA_SIZE) { + BREAK_TO_DEBUGGER(); + return DDC_RESULT_FAILED_INVALID_OPERATION; + } + + if (dal_i2caux_submit_aux_command( + ddc->ctx->i2caux, + ddc->ddc_pin, + &command)) + return DDC_RESULT_SUCESSFULL; + + return DDC_RESULT_FAILED_OPERATION; +} + +/*test only function*/ +void dal_ddc_service_set_ddc_pin( + struct ddc_service *ddc_service, + struct ddc *ddc) +{ + ddc_service->ddc_pin = ddc; +} + +struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service) +{ + return ddc_service->ddc_pin; +} + +void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service, + uint32_t pix_clk, + bool lte_340_scramble) +{ + bool over_340_mhz = pix_clk > 340000 ? 1 : 0; + uint8_t slave_address = HDMI_SCDC_ADDRESS; + uint8_t offset = HDMI_SCDC_SINK_VERSION; + uint8_t sink_version = 0; + uint8_t write_buffer[2] = {0}; + /*Lower than 340 Scramble bit from SCDC caps*/ + + dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, + sizeof(offset), &sink_version, sizeof(sink_version)); + if (sink_version == 1) { + /*Source Version = 1*/ + write_buffer[0] = HDMI_SCDC_SOURCE_VERSION; + write_buffer[1] = 1; + dal_ddc_service_query_ddc_data(ddc_service, slave_address, + write_buffer, sizeof(write_buffer), NULL, 0); + /*Read Request from SCDC caps*/ + } + write_buffer[0] = HDMI_SCDC_TMDS_CONFIG; + + if (over_340_mhz) { + write_buffer[1] = 3; + } else if (lte_340_scramble) { + write_buffer[1] = 1; + } else { + write_buffer[1] = 0; + } + dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer, + sizeof(write_buffer), NULL, 0); +} + +void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service) +{ + uint8_t slave_address = HDMI_SCDC_ADDRESS; + uint8_t offset = HDMI_SCDC_TMDS_CONFIG; + uint8_t tmds_config = 0; + + dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, + sizeof(offset), &tmds_config, sizeof(tmds_config)); + if (tmds_config & 0x1) { + union hdmi_scdc_status_flags_data status_data = { {0} }; + uint8_t scramble_status = 0; + + offset = HDMI_SCDC_SCRAMBLER_STATUS; + dal_ddc_service_query_ddc_data(ddc_service, slave_address, + &offset, sizeof(offset), &scramble_status, + sizeof(scramble_status)); + offset = HDMI_SCDC_STATUS_FLAGS; + dal_ddc_service_query_ddc_data(ddc_service, slave_address, + &offset, sizeof(offset), status_data.byte, + sizeof(status_data.byte)); + } +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c new file mode 100644 index 000000000000..2585ec332e58 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -0,0 +1,2462 @@ +/* Copyright 2015 Advanced Micro Devices, Inc. */ +#include "dm_services.h" +#include "dc.h" +#include "dc_link_dp.h" +#include "dm_helpers.h" + +#include "inc/core_types.h" +#include "link_hwss.h" +#include "dc_link_ddc.h" +#include "core_status.h" +#include "dpcd_defs.h" + +#include "core_dc.h" + +/* maximum pre emphasis level allowed for each voltage swing level*/ +static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = { + PRE_EMPHASIS_LEVEL3, + PRE_EMPHASIS_LEVEL2, + PRE_EMPHASIS_LEVEL1, + PRE_EMPHASIS_DISABLED }; + +enum { + POST_LT_ADJ_REQ_LIMIT = 6, + POST_LT_ADJ_REQ_TIMEOUT = 200 +}; + +enum { + LINK_TRAINING_MAX_RETRY_COUNT = 5, + /* to avoid infinite loop where-in the receiver + * switches between different VS + */ + LINK_TRAINING_MAX_CR_RETRY = 100 +}; + +static const struct dc_link_settings link_training_fallback_table[] = { +/* 4320 Mbytes/sec*/ +{ LANE_COUNT_FOUR, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, +/* 2160 Mbytes/sec*/ +{ LANE_COUNT_FOUR, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, +/* 1080 Mbytes/sec*/ +{ LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, +/* 648 Mbytes/sec*/ +{ LANE_COUNT_FOUR, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, +/* 2160 Mbytes/sec*/ +{ LANE_COUNT_TWO, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, +/* 1080 Mbytes/sec*/ +{ LANE_COUNT_TWO, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, +/* 540 Mbytes/sec*/ +{ LANE_COUNT_TWO, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, +/* 324 Mbytes/sec*/ +{ LANE_COUNT_TWO, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, +/* 1080 Mbytes/sec*/ +{ LANE_COUNT_ONE, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, +/* 540 Mbytes/sec*/ +{ LANE_COUNT_ONE, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, +/* 270 Mbytes/sec*/ +{ LANE_COUNT_ONE, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, +/* 162 Mbytes/sec*/ +{ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED } }; + +static void wait_for_training_aux_rd_interval( + struct core_link* link, + uint32_t default_wait_in_micro_secs) +{ + union training_aux_rd_interval training_rd_interval; + + /* overwrite the delay if rev > 1.1*/ + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + /* DP 1.2 or later - retrieve delay through + * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL, + (uint8_t *)&training_rd_interval, + sizeof(training_rd_interval)); + + if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) + default_wait_in_micro_secs = + training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; + } + + udelay(default_wait_in_micro_secs); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s:\n wait = %d\n", + __func__, + default_wait_in_micro_secs); +} + +static void dpcd_set_training_pattern( + struct core_link* link, + union dpcd_training_pattern dpcd_pattern) +{ + core_link_write_dpcd( + link, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + &dpcd_pattern.raw, + 1); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s\n %x pattern = %x\n", + __func__, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + dpcd_pattern.v1_4.TRAINING_PATTERN_SET); +} + +static void dpcd_set_link_settings( + struct core_link* link, + const struct link_training_settings *lt_settings) +{ + uint8_t rate = (uint8_t) + (lt_settings->link_settings.link_rate); + + union down_spread_ctrl downspread = {{0}}; + union lane_count_set lane_count_set = {{0}}; + uint8_t link_set_buffer[2]; + + downspread.raw = (uint8_t) + (lt_settings->link_settings.link_spread); + + lane_count_set.bits.LANE_COUNT_SET = + lt_settings->link_settings.lane_count; + + lane_count_set.bits.ENHANCED_FRAMING = 1; + + lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = + link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED; + + link_set_buffer[0] = rate; + link_set_buffer[1] = lane_count_set.raw; + + core_link_write_dpcd(link, DPCD_ADDRESS_LINK_BW_SET, + link_set_buffer, 2); + core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + &downspread.raw, sizeof(downspread)); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n", + __func__, + DPCD_ADDRESS_LINK_BW_SET, + lt_settings->link_settings.link_rate, + DPCD_ADDRESS_LANE_COUNT_SET, + lt_settings->link_settings.lane_count, + DPCD_ADDRESS_DOWNSPREAD_CNTL, + lt_settings->link_settings.link_spread); + +} + +static enum dpcd_training_patterns + hw_training_pattern_to_dpcd_training_pattern( + struct core_link* link, + enum hw_dp_training_pattern pattern) +{ + enum dpcd_training_patterns dpcd_tr_pattern = + DPCD_TRAINING_PATTERN_VIDEOIDLE; + + switch (pattern) { + case HW_DP_TRAINING_PATTERN_1: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1; + break; + case HW_DP_TRAINING_PATTERN_2: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2; + break; + case HW_DP_TRAINING_PATTERN_3: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3; + break; + case HW_DP_TRAINING_PATTERN_4: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4; + break; + default: + ASSERT(0); + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s: Invalid HW Training pattern: %d\n", + __func__, pattern); + break; + } + + return dpcd_tr_pattern; + +} + +static void dpcd_set_lt_pattern_and_lane_settings( + struct core_link* link, + const struct link_training_settings *lt_settings, + enum hw_dp_training_pattern pattern) +{ + union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; + const uint32_t dpcd_base_lt_offset = + DPCD_ADDRESS_TRAINING_PATTERN_SET; + uint8_t dpcd_lt_buffer[5] = {0}; + union dpcd_training_pattern dpcd_pattern = {{0}}; + uint32_t lane; + uint32_t size_in_bytes; + bool edp_workaround = false; /* TODO link_prop.INTERNAL */ + + /***************************************************************** + * DpcdAddress_TrainingPatternSet + *****************************************************************/ + dpcd_pattern.v1_4.TRAINING_PATTERN_SET = + hw_training_pattern_to_dpcd_training_pattern(link, pattern); + + dpcd_lt_buffer[DPCD_ADDRESS_TRAINING_PATTERN_SET - dpcd_base_lt_offset] + = dpcd_pattern.raw; + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s\n %x pattern = %x\n", + __func__, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + dpcd_pattern.v1_4.TRAINING_PATTERN_SET); + + /***************************************************************** + * DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set + *****************************************************************/ + for (lane = 0; lane < + (uint32_t)(lt_settings->link_settings.lane_count); lane++) { + + dpcd_lane[lane].bits.VOLTAGE_SWING_SET = + (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING); + dpcd_lane[lane].bits.PRE_EMPHASIS_SET = + (uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS); + + dpcd_lane[lane].bits.MAX_SWING_REACHED = + (lt_settings->lane_settings[lane].VOLTAGE_SWING == + VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); + dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = + (lt_settings->lane_settings[lane].PRE_EMPHASIS == + PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); + } + + /* concatinate everything into one buffer*/ + + size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]); + + // 0x00103 - 0x00102 + memmove( + &dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset], + dpcd_lane, + size_in_bytes); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s:\n %x VS set = %x PE set = %x \ + max VS Reached = %x max PE Reached = %x\n", + __func__, + DPCD_ADDRESS_LANE0_SET, + dpcd_lane[0].bits.VOLTAGE_SWING_SET, + dpcd_lane[0].bits.PRE_EMPHASIS_SET, + dpcd_lane[0].bits.MAX_SWING_REACHED, + dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); + + if (edp_workaround) { + /* for eDP write in 2 parts because the 5-byte burst is + * causing issues on some eDP panels (EPR#366724) + */ + core_link_write_dpcd( + link, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + &dpcd_pattern.raw, + sizeof(dpcd_pattern.raw) ); + + core_link_write_dpcd( + link, + DPCD_ADDRESS_LANE0_SET, + (uint8_t *)(dpcd_lane), + size_in_bytes); + + } else + /* write it all in (1 + number-of-lanes)-byte burst*/ + core_link_write_dpcd( + link, + dpcd_base_lt_offset, + dpcd_lt_buffer, + size_in_bytes + sizeof(dpcd_pattern.raw) ); + + link->public.cur_lane_setting = lt_settings->lane_settings[0]; +} + +static bool is_cr_done(enum dc_lane_count ln_count, + union lane_status *dpcd_lane_status) +{ + bool done = true; + uint32_t lane; + /*LANEx_CR_DONE bits All 1's?*/ + for (lane = 0; lane < (uint32_t)(ln_count); lane++) { + if (!dpcd_lane_status[lane].bits.CR_DONE_0) + done = false; + } + return done; + +} + +static bool is_ch_eq_done(enum dc_lane_count ln_count, + union lane_status *dpcd_lane_status, + union lane_align_status_updated *lane_status_updated) +{ + bool done = true; + uint32_t lane; + if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE) + done = false; + else { + for (lane = 0; lane < (uint32_t)(ln_count); lane++) { + if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 || + !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0) + done = false; + } + } + return done; + +} + +static void update_drive_settings( + struct link_training_settings *dest, + struct link_training_settings src) +{ + uint32_t lane; + for (lane = 0; lane < src.link_settings.lane_count; lane++) { + dest->lane_settings[lane].VOLTAGE_SWING = + src.lane_settings[lane].VOLTAGE_SWING; + dest->lane_settings[lane].PRE_EMPHASIS = + src.lane_settings[lane].PRE_EMPHASIS; + dest->lane_settings[lane].POST_CURSOR2 = + src.lane_settings[lane].POST_CURSOR2; + } +} + +static uint8_t get_nibble_at_index(const uint8_t *buf, + uint32_t index) +{ + uint8_t nibble; + nibble = buf[index / 2]; + + if (index % 2) + nibble >>= 4; + else + nibble &= 0x0F; + + return nibble; +} + +static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing( + enum dc_voltage_swing voltage) +{ + enum dc_pre_emphasis pre_emphasis; + pre_emphasis = PRE_EMPHASIS_MAX_LEVEL; + + if (voltage <= VOLTAGE_SWING_MAX_LEVEL) + pre_emphasis = voltage_swing_to_pre_emphasis[voltage]; + + return pre_emphasis; + +} + +static void find_max_drive_settings( + const struct link_training_settings *link_training_setting, + struct link_training_settings *max_lt_setting) +{ + uint32_t lane; + struct dc_lane_settings max_requested; + + max_requested.VOLTAGE_SWING = + link_training_setting-> + lane_settings[0].VOLTAGE_SWING; + max_requested.PRE_EMPHASIS = + link_training_setting-> + lane_settings[0].PRE_EMPHASIS; + /*max_requested.postCursor2 = + * link_training_setting->laneSettings[0].postCursor2;*/ + + /* Determine what the maximum of the requested settings are*/ + for (lane = 1; lane < link_training_setting->link_settings.lane_count; + lane++) { + if (link_training_setting->lane_settings[lane].VOLTAGE_SWING > + max_requested.VOLTAGE_SWING) + + max_requested.VOLTAGE_SWING = + link_training_setting-> + lane_settings[lane].VOLTAGE_SWING; + + if (link_training_setting->lane_settings[lane].PRE_EMPHASIS > + max_requested.PRE_EMPHASIS) + max_requested.PRE_EMPHASIS = + link_training_setting-> + lane_settings[lane].PRE_EMPHASIS; + + /* + if (link_training_setting->laneSettings[lane].postCursor2 > + max_requested.postCursor2) + { + max_requested.postCursor2 = + link_training_setting->laneSettings[lane].postCursor2; + } + */ + } + + /* make sure the requested settings are + * not higher than maximum settings*/ + if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL) + max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL; + + if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL) + max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL; + /* + if (max_requested.postCursor2 > PostCursor2_MaxLevel) + max_requested.postCursor2 = PostCursor2_MaxLevel; + */ + + /* make sure the pre-emphasis matches the voltage swing*/ + if (max_requested.PRE_EMPHASIS > + get_max_pre_emphasis_for_voltage_swing( + max_requested.VOLTAGE_SWING)) + max_requested.PRE_EMPHASIS = + get_max_pre_emphasis_for_voltage_swing( + max_requested.VOLTAGE_SWING); + + /* + * Post Cursor2 levels are completely independent from + * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels + * can only be applied to each allowable combination of voltage + * swing and pre-emphasis levels */ + /* if ( max_requested.postCursor2 > + * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing)) + * max_requested.postCursor2 = + * getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing); + */ + + max_lt_setting->link_settings.link_rate = + link_training_setting->link_settings.link_rate; + max_lt_setting->link_settings.lane_count = + link_training_setting->link_settings.lane_count; + max_lt_setting->link_settings.link_spread = + link_training_setting->link_settings.link_spread; + + for (lane = 0; lane < + link_training_setting->link_settings.lane_count; + lane++) { + max_lt_setting->lane_settings[lane].VOLTAGE_SWING = + max_requested.VOLTAGE_SWING; + max_lt_setting->lane_settings[lane].PRE_EMPHASIS = + max_requested.PRE_EMPHASIS; + /*max_lt_setting->laneSettings[lane].postCursor2 = + * max_requested.postCursor2; + */ + } + +} + +static void get_lane_status_and_drive_settings( + struct core_link* link, + const struct link_training_settings *link_training_setting, + union lane_status *ln_status, + union lane_align_status_updated *ln_status_updated, + struct link_training_settings *req_settings) +{ + uint8_t dpcd_buf[6] = {0}; + union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {{{0}}}; + struct link_training_settings request_settings = {{0}}; + uint32_t lane; + + memset(req_settings, '\0', sizeof(struct link_training_settings)); + + core_link_read_dpcd( + link, + DPCD_ADDRESS_LANE_01_STATUS, + (uint8_t *)(dpcd_buf), + sizeof(dpcd_buf)); + + for (lane = 0; lane < + (uint32_t)(link_training_setting->link_settings.lane_count); + lane++) { + + ln_status[lane].raw = + get_nibble_at_index(&dpcd_buf[0], lane); + dpcd_lane_adjust[lane].raw = + get_nibble_at_index(&dpcd_buf[4], lane); + } + + ln_status_updated->raw = dpcd_buf[2]; + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ", + __func__, + DPCD_ADDRESS_LANE_01_STATUS, dpcd_buf[0], + DPCD_ADDRESS_LANE_23_STATUS, dpcd_buf[1]); + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n", + __func__, + DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, + dpcd_buf[4], + DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3, + dpcd_buf[5]); + + /*copy to req_settings*/ + request_settings.link_settings.lane_count = + link_training_setting->link_settings.lane_count; + request_settings.link_settings.link_rate = + link_training_setting->link_settings.link_rate; + request_settings.link_settings.link_spread = + link_training_setting->link_settings.link_spread; + + for (lane = 0; lane < + (uint32_t)(link_training_setting->link_settings.lane_count); + lane++) { + + request_settings.lane_settings[lane].VOLTAGE_SWING = + (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits. + VOLTAGE_SWING_LANE); + request_settings.lane_settings[lane].PRE_EMPHASIS = + (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits. + PRE_EMPHASIS_LANE); + } + + /*Note: for postcursor2, read adjusted + * postcursor2 settings from*/ + /*DpcdAddress_AdjustRequestPostCursor2 = + *0x020C (not implemented yet)*/ + + /* we find the maximum of the requested settings across all lanes*/ + /* and set this maximum for all lanes*/ + find_max_drive_settings(&request_settings, req_settings); + + /* if post cursor 2 is needed in the future, + * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C + */ + +} + +static void dpcd_set_lane_settings( + struct core_link* link, + const struct link_training_settings *link_training_setting) +{ + union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; + uint32_t lane; + + for (lane = 0; lane < + (uint32_t)(link_training_setting-> + link_settings.lane_count); + lane++) { + dpcd_lane[lane].bits.VOLTAGE_SWING_SET = + (uint8_t)(link_training_setting-> + lane_settings[lane].VOLTAGE_SWING); + dpcd_lane[lane].bits.PRE_EMPHASIS_SET = + (uint8_t)(link_training_setting-> + lane_settings[lane].PRE_EMPHASIS); + dpcd_lane[lane].bits.MAX_SWING_REACHED = + (link_training_setting-> + lane_settings[lane].VOLTAGE_SWING == + VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); + dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = + (link_training_setting-> + lane_settings[lane].PRE_EMPHASIS == + PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); + } + + core_link_write_dpcd(link, + DPCD_ADDRESS_LANE0_SET, + (uint8_t *)(dpcd_lane), + link_training_setting->link_settings.lane_count); + + /* + if (LTSettings.link.rate == LinkRate_High2) + { + DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0}; + for ( uint32_t lane = 0; + lane < lane_count_DPMax; lane++) + { + dpcd_lane2[lane].bits.post_cursor2_set = + static_cast( + LTSettings.laneSettings[lane].postCursor2); + dpcd_lane2[lane].bits.max_post_cursor2_reached = 0; + } + m_pDpcdAccessSrv->WriteDpcdData( + DpcdAddress_Lane0Set2, + reinterpret_cast(dpcd_lane2), + LTSettings.link.lanes); + } + */ + + dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, + "%s\n %x VS set = %x PE set = %x \ + max VS Reached = %x max PE Reached = %x\n", + __func__, + DPCD_ADDRESS_LANE0_SET, + dpcd_lane[0].bits.VOLTAGE_SWING_SET, + dpcd_lane[0].bits.PRE_EMPHASIS_SET, + dpcd_lane[0].bits.MAX_SWING_REACHED, + dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); + + link->public.cur_lane_setting = link_training_setting->lane_settings[0]; + +} + +static bool is_max_vs_reached( + const struct link_training_settings *lt_settings) +{ + uint32_t lane; + for (lane = 0; lane < + (uint32_t)(lt_settings->link_settings.lane_count); + lane++) { + if (lt_settings->lane_settings[lane].VOLTAGE_SWING + == VOLTAGE_SWING_MAX_LEVEL) + return true; + } + return false; + +} + +void dc_link_dp_set_drive_settings( + struct dc_link *link, + struct link_training_settings *lt_settings) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + /* program ASIC PHY settings*/ + dp_set_hw_lane_settings(core_link, lt_settings); + + /* Notify DP sink the PHY settings from source */ + dpcd_set_lane_settings(core_link, lt_settings); +} + +static bool perform_post_lt_adj_req_sequence( + struct core_link *link, + struct link_training_settings *lt_settings) +{ + enum dc_lane_count lane_count = + lt_settings->link_settings.lane_count; + + uint32_t adj_req_count; + uint32_t adj_req_timer; + bool req_drv_setting_changed; + uint32_t lane; + + req_drv_setting_changed = false; + for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT; + adj_req_count++) { + + req_drv_setting_changed = false; + + for (adj_req_timer = 0; + adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT; + adj_req_timer++) { + + struct link_training_settings req_settings; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; + union lane_align_status_updated + dpcd_lane_status_updated; + + get_lane_status_and_drive_settings( + link, + lt_settings, + dpcd_lane_status, + &dpcd_lane_status_updated, + &req_settings); + + if (dpcd_lane_status_updated.bits. + POST_LT_ADJ_REQ_IN_PROGRESS == 0) + return true; + + if (!is_cr_done(lane_count, dpcd_lane_status)) + return false; + + if (!is_ch_eq_done( + lane_count, + dpcd_lane_status, + &dpcd_lane_status_updated)) + return false; + + for (lane = 0; lane < (uint32_t)(lane_count); lane++) { + + if (lt_settings-> + lane_settings[lane].VOLTAGE_SWING != + req_settings.lane_settings[lane]. + VOLTAGE_SWING || + lt_settings->lane_settings[lane].PRE_EMPHASIS != + req_settings.lane_settings[lane].PRE_EMPHASIS) { + + req_drv_setting_changed = true; + break; + } + } + + if (req_drv_setting_changed) { + update_drive_settings( + lt_settings,req_settings); + + dc_link_dp_set_drive_settings(&link->public, + lt_settings); + break; + } + + msleep(1); + } + + if (!req_drv_setting_changed) { + dm_logger_write(link->ctx->logger, LOG_WARNING, + "%s: Post Link Training Adjust Request Timed out\n", + __func__); + + ASSERT(0); + return true; + } + } + dm_logger_write(link->ctx->logger, LOG_WARNING, + "%s: Post Link Training Adjust Request limit reached\n", + __func__); + + ASSERT(0); + return true; + +} + +static enum hw_dp_training_pattern get_supported_tp(struct core_link *link) +{ + enum hw_dp_training_pattern highest_tp = HW_DP_TRAINING_PATTERN_2; + struct encoder_feature_support *features = &link->link_enc->features; + struct dpcd_caps *dpcd_caps = &link->dpcd_caps; + + if (features->flags.bits.IS_TPS3_CAPABLE) + highest_tp = HW_DP_TRAINING_PATTERN_3; + + if (features->flags.bits.IS_TPS4_CAPABLE) + highest_tp = HW_DP_TRAINING_PATTERN_4; + + if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED && + highest_tp >= HW_DP_TRAINING_PATTERN_4) + return HW_DP_TRAINING_PATTERN_4; + + if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED && + highest_tp >= HW_DP_TRAINING_PATTERN_3) + return HW_DP_TRAINING_PATTERN_3; + + return HW_DP_TRAINING_PATTERN_2; +} + +static bool perform_channel_equalization_sequence( + struct core_link *link, + struct link_training_settings *lt_settings) +{ + struct link_training_settings req_settings; + enum hw_dp_training_pattern hw_tr_pattern; + uint32_t retries_ch_eq; + enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; + union lane_align_status_updated dpcd_lane_status_updated = {{0}}; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};; + + hw_tr_pattern = get_supported_tp(link); + + dp_set_hw_training_pattern(link, hw_tr_pattern); + + for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT; + retries_ch_eq++) { + + dp_set_hw_lane_settings(link, lt_settings); + + /* 2. update DPCD*/ + if (!retries_ch_eq) + /* EPR #361076 - write as a 5-byte burst, + * but only for the 1-st iteration*/ + dpcd_set_lt_pattern_and_lane_settings( + link, + lt_settings, + hw_tr_pattern); + else + dpcd_set_lane_settings(link, lt_settings); + + /* 3. wait for receiver to lock-on*/ + wait_for_training_aux_rd_interval(link, 400); + + /* 4. Read lane status and requested + * drive settings as set by the sink*/ + + get_lane_status_and_drive_settings( + link, + lt_settings, + dpcd_lane_status, + &dpcd_lane_status_updated, + &req_settings); + + /* 5. check CR done*/ + if (!is_cr_done(lane_count, dpcd_lane_status)) + return false; + + /* 6. check CHEQ done*/ + if (is_ch_eq_done(lane_count, + dpcd_lane_status, + &dpcd_lane_status_updated)) + return true; + + /* 7. update VS/PE/PC2 in lt_settings*/ + update_drive_settings(lt_settings, req_settings); + } + + return false; + +} + +static bool perform_clock_recovery_sequence( + struct core_link *link, + struct link_training_settings *lt_settings) +{ + uint32_t retries_cr; + uint32_t retry_count; + uint32_t lane; + struct link_training_settings req_settings; + enum dc_lane_count lane_count = + lt_settings->link_settings.lane_count; + enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; + union lane_align_status_updated dpcd_lane_status_updated; + + retries_cr = 0; + retry_count = 0; + /* initial drive setting (VS/PE/PC2)*/ + for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { + lt_settings->lane_settings[lane].VOLTAGE_SWING = + VOLTAGE_SWING_LEVEL0; + lt_settings->lane_settings[lane].PRE_EMPHASIS = + PRE_EMPHASIS_DISABLED; + lt_settings->lane_settings[lane].POST_CURSOR2 = + POST_CURSOR2_DISABLED; + } + + dp_set_hw_training_pattern(link, hw_tr_pattern); + + /* najeeb - The synaptics MST hub can put the LT in + * infinite loop by switching the VS + */ + /* between level 0 and level 1 continuously, here + * we try for CR lock for LinkTrainingMaxCRRetry count*/ + while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) && + (retry_count < LINK_TRAINING_MAX_CR_RETRY)) { + + memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); + memset(&dpcd_lane_status_updated, '\0', + sizeof(dpcd_lane_status_updated)); + + /* 1. call HWSS to set lane settings*/ + dp_set_hw_lane_settings( + link, + lt_settings); + + /* 2. update DPCD of the receiver*/ + if (!retries_cr) + /* EPR #361076 - write as a 5-byte burst, + * but only for the 1-st iteration.*/ + dpcd_set_lt_pattern_and_lane_settings( + link, + lt_settings, + hw_tr_pattern); + else + dpcd_set_lane_settings( + link, + lt_settings); + + /* 3. wait receiver to lock-on*/ + wait_for_training_aux_rd_interval( + link, + 100); + + /* 4. Read lane status and requested drive + * settings as set by the sink + */ + get_lane_status_and_drive_settings( + link, + lt_settings, + dpcd_lane_status, + &dpcd_lane_status_updated, + &req_settings); + + /* 5. check CR done*/ + if (is_cr_done(lane_count, dpcd_lane_status)) + return true; + + /* 6. max VS reached*/ + if (is_max_vs_reached(lt_settings)) + return false; + + /* 7. same voltage*/ + /* Note: VS same for all lanes, + * so comparing first lane is sufficient*/ + if (lt_settings->lane_settings[0].VOLTAGE_SWING == + req_settings.lane_settings[0].VOLTAGE_SWING) + retries_cr++; + else + retries_cr = 0; + + /* 8. update VS/PE/PC2 in lt_settings*/ + update_drive_settings(lt_settings, req_settings); + + retry_count++; + } + + if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) { + ASSERT(0); + dm_logger_write(link->ctx->logger, LOG_ERROR, + "%s: Link Training Error, could not \ + get CR after %d tries. \ + Possibly voltage swing issue", __func__, + LINK_TRAINING_MAX_CR_RETRY); + + } + + return false; +} + +static inline bool perform_link_training_int( + struct core_link *link, + struct link_training_settings *lt_settings, + bool status) +{ + union lane_count_set lane_count_set = { {0} }; + union dpcd_training_pattern dpcd_pattern = { {0} }; + + /* 3. set training not in progress*/ + dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE; + dpcd_set_training_pattern(link, dpcd_pattern); + + /* 4. mainlink output idle pattern*/ + dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); + + /* + * 5. post training adjust if required + * If the upstream DPTX and downstream DPRX both support TPS4, + * TPS4 must be used instead of POST_LT_ADJ_REQ. + */ + if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 && + get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4) + return status; + + if (status && + perform_post_lt_adj_req_sequence(link, lt_settings) == false) + status = false; + + lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count; + lane_count_set.bits.ENHANCED_FRAMING = 1; + lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0; + + core_link_write_dpcd( + link, + DPCD_ADDRESS_LANE_COUNT_SET, + &lane_count_set.raw, + sizeof(lane_count_set)); + + return status; +} + +bool dc_link_dp_perform_link_training( + struct dc_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + bool status; + + char *link_rate = "Unknown"; + struct link_training_settings lt_settings; + + status = false; + memset(<_settings, '\0', sizeof(lt_settings)); + + lt_settings.link_settings.link_rate = link_setting->link_rate; + lt_settings.link_settings.lane_count = link_setting->lane_count; + + /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/ + + /* TODO hard coded to SS for now + * lt_settings.link_settings.link_spread = + * dal_display_path_is_ss_supported( + * path_mode->display_path) ? + * LINK_SPREAD_05_DOWNSPREAD_30KHZ : + * LINK_SPREAD_DISABLED; + */ + lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ; + + /* 1. set link rate, lane count and spread*/ + dpcd_set_link_settings(core_link, <_settings); + + /* 2. perform link training (set link training done + * to false is done as well)*/ + if (perform_clock_recovery_sequence(core_link, <_settings)) { + + if (perform_channel_equalization_sequence(core_link, + <_settings)) + status = true; + } + + if (status || !skip_video_pattern) + status = perform_link_training_int(core_link, + <_settings, status); + + /* 6. print status message*/ + switch (lt_settings.link_settings.link_rate) { + + case LINK_RATE_LOW: + link_rate = "RBR"; + break; + case LINK_RATE_HIGH: + link_rate = "HBR"; + break; + case LINK_RATE_HIGH2: + link_rate = "HBR2"; + break; + case LINK_RATE_RBR2: + link_rate = "RBR2"; + break; + case LINK_RATE_HIGH3: + link_rate = "HBR3"; + break; + default: + break; + } + + /* Connectivity log: link training */ + CONN_MSG_LT(core_link, "%sx%d %s VS=%d, PE=%d", + link_rate, + lt_settings.link_settings.lane_count, + status ? "pass" : "fail", + lt_settings.lane_settings[0].VOLTAGE_SWING, + lt_settings.lane_settings[0].PRE_EMPHASIS); + + return status; +} + + +bool perform_link_training_with_retries( + struct core_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern, + int attempts) +{ + uint8_t j; + uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY; + + for (j = 0; j < attempts; ++j) { + + if (dc_link_dp_perform_link_training( + &link->public, + link_setting, + skip_video_pattern)) + return true; + + msleep(delay_between_attempts); + delay_between_attempts += LINK_TRAINING_RETRY_DELAY; + } + + return false; +} + +/*TODO add more check to see if link support request link configuration */ +static bool is_link_setting_supported( + const struct dc_link_settings *link_setting, + const struct dc_link_settings *max_link_setting) +{ + if (link_setting->lane_count > max_link_setting->lane_count || + link_setting->link_rate > max_link_setting->link_rate) + return false; + return true; +} + +static const uint32_t get_link_training_fallback_table_len( + struct core_link *link) +{ + return ARRAY_SIZE(link_training_fallback_table); +} + +static const struct dc_link_settings *get_link_training_fallback_table( + struct core_link *link, uint32_t i) +{ + return &link_training_fallback_table[i]; +} + +static bool exceeded_limit_link_setting( + const struct dc_link_settings *link_setting, + const struct dc_link_settings *limit_link_setting) +{ + return (link_setting->lane_count * link_setting->link_rate + > limit_link_setting->lane_count * limit_link_setting->link_rate ? + true : false); +} + +static struct dc_link_settings get_max_link_cap(struct core_link *link) +{ + /* Set Default link settings */ + struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, + LINK_SPREAD_05_DOWNSPREAD_30KHZ}; + + /* Higher link settings based on feature supported */ + if (link->link_enc->features.flags.bits.IS_HBR2_CAPABLE) + max_link_cap.link_rate = LINK_RATE_HIGH2; + + if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE) + max_link_cap.link_rate = LINK_RATE_HIGH3; + + /* Lower link settings based on sink's link cap */ + if (link->public.reported_link_cap.lane_count < max_link_cap.lane_count) + max_link_cap.lane_count = + link->public.reported_link_cap.lane_count; + if (link->public.reported_link_cap.link_rate < max_link_cap.link_rate) + max_link_cap.link_rate = + link->public.reported_link_cap.link_rate; + if (link->public.reported_link_cap.link_spread < + max_link_cap.link_spread) + max_link_cap.link_spread = + link->public.reported_link_cap.link_spread; + return max_link_cap; +} + +bool dp_hbr_verify_link_cap( + struct core_link *link, + struct dc_link_settings *known_limit_link_setting) +{ + struct dc_link_settings max_link_cap = {0}; + bool success; + bool skip_link_training; + const struct dc_link_settings *cur; + bool skip_video_pattern; + uint32_t i; + struct clock_source *dp_cs; + enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL; + + success = false; + skip_link_training = false; + + max_link_cap = get_max_link_cap(link); + + /* TODO implement override and monitor patch later */ + + /* try to train the link from high to low to + * find the physical link capability + */ + /* disable PHY done possible by BIOS, will be done by driver itself */ + dp_disable_link_phy(link, link->public.connector_signal); + + dp_cs = link->dc->res_pool->dp_clock_source; + + if (dp_cs) + dp_cs_id = dp_cs->id; + else { + /* + * dp clock source is not initialized for some reason. + * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used + */ + ASSERT(dp_cs); + } + + for (i = 0; i < get_link_training_fallback_table_len(link) && + !success; i++) { + cur = get_link_training_fallback_table(link, i); + + if (known_limit_link_setting->lane_count != LANE_COUNT_UNKNOWN && + exceeded_limit_link_setting(cur, + known_limit_link_setting)) + continue; + + if (!is_link_setting_supported(cur, &max_link_cap)) + continue; + + skip_video_pattern = true; + if (cur->link_rate == LINK_RATE_LOW) + skip_video_pattern = false; + + dp_enable_link_phy( + link, + link->public.connector_signal, + dp_cs_id, + cur); + + if (skip_link_training) + success = true; + else { + success = dc_link_dp_perform_link_training( + &link->public, + cur, + skip_video_pattern); + } + + if (success) + link->public.verified_link_cap = *cur; + + /* always disable the link before trying another + * setting or before returning we'll enable it later + * based on the actual mode we're driving + */ + dp_disable_link_phy(link, link->public.connector_signal); + } + + /* Link Training failed for all Link Settings + * (Lane Count is still unknown) + */ + if (!success) { + /* If all LT fails for all settings, + * set verified = failed safe (1 lane low) + */ + link->public.verified_link_cap.lane_count = LANE_COUNT_ONE; + link->public.verified_link_cap.link_rate = LINK_RATE_LOW; + + link->public.verified_link_cap.link_spread = + LINK_SPREAD_DISABLED; + } + + link->public.max_link_setting = link->public.verified_link_cap; + + return success; +} + +static uint32_t bandwidth_in_kbps_from_timing( + const struct dc_crtc_timing *timing) +{ + uint32_t bits_per_channel = 0; + uint32_t kbps; + switch (timing->display_color_depth) { + + case COLOR_DEPTH_666: + bits_per_channel = 6; + break; + case COLOR_DEPTH_888: + bits_per_channel = 8; + break; + case COLOR_DEPTH_101010: + bits_per_channel = 10; + break; + case COLOR_DEPTH_121212: + bits_per_channel = 12; + break; + case COLOR_DEPTH_141414: + bits_per_channel = 14; + break; + case COLOR_DEPTH_161616: + bits_per_channel = 16; + break; + default: + break; + } + ASSERT(bits_per_channel != 0); + + kbps = timing->pix_clk_khz; + kbps *= bits_per_channel; + + if (timing->flags.Y_ONLY != 1) + /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ + kbps *= 3; + + return kbps; + +} + +static uint32_t bandwidth_in_kbps_from_link_settings( + const struct dc_link_settings *link_setting) +{ + uint32_t link_rate_in_kbps = link_setting->link_rate * + LINK_RATE_REF_FREQ_IN_KHZ; + + uint32_t lane_count = link_setting->lane_count; + uint32_t kbps = link_rate_in_kbps; + kbps *= lane_count; + kbps *= 8; /* 8 bits per byte*/ + + return kbps; + +} + +bool dp_validate_mode_timing( + struct core_link *link, + const struct dc_crtc_timing *timing) +{ + uint32_t req_bw; + uint32_t max_bw; + + const struct dc_link_settings *link_setting; + + /*always DP fail safe mode*/ + if (timing->pix_clk_khz == (uint32_t)25175 && + timing->h_addressable == (uint32_t)640 && + timing->v_addressable == (uint32_t)480) + return true; + + /* We always use verified link settings */ + link_setting = &link->public.verified_link_cap; + + /* TODO: DYNAMIC_VALIDATION needs to be implemented */ + /*if (flags.DYNAMIC_VALIDATION == 1 && + link->public.verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) + link_setting = &link->public.verified_link_cap; + */ + + req_bw = bandwidth_in_kbps_from_timing(timing); + max_bw = bandwidth_in_kbps_from_link_settings(link_setting); + + if (req_bw <= max_bw) { + /* remember the biggest mode here, during + * initial link training (to get + * verified_link_cap), LS sends event about + * cannot train at reported cap to upper + * layer and upper layer will re-enumerate modes. + * this is not necessary if the lower + * verified_link_cap is enough to drive + * all the modes */ + + /* TODO: DYNAMIC_VALIDATION needs to be implemented */ + /* if (flags.DYNAMIC_VALIDATION == 1) + dpsst->max_req_bw_for_verified_linkcap = dal_max( + dpsst->max_req_bw_for_verified_linkcap, req_bw); */ + return true; + } else + return false; +} + +void decide_link_settings(struct core_stream *stream, + struct dc_link_settings *link_setting) +{ + + const struct dc_link_settings *cur_ls; + struct core_link* link; + uint32_t req_bw; + uint32_t link_bw; + uint32_t i; + + req_bw = bandwidth_in_kbps_from_timing( + &stream->public.timing); + + /* if preferred is specified through AMDDP, use it, if it's enough + * to drive the mode + */ + link = stream->sink->link; + + if ((link->public.reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) && + (link->public.reported_link_cap.link_rate <= + link->public.verified_link_cap.link_rate)) { + + link_bw = bandwidth_in_kbps_from_link_settings( + &link->public.reported_link_cap); + + if (req_bw < link_bw) { + *link_setting = link->public.reported_link_cap; + return; + } + } + + /* search for first suitable setting for the requested + * bandwidth + */ + for (i = 0; i < get_link_training_fallback_table_len(link); i++) { + + cur_ls = get_link_training_fallback_table(link, i); + + link_bw = + bandwidth_in_kbps_from_link_settings( + cur_ls); + + if (req_bw < link_bw) { + if (is_link_setting_supported( + cur_ls, + &link->public.max_link_setting)) { + *link_setting = *cur_ls; + return; + } + } + } + + BREAK_TO_DEBUGGER(); + ASSERT(link->public.verified_link_cap.lane_count != + LANE_COUNT_UNKNOWN); + + *link_setting = link->public.verified_link_cap; +} + +/*************************Short Pulse IRQ***************************/ + +static bool hpd_rx_irq_check_link_loss_status( + struct core_link *link, + union hpd_irq_data *hpd_irq_dpcd_data) +{ + uint8_t irq_reg_rx_power_state; + enum dc_status dpcd_result = DC_ERROR_UNEXPECTED; + union lane_status lane_status; + uint32_t lane; + bool sink_status_changed; + bool return_code; + + sink_status_changed = false; + return_code = false; + + if (link->public.cur_link_settings.lane_count == 0) + return return_code; + /*1. Check that we can handle interrupt: Not in FS DOS, + * Not in "Display Timeout" state, Link is trained. + */ + + dpcd_result = core_link_read_dpcd(link, + DPCD_ADDRESS_POWER_STATE, + &irq_reg_rx_power_state, + sizeof(irq_reg_rx_power_state)); + + if (dpcd_result != DC_OK) { + irq_reg_rx_power_state = DP_PWR_STATE_D0; + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: DPCD read failed to obtain power state.\n", + __func__); + } + + if (irq_reg_rx_power_state == DP_PWR_STATE_D0) { + + /*2. Check that Link Status changed, before re-training.*/ + + /*parse lane status*/ + for (lane = 0; + lane < link->public.cur_link_settings.lane_count; + lane++) { + + /* check status of lanes 0,1 + * changed DpcdAddress_Lane01Status (0x202)*/ + lane_status.raw = get_nibble_at_index( + &hpd_irq_dpcd_data->bytes.lane01_status.raw, + lane); + + if (!lane_status.bits.CHANNEL_EQ_DONE_0 || + !lane_status.bits.CR_DONE_0 || + !lane_status.bits.SYMBOL_LOCKED_0) { + /* if one of the channel equalization, clock + * recovery or symbol lock is dropped + * consider it as (link has been + * dropped) dp sink status has changed*/ + sink_status_changed = true; + break; + } + + } + + /* Check interlane align.*/ + if (sink_status_changed || + !hpd_irq_dpcd_data->bytes.lane_status_updated.bits. + INTERLANE_ALIGN_DONE) { + + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: Link Status changed.\n", + __func__); + + return_code = true; + } + } + + return return_code; +} + +static enum dc_status read_hpd_rx_irq_data( + struct core_link *link, + union hpd_irq_data *irq_data) +{ + /* The HW reads 16 bytes from 200h on HPD, + * but if we get an AUX_DEFER, the HW cannot retry + * and this causes the CTS tests 4.3.2.1 - 3.2.4 to + * fail, so we now explicitly read 6 bytes which is + * the req from the above mentioned test cases. + */ + return core_link_read_dpcd( + link, + DPCD_ADDRESS_SINK_COUNT, + irq_data->raw, + sizeof(union hpd_irq_data)); +} + +static bool allow_hpd_rx_irq(const struct core_link *link) +{ + /* + * Don't handle RX IRQ unless one of following is met: + * 1) The link is established (cur_link_settings != unknown) + * 2) We kicked off MST detection + * 3) We know we're dealing with an active dongle + */ + + if ((link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || + (link->public.type == dc_connection_mst_branch) || + is_dp_active_dongle(link)) + return true; + + return false; +} + +static bool handle_hpd_irq_psr_sink(const struct core_link *link) +{ + union dpcd_psr_configuration psr_configuration; + + if (link->public.psr_caps.psr_version == 0) + return false; + + dal_ddc_service_read_dpcd_data( + link->ddc, + 368 /*DpcdAddress_PSR_Enable_Cfg*/, + &psr_configuration.raw, + sizeof(psr_configuration.raw)); + + if (psr_configuration.bits.ENABLE) { + unsigned char dpcdbuf[3] = {0}; + union psr_error_status psr_error_status; + union psr_sink_psr_status psr_sink_psr_status; + + dal_ddc_service_read_dpcd_data( + link->ddc, + 0x2006 /*DpcdAddress_PSR_Error_Status*/, + (unsigned char *) dpcdbuf, + sizeof(dpcdbuf)); + + /*DPCD 2006h ERROR STATUS*/ + psr_error_status.raw = dpcdbuf[0]; + /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/ + psr_sink_psr_status.raw = dpcdbuf[2]; + + if (psr_error_status.bits.LINK_CRC_ERROR || + psr_error_status.bits.RFB_STORAGE_ERROR) { + /* Acknowledge and clear error bits */ + dal_ddc_service_write_dpcd_data( + link->ddc, + 8198 /*DpcdAddress_PSR_Error_Status*/, + &psr_error_status.raw, + sizeof(psr_error_status.raw)); + + /* PSR error, disable and re-enable PSR */ + dc_link_set_psr_enable(&link->public, false); + dc_link_set_psr_enable(&link->public, true); + + return true; + } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == + PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){ + /* No error is detect, PSR is active. + * We should return with IRQ_HPD handled without + * checking for loss of sync since PSR would have + * powered down main link. + */ + return true; + } + } + return false; +} + +static void dp_test_send_link_training(struct core_link *link) +{ + struct dc_link_settings link_settings; + + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_LANE_COUNT, + (unsigned char *)(&link_settings.lane_count), + 1); + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_LINK_RATE, + (unsigned char *)(&link_settings.link_rate), + 1); + + /* Set preferred link settings */ + link->public.verified_link_cap.lane_count = link_settings.lane_count; + link->public.verified_link_cap.link_rate = link_settings.link_rate; + + dp_retrain_link(link); +} + +static void dp_test_send_phy_test_pattern(struct core_link *link) +{ + union phy_test_pattern dpcd_test_pattern; + union lane_adjust dpcd_lane_adjustment[2]; + unsigned char dpcd_post_cursor_2_adjustment = 0; + unsigned char test_80_bit_pattern[ + (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; + enum dp_test_pattern test_pattern; + struct dc_link_training_settings link_settings; + union lane_adjust dpcd_lane_adjust; + unsigned int lane; + struct link_training_settings link_training_settings; + int i = 0; + + dpcd_test_pattern.raw = 0; + memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment)); + memset(&link_settings, 0, sizeof(link_settings)); + + /* get phy test pattern and pattern parameters from DP receiver */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_PHY_PATTERN, + &dpcd_test_pattern.raw, + sizeof(dpcd_test_pattern)); + core_link_read_dpcd( + link, + DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, + &dpcd_lane_adjustment[0].raw, + sizeof(dpcd_lane_adjustment)); + + /*get post cursor 2 parameters + * For DP 1.1a or eariler, this DPCD register's value is 0 + * For DP 1.2 or later: + * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1 + * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3 + */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2, + &dpcd_post_cursor_2_adjustment, + sizeof(dpcd_post_cursor_2_adjustment)); + + /* translate request */ + switch (dpcd_test_pattern.bits.PATTERN) { + case PHY_TEST_PATTERN_D10_2: + test_pattern = DP_TEST_PATTERN_D102; + break; + case PHY_TEST_PATTERN_SYMBOL_ERROR: + test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR; + break; + case PHY_TEST_PATTERN_PRBS7: + test_pattern = DP_TEST_PATTERN_PRBS7; + break; + case PHY_TEST_PATTERN_80BIT_CUSTOM: + test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; + break; + case PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE: + test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + break; + default: + test_pattern = DP_TEST_PATTERN_VIDEO_MODE; + break; + } + + if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0, + test_80_bit_pattern, + sizeof(test_80_bit_pattern)); + + /* prepare link training settings */ + link_settings.link = link->public.cur_link_settings; + + for (lane = 0; lane < + (unsigned int)(link->public.cur_link_settings.lane_count); + lane++) { + dpcd_lane_adjust.raw = + get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); + link_settings.lane_settings[lane].VOLTAGE_SWING = + (enum dc_voltage_swing) + (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE); + link_settings.lane_settings[lane].PRE_EMPHASIS = + (enum dc_pre_emphasis) + (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE); + link_settings.lane_settings[lane].POST_CURSOR2 = + (enum dc_post_cursor2) + ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); + } + + for (i = 0; i < 4; i++) + link_training_settings.lane_settings[i] = + link_settings.lane_settings[i]; + link_training_settings.link_settings = link_settings.link; + link_training_settings.allow_invalid_msa_timing_param = false; + /*Usage: Measure DP physical lane signal + * by DP SI test equipment automatically. + * PHY test pattern request is generated by equipment via HPD interrupt. + * HPD needs to be active all the time. HPD should be active + * all the time. Do not touch it. + * forward request to DS + */ + dc_link_dp_set_test_pattern( + &link->public, + test_pattern, + &link_training_settings, + test_80_bit_pattern, + (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); +} + +static void dp_test_send_link_test_pattern(struct core_link *link) +{ + union link_test_pattern dpcd_test_pattern; + union test_misc dpcd_test_params; + enum dp_test_pattern test_pattern; + + memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern)); + memset(&dpcd_test_params, 0, sizeof(dpcd_test_params)); + + /* get link test pattern and pattern parameters */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_PATTERN, + &dpcd_test_pattern.raw, + sizeof(dpcd_test_pattern)); + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_MISC1, + &dpcd_test_params.raw, + sizeof(dpcd_test_params)); + + switch (dpcd_test_pattern.bits.PATTERN) { + case LINK_TEST_PATTERN_COLOR_RAMP: + test_pattern = DP_TEST_PATTERN_COLOR_RAMP; + break; + case LINK_TEST_PATTERN_VERTICAL_BARS: + test_pattern = DP_TEST_PATTERN_VERTICAL_BARS; + break; /* black and white */ + case LINK_TEST_PATTERN_COLOR_SQUARES: + test_pattern = (dpcd_test_params.bits.DYN_RANGE == + TEST_DYN_RANGE_VESA ? + DP_TEST_PATTERN_COLOR_SQUARES : + DP_TEST_PATTERN_COLOR_SQUARES_CEA); + break; + default: + test_pattern = DP_TEST_PATTERN_VIDEO_MODE; + break; + } + + dc_link_dp_set_test_pattern( + &link->public, + test_pattern, + NULL, + NULL, + 0); +} + +static void handle_automated_test(struct core_link *link) +{ + union test_request test_request; + union test_response test_response; + + memset(&test_request, 0, sizeof(test_request)); + memset(&test_response, 0, sizeof(test_response)); + + core_link_read_dpcd( + link, + DPCD_ADDRESS_TEST_REQUEST, + &test_request.raw, + sizeof(union test_request)); + if (test_request.bits.LINK_TRAINING) { + /* ACK first to let DP RX test box monitor LT sequence */ + test_response.bits.ACK = 1; + core_link_write_dpcd( + link, + DPCD_ADDRESS_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); + dp_test_send_link_training(link); + /* no acknowledge request is needed again */ + test_response.bits.ACK = 0; + } + if (test_request.bits.LINK_TEST_PATTRN) { + dp_test_send_link_test_pattern(link); + link->public.compliance_test_state.bits. + SET_TEST_PATTERN_PENDING = 1; + } + if (test_request.bits.PHY_TEST_PATTERN) { + dp_test_send_phy_test_pattern(link); + test_response.bits.ACK = 1; + } + if (!test_request.raw) + /* no requests, revert all test signals + * TODO: revert all test signals + */ + test_response.bits.ACK = 1; + /* send request acknowledgment */ + if (test_response.bits.ACK) + core_link_write_dpcd( + link, + DPCD_ADDRESS_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); +} + +bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) +{ + struct core_link *link = DC_LINK_TO_LINK(dc_link); + union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; + union device_service_irq device_service_clear = {0}; + enum dc_status result = DDC_RESULT_UNKNOWN; + bool status = false; + /* For use cases related to down stream connection status change, + * PSR and device auto test, refer to function handle_sst_hpd_irq + * in DAL2.1*/ + + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: Got short pulse HPD on link %d\n", + __func__, link->public.link_index); + + /* All the "handle_hpd_irq_xxx()" methods + * should be called only after + * dal_dpsst_ls_read_hpd_irq_data + * Order of calls is important too + */ + result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data); + + if (result != DC_OK) { + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: DPCD read failed to obtain irq data\n", + __func__); + return false; + } + + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) { + device_service_clear.bits.AUTOMATED_TEST = 1; + core_link_write_dpcd( + link, + DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR, + &device_service_clear.raw, + sizeof(device_service_clear.raw)); + device_service_clear.raw = 0; + handle_automated_test(link); + return false; + } + + if (!allow_hpd_rx_irq(link)) { + dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, + "%s: skipping HPD handling on %d\n", + __func__, link->public.link_index); + return false; + } + + if (handle_hpd_irq_psr_sink(link)) + /* PSR-related error was detected and handled */ + return true; + + /* If PSR-related error handled, Main link may be off, + * so do not handle as a normal sink status change interrupt. + */ + + /* check if we have MST msg and return since we poll for it */ + if (hpd_irq_dpcd_data.bytes.device_service_irq. + bits.DOWN_REP_MSG_RDY || + hpd_irq_dpcd_data.bytes.device_service_irq. + bits.UP_REQ_MSG_RDY) + return false; + + /* For now we only handle 'Downstream port status' case. + * If we got sink count changed it means + * Downstream port status changed, + * then DM should call DC to do the detection. */ + if (hpd_rx_irq_check_link_loss_status( + link, + &hpd_irq_dpcd_data)) { + /* Connectivity log: link loss */ + CONN_DATA_LINK_LOSS(link, + hpd_irq_dpcd_data.raw, + sizeof(hpd_irq_dpcd_data), + "Status: "); + + perform_link_training_with_retries(link, + &link->public.cur_link_settings, + true, LINK_TRAINING_ATTEMPTS); + + status = false; + } + + if (link->public.type == dc_connection_active_dongle && + hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT + != link->dpcd_sink_count) + status = true; + + /* reasons for HPD RX: + * 1. Link Loss - ie Re-train the Link + * 2. MST sideband message + * 3. Automated Test - ie. Internal Commit + * 4. CP (copy protection) - (not interesting for DM???) + * 5. DRR + * 6. Downstream Port status changed + * -ie. Detect - this the only one + * which is interesting for DM because + * it must call dc_link_detect. + */ + return status; +} + +/*query dpcd for version and mst cap addresses*/ +bool is_mst_supported(struct core_link *link) +{ + bool mst = false; + enum dc_status st = DC_OK; + union dpcd_rev rev; + union mstm_cap cap; + + rev.raw = 0; + cap.raw = 0; + + st = core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, &rev.raw, + sizeof(rev)); + + if (st == DC_OK && rev.raw >= DPCD_REV_12) { + + st = core_link_read_dpcd(link, DPCD_ADDRESS_MSTM_CAP, + &cap.raw, sizeof(cap)); + if (st == DC_OK && cap.bits.MST_CAP == 1) + mst = true; + } + return mst; + +} + +bool is_dp_active_dongle(const struct core_link *link) +{ + enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type; + + return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) || + (dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER) || + (dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER); +} + +static void get_active_converter_info( + uint8_t data, struct core_link *link) +{ + union dp_downstream_port_present ds_port = { .byte = data }; + + /* decode converter info*/ + if (!ds_port.fields.PORT_PRESENT) { + link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; + ddc_service_set_dongle_type(link->ddc, + link->dpcd_caps.dongle_type); + return; + } + + switch (ds_port.fields.PORT_TYPE) { + case DOWNSTREAM_VGA: + link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER; + break; + case DOWNSTREAM_DVI_HDMI: + /* At this point we don't know is it DVI or HDMI, + * assume DVI.*/ + link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER; + break; + default: + link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; + break; + } + + if (link->dpcd_caps.dpcd_rev.raw >= DCS_DPCD_REV_11) { + uint8_t det_caps[4]; + union dwnstream_port_caps_byte0 *port_caps = + (union dwnstream_port_caps_byte0 *)det_caps; + core_link_read_dpcd(link, DPCD_ADDRESS_DWN_STRM_PORT0_CAPS, + det_caps, sizeof(det_caps)); + + switch (port_caps->bits.DWN_STRM_PORTX_TYPE) { + case DOWN_STREAM_DETAILED_VGA: + link->dpcd_caps.dongle_type = + DISPLAY_DONGLE_DP_VGA_CONVERTER; + break; + case DOWN_STREAM_DETAILED_DVI: + link->dpcd_caps.dongle_type = + DISPLAY_DONGLE_DP_DVI_CONVERTER; + break; + case DOWN_STREAM_DETAILED_HDMI: + link->dpcd_caps.dongle_type = + DISPLAY_DONGLE_DP_HDMI_CONVERTER; + + if (ds_port.fields.DETAILED_CAPS) { + + union dwnstream_port_caps_byte3_hdmi + hdmi_caps = {.raw = det_caps[3] }; + + link->dpcd_caps.is_dp_hdmi_s3d_converter = + hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK; + } + break; + } + } + + ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); + + { + struct dp_device_vendor_id dp_id; + + /* read IEEE branch device id */ + core_link_read_dpcd( + link, + DPCD_ADDRESS_BRANCH_DEVICE_ID_START, + (uint8_t *)&dp_id, + sizeof(dp_id)); + + link->dpcd_caps.branch_dev_id = + (dp_id.ieee_oui[0] << 16) + + (dp_id.ieee_oui[1] << 8) + + dp_id.ieee_oui[2]; + + memmove( + link->dpcd_caps.branch_dev_name, + dp_id.ieee_device_id, + sizeof(dp_id.ieee_device_id)); + } + + { + struct dp_sink_hw_fw_revision dp_hw_fw_revision; + + core_link_read_dpcd( + link, + DPCD_ADDRESS_BRANCH_REVISION_START, + (uint8_t *)&dp_hw_fw_revision, + sizeof(dp_hw_fw_revision)); + + link->dpcd_caps.branch_hw_revision = + dp_hw_fw_revision.ieee_hw_rev; + } +} + +static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, + int length) +{ + int retry = 0; + union dp_downstream_port_present ds_port = { 0 }; + + if (!link->dpcd_caps.dpcd_rev.raw) { + do { + dp_receiver_power_ctrl(link, true); + core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, + dpcd_data, length); + link->dpcd_caps.dpcd_rev.raw = dpcd_data[ + DPCD_ADDRESS_DPCD_REV - + DPCD_ADDRESS_DPCD_REV]; + } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw); + } + + ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - + DPCD_ADDRESS_DPCD_REV]; + + if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) { + switch (link->dpcd_caps.branch_dev_id) { + /* Some active dongles (DP-VGA, DP-DLDVI converters) power down + * all internal circuits including AUX communication preventing + * reading DPCD table and EDID (spec violation). + * Encoder will skip DP RX power down on disable_output to + * keep receiver powered all the time.*/ + case DP_BRANCH_DEVICE_ID_1: + case DP_BRANCH_DEVICE_ID_4: + link->wa_flags.dp_keep_receiver_powered = true; + break; + + /* TODO: May need work around for other dongles. */ + default: + link->wa_flags.dp_keep_receiver_powered = false; + break; + } + } else + link->wa_flags.dp_keep_receiver_powered = false; +} + +static void retrieve_psr_link_cap(struct core_link *link, + enum edp_revision edp_revision) +{ + if (edp_revision >= EDP_REVISION_13) { + core_link_read_dpcd(link, + DPCD_ADDRESS_PSR_SUPPORT_VER, + (uint8_t *)(&link->public.psr_caps), + sizeof(link->public.psr_caps)); + if (link->public.psr_caps.psr_version != 0) { + unsigned char psr_capability = 0; + + core_link_read_dpcd(link, + DPCD_ADDRESS_PSR_CAPABILITY, + &psr_capability, + sizeof(psr_capability)); + /* Bit 0 determines whether fast link training is + * required on PSR exit. If set to 0, link training + * is required. If set to 1, sink must lock within + * five Idle Patterns after Main Link is turned on. + */ + link->public.psr_caps.psr_exit_link_training_required + = !(psr_capability & 0x1); + + psr_capability = (psr_capability >> 1) & 0x7; + link->public.psr_caps.psr_rfb_setup_time = + 55 * (6 - psr_capability); + } + } +} + +static void retrieve_link_cap(struct core_link *link) +{ + uint8_t dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL - DPCD_ADDRESS_DPCD_REV + 1]; + + union down_stream_port_count down_strm_port_count; + union edp_configuration_cap edp_config_cap; + union dp_downstream_port_present ds_port = { 0 }; + + memset(dpcd_data, '\0', sizeof(dpcd_data)); + memset(&down_strm_port_count, + '\0', sizeof(union down_stream_port_count)); + memset(&edp_config_cap, '\0', + sizeof(union edp_configuration_cap)); + + core_link_read_dpcd( + link, + DPCD_ADDRESS_DPCD_REV, + dpcd_data, + sizeof(dpcd_data)); + + link->dpcd_caps.dpcd_rev.raw = + dpcd_data[DPCD_ADDRESS_DPCD_REV - DPCD_ADDRESS_DPCD_REV]; + + { + union training_aux_rd_interval aux_rd_interval; + + aux_rd_interval.raw = + dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL]; + + if (aux_rd_interval.bits.EXT_RECIEVER_CAP_FIELD_PRESENT == 1) { + core_link_read_dpcd( + link, + DPCD_ADDRESS_DP13_DPCD_REV, + dpcd_data, + sizeof(dpcd_data)); + } + } + + ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - + DPCD_ADDRESS_DPCD_REV]; + + get_active_converter_info(ds_port.byte, link); + + dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data)); + + link->dpcd_caps.allow_invalid_MSA_timing_param = + down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM; + + link->dpcd_caps.max_ln_count.raw = dpcd_data[ + DPCD_ADDRESS_MAX_LANE_COUNT - DPCD_ADDRESS_DPCD_REV]; + + link->dpcd_caps.max_down_spread.raw = dpcd_data[ + DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV]; + + link->public.reported_link_cap.lane_count = + link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; + link->public.reported_link_cap.link_rate = dpcd_data[ + DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV]; + link->public.reported_link_cap.link_spread = + link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? + LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; + + edp_config_cap.raw = dpcd_data[ + DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV]; + link->dpcd_caps.panel_mode_edp = + edp_config_cap.bits.ALT_SCRAMBLER_RESET; + + link->edp_revision = DPCD_EDP_REVISION_EDP_UNKNOWN; + + link->public.test_pattern_enabled = false; + link->public.compliance_test_state.raw = 0; + + link->public.psr_caps.psr_exit_link_training_required = false; + link->public.psr_caps.psr_frame_capture_indication_req = false; + link->public.psr_caps.psr_rfb_setup_time = 0; + link->public.psr_caps.psr_sdp_transmit_line_num_deadline = 0; + link->public.psr_caps.psr_version = 0; + + /* read sink count */ + core_link_read_dpcd(link, + DPCD_ADDRESS_SINK_COUNT, + &link->dpcd_caps.sink_count.raw, + sizeof(link->dpcd_caps.sink_count.raw)); + + /* Display control registers starting at DPCD 700h are only valid and + * enabled if this eDP config cap bit is set. */ + if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) { + /* Read the Panel's eDP revision at DPCD 700h. */ + core_link_read_dpcd(link, + DPCD_ADDRESS_EDP_REV, + (uint8_t *)(&link->edp_revision), + sizeof(link->edp_revision)); + } + + /* Connectivity log: detection */ + CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); + + /* TODO: Confirm if need retrieve_psr_link_cap */ + retrieve_psr_link_cap(link, link->edp_revision); +} + +void detect_dp_sink_caps(struct core_link *link) +{ + retrieve_link_cap(link); + + /* dc init_hw has power encoder using default + * signal for connector. For native DP, no + * need to power up encoder again. If not native + * DP, hw_init may need check signal or power up + * encoder here. + */ + + if (is_mst_supported(link)) { + link->public.verified_link_cap = link->public.reported_link_cap; + } else { + dp_hbr_verify_link_cap(link, + &link->public.reported_link_cap); + } + /* TODO save sink caps in link->sink */ +} + +void dc_link_dp_enable_hpd(const struct dc_link *link) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + struct link_encoder *encoder = core_link->link_enc; + + if (encoder != NULL && encoder->funcs->enable_hpd != NULL) + encoder->funcs->enable_hpd(encoder); +} + +void dc_link_dp_disable_hpd(const struct dc_link *link) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + struct link_encoder *encoder = core_link->link_enc; + + if (encoder != NULL && encoder->funcs->enable_hpd != NULL) + encoder->funcs->disable_hpd(encoder); +} + +static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) +{ + if (test_pattern == DP_TEST_PATTERN_D102 || + test_pattern == DP_TEST_PATTERN_SYMBOL_ERROR || + test_pattern == DP_TEST_PATTERN_PRBS7 || + test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM || + test_pattern == DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE || + test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN1 || + test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN2 || + test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN3 || + test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN4 || + test_pattern == DP_TEST_PATTERN_VIDEO_MODE) + return true; + else + return false; +} + +static void set_crtc_test_pattern(struct core_link *link, + struct pipe_ctx *pipe_ctx, + enum dp_test_pattern test_pattern) +{ + enum controller_dp_test_pattern controller_test_pattern; + enum dc_color_depth color_depth = pipe_ctx-> + stream->public.timing.display_color_depth; + struct bit_depth_reduction_params params; + + memset(¶ms, 0, sizeof(params)); + + switch (test_pattern) { + case DP_TEST_PATTERN_COLOR_SQUARES: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES; + break; + case DP_TEST_PATTERN_COLOR_SQUARES_CEA: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA; + break; + case DP_TEST_PATTERN_VERTICAL_BARS: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS; + break; + case DP_TEST_PATTERN_HORIZONTAL_BARS: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS; + break; + case DP_TEST_PATTERN_COLOR_RAMP: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_COLORRAMP; + break; + default: + controller_test_pattern = + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE; + break; + } + + switch (test_pattern) { + case DP_TEST_PATTERN_COLOR_SQUARES: + case DP_TEST_PATTERN_COLOR_SQUARES_CEA: + case DP_TEST_PATTERN_VERTICAL_BARS: + case DP_TEST_PATTERN_HORIZONTAL_BARS: + case DP_TEST_PATTERN_COLOR_RAMP: + { + /* disable bit depth reduction */ + pipe_ctx->stream->bit_depth_params = params; + pipe_ctx->opp->funcs-> + opp_program_bit_depth_reduction(pipe_ctx->opp, ¶ms); + + pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + controller_test_pattern, color_depth); + } + break; + case DP_TEST_PATTERN_VIDEO_MODE: + { + /* restore bitdepth reduction */ + link->dc->current_context->res_ctx.pool->funcs-> + build_bit_depth_reduction_params(pipe_ctx->stream, + ¶ms); + pipe_ctx->stream->bit_depth_params = params; + pipe_ctx->opp->funcs-> + opp_program_bit_depth_reduction(pipe_ctx->opp, ¶ms); + + pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + color_depth); + } + break; + + default: + break; + } +} + +bool dc_link_dp_set_test_pattern( + const struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size) +{ + struct core_link *core_link = DC_LINK_TO_CORE(link); + struct pipe_ctx *pipes = + core_link->dc->current_context->res_ctx.pipe_ctx; + struct pipe_ctx pipe_ctx = pipes[0]; + unsigned int lane; + unsigned int i; + unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; + union dpcd_training_pattern training_pattern; + union test_response test_response; + enum dpcd_phy_test_patterns pattern; + + memset(&training_pattern, 0, sizeof(training_pattern)); + memset(&test_response, 0, sizeof(test_response)); + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream->sink->link == core_link) { + pipe_ctx = pipes[i]; + break; + } + } + + /* Reset CRTC Test Pattern if it is currently running and request + * is VideoMode Reset DP Phy Test Pattern if it is currently running + * and request is VideoMode + */ + if (core_link->public.test_pattern_enabled && test_pattern == + DP_TEST_PATTERN_VIDEO_MODE) { + /* Set CRTC Test Pattern */ + set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); + dp_set_hw_test_pattern(core_link, test_pattern, + (uint8_t *)p_custom_pattern, + (uint32_t)cust_pattern_size); + + /* Unblank Stream */ + core_link->dc->hwss.unblank_stream( + &pipe_ctx, + &core_link->public.verified_link_cap); + /* TODO:m_pHwss->MuteAudioEndpoint + * (pPathMode->pDisplayPath, false); + */ + + /* Reset Test Pattern state */ + core_link->public.test_pattern_enabled = false; + + return true; + } + + /* Check for PHY Test Patterns */ + if (is_dp_phy_pattern(test_pattern)) { + /* Set DPCD Lane Settings before running test pattern */ + if (p_link_settings != NULL) { + dp_set_hw_lane_settings(core_link, p_link_settings); + dpcd_set_lane_settings(core_link, p_link_settings); + } + + /* Blank stream if running test pattern */ + if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { + /*TODO: + * m_pHwss-> + * MuteAudioEndpoint(pPathMode->pDisplayPath, true); + */ + /* Blank stream */ + pipes->stream_enc->funcs->dp_blank(pipe_ctx.stream_enc); + } + + dp_set_hw_test_pattern(core_link, test_pattern, + (uint8_t *)p_custom_pattern, + (uint32_t)cust_pattern_size); + + if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { + /* Set Test Pattern state */ + core_link->public.test_pattern_enabled = true; + if (p_link_settings != NULL) + dpcd_set_link_settings(core_link, + p_link_settings); + } + + switch (test_pattern) { + case DP_TEST_PATTERN_VIDEO_MODE: + pattern = PHY_TEST_PATTERN_NONE; + break; + case DP_TEST_PATTERN_D102: + pattern = PHY_TEST_PATTERN_D10_2; + break; + case DP_TEST_PATTERN_SYMBOL_ERROR: + pattern = PHY_TEST_PATTERN_SYMBOL_ERROR; + break; + case DP_TEST_PATTERN_PRBS7: + pattern = PHY_TEST_PATTERN_PRBS7; + break; + case DP_TEST_PATTERN_80BIT_CUSTOM: + pattern = PHY_TEST_PATTERN_80BIT_CUSTOM; + break; + case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: + pattern = PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + break; + default: + return false; + } + + if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE + /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/) + return false; + + if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + /* tell receiver that we are sending qualification + * pattern DP 1.2 or later - DP receiver's link quality + * pattern is set using DPCD LINK_QUAL_LANEx_SET + * register (0x10B~0x10E)\ + */ + for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) + link_qual_pattern[lane] = + (unsigned char)(pattern); + + core_link_write_dpcd(core_link, + DPCD_ADDRESS_LINK_QUAL_LANE0_SET, + link_qual_pattern, + sizeof(link_qual_pattern)); + } else if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || + core_link->dpcd_caps.dpcd_rev.raw == 0) { + /* tell receiver that we are sending qualification + * pattern DP 1.1a or earlier - DP receiver's link + * quality pattern is set using + * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET + * register (0x102). We will use v_1.3 when we are + * setting test pattern for DP 1.1. + */ + core_link_read_dpcd(core_link, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); + training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern; + core_link_write_dpcd(core_link, + DPCD_ADDRESS_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); + } + } else { + /* CRTC Patterns */ + set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); + /* Set Test Pattern state */ + core_link->public.test_pattern_enabled = true; + + /* If this is called because of compliance test request, + * we respond ack here. + */ + if (core_link->public.compliance_test_state.bits. + SET_TEST_PATTERN_PENDING == 1) { + core_link->public.compliance_test_state.bits. + SET_TEST_PATTERN_PENDING = 0; + test_response.bits.ACK = 1; + core_link_write_dpcd(core_link, + DPCD_ADDRESS_TEST_RESPONSE, + &test_response.raw, + sizeof(test_response)); + } + } + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c new file mode 100644 index 000000000000..e89f5f176ec3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -0,0 +1,222 @@ +/* Copyright 2015 Advanced Micro Devices, Inc. */ + + +#include "dm_services.h" +#include "dc.h" +#include "inc/core_dc.h" +#include "include/ddc_service_types.h" +#include "include/i2caux_interface.h" +#include "link_hwss.h" +#include "hw_sequencer.h" +#include "dc_link_dp.h" +#include "dc_link_ddc.h" +#include "dm_helpers.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" + +enum dc_status core_link_read_dpcd( + struct core_link* link, + uint32_t address, + uint8_t *data, + uint32_t size) +{ + if (!dm_helpers_dp_read_dpcd(link->ctx, + &link->public, + address, data, size)) + return DC_ERROR_UNEXPECTED; + + return DC_OK; +} + +enum dc_status core_link_write_dpcd( + struct core_link* link, + uint32_t address, + const uint8_t *data, + uint32_t size) +{ + if (!dm_helpers_dp_write_dpcd(link->ctx, + &link->public, + address, data, size)) + return DC_ERROR_UNEXPECTED; + + return DC_OK; +} + +void dp_receiver_power_ctrl(struct core_link *link, bool on) +{ + uint8_t state; + + state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3; + + core_link_write_dpcd(link, DPCD_ADDRESS_POWER_STATE, &state, + sizeof(state)); +} + +void dp_enable_link_phy( + struct core_link *link, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings) +{ + struct link_encoder *link_enc = link->link_enc; + + if (dc_is_dp_sst_signal(signal)) { + if (signal == SIGNAL_TYPE_EDP) { + link_enc->funcs->power_control(link_enc, true); + link_enc->funcs->backlight_control(link_enc, true); + } + + link_enc->funcs->enable_dp_output( + link_enc, + link_settings, + clock_source); + } else { + link_enc->funcs->enable_dp_mst_output( + link_enc, + link_settings, + clock_source); + } + + dp_receiver_power_ctrl(link, true); +} + +void dp_disable_link_phy(struct core_link *link, enum signal_type signal) +{ + if (!link->wa_flags.dp_keep_receiver_powered) + dp_receiver_power_ctrl(link, false); + + if (signal == SIGNAL_TYPE_EDP) + link->link_enc->funcs->backlight_control(link->link_enc, false); + + link->link_enc->funcs->disable_output(link->link_enc, signal); + + /* Clear current link setting.*/ + memset(&link->public.cur_link_settings, 0, + sizeof(link->public.cur_link_settings)); +} + +void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal) +{ + /* MST disable link only when no stream use the link */ + if (link->mst_stream_alloc_table.stream_count > 0) + return; + + dp_disable_link_phy(link, signal); +} + +bool dp_set_hw_training_pattern( + struct core_link *link, + enum hw_dp_training_pattern pattern) +{ + enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; + + switch (pattern) { + case HW_DP_TRAINING_PATTERN_1: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1; + break; + case HW_DP_TRAINING_PATTERN_2: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2; + break; + case HW_DP_TRAINING_PATTERN_3: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3; + break; + case HW_DP_TRAINING_PATTERN_4: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; + break; + default: + break; + } + + dp_set_hw_test_pattern(link, test_pattern, NULL, 0); + + return true; +} + +void dp_set_hw_lane_settings( + struct core_link *link, + const struct link_training_settings *link_settings) +{ + struct link_encoder *encoder = link->link_enc; + + /* call Encoder to set lane settings */ + encoder->funcs->dp_set_lane_settings(encoder, link_settings); +} + +enum dp_panel_mode dp_get_panel_mode(struct core_link *link) +{ + /* We need to explicitly check that connector + * is not DP. Some Travis_VGA get reported + * by video bios as DP. + */ + if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { + + switch (link->dpcd_caps.branch_dev_id) { + case DP_BRANCH_DEVICE_ID_2: + if (strncmp( + link->dpcd_caps.branch_dev_name, + DP_VGA_LVDS_CONVERTER_ID_2, + sizeof( + link->dpcd_caps. + branch_dev_name)) == 0) { + return DP_PANEL_MODE_SPECIAL; + } + break; + case DP_BRANCH_DEVICE_ID_3: + if (strncmp(link->dpcd_caps.branch_dev_name, + DP_VGA_LVDS_CONVERTER_ID_3, + sizeof( + link->dpcd_caps. + branch_dev_name)) == 0) { + return DP_PANEL_MODE_SPECIAL; + } + break; + default: + break; + } + + if (link->dpcd_caps.panel_mode_edp) { + return DP_PANEL_MODE_EDP; + } + } + + return DP_PANEL_MODE_DEFAULT; +} + +void dp_set_hw_test_pattern( + struct core_link *link, + enum dp_test_pattern test_pattern, + uint8_t *custom_pattern, + uint32_t custom_pattern_size) +{ + struct encoder_set_dp_phy_pattern_param pattern_param = {0}; + struct link_encoder *encoder = link->link_enc; + + pattern_param.dp_phy_pattern = test_pattern; + pattern_param.custom_pattern = custom_pattern; + pattern_param.custom_pattern_size = custom_pattern_size; + pattern_param.dp_panel_mode = dp_get_panel_mode(link); + + encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); +} + + +void dp_retrain_link(struct core_link *link) +{ + struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; + unsigned int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream_enc != NULL) { + dm_delay_in_microseconds(link->ctx, 100); + pipes->stream_enc->funcs->dp_blank(pipes[i].stream_enc); + link->dc->hwss.disable_stream(&pipes[i]); + dc_link_dp_perform_link_training( + &link->public, + &link->public.verified_link_cap, + true); + link->dc->hwss.enable_stream(&pipes[i]); + link->dc->hwss.unblank_stream(&pipes[i], + &link->public.verified_link_cap); + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c new file mode 100644 index 000000000000..bd53d27e5414 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -0,0 +1,1934 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "link_encoder.h" +#include "stream_encoder.h" +#include "opp.h" +#include "timing_generator.h" +#include "transform.h" +#include "set_mode_types.h" + +#include "virtual/virtual_stream_encoder.h" + +#include "dce80/dce80_resource.h" +#include "dce100/dce100_resource.h" +#include "dce110/dce110_resource.h" +#include "dce112/dce112_resource.h" + +enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) +{ + enum dce_version dc_version = DCE_VERSION_UNKNOWN; + switch (asic_id.chip_family) { + + case FAMILY_CI: + case FAMILY_KV: + dc_version = DCE_VERSION_8_0; + break; + case FAMILY_CZ: + dc_version = DCE_VERSION_11_0; + break; + + case FAMILY_VI: + if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || + ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { + dc_version = DCE_VERSION_10_0; + break; + } + if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || + ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) { + dc_version = DCE_VERSION_11_2; + } + break; + default: + dc_version = DCE_VERSION_UNKNOWN; + break; + } + return dc_version; +} + +struct resource_pool *dc_create_resource_pool( + struct core_dc *dc, + int num_virtual_links, + enum dce_version dc_version, + struct hw_asic_id asic_id) +{ + + switch (dc_version) { + case DCE_VERSION_8_0: + return dce80_create_resource_pool( + num_virtual_links, dc); + case DCE_VERSION_10_0: + return dce100_create_resource_pool( + num_virtual_links, dc); + case DCE_VERSION_11_0: + return dce110_create_resource_pool( + num_virtual_links, dc, asic_id); + case DCE_VERSION_11_2: + return dce112_create_resource_pool( + num_virtual_links, dc); + default: + break; + } + + return false; +} + +void dc_destroy_resource_pool(struct core_dc *dc) +{ + if (dc) { + if (dc->res_pool) + dc->res_pool->funcs->destroy(&dc->res_pool); + + if (dc->hwseq) + dm_free(dc->hwseq); + } +} + +static void update_num_audio( + const struct resource_straps *straps, + unsigned int *num_audio, + struct audio_support *aud_support) +{ + if (straps->hdmi_disable == 0) { + aud_support->hdmi_audio_native = true; + aud_support->hdmi_audio_on_dongle = true; + aud_support->dp_audio = true; + } else { + if (straps->dc_pinstraps_audio & 0x2) { + aud_support->hdmi_audio_on_dongle = true; + aud_support->dp_audio = true; + } else { + aud_support->dp_audio = true; + } + } + + switch (straps->audio_stream_number) { + case 0: /* multi streams supported */ + break; + case 1: /* multi streams not supported */ + *num_audio = 1; + break; + default: + DC_ERR("DC: unexpected audio fuse!\n"); + }; +} + +bool resource_construct( + unsigned int num_virtual_links, + struct core_dc *dc, + struct resource_pool *pool, + const struct resource_create_funcs *create_funcs) +{ + struct dc_context *ctx = dc->ctx; + const struct resource_caps *caps = pool->res_cap; + int i; + unsigned int num_audio = caps->num_audio; + struct resource_straps straps = {0}; + + if (create_funcs->read_dce_straps) + create_funcs->read_dce_straps(dc->ctx, &straps); + + pool->audio_count = 0; + if (create_funcs->create_audio) { + /* find the total number of streams available via the + * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT + * registers (one for each pin) starting from pin 1 + * up to the max number of audio pins. + * We stop on the first pin where + * PORT_CONNECTIVITY == 1 (as instructed by HW team). + */ + update_num_audio(&straps, &num_audio, &pool->audio_support); + for (i = 0; i < pool->pipe_count && i < num_audio; i++) { + struct audio *aud = create_funcs->create_audio(ctx, i); + + if (aud == NULL) { + DC_ERR("DC: failed to create audio!\n"); + return false; + } + + if (!aud->funcs->endpoint_valid(aud)) { + aud->funcs->destroy(&aud); + break; + } + + pool->audios[i] = aud; + pool->audio_count++; + } + } + + pool->stream_enc_count = 0; + if (create_funcs->create_stream_encoder) { + for (i = 0; i < caps->num_stream_encoder; i++) { + pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); + if (pool->stream_enc[i] == NULL) + DC_ERR("DC: failed to create stream_encoder!\n"); + pool->stream_enc_count++; + } + } + + for (i = 0; i < num_virtual_links; i++) { + pool->stream_enc[pool->stream_enc_count] = + virtual_stream_encoder_create( + ctx, ctx->dc_bios); + if (pool->stream_enc[pool->stream_enc_count] == NULL) { + DC_ERR("DC: failed to create stream_encoder!\n"); + return false; + } + pool->stream_enc_count++; + } + + dc->hwseq = create_funcs->create_hwseq(ctx); + + return true; +} + + +void resource_unreference_clock_source( + struct resource_context *res_ctx, + struct clock_source *clock_source) +{ + int i; + for (i = 0; i < res_ctx->pool->clk_src_count; i++) { + if (res_ctx->pool->clock_sources[i] != clock_source) + continue; + + res_ctx->clock_source_ref_count[i]--; + + if (res_ctx->clock_source_ref_count[i] == 0) + clock_source->funcs->cs_power_down(clock_source); + + break; + } + + if (res_ctx->pool->dp_clock_source == clock_source) { + res_ctx->dp_clock_source_ref_count--; + + if (res_ctx->dp_clock_source_ref_count == 0) + clock_source->funcs->cs_power_down(clock_source); + } +} + +void resource_reference_clock_source( + struct resource_context *res_ctx, + struct clock_source *clock_source) +{ + int i; + for (i = 0; i < res_ctx->pool->clk_src_count; i++) { + if (res_ctx->pool->clock_sources[i] != clock_source) + continue; + + res_ctx->clock_source_ref_count[i]++; + break; + } + + if (res_ctx->pool->dp_clock_source == clock_source) + res_ctx->dp_clock_source_ref_count++; +} + +bool resource_are_streams_timing_synchronizable( + const struct core_stream *stream1, + const struct core_stream *stream2) +{ + if (stream1->public.timing.h_total != stream2->public.timing.h_total) + return false; + + if (stream1->public.timing.v_total != stream2->public.timing.v_total) + return false; + + if (stream1->public.timing.h_addressable + != stream2->public.timing.h_addressable) + return false; + + if (stream1->public.timing.v_addressable + != stream2->public.timing.v_addressable) + return false; + + if (stream1->public.timing.pix_clk_khz + != stream2->public.timing.pix_clk_khz) + return false; + + if (stream1->phy_pix_clk != stream2->phy_pix_clk + && !dc_is_dp_signal(stream1->signal) + && !dc_is_dp_signal(stream2->signal)) + return false; + + return true; +} + +static bool is_sharable_clk_src( + const struct pipe_ctx *pipe_with_clk_src, + const struct pipe_ctx *pipe) +{ + if (pipe_with_clk_src->clock_source == NULL) + return false; + + if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) + return false; + + if (dc_is_dp_signal(pipe_with_clk_src->stream->signal)) + return false; + + if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) + && dc_is_dvi_signal(pipe->stream->signal)) + return false; + + if (dc_is_hdmi_signal(pipe->stream->signal) + && dc_is_dvi_signal(pipe_with_clk_src->stream->signal)) + return false; + + if (!resource_are_streams_timing_synchronizable( + pipe_with_clk_src->stream, pipe->stream)) + return false; + + return true; +} + +struct clock_source *resource_find_used_clk_src_for_sharing( + struct resource_context *res_ctx, + struct pipe_ctx *pipe_ctx) +{ + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) + return res_ctx->pipe_ctx[i].clock_source; + } + + return NULL; +} + +static enum pixel_format convert_pixel_format_to_dalsurface( + enum surface_pixel_format surface_pixel_format) +{ + enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; + + switch (surface_pixel_format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + dal_pixel_format = PIXEL_FORMAT_INDEX8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + dal_pixel_format = PIXEL_FORMAT_RGB565; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + dal_pixel_format = PIXEL_FORMAT_RGB565; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + dal_pixel_format = PIXEL_FORMAT_ARGB8888; + break; + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + dal_pixel_format = PIXEL_FORMAT_ARGB8888; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + dal_pixel_format = PIXEL_FORMAT_ARGB2101010; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + dal_pixel_format = PIXEL_FORMAT_ARGB2101010; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + dal_pixel_format = PIXEL_FORMAT_FP16; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + dal_pixel_format = PIXEL_FORMAT_420BPP12; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + dal_pixel_format = PIXEL_FORMAT_420BPP12; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + default: + dal_pixel_format = PIXEL_FORMAT_UNKNOWN; + break; + } + return dal_pixel_format; +} + +static void rect_swap_helper(struct rect *rect) +{ + uint32_t temp = 0; + + temp = rect->height; + rect->height = rect->width; + rect->width = temp; + + temp = rect->x; + rect->x = rect->y; + rect->y = temp; +} + +static void calculate_viewport( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx) +{ + struct rect stream_src = pipe_ctx->stream->public.src; + struct rect src = surface->src_rect; + struct rect dst = surface->dst_rect; + struct rect surface_clip = surface->clip_rect; + struct rect clip = {0}; + + + if (surface->rotation == ROTATION_ANGLE_90 || + surface->rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&src); + rect_swap_helper(&dst); + rect_swap_helper(&surface_clip); + rect_swap_helper(&stream_src); + } + + /* The actual clip is an intersection between stream + * source and surface clip + */ + clip.x = stream_src.x > surface_clip.x ? + stream_src.x : surface_clip.x; + + clip.width = stream_src.x + stream_src.width < + surface_clip.x + surface_clip.width ? + stream_src.x + stream_src.width - clip.x : + surface_clip.x + surface_clip.width - clip.x ; + + clip.y = stream_src.y > surface_clip.y ? + stream_src.y : surface_clip.y; + + clip.height = stream_src.y + stream_src.height < + surface_clip.y + surface_clip.height ? + stream_src.y + stream_src.height - clip.y : + surface_clip.y + surface_clip.height - clip.y ; + + /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio + * num_pixels = clip.num_pix * scl_ratio + */ + pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) * + src.width / dst.width; + pipe_ctx->scl_data.viewport.width = clip.width * + src.width / dst.width; + + pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) * + src.height / dst.height; + pipe_ctx->scl_data.viewport.height = clip.height * + src.height / dst.height; + + /* Minimum viewport such that 420/422 chroma vp is non 0 */ + if (pipe_ctx->scl_data.viewport.width < 2) + pipe_ctx->scl_data.viewport.width = 2; + if (pipe_ctx->scl_data.viewport.height < 2) + pipe_ctx->scl_data.viewport.height = 2; +} + +static void calculate_recout( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct rect clip = surface->clip_rect; + + pipe_ctx->scl_data.recout.x = stream->public.dst.x; + if (stream->public.src.x < clip.x) + pipe_ctx->scl_data.recout.x += (clip.x + - stream->public.src.x) * stream->public.dst.width + / stream->public.src.width; + + pipe_ctx->scl_data.recout.width = clip.width * + stream->public.dst.width / stream->public.src.width; + if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > + stream->public.dst.x + stream->public.dst.width) + pipe_ctx->scl_data.recout.width = + stream->public.dst.x + stream->public.dst.width + - pipe_ctx->scl_data.recout.x; + + pipe_ctx->scl_data.recout.y = stream->public.dst.y; + if (stream->public.src.y < clip.y) + pipe_ctx->scl_data.recout.y += (clip.y + - stream->public.src.y) * stream->public.dst.height + / stream->public.src.height; + + pipe_ctx->scl_data.recout.height = clip.height * + stream->public.dst.height / stream->public.src.height; + if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > + stream->public.dst.y + stream->public.dst.height) + pipe_ctx->scl_data.recout.height = + stream->public.dst.y + stream->public.dst.height + - pipe_ctx->scl_data.recout.y; +} + +static void calculate_scaling_ratios( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + const uint32_t in_w = stream->public.src.width; + const uint32_t in_h = stream->public.src.height; + const uint32_t out_w = stream->public.dst.width; + const uint32_t out_h = stream->public.dst.height; + + pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( + surface->src_rect.width, + surface->dst_rect.width); + pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( + surface->src_rect.height, + surface->dst_rect.height); + + if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE) + pipe_ctx->scl_data.ratios.horz.value *= 2; + else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) + pipe_ctx->scl_data.ratios.vert.value *= 2; + + pipe_ctx->scl_data.ratios.vert.value = div64_s64( + pipe_ctx->scl_data.ratios.vert.value * in_h, out_h); + pipe_ctx->scl_data.ratios.horz.value = div64_s64( + pipe_ctx->scl_data.ratios.horz.value * in_w, out_w); + + pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; + pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; + + if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) { + pipe_ctx->scl_data.ratios.horz_c.value /= 2; + pipe_ctx->scl_data.ratios.vert_c.value /= 2; + } +} + +bool resource_build_scaling_params( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx) +{ + bool res; + struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + /* Important: scaling ratio calculation requires pixel format, + * lb depth calculation requires recout and taps require scaling ratios. + */ + pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format); + + calculate_viewport(surface, pipe_ctx); + + if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16) + return false; + + calculate_scaling_ratios(surface, pipe_ctx); + + calculate_recout(surface, pipe_ctx); + + /** + * Setting line buffer pixel depth to 24bpp yields banding + * on certain displays, such as the Sharp 4k + */ + pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + + pipe_ctx->scl_data.h_active = timing->h_addressable; + pipe_ctx->scl_data.v_active = timing->v_addressable; + + /* Taps calculations */ + res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + + if (!res) { + /* Try 24 bpp linebuffer */ + pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; + + res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + } + + dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, + "%s: Viewport:\nheight:%d width:%d x:%d " + "y:%d\n dst_rect:\nheight:%d width:%d x:%d " + "y:%d\n", + __func__, + pipe_ctx->scl_data.viewport.height, + pipe_ctx->scl_data.viewport.width, + pipe_ctx->scl_data.viewport.x, + pipe_ctx->scl_data.viewport.y, + surface->dst_rect.height, + surface->dst_rect.width, + surface->dst_rect.x, + surface->dst_rect.y); + + return res; +} + + +enum dc_status resource_build_scaling_params_for_context( + const struct core_dc *dc, + struct validate_context *context) +{ + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (context->res_ctx.pipe_ctx[i].surface != NULL && + context->res_ctx.pipe_ctx[i].stream != NULL) + if (!resource_build_scaling_params( + &context->res_ctx.pipe_ctx[i].surface->public, + &context->res_ctx.pipe_ctx[i])) + return DC_FAIL_BANDWIDTH_VALIDATE; + } + + return DC_OK; +} + +static void detach_surfaces_for_target( + struct validate_context *context, + const struct dc_target *dc_target) +{ + int i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; + if (cur_pipe->stream == stream) { + cur_pipe->surface = NULL; + cur_pipe->top_pipe = NULL; + cur_pipe->bottom_pipe = NULL; + } + } +} + +struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx) +{ + int i; + struct pipe_ctx *secondary_pipe = NULL; + + /* + * search backwards for the second pipe to keep pipe + * assignment more consistent + */ + + for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + if (res_ctx->pipe_ctx[i].stream == NULL) { + secondary_pipe = &res_ctx->pipe_ctx[i]; + secondary_pipe->pipe_idx = i; + break; + } + } + + + return secondary_pipe; +} + +struct pipe_ctx *resource_get_head_pipe_for_stream( + struct resource_context *res_ctx, + const struct core_stream *stream) +{ + int i; + for (i = 0; i < res_ctx->pool->pipe_count; i++) { + if (res_ctx->pipe_ctx[i].stream == stream && + !res_ctx->pipe_ctx[i].top_pipe) { + return &res_ctx->pipe_ctx[i]; + break; + } + } + return NULL; +} + +/* + * A free_pipe for a target is defined here as a pipe with a stream that belongs + * to the target but has no surface attached yet + */ +static struct pipe_ctx *acquire_free_pipe_for_target( + struct resource_context *res_ctx, + const struct dc_target *dc_target) +{ + int i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + + struct pipe_ctx *head_pipe = NULL; + + /* Find head pipe, which has the back end set up*/ + + head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); + + if (!head_pipe) + ASSERT(0); + + if (!head_pipe->surface) + return head_pipe; + + /* Re-use pipe already acquired for this stream if available*/ + for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + if (res_ctx->pipe_ctx[i].stream == stream && + !res_ctx->pipe_ctx[i].surface) { + return &res_ctx->pipe_ctx[i]; + } + } + + /* + * At this point we have no re-useable pipe for this stream and we need + * to acquire an idle one to satisfy the request + */ + + if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer) + return NULL; + + return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream); + +} + +static void release_free_pipes_for_target( + struct resource_context *res_ctx, + const struct dc_target *dc_target) +{ + int i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + + for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + if (res_ctx->pipe_ctx[i].stream == stream && + !res_ctx->pipe_ctx[i].surface) { + res_ctx->pipe_ctx[i].stream = NULL; + } + } +} + +bool resource_attach_surfaces_to_context( + const struct dc_surface * const *surfaces, + int surface_count, + const struct dc_target *dc_target, + struct validate_context *context) +{ + int i; + struct pipe_ctx *tail_pipe; + struct dc_target_status *target_status = NULL; + + + if (surface_count > MAX_SURFACE_NUM) { + dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n", + surface_count, MAX_SURFACE_NUM); + return false; + } + + for (i = 0; i < context->target_count; i++) + if (&context->targets[i]->public == dc_target) { + target_status = &context->target_status[i]; + break; + } + if (target_status == NULL) { + dm_error("Existing target not found; failed to attach surfaces\n"); + return false; + } + + /* retain new surfaces */ + for (i = 0; i < surface_count; i++) + dc_surface_retain(surfaces[i]); + + detach_surfaces_for_target(context, dc_target); + + /* release existing surfaces*/ + for (i = 0; i < target_status->surface_count; i++) + dc_surface_release(target_status->surfaces[i]); + + for (i = surface_count; i < target_status->surface_count; i++) + target_status->surfaces[i] = NULL; + + target_status->surface_count = 0; + + if (surface_count == 0) + return true; + + tail_pipe = NULL; + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); + struct pipe_ctx *free_pipe = acquire_free_pipe_for_target( + &context->res_ctx, dc_target); + + if (!free_pipe) { + target_status->surfaces[i] = NULL; + return false; + } + + free_pipe->surface = surface; + + if (tail_pipe) { + free_pipe->top_pipe = tail_pipe; + tail_pipe->bottom_pipe = free_pipe; + } + + tail_pipe = free_pipe; + } + + release_free_pipes_for_target(&context->res_ctx, dc_target); + + /* assign new surfaces*/ + for (i = 0; i < surface_count; i++) + target_status->surfaces[i] = surfaces[i]; + + target_status->surface_count = surface_count; + + return true; +} + + +static bool is_timing_changed(const struct core_stream *cur_stream, + const struct core_stream *new_stream) +{ + if (cur_stream == NULL) + return true; + + /* If sink pointer changed, it means this is a hotplug, we should do + * full hw setting. + */ + if (cur_stream->sink != new_stream->sink) + return true; + + /* If output color space is changed, need to reprogram info frames */ + if (cur_stream->public.output_color_space != + new_stream->public.output_color_space) + return true; + + return memcmp( + &cur_stream->public.timing, + &new_stream->public.timing, + sizeof(struct dc_crtc_timing)) != 0; +} + +static bool are_stream_backends_same( + const struct core_stream *stream_a, const struct core_stream *stream_b) +{ + if (stream_a == stream_b) + return true; + + if (stream_a == NULL || stream_b == NULL) + return false; + + if (is_timing_changed(stream_a, stream_b)) + return false; + + return true; +} + +bool is_target_unchanged( + const struct core_target *old_target, const struct core_target *target) +{ + int i; + + if (old_target == target) + return true; + if (old_target->public.stream_count != target->public.stream_count) + return false; + + for (i = 0; i < old_target->public.stream_count; i++) { + const struct core_stream *old_stream = DC_STREAM_TO_CORE( + old_target->public.streams[i]); + const struct core_stream *stream = DC_STREAM_TO_CORE( + target->public.streams[i]); + + if (!are_stream_backends_same(old_stream, stream)) + return false; + } + + return true; +} + +bool resource_validate_attach_surfaces( + const struct dc_validation_set set[], + int set_count, + const struct validate_context *old_context, + struct validate_context *context) +{ + int i, j; + + for (i = 0; i < set_count; i++) { + for (j = 0; j < old_context->target_count; j++) + if (is_target_unchanged( + old_context->targets[j], + context->targets[i])) { + if (!resource_attach_surfaces_to_context( + old_context->target_status[j].surfaces, + old_context->target_status[j].surface_count, + &context->targets[i]->public, + context)) + return false; + context->target_status[i] = old_context->target_status[j]; + } + if (set[i].surface_count != 0) + if (!resource_attach_surfaces_to_context( + set[i].surfaces, + set[i].surface_count, + &context->targets[i]->public, + context)) + return false; + + } + + return true; +} + +/* Maximum TMDS single link pixel clock 165MHz */ +#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 + +static void set_stream_engine_in_use( + struct resource_context *res_ctx, + struct stream_encoder *stream_enc) +{ + int i; + + for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { + if (res_ctx->pool->stream_enc[i] == stream_enc) + res_ctx->is_stream_enc_acquired[i] = true; + } +} + +/* TODO: release audio object */ +static void set_audio_in_use( + struct resource_context *res_ctx, + struct audio *audio) +{ + int i; + for (i = 0; i < res_ctx->pool->audio_count; i++) { + if (res_ctx->pool->audios[i] == audio) { + res_ctx->is_audio_acquired[i] = true; + } + } +} + +static int acquire_first_free_pipe( + struct resource_context *res_ctx, + struct core_stream *stream) +{ + int i; + + for (i = 0; i < res_ctx->pool->pipe_count; i++) { + if (!res_ctx->pipe_ctx[i].stream) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + pipe_ctx->tg = res_ctx->pool->timing_generators[i]; + pipe_ctx->mi = res_ctx->pool->mis[i]; + pipe_ctx->ipp = res_ctx->pool->ipps[i]; + pipe_ctx->xfm = res_ctx->pool->transforms[i]; + pipe_ctx->opp = res_ctx->pool->opps[i]; + pipe_ctx->dis_clk = res_ctx->pool->display_clock; + pipe_ctx->pipe_idx = i; + + pipe_ctx->stream = stream; + return i; + } + } + return -1; +} + +static struct stream_encoder *find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + struct core_stream *stream) +{ + int i; + int j = -1; + struct core_link *link = stream->sink->link; + + for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { + if (!res_ctx->is_stream_enc_acquired[i] && + res_ctx->pool->stream_enc[i]) { + /* Store first available for MST second display + * in daisy chain use case */ + j = i; + if (res_ctx->pool->stream_enc[i]->id == + link->link_enc->preferred_engine) + return res_ctx->pool->stream_enc[i]; + } + } + + /* + * below can happen in cases when stream encoder is acquired: + * 1) for second MST display in chain, so preferred engine already + * acquired; + * 2) for another link, which preferred engine already acquired by any + * MST configuration. + * + * If signal is of DP type and preferred engine not found, return last available + * + * TODO - This is just a patch up and a generic solution is + * required for non DP connectors. + */ + + if (j >= 0 && dc_is_dp_signal(stream->signal)) + return res_ctx->pool->stream_enc[j]; + + return NULL; +} + +static struct audio *find_first_free_audio(struct resource_context *res_ctx) +{ + int i; + for (i = 0; i < res_ctx->pool->audio_count; i++) { + if (res_ctx->is_audio_acquired[i] == false) { + return res_ctx->pool->audios[i]; + } + } + + return 0; +} + +static void update_stream_signal(struct core_stream *stream) +{ + const struct dc_sink *dc_sink = stream->public.sink; + + stream->signal = dc_sink->sink_signal; + /* For asic supports dual link DVI, we should adjust signal type + * based on timing pixel clock. If pixel clock more than 165Mhz, + * signal is dual link, otherwise, single link. + */ + if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || + dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) { + if (stream->public.timing.pix_clk_khz > + TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + else + stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + } +} + +bool resource_is_stream_unchanged( + const struct validate_context *old_context, struct core_stream *stream) +{ + int i, j; + + for (i = 0; i < old_context->target_count; i++) { + struct core_target *old_target = old_context->targets[i]; + + for (j = 0; j < old_target->public.stream_count; j++) { + struct core_stream *old_stream = + DC_STREAM_TO_CORE(old_target->public.streams[j]); + + if (are_stream_backends_same(old_stream, stream)) + return true; + } + } + + return false; +} + +static void copy_pipe_ctx( + const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) +{ + struct core_surface *surface = to_pipe_ctx->surface; + struct core_stream *stream = to_pipe_ctx->stream; + + *to_pipe_ctx = *from_pipe_ctx; + to_pipe_ctx->stream = stream; + if (surface != NULL) + to_pipe_ctx->surface = surface; +} + +static struct core_stream *find_pll_sharable_stream( + const struct core_stream *stream_needs_pll, + struct validate_context *context) +{ + int i, j; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream_has_pll = + DC_STREAM_TO_CORE(target->public.streams[j]); + + /* We are looking for non dp, non virtual stream */ + if (resource_are_streams_timing_synchronizable( + stream_needs_pll, stream_has_pll) + && !dc_is_dp_signal(stream_has_pll->signal) + && stream_has_pll->sink->link->public.connector_signal + != SIGNAL_TYPE_VIRTUAL) + return stream_has_pll; + } + } + + return NULL; +} + +static int get_norm_pix_clk(const struct dc_crtc_timing *timing) +{ + uint32_t pix_clk = timing->pix_clk_khz; + uint32_t normalized_pix_clk = pix_clk; + + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + pix_clk /= 2; + + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + normalized_pix_clk = pix_clk; + break; + case COLOR_DEPTH_101010: + normalized_pix_clk = (pix_clk * 30) / 24; + break; + case COLOR_DEPTH_121212: + normalized_pix_clk = (pix_clk * 36) / 24; + break; + case COLOR_DEPTH_161616: + normalized_pix_clk = (pix_clk * 48) / 24; + break; + default: + ASSERT(0); + break; + } + + return normalized_pix_clk; +} + +static void calculate_phy_pix_clks( + const struct core_dc *dc, + struct validate_context *context) +{ + int i, j; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + update_stream_signal(stream); + + /* update actual pixel clock on all streams */ + if (dc_is_hdmi_signal(stream->signal)) + stream->phy_pix_clk = get_norm_pix_clk( + &stream->public.timing); + else + stream->phy_pix_clk = + stream->public.timing.pix_clk_khz; + } + } +} + +enum dc_status resource_map_pool_resources( + const struct core_dc *dc, + struct validate_context *context) +{ + int i, j, k; + + calculate_phy_pix_clks(dc, context); + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + if (!resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + /* mark resources used for stream that is already active */ + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + const struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[k]; + + if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) + continue; + + pipe_ctx->stream = stream; + copy_pipe_ctx(old_pipe_ctx, pipe_ctx); + + set_stream_engine_in_use( + &context->res_ctx, + pipe_ctx->stream_enc); + + /* Switch to dp clock source only if there is + * no non dp stream that shares the same timing + * with the dp stream. + */ + if (dc_is_dp_signal(pipe_ctx->stream->signal) && + !find_pll_sharable_stream(stream, context)) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); + + set_audio_in_use(&context->res_ctx, + pipe_ctx->audio); + } + } + } + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct pipe_ctx *pipe_ctx = NULL; + int pipe_idx = -1; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + /* acquire new resources */ + pipe_idx = acquire_first_free_pipe( + &context->res_ctx, stream); + if (pipe_idx < 0) + return DC_NO_CONTROLLER_RESOURCE; + + + pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + pipe_ctx->stream_enc = + find_first_free_match_stream_enc_for_link( + &context->res_ctx, stream); + + if (!pipe_ctx->stream_enc) + return DC_NO_STREAM_ENG_RESOURCE; + + set_stream_engine_in_use( + &context->res_ctx, + pipe_ctx->stream_enc); + + /* TODO: Add check if ASIC support and EDID audio */ + if (!stream->sink->converter_disable_audio && + dc_is_audio_capable_signal(pipe_ctx->stream->signal) && + stream->public.audio_info.mode_count) { + pipe_ctx->audio = find_first_free_audio( + &context->res_ctx); + + /* + * Audio assigned in order first come first get. + * There are asics which has number of audio + * resources less then number of pipes + */ + if (pipe_ctx->audio) + set_audio_in_use( + &context->res_ctx, + pipe_ctx->audio); + } + + if (j == 0) { + context->target_status[i].primary_otg_inst = + pipe_ctx->tg->inst; + } + } + } + + return DC_OK; +} + +/* first target in the context is used to populate the rest */ +void validate_guaranteed_copy_target( + struct validate_context *context, + int max_targets) +{ + int i; + + for (i = 1; i < max_targets; i++) { + context->targets[i] = context->targets[0]; + + copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], + &context->res_ctx.pipe_ctx[i]); + context->res_ctx.pipe_ctx[i].stream = + context->res_ctx.pipe_ctx[0].stream; + + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } +} + +static void translate_info_frame(const struct hw_info_frame *hw_info_frame, + struct encoder_info_frame *encoder_info_frame) +{ + memset( + encoder_info_frame, 0, sizeof(struct encoder_info_frame)); + + /* For gamut we recalc checksum */ + if (hw_info_frame->gamut_packet.valid) { + uint8_t chk_sum = 0; + uint8_t *ptr; + uint8_t i; + + memmove( + &encoder_info_frame->gamut, + &hw_info_frame->gamut_packet, + sizeof(struct hw_info_packet)); + + /*start of the Gamut data. */ + ptr = &encoder_info_frame->gamut.sb[3]; + + for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++) + chk_sum += ptr[i]; + + encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum); + } + + if (hw_info_frame->avi_info_packet.valid) { + memmove( + &encoder_info_frame->avi, + &hw_info_frame->avi_info_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->vendor_info_packet.valid) { + memmove( + &encoder_info_frame->vendor, + &hw_info_frame->vendor_info_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->spd_packet.valid) { + memmove( + &encoder_info_frame->spd, + &hw_info_frame->spd_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->vsc_packet.valid) { + memmove( + &encoder_info_frame->vsc, + &hw_info_frame->vsc_packet, + sizeof(struct hw_info_packet)); + } +} + +static void set_avi_info_frame( + struct hw_info_packet *info_packet, + struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; + struct info_frame info_frame = { {0} }; + uint32_t pixel_encoding = 0; + enum scanning_type scan_type = SCANNING_TYPE_NODATA; + enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; + bool itc = false; + uint8_t cn0_cn1 = 0; + uint8_t *check_sum = NULL; + uint8_t byte_index = 0; + + if (info_packet == NULL) + return; + + color_space = pipe_ctx->stream->public.output_color_space; + + /* Initialize header */ + info_frame.avi_info_packet.info_packet_hdmi.bits.header. + info_frame_type = INFO_FRAME_AVI; + /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall + * not be used in HDMI 2.0 (Section 10.1) */ + info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = + INFO_FRAME_VERSION_2; + info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = + INFO_FRAME_SIZE_AVI; + + /* + * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built + * according to HDMI 2.0 spec (Section 10.1) + */ + + switch (stream->public.timing.pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + pixel_encoding = 1; + break; + + case PIXEL_ENCODING_YCBCR444: + pixel_encoding = 2; + break; + case PIXEL_ENCODING_YCBCR420: + pixel_encoding = 3; + break; + + case PIXEL_ENCODING_RGB: + default: + pixel_encoding = 0; + } + + /* Y0_Y1_Y2 : The pixel encoding */ + /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ + info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 = + pixel_encoding; + + /* A0 = 1 Active Format Information valid */ + info_frame.avi_info_packet.info_packet_hdmi.bits.A0 = + ACTIVE_FORMAT_VALID; + + /* B0, B1 = 3; Bar info data is valid */ + info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 = + BAR_INFO_BOTH_VALID; + + info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 = + PICTURE_SCALING_UNIFORM; + + /* S0, S1 : Underscan / Overscan */ + /* TODO: un-hardcode scan type */ + scan_type = SCANNING_TYPE_UNDERSCAN; + info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; + + /* C0, C1 : Colorimetry */ + if (color_space == COLOR_SPACE_YCBCR709) + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_ITU709; + else if (color_space == COLOR_SPACE_YCBCR601) + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_ITU601; + else + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_NO_DATA; + + /* TODO: un-hardcode aspect ratio */ + aspect = stream->public.timing.aspect_ratio; + + switch (aspect) { + case ASPECT_RATIO_4_3: + case ASPECT_RATIO_16_9: + info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect; + break; + + case ASPECT_RATIO_NO_DATA: + case ASPECT_RATIO_64_27: + case ASPECT_RATIO_256_135: + default: + info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0; + } + + /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ + info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 = + ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; + + /* TODO: un-hardcode cn0_cn1 and itc */ + cn0_cn1 = 0; + itc = false; + + if (itc) { + info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1; + info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 = + cn0_cn1; + } + + /* TODO : We should handle YCC quantization */ + /* but we do not have matrix calculation */ + if (color_space == COLOR_SPACE_SRGB) { + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_FULL_RANGE; + info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = + YYC_QUANTIZATION_FULL_RANGE; + } else if (color_space == COLOR_SPACE_SRGB_LIMITED) { + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_LIMITED_RANGE; + info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = + YYC_QUANTIZATION_LIMITED_RANGE; + } else { + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_DEFAULT_RANGE; + info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = + YYC_QUANTIZATION_LIMITED_RANGE; + } + + info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 = + stream->public.timing.vic; + + /* pixel repetition + * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel + * repetition start from 1 */ + info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0; + + /* Bar Info + * barTop: Line Number of End of Top Bar. + * barBottom: Line Number of Start of Bottom Bar. + * barLeft: Pixel Number of End of Left Bar. + * barRight: Pixel Number of Start of Right Bar. */ + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top = + stream->public.timing.v_border_top; + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom = + (stream->public.timing.v_border_top + - stream->public.timing.v_border_bottom + 1); + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left = + stream->public.timing.h_border_left; + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right = + (stream->public.timing.h_total + - stream->public.timing.h_border_right + 1); + + /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ + check_sum = + &info_frame. + avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; + *check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI + + INFO_FRAME_VERSION_2; + + for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++) + *check_sum += info_frame.avi_info_packet.info_packet_hdmi. + packet_raw_data.sb[byte_index]; + + /* one byte complement */ + *check_sum = (uint8_t) (0x100 - *check_sum); + + /* Store in hw_path_mode */ + info_packet->hb0 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0; + info_packet->hb1 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1; + info_packet->hb2 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; + + for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++) + info_packet->sb[byte_index] = info_frame.avi_info_packet. + info_packet_hdmi.packet_raw_data.sb[byte_index]; + + info_packet->valid = true; +} + +static void set_vendor_info_packet(struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + uint32_t length = 0; + bool hdmi_vic_mode = false; + uint8_t checksum = 0; + uint32_t i = 0; + enum dc_timing_3d_format format; + + ASSERT_CRITICAL(stream != NULL); + ASSERT_CRITICAL(info_packet != NULL); + + format = stream->public.timing.timing_3d_format; + + /* Can be different depending on packet content */ + length = 5; + + if (stream->public.timing.hdmi_vic != 0 + && stream->public.timing.h_total >= 3840 + && stream->public.timing.v_total >= 2160) + hdmi_vic_mode = true; + + /* According to HDMI 1.4a CTS, VSIF should be sent + * for both 3D stereo and HDMI VIC modes. + * For all other modes, there is no VSIF sent. */ + + if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) + return; + + /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ + info_packet->sb[1] = 0x03; + info_packet->sb[2] = 0x0C; + info_packet->sb[3] = 0x00; + + /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. + * The value for HDMI_Video_Format are: + * 0x0 (0b000) - No additional HDMI video format is presented in this + * packet + * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC + * parameter follows + * 0x2 (0b010) - 3D format indication present. 3D_Structure and + * potentially 3D_Ext_Data follows + * 0x3..0x7 (0b011..0b111) - reserved for future use */ + if (format != TIMING_3D_FORMAT_NONE) + info_packet->sb[4] = (2 << 5); + else if (hdmi_vic_mode) + info_packet->sb[4] = (1 << 5); + + /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): + * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. + * The value for 3D_Structure are: + * 0x0 - Frame Packing + * 0x1 - Field Alternative + * 0x2 - Line Alternative + * 0x3 - Side-by-Side (full) + * 0x4 - L + depth + * 0x5 - L + depth + graphics + graphics-depth + * 0x6 - Top-and-Bottom + * 0x7 - Reserved for future use + * 0x8 - Side-by-Side (Half) + * 0x9..0xE - Reserved for future use + * 0xF - Not used */ + switch (format) { + case TIMING_3D_FORMAT_HW_FRAME_PACKING: + case TIMING_3D_FORMAT_SW_FRAME_PACKING: + info_packet->sb[5] = (0x0 << 4); + break; + + case TIMING_3D_FORMAT_SIDE_BY_SIDE: + case TIMING_3D_FORMAT_SBS_SW_PACKED: + info_packet->sb[5] = (0x8 << 4); + length = 6; + break; + + case TIMING_3D_FORMAT_TOP_AND_BOTTOM: + case TIMING_3D_FORMAT_TB_SW_PACKED: + info_packet->sb[5] = (0x6 << 4); + break; + + default: + break; + } + + /*PB5: If PB4 is set to 0x1 (extended resolution format) + * fill PB5 with the correct HDMI VIC code */ + if (hdmi_vic_mode) + info_packet->sb[5] = stream->public.timing.hdmi_vic; + + /* Header */ + info_packet->hb0 = 0x81; /* VSIF packet type. */ + info_packet->hb1 = 0x01; /* Version */ + + /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ + info_packet->hb2 = (uint8_t) (length); + + /* Calculate checksum */ + checksum = 0; + checksum += info_packet->hb0; + checksum += info_packet->hb1; + checksum += info_packet->hb2; + + for (i = 1; i <= length; i++) + checksum += info_packet->sb[i]; + + info_packet->sb[0] = (uint8_t) (0x100 - checksum); + + info_packet->valid = true; +} + +static void set_spd_info_packet(struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + /* SPD info packet for FreeSync */ + + unsigned char checksum = 0; + unsigned int idx, payload_size = 0; + + /* Check if Freesync is supported. Return if false. If true, + * set the corresponding bit in the info packet + */ + if (stream->public.freesync_ctx.supported == false) + return; + + if (dc_is_hdmi_signal(stream->signal)) { + + /* HEADER */ + + /* HB0 = Packet Type = 0x83 (Source Product + * Descriptor InfoFrame) + */ + info_packet->hb0 = 0x83; + + /* HB1 = Version = 0x01 */ + info_packet->hb1 = 0x01; + + /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */ + info_packet->hb2 = 0x08; + + payload_size = 0x08; + + } else if (dc_is_dp_signal(stream->signal)) { + + /* HEADER */ + + /* HB0 = Secondary-data Packet ID = 0 - Only non-zero + * when used to associate audio related info packets + */ + info_packet->hb0 = 0x00; + + /* HB1 = Packet Type = 0x83 (Source Product + * Descriptor InfoFrame) + */ + info_packet->hb1 = 0x83; + + /* HB2 = [Bits 7:0 = Least significant eight bits - + * For INFOFRAME, the value must be 1Bh] + */ + info_packet->hb2 = 0x1B; + + /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1] + * [Bits 1:0 = Most significant two bits = 0x00] + */ + info_packet->hb3 = 0x04; + + payload_size = 0x1B; + } + + /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */ + info_packet->sb[1] = 0x1A; + + /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */ + info_packet->sb[2] = 0x00; + + /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */ + info_packet->sb[3] = 0x00; + + /* PB4 = Reserved */ + info_packet->sb[4] = 0x00; + + /* PB5 = Reserved */ + info_packet->sb[5] = 0x00; + + /* PB6 = [Bits 7:3 = Reserved] */ + info_packet->sb[6] = 0x00; + + if (stream->public.freesync_ctx.supported == true) + /* PB6 = [Bit 0 = FreeSync Supported] */ + info_packet->sb[6] |= 0x01; + + if (stream->public.freesync_ctx.enabled == true) + /* PB6 = [Bit 1 = FreeSync Enabled] */ + info_packet->sb[6] |= 0x02; + + if (stream->public.freesync_ctx.active == true) + /* PB6 = [Bit 2 = FreeSync Active] */ + info_packet->sb[6] |= 0x04; + + /* PB7 = FreeSync Minimum refresh rate (Hz) */ + info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx. + min_refresh_in_micro_hz / 1000000); + + /* PB8 = FreeSync Maximum refresh rate (Hz) + * + * Note: We do not use the maximum capable refresh rate + * of the panel, because we should never go above the field + * rate of the mode timing set. + */ + info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx. + nominal_refresh_in_micro_hz / 1000000); + + /* PB9 - PB27 = Reserved */ + for (idx = 9; idx <= 27; idx++) + info_packet->sb[idx] = 0x00; + + /* Calculate checksum */ + checksum += info_packet->hb0; + checksum += info_packet->hb1; + checksum += info_packet->hb2; + checksum += info_packet->hb3; + + for (idx = 1; idx <= payload_size; idx++) + checksum += info_packet->sb[idx]; + + /* PB0 = Checksum (one byte complement) */ + info_packet->sb[0] = (unsigned char) (0x100 - checksum); + + info_packet->valid = true; +} + +static void set_vsc_info_packet(struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + unsigned int vscPacketRevision = 0; + unsigned int i; + + if (stream->sink->link->public.psr_caps.psr_version != 0) { + vscPacketRevision = 2; + } + + /* VSC packet not needed based on the features + * supported by this DP display + */ + if (vscPacketRevision == 0) + return; + + if (vscPacketRevision == 0x2) { + /* Secondary-data Packet ID = 0*/ + info_packet->hb0 = 0x00; + /* 07h - Packet Type Value indicating Video + * Stream Configuration packet + */ + info_packet->hb1 = 0x07; + /* 02h = VSC SDP supporting 3D stereo and PSR + * (applies to eDP v1.3 or higher). + */ + info_packet->hb2 = 0x02; + /* 08h = VSC packet supporting 3D stereo + PSR + * (HB2 = 02h). + */ + info_packet->hb3 = 0x08; + + for (i = 0; i < 28; i++) + info_packet->sb[i] = 0; + + info_packet->valid = true; + } + + /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ +} + +void resource_validate_ctx_destruct(struct validate_context *context) +{ + int i, j; + + for (i = 0; i < context->target_count; i++) { + for (j = 0; j < context->target_status[i].surface_count; j++) + dc_surface_release( + context->target_status[i].surfaces[j]); + + context->target_status[i].surface_count = 0; + dc_target_release(&context->targets[i]->public); + } +} + +/* + * Copy src_ctx into dst_ctx and retain all surfaces and targets referenced + * by the src_ctx + */ +void resource_validate_ctx_copy_construct( + const struct validate_context *src_ctx, + struct validate_context *dst_ctx) +{ + int i, j; + + *dst_ctx = *src_ctx; + + for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; + + if (cur_pipe->top_pipe) + cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; + + if (cur_pipe->bottom_pipe) + cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; + + } + + for (i = 0; i < dst_ctx->target_count; i++) { + dc_target_retain(&dst_ctx->targets[i]->public); + for (j = 0; j < dst_ctx->target_status[i].surface_count; j++) + dc_surface_retain( + dst_ctx->target_status[i].surfaces[j]); + } +} + +struct clock_source *dc_resource_find_first_free_pll( + struct resource_context *res_ctx) +{ + int i; + + for (i = 0; i < res_ctx->pool->clk_src_count; ++i) { + if (res_ctx->clock_source_ref_count[i] == 0) + return res_ctx->pool->clock_sources[i]; + } + + return NULL; +} + +void resource_build_info_frame(struct pipe_ctx *pipe_ctx) +{ + enum signal_type signal = SIGNAL_TYPE_NONE; + struct hw_info_frame info_frame = { { 0 } }; + + /* default all packets to invalid */ + info_frame.avi_info_packet.valid = false; + info_frame.gamut_packet.valid = false; + info_frame.vendor_info_packet.valid = false; + info_frame.spd_packet.valid = false; + info_frame.vsc_packet.valid = false; + + signal = pipe_ctx->stream->signal; + + /* HDMi and DP have different info packets*/ + if (dc_is_hdmi_signal(signal)) { + set_avi_info_frame( + &info_frame.avi_info_packet, pipe_ctx); + set_vendor_info_packet( + pipe_ctx->stream, &info_frame.vendor_info_packet); + set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + } + + else if (dc_is_dp_signal(signal)) + set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); + set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + + translate_info_frame(&info_frame, + &pipe_ctx->encoder_info_frame); +} + +enum dc_status resource_map_clock_resources( + const struct core_dc *dc, + struct validate_context *context) +{ + int i, j, k; + + /* acquire new resources */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + else { + pipe_ctx->clock_source = NULL; + + if (!dc->public.config.disable_disp_pll_sharing) + resource_find_used_clk_src_for_sharing( + &context->res_ctx, + pipe_ctx); + + if (pipe_ctx->clock_source == NULL) + pipe_ctx->clock_source = + dc_resource_find_first_free_pll(&context->res_ctx); + } + + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; + + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); + + /* only one cs per stream regardless of mpo */ + break; + } + } + } + + return DC_OK; +} + +/* + * Note: We need to disable output if clock sources change, + * since bios does optimization and doesn't apply if changing + * PHY when not already disabled. + */ +bool pipe_need_reprogram( + struct pipe_ctx *pipe_ctx_old, + struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) + return true; + + if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) + return true; + + if (pipe_ctx_old->audio != pipe_ctx->audio) + return true; + + if (pipe_ctx_old->clock_source != pipe_ctx->clock_source + && pipe_ctx_old->stream != pipe_ctx->stream) + return true; + + if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc) + return true; + + if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) + return true; + + + return false; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c new file mode 100644 index 000000000000..67ae799b6f4f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -0,0 +1,113 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dm_helpers.h" +#include "core_types.h" + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +struct sink { + struct core_sink protected; + int ref_count; +}; + +#define DC_SINK_TO_SINK(dc_sink) \ + container_of(dc_sink, struct sink, protected.public) + +/******************************************************************************* + * Private functions + ******************************************************************************/ + +static void destruct(struct sink *sink) +{ + +} + +static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params) +{ + + struct core_link *core_link = DC_LINK_TO_LINK(init_params->link); + + sink->protected.public.sink_signal = init_params->sink_signal; + sink->protected.link = core_link; + sink->protected.ctx = core_link->ctx; + sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk; + sink->protected.converter_disable_audio = + init_params->converter_disable_audio; + + return true; +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ + +void dc_sink_retain(const struct dc_sink *dc_sink) +{ + struct sink *sink = DC_SINK_TO_SINK(dc_sink); + + ++sink->ref_count; +} + +void dc_sink_release(const struct dc_sink *dc_sink) +{ + struct sink *sink = DC_SINK_TO_SINK(dc_sink); + + --sink->ref_count; + + if (sink->ref_count == 0) { + destruct(sink); + dm_free(sink); + } +} + +struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) +{ + struct sink *sink = dm_alloc(sizeof(*sink)); + + if (NULL == sink) + goto alloc_fail; + + if (false == construct(sink, init_params)) + goto construct_fail; + + /* TODO should we move this outside to where the assignment actually happens? */ + dc_sink_retain(&sink->protected.public); + + return &sink->protected.public; + +construct_fail: + dm_free(sink); + +alloc_fail: + return NULL; +} + +/******************************************************************************* + * Protected functions - visible only inside of DC (not visible in DM) + ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c new file mode 100644 index 000000000000..8d6aa607e1f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -0,0 +1,141 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_types.h" +#include "resource.h" + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +struct stream { + struct core_stream protected; + int ref_count; +}; + +#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public) + +/******************************************************************************* + * Private functions + ******************************************************************************/ + +static bool construct(struct core_stream *stream, + const struct dc_sink *dc_sink_data) +{ + uint32_t i = 0; + + stream->sink = DC_SINK_TO_CORE(dc_sink_data); + stream->ctx = stream->sink->ctx; + stream->public.sink = dc_sink_data; + + dc_sink_retain(dc_sink_data); + + /* Copy audio modes */ + /* TODO - Remove this translation */ + for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++) + { + stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count; + stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code; + stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate; + stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size; + } + stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count; + stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency; + stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency; + memmove( + stream->public.audio_info.display_name, + dc_sink_data->edid_caps.display_name, + AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS); + stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id; + stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id; + stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; + + /* TODO - Unhardcode port_id */ + stream->public.audio_info.port_id[0] = 0x5558859e; + stream->public.audio_info.port_id[1] = 0xd989449; + + /* EDID CAP translation for HDMI 2.0 */ + stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; + + stream->status.link = &stream->sink->link->public; + + return true; +} + +static void destruct(struct core_stream *stream) +{ + dc_sink_release(&stream->sink->public); +} + +void dc_stream_retain(const struct dc_stream *dc_stream) +{ + struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); + stream->ref_count++; +} + +void dc_stream_release(const struct dc_stream *public) +{ + struct stream *stream = DC_STREAM_TO_STREAM(public); + struct core_stream *protected = DC_STREAM_TO_CORE(public); + + if (public != NULL) { + stream->ref_count--; + + if (stream->ref_count == 0) { + destruct(protected); + dm_free(stream); + } + } +} + +struct dc_stream *dc_create_stream_for_sink( + const struct dc_sink *dc_sink) +{ + struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); + struct stream *stream; + + if (sink == NULL) + goto alloc_fail; + + stream = dm_alloc(sizeof(struct stream)); + + if (NULL == stream) + goto alloc_fail; + + if (false == construct(&stream->protected, dc_sink)) + goto construct_fail; + + dc_stream_retain(&stream->protected.public); + + return &stream->protected.public; + +construct_fail: + dm_free(stream); + +alloc_fail: + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c new file mode 100644 index 000000000000..b89d3b5d0ba0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -0,0 +1,213 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* DC interface (public) */ +#include "dm_services.h" +#include "dc.h" + +/* DC core (private) */ +#include "core_dc.h" +#include "transform.h" + +/******************************************************************************* + * Private structures + ******************************************************************************/ +struct surface { + struct core_surface protected; + enum dc_irq_source irq_source; + int ref_count; +}; + +struct gamma { + struct core_gamma protected; + int ref_count; +}; + +#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) +#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) + +#define DC_GAMMA_TO_GAMMA(dc_gamma) \ + container_of(dc_gamma, struct gamma, protected.public) +#define CORE_GAMMA_TO_GAMMA(core_gamma) \ + container_of(core_gamma, struct gamma, protected) + +/******************************************************************************* + * Private functions + ******************************************************************************/ +static bool construct(struct dc_context *ctx, struct surface *surface) +{ + surface->protected.ctx = ctx; + return true; +} + +static void destruct(struct surface *surface) +{ + +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +void enable_surface_flip_reporting(struct dc_surface *dc_surface, + uint32_t controller_id) +{ + struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; + /*register_flip_interrupt(surface);*/ +} + +struct dc_surface *dc_create_surface(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct surface *surface = dm_alloc(sizeof(*surface)); + + if (NULL == surface) + goto alloc_fail; + + if (false == construct(core_dc->ctx, surface)) + goto construct_fail; + + dc_surface_retain(&surface->protected.public); + + return &surface->protected.public; + +construct_fail: + dm_free(surface); + +alloc_fail: + return NULL; +} + +const struct dc_surface_status *dc_surface_get_status( + const struct dc_surface *dc_surface) +{ + struct dc_surface_status *surface_status; + struct core_surface *core_surface; + struct core_dc *core_dc; + int i; + + if (dc_surface == NULL) + return NULL; + + core_surface = DC_SURFACE_TO_CORE(dc_surface); + + if (core_surface == NULL || core_surface->ctx == NULL) + return NULL; + + surface_status = &core_surface->status; + + if (core_surface->ctx == NULL || core_surface->ctx->dc == NULL) + return NULL; + + core_dc = DC_TO_CORE(core_surface->ctx->dc); + + + if (core_dc->current_context == NULL) + return NULL; + + for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; + i++) { + struct pipe_ctx *pipe_ctx = + &core_dc->current_context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->surface != + DC_SURFACE_TO_CORE(dc_surface)) + continue; + + core_dc->hwss.update_pending_status(pipe_ctx); + } + + return surface_status; +} + +void dc_surface_retain(const struct dc_surface *dc_surface) +{ + struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + + ++surface->ref_count; +} + +void dc_surface_release(const struct dc_surface *dc_surface) +{ + struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + + --surface->ref_count; + + if (surface->ref_count == 0) { + destruct(surface); + dm_free(surface); + } +} + +static bool construct_gamma(struct gamma *gamma) +{ + return true; +} + +static void destruct_gamma(struct gamma *gamma) +{ + +} + +void dc_gamma_retain(const struct dc_gamma *dc_gamma) +{ + struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + + ++gamma->ref_count; +} + +void dc_gamma_release(const struct dc_gamma *dc_gamma) +{ + struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + --gamma->ref_count; + + if (gamma->ref_count == 0) { + destruct_gamma(gamma); + dm_free(gamma); + } +} + +struct dc_gamma *dc_create_gamma() +{ + struct gamma *gamma = dm_alloc(sizeof(*gamma)); + + if (gamma == NULL) + goto alloc_fail; + + if (false == construct_gamma(gamma)) + goto construct_fail; + + dc_gamma_retain(&gamma->protected.public); + + return &gamma->protected.public; + +construct_fail: + dm_free(gamma); + +alloc_fail: + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c new file mode 100644 index 000000000000..48eb7b0e0350 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c @@ -0,0 +1,334 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "core_types.h" +#include "hw_sequencer.h" +#include "resource.h" +#include "ipp.h" +#include "timing_generator.h" + +struct target { + struct core_target protected; + int ref_count; +}; + +#define DC_TARGET_TO_TARGET(dc_target) \ + container_of(dc_target, struct target, protected.public) +#define CORE_TARGET_TO_TARGET(core_target) \ + container_of(core_target, struct target, protected) + +static void construct( + struct core_target *target, + struct dc_context *ctx, + struct dc_stream *dc_streams[], + uint8_t stream_count) +{ + uint8_t i; + for (i = 0; i < stream_count; i++) { + target->public.streams[i] = dc_streams[i]; + dc_stream_retain(dc_streams[i]); + } + + target->ctx = ctx; + target->public.stream_count = stream_count; +} + +static void destruct(struct core_target *core_target) +{ + int i; + + for (i = 0; i < core_target->public.stream_count; i++) { + dc_stream_release( + (struct dc_stream *)core_target->public.streams[i]); + core_target->public.streams[i] = NULL; + } +} + +void dc_target_retain(const struct dc_target *dc_target) +{ + struct target *target = DC_TARGET_TO_TARGET(dc_target); + + target->ref_count++; +} + +void dc_target_release(const struct dc_target *dc_target) +{ + struct target *target = DC_TARGET_TO_TARGET(dc_target); + struct core_target *protected = DC_TARGET_TO_CORE(dc_target); + + ASSERT(target->ref_count > 0); + target->ref_count--; + if (target->ref_count == 0) { + destruct(protected); + dm_free(target); + } +} + +const struct dc_target_status *dc_target_get_status( + const struct dc_target* dc_target) +{ + uint8_t i; + struct core_target* target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *dc = DC_TO_CORE(target->ctx->dc); + + for (i = 0; i < dc->current_context->target_count; i++) + if (target == dc->current_context->targets[i]) + return &dc->current_context->target_status[i]; + + return NULL; +} + +struct dc_target *dc_create_target_for_streams( + struct dc_stream *dc_streams[], + uint8_t stream_count) +{ + struct core_stream *stream; + struct target *target; + + if (0 == stream_count) + goto target_alloc_fail; + + stream = DC_STREAM_TO_CORE(dc_streams[0]); + + target = dm_alloc(sizeof(struct target)); + + if (NULL == target) + goto target_alloc_fail; + + construct(&target->protected, stream->ctx, dc_streams, stream_count); + + dc_target_retain(&target->protected.public); + + return &target->protected.public; + +target_alloc_fail: + return NULL; +} + +bool dc_target_is_connected_to_sink( + const struct dc_target * dc_target, + const struct dc_sink *dc_sink) +{ + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + uint8_t i; + for (i = 0; i < target->public.stream_count; i++) { + if (target->public.streams[i]->sink == dc_sink) + return true; + } + return false; +} + +/** + * Update the cursor attributes and set cursor surface address + */ +bool dc_target_set_cursor_attributes( + struct dc_target *dc_target, + const struct dc_cursor_attributes *attributes) +{ + uint8_t i, j; + struct core_target *target; + struct core_dc *core_dc; + struct resource_context *res_ctx; + + if (NULL == dc_target) { + dm_error("DC: dc_target is NULL!\n"); + return false; + + } + if (NULL == attributes) { + dm_error("DC: attributes is NULL!\n"); + return false; + + } + + target = DC_TARGET_TO_CORE(dc_target); + core_dc = DC_TO_CORE(target->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + + for (i = 0; i < target->public.stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + struct input_pixel_processor *ipp = + res_ctx->pipe_ctx[j].ipp; + + if (res_ctx->pipe_ctx[j].stream != + DC_STREAM_TO_CORE(target->public.streams[i])) + continue; + + /* As of writing of this code cursor is on the top + * plane so we only need to set it on first pipe we + * find. May need to make this code dce specific later. + */ + if (ipp->funcs->ipp_cursor_set_attributes( + ipp, attributes)) + return true; + } + } + + return false; +} + +bool dc_target_set_cursor_position( + struct dc_target *dc_target, + const struct dc_cursor_position *position) +{ + uint8_t i, j; + struct core_target *target; + struct core_dc *core_dc; + struct resource_context *res_ctx; + + if (NULL == dc_target) { + dm_error("DC: dc_target is NULL!\n"); + return false; + } + + if (NULL == position) { + dm_error("DC: cursor position is NULL!\n"); + return false; + } + + target = DC_TARGET_TO_CORE(dc_target); + core_dc = DC_TO_CORE(target->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + + for (i = 0; i < target->public.stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + struct input_pixel_processor *ipp = + res_ctx->pipe_ctx[j].ipp; + + if (res_ctx->pipe_ctx[j].stream != + DC_STREAM_TO_CORE(target->public.streams[i])) + continue; + + /* As of writing of this code cursor is on the top + * plane so we only need to set it on first pipe we + * find. May need to make this code dce specific later. + */ + ipp->funcs->ipp_cursor_set_position(ipp, position); + return true; + } + } + + return false; +} + +uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target) +{ + uint8_t i, j; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); + struct resource_context *res_ctx = + &core_dc->current_context->res_ctx; + + for (i = 0; i < target->public.stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + struct timing_generator *tg = res_ctx->pipe_ctx[j].tg; + + if (res_ctx->pipe_ctx[j].stream != + DC_STREAM_TO_CORE(target->public.streams[i])) + continue; + + return tg->funcs->get_frame_count(tg); + } + } + + return 0; +} + +uint32_t dc_target_get_scanoutpos( + const struct dc_target *dc_target, + uint32_t *vbl, + uint32_t *position) +{ + uint8_t i, j; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); + struct resource_context *res_ctx = + &core_dc->current_context->res_ctx; + + for (i = 0; i < target->public.stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + struct timing_generator *tg = res_ctx->pipe_ctx[j].tg; + + if (res_ctx->pipe_ctx[j].stream != + DC_STREAM_TO_CORE(target->public.streams[i])) + continue; + + return tg->funcs->get_scanoutpos(tg, vbl, position); + } + } + + return 0; +} + +void dc_target_log( + const struct dc_target *dc_target, + struct dal_logger *dm_logger, + enum dc_log_type log_type) +{ + int i; + + const struct core_target *core_target = + CONST_DC_TARGET_TO_CORE(dc_target); + + dm_logger_write(dm_logger, + log_type, + "core_target 0x%x: stream_count=%d\n", + core_target, + core_target->public.stream_count); + + for (i = 0; i < core_target->public.stream_count; i++) { + const struct core_stream *core_stream = + DC_STREAM_TO_CORE(core_target->public.streams[i]); + + dm_logger_write(dm_logger, + log_type, + "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n", + core_stream, + core_stream->public.src.x, + core_stream->public.src.y, + core_stream->public.src.width, + core_stream->public.src.height, + core_stream->public.dst.x, + core_stream->public.dst.y, + core_stream->public.dst.width, + core_stream->public.dst.height); + dm_logger_write(dm_logger, + log_type, + "\tpix_clk_khz: %d, h_total: %d, v_total: %d\n", + core_stream->public.timing.pix_clk_khz, + core_stream->public.timing.h_total, + core_stream->public.timing.v_total); + dm_logger_write(dm_logger, + log_type, + "\tsink name: %s, serial: %d\n", + core_stream->sink->public.edid_caps.display_name, + core_stream->sink->public.edid_caps.serial_number); + dm_logger_write(dm_logger, + log_type, + "\tlink: %d\n", + core_stream->sink->link->public.link_index); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h new file mode 100644 index 000000000000..5575484323b3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -0,0 +1,780 @@ +/* + * Copyright 2012-14 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_INTERFACE_H_ +#define DC_INTERFACE_H_ + +#include "dc_types.h" +#include "dpcd_defs.h" +#include "grph_object_defs.h" +#include "logger_types.h" +#include "gpio_types.h" +#include "link_service_types.h" + +#define MAX_TARGETS 6 +#define MAX_SURFACES 6 +#define MAX_SINKS_PER_LINK 4 + +/******************************************************************************* + * Display Core Interfaces + ******************************************************************************/ + +struct dc_caps { + uint32_t max_targets; + uint32_t max_links; + uint32_t max_audios; + uint32_t max_slave_planes; + uint32_t max_downscale_ratio; + uint32_t i2c_speed_in_khz; +}; + + +struct dc_dcc_surface_param { + enum surface_pixel_format format; + struct dc_size surface_size; + enum dc_scan_direction scan; +}; + +struct dc_dcc_setting { + unsigned int max_compressed_blk_size; + unsigned int max_uncompressed_blk_size; + bool independent_64b_blks; +}; + +struct dc_surface_dcc_cap { + bool capable; + bool const_color_support; + + union { + struct { + struct dc_dcc_setting rgb; + } grph; + + struct { + struct dc_dcc_setting luma; + struct dc_dcc_setting chroma; + } video; + }; +}; + +/* Forward declaration*/ +struct dc; +struct dc_surface; +struct validate_context; + +struct dc_cap_funcs { + int i; +}; + +struct dc_stream_funcs { + bool (*adjust_vmin_vmax)(struct dc *dc, + const struct dc_stream **stream, + int num_streams, + int vmin, + int vmax); + + void (*stream_update_scaling)(const struct dc *dc, + const struct dc_stream *dc_stream, + const struct rect *src, + const struct rect *dst); + bool (*set_gamut_remap)(struct dc *dc, + const struct dc_stream **stream, int num_streams); + bool (*set_backlight)(struct dc *dc, unsigned int backlight_level, + unsigned int frame_ramp, const struct dc_stream *stream); + bool (*init_dmcu_backlight_settings)(struct dc *dc); + bool (*set_abm_level)(struct dc *dc, unsigned int abm_level); + bool (*set_psr_enable)(struct dc *dc, bool enable); + bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream); +}; + +struct link_training_settings; + +struct dc_link_funcs { + void (*set_drive_settings)(struct dc *dc, + struct link_training_settings *lt_settings); + void (*perform_link_training)(struct dc *dc, + struct dc_link_settings *link_setting, + bool skip_video_pattern); + void (*set_preferred_link_settings)(struct dc *dc, + struct dc_link_settings *link_setting); + void (*enable_hpd)(const struct dc_link *link); + void (*disable_hpd)(const struct dc_link *link); + void (*set_test_pattern)( + const struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size); +}; + +/* Structure to hold configuration flags set by dm at dc creation. */ +struct dc_config { + bool gpu_vm_support; + bool disable_disp_pll_sharing; +}; + +struct dc_debug { + bool surface_visual_confirm; + bool max_disp_clk; + bool target_trace; + bool surface_trace; + bool validation_trace; + bool disable_stutter; + bool disable_dcc; + bool disable_dfs_bypass; + bool disable_power_gate; + bool disable_clock_gate; +}; + +struct dc { + struct dc_caps caps; + struct dc_cap_funcs cap_funcs; + struct dc_stream_funcs stream_funcs; + struct dc_link_funcs link_funcs; + struct dc_config config; + struct dc_debug debug; +}; + +enum frame_buffer_mode { + FRAME_BUFFER_MODE_LOCAL_ONLY = 0, + FRAME_BUFFER_MODE_ZFB_ONLY, + FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL, +} ; + +struct dchub_init_data { + bool dchub_initialzied; + bool dchub_info_valid; + int64_t zfb_phys_addr_base; + int64_t zfb_mc_base_addr; + uint64_t zfb_size_in_byte; + enum frame_buffer_mode fb_mode; +}; + +struct dc_init_data { + struct hw_asic_id asic_id; + void *driver; /* ctx */ + struct cgs_device *cgs_device; + + int num_virtual_links; + /* + * If 'vbios_override' not NULL, it will be called instead + * of the real VBIOS. Intended use is Diagnostics on FPGA. + */ + struct dc_bios *vbios_override; + enum dce_environment dce_environment; + + struct dc_config flags; +}; + +struct dc *dc_create(const struct dc_init_data *init_params); + +void dc_destroy(struct dc **dc); + +bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); + +/******************************************************************************* + * Surface Interfaces + ******************************************************************************/ + +enum { + RGB_256X3X16 = 256, + FLOAT_GAMMA_RAMP_MAX = 1025 +}; + +enum dc_gamma_ramp_type { + GAMMA_RAMP_RBG256X3X16, + GAMMA_RAMP_FLOAT, +}; + +struct float_rgb { + struct fixed32_32 red; + struct fixed32_32 green; + struct fixed32_32 blue; +}; + +struct dc_gamma_ramp_float { + struct float_rgb scale; + struct float_rgb offset; + struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX]; +}; + +struct dc_gamma_ramp_rgb256x3x16 { + uint16_t red[RGB_256X3X16]; + uint16_t green[RGB_256X3X16]; + uint16_t blue[RGB_256X3X16]; +}; + +struct dc_gamma { + enum dc_gamma_ramp_type type; + union { + struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16; + struct dc_gamma_ramp_float gamma_ramp_float; + }; + uint32_t size; +}; + +struct dc_surface { + bool visible; + bool flip_immediate; + struct dc_plane_address address; + + struct scaling_taps scaling_quality; + struct rect src_rect; + struct rect dst_rect; + struct rect clip_rect; + + union plane_size plane_size; + union dc_tiling_info tiling_info; + struct dc_plane_dcc_param dcc; + enum dc_color_space color_space; + + enum surface_pixel_format format; + enum dc_rotation_angle rotation; + bool horizontal_mirror; + enum plane_stereo_format stereo_format; + + const struct dc_gamma *gamma_correction; +}; + +struct dc_plane_info { + union plane_size plane_size; + union dc_tiling_info tiling_info; + enum surface_pixel_format format; + enum dc_rotation_angle rotation; + bool horizontal_mirror; + enum plane_stereo_format stereo_format; + enum dc_color_space color_space; /*todo: wrong place, fits in scaling info*/ + bool visible; +}; + +struct dc_scaling_info { + struct rect src_rect; + struct rect dst_rect; + struct rect clip_rect; + struct scaling_taps scaling_quality; +}; + +struct dc_surface_update { + const struct dc_surface *surface; + + /* isr safe update parameters. null means no updates */ + struct dc_flip_addrs *flip_addr; + struct dc_plane_info *plane_info; + struct dc_scaling_info *scaling_info; + /* following updates require alloc/sleep/spin that is not isr safe, + * null means no updates + */ + struct dc_gamma *gamma; + + +}; +/* + * This structure is filled in by dc_surface_get_status and contains + * the last requested address and the currently active address so the called + * can determine if there are any outstanding flips + */ +struct dc_surface_status { + struct dc_plane_address requested_address; + struct dc_plane_address current_address; + bool is_flip_pending; +}; + +/* + * Create a new surface with default parameters; + */ +struct dc_surface *dc_create_surface(const struct dc *dc); +const struct dc_surface_status *dc_surface_get_status( + const struct dc_surface *dc_surface); + +void dc_surface_retain(const struct dc_surface *dc_surface); +void dc_surface_release(const struct dc_surface *dc_surface); + +void dc_gamma_release(const struct dc_gamma *dc_gamma); +struct dc_gamma *dc_create_gamma(void); + +/* + * This structure holds a surface address. There could be multiple addresses + * in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such + * as frame durations and DCC format can also be set. + */ +struct dc_flip_addrs { + struct dc_plane_address address; + bool flip_immediate; + /* TODO: DCC format info */ + /* TODO: add flip duration for FreeSync */ +}; + +/* + * Optimized flip address update function. + * + * After this call: + * Surface addresses and flip attributes are programmed. + * Surface flip occur at next configured time (h_sync or v_sync flip) + */ +void dc_flip_surface_addrs(struct dc *dc, + const struct dc_surface *const surfaces[], + struct dc_flip_addrs flip_addrs[], + uint32_t count); + +/* + * Set up surface attributes and associate to a target + * The surfaces parameter is an absolute set of all surface active for the target. + * If no surfaces are provided, the target will be blanked; no memory read. + * Any flip related attribute changes must be done through this interface. + * + * After this call: + * Surfaces attributes are programmed and configured to be composed into target. + * This does not trigger a flip. No surface address is programmed. + */ + +bool dc_commit_surfaces_to_target( + struct dc *dc, + const struct dc_surface **dc_surfaces, + uint8_t surface_count, + struct dc_target *dc_target); + +bool dc_pre_update_surfaces_to_target( + struct dc *dc, + const struct dc_surface *const *new_surfaces, + uint8_t new_surface_count, + struct dc_target *dc_target); + +bool dc_post_update_surfaces_to_target( + struct dc *dc); + +void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates, + int surface_count, struct dc_target *dc_target); + +/******************************************************************************* + * Target Interfaces + ******************************************************************************/ +#define MAX_STREAM_NUM 1 + +struct dc_target { + uint8_t stream_count; + const struct dc_stream *streams[MAX_STREAM_NUM]; +}; + +/* + * Target status is returned from dc_target_get_status in order to get the + * the IRQ source, current frame counter and currently attached surfaces. + */ +struct dc_target_status { + int primary_otg_inst; + int cur_frame_count; + int surface_count; + const struct dc_surface *surfaces[MAX_SURFACE_NUM]; +}; + +struct dc_target *dc_create_target_for_streams( + struct dc_stream *dc_streams[], + uint8_t stream_count); + +/* + * Get the current target status. + */ +const struct dc_target_status *dc_target_get_status( + const struct dc_target* dc_target); + +void dc_target_retain(const struct dc_target *dc_target); +void dc_target_release(const struct dc_target *dc_target); +void dc_target_log( + const struct dc_target *dc_target, + struct dal_logger *dc_logger, + enum dc_log_type log_type); + +uint8_t dc_get_current_target_count(const struct dc *dc); +struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i); + +bool dc_target_is_connected_to_sink( + const struct dc_target *dc_target, + const struct dc_sink *dc_sink); + +uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target); + +/* TODO: Return parsed values rather than direct register read + * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) + * being refactored properly to be dce-specific + */ +uint32_t dc_target_get_scanoutpos( + const struct dc_target *dc_target, + uint32_t *vbl, + uint32_t *position); + +/* + * Structure to store surface/target associations for validation + */ +struct dc_validation_set { + const struct dc_target *target; + const struct dc_surface *surfaces[MAX_SURFACES]; + uint8_t surface_count; +}; + +/* + * This function takes a set of resources and checks that they are cofunctional. + * + * After this call: + * No hardware is programmed for call. Only validation is done. + */ +bool dc_validate_resources( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count); + +/* + * This function takes a target and checks if it is guaranteed to be supported. + * Guaranteed means that MAX_COFUNC*target is supported. + * + * After this call: + * No hardware is programmed for call. Only validation is done. + */ + +bool dc_validate_guaranteed( + const struct dc *dc, + const struct dc_target *dc_target); + +/* + * Set up streams and links associated to targets to drive sinks + * The targets parameter is an absolute set of all active targets. + * + * After this call: + * Phy, Encoder, Timing Generator are programmed and enabled. + * New targets are enabled with blank stream; no memory read. + */ +bool dc_commit_targets( + struct dc *dc, + struct dc_target *targets[], + uint8_t target_count); + +/******************************************************************************* + * Stream Interfaces + ******************************************************************************/ +struct dc_stream { + const struct dc_sink *sink; + struct dc_crtc_timing timing; + + enum dc_color_space output_color_space; + + struct rect src; /* viewport in target space*/ + struct rect dst; /* stream addressable area */ + + struct audio_info audio_info; + + bool ignore_msa_timing_param; + + struct freesync_context freesync_ctx; + + /* TODO: dithering */ + /* TODO: transfer function (CSC/regamma/gamut remap) */ + struct colorspace_transform gamut_remap_matrix; + struct csc_transform csc_color_matrix; + /* TODO: custom INFO packets */ + /* TODO: ABM info (DMCU) */ + /* TODO: PSR info */ + /* TODO: CEA VIC */ +}; + +/** + * Create a new default stream for the requested sink + */ +struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink); + +void dc_stream_retain(const struct dc_stream *dc_stream); +void dc_stream_release(const struct dc_stream *dc_stream); + +struct dc_stream_status { + /* + * link this stream passes through + */ + const struct dc_link *link; +}; + +const struct dc_stream_status *dc_stream_get_status( + const struct dc_stream *dc_stream); + +/******************************************************************************* + * Link Interfaces + ******************************************************************************/ + +/* + * A link contains one or more sinks and their connected status. + * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. + */ +struct dc_link { + const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; + unsigned int sink_count; + const struct dc_sink *local_sink; + unsigned int link_index; + enum dc_connection_type type; + enum signal_type connector_signal; + enum dc_irq_source irq_source_hpd; + enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */ + /* caps is the same as reported_link_cap. link_traing use + * reported_link_cap. Will clean up. TODO + */ + struct dc_link_settings reported_link_cap; + struct dc_link_settings verified_link_cap; + struct dc_link_settings max_link_setting; + struct dc_link_settings cur_link_settings; + struct dc_lane_settings cur_lane_setting; + + uint8_t ddc_hw_inst; + uint8_t link_enc_hw_inst; + + struct psr_caps psr_caps; + bool test_pattern_enabled; + union compliance_test_state compliance_test_state; +}; + +struct dpcd_caps { + union dpcd_rev dpcd_rev; + union max_lane_count max_ln_count; + union max_down_spread max_down_spread; + + /* dongle type (DP converter, CV smart dongle) */ + enum display_dongle_type dongle_type; + /* Dongle's downstream count. */ + union sink_count sink_count; + /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, + indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ + bool is_dp_hdmi_s3d_converter; + + bool allow_invalid_MSA_timing_param; + bool panel_mode_edp; + uint32_t sink_dev_id; + uint32_t branch_dev_id; + int8_t branch_dev_name[6]; + int8_t branch_hw_revision; +}; + +struct dc_link_status { + struct dpcd_caps *dpcd_caps; +}; + +const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); + +/* + * Return an enumerated dc_link. dc_link order is constant and determined at + * boot time. They cannot be created or destroyed. + * Use dc_get_caps() to get number of links. + */ +const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); + +/* Return id of physical connector represented by a dc_link at link_index.*/ +const struct graphics_object_id dc_get_link_id_at_index( + struct dc *dc, uint32_t link_index); + +/* Set backlight level of an embedded panel (eDP, LVDS). */ +bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, + uint32_t frame_ramp, const struct dc_stream *stream); + +bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link); + +bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level); + +bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); + +bool dc_link_setup_psr(const struct dc_link *dc_link, + const struct dc_stream *stream); + +/* Request DC to detect if there is a Panel connected. + * boot - If this call is during initial boot. + * Return false for any type of detection failure or MST detection + * true otherwise. True meaning further action is required (status update + * and OS notification). + */ +bool dc_link_detect(const struct dc_link *dc_link, bool boot); + +/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). + * Return: + * true - Downstream port status changed. DM should call DC to do the + * detection. + * false - no change in Downstream port status. No further action required + * from DM. */ +bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link); + +struct dc_sink_init_data; + +struct dc_sink *dc_link_add_remote_sink( + const struct dc_link *dc_link, + const uint8_t *edid, + int len, + struct dc_sink_init_data *init_data); + +void dc_link_remove_remote_sink( + const struct dc_link *link, + const struct dc_sink *sink); + +/* Used by diagnostics for virtual link at the moment */ +void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink); + +void dc_link_dp_set_drive_settings( + struct dc_link *link, + struct link_training_settings *lt_settings); + +bool dc_link_dp_perform_link_training( + struct dc_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern); + +void dc_link_dp_enable_hpd(const struct dc_link *link); + +void dc_link_dp_disable_hpd(const struct dc_link *link); + +bool dc_link_dp_set_test_pattern( + const struct dc_link *link, + enum dp_test_pattern test_pattern, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size); + +/******************************************************************************* + * Sink Interfaces - A sink corresponds to a display output device + ******************************************************************************/ + +/* + * The sink structure contains EDID and other display device properties + */ +struct dc_sink { + enum signal_type sink_signal; + struct dc_edid dc_edid; /* raw edid */ + struct dc_edid_caps edid_caps; /* parse display caps */ +}; + +void dc_sink_retain(const struct dc_sink *sink); +void dc_sink_release(const struct dc_sink *sink); + +const struct audio **dc_get_audios(struct dc *dc); + +struct dc_sink_init_data { + enum signal_type sink_signal; + const struct dc_link *link; + uint32_t dongle_max_pix_clk; + bool converter_disable_audio; +}; + +struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); + +/******************************************************************************* + * Cursor interfaces - To manages the cursor within a target + ******************************************************************************/ +/* TODO: Deprecated once we switch to dc_set_cursor_position */ +bool dc_target_set_cursor_attributes( + struct dc_target *dc_target, + const struct dc_cursor_attributes *attributes); + +bool dc_target_set_cursor_position( + struct dc_target *dc_target, + const struct dc_cursor_position *position); + +/* Newer interfaces */ +struct dc_cursor { + struct dc_plane_address address; + struct dc_cursor_attributes attributes; +}; + +/* + * Create a new cursor with default values for a given target. + */ +struct dc_cursor *dc_create_cursor_for_target( + const struct dc *dc, + struct dc_target *dc_target); + +/** + * Commit cursor attribute changes such as pixel format and dimensions and + * surface address. + * + * After this call: + * Cursor address and format is programmed to the new values. + * Cursor position is unmodified. + */ +bool dc_commit_cursor( + const struct dc *dc, + struct dc_cursor *cursor); + +/* + * Optimized cursor position update + * + * After this call: + * Cursor position will be programmed as well as enable/disable bit. + */ +bool dc_set_cursor_position( + const struct dc *dc, + struct dc_cursor *cursor, + struct dc_cursor_position *pos); + +/******************************************************************************* + * Interrupt interfaces + ******************************************************************************/ +enum dc_irq_source dc_interrupt_to_irq_source( + struct dc *dc, + uint32_t src_id, + uint32_t ext_id); +void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable); +void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src); +enum dc_irq_source dc_get_hpd_irq_source_at_index( + struct dc *dc, uint32_t link_index); + +/******************************************************************************* + * Power Interfaces + ******************************************************************************/ + +void dc_set_power_state( + struct dc *dc, + enum dc_acpi_cm_power_state power_state, + enum dc_video_power_state video_power_state); +void dc_resume(const struct dc *dc); + +/******************************************************************************* + * DDC Interfaces + ******************************************************************************/ + +const struct ddc_service *dc_get_ddc_at_index( + struct dc *dc, uint32_t link_index); + +/* + * DPCD access interfaces + */ + +bool dc_read_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *data, + uint32_t size); + +bool dc_write_dpcd( + struct dc *dc, + uint32_t link_index, + uint32_t address, + const uint8_t *data, + uint32_t size); + +bool dc_submit_i2c( + struct dc *dc, + uint32_t link_index, + struct i2c_command *cmd); + +#endif /* DC_INTERFACE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h new file mode 100644 index 000000000000..790c5bd51cb9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -0,0 +1,224 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_BIOS_TYPES_H +#define DC_BIOS_TYPES_H + +/****************************************************************************** + * Interface file for VBIOS implementations. + * + * The default implementation is inside DC. + * Display Manager (which instantiates DC) has the option to supply it's own + * (external to DC) implementation of VBIOS, which will be called by DC, using + * this interface. + * (The intended use is Diagnostics, but other uses may appear.) + *****************************************************************************/ + +#include "include/bios_parser_types.h" + +struct dc_vbios_funcs { + uint8_t (*get_connectors_number)(struct dc_bios *bios); + + struct graphics_object_id (*get_encoder_id)( + struct dc_bios *bios, + uint32_t i); + struct graphics_object_id (*get_connector_id)( + struct dc_bios *bios, + uint8_t connector_index); + uint32_t (*get_dst_number)( + struct dc_bios *bios, + struct graphics_object_id id); + + uint32_t (*get_gpio_record)( + struct dc_bios *dcb, + struct graphics_object_id id, + struct bp_gpio_cntl_info *gpio_record, + uint32_t record_size); + + enum bp_result (*get_src_obj)( + struct dc_bios *bios, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *src_object_id); + enum bp_result (*get_dst_obj)( + struct dc_bios *bios, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *dest_object_id); + + enum bp_result (*get_i2c_info)( + struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_i2c_info *info); + + enum bp_result (*get_voltage_ddc_info)( + struct dc_bios *bios, + uint32_t index, + struct graphics_object_i2c_info *info); + enum bp_result (*get_thermal_ddc_info)( + struct dc_bios *bios, + uint32_t i2c_channel_id, + struct graphics_object_i2c_info *info); + enum bp_result (*get_hpd_info)( + struct dc_bios *bios, + struct graphics_object_id id, + struct graphics_object_hpd_info *info); + enum bp_result (*get_device_tag)( + struct dc_bios *bios, + struct graphics_object_id connector_object_id, + uint32_t device_tag_index, + struct connector_device_tag_info *info); + enum bp_result (*get_firmware_info)( + struct dc_bios *bios, + struct firmware_info *info); + enum bp_result (*get_spread_spectrum_info)( + struct dc_bios *bios, + enum as_signal_type signal, + uint32_t index, + struct spread_spectrum_info *ss_info); + uint32_t (*get_ss_entry_number)( + struct dc_bios *bios, + enum as_signal_type signal); + enum bp_result (*get_embedded_panel_info)( + struct dc_bios *bios, + struct embedded_panel_info *info); + enum bp_result (*get_gpio_pin_info)( + struct dc_bios *bios, + uint32_t gpio_id, + struct gpio_pin_info *info); + enum bp_result (*get_encoder_cap_info)( + struct dc_bios *bios, + struct graphics_object_id object_id, + struct bp_encoder_cap_info *info); + + bool (*is_lid_status_changed)( + struct dc_bios *bios); + bool (*is_display_config_changed)( + struct dc_bios *bios); + bool (*is_accelerated_mode)( + struct dc_bios *bios); + void (*get_bios_event_info)( + struct dc_bios *bios, + struct bios_event_info *info); + void (*update_requested_backlight_level)( + struct dc_bios *bios, + uint32_t backlight_8bit); + uint32_t (*get_requested_backlight_level)( + struct dc_bios *bios); + void (*take_backlight_control)( + struct dc_bios *bios, + bool cntl); + + bool (*is_active_display)( + struct dc_bios *bios, + enum signal_type signal, + const struct connector_device_tag_info *device_tag); + enum controller_id (*get_embedded_display_controller_id)( + struct dc_bios *bios); + uint32_t (*get_embedded_display_refresh_rate)( + struct dc_bios *bios); + + void (*set_scratch_critical_state)( + struct dc_bios *bios, + bool state); + bool (*is_device_id_supported)( + struct dc_bios *bios, + struct device_id id); + + /* COMMANDS */ + + enum bp_result (*encoder_control)( + struct dc_bios *bios, + struct bp_encoder_control *cntl); + enum bp_result (*transmitter_control)( + struct dc_bios *bios, + struct bp_transmitter_control *cntl); + enum bp_result (*crt_control)( + struct dc_bios *bios, + enum engine_id engine_id, + bool enable, + uint32_t pixel_clock); + enum bp_result (*enable_crtc)( + struct dc_bios *bios, + enum controller_id id, + bool enable); + enum bp_result (*adjust_pixel_clock)( + struct dc_bios *bios, + struct bp_adjust_pixel_clock_parameters *bp_params); + enum bp_result (*set_pixel_clock)( + struct dc_bios *bios, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*set_dce_clock)( + struct dc_bios *bios, + struct bp_set_dce_clock_parameters *bp_params); + unsigned int (*get_smu_clock_info)( + struct dc_bios *bios); + enum bp_result (*enable_spread_spectrum_on_ppll)( + struct dc_bios *bios, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); + enum bp_result (*program_crtc_timing)( + struct dc_bios *bios, + struct bp_hw_crtc_timing_parameters *bp_params); + + enum bp_result (*crtc_source_select)( + struct dc_bios *bios, + struct bp_crtc_source_select *bp_params); + enum bp_result (*program_display_engine_pll)( + struct dc_bios *bios, + struct bp_pixel_clock_parameters *bp_params); + + enum signal_type (*dac_load_detect)( + struct dc_bios *bios, + struct graphics_object_id encoder, + struct graphics_object_id connector, + enum signal_type display_signal); + + enum bp_result (*enable_disp_power_gating)( + struct dc_bios *bios, + enum controller_id controller_id, + enum bp_pipe_control_action action); + + void (*post_init)(struct dc_bios *bios); + + void (*bios_parser_destroy)(struct dc_bios **dcb); +}; + +struct bios_registers { + uint32_t BIOS_SCRATCH_6; +}; + +struct dc_bios { + const struct dc_vbios_funcs *funcs; + + uint8_t *bios; + uint32_t bios_size; + + uint8_t *bios_local_image; + + struct dc_context *ctx; + const struct bios_registers *regs; + struct integrated_info *integrated_info; +}; + +#endif /* DC_BIOS_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h new file mode 100644 index 000000000000..b143fe88f49f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h @@ -0,0 +1,115 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef DC_DDC_TYPES_H_ +#define DC_DDC_TYPES_H_ + +struct i2c_payload { + bool write; + uint8_t address; + uint32_t length; + uint8_t *data; +}; + +enum i2c_command_engine { + I2C_COMMAND_ENGINE_DEFAULT, + I2C_COMMAND_ENGINE_SW, + I2C_COMMAND_ENGINE_HW +}; + +struct i2c_command { + struct i2c_payload *payloads; + uint8_t number_of_payloads; + + enum i2c_command_engine engine; + + /* expressed in KHz + * zero means "use default value" */ + uint32_t speed; +}; + +struct gpio_ddc_hw_info { + bool hw_supported; + uint32_t ddc_channel; +}; + +struct ddc { + struct gpio *pin_data; + struct gpio *pin_clock; + struct gpio_ddc_hw_info hw_info; + struct dc_context *ctx; +}; + +union ddc_wa { + struct { + uint32_t DP_SKIP_POWER_OFF:1; + uint32_t DP_AUX_POWER_UP_WA_DELAY:1; + } bits; + uint32_t raw; +}; + +struct ddc_flags { + uint8_t EDID_QUERY_DONE_ONCE:1; + uint8_t IS_INTERNAL_DISPLAY:1; + uint8_t FORCE_READ_REPEATED_START:1; + uint8_t EDID_STRESS_READ:1; + +}; + +enum ddc_transaction_type { + DDC_TRANSACTION_TYPE_NONE = 0, + DDC_TRANSACTION_TYPE_I2C, + DDC_TRANSACTION_TYPE_I2C_OVER_AUX, + DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER, + DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER +}; + +enum display_dongle_type { + DISPLAY_DONGLE_NONE = 0, + /* Active converter types*/ + DISPLAY_DONGLE_DP_VGA_CONVERTER, + DISPLAY_DONGLE_DP_DVI_CONVERTER, + DISPLAY_DONGLE_DP_HDMI_CONVERTER, + /* DP-HDMI/DVI passive dongles (Type 1 and Type 2)*/ + DISPLAY_DONGLE_DP_DVI_DONGLE, + DISPLAY_DONGLE_DP_HDMI_DONGLE, + /* Other types of dongle*/ + DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE, +}; + +struct ddc_service { + struct ddc *ddc_pin; + struct ddc_flags flags; + union ddc_wa wa; + enum ddc_transaction_type transaction_type; + enum display_dongle_type dongle_type; + struct dc_context *ctx; + struct core_link *link; + + uint32_t address; + uint32_t edid_buf_len; + uint8_t edid_buf[MAX_EDID_BUFFER_SIZE]; +}; + +#endif /* DC_DDC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h new file mode 100644 index 000000000000..befc4985fe54 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -0,0 +1,105 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_DP_TYPES_H +#define DC_DP_TYPES_H + +enum dc_lane_count { + LANE_COUNT_UNKNOWN = 0, + LANE_COUNT_ONE = 1, + LANE_COUNT_TWO = 2, + LANE_COUNT_FOUR = 4, + LANE_COUNT_EIGHT = 8, + LANE_COUNT_DP_MAX = LANE_COUNT_FOUR +}; + +/* This is actually a reference clock (27MHz) multiplier + * 162MBps bandwidth for 1.62GHz like rate, + * 270MBps for 2.70GHz, + * 324MBps for 3.24Ghz, + * 540MBps for 5.40GHz + * 810MBps for 8.10GHz + */ +enum dc_link_rate { + LINK_RATE_UNKNOWN = 0, + LINK_RATE_LOW = 0x06, + LINK_RATE_HIGH = 0x0A, + LINK_RATE_RBR2 = 0x0C, + LINK_RATE_HIGH2 = 0x14, + LINK_RATE_HIGH3 = 0x1E +}; + +enum dc_link_spread { + LINK_SPREAD_DISABLED = 0x00, + /* 0.5 % downspread 30 kHz */ + LINK_SPREAD_05_DOWNSPREAD_30KHZ = 0x10, + /* 0.5 % downspread 33 kHz */ + LINK_SPREAD_05_DOWNSPREAD_33KHZ = 0x11 +}; + +enum dc_voltage_swing { + VOLTAGE_SWING_LEVEL0 = 0, /* direct HW translation! */ + VOLTAGE_SWING_LEVEL1, + VOLTAGE_SWING_LEVEL2, + VOLTAGE_SWING_LEVEL3, + VOLTAGE_SWING_MAX_LEVEL = VOLTAGE_SWING_LEVEL3 +}; + +enum dc_pre_emphasis { + PRE_EMPHASIS_DISABLED = 0, /* direct HW translation! */ + PRE_EMPHASIS_LEVEL1, + PRE_EMPHASIS_LEVEL2, + PRE_EMPHASIS_LEVEL3, + PRE_EMPHASIS_MAX_LEVEL = PRE_EMPHASIS_LEVEL3 +}; +/* Post Cursor 2 is optional for transmitter + * and it applies only to the main link operating at HBR2 + */ +enum dc_post_cursor2 { + POST_CURSOR2_DISABLED = 0, /* direct HW translation! */ + POST_CURSOR2_LEVEL1, + POST_CURSOR2_LEVEL2, + POST_CURSOR2_LEVEL3, + POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3, +}; + +struct dc_link_settings { + enum dc_lane_count lane_count; + enum dc_link_rate link_rate; + enum dc_link_spread link_spread; +}; + +struct dc_lane_settings { + enum dc_voltage_swing VOLTAGE_SWING; + enum dc_pre_emphasis PRE_EMPHASIS; + enum dc_post_cursor2 POST_CURSOR2; +}; + +struct dc_link_training_settings { + struct dc_link_settings link; + struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]; +}; + +#endif /* DC_DP_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c new file mode 100644 index 000000000000..3a80b0c08ae4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -0,0 +1,144 @@ +/* + * dc_helper.c + * + * Created on: Aug 30, 2016 + * Author: agrodzov + */ +#include "dm_services.h" +#include + +uint32_t generic_reg_update_ex(const struct dc_context *ctx, + uint32_t addr, uint32_t reg_val, int n, + uint8_t shift1, uint32_t mask1, uint32_t field_value1, + ...) +{ + uint32_t shift, mask, field_value; + int i = 1; + + va_list ap; + va_start(ap, field_value1); + + reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1); + + while (i < n) { + shift = va_arg(ap, uint32_t); + mask = va_arg(ap, uint32_t); + field_value = va_arg(ap, uint32_t); + + reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift); + i++; + } + + dm_write_reg(ctx, addr, reg_val); + va_end(ap); + + return reg_val; +} + +uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr, + uint8_t shift, uint32_t mask, uint32_t *field_value) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value = get_reg_field_value_ex(reg_val, mask, shift); + return reg_val; +} + +uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); + *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); + return reg_val; +} + +uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); + *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); + *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); + return reg_val; +} + +uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3, + uint8_t shift4, uint32_t mask4, uint32_t *field_value4, + uint8_t shift5, uint32_t mask5, uint32_t *field_value5) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); + *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); + *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); + *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); + *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5); + return reg_val; +} + +/* note: va version of this is pretty bad idea, since there is a output parameter pass by pointer + * compiler won't be able to check for size match and is prone to stack corruption type of bugs + +uint32_t generic_reg_get(const struct dc_context *ctx, + uint32_t addr, int n, ...) +{ + uint32_t shift, mask; + uint32_t *field_value; + uint32_t reg_val; + int i = 0; + + reg_val = dm_read_reg(ctx, addr); + + va_list ap; + va_start(ap, n); + + while (i < n) { + shift = va_arg(ap, uint32_t); + mask = va_arg(ap, uint32_t); + field_value = va_arg(ap, uint32_t *); + + *field_value = get_reg_field_value_ex(reg_val, mask, shift); + i++; + } + + va_end(ap); + + return reg_val; +} +*/ + +uint32_t generic_reg_wait(const struct dc_context *ctx, + uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value, + unsigned int delay_between_poll_us, unsigned int time_out_num_tries, + const char *func_name) +{ + uint32_t field_value; + uint32_t reg_val; + int i; + + for (i = 0; i <= time_out_num_tries; i++) { + if (i) { + if (0 < delay_between_poll_us && delay_between_poll_us < 1000) + udelay(delay_between_poll_us); + + if (delay_between_poll_us > 1000) + msleep(delay_between_poll_us/1000); + } + + reg_val = dm_read_reg(ctx, addr); + + field_value = get_reg_field_value_ex(reg_val, mask, shift); + + if (field_value == condition_value) + return reg_val; + } + + DC_ERR("REG_WAIT timeout %dus * %d tries - %s", + delay_between_poll_us, time_out_num_tries, func_name); + return reg_val; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h new file mode 100644 index 000000000000..5605a5c96da7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -0,0 +1,588 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_HW_TYPES_H +#define DC_HW_TYPES_H + +#include "os_types.h" + +/****************************************************************************** + * Data types for Virtual HW Layer of DAL3. + * (see DAL3 design documents for HW Layer definition) + * + * The intended uses are: + * 1. Generation pseudocode sequences for HW programming. + * 2. Implementation of real HW programming by HW Sequencer of DAL3. + * + * Note: do *not* add any types which are *not* used for HW programming - this + * will ensure separation of Logic layer from HW layer. + ******************************************************************************/ + +union large_integer { + struct { + uint32_t low_part; + int32_t high_part; + }; + + struct { + uint32_t low_part; + int32_t high_part; + } u; + + int64_t quad_part; +}; + +#define PHYSICAL_ADDRESS_LOC union large_integer + +enum dc_plane_addr_type { + PLN_ADDR_TYPE_GRAPHICS = 0, + PLN_ADDR_TYPE_GRPH_STEREO, + PLN_ADDR_TYPE_VIDEO_PROGRESSIVE, +}; + +struct dc_plane_address { + enum dc_plane_addr_type type; + union { + struct{ + PHYSICAL_ADDRESS_LOC addr; + PHYSICAL_ADDRESS_LOC meta_addr; + union large_integer dcc_const_color; + } grph; + + /*stereo*/ + struct { + PHYSICAL_ADDRESS_LOC left_addr; + PHYSICAL_ADDRESS_LOC left_meta_addr; + union large_integer left_dcc_const_color; + + PHYSICAL_ADDRESS_LOC right_addr; + PHYSICAL_ADDRESS_LOC right_meta_addr; + union large_integer right_dcc_const_color; + + } grph_stereo; + + /*video progressive*/ + struct { + PHYSICAL_ADDRESS_LOC luma_addr; + PHYSICAL_ADDRESS_LOC luma_meta_addr; + union large_integer luma_dcc_const_color; + + PHYSICAL_ADDRESS_LOC chroma_addr; + PHYSICAL_ADDRESS_LOC chroma_meta_addr; + union large_integer chroma_dcc_const_color; + } video_progressive; + }; +}; + +struct dc_size { + uint32_t width; + uint32_t height; +}; + +struct rect { + int x; + int y; + uint32_t width; + uint32_t height; +}; + +union plane_size { + /* Grph or Video will be selected + * based on format above: + * Use Video structure if + * format >= DalPixelFormat_VideoBegin + * else use Grph structure + */ + struct { + struct rect surface_size; + /* Graphic surface pitch in pixels. + * In LINEAR_GENERAL mode, pitch + * is 32 pixel aligned. + */ + uint32_t surface_pitch; + + uint32_t meta_pitch; + } grph; + + struct { + struct rect luma_size; + /* Graphic surface pitch in pixels. + * In LINEAR_GENERAL mode, pitch is + * 32 pixel aligned. + */ + uint32_t luma_pitch; + uint32_t meta_luma_pitch; + + struct rect chroma_size; + /* Graphic surface pitch in pixels. + * In LINEAR_GENERAL mode, pitch is + * 32 pixel aligned. + */ + uint32_t chroma_pitch; + uint32_t meta_chroma_pitch; + } video; +}; + +struct dc_plane_dcc_param { + bool enable; + + union { + struct { + uint32_t meta_pitch; + bool independent_64b_blks; + } grph; + + struct { + uint32_t meta_pitch_l; + bool independent_64b_blks_l; + + uint32_t meta_pitch_c; + bool independent_64b_blks_c; + } video; + }; +}; + +/*Displayable pixel format in fb*/ +enum surface_pixel_format { + SURFACE_PIXEL_FORMAT_GRPH_BEGIN = 0, + /*TOBE REMOVED paletta 256 colors*/ + SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS = + SURFACE_PIXEL_FORMAT_GRPH_BEGIN, + /*16 bpp*/ + SURFACE_PIXEL_FORMAT_GRPH_ARGB1555, + /*16 bpp*/ + SURFACE_PIXEL_FORMAT_GRPH_RGB565, + /*32 bpp*/ + SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, + /*32 bpp swaped*/ + SURFACE_PIXEL_FORMAT_GRPH_BGRA8888, + + SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010, + /*swaped*/ + SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010, + /*TOBE REMOVED swaped, XR_BIAS has no differance + * for pixel layout than previous and we can + * delete this after discusion*/ + SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS, + /*64 bpp */ + SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616, + /*float*/ + SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F, + /*swaped & float*/ + SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F, + /*grow graphics here if necessary */ + + SURFACE_PIXEL_FORMAT_VIDEO_BEGIN, + SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr = + SURFACE_PIXEL_FORMAT_VIDEO_BEGIN, + SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb, + SURFACE_PIXEL_FORMAT_INVALID + + /*grow 444 video here if necessary */ +}; + +/* Pixel format */ +enum pixel_format { + /*graph*/ + PIXEL_FORMAT_UNINITIALIZED, + PIXEL_FORMAT_INDEX8, + PIXEL_FORMAT_RGB565, + PIXEL_FORMAT_ARGB8888, + PIXEL_FORMAT_ARGB2101010, + PIXEL_FORMAT_ARGB2101010_XRBIAS, + PIXEL_FORMAT_FP16, + /*video*/ + PIXEL_FORMAT_420BPP12, + /*end of pixel format definition*/ + PIXEL_FORMAT_INVALID, + + PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8, + PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16, + PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12, + PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP12, + PIXEL_FORMAT_UNKNOWN +}; + +enum tile_split_values { + DC_DISPLAY_MICRO_TILING = 0x0, + DC_THIN_MICRO_TILING = 0x1, + DC_DEPTH_MICRO_TILING = 0x2, + DC_ROTATED_MICRO_TILING = 0x3, +}; + +/* TODO: These values come from hardware spec. We need to readdress this + * if they ever change. + */ +enum array_mode_values { + DC_ARRAY_LINEAR_GENERAL = 0, + DC_ARRAY_LINEAR_ALLIGNED, + DC_ARRAY_1D_TILED_THIN1, + DC_ARRAY_1D_TILED_THICK, + DC_ARRAY_2D_TILED_THIN1, + DC_ARRAY_PRT_TILED_THIN1, + DC_ARRAY_PRT_2D_TILED_THIN1, + DC_ARRAY_2D_TILED_THICK, + DC_ARRAY_2D_TILED_X_THICK, + DC_ARRAY_PRT_TILED_THICK, + DC_ARRAY_PRT_2D_TILED_THICK, + DC_ARRAY_PRT_3D_TILED_THIN1, + DC_ARRAY_3D_TILED_THIN1, + DC_ARRAY_3D_TILED_THICK, + DC_ARRAY_3D_TILED_X_THICK, + DC_ARRAY_PRT_3D_TILED_THICK, +}; + +enum tile_mode_values { + DC_ADDR_SURF_MICRO_TILING_DISPLAY = 0x0, + DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1, +}; + +union dc_tiling_info { + + struct { + /* Specifies the number of memory banks for tiling + * purposes. + * Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: 2,4,8,16 + */ + unsigned int num_banks; + /* Specifies the number of tiles in the x direction + * to be incorporated into the same bank. + * Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: 1,2,4,8 + */ + unsigned int bank_width; + unsigned int bank_width_c; + /* Specifies the number of tiles in the y direction to + * be incorporated into the same bank. + * Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: 1,2,4,8 + */ + unsigned int bank_height; + unsigned int bank_height_c; + /* Specifies the macro tile aspect ratio. Only applies + * to 2D and 3D tiling modes. + */ + unsigned int tile_aspect; + unsigned int tile_aspect_c; + /* Specifies the number of bytes that will be stored + * contiguously for each tile. + * If the tile data requires more storage than this + * amount, it is split into multiple slices. + * This field must not be larger than + * GB_ADDR_CONFIG.DRAM_ROW_SIZE. + * Only applies to 2D and 3D tiling modes. + * For color render targets, TILE_SPLIT >= 256B. + */ + enum tile_split_values tile_split; + enum tile_split_values tile_split_c; + /* Specifies the addressing within a tile. + * 0x0 - DISPLAY_MICRO_TILING + * 0x1 - THIN_MICRO_TILING + * 0x2 - DEPTH_MICRO_TILING + * 0x3 - ROTATED_MICRO_TILING + */ + enum tile_mode_values tile_mode; + enum tile_mode_values tile_mode_c; + /* Specifies the number of pipes and how they are + * interleaved in the surface. + * Refer to memory addressing document for complete + * details and constraints. + */ + unsigned int pipe_config; + /* Specifies the tiling mode of the surface. + * THIN tiles use an 8x8x1 tile size. + * THICK tiles use an 8x8x4 tile size. + * 2D tiling modes rotate banks for successive Z slices + * 3D tiling modes rotate pipes and banks for Z slices + * Refer to memory addressing document for complete + * details and constraints. + */ + enum array_mode_values array_mode; + } gfx8; + +}; + +/* Rotation angle */ +enum dc_rotation_angle { + ROTATION_ANGLE_0 = 0, + ROTATION_ANGLE_90, + ROTATION_ANGLE_180, + ROTATION_ANGLE_270, + ROTATION_ANGLE_COUNT +}; + +enum dc_scan_direction { + SCAN_DIRECTION_UNKNOWN = 0, + SCAN_DIRECTION_HORIZONTAL = 1, /* 0, 180 rotation */ + SCAN_DIRECTION_VERTICAL = 2, /* 90, 270 rotation */ +}; + +struct dc_cursor_position { + uint32_t x; + uint32_t y; + + uint32_t x_hotspot; + uint32_t y_hotspot; + + /* + * This parameter indicates whether HW cursor should be enabled + */ + bool enable; + + /* + * This parameter indicates whether cursor hot spot should be + * programmed + */ + bool hot_spot_enable; +}; + +/* IPP related types */ + +/* Used by both ipp amd opp functions*/ +/* TODO: to be consolidated with enum color_space */ + +/* + * This enum is for programming CURSOR_MODE register field. What this register + * should be programmed to depends on OS requested cursor shape flags and what + * we stored in the cursor surface. + */ +enum dc_cursor_color_format { + CURSOR_MODE_MONO, + CURSOR_MODE_COLOR_1BIT_AND, + CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA, + CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA +}; + +/* + * This is all the parameters required by DAL in order to update the cursor + * attributes, including the new cursor image surface address, size, hotspot + * location, color format, etc. + */ + +union dc_cursor_attribute_flags { + struct { + uint32_t ENABLE_MAGNIFICATION:1; + uint32_t INVERSE_TRANSPARENT_CLAMPING:1; + uint32_t HORIZONTAL_MIRROR:1; + uint32_t VERTICAL_MIRROR:1; + uint32_t INVERT_PIXEL_DATA:1; + uint32_t ZERO_EXPANSION:1; + uint32_t MIN_MAX_INVERT:1; + uint32_t RESERVED:25; + } bits; + uint32_t value; +}; + +struct dc_cursor_attributes { + PHYSICAL_ADDRESS_LOC address; + + /* Width and height should correspond to cursor surface width x heigh */ + uint32_t width; + uint32_t height; + uint32_t x_hot; + uint32_t y_hot; + + enum dc_cursor_color_format color_format; + + /* In case we support HW Cursor rotation in the future */ + enum dc_rotation_angle rotation_angle; + + union dc_cursor_attribute_flags attribute_flags; +}; + +/* OPP */ + +enum dc_color_space { + COLOR_SPACE_UNKNOWN, + COLOR_SPACE_SRGB, + COLOR_SPACE_SRGB_LIMITED, + COLOR_SPACE_YPBPR601, + COLOR_SPACE_YPBPR709, + COLOR_SPACE_YCBCR601, + COLOR_SPACE_YCBCR709, + COLOR_SPACE_YCBCR601_LIMITED, + COLOR_SPACE_YCBCR709_LIMITED +}; + +enum dc_quantization_range { + QUANTIZATION_RANGE_UNKNOWN, + QUANTIZATION_RANGE_FULL, + QUANTIZATION_RANGE_LIMITED +}; + +/* XFM */ + +/* used in struct dc_surface */ +struct scaling_taps { + uint32_t v_taps; + uint32_t h_taps; + uint32_t v_taps_c; + uint32_t h_taps_c; +}; + +enum dc_timing_standard { + TIMING_STANDARD_UNDEFINED, + TIMING_STANDARD_DMT, + TIMING_STANDARD_GTF, + TIMING_STANDARD_CVT, + TIMING_STANDARD_CVT_RB, + TIMING_STANDARD_CEA770, + TIMING_STANDARD_CEA861, + TIMING_STANDARD_HDMI, + TIMING_STANDARD_TV_NTSC, + TIMING_STANDARD_TV_NTSC_J, + TIMING_STANDARD_TV_PAL, + TIMING_STANDARD_TV_PAL_M, + TIMING_STANDARD_TV_PAL_CN, + TIMING_STANDARD_TV_SECAM, + TIMING_STANDARD_EXPLICIT, + /*!< For explicit timings from EDID, VBIOS, etc.*/ + TIMING_STANDARD_USER_OVERRIDE, + /*!< For mode timing override by user*/ + TIMING_STANDARD_MAX +}; + +enum dc_timing_3d_format { + TIMING_3D_FORMAT_NONE, + TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/ + TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/ + TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/ + /* for active DP-HDMI dongle*/ + TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/ + TIMING_3D_FORMAT_HW_FRAME_PACKING, + TIMING_3D_FORMAT_SW_FRAME_PACKING, + TIMING_3D_FORMAT_ROW_INTERLEAVE, + TIMING_3D_FORMAT_COLUMN_INTERLEAVE, + TIMING_3D_FORMAT_PIXEL_INTERLEAVE, + TIMING_3D_FORMAT_SIDE_BY_SIDE, + TIMING_3D_FORMAT_TOP_AND_BOTTOM, + TIMING_3D_FORMAT_SBS_SW_PACKED, + /* Side-by-side, packed by application/driver into 2D frame*/ + TIMING_3D_FORMAT_TB_SW_PACKED, + /* Top-and-bottom, packed by application/driver into 2D frame*/ + + TIMING_3D_FORMAT_MAX, +}; + +enum dc_color_depth { + COLOR_DEPTH_UNDEFINED, + COLOR_DEPTH_666, + COLOR_DEPTH_888, + COLOR_DEPTH_101010, + COLOR_DEPTH_121212, + COLOR_DEPTH_141414, + COLOR_DEPTH_161616, + COLOR_DEPTH_COUNT +}; + +enum dc_pixel_encoding { + PIXEL_ENCODING_UNDEFINED, + PIXEL_ENCODING_RGB, + PIXEL_ENCODING_YCBCR422, + PIXEL_ENCODING_YCBCR444, + PIXEL_ENCODING_YCBCR420, + PIXEL_ENCODING_COUNT +}; + +enum dc_aspect_ratio { + ASPECT_RATIO_NO_DATA, + ASPECT_RATIO_4_3, + ASPECT_RATIO_16_9, + ASPECT_RATIO_64_27, + ASPECT_RATIO_256_135, + ASPECT_RATIO_FUTURE +}; + +enum scanning_type { + SCANNING_TYPE_NODATA = 0, + SCANNING_TYPE_OVERSCAN, + SCANNING_TYPE_UNDERSCAN, + SCANNING_TYPE_FUTURE, + SCANNING_TYPE_UNDEFINED +}; + +struct dc_crtc_timing_flags { + uint32_t INTERLACE :1; + uint32_t HSYNC_POSITIVE_POLARITY :1; /* when set to 1, + it is positive polarity --reversed with dal1 or video bios define*/ + uint32_t VSYNC_POSITIVE_POLARITY :1; /* when set to 1, + it is positive polarity --reversed with dal1 or video bios define*/ + + uint32_t HORZ_COUNT_BY_TWO:1; + + uint32_t EXCLUSIVE_3D :1; /* if this bit set, + timing can be driven in 3D format only + and there is no corresponding 2D timing*/ + uint32_t RIGHT_EYE_3D_POLARITY :1; /* 1 - means right eye polarity + (right eye = '1', left eye = '0') */ + uint32_t SUB_SAMPLE_3D :1; /* 1 - means left/right images subsampled + when mixed into 3D image. 0 - means summation (3D timing is doubled)*/ + uint32_t USE_IN_3D_VIEW_ONLY :1; /* Do not use this timing in 2D View, + because corresponding 2D timing also present in the list*/ + uint32_t STEREO_3D_PREFERENCE :1; /* Means this is 2D timing + and we want to match priority of corresponding 3D timing*/ + uint32_t Y_ONLY :1; + + uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */ + uint32_t DTD_COUNTER :5; /* values 1 to 16 */ + + /* HDMI 2.0 - Support scrambling for TMDS character + * rates less than or equal to 340Mcsc */ + uint32_t LTE_340MCSC_SCRAMBLE:1; + +}; + +struct dc_crtc_timing { + + uint32_t h_total; + uint32_t h_border_left; + uint32_t h_addressable; + uint32_t h_border_right; + uint32_t h_front_porch; + uint32_t h_sync_width; + + uint32_t v_total; + uint32_t v_border_top; + uint32_t v_addressable; + uint32_t v_border_bottom; + uint32_t v_front_porch; + uint32_t v_sync_width; + + uint32_t pix_clk_khz; + + uint32_t vic; + uint32_t hdmi_vic; + enum dc_timing_3d_format timing_3d_format; + enum dc_color_depth display_color_depth; + enum dc_pixel_encoding pixel_encoding; + enum dc_aspect_ratio aspect_ratio; + enum scanning_type scan_type; + + struct dc_crtc_timing_flags flags; +}; + +#endif /* DC_HW_TYPES_H */ + diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h new file mode 100644 index 000000000000..ae9fcca121e6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -0,0 +1,493 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef DC_TYPES_H_ +#define DC_TYPES_H_ + +#include "fixed32_32.h" +#include "fixed31_32.h" +#include "irq_types.h" +#include "dc_dp_types.h" +#include "dc_hw_types.h" +#include "dal_types.h" + +/* forward declarations */ +struct dc_surface; +struct dc_target; +struct dc_stream; +struct dc_link; +struct dc_sink; +struct dal; + +/******************************** + * Environment definitions + ********************************/ +enum dce_environment { + DCE_ENV_PRODUCTION_DRV = 0, + /* Emulation on FPGA, in "Maximus" System. + * This environment enforces that *only* DC registers accessed. + * (access to non-DC registers will hang FPGA) */ + DCE_ENV_FPGA_MAXIMUS, + /* Emulation on real HW or on FPGA. Used by Diagnostics, enforces + * requirements of Diagnostics team. */ + DCE_ENV_DIAG +}; + +/* Note: use these macro definitions instead of direct comparison! */ +#define IS_FPGA_MAXIMUS_DC(dce_environment) \ + (dce_environment == DCE_ENV_FPGA_MAXIMUS) + +#define IS_DIAG_DC(dce_environment) \ + (IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG)) + +struct hw_asic_id { + uint32_t chip_id; + uint32_t chip_family; + uint32_t pci_revision_id; + uint32_t hw_internal_rev; + uint32_t vram_type; + uint32_t vram_width; + uint32_t feature_flags; + uint32_t fake_paths_num; + void *atombios_base_address; +}; + +struct dc_context { + struct dc *dc; + + void *driver_context; /* e.g. amdgpu_device */ + + struct dal_logger *logger; + void *cgs_device; + + enum dce_environment dce_environment; + struct hw_asic_id asic_id; + + /* todo: below should probably move to dc. to facilitate removal + * of AS we will store these here + */ + enum dce_version dce_version; + struct dc_bios *dc_bios; + bool created_bios; + struct gpio_service *gpio_service; + struct i2caux *i2caux; +}; + + +#define MAX_EDID_BUFFER_SIZE 512 +#define EDID_BLOCK_SIZE 128 +#define MAX_SURFACE_NUM 2 +#define NUM_PIXEL_FORMATS 10 + +#include "dc_ddc_types.h" + +enum tiling_mode { + TILING_MODE_INVALID, + TILING_MODE_LINEAR, + TILING_MODE_TILED, + TILING_MODE_COUNT +}; + +enum view_3d_format { + VIEW_3D_FORMAT_NONE = 0, + VIEW_3D_FORMAT_FRAME_SEQUENTIAL, + VIEW_3D_FORMAT_SIDE_BY_SIDE, + VIEW_3D_FORMAT_TOP_AND_BOTTOM, + VIEW_3D_FORMAT_COUNT, + VIEW_3D_FORMAT_FIRST = VIEW_3D_FORMAT_FRAME_SEQUENTIAL +}; + +enum plane_stereo_format { + PLANE_STEREO_FORMAT_NONE = 0, + PLANE_STEREO_FORMAT_SIDE_BY_SIDE = 1, + PLANE_STEREO_FORMAT_TOP_AND_BOTTOM = 2, + PLANE_STEREO_FORMAT_FRAME_ALTERNATE = 3, + PLANE_STEREO_FORMAT_ROW_INTERLEAVED = 5, + PLANE_STEREO_FORMAT_COLUMN_INTERLEAVED = 6, + PLANE_STEREO_FORMAT_CHECKER_BOARD = 7 +}; + +/* TODO: Find way to calculate number of bits + * Please increase if pixel_format enum increases + * num from PIXEL_FORMAT_INDEX8 to PIXEL_FORMAT_444BPP32 + */ + +enum dc_edid_connector_type { + EDID_CONNECTOR_UNKNOWN = 0, + EDID_CONNECTOR_ANALOG = 1, + EDID_CONNECTOR_DIGITAL = 10, + EDID_CONNECTOR_DVI = 11, + EDID_CONNECTOR_HDMIA = 12, + EDID_CONNECTOR_MDDI = 14, + EDID_CONNECTOR_DISPLAYPORT = 15 +}; + +enum dc_edid_status { + EDID_OK, + EDID_BAD_INPUT, + EDID_NO_RESPONSE, + EDID_BAD_CHECKSUM, +}; + +/* audio capability from EDID*/ +struct dc_cea_audio_mode { + uint8_t format_code; /* ucData[0] [6:3]*/ + uint8_t channel_count; /* ucData[0] [2:0]*/ + uint8_t sample_rate; /* ucData[1]*/ + union { + uint8_t sample_size; /* for LPCM*/ + /* for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/ + uint8_t max_bit_rate; + uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/ + }; +}; + +struct dc_edid { + uint32_t length; + uint8_t raw_edid[MAX_EDID_BUFFER_SIZE]; +}; + +/* When speaker location data block is not available, DEFAULT_SPEAKER_LOCATION + * is used. In this case we assume speaker location are: front left, front + * right and front center. */ +#define DEFAULT_SPEAKER_LOCATION 5 + +#define DC_MAX_AUDIO_DESC_COUNT 16 + +#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20 + +struct dc_edid_caps { + /* sink identification */ + uint16_t manufacturer_id; + uint16_t product_id; + uint32_t serial_number; + uint8_t manufacture_week; + uint8_t manufacture_year; + uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS]; + + /* audio caps */ + uint8_t speaker_flags; + uint32_t audio_mode_count; + struct dc_cea_audio_mode audio_modes[DC_MAX_AUDIO_DESC_COUNT]; + uint32_t audio_latency; + uint32_t video_latency; + + /*HDMI 2.0 caps*/ + bool lte_340mcsc_scramble; + + bool edid_hdmi; +}; + +struct view { + uint32_t width; + uint32_t height; +}; + +struct dc_mode_flags { + /* note: part of refresh rate flag*/ + uint32_t INTERLACE :1; + /* native display timing*/ + uint32_t NATIVE :1; + /* preferred is the recommended mode, one per display */ + uint32_t PREFERRED :1; + /* true if this mode should use reduced blanking timings + *_not_ related to the Reduced Blanking adjustment*/ + uint32_t REDUCED_BLANKING :1; + /* note: part of refreshrate flag*/ + uint32_t VIDEO_OPTIMIZED_RATE :1; + /* should be reported to upper layers as mode_flags*/ + uint32_t PACKED_PIXEL_FORMAT :1; + /*< preferred view*/ + uint32_t PREFERRED_VIEW :1; + /* this timing should be used only in tiled mode*/ + uint32_t TILED_MODE :1; + uint32_t DSE_MODE :1; + /* Refresh rate divider when Miracast sink is using a + different rate than the output display device + Must be zero for wired displays and non-zero for + Miracast displays*/ + uint32_t MIRACAST_REFRESH_DIVIDER; +}; + + +enum dc_timing_source { + TIMING_SOURCE_UNDEFINED, + + /* explicitly specifed by user, most important*/ + TIMING_SOURCE_USER_FORCED, + TIMING_SOURCE_USER_OVERRIDE, + TIMING_SOURCE_CUSTOM, + TIMING_SOURCE_EXPLICIT, + + /* explicitly specified by the display device, more important*/ + TIMING_SOURCE_EDID_CEA_SVD_3D, + TIMING_SOURCE_EDID_CEA_SVD_PREFERRED, + TIMING_SOURCE_EDID_CEA_SVD_420, + TIMING_SOURCE_EDID_DETAILED, + TIMING_SOURCE_EDID_ESTABLISHED, + TIMING_SOURCE_EDID_STANDARD, + TIMING_SOURCE_EDID_CEA_SVD, + TIMING_SOURCE_EDID_CVT_3BYTE, + TIMING_SOURCE_EDID_4BYTE, + TIMING_SOURCE_VBIOS, + TIMING_SOURCE_CV, + TIMING_SOURCE_TV, + TIMING_SOURCE_HDMI_VIC, + + /* implicitly specified by display device, still safe but less important*/ + TIMING_SOURCE_DEFAULT, + + /* only used for custom base modes */ + TIMING_SOURCE_CUSTOM_BASE, + + /* these timing might not work, least important*/ + TIMING_SOURCE_RANGELIMIT, + TIMING_SOURCE_OS_FORCED, + TIMING_SOURCE_IMPLICIT, + + /* only used by default mode list*/ + TIMING_SOURCE_BASICMODE, + + TIMING_SOURCE_COUNT +}; + +enum dc_timing_support_method { + TIMING_SUPPORT_METHOD_UNDEFINED, + TIMING_SUPPORT_METHOD_EXPLICIT, + TIMING_SUPPORT_METHOD_IMPLICIT, + TIMING_SUPPORT_METHOD_NATIVE +}; + +struct dc_mode_info { + uint32_t pixel_width; + uint32_t pixel_height; + uint32_t field_rate; + /* Vertical refresh rate for progressive modes. + * Field rate for interlaced modes.*/ + + enum dc_timing_standard timing_standard; + enum dc_timing_source timing_source; + struct dc_mode_flags flags; +}; + +enum dc_power_state { + DC_POWER_STATE_ON = 1, + DC_POWER_STATE_STANDBY, + DC_POWER_STATE_SUSPEND, + DC_POWER_STATE_OFF +}; + +/* DC PowerStates */ +enum dc_video_power_state { + DC_VIDEO_POWER_UNSPECIFIED = 0, + DC_VIDEO_POWER_ON = 1, + DC_VIDEO_POWER_STANDBY, + DC_VIDEO_POWER_SUSPEND, + DC_VIDEO_POWER_OFF, + DC_VIDEO_POWER_HIBERNATE, + DC_VIDEO_POWER_SHUTDOWN, + DC_VIDEO_POWER_ULPS, /* BACO or Ultra-Light-Power-State */ + DC_VIDEO_POWER_AFTER_RESET, + DC_VIDEO_POWER_MAXIMUM +}; + +enum dc_acpi_cm_power_state { + DC_ACPI_CM_POWER_STATE_D0 = 1, + DC_ACPI_CM_POWER_STATE_D1 = 2, + DC_ACPI_CM_POWER_STATE_D2 = 4, + DC_ACPI_CM_POWER_STATE_D3 = 8 +}; + +enum dc_connection_type { + dc_connection_none, + dc_connection_single, + dc_connection_mst_branch, + dc_connection_active_dongle +}; + +struct dc_csc_adjustments { + struct fixed31_32 contrast; + struct fixed31_32 saturation; + struct fixed31_32 brightness; + struct fixed31_32 hue; +}; + +enum { + MAX_LANES = 2, + MAX_COFUNC_PATH = 6, + LAYER_INDEX_PRIMARY = -1, +}; + +/* Scaling format */ +enum scaling_transformation { + SCALING_TRANSFORMATION_UNINITIALIZED, + SCALING_TRANSFORMATION_IDENTITY = 0x0001, + SCALING_TRANSFORMATION_CENTER_TIMING = 0x0002, + SCALING_TRANSFORMATION_FULL_SCREEN_SCALE = 0x0004, + SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE = 0x0008, + SCALING_TRANSFORMATION_DAL_DECIDE = 0x0010, + SCALING_TRANSFORMATION_INVALID = 0x80000000, + + /* Flag the first and last */ + SCALING_TRANSFORMATION_BEGING = SCALING_TRANSFORMATION_IDENTITY, + SCALING_TRANSFORMATION_END = + SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE +}; + +/* audio*/ + +union audio_sample_rates { + struct sample_rates { + uint8_t RATE_32:1; + uint8_t RATE_44_1:1; + uint8_t RATE_48:1; + uint8_t RATE_88_2:1; + uint8_t RATE_96:1; + uint8_t RATE_176_4:1; + uint8_t RATE_192:1; + } rate; + + uint8_t all; +}; + +struct audio_speaker_flags { + uint32_t FL_FR:1; + uint32_t LFE:1; + uint32_t FC:1; + uint32_t RL_RR:1; + uint32_t RC:1; + uint32_t FLC_FRC:1; + uint32_t RLC_RRC:1; + uint32_t SUPPORT_AI:1; +}; + +struct audio_speaker_info { + uint32_t ALLSPEAKERS:7; + uint32_t SUPPORT_AI:1; +}; + + +struct audio_info_flags { + + union { + + struct audio_speaker_flags speaker_flags; + struct audio_speaker_info info; + + uint8_t all; + }; +}; + +enum audio_format_code { + AUDIO_FORMAT_CODE_FIRST = 1, + AUDIO_FORMAT_CODE_LINEARPCM = AUDIO_FORMAT_CODE_FIRST, + + AUDIO_FORMAT_CODE_AC3, + /*Layers 1 & 2 */ + AUDIO_FORMAT_CODE_MPEG1, + /*MPEG1 Layer 3 */ + AUDIO_FORMAT_CODE_MP3, + /*multichannel */ + AUDIO_FORMAT_CODE_MPEG2, + AUDIO_FORMAT_CODE_AAC, + AUDIO_FORMAT_CODE_DTS, + AUDIO_FORMAT_CODE_ATRAC, + AUDIO_FORMAT_CODE_1BITAUDIO, + AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS, + AUDIO_FORMAT_CODE_DTS_HD, + AUDIO_FORMAT_CODE_MAT_MLP, + AUDIO_FORMAT_CODE_DST, + AUDIO_FORMAT_CODE_WMAPRO, + AUDIO_FORMAT_CODE_LAST, + AUDIO_FORMAT_CODE_COUNT = + AUDIO_FORMAT_CODE_LAST - AUDIO_FORMAT_CODE_FIRST +}; + +struct audio_mode { + /* ucData[0] [6:3] */ + enum audio_format_code format_code; + /* ucData[0] [2:0] */ + uint8_t channel_count; + /* ucData[1] */ + union audio_sample_rates sample_rates; + union { + /* for LPCM */ + uint8_t sample_size; + /* for Audio Formats 2-8 (Max bit rate divided by 8 kHz) */ + uint8_t max_bit_rate; + /* for Audio Formats 9-15 */ + uint8_t vendor_specific; + }; +}; + +struct audio_info { + struct audio_info_flags flags; + uint32_t video_latency; + uint32_t audio_latency; + uint32_t display_index; + uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS]; + uint32_t manufacture_id; + uint32_t product_id; + /* PortID used for ContainerID when defined */ + uint32_t port_id[2]; + uint32_t mode_count; + /* this field must be last in this struct */ + struct audio_mode modes[DC_MAX_AUDIO_DESC_COUNT]; +}; + +struct freesync_context { + bool supported; + bool enabled; + bool active; + + unsigned int min_refresh_in_micro_hz; + unsigned int nominal_refresh_in_micro_hz; +}; + +struct colorspace_transform { + struct fixed31_32 matrix[12]; + bool enable_remap; +}; + +struct csc_transform { + uint16_t matrix[12]; + bool enable_adjustment; +}; + +struct psr_caps { + /* These parameters are from PSR capabilities reported by Sink DPCD */ + unsigned char psr_version; + unsigned int psr_rfb_setup_time; + bool psr_exit_link_training_required; + + /* These parameters are calculated in Driver, + * based on display timing and Sink capabilities. + * If VBLANK region is too small and Sink takes a long time + * to set up RFB, it may take an extra frame to enter PSR state. + */ + bool psr_frame_capture_indication_req; + unsigned int psr_sdp_transmit_line_num_deadline; +}; + +#endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile new file mode 100644 index 000000000000..bfca38170329 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for common 'dce' logic +# HW object file under this folder follow similar pattern for HW programming +# - register offset and/or shift + mask stored in the dec_hw struct +# - register programming through common macros that look up register +# offset/shift/mask stored in dce_hw struct + +DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ +dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o + + +AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c new file mode 100644 index 000000000000..dc44053e8575 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -0,0 +1,920 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dce_audio.h" +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#define DCE_AUD(audio)\ + container_of(audio, struct dce_audio, base) + +#define CTX \ + aud->base.ctx +#define REG(reg)\ + (aud->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + aud->shifts->field_name, aud->masks->field_name + +#define IX_REG(reg)\ + ix ## reg + +#define AZ_REG_READ(reg_name) \ + read_indirect_azalia_reg(audio, IX_REG(reg_name)) + +#define AZ_REG_WRITE(reg_name, value) \ + write_indirect_azalia_reg(audio, IX_REG(reg_name), value) + +static void write_indirect_azalia_reg(struct audio *audio, + uint32_t reg_index, + uint32_t reg_data) +{ + struct dce_audio *aud = DCE_AUD(audio); + + /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ + REG_SET(AZALIA_F0_CODEC_ENDPOINT_INDEX, 0, + AZALIA_ENDPOINT_REG_INDEX, reg_index); + + /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ + REG_SET(AZALIA_F0_CODEC_ENDPOINT_DATA, 0, + AZALIA_ENDPOINT_REG_DATA, reg_data); + + dm_logger_write(CTX->logger, LOG_HW_AUDIO, + "AUDIO:write_indirect_azalia_reg: index: %u data: %u\n", + reg_index, reg_data); +} + +static uint32_t read_indirect_azalia_reg(struct audio *audio, uint32_t reg_index) +{ + struct dce_audio *aud = DCE_AUD(audio); + + uint32_t value = 0; + + /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ + REG_SET(AZALIA_F0_CODEC_ENDPOINT_INDEX, 0, + AZALIA_ENDPOINT_REG_INDEX, reg_index); + + /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ + value = REG_READ(AZALIA_F0_CODEC_ENDPOINT_DATA); + + dm_logger_write(CTX->logger, LOG_HW_AUDIO, + "AUDIO:read_indirect_azalia_reg: index: %u data: %u\n", + reg_index, value); + + return value; +} + +static bool is_audio_format_supported( + const struct audio_info *audio_info, + enum audio_format_code audio_format_code, + uint32_t *format_index) +{ + uint32_t index; + uint32_t max_channe_index = 0; + bool found = false; + + if (audio_info == NULL) + return found; + + /* pass through whole array */ + for (index = 0; index < audio_info->mode_count; index++) { + if (audio_info->modes[index].format_code == audio_format_code) { + if (found) { + /* format has multiply entries, choose one with + * highst number of channels */ + if (audio_info->modes[index].channel_count > + audio_info->modes[max_channe_index].channel_count) { + max_channe_index = index; + } + } else { + /* format found, save it's index */ + found = true; + max_channe_index = index; + } + } + } + + /* return index */ + if (found && format_index != NULL) + *format_index = max_channe_index; + + return found; +} + +/*For HDMI, calculate if specified sample rates can fit into a given timing */ +static void check_audio_bandwidth_hdmi( + const struct audio_crtc_info *crtc_info, + uint32_t channel_count, + union audio_sample_rates *sample_rates) +{ + uint32_t samples; + uint32_t h_blank; + bool limit_freq_to_48_khz = false; + bool limit_freq_to_88_2_khz = false; + bool limit_freq_to_96_khz = false; + bool limit_freq_to_174_4_khz = false; + + /* For two channels supported return whatever sink support,unmodified*/ + if (channel_count > 2) { + + /* Based on HDMI spec 1.3 Table 7.5 */ + if ((crtc_info->requested_pixel_clock <= 27000) && + (crtc_info->v_active <= 576) && + !(crtc_info->interlaced) && + !(crtc_info->pixel_repetition == 2 || + crtc_info->pixel_repetition == 4)) { + limit_freq_to_48_khz = true; + + } else if ((crtc_info->requested_pixel_clock <= 27000) && + (crtc_info->v_active <= 576) && + (crtc_info->interlaced) && + (crtc_info->pixel_repetition == 2)) { + limit_freq_to_88_2_khz = true; + + } else if ((crtc_info->requested_pixel_clock <= 54000) && + (crtc_info->v_active <= 576) && + !(crtc_info->interlaced)) { + limit_freq_to_174_4_khz = true; + } + } + + /* Also do some calculation for the available Audio Bandwidth for the + * 8 ch (i.e. for the Layout 1 => ch > 2) + */ + h_blank = crtc_info->h_total - crtc_info->h_active; + + if (crtc_info->pixel_repetition) + h_blank *= crtc_info->pixel_repetition; + + /*based on HDMI spec 1.3 Table 7.5 */ + h_blank -= 58; + /*for Control Period */ + h_blank -= 16; + + samples = h_blank * 10; + /* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number + * of Audio samples per line multiplied by 10 - Layout 1) + */ + samples /= 32; + samples *= crtc_info->v_active; + /*Number of samples multiplied by 10, per second */ + samples *= crtc_info->refresh_rate; + /*Number of Audio samples per second */ + samples /= 10; + + /* @todo do it after deep color is implemented + * 8xx - deep color bandwidth scaling + * Extra bandwidth is avaliable in deep color b/c link runs faster than + * pixel rate. This has the effect of allowing more tmds characters to + * be transmitted during blank + */ + + switch (crtc_info->color_depth) { + case COLOR_DEPTH_888: + samples *= 4; + break; + case COLOR_DEPTH_101010: + samples *= 5; + break; + case COLOR_DEPTH_121212: + samples *= 6; + break; + default: + samples *= 4; + break; + } + + samples /= 4; + + /*check limitation*/ + if (samples < 88200) + limit_freq_to_48_khz = true; + else if (samples < 96000) + limit_freq_to_88_2_khz = true; + else if (samples < 176400) + limit_freq_to_96_khz = true; + else if (samples < 192000) + limit_freq_to_174_4_khz = true; + + if (sample_rates != NULL) { + /* limit frequencies */ + if (limit_freq_to_174_4_khz) + sample_rates->rate.RATE_192 = 0; + + if (limit_freq_to_96_khz) { + sample_rates->rate.RATE_192 = 0; + sample_rates->rate.RATE_176_4 = 0; + } + if (limit_freq_to_88_2_khz) { + sample_rates->rate.RATE_192 = 0; + sample_rates->rate.RATE_176_4 = 0; + sample_rates->rate.RATE_96 = 0; + } + if (limit_freq_to_48_khz) { + sample_rates->rate.RATE_192 = 0; + sample_rates->rate.RATE_176_4 = 0; + sample_rates->rate.RATE_96 = 0; + sample_rates->rate.RATE_88_2 = 0; + } + } +} + +/*For DP SST, calculate if specified sample rates can fit into a given timing */ +static void check_audio_bandwidth_dpsst( + const struct audio_crtc_info *crtc_info, + uint32_t channel_count, + union audio_sample_rates *sample_rates) +{ + /* do nothing */ +} + +/*For DP MST, calculate if specified sample rates can fit into a given timing */ +static void check_audio_bandwidth_dpmst( + const struct audio_crtc_info *crtc_info, + uint32_t channel_count, + union audio_sample_rates *sample_rates) +{ + /* do nothing */ +} + +static void check_audio_bandwidth( + const struct audio_crtc_info *crtc_info, + uint32_t channel_count, + enum signal_type signal, + union audio_sample_rates *sample_rates) +{ + switch (signal) { + case SIGNAL_TYPE_HDMI_TYPE_A: + check_audio_bandwidth_hdmi( + crtc_info, channel_count, sample_rates); + break; + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + check_audio_bandwidth_dpsst( + crtc_info, channel_count, sample_rates); + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + check_audio_bandwidth_dpmst( + crtc_info, channel_count, sample_rates); + break; + default: + break; + } +} + +/* expose/not expose HBR capability to Audio driver */ +static void set_high_bit_rate_capable( + struct audio *audio, + bool capable) +{ + uint32_t value = 0; + + /* set high bit rate audio capable*/ + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR); + + set_reg_field_value(value, capable, + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, + HBR_CAPABLE); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, value); +} + +/* set video latency in in ms/2+1 */ +static void set_video_latency( + struct audio *audio, + int latency_in_ms) +{ + uint32_t value = 0; + + if ((latency_in_ms < 0) || (latency_in_ms > 255)) + return; + + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); + + set_reg_field_value(value, latency_in_ms, + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, + VIDEO_LIPSYNC); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, + value); +} + +/* set audio latency in in ms/2+1 */ +static void set_audio_latency( + struct audio *audio, + int latency_in_ms) +{ + uint32_t value = 0; + + if (latency_in_ms < 0) + latency_in_ms = 0; + + if (latency_in_ms > 255) + latency_in_ms = 255; + + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); + + set_reg_field_value(value, latency_in_ms, + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, + AUDIO_LIPSYNC); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, + value); +} + +void dce_aud_az_enable(struct audio *audio) +{ + uint32_t value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); + + if (get_reg_field_value(value, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + AUDIO_ENABLED) != 1) + set_reg_field_value(value, 1, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + AUDIO_ENABLED); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); +} + +void dce_aud_az_disable(struct audio *audio) +{ + uint32_t value; + + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); + + set_reg_field_value(value, 0, + AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, + AUDIO_ENABLED); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); +} + +void dce_aud_az_configure( + struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_info *audio_info) +{ + struct dce_audio *aud = DCE_AUD(audio); + + uint32_t speakers = audio_info->flags.info.ALLSPEAKERS; + uint32_t value; + uint32_t field = 0; + enum audio_format_code audio_format_code; + uint32_t format_index; + uint32_t index; + bool is_ac3_supported = false; + union audio_sample_rates sample_rate; + uint32_t strlen = 0; + + /* Speaker Allocation */ + /* + uint32_t value; + uint32_t field = 0;*/ + value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); + + set_reg_field_value(value, + speakers, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + SPEAKER_ALLOCATION); + + /* LFE_PLAYBACK_LEVEL = LFEPBL + * LFEPBL = 0 : Unknown or refer to other information + * LFEPBL = 1 : 0dB playback + * LFEPBL = 2 : +10dB playback + * LFE_BL = 3 : Reserved + */ + set_reg_field_value(value, + 0, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + LFE_PLAYBACK_LEVEL); + /* todo: according to reg spec LFE_PLAYBACK_LEVEL is read only. + * why are we writing to it? DCE8 does not write this */ + + + set_reg_field_value(value, + 0, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + HDMI_CONNECTION); + + set_reg_field_value(value, + 0, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + DP_CONNECTION); + + field = get_reg_field_value(value, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + EXTRA_CONNECTION_INFO); + + field &= ~0x1; + + set_reg_field_value(value, + field, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + EXTRA_CONNECTION_INFO); + + /* set audio for output signal */ + switch (signal) { + case SIGNAL_TYPE_HDMI_TYPE_A: + set_reg_field_value(value, + 1, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + HDMI_CONNECTION); + + break; + + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + set_reg_field_value(value, + 1, + AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, + DP_CONNECTION); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, value); + + /* Audio Descriptors */ + /* pass through all formats */ + for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT; + format_index++) { + audio_format_code = + (AUDIO_FORMAT_CODE_FIRST + format_index); + + /* those are unsupported, skip programming */ + if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO || + audio_format_code == AUDIO_FORMAT_CODE_DST) + continue; + + value = 0; + + /* check if supported */ + if (is_audio_format_supported( + audio_info, audio_format_code, &index)) { + const struct audio_mode *audio_mode = + &audio_info->modes[index]; + union audio_sample_rates sample_rates = + audio_mode->sample_rates; + uint8_t byte2 = audio_mode->max_bit_rate; + + /* adjust specific properties */ + switch (audio_format_code) { + case AUDIO_FORMAT_CODE_LINEARPCM: { + check_audio_bandwidth( + crtc_info, + audio_mode->channel_count, + signal, + &sample_rates); + + byte2 = audio_mode->sample_size; + + set_reg_field_value(value, + sample_rates.all, + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, + SUPPORTED_FREQUENCIES_STEREO); + } + break; + case AUDIO_FORMAT_CODE_AC3: + is_ac3_supported = true; + break; + case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS: + case AUDIO_FORMAT_CODE_DTS_HD: + case AUDIO_FORMAT_CODE_MAT_MLP: + case AUDIO_FORMAT_CODE_DST: + case AUDIO_FORMAT_CODE_WMAPRO: + byte2 = audio_mode->vendor_specific; + break; + default: + break; + } + + /* fill audio format data */ + set_reg_field_value(value, + audio_mode->channel_count - 1, + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, + MAX_CHANNELS); + + set_reg_field_value(value, + sample_rates.all, + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, + SUPPORTED_FREQUENCIES); + + set_reg_field_value(value, + byte2, + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, + DESCRIPTOR_BYTE_2); + } /* if */ + + AZ_REG_WRITE( + AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 + format_index, + value); + } /* for */ + + if (is_ac3_supported) + /* todo: this reg global. why program global register? */ + REG_WRITE(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, + 0x05); + + /* check for 192khz/8-Ch support for HBR requirements */ + sample_rate.all = 0; + sample_rate.rate.RATE_192 = 1; + + check_audio_bandwidth( + crtc_info, + 8, + signal, + &sample_rate); + + set_high_bit_rate_capable(audio, sample_rate.rate.RATE_192); + + /* Audio and Video Lipsync */ + set_video_latency(audio, audio_info->video_latency); + set_audio_latency(audio, audio_info->audio_latency); + + value = 0; + set_reg_field_value(value, audio_info->manufacture_id, + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, + MANUFACTURER_ID); + + set_reg_field_value(value, audio_info->product_id, + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, + PRODUCT_ID); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, + value); + + value = 0; + + /*get display name string length */ + while (audio_info->display_name[strlen++] != '\0') { + if (strlen >= + MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS) + break; + } + set_reg_field_value(value, strlen, + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, + SINK_DESCRIPTION_LEN); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, + value); + + /* + *write the port ID: + *PORT_ID0 = display index + *PORT_ID1 = 16bit BDF + *(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function) + */ + + value = 0; + + set_reg_field_value(value, audio_info->port_id[0], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, + PORT_ID0); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, value); + + value = 0; + set_reg_field_value(value, audio_info->port_id[1], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, + PORT_ID1); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, value); + + /*write the 18 char monitor string */ + + value = 0; + set_reg_field_value(value, audio_info->display_name[0], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, + DESCRIPTION0); + + set_reg_field_value(value, audio_info->display_name[1], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, + DESCRIPTION1); + + set_reg_field_value(value, audio_info->display_name[2], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, + DESCRIPTION2); + + set_reg_field_value(value, audio_info->display_name[3], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, + DESCRIPTION3); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, value); + + value = 0; + set_reg_field_value(value, audio_info->display_name[4], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, + DESCRIPTION4); + + set_reg_field_value(value, audio_info->display_name[5], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, + DESCRIPTION5); + + set_reg_field_value(value, audio_info->display_name[6], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, + DESCRIPTION6); + + set_reg_field_value(value, audio_info->display_name[7], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, + DESCRIPTION7); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, value); + + value = 0; + set_reg_field_value(value, audio_info->display_name[8], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, + DESCRIPTION8); + + set_reg_field_value(value, audio_info->display_name[9], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, + DESCRIPTION9); + + set_reg_field_value(value, audio_info->display_name[10], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, + DESCRIPTION10); + + set_reg_field_value(value, audio_info->display_name[11], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, + DESCRIPTION11); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, value); + + value = 0; + set_reg_field_value(value, audio_info->display_name[12], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, + DESCRIPTION12); + + set_reg_field_value(value, audio_info->display_name[13], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, + DESCRIPTION13); + + set_reg_field_value(value, audio_info->display_name[14], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, + DESCRIPTION14); + + set_reg_field_value(value, audio_info->display_name[15], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, + DESCRIPTION15); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, value); + + value = 0; + set_reg_field_value(value, audio_info->display_name[16], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, + DESCRIPTION16); + + set_reg_field_value(value, audio_info->display_name[17], + AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, + DESCRIPTION17); + + AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, value); +} + +/* +* todo: wall clk related functionality probably belong to clock_src. +*/ + +/* search pixel clock value for Azalia HDMI Audio */ +static bool get_azalia_clock_info_hdmi( + uint32_t crtc_pixel_clock_in_khz, + uint32_t actual_pixel_clock_in_khz, + struct azalia_clock_info *azalia_clock_info) +{ + if (azalia_clock_info == NULL) + return false; + + /* audio_dto_phase= 24 * 10,000; + * 24MHz in [100Hz] units */ + azalia_clock_info->audio_dto_phase = + 24 * 10000; + + /* audio_dto_module = PCLKFrequency * 10,000; + * [khz] -> [100Hz] */ + azalia_clock_info->audio_dto_module = + actual_pixel_clock_in_khz * 10; + + return true; +} + +static bool get_azalia_clock_info_dp( + uint32_t requested_pixel_clock_in_khz, + const struct audio_pll_info *pll_info, + struct azalia_clock_info *azalia_clock_info) +{ + if (pll_info == NULL || azalia_clock_info == NULL) + return false; + + /* Reported dpDtoSourceClockInkhz value for + * DCE8 already adjusted for SS, do not need any + * adjustment here anymore + */ + + /*audio_dto_phase = 24 * 10,000; + * 24MHz in [100Hz] units */ + azalia_clock_info->audio_dto_phase = 24 * 10000; + + /*audio_dto_module = dpDtoSourceClockInkhz * 10,000; + * [khz] ->[100Hz] */ + azalia_clock_info->audio_dto_module = + pll_info->dp_dto_source_clock_in_khz * 10; + + return true; +} + +void dce_aud_wall_dto_setup( + struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_pll_info *pll_info) +{ + struct dce_audio *aud = DCE_AUD(audio); + + struct azalia_clock_info clock_info = { 0 }; + + if (dc_is_hdmi_signal(signal)) { + uint32_t src_sel; + + /*DTO0 Programming goal: + -generate 24MHz, 128*Fs from 24MHz + -use DTO0 when an active HDMI port is connected + (optionally a DP is connected) */ + + /* calculate DTO settings */ + get_azalia_clock_info_hdmi( + crtc_info->requested_pixel_clock, + crtc_info->calculated_pixel_clock, + &clock_info); + + /* On TN/SI, Program DTO source select and DTO select before + programming DTO modulo and DTO phase. These bits must be + programmed first, otherwise there will be no HDMI audio at boot + up. This is a HW sequence change (different from old ASICs). + Caution when changing this programming sequence. + + HDMI enabled, using DTO0 + program master CRTC for DTO0 */ + src_sel = pll_info->dto_source - DTO_SOURCE_ID0; + REG_UPDATE_2(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO0_SOURCE_SEL, src_sel, + DCCG_AUDIO_DTO_SEL, 0); + + /* module */ + REG_UPDATE(DCCG_AUDIO_DTO0_MODULE, + DCCG_AUDIO_DTO0_MODULE, clock_info.audio_dto_module); + + /* phase */ + REG_UPDATE(DCCG_AUDIO_DTO0_PHASE, + DCCG_AUDIO_DTO0_PHASE, clock_info.audio_dto_phase); + } else { + /*DTO1 Programming goal: + -generate 24MHz, 512*Fs, 128*Fs from 24MHz + -default is to used DTO1, and switch to DTO0 when an audio + master HDMI port is connected + -use as default for DP + + calculate DTO settings */ + get_azalia_clock_info_dp( + crtc_info->requested_pixel_clock, + pll_info, + &clock_info); + + /* Program DTO select before programming DTO modulo and DTO + phase. default to use DTO1 */ + + REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO_SEL, 1); + + REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO_SEL, 1); + /* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1) + * Select 512fs for DP TODO: web register definition + * does not match register header file + * DCE11 version it's commented out while DCE8 it's set to 1 + */ + + /* module */ + REG_UPDATE(DCCG_AUDIO_DTO1_MODULE, + DCCG_AUDIO_DTO1_MODULE, clock_info.audio_dto_module); + + /* phase */ + REG_UPDATE(DCCG_AUDIO_DTO1_PHASE, + DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase); + + /* DAL2 code separate DCCG_AUDIO_DTO_SEL and + DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different + location. merge together should not hurt */ + /*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1; + dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/ + } +} + +bool dce_aud_endpoint_valid( + struct audio *audio) +{ + uint32_t value; + uint32_t port_connectivity; + + value = AZ_REG_READ( + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT); + + port_connectivity = get_reg_field_value(value, + AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT, + PORT_CONNECTIVITY); + + return !(port_connectivity == 1); +} + +/* initialize HW state */ +void dce_aud_hw_init( + struct audio *audio) +{ + struct dce_audio *aud = DCE_AUD(audio); + + /* we only need to program the following registers once, so we only do + it for the inst 0*/ + if (audio->inst != 0) + return; + + /* Suport R5 - 32khz + * Suport R6 - 44.1khz + * Suport R7 - 48khz + */ + REG_UPDATE(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, + AUDIO_RATE_CAPABILITIES, 0x70); + + /*Keep alive bit to verify HW block in BU. */ + REG_UPDATE_2(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, + CLKSTOP, 1, + EPSS, 1); +} + +static const struct audio_funcs funcs = { + .endpoint_valid = dce_aud_endpoint_valid, + .hw_init = dce_aud_hw_init, + .wall_dto_setup = dce_aud_wall_dto_setup, + .az_enable = dce_aud_az_enable, + .az_disable = dce_aud_az_disable, + .az_configure = dce_aud_az_configure, + .destroy = dce_aud_destroy, +}; + +void dce_aud_destroy(struct audio **audio) +{ + dm_free(*audio); + *audio = NULL; +} + +struct audio *dce_audio_create( + struct dc_context *ctx, + unsigned int inst, + const struct dce_audio_registers *reg, + const struct dce_audio_shift *shifts, + const struct dce_aduio_mask *masks + ) +{ + struct dce_audio *audio = dm_alloc(sizeof(*audio)); + + if (audio == NULL) { + ASSERT_CRITICAL(audio); + return NULL; + } + + audio->base.ctx = ctx; + audio->base.inst = inst; + audio->base.funcs = &funcs; + + audio->regs = reg; + audio->shifts = shifts; + audio->masks = masks; + + return &audio->base; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h new file mode 100644 index 000000000000..bf97cd8c8221 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -0,0 +1,145 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_AUDIO_DCE_110_H__ +#define __DAL_AUDIO_DCE_110_H__ + +#include "audio.h" + +#define AUD_COMMON_REG_LIST(id)\ + SRI(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id),\ + SRI(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id),\ + SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS),\ + SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES),\ + SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES),\ + SR(DCCG_AUDIO_DTO_SOURCE),\ + SR(DCCG_AUDIO_DTO0_MODULE),\ + SR(DCCG_AUDIO_DTO0_PHASE),\ + SR(DCCG_AUDIO_DTO1_MODULE),\ + SR(DCCG_AUDIO_DTO1_PHASE) + + + /* set field name */ +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + + +#define AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ + SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh) + +#define AUD_COMMON_MASK_SH_LIST(mask_sh)\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh),\ + SF(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh) + + +struct dce_audio_registers { + uint32_t AZALIA_F0_CODEC_ENDPOINT_INDEX; + uint32_t AZALIA_F0_CODEC_ENDPOINT_DATA; + + uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS; + uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES; + uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES; + + uint32_t DCCG_AUDIO_DTO_SOURCE; + uint32_t DCCG_AUDIO_DTO0_MODULE; + uint32_t DCCG_AUDIO_DTO0_PHASE; + uint32_t DCCG_AUDIO_DTO1_MODULE; + uint32_t DCCG_AUDIO_DTO1_PHASE; + + uint32_t AUDIO_RATE_CAPABILITIES; +}; + +struct dce_audio_shift { + uint8_t AZALIA_ENDPOINT_REG_INDEX; + uint8_t AZALIA_ENDPOINT_REG_DATA; + + uint8_t AUDIO_RATE_CAPABILITIES; + uint8_t CLKSTOP; + uint8_t EPSS; + + uint8_t DCCG_AUDIO_DTO0_SOURCE_SEL; + uint8_t DCCG_AUDIO_DTO_SEL; + uint8_t DCCG_AUDIO_DTO0_MODULE; + uint8_t DCCG_AUDIO_DTO0_PHASE; + uint8_t DCCG_AUDIO_DTO1_MODULE; + uint8_t DCCG_AUDIO_DTO1_PHASE; +}; + +struct dce_aduio_mask { + uint32_t AZALIA_ENDPOINT_REG_INDEX; + uint32_t AZALIA_ENDPOINT_REG_DATA; + + uint32_t AUDIO_RATE_CAPABILITIES; + uint32_t CLKSTOP; + uint32_t EPSS; + + uint32_t DCCG_AUDIO_DTO0_SOURCE_SEL; + uint32_t DCCG_AUDIO_DTO_SEL; + uint32_t DCCG_AUDIO_DTO0_MODULE; + uint32_t DCCG_AUDIO_DTO0_PHASE; + uint32_t DCCG_AUDIO_DTO1_MODULE; + uint32_t DCCG_AUDIO_DTO1_PHASE; +}; + +struct dce_audio { + struct audio base; + const struct dce_audio_registers *regs; + const struct dce_audio_shift *shifts; + const struct dce_aduio_mask *masks; +}; + +struct audio *dce_audio_create( + struct dc_context *ctx, + unsigned int inst, + const struct dce_audio_registers *reg, + const struct dce_audio_shift *shifts, + const struct dce_aduio_mask *masks); + +void dce_aud_destroy(struct audio **audio); + +void dce_aud_hw_init(struct audio *audio); + +void dce_aud_az_enable(struct audio *audio); +void dce_aud_az_disable(struct audio *audio); + +void dce_aud_az_configure(struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_info *audio_info); + +void dce_aud_wall_dto_setup(struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_pll_info *pll_info); + +#endif /*__DAL_AUDIO_DCE_110_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c new file mode 100644 index 000000000000..80ac5d9efa71 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -0,0 +1,1264 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + + +#include "dc_types.h" +#include "core_types.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" + +#include "dce_clock_source.h" + +#include "reg_helper.h" + +#define REG(reg)\ + (clk_src->regs->reg) + +#define CTX \ + clk_src->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + clk_src->cs_shift->field_name, clk_src->cs_mask->field_name + +#define FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM 6 +#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1 +#define MAX_PLL_CALC_ERROR 0xFFFFFFFF + +static const struct spread_spectrum_data *get_ss_data_entry( + struct dce110_clk_src *clk_src, + enum signal_type signal, + uint32_t pix_clk_khz) +{ + + uint32_t entrys_num; + uint32_t i; + struct spread_spectrum_data *ss_parm = NULL; + struct spread_spectrum_data *ret = NULL; + + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + ss_parm = clk_src->dvi_ss_params; + entrys_num = clk_src->dvi_ss_params_cnt; + break; + + case SIGNAL_TYPE_HDMI_TYPE_A: + ss_parm = clk_src->hdmi_ss_params; + entrys_num = clk_src->hdmi_ss_params_cnt; + break; + + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_VIRTUAL: + ss_parm = clk_src->dp_ss_params; + entrys_num = clk_src->dp_ss_params_cnt; + break; + + default: + ss_parm = NULL; + entrys_num = 0; + break; + } + + if (ss_parm == NULL) + return ret; + + for (i = 0; i < entrys_num; ++i, ++ss_parm) { + if (ss_parm->freq_range_khz >= pix_clk_khz) { + ret = ss_parm; + break; + } + } + + return ret; +} + +/** +* Function: calculate_fb_and_fractional_fb_divider +* +* * DESCRIPTION: Calculates feedback and fractional feedback dividers values +* +*PARAMETERS: +* targetPixelClock Desired frequency in 10 KHz +* ref_divider Reference divider (already known) +* postDivider Post Divider (already known) +* feedback_divider_param Pointer where to store +* calculated feedback divider value +* fract_feedback_divider_param Pointer where to store +* calculated fract feedback divider value +* +*RETURNS: +* It fills the locations pointed by feedback_divider_param +* and fract_feedback_divider_param +* It returns - true if feedback divider not 0 +* - false should never happen) +*/ +static bool calculate_fb_and_fractional_fb_divider( + struct calc_pll_clock_source *calc_pll_cs, + uint32_t target_pix_clk_khz, + uint32_t ref_divider, + uint32_t post_divider, + uint32_t *feedback_divider_param, + uint32_t *fract_feedback_divider_param) +{ + uint64_t feedback_divider; + + feedback_divider = + (uint64_t)(target_pix_clk_khz * ref_divider * post_divider); + feedback_divider *= 10; + /* additional factor, since we divide by 10 afterwards */ + feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor); + feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz); + +/*Round to the number of precision + * The following code replace the old code (ullfeedbackDivider + 5)/10 + * for example if the difference between the number + * of fractional feedback decimal point and the fractional FB Divider precision + * is 2 then the equation becomes (ullfeedbackDivider + 5*100) / (10*100))*/ + + feedback_divider += (uint64_t) + (5 * calc_pll_cs->fract_fb_divider_precision_factor); + feedback_divider = + div_u64(feedback_divider, + calc_pll_cs->fract_fb_divider_precision_factor * 10); + feedback_divider *= (uint64_t) + (calc_pll_cs->fract_fb_divider_precision_factor); + + *feedback_divider_param = + div_u64_rem( + feedback_divider, + calc_pll_cs->fract_fb_divider_factor, + fract_feedback_divider_param); + + if (*feedback_divider_param != 0) + return true; + return false; +} + +/** +*calc_fb_divider_checking_tolerance +* +*DESCRIPTION: Calculates Feedback and Fractional Feedback divider values +* for passed Reference and Post divider, checking for tolerance. +*PARAMETERS: +* pll_settings Pointer to structure +* ref_divider Reference divider (already known) +* postDivider Post Divider (already known) +* tolerance Tolerance for Calculated Pixel Clock to be within +* +*RETURNS: +* It fills the PLLSettings structure with PLL Dividers values +* if calculated values are within required tolerance +* It returns - true if eror is within tolerance +* - false if eror is not within tolerance +*/ +static bool calc_fb_divider_checking_tolerance( + struct calc_pll_clock_source *calc_pll_cs, + struct pll_settings *pll_settings, + uint32_t ref_divider, + uint32_t post_divider, + uint32_t tolerance) +{ + uint32_t feedback_divider; + uint32_t fract_feedback_divider; + uint32_t actual_calculated_clock_khz; + uint32_t abs_err; + uint64_t actual_calc_clk_khz; + + calculate_fb_and_fractional_fb_divider( + calc_pll_cs, + pll_settings->adjusted_pix_clk, + ref_divider, + post_divider, + &feedback_divider, + &fract_feedback_divider); + + /*Actual calculated value*/ + actual_calc_clk_khz = (uint64_t)(feedback_divider * + calc_pll_cs->fract_fb_divider_factor) + + fract_feedback_divider; + actual_calc_clk_khz *= calc_pll_cs->ref_freq_khz; + actual_calc_clk_khz = + div_u64(actual_calc_clk_khz, + ref_divider * post_divider * + calc_pll_cs->fract_fb_divider_factor); + + actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz); + + abs_err = (actual_calculated_clock_khz > + pll_settings->adjusted_pix_clk) + ? actual_calculated_clock_khz - + pll_settings->adjusted_pix_clk + : pll_settings->adjusted_pix_clk - + actual_calculated_clock_khz; + + if (abs_err <= tolerance) { + /*found good values*/ + pll_settings->reference_freq = calc_pll_cs->ref_freq_khz; + pll_settings->reference_divider = ref_divider; + pll_settings->feedback_divider = feedback_divider; + pll_settings->fract_feedback_divider = fract_feedback_divider; + pll_settings->pix_clk_post_divider = post_divider; + pll_settings->calculated_pix_clk = + actual_calculated_clock_khz; + pll_settings->vco_freq = + actual_calculated_clock_khz * post_divider; + return true; + } + return false; +} + +static bool calc_pll_dividers_in_range( + struct calc_pll_clock_source *calc_pll_cs, + struct pll_settings *pll_settings, + uint32_t min_ref_divider, + uint32_t max_ref_divider, + uint32_t min_post_divider, + uint32_t max_post_divider, + uint32_t err_tolerance) +{ + uint32_t ref_divider; + uint32_t post_divider; + uint32_t tolerance; + +/* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25% + * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/ + tolerance = (pll_settings->adjusted_pix_clk * err_tolerance) / + 10000; + if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE) + tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE; + + for ( + post_divider = max_post_divider; + post_divider >= min_post_divider; + --post_divider) { + for ( + ref_divider = min_ref_divider; + ref_divider <= max_ref_divider; + ++ref_divider) { + if (calc_fb_divider_checking_tolerance( + calc_pll_cs, + pll_settings, + ref_divider, + post_divider, + tolerance)) { + return true; + } + } + } + + return false; +} + +static uint32_t calculate_pixel_clock_pll_dividers( + struct calc_pll_clock_source *calc_pll_cs, + struct pll_settings *pll_settings) +{ + uint32_t err_tolerance; + uint32_t min_post_divider; + uint32_t max_post_divider; + uint32_t min_ref_divider; + uint32_t max_ref_divider; + + if (pll_settings->adjusted_pix_clk == 0) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "%s Bad requested pixel clock", __func__); + return MAX_PLL_CALC_ERROR; + } + +/* 1) Find Post divider ranges */ + if (pll_settings->pix_clk_post_divider) { + min_post_divider = pll_settings->pix_clk_post_divider; + max_post_divider = pll_settings->pix_clk_post_divider; + } else { + min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider; + if (min_post_divider * pll_settings->adjusted_pix_clk < + calc_pll_cs->min_vco_khz) { + min_post_divider = calc_pll_cs->min_vco_khz / + pll_settings->adjusted_pix_clk; + if ((min_post_divider * + pll_settings->adjusted_pix_clk) < + calc_pll_cs->min_vco_khz) + min_post_divider++; + } + + max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider; + if (max_post_divider * pll_settings->adjusted_pix_clk + > calc_pll_cs->max_vco_khz) + max_post_divider = calc_pll_cs->max_vco_khz / + pll_settings->adjusted_pix_clk; + } + +/* 2) Find Reference divider ranges + * When SS is enabled, or for Display Port even without SS, + * pll_settings->referenceDivider is not zero. + * So calculate PPLL FB and fractional FB divider + * using the passed reference divider*/ + + if (pll_settings->reference_divider) { + min_ref_divider = pll_settings->reference_divider; + max_ref_divider = pll_settings->reference_divider; + } else { + min_ref_divider = ((calc_pll_cs->ref_freq_khz + / calc_pll_cs->max_pll_input_freq_khz) + > calc_pll_cs->min_pll_ref_divider) + ? calc_pll_cs->ref_freq_khz + / calc_pll_cs->max_pll_input_freq_khz + : calc_pll_cs->min_pll_ref_divider; + + max_ref_divider = ((calc_pll_cs->ref_freq_khz + / calc_pll_cs->min_pll_input_freq_khz) + < calc_pll_cs->max_pll_ref_divider) + ? calc_pll_cs->ref_freq_khz / + calc_pll_cs->min_pll_input_freq_khz + : calc_pll_cs->max_pll_ref_divider; + } + +/* If some parameters are invalid we could have scenario when "min">"max" + * which produced endless loop later. + * We should investigate why we get the wrong parameters. + * But to follow the similar logic when "adjustedPixelClock" is set to be 0 + * it is better to return here than cause system hang/watchdog timeout later. + * ## SVS Wed 15 Jul 2009 */ + + if (min_post_divider > max_post_divider) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "%s Post divider range is invalid", __func__); + return MAX_PLL_CALC_ERROR; + } + + if (min_ref_divider > max_ref_divider) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "%s Reference divider range is invalid", __func__); + return MAX_PLL_CALC_ERROR; + } + +/* 3) Try to find PLL dividers given ranges + * starting with minimal error tolerance. + * Increase error tolerance until PLL dividers found*/ + err_tolerance = MAX_PLL_CALC_ERROR; + + while (!calc_pll_dividers_in_range( + calc_pll_cs, + pll_settings, + min_ref_divider, + max_ref_divider, + min_post_divider, + max_post_divider, + err_tolerance)) + err_tolerance += (err_tolerance > 10) + ? (err_tolerance / 10) + : 1; + + return err_tolerance; +} + +static bool pll_adjust_pix_clk( + struct dce110_clk_src *clk_src, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t actual_pix_clk_khz = 0; + uint32_t requested_clk_khz = 0; + struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = { + 0 }; + enum bp_result bp_result; + + switch (pix_clk_params->signal_type) { + case SIGNAL_TYPE_HDMI_TYPE_A: { + requested_clk_khz = pix_clk_params->requested_pix_clk; + + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_101010: + requested_clk_khz = (requested_clk_khz * 5) >> 2; + break; /* x1.25*/ + case COLOR_DEPTH_121212: + requested_clk_khz = (requested_clk_khz * 6) >> 2; + break; /* x1.5*/ + case COLOR_DEPTH_161616: + requested_clk_khz = requested_clk_khz * 2; + break; /* x2.0*/ + default: + break; + } + + actual_pix_clk_khz = requested_clk_khz; + } + break; + + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + requested_clk_khz = pix_clk_params->requested_sym_clk; + actual_pix_clk_khz = pix_clk_params->requested_pix_clk; + break; + + default: + requested_clk_khz = pix_clk_params->requested_pix_clk; + actual_pix_clk_khz = pix_clk_params->requested_pix_clk; + break; + } + + bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz; + bp_adjust_pixel_clock_params. + encoder_object_id = pix_clk_params->encoder_object_id; + bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type; + bp_adjust_pixel_clock_params. + ss_enable = pix_clk_params->flags.ENABLE_SS; + bp_result = clk_src->bios->funcs->adjust_pixel_clock( + clk_src->bios, &bp_adjust_pixel_clock_params); + if (bp_result == BP_RESULT_OK) { + pll_settings->actual_pix_clk = actual_pix_clk_khz; + pll_settings->adjusted_pix_clk = + bp_adjust_pixel_clock_params.adjusted_pixel_clock; + pll_settings->reference_divider = + bp_adjust_pixel_clock_params.reference_divider; + pll_settings->pix_clk_post_divider = + bp_adjust_pixel_clock_params.pixel_clock_post_divider; + + return true; + } + + return false; +} + +/** + * Calculate PLL Dividers for given Clock Value. + * First will call VBIOS Adjust Exec table to check if requested Pixel clock + * will be Adjusted based on usage. + * Then it will calculate PLL Dividers for this Adjusted clock using preferred + * method (Maximum VCO frequency). + * + * \return + * Calculation error in units of 0.01% + */ + +static uint32_t dce110_get_pix_clk_dividers_helper ( + struct dce110_clk_src *clk_src, + struct pll_settings *pll_settings, + struct pixel_clk_params *pix_clk_params) +{ + uint32_t addr = 0; + uint32_t value = 0; + uint32_t field = 0; + uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; + + /* Check if reference clock is external (not pcie/xtalin) + * HW Dce80 spec: + * 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB + * 04 - HSYNCA, 05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */ + value = REG_READ(PLL_CNTL); + REG_GET(PLL_CNTL, PLL_REF_DIV_SRC, &field); + pll_settings->use_external_clk = (field > 1); + + /* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always + * (we do not care any more from SI for some older DP Sink which + * does not report SS support, no known issues) */ + if ((pix_clk_params->flags.ENABLE_SS) || + (dc_is_dp_signal(pix_clk_params->signal_type))) { + + const struct spread_spectrum_data *ss_data = get_ss_data_entry( + clk_src, + pix_clk_params->signal_type, + pll_settings->adjusted_pix_clk); + + if (NULL != ss_data) + pll_settings->ss_percentage = ss_data->percentage; + } + + /* Check VBIOS AdjustPixelClock Exec table */ + if (!pll_adjust_pix_clk(clk_src, pix_clk_params, pll_settings)) { + /* Should never happen, ASSERT and fill up values to be able + * to continue. */ + dm_logger_write(clk_src->base.ctx->logger, LOG_ERROR, + "%s: Failed to adjust pixel clock!!", __func__); + pll_settings->actual_pix_clk = + pix_clk_params->requested_pix_clk; + pll_settings->adjusted_pix_clk = + pix_clk_params->requested_pix_clk; + + if (dc_is_dp_signal(pix_clk_params->signal_type)) + pll_settings->adjusted_pix_clk = 100000; + } + + /* Calculate Dividers */ + if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) + /*Calculate Dividers by HDMI object, no SS case or SS case */ + pll_calc_error = + calculate_pixel_clock_pll_dividers( + &clk_src->calc_pll_hdmi, + pll_settings); + else + /*Calculate Dividers by default object, no SS case or SS case */ + pll_calc_error = + calculate_pixel_clock_pll_dividers( + &clk_src->calc_pll, + pll_settings); + + return pll_calc_error; +} + +static void dce112_get_pix_clk_dividers_helper ( + struct dce110_clk_src *clk_src, + struct pll_settings *pll_settings, + struct pixel_clk_params *pix_clk_params) +{ + uint32_t actualPixelClockInKHz; + + actualPixelClockInKHz = pix_clk_params->requested_pix_clk; + /* Calculate Dividers */ + if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_101010: + actualPixelClockInKHz = (actualPixelClockInKHz * 5) >> 2; + break; + case COLOR_DEPTH_121212: + actualPixelClockInKHz = (actualPixelClockInKHz * 6) >> 2; + break; + case COLOR_DEPTH_161616: + actualPixelClockInKHz = actualPixelClockInKHz * 2; + break; + default: + break; + } + } + pll_settings->actual_pix_clk = actualPixelClockInKHz; + pll_settings->adjusted_pix_clk = actualPixelClockInKHz; + pll_settings->calculated_pix_clk = pix_clk_params->requested_pix_clk; +} + +static uint32_t dce110_get_pix_clk_dividers( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs); + uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; + + if (pix_clk_params == NULL || pll_settings == NULL + || pix_clk_params->requested_pix_clk == 0) { + dm_logger_write(clk_src->base.ctx->logger, LOG_ERROR, + "%s: Invalid parameters!!\n", __func__); + return pll_calc_error; + } + + memset(pll_settings, 0, sizeof(*pll_settings)); + + if (cs->id == CLOCK_SOURCE_ID_DP_DTO || + cs->id == CLOCK_SOURCE_ID_EXTERNAL) { + pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz; + pll_settings->calculated_pix_clk = clk_src->ext_clk_khz; + pll_settings->actual_pix_clk = + pix_clk_params->requested_pix_clk; + return 0; + } + + switch (cs->ctx->dce_version) { + case DCE_VERSION_8_0: + case DCE_VERSION_10_0: + case DCE_VERSION_11_0: + pll_calc_error = + dce110_get_pix_clk_dividers_helper(clk_src, + pll_settings, pix_clk_params); + break; + case DCE_VERSION_11_2: + dce112_get_pix_clk_dividers_helper(clk_src, + pll_settings, pix_clk_params); + break; + default: + break; + } + + return pll_calc_error; +} + +static bool disable_spread_spectrum(struct dce110_clk_src *clk_src) +{ + enum bp_result result; + struct bp_spread_spectrum_parameters bp_ss_params = {0}; + + bp_ss_params.pll_id = clk_src->base.id; + + /*Call ASICControl to process ATOMBIOS Exec table*/ + result = clk_src->bios->funcs->enable_spread_spectrum_on_ppll( + clk_src->bios, + &bp_ss_params, + false); + + return result == BP_RESULT_OK; +} + +static bool calculate_ss( + const struct pll_settings *pll_settings, + const struct spread_spectrum_data *ss_data, + struct delta_sigma_data *ds_data) +{ + struct fixed32_32 fb_div; + struct fixed32_32 ss_amount; + struct fixed32_32 ss_nslip_amount; + struct fixed32_32 ss_ds_frac_amount; + struct fixed32_32 ss_step_size; + struct fixed32_32 modulation_time; + + if (ds_data == NULL) + return false; + if (ss_data == NULL) + return false; + if (ss_data->percentage == 0) + return false; + if (pll_settings == NULL) + return false; + + memset(ds_data, 0, sizeof(struct delta_sigma_data)); + + /* compute SS_AMOUNT_FBDIV & SS_AMOUNT_NFRAC_SLIP & SS_AMOUNT_DSFRAC*/ + /* 6 decimal point support in fractional feedback divider */ + fb_div = dal_fixed32_32_from_fraction( + pll_settings->fract_feedback_divider, 1000000); + fb_div = dal_fixed32_32_add_int(fb_div, pll_settings->feedback_divider); + + ds_data->ds_frac_amount = 0; + /*spreadSpectrumPercentage is in the unit of .01%, + * so have to divided by 100 * 100*/ + ss_amount = dal_fixed32_32_mul( + fb_div, dal_fixed32_32_from_fraction(ss_data->percentage, + 100 * ss_data->percentage_divider)); + ds_data->feedback_amount = dal_fixed32_32_floor(ss_amount); + + ss_nslip_amount = dal_fixed32_32_sub(ss_amount, + dal_fixed32_32_from_int(ds_data->feedback_amount)); + ss_nslip_amount = dal_fixed32_32_mul_int(ss_nslip_amount, 10); + ds_data->nfrac_amount = dal_fixed32_32_floor(ss_nslip_amount); + + ss_ds_frac_amount = dal_fixed32_32_sub(ss_nslip_amount, + dal_fixed32_32_from_int(ds_data->nfrac_amount)); + ss_ds_frac_amount = dal_fixed32_32_mul_int(ss_ds_frac_amount, 65536); + ds_data->ds_frac_amount = dal_fixed32_32_floor(ss_ds_frac_amount); + + /* compute SS_STEP_SIZE_DSFRAC */ + modulation_time = dal_fixed32_32_from_fraction( + pll_settings->reference_freq * 1000, + pll_settings->reference_divider * ss_data->modulation_freq_hz); + + if (ss_data->flags.CENTER_SPREAD) + modulation_time = dal_fixed32_32_div_int(modulation_time, 4); + else + modulation_time = dal_fixed32_32_div_int(modulation_time, 2); + + ss_step_size = dal_fixed32_32_div(ss_amount, modulation_time); + /* SS_STEP_SIZE_DSFRAC_DEC = Int(SS_STEP_SIZE * 2 ^ 16 * 10)*/ + ss_step_size = dal_fixed32_32_mul_int(ss_step_size, 65536 * 10); + ds_data->ds_frac_size = dal_fixed32_32_floor(ss_step_size); + + return true; +} + +static bool enable_spread_spectrum( + struct dce110_clk_src *clk_src, + enum signal_type signal, struct pll_settings *pll_settings) +{ + struct bp_spread_spectrum_parameters bp_params = {0}; + struct delta_sigma_data d_s_data; + const struct spread_spectrum_data *ss_data = NULL; + + ss_data = get_ss_data_entry( + clk_src, + signal, + pll_settings->calculated_pix_clk); + +/* Pixel clock PLL has been programmed to generate desired pixel clock, + * now enable SS on pixel clock */ +/* TODO is it OK to return true not doing anything ??*/ + if (ss_data != NULL && pll_settings->ss_percentage != 0) { + if (calculate_ss(pll_settings, ss_data, &d_s_data)) { + bp_params.ds.feedback_amount = + d_s_data.feedback_amount; + bp_params.ds.nfrac_amount = + d_s_data.nfrac_amount; + bp_params.ds.ds_frac_size = d_s_data.ds_frac_size; + bp_params.ds_frac_amount = + d_s_data.ds_frac_amount; + bp_params.flags.DS_TYPE = 1; + bp_params.pll_id = clk_src->base.id; + bp_params.percentage = ss_data->percentage; + if (ss_data->flags.CENTER_SPREAD) + bp_params.flags.CENTER_SPREAD = 1; + if (ss_data->flags.EXTERNAL_SS) + bp_params.flags.EXTERNAL_SS = 1; + + if (BP_RESULT_OK != + clk_src->bios->funcs-> + enable_spread_spectrum_on_ppll( + clk_src->bios, + &bp_params, + true)) + return false; + } else + return false; + } + return true; +} + +static void dce110_program_pixel_clk_resync( + struct dce110_clk_src *clk_src, + enum signal_type signal_type, + enum dc_color_depth colordepth) +{ + uint32_t value = 0; + + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 0); + /* + 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) + 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) + 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) + 48 bit mode: TMDS clock = 2 x pixel clock (2:1) + */ + if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return; + + switch (colordepth) { + case COLOR_DEPTH_888: + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 0); + break; + case COLOR_DEPTH_101010: + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 1); + break; + case COLOR_DEPTH_121212: + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 2); + break; + case COLOR_DEPTH_161616: + REG_UPDATE(RESYNC_CNTL, + DCCG_DEEP_COLOR_CNTL1, 3); + break; + default: + break; + } +} + +static void dce112_program_pixel_clk_resync( + struct dce110_clk_src *clk_src, + enum signal_type signal_type, + enum dc_color_depth colordepth, + bool enable_ycbcr420) +{ + uint32_t value = 0; + + REG_UPDATE(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0); + /* + 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) + 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) + 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) + 48 bit mode: TMDS clock = 2 x pixel clock (2:1) + */ + if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return; + + switch (colordepth) { + case COLOR_DEPTH_888: + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); + break; + case COLOR_DEPTH_101010: + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 1, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); + break; + case COLOR_DEPTH_121212: + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 2, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, 3, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); + break; + default: + break; + } +} + +static bool dce110_program_pix_clk( + struct clock_source *clk_src, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src); + struct bp_pixel_clock_parameters bp_pc_params = {0}; + + /* First disable SS + * ATOMBIOS will enable by default SS on PLL for DP, + * do not disable it here + */ + if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL && + !dc_is_dp_signal(pix_clk_params->signal_type) && + clk_src->ctx->dce_version <= DCE_VERSION_11_0) + disable_spread_spectrum(dce110_clk_src); + + /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ + bp_pc_params.controller_id = pix_clk_params->controller_id; + bp_pc_params.pll_id = clk_src->id; + bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk; + bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; + bp_pc_params.signal_type = pix_clk_params->signal_type; + + switch (clk_src->ctx->dce_version) { + case DCE_VERSION_11_2: + if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) { + bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = + pll_settings->use_external_clk; + bp_pc_params.flags.SET_XTALIN_REF_SRC = + !pll_settings->use_external_clk; + if (pix_clk_params->flags.SUPPORT_YCBCR420) { + bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2; + bp_pc_params.flags.SUPPORT_YUV_420 = 1; + } + } + if (dce110_clk_src->bios->funcs->set_pixel_clock( + dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Resync deep color DTO */ + if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) + dce112_program_pixel_clk_resync(dce110_clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth, + pix_clk_params->flags.SUPPORT_YCBCR420); + break; + case DCE_VERSION_8_0: + case DCE_VERSION_10_0: + case DCE_VERSION_11_0: + bp_pc_params.reference_divider = pll_settings->reference_divider; + bp_pc_params.feedback_divider = pll_settings->feedback_divider; + bp_pc_params.fractional_feedback_divider = + pll_settings->fract_feedback_divider; + bp_pc_params.pixel_clock_post_divider = + pll_settings->pix_clk_post_divider; + bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC = + pll_settings->use_external_clk; + + if (dce110_clk_src->bios->funcs->set_pixel_clock( + dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Enable SS + * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock), + * based on HW display PLL team, SS control settings should be programmed + * during PLL Reset, but they do not have effect + * until SS_EN is asserted.*/ + if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL + && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( + pix_clk_params->signal_type)) { + + if (!enable_spread_spectrum(dce110_clk_src, + pix_clk_params->signal_type, + pll_settings)) + return false; + /* Resync deep color DTO */ + dce110_program_pixel_clk_resync(dce110_clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth); + } + break; + default: + break; + } + + return true; +} + +static bool dce110_clock_source_power_down( + struct clock_source *clk_src) +{ + struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src); + enum bp_result bp_result; + struct bp_pixel_clock_parameters bp_pixel_clock_params = {0}; + + if (clk_src->dp_clk_src) + return true; + + /* If Pixel Clock is 0 it means Power Down Pll*/ + bp_pixel_clock_params.controller_id = CONTROLLER_ID_UNDEFINED; + bp_pixel_clock_params.pll_id = clk_src->id; + bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1; + + /*Call ASICControl to process ATOMBIOS Exec table*/ + bp_result = dce110_clk_src->bios->funcs->set_pixel_clock( + dce110_clk_src->bios, + &bp_pixel_clock_params); + + return bp_result == BP_RESULT_OK; +} + +/*****************************************/ +/* Constructor */ +/*****************************************/ +static const struct clock_source_funcs dce110_clk_src_funcs = { + .cs_power_down = dce110_clock_source_power_down, + .program_pix_clk = dce110_program_pix_clk, + .get_pix_clk_dividers = dce110_get_pix_clk_dividers +}; + +static void get_ss_info_from_atombios( + struct dce110_clk_src *clk_src, + enum as_signal_type as_signal, + struct spread_spectrum_data *spread_spectrum_data[], + uint32_t *ss_entries_num) +{ + enum bp_result bp_result = BP_RESULT_FAILURE; + struct spread_spectrum_info *ss_info; + struct spread_spectrum_data *ss_data; + struct spread_spectrum_info *ss_info_cur; + struct spread_spectrum_data *ss_data_cur; + uint32_t i; + + if (ss_entries_num == NULL) { + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "Invalid entry !!!\n"); + return; + } + if (spread_spectrum_data == NULL) { + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "Invalid array pointer!!!\n"); + return; + } + + spread_spectrum_data[0] = NULL; + *ss_entries_num = 0; + + *ss_entries_num = clk_src->bios->funcs->get_ss_entry_number( + clk_src->bios, + as_signal); + + if (*ss_entries_num == 0) + return; + + ss_info = dm_alloc(sizeof(struct spread_spectrum_info) * (*ss_entries_num)); + ss_info_cur = ss_info; + if (ss_info == NULL) + return; + + ss_data = dm_alloc(sizeof(struct spread_spectrum_data) * (*ss_entries_num)); + if (ss_data == NULL) + goto out_free_info; + + for (i = 0, ss_info_cur = ss_info; + i < (*ss_entries_num); + ++i, ++ss_info_cur) { + + bp_result = clk_src->bios->funcs->get_spread_spectrum_info( + clk_src->bios, + as_signal, + i, + ss_info_cur); + + if (bp_result != BP_RESULT_OK) + goto out_free_data; + } + + for (i = 0, ss_info_cur = ss_info, ss_data_cur = ss_data; + i < (*ss_entries_num); + ++i, ++ss_info_cur, ++ss_data_cur) { + + if (ss_info_cur->type.STEP_AND_DELAY_INFO != false) { + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "Invalid ATOMBIOS SS Table!!!\n"); + goto out_free_data; + } + + /* for HDMI check SS percentage, + * if it is > 6 (0.06%), the ATOMBIOS table info is invalid*/ + if (as_signal == AS_SIGNAL_TYPE_HDMI + && ss_info_cur->spread_spectrum_percentage > 6){ + /* invalid input, do nothing */ + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "Invalid SS percentage "); + dm_logger_write(clk_src->base.ctx->logger, LOG_SYNC, + "for HDMI in ATOMBIOS info Table!!!\n"); + continue; + } + if (ss_info_cur->spread_percentage_divider == 1000) { + /* Keep previous precision from ATOMBIOS for these + * in case new precision set by ATOMBIOS for these + * (otherwise all code in DCE specific classes + * for all previous ASICs would need + * to be updated for SS calculations, + * Audio SS compensation and DP DTO SS compensation + * which assumes fixed SS percentage Divider = 100)*/ + ss_info_cur->spread_spectrum_percentage /= 10; + ss_info_cur->spread_percentage_divider = 100; + } + + ss_data_cur->freq_range_khz = ss_info_cur->target_clock_range; + ss_data_cur->percentage = + ss_info_cur->spread_spectrum_percentage; + ss_data_cur->percentage_divider = + ss_info_cur->spread_percentage_divider; + ss_data_cur->modulation_freq_hz = + ss_info_cur->spread_spectrum_range; + + if (ss_info_cur->type.CENTER_MODE) + ss_data_cur->flags.CENTER_SPREAD = 1; + + if (ss_info_cur->type.EXTERNAL) + ss_data_cur->flags.EXTERNAL_SS = 1; + + } + + *spread_spectrum_data = ss_data; + dm_free(ss_info); + return; + +out_free_data: + dm_free(ss_data); + *ss_entries_num = 0; +out_free_info: + dm_free(ss_info); +} + +static void ss_info_from_atombios_create( + struct dce110_clk_src *clk_src) +{ + get_ss_info_from_atombios( + clk_src, + AS_SIGNAL_TYPE_DISPLAY_PORT, + &clk_src->dp_ss_params, + &clk_src->dp_ss_params_cnt); + get_ss_info_from_atombios( + clk_src, + AS_SIGNAL_TYPE_HDMI, + &clk_src->hdmi_ss_params, + &clk_src->hdmi_ss_params_cnt); + get_ss_info_from_atombios( + clk_src, + AS_SIGNAL_TYPE_DVI, + &clk_src->dvi_ss_params, + &clk_src->dvi_ss_params_cnt); +} + +static bool calc_pll_max_vco_construct( + struct calc_pll_clock_source *calc_pll_cs, + struct calc_pll_clock_source_init_data *init_data) +{ + uint32_t i; + struct firmware_info fw_info = { { 0 } }; + if (calc_pll_cs == NULL || + init_data == NULL || + init_data->bp == NULL) + return false; + + if (init_data->bp->funcs->get_firmware_info( + init_data->bp, + &fw_info) != BP_RESULT_OK) + return false; + + calc_pll_cs->ctx = init_data->ctx; + calc_pll_cs->ref_freq_khz = fw_info.pll_info.crystal_frequency; + calc_pll_cs->min_vco_khz = + fw_info.pll_info.min_output_pxl_clk_pll_frequency; + calc_pll_cs->max_vco_khz = + fw_info.pll_info.max_output_pxl_clk_pll_frequency; + + if (init_data->max_override_input_pxl_clk_pll_freq_khz != 0) + calc_pll_cs->max_pll_input_freq_khz = + init_data->max_override_input_pxl_clk_pll_freq_khz; + else + calc_pll_cs->max_pll_input_freq_khz = + fw_info.pll_info.max_input_pxl_clk_pll_frequency; + + if (init_data->min_override_input_pxl_clk_pll_freq_khz != 0) + calc_pll_cs->min_pll_input_freq_khz = + init_data->min_override_input_pxl_clk_pll_freq_khz; + else + calc_pll_cs->min_pll_input_freq_khz = + fw_info.pll_info.min_input_pxl_clk_pll_frequency; + + calc_pll_cs->min_pix_clock_pll_post_divider = + init_data->min_pix_clk_pll_post_divider; + calc_pll_cs->max_pix_clock_pll_post_divider = + init_data->max_pix_clk_pll_post_divider; + calc_pll_cs->min_pll_ref_divider = + init_data->min_pll_ref_divider; + calc_pll_cs->max_pll_ref_divider = + init_data->max_pll_ref_divider; + + if (init_data->num_fract_fb_divider_decimal_point == 0 || + init_data->num_fract_fb_divider_decimal_point_precision > + init_data->num_fract_fb_divider_decimal_point) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "The dec point num or precision is incorrect!"); + return false; + } + if (init_data->num_fract_fb_divider_decimal_point_precision == 0) { + dm_logger_write(calc_pll_cs->ctx->logger, LOG_ERROR, + "Incorrect fract feedback divider precision num!"); + return false; + } + + calc_pll_cs->fract_fb_divider_decimal_points_num = + init_data->num_fract_fb_divider_decimal_point; + calc_pll_cs->fract_fb_divider_precision = + init_data->num_fract_fb_divider_decimal_point_precision; + calc_pll_cs->fract_fb_divider_factor = 1; + for (i = 0; i < calc_pll_cs->fract_fb_divider_decimal_points_num; ++i) + calc_pll_cs->fract_fb_divider_factor *= 10; + + calc_pll_cs->fract_fb_divider_precision_factor = 1; + for ( + i = 0; + i < (calc_pll_cs->fract_fb_divider_decimal_points_num - + calc_pll_cs->fract_fb_divider_precision); + ++i) + calc_pll_cs->fract_fb_divider_precision_factor *= 10; + + return true; +} + +bool dce110_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask) +{ + struct firmware_info fw_info = { { 0 } }; + struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi; + struct calc_pll_clock_source_init_data calc_pll_cs_init_data; + + clk_src->base.ctx = ctx; + clk_src->bios = bios; + clk_src->base.id = id; + clk_src->base.funcs = &dce110_clk_src_funcs; + + clk_src->regs = regs; + clk_src->cs_shift = cs_shift; + clk_src->cs_mask = cs_mask; + + if (clk_src->bios->funcs->get_firmware_info( + clk_src->bios, &fw_info) != BP_RESULT_OK) { + ASSERT_CRITICAL(false); + goto unexpected_failure; + } + + clk_src->ext_clk_khz = + fw_info.external_clock_source_frequency_for_dp; + + switch (clk_src->base.ctx->dce_version) { + case DCE_VERSION_8_0: + case DCE_VERSION_10_0: + case DCE_VERSION_11_0: + + /* structure normally used with PLL ranges from ATOMBIOS; DS on by default */ + calc_pll_cs_init_data.bp = bios; + calc_pll_cs_init_data.min_pix_clk_pll_post_divider = 1; + calc_pll_cs_init_data.max_pix_clk_pll_post_divider = + clk_src->cs_mask->PLL_POST_DIV_PIXCLK; + calc_pll_cs_init_data.min_pll_ref_divider = 1; + calc_pll_cs_init_data.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV; + /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ + calc_pll_cs_init_data.min_override_input_pxl_clk_pll_freq_khz = 0; + /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ + calc_pll_cs_init_data.max_override_input_pxl_clk_pll_freq_khz = 0; + /*numberOfFractFBDividerDecimalPoints*/ + calc_pll_cs_init_data.num_fract_fb_divider_decimal_point = + FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM; + /*number of decimal point to round off for fractional feedback divider value*/ + calc_pll_cs_init_data.num_fract_fb_divider_decimal_point_precision = + FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM; + calc_pll_cs_init_data.ctx = ctx; + + /*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */ + calc_pll_cs_init_data_hdmi.bp = bios; + calc_pll_cs_init_data_hdmi.min_pix_clk_pll_post_divider = 1; + calc_pll_cs_init_data_hdmi.max_pix_clk_pll_post_divider = + clk_src->cs_mask->PLL_POST_DIV_PIXCLK; + calc_pll_cs_init_data_hdmi.min_pll_ref_divider = 1; + calc_pll_cs_init_data_hdmi.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV; + /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ + calc_pll_cs_init_data_hdmi.min_override_input_pxl_clk_pll_freq_khz = 13500; + /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ + calc_pll_cs_init_data_hdmi.max_override_input_pxl_clk_pll_freq_khz = 27000; + /*numberOfFractFBDividerDecimalPoints*/ + calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point = + FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM; + /*number of decimal point to round off for fractional feedback divider value*/ + calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point_precision = + FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM; + calc_pll_cs_init_data_hdmi.ctx = ctx; + + clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency; + + if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL) + return true; + + /* PLL only from here on */ + ss_info_from_atombios_create(clk_src); + + if (!calc_pll_max_vco_construct( + &clk_src->calc_pll, + &calc_pll_cs_init_data)) { + ASSERT_CRITICAL(false); + goto unexpected_failure; + } + + if (clk_src->ref_freq_khz == 48000) { + calc_pll_cs_init_data_hdmi. + min_override_input_pxl_clk_pll_freq_khz = 24000; + calc_pll_cs_init_data_hdmi. + max_override_input_pxl_clk_pll_freq_khz = 48000; + } else if (clk_src->ref_freq_khz == 100000) { + calc_pll_cs_init_data_hdmi. + min_override_input_pxl_clk_pll_freq_khz = 25000; + calc_pll_cs_init_data_hdmi. + max_override_input_pxl_clk_pll_freq_khz = 50000; + } + + if (!calc_pll_max_vco_construct( + &clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) { + ASSERT_CRITICAL(false); + goto unexpected_failure; + } + break; + default: + break; + } + + return true; + +unexpected_failure: + return false; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h new file mode 100644 index 000000000000..067e4ac0e67a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -0,0 +1,109 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_CLOCK_SOURCE_DCE_H__ +#define __DC_CLOCK_SOURCE_DCE_H__ + +#include "../inc/clock_source.h" + +#define TO_DCE110_CLK_SRC(clk_src)\ + container_of(clk_src, struct dce110_clk_src, base) + +#define CS_COMMON_REG_LIST_DCE_100_110(id) \ + SRI(RESYNC_CNTL, PIXCLK, id), \ + SRI(PLL_CNTL, BPHYC_PLL, id) + +#define CS_COMMON_REG_LIST_DCE_80(id) \ + SRI(RESYNC_CNTL, PIXCLK, id), \ + SRI(PLL_CNTL, DCCG_PLL, id) + +#define CS_COMMON_REG_LIST_DCE_112(id) \ + SRI(PIXCLK_RESYNC_CNTL, PHYPLL, id) + +#define CS_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ + CS_SF(PLL_CNTL, PLL_REF_DIV_SRC, mask_sh),\ + CS_SF(PIXCLK1_RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, mask_sh),\ + CS_SF(PLL_POST_DIV, PLL_POST_DIV_PIXCLK, mask_sh),\ + CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh),\ + +#define CS_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh),\ + +#define CS_REG_FIELD_LIST(type) \ + type PLL_REF_DIV_SRC; \ + type DCCG_DEEP_COLOR_CNTL1; \ + type PHYPLLA_DCCG_DEEP_COLOR_CNTL; \ + type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \ + type PLL_POST_DIV_PIXCLK; \ + type PLL_REF_DIV; \ + +struct dce110_clk_src_shift { + CS_REG_FIELD_LIST(uint8_t) +}; + +struct dce110_clk_src_mask{ + CS_REG_FIELD_LIST(uint32_t) +}; + +struct dce110_clk_src_regs { + uint32_t RESYNC_CNTL; + uint32_t PIXCLK_RESYNC_CNTL; + uint32_t PLL_CNTL; +}; + +struct dce110_clk_src { + struct clock_source base; + const struct dce110_clk_src_regs *regs; + const struct dce110_clk_src_mask *cs_mask; + const struct dce110_clk_src_shift *cs_shift; + struct dc_bios *bios; + + struct spread_spectrum_data *dp_ss_params; + uint32_t dp_ss_params_cnt; + struct spread_spectrum_data *hdmi_ss_params; + uint32_t hdmi_ss_params_cnt; + struct spread_spectrum_data *dvi_ss_params; + uint32_t dvi_ss_params_cnt; + + uint32_t ext_clk_khz; + uint32_t ref_freq_khz; + + struct calc_pll_clock_source calc_pll; + struct calc_pll_clock_source calc_pll_hdmi; +}; + +bool dce110_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c new file mode 100644 index 000000000000..dd1cf5e6e949 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -0,0 +1,195 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_hwseq.h" +#include "reg_helper.h" +#include "hw_sequencer.h" + +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + +void dce_enable_fe_clock(struct dce_hwseq *hws, + unsigned int fe_inst, bool enable) +{ + REG_UPDATE(DCFE_CLOCK_CONTROL[fe_inst], + DCFE_CLOCK_ENABLE, enable); +} + +void dce_pipe_control_lock(struct dce_hwseq *hws, + unsigned int blnd_inst, + enum pipe_lock_control control_mask, + bool lock) +{ + uint32_t lock_val = lock ? 1 : 0; + uint32_t dcp_grph, scl, dcp_grph_surf, blnd, update_lock_mode; + + uint32_t val = REG_GET_5(BLND_V_UPDATE_LOCK[blnd_inst], + BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, + BLND_SCL_V_UPDATE_LOCK, &scl, + BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, &dcp_grph_surf, + BLND_BLND_V_UPDATE_LOCK, &blnd, + BLND_V_UPDATE_LOCK_MODE, &update_lock_mode); + + if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) + dcp_grph = lock_val; + + if (control_mask & PIPE_LOCK_CONTROL_SCL) + scl = lock_val; + + if (control_mask & PIPE_LOCK_CONTROL_SURFACE) + dcp_grph_surf = lock_val; + + if (control_mask & PIPE_LOCK_CONTROL_BLENDER) + blnd = lock_val; + + if (control_mask & PIPE_LOCK_CONTROL_MODE) + update_lock_mode = lock_val; + + REG_SET_5(BLND_V_UPDATE_LOCK[blnd_inst], val, + BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, + BLND_SCL_V_UPDATE_LOCK, scl, + BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, dcp_grph_surf, + BLND_BLND_V_UPDATE_LOCK, blnd, + BLND_V_UPDATE_LOCK_MODE, update_lock_mode); + + if (hws->wa.blnd_crtc_trigger) + if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) { + uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]); + REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value); + } +} + +void dce_set_blender_mode(struct dce_hwseq *hws, + unsigned int blnd_inst, + enum blnd_mode mode) +{ + uint32_t feedthrough = 1; + uint32_t blnd_mode = 0; + uint32_t multiplied_mode = 0; + uint32_t alpha_mode = 2; + + switch (mode) { + case BLND_MODE_OTHER_PIPE: + feedthrough = 0; + blnd_mode = 1; + alpha_mode = 0; + break; + case BLND_MODE_BLENDING: + feedthrough = 0; + blnd_mode = 2; + alpha_mode = 0; + multiplied_mode = 1; + break; + case BLND_MODE_CURRENT_PIPE: + default: + if (REG(BLND_CONTROL[blnd_inst]) == REG(BLNDV_CONTROL) || + blnd_inst == 0) + feedthrough = 0; + break; + } + + REG_UPDATE_4(BLND_CONTROL[blnd_inst], + BLND_FEEDTHROUGH_EN, feedthrough, + BLND_ALPHA_MODE, alpha_mode, + BLND_MODE, blnd_mode, + BLND_MULTIPLIED_MODE, multiplied_mode); +} + + +static void dce_disable_sram_shut_down(struct dce_hwseq *hws) +{ + if (REG(DC_MEM_GLOBAL_PWR_REQ_CNTL)) + REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL, + DC_MEM_GLOBAL_PWR_REQ_DIS, 1); +} + +static void dce_underlay_clock_enable(struct dce_hwseq *hws) +{ + /* todo: why do we need this at boot? is dce_enable_fe_clock enough? */ + if (REG(DCFEV_CLOCK_CONTROL)) + REG_UPDATE(DCFEV_CLOCK_CONTROL, + DCFEV_CLOCK_ENABLE, 1); +} + +static void enable_hw_base_light_sleep(void) +{ + /* TODO: implement */ +} + +static void disable_sw_manual_control_light_sleep(void) +{ + /* TODO: implement */ +} + +void dce_clock_gating_power_up(struct dce_hwseq *hws, + bool enable) +{ + if (enable) { + enable_hw_base_light_sleep(); + disable_sw_manual_control_light_sleep(); + } else { + dce_disable_sram_shut_down(hws); + dce_underlay_clock_enable(hws); + } +} + +void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, + struct clock_source *clk_src, + unsigned int tg_inst) +{ + if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) { + REG_UPDATE(PIXEL_RATE_CNTL[tg_inst], + DP_DTO0_ENABLE, 1); + + } else if (clk_src->id >= CLOCK_SOURCE_COMBO_PHY_PLL0) { + uint32_t rate_source = clk_src->id - CLOCK_SOURCE_COMBO_PHY_PLL0; + + REG_UPDATE_2(PHYPLL_PIXEL_RATE_CNTL[tg_inst], + PHYPLL_PIXEL_RATE_SOURCE, rate_source, + PIXEL_RATE_PLL_SOURCE, 0); + + REG_UPDATE(PIXEL_RATE_CNTL[tg_inst], + DP_DTO0_ENABLE, 0); + + } else if (clk_src->id <= CLOCK_SOURCE_ID_PLL2) { + uint32_t rate_source = clk_src->id - CLOCK_SOURCE_ID_PLL0; + + REG_UPDATE_2(PIXEL_RATE_CNTL[tg_inst], + PIXEL_RATE_SOURCE, rate_source, + DP_DTO0_ENABLE, 0); + + if (REG(PHYPLL_PIXEL_RATE_CNTL[tg_inst])) + REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst], + PIXEL_RATE_PLL_SOURCE, 1); + } else { + DC_ERR("unknown clock source"); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h new file mode 100644 index 000000000000..4af8d560a7ee --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -0,0 +1,250 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DCE_HWSEQ_H__ +#define __DCE_HWSEQ_H__ + +#include "hw_sequencer.h" + +#define HWSEQ_DCEF_REG_LIST_DCE8() \ + .DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[2] = mmCRTC2_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[3] = mmCRTC3_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[4] = mmCRTC4_CRTC_DCFE_CLOCK_CONTROL, \ + .DCFE_CLOCK_CONTROL[5] = mmCRTC5_CRTC_DCFE_CLOCK_CONTROL + +#define HWSEQ_DCEF_REG_LIST() \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 0), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 1), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 2), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 3), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 4), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 5), \ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL) + +#define HWSEQ_BLND_REG_LIST() \ + SRII(BLND_V_UPDATE_LOCK, BLND, 0), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 1), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 2), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 3), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 4), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 5), \ + SRII(BLND_CONTROL, BLND, 0), \ + SRII(BLND_CONTROL, BLND, 1), \ + SRII(BLND_CONTROL, BLND, 2), \ + SRII(BLND_CONTROL, BLND, 3), \ + SRII(BLND_CONTROL, BLND, 4), \ + SRII(BLND_CONTROL, BLND, 5) + +#define HWSEQ_PIXEL_RATE_REG_LIST(blk) \ + SRII(PIXEL_RATE_CNTL, blk, 0), \ + SRII(PIXEL_RATE_CNTL, blk, 1), \ + SRII(PIXEL_RATE_CNTL, blk, 2), \ + SRII(PIXEL_RATE_CNTL, blk, 3), \ + SRII(PIXEL_RATE_CNTL, blk, 4), \ + SRII(PIXEL_RATE_CNTL, blk, 5) + +#define HWSEQ_PHYPLL_REG_LIST(blk) \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 0), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 1), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 2), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 3), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 4), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 5) + +#define HWSEQ_DCE11_REG_LIST_BASE() \ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SR(DCFEV_CLOCK_CONTROL), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 0), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 1), \ + SRII(CRTC_H_BLANK_START_END, CRTC, 0),\ + SRII(CRTC_H_BLANK_START_END, CRTC, 1),\ + SRII(BLND_V_UPDATE_LOCK, BLND, 0),\ + SRII(BLND_V_UPDATE_LOCK, BLND, 1),\ + SRII(BLND_CONTROL, BLND, 0),\ + SRII(BLND_CONTROL, BLND, 1),\ + SR(BLNDV_CONTROL),\ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + +#define HWSEQ_DCE8_REG_LIST() \ + HWSEQ_DCEF_REG_LIST_DCE8(), \ + HWSEQ_BLND_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + +#define HWSEQ_DCE10_REG_LIST() \ + HWSEQ_DCEF_REG_LIST(), \ + HWSEQ_BLND_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + +#define HWSEQ_ST_REG_LIST() \ + HWSEQ_DCE11_REG_LIST_BASE(), \ + .DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \ + .CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \ + .BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \ + .BLND_CONTROL[2] = mmBLNDV_CONTROL, + +#define HWSEQ_CZ_REG_LIST() \ + HWSEQ_DCE11_REG_LIST_BASE(), \ + SRII(DCFE_CLOCK_CONTROL, DCFE, 2), \ + SRII(CRTC_H_BLANK_START_END, CRTC, 2), \ + SRII(BLND_V_UPDATE_LOCK, BLND, 2), \ + SRII(BLND_CONTROL, BLND, 2), \ + .DCFE_CLOCK_CONTROL[3] = mmDCFEV_CLOCK_CONTROL, \ + .CRTC_H_BLANK_START_END[3] = mmCRTCV_H_BLANK_START_END, \ + .BLND_V_UPDATE_LOCK[3] = mmBLNDV_V_UPDATE_LOCK, \ + .BLND_CONTROL[3] = mmBLNDV_CONTROL + +#define HWSEQ_DCE112_REG_LIST() \ + HWSEQ_DCE10_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ + HWSEQ_PHYPLL_REG_LIST(CRTC) + +struct dce_hwseq_registers { + uint32_t DCFE_CLOCK_CONTROL[6]; + uint32_t DCFEV_CLOCK_CONTROL; + uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL; + uint32_t BLND_V_UPDATE_LOCK[6]; + uint32_t BLND_CONTROL[6]; + uint32_t BLNDV_CONTROL; + + uint32_t CRTC_H_BLANK_START_END[6]; + uint32_t PIXEL_RATE_CNTL[6]; + uint32_t PHYPLL_PIXEL_RATE_CNTL[6]; +}; + /* set field name */ +#define HWS_SF(blk_name, reg_name, field_name, post_fix)\ + .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix + +#define HWS_SF1(blk_name, reg_name, field_name, post_fix)\ + .field_name = blk_name ## reg_name ## __ ## blk_name ## field_name ## post_fix + + +#define HWSEQ_DCEF_MASK_SH_LIST(mask_sh, blk)\ + HWS_SF(blk, CLOCK_CONTROL, DCFE_CLOCK_ENABLE, mask_sh),\ + SF(DC_MEM_GLOBAL_PWR_REQ_CNTL, DC_MEM_GLOBAL_PWR_REQ_DIS, mask_sh) + +#define HWSEQ_BLND_MASK_SH_LIST(mask_sh, blk)\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_BLND_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(blk, V_UPDATE_LOCK, BLND_V_UPDATE_LOCK_MODE, mask_sh),\ + HWS_SF(blk, CONTROL, BLND_FEEDTHROUGH_EN, mask_sh),\ + HWS_SF(blk, CONTROL, BLND_ALPHA_MODE, mask_sh),\ + HWS_SF(blk, CONTROL, BLND_MODE, mask_sh),\ + HWS_SF(blk, CONTROL, BLND_MULTIPLIED_MODE, mask_sh) + +#define HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, blk)\ + HWS_SF1(blk, PIXEL_RATE_CNTL, PIXEL_RATE_SOURCE, mask_sh),\ + HWS_SF(blk, PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) + +#define HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, blk)\ + HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh),\ + HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh) + +#define HWSEQ_DCE8_MASK_SH_LIST(mask_sh)\ + .DCFE_CLOCK_ENABLE = CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE ## mask_sh, \ + HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ + HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + +#define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\ + HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + +#define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ + SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + +#define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) + +#define HWSEQ_REG_FIED_LIST(type) \ + type DCFE_CLOCK_ENABLE; \ + type DCFEV_CLOCK_ENABLE; \ + type DC_MEM_GLOBAL_PWR_REQ_DIS; \ + type BLND_DCP_GRPH_V_UPDATE_LOCK; \ + type BLND_SCL_V_UPDATE_LOCK; \ + type BLND_DCP_GRPH_SURF_V_UPDATE_LOCK; \ + type BLND_BLND_V_UPDATE_LOCK; \ + type BLND_V_UPDATE_LOCK_MODE; \ + type BLND_FEEDTHROUGH_EN; \ + type BLND_ALPHA_MODE; \ + type BLND_MODE; \ + type BLND_MULTIPLIED_MODE; \ + type DP_DTO0_ENABLE; \ + type PIXEL_RATE_SOURCE; \ + type PHYPLL_PIXEL_RATE_SOURCE; \ + type PIXEL_RATE_PLL_SOURCE; \ + +struct dce_hwseq_shift { + HWSEQ_REG_FIED_LIST(uint8_t) +}; + +struct dce_hwseq_mask { + HWSEQ_REG_FIED_LIST(uint32_t) +}; + +struct dce_hwseq_wa { + bool blnd_crtc_trigger; +}; + +struct dce_hwseq { + struct dc_context *ctx; + const struct dce_hwseq_registers *regs; + const struct dce_hwseq_shift *shifts; + const struct dce_hwseq_mask *masks; + struct dce_hwseq_wa wa; +}; + +enum blnd_mode { + BLND_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */ + BLND_MODE_OTHER_PIPE, /* Data from other pipe only */ + BLND_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */ +}; + +void dce_enable_fe_clock(struct dce_hwseq *hwss, + unsigned int inst, bool enable); + +void dce_pipe_control_lock(struct dce_hwseq *hws, + unsigned int blnd_inst, + enum pipe_lock_control control_mask, + bool lock); + +void dce_set_blender_mode(struct dce_hwseq *hws, + unsigned int blnd_inst, enum blnd_mode mode); + +void dce_clock_gating_power_up(struct dce_hwseq *hws, + bool enable); + +void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, + struct clock_source *clk_src, + unsigned int tg_inst); +#endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c new file mode 100644 index 000000000000..86e55d028cbf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -0,0 +1,2176 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dce_link_encoder.h" +#include "stream_encoder.h" +#include "i2caux_interface.h" +#include "dc_bios_types.h" + +#include "gpio_service_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +#include "dce/dce_11_0_enum.h" + +#ifndef ATOM_S2_CURRENT_BL_LEVEL_MASK +#define ATOM_S2_CURRENT_BL_LEVEL_MASK 0x0000FF00L +#define ATOM_S2_VRI_BRIGHT_ENABLE 0x20000000L +#endif + +#ifndef ATOM_S2_CURRENT_BL_LEVEL_SHIFT +#define ATOM_S2_CURRENT_BL_LEVEL_SHIFT 8 +#endif + +#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK +#define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L +#endif + +#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT +#define HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT 0x1c +#endif + +#define CTX \ + enc110->base.ctx + +#define REG(reg)\ + (enc110->link_regs->reg) + +#define AUX_REG(reg)\ + (enc110->aux_regs->reg) + +#define HPD_REG(reg)\ + (enc110->hpd_regs->reg) + +/* For current ASICs pixel clock - 600MHz */ +#define MAX_ENCODER_CLK 600000 + +#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 594000 + +#define DEFAULT_AUX_MAX_DATA_SIZE 16 +#define AUX_MAX_DEFER_WRITE_RETRY 20 +/* + * @brief + * Trigger Source Select + * ASIC-dependent, actual values for register programming + */ +#define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x0 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x1 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x2 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x4 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 + +/* all values are in milliseconds */ +/* For eDP, after power-up/power/down, + * 300/500 msec max. delay from LCDVCC to black video generation */ +#define PANEL_POWER_UP_TIMEOUT 300 +#define PANEL_POWER_DOWN_TIMEOUT 500 +#define HPD_CHECK_INTERVAL 10 + +/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ +#define TMDS_MIN_PIXEL_CLOCK 25000 +/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ +#define TMDS_MAX_PIXEL_CLOCK 165000 +/* For current ASICs pixel clock - 600MHz */ +#define MAX_ENCODER_CLOCK 600000 + +/* Set the ABM Pipe */ +#define MCP_ABM_PIPE_SET 0x66 +/* Set the ABM level */ +#define MCP_ABM_LEVEL_SET 0x65 +/* Set backlight level */ +#define MCP_BL_SET 0x67 + +/* PSR related commands */ +#define PSR_ENABLE 0x20 +#define PSR_EXIT 0x21 +#define PSR_SET 0x23 + +/*TODO: Used for psr wakeup for set backlight level*/ +static unsigned int psr_crtc_offset; + +/* registers setting needs to be save and restored used at InitBacklight */ +static struct dce110_abm_backlight_registers stored_backlight_registers; + +enum { + DP_MST_UPDATE_MAX_RETRY = 50 +}; + +#define DIG_REG(reg)\ + (reg + enc110->offsets.dig) + +#define DP_REG(reg)\ + (reg + enc110->offsets.dp) + +static const struct link_encoder_funcs dce110_lnk_enc_funcs = { + .validate_output_with_stream = + dce110_link_encoder_validate_output_with_stream, + .hw_init = dce110_link_encoder_hw_init, + .setup = dce110_link_encoder_setup, + .enable_tmds_output = dce110_link_encoder_enable_tmds_output, + .enable_dp_output = dce110_link_encoder_enable_dp_output, + .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output, + .disable_output = dce110_link_encoder_disable_output, + .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dce110_link_encoder_update_mst_stream_allocation_table, + .set_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level, + .set_dmcu_backlight_level = + dce110_link_encoder_set_dmcu_backlight_level, + .init_dmcu_backlight_settings = + dce110_link_encoder_init_dmcu_backlight_settings, + .set_dmcu_abm_level = dce110_link_encoder_set_dmcu_abm_level, + .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable, + .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr, + .backlight_control = dce110_link_encoder_edp_backlight_control, + .power_control = dce110_link_encoder_edp_power_control, + .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dce110_link_encoder_enable_hpd, + .disable_hpd = dce110_link_encoder_disable_hpd, + .destroy = dce110_link_encoder_destroy +}; + + +static enum bp_result link_transmitter_control( + struct dce110_link_encoder *enc110, + struct bp_transmitter_control *cntl) +{ + enum bp_result result; + struct dc_bios *bp = enc110->base.ctx->dc_bios; + + result = bp->funcs->transmitter_control(bp, cntl); + + return result; +} + +static void enable_phy_bypass_mode( + struct dce110_link_encoder *enc110, + bool enable) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable); + +} + +static void disable_prbs_symbols( + struct dce110_link_encoder *enc110, + bool disable) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_UPDATE_4(DP_DPHY_CNTL, + DPHY_ATEST_SEL_LANE0, disable, + DPHY_ATEST_SEL_LANE1, disable, + DPHY_ATEST_SEL_LANE2, disable, + DPHY_ATEST_SEL_LANE3, disable); +} + +static void disable_prbs_mode( + struct dce110_link_encoder *enc110) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0); +} + +static void program_pattern_symbols( + struct dce110_link_encoder *enc110, + uint16_t pattern_symbols[8]) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_SET_3(DP_DPHY_SYM0, 0, + DPHY_SYM1, pattern_symbols[0], + DPHY_SYM2, pattern_symbols[1], + DPHY_SYM3, pattern_symbols[2]); + + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_SET_3(DP_DPHY_SYM1, 0, + DPHY_SYM4, pattern_symbols[3], + DPHY_SYM5, pattern_symbols[4], + DPHY_SYM6, pattern_symbols[5]); + + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_SET_2(DP_DPHY_SYM2, 0, + DPHY_SYM7, pattern_symbols[6], + DPHY_SYM8, pattern_symbols[7]); +} + +static void set_dp_phy_pattern_d102( + struct dce110_link_encoder *enc110) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc110, false); + + /* For 10-bit PRBS or debug symbols + * please use the following sequence: */ + + /* Enable debug symbols on the lanes */ + + disable_prbs_symbols(enc110, true); + + /* Disable PRBS mode, + * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ + + disable_prbs_mode(enc110); + + /* Program debug symbols to be output */ + { + uint16_t pattern_symbols[8] = { + 0x2AA, 0x2AA, 0x2AA, 0x2AA, + 0x2AA, 0x2AA, 0x2AA, 0x2AA + }; + + program_pattern_symbols(enc110, pattern_symbols); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc110, true); +} + +static void set_link_training_complete( + struct dce110_link_encoder *enc110, + bool complete) +{ + /* This register resides in DP back end block; + * transmitter is used for the offset */ + + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete); + +} + +void dce110_link_encoder_set_dp_phy_pattern_training_pattern( + struct link_encoder *enc, + uint32_t index) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + /* Write Training Pattern */ + + REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index); + + /* Set HW Register Training Complete to false */ + + set_link_training_complete(enc110, false); + + /* Disable PHY Bypass mode to output Training Pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* Disable PRBS mode, + * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ + + disable_prbs_mode(enc110); +} + +static void set_dp_phy_pattern_symbol_error( + struct dce110_link_encoder *enc110) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + uint32_t value = 0x0; + + enable_phy_bypass_mode(enc110, false); + + /* program correct panel mode*/ + { + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + /*DCE 120 does not have this reg*/ + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); + } + + /* A PRBS23 pattern is used for most DP electrical measurements. */ + + /* Enable PRBS symbols on the lanes */ + + disable_prbs_symbols(enc110, false); + + /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ + { + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 1, + DPHY_PRBS_EN, 1); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc110, true); +} + +static void set_dp_phy_pattern_prbs7( + struct dce110_link_encoder *enc110) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* A PRBS7 pattern is used for most DP electrical measurements. */ + + /* Enable PRBS symbols on the lanes */ + + disable_prbs_symbols(enc110, false); + + /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ + { + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 0, + DPHY_PRBS_EN, 1); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc110, true); +} + +static void set_dp_phy_pattern_80bit_custom( + struct dce110_link_encoder *enc110, + const uint8_t *pattern) +{ + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc110, false); + + /* Enable debug symbols on the lanes */ + + disable_prbs_symbols(enc110, true); + + /* Enable PHY bypass mode to enable the test pattern */ + /* TODO is it really needed ? */ + + enable_phy_bypass_mode(enc110, true); + + /* Program 80 bit custom pattern */ + { + uint16_t pattern_symbols[8]; + + pattern_symbols[0] = + ((pattern[1] & 0x03) << 8) | pattern[0]; + pattern_symbols[1] = + ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f); + pattern_symbols[2] = + ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f); + pattern_symbols[3] = + (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03); + pattern_symbols[4] = + ((pattern[6] & 0x03) << 8) | pattern[5]; + pattern_symbols[5] = + ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f); + pattern_symbols[6] = + ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f); + pattern_symbols[7] = + (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03); + + program_pattern_symbols(enc110, pattern_symbols); + } + + /* Enable phy bypass mode to enable the test pattern */ + + enable_phy_bypass_mode(enc110, true); +} + +static void set_dp_phy_pattern_hbr2_compliance( + struct dce110_link_encoder *enc110) +{ + + /* previously there is a register DP_HBR2_EYE_PATTERN + * that is enabled to get the pattern. + * But it does not work with the latest spec change, + * so we are programming the following registers manually. + * + * The following settings have been confirmed + * by Nick Chorney and Sandra Liu */ + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* Setup DIG encoder in DP SST mode */ + + enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT); + + /* program correct panel mode*/ + { + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0x0); + } + + /* no vbid after BS (SR) + * DP_LINK_FRAMING_CNTL changed history Sandra Liu + * 11000260 / 11000104 / 110000FC */ + + /* TODO DP_LINK_FRAMING_CNTL should always use hardware default value + * output except output hbr2_compliance pattern for physical PHY + * measurement. This is not normal usage case. SW should reset this + * register to hardware default value after end use of HBR2 eye + */ + BREAK_TO_DEBUGGER(); + /* TODO: do we still need this, find out at compliance test + addr = mmDP_LINK_FRAMING_CNTL + fe_addr_offset; + + value = dal_read_reg(ctx, addr); + + set_reg_field_value(value, 0xFC, + DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL); + set_reg_field_value(value, 1, + DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE); + set_reg_field_value(value, 1, + DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE); + + dal_write_reg(ctx, addr, value); + */ + /* swap every BS with SR */ + + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); + + /*TODO add support for this test pattern + * support_dp_hbr2_eye_pattern + */ + + /* set link training complete */ + set_link_training_complete(enc110, true); + /* do not enable video stream */ + + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); +} + +static void set_dp_phy_pattern_passthrough_mode( + struct dce110_link_encoder *enc110, + enum dp_panel_mode panel_mode) +{ + uint32_t value; + + /* program correct panel mode */ + { + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + value = REG_READ(DP_DPHY_INTERNAL_CTRL); + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + value = 0x1; + break; + case DP_PANEL_MODE_SPECIAL: + value = 0x11; + break; + default: + value = 0x0; + break; + } + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); + } + + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF); + + /* set link training complete */ + + set_link_training_complete(enc110, true); + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* Disable PRBS mode, + * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ + + disable_prbs_mode(enc110); +} + +/* return value is bit-vector */ +static uint8_t get_frontend_source( + enum engine_id engine) +{ + switch (engine) { + case ENGINE_ID_DIGA: + return DCE110_DIG_FE_SOURCE_SELECT_DIGA; + case ENGINE_ID_DIGB: + return DCE110_DIG_FE_SOURCE_SELECT_DIGB; + case ENGINE_ID_DIGC: + return DCE110_DIG_FE_SOURCE_SELECT_DIGC; + case ENGINE_ID_DIGD: + return DCE110_DIG_FE_SOURCE_SELECT_DIGD; + case ENGINE_ID_DIGE: + return DCE110_DIG_FE_SOURCE_SELECT_DIGE; + case ENGINE_ID_DIGF: + return DCE110_DIG_FE_SOURCE_SELECT_DIGF; + default: + ASSERT_CRITICAL(false); + return DCE110_DIG_FE_SOURCE_SELECT_INVALID; + } +} + +static void configure_encoder( + struct dce110_link_encoder *enc110, + const struct dc_link_settings *link_settings) +{ + /* set number of lanes */ + + REG_SET(DP_CONFIG, 0, + DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE); + + /* setup scrambler */ + REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); +} + +static bool is_panel_powered_on(struct dce110_link_encoder *enc110) +{ + bool ret; + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); + ret = value; + + return ret == 1; +} + + +/* TODO duplicate of dc_link.c version */ +static struct gpio *get_hpd_gpio(const struct link_encoder *enc) +{ + enum bp_result bp_result; + struct dc_bios *dcb = enc->ctx->dc_bios; + struct graphics_object_hpd_info hpd_info; + struct gpio_pin_info pin_info; + + if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK) + return NULL; + + bp_result = dcb->funcs->get_gpio_pin_info(dcb, + hpd_info.hpd_int_gpio_uid, &pin_info); + + if (bp_result != BP_RESULT_OK) { + ASSERT(bp_result == BP_RESULT_NORECORD); + return NULL; + } + + return dal_gpio_service_create_irq( + enc->ctx->gpio_service, + pin_info.offset, + pin_info.mask); +} + +/* + * @brief + * eDP only. + */ +static void link_encoder_edp_wait_for_hpd_ready( + struct dce110_link_encoder *enc110, + bool power_up) +{ + struct dc_context *ctx = enc110->base.ctx; + struct graphics_object_id connector = enc110->base.connector; + struct gpio *hpd; + bool edp_hpd_high = false; + uint32_t time_elapsed = 0; + uint32_t timeout = power_up ? + PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; + + if (dal_graphics_object_id_get_connector_id(connector) != + CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (!power_up) + /* from KV, we will not HPD low after turning off VCC - + * instead, we will check the SW timer in power_up(). */ + return; + + /* when we power on/off the eDP panel, + * we need to wait until SENSE bit is high/low */ + + /* obtain HPD */ + /* TODO what to do with this? */ + hpd = get_hpd_gpio(&enc110->base); + + if (!hpd) { + BREAK_TO_DEBUGGER(); + return; + } + + dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); + + /* wait until timeout or panel detected */ + + do { + uint32_t detected = 0; + + dal_gpio_get_value(hpd, &detected); + + if (!(detected ^ power_up)) { + edp_hpd_high = true; + break; + } + + msleep(HPD_CHECK_INTERVAL); + + time_elapsed += HPD_CHECK_INTERVAL; + } while (time_elapsed < timeout); + + dal_gpio_close(hpd); + + dal_gpio_destroy_irq(&hpd); + + if (false == edp_hpd_high) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: wait timed out!\n", __func__); + } +} + +/* + * @brief + * eDP only. Control the power of the eDP panel. + */ +void dce110_link_encoder_edp_power_control( + struct link_encoder *enc, + bool power_up) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result bp_result; + + if (dal_graphics_object_id_get_connector_id(enc110->base.connector) != + CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if ((power_up && !is_panel_powered_on(enc110)) || + (!power_up && is_panel_powered_on(enc110))) { + + /* Send VBIOS command to prompt eDP panel power */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + + cntl.action = power_up ? + TRANSMITTER_CONTROL_POWER_ON : + TRANSMITTER_CONTROL_POWER_OFF; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; + cntl.coherent = false; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = enc110->base.hpd_source; + + bp_result = link_transmitter_control(enc110, &cntl); + + if (BP_RESULT_OK != bp_result) { + + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Panel Power bp_result: %d\n", + __func__, bp_result); + } + } else { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Skipping Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + } + + link_encoder_edp_wait_for_hpd_ready(enc110, true); +} + +static void aux_initialize( + struct dce110_link_encoder *enc110) +{ + struct dc_context *ctx = enc110->base.ctx; + enum hpd_source_id hpd_source = enc110->base.hpd_source; + uint32_t addr = AUX_REG(AUX_CONTROL); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL); + set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN); + dm_write_reg(ctx, addr, value); + + addr = AUX_REG(AUX_DPHY_RX_CONTROL0); + value = dm_read_reg(ctx, addr); + + /* 1/4 window (the maximum allowed) */ + set_reg_field_value(value, 1, + AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW); + dm_write_reg(ctx, addr, value); + +} + +/*todo: cloned in stream enc, fix*/ +static bool is_panel_backlight_on(struct dce110_link_encoder *enc110) +{ + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); + + return value; +} + +/*todo: cloned in stream enc, fix*/ +/* + * @brief + * eDP only. Control the backlight of the eDP panel + */ +void dce110_link_encoder_edp_backlight_control( + struct link_encoder *enc, + bool enable) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + + if (dal_graphics_object_id_get_connector_id(enc110->base.connector) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (enable && is_panel_backlight_on(enc110)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered up. Do nothing.\n", + __func__); + return; + } + + if (!enable && !is_panel_powered_on(enc110)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered down. Do nothing.\n", + __func__); + return; + } + + /* Send VBIOS command to control eDP panel backlight */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: backlight action: %s\n", + __func__, (enable ? "On":"Off")); + + cntl.action = enable ? + TRANSMITTER_CONTROL_BACKLIGHT_ON : + TRANSMITTER_CONTROL_BACKLIGHT_OFF; + /*cntl.engine_id = ctx->engine;*/ + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; + /*todo: unhardcode*/ + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = enc110->base.hpd_source; + + /* For eDP, the following delays might need to be considered + * after link training completed: + * idle period - min. accounts for required BS-Idle pattern, + * max. allows for source frame synchronization); + * 50 msec max. delay from valid video data from source + * to video on dislpay or backlight enable. + * + * Disable the delay for now. + * Enable it in the future if necessary. + */ + /* dc_service_sleep_in_milliseconds(50); */ + link_transmitter_control(enc110, &cntl); +} + +static bool is_dig_enabled(const struct dce110_link_encoder *enc110) +{ + uint32_t value; + + REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value); + return value; +} + +static void link_encoder_disable(struct dce110_link_encoder *enc110) +{ + /* reset training pattern */ + REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0, + DPHY_TRAINING_PATTERN_SEL, 0); + + /* reset training complete */ + REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); + + /* reset panel mode */ + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0); +} + +static void hpd_initialize( + struct dce110_link_encoder *enc110) +{ + /* Associate HPD with DIG_BE */ + enum hpd_source_id hpd_source = enc110->base.hpd_source; + + REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source); +} + +bool dce110_link_encoder_validate_dvi_output( + const struct dce110_link_encoder *enc110, + enum signal_type connector_signal, + enum signal_type signal, + const struct dc_crtc_timing *crtc_timing) +{ + uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; + + if (enc110->base.features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK) + max_pixel_clock = enc110->base.features.max_pixel_clock; + + if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) + max_pixel_clock <<= 1; + + /* This handles the case of HDMI downgrade to DVI we don't want to + * we don't want to cap the pixel clock if the DDI is not DVI. + */ + if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && + connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + max_pixel_clock = enc110->base.features.max_pixel_clock; + + /* DVI only support RGB pixel encoding */ + if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) + return false; + + if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) + return false; + + if (crtc_timing->pix_clk_khz > max_pixel_clock) + return false; + + /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */ + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + case COLOR_DEPTH_888: + break; + case COLOR_DEPTH_101010: + case COLOR_DEPTH_161616: + if (signal != SIGNAL_TYPE_DVI_DUAL_LINK) + return false; + break; + default: + return false; + } + + return true; +} + +static bool dce110_link_encoder_validate_hdmi_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing, + int adjusted_pix_clk_khz) +{ + enum dc_color_depth max_deep_color = + enc110->base.features.max_hdmi_deep_color; + + if (max_deep_color > enc110->base.features.max_deep_color) + max_deep_color = enc110->base.features.max_deep_color; + + if (max_deep_color < crtc_timing->display_color_depth) + return false; + + if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) + return false; + + if ((adjusted_pix_clk_khz == 0) || + (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock) || + (adjusted_pix_clk_khz > enc110->base.features.max_pixel_clock)) + return false; + + /* DCE11 HW does not support 420 */ + if (!enc110->base.features.ycbcr420_supported && + crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + return false; + + return true; +} + +bool dce110_link_encoder_validate_rgb_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing) +{ + if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) + return false; + + if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) + return false; + + return true; +} + +bool dce110_link_encoder_validate_dp_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing) +{ + /* default RGB only */ + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) + return true; + + if (enc110->base.features.flags.bits.IS_YCBCR_CAPABLE) + return true; + + /* for DCE 8.x or later DP Y-only feature, + * we need ASIC cap + FeatureSupportDPYonly, not support 666 */ + if (crtc_timing->flags.Y_ONLY && + enc110->base.features.flags.bits.IS_YCBCR_CAPABLE && + crtc_timing->display_color_depth != COLOR_DEPTH_666) + return true; + + return false; +} + +bool dce110_link_encoder_validate_wireless_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing) +{ + if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) + return false; + + /* Wireless only supports YCbCr444 */ + if (crtc_timing->pixel_encoding == + PIXEL_ENCODING_YCBCR444) + return true; + + return false; +} + +bool dce110_link_encoder_construct( + struct dce110_link_encoder *enc110, + const struct encoder_init_data *init_data, + const struct dce110_link_enc_registers *link_regs, + const struct dce110_link_enc_aux_registers *aux_regs, + const struct dce110_link_enc_hpd_registers *hpd_regs) +{ + enc110->base.funcs = &dce110_lnk_enc_funcs; + enc110->base.ctx = init_data->ctx; + enc110->base.id = init_data->encoder; + + enc110->base.hpd_source = init_data->hpd_source; + enc110->base.connector = init_data->connector; + enc110->base.input_signals = SIGNAL_TYPE_ALL; + + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc110->base.features.flags.raw = 0; + + enc110->base.transmitter = init_data->transmitter; + + enc110->base.features.flags.bits.IS_AUDIO_CAPABLE = true; + + enc110->base.features.max_pixel_clock = + MAX_ENCODER_CLK; + + enc110->base.features.max_deep_color = COLOR_DEPTH_121212; + enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc110->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc110->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc110->link_regs = link_regs; + enc110->aux_regs = aux_regs; + enc110->hpd_regs = hpd_regs; + + switch (enc110->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc110->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc110->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc110->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc110->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc110->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc110->base.preferred_engine = ENGINE_ID_DIGF; + break; + default: + ASSERT_CRITICAL(false); + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + dm_logger_write(init_data->ctx->logger, LOG_I2C_AUX, + "Using channel: %s [%d]\n", + DECODE_CHANNEL_ID(init_data->channel), + init_data->channel); + + /* Override features with DCE-specific values */ + { + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = enc110->base.ctx->dc_bios->funcs; + + if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( + enc110->base.ctx->dc_bios, enc110->base.id, + &bp_cap_info)) + enc110->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_CAP; + } + /* test pattern 3 support */ + enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true; + + enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE = false; + /* + dal_adapter_service_is_feature_supported(as, + FEATURE_SUPPORT_DP_Y_ONLY); +*/ + enc110->base.features.flags.bits.IS_YCBCR_CAPABLE = true; + /* + dal_adapter_service_is_feature_supported(as, + FEATURE_SUPPORT_DP_YUV); + */ + return true; +} + +bool dce110_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + bool is_valid; + + switch (pipe_ctx->stream->signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + is_valid = dce110_link_encoder_validate_dvi_output( + enc110, + stream->sink->link->public.connector_signal, + pipe_ctx->stream->signal, + &stream->public.timing); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + is_valid = dce110_link_encoder_validate_hdmi_output( + enc110, + &stream->public.timing, + stream->phy_pix_clk); + break; + case SIGNAL_TYPE_RGB: + is_valid = dce110_link_encoder_validate_rgb_output( + enc110, &stream->public.timing); + break; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + is_valid = dce110_link_encoder_validate_dp_output( + enc110, &stream->public.timing); + break; + case SIGNAL_TYPE_WIRELESS: + is_valid = dce110_link_encoder_validate_wireless_output( + enc110, &stream->public.timing); + break; + default: + is_valid = true; + break; + } + + return is_valid; +} + +void dce110_link_encoder_hw_init( + struct link_encoder *enc) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + cntl.action = TRANSMITTER_CONTROL_INIT; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.coherent = false; + cntl.hpd_sel = enc110->base.hpd_source; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + if (enc110->base.connector.id == CONNECTOR_ID_LVDS) { + cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS; + + result = link_transmitter_control(enc110, &cntl); + + ASSERT(result == BP_RESULT_OK); + + } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) { + enc->funcs->power_control(&enc110->base, true); + } + aux_initialize(enc110); + + /* reinitialize HPD. + * hpd_initialize() will pass DIG_FE id to HW context. + * All other routine within HW context will use fe_engine_offset + * as DIG_FE id even caller pass DIG_FE id. + * So this routine must be called first. */ + hpd_initialize(enc110); +} + +void dce110_link_encoder_destroy(struct link_encoder **enc) +{ + dm_free(TO_DCE110_LINK_ENC(*enc)); + *enc = NULL; +} + +void dce110_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + switch (signal) { + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT: + /* DP SST */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0); + break; + case SIGNAL_TYPE_LVDS: + /* LVDS */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1); + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + /* TMDS-DVI */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + /* TMDS-HDMI */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3); + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + /* DP MST */ + REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5); + break; + default: + ASSERT_CRITICAL(false); + /* invalid mode ! */ + break; + } + +} + +/* TODO: still need depth or just pass in adjusted pixel clock? */ +void dce110_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + bool hdmi, + bool dual_link, + uint32_t pixel_clock) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.pll_id = clock_source; + if (hdmi) { + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.lanes_number = 4; + } else if (dual_link) { + cntl.signal = SIGNAL_TYPE_DVI_DUAL_LINK; + cntl.lanes_number = 8; + } else { + cntl.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.lanes_number = 4; + } + cntl.hpd_sel = enc110->base.hpd_source; + + cntl.pixel_clock = pixel_clock; + cntl.color_depth = color_depth; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +/* enables DP PHY output */ +void dce110_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + configure_encoder(enc110, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +/* enables DP PHY output in MST mode */ +void dce110_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + configure_encoder(enc110, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} +/* + * @brief + * Disable transmitter and its encoder + */ +void dce110_link_encoder_disable_output( + struct link_encoder *enc, + enum signal_type signal) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + if (!is_dig_enabled(enc110)) { + /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ + return; + } + /* Power-down RX and disable GPU PHY should be paired. + * Disabling PHY without powering down RX may cause + * symbol lock loss, on which we will get DP Sink interrupt. */ + + /* There is a case for the DP active dongles + * where we want to disable the PHY but keep RX powered, + * for those we need to ignore DP Sink interrupt + * by checking lane count that has been set + * on the last do_enable_output(). */ + + /* disable transmitter */ + cntl.action = TRANSMITTER_CONTROL_DISABLE; + cntl.transmitter = enc110->base.transmitter; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.signal = signal; + cntl.connector_obj_id = enc110->base.connector; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + /* disable encoder */ + if (dc_is_dp_signal(signal)) + link_encoder_disable(enc110); + + if (enc110->base.connector.id == CONNECTOR_ID_EDP) { + /* power down eDP panel */ + /* TODO: Power control cause regression, we should implement + * it properly, for now just comment it. + * + * link_encoder_edp_wait_for_hpd_ready( + link_enc, + link_enc->connector, + false); + + * link_encoder_edp_power_control( + link_enc, false); */ + } +} + +void dce110_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct link_training_settings *link_settings) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + union dpcd_training_lane_set training_lane_set = { { 0 } }; + int32_t lane = 0; + struct bp_transmitter_control cntl = { 0 }; + + if (!link_settings) { + BREAK_TO_DEBUGGER(); + return; + } + + cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; + cntl.transmitter = enc110->base.transmitter; + cntl.connector_obj_id = enc110->base.connector; + cntl.lanes_number = link_settings->link_settings.lane_count; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.pixel_clock = link_settings->link_settings.link_rate * + LINK_RATE_REF_FREQ_IN_KHZ; + + for (lane = 0; lane < link_settings->link_settings.lane_count; ++lane) { + /* translate lane settings */ + + training_lane_set.bits.VOLTAGE_SWING_SET = + link_settings->lane_settings[lane].VOLTAGE_SWING; + training_lane_set.bits.PRE_EMPHASIS_SET = + link_settings->lane_settings[lane].PRE_EMPHASIS; + + /* post cursor 2 setting only applies to HBR2 link rate */ + if (link_settings->link_settings.link_rate == LINK_RATE_HIGH2) { + /* this is passed to VBIOS + * to program post cursor 2 level */ + + training_lane_set.bits.POST_CURSOR2_SET = + link_settings->lane_settings[lane].POST_CURSOR2; + } + + cntl.lane_select = lane; + cntl.lane_settings = training_lane_set.raw; + + /* call VBIOS table to set voltage swing and pre-emphasis */ + link_transmitter_control(enc110, &cntl); + } +} + +/* set DP PHY test and training patterns */ +void dce110_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + switch (param->dp_phy_pattern) { + case DP_TEST_PATTERN_TRAINING_PATTERN1: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN2: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN3: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); + break; + case DP_TEST_PATTERN_D102: + set_dp_phy_pattern_d102(enc110); + break; + case DP_TEST_PATTERN_SYMBOL_ERROR: + set_dp_phy_pattern_symbol_error(enc110); + break; + case DP_TEST_PATTERN_PRBS7: + set_dp_phy_pattern_prbs7(enc110); + break; + case DP_TEST_PATTERN_80BIT_CUSTOM: + set_dp_phy_pattern_80bit_custom( + enc110, param->custom_pattern); + break; + case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: + set_dp_phy_pattern_hbr2_compliance(enc110); + break; + case DP_TEST_PATTERN_VIDEO_MODE: { + set_dp_phy_pattern_passthrough_mode( + enc110, param->dp_panel_mode); + break; + } + + default: + /* invalid phy pattern */ + ASSERT_CRITICAL(false); + break; + } +} + +static void fill_stream_allocation_row_info( + const struct link_mst_stream_allocation *stream_allocation, + uint32_t *src, + uint32_t *slots) +{ + const struct stream_encoder *stream_enc = stream_allocation->stream_enc; + + if (stream_enc) { + *src = stream_enc->id; + *slots = stream_allocation->slot_count; + } else { + *src = 0; + *slots = 0; + } +} + +/* programs DP MST VC payload allocation */ +void dce110_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + uint32_t value0 = 0; + uint32_t value1 = 0; + uint32_t value2 = 0; + uint32_t slots = 0; + uint32_t src = 0; + uint32_t retries = 0; + + /* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/ + + /* --- Set MSE Stream Attribute - + * Setup VC Payload Table on Tx Side, + * Issue allocation change trigger + * to commit payload on both tx and rx side */ + + /* we should clean-up table each time */ + + if (table->stream_count >= 1) { + fill_stream_allocation_row_info( + &table->stream_allocations[0], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT0, + DP_MSE_SAT_SRC0, src, + DP_MSE_SAT_SLOT_COUNT0, slots); + + if (table->stream_count >= 2) { + fill_stream_allocation_row_info( + &table->stream_allocations[1], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT0, + DP_MSE_SAT_SRC1, src, + DP_MSE_SAT_SLOT_COUNT1, slots); + + if (table->stream_count >= 3) { + fill_stream_allocation_row_info( + &table->stream_allocations[2], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT1, + DP_MSE_SAT_SRC2, src, + DP_MSE_SAT_SLOT_COUNT2, slots); + + if (table->stream_count >= 4) { + fill_stream_allocation_row_info( + &table->stream_allocations[3], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_MSE_SAT1, + DP_MSE_SAT_SRC3, src, + DP_MSE_SAT_SLOT_COUNT3, slots); + + /* --- wait for transaction finish */ + + /* send allocation change trigger (ACT) ? + * this step first sends the ACT, + * then double buffers the SAT into the hardware + * making the new allocation active on the DP MST mode link */ + + + /* DP_MSE_SAT_UPDATE: + * 0 - No Action + * 1 - Update SAT with trigger + * 2 - Update SAT without trigger */ + + REG_UPDATE(DP_MSE_SAT_UPDATE, + DP_MSE_SAT_UPDATE, 1); + + /* wait for update to complete + * (i.e. DP_MSE_SAT_UPDATE field is reset to 0) + * then wait for the transmission + * of at least 16 MTP headers on immediate local link. + * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0 + * a value of 1 indicates that DP MST mode + * is in the 16 MTP keepout region after a VC has been added. + * MST stream bandwidth (VC rate) can be configured + * after this bit is cleared */ + + do { + udelay(10); + + value0 = REG_READ(DP_MSE_SAT_UPDATE); + + REG_GET(DP_MSE_SAT_UPDATE, + DP_MSE_SAT_UPDATE, &value1); + + REG_GET(DP_MSE_SAT_UPDATE, + DP_MSE_16_MTP_KEEPOUT, &value2); + + /* bit field DP_MSE_SAT_UPDATE is set to 1 already */ + if (!value1 && !value2) + break; + ++retries; + } while (retries < DP_MST_UPDATE_MAX_RETRY); +} + +void dce110_link_encoder_set_lcd_backlight_level( + struct link_encoder *enc, + uint32_t level) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + const uint32_t backlight_update_pending_max_retry = 1000; + + uint32_t backlight_lock; + + uint32_t i; + uint32_t backlight_24bit; + uint32_t backlight_17bit; + uint32_t backlight_16bit; + uint32_t masked_pwm_period; + uint8_t rounding_bit; + uint8_t bit_count; + uint64_t active_duty_cycle; + uint32_t pwm_period_bitcnt; + + backlight_lock = REG_READ(BL_PWM_GRP1_REG_LOCK); + + /* + * 1. Convert 8-bit value to 17 bit U1.16 format + * (1 integer, 16 fractional bits) + */ + + /* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value, + * effectively multiplying value by 256/255 + * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF + */ + backlight_24bit = level * 0x10101; + + /* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8 + * used for rounding, take most significant bit of fraction for + * rounding, e.g. for 0xEFEFEF, rounding bit is 1 + */ + rounding_bit = (backlight_24bit >> 7) & 1; + + /* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit + * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1 + */ + backlight_17bit = (backlight_24bit >> 8) + rounding_bit; + + /* + * 2. Find 16 bit backlight active duty cycle, where 0 <= backlight + * active duty cycle <= backlight period + */ + + /* 2.1 Apply bitmask for backlight period value based on value of BITCNT + */ + { + REG_GET(BL_PWM_PERIOD_CNTL, + BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt); + + if (pwm_period_bitcnt == 0) + bit_count = 16; + else + bit_count = pwm_period_bitcnt; + } + + /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ + masked_pwm_period = + REG_GET(BL_PWM_PERIOD_CNTL, + BL_PWM_PERIOD, &masked_pwm_period) + & ((1 << bit_count) - 1); + + /* 2.2 Calculate integer active duty cycle required upper 16 bits + * contain integer component, lower 16 bits contain fractional component + * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 + */ + active_duty_cycle = backlight_17bit * masked_pwm_period; + + /* 2.3 Calculate 16 bit active duty cycle from integer and fractional + * components shift by bitCount then mask 16 bits and add rounding bit + * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 + */ + backlight_16bit = active_duty_cycle >> bit_count; + backlight_16bit &= 0xFFFF; + backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; + + REG_UPDATE(BL_PWM_CNTL, + BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); + + /* + * 3. Program register with updated value + */ + + /* 3.1 Lock group 2 backlight registers */ + + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1); + + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 1); + + /* 3.3 Unlock group 2 backlight registers */ + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 0); + + /* 5.4.4 Wait for pending bit to be cleared */ + for (i = 0; i < backlight_update_pending_max_retry; ++i) { + REG_GET(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_UPDATE_PENDING, &backlight_lock); + if (!backlight_lock) + break; + + udelay(10); + } +} + +void dce110_link_encoder_set_dmcu_backlight_level( + struct link_encoder *enc, + uint32_t level, + uint32_t frame_ramp, + uint32_t controller_id) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int backlight_17bit = level * 0x10101; + unsigned char temp_uchar = + (unsigned char)(((backlight_17bit & 0x80) >> 7) & 1); + unsigned int regValue; + uint32_t rampingBoundary = 0xFFFF; + uint32_t s2; + + backlight_17bit = (backlight_17bit >> 8) + temp_uchar; + + /* set ramping boundary */ + REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary); + + /* setDMCUParam_Pipe */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, + MASTER_COMM_CMD_REG_BYTE1, controller_id); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_BL */ + REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17bit); + + /* write ramp */ + REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* UpdateRequestedBacklightLevel */ + s2 = REG_READ(BIOS_SCRATCH_2); + + s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; + level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >> + ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + + REG_WRITE(BIOS_SCRATCH_2, s2); +} + +void dce110_link_encoder_init_dmcu_backlight_settings( + struct link_encoder *enc) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + uint32_t bl_pwm_cntl; + uint32_t pwmCntl; + uint32_t pwmCntl2; + uint32_t periodCntl; + uint32_t s2; + uint32_t value; + + bl_pwm_cntl = REG_READ(BL_PWM_CNTL); + + /* It must not be 0, so we have to restore them + * Bios bug w/a - period resets to zero, + * restoring to cache values which is always correct + */ + REG_GET(BL_PWM_CNTL, + BL_ACTIVE_INT_FRAC_CNT, &value); + if (value == 0 || bl_pwm_cntl == 1) { + if (stored_backlight_registers.vBL_PWM_CNTL != 0) { + pwmCntl = stored_backlight_registers.vBL_PWM_CNTL; + REG_WRITE(BL_PWM_CNTL, pwmCntl); + + pwmCntl2 = stored_backlight_registers.vBL_PWM_CNTL2; + REG_WRITE(BL_PWM_CNTL2, pwmCntl2); + + periodCntl = + stored_backlight_registers.vBL_PWM_PERIOD_CNTL; + REG_WRITE(BL_PWM_PERIOD_CNTL, periodCntl); + + REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, + BL_PWM_REF_DIV, + stored_backlight_registers. + vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } + } else { + stored_backlight_registers.vBL_PWM_CNTL = + REG_READ(BL_PWM_CNTL); + stored_backlight_registers.vBL_PWM_CNTL2 = + REG_READ(BL_PWM_CNTL2); + stored_backlight_registers.vBL_PWM_PERIOD_CNTL = + REG_READ(BL_PWM_PERIOD_CNTL); + + REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, + &stored_backlight_registers. + vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } + + /* Have driver take backlight control + * TakeBacklightControl(true) + */ + s2 = REG_READ(BIOS_SCRATCH_2); + s2 |= ATOM_S2_VRI_BRIGHT_ENABLE; + REG_WRITE(BIOS_SCRATCH_2, s2); + + /* Enable the backlight output */ + REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); + +} + +void dce110_link_encoder_set_dmcu_abm_level( + struct link_encoder *enc, uint32_t level) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int regValue; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_ABMLevel */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, + MASTER_COMM_CMD_REG_BYTE2, level); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + + uint32_t count = 0; + uint32_t psrStateOffset = 0xf0; + uint32_t value; + + /* Enable write access to IRAM */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); + + do { + dm_delay_in_microseconds(ctx, 2); + REG_GET(DCI_MEM_PWR_STATUS, + DMCU_IRAM_MEM_PWR_STATE, &value); + } while + (value != 0 && count++ < 10); + + /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ + REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); + + /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ + *psr_state = REG_READ(DMCU_IRAM_RD_DATA); + + /* Disable write access to IRAM after finished using IRAM + * in order to allow dynamic sleep state + */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); +} + +void dce110_link_encoder_set_dmcu_psr_enable(struct link_encoder *enc, + bool enable) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + + unsigned int regValue; + + unsigned int retryCount; + uint32_t psr_state = 0; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_Cmd */ + if (enable) + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_ENABLE); + else + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_EXIT); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + for (retryCount = 0; retryCount <= 100; retryCount++) { + get_dmcu_psr_state(enc, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + dm_delay_in_microseconds(ctx, 10); + } +} + +void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc, + struct psr_dmcu_context *psr_context) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int regValue; + + union dce110_dmcu_psr_config_data_reg1 masterCmdData1; + union dce110_dmcu_psr_config_data_reg2 masterCmdData2; + union dce110_dmcu_psr_config_data_reg3 masterCmdData3; + + if (psr_context->psrExitLinkTrainingRequired) + REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 1); + else { + REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 0); + /*In DCE 11, we are able to pre-program a Force SR register + * to be able to trigger SR symbol after 5 idle patterns + * transmitted. Upon PSR Exit, DMCU can trigger + * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to + * DPHY_LOAD_BS_COUNT_START and the internal counter + * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be + * replaced by SR symbol once. + */ + + REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); + } + + /* Enable static screen interrupts for PSR supported display */ + /* Disable the interrupt coming from other displays. */ + REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 0, + STATIC_SCREEN2_INT_TO_UC_EN, 0, + STATIC_SCREEN3_INT_TO_UC_EN, 0, + STATIC_SCREEN4_INT_TO_UC_EN, 0); + + switch (psr_context->controllerId) { + /* Driver uses case 1 for unconfigured */ + case 1: + psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + case 2: + psr_crtc_offset = mmCRTC1_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN2_INT_TO_UC_EN, 1); + break; + case 3: + psr_crtc_offset = mmCRTC2_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN3_INT_TO_UC_EN, 1); + break; + case 4: + psr_crtc_offset = mmCRTC3_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN4_INT_TO_UC_EN, 1); + break; + case 5: + psr_crtc_offset = mmCRTC4_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + /* CZ/NL only has 4 CRTC!! + * really valid. + * There is no interrupt enable mask for these instances. + */ + break; + case 6: + psr_crtc_offset = mmCRTC5_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + /* CZ/NL only has 4 CRTC!! + * These are here because they are defined in HW regspec, + * but not really valid. There is no interrupt enable mask + * for these instances. + */ + break; + default: + psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL - + mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; + + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + } + + REG_UPDATE_2(DP_SEC_CNTL1, + DP_SEC_GSP0_LINE_NUM, psr_context->sdpTransmitLineNumDeadline, + DP_SEC_GSP0_PRIORITY, 1); + + if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) { + REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); + } + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_PSRHostConfigData */ + masterCmdData1.u32All = 0; + masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames; + masterCmdData1.bits.hyst_lines = psr_context->hyst_lines; + masterCmdData1.bits.rfb_update_auto_en = + psr_context->rfb_update_auto_en; + masterCmdData1.bits.dp_port_num = psr_context->transmitterId; + masterCmdData1.bits.dcp_sel = psr_context->controllerId; + masterCmdData1.bits.phy_type = psr_context->phyType; + masterCmdData1.bits.frame_cap_ind = + psr_context->psrFrameCaptureIndicationReq; + masterCmdData1.bits.aux_chan = psr_context->channel; + masterCmdData1.bits.aux_repeat = psr_context->aux_repeats; + dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), + masterCmdData1.u32All); + + masterCmdData2.u32All = 0; + masterCmdData2.bits.dig_fe = psr_context->engineId; + masterCmdData2.bits.dig_be = psr_context->transmitterId; + masterCmdData2.bits.skip_wait_for_pll_lock = + psr_context->skipPsrWaitForPllLock; + masterCmdData2.bits.frame_delay = psr_context->frame_delay; + masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId; + masterCmdData2.bits.num_of_controllers = + psr_context->numberOfControllers; + dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG2), + masterCmdData2.u32All); + + masterCmdData3.u32All = 0; + masterCmdData3.bits.psr_level = psr_context->psr_level.u32all; + dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG3), + masterCmdData3.u32All); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, PSR_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +void dce110_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + uint32_t field; + + if (engine != ENGINE_ID_UNKNOWN) { + + REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field); + + if (connect) + field |= get_frontend_source(engine); + else + field &= ~get_frontend_source(engine); + + REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field); + } +} + +void dce110_link_encoder_enable_hpd(struct link_encoder *enc) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = HPD_REG(DC_HPD_CONTROL); + uint32_t hpd_enable = 0; + uint32_t value = dm_read_reg(ctx, addr); + + get_reg_field_value(hpd_enable, DC_HPD_CONTROL, DC_HPD_EN); + + if (hpd_enable == 0) + set_reg_field_value(value, 1, DC_HPD_CONTROL, DC_HPD_EN); +} + +void dce110_link_encoder_disable_hpd(struct link_encoder *enc) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct dc_context *ctx = enc110->base.ctx; + uint32_t addr = HPD_REG(DC_HPD_CONTROL); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h new file mode 100644 index 000000000000..1635b239402f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -0,0 +1,363 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_ENCODER__DCE110_H__ +#define __DC_LINK_ENCODER__DCE110_H__ + +#include "link_encoder.h" + +#define TO_DCE110_LINK_ENC(link_encoder)\ + container_of(link_encoder, struct dce110_link_encoder, base) + +#define AUX_REG_LIST(id)\ + SRI(AUX_CONTROL, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id) + +#define HPD_REG_LIST(id)\ + SRI(DC_HPD_CONTROL, HPD, id) + +#define LE_COMMON_REG_LIST_BASE(id) \ + SR(BL_PWM_CNTL), \ + SR(BL_PWM_GRP1_REG_LOCK), \ + SR(BL_PWM_PERIOD_CNTL), \ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE), \ + SR(BL_PWM_CNTL2), \ + SR(LVTMA_PWRSEQ_REF_DIV), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(MASTER_COMM_DATA_REG2), \ + SR(MASTER_COMM_DATA_REG3), \ + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_CNTL_REG), \ + SR(DMCU_RAM_ACCESS_CTRL), \ + SR(DMCU_IRAM_RD_CTRL), \ + SR(DMCU_IRAM_RD_DATA), \ + SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ + SR(SMU_INTERRUPT_CONTROL), \ + SRI(DIG_BE_CNTL, DIG, id), \ + SRI(DIG_BE_EN_CNTL, DIG, id), \ + SRI(DP_CONFIG, DP, id), \ + SRI(DP_DPHY_CNTL, DP, id), \ + SRI(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ + SRI(DP_DPHY_SYM0, DP, id), \ + SRI(DP_DPHY_SYM1, DP, id), \ + SRI(DP_DPHY_SYM2, DP, id), \ + SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI(DP_LINK_CNTL, DP, id), \ + SRI(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI(DP_MSE_SAT0, DP, id), \ + SRI(DP_MSE_SAT1, DP, id), \ + SRI(DP_MSE_SAT2, DP, id), \ + SRI(DP_MSE_SAT_UPDATE, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_DPHY_FAST_TRAINING, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id) + + #define LE_COMMON_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(BIOS_SCRATCH_2), \ + SR(BL1_PWM_USER_LEVEL), \ + SR(DCI_MEM_PWR_STATUS) + + #define LE_DCE110_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(BIOS_SCRATCH_2), \ + SR(BL1_PWM_USER_LEVEL), \ + SR(DCI_MEM_PWR_STATUS) + + #define LE_DCE80_REG_LIST(id)\ + SR(BIOS_SCRATCH_2), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(BL1_PWM_USER_LEVEL), \ + LE_COMMON_REG_LIST_BASE(id) + + +struct dce110_link_enc_aux_registers { + uint32_t AUX_CONTROL; + uint32_t AUX_DPHY_RX_CONTROL0; +}; + +struct dce110_link_enc_hpd_registers { + uint32_t DC_HPD_CONTROL; +}; + +struct dce110_link_enc_registers { + /* BL registers */ + uint32_t BL_PWM_CNTL; + uint32_t BL_PWM_GRP1_REG_LOCK; + uint32_t BL_PWM_PERIOD_CNTL; + uint32_t LVTMA_PWRSEQ_CNTL; + uint32_t LVTMA_PWRSEQ_STATE; + uint32_t BL_PWM_CNTL2; + uint32_t LVTMA_PWRSEQ_REF_DIV; + + /* DMCU registers */ + uint32_t BL1_PWM_USER_LEVEL; + uint32_t ABM0_BL1_PWM_USER_LEVEL; + uint32_t MASTER_COMM_DATA_REG1; + uint32_t MASTER_COMM_DATA_REG2; + uint32_t MASTER_COMM_DATA_REG3; + uint32_t MASTER_COMM_CMD_REG; + uint32_t MASTER_COMM_CNTL_REG; + uint32_t BIOS_SCRATCH_2; + uint32_t DMCU_RAM_ACCESS_CTRL; + uint32_t DCI_MEM_PWR_STATUS; + uint32_t DMU_MEM_PWR_CNTL; + uint32_t DMCU_IRAM_RD_CTRL; + uint32_t DMCU_IRAM_RD_DATA; + uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; + uint32_t SMU_INTERRUPT_CONTROL; + + + /* Common DP registers */ + uint32_t DIG_BE_CNTL; + uint32_t DIG_BE_EN_CNTL; + uint32_t DP_CONFIG; + uint32_t DP_DPHY_CNTL; + uint32_t DP_DPHY_INTERNAL_CTRL; + uint32_t DP_DPHY_PRBS_CNTL; + uint32_t DP_DPHY_SCRAM_CNTL; + uint32_t DP_DPHY_SYM0; + uint32_t DP_DPHY_SYM1; + uint32_t DP_DPHY_SYM2; + uint32_t DP_DPHY_TRAINING_PATTERN_SEL; + uint32_t DP_LINK_CNTL; + uint32_t DP_LINK_FRAMING_CNTL; + uint32_t DP_MSE_SAT0; + uint32_t DP_MSE_SAT1; + uint32_t DP_MSE_SAT2; + uint32_t DP_MSE_SAT_UPDATE; + uint32_t DP_SEC_CNTL; + uint32_t DP_VID_STREAM_CNTL; + uint32_t DP_DPHY_FAST_TRAINING; + uint32_t DP_DPHY_BS_SR_SWAP_CNTL; + uint32_t DP_SEC_CNTL1; +}; + +struct dce110_link_encoder { + struct link_encoder base; + const struct dce110_link_enc_registers *link_regs; + const struct dce110_link_enc_aux_registers *aux_regs; + const struct dce110_link_enc_hpd_registers *hpd_regs; +}; + +/******************************************************************* +* MASTER_COMM_DATA_REG1 Bit position Data +* 7:0 hyst_frames[7:0] +* 14:8 hyst_lines[6:0] +* 15 RFB_UPDATE_AUTO_EN +* 18:16 phy_num[2:0] +* 21:19 dcp_sel[2:0] +* 22 phy_type +* 23 frame_cap_ind +* 26:24 aux_chan[2:0] +* 30:27 aux_repeat[3:0] +* 31:31 reserved[31:31] +*******************************************************************/ +union dce110_dmcu_psr_config_data_reg1 { + struct { + unsigned int timehyst_frames:8; /*[7:0]*/ + unsigned int hyst_lines:7; /*[14:8]*/ + unsigned int rfb_update_auto_en:1; /*[15:15]*/ + unsigned int dp_port_num:3; /*[18:16]*/ + unsigned int dcp_sel:3; /*[21:19]*/ + unsigned int phy_type:1; /*[22:22]*/ + unsigned int frame_cap_ind:1; /*[23:23]*/ + unsigned int aux_chan:3; /*[26:24]*/ + unsigned int aux_repeat:4; /*[30:27]*/ + unsigned int reserved:1; /*[31:31]*/ + } bits; + unsigned int u32All; +}; + +/******************************************************************* +* MASTER_COMM_DATA_REG2 +*******************************************************************/ +union dce110_dmcu_psr_config_data_reg2 { + struct { + unsigned int dig_fe:3; /*[2:0]*/ + unsigned int dig_be:3; /*[5:3]*/ + unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/ + unsigned int reserved:9; /*[15:7]*/ + unsigned int frame_delay:8; /*[23:16]*/ + unsigned int smu_phy_id:4; /*[27:24]*/ + unsigned int num_of_controllers:4; /*[31:28]*/ + } bits; + unsigned int u32All; +}; + +/******************************************************************* +* MASTER_COMM_DATA_REG3 +*******************************************************************/ +union dce110_dmcu_psr_config_data_reg3 { + struct { + unsigned int psr_level:16; /*[15:0]*/ + unsigned int link_rate:4; /*[19:16]*/ + unsigned int reserved:12; /*[31:20]*/ + } bits; + unsigned int u32All; +}; + +struct dce110_abm_backlight_registers { + unsigned int vBL_PWM_CNTL; + unsigned int vBL_PWM_CNTL2; + unsigned int vBL_PWM_PERIOD_CNTL; + unsigned int vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; +}; + +bool dce110_link_encoder_construct( + struct dce110_link_encoder *enc110, + const struct encoder_init_data *init_data, + const struct dce110_link_enc_registers *link_regs, + const struct dce110_link_enc_aux_registers *aux_regs, + const struct dce110_link_enc_hpd_registers *hpd_regs); + +bool dce110_link_encoder_validate_dvi_output( + const struct dce110_link_encoder *enc110, + enum signal_type connector_signal, + enum signal_type signal, + const struct dc_crtc_timing *crtc_timing); + +bool dce110_link_encoder_validate_rgb_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing); + +bool dce110_link_encoder_validate_dp_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing); + +bool dce110_link_encoder_validate_wireless_output( + const struct dce110_link_encoder *enc110, + const struct dc_crtc_timing *crtc_timing); + +bool dce110_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + struct pipe_ctx *pipe_ctx); + +/****************** HW programming ************************/ + +/* initialize HW */ /* why do we initialze aux in here? */ +void dce110_link_encoder_hw_init(struct link_encoder *enc); + +void dce110_link_encoder_destroy(struct link_encoder **enc); + +/* program DIG_MODE in DIG_BE */ +/* TODO can this be combined with enable_output? */ +void dce110_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal); + +/* enables TMDS PHY output */ +/* TODO: still need depth or just pass in adjusted pixel clock? */ +void dce110_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + bool hdmi, + bool dual_link, + uint32_t pixel_clock); + +/* enables DP PHY output */ +void dce110_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* enables DP PHY output in MST mode */ +void dce110_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + +/* disable PHY output */ +void dce110_link_encoder_disable_output( + struct link_encoder *link_enc, + enum signal_type signal); + +/* set DP lane settings */ +void dce110_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct link_training_settings *link_settings); + +void dce110_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param); + +/* programs DP MST VC payload allocation */ +void dce110_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table); + +void dce110_link_encoder_set_lcd_backlight_level( + struct link_encoder *enc, + uint32_t level); + +void dce110_link_encoder_set_dmcu_backlight_level( + struct link_encoder *enc, + uint32_t level, + uint32_t frame_ramp, + uint32_t controller_id); + +void dce110_link_encoder_init_dmcu_backlight_settings( + struct link_encoder *enc); + +void dce110_link_encoder_set_dmcu_abm_level( + struct link_encoder *enc, + uint32_t level); + +void dce110_link_encoder_set_dmcu_psr_enable( + struct link_encoder *enc, bool enable); + +void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc, + struct psr_dmcu_context *psr_context); + +void dce110_link_encoder_edp_backlight_control( + struct link_encoder *enc, + bool enable); + +void dce110_link_encoder_edp_power_control( + struct link_encoder *enc, + bool power_up); + +void dce110_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect); + +void dce110_link_encoder_set_dp_phy_pattern_training_pattern( + struct link_encoder *enc, + uint32_t index); + +void dce110_link_encoder_enable_hpd(struct link_encoder *enc); + +void dce110_link_encoder_disable_hpd(struct link_encoder *enc); + +#endif /* __DC_LINK_ENCODER__DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c new file mode 100644 index 000000000000..654731cccdcd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -0,0 +1,384 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "mem_input.h" +#include "reg_helper.h" + +#define CTX \ + mi->ctx +#define REG(reg)\ + mi->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + mi->shifts->field_name, mi->masks->field_name + + +static void program_urgency_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t urgency_low_wm, + uint32_t urgency_high_wm) +{ + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK, wm_select); + + REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0, + URGENCY_LOW_WATERMARK, urgency_low_wm, + URGENCY_HIGH_WATERMARK, urgency_high_wm); +} + +static void program_nbp_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t nbp_wm) +{ + if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) { + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select); + + REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE, 1, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1); + + REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK, nbp_wm); + } +} + +static void program_stutter_watermark(struct mem_input *mi, + uint32_t wm_select, + uint32_t stutter_mark) +{ + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); + + REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); +} + +void dce_mem_input_program_display_marks(struct mem_input *mi, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; + + program_urgency_watermark(mi, 0, /* set a */ + urgent.a_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 1, /* set b */ + urgent.b_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 2, /* set c */ + urgent.c_mark, total_dest_line_time_ns); + program_urgency_watermark(mi, 3, /* set d */ + urgent.d_mark, total_dest_line_time_ns); + + REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE, stutter_en, + STUTTER_IGNORE_FBC, 1); + program_nbp_watermark(mi, 0, nbp.a_mark); /* set a */ + program_nbp_watermark(mi, 1, nbp.b_mark); /* set b */ + program_nbp_watermark(mi, 2, nbp.c_mark); /* set c */ + program_nbp_watermark(mi, 3, nbp.d_mark); /* set d */ + + program_stutter_watermark(mi, 0, stutter.a_mark); /* set a */ + program_stutter_watermark(mi, 1, stutter.b_mark); /* set b */ + program_stutter_watermark(mi, 2, stutter.c_mark); /* set c */ + program_stutter_watermark(mi, 3, stutter.d_mark); /* set d */ +} + +static void program_tiling(struct mem_input *mi, + const union dc_tiling_info *info) +{ + if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ + REG_UPDATE_9(GRPH_CONTROL, + GRPH_NUM_BANKS, info->gfx8.num_banks, + GRPH_BANK_WIDTH, info->gfx8.bank_width, + GRPH_BANK_HEIGHT, info->gfx8.bank_height, + GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect, + GRPH_TILE_SPLIT, info->gfx8.tile_split, + GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode, + GRPH_PIPE_CONFIG, info->gfx8.pipe_config, + GRPH_ARRAY_MODE, info->gfx8.array_mode, + GRPH_COLOR_EXPANSION_MODE, 1); + /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */ + /* + GRPH_Z, 0); + */ + } +} + + +static void program_size_and_rotation( + struct mem_input *mi, + enum dc_rotation_angle rotation, + const union plane_size *plane_size) +{ + const struct rect *in_rect = &plane_size->grph.surface_size; + struct rect hw_rect = plane_size->grph.surface_size; + const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = { + [ROTATION_ANGLE_0] = 0, + [ROTATION_ANGLE_90] = 1, + [ROTATION_ANGLE_180] = 2, + [ROTATION_ANGLE_270] = 3, + }; + + if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) { + hw_rect.x = in_rect->y; + hw_rect.y = in_rect->x; + + hw_rect.height = in_rect->width; + hw_rect.width = in_rect->height; + } + + REG_SET(GRPH_X_START, 0, + GRPH_X_START, hw_rect.x); + + REG_SET(GRPH_Y_START, 0, + GRPH_Y_START, hw_rect.y); + + REG_SET(GRPH_X_END, 0, + GRPH_X_END, hw_rect.width); + + REG_SET(GRPH_Y_END, 0, + GRPH_Y_END, hw_rect.height); + + REG_SET(GRPH_PITCH, 0, + GRPH_PITCH, plane_size->grph.surface_pitch); + + REG_SET(HW_ROTATION, 0, + GRPH_ROTATION_ANGLE, rotation_angles[rotation]); +} + +static void program_grph_pixel_format( + struct mem_input *mi, + enum surface_pixel_format format) +{ + uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ + uint32_t grph_depth, grph_format; + uint32_t sign = 0, floating = 0; + + if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 || + /*todo: doesn't look like we handle BGRA here, + * should problem swap endian*/ + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS || + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { + /* ABGR formats */ + red_xbar = 2; + blue_xbar = 2; + } + + REG_SET_2(GRPH_SWAP_CNTL, 0, + GRPH_RED_CROSSBAR, red_xbar, + GRPH_BLUE_CROSSBAR, blue_xbar); + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + grph_depth = 0; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + grph_depth = 1; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + grph_depth = 1; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + grph_depth = 2; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + grph_depth = 2; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + sign = 1; + floating = 1; + /* no break */ + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */ + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + grph_depth = 3; + grph_format = 0; + break; + default: + DC_ERR("unsupported grph pixel format"); + break; + } + + REG_UPDATE_2(GRPH_CONTROL, + GRPH_DEPTH, grph_depth, + GRPH_FORMAT, grph_format); + + REG_UPDATE_4(PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_SELECT, floating, + GRPH_PRESCALE_R_SIGN, sign, + GRPH_PRESCALE_G_SIGN, sign, + GRPH_PRESCALE_B_SIGN, sign); +} + +bool dce_mem_input_program_surface_config(struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror) +{ + REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); + + program_tiling(mi, tiling_info); + program_size_and_rotation(mi, rotation, plane_size); + + if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && + format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + program_grph_pixel_format(mi, format); + + return true; +} + +static uint32_t get_dmif_switch_time_us( + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz) +{ + uint32_t frame_time; + uint32_t pixels_per_second; + uint32_t pixels_per_frame; + uint32_t refresh_rate; + const uint32_t us_in_sec = 1000000; + const uint32_t min_single_frame_time_us = 30000; + /*return double of frame time*/ + const uint32_t single_frame_time_multiplier = 2; + + if (!h_total || v_total || !pix_clk_khz) + return single_frame_time_multiplier * min_single_frame_time_us; + + /*TODO: should we use pixel format normalized pixel clock here?*/ + pixels_per_second = pix_clk_khz * 1000; + pixels_per_frame = h_total * v_total; + + if (!pixels_per_second || !pixels_per_frame) { + /* avoid division by zero */ + ASSERT(pixels_per_frame); + ASSERT(pixels_per_second); + return single_frame_time_multiplier * min_single_frame_time_us; + } + + refresh_rate = pixels_per_second / pixels_per_frame; + + if (!refresh_rate) { + /* avoid division by zero*/ + ASSERT(refresh_rate); + return single_frame_time_multiplier * min_single_frame_time_us; + } + + frame_time = us_in_sec / refresh_rate; + + if (frame_time < min_single_frame_time_us) + frame_time = min_single_frame_time_us; + + frame_time *= single_frame_time_multiplier; + + return frame_time; +} + +void dce_mem_input_allocate_dmif(struct mem_input *mi, + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz, + uint32_t total_stream_num) +{ + const uint32_t retry_delay = 10; + uint32_t retry_count = get_dmif_switch_time_us( + h_total, + v_total, + pix_clk_khz) / retry_delay; + + uint32_t pix_dur; + uint32_t buffers_allocated; + uint32_t dmif_buffer_control; + + dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATED, &buffers_allocated); + + if (buffers_allocated == 2) + return; + + REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, + DMIF_BUFFERS_ALLOCATED, 2); + + REG_WAIT(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, + retry_delay, retry_count); + + if (pix_clk_khz != 0) { + pix_dur = 1000000000ULL / pix_clk_khz; + + REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION, pix_dur); + } + + if (mi->wa.single_head_rdreq_dmif_limit) { + uint32_t eanble = (total_stream_num > 1) ? 0 : + mi->wa.single_head_rdreq_dmif_limit; + + REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, + ENABLE, eanble); + } +} + +void dce_mem_input_free_dmif(struct mem_input *mi, + uint32_t total_stream_num) +{ + uint32_t buffers_allocated; + uint32_t dmif_buffer_control; + + dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATED, &buffers_allocated); + + if (buffers_allocated == 0) + return; + + REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control, + DMIF_BUFFERS_ALLOCATED, 0); + + REG_WAIT(DMIF_BUFFER_CONTROL, + DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, + 10, 0xBB8); + + if (mi->wa.single_head_rdreq_dmif_limit) { + uint32_t eanble = (total_stream_num > 1) ? 0 : + mi->wa.single_head_rdreq_dmif_limit; + + REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, + ENABLE, eanble); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h new file mode 100644 index 000000000000..d5930a925fcb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -0,0 +1,217 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DCE_MEM_INPUT_H__ +#define __DCE_MEM_INPUT_H__ + +#define MI_DCE_BASE_REG_LIST(id)\ + SRI(GRPH_ENABLE, DCP, id),\ + SRI(GRPH_CONTROL, DCP, id),\ + SRI(GRPH_X_START, DCP, id),\ + SRI(GRPH_Y_START, DCP, id),\ + SRI(GRPH_X_END, DCP, id),\ + SRI(GRPH_Y_END, DCP, id),\ + SRI(GRPH_PITCH, DCP, id),\ + SRI(HW_ROTATION, DCP, id),\ + SRI(GRPH_SWAP_CNTL, DCP, id),\ + SRI(PRESCALE_GRPH_CONTROL, DCP, id),\ + SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\ + SRI(DPG_WATERMARK_MASK_CONTROL, DMIF_PG, id),\ + SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\ + SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\ + SRI(DMIF_BUFFER_CONTROL, PIPE, id) + +#define MI_REG_LIST(id)\ + MI_DCE_BASE_REG_LIST(id),\ + SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id) + +struct dce_mem_input_registers { + /* DCP */ + uint32_t GRPH_ENABLE; + uint32_t GRPH_CONTROL; + uint32_t GRPH_X_START; + uint32_t GRPH_Y_START; + uint32_t GRPH_X_END; + uint32_t GRPH_Y_END; + uint32_t GRPH_PITCH; + uint32_t HW_ROTATION; + uint32_t GRPH_SWAP_CNTL; + uint32_t PRESCALE_GRPH_CONTROL; + /* DMIF_PG */ + uint32_t DPG_PIPE_ARBITRATION_CONTROL1; + uint32_t DPG_WATERMARK_MASK_CONTROL; + uint32_t DPG_PIPE_URGENCY_CONTROL; + uint32_t DPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + uint32_t DPG_PIPE_LOW_POWER_CONTROL; + uint32_t DPG_PIPE_STUTTER_CONTROL; + uint32_t DPG_PIPE_STUTTER_CONTROL2; + /* DCI */ + uint32_t DMIF_BUFFER_CONTROL; + /* MC_HUB */ + uint32_t MC_HUB_RDREQ_DMIF_LIMIT; +}; + +/* Set_Filed_for_Block */ +#define SFB(blk_name, reg_name, field_name, post_fix)\ + .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix + +#define MI_GFX8_TILE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_MICRO_TILE_MODE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_PIPE_CONFIG, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_ARRAY_MODE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh) + +#define MI_DCP_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_ENABLE, GRPH_ENABLE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_DEPTH, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_FORMAT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\ + SFB(blk, GRPH_X_START, GRPH_X_START, mask_sh),\ + SFB(blk, GRPH_Y_START, GRPH_Y_START, mask_sh),\ + SFB(blk, GRPH_X_END, GRPH_X_END, mask_sh),\ + SFB(blk, GRPH_Y_END, GRPH_Y_END, mask_sh),\ + SFB(blk, GRPH_PITCH, GRPH_PITCH, mask_sh),\ + SFB(blk, HW_ROTATION, GRPH_ROTATION_ANGLE, mask_sh),\ + SFB(blk, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR, mask_sh),\ + SFB(blk, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh) + +#define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_IGNORE_FBC, mask_sh),\ + SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED, mask_sh),\ + SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, mask_sh) + +#define MI_DMIF_PG_MASK_SH_DCE(mask_sh, blk)\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh) + +#define MI_DCE_MASK_SH_LIST(mask_sh)\ + MI_DCP_MASK_SH_LIST(mask_sh,),\ + MI_DMIF_PG_MASK_SH_LIST(mask_sh,),\ + MI_DMIF_PG_MASK_SH_DCE(mask_sh,),\ + MI_GFX8_TILE_MASK_SH_LIST(mask_sh,) + +#define MI_REG_FIELD_LIST(type) \ + type GRPH_ENABLE; \ + type GRPH_X_START; \ + type GRPH_Y_START; \ + type GRPH_X_END; \ + type GRPH_Y_END; \ + type GRPH_PITCH; \ + type GRPH_ROTATION_ANGLE; \ + type GRPH_RED_CROSSBAR; \ + type GRPH_BLUE_CROSSBAR; \ + type GRPH_PRESCALE_SELECT; \ + type GRPH_PRESCALE_R_SIGN; \ + type GRPH_PRESCALE_G_SIGN; \ + type GRPH_PRESCALE_B_SIGN; \ + type GRPH_DEPTH; \ + type GRPH_FORMAT; \ + type GRPH_NUM_BANKS; \ + type GRPH_BANK_WIDTH;\ + type GRPH_BANK_HEIGHT;\ + type GRPH_MACRO_TILE_ASPECT;\ + type GRPH_TILE_SPLIT;\ + type GRPH_MICRO_TILE_MODE;\ + type GRPH_PIPE_CONFIG;\ + type GRPH_ARRAY_MODE;\ + type GRPH_COLOR_EXPANSION_MODE;\ + type GRPH_SW_MODE; \ + type GRPH_NUM_SHADER_ENGINES; \ + type GRPH_NUM_PIPES; \ + type PIXEL_DURATION; \ + type URGENCY_WATERMARK_MASK; \ + type PSTATE_CHANGE_WATERMARK_MASK; \ + type NB_PSTATE_CHANGE_WATERMARK_MASK; \ + type STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK; \ + type URGENCY_LOW_WATERMARK; \ + type URGENCY_HIGH_WATERMARK; \ + type NB_PSTATE_CHANGE_ENABLE; \ + type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST; \ + type NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \ + type NB_PSTATE_CHANGE_WATERMARK; \ + type PSTATE_CHANGE_ENABLE; \ + type PSTATE_CHANGE_URGENT_DURING_REQUEST; \ + type PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \ + type PSTATE_CHANGE_WATERMARK; \ + type STUTTER_ENABLE; \ + type STUTTER_IGNORE_FBC; \ + type STUTTER_EXIT_SELF_REFRESH_WATERMARK; \ + type DMIF_BUFFERS_ALLOCATED; \ + type DMIF_BUFFERS_ALLOCATION_COMPLETED; \ + type ENABLE; /* MC_HUB_RDREQ_DMIF_LIMIT */\ + +struct dce_mem_input_shift { + MI_REG_FIELD_LIST(uint8_t) +}; + +struct dce_mem_input_mask { + MI_REG_FIELD_LIST(uint32_t) +}; + +struct dce_mem_input_wa { + uint8_t single_head_rdreq_dmif_limit; +}; + +struct mem_input; +bool dce_mem_input_program_surface_config(struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +void dce_mem_input_allocate_dmif(struct mem_input *mi, + uint32_t h_total, + uint32_t v_total, + uint32_t pix_clk_khz, + uint32_t total_stream_num); + +void dce_mem_input_free_dmif(struct mem_input *mi, + uint32_t total_stream_num); + +void dce_mem_input_program_display_marks(struct mem_input *mi, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + +#endif /*__DCE_MEM_INPUT_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c new file mode 100644 index 000000000000..3aab86781be2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c @@ -0,0 +1,501 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "transform.h" + +const uint16_t filter_2tap_16p[18] = { + 4096, 0, + 3840, 256, + 3584, 512, + 3328, 768, + 3072, 1024, + 2816, 1280, + 2560, 1536, + 2304, 1792, + 2048, 2048 +}; + +const uint16_t filter_3tap_16p_upscale[27] = { + 2048, 2048, 0, + 1708, 2424, 16348, + 1372, 2796, 16308, + 1056, 3148, 16272, + 768, 3464, 16244, + 512, 3728, 16236, + 296, 3928, 16252, + 124, 4052, 16296, + 0, 4096, 0 +}; + +const uint16_t filter_3tap_16p_117[27] = { + 2048, 2048, 0, + 1824, 2276, 16376, + 1600, 2496, 16380, + 1376, 2700, 16, + 1156, 2880, 52, + 948, 3032, 108, + 756, 3144, 192, + 580, 3212, 296, + 428, 3236, 428 +}; + +const uint16_t filter_3tap_16p_150[27] = { + 2048, 2048, 0, + 1872, 2184, 36, + 1692, 2308, 88, + 1516, 2420, 156, + 1340, 2516, 236, + 1168, 2592, 328, + 1004, 2648, 440, + 844, 2684, 560, + 696, 2696, 696 +}; + +const uint16_t filter_3tap_16p_183[27] = { + 2048, 2048, 0, + 1892, 2104, 92, + 1744, 2152, 196, + 1592, 2196, 300, + 1448, 2232, 412, + 1304, 2256, 528, + 1168, 2276, 648, + 1032, 2288, 772, + 900, 2292, 900 +}; + +const uint16_t filter_4tap_16p_upscale[36] = { + 0, 4096, 0, 0, + 16240, 4056, 180, 16380, + 16136, 3952, 404, 16364, + 16072, 3780, 664, 16344, + 16040, 3556, 952, 16312, + 16036, 3284, 1268, 16272, + 16052, 2980, 1604, 16224, + 16084, 2648, 1952, 16176, + 16128, 2304, 2304, 16128 +}; + +const uint16_t filter_4tap_16p_117[36] = { + 428, 3236, 428, 0, + 276, 3232, 604, 16364, + 148, 3184, 800, 16340, + 44, 3104, 1016, 16312, + 16344, 2984, 1244, 16284, + 16284, 2832, 1488, 16256, + 16244, 2648, 1732, 16236, + 16220, 2440, 1976, 16220, + 16212, 2216, 2216, 16212 +}; + +const uint16_t filter_4tap_16p_150[36] = { + 696, 2700, 696, 0, + 560, 2700, 848, 16364, + 436, 2676, 1008, 16348, + 328, 2628, 1180, 16336, + 232, 2556, 1356, 16328, + 152, 2460, 1536, 16328, + 84, 2344, 1716, 16332, + 28, 2208, 1888, 16348, + 16376, 2052, 2052, 16376 +}; + +const uint16_t filter_4tap_16p_183[36] = { + 940, 2208, 940, 0, + 832, 2200, 1052, 4, + 728, 2180, 1164, 16, + 628, 2148, 1280, 36, + 536, 2100, 1392, 60, + 448, 2044, 1504, 92, + 368, 1976, 1612, 132, + 296, 1900, 1716, 176, + 232, 1812, 1812, 232 +}; + +const uint16_t filter_2tap_64p[66] = { + 4096, 0, + 4032, 64, + 3968, 128, + 3904, 192, + 3840, 256, + 3776, 320, + 3712, 384, + 3648, 448, + 3584, 512, + 3520, 576, + 3456, 640, + 3392, 704, + 3328, 768, + 3264, 832, + 3200, 896, + 3136, 960, + 3072, 1024, + 3008, 1088, + 2944, 1152, + 2880, 1216, + 2816, 1280, + 2752, 1344, + 2688, 1408, + 2624, 1472, + 2560, 1536, + 2496, 1600, + 2432, 1664, + 2368, 1728, + 2304, 1792, + 2240, 1856, + 2176, 1920, + 2112, 1984, + 2048, 2048 }; + +const uint16_t filter_3tap_64p_upscale[99] = { + 2048, 2048, 0, + 1960, 2140, 16376, + 1876, 2236, 16364, + 1792, 2328, 16356, + 1708, 2424, 16348, + 1620, 2516, 16336, + 1540, 2612, 16328, + 1456, 2704, 16316, + 1372, 2796, 16308, + 1292, 2884, 16296, + 1212, 2976, 16288, + 1136, 3060, 16280, + 1056, 3148, 16272, + 984, 3228, 16264, + 908, 3312, 16256, + 836, 3388, 16248, + 768, 3464, 16244, + 700, 3536, 16240, + 636, 3604, 16236, + 572, 3668, 16236, + 512, 3728, 16236, + 456, 3784, 16236, + 400, 3836, 16240, + 348, 3884, 16244, + 296, 3928, 16252, + 252, 3964, 16260, + 204, 4000, 16268, + 164, 4028, 16284, + 124, 4052, 16296, + 88, 4072, 16316, + 56, 4084, 16336, + 24, 4092, 16356, + 0, 4096, 0 +}; + +const uint16_t filter_3tap_64p_117[99] = { + 2048, 2048, 0, + 1992, 2104, 16380, + 1936, 2160, 16380, + 1880, 2220, 16376, + 1824, 2276, 16376, + 1768, 2332, 16376, + 1712, 2388, 16376, + 1656, 2444, 16376, + 1600, 2496, 16380, + 1544, 2548, 0, + 1488, 2600, 4, + 1432, 2652, 8, + 1376, 2700, 16, + 1320, 2748, 20, + 1264, 2796, 32, + 1212, 2840, 40, + 1156, 2880, 52, + 1104, 2920, 64, + 1052, 2960, 80, + 1000, 2996, 92, + 948, 3032, 108, + 900, 3060, 128, + 852, 3092, 148, + 804, 3120, 168, + 756, 3144, 192, + 712, 3164, 216, + 668, 3184, 240, + 624, 3200, 268, + 580, 3212, 296, + 540, 3220, 328, + 500, 3228, 360, + 464, 3232, 392, + 428, 3236, 428 +}; + +const uint16_t filter_3tap_64p_150[99] = { + 2048, 2048, 0, + 2004, 2080, 8, + 1960, 2116, 16, + 1916, 2148, 28, + 1872, 2184, 36, + 1824, 2216, 48, + 1780, 2248, 60, + 1736, 2280, 76, + 1692, 2308, 88, + 1648, 2336, 104, + 1604, 2368, 120, + 1560, 2392, 136, + 1516, 2420, 156, + 1472, 2444, 172, + 1428, 2472, 192, + 1384, 2492, 212, + 1340, 2516, 236, + 1296, 2536, 256, + 1252, 2556, 280, + 1212, 2576, 304, + 1168, 2592, 328, + 1124, 2608, 356, + 1084, 2624, 384, + 1044, 2636, 412, + 1004, 2648, 440, + 964, 2660, 468, + 924, 2668, 500, + 884, 2676, 528, + 844, 2684, 560, + 808, 2688, 596, + 768, 2692, 628, + 732, 2696, 664, + 696, 2696, 696 +}; + +const uint16_t filter_3tap_64p_183[99] = { + 2048, 2048, 0, + 2008, 2060, 20, + 1968, 2076, 44, + 1932, 2088, 68, + 1892, 2104, 92, + 1856, 2116, 120, + 1816, 2128, 144, + 1780, 2140, 168, + 1744, 2152, 196, + 1704, 2164, 220, + 1668, 2176, 248, + 1632, 2188, 272, + 1592, 2196, 300, + 1556, 2204, 328, + 1520, 2216, 356, + 1484, 2224, 384, + 1448, 2232, 412, + 1412, 2240, 440, + 1376, 2244, 468, + 1340, 2252, 496, + 1304, 2256, 528, + 1272, 2264, 556, + 1236, 2268, 584, + 1200, 2272, 616, + 1168, 2276, 648, + 1132, 2280, 676, + 1100, 2284, 708, + 1064, 2288, 740, + 1032, 2288, 772, + 996, 2292, 800, + 964, 2292, 832, + 932, 2292, 868, + 900, 2292, 900 +}; + +const uint16_t filter_4tap_64p_upscale[132] = { + 0, 4096, 0, 0, + 16344, 4092, 40, 0, + 16308, 4084, 84, 16380, + 16272, 4072, 132, 16380, + 16240, 4056, 180, 16380, + 16212, 4036, 232, 16376, + 16184, 4012, 288, 16372, + 16160, 3984, 344, 16368, + 16136, 3952, 404, 16364, + 16116, 3916, 464, 16360, + 16100, 3872, 528, 16356, + 16084, 3828, 596, 16348, + 16072, 3780, 664, 16344, + 16060, 3728, 732, 16336, + 16052, 3676, 804, 16328, + 16044, 3616, 876, 16320, + 16040, 3556, 952, 16312, + 16036, 3492, 1028, 16300, + 16032, 3424, 1108, 16292, + 16032, 3356, 1188, 16280, + 16036, 3284, 1268, 16272, + 16036, 3212, 1352, 16260, + 16040, 3136, 1436, 16248, + 16044, 3056, 1520, 16236, + 16052, 2980, 1604, 16224, + 16060, 2896, 1688, 16212, + 16064, 2816, 1776, 16200, + 16076, 2732, 1864, 16188, + 16084, 2648, 1952, 16176, + 16092, 2564, 2040, 16164, + 16104, 2476, 2128, 16152, + 16116, 2388, 2216, 16140, + 16128, 2304, 2304, 16128 }; + +const uint16_t filter_4tap_64p_117[132] = { + 420, 3248, 420, 0, + 380, 3248, 464, 16380, + 344, 3248, 508, 16372, + 308, 3248, 552, 16368, + 272, 3240, 596, 16364, + 236, 3236, 644, 16356, + 204, 3224, 692, 16352, + 172, 3212, 744, 16344, + 144, 3196, 796, 16340, + 116, 3180, 848, 16332, + 88, 3160, 900, 16324, + 60, 3136, 956, 16320, + 36, 3112, 1012, 16312, + 16, 3084, 1068, 16304, + 16380, 3056, 1124, 16296, + 16360, 3024, 1184, 16292, + 16340, 2992, 1244, 16284, + 16324, 2956, 1304, 16276, + 16308, 2920, 1364, 16268, + 16292, 2880, 1424, 16264, + 16280, 2836, 1484, 16256, + 16268, 2792, 1548, 16252, + 16256, 2748, 1608, 16244, + 16248, 2700, 1668, 16240, + 16240, 2652, 1732, 16232, + 16232, 2604, 1792, 16228, + 16228, 2552, 1856, 16224, + 16220, 2500, 1916, 16220, + 16216, 2444, 1980, 16216, + 16216, 2388, 2040, 16216, + 16212, 2332, 2100, 16212, + 16212, 2276, 2160, 16212, + 16212, 2220, 2220, 16212 }; + +const uint16_t filter_4tap_64p_150[132] = { + 696, 2700, 696, 0, + 660, 2704, 732, 16380, + 628, 2704, 768, 16376, + 596, 2704, 804, 16372, + 564, 2700, 844, 16364, + 532, 2696, 884, 16360, + 500, 2692, 924, 16356, + 472, 2684, 964, 16352, + 440, 2676, 1004, 16352, + 412, 2668, 1044, 16348, + 384, 2656, 1088, 16344, + 360, 2644, 1128, 16340, + 332, 2632, 1172, 16336, + 308, 2616, 1216, 16336, + 284, 2600, 1260, 16332, + 260, 2580, 1304, 16332, + 236, 2560, 1348, 16328, + 216, 2540, 1392, 16328, + 196, 2516, 1436, 16328, + 176, 2492, 1480, 16324, + 156, 2468, 1524, 16324, + 136, 2440, 1568, 16328, + 120, 2412, 1612, 16328, + 104, 2384, 1656, 16328, + 88, 2352, 1700, 16332, + 72, 2324, 1744, 16332, + 60, 2288, 1788, 16336, + 48, 2256, 1828, 16340, + 36, 2220, 1872, 16344, + 24, 2184, 1912, 16352, + 12, 2148, 1952, 16356, + 4, 2112, 1996, 16364, + 16380, 2072, 2036, 16372 }; + +const uint16_t filter_4tap_64p_183[132] = { + 944, 2204, 944, 0, + 916, 2204, 972, 0, + 888, 2200, 996, 0, + 860, 2200, 1024, 4, + 832, 2196, 1052, 4, + 808, 2192, 1080, 8, + 780, 2188, 1108, 12, + 756, 2180, 1140, 12, + 728, 2176, 1168, 16, + 704, 2168, 1196, 20, + 680, 2160, 1224, 24, + 656, 2152, 1252, 28, + 632, 2144, 1280, 36, + 608, 2132, 1308, 40, + 584, 2120, 1336, 48, + 560, 2112, 1364, 52, + 536, 2096, 1392, 60, + 516, 2084, 1420, 68, + 492, 2072, 1448, 76, + 472, 2056, 1476, 84, + 452, 2040, 1504, 92, + 428, 2024, 1532, 100, + 408, 2008, 1560, 112, + 392, 1992, 1584, 120, + 372, 1972, 1612, 132, + 352, 1956, 1636, 144, + 336, 1936, 1664, 156, + 316, 1916, 1688, 168, + 300, 1896, 1712, 180, + 284, 1876, 1736, 192, + 268, 1852, 1760, 208, + 252, 1832, 1784, 220, + 236, 1808, 1808, 236 }; + +const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_3tap_16p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_3tap_16p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_3tap_16p_150; + else + return filter_3tap_16p_183; +} + +const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_3tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_3tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_3tap_64p_150; + else + return filter_3tap_64p_183; +} + +const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_4tap_16p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_4tap_16p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_4tap_16p_150; + else + return filter_4tap_16p_183; +} + +const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_4tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_4tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_4tap_64p_150; + else + return filter_4tap_64p_183; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c new file mode 100644 index 000000000000..842182ce93a8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -0,0 +1,1302 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dc_bios_types.h" +#include "dce_stream_encoder.h" +#include "reg_helper.h" + +enum DP_PIXEL_ENCODING { +DP_PIXEL_ENCODING_RGB444 = 0x00000000, +DP_PIXEL_ENCODING_YCBCR422 = 0x00000001, +DP_PIXEL_ENCODING_YCBCR444 = 0x00000002, +DP_PIXEL_ENCODING_RGB_WIDE_GAMUT = 0x00000003, +DP_PIXEL_ENCODING_Y_ONLY = 0x00000004, +DP_PIXEL_ENCODING_YCBCR420 = 0x00000005, +DP_PIXEL_ENCODING_RESERVED = 0x00000006, +}; + + +enum DP_COMPONENT_DEPTH { +DP_COMPONENT_DEPTH_6BPC = 0x00000000, +DP_COMPONENT_DEPTH_8BPC = 0x00000001, +DP_COMPONENT_DEPTH_10BPC = 0x00000002, +DP_COMPONENT_DEPTH_12BPC = 0x00000003, +DP_COMPONENT_DEPTH_16BPC = 0x00000004, +DP_COMPONENT_DEPTH_RESERVED = 0x00000005, +}; + + +#define REG(reg)\ + (enc110->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc110->se_shift->field_name, enc110->se_mask->field_name + +#define VBI_LINE_0 0 +#define DP_BLANK_MAX_RETRY 20 +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 + +#ifndef TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK + #define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L + #define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L + #define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004 + #define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008 +#endif + +enum { + DP_MST_UPDATE_MAX_RETRY = 50 +}; + +#define DCE110_SE(audio)\ + container_of(audio, struct dce110_stream_encoder, base) + +#define CTX \ + enc110->base.ctx + +static void dce110_update_generic_info_packet( + struct dce110_stream_encoder *enc110, + uint32_t packet_index, + const struct encoder_info_packet *info_packet) +{ + uint32_t regval; + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + + if (REG(AFMT_VBI_PACKET_CONTROL1)) { + if (packet_index >= 8) + ASSERT(0); + + /* poll dig_update_lock is not locked -> asic internal signal + * assume otg master lock will unlock it + */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, + 1, 10, max_retries); + + /* check if HW reading GSP memory */ + REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, + 1, 10, max_retries); + + /* HW does is not reading GSP memory not reading too long -> + * something wrong. clear GPS memory access and notify? + * hw SW is writing to GSP memory + */ + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, 1); + } + /* choose which generic packet to use */ + { + regval = REG_READ(AFMT_VBI_PACKET_CONTROL); + REG_UPDATE(AFMT_VBI_PACKET_CONTROL, + AFMT_GENERIC_INDEX, packet_index); + } + + /* write generic packet header + * (4th byte is for GENERIC0 only) */ + { + REG_SET_4(AFMT_GENERIC_HDR, 0, + AFMT_GENERIC_HB0, info_packet->hb0, + AFMT_GENERIC_HB1, info_packet->hb1, + AFMT_GENERIC_HB2, info_packet->hb2, + AFMT_GENERIC_HB3, info_packet->hb3); + } + + /* write generic packet contents + * (we never use last 4 bytes) + * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers */ + { + const uint32_t *content = + (const uint32_t *) &info_packet->sb[0]; + + REG_WRITE(AFMT_GENERIC_0, *content++); + REG_WRITE(AFMT_GENERIC_1, *content++); + REG_WRITE(AFMT_GENERIC_2, *content++); + REG_WRITE(AFMT_GENERIC_3, *content++); + REG_WRITE(AFMT_GENERIC_4, *content++); + REG_WRITE(AFMT_GENERIC_5, *content++); + REG_WRITE(AFMT_GENERIC_6, *content); + REG_WRITE(AFMT_GENERIC_7, 0); + } + + if (!REG(AFMT_VBI_PACKET_CONTROL1)) { + /* force double-buffered packet update */ + REG_UPDATE_2(AFMT_VBI_PACKET_CONTROL, + AFMT_GENERIC0_UPDATE, (packet_index == 0), + AFMT_GENERIC2_UPDATE, (packet_index == 2)); + } +} + +static void dce110_update_hdmi_info_packet( + struct dce110_stream_encoder *enc110, + uint32_t packet_index, + const struct encoder_info_packet *info_packet) +{ + struct dc_context *ctx = enc110->base.ctx; + uint32_t cont, send, line; + + if (info_packet->valid) { + dce110_update_generic_info_packet( + enc110, + packet_index, + info_packet); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 3: + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + default: + /* invalid HW packet index */ + dm_logger_write( + ctx->logger, LOG_WARNING, + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +/* setup stream encoder in dp mode */ +static void dce110_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space) +{ + + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + /* set pixel encoding */ + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_YCBCR422); + break; + case PIXEL_ENCODING_YCBCR444: + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_YCBCR444); + + if (crtc_timing->flags.Y_ONLY) + if (crtc_timing->display_color_depth != COLOR_DEPTH_666) + /* HW testing only, no use case yet. + * Color depth of Y-only could be + * 8, 10, 12, 16 bits */ + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_Y_ONLY); + /* Note: DP_MSA_MISC1 bit 7 is the indicator + * of Y-only mode. + * This bit is set in HW if register + * DP_PIXEL_ENCODING is programmed to 0x4 */ + break; + case PIXEL_ENCODING_YCBCR420: + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_YCBCR420); + if (enc110->se_mask->DP_VID_M_DOUBLE_VALUE_EN) + REG_UPDATE(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, 1); + + break; + default: + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, + DP_PIXEL_ENCODING_RGB444); + break; + } + + /* set color depth */ + + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + 0); + break; + case COLOR_DEPTH_888: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + DP_COMPONENT_DEPTH_8BPC); + break; + case COLOR_DEPTH_101010: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + DP_COMPONENT_DEPTH_10BPC); + + break; + case COLOR_DEPTH_121212: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + DP_COMPONENT_DEPTH_12BPC); + break; + default: + REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, + DP_COMPONENT_DEPTH_6BPC); + break; + } + + /* set dynamic range and YCbCr range */ + if (enc110->se_mask->DP_DYN_RANGE && enc110->se_mask->DP_YCBCR_RANGE) + REG_UPDATE_2( + DP_PIXEL_FORMAT, + DP_DYN_RANGE, 0, + DP_YCBCR_RANGE, 0); + +} + +static void dce110_stream_encoder_set_stream_attribute_helper( + struct dce110_stream_encoder *enc110, + struct dc_crtc_timing *crtc_timing) +{ + if (enc110->regs->TMDS_CNTL) { + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(TMDS_CNTL, TMDS_PIXEL_ENCODING, 1); + break; + default: + REG_UPDATE(TMDS_CNTL, TMDS_PIXEL_ENCODING, 0); + break; + } + REG_UPDATE(TMDS_CNTL, TMDS_COLOR_FORMAT, 0); + } else if (enc110->regs->DIG_FE_CNTL) { + switch (crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 1); + break; + default: + REG_UPDATE(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, 0); + break; + } + REG_UPDATE(DIG_FE_CNTL, TMDS_COLOR_FORMAT, 0); + } + +} + +/* setup stream encoder in hdmi mode */ +static void dce110_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc110->base.id; + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.enable_dp_audio = enable_audio; + cntl.pixel_clock = actual_pix_clk_khz; + cntl.lanes_number = LANE_COUNT_FOUR; + + if (enc110->base.bp->funcs->encoder_control( + enc110->base.bp, &cntl) != BP_RESULT_OK) + return; + + dce110_stream_encoder_set_stream_attribute_helper(enc110, crtc_timing); + + /* setup HDMI engine */ + if (!enc110->se_mask->HDMI_DATA_SCRAMBLE_EN) { + REG_UPDATE_3(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + } else if (enc110->regs->DIG_FE_CNTL) { + REG_UPDATE_5(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_888: + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); + break; + case COLOR_DEPTH_101010: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + case COLOR_DEPTH_121212: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + default: + break; + } + + if (enc110->se_mask->HDMI_DATA_SCRAMBLE_EN) { + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M + * Clock channel frequency is 1/4 of character rate. + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 1); + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { + + /* TODO: New feature for DCE11, still need to implement */ + + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE + * Clock channel frequency is the same + * as character rate + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + } + + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, + HDMI_GC_CONT, 1, + HDMI_GC_SEND, 1, + HDMI_NULL_SEND, 1); + + /* following belongs to audio */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); + + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, + VBI_LINE_0 + 2); + + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); + +} + +/* setup stream encoder in dvi mode */ +static void dce110_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc110->base.id; + cntl.signal = is_dual_link ? + SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.enable_dp_audio = false; + cntl.pixel_clock = crtc_timing->pix_clk_khz; + cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; + + if (enc110->base.bp->funcs->encoder_control( + enc110->base.bp, &cntl) != BP_RESULT_OK) + return; + + ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); + ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); + dce110_stream_encoder_set_stream_attribute_helper(enc110, crtc_timing); +} + +static void dce110_stream_encoder_set_mst_bandwidth( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t x = dal_fixed31_32_floor( + avg_time_slots_per_mtp); + uint32_t y = dal_fixed31_32_ceil( + dal_fixed31_32_shl( + dal_fixed31_32_sub_int( + avg_time_slots_per_mtp, + x), + 26)); + + { + REG_SET_2(DP_MSE_RATE_CNTL, 0, + DP_MSE_RATE_X, x, + DP_MSE_RATE_Y, y); + } + + /* wait for update to be completed on the link */ + /* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */ + /* is reset to 0 (not pending) */ + REG_WAIT(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, + 0, + 10, DP_MST_UPDATE_MAX_RETRY); +} + +static void dce110_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + if (enc110->se_mask->HDMI_AVI_INFO_CONT && + enc110->se_mask->HDMI_AVI_INFO_SEND) { + + if (info_frame->avi.valid) { + const uint32_t *content = + (const uint32_t *) &info_frame->avi.sb[0]; + + REG_WRITE(AFMT_AVI_INFO0, content[0]); + + REG_WRITE(AFMT_AVI_INFO1, content[1]); + + REG_WRITE(AFMT_AVI_INFO2, content[2]); + + REG_WRITE(AFMT_AVI_INFO3, content[3]); + + REG_UPDATE(AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, + info_frame->avi.hb1); + + REG_UPDATE_2(HDMI_INFOFRAME_CONTROL0, + HDMI_AVI_INFO_SEND, 1, + HDMI_AVI_INFO_CONT, 1); + + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, + VBI_LINE_0 + 2); + + } else { + REG_UPDATE_2(HDMI_INFOFRAME_CONTROL0, + HDMI_AVI_INFO_SEND, 0, + HDMI_AVI_INFO_CONT, 0); + } + } + + if (enc110->se_mask->HDMI_AVI_INFO_CONT && + enc110->se_mask->HDMI_AVI_INFO_SEND) { + dce110_update_hdmi_info_packet(enc110, 0, &info_frame->vendor); + dce110_update_hdmi_info_packet(enc110, 1, &info_frame->gamut); + dce110_update_hdmi_info_packet(enc110, 2, &info_frame->spd); + } + +} + +static void dce110_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + /* stop generic packets 0 & 1 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0); + + /* stop generic packets 2 & 3 on HDMI */ + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); + +} + +static void dce110_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t value = REG_READ(DP_SEC_CNTL); + + if (info_frame->vsc.valid) + dce110_update_generic_info_packet( + enc110, + 0, /* packetIndex */ + &info_frame->vsc); + + /* enable/disable transmission of packet(s). + * If enabled, packet transmission begins on the next frame + */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void dce110_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc) +{ + /* stop generic packets on DP */ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t value = REG_READ(DP_SEC_CNTL); + + if (enc110->se_mask->DP_SEC_AVI_ENABLE) { + REG_SET_7(DP_SEC_CNTL, 0, + DP_SEC_GSP0_ENABLE, 0, + DP_SEC_GSP1_ENABLE, 0, + DP_SEC_GSP2_ENABLE, 0, + DP_SEC_GSP3_ENABLE, 0, + DP_SEC_AVI_ENABLE, 0, + DP_SEC_MPG_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + } + + /* this register shared with audio info frame. + * therefore we need to keep master enabled + * if at least one of the fields is not 0 */ + + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + +} + +static void dce110_stream_encoder_dp_blank( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t retries = 0; + uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; + + /* Note: For CZ, we are changing driver default to disable + * stream deferred to next VBLANK. If results are positive, we + * will make the same change to all DCE versions. There are a + * handful of panels that cannot handle disable stream at + * HBLANK and will result in a white line flash across the + * screen on stream disable. */ + + /* Specify the video stream disable point + * (2 = start of the next vertical blank) */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2); + /* Larger delay to wait until VBLANK - use max retry of + * 10us*3000=30ms. This covers 16.6ms of typical 60 Hz mode + + * a little more because we may not trust delay accuracy. + */ + max_retries = DP_BLANK_MAX_RETRY * 150; + + /* disable DP stream */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + /* the encoder stops sending the video stream + * at the start of the vertical blanking. + * Poll for DP_VID_STREAM_STATUS == 0 + */ + + REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, + 1, + 10, max_retries); + + ASSERT(retries <= max_retries); + + /* Tell the DP encoder to ignore timing from CRTC, must be done after + * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is + * complete, stream status will be stuck in video stream enabled state, + * i.e. DP_VID_STREAM_STATUS stuck at 1. + */ + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); +} + +/* output video stream to link encoder */ +static void dce110_stream_encoder_dp_unblank( + struct stream_encoder *enc, + const struct encoder_unblank_param *param) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) { + uint32_t n_vid = 0x8000; + uint32_t m_vid; + + /* M / N = Fstream / Flink + * m_vid / n_vid = pixel rate / link rate + */ + + uint64_t m_vid_l = n_vid; + + m_vid_l *= param->crtc_timing.pixel_clock; + m_vid_l = div_u64(m_vid_l, + param->link_settings.link_rate + * LINK_RATE_REF_FREQ_IN_KHZ); + + m_vid = (uint32_t) m_vid_l; + + /* enable auto measurement */ + + REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 0); + + /* auto measurement need 1 full 0x8000 symbol cycle to kick in, + * therefore program initial value for Mvid and Nvid + */ + + REG_UPDATE(DP_VID_N, DP_VID_N, n_vid); + + REG_UPDATE(DP_VID_M, DP_VID_M, m_vid); + + REG_UPDATE(DP_VID_TIMING, DP_VID_M_N_GEN_EN, 1); + } + + /* set DIG_START to 0x1 to resync FIFO */ + + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + + /* switch DP encoder to CRTC data */ + + REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0); + + /* wait 100us for DIG/DP logic to prime + * (i.e. a few video lines) + */ + udelay(100); + + /* the hardware would start sending video at the start of the next DP + * frame (i.e. rising edge of the vblank). + * NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this + * register has no effect on enable transition! HW always guarantees + * VID_STREAM enable at start of next frame, and this is not + * programmable + */ + + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); +} + + +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 + +#include "include/audio_types.h" + +/** +* speakersToChannels +* +* @brief +* translate speakers to channels +* +* FL - Front Left +* FR - Front Right +* RL - Rear Left +* RR - Rear Right +* RC - Rear Center +* FC - Front Center +* FLC - Front Left Center +* FRC - Front Right Center +* RLC - Rear Left Center +* RRC - Rear Right Center +* LFE - Low Freq Effect +* +* FC +* FLC FRC +* FL FR +* +* LFE +* () +* +* +* RL RR +* RLC RRC +* RC +* +* ch 8 7 6 5 4 3 2 1 +* 0b00000011 - - - - - - FR FL +* 0b00000111 - - - - - LFE FR FL +* 0b00001011 - - - - FC - FR FL +* 0b00001111 - - - - FC LFE FR FL +* 0b00010011 - - - RC - - FR FL +* 0b00010111 - - - RC - LFE FR FL +* 0b00011011 - - - RC FC - FR FL +* 0b00011111 - - - RC FC LFE FR FL +* 0b00110011 - - RR RL - - FR FL +* 0b00110111 - - RR RL - LFE FR FL +* 0b00111011 - - RR RL FC - FR FL +* 0b00111111 - - RR RL FC LFE FR FL +* 0b01110011 - RC RR RL - - FR FL +* 0b01110111 - RC RR RL - LFE FR FL +* 0b01111011 - RC RR RL FC - FR FL +* 0b01111111 - RC RR RL FC LFE FR FL +* 0b11110011 RRC RLC RR RL - - FR FL +* 0b11110111 RRC RLC RR RL - LFE FR FL +* 0b11111011 RRC RLC RR RL FC - FR FL +* 0b11111111 RRC RLC RR RL FC LFE FR FL +* 0b11000011 FRC FLC - - - - FR FL +* 0b11000111 FRC FLC - - - LFE FR FL +* 0b11001011 FRC FLC - - FC - FR FL +* 0b11001111 FRC FLC - - FC LFE FR FL +* 0b11010011 FRC FLC - RC - - FR FL +* 0b11010111 FRC FLC - RC - LFE FR FL +* 0b11011011 FRC FLC - RC FC - FR FL +* 0b11011111 FRC FLC - RC FC LFE FR FL +* 0b11110011 FRC FLC RR RL - - FR FL +* 0b11110111 FRC FLC RR RL - LFE FR FL +* 0b11111011 FRC FLC RR RL FC - FR FL +* 0b11111111 FRC FLC RR RL FC LFE FR FL +* +* @param +* speakers - speaker information as it comes from CEA audio block +*/ +/* translate speakers to channels */ + +union audio_cea_channels { + uint8_t all; + struct audio_cea_channels_bits { + uint32_t FL:1; + uint32_t FR:1; + uint32_t LFE:1; + uint32_t FC:1; + uint32_t RL_RC:1; + uint32_t RR:1; + uint32_t RC_RLC_FLC:1; + uint32_t RRC_FRC:1; + } channels; +}; + +struct audio_clock_info { + /* pixel clock frequency*/ + uint32_t pixel_clock_in_10khz; + /* N - 32KHz audio */ + uint32_t n_32khz; + /* CTS - 32KHz audio*/ + uint32_t cts_32khz; + uint32_t n_44khz; + uint32_t cts_44khz; + uint32_t n_48khz; + uint32_t cts_48khz; +}; + +/* 25.2MHz/1.001*/ +/* 25.2MHz/1.001*/ +/* 25.2MHz*/ +/* 27MHz */ +/* 27MHz*1.001*/ +/* 27MHz*1.001*/ +/* 54MHz*/ +/* 54MHz*1.001*/ +/* 74.25MHz/1.001*/ +/* 74.25MHz*/ +/* 148.5MHz/1.001*/ +/* 148.5MHz*/ + +static const struct audio_clock_info audio_clock_info_table[12] = { + {2517, 4576, 28125, 7007, 31250, 6864, 28125}, + {2518, 4576, 28125, 7007, 31250, 6864, 28125}, + {2520, 4096, 25200, 6272, 28000, 6144, 25200}, + {2700, 4096, 27000, 6272, 30000, 6144, 27000}, + {2702, 4096, 27027, 6272, 30030, 6144, 27027}, + {2703, 4096, 27027, 6272, 30030, 6144, 27027}, + {5400, 4096, 54000, 6272, 60000, 6144, 54000}, + {5405, 4096, 54054, 6272, 60060, 6144, 54054}, + {7417, 11648, 210937, 17836, 234375, 11648, 140625}, + {7425, 4096, 74250, 6272, 82500, 6144, 74250}, + {14835, 11648, 421875, 8918, 234375, 5824, 140625}, + {14850, 4096, 148500, 6272, 165000, 6144, 148500} +}; + +static const struct audio_clock_info audio_clock_info_table_36bpc[12] = { + {2517, 9152, 84375, 7007, 48875, 9152, 56250}, + {2518, 9152, 84375, 7007, 48875, 9152, 56250}, + {2520, 4096, 37800, 6272, 42000, 6144, 37800}, + {2700, 4096, 40500, 6272, 45000, 6144, 40500}, + {2702, 8192, 81081, 6272, 45045, 8192, 54054}, + {2703, 8192, 81081, 6272, 45045, 8192, 54054}, + {5400, 4096, 81000, 6272, 90000, 6144, 81000}, + {5405, 4096, 81081, 6272, 90090, 6144, 81081}, + {7417, 11648, 316406, 17836, 351562, 11648, 210937}, + {7425, 4096, 111375, 6272, 123750, 6144, 111375}, + {14835, 11648, 632812, 17836, 703125, 11648, 421875}, + {14850, 4096, 222750, 6272, 247500, 6144, 222750} +}; + +static const struct audio_clock_info audio_clock_info_table_48bpc[12] = { + {2517, 4576, 56250, 7007, 62500, 6864, 56250}, + {2518, 4576, 56250, 7007, 62500, 6864, 56250}, + {2520, 4096, 50400, 6272, 56000, 6144, 50400}, + {2700, 4096, 54000, 6272, 60000, 6144, 54000}, + {2702, 4096, 54054, 6267, 60060, 8192, 54054}, + {2703, 4096, 54054, 6272, 60060, 8192, 54054}, + {5400, 4096, 108000, 6272, 120000, 6144, 108000}, + {5405, 4096, 108108, 6272, 120120, 6144, 108108}, + {7417, 11648, 421875, 17836, 468750, 11648, 281250}, + {7425, 4096, 148500, 6272, 165000, 6144, 148500}, + {14835, 11648, 843750, 8918, 468750, 11648, 281250}, + {14850, 4096, 297000, 6272, 330000, 6144, 297000} +}; + +union audio_cea_channels speakers_to_channels( + struct audio_speaker_flags speaker_flags) +{ + union audio_cea_channels cea_channels = {0}; + + /* these are one to one */ + cea_channels.channels.FL = speaker_flags.FL_FR; + cea_channels.channels.FR = speaker_flags.FL_FR; + cea_channels.channels.LFE = speaker_flags.LFE; + cea_channels.channels.FC = speaker_flags.FC; + + /* if Rear Left and Right exist move RC speaker to channel 7 + * otherwise to channel 5 + */ + if (speaker_flags.RL_RR) { + cea_channels.channels.RL_RC = speaker_flags.RL_RR; + cea_channels.channels.RR = speaker_flags.RL_RR; + cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; + } else { + cea_channels.channels.RL_RC = speaker_flags.RC; + } + + /* FRONT Left Right Center and REAR Left Right Center are exclusive */ + if (speaker_flags.FLC_FRC) { + cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; + cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; + } else { + cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; + cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; + } + + return cea_channels; +} + +uint32_t calc_max_audio_packets_per_line( + const struct audio_crtc_info *crtc_info) +{ + uint32_t max_packets_per_line; + + max_packets_per_line = + crtc_info->h_total - crtc_info->h_active; + + if (crtc_info->pixel_repetition) + max_packets_per_line *= crtc_info->pixel_repetition; + + /* for other hdmi features */ + max_packets_per_line -= 58; + /* for Control Period */ + max_packets_per_line -= 16; + /* Number of Audio Packets per Line */ + max_packets_per_line /= 32; + + return max_packets_per_line; +} + +bool get_audio_clock_info( + enum dc_color_depth color_depth, + uint32_t crtc_pixel_clock_in_khz, + uint32_t actual_pixel_clock_in_khz, + struct audio_clock_info *audio_clock_info) +{ + const struct audio_clock_info *clock_info; + uint32_t index; + uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10; + uint32_t audio_array_size; + + if (audio_clock_info == NULL) + return false; /* should not happen */ + + switch (color_depth) { + case COLOR_DEPTH_161616: + clock_info = audio_clock_info_table_48bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_48bpc); + break; + case COLOR_DEPTH_121212: + clock_info = audio_clock_info_table_36bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_36bpc); + break; + default: + clock_info = audio_clock_info_table; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table); + break; + } + + if (clock_info != NULL) { + /* search for exact pixel clock in table */ + for (index = 0; index < audio_array_size; index++) { + if (clock_info[index].pixel_clock_in_10khz > + crtc_pixel_clock_in_10khz) + break; /* not match */ + else if (clock_info[index].pixel_clock_in_10khz == + crtc_pixel_clock_in_10khz) { + /* match found */ + *audio_clock_info = clock_info[index]; + return true; + } + } + } + + /* not found */ + if (actual_pixel_clock_in_khz == 0) + actual_pixel_clock_in_khz = crtc_pixel_clock_in_khz; + + /* See HDMI spec the table entry under + * pixel clock of "Other". */ + audio_clock_info->pixel_clock_in_10khz = + actual_pixel_clock_in_khz / 10; + audio_clock_info->cts_32khz = actual_pixel_clock_in_khz; + audio_clock_info->cts_44khz = actual_pixel_clock_in_khz; + audio_clock_info->cts_48khz = actual_pixel_clock_in_khz; + + audio_clock_info->n_32khz = 4096; + audio_clock_info->n_44khz = 6272; + audio_clock_info->n_48khz = 6144; + + return true; +} + +static void dce110_se_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *audio_info) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + uint32_t speakers = 0; + uint32_t channels = 0; + + ASSERT(audio_info); + if (audio_info == NULL) + /* This should not happen.it does so we don't get BSOD*/ + return; + + speakers = audio_info->flags.info.ALLSPEAKERS; + channels = speakers_to_channels(audio_info->flags.speaker_flags).all; + + /* setup the audio stream source select (audio -> dig mapping) */ + REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst); + + /* Channel allocation */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels); +} + +static void dce110_se_setup_hdmi_audio( + struct stream_encoder *enc, + const struct audio_crtc_info *crtc_info) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + struct audio_clock_info audio_clock_info = {0}; + uint32_t max_packets_per_line; + + /* For now still do calculation, although this field is ignored when + above HDMI_PACKET_GEN_VERSION set to 1 */ + max_packets_per_line = calc_max_audio_packets_per_line(crtc_info); + + /* HDMI_AUDIO_PACKET_CONTROL */ + REG_UPDATE_2(HDMI_AUDIO_PACKET_CONTROL, + HDMI_AUDIO_PACKETS_PER_LINE, max_packets_per_line, + HDMI_AUDIO_DELAY_EN, 1); + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* HDMI_ACR_PACKET_CONTROL */ + REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, + HDMI_ACR_AUTO_SEND, 1, + HDMI_ACR_SOURCE, 0, + HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ + if (get_audio_clock_info( + crtc_info->color_depth, + crtc_info->requested_pixel_clock, + crtc_info->calculated_pixel_clock, + &audio_clock_info)) { + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + be used by HD Audio driver + HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + programmed below in interruppt callback */ + } /* if */ + + /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & + AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ + REG_UPDATE_2(AFMT_60958_0, + AFMT_60958_CS_CHANNEL_NUMBER_L, 1, + AFMT_60958_CS_CLOCK_ACCURACY, 0); + + /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ + REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2); + + /*AFMT_60958_2 now keep this settings until + * Programming guide comes out*/ + REG_UPDATE_6(AFMT_60958_2, + AFMT_60958_CS_CHANNEL_NUMBER_2, 3, + AFMT_60958_CS_CHANNEL_NUMBER_3, 4, + AFMT_60958_CS_CHANNEL_NUMBER_4, 5, + AFMT_60958_CS_CHANNEL_NUMBER_5, 6, + AFMT_60958_CS_CHANNEL_NUMBER_6, 7, + AFMT_60958_CS_CHANNEL_NUMBER_7, 8); +} + +static void dce110_se_setup_dp_audio( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + /* --- DP Audio packet configurations --- */ + + /* ATP Configuration */ + REG_SET(DP_SEC_AUD_N, 0, + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); + + /* Async/auto-calc timestamp mode */ + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); + + /* --- The following are the registers + * copied from the SetupHDMI --- */ + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + /* Program the ATP and AIP next */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* AFMT_INFOFRAME_CONTROL0 */ + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ + REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0); +} + +static void dce110_se_enable_audio_clock( + struct stream_encoder *enc, + bool enable) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + if (REG(AFMT_CNTL) == 0) + return; /* DCE8/10 does not have this register */ + + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, !!enable); + + /* wait for AFMT clock to turn on, + * expectation: this should complete in 1-2 reads + * + * REG_WAIT(AFMT_CNTL, AFMT_AUDIO_CLOCK_ON, !!enable, 1, 10); + * + * TODO: wait for clock_on does not work well. May need HW + * program sequence. But audio seems work normally even without wait + * for clock_on status change + */ +} + +static void dce110_se_enable_dp_audio( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + /* Enable Audio packets */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, 1); + + /* Program the ATP and AIP next */ + REG_UPDATE_2(DP_SEC_CNTL, + DP_SEC_ATP_ENABLE, 1, + DP_SEC_AIP_ENABLE, 1); + + /* Program STREAM_ENABLE after all the other enables. */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void dce110_se_disable_dp_audio( + struct stream_encoder *enc) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + uint32_t value = REG_READ(DP_SEC_CNTL); + + /* Disable Audio packets */ + REG_UPDATE_5(DP_SEC_CNTL, + DP_SEC_ASP_ENABLE, 0, + DP_SEC_ATP_ENABLE, 0, + DP_SEC_AIP_ENABLE, 0, + DP_SEC_ACM_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + + /* This register shared with encoder info frame. Therefore we need to + keep master enabled if at least on of the fields is not 0 */ + if (value != 0) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + +} + +void dce110_se_audio_mute_control( + struct stream_encoder *enc, + bool mute) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute); +} + +void dce110_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + dce110_se_audio_setup(enc, az_inst, info); +} + +void dce110_se_dp_audio_enable( + struct stream_encoder *enc) +{ + dce110_se_enable_audio_clock(enc, true); + dce110_se_setup_dp_audio(enc); + dce110_se_enable_dp_audio(enc); +} + +void dce110_se_dp_audio_disable( + struct stream_encoder *enc) +{ + dce110_se_disable_dp_audio(enc); + dce110_se_enable_audio_clock(enc, false); +} + +void dce110_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info) +{ + dce110_se_enable_audio_clock(enc, true); + dce110_se_setup_hdmi_audio(enc, audio_crtc_info); + dce110_se_audio_setup(enc, az_inst, info); +} + +void dce110_se_hdmi_audio_disable( + struct stream_encoder *enc) +{ + dce110_se_enable_audio_clock(enc, false); +} + +static const struct stream_encoder_funcs dce110_str_enc_funcs = { + .dp_set_stream_attribute = + dce110_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + dce110_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + dce110_stream_encoder_dvi_set_stream_attribute, + .set_mst_bandwidth = + dce110_stream_encoder_set_mst_bandwidth, + .update_hdmi_info_packets = + dce110_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + dce110_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets = + dce110_stream_encoder_update_dp_info_packets, + .stop_dp_info_packets = + dce110_stream_encoder_stop_dp_info_packets, + .dp_blank = + dce110_stream_encoder_dp_blank, + .dp_unblank = + dce110_stream_encoder_dp_unblank, + + .audio_mute_control = dce110_se_audio_mute_control, + + .dp_audio_setup = dce110_se_dp_audio_setup, + .dp_audio_enable = dce110_se_dp_audio_enable, + .dp_audio_disable = dce110_se_dp_audio_disable, + + .hdmi_audio_setup = dce110_se_hdmi_audio_setup, + .hdmi_audio_disable = dce110_se_hdmi_audio_disable, +}; + +bool dce110_stream_encoder_construct( + struct dce110_stream_encoder *enc110, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dce110_stream_enc_registers *regs, + const struct dce_stream_encoder_shift *se_shift, + const struct dce_stream_encoder_mask *se_mask) +{ + if (!enc110) + return false; + if (!bp) + return false; + + enc110->base.funcs = &dce110_str_enc_funcs; + enc110->base.ctx = ctx; + enc110->base.id = eng_id; + enc110->base.bp = bp; + enc110->regs = regs; + enc110->se_shift = se_shift; + enc110->se_mask = se_mask; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h new file mode 100644 index 000000000000..458a37000956 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -0,0 +1,564 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_STREAM_ENCODER_DCE110_H__ +#define __DC_STREAM_ENCODER_DCE110_H__ + +#include "stream_encoder.h" + +#define DCE110STRENC_FROM_STRENC(stream_encoder)\ + container_of(stream_encoder, struct dce110_stream_encoder, base) + +#ifndef TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK + #define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L + #define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L + #define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004 + #define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008 +#endif + + +#define SE_COMMON_REG_LIST_DCE_BASE(id) \ + SE_COMMON_REG_LIST_BASE(id),\ + SRI(AFMT_AVI_INFO0, DIG, id), \ + SRI(AFMT_AVI_INFO1, DIG, id), \ + SRI(AFMT_AVI_INFO2, DIG, id), \ + SRI(AFMT_AVI_INFO3, DIG, id) + +#define SE_COMMON_REG_LIST_BASE(id) \ + SRI(AFMT_GENERIC_0, DIG, id), \ + SRI(AFMT_GENERIC_1, DIG, id), \ + SRI(AFMT_GENERIC_2, DIG, id), \ + SRI(AFMT_GENERIC_3, DIG, id), \ + SRI(AFMT_GENERIC_4, DIG, id), \ + SRI(AFMT_GENERIC_5, DIG, id), \ + SRI(AFMT_GENERIC_6, DIG, id), \ + SRI(AFMT_GENERIC_7, DIG, id), \ + SRI(AFMT_GENERIC_HDR, DIG, id), \ + SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \ + SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \ + SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \ + SRI(AFMT_60958_0, DIG, id), \ + SRI(AFMT_60958_1, DIG, id), \ + SRI(AFMT_60958_2, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(HDMI_CONTROL, DIG, id), \ + SRI(HDMI_GC, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_32_0, DIG, id),\ + SRI(HDMI_ACR_32_1, DIG, id),\ + SRI(HDMI_ACR_44_0, DIG, id),\ + SRI(HDMI_ACR_44_1, DIG, id),\ + SRI(HDMI_ACR_48_0, DIG, id),\ + SRI(HDMI_ACR_48_1, DIG, id),\ + SRI(TMDS_CNTL, DIG, id), \ + SRI(DP_MSE_RATE_CNTL, DP, id), \ + SRI(DP_MSE_RATE_UPDATE, DP, id), \ + SRI(DP_PIXEL_FORMAT, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_STEER_FIFO, DP, id), \ + SRI(DP_VID_M, DP, id), \ + SRI(DP_VID_N, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_VID_TIMING, DP, id), \ + SRI(DP_SEC_AUD_N, DP, id), \ + SRI(DP_SEC_TIMESTAMP, DP, id) + +#define SE_COMMON_REG_LIST(id)\ + SE_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(AFMT_CNTL, DIG, id) + +#define SE_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ + SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ + SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\ + SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, mask_sh),\ + SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ + SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\ + SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\ + SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DP_PIXEL_FORMAT, DP_DYN_RANGE, mask_sh),\ + SE_SF(DP_PIXEL_FORMAT, DP_YCBCR_RANGE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, mask_sh),\ + SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ + SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ + SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ + SE_SF(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ + SE_SF(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ + SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ + SE_SF(DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\ + SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCE80_100(mask_sh)\ + SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ + SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCE110(mask_sh)\ + SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ + SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) + +#define SE_COMMON_MASK_SH_LIST_DCE112(mask_sh)\ + SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ + SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) + +struct dce_stream_encoder_shift { + uint8_t AFMT_GENERIC_INDEX; + uint8_t AFMT_GENERIC0_UPDATE; + uint8_t AFMT_GENERIC2_UPDATE; + uint8_t AFMT_GENERIC_HB0; + uint8_t AFMT_GENERIC_HB1; + uint8_t AFMT_GENERIC_HB2; + uint8_t AFMT_GENERIC_HB3; + uint8_t AFMT_GENERIC_LOCK_STATUS; + uint8_t AFMT_GENERIC_CONFLICT; + uint8_t AFMT_GENERIC_CONFLICT_CLR; + uint8_t AFMT_GENERIC0_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC1_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC2_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC3_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC4_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC5_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC6_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC7_FRAME_UPDATE_PENDING; + uint8_t AFMT_GENERIC0_FRAME_UPDATE; + uint8_t AFMT_GENERIC1_FRAME_UPDATE; + uint8_t AFMT_GENERIC2_FRAME_UPDATE; + uint8_t AFMT_GENERIC3_FRAME_UPDATE; + uint8_t AFMT_GENERIC4_FRAME_UPDATE; + uint8_t AFMT_GENERIC5_FRAME_UPDATE; + uint8_t AFMT_GENERIC6_FRAME_UPDATE; + uint8_t AFMT_GENERIC7_FRAME_UPDATE; + uint8_t HDMI_GENERIC0_CONT; + uint8_t HDMI_GENERIC0_SEND; + uint8_t HDMI_GENERIC0_LINE; + uint8_t HDMI_GENERIC1_CONT; + uint8_t HDMI_GENERIC1_SEND; + uint8_t HDMI_GENERIC1_LINE; + uint8_t DP_PIXEL_ENCODING; + uint8_t DP_COMPONENT_DEPTH; + uint8_t DP_DYN_RANGE; + uint8_t DP_YCBCR_RANGE; + uint8_t HDMI_PACKET_GEN_VERSION; + uint8_t HDMI_KEEPOUT_MODE; + uint8_t HDMI_DEEP_COLOR_ENABLE; + uint8_t HDMI_CLOCK_CHANNEL_RATE; + uint8_t HDMI_DEEP_COLOR_DEPTH; + uint8_t HDMI_GC_CONT; + uint8_t HDMI_GC_SEND; + uint8_t HDMI_NULL_SEND; + uint8_t HDMI_DATA_SCRAMBLE_EN; + uint8_t HDMI_AUDIO_INFO_SEND; + uint8_t AFMT_AUDIO_INFO_UPDATE; + uint8_t HDMI_AUDIO_INFO_LINE; + uint8_t HDMI_GC_AVMUTE; + uint8_t DP_MSE_RATE_X; + uint8_t DP_MSE_RATE_Y; + uint8_t DP_MSE_RATE_UPDATE_PENDING; + uint8_t AFMT_AVI_INFO_VERSION; + uint8_t HDMI_AVI_INFO_SEND; + uint8_t HDMI_AVI_INFO_CONT; + uint8_t HDMI_AVI_INFO_LINE; + uint8_t DP_SEC_GSP0_ENABLE; + uint8_t DP_SEC_STREAM_ENABLE; + uint8_t DP_SEC_GSP1_ENABLE; + uint8_t DP_SEC_GSP2_ENABLE; + uint8_t DP_SEC_GSP3_ENABLE; + uint8_t DP_SEC_GSP4_ENABLE; + uint8_t DP_SEC_GSP5_ENABLE; + uint8_t DP_SEC_GSP6_ENABLE; + uint8_t DP_SEC_GSP7_ENABLE; + uint8_t DP_SEC_AVI_ENABLE; + uint8_t DP_SEC_MPG_ENABLE; + uint8_t DP_VID_STREAM_DIS_DEFER; + uint8_t DP_VID_STREAM_ENABLE; + uint8_t DP_VID_STREAM_STATUS; + uint8_t DP_STEER_FIFO_RESET; + uint8_t DP_VID_M_N_GEN_EN; + uint8_t DP_VID_N; + uint8_t DP_VID_M; + uint8_t DIG_START; + uint8_t AFMT_AUDIO_SRC_SELECT; + uint8_t AFMT_AUDIO_CHANNEL_ENABLE; + uint8_t HDMI_AUDIO_PACKETS_PER_LINE; + uint8_t HDMI_AUDIO_DELAY_EN; + uint8_t AFMT_60958_CS_UPDATE; + uint8_t AFMT_AUDIO_LAYOUT_OVRD; + uint8_t AFMT_60958_OSF_OVRD; + uint8_t HDMI_ACR_AUTO_SEND; + uint8_t HDMI_ACR_SOURCE; + uint8_t HDMI_ACR_AUDIO_PRIORITY; + uint8_t HDMI_ACR_CTS_32; + uint8_t HDMI_ACR_N_32; + uint8_t HDMI_ACR_CTS_44; + uint8_t HDMI_ACR_N_44; + uint8_t HDMI_ACR_CTS_48; + uint8_t HDMI_ACR_N_48; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_L; + uint8_t AFMT_60958_CS_CLOCK_ACCURACY; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_R; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_2; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_3; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_4; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_5; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_6; + uint8_t AFMT_60958_CS_CHANNEL_NUMBER_7; + uint8_t DP_SEC_AUD_N; + uint8_t DP_SEC_TIMESTAMP_MODE; + uint8_t DP_SEC_ASP_ENABLE; + uint8_t DP_SEC_ATP_ENABLE; + uint8_t DP_SEC_AIP_ENABLE; + uint8_t DP_SEC_ACM_ENABLE; + uint8_t AFMT_AUDIO_SAMPLE_SEND; + uint8_t AFMT_AUDIO_CLOCK_EN; + uint8_t TMDS_PIXEL_ENCODING; + uint8_t TMDS_COLOR_FORMAT; + uint8_t DP_DB_DISABLE; + uint8_t DP_MSA_MISC0; + uint8_t DP_MSA_HTOTAL; + uint8_t DP_MSA_VTOTAL; + uint8_t DP_MSA_HSTART; + uint8_t DP_MSA_VSTART; + uint8_t DP_MSA_HSYNCWIDTH; + uint8_t DP_MSA_HSYNCPOLARITY; + uint8_t DP_MSA_VSYNCWIDTH; + uint8_t DP_MSA_VSYNCPOLARITY; + uint8_t DP_MSA_HWIDTH; + uint8_t DP_MSA_VHEIGHT; + uint8_t HDMI_DB_DISABLE; + uint8_t DP_VID_N_MUL; + uint8_t DP_VID_M_DOUBLE_VALUE_EN; +}; + +struct dce_stream_encoder_mask { + uint32_t AFMT_GENERIC_INDEX; + uint32_t AFMT_GENERIC0_UPDATE; + uint32_t AFMT_GENERIC2_UPDATE; + uint32_t AFMT_GENERIC_HB0; + uint32_t AFMT_GENERIC_HB1; + uint32_t AFMT_GENERIC_HB2; + uint32_t AFMT_GENERIC_HB3; + uint32_t AFMT_GENERIC_LOCK_STATUS; + uint32_t AFMT_GENERIC_CONFLICT; + uint32_t AFMT_GENERIC_CONFLICT_CLR; + uint32_t AFMT_GENERIC0_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC1_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC2_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC3_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC4_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC5_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC6_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC7_FRAME_UPDATE_PENDING; + uint32_t AFMT_GENERIC0_FRAME_UPDATE; + uint32_t AFMT_GENERIC1_FRAME_UPDATE; + uint32_t AFMT_GENERIC2_FRAME_UPDATE; + uint32_t AFMT_GENERIC3_FRAME_UPDATE; + uint32_t AFMT_GENERIC4_FRAME_UPDATE; + uint32_t AFMT_GENERIC5_FRAME_UPDATE; + uint32_t AFMT_GENERIC6_FRAME_UPDATE; + uint32_t AFMT_GENERIC7_FRAME_UPDATE; + uint32_t HDMI_GENERIC0_CONT; + uint32_t HDMI_GENERIC0_SEND; + uint32_t HDMI_GENERIC0_LINE; + uint32_t HDMI_GENERIC1_CONT; + uint32_t HDMI_GENERIC1_SEND; + uint32_t HDMI_GENERIC1_LINE; + uint32_t DP_PIXEL_ENCODING; + uint32_t DP_COMPONENT_DEPTH; + uint32_t DP_DYN_RANGE; + uint32_t DP_YCBCR_RANGE; + uint32_t HDMI_PACKET_GEN_VERSION; + uint32_t HDMI_KEEPOUT_MODE; + uint32_t HDMI_DEEP_COLOR_ENABLE; + uint32_t HDMI_CLOCK_CHANNEL_RATE; + uint32_t HDMI_DEEP_COLOR_DEPTH; + uint32_t HDMI_GC_CONT; + uint32_t HDMI_GC_SEND; + uint32_t HDMI_NULL_SEND; + uint32_t HDMI_DATA_SCRAMBLE_EN; + uint32_t HDMI_AUDIO_INFO_SEND; + uint32_t AFMT_AUDIO_INFO_UPDATE; + uint32_t HDMI_AUDIO_INFO_LINE; + uint32_t HDMI_GC_AVMUTE; + uint32_t DP_MSE_RATE_X; + uint32_t DP_MSE_RATE_Y; + uint32_t DP_MSE_RATE_UPDATE_PENDING; + uint32_t AFMT_AVI_INFO_VERSION; + uint32_t HDMI_AVI_INFO_SEND; + uint32_t HDMI_AVI_INFO_CONT; + uint32_t HDMI_AVI_INFO_LINE; + uint32_t DP_SEC_GSP0_ENABLE; + uint32_t DP_SEC_STREAM_ENABLE; + uint32_t DP_SEC_GSP1_ENABLE; + uint32_t DP_SEC_GSP2_ENABLE; + uint32_t DP_SEC_GSP3_ENABLE; + uint32_t DP_SEC_GSP4_ENABLE; + uint32_t DP_SEC_GSP5_ENABLE; + uint32_t DP_SEC_GSP6_ENABLE; + uint32_t DP_SEC_GSP7_ENABLE; + uint32_t DP_SEC_AVI_ENABLE; + uint32_t DP_SEC_MPG_ENABLE; + uint32_t DP_VID_STREAM_DIS_DEFER; + uint32_t DP_VID_STREAM_ENABLE; + uint32_t DP_VID_STREAM_STATUS; + uint32_t DP_STEER_FIFO_RESET; + uint32_t DP_VID_M_N_GEN_EN; + uint32_t DP_VID_N; + uint32_t DP_VID_M; + uint32_t DIG_START; + uint32_t AFMT_AUDIO_SRC_SELECT; + uint32_t AFMT_AUDIO_CHANNEL_ENABLE; + uint32_t HDMI_AUDIO_PACKETS_PER_LINE; + uint32_t HDMI_AUDIO_DELAY_EN; + uint32_t AFMT_60958_CS_UPDATE; + uint32_t AFMT_AUDIO_LAYOUT_OVRD; + uint32_t AFMT_60958_OSF_OVRD; + uint32_t HDMI_ACR_AUTO_SEND; + uint32_t HDMI_ACR_SOURCE; + uint32_t HDMI_ACR_AUDIO_PRIORITY; + uint32_t HDMI_ACR_CTS_32; + uint32_t HDMI_ACR_N_32; + uint32_t HDMI_ACR_CTS_44; + uint32_t HDMI_ACR_N_44; + uint32_t HDMI_ACR_CTS_48; + uint32_t HDMI_ACR_N_48; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_L; + uint32_t AFMT_60958_CS_CLOCK_ACCURACY; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_R; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_2; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_3; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_4; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_5; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_6; + uint32_t AFMT_60958_CS_CHANNEL_NUMBER_7; + uint32_t DP_SEC_AUD_N; + uint32_t DP_SEC_TIMESTAMP_MODE; + uint32_t DP_SEC_ASP_ENABLE; + uint32_t DP_SEC_ATP_ENABLE; + uint32_t DP_SEC_AIP_ENABLE; + uint32_t DP_SEC_ACM_ENABLE; + uint32_t AFMT_AUDIO_SAMPLE_SEND; + uint32_t AFMT_AUDIO_CLOCK_EN; + uint32_t TMDS_PIXEL_ENCODING; + uint32_t TMDS_COLOR_FORMAT; + uint32_t DP_DB_DISABLE; + uint32_t DP_MSA_MISC0; + uint32_t DP_MSA_HTOTAL; + uint32_t DP_MSA_VTOTAL; + uint32_t DP_MSA_HSTART; + uint32_t DP_MSA_VSTART; + uint32_t DP_MSA_HSYNCWIDTH; + uint32_t DP_MSA_HSYNCPOLARITY; + uint32_t DP_MSA_VSYNCWIDTH; + uint32_t DP_MSA_VSYNCPOLARITY; + uint32_t DP_MSA_HWIDTH; + uint32_t DP_MSA_VHEIGHT; + uint32_t HDMI_DB_DISABLE; + uint32_t DP_VID_N_MUL; + uint32_t DP_VID_M_DOUBLE_VALUE_EN; +}; + +struct dce110_stream_enc_registers { + uint32_t AFMT_CNTL; + uint32_t AFMT_AVI_INFO0; + uint32_t AFMT_AVI_INFO1; + uint32_t AFMT_AVI_INFO2; + uint32_t AFMT_AVI_INFO3; + uint32_t AFMT_GENERIC_0; + uint32_t AFMT_GENERIC_1; + uint32_t AFMT_GENERIC_2; + uint32_t AFMT_GENERIC_3; + uint32_t AFMT_GENERIC_4; + uint32_t AFMT_GENERIC_5; + uint32_t AFMT_GENERIC_6; + uint32_t AFMT_GENERIC_7; + uint32_t AFMT_GENERIC_HDR; + uint32_t AFMT_INFOFRAME_CONTROL0; + uint32_t AFMT_VBI_PACKET_CONTROL; + uint32_t AFMT_VBI_PACKET_CONTROL1; + uint32_t AFMT_AUDIO_PACKET_CONTROL; + uint32_t AFMT_AUDIO_PACKET_CONTROL2; + uint32_t AFMT_AUDIO_SRC_CONTROL; + uint32_t AFMT_60958_0; + uint32_t AFMT_60958_1; + uint32_t AFMT_60958_2; + uint32_t DIG_FE_CNTL; + uint32_t DP_MSE_RATE_CNTL; + uint32_t DP_MSE_RATE_UPDATE; + uint32_t DP_PIXEL_FORMAT; + uint32_t DP_SEC_CNTL; + uint32_t DP_STEER_FIFO; + uint32_t DP_VID_M; + uint32_t DP_VID_N; + uint32_t DP_VID_STREAM_CNTL; + uint32_t DP_VID_TIMING; + uint32_t DP_SEC_AUD_N; + uint32_t DP_SEC_TIMESTAMP; + uint32_t HDMI_CONTROL; + uint32_t HDMI_GC; + uint32_t HDMI_GENERIC_PACKET_CONTROL0; + uint32_t HDMI_GENERIC_PACKET_CONTROL1; + uint32_t HDMI_GENERIC_PACKET_CONTROL2; + uint32_t HDMI_GENERIC_PACKET_CONTROL3; + uint32_t HDMI_INFOFRAME_CONTROL0; + uint32_t HDMI_INFOFRAME_CONTROL1; + uint32_t HDMI_VBI_PACKET_CONTROL; + uint32_t HDMI_AUDIO_PACKET_CONTROL; + uint32_t HDMI_ACR_PACKET_CONTROL; + uint32_t HDMI_ACR_32_0; + uint32_t HDMI_ACR_32_1; + uint32_t HDMI_ACR_44_0; + uint32_t HDMI_ACR_44_1; + uint32_t HDMI_ACR_48_0; + uint32_t HDMI_ACR_48_1; + uint32_t TMDS_CNTL; +}; + +struct dce110_stream_encoder { + struct stream_encoder base; + const struct dce110_stream_enc_registers *regs; + const struct dce_stream_encoder_shift *se_shift; + const struct dce_stream_encoder_mask *se_mask; +}; + +bool dce110_stream_encoder_construct( + struct dce110_stream_encoder *enc110, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + const struct dce110_stream_enc_registers *regs, + const struct dce_stream_encoder_shift *se_shift, + const struct dce_stream_encoder_mask *se_mask); + + +void dce110_se_audio_mute_control( + struct stream_encoder *enc, bool mute); + +void dce110_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + +void dce110_se_dp_audio_enable( + struct stream_encoder *enc); + +void dce110_se_dp_audio_disable( + struct stream_encoder *enc); + +void dce110_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + +void dce110_se_hdmi_audio_disable( + struct stream_encoder *enc); + +#endif /* __DC_STREAM_ENCODER_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c new file mode 100644 index 000000000000..f47b6617f662 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -0,0 +1,1002 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_transform.h" +#include "reg_helper.h" +#include "opp.h" +#include "basics/conversion.h" + +#define REG(reg) \ + (xfm_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + xfm_dce->xfm_shift->field_name, xfm_dce->xfm_mask->field_name + +#define CTX \ + xfm_dce->base.ctx + +#define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) +#define GAMUT_MATRIX_SIZE 12 +#define SCL_PHASES 16 + +enum dcp_out_trunc_round_mode { + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, + DCP_OUT_TRUNC_ROUND_MODE_ROUND +}; + +enum dcp_out_trunc_round_depth { + DCP_OUT_TRUNC_ROUND_DEPTH_14BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_13BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_12BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_11BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_10BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_9BIT, + DCP_OUT_TRUNC_ROUND_DEPTH_8BIT +}; + +/* defines the various methods of bit reduction available for use */ +enum dcp_bit_depth_reduction_mode { + DCP_BIT_DEPTH_REDUCTION_MODE_DITHER, + DCP_BIT_DEPTH_REDUCTION_MODE_ROUND, + DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE, + DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED, + DCP_BIT_DEPTH_REDUCTION_MODE_INVALID +}; + +enum dcp_spatial_dither_mode { + DCP_SPATIAL_DITHER_MODE_AAAA, + DCP_SPATIAL_DITHER_MODE_A_AA_A, + DCP_SPATIAL_DITHER_MODE_AABBAABB, + DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC, + DCP_SPATIAL_DITHER_MODE_INVALID +}; + +enum dcp_spatial_dither_depth { + DCP_SPATIAL_DITHER_DEPTH_30BPP, + DCP_SPATIAL_DITHER_DEPTH_24BPP +}; + +static bool setup_scaling_configuration( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + struct dc_context *ctx = xfm_dce->base.ctx; + + if (data->taps.h_taps + data->taps.v_taps <= 2) { + /* Set bypass */ + REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); + return false; + } + + REG_SET_2(SCL_TAP_CONTROL, 0, + SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1, + SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1); + + if (data->format <= PIXEL_FORMAT_GRPH_END) + REG_UPDATE_2(SCL_MODE, SCL_MODE, 1, SCL_PSCL_EN, 1); + else + REG_UPDATE_2(SCL_MODE, SCL_MODE, 2, SCL_PSCL_EN, 1); + + /* 1 - Replace out of bound pixels with edge */ + REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1); + + return true; +} + +static void program_overscan( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + int overscan_right = data->h_active + - data->recout.x - data->recout.width; + int overscan_bottom = data->v_active + - data->recout.y - data->recout.height; + + if (overscan_right < 0) { + BREAK_TO_DEBUGGER(); + overscan_right = 0; + } + if (overscan_bottom < 0) { + BREAK_TO_DEBUGGER(); + overscan_bottom = 0; + } + + REG_SET_2(EXT_OVERSCAN_LEFT_RIGHT, 0, + EXT_OVERSCAN_LEFT, data->recout.x, + EXT_OVERSCAN_RIGHT, overscan_right); + REG_SET_2(EXT_OVERSCAN_TOP_BOTTOM, 0, + EXT_OVERSCAN_TOP, data->recout.y, + EXT_OVERSCAN_BOTTOM, overscan_bottom); +} + +static void program_multi_taps_filter( + struct dce_transform *xfm_dce, + int taps, + const uint16_t *coeffs, + enum ram_filter_type filter_type) +{ + int phase, pair; + int array_idx = 0; + int taps_pairs = (taps + 1) / 2; + int phases_to_program = SCL_PHASES / 2 + 1; + + uint32_t power_ctl = 0; + + if (!coeffs) + return; + + /*We need to disable power gating on coeff memory to do programming*/ + if (REG(DCFE_MEM_PWR_CTRL)) { + power_ctl = REG_READ(DCFE_MEM_PWR_CTRL); + REG_SET(DCFE_MEM_PWR_CTRL, power_ctl, SCL_COEFF_MEM_PWR_DIS, 1); + + REG_WAIT(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, 0, 1, 10); + } + for (phase = 0; phase < phases_to_program; phase++) { + /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror + phase 0 is unique and phase N/2 is unique if N is even*/ + for (pair = 0; pair < taps_pairs; pair++) { + uint16_t odd_coeff = 0; + uint16_t even_coeff = coeffs[array_idx]; + + REG_SET_3(SCL_COEF_RAM_SELECT, 0, + SCL_C_RAM_FILTER_TYPE, filter_type, + SCL_C_RAM_PHASE, phase, + SCL_C_RAM_TAP_PAIR_IDX, pair); + + if (taps % 2 && pair == taps_pairs - 1) + array_idx++; + else { + odd_coeff = coeffs[array_idx + 1]; + array_idx += 2; + } + + REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, + SCL_C_RAM_EVEN_TAP_COEF_EN, 1, + SCL_C_RAM_EVEN_TAP_COEF, even_coeff, + SCL_C_RAM_ODD_TAP_COEF_EN, 1, + SCL_C_RAM_ODD_TAP_COEF, odd_coeff); + } + } + + /*We need to restore power gating on coeff memory to initial state*/ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_WRITE(DCFE_MEM_PWR_CTRL, power_ctl); +} + +static void program_viewport( + struct dce_transform *xfm_dce, + const struct rect *view_port) +{ + REG_SET_2(VIEWPORT_START, 0, + VIEWPORT_X_START, view_port->x, + VIEWPORT_Y_START, view_port->y); + + REG_SET_2(VIEWPORT_SIZE, 0, + VIEWPORT_HEIGHT, view_port->height, + VIEWPORT_WIDTH, view_port->width); + + /* TODO: add stereo support */ +} + +static void calculate_inits( + struct dce_transform *xfm_dce, + const struct scaler_data *data, + struct scl_ratios_inits *inits) +{ + struct fixed31_32 h_init; + struct fixed31_32 v_init; + + inits->h_int_scale_ratio = + dal_fixed31_32_u2d19(data->ratios.horz) << 5; + inits->v_int_scale_ratio = + dal_fixed31_32_u2d19(data->ratios.vert) << 5; + + h_init = + dal_fixed31_32_div_int( + dal_fixed31_32_add( + data->ratios.horz, + dal_fixed31_32_from_int(data->taps.h_taps + 1)), + 2); + inits->h_init.integer = dal_fixed31_32_floor(h_init); + inits->h_init.fraction = dal_fixed31_32_u0d19(h_init) << 5; + + v_init = + dal_fixed31_32_div_int( + dal_fixed31_32_add( + data->ratios.vert, + dal_fixed31_32_from_int(data->taps.v_taps + 1)), + 2); + inits->v_init.integer = dal_fixed31_32_floor(v_init); + inits->v_init.fraction = dal_fixed31_32_u0d19(v_init) << 5; +} + +static void program_scl_ratios_inits( + struct dce_transform *xfm_dce, + struct scl_ratios_inits *inits) +{ + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, + SCL_H_SCALE_RATIO, inits->h_int_scale_ratio); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, + SCL_V_SCALE_RATIO, inits->v_int_scale_ratio); + + REG_SET_2(SCL_HORZ_FILTER_INIT, 0, + SCL_H_INIT_INT, inits->h_init.integer, + SCL_H_INIT_FRAC, inits->h_init.fraction); + + REG_SET_2(SCL_VERT_FILTER_INIT, 0, + SCL_V_INIT_INT, inits->v_init.integer, + SCL_V_INIT_FRAC, inits->v_init.fraction); + + REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0); +} + +static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio) +{ + if (taps == 4) + return get_filter_4tap_16p(ratio); + else if (taps == 3) + return get_filter_3tap_16p(ratio); + else if (taps == 2) + return filter_2tap_16p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static void dce_transform_set_scaler( + struct transform *xfm, + const struct scaler_data *data) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + bool is_scaling_required; + bool filter_updated = false; + const uint16_t *coeffs_v, *coeffs_h; + + /*Use all three pieces of memory always*/ + REG_SET_2(LB_MEMORY_CTRL, 0, + LB_MEMORY_CONFIG, 0, + LB_MEMORY_SIZE, xfm_dce->lb_memory_size); + + /* 1. Program overscan */ + program_overscan(xfm_dce, data); + + /* 2. Program taps and configuration */ + is_scaling_required = setup_scaling_configuration(xfm_dce, data); + + if (is_scaling_required) { + /* 3. Calculate and program ratio, filter initialization */ + struct scl_ratios_inits inits = { 0 }; + + calculate_inits(xfm_dce, data, &inits); + + program_scl_ratios_inits(xfm_dce, &inits); + + coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert); + coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz); + + if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) { + /* 4. Program vertical filters */ + if (xfm_dce->filter_v == NULL) + REG_SET(SCL_VERT_FILTER_CONTROL, 0, + SCL_V_2TAP_HARDCODE_COEF_EN, 0); + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps, + coeffs_v, + FILTER_TYPE_RGB_Y_VERTICAL); + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps, + coeffs_v, + FILTER_TYPE_ALPHA_VERTICAL); + + /* 5. Program horizontal filters */ + if (xfm_dce->filter_h == NULL) + REG_SET(SCL_HORZ_FILTER_CONTROL, 0, + SCL_H_2TAP_HARDCODE_COEF_EN, 0); + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps, + coeffs_h, + FILTER_TYPE_RGB_Y_HORIZONTAL); + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps, + coeffs_h, + FILTER_TYPE_ALPHA_HORIZONTAL); + + xfm_dce->filter_v = coeffs_v; + xfm_dce->filter_h = coeffs_h; + filter_updated = true; + } + } + + /* 6. Program the viewport */ + program_viewport(xfm_dce, &data->viewport); + + /* 7. Set bit to flip to new coefficient memory */ + if (filter_updated) + REG_UPDATE(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, 1); + + REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en); +} + +/***************************************************************************** + * set_clamp + * + * @param depth : bit depth to set the clamp to (should match denorm) + * + * @brief + * Programs clamp according to panel bit depth. + * + *******************************************************************************/ +static void set_clamp( + struct dce_transform *xfm_dce, + enum dc_color_depth depth) +{ + int clamp_max = 0; + + /* At the clamp block the data will be MSB aligned, so we set the max + * clamp accordingly. + * For example, the max value for 6 bits MSB aligned (14 bit bus) would + * be "11 1111 0000 0000" in binary, so 0x3F00. + */ + switch (depth) { + case COLOR_DEPTH_666: + /* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */ + clamp_max = 0x3F00; + break; + case COLOR_DEPTH_888: + /* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */ + clamp_max = 0x3FC0; + break; + case COLOR_DEPTH_101010: + /* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */ + clamp_max = 0x3FFC; + break; + case COLOR_DEPTH_121212: + /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */ + clamp_max = 0x3FFF; + break; + default: + clamp_max = 0x3FC0; + BREAK_TO_DEBUGGER(); /* Invalid clamp bit depth */ + } + REG_SET_2(OUT_CLAMP_CONTROL_B_CB, 0, + OUT_CLAMP_MIN_B_CB, 0, + OUT_CLAMP_MAX_B_CB, clamp_max); + + REG_SET_2(OUT_CLAMP_CONTROL_G_Y, 0, + OUT_CLAMP_MIN_G_Y, 0, + OUT_CLAMP_MAX_G_Y, clamp_max); + + REG_SET_2(OUT_CLAMP_CONTROL_R_CR, 0, + OUT_CLAMP_MIN_R_CR, 0, + OUT_CLAMP_MAX_R_CR, clamp_max); +} + +/******************************************************************************* + * set_round + * + * @brief + * Programs Round/Truncate + * + * @param [in] mode :round or truncate + * @param [in] depth :bit depth to round/truncate to + OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode + POSSIBLE VALUES: + 00 - truncate to u0.12 + 01 - truncate to u0.11 + 02 - truncate to u0.10 + 03 - truncate to u0.9 + 04 - truncate to u0.8 + 05 - reserved + 06 - truncate to u0.14 + 07 - truncate to u0.13 set_reg_field_value( + value, + clamp_max, + OUT_CLAMP_CONTROL_R_CR, + OUT_CLAMP_MAX_R_CR); + 08 - round to u0.12 + 09 - round to u0.11 + 10 - round to u0.10 + 11 - round to u0.9 + 12 - round to u0.8 + 13 - reserved + 14 - round to u0.14 + 15 - round to u0.13 + + ******************************************************************************/ +static void set_round( + struct dce_transform *xfm_dce, + enum dcp_out_trunc_round_mode mode, + enum dcp_out_trunc_round_depth depth) +{ + int depth_bits = 0; + int mode_bit = 0; + + /* set up bit depth */ + switch (depth) { + case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT: + depth_bits = 6; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT: + depth_bits = 7; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT: + depth_bits = 0; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT: + depth_bits = 1; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT: + depth_bits = 2; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT: + depth_bits = 3; + break; + case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT: + depth_bits = 4; + break; + default: + depth_bits = 4; + BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_depth */ + } + + /* set up round or truncate */ + switch (mode) { + case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE: + mode_bit = 0; + break; + case DCP_OUT_TRUNC_ROUND_MODE_ROUND: + mode_bit = 1; + break; + default: + BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_mode */ + } + + depth_bits |= mode_bit << 3; + + REG_SET(OUT_ROUND_CONTROL, 0, OUT_ROUND_TRUNC_MODE, depth_bits); +} + +/***************************************************************************** + * set_dither + * + * @brief + * Programs Dither + * + * @param [in] dither_enable : enable dither + * @param [in] dither_mode : dither mode to set + * @param [in] dither_depth : bit depth to dither to + * @param [in] frame_random_enable : enable frame random + * @param [in] rgb_random_enable : enable rgb random + * @param [in] highpass_random_enable : enable highpass random + * + ******************************************************************************/ + +static void set_dither( + struct dce_transform *xfm_dce, + bool dither_enable, + enum dcp_spatial_dither_mode dither_mode, + enum dcp_spatial_dither_depth dither_depth, + bool frame_random_enable, + bool rgb_random_enable, + bool highpass_random_enable) +{ + int dither_depth_bits = 0; + int dither_mode_bits = 0; + + switch (dither_mode) { + case DCP_SPATIAL_DITHER_MODE_AAAA: + dither_mode_bits = 0; + break; + case DCP_SPATIAL_DITHER_MODE_A_AA_A: + dither_mode_bits = 1; + break; + case DCP_SPATIAL_DITHER_MODE_AABBAABB: + dither_mode_bits = 2; + break; + case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC: + dither_mode_bits = 3; + break; + default: + /* Invalid dcp_spatial_dither_mode */ + BREAK_TO_DEBUGGER(); + } + + switch (dither_depth) { + case DCP_SPATIAL_DITHER_DEPTH_30BPP: + dither_depth_bits = 0; + break; + case DCP_SPATIAL_DITHER_DEPTH_24BPP: + dither_depth_bits = 1; + break; + default: + /* Invalid dcp_spatial_dither_depth */ + BREAK_TO_DEBUGGER(); + } + + /* write the register */ + REG_SET_6(DCP_SPATIAL_DITHER_CNTL, 0, + DCP_SPATIAL_DITHER_EN, dither_enable, + DCP_SPATIAL_DITHER_MODE, dither_mode_bits, + DCP_SPATIAL_DITHER_DEPTH, dither_depth_bits, + DCP_FRAME_RANDOM_ENABLE, frame_random_enable, + DCP_RGB_RANDOM_ENABLE, rgb_random_enable, + DCP_HIGHPASS_RANDOM_ENABLE, highpass_random_enable); +} + +/***************************************************************************** + * dce_transform_bit_depth_reduction_program + * + * @brief + * Programs the DCP bit depth reduction registers (Clamp, Round/Truncate, + * Dither) for dce + * + * @param depth : bit depth to set the clamp to (should match denorm) + * + ******************************************************************************/ +static void program_bit_depth_reduction( + struct dce_transform *xfm_dce, + enum dc_color_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + enum dcp_bit_depth_reduction_mode depth_reduction_mode; + enum dcp_spatial_dither_mode spatial_dither_mode; + bool frame_random_enable; + bool rgb_random_enable; + bool highpass_random_enable; + + ASSERT(depth < COLOR_DEPTH_121212); /* Invalid clamp bit depth */ + + if (bit_depth_params->flags.SPATIAL_DITHER_ENABLED) { + depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DITHER; + frame_random_enable = true; + rgb_random_enable = true; + highpass_random_enable = true; + + } else { + depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED; + frame_random_enable = false; + rgb_random_enable = false; + highpass_random_enable = false; + } + + spatial_dither_mode = DCP_SPATIAL_DITHER_MODE_A_AA_A; + + set_clamp(xfm_dce, depth); + + switch (depth_reduction_mode) { + case DCP_BIT_DEPTH_REDUCTION_MODE_DITHER: + /* Spatial Dither: Set round/truncate to bypass (12bit), + * enable Dither (30bpp) */ + set_round(xfm_dce, + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, + DCP_OUT_TRUNC_ROUND_DEPTH_12BIT); + + set_dither(xfm_dce, true, spatial_dither_mode, + DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, + rgb_random_enable, highpass_random_enable); + break; + case DCP_BIT_DEPTH_REDUCTION_MODE_ROUND: + /* Round: Enable round (10bit), disable Dither */ + set_round(xfm_dce, + DCP_OUT_TRUNC_ROUND_MODE_ROUND, + DCP_OUT_TRUNC_ROUND_DEPTH_10BIT); + + set_dither(xfm_dce, false, spatial_dither_mode, + DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, + rgb_random_enable, highpass_random_enable); + break; + case DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE: /* Truncate */ + /* Truncate: Enable truncate (10bit), disable Dither */ + set_round(xfm_dce, + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, + DCP_OUT_TRUNC_ROUND_DEPTH_10BIT); + + set_dither(xfm_dce, false, spatial_dither_mode, + DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, + rgb_random_enable, highpass_random_enable); + break; + + case DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED: /* Disabled */ + /* Truncate: Set round/truncate to bypass (12bit), + * disable Dither */ + set_round(xfm_dce, + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, + DCP_OUT_TRUNC_ROUND_DEPTH_12BIT); + + set_dither(xfm_dce, false, spatial_dither_mode, + DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable, + rgb_random_enable, highpass_random_enable); + break; + default: + /* Invalid DCP Depth reduction mode */ + BREAK_TO_DEBUGGER(); + break; + } +} + +static int dce_transform_get_max_num_of_supported_lines( + struct dce_transform *xfm_dce, + enum lb_pixel_depth depth, + int pixel_width) +{ + int pixels_per_entries = 0; + int max_pixels_supports = 0; + + ASSERT(pixel_width); + + /* Find number of pixels that can fit into a single LB entry and + * take floor of the value since we cannot store a single pixel + * across multiple entries. */ + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + pixels_per_entries = xfm_dce->lb_bits_per_entry / 18; + break; + + case LB_PIXEL_DEPTH_24BPP: + pixels_per_entries = xfm_dce->lb_bits_per_entry / 24; + break; + + case LB_PIXEL_DEPTH_30BPP: + pixels_per_entries = xfm_dce->lb_bits_per_entry / 30; + break; + + case LB_PIXEL_DEPTH_36BPP: + pixels_per_entries = xfm_dce->lb_bits_per_entry / 36; + break; + + default: + dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING, + "%s: Invalid LB pixel depth", + __func__); + BREAK_TO_DEBUGGER(); + break; + } + + ASSERT(pixels_per_entries); + + max_pixels_supports = + pixels_per_entries * + xfm_dce->lb_memory_size; + + return (max_pixels_supports / pixel_width); +} + +static void set_denormalization( + struct dce_transform *xfm_dce, + enum dc_color_depth depth) +{ + int denorm_mode = 0; + + switch (depth) { + case COLOR_DEPTH_666: + /* 63/64 for 6 bit output color depth */ + denorm_mode = 1; + break; + case COLOR_DEPTH_888: + /* Unity for 8 bit output color depth + * because prescale is disabled by default */ + denorm_mode = 0; + break; + case COLOR_DEPTH_101010: + /* 1023/1024 for 10 bit output color depth */ + denorm_mode = 3; + break; + case COLOR_DEPTH_121212: + /* 4095/4096 for 12 bit output color depth */ + denorm_mode = 5; + break; + case COLOR_DEPTH_141414: + case COLOR_DEPTH_161616: + default: + /* not valid used case! */ + break; + } + + REG_SET(DENORM_CONTROL, 0, DENORM_MODE, denorm_mode); +} + +static void dce_transform_set_pixel_storage_depth( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + int pixel_depth, expan_mode; + enum dc_color_depth color_depth; + + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + color_depth = COLOR_DEPTH_666; + pixel_depth = 2; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_24BPP: + color_depth = COLOR_DEPTH_888; + pixel_depth = 1; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_30BPP: + color_depth = COLOR_DEPTH_101010; + pixel_depth = 0; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_36BPP: + color_depth = COLOR_DEPTH_121212; + pixel_depth = 3; + expan_mode = 0; + break; + default: + color_depth = COLOR_DEPTH_101010; + pixel_depth = 0; + expan_mode = 1; + BREAK_TO_DEBUGGER(); + break; + } + + set_denormalization(xfm_dce, color_depth); + program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params); + + REG_UPDATE_2(LB_DATA_FORMAT, + PIXEL_DEPTH, pixel_depth, + PIXEL_EXPAN_MODE, expan_mode); + + if (!(xfm_dce->lb_pixel_depth_supported & depth)) { + /*we should use unsupported capabilities + * unless it is required by w/a*/ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } +} + +static void program_gamut_remap( + struct dce_transform *xfm_dce, + const uint16_t *reg_val) +{ + if (reg_val) { + REG_SET_2(GAMUT_REMAP_C11_C12, 0, + GAMUT_REMAP_C11, reg_val[0], + GAMUT_REMAP_C12, reg_val[1]); + REG_SET_2(GAMUT_REMAP_C13_C14, 0, + GAMUT_REMAP_C13, reg_val[2], + GAMUT_REMAP_C14, reg_val[3]); + REG_SET_2(GAMUT_REMAP_C21_C22, 0, + GAMUT_REMAP_C21, reg_val[4], + GAMUT_REMAP_C22, reg_val[5]); + REG_SET_2(GAMUT_REMAP_C23_C24, 0, + GAMUT_REMAP_C23, reg_val[6], + GAMUT_REMAP_C24, reg_val[7]); + REG_SET_2(GAMUT_REMAP_C31_C32, 0, + GAMUT_REMAP_C31, reg_val[8], + GAMUT_REMAP_C32, reg_val[9]); + REG_SET_2(GAMUT_REMAP_C33_C34, 0, + GAMUT_REMAP_C33, reg_val[10], + GAMUT_REMAP_C34, reg_val[11]); + + REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 1); + } else + REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 0); + +} + +/** + ***************************************************************************** + * Function: dal_transform_wide_gamut_set_gamut_remap + * + * @param [in] const struct xfm_grph_csc_adjustment *adjust + * + * @return + * void + * + * @note calculate and apply color temperature adjustment to in Rgb color space + * + * @see + * + ***************************************************************************** + */ +static void dce_transform_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + /* Bypass if type is bypass or hw */ + program_gamut_remap(xfm_dce, NULL); + else { + struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE]; + uint16_t arr_reg_val[GAMUT_MATRIX_SIZE]; + + arr_matrix[0] = adjust->temperature_matrix[0]; + arr_matrix[1] = adjust->temperature_matrix[1]; + arr_matrix[2] = adjust->temperature_matrix[2]; + arr_matrix[3] = dal_fixed31_32_zero; + + arr_matrix[4] = adjust->temperature_matrix[3]; + arr_matrix[5] = adjust->temperature_matrix[4]; + arr_matrix[6] = adjust->temperature_matrix[5]; + arr_matrix[7] = dal_fixed31_32_zero; + + arr_matrix[8] = adjust->temperature_matrix[6]; + arr_matrix[9] = adjust->temperature_matrix[7]; + arr_matrix[10] = adjust->temperature_matrix[8]; + arr_matrix[11] = dal_fixed31_32_zero; + + convert_float_matrix( + arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE); + + program_gamut_remap(xfm_dce, arr_reg_val); + } +} + +static uint32_t decide_taps(struct fixed31_32 ratio, uint32_t in_taps, bool chroma) +{ + uint32_t taps; + + if (IDENTITY_RATIO(ratio)) { + return 1; + } else if (in_taps != 0) { + taps = in_taps; + } else { + taps = 4; + } + + if (chroma) { + taps /= 2; + if (taps < 2) + taps = 2; + } + + return taps; +} + + +bool dce_transform_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + int pixel_width = scl_data->viewport.width; + int max_num_of_lines; + + if (xfm_dce->prescaler_on && + (scl_data->viewport.width > scl_data->recout.width)) + pixel_width = scl_data->recout.width; + + max_num_of_lines = dce_transform_get_max_num_of_supported_lines( + xfm_dce, + scl_data->lb_params.depth, + pixel_width); + + /* Fail if in_taps are impossible */ + if (in_taps->v_taps >= max_num_of_lines) + return false; + + /* + * Set taps according to this policy (in this order) + * - Use 1 for no scaling + * - Use input taps + * - Use 4 and reduce as required by line buffer size + * - Decide chroma taps if chroma is scaled + * + * Ignore input chroma taps. Decide based on non-chroma + */ + scl_data->taps.h_taps = decide_taps(scl_data->ratios.horz, in_taps->h_taps, false); + scl_data->taps.v_taps = decide_taps(scl_data->ratios.vert, in_taps->v_taps, false); + scl_data->taps.h_taps_c = decide_taps(scl_data->ratios.horz_c, in_taps->h_taps, true); + scl_data->taps.v_taps_c = decide_taps(scl_data->ratios.vert_c, in_taps->v_taps, true); + + if (!IDENTITY_RATIO(scl_data->ratios.vert)) { + /* reduce v_taps if needed but ensure we have at least two */ + if (in_taps->v_taps == 0 + && max_num_of_lines <= scl_data->taps.v_taps + && scl_data->taps.v_taps > 1) { + scl_data->taps.v_taps = max_num_of_lines - 1; + } + + if (scl_data->taps.v_taps <= 1) + return false; + } + + if (!IDENTITY_RATIO(scl_data->ratios.vert_c)) { + /* reduce chroma v_taps if needed but ensure we have at least two */ + if (max_num_of_lines <= scl_data->taps.v_taps_c && scl_data->taps.v_taps_c > 1) { + scl_data->taps.v_taps_c = max_num_of_lines - 1; + } + + if (scl_data->taps.v_taps_c <= 1) + return false; + } + + /* we've got valid taps */ + return true; +} + +static void dce_transform_reset(struct transform *xfm) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + xfm_dce->filter_h = NULL; + xfm_dce->filter_v = NULL; +} + + +static const struct transform_funcs dce_transform_funcs = { + .transform_reset = dce_transform_reset, + .transform_set_scaler = + dce_transform_set_scaler, + .transform_set_gamut_remap = + dce_transform_set_gamut_remap, + .transform_set_pixel_storage_depth = + dce_transform_set_pixel_storage_depth, + .transform_get_optimal_number_of_taps = + dce_transform_get_optimal_number_of_taps +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce_transform_construct( + struct dce_transform *xfm_dce, + struct dc_context *ctx, + uint32_t inst, + const struct dce_transform_registers *regs, + const struct dce_transform_shift *xfm_shift, + const struct dce_transform_mask *xfm_mask) +{ + xfm_dce->base.ctx = ctx; + + xfm_dce->base.inst = inst; + xfm_dce->base.funcs = &dce_transform_funcs; + + xfm_dce->regs = regs; + xfm_dce->xfm_shift = xfm_shift; + xfm_dce->xfm_mask = xfm_mask; + + xfm_dce->prescaler_on = true; + xfm_dce->lb_pixel_depth_supported = + LB_PIXEL_DEPTH_18BPP | + LB_PIXEL_DEPTH_24BPP | + LB_PIXEL_DEPTH_30BPP; + + xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; + xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h new file mode 100644 index 000000000000..897645e2889f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -0,0 +1,313 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCE_DCE_TRANSFORM_H_ +#define _DCE_DCE_TRANSFORM_H_ + + +#include "transform.h" + +#define TO_DCE_TRANSFORM(transform)\ + container_of(transform, struct dce_transform, base) + +#define LB_TOTAL_NUMBER_OF_ENTRIES 1712 +#define LB_BITS_PER_ENTRY 144 + +#define XFM_COMMON_REG_LIST_DCE_BASE(id) \ + SRI(LB_DATA_FORMAT, LB, id), \ + SRI(GAMUT_REMAP_CONTROL, DCP, id), \ + SRI(GAMUT_REMAP_C11_C12, DCP, id), \ + SRI(GAMUT_REMAP_C13_C14, DCP, id), \ + SRI(GAMUT_REMAP_C21_C22, DCP, id), \ + SRI(GAMUT_REMAP_C23_C24, DCP, id), \ + SRI(GAMUT_REMAP_C31_C32, DCP, id), \ + SRI(GAMUT_REMAP_C33_C34, DCP, id), \ + SRI(DENORM_CONTROL, DCP, id), \ + SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \ + SRI(OUT_ROUND_CONTROL, DCP, id), \ + SRI(OUT_CLAMP_CONTROL_R_CR, DCP, id), \ + SRI(OUT_CLAMP_CONTROL_G_Y, DCP, id), \ + SRI(OUT_CLAMP_CONTROL_B_CB, DCP, id), \ + SRI(SCL_MODE, SCL, id), \ + SRI(SCL_TAP_CONTROL, SCL, id), \ + SRI(SCL_CONTROL, SCL, id), \ + SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \ + SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \ + SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \ + SRI(SCL_HORZ_FILTER_CONTROL, SCL, id), \ + SRI(SCL_COEF_RAM_SELECT, SCL, id), \ + SRI(SCL_COEF_RAM_TAP_DATA, SCL, id), \ + SRI(VIEWPORT_START, SCL, id), \ + SRI(VIEWPORT_SIZE, SCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO, SCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO, SCL, id), \ + SRI(SCL_HORZ_FILTER_INIT, SCL, id), \ + SRI(SCL_VERT_FILTER_INIT, SCL, id), \ + SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \ + SRI(LB_MEMORY_CTRL, LB, id), \ + SRI(SCL_UPDATE, SCL, id) + +#define XFM_COMMON_REG_LIST_DCE100(id) \ + XFM_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \ + SRI(DCFE_MEM_PWR_STATUS, CRTC, id) + +#define XFM_COMMON_REG_LIST_DCE110(id) \ + XFM_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DCFE_MEM_PWR_STATUS, DCFE, id) + +#define XFM_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MIN_G_Y, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MAX_G_Y, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MIN_R_CR, mask_sh), \ + XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR, mask_sh), \ + XFM_SF(OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DENORM_CONTROL, DENORM_MODE, mask_sh), \ + XFM_SF(LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh), \ + XFM_SF(LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh), \ + XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \ + XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \ + XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \ + XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \ + XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \ + XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \ + XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \ + XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \ + XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \ + XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \ + XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ + XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ + XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \ + XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \ + XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \ + XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \ + XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \ + XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \ + XFM_SF(VIEWPORT_START, VIEWPORT_X_START, mask_sh), \ + XFM_SF(VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \ + XFM_SF(VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \ + XFM_SF(VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \ + XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_CONFIG, mask_sh), \ + XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_SIZE, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh), \ + XFM_SF(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \ + XFM_SF(LB_DATA_FORMAT, ALPHA_EN, mask_sh) + +#define XFM_COMMON_MASK_SH_LIST_DCE110(mask_sh) \ + XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ + XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ + XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) + +#define XFM_REG_FIELD_LIST(type) \ + type OUT_CLAMP_MIN_B_CB; \ + type OUT_CLAMP_MAX_B_CB; \ + type OUT_CLAMP_MIN_G_Y; \ + type OUT_CLAMP_MAX_G_Y; \ + type OUT_CLAMP_MIN_R_CR; \ + type OUT_CLAMP_MAX_R_CR; \ + type OUT_ROUND_TRUNC_MODE; \ + type DCP_SPATIAL_DITHER_EN; \ + type DCP_SPATIAL_DITHER_MODE; \ + type DCP_SPATIAL_DITHER_DEPTH; \ + type DCP_FRAME_RANDOM_ENABLE; \ + type DCP_RGB_RANDOM_ENABLE; \ + type DCP_HIGHPASS_RANDOM_ENABLE; \ + type DENORM_MODE; \ + type PIXEL_DEPTH; \ + type PIXEL_EXPAN_MODE; \ + type GAMUT_REMAP_C11; \ + type GAMUT_REMAP_C12; \ + type GAMUT_REMAP_C13; \ + type GAMUT_REMAP_C14; \ + type GAMUT_REMAP_C21; \ + type GAMUT_REMAP_C22; \ + type GAMUT_REMAP_C23; \ + type GAMUT_REMAP_C24; \ + type GAMUT_REMAP_C31; \ + type GAMUT_REMAP_C32; \ + type GAMUT_REMAP_C33; \ + type GAMUT_REMAP_C34; \ + type GRPH_GAMUT_REMAP_MODE; \ + type SCL_MODE; \ + type SCL_PSCL_EN; \ + type SCL_H_NUM_OF_TAPS; \ + type SCL_V_NUM_OF_TAPS; \ + type SCL_BOUNDARY_MODE; \ + type EXT_OVERSCAN_LEFT; \ + type EXT_OVERSCAN_RIGHT; \ + type EXT_OVERSCAN_TOP; \ + type EXT_OVERSCAN_BOTTOM; \ + type SCL_COEFF_MEM_PWR_DIS; \ + type SCL_COEFF_MEM_PWR_STATE; \ + type SCL_C_RAM_FILTER_TYPE; \ + type SCL_C_RAM_PHASE; \ + type SCL_C_RAM_TAP_PAIR_IDX; \ + type SCL_C_RAM_EVEN_TAP_COEF_EN; \ + type SCL_C_RAM_EVEN_TAP_COEF; \ + type SCL_C_RAM_ODD_TAP_COEF_EN; \ + type SCL_C_RAM_ODD_TAP_COEF; \ + type VIEWPORT_X_START; \ + type VIEWPORT_Y_START; \ + type VIEWPORT_HEIGHT; \ + type VIEWPORT_WIDTH; \ + type SCL_H_SCALE_RATIO; \ + type SCL_V_SCALE_RATIO; \ + type SCL_H_INIT_INT; \ + type SCL_H_INIT_FRAC; \ + type SCL_V_INIT_INT; \ + type SCL_V_INIT_FRAC; \ + type LB_MEMORY_CONFIG; \ + type LB_MEMORY_SIZE; \ + type SCL_V_2TAP_HARDCODE_COEF_EN; \ + type SCL_H_2TAP_HARDCODE_COEF_EN; \ + type SCL_COEF_UPDATE_COMPLETE; \ + type ALPHA_EN + +struct dce_transform_shift { + XFM_REG_FIELD_LIST(uint8_t); +}; + +struct dce_transform_mask { + XFM_REG_FIELD_LIST(uint32_t); +}; + +struct dce_transform_registers { + uint32_t LB_DATA_FORMAT; + uint32_t GAMUT_REMAP_CONTROL; + uint32_t GAMUT_REMAP_C11_C12; + uint32_t GAMUT_REMAP_C13_C14; + uint32_t GAMUT_REMAP_C21_C22; + uint32_t GAMUT_REMAP_C23_C24; + uint32_t GAMUT_REMAP_C31_C32; + uint32_t GAMUT_REMAP_C33_C34; + uint32_t DENORM_CONTROL; + uint32_t DCP_SPATIAL_DITHER_CNTL; + uint32_t OUT_ROUND_CONTROL; + uint32_t OUT_CLAMP_CONTROL_R_CR; + uint32_t OUT_CLAMP_CONTROL_G_Y; + uint32_t OUT_CLAMP_CONTROL_B_CB; + uint32_t SCL_MODE; + uint32_t SCL_TAP_CONTROL; + uint32_t SCL_CONTROL; + uint32_t EXT_OVERSCAN_LEFT_RIGHT; + uint32_t EXT_OVERSCAN_TOP_BOTTOM; + uint32_t SCL_VERT_FILTER_CONTROL; + uint32_t SCL_HORZ_FILTER_CONTROL; + uint32_t DCFE_MEM_PWR_CTRL; + uint32_t DCFE_MEM_PWR_STATUS; + uint32_t SCL_COEF_RAM_SELECT; + uint32_t SCL_COEF_RAM_TAP_DATA; + uint32_t VIEWPORT_START; + uint32_t VIEWPORT_SIZE; + uint32_t SCL_HORZ_FILTER_SCALE_RATIO; + uint32_t SCL_VERT_FILTER_SCALE_RATIO; + uint32_t SCL_HORZ_FILTER_INIT; + uint32_t SCL_VERT_FILTER_INIT; + uint32_t SCL_AUTOMATIC_MODE_CONTROL; + uint32_t LB_MEMORY_CTRL; + uint32_t SCL_UPDATE; +}; + +struct init_int_and_frac { + uint32_t integer; + uint32_t fraction; +}; + +struct scl_ratios_inits { + uint32_t h_int_scale_ratio; + uint32_t v_int_scale_ratio; + struct init_int_and_frac h_init; + struct init_int_and_frac v_init; +}; + +enum ram_filter_type { + FILTER_TYPE_RGB_Y_VERTICAL = 0, /* 0 - RGB/Y Vertical filter */ + FILTER_TYPE_CBCR_VERTICAL = 1, /* 1 - CbCr Vertical filter */ + FILTER_TYPE_RGB_Y_HORIZONTAL = 2, /* 1 - RGB/Y Horizontal filter */ + FILTER_TYPE_CBCR_HORIZONTAL = 3, /* 3 - CbCr Horizontal filter */ + FILTER_TYPE_ALPHA_VERTICAL = 4, /* 4 - Alpha Vertical filter. */ + FILTER_TYPE_ALPHA_HORIZONTAL = 5, /* 5 - Alpha Horizontal filter. */ +}; + +struct dce_transform { + struct transform base; + const struct dce_transform_registers *regs; + const struct dce_transform_shift *xfm_shift; + const struct dce_transform_mask *xfm_mask; + + const uint16_t *filter_v; + const uint16_t *filter_h; + const uint16_t *filter_v_c; + const uint16_t *filter_h_c; + int lb_pixel_depth_supported; + int lb_memory_size; + int lb_bits_per_entry; + bool prescaler_on; +}; + +bool dce_transform_construct(struct dce_transform *xfm110, + struct dc_context *ctx, + uint32_t inst, + const struct dce_transform_registers *regs, + const struct dce_transform_shift *xfm_shift, + const struct dce_transform_mask *xfm_mask); + +bool dce_transform_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); + + +#endif /* _DCE_DCE_TRANSFORM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/Makefile b/drivers/gpu/drm/amd/display/dc/dce100/Makefile new file mode 100644 index 000000000000..ea40870624b3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/Makefile @@ -0,0 +1,23 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE100 = dce100_resource.o dce100_hw_sequencer.o + +AMD_DAL_DCE100 = $(addprefix $(AMDDALPATH)/dc/dce100/,$(DCE100)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE100) + + +############################################################################### +# DCE 10x +############################################################################### +ifdef 0#CONFIG_DRM_AMD_DC_DCE11_0 +TG_DCE100 = dce100_resource.o + +AMD_DAL_TG_DCE100 = $(addprefix \ + $(AMDDALPATH)/dc/dce100/,$(TG_DCE100)) + +AMD_DISPLAY_FILES += $(AMD_DAL_TG_DCE100) +endif + diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c new file mode 100644 index 000000000000..e2fe024e1182 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -0,0 +1,140 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "hw_sequencer.h" +#include "dce100_hw_sequencer.h" +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE10 register header files */ +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +struct dce100_hw_seq_reg_offsets { + uint32_t blnd; + uint32_t crtc; +}; + +static const struct dce100_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +/******************************************************************************* + * Private definitions + ******************************************************************************/ +/***************************PIPE_CONTROL***********************************/ + +static bool dce100_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0)){ + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + */ + dm_write_reg(ctx, + HW_REG_CRTC(mmMASTER_UPDATE_MODE, controller_id), + 0); + } + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + +static void set_display_mark_for_pipe_if_needed(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +static void set_displaymarks( + const struct core_dc *dc, struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +static void set_bandwidth(struct core_dc *dc) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + + +/**************************************************************************/ + +bool dce100_hw_sequencer_construct(struct core_dc *dc) +{ + dce110_hw_sequencer_construct(dc); + + /* TODO: dce80 is empty implementation at the moment*/ + dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; + dc->hwss.set_displaymarks = set_displaymarks; + dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed; + dc->hwss.set_bandwidth = set_bandwidth; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h new file mode 100644 index 000000000000..cf497ea605c8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE100_H__ +#define __DC_HWSS_DCE100_H__ + +#include "core_types.h" + +struct core_dc; + +bool dce100_hw_sequencer_construct(struct core_dc *dc); + +#endif /* __DC_HWSS_DCE100_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c new file mode 100644 index 000000000000..16595dc875a1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -0,0 +1,1085 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "../virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dce110/dce110_timing_generator.h" +#include "irq/dce110/irq_service_dce110.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce110/dce110_mem_input.h" +#include "dce110/dce110_mem_input_v.h" +#include "dce110/dce110_ipp.h" +#include "dce/dce_transform.h" +#include "dce110/dce110_opp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "dce100/dce100_hw_sequencer.h" + +#include "reg_helper.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + + +static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), +} +}; + + + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE100(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE110_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST_DCE_BASE(id),\ + .AFMT_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5), + stream_enc_regs(6) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_100_110(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + + + +#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03 + +static const struct dce110_opp_reg_offsets dce100_opp_reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT_CONTROL), + .dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 3 +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x1918 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce100_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce110_timing_generator_construct(tg110, ctx, instance, + offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static struct stream_encoder *dce100_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE10_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE10_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce100_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce100_stream_encoder_create, + .create_hwseq = dce100_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static struct mem_input *dce100_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { + struct mem_input *mi = &mem_input110->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 2; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input110); + return NULL; +} + +static void dce100_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce100_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) { + return &transform->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static struct input_pixel_processor *dce100_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offsets) +{ + struct dce110_ipp *ipp = + dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce110_ipp_construct(ipp, ctx, inst, offsets)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +struct link_encoder *dce100_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + enc110->base.features.ycbcr420_supported = false; + enc110->base.features.max_hdmi_pixel_clock = 300000; + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +struct output_pixel_processor *dce100_opp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offset) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, offset)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + +void dce100_opp_destroy(struct output_pixel_processor **opp) +{ + struct dce110_opp *dce110_opp; + + if (!opp || !*opp) + return; + + dce110_opp = FROM_DCE11_OPP(*opp); + + dm_free(dce110_opp->regamma.coeff128_dx); + dm_free(dce110_opp->regamma.coeff128_oem); + dm_free(dce110_opp->regamma.coeff128); + dm_free(dce110_opp->regamma.axis_x_1025); + dm_free(dce110_opp->regamma.axis_x_256); + dm_free(dce110_opp->regamma.coordinates_x); + dm_free(dce110_opp->regamma.rgb_regamma); + dm_free(dce110_opp->regamma.rgb_resulted); + dm_free(dce110_opp->regamma.rgb_oem); + dm_free(dce110_opp->regamma.rgb_user); + dm_free(dce110_opp); + + *opp = NULL; +} + +struct clock_source *dce100_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce100_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce100_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce100_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce110_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) + dce100_clock_source_destroy(&pool->base.clock_sources[i]); + } + + if (pool->base.dp_clock_source != NULL) + dce100_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) + dce_aud_destroy(&pool->base.audios[i]); + } + + if (pool->base.display_clock != NULL) + dal_display_clock_destroy(&pool->base.display_clock); + + if (pool->base.irqs != NULL) + dal_irq_service_destroy(&pool->base.irqs); +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j, k; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = dce110_resource_build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + resource_build_info_frame(pipe_ctx); + + /* do not need to validate non root pipes */ + break; + } + } + } + + return DC_OK; +} + +enum dc_status dce100_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + /* TODO implement when needed but for now hardcode max value*/ + context->bw_results.dispclk_khz = 681000; + + return DC_OK; +} + +static bool dce100_validate_surface_sets( + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) { + if (set[i].surface_count == 0) + continue; + + if (set[i].surface_count > 1) + return false; + + if (set[i].surfaces[0]->clip_rect.width + != set[i].target->streams[0]->src.width + || set[i].surfaces[0]->clip_rect.height + != set[i].target->streams[0]->src.height) + return false; + if (set[i].surfaces[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +enum dc_status dce100_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + + if (!dce100_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + context->res_ctx.pool = dc->res_pool; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (!resource_validate_attach_surfaces( + set, set_count, dc->current_context, context)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + result = resource_build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce100_validate_bandwidth(dc, context); + + return result; +} + +enum dc_status dce100_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->res_ctx.pool = dc->res_pool; + + context->targets[0] = DC_TARGET_TO_CORE(dc_target); + dc_target_retain(&context->targets[0]->public); + context->target_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_target( + context, dc->public.caps.max_targets); + result = resource_build_scaling_params_for_context(dc, context); + } + + if (result == DC_OK) + result = dce100_validate_bandwidth(dc, context); + + return result; +} + +static void dce100_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce100_res_pool_funcs = { + .destroy = dce100_destroy_resource_pool, + .link_enc_create = dce100_link_encoder_create, + .validate_with_context = dce100_validate_with_context, + .validate_guaranteed = dce100_validate_guaranteed, + .validate_bandwidth = dce100_validate_bandwidth +}; + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce100_res_pool_funcs; + pool->base.underlay_pipe_index = -1; + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dal_display_clock_dce110_create(ctx); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + /* get static clock information for PPLIB or firmware, save + * max_clock_state + */ + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { + enum clocks_state max_clocks_state = + dce110_resource_convert_clock_state_pp_to_dc( + static_clk_info.max_clocks_state); + + dal_display_clock_store_max_clocks_state( + pool->base.display_clock, max_clocks_state); + } + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = -1; + pool->base.pipe_count = res_cap.num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 40; + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = + dce100_timing_generator_create( + ctx, + i, + &dce100_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce100_mem_input_create(ctx, i, + &dce100_mi_reg_offsets[i]); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce100_ipp_create(ctx, i, + &dce100_ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce100_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce100_hw_sequencer_construct(dc)) + goto res_create_fail; + + return true; + +res_create_fail: + destruct(pool); + + return false; +} + +struct resource_pool *dce100_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h new file mode 100644 index 000000000000..bfd7518c94c9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -0,0 +1,19 @@ +/* + * dce100_resource.h + * + * Created on: 2016-01-20 + * Author: qyang + */ + +#ifndef DCE100_RESOURCE_H_ +#define DCE100_RESOURCE_H_ + +struct core_dc; +struct resource_pool; +struct dc_validation_set; + +struct resource_pool *dce100_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +#endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile new file mode 100644 index 000000000000..cd7a9095fa06 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ +dce110_ipp_gamma.o dce110_opp.o dce110_opp_csc.o \ +dce110_timing_generator.o dce110_opp_formatter.o dce110_opp_regamma.o \ +dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ +dce110_resource.o \ +dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ +dce110_mem_input_v.o dce110_opp_v.o dce110_transform_v.o + +AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE110) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c new file mode 100644 index 000000000000..518150a414e2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -0,0 +1,859 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +#include "gmc/gmc_8_2_sh_mask.h" +#include "gmc/gmc_8_2_d.h" + +#include "include/logger_interface.h" + +#include "dce110_compressor.h" + +#define DCP_REG(reg)\ + (reg + cp110->offsets.dcp_offset) +#define DMIF_REG(reg)\ + (reg + cp110->offsets.dmif_offset) + +static const struct dce110_compressor_reg_offsets reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +} +}; + +static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; + +enum fbc_idle_force { + /* Bit 0 - Display registers updated */ + FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, + + /* Bit 2 - FBC_GRPH_COMP_EN register updated */ + FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, + /* Bit 3 - FBC_SRC_SEL register updated */ + FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, + /* Bit 4 - FBC_MIN_COMPRESSION register updated */ + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, + /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ + FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, + /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, + /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, + + /* Bit 24 - Memory write to region 0 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, + /* Bit 25 - Memory write to region 1 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, + /* Bit 26 - Memory write to region 2 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, + /* Bit 27 - Memory write to region 3 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, + + /* Bit 28 - Memory write from any client other than MCIF */ + FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, + /* Bit 29 - CG statics screen signal is inactive */ + FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, +}; + +static uint32_t lpt_size_alignment(struct dce110_compressor *cp110) +{ + /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ + return cp110->base.raw_size * cp110->base.banks_num * + cp110->base.dram_channels_num; +} + +static uint32_t lpt_memory_control_config(struct dce110_compressor *cp110, + uint32_t lpt_control) +{ + /*LPT MC Config */ + if (cp110->base.options.bits.LPT_MC_CONFIG == 1) { + /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): + * 00 - 1 CHANNEL + * 01 - 2 CHANNELS + * 02 - 4 OR 6 CHANNELS + * (Only for discrete GPU, N/A for CZ) + * 03 - 8 OR 12 CHANNELS + * (Only for discrete GPU, N/A for CZ) */ + switch (cp110->base.dram_channels_num) { + case 2: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + case 1: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_PIPES!!!", + __func__); + break; + } + + /* The mapping for LPT NUM_BANKS is in + * GRPH_CONTROL.GRPH_NUM_BANKS register field + * Specifies the number of memory banks for tiling + * purposes. Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: + * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK + * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK + * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK + * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ + switch (cp110->base.banks_num) { + case 16: + set_reg_field_value( + lpt_control, + 3, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 8: + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 4: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 2: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_BANKS!!!", + __func__); + break; + } + + /* The mapping is in DMIF_ADDR_CALC. + * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for + * Carrizo specifies the memory interleave per pipe. + * It effectively specifies the location of pipe bits in + * the memory address. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte + * interleave + * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte + * interleave + */ + switch (cp110->base.channel_interleave_size) { + case 256: /*256B */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + case 512: /*512B */ + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT INTERLEAVE_SIZE!!!", + __func__); + break; + } + + /* The mapping for LOW_POWER_TILING_ROW_SIZE is in + * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field + * for Carrizo. Specifies the size of dram row in bytes. + * This should match up with NOOFCOLS field in + * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). + * This register DMIF_ADDR_CALC is not used by the + * hardware as it is only used for addrlib assertions. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row + * boundary + * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row + * boundary + * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row + * boundary */ + switch (cp110->base.raw_size) { + case 4096: /*4 KB */ + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 2048: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 1024: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT ROW_SIZE!!!", + __func__); + break; + } + } else { + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: LPT MC Configuration is not provided", + __func__); + } + + return lpt_control; +} + +static bool is_source_bigger_than_epanel_size( + struct dce110_compressor *cp110, + uint32_t source_view_width, + uint32_t source_view_height) +{ + if (cp110->base.embedded_panel_h_size != 0 && + cp110->base.embedded_panel_v_size != 0 && + ((source_view_width * source_view_height) > + (cp110->base.embedded_panel_h_size * + cp110->base.embedded_panel_v_size))) + return true; + + return false; +} + +static uint32_t align_to_chunks_number_per_line( + struct dce110_compressor *cp110, + uint32_t pixels) +{ + return 256 * ((pixels + 255) / 256); +} + +static void wait_for_fbc_state_changed( + struct dce110_compressor *cp110, + bool enabled) +{ + uint8_t counter = 0; + uint32_t addr = mmFBC_STATUS; + uint32_t value; + + while (counter < 10) { + value = dm_read_reg(cp110->base.ctx, addr); + if (get_reg_field_value( + value, + FBC_STATUS, + FBC_ENABLE_STATUS) == enabled) + break; + udelay(10); + counter++; + } + + if (counter == 10) { + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: wait counter exceeded, changes to HW not applied", + __func__); + } +} + +void dce110_compressor_power_up_fbc(struct compressor *compressor) +{ + uint32_t value; + uint32_t addr; + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value(value, 1, FBC_CNTL, FBC_EN); + set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE); + if (compressor->options.bits.CLK_GATING_DISABLED == 1) { + /* HW needs to do power measurement comparison. */ + set_reg_field_value( + value, + 0, + FBC_CNTL, + FBC_COMP_CLK_GATE_EN); + } + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_MODE; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN); + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN); + dm_write_reg(compressor->ctx, addr, value); + /*FBC_MIN_COMPRESSION 0 ==> 2:1 */ + /* 1 ==> 4:1 */ + /* 2 ==> 8:1 */ + /* 0xF ==> 1:1 */ + set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION); + dm_write_reg(compressor->ctx, addr, value); + compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1; + + value = 0; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value); + + value = 0xFFFFFF; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value); +} + +void dce110_compressor_enable_fbc( + struct compressor *compressor, + uint32_t paths_num, + struct compr_addr_and_pitch_params *params) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + (compressor->options.bits.DUMMY_BACKEND == 0) && + (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && + (!is_source_bigger_than_epanel_size( + cp110, + params->source_view_width, + params->source_view_height))) { + + uint32_t addr; + uint32_t value; + + /* Before enabling FBC first need to enable LPT if applicable + * LPT state should always be changed (enable/disable) while FBC + * is disabled */ + if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && + (params->source_view_width * + params->source_view_height <= + dce11_one_lpt_channel_max_resolution)) { + dce110_compressor_enable_lpt(compressor); + } + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value( + value, + params->inst, + FBC_CNTL, FBC_SRC_SEL); + dm_write_reg(compressor->ctx, addr, value); + + /* Keep track of enum controller_id FBC is attached to */ + compressor->is_enabled = true; + compressor->attached_inst = params->inst; + cp110->offsets = reg_offsets[params->inst - 1]; + + /*Toggle it as there is bug in HW */ + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + + wait_for_fbc_state_changed(cp110, true); + } +} + +void dce110_compressor_disable_fbc(struct compressor *compressor) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { + uint32_t reg_data; + /* Turn off compression */ + reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); + set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); + + /* Reset enum controller_id to undefined */ + compressor->attached_inst = 0; + compressor->is_enabled = false; + + /* Whenever disabling FBC make sure LPT is disabled if LPT + * supported */ + if (compressor->options.bits.LPT_SUPPORT) + dce110_compressor_disable_lpt(compressor); + + wait_for_fbc_state_changed(cp110, false); + } +} + +bool dce110_compressor_is_fbc_enabled_in_hw( + struct compressor *compressor, + uint32_t *inst) +{ + /* Check the hardware register */ + uint32_t value; + + value = dm_read_reg(compressor->ctx, mmFBC_STATUS); + if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) { + if (inst != NULL) + *inst = compressor->attached_inst; + return true; + } + + value = dm_read_reg(compressor->ctx, mmFBC_MISC); + if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) { + value = dm_read_reg(compressor->ctx, mmFBC_CNTL); + + if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) { + if (inst != NULL) + *inst = + compressor->attached_inst; + return true; + } + } + return false; +} + +bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) +{ + /* Check the hardware register */ + uint32_t value = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + return get_reg_field_value( + value, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); +} + +void dce110_compressor_program_compressed_surface_address_and_pitch( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + uint32_t value = 0; + uint32_t fbc_pitch = 0; + uint32_t compressed_surf_address_low_part = + compressor->compr_surface_address.addr.low_part; + + /* Clear content first. */ + dm_write_reg( + compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + 0); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); + + if (compressor->options.bits.LPT_SUPPORT) { + uint32_t lpt_alignment = lpt_size_alignment(cp110); + + if (lpt_alignment != 0) { + compressed_surf_address_low_part = + ((compressed_surf_address_low_part + + (lpt_alignment - 1)) / lpt_alignment) + * lpt_alignment; + } + } + + /* Write address, HIGH has to be first. */ + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + compressor->compr_surface_address.addr.high_part); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), + compressed_surf_address_low_part); + + fbc_pitch = align_to_chunks_number_per_line( + cp110, + params->source_view_width); + + if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) + fbc_pitch = fbc_pitch / 8; + else + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Unexpected DCE11 compression ratio", + __func__); + + /* Clear content first. */ + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0); + + /* Write FBC Pitch. */ + set_reg_field_value( + value, + fbc_pitch, + GRPH_COMPRESS_PITCH, + GRPH_COMPRESS_PITCH); + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value); + +} + +void dce110_compressor_disable_lpt(struct compressor *compressor) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t inx; + + /* Disable all pipes LPT Stutter */ + for (inx = 0; inx < 3; inx++) { + value = + dm_read_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 0, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), + value); + } + /* Disable Underlay pipe LPT Stutter */ + addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, addr, value); + + /* Disable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); + + /* Clear selection of Channel(s) containing Compressed Surface */ + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0xFFFFFFFF, + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); +} + +void dce110_compressor_enable_lpt(struct compressor *compressor) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t value_control; + uint32_t channels; + + /* Enable LPT Stutter from Display pipe */ + value = dm_read_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 1, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); + + /* Enable Underlay pipe LPT Stutter */ + addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, addr, value); + + /* Selection of Channel(s) containing Compressed Surface: 0xfffffff + * will disable LPT. + * STCTRL_LPT_TARGETn corresponds to channel n. */ + addr = mmLOW_POWER_TILING_CONTROL; + value_control = dm_read_reg(compressor->ctx, addr); + channels = get_reg_field_value(value_control, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + channels + 1, /* not mentioned in programming guide, + but follow DCE8.1 */ + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, addr, value); + + /* Enable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); +} + +void dce110_compressor_program_lpt_control( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); + uint32_t rows_per_channel; + uint32_t lpt_alignment; + uint32_t source_view_width; + uint32_t source_view_height; + uint32_t lpt_control = 0; + + if (!compressor->options.bits.LPT_SUPPORT) + return; + + lpt_control = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + /* POSSIBLE VALUES for Low Power Tiling Mode: + * 00 - Use channel 0 + * 01 - Use Channel 0 and 1 + * 02 - Use Channel 0,1,2,3 + * 03 - reserved */ + switch (compressor->lpt_channels_num) { + /* case 2: + * Use Channel 0 & 1 / Not used for DCE 11 */ + case 1: + /*Use Channel 0 for LPT for DCE 11 */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + break; + default: + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Invalid selected DRAM channels for LPT!!!", + __func__); + break; + } + + lpt_control = lpt_memory_control_config(cp110, lpt_control); + + /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on + * FBC compressed surface pitch. + * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * + * Surface Pitch) / (Row Size * Number of Channels * + * Number of Banks)). */ + rows_per_channel = 0; + lpt_alignment = lpt_size_alignment(cp110); + source_view_width = + align_to_chunks_number_per_line( + cp110, + params->source_view_width); + source_view_height = (params->source_view_height + 1) & (~0x1); + + if (lpt_alignment != 0) { + rows_per_channel = source_view_width * source_view_height * 4; + rows_per_channel = + (rows_per_channel % lpt_alignment) ? + (rows_per_channel / lpt_alignment + 1) : + rows_per_channel / lpt_alignment; + } + + set_reg_field_value( + lpt_control, + rows_per_channel, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROWS_PER_CHAN); + + dm_write_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL, lpt_control); +} + +/* + * DCE 11 Frame Buffer Compression Implementation + */ + +void dce110_compressor_set_fbc_invalidation_triggers( + struct compressor *compressor, + uint32_t fbc_trigger) +{ + /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19) + * for DCE 11 regions cannot be used - does not work with S/G + */ + uint32_t addr = mmFBC_CLIENT_REGION_MASK; + uint32_t value = dm_read_reg(compressor->ctx, addr); + + set_reg_field_value( + value, + 0, + FBC_CLIENT_REGION_MASK, + FBC_MEMORY_REGION_MASK); + dm_write_reg(compressor->ctx, addr, value); + + /* Setup events when to clear all CSM entries (effectively marking + * current compressed data invalid) + * For DCE 11 CSM metadata 11111 means - "Not Compressed" + * Used as the initial value of the metadata sent to the compressor + * after invalidation, to indicate that the compressor should attempt + * to compress all chunks on the current pass. Also used when the chunk + * is not successfully written to memory. + * When this CSM value is detected, FBC reads from the uncompressed + * buffer. Set events according to passed in value, these events are + * valid for DCE11: + * - bit 0 - display register updated + * - bit 28 - memory write from any client except from MCIF + * - bit 29 - CG static screen signal is inactive + * In addition, DCE11.1 also needs to set new DCE11.1 specific events + * that are used to trigger invalidation on certain register changes, + * for example enabling of Alpha Compression may trigger invalidation of + * FBC once bit is set. These events are as follows: + * - Bit 2 - FBC_GRPH_COMP_EN register updated + * - Bit 3 - FBC_SRC_SEL register updated + * - Bit 4 - FBC_MIN_COMPRESSION register updated + * - Bit 5 - FBC_ALPHA_COMP_EN register updated + * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated + * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated + */ + addr = mmFBC_IDLE_FORCE_CLEAR_MASK; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + fbc_trigger | + FBC_IDLE_FORCE_GRPH_COMP_EN | + FBC_IDLE_FORCE_SRC_SEL_CHANGE | + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | + FBC_IDLE_FORCE_ALPHA_COMP_EN | + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, + FBC_IDLE_FORCE_CLEAR_MASK, + FBC_IDLE_FORCE_CLEAR_MASK); + dm_write_reg(compressor->ctx, addr, value); +} + +bool dce110_compressor_construct(struct dce110_compressor *compressor, + struct dc_context *ctx) +{ + struct dc_bios *bp = ctx->dc_bios; + struct embedded_panel_info panel_info; + + compressor->base.options.bits.FBC_SUPPORT = true; + compressor->base.options.bits.LPT_SUPPORT = true; + /* For DCE 11 always use one DRAM channel for LPT */ + compressor->base.lpt_channels_num = 1; + compressor->base.options.bits.DUMMY_BACKEND = false; + + /* Check if this system has more than 1 DRAM channel; if only 1 then LPT + * should not be supported */ + if (compressor->base.memory_bus_width == 64) + compressor->base.options.bits.LPT_SUPPORT = false; + + compressor->base.options.bits.CLK_GATING_DISABLED = false; + + compressor->base.ctx = ctx; + compressor->base.embedded_panel_h_size = 0; + compressor->base.embedded_panel_v_size = 0; + compressor->base.memory_bus_width = ctx->asic_id.vram_width; + compressor->base.allocated_size = 0; + compressor->base.preferred_requested_size = 0; + compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; + compressor->base.options.raw = 0; + compressor->base.banks_num = 0; + compressor->base.raw_size = 0; + compressor->base.channel_interleave_size = 0; + compressor->base.dram_channels_num = 0; + compressor->base.lpt_channels_num = 0; + compressor->base.attached_inst = 0; + compressor->base.is_enabled = false; + + if (BP_RESULT_OK == + bp->funcs->get_embedded_panel_info(bp, &panel_info)) { + compressor->base.embedded_panel_h_size = + panel_info.lcd_timing.horizontal_addressable; + compressor->base.embedded_panel_v_size = + panel_info.lcd_timing.vertical_addressable; + } + return true; +} + +struct compressor *dce110_compressor_create(struct dc_context *ctx) +{ + struct dce110_compressor *cp110 = + dm_alloc(sizeof(struct dce110_compressor)); + + if (!cp110) + return NULL; + + if (dce110_compressor_construct(cp110, ctx)) + return &cp110->base; + + BREAK_TO_DEBUGGER(); + dm_free(cp110); + return NULL; +} + +void dce110_compressor_destroy(struct compressor **compressor) +{ + dm_free(TO_DCE110_COMPRESSOR(*compressor)); + *compressor = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h new file mode 100644 index 000000000000..22af5be51581 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h @@ -0,0 +1,78 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_COMPRESSOR_DCE110_H__ +#define __DC_COMPRESSOR_DCE110_H__ + +#include "../inc/compressor.h" + +#define TO_DCE110_COMPRESSOR(compressor)\ + container_of(compressor, struct dce110_compressor, base) + +struct dce110_compressor_reg_offsets { + uint32_t dcp_offset; + uint32_t dmif_offset; +}; + +struct dce110_compressor { + struct compressor base; + struct dce110_compressor_reg_offsets offsets; +}; + +struct compressor *dce110_compressor_create(struct dc_context *ctx); + +bool dce110_compressor_construct(struct dce110_compressor *cp110, + struct dc_context *ctx); + +void dce110_compressor_destroy(struct compressor **cp); + +/* FBC RELATED */ +void dce110_compressor_power_up_fbc(struct compressor *cp); + +void dce110_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, + struct compr_addr_and_pitch_params *params); + +void dce110_compressor_disable_fbc(struct compressor *cp); + +void dce110_compressor_set_fbc_invalidation_triggers(struct compressor *cp, + uint32_t fbc_trigger); + +void dce110_compressor_program_compressed_surface_address_and_pitch( + struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce110_compressor_is_fbc_enabled_in_hw(struct compressor *cp, + uint32_t *fbc_mapped_crtc_id); + +/* LPT RELATED */ +void dce110_compressor_enable_lpt(struct compressor *cp); + +void dce110_compressor_disable_lpt(struct compressor *cp); + +void dce110_compressor_program_lpt_control(struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *cp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c new file mode 100644 index 000000000000..1a682996b531 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -0,0 +1,1978 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dc.h" +#include "dc_bios_types.h" +#include "core_types.h" +#include "core_status.h" +#include "resource.h" +#include "hw_sequencer.h" +#include "dm_helpers.h" +#include "dce110_hw_sequencer.h" +#include "dce110_timing_generator.h" + +#include "bios/bios_parser_helper.h" +#include "timing_generator.h" +#include "mem_input.h" +#include "opp.h" +#include "ipp.h" +#include "transform.h" +#include "stream_encoder.h" +#include "link_encoder.h" +#include "clock_source.h" +#include "gamma_calcs.h" +#include "audio.h" +#include "dce/dce_hwseq.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +struct dce110_hw_seq_reg_offsets { + uint32_t crtc; +}; + +static const struct dce110_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; + +#define HW_REG_BLND(reg, id)\ + (reg + reg_offsets[id].blnd) + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +#define MAX_WATERMARK 0xFFFF +#define SAFE_NBP_MARK 0x7FFF + +/******************************************************************************* + * Private definitions + ******************************************************************************/ +/***************************PIPE_CONTROL***********************************/ +static void dce110_init_pte(struct dc_context *ctx) +{ + uint32_t addr; + uint32_t value = 0; + uint32_t chunk_int = 0; + uint32_t chunk_mul = 0; + + addr = mmUNP_DVMM_PTE_CONTROL; + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + DVMM_PTE_CONTROL, + DVMM_USE_SINGLE_PTE); + + set_reg_field_value( + value, + 1, + DVMM_PTE_CONTROL, + DVMM_PTE_BUFFER_MODE0); + + set_reg_field_value( + value, + 1, + DVMM_PTE_CONTROL, + DVMM_PTE_BUFFER_MODE1); + + dm_write_reg(ctx, addr, value); + + addr = mmDVMM_PTE_REQ; + value = dm_read_reg(ctx, addr); + + chunk_int = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + chunk_mul = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + if (chunk_int != 0x4 || chunk_mul != 0x4) { + + set_reg_field_value( + value, + 255, + DVMM_PTE_REQ, + MAX_PTEREQ_TO_ISSUE); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + dm_write_reg(ctx, addr, value); + } +} +/**************************************************************************/ + +static void enable_display_pipe_clock_gating( + struct dc_context *ctx, + bool clock_gating) +{ + /*TODO*/ +} + +static bool dce110_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; + + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + return true; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (controller_id == underlay_idx) + controller_id = CONTROLLER_ID_UNDERLAY0 - 1; + + if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){ + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + * + * Bios parser accepts controller_id = 6 as indicative of + * underlay pipe in dce110. But we do not support more + * than 3. + */ + if (controller_id < CONTROLLER_ID_MAX - 1) + dm_write_reg(ctx, + HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id), + 0); + } + + if (power_gating != PIPE_GATING_CONTROL_ENABLE) + dce110_init_pte(ctx); + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + +static void build_prescale_params(struct ipp_prescale_params *prescale_params, + const struct core_surface *surface) +{ + prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; + + switch (surface->public.format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + prescale_params->scale = 0x2020; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + prescale_params->scale = 0x2008; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + prescale_params->scale = 0x2000; + break; + default: + ASSERT(false); + } +} + +static bool set_gamma_ramp( + struct input_pixel_processor *ipp, + struct output_pixel_processor *opp, + const struct core_gamma *ramp, + const struct core_surface *surface) +{ + struct ipp_prescale_params prescale_params = { 0 }; + struct pwl_params *regamma_params; + bool result = false; + + regamma_params = dm_alloc(sizeof(struct pwl_params)); + if (regamma_params == NULL) + goto regamma_alloc_fail; + + regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; + + opp->funcs->opp_power_on_regamma_lut(opp, true); + + if (ipp) { + build_prescale_params(&prescale_params, surface); + ipp->funcs->ipp_program_prescale(ipp, &prescale_params); + } + + if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) { + + opp->funcs->opp_program_regamma_pwl(opp, regamma_params); + if (ipp) + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + } else { + if (ipp) + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); + } + + opp->funcs->opp_power_on_regamma_lut(opp, false); + + result = true; + + dm_free(regamma_params); + +regamma_alloc_fail: + return result; +} + +static enum dc_status bios_parser_crtc_source_select( + struct pipe_ctx *pipe_ctx) +{ + struct dc_bios *dcb; + /* call VBIOS table to set CRTC source for the HW + * encoder block + * note: video bios clears all FMT setting here. */ + struct bp_crtc_source_select crtc_source_select = {0}; + const struct core_sink *sink = pipe_ctx->stream->sink; + + crtc_source_select.engine_id = pipe_ctx->stream_enc->id; + crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1; + /*TODO: Need to un-hardcode color depth, dp_audio and account for + * the case where signal and sink signal is different (translator + * encoder)*/ + crtc_source_select.signal = pipe_ctx->stream->signal; + crtc_source_select.enable_dp_audio = false; + crtc_source_select.sink_signal = pipe_ctx->stream->signal; + crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; + + dcb = sink->ctx->dc_bios; + + if (BP_RESULT_OK != dcb->funcs->crtc_source_select( + dcb, + &crtc_source_select)) { + return DC_ERROR_UNEXPECTED; + } + + return DC_OK; +} + +void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) +{ + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->update_hdmi_info_packets( + pipe_ctx->stream_enc, + &pipe_ctx->encoder_info_frame); + else if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->update_dp_info_packets( + pipe_ctx->stream_enc, + &pipe_ctx->encoder_info_frame); +} + +void dce110_enable_stream(struct pipe_ctx *pipe_ctx) +{ + enum dc_lane_count lane_count = + pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count; + + struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + struct core_link *link = pipe_ctx->stream->sink->link; + + /* 1. update AVI info frame (HDMI, DP) + * we always need to update info frame + */ + uint32_t active_total_with_borders; + uint32_t early_control = 0; + struct timing_generator *tg = pipe_ctx->tg; + + /* TODOFPGA may change to hwss.update_info_frame */ + dce110_update_info_frame(pipe_ctx); + /* enable early control to avoid corruption on DP monitor*/ + active_total_with_borders = + timing->h_addressable + + timing->h_border_left + + timing->h_border_right; + + if (lane_count != 0) + early_control = active_total_with_borders % lane_count; + + if (early_control == 0) + early_control = lane_count; + + tg->funcs->set_early_control(tg, early_control); + + /* enable audio only within mode set */ + if (pipe_ctx->audio != NULL) { + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_enc); + } + + /* For MST, there are multiply stream go to only one link. + * connect DIG back_end to front_end while enable_stream and + * disconnect them during disable_stream + * BY this, it is logic clean to separate stream and link */ + link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, + pipe_ctx->stream_enc->id, true); + +} + +void dce110_disable_stream(struct pipe_ctx *pipe_ctx) +{ + struct core_stream *stream = pipe_ctx->stream; + struct core_link *link = stream->sink->link; + + if (pipe_ctx->audio) { + pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_audio_disable( + pipe_ctx->stream_enc); + else + pipe_ctx->stream_enc->funcs->hdmi_audio_disable( + pipe_ctx->stream_enc); + + pipe_ctx->audio = NULL; + + /* TODO: notify audio driver for if audio modes list changed + * add audio mode list change flag */ + /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, + * stream->stream_engine_id); + */ + } + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets( + pipe_ctx->stream_enc); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->stop_dp_info_packets( + pipe_ctx->stream_enc); + + pipe_ctx->stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_enc, true); + + + /* blank at encoder level */ + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc); + + link->link_enc->funcs->connect_dig_be_to_fe( + link->link_enc, + pipe_ctx->stream_enc->id, + false); + +} + +void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, + struct dc_link_settings *link_settings) +{ + struct encoder_unblank_param params = { { 0 } }; + + /* only 3 items below are used by unblank */ + params.crtc_timing.pixel_clock = + pipe_ctx->stream->public.timing.pix_clk_khz; + params.link_settings.link_rate = link_settings->link_rate; + pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); +} + +static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) +{ + switch (crtc_id) { + case CONTROLLER_ID_D0: + return DTO_SOURCE_ID0; + case CONTROLLER_ID_D1: + return DTO_SOURCE_ID1; + case CONTROLLER_ID_D2: + return DTO_SOURCE_ID2; + case CONTROLLER_ID_D3: + return DTO_SOURCE_ID3; + case CONTROLLER_ID_D4: + return DTO_SOURCE_ID4; + case CONTROLLER_ID_D5: + return DTO_SOURCE_ID5; + default: + return DTO_SOURCE_UNKNOWN; + } +} + +static void build_audio_output( + const struct pipe_ctx *pipe_ctx, + struct audio_output *audio_output) +{ + const struct core_stream *stream = pipe_ctx->stream; + audio_output->engine_id = pipe_ctx->stream_enc->id; + + audio_output->signal = pipe_ctx->stream->signal; + + /* audio_crtc_info */ + + audio_output->crtc_info.h_total = + stream->public.timing.h_total; + + /* + * Audio packets are sent during actual CRTC blank physical signal, we + * need to specify actual active signal portion + */ + audio_output->crtc_info.h_active = + stream->public.timing.h_addressable + + stream->public.timing.h_border_left + + stream->public.timing.h_border_right; + + audio_output->crtc_info.v_active = + stream->public.timing.v_addressable + + stream->public.timing.v_border_top + + stream->public.timing.v_border_bottom; + + audio_output->crtc_info.pixel_repetition = 1; + + audio_output->crtc_info.interlaced = + stream->public.timing.flags.INTERLACE; + + audio_output->crtc_info.refresh_rate = + (stream->public.timing.pix_clk_khz*1000)/ + (stream->public.timing.h_total*stream->public.timing.v_total); + + audio_output->crtc_info.color_depth = + stream->public.timing.display_color_depth; + + audio_output->crtc_info.requested_pixel_clock = + pipe_ctx->pix_clk_params.requested_pix_clk; + + /* + * TODO - Investigate why calculated pixel clk has to be + * requested pixel clk + */ + audio_output->crtc_info.calculated_pixel_clock = + pipe_ctx->pix_clk_params.requested_pix_clk; + + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || + pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + audio_output->pll_info.dp_dto_source_clock_in_khz = + dal_display_clock_get_dp_ref_clk_frequency( + pipe_ctx->dis_clk); + } + + audio_output->pll_info.feed_back_divider = + pipe_ctx->pll_settings.feedback_divider; + + audio_output->pll_info.dto_source = + translate_to_dto_source( + pipe_ctx->pipe_idx + 1); + + /* TODO hard code to enable for now. Need get from stream */ + audio_output->pll_info.ss_enabled = true; + + audio_output->pll_info.ss_percentage = + pipe_ctx->pll_settings.ss_percentage; +} + +static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4; + + switch (pipe_ctx->scl_data.format) { + case PIXEL_FORMAT_ARGB8888: + /* set boarder color to red */ + color->color_r_cr = color_value; + break; + + case PIXEL_FORMAT_ARGB2101010: + /* set boarder color to blue */ + color->color_b_cb = color_value; + break; + case PIXEL_FORMAT_420BPP12: + /* set boarder color to green */ + color->color_g_y = color_value; + break; + case PIXEL_FORMAT_FP16: + /* set boarder color to white */ + color->color_r_cr = color_value; + color->color_b_cb = color_value; + color->color_g_y = color_value; + break; + default: + break; + } +} + +static void program_scaler(const struct core_dc *dc, + const struct pipe_ctx *pipe_ctx) +{ + struct tg_color color = {0}; + + if (dc->public.debug.surface_visual_confirm) + get_surface_visual_confirm_color(pipe_ctx, &color); + else + color_space_to_black_color(dc, + pipe_ctx->stream->public.output_color_space, + &color); + + pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth( + pipe_ctx->xfm, + pipe_ctx->scl_data.lb_params.depth, + &pipe_ctx->stream->bit_depth_params); + + if (pipe_ctx->tg->funcs->set_overscan_blank_color) + pipe_ctx->tg->funcs->set_overscan_blank_color( + pipe_ctx->tg, + &color); + + pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, + &pipe_ctx->scl_data); +} + +static enum dc_status prog_pixclk_crtc_otg( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct core_dc *dc) +{ + struct core_stream *stream = pipe_ctx->stream; + struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. + pipe_ctx[pipe_ctx->pipe_idx]; + struct tg_color black_color = {0}; + + if (!pipe_ctx_old->stream) { + + /* program blank color */ + color_space_to_black_color(dc, + stream->public.output_color_space, &black_color); + pipe_ctx->tg->funcs->set_blank_color( + pipe_ctx->tg, + &black_color); + /* + * Must blank CRTC after disabling power gating and before any + * programming, otherwise CRTC will be hung in bad state + */ + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + + if (false == pipe_ctx->clock_source->funcs->program_pix_clk( + pipe_ctx->clock_source, + &pipe_ctx->pix_clk_params, + &pipe_ctx->pll_settings)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + + pipe_ctx->tg->funcs->program_timing( + pipe_ctx->tg, + &stream->public.timing, + true); + } + + if (!pipe_ctx_old->stream) { + if (false == pipe_ctx->tg->funcs->enable_crtc( + pipe_ctx->tg)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + } + + return DC_OK; +} + +static enum dc_status apply_single_controller_ctx_to_hw( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct core_dc *dc) +{ + struct core_stream *stream = pipe_ctx->stream; + struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. + pipe_ctx[pipe_ctx->pipe_idx]; + + /* */ + dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc); + + pipe_ctx->opp->funcs->opp_set_dyn_expansion( + pipe_ctx->opp, + COLOR_SPACE_YCBCR601, + stream->public.timing.display_color_depth, + pipe_ctx->stream->signal); + + pipe_ctx->opp->funcs->opp_program_fmt( + pipe_ctx->opp, + &stream->bit_depth_params, + &stream->clamping); + + /* FPGA does not program backend */ + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + return DC_OK; + + /* TODO: move to stream encoder */ + if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) + if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + + if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) + stream->sink->link->link_enc->funcs->setup( + stream->sink->link->link_enc, + pipe_ctx->stream->signal); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_set_stream_attribute( + pipe_ctx->stream_enc, + &stream->public.timing, + stream->public.output_color_space); + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute( + pipe_ctx->stream_enc, + &stream->public.timing, + stream->phy_pix_clk, + pipe_ctx->audio != NULL); + + if (dc_is_dvi_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute( + pipe_ctx->stream_enc, + &stream->public.timing, + (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? + true : false); + + if (!pipe_ctx_old->stream) { + core_link_enable_stream(pipe_ctx); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dce110_unblank_stream(pipe_ctx, + &stream->sink->link->public.cur_link_settings); + } + + pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + /* program_scaler and allocate_mem_input are not new asic */ + if (!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data, + &pipe_ctx->scl_data, + sizeof(struct scaler_data)) != 0) + program_scaler(dc, pipe_ctx); + + /* mst support - use total stream count */ + pipe_ctx->mi->funcs->allocate_mem_input( + pipe_ctx->mi, + stream->public.timing.h_total, + stream->public.timing.v_total, + stream->public.timing.pix_clk_khz, + context->target_count); + + return DC_OK; +} + +/******************************************************************************/ + +static void power_down_encoders(struct core_dc *dc) +{ + int i; + + for (i = 0; i < dc->link_count; i++) { + dc->links[i]->link_enc->funcs->disable_output( + dc->links[i]->link_enc, SIGNAL_TYPE_NONE); + } +} + +static void power_down_controllers(struct core_dc *dc) +{ + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + dc->res_pool->timing_generators[i]->funcs->disable_crtc( + dc->res_pool->timing_generators[i]); + } +} + +static void power_down_clock_sources(struct core_dc *dc) +{ + int i; + + if (dc->res_pool->dp_clock_source->funcs->cs_power_down( + dc->res_pool->dp_clock_source) == false) + dm_error("Failed to power down pll! (dp clk src)\n"); + + for (i = 0; i < dc->res_pool->clk_src_count; i++) { + if (dc->res_pool->clock_sources[i]->funcs->cs_power_down( + dc->res_pool->clock_sources[i]) == false) + dm_error("Failed to power down pll! (clk src index=%d)\n", i); + } +} + +static void power_down_all_hw_blocks(struct core_dc *dc) +{ + power_down_encoders(dc); + + power_down_controllers(dc); + + power_down_clock_sources(dc); +} + +static void disable_vga_and_power_gate_all_controllers( + struct core_dc *dc) +{ + int i; + struct timing_generator *tg; + struct dc_context *ctx = dc->ctx; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + tg = dc->res_pool->timing_generators[i]; + + tg->funcs->disable_vga(tg); + + /* Enable CLOCK gating for each pipe BEFORE controller + * powergating. */ + enable_display_pipe_clock_gating(ctx, + true); + + dc->hwss.power_down_front_end( + dc, &dc->current_context->res_ctx.pipe_ctx[i]); + } +} + +/** + * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need: + * 1. Power down all DC HW blocks + * 2. Disable VGA engine on all controllers + * 3. Enable power gating for controller + * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) + */ +void dce110_enable_accelerated_mode(struct core_dc *dc) +{ + power_down_all_hw_blocks(dc); + + disable_vga_and_power_gate_all_controllers(dc); + bios_set_scratch_acc_mode_change(dc->ctx->dc_bios); +} + +/** + * Call display_engine_clock_dce80 to perform the Dclk programming. + */ +void dce110_set_display_clock(struct validate_context *context) +{ + /* Program the display engine clock. + * Check DFS bypass mode support or not. DFSbypass feature is only when + * BIOS GPU info table reports support. */ + + if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) { + /*TODO: set_display_clock_dfs_bypass( + hws, + path_set, + context->res_ctx.pool->display_clock, + context->res_ctx.min_clocks.min_dclk_khz);*/ + } else { + /* + * TODO: need to either port work around from DAL2 function + * getActualRequiredDisplayClock or program displayclock without + * calling vbios. Currently temporily work + * around by increasing the displclk by 15 percent + */ + dal_display_clock_set_clock( + context->res_ctx.pool->display_clock, + context->bw_results.dispclk_khz * 115 / 100); + } + + + /* TODO: When changing display engine clock, DMCU WaitLoop must be + * reconfigured in order to maintain the same delays within DMCU + * programming sequences. */ +} + +static uint32_t compute_pstate_blackout_duration( + struct bw_fixed blackout_duration, + const struct core_stream *stream) +{ + uint32_t total_dest_line_time_ns; + uint32_t pstate_blackout_duration_ns; + + pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; + + total_dest_line_time_ns = 1000000UL * + stream->public.timing.h_total / + stream->public.timing.pix_clk_khz + + pstate_blackout_duration_ns; + + return total_dest_line_time_ns; +} + +/* get the index of the pipe_ctx if there were no gaps in the pipe_ctx array*/ +int get_bw_result_idx( + struct resource_context *res_ctx, + int pipe_idx) +{ + int i, collapsed_idx; + + if (res_ctx->pipe_ctx[pipe_idx].top_pipe) + return 3; + + collapsed_idx = 0; + for (i = 0; i < pipe_idx; i++) { + if (res_ctx->pipe_ctx[i].stream) + collapsed_idx++; + } + + return collapsed_idx; +} + +static bool is_watermark_set_a_greater( + const struct bw_watermarks *set_a, + const struct bw_watermarks *set_b) +{ + if (set_a->a_mark > set_b->a_mark + || set_a->b_mark > set_b->b_mark + || set_a->c_mark > set_b->c_mark + || set_a->d_mark > set_b->d_mark) + return true; + return false; +} + +static bool did_watermarks_increase( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct validate_context *old_context) +{ + int collapsed_pipe_idx = get_bw_result_idx(&context->res_ctx, + pipe_ctx->pipe_idx); + int old_collapsed_pipe_idx = get_bw_result_idx(&old_context->res_ctx, + pipe_ctx->pipe_idx); + struct pipe_ctx *old_pipe_ctx = &old_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + + if (!old_pipe_ctx->stream) + return true; + + if (is_watermark_set_a_greater( + &context->bw_results.nbp_state_change_wm_ns[collapsed_pipe_idx], + &old_context->bw_results.nbp_state_change_wm_ns[old_collapsed_pipe_idx])) + return true; + if (is_watermark_set_a_greater( + &context->bw_results.stutter_exit_wm_ns[collapsed_pipe_idx], + &old_context->bw_results.stutter_exit_wm_ns[old_collapsed_pipe_idx])) + return true; + if (is_watermark_set_a_greater( + &context->bw_results.urgent_wm_ns[collapsed_pipe_idx], + &old_context->bw_results.urgent_wm_ns[old_collapsed_pipe_idx])) + return true; + + return false; +} + +static void program_wm_for_pipe(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + int total_dest_line_time_ns = compute_pstate_blackout_duration( + dc->bw_vbios.blackout_duration, + pipe_ctx->stream); + int bw_result_idx = get_bw_result_idx(&context->res_ctx, + pipe_ctx->pipe_idx); + + pipe_ctx->mi->funcs->mem_input_program_display_marks( + pipe_ctx->mi, + context->bw_results.nbp_state_change_wm_ns[bw_result_idx], + context->bw_results.stutter_exit_wm_ns[bw_result_idx], + context->bw_results.urgent_wm_ns[bw_result_idx], + total_dest_line_time_ns); + + if (pipe_ctx->top_pipe) + pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( + pipe_ctx->mi, + context->bw_results.nbp_state_change_wm_ns[bw_result_idx + 1], + context->bw_results.stutter_exit_wm_ns[bw_result_idx + 1], + context->bw_results.urgent_wm_ns[bw_result_idx + 1], + total_dest_line_time_ns); +} + +void dce110_set_displaymarks( + const struct core_dc *dc, + struct validate_context *context) +{ + uint8_t i, num_pipes; + unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; + + for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + uint32_t total_dest_line_time_ns; + + if (pipe_ctx->stream == NULL) + continue; + + total_dest_line_time_ns = compute_pstate_blackout_duration( + dc->bw_vbios.blackout_duration, pipe_ctx->stream); + pipe_ctx->mi->funcs->mem_input_program_display_marks( + pipe_ctx->mi, + context->bw_results.nbp_state_change_wm_ns[num_pipes], + context->bw_results.stutter_exit_wm_ns[num_pipes], + context->bw_results.urgent_wm_ns[num_pipes], + total_dest_line_time_ns); + if (i == underlay_idx) { + num_pipes++; + pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( + pipe_ctx->mi, + context->bw_results.nbp_state_change_wm_ns[num_pipes], + context->bw_results.stutter_exit_wm_ns[num_pipes], + context->bw_results.urgent_wm_ns[num_pipes], + total_dest_line_time_ns); + } + num_pipes++; + } +} + +static void set_safe_displaymarks(struct resource_context *res_ctx) +{ + int i; + int underlay_idx = res_ctx->pool->underlay_pipe_index; + struct bw_watermarks max_marks = { + MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; + struct bw_watermarks nbp_marks = { + SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; + + for (i = 0; i < MAX_PIPES; i++) { + if (res_ctx->pipe_ctx[i].stream == NULL) + continue; + + res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks( + res_ctx->pipe_ctx[i].mi, + nbp_marks, + max_marks, + max_marks, + MAX_WATERMARK); + if (i == underlay_idx) + res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_chroma_display_marks( + res_ctx->pipe_ctx[i].mi, + nbp_marks, + max_marks, + max_marks, + MAX_WATERMARK); + } +} + +static void switch_dp_clock_sources( + const struct core_dc *dc, + struct resource_context *res_ctx) +{ + uint8_t i; + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) + continue; + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) { + struct clock_source *clk_src = + resource_find_used_clk_src_for_sharing( + res_ctx, pipe_ctx); + + if (clk_src && + clk_src != pipe_ctx->clock_source) { + resource_unreference_clock_source( + res_ctx, pipe_ctx->clock_source); + pipe_ctx->clock_source = clk_src; + resource_reference_clock_source(res_ctx, clk_src); + + dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i); + } + } + } +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ + +static void reset_single_pipe_hw_ctx( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + core_link_disable_stream(pipe_ctx); + if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) { + dm_error("DC: failed to blank crtc!\n"); + BREAK_TO_DEBUGGER(); + } + pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); + pipe_ctx->mi->funcs->free_mem_input( + pipe_ctx->mi, context->target_count); + resource_unreference_clock_source( + &context->res_ctx, pipe_ctx->clock_source); + + dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); + + pipe_ctx->stream = NULL; +} + +static void set_drr(struct pipe_ctx **pipe_ctx, + int num_pipes, int vmin, int vmax) +{ + int i = 0; + struct drr_params params = {0}; + + params.vertical_total_max = vmax; + params.vertical_total_min = vmin; + + /* TODO: If multiple pipes are to be supported, you need + * some GSL stuff + */ + + for (i = 0; i < num_pipes; i++) { + pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, ¶ms); + } +} + +static void set_static_screen_control(struct pipe_ctx **pipe_ctx, + int num_pipes, int value) +{ + unsigned int i; + + for (i = 0; i < num_pipes; i++) + pipe_ctx[i]->tg->funcs-> + set_static_screen_control(pipe_ctx[i]->tg, value); +} + +/* unit: in_khz before mode set, get pixel clock from context. ASIC register + * may not be programmed yet. + * TODO: after mode set, pre_mode_set = false, + * may read PLL register to get pixel clock + */ +static uint32_t get_max_pixel_clock_for_all_paths( + struct core_dc *dc, + struct validate_context *context, + bool pre_mode_set) +{ + uint32_t max_pix_clk = 0; + int i; + + if (!pre_mode_set) { + /* TODO: read ASIC register to get pixel clock */ + ASSERT(0); + } + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + /* do not check under lay */ + if (pipe_ctx->top_pipe) + continue; + + if (pipe_ctx->pix_clk_params.requested_pix_clk > max_pix_clk) + max_pix_clk = + pipe_ctx->pix_clk_params.requested_pix_clk; + } + + if (max_pix_clk == 0) + ASSERT(0); + + return max_pix_clk; +} + +/* + * Find clock state based on clock requested. if clock value is 0, simply + * set clock state as requested without finding clock state by clock value + */ +static void apply_min_clocks( + struct core_dc *dc, + struct validate_context *context, + enum clocks_state *clocks_state, + bool pre_mode_set) +{ + struct state_dependent_clocks req_clocks = {0}; + struct pipe_ctx *pipe_ctx; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; + if (pipe_ctx->dis_clk != NULL) + break; + } + + if (!pre_mode_set) { + /* set clock_state without verification */ + if (dal_display_clock_set_min_clocks_state( + pipe_ctx->dis_clk, *clocks_state)) + return; + + /* TODOFPGA */ + } + + /* get the required state based on state dependent clocks: + * display clock and pixel clock + */ + req_clocks.display_clk_khz = context->bw_results.dispclk_khz; + + req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( + dc, context, true); + + if (dal_display_clock_get_required_clocks_state( + pipe_ctx->dis_clk, &req_clocks, clocks_state)) { + dal_display_clock_set_min_clocks_state( + pipe_ctx->dis_clk, *clocks_state); + } else { + } +} + +static enum dc_status apply_ctx_to_hw_fpga( + struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_ERROR_UNEXPECTED; + int i; + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->stream == pipe_ctx_old->stream) + continue; + + status = apply_single_controller_ctx_to_hw( + pipe_ctx, + context, + dc); + + if (status != DC_OK) + return status; + } + + return DC_OK; +} + +static void reset_hw_ctx_wrap( + struct core_dc *dc, + struct validate_context *context) +{ + int i; + + /* Reset old context */ + /* look up the targets that have been removed since last commit */ + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + /* Note: We need to disable output if clock sources change, + * since bios does optimization and doesn't apply if changing + * PHY when not already disabled. + */ + + /* Skip underlay pipe since it will be handled in commit surface*/ + if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe) + continue; + + if (!pipe_ctx->stream || + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + reset_single_pipe_hw_ctx( + dc, pipe_ctx_old, dc->current_context); + } +} + +/*TODO: const validate_context*/ +enum dc_status dce110_apply_ctx_to_hw( + struct core_dc *dc, + struct validate_context *context) +{ + struct dc_bios *dcb = dc->ctx->dc_bios; + enum dc_status status; + int i; + bool programmed_audio_dto = false; + enum clocks_state clocks_state = CLOCKS_STATE_INVALID; + + /* Reset old context */ + /* look up the targets that have been removed since last commit */ + dc->hwss.reset_hw_ctx_wrap(dc, context); + + /* Skip applying if no targets */ + if (context->target_count <= 0) + return DC_OK; + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + apply_ctx_to_hw_fpga(dc, context); + return DC_OK; + } + + /* Apply new context */ + dcb->funcs->set_scratch_critical_state(dcb, true); + + /* below is for real asic only */ + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) + continue; + + if (pipe_ctx->stream == pipe_ctx_old->stream) { + if (pipe_ctx_old->clock_source != pipe_ctx->clock_source) + dce_crtc_switch_to_clk_src(dc->hwseq, + pipe_ctx->clock_source, i); + continue; + } + + dc->hwss.enable_display_power_gating( + dc, i, dc->ctx->dc_bios, + PIPE_GATING_CONTROL_DISABLE); + } + + set_safe_displaymarks(&context->res_ctx); + /*TODO: when pplib works*/ + apply_min_clocks(dc, context, &clocks_state, true); + + if (context->bw_results.dispclk_khz + > dc->current_context->bw_results.dispclk_khz) + dc->hwss.set_display_clock(context); + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->stream == pipe_ctx_old->stream) + continue; + + if (pipe_ctx->top_pipe) + continue; + + if (context->res_ctx.pipe_ctx[i].audio != NULL) { + /* Setup audio rate clock source */ + /* Issue: + * Audio lag happened on DP monitor when unplug a HDMI monitor + * + * Cause: + * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL + * is set to either dto0 or dto1, audio should work fine. + * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, + * set to dto0 will cause audio lag. + * + * Solution: + * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, + * find first available pipe with audio, setup audio wall DTO per topology + * instead of per pipe. + */ + struct audio_output audio_output; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + build_audio_output(pipe_ctx, &audio_output); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_enc, + pipe_ctx->audio->inst, + &pipe_ctx->stream->public.audio_info); + else + pipe_ctx->stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_enc, + pipe_ctx->audio->inst, + &pipe_ctx->stream->public.audio_info, + &audio_output.crtc_info); + + pipe_ctx->audio->funcs->az_configure( + pipe_ctx->audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &pipe_ctx->stream->public.audio_info); + + if (!programmed_audio_dto) { + pipe_ctx->audio->funcs->wall_dto_setup( + pipe_ctx->audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + programmed_audio_dto = true; + } + } + + status = apply_single_controller_ctx_to_hw( + pipe_ctx, + context, + dc); + + if (DC_OK != status) + return status; + } + + dc->hwss.set_displaymarks(dc, context); + + /* to save power */ + apply_min_clocks(dc, context, &clocks_state, false); + + dcb->funcs->set_scratch_critical_state(dcb, false); + + switch_dp_clock_sources(dc, &context->res_ctx); + + return DC_OK; +} + +/******************************************************************************* + * Front End programming + ******************************************************************************/ +static void set_default_colors(struct pipe_ctx *pipe_ctx) +{ + struct default_adjustment default_adjust = { 0 }; + + default_adjust.force_hw_default = false; + if (pipe_ctx->surface == NULL) + default_adjust.in_color_space = COLOR_SPACE_SRGB; + else + default_adjust.in_color_space = + pipe_ctx->surface->public.color_space; + if (pipe_ctx->stream == NULL) + default_adjust.out_color_space = COLOR_SPACE_SRGB; + else + default_adjust.out_color_space = + pipe_ctx->stream->public.output_color_space; + default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; + default_adjust.surface_pixel_format = pipe_ctx->scl_data.format; + + /* display color depth */ + default_adjust.color_depth = + pipe_ctx->stream->public.timing.display_color_depth; + + /* Lb color depth */ + default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth; + + pipe_ctx->opp->funcs->opp_set_csc_default( + pipe_ctx->opp, &default_adjust); +} + +static void program_blender(const struct core_dc *dc, + struct pipe_ctx *pipe_ctx) +{ + enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; + + if (pipe_ctx->bottom_pipe) { + if (pipe_ctx->bottom_pipe->surface->public.visible) { + if (pipe_ctx->surface->public.visible) + blender_mode = BLND_MODE_BLENDING; + else + blender_mode = BLND_MODE_OTHER_PIPE; + } + } + dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); +} + +/** + * TODO REMOVE, USE UPDATE INSTEAD + */ +static void set_plane_config( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct resource_context *res_ctx) +{ + struct mem_input *mi = pipe_ctx->mi; + struct core_surface *surface = pipe_ctx->surface; + struct xfm_grph_csc_adjustment adjust; + struct out_csc_color_matrix tbl_entry; + unsigned int i; + + memset(&adjust, 0, sizeof(adjust)); + memset(&tbl_entry, 0, sizeof(tbl_entry)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); + + set_default_colors(pipe_ctx); + if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + == true) { + tbl_entry.color_space = + pipe_ctx->stream->public.output_color_space; + + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = + pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + + pipe_ctx->opp->funcs->opp_set_csc_adjustment + (pipe_ctx->opp, &tbl_entry); + } + + if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + adjust.temperature_matrix[0] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[0]; + adjust.temperature_matrix[1] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[1]; + adjust.temperature_matrix[2] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[2]; + adjust.temperature_matrix[3] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[4]; + adjust.temperature_matrix[4] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[5]; + adjust.temperature_matrix[5] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[6]; + adjust.temperature_matrix[6] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[8]; + adjust.temperature_matrix[7] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[9]; + adjust.temperature_matrix[8] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[10]; + } + + pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + + pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + program_scaler(dc, pipe_ctx); + + program_blender(dc, pipe_ctx); + + mi->funcs->mem_input_program_surface_config( + mi, + surface->public.format, + &surface->public.tiling_info, + &surface->public.plane_size, + surface->public.rotation, + NULL, + false); + + if (dc->public.config.gpu_vm_support) + mi->funcs->mem_input_program_pte_vm( + pipe_ctx->mi, + surface->public.format, + &surface->public.tiling_info, + surface->public.rotation); +} + +static void update_plane_addr(const struct core_dc *dc, + struct pipe_ctx *pipe_ctx) +{ + struct core_surface *surface = pipe_ctx->surface; + + if (surface == NULL) + return; + + pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( + pipe_ctx->mi, + &surface->public.address, + surface->public.flip_immediate); + + surface->status.requested_address = surface->public.address; + + if (surface->public.visible) + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false); +} + +void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) +{ + struct core_surface *surface = pipe_ctx->surface; + + if (surface == NULL) + return; + + surface->status.is_flip_pending = + pipe_ctx->mi->funcs->mem_input_is_flip_pending( + pipe_ctx->mi); + + if (surface->status.is_flip_pending && !surface->public.visible) + pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; + + surface->status.current_address = pipe_ctx->mi->current_address; +} + +void dce110_power_down(struct core_dc *dc) +{ + power_down_all_hw_blocks(dc); + disable_vga_and_power_gate_all_controllers(dc); +} + +static bool wait_for_reset_trigger_to_occur( + struct dc_context *dc_ctx, + struct timing_generator *tg) +{ + bool rc = false; + + /* To avoid endless loop we wait at most + * frames_to_wait_on_triggered_reset frames for the reset to occur. */ + const uint32_t frames_to_wait_on_triggered_reset = 10; + uint32_t i; + + for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { + + if (!tg->funcs->is_counter_moving(tg)) { + DC_ERROR("TG counter is not moving!\n"); + break; + } + + if (tg->funcs->did_triggered_reset_occur(tg)) { + rc = true; + /* usually occurs at i=1 */ + DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", + i); + break; + } + + /* Wait for one frame. */ + tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); + tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); + } + + if (false == rc) + DC_ERROR("GSL: Timeout on reset trigger!\n"); + + return rc; +} + +/* Enable timing synchronization for a group of Timing Generators. */ +static void dce110_enable_timing_synchronization( + struct core_dc *dc, + int group_index, + int group_size, + struct pipe_ctx *grouped_pipes[]) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dcp_gsl_params gsl_params = { 0 }; + int i; + + DC_SYNC_INFO("GSL: Setting-up...\n"); + + /* Designate a single TG in the group as a master. + * Since HW doesn't care which one, we always assign + * the 1st one in the group. */ + gsl_params.gsl_group = 0; + gsl_params.gsl_master = grouped_pipes[0]->tg->inst; + + for (i = 0; i < group_size; i++) + grouped_pipes[i]->tg->funcs->setup_global_swap_lock( + grouped_pipes[i]->tg, &gsl_params); + + /* Reset slave controllers on master VSync */ + DC_SYNC_INFO("GSL: enabling trigger-reset\n"); + + for (i = 1 /* skip the master */; i < group_size; i++) + grouped_pipes[i]->tg->funcs->enable_reset_trigger( + grouped_pipes[i]->tg, gsl_params.gsl_group); + + + + for (i = 1 /* skip the master */; i < group_size; i++) { + DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->tg); + /* Regardless of success of the wait above, remove the reset or + * the driver will start timing out on Display requests. */ + DC_SYNC_INFO("GSL: disabling trigger-reset.\n"); + grouped_pipes[i]->tg->funcs->disable_reset_trigger(grouped_pipes[i]->tg); + } + + + /* GSL Vblank synchronization is a one time sync mechanism, assumption + * is that the sync'ed displays will not drift out of sync over time*/ + DC_SYNC_INFO("GSL: Restoring register states.\n"); + for (i = 0; i < group_size; i++) + grouped_pipes[i]->tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->tg); + + DC_SYNC_INFO("GSL: Set-up complete.\n"); +} + +static void init_hw(struct core_dc *dc) +{ + int i; + struct dc_bios *bp; + struct transform *xfm; + + bp = dc->ctx->dc_bios; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + xfm = dc->res_pool->transforms[i]; + xfm->funcs->transform_reset(xfm); + + dc->hwss.enable_display_power_gating( + dc, i, bp, + PIPE_GATING_CONTROL_INIT); + dc->hwss.enable_display_power_gating( + dc, i, bp, + PIPE_GATING_CONTROL_DISABLE); + dc->hwss.enable_display_pipe_clock_gating( + dc->ctx, + true); + } + + dce_clock_gating_power_up(dc->hwseq, false);; + /***************************************/ + + for (i = 0; i < dc->link_count; i++) { + /****************************************/ + /* Power up AND update implementation according to the + * required signal (which may be different from the + * default signal on connector). */ + struct core_link *link = dc->links[i]; + link->link_enc->funcs->hw_init(link->link_enc); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + + tg->funcs->disable_vga(tg); + + /* Blank controller using driver code instead of + * command table. */ + tg->funcs->set_blank(tg, true); + } + + for (i = 0; i < dc->res_pool->audio_count; i++) { + struct audio *audio = dc->res_pool->audios[i]; + audio->funcs->hw_init(audio); + } +} + +/* TODO: move this to apply_ctx_tohw some how?*/ +static void dce110_power_on_pipe_if_needed( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + struct dc_bios *dcb = dc->ctx->dc_bios; + struct tg_color black_color = {0}; + + if (!old_pipe_ctx->stream && pipe_ctx->stream) { + dc->hwss.enable_display_power_gating( + dc, + pipe_ctx->pipe_idx, + dcb, PIPE_GATING_CONTROL_DISABLE); + + /* + * This is for powering on underlay, so crtc does not + * need to be enabled + */ + + pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, + &pipe_ctx->stream->public.timing, + false); + + pipe_ctx->tg->funcs->enable_advanced_request( + pipe_ctx->tg, + true, + &pipe_ctx->stream->public.timing); + + pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, + pipe_ctx->stream->public.timing.h_total, + pipe_ctx->stream->public.timing.v_total, + pipe_ctx->stream->public.timing.pix_clk_khz, + context->target_count); + + /* TODO unhardcode*/ + color_space_to_black_color(dc, + COLOR_SPACE_YCBCR601, &black_color); + pipe_ctx->tg->funcs->set_blank_color( + pipe_ctx->tg, + &black_color); + } +} + +static void dce110_increase_watermarks_for_pipe( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + if (did_watermarks_increase(pipe_ctx, context, dc->current_context)) + program_wm_for_pipe(dc, pipe_ctx, context); +} + +static void dce110_set_bandwidth(struct core_dc *dc) +{ + int i; + + for (i = 0; i < dc->current_context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->stream) + continue; + + program_wm_for_pipe(dc, pipe_ctx, dc->current_context); + } + + dc->hwss.set_display_clock(dc->current_context); +} + +static void dce110_program_front_end_for_pipe( + struct core_dc *dc, struct pipe_ctx *pipe_ctx) +{ + struct mem_input *mi = pipe_ctx->mi; + struct pipe_ctx *old_pipe = NULL; + struct core_surface *surface = pipe_ctx->surface; + struct xfm_grph_csc_adjustment adjust; + struct out_csc_color_matrix tbl_entry; + unsigned int i; + + memset(&tbl_entry, 0, sizeof(tbl_entry)); + + if (dc->current_context) + old_pipe = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + + memset(&adjust, 0, sizeof(adjust)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); + + set_default_colors(pipe_ctx); + if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + == true) { + tbl_entry.color_space = + pipe_ctx->stream->public.output_color_space; + + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = + pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + + pipe_ctx->opp->funcs->opp_set_csc_adjustment + (pipe_ctx->opp, &tbl_entry); + } + + if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + adjust.temperature_matrix[0] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[0]; + adjust.temperature_matrix[1] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[1]; + adjust.temperature_matrix[2] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[2]; + adjust.temperature_matrix[3] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[4]; + adjust.temperature_matrix[4] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[5]; + adjust.temperature_matrix[5] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[6]; + adjust.temperature_matrix[6] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[8]; + adjust.temperature_matrix[7] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[9]; + adjust.temperature_matrix[8] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[10]; + } + + pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + + pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + if (old_pipe && memcmp(&old_pipe->scl_data, + &pipe_ctx->scl_data, + sizeof(struct scaler_data)) != 0) + program_scaler(dc, pipe_ctx); + + mi->funcs->mem_input_program_surface_config( + mi, + surface->public.format, + &surface->public.tiling_info, + &surface->public.plane_size, + surface->public.rotation, + false, + false); + + if (dc->public.config.gpu_vm_support) + mi->funcs->mem_input_program_pte_vm( + pipe_ctx->mi, + surface->public.format, + &surface->public.tiling_info, + surface->public.rotation); + + dm_logger_write(dc->ctx->logger, LOG_SURFACE, + "Pipe:%d 0x%x: addr hi:0x%x, " + "addr low:0x%x, " + "src: %d, %d, %d," + " %d; dst: %d, %d, %d, %d;" + "clip: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->surface, + pipe_ctx->surface->public.address.grph.addr.high_part, + pipe_ctx->surface->public.address.grph.addr.low_part, + pipe_ctx->surface->public.src_rect.x, + pipe_ctx->surface->public.src_rect.y, + pipe_ctx->surface->public.src_rect.width, + pipe_ctx->surface->public.src_rect.height, + pipe_ctx->surface->public.dst_rect.x, + pipe_ctx->surface->public.dst_rect.y, + pipe_ctx->surface->public.dst_rect.width, + pipe_ctx->surface->public.dst_rect.height, + pipe_ctx->surface->public.clip_rect.x, + pipe_ctx->surface->public.clip_rect.y, + pipe_ctx->surface->public.clip_rect.width, + pipe_ctx->surface->public.clip_rect.height); + + dm_logger_write(dc->ctx->logger, LOG_SURFACE, + "Pipe %d: width, height, x, y\n" + "viewport:%d, %d, %d, %d\n" + "recout: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->scl_data.viewport.width, + pipe_ctx->scl_data.viewport.height, + pipe_ctx->scl_data.viewport.x, + pipe_ctx->scl_data.viewport.y, + pipe_ctx->scl_data.recout.width, + pipe_ctx->scl_data.recout.height, + pipe_ctx->scl_data.recout.x, + pipe_ctx->scl_data.recout.y); +} + + + +static void dce110_prepare_pipe_for_surface_commit( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) { + struct core_gamma *gamma = NULL; + + dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context); + + if (pipe_ctx->surface->public.gamma_correction) + gamma = DC_GAMMA_TO_CORE( + pipe_ctx->surface->public.gamma_correction); + + dc->hwss.set_gamma_correction( + pipe_ctx->ipp, + pipe_ctx->opp, + gamma, pipe_ctx->surface); +} + +static void dce110_prepare_pipe_for_context( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + dce110_power_on_pipe_if_needed(dc, pipe_ctx, context); + dce110_prepare_pipe_for_surface_commit(dc, pipe_ctx, context); +} + +static void dce110_apply_ctx_for_surface( + struct core_dc *dc, + struct core_surface *surface, + struct validate_context *context) +{ + int i; + + /* TODO remove when removing the surface reset workaroud*/ + if (!surface) + return; + + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->surface != surface) + continue; + + dce110_program_front_end_for_pipe(dc, pipe_ctx); + program_blender(dc, pipe_ctx); + + } + +} + +static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) +{ + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) + if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe) + break; + + if (i == dc->res_pool->pipe_count) + return; + + dc->hwss.enable_display_power_gating( + dc, i, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); + if (pipe->xfm) + pipe->xfm->funcs->transform_reset(pipe->xfm); + memset(&pipe->scl_data, 0, sizeof(struct scaler_data)); +} + +static const struct hw_sequencer_funcs dce110_funcs = { + .init_hw = init_hw, + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .prepare_pipe_for_context = dce110_prepare_pipe_for_context, + .apply_ctx_for_surface = dce110_apply_ctx_for_surface, + .set_plane_config = set_plane_config, + .update_plane_addr = update_plane_addr, + .update_pending_status = dce110_update_pending_status, + .set_gamma_correction = set_gamma_ramp, + .power_down = dce110_power_down, + .enable_accelerated_mode = dce110_enable_accelerated_mode, + .enable_timing_synchronization = dce110_enable_timing_synchronization, + .update_info_frame = dce110_update_info_frame, + .enable_stream = dce110_enable_stream, + .disable_stream = dce110_disable_stream, + .unblank_stream = dce110_unblank_stream, + .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, + .enable_display_power_gating = dce110_enable_display_power_gating, + .power_down_front_end = dce110_power_down_fe, + .pipe_control_lock = dce_pipe_control_lock, + .set_display_clock = dce110_set_display_clock, + .set_displaymarks = dce110_set_displaymarks, + .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe, + .set_bandwidth = dce110_set_bandwidth, + .set_drr = set_drr, + .set_static_screen_control = set_static_screen_control, + .reset_hw_ctx_wrap = reset_hw_ctx_wrap, + .prog_pixclk_crtc_otg = prog_pixclk_crtc_otg, +}; + +bool dce110_hw_sequencer_construct(struct core_dc *dc) +{ + dc->hwss = dce110_funcs; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h new file mode 100644 index 000000000000..a6b4d0d2429f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -0,0 +1,62 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE110_H__ +#define __DC_HWSS_DCE110_H__ + +#include "core_types.h" + +#define GAMMA_HW_POINTS_NUM 256 +struct core_dc; + +bool dce110_hw_sequencer_construct(struct core_dc *dc); + +enum dc_status dce110_apply_ctx_to_hw( + struct core_dc *dc, + struct validate_context *context); + +void dce110_set_display_clock(struct validate_context *context); + +void dce110_set_displaymarks( + const struct core_dc *dc, + struct validate_context *context); + +void dce110_enable_stream(struct pipe_ctx *pipe_ctx); + +void dce110_disable_stream(struct pipe_ctx *pipe_ctx); + +void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, + struct dc_link_settings *link_settings); + +void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); + +void dce110_enable_accelerated_mode(struct core_dc *dc); + +void dce110_power_down(struct core_dc *dc); + +void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); + +#endif /* __DC_HWSS_DCE110_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c new file mode 100644 index 000000000000..dd69f6060bb9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c @@ -0,0 +1,62 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" + +static const struct ipp_funcs funcs = { + .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce110_ipp_cursor_set_position, + .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_set_degamma = dce110_ipp_set_degamma, +}; + +bool dce110_ipp_construct( + struct dce110_ipp* ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + ipp->base.ctx = ctx; + + ipp->base.inst = inst; + + ipp->offsets = *offset; + + ipp->base.funcs = &funcs; + + return true; +} + +void dce110_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE110_IPP(*ipp)); + *ipp = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h new file mode 100644 index 000000000000..60eebdecfa10 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -0,0 +1,76 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_IPP_DCE110_H__ +#define __DC_IPP_DCE110_H__ + +#include "ipp.h" + +struct gamma_parameters; +struct dev_c_lut; + +#define TO_DCE110_IPP(input_pixel_processor)\ + container_of(input_pixel_processor, struct dce110_ipp, base) + +struct dce110_ipp_reg_offsets { + uint32_t dcp_offset; +}; + +struct dce110_ipp { + struct input_pixel_processor base; + struct dce110_ipp_reg_offsets offsets; +}; + +bool dce110_ipp_construct( + struct dce110_ipp* ipp, + struct dc_context *ctx, + enum controller_id id, + const struct dce110_ipp_reg_offsets *offset); + +void dce110_ipp_destroy(struct input_pixel_processor **ipp); + +/* CURSOR RELATED */ +void dce110_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position); + +bool dce110_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes); + +/* DEGAMMA RELATED */ +bool dce110_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode); + +void dce110_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params); +/* + * Helper functions to be resused in other ASICs + */ +void dce110_helper_select_lut(struct dce110_ipp *ipp110); + +#endif /*__DC_IPP_DCE110_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c new file mode 100644 index 000000000000..95f6ca3ba5df --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c @@ -0,0 +1,253 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" + +#define CURSOR_COLOR_BLACK 0x00000000 +#define CURSOR_COLOR_WHITE 0xFFFFFFFF + +#define DCP_REG(reg)\ + (reg + ipp110->offsets.dcp_offset) + +static void enable( + struct dce110_ipp *ipp110, + bool enable); + +static void lock( + struct dce110_ipp *ipp110, + bool enable); + +static void program_position( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y); + +static bool program_control( + struct dce110_ipp *ipp110, + enum dc_cursor_color_format color_format, + bool enable_magnification, + bool inverse_transparent_clamping); + +static void program_hotspot( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y); + +static void program_size( + struct dce110_ipp *ipp110, + uint32_t width, + uint32_t height); + +static void program_address( + struct dce110_ipp *ipp110, + PHYSICAL_ADDRESS_LOC address); + +void dce110_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* lock cursor registers */ + lock(ipp110, true); + + /* Flag passed in structure differentiates cursor enable/disable. */ + /* Update if it differs from cached state. */ + enable(ipp110, position->enable); + + program_position(ipp110, position->x, position->y); + + if (position->hot_spot_enable) + program_hotspot( + ipp110, + position->x_hotspot, + position->y_hotspot); + + /* unlock cursor registers */ + lock(ipp110, false); +} + +bool dce110_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + /* Lock cursor registers */ + lock(ipp110, true); + + /* Program cursor control */ + program_control( + ipp110, + attributes->color_format, + attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, + attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); + + /* Program hot spot coordinates */ + program_hotspot(ipp110, attributes->x_hot, attributes->y_hot); + + /* + * Program cursor size -- NOTE: HW spec specifies that HW register + * stores size as (height - 1, width - 1) + */ + program_size(ipp110, attributes->width-1, attributes->height-1); + + /* Program cursor surface address */ + program_address(ipp110, attributes->address); + + /* Unlock Cursor registers. */ + lock(ipp110, false); + + return true; +} + +static void enable( + struct dce110_ipp *ipp110, bool enable) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_CONTROL); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, enable, CUR_CONTROL, CURSOR_EN); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void lock( + struct dce110_ipp *ipp110, bool lock) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_UPDATE); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, lock, CUR_UPDATE, CURSOR_UPDATE_LOCK); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_position( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_POSITION); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, x, CUR_POSITION, CURSOR_X_POSITION); + set_reg_field_value(value, y, CUR_POSITION, CURSOR_Y_POSITION); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static bool program_control( + struct dce110_ipp *ipp110, + enum dc_cursor_color_format color_format, + bool enable_magnification, + bool inverse_transparent_clamping) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_CONTROL); + uint32_t mode = 0; + + switch (color_format) { + case CURSOR_MODE_MONO: + mode = 0; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + mode = 1; + break; + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + mode = 2; + break; + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + mode = 3; + break; + default: + return false; + } + + set_reg_field_value(value, mode, CUR_CONTROL, CURSOR_MODE); + set_reg_field_value(value, enable_magnification, + CUR_CONTROL, CURSOR_2X_MAGNIFY); + set_reg_field_value(value, inverse_transparent_clamping, + CUR_CONTROL, CUR_INV_TRANS_CLAMP); + dm_write_reg(ipp110->base.ctx, addr, value); + + if (color_format == CURSOR_MODE_MONO) { + addr = DCP_REG(mmCUR_COLOR1); + dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_BLACK); + addr = DCP_REG(mmCUR_COLOR2); + dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_WHITE); + } + return true; +} + +static void program_hotspot( + struct dce110_ipp *ipp110, + uint32_t x, + uint32_t y) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_HOT_SPOT); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, x, CUR_HOT_SPOT, CURSOR_HOT_SPOT_X); + set_reg_field_value(value, y, CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_size( + struct dce110_ipp *ipp110, + uint32_t width, + uint32_t height) +{ + uint32_t value = 0; + uint32_t addr = DCP_REG(mmCUR_SIZE); + + value = dm_read_reg(ipp110->base.ctx, addr); + set_reg_field_value(value, width, CUR_SIZE, CURSOR_WIDTH); + set_reg_field_value(value, height, CUR_SIZE, CURSOR_HEIGHT); + dm_write_reg(ipp110->base.ctx, addr, value); +} + +static void program_address( + struct dce110_ipp *ipp110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t addr = DCP_REG(mmCUR_SURFACE_ADDRESS_HIGH); + /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor + * surface base address in byte. It is 4K byte aligned. + * The correct way to program cursor surface address is to first write + * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS */ + + dm_write_reg(ipp110->base.ctx, addr, address.high_part); + + addr = DCP_REG(mmCUR_SURFACE_ADDRESS); + dm_write_reg(ipp110->base.ctx, addr, address.low_part); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c new file mode 100644 index 000000000000..79a6a6dd72fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c @@ -0,0 +1,303 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" +#include "include/fixed31_32.h" +#include "basics/conversion.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_ipp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + ipp110->offsets.dcp_offset) + +enum { + MAX_INPUT_LUT_ENTRY = 256 +}; + +/*PROTOTYPE DECLARATIONS*/ +static void set_lut_inc( + struct dce110_ipp *ipp110, + uint8_t inc, + bool is_float, + bool is_signed); + +bool dce110_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + uint32_t value = 0; + + uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; + + ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || + mode == IPP_DEGAMMA_MODE_HW_sRGB); + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + GRPH_DEGAMMA_MODE); + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + CURSOR_DEGAMMA_MODE); + + set_reg_field_value( + value, + degamma_type, + DEGAMMA_CONTROL, + CURSOR2_DEGAMMA_MODE); + + dm_write_reg(ipp110->base.ctx, DCP_REG(mmDEGAMMA_CONTROL), value); + + return true; +} + +void dce110_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + uint32_t prescale_control = 0; + uint32_t prescale_value = 0; + uint32_t legacy_lut_control = 0; + + prescale_control = dm_read_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_GRPH_CONTROL)); + + if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + + set_reg_field_value( + prescale_control, + 0, + PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS); + + /* + * If prescale is in use, then legacy lut should + * be bypassed + */ + legacy_lut_control = dm_read_reg(ipp110->base.ctx, + DCP_REG(mmINPUT_GAMMA_CONTROL)); + + set_reg_field_value( + legacy_lut_control, + 1, + INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmINPUT_GAMMA_CONTROL), + legacy_lut_control); + } else { + set_reg_field_value( + prescale_control, + 1, + PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS); + } + + set_reg_field_value( + prescale_value, + params->scale, + PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_SCALE_R); + + set_reg_field_value( + prescale_value, + params->bias, + PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_BIAS_R); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_GRPH_CONTROL), + prescale_control); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_R), + prescale_value); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_G), + prescale_value); + + dm_write_reg(ipp110->base.ctx, + DCP_REG(mmPRESCALE_VALUES_GRPH_B), + prescale_value); +} + +static void set_lut_inc( + struct dce110_ipp *ipp110, + uint8_t inc, + bool is_float, + bool is_signed) +{ + const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); + + uint32_t value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_R); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_G); + + set_reg_field_value( + value, + inc, + DC_LUT_CONTROL, + DC_LUT_INC_B); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_R_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_G_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_float, + DC_LUT_CONTROL, + DC_LUT_DATA_B_FLOAT_POINT_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_R_SIGNED_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_G_SIGNED_EN); + + set_reg_field_value( + value, + is_signed, + DC_LUT_CONTROL, + DC_LUT_DATA_B_SIGNED_EN); + + dm_write_reg(ipp110->base.ctx, addr, value); +} + +void dce110_helper_select_lut(struct dce110_ipp *ipp110) +{ + uint32_t value = 0; + + set_lut_inc(ipp110, 0, false, false); + + { + const uint32_t addr = DCP_REG(mmDC_LUT_WRITE_EN_MASK); + + value = dm_read_reg(ipp110->base.ctx, addr); + + /* enable all */ + set_reg_field_value( + value, + 0x7, + DC_LUT_WRITE_EN_MASK, + DC_LUT_WRITE_EN_MASK); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE); + + value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + 0, + DC_LUT_RW_MODE, + DC_LUT_RW_MODE); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); + + value = dm_read_reg(ipp110->base.ctx, addr); + + /* 00 - new u0.12 */ + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_R_FORMAT); + + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_G_FORMAT); + + set_reg_field_value( + value, + 3, + DC_LUT_CONTROL, + DC_LUT_DATA_B_FORMAT); + + dm_write_reg(ipp110->base.ctx, addr, value); + } + + { + const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX); + + value = dm_read_reg(ipp110->base.ctx, addr); + + set_reg_field_value( + value, + 0, + DC_LUT_RW_INDEX, + DC_LUT_RW_INDEX); + + dm_write_reg(ipp110->base.ctx, addr, value); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c new file mode 100644 index 000000000000..c0a68c6f585e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -0,0 +1,535 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +/* TODO: this needs to be looked at, used by Stella's workaround*/ +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" + +#include "include/logger_interface.h" + +#include "dce110_mem_input.h" + +#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) +#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) +#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) + +static void program_sec_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp; + + /*high register MUST be programmed first*/ + temp = address.high_part & + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; + set_reg_field_value(value, temp, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH), value); + + value = 0; + temp = address.low_part >> + GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; + set_reg_field_value(value, temp, + GRPH_SECONDARY_SURFACE_ADDRESS, + GRPH_SECONDARY_SURFACE_ADDRESS); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS), value); +} + +static void program_pri_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp; + + /*high register MUST be programmed first*/ + temp = address.high_part & + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; + set_reg_field_value(value, temp, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH), value); + + value = 0; + temp = address.low_part >> + GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; + set_reg_field_value(value, temp, + GRPH_PRIMARY_SURFACE_ADDRESS, + GRPH_PRIMARY_SURFACE_ADDRESS); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS), value); +} + +bool dce110_mem_input_is_flip_pending(struct mem_input *mem_input) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + uint32_t value; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); + + if (get_reg_field_value(value, GRPH_UPDATE, + GRPH_SURFACE_UPDATE_PENDING)) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +bool dce110_mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + uint32_t value = 0; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL)); + if (flip_immediate) { + set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); + set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); + } else { + set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); + set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); + } + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value); + + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) + break; + program_pri_addr(mem_input110, address->grph.addr); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0 + || address->grph_stereo.right_addr.quad_part == 0) + break; + program_pri_addr(mem_input110, address->grph_stereo.left_addr); + program_sec_addr(mem_input110, address->grph_stereo.right_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + break; + } + + mem_input->request_address = *address; + if (flip_immediate) + mem_input->current_address = *address; + + return true; +} + +/* Scatter Gather param tables */ +static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = { + { 8, 64, 64, 8, 8, 1, 4, 0, 0}, + { 16, 64, 32, 8, 16, 1, 8, 0, 0}, + { 32, 32, 32, 16, 16, 1, 8, 0, 0}, + { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ +}; + +static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = { + { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ + { 16, 256, 8, 2, 0, 1, 0, 0, 0}, + { 32, 128, 8, 4, 0, 1, 0, 0, 0}, + { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ +}; + +static const unsigned int dvmm_Hw_Setting_Linear[4][9] = { + { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, + { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, + { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, + { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ +}; + +/* Helper to get table entry from surface info */ +static const unsigned int *get_dvmm_hw_setting( + union dc_tiling_info *tiling_info, + enum surface_pixel_format format) +{ + enum bits_per_pixel { + bpp_8 = 0, + bpp_16, + bpp_32, + bpp_64 + } bpp; + + if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) + bpp = bpp_64; + else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) + bpp = bpp_32; + else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555) + bpp = bpp_16; + else + bpp = bpp_8; + + switch (tiling_info->gfx8.array_mode) { + case DC_ARRAY_1D_TILED_THIN1: + case DC_ARRAY_1D_TILED_THICK: + case DC_ARRAY_PRT_TILED_THIN1: + return dvmm_Hw_Setting_1DTiling[bpp]; + case DC_ARRAY_2D_TILED_THIN1: + case DC_ARRAY_2D_TILED_THICK: + case DC_ARRAY_2D_TILED_X_THICK: + case DC_ARRAY_PRT_2D_TILED_THIN1: + case DC_ARRAY_PRT_2D_TILED_THICK: + return dvmm_Hw_Setting_2DTiling[bpp]; + case DC_ARRAY_LINEAR_GENERAL: + case DC_ARRAY_LINEAR_ALLIGNED: + return dvmm_Hw_Setting_Linear[bpp]; + default: + return dvmm_Hw_Setting_2DTiling[bpp]; + } +} + +bool dce110_mem_input_program_pte_vm( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format); + + unsigned int page_width = 0; + unsigned int page_height = 0; + unsigned int temp_page_width = pte[1]; + unsigned int temp_page_height = pte[2]; + unsigned int min_pte_before_flip = 0; + uint32_t value = 0; + + while ((temp_page_width >>= 1) != 0) + page_width++; + while ((temp_page_height >>= 1) != 0) + page_height++; + + switch (rotation) { + case ROTATION_ANGLE_90: + case ROTATION_ANGLE_270: + min_pte_before_flip = pte[4]; + break; + default: + min_pte_before_flip = pte[3]; + break; + } + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT)); + set_reg_field_value(value, 0xff, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL)); + set_reg_field_value(value, page_width, DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); + set_reg_field_value(value, page_height, DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); + set_reg_field_value(value, min_pte_before_flip, DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL)); + set_reg_field_value(value, pte[5], DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); + set_reg_field_value(value, 0xff, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL), value); + + return true; +} + +static void program_urgency_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + /* register value */ + uint32_t urgency_cntl = 0; + uint32_t wm_mask_cntl = 0; + + uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL; + uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + + /*Write mask to enable reading/writing of watermark set A*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value( + urgency_cntl, + marks_low.d_mark, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value( + urgency_cntl, + total_dest_line_time_ns, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + dm_write_reg(ctx, urgency_addr, urgency_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPG_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value(urgency_cntl, + marks_low.a_mark, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value(urgency_cntl, + total_dest_line_time_ns, + DPG_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + dm_write_reg(ctx, urgency_addr, urgency_cntl); +} + +static void program_stutter_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks) +{ + /* register value */ + uint32_t stutter_cntl = 0; + uint32_t wm_mask_cntl = 0; + + uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL; + uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + + /*Write mask to enable reading/writing of watermark set A*/ + + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + + if (ctx->dc->debug.disable_stutter) { + set_reg_field_value(stutter_cntl, + 0, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + } else { + set_reg_field_value(stutter_cntl, + 1, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + } + + set_reg_field_value(stutter_cntl, + 1, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_IGNORE_FBC); + + /*Write watermark set A*/ + set_reg_field_value(stutter_cntl, + marks.d_mark, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPG_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + + /*Write watermark set B*/ + set_reg_field_value(stutter_cntl, + marks.a_mark, + DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); +} + +static void program_nbp_watermark( + const struct dc_context *ctx, + const uint32_t offset, + struct bw_watermarks marks) +{ + uint32_t value; + uint32_t addr; + /* Write mask to enable reading/writing of watermark set A */ + addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, addr, value); + + addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, addr, value); + + /* Write watermark set A */ + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + marks.d_mark, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, addr, value); + + /* Write mask to enable reading/writing of watermark set B */ + addr = offset + mmDPG_WATERMARK_MASK_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 2, + DPG_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, addr, value); + + addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, addr, value); + + /* Write watermark set B */ + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + marks.a_mark, + DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, addr, value); +} + +void dce110_mem_input_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); + + program_urgency_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + urgent, + total_dest_line_time_ns); + + program_nbp_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + nbp); + + program_stutter_watermark( + mem_input->ctx, + bm_dce110->offsets.dmif, + stutter); +} + +static struct mem_input_funcs dce110_mem_input_funcs = { + .mem_input_program_display_marks = + dce110_mem_input_program_display_marks, + .allocate_mem_input = dce_mem_input_allocate_dmif, + .free_mem_input = dce_mem_input_free_dmif, + .mem_input_program_surface_flip_and_addr = + dce110_mem_input_program_surface_flip_and_addr, + .mem_input_program_pte_vm = + dce110_mem_input_program_pte_vm, + .mem_input_program_surface_config = + dce_mem_input_program_surface_config, + .mem_input_is_flip_pending = + dce110_mem_input_is_flip_pending, + .mem_input_update_dchub = NULL +}; +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce110_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + /* supported stutter method + * STUTTER_MODE_ENHANCED + * STUTTER_MODE_QUAD_DMIF_BUFFER + * STUTTER_MODE_WATERMARK_NBP_STATE + */ + mem_input110->base.funcs = &dce110_mem_input_funcs; + mem_input110->base.ctx = ctx; + + mem_input110->base.inst = inst; + + mem_input110->offsets = *offsets; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h new file mode 100644 index 000000000000..83b2df93ce49 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h @@ -0,0 +1,131 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCE110_H__ +#define __DC_MEM_INPUT_DCE110_H__ + +#include "mem_input.h" + +#define TO_DCE110_MEM_INPUT(mi)\ + container_of(mi, struct dce110_mem_input, base) + +struct dce110_mem_input_reg_offsets { + uint32_t dcp; + uint32_t dmif; + uint32_t pipe; +}; + +struct dce110_mem_input { + struct mem_input base; + struct dce110_mem_input_reg_offsets offsets; +}; + +bool dce110_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + +/* + * dce110_mem_input_program_display_marks + * + * This function will program nbp stutter and urgency watermarks to minimum + * allowable values + */ +void dce110_mem_input_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + +/* + * dce110_allocate_mem_input + * + * This function will allocate a dmif buffer and program required + * pixel duration for pipe + */ +void dce110_allocate_mem_input( + struct mem_input *mem_input, + uint32_t h_total,/* for current stream */ + uint32_t v_total,/* for current stream */ + uint32_t pix_clk_khz,/* for current stream */ + uint32_t total_stream_num); + +/* + * dce110_free_mem_input + * + * This function will deallocate a dmif buffer from pipe + */ +void dce110_free_mem_input( + struct mem_input *mem_input, + uint32_t total_stream_num); + +/* + * dce110_mem_input_program_surface_flip_and_addr + * + * This function programs hsync/vsync mode and surface address + */ +bool dce110_mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + +/* + * dce110_mem_input_program_surface_config + * + * This function will program surface tiling, size, rotation and pixel format + * to corresponding dcp registers. + */ +bool dce110_mem_input_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +/* + * dce110_mem_input_program_pte_vm + * + * This function will program pte vm registers. + */ +bool dce110_mem_input_program_pte_vm( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + +/* + * dce110_mem_input_is_flip_pending + * + * This function will wait until the surface update-pending bit is cleared. + * This is necessary when a flip immediate call is requested as we shouldn't + * return until the flip has actually occurred. + */ +bool dce110_mem_input_is_flip_pending( + struct mem_input *mem_input); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c new file mode 100644 index 000000000000..f0310bab4030 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -0,0 +1,1081 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +/* TODO: this needs to be looked at, used by Stella's workaround*/ +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" + +#include "include/logger_interface.h" +#include "inc/bandwidth_calcs.h" + +#include "dce110_mem_input.h" + +#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) +/*#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif)*/ +/*#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe)*/ + +static const struct dce110_mem_input_reg_offsets dce110_mi_v_reg_offsets[] = { + { + .dcp = 0, + .dmif = 0, + .pipe = 0, + } +}; + +static void set_flip_control( + struct dce110_mem_input *mem_input110, + bool immediate) +{ + uint32_t value = 0; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_FLIP_CONTROL)); + + set_reg_field_value(value, 1, + UNP_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_PENDING_MODE); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_FLIP_CONTROL), + value); +} + +/* chroma part */ +static void program_pri_addr_c( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp = 0; + /*high register MUST be programmed first*/ + temp = address.high_part & +UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MASK; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C), + value); + + temp = 0; + value = 0; + temp = address.low_part >> + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C__SHIFT; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C, + GRPH_PRIMARY_SURFACE_ADDRESS_C); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C), + value); +} + +/* luma part */ +static void program_pri_addr_l( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t value = 0; + uint32_t temp = 0; + + /*high register MUST be programmed first*/ + temp = address.high_part & +UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L), + value); + + temp = 0; + value = 0; + temp = address.low_part >> + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT; + + set_reg_field_value(value, temp, + UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, + GRPH_PRIMARY_SURFACE_ADDRESS_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L), + value); +} + +static void program_addr( + struct dce110_mem_input *mem_input110, + const struct dc_plane_address *addr) +{ + switch (addr->type) { + case PLN_ADDR_TYPE_GRAPHICS: + program_pri_addr_l( + mem_input110, + addr->grph.addr); + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + program_pri_addr_l( + mem_input110, + addr->video_progressive.luma_addr); + program_pri_addr_c( + mem_input110, + addr->video_progressive.chroma_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + } +} + +static void enable(struct dce110_mem_input *mem_input110) +{ + uint32_t value = 0; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_ENABLE)); + set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE); + dm_write_reg(mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_ENABLE), + value); +} + +static void program_tiling( + struct dce110_mem_input *mem_input110, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format) +{ + uint32_t value = 0; + + set_reg_field_value(value, info->gfx8.num_banks, + UNP_GRPH_CONTROL, GRPH_NUM_BANKS); + + set_reg_field_value(value, info->gfx8.bank_width, + UNP_GRPH_CONTROL, GRPH_BANK_WIDTH_L); + + set_reg_field_value(value, info->gfx8.bank_height, + UNP_GRPH_CONTROL, GRPH_BANK_HEIGHT_L); + + set_reg_field_value(value, info->gfx8.tile_aspect, + UNP_GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT_L); + + set_reg_field_value(value, info->gfx8.tile_split, + UNP_GRPH_CONTROL, GRPH_TILE_SPLIT_L); + + set_reg_field_value(value, info->gfx8.tile_mode, + UNP_GRPH_CONTROL, GRPH_MICRO_TILE_MODE_L); + + set_reg_field_value(value, info->gfx8.pipe_config, + UNP_GRPH_CONTROL, GRPH_PIPE_CONFIG); + + set_reg_field_value(value, info->gfx8.array_mode, + UNP_GRPH_CONTROL, GRPH_ARRAY_MODE); + + set_reg_field_value(value, 1, + UNP_GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE); + + set_reg_field_value(value, 0, + UNP_GRPH_CONTROL, GRPH_Z); + + dm_write_reg( + mem_input110->base.ctx, + mmUNP_GRPH_CONTROL, + value); + + value = 0; + + set_reg_field_value(value, info->gfx8.bank_width_c, + UNP_GRPH_CONTROL_C, GRPH_BANK_WIDTH_C); + + set_reg_field_value(value, info->gfx8.bank_height_c, + UNP_GRPH_CONTROL_C, GRPH_BANK_HEIGHT_C); + + set_reg_field_value(value, info->gfx8.tile_aspect_c, + UNP_GRPH_CONTROL_C, GRPH_MACRO_TILE_ASPECT_C); + + set_reg_field_value(value, info->gfx8.tile_split_c, + UNP_GRPH_CONTROL_C, GRPH_TILE_SPLIT_C); + + set_reg_field_value(value, info->gfx8.tile_mode_c, + UNP_GRPH_CONTROL_C, GRPH_MICRO_TILE_MODE_C); + + dm_write_reg( + mem_input110->base.ctx, + mmUNP_GRPH_CONTROL_C, + value); +} + +static void program_size_and_rotation( + struct dce110_mem_input *mem_input110, + enum dc_rotation_angle rotation, + const union plane_size *plane_size) +{ + uint32_t value = 0; + union plane_size local_size = *plane_size; + + if (rotation == ROTATION_ANGLE_90 || + rotation == ROTATION_ANGLE_270) { + + uint32_t swap; + swap = local_size.video.luma_size.x; + local_size.video.luma_size.x = + local_size.video.luma_size.y; + local_size.video.luma_size.y = swap; + + swap = local_size.video.luma_size.width; + local_size.video.luma_size.width = + local_size.video.luma_size.height; + local_size.video.luma_size.height = swap; + + swap = local_size.video.chroma_size.x; + local_size.video.chroma_size.x = + local_size.video.chroma_size.y; + local_size.video.chroma_size.y = swap; + + swap = local_size.video.chroma_size.width; + local_size.video.chroma_size.width = + local_size.video.chroma_size.height; + local_size.video.chroma_size.height = swap; + } + + value = 0; + set_reg_field_value(value, local_size.video.luma_pitch, + UNP_GRPH_PITCH_L, GRPH_PITCH_L); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PITCH_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_pitch, + UNP_GRPH_PITCH_C, GRPH_PITCH_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_PITCH_C), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_X_START_L, GRPH_X_START_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_START_L), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_X_START_C, GRPH_X_START_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_START_C), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_Y_START_L, GRPH_Y_START_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_START_L), + value); + + value = 0; + set_reg_field_value(value, 0, + UNP_GRPH_Y_START_C, GRPH_Y_START_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_START_C), + value); + + value = 0; + set_reg_field_value(value, local_size.video.luma_size.x + + local_size.video.luma_size.width, + UNP_GRPH_X_END_L, GRPH_X_END_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_END_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_size.x + + local_size.video.chroma_size.width, + UNP_GRPH_X_END_C, GRPH_X_END_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_X_END_C), + value); + + value = 0; + set_reg_field_value(value, local_size.video.luma_size.y + + local_size.video.luma_size.height, + UNP_GRPH_Y_END_L, GRPH_Y_END_L); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_END_L), + value); + + value = 0; + set_reg_field_value(value, local_size.video.chroma_size.y + + local_size.video.chroma_size.height, + UNP_GRPH_Y_END_C, GRPH_Y_END_C); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_Y_END_C), + value); + + value = 0; + switch (rotation) { + case ROTATION_ANGLE_90: + set_reg_field_value(value, 3, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + case ROTATION_ANGLE_180: + set_reg_field_value(value, 2, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + case ROTATION_ANGLE_270: + set_reg_field_value(value, 1, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + default: + set_reg_field_value(value, 0, + UNP_HW_ROTATION, ROTATION_ANGLE); + break; + } + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_HW_ROTATION), + value); +} + +static void program_pixel_format( + struct dce110_mem_input *mem_input110, + enum surface_pixel_format format) +{ + if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + uint32_t value; + uint8_t grph_depth; + uint8_t grph_format; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL)); + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: + grph_depth = 0; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + grph_depth = 1; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + grph_depth = 2; + grph_format = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + grph_depth = 2; + grph_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + grph_depth = 3; + grph_format = 0; + break; + default: + grph_depth = 2; + grph_format = 0; + break; + } + + set_reg_field_value( + value, + grph_depth, + UNP_GRPH_CONTROL, + GRPH_DEPTH); + set_reg_field_value( + value, + grph_format, + UNP_GRPH_CONTROL, + GRPH_FORMAT); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL), + value); + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + + /* VIDEO FORMAT 0 */ + set_reg_field_value( + value, + 0, + UNP_GRPH_CONTROL_EXP, + VIDEO_FORMAT); + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP), + value); + + } else { + /* Video 422 and 420 needs UNP_GRPH_CONTROL_EXP programmed */ + uint32_t value; + uint8_t video_format; + + value = dm_read_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + + switch (format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + video_format = 2; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + video_format = 3; + break; + default: + video_format = 0; + break; + } + + set_reg_field_value( + value, + video_format, + UNP_GRPH_CONTROL_EXP, + VIDEO_FORMAT); + + dm_write_reg( + mem_input110->base.ctx, + DCP_REG(mmUNP_GRPH_CONTROL_EXP), + value); + } +} + +bool dce110_mem_input_v_is_surface_pending(struct mem_input *mem_input) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + uint32_t value; + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_UPDATE)); + + if (get_reg_field_value(value, UNP_GRPH_UPDATE, + GRPH_SURFACE_UPDATE_PENDING)) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +bool dce110_mem_input_v_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + set_flip_control(mem_input110, flip_immediate); + program_addr(mem_input110, + address); + + mem_input->request_address = *address; + + return true; +} + +/* Scatter Gather param tables */ +static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = { + { 8, 64, 64, 8, 8, 1, 4, 0, 0}, + { 16, 64, 32, 8, 16, 1, 8, 0, 0}, + { 32, 32, 32, 16, 16, 1, 8, 0, 0}, + { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ +}; + +static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = { + { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ + { 16, 256, 8, 2, 0, 1, 0, 0, 0}, + { 32, 128, 8, 4, 0, 1, 0, 0, 0}, + { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ +}; + +static const unsigned int dvmm_Hw_Setting_Linear[4][9] = { + { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, + { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, + { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, + { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ +}; + +/* Helper to get table entry from surface info */ +static const unsigned int *get_dvmm_hw_setting( + union dc_tiling_info *tiling_info, + enum surface_pixel_format format, + bool chroma) +{ + enum bits_per_pixel { + bpp_8 = 0, + bpp_16, + bpp_32, + bpp_64 + } bpp; + + if (format >= SURFACE_PIXEL_FORMAT_INVALID) + bpp = bpp_32; + else if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + bpp = chroma ? bpp_16 : bpp_8; + else + bpp = bpp_8; + + switch (tiling_info->gfx8.array_mode) { + case DC_ARRAY_1D_TILED_THIN1: + case DC_ARRAY_1D_TILED_THICK: + case DC_ARRAY_PRT_TILED_THIN1: + return dvmm_Hw_Setting_1DTiling[bpp]; + case DC_ARRAY_2D_TILED_THIN1: + case DC_ARRAY_2D_TILED_THICK: + case DC_ARRAY_2D_TILED_X_THICK: + case DC_ARRAY_PRT_2D_TILED_THIN1: + case DC_ARRAY_PRT_2D_TILED_THICK: + return dvmm_Hw_Setting_2DTiling[bpp]; + case DC_ARRAY_LINEAR_GENERAL: + case DC_ARRAY_LINEAR_ALLIGNED: + return dvmm_Hw_Setting_Linear[bpp]; + default: + return dvmm_Hw_Setting_2DTiling[bpp]; + } +} + +bool dce110_mem_input_v_program_pte_vm( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format, false); + const unsigned int *pte_chroma = get_dvmm_hw_setting(tiling_info, format, true); + + unsigned int page_width = 0; + unsigned int page_height = 0; + unsigned int page_width_chroma = 0; + unsigned int page_height_chroma = 0; + unsigned int temp_page_width = pte[1]; + unsigned int temp_page_height = pte[2]; + unsigned int min_pte_before_flip = 0; + unsigned int min_pte_before_flip_chroma = 0; + uint32_t value = 0; + + while ((temp_page_width >>= 1) != 0) + page_width++; + while ((temp_page_height >>= 1) != 0) + page_height++; + + temp_page_width = pte_chroma[1]; + temp_page_height = pte_chroma[2]; + while ((temp_page_width >>= 1) != 0) + page_width_chroma++; + while ((temp_page_height >>= 1) != 0) + page_height_chroma++; + + switch (rotation) { + case ROTATION_ANGLE_90: + case ROTATION_ANGLE_270: + min_pte_before_flip = pte[4]; + min_pte_before_flip_chroma = pte_chroma[4]; + break; + default: + min_pte_before_flip = pte[3]; + min_pte_before_flip_chroma = pte_chroma[3]; + break; + } + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT)); + /* TODO: un-hardcode requestlimit */ + set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L); + set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL)); + set_reg_field_value(value, page_width, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); + set_reg_field_value(value, page_height, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); + set_reg_field_value(value, min_pte_before_flip, UNP_DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL)); + set_reg_field_value(value, pte[5], UNP_DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); + set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C)); + set_reg_field_value(value, page_width_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_WIDTH_C); + set_reg_field_value(value, page_height_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_HEIGHT_C); + set_reg_field_value(value, min_pte_before_flip_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_MIN_PTE_BEFORE_FLIP_C); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C), value); + + value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C)); + set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C); + set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C), value); + + return true; +} + +bool dce110_mem_input_v_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizotal_mirror) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + enable(mem_input110); + program_tiling(mem_input110, tiling_info, format); + program_size_and_rotation(mem_input110, rotation, plane_size); + program_pixel_format(mem_input110, format); + + return true; +} + +static void program_urgency_watermark( + const struct dc_context *ctx, + const uint32_t urgency_addr, + const uint32_t wm_addr, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + /* register value */ + uint32_t urgency_cntl = 0; + uint32_t wm_mask_cntl = 0; + + /*Write mask to enable reading/writing of watermark set A*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPGV0_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value( + urgency_cntl, + marks_low.a_mark, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value( + urgency_cntl, + total_dest_line_time_ns, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + dm_write_reg(ctx, urgency_addr, urgency_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPGV0_WATERMARK_MASK_CONTROL, + URGENCY_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + urgency_cntl = dm_read_reg(ctx, urgency_addr); + + set_reg_field_value(urgency_cntl, + marks_low.b_mark, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_LOW_WATERMARK); + + set_reg_field_value(urgency_cntl, + total_dest_line_time_ns, + DPGV0_PIPE_URGENCY_CONTROL, + URGENCY_HIGH_WATERMARK); + + dm_write_reg(ctx, urgency_addr, urgency_cntl); +} + +static void program_urgency_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark( + ctx, + mmDPGV0_PIPE_URGENCY_CONTROL, + mmDPGV0_WATERMARK_MASK_CONTROL, + marks_low, + total_dest_line_time_ns); +} + +static void program_urgency_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks_low, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark( + ctx, + mmDPGV1_PIPE_URGENCY_CONTROL, + mmDPGV1_WATERMARK_MASK_CONTROL, + marks_low, + total_dest_line_time_ns); +} + +static void program_stutter_watermark( + const struct dc_context *ctx, + const uint32_t stutter_addr, + const uint32_t wm_addr, + struct bw_watermarks marks) +{ + /* register value */ + uint32_t stutter_cntl = 0; + uint32_t wm_mask_cntl = 0; + + /*Write mask to enable reading/writing of watermark set A*/ + + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 1, + DPGV0_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + + if (ctx->dc->debug.disable_stutter) { + set_reg_field_value(stutter_cntl, + 0, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + } else { + set_reg_field_value(stutter_cntl, + 1, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE); + } + + set_reg_field_value(stutter_cntl, + 1, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_IGNORE_FBC); + + /*Write watermark set A*/ + set_reg_field_value(stutter_cntl, + marks.a_mark, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); + + /*Write mask to enable reading/writing of watermark set B*/ + wm_mask_cntl = dm_read_reg(ctx, wm_addr); + set_reg_field_value(wm_mask_cntl, + 2, + DPGV0_WATERMARK_MASK_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); + dm_write_reg(ctx, wm_addr, wm_mask_cntl); + + stutter_cntl = dm_read_reg(ctx, stutter_addr); + /*Write watermark set B*/ + set_reg_field_value(stutter_cntl, + marks.b_mark, + DPGV0_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK); + dm_write_reg(ctx, stutter_addr, stutter_cntl); +} + +static void program_stutter_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_stutter_watermark(ctx, + mmDPGV0_PIPE_STUTTER_CONTROL, + mmDPGV0_WATERMARK_MASK_CONTROL, + marks); +} + +static void program_stutter_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_stutter_watermark(ctx, + mmDPGV1_PIPE_STUTTER_CONTROL, + mmDPGV1_WATERMARK_MASK_CONTROL, + marks); +} + +static void program_nbp_watermark( + const struct dc_context *ctx, + const uint32_t wm_mask_ctrl_addr, + const uint32_t nbp_pstate_ctrl_addr, + struct bw_watermarks marks) +{ + uint32_t value; + + /* Write mask to enable reading/writing of watermark set A */ + + value = dm_read_reg(ctx, wm_mask_ctrl_addr); + + set_reg_field_value( + value, + 1, + DPGV0_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, wm_mask_ctrl_addr, value); + + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write watermark set A */ + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + marks.a_mark, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write mask to enable reading/writing of watermark set B */ + value = dm_read_reg(ctx, wm_mask_ctrl_addr); + set_reg_field_value( + value, + 2, + DPGV0_WATERMARK_MASK_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK); + dm_write_reg(ctx, wm_mask_ctrl_addr, value); + + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); + + /* Write watermark set B */ + value = dm_read_reg(ctx, nbp_pstate_ctrl_addr); + set_reg_field_value( + value, + marks.b_mark, + DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK); + dm_write_reg(ctx, nbp_pstate_ctrl_addr, value); +} + +static void program_nbp_watermark_l( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_nbp_watermark(ctx, + mmDPGV0_WATERMARK_MASK_CONTROL, + mmDPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL, + marks); +} + +static void program_nbp_watermark_c( + const struct dc_context *ctx, + struct bw_watermarks marks) +{ + program_nbp_watermark(ctx, + mmDPGV1_WATERMARK_MASK_CONTROL, + mmDPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL, + marks); +} + +void dce110_mem_input_v_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark_l( + mem_input->ctx, + urgent, + total_dest_line_time_ns); + + program_nbp_watermark_l( + mem_input->ctx, + nbp); + + program_stutter_watermark_l( + mem_input->ctx, + stutter); + +} + +void dce110_mem_input_program_chroma_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + program_urgency_watermark_c( + mem_input->ctx, + urgent, + total_dest_line_time_ns); + + program_nbp_watermark_c( + mem_input->ctx, + nbp); + + program_stutter_watermark_c( + mem_input->ctx, + stutter); +} + +void dce110_allocate_mem_input_v( + struct mem_input *mi, + uint32_t h_total,/* for current stream */ + uint32_t v_total,/* for current stream */ + uint32_t pix_clk_khz,/* for current stream */ + uint32_t total_stream_num) +{ + uint32_t addr; + uint32_t value; + uint32_t pix_dur; + if (pix_clk_khz != 0) { + addr = mmDPGV0_PIPE_ARBITRATION_CONTROL1; + value = dm_read_reg(mi->ctx, addr); + pix_dur = 1000000000ULL / pix_clk_khz; + set_reg_field_value( + value, + pix_dur, + DPGV0_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION); + dm_write_reg(mi->ctx, addr, value); + + addr = mmDPGV1_PIPE_ARBITRATION_CONTROL1; + value = dm_read_reg(mi->ctx, addr); + pix_dur = 1000000000ULL / pix_clk_khz; + set_reg_field_value( + value, + pix_dur, + DPGV1_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION); + dm_write_reg(mi->ctx, addr, value); + + addr = mmDPGV0_PIPE_ARBITRATION_CONTROL2; + value = 0x4000800; + dm_write_reg(mi->ctx, addr, value); + + addr = mmDPGV1_PIPE_ARBITRATION_CONTROL2; + value = 0x4000800; + dm_write_reg(mi->ctx, addr, value); + } + +} + +void dce110_free_mem_input_v( + struct mem_input *mi, + uint32_t total_stream_num) +{ +} + +static struct mem_input_funcs dce110_mem_input_v_funcs = { + .mem_input_program_display_marks = + dce110_mem_input_v_program_display_marks, + .mem_input_program_chroma_display_marks = + dce110_mem_input_program_chroma_display_marks, + .allocate_mem_input = dce110_allocate_mem_input_v, + .free_mem_input = dce110_free_mem_input_v, + .mem_input_program_surface_flip_and_addr = + dce110_mem_input_v_program_surface_flip_and_addr, + .mem_input_program_pte_vm = + dce110_mem_input_v_program_pte_vm, + .mem_input_program_surface_config = + dce110_mem_input_v_program_surface_config, + .mem_input_is_flip_pending = + dce110_mem_input_v_is_surface_pending +}; +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce110_mem_input_v_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx) +{ + mem_input110->base.funcs = &dce110_mem_input_v_funcs; + mem_input110->base.ctx = ctx; + + mem_input110->base.inst = 0; + + mem_input110->offsets = dce110_mi_v_reg_offsets[0]; + + return true; +} + +#if 0 +void dce110_mem_input_v_destroy(struct mem_input **mem_input) +{ + dm_free(TO_DCE110_MEM_INPUT(*mem_input)); + *mem_input = NULL; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h new file mode 100644 index 000000000000..5b1796ccefc0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h @@ -0,0 +1,94 @@ +/* Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_V_DCE110_H__ +#define __DC_MEM_INPUT_V_DCE110_H__ + +#include "mem_input.h" +#include "dce110_mem_input.h" + +bool dce110_mem_input_v_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx); + +/* + * This function will program nbp stutter and urgency watermarks to minimum + * allowable values + */ +void dce110_mem_input_v_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + +/* + * This function will allocate a dmif buffer and program required + * pixel duration for pipe + */ +void dce110_allocate_mem_v_input( + struct mem_input *mem_input, + uint32_t h_total,/* for current stream */ + uint32_t v_total,/* for current stream */ + uint32_t pix_clk_khz,/* for current stream */ + uint32_t total_stream_num); + +/* + * This function will deallocate a dmif buffer from pipe + */ +void dce110_free_mem_v_input( + struct mem_input *mem_input, + uint32_t total_stream_num); + +/* + * This function programs hsync/vsync mode and surface address + */ +bool dce110_mem_input_v_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + +/* + * dce110_mem_input_v_program_scatter_gather + * + * This function will program scatter gather registers. + */ +bool dce110_mem_input_v_program_pte_vm( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + +/* + * This function will program surface tiling, size, rotation and pixel format + * to corresponding dcp registers. + */ +bool dce110_mem_input_v_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c new file mode 100644 index 000000000000..698ec2f55d0f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c @@ -0,0 +1,77 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" + +#include "gamma_types.h" + +enum { + MAX_LUT_ENTRY = 256, + MAX_NUMBER_OF_ENTRIES = 256 +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static const struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce110_opp_program_fmt, +}; + +bool dce110_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets) +{ + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; + + opp110->base.inst = inst; + + opp110->offsets = *offsets; + + return true; +} + +void dce110_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free(FROM_DCE11_OPP(*opp)); + *opp = NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h new file mode 100644 index 000000000000..2fbb2415cc97 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h @@ -0,0 +1,149 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE110_H__ +#define __DC_OPP_DCE110_H__ + +#include "dc_types.h" +#include "opp.h" +#include "core_types.h" + +#include "gamma_types.h" /* decprecated */ + +struct gamma_parameters; + +#define FROM_DCE11_OPP(opp)\ + container_of(opp, struct dce110_opp, base) + +enum dce110_opp_reg_type { + DCE110_OPP_REG_DCP = 0, + DCE110_OPP_REG_DCFE, + DCE110_OPP_REG_FMT, + + DCE110_OPP_REG_MAX +}; + +struct dce110_regamma { + struct gamma_curve arr_curve_points[16]; + struct curve_points arr_points[3]; + uint32_t hw_points_num; + struct hw_x_point *coordinates_x; + struct pwl_result_data *rgb_resulted; + + /* re-gamma curve */ + struct pwl_float_data_ex *rgb_regamma; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 256 */ + struct pixel_gamma_point *coeff128; + struct pixel_gamma_point *coeff128_oem; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 1025 */ + struct pixel_gamma_point *coeff128_dx; + /* evenly distributed points, gamma 256 software points 0-255 */ + struct gamma_pixel *axis_x_256; + /* evenly distributed points, gamma 1025 software points 0-1025 */ + struct gamma_pixel *axis_x_1025; + /* OEM supplied gamma for regamma LUT */ + struct pwl_float_data *rgb_oem; + /* user supplied gamma */ + struct pwl_float_data *rgb_user; + uint32_t extra_points; + bool use_half_points; + struct fixed31_32 x_max1; + struct fixed31_32 x_max2; + struct fixed31_32 x_min; + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; +}; + +/* OPP RELATED */ +#define TO_DCE110_OPP(opp)\ + container_of(opp, struct dce110_opp, base) + +struct dce110_opp_reg_offsets { + uint32_t fmt_offset; + uint32_t fmt_mem_offset; + uint32_t dcp_offset; + uint32_t dcfe_offset; +}; + +struct dce110_opp { + struct output_pixel_processor base; + struct dce110_opp_reg_offsets offsets; + struct dce110_regamma regamma; +}; + +bool dce110_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets); + +void dce110_opp_destroy(struct output_pixel_processor **opp); + +/* REGAMMA RELATED */ +void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on); + +bool dce110_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params); + +void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode); + +void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + +void dce110_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + +/* FORMATTER RELATED */ +void dce110_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + +void dce110_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params); + +void dce110_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + +void dce110_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + +void dce110_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c new file mode 100644 index 000000000000..b46db202ddbb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c @@ -0,0 +1,363 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dce110_opp.h" +#include "basics/conversion.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#define DCP_REG(reg)\ + (reg + opp110->offsets.dcp_offset) + +enum { + OUTPUT_CSC_MATRIX_SIZE = 12 +}; + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + +static void program_color_matrix( + struct dce110_opp *opp110, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + struct dc_context *ctx = opp110->base.ctx; + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[0], + OUTPUT_CSC_C11_C12, + OUTPUT_CSC_C11); + + set_reg_field_value( + value, + tbl_entry->regval[1], + OUTPUT_CSC_C11_C12, + OUTPUT_CSC_C12); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[2], + OUTPUT_CSC_C13_C14, + OUTPUT_CSC_C13); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[3], + OUTPUT_CSC_C13_C14, + OUTPUT_CSC_C14); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[4], + OUTPUT_CSC_C21_C22, + OUTPUT_CSC_C21); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[5], + OUTPUT_CSC_C21_C22, + OUTPUT_CSC_C22); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[6], + OUTPUT_CSC_C23_C24, + OUTPUT_CSC_C23); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[7], + OUTPUT_CSC_C23_C24, + OUTPUT_CSC_C24); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[8], + OUTPUT_CSC_C31_C32, + OUTPUT_CSC_C31); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[9], + OUTPUT_CSC_C31_C32, + OUTPUT_CSC_C32); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[10], + OUTPUT_CSC_C33_C34, + OUTPUT_CSC_C33); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[11], + OUTPUT_CSC_C33_C34, + OUTPUT_CSC_C34); + + dm_write_reg(ctx, addr, value); + } +} + +static bool configure_graphics_mode( + struct dce110_opp *opp110, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + struct dc_context *ctx = opp110->base.ctx; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { + set_reg_field_value( + value, + 4, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + } else { + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + set_reg_field_value( + value, + 1, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + default: + return false; + } + } + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + set_reg_field_value( + value, + 1, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + default: + return false; + } + + } else + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + + addr = DCP_REG(mmOUTPUT_CSC_CONTROL); + dm_write_reg(ctx, addr, value); + + return true; +} + +void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix( + opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); +} + +void dce110_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file */ + program_color_matrix(opp110, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix */ + + configure_graphics_mode(opp110, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c new file mode 100644 index 000000000000..975466f6e424 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -0,0 +1,738 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dce110_opp.h" +#include "basics/conversion.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +#include "dce/dce_11_0_enum.h" + +enum { + OUTPUT_CSC_MATRIX_SIZE = 12 +}; + +/* constrast:0 - 2.0, default 1.0 */ +#define UNDERLAY_CONTRAST_DEFAULT 100 +#define UNDERLAY_CONTRAST_MAX 200 +#define UNDERLAY_CONTRAST_MIN 0 +#define UNDERLAY_CONTRAST_STEP 1 +#define UNDERLAY_CONTRAST_DIVIDER 100 + +/* Saturation: 0 - 2.0; default 1.0 */ +#define UNDERLAY_SATURATION_DEFAULT 100 /*1.00*/ +#define UNDERLAY_SATURATION_MIN 0 +#define UNDERLAY_SATURATION_MAX 200 /* 2.00 */ +#define UNDERLAY_SATURATION_STEP 1 /* 0.01 */ +/*actual max overlay saturation + * value = UNDERLAY_SATURATION_MAX /UNDERLAY_SATURATION_DIVIDER + */ + +/* Hue */ +#define UNDERLAY_HUE_DEFAULT 0 +#define UNDERLAY_HUE_MIN -300 +#define UNDERLAY_HUE_MAX 300 +#define UNDERLAY_HUE_STEP 5 +#define UNDERLAY_HUE_DIVIDER 10 /* HW range: -30 ~ +30 */ +#define UNDERLAY_SATURATION_DIVIDER 100 + +/* Brightness: in DAL usually -.25 ~ .25. + * In MMD is -100 to +100 in 16-235 range; which when scaled to full range is + * ~-116 to +116. When normalized this is about 0.4566. + * With 100 divider this becomes 46, but we may use another for better precision + * The ideal one is 100/219 ((100/255)*(255/219)), + * i.e. min/max = +-100, divider = 219 + * default 0.0 + */ +#define UNDERLAY_BRIGHTNESS_DEFAULT 0 +#define UNDERLAY_BRIGHTNESS_MIN -46 /* ~116/255 */ +#define UNDERLAY_BRIGHTNESS_MAX 46 +#define UNDERLAY_BRIGHTNESS_STEP 1 /* .01 */ +#define UNDERLAY_BRIGHTNESS_DIVIDER 100 + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + +static void program_color_matrix_v( + struct dce110_opp *opp110, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + struct dc_context *ctx = opp110->base.ctx; + uint32_t cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL); + bool use_set_a = (get_reg_field_value(cntl_value, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE) != 4); + + set_reg_field_value( + cntl_value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + + if (use_set_a) { + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C11_C12_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[0], + OUTPUT_CSC_C11_C12_A, + OUTPUT_CSC_C11_A); + + set_reg_field_value( + value, + tbl_entry->regval[1], + OUTPUT_CSC_C11_C12_A, + OUTPUT_CSC_C12_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C13_C14_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[2], + OUTPUT_CSC_C13_C14_A, + OUTPUT_CSC_C13_A); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[3], + OUTPUT_CSC_C13_C14_A, + OUTPUT_CSC_C14_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C21_C22_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[4], + OUTPUT_CSC_C21_C22_A, + OUTPUT_CSC_C21_A); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[5], + OUTPUT_CSC_C21_C22_A, + OUTPUT_CSC_C22_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C23_C24_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[6], + OUTPUT_CSC_C23_C24_A, + OUTPUT_CSC_C23_A); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[7], + OUTPUT_CSC_C23_C24_A, + OUTPUT_CSC_C24_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C31_C32_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[8], + OUTPUT_CSC_C31_C32_A, + OUTPUT_CSC_C31_A); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[9], + OUTPUT_CSC_C31_C32_A, + OUTPUT_CSC_C32_A); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C33_C34_A; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[10], + OUTPUT_CSC_C33_C34_A, + OUTPUT_CSC_C33_A); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[11], + OUTPUT_CSC_C33_C34_A, + OUTPUT_CSC_C34_A); + + dm_write_reg(ctx, addr, value); + } + set_reg_field_value( + cntl_value, + 4, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + } else { + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C11_C12_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[0], + OUTPUT_CSC_C11_C12_B, + OUTPUT_CSC_C11_B); + + set_reg_field_value( + value, + tbl_entry->regval[1], + OUTPUT_CSC_C11_C12_B, + OUTPUT_CSC_C12_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C13_C14_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[2], + OUTPUT_CSC_C13_C14_B, + OUTPUT_CSC_C13_B); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[3], + OUTPUT_CSC_C13_C14_B, + OUTPUT_CSC_C14_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C21_C22_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[4], + OUTPUT_CSC_C21_C22_B, + OUTPUT_CSC_C21_B); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[5], + OUTPUT_CSC_C21_C22_B, + OUTPUT_CSC_C22_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C23_C24_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[6], + OUTPUT_CSC_C23_C24_B, + OUTPUT_CSC_C23_B); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[7], + OUTPUT_CSC_C23_C24_B, + OUTPUT_CSC_C24_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C31_C32_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[8], + OUTPUT_CSC_C31_C32_B, + OUTPUT_CSC_C31_B); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[9], + OUTPUT_CSC_C31_C32_B, + OUTPUT_CSC_C32_B); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = mmOUTPUT_CSC_C33_C34_B; + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[10], + OUTPUT_CSC_C33_C34_B, + OUTPUT_CSC_C33_B); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[11], + OUTPUT_CSC_C33_C34_B, + OUTPUT_CSC_C34_B); + + dm_write_reg(ctx, addr, value); + } + set_reg_field_value( + cntl_value, + 5, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + } + + dm_write_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL, cntl_value); +} + +static bool configure_graphics_mode_v( + struct dce110_opp *opp110, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + struct dc_context *ctx = opp110->base.ctx; + uint32_t addr = mmCOL_MAN_OUTPUT_CSC_CONTROL; + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) + return true; + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* not supported for underlay on CZ */ + return false; + + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + default: + return false; + } + + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* not supported for underlay on CZ */ + return false; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + break; + default: + return false; + } + + } else + /* by pass */ + set_reg_field_value( + value, + 0, + COL_MAN_OUTPUT_CSC_CONTROL, + OUTPUT_CSC_MODE); + + addr = mmCOL_MAN_OUTPUT_CSC_CONTROL; + dm_write_reg(ctx, addr, value); + + return true; +} + +/*TODO: color depth is not correct when this is called*/ +static void set_Denormalization(struct output_pixel_processor *opp, + enum dc_color_depth color_depth) +{ + uint32_t value = dm_read_reg(opp->ctx, mmDENORM_CLAMP_CONTROL); + + switch (color_depth) { + case COLOR_DEPTH_888: + /* 255/256 for 8 bit output color depth */ + set_reg_field_value( + value, + 1, + DENORM_CLAMP_CONTROL, + DENORM_MODE); + break; + case COLOR_DEPTH_101010: + /* 1023/1024 for 10 bit output color depth */ + set_reg_field_value( + value, + 2, + DENORM_CLAMP_CONTROL, + DENORM_MODE); + break; + case COLOR_DEPTH_121212: + /* 4095/4096 for 12 bit output color depth */ + set_reg_field_value( + value, + 3, + DENORM_CLAMP_CONTROL, + DENORM_MODE); + break; + default: + /* not valid case */ + break; + } + + set_reg_field_value( + value, + 1, + DENORM_CLAMP_CONTROL, + DENORM_10BIT_OUT); + + dm_write_reg(opp->ctx, mmDENORM_CLAMP_CONTROL, value); +} + +struct input_csc_matrix { + enum dc_color_space color_space; + uint32_t regval[12]; +}; + +static const struct input_csc_matrix input_csc_matrix[] = { + {COLOR_SPACE_SRGB, +/*1_1 1_2 1_3 1_4 2_1 2_2 2_3 2_4 3_1 3_2 3_3 3_4 */ + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_SRGB_LIMITED, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_YCBCR601, + {0x2cdd, 0x2000, 0x0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, + 0x0, 0x2000, 0x38b4, 0xe3a6} }, + {COLOR_SPACE_YCBCR601_LIMITED, + {0x3353, 0x2568, 0x0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, + 0x0, 0x2568, 0x40de, 0xdd3a} }, + {COLOR_SPACE_YCBCR709, + {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, + 0x2000, 0x3b61, 0xe24f} }, + {COLOR_SPACE_YCBCR709_LIMITED, + {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, + 0x2568, 0x43ee, 0xdbb2} } +}; + +static void program_input_csc( + struct output_pixel_processor *opp, enum dc_color_space color_space) +{ + int arr_size = sizeof(input_csc_matrix)/sizeof(struct input_csc_matrix); + struct dc_context *ctx = opp->ctx; + const uint32_t *regval = NULL; + bool use_set_a; + uint32_t value; + int i; + + for (i = 0; i < arr_size; i++) + if (input_csc_matrix[i].color_space == color_space) { + regval = input_csc_matrix[i].regval; + break; + } + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + /* + * 1 == set A, the logic is 'if currently we're not using set A, + * then use set A, otherwise use set B' + */ + value = dm_read_reg(ctx, mmCOL_MAN_INPUT_CSC_CONTROL); + use_set_a = get_reg_field_value( + value, COL_MAN_INPUT_CSC_CONTROL, INPUT_CSC_MODE) != 1; + + if (use_set_a) { + /* fixed S2.13 format */ + value = 0; + set_reg_field_value( + value, regval[0], INPUT_CSC_C11_C12_A, INPUT_CSC_C11_A); + set_reg_field_value( + value, regval[1], INPUT_CSC_C11_C12_A, INPUT_CSC_C12_A); + dm_write_reg(ctx, mmINPUT_CSC_C11_C12_A, value); + + value = 0; + set_reg_field_value( + value, regval[2], INPUT_CSC_C13_C14_A, INPUT_CSC_C13_A); + set_reg_field_value( + value, regval[3], INPUT_CSC_C13_C14_A, INPUT_CSC_C14_A); + dm_write_reg(ctx, mmINPUT_CSC_C13_C14_A, value); + + value = 0; + set_reg_field_value( + value, regval[4], INPUT_CSC_C21_C22_A, INPUT_CSC_C21_A); + set_reg_field_value( + value, regval[5], INPUT_CSC_C21_C22_A, INPUT_CSC_C22_A); + dm_write_reg(ctx, mmINPUT_CSC_C21_C22_A, value); + + value = 0; + set_reg_field_value( + value, regval[6], INPUT_CSC_C23_C24_A, INPUT_CSC_C23_A); + set_reg_field_value( + value, regval[7], INPUT_CSC_C23_C24_A, INPUT_CSC_C24_A); + dm_write_reg(ctx, mmINPUT_CSC_C23_C24_A, value); + + value = 0; + set_reg_field_value( + value, regval[8], INPUT_CSC_C31_C32_A, INPUT_CSC_C31_A); + set_reg_field_value( + value, regval[9], INPUT_CSC_C31_C32_A, INPUT_CSC_C32_A); + dm_write_reg(ctx, mmINPUT_CSC_C31_C32_A, value); + + value = 0; + set_reg_field_value( + value, regval[10], INPUT_CSC_C33_C34_A, INPUT_CSC_C33_A); + set_reg_field_value( + value, regval[11], INPUT_CSC_C33_C34_A, INPUT_CSC_C34_A); + dm_write_reg(ctx, mmINPUT_CSC_C33_C34_A, value); + } else { + /* fixed S2.13 format */ + value = 0; + set_reg_field_value( + value, regval[0], INPUT_CSC_C11_C12_B, INPUT_CSC_C11_B); + set_reg_field_value( + value, regval[1], INPUT_CSC_C11_C12_B, INPUT_CSC_C12_B); + dm_write_reg(ctx, mmINPUT_CSC_C11_C12_B, value); + + value = 0; + set_reg_field_value( + value, regval[2], INPUT_CSC_C13_C14_B, INPUT_CSC_C13_B); + set_reg_field_value( + value, regval[3], INPUT_CSC_C13_C14_B, INPUT_CSC_C14_B); + dm_write_reg(ctx, mmINPUT_CSC_C13_C14_B, value); + + value = 0; + set_reg_field_value( + value, regval[4], INPUT_CSC_C21_C22_B, INPUT_CSC_C21_B); + set_reg_field_value( + value, regval[5], INPUT_CSC_C21_C22_B, INPUT_CSC_C22_B); + dm_write_reg(ctx, mmINPUT_CSC_C21_C22_B, value); + + value = 0; + set_reg_field_value( + value, regval[6], INPUT_CSC_C23_C24_B, INPUT_CSC_C23_B); + set_reg_field_value( + value, regval[7], INPUT_CSC_C23_C24_B, INPUT_CSC_C24_B); + dm_write_reg(ctx, mmINPUT_CSC_C23_C24_B, value); + + value = 0; + set_reg_field_value( + value, regval[8], INPUT_CSC_C31_C32_B, INPUT_CSC_C31_B); + set_reg_field_value( + value, regval[9], INPUT_CSC_C31_C32_B, INPUT_CSC_C32_B); + dm_write_reg(ctx, mmINPUT_CSC_C31_C32_B, value); + + value = 0; + set_reg_field_value( + value, regval[10], INPUT_CSC_C33_C34_B, INPUT_CSC_C33_B); + set_reg_field_value( + value, regval[11], INPUT_CSC_C33_C34_B, INPUT_CSC_C34_B); + dm_write_reg(ctx, mmINPUT_CSC_C33_C34_B, value); + } + + /* KK: leave INPUT_CSC_CONVERSION_MODE at default */ + value = 0; + /* + * select 8.4 input type instead of default 12.0. From the discussion + * with HW team, this format depends on the UNP surface format, so for + * 8-bit we should select 8.4 (4 bits truncated). For 10 it should be + * 10.2. For Carrizo we only support 8-bit surfaces on underlay pipe + * so we can always keep this at 8.4 (input_type=2). If the later asics + * start supporting 10+ bits, we will have a problem: surface + * programming including UNP_GRPH* is being done in DalISR after this, + * so either we pass surface format to here, or move this logic to ISR + */ + + set_reg_field_value( + value, 2, COL_MAN_INPUT_CSC_CONTROL, INPUT_CSC_INPUT_TYPE); + set_reg_field_value( + value, + use_set_a ? 1 : 2, + COL_MAN_INPUT_CSC_CONTROL, + INPUT_CSC_MODE); + + dm_write_reg(ctx, mmCOL_MAN_INPUT_CSC_CONTROL, value); +} + +void dce110_opp_v_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file + */ + program_color_matrix_v(opp110, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + program_input_csc(opp, default_adjust->in_color_space); + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix + */ + + configure_graphics_mode_v(opp110, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); + + set_Denormalization(opp, default_adjust->color_depth); +} + +void dce110_opp_v_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix_v( + opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode_v(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); + + /*TODO: Check if denormalization is needed*/ + /*set_Denormalization(opp, adjust->color_depth);*/ +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c new file mode 100644 index 000000000000..eac20775c23f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c @@ -0,0 +1,627 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" + +#define FMT_REG(reg)\ + (reg + opp110->offsets.fmt_offset) +/** + * set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE11 power saving reason. + */ +static void set_truncation( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + uint32_t value = 0; + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + + /*Disable truncation*/ + value = dm_read_reg(opp110->base.ctx, addr); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); + + dm_write_reg(opp110->base.ctx, addr, value); + + /* no 10bpc trunc on DCE11*/ + if (params->flags.TRUNCATE_ENABLED == 0 || + params->flags.TRUNCATE_DEPTH == 2) + return; + + /*Set truncation depth and Enable truncation*/ + set_reg_field_value(value, 1, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); + set_reg_field_value(value, params->flags.TRUNCATE_MODE, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); + set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); + + dm_write_reg(opp110->base.ctx, addr, value); + +} + +/** + * set_spatial_dither + * 1) set spatial dithering mode: pattern of seed + * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp + * 3) set random seed + * 4) set random mode + * lfsr is reset every frame or not reset + * RGB dithering method + * 0: RGB data are all dithered with x^28+x^3+1 + * 1: R data is dithered with x^28+x^3+1 + * G data is dithered with x^28+X^9+1 + * B data is dithered with x^28+x^13+1 + * enable high pass filter or not + * 5) enable spatical dithering + */ +static void set_spatial_dither( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + uint32_t depth_cntl_value = 0; + uint32_t fmt_cntl_value = 0; + uint32_t dither_r_value = 0; + uint32_t dither_g_value = 0; + uint32_t dither_b_value = 0; + + /*Disable spatial (random) dithering*/ + depth_cntl_value = dm_read_reg(opp110->base.ctx, addr); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE); + + dm_write_reg(opp110->base.ctx, addr, depth_cntl_value); + + /* no 10bpc on DCE11*/ + if (params->flags.SPATIAL_DITHER_ENABLED == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 2) + return; + + addr = FMT_REG(mmFMT_CONTROL); + fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); + /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ + if (params->flags.FRAME_RANDOM == 1) { + if (params->flags.SPATIAL_DITHER_DEPTH == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 1) { + set_reg_field_value(fmt_cntl_value, 15, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); + set_reg_field_value(fmt_cntl_value, 2, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); + } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { + set_reg_field_value(fmt_cntl_value, 3, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); + set_reg_field_value(fmt_cntl_value, 1, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); + } else + return; + } else { + set_reg_field_value(fmt_cntl_value, 0, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); + set_reg_field_value(fmt_cntl_value, 0, + FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); + } + + dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); + + /*Set seed for random values for + * spatial dithering for R,G,B channels*/ + addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED); + set_reg_field_value(dither_r_value, params->r_seed_value, + FMT_DITHER_RAND_R_SEED, + FMT_RAND_R_SEED); + dm_write_reg(opp110->base.ctx, addr, dither_r_value); + + addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED); + set_reg_field_value(dither_g_value, + params->g_seed_value, + FMT_DITHER_RAND_G_SEED, + FMT_RAND_G_SEED); + dm_write_reg(opp110->base.ctx, addr, dither_g_value); + + addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED); + set_reg_field_value(dither_b_value, params->b_seed_value, + FMT_DITHER_RAND_B_SEED, + FMT_RAND_B_SEED); + dm_write_reg(opp110->base.ctx, addr, dither_b_value); + + /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero + * offset for the R/Cr channel, lower 4LSB + * is forced to zeros. Typically set to 0 + * RGB and 0x80000 YCbCr. + */ + /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero + * offset for the G/Y channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB + * and 0x80000 YCbCr. + */ + /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero + * offset for the B/Cb channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB and + * 0x80000 YCbCr. + */ + + /*Set spatial dithering bit depth*/ + set_reg_field_value(depth_cntl_value, + params->flags.SPATIAL_DITHER_DEPTH, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_DEPTH); + + /* Set spatial dithering mode + * (default is Seed patterrn AAAA...) + */ + set_reg_field_value(depth_cntl_value, + params->flags.SPATIAL_DITHER_MODE, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_MODE); + + /*Reset only at startup*/ + set_reg_field_value(depth_cntl_value, + params->flags.FRAME_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_FRAME_RANDOM_ENABLE); + + /*Set RGB data dithered with x^28+x^3+1*/ + set_reg_field_value(depth_cntl_value, + params->flags.RGB_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_RGB_RANDOM_ENABLE); + + /*Disable High pass filter*/ + set_reg_field_value(depth_cntl_value, + params->flags.HIGHPASS_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_HIGHPASS_RANDOM_ENABLE); + + /*Enable spatial dithering*/ + set_reg_field_value(depth_cntl_value, + 1, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_EN); + + addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + dm_write_reg(opp110->base.ctx, addr, depth_cntl_value); + +} + +/** + * SetTemporalDither (Frame Modulation) + * 1) set temporal dither depth + * 2) select pattern: from hard-coded pattern or programmable pattern + * 3) select optimized strips for BGR or RGB LCD sub-pixel + * 4) set s matrix + * 5) set t matrix + * 6) set grey level for 0.25, 0.5, 0.75 + * 7) enable temporal dithering + */ +static void set_temporal_dither( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + uint32_t value; + + /*Disable temporal (frame modulation) dithering first*/ + value = dm_read_reg(opp110->base.ctx, addr); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_RESET); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_OFFSET); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_50FRC_SEL); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_75FRC_SEL); + + dm_write_reg(opp110->base.ctx, addr, value); + + /* no 10bpc dither on DCE11*/ + if (params->flags.FRAME_MODULATION_ENABLED == 0 || + params->flags.FRAME_MODULATION_DEPTH == 2) + return; + + /* Set temporal dithering depth*/ + set_reg_field_value(value, + params->flags.FRAME_MODULATION_DEPTH, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_RESET); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_OFFSET); + + /*Select legacy pattern based on FRC and Temporal level*/ + addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL); + dm_write_reg(opp110->base.ctx, addr, 0); + /*Set s matrix*/ + addr = FMT_REG( + mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); + dm_write_reg(opp110->base.ctx, addr, 0); + /*Set t matrix*/ + addr = FMT_REG( + mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); + dm_write_reg(opp110->base.ctx, addr, 0); + + /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ + set_reg_field_value(value, + params->flags.TEMPORAL_LEVEL, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL); + + set_reg_field_value(value, + params->flags.FRC25, + FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL); + + set_reg_field_value(value, + params->flags.FRC50, + FMT_BIT_DEPTH_CONTROL, + FMT_50FRC_SEL); + + set_reg_field_value(value, + params->flags.FRC75, + FMT_BIT_DEPTH_CONTROL, + FMT_75FRC_SEL); + + /*Enable bit reduction by temporal (frame modulation) dithering*/ + set_reg_field_value(value, + 1, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN); + + addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + dm_write_reg(opp110->base.ctx, addr, value); + +} + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +void dce110_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t clamp_cntl_value = 0; + uint32_t red_clamp_value = 0; + uint32_t green_clamp_value = 0; + uint32_t blue_clamp_value = 0; + uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); + + clamp_cntl_value = dm_read_reg(opp110->base.ctx, addr); + + set_reg_field_value(clamp_cntl_value, + 0, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 0, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + break; + + case CLAMPING_LIMITED_RANGE_8BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + + case CLAMPING_LIMITED_RANGE_10BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 2, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + case CLAMPING_LIMITED_RANGE_12BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 3, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 7, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + /*set the defaults*/ + set_reg_field_value(red_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_R, + FMT_CLAMP_LOWER_R); + + set_reg_field_value(red_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_R, + FMT_CLAMP_UPPER_R); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R); + dm_write_reg(opp110->base.ctx, addr, red_clamp_value); + + set_reg_field_value(green_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_G, + FMT_CLAMP_LOWER_G); + + set_reg_field_value(green_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_G, + FMT_CLAMP_UPPER_G); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G); + dm_write_reg(opp110->base.ctx, addr, green_clamp_value); + + set_reg_field_value(blue_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_B, + FMT_CLAMP_LOWER_B); + + set_reg_field_value(blue_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_B, + FMT_CLAMP_UPPER_B); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B); + dm_write_reg(opp110->base.ctx, addr, blue_clamp_value); + + break; + + default: + break; + } + + addr = FMT_REG(mmFMT_CLAMP_CNTL); + /*Set clamp control*/ + dm_write_reg(opp110->base.ctx, addr, clamp_cntl_value); + +} + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void set_pixel_encoding( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t fmt_cntl_value; + uint32_t addr = FMT_REG(mmFMT_CONTROL); + + /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ + fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); + + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + set_reg_field_value(fmt_cntl_value, + 1, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /*00 - Pixels drop mode ,01 - Pixels average mode*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_MODE); + + /*00 - Cb before Cr ,01 - Cr before Cb*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_ORDER); + } + dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); + +} + +void dce110_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + set_truncation(opp110, params); + set_spatial_dither(opp110, params); + set_temporal_dither(opp110, params); +} + +void dce110_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + dce110_opp_set_clamping(opp110, params); + set_pixel_encoding(opp110, params); +} + +void dce110_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t value; + bool enable_dyn_exp = false; + uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); + + value = dm_read_reg(opp->ctx, addr); + + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + + /* From HW programming guide: + FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output + FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ + if (color_sp == COLOR_SPACE_SRGB) + enable_dyn_exp = true; + + /*00 - 10-bit -> 12-bit dynamic expansion*/ + /*01 - 8-bit -> 12-bit dynamic expansion*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (color_dpth) { + case COLOR_DEPTH_888: + set_reg_field_value(value, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 1, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + break; + case COLOR_DEPTH_101010: + set_reg_field_value(value, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + break; + case COLOR_DEPTH_121212: + break; + default: + break; + } + } + + dm_write_reg(opp->ctx, addr, value); +} + +void dce110_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + /* dithering is affected by , hence should be + * programmed afterwards */ + dce110_opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + dce110_opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + return; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c new file mode 100644 index 000000000000..62051abcfe2f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c @@ -0,0 +1,537 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + opp110->offsets.dcp_offset) + +#define DCFE_REG(reg)\ + (reg + opp110->offsets.dcfe_offset) + +enum { + MAX_PWL_ENTRY = 128, + MAX_REGIONS_NUMBER = 16 + +}; + +/* + ***************************************************************************** + * Function: regamma_config_regions_and_segments + * + * build regamma curve by using predefined hw points + * uses interface parameters ,like EDID coeff. + * + * @param : parameters interface parameters + * @return void + * + * @note + * + * @see + * + ***************************************************************************** + */ +static void regamma_config_regions_and_segments( + struct dce110_opp *opp110, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + uint32_t value = 0; + + { + set_reg_field_value( + value, + params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START); + + set_reg_field_value( + value, + 0, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_START_CNTL), + value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[0].custom_float_slope, + REGAMMA_CNTLA_SLOPE_CNTL, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[1].custom_float_x, + REGAMMA_CNTLA_END_CNTL1, + REGAMMA_CNTLA_EXP_REGION_END); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[2].custom_float_slope, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_BASE); + + set_reg_field_value( + value, + params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); + } + + curve = params->arr_curve_points; + + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); + + dm_write_reg( + opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_0_1), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_2_3), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_4_5), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_6_7), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_8_9), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_10_11), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_12_13), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), + value); + } +} + +static void program_pwl( + struct dce110_opp *opp110, + const struct pwl_params *params) +{ + uint32_t value; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + value = dm_read_reg(opp110->base.ctx, + DCFE_REG(mmDCFE_MEM_PWR_CTRL)); + + set_reg_field_value( + value, + 1, + DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS); + + dm_write_reg(opp110->base.ctx, + DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); + + while (counter < max_tries) { + value = + dm_read_reg( + opp110->base.ctx, + DCFE_REG(mmDCFE_MEM_PWR_STATUS)); + + if (get_reg_field_value( + value, + DCFE_MEM_PWR_STATUS, + DCP_REGAMMA_MEM_PWR_STATE) == 0) + break; + + ++counter; + } + + if (counter == max_tries) { + dm_logger_write(opp110->base.ctx->logger, LOG_WARNING, + "%s: regamma lut was not powered on " + "in a timely manner," + " programming still proceeds\n", + __func__); + } + } + + value = 0; + + set_reg_field_value( + value, + 7, + REGAMMA_LUT_WRITE_EN_MASK, + REGAMMA_LUT_WRITE_EN_MASK); + + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); + dm_write_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_LUT_INDEX), 0); + + /* Program REGAMMA_LUT_DATA */ + { + const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); + + uint32_t i = 0; + + const struct pwl_result_data *rgb = params->rgb_resulted; + + while (i != params->hw_points_num) { + dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); + + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_red_reg); + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_green_reg); + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + value = dm_read_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL)); + + set_reg_field_value( + value, + 0, + DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS); + + dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); +} + +bool dce110_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + /* Setup regions */ + regamma_config_regions_and_segments(opp110, params); + + /* Program PWL */ + program_pwl(opp110, params); + + return true; +} + +void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + uint32_t value = + dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL)); + + set_reg_field_value( + value, + power_on, + DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS); + + set_reg_field_value( + value, + power_on, + DCFE_MEM_PWR_CTRL, + DCP_LUT_MEM_PWR_DIS); + + dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); +} + +void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t value = dm_read_reg(opp110->base.ctx, + DCP_REG(mmREGAMMA_CONTROL)); + + set_reg_field_value( + value, + mode, + REGAMMA_CONTROL, + GRPH_REGAMMA_MODE); + + dm_write_reg(opp110->base.ctx, DCP_REG(mmREGAMMA_CONTROL), + value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c new file mode 100644 index 000000000000..3b3a9175b2c3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -0,0 +1,551 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" +#include "gamma_types.h" + +static void power_on_lut(struct output_pixel_processor *opp, + bool power_on, bool inputgamma, bool regamma) +{ + uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + int i; + + if (power_on) { + if (inputgamma) + set_reg_field_value( + value, + 1, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); + if (regamma) + set_reg_field_value( + value, + 1, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_DIS); + } else { + if (inputgamma) + set_reg_field_value( + value, + 0, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); + if (regamma) + set_reg_field_value( + value, + 0, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_DIS); + } + + dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); + + for (i = 0; i < 3; i++) { + value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + if (get_reg_field_value(value, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) && + get_reg_field_value(value, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_DIS)) + break; + + udelay(2); + } +} + +static void set_bypass_input_gamma(struct dce110_opp *opp110) +{ + uint32_t value; + + value = dm_read_reg(opp110->base.ctx, + mmCOL_MAN_INPUT_GAMMA_CONTROL1); + + set_reg_field_value( + value, + 0, + COL_MAN_INPUT_GAMMA_CONTROL1, + INPUT_GAMMA_MODE); + + dm_write_reg(opp110->base.ctx, + mmCOL_MAN_INPUT_GAMMA_CONTROL1, value); +} + +static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) +{ + uint32_t value = 0; + + set_reg_field_value( + value, + mode, + GAMMA_CORR_CONTROL, + GAMMA_CORR_MODE); + + dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CONTROL, 0); +} + +/* + ***************************************************************************** + * Function: regamma_config_regions_and_segments + * + * build regamma curve by using predefined hw points + * uses interface parameters ,like EDID coeff. + * + * @param : parameters interface parameters + * @return void + * + * @note + * + * @see + * + ***************************************************************************** + */ +static void regamma_config_regions_and_segments( + struct dce110_opp *opp110, const struct pwl_params *params) +{ + const struct gamma_curve *curve; + uint32_t value = 0; + + { + set_reg_field_value( + value, + params->arr_points[0].custom_float_x, + GAMMA_CORR_CNTLA_START_CNTL, + GAMMA_CORR_CNTLA_EXP_REGION_START); + + set_reg_field_value( + value, + 0, + GAMMA_CORR_CNTLA_START_CNTL, + GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT); + + dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, + value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[0].custom_float_slope, + GAMMA_CORR_CNTLA_SLOPE_CNTL, + GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[1].custom_float_x, + GAMMA_CORR_CNTLA_END_CNTL1, + GAMMA_CORR_CNTLA_EXP_REGION_END); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_END_CNTL1, value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[2].custom_float_slope, + GAMMA_CORR_CNTLA_END_CNTL2, + GAMMA_CORR_CNTLA_EXP_REGION_END_BASE); + + set_reg_field_value( + value, + params->arr_points[1].custom_float_y, + GAMMA_CORR_CNTLA_END_CNTL2, + GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_END_CNTL2, value); + } + + curve = params->arr_curve_points; + + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_0_1, + GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_0_1, + GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_0_1, + GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_0_1, + GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS); + + dm_write_reg( + opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_0_1, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_2_3, + GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_2_3, + GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_2_3, + GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_2_3, + GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_2_3, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_4_5, + GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_4_5, + GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_4_5, + GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_4_5, + GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_4_5, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_6_7, + GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_6_7, + GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_6_7, + GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_6_7, + GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_6_7, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_8_9, + GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_8_9, + GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_8_9, + GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_8_9, + GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_8_9, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_10_11, + GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_10_11, + GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_10_11, + GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_10_11, + GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_10_11, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_12_13, + GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_12_13, + GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_12_13, + GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_12_13, + GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_12_13, + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + GAMMA_CORR_CNTLA_REGION_14_15, + GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + GAMMA_CORR_CNTLA_REGION_14_15, + GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + GAMMA_CORR_CNTLA_REGION_14_15, + GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + GAMMA_CORR_CNTLA_REGION_14_15, + GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_CNTLA_REGION_14_15, + value); + } +} + +static void program_pwl(struct dce110_opp *opp110, + const struct pwl_params *params) +{ + uint32_t value = 0; + + set_reg_field_value( + value, + 7, + GAMMA_CORR_LUT_WRITE_EN_MASK, + GAMMA_CORR_LUT_WRITE_EN_MASK); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_LUT_WRITE_EN_MASK, value); + + dm_write_reg(opp110->base.ctx, + mmGAMMA_CORR_LUT_INDEX, 0); + + /* Program REGAMMA_LUT_DATA */ + { + const uint32_t addr = mmGAMMA_CORR_LUT_DATA; + uint32_t i = 0; + const struct pwl_result_data *rgb = + params->rgb_resulted; + + while (i != params->hw_points_num) { + dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); + + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_red_reg); + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_green_reg); + dm_write_reg(opp110->base.ctx, addr, + rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } +} + +bool dce110_opp_program_regamma_pwl_v( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + /* Setup regions */ + regamma_config_regions_and_segments(opp110, params); + + set_bypass_input_gamma(opp110); + + /* Power on gamma LUT memory */ + power_on_lut(opp, true, false, true); + + /* Program PWL */ + program_pwl(opp110, params); + + /* program regamma config */ + configure_regamma_mode(opp110, 1); + + /* Power return to auto back */ + power_on_lut(opp, false, false, true); + + return true; +} + +void dce110_opp_power_on_regamma_lut_v( + struct output_pixel_processor *opp, + bool power_on) +{ + uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + + set_reg_field_value( + value, + 0, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_FORCE); + + set_reg_field_value( + value, + power_on, + DCFEV_MEM_PWR_CTRL, + COL_MAN_GAMMA_CORR_MEM_PWR_DIS); + + set_reg_field_value( + value, + 0, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE); + + set_reg_field_value( + value, + power_on, + DCFEV_MEM_PWR_CTRL, + COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); + + dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c new file mode 100644 index 000000000000..4b32397529ec --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -0,0 +1,63 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dce110_opp.h" +#include "dce110_opp_v.h" + +#include "gamma_types.h" + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static const struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, + .opp_set_csc_default = dce110_opp_v_set_csc_default, + .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce110_opp_program_fmt, + .opp_program_bit_depth_reduction = + dce110_opp_program_bit_depth_reduction +}; + +bool dce110_opp_v_construct(struct dce110_opp *opp110, + struct dc_context *ctx) +{ + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h new file mode 100644 index 000000000000..dcdbf86fccc1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -0,0 +1,56 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE110_V_H__ +#define __DC_OPP_DCE110_V_H__ + +#include "dc_types.h" +#include "opp.h" +#include "core_types.h" + +#include "gamma_types.h" /* decprecated */ + +struct gamma_parameters; + +bool dce110_opp_v_construct(struct dce110_opp *opp110, + struct dc_context *ctx); + +/* underlay callbacks */ +void dce110_opp_v_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + +void dce110_opp_v_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + +bool dce110_opp_program_regamma_pwl_v( + struct output_pixel_processor *opp, + const struct pwl_params *params); + +void dce110_opp_power_on_regamma_lut_v( + struct output_pixel_processor *opp, + bool power_on); + +#endif /* __DC_OPP_DCE110_V_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c new file mode 100644 index 000000000000..959467fa421e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -0,0 +1,1413 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "dce110/dce110_resource.h" + +#include "include/irq_service_interface.h" +#include "dce/dce_audio.h" +#include "dce110/dce110_timing_generator.h" +#include "irq/dce110/irq_service_dce110.h" +#include "dce110/dce110_timing_generator_v.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce110/dce110_mem_input.h" +#include "dce110/dce110_mem_input_v.h" +#include "dce110/dce110_ipp.h" +#include "dce/dce_transform.h" +#include "dce110/dce110_transform_v.h" +#include "dce110/dce110_opp.h" +#include "dce110/dce110_opp_v.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_hwseq.h" +#include "dce110/dce110_hw_sequencer.h" + +#include "reg_helper.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +#ifndef DPHY_RX_FAST_TRAINING_CAPABLE + #define DPHY_RX_FAST_TRAINING_CAPABLE 0x1 +#endif + +static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + + +static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), +} +}; + + + + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + + +#define link_regs(id)\ +[id] = {\ + LE_DCE110_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */ +static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_100_110(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps carrizo_resource_cap = { + .num_timing_generator = 3, + .num_video_plane = 1, + .num_audio = 3, + .num_stream_encoder = 3, + .num_pll = 2, +}; + +static const struct resource_caps stoney_resource_cap = { + .num_timing_generator = 2, + .num_video_plane = 1, + .num_audio = 3, + .num_stream_encoder = 3, + .num_pll = 2, +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x4819 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce110_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static struct stream_encoder *dce110_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_stoney_reg = { + HWSEQ_ST_REG_LIST() +}; + +static const struct dce_hwseq_registers hwseq_cz_reg = { + HWSEQ_CZ_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE11_MASK_SH_LIST(__SHIFT), +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE11_MASK_SH_LIST(_MASK), +}; + +static struct dce_hwseq *dce110_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev) ? + &hwseq_stoney_reg : &hwseq_cz_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + hws->wa.blnd_crtc_trigger = true; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce110_stream_encoder_create, + .create_hwseq = dce110_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static struct mem_input *dce110_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { + struct mem_input *mi = &mem_input110->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 3; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input110); + return NULL; +} + +static void dce110_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce110_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) + return &transform->base; + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static struct input_pixel_processor *dce110_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offsets) +{ + struct dce110_ipp *ipp = + dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce110_ipp_construct(ipp, ctx, inst, offsets)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +struct link_encoder *dce110_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + enc110->base.features.ycbcr420_supported = false; + enc110->base.features.max_hdmi_pixel_clock = 594000; + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +static struct output_pixel_processor *dce110_opp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, offsets)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + +struct clock_source *dce110_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce110_clock_source_destroy(struct clock_source **clk_src) +{ + struct dce110_clk_src *dce110_clk_src; + + if (!clk_src) + return; + + dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); + + if (dce110_clk_src->dp_ss_params) + dm_free(dce110_clk_src->dp_ss_params); + + if (dce110_clk_src->hdmi_ss_params) + dm_free(dce110_clk_src->hdmi_ss_params); + + if (dce110_clk_src->dvi_ss_params) + dm_free(dce110_clk_src->dvi_ss_params); + + dm_free(dce110_clk_src); + *clk_src = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce110_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce110_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce110_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.dp_clock_source != NULL) + dce110_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.display_clock != NULL) { + dal_display_clock_destroy(&pool->base.display_clock); + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + + +static void get_pixel_clock_parameters( + const struct pipe_ctx *pipe_ctx, + struct pixel_clk_params *pixel_clk_params) +{ + const struct core_stream *stream = pipe_ctx->stream; + + /*TODO: is this halved for YCbCr 420? in that case we might want to move + * the pixel clock normalization for hdmi up to here instead of doing it + * in pll_adjust_pix_clk + */ + pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; + pixel_clk_params->signal_type = pipe_ctx->stream->signal; + pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; + /* TODO: un-hardcode*/ + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->public.timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; + pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == + PIXEL_ENCODING_YCBCR420); +} + +void dce110_resource_build_bit_depth_reduction_params( + const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth) +{ + memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); + + /*TODO: Need to un-hardcode, refer to function with same name + * in dal2 hw_sequencer*/ + + fmt_bit_depth->flags.TRUNCATE_ENABLED = 0; + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0; + fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0; + + /* Diagnostics need consistent CRC of the image, that means + * dithering should not be enabled for Diagnostics. */ + if (IS_DIAG_DC(stream->ctx->dce_environment) == false) { + switch (stream->public.timing.display_color_depth) { + case COLOR_DEPTH_666: + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; + break; + case COLOR_DEPTH_888: + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; + break; + case COLOR_DEPTH_101010: + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; + break; + default: + break; + } + fmt_bit_depth->flags.RGB_RANDOM = 1; + fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; + } + + return; +} + +enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +{ + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( + pipe_ctx->clock_source, + &pipe_ctx->pix_clk_params, + &pipe_ctx->pll_settings); + dce110_resource_build_bit_depth_reduction_params(pipe_ctx->stream, + &pipe_ctx->stream->bit_depth_params); + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; + + return DC_OK; +} + +static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx) +{ + if (pipe_ctx->pipe_idx != underlay_idx) + return true; + if (!pipe_ctx->surface) + return false; + if (pipe_ctx->surface->public.format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + return true; +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j, k; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (!is_surface_pixel_format_supported(pipe_ctx, + context->res_ctx.pool->underlay_pipe_index)) + return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = dce110_resource_build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + resource_build_info_frame(pipe_ctx); + + /* do not need to validate non root pipes */ + break; + } + } + } + + return DC_OK; +} + +enum dc_status dce110_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + dm_logger_write( + dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "%s: start", + __func__); + + if (!bw_calcs( + dc->ctx, + &dc->bw_dceip, + &dc->bw_vbios, + context->res_ctx.pipe_ctx, + context->res_ctx.pool->pipe_count, + &context->bw_results)) + result = DC_FAIL_BANDWIDTH_VALIDATE; + else + result = DC_OK; + + if (result == DC_FAIL_BANDWIDTH_VALIDATE) + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, + "%s: %dx%d@%d Bandwidth validation failed!\n", + __func__, + context->targets[0]->public.streams[0]->timing.h_addressable, + context->targets[0]->public.streams[0]->timing.v_addressable, + context->targets[0]->public.streams[0]->timing.pix_clk_khz); + + if (memcmp(&dc->current_context->bw_results, + &context->bw_results, sizeof(context->bw_results))) { + struct log_entry log_entry; + dm_logger_open( + dc->ctx->logger, + &log_entry, + LOG_BANDWIDTH_CALCS); + dm_logger_append(&log_entry, "%s: finish,\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n", + __func__, + context->bw_results.nbp_state_change_wm_ns[0].b_mark, + context->bw_results.nbp_state_change_wm_ns[0].a_mark, + context->bw_results.urgent_wm_ns[0].b_mark, + context->bw_results.urgent_wm_ns[0].a_mark, + context->bw_results.stutter_exit_wm_ns[0].b_mark, + context->bw_results.stutter_exit_wm_ns[0].a_mark); + dm_logger_append(&log_entry, + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n", + context->bw_results.nbp_state_change_wm_ns[1].b_mark, + context->bw_results.nbp_state_change_wm_ns[1].a_mark, + context->bw_results.urgent_wm_ns[1].b_mark, + context->bw_results.urgent_wm_ns[1].a_mark, + context->bw_results.stutter_exit_wm_ns[1].b_mark, + context->bw_results.stutter_exit_wm_ns[1].a_mark); + dm_logger_append(&log_entry, + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", + context->bw_results.nbp_state_change_wm_ns[2].b_mark, + context->bw_results.nbp_state_change_wm_ns[2].a_mark, + context->bw_results.urgent_wm_ns[2].b_mark, + context->bw_results.urgent_wm_ns[2].a_mark, + context->bw_results.stutter_exit_wm_ns[2].b_mark, + context->bw_results.stutter_exit_wm_ns[2].a_mark, + context->bw_results.stutter_mode_enable); + dm_logger_append(&log_entry, + "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" + "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", + context->bw_results.cpuc_state_change_enable, + context->bw_results.cpup_state_change_enable, + context->bw_results.nbp_state_change_enable, + context->bw_results.all_displays_in_sync, + context->bw_results.dispclk_khz, + context->bw_results.required_sclk, + context->bw_results.required_sclk_deep_sleep, + context->bw_results.required_yclk, + context->bw_results.blackout_recovery_time_us); + dm_logger_close(&log_entry); + } + return result; +} + +static bool dce110_validate_surface_sets( + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) { + if (set[i].surface_count == 0) + continue; + + if (set[i].surface_count > 2) + return false; + + if (set[i].surfaces[0]->src_rect.width + != set[i].target->streams[0]->src.width + || set[i].surfaces[0]->src_rect.height + != set[i].target->streams[0]->src.height) + return false; + if (set[i].surfaces[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + + if (set[i].surface_count == 2) { + if (set[i].surfaces[1]->format + < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + if (set[i].surfaces[1]->src_rect.width > 1920 + || set[i].surfaces[1]->src_rect.height > 1080) + return false; + + if (set[i].target->streams[0]->timing.pixel_encoding != PIXEL_ENCODING_RGB) + return false; + } + } + + return true; +} + +enum dc_status dce110_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + + if (!dce110_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + context->res_ctx.pool = dc->res_pool; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (!resource_validate_attach_surfaces( + set, set_count, dc->current_context, context)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + result = resource_build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce110_validate_bandwidth(dc, context); + + return result; +} + +enum dc_status dce110_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->res_ctx.pool = dc->res_pool; + + context->targets[0] = DC_TARGET_TO_CORE(dc_target); + dc_target_retain(&context->targets[0]->public); + context->target_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_target( + context, dc->public.caps.max_targets); + result = resource_build_scaling_params_for_context(dc, context); + } + + if (result == DC_OK) + result = dce110_validate_bandwidth(dc, context); + + return result; +} + +static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer( + struct resource_context *res_ctx, + struct core_stream *stream) +{ + unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index; + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; + + if (res_ctx->pipe_ctx[underlay_idx].stream) { + return NULL; + } + + pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx]; + pipe_ctx->mi = res_ctx->pool->mis[underlay_idx]; + /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/ + pipe_ctx->xfm = res_ctx->pool->transforms[underlay_idx]; + pipe_ctx->opp = res_ctx->pool->opps[underlay_idx]; + pipe_ctx->dis_clk = res_ctx->pool->display_clock; + pipe_ctx->pipe_idx = underlay_idx; + + pipe_ctx->stream = stream; + + return pipe_ctx; + +} + +static void dce110_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + + +static const struct resource_funcs dce110_res_pool_funcs = { + .destroy = dce110_destroy_resource_pool, + .link_enc_create = dce110_link_encoder_create, + .validate_with_context = dce110_validate_with_context, + .validate_guaranteed = dce110_validate_guaranteed, + .validate_bandwidth = dce110_validate_bandwidth, + .acquire_idle_pipe_for_layer = dce110_acquire_idle_pipe_for_layer, + .build_bit_depth_reduction_params = + dce110_resource_build_bit_depth_reduction_params +}; + +static void underlay_create(struct dc_context *ctx, struct resource_pool *pool) +{ + struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); + struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); + struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); + struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); + + dce110_opp_v_construct(dce110_oppv, ctx); + dce110_timing_generator_v_construct(dce110_tgv, ctx); + dce110_mem_input_v_construct(dce110_miv, ctx); + dce110_transform_v_construct(dce110_xfmv, ctx); + + pool->opps[pool->pipe_count] = &dce110_oppv->base; + pool->timing_generators[pool->pipe_count] = &dce110_tgv->base; + pool->mis[pool->pipe_count] = &dce110_miv->base; + pool->transforms[pool->pipe_count] = &dce110_xfmv->base; + pool->pipe_count++; + + /* update the public caps to indicate an underlay is available */ + ctx->dc->caps.max_slave_planes = 1; + ctx->dc->caps.max_slave_planes = 1; +} + +static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +{ + struct dm_pp_clock_levels clks = {0}; + + /*do system clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &clks); + /* convert all the clock fro kHz to fix point mHz */ + dc->bw_vbios.high_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels/8], 1000); + dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*2/8], 1000); + dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*3/8], 1000); + dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*4/8], 1000); + dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*5/8], 1000); + dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*6/8], 1000); + dc->bw_vbios.low_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + dc->sclk_lvls = clks; + + /*do display clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_DISPLAY_CLK, + &clks); + dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios.mid_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1], 1000); + dc->bw_vbios.low_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &clks); + + dc->bw_vbios.low_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); + dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, + 1000); + dc->bw_vbios.high_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, + 1000); +} + +enum clocks_state dce110_resource_convert_clock_state_pp_to_dc( + enum dm_pp_clocks_state pp_clock_state) +{ + enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID; + + switch (pp_clock_state) { + case DM_PP_CLOCKS_STATE_INVALID: + dc_clocks_state = CLOCKS_STATE_INVALID; + break; + case DM_PP_CLOCKS_STATE_ULTRA_LOW: + dc_clocks_state = CLOCKS_STATE_ULTRA_LOW; + break; + case DM_PP_CLOCKS_STATE_LOW: + dc_clocks_state = CLOCKS_STATE_LOW; + break; + case DM_PP_CLOCKS_STATE_NOMINAL: + dc_clocks_state = CLOCKS_STATE_NOMINAL; + break; + case DM_PP_CLOCKS_STATE_PERFORMANCE: + dc_clocks_state = CLOCKS_STATE_PERFORMANCE; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7; + break; + default: + dc_clocks_state = CLOCKS_STATE_INVALID; + break; + } + + return dc_clocks_state; +} + +const struct resource_caps *dce110_resource_cap( + struct hw_asic_id *asic_id) +{ + if (ASIC_REV_IS_STONEY(asic_id->hw_internal_rev)) + return &stoney_resource_cap; + else + return &carrizo_resource_cap; +} + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool, + struct hw_asic_id asic_id) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = dce110_resource_cap(&ctx->asic_id); + pool->base.funcs = &dce110_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.underlay_pipe_index = pool->base.pipe_count; + + dc->public.caps.max_downscale_ratio = 150; + dc->public.caps.i2c_speed_in_khz = 100; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, + &clk_src_regs[1], false); + + pool->base.clk_src_count = 2; + + /* TODO: find out if CZ support 3 PLLs */ + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dal_display_clock_dce110_create(ctx); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + /* get static clock information for PPLIB or firmware, save + * max_clock_state + */ + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { + enum clocks_state max_clocks_state = + dce110_resource_convert_clock_state_pp_to_dc( + static_clk_info.max_clocks_state); + + dal_display_clock_store_max_clocks_state( + pool->base.display_clock, max_clocks_state); + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce110_timing_generator_create( + ctx, i, &dce110_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce110_mem_input_create(ctx, i, + &dce110_mi_reg_offsets[i]); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce110_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + underlay_create(ctx, &pool->base); + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce110_hw_sequencer_construct(dc)) + goto res_create_fail; + + if (ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev)) + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_STONEY); + else + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_CARRIZO); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce110_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc, + struct hw_asic_id asic_id) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool, asic_id)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h new file mode 100644 index 000000000000..535623aa0052 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -0,0 +1,56 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE110_H__ +#define __DC_RESOURCE_DCE110_H__ + +#include "core_types.h" + +struct core_dc; +struct resource_pool; + +#define TO_DCE110_RES_POOL(pool)\ + container_of(pool, struct dce110_resource_pool, base) + +struct dce110_resource_pool { + struct resource_pool base; +}; + +enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); + +enum clocks_state dce110_resource_convert_clock_state_pp_to_dc( + enum dm_pp_clocks_state pp_clock_state); + +void dce110_resource_build_bit_depth_reduction_params( + const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth); + +struct resource_pool *dce110_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc, + struct hw_asic_id asic_id); + +#endif /* __DC_RESOURCE_DCE110_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c new file mode 100644 index 000000000000..b1c97125f6fb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -0,0 +1,1953 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dc_types.h" +#include "dc_bios_types.h" +#include "dc.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "dce110_timing_generator.h" + +#include "timing_generator.h" + + +#define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10 + +#define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1) +#define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1) + +#define CRTC_REG(reg) (reg + tg110->offsets.crtc) +#define DCP_REG(reg) (reg + tg110->offsets.dcp) + +/* Flowing register offsets are same in files of + * dce/dce_11_0_d.h + * dce/vi_polaris10_p/vi_polaris10_d.h + * + * So we can create dce110 timing generator to use it. + */ + + +/* +* apply_front_porch_workaround +* +* This is a workaround for a bug that has existed since R5xx and has not been +* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. +*/ +static void dce110_timing_generator_apply_front_porch_workaround( + struct timing_generator *tg, + struct dc_crtc_timing *timing) +{ + if (timing->flags.INTERLACE == 1) { + if (timing->v_front_porch < 2) + timing->v_front_porch = 2; + } else { + if (timing->v_front_porch < 1) + timing->v_front_porch = 1; + } +} + +/** + ***************************************************************************** + * Function: is_in_vertical_blank + * + * @brief + * check the current status of CRTC to check if we are in Vertical Blank + * regioneased" state + * + * @return + * true if currently in blank region, false otherwise + * + ***************************************************************************** + */ +static bool dce110_timing_generator_is_in_vertical_blank( + struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t value = 0; + uint32_t field = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + addr = CRTC_REG(mmCRTC_STATUS); + value = dm_read_reg(tg->ctx, addr); + field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK); + return field == 1; +} + +void dce110_timing_generator_set_early_control( + struct timing_generator *tg, + uint32_t early_cntl) +{ + uint32_t regval; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t address = CRTC_REG(mmCRTC_CONTROL); + + regval = dm_read_reg(tg->ctx, address); + set_reg_field_value(regval, early_cntl, + CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL); + dm_write_reg(tg->ctx, address, regval); +} + +/** + * Enable CRTC + * Enable CRTC - call ASIC Control Object to enable Timing generator. + */ +bool dce110_timing_generator_enable_crtc(struct timing_generator *tg) +{ + enum bp_result result; + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = 0; + + /* + * 3 is used to make sure V_UPDATE occurs at the beginning of the first + * line of vertical front porch + */ + set_reg_field_value( + value, + 0, + CRTC_MASTER_UPDATE_MODE, + MASTER_UPDATE_MODE); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value); + + /* TODO: may want this on to catch underflow */ + value = 0; + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK), value); + + result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true); + + return result == BP_RESULT_OK; +} + +void dce110_timing_generator_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR); + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + black_color->color_b_cb, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB); + set_reg_field_value( + value, + black_color->color_g_y, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_G_Y); + set_reg_field_value( + value, + black_color->color_r_cr, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_R_CR); + + dm_write_reg(tg->ctx, addr, value); +} + +/** + ***************************************************************************** + * Function: disable_stereo + * + * @brief + * Disables active stereo on controller + * Frame Packing need to be disabled in vBlank or when CRTC not running + ***************************************************************************** + */ +#if 0 +@TODOSTEREO +static void disable_stereo(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL); + uint32_t value = 0; + uint32_t test = 0; + uint32_t field = 0; + uint32_t struc_en = 0; + uint32_t struc_stereo_sel_ovr = 0; + + value = dm_read_reg(tg->ctx, addr); + struc_en = get_reg_field_value( + value, + CRTC_3D_STRUCTURE_CONTROL, + CRTC_3D_STRUCTURE_EN); + + struc_stereo_sel_ovr = get_reg_field_value( + value, + CRTC_3D_STRUCTURE_CONTROL, + CRTC_3D_STRUCTURE_STEREO_SEL_OVR); + + /* + * When disabling Frame Packing in 2 step mode, we need to program both + * registers at the same frame + * Programming it in the beginning of VActive makes sure we are ok + */ + + if (struc_en != 0 && struc_stereo_sel_ovr == 0) { + tg->funcs->wait_for_vblank(tg); + tg->funcs->wait_for_vactive(tg); + } + + value = 0; + dm_write_reg(tg->ctx, addr, value); + + addr = tg->regs[IDX_CRTC_STEREO_CONTROL]; + dm_write_reg(tg->ctx, addr, value); +} +#endif + +/** + * disable_crtc - call ASIC Control Object to disable Timing generator. + */ +bool dce110_timing_generator_disable_crtc(struct timing_generator *tg) +{ + enum bp_result result; + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false); + + /* Need to make sure stereo is disabled according to the DCE5.0 spec */ + + /* + * @TODOSTEREO call this when adding stereo support + * tg->funcs->disable_stereo(tg); + */ + + return result == BP_RESULT_OK; +} + +/** +* program_horz_count_by_2 +* Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise +* +*/ +static void program_horz_count_by_2( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t regval; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + regval = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_COUNT_CONTROL)); + + set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL, + CRTC_HORZ_COUNT_BY2_EN); + + if (timing->flags.HORZ_COUNT_BY_TWO) + set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL, + CRTC_HORZ_COUNT_BY2_EN); + + dm_write_reg(tg->ctx, + CRTC_REG(mmCRTC_COUNT_CONTROL), regval); +} + +/** + * program_timing_generator + * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition. + * Call ASIC Control Object to program Timings. + */ +bool dce110_timing_generator_program_timing_generator( + struct timing_generator *tg, + const struct dc_crtc_timing *dc_crtc_timing) +{ + enum bp_result result; + struct bp_hw_crtc_timing_parameters bp_params; + struct dc_crtc_timing patched_crtc_timing; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + uint32_t vsync_offset = dc_crtc_timing->v_border_bottom + + dc_crtc_timing->v_front_porch; + uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset; + + uint32_t hsync_offset = dc_crtc_timing->h_border_right + + dc_crtc_timing->h_front_porch; + uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset; + + memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters)); + + /* Due to an asic bug we need to apply the Front Porch workaround prior + * to programming the timing. + */ + + patched_crtc_timing = *dc_crtc_timing; + + dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing); + + bp_params.controller_id = tg110->controller_id; + + bp_params.h_total = patched_crtc_timing.h_total; + bp_params.h_addressable = + patched_crtc_timing.h_addressable; + bp_params.v_total = patched_crtc_timing.v_total; + bp_params.v_addressable = patched_crtc_timing.v_addressable; + + bp_params.h_sync_start = h_sync_start; + bp_params.h_sync_width = patched_crtc_timing.h_sync_width; + bp_params.v_sync_start = v_sync_start; + bp_params.v_sync_width = patched_crtc_timing.v_sync_width; + + /* Set overscan */ + bp_params.h_overscan_left = + patched_crtc_timing.h_border_left; + bp_params.h_overscan_right = + patched_crtc_timing.h_border_right; + bp_params.v_overscan_top = patched_crtc_timing.v_border_top; + bp_params.v_overscan_bottom = + patched_crtc_timing.v_border_bottom; + + /* Set flags */ + if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1) + bp_params.flags.HSYNC_POSITIVE_POLARITY = 1; + + if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1) + bp_params.flags.VSYNC_POSITIVE_POLARITY = 1; + + if (patched_crtc_timing.flags.INTERLACE == 1) + bp_params.flags.INTERLACE = 1; + + if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1) + bp_params.flags.HORZ_COUNT_BY_TWO = 1; + + result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params); + + program_horz_count_by_2(tg, &patched_crtc_timing); + + tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing); + + /* Enable stereo - only when we need to pack 3D frame. Other types + * of stereo handled in explicit call */ + + return result == BP_RESULT_OK; +} + +/** + ***************************************************************************** + * Function: set_drr + * + * @brief + * Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*. + * + * @param [in] pHwCrtcTiming: point to H + * wCrtcTiming struct + ***************************************************************************** + */ +void dce110_timing_generator_set_drr( + struct timing_generator *tg, + const struct drr_params *params) +{ + /* register values */ + uint32_t v_total_min = 0; + uint32_t v_total_max = 0; + uint32_t v_total_cntl = 0; + uint32_t static_screen_cntl = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + uint32_t addr = 0; + + addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); + v_total_min = dm_read_reg(tg->ctx, addr); + + addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); + v_total_max = dm_read_reg(tg->ctx, addr); + + addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); + v_total_cntl = dm_read_reg(tg->ctx, addr); + + addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); + static_screen_cntl = dm_read_reg(tg->ctx, addr); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + set_reg_field_value(v_total_max, + params->vertical_total_max - 1, + CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX); + + set_reg_field_value(v_total_min, + params->vertical_total_min - 1, + CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN); + + set_reg_field_value(v_total_cntl, + 1, + CRTC_V_TOTAL_CONTROL, + CRTC_V_TOTAL_MIN_SEL); + + set_reg_field_value(v_total_cntl, + 1, + CRTC_V_TOTAL_CONTROL, + CRTC_V_TOTAL_MAX_SEL); + + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_FORCE_LOCK_ON_EVENT); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_FORCE_LOCK_TO_MASTER_VSYNC); + + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_SET_V_TOTAL_MIN_MASK_EN); + + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_SET_V_TOTAL_MIN_MASK); + + set_reg_field_value(static_screen_cntl, + 0x180, + CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK); + } else { + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_SET_V_TOTAL_MIN_MASK); + set_reg_field_value(static_screen_cntl, + 0, + CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK); + set_reg_field_value(v_total_min, + 0, + CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN); + set_reg_field_value(v_total_max, + 0, + CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_V_TOTAL_MIN_SEL); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_V_TOTAL_MAX_SEL); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_FORCE_LOCK_ON_EVENT); + set_reg_field_value(v_total_cntl, + 0, + CRTC_V_TOTAL_CONTROL, + CRTC_FORCE_LOCK_TO_MASTER_VSYNC); + } + + addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); + dm_write_reg(tg->ctx, addr, v_total_min); + + addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); + dm_write_reg(tg->ctx, addr, v_total_max); + + addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); + dm_write_reg(tg->ctx, addr, v_total_cntl); + + addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); + dm_write_reg(tg->ctx, addr, static_screen_cntl); +} + +void dce110_timing_generator_set_static_screen_control( + struct timing_generator *tg, + uint32_t value) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t static_screen_cntl = 0; + uint32_t addr = 0; + + addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); + static_screen_cntl = dm_read_reg(tg->ctx, addr); + + set_reg_field_value(static_screen_cntl, + value, + CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK); + + set_reg_field_value(static_screen_cntl, + 2, + CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_FRAME_COUNT); + + dm_write_reg(tg->ctx, addr, static_screen_cntl); +} + +/* + * get_vblank_counter + * + * @brief + * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which + * holds the counter of frames. + * + * @param + * struct timing_generator *tg - [in] timing generator which controls the + * desired CRTC + * + * @return + * Counter of frames, which should equal to number of vblanks. + */ +uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT); + uint32_t value = dm_read_reg(tg->ctx, addr); + uint32_t field = get_reg_field_value( + value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT); + + return field; +} + +/** + ***************************************************************************** + * Function: dce110_get_crtc_positions + * + * @brief + * Returns CRTC vertical/horizontal counters + * + * @param [out] v_position, h_position + ***************************************************************************** + */ + +void dce110_timing_generator_get_crtc_positions( + struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position) +{ + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION)); + + *h_position = get_reg_field_value( + value, + CRTC_STATUS_POSITION, + CRTC_HORZ_COUNT); + + *v_position = get_reg_field_value( + value, + CRTC_STATUS_POSITION, + CRTC_VERT_COUNT); +} + +/** + ***************************************************************************** + * Function: get_crtc_scanoutpos + * + * @brief + * Returns CRTC vertical/horizontal counters + * + * @param [out] vpos, hpos + ***************************************************************************** + */ +uint32_t dce110_timing_generator_get_crtc_scanoutpos( + struct timing_generator *tg, + uint32_t *vbl, + uint32_t *position) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + /* TODO 1: Update the implementation once caller is updated + * WARNING!! This function is returning the whole register value + * because the caller is expecting it instead of proper vertical and + * horizontal position. This should be a temporary implementation + * until the caller is updated. */ + + /* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */ + + *vbl = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_V_BLANK_START_END)); + + *position = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_STATUS_POSITION)); + + /* @TODO: return value should indicate if current + * crtc is inside vblank*/ + return 0; +} + +/* TODO: is it safe to assume that mask/shift of Primary and Underlay + * are the same? + * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always + * guaranteed? */ +void dce110_timing_generator_program_blanking( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t vsync_offset = timing->v_border_bottom + + timing->v_front_porch; + uint32_t v_sync_start =timing->v_addressable + vsync_offset; + + uint32_t hsync_offset = timing->h_border_right + + timing->h_front_porch; + uint32_t h_sync_start = timing->h_addressable + hsync_offset; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + struct dc_context *ctx = tg->ctx; + uint32_t value = 0; + uint32_t addr = 0; + uint32_t tmp = 0; + + addr = CRTC_REG(mmCRTC_H_TOTAL); + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->h_total - 1, + CRTC_H_TOTAL, + CRTC_H_TOTAL); + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_V_TOTAL); + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->v_total - 1, + CRTC_V_TOTAL, + CRTC_V_TOTAL); + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_H_BLANK_START_END); + value = dm_read_reg(ctx, addr); + + tmp = timing->h_total - + (h_sync_start + timing->h_border_left); + + set_reg_field_value( + value, + tmp, + CRTC_H_BLANK_START_END, + CRTC_H_BLANK_END); + + tmp = tmp + timing->h_addressable + + timing->h_border_left + timing->h_border_right; + + set_reg_field_value( + value, + tmp, + CRTC_H_BLANK_START_END, + CRTC_H_BLANK_START); + + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_V_BLANK_START_END); + value = dm_read_reg(ctx, addr); + + tmp = timing->v_total - (v_sync_start + timing->v_border_top); + + set_reg_field_value( + value, + tmp, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_END); + + tmp = tmp + timing->v_addressable + timing->v_border_top + + timing->v_border_bottom; + + set_reg_field_value( + value, + tmp, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + + dm_write_reg(ctx, addr, value); +} + +void dce110_timing_generator_set_test_pattern( + struct timing_generator *tg, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth) +{ + struct dc_context *ctx = tg->ctx; + uint32_t value; + uint32_t addr; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + enum test_pattern_color_format bit_depth; + enum test_pattern_dyn_range dyn_range; + enum test_pattern_mode mode; + /* color ramp generator mixes 16-bits color */ + uint32_t src_bpc = 16; + /* requested bpc */ + uint32_t dst_bpc; + uint32_t index; + /* RGB values of the color bars. + * Produce two RGB colors: RGB0 - white (all Fs) + * and RGB1 - black (all 0s) + * (three RGB components for two colors) + */ + uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, + 0x0000, 0x0000}; + /* dest color (converted to the specified color format) */ + uint16_t dst_color[6]; + uint32_t inc_base; + + /* translate to bit depth */ + switch (color_depth) { + case COLOR_DEPTH_666: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; + break; + case COLOR_DEPTH_888: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + case COLOR_DEPTH_101010: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; + break; + case COLOR_DEPTH_121212: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; + break; + default: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + } + + switch (test_pattern) { + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: + { + dyn_range = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? + TEST_PATTERN_DYN_RANGE_CEA : + TEST_PATTERN_DYN_RANGE_VESA); + mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); + + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES); + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_HRES); + + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); + value = 0; + + set_reg_field_value( + value, + 1, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN); + + set_reg_field_value( + value, + mode, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_MODE); + + set_reg_field_value( + value, + dyn_range, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_DYNAMIC_RANGE); + set_reg_field_value( + value, + bit_depth, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_COLOR_FORMAT); + dm_write_reg(ctx, addr, value); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: + case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: + { + mode = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? + TEST_PATTERN_MODE_VERTICALBARS : + TEST_PATTERN_MODE_HORIZONTALBARS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* adjust color to the required colorFormat */ + for (index = 0; index < 6; index++) { + /* dst = 2^dstBpc * src / 2^srcBpc = src >> + * (srcBpc - dstBpc); + */ + dst_color[index] = + src_color[index] >> (src_bpc - dst_bpc); + /* CRTC_TEST_PATTERN_DATA has 16 bits, + * lowest 6 are hardwired to ZERO + * color bits should be left aligned aligned to MSB + * XXXXXXXXXX000000 for 10 bit, + * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 + */ + dst_color[index] <<= (16 - dst_bpc); + } + + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); + dm_write_reg(ctx, addr, value); + + /* We have to write the mask before data, similar to pipeline. + * For example, for 8 bpc, if we want RGB0 to be magenta, + * and RGB1 to be cyan, + * we need to make 7 writes: + * MASK DATA + * 000001 00000000 00000000 set mask to R0 + * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 + * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 + * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 + * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 + * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 + * 100000 11111111 00000000 B1 255, 0xFF00 + * + * we will make a loop of 6 in which we prepare the mask, + * then write, then prepare the color for next write. + * first iteration will write mask only, + * but each next iteration color prepared in + * previous iteration will be written within new mask, + * the last component will written separately, + * mask is not changing between 6th and 7th write + * and color will be prepared by last iteration + */ + + /* write color, color values mask in CRTC_TEST_PATTERN_MASK + * is B1, G1, R1, B0, G0, R0 + */ + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR); + for (index = 0; index < 6; index++) { + /* prepare color mask, first write PATTERN_DATA + * will have all zeros + */ + set_reg_field_value( + value, + (1 << index), + CRTC_TEST_PATTERN_COLOR, + CRTC_TEST_PATTERN_MASK); + /* write color component */ + dm_write_reg(ctx, addr, value); + /* prepare next color component, + * will be written in the next iteration + */ + set_reg_field_value( + value, + dst_color[index], + CRTC_TEST_PATTERN_COLOR, + CRTC_TEST_PATTERN_DATA); + } + /* write last color component, + * it's been already prepared in the loop + */ + dm_write_reg(ctx, addr, value); + + /* enable test pattern */ + addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); + value = 0; + + set_reg_field_value( + value, + 1, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN); + + set_reg_field_value( + value, + mode, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_MODE); + + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_DYNAMIC_RANGE); + + set_reg_field_value( + value, + bit_depth, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_COLOR_FORMAT); + + dm_write_reg(ctx, addr, value); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: + { + mode = (bit_depth == + TEST_PATTERN_COLOR_FORMAT_BPC_10 ? + TEST_PATTERN_MODE_DUALRAMP_RGB : + TEST_PATTERN_MODE_SINGLERAMP_RGB); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* increment for the first ramp for one color gradation + * 1 gradation for 6-bit color is 2^10 + * gradations in 16-bit color + */ + inc_base = (src_bpc - dst_bpc); + + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + { + set_reg_field_value( + value, + inc_base, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0); + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC1); + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_HRES); + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES); + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_RAMP0_OFFSET); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + { + set_reg_field_value( + value, + inc_base, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0); + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC1); + set_reg_field_value( + value, + 8, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_HRES); + set_reg_field_value( + value, + 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES); + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_RAMP0_OFFSET); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + { + set_reg_field_value( + value, + inc_base, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0); + set_reg_field_value( + value, + inc_base + 2, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC1); + set_reg_field_value( + value, + 8, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_HRES); + set_reg_field_value( + value, + 5, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES); + set_reg_field_value( + value, + 384 << 6, + CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_RAMP0_OFFSET); + } + break; + default: + break; + } + dm_write_reg(ctx, addr, value); + + value = 0; + addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR); + dm_write_reg(ctx, addr, value); + + /* enable test pattern */ + addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL); + value = 0; + + set_reg_field_value( + value, + 1, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN); + + set_reg_field_value( + value, + mode, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_MODE); + + set_reg_field_value( + value, + 0, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_DYNAMIC_RANGE); + /* add color depth translation here */ + set_reg_field_value( + value, + bit_depth, + CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_COLOR_FORMAT); + + dm_write_reg(ctx, addr, value); + } + break; + case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: + { + value = 0; + dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL), value); + dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_COLOR), value); + dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS), + value); + } + break; + default: + break; + } +} + +/** +* dce110_timing_generator_validate_timing +* The timing generators support a maximum display size of is 8192 x 8192 pixels, +* including both active display and blanking periods. Check H Total and V Total. +*/ +bool dce110_timing_generator_validate_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *timing, + enum signal_type signal) +{ + uint32_t h_blank; + uint32_t h_back_porch; + uint32_t hsync_offset = timing->h_border_right + + timing->h_front_porch; + uint32_t h_sync_start = timing->h_addressable + hsync_offset; + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + ASSERT(timing != NULL); + + if (!timing) + return false; + + /* Check maximum number of pixels supported by Timing Generator + * (Currently will never fail, in order to fail needs display which + * needs more than 8192 horizontal and + * more than 8192 vertical total pixels) + */ + if (timing->h_total > tg110->max_h_total || + timing->v_total > tg110->max_v_total) + return false; + + h_blank = (timing->h_total - timing->h_addressable - + timing->h_border_right - + timing->h_border_left); + + if (h_blank < tg110->min_h_blank) + return false; + + if (timing->h_front_porch < tg110->min_h_front_porch) + return false; + + h_back_porch = h_blank - (h_sync_start - + timing->h_addressable - + timing->h_border_right - + timing->h_sync_width); + + if (h_back_porch < tg110->min_h_back_porch) + return false; + + return true; +} + +/** +* Wait till we are at the beginning of VBlank. +*/ +void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg) +{ + /* We want to catch beginning of VBlank here, so if the first try are + * in VBlank, we might be very close to Active, in this case wait for + * another frame + */ + while (dce110_timing_generator_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } + + while (!dce110_timing_generator_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/** +* Wait till we are in VActive (anywhere in VActive) +*/ +void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg) +{ + while (dce110_timing_generator_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/** + ***************************************************************************** + * Function: dce110_timing_generator_setup_global_swap_lock + * + * @brief + * Setups Global Swap Lock group for current pipe + * Pipe can join or leave GSL group, become a TimingServer or TimingClient + * + * @param [in] gsl_params: setup data + ***************************************************************************** + */ + +void dce110_timing_generator_setup_global_swap_lock( + struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params) +{ + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t address = DCP_REG(mmDCP_GSL_CONTROL); + uint32_t check_point = FLIP_READY_BACK_LOOKUP; + + value = dm_read_reg(tg->ctx, address); + + /* This pipe will belong to GSL Group zero. */ + set_reg_field_value(value, + 1, + DCP_GSL_CONTROL, + DCP_GSL0_EN); + + set_reg_field_value(value, + gsl_params->gsl_master == tg->inst, + DCP_GSL_CONTROL, + DCP_GSL_MASTER_EN); + + set_reg_field_value(value, + HFLIP_READY_DELAY, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_FORCE_DELAY); + + /* Keep signal low (pending high) during 6 lines. + * Also defines minimum interval before re-checking signal. */ + set_reg_field_value(value, + HFLIP_CHECK_DELAY, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_CHECK_DELAY); + + + { + uint32_t value_crtc_vtotal; + + value_crtc_vtotal = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_V_TOTAL)); + + set_reg_field_value(value, + 0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */ + DCP_GSL_CONTROL, + DCP_GSL_SYNC_SOURCE); + + /* Checkpoint relative to end of frame */ + check_point = get_reg_field_value(value_crtc_vtotal, + CRTC_V_TOTAL, + CRTC_V_TOTAL); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0); + } + + set_reg_field_value(value, + 1, + DCP_GSL_CONTROL, + DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); + + dm_write_reg(tg->ctx, address, value); + + /********************************************************************/ + address = CRTC_REG(mmCRTC_GSL_CONTROL); + + value = 0; + set_reg_field_value(value, + check_point - FLIP_READY_BACK_LOOKUP, + CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM); + + set_reg_field_value(value, + VFLIP_READY_DELAY, + CRTC_GSL_CONTROL, + CRTC_GSL_FORCE_DELAY); + + dm_write_reg(tg->ctx, address, value); +} + +void dce110_timing_generator_tear_down_global_swap_lock( + struct timing_generator *tg) +{ + /* Clear all the register writes done by + * dce110_timing_generator_setup_global_swap_lock + */ + + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t address = DCP_REG(mmDCP_GSL_CONTROL); + + value = 0; + + /* This pipe will belong to GSL Group zero. */ + /* Settig HW default values from reg specs */ + set_reg_field_value(value, + 0, + DCP_GSL_CONTROL, + DCP_GSL0_EN); + + set_reg_field_value(value, + 0, + DCP_GSL_CONTROL, + DCP_GSL_MASTER_EN); + + set_reg_field_value(value, + 0x2, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_FORCE_DELAY); + + set_reg_field_value(value, + 0x6, + DCP_GSL_CONTROL, + DCP_GSL_HSYNC_FLIP_CHECK_DELAY); + + /* Restore DCP_GSL_PURPOSE_SURFACE_FLIP */ + { + uint32_t value_crtc_vtotal; + + value_crtc_vtotal = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_V_TOTAL)); + + set_reg_field_value(value, + 0, + DCP_GSL_CONTROL, + DCP_GSL_SYNC_SOURCE); + } + + set_reg_field_value(value, + 0, + DCP_GSL_CONTROL, + DCP_GSL_DELAY_SURFACE_UPDATE_PENDING); + + dm_write_reg(tg->ctx, address, value); + + /********************************************************************/ + address = CRTC_REG(mmCRTC_GSL_CONTROL); + + value = 0; + set_reg_field_value(value, + 0, + CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM); + + set_reg_field_value(value, + 0x2, + CRTC_GSL_CONTROL, + CRTC_GSL_FORCE_DELAY); + + dm_write_reg(tg->ctx, address, value); +} +/** + ***************************************************************************** + * Function: is_counter_moving + * + * @brief + * check if the timing generator is currently going + * + * @return + * true if currently going, false if currently paused or stopped. + * + ***************************************************************************** + */ +bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg) +{ + uint32_t h1 = 0; + uint32_t h2 = 0; + uint32_t v1 = 0; + uint32_t v2 = 0; + + tg->funcs->get_position(tg, &h1, &v1); + tg->funcs->get_position(tg, &h2, &v2); + + if (h1 == h2 && v1 == v2) + return false; + else + return true; +} + +void dce110_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL); + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (enable) { + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + if ((timing->v_sync_width + timing->v_front_porch) <= 3) { + set_reg_field_value( + value, + 3, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } else { + set_reg_field_value( + value, + 4, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PROGRESSIVE_START_LINE_EARLY); + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_INTERLACE_START_LINE_EARLY); + + dm_write_reg(tg->ctx, addr, value); +} + +/*TODO: Figure out if we need this function. */ +void dce110_timing_generator_set_lock_master(struct timing_generator *tg, + bool lock) +{ + struct dc_context *ctx = tg->ctx; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + lock ? 1 : 0, + CRTC_MASTER_UPDATE_LOCK, + MASTER_UPDATE_LOCK); + + dm_write_reg(ctx, addr, value); +} + +void dce110_timing_generator_enable_reset_trigger( + struct timing_generator *tg, + int source_tg_inst) +{ + uint32_t value; + uint32_t rising_edge = 0; + uint32_t falling_edge = 0; + enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + /* Setup trigger edge */ + { + uint32_t pol_value = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_V_SYNC_A_CNTL)); + + /* Register spec has reversed definition: + * 0 for positive, 1 for negative */ + if (get_reg_field_value(pol_value, + CRTC_V_SYNC_A_CNTL, + CRTC_V_SYNC_A_POL) == 0) { + rising_edge = 1; + } else { + falling_edge = 1; + } + } + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); + + trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0; + + set_reg_field_value(value, + trig_src_select, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT); + + set_reg_field_value(value, + TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_POLARITY_SELECT); + + set_reg_field_value(value, + rising_edge, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_RISING_EDGE_DETECT_CNTL); + + set_reg_field_value(value, + falling_edge, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL); + + set_reg_field_value(value, + 0, /* send every signal */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_FREQUENCY_SELECT); + + set_reg_field_value(value, + 0, /* no delay */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_DELAY); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); + + /**************************************************************/ + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + set_reg_field_value(value, + 2, /* force H count to H_TOTAL and V count to V_TOTAL */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); + + set_reg_field_value(value, + 1, /* TriggerB - we never use TriggerA */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_TRIG_SEL); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); +} + +void dce110_timing_generator_disable_reset_trigger( + struct timing_generator *tg) +{ + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + set_reg_field_value(value, + 0, /* force counter now mode is disabled */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value); + + /********************************************************************/ + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL)); + + set_reg_field_value(value, + TRIGGER_SOURCE_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT); + + set_reg_field_value(value, + TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + CRTC_TRIGB_CNTL, + CRTC_TRIGB_POLARITY_SELECT); + + set_reg_field_value(value, + 1, /* clear trigger status */ + CRTC_TRIGB_CNTL, + CRTC_TRIGB_CLEAR); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value); +} + +/** + ***************************************************************************** + * @brief + * Checks whether CRTC triggered reset occurred + * + * @return + * true if triggered reset occurred, false otherwise + ***************************************************************************** + */ +bool dce110_timing_generator_did_triggered_reset_occur( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg(tg->ctx, + CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL)); + + return get_reg_field_value(value, + CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; +} + +/** + * dce110_timing_generator_disable_vga + * Turn OFF VGA Mode and Timing - DxVGA_CONTROL + * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors; + */ +void dce110_timing_generator_disable_vga( + struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t value = 0; + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + switch (tg110->controller_id) { + case CONTROLLER_ID_D0: + addr = mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D1: + addr = mmD2VGA_CONTROL; + break; + case CONTROLLER_ID_D2: + addr = mmD3VGA_CONTROL; + break; + case CONTROLLER_ID_D3: + addr = mmD4VGA_CONTROL; + break; + case CONTROLLER_ID_D4: + addr = mmD5VGA_CONTROL; + break; + case CONTROLLER_ID_D5: + addr = mmD6VGA_CONTROL; + break; + default: + break; + } + value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE); + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT); + set_reg_field_value( + value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT); + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN); + + dm_write_reg(tg->ctx, addr, value); +} + +/** +* set_overscan_color_black +* +* @param :black_color is one of the color space +* :this routine will set overscan black color according to the color space. +* @return none +*/ + +void dce110_timing_generator_set_overscan_color_black( + struct timing_generator *tg, + const struct tg_color *color) +{ + struct dc_context *ctx = tg->ctx; + uint32_t addr; + uint32_t value = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + set_reg_field_value( + value, + color->color_b_cb, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE); + + set_reg_field_value( + value, + color->color_r_cr, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_RED); + + set_reg_field_value( + value, + color->color_g_y, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_GREEN); + + addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR); + dm_write_reg(ctx, addr, value); + addr = CRTC_REG(mmCRTC_BLACK_COLOR); + dm_write_reg(ctx, addr, value); + /* This is desirable to have a constant DAC output voltage during the + * blank time that is higher than the 0 volt reference level that the + * DAC outputs when the NBLANK signal + * is asserted low, such as for output to an analog TV. */ + addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR); + dm_write_reg(ctx, addr, value); + + /* TO DO we have to program EXT registers and we need to know LB DATA + * format because it is used when more 10 , i.e. 12 bits per color + * + * m_mmDxCRTC_OVERSCAN_COLOR_EXT + * m_mmDxCRTC_BLACK_COLOR_EXT + * m_mmDxCRTC_BLANK_DATA_COLOR_EXT + */ + +} + +void dce110_tg_program_blank_color(struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR); + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + black_color->color_b_cb, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB); + set_reg_field_value( + value, + black_color->color_g_y, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_G_Y); + set_reg_field_value( + value, + black_color->color_r_cr, + CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_R_CR); + + dm_write_reg(tg->ctx, addr, value); + + addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR); + dm_write_reg(tg->ctx, addr, value); +} + +void dce110_tg_set_overscan_color(struct timing_generator *tg, + const struct tg_color *overscan_color) +{ + struct dc_context *ctx = tg->ctx; + uint32_t value = 0; + uint32_t addr; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + set_reg_field_value( + value, + overscan_color->color_b_cb, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE); + + set_reg_field_value( + value, + overscan_color->color_g_y, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_GREEN); + + set_reg_field_value( + value, + overscan_color->color_r_cr, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_RED); + + addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR); + dm_write_reg(ctx, addr, value); +} + +void dce110_tg_get_position(struct timing_generator *tg, + struct crtc_position *position) +{ + int32_t h_position; + int32_t v_position; + + dce110_timing_generator_get_crtc_positions(tg, &h_position, &v_position); + + position->horizontal_count = (uint32_t)h_position; + position->vertical_count = (uint32_t)v_position; +} + +void dce110_tg_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + if (use_vbios) + dce110_timing_generator_program_timing_generator(tg, timing); + else + dce110_timing_generator_program_blanking(tg, timing); +} + +bool dce110_tg_is_blanked(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL)); + + if (get_reg_field_value( + value, + CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTC_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) + return true; + return false; +} + +bool dce110_tg_set_blank(struct timing_generator *tg, + bool enable_blanking) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = 0; + + set_reg_field_value( + value, + 1, + CRTC_DOUBLE_BUFFER_CONTROL, + CRTC_BLANK_DATA_DOUBLE_BUFFER_EN); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_DOUBLE_BUFFER_CONTROL), value); + value = 0; + + if (enable_blanking) { + int counter; + + set_reg_field_value( + value, + 1, + CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value); + + for (counter = 0; counter < 100; counter++) { + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL)); + + if (get_reg_field_value( + value, + CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTC_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) + break; + + msleep(1); + } + + if (counter == 100) { + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "timing generator %d blank timing out.\n", + tg110->controller_id); + return false; + } + } else + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0); + + return true; +} + +bool dce110_tg_validate_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE); +} + +void dce110_tg_wait_for_state(struct timing_generator *tg, + enum crtc_state state) +{ + switch (state) { + case CRTC_STATE_VBLANK: + dce110_timing_generator_wait_for_vblank(tg); + break; + + case CRTC_STATE_VACTIVE: + dce110_timing_generator_wait_for_vactive(tg); + break; + + default: + break; + } +} + +void dce110_tg_set_colors(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color) +{ + if (blank_color != NULL) + dce110_tg_program_blank_color(tg, blank_color); + if (overscan_color != NULL) + dce110_tg_set_overscan_color(tg, overscan_color); +} + +static const struct timing_generator_funcs dce110_tg_funcs = { + .validate_timing = dce110_tg_validate_timing, + .program_timing = dce110_tg_program_timing, + .enable_crtc = dce110_timing_generator_enable_crtc, + .disable_crtc = dce110_timing_generator_disable_crtc, + .is_counter_moving = dce110_timing_generator_is_counter_moving, + .get_position = dce110_timing_generator_get_crtc_positions, + .get_frame_count = dce110_timing_generator_get_vblank_counter, + .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, + .set_early_control = dce110_timing_generator_set_early_control, + .wait_for_state = dce110_tg_wait_for_state, + .set_blank = dce110_tg_set_blank, + .is_blanked = dce110_tg_is_blanked, + .set_colors = dce110_tg_set_colors, + .set_overscan_blank_color = + dce110_timing_generator_set_overscan_color_black, + .set_blank_color = dce110_timing_generator_program_blank_color, + .disable_vga = dce110_timing_generator_disable_vga, + .did_triggered_reset_occur = + dce110_timing_generator_did_triggered_reset_occur, + .setup_global_swap_lock = + dce110_timing_generator_setup_global_swap_lock, + .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, + .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, + .tear_down_global_swap_lock = + dce110_timing_generator_tear_down_global_swap_lock, + .enable_advanced_request = + dce110_timing_generator_enable_advanced_request, + .set_drr = + dce110_timing_generator_set_drr, + .set_static_screen_control = + dce110_timing_generator_set_static_screen_control, + .set_test_pattern = dce110_timing_generator_set_test_pattern + +}; + +bool dce110_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + if (!tg110) + return false; + + tg110->controller_id = CONTROLLER_ID_D0 + instance; + tg110->base.inst = instance; + + tg110->offsets = *offsets; + + tg110->base.funcs = &dce110_tg_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + tg110->min_h_blank = 56; + tg110->min_h_front_porch = 4; + tg110->min_h_back_porch = 4; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h new file mode 100644 index 000000000000..39906502ad5c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -0,0 +1,273 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCE110_H__ +#define __DC_TIMING_GENERATOR_DCE110_H__ + +#include "timing_generator.h" +#include "../include/grph_object_id.h" +#include "../include/hw_sequencer_types.h" + +/* GSL Sync related values */ + +/* In VSync mode, after 4 units of time, master pipe will generate + * flip_ready signal */ +#define VFLIP_READY_DELAY 4 +/* In HSync mode, after 2 units of time, master pipe will generate + * flip_ready signal */ +#define HFLIP_READY_DELAY 2 +/* 6 lines delay between forcing flip and checking all pipes ready */ +#define HFLIP_CHECK_DELAY 6 +/* 3 lines before end of frame */ +#define FLIP_READY_BACK_LOOKUP 3 + +/* Trigger Source Select - ASIC-defendant, actual values for the + * register programming */ +enum trigger_source_select { + TRIGGER_SOURCE_SELECT_LOGIC_ZERO = 0, + TRIGGER_SOURCE_SELECT_CRTC_VSYNCA = 1, + TRIGGER_SOURCE_SELECT_CRTC_HSYNCA = 2, + TRIGGER_SOURCE_SELECT_CRTC_VSYNCB = 3, + TRIGGER_SOURCE_SELECT_CRTC_HSYNCB = 4, + TRIGGER_SOURCE_SELECT_GENERICF = 5, + TRIGGER_SOURCE_SELECT_GENERICE = 6, + TRIGGER_SOURCE_SELECT_VSYNCA = 7, + TRIGGER_SOURCE_SELECT_HSYNCA = 8, + TRIGGER_SOURCE_SELECT_VSYNCB = 9, + TRIGGER_SOURCE_SELECT_HSYNCB = 10, + TRIGGER_SOURCE_SELECT_HPD1 = 11, + TRIGGER_SOURCE_SELECT_HPD2 = 12, + TRIGGER_SOURCE_SELECT_GENERICD = 13, + TRIGGER_SOURCE_SELECT_GENERICC = 14, + TRIGGER_SOURCE_SELECT_VIDEO_CAPTURE = 15, + TRIGGER_SOURCE_SELECT_GSL_GROUP0 = 16, + TRIGGER_SOURCE_SELECT_GSL_GROUP1 = 17, + TRIGGER_SOURCE_SELECT_GSL_GROUP2 = 18, + TRIGGER_SOURCE_SELECT_BLONY = 19, + TRIGGER_SOURCE_SELECT_GENERICA = 20, + TRIGGER_SOURCE_SELECT_GENERICB = 21, + TRIGGER_SOURCE_SELECT_GSL_ALLOW_FLIP = 22, + TRIGGER_SOURCE_SELECT_MANUAL_TRIGGER = 23 +}; + +/* Trigger Source Select - ASIC-dependant, actual values for the + * register programming */ +enum trigger_polarity_select { + TRIGGER_POLARITY_SELECT_LOGIC_ZERO = 0, + TRIGGER_POLARITY_SELECT_CRTC = 1, + TRIGGER_POLARITY_SELECT_GENERICA = 2, + TRIGGER_POLARITY_SELECT_GENERICB = 3, + TRIGGER_POLARITY_SELECT_HSYNCA = 4, + TRIGGER_POLARITY_SELECT_HSYNCB = 5, + TRIGGER_POLARITY_SELECT_VIDEO_CAPTURE = 6, + TRIGGER_POLARITY_SELECT_GENERICC = 7 +}; + + +struct dce110_timing_generator_offsets { + int32_t crtc; + int32_t dcp; + + /* DCE80 use only */ + int32_t dmif; +}; + +struct dce110_timing_generator { + struct timing_generator base; + struct dce110_timing_generator_offsets offsets; + struct dce110_timing_generator_offsets derived_offsets; + + enum controller_id controller_id; + + uint32_t max_h_total; + uint32_t max_v_total; + + uint32_t min_h_blank; + uint32_t min_h_front_porch; + uint32_t min_h_back_porch; + + uint32_t min_h_sync_width; + uint32_t min_v_sync_width; + uint32_t min_v_blank; + +}; + +#define DCE110TG_FROM_TG(tg)\ + container_of(tg, struct dce110_timing_generator, base) + +bool dce110_timing_generator_construct( + struct dce110_timing_generator *tg, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets); + +/* determine if given timing can be supported by TG */ +bool dce110_timing_generator_validate_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *timing, + enum signal_type signal); + +/******** HW programming ************/ + +/* Program timing generator with given timing */ +bool dce110_timing_generator_program_timing_generator( + struct timing_generator *tg, + const struct dc_crtc_timing *dc_crtc_timing); + +/* Disable/Enable Timing Generator */ +bool dce110_timing_generator_enable_crtc(struct timing_generator *tg); +bool dce110_timing_generator_disable_crtc(struct timing_generator *tg); + +void dce110_timing_generator_set_early_control( + struct timing_generator *tg, + uint32_t early_cntl); + +/**************** TG current status ******************/ + +/* return the current frame counter. Used by Linux kernel DRM */ +uint32_t dce110_timing_generator_get_vblank_counter( + struct timing_generator *tg); + +/* Get current H and V position */ +void dce110_timing_generator_get_crtc_positions( + struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position); + +/* return true if TG counter is moving. false if TG is stopped */ +bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg); + +/* wait until TG is in beginning of vertical blank region */ +void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg); + +/* wait until TG is in beginning of active region */ +void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg); + +/*********** Timing Generator Synchronization routines ****/ + +/* Setups Global Swap Lock group, TimingServer or TimingClient*/ +void dce110_timing_generator_setup_global_swap_lock( + struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params); + +/* Clear all the register writes done by setup_global_swap_lock */ +void dce110_timing_generator_tear_down_global_swap_lock( + struct timing_generator *tg); + +/* Reset slave controllers on master VSync */ +void dce110_timing_generator_enable_reset_trigger( + struct timing_generator *tg, + int source); + +/* disabling trigger-reset */ +void dce110_timing_generator_disable_reset_trigger( + struct timing_generator *tg); + +/* Checks whether CRTC triggered reset occurred */ +bool dce110_timing_generator_did_triggered_reset_occur( + struct timing_generator *tg); + +/******** Stuff to move to other virtual HW objects *****************/ +/* Move to enable accelerated mode */ +void dce110_timing_generator_disable_vga(struct timing_generator *tg); +/* TODO: Should we move it to transform */ +/* Fully program CRTC timing in timing generator */ +void dce110_timing_generator_program_blanking( + struct timing_generator *tg, + const struct dc_crtc_timing *timing); + +/* TODO: Should we move it to opp? */ +/* Combine with below and move YUV/RGB color conversion to SW layer */ +void dce110_timing_generator_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color); +/* Combine with above and move YUV/RGB color conversion to SW layer */ +void dce110_timing_generator_set_overscan_color_black( + struct timing_generator *tg, + const struct tg_color *color); +void dce110_timing_generator_color_space_to_black_color( + enum dc_color_space colorspace, + struct tg_color *black_color); +/*************** End-of-move ********************/ + +/* Not called yet */ +void dce110_timing_generator_set_test_pattern( + struct timing_generator *tg, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth); + +void dce110_timing_generator_set_drr( + struct timing_generator *tg, + const struct drr_params *params); + +void dce110_timing_generator_set_static_screen_control( + struct timing_generator *tg, + uint32_t value); + +uint32_t dce110_timing_generator_get_crtc_scanoutpos( + struct timing_generator *tg, + uint32_t *vbl, + uint32_t *position); + +void dce110_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing); + +void dce110_timing_generator_set_lock_master(struct timing_generator *tg, + bool lock); + +void dce110_tg_program_blank_color(struct timing_generator *tg, + const struct tg_color *black_color); + +void dce110_tg_set_overscan_color(struct timing_generator *tg, + const struct tg_color *overscan_color); + +void dce110_tg_get_position(struct timing_generator *tg, + struct crtc_position *position); + +void dce110_tg_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios); + +bool dce110_tg_is_blanked(struct timing_generator *tg); + +bool dce110_tg_set_blank(struct timing_generator *tg, + bool enable_blanking); + +bool dce110_tg_validate_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing); + +void dce110_tg_wait_for_state(struct timing_generator *tg, + enum crtc_state state); + +void dce110_tg_set_colors(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color); + +#endif /* __DC_TIMING_GENERATOR_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c new file mode 100644 index 000000000000..3bf3179e07c5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -0,0 +1,743 @@ +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "dc_types.h" +#include "dc_bios_types.h" +#include "dc.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "dce110_timing_generator.h" +#include "dce110_timing_generator_v.h" + +#include "timing_generator.h" + +/** ******************************************************************************** + * + * DCE11 Timing Generator Implementation + * + **********************************************************************************/ + +/** +* Enable CRTCV +*/ + +static bool dce110_timing_generator_v_enable_crtc(struct timing_generator *tg) +{ +/* +* Set MASTER_UPDATE_MODE to 0 +* This is needed for DRR, and also suggested to be default value by Syed. +*/ + + uint32_t value; + + value = 0; + set_reg_field_value(value, 0, + CRTCV_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE); + dm_write_reg(tg->ctx, + mmCRTCV_MASTER_UPDATE_MODE, value); + + /* TODO: may want this on for looking for underflow */ + value = 0; + dm_write_reg(tg->ctx, mmCRTCV_MASTER_UPDATE_MODE, value); + + value = 0; + set_reg_field_value(value, 1, + CRTCV_MASTER_EN, CRTC_MASTER_EN); + dm_write_reg(tg->ctx, + mmCRTCV_MASTER_EN, value); + + return true; +} + +static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg) +{ + uint32_t value; + + value = dm_read_reg(tg->ctx, + mmCRTCV_CONTROL); + set_reg_field_value(value, 0, + CRTCV_CONTROL, CRTC_DISABLE_POINT_CNTL); + set_reg_field_value(value, 0, + CRTCV_CONTROL, CRTC_MASTER_EN); + dm_write_reg(tg->ctx, + mmCRTCV_CONTROL, value); + /* + * TODO: call this when adding stereo support + * tg->funcs->disable_stereo(tg); + */ + return true; +} + +static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = mmCRTCV_BLANK_CONTROL; + uint32_t value = dm_read_reg(tg->ctx, addr); + uint8_t counter = 100; + + set_reg_field_value( + value, + 1, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DATA_EN); + + set_reg_field_value( + value, + 0, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DE_MODE); + + dm_write_reg(tg->ctx, addr, value); + + while (counter > 0) { + value = dm_read_reg(tg->ctx, addr); + + if (get_reg_field_value( + value, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTCV_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) + break; + + msleep(1); + counter--; + } + + if (!counter) { + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "timing generator %d blank timing out.\n", + tg110->controller_id); + return false; + } + + return true; +} + +static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) +{ + uint32_t addr = mmCRTCV_BLANK_CONTROL; + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + 0, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DATA_EN); + + set_reg_field_value( + value, + 0, + CRTCV_BLANK_CONTROL, + CRTC_BLANK_DE_MODE); + + dm_write_reg(tg->ctx, addr, value); + + return true; +} + +static bool dce110_timing_generator_v_is_in_vertical_blank( + struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t value = 0; + uint32_t field = 0; + + addr = mmCRTCV_STATUS; + value = dm_read_reg(tg->ctx, addr); + field = get_reg_field_value(value, CRTCV_STATUS, CRTC_V_BLANK); + return field == 1; +} + +static bool dce110_timing_generator_v_is_counter_moving(struct timing_generator *tg) +{ + uint32_t value; + uint32_t h1 = 0; + uint32_t h2 = 0; + uint32_t v1 = 0; + uint32_t v2 = 0; + + value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION); + + h1 = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_HORZ_COUNT); + + v1 = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_VERT_COUNT); + + value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION); + + h2 = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_HORZ_COUNT); + + v2 = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_VERT_COUNT); + + if (h1 == h2 && v1 == v2) + return false; + else + return true; +} + +static void dce110_timing_generator_v_wait_for_vblank(struct timing_generator *tg) +{ + /* We want to catch beginning of VBlank here, so if the first try are + * in VBlank, we might be very close to Active, in this case wait for + * another frame + */ + while (dce110_timing_generator_v_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_v_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } + + while (!dce110_timing_generator_v_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_v_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/** +* Wait till we are in VActive (anywhere in VActive) +*/ +static void dce110_timing_generator_v_wait_for_vactive(struct timing_generator *tg) +{ + while (dce110_timing_generator_v_is_in_vertical_blank(tg)) { + if (!dce110_timing_generator_v_is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +static void dce110_timing_generator_v_wait_for_state(struct timing_generator *tg, + enum crtc_state state) +{ + switch (state) { + case CRTC_STATE_VBLANK: + dce110_timing_generator_v_wait_for_vblank(tg); + break; + + case CRTC_STATE_VACTIVE: + dce110_timing_generator_v_wait_for_vactive(tg); + break; + + default: + break; + } +} + +static void dce110_timing_generator_v_program_blanking( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t vsync_offset = timing->v_border_bottom + + timing->v_front_porch; + uint32_t v_sync_start = timing->v_addressable + vsync_offset; + + uint32_t hsync_offset = timing->h_border_right + + timing->h_front_porch; + uint32_t h_sync_start = timing->h_addressable + hsync_offset; + + struct dc_context *ctx = tg->ctx; + uint32_t value = 0; + uint32_t addr = 0; + uint32_t tmp = 0; + + addr = mmCRTCV_H_TOTAL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->h_total - 1, + CRTCV_H_TOTAL, + CRTC_H_TOTAL); + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_V_TOTAL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->v_total - 1, + CRTCV_V_TOTAL, + CRTC_V_TOTAL); + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_H_BLANK_START_END; + value = dm_read_reg(ctx, addr); + + tmp = timing->h_total - + (h_sync_start + timing->h_border_left); + + set_reg_field_value( + value, + tmp, + CRTCV_H_BLANK_START_END, + CRTC_H_BLANK_END); + + tmp = tmp + timing->h_addressable + + timing->h_border_left + timing->h_border_right; + + set_reg_field_value( + value, + tmp, + CRTCV_H_BLANK_START_END, + CRTC_H_BLANK_START); + + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_V_BLANK_START_END; + value = dm_read_reg(ctx, addr); + + tmp = timing->v_total - (v_sync_start + timing->v_border_top); + + set_reg_field_value( + value, + tmp, + CRTCV_V_BLANK_START_END, + CRTC_V_BLANK_END); + + tmp = tmp + timing->v_addressable + timing->v_border_top + + timing->v_border_bottom; + + set_reg_field_value( + value, + tmp, + CRTCV_V_BLANK_START_END, + CRTC_V_BLANK_START); + + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_H_SYNC_A; + value = 0; + set_reg_field_value( + value, + timing->h_sync_width, + CRTCV_H_SYNC_A, + CRTC_H_SYNC_A_END); + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_H_SYNC_A_CNTL; + value = dm_read_reg(ctx, addr); + if (timing->flags.HSYNC_POSITIVE_POLARITY) { + set_reg_field_value( + value, + 0, + CRTCV_H_SYNC_A_CNTL, + CRTC_H_SYNC_A_POL); + } else { + set_reg_field_value( + value, + 1, + CRTCV_H_SYNC_A_CNTL, + CRTC_H_SYNC_A_POL); + } + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_V_SYNC_A; + value = 0; + set_reg_field_value( + value, + timing->v_sync_width, + CRTCV_V_SYNC_A, + CRTC_V_SYNC_A_END); + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_V_SYNC_A_CNTL; + value = dm_read_reg(ctx, addr); + if (timing->flags.VSYNC_POSITIVE_POLARITY) { + set_reg_field_value( + value, + 0, + CRTCV_V_SYNC_A_CNTL, + CRTC_V_SYNC_A_POL); + } else { + set_reg_field_value( + value, + 1, + CRTCV_V_SYNC_A_CNTL, + CRTC_V_SYNC_A_POL); + } + dm_write_reg(ctx, addr, value); + + addr = mmCRTCV_INTERLACE_CONTROL; + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->flags.INTERLACE, + CRTCV_INTERLACE_CONTROL, + CRTC_INTERLACE_ENABLE); + dm_write_reg(ctx, addr, value); +} + +static void dce110_timing_generator_v_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + uint32_t addr = mmCRTCV_START_LINE_CONTROL; + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (enable) { + if ((timing->v_sync_width + timing->v_front_porch) <= 3) { + set_reg_field_value( + value, + 3, + CRTCV_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + } else { + set_reg_field_value( + value, + 4, + CRTCV_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + } + set_reg_field_value( + value, + 0, + CRTCV_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 2, + CRTCV_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 1, + CRTCV_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + dm_write_reg(tg->ctx, addr, value); +} + +static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg, + bool enable_blanking) +{ + if (enable_blanking) + return dce110_timing_generator_v_blank_crtc(tg); + else + return dce110_timing_generator_v_unblank_crtc(tg); +} + +static void dce110_timing_generator_v_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + if (use_vbios) + dce110_timing_generator_program_timing_generator(tg, timing); + else + dce110_timing_generator_v_program_blanking(tg, timing); +} + +static void dce110_timing_generator_v_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color) +{ + uint32_t addr = mmCRTCV_BLACK_COLOR; + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + black_color->color_b_cb, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB); + set_reg_field_value( + value, + black_color->color_g_y, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_G_Y); + set_reg_field_value( + value, + black_color->color_r_cr, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_R_CR); + + dm_write_reg(tg->ctx, addr, value); +} + +static void dce110_timing_generator_v_set_overscan_color_black( + struct timing_generator *tg, + const struct tg_color *color) +{ + struct dc_context *ctx = tg->ctx; + uint32_t addr; + uint32_t value = 0; + + set_reg_field_value( + value, + color->color_b_cb, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE); + + set_reg_field_value( + value, + color->color_r_cr, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_RED); + + set_reg_field_value( + value, + color->color_g_y, + CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_GREEN); + + addr = mmCRTCV_OVERSCAN_COLOR; + dm_write_reg(ctx, addr, value); + addr = mmCRTCV_BLACK_COLOR; + dm_write_reg(ctx, addr, value); + /* This is desirable to have a constant DAC output voltage during the + * blank time that is higher than the 0 volt reference level that the + * DAC outputs when the NBLANK signal + * is asserted low, such as for output to an analog TV. */ + addr = mmCRTCV_BLANK_DATA_COLOR; + dm_write_reg(ctx, addr, value); + + /* TO DO we have to program EXT registers and we need to know LB DATA + * format because it is used when more 10 , i.e. 12 bits per color + * + * m_mmDxCRTC_OVERSCAN_COLOR_EXT + * m_mmDxCRTC_BLACK_COLOR_EXT + * m_mmDxCRTC_BLANK_DATA_COLOR_EXT + */ +} + +static void dce110_tg_v_program_blank_color(struct timing_generator *tg, + const struct tg_color *black_color) +{ + uint32_t addr = mmCRTCV_BLACK_COLOR; + uint32_t value = dm_read_reg(tg->ctx, addr); + + set_reg_field_value( + value, + black_color->color_b_cb, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB); + set_reg_field_value( + value, + black_color->color_g_y, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_G_Y); + set_reg_field_value( + value, + black_color->color_r_cr, + CRTCV_BLACK_COLOR, + CRTC_BLACK_COLOR_R_CR); + + dm_write_reg(tg->ctx, addr, value); + + addr = mmCRTCV_BLANK_DATA_COLOR; + dm_write_reg(tg->ctx, addr, value); +} + +static void dce110_timing_generator_v_set_overscan_color(struct timing_generator *tg, + const struct tg_color *overscan_color) +{ + struct dc_context *ctx = tg->ctx; + uint32_t value = 0; + uint32_t addr; + + set_reg_field_value( + value, + overscan_color->color_b_cb, + CRTCV_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE); + + set_reg_field_value( + value, + overscan_color->color_g_y, + CRTCV_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_GREEN); + + set_reg_field_value( + value, + overscan_color->color_r_cr, + CRTCV_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_RED); + + addr = mmCRTCV_OVERSCAN_COLOR; + dm_write_reg(ctx, addr, value); +} + +static void dce110_timing_generator_v_set_colors(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color) +{ + if (blank_color != NULL) + dce110_tg_v_program_blank_color(tg, blank_color); + if (overscan_color != NULL) + dce110_timing_generator_v_set_overscan_color(tg, overscan_color); +} + +static void dce110_timing_generator_v_set_early_control( + struct timing_generator *tg, + uint32_t early_cntl) +{ + uint32_t regval; + uint32_t address = mmCRTC_CONTROL; + + regval = dm_read_reg(tg->ctx, address); + set_reg_field_value(regval, early_cntl, + CRTCV_CONTROL, CRTC_HBLANK_EARLY_CONTROL); + dm_write_reg(tg->ctx, address, regval); +} + +static void dce110_timing_generator_v_get_crtc_positions( + struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position) +{ + uint32_t value; + + value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION); + + *h_position = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_HORZ_COUNT); + + *v_position = get_reg_field_value( + value, + CRTCV_STATUS_POSITION, + CRTC_VERT_COUNT); +} + +static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg) +{ + uint32_t addr = mmCRTCV_STATUS_FRAME_COUNT; + uint32_t value = dm_read_reg(tg->ctx, addr); + uint32_t field = get_reg_field_value( + value, CRTCV_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT); + + return field; +} + +static bool dce110_timing_generator_v_did_triggered_reset_occur( + struct timing_generator *tg) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return false; +} + +static void dce110_timing_generator_v_setup_global_swap_lock( + struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return; +} + +static void dce110_timing_generator_v_enable_reset_trigger( + struct timing_generator *tg, + int source_tg_inst) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return; +} + +static void dce110_timing_generator_v_disable_reset_trigger( + struct timing_generator *tg) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return; +} + +static void dce110_timing_generator_v_tear_down_global_swap_lock( + struct timing_generator *tg) +{ + dm_logger_write(tg->ctx->logger, LOG_ERROR, + "Timing Sync not supported on underlay pipe\n"); + return; +} + +static void dce110_timing_generator_v_disable_vga( + struct timing_generator *tg) +{ + return; +} + +static bool dce110_tg_v_is_blanked(struct timing_generator *tg) +{ + /* Signal comes from the primary pipe, underlay is never blanked. */ + return false; +} + +/** ******************************************************************************************** + * + * DCE11 Timing Generator Constructor / Destructor + * + *********************************************************************************************/ +static const struct timing_generator_funcs dce110_tg_v_funcs = { + .validate_timing = dce110_tg_validate_timing, + .program_timing = dce110_timing_generator_v_program_timing, + .enable_crtc = dce110_timing_generator_v_enable_crtc, + .disable_crtc = dce110_timing_generator_v_disable_crtc, + .is_counter_moving = dce110_timing_generator_v_is_counter_moving, + .get_position = dce110_timing_generator_v_get_crtc_positions, + .get_frame_count = dce110_timing_generator_v_get_vblank_counter, + .set_early_control = dce110_timing_generator_v_set_early_control, + .wait_for_state = dce110_timing_generator_v_wait_for_state, + .set_blank = dce110_timing_generator_v_set_blank, + .is_blanked = dce110_tg_v_is_blanked, + .set_colors = dce110_timing_generator_v_set_colors, + .set_overscan_blank_color = + dce110_timing_generator_v_set_overscan_color_black, + .set_blank_color = dce110_timing_generator_v_program_blank_color, + .disable_vga = dce110_timing_generator_v_disable_vga, + .did_triggered_reset_occur = + dce110_timing_generator_v_did_triggered_reset_occur, + .setup_global_swap_lock = + dce110_timing_generator_v_setup_global_swap_lock, + .enable_reset_trigger = dce110_timing_generator_v_enable_reset_trigger, + .disable_reset_trigger = dce110_timing_generator_v_disable_reset_trigger, + .tear_down_global_swap_lock = + dce110_timing_generator_v_tear_down_global_swap_lock, + .enable_advanced_request = + dce110_timing_generator_v_enable_advanced_request +}; + +bool dce110_timing_generator_v_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx) +{ + if (!tg110) + return false; + + tg110->controller_id = CONTROLLER_ID_UNDERLAY0; + + tg110->base.funcs = &dce110_tg_v_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + tg110->min_h_blank = 56; + tg110->min_h_front_porch = 4; + tg110->min_h_back_porch = 4; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h new file mode 100644 index 000000000000..7e49ca8e26ad --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_V_DCE110_H__ +#define __DC_TIMING_GENERATOR_V_DCE110_H__ + +bool dce110_timing_generator_v_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx); + +#endif /* __DC_TIMING_GENERATOR_V_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c new file mode 100644 index 000000000000..7d8cf7a58f46 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -0,0 +1,704 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce110_transform_v.h" +#include "dm_services.h" +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#define SCLV_PHASES 64 + +struct sclv_ratios_inits { + uint32_t h_int_scale_ratio_luma; + uint32_t h_int_scale_ratio_chroma; + uint32_t v_int_scale_ratio_luma; + uint32_t v_int_scale_ratio_chroma; + struct init_int_and_frac h_init_luma; + struct init_int_and_frac h_init_chroma; + struct init_int_and_frac v_init_luma; + struct init_int_and_frac v_init_chroma; +}; + +static void calculate_viewport( + const struct scaler_data *scl_data, + struct rect *luma_viewport, + struct rect *chroma_viewport) +{ + /*Do not set chroma vp for rgb444 pixel format*/ + luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2; + luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2; + luma_viewport->width = + scl_data->viewport.width - scl_data->viewport.width % 2; + luma_viewport->height = + scl_data->viewport.height - scl_data->viewport.height % 2; + chroma_viewport->x = luma_viewport->x; + chroma_viewport->y = luma_viewport->y; + chroma_viewport->height = luma_viewport->height; + chroma_viewport->width = luma_viewport->width; + + if (scl_data->format == PIXEL_FORMAT_420BPP12) { + luma_viewport->height += luma_viewport->height % 2; + luma_viewport->width += luma_viewport->width % 2; + /*for 420 video chroma is 1/4 the area of luma, scaled + *vertically and horizontally + */ + chroma_viewport->x = luma_viewport->x / 2; + chroma_viewport->y = luma_viewport->y / 2; + chroma_viewport->height = luma_viewport->height / 2; + chroma_viewport->width = luma_viewport->width / 2; + } +} + +static void program_viewport( + struct dce_transform *xfm_dce, + struct rect *luma_view_port, + struct rect *chroma_view_port) +{ + struct dc_context *ctx = xfm_dce->base.ctx; + uint32_t value = 0; + uint32_t addr = 0; + + if (luma_view_port->width != 0 && luma_view_port->height != 0) { + addr = mmSCLV_VIEWPORT_START; + value = 0; + set_reg_field_value( + value, + luma_view_port->x, + SCLV_VIEWPORT_START, + VIEWPORT_X_START); + set_reg_field_value( + value, + luma_view_port->y, + SCLV_VIEWPORT_START, + VIEWPORT_Y_START); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VIEWPORT_SIZE; + value = 0; + set_reg_field_value( + value, + luma_view_port->height, + SCLV_VIEWPORT_SIZE, + VIEWPORT_HEIGHT); + set_reg_field_value( + value, + luma_view_port->width, + SCLV_VIEWPORT_SIZE, + VIEWPORT_WIDTH); + dm_write_reg(ctx, addr, value); + } + + if (chroma_view_port->width != 0 && chroma_view_port->height != 0) { + addr = mmSCLV_VIEWPORT_START_C; + value = 0; + set_reg_field_value( + value, + chroma_view_port->x, + SCLV_VIEWPORT_START_C, + VIEWPORT_X_START_C); + set_reg_field_value( + value, + chroma_view_port->y, + SCLV_VIEWPORT_START_C, + VIEWPORT_Y_START_C); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VIEWPORT_SIZE_C; + value = 0; + set_reg_field_value( + value, + chroma_view_port->height, + SCLV_VIEWPORT_SIZE_C, + VIEWPORT_HEIGHT_C); + set_reg_field_value( + value, + chroma_view_port->width, + SCLV_VIEWPORT_SIZE_C, + VIEWPORT_WIDTH_C); + dm_write_reg(ctx, addr, value); + } +} + +/* + * Function: + * void setup_scaling_configuration + * + * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps + * Input: data + * + * Output: + * void + */ +static bool setup_scaling_configuration( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + bool is_scaling_needed = false; + struct dc_context *ctx = xfm_dce->base.ctx; + uint32_t value = 0; + + set_reg_field_value(value, data->taps.h_taps - 1, + SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS); + set_reg_field_value(value, data->taps.v_taps - 1, + SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS); + set_reg_field_value(value, data->taps.h_taps_c - 1, + SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C); + set_reg_field_value(value, data->taps.v_taps_c - 1, + SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C); + dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value); + + value = 0; + if (data->taps.h_taps + data->taps.v_taps > 2) { + set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE); + set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN); + is_scaling_needed = true; + } else { + set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE); + set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN); + } + + if (data->taps.h_taps_c + data->taps.v_taps_c > 2) { + set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C); + set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C); + is_scaling_needed = true; + } else if (data->format != PIXEL_FORMAT_420BPP12) { + set_reg_field_value( + value, + get_reg_field_value(value, SCLV_MODE, SCL_MODE), + SCLV_MODE, + SCL_MODE_C); + set_reg_field_value( + value, + get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN), + SCLV_MODE, + SCL_PSCL_EN_C); + } else { + set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C); + set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C); + } + dm_write_reg(ctx, mmSCLV_MODE, value); + + value = 0; + /* + * 0 - Replaced out of bound pixels with black pixel + * (or any other required color) + * 1 - Replaced out of bound pixels with the edge pixel + */ + set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE); + dm_write_reg(ctx, mmSCLV_CONTROL, value); + + return is_scaling_needed; +} + +/** +* Function: +* void program_overscan +* +* Purpose: Programs overscan border +* Input: overscan +* +* Output: + void +*/ +static void program_overscan( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + uint32_t overscan_left_right = 0; + uint32_t overscan_top_bottom = 0; + + int overscan_right = data->h_active - data->recout.x - data->recout.width; + int overscan_bottom = data->v_active - data->recout.y - data->recout.height; + + if (overscan_right < 0) { + BREAK_TO_DEBUGGER(); + overscan_right = 0; + } + if (overscan_bottom < 0) { + BREAK_TO_DEBUGGER(); + overscan_bottom = 0; + } + + set_reg_field_value(overscan_left_right, data->recout.x, + EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT); + + set_reg_field_value(overscan_left_right, overscan_right, + EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT); + + set_reg_field_value(overscan_top_bottom, data->recout.y, + EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP); + + set_reg_field_value(overscan_top_bottom, overscan_bottom, + EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM); + + dm_write_reg(xfm_dce->base.ctx, + mmSCLV_EXT_OVERSCAN_LEFT_RIGHT, + overscan_left_right); + + dm_write_reg(xfm_dce->base.ctx, + mmSCLV_EXT_OVERSCAN_TOP_BOTTOM, + overscan_top_bottom); +} + +static void set_coeff_update_complete( + struct dce_transform *xfm_dce) +{ + uint32_t value; + + value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE); + set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE); + dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value); +} + +static void program_multi_taps_filter( + struct dce_transform *xfm_dce, + int taps, + const uint16_t *coeffs, + enum ram_filter_type filter_type) +{ + struct dc_context *ctx = xfm_dce->base.ctx; + int i, phase, pair; + int array_idx = 0; + int taps_pairs = (taps + 1) / 2; + int phases_to_program = SCLV_PHASES / 2 + 1; + + uint32_t select = 0; + uint32_t power_ctl, power_ctl_off; + + if (!coeffs) + return; + + /*We need to disable power gating on coeff memory to do programming*/ + power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL); + power_ctl_off = power_ctl; + set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS); + dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off); + + /*Wait to disable gating:*/ + for (i = 0; i < 10; i++) { + if (get_reg_field_value( + dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS), + DCFEV_MEM_PWR_STATUS, + SCLV_COEFF_MEM_PWR_STATE) == 0) + break; + + udelay(1); + } + + set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE); + + for (phase = 0; phase < phases_to_program; phase++) { + /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror + phase 0 is unique and phase N/2 is unique if N is even*/ + set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE); + for (pair = 0; pair < taps_pairs; pair++) { + uint32_t data = 0; + + set_reg_field_value(select, pair, + SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX); + + dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select); + + set_reg_field_value( + data, 1, + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_EVEN_TAP_COEF_EN); + set_reg_field_value( + data, coeffs[array_idx], + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_EVEN_TAP_COEF); + + if (taps % 2 && pair == taps_pairs - 1) { + set_reg_field_value( + data, 0, + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_ODD_TAP_COEF_EN); + array_idx++; + } else { + set_reg_field_value( + data, 1, + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_ODD_TAP_COEF_EN); + set_reg_field_value( + data, coeffs[array_idx + 1], + SCLV_COEF_RAM_TAP_DATA, + SCL_C_RAM_ODD_TAP_COEF); + + array_idx += 2; + } + + dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data); + } + } + + /*We need to restore power gating on coeff memory to initial state*/ + dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl); +} + +static void calculate_inits( + struct dce_transform *xfm_dce, + const struct scaler_data *data, + struct sclv_ratios_inits *inits, + struct rect *luma_viewport, + struct rect *chroma_viewport) +{ + inits->h_int_scale_ratio_luma = + dal_fixed31_32_u2d19(data->ratios.horz) << 5; + inits->v_int_scale_ratio_luma = + dal_fixed31_32_u2d19(data->ratios.vert) << 5; + inits->h_int_scale_ratio_chroma = + dal_fixed31_32_u2d19(data->ratios.horz_c) << 5; + inits->v_int_scale_ratio_chroma = + dal_fixed31_32_u2d19(data->ratios.vert_c) << 5; + + inits->h_init_luma.integer = 1; + inits->v_init_luma.integer = 1; + inits->h_init_chroma.integer = 1; + inits->v_init_chroma.integer = 1; +} + +static void program_scl_ratios_inits( + struct dce_transform *xfm_dce, + struct sclv_ratios_inits *inits) +{ + struct dc_context *ctx = xfm_dce->base.ctx; + uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO; + uint32_t value = 0; + + set_reg_field_value( + value, + inits->h_int_scale_ratio_luma, + SCLV_HORZ_FILTER_SCALE_RATIO, + SCL_H_SCALE_RATIO); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VERT_FILTER_SCALE_RATIO; + value = 0; + set_reg_field_value( + value, + inits->v_int_scale_ratio_luma, + SCLV_VERT_FILTER_SCALE_RATIO, + SCL_V_SCALE_RATIO); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C; + value = 0; + set_reg_field_value( + value, + inits->h_int_scale_ratio_chroma, + SCLV_HORZ_FILTER_SCALE_RATIO_C, + SCL_H_SCALE_RATIO_C); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C; + value = 0; + set_reg_field_value( + value, + inits->v_int_scale_ratio_chroma, + SCLV_VERT_FILTER_SCALE_RATIO_C, + SCL_V_SCALE_RATIO_C); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_HORZ_FILTER_INIT; + value = 0; + set_reg_field_value( + value, + inits->h_init_luma.fraction, + SCLV_HORZ_FILTER_INIT, + SCL_H_INIT_FRAC); + set_reg_field_value( + value, + inits->h_init_luma.integer, + SCLV_HORZ_FILTER_INIT, + SCL_H_INIT_INT); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VERT_FILTER_INIT; + value = 0; + set_reg_field_value( + value, + inits->v_init_luma.fraction, + SCLV_VERT_FILTER_INIT, + SCL_V_INIT_FRAC); + set_reg_field_value( + value, + inits->v_init_luma.integer, + SCLV_VERT_FILTER_INIT, + SCL_V_INIT_INT); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_HORZ_FILTER_INIT_C; + value = 0; + set_reg_field_value( + value, + inits->h_init_chroma.fraction, + SCLV_HORZ_FILTER_INIT_C, + SCL_H_INIT_FRAC_C); + set_reg_field_value( + value, + inits->h_init_chroma.integer, + SCLV_HORZ_FILTER_INIT_C, + SCL_H_INIT_INT_C); + dm_write_reg(ctx, addr, value); + + addr = mmSCLV_VERT_FILTER_INIT_C; + value = 0; + set_reg_field_value( + value, + inits->v_init_chroma.fraction, + SCLV_VERT_FILTER_INIT_C, + SCL_V_INIT_FRAC_C); + set_reg_field_value( + value, + inits->v_init_chroma.integer, + SCLV_VERT_FILTER_INIT_C, + SCL_V_INIT_INT_C); + dm_write_reg(ctx, addr, value); +} + +static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +{ + if (taps == 4) + return get_filter_4tap_64p(ratio); + else if (taps == 2) + return filter_2tap_64p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + uint32_t value; + + value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL); + + /*Use all three pieces of memory always*/ + set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG); + /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/ + set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL, + LB_MEMORY_SIZE); + + dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value); + + return true; +} + +static void dce110_xfmv_set_scaler( + struct transform *xfm, + const struct scaler_data *data) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + bool is_scaling_required = false; + bool filter_updated = false; + const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c; + struct rect luma_viewport = {0}; + struct rect chroma_viewport = {0}; + + dce110_xfmv_power_up_line_buffer(xfm); + /* 1. Calculate viewport, viewport programming should happen after init + * calculations as they may require an adjustment in the viewport. + */ + + calculate_viewport(data, &luma_viewport, &chroma_viewport); + + /* 2. Program overscan */ + program_overscan(xfm_dce, data); + + /* 3. Program taps and configuration */ + is_scaling_required = setup_scaling_configuration(xfm_dce, data); + + if (is_scaling_required) { + /* 4. Calculate and program ratio, filter initialization */ + + struct sclv_ratios_inits inits = { 0 }; + + calculate_inits( + xfm_dce, + data, + &inits, + &luma_viewport, + &chroma_viewport); + + program_scl_ratios_inits(xfm_dce, &inits); + + coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert); + coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz); + coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c); + coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c); + + if (coeffs_v != xfm_dce->filter_v + || coeffs_v_c != xfm_dce->filter_v_c + || coeffs_h != xfm_dce->filter_h + || coeffs_h_c != xfm_dce->filter_h_c) { + /* 5. Program vertical filters */ + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps, + coeffs_v, + FILTER_TYPE_RGB_Y_VERTICAL); + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps_c, + coeffs_v_c, + FILTER_TYPE_CBCR_VERTICAL); + + /* 6. Program horizontal filters */ + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps, + coeffs_h, + FILTER_TYPE_RGB_Y_HORIZONTAL); + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps_c, + coeffs_h_c, + FILTER_TYPE_CBCR_HORIZONTAL); + + xfm_dce->filter_v = coeffs_v; + xfm_dce->filter_v_c = coeffs_v_c; + xfm_dce->filter_h = coeffs_h; + xfm_dce->filter_h_c = coeffs_h_c; + filter_updated = true; + } + } + + /* 7. Program the viewport */ + program_viewport(xfm_dce, &luma_viewport, &chroma_viewport); + + /* 8. Set bit to flip to new coefficient memory */ + if (filter_updated) + set_coeff_update_complete(xfm_dce); +} + +static void dce110_xfmv_reset(struct transform *xfm) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + xfm_dce->filter_h = NULL; + xfm_dce->filter_v = NULL; + xfm_dce->filter_h_c = NULL; + xfm_dce->filter_v_c = NULL; +} + +static void dce110_xfmv_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + /* DO NOTHING*/ +} + +static void dce110_xfmv_set_pixel_storage_depth( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + int pixel_depth, expan_mode; + uint32_t reg_data = 0; + + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + pixel_depth = 2; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_24BPP: + pixel_depth = 1; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_30BPP: + pixel_depth = 0; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_36BPP: + pixel_depth = 3; + expan_mode = 0; + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + set_reg_field_value( + reg_data, + expan_mode, + LBV_DATA_FORMAT, + PIXEL_EXPAN_MODE); + + set_reg_field_value( + reg_data, + pixel_depth, + LBV_DATA_FORMAT, + PIXEL_DEPTH); + + dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data); + + if (!(xfm_dce->lb_pixel_depth_supported & depth)) { + /*we should use unsupported capabilities + * unless it is required by w/a*/ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } +} + +static const struct transform_funcs dce110_xfmv_funcs = { + .transform_reset = dce110_xfmv_reset, + .transform_set_scaler = dce110_xfmv_set_scaler, + .transform_set_gamut_remap = + dce110_xfmv_set_gamut_remap, + .transform_set_pixel_storage_depth = + dce110_xfmv_set_pixel_storage_depth, + .transform_get_optimal_number_of_taps = + dce_transform_get_optimal_number_of_taps +}; +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce110_transform_v_construct( + struct dce_transform *xfm_dce, + struct dc_context *ctx) +{ + xfm_dce->base.ctx = ctx; + + xfm_dce->base.funcs = &dce110_xfmv_funcs; + + xfm_dce->lb_pixel_depth_supported = + LB_PIXEL_DEPTH_18BPP | + LB_PIXEL_DEPTH_24BPP | + LB_PIXEL_DEPTH_30BPP; + + xfm_dce->prescaler_on = true; + xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; + xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h new file mode 100644 index 000000000000..267af34db3e5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h @@ -0,0 +1,37 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TRANSFORM_V_DCE110_H__ +#define __DAL_TRANSFORM_V_DCE110_H__ + +#include "../dce/dce_transform.h" + +#define LB_TOTAL_NUMBER_OF_ENTRIES 1712 +#define LB_BITS_PER_ENTRY 144 + +bool dce110_transform_v_construct( + struct dce_transform *xfm110, + struct dc_context *ctx); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h new file mode 100644 index 000000000000..55f52382ddfb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h @@ -0,0 +1,30 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCE110_TYPES_H_ +#define __DCE110_TYPES_H_ + +#define GAMMA_SEGMENTS_NUM 16 + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_DCE110_DCE110_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile new file mode 100644 index 000000000000..34fba0730bed --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE112 = dce112_compressor.o dce112_hw_sequencer.o \ +dce112_resource.o dce112_mem_input.o dce112_opp_formatter.o \ +dce112_opp.o + +AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE112) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c new file mode 100644 index 000000000000..22a5aba073ca --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -0,0 +1,859 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "gmc/gmc_8_1_d.h" + +#include "include/logger_interface.h" + +#include "dce112_compressor.h" + +#define DCP_REG(reg)\ + (reg + cp110->offsets.dcp_offset) +#define DMIF_REG(reg)\ + (reg + cp110->offsets.dmif_offset) + +static const struct dce112_compressor_reg_offsets reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = + (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +} +}; + +static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600; + +enum fbc_idle_force { + /* Bit 0 - Display registers updated */ + FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, + + /* Bit 2 - FBC_GRPH_COMP_EN register updated */ + FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, + /* Bit 3 - FBC_SRC_SEL register updated */ + FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, + /* Bit 4 - FBC_MIN_COMPRESSION register updated */ + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, + /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ + FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, + /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, + /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, + + /* Bit 24 - Memory write to region 0 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, + /* Bit 25 - Memory write to region 1 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, + /* Bit 26 - Memory write to region 2 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, + /* Bit 27 - Memory write to region 3 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, + + /* Bit 28 - Memory write from any client other than MCIF */ + FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, + /* Bit 29 - CG statics screen signal is inactive */ + FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, +}; + +static uint32_t lpt_size_alignment(struct dce112_compressor *cp110) +{ + /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ + return cp110->base.raw_size * cp110->base.banks_num * + cp110->base.dram_channels_num; +} + +static uint32_t lpt_memory_control_config(struct dce112_compressor *cp110, + uint32_t lpt_control) +{ + /*LPT MC Config */ + if (cp110->base.options.bits.LPT_MC_CONFIG == 1) { + /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): + * 00 - 1 CHANNEL + * 01 - 2 CHANNELS + * 02 - 4 OR 6 CHANNELS + * (Only for discrete GPU, N/A for CZ) + * 03 - 8 OR 12 CHANNELS + * (Only for discrete GPU, N/A for CZ) */ + switch (cp110->base.dram_channels_num) { + case 2: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + case 1: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_PIPES!!!", + __func__); + break; + } + + /* The mapping for LPT NUM_BANKS is in + * GRPH_CONTROL.GRPH_NUM_BANKS register field + * Specifies the number of memory banks for tiling + * purposes. Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: + * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK + * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK + * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK + * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ + switch (cp110->base.banks_num) { + case 16: + set_reg_field_value( + lpt_control, + 3, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 8: + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 4: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 2: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_BANKS!!!", + __func__); + break; + } + + /* The mapping is in DMIF_ADDR_CALC. + * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for + * Carrizo specifies the memory interleave per pipe. + * It effectively specifies the location of pipe bits in + * the memory address. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte + * interleave + * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte + * interleave + */ + switch (cp110->base.channel_interleave_size) { + case 256: /*256B */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + case 512: /*512B */ + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT INTERLEAVE_SIZE!!!", + __func__); + break; + } + + /* The mapping for LOW_POWER_TILING_ROW_SIZE is in + * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field + * for Carrizo. Specifies the size of dram row in bytes. + * This should match up with NOOFCOLS field in + * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). + * This register DMIF_ADDR_CALC is not used by the + * hardware as it is only used for addrlib assertions. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row + * boundary + * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row + * boundary + * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row + * boundary */ + switch (cp110->base.raw_size) { + case 4096: /*4 KB */ + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 2048: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 1024: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + default: + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT ROW_SIZE!!!", + __func__); + break; + } + } else { + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: LPT MC Configuration is not provided", + __func__); + } + + return lpt_control; +} + +static bool is_source_bigger_than_epanel_size( + struct dce112_compressor *cp110, + uint32_t source_view_width, + uint32_t source_view_height) +{ + if (cp110->base.embedded_panel_h_size != 0 && + cp110->base.embedded_panel_v_size != 0 && + ((source_view_width * source_view_height) > + (cp110->base.embedded_panel_h_size * + cp110->base.embedded_panel_v_size))) + return true; + + return false; +} + +static uint32_t align_to_chunks_number_per_line( + struct dce112_compressor *cp110, + uint32_t pixels) +{ + return 256 * ((pixels + 255) / 256); +} + +static void wait_for_fbc_state_changed( + struct dce112_compressor *cp110, + bool enabled) +{ + uint8_t counter = 0; + uint32_t addr = mmFBC_STATUS; + uint32_t value; + + while (counter < 10) { + value = dm_read_reg(cp110->base.ctx, addr); + if (get_reg_field_value( + value, + FBC_STATUS, + FBC_ENABLE_STATUS) == enabled) + break; + udelay(10); + counter++; + } + + if (counter == 10) { + dm_logger_write( + cp110->base.ctx->logger, LOG_WARNING, + "%s: wait counter exceeded, changes to HW not applied", + __func__); + } +} + +void dce112_compressor_power_up_fbc(struct compressor *compressor) +{ + uint32_t value; + uint32_t addr; + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value(value, 1, FBC_CNTL, FBC_EN); + set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE); + if (compressor->options.bits.CLK_GATING_DISABLED == 1) { + /* HW needs to do power measurement comparison. */ + set_reg_field_value( + value, + 0, + FBC_CNTL, + FBC_COMP_CLK_GATE_EN); + } + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_MODE; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN); + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN); + dm_write_reg(compressor->ctx, addr, value); + /*FBC_MIN_COMPRESSION 0 ==> 2:1 */ + /* 1 ==> 4:1 */ + /* 2 ==> 8:1 */ + /* 0xF ==> 1:1 */ + set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION); + dm_write_reg(compressor->ctx, addr, value); + compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1; + + value = 0; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value); + + value = 0xFFFFFF; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value); +} + +void dce112_compressor_enable_fbc( + struct compressor *compressor, + uint32_t paths_num, + struct compr_addr_and_pitch_params *params) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + (compressor->options.bits.DUMMY_BACKEND == 0) && + (!dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && + (!is_source_bigger_than_epanel_size( + cp110, + params->source_view_width, + params->source_view_height))) { + + uint32_t addr; + uint32_t value; + + /* Before enabling FBC first need to enable LPT if applicable + * LPT state should always be changed (enable/disable) while FBC + * is disabled */ + if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && + (params->source_view_width * + params->source_view_height <= + dce11_one_lpt_channel_max_resolution)) { + dce112_compressor_enable_lpt(compressor); + } + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value( + value, + params->inst, + FBC_CNTL, FBC_SRC_SEL); + dm_write_reg(compressor->ctx, addr, value); + + /* Keep track of enum controller_id FBC is attached to */ + compressor->is_enabled = true; + compressor->attached_inst = params->inst; + cp110->offsets = reg_offsets[params->inst - 1]; + + /*Toggle it as there is bug in HW */ + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + + wait_for_fbc_state_changed(cp110, true); + } +} + +void dce112_compressor_disable_fbc(struct compressor *compressor) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + dce112_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { + uint32_t reg_data; + /* Turn off compression */ + reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); + set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); + + /* Reset enum controller_id to undefined */ + compressor->attached_inst = 0; + compressor->is_enabled = false; + + /* Whenever disabling FBC make sure LPT is disabled if LPT + * supported */ + if (compressor->options.bits.LPT_SUPPORT) + dce112_compressor_disable_lpt(compressor); + + wait_for_fbc_state_changed(cp110, false); + } +} + +bool dce112_compressor_is_fbc_enabled_in_hw( + struct compressor *compressor, + uint32_t *inst) +{ + /* Check the hardware register */ + uint32_t value; + + value = dm_read_reg(compressor->ctx, mmFBC_STATUS); + if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) { + if (inst != NULL) + *inst = compressor->attached_inst; + return true; + } + + value = dm_read_reg(compressor->ctx, mmFBC_MISC); + if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) { + value = dm_read_reg(compressor->ctx, mmFBC_CNTL); + + if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) { + if (inst != NULL) + *inst = + compressor->attached_inst; + return true; + } + } + return false; +} + +bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) +{ + /* Check the hardware register */ + uint32_t value = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + return get_reg_field_value( + value, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); +} + +void dce112_compressor_program_compressed_surface_address_and_pitch( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + uint32_t value = 0; + uint32_t fbc_pitch = 0; + uint32_t compressed_surf_address_low_part = + compressor->compr_surface_address.addr.low_part; + + /* Clear content first. */ + dm_write_reg( + compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + 0); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); + + if (compressor->options.bits.LPT_SUPPORT) { + uint32_t lpt_alignment = lpt_size_alignment(cp110); + + if (lpt_alignment != 0) { + compressed_surf_address_low_part = + ((compressed_surf_address_low_part + + (lpt_alignment - 1)) / lpt_alignment) + * lpt_alignment; + } + } + + /* Write address, HIGH has to be first. */ + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + compressor->compr_surface_address.addr.high_part); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), + compressed_surf_address_low_part); + + fbc_pitch = align_to_chunks_number_per_line( + cp110, + params->source_view_width); + + if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) + fbc_pitch = fbc_pitch / 8; + else + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Unexpected DCE11 compression ratio", + __func__); + + /* Clear content first. */ + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0); + + /* Write FBC Pitch. */ + set_reg_field_value( + value, + fbc_pitch, + GRPH_COMPRESS_PITCH, + GRPH_COMPRESS_PITCH); + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value); + +} + +void dce112_compressor_disable_lpt(struct compressor *compressor) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t inx; + + /* Disable all pipes LPT Stutter */ + for (inx = 0; inx < 3; inx++) { + value = + dm_read_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 0, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), + value); + } + /* Disable Underlay pipe LPT Stutter */ + addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, addr, value); + + /* Disable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); + + /* Clear selection of Channel(s) containing Compressed Surface */ + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0xFFFFFFFF, + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); +} + +void dce112_compressor_enable_lpt(struct compressor *compressor) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t value_control; + uint32_t channels; + + /* Enable LPT Stutter from Display pipe */ + value = dm_read_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 1, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); + + /* Enable Underlay pipe LPT Stutter */ + addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, addr, value); + + /* Selection of Channel(s) containing Compressed Surface: 0xfffffff + * will disable LPT. + * STCTRL_LPT_TARGETn corresponds to channel n. */ + addr = mmLOW_POWER_TILING_CONTROL; + value_control = dm_read_reg(compressor->ctx, addr); + channels = get_reg_field_value(value_control, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + channels + 1, /* not mentioned in programming guide, + but follow DCE8.1 */ + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, addr, value); + + /* Enable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); +} + +void dce112_compressor_program_lpt_control( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce112_compressor *cp110 = TO_DCE112_COMPRESSOR(compressor); + uint32_t rows_per_channel; + uint32_t lpt_alignment; + uint32_t source_view_width; + uint32_t source_view_height; + uint32_t lpt_control = 0; + + if (!compressor->options.bits.LPT_SUPPORT) + return; + + lpt_control = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + /* POSSIBLE VALUES for Low Power Tiling Mode: + * 00 - Use channel 0 + * 01 - Use Channel 0 and 1 + * 02 - Use Channel 0,1,2,3 + * 03 - reserved */ + switch (compressor->lpt_channels_num) { + /* case 2: + * Use Channel 0 & 1 / Not used for DCE 11 */ + case 1: + /*Use Channel 0 for LPT for DCE 11 */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + break; + default: + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Invalid selected DRAM channels for LPT!!!", + __func__); + break; + } + + lpt_control = lpt_memory_control_config(cp110, lpt_control); + + /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on + * FBC compressed surface pitch. + * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * + * Surface Pitch) / (Row Size * Number of Channels * + * Number of Banks)). */ + rows_per_channel = 0; + lpt_alignment = lpt_size_alignment(cp110); + source_view_width = + align_to_chunks_number_per_line( + cp110, + params->source_view_width); + source_view_height = (params->source_view_height + 1) & (~0x1); + + if (lpt_alignment != 0) { + rows_per_channel = source_view_width * source_view_height * 4; + rows_per_channel = + (rows_per_channel % lpt_alignment) ? + (rows_per_channel / lpt_alignment + 1) : + rows_per_channel / lpt_alignment; + } + + set_reg_field_value( + lpt_control, + rows_per_channel, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROWS_PER_CHAN); + + dm_write_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL, lpt_control); +} + +/* + * DCE 11 Frame Buffer Compression Implementation + */ + +void dce112_compressor_set_fbc_invalidation_triggers( + struct compressor *compressor, + uint32_t fbc_trigger) +{ + /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19) + * for DCE 11 regions cannot be used - does not work with S/G + */ + uint32_t addr = mmFBC_CLIENT_REGION_MASK; + uint32_t value = dm_read_reg(compressor->ctx, addr); + + set_reg_field_value( + value, + 0, + FBC_CLIENT_REGION_MASK, + FBC_MEMORY_REGION_MASK); + dm_write_reg(compressor->ctx, addr, value); + + /* Setup events when to clear all CSM entries (effectively marking + * current compressed data invalid) + * For DCE 11 CSM metadata 11111 means - "Not Compressed" + * Used as the initial value of the metadata sent to the compressor + * after invalidation, to indicate that the compressor should attempt + * to compress all chunks on the current pass. Also used when the chunk + * is not successfully written to memory. + * When this CSM value is detected, FBC reads from the uncompressed + * buffer. Set events according to passed in value, these events are + * valid for DCE11: + * - bit 0 - display register updated + * - bit 28 - memory write from any client except from MCIF + * - bit 29 - CG static screen signal is inactive + * In addition, DCE11.1 also needs to set new DCE11.1 specific events + * that are used to trigger invalidation on certain register changes, + * for example enabling of Alpha Compression may trigger invalidation of + * FBC once bit is set. These events are as follows: + * - Bit 2 - FBC_GRPH_COMP_EN register updated + * - Bit 3 - FBC_SRC_SEL register updated + * - Bit 4 - FBC_MIN_COMPRESSION register updated + * - Bit 5 - FBC_ALPHA_COMP_EN register updated + * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated + * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated + */ + addr = mmFBC_IDLE_FORCE_CLEAR_MASK; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + fbc_trigger | + FBC_IDLE_FORCE_GRPH_COMP_EN | + FBC_IDLE_FORCE_SRC_SEL_CHANGE | + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | + FBC_IDLE_FORCE_ALPHA_COMP_EN | + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, + FBC_IDLE_FORCE_CLEAR_MASK, + FBC_IDLE_FORCE_CLEAR_MASK); + dm_write_reg(compressor->ctx, addr, value); +} + +bool dce112_compressor_construct(struct dce112_compressor *compressor, + struct dc_context *ctx) +{ + struct dc_bios *bp = ctx->dc_bios; + struct embedded_panel_info panel_info; + + compressor->base.options.bits.FBC_SUPPORT = true; + compressor->base.options.bits.LPT_SUPPORT = true; + /* For DCE 11 always use one DRAM channel for LPT */ + compressor->base.lpt_channels_num = 1; + compressor->base.options.bits.DUMMY_BACKEND = false; + + /* Check if this system has more than 1 DRAM channel; if only 1 then LPT + * should not be supported */ + if (compressor->base.memory_bus_width == 64) + compressor->base.options.bits.LPT_SUPPORT = false; + + compressor->base.options.bits.CLK_GATING_DISABLED = false; + + compressor->base.ctx = ctx; + compressor->base.embedded_panel_h_size = 0; + compressor->base.embedded_panel_v_size = 0; + compressor->base.memory_bus_width = ctx->asic_id.vram_width; + compressor->base.allocated_size = 0; + compressor->base.preferred_requested_size = 0; + compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; + compressor->base.options.raw = 0; + compressor->base.banks_num = 0; + compressor->base.raw_size = 0; + compressor->base.channel_interleave_size = 0; + compressor->base.dram_channels_num = 0; + compressor->base.lpt_channels_num = 0; + compressor->base.attached_inst = 0; + compressor->base.is_enabled = false; + + if (BP_RESULT_OK == + bp->funcs->get_embedded_panel_info(bp, &panel_info)) { + compressor->base.embedded_panel_h_size = + panel_info.lcd_timing.horizontal_addressable; + compressor->base.embedded_panel_v_size = + panel_info.lcd_timing.vertical_addressable; + } + return true; +} + +struct compressor *dce112_compressor_create(struct dc_context *ctx) +{ + struct dce112_compressor *cp110 = + dm_alloc(sizeof(struct dce112_compressor)); + + if (!cp110) + return NULL; + + if (dce112_compressor_construct(cp110, ctx)) + return &cp110->base; + + BREAK_TO_DEBUGGER(); + dm_free(cp110); + return NULL; +} + +void dce112_compressor_destroy(struct compressor **compressor) +{ + dm_free(TO_DCE112_COMPRESSOR(*compressor)); + *compressor = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h new file mode 100644 index 000000000000..106506387270 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h @@ -0,0 +1,78 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_COMPRESSOR_DCE112_H__ +#define __DC_COMPRESSOR_DCE112_H__ + +#include "../inc/compressor.h" + +#define TO_DCE112_COMPRESSOR(compressor)\ + container_of(compressor, struct dce112_compressor, base) + +struct dce112_compressor_reg_offsets { + uint32_t dcp_offset; + uint32_t dmif_offset; +}; + +struct dce112_compressor { + struct compressor base; + struct dce112_compressor_reg_offsets offsets; +}; + +struct compressor *dce112_compressor_create(struct dc_context *ctx); + +bool dce112_compressor_construct(struct dce112_compressor *cp110, + struct dc_context *ctx); + +void dce112_compressor_destroy(struct compressor **cp); + +/* FBC RELATED */ +void dce112_compressor_power_up_fbc(struct compressor *cp); + +void dce112_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, + struct compr_addr_and_pitch_params *params); + +void dce112_compressor_disable_fbc(struct compressor *cp); + +void dce112_compressor_set_fbc_invalidation_triggers(struct compressor *cp, + uint32_t fbc_trigger); + +void dce112_compressor_program_compressed_surface_address_and_pitch( + struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce112_compressor_is_fbc_enabled_in_hw(struct compressor *cp, + uint32_t *fbc_mapped_crtc_id); + +/* LPT RELATED */ +void dce112_compressor_enable_lpt(struct compressor *cp); + +void dce112_compressor_disable_lpt(struct compressor *cp); + +void dce112_compressor_program_lpt_control(struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce112_compressor_is_lpt_enabled_in_hw(struct compressor *cp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c new file mode 100644 index 000000000000..204f613467b7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c @@ -0,0 +1,166 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "dce112_hw_sequencer.h" + +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE11.2 register header files */ +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +struct dce112_hw_seq_reg_offsets { + uint32_t crtc; +}; + + +static const struct dce112_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +static void dce112_init_pte(struct dc_context *ctx) +{ + uint32_t addr; + uint32_t value = 0; + uint32_t chunk_int = 0; + uint32_t chunk_mul = 0; + + addr = mmDVMM_PTE_REQ; + value = dm_read_reg(ctx, addr); + + chunk_int = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + chunk_mul = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + if (chunk_int != 0x4 || chunk_mul != 0x4) { + + set_reg_field_value( + value, + 255, + DVMM_PTE_REQ, + MAX_PTEREQ_TO_ISSUE); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + dm_write_reg(ctx, addr, value); + } +} + +static bool dce112_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + return true; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){ + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + */ + dm_write_reg(ctx, + HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id), + 0); + } + + if (power_gating != PIPE_GATING_CONTROL_ENABLE) + dce112_init_pte(ctx); + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + +bool dce112_hw_sequencer_construct(struct core_dc *dc) +{ + /* All registers used by dce11.2 match those in dce11 in offset and + * structure + */ + dce110_hw_sequencer_construct(dc); + dc->hwss.enable_display_power_gating = dce112_enable_display_power_gating; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h new file mode 100644 index 000000000000..d96c582da45c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE112_H__ +#define __DC_HWSS_DCE112_H__ + +#include "core_types.h" + +struct core_dc; + +bool dce112_hw_sequencer_construct(struct core_dc *dc); + +#endif /* __DC_HWSS_DCE112_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c new file mode 100644 index 000000000000..c29007dafe21 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c @@ -0,0 +1,54 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dce112_mem_input.h" + + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + + +#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) +#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) +#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce112_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) + return false; + + mem_input110->base.funcs->mem_input_program_display_marks = + dce_mem_input_program_display_marks; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h new file mode 100644 index 000000000000..de2aaf0f9a8e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h @@ -0,0 +1,38 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCE112_H__ +#define __DC_MEM_INPUT_DCE112_H__ + +#include "mem_input.h" +#include "dce110/dce110_mem_input.h" + +bool dce112_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c new file mode 100644 index 000000000000..23c2d1086b3b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c @@ -0,0 +1,72 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE11 register header files */ +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#include "dce112_opp.h" + +#include "gamma_types.h" + +enum { + MAX_LUT_ENTRY = 256, + MAX_NUMBER_OF_ENTRIES = 256 +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce112_opp_program_fmt, + .opp_program_bit_depth_reduction = + dce110_opp_program_bit_depth_reduction +}; + +bool dce112_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets) +{ + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; + + opp110->base.inst = inst; + + opp110->offsets = *offsets; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h new file mode 100644 index 000000000000..9443b87776c6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h @@ -0,0 +1,48 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE112_H__ +#define __DC_OPP_DCE112_H__ + +#include "dc_types.h" +#include "opp.h" +#include "../dce110/dce110_opp.h" +#include "core_types.h" + +void dce112_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params); + +void dce112_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + +bool dce112_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets); + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c new file mode 100644 index 000000000000..2d9072138834 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c @@ -0,0 +1,215 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#include "dce112_opp.h" + +#define FMT_REG(reg)\ + (reg + opp110->offsets.fmt_offset) +#define FMT_MEM_REG(reg)\ + (reg + opp110->offsets.fmt_mem_offset) + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + * 2: YCbCr 4:2:0 + */ +static void set_pixel_encoding( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t fmt_cntl_value; + uint32_t addr = FMT_REG(mmFMT_CONTROL); + + /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ + fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); + + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /*00 - Pixels drop mode HW default*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_MODE); + + /* By default no bypass*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_CBCR_BIT_REDUCTION_BYPASS); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + set_reg_field_value(fmt_cntl_value, + 1, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /*00 - Cb before Cr ,01 - Cr before Cb*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_ORDER); + } + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + set_reg_field_value(fmt_cntl_value, + 2, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /* 02 - Subsampling mode, 3 taps*/ + set_reg_field_value(fmt_cntl_value, + 2, + FMT_CONTROL, + FMT_SUBSAMPLING_MODE); + + /* 00 - Enable CbCr bit reduction bypass to preserve precision*/ + set_reg_field_value(fmt_cntl_value, + 1, + FMT_CONTROL, + FMT_CBCR_BIT_REDUCTION_BYPASS); + } + dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); + +} + +void dce112_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + dce110_opp_set_clamping(opp110, params); + set_pixel_encoding(opp110, params); +} + +static void program_formatter_420_memory(struct output_pixel_processor *opp) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t fmt_cntl_value; + uint32_t fmt_mem_cntl_value; + uint32_t fmt_cntl_addr = FMT_REG(mmFMT_CONTROL); + uint32_t fmt_mem_cntl_addr = FMT_MEM_REG(mmFMT_MEMORY0_CONTROL); + + fmt_mem_cntl_value = dm_read_reg(opp110->base.ctx, fmt_mem_cntl_addr); + fmt_cntl_value = dm_read_reg(opp110->base.ctx, fmt_cntl_addr); + /* Program source select*/ + /* Use HW default source select for FMT_MEMORYx_CONTROL */ + /* Use that value for FMT_SRC_SELECT as well*/ + set_reg_field_value(fmt_cntl_value, + get_reg_field_value(fmt_mem_cntl_value, FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL), + FMT_CONTROL, + FMT_SRC_SELECT); + dm_write_reg(opp110->base.ctx, fmt_cntl_addr, fmt_cntl_value); + + /* Turn on the memory */ + set_reg_field_value(fmt_mem_cntl_value, + 0, + FMT_MEMORY0_CONTROL, + FMT420_MEM0_PWR_FORCE); + dm_write_reg(opp110->base.ctx, fmt_mem_cntl_addr, fmt_mem_cntl_value); +} + +static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t value; + uint32_t addr = FMT_REG(mmFMT_CONTROL); + uint8_t counter = 10; + + + value = dm_read_reg(opp110->base.ctx, addr); + + /* clear previous phase lock status*/ + set_reg_field_value(value, + 1, + FMT_CONTROL, + FMT_420_PIXEL_PHASE_LOCKED_CLEAR); + dm_write_reg(opp110->base.ctx, addr, value); + + /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ + while (counter > 0) { + value = dm_read_reg(opp110->base.ctx, addr); + + if (get_reg_field_value( + value, + FMT_CONTROL, + FMT_420_PIXEL_PHASE_LOCKED) == 1) + break; + + msleep(10); + counter--; + } + + if (counter == 0) + dm_logger_write(opp->ctx->logger, LOG_ERROR, + "%s:opp program formattter reset dig resync info time out.\n", + __func__); +} + +void dce112_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + /* dithering is affected by , hence should be + * programmed afterwards */ + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_420_memory(opp); + + dce110_opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + dce112_opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_reset_dig_resync_fifo(opp); + + return; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c new file mode 100644 index 000000000000..bfb2c3fcd2cb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -0,0 +1,1418 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dce110/dce110_resource.h" +#include "dce110/dce110_timing_generator.h" +#include "dce112/dce112_mem_input.h" + +#include "irq/dce110/irq_service_dce110.h" +#include "dce/dce_transform.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_audio.h" +#include "dce112/dce112_opp.h" +#include "dce110/dce110_ipp.h" +#include "dce/dce_clock_source.h" + +#include "dce/dce_hwseq.h" +#include "dce112/dce112_hw_sequencer.h" + +#include "reg_helper.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +enum dce112_clk_src_array_id { + DCE112_CLK_SRC_PLL0, + DCE112_CLK_SRC_PLL1, + DCE112_CLK_SRC_PLL2, + DCE112_CLK_SRC_PLL3, + DCE112_CLK_SRC_PLL4, + DCE112_CLK_SRC_PLL5, + + DCE112_CLK_SRC_TOTAL +}; + +static const struct dce110_timing_generator_offsets dce112_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce112_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + +static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), +} +}; + + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE110_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE112(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE112(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5) +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + + +static const struct dce110_opp_reg_offsets dce112_opp_reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY0_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY1_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY2_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY3_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY4_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .fmt_mem_offset = (mmFMT_MEMORY5_CONTROL - mmFMT_MEMORY0_CONTROL), + .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +#define clk_src_regs(index, id)\ +[index] = {\ + CS_COMMON_REG_LIST_DCE_112(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps polaris_10_resource_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */ +}; + +static const struct resource_caps polaris_11_resource_cap = { + .num_timing_generator = 5, + .num_audio = 5, + .num_stream_encoder = 5, + .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */ +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x4819 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + + +static struct timing_generator *dce112_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static struct stream_encoder *dce112_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE112_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE112_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE112_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce112_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce112_stream_encoder_create, + .create_hwseq = dce112_hwseq_create, +}; + +#define mi_inst_regs(id) { MI_REG_LIST(id) } +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE_MASK_SH_LIST(_MASK) +}; + +static struct mem_input *dce112_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce112_mem_input_construct(mem_input110, ctx, inst, offset)) { + struct mem_input *mi = &mem_input110->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input110); + return NULL; +} + +static void dce112_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce112_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) { + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} +struct link_encoder *dce112_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + enc110->base.features.ycbcr420_supported = false; + enc110->base.features.max_hdmi_pixel_clock = 600000; + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +struct input_pixel_processor *dce112_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + struct dce110_ipp *ipp = + dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce110_ipp_construct(ipp, ctx, inst, offset)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +void dce112_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE110_IPP(*ipp)); + *ipp = NULL; +} + +struct output_pixel_processor *dce112_opp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_opp_reg_offsets *offset) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce112_opp_construct(opp, + ctx, inst, offset)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + +void dce112_opp_destroy(struct output_pixel_processor **opp) +{ + struct dce110_opp *dce110_opp; + + if (!opp || !*opp) + return; + + dce110_opp = FROM_DCE11_OPP(*opp); + + dm_free(dce110_opp->regamma.coeff128_dx); + dm_free(dce110_opp->regamma.coeff128_oem); + dm_free(dce110_opp->regamma.coeff128); + dm_free(dce110_opp->regamma.axis_x_1025); + dm_free(dce110_opp->regamma.axis_x_256); + dm_free(dce110_opp->regamma.coordinates_x); + dm_free(dce110_opp->regamma.rgb_regamma); + dm_free(dce110_opp->regamma.rgb_resulted); + dm_free(dce110_opp->regamma.rgb_oem); + dm_free(dce110_opp->regamma.rgb_user); + + dm_free(dce110_opp); + *opp = NULL; +} + +struct clock_source *dce112_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce112_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce112_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce112_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce112_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce112_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.dp_clock_source != NULL) + dce112_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.display_clock != NULL) { + dal_display_clock_destroy(&pool->base.display_clock); + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + +static struct clock_source *find_matching_pll(struct resource_context *res_ctx, + const struct core_stream *const stream) +{ + switch (stream->sink->link->link_enc->transmitter) { + case TRANSMITTER_UNIPHY_A: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL0]; + case TRANSMITTER_UNIPHY_B: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL1]; + case TRANSMITTER_UNIPHY_C: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL2]; + case TRANSMITTER_UNIPHY_D: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL3]; + case TRANSMITTER_UNIPHY_E: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL4]; + case TRANSMITTER_UNIPHY_F: + return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL5]; + default: + return NULL; + }; + + return 0; +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j, k; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = dce110_resource_build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + resource_build_info_frame(pipe_ctx); + + /* do not need to validate non root pipes */ + break; + } + } + } + + return DC_OK; +} + +enum dc_status dce112_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + dm_logger_write( + dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "%s: start", + __func__); + + if (!bw_calcs( + dc->ctx, + &dc->bw_dceip, + &dc->bw_vbios, + context->res_ctx.pipe_ctx, + context->res_ctx.pool->pipe_count, + &context->bw_results)) + result = DC_FAIL_BANDWIDTH_VALIDATE; + else + result = DC_OK; + + if (result == DC_FAIL_BANDWIDTH_VALIDATE) + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, + "%s: Bandwidth validation failed!", + __func__); + + if (memcmp(&dc->current_context->bw_results, + &context->bw_results, sizeof(context->bw_results))) { + struct log_entry log_entry; + dm_logger_open( + dc->ctx->logger, + &log_entry, + LOG_BANDWIDTH_CALCS); + dm_logger_append(&log_entry, "%s: finish,\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n", + __func__, + context->bw_results.nbp_state_change_wm_ns[0].b_mark, + context->bw_results.nbp_state_change_wm_ns[0].a_mark, + context->bw_results.urgent_wm_ns[0].b_mark, + context->bw_results.urgent_wm_ns[0].a_mark, + context->bw_results.stutter_exit_wm_ns[0].b_mark, + context->bw_results.stutter_exit_wm_ns[0].a_mark); + dm_logger_append(&log_entry, + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n", + context->bw_results.nbp_state_change_wm_ns[1].b_mark, + context->bw_results.nbp_state_change_wm_ns[1].a_mark, + context->bw_results.urgent_wm_ns[1].b_mark, + context->bw_results.urgent_wm_ns[1].a_mark, + context->bw_results.stutter_exit_wm_ns[1].b_mark, + context->bw_results.stutter_exit_wm_ns[1].a_mark); + dm_logger_append(&log_entry, + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", + context->bw_results.nbp_state_change_wm_ns[2].b_mark, + context->bw_results.nbp_state_change_wm_ns[2].a_mark, + context->bw_results.urgent_wm_ns[2].b_mark, + context->bw_results.urgent_wm_ns[2].a_mark, + context->bw_results.stutter_exit_wm_ns[2].b_mark, + context->bw_results.stutter_exit_wm_ns[2].a_mark, + context->bw_results.stutter_mode_enable); + dm_logger_append(&log_entry, + "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" + "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", + context->bw_results.cpuc_state_change_enable, + context->bw_results.cpup_state_change_enable, + context->bw_results.nbp_state_change_enable, + context->bw_results.all_displays_in_sync, + context->bw_results.dispclk_khz, + context->bw_results.required_sclk, + context->bw_results.required_sclk_deep_sleep, + context->bw_results.required_yclk, + context->bw_results.blackout_recovery_time_us); + dm_logger_close(&log_entry); + } + return result; +} + +enum dc_status resource_map_phy_clock_resources( + const struct core_dc *dc, + struct validate_context *context) +{ + uint8_t i, j, k; + + /* acquire new resources */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + else + pipe_ctx->clock_source = + find_matching_pll(&context->res_ctx, + stream); + + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; + + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); + + /* only one cs per stream regardless of mpo */ + break; + } + } + } + + return DC_OK; +} + +static bool dce112_validate_surface_sets( + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) { + if (set[i].surface_count == 0) + continue; + + if (set[i].surface_count > 1) + return false; + + if (set[i].surfaces[0]->clip_rect.width + != set[i].target->streams[0]->src.width + || set[i].surfaces[0]->clip_rect.height + != set[i].target->streams[0]->src.height) + return false; + if (set[i].surfaces[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +enum dc_status dce112_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + + if (!dce112_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + context->res_ctx.pool = dc->res_pool; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, context); + + if (!resource_validate_attach_surfaces( + set, set_count, dc->current_context, context)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + result = resource_build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce112_validate_bandwidth(dc, context); + + return result; +} + +enum dc_status dce112_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->res_ctx.pool = dc->res_pool; + + context->targets[0] = DC_TARGET_TO_CORE(dc_target); + dc_target_retain(&context->targets[0]->public); + context->target_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_target( + context, dc->public.caps.max_targets); + result = resource_build_scaling_params_for_context(dc, context); + } + + if (result == DC_OK) + result = dce112_validate_bandwidth(dc, context); + + return result; +} + +static void dce112_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce112_res_pool_funcs = { + .destroy = dce112_destroy_resource_pool, + .link_enc_create = dce112_link_encoder_create, + .validate_with_context = dce112_validate_with_context, + .validate_guaranteed = dce112_validate_guaranteed, + .validate_bandwidth = dce112_validate_bandwidth +}; + +static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +{ + struct dm_pp_clock_levels_with_latency eng_clks = {0}; + struct dm_pp_clock_levels_with_latency mem_clks = {0}; + struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; + struct dm_pp_clock_levels clks = {0}; + + /*do system clock TODO PPLIB: after PPLIB implement, + * then remove old way + */ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &eng_clks)) { + + /* This is only for temporary */ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &clks); + /* convert all the clock fro kHz to fix point mHz */ + dc->bw_vbios.high_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels/8], 1000); + dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*2/8], 1000); + dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*3/8], 1000); + dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*4/8], 1000); + dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*5/8], 1000); + dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*6/8], 1000); + dc->bw_vbios.low_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &clks); + + dc->bw_vbios.low_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); + dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, + 1000); + dc->bw_vbios.high_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, + 1000); + + return; + } + + /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ + dc->bw_vbios.high_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); + dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); + dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); + dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); + dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); + dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); + dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); + dc->bw_vbios.low_sclk = bw_frc_to_fixed( + eng_clks.data[0].clocks_in_khz, 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &mem_clks); + + /* we don't need to call PPLIB for validation clock since they + * also give us the highest sclk and highest mclk (UMA clock). + * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): + * YCLK = UMACLK*m_memoryTypeMultiplier + */ + dc->bw_vbios.low_yclk = bw_frc_to_fixed( + mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); + dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, + 1000); + dc->bw_vbios.high_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, + 1000); + + /* Now notify PPLib/SMU about which Watermarks sets they should select + * depending on DPM state they are in. And update BW MGR GFX Engine and + * Memory clock member variables for Watermarks calculations for each + * Watermark Set + */ + clk_ranges.num_wm_sets = 4; + clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[0].wm_min_memg_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[1].wm_min_memg_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[2].wm_min_memg_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; + + clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[3].wm_min_memg_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); +} + +const struct resource_caps *dce112_resource_cap( + struct hw_asic_id *asic_id) +{ + if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev)) + return &polaris_11_resource_cap; + else + return &polaris_10_resource_cap; +} + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = dce112_resource_cap(&ctx->asic_id); + pool->base.funcs = &dce112_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = -1; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 100; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCE112_CLK_SRC_PLL0] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL1] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL2] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL3] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL4] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL5] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + pool->base.clk_src_count = DCE112_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, &clk_src_regs[0], true); + + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dal_display_clock_dce112_create( + ctx); + + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + /* get static clock information for PPLIB or firmware, save + * max_clock_state + */ + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { + enum clocks_state max_clocks_state = + dce110_resource_convert_clock_state_pp_to_dc( + static_clk_info.max_clocks_state); + + dal_display_clock_store_max_clocks_state( + pool->base.display_clock, max_clocks_state); + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = + dce112_timing_generator_create( + ctx, + i, + &dce112_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce112_mem_input_create( + ctx, + i, + &dce112_mi_reg_offsets[i]); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce112_ipp_create( + ctx, + i, + &ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce112_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce112_opp_create( + ctx, + i, + &dce112_opp_reg_offsets[i]); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce112_hw_sequencer_construct(dc)) + goto res_create_fail; + + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_POLARIS11); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce112_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h new file mode 100644 index 000000000000..f21eb57857d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -0,0 +1,55 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE112_H__ +#define __DC_RESOURCE_DCE112_H__ + +#include "core_types.h" + +struct core_dc; +struct resource_pool; + +struct resource_pool *dce112_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +enum dc_status dce112_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context); + +enum dc_status dce112_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context); + +enum dc_status dce112_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context); + + +#endif /* __DC_RESOURCE_DCE112_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile new file mode 100644 index 000000000000..9979b8441a8d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE80 = dce80_ipp.o dce80_ipp_gamma.o dce80_opp.o \ + dce80_opp_formatter.o dce80_opp_regamma.o \ + dce80_timing_generator.o dce80_opp_csc.o\ + dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ + dce80_resource.o + +AMD_DAL_DCE80 = $(addprefix $(AMDDALPATH)/dc/dce80/,$(DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE80) + + + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c new file mode 100644 index 000000000000..eeedb7c4fe53 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c @@ -0,0 +1,839 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" +#include "gmc/gmc_7_1_sh_mask.h" +#include "gmc/gmc_7_1_d.h" + +#include "include/logger_interface.h" +#include "dce80_compressor.h" + +#define DCP_REG(reg)\ + (reg + cp80->offsets.dcp_offset) +#define DMIF_REG(reg)\ + (reg + cp80->offsets.dmif_offset) + +static const struct dce80_compressor_reg_offsets reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG0_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG1_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG2_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG3_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG4_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif_offset = (mmDMIF_PG5_DPG_PIPE_DPM_CONTROL + - mmDMIF_PG0_DPG_PIPE_DPM_CONTROL), +} +}; + +static const uint32_t dce8_one_lpt_channel_max_resolution = 2048 * 1200; + +enum fbc_idle_force { + /* Bit 0 - Display registers updated */ + FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001, + + /* Bit 2 - FBC_GRPH_COMP_EN register updated */ + FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002, + /* Bit 3 - FBC_SRC_SEL register updated */ + FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004, + /* Bit 4 - FBC_MIN_COMPRESSION register updated */ + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008, + /* Bit 5 - FBC_ALPHA_COMP_EN register updated */ + FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010, + /* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */ + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020, + /* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040, + + /* Bit 24 - Memory write to region 0 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000, + /* Bit 25 - Memory write to region 1 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000, + /* Bit 26 - Memory write to region 2 defined by MC registers */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000, + /* Bit 27 - Memory write to region 3 defined by MC registers. */ + FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000, + + /* Bit 28 - Memory write from any client other than MCIF */ + FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000, + /* Bit 29 - CG statics screen signal is inactive */ + FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, +}; + +static uint32_t lpt_size_alignment(struct dce80_compressor *cp80) +{ + /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ + return cp80->base.raw_size * cp80->base.banks_num * + cp80->base.dram_channels_num; +} + +static uint32_t lpt_memory_control_config(struct dce80_compressor *cp80, + uint32_t lpt_control) +{ + /*LPT MC Config */ + if (cp80->base.options.bits.LPT_MC_CONFIG == 1) { + /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): + * 00 - 1 CHANNEL + * 01 - 2 CHANNELS + * 02 - 4 OR 6 CHANNELS + * (Only for discrete GPU, N/A for CZ) + * 03 - 8 OR 12 CHANNELS + * (Only for discrete GPU, N/A for CZ) */ + switch (cp80->base.dram_channels_num) { + case 2: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + case 1: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_PIPES); + break; + default: + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_PIPES!!!", + __func__); + break; + } + + /* The mapping for LPT NUM_BANKS is in + * GRPH_CONTROL.GRPH_NUM_BANKS register field + * Specifies the number of memory banks for tiling + * purposes. Only applies to 2D and 3D tiling modes. + * POSSIBLE VALUES: + * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK + * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK + * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK + * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ + switch (cp80->base.banks_num) { + case 16: + set_reg_field_value( + lpt_control, + 3, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 8: + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 4: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + case 2: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_NUM_BANKS); + break; + default: + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT NUM_BANKS!!!", + __func__); + break; + } + + /* The mapping is in DMIF_ADDR_CALC. + * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for + * Carrizo specifies the memory interleave per pipe. + * It effectively specifies the location of pipe bits in + * the memory address. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte + * interleave + * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte + * interleave + */ + switch (cp80->base.channel_interleave_size) { + case 256: /*256B */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + case 512: /*512B */ + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); + break; + default: + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT INTERLEAVE_SIZE!!!", + __func__); + break; + } + + /* The mapping for LOW_POWER_TILING_ROW_SIZE is in + * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field + * for Carrizo. Specifies the size of dram row in bytes. + * This should match up with NOOFCOLS field in + * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). + * This register DMIF_ADDR_CALC is not used by the + * hardware as it is only used for addrlib assertions. + * POSSIBLE VALUES: + * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row + * boundary + * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row + * boundary + * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row + * boundary */ + switch (cp80->base.raw_size) { + case 4096: /*4 KB */ + set_reg_field_value( + lpt_control, + 2, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 2048: + set_reg_field_value( + lpt_control, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + case 1024: + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROW_SIZE); + break; + default: + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: Invalid LPT ROW_SIZE!!!", + __func__); + break; + } + } else { + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: LPT MC Configuration is not provided", + __func__); + } + + return lpt_control; +} + +static bool is_source_bigger_than_epanel_size( + struct dce80_compressor *cp80, + uint32_t source_view_width, + uint32_t source_view_height) +{ + if (cp80->base.embedded_panel_h_size != 0 && + cp80->base.embedded_panel_v_size != 0 && + ((source_view_width * source_view_height) > + (cp80->base.embedded_panel_h_size * + cp80->base.embedded_panel_v_size))) + return true; + + return false; +} + +static uint32_t align_to_chunks_number_per_line( + struct dce80_compressor *cp80, + uint32_t pixels) +{ + return 256 * ((pixels + 255) / 256); +} + +static void wait_for_fbc_state_changed( + struct dce80_compressor *cp80, + bool enabled) +{ + uint8_t counter = 0; + uint32_t addr = mmFBC_STATUS; + uint32_t value; + + while (counter < 10) { + value = dm_read_reg(cp80->base.ctx, addr); + if (get_reg_field_value( + value, + FBC_STATUS, + FBC_ENABLE_STATUS) == enabled) + break; + udelay(10); + counter++; + } + + if (counter == 10) { + dm_logger_write( + cp80->base.ctx->logger, LOG_WARNING, + "%s: wait counter exceeded, changes to HW not applied", + __func__); + } +} + +void dce80_compressor_power_up_fbc(struct compressor *compressor) +{ + uint32_t value; + uint32_t addr; + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value(value, 1, FBC_CNTL, FBC_EN); + set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE); + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_MODE; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN); + set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN); + dm_write_reg(compressor->ctx, addr, value); + + addr = mmFBC_COMP_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN); + dm_write_reg(compressor->ctx, addr, value); + /*FBC_MIN_COMPRESSION 0 ==> 2:1 */ + /* 1 ==> 4:1 */ + /* 2 ==> 8:1 */ + /* 0xF ==> 1:1 */ + set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION); + dm_write_reg(compressor->ctx, addr, value); + compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1; + + value = 0; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value); + + value = 0xFFFFFF; + dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value); +} + +void dce80_compressor_enable_fbc( + struct compressor *compressor, + uint32_t paths_num, + struct compr_addr_and_pitch_params *params) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + (compressor->options.bits.DUMMY_BACKEND == 0) && + (!dce80_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && + (!is_source_bigger_than_epanel_size( + cp80, + params->source_view_width, + params->source_view_height))) { + + uint32_t addr; + uint32_t value; + + /* Before enabling FBC first need to enable LPT if applicable + * LPT state should always be changed (enable/disable) while FBC + * is disabled */ + if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && + (params->source_view_width * + params->source_view_height <= + dce8_one_lpt_channel_max_resolution)) { + dce80_compressor_enable_lpt(compressor); + } + + addr = mmFBC_CNTL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + set_reg_field_value( + value, + params->inst, + FBC_CNTL, FBC_SRC_SEL); + dm_write_reg(compressor->ctx, addr, value); + + /* Keep track of enum controller_id FBC is attached to */ + compressor->is_enabled = true; + compressor->attached_inst = params->inst; + cp80->offsets = reg_offsets[params->inst - 1]; + + /*Toggle it as there is bug in HW */ + set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, addr, value); + + wait_for_fbc_state_changed(cp80, true); + } +} + +void dce80_compressor_disable_fbc(struct compressor *compressor) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + + if (compressor->options.bits.FBC_SUPPORT && + dce80_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { + uint32_t reg_data; + /* Turn off compression */ + reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); + set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); + + /* Reset enum controller_id to undefined */ + compressor->attached_inst = 0; + compressor->is_enabled = false; + + /* Whenever disabling FBC make sure LPT is disabled if LPT + * supported */ + if (compressor->options.bits.LPT_SUPPORT) + dce80_compressor_disable_lpt(compressor); + + wait_for_fbc_state_changed(cp80, false); + } +} + +bool dce80_compressor_is_fbc_enabled_in_hw( + struct compressor *compressor, + uint32_t *inst) +{ + /* Check the hardware register */ + uint32_t value; + + value = dm_read_reg(compressor->ctx, mmFBC_STATUS); + if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) { + if (inst != NULL) + *inst = compressor->attached_inst; + return true; + } + + value = dm_read_reg(compressor->ctx, mmFBC_CNTL); + if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) { + if (inst != NULL) + *inst = compressor->attached_inst; + return true; + } + + return false; +} + +bool dce80_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) +{ + /* Check the hardware register */ + uint32_t value = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + return get_reg_field_value( + value, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); +} + +void dce80_compressor_program_compressed_surface_address_and_pitch( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + uint32_t value = 0; + uint32_t fbc_pitch = 0; + uint32_t compressed_surf_address_low_part = + compressor->compr_surface_address.addr.low_part; + + /* Clear content first. */ + dm_write_reg( + compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + 0); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); + + if (compressor->options.bits.LPT_SUPPORT) { + uint32_t lpt_alignment = lpt_size_alignment(cp80); + + if (lpt_alignment != 0) { + compressed_surf_address_low_part = + ((compressed_surf_address_low_part + + (lpt_alignment - 1)) / lpt_alignment) + * lpt_alignment; + } + } + + /* Write address, HIGH has to be first. */ + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), + compressor->compr_surface_address.addr.high_part); + dm_write_reg(compressor->ctx, + DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), + compressed_surf_address_low_part); + + fbc_pitch = align_to_chunks_number_per_line( + cp80, + params->source_view_width); + + if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) + fbc_pitch = fbc_pitch / 8; + else + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Unexpected DCE8 compression ratio", + __func__); + + /* Clear content first. */ + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0); + + /* Write FBC Pitch. */ + set_reg_field_value( + value, + fbc_pitch, + GRPH_COMPRESS_PITCH, + GRPH_COMPRESS_PITCH); + dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value); + +} + +void dce80_compressor_disable_lpt(struct compressor *compressor) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t inx; + + /* Disable all pipes LPT Stutter */ + for (inx = 0; inx < 3; inx++) { + value = + dm_read_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 0, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg( + compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), + value); + } + + /* Disable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); + + /* Clear selection of Channel(s) containing Compressed Surface */ + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 0xFFFFFFFF, + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); +} + +void dce80_compressor_enable_lpt(struct compressor *compressor) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + uint32_t value; + uint32_t addr; + uint32_t value_control; + uint32_t channels; + + /* Enable LPT Stutter from Display pipe */ + value = dm_read_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); + set_reg_field_value( + value, + 1, + DPG_PIPE_STUTTER_CONTROL_NONLPTCH, + STUTTER_ENABLE_NONLPTCH); + dm_write_reg(compressor->ctx, + DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); + + /* Selection of Channel(s) containing Compressed Surface: 0xfffffff + * will disable LPT. + * STCTRL_LPT_TARGETn corresponds to channel n. */ + addr = mmLOW_POWER_TILING_CONTROL; + value_control = dm_read_reg(compressor->ctx, addr); + channels = get_reg_field_value(value_control, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + + addr = mmGMCON_LPT_TARGET; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + channels + 1, /* not mentioned in programming guide, + but follow DCE8.1 */ + GMCON_LPT_TARGET, + STCTRL_LPT_TARGET); + dm_write_reg(compressor->ctx, addr, value); + + /* Enable LPT */ + addr = mmLOW_POWER_TILING_CONTROL; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + 1, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ENABLE); + dm_write_reg(compressor->ctx, addr, value); +} + +void dce80_compressor_program_lpt_control( + struct compressor *compressor, + struct compr_addr_and_pitch_params *params) +{ + struct dce80_compressor *cp80 = TO_DCE80_COMPRESSOR(compressor); + uint32_t rows_per_channel; + uint32_t lpt_alignment; + uint32_t source_view_width; + uint32_t source_view_height; + uint32_t lpt_control = 0; + + if (!compressor->options.bits.LPT_SUPPORT) + return; + + lpt_control = dm_read_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL); + + /* POSSIBLE VALUES for Low Power Tiling Mode: + * 00 - Use channel 0 + * 01 - Use Channel 0 and 1 + * 02 - Use Channel 0,1,2,3 + * 03 - reserved */ + switch (compressor->lpt_channels_num) { + /* case 2: + * Use Channel 0 & 1 / Not used for DCE 11 */ + case 1: + /*Use Channel 0 for LPT for DCE 11 */ + set_reg_field_value( + lpt_control, + 0, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_MODE); + break; + default: + dm_logger_write( + compressor->ctx->logger, LOG_WARNING, + "%s: Invalid selected DRAM channels for LPT!!!", + __func__); + break; + } + + lpt_control = lpt_memory_control_config(cp80, lpt_control); + + /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on + * FBC compressed surface pitch. + * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * + * Surface Pitch) / (Row Size * Number of Channels * + * Number of Banks)). */ + rows_per_channel = 0; + lpt_alignment = lpt_size_alignment(cp80); + source_view_width = + align_to_chunks_number_per_line( + cp80, + params->source_view_width); + source_view_height = (params->source_view_height + 1) & (~0x1); + + if (lpt_alignment != 0) { + rows_per_channel = source_view_width * source_view_height * 4; + rows_per_channel = + (rows_per_channel % lpt_alignment) ? + (rows_per_channel / lpt_alignment + 1) : + rows_per_channel / lpt_alignment; + } + + set_reg_field_value( + lpt_control, + rows_per_channel, + LOW_POWER_TILING_CONTROL, + LOW_POWER_TILING_ROWS_PER_CHAN); + + dm_write_reg(compressor->ctx, + mmLOW_POWER_TILING_CONTROL, lpt_control); +} + +/* + * DCE 11 Frame Buffer Compression Implementation + */ + +void dce80_compressor_set_fbc_invalidation_triggers( + struct compressor *compressor, + uint32_t fbc_trigger) +{ + /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19) + * for DCE 11 regions cannot be used - does not work with S/G + */ + uint32_t addr = mmFBC_CLIENT_REGION_MASK; + uint32_t value = dm_read_reg(compressor->ctx, addr); + + set_reg_field_value( + value, + 0, + FBC_CLIENT_REGION_MASK, + FBC_MEMORY_REGION_MASK); + dm_write_reg(compressor->ctx, addr, value); + + /* Setup events when to clear all CSM entries (effectively marking + * current compressed data invalid) + * For DCE 11 CSM metadata 11111 means - "Not Compressed" + * Used as the initial value of the metadata sent to the compressor + * after invalidation, to indicate that the compressor should attempt + * to compress all chunks on the current pass. Also used when the chunk + * is not successfully written to memory. + * When this CSM value is detected, FBC reads from the uncompressed + * buffer. Set events according to passed in value, these events are + * valid for DCE8: + * - bit 0 - display register updated + * - bit 28 - memory write from any client except from MCIF + * - bit 29 - CG static screen signal is inactive + * In addition, DCE8.1 also needs to set new DCE8.1 specific events + * that are used to trigger invalidation on certain register changes, + * for example enabling of Alpha Compression may trigger invalidation of + * FBC once bit is set. These events are as follows: + * - Bit 2 - FBC_GRPH_COMP_EN register updated + * - Bit 3 - FBC_SRC_SEL register updated + * - Bit 4 - FBC_MIN_COMPRESSION register updated + * - Bit 5 - FBC_ALPHA_COMP_EN register updated + * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated + * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated + */ + addr = mmFBC_IDLE_FORCE_CLEAR_MASK; + value = dm_read_reg(compressor->ctx, addr); + set_reg_field_value( + value, + fbc_trigger | + FBC_IDLE_FORCE_GRPH_COMP_EN | + FBC_IDLE_FORCE_SRC_SEL_CHANGE | + FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | + FBC_IDLE_FORCE_ALPHA_COMP_EN | + FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | + FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, + FBC_IDLE_FORCE_CLEAR_MASK, + FBC_IDLE_FORCE_CLEAR_MASK); + dm_write_reg(compressor->ctx, addr, value); +} + +bool dce80_compressor_construct(struct dce80_compressor *compressor, + struct dc_context *ctx) +{ + struct dc_bios *bp = ctx->dc_bios; + struct embedded_panel_info panel_info; + + compressor->base.options.bits.FBC_SUPPORT = true; + compressor->base.options.bits.LPT_SUPPORT = true; + /* For DCE 11 always use one DRAM channel for LPT */ + compressor->base.lpt_channels_num = 1; + compressor->base.options.bits.DUMMY_BACKEND = false; + + /* Check if this system has more than 1 DRAM channel; if only 1 then LPT + * should not be supported */ + if (compressor->base.memory_bus_width == 64) + compressor->base.options.bits.LPT_SUPPORT = false; + + compressor->base.options.bits.CLK_GATING_DISABLED = false; + + compressor->base.ctx = ctx; + compressor->base.embedded_panel_h_size = 0; + compressor->base.embedded_panel_v_size = 0; + compressor->base.memory_bus_width = ctx->asic_id.vram_width; + compressor->base.allocated_size = 0; + compressor->base.preferred_requested_size = 0; + compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; + compressor->base.options.raw = 0; + compressor->base.banks_num = 0; + compressor->base.raw_size = 0; + compressor->base.channel_interleave_size = 0; + compressor->base.dram_channels_num = 0; + compressor->base.lpt_channels_num = 0; + compressor->base.attached_inst = 0; + compressor->base.is_enabled = false; + + if (BP_RESULT_OK == + bp->funcs->get_embedded_panel_info(bp, &panel_info)) { + compressor->base.embedded_panel_h_size = + panel_info.lcd_timing.horizontal_addressable; + compressor->base.embedded_panel_v_size = + panel_info.lcd_timing.vertical_addressable; + } + return true; +} + +struct compressor *dce80_compressor_create(struct dc_context *ctx) +{ + struct dce80_compressor *cp80 = + dm_alloc(sizeof(struct dce80_compressor)); + + if (!cp80) + return NULL; + + if (dce80_compressor_construct(cp80, ctx)) + return &cp80->base; + + BREAK_TO_DEBUGGER(); + dm_free(cp80); + return NULL; +} + +void dce80_compressor_destroy(struct compressor **compressor) +{ + dm_free(TO_DCE80_COMPRESSOR(*compressor)); + *compressor = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h new file mode 100644 index 000000000000..01290969ff92 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h @@ -0,0 +1,78 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_COMPRESSOR_DCE80_H__ +#define __DC_COMPRESSOR_DCE80_H__ + +#include "../inc/compressor.h" + +#define TO_DCE80_COMPRESSOR(compressor)\ + container_of(compressor, struct dce80_compressor, base) + +struct dce80_compressor_reg_offsets { + uint32_t dcp_offset; + uint32_t dmif_offset; +}; + +struct dce80_compressor { + struct compressor base; + struct dce80_compressor_reg_offsets offsets; +}; + +struct compressor *dce80_compressor_create(struct dc_context *ctx); + +bool dce80_compressor_construct(struct dce80_compressor *cp80, + struct dc_context *ctx); + +void dce80_compressor_destroy(struct compressor **cp); + +/* FBC RELATED */ +void dce80_compressor_power_up_fbc(struct compressor *cp); + +void dce80_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, + struct compr_addr_and_pitch_params *params); + +void dce80_compressor_disable_fbc(struct compressor *cp); + +void dce80_compressor_set_fbc_invalidation_triggers(struct compressor *cp, + uint32_t fbc_trigger); + +void dce80_compressor_program_compressed_surface_address_and_pitch( + struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce80_compressor_is_fbc_enabled_in_hw(struct compressor *cp, + uint32_t *fbc_mapped_crtc_id); + +/* LPT RELATED */ +void dce80_compressor_enable_lpt(struct compressor *cp); + +void dce80_compressor_disable_lpt(struct compressor *cp); + +void dce80_compressor_program_lpt_control(struct compressor *cp, + struct compr_addr_and_pitch_params *params); + +bool dce80_compressor_is_lpt_enabled_in_hw(struct compressor *cp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c new file mode 100644 index 000000000000..c7a2b768bcd1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -0,0 +1,141 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "dce80_hw_sequencer.h" + +#include "dce/dce_hwseq.h" +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +struct dce80_hw_seq_reg_offsets { + uint32_t crtc; +}; + +static const struct dce80_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL), +} +}; + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +/***************************PIPE_CONTROL***********************************/ + +static bool dce80_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0)){ + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + */ + dm_write_reg(ctx, + HW_REG_CRTC(mmMASTER_UPDATE_MODE, controller_id), + 0); + } + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +} + + +static void set_display_mark_for_pipe_if_needed(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +static void set_displaymarks( + const struct core_dc *dc, struct validate_context *context) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + +static void set_bandwidth(struct core_dc *dc) +{ + /* Do nothing until we have proper bandwitdth calcs */ +} + + +bool dce80_hw_sequencer_construct(struct core_dc *dc) +{ + dce110_hw_sequencer_construct(dc); + + dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating; + dc->hwss.pipe_control_lock = dce_pipe_control_lock; + dc->hwss.set_displaymarks = set_displaymarks; + dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed; + dc->hwss.set_bandwidth = set_bandwidth; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h new file mode 100644 index 000000000000..7cc203f433d3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE80_H__ +#define __DC_HWSS_DCE80_H__ + +#include "core_types.h" + +struct core_dc; + +bool dce80_hw_sequencer_construct(struct core_dc *dc); + +#endif /* __DC_HWSS_DCE80_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c new file mode 100644 index 000000000000..86826c229d39 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c @@ -0,0 +1,64 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_ipp.h" + +#include "dce110/dce110_ipp.h" + +static const struct ipp_funcs funcs = { + .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce110_ipp_cursor_set_position, + .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_set_degamma = dce110_ipp_set_degamma, +}; + +bool dce80_ipp_construct( + struct dce110_ipp *ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + ipp->base.ctx = ctx; + + ipp->base.inst = inst; + + ipp->offsets = *offset; + + ipp->base.funcs = &funcs; + + return true; +} + +void dce80_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE80_IPP(*ipp)); + *ipp = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h new file mode 100644 index 000000000000..d350138e5feb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h @@ -0,0 +1,47 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_IPP_DCE80_H__ +#define __DC_IPP_DCE80_H__ + +#include "ipp.h" + +#define TO_DCE80_IPP(input_pixel_processor)\ + container_of(input_pixel_processor, struct dce110_ipp, base) + +struct dce110_ipp; +struct dce110_ipp_reg_offsets; +struct gamma_parameters; +struct dev_c_lut; + +bool dce80_ipp_construct( + struct dce110_ipp *ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset); + +void dce80_ipp_destroy(struct input_pixel_processor **ipp); + +#endif /*__DC_IPP_DCE80_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c new file mode 100644 index 000000000000..eacb14e40d52 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c @@ -0,0 +1,76 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" +#include "include/fixed31_32.h" +#include "basics/conversion.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_ipp.h" +#include "dce110/dce110_ipp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + ipp80->offsets.dcp_offset) + +enum { + MAX_INPUT_LUT_ENTRY = 256 +}; + +/*PROTOTYPE DECLARATIONS*/ + +static void set_legacy_input_gamma_mode( + struct dce110_ipp *ipp80, + bool is_legacy); + +void dce80_ipp_set_legacy_input_gamma_mode( + struct input_pixel_processor *ipp, + bool is_legacy) +{ + struct dce110_ipp *ipp80 = TO_DCE80_IPP(ipp); + + set_legacy_input_gamma_mode(ipp80, is_legacy); +} + +static void set_legacy_input_gamma_mode( + struct dce110_ipp *ipp80, + bool is_legacy) +{ + const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL); + uint32_t value = dm_read_reg(ipp80->base.ctx, addr); + + set_reg_field_value( + value, + !is_legacy, + INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE); + + dm_write_reg(ipp80->base.ctx, addr, value); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c new file mode 100644 index 000000000000..ebb8df3cdf4a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -0,0 +1,83 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" +/* TODO: this needs to be looked at, used by Stella's workaround*/ +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" + +#include "include/logger_interface.h" +#include "inc/bandwidth_calcs.h" + +#include "../dce110/dce110_mem_input.h" +#include "dce80_mem_input.h" + +#define MAX_WATERMARK 0xFFFF +#define SAFE_NBP_MARK 0x7FFF + +#define DCP_REG(reg) (reg + mem_input80->offsets.dcp) +#define DMIF_REG(reg) (reg + mem_input80->offsets.dmif) +#define PIPE_REG(reg) (reg + mem_input80->offsets.pipe) + +static struct mem_input_funcs dce80_mem_input_funcs = { + .mem_input_program_display_marks = + dce110_mem_input_program_display_marks, + .allocate_mem_input = dce_mem_input_allocate_dmif, + .free_mem_input = dce_mem_input_free_dmif, + .mem_input_program_surface_flip_and_addr = + dce110_mem_input_program_surface_flip_and_addr, + .mem_input_program_surface_config = + dce_mem_input_program_surface_config, + .mem_input_is_flip_pending = + dce110_mem_input_is_flip_pending, + .mem_input_update_dchub = NULL +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce80_mem_input_construct( + struct dce110_mem_input *mem_input80, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + /* supported stutter method + * STUTTER_MODE_ENHANCED + * STUTTER_MODE_QUAD_DMIF_BUFFER + */ + mem_input80->base.funcs = &dce80_mem_input_funcs; + mem_input80->base.ctx = ctx; + + mem_input80->base.inst = inst; + + mem_input80->offsets = *offsets; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h new file mode 100644 index 000000000000..357b9e2e9f1e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h @@ -0,0 +1,36 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCE80_H__ +#define __DC_MEM_INPUT_DCE80_H__ + +#include "mem_input.h" + +bool dce80_mem_input_construct( + struct dce110_mem_input *mem_input80, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c new file mode 100644 index 000000000000..b69e8a5d844d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c @@ -0,0 +1,136 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_opp.h" + +#define FROM_OPP(opp)\ + container_of(opp, struct dce80_opp, base) + +enum { + MAX_LUT_ENTRY = 256, + MAX_NUMBER_OF_ENTRIES = 256 +}; + +static const struct dce80_opp_reg_offsets reg_offsets[] = { +{ + .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), + .crtc_offset = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - + mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +static const struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce80_opp_power_on_regamma_lut, + .opp_set_csc_adjustment = dce80_opp_set_csc_adjustment, + .opp_set_csc_default = dce80_opp_set_csc_default, + .opp_set_dyn_expansion = dce80_opp_set_dyn_expansion, + .opp_program_regamma_pwl = dce80_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce80_opp_set_regamma_mode, + .opp_destroy = dce80_opp_destroy, + .opp_program_fmt = dce110_opp_program_fmt, +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce80_opp_construct(struct dce80_opp *opp80, + struct dc_context *ctx, + uint32_t inst) +{ + if (inst >= ARRAY_SIZE(reg_offsets)) + return false; + + opp80->base.funcs = &funcs; + + opp80->base.ctx = ctx; + + opp80->base.inst = inst; + + opp80->offsets = reg_offsets[inst]; + + return true; +} + +void dce80_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free(FROM_OPP(*opp)); + *opp = NULL; +} + +struct output_pixel_processor *dce80_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce80_opp *opp = + dm_alloc(sizeof(struct dce80_opp)); + + if (!opp) + return NULL; + + if (dce80_opp_construct(opp, + ctx, inst)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h new file mode 100644 index 000000000000..965cce37f7e3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h @@ -0,0 +1,130 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE80_H__ +#define __DC_OPP_DCE80_H__ + +#include "dc_types.h" +#include "opp.h" +#include "gamma_types.h" +#include "../dce110/dce110_opp.h" + +struct gamma_parameters; + +struct dce80_regamma { + struct gamma_curve arr_curve_points[16]; + struct curve_points arr_points[3]; + uint32_t hw_points_num; + struct hw_x_point *coordinates_x; + struct pwl_result_data *rgb_resulted; + + /* re-gamma curve */ + struct pwl_float_data_ex *rgb_regamma; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 256 */ + struct pixel_gamma_point *coeff128; + struct pixel_gamma_point *coeff128_oem; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 1025 */ + struct pixel_gamma_point *coeff128_dx; + /* evenly distributed points, gamma 256 software points 0-255 */ + struct gamma_pixel *axis_x_256; + /* evenly distributed points, gamma 1025 software points 0-1025 */ + struct gamma_pixel *axis_x_1025; + /* OEM supplied gamma for regamma LUT */ + struct pwl_float_data *rgb_oem; + /* user supplied gamma */ + struct pwl_float_data *rgb_user; + uint32_t extra_points; + bool use_half_points; + struct fixed31_32 x_max1; + struct fixed31_32 x_max2; + struct fixed31_32 x_min; + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; +}; + +/* OPP RELATED */ +#define TO_DCE80_OPP(opp)\ + container_of(opp, struct dce80_opp, base) + +struct dce80_opp_reg_offsets { + uint32_t fmt_offset; + uint32_t dcp_offset; + uint32_t crtc_offset; +}; + +struct dce80_opp { + struct output_pixel_processor base; + struct dce80_opp_reg_offsets offsets; + struct dce80_regamma regamma; +}; + +bool dce80_opp_construct(struct dce80_opp *opp80, + struct dc_context *ctx, + uint32_t inst); + +void dce80_opp_destroy(struct output_pixel_processor **opp); + +struct output_pixel_processor *dce80_opp_create( + struct dc_context *ctx, + uint32_t inst); + +/* REGAMMA RELATED */ +void dce80_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on); + +bool dce80_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *pamras); + +void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode); + +void dce80_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + +void dce80_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + +/* FORMATTER RELATED */ +void dce80_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + +void dce80_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params); + +void dce80_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c new file mode 100644 index 000000000000..bdb9e0a77982 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c @@ -0,0 +1,363 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce80_opp.h" +#include "basics/conversion.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#define DCP_REG(reg)\ + (reg + opp80->offsets.dcp_offset) + +enum { + OUTPUT_CSC_MATRIX_SIZE = 12 +}; + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + +static void program_color_matrix( + struct dce80_opp *opp80, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + struct dc_context *ctx = opp80->base.ctx; + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[0], + OUTPUT_CSC_C11_C12, + OUTPUT_CSC_C11); + + set_reg_field_value( + value, + tbl_entry->regval[1], + OUTPUT_CSC_C11_C12, + OUTPUT_CSC_C12); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[2], + OUTPUT_CSC_C13_C14, + OUTPUT_CSC_C13); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[3], + OUTPUT_CSC_C13_C14, + OUTPUT_CSC_C14); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[4], + OUTPUT_CSC_C21_C22, + OUTPUT_CSC_C21); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[5], + OUTPUT_CSC_C21_C22, + OUTPUT_CSC_C22); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[6], + OUTPUT_CSC_C23_C24, + OUTPUT_CSC_C23); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[7], + OUTPUT_CSC_C23_C24, + OUTPUT_CSC_C24); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[8], + OUTPUT_CSC_C31_C32, + OUTPUT_CSC_C31); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[9], + OUTPUT_CSC_C31_C32, + OUTPUT_CSC_C32); + + dm_write_reg(ctx, addr, value); + } + { + uint32_t value = 0; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34); + /* fixed S2.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[10], + OUTPUT_CSC_C33_C34, + OUTPUT_CSC_C33); + /* fixed S0.13 format */ + set_reg_field_value( + value, + tbl_entry->regval[11], + OUTPUT_CSC_C33_C34, + OUTPUT_CSC_C34); + + dm_write_reg(ctx, addr, value); + } +} + +static bool configure_graphics_mode( + struct dce80_opp *opp80, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + struct dc_context *ctx = opp80->base.ctx; + uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); + uint32_t value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { + set_reg_field_value( + value, + 4, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + } else { + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + set_reg_field_value( + value, + 1, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + default: + return false; + } + } + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + set_reg_field_value( + value, + 1, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + set_reg_field_value( + value, + 2, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + set_reg_field_value( + value, + 3, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + break; + default: + return false; + } + + } else + /* by pass */ + set_reg_field_value( + value, + 0, + OUTPUT_CSC_CONTROL, + OUTPUT_CSC_GRPH_MODE); + + addr = DCP_REG(mmOUTPUT_CSC_CONTROL); + dm_write_reg(ctx, addr, value); + + return true; +} + +void dce80_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix(opp80, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode(opp80, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); +} + +void dce80_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file */ + program_color_matrix(opp80, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix */ + + configure_graphics_mode(opp80, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c new file mode 100644 index 000000000000..433296a4ed12 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c @@ -0,0 +1,577 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_opp.h" + +#define FMT_REG(reg)\ + (reg + opp80->offsets.fmt_offset) + +/** + * set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE8 power saving reason. + */ +static void set_truncation( + struct dce80_opp *opp80, + const struct bit_depth_reduction_params *params) +{ + uint32_t value = 0; + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + + /*Disable truncation*/ + value = dm_read_reg(opp80->base.ctx, addr); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); + set_reg_field_value(value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); + + dm_write_reg(opp80->base.ctx, addr, value); + + /* no 10bpc trunc on DCE8*/ + if (params->flags.TRUNCATE_ENABLED == 0 || + params->flags.TRUNCATE_DEPTH == 2) + return; + + /*Set truncation depth and Enable truncation*/ + set_reg_field_value(value, 1, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); + set_reg_field_value(value, params->flags.TRUNCATE_MODE, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); + set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, + FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); + + dm_write_reg(opp80->base.ctx, addr, value); + +} + +/** + * set_spatial_dither + * 1) set spatial dithering mode: pattern of seed + * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp + * 3) set random seed + * 4) set random mode + * lfsr is reset every frame or not reset + * RGB dithering method + * 0: RGB data are all dithered with x^28+x^3+1 + * 1: R data is dithered with x^28+x^3+1 + * G data is dithered with x^28+X^9+1 + * B data is dithered with x^28+x^13+1 + * enable high pass filter or not + * 5) enable spatical dithering + */ +static void set_spatial_dither( + struct dce80_opp *opp80, + const struct bit_depth_reduction_params *params) +{ + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + uint32_t depth_cntl_value = 0; + uint32_t dither_r_value = 0; + uint32_t dither_g_value = 0; + uint32_t dither_b_value = 0; + + /*Disable spatial (random) dithering*/ + depth_cntl_value = dm_read_reg(opp80->base.ctx, addr); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE); + set_reg_field_value(depth_cntl_value, 0, + FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE); + + dm_write_reg(opp80->base.ctx, addr, depth_cntl_value); + + /* no 10bpc on DCE8*/ + if (params->flags.SPATIAL_DITHER_ENABLED == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 2) + return; + + /*Set seed for random values for + * spatial dithering for R,G,B channels*/ + addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED); + set_reg_field_value(dither_r_value, params->r_seed_value, + FMT_DITHER_RAND_R_SEED, + FMT_RAND_R_SEED); + dm_write_reg(opp80->base.ctx, addr, dither_r_value); + + addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED); + set_reg_field_value(dither_g_value, + params->g_seed_value, + FMT_DITHER_RAND_G_SEED, + FMT_RAND_G_SEED); + dm_write_reg(opp80->base.ctx, addr, dither_g_value); + + addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED); + set_reg_field_value(dither_b_value, params->b_seed_value, + FMT_DITHER_RAND_B_SEED, + FMT_RAND_B_SEED); + dm_write_reg(opp80->base.ctx, addr, dither_b_value); + + /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero + * offset for the R/Cr channel, lower 4LSB + * is forced to zeros. Typically set to 0 + * RGB and 0x80000 YCbCr. + */ + /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero + * offset for the G/Y channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB + * and 0x80000 YCbCr. + */ + /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero + * offset for the B/Cb channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB and + * 0x80000 YCbCr. + */ + + /*Set spatial dithering bit depth*/ + set_reg_field_value(depth_cntl_value, + params->flags.SPATIAL_DITHER_DEPTH, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_DEPTH); + + /* Set spatial dithering mode + * (default is Seed patterrn AAAA...) + */ + set_reg_field_value(depth_cntl_value, + params->flags.SPATIAL_DITHER_MODE, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_MODE); + + /*Reset only at startup*/ + set_reg_field_value(depth_cntl_value, + params->flags.FRAME_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_FRAME_RANDOM_ENABLE); + + /*Set RGB data dithered with x^28+x^3+1*/ + set_reg_field_value(depth_cntl_value, + params->flags.RGB_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_RGB_RANDOM_ENABLE); + + /*Disable High pass filter*/ + set_reg_field_value(depth_cntl_value, + params->flags.HIGHPASS_RANDOM, + FMT_BIT_DEPTH_CONTROL, + FMT_HIGHPASS_RANDOM_ENABLE); + + /*Enable spatial dithering*/ + set_reg_field_value(depth_cntl_value, + 1, + FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_EN); + + addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + dm_write_reg(opp80->base.ctx, addr, depth_cntl_value); + +} + +/** + * SetTemporalDither (Frame Modulation) + * 1) set temporal dither depth + * 2) select pattern: from hard-coded pattern or programmable pattern + * 3) select optimized strips for BGR or RGB LCD sub-pixel + * 4) set s matrix + * 5) set t matrix + * 6) set grey level for 0.25, 0.5, 0.75 + * 7) enable temporal dithering + */ +static void set_temporal_dither( + struct dce80_opp *opp80, + const struct bit_depth_reduction_params *params) +{ + uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + uint32_t value; + + /*Disable temporal (frame modulation) dithering first*/ + value = dm_read_reg(opp80->base.ctx, addr); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_RESET); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_OFFSET); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL); + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_50FRC_SEL); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_75FRC_SEL); + + dm_write_reg(opp80->base.ctx, addr, value); + + /* no 10bpc dither on DCE8*/ + if (params->flags.FRAME_MODULATION_ENABLED == 0 || + params->flags.FRAME_MODULATION_DEPTH == 2) + return; + + /* Set temporal dithering depth*/ + set_reg_field_value(value, + params->flags.FRAME_MODULATION_DEPTH, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_RESET); + + set_reg_field_value(value, + 0, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_OFFSET); + + /*Select legacy pattern based on FRC and Temporal level*/ + addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL); + dm_write_reg(opp80->base.ctx, addr, 0); + /*Set s matrix*/ + addr = FMT_REG( + mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); + dm_write_reg(opp80->base.ctx, addr, 0); + /*Set t matrix*/ + addr = FMT_REG( + mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); + dm_write_reg(opp80->base.ctx, addr, 0); + + /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ + set_reg_field_value(value, + params->flags.TEMPORAL_LEVEL, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL); + + set_reg_field_value(value, + params->flags.FRC25, + FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL); + + set_reg_field_value(value, + params->flags.FRC50, + FMT_BIT_DEPTH_CONTROL, + FMT_50FRC_SEL); + + set_reg_field_value(value, + params->flags.FRC75, + FMT_BIT_DEPTH_CONTROL, + FMT_75FRC_SEL); + + /*Enable bit reduction by temporal (frame modulation) dithering*/ + set_reg_field_value(value, + 1, + FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN); + + addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); + dm_write_reg(opp80->base.ctx, addr, value); + +} + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +static void set_clamping( + struct dce80_opp *opp80, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t clamp_cntl_value = 0; + uint32_t red_clamp_value = 0; + uint32_t green_clamp_value = 0; + uint32_t blue_clamp_value = 0; + uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); + + clamp_cntl_value = dm_read_reg(opp80->base.ctx, addr); + + set_reg_field_value(clamp_cntl_value, + 0, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 0, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + break; + + case CLAMPING_LIMITED_RANGE_8BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + + case CLAMPING_LIMITED_RANGE_10BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 2, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + case CLAMPING_LIMITED_RANGE_12BPC: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 3, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + set_reg_field_value(clamp_cntl_value, + 1, + FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN); + + set_reg_field_value(clamp_cntl_value, + 7, + FMT_CLAMP_CNTL, + FMT_CLAMP_COLOR_FORMAT); + + /*set the defaults*/ + set_reg_field_value(red_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_R, + FMT_CLAMP_LOWER_R); + + set_reg_field_value(red_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_R, + FMT_CLAMP_UPPER_R); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R); + dm_write_reg(opp80->base.ctx, addr, red_clamp_value); + + set_reg_field_value(green_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_G, + FMT_CLAMP_LOWER_G); + + set_reg_field_value(green_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_G, + FMT_CLAMP_UPPER_G); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G); + dm_write_reg(opp80->base.ctx, addr, green_clamp_value); + + set_reg_field_value(blue_clamp_value, + 0x10, + FMT_CLAMP_COMPONENT_B, + FMT_CLAMP_LOWER_B); + + set_reg_field_value(blue_clamp_value, + 0xFEF, + FMT_CLAMP_COMPONENT_B, + FMT_CLAMP_UPPER_B); + + addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B); + dm_write_reg(opp80->base.ctx, addr, blue_clamp_value); + + break; + + default: + break; + } + + addr = FMT_REG(mmFMT_CLAMP_CNTL); + /*Set clamp control*/ + dm_write_reg(opp80->base.ctx, addr, clamp_cntl_value); + +} + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void set_pixel_encoding( + struct dce80_opp *opp80, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t fmt_cntl_value; + uint32_t addr = FMT_REG(mmFMT_CONTROL); + + /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ + fmt_cntl_value = dm_read_reg(opp80->base.ctx, addr); + + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + set_reg_field_value(fmt_cntl_value, + 1, + FMT_CONTROL, + FMT_PIXEL_ENCODING); + + /*00 - Pixels drop mode ,01 - Pixels average mode*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_MODE); + + /*00 - Cb before Cr ,01 - Cr before Cb*/ + set_reg_field_value(fmt_cntl_value, + 0, + FMT_CONTROL, + FMT_SUBSAMPLING_ORDER); + } + dm_write_reg(opp80->base.ctx, addr, fmt_cntl_value); + +} + +void dce80_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + + set_truncation(opp80, params); + set_spatial_dither(opp80, params); + set_temporal_dither(opp80, params); +} + +void dce80_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + + set_clamping(opp80, params); + set_pixel_encoding(opp80, params); +} + +void dce80_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + uint32_t value; + bool enable_dyn_exp = false; + uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); + + value = dm_read_reg(opp->ctx, addr); + + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + + /* From HW programming guide: + FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output + FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ + if (color_sp == COLOR_SPACE_SRGB) + enable_dyn_exp = true; + + /*00 - 10-bit -> 12-bit dynamic expansion*/ + /*01 - 8-bit -> 12-bit dynamic expansion*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (color_dpth) { + case COLOR_DEPTH_888: + set_reg_field_value(value, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 1, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + break; + case COLOR_DEPTH_101010: + set_reg_field_value(value, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); + set_reg_field_value(value, 0, + FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); + break; + case COLOR_DEPTH_121212: + break; + default: + break; + } + } + + dm_write_reg(opp->ctx, addr, value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c new file mode 100644 index 000000000000..648e3ef35d91 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c @@ -0,0 +1,543 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dce80_opp.h" +#include "gamma_types.h" + +#define DCP_REG(reg)\ + (reg + opp80->offsets.dcp_offset) + +#define DCFE_REG(reg)\ + (reg + opp80->offsets.crtc_offset) + +enum { + MAX_PWL_ENTRY = 128, + MAX_REGIONS_NUMBER = 16 + +}; + +struct curve_config { + uint32_t offset; + int8_t segments[MAX_REGIONS_NUMBER]; + int8_t begin; +}; + +/* + ***************************************************************************** + * Function: regamma_config_regions_and_segments + * + * build regamma curve by using predefined hw points + * uses interface parameters ,like EDID coeff. + * + * @param : parameters interface parameters + * @return void + * + * @note + * + * @see + * + ***************************************************************************** + */ +static void regamma_config_regions_and_segments( + struct dce80_opp *opp80, const struct pwl_params *params) +{ + const struct gamma_curve *curve; + uint32_t value = 0; + + { + set_reg_field_value( + value, + params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START); + + set_reg_field_value( + value, + 0, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_START_CNTL), + value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[0].custom_float_slope, + REGAMMA_CNTLA_SLOPE_CNTL, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[1].custom_float_x, + REGAMMA_CNTLA_END_CNTL1, + REGAMMA_CNTLA_EXP_REGION_END); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); + } + { + value = 0; + set_reg_field_value( + value, + params->arr_points[2].custom_float_slope, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_BASE); + + set_reg_field_value( + value, + params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); + } + + curve = params->arr_curve_points; + + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_0_1, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); + + dm_write_reg( + opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_0_1), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_2_3, + REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_2_3), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_4_5, + REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_4_5), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_6_7, + REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_6_7), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_8_9, + REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_8_9), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_10_11, + REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_10_11), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_12_13, + REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_12_13), + value); + } + + curve += 2; + { + value = 0; + set_reg_field_value( + value, + curve[0].offset, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET); + + set_reg_field_value( + value, + curve[0].segments_num, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS); + + set_reg_field_value( + value, + curve[1].offset, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET); + + set_reg_field_value( + value, + curve[1].segments_num, + REGAMMA_CNTLA_REGION_14_15, + REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), + value); + } +} + +static void program_pwl( + struct dce80_opp *opp80, + const struct pwl_params *params) +{ + uint32_t value; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + value = dm_read_reg(opp80->base.ctx, + DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); + + set_reg_field_value( + value, + 1, + DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS); + + dm_write_reg(opp80->base.ctx, + DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value); + + while (counter < max_tries) { + value = + dm_read_reg( + opp80->base.ctx, + DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); + + if (get_reg_field_value( + value, + DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_MEM_PWR_STATE) == 0) + break; + + ++counter; + } + + if (counter == max_tries) { + dm_logger_write(opp80->base.ctx->logger, LOG_WARNING, + "%s: regamma lut was not powered on " + "in a timely manner," + " programming still proceeds\n", + __func__); + } + } + + value = 0; + + set_reg_field_value( + value, + 7, + REGAMMA_LUT_WRITE_EN_MASK, + REGAMMA_LUT_WRITE_EN_MASK); + + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); + dm_write_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_LUT_INDEX), 0); + + /* Program REGAMMA_LUT_DATA */ + { + const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); + + uint32_t i = 0; + + const struct pwl_result_data *rgb = + params->rgb_resulted; + + while (i != params->hw_points_num) { + dm_write_reg(opp80->base.ctx, addr, rgb->red_reg); + dm_write_reg(opp80->base.ctx, addr, rgb->green_reg); + dm_write_reg(opp80->base.ctx, addr, rgb->blue_reg); + + dm_write_reg(opp80->base.ctx, addr, + rgb->delta_red_reg); + dm_write_reg(opp80->base.ctx, addr, + rgb->delta_green_reg); + dm_write_reg(opp80->base.ctx, addr, + rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + value = dm_read_reg(opp80->base.ctx, + DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); + + set_reg_field_value( + value, + 0, + DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS); + + dm_write_reg(opp80->base.ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), + value); +} + +void dce80_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + + uint32_t value = + dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); + + set_reg_field_value( + value, + power_on, + DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS); + + set_reg_field_value( + value, + power_on, + DCFE_MEM_LIGHT_SLEEP_CNTL, + DCP_LUT_LIGHT_SLEEP_DIS); + + dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value); +} + +bool dce80_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + + regamma_config_regions_and_segments(opp80, params); + + program_pwl(opp80, params); + + return true; +} + +void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + struct dce80_opp *opp80 = TO_DCE80_OPP(opp); + uint32_t value = dm_read_reg(opp80->base.ctx, + DCP_REG(mmREGAMMA_CONTROL)); + + set_reg_field_value( + value, + mode, + REGAMMA_CONTROL, + GRPH_REGAMMA_MODE); + + dm_write_reg(opp80->base.ctx, DCP_REG(mmREGAMMA_CONTROL), value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c new file mode 100644 index 000000000000..06720407b6fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -0,0 +1,1063 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "irq/dce80/irq_service_dce80.h" +#include "dce110/dce110_timing_generator.h" +#include "dce110/dce110_mem_input.h" +#include "dce110/dce110_resource.h" +#include "dce80/dce80_timing_generator.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce80/dce80_mem_input.h" +#include "dce80/dce80_ipp.h" +#include "dce/dce_transform.h" +#include "dce80/dce80_opp.h" +#include "dce110/dce110_ipp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "dce80/dce80_hw_sequencer.h" + +#include "reg_helper.h" + +/* TODO remove this include */ + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL +#define mmDP_DPHY_INTERNAL_CTRL 0x1CDE +#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE +#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE +#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE +#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE +#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE +#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE +#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE +#endif + + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x1CCE + #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE + #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE + #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE + #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE + #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE + #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE +#endif + + +#ifndef mmHPD_DC_HPD_CONTROL + #define mmHPD_DC_HPD_CONTROL 0x189A + #define mmHPD0_DC_HPD_CONTROL 0x189A + #define mmHPD1_DC_HPD_CONTROL 0x18A2 + #define mmHPD2_DC_HPD_CONTROL 0x18AA + #define mmHPD3_DC_HPD_CONTROL 0x18B2 + #define mmHPD4_DC_HPD_CONTROL 0x18BA + #define mmHPD5_DC_HPD_CONTROL 0x18C2 +#endif + +#define DCE11_DIG_FE_CNTL 0x4a00 +#define DCE11_DIG_BE_CNTL 0x4a47 +#define DCE11_DP_SEC 0x4ac3 + +static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets[] = { + { + .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + +static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { +{ + .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL), +}, +{ + .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL), +} +}; + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE80_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST_DCE_BASE(id),\ + .AFMT_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_80(id),\ +} + + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 3, +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x1918 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce80_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce80_timing_generator_construct(tg110, ctx, instance, offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static struct stream_encoder *dce80_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE8_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE8_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE8_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce80_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce80_stream_encoder_create, + .create_hwseq = dce80_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static struct mem_input *dce80_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + struct dce110_mem_input *mem_input80 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input80) + return NULL; + + if (dce80_mem_input_construct(mem_input80, ctx, inst, offsets)) { + struct mem_input *mi = &mem_input80->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + mi->wa.single_head_rdreq_dmif_limit = 2; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input80); + return NULL; +} + +static void dce80_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce80_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) { + transform->prescaler_on = false; + return &transform->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static struct input_pixel_processor *dce80_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + struct dce110_ipp *ipp = + dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce80_ipp_construct(ipp, ctx, inst, offset)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +struct link_encoder *dce80_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + enc110->base.features.ycbcr420_supported = false; + enc110->base.features.max_hdmi_pixel_clock = 297000; + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +struct clock_source *dce80_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce80_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce80_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce80_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce80_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce80_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.dp_clock_source != NULL) + dce80_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.display_clock != NULL) { + dal_display_clock_destroy(&pool->base.display_clock); + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j, k; + + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (k = 0; k < MAX_PIPES; k++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[k]; + + if (context->res_ctx.pipe_ctx[k].stream != stream) + continue; + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = dce110_resource_build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); + + if (status != DC_OK) + return status; + + resource_build_info_frame(pipe_ctx); + + /* do not need to validate non root pipes */ + break; + } + } + } + + return DC_OK; +} + +enum dc_status dce80_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + /* TODO implement when needed but for now hardcode max value*/ + context->bw_results.dispclk_khz = 681000; + context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; + + return DC_OK; +} + +static bool dce80_validate_surface_sets( + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) { + if (set[i].surface_count == 0) + continue; + + if (set[i].surface_count > 1) + return false; + + if (set[i].surfaces[0]->clip_rect.width + != set[i].target->streams[0]->src.width + || set[i].surfaces[0]->clip_rect.height + != set[i].target->streams[0]->src.height) + return false; + if (set[i].surfaces[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +enum dc_status dce80_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status result = DC_ERROR_UNEXPECTED; + int i; + + if (!dce80_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + context->res_ctx.pool = dc->res_pool; + + for (i = 0; i < set_count; i++) { + context->targets[i] = DC_TARGET_TO_CORE(set[i].target); + dc_target_retain(&context->targets[i]->public); + context->target_count++; + } + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (!resource_validate_attach_surfaces( + set, set_count, dc->current_context, context)) { + DC_ERROR("Failed to attach surface to target!\n"); + return DC_FAIL_ATTACH_SURFACES; + } + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) + result = resource_build_scaling_params_for_context(dc, context); + + if (result == DC_OK) + result = dce80_validate_bandwidth(dc, context); + + return result; +} + +enum dc_status dce80_validate_guaranteed( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->res_ctx.pool = dc->res_pool; + + context->targets[0] = DC_TARGET_TO_CORE(dc_target); + dc_target_retain(&context->targets[0]->public); + context->target_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_target( + context, dc->public.caps.max_targets); + result = resource_build_scaling_params_for_context(dc, context); + } + + if (result == DC_OK) + result = dce80_validate_bandwidth(dc, context); + + return result; +} + +static void dce80_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce80_res_pool_funcs = { + .destroy = dce80_destroy_resource_pool, + .link_enc_create = dce80_link_encoder_create, + .validate_with_context = dce80_validate_with_context, + .validate_guaranteed = dce80_validate_guaranteed, + .validate_bandwidth = dce80_validate_bandwidth +}; + +static enum clocks_state dce80_resource_convert_clock_state_pp_to_dc( + enum dm_pp_clocks_state pp_clock_state) +{ + enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID; + + switch (pp_clock_state) { + case DM_PP_CLOCKS_STATE_INVALID: + dc_clocks_state = CLOCKS_STATE_INVALID; + break; + case DM_PP_CLOCKS_STATE_ULTRA_LOW: + dc_clocks_state = CLOCKS_STATE_ULTRA_LOW; + break; + case DM_PP_CLOCKS_STATE_LOW: + dc_clocks_state = CLOCKS_STATE_LOW; + break; + case DM_PP_CLOCKS_STATE_NOMINAL: + dc_clocks_state = CLOCKS_STATE_NOMINAL; + break; + case DM_PP_CLOCKS_STATE_PERFORMANCE: + dc_clocks_state = CLOCKS_STATE_PERFORMANCE; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6; + break; + case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: + dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7; + break; + default: + dc_clocks_state = CLOCKS_STATE_INVALID; + break; + } + + return dc_clocks_state; +} + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = -1; + pool->base.pipe_count = res_cap.num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 40; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dal_display_clock_dce80_create(ctx); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { + enum clocks_state max_clocks_state = + dce80_resource_convert_clock_state_pp_to_dc( + static_clk_info.max_clocks_state); + + dal_display_clock_store_max_clocks_state( + pool->base.display_clock, max_clocks_state); + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i, + &dce80_mi_reg_offsets[i]); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i, &ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce80_hw_sequencer_construct(dc)) + goto res_create_fail; + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce80_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h new file mode 100644 index 000000000000..2a0cdccddeaf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h @@ -0,0 +1,39 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE80_H__ +#define __DC_RESOURCE_DCE80_H__ + +#include "core_types.h" + +struct core_dc; +struct resource_pool; + +struct resource_pool *dce80_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +#endif /* __DC_RESOURCE_DCE80_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c new file mode 100644 index 000000000000..e8fae0a7eeb4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -0,0 +1,241 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE8 register header files */ +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dc_types.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "../dce110/dce110_timing_generator.h" +#include "dce80_timing_generator.h" + +#include "timing_generator.h" + +enum black_color_format { + BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, /* used as index in array */ + BLACK_COLOR_FORMAT_RGB_LIMITED, + BLACK_COLOR_FORMAT_YUV_TV, + BLACK_COLOR_FORMAT_YUV_CV, + BLACK_COLOR_FORMAT_YUV_SUPER_AA, + + BLACK_COLOR_FORMAT_COUNT +}; + +static const struct dce110_timing_generator_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +#define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10 + +#define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1) +#define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1) + +#define CRTC_REG(reg) (reg + tg110->offsets.crtc) +#define DCP_REG(reg) (reg + tg110->offsets.dcp) +#define DMIF_REG(reg) (reg + tg110->offsets.dmif) + +void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_khz) +{ + uint64_t pix_dur; + uint32_t addr = mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1 + + DCE110TG_FROM_TG(tg)->offsets.dmif; + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (pix_clk_khz == 0) + return; + + pix_dur = 1000000000 / pix_clk_khz; + + set_reg_field_value( + value, + pix_dur, + DPG_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION); + + dm_write_reg(tg->ctx, addr, value); +} + +static void program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + if (!use_vbios) + program_pix_dur(tg, timing->pix_clk_khz); + + dce110_tg_program_timing(tg, timing, use_vbios); +} + +static const struct timing_generator_funcs dce80_tg_funcs = { + .validate_timing = dce110_tg_validate_timing, + .program_timing = program_timing, + .enable_crtc = dce110_timing_generator_enable_crtc, + .disable_crtc = dce110_timing_generator_disable_crtc, + .is_counter_moving = dce110_timing_generator_is_counter_moving, + .get_position = dce110_timing_generator_get_crtc_positions, + .get_frame_count = dce110_timing_generator_get_vblank_counter, + .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, + .set_early_control = dce110_timing_generator_set_early_control, + .wait_for_state = dce110_tg_wait_for_state, + .set_blank = dce110_tg_set_blank, + .is_blanked = dce110_tg_is_blanked, + .set_colors = dce110_tg_set_colors, + .set_overscan_blank_color = + dce110_timing_generator_set_overscan_color_black, + .set_blank_color = dce110_timing_generator_program_blank_color, + .disable_vga = dce110_timing_generator_disable_vga, + .did_triggered_reset_occur = + dce110_timing_generator_did_triggered_reset_occur, + .setup_global_swap_lock = + dce110_timing_generator_setup_global_swap_lock, + .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, + .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, + .tear_down_global_swap_lock = + dce110_timing_generator_tear_down_global_swap_lock, + + /* DCE8.0 overrides */ + .enable_advanced_request = + dce80_timing_generator_enable_advanced_request, + .set_drr = + dce110_timing_generator_set_drr, +}; + +bool dce80_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + if (!tg110) + return false; + + tg110->controller_id = CONTROLLER_ID_D0 + instance; + tg110->base.inst = instance; + tg110->offsets = *offsets; + tg110->derived_offsets = reg_offsets[instance]; + + tg110->base.funcs = &dce80_tg_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + tg110->min_h_blank = 56; + tg110->min_h_front_porch = 4; + tg110->min_h_back_porch = 4; + + return true; +} + +void dce80_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL); + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (enable) { + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + if ((timing->v_sync_width + timing->v_front_porch) <= 3) { + set_reg_field_value( + value, + 3, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } else { + set_reg_field_value( + value, + 4, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PROGRESSIVE_START_LINE_EARLY); + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_INTERLACE_START_LINE_EARLY); + + dm_write_reg(tg->ctx, addr, value); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h new file mode 100644 index 000000000000..6e4722a970d7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h @@ -0,0 +1,45 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCE80_H__ +#define __DC_TIMING_GENERATOR_DCE80_H__ + +#include "timing_generator.h" +#include "../include/grph_object_id.h" + +/* DCE8.0 implementation inherits from DCE11.0 */ +bool dce80_timing_generator_construct( + struct dce110_timing_generator *tg, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets); + +/******** HW programming ************/ +void dce80_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing); + +#endif /* __DC_TIMING_GENERATOR_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h new file mode 100644 index 000000000000..d6c52d31f0f0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -0,0 +1,101 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * This file defines helper functions provided by the Display Manager to + * Display Core. + */ +#ifndef __DM_HELPERS__ +#define __DM_HELPERS__ + +#include "dc_types.h" +#include "dc.h" + +struct dp_mst_stream_allocation_table; + +enum dc_edid_status dm_helpers_parse_edid_caps( + struct dc_context *ctx, + const struct dc_edid *edid, + struct dc_edid_caps *edid_caps); + +/* + * Writes payload allocation table in immediate downstream device. + */ +bool dm_helpers_dp_mst_write_payload_allocation_table( + struct dc_context *ctx, + const struct dc_stream *stream, + struct dp_mst_stream_allocation_table *proposed_table, + bool enable); + +/* + * Polls for ACT (allocation change trigger) handled and + */ +bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( + struct dc_context *ctx, + const struct dc_stream *stream); +/* + * Sends ALLOCATE_PAYLOAD message. + */ +bool dm_helpers_dp_mst_send_payload_allocation( + struct dc_context *ctx, + const struct dc_stream *stream, + bool enable); + +bool dm_helpers_dp_mst_start_top_mgr( + struct dc_context *ctx, + const struct dc_link *link, + bool boot); + +void dm_helpers_dp_mst_stop_top_mgr( + struct dc_context *ctx, + const struct dc_link *link); + +/** + * OS specific aux read callback. + */ +bool dm_helpers_dp_read_dpcd( + struct dc_context *ctx, + const struct dc_link *link, + uint32_t address, + uint8_t *data, + uint32_t size); + +/** + * OS specific aux write callback. + */ +bool dm_helpers_dp_write_dpcd( + struct dc_context *ctx, + const struct dc_link *link, + uint32_t address, + const uint8_t *data, + uint32_t size); + +bool dm_helpers_submit_i2c( + struct dc_context *ctx, + const struct dc_link *link, + struct i2c_command *cmd); + + +#endif /* __DM_HELPERS__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h new file mode 100644 index 000000000000..7a3f10354830 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -0,0 +1,424 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * This file defines external dependencies of Display Core. + */ + +#ifndef __DM_SERVICES_H__ + +#define __DM_SERVICES_H__ + +/* TODO: remove when DC is complete. */ +#include "dm_services_types.h" +#include "logger_interface.h" +#include "link_service_types.h" + +#undef DEPRECATED + +/* + * + * general debug capabilities + * + */ +#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) + +#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + kgdb_breakpoint(); \ + } \ +} while (0) +#else +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + ; \ + } \ +} while (0) +#endif + +#if defined(CONFIG_DEBUG_KERNEL_DC) +#define ASSERT(expr) ASSERT_CRITICAL(expr) + +#else +#define ASSERT(expr) WARN_ON(!(expr)) +#endif + +#define BREAK_TO_DEBUGGER() ASSERT(0) + +#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ + +#define DC_ERR(...) do { \ + dm_error(__VA_ARGS__); \ + BREAK_TO_DEBUGGER(); \ +} while (0) + +#define dm_alloc(size) kzalloc(size, GFP_KERNEL) +#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) +#define dm_free(ptr) kfree(ptr) + +irq_handler_idx dm_register_interrupt( + struct dc_context *ctx, + struct dc_interrupt_params *int_params, + interrupt_handler ih, + void *handler_args); + + +/* + * + * GPU registers access + * + */ + +#define dm_read_reg(ctx, address) \ + dm_read_reg_func(ctx, address, __func__) + +static inline uint32_t dm_read_reg_func( + const struct dc_context *ctx, + uint32_t address, + const char *func_name) +{ + uint32_t value; + + if (address == 0) { + DC_ERR("invalid register read. address = 0"); + return 0; + } + + value = cgs_read_register(ctx->cgs_device, address); + +#if defined(__DAL_REGISTER_LOGGER__) + if (true == dal_reg_logger_should_dump_register()) { + dal_reg_logger_rw_count_increment(); + DRM_INFO("%s DC_READ_REG: 0x%x 0x%x\n", func_name, address, value); + } +#endif + return value; +} + +#define dm_write_reg(ctx, address, value) \ + dm_write_reg_func(ctx, address, value, __func__) + +static inline void dm_write_reg_func( + const struct dc_context *ctx, + uint32_t address, + uint32_t value, + const char *func_name) +{ +#if defined(__DAL_REGISTER_LOGGER__) + if (true == dal_reg_logger_should_dump_register()) { + dal_reg_logger_rw_count_increment(); + DRM_INFO("%s DC_WRITE_REG: 0x%x 0x%x\n", func_name, address, value); + } +#endif + + if (address == 0) { + DC_ERR("invalid register write. address = 0"); + return; + } + cgs_write_register(ctx->cgs_device, address, value); +} + +static inline uint32_t dm_read_index_reg( + const struct dc_context *ctx, + enum cgs_ind_reg addr_space, + uint32_t index) +{ + return cgs_read_ind_register(ctx->cgs_device, addr_space, index); +} + +static inline void dm_write_index_reg( + const struct dc_context *ctx, + enum cgs_ind_reg addr_space, + uint32_t index, + uint32_t value) +{ + cgs_write_ind_register(ctx->cgs_device, addr_space, index, value); +} + +static inline uint32_t get_reg_field_value_ex( + uint32_t reg_value, + uint32_t mask, + uint8_t shift) +{ + return (mask & reg_value) >> shift; +} + +#define get_reg_field_value(reg_value, reg_name, reg_field)\ + get_reg_field_value_ex(\ + (reg_value),\ + reg_name ## __ ## reg_field ## _MASK,\ + reg_name ## __ ## reg_field ## __SHIFT) + +static inline uint32_t set_reg_field_value_ex( + uint32_t reg_value, + uint32_t value, + uint32_t mask, + uint8_t shift) +{ + return (reg_value & ~mask) | (mask & (value << shift)); +} + +#define set_reg_field_value(reg_value, value, reg_name, reg_field)\ + (reg_value) = set_reg_field_value_ex(\ + (reg_value),\ + (value),\ + reg_name ## __ ## reg_field ## _MASK,\ + reg_name ## __ ## reg_field ## __SHIFT) + +uint32_t generic_reg_update_ex(const struct dc_context *ctx, + uint32_t addr, uint32_t reg_val, int n, + uint8_t shift1, uint32_t mask1, uint32_t field_value1, ...); + +#define FD(reg_field) reg_field ## __SHIFT, \ + reg_field ## _MASK + +/* + * return number of poll before condition is met + * return 0 if condition is not meet after specified time out tries + */ +unsigned int generic_reg_wait(const struct dc_context *ctx, + uint32_t addr, uint32_t mask, uint32_t shift, uint32_t condition_value, + unsigned int delay_between_poll_us, unsigned int time_out_num_tries, + const char *func_name); + +/************************************** + * Power Play (PP) interfaces + **************************************/ + +/* DAL calls this function to notify PP about clocks it needs for the Mode Set. + * This is done *before* it changes DCE clock. + * + * If required clock is higher than current, then PP will increase the voltage. + * + * If required clock is lower than current, then PP will defer reduction of + * voltage until the call to dc_service_pp_post_dce_clock_change(). + * + * \input - Contains clocks needed for Mode Set. + * + * \output - Contains clocks adjusted by PP which DAL should use for Mode Set. + * Valid only if function returns zero. + * + * \returns true - call is successful + * false - call failed + */ +bool dm_pp_pre_dce_clock_change( + struct dc_context *ctx, + struct dm_pp_gpu_clock_range *requested_state, + struct dm_pp_gpu_clock_range *actual_state); + +/* The returned clocks range are 'static' system clocks which will be used for + * mode validation purposes. + * + * \returns true - call is successful + * false - call failed + */ +bool dc_service_get_system_clocks_range( + const struct dc_context *ctx, + struct dm_pp_gpu_clock_range *sys_clks); + +/* Gets valid clocks levels from pplib + * + * input: clk_type - display clk / sclk / mem clk + * + * output: array of valid clock levels for given type in ascending order, + * with invalid levels filtered out + * + */ +bool dm_pp_get_clock_levels_by_type( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels *clk_level_info); + +bool dm_pp_get_clock_levels_by_type_with_latency( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels_with_latency *clk_level_info); + +bool dm_pp_get_clock_levels_by_type_with_voltage( + const struct dc_context *ctx, + enum dm_pp_clock_type clk_type, + struct dm_pp_clock_levels_with_voltage *clk_level_info); + +bool dm_pp_notify_wm_clock_changes( + const struct dc_context *ctx, + struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); + +/* DAL calls this function to notify PP about completion of Mode Set. + * For PP it means that current DCE clocks are those which were returned + * by dc_service_pp_pre_dce_clock_change(), in the 'output' parameter. + * + * If the clocks are higher than before, then PP does nothing. + * + * If the clocks are lower than before, then PP reduces the voltage. + * + * \returns true - call is successful + * false - call failed + */ +bool dm_pp_apply_display_requirements( + const struct dc_context *ctx, + const struct dm_pp_display_configuration *pp_display_cfg); + +bool dm_pp_apply_power_level_change_request( + const struct dc_context *ctx, + struct dm_pp_power_level_change_request *level_change_req); + +bool dm_pp_apply_clock_for_voltage_request( + const struct dc_context *ctx, + struct dm_pp_clock_for_voltage_req *clock_for_voltage_req); + +bool dm_pp_get_static_clocks( + const struct dc_context *ctx, + struct dm_pp_static_clock_info *static_clk_info); + +/****** end of PP interfaces ******/ + +enum platform_method { + PM_GET_AVAILABLE_METHODS = 1 << 0, + PM_GET_LID_STATE = 1 << 1, + PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2 +}; + +struct platform_info_params { + enum platform_method method; + void *data; +}; + +struct platform_info_brightness_caps { + uint8_t ac_level_percentage; + uint8_t dc_level_percentage; +}; + +struct platform_info_ext_brightness_caps { + struct platform_info_brightness_caps basic_caps; + struct data_point { + uint8_t luminance; + uint8_t signal_level; + } data_points[99]; + + uint8_t data_points_num; + uint8_t min_input_signal; + uint8_t max_input_signal; +}; + +bool dm_get_platform_info( + struct dc_context *ctx, + struct platform_info_params *params); + +struct persistent_data_flag { + bool save_per_link; + bool save_per_edid; +}; + +/* Call to write data in registry editor for persistent data storage. + * + * \inputs sink - identify edid/link for registry folder creation + * module name - identify folders for registry + * key name - identify keys within folders for registry + * params - value to write in defined folder/key + * size - size of the input params + * flag - determine whether to save by link or edid + * + * \returns true - call is successful + * false - call failed + * + * sink module key + * ----------------------------------------------------------------------------- + * NULL NULL NULL - failure + * NULL NULL - - create key with param value + * under base folder + * NULL - NULL - create module folder under base folder + * - NULL NULL - failure + * NULL - - - create key under module folder + * with no edid/link identification + * - NULL - - create key with param value + * under base folder + * - - NULL - create module folder under base folder + * - - - - create key under module folder + * with edid/link identification + */ +bool dm_write_persistent_data(struct dc_context *ctx, + const struct dc_sink *sink, + const char *module_name, + const char *key_name, + void *params, + unsigned int size, + struct persistent_data_flag *flag); + + +/* Call to read data in registry editor for persistent data storage. + * + * \inputs sink - identify edid/link for registry folder creation + * module name - identify folders for registry + * key name - identify keys within folders for registry + * size - size of the output params + * flag - determine whether it was save by link or edid + * + * \returns params - value read from defined folder/key + * true - call is successful + * false - call failed + * + * sink module key + * ----------------------------------------------------------------------------- + * NULL NULL NULL - failure + * NULL NULL - - read key under base folder + * NULL - NULL - failure + * - NULL NULL - failure + * NULL - - - read key under module folder + * with no edid/link identification + * - NULL - - read key under base folder + * - - NULL - failure + * - - - - read key under module folder + * with edid/link identification + */ +bool dm_read_persistent_data(struct dc_context *ctx, + const struct dc_sink *sink, + const char *module_name, + const char *key_name, + void *params, + unsigned int size, + struct persistent_data_flag *flag); + +void dm_delay_in_microseconds + (struct dc_context *ctx, unsigned int microSeconds); + +bool dm_query_extended_brightness_caps + (struct dc_context *ctx, enum dm_acpi_display_type display, + struct dm_acpi_atif_backlight_caps *pCaps); + +bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); + +/* + * + * print-out services + * + */ +#define dm_log_to_buffer(buffer, size, fmt, args)\ + vsnprintf(buffer, size, fmt, args) + +long dm_get_pid(void); +long dm_get_tgid(void); + +#endif /* __DM_SERVICES_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h new file mode 100644 index 000000000000..44bad17fa318 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -0,0 +1,242 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DM_SERVICES_TYPES_H__ +#define __DM_SERVICES_TYPES_H__ + +#include "os_types.h" +#include "dc_types.h" + +struct dm_pp_clock_range { + int min_khz; + int max_khz; +}; + +enum dm_pp_clocks_state { + DM_PP_CLOCKS_STATE_INVALID, + DM_PP_CLOCKS_STATE_ULTRA_LOW, + DM_PP_CLOCKS_STATE_LOW, + DM_PP_CLOCKS_STATE_NOMINAL, + DM_PP_CLOCKS_STATE_PERFORMANCE, + + /* Starting from DCE11, Max 8 levels of DPM state supported. */ + DM_PP_CLOCKS_DPM_STATE_LEVEL_INVALID = DM_PP_CLOCKS_STATE_INVALID, + DM_PP_CLOCKS_DPM_STATE_LEVEL_0 = DM_PP_CLOCKS_STATE_ULTRA_LOW, + DM_PP_CLOCKS_DPM_STATE_LEVEL_1 = DM_PP_CLOCKS_STATE_LOW, + DM_PP_CLOCKS_DPM_STATE_LEVEL_2 = DM_PP_CLOCKS_STATE_NOMINAL, + /* to be backward compatible */ + DM_PP_CLOCKS_DPM_STATE_LEVEL_3 = DM_PP_CLOCKS_STATE_PERFORMANCE, + DM_PP_CLOCKS_DPM_STATE_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1, +}; + +struct dm_pp_gpu_clock_range { + enum dm_pp_clocks_state clock_state; + struct dm_pp_clock_range sclk; + struct dm_pp_clock_range mclk; + struct dm_pp_clock_range eclk; + struct dm_pp_clock_range dclk; +}; + +enum dm_pp_clock_type { + DM_PP_CLOCK_TYPE_DISPLAY_CLK = 1, + DM_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */ + DM_PP_CLOCK_TYPE_MEMORY_CLK, + DM_PP_CLOCK_TYPE_DCFCLK, + DM_PP_CLOCK_TYPE_SOCCLK, + DM_PP_CLOCK_TYPE_PIXELCLK, + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK +}; + +#define DC_DECODE_PP_CLOCK_TYPE(clk_type) \ + (clk_type) == DM_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \ + (clk_type) == DM_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \ + (clk_type) == DM_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid" + +#define DM_PP_MAX_CLOCK_LEVELS 8 + +struct dm_pp_clock_levels { + uint32_t num_levels; + uint32_t clocks_in_khz[DM_PP_MAX_CLOCK_LEVELS]; +}; + +struct dm_pp_clock_with_latency { + uint32_t clocks_in_khz; + uint32_t latency_in_us; +}; + +struct dm_pp_clock_levels_with_latency { + uint32_t num_levels; + struct dm_pp_clock_with_latency data[DM_PP_MAX_CLOCK_LEVELS]; +}; + +struct dm_pp_clock_with_voltage { + uint32_t clocks_in_khz; + uint32_t voltage_in_mv; +}; + +struct dm_pp_clock_levels_with_voltage { + uint32_t num_levels; + struct dm_pp_clock_with_voltage data[DM_PP_MAX_CLOCK_LEVELS]; +}; + +struct dm_pp_single_disp_config { + enum signal_type signal; + uint8_t transmitter; + uint8_t ddi_channel_mapping; + uint8_t pipe_idx; + uint32_t src_height; + uint32_t src_width; + uint32_t v_refresh; + uint32_t sym_clock; /* HDMI only */ + struct dc_link_settings link_settings; /* DP only */ +}; + +#define MAX_WM_SETS 4 + +enum dm_pp_wm_set_id { + WM_SET_A = 0, + WM_SET_B, + WM_SET_C, + WM_SET_D, + WM_SET_INVALID = 0xffff, +}; + +struct dm_pp_clock_range_for_wm_set { + enum dm_pp_wm_set_id wm_set_id; + uint32_t wm_min_eng_clk_in_khz; + uint32_t wm_max_eng_clk_in_khz; + uint32_t wm_min_memg_clk_in_khz; + uint32_t wm_max_mem_clk_in_khz; +}; + +struct dm_pp_wm_sets_with_clock_ranges { + uint32_t num_wm_sets; + struct dm_pp_clock_range_for_wm_set wm_clk_ranges[MAX_WM_SETS]; +}; + +#define MAX_DISPLAY_CONFIGS 6 + +struct dm_pp_display_configuration { + bool nb_pstate_switch_disable;/* controls NB PState switch */ + bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */ + bool cpu_pstate_disable; + uint32_t cpu_pstate_separation_time; + + uint32_t min_memory_clock_khz; + uint32_t min_engine_clock_khz; + uint32_t min_engine_clock_deep_sleep_khz; + + uint32_t avail_mclk_switch_time_us; + uint32_t avail_mclk_switch_time_in_disp_active_us; + + uint32_t disp_clk_khz; + + bool all_displays_in_sync; + + uint8_t display_count; + struct dm_pp_single_disp_config disp_configs[MAX_DISPLAY_CONFIGS]; + + /*Controller Index of primary display - used in MCLK SMC switching hang + * SW Workaround*/ + uint8_t crtc_index; + /*htotal*1000/pixelclk - used in MCLK SMC switching hang SW Workaround*/ + uint32_t line_time_in_us; +}; + +struct dm_bl_data_point { + /* Brightness level in percentage */ + uint8_t luminance; + /* Brightness level as effective value in range 0-255, + * corresponding to above percentage + */ + uint8_t signalLevel; +}; + +/* Total size of the structure should not exceed 256 bytes */ +struct dm_acpi_atif_backlight_caps { + + + uint16_t size; /* Bytes 0-1 (2 bytes) */ + uint16_t flags; /* Byted 2-3 (2 bytes) */ + uint8_t errorCode; /* Byte 4 */ + uint8_t acLevelPercentage; /* Byte 5 */ + uint8_t dcLevelPercentage; /* Byte 6 */ + uint8_t minInputSignal; /* Byte 7 */ + uint8_t maxInputSignal; /* Byte 8 */ + uint8_t numOfDataPoints; /* Byte 9 */ + struct dm_bl_data_point dataPoints[99]; /* Bytes 10-207 (198 bytes)*/ +}; + +enum dm_acpi_display_type { + AcpiDisplayType_LCD1 = 0, + AcpiDisplayType_CRT1 = 1, + AcpiDisplayType_DFP1 = 3, + AcpiDisplayType_CRT2 = 4, + AcpiDisplayType_LCD2 = 5, + AcpiDisplayType_DFP2 = 7, + AcpiDisplayType_DFP3 = 9, + AcpiDisplayType_DFP4 = 10, + AcpiDisplayType_DFP5 = 11, + AcpiDisplayType_DFP6 = 12 +}; + +enum dm_pp_power_level { + DM_PP_POWER_LEVEL_INVALID, + DM_PP_POWER_LEVEL_ULTRA_LOW, + DM_PP_POWER_LEVEL_LOW, + DM_PP_POWER_LEVEL_NOMINAL, + DM_PP_POWER_LEVEL_PERFORMANCE, + + DM_PP_POWER_LEVEL_0 = DM_PP_POWER_LEVEL_ULTRA_LOW, + DM_PP_POWER_LEVEL_1 = DM_PP_POWER_LEVEL_LOW, + DM_PP_POWER_LEVEL_2 = DM_PP_POWER_LEVEL_NOMINAL, + DM_PP_POWER_LEVEL_3 = DM_PP_POWER_LEVEL_PERFORMANCE, + DM_PP_POWER_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1, + DM_PP_POWER_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1, + DM_PP_POWER_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1, + DM_PP_POWER_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1, +}; + +struct dm_pp_power_level_change_request { + enum dm_pp_power_level power_level; +}; + +struct dm_pp_clock_for_voltage_req { + enum dm_pp_clock_type clk_type; + uint32_t clocks_in_khz; +}; + +struct dm_pp_static_clock_info { + uint32_t max_sclk_khz; + uint32_t max_mclk_khz; + + /* max possible display block clocks state */ + enum dm_pp_clocks_state max_clocks_state; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile new file mode 100644 index 000000000000..a15c257fd2fa --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -0,0 +1,38 @@ +# +# Makefile for the 'gpio' sub-component of DAL. +# It provides the control and status of HW GPIO pins. + +GPIO = gpio_base.o gpio_service.o hw_factory.o \ + hw_gpio.o hw_hpd.o hw_ddc.o hw_translate.o + +AMD_DAL_GPIO = $(addprefix $(AMDDALPATH)/dc/gpio/,$(GPIO)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO) + +############################################################################### +# DCE 8x +############################################################################### +# all DCE8.x are derived from DCE8.0 +GPIO_DCE80 = hw_translate_dce80.o hw_factory_dce80.o + +AMD_DAL_GPIO_DCE80 = $(addprefix $(AMDDALPATH)/dc/gpio/dce80/,$(GPIO_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE80) + +############################################################################### +# DCE 11x +############################################################################### +GPIO_DCE110 = hw_translate_dce110.o hw_factory_dce110.o + +AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE110) + +############################################################################### +# Diagnostics on FPGA +############################################################################### +GPIO_DIAG_FPGA = hw_translate_diag.o hw_factory_diag.o + +AMD_DAL_GPIO_DIAG_FPGA = $(addprefix $(AMDDALPATH)/dc/gpio/diagnostics/,$(GPIO_DIAG_FPGA)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DIAG_FPGA) diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c new file mode 100644 index 000000000000..20d81bca119c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.c @@ -0,0 +1,178 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + +#include "hw_factory_dce110.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +/* set field name */ +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define REG(reg_name)\ + mm ## reg_name + +#define REGI(reg_name, block, id)\ + mm ## block ## id ## _ ## reg_name + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + +static const struct hw_factory_funcs funcs = { + .create_ddc_data = dal_hw_ddc_create, + .create_ddc_clock = dal_hw_ddc_create, + .create_generic = NULL, + .create_hpd = dal_hw_hpd_create, + .create_sync = NULL, + .create_gsl = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; + +/* + * dal_hw_factory_dce110_init + * + * @brief + * Initialize HW factory function pointers and pin info + * + * @param + * struct hw_factory *factory - [out] struct of function pointers + */ +void dal_hw_factory_dce110_init(struct hw_factory *factory) +{ + /*TODO check ASIC CAPs*/ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h new file mode 100644 index 000000000000..ecf06ed0d587 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_factory_dce110.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCE110_H__ +#define __DAL_HW_FACTORY_DCE110_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_dce110_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c new file mode 100644 index 000000000000..ac4cddbba815 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.c @@ -0,0 +1,387 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "hw_translate_dce110.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case mmDC_GPIO_GENERIC_A: + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* HPD */ + case mmDC_GPIO_HPD_A: + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* SYNCA */ + case mmDC_GPIO_SYNCA_A: + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* mmDC_GPIO_GENLK_MASK */ + case mmDC_GPIO_GENLK_A: + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case mmDC_GPIO_DDC1_A: + *en = GPIO_DDC_LINE_DDC1; + return true; + case mmDC_GPIO_DDC2_A: + *en = GPIO_DDC_LINE_DDC2; + return true; + case mmDC_GPIO_DDC3_A: + *en = GPIO_DDC_LINE_DDC3; + return true; + case mmDC_GPIO_DDC4_A: + *en = GPIO_DDC_LINE_DDC4; + return true; + case mmDC_GPIO_DDC5_A: + *en = GPIO_DDC_LINE_DDC5; + return true; + case mmDC_GPIO_DDC6_A: + *en = GPIO_DDC_LINE_DDC6; + return true; + case mmDC_GPIO_DDCVGA_A: + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case mmDC_GPIO_I2CPAD_A: + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case mmDC_GPIO_PWRSEQ_A: + case mmDC_GPIO_PAD_STRENGTH_1: + case mmDC_GPIO_PAD_STRENGTH_2: + case mmDC_GPIO_DEBUG: + return false; + /* UNEXPECTED */ + default: + ASSERT_CRITICAL(false); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = mmDC_GPIO_GENERIC_A; + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = mmDC_GPIO_HPD_A; + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_VIP_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +/* + * dal_hw_translate_dce110_init + * + * @brief + * Initialize Hw translate function pointers. + * + * @param + * struct hw_translate *tr - [out] struct of function pointers + * + */ +void dal_hw_translate_dce110_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h new file mode 100644 index 000000000000..4d16e09853c8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce110/hw_translate_dce110.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCE110_H__ +#define __DAL_HW_TRANSLATE_DCE110_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_dce110_init(struct hw_translate *tr); + +#endif /* __DAL_HW_TRANSLATE_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c new file mode 100644 index 000000000000..48b67866377e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c @@ -0,0 +1,173 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + +#include "hw_factory_dce80.h" + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#define REG(reg_name)\ + mm ## reg_name + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define HPD_REG_LIST_DCE8(id) \ + HPD_GPIO_REG_LIST(id), \ + .int_status = mmDC_HPD ## id ## _INT_STATUS,\ + .toggle_filt_cntl = mmDC_HPD ## id ## _TOGGLE_FILT_CNTL + +#define HPD_MASK_SH_LIST_DCE8(mask_sh) \ + .DC_HPD_SENSE_DELAYED = DC_HPD1_INT_STATUS__DC_HPD1_SENSE_DELAYED ## mask_sh,\ + .DC_HPD_SENSE = DC_HPD1_INT_STATUS__DC_HPD1_SENSE ## mask_sh,\ + .DC_HPD_CONNECT_INT_DELAY = DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_CONNECT_INT_DELAY ## mask_sh,\ + .DC_HPD_DISCONNECT_INT_DELAY = DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_DISCONNECT_INT_DELAY ## mask_sh + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST_DCE8(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5), + hpd_regs(6) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST_DCE8(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST_DCE8(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + +static const struct hw_factory_funcs funcs = { + .create_ddc_data = dal_hw_ddc_create, + .create_ddc_clock = dal_hw_ddc_create, + .create_generic = NULL, + .create_hpd = dal_hw_hpd_create, + .create_sync = NULL, + .create_gsl = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; + +void dal_hw_factory_dce80_init( + struct hw_factory *factory) +{ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h new file mode 100644 index 000000000000..e78a8b36f35a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCE80_H__ +#define __DAL_HW_FACTORY_DCE80_H__ + +void dal_hw_factory_dce80_init( + struct hw_factory *factory); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c new file mode 100644 index 000000000000..fabb9da504be --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c @@ -0,0 +1,411 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "hw_translate_dce80.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" +#include "smu/smu_7_0_1_d.h" + +/* + * @brief + * Returns index of first bit (starting with LSB) which is set + */ +static uint32_t index_from_vector( + uint32_t vector) +{ + uint32_t result = 0; + uint32_t mask = 1; + + do { + if (vector == mask) + return result; + + ++result; + mask <<= 1; + } while (mask); + + BREAK_TO_DEBUGGER(); + + return GPIO_ENUM_UNKNOWN; +} + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case mmDC_GPIO_GENERIC_A: + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* HPD */ + case mmDC_GPIO_HPD_A: + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* SYNCA */ + case mmDC_GPIO_SYNCA_A: + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* mmDC_GPIO_GENLK_MASK */ + case mmDC_GPIO_GENLK_A: + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* GPIOPAD */ + case mmGPIOPAD_A: + *id = GPIO_ID_GPIO_PAD; + *en = index_from_vector(mask); + return (*en <= GPIO_GPIO_PAD_MAX); + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case mmDC_GPIO_DDC1_A: + *en = GPIO_DDC_LINE_DDC1; + return true; + case mmDC_GPIO_DDC2_A: + *en = GPIO_DDC_LINE_DDC2; + return true; + case mmDC_GPIO_DDC3_A: + *en = GPIO_DDC_LINE_DDC3; + return true; + case mmDC_GPIO_DDC4_A: + *en = GPIO_DDC_LINE_DDC4; + return true; + case mmDC_GPIO_DDC5_A: + *en = GPIO_DDC_LINE_DDC5; + return true; + case mmDC_GPIO_DDC6_A: + *en = GPIO_DDC_LINE_DDC6; + return true; + case mmDC_GPIO_DDCVGA_A: + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case mmDC_GPIO_I2CPAD_A: + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case mmDC_GPIO_PWRSEQ_A: + case mmDC_GPIO_PAD_STRENGTH_1: + case mmDC_GPIO_PAD_STRENGTH_2: + case mmDC_GPIO_DEBUG: + return false; + /* UNEXPECTED */ + default: + BREAK_TO_DEBUGGER(); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = mmDC_GPIO_GENERIC_A; + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = mmDC_GPIO_HPD_A; + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GPIO_PAD: + info->offset = mmGPIOPAD_A; + info->mask = (1 << en); + result = (info->mask <= GPIO_GPIO_PAD_MAX); + break; + case GPIO_ID_VIP_PAD: + default: + BREAK_TO_DEBUGGER(); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +void dal_hw_translate_dce80_init( + struct hw_translate *translate) +{ + translate->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h new file mode 100644 index 000000000000..374f2f3282a1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCE80_H__ +#define __DAL_HW_TRANSLATE_DCE80_H__ + +void dal_hw_translate_dce80_init( + struct hw_translate *tr); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h new file mode 100644 index 000000000000..9c4a56c738c0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h @@ -0,0 +1,150 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_ + +#include "gpio_regs.h" + +/****************************** new register headers */ +/*** following in header */ + +#define DDC_GPIO_REG_LIST_ENTRY(type,cd,id) \ + .type ## _reg = REG(DC_GPIO_DDC ## id ## _ ## type),\ + .type ## _mask = DC_GPIO_DDC ## id ## _ ## type ## __DC_GPIO_DDC ## id ## cd ## _ ## type ## _MASK,\ + .type ## _shift = DC_GPIO_DDC ## id ## _ ## type ## __DC_GPIO_DDC ## id ## cd ## _ ## type ## __SHIFT + +#define DDC_GPIO_REG_LIST(cd,id) \ + {\ + DDC_GPIO_REG_LIST_ENTRY(MASK,cd,id),\ + DDC_GPIO_REG_LIST_ENTRY(A,cd,id),\ + DDC_GPIO_REG_LIST_ENTRY(EN,cd,id),\ + DDC_GPIO_REG_LIST_ENTRY(Y,cd,id)\ + } + +#define DDC_REG_LIST(cd,id) \ + DDC_GPIO_REG_LIST(cd,id),\ + .ddc_setup = REG(DC_I2C_DDC ## id ## _SETUP) + +#define DDC_GPIO_VGA_REG_LIST_ENTRY(type,cd)\ + .type ## _reg = REG(DC_GPIO_DDCVGA_ ## type),\ + .type ## _mask = DC_GPIO_DDCVGA_ ## type ## __DC_GPIO_DDCVGA ## cd ## _ ## type ## _MASK,\ + .type ## _shift = DC_GPIO_DDCVGA_ ## type ## __DC_GPIO_DDCVGA ## cd ## _ ## type ## __SHIFT + +#define DDC_GPIO_VGA_REG_LIST(cd) \ + {\ + DDC_GPIO_VGA_REG_LIST_ENTRY(MASK,cd),\ + DDC_GPIO_VGA_REG_LIST_ENTRY(A,cd),\ + DDC_GPIO_VGA_REG_LIST_ENTRY(EN,cd),\ + DDC_GPIO_VGA_REG_LIST_ENTRY(Y,cd)\ + } + +#define DDC_VGA_REG_LIST(cd) \ + DDC_GPIO_VGA_REG_LIST(cd),\ + .ddc_setup = mmDC_I2C_DDCVGA_SETUP + +#define DDC_GPIO_I2C_REG_LIST_ENTRY(type,cd) \ + .type ## _reg = REG(DC_GPIO_I2CPAD_ ## type),\ + .type ## _mask = DC_GPIO_I2CPAD_ ## type ## __DC_GPIO_ ## cd ## _ ## type ## _MASK,\ + .type ## _shift = DC_GPIO_I2CPAD_ ## type ## __DC_GPIO_ ## cd ## _ ## type ## __SHIFT + +#define DDC_GPIO_I2C_REG_LIST(cd) \ + {\ + DDC_GPIO_I2C_REG_LIST_ENTRY(MASK,cd),\ + DDC_GPIO_I2C_REG_LIST_ENTRY(A,cd),\ + DDC_GPIO_I2C_REG_LIST_ENTRY(EN,cd),\ + DDC_GPIO_I2C_REG_LIST_ENTRY(Y,cd)\ + } + +#define DDC_I2C_REG_LIST(cd) \ + DDC_GPIO_I2C_REG_LIST(cd),\ + .ddc_setup = 0 + +#define DDC_MASK_SH_LIST(mask_sh) \ + SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\ + SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_EDID_DETECT_ENABLE, mask_sh),\ + SF_DDC(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_EDID_DETECT_MODE, mask_sh),\ + SF_DDC(DC_GPIO_DDC1_MASK, DC_GPIO_DDC1DATA_PD_EN, mask_sh),\ + SF_DDC(DC_GPIO_DDC1_MASK, DC_GPIO_DDC1CLK_PD_EN, mask_sh),\ + SF_DDC(DC_GPIO_DDC1_MASK, AUX_PAD1_MODE, mask_sh),\ + SF_DDC(DC_GPIO_I2CPAD_MASK, DC_GPIO_SDA_PD_DIS, mask_sh),\ + SF_DDC(DC_GPIO_I2CPAD_MASK, DC_GPIO_SCL_PD_DIS, mask_sh) + + +struct ddc_registers { + struct gpio_registers gpio; + uint32_t ddc_setup; +}; + +struct ddc_sh_mask { + /* i2c_dd_setup */ + uint32_t DC_I2C_DDC1_ENABLE; + uint32_t DC_I2C_DDC1_EDID_DETECT_ENABLE; + uint32_t DC_I2C_DDC1_EDID_DETECT_MODE; + /* ddc1_mask */ + uint32_t DC_GPIO_DDC1DATA_PD_EN; + uint32_t DC_GPIO_DDC1CLK_PD_EN; + uint32_t AUX_PAD1_MODE; + /* i2cpad_mask */ + uint32_t DC_GPIO_SDA_PD_DIS; + uint32_t DC_GPIO_SCL_PD_DIS; +}; + + + +/*** following in dc_resource */ + +#define ddc_data_regs(id) \ +{\ + DDC_REG_LIST(DATA,id)\ +} + +#define ddc_clk_regs(id) \ +{\ + DDC_REG_LIST(CLK,id)\ +} + +#define ddc_vga_data_regs \ +{\ + DDC_VGA_REG_LIST(DATA)\ +} + +#define ddc_vga_clk_regs \ +{\ + DDC_VGA_REG_LIST(CLK)\ +} + +#define ddc_i2c_data_regs \ +{\ + DDC_I2C_REG_LIST(SDA)\ +} + +#define ddc_i2c_clk_regs \ +{\ + DDC_I2C_REG_LIST(SCL)\ +} + + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_DDC_REGS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c new file mode 100644 index 000000000000..26695b963c58 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.c @@ -0,0 +1,63 @@ +/* + * Copyright 2013-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + +/* + * Header of this unit + */ + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +/* function table */ +static const struct hw_factory_funcs funcs = { + .create_ddc_data = NULL, + .create_ddc_clock = NULL, + .create_generic = NULL, + .create_hpd = NULL, + .create_sync = NULL, + .create_gsl = NULL, +}; + +void dal_hw_factory_diag_fpga_init(struct hw_factory *factory) +{ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h new file mode 100644 index 000000000000..8a74f6adb8ee --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_factory_diag.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DIAG_FPGA_H__ +#define __DAL_HW_FACTORY_DIAG_FPGA_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_diag_fpga_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DIAG_FPGA_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c new file mode 100644 index 000000000000..bf9068846927 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.c @@ -0,0 +1,40 @@ +/* + * Copyright 2013-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" + +#include "../hw_translate.h" + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = NULL, + .id_to_offset = NULL, +}; + +void dal_hw_translate_diag_fpga_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h new file mode 100644 index 000000000000..4f053241fe96 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/diagnostics/hw_translate_diag.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DIAG_FPGA_H__ +#define __DAL_HW_TRANSLATE_DIAG_FPGA_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_diag_fpga_init(struct hw_translate *tr); + +#endif /* __DAL_HW_TRANSLATE_DIAG_FPGA_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c new file mode 100644 index 000000000000..d42eb3de2ea4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c @@ -0,0 +1,272 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "dm_services.h" + +#include "include/gpio_interface.h" +#include "include/gpio_service_interface.h" +#include "hw_gpio.h" +#include "hw_translate.h" +#include "hw_factory.h" +#include "gpio_service.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +/* + * @brief + * Public API + */ + +enum gpio_result dal_gpio_open( + struct gpio *gpio, + enum gpio_mode mode) +{ + return dal_gpio_open_ex(gpio, mode); +} + +enum gpio_result dal_gpio_open_ex( + struct gpio *gpio, + enum gpio_mode mode) +{ + if (gpio->pin) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_ALREADY_OPENED; + } + + gpio->mode = mode; + + return dal_gpio_service_open( + gpio->service, gpio->id, gpio->en, mode, &gpio->pin); +} + +enum gpio_result dal_gpio_get_value( + const struct gpio *gpio, + uint32_t *value) +{ + if (!gpio->pin) { + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NULL_HANDLE; + } + + return gpio->pin->funcs->get_value(gpio->pin, value); +} + +enum gpio_result dal_gpio_set_value( + const struct gpio *gpio, + uint32_t value) +{ + if (!gpio->pin) { + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NULL_HANDLE; + } + + return gpio->pin->funcs->set_value(gpio->pin, value); +} + +enum gpio_mode dal_gpio_get_mode( + const struct gpio *gpio) +{ + return gpio->mode; +} + +enum gpio_result dal_gpio_change_mode( + struct gpio *gpio, + enum gpio_mode mode) +{ + if (!gpio->pin) { + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NULL_HANDLE; + } + + return gpio->pin->funcs->change_mode(gpio->pin, mode); +} + +enum gpio_id dal_gpio_get_id( + const struct gpio *gpio) +{ + return gpio->id; +} + +uint32_t dal_gpio_get_enum( + const struct gpio *gpio) +{ + return gpio->en; +} + +enum gpio_result dal_gpio_set_config( + struct gpio *gpio, + const struct gpio_config_data *config_data) +{ + if (!gpio->pin) { + BREAK_TO_DEBUGGER(); + return GPIO_RESULT_NULL_HANDLE; + } + + return gpio->pin->funcs->set_config(gpio->pin, config_data); +} + +enum gpio_result dal_gpio_get_pin_info( + const struct gpio *gpio, + struct gpio_pin_info *pin_info) +{ + return gpio->service->translate.funcs->id_to_offset( + gpio->id, gpio->en, pin_info) ? + GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA; +} + +enum sync_source dal_gpio_get_sync_source( + const struct gpio *gpio) +{ + switch (gpio->id) { + case GPIO_ID_GENERIC: + switch (gpio->en) { + case GPIO_GENERIC_A: + return SYNC_SOURCE_IO_GENERIC_A; + case GPIO_GENERIC_B: + return SYNC_SOURCE_IO_GENERIC_B; + case GPIO_GENERIC_C: + return SYNC_SOURCE_IO_GENERIC_C; + case GPIO_GENERIC_D: + return SYNC_SOURCE_IO_GENERIC_D; + case GPIO_GENERIC_E: + return SYNC_SOURCE_IO_GENERIC_E; + case GPIO_GENERIC_F: + return SYNC_SOURCE_IO_GENERIC_F; + default: + return SYNC_SOURCE_NONE; + } + break; + case GPIO_ID_SYNC: + switch (gpio->en) { + case GPIO_SYNC_HSYNC_A: + return SYNC_SOURCE_IO_HSYNC_A; + case GPIO_SYNC_VSYNC_A: + return SYNC_SOURCE_IO_VSYNC_A; + case GPIO_SYNC_HSYNC_B: + return SYNC_SOURCE_IO_HSYNC_B; + case GPIO_SYNC_VSYNC_B: + return SYNC_SOURCE_IO_VSYNC_B; + default: + return SYNC_SOURCE_NONE; + } + break; + case GPIO_ID_HPD: + switch (gpio->en) { + case GPIO_HPD_1: + return SYNC_SOURCE_IO_HPD1; + case GPIO_HPD_2: + return SYNC_SOURCE_IO_HPD2; + default: + return SYNC_SOURCE_NONE; + } + break; + case GPIO_ID_GSL: + switch (gpio->en) { + case GPIO_GSL_GENLOCK_CLOCK: + return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK; + case GPIO_GSL_GENLOCK_VSYNC: + return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC; + case GPIO_GSL_SWAPLOCK_A: + return SYNC_SOURCE_GSL_IO_SWAPLOCK_A; + case GPIO_GSL_SWAPLOCK_B: + return SYNC_SOURCE_GSL_IO_SWAPLOCK_B; + default: + return SYNC_SOURCE_NONE; + } + break; + default: + return SYNC_SOURCE_NONE; + } +} + +enum gpio_pin_output_state dal_gpio_get_output_state( + const struct gpio *gpio) +{ + return gpio->output_state; +} + +void dal_gpio_close( + struct gpio *gpio) +{ + if (!gpio) + return; + + dal_gpio_service_close(gpio->service, &gpio->pin); + + gpio->mode = GPIO_MODE_UNKNOWN; +} + +/* + * @brief + * Creation and destruction + */ + +struct gpio *dal_gpio_create( + struct gpio_service *service, + enum gpio_id id, + uint32_t en, + enum gpio_pin_output_state output_state) +{ + struct gpio *gpio = dm_alloc(sizeof(struct gpio)); + + if (!gpio) { + ASSERT_CRITICAL(false); + return NULL; + } + + gpio->service = service; + gpio->pin = NULL; + gpio->id = id; + gpio->en = en; + gpio->mode = GPIO_MODE_UNKNOWN; + gpio->output_state = output_state; + + return gpio; +} + +void dal_gpio_destroy( + struct gpio **gpio) +{ + if (!gpio || !*gpio) { + ASSERT_CRITICAL(false); + return; + } + + dal_gpio_close(*gpio); + + dm_free(*gpio); + + *gpio = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h new file mode 100644 index 000000000000..5c5925299f8d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_regs.h @@ -0,0 +1,45 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_ + +struct gpio_registers { + uint32_t MASK_reg; + uint32_t MASK_mask; + uint32_t MASK_shift; + uint32_t A_reg; + uint32_t A_mask; + uint32_t A_shift; + uint32_t EN_reg; + uint32_t EN_mask; + uint32_t EN_shift; + uint32_t Y_reg; + uint32_t Y_mask; + uint32_t Y_shift; +}; + + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_GPIO_REGS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c new file mode 100644 index 000000000000..eeb1cd0f75a6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -0,0 +1,592 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "dm_services.h" +#include "include/gpio_interface.h" +#include "include/gpio_service_interface.h" +#include "hw_translate.h" +#include "hw_factory.h" + +/* + * Header of this unit + */ + +#include "gpio_service.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "hw_gpio.h" + +/* + * @brief + * Public API. + */ + +struct gpio_service *dal_gpio_service_create( + enum dce_version dce_version_major, + enum dce_version dce_version_minor, + struct dc_context *ctx) +{ + struct gpio_service *service; + + uint32_t index_of_id; + + service = dm_alloc(sizeof(struct gpio_service)); + + if (!service) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (!dal_hw_translate_init(&service->translate, dce_version_major, + dce_version_minor)) { + BREAK_TO_DEBUGGER(); + goto failure_1; + } + + if (!dal_hw_factory_init(&service->factory, dce_version_major, + dce_version_minor)) { + BREAK_TO_DEBUGGER(); + goto failure_1; + } + + /* allocate and initialize business storage */ + { + const uint32_t bits_per_uint = sizeof(uint32_t) << 3; + + index_of_id = 0; + service->ctx = ctx; + + do { + uint32_t number_of_bits = + service->factory.number_of_pins[index_of_id]; + + uint32_t number_of_uints = + (number_of_bits + bits_per_uint - 1) / + bits_per_uint; + + uint32_t *slot; + + if (number_of_bits) { + uint32_t index_of_uint = 0; + + slot = dm_alloc(number_of_uints * sizeof(uint32_t)); + + if (!slot) { + BREAK_TO_DEBUGGER(); + goto failure_2; + } + + do { + slot[index_of_uint] = 0; + + ++index_of_uint; + } while (index_of_uint < number_of_uints); + } else + slot = NULL; + + service->busyness[index_of_id] = slot; + + ++index_of_id; + } while (index_of_id < GPIO_ID_COUNT); + } + + return service; + +failure_2: + while (index_of_id) { + uint32_t *slot; + + --index_of_id; + + slot = service->busyness[index_of_id]; + + if (slot) + dm_free(slot); + }; + +failure_1: + dm_free(service); + + return NULL; +} + +struct gpio *dal_gpio_service_create_irq( + struct gpio_service *service, + uint32_t offset, + uint32_t mask) +{ + enum gpio_id id; + uint32_t en; + + if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) { + ASSERT_CRITICAL(false); + return NULL; + } + + return dal_gpio_create_irq(service, id, en); +} + +void dal_gpio_service_destroy( + struct gpio_service **ptr) +{ + if (!ptr || !*ptr) { + BREAK_TO_DEBUGGER(); + return; + } + + /* free business storage */ + { + uint32_t index_of_id = 0; + + do { + uint32_t *slot = (*ptr)->busyness[index_of_id]; + + if (slot) + dm_free(slot); + + ++index_of_id; + } while (index_of_id < GPIO_ID_COUNT); + } + + dm_free(*ptr); + + *ptr = NULL; +} + +/* + * @brief + * Private API. + */ + +static bool is_pin_busy( + const struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + const uint32_t bits_per_uint = sizeof(uint32_t) << 3; + + const uint32_t *slot = service->busyness[id] + (en / bits_per_uint); + + return 0 != (*slot & (1 << (en % bits_per_uint))); +} + +static void set_pin_busy( + struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + const uint32_t bits_per_uint = sizeof(uint32_t) << 3; + + service->busyness[id][en / bits_per_uint] |= + (1 << (en % bits_per_uint)); +} + +static void set_pin_free( + struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + const uint32_t bits_per_uint = sizeof(uint32_t) << 3; + + service->busyness[id][en / bits_per_uint] &= + ~(1 << (en % bits_per_uint)); +} + +enum gpio_result dal_gpio_service_open( + struct gpio_service *service, + enum gpio_id id, + uint32_t en, + enum gpio_mode mode, + struct hw_gpio_pin **ptr) +{ + struct hw_gpio_pin *pin; + + if (!service->busyness[id]) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_OPEN_FAILED; + } + + if (is_pin_busy(service, id, en)) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_DEVICE_BUSY; + } + + switch (id) { + case GPIO_ID_DDC_DATA: + pin = service->factory.funcs->create_ddc_data( + service->ctx, id, en); + service->factory.funcs->define_ddc_registers(pin, en); + break; + case GPIO_ID_DDC_CLOCK: + pin = service->factory.funcs->create_ddc_clock( + service->ctx, id, en); + service->factory.funcs->define_ddc_registers(pin, en); + break; + case GPIO_ID_GENERIC: + pin = service->factory.funcs->create_generic( + service->ctx, id, en); + break; + case GPIO_ID_HPD: + pin = service->factory.funcs->create_hpd( + service->ctx, id, en); + service->factory.funcs->define_hpd_registers(pin, en); + break; + case GPIO_ID_SYNC: + pin = service->factory.funcs->create_sync( + service->ctx, id, en); + break; + case GPIO_ID_GSL: + pin = service->factory.funcs->create_gsl( + service->ctx, id, en); + break; + default: + ASSERT_CRITICAL(false); + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } + + if (!pin) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } + + if (!pin->funcs->open(pin, mode)) { + ASSERT_CRITICAL(false); + dal_gpio_service_close(service, &pin); + return GPIO_RESULT_OPEN_FAILED; + } + + set_pin_busy(service, id, en); + *ptr = pin; + return GPIO_RESULT_OK; +} + +void dal_gpio_service_close( + struct gpio_service *service, + struct hw_gpio_pin **ptr) +{ + struct hw_gpio_pin *pin; + + if (!ptr) { + ASSERT_CRITICAL(false); + return; + } + + pin = *ptr; + + if (pin) { + set_pin_free(service, pin->id, pin->en); + + pin->funcs->close(pin); + + pin->funcs->destroy(ptr); + } +} + + +enum dc_irq_source dal_irq_get_source( + const struct gpio *irq) +{ + enum gpio_id id = dal_gpio_get_id(irq); + + switch (id) { + case GPIO_ID_HPD: + return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 + + dal_gpio_get_enum(irq)); + case GPIO_ID_GPIO_PAD: + return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 + + dal_gpio_get_enum(irq)); + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +enum dc_irq_source dal_irq_get_rx_source( + const struct gpio *irq) +{ + enum gpio_id id = dal_gpio_get_id(irq); + + switch (id) { + case GPIO_ID_HPD: + return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX + + dal_gpio_get_enum(irq)); + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +enum gpio_result dal_irq_setup_hpd_filter( + struct gpio *irq, + struct gpio_hpd_config *config) +{ + struct gpio_config_data config_data; + + if (!config) + return GPIO_RESULT_INVALID_DATA; + + config_data.type = GPIO_CONFIG_TYPE_HPD; + config_data.config.hpd = *config; + + return dal_gpio_set_config(irq, &config_data); +} + +/* + * @brief + * Creation and destruction + */ + +struct gpio *dal_gpio_create_irq( + struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + struct gpio *irq; + + switch (id) { + case GPIO_ID_HPD: + case GPIO_ID_GPIO_PAD: + break; + default: + ASSERT_CRITICAL(false); + return NULL; + } + + irq = dal_gpio_create( + service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); + + if (irq) + return irq; + + ASSERT_CRITICAL(false); + return NULL; +} + +void dal_gpio_destroy_irq( + struct gpio **irq) +{ + if (!irq || !*irq) { + ASSERT_CRITICAL(false); + return; + } + + dal_gpio_close(*irq); + dal_gpio_destroy(irq); + dm_free(*irq); + + *irq = NULL; +} + +struct ddc *dal_gpio_create_ddc( + struct gpio_service *service, + uint32_t offset, + uint32_t mask, + struct gpio_ddc_hw_info *info) +{ + enum gpio_id id; + uint32_t en; + struct ddc *ddc; + + if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) + return NULL; + + ddc = dm_alloc(sizeof(struct ddc)); + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + ddc->pin_data = dal_gpio_create( + service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); + + if (!ddc->pin_data) { + BREAK_TO_DEBUGGER(); + goto failure_1; + } + + ddc->pin_clock = dal_gpio_create( + service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); + + if (!ddc->pin_clock) { + BREAK_TO_DEBUGGER(); + goto failure_2; + } + + ddc->hw_info = *info; + + ddc->ctx = service->ctx; + + return ddc; + +failure_2: + dal_gpio_destroy(&ddc->pin_data); + +failure_1: + dm_free(ddc); + + return NULL; +} + +void dal_gpio_destroy_ddc( + struct ddc **ddc) +{ + if (!ddc || !*ddc) { + BREAK_TO_DEBUGGER(); + return; + } + + dal_ddc_close(*ddc); + dal_gpio_destroy(&(*ddc)->pin_data); + dal_gpio_destroy(&(*ddc)->pin_clock); + dm_free(*ddc); + + *ddc = NULL; +} + +enum gpio_result dal_ddc_open( + struct ddc *ddc, + enum gpio_mode mode, + enum gpio_ddc_config_type config_type) +{ + enum gpio_result result; + + struct gpio_config_data config_data; + struct hw_gpio *hw_data; + struct hw_gpio *hw_clock; + + result = dal_gpio_open_ex(ddc->pin_data, mode); + + if (result != GPIO_RESULT_OK) { + BREAK_TO_DEBUGGER(); + return result; + } + + result = dal_gpio_open_ex(ddc->pin_clock, mode); + + if (result != GPIO_RESULT_OK) { + BREAK_TO_DEBUGGER(); + goto failure; + } + + /* DDC clock and data pins should belong + * to the same DDC block id, + * we use the data pin to set the pad mode. */ + + if (mode == GPIO_MODE_INPUT) + /* this is from detect_sink_type, + * we need extra delay there */ + config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE; + else + config_data.type = GPIO_CONFIG_TYPE_DDC; + + config_data.config.ddc.type = config_type; + + hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin); + hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin); + + config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0; + config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0; + + result = dal_gpio_set_config(ddc->pin_data, &config_data); + + if (result == GPIO_RESULT_OK) + return result; + + BREAK_TO_DEBUGGER(); + + dal_gpio_close(ddc->pin_clock); + +failure: + dal_gpio_close(ddc->pin_data); + + return result; +} + +enum gpio_result dal_ddc_change_mode( + struct ddc *ddc, + enum gpio_mode mode) +{ + enum gpio_result result; + + enum gpio_mode original_mode = + dal_gpio_get_mode(ddc->pin_data); + + result = dal_gpio_change_mode(ddc->pin_data, mode); + + /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR + * in case of failures; + * set_mode() is so that, in case of failure, + * we must explicitly set original mode */ + + if (result != GPIO_RESULT_OK) + goto failure; + + result = dal_gpio_change_mode(ddc->pin_clock, mode); + + if (result == GPIO_RESULT_OK) + return result; + + dal_gpio_change_mode(ddc->pin_clock, original_mode); + +failure: + dal_gpio_change_mode(ddc->pin_data, original_mode); + + return result; +} + +enum gpio_ddc_line dal_ddc_get_line( + const struct ddc *ddc) +{ + return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data); +} + +enum gpio_result dal_ddc_set_config( + struct ddc *ddc, + enum gpio_ddc_config_type config_type) +{ + struct gpio_config_data config_data; + + config_data.type = GPIO_CONFIG_TYPE_DDC; + + config_data.config.ddc.type = config_type; + config_data.config.ddc.data_en_bit_present = false; + config_data.config.ddc.clock_en_bit_present = false; + + return dal_gpio_set_config(ddc->pin_data, &config_data); +} + +void dal_ddc_close( + struct ddc *ddc) +{ + dal_gpio_close(ddc->pin_clock); + dal_gpio_close(ddc->pin_data); +} + diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h new file mode 100644 index 000000000000..c7f3081f59cc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h @@ -0,0 +1,56 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_SERVICE_H__ +#define __DAL_GPIO_SERVICE_H__ + +struct hw_translate; +struct hw_factory; + +struct gpio_service { + struct dc_context *ctx; + struct hw_translate translate; + struct hw_factory factory; + /* + * @brief + * Business storage. + * For each member of 'enum gpio_id', + * store array of bits (packed into uint32_t slots), + * index individual bit by 'en' value */ + uint32_t *busyness[GPIO_ID_COUNT]; +}; + +enum gpio_result dal_gpio_service_open( + struct gpio_service *service, + enum gpio_id id, + uint32_t en, + enum gpio_mode mode, + struct hw_gpio_pin **ptr); + +void dal_gpio_service_close( + struct gpio_service *service, + struct hw_gpio_pin **ptr); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h new file mode 100644 index 000000000000..dcfdd71b2304 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hpd_regs.h @@ -0,0 +1,79 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_ + +#include "gpio_regs.h" + +#define ONE_MORE_0 1 +#define ONE_MORE_1 2 +#define ONE_MORE_2 3 +#define ONE_MORE_3 4 +#define ONE_MORE_4 5 +#define ONE_MORE_5 6 + + +#define HPD_GPIO_REG_LIST_ENTRY(type,cd,id) \ + .type ## _reg = REG(DC_GPIO_HPD_## type),\ + .type ## _mask = DC_GPIO_HPD_ ## type ## __DC_GPIO_HPD ## id ## _ ## type ## _MASK,\ + .type ## _shift = DC_GPIO_HPD_ ## type ## __DC_GPIO_HPD ## id ## _ ## type ## __SHIFT + +#define HPD_GPIO_REG_LIST(id) \ + {\ + HPD_GPIO_REG_LIST_ENTRY(MASK,cd,id),\ + HPD_GPIO_REG_LIST_ENTRY(A,cd,id),\ + HPD_GPIO_REG_LIST_ENTRY(EN,cd,id),\ + HPD_GPIO_REG_LIST_ENTRY(Y,cd,id)\ + } + +#define HPD_REG_LIST(id) \ + HPD_GPIO_REG_LIST(ONE_MORE_ ## id), \ + .int_status = REGI(DC_HPD_INT_STATUS, HPD, id),\ + .toggle_filt_cntl = REGI(DC_HPD_TOGGLE_FILT_CNTL, HPD, id) + + #define HPD_MASK_SH_LIST(mask_sh) \ + SF_HPD(DC_HPD_INT_STATUS, DC_HPD_SENSE_DELAYED, mask_sh),\ + SF_HPD(DC_HPD_INT_STATUS, DC_HPD_SENSE, mask_sh),\ + SF_HPD(DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, mask_sh),\ + SF_HPD(DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, mask_sh) + +struct hpd_registers { + struct gpio_registers gpio; + uint32_t int_status; + uint32_t toggle_filt_cntl; +}; + +struct hpd_sh_mask { + /* int_status */ + uint32_t DC_HPD_SENSE_DELAYED; + uint32_t DC_HPD_SENSE; + /* toggle_filt_cntl */ + uint32_t DC_HPD_CONNECT_INT_DELAY; + uint32_t DC_HPD_DISCONNECT_INT_DELAY; +}; + + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_GPIO_HPD_REGS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c new file mode 100644 index 000000000000..47e0f8f24a86 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -0,0 +1,243 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/gpio_types.h" +#include "hw_gpio.h" +#include "hw_ddc.h" + +#include "reg_helper.h" +#include "gpio_regs.h" + + +#undef FN +#define FN(reg_name, field_name) \ + ddc->shifts->field_name, ddc->masks->field_name + +#define CTX \ + ddc->base.base.ctx +#define REG(reg)\ + (ddc->regs->reg) + +static void destruct( + struct hw_ddc *pin) +{ + dal_hw_gpio_destruct(&pin->base); +} + +static void destroy( + struct hw_gpio_pin **ptr) +{ + struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr); + + destruct(pin); + + dm_free(pin); + + *ptr = NULL; +} + +static enum gpio_result set_config( + struct hw_gpio_pin *ptr, + const struct gpio_config_data *config_data) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr); + struct hw_gpio *hw_gpio = NULL; + uint32_t regval; + uint32_t ddc_data_pd_en = 0; + uint32_t ddc_clk_pd_en = 0; + uint32_t aux_pad_mode = 0; + + hw_gpio = &ddc->base; + + if (hw_gpio == NULL) { + ASSERT_CRITICAL(false); + return GPIO_RESULT_NULL_HANDLE; + } + + regval = REG_GET_3(gpio.MASK_reg, + DC_GPIO_DDC1DATA_PD_EN, &ddc_data_pd_en, + DC_GPIO_DDC1CLK_PD_EN, &ddc_clk_pd_en, + AUX_PAD1_MODE, &aux_pad_mode); + + switch (config_data->config.ddc.type) { + case GPIO_DDC_CONFIG_TYPE_MODE_I2C: + /* On plug-in, there is a transient level on the pad + * which must be discharged through the internal pull-down. + * Enable internal pull-down, 2.5msec discharge time + * is required for detection of AUX mode */ + if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) { + if (!ddc_data_pd_en || !ddc_clk_pd_en) { + + REG_SET_2(gpio.MASK_reg, regval, + DC_GPIO_DDC1DATA_PD_EN, 1, + DC_GPIO_DDC1CLK_PD_EN, 1); + + if (config_data->type == + GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) + msleep(3); + } + } else { + uint32_t reg2; + uint32_t sda_pd_dis = 0; + uint32_t scl_pd_dis = 0; + + reg2 = REG_GET_2(gpio.MASK_reg, + DC_GPIO_SDA_PD_DIS, &sda_pd_dis, + DC_GPIO_SCL_PD_DIS, &scl_pd_dis); + + if (sda_pd_dis) { + REG_SET(gpio.MASK_reg, regval, + DC_GPIO_SDA_PD_DIS, 0); + + if (config_data->type == + GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) + msleep(3); + } + + if (!scl_pd_dis) { + REG_SET(gpio.MASK_reg, regval, + DC_GPIO_SCL_PD_DIS, 1); + + if (config_data->type == + GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE) + msleep(3); + } + } + + if (aux_pad_mode) { + /* let pins to get de-asserted + * before setting pad to I2C mode */ + if (config_data->config.ddc.data_en_bit_present || + config_data->config.ddc.clock_en_bit_present) + /* [anaumov] in DAL2, there was + * dc_service_delay_in_microseconds(2000); */ + msleep(2); + + /* set the I2C pad mode */ + /* read the register again, + * some bits may have been changed */ + REG_UPDATE(gpio.MASK_reg, + AUX_PAD1_MODE, 0); + } + + return GPIO_RESULT_OK; + case GPIO_DDC_CONFIG_TYPE_MODE_AUX: + /* set the AUX pad mode */ + if (!aux_pad_mode) { + REG_SET(gpio.MASK_reg, regval, + AUX_PAD1_MODE, 1); + } + + return GPIO_RESULT_OK; + case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT: + if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && + (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { + REG_UPDATE_3(ddc_setup, + DC_I2C_DDC1_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_MODE, 0); + return GPIO_RESULT_OK; + } + break; + case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT: + if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && + (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { + REG_UPDATE_3(ddc_setup, + DC_I2C_DDC1_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 1, + DC_I2C_DDC1_EDID_DETECT_MODE, 1); + return GPIO_RESULT_OK; + } + break; + case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING: + if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) && + (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) { + REG_UPDATE_2(ddc_setup, + DC_I2C_DDC1_ENABLE, 0, + DC_I2C_DDC1_EDID_DETECT_ENABLE, 0); + return GPIO_RESULT_OK; + } + break; + } + + BREAK_TO_DEBUGGER(); + + return GPIO_RESULT_NON_SPECIFIC_ERROR; +} + +static const struct hw_gpio_pin_funcs funcs = { + .destroy = destroy, + .open = dal_hw_gpio_open, + .get_value = dal_hw_gpio_get_value, + .set_value = dal_hw_gpio_set_value, + .set_config = set_config, + .change_mode = dal_hw_gpio_change_mode, + .close = dal_hw_gpio_close, +}; + +static bool construct( + struct hw_ddc *ddc, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) { + ASSERT_CRITICAL(false); + return false; + } + + if (!dal_hw_gpio_construct(&ddc->base, id, en, ctx)) { + ASSERT_CRITICAL(false); + return false; + } + + ddc->base.base.funcs = &funcs; + + return true; +} + +struct hw_gpio_pin *dal_hw_ddc_create( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en) +{ + struct hw_ddc *pin = dm_alloc(sizeof(struct hw_ddc)); + + if (!pin) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(pin, id, en, ctx)) + return &pin->base.base; + + ASSERT_CRITICAL(false); + + dm_free(pin); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h new file mode 100644 index 000000000000..9690e2a885d7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h @@ -0,0 +1,46 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_DDC_H__ +#define __DAL_HW_DDC_H__ + +#include "ddc_regs.h" + +struct hw_ddc { + struct hw_gpio base; + const struct ddc_registers *regs; + const struct ddc_sh_mask *shifts; + const struct ddc_sh_mask *masks; +}; + +#define HW_DDC_FROM_BASE(hw_gpio) \ + container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_ddc, base) + +struct hw_gpio_pin *dal_hw_ddc_create( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c new file mode 100644 index 000000000000..f1a6fa7391c6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -0,0 +1,93 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/gpio_types.h" + +/* + * Header of this unit + */ + +#include "hw_factory.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "dce80/hw_factory_dce80.h" + +#include "dce110/hw_factory_dce110.h" + +#include "diagnostics/hw_factory_diag.h" + +/* + * This unit + */ + +bool dal_hw_factory_init( + struct hw_factory *factory, + enum dce_version dce_version, + enum dce_environment dce_environment) +{ + if (IS_FPGA_MAXIMUS_DC(dce_environment)) { + dal_hw_factory_diag_fpga_init(factory); + return true; + } + + switch (dce_version) { + case DCE_VERSION_8_0: + dal_hw_factory_dce80_init(factory); + return true; + + case DCE_VERSION_10_0: + dal_hw_factory_dce110_init(factory); + return true; + case DCE_VERSION_11_0: + case DCE_VERSION_11_2: + dal_hw_factory_dce110_init(factory); + return true; + default: + ASSERT_CRITICAL(false); + return false; + } +} + +void dal_hw_factory_destroy( + struct dc_context *ctx, + struct hw_factory **factory) +{ + if (!factory || !*factory) { + BREAK_TO_DEBUGGER(); + return; + } + + dm_free(*factory); + + *factory = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h new file mode 100644 index 000000000000..6e4dd3521935 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.h @@ -0,0 +1,74 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_H__ +#define __DAL_HW_FACTORY_H__ + +struct hw_gpio_pin; +struct hw_hpd; + +struct hw_factory { + uint32_t number_of_pins[GPIO_ID_COUNT]; + + const struct hw_factory_funcs { + struct hw_gpio_pin *(*create_ddc_data)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_ddc_clock)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_generic)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_hpd)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_sync)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_gsl)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + void (*define_hpd_registers)( + struct hw_gpio_pin *pin, + uint32_t en); + void (*define_ddc_registers)( + struct hw_gpio_pin *pin, + uint32_t en); + } *funcs; +}; + +bool dal_hw_factory_init( + struct hw_factory *factory, + enum dce_version dce_version, + enum dce_environment dce_environment); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c new file mode 100644 index 000000000000..4cdcdfb73e5c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c @@ -0,0 +1,205 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "hw_gpio.h" + +#include "reg_helper.h" +#include "gpio_regs.h" + +#undef FN +#define FN(reg_name, field_name) \ + gpio->regs->field_name ## _shift, gpio->regs->field_name ## _mask + +#define CTX \ + gpio->base.ctx +#define REG(reg)\ + (gpio->regs->reg) + +static void store_registers( + struct hw_gpio *gpio) +{ + REG_GET(MASK_reg, MASK, &gpio->store.mask); + REG_GET(A_reg, A, &gpio->store.a); + REG_GET(EN_reg, EN, &gpio->store.en); + /* TODO store GPIO_MUX_CONTROL if we ever use it */ +} + +static void restore_registers( + struct hw_gpio *gpio) +{ + REG_UPDATE(MASK_reg, MASK, gpio->store.mask); + REG_UPDATE(A_reg, A, gpio->store.a); + REG_UPDATE(EN_reg, EN, gpio->store.en); + /* TODO restore GPIO_MUX_CONTROL if we ever use it */ +} + +bool dal_hw_gpio_open( + struct hw_gpio_pin *ptr, + enum gpio_mode mode) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + store_registers(pin); + + ptr->opened = (dal_hw_gpio_config_mode(pin, mode) == GPIO_RESULT_OK); + + return ptr->opened; +} + +enum gpio_result dal_hw_gpio_get_value( + const struct hw_gpio_pin *ptr, + uint32_t *value) +{ + const struct hw_gpio *gpio = FROM_HW_GPIO_PIN(ptr); + + enum gpio_result result = GPIO_RESULT_OK; + + switch (ptr->mode) { + case GPIO_MODE_INPUT: + case GPIO_MODE_OUTPUT: + case GPIO_MODE_HARDWARE: + case GPIO_MODE_FAST_OUTPUT: + REG_GET(Y_reg, Y, value); + break; + default: + result = GPIO_RESULT_NON_SPECIFIC_ERROR; + } + + return result; +} + +enum gpio_result dal_hw_gpio_set_value( + const struct hw_gpio_pin *ptr, + uint32_t value) +{ + struct hw_gpio *gpio = FROM_HW_GPIO_PIN(ptr); + + /* This is the public interface + * where the input comes from client, not shifted yet + * (because client does not know the shifts). */ + + switch (ptr->mode) { + case GPIO_MODE_OUTPUT: + REG_UPDATE(A_reg, A, value); + return GPIO_RESULT_OK; + case GPIO_MODE_FAST_OUTPUT: + /* We use (EN) to faster switch (used in DDC GPIO). + * So (A) is grounded, output is driven by (EN = 0) + * to pull the line down (output == 0) and (EN=1) + * then output is tri-state */ + REG_UPDATE(EN_reg, EN, ~value); + return GPIO_RESULT_OK; + default: + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } +} + +enum gpio_result dal_hw_gpio_change_mode( + struct hw_gpio_pin *ptr, + enum gpio_mode mode) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + return dal_hw_gpio_config_mode(pin, mode); +} + +void dal_hw_gpio_close( + struct hw_gpio_pin *ptr) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + restore_registers(pin); + + ptr->mode = GPIO_MODE_UNKNOWN; + ptr->opened = false; +} + +enum gpio_result dal_hw_gpio_config_mode( + struct hw_gpio *gpio, + enum gpio_mode mode) +{ + gpio->base.mode = mode; + + switch (mode) { + case GPIO_MODE_INPUT: + /* turn off output enable, act as input pin; + * program the pin as GPIO, mask out signal driven by HW */ + REG_UPDATE(EN_reg, EN, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_OUTPUT: + /* turn on output enable, act as output pin; + * program the pin as GPIO, mask out signal driven by HW */ + REG_UPDATE(A_reg, A, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_FAST_OUTPUT: + /* grounding the A register then use the EN register bit + * will have faster effect on the rise time */ + REG_UPDATE(A_reg, A, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_HARDWARE: + /* program the pin as tri-state, pin is driven by HW */ + REG_UPDATE(MASK_reg, MASK, 0); + return GPIO_RESULT_OK; + case GPIO_MODE_INTERRUPT: + /* Interrupt mode supported only by HPD (IrqGpio) pins. */ + REG_UPDATE(MASK_reg, MASK, 0); + return GPIO_RESULT_OK; + default: + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } +} + +bool dal_hw_gpio_construct( + struct hw_gpio *pin, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + pin->base.ctx = ctx; + pin->base.id = id; + pin->base.en = en; + pin->base.mode = GPIO_MODE_UNKNOWN; + pin->base.opened = false; + + pin->store.mask = 0; + pin->store.a = 0; + pin->store.en = 0; + pin->store.mux = 0; + + pin->mux_supported = false; + + return true; +} + +void dal_hw_gpio_destruct( + struct hw_gpio *pin) +{ + ASSERT(!pin->base.opened); +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h new file mode 100644 index 000000000000..fb41ee2be958 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h @@ -0,0 +1,144 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_GPIO_H__ +#define __DAL_HW_GPIO_H__ + +#include "gpio_regs.h" + +#define FROM_HW_GPIO_PIN(ptr) \ + container_of((ptr), struct hw_gpio, base) + +struct addr_mask { + uint32_t addr; + uint32_t mask; +}; + +struct hw_gpio_pin { + const struct hw_gpio_pin_funcs *funcs; + enum gpio_id id; + uint32_t en; + enum gpio_mode mode; + bool opened; + struct dc_context *ctx; +}; + +struct hw_gpio_pin_funcs { + void (*destroy)( + struct hw_gpio_pin **ptr); + bool (*open)( + struct hw_gpio_pin *pin, + enum gpio_mode mode); + enum gpio_result (*get_value)( + const struct hw_gpio_pin *pin, + uint32_t *value); + enum gpio_result (*set_value)( + const struct hw_gpio_pin *pin, + uint32_t value); + enum gpio_result (*set_config)( + struct hw_gpio_pin *pin, + const struct gpio_config_data *config_data); + enum gpio_result (*change_mode)( + struct hw_gpio_pin *pin, + enum gpio_mode mode); + void (*close)( + struct hw_gpio_pin *pin); +}; + + +struct hw_gpio; + +/* Register indices are represented by member variables + * and are to be filled in by constructors of derived classes. + * These members permit the use of common code + * for programming registers, where the sequence is the same + * but register sets are different. + * Some GPIOs have HW mux which allows to choose + * what is the source of the signal in HW mode */ + +struct hw_gpio_pin_reg { + struct addr_mask DC_GPIO_DATA_MASK; + struct addr_mask DC_GPIO_DATA_A; + struct addr_mask DC_GPIO_DATA_EN; + struct addr_mask DC_GPIO_DATA_Y; +}; + +struct hw_gpio_mux_reg { + struct addr_mask GPIO_MUX_CONTROL; + struct addr_mask GPIO_MUX_STEREO_SEL; +}; + +struct hw_gpio { + struct hw_gpio_pin base; + + /* variables to save register value */ + struct { + uint32_t mask; + uint32_t a; + uint32_t en; + uint32_t mux; + } store; + + /* GPIO MUX support */ + bool mux_supported; + const struct gpio_registers *regs; +}; + +#define HW_GPIO_FROM_BASE(hw_gpio_pin) \ + container_of((hw_gpio_pin), struct hw_gpio, base) + +bool dal_hw_gpio_construct( + struct hw_gpio *pin, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx); + +bool dal_hw_gpio_open( + struct hw_gpio_pin *pin, + enum gpio_mode mode); + +enum gpio_result dal_hw_gpio_get_value( + const struct hw_gpio_pin *pin, + uint32_t *value); + +enum gpio_result dal_hw_gpio_config_mode( + struct hw_gpio *pin, + enum gpio_mode mode); + +void dal_hw_gpio_destruct( + struct hw_gpio *pin); + +enum gpio_result dal_hw_gpio_set_value( + const struct hw_gpio_pin *ptr, + uint32_t value); + +enum gpio_result dal_hw_gpio_change_mode( + struct hw_gpio_pin *ptr, + enum gpio_mode mode); + +void dal_hw_gpio_close( + struct hw_gpio_pin *ptr); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c new file mode 100644 index 000000000000..9634e8841d90 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c @@ -0,0 +1,175 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/gpio_types.h" +#include "hw_gpio.h" +#include "hw_hpd.h" + +#include "reg_helper.h" +#include "hpd_regs.h" + +#undef FN +#define FN(reg_name, field_name) \ + hpd->shifts->field_name, hpd->masks->field_name + +#define CTX \ + hpd->base.base.ctx +#define REG(reg)\ + (hpd->regs->reg) + +static bool dal_hw_hpd_construct( + struct hw_hpd *pin, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + if (!dal_hw_gpio_construct(&pin->base, id, en, ctx)) + return false; + return true; +} + +static void dal_hw_hpd_destruct( + struct hw_hpd *pin) +{ + dal_hw_gpio_destruct(&pin->base); +} + + +static void destruct( + struct hw_hpd *hpd) +{ + dal_hw_hpd_destruct(hpd); +} + +static void destroy( + struct hw_gpio_pin **ptr) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(*ptr); + + destruct(hpd); + + dm_free(hpd); + + *ptr = NULL; +} + +static enum gpio_result get_value( + const struct hw_gpio_pin *ptr, + uint32_t *value) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(ptr); + uint32_t hpd_delayed = 0; + + /* in Interrupt mode we ask for SENSE bit */ + + if (ptr->mode == GPIO_MODE_INTERRUPT) { + + REG_GET(int_status, + DC_HPD_SENSE_DELAYED, &hpd_delayed); + + *value = hpd_delayed; + return GPIO_RESULT_OK; + } + + /* in any other modes, operate as normal GPIO */ + + return dal_hw_gpio_get_value(ptr, value); +} + +static enum gpio_result set_config( + struct hw_gpio_pin *ptr, + const struct gpio_config_data *config_data) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(ptr); + + if (!config_data) + return GPIO_RESULT_INVALID_DATA; + + REG_UPDATE_2(toggle_filt_cntl, + DC_HPD_CONNECT_INT_DELAY, config_data->config.hpd.delay_on_connect / 10, + DC_HPD_DISCONNECT_INT_DELAY, config_data->config.hpd.delay_on_disconnect / 10); + + return GPIO_RESULT_OK; +} + +static const struct hw_gpio_pin_funcs funcs = { + .destroy = destroy, + .open = dal_hw_gpio_open, + .get_value = get_value, + .set_value = dal_hw_gpio_set_value, + .set_config = set_config, + .change_mode = dal_hw_gpio_change_mode, + .close = dal_hw_gpio_close, +}; + +static bool construct( + struct hw_hpd *hpd, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + if (id != GPIO_ID_HPD) { + ASSERT_CRITICAL(false); + return false; + } + + if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) { + ASSERT_CRITICAL(false); + return false; + } + + if (!dal_hw_hpd_construct(hpd, id, en, ctx)) { + ASSERT_CRITICAL(false); + return false; + } + + hpd->base.base.funcs = &funcs; + + return true; +} + +struct hw_gpio_pin *dal_hw_hpd_create( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en) +{ + struct hw_hpd *hpd = dm_alloc(sizeof(struct hw_hpd)); + + if (!hpd) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(hpd, id, en, ctx)) + return &hpd->base.base; + + ASSERT_CRITICAL(false); + + dm_free(hpd); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h new file mode 100644 index 000000000000..4ab7a208f781 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.h @@ -0,0 +1,46 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_HPD_H__ +#define __DAL_HW_HPD_H__ + +#include "hpd_regs.h" + +struct hw_hpd { + struct hw_gpio base; + const struct hpd_registers *regs; + const struct hpd_sh_mask *shifts; + const struct hpd_sh_mask *masks; +}; + +#define HW_HPD_FROM_BASE(hw_gpio) \ + container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_hpd, base) + +struct hw_gpio_pin *dal_hw_hpd_create( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c new file mode 100644 index 000000000000..23e097fa5ace --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -0,0 +1,75 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/gpio_types.h" + +/* + * Header of this unit + */ + +#include "hw_translate.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "dce80/hw_translate_dce80.h" +#include "dce110/hw_translate_dce110.h" + +#include "diagnostics/hw_translate_diag.h" + +/* + * This unit + */ + +bool dal_hw_translate_init( + struct hw_translate *translate, + enum dce_version dce_version, + enum dce_environment dce_environment) +{ + if (IS_FPGA_MAXIMUS_DC(dce_environment)) { + dal_hw_translate_diag_fpga_init(translate); + return true; + } + + switch (dce_version) { + case DCE_VERSION_8_0: + dal_hw_translate_dce80_init(translate); + return true; + case DCE_VERSION_10_0: + case DCE_VERSION_11_0: + case DCE_VERSION_11_2: + dal_hw_translate_dce110_init(translate); + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h new file mode 100644 index 000000000000..3a7d89ca1605 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.h @@ -0,0 +1,50 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_H__ +#define __DAL_HW_TRANSLATE_H__ + +struct hw_translate_funcs { + bool (*offset_to_id)( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en); + bool (*id_to_offset)( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info); +}; + +struct hw_translate { + const struct hw_translate_funcs *funcs; +}; + +bool dal_hw_translate_init( + struct hw_translate *translate, + enum dce_version dce_version, + enum dce_environment dce_environment); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile new file mode 100644 index 000000000000..fd17af1ce88e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/Makefile @@ -0,0 +1,36 @@ +# +# Makefile for the 'gpu' sub-component of DAL. +# It provides the control and status of HW adapter resources, +# that are global for the ASIC and sharable between pipes. + +GPU = display_clock.o divider_range.o + +AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPU) + +############################################################################### +# DCE 80 family +############################################################################### +GPU_DCE80 = display_clock_dce80.o + +AMD_DAL_GPU_DCE80 = $(addprefix $(AMDDALPATH)/dc/gpu/dce80/,$(GPU_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE80) + + +############################################################################### +# DCE 110 family +############################################################################### +GPU_DCE110 = display_clock_dce110.o + +AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) + +GPU_DCE112 = display_clock_dce112.o + +AMD_DAL_GPU_DCE112 = $(addprefix $(AMDDALPATH)/dc/gpu/dce112/,$(GPU_DCE112)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) $(AMD_DAL_GPU_DCE112) + diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c new file mode 100644 index 000000000000..1bc39f12b6a1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -0,0 +1,1035 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "include/bios_parser_interface.h" +#include "include/fixed32_32.h" +#include "include/logger_interface.h" + +#include "../divider_range.h" + +#include "display_clock_dce110.h" +#include "dc.h" + +#define FROM_DISPLAY_CLOCK(base) \ + container_of(base, struct display_clock_dce110, disp_clk_base) + +#define PSR_SET_WAITLOOP 0x31 + +static struct state_dependent_clocks max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; + +/* Starting point for each divider range.*/ +enum divider_range_start { + DIVIDER_RANGE_01_START = 200, /* 2.00*/ + DIVIDER_RANGE_02_START = 1600, /* 16.00*/ + DIVIDER_RANGE_03_START = 3200, /* 32.00*/ + DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ +}; + +/* Array identifiers and count for the divider ranges.*/ +enum divider_range_count { + DIVIDER_RANGE_01 = 0, + DIVIDER_RANGE_02, + DIVIDER_RANGE_03, + DIVIDER_RANGE_MAX /* == 3*/ +}; + +/* Ranges for divider identifiers (Divider ID or DID) + mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +enum divider_id_register_setting { + DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, + DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, + DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, + DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 +}; + +/* Step size between each divider within a range. + Incrementing the DENTIST_DISPCLK_WDIVIDER by one + will increment the divider by this much.*/ +enum divider_range_step_size { + DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ + DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ + DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +}; + +union dce110_dmcu_psr_config_data_wait_loop_reg1 { + struct { + unsigned int waitLoop:16; /* [15:0] */ + unsigned int reserved:16; /* [31:16] */ + } bits; + unsigned int u32All; +}; + +static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + +#define DCE110_DFS_BYPASS_THRESHOLD_KHZ 400000 +/***************************************************************************** + * static functions + *****************************************************************************/ + +/* + * store_max_clocks_state + * + * @brief + * Cache the clock state + * + * @param + * struct display_clock *base - [out] cach the state in this structure + * enum clocks_state max_clocks_state - [in] state to be stored + */ +static void store_max_clocks_state( + struct display_clock *base, + enum clocks_state max_clocks_state) +{ + struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); + + switch (max_clocks_state) { + case CLOCKS_STATE_LOW: + case CLOCKS_STATE_NOMINAL: + case CLOCKS_STATE_PERFORMANCE: + case CLOCKS_STATE_ULTRA_LOW: + dc->max_clks_state = max_clocks_state; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State!*/ + ASSERT_CRITICAL(false); + break; + } +} + +static enum clocks_state get_min_clocks_state(struct display_clock *base) +{ + return base->cur_min_clks_state; +} + +static bool set_min_clocks_state( + struct display_clock *base, + enum clocks_state clocks_state) +{ + struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); + struct dm_pp_power_level_change_request level_change_req = { + DM_PP_POWER_LEVEL_INVALID}; + + if (clocks_state > dc->max_clks_state) { + /*Requested state exceeds max supported state.*/ + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Requested state exceeds max supported state"); + return false; + } else if (clocks_state == base->cur_min_clks_state) { + /*if we're trying to set the same state, we can just return + * since nothing needs to be done*/ + return true; + } + + switch (clocks_state) { + case CLOCKS_STATE_ULTRA_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; + break; + case CLOCKS_STATE_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; + break; + case CLOCKS_STATE_NOMINAL: + level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; + break; + case CLOCKS_STATE_PERFORMANCE: + level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; + break; + case CLOCKS_STATE_INVALID: + default: + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Requested state invalid state"); + return false; + } + + /* get max clock state from PPLIB */ + if (dm_pp_apply_power_level_change_request( + base->ctx, &level_change_req)) + base->cur_min_clks_state = clocks_state; + + return true; +} + +static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) +{ + uint32_t dispclk_cntl_value; + uint32_t dp_ref_clk_cntl_value; + uint32_t dp_ref_clk_cntl_src_sel_value; + uint32_t dp_ref_clk_khz = 600000; + uint32_t target_div = INVALID_DIVIDER; + struct display_clock_dce110 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + /* ASSERT DP Reference Clock source is from DFS*/ + dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, + mmDPREFCLK_CNTL); + + dp_ref_clk_cntl_src_sel_value = + get_reg_field_value( + dp_ref_clk_cntl_value, + DPREFCLK_CNTL, DPREFCLK_SRC_SEL); + + ASSERT(dp_ref_clk_cntl_src_sel_value == 0); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + dispclk_cntl_value = dm_read_reg(dc->ctx, + mmDENTIST_DISPCLK_CNTL); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + get_reg_field_value(dispclk_cntl_value, + DENTIST_DISPCLK_CNTL, + DENTIST_DPREFCLK_WDIVIDER)); + + if (target_div != INVALID_DIVIDER) { + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + } + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) + if clock is spread for all cases: + -if SS enabled on DP Ref clock and HW de-spreading enabled with SW + calculations for DS_INCR/DS_MODULO (this is planned to be default case) + -if SS enabled on DP Ref clock and HW de-spreading enabled with HW + calculations (not planned to be used, but average clock should still + be valid) + -if SS enabled on DP Ref clock and HW de-spreading disabled + (should not be case with CIK) then SW should program all rates + generated according to average value (case as with previous ASICs) + */ + if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk->gpu_pll_ss_percentage, + disp_clk->gpu_pll_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} + +static void destroy(struct display_clock **base) +{ + struct display_clock_dce110 *dc110; + + dc110 = DCLCK110_FROM_BASE(*base); + + dm_free(dc110); + + *base = NULL; +} + +static uint32_t get_validation_clock(struct display_clock *dc) +{ + uint32_t clk = 0; + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + + switch (disp_clk->max_clks_state) { + case CLOCKS_STATE_ULTRA_LOW: + /*Currently not supported, it has 0 in table entry*/ + case CLOCKS_STATE_LOW: + clk = max_clks_by_state[CLOCKS_STATE_LOW]. + display_clk_khz; + break; + + case CLOCKS_STATE_NOMINAL: + clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. + display_clk_khz; + break; + + case CLOCKS_STATE_PERFORMANCE: + clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. + display_clk_khz; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "Invalid clock state"); + /* just return the display engine clock for + * lowest supported state*/ + clk = max_clks_by_state[CLOCKS_STATE_LOW]. + display_clk_khz; + break; + } + return clk; +} + +static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) +{ + /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ + struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); + + if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return deep_color_factor; + + switch (params->deep_color_depth) { + case COLOR_DEPTH_101010: + /*deep color ratio for 30bpp is 30/24 = 1.25*/ + deep_color_factor = dal_fixed32_32_from_fraction(30, 24); + break; + + case COLOR_DEPTH_121212: + /* deep color ratio for 36bpp is 36/24 = 1.5*/ + deep_color_factor = dal_fixed32_32_from_fraction(36, 24); + break; + + case COLOR_DEPTH_161616: + /* deep color ratio for 48bpp is 48/24 = 2.0 */ + deep_color_factor = dal_fixed32_32_from_fraction(48, 24); + break; + default: + break; + } + return deep_color_factor; +} + +static struct fixed32_32 get_scaler_efficiency( + struct dc_context *ctx, + struct min_clock_params *params) +{ + struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); + + if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { + scaler_efficiency = + dal_fixed32_32_add( + dal_fixed32_32_from_fraction(35555, 10000), + dal_fixed32_32_from_fraction( + 55556, + 100000 * 10000)); + } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { + scaler_efficiency = + dal_fixed32_32_add( + dal_fixed32_32_from_fraction(34285, 10000), + dal_fixed32_32_from_fraction( + 71429, + 100000 * 10000)); + } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) + scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); + + return scaler_efficiency; +} + +static struct fixed32_32 get_lb_lines_in_per_line_out( + struct min_clock_params *params, + struct fixed32_32 v_scale_ratio) +{ + struct fixed32_32 two = dal_fixed32_32_from_int(2); + struct fixed32_32 four = dal_fixed32_32_from_int(4); + struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); + struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); + + if (params->line_buffer_prefetch_enabled) + return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); + else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) + return dal_fixed32_32_one; + else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) + return f4_to_3; + else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) + return f6_to_4; + else if (dal_fixed32_32_le(v_scale_ratio, two)) + return two; + else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) + return four; + else + return dal_fixed32_32_zero; +} + +static uint32_t get_actual_required_display_clk( + struct display_clock_dce110 *disp_clk, + uint32_t target_clk_khz) +{ + uint32_t disp_clk_khz = target_clk_khz; + uint32_t div = INVALID_DIVIDER; + uint32_t did = INVALID_DID; + uint32_t scaled_vco = + disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; + + ASSERT_CRITICAL(!!disp_clk_khz); + + if (disp_clk_khz) + div = scaled_vco / disp_clk_khz; + + did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); + + if (did != INVALID_DID) { + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, did); + + if ((div != INVALID_DIVIDER) && + (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) + if (disp_clk_khz > (scaled_vco / div)) + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, + did - 1); + + if (div != INVALID_DIVIDER) + disp_clk_khz = scaled_vco / div; + + } + /* We need to add 10KHz to this value because the accuracy in VBIOS is + in 10KHz units. So we need to always round the last digit up in order + to reach the next div level.*/ + return disp_clk_khz + 10; +} + +static uint32_t calc_single_display_min_clks( + struct display_clock *base, + struct min_clock_params *params, + bool set_clk) +{ + struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; + struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; + uint32_t pix_clk_khz = 0; + uint32_t lb_source_width = 0; + struct fixed32_32 deep_color_factor; + struct fixed32_32 scaler_efficiency; + struct fixed32_32 v_filter_init; + uint32_t v_filter_init_trunc; + uint32_t num_lines_at_frame_start = 3; + struct fixed32_32 v_filter_init_ceil; + struct fixed32_32 lines_per_lines_out_at_frame_start; + struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ + uint32_t src_wdth_rnd_to_chunks; + struct fixed32_32 scaling_coeff; + struct fixed32_32 h_blank_granularity_factor = + dal_fixed32_32_one; + struct fixed32_32 fx_disp_clk_mhz; + struct fixed32_32 line_time; + struct fixed32_32 disp_pipe_pix_throughput; + struct fixed32_32 fx_alt_disp_clk_mhz; + uint32_t disp_clk_khz; + uint32_t alt_disp_clk_khz; + struct display_clock_dce110 *disp_clk_110 = DCLCK110_FROM_BASE(base); + uint32_t max_clk_khz = get_validation_clock(base); + bool panning_allowed = false; /* TODO: receive this value from AS */ + + if (params == NULL) { + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Invalid input parameter in %s", + __func__); + return 0; + } + + deep_color_factor = get_deep_color_factor(params); + scaler_efficiency = get_scaler_efficiency(base->ctx, params); + pix_clk_khz = params->requested_pixel_clock; + lb_source_width = params->source_view.width; + + if (0 != params->dest_view.height && 0 != params->dest_view.width) { + + h_scale_ratio = dal_fixed32_32_from_fraction( + params->source_view.width, + params->dest_view.width); + v_scale_ratio = dal_fixed32_32_from_fraction( + params->source_view.height, + params->dest_view.height); + } else { + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Destination height or width is 0!\n"); + } + + v_filter_init = + dal_fixed32_32_add( + v_scale_ratio, + dal_fixed32_32_add_int( + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int( + v_scale_ratio, + params->timing_info.INTERLACED), + 2), + params->scaling_info.v_taps + 1)); + v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); + + v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); + + v_filter_init_ceil = dal_fixed32_32_from_fraction( + v_filter_init_trunc, 2); + v_filter_init_ceil = dal_fixed32_32_from_int( + dal_fixed32_32_ceil(v_filter_init_ceil)); + v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); + + lines_per_lines_out_at_frame_start = + dal_fixed32_32_div_int(v_filter_init_ceil, + num_lines_at_frame_start); + lb_lines_in_per_line_out = + get_lb_lines_in_per_line_out(params, v_scale_ratio); + + if (panning_allowed) + src_wdth_rnd_to_chunks = + ((lb_source_width - 1) / 128) * 128 + 256; + else + src_wdth_rnd_to_chunks = + ((lb_source_width + 127) / 128) * 128; + + scaling_coeff = + dal_fixed32_32_div( + dal_fixed32_32_from_int(params->scaling_info.v_taps), + scaler_efficiency); + + if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) + scaling_coeff = dal_fixed32_32_max( + dal_fixed32_32_from_int( + dal_fixed32_32_ceil( + dal_fixed32_32_from_fraction( + params->scaling_info.h_taps, + 4))), + dal_fixed32_32_max( + dal_fixed32_32_mul( + scaling_coeff, + h_scale_ratio), + dal_fixed32_32_one)); + + if (!params->line_buffer_prefetch_enabled && + dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && + dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { + uint32_t line_total_pixel = + params->timing_info.h_total + lb_source_width - 256; + h_blank_granularity_factor = dal_fixed32_32_div( + dal_fixed32_32_from_int(params->timing_info.h_total), + dal_fixed32_32_div( + dal_fixed32_32_from_fraction( + line_total_pixel, 2), + h_scale_ratio)); + } + + /* Calculate display clock with ramping. Ramping factor is 1.1*/ + fx_disp_clk_mhz = + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int(scaling_coeff, 11), + 10); + line_time = dal_fixed32_32_from_fraction( + params->timing_info.h_total * 1000, pix_clk_khz); + + disp_pipe_pix_throughput = dal_fixed32_32_mul( + lb_lines_in_per_line_out, h_blank_granularity_factor); + disp_pipe_pix_throughput = dal_fixed32_32_max( + disp_pipe_pix_throughput, + lines_per_lines_out_at_frame_start); + disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( + disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), + line_time); + + if (0 != params->timing_info.h_total) { + fx_disp_clk_mhz = + dal_fixed32_32_max( + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int( + scaling_coeff, pix_clk_khz), + 1000), + disp_pipe_pix_throughput); + fx_disp_clk_mhz = + dal_fixed32_32_mul( + fx_disp_clk_mhz, + dal_fixed32_32_from_fraction(11, 10)); + } + + fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, + dal_fixed32_32_mul(deep_color_factor, + dal_fixed32_32_from_fraction(11, 10))); + + /* Calculate display clock without ramping */ + fx_alt_disp_clk_mhz = scaling_coeff; + + if (0 != params->timing_info.h_total) { + fx_alt_disp_clk_mhz = dal_fixed32_32_max( + dal_fixed32_32_div_int(dal_fixed32_32_mul_int( + scaling_coeff, pix_clk_khz), + 1000), + dal_fixed32_32_div_int(dal_fixed32_32_mul_int( + disp_pipe_pix_throughput, 105), + 100)); + } + + if (set_clk && disp_clk_110->ss_on_gpu_pll && + disp_clk_110->gpu_pll_ss_divider) + fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, + dal_fixed32_32_add_int( + dal_fixed32_32_div_int( + dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk_110->gpu_pll_ss_percentage, + disp_clk_110->gpu_pll_ss_divider), 100), + 2), + 1)); + + /* convert to integer */ + disp_clk_khz = dal_fixed32_32_round( + dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); + alt_disp_clk_khz = dal_fixed32_32_round( + dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); + + if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) + disp_clk_khz = alt_disp_clk_khz; + + if (set_clk) { /* only compensate clock if we are going to set it.*/ + disp_clk_khz = get_actual_required_display_clk( + disp_clk_110, disp_clk_khz); + } + + disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; + + return disp_clk_khz; +} + +static uint32_t calculate_min_clock( + struct display_clock *base, + uint32_t path_num, + struct min_clock_params *params) +{ + uint32_t i; + uint32_t validation_clk_khz = + get_validation_clock(base); + uint32_t min_clk_khz = validation_clk_khz; + uint32_t max_clk_khz = 0; + struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); + + if (dc->use_max_disp_clk) + return min_clk_khz; + + if (params != NULL) { + uint32_t disp_clk_khz = 0; + + for (i = 0; i < path_num; ++i) { + + disp_clk_khz = calc_single_display_min_clks( + base, params, true); + + /* update the max required clock found*/ + if (disp_clk_khz > max_clk_khz) + max_clk_khz = disp_clk_khz; + + params++; + } + } + + min_clk_khz = max_clk_khz; + + if (min_clk_khz > validation_clk_khz) + min_clk_khz = validation_clk_khz; + else if (min_clk_khz < base->min_display_clk_threshold_khz) + min_clk_khz = base->min_display_clk_threshold_khz; + + if (dc->use_max_disp_clk) + min_clk_khz = get_validation_clock(base); + + return min_clk_khz; +} + +static bool display_clock_integrated_info_construct( + struct display_clock_dce110 *disp_clk) +{ + struct dc_debug *debug = &disp_clk->disp_clk_base.ctx->dc->debug; + struct dc_bios *bp = disp_clk->disp_clk_base.ctx->dc_bios; + struct integrated_info info; + struct firmware_info fw_info; + uint32_t i; + struct display_clock *base = &disp_clk->disp_clk_base; + + memset(&info, 0, sizeof(struct integrated_info)); + memset(&fw_info, 0, sizeof(struct firmware_info)); + + if (bp->integrated_info) + info = *bp->integrated_info; + + disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; + if (disp_clk->dentist_vco_freq_khz == 0) { + bp->funcs->get_firmware_info(bp, &fw_info); + disp_clk->dentist_vco_freq_khz = + fw_info.smu_gpu_pll_output_freq; + if (disp_clk->dentist_vco_freq_khz == 0) + disp_clk->dentist_vco_freq_khz = 3600000; + } + + base->min_display_clk_threshold_khz = + disp_clk->dentist_vco_freq_khz / 64; + + if (bp->integrated_info == NULL) + return false; + + /*update the maximum display clock for each power state*/ + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + enum clocks_state clk_state = CLOCKS_STATE_INVALID; + + switch (i) { + case 0: + clk_state = CLOCKS_STATE_ULTRA_LOW; + break; + + case 1: + clk_state = CLOCKS_STATE_LOW; + break; + + case 2: + clk_state = CLOCKS_STATE_NOMINAL; + break; + + case 3: + clk_state = CLOCKS_STATE_PERFORMANCE; + break; + + default: + clk_state = CLOCKS_STATE_INVALID; + break; + } + + /*Do not allow bad VBIOS/SBIOS to override with invalid values, + * check for > 100MHz*/ + if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { + max_clks_by_state[clk_state].display_clk_khz = + info.disp_clk_voltage[i].max_supported_clk; + } + } + + disp_clk->dfs_bypass_enabled = false; + if (!debug->disable_dfs_bypass) + if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) + disp_clk->dfs_bypass_enabled = true; + + disp_clk->use_max_disp_clk = debug->max_disp_clk; + + return true; +} + +static uint32_t get_clock(struct display_clock *dc) +{ + uint32_t disp_clock = get_validation_clock(dc); + uint32_t target_div = INVALID_DIVIDER; + uint32_t addr = mmDENTIST_DISPCLK_CNTL; + uint32_t value = 0; + uint32_t field = 0; + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + + if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) + return disp_clk->dfs_bypass_disp_clk; + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed + DID DENTIST_DISPCLK_WDIVIDER.*/ + value = dm_read_reg(dc->ctx, addr); + field = get_reg_field_value( + value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); + + /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + field); + + if (target_div != INVALID_DIVIDER) + /* Calculate the current DFS clock in KHz. + Should be okay up to 42.9 THz before overflowing.*/ + disp_clock = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + return disp_clock; +} + +static enum clocks_state get_required_clocks_state( + struct display_clock *dc, + struct state_dependent_clocks *req_clocks) +{ + int32_t i; + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + enum clocks_state low_req_clk = disp_clk->max_clks_state; + + if (!req_clocks) { + /* NULL pointer*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "%s: Invalid parameter", + __func__); + return CLOCKS_STATE_INVALID; + } + + /* Iterate from highest supported to lowest valid state, and update + * lowest RequiredState with the lowest state that satisfies + * all required clocks + */ + for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + if ((req_clocks->display_clk_khz <= + max_clks_by_state[i].display_clk_khz) && + (req_clocks->pixel_clk_khz <= + max_clks_by_state[i].pixel_clk_khz)) + low_req_clk = i; + } + return low_req_clk; +} + +static void psr_wait_loop(struct dc_context *ctx, unsigned int display_clk_khz) +{ + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int regValue; + uint32_t masterCmd; + uint32_t masterComCntl; + union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + regValue = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + masterCmdData1.u32All = 0; + masterCmdData1.bits.waitLoop = display_clk_khz / 1000 / 7; + dm_write_reg(ctx, mmMASTER_COMM_DATA_REG1, masterCmdData1.u32All); + + /* setDMCUParam_Cmd */ + masterCmd = dm_read_reg(ctx, mmMASTER_COMM_CMD_REG); + set_reg_field_value( + masterCmd, + PSR_SET_WAITLOOP, + MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0); + + dm_write_reg(ctx, mmMASTER_COMM_CMD_REG, masterCmd); + + /* notifyDMCUMsg */ + masterComCntl = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG); + set_reg_field_value( + masterComCntl, + 1, + MASTER_COMM_CNTL_REG, + MASTER_COMM_INTERRUPT); + dm_write_reg(ctx, mmMASTER_COMM_CNTL_REG, masterComCntl); +} + +static void set_clock( + struct display_clock *base, + uint32_t requested_clk_khz) +{ + struct bp_pixel_clock_parameters pxl_clk_params; + struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); + struct dc_bios *bp = base->ctx->dc_bios; + + /* Prepare to program display clock*/ + memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); + + /* Make sure requested clock isn't lower than minimum threshold*/ + if (requested_clk_khz > 0) + requested_clk_khz = dm_max(requested_clk_khz, + base->min_display_clk_threshold_khz); + + pxl_clk_params.target_pixel_clock = requested_clk_khz; + pxl_clk_params.pll_id = base->id; + + bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); + + if (dc->dfs_bypass_enabled) { + + /* Cache the fixed display clock*/ + dc->dfs_bypass_disp_clk = + pxl_clk_params.dfs_bypass_display_clock; + } + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + + psr_wait_loop(base->ctx, requested_clk_khz); +} + +static void set_clock_state( + struct display_clock *dc, + struct display_clock_state clk_state) +{ + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + + disp_clk->clock_state = clk_state; +} + +static struct display_clock_state get_clock_state( + struct display_clock *dc) +{ + struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); + + return disp_clk->clock_state; +} + +static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) +{ + return DCE110_DFS_BYPASS_THRESHOLD_KHZ; +} + +static const struct display_clock_funcs funcs = { + .destroy = destroy, + .calculate_min_clock = calculate_min_clock, + .get_clock = get_clock, + .get_clock_state = get_clock_state, + .get_dfs_bypass_threshold = get_dfs_bypass_threshold, + .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, + .get_min_clocks_state = get_min_clocks_state, + .get_required_clocks_state = get_required_clocks_state, + .get_validation_clock = get_validation_clock, + .set_clock = set_clock, + .set_clock_state = set_clock_state, + .set_dp_ref_clock_source = NULL, + .set_min_clocks_state = set_min_clocks_state, + .store_max_clocks_state = store_max_clocks_state, + .validate = NULL, +}; + +static bool dal_display_clock_dce110_construct( + struct display_clock_dce110 *dc110, + struct dc_context *ctx) +{ + struct display_clock *dc_base = &dc110->disp_clk_base; + struct dc_bios *bp = ctx->dc_bios; + + if (!dal_display_clock_construct_base(dc_base, ctx)) + return false; + + dc_base->funcs = &funcs; + + dc110->dfs_bypass_disp_clk = 0; + + if (!display_clock_integrated_info_construct(dc110)) + dm_logger_write(dc_base->ctx->logger, LOG_WARNING, + "Cannot obtain VBIOS integrated info\n"); + + dc110->gpu_pll_ss_percentage = 0; + dc110->gpu_pll_ss_divider = 1000; + dc110->ss_on_gpu_pll = false; + + dc_base->id = CLOCK_SOURCE_ID_DFS; +/* Initially set max clocks state to nominal. This should be updated by + * via a pplib call to DAL IRI eventually calling a + * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in + * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ + dc110->max_clks_state = CLOCKS_STATE_NOMINAL; + + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_01], + DIVIDER_RANGE_01_START, + DIVIDER_RANGE_01_STEP_SIZE, + DIVIDER_RANGE_01_BASE_DIVIDER_ID, + DIVIDER_RANGE_02_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_02], + DIVIDER_RANGE_02_START, + DIVIDER_RANGE_02_STEP_SIZE, + DIVIDER_RANGE_02_BASE_DIVIDER_ID, + DIVIDER_RANGE_03_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_03], + DIVIDER_RANGE_03_START, + DIVIDER_RANGE_03_STEP_SIZE, + DIVIDER_RANGE_03_BASE_DIVIDER_ID, + DIVIDER_RANGE_MAX_DIVIDER_ID); + + { + uint32_t ss_info_num = + bp->funcs->get_ss_entry_number(bp, + AS_SIGNAL_TYPE_GPU_PLL); + + if (ss_info_num) { + struct spread_spectrum_info info; + enum bp_result result; + + memset(&info, 0, sizeof(info)); + + result = bp->funcs->get_spread_spectrum_info(bp, + AS_SIGNAL_TYPE_GPU_PLL, + 0, + &info); + + /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS + * even if SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be sign + * that SS is enabled + */ + if (result == BP_RESULT_OK && + info.spread_spectrum_percentage != 0) { + dc110->ss_on_gpu_pll = true; + dc110->gpu_pll_ss_divider = + info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + dc110->gpu_pll_ss_percentage = + info.spread_spectrum_percentage; + } + } + + } + } + + return true; +} + +/***************************************************************************** + * public functions + *****************************************************************************/ + +struct display_clock *dal_display_clock_dce110_create( + struct dc_context *ctx) +{ + struct display_clock_dce110 *dc110; + + dc110 = dm_alloc(sizeof(struct display_clock_dce110)); + + if (dc110 == NULL) + return NULL; + + if (dal_display_clock_dce110_construct(dc110, ctx)) + return &dc110->disp_clk_base; + + dm_free(dc110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h new file mode 100644 index 000000000000..0cdc7b52a09f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_DISPLAY_CLOCK_DCE110_H__ +#define __DAL_DISPLAY_CLOCK_DCE110_H__ + +#include "gpu/display_clock.h" + +struct display_clock_dce110 { + struct display_clock disp_clk_base; + /* Max display block clocks state*/ + enum clocks_state max_clks_state; + bool use_max_disp_clk; + uint32_t dentist_vco_freq_khz; + /* Cache the status of DFS-bypass feature*/ + bool dfs_bypass_enabled; + /* GPU PLL SS percentage (if down-spread enabled) */ + uint32_t gpu_pll_ss_percentage; + /* GPU PLL SS percentage Divider (100 or 1000) */ + uint32_t gpu_pll_ss_divider; + /* Flag for Enabled SS on GPU PLL */ + bool ss_on_gpu_pll; + /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. + * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ + uint32_t dfs_bypass_disp_clk; + struct display_clock_state clock_state; +}; + +#define DCLCK110_FROM_BASE(dc_base) \ + container_of(dc_base, struct display_clock_dce110, disp_clk_base) + +#endif /* __DAL_DISPLAY_CLOCK_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c new file mode 100644 index 000000000000..9b7c9755e316 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -0,0 +1,964 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#include "include/bios_parser_interface.h" +#include "include/fixed32_32.h" +#include "include/logger_interface.h" + +#include "../divider_range.h" + +#include "display_clock_dce112.h" + +#define FROM_DISPLAY_CLOCK(base) \ + container_of(base, struct display_clock_dce112, disp_clk_base) + +static struct state_dependent_clocks max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; + +/* Ranges for divider identifiers (Divider ID or DID) + mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +enum divider_id_register_setting { + DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, + DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, + DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, + DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 +}; + +/* Step size between each divider within a range. + Incrementing the DENTIST_DISPCLK_WDIVIDER by one + will increment the divider by this much.*/ +enum divider_range_step_size { + DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ + DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ + DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +}; + +static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + +#define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 +/***************************************************************************** + * static functions + *****************************************************************************/ + +/* + * store_max_clocks_state + * + * @brief + * Cache the clock state + * + * @param + * struct display_clock *base - [out] cach the state in this structure + * enum clocks_state max_clocks_state - [in] state to be stored + */ +void dispclk_dce112_store_max_clocks_state( + struct display_clock *base, + enum clocks_state max_clocks_state) +{ + struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); + + switch (max_clocks_state) { + case CLOCKS_STATE_LOW: + case CLOCKS_STATE_NOMINAL: + case CLOCKS_STATE_PERFORMANCE: + case CLOCKS_STATE_ULTRA_LOW: + dc->max_clks_state = max_clocks_state; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State!*/ + ASSERT_CRITICAL(false); + break; + } +} + +enum clocks_state dispclk_dce112_get_min_clocks_state( + struct display_clock *base) +{ + return base->cur_min_clks_state; +} + +bool dispclk_dce112_set_min_clocks_state( + struct display_clock *base, + enum clocks_state clocks_state) +{ + struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); + struct dm_pp_power_level_change_request level_change_req = { + DM_PP_POWER_LEVEL_INVALID}; + + if (clocks_state > dc->max_clks_state) { + /*Requested state exceeds max supported state.*/ + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Requested state exceeds max supported state"); + return false; + } else if (clocks_state == base->cur_min_clks_state) { + /*if we're trying to set the same state, we can just return + * since nothing needs to be done*/ + return true; + } + + switch (clocks_state) { + case CLOCKS_STATE_ULTRA_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; + break; + case CLOCKS_STATE_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; + break; + case CLOCKS_STATE_NOMINAL: + level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; + break; + case CLOCKS_STATE_PERFORMANCE: + level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; + break; + case CLOCKS_STATE_INVALID: + default: + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Requested state invalid state"); + return false; + } + + /* get max clock state from PPLIB */ + if (dm_pp_apply_power_level_change_request( + base->ctx, &level_change_req)) + base->cur_min_clks_state = clocks_state; + + return true; +} + +static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) +{ + uint32_t dispclk_cntl_value; + uint32_t dp_ref_clk_cntl_value; + uint32_t dp_ref_clk_cntl_src_sel_value; + uint32_t dp_ref_clk_khz = 600000; + uint32_t target_div = INVALID_DIVIDER; + struct display_clock_dce112 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + /* ASSERT DP Reference Clock source is from DFS*/ + dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, + mmDPREFCLK_CNTL); + + dp_ref_clk_cntl_src_sel_value = + get_reg_field_value( + dp_ref_clk_cntl_value, + DPREFCLK_CNTL, DPREFCLK_SRC_SEL); + + ASSERT(dp_ref_clk_cntl_src_sel_value == 0); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + dispclk_cntl_value = dm_read_reg(dc->ctx, + mmDENTIST_DISPCLK_CNTL); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + get_reg_field_value(dispclk_cntl_value, + DENTIST_DISPCLK_CNTL, + DENTIST_DPREFCLK_WDIVIDER)); + + if (target_div != INVALID_DIVIDER) { + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + } + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) + if clock is spread for all cases: + -if SS enabled on DP Ref clock and HW de-spreading enabled with SW + calculations for DS_INCR/DS_MODULO (this is planned to be default case) + -if SS enabled on DP Ref clock and HW de-spreading enabled with HW + calculations (not planned to be used, but average clock should still + be valid) + -if SS enabled on DP Ref clock and HW de-spreading disabled + (should not be case with CIK) then SW should program all rates + generated according to average value (case as with previous ASICs) + */ + if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk->gpu_pll_ss_percentage, + disp_clk->gpu_pll_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} + +void dispclk_dce112_destroy(struct display_clock **base) +{ + struct display_clock_dce112 *dc112; + + dc112 = DCLCK112_FROM_BASE(*base); + + dm_free(dc112); + + *base = NULL; +} + +uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc) +{ + uint32_t clk = 0; + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + + switch (disp_clk->max_clks_state) { + case CLOCKS_STATE_ULTRA_LOW: + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_ULTRA_LOW)-> + display_clk_khz; + + case CLOCKS_STATE_LOW: + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)-> + display_clk_khz; + break; + + case CLOCKS_STATE_NOMINAL: + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_NOMINAL)-> + display_clk_khz; + break; + + case CLOCKS_STATE_PERFORMANCE: + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_PERFORMANCE)-> + display_clk_khz; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "Invalid clock state"); + /* just return the display engine clock for + * lowest supported state*/ + clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)-> + display_clk_khz; + break; + } + return clk; +} + +static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) +{ + /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ + struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); + + if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return deep_color_factor; + + switch (params->deep_color_depth) { + case COLOR_DEPTH_101010: + /*deep color ratio for 30bpp is 30/24 = 1.25*/ + deep_color_factor = dal_fixed32_32_from_fraction(30, 24); + break; + + case COLOR_DEPTH_121212: + /* deep color ratio for 36bpp is 36/24 = 1.5*/ + deep_color_factor = dal_fixed32_32_from_fraction(36, 24); + break; + + case COLOR_DEPTH_161616: + /* deep color ratio for 48bpp is 48/24 = 2.0 */ + deep_color_factor = dal_fixed32_32_from_fraction(48, 24); + break; + default: + break; + } + return deep_color_factor; +} + +static struct fixed32_32 get_scaler_efficiency( + struct dc_context *ctx, + struct min_clock_params *params) +{ + struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); + + if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { + scaler_efficiency = + dal_fixed32_32_add( + dal_fixed32_32_from_fraction(35555, 10000), + dal_fixed32_32_from_fraction( + 55556, + 100000 * 10000)); + } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { + scaler_efficiency = + dal_fixed32_32_add( + dal_fixed32_32_from_fraction(34285, 10000), + dal_fixed32_32_from_fraction( + 71429, + 100000 * 10000)); + } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) + scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); + + return scaler_efficiency; +} + +static struct fixed32_32 get_lb_lines_in_per_line_out( + struct min_clock_params *params, + struct fixed32_32 v_scale_ratio) +{ + struct fixed32_32 two = dal_fixed32_32_from_int(2); + struct fixed32_32 four = dal_fixed32_32_from_int(4); + struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); + struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); + + if (params->line_buffer_prefetch_enabled) + return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); + else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) + return dal_fixed32_32_one; + else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) + return f4_to_3; + else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) + return f6_to_4; + else if (dal_fixed32_32_le(v_scale_ratio, two)) + return two; + else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) + return four; + else + return dal_fixed32_32_zero; +} + +static uint32_t get_actual_required_display_clk( + struct display_clock_dce112 *disp_clk, + uint32_t target_clk_khz) +{ + uint32_t disp_clk_khz = target_clk_khz; + uint32_t div = INVALID_DIVIDER; + uint32_t did = INVALID_DID; + uint32_t scaled_vco = + disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; + + ASSERT_CRITICAL(!!disp_clk_khz); + + if (disp_clk_khz) + div = scaled_vco / disp_clk_khz; + + did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); + + if (did != INVALID_DID) { + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, did); + + if ((div != INVALID_DIVIDER) && + (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) + if (disp_clk_khz > (scaled_vco / div)) + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, + did - 1); + + if (div != INVALID_DIVIDER) + disp_clk_khz = scaled_vco / div; + + } + /* We need to add 10KHz to this value because the accuracy in VBIOS is + in 10KHz units. So we need to always round the last digit up in order + to reach the next div level.*/ + return disp_clk_khz + 10; +} + +static uint32_t calc_single_display_min_clks( + struct display_clock *base, + struct min_clock_params *params, + bool set_clk) +{ + struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; + struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; + uint32_t pix_clk_khz = 0; + uint32_t lb_source_width = 0; + struct fixed32_32 deep_color_factor; + struct fixed32_32 scaler_efficiency; + struct fixed32_32 v_filter_init; + uint32_t v_filter_init_trunc; + uint32_t num_lines_at_frame_start = 3; + struct fixed32_32 v_filter_init_ceil; + struct fixed32_32 lines_per_lines_out_at_frame_start; + struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ + uint32_t src_wdth_rnd_to_chunks; + struct fixed32_32 scaling_coeff; + struct fixed32_32 h_blank_granularity_factor = + dal_fixed32_32_one; + struct fixed32_32 fx_disp_clk_mhz; + struct fixed32_32 line_time; + struct fixed32_32 disp_pipe_pix_throughput; + struct fixed32_32 fx_alt_disp_clk_mhz; + uint32_t disp_clk_khz; + uint32_t alt_disp_clk_khz; + struct display_clock_dce112 *disp_clk_110 = DCLCK112_FROM_BASE(base); + uint32_t max_clk_khz = dispclk_dce112_get_validation_clock(base); + bool panning_allowed = false; /* TODO: receive this value from AS */ + + if (params == NULL) { + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Invalid input parameter in %s", + __func__); + return 0; + } + + deep_color_factor = get_deep_color_factor(params); + scaler_efficiency = get_scaler_efficiency(base->ctx, params); + pix_clk_khz = params->requested_pixel_clock; + lb_source_width = params->source_view.width; + + if (0 != params->dest_view.height && 0 != params->dest_view.width) { + + h_scale_ratio = dal_fixed32_32_from_fraction( + params->source_view.width, + params->dest_view.width); + v_scale_ratio = dal_fixed32_32_from_fraction( + params->source_view.height, + params->dest_view.height); + } else { + dm_logger_write(base->ctx->logger, LOG_WARNING, + "Destination height or width is 0!\n"); + } + + v_filter_init = + dal_fixed32_32_add( + v_scale_ratio, + dal_fixed32_32_add_int( + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int( + v_scale_ratio, + params->timing_info.INTERLACED), + 2), + params->scaling_info.v_taps + 1)); + v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); + + v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); + + v_filter_init_ceil = dal_fixed32_32_from_fraction( + v_filter_init_trunc, 2); + v_filter_init_ceil = dal_fixed32_32_from_int( + dal_fixed32_32_ceil(v_filter_init_ceil)); + v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); + + lines_per_lines_out_at_frame_start = + dal_fixed32_32_div_int(v_filter_init_ceil, + num_lines_at_frame_start); + lb_lines_in_per_line_out = + get_lb_lines_in_per_line_out(params, v_scale_ratio); + + if (panning_allowed) + src_wdth_rnd_to_chunks = + ((lb_source_width - 1) / 128) * 128 + 256; + else + src_wdth_rnd_to_chunks = + ((lb_source_width + 127) / 128) * 128; + + scaling_coeff = + dal_fixed32_32_div( + dal_fixed32_32_from_int(params->scaling_info.v_taps), + scaler_efficiency); + + if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) + scaling_coeff = dal_fixed32_32_max( + dal_fixed32_32_from_int( + dal_fixed32_32_ceil( + dal_fixed32_32_from_fraction( + params->scaling_info.h_taps, + 4))), + dal_fixed32_32_max( + dal_fixed32_32_mul( + scaling_coeff, + h_scale_ratio), + dal_fixed32_32_one)); + + if (!params->line_buffer_prefetch_enabled && + dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && + dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { + uint32_t line_total_pixel = + params->timing_info.h_total + lb_source_width - 256; + h_blank_granularity_factor = dal_fixed32_32_div( + dal_fixed32_32_from_int(params->timing_info.h_total), + dal_fixed32_32_div( + dal_fixed32_32_from_fraction( + line_total_pixel, 2), + h_scale_ratio)); + } + + /* Calculate display clock with ramping. Ramping factor is 1.1*/ + fx_disp_clk_mhz = + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int(scaling_coeff, 11), + 10); + line_time = dal_fixed32_32_from_fraction( + params->timing_info.h_total * 1000, pix_clk_khz); + + disp_pipe_pix_throughput = dal_fixed32_32_mul( + lb_lines_in_per_line_out, h_blank_granularity_factor); + disp_pipe_pix_throughput = dal_fixed32_32_max( + disp_pipe_pix_throughput, + lines_per_lines_out_at_frame_start); + disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( + disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), + line_time); + + if (0 != params->timing_info.h_total) { + fx_disp_clk_mhz = + dal_fixed32_32_max( + dal_fixed32_32_div_int( + dal_fixed32_32_mul_int( + scaling_coeff, pix_clk_khz), + 1000), + disp_pipe_pix_throughput); + fx_disp_clk_mhz = + dal_fixed32_32_mul( + fx_disp_clk_mhz, + dal_fixed32_32_from_fraction(11, 10)); + } + + fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, + dal_fixed32_32_mul(deep_color_factor, + dal_fixed32_32_from_fraction(11, 10))); + + /* Calculate display clock without ramping */ + fx_alt_disp_clk_mhz = scaling_coeff; + + if (0 != params->timing_info.h_total) { + fx_alt_disp_clk_mhz = dal_fixed32_32_max( + dal_fixed32_32_div_int(dal_fixed32_32_mul_int( + scaling_coeff, pix_clk_khz), + 1000), + dal_fixed32_32_div_int(dal_fixed32_32_mul_int( + disp_pipe_pix_throughput, 105), + 100)); + } + + if (set_clk && disp_clk_110->ss_on_gpu_pll && + disp_clk_110->gpu_pll_ss_divider) + fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, + dal_fixed32_32_add_int( + dal_fixed32_32_div_int( + dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk_110->gpu_pll_ss_percentage, + disp_clk_110->gpu_pll_ss_divider), 100), + 2), + 1)); + + /* convert to integer */ + disp_clk_khz = dal_fixed32_32_round( + dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); + alt_disp_clk_khz = dal_fixed32_32_round( + dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); + + if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) + disp_clk_khz = alt_disp_clk_khz; + + if (set_clk) { /* only compensate clock if we are going to set it.*/ + disp_clk_khz = get_actual_required_display_clk( + disp_clk_110, disp_clk_khz); + } + + disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; + + return disp_clk_khz; +} + +uint32_t dispclk_dce112_calculate_min_clock( + struct display_clock *base, + uint32_t path_num, + struct min_clock_params *params) +{ + uint32_t i; + uint32_t validation_clk_khz = + dispclk_dce112_get_validation_clock(base); + uint32_t min_clk_khz = validation_clk_khz; + uint32_t max_clk_khz = 0; + struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); + + if (dc->use_max_disp_clk) + return min_clk_khz; + + if (params != NULL) { + uint32_t disp_clk_khz = 0; + + for (i = 0; i < path_num; ++i) { + + disp_clk_khz = calc_single_display_min_clks( + base, params, true); + + /* update the max required clock found*/ + if (disp_clk_khz > max_clk_khz) + max_clk_khz = disp_clk_khz; + + params++; + } + } + + min_clk_khz = max_clk_khz; + + if (min_clk_khz > validation_clk_khz) + min_clk_khz = validation_clk_khz; + else if (min_clk_khz < base->min_display_clk_threshold_khz) + min_clk_khz = base->min_display_clk_threshold_khz; + + if (dc->use_max_disp_clk) + min_clk_khz = dispclk_dce112_get_validation_clock(base); + + return min_clk_khz; +} + +static bool display_clock_integrated_info_construct( + struct display_clock_dce112 *disp_clk) +{ + struct integrated_info info; + uint32_t i; + struct display_clock *base = &disp_clk->disp_clk_base; + + memset(&info, 0, sizeof(struct integrated_info)); + + disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; + if (disp_clk->dentist_vco_freq_khz == 0) + disp_clk->dentist_vco_freq_khz = 3600000; + + disp_clk->crystal_freq_khz = 100000; + + base->min_display_clk_threshold_khz = + disp_clk->dentist_vco_freq_khz / 64; + + /*update the maximum display clock for each power state*/ + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + enum clocks_state clk_state = CLOCKS_STATE_INVALID; + + switch (i) { + case 0: + clk_state = CLOCKS_STATE_ULTRA_LOW; + break; + + case 1: + clk_state = CLOCKS_STATE_LOW; + break; + + case 2: + clk_state = CLOCKS_STATE_NOMINAL; + break; + + case 3: + clk_state = CLOCKS_STATE_PERFORMANCE; + break; + + default: + clk_state = CLOCKS_STATE_INVALID; + break; + } + + /*Do not allow bad VBIOS/SBIOS to override with invalid values, + * check for > 100MHz*/ + if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { + (disp_clk->max_clks_by_state + clk_state)-> + display_clk_khz = + info.disp_clk_voltage[i].max_supported_clk; + } + } + + return true; +} + +static uint32_t get_clock(struct display_clock *dc) +{ + uint32_t disp_clock = dispclk_dce112_get_validation_clock(dc); + uint32_t target_div = INVALID_DIVIDER; + uint32_t addr = mmDENTIST_DISPCLK_CNTL; + uint32_t value = 0; + uint32_t field = 0; + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed + DID DENTIST_DISPCLK_WDIVIDER.*/ + value = dm_read_reg(dc->ctx, addr); + field = get_reg_field_value( + value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); + + /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + field); + + if (target_div != INVALID_DIVIDER) + /* Calculate the current DFS clock in KHz. + Should be okay up to 42.9 THz before overflowing.*/ + disp_clock = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + return disp_clock; +} + +enum clocks_state dispclk_dce112_get_required_clocks_state( + struct display_clock *dc, + struct state_dependent_clocks *req_clocks) +{ + int32_t i; + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + enum clocks_state low_req_clk = disp_clk->max_clks_state; + + if (!req_clocks) { + /* NULL pointer*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "%s: Invalid parameter", + __func__); + return CLOCKS_STATE_INVALID; + } + + /* Iterate from highest supported to lowest valid state, and update + * lowest RequiredState with the lowest state that satisfies + * all required clocks + */ + for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + if ((req_clocks->display_clk_khz <= + (disp_clk->max_clks_by_state + i)-> + display_clk_khz) && + (req_clocks->pixel_clk_khz <= + (disp_clk->max_clks_by_state + i)-> + pixel_clk_khz)) + low_req_clk = i; + } + return low_req_clk; +} + +void dispclk_dce112_set_clock( + struct display_clock *base, + uint32_t requested_clk_khz) +{ + struct bp_set_dce_clock_parameters dce_clk_params; + struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); + struct dc_bios *bp = base->ctx->dc_bios; + + /* Prepare to program display clock*/ + memset(&dce_clk_params, 0, sizeof(dce_clk_params)); + + /* Make sure requested clock isn't lower than minimum threshold*/ + if (requested_clk_khz > 0) + requested_clk_khz = dm_max(requested_clk_khz, + base->min_display_clk_threshold_khz); + + dce_clk_params.target_clock_frequency = requested_clk_khz; + dce_clk_params.pll_id = dc->disp_clk_base.id; + dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; + + bp->funcs->set_dce_clock(bp, &dce_clk_params); + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + + /*Program DP ref Clock*/ + /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ + dce_clk_params.target_clock_frequency = 0; + dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; + dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = + (dce_clk_params.pll_id == + CLOCK_SOURCE_COMBO_DISPLAY_PLL0); + + bp->funcs->set_dce_clock(bp, &dce_clk_params); +} + +void dispclk_dce112_set_clock_state( + struct display_clock *dc, + struct display_clock_state clk_state) +{ + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + + disp_clk->clock_state = clk_state; +} + +struct display_clock_state dispclk_dce112_get_clock_state( + struct display_clock *dc) +{ + struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); + + return disp_clk->clock_state; +} + +uint32_t dispclk_dce112_get_dfs_bypass_threshold( + struct display_clock *dc) +{ + return dce112_DFS_BYPASS_THRESHOLD_KHZ; +} + +static const struct display_clock_funcs funcs = { + .destroy = dispclk_dce112_destroy, + .calculate_min_clock = dispclk_dce112_calculate_min_clock, + .get_clock = get_clock, + .get_clock_state = dispclk_dce112_get_clock_state, + .get_dfs_bypass_threshold = dispclk_dce112_get_dfs_bypass_threshold, + .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, + .get_min_clocks_state = dispclk_dce112_get_min_clocks_state, + .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, + .get_validation_clock = dispclk_dce112_get_validation_clock, + .set_clock = dispclk_dce112_set_clock, + .set_clock_state = dispclk_dce112_set_clock_state, + .set_dp_ref_clock_source = NULL, + .set_min_clocks_state = dispclk_dce112_set_min_clocks_state, + .store_max_clocks_state = dispclk_dce112_store_max_clocks_state, + .validate = NULL, +}; + +bool dal_display_clock_dce112_construct( + struct display_clock_dce112 *dc112, + struct dc_context *ctx) +{ + struct display_clock *dc_base = &dc112->disp_clk_base; + + /*if (NULL == as) + return false;*/ + + if (!dal_display_clock_construct_base(dc_base, ctx)) + return false; + + dc_base->funcs = &funcs; + + dc112->dfs_bypass_disp_clk = 0; + + if (!display_clock_integrated_info_construct(dc112)) + dm_logger_write(dc_base->ctx->logger, LOG_WARNING, + "Cannot obtain VBIOS integrated info\n"); + + dc112->gpu_pll_ss_percentage = 0; + dc112->gpu_pll_ss_divider = 1000; + dc112->ss_on_gpu_pll = false; + + dc_base->id = CLOCK_SOURCE_ID_DFS; +/* Initially set max clocks state to nominal. This should be updated by + * via a pplib call to DAL IRI eventually calling a + * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in + * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ + dc112->max_clks_state = CLOCKS_STATE_NOMINAL; + + dc112->disp_clk_base.min_display_clk_threshold_khz = + dc112->crystal_freq_khz; + + if (dc112->disp_clk_base.min_display_clk_threshold_khz < + (dc112->dentist_vco_freq_khz / 62)) + dc112->disp_clk_base.min_display_clk_threshold_khz = + (dc112->dentist_vco_freq_khz / 62); + + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_01], + DIVIDER_RANGE_01_START, + DIVIDER_RANGE_01_STEP_SIZE, + DIVIDER_RANGE_01_BASE_DIVIDER_ID, + DIVIDER_RANGE_02_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_02], + DIVIDER_RANGE_02_START, + DIVIDER_RANGE_02_STEP_SIZE, + DIVIDER_RANGE_02_BASE_DIVIDER_ID, + DIVIDER_RANGE_03_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_03], + DIVIDER_RANGE_03_START, + DIVIDER_RANGE_03_STEP_SIZE, + DIVIDER_RANGE_03_BASE_DIVIDER_ID, + DIVIDER_RANGE_MAX_DIVIDER_ID); + + { + uint32_t ss_info_num = + ctx->dc_bios->funcs-> + get_ss_entry_number(ctx->dc_bios, AS_SIGNAL_TYPE_GPU_PLL); + + if (ss_info_num) { + struct spread_spectrum_info info; + bool result; + + memset(&info, 0, sizeof(info)); + + result = + (BP_RESULT_OK == ctx->dc_bios->funcs-> + get_spread_spectrum_info(ctx->dc_bios, + AS_SIGNAL_TYPE_GPU_PLL, 0, &info)) ? true : false; + + + /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS + * even if SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be sign + * that SS is enabled + */ + if (result && info.spread_spectrum_percentage != 0) { + dc112->ss_on_gpu_pll = true; + dc112->gpu_pll_ss_divider = + info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + dc112->gpu_pll_ss_percentage = + info.spread_spectrum_percentage; + } + } + + } + } + + dc112->use_max_disp_clk = true; + dc112->max_clks_by_state = max_clks_by_state; + + return true; +} + +/***************************************************************************** + * public functions + *****************************************************************************/ + +struct display_clock *dal_display_clock_dce112_create( + struct dc_context *ctx) +{ + struct display_clock_dce112 *dc112; + + dc112 = dm_alloc(sizeof(struct display_clock_dce112)); + + if (dc112 == NULL) + return NULL; + + if (dal_display_clock_dce112_construct(dc112, ctx)) + return &dc112->disp_clk_base; + + dm_free(dc112); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h new file mode 100644 index 000000000000..937e17929b7c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -0,0 +1,114 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_DISPLAY_CLOCK_DCE112_H__ +#define __DAL_DISPLAY_CLOCK_DCE112_H__ + +#include "gpu/display_clock.h" + +struct display_clock_dce112 { + struct display_clock disp_clk_base; + /* Max display block clocks state*/ + enum clocks_state max_clks_state; + bool use_max_disp_clk; + uint32_t crystal_freq_khz; + uint32_t dentist_vco_freq_khz; + /* Cache the status of DFS-bypass feature*/ + bool dfs_bypass_enabled; + /* GPU PLL SS percentage (if down-spread enabled) */ + uint32_t gpu_pll_ss_percentage; + /* GPU PLL SS percentage Divider (100 or 1000) */ + uint32_t gpu_pll_ss_divider; + /* Flag for Enabled SS on GPU PLL */ + bool ss_on_gpu_pll; + /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. + * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ + uint32_t dfs_bypass_disp_clk; + struct display_clock_state clock_state; + struct state_dependent_clocks *max_clks_by_state; + +}; + +#define DCLCK112_FROM_BASE(dc_base) \ + container_of(dc_base, struct display_clock_dce112, disp_clk_base) + +/* Array identifiers and count for the divider ranges.*/ +enum divider_range_count { + DIVIDER_RANGE_01 = 0, + DIVIDER_RANGE_02, + DIVIDER_RANGE_03, + DIVIDER_RANGE_MAX /* == 3*/ +}; + +/* Starting point for each divider range.*/ +enum divider_range_start { + DIVIDER_RANGE_01_START = 200, /* 2.00*/ + DIVIDER_RANGE_02_START = 1600, /* 16.00*/ + DIVIDER_RANGE_03_START = 3200, /* 32.00*/ + DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ +}; + +bool dal_display_clock_dce112_construct( + struct display_clock_dce112 *dc112, + struct dc_context *ctx); + +void dispclk_dce112_destroy(struct display_clock **base); + +uint32_t dispclk_dce112_calculate_min_clock( + struct display_clock *base, + uint32_t path_num, + struct min_clock_params *params); + +struct display_clock_state dispclk_dce112_get_clock_state( + struct display_clock *dc); + +uint32_t dispclk_dce112_get_dfs_bypass_threshold( + struct display_clock *dc); + +enum clocks_state dispclk_dce112_get_min_clocks_state( + struct display_clock *base); + +enum clocks_state dispclk_dce112_get_required_clocks_state( + struct display_clock *dc, + struct state_dependent_clocks *req_clocks); + +uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc); + +void dispclk_dce112_set_clock( + struct display_clock *base, + uint32_t requested_clk_khz); + +void dispclk_dce112_set_clock_state( + struct display_clock *dc, + struct display_clock_state clk_state); + +bool dispclk_dce112_set_min_clocks_state( + struct display_clock *base, + enum clocks_state clocks_state); + +void dispclk_dce112_store_max_clocks_state( + struct display_clock *base, + enum clocks_state max_clocks_state); + +#endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c new file mode 100644 index 000000000000..eedcfd6232fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -0,0 +1,934 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "include/bios_parser_interface.h" +#include "include/fixed32_32.h" +#include "include/logger_interface.h" + +#include "../divider_range.h" +#include "display_clock_dce80.h" +#include "dc.h" + +#define DCE80_DFS_BYPASS_THRESHOLD_KHZ 100000 + +/* Max clock values for each state indexed by "enum clocks_state": */ +static struct state_dependent_clocks max_clks_by_state[] = { +/* ClocksStateInvalid - should not be used */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateLow */ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, +/* ClocksStateNominal */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, +/* ClocksStatePerformance */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; + +/* Starting point for each divider range.*/ +enum divider_range_start { + DIVIDER_RANGE_01_START = 200, /* 2.00*/ + DIVIDER_RANGE_02_START = 1600, /* 16.00*/ + DIVIDER_RANGE_03_START = 3200, /* 32.00*/ + DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ +}; + +/* Ranges for divider identifiers (Divider ID or DID) + mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +enum divider_id_register_setting { + DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, + DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, + DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, + DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 +}; + +/* Step size between each divider within a range. + Incrementing the DENTIST_DISPCLK_WDIVIDER by one + will increment the divider by this much.*/ +enum divider_range_step_size { + DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ + DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ + DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +}; + +/* Array identifiers and count for the divider ranges.*/ +enum divider_range_count { + DIVIDER_RANGE_01 = 0, + DIVIDER_RANGE_02, + DIVIDER_RANGE_03, + DIVIDER_RANGE_MAX /* == 3*/ +}; + +static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + +#define FROM_DISPLAY_CLOCK(base) \ + container_of(base, struct display_clock_dce80, disp_clk) + +static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) +{ + /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ + struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); + + if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) + return deep_color_factor; + + switch (params->deep_color_depth) { + case COLOR_DEPTH_101010: + /*deep color ratio for 30bpp is 30/24 = 1.25*/ + deep_color_factor = dal_fixed32_32_from_fraction(30, 24); + break; + + case COLOR_DEPTH_121212: + /* deep color ratio for 36bpp is 36/24 = 1.5*/ + deep_color_factor = dal_fixed32_32_from_fraction(36, 24); + break; + + case COLOR_DEPTH_161616: + /* deep color ratio for 48bpp is 48/24 = 2.0 */ + deep_color_factor = dal_fixed32_32_from_fraction(48, 24); + break; + default: + break; + } + return deep_color_factor; +} + +static uint32_t get_scaler_efficiency(struct min_clock_params *params) +{ + uint32_t scaler_efficiency = 3; + + switch (params->scaler_efficiency) { + case V_SCALER_EFFICIENCY_LB18BPP: + case V_SCALER_EFFICIENCY_LB24BPP: + scaler_efficiency = 4; + break; + + case V_SCALER_EFFICIENCY_LB30BPP: + case V_SCALER_EFFICIENCY_LB36BPP: + scaler_efficiency = 3; + break; + + default: + break; + } + + return scaler_efficiency; +} + +static uint32_t get_actual_required_display_clk( + struct display_clock_dce80 *disp_clk, + uint32_t target_clk_khz) +{ + uint32_t disp_clk_khz = target_clk_khz; + uint32_t div = INVALID_DIVIDER; + uint32_t did = INVALID_DID; + uint32_t scaled_vco = + disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; + + ASSERT(disp_clk_khz); + + if (disp_clk_khz) + div = scaled_vco / disp_clk_khz; + + did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); + + if (did != INVALID_DID) { + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, did); + + if ((div != INVALID_DIVIDER) && + (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) + if (disp_clk_khz > (scaled_vco / div)) + div = dal_divider_range_get_divider( + divider_ranges, DIVIDER_RANGE_MAX, + did - 1); + + if (div != INVALID_DIVIDER) + disp_clk_khz = scaled_vco / div; + + } + /* We need to add 10KHz to this value because the accuracy in VBIOS is + in 10KHz units. So we need to always round the last digit up in order + to reach the next div level.*/ + return disp_clk_khz + 10; +} + +static uint32_t get_validation_clock(struct display_clock *dc) +{ + uint32_t clk = 0; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + switch (disp_clk->max_clks_state) { + case CLOCKS_STATE_ULTRA_LOW: + /*Currently not supported, it has 0 in table entry*/ + case CLOCKS_STATE_LOW: + clk = max_clks_by_state[CLOCKS_STATE_LOW]. + display_clk_khz; + break; + + case CLOCKS_STATE_NOMINAL: + clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. + display_clk_khz; + break; + + case CLOCKS_STATE_PERFORMANCE: + clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. + display_clk_khz; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State*/ + BREAK_TO_DEBUGGER(); + /* just return the display engine clock for + * lowest supported state*/ + clk = max_clks_by_state[CLOCKS_STATE_LOW]. + display_clk_khz; + break; + } + return clk; +} + +static uint32_t calc_single_display_min_clks( + struct display_clock *base, + struct min_clock_params *params, + bool set_clk) +{ + struct fixed32_32 h_scale = dal_fixed32_32_from_int(1); + struct fixed32_32 v_scale = dal_fixed32_32_from_int(1); + uint32_t pix_clk_khz = params->requested_pixel_clock; + uint32_t line_total = params->timing_info.h_total; + uint32_t max_clk_khz = get_validation_clock(base); + struct fixed32_32 deep_color_factor = get_deep_color_factor(params); + uint32_t scaler_efficiency = get_scaler_efficiency(params); + struct fixed32_32 v_filter_init; + uint32_t v_filter_init_trunc; + struct fixed32_32 v_filter_init_ceil; + struct fixed32_32 src_lines_per_dst_line; + uint32_t src_wdth_rnd_to_chunks; + struct fixed32_32 scaling_coeff; + struct fixed32_32 fx_disp_clk_khz; + struct fixed32_32 fx_alt_disp_clk_khz; + uint32_t disp_clk_khz; + uint32_t alt_disp_clk_khz; + struct display_clock_dce80 *dc = FROM_DISPLAY_CLOCK(base); + + if (0 != params->dest_view.height && 0 != params->dest_view.width) { + + h_scale = dal_fixed32_32_from_fraction( + params->source_view.width, + params->dest_view.width); + v_scale = dal_fixed32_32_from_fraction( + params->source_view.height, + params->dest_view.height); + } + + v_filter_init = dal_fixed32_32_from_fraction( + params->scaling_info.v_taps, 2u); + v_filter_init = dal_fixed32_32_add(v_filter_init, + dal_fixed32_32_div_int(v_scale, 2)); + v_filter_init = dal_fixed32_32_add(v_filter_init, + dal_fixed32_32_from_fraction(15, 10)); + + v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); + + v_filter_init_ceil = dal_fixed32_32_from_fraction( + v_filter_init_trunc, 2); + v_filter_init_ceil = dal_fixed32_32_from_int( + dal_fixed32_32_ceil(v_filter_init_ceil)); + v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); + v_filter_init_ceil = dal_fixed32_32_div_int(v_filter_init_ceil, 3); + v_filter_init_ceil = dal_fixed32_32_from_int( + dal_fixed32_32_ceil(v_filter_init_ceil)); + + src_lines_per_dst_line = dal_fixed32_32_max( + dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_scale)), + v_filter_init_ceil); + + src_wdth_rnd_to_chunks = + ((params->source_view.width - 1) / 128) * 128 + 256; + + scaling_coeff = dal_fixed32_32_max( + dal_fixed32_32_from_fraction(params->scaling_info.h_taps, 4), + dal_fixed32_32_mul( + dal_fixed32_32_from_fraction( + params->scaling_info.v_taps, + scaler_efficiency), + h_scale)); + + scaling_coeff = dal_fixed32_32_max(scaling_coeff, h_scale); + + fx_disp_clk_khz = dal_fixed32_32_mul( + scaling_coeff, dal_fixed32_32_from_fraction(11, 10)); + if (0 != line_total) { + struct fixed32_32 d_clk = dal_fixed32_32_mul_int( + src_lines_per_dst_line, src_wdth_rnd_to_chunks); + d_clk = dal_fixed32_32_div_int(d_clk, line_total); + d_clk = dal_fixed32_32_mul(d_clk, + dal_fixed32_32_from_fraction(11, 10)); + fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, d_clk); + } + + fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, + dal_fixed32_32_mul(deep_color_factor, + dal_fixed32_32_from_fraction(11, 10))); + + fx_disp_clk_khz = dal_fixed32_32_mul_int(fx_disp_clk_khz, pix_clk_khz); + fx_disp_clk_khz = dal_fixed32_32_mul(fx_disp_clk_khz, + dal_fixed32_32_from_fraction(1005, 1000)); + + fx_alt_disp_clk_khz = scaling_coeff; + + if (0 != line_total) { + struct fixed32_32 d_clk = dal_fixed32_32_mul_int( + src_lines_per_dst_line, src_wdth_rnd_to_chunks); + d_clk = dal_fixed32_32_div_int(d_clk, line_total); + d_clk = dal_fixed32_32_mul(d_clk, + dal_fixed32_32_from_fraction(105, 100)); + fx_alt_disp_clk_khz = dal_fixed32_32_max( + fx_alt_disp_clk_khz, d_clk); + } + fx_alt_disp_clk_khz = dal_fixed32_32_max( + fx_alt_disp_clk_khz, fx_alt_disp_clk_khz); + + fx_alt_disp_clk_khz = dal_fixed32_32_mul_int( + fx_alt_disp_clk_khz, pix_clk_khz); + + /* convert to integer*/ + disp_clk_khz = dal_fixed32_32_floor(fx_disp_clk_khz); + alt_disp_clk_khz = dal_fixed32_32_floor(fx_alt_disp_clk_khz); + + if (set_clk) { /* only compensate clock if we are going to set it.*/ + disp_clk_khz = get_actual_required_display_clk( + dc, disp_clk_khz); + alt_disp_clk_khz = get_actual_required_display_clk( + dc, alt_disp_clk_khz); + } + + if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) + disp_clk_khz = alt_disp_clk_khz; + + return disp_clk_khz; + +} + +static uint32_t calc_cursor_bw_for_min_clks(struct min_clock_params *params) +{ + + struct fixed32_32 v_scale = dal_fixed32_32_from_int(1); + struct fixed32_32 v_filter_ceiling; + struct fixed32_32 src_lines_per_dst_line; + struct fixed32_32 cursor_bw; + + /* DCE8 Mode Support and Mode Set Architecture Specification Rev 1.3 + 6.3.3 Cursor data Throughput requirement on DISPCLK + The MCIF to DCP cursor data return throughput is one pixel per DISPCLK + shared among the display heads. + If (Total Cursor Bandwidth in pixels for All heads> DISPCLK) + The mode is not supported + Cursor Bandwidth in Pixels = Cursor Width * + (SourceLinesPerDestinationLine / Line Time) + Assuming that Cursor Width = 128 + */ + /*In the hardware doc they mention an Interlace Factor + It is not used here because we have already used it when + calculating destination view*/ + if (0 != params->dest_view.height) + v_scale = dal_fixed32_32_from_fraction( + params->source_view.height, + params->dest_view.height); + + { + /*Do: Vertical Filter Init = 0.5 + VTAPS/2 + VSR/2 * Interlace Factor*/ + /*Interlace Factor is included in verticalScaleRatio*/ + struct fixed32_32 v_filter = dal_fixed32_32_add( + dal_fixed32_32_from_fraction(params->scaling_info.v_taps, 2), + dal_fixed32_32_div_int(v_scale, 2)); + /*Do : Ceiling (Vertical Filter Init, 2)/3 )*/ + v_filter_ceiling = dal_fixed32_32_div_int(v_filter, 2); + v_filter_ceiling = dal_fixed32_32_mul_int( + dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_filter_ceiling)), + 2); + v_filter_ceiling = dal_fixed32_32_div_int(v_filter_ceiling, 3); + } + /*Do : MAX( CeilCeiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/ + /*Do : SourceLinesPerDestinationLine = + * MAX( Ceiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/ + src_lines_per_dst_line = dal_fixed32_32_max(v_scale, v_filter_ceiling); + + if ((params->requested_pixel_clock != 0) && + (params->timing_info.h_total != 0)) { + /* pixelClock is in units of KHz. Calc lineTime in us*/ + struct fixed32_32 inv_line_time = dal_fixed32_32_from_fraction( + params->requested_pixel_clock, + params->timing_info.h_total); + cursor_bw = dal_fixed32_32_mul( + dal_fixed32_32_mul_int(inv_line_time, 128), + src_lines_per_dst_line); + } + + /* convert to integer*/ + return dal_fixed32_32_floor(cursor_bw); +} + +static bool validate( + struct display_clock *dc, + struct min_clock_params *params) +{ + uint32_t max_clk_khz = get_validation_clock(dc); + uint32_t req_clk_khz; + + if (params == NULL) + return false; + + req_clk_khz = calc_single_display_min_clks(dc, params, false); + + return (req_clk_khz <= max_clk_khz); +} + +static uint32_t calculate_min_clock( + struct display_clock *dc, + uint32_t path_num, + struct min_clock_params *params) +{ + uint32_t i; + uint32_t validation_clk_khz = get_validation_clock(dc); + uint32_t min_clk_khz = validation_clk_khz; + uint32_t max_clk_khz = 0; + uint32_t total_cursor_bw = 0; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + if (disp_clk->use_max_disp_clk) + return min_clk_khz; + + if (params != NULL) { + uint32_t disp_clk_khz = 0; + + for (i = 0; i < path_num; ++i) { + disp_clk_khz = calc_single_display_min_clks( + dc, params, true); + + /* update the max required clock found*/ + if (disp_clk_khz > max_clk_khz) + max_clk_khz = disp_clk_khz; + + disp_clk_khz = calc_cursor_bw_for_min_clks(params); + + total_cursor_bw += disp_clk_khz; + + params++; + + } + } + + max_clk_khz = (total_cursor_bw > max_clk_khz) ? total_cursor_bw : + max_clk_khz; + + min_clk_khz = max_clk_khz; + + /*"Cursor data Throughput requirement on DISPCLK is now a factor, + * need to change the code */ + ASSERT(total_cursor_bw < validation_clk_khz); + + if (min_clk_khz > validation_clk_khz) + min_clk_khz = validation_clk_khz; + else if (min_clk_khz < dc->min_display_clk_threshold_khz) + min_clk_khz = dc->min_display_clk_threshold_khz; + + return min_clk_khz; +} + +static void set_clock( + struct display_clock *dc, + uint32_t requested_clk_khz) +{ + struct bp_pixel_clock_parameters pxl_clk_params; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + struct dc_bios *bp = dc->ctx->dc_bios; + + /* Prepare to program display clock*/ + memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); + + pxl_clk_params.target_pixel_clock = requested_clk_khz; + pxl_clk_params.pll_id = dc->id; + + bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); + + if (disp_clk->dfs_bypass_enabled) { + + /* Cache the fixed display clock*/ + disp_clk->dfs_bypass_disp_clk = + pxl_clk_params.dfs_bypass_display_clock; + } + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + disp_clk->cur_min_clks_state = CLOCKS_STATE_NOMINAL; +} + +static uint32_t get_clock(struct display_clock *dc) +{ + uint32_t disp_clock = get_validation_clock(dc); + uint32_t target_div = INVALID_DIVIDER; + uint32_t addr = mmDENTIST_DISPCLK_CNTL; + uint32_t value = 0; + uint32_t field = 0; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) + return disp_clk->dfs_bypass_disp_clk; + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed + DID DENTIST_DISPCLK_WDIVIDER.*/ + value = dm_read_reg(dc->ctx, addr); + field = get_reg_field_value( + value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); + + /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + field); + + if (target_div != INVALID_DIVIDER) + /* Calculate the current DFS clock in KHz. + Should be okay up to 42.9 THz before overflowing.*/ + disp_clock = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + return disp_clock; +} + +static void set_clock_state( + struct display_clock *dc, + struct display_clock_state clk_state) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + disp_clk->clock_state = clk_state; +} +static struct display_clock_state get_clock_state( + struct display_clock *dc) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + return disp_clk->clock_state; +} + +static enum clocks_state get_min_clocks_state(struct display_clock *dc) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + return disp_clk->cur_min_clks_state; +} + +static enum clocks_state get_required_clocks_state + (struct display_clock *dc, + struct state_dependent_clocks *req_clocks) +{ + int32_t i; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + enum clocks_state low_req_clk = disp_clk->max_clks_state; + + if (!req_clocks) { + /* NULL pointer*/ + BREAK_TO_DEBUGGER(); + return CLOCKS_STATE_INVALID; + } + + /* Iterate from highest supported to lowest valid state, and update + * lowest RequiredState with the lowest state that satisfies + * all required clocks + */ + for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + if ((req_clocks->display_clk_khz <= + max_clks_by_state[i].display_clk_khz) && + (req_clocks->pixel_clk_khz <= + max_clks_by_state[i].pixel_clk_khz)) + low_req_clk = i; + } + return low_req_clk; +} + +static bool set_min_clocks_state( + struct display_clock *dc, + enum clocks_state clocks_state) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + struct dm_pp_power_level_change_request level_change_req = { + DM_PP_POWER_LEVEL_INVALID}; + + if (clocks_state > disp_clk->max_clks_state) { + /*Requested state exceeds max supported state.*/ + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "Requested state exceeds max supported state"); + return false; + } else if (clocks_state == dc->cur_min_clks_state) { + /*if we're trying to set the same state, we can just return + * since nothing needs to be done*/ + return true; + } + + switch (clocks_state) { + case CLOCKS_STATE_ULTRA_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; + break; + case CLOCKS_STATE_LOW: + level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; + break; + case CLOCKS_STATE_NOMINAL: + level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; + break; + case CLOCKS_STATE_PERFORMANCE: + level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; + break; + case CLOCKS_STATE_INVALID: + default: + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "Requested state invalid state"); + return false; + } + + /* get max clock state from PPLIB */ + if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) + dc->cur_min_clks_state = clocks_state; + + return true; +} + +static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) +{ + uint32_t dispclk_cntl_value; + uint32_t dp_ref_clk_cntl_value; + uint32_t dp_ref_clk_cntl_src_sel_value; + uint32_t dp_ref_clk_khz = 600000; + uint32_t target_div = INVALID_DIVIDER; + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + /* ASSERT DP Reference Clock source is from DFS*/ + dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, + mmDPREFCLK_CNTL); + + dp_ref_clk_cntl_src_sel_value = + get_reg_field_value( + dp_ref_clk_cntl_value, + DPREFCLK_CNTL, DPREFCLK_SRC_SEL); + + ASSERT(dp_ref_clk_cntl_src_sel_value == 0); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + dispclk_cntl_value = dm_read_reg(dc->ctx, + mmDENTIST_DISPCLK_CNTL); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dal_divider_range_get_divider( + divider_ranges, + DIVIDER_RANGE_MAX, + get_reg_field_value(dispclk_cntl_value, + DENTIST_DISPCLK_CNTL, + DENTIST_DPREFCLK_WDIVIDER)); + + if (target_div != INVALID_DIVIDER) { + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR + * disp_clk->dentist_vco_freq_khz) / target_div; + } + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) + if clock is spread for all cases: + -if SS enabled on DP Ref clock and HW de-spreading enabled with SW + calculations for DS_INCR/DS_MODULO (this is planned to be default case) + -if SS enabled on DP Ref clock and HW de-spreading enabled with HW + calculations (not planned to be used, but average clock should still + be valid) + -if SS enabled on DP Ref clock and HW de-spreading disabled + (should not be case with CIK) then SW should program all rates + generated according to average value (case as with previous ASICs) + */ + if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + disp_clk->gpu_pll_ss_percentage, + disp_clk->gpu_pll_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} + +static void store_max_clocks_state( + struct display_clock *dc, + enum clocks_state max_clocks_state) +{ + struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); + + switch (max_clocks_state) { + case CLOCKS_STATE_LOW: + case CLOCKS_STATE_NOMINAL: + case CLOCKS_STATE_PERFORMANCE: + case CLOCKS_STATE_ULTRA_LOW: + disp_clk->max_clks_state = max_clocks_state; + break; + + case CLOCKS_STATE_INVALID: + default: + /*Invalid Clocks State!*/ + BREAK_TO_DEBUGGER(); + break; + } +} + +static void display_clock_ss_construct( + struct display_clock_dce80 *disp_clk) +{ + struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios; + uint32_t ss_entry_num = bp->funcs->get_ss_entry_number(bp, + AS_SIGNAL_TYPE_GPU_PLL); + + /*Read SS Info from VBIOS SS Info table for DP Reference Clock spread.*/ + if (ss_entry_num > 0) {/* Should be only one entry */ + struct spread_spectrum_info ss_info; + enum bp_result res; + + memset(&ss_info, 0, sizeof(struct spread_spectrum_info)); + + res = bp->funcs->get_spread_spectrum_info(bp, + AS_SIGNAL_TYPE_GPU_PLL, 0, &ss_info); + + /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS even if + * SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be + * sign that SS is enabled*/ + if (res == BP_RESULT_OK && ss_info.spread_spectrum_percentage != 0) { + disp_clk->ss_on_gpu_pll = true; + disp_clk->gpu_pll_ss_divider = + ss_info.spread_percentage_divider; + if (ss_info.type.CENTER_MODE == 0) + /* Currently we need only SS + * percentage for down-spread*/ + disp_clk->gpu_pll_ss_percentage = + ss_info.spread_spectrum_percentage; + } + } +} + +static bool display_clock_integrated_info_construct( + struct display_clock_dce80 *disp_clk) +{ + struct dc_debug *debug = &disp_clk->disp_clk.ctx->dc->debug; + struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios; + struct integrated_info info = { { { 0 } } }; + struct firmware_info fw_info = { { 0 } }; + uint32_t i; + + if (bp->integrated_info) + info = *bp->integrated_info; + + disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; + if (disp_clk->dentist_vco_freq_khz == 0) { + bp->funcs->get_firmware_info(bp, &fw_info); + disp_clk->dentist_vco_freq_khz = + fw_info.smu_gpu_pll_output_freq; + if (disp_clk->dentist_vco_freq_khz == 0) + disp_clk->dentist_vco_freq_khz = 3600000; + } + disp_clk->disp_clk.min_display_clk_threshold_khz = + disp_clk->dentist_vco_freq_khz / 64; + + /* TODO: initialise disp_clk->dfs_bypass_disp_clk */ + + /*update the maximum display clock for each power state*/ + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + enum clocks_state clk_state = CLOCKS_STATE_INVALID; + + switch (i) { + case 0: + clk_state = CLOCKS_STATE_ULTRA_LOW; + break; + + case 1: + clk_state = CLOCKS_STATE_LOW; + break; + + case 2: + clk_state = CLOCKS_STATE_NOMINAL; + break; + + case 3: + clk_state = CLOCKS_STATE_PERFORMANCE; + break; + + default: + clk_state = CLOCKS_STATE_INVALID; + break; + } + + /*Do not allow bad VBIOS/SBIOS to override with invalid values, + * check for > 100MHz*/ + if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { + max_clks_by_state[clk_state].display_clk_khz = + info.disp_clk_voltage[i].max_supported_clk; + } + } + + disp_clk->dfs_bypass_enabled = false; + if (!debug->disable_dfs_bypass) + if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) + disp_clk->dfs_bypass_enabled = true; + + disp_clk->use_max_disp_clk = debug->max_disp_clk; + + return true; +} + +static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) +{ + return DCE80_DFS_BYPASS_THRESHOLD_KHZ; +} + +static void destroy(struct display_clock **dc) +{ + struct display_clock_dce80 *disp_clk; + + disp_clk = FROM_DISPLAY_CLOCK(*dc); + dm_free(disp_clk); + *dc = NULL; +} + +static const struct display_clock_funcs funcs = { + .calculate_min_clock = calculate_min_clock, + .destroy = destroy, + .get_clock = get_clock, + .get_clock_state = get_clock_state, + .get_dfs_bypass_threshold = get_dfs_bypass_threshold, + .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, + .get_min_clocks_state = get_min_clocks_state, + .get_required_clocks_state = get_required_clocks_state, + .get_validation_clock = get_validation_clock, + .set_clock = set_clock, + .set_clock_state = set_clock_state, + .set_dp_ref_clock_source = + dal_display_clock_base_set_dp_ref_clock_source, + .set_min_clocks_state = set_min_clocks_state, + .store_max_clocks_state = store_max_clocks_state, + .validate = validate, +}; + +static bool display_clock_construct( + struct dc_context *ctx, + struct display_clock_dce80 *disp_clk) +{ + struct display_clock *dc_base = &disp_clk->disp_clk; + + if (!dal_display_clock_construct_base(dc_base, ctx)) + return false; + + dc_base->funcs = &funcs; + /* + * set_dp_ref_clock_source + * set_clock_state + * get_clock_state + * get_dfs_bypass_threshold + */ + + disp_clk->gpu_pll_ss_percentage = 0; + disp_clk->gpu_pll_ss_divider = 1000; + disp_clk->ss_on_gpu_pll = false; + disp_clk->dfs_bypass_enabled = false; + disp_clk->dfs_bypass_disp_clk = 0; + disp_clk->use_max_disp_clk = true;/* false will hang the system! */ + + disp_clk->disp_clk.id = CLOCK_SOURCE_ID_DFS; +/* Initially set max clocks state to nominal. This should be updated by + * via a pplib call to DAL IRI eventually calling a + * DisplayEngineClock_Dce50::StoreMaxClocksState(). This call will come in + * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ + disp_clk->max_clks_state = CLOCKS_STATE_NOMINAL; +/* Initially set current min clocks state to invalid since we + * cannot make any assumption about PPLIB's initial state. This will be updated + * by HWSS via SetMinClocksState() on first mode set prior to programming + * state dependent clocks.*/ + disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; + + display_clock_ss_construct(disp_clk); + + if (!display_clock_integrated_info_construct(disp_clk)) { + dm_logger_write(dc_base->ctx->logger, LOG_WARNING, + "Cannot obtain VBIOS integrated info"); + } + + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_01], + DIVIDER_RANGE_01_START, + DIVIDER_RANGE_01_STEP_SIZE, + DIVIDER_RANGE_01_BASE_DIVIDER_ID, + DIVIDER_RANGE_02_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_02], + DIVIDER_RANGE_02_START, + DIVIDER_RANGE_02_STEP_SIZE, + DIVIDER_RANGE_02_BASE_DIVIDER_ID, + DIVIDER_RANGE_03_BASE_DIVIDER_ID); + dal_divider_range_construct( + ÷r_ranges[DIVIDER_RANGE_03], + DIVIDER_RANGE_03_START, + DIVIDER_RANGE_03_STEP_SIZE, + DIVIDER_RANGE_03_BASE_DIVIDER_ID, + DIVIDER_RANGE_MAX_DIVIDER_ID); + return true; +} + +struct display_clock *dal_display_clock_dce80_create( + struct dc_context *ctx) +{ + struct display_clock_dce80 *disp_clk; + + disp_clk = dm_alloc(sizeof(struct display_clock_dce80)); + + if (disp_clk == NULL) + return NULL; + + if (display_clock_construct(ctx, disp_clk)) + return &disp_clk->disp_clk; + + dm_free(disp_clk); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h new file mode 100644 index 000000000000..944dd0380413 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -0,0 +1,57 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_DISPLAY_CLOCK_DCE80_H__ +#define __DAL_DISPLAY_CLOCK_DCE80_H__ + +#include "gpu/display_clock.h" + +struct display_clock_dce80 { + struct display_clock disp_clk; + /* DFS input - GPUPLL VCO frequency - from VBIOS Firmware info. */ + uint32_t dentist_vco_freq_khz; + /* GPU PLL SS percentage (if down-spread enabled)*/ + uint32_t gpu_pll_ss_percentage; + /* GPU PLL SS percentage Divider (100 or 1000)*/ + uint32_t gpu_pll_ss_divider; + /* Flag for Enabled SS on GPU PLL*/ + bool ss_on_gpu_pll; + /* Max display block clocks state*/ + enum clocks_state max_clks_state; + /* Current minimum display block clocks state*/ + enum clocks_state cur_min_clks_state; + /* DFS-bypass feature variable + Cache the status of DFS-bypass feature*/ + bool dfs_bypass_enabled; + /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. + * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ + uint32_t dfs_bypass_disp_clk; + bool use_max_disp_clk; + struct display_clock_state clock_state; +}; + +struct display_clock *dal_display_clock_dce80_create( + struct dc_context *ctx); + +#endif /* __DAL_DISPLAY_CLOCK_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c new file mode 100644 index 000000000000..bcc0a5132600 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c @@ -0,0 +1,217 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "display_clock.h" + +void dal_display_clock_base_set_dp_ref_clock_source( + struct display_clock *disp_clk, + enum clock_source_id clk_src) +{/*must be implemented in derived*/ + +} + +void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, + struct display_clock_state clk_state) +{ + /*Implemented only in DCE81*/ +} +struct display_clock_state dal_display_clock_base_get_clock_state( + struct display_clock *disp_clk) +{ + /*Implemented only in DCE81*/ + struct display_clock_state state = {0}; + return state; +} +uint32_t dal_display_clock_base_get_dfs_bypass_threshold( + struct display_clock *disp_clk) +{ + /*Implemented only in DCE81*/ + return 0; +} + +bool dal_display_clock_construct_base( + struct display_clock *base, + struct dc_context *ctx) +{ + base->ctx = ctx; + base->id = CLOCK_SOURCE_ID_DCPLL; + base->min_display_clk_threshold_khz = 0; + +/* Initially set current min clocks state to invalid since we + * cannot make any assumption about PPLIB's initial state. This will be updated + * by HWSS via SetMinClocksState() on first mode set prior to programming + * state dependent clocks.*/ + base->cur_min_clks_state = CLOCKS_STATE_INVALID; + + return true; +} + +void dal_display_clock_destroy(struct display_clock **disp_clk) +{ + if (!disp_clk || !*disp_clk) { + BREAK_TO_DEBUGGER(); + return; + } + + (*disp_clk)->funcs->destroy(disp_clk); + + *disp_clk = NULL; +} + +bool dal_display_clock_validate( + struct display_clock *disp_clk, + struct min_clock_params *params) +{ + return disp_clk->funcs->validate(disp_clk, params); +} + +uint32_t dal_display_clock_calculate_min_clock( + struct display_clock *disp_clk, + uint32_t path_num, + struct min_clock_params *params) +{ + return disp_clk->funcs->calculate_min_clock(disp_clk, path_num, params); +} + +uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_validation_clock(disp_clk); +} + +void dal_display_clock_set_clock( + struct display_clock *disp_clk, + uint32_t requested_clock_khz) +{ + disp_clk->funcs->set_clock(disp_clk, requested_clock_khz); +} + +uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_clock(disp_clk); +} + +bool dal_display_clock_get_min_clocks_state( + struct display_clock *disp_clk, + enum clocks_state *clocks_state) +{ + if (!disp_clk->funcs->get_min_clocks_state) + return false; + + *clocks_state = disp_clk->funcs->get_min_clocks_state(disp_clk); + return true; +} + +bool dal_display_clock_get_required_clocks_state( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks, + enum clocks_state *clocks_state) +{ + if (!disp_clk->funcs->get_required_clocks_state) + return false; + + *clocks_state = disp_clk->funcs->get_required_clocks_state( + disp_clk, req_clocks); + return true; +} + +bool dal_display_clock_set_min_clocks_state( + struct display_clock *disp_clk, + enum clocks_state clocks_state) +{ + if (!disp_clk->funcs->set_min_clocks_state) + return false; + + disp_clk->funcs->set_min_clocks_state(disp_clk, clocks_state); + return true; +} + +uint32_t dal_display_clock_get_dp_ref_clk_frequency( + struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk); +} + +/*the second parameter of "switchreferenceclock" is + * a dummy argument for all pre dce 6.0 versions*/ + +void dal_display_clock_switch_reference_clock( + struct display_clock *disp_clk, + bool use_external_ref_clk, + uint32_t requested_clk_khz) +{ + /* TODO: requires Asic Control*/ + /* + struct ac_pixel_clk_params params; + struct asic_control *ac = + dal_adapter_service_get_asic_control(disp_clk->as); + dc_service_memset(¶ms, 0, sizeof(struct ac_pixel_clk_params)); + + params.tgt_pixel_clk_khz = requested_clk_khz; + params.flags.SET_EXTERNAL_REF_DIV_SRC = use_external_ref_clk; + params.pll_id = disp_clk->id; + dal_asic_control_program_display_engine_pll(ac, ¶ms); + */ +} + +void dal_display_clock_set_dp_ref_clock_source( + struct display_clock *disp_clk, + enum clock_source_id clk_src) +{ + disp_clk->funcs->set_dp_ref_clock_source(disp_clk, clk_src); +} + +void dal_display_clock_store_max_clocks_state( + struct display_clock *disp_clk, + enum clocks_state max_clocks_state) +{ + disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state); +} + +void dal_display_clock_set_clock_state( + struct display_clock *disp_clk, + struct display_clock_state clk_state) +{ + disp_clk->funcs->set_clock_state(disp_clk, clk_state); +} + +struct display_clock_state dal_display_clock_get_clock_state( + struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_clock_state(disp_clk); +} + +uint32_t dal_display_clock_get_dfs_bypass_threshold( + struct display_clock *disp_clk) +{ + return disp_clk->funcs->get_dfs_bypass_threshold(disp_clk); +} + +void dal_display_clock_invalid_clock_state( + struct display_clock *disp_clk) +{ + disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; +} + diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h new file mode 100644 index 000000000000..663580d18a09 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h @@ -0,0 +1,89 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DISPLAY_CLOCK_H__ +#define __DAL_DISPLAY_CLOCK_H__ + +#include "include/display_clock_interface.h" + +struct display_clock_funcs { + void (*destroy)(struct display_clock **to_destroy); + bool (*validate)(struct display_clock *disp_clk, + struct min_clock_params *params); + uint32_t (*calculate_min_clock)(struct display_clock *disp_clk, + uint32_t path_num, struct min_clock_params *params); + uint32_t (*get_validation_clock)(struct display_clock *disp_clk); + void (*set_clock)(struct display_clock *disp_clk, + uint32_t requested_clock_khz); + uint32_t (*get_clock)(struct display_clock *disp_clk); + enum clocks_state (*get_min_clocks_state)( + struct display_clock *disp_clk); + enum clocks_state (*get_required_clocks_state)( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks); + bool (*set_min_clocks_state)(struct display_clock *disp_clk, + enum clocks_state clocks_state); + uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); + void (*set_dp_ref_clock_source)(struct display_clock *disp_clk, + enum clock_source_id clk_src); + void (*store_max_clocks_state)(struct display_clock *disp_clk, + enum clocks_state max_clocks_state); + void (*set_clock_state)(struct display_clock *disp_clk, + struct display_clock_state clk_state); + struct display_clock_state (*get_clock_state)( + struct display_clock *disp_clk); + uint32_t (*get_dfs_bypass_threshold)(struct display_clock *disp_clk); + +}; + +struct display_clock { + struct dc_context *ctx; + const struct display_clock_funcs *funcs; + uint32_t min_display_clk_threshold_khz; + enum clock_source_id id; + + enum clocks_state cur_min_clks_state; +}; +void dal_display_clock_base_set_dp_ref_clock_source( + struct display_clock *disp_clk, + enum clock_source_id clk_src); +struct display_clock_state dal_display_clock_base_get_clock_state( + struct display_clock *disp_clk); +uint32_t dal_display_clock_base_get_dfs_bypass_threshold( + struct display_clock *disp_clk); +void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, + struct display_clock_state clk_state); +bool dal_display_clock_construct_base( + struct display_clock *base, + struct dc_context *ctx); + +uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); + +void dal_display_clock_store_max_clocks_state( + struct display_clock *disp_clk, + enum clocks_state max_clocks_state); + + +#endif /* __DAL_DISPLAY_CLOCK_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c new file mode 100644 index 000000000000..59d44004411b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c @@ -0,0 +1,127 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "divider_range.h" + +bool dal_divider_range_construct( + struct divider_range *div_range, + uint32_t range_start, + uint32_t range_step, + uint32_t did_min, + uint32_t did_max) +{ + div_range->div_range_start = range_start; + div_range->div_range_step = range_step; + div_range->did_min = did_min; + div_range->did_max = did_max; + + if (div_range->div_range_step == 0) { + div_range->div_range_step = 1; + /*div_range_step cannot be zero*/ + BREAK_TO_DEBUGGER(); + } + /* Calculate this based on the other inputs.*/ + /* See DividerRange.h for explanation of */ + /* the relationship between divider id (DID) and a divider.*/ + /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ + /* Maximum divider identified in this range = + * (Number of Divider IDs)*Step size between dividers + * + The start of this range.*/ + div_range->div_range_end = (did_max - did_min) * range_step + + range_start; + return true; +} + +static uint32_t dal_divider_range_calc_divider( + struct divider_range *div_range, + uint32_t did) +{ + /* Is this DID within our range?*/ + if ((did < div_range->did_min) || (did >= div_range->did_max)) + return INVALID_DIVIDER; + + return ((did - div_range->did_min) * div_range->div_range_step) + + div_range->div_range_start; + +} + +static uint32_t dal_divider_range_calc_did( + struct divider_range *div_range, + uint32_t div) +{ + uint32_t did; + /* Check before dividing.*/ + if (div_range->div_range_step == 0) { + div_range->div_range_step = 1; + /*div_range_step cannot be zero*/ + BREAK_TO_DEBUGGER(); + } + /* Is this divider within our range?*/ + if ((div < div_range->div_range_start) + || (div >= div_range->div_range_end)) + return INVALID_DID; +/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ + did = div - div_range->div_range_start; + did += div_range->div_range_step - 1; + did /= div_range->div_range_step; + did += div_range->did_min; + return did; +} + +uint32_t dal_divider_range_get_divider( + struct divider_range *div_range, + uint32_t ranges_num, + uint32_t did) +{ + uint32_t div = INVALID_DIVIDER; + uint32_t i; + + for (i = 0; i < ranges_num; i++) { + /* Calculate divider with given divider ID*/ + div = dal_divider_range_calc_divider(&div_range[i], did); + /* Found a valid return divider*/ + if (div != INVALID_DIVIDER) + break; + } + return div; +} +uint32_t dal_divider_range_get_did( + struct divider_range *div_range, + uint32_t ranges_num, + uint32_t divider) +{ + uint32_t did = INVALID_DID; + uint32_t i; + + for (i = 0; i < ranges_num; i++) { + /* CalcDid returns InvalidDid if a divider ID isn't found*/ + did = dal_divider_range_calc_did(&div_range[i], divider); + /* Found a valid return did*/ + if (did != INVALID_DID) + break; + } + return did; +} + diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h new file mode 100644 index 000000000000..e53522f652cc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h @@ -0,0 +1,62 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DIVIDER_RANGE_H__ +#define __DAL_DIVIDER_RANGE_H__ + +enum divider_error_types { + INVALID_DID = 0, + INVALID_DIVIDER = 1 +}; + +struct divider_range { + uint32_t div_range_start; + /* The end of this range of dividers.*/ + uint32_t div_range_end; + /* The distance between each divider in this range.*/ + uint32_t div_range_step; + /* The divider id for the lowest divider.*/ + uint32_t did_min; + /* The divider id for the highest divider.*/ + uint32_t did_max; +}; + +bool dal_divider_range_construct( + struct divider_range *div_range, + uint32_t range_start, + uint32_t range_step, + uint32_t did_min, + uint32_t did_max); + +uint32_t dal_divider_range_get_divider( + struct divider_range *div_range, + uint32_t ranges_num, + uint32_t did); +uint32_t dal_divider_range_get_did( + struct divider_range *div_range, + uint32_t ranges_num, + uint32_t divider); + +#endif /* __DAL_DIVIDER_RANGE_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile new file mode 100644 index 000000000000..83dfc437aae4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -0,0 +1,58 @@ +# +# Makefile for the 'i2c' sub-component of DAL. +# It provides the control and status of HW i2c engine of the adapter. + +I2CAUX = aux_engine.o engine_base.o i2caux.o i2c_engine.o \ + i2c_generic_hw_engine.o i2c_hw_engine.o i2c_sw_engine.o + +AMD_DAL_I2CAUX = $(addprefix $(AMDDALPATH)/dc/i2caux/,$(I2CAUX)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX) + +############################################################################### +# DCE 8x family +############################################################################### +I2CAUX_DCE80 = i2caux_dce80.o i2c_hw_engine_dce80.o \ + i2c_sw_engine_dce80.o + +AMD_DAL_I2CAUX_DCE80 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce80/,$(I2CAUX_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE80) + +############################################################################### +# DCE 100 family +############################################################################### +I2CAUX_DCE100 = i2caux_dce100.o + +AMD_DAL_I2CAUX_DCE100 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce100/,$(I2CAUX_DCE100)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE100) + +############################################################################### +# DCE 110 family +############################################################################### +I2CAUX_DCE110 = i2caux_dce110.o i2c_sw_engine_dce110.o i2c_hw_engine_dce110.o \ + aux_engine_dce110.o + +AMD_DAL_I2CAUX_DCE110 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce110/,$(I2CAUX_DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE110) + +############################################################################### +# DCE 112 family +############################################################################### +I2CAUX_DCE112 = i2caux_dce112.o + +AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE112)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) + +############################################################################### +# Diagnostics on FPGA +############################################################################### +I2CAUX_DIAG = i2caux_diag.o + +AMD_DAL_I2CAUX_DIAG = $(addprefix $(AMDDALPATH)/dc/i2caux/diagnostics/,$(I2CAUX_DIAG)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DIAG) + diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c new file mode 100644 index 000000000000..667660f3fa26 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c @@ -0,0 +1,567 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" + +/* + * Header of this unit + */ + +#include "aux_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "include/link_service_types.h" + +/* + * This unit + */ + +enum { + AUX_INVALID_REPLY_RETRY_COUNTER = 1, + AUX_TIMED_OUT_RETRY_COUNTER = 2, + AUX_DEFER_RETRY_COUNTER = 6 +}; + +#define FROM_ENGINE(ptr) \ + container_of((ptr), struct aux_engine, base) + +enum i2caux_engine_type dal_aux_engine_get_engine_type( + const struct engine *engine) +{ + return I2CAUX_ENGINE_TYPE_AUX; +} + +bool dal_aux_engine_acquire( + struct engine *engine, + struct ddc *ddc) +{ + struct aux_engine *aux_engine = FROM_ENGINE(engine); + + enum gpio_result result; + + result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, + GPIO_DDC_CONFIG_TYPE_MODE_AUX); + + if (result != GPIO_RESULT_OK) + return false; + + if (!aux_engine->funcs->acquire_engine(aux_engine)) { + dal_ddc_close(ddc); + return false; + } + + engine->ddc = ddc; + + return true; +} + +struct read_command_context { + uint8_t *buffer; + uint32_t current_read_length; + uint32_t offset; + enum i2caux_transaction_status status; + + struct aux_request_transaction_data request; + struct aux_reply_transaction_data reply; + + uint8_t returned_byte; + + uint32_t timed_out_retry_aux; + uint32_t invalid_reply_retry_aux; + uint32_t defer_retry_aux; + uint32_t defer_retry_i2c; + uint32_t invalid_reply_retry_aux_on_ack; + + bool transaction_complete; + bool operation_succeeded; +}; + +static void process_read_reply( + struct aux_engine *engine, + struct read_command_context *ctx) +{ + engine->funcs->process_channel_reply(engine, &ctx->reply); + + switch (ctx->reply.status) { + case AUX_TRANSACTION_REPLY_AUX_ACK: + ctx->defer_retry_aux = 0; + if (ctx->returned_byte > ctx->current_read_length) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } else if (ctx->returned_byte < ctx->current_read_length) { + ctx->current_read_length -= ctx->returned_byte; + + ctx->offset += ctx->returned_byte; + + ++ctx->invalid_reply_retry_aux_on_ack; + + if (ctx->invalid_reply_retry_aux_on_ack > + AUX_INVALID_REPLY_RETRY_COUNTER) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } + } else { + ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + ctx->transaction_complete = true; + ctx->operation_succeeded = true; + } + break; + case AUX_TRANSACTION_REPLY_AUX_NACK: + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + ctx->operation_succeeded = false; + break; + case AUX_TRANSACTION_REPLY_AUX_DEFER: + ++ctx->defer_retry_aux; + + if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } + break; + case AUX_TRANSACTION_REPLY_I2C_DEFER: + ctx->defer_retry_aux = 0; + + ++ctx->defer_retry_i2c; + + if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } + break; + default: + ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; + ctx->operation_succeeded = false; + } +} + +static void process_read_request( + struct aux_engine *engine, + struct read_command_context *ctx) +{ + enum aux_channel_operation_result operation_result; + + engine->funcs->submit_channel_request(engine, &ctx->request); + + operation_result = engine->funcs->get_channel_status( + engine, &ctx->returned_byte); + + switch (operation_result) { + case AUX_CHANNEL_OPERATION_SUCCEEDED: + if (ctx->returned_byte > ctx->current_read_length) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } else { + ctx->timed_out_retry_aux = 0; + ctx->invalid_reply_retry_aux = 0; + + ctx->reply.length = ctx->returned_byte; + ctx->reply.data = ctx->buffer; + + process_read_reply(engine, ctx); + } + break; + case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: + ++ctx->invalid_reply_retry_aux; + + if (ctx->invalid_reply_retry_aux > + AUX_INVALID_REPLY_RETRY_COUNTER) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } else + udelay(400); + break; + case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: + ++ctx->timed_out_retry_aux; + + if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } else { + /* DP 1.2a, table 2-58: + * "S3: AUX Request CMD PENDING: + * retry 3 times, with 400usec wait on each" + * The HW timeout is set to 550usec, + * so we should not wait here */ + } + break; + default: + ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; + ctx->operation_succeeded = false; + } +} + +static bool read_command( + struct aux_engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction) +{ + struct read_command_context ctx; + + ctx.buffer = request->payload.data; + ctx.current_read_length = request->payload.length; + ctx.offset = 0; + ctx.timed_out_retry_aux = 0; + ctx.invalid_reply_retry_aux = 0; + ctx.defer_retry_aux = 0; + ctx.defer_retry_i2c = 0; + ctx.invalid_reply_retry_aux_on_ack = 0; + ctx.transaction_complete = false; + ctx.operation_succeeded = true; + + if (request->payload.address_space == + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { + ctx.request.type = AUX_TRANSACTION_TYPE_DP; + ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ; + ctx.request.address = request->payload.address; + } else if (request->payload.address_space == + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { + ctx.request.type = AUX_TRANSACTION_TYPE_I2C; + ctx.request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_READ; + ctx.request.address = request->payload.address >> 1; + } else { + /* in DAL2, there was no return in such case */ + BREAK_TO_DEBUGGER(); + return false; + } + + ctx.request.delay = 0; + + do { + memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length); + + ctx.request.data = ctx.buffer + ctx.offset; + ctx.request.length = ctx.current_read_length; + + process_read_request(engine, &ctx); + + request->status = ctx.status; + + if (ctx.operation_succeeded && !ctx.transaction_complete) + if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) + msleep(engine->delay); + } while (ctx.operation_succeeded && !ctx.transaction_complete); + + return ctx.operation_succeeded; +} + +struct write_command_context { + bool mot; + + uint8_t *buffer; + uint32_t current_write_length; + enum i2caux_transaction_status status; + + struct aux_request_transaction_data request; + struct aux_reply_transaction_data reply; + + uint8_t returned_byte; + + uint32_t timed_out_retry_aux; + uint32_t invalid_reply_retry_aux; + uint32_t defer_retry_aux; + uint32_t defer_retry_i2c; + uint32_t max_defer_retry; + uint32_t ack_m_retry; + + uint8_t reply_data[DEFAULT_AUX_MAX_DATA_SIZE]; + + bool transaction_complete; + bool operation_succeeded; +}; + +static void process_write_reply( + struct aux_engine *engine, + struct write_command_context *ctx) +{ + engine->funcs->process_channel_reply(engine, &ctx->reply); + + switch (ctx->reply.status) { + case AUX_TRANSACTION_REPLY_AUX_ACK: + ctx->operation_succeeded = true; + + if (ctx->returned_byte) { + ctx->request.action = ctx->mot ? + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; + + ctx->current_write_length = 0; + + ++ctx->ack_m_retry; + + if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } else + udelay(300); + } else { + ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + ctx->defer_retry_aux = 0; + ctx->ack_m_retry = 0; + ctx->transaction_complete = true; + } + break; + case AUX_TRANSACTION_REPLY_AUX_NACK: + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + ctx->operation_succeeded = false; + break; + case AUX_TRANSACTION_REPLY_AUX_DEFER: + ++ctx->defer_retry_aux; + + if (ctx->defer_retry_aux > ctx->max_defer_retry) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } + break; + case AUX_TRANSACTION_REPLY_I2C_DEFER: + ctx->defer_retry_aux = 0; + ctx->current_write_length = 0; + + ctx->request.action = ctx->mot ? + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; + + ++ctx->defer_retry_i2c; + + if (ctx->defer_retry_i2c > ctx->max_defer_retry) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } + break; + default: + ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; + ctx->operation_succeeded = false; + } +} + +static void process_write_request( + struct aux_engine *engine, + struct write_command_context *ctx) +{ + enum aux_channel_operation_result operation_result; + + engine->funcs->submit_channel_request(engine, &ctx->request); + + operation_result = engine->funcs->get_channel_status( + engine, &ctx->returned_byte); + + switch (operation_result) { + case AUX_CHANNEL_OPERATION_SUCCEEDED: + ctx->timed_out_retry_aux = 0; + ctx->invalid_reply_retry_aux = 0; + + ctx->reply.length = ctx->returned_byte; + ctx->reply.data = ctx->reply_data; + + process_write_reply(engine, ctx); + break; + case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: + ++ctx->invalid_reply_retry_aux; + + if (ctx->invalid_reply_retry_aux > + AUX_INVALID_REPLY_RETRY_COUNTER) { + ctx->status = + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; + ctx->operation_succeeded = false; + } else + udelay(400); + break; + case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: + ++ctx->timed_out_retry_aux; + + if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { + ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + ctx->operation_succeeded = false; + } else { + /* DP 1.2a, table 2-58: + * "S3: AUX Request CMD PENDING: + * retry 3 times, with 400usec wait on each" + * The HW timeout is set to 550usec, + * so we should not wait here */ + } + break; + default: + ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; + ctx->operation_succeeded = false; + } +} + +static bool write_command( + struct aux_engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction) +{ + struct write_command_context ctx; + + ctx.mot = middle_of_transaction; + ctx.buffer = request->payload.data; + ctx.current_write_length = request->payload.length; + ctx.timed_out_retry_aux = 0; + ctx.invalid_reply_retry_aux = 0; + ctx.defer_retry_aux = 0; + ctx.defer_retry_i2c = 0; + ctx.ack_m_retry = 0; + ctx.transaction_complete = false; + ctx.operation_succeeded = true; + + if (request->payload.address_space == + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { + ctx.request.type = AUX_TRANSACTION_TYPE_DP; + ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE; + ctx.request.address = request->payload.address; + } else if (request->payload.address_space == + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { + ctx.request.type = AUX_TRANSACTION_TYPE_I2C; + ctx.request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + ctx.request.address = request->payload.address >> 1; + } else { + /* in DAL2, there was no return in such case */ + BREAK_TO_DEBUGGER(); + return false; + } + + ctx.request.delay = 0; + + ctx.max_defer_retry = + (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ? + engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER; + + do { + ctx.request.data = ctx.buffer; + ctx.request.length = ctx.current_write_length; + + process_write_request(engine, &ctx); + + request->status = ctx.status; + + if (ctx.operation_succeeded && !ctx.transaction_complete) + if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) + msleep(engine->delay); + } while (ctx.operation_succeeded && !ctx.transaction_complete); + + return ctx.operation_succeeded; +} + +static bool end_of_transaction_command( + struct aux_engine *engine, + struct i2caux_transaction_request *request) +{ + struct i2caux_transaction_request dummy_request; + uint8_t dummy_data; + + /* [tcheng] We only need to send the stop (read with MOT = 0) + * for I2C-over-Aux, not native AUX */ + + if (request->payload.address_space != + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) + return false; + + dummy_request.operation = request->operation; + dummy_request.payload.address_space = request->payload.address_space; + dummy_request.payload.address = request->payload.address; + + /* + * Add a dummy byte due to some receiver quirk + * where one byte is sent along with MOT = 0. + * Ideally this should be 0. + */ + + dummy_request.payload.length = 0; + dummy_request.payload.data = &dummy_data; + + if (request->operation == I2CAUX_TRANSACTION_READ) + return read_command(engine, &dummy_request, false); + else + return write_command(engine, &dummy_request, false); + + /* according Syed, it does not need now DoDummyMOT */ +} + +bool dal_aux_engine_submit_request( + struct engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction) +{ + struct aux_engine *aux_engine = FROM_ENGINE(engine); + + bool result; + bool mot_used = true; + + switch (request->operation) { + case I2CAUX_TRANSACTION_READ: + result = read_command(aux_engine, request, mot_used); + break; + case I2CAUX_TRANSACTION_WRITE: + result = write_command(aux_engine, request, mot_used); + break; + default: + result = false; + } + + /* [tcheng] + * need to send stop for the last transaction to free up the AUX + * if the above command fails, this would be the last transaction */ + + if (!middle_of_transaction || !result) + end_of_transaction_command(aux_engine, request); + + /* mask AUX interrupt */ + + return result; +} + +bool dal_aux_engine_construct( + struct aux_engine *engine, + struct dc_context *ctx) +{ + if (!dal_i2caux_construct_engine(&engine->base, ctx)) + return false; + engine->delay = 0; + engine->max_defer_write_retry = 0; + return true; +} + +void dal_aux_engine_destruct( + struct aux_engine *engine) +{ + dal_i2caux_destruct_engine(&engine->base); +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h new file mode 100644 index 000000000000..b5d6c79eb029 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h @@ -0,0 +1,117 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_AUX_ENGINE_H__ +#define __DAL_AUX_ENGINE_H__ + +enum aux_transaction_type { + AUX_TRANSACTION_TYPE_DP, + AUX_TRANSACTION_TYPE_I2C +}; + +struct aux_request_transaction_data { + enum aux_transaction_type type; + enum i2caux_transaction_action action; + /* 20-bit AUX channel transaction address */ + uint32_t address; + /* delay, in 100-microsecond units */ + uint8_t delay; + uint32_t length; + uint8_t *data; +}; + +enum aux_transaction_reply { + AUX_TRANSACTION_REPLY_AUX_ACK = 0x00, + AUX_TRANSACTION_REPLY_AUX_NACK = 0x01, + AUX_TRANSACTION_REPLY_AUX_DEFER = 0x02, + + AUX_TRANSACTION_REPLY_I2C_ACK = 0x00, + AUX_TRANSACTION_REPLY_I2C_NACK = 0x10, + AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20, + + AUX_TRANSACTION_REPLY_INVALID = 0xFF +}; + +struct aux_reply_transaction_data { + enum aux_transaction_reply status; + uint32_t length; + uint8_t *data; +}; + +enum aux_channel_operation_result { + AUX_CHANNEL_OPERATION_SUCCEEDED, + AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN, + AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY, + AUX_CHANNEL_OPERATION_FAILED_TIMEOUT +}; + +struct aux_engine; + +struct aux_engine_funcs { + void (*destroy)( + struct aux_engine **ptr); + bool (*acquire_engine)( + struct aux_engine *engine); + void (*configure)( + struct aux_engine *engine, + union aux_config cfg); + void (*submit_channel_request)( + struct aux_engine *engine, + struct aux_request_transaction_data *request); + void (*process_channel_reply)( + struct aux_engine *engine, + struct aux_reply_transaction_data *reply); + enum aux_channel_operation_result (*get_channel_status)( + struct aux_engine *engine, + uint8_t *returned_bytes); +}; + +struct aux_engine { + struct engine base; + const struct aux_engine_funcs *funcs; + /* following values are expressed in milliseconds */ + uint32_t delay; + uint32_t max_defer_write_retry; + + bool acquire_reset; +}; + +bool dal_aux_engine_construct( + struct aux_engine *engine, + struct dc_context *ctx); + +void dal_aux_engine_destruct( + struct aux_engine *engine); +bool dal_aux_engine_submit_request( + struct engine *ptr, + struct i2caux_transaction_request *request, + bool middle_of_transaction); +bool dal_aux_engine_acquire( + struct engine *ptr, + struct ddc *ddc); +enum i2caux_engine_type dal_aux_engine_get_engine_type( + const struct engine *engine); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c new file mode 100644 index 000000000000..0712cafb4c42 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c @@ -0,0 +1,112 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +#include "../dce110/aux_engine_dce110.h" +#include "../dce110/i2c_hw_engine_dce110.h" +#include "../dce110/i2caux_dce110.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_aux_registers dce100_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5), +}; + +static const struct dce110_i2c_hw_engine_registers dce100_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE100(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE100(_MASK) +}; + +struct i2caux *dal_i2caux_dce100_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dce100_aux_regs, + dce100_hw_engine_regs, + &i2c_shift, + &i2c_mask)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h new file mode 100644 index 000000000000..2b508d3e0ef4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE100_H__ +#define __DAL_I2C_AUX_DCE100_H__ + +struct i2caux *dal_i2caux_dce100_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c new file mode 100644 index 000000000000..f49fd1ad3807 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -0,0 +1,456 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../aux_engine.h" + +/* + * Header of this unit + */ + +#include "aux_engine_dce110.h" + +/* + * Post-requisites: headers required by this unit + */ +#include "dce/dce_11_0_sh_mask.h" + +#define CTX \ + aux110->base.base.ctx +#define REG(reg_name)\ + (aux110->regs->reg_name) +#include "reg_helper.h" + +/* + * This unit + */ + +/* + * @brief + * Cast 'struct aux_engine *' + * to 'struct aux_engine_dce110 *' + */ +#define FROM_AUX_ENGINE(ptr) \ + container_of((ptr), struct aux_engine_dce110, base) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct aux_engine_dce110 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base)) + +static void release_engine( + struct engine *engine) +{ + struct aux_engine_dce110 *aux110 = FROM_ENGINE(engine); + + REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); +} + +static void destruct( + struct aux_engine_dce110 *engine); + +static void destroy( + struct aux_engine **aux_engine) +{ + struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine); + + destruct(engine); + + dm_free(engine); + + *aux_engine = NULL; +} + +#define SW_CAN_ACCESS_AUX 1 + +static bool acquire_engine( + struct aux_engine *engine) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + + /* enable AUX before request SW to access AUX */ + uint32_t value = REG_READ(AUX_CONTROL); + uint32_t field = get_reg_field_value(value, + AUX_CONTROL, + AUX_EN); + + if (field == 0) { + set_reg_field_value( + value, + 1, + AUX_CONTROL, + AUX_EN); + + if (REG(AUX_RESET_MASK)) { + /*DP_AUX block as part of the enable sequence*/ + set_reg_field_value( + value, + 1, + AUX_CONTROL, + AUX_RESET); + } + + REG_WRITE(AUX_CONTROL, value); + + if (REG(AUX_RESET_MASK)) { + /*poll HW to make sure reset it done*/ + + REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, + 1, 11); + + set_reg_field_value( + value, + 0, + AUX_CONTROL, + AUX_RESET); + + REG_WRITE(AUX_CONTROL, value); + + REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, + 1, 11); + } + } /*if (field)*/ + + /* request SW to access AUX */ + REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); + + value = REG_READ(AUX_ARB_CONTROL); + field = get_reg_field_value( + value, + AUX_ARB_CONTROL, + AUX_REG_RW_CNTL_STATUS); + + return (field == SW_CAN_ACCESS_AUX); +} + +#define COMPOSE_AUX_SW_DATA_16_20(command, address) \ + ((command) | ((0xF0000 & (address)) >> 16)) + +#define COMPOSE_AUX_SW_DATA_8_15(address) \ + ((0xFF00 & (address)) >> 8) + +#define COMPOSE_AUX_SW_DATA_0_7(address) \ + (0xFF & (address)) + +static void submit_channel_request( + struct aux_engine *engine, + struct aux_request_transaction_data *request) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + uint32_t value; + uint32_t length; + + bool is_write = + ((request->type == AUX_TRANSACTION_TYPE_DP) && + (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || + ((request->type == AUX_TRANSACTION_TYPE_I2C) && + ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || + (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); + + /* clear_aux_error */ + REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, + 1, + 0); + + REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, + 1, + 0); + + /* force_default_calibrate */ + REG_UPDATE_1BY1_2(AUXN_IMPCAL, + AUXN_IMPCAL_ENABLE, 1, + AUXN_IMPCAL_OVERRIDE_ENABLE, 0); + + /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ + + REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, + 1, + 0); + + /* set the delay and the number of bytes to write */ + + /* The length include + * the 4 bit header and the 20 bit address + * (that is 3 byte). + * If the requested length is non zero this means + * an addition byte specifying the length is required. */ + + length = request->length ? 4 : 3; + if (is_write) + length += request->length; + + REG_UPDATE_2(AUX_SW_CONTROL, + AUX_SW_START_DELAY, request->delay, + AUX_SW_WR_BYTES, length); + + /* program action and address and payload data (if 'is_write') */ + value = REG_UPDATE_4(AUX_SW_DATA, + AUX_SW_INDEX, 0, + AUX_SW_DATA_RW, 0, + AUX_SW_AUTOINCREMENT_DISABLE, 1, + AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); + + value = REG_SET_2(AUX_SW_DATA, value, + AUX_SW_AUTOINCREMENT_DISABLE, 0, + AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); + + value = REG_SET(AUX_SW_DATA, value, + AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); + + if (request->length) { + value = REG_SET(AUX_SW_DATA, value, + AUX_SW_DATA, request->length - 1); + } + + if (is_write) { + /* Load the HW buffer with the Data to be sent. + * This is relevant for write operation. + * For read, the data recived data will be + * processed in process_channel_reply(). */ + uint32_t i = 0; + + while (i < request->length) { + value = REG_SET(AUX_SW_DATA, value, + AUX_SW_DATA, request->data[i]); + + ++i; + } + } + + REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); + REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, + 10, aux110->timeout_period/10); + REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); +} + +static void process_channel_reply( + struct aux_engine *engine, + struct aux_reply_transaction_data *reply) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + + /* Need to do a read to get the number of bytes to process + * Alternatively, this information can be passed - + * but that causes coupling which isn't good either. */ + + uint32_t bytes_replied; + uint32_t value; + + value = REG_GET(AUX_SW_STATUS, + AUX_SW_REPLY_BYTE_COUNT, &bytes_replied); + + if (bytes_replied) { + uint32_t reply_result; + + REG_UPDATE_1BY1_3(AUX_SW_DATA, + AUX_SW_INDEX, 0, + AUX_SW_AUTOINCREMENT_DISABLE, 1, + AUX_SW_DATA_RW, 1); + + REG_GET(AUX_SW_DATA, + AUX_SW_DATA, &reply_result); + + reply_result = reply_result >> 4; + + switch (reply_result) { + case 0: /* ACK */ { + uint32_t i = 0; + + /* first byte was already used + * to get the command status */ + --bytes_replied; + + while (i < bytes_replied) { + uint32_t aux_sw_data_val; + + REG_GET(AUX_SW_DATA, + AUX_SW_DATA, &aux_sw_data_val); + + reply->data[i] = aux_sw_data_val; + ++i; + } + + reply->status = AUX_TRANSACTION_REPLY_AUX_ACK; + } + break; + case 1: /* NACK */ + reply->status = AUX_TRANSACTION_REPLY_AUX_NACK; + break; + case 2: /* DEFER */ + reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER; + break; + case 4: /* AUX ACK / I2C NACK */ + reply->status = AUX_TRANSACTION_REPLY_I2C_NACK; + break; + case 8: /* AUX ACK / I2C DEFER */ + reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER; + break; + default: + reply->status = AUX_TRANSACTION_REPLY_INVALID; + } + } else { + /* Need to handle an error case... + * hopefully, upper layer function won't call this function + * if the number of bytes in the reply was 0 + * because there was surely an error that was asserted + * that should have been handled + * for hot plug case, this could happens*/ + if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) + ASSERT_CRITICAL(false); + } +} + +static enum aux_channel_operation_result get_channel_status( + struct aux_engine *engine, + uint8_t *returned_bytes) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + + uint32_t value; + + if (returned_bytes == NULL) { + /*caller pass NULL pointer*/ + ASSERT_CRITICAL(false); + return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN; + } + *returned_bytes = 0; + + /* poll to make sure that SW_DONE is asserted */ + value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, + 10, aux110->timeout_period/10); + + /* Note that the following bits are set in 'status.bits' + * during CTS 4.2.1.2: + * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, + * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. + * + * AUX_SW_RX_MIN_COUNT_VIOL is an internal, + * HW debugging bit and should be ignored. */ + if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { + if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || + (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) + return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; + + else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || + (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || + (value & + AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || + (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) + return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; + + *returned_bytes = get_reg_field_value(value, + AUX_SW_STATUS, + AUX_SW_REPLY_BYTE_COUNT); + + if (*returned_bytes == 0) + return + AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; + else { + *returned_bytes -= 1; + return AUX_CHANNEL_OPERATION_SUCCEEDED; + } + } else { + /*time_elapsed >= aux_engine->timeout_period */ + if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) + ASSERT_CRITICAL(false); + + return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; + } +} + +static const struct aux_engine_funcs aux_engine_funcs = { + .destroy = destroy, + .acquire_engine = acquire_engine, + .submit_channel_request = submit_channel_request, + .process_channel_reply = process_channel_reply, + .get_channel_status = get_channel_status, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .submit_request = dal_aux_engine_submit_request, + .get_engine_type = dal_aux_engine_get_engine_type, + .acquire = dal_aux_engine_acquire, +}; + +static bool construct( + struct aux_engine_dce110 *engine, + const struct aux_engine_dce110_init_data *aux_init_data) +{ + if (!dal_aux_engine_construct( + &engine->base, aux_init_data->ctx)) { + ASSERT_CRITICAL(false); + return false; + } + engine->base.base.funcs = &engine_funcs; + engine->base.funcs = &aux_engine_funcs; + + engine->timeout_period = aux_init_data->timeout_period; + engine->regs = aux_init_data->regs; + + return true; +} + +static void destruct( + struct aux_engine_dce110 *engine) +{ + dal_aux_engine_destruct(&engine->base); +} + +struct aux_engine *dal_aux_engine_dce110_create( + const struct aux_engine_dce110_init_data *aux_init_data) +{ + struct aux_engine_dce110 *engine; + + if (!aux_init_data) { + ASSERT_CRITICAL(false); + return NULL; + } + + engine = dm_alloc(sizeof(*engine)); + + if (!engine) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(engine, aux_init_data)) + return &engine->base; + + ASSERT_CRITICAL(false); + + dm_free(engine); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h new file mode 100644 index 000000000000..85ee82162590 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.h @@ -0,0 +1,78 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_AUX_ENGINE_DCE110_H__ +#define __DAL_AUX_ENGINE_DCE110_H__ + +#include "../aux_engine.h" + +#define AUX_COMMON_REG_LIST(id)\ + SRI(AUX_CONTROL, DP_AUX, id), \ + SRI(AUX_ARB_CONTROL, DP_AUX, id), \ + SRI(AUX_SW_DATA, DP_AUX, id), \ + SRI(AUX_SW_CONTROL, DP_AUX, id), \ + SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ + SRI(AUX_SW_STATUS, DP_AUX, id), \ + SR(AUXN_IMPCAL), \ + SR(AUXP_IMPCAL) + +struct dce110_aux_registers { + uint32_t AUX_CONTROL; + uint32_t AUX_ARB_CONTROL; + uint32_t AUX_SW_DATA; + uint32_t AUX_SW_CONTROL; + uint32_t AUX_INTERRUPT_CONTROL; + uint32_t AUX_SW_STATUS; + uint32_t AUXN_IMPCAL; + uint32_t AUXP_IMPCAL; + + uint32_t AUX_RESET_MASK; +}; + +struct aux_engine_dce110 { + struct aux_engine base; + const struct dce110_aux_registers *regs; + struct { + uint32_t aux_control; + uint32_t aux_arb_control; + uint32_t aux_sw_data; + uint32_t aux_sw_control; + uint32_t aux_interrupt_control; + uint32_t aux_sw_status; + } addr; + uint32_t timeout_period; +}; + +struct aux_engine_dce110_init_data { + uint32_t engine_id; + uint32_t timeout_period; + struct dc_context *ctx; + const struct dce110_aux_registers *regs; +}; + +struct aux_engine *dal_aux_engine_dce110_create( + const struct aux_engine_dce110_init_data *aux_init_data); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c new file mode 100644 index 000000000000..80d06ad78e07 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c @@ -0,0 +1,577 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_hw_engine.h" +#include "../i2c_generic_hw_engine.h" +/* + * Header of this unit + */ + +#include "i2c_hw_engine_dce110.h" + +/* + * Post-requisites: headers required by this unit + */ +#include "reg_helper.h" + +/* + * This unit + */ + +enum dc_i2c_status { + DC_I2C_STATUS__DC_I2C_STATUS_IDLE, + DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW, + DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW +}; + +enum dc_i2c_arbitration { + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH +}; + +enum { + /* No timeout in HW + * (timeout implemented in SW by querying status) */ + I2C_SETUP_TIME_LIMIT = 255, + I2C_HW_BUFFER_SIZE = 538 +}; + +/* + * @brief + * Cast pointer to 'struct i2c_hw_engine *' + * to pointer 'struct i2c_hw_engine_dce110 *' + */ +#define FROM_I2C_HW_ENGINE(ptr) \ + container_of((ptr), struct i2c_hw_engine_dce110, base) +/* + * @brief + * Cast pointer to 'struct i2c_engine *' + * to pointer to 'struct i2c_hw_engine_dce110 *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) + +/* + * @brief + * Cast pointer to 'struct engine *' + * to 'pointer to struct i2c_hw_engine_dce110 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +#define CTX \ + hw_engine->base.base.base.ctx + +#define REG(reg_name)\ + (hw_engine->regs->reg_name) + +#undef FN +#define FN(reg_name, field_name) \ + hw_engine->i2c_shift->field_name, hw_engine->i2c_mask->field_name + +#include "reg_helper.h" + +static void disable_i2c_hw_engine( + struct i2c_hw_engine_dce110 *hw_engine) +{ + REG_UPDATE_N(SETUP, 1, FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 0); +} + +static void release_engine( + struct engine *engine) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); + + struct i2c_engine *base = NULL; + bool safe_to_reset; + + base = &hw_engine->base.base; + + /* Restore original HW engine speed */ + + base->funcs->set_speed(base, hw_engine->base.original_speed); + + /* Release I2C */ + REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1); + + /* Reset HW engine */ + { + uint32_t i2c_sw_status = 0; + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + /* if used by SW, safe to reset */ + safe_to_reset = (i2c_sw_status == 1); + } + + if (safe_to_reset) + REG_UPDATE_2( + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET, 1, + DC_I2C_SW_STATUS_RESET, 1); + else + REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1); + + /* HW I2c engine - clock gating feature */ + if (!hw_engine->engine_keep_power_up_count) + disable_i2c_hw_engine(hw_engine); +} + +static bool setup_engine( + struct i2c_engine *i2c_engine) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); + + /* Program pin select */ + REG_UPDATE_6( + DC_I2C_CONTROL, + DC_I2C_GO, 0, + DC_I2C_SOFT_RESET, 0, + DC_I2C_SEND_RESET, 0, + DC_I2C_SW_STATUS_RESET, 1, + DC_I2C_TRANSACTION_COUNT, 0, + DC_I2C_DDC_SELECT, hw_engine->engine_id); + + /* Program time limit */ + REG_UPDATE_N( + SETUP, 2, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), I2C_SETUP_TIME_LIMIT, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1); + + /* Program HW priority + * set to High - interrupt software I2C at any time + * Enable restart of SW I2C that was interrupted by HW + * disable queuing of software while I2C is in use by HW */ + REG_UPDATE_2( + DC_I2C_ARBITRATION, + DC_I2C_NO_QUEUED_SW_GO, 0, + DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL); + + return true; +} + +static uint32_t get_speed( + const struct i2c_engine *i2c_engine) +{ + const struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); + uint32_t pre_scale = 0; + + REG_GET(SPEED, DC_I2C_DDC1_PRESCALE, &pre_scale); + + /* [anaumov] it seems following is unnecessary */ + /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/ + return pre_scale ? + hw_engine->reference_frequency / pre_scale : + hw_engine->base.default_speed; +} + +static void set_speed( + struct i2c_engine *i2c_engine, + uint32_t speed) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); + + if (speed) { + if (hw_engine->i2c_mask->DC_I2C_DDC1_START_STOP_TIMING_CNTL) + REG_UPDATE_N( + SPEED, 3, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1); + else + REG_UPDATE_N( + SPEED, 2, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed, + FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2); + } +} + +static inline void reset_hw_engine(struct engine *engine) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); + + REG_UPDATE_2( + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET, 1, + DC_I2C_SW_STATUS_RESET, 1); +} + +static bool is_hw_busy(struct engine *engine) +{ + struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine); + uint32_t i2c_sw_status = 0; + + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE) + return false; + + reset_hw_engine(engine); + + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE; +} + + +#define STOP_TRANS_PREDICAT \ + ((hw_engine->transaction_count == 3) || \ + (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || \ + (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) + +#define SET_I2C_TRANSACTION(id) \ + do { \ + REG_UPDATE_N(DC_I2C_TRANSACTION##id, 5, \ + FN(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0), 1, \ + FN(DC_I2C_TRANSACTION0, DC_I2C_START0), 1, \ + FN(DC_I2C_TRANSACTION0, DC_I2C_STOP0), STOP_TRANS_PREDICAT ? 1:0, \ + FN(DC_I2C_TRANSACTION0, DC_I2C_RW0), (0 != (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)), \ + FN(DC_I2C_TRANSACTION0, DC_I2C_COUNT0), length); \ + if (STOP_TRANS_PREDICAT) \ + last_transaction = true; \ + } while (false) + + +static bool process_transaction( + struct i2c_hw_engine_dce110 *hw_engine, + struct i2c_request_transaction_data *request) +{ + uint32_t length = request->length; + uint8_t *buffer = request->data; + uint32_t value = 0; + + bool last_transaction = false; + + struct dc_context *ctx = NULL; + + ctx = hw_engine->base.base.base.ctx; + + + + switch (hw_engine->transaction_count) { + case 0: + SET_I2C_TRANSACTION(0); + break; + case 1: + SET_I2C_TRANSACTION(1); + break; + case 2: + SET_I2C_TRANSACTION(2); + break; + case 3: + SET_I2C_TRANSACTION(3); + break; + default: + /* TODO Warning ? */ + break; + } + + + /* Write the I2C address and I2C data + * into the hardware circular buffer, one byte per entry. + * As an example, the 7-bit I2C slave address for CRT monitor + * for reading DDC/EDID information is 0b1010001. + * For an I2C send operation, the LSB must be programmed to 0; + * for I2C receive operation, the LSB must be programmed to 1. */ + if (hw_engine->transaction_count == 0) { + value = REG_SET_4(DC_I2C_DATA, 0, + DC_I2C_DATA_RW, false, + DC_I2C_DATA, request->address, + DC_I2C_INDEX, 0, + DC_I2C_INDEX_WRITE, 1); + hw_engine->buffer_used_write = 0; + } else + value = REG_SET_2(DC_I2C_DATA, 0, + DC_I2C_DATA_RW, false, + DC_I2C_DATA, request->address); + + hw_engine->buffer_used_write++; + + if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { + while (length) { + REG_SET_2(DC_I2C_DATA, value, + DC_I2C_INDEX_WRITE, 0, + DC_I2C_DATA, *buffer++); + hw_engine->buffer_used_write++; + --length; + } + } + + ++hw_engine->transaction_count; + hw_engine->buffer_used_bytes += length + 1; + + return last_transaction; +} + +static void execute_transaction( + struct i2c_hw_engine_dce110 *hw_engine) +{ + REG_UPDATE_N(SETUP, 5, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0, + FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0); + + + REG_UPDATE_5(DC_I2C_CONTROL, + DC_I2C_SOFT_RESET, 0, + DC_I2C_SW_STATUS_RESET, 0, + DC_I2C_SEND_RESET, 0, + DC_I2C_GO, 0, + DC_I2C_TRANSACTION_COUNT, hw_engine->transaction_count - 1); + + /* start I2C transfer */ + REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1); + + /* all transactions were executed and HW buffer became empty + * (even though it actually happens when status becomes DONE) */ + hw_engine->transaction_count = 0; + hw_engine->buffer_used_bytes = 0; +} + +static void submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request) +{ + request->status = I2C_CHANNEL_OPERATION_SUCCEEDED; + + if (!process_transaction(FROM_I2C_ENGINE(engine), request)) + return; + + if (is_hw_busy(&engine->base)) { + request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; + return; + } + + execute_transaction(FROM_I2C_ENGINE(engine)); +} + +static void process_channel_reply( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply) +{ + uint32_t length = reply->length; + uint8_t *buffer = reply->data; + + struct i2c_hw_engine_dce110 *hw_engine = + FROM_I2C_ENGINE(engine); + + + REG_SET_3(DC_I2C_DATA, 0, + DC_I2C_INDEX, hw_engine->buffer_used_write, + DC_I2C_DATA_RW, 1, + DC_I2C_INDEX_WRITE, 1); + + while (length) { + /* after reading the status, + * if the I2C operation executed successfully + * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller + * should read data bytes from I2C circular data buffer */ + + uint32_t i2c_data; + + REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data); + *buffer++ = i2c_data; + + --length; + } +} + +static enum i2c_channel_operation_result get_channel_status( + struct i2c_engine *i2c_engine, + uint8_t *returned_bytes) +{ + uint32_t i2c_sw_status = 0; + struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine); + uint32_t value = + REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status); + + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW) + return I2C_CHANNEL_OPERATION_ENGINE_BUSY; + else if (value & hw_engine->i2c_mask->DC_I2C_SW_STOPPED_ON_NACK) + return I2C_CHANNEL_OPERATION_NO_RESPONSE; + else if (value & hw_engine->i2c_mask->DC_I2C_SW_TIMEOUT) + return I2C_CHANNEL_OPERATION_TIMEOUT; + else if (value & hw_engine->i2c_mask->DC_I2C_SW_ABORTED) + return I2C_CHANNEL_OPERATION_FAILED; + else if (value & hw_engine->i2c_mask->DC_I2C_SW_DONE) + return I2C_CHANNEL_OPERATION_SUCCEEDED; + + /* + * this is the case when HW used for communication, I2C_SW_STATUS + * could be zero + */ + return I2C_CHANNEL_OPERATION_SUCCEEDED; +} + +static uint32_t get_hw_buffer_available_size( + const struct i2c_hw_engine *engine) +{ + return I2C_HW_BUFFER_SIZE - + FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes; +} + +static uint32_t get_transaction_timeout( + const struct i2c_hw_engine *engine, + uint32_t length) +{ + uint32_t speed = engine->base.funcs->get_speed(&engine->base); + + uint32_t period_timeout; + uint32_t num_of_clock_stretches; + + if (!speed) + return 0; + + period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed; + + num_of_clock_stretches = 1 + (length << 3) + 1; + num_of_clock_stretches += + (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) + + (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1); + + return period_timeout * num_of_clock_stretches; +} + +static void destroy( + struct i2c_engine **i2c_engine) +{ + struct i2c_hw_engine_dce110 *engine_dce110 = + FROM_I2C_ENGINE(*i2c_engine); + + dal_i2c_hw_engine_destruct(&engine_dce110->base); + + dm_free(engine_dce110); + + *i2c_engine = NULL; +} + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .destroy = destroy, + .get_speed = get_speed, + .set_speed = set_speed, + .setup_engine = setup_engine, + .submit_channel_request = submit_channel_request, + .process_channel_reply = process_channel_reply, + .get_channel_status = get_channel_status, + .acquire_engine = dal_i2c_hw_engine_acquire_engine, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_hw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_hw_engine_submit_request, +}; + +static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { + .get_hw_buffer_available_size = get_hw_buffer_available_size, + .get_transaction_timeout = get_transaction_timeout, + .wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result, +}; + +bool i2c_hw_engine_dce110_construct( + struct i2c_hw_engine_dce110 *hw_engine, + const struct i2c_hw_engine_dce110_create_arg *arg) +{ + uint32_t xtal_ref_div = 0; + + if (!arg->reference_frequency) + return false; + + if (!dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx)) + return false; + + hw_engine->base.base.base.funcs = &engine_funcs; + hw_engine->base.base.funcs = &i2c_engine_funcs; + hw_engine->base.funcs = &i2c_hw_engine_funcs; + hw_engine->base.default_speed = arg->default_speed; + + hw_engine->regs = arg->regs; + hw_engine->i2c_shift = arg->i2c_shift; + hw_engine->i2c_mask = arg->i2c_mask; + + hw_engine->engine_id = arg->engine_id; + + hw_engine->buffer_used_bytes = 0; + hw_engine->transaction_count = 0; + hw_engine->engine_keep_power_up_count = 1; + + + REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div); + + if (xtal_ref_div == 0) { + dm_logger_write( + hw_engine->base.base.base.ctx->logger, LOG_WARNING, + "Invalid base timer divider\n", + __func__); + xtal_ref_div = 2; + } + + /*Calculating Reference Clock by divding original frequency by + * XTAL_REF_DIV. + * At upper level, uint32_t reference_frequency = + * dal_i2caux_get_reference_clock(as) >> 1 + * which already divided by 2. So we need x2 to get original + * reference clock from ppll_info + */ + hw_engine->reference_frequency = + (arg->reference_frequency * 2) / xtal_ref_div; + + return true; +} + +struct i2c_engine *dal_i2c_hw_engine_dce110_create( + const struct i2c_hw_engine_dce110_create_arg *arg) +{ + struct i2c_hw_engine_dce110 *engine_dce10; + + if (!arg) { + ASSERT_CRITICAL(false); + return NULL; + } + + engine_dce10 = dm_alloc(sizeof(struct i2c_hw_engine_dce110)); + + if (!engine_dce10) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (i2c_hw_engine_dce110_construct(engine_dce10, arg)) + return &engine_dce10->base.base; + + ASSERT_CRITICAL(false); + + dm_free(engine_dce10); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h new file mode 100644 index 000000000000..c573c6459ec6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h @@ -0,0 +1,214 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_HW_ENGINE_DCE110_H__ +#define __DAL_I2C_HW_ENGINE_DCE110_H__ + +#define I2C_HW_ENGINE_COMMON_REG_LIST(id)\ + SRI(SETUP, DC_I2C_DDC, id),\ + SRI(SPEED, DC_I2C_DDC, id),\ + SR(DC_I2C_ARBITRATION),\ + SR(DC_I2C_CONTROL),\ + SR(DC_I2C_SW_STATUS),\ + SR(DC_I2C_TRANSACTION0),\ + SR(DC_I2C_TRANSACTION1),\ + SR(DC_I2C_TRANSACTION2),\ + SR(DC_I2C_TRANSACTION3),\ + SR(DC_I2C_DATA),\ + SR(MICROSECOND_TIME_BASE_DIV) + +#define I2C_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY, mask_sh),\ + I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, mask_sh),\ + I2C_SF(DC_I2C_ARBITRATION, DC_I2C_NO_QUEUED_SW_GO, mask_sh),\ + I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_PRIORITY, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_SOFT_RESET, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_GO, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_SEND_RESET, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_TRANSACTION_COUNT, mask_sh),\ + I2C_SF(DC_I2C_CONTROL, DC_I2C_DDC_SELECT, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE, mask_sh),\ + I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STOPPED_ON_NACK, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_TIMEOUT, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_ABORTED, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_DONE, mask_sh),\ + I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_START0, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_RW0, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP0, mask_sh),\ + I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_COUNT0, mask_sh),\ + I2C_SF(DC_I2C_DATA, DC_I2C_DATA_RW, mask_sh),\ + I2C_SF(DC_I2C_DATA, DC_I2C_DATA, mask_sh),\ + I2C_SF(DC_I2C_DATA, DC_I2C_INDEX, mask_sh),\ + I2C_SF(DC_I2C_DATA, DC_I2C_INDEX_WRITE, mask_sh),\ + I2C_SF(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, mask_sh) + +#define I2C_COMMON_MASK_SH_LIST_DCE100(mask_sh)\ + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) + +#define I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh)\ + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL, mask_sh) + +struct dce110_i2c_hw_engine_shift { + uint8_t DC_I2C_DDC1_ENABLE; + uint8_t DC_I2C_DDC1_TIME_LIMIT; + uint8_t DC_I2C_DDC1_DATA_DRIVE_EN; + uint8_t DC_I2C_DDC1_CLK_DRIVE_EN; + uint8_t DC_I2C_DDC1_DATA_DRIVE_SEL; + uint8_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY; + uint8_t DC_I2C_DDC1_INTRA_BYTE_DELAY; + uint8_t DC_I2C_SW_DONE_USING_I2C_REG; + uint8_t DC_I2C_NO_QUEUED_SW_GO; + uint8_t DC_I2C_SW_PRIORITY; + uint8_t DC_I2C_SOFT_RESET; + uint8_t DC_I2C_SW_STATUS_RESET; + uint8_t DC_I2C_GO; + uint8_t DC_I2C_SEND_RESET; + uint8_t DC_I2C_TRANSACTION_COUNT; + uint8_t DC_I2C_DDC_SELECT; + uint8_t DC_I2C_DDC1_PRESCALE; + uint8_t DC_I2C_DDC1_THRESHOLD; + uint8_t DC_I2C_DDC1_START_STOP_TIMING_CNTL; + uint8_t DC_I2C_SW_STOPPED_ON_NACK; + uint8_t DC_I2C_SW_TIMEOUT; + uint8_t DC_I2C_SW_ABORTED; + uint8_t DC_I2C_SW_DONE; + uint8_t DC_I2C_SW_STATUS; + uint8_t DC_I2C_STOP_ON_NACK0; + uint8_t DC_I2C_START0; + uint8_t DC_I2C_RW0; + uint8_t DC_I2C_STOP0; + uint8_t DC_I2C_COUNT0; + uint8_t DC_I2C_DATA_RW; + uint8_t DC_I2C_DATA; + uint8_t DC_I2C_INDEX; + uint8_t DC_I2C_INDEX_WRITE; + uint8_t XTAL_REF_DIV; +}; + +struct dce110_i2c_hw_engine_mask { + uint32_t DC_I2C_DDC1_ENABLE; + uint32_t DC_I2C_DDC1_TIME_LIMIT; + uint32_t DC_I2C_DDC1_DATA_DRIVE_EN; + uint32_t DC_I2C_DDC1_CLK_DRIVE_EN; + uint32_t DC_I2C_DDC1_DATA_DRIVE_SEL; + uint32_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY; + uint32_t DC_I2C_DDC1_INTRA_BYTE_DELAY; + uint32_t DC_I2C_SW_DONE_USING_I2C_REG; + uint32_t DC_I2C_NO_QUEUED_SW_GO; + uint32_t DC_I2C_SW_PRIORITY; + uint32_t DC_I2C_SOFT_RESET; + uint32_t DC_I2C_SW_STATUS_RESET; + uint32_t DC_I2C_GO; + uint32_t DC_I2C_SEND_RESET; + uint32_t DC_I2C_TRANSACTION_COUNT; + uint32_t DC_I2C_DDC_SELECT; + uint32_t DC_I2C_DDC1_PRESCALE; + uint32_t DC_I2C_DDC1_THRESHOLD; + uint32_t DC_I2C_DDC1_START_STOP_TIMING_CNTL; + uint32_t DC_I2C_SW_STOPPED_ON_NACK; + uint32_t DC_I2C_SW_TIMEOUT; + uint32_t DC_I2C_SW_ABORTED; + uint32_t DC_I2C_SW_DONE; + uint32_t DC_I2C_SW_STATUS; + uint32_t DC_I2C_STOP_ON_NACK0; + uint32_t DC_I2C_START0; + uint32_t DC_I2C_RW0; + uint32_t DC_I2C_STOP0; + uint32_t DC_I2C_COUNT0; + uint32_t DC_I2C_DATA_RW; + uint32_t DC_I2C_DATA; + uint32_t DC_I2C_INDEX; + uint32_t DC_I2C_INDEX_WRITE; + uint32_t XTAL_REF_DIV; +}; + +struct dce110_i2c_hw_engine_registers { + uint32_t SETUP; + uint32_t SPEED; + uint32_t DC_I2C_ARBITRATION; + uint32_t DC_I2C_CONTROL; + uint32_t DC_I2C_SW_STATUS; + uint32_t DC_I2C_TRANSACTION0; + uint32_t DC_I2C_TRANSACTION1; + uint32_t DC_I2C_TRANSACTION2; + uint32_t DC_I2C_TRANSACTION3; + uint32_t DC_I2C_DATA; + uint32_t MICROSECOND_TIME_BASE_DIV; +}; + +struct i2c_hw_engine_dce110 { + struct i2c_hw_engine base; + const struct dce110_i2c_hw_engine_registers *regs; + const struct dce110_i2c_hw_engine_shift *i2c_shift; + const struct dce110_i2c_hw_engine_mask *i2c_mask; + struct { + uint32_t DC_I2C_DDCX_SETUP; + uint32_t DC_I2C_DDCX_SPEED; + } addr; + uint32_t engine_id; + /* expressed in kilohertz */ + uint32_t reference_frequency; + /* number of bytes currently used in HW buffer */ + uint32_t buffer_used_bytes; + /* number of bytes used for write transaction in HW buffer + * - this will be used as the index to read from*/ + uint32_t buffer_used_write; + /* number of pending transactions (before GO) */ + uint32_t transaction_count; + uint32_t engine_keep_power_up_count; +}; + +struct i2c_hw_engine_dce110_create_arg { + uint32_t engine_id; + uint32_t reference_frequency; + uint32_t default_speed; + struct dc_context *ctx; + const struct dce110_i2c_hw_engine_registers *regs; + const struct dce110_i2c_hw_engine_shift *i2c_shift; + const struct dce110_i2c_hw_engine_mask *i2c_mask; +}; + +struct i2c_engine *dal_i2c_hw_engine_dce110_create( + const struct i2c_hw_engine_dce110_create_arg *arg); + +bool i2c_hw_engine_dce110_construct( + struct i2c_hw_engine_dce110 *engine_dce110, + const struct i2c_hw_engine_dce110_create_arg *arg); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c new file mode 100644 index 000000000000..996813d9165f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c @@ -0,0 +1,171 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_sw_engine_dce110.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +/* + * @brief + * Cast 'struct i2c_sw_engine *' + * to 'struct i2c_sw_engine_dce110 *' + */ +#define FROM_I2C_SW_ENGINE(ptr) \ + container_of((ptr), struct i2c_sw_engine_dce110, base) +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base)) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +static void release_engine( + struct engine *engine) +{ +} + +static void destruct( + struct i2c_sw_engine_dce110 *engine) +{ + dal_i2c_sw_engine_destruct(&engine->base); +} + +static void destroy( + struct i2c_engine **engine) +{ + struct i2c_sw_engine_dce110 *sw_engine = FROM_I2C_ENGINE(*engine); + + destruct(sw_engine); + + dm_free(sw_engine); + + *engine = NULL; +} + +static bool acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc_handle) +{ + return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle); +} + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .acquire_engine = acquire_engine, + .destroy = destroy, + .get_speed = dal_i2c_sw_engine_get_speed, + .set_speed = dal_i2c_sw_engine_set_speed, + .setup_engine = dal_i2c_engine_setup_i2c_engine, + .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, + .process_channel_reply = dal_i2c_engine_process_channel_reply, + .get_channel_status = dal_i2c_sw_engine_get_channel_status, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_sw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_sw_engine_submit_request, +}; + +static bool construct( + struct i2c_sw_engine_dce110 *engine_dce110, + const struct i2c_sw_engine_dce110_create_arg *arg_dce110) +{ + struct i2c_sw_engine_create_arg arg_base; + + arg_base.ctx = arg_dce110->ctx; + arg_base.default_speed = arg_dce110->default_speed; + + if (!dal_i2c_sw_engine_construct( + &engine_dce110->base, &arg_base)) { + ASSERT_CRITICAL(false); + return false; + } + + /*struct engine struct engine_funcs*/ + engine_dce110->base.base.base.funcs = &engine_funcs; + /*struct i2c_engine struct i2c_engine_funcs*/ + engine_dce110->base.base.funcs = &i2c_engine_funcs; + engine_dce110->base.default_speed = arg_dce110->default_speed; + engine_dce110->engine_id = arg_dce110->engine_id; + + return true; +} + +struct i2c_engine *dal_i2c_sw_engine_dce110_create( + const struct i2c_sw_engine_dce110_create_arg *arg) +{ + struct i2c_sw_engine_dce110 *engine_dce110; + + if (!arg) { + ASSERT_CRITICAL(false); + return NULL; + } + + engine_dce110 = dm_alloc(sizeof(struct i2c_sw_engine_dce110)); + + if (!engine_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(engine_dce110, arg)) + return &engine_dce110->base.base; + + ASSERT_CRITICAL(false); + + dm_free(engine_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h new file mode 100644 index 000000000000..c48c61f540a8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_SW_ENGINE_DCE110_H__ +#define __DAL_I2C_SW_ENGINE_DCE110_H__ + +struct i2c_sw_engine_dce110 { + struct i2c_sw_engine base; + uint32_t engine_id; +}; + +struct i2c_sw_engine_dce110_create_arg { + uint32_t engine_id; + uint32_t default_speed; + struct dc_context *ctx; +}; + +struct i2c_engine *dal_i2c_sw_engine_dce110_create( + const struct i2c_sw_engine_dce110_create_arg *arg); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c new file mode 100644 index 000000000000..1c00ed0010d9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c @@ -0,0 +1,323 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +/* + * Header of this unit + */ +#include "i2caux_dce110.h" + +#include "i2c_sw_engine_dce110.h" +#include "i2c_hw_engine_dce110.h" +#include "aux_engine_dce110.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ +/*cast pointer to struct i2caux TO pointer to struct i2caux_dce110*/ +#define FROM_I2C_AUX(ptr) \ + container_of((ptr), struct i2caux_dce110, base) + +static void destruct( + struct i2caux_dce110 *i2caux_dce110) +{ + dal_i2caux_destruct(&i2caux_dce110->base); +} + +static void destroy( + struct i2caux **i2c_engine) +{ + struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(*i2c_engine); + + destruct(i2caux_dce110); + + dm_free(i2caux_dce110); + + *i2c_engine = NULL; +} + +static struct i2c_engine *acquire_i2c_hw_engine( + struct i2caux *i2caux, + struct ddc *ddc) +{ + struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux); + + struct i2c_engine *engine = NULL; + /* generic hw engine is not used for EDID read + * It may be needed for external i2c device, like thermal chip, + * TODO will be implemented when needed. + * check dce80 bool non_generic for generic hw engine; + */ + + if (!ddc) + return NULL; + + if (ddc->hw_info.hw_supported) { + enum gpio_ddc_line line = dal_ddc_get_line(ddc); + + if (line < GPIO_DDC_LINE_COUNT) + engine = i2caux->i2c_hw_engines[line]; + } + + if (!engine) + return NULL; + + if (!i2caux_dce110->i2c_hw_buffer_in_use && + engine->base.funcs->acquire(&engine->base, ddc)) { + i2caux_dce110->i2c_hw_buffer_in_use = true; + return engine; + } + + return NULL; +} + +static void release_engine( + struct i2caux *i2caux, + struct engine *engine) +{ + struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux); + + if (engine->funcs->get_engine_type(engine) == + I2CAUX_ENGINE_TYPE_I2C_DDC_HW) + i2caux_dce110->i2c_hw_buffer_in_use = false; + + dal_i2caux_release_engine(i2caux, engine); +} + +static const enum gpio_ddc_line hw_ddc_lines[] = { + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6, +}; + +static const enum gpio_ddc_line hw_aux_lines[] = { + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6, +}; + +/* function table */ +static const struct i2caux_funcs i2caux_funcs = { + .destroy = destroy, + .acquire_i2c_hw_engine = acquire_i2c_hw_engine, + .release_engine = release_engine, + .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine, + .acquire_aux_engine = dal_i2caux_acquire_aux_engine, +}; + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \ +} + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_aux_registers dce110_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +static const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +bool dal_i2caux_dce110_construct( + struct i2caux_dce110 *i2caux_dce110, + struct dc_context *ctx, + const struct dce110_aux_registers aux_regs[], + const struct dce110_i2c_hw_engine_registers i2c_hw_engine_regs[], + const struct dce110_i2c_hw_engine_shift *i2c_shift, + const struct dce110_i2c_hw_engine_mask *i2c_mask) +{ + uint32_t i = 0; + uint32_t reference_frequency = 0; + bool use_i2c_sw_engine = false; + struct i2caux *base = NULL; + /*TODO: For CZ bring up, if dal_i2caux_get_reference_clock + * does not return 48KHz, we need hard coded for 48Khz. + * Some BIOS setting incorrect cause this + * For production, we always get value from BIOS*/ + reference_frequency = + dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1; + + base = &i2caux_dce110->base; + + if (!dal_i2caux_construct(base, ctx)) { + ASSERT_CRITICAL(false); + return false; + } + + i2caux_dce110->base.funcs = &i2caux_funcs; + i2caux_dce110->i2c_hw_buffer_in_use = false; + /* Create I2C engines (DDC lines per connector) + * different I2C/AUX usage cases, DDC, Generic GPIO, AUX. + */ + do { + enum gpio_ddc_line line_id = hw_ddc_lines[i]; + + struct i2c_hw_engine_dce110_create_arg hw_arg_dce110; + + if (use_i2c_sw_engine) { + struct i2c_sw_engine_dce110_create_arg sw_arg; + + sw_arg.engine_id = i; + sw_arg.default_speed = base->default_i2c_sw_speed; + sw_arg.ctx = ctx; + base->i2c_sw_engines[line_id] = + dal_i2c_sw_engine_dce110_create(&sw_arg); + } + + hw_arg_dce110.engine_id = i; + hw_arg_dce110.reference_frequency = reference_frequency; + hw_arg_dce110.default_speed = base->default_i2c_hw_speed; + hw_arg_dce110.ctx = ctx; + hw_arg_dce110.regs = &i2c_hw_engine_regs[i]; + hw_arg_dce110.i2c_shift = i2c_shift; + hw_arg_dce110.i2c_mask = i2c_mask; + + base->i2c_hw_engines[line_id] = + dal_i2c_hw_engine_dce110_create(&hw_arg_dce110); + + ++i; + } while (i < ARRAY_SIZE(hw_ddc_lines)); + + /* Create AUX engines for all lines which has assisted HW AUX + * 'i' (loop counter) used as DDC/AUX engine_id */ + + i = 0; + + do { + enum gpio_ddc_line line_id = hw_aux_lines[i]; + + struct aux_engine_dce110_init_data aux_init_data; + + aux_init_data.engine_id = i; + aux_init_data.timeout_period = base->aux_timeout_period; + aux_init_data.ctx = ctx; + aux_init_data.regs = &aux_regs[i]; + + base->aux_engines[line_id] = + dal_aux_engine_dce110_create(&aux_init_data); + + ++i; + } while (i < ARRAY_SIZE(hw_aux_lines)); + + /*TODO Generic I2C SW and HW*/ + + return true; +} + +/* + * dal_i2caux_dce110_create + * + * @brief + * public interface to allocate memory for DCE11 I2CAUX + * + * @param + * struct adapter_service *as - [in] + * struct dc_context *ctx - [in] + * + * @return + * pointer to the base struct of DCE11 I2CAUX + */ +struct i2caux *dal_i2caux_dce110_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dce110_aux_regs, + i2c_hw_engine_regs, + &i2c_shift, + &i2c_mask)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h new file mode 100644 index 000000000000..fd1cc23c3d70 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE110_H__ +#define __DAL_I2C_AUX_DCE110_H__ + +#include "../i2caux.h" + +struct i2caux_dce110 { + struct i2caux base; + /* indicate the I2C HW circular buffer is in use */ + bool i2c_hw_buffer_in_use; +}; + +struct dce110_aux_registers; +struct dce110_i2c_hw_engine_registers; +struct dce110_i2c_hw_engine_shift; +struct dce110_i2c_hw_engine_mask; + +struct i2caux *dal_i2caux_dce110_create( + struct dc_context *ctx); + +bool dal_i2caux_dce110_construct( + struct i2caux_dce110 *i2caux_dce110, + struct dc_context *ctx, + const struct dce110_aux_registers *aux_regs, + const struct dce110_i2c_hw_engine_registers *i2c_hw_engine_regs, + const struct dce110_i2c_hw_engine_shift *i2c_shift, + const struct dce110_i2c_hw_engine_mask *i2c_mask); + +#endif /* __DAL_I2C_AUX_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c new file mode 100644 index 000000000000..d74f3f15d600 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c @@ -0,0 +1,140 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +#include "../dce110/i2caux_dce110.h" +#include "i2caux_dce112.h" + +#include "../dce110/aux_engine_dce110.h" + +#include "../dce110/i2c_hw_engine_dce110.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = AUX_CONTROL__AUX_RESET_MASK \ +} + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_aux_registers dce112_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5), +}; + +static const struct dce110_i2c_hw_engine_registers dce112_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +static bool construct( + struct i2caux_dce110 *i2caux_dce110, + struct dc_context *ctx) +{ + if (!dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dce112_aux_regs, + dce112_hw_engine_regs, + &i2c_shift, + &i2c_mask)) { + ASSERT_CRITICAL(false); + return false; + } + + return true; +} + +/* + * dal_i2caux_dce110_create + * + * @brief + * public interface to allocate memory for DCE11 I2CAUX + * + * @param + * struct adapter_service *as - [in] + * struct dc_context *ctx - [in] + * + * @return + * pointer to the base struct of DCE11 I2CAUX + */ +struct i2caux *dal_i2caux_dce112_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(i2caux_dce110, ctx)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h new file mode 100644 index 000000000000..8d35453c25b6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE112_H__ +#define __DAL_I2C_AUX_DCE112_H__ + +struct i2caux *dal_i2caux_dce112_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c new file mode 100644 index 000000000000..423c38ac880c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c @@ -0,0 +1,885 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_hw_engine.h" +#include "../i2c_generic_hw_engine.h" +/* + * Header of this unit + */ + +#include "i2c_hw_engine_dce80.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" +/* + * This unit + */ + +enum dc_i2c_status { + DC_I2C_STATUS__DC_I2C_STATUS_IDLE, + DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW, + DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW +}; + +enum dc_i2c_arbitration { + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH +}; + +enum { + /* No timeout in HW + * (timeout implemented in SW by querying status) */ + I2C_SETUP_TIME_LIMIT = 255, + I2C_HW_BUFFER_SIZE = 144 +}; + +/* + * @brief + * Cast 'struct i2c_hw_engine *' + * to 'struct i2c_hw_engine_dce80 *' + */ +#define FROM_I2C_HW_ENGINE(ptr) \ + container_of((ptr), struct i2c_hw_engine_dce80, base) + +/* + * @brief + * Cast pointer to 'struct i2c_engine *' + * to pointer to 'struct i2c_hw_engine_dce80 *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) + +/* + * @brief + * Cast pointer to 'struct engine *' + * to 'pointer to struct i2c_hw_engine_dce80 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +static void disable_i2c_hw_engine( + struct i2c_hw_engine_dce80 *engine) +{ + const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; + uint32_t value = 0; + + struct dc_context *ctx = NULL; + + ctx = engine->base.base.base.ctx; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_ENABLE); + + dm_write_reg(ctx, addr, value); +} + +static void release_engine( + struct engine *engine) +{ + struct i2c_hw_engine_dce80 *hw_engine = FROM_ENGINE(engine); + + struct i2c_engine *base = NULL; + bool safe_to_reset; + uint32_t value = 0; + + base = &hw_engine->base.base; + + /* Restore original HW engine speed */ + + base->funcs->set_speed(base, hw_engine->base.original_speed); + + /* Release I2C */ + { + value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION); + + set_reg_field_value( + value, + 1, + DC_I2C_ARBITRATION, + DC_I2C_SW_DONE_USING_I2C_REG); + + dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value); + } + + /* Reset HW engine */ + { + uint32_t i2c_sw_status = 0; + + value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); + + i2c_sw_status = get_reg_field_value( + value, + DC_I2C_SW_STATUS, + DC_I2C_SW_STATUS); + /* if used by SW, safe to reset */ + safe_to_reset = (i2c_sw_status == 1); + } + { + value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL); + + if (safe_to_reset) + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET); + + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET); + + dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value); + } + + /* HW I2c engine - clock gating feature */ + if (!hw_engine->engine_keep_power_up_count) + disable_i2c_hw_engine(hw_engine); +} + +static void destruct( + struct i2c_hw_engine_dce80 *engine) +{ + dal_i2c_hw_engine_destruct(&engine->base); +} + +static void destroy( + struct i2c_engine **i2c_engine) +{ + struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(*i2c_engine); + + destruct(engine); + + dm_free(engine); + + *i2c_engine = NULL; +} + +static bool setup_engine( + struct i2c_engine *i2c_engine) +{ + uint32_t value = 0; + struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); + + /* Program pin select */ + { + const uint32_t addr = mmDC_I2C_CONTROL; + + value = dm_read_reg(i2c_engine->base.ctx, addr); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_GO); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SEND_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_TRANSACTION_COUNT); + + set_reg_field_value( + value, + engine->engine_id, + DC_I2C_CONTROL, + DC_I2C_DDC_SELECT); + + dm_write_reg(i2c_engine->base.ctx, addr, value); + } + + /* Program time limit */ + { + const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; + + value = dm_read_reg(i2c_engine->base.ctx, addr); + + set_reg_field_value( + value, + I2C_SETUP_TIME_LIMIT, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_TIME_LIMIT); + + set_reg_field_value( + value, + 1, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_ENABLE); + + dm_write_reg(i2c_engine->base.ctx, addr, value); + } + + /* Program HW priority + * set to High - interrupt software I2C at any time + * Enable restart of SW I2C that was interrupted by HW + * disable queuing of software while I2C is in use by HW */ + { + value = dm_read_reg(i2c_engine->base.ctx, + mmDC_I2C_ARBITRATION); + + set_reg_field_value( + value, + 0, + DC_I2C_ARBITRATION, + DC_I2C_NO_QUEUED_SW_GO); + + set_reg_field_value( + value, + DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL, + DC_I2C_ARBITRATION, + DC_I2C_SW_PRIORITY); + + dm_write_reg(i2c_engine->base.ctx, + mmDC_I2C_ARBITRATION, value); + } + + return true; +} + +static uint32_t get_speed( + const struct i2c_engine *i2c_engine) +{ + const struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); + + const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED; + + uint32_t pre_scale = 0; + + uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr); + + pre_scale = get_reg_field_value( + value, + DC_I2C_DDC1_SPEED, + DC_I2C_DDC1_PRESCALE); + + /* [anaumov] it seems following is unnecessary */ + /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/ + + return pre_scale ? + engine->reference_frequency / pre_scale : + engine->base.default_speed; +} + +static void set_speed( + struct i2c_engine *i2c_engine, + uint32_t speed) +{ + struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine); + + if (speed) { + const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED; + + uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr); + + set_reg_field_value( + value, + engine->reference_frequency / speed, + DC_I2C_DDC1_SPEED, + DC_I2C_DDC1_PRESCALE); + + set_reg_field_value( + value, + 2, + DC_I2C_DDC1_SPEED, + DC_I2C_DDC1_THRESHOLD); + + dm_write_reg(i2c_engine->base.ctx, addr, value); + } +} + +static inline void reset_hw_engine(struct engine *engine) +{ + uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL); + + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET); + + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET); + + dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value); +} + +static bool is_hw_busy(struct engine *engine) +{ + uint32_t i2c_sw_status = 0; + + uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); + + i2c_sw_status = get_reg_field_value( + value, + DC_I2C_SW_STATUS, + DC_I2C_SW_STATUS); + + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE) + return false; + + reset_hw_engine(engine); + + value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS); + + i2c_sw_status = get_reg_field_value( + value, + DC_I2C_SW_STATUS, + DC_I2C_SW_STATUS); + + return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE; +} + +/* + * @brief + * DC_GPIO_DDC MM register offsets + */ +static const uint32_t transaction_addr[] = { + mmDC_I2C_TRANSACTION0, + mmDC_I2C_TRANSACTION1, + mmDC_I2C_TRANSACTION2, + mmDC_I2C_TRANSACTION3 +}; + +static bool process_transaction( + struct i2c_hw_engine_dce80 *engine, + struct i2c_request_transaction_data *request) +{ + uint32_t length = request->length; + uint8_t *buffer = request->data; + + bool last_transaction = false; + uint32_t value = 0; + + struct dc_context *ctx = NULL; + + ctx = engine->base.base.base.ctx; + + { + const uint32_t addr = + transaction_addr[engine->transaction_count]; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 1, + DC_I2C_TRANSACTION0, + DC_I2C_STOP_ON_NACK0); + + set_reg_field_value( + value, + 1, + DC_I2C_TRANSACTION0, + DC_I2C_START0); + + if ((engine->transaction_count == 3) || + (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || + (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { + + set_reg_field_value( + value, + 1, + DC_I2C_TRANSACTION0, + DC_I2C_STOP0); + + last_transaction = true; + } else + set_reg_field_value( + value, + 0, + DC_I2C_TRANSACTION0, + DC_I2C_STOP0); + + set_reg_field_value( + value, + (0 != (request->action & + I2CAUX_TRANSACTION_ACTION_I2C_READ)), + DC_I2C_TRANSACTION0, + DC_I2C_RW0); + + set_reg_field_value( + value, + length, + DC_I2C_TRANSACTION0, + DC_I2C_COUNT0); + + dm_write_reg(ctx, addr, value); + } + + /* Write the I2C address and I2C data + * into the hardware circular buffer, one byte per entry. + * As an example, the 7-bit I2C slave address for CRT monitor + * for reading DDC/EDID information is 0b1010001. + * For an I2C send operation, the LSB must be programmed to 0; + * for I2C receive operation, the LSB must be programmed to 1. */ + + { + value = 0; + + set_reg_field_value( + value, + false, + DC_I2C_DATA, + DC_I2C_DATA_RW); + + set_reg_field_value( + value, + request->address, + DC_I2C_DATA, + DC_I2C_DATA); + + if (engine->transaction_count == 0) { + set_reg_field_value( + value, + 0, + DC_I2C_DATA, + DC_I2C_INDEX); + + /*enable index write*/ + set_reg_field_value( + value, + 1, + DC_I2C_DATA, + DC_I2C_INDEX_WRITE); + } + + dm_write_reg(ctx, mmDC_I2C_DATA, value); + + if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) { + + set_reg_field_value( + value, + 0, + DC_I2C_DATA, + DC_I2C_INDEX_WRITE); + + while (length) { + + set_reg_field_value( + value, + *buffer++, + DC_I2C_DATA, + DC_I2C_DATA); + + dm_write_reg(ctx, mmDC_I2C_DATA, value); + --length; + } + } + } + + ++engine->transaction_count; + engine->buffer_used_bytes += length + 1; + + return last_transaction; +} + +static void execute_transaction( + struct i2c_hw_engine_dce80 *engine) +{ + uint32_t value = 0; + struct dc_context *ctx = NULL; + + ctx = engine->base.base.base.ctx; + + { + const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_DATA_DRIVE_EN); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_CLK_DRIVE_EN); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_DATA_DRIVE_SEL); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_INTRA_TRANSACTION_DELAY); + + set_reg_field_value( + value, + 0, + DC_I2C_DDC1_SETUP, + DC_I2C_DDC1_INTRA_BYTE_DELAY); + + dm_write_reg(ctx, addr, value); + } + + { + const uint32_t addr = mmDC_I2C_CONTROL; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SW_STATUS_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_SEND_RESET); + + set_reg_field_value( + value, + 0, + DC_I2C_CONTROL, + DC_I2C_GO); + + set_reg_field_value( + value, + engine->transaction_count - 1, + DC_I2C_CONTROL, + DC_I2C_TRANSACTION_COUNT); + + dm_write_reg(ctx, addr, value); + } + + /* start I2C transfer */ + { + const uint32_t addr = mmDC_I2C_CONTROL; + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, + 1, + DC_I2C_CONTROL, + DC_I2C_GO); + + dm_write_reg(ctx, addr, value); + } + + /* all transactions were executed and HW buffer became empty + * (even though it actually happens when status becomes DONE) */ + engine->transaction_count = 0; + engine->buffer_used_bytes = 0; +} + +static void submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request) +{ + request->status = I2C_CHANNEL_OPERATION_SUCCEEDED; + + if (!process_transaction(FROM_I2C_ENGINE(engine), request)) + return; + + if (is_hw_busy(&engine->base)) { + request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY; + return; + } + + execute_transaction(FROM_I2C_ENGINE(engine)); +} + +static void process_channel_reply( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply) +{ + uint32_t length = reply->length; + uint8_t *buffer = reply->data; + + uint32_t value = 0; + + /*set index*/ + set_reg_field_value( + value, + length - 1, + DC_I2C_DATA, + DC_I2C_INDEX); + + set_reg_field_value( + value, + 1, + DC_I2C_DATA, + DC_I2C_DATA_RW); + + set_reg_field_value( + value, + 1, + DC_I2C_DATA, + DC_I2C_INDEX_WRITE); + + dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value); + + while (length) { + /* after reading the status, + * if the I2C operation executed successfully + * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller + * should read data bytes from I2C circular data buffer */ + + value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA); + + *buffer++ = get_reg_field_value( + value, + DC_I2C_DATA, + DC_I2C_DATA); + + --length; + } +} + +static enum i2c_channel_operation_result get_channel_status( + struct i2c_engine *engine, + uint8_t *returned_bytes) +{ + uint32_t i2c_sw_status = 0; + uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS); + + i2c_sw_status = get_reg_field_value( + value, + DC_I2C_SW_STATUS, + DC_I2C_SW_STATUS); + + if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW) + return I2C_CHANNEL_OPERATION_ENGINE_BUSY; + else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK) + return I2C_CHANNEL_OPERATION_NO_RESPONSE; + else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK) + return I2C_CHANNEL_OPERATION_TIMEOUT; + else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK) + return I2C_CHANNEL_OPERATION_FAILED; + else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK) + return I2C_CHANNEL_OPERATION_SUCCEEDED; + + /* + * this is the case when HW used for communication, I2C_SW_STATUS + * could be zero + */ + return I2C_CHANNEL_OPERATION_SUCCEEDED; +} + +static uint32_t get_hw_buffer_available_size( + const struct i2c_hw_engine *engine) +{ + return I2C_HW_BUFFER_SIZE - + FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes; +} + +static uint32_t get_transaction_timeout( + const struct i2c_hw_engine *engine, + uint32_t length) +{ + uint32_t speed = engine->base.funcs->get_speed(&engine->base); + + uint32_t period_timeout; + uint32_t num_of_clock_stretches; + + if (!speed) + return 0; + + period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed; + + num_of_clock_stretches = 1 + (length << 3) + 1; + num_of_clock_stretches += + (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) + + (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1); + + return period_timeout * num_of_clock_stretches; +} + +/* + * @brief + * DC_I2C_DDC1_SETUP MM register offsets + * + * @note + * The indices of this offset array are DDC engine IDs + */ +static const int32_t ddc_setup_offset[] = { + + mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */ + mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */ + mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */ + mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */ + mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */ + mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */ + mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */ +}; + +/* + * @brief + * DC_I2C_DDC1_SPEED MM register offsets + * + * @note + * The indices of this offset array are DDC engine IDs + */ +static const int32_t ddc_speed_offset[] = { + mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */ + mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */ + mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */ + mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */ + mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */ + mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */ + mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */ +}; + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .destroy = destroy, + .get_speed = get_speed, + .set_speed = set_speed, + .setup_engine = setup_engine, + .submit_channel_request = submit_channel_request, + .process_channel_reply = process_channel_reply, + .get_channel_status = get_channel_status, + .acquire_engine = dal_i2c_hw_engine_acquire_engine, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_hw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_hw_engine_submit_request, +}; + +static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { + .get_hw_buffer_available_size = + get_hw_buffer_available_size, + .get_transaction_timeout = + get_transaction_timeout, + .wait_on_operation_result = + dal_i2c_hw_engine_wait_on_operation_result, +}; + +static bool construct( + struct i2c_hw_engine_dce80 *engine, + const struct i2c_hw_engine_dce80_create_arg *arg) +{ + if (arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) + return false; + if (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) + return false; + + if (!arg->reference_frequency) + return false; + + if (!dal_i2c_hw_engine_construct(&engine->base, arg->ctx)) + return false; + + engine->base.base.base.funcs = &engine_funcs; + engine->base.base.funcs = &i2c_engine_funcs; + engine->base.funcs = &i2c_hw_engine_funcs; + engine->base.default_speed = arg->default_speed; + engine->addr.DC_I2C_DDCX_SETUP = + mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id]; + engine->addr.DC_I2C_DDCX_SPEED = + mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id]; + + engine->engine_id = arg->engine_id; + engine->reference_frequency = arg->reference_frequency; + engine->buffer_used_bytes = 0; + engine->transaction_count = 0; + engine->engine_keep_power_up_count = 1; + + return true; +} + +struct i2c_engine *dal_i2c_hw_engine_dce80_create( + const struct i2c_hw_engine_dce80_create_arg *arg) +{ + struct i2c_hw_engine_dce80 *engine; + + if (!arg) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + engine = dm_alloc(sizeof(struct i2c_hw_engine_dce80)); + + if (!engine) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (construct(engine, arg)) + return &engine->base.base; + + BREAK_TO_DEBUGGER(); + + dm_free(engine); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h new file mode 100644 index 000000000000..5c6116fb5479 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.h @@ -0,0 +1,54 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_HW_ENGINE_DCE80_H__ +#define __DAL_I2C_HW_ENGINE_DCE80_H__ + +struct i2c_hw_engine_dce80 { + struct i2c_hw_engine base; + struct { + uint32_t DC_I2C_DDCX_SETUP; + uint32_t DC_I2C_DDCX_SPEED; + } addr; + uint32_t engine_id; + /* expressed in kilohertz */ + uint32_t reference_frequency; + /* number of bytes currently used in HW buffer */ + uint32_t buffer_used_bytes; + /* number of pending transactions (before GO) */ + uint32_t transaction_count; + uint32_t engine_keep_power_up_count; +}; + +struct i2c_hw_engine_dce80_create_arg { + uint32_t engine_id; + uint32_t reference_frequency; + uint32_t default_speed; + struct dc_context *ctx; +}; + +struct i2c_engine *dal_i2c_hw_engine_dce80_create( + const struct i2c_hw_engine_dce80_create_arg *arg); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c new file mode 100644 index 000000000000..804a3266c578 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c @@ -0,0 +1,184 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_sw_engine_dce80.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +/* + * This unit + */ + +static const uint32_t ddc_hw_status_addr[] = { + mmDC_I2C_DDC1_HW_STATUS, + mmDC_I2C_DDC2_HW_STATUS, + mmDC_I2C_DDC3_HW_STATUS, + mmDC_I2C_DDC4_HW_STATUS, + mmDC_I2C_DDC5_HW_STATUS, + mmDC_I2C_DDC6_HW_STATUS, + mmDC_I2C_DDCVGA_HW_STATUS +}; + +/* + * @brief + * Cast 'struct i2c_sw_engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_I2C_SW_ENGINE(ptr) \ + container_of((ptr), struct i2c_sw_engine_dce80, base) + +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base)) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_sw_engine_dce80 *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +static void release_engine( + struct engine *engine) +{ + +} + +static void destruct( + struct i2c_sw_engine_dce80 *engine) +{ + dal_i2c_sw_engine_destruct(&engine->base); +} + +static void destroy( + struct i2c_engine **engine) +{ + struct i2c_sw_engine_dce80 *sw_engine = FROM_I2C_ENGINE(*engine); + + destruct(sw_engine); + + dm_free(sw_engine); + + *engine = NULL; +} + +static bool acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc_handle) +{ + return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle); +} + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .acquire_engine = acquire_engine, + .destroy = destroy, + .get_speed = dal_i2c_sw_engine_get_speed, + .set_speed = dal_i2c_sw_engine_set_speed, + .setup_engine = dal_i2c_engine_setup_i2c_engine, + .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, + .process_channel_reply = dal_i2c_engine_process_channel_reply, + .get_channel_status = dal_i2c_sw_engine_get_channel_status, +}; + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_sw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_sw_engine_submit_request, +}; + +static bool construct( + struct i2c_sw_engine_dce80 *engine, + const struct i2c_sw_engine_dce80_create_arg *arg) +{ + struct i2c_sw_engine_create_arg arg_base; + + arg_base.ctx = arg->ctx; + arg_base.default_speed = arg->default_speed; + + if (!dal_i2c_sw_engine_construct(&engine->base, &arg_base)) { + BREAK_TO_DEBUGGER(); + return false; + } + + engine->base.base.base.funcs = &engine_funcs; + engine->base.base.funcs = &i2c_engine_funcs; + engine->base.default_speed = arg->default_speed; + engine->engine_id = arg->engine_id; + + return true; +} + +struct i2c_engine *dal_i2c_sw_engine_dce80_create( + const struct i2c_sw_engine_dce80_create_arg *arg) +{ + struct i2c_sw_engine_dce80 *engine; + + if (!arg) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + engine = dm_alloc(sizeof(struct i2c_sw_engine_dce80)); + + if (!engine) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (construct(engine, arg)) + return &engine->base.base; + + BREAK_TO_DEBUGGER(); + + dm_free(engine); + + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h new file mode 100644 index 000000000000..26355c088746 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_SW_ENGINE_DCE80_H__ +#define __DAL_I2C_SW_ENGINE_DCE80_H__ + +struct i2c_sw_engine_dce80 { + struct i2c_sw_engine base; + uint32_t engine_id; +}; + +struct i2c_sw_engine_dce80_create_arg { + uint32_t engine_id; + uint32_t default_speed; + struct dc_context *ctx; +}; + +struct i2c_engine *dal_i2c_sw_engine_dce80_create( + const struct i2c_sw_engine_dce80_create_arg *arg); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c new file mode 100644 index 000000000000..5e71450c44e0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c @@ -0,0 +1,295 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../i2caux.h" + +/* + * Header of this unit + */ + +#include "i2caux_dce80.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "i2c_sw_engine_dce80.h" +#include "../i2c_hw_engine.h" +#include "i2c_hw_engine_dce80.h" +#include "../i2c_generic_hw_engine.h" +#include "../aux_engine.h" + + +#include "../dce110/aux_engine_dce110.h" +#include "../dce110/i2caux_dce110.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers dce80_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +/* + * This unit + */ + +#define FROM_I2C_AUX(ptr) \ + container_of((ptr), struct i2caux_dce80, base) + +static void destruct( + struct i2caux_dce80 *i2caux_dce80) +{ + dal_i2caux_destruct(&i2caux_dce80->base); +} + +static void destroy( + struct i2caux **i2c_engine) +{ + struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(*i2c_engine); + + destruct(i2caux_dce80); + + dm_free(i2caux_dce80); + + *i2c_engine = NULL; +} + +static struct i2c_engine *acquire_i2c_hw_engine( + struct i2caux *i2caux, + struct ddc *ddc) +{ + struct i2caux_dce80 *i2caux_dce80 = FROM_I2C_AUX(i2caux); + + struct i2c_engine *engine = NULL; + bool non_generic; + + if (!ddc) + return NULL; + + if (ddc->hw_info.hw_supported) { + enum gpio_ddc_line line = dal_ddc_get_line(ddc); + + if (line < GPIO_DDC_LINE_COUNT) { + non_generic = true; + engine = i2caux->i2c_hw_engines[line]; + } + } + + if (!engine) { + non_generic = false; + engine = i2caux->i2c_generic_hw_engine; + } + + if (!engine) + return NULL; + + if (non_generic) { + if (!i2caux_dce80->i2c_hw_buffer_in_use && + engine->base.funcs->acquire(&engine->base, ddc)) { + i2caux_dce80->i2c_hw_buffer_in_use = true; + return engine; + } + } else { + if (engine->base.funcs->acquire(&engine->base, ddc)) + return engine; + } + + return NULL; +} + +static void release_engine( + struct i2caux *i2caux, + struct engine *engine) +{ + if (engine->funcs->get_engine_type(engine) == + I2CAUX_ENGINE_TYPE_I2C_DDC_HW) + FROM_I2C_AUX(i2caux)->i2c_hw_buffer_in_use = false; + + dal_i2caux_release_engine(i2caux, engine); +} + +static const enum gpio_ddc_line hw_ddc_lines[] = { + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6, + GPIO_DDC_LINE_DDC_VGA +}; + +static const enum gpio_ddc_line hw_aux_lines[] = { + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6 +}; + +static const struct i2caux_funcs i2caux_funcs = { + .destroy = destroy, + .acquire_i2c_hw_engine = acquire_i2c_hw_engine, + .release_engine = release_engine, + .acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine, + .acquire_aux_engine = dal_i2caux_acquire_aux_engine, +}; + +static bool construct( + struct i2caux_dce80 *i2caux_dce80, + struct dc_context *ctx) +{ + /* Entire family have I2C engine reference clock frequency + * changed from XTALIN (27) to XTALIN/2 (13.5) */ + + struct i2caux *base = &i2caux_dce80->base; + + uint32_t reference_frequency = + dal_i2caux_get_reference_clock(ctx->dc_bios) >> 1; + + /*bool use_i2c_sw_engine = dal_adapter_service_is_feature_supported(as, + FEATURE_RESTORE_USAGE_I2C_SW_ENGINE);*/ + + /* Use SWI2C for dce8 currently, sicne we have bug with hwi2c */ + bool use_i2c_sw_engine = true; + + uint32_t i; + + if (!dal_i2caux_construct(base, ctx)) { + BREAK_TO_DEBUGGER(); + return false; + } + + i2caux_dce80->base.funcs = &i2caux_funcs; + i2caux_dce80->i2c_hw_buffer_in_use = false; + + /* Create I2C HW engines (HW + SW pairs) + * for all lines which has assisted HW DDC + * 'i' (loop counter) used as DDC/AUX engine_id */ + + i = 0; + + do { + enum gpio_ddc_line line_id = hw_ddc_lines[i]; + + struct i2c_hw_engine_dce80_create_arg hw_arg; + + if (use_i2c_sw_engine) { + struct i2c_sw_engine_dce80_create_arg sw_arg; + + sw_arg.engine_id = i; + sw_arg.default_speed = base->default_i2c_sw_speed; + sw_arg.ctx = ctx; + base->i2c_sw_engines[line_id] = + dal_i2c_sw_engine_dce80_create(&sw_arg); + } + + hw_arg.engine_id = i; + hw_arg.reference_frequency = reference_frequency; + hw_arg.default_speed = base->default_i2c_hw_speed; + hw_arg.ctx = ctx; + + base->i2c_hw_engines[line_id] = + dal_i2c_hw_engine_dce80_create(&hw_arg); + + ++i; + } while (i < ARRAY_SIZE(hw_ddc_lines)); + + /* Create AUX engines for all lines which has assisted HW AUX + * 'i' (loop counter) used as DDC/AUX engine_id */ + + i = 0; + + do { + enum gpio_ddc_line line_id = hw_aux_lines[i]; + + struct aux_engine_dce110_init_data arg; + + arg.engine_id = i; + arg.timeout_period = base->aux_timeout_period; + arg.ctx = ctx; + arg.regs = &dce80_aux_regs[i]; + + base->aux_engines[line_id] = + dal_aux_engine_dce110_create(&arg); + + ++i; + } while (i < ARRAY_SIZE(hw_aux_lines)); + + /* TODO Generic I2C SW and HW */ + + return true; +} + +struct i2caux *dal_i2caux_dce80_create( + struct dc_context *ctx) +{ + struct i2caux_dce80 *i2caux_dce80 = + dm_alloc(sizeof(struct i2caux_dce80)); + + if (!i2caux_dce80) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (construct(i2caux_dce80, ctx)) + return &i2caux_dce80->base; + + BREAK_TO_DEBUGGER(); + + dm_free(i2caux_dce80); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h new file mode 100644 index 000000000000..21908629e973 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE80_H__ +#define __DAL_I2C_AUX_DCE80_H__ + +struct i2caux_dce80 { + struct i2caux base; + /* indicate the I2C HW circular buffer is in use */ + bool i2c_hw_buffer_in_use; +}; + +struct i2caux *dal_i2caux_dce80_create( + struct dc_context *ctx); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c new file mode 100644 index 000000000000..029bf735036c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c @@ -0,0 +1,108 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +/* + * Header of this unit + */ +#include "i2caux_diag.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +static void destruct( + struct i2caux *i2caux) +{ + dal_i2caux_destruct(i2caux); +} + +static void destroy( + struct i2caux **i2c_engine) +{ + destruct(*i2c_engine); + + dm_free(*i2c_engine); + + *i2c_engine = NULL; +} + +/* function table */ +static const struct i2caux_funcs i2caux_funcs = { + .destroy = destroy, + .acquire_i2c_hw_engine = NULL, + .release_engine = NULL, + .acquire_i2c_sw_engine = NULL, + .acquire_aux_engine = NULL, +}; + +static bool construct( + struct i2caux *i2caux, + struct dc_context *ctx) +{ + if (!dal_i2caux_construct(i2caux, ctx)) { + ASSERT_CRITICAL(false); + return false; + } + + i2caux->funcs = &i2caux_funcs; + + return true; +} + +struct i2caux *dal_i2caux_diag_fpga_create( + struct dc_context *ctx) +{ + struct i2caux *i2caux = dm_alloc(sizeof(struct i2caux)); + + if (!i2caux) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (construct(i2caux, ctx)) + return i2caux; + + ASSERT_CRITICAL(false); + + dm_free(i2caux); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h new file mode 100644 index 000000000000..a83eeb748283 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DIAG_FPGA_H__ +#define __DAL_I2C_AUX_DIAG_FPGA_H__ + +struct i2caux *dal_i2caux_diag_fpga_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DIAG_FPGA_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h new file mode 100644 index 000000000000..76fe2df3c2f8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h @@ -0,0 +1,120 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_ENGINE_H__ +#define __DAL_ENGINE_H__ + +enum i2caux_transaction_operation { + I2CAUX_TRANSACTION_READ, + I2CAUX_TRANSACTION_WRITE +}; + +enum i2caux_transaction_address_space { + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1, + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD +}; + +struct i2caux_transaction_payload { + enum i2caux_transaction_address_space address_space; + uint32_t address; + uint32_t length; + uint8_t *data; +}; + +enum i2caux_transaction_status { + I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L), + I2CAUX_TRANSACTION_STATUS_SUCCEEDED, + I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY, + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT, + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR, + I2CAUX_TRANSACTION_STATUS_FAILED_NACK, + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE, + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION, + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION, + I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW +}; + +struct i2caux_transaction_request { + enum i2caux_transaction_operation operation; + struct i2caux_transaction_payload payload; + enum i2caux_transaction_status status; +}; + +enum i2caux_engine_type { + I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L), + I2CAUX_ENGINE_TYPE_AUX, + I2CAUX_ENGINE_TYPE_I2C_DDC_HW, + I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW, + I2CAUX_ENGINE_TYPE_I2C_SW +}; + +enum i2c_default_speed { + I2CAUX_DEFAULT_I2C_HW_SPEED = 50, + I2CAUX_DEFAULT_I2C_SW_SPEED = 50 +}; + +enum i2caux_transaction_action { + I2CAUX_TRANSACTION_ACTION_I2C_WRITE = 0x00, + I2CAUX_TRANSACTION_ACTION_I2C_READ = 0x10, + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20, + + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40, + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT = 0x50, + I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60, + + I2CAUX_TRANSACTION_ACTION_DP_WRITE = 0x80, + I2CAUX_TRANSACTION_ACTION_DP_READ = 0x90 +}; + +struct engine; + +struct engine_funcs { + enum i2caux_engine_type (*get_engine_type)( + const struct engine *engine); + bool (*acquire)( + struct engine *engine, + struct ddc *ddc); + bool (*submit_request)( + struct engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction); + void (*release_engine)( + struct engine *engine); +}; + +struct engine { + const struct engine_funcs *funcs; + struct ddc *ddc; + struct dc_context *ctx; +}; + +bool dal_i2caux_construct_engine( + struct engine *engine, + struct dc_context *ctx); + +void dal_i2caux_destruct_engine( + struct engine *engine); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c new file mode 100644 index 000000000000..09da81379491 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c @@ -0,0 +1,53 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" + +/* + * Header of this unit + */ + +#include "engine.h" + +bool dal_i2caux_construct_engine( + struct engine *engine, + struct dc_context *ctx) +{ + engine->ddc = NULL; + engine->ctx = ctx; + return true; +} + +void dal_i2caux_destruct_engine( + struct engine *engine) +{ + /* nothing to do */ +} + diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c new file mode 100644 index 000000000000..144f51dc4523 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c @@ -0,0 +1,121 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" + +/* + * Header of this unit + */ + +#include "i2c_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +#define FROM_ENGINE(ptr) \ + container_of((ptr), struct i2c_engine, base) + +bool dal_i2c_engine_acquire( + struct engine *engine, + struct ddc *ddc_handle) +{ + struct i2c_engine *i2c_engine = FROM_ENGINE(engine); + + uint32_t counter = 0; + bool result; + + do { + result = i2c_engine->funcs->acquire_engine( + i2c_engine, ddc_handle); + + if (result) + break; + + /* i2c_engine is busy by VBios, lets wait and retry */ + + udelay(10); + + ++counter; + } while (counter < 2); + + if (result) { + if (!i2c_engine->funcs->setup_engine(i2c_engine)) { + engine->funcs->release_engine(engine); + result = false; + } + } + + return result; +} + +bool dal_i2c_engine_setup_i2c_engine( + struct i2c_engine *engine) +{ + /* Derivative classes do not have to override this */ + + return true; +} + +void dal_i2c_engine_submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request) +{ + +} + +void dal_i2c_engine_process_channel_reply( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply) +{ + +} + +bool dal_i2c_engine_construct( + struct i2c_engine *engine, + struct dc_context *ctx) +{ + if (!dal_i2caux_construct_engine(&engine->base, ctx)) + return false; + + engine->timeout_delay = 0; + return true; +} + +void dal_i2c_engine_destruct( + struct i2c_engine *engine) +{ + dal_i2caux_destruct_engine(&engine->base); +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h new file mode 100644 index 000000000000..ce2c51ddea02 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h @@ -0,0 +1,113 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_ENGINE_H__ +#define __DAL_I2C_ENGINE_H__ + +enum i2c_channel_operation_result { + I2C_CHANNEL_OPERATION_SUCCEEDED, + I2C_CHANNEL_OPERATION_FAILED, + I2C_CHANNEL_OPERATION_NOT_GRANTED, + I2C_CHANNEL_OPERATION_IS_BUSY, + I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED, + I2C_CHANNEL_OPERATION_CHANNEL_IN_USE, + I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED, + I2C_CHANNEL_OPERATION_ENGINE_BUSY, + I2C_CHANNEL_OPERATION_TIMEOUT, + I2C_CHANNEL_OPERATION_NO_RESPONSE, + I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS, + I2C_CHANNEL_OPERATION_WRONG_PARAMETER, + I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES, + I2C_CHANNEL_OPERATION_NOT_STARTED +}; + +struct i2c_request_transaction_data { + enum i2caux_transaction_action action; + enum i2c_channel_operation_result status; + uint8_t address; + uint32_t length; + uint8_t *data; +}; + +struct i2c_reply_transaction_data { + uint32_t length; + uint8_t *data; +}; + +struct i2c_engine; + +struct i2c_engine_funcs { + void (*destroy)( + struct i2c_engine **ptr); + uint32_t (*get_speed)( + const struct i2c_engine *engine); + void (*set_speed)( + struct i2c_engine *engine, + uint32_t speed); + bool (*acquire_engine)( + struct i2c_engine *engine, + struct ddc *ddc); + bool (*setup_engine)( + struct i2c_engine *engine); + void (*submit_channel_request)( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request); + void (*process_channel_reply)( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply); + enum i2c_channel_operation_result (*get_channel_status)( + struct i2c_engine *engine, + uint8_t *returned_bytes); +}; + +struct i2c_engine { + struct engine base; + const struct i2c_engine_funcs *funcs; + uint32_t timeout_delay; +}; + +bool dal_i2c_engine_construct( + struct i2c_engine *engine, + struct dc_context *ctx); + +void dal_i2c_engine_destruct( + struct i2c_engine *engine); + +bool dal_i2c_engine_setup_i2c_engine( + struct i2c_engine *engine); + +void dal_i2c_engine_submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *request); + +void dal_i2c_engine_process_channel_reply( + struct i2c_engine *engine, + struct i2c_reply_transaction_data *reply); + +bool dal_i2c_engine_acquire( + struct engine *ptr, + struct ddc *ddc_handle); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c new file mode 100644 index 000000000000..521c4ec98632 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c @@ -0,0 +1,286 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" +#include "i2c_engine.h" +#include "i2c_hw_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_generic_hw_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +/* + * @brief + * Cast 'struct i2c_hw_engine *' + * to 'struct i2c_generic_hw_engine *' + */ +#define FROM_I2C_HW_ENGINE(ptr) \ + container_of((ptr), struct i2c_generic_hw_engine, base) + +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_generic_hw_engine *' + */ +#define FROM_I2C_ENGINE(ptr) \ + FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base)) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_generic_hw_engine *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type( + const struct engine *engine) +{ + return I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW; +} + +/* + * @brief + * Single transaction handling. + * Since transaction may be bigger than HW buffer size, + * it divides transaction to sub-transactions + * and uses batch transaction feature of the engine. + */ +bool dal_i2c_generic_hw_engine_submit_request( + struct engine *engine, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction) +{ + struct i2c_generic_hw_engine *hw_engine = FROM_ENGINE(engine); + + struct i2c_hw_engine *base = &hw_engine->base; + + uint32_t max_payload_size = + base->funcs->get_hw_buffer_available_size(base); + + bool initial_stop_bit = !middle_of_transaction; + + struct i2c_generic_transaction_attributes attributes; + + enum i2c_channel_operation_result operation_result = + I2C_CHANNEL_OPERATION_FAILED; + + bool result = false; + + /* setup transaction initial properties */ + + uint8_t address = i2caux_request->payload.address; + uint8_t *current_payload = i2caux_request->payload.data; + uint32_t remaining_payload_size = i2caux_request->payload.length; + + bool first_iteration = true; + + if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) + attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_READ; + else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) + attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + else { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; + return false; + } + + /* Do batch transaction. + * Divide read/write data into payloads which fit HW buffer size. + * 1. Single transaction: + * start_bit = 1, stop_bit depends on session state, ack_on_read = 0; + * 2. Start of batch transaction: + * start_bit = 1, stop_bit = 0, ack_on_read = 1; + * 3. Middle of batch transaction: + * start_bit = 0, stop_bit = 0, ack_on_read = 1; + * 4. End of batch transaction: + * start_bit = 0, stop_bit depends on session state, ack_on_read = 0. + * Session stop bit is set if 'middle_of_transaction' = 0. */ + + while (remaining_payload_size) { + uint32_t current_transaction_size; + uint32_t current_payload_size; + + bool last_iteration; + bool stop_bit; + + /* Calculate current transaction size and payload size. + * Transaction size = total number of bytes in transaction, + * including slave's address; + * Payload size = number of data bytes in transaction. */ + + if (first_iteration) { + /* In the first sub-transaction we send slave's address + * thus we need to reserve one byte for it */ + current_transaction_size = + (remaining_payload_size > max_payload_size - 1) ? + max_payload_size : + remaining_payload_size + 1; + + current_payload_size = current_transaction_size - 1; + } else { + /* Second and further sub-transactions will have + * entire buffer reserved for data */ + current_transaction_size = + (remaining_payload_size > max_payload_size) ? + max_payload_size : + remaining_payload_size; + + current_payload_size = current_transaction_size; + } + + last_iteration = + (remaining_payload_size == current_payload_size); + + stop_bit = last_iteration ? initial_stop_bit : false; + + /* write slave device address */ + + if (first_iteration) + hw_engine->funcs->write_address(hw_engine, address); + + /* write current portion of data, if requested */ + + if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) + hw_engine->funcs->write_data( + hw_engine, + current_payload, + current_payload_size); + + /* execute transaction */ + + attributes.start_bit = first_iteration; + attributes.stop_bit = stop_bit; + attributes.last_read = last_iteration; + attributes.transaction_size = current_transaction_size; + + hw_engine->funcs->execute_transaction(hw_engine, &attributes); + + /* wait until transaction is processed; if it fails - quit */ + + operation_result = base->funcs->wait_on_operation_result( + base, + base->funcs->get_transaction_timeout( + base, current_transaction_size), + I2C_CHANNEL_OPERATION_ENGINE_BUSY); + + if (operation_result != I2C_CHANNEL_OPERATION_SUCCEEDED) + break; + + /* read current portion of data, if requested */ + + /* the read offset should be 1 for first sub-transaction, + * and 0 for any next one */ + + if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) + hw_engine->funcs->read_data(hw_engine, current_payload, + current_payload_size, first_iteration ? 1 : 0); + + /* update loop variables */ + + first_iteration = false; + current_payload += current_payload_size; + remaining_payload_size -= current_payload_size; + } + + /* update transaction status */ + + switch (operation_result) { + case I2C_CHANNEL_OPERATION_SUCCEEDED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + result = true; + break; + case I2C_CHANNEL_OPERATION_NO_RESPONSE: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + break; + case I2C_CHANNEL_OPERATION_TIMEOUT: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + break; + case I2C_CHANNEL_OPERATION_FAILED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; + break; + default: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; + } + + return result; +} + +/* + * @brief + * Returns number of microseconds to wait until timeout to be considered + */ +uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( + const struct i2c_hw_engine *engine, + uint32_t length) +{ + const struct i2c_engine *base = &engine->base; + + uint32_t speed = base->funcs->get_speed(base); + + if (!speed) + return 0; + + /* total timeout = period_timeout * (start + data bits count + stop) */ + + return ((1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed) * + (1 + (length << 3) + 1); +} + +bool dal_i2c_generic_hw_engine_construct( + struct i2c_generic_hw_engine *engine, + struct dc_context *ctx) +{ + if (!dal_i2c_hw_engine_construct(&engine->base, ctx)) + return false; + return true; +} + +void dal_i2c_generic_hw_engine_destruct( + struct i2c_generic_hw_engine *engine) +{ + dal_i2c_hw_engine_destruct(&engine->base); +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h new file mode 100644 index 000000000000..083bb0dee9a1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h @@ -0,0 +1,77 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_GENERIC_HW_ENGINE_H__ +#define __DAL_I2C_GENERIC_HW_ENGINE_H__ + +struct i2c_generic_transaction_attributes { + enum i2caux_transaction_action action; + uint32_t transaction_size; + bool start_bit; + bool stop_bit; + bool last_read; +}; + +struct i2c_generic_hw_engine; + +struct i2c_generic_hw_engine_funcs { + void (*write_address)( + struct i2c_generic_hw_engine *engine, + uint8_t address); + void (*write_data)( + struct i2c_generic_hw_engine *engine, + const uint8_t *buffer, + uint32_t length); + void (*read_data)( + struct i2c_generic_hw_engine *engine, + uint8_t *buffer, + uint32_t length, + uint32_t offset); + void (*execute_transaction)( + struct i2c_generic_hw_engine *engine, + struct i2c_generic_transaction_attributes *attributes); +}; + +struct i2c_generic_hw_engine { + struct i2c_hw_engine base; + const struct i2c_generic_hw_engine_funcs *funcs; +}; + +bool dal_i2c_generic_hw_engine_construct( + struct i2c_generic_hw_engine *engine, + struct dc_context *ctx); + +void dal_i2c_generic_hw_engine_destruct( + struct i2c_generic_hw_engine *engine); +enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type( + const struct engine *engine); +bool dal_i2c_generic_hw_engine_submit_request( + struct engine *ptr, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction); +uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( + const struct i2c_hw_engine *engine, + uint32_t length); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c new file mode 100644 index 000000000000..00a8f07a74e9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c @@ -0,0 +1,246 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" +#include "i2c_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_hw_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_hw_engine *' + */ +#define FROM_I2C_ENGINE(ptr) \ + container_of((ptr), struct i2c_hw_engine, base) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_hw_engine *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type( + const struct engine *engine) +{ + return I2CAUX_ENGINE_TYPE_I2C_DDC_HW; +} + +bool dal_i2c_hw_engine_submit_request( + struct engine *engine, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction) +{ + struct i2c_hw_engine *hw_engine = FROM_ENGINE(engine); + + struct i2c_request_transaction_data request; + + uint32_t transaction_timeout; + + enum i2c_channel_operation_result operation_result; + + bool result = false; + + /* We need following: + * transaction length will not exceed + * the number of free bytes in HW buffer (minus one for address)*/ + + if (i2caux_request->payload.length >= + hw_engine->funcs->get_hw_buffer_available_size(hw_engine)) { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW; + return false; + } + + if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) + request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_READ; + else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) + request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + else { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; + /* [anaumov] in DAL2, there was no "return false" */ + return false; + } + + request.address = (uint8_t)i2caux_request->payload.address; + request.length = i2caux_request->payload.length; + request.data = i2caux_request->payload.data; + + /* obtain timeout value before submitting request */ + + transaction_timeout = hw_engine->funcs->get_transaction_timeout( + hw_engine, i2caux_request->payload.length + 1); + + hw_engine->base.funcs->submit_channel_request( + &hw_engine->base, &request); + + if ((request.status == I2C_CHANNEL_OPERATION_FAILED) || + (request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY)) { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY; + return false; + } + + /* wait until transaction proceed */ + + operation_result = hw_engine->funcs->wait_on_operation_result( + hw_engine, + transaction_timeout, + I2C_CHANNEL_OPERATION_ENGINE_BUSY); + + /* update transaction status */ + + switch (operation_result) { + case I2C_CHANNEL_OPERATION_SUCCEEDED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + result = true; + break; + case I2C_CHANNEL_OPERATION_NO_RESPONSE: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + break; + case I2C_CHANNEL_OPERATION_TIMEOUT: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + break; + case I2C_CHANNEL_OPERATION_FAILED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; + break; + default: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; + } + + if (result && (i2caux_request->operation == I2CAUX_TRANSACTION_READ)) { + struct i2c_reply_transaction_data reply; + + reply.data = i2caux_request->payload.data; + reply.length = i2caux_request->payload.length; + + hw_engine->base.funcs-> + process_channel_reply(&hw_engine->base, &reply); + } + + return result; +} + +bool dal_i2c_hw_engine_acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc) +{ + enum gpio_result result; + uint32_t current_speed; + + result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, + GPIO_DDC_CONFIG_TYPE_MODE_I2C); + + if (result != GPIO_RESULT_OK) + return false; + + engine->base.ddc = ddc; + + current_speed = engine->funcs->get_speed(engine); + + if (current_speed) + FROM_I2C_ENGINE(engine)->original_speed = current_speed; + + return true; +} +/* + * @brief + * Queries in a loop for current engine status + * until retrieved status matches 'expected_result', or timeout occurs. + * Timeout given in microseconds + * and the status query frequency is also one per microsecond. + */ +enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( + struct i2c_hw_engine *engine, + uint32_t timeout, + enum i2c_channel_operation_result expected_result) +{ + enum i2c_channel_operation_result result; + uint32_t i = 0; + + if (!timeout) + return I2C_CHANNEL_OPERATION_SUCCEEDED; + + do { + result = engine->base.funcs->get_channel_status( + &engine->base, NULL); + + if (result != expected_result) + break; + + udelay(1); + + ++i; + } while (i < timeout); + + return result; +} + +bool dal_i2c_hw_engine_construct( + struct i2c_hw_engine *engine, + struct dc_context *ctx) +{ + if (!dal_i2c_engine_construct(&engine->base, ctx)) + return false; + engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; + engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; + return true; +} + +void dal_i2c_hw_engine_destruct( + struct i2c_hw_engine *engine) +{ + dal_i2c_engine_destruct(&engine->base); +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h new file mode 100644 index 000000000000..f2df1749820e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h @@ -0,0 +1,80 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_HW_ENGINE_H__ +#define __DAL_I2C_HW_ENGINE_H__ + +enum { + TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32 +}; + +struct i2c_hw_engine; + +struct i2c_hw_engine_funcs { + uint32_t (*get_hw_buffer_available_size)( + const struct i2c_hw_engine *engine); + enum i2c_channel_operation_result (*wait_on_operation_result)( + struct i2c_hw_engine *engine, + uint32_t timeout, + enum i2c_channel_operation_result expected_result); + uint32_t (*get_transaction_timeout)( + const struct i2c_hw_engine *engine, + uint32_t length); +}; + +struct i2c_hw_engine { + struct i2c_engine base; + const struct i2c_hw_engine_funcs *funcs; + + /* Values below are in kilohertz */ + uint32_t original_speed; + uint32_t default_speed; +}; + +bool dal_i2c_hw_engine_construct( + struct i2c_hw_engine *engine, + struct dc_context *ctx); + +void dal_i2c_hw_engine_destruct( + struct i2c_hw_engine *engine); + +enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( + struct i2c_hw_engine *engine, + uint32_t timeout, + enum i2c_channel_operation_result expected_result); + +bool dal_i2c_hw_engine_acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc); + +bool dal_i2c_hw_engine_submit_request( + struct engine *ptr, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction); + +enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type( + const struct engine *engine); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c new file mode 100644 index 000000000000..95bc4457d44b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c @@ -0,0 +1,610 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "engine.h" +#include "i2c_engine.h" + +/* + * Header of this unit + */ + +#include "i2c_sw_engine.h" + +/* + * Post-requisites: headers required by this unit + */ + +/* + * This unit + */ + +#define SCL false +#define SDA true + +static inline bool read_bit_from_ddc( + struct ddc *ddc, + bool data_nor_clock) +{ + uint32_t value = 0; + + if (data_nor_clock) + dal_gpio_get_value(ddc->pin_data, &value); + else + dal_gpio_get_value(ddc->pin_clock, &value); + + return (value != 0); +} + +static inline void write_bit_to_ddc( + struct ddc *ddc, + bool data_nor_clock, + bool bit) +{ + uint32_t value = bit ? 1 : 0; + + if (data_nor_clock) + dal_gpio_set_value(ddc->pin_data, value); + else + dal_gpio_set_value(ddc->pin_clock, value); +} + +static bool wait_for_scl_high( + struct dc_context *ctx, + struct ddc *ddc, + uint16_t clock_delay_div_4) +{ + uint32_t scl_retry = 0; + uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4; + + udelay(clock_delay_div_4); + + /* 3 milliseconds delay + * to wake up some displays from "low power" state. + */ + + do { + if (read_bit_from_ddc(ddc, SCL)) + return true; + + udelay(clock_delay_div_4); + + ++scl_retry; + } while (scl_retry <= scl_retry_max); + + return false; +} + +static bool start_sync( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4) +{ + uint32_t retry = 0; + + /* The I2C communications start signal is: + * the SDA going low from high, while the SCL is high. */ + + write_bit_to_ddc(ddc_handle, SCL, true); + + udelay(clock_delay_div_4); + + do { + write_bit_to_ddc(ddc_handle, SDA, true); + + if (!read_bit_from_ddc(ddc_handle, SDA)) { + ++retry; + continue; + } + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + break; + + write_bit_to_ddc(ddc_handle, SDA, false); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4); + + return true; + } while (retry <= I2C_SW_RETRIES); + + return false; +} + +static bool stop_sync( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4) +{ + uint32_t retry = 0; + + /* The I2C communications stop signal is: + * the SDA going high from low, while the SCL is high. */ + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SDA, false); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + write_bit_to_ddc(ddc_handle, SDA, true); + + do { + udelay(clock_delay_div_4); + + if (read_bit_from_ddc(ddc_handle, SDA)) + return true; + + ++retry; + } while (retry <= 2); + + return false; +} + +static bool write_byte( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4, + uint8_t byte) +{ + int32_t shift = 7; + bool ack; + + /* bits are transmitted serially, starting from MSB */ + + do { + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + write_bit_to_ddc(ddc_handle, SCL, false); + + --shift; + } while (shift >= 0); + + /* The display sends ACK by preventing the SDA from going high + * after the SCL pulse we use to send our last data bit. + * If the SDA goes high after that bit, it's a NACK */ + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SDA, true); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + /* read ACK bit */ + + ack = !read_bit_from_ddc(ddc_handle, SDA); + + udelay(clock_delay_div_4 << 1); + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4 << 1); + + return ack; +} + +static bool read_byte( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4, + uint8_t *byte, + bool more) +{ + int32_t shift = 7; + + uint8_t data = 0; + + /* The data bits are read from MSB to LSB; + * bit is read while SCL is high */ + + do { + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + if (read_bit_from_ddc(ddc_handle, SDA)) + data |= (1 << shift); + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4 << 1); + + --shift; + } while (shift >= 0); + + /* read only whole byte */ + + *byte = data; + + udelay(clock_delay_div_4); + + /* send the acknowledge bit: + * SDA low means ACK, SDA high means NACK */ + + write_bit_to_ddc(ddc_handle, SDA, !more); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SCL, true); + + if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4)) + return false; + + write_bit_to_ddc(ddc_handle, SCL, false); + + udelay(clock_delay_div_4); + + write_bit_to_ddc(ddc_handle, SDA, true); + + udelay(clock_delay_div_4); + + return true; +} + +static bool i2c_write( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4, + uint8_t address, + uint32_t length, + const uint8_t *data) +{ + uint32_t i = 0; + + if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address)) + return false; + + while (i < length) { + if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i])) + return false; + ++i; + } + + return true; +} + +static bool i2c_read( + struct dc_context *ctx, + struct ddc *ddc_handle, + uint16_t clock_delay_div_4, + uint8_t address, + uint32_t length, + uint8_t *data) +{ + uint32_t i = 0; + + if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address)) + return false; + + while (i < length) { + if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i, + i < length - 1)) + return false; + ++i; + } + + return true; +} + +/* + * @brief + * Cast 'struct i2c_engine *' + * to 'struct i2c_sw_engine *' + */ +#define FROM_I2C_ENGINE(ptr) \ + container_of((ptr), struct i2c_sw_engine, base) + +/* + * @brief + * Cast 'struct engine *' + * to 'struct i2c_sw_engine *' + */ +#define FROM_ENGINE(ptr) \ + FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base)) + +enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type( + const struct engine *engine) +{ + return I2CAUX_ENGINE_TYPE_I2C_SW; +} + +bool dal_i2c_sw_engine_submit_request( + struct engine *engine, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction) +{ + struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine); + + struct i2c_engine *base = &sw_engine->base; + + struct i2c_request_transaction_data request; + bool operation_succeeded = false; + + if (i2caux_request->operation == I2CAUX_TRANSACTION_READ) + request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_READ; + else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE) + request.action = middle_of_transaction ? + I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : + I2CAUX_TRANSACTION_ACTION_I2C_WRITE; + else { + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION; + /* in DAL2, there was no "return false" */ + return false; + } + + request.address = (uint8_t)i2caux_request->payload.address; + request.length = i2caux_request->payload.length; + request.data = i2caux_request->payload.data; + + base->funcs->submit_channel_request(base, &request); + + if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) || + (request.status == I2C_CHANNEL_OPERATION_FAILED)) + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY; + else { + enum i2c_channel_operation_result operation_result; + + do { + operation_result = + base->funcs->get_channel_status(base, NULL); + + switch (operation_result) { + case I2C_CHANNEL_OPERATION_SUCCEEDED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_SUCCEEDED; + operation_succeeded = true; + break; + case I2C_CHANNEL_OPERATION_NO_RESPONSE: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_NACK; + break; + case I2C_CHANNEL_OPERATION_TIMEOUT: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; + break; + case I2C_CHANNEL_OPERATION_FAILED: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE; + break; + default: + i2caux_request->status = + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION; + break; + } + } while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY); + } + + return operation_succeeded; +} + +uint32_t dal_i2c_sw_engine_get_speed( + const struct i2c_engine *engine) +{ + return FROM_I2C_ENGINE(engine)->speed; +} + +void dal_i2c_sw_engine_set_speed( + struct i2c_engine *engine, + uint32_t speed) +{ + struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine); + + ASSERT(speed); + + sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED; + + sw_engine->clock_delay = 1000 / sw_engine->speed; + + if (sw_engine->clock_delay < 12) + sw_engine->clock_delay = 12; +} + +bool dal_i2caux_i2c_sw_engine_acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc) +{ + enum gpio_result result; + + result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT, + GPIO_DDC_CONFIG_TYPE_MODE_I2C); + + if (result != GPIO_RESULT_OK) + return false; + + engine->base.ddc = ddc; + + return true; +} + +void dal_i2c_sw_engine_submit_channel_request( + struct i2c_engine *engine, + struct i2c_request_transaction_data *req) +{ + struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine); + + struct ddc *ddc = engine->base.ddc; + uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2; + + /* send sync (start / repeated start) */ + + bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4); + + /* process payload */ + + if (result) { + switch (req->action) { + case I2CAUX_TRANSACTION_ACTION_I2C_WRITE: + case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT: + result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4, + req->address, req->length, req->data); + break; + case I2CAUX_TRANSACTION_ACTION_I2C_READ: + case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT: + result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4, + req->address, req->length, req->data); + break; + default: + result = false; + break; + } + } + + /* send stop if not 'mot' or operation failed */ + + if (!result || + (req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || + (req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ)) + if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4)) + result = false; + + req->status = result ? + I2C_CHANNEL_OPERATION_SUCCEEDED : + I2C_CHANNEL_OPERATION_FAILED; +} + +enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status( + struct i2c_engine *engine, + uint8_t *returned_bytes) +{ + /* No arbitration with VBIOS is performed since DCE 6.0 */ + return I2C_CHANNEL_OPERATION_SUCCEEDED; +} + +void dal_i2c_sw_engine_destruct( + struct i2c_sw_engine *engine) +{ + dal_i2c_engine_destruct(&engine->base); +} + +static void destroy( + struct i2c_engine **ptr) +{ + dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr)); + + dm_free(*ptr); + *ptr = NULL; +} + +static const struct i2c_engine_funcs i2c_engine_funcs = { + .acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine, + .destroy = destroy, + .get_speed = dal_i2c_sw_engine_get_speed, + .set_speed = dal_i2c_sw_engine_set_speed, + .setup_engine = dal_i2c_engine_setup_i2c_engine, + .submit_channel_request = dal_i2c_sw_engine_submit_channel_request, + .process_channel_reply = dal_i2c_engine_process_channel_reply, + .get_channel_status = dal_i2c_sw_engine_get_channel_status, +}; + +static void release_engine( + struct engine *engine) +{ + +} + +static const struct engine_funcs engine_funcs = { + .release_engine = release_engine, + .get_engine_type = dal_i2c_sw_engine_get_engine_type, + .acquire = dal_i2c_engine_acquire, + .submit_request = dal_i2c_sw_engine_submit_request, +}; + +bool dal_i2c_sw_engine_construct( + struct i2c_sw_engine *engine, + const struct i2c_sw_engine_create_arg *arg) +{ + if (!dal_i2c_engine_construct(&engine->base, arg->ctx)) + return false; + + dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed); + engine->base.funcs = &i2c_engine_funcs; + engine->base.base.funcs = &engine_funcs; + return true; +} + +struct i2c_engine *dal_i2c_sw_engine_create( + const struct i2c_sw_engine_create_arg *arg) +{ + struct i2c_sw_engine *engine; + + if (!arg) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + engine = dm_alloc(sizeof(struct i2c_sw_engine)); + + if (!engine) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (dal_i2c_sw_engine_construct(engine, arg)) + return &engine->base; + + BREAK_TO_DEBUGGER(); + + dm_free(engine); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h new file mode 100644 index 000000000000..e0cb4c3d483d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h @@ -0,0 +1,81 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_SW_ENGINE_H__ +#define __DAL_I2C_SW_ENGINE_H__ + +enum { + I2C_SW_RETRIES = 10, + I2C_SW_SCL_READ_RETRIES = 128, + /* following value is in microseconds */ + I2C_SW_TIMEOUT_DELAY = 3000 +}; + +struct i2c_sw_engine; + +struct i2c_sw_engine { + struct i2c_engine base; + uint32_t clock_delay; + /* Values below are in KHz */ + uint32_t speed; + uint32_t default_speed; +}; + +struct i2c_sw_engine_create_arg { + uint32_t default_speed; + struct dc_context *ctx; +}; + +bool dal_i2c_sw_engine_construct( + struct i2c_sw_engine *engine, + const struct i2c_sw_engine_create_arg *arg); + +bool dal_i2caux_i2c_sw_engine_acquire_engine( + struct i2c_engine *engine, + struct ddc *ddc_handle); + +void dal_i2c_sw_engine_destruct( + struct i2c_sw_engine *engine); + +struct i2c_engine *dal_i2c_sw_engine_create( + const struct i2c_sw_engine_create_arg *arg); +enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type( + const struct engine *engine); +bool dal_i2c_sw_engine_submit_request( + struct engine *ptr, + struct i2caux_transaction_request *i2caux_request, + bool middle_of_transaction); +uint32_t dal_i2c_sw_engine_get_speed( + const struct i2c_engine *engine); +void dal_i2c_sw_engine_set_speed( + struct i2c_engine *ptr, + uint32_t speed); +void dal_i2c_sw_engine_submit_channel_request( + struct i2c_engine *ptr, + struct i2c_request_transaction_data *req); +enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status( + struct i2c_engine *engine, + uint8_t *returned_bytes); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c new file mode 100644 index 000000000000..5391655af23a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -0,0 +1,459 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/i2caux_interface.h" +#include "dc_bios_types.h" + +/* + * Header of this unit + */ + +#include "i2caux.h" + +/* + * Post-requisites: headers required by this unit + */ + +#include "engine.h" +#include "i2c_engine.h" +#include "aux_engine.h" + +/* + * This unit + */ + +#include "dce80/i2caux_dce80.h" + +#include "dce100/i2caux_dce100.h" + +#include "dce110/i2caux_dce110.h" + +#include "dce112/i2caux_dce112.h" + +#include "diagnostics/i2caux_diag.h" + +/* + * @brief + * Plain API, available publicly + */ + +struct i2caux *dal_i2caux_create( + struct dc_context *ctx) +{ + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { + return dal_i2caux_diag_fpga_create(ctx); + } + + switch (ctx->dce_version) { + case DCE_VERSION_8_0: + return dal_i2caux_dce80_create(ctx); + case DCE_VERSION_11_2: + return dal_i2caux_dce112_create(ctx); + case DCE_VERSION_11_0: + return dal_i2caux_dce110_create(ctx); + case DCE_VERSION_10_0: + return dal_i2caux_dce100_create(ctx); + default: + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +bool dal_i2caux_submit_i2c_command( + struct i2caux *i2caux, + struct ddc *ddc, + struct i2c_command *cmd) +{ + struct i2c_engine *engine; + uint8_t index_of_payload = 0; + bool result; + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!cmd) { + BREAK_TO_DEBUGGER(); + return false; + } + + /* + * default will be SW, however there is a feature flag in adapter + * service that determines whether SW i2c_engine will be available or + * not, if sw i2c is not available we will fallback to hw. This feature + * flag is set to not creating sw i2c engine for every dce except dce80 + * currently + */ + switch (cmd->engine) { + case I2C_COMMAND_ENGINE_DEFAULT: + case I2C_COMMAND_ENGINE_SW: + /* try to acquire SW engine first, + * acquire HW engine if SW engine not available */ + engine = i2caux->funcs->acquire_i2c_sw_engine(i2caux, ddc); + + if (!engine) + engine = i2caux->funcs->acquire_i2c_hw_engine( + i2caux, ddc); + break; + case I2C_COMMAND_ENGINE_HW: + default: + /* try to acquire HW engine first, + * acquire SW engine if HW engine not available */ + engine = i2caux->funcs->acquire_i2c_hw_engine(i2caux, ddc); + + if (!engine) + engine = i2caux->funcs->acquire_i2c_sw_engine( + i2caux, ddc); + } + + if (!engine) + return false; + + engine->funcs->set_speed(engine, cmd->speed); + + result = true; + + while (index_of_payload < cmd->number_of_payloads) { + bool mot = (index_of_payload != cmd->number_of_payloads - 1); + + struct i2c_payload *payload = cmd->payloads + index_of_payload; + + struct i2caux_transaction_request request = { 0 }; + + request.operation = payload->write ? + I2CAUX_TRANSACTION_WRITE : + I2CAUX_TRANSACTION_READ; + + request.payload.address_space = + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C; + request.payload.address = (payload->address << 1) | + !payload->write; + request.payload.length = payload->length; + request.payload.data = payload->data; + + if (!engine->base.funcs->submit_request( + &engine->base, &request, mot)) { + result = false; + break; + } + + ++index_of_payload; + } + + i2caux->funcs->release_engine(i2caux, &engine->base); + + return result; +} + +bool dal_i2caux_submit_aux_command( + struct i2caux *i2caux, + struct ddc *ddc, + struct aux_command *cmd) +{ + struct aux_engine *engine; + uint8_t index_of_payload = 0; + bool result; + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!cmd) { + BREAK_TO_DEBUGGER(); + return false; + } + + engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc); + + if (!engine) + return false; + + engine->delay = cmd->defer_delay; + engine->max_defer_write_retry = cmd->max_defer_write_retry; + + result = true; + + while (index_of_payload < cmd->number_of_payloads) { + bool mot = (index_of_payload != cmd->number_of_payloads - 1); + + struct aux_payload *payload = cmd->payloads + index_of_payload; + + struct i2caux_transaction_request request = { 0 }; + + request.operation = payload->write ? + I2CAUX_TRANSACTION_WRITE : + I2CAUX_TRANSACTION_READ; + + if (payload->i2c_over_aux) { + request.payload.address_space = + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C; + + request.payload.address = (payload->address << 1) | + !payload->write; + } else { + request.payload.address_space = + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD; + + request.payload.address = payload->address; + } + + request.payload.length = payload->length; + request.payload.data = payload->data; + + if (!engine->base.funcs->submit_request( + &engine->base, &request, mot)) { + result = false; + break; + } + + ++index_of_payload; + } + + i2caux->funcs->release_engine(i2caux, &engine->base); + + return result; +} + +static bool get_hw_supported_ddc_line( + struct ddc *ddc, + enum gpio_ddc_line *line) +{ + enum gpio_ddc_line line_found; + + if (!ddc) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!ddc->hw_info.hw_supported) + return false; + + line_found = dal_ddc_get_line(ddc); + + if (line_found >= GPIO_DDC_LINE_COUNT) + return false; + + *line = line_found; + + return true; +} + +void dal_i2caux_configure_aux( + struct i2caux *i2caux, + struct ddc *ddc, + union aux_config cfg) +{ + struct aux_engine *engine = + i2caux->funcs->acquire_aux_engine(i2caux, ddc); + + if (!engine) + return; + + engine->funcs->configure(engine, cfg); + + i2caux->funcs->release_engine(i2caux, &engine->base); +} + +void dal_i2caux_destroy( + struct i2caux **i2caux) +{ + if (!i2caux || !*i2caux) { + BREAK_TO_DEBUGGER(); + return; + } + + (*i2caux)->funcs->destroy(i2caux); + + *i2caux = NULL; +} + +/* + * @brief + * An utility function used by 'struct i2caux' and its descendants + */ + +uint32_t dal_i2caux_get_reference_clock( + struct dc_bios *bios) +{ + struct firmware_info info = { { 0 } }; + + if (bios->funcs->get_firmware_info(bios, &info) != BP_RESULT_OK) + return 0; + + return info.pll_info.crystal_frequency; +} + +/* + * @brief + * i2caux + */ + +enum { + /* following are expressed in KHz */ + DEFAULT_I2C_SW_SPEED = 50, + DEFAULT_I2C_HW_SPEED = 50, + + /* This is the timeout as defined in DP 1.2a, + * 2.3.4 "Detailed uPacket TX AUX CH State Description". */ + AUX_TIMEOUT_PERIOD = 400, + + /* Ideally, the SW timeout should be just above 550usec + * which is programmed in HW. + * But the SW timeout of 600usec is not reliable, + * because on some systems, delay_in_microseconds() + * returns faster than it should. + * EPR #379763: by trial-and-error on different systems, + * 700usec is the minimum reliable SW timeout for polling + * the AUX_SW_STATUS.AUX_SW_DONE bit. + * This timeout expires *only* when there is + * AUX Error or AUX Timeout conditions - not during normal operation. + * During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set + * at most within ~240usec. That means, + * increasing this timeout will not affect normal operation, + * and we'll timeout after + * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 1600usec. + * This timeout is especially important for + * resume from S3 and CTS. */ + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4 +}; + +struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine( + struct i2caux *i2caux, + struct ddc *ddc) +{ + enum gpio_ddc_line line; + struct i2c_engine *engine = NULL; + + if (get_hw_supported_ddc_line(ddc, &line)) + engine = i2caux->i2c_sw_engines[line]; + + if (!engine) + engine = i2caux->i2c_generic_sw_engine; + + if (!engine) + return NULL; + + if (!engine->base.funcs->acquire(&engine->base, ddc)) + return NULL; + + return engine; +} + +struct aux_engine *dal_i2caux_acquire_aux_engine( + struct i2caux *i2caux, + struct ddc *ddc) +{ + enum gpio_ddc_line line; + struct aux_engine *engine; + + if (!get_hw_supported_ddc_line(ddc, &line)) + return NULL; + + engine = i2caux->aux_engines[line]; + + if (!engine) + return NULL; + + if (!engine->base.funcs->acquire(&engine->base, ddc)) + return NULL; + + return engine; +} + +void dal_i2caux_release_engine( + struct i2caux *i2caux, + struct engine *engine) +{ + engine->funcs->release_engine(engine); + + dal_ddc_close(engine->ddc); + + engine->ddc = NULL; +} + +bool dal_i2caux_construct( + struct i2caux *i2caux, + struct dc_context *ctx) +{ + uint32_t i = 0; + + i2caux->ctx = ctx; + do { + i2caux->i2c_sw_engines[i] = NULL; + i2caux->i2c_hw_engines[i] = NULL; + i2caux->aux_engines[i] = NULL; + + ++i; + } while (i < GPIO_DDC_LINE_COUNT); + + i2caux->i2c_generic_sw_engine = NULL; + i2caux->i2c_generic_hw_engine = NULL; + + i2caux->aux_timeout_period = + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD; + + i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; + i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; + + return true; +} + +void dal_i2caux_destruct( + struct i2caux *i2caux) +{ + uint32_t i = 0; + + if (i2caux->i2c_generic_hw_engine) + i2caux->i2c_generic_hw_engine->funcs->destroy( + &i2caux->i2c_generic_hw_engine); + + if (i2caux->i2c_generic_sw_engine) + i2caux->i2c_generic_sw_engine->funcs->destroy( + &i2caux->i2c_generic_sw_engine); + + do { + if (i2caux->aux_engines[i]) + i2caux->aux_engines[i]->funcs->destroy( + &i2caux->aux_engines[i]); + + if (i2caux->i2c_hw_engines[i]) + i2caux->i2c_hw_engines[i]->funcs->destroy( + &i2caux->i2c_hw_engines[i]); + + if (i2caux->i2c_sw_engines[i]) + i2caux->i2c_sw_engines[i]->funcs->destroy( + &i2caux->i2c_sw_engines[i]); + + ++i; + } while (i < GPIO_DDC_LINE_COUNT); +} + diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h new file mode 100644 index 000000000000..bc20de3da1c4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h @@ -0,0 +1,122 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_H__ +#define __DAL_I2C_AUX_H__ + +uint32_t dal_i2caux_get_reference_clock( + struct dc_bios *bios); + +struct i2caux; + +struct engine; + +struct i2caux_funcs { + void (*destroy)(struct i2caux **ptr); + struct i2c_engine * (*acquire_i2c_sw_engine)( + struct i2caux *i2caux, + struct ddc *ddc); + struct i2c_engine * (*acquire_i2c_hw_engine)( + struct i2caux *i2caux, + struct ddc *ddc); + struct aux_engine * (*acquire_aux_engine)( + struct i2caux *i2caux, + struct ddc *ddc); + void (*release_engine)( + struct i2caux *i2caux, + struct engine *engine); +}; + +struct i2c_engine; +struct aux_engine; + +struct i2caux { + struct dc_context *ctx; + const struct i2caux_funcs *funcs; + /* On ASIC we have certain amount of lines with HW DDC engine + * (4, 6, or maybe more in the future). + * For every such line, we create separate HW DDC engine + * (since we have these engines in HW) and separate SW DDC engine + * (to allow concurrent use of few lines). + * In similar way we have AUX engines. */ + + /* I2C SW engines, per DDC line. + * Only lines with HW DDC support will be initialized */ + struct i2c_engine *i2c_sw_engines[GPIO_DDC_LINE_COUNT]; + + /* I2C HW engines, per DDC line. + * Only lines with HW DDC support will be initialized */ + struct i2c_engine *i2c_hw_engines[GPIO_DDC_LINE_COUNT]; + + /* AUX engines, per DDC line. + * Only lines with HW AUX support will be initialized */ + struct aux_engine *aux_engines[GPIO_DDC_LINE_COUNT]; + + /* For all other lines, we can use + * single instance of generic I2C HW engine + * (since in HW, there is single instance of it) + * or single instance of generic I2C SW engine. + * AUX is not supported for other lines. */ + + /* General-purpose I2C SW engine. + * Can be assigned dynamically to any line per transaction */ + struct i2c_engine *i2c_generic_sw_engine; + + /* General-purpose I2C generic HW engine. + * Can be assigned dynamically to almost any line per transaction */ + struct i2c_engine *i2c_generic_hw_engine; + + /* [anaumov] in DAL2, there is a Mutex */ + + uint32_t aux_timeout_period; + + /* expressed in KHz */ + uint32_t default_i2c_sw_speed; + uint32_t default_i2c_hw_speed; +}; + +bool dal_i2caux_construct( + struct i2caux *i2caux, + struct dc_context *ctx); + +void dal_i2caux_release_engine( + struct i2caux *i2caux, + struct engine *engine); + +void dal_i2caux_destruct( + struct i2caux *i2caux); + +void dal_i2caux_destroy( + struct i2caux **ptr); + +struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine( + struct i2caux *i2caux, + struct ddc *ddc); + +struct aux_engine *dal_i2caux_acquire_aux_engine( + struct i2caux *i2caux, + struct ddc *ddc); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h new file mode 100644 index 000000000000..f9b871b6199b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h @@ -0,0 +1,503 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * Bandwidth and Watermark calculations interface. + * (Refer to "DCEx_mode_support.xlsm" from Perforce.) + */ +#ifndef __BANDWIDTH_CALCS_H__ +#define __BANDWIDTH_CALCS_H__ + +#include "bw_fixed.h" + +struct pipe_ctx; + +enum bw_calcs_version { + BW_CALCS_VERSION_INVALID, + BW_CALCS_VERSION_CARRIZO, + BW_CALCS_VERSION_POLARIS10, + BW_CALCS_VERSION_POLARIS11, + BW_CALCS_VERSION_STONEY, +}; + +/******************************************************************************* + * There are three types of input into Calculations: + * 1. per-DCE static values - these are "hardcoded" properties of the DCEIP + * 2. board-level values - these are generally coming from VBIOS parser + * 3. mode/configuration values - depending Mode, Scaling number of Displays etc. + ******************************************************************************/ + +enum bw_defines { + //Common + bw_def_no = 0, + bw_def_none = 0, + bw_def_yes = 1, + bw_def_ok = 1, + bw_def_high = 2, + bw_def_mid = 1, + bw_def_low = 0, + + //Internal + bw_defs_start = 255, + bw_def_underlay422, + bw_def_underlay420_luma, + bw_def_underlay420_chroma, + bw_def_underlay444, + bw_def_graphics, + bw_def_display_write_back420_luma, + bw_def_display_write_back420_chroma, + bw_def_portrait, + bw_def_hsr_mtn_4, + bw_def_hsr_mtn_h_taps, + bw_def_ceiling__h_taps_div_4___meq_hsr, + bw_def_invalid_linear_or_stereo_mode, + bw_def_invalid_rotation_or_bpp_or_stereo, + bw_def_vsr_mtn_v_taps, + bw_def_vsr_mtn_4, + bw_def_auto, + bw_def_manual, + bw_def_exceeded_allowed_maximum_sclk, + bw_def_exceeded_allowed_page_close_open, + bw_def_exceeded_allowed_outstanding_pte_req_queue_size, + bw_def_exceeded_allowed_maximum_bw, + bw_def_landscape, + + //Panning and bezel + bw_def_any_lines, + + //Underlay mode + bw_def_underlay_only, + bw_def_blended, + bw_def_blend, + + //Stereo mode + bw_def_mono, + bw_def_side_by_side, + bw_def_top_bottom, + + //Underlay surface type + bw_def_420, + bw_def_422, + bw_def_444, + + //Tiling mode + bw_def_linear, + bw_def_tiled, + bw_def_array_linear_general, + bw_def_array_linear_aligned, + bw_def_rotated_micro_tiling, + bw_def_display_micro_tiling, + + //Memory type + bw_def_gddr5, + bw_def_hbm, + + //Voltage + bw_def_high_no_nbp_state_change, + bw_def_0_72, + bw_def_0_8, + bw_def_0_9, + + bw_def_notok = -1, + bw_def_na = -1 +}; + +struct bw_calcs_dceip { + enum bw_calcs_version version; + bool large_cursor; + uint32_t cursor_max_outstanding_group_num; + bool dmif_pipe_en_fbc_chunk_tracker; + struct bw_fixed dmif_request_buffer_size; + uint32_t lines_interleaved_into_lb; + uint32_t low_power_tiling_mode; + uint32_t chunk_width; + uint32_t number_of_graphics_pipes; + uint32_t number_of_underlay_pipes; + bool display_write_back_supported; + bool argb_compression_support; + struct bw_fixed underlay_vscaler_efficiency6_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency8_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency10_bit_per_component; + struct bw_fixed underlay_vscaler_efficiency12_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency6_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency8_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency10_bit_per_component; + struct bw_fixed graphics_vscaler_efficiency12_bit_per_component; + struct bw_fixed alpha_vscaler_efficiency; + uint32_t max_dmif_buffer_allocated; + uint32_t graphics_dmif_size; + uint32_t underlay_luma_dmif_size; + uint32_t underlay_chroma_dmif_size; + bool pre_downscaler_enabled; + bool underlay_downscale_prefetch_enabled; + struct bw_fixed lb_write_pixels_per_dispclk; + struct bw_fixed lb_size_per_component444; + bool graphics_lb_nodownscaling_multi_line_prefetching; + struct bw_fixed stutter_and_dram_clock_state_change_gated_before_cursor; + struct bw_fixed underlay420_luma_lb_size_per_component; + struct bw_fixed underlay420_chroma_lb_size_per_component; + struct bw_fixed underlay422_lb_size_per_component; + struct bw_fixed cursor_chunk_width; + struct bw_fixed cursor_dcp_buffer_lines; + struct bw_fixed underlay_maximum_width_efficient_for_tiling; + struct bw_fixed underlay_maximum_height_efficient_for_tiling; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation; + struct bw_fixed minimum_outstanding_pte_request_limit; + struct bw_fixed maximum_total_outstanding_pte_requests_allowed_by_saw; + bool limit_excessive_outstanding_dmif_requests; + struct bw_fixed linear_mode_line_request_alternation_slice; + uint32_t scatter_gather_lines_of_pte_prefetching_in_linear_mode; + uint32_t display_write_back420_luma_mcifwr_buffer_size; + uint32_t display_write_back420_chroma_mcifwr_buffer_size; + struct bw_fixed request_efficiency; + struct bw_fixed dispclk_per_request; + struct bw_fixed dispclk_ramping_factor; + struct bw_fixed display_pipe_throughput_factor; + uint32_t scatter_gather_pte_request_rows_in_tiling_mode; + struct bw_fixed mcifwr_all_surfaces_burst_time; +}; + +struct bw_calcs_vbios { + enum bw_defines memory_type; + uint32_t dram_channel_width_in_bits; + uint32_t number_of_dram_channels; + uint32_t number_of_dram_banks; + struct bw_fixed low_yclk; /*m_hz*/ + struct bw_fixed mid_yclk; /*m_hz*/ + struct bw_fixed high_yclk; /*m_hz*/ + struct bw_fixed low_sclk; /*m_hz*/ + struct bw_fixed mid1_sclk; /*m_hz*/ + struct bw_fixed mid2_sclk; /*m_hz*/ + struct bw_fixed mid3_sclk; /*m_hz*/ + struct bw_fixed mid4_sclk; /*m_hz*/ + struct bw_fixed mid5_sclk; /*m_hz*/ + struct bw_fixed mid6_sclk; /*m_hz*/ + struct bw_fixed high_sclk; /*m_hz*/ + struct bw_fixed low_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed mid_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed high_voltage_max_dispclk; /*m_hz*/ + struct bw_fixed low_voltage_max_phyclk; + struct bw_fixed mid_voltage_max_phyclk; + struct bw_fixed high_voltage_max_phyclk; + struct bw_fixed data_return_bus_width; + struct bw_fixed trc; + struct bw_fixed dmifmc_urgent_latency; + struct bw_fixed stutter_self_refresh_exit_latency; + struct bw_fixed stutter_self_refresh_entry_latency; + struct bw_fixed nbp_state_change_latency; + struct bw_fixed mcifwrmc_urgent_latency; + bool scatter_gather_enable; + struct bw_fixed down_spread_percentage; + uint32_t cursor_width; + uint32_t average_compression_rate; + uint32_t number_of_request_slots_gmc_reserves_for_dmif_per_channel; + struct bw_fixed blackout_duration; + struct bw_fixed maximum_blackout_recovery_time; +}; + +/******************************************************************************* + * Temporary data structure(s). + ******************************************************************************/ +#define maximum_number_of_surfaces 12 +/*Units : MHz, us */ + +struct bw_calcs_data { + /* data for all displays */ + uint32_t number_of_displays; + enum bw_defines underlay_surface_type; + enum bw_defines panning_and_bezel_adjustment; + enum bw_defines graphics_tiling_mode; + uint32_t graphics_lb_bpc; + uint32_t underlay_lb_bpc; + enum bw_defines underlay_tiling_mode; + enum bw_defines d0_underlay_mode; + bool d1_display_write_back_dwb_enable; + enum bw_defines d1_underlay_mode; + + bool cpup_state_change_enable; + bool cpuc_state_change_enable; + bool nbp_state_change_enable; + bool stutter_mode_enable; + uint32_t y_clk_level; + uint32_t sclk_level; + uint32_t number_of_underlay_surfaces; + uint32_t number_of_dram_wrchannels; + uint32_t chunk_request_delay; + uint32_t number_of_dram_channels; + enum bw_defines underlay_micro_tile_mode; + enum bw_defines graphics_micro_tile_mode; + struct bw_fixed max_phyclk; + struct bw_fixed dram_efficiency; + struct bw_fixed src_width_after_surface_type; + struct bw_fixed src_height_after_surface_type; + struct bw_fixed hsr_after_surface_type; + struct bw_fixed vsr_after_surface_type; + struct bw_fixed src_width_after_rotation; + struct bw_fixed src_height_after_rotation; + struct bw_fixed hsr_after_rotation; + struct bw_fixed vsr_after_rotation; + struct bw_fixed source_height_pixels; + struct bw_fixed hsr_after_stereo; + struct bw_fixed vsr_after_stereo; + struct bw_fixed source_width_in_lb; + struct bw_fixed lb_line_pitch; + struct bw_fixed underlay_maximum_source_efficient_for_tiling; + struct bw_fixed num_lines_at_frame_start; + struct bw_fixed min_dmif_size_in_time; + struct bw_fixed min_mcifwr_size_in_time; + struct bw_fixed total_requests_for_dmif_size; + struct bw_fixed peak_pte_request_to_eviction_ratio_limiting; + struct bw_fixed useful_pte_per_pte_request; + struct bw_fixed scatter_gather_pte_request_rows; + struct bw_fixed scatter_gather_row_height; + struct bw_fixed scatter_gather_pte_requests_in_vblank; + struct bw_fixed inefficient_linear_pitch_in_bytes; + struct bw_fixed cursor_total_data; + struct bw_fixed cursor_total_request_groups; + struct bw_fixed scatter_gather_total_pte_requests; + struct bw_fixed scatter_gather_total_pte_request_groups; + struct bw_fixed tile_width_in_pixels; + struct bw_fixed dmif_total_number_of_data_request_page_close_open; + struct bw_fixed mcifwr_total_number_of_data_request_page_close_open; + struct bw_fixed bytes_per_page_close_open; + struct bw_fixed mcifwr_total_page_close_open_time; + struct bw_fixed total_requests_for_adjusted_dmif_size; + struct bw_fixed total_dmifmc_urgent_trips; + struct bw_fixed total_dmifmc_urgent_latency; + struct bw_fixed total_display_reads_required_data; + struct bw_fixed total_display_reads_required_dram_access_data; + struct bw_fixed total_display_writes_required_data; + struct bw_fixed total_display_writes_required_dram_access_data; + struct bw_fixed display_reads_required_data; + struct bw_fixed display_reads_required_dram_access_data; + struct bw_fixed dmif_total_page_close_open_time; + struct bw_fixed min_cursor_memory_interface_buffer_size_in_time; + struct bw_fixed min_read_buffer_size_in_time; + struct bw_fixed display_reads_time_for_data_transfer; + struct bw_fixed display_writes_time_for_data_transfer; + struct bw_fixed dmif_required_dram_bandwidth; + struct bw_fixed mcifwr_required_dram_bandwidth; + struct bw_fixed required_dmifmc_urgent_latency_for_page_close_open; + struct bw_fixed required_mcifmcwr_urgent_latency; + struct bw_fixed required_dram_bandwidth_gbyte_per_second; + struct bw_fixed dram_bandwidth; + struct bw_fixed dmif_required_sclk; + struct bw_fixed mcifwr_required_sclk; + struct bw_fixed required_sclk; + struct bw_fixed downspread_factor; + struct bw_fixed v_scaler_efficiency; + struct bw_fixed scaler_limits_factor; + struct bw_fixed display_pipe_pixel_throughput; + struct bw_fixed total_dispclk_required_with_ramping; + struct bw_fixed total_dispclk_required_without_ramping; + struct bw_fixed total_read_request_bandwidth; + struct bw_fixed total_write_request_bandwidth; + struct bw_fixed dispclk_required_for_total_read_request_bandwidth; + struct bw_fixed total_dispclk_required_with_ramping_with_request_bandwidth; + struct bw_fixed total_dispclk_required_without_ramping_with_request_bandwidth; + struct bw_fixed dispclk; + struct bw_fixed blackout_recovery_time; + struct bw_fixed min_pixels_per_data_fifo_entry; + struct bw_fixed sclk_deep_sleep; + struct bw_fixed chunk_request_time; + struct bw_fixed cursor_request_time; + struct bw_fixed line_source_pixels_transfer_time; + struct bw_fixed dmifdram_access_efficiency; + struct bw_fixed mcifwrdram_access_efficiency; + struct bw_fixed total_average_bandwidth_no_compression; + struct bw_fixed total_average_bandwidth; + struct bw_fixed total_stutter_cycle_duration; + struct bw_fixed stutter_burst_time; + struct bw_fixed time_in_self_refresh; + struct bw_fixed stutter_efficiency; + struct bw_fixed worst_number_of_trips_to_memory; + struct bw_fixed immediate_flip_time; + struct bw_fixed latency_for_non_dmif_clients; + struct bw_fixed latency_for_non_mcifwr_clients; + struct bw_fixed dmifmc_urgent_latency_supported_in_high_sclk_and_yclk; + struct bw_fixed nbp_state_dram_speed_change_margin; + struct bw_fixed display_reads_time_for_data_transfer_and_urgent_latency; + struct bw_fixed dram_speed_change_margin; + struct bw_fixed min_vblank_dram_speed_change_margin; + struct bw_fixed min_stutter_refresh_duration; + uint32_t total_stutter_dmif_buffer_size; + uint32_t total_bytes_requested; + uint32_t min_stutter_dmif_buffer_size; + uint32_t num_stutter_bursts; + struct bw_fixed v_blank_nbp_state_dram_speed_change_latency_supported; + struct bw_fixed nbp_state_dram_speed_change_latency_supported; + bool fbc_en[maximum_number_of_surfaces]; + bool lpt_en[maximum_number_of_surfaces]; + bool displays_match_flag[maximum_number_of_surfaces]; + bool use_alpha[maximum_number_of_surfaces]; + bool orthogonal_rotation[maximum_number_of_surfaces]; + bool enable[maximum_number_of_surfaces]; + bool access_one_channel_only[maximum_number_of_surfaces]; + bool scatter_gather_enable_for_pipe[maximum_number_of_surfaces]; + bool interlace_mode[maximum_number_of_surfaces]; + bool display_pstate_change_enable[maximum_number_of_surfaces]; + bool line_buffer_prefetch[maximum_number_of_surfaces]; + uint32_t bytes_per_pixel[maximum_number_of_surfaces]; + uint32_t max_chunks_non_fbc_mode[maximum_number_of_surfaces]; + uint32_t lb_bpc[maximum_number_of_surfaces]; + uint32_t output_bpphdmi[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr2[maximum_number_of_surfaces]; + uint32_t output_bppdp4_lane_hbr3[maximum_number_of_surfaces]; + enum bw_defines stereo_mode[maximum_number_of_surfaces]; + struct bw_fixed dmif_buffer_transfer_time[maximum_number_of_surfaces]; + struct bw_fixed displays_with_same_mode[maximum_number_of_surfaces]; + struct bw_fixed stutter_dmif_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed stutter_refresh_duration[maximum_number_of_surfaces]; + struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces]; + struct bw_fixed stutter_entry_watermark[maximum_number_of_surfaces]; + struct bw_fixed h_total[maximum_number_of_surfaces]; + struct bw_fixed v_total[maximum_number_of_surfaces]; + struct bw_fixed pixel_rate[maximum_number_of_surfaces]; + struct bw_fixed src_width[maximum_number_of_surfaces]; + struct bw_fixed pitch_in_pixels[maximum_number_of_surfaces]; + struct bw_fixed pitch_in_pixels_after_surface_type[maximum_number_of_surfaces]; + struct bw_fixed src_height[maximum_number_of_surfaces]; + struct bw_fixed scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed h_taps[maximum_number_of_surfaces]; + struct bw_fixed v_taps[maximum_number_of_surfaces]; + struct bw_fixed h_scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed v_scale_ratio[maximum_number_of_surfaces]; + struct bw_fixed rotation_angle[maximum_number_of_surfaces]; + struct bw_fixed compression_rate[maximum_number_of_surfaces]; + struct bw_fixed hsr[maximum_number_of_surfaces]; + struct bw_fixed vsr[maximum_number_of_surfaces]; + struct bw_fixed source_width_rounded_up_to_chunks[maximum_number_of_surfaces]; + struct bw_fixed source_width_pixels[maximum_number_of_surfaces]; + struct bw_fixed source_height_rounded_up_to_chunks[maximum_number_of_surfaces]; + struct bw_fixed display_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed request_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed bytes_per_request[maximum_number_of_surfaces]; + struct bw_fixed useful_bytes_per_request[maximum_number_of_surfaces]; + struct bw_fixed lines_interleaved_in_mem_access[maximum_number_of_surfaces]; + struct bw_fixed latency_hiding_lines[maximum_number_of_surfaces]; + struct bw_fixed lb_partitions[maximum_number_of_surfaces]; + struct bw_fixed lb_partitions_max[maximum_number_of_surfaces]; + struct bw_fixed dispclk_required_with_ramping[maximum_number_of_surfaces]; + struct bw_fixed dispclk_required_without_ramping[maximum_number_of_surfaces]; + struct bw_fixed data_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed outstanding_chunk_request_limit[maximum_number_of_surfaces]; + struct bw_fixed urgent_watermark[maximum_number_of_surfaces]; + struct bw_fixed nbp_state_change_watermark[maximum_number_of_surfaces]; + struct bw_fixed v_filter_init[maximum_number_of_surfaces]; + struct bw_fixed stutter_cycle_duration[maximum_number_of_surfaces]; + struct bw_fixed average_bandwidth[maximum_number_of_surfaces]; + struct bw_fixed average_bandwidth_no_compression[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_pte_request_limit[maximum_number_of_surfaces]; + struct bw_fixed lb_size_per_component[maximum_number_of_surfaces]; + struct bw_fixed memory_chunk_size_in_bytes[maximum_number_of_surfaces]; + struct bw_fixed pipe_chunk_size_in_bytes[maximum_number_of_surfaces]; + struct bw_fixed number_of_trips_to_memory_for_getting_apte_row[maximum_number_of_surfaces]; + struct bw_fixed adjusted_data_buffer_size[maximum_number_of_surfaces]; + struct bw_fixed adjusted_data_buffer_size_in_memory[maximum_number_of_surfaces]; + struct bw_fixed pixels_per_data_fifo_entry[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_pte_requests_in_row[maximum_number_of_surfaces]; + struct bw_fixed pte_request_per_chunk[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_page_width[maximum_number_of_surfaces]; + struct bw_fixed scatter_gather_page_height[maximum_number_of_surfaces]; + struct bw_fixed lb_lines_in_per_line_out_in_beginning_of_frame[maximum_number_of_surfaces]; + struct bw_fixed lb_lines_in_per_line_out_in_middle_of_frame[maximum_number_of_surfaces]; + struct bw_fixed cursor_width_pixels[maximum_number_of_surfaces]; + struct bw_fixed minimum_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed maximum_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed minimum_latency_hiding_with_cursor[maximum_number_of_surfaces]; + struct bw_fixed maximum_latency_hiding_with_cursor[maximum_number_of_surfaces]; + struct bw_fixed src_pixels_for_first_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_pixels_for_last_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_data_for_first_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed src_data_for_last_output_pixel[maximum_number_of_surfaces]; + struct bw_fixed active_time[maximum_number_of_surfaces]; + struct bw_fixed horizontal_blank_and_chunk_granularity_factor[maximum_number_of_surfaces]; + struct bw_fixed cursor_latency_hiding[maximum_number_of_surfaces]; + struct bw_fixed v_blank_dram_speed_change_margin[maximum_number_of_surfaces]; + uint32_t num_displays_with_margin[3][8]; + struct bw_fixed dmif_burst_time[3][8]; + struct bw_fixed mcifwr_burst_time[3][8]; + struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][8]; + struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][8]; + struct bw_fixed min_dram_speed_change_margin[3][8]; + struct bw_fixed dispclk_required_for_dram_speed_change[3][8]; + struct bw_fixed blackout_duration_margin[3][8]; + struct bw_fixed dispclk_required_for_blackout_duration[3][8]; + struct bw_fixed dispclk_required_for_blackout_recovery[3][8]; + struct bw_fixed dmif_required_sclk_for_urgent_latency[6]; +}; + +/******************************************************************************* + * Output data structures. + ******************************************************************************/ +struct bw_watermarks { + uint32_t a_mark; + uint32_t b_mark; + uint32_t c_mark; + uint32_t d_mark; +}; + +struct bw_calcs_output { + bool cpuc_state_change_enable; + bool cpup_state_change_enable; + bool stutter_mode_enable; + bool nbp_state_change_enable; + bool all_displays_in_sync; + struct bw_watermarks urgent_wm_ns[6]; + struct bw_watermarks stutter_exit_wm_ns[6]; + struct bw_watermarks nbp_state_change_wm_ns[6]; + uint32_t required_sclk; + uint32_t required_sclk_deep_sleep; + uint32_t required_yclk; + uint32_t dispclk_khz; + int blackout_recovery_time_us; +}; + +/** + * Initialize structures with data which will NOT change at runtime. + */ +void bw_calcs_init( + struct bw_calcs_dceip *bw_dceip, + struct bw_calcs_vbios *bw_vbios, + enum bw_calcs_version version); + +/** + * Return: + * true - Display(s) configuration supported. + * In this case 'calcs_output' contains data for HW programming + * false - Display(s) configuration not supported (not enough bandwidth). + */ +bool bw_calcs( + struct dc_context *ctx, + const struct bw_calcs_dceip *dceip, + const struct bw_calcs_vbios *vbios, + const struct pipe_ctx *pipe, + int pipe_count, + struct bw_calcs_output *calcs_output); + +#endif /* __BANDWIDTH_CALCS_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h new file mode 100644 index 000000000000..b31d07a57c31 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h @@ -0,0 +1,63 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef BW_FIXED_H_ +#define BW_FIXED_H_ + +struct bw_fixed { + int64_t value; +}; + +struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3); + +struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3); + +struct bw_fixed bw_int_to_fixed(int64_t value); + +int32_t bw_fixed_to_int(struct bw_fixed value); + +struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum); + +struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw); + +struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2); + +struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2); +struct bw_fixed bw_floor2(const struct bw_fixed arg, const struct bw_fixed significance); +struct bw_fixed bw_ceil2(const struct bw_fixed arg, const struct bw_fixed significance); + +bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2); +bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2); + +#endif //BW_FIXED_H_ diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h new file mode 100644 index 000000000000..c91c7815ec6e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h @@ -0,0 +1,178 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_CLOCK_SOURCE_H__ +#define __DC_CLOCK_SOURCE_H__ + +#include "dc_types.h" +#include "include/grph_object_id.h" +#include "include/bios_parser_types.h" + +struct clock_source; + +struct spread_spectrum_data { + uint32_t percentage; /*> In unit of 0.01% or 0.001%*/ + uint32_t percentage_divider; /*> 100 or 1000 */ + uint32_t freq_range_khz; + uint32_t modulation_freq_hz; + + struct spread_spectrum_flags flags; +}; + +struct delta_sigma_data { + uint32_t feedback_amount; + uint32_t nfrac_amount; + uint32_t ds_frac_size; + uint32_t ds_frac_amount; +}; + +/** + * Pixel Clock Parameters structure + * These parameters are required as input + * when calculating Pixel Clock Dividers for requested Pixel Clock + */ +struct pixel_clk_flags { + uint32_t ENABLE_SS:1; + uint32_t DISPLAY_BLANKED:1; + uint32_t PROGRAM_PIXEL_CLOCK:1; + uint32_t PROGRAM_ID_CLOCK:1; + uint32_t SUPPORT_YCBCR420:1; +}; + +/** + * Display Port HW De spread of Reference Clock related Parameters structure + * Store it once at boot for later usage + */ +struct csdp_ref_clk_ds_params { + bool hw_dso_n_dp_ref_clk; +/* Flag for HW De Spread enabled (if enabled SS on DP Reference Clock)*/ + uint32_t avg_dp_ref_clk_khz; +/* Average DP Reference clock (in KHz)*/ + uint32_t ss_percentage_on_dp_ref_clk; +/* DP Reference clock SS percentage + * (not to be mixed with DP IDCLK SS from PLL Settings)*/ + uint32_t ss_percentage_divider; +/* DP Reference clock SS percentage divider */ +}; + +struct pixel_clk_params { + uint32_t requested_pix_clk; /* in KHz */ +/*> Requested Pixel Clock + * (based on Video Timing standard used for requested mode)*/ + uint32_t requested_sym_clk; /* in KHz */ +/*> Requested Sym Clock (relevant only for display port)*/ + uint32_t dp_ref_clk; /* in KHz */ +/*> DP reference clock - calculated only for DP signal for specific cases*/ + struct graphics_object_id encoder_object_id; +/*> Encoder object Id - needed by VBIOS Exec table*/ + enum signal_type signal_type; +/*> signalType -> Encoder Mode - needed by VBIOS Exec table*/ + enum controller_id controller_id; +/*> ControllerId - which controller using this PLL*/ + enum dc_color_depth color_depth; + struct csdp_ref_clk_ds_params de_spread_params; +/*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/ + + struct pixel_clk_flags flags; +}; + +/** + * Pixel Clock Dividers structure with desired Pixel Clock + * (adjusted after VBIOS exec table), + * with actually calculated Clock and reference Crystal frequency + */ +struct pll_settings { + uint32_t actual_pix_clk; + uint32_t adjusted_pix_clk; + uint32_t calculated_pix_clk; + uint32_t vco_freq; + uint32_t reference_freq; + uint32_t reference_divider; + uint32_t feedback_divider; + uint32_t fract_feedback_divider; + uint32_t pix_clk_post_divider; + uint32_t ss_percentage; + bool use_external_clk; +}; + +struct calc_pll_clock_source_init_data { + struct dc_bios *bp; + uint32_t min_pix_clk_pll_post_divider; + uint32_t max_pix_clk_pll_post_divider; + uint32_t min_pll_ref_divider; + uint32_t max_pll_ref_divider; + uint32_t min_override_input_pxl_clk_pll_freq_khz; +/* if not 0, override the firmware info */ + + uint32_t max_override_input_pxl_clk_pll_freq_khz; +/* if not 0, override the firmware info */ + + uint32_t num_fract_fb_divider_decimal_point; +/* number of decimal point for fractional feedback divider value */ + + uint32_t num_fract_fb_divider_decimal_point_precision; +/* number of decimal point to round off for fractional feedback divider value*/ + struct dc_context *ctx; + +}; + +struct calc_pll_clock_source { + uint32_t ref_freq_khz; + uint32_t min_pix_clock_pll_post_divider; + uint32_t max_pix_clock_pll_post_divider; + uint32_t min_pll_ref_divider; + uint32_t max_pll_ref_divider; + + uint32_t max_vco_khz; + uint32_t min_vco_khz; + uint32_t min_pll_input_freq_khz; + uint32_t max_pll_input_freq_khz; + + uint32_t fract_fb_divider_decimal_points_num; + uint32_t fract_fb_divider_factor; + uint32_t fract_fb_divider_precision; + uint32_t fract_fb_divider_precision_factor; + struct dc_context *ctx; +}; + +struct clock_source_funcs { + bool (*cs_power_down)( + struct clock_source *); + bool (*program_pix_clk)(struct clock_source *, + struct pixel_clk_params *, struct pll_settings *); + uint32_t (*get_pix_clk_dividers)( + struct clock_source *, + struct pixel_clk_params *, + struct pll_settings *); +}; + +struct clock_source { + const struct clock_source_funcs *funcs; + struct dc_context *ctx; + enum clock_source_id id; + bool dp_clk_src; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h new file mode 100644 index 000000000000..af292596b101 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.h @@ -0,0 +1,93 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMPRESSOR_H__ +#define __DAL_COMPRESSOR_H__ + +#include "include/grph_object_id.h" +#include "bios_parser_interface.h" + +enum fbc_compress_ratio { + FBC_COMPRESS_RATIO_INVALID = 0, + FBC_COMPRESS_RATIO_1TO1 = 1, + FBC_COMPRESS_RATIO_2TO1 = 2, + FBC_COMPRESS_RATIO_4TO1 = 4, + FBC_COMPRESS_RATIO_8TO1 = 8, +}; + +union fbc_physical_address { + struct { + uint32_t low_part; + int32_t high_part; + } addr; +}; + +struct compr_addr_and_pitch_params { + uint32_t inst; + uint32_t source_view_width; + uint32_t source_view_height; +}; + +enum fbc_hw_max_resolution_supported { + FBC_MAX_X = 3840, + FBC_MAX_Y = 2400 +}; + +struct compressor { + struct dc_context *ctx; + uint32_t attached_inst; + bool is_enabled; + + union { + uint32_t raw; + struct { + uint32_t FBC_SUPPORT:1; + uint32_t FB_POOL:1; + uint32_t DYNAMIC_ALLOC:1; + uint32_t LPT_SUPPORT:1; + uint32_t LPT_MC_CONFIG:1; + uint32_t DUMMY_BACKEND:1; + uint32_t CLK_GATING_DISABLED:1; + + } bits; + } options; + + union fbc_physical_address compr_surface_address; + + uint32_t embedded_panel_h_size; + uint32_t embedded_panel_v_size; + uint32_t memory_bus_width; + uint32_t banks_num; + uint32_t raw_size; + uint32_t channel_interleave_size; + uint32_t dram_channels_num; + + uint32_t allocated_size; + uint32_t preferred_requested_size; + uint32_t lpt_channels_num; + enum fbc_compress_ratio min_compress_ratio; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h new file mode 100644 index 000000000000..7d6dc8ea75ab --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -0,0 +1,50 @@ +/* + * core_dc.h + * + * Created on: Nov 13, 2015 + * Author: yonsun + */ + +#ifndef __CORE_DC_H__ +#define __CORE_DC_H__ + +#include "core_types.h" +#include "hw_sequencer.h" + +#define DC_TO_CORE(dc)\ + container_of(dc, struct core_dc, public) + +struct core_dc { + struct dc public; + struct dc_context *ctx; + + uint8_t link_count; + struct core_link *links[MAX_PIPES * 2]; + + /* TODO: determine max number of targets*/ + struct validate_context *current_context; + struct validate_context *temp_flip_context; + struct resource_pool *res_pool; + + /*Power State*/ + enum dc_video_power_state previous_power_state; + enum dc_video_power_state current_power_state; + + /* Display Engine Clock levels */ + struct dm_pp_clock_levels sclk_lvls; + + /* Inputs into BW and WM calculations. */ + struct bw_calcs_dceip bw_dceip; + struct bw_calcs_vbios bw_vbios; + + /* HW functions */ + struct hw_sequencer_funcs hwss; + struct dce_hwseq *hwseq; + + /* temp store of dm_pp_display_configuration + * to compare to see if display config changed + */ + struct dm_pp_display_configuration prev_display_config; +}; + +#endif /* __CORE_DC_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h new file mode 100644 index 000000000000..32a2cc712000 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _CORE_STATUS_H_ +#define _CORE_STATUS_H_ + +enum dc_status { + DC_OK = 1, + + DC_NO_CONTROLLER_RESOURCE, + DC_NO_STREAM_ENG_RESOURCE, + DC_NO_CLOCK_SOURCE_RESOURCE, + DC_FAIL_CONTROLLER_VALIDATE, + DC_FAIL_ENC_VALIDATE, + DC_FAIL_ATTACH_SURFACES, + DC_FAIL_SURFACE_VALIDATE, + DC_NO_DP_LINK_BANDWIDTH, + DC_EXCEED_DONGLE_MAX_CLK, + DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED, + DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */ + + DC_ERROR_UNEXPECTED = -1 +}; + +#endif /* _CORE_STATUS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h new file mode 100644 index 000000000000..f2eb8945d5c4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -0,0 +1,319 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _CORE_TYPES_H_ +#define _CORE_TYPES_H_ + +#include "dc.h" +#include "bandwidth_calcs.h" +#include "ddc_service_types.h" +#include "dc_bios_types.h" + +struct core_stream; +/********* core_target *************/ + +#define CONST_DC_TARGET_TO_CORE(dc_target) \ + container_of(dc_target, const struct core_target, public) +#define DC_TARGET_TO_CORE(dc_target) \ + container_of(dc_target, struct core_target, public) + +#define MAX_PIPES 6 +#define MAX_CLOCK_SOURCES 7 + +struct core_target { + struct dc_target public; + + struct dc_context *ctx; +}; + +/********* core_surface **********/ +#define DC_SURFACE_TO_CORE(dc_surface) \ + container_of(dc_surface, struct core_surface, public) + +#define DC_GAMMA_TO_CORE(dc_gamma) \ + container_of(dc_gamma, struct core_gamma, public) + +struct core_surface { + struct dc_surface public; + struct dc_surface_status status; + struct dc_context *ctx; +}; + +struct core_gamma { + struct dc_gamma public; + struct dc_context *ctx; +}; + +void enable_surface_flip_reporting(struct dc_surface *dc_surface, + uint32_t controller_id); + +/********* core_stream ************/ +#include "grph_object_id.h" +#include "link_encoder.h" +#include "stream_encoder.h" +#include "clock_source.h" +#include "audio.h" +#include "hw_sequencer_types.h" +#include "opp.h" + +#define DC_STREAM_TO_CORE(dc_stream) container_of( \ + dc_stream, struct core_stream, public) + +struct core_stream { + struct dc_stream public; + + /* field internal to DC */ + struct dc_context *ctx; + const struct core_sink *sink; + + /* used by DCP and FMT */ + struct bit_depth_reduction_params bit_depth_params; + struct clamping_and_pixel_encoding_params clamping; + + int phy_pix_clk; + enum signal_type signal; + + struct dc_stream_status status; +}; + +/************ core_sink *****************/ + +#define DC_SINK_TO_CORE(dc_sink) \ + container_of(dc_sink, struct core_sink, public) + +struct core_sink { + /** The public, read-only (for DM) area of sink. **/ + struct dc_sink public; + /** End-of-public area. **/ + + /** The 'protected' area - read/write access, for use only inside DC **/ + /* not used for now */ + struct core_link *link; + struct dc_context *ctx; + uint32_t dongle_max_pix_clk; + bool converter_disable_audio; +}; + +/************ link *****************/ +#define DC_LINK_TO_CORE(dc_link) container_of(dc_link, struct core_link, public) + +struct link_init_data { + const struct core_dc *dc; + struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ + uint32_t connector_index; /* this will be mapped to the HPD pins */ + uint32_t link_index; /* this is mapped to DAL display_index + TODO: remove it when DC is complete. */ +}; + +/* DP MST stream allocation (payload bandwidth number) */ +struct link_mst_stream_allocation { + /* DIG front */ + const struct stream_encoder *stream_enc; + /* associate DRM payload table with DC stream encoder */ + uint8_t vcp_id; + /* number of slots required for the DP stream in transport packet */ + uint8_t slot_count; +}; + +/* DP MST stream allocation table */ +struct link_mst_stream_allocation_table { + /* number of DP video streams */ + int stream_count; + /* array of stream allocations */ + struct link_mst_stream_allocation + stream_allocations[MAX_CONTROLLER_NUM]; +}; + +struct core_link { + struct dc_link public; + const struct core_dc *dc; + + struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/ + + struct link_encoder *link_enc; + struct ddc_service *ddc; + struct graphics_object_id link_id; + union ddi_channel_mapping ddi_channel_mapping; + struct connector_device_tag_info device_tag; + struct dpcd_caps dpcd_caps; + unsigned int dpcd_sink_count; + + enum edp_revision edp_revision; + + /* MST record stream using this link */ + struct link_flags { + bool dp_keep_receiver_powered; + } wa_flags; + struct link_mst_stream_allocation_table mst_stream_alloc_table; + + struct dc_link_status link_status; +}; + +#define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public) + +struct core_link *link_create(const struct link_init_data *init_params); +void link_destroy(struct core_link **link); + +enum dc_status dc_link_validate_mode_timing( + const struct core_stream *stream, + struct core_link *link, + const struct dc_crtc_timing *timing); + +void core_link_resume(struct core_link *link); + +void core_link_enable_stream(struct pipe_ctx *pipe_ctx); + +void core_link_disable_stream(struct pipe_ctx *pipe_ctx); + +/********** DAL Core*********************/ +#include "display_clock_interface.h" +#include "transform.h" + +struct resource_pool; +struct validate_context; +struct resource_context; + +struct resource_funcs { + void (*destroy)(struct resource_pool **pool); + struct link_encoder *(*link_enc_create)( + const struct encoder_init_data *init); + enum dc_status (*validate_with_context)( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context); + + enum dc_status (*validate_guaranteed)( + const struct core_dc *dc, + const struct dc_target *dc_target, + struct validate_context *context); + + enum dc_status (*validate_bandwidth)( + const struct core_dc *dc, + struct validate_context *context); + + struct validate_context *(*apply_clk_constraints)( + const struct core_dc *dc, + struct validate_context *context); + + struct pipe_ctx *(*acquire_idle_pipe_for_layer)( + struct resource_context *res_ctx, + struct core_stream *stream); + + void (*build_bit_depth_reduction_params)( + const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth); +}; + +struct audio_support{ + bool dp_audio; + bool hdmi_audio_on_dongle; + bool hdmi_audio_native; +}; + +struct resource_pool { + struct mem_input *mis[MAX_PIPES]; + struct input_pixel_processor *ipps[MAX_PIPES]; + struct transform *transforms[MAX_PIPES]; + struct output_pixel_processor *opps[MAX_PIPES]; + struct timing_generator *timing_generators[MAX_PIPES]; + struct stream_encoder *stream_enc[MAX_PIPES * 2]; + + unsigned int pipe_count; + unsigned int underlay_pipe_index; + unsigned int stream_enc_count; + + /* + * reserved clock source for DP + */ + struct clock_source *dp_clock_source; + + struct clock_source *clock_sources[MAX_CLOCK_SOURCES]; + unsigned int clk_src_count; + + struct audio *audios[MAX_PIPES]; + unsigned int audio_count; + struct audio_support audio_support; + + struct display_clock *display_clock; + struct irq_service *irqs; + + const struct resource_funcs *funcs; + const struct resource_caps *res_cap; +}; + +struct pipe_ctx { + struct core_surface *surface; + struct core_stream *stream; + + struct mem_input *mi; + struct input_pixel_processor *ipp; + struct transform *xfm; + struct output_pixel_processor *opp; + struct timing_generator *tg; + + struct scaler_data scl_data; + + struct stream_encoder *stream_enc; + struct display_clock *dis_clk; + struct clock_source *clock_source; + + struct audio *audio; + + struct pixel_clk_params pix_clk_params; + struct pll_settings pll_settings; + + /*fmt*/ + struct encoder_info_frame encoder_info_frame; + + uint8_t pipe_idx; + + struct pipe_ctx *top_pipe; + struct pipe_ctx *bottom_pipe; +}; + +struct resource_context { + const struct resource_pool *pool; + struct pipe_ctx pipe_ctx[MAX_PIPES]; + bool is_stream_enc_acquired[MAX_PIPES * 2]; + bool is_audio_acquired[MAX_PIPES]; + uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; + uint8_t dp_clock_source_ref_count; + }; + +struct validate_context { + struct core_target *targets[MAX_PIPES]; + struct dc_target_status target_status[MAX_PIPES]; + uint8_t target_count; + + struct resource_context res_ctx; + + /* The output from BW and WM calculations. */ + struct bw_calcs_output bw_results; + /* Note: this is a big structure, do *not* put on stack! */ + struct dm_pp_display_configuration pp_display_cfg; +}; + +#endif /* _CORE_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h new file mode 100644 index 000000000000..830fc3d039c9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -0,0 +1,145 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DDC_SERVICE_H__ +#define __DAL_DDC_SERVICE_H__ + +#include "include/ddc_service_types.h" +#include "include/i2caux_interface.h" + +#define EDID_SEGMENT_SIZE 256 + +struct ddc_service; +struct graphics_object_id; +enum ddc_result; +struct av_sync_data; +struct dp_receiver_id_info; + +struct i2c_payloads; +struct aux_payloads; + +struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count); +struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p); +uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p); +void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p); + +struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count); +struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p); +uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p); +void dal_ddc_aux_payloads_destroy(struct aux_payloads **p); + +void dal_ddc_i2c_payloads_add( + struct i2c_payloads *payloads, + uint32_t address, + uint32_t len, + uint8_t *data, + bool write); + +void dal_ddc_aux_payloads_add( + struct aux_payloads *payloads, + uint32_t address, + uint32_t len, + uint8_t *data, + bool write); + +struct ddc_service_init_data { + struct graphics_object_id id; + struct dc_context *ctx; + struct core_link *link; +}; + +struct ddc_service *dal_ddc_service_create( + struct ddc_service_init_data *ddc_init_data); + +void dal_ddc_service_destroy(struct ddc_service **ddc); + +enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc); + +void dal_ddc_service_set_transaction_type( + struct ddc_service *ddc, + enum ddc_transaction_type type); + +bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc); + +uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc); + +uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc); + +void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf); + +void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( + struct ddc_service *ddc, + struct display_sink_capability *sink_cap); + +bool dal_ddc_service_query_ddc_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size); + +enum ddc_result dal_ddc_service_read_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *data, + uint32_t len); + +enum ddc_result dal_ddc_service_write_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + const uint8_t *data, + uint32_t len); + +void dal_ddc_service_write_scdc_data( + struct ddc_service *ddc_service, + uint32_t pix_clk, + bool lte_340_scramble); + +void dal_ddc_service_read_scdc_data( + struct ddc_service *ddc_service); + +void ddc_service_set_dongle_type(struct ddc_service *ddc, + enum display_dongle_type dongle_type); + +void dal_ddc_service_set_ddc_pin( + struct ddc_service *ddc_service, + struct ddc *ddc); + +struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service); + +enum ddc_result dal_ddc_service_read_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *data, + uint32_t len); +enum ddc_result dal_ddc_service_write_dpcd_data( + struct ddc_service *ddc, + uint32_t address, + const uint8_t *data, + uint32_t len); + +#endif /* __DAL_DDC_SERVICE_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h new file mode 100644 index 000000000000..b0cf8e00059c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_DP_H__ +#define __DC_LINK_DP_H__ + +#define LINK_TRAINING_ATTEMPTS 4 +#define LINK_TRAINING_RETRY_DELAY 50 /* ms */ + +struct core_link; +struct core_stream; +struct dc_link_settings; + +bool dp_hbr_verify_link_cap( + struct core_link *link, + struct dc_link_settings *known_limit_link_setting); + +bool dp_validate_mode_timing( + struct core_link *link, + const struct dc_crtc_timing *timing); + +void decide_link_settings( + struct core_stream *stream, + struct dc_link_settings *link_setting); + +bool perform_link_training_with_retries( + struct core_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern, + int attempts); + +bool is_mst_supported(struct core_link *link); + +void detect_dp_sink_caps(struct core_link *link); + +bool is_dp_active_dongle(const struct core_link *link); + +#endif /* __DC_LINK_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h new file mode 100644 index 000000000000..e2c63fd4fe92 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h @@ -0,0 +1,19 @@ +/* + * gamma_calcs.h + * + * Created on: Feb 9, 2016 + * Author: yonsun + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ + +#include "opp.h" +#include "core_types.h" +#include "dc.h" + +bool calculate_regamma_params(struct pwl_params *params, + const struct core_gamma *ramp, + const struct core_surface *surface); + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h new file mode 100644 index 000000000000..7948d2cc0715 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef GAMMA_TYPES_H_ + +#define GAMMA_TYPES_H_ + +#include "dc_types.h" + +/* TODO: Used in IPP and OPP */ + +struct dev_c_lut16 { + uint16_t red; + uint16_t green; + uint16_t blue; +}; +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/audio.h b/drivers/gpu/drm/amd/display/dc/inc/hw/audio.h new file mode 100644 index 000000000000..925204f49717 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/audio.h @@ -0,0 +1,62 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_AUDIO_H__ +#define __DAL_AUDIO_H__ + +#include "audio_types.h" + +struct audio; + +struct audio_funcs { + + bool (*endpoint_valid)(struct audio *audio); + + void (*hw_init)(struct audio *audio); + + void (*az_enable)(struct audio *audio); + + void (*az_disable)(struct audio *audio); + + void (*az_configure)(struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_info *audio_info); + + void (*wall_dto_setup)(struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_pll_info *pll_info); + + void (*destroy)(struct audio **audio); +}; + +struct audio { + const struct audio_funcs *funcs; + struct dc_context *ctx; + unsigned int inst; +}; + +#endif /* __DAL_AUDIO__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h b/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h new file mode 100644 index 000000000000..90d0148430fb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/gpio.h @@ -0,0 +1,86 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_H__ +#define __DAL_GPIO_H__ + +#include "gpio_types.h" + +struct gpio { + struct gpio_service *service; + struct hw_gpio_pin *pin; + enum gpio_id id; + uint32_t en; + enum gpio_mode mode; + /* when GPIO comes from VBIOS, it has defined output state */ + enum gpio_pin_output_state output_state; +}; + +#if 0 +struct gpio_funcs { + + struct hw_gpio_pin *(*create_ddc_data)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_ddc_clock)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_generic)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_hpd)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_gpio_pad)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_sync)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + struct hw_gpio_pin *(*create_gsl)( + struct dc_context *ctx, + enum gpio_id id, + uint32_t en); + + /* HW translation */ + bool (*offset_to_id)( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en); + bool (*id_to_offset)( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info); +}; +#endif + +#endif /* __DAL_GPIO__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h new file mode 100644 index 000000000000..3b0e616f7066 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_SHARED_H__ +#define __DAL_HW_SHARED_H__ + +/****************************************************************************** + * Data types shared between different Virtual HW blocks + ******************************************************************************/ +struct gamma_curve { + uint32_t offset; + uint32_t segments_num; +}; + +struct curve_points { + struct fixed31_32 x; + struct fixed31_32 y; + struct fixed31_32 offset; + struct fixed31_32 slope; + + uint32_t custom_float_x; + uint32_t custom_float_y; + uint32_t custom_float_offset; + uint32_t custom_float_slope; +}; + +struct pwl_result_data { + struct fixed31_32 red; + struct fixed31_32 green; + struct fixed31_32 blue; + + struct fixed31_32 delta_red; + struct fixed31_32 delta_green; + struct fixed31_32 delta_blue; + + uint32_t red_reg; + uint32_t green_reg; + uint32_t blue_reg; + + uint32_t delta_red_reg; + uint32_t delta_green_reg; + uint32_t delta_blue_reg; +}; + +struct pwl_params { + uint32_t *data; + struct gamma_curve arr_curve_points[16]; + struct curve_points arr_points[3]; + struct pwl_result_data rgb_resulted[256 + 3]; + uint32_t hw_points_num; +}; +#endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h new file mode 100644 index 000000000000..7e5f3e02a719 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -0,0 +1,121 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IPP_H__ +#define __DAL_IPP_H__ + +#include "hw_shared.h" + +#define MAXTRIX_COEFFICIENTS_NUMBER 12 +#define MAXTRIX_COEFFICIENTS_WRAP_NUMBER (MAXTRIX_COEFFICIENTS_NUMBER + 4) +#define MAX_OVL_MATRIX_COUNT 12 + +/* IPP RELATED */ +struct input_pixel_processor { + struct dc_context *ctx; + uint32_t inst; + const struct ipp_funcs *funcs; +}; + +enum ipp_prescale_mode { + IPP_PRESCALE_MODE_BYPASS, + IPP_PRESCALE_MODE_FIXED_SIGNED, + IPP_PRESCALE_MODE_FLOAT_SIGNED, + IPP_PRESCALE_MODE_FIXED_UNSIGNED, + IPP_PRESCALE_MODE_FLOAT_UNSIGNED +}; + +struct ipp_prescale_params { + enum ipp_prescale_mode mode; + uint16_t bias; + uint16_t scale; +}; + +enum ipp_degamma_mode { + IPP_DEGAMMA_MODE_BYPASS, + IPP_DEGAMMA_MODE_HW_sRGB, + IPP_DEGAMMA_MODE_HW_xvYCC, + IPP_DEGAMMA_MODE_USER_PWL +}; + +enum ovl_color_space { + OVL_COLOR_SPACE_UNKNOWN = 0, + OVL_COLOR_SPACE_RGB, + OVL_COLOR_SPACE_YUV601, + OVL_COLOR_SPACE_YUV709 +}; + +enum expansion_mode { + EXPANSION_MODE_DYNAMIC, + EXPANSION_MODE_ZERO +}; + +enum ipp_output_format { + IPP_OUTPUT_FORMAT_12_BIT_FIX, + IPP_OUTPUT_FORMAT_16_BIT_BYPASS, + IPP_OUTPUT_FORMAT_FLOAT +}; + +struct ipp_funcs { + + /*** cursor ***/ + void (*ipp_cursor_set_position)( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position); + + bool (*ipp_cursor_set_attributes)( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes); + + /*** setup input pixel processing ***/ + + /* put the entire pixel processor to bypass */ + void (*ipp_full_bypass)( + struct input_pixel_processor *ipp); + + /* setup ipp to expand/convert input to pixel processor internal format */ + void (*ipp_setup)( + struct input_pixel_processor *ipp, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format output_format); + + /* DCE function to setup IPP. TODO: see if we can consolidate to setup */ + void (*ipp_program_prescale)( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params); + + /*** DEGAMMA RELATED ***/ + bool (*ipp_set_degamma)( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode); + + bool (*ipp_program_degamma_pwl)( + struct input_pixel_processor *ipp, + const struct pwl_params *params); + +}; + +#endif /* __DAL_IPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h new file mode 100644 index 000000000000..77f8aa410898 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -0,0 +1,263 @@ +/* + * link_encoder.h + * + * Created on: Oct 6, 2015 + * Author: yonsun + */ + +#ifndef LINK_ENCODER_H_ +#define LINK_ENCODER_H_ + +#include "grph_object_defs.h" +#include "signal_types.h" +#include "dc_types.h" + +struct dc_context; +struct encoder_set_dp_phy_pattern_param; +struct link_mst_stream_allocation_table; +struct dc_link_settings; +struct link_training_settings; +struct core_stream; +struct pipe_ctx; + +struct encoder_init_data { + enum channel_id channel; + struct graphics_object_id connector; + enum hpd_source_id hpd_source; + /* TODO: in DAL2, here was pointer to EventManagerInterface */ + struct graphics_object_id encoder; + struct dc_context *ctx; + enum transmitter transmitter; +}; + +struct encoder_feature_support { + union { + struct { + /* 1 - external encoder; 0 - internal encoder */ + uint32_t EXTERNAL_ENCODER:1; + uint32_t ANALOG_ENCODER:1; + uint32_t STEREO_SYNC:1; + /* check the DDC data pin + * when performing DP Sink detection */ + uint32_t DP_SINK_DETECT_POLL_DATA_PIN:1; + /* CPLIB authentication + * for external DP chip supported */ + uint32_t CPLIB_DP_AUTHENTICATION:1; + uint32_t IS_HBR2_CAPABLE:1; + uint32_t IS_HBR3_CAPABLE:1; + uint32_t IS_HBR2_VALIDATED:1; + uint32_t IS_TPS3_CAPABLE:1; + uint32_t IS_TPS4_CAPABLE:1; + uint32_t IS_AUDIO_CAPABLE:1; + uint32_t IS_VCE_SUPPORTED:1; + uint32_t IS_CONVERTER:1; + uint32_t IS_Y_ONLY_CAPABLE:1; + uint32_t IS_YCBCR_CAPABLE:1; + } bits; + uint32_t raw; + } flags; + /* maximum supported deep color depth */ + enum dc_color_depth max_deep_color; + enum dc_color_depth max_hdmi_deep_color; + /* maximum supported clock */ + unsigned int max_pixel_clock; + unsigned int max_hdmi_pixel_clock; + bool ycbcr420_supported; +}; + +enum physical_phy_id { + PHYLD_0, + PHYLD_1, + PHYLD_2, + PHYLD_3, + PHYLD_4, + PHYLD_5, + PHYLD_6, + PHYLD_7, + PHYLD_8, + PHYLD_9, + PHYLD_COUNT, + PHYLD_UNKNOWN = (-1L) +}; + +enum phy_type { + PHY_TYPE_UNKNOWN = 1, + PHY_TYPE_PCIE_PHY = 2, + PHY_TYPE_UNIPHY = 3, +}; + +union dmcu_psr_level { + struct { + unsigned int SKIP_CRC:1; + unsigned int SKIP_DP_VID_STREAM_DISABLE:1; + unsigned int SKIP_PHY_POWER_DOWN:1; + unsigned int SKIP_AUX_ACK_CHECK:1; + unsigned int SKIP_CRTC_DISABLE:1; + unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1; + unsigned int SKIP_SMU_NOTIFICATION:1; + unsigned int SKIP_AUTO_STATE_ADVANCE:1; + unsigned int DISABLE_PSR_ENTRY_ABORT:1; + unsigned int RESERVED:23; + } bits; + unsigned int u32all; +}; + +union dpcd_psr_configuration { + struct { + unsigned char ENABLE : 1; + unsigned char TRANSMITTER_ACTIVE_IN_PSR : 1; + unsigned char CRC_VERIFICATION : 1; + unsigned char FRAME_CAPTURE_INDICATION : 1; + /* For eDP 1.4, PSR v2*/ + unsigned char LINE_CAPTURE_INDICATION : 1; + /* For eDP 1.4, PSR v2*/ + unsigned char IRQ_HPD_WITH_CRC_ERROR : 1; + unsigned char RESERVED : 2; + } bits; + unsigned char raw; +}; + +union psr_error_status { + struct { + unsigned char LINK_CRC_ERROR :1; + unsigned char RFB_STORAGE_ERROR :1; + unsigned char RESERVED :6; + } bits; + unsigned char raw; +}; + +union psr_sink_psr_status { + struct { + unsigned char SINK_SELF_REFRESH_STATUS :3; + unsigned char RESERVED :5; + } bits; + unsigned char raw; +}; + +struct psr_dmcu_context { + /* ddc line */ + enum channel_id channel; + /* Transmitter id */ + enum transmitter transmitterId; + /* Engine Id is used for Dig Be source select */ + enum engine_id engineId; + /* Controller Id used for Dig Fe source select */ + enum controller_id controllerId; + /* Pcie or Uniphy */ + enum phy_type phyType; + /* Physical PHY Id used by SMU interpretation */ + enum physical_phy_id smuPhyId; + /* Vertical total pixels from crtc timing. + * This is used for static screen detection. + * ie. If we want to detect half a frame, + * we use this to determine the hyst lines. + */ + unsigned int crtcTimingVerticalTotal; + /* PSR supported from panel capabilities and + * current display configuration + */ + bool psrSupportedDisplayConfig; + /* Whether fast link training is supported by the panel */ + bool psrExitLinkTrainingRequired; + /* If RFB setup time is greater than the total VBLANK time, + * it is not possible for the sink to capture the video frame + * in the same frame the SDP is sent. In this case, + * the frame capture indication bit should be set and an extra + * static frame should be transmitted to the sink. + */ + bool psrFrameCaptureIndicationReq; + /* Set the last possible line SDP may be transmitted without violating + * the RFB setup time or entering the active video frame. + */ + unsigned int sdpTransmitLineNumDeadline; + /* The VSync rate in Hz used to calculate the + * step size for smooth brightness feature + */ + unsigned int vsyncRateHz; + unsigned int skipPsrWaitForPllLock; + unsigned int numberOfControllers; + /* Unused, for future use. To indicate that first changed frame from + * state3 shouldn't result in psr_inactive, but rather to perform + * an automatic single frame rfb_update. + */ + bool rfb_update_auto_en; + /* Number of frame before entering static screen */ + unsigned int timehyst_frames; + /* Partial frames before entering static screen */ + unsigned int hyst_lines; + /* # of repeated AUX transaction attempts to make before + * indicating failure to the driver + */ + unsigned int aux_repeats; + /* Controls hw blocks to power down during PSR active state */ + union dmcu_psr_level psr_level; + /* Controls additional delay after remote frame capture before + * continuing powerd own + */ + unsigned int frame_delay; +}; + + +struct link_encoder { + const struct link_encoder_funcs *funcs; + int32_t aux_channel_offset; + struct dc_context *ctx; + struct graphics_object_id id; + struct graphics_object_id connector; + uint32_t input_signals; + uint32_t output_signals; + enum engine_id preferred_engine; + struct encoder_feature_support features; + enum transmitter transmitter; + enum hpd_source_id hpd_source; +}; + +struct link_encoder_funcs { + bool (*validate_output_with_stream)( + struct link_encoder *enc, struct pipe_ctx *pipe_ctx); + void (*hw_init)(struct link_encoder *enc); + void (*setup)(struct link_encoder *enc, + enum signal_type signal); + void (*enable_tmds_output)(struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + bool hdmi, + bool dual_link, + uint32_t pixel_clock); + void (*enable_dp_output)(struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + void (*enable_dp_mst_output)(struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source); + void (*disable_output)(struct link_encoder *link_enc, + enum signal_type signal); + void (*dp_set_lane_settings)(struct link_encoder *enc, + const struct link_training_settings *link_settings); + void (*dp_set_phy_pattern)(struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *para); + void (*update_mst_stream_allocation_table)( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table); + void (*set_lcd_backlight_level) (struct link_encoder *enc, + uint32_t level); + void (*set_dmcu_backlight_level)(struct link_encoder *enc, + uint32_t level, uint32_t frame_ramp, uint32_t controller_id); + void (*init_dmcu_backlight_settings)(struct link_encoder *enc); + void (*set_dmcu_abm_level)(struct link_encoder *enc, uint32_t level); + void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable); + void (*setup_dmcu_psr)(struct link_encoder *enc, + struct psr_dmcu_context *psr_context); + void (*backlight_control) (struct link_encoder *enc, + bool enable); + void (*power_control) (struct link_encoder *enc, + bool power_up); + void (*connect_dig_be_to_fe)(struct link_encoder *enc, + enum engine_id engine, + bool connect); + void (*enable_hpd)(struct link_encoder *enc); + void (*disable_hpd)(struct link_encoder *enc); + void (*destroy)(struct link_encoder **enc); +}; + +#endif /* LINK_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h new file mode 100644 index 000000000000..78dab74edc2d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -0,0 +1,106 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_MEM_INPUT_H__ +#define __DAL_MEM_INPUT_H__ + +#include "dc.h" +#include "include/grph_object_id.h" +#include "inc/bandwidth_calcs.h" + +#include "dce/dce_mem_input.h" /* temporary */ + +struct stutter_modes { + bool enhanced; + bool quad_dmif_buffer; + bool watermark_nb_pstate; +}; + +struct mem_input { + struct mem_input_funcs *funcs; + struct dc_context *ctx; + struct dc_plane_address request_address; + struct dc_plane_address current_address; + uint32_t inst; + struct stutter_modes stutter_mode; + + const struct dce_mem_input_registers *regs; + const struct dce_mem_input_shift *shifts; + const struct dce_mem_input_mask *masks; + struct dce_mem_input_wa wa; +}; + +struct mem_input_funcs { + void (*mem_input_program_display_marks)( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + + void (*mem_input_program_chroma_display_marks)( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns); + + void (*allocate_mem_input)( + struct mem_input *mem_input, + uint32_t h_total,/* for current target */ + uint32_t v_total,/* for current target */ + uint32_t pix_clk_khz,/* for current target */ + uint32_t total_streams_num); + + void (*free_mem_input)( + struct mem_input *mem_input, + uint32_t paths_num); + + bool (*mem_input_program_surface_flip_and_addr)( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + + bool (*mem_input_program_pte_vm)( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + + bool (*mem_input_program_surface_config)( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + + bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); + + void (*mem_input_update_dchub)(struct mem_input *mem_input, + struct dchub_init_data *dh_data); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h new file mode 100644 index 000000000000..e615997be20e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -0,0 +1,322 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_OPP_H__ +#define __DAL_OPP_H__ + +#include "hw_shared.h" +#include "transform.h" + +struct fixed31_32; +struct gamma_parameters; + +/* TODO: Need cleanup */ +enum clamping_range { + CLAMPING_FULL_RANGE = 0, /* No Clamping */ + CLAMPING_LIMITED_RANGE_8BPC, /* 8 bpc: Clamping 1 to FE */ + CLAMPING_LIMITED_RANGE_10BPC, /* 10 bpc: Clamping 4 to 3FB */ + CLAMPING_LIMITED_RANGE_12BPC, /* 12 bpc: Clamping 10 to FEF */ + /* Use programmable clampping value on FMT_CLAMP_COMPONENT_R/G/B. */ + CLAMPING_LIMITED_RANGE_PROGRAMMABLE +}; + +struct clamping_and_pixel_encoding_params { + enum dc_pixel_encoding pixel_encoding; /* Pixel Encoding */ + enum clamping_range clamping_level; /* Clamping identifier */ + enum dc_color_depth c_depth; /* Deep color use. */ +}; + +struct bit_depth_reduction_params { + struct { + /* truncate/round */ + /* trunc/round enabled*/ + uint32_t TRUNCATE_ENABLED:1; + /* 2 bits: 0=6 bpc, 1=8 bpc, 2 = 10bpc*/ + uint32_t TRUNCATE_DEPTH:2; + /* truncate or round*/ + uint32_t TRUNCATE_MODE:1; + + /* spatial dither */ + /* Spatial Bit Depth Reduction enabled*/ + uint32_t SPATIAL_DITHER_ENABLED:1; + /* 2 bits: 0=6 bpc, 1 = 8 bpc, 2 = 10bpc*/ + uint32_t SPATIAL_DITHER_DEPTH:2; + /* 0-3 to select patterns*/ + uint32_t SPATIAL_DITHER_MODE:2; + /* Enable RGB random dithering*/ + uint32_t RGB_RANDOM:1; + /* Enable Frame random dithering*/ + uint32_t FRAME_RANDOM:1; + /* Enable HighPass random dithering*/ + uint32_t HIGHPASS_RANDOM:1; + + /* temporal dither*/ + /* frame modulation enabled*/ + uint32_t FRAME_MODULATION_ENABLED:1; + /* same as for trunc/spatial*/ + uint32_t FRAME_MODULATION_DEPTH:2; + /* 2/4 gray levels*/ + uint32_t TEMPORAL_LEVEL:1; + uint32_t FRC25:2; + uint32_t FRC50:2; + uint32_t FRC75:2; + } flags; + + uint32_t r_seed_value; + uint32_t b_seed_value; + uint32_t g_seed_value; +}; + +enum wide_gamut_regamma_mode { + /* 0x0 - BITS2:0 Bypass */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS, + /* 0x1 - Fixed curve sRGB 2.4 */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24, + /* 0x2 - Fixed curve xvYCC 2.22 */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22, + /* 0x3 - Programmable control A */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A, + /* 0x4 - Programmable control B */ + WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B, + /* 0x0 - BITS6:4 Bypass */ + WIDE_GAMUT_REGAMMA_MODE_OVL_BYPASS, + /* 0x1 - Fixed curve sRGB 2.4 */ + WIDE_GAMUT_REGAMMA_MODE_OVL_SRGB24, + /* 0x2 - Fixed curve xvYCC 2.22 */ + WIDE_GAMUT_REGAMMA_MODE_OVL_XYYCC22, + /* 0x3 - Programmable control A */ + WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_A, + /* 0x4 - Programmable control B */ + WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_B +}; + +struct gamma_pixel { + struct fixed31_32 r; + struct fixed31_32 g; + struct fixed31_32 b; +}; + +enum channel_name { + CHANNEL_NAME_RED, + CHANNEL_NAME_GREEN, + CHANNEL_NAME_BLUE +}; + +struct custom_float_format { + uint32_t mantissa_bits; + uint32_t exponenta_bits; + bool sign; +}; + +struct custom_float_value { + uint32_t mantissa; + uint32_t exponenta; + uint32_t value; + bool negative; +}; + +struct hw_x_point { + uint32_t custom_float_x; + uint32_t custom_float_x_adjusted; + struct fixed31_32 x; + struct fixed31_32 adjusted_x; + struct fixed31_32 regamma_y_red; + struct fixed31_32 regamma_y_green; + struct fixed31_32 regamma_y_blue; + +}; + +struct pwl_float_data_ex { + struct fixed31_32 r; + struct fixed31_32 g; + struct fixed31_32 b; + struct fixed31_32 delta_r; + struct fixed31_32 delta_g; + struct fixed31_32 delta_b; +}; + +enum hw_point_position { + /* hw point sits between left and right sw points */ + HW_POINT_POSITION_MIDDLE, + /* hw point lays left from left (smaller) sw point */ + HW_POINT_POSITION_LEFT, + /* hw point lays stays from right (bigger) sw point */ + HW_POINT_POSITION_RIGHT +}; + +struct gamma_point { + int32_t left_index; + int32_t right_index; + enum hw_point_position pos; + struct fixed31_32 coeff; +}; + +struct pixel_gamma_point { + struct gamma_point r; + struct gamma_point g; + struct gamma_point b; +}; + +struct gamma_coefficients { + struct fixed31_32 a0[3]; + struct fixed31_32 a1[3]; + struct fixed31_32 a2[3]; + struct fixed31_32 a3[3]; + struct fixed31_32 user_gamma[3]; + struct fixed31_32 user_contrast; + struct fixed31_32 user_brightness; +}; + +struct pwl_float_data { + struct fixed31_32 r; + struct fixed31_32 g; + struct fixed31_32 b; +}; + +enum opp_regamma { + OPP_REGAMMA_BYPASS = 0, + OPP_REGAMMA_SRGB, + OPP_REGAMMA_3_6, + OPP_REGAMMA_USER, +}; + +struct output_pixel_processor { + struct dc_context *ctx; + uint32_t inst; + const struct opp_funcs *funcs; +}; + +enum fmt_stereo_action { + FMT_STEREO_ACTION_ENABLE = 0, + FMT_STEREO_ACTION_DISABLE, + FMT_STEREO_ACTION_UPDATE_POLARITY +}; + +enum graphics_csc_adjust_type { + GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0, + GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */ + GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ +}; + +struct default_adjustment { + enum lb_pixel_depth lb_color_depth; + enum dc_color_space out_color_space; + enum dc_color_space in_color_space; + enum dc_color_depth color_depth; + enum pixel_format surface_pixel_format; + enum graphics_csc_adjust_type csc_adjust_type; + bool force_hw_default; +}; + +enum grph_color_adjust_option { + GRPH_COLOR_MATRIX_HW_DEFAULT = 1, + GRPH_COLOR_MATRIX_SW +}; + +struct opp_grph_csc_adjustment { + enum grph_color_adjust_option color_adjust_option; + enum dc_color_space c_space; + enum dc_color_depth color_depth; /* clean up to uint32_t */ + enum graphics_csc_adjust_type csc_adjust_type; + int32_t adjust_divider; + int32_t grph_cont; + int32_t grph_sat; + int32_t grph_bright; + int32_t grph_hue; +}; + +struct out_csc_color_matrix { + enum dc_color_space color_space; + uint16_t regval[12]; +}; + +/* Underlay related types */ + +struct hw_adjustment_range { + int32_t hw_default; + int32_t min; + int32_t max; + int32_t step; + uint32_t divider; /* (actually HW range is min/divider; divider !=0) */ +}; + +enum ovl_csc_adjust_item { + OVERLAY_BRIGHTNESS = 0, + OVERLAY_GAMMA, + OVERLAY_CONTRAST, + OVERLAY_SATURATION, + OVERLAY_HUE, + OVERLAY_ALPHA, + OVERLAY_ALPHA_PER_PIX, + OVERLAY_COLOR_TEMPERATURE +}; + +struct opp_funcs { + void (*opp_power_on_regamma_lut)( + struct output_pixel_processor *opp, + bool power_on); + + bool (*opp_program_regamma_pwl)( + struct output_pixel_processor *opp, + const struct pwl_params *params); + + void (*opp_set_regamma_mode)(struct output_pixel_processor *opp, + enum opp_regamma mode); + + void (*opp_set_csc_adjustment)( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + + void (*opp_set_csc_default)( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + + /* FORMATTER RELATED */ + + void (*opp_program_fmt)( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + + void (*opp_set_dyn_expansion)( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + + void (*opp_program_bit_depth_reduction)( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + + /* underlay related */ + void (*opp_get_underlay_adjustment_range)( + struct output_pixel_processor *opp, + enum ovl_csc_adjust_item overlay_adjust_item, + struct hw_adjustment_range *range); + + void (*opp_destroy)(struct output_pixel_processor **opp); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h new file mode 100644 index 000000000000..9caf2b365420 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -0,0 +1,121 @@ +/* + * stream_encoder.h + * + */ + +#ifndef STREAM_ENCODER_H_ +#define STREAM_ENCODER_H_ + +#include "include/hw_sequencer_types.h" +#include "audio_types.h" + +struct dc_bios; +struct dc_context; +struct dc_crtc_timing; + +struct encoder_info_packet { + bool valid; + uint8_t hb0; + uint8_t hb1; + uint8_t hb2; + uint8_t hb3; + uint8_t sb[28]; +}; + +struct encoder_info_frame { + /* auxiliary video information */ + struct encoder_info_packet avi; + struct encoder_info_packet gamut; + struct encoder_info_packet vendor; + /* source product description */ + struct encoder_info_packet spd; + /* video stream configuration */ + struct encoder_info_packet vsc; +}; + +struct encoder_unblank_param { + struct hw_crtc_timing crtc_timing; + struct dc_link_settings link_settings; +}; + +struct encoder_set_dp_phy_pattern_param { + enum dp_test_pattern dp_phy_pattern; + const uint8_t *custom_pattern; + uint32_t custom_pattern_size; + enum dp_panel_mode dp_panel_mode; +}; + +struct stream_encoder { + const struct stream_encoder_funcs *funcs; + struct dc_context *ctx; + struct dc_bios *bp; + enum engine_id id; +}; + +struct stream_encoder_funcs { + void (*dp_set_stream_attribute)( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space); + + void (*hdmi_set_stream_attribute)( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio); + + void (*dvi_set_stream_attribute)( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link); + + void (*set_mst_bandwidth)( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp); + + void (*update_hdmi_info_packets)( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + + void (*stop_hdmi_info_packets)( + struct stream_encoder *enc); + + void (*update_dp_info_packets)( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + + void (*stop_dp_info_packets)( + struct stream_encoder *enc); + + void (*dp_blank)( + struct stream_encoder *enc); + + void (*dp_unblank)( + struct stream_encoder *enc, + const struct encoder_unblank_param *param); + + void (*audio_mute_control)( + struct stream_encoder *enc, bool mute); + + void (*dp_audio_setup)( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + + void (*dp_audio_enable) ( + struct stream_encoder *enc); + + void (*dp_audio_disable) ( + struct stream_encoder *enc); + + void (*hdmi_audio_setup)( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + + void (*hdmi_audio_disable) ( + struct stream_encoder *enc); +}; + +#endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h new file mode 100644 index 000000000000..6ac609f6f89f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -0,0 +1,162 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TIMING_GENERATOR_TYPES_H__ +#define __DAL_TIMING_GENERATOR_TYPES_H__ + +struct dc_bios; + +/** + * These parameters are required as input when doing blanking/Unblanking +*/ +#define MAX_TG_COLOR_VALUE 0x3FF + +struct tg_color { + /* Maximum 10 bits color value */ + uint16_t color_r_cr; + uint16_t color_g_y; + uint16_t color_b_cb; +}; + +/* Contains CRTC vertical/horizontal pixel counters */ +struct crtc_position { + uint32_t vertical_count; + uint32_t horizontal_count; + uint32_t nominal_vcount; +}; + +struct dcp_gsl_params { + int gsl_group; + int gsl_master; +}; + +#define LEFT_EYE_3D_PRIMARY_SURFACE 1 +#define RIGHT_EYE_3D_PRIMARY_SURFACE 0 + +enum test_pattern_dyn_range { + TEST_PATTERN_DYN_RANGE_VESA = 0, + TEST_PATTERN_DYN_RANGE_CEA +}; + +enum test_pattern_mode { + TEST_PATTERN_MODE_COLORSQUARES_RGB = 0, + TEST_PATTERN_MODE_COLORSQUARES_YCBCR601, + TEST_PATTERN_MODE_COLORSQUARES_YCBCR709, + TEST_PATTERN_MODE_VERTICALBARS, + TEST_PATTERN_MODE_HORIZONTALBARS, + TEST_PATTERN_MODE_SINGLERAMP_RGB, + TEST_PATTERN_MODE_DUALRAMP_RGB +}; + +enum test_pattern_color_format { + TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0, + TEST_PATTERN_COLOR_FORMAT_BPC_8, + TEST_PATTERN_COLOR_FORMAT_BPC_10, + TEST_PATTERN_COLOR_FORMAT_BPC_12 +}; + +enum controller_dp_test_pattern { + CONTROLLER_DP_TEST_PATTERN_D102 = 0, + CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR, + CONTROLLER_DP_TEST_PATTERN_PRBS7, + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES, + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS, + CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS, + CONTROLLER_DP_TEST_PATTERN_COLORRAMP, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + CONTROLLER_DP_TEST_PATTERN_RESERVED_8, + CONTROLLER_DP_TEST_PATTERN_RESERVED_9, + CONTROLLER_DP_TEST_PATTERN_RESERVED_A, + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA +}; + +enum crtc_state { + CRTC_STATE_VBLANK = 0, + CRTC_STATE_VACTIVE +}; + +struct timing_generator { + const struct timing_generator_funcs *funcs; + struct dc_bios *bp; + struct dc_context *ctx; + int inst; +}; + +struct dc_crtc_timing; + +struct drr_params; + +struct timing_generator_funcs { + bool (*validate_timing)(struct timing_generator *tg, + const struct dc_crtc_timing *timing); + void (*program_timing)(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios); + bool (*enable_crtc)(struct timing_generator *tg); + bool (*disable_crtc)(struct timing_generator *tg); + bool (*is_counter_moving)(struct timing_generator *tg); + void (*get_position)(struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position); + uint32_t (*get_frame_count)(struct timing_generator *tg); + uint32_t (*get_scanoutpos)( + struct timing_generator *tg, + uint32_t *vbl, + uint32_t *position); + void (*set_early_control)(struct timing_generator *tg, + uint32_t early_cntl); + void (*wait_for_state)(struct timing_generator *tg, + enum crtc_state state); + bool (*set_blank)(struct timing_generator *tg, + bool enable_blanking); + bool (*is_blanked)(struct timing_generator *tg); + void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color); + void (*set_blank_color)(struct timing_generator *tg, const struct tg_color *color); + void (*set_colors)(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color); + + void (*disable_vga)(struct timing_generator *tg); + bool (*did_triggered_reset_occur)(struct timing_generator *tg); + void (*setup_global_swap_lock)(struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params); + void (*unlock)(struct timing_generator *tg); + void (*lock)(struct timing_generator *tg); + void (*enable_reset_trigger)(struct timing_generator *tg, int source_tg_inst); + void (*disable_reset_trigger)(struct timing_generator *tg); + void (*tear_down_global_swap_lock)(struct timing_generator *tg); + void (*enable_advanced_request)(struct timing_generator *tg, + bool enable, const struct dc_crtc_timing *timing); + void (*set_drr)(struct timing_generator *tg, const struct drr_params *params); + void (*set_static_screen_control)(struct timing_generator *tg, + uint32_t value); + void (*set_test_pattern)( + struct timing_generator *tg, + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth); + +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h new file mode 100644 index 000000000000..ef743b70b3e9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -0,0 +1,179 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TRANSFORM_H__ +#define __DAL_TRANSFORM_H__ + +#include "dc_hw_types.h" +#include "fixed31_32.h" + +#define CSC_TEMPERATURE_MATRIX_SIZE 9 + +struct bit_depth_reduction_params; + +struct transform { + const struct transform_funcs *funcs; + struct dc_context *ctx; + int inst; +}; + +/* Colorimetry */ +enum colorimetry { + COLORIMETRY_NO_DATA = 0, + COLORIMETRY_ITU601 = 1, + COLORIMETRY_ITU709 = 2, + COLORIMETRY_EXTENDED = 3 +}; + +enum active_format_info { + ACTIVE_FORMAT_NO_DATA = 0, + ACTIVE_FORMAT_VALID = 1 +}; + +/* Active format aspect ratio */ +enum active_format_aspect_ratio { + ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE = 8, + ACTIVE_FORMAT_ASPECT_RATIO_4_3 = 9, + ACTIVE_FORMAT_ASPECT_RATIO_16_9 = 0XA, + ACTIVE_FORMAT_ASPECT_RATIO_14_9 = 0XB +}; + +enum bar_info { + BAR_INFO_NOT_VALID = 0, + BAR_INFO_VERTICAL_VALID = 1, + BAR_INFO_HORIZONTAL_VALID = 2, + BAR_INFO_BOTH_VALID = 3 +}; + +enum picture_scaling { + PICTURE_SCALING_UNIFORM = 0, + PICTURE_SCALING_HORIZONTAL = 1, + PICTURE_SCALING_VERTICAL = 2, + PICTURE_SCALING_BOTH = 3 +}; + +/* RGB quantization range */ +enum rgb_quantization_range { + RGB_QUANTIZATION_DEFAULT_RANGE = 0, + RGB_QUANTIZATION_LIMITED_RANGE = 1, + RGB_QUANTIZATION_FULL_RANGE = 2, + RGB_QUANTIZATION_RESERVED = 3 +}; + +/* YYC quantization range */ +enum yyc_quantization_range { + YYC_QUANTIZATION_LIMITED_RANGE = 0, + YYC_QUANTIZATION_FULL_RANGE = 1, + YYC_QUANTIZATION_RESERVED2 = 2, + YYC_QUANTIZATION_RESERVED3 = 3 +}; + +enum graphics_gamut_adjust_type { + GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS = 0, + GRAPHICS_GAMUT_ADJUST_TYPE_HW, /* without adjustments */ + GRAPHICS_GAMUT_ADJUST_TYPE_SW /* use adjustments */ +}; + +struct xfm_grph_csc_adjustment { + struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; + enum graphics_gamut_adjust_type gamut_adjust_type; +}; + +enum lb_pixel_depth { + /* do not change the values because it is used as bit vector */ + LB_PIXEL_DEPTH_18BPP = 1, + LB_PIXEL_DEPTH_24BPP = 2, + LB_PIXEL_DEPTH_30BPP = 4, + LB_PIXEL_DEPTH_36BPP = 8 +}; + +struct overscan_info { + int left; + int right; + int top; + int bottom; +}; + +struct scaling_ratios { + struct fixed31_32 horz; + struct fixed31_32 vert; + struct fixed31_32 horz_c; + struct fixed31_32 vert_c; +}; + +struct sharpness_adj { + int horz; + int vert; +}; + +struct line_buffer_params { + bool alpha_en; + bool pixel_expan_mode; + bool interleave_en; + int dynamic_pixel_depth; + enum lb_pixel_depth depth; +}; + +struct scaler_data { + int h_active; + int v_active; + struct scaling_taps taps; + struct rect viewport; + struct rect recout; + struct scaling_ratios ratios; + struct sharpness_adj sharpness; + enum pixel_format format; + struct line_buffer_params lb_params; +}; + +struct transform_funcs { + void (*transform_reset)(struct transform *xfm); + + void (*transform_set_scaler)(struct transform *xfm, + const struct scaler_data *scl_data); + + void (*transform_set_gamut_remap)( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust); + + void (*transform_set_pixel_storage_depth)( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params); + + bool (*transform_get_optimal_number_of_taps)( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); +}; + +extern const uint16_t filter_2tap_16p[18]; +extern const uint16_t filter_2tap_64p[66]; +const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio); +const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio); +const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h new file mode 100644 index 000000000000..35a556dd9054 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -0,0 +1,156 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HW_SEQUENCER_H__ +#define __DC_HW_SEQUENCER_H__ +#include "core_types.h" +#include "timing_generator.h" + +struct gamma_parameters; + +enum pipe_gating_control { + PIPE_GATING_CONTROL_DISABLE = 0, + PIPE_GATING_CONTROL_ENABLE, + PIPE_GATING_CONTROL_INIT +}; + +enum pipe_lock_control { + PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, + PIPE_LOCK_CONTROL_BLENDER = 1 << 1, + PIPE_LOCK_CONTROL_SCL = 1 << 2, + PIPE_LOCK_CONTROL_SURFACE = 1 << 3, + PIPE_LOCK_CONTROL_MODE = 1 << 4 +}; + +struct dce_hwseq; + +struct hw_sequencer_funcs { + + void (*init_hw)(struct core_dc *dc); + + enum dc_status (*apply_ctx_to_hw)( + struct core_dc *dc, struct validate_context *context); + + void (*reset_hw_ctx_wrap)( + struct core_dc *dc, struct validate_context *context); + + void (*prepare_pipe_for_context)( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context); + + void (*apply_ctx_for_surface)( + struct core_dc *dc, + struct core_surface *surface, + struct validate_context *context); + + void (*set_plane_config)( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct resource_context *res_ctx); + + void (*update_plane_addr)( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx); + + void (*update_pending_status)( + struct pipe_ctx *pipe_ctx); + + bool (*set_gamma_correction)( + struct input_pixel_processor *ipp, + struct output_pixel_processor *opp, + const struct core_gamma *ramp, + const struct core_surface *surface); + + void (*power_down)(struct core_dc *dc); + + void (*enable_accelerated_mode)(struct core_dc *dc); + + void (*enable_timing_synchronization)( + struct core_dc *dc, + int group_index, + int group_size, + struct pipe_ctx *grouped_pipes[]); + + /* backlight control */ + void (*encoder_set_lcd_backlight_level)( + struct link_encoder *enc, uint32_t level); + + void (*enable_display_pipe_clock_gating)( + struct dc_context *ctx, + bool clock_gating); + + bool (*enable_display_power_gating)( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating); + + void (*power_down_front_end)(struct core_dc *dc, struct pipe_ctx *pipe); + void (*update_info_frame)(struct pipe_ctx *pipe_ctx); + + void (*enable_stream)(struct pipe_ctx *pipe_ctx); + + void (*disable_stream)(struct pipe_ctx *pipe_ctx); + + void (*unblank_stream)(struct pipe_ctx *pipe_ctx, + struct dc_link_settings *link_settings); + + void (*pipe_control_lock)( + struct dce_hwseq *hwseq, + unsigned int blnd_inst, + enum pipe_lock_control control_mask, + bool lock); + + void (*set_displaymarks)( + const struct core_dc *dc, + struct validate_context *context); + + void (*increase_watermarks_for_pipe)(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context); + + void (*set_display_clock)(struct validate_context *context); + + void (*set_bandwidth)(struct core_dc *dc); + + void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, + int vmin, int vmax); + + void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, + int num_pipes, int value); + + enum dc_status (*prog_pixclk_crtc_otg)( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct core_dc *dc); +}; + +void color_space_to_black_color( + const struct core_dc *dc, + enum dc_color_space colorspace, + struct tg_color *black_color); + +#endif /* __DC_HW_SEQUENCER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h new file mode 100644 index 000000000000..662fa30d45f7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -0,0 +1,73 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_LINK_HWSS_H__ +#define __DC_LINK_HWSS_H__ + +#include "inc/core_status.h" + +enum dc_status core_link_read_dpcd( + struct core_link* link, + uint32_t address, + uint8_t *data, + uint32_t size); + +enum dc_status core_link_write_dpcd( + struct core_link* link, + uint32_t address, + const uint8_t *data, + uint32_t size); + +void dp_enable_link_phy( + struct core_link *link, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings); + +void dp_receiver_power_ctrl(struct core_link *link, bool on); + +void dp_disable_link_phy(struct core_link *link, enum signal_type signal); + +void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal); + +bool dp_set_hw_training_pattern( + struct core_link *link, + enum hw_dp_training_pattern pattern); + +void dp_set_hw_lane_settings( + struct core_link *link, + const struct link_training_settings *link_settings); + +void dp_set_hw_test_pattern( + struct core_link *link, + enum dp_test_pattern test_pattern, + uint8_t *custom_pattern, + uint32_t custom_pattern_size); + +enum dp_panel_mode dp_get_panel_mode(struct core_link *link); + +void dp_retrain_link(struct core_link *link); + +#endif /* __DC_LINK_HWSS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h new file mode 100644 index 000000000000..159b2c519f2b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -0,0 +1,290 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ + +#include "dm_services.h" + +/* macro for register read/write + * user of macro need to define + * + * CTX ==> macro to ptr to dc_context + * eg. aud110->base.ctx + * + * REG ==> macro to location of register offset + * eg. aud110->regs->reg + */ +#define REG_READ(reg_name) \ + dm_read_reg(CTX, REG(reg_name)) + +#define REG_WRITE(reg_name, value) \ + dm_write_reg(CTX, REG(reg_name), value) + +#ifdef REG_SET +#undef REG_SET +#endif + +#ifdef REG_GET +#undef REG_GET +#endif + +/* macro to set register fields. */ +#define REG_SET_N(reg_name, n, initial_val, ...) \ + generic_reg_update_ex(CTX, \ + REG(reg_name), \ + initial_val, \ + n, __VA_ARGS__) + +#define FN(reg_name, field) \ + FD(reg_name##__##field) + +#define REG_SET(reg_name, initial_val, field, val) \ + REG_SET_N(reg_name, 1, initial_val, \ + FN(reg_name, field), val) + +#define REG_SET_2(reg, init_value, f1, v1, f2, v2) \ + REG_SET_N(reg, 2, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2) + +#define REG_SET_3(reg, init_value, f1, v1, f2, v2, f3, v3) \ + REG_SET_N(reg, 3, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3) + +#define REG_SET_4(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4) \ + REG_SET_N(reg, 4, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4) + +#define REG_SET_5(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ + f5, v5) \ + REG_SET_N(reg, 6, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4,\ + FN(reg, f5), v5) + +#define REG_SET_6(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ + f5, v5, f6, v6) \ + REG_SET_N(reg, 6, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4,\ + FN(reg, f5), v5,\ + FN(reg, f6), v6) + +#define REG_SET_7(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ + f5, v5, f6, v6, f7, v7) \ + REG_SET_N(reg, 7, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4,\ + FN(reg, f5), v5,\ + FN(reg, f6), v6,\ + FN(reg, f7), v7) + +#define REG_SET_10(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \ + v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ + REG_SET_N(reg, 10, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10) + +/* macro to get register fields + * read given register and fill in field value in output parameter */ +#define REG_GET(reg_name, field, val) \ + generic_reg_get(CTX, REG(reg_name), \ + FN(reg_name, field), val) + +#define REG_GET_2(reg_name, f1, v1, f2, v2) \ + generic_reg_get2(CTX, REG(reg_name), \ + FN(reg_name, f1), v1, \ + FN(reg_name, f2), v2) + +#define REG_GET_3(reg_name, f1, v1, f2, v2, f3, v3) \ + generic_reg_get3(CTX, REG(reg_name), \ + FN(reg_name, f1), v1, \ + FN(reg_name, f2), v2, \ + FN(reg_name, f3), v3) + +#define REG_GET_5(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \ + generic_reg_get5(CTX, REG(reg_name), \ + FN(reg_name, f1), v1, \ + FN(reg_name, f2), v2, \ + FN(reg_name, f3), v3, \ + FN(reg_name, f4), v4, \ + FN(reg_name, f5), v5) + +/* macro to poll and wait for a register field to read back given value */ + +#define REG_WAIT(reg_name, field, val, delay, max_try) \ + generic_reg_wait(CTX, \ + REG(reg_name), FN(reg_name, field), val,\ + delay, max_try, __func__) + +/* macro to update (read, modify, write) register fields + */ +#define REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_ex(CTX, \ + REG(reg_name), \ + REG_READ(reg_name), \ + n, __VA_ARGS__) + +#define REG_UPDATE(reg_name, field, val) \ + REG_UPDATE_N(reg_name, 1, \ + FN(reg_name, field), val) + +#define REG_UPDATE_2(reg, f1, v1, f2, v2) \ + REG_UPDATE_N(reg, 2,\ + FN(reg, f1), v1,\ + FN(reg, f2), v2) + +#define REG_UPDATE_3(reg, f1, v1, f2, v2, f3, v3) \ + REG_UPDATE_N(reg, 3, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3) + +#define REG_UPDATE_4(reg, f1, v1, f2, v2, f3, v3, f4, v4) \ + REG_UPDATE_N(reg, 4, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4) + +#define REG_UPDATE_5(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \ + REG_UPDATE_N(reg, 5, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5) + +#define REG_UPDATE_6(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) \ + REG_UPDATE_N(reg, 6, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6) + +#define REG_UPDATE_7(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) \ + REG_UPDATE_N(reg, 7, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7) + +#define REG_UPDATE_8(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) \ + REG_UPDATE_N(reg, 8, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8) + +#define REG_UPDATE_9(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) \ + REG_UPDATE_N(reg, 9, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9) + +#define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ + REG_UPDATE_N(reg, 10, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10) + +/* macro to update a register field to specified values in given sequences. + * useful when toggling bits + */ +#define REG_UPDATE_SEQ(reg, field, value1, value2) \ +{ uint32_t val = REG_UPDATE(reg, field, value1); \ + REG_SET(reg, val, field, value2); } + +/* macro to update fields in register 1 field at a time in given order */ +#define REG_UPDATE_1BY1_2(reg, f1, v1, f2, v2) \ +{ uint32_t val = REG_UPDATE(reg, f1, v1); \ + REG_SET(reg, val, f2, v2); } + +#define REG_UPDATE_1BY1_3(reg, f1, v1, f2, v2, f3, v3) \ +{ uint32_t val = REG_UPDATE(reg, f1, v1); \ + val = REG_SET(reg, val, f2, v2); \ + REG_SET(reg, val, f3, v3); } + +uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr, + uint8_t shift, uint32_t mask, uint32_t *field_value); + +uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2); + +uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3); + +uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3, + uint8_t shift4, uint32_t mask4, uint32_t *field_value4, + uint8_t shift5, uint32_t mask5, uint32_t *field_value5); + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h new file mode 100644 index 000000000000..8dd676de6b07 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -0,0 +1,164 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + */ + +#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ +#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ + +#include "core_types.h" +#include "core_status.h" +#include "core_dc.h" +#include "dal_asic_id.h" + +/* TODO unhardcode, 4 for CZ*/ +#define MEMORY_TYPE_MULTIPLIER 4 + +enum dce_version resource_parse_asic_id( + struct hw_asic_id asic_id); + +struct resource_caps { + int num_timing_generator; + int num_video_plane; + int num_audio; + int num_stream_encoder; + int num_pll; +}; + +struct resource_straps { + uint32_t hdmi_disable; + uint32_t dc_pinstraps_audio; + uint32_t audio_stream_number; +}; + +struct resource_create_funcs { + void (*read_dce_straps)( + struct dc_context *ctx, struct resource_straps *straps); + + struct audio *(*create_audio)( + struct dc_context *ctx, unsigned int inst); + + struct stream_encoder *(*create_stream_encoder)( + enum engine_id eng_id, struct dc_context *ctx); + + struct dce_hwseq *(*create_hwseq)( + struct dc_context *ctx); +}; + +bool resource_construct( + unsigned int num_virtual_links, + struct core_dc *dc, + struct resource_pool *pool, + const struct resource_create_funcs *create_funcs); + +struct resource_pool *dc_create_resource_pool( + struct core_dc *dc, + int num_virtual_links, + enum dce_version dc_version, + struct hw_asic_id asic_id); + +void dc_destroy_resource_pool(struct core_dc *dc); + +enum dc_status resource_map_pool_resources( + const struct core_dc *dc, + struct validate_context *context); + +bool resource_build_scaling_params( + const struct dc_surface *surface, + struct pipe_ctx *pipe_ctx); + +enum dc_status resource_build_scaling_params_for_context( + const struct core_dc *dc, + struct validate_context *context); + +void resource_build_info_frame(struct pipe_ctx *pipe_ctx); + +void resource_unreference_clock_source( + struct resource_context *res_ctx, + struct clock_source *clock_source); + +void resource_reference_clock_source( + struct resource_context *res_ctx, + struct clock_source *clock_source); + +bool resource_are_streams_timing_synchronizable( + const struct core_stream *stream1, + const struct core_stream *stream2); + +struct clock_source *resource_find_used_clk_src_for_sharing( + struct resource_context *res_ctx, + struct pipe_ctx *pipe_ctx); + +struct clock_source *dc_resource_find_first_free_pll( + struct resource_context *res_ctx); + +struct pipe_ctx *resource_get_head_pipe_for_stream( + struct resource_context *res_ctx, + const struct core_stream *stream); + +bool resource_attach_surfaces_to_context( + const struct dc_surface *const *surfaces, + int surface_count, + const struct dc_target *dc_target, + struct validate_context *context); + +struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx); + +bool resource_is_stream_unchanged( + const struct validate_context *old_context, struct core_stream *stream); + +bool is_target_unchanged( + const struct core_target *old_target, const struct core_target *target); +bool resource_validate_attach_surfaces( + const struct dc_validation_set set[], + int set_count, + const struct validate_context *old_context, + struct validate_context *context); + +void validate_guaranteed_copy_target( + struct validate_context *context, + int max_targets); + +void resource_validate_ctx_update_pointer_after_copy( + const struct validate_context *src_ctx, + struct validate_context *dst_ctx); + +void resource_validate_ctx_copy_construct( + const struct validate_context *src_ctx, + struct validate_context *dst_ctx); + +void resource_validate_ctx_destruct(struct validate_context *context); + +enum dc_status resource_map_clock_resources( + const struct core_dc *dc, + struct validate_context *context); + +enum dc_status resource_map_phy_clock_resources( + const struct core_dc *dc, + struct validate_context *context); + +bool pipe_need_reprogram( + struct pipe_ctx *pipe_ctx_old, + struct pipe_ctx *pipe_ctx); + + +#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile new file mode 100644 index 000000000000..02710333ce0a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -0,0 +1,28 @@ +# +# Makefile for the 'audio' sub-component of DAL. +# It provides the control and status of HW adapter resources, +# that are global for the ASIC and sharable between pipes. + +IRQ = irq_service.o + +AMD_DAL_IRQ = $(addprefix $(AMDDALPATH)/dc/irq/,$(IRQ)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ) + +############################################################################### +# DCE 8x +############################################################################### +IRQ_DCE80 = irq_service_dce80.o + +AMD_DAL_IRQ_DCE80 = $(addprefix $(AMDDALPATH)/dc/irq/dce80/,$(IRQ_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE80) + +############################################################################### +# DCE 11x +############################################################################### +IRQ_DCE11 = irq_service_dce110.o + +AMD_DAL_IRQ_DCE11 = $(addprefix $(AMDDALPATH)/dc/irq/dce110/,$(IRQ_DCE11)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE11) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c new file mode 100644 index 000000000000..f3eda1b4eebf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -0,0 +1,367 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "irq_service_dce110.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" +#include "ivsrcid/ivsrcid_vislands30.h" + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + DC_HPD_INT_STATUS, + DC_HPD_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + DC_HPD_INT_CONTROL, + DC_HPD_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ + .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ + .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\ + ~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\ + },\ + .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ + .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ + .ack_value = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\ + .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ + .enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ + .enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\ + ~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\ + .ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\ + .ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ + .ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\ + .status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\ + .funcs = &hpd_rx_irq_info_funcs\ + } +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + .enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\ + .enable_mask =\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + .enable_value = {\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ + .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ + .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\ + .enable_mask =\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + .enable_value = {\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ + .ack_mask =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .ack_value =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + +bool dal_irq_service_dummy_set( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable) +{ + dm_logger_write( + irq_service->ctx->logger, LOG_ERROR, + "%s: called for non-implemented irq source\n", + __func__); + return false; +} + +bool dal_irq_service_dummy_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + dm_logger_write( + irq_service->ctx->logger, LOG_ERROR, + "%s: called for non-implemented irq source\n", + __func__); + return false; +} + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(0), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_rx_int_entry(0), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + pflip_int_entry(4), + pflip_int_entry(5), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), +}; + +enum dc_irq_source to_dal_irq_source_dce110( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + switch (src_id) { + case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE1; + case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE2; + case VISLANDS30_IV_SRCID_D3_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE3; + case VISLANDS30_IV_SRCID_D4_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE4; + case VISLANDS30_IV_SRCID_D5_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE5; + case VISLANDS30_IV_SRCID_D6_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE6; + case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP1; + case VISLANDS30_IV_SRCID_D2_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP2; + case VISLANDS30_IV_SRCID_D3_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP3; + case VISLANDS30_IV_SRCID_D4_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP4; + case VISLANDS30_IV_SRCID_D5_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP5; + case VISLANDS30_IV_SRCID_D6_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP6; + + case VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A: + /* generic src_id for all HPD and HPDRX interrupts */ + switch (ext_id) { + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_A: + return DC_IRQ_SOURCE_HPD1; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_B: + return DC_IRQ_SOURCE_HPD2; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_C: + return DC_IRQ_SOURCE_HPD3; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_D: + return DC_IRQ_SOURCE_HPD4; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_E: + return DC_IRQ_SOURCE_HPD5; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_F: + return DC_IRQ_SOURCE_HPD6; + case VISLANDS30_IV_EXTID_HPD_RX_A: + return DC_IRQ_SOURCE_HPD1RX; + case VISLANDS30_IV_EXTID_HPD_RX_B: + return DC_IRQ_SOURCE_HPD2RX; + case VISLANDS30_IV_EXTID_HPD_RX_C: + return DC_IRQ_SOURCE_HPD3RX; + case VISLANDS30_IV_EXTID_HPD_RX_D: + return DC_IRQ_SOURCE_HPD4RX; + case VISLANDS30_IV_EXTID_HPD_RX_E: + return DC_IRQ_SOURCE_HPD5RX; + case VISLANDS30_IV_EXTID_HPD_RX_F: + return DC_IRQ_SOURCE_HPD6RX; + default: + return DC_IRQ_SOURCE_INVALID; + } + break; + + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +static const struct irq_service_funcs irq_service_funcs_dce110 = { + .to_dal_irq_source = to_dal_irq_source_dce110 +}; + +bool construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!dal_irq_service_construct(irq_service, init_data)) + return false; + + irq_service->info = irq_source_info_dce110; + irq_service->funcs = &irq_service_funcs_dce110; + + return true; +} + +struct irq_service *dal_irq_service_dce110_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + + if (!irq_service) + return NULL; + + if (construct(irq_service, init_data)) + return irq_service; + + dm_free(irq_service); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h new file mode 100644 index 000000000000..a84f360c6515 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h @@ -0,0 +1,48 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCE110_H__ +#define __DAL_IRQ_SERVICE_DCE110_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dce110_create( + struct irq_service_init_data *init_data); + +enum dc_irq_source to_dal_irq_source_dce110( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id); + +bool dal_irq_service_dummy_set( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable); + +bool dal_irq_service_dummy_ack( + struct irq_service *irq_service, + const struct irq_source_info *info); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c new file mode 100644 index 000000000000..8b4f45389783 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -0,0 +1,283 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "irq_service_dce80.h" +#include "../dce110/irq_service_dce110.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "ivsrcid/ivsrcid_vislands30.h" + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + DC_HPD1_INT_STATUS, + DC_HPD1_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + DC_HPD1_INT_CONTROL, + DC_HPD1_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_INVALID + reg_num] = {\ + .enable_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\ + ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\ + },\ + .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\ + .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\ + .status_reg = mmDC_HPD ## reg_num ## _INT_STATUS,\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD6 + reg_num] = {\ + .enable_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\ + ~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\ + .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\ + .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\ + .status_reg = mmDC_HPD ## reg_num ## _INT_STATUS,\ + .funcs = &hpd_rx_irq_info_funcs\ + } + +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + .enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\ + .enable_mask =\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + .enable_value = {\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ + .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ + .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\ + .enable_mask =\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + .enable_value = {\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ + .ack_mask =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .ack_value =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dce80[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_int_entry(6), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + hpd_rx_int_entry(6), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + pflip_int_entry(4), + pflip_int_entry(5), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), +}; + +static const struct irq_service_funcs irq_service_funcs_dce80 = { + .to_dal_irq_source = to_dal_irq_source_dce110 +}; + +static bool construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!dal_irq_service_construct(irq_service, init_data)) + return false; + + irq_service->info = irq_source_info_dce80; + irq_service->funcs = &irq_service_funcs_dce80; + + return true; +} + +struct irq_service *dal_irq_service_dce80_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + + if (!irq_service) + return NULL; + + if (construct(irq_service, init_data)) + return irq_service; + + dm_free(irq_service); + return NULL; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h new file mode 100644 index 000000000000..3dd1013576ea --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.h @@ -0,0 +1,35 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCE80_H__ +#define __DAL_IRQ_SERVICE_DCE80_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dce80_create( + struct irq_service_init_data *init_data); + +#endif + diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c new file mode 100644 index 000000000000..fbaa2fc00ddb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -0,0 +1,163 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/irq_service_interface.h" +#include "include/logger_interface.h" + +#include "dce110/irq_service_dce110.h" + + +#include "dce80/irq_service_dce80.h" + + +#include "reg_helper.h" +#include "irq_service.h" + + + +#define CTX \ + irq_service->ctx + +bool dal_irq_service_construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!init_data || !init_data->ctx) + return false; + + irq_service->ctx = init_data->ctx; + return true; +} + +void dal_irq_service_destroy(struct irq_service **irq_service) +{ + if (!irq_service || !*irq_service) { + BREAK_TO_DEBUGGER(); + return; + } + + dm_free(*irq_service); + + *irq_service = NULL; +} + +const struct irq_source_info *find_irq_source_info( + struct irq_service *irq_service, + enum dc_irq_source source) +{ + if (source > DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID) + return NULL; + + return &irq_service->info[source]; +} + +void dal_irq_service_set_generic( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable) +{ + uint32_t addr = info->enable_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + + value = (value & ~info->enable_mask) | + (info->enable_value[enable ? 0 : 1] & info->enable_mask); + dm_write_reg(irq_service->ctx, addr, value); +} + +bool dal_irq_service_set( + struct irq_service *irq_service, + enum dc_irq_source source, + bool enable) +{ + const struct irq_source_info *info = + find_irq_source_info(irq_service, source); + + if (!info) { + dm_logger_write( + irq_service->ctx->logger, LOG_ERROR, + "%s: cannot find irq info table entry for %d\n", + __func__, + source); + return false; + } + + dal_irq_service_ack(irq_service, source); + + if (info->funcs->set) + return info->funcs->set(irq_service, info, enable); + + dal_irq_service_set_generic(irq_service, info, enable); + + return true; +} + +void dal_irq_service_ack_generic( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->ack_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + + value = (value & ~info->ack_mask) | + (info->ack_value & info->ack_mask); + dm_write_reg(irq_service->ctx, addr, value); +} + +bool dal_irq_service_ack( + struct irq_service *irq_service, + enum dc_irq_source source) +{ + const struct irq_source_info *info = + find_irq_source_info(irq_service, source); + + if (!info) { + dm_logger_write( + irq_service->ctx->logger, LOG_ERROR, + "%s: cannot find irq info table entry for %d\n", + __func__, + source); + return false; + } + + if (info->funcs->ack) + return info->funcs->ack(irq_service, info); + + dal_irq_service_ack_generic(irq_service, info); + + return true; +} + +enum dc_irq_source dal_irq_service_to_irq_source( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + return irq_service->funcs->to_dal_irq_source( + irq_service, + src_id, + ext_id); +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h new file mode 100644 index 000000000000..a2a2d6965c2f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h @@ -0,0 +1,85 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_H__ +#define __DAL_IRQ_SERVICE_H__ + +#include "include/irq_service_interface.h" + +#include "irq_types.h" + +struct irq_service; +struct irq_source_info; + +struct irq_source_info_funcs { + bool (*set)( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable); + bool (*ack)( + struct irq_service *irq_service, + const struct irq_source_info *info); +}; + +struct irq_source_info { + uint32_t src_id; + uint32_t ext_id; + uint32_t enable_reg; + uint32_t enable_mask; + uint32_t enable_value[2]; + uint32_t ack_reg; + uint32_t ack_mask; + uint32_t ack_value; + uint32_t status_reg; + const struct irq_source_info_funcs *funcs; +}; + +struct irq_service_funcs { + enum dc_irq_source (*to_dal_irq_source)( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id); +}; + +struct irq_service { + struct dc_context *ctx; + const struct irq_source_info *info; + const struct irq_service_funcs *funcs; +}; + +bool dal_irq_service_construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data); + +void dal_irq_service_ack_generic( + struct irq_service *irq_service, + const struct irq_source_info *info); + +void dal_irq_service_set_generic( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h new file mode 100644 index 000000000000..e4b4b99a86fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -0,0 +1,185 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_TYPES_H__ +#define __DAL_IRQ_TYPES_H__ + +struct dc_context; + +typedef void (*interrupt_handler)(void *); + +typedef void *irq_handler_idx; +#define DAL_INVALID_IRQ_HANDLER_IDX NULL + +/* The order of the IRQ sources is important and MUST match the one's +of base driver */ +enum dc_irq_source { + /* Use as mask to specify invalid irq source */ + DC_IRQ_SOURCE_INVALID = 0, + + DC_IRQ_SOURCE_HPD1, + DC_IRQ_SOURCE_HPD2, + DC_IRQ_SOURCE_HPD3, + DC_IRQ_SOURCE_HPD4, + DC_IRQ_SOURCE_HPD5, + DC_IRQ_SOURCE_HPD6, + + DC_IRQ_SOURCE_HPD1RX, + DC_IRQ_SOURCE_HPD2RX, + DC_IRQ_SOURCE_HPD3RX, + DC_IRQ_SOURCE_HPD4RX, + DC_IRQ_SOURCE_HPD5RX, + DC_IRQ_SOURCE_HPD6RX, + + DC_IRQ_SOURCE_I2C_DDC1, + DC_IRQ_SOURCE_I2C_DDC2, + DC_IRQ_SOURCE_I2C_DDC3, + DC_IRQ_SOURCE_I2C_DDC4, + DC_IRQ_SOURCE_I2C_DDC5, + DC_IRQ_SOURCE_I2C_DDC6, + + DC_IRQ_SOURCE_DPSINK1, + DC_IRQ_SOURCE_DPSINK2, + DC_IRQ_SOURCE_DPSINK3, + DC_IRQ_SOURCE_DPSINK4, + DC_IRQ_SOURCE_DPSINK5, + DC_IRQ_SOURCE_DPSINK6, + + DC_IRQ_SOURCE_TIMER, + + DC_IRQ_SOURCE_PFLIP_FIRST, + DC_IRQ_SOURCE_PFLIP1 = DC_IRQ_SOURCE_PFLIP_FIRST, + DC_IRQ_SOURCE_PFLIP2, + DC_IRQ_SOURCE_PFLIP3, + DC_IRQ_SOURCE_PFLIP4, + DC_IRQ_SOURCE_PFLIP5, + DC_IRQ_SOURCE_PFLIP6, + DC_IRQ_SOURCE_PFLIP_UNDERLAY0, + DC_IRQ_SOURCE_PFLIP_LAST = DC_IRQ_SOURCE_PFLIP_UNDERLAY0, + + DC_IRQ_SOURCE_GPIOPAD0, + DC_IRQ_SOURCE_GPIOPAD1, + DC_IRQ_SOURCE_GPIOPAD2, + DC_IRQ_SOURCE_GPIOPAD3, + DC_IRQ_SOURCE_GPIOPAD4, + DC_IRQ_SOURCE_GPIOPAD5, + DC_IRQ_SOURCE_GPIOPAD6, + DC_IRQ_SOURCE_GPIOPAD7, + DC_IRQ_SOURCE_GPIOPAD8, + DC_IRQ_SOURCE_GPIOPAD9, + DC_IRQ_SOURCE_GPIOPAD10, + DC_IRQ_SOURCE_GPIOPAD11, + DC_IRQ_SOURCE_GPIOPAD12, + DC_IRQ_SOURCE_GPIOPAD13, + DC_IRQ_SOURCE_GPIOPAD14, + DC_IRQ_SOURCE_GPIOPAD15, + DC_IRQ_SOURCE_GPIOPAD16, + DC_IRQ_SOURCE_GPIOPAD17, + DC_IRQ_SOURCE_GPIOPAD18, + DC_IRQ_SOURCE_GPIOPAD19, + DC_IRQ_SOURCE_GPIOPAD20, + DC_IRQ_SOURCE_GPIOPAD21, + DC_IRQ_SOURCE_GPIOPAD22, + DC_IRQ_SOURCE_GPIOPAD23, + DC_IRQ_SOURCE_GPIOPAD24, + DC_IRQ_SOURCE_GPIOPAD25, + DC_IRQ_SOURCE_GPIOPAD26, + DC_IRQ_SOURCE_GPIOPAD27, + DC_IRQ_SOURCE_GPIOPAD28, + DC_IRQ_SOURCE_GPIOPAD29, + DC_IRQ_SOURCE_GPIOPAD30, + + DC_IRQ_SOURCE_DC1UNDERFLOW, + DC_IRQ_SOURCE_DC2UNDERFLOW, + DC_IRQ_SOURCE_DC3UNDERFLOW, + DC_IRQ_SOURCE_DC4UNDERFLOW, + DC_IRQ_SOURCE_DC5UNDERFLOW, + DC_IRQ_SOURCE_DC6UNDERFLOW, + + DC_IRQ_SOURCE_DMCU_SCP, + DC_IRQ_SOURCE_VBIOS_SW, + + DC_IRQ_SOURCE_VUPDATE1, + DC_IRQ_SOURCE_VUPDATE2, + DC_IRQ_SOURCE_VUPDATE3, + DC_IRQ_SOURCE_VUPDATE4, + DC_IRQ_SOURCE_VUPDATE5, + DC_IRQ_SOURCE_VUPDATE6, + + DAL_IRQ_SOURCES_NUMBER +}; + +enum irq_type +{ + IRQ_TYPE_PFLIP = DC_IRQ_SOURCE_PFLIP1, + IRQ_TYPE_VUPDATE = DC_IRQ_SOURCE_VUPDATE1, +}; + +#define DAL_VALID_IRQ_SRC_NUM(src) \ + ((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) + +/* Number of Page Flip IRQ Sources. */ +#define DAL_PFLIP_IRQ_SRC_NUM \ + (DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1) + +/* the number of contexts may be expanded in the future based on needs */ +enum dc_interrupt_context { + INTERRUPT_LOW_IRQ_CONTEXT = 0, + INTERRUPT_HIGH_IRQ_CONTEXT, + INTERRUPT_CONTEXT_NUMBER +}; + +enum dc_interrupt_porlarity { + INTERRUPT_POLARITY_DEFAULT = 0, + INTERRUPT_POLARITY_LOW = INTERRUPT_POLARITY_DEFAULT, + INTERRUPT_POLARITY_HIGH, + INTERRUPT_POLARITY_BOTH +}; + +#define DC_DECODE_INTERRUPT_POLARITY(int_polarity) \ + (int_polarity == INTERRUPT_POLARITY_LOW) ? "Low" : \ + (int_polarity == INTERRUPT_POLARITY_HIGH) ? "High" : \ + (int_polarity == INTERRUPT_POLARITY_BOTH) ? "Both" : "Invalid" + +struct dc_timer_interrupt_params { + uint32_t micro_sec_interval; + enum dc_interrupt_context int_context; +}; + +struct dc_interrupt_params { + /* The polarity *change* which will trigger an interrupt. + * If 'requested_polarity == INTERRUPT_POLARITY_BOTH', then + * 'current_polarity' must be initialised. */ + enum dc_interrupt_porlarity requested_polarity; + /* If 'requested_polarity == INTERRUPT_POLARITY_BOTH', + * 'current_polarity' should contain the current state, which means + * the interrupt will be triggered when state changes from what is, + * in 'current_polarity'. */ + enum dc_interrupt_porlarity current_polarity; + enum dc_irq_source irq_source; + enum dc_interrupt_context int_context; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h new file mode 100644 index 000000000000..459a2741eccb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -0,0 +1,61 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _OS_TYPES_H_ +#define _OS_TYPES_H_ + +#if defined __KERNEL__ + +#include +#include +#include + +#include "cgs_linux.h" + +#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU) +#define BIGENDIAN_CPU +#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU) +#define LITTLEENDIAN_CPU +#endif + +#undef READ +#undef WRITE +#undef FRAME_SIZE + +#define dm_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__) + +#define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__) + +#define dm_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__) + +#define dm_vlog(fmt, args) vprintk(fmt, args) + +#define dm_min(x, y) min(x, y) +#define dm_max(x, y) max(x, y) + +#endif + + +#endif /* _OS_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/Makefile b/drivers/gpu/drm/amd/display/dc/virtual/Makefile new file mode 100644 index 000000000000..fc0b7318d9cc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the virtual sub-component of DAL. +# It provides the control and status of HW CRTC block. + +VIRTUAL = virtual_link_encoder.o virtual_stream_encoder.o + +AMD_DAL_VIRTUAL = $(addprefix $(AMDDALPATH)/dc/virtual/,$(VIRTUAL)) + +AMD_DISPLAY_FILES += $(AMD_DAL_VIRTUAL) diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c new file mode 100644 index 000000000000..bb4433ff3b6e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -0,0 +1,150 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dm_services_types.h" + +#include "virtual_link_encoder.h" + +#define VIRTUAL_MAX_PIXEL_CLK_IN_KHZ 600000 + +static bool virtual_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + struct pipe_ctx *pipe_ctx) { return true; } + +static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} + +static void virtual_link_encoder_setup( + struct link_encoder *enc, + enum signal_type signal) {} + +static void virtual_link_encoder_enable_tmds_output( + struct link_encoder *enc, + enum clock_source_id clock_source, + enum dc_color_depth color_depth, + bool hdmi, + bool dual_link, + uint32_t pixel_clock) {} + +static void virtual_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) {} + +static void virtual_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) {} + +static void virtual_link_encoder_disable_output( + struct link_encoder *link_enc, + enum signal_type signal) {} + +static void virtual_link_encoder_dp_set_lane_settings( + struct link_encoder *enc, + const struct link_training_settings *link_settings) {} + +static void virtual_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param) {} + +static void virtual_link_encoder_update_mst_stream_allocation_table( + struct link_encoder *enc, + const struct link_mst_stream_allocation_table *table) {} + +static void virtual_link_encoder_set_lcd_backlight_level( + struct link_encoder *enc, + uint32_t level) {} + +static void virtual_link_encoder_set_dmcu_backlight_level( + struct link_encoder *enc, + uint32_t level, + uint32_t frame_ramp, + uint32_t controller_id) {} + +static void virtual_link_encoder_edp_backlight_control( + struct link_encoder *enc, + bool enable) {} + +static void virtual_link_encoder_edp_power_control( + struct link_encoder *enc, + bool power_up) {} + +static void virtual_link_encoder_connect_dig_be_to_fe( + struct link_encoder *enc, + enum engine_id engine, + bool connect) {} + +static void virtual_link_encoder_destroy(struct link_encoder **enc) +{ + dm_free(*enc); + *enc = NULL; +} + + +static const struct link_encoder_funcs virtual_lnk_enc_funcs = { + .validate_output_with_stream = + virtual_link_encoder_validate_output_with_stream, + .hw_init = virtual_link_encoder_hw_init, + .setup = virtual_link_encoder_setup, + .enable_tmds_output = virtual_link_encoder_enable_tmds_output, + .enable_dp_output = virtual_link_encoder_enable_dp_output, + .enable_dp_mst_output = virtual_link_encoder_enable_dp_mst_output, + .disable_output = virtual_link_encoder_disable_output, + .dp_set_lane_settings = virtual_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + virtual_link_encoder_update_mst_stream_allocation_table, + .set_lcd_backlight_level = virtual_link_encoder_set_lcd_backlight_level, + .set_dmcu_backlight_level = + virtual_link_encoder_set_dmcu_backlight_level, + .backlight_control = virtual_link_encoder_edp_backlight_control, + .power_control = virtual_link_encoder_edp_power_control, + .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, + .destroy = virtual_link_encoder_destroy +}; + +bool virtual_link_encoder_construct( + struct link_encoder *enc, const struct encoder_init_data *init_data) +{ + enc->funcs = &virtual_lnk_enc_funcs; + enc->ctx = init_data->ctx; + enc->id = init_data->encoder; + + enc->hpd_source = init_data->hpd_source; + enc->connector = init_data->connector; + + enc->transmitter = init_data->transmitter; + + enc->features.max_pixel_clock = VIRTUAL_MAX_PIXEL_CLK_IN_KHZ; + + enc->output_signals = SIGNAL_TYPE_VIRTUAL; + + enc->preferred_engine = ENGINE_ID_VIRTUAL; + + return true; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h new file mode 100644 index 000000000000..eb1a94fb8a9b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_VIRTUAL_LINK_ENCODER_H__ +#define __DC_VIRTUAL_LINK_ENCODER_H__ + +#include "link_encoder.h" + +bool virtual_link_encoder_construct( + struct link_encoder *enc, const struct encoder_init_data *init_data); + +#endif /* __DC_VIRTUAL_LINK_ENCODER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c new file mode 100644 index 000000000000..8de21d9a8079 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -0,0 +1,132 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "virtual_stream_encoder.h" + +static void virtual_stream_encoder_dp_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space) {} + +static void virtual_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) {} + +static void virtual_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) {} + +static void virtual_stream_encoder_set_mst_bandwidth( + struct stream_encoder *enc, + struct fixed31_32 avg_time_slots_per_mtp) {} + +static void virtual_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) {} + +static void virtual_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) {} + +static void virtual_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) {} + +static void virtual_stream_encoder_stop_dp_info_packets( + struct stream_encoder *enc) {} + +static void virtual_stream_encoder_dp_blank( + struct stream_encoder *enc) {} + +static void virtual_stream_encoder_dp_unblank( + struct stream_encoder *enc, + const struct encoder_unblank_param *param) {} + +static void virtual_audio_mute_control( + struct stream_encoder *enc, + bool mute) {} + +static const struct stream_encoder_funcs virtual_str_enc_funcs = { + .dp_set_stream_attribute = + virtual_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + virtual_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + virtual_stream_encoder_dvi_set_stream_attribute, + .set_mst_bandwidth = + virtual_stream_encoder_set_mst_bandwidth, + .update_hdmi_info_packets = + virtual_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + virtual_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets = + virtual_stream_encoder_update_dp_info_packets, + .stop_dp_info_packets = + virtual_stream_encoder_stop_dp_info_packets, + .dp_blank = + virtual_stream_encoder_dp_blank, + .dp_unblank = + virtual_stream_encoder_dp_unblank, + + .audio_mute_control = virtual_audio_mute_control, +}; + +bool virtual_stream_encoder_construct( + struct stream_encoder *enc, + struct dc_context *ctx, + struct dc_bios *bp) +{ + if (!enc) + return false; + if (!bp) + return false; + + enc->funcs = &virtual_str_enc_funcs; + enc->ctx = ctx; + enc->id = ENGINE_ID_VIRTUAL; + enc->bp = bp; + + return true; +} + +struct stream_encoder *virtual_stream_encoder_create( + struct dc_context *ctx, struct dc_bios *bp) +{ + struct stream_encoder *enc = dm_alloc(sizeof(*enc)); + + if (!enc) + return NULL; + + if (virtual_stream_encoder_construct(enc, ctx, bp)) + return enc; + + BREAK_TO_DEBUGGER(); + dm_free(enc); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h new file mode 100644 index 000000000000..bf3422c66976 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.h @@ -0,0 +1,39 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_VIRTUAL_STREAM_ENCODER_H__ +#define __DC_VIRTUAL_STREAM_ENCODER_H__ + +#include "stream_encoder.h" + +struct stream_encoder *virtual_stream_encoder_create( + struct dc_context *ctx, struct dc_bios *bp); + +bool virtual_stream_encoder_construct( + struct stream_encoder *enc, + struct dc_context *ctx, + struct dc_bios *bp); + +#endif /* __DC_VIRTUAL_STREAM_ENCODER_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_interface.h b/drivers/gpu/drm/amd/display/include/asic_capability_interface.h new file mode 100644 index 000000000000..57cc72fdc560 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/asic_capability_interface.h @@ -0,0 +1,55 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of enc software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and enc permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_ASIC_CAPABILITY_INTERFACE_H__ +#define __DAL_ASIC_CAPABILITY_INTERFACE_H__ + +/* Include */ +#include "include/asic_capability_types.h" + +/* Forward declaration */ +struct hw_asic_id; + +/* ASIC capability */ +struct asic_capability { + struct dc_context *ctx; + struct asic_caps caps; + struct asic_stereo_3d_caps stereo_3d_caps; + struct asic_bugs bugs; + uint32_t data[ASIC_DATA_MAX_NUMBER]; +}; + +/** + * Interfaces + */ + +/* Create and initialize ASIC capability */ +struct asic_capability *dal_asic_capability_create(struct hw_asic_id *init, + struct dc_context *ctx); + +/* Destroy ASIC capability and free memory space */ +void dal_asic_capability_destroy(struct asic_capability **cap); + +#endif /* __DAL_ASIC_CAPABILITY_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_types.h b/drivers/gpu/drm/amd/display/include/asic_capability_types.h new file mode 100644 index 000000000000..c44dae043599 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/asic_capability_types.h @@ -0,0 +1,116 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_ASIC_CAPABILITY_TYPES_H__ +#define __DAL_ASIC_CAPABILITY_TYPES_H__ + +/* + * ASIC Capabilities + */ +struct asic_caps { + bool CONSUMER_SINGLE_SELECTED_TIMING:1; + bool UNDERSCAN_ADJUST:1; + bool DELTA_SIGMA_SUPPORT:1; + bool PANEL_SELF_REFRESH_SUPPORTED:1; + bool IS_FUSION:1; + bool DP_MST_SUPPORTED:1; + bool UNDERSCAN_FOR_HDMI_ONLY:1; + bool DVI_CLOCK_SHARE_CAPABILITY:1; + bool SUPPORT_CEA861E_FINAL:1; + bool MIRABILIS_SUPPORTED:1; + bool MIRABILIS_ENABLED_BY_DEFAULT:1; + bool DEVICE_TAG_REMAP_SUPPORTED:1; + bool HEADLESS_NO_OPM_SUPPORTED:1; + bool WIRELESS_LIMIT_TO_720P:1; + bool WIRELESS_FULL_TIMING_ADJUSTMENT:1; + bool WIRELESS_TIMING_ADJUSTMENT:1; + bool WIRELESS_COMPRESSED_AUDIO:1; + bool VCE_SUPPORTED:1; + bool HPD_CHECK_FOR_EDID:1; + bool NEED_MC_TUNING:1; + bool SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT:1; + bool DFSBYPASS_DYNAMIC_SUPPORT:1; + bool SUPPORT_8BPP:1; +}; + +/* + * ASIC Stereo 3D Caps + */ +struct asic_stereo_3d_caps { + bool SUPPORTED:1; + bool DISPLAY_BASED_ON_WS:1; + bool HDMI_FRAME_PACK:1; + bool INTERLACE_FRAME_PACK:1; + bool DISPLAYPORT_FRAME_PACK:1; + bool DISPLAYPORT_FRAME_ALT:1; + bool INTERLEAVE:1; +}; + +/* + * ASIC Bugs + */ +struct asic_bugs { + bool MST_SYMBOL_MISALIGNMENT:1; + bool PSR_2X_LANE_GANGING:1; + bool LB_WA_IS_SUPPORTED:1; + bool ROM_REGISTER_ACCESS:1; + bool PSR_WA_OVERSCAN_CRC_ERROR:1; +}; + +/* + * ASIC Data + */ +enum asic_data { + ASIC_DATA_FIRST = 0, + ASIC_DATA_DCE_VERSION = ASIC_DATA_FIRST, + ASIC_DATA_DCE_VERSION_MINOR, + ASIC_DATA_LINEBUFFER_SIZE, + ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY, + ASIC_DATA_MC_LATENCY, + ASIC_DATA_MC_LATENCY_SLOW, + ASIC_DATA_MEMORYTYPE_MULTIPLIER, + ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR, + ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE, + ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY, + ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN, + ASIC_DATA_DOWNSCALE_LIMIT, + ASIC_DATA_MAX_NUMBER /* end of enum */ +}; + +/* + * ASIC Feature Flags + */ +struct asic_feature_flags { + union { + uint32_t raw; + struct { + uint32_t LEGACY_CLIENT:1; + uint32_t PACKED_PIXEL_FORMAT:1; + uint32_t WORKSTATION_STEREO:1; + uint32_t WORKSTATION:1; + } bits; + }; +}; + +#endif /* __DAL_ASIC_CAPABILITY_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/audio_types.h b/drivers/gpu/drm/amd/display/include/audio_types.h new file mode 100644 index 000000000000..6364fbc24cfe --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/audio_types.h @@ -0,0 +1,106 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AUDIO_TYPES_H__ +#define __AUDIO_TYPES_H__ + +#include "signal_types.h" + +#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20 +#define MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 18 +#define MULTI_CHANNEL_SPLIT_NO_ASSO_INFO 0xFFFFFFFF + + +struct audio_crtc_info { + uint32_t h_total; + uint32_t h_active; + uint32_t v_active; + uint32_t pixel_repetition; + uint32_t requested_pixel_clock; /* in KHz */ + uint32_t calculated_pixel_clock; /* in KHz */ + uint32_t refresh_rate; + enum dc_color_depth color_depth; + bool interlaced; +}; +struct azalia_clock_info { + uint32_t pixel_clock_in_10khz; + uint32_t audio_dto_phase; + uint32_t audio_dto_module; + uint32_t audio_dto_wall_clock_ratio; +}; + +enum audio_dto_source { + DTO_SOURCE_UNKNOWN = 0, + DTO_SOURCE_ID0, + DTO_SOURCE_ID1, + DTO_SOURCE_ID2, + DTO_SOURCE_ID3, + DTO_SOURCE_ID4, + DTO_SOURCE_ID5 +}; + +/* PLL information required for AZALIA DTO calculation */ + +struct audio_pll_info { + uint32_t dp_dto_source_clock_in_khz; + uint32_t feed_back_divider; + enum audio_dto_source dto_source; + bool ss_enabled; + uint32_t ss_percentage; + uint32_t ss_percentage_divider; +}; + +struct audio_channel_associate_info { + union { + struct { + uint32_t ALL_CHANNEL_FL:4; + uint32_t ALL_CHANNEL_FR:4; + uint32_t ALL_CHANNEL_FC:4; + uint32_t ALL_CHANNEL_Sub:4; + uint32_t ALL_CHANNEL_SL:4; + uint32_t ALL_CHANNEL_SR:4; + uint32_t ALL_CHANNEL_BL:4; + uint32_t ALL_CHANNEL_BR:4; + } bits; + uint32_t u32all; + }; +}; + +struct audio_output { + /* Front DIG id. */ + enum engine_id engine_id; + /* encoder output signal */ + enum signal_type signal; + /* video timing */ + struct audio_crtc_info crtc_info; + /* PLL for audio */ + struct audio_pll_info pll_info; +}; + +enum audio_payload { + CHANNEL_SPLIT_MAPPINGCHANG = 0x9, +}; + +#endif /* __AUDIO_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_interface.h b/drivers/gpu/drm/amd/display/include/bios_parser_interface.h new file mode 100644 index 000000000000..d51101c5c6b0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/bios_parser_interface.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_INTERFACE_H__ +#define __DAL_BIOS_PARSER_INTERFACE_H__ + +#include "dc_bios_types.h" + +struct bios_parser; + +struct bp_init_data { + struct dc_context *ctx; + uint8_t *bios; +}; + +struct dc_bios *dal_bios_parser_create( + struct bp_init_data *init, + enum dce_version dce_version); + +void dal_bios_parser_destroy(struct dc_bios **dcb); + +#endif /* __DAL_BIOS_PARSER_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h new file mode 100644 index 000000000000..9ab9065735f7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -0,0 +1,338 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_TYPES_H__ + +#define __DAL_BIOS_PARSER_TYPES_H__ + +#include "dm_services.h" +#include "include/signal_types.h" +#include "include/grph_object_ctrl_defs.h" +#include "include/gpio_types.h" +#include "include/link_service_types.h" + +/* TODO: include signal_types.h and remove this enum */ +enum as_signal_type { + AS_SIGNAL_TYPE_NONE = 0L, /* no signal */ + AS_SIGNAL_TYPE_DVI, + AS_SIGNAL_TYPE_HDMI, + AS_SIGNAL_TYPE_LVDS, + AS_SIGNAL_TYPE_DISPLAY_PORT, + AS_SIGNAL_TYPE_GPU_PLL, + AS_SIGNAL_TYPE_UNKNOWN +}; + +enum bp_result { + BP_RESULT_OK = 0, /* There was no error */ + BP_RESULT_BADINPUT, /*Bad input parameter */ + BP_RESULT_BADBIOSTABLE, /* Bad BIOS table */ + BP_RESULT_UNSUPPORTED, /* BIOS Table is not supported */ + BP_RESULT_NORECORD, /* Record can't be found */ + BP_RESULT_FAILURE +}; + +enum bp_encoder_control_action { + /* direct VBIOS translation! Just to simplify the translation */ + ENCODER_CONTROL_DISABLE = 0, + ENCODER_CONTROL_ENABLE, + ENCODER_CONTROL_SETUP, + ENCODER_CONTROL_INIT +}; + +enum bp_transmitter_control_action { + /* direct VBIOS translation! Just to simplify the translation */ + TRANSMITTER_CONTROL_DISABLE = 0, + TRANSMITTER_CONTROL_ENABLE, + TRANSMITTER_CONTROL_BACKLIGHT_OFF, + TRANSMITTER_CONTROL_BACKLIGHT_ON, + TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS, + TRANSMITTER_CONTROL_LCD_SETF_TEST_START, + TRANSMITTER_CONTROL_LCD_SELF_TEST_STOP, + TRANSMITTER_CONTROL_INIT, + TRANSMITTER_CONTROL_DEACTIVATE, + TRANSMITTER_CONTROL_ACTIAVATE, + TRANSMITTER_CONTROL_SETUP, + TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS, + /* ATOM_TRANSMITTER_ACTION_POWER_ON. This action is for eDP only + * (power up the panel) + */ + TRANSMITTER_CONTROL_POWER_ON, + /* ATOM_TRANSMITTER_ACTION_POWER_OFF. This action is for eDP only + * (power down the panel) + */ + TRANSMITTER_CONTROL_POWER_OFF +}; + +enum bp_external_encoder_control_action { + EXTERNAL_ENCODER_CONTROL_DISABLE = 0, + EXTERNAL_ENCODER_CONTROL_ENABLE = 1, + EXTERNAL_ENCODER_CONTROL_INIT = 0x7, + EXTERNAL_ENCODER_CONTROL_SETUP = 0xf, + EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10, + EXTERNAL_ENCODER_CONTROL_BLANK = 0x11, +}; + +enum bp_pipe_control_action { + ASIC_PIPE_DISABLE = 0, + ASIC_PIPE_ENABLE, + ASIC_PIPE_INIT +}; + +struct bp_encoder_control { + enum bp_encoder_control_action action; + enum engine_id engine_id; + enum transmitter transmitter; + enum signal_type signal; + enum dc_lane_count lanes_number; + enum dc_color_depth color_depth; + bool enable_dp_audio; + uint32_t pixel_clock; /* khz */ +}; + +struct bp_external_encoder_control { + enum bp_external_encoder_control_action action; + enum engine_id engine_id; + enum dc_link_rate link_rate; + enum dc_lane_count lanes_number; + enum signal_type signal; + enum dc_color_depth color_depth; + bool coherent; + struct graphics_object_id encoder_id; + struct graphics_object_id connector_obj_id; + uint32_t pixel_clock; /* in KHz */ +}; + +struct bp_crtc_source_select { + enum engine_id engine_id; + enum controller_id controller_id; + /* from GPU Tx aka asic_signal */ + enum signal_type signal; + /* sink_signal may differ from asicSignal if Translator encoder */ + enum signal_type sink_signal; + enum display_output_bit_depth display_output_bit_depth; + bool enable_dp_audio; +}; + +struct bp_transmitter_control { + enum bp_transmitter_control_action action; + enum engine_id engine_id; + enum transmitter transmitter; /* PhyId */ + enum dc_lane_count lanes_number; + enum clock_source_id pll_id; /* needed for DCE 4.0 */ + enum signal_type signal; + enum dc_color_depth color_depth; /* not used for DCE6.0 */ + enum hpd_source_id hpd_sel; /* ucHPDSel, used for DCe6.0 */ + struct graphics_object_id connector_obj_id; + /* symClock; in 10kHz, pixel clock, in HDMI deep color mode, it should + * be pixel clock * deep_color_ratio (in KHz) + */ + uint32_t pixel_clock; + uint32_t lane_select; + uint32_t lane_settings; + bool coherent; + bool multi_path; + bool single_pll_mode; +}; + +struct bp_blank_crtc_parameters { + enum controller_id controller_id; + uint32_t black_color_rcr; + uint32_t black_color_gy; + uint32_t black_color_bcb; +}; + +struct bp_hw_crtc_timing_parameters { + enum controller_id controller_id; + /* horizontal part */ + uint32_t h_total; + uint32_t h_addressable; + uint32_t h_overscan_left; + uint32_t h_overscan_right; + uint32_t h_sync_start; + uint32_t h_sync_width; + + /* vertical part */ + uint32_t v_total; + uint32_t v_addressable; + uint32_t v_overscan_top; + uint32_t v_overscan_bottom; + uint32_t v_sync_start; + uint32_t v_sync_width; + + struct timing_flags { + uint32_t INTERLACE:1; + uint32_t PIXEL_REPETITION:4; + uint32_t HSYNC_POSITIVE_POLARITY:1; + uint32_t VSYNC_POSITIVE_POLARITY:1; + uint32_t HORZ_COUNT_BY_TWO:1; + } flags; +}; + +struct bp_hw_crtc_overscan_parameters { + enum controller_id controller_id; + uint32_t h_overscan_left; + uint32_t h_overscan_right; + uint32_t v_overscan_top; + uint32_t v_overscan_bottom; +}; + +struct bp_adjust_pixel_clock_parameters { + /* Input: Signal Type - to be converted to Encoder mode */ + enum signal_type signal_type; + /* Input: Encoder object id */ + struct graphics_object_id encoder_object_id; + /* Input: Pixel Clock (requested Pixel clock based on Video timing + * standard used) in KHz + */ + uint32_t pixel_clock; + /* Output: Adjusted Pixel Clock (after VBIOS exec table) in KHz */ + uint32_t adjusted_pixel_clock; + /* Output: If non-zero, this refDiv value should be used to calculate + * other ppll params */ + uint32_t reference_divider; + /* Output: If non-zero, this postDiv value should be used to calculate + * other ppll params */ + uint32_t pixel_clock_post_divider; + /* Input: Enable spread spectrum */ + bool ss_enable; +}; + +struct bp_pixel_clock_parameters { + enum controller_id controller_id; /* (Which CRTC uses this PLL) */ + enum clock_source_id pll_id; /* Clock Source Id */ + /* signal_type -> Encoder Mode - needed by VBIOS Exec table */ + enum signal_type signal_type; + /* Adjusted Pixel Clock (after VBIOS exec table) + * that becomes Target Pixel Clock (KHz) */ + uint32_t target_pixel_clock; + /* Calculated Reference divider of Display PLL */ + uint32_t reference_divider; + /* Calculated Feedback divider of Display PLL */ + uint32_t feedback_divider; + /* Calculated Fractional Feedback divider of Display PLL */ + uint32_t fractional_feedback_divider; + /* Calculated Pixel Clock Post divider of Display PLL */ + uint32_t pixel_clock_post_divider; + struct graphics_object_id encoder_object_id; /* Encoder object id */ + /* VBIOS returns a fixed display clock when DFS-bypass feature + * is enabled (KHz) */ + uint32_t dfs_bypass_display_clock; + /* color depth to support HDMI deep color */ + enum transmitter_color_depth color_depth; + + struct program_pixel_clock_flags { + uint32_t FORCE_PROGRAMMING_OF_PLL:1; + /* Use Engine Clock as source for Display Clock when + * programming PLL */ + uint32_t USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK:1; + /* Use external reference clock (refDivSrc for PLL) */ + uint32_t SET_EXTERNAL_REF_DIV_SRC:1; + /* Force program PHY PLL only */ + uint32_t PROGRAM_PHY_PLL_ONLY:1; + /* Support for YUV420 */ + uint32_t SUPPORT_YUV_420:1; + /* Use XTALIN reference clock source */ + uint32_t SET_XTALIN_REF_SRC:1; + /* Use GENLK reference clock source */ + uint32_t SET_GENLOCK_REF_DIV_SRC:1; + } flags; +}; + +struct bp_display_clock_parameters { + uint32_t target_display_clock; /* KHz */ + /* Actual Display Clock set due to clock divider granularity KHz */ + uint32_t actual_display_clock; + /* Actual Post Divider ID used to generate the actual clock */ + uint32_t actual_post_divider_id; +}; + +enum bp_dce_clock_type { + DCECLOCK_TYPE_DISPLAY_CLOCK = 0, + DCECLOCK_TYPE_DPREFCLK = 1 +}; + +/* DCE Clock Parameters structure for SetDceClock Exec command table */ +struct bp_set_dce_clock_parameters { + enum clock_source_id pll_id; /* Clock Source Id */ + /* Display clock or DPREFCLK value */ + uint32_t target_clock_frequency; + /* Clock to set: =0: DISPCLK =1: DPREFCLK =2: PIXCLK */ + enum bp_dce_clock_type clock_type; + + struct set_dce_clock_flags { + uint32_t USE_GENERICA_AS_SOURCE_FOR_DPREFCLK:1; + /* Use XTALIN reference clock source */ + uint32_t USE_XTALIN_AS_SOURCE_FOR_DPREFCLK:1; + /* Use PCIE reference clock source */ + uint32_t USE_PCIE_AS_SOURCE_FOR_DPREFCLK:1; + /* Use GENLK reference clock source */ + uint32_t USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK:1; + } flags; +}; + +struct spread_spectrum_flags { + /* 1 = Center Spread; 0 = down spread */ + uint32_t CENTER_SPREAD:1; + /* 1 = external; 0 = internal */ + uint32_t EXTERNAL_SS:1; + /* 1 = delta-sigma type parameter; 0 = ver1 */ + uint32_t DS_TYPE:1; +}; + +struct bp_spread_spectrum_parameters { + enum clock_source_id pll_id; + uint32_t percentage; + uint32_t ds_frac_amount; + + union { + struct { + uint32_t step; + uint32_t delay; + uint32_t range; /* In Hz unit */ + } ver1; + struct { + uint32_t feedback_amount; + uint32_t nfrac_amount; + uint32_t ds_frac_size; + } ds; + }; + + struct spread_spectrum_flags flags; +}; + +struct bp_encoder_cap_info { + uint32_t DP_HBR2_CAP:1; + uint32_t DP_HBR2_EN:1; + uint32_t DP_HBR3_EN:1; + uint32_t HDMI_6GB_EN:1; + uint32_t RESERVED:30; +}; + +struct bp_gpio_cntl_info { + uint32_t id; + enum gpio_pin_output_state state; +}; + +#endif /*__DAL_BIOS_PARSER_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h new file mode 100644 index 000000000000..119297e3bdc0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -0,0 +1,125 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_ASIC_ID_H__ +#define __DAL_ASIC_ID_H__ + +/* + * ASIC internal revision ID + */ + +/* DCE80 (based on ci_id.h in Perforce) */ +#define CI_BONAIRE_M_A0 0x14 +#define CI_BONAIRE_M_A1 0x15 +#define CI_HAWAII_P_A0 0x28 + +#define CI_UNKNOWN 0xFF + +#define ASIC_REV_IS_BONAIRE_M(rev) \ + ((rev >= CI_BONAIRE_M_A0) && (rev < CI_HAWAII_P_A0)) + +#define ASIC_REV_IS_HAWAII_P(rev) \ + (rev >= CI_HAWAII_P_A0) + +/* KV1 with Spectre GFX core, 8-8-1-2 (CU-Pix-Primitive-RB) */ +#define KV_SPECTRE_A0 0x01 + +/* KV2 with Spooky GFX core, including downgraded from Spectre core, + * 3-4-1-1 (CU-Pix-Primitive-RB) */ +#define KV_SPOOKY_A0 0x41 + +/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define KB_KALINDI_A0 0x81 + +/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define KB_KALINDI_A1 0x82 + +/* BV with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define BV_KALINDI_A2 0x85 + +/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define ML_GODAVARI_A0 0xA1 + +/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ +#define ML_GODAVARI_A1 0xA2 + +#define KV_UNKNOWN 0xFF + +#define ASIC_REV_IS_KALINDI(rev) \ + ((rev >= KB_KALINDI_A0) && (rev < KV_UNKNOWN)) + +#define ASIC_REV_IS_BHAVANI(rev) \ + ((rev >= BV_KALINDI_A2) && (rev < ML_GODAVARI_A0)) + +#define ASIC_REV_IS_GODAVARI(rev) \ + ((rev >= ML_GODAVARI_A0) && (rev < KV_UNKNOWN)) + +/* VI Family */ +/* DCE10 */ +#define VI_TONGA_P_A0 20 +#define VI_TONGA_P_A1 21 +#define VI_FIJI_P_A0 60 + +/* DCE112 */ +#define VI_POLARIS10_P_A0 80 +#define VI_POLARIS11_M_A0 90 + +#define VI_UNKNOWN 0xFF + +#define ASIC_REV_IS_TONGA_P(eChipRev) ((eChipRev >= VI_TONGA_P_A0) && \ + (eChipRev < 40)) +#define ASIC_REV_IS_FIJI_P(eChipRev) ((eChipRev >= VI_FIJI_P_A0) && \ + (eChipRev < 80)) + +#define ASIC_REV_IS_POLARIS10_P(eChipRev) ((eChipRev >= VI_POLARIS10_P_A0) && \ + (eChipRev < VI_POLARIS11_M_A0)) +#define ASIC_REV_IS_POLARIS11_M(eChipRev) (eChipRev >= VI_POLARIS11_M_A0) + +/* DCE11 */ +#define CZ_CARRIZO_A0 0x01 + +#define STONEY_A0 0x61 +#define CZ_UNKNOWN 0xFF + +#define ASIC_REV_IS_STONEY(rev) \ + ((rev >= STONEY_A0) && (rev < CZ_UNKNOWN)) + +/* + * ASIC chip ID + */ +/* DCE80 */ +#define DEVICE_ID_KALINDI_9834 0x9834 +#define DEVICE_ID_TEMASH_9839 0x9839 +#define DEVICE_ID_TEMASH_983D 0x983D + +/* Asic Family IDs for different asic family. */ +#define FAMILY_CI 120 /* Sea Islands: Hawaii (P), Bonaire (M) */ +#define FAMILY_KV 125 /* Fusion => Kaveri: Spectre, Spooky; Kabini: Kalindi */ +#define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */ +#define FAMILY_CZ 135 /* Carrizo */ + +#define FAMILY_UNKNOWN 0xFF + +#endif /* __DAL_ASIC_ID_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_register_logger.h b/drivers/gpu/drm/amd/display/include/dal_register_logger.h new file mode 100644 index 000000000000..00dfcd70cc37 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/dal_register_logger.h @@ -0,0 +1,42 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_REGISTER_LOGGER__ +#define __DAL_REGISTER_LOGGER__ + +/**************** + * API functions + ***************/ + +/* dal_reg_logger_push - begin Register Logging */ +void dal_reg_logger_push(const char *caller_func); +/* dal_reg_logger_pop - stop Register Logging */ +void dal_reg_logger_pop(void); + +/* for internal use of the Logger only */ +void dal_reg_logger_rw_count_increment(void); +bool dal_reg_logger_should_dump_register(void); + +#endif /* __DAL_REGISTER_LOGGER__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h new file mode 100644 index 000000000000..ada5b19e85eb --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TYPES_H__ +#define __DAL_TYPES_H__ + +#include "signal_types.h" +#include "dc_types.h" + +struct dal_logger; +struct dc_bios; + +enum dce_version { + DCE_VERSION_UNKNOWN = (-1), + DCE_VERSION_8_0, + DCE_VERSION_10_0, + DCE_VERSION_11_0, + DCE_VERSION_11_2, + DCE_VERSION_MAX, +}; + +#endif /* __DAL_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h new file mode 100644 index 000000000000..0a6ba91e3eba --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -0,0 +1,189 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DAL_DDC_SERVICE_TYPES_H__ +#define __DAL_DDC_SERVICE_TYPES_H__ + +#define DP_BRANCH_DEVICE_ID_1 0x0010FA +#define DP_BRANCH_DEVICE_ID_2 0x0022B9 +#define DP_SINK_DEVICE_ID_1 0x4CE000 +#define DP_BRANCH_DEVICE_ID_3 0x00001A +#define DP_BRANCH_DEVICE_ID_4 0x0080e1 +#define DP_BRANCH_DEVICE_ID_5 0x006037 +#define DP_SINK_DEVICE_ID_2 0x001CF8 + + +enum ddc_result { + DDC_RESULT_UNKNOWN = 0, + DDC_RESULT_SUCESSFULL, + DDC_RESULT_FAILED_CHANNEL_BUSY, + DDC_RESULT_FAILED_TIMEOUT, + DDC_RESULT_FAILED_PROTOCOL_ERROR, + DDC_RESULT_FAILED_NACK, + DDC_RESULT_FAILED_INCOMPLETE, + DDC_RESULT_FAILED_OPERATION, + DDC_RESULT_FAILED_INVALID_OPERATION, + DDC_RESULT_FAILED_BUFFER_OVERFLOW +}; + +enum ddc_service_type { + DDC_SERVICE_TYPE_CONNECTOR, + DDC_SERVICE_TYPE_DISPLAY_PORT_MST, +}; + +enum dcs_dpcd_revision { + DCS_DPCD_REV_10 = 0x10, + DCS_DPCD_REV_11 = 0x11, + DCS_DPCD_REV_12 = 0x12 +}; + +/** + * display sink capability + */ +struct display_sink_capability { + /* dongle type (DP converter, CV smart dongle) */ + enum display_dongle_type dongle_type; + + /********************************************************** + capabilities going INTO SINK DEVICE (stream capabilities) + **********************************************************/ + /* Dongle's downstream count. */ + uint32_t downstrm_sink_count; + /* Is dongle's downstream count info field (downstrm_sink_count) + * valid. */ + bool downstrm_sink_count_valid; + + /* Maximum additional audio delay in microsecond (us) */ + uint32_t additional_audio_delay; + /* Audio latency value in microsecond (us) */ + uint32_t audio_latency; + /* Interlace video latency value in microsecond (us) */ + uint32_t video_latency_interlace; + /* Progressive video latency value in microsecond (us) */ + uint32_t video_latency_progressive; + /* Dongle caps: Maximum pixel clock supported over dongle for HDMI */ + uint32_t max_hdmi_pixel_clock; + /* Dongle caps: Maximum deep color supported over dongle for HDMI */ + enum dc_color_depth max_hdmi_deep_color; + + /************************************************************ + capabilities going OUT OF SOURCE DEVICE (link capabilities) + ************************************************************/ + /* support for Spread Spectrum(SS) */ + bool ss_supported; + /* DP link settings (laneCount, linkRate, Spread) */ + uint32_t dp_link_lane_count; + uint32_t dp_link_rate; + uint32_t dp_link_spead; + + enum dcs_dpcd_revision dpcd_revision; + /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, + indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ + bool is_dp_hdmi_s3d_converter; + /* to check if we have queried the display capability + * for eDP panel already. */ + bool is_edp_sink_cap_valid; + + enum ddc_transaction_type transaction_type; + enum signal_type signal; +}; + +struct av_sync_data { + uint8_t av_granularity;/* DPCD 00023h */ + uint8_t aud_dec_lat1;/* DPCD 00024h */ + uint8_t aud_dec_lat2;/* DPCD 00025h */ + uint8_t aud_pp_lat1;/* DPCD 00026h */ + uint8_t aud_pp_lat2;/* DPCD 00027h */ + uint8_t vid_inter_lat;/* DPCD 00028h */ + uint8_t vid_prog_lat;/* DPCD 00029h */ + uint8_t aud_del_ins1;/* DPCD 0002Bh */ + uint8_t aud_del_ins2;/* DPCD 0002Ch */ + uint8_t aud_del_ins3;/* DPCD 0002Dh */ +}; + +/** EDID retrieval related constants, also used by MstMgr **/ + +#define DDC_EDID_SEGMENT_SIZE 256 +#define DDC_EDID_BLOCK_SIZE 128 +#define DDC_EDID_BLOCKS_PER_SEGMENT \ + (DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE) + +#define DDC_EDID_EXT_COUNT_OFFSET 0x7E + +#define DDC_EDID_ADDRESS_START 0x50 +#define DDC_EDID_ADDRESS_END 0x52 +#define DDC_EDID_SEGMENT_ADDRESS 0x30 + +/* signatures for Edid 1x */ +#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8 +#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4 +#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126 +#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2 +#define DDC_EDID1X_CHECKSUM_OFFSET 127 +/* signatures for Edid 20*/ +#define DDC_EDID_20_SIGNATURE_OFFSET 0 +#define DDC_EDID_20_SIGNATURE 0x20 + +#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1 +#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4 +#define DDC_EDID20_CHECKSUM_OFFSET 255 +#define DDC_EDID20_CHECKSUM_LEN 1 + +/*DP to VGA converter*/ +static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa"; +/*DP to Dual link DVI converter*/ +static const uint8_t DP_DVI_CONVERTER_ID_1[] = "m2DVIa"; +/*Travis*/ +static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT"; +/*Nutmeg*/ +static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA"; +/*DP to VGA converter*/ +static const uint8_t DP_VGA_CONVERTER_ID_4[] = "DpVga"; +/*DP to Dual link DVI converter*/ +static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa"; +/*DP to Dual link DVI converter 2*/ +static const uint8_t DP_DVI_CONVERTER_ID_42[] = "v2DVIa"; + +static const uint8_t DP_SINK_DEV_STRING_ID2_REV0[] = "\0\0\0\0\0\0"; + +/* Identifies second generation PSR TCON from Parade: Device ID string: + * yy-xx-**-**-**-** + */ +/* xx - Hw ID high byte */ +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_HIGH_BYTE = + 0x06; + +/* yy - HW ID low byte, the same silicon has several package/feature flavors */ +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE1 = + 0x61; +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE2 = + 0x62; +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE3 = + 0x63; +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE4 = + 0x72; +static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE5 = + 0x73; + +#endif /* __DAL_DDC_SERVICE_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h new file mode 100644 index 000000000000..2006fa21f54c --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -0,0 +1,175 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DISPLAY_CLOCK_INTERFACE_H__ +#define __DISPLAY_CLOCK_INTERFACE_H__ + +#include "hw_sequencer_types.h" +#include "grph_object_defs.h" +#include "signal_types.h" + +/* Timing related information*/ +struct dc_timing_params { + uint32_t INTERLACED:1; + uint32_t HCOUNT_BY_TWO:1; + uint32_t PIXEL_REPETITION:4; /*< values 1 to 10 supported*/ + uint32_t PREFETCH:1; + + uint32_t h_total; + uint32_t h_addressable; + uint32_t h_sync_width; +}; + +/* Scaling related information*/ +struct dc_scaling_params { + uint32_t h_overscan_right; + uint32_t h_overscan_left; + uint32_t h_taps; + uint32_t v_taps; +}; + +/* VScalerEfficiency */ +enum v_scaler_efficiency { + V_SCALER_EFFICIENCY_LB36BPP = 0, + V_SCALER_EFFICIENCY_LB30BPP = 1, + V_SCALER_EFFICIENCY_LB24BPP = 2, + V_SCALER_EFFICIENCY_LB18BPP = 3 +}; + +/* Parameters required for minimum Engine + * and minimum Display clock calculations*/ +struct min_clock_params { + uint32_t id; + uint32_t requested_pixel_clock; /* in KHz */ + uint32_t actual_pixel_clock; /* in KHz */ + struct view source_view; + struct view dest_view; + struct dc_timing_params timing_info; + struct dc_scaling_params scaling_info; + enum signal_type signal_type; + enum dc_color_depth deep_color_depth; + enum v_scaler_efficiency scaler_efficiency; + bool line_buffer_prefetch_enabled; +}; + +/* Result of Minimum System and Display clock calculations. + * Minimum System clock and Display clock, source and path to be used + * for Display clock*/ +struct minimum_clocks_calculation_result { + uint32_t min_sclk_khz; + uint32_t min_dclk_khz; + uint32_t min_mclk_khz; + uint32_t min_deep_sleep_sclk; +}; + +/* Enumeration of all clocks states */ +enum clocks_state { + CLOCKS_STATE_INVALID = 0, + CLOCKS_STATE_ULTRA_LOW, + CLOCKS_STATE_LOW, + CLOCKS_STATE_NOMINAL, + CLOCKS_STATE_PERFORMANCE, + /* Starting from DCE11, Max 8 level DPM state supported */ + CLOCKS_DPM_STATE_LEVEL_INVALID = CLOCKS_STATE_INVALID, + CLOCKS_DPM_STATE_LEVEL_0 = CLOCKS_STATE_ULTRA_LOW, + CLOCKS_DPM_STATE_LEVEL_1 = CLOCKS_STATE_LOW, + CLOCKS_DPM_STATE_LEVEL_2 = CLOCKS_STATE_NOMINAL, + CLOCKS_DPM_STATE_LEVEL_3 = CLOCKS_STATE_PERFORMANCE, + CLOCKS_DPM_STATE_LEVEL_4 = CLOCKS_DPM_STATE_LEVEL_3 + 1, + CLOCKS_DPM_STATE_LEVEL_5 = CLOCKS_DPM_STATE_LEVEL_4 + 1, + CLOCKS_DPM_STATE_LEVEL_6 = CLOCKS_DPM_STATE_LEVEL_5 + 1, + CLOCKS_DPM_STATE_LEVEL_7 = CLOCKS_DPM_STATE_LEVEL_6 + 1, +}; + +/* Structure containing all state-dependent clocks + * (dependent on "enum clocks_state") */ +struct state_dependent_clocks { + uint32_t display_clk_khz; + uint32_t pixel_clk_khz; +}; + +struct display_clock_state { + uint32_t DFS_BYPASS_ACTIVE:1; +}; + +struct display_clock; + +struct display_clock *dal_display_clock_dce112_create( + struct dc_context *ctx); + +struct display_clock *dal_display_clock_dce110_create( + struct dc_context *ctx); + +struct display_clock *dal_display_clock_dce80_create( + struct dc_context *ctx); + +void dal_display_clock_destroy(struct display_clock **to_destroy); +bool dal_display_clock_validate( + struct display_clock *disp_clk, + struct min_clock_params *params); +uint32_t dal_display_clock_calculate_min_clock( + struct display_clock *disp_clk, + uint32_t path_num, + struct min_clock_params *params); +uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); +void dal_display_clock_set_clock( + struct display_clock *disp_clk, + uint32_t requested_clock_khz); +uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk); +bool dal_display_clock_get_min_clocks_state( + struct display_clock *disp_clk, + enum clocks_state *clocks_state); +bool dal_display_clock_get_required_clocks_state( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks, + enum clocks_state *clocks_state); +bool dal_display_clock_set_min_clocks_state( + struct display_clock *disp_clk, + enum clocks_state clocks_state); +uint32_t dal_display_clock_get_dp_ref_clk_frequency( + struct display_clock *disp_clk); +/*the second parameter of "switchreferenceclock" is + * a dummy argument for all pre dce 6.0 versions*/ +void dal_display_clock_switch_reference_clock( + struct display_clock *disp_clk, + bool use_external_ref_clk, + uint32_t requested_clock_khz); +void dal_display_clock_set_dp_ref_clock_source( + struct display_clock *disp_clk, + enum clock_source_id clk_src); +void dal_display_clock_store_max_clocks_state( + struct display_clock *disp_clk, + enum clocks_state max_clocks_state); +void dal_display_clock_set_clock_state( + struct display_clock *disp_clk, + struct display_clock_state clk_state); +struct display_clock_state dal_display_clock_get_clock_state( + struct display_clock *disp_clk); +uint32_t dal_display_clock_get_dfs_bypass_threshold( + struct display_clock *disp_clk); +void dal_display_clock_invalid_clock_state( + struct display_clock *disp_clk); + +#endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h new file mode 100644 index 000000000000..fbb2729148df --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -0,0 +1,742 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DPCD_DEFS_H__ +#define __DAL_DPCD_DEFS_H__ + +enum dpcd_address { +/* addresses marked with 1.2 are only defined since DP 1.2 spec */ + + /* Reciever Capability Field */ + DPCD_ADDRESS_DPCD_REV = 0x00000, + DPCD_ADDRESS_MAX_LINK_RATE = 0x00001, + DPCD_ADDRESS_MAX_LANE_COUNT = 0x00002, + DPCD_ADDRESS_MAX_DOWNSPREAD = 0x00003, + DPCD_ADDRESS_NORP = 0x00004, + DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT = 0x00005, + DPCD_ADDRESS_MAIN_LINK_CHANNEL_CODING = 0x00006, + DPCD_ADDRESS_DOWNSTREAM_PORT_COUNT = 0x00007, + DPCD_ADDRESS_RECEIVE_PORT0_CAP0 = 0x00008, + DPCD_ADDRESS_RECEIVE_PORT0_CAP1 = 0x00009, + DPCD_ADDRESS_RECEIVE_PORT1_CAP0 = 0x0000A, + DPCD_ADDRESS_RECEIVE_PORT1_CAP1 = 0x0000B, + + DPCD_ADDRESS_I2C_SPEED_CNTL_CAP = 0x0000C,/*1.2*/ + DPCD_ADDRESS_EDP_CONFIG_CAP = 0x0000D,/*1.2*/ + DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL = 0x000E,/*1.2*/ + + DPCD_ADDRESS_MSTM_CAP = 0x00021,/*1.2*/ + + /* Audio Video Sync Data Feild */ + DPCD_ADDRESS_AV_GRANULARITY = 0x0023, + DPCD_ADDRESS_AUDIO_DECODE_LATENCY1 = 0x0024, + DPCD_ADDRESS_AUDIO_DECODE_LATENCY2 = 0x0025, + DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY1 = 0x0026, + DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY2 = 0x0027, + DPCD_ADDRESS_VIDEO_INTERLACED_LATENCY = 0x0028, + DPCD_ADDRESS_VIDEO_PROGRESSIVE_LATENCY = 0x0029, + DPCD_ADDRESS_AUDIO_DELAY_INSERT1 = 0x0002B, + DPCD_ADDRESS_AUDIO_DELAY_INSERT2 = 0x0002C, + DPCD_ADDRESS_AUDIO_DELAY_INSERT3 = 0x0002D, + + /* Audio capability */ + DPCD_ADDRESS_NUM_OF_AUDIO_ENDPOINTS = 0x00022, + + DPCD_ADDRESS_GUID_START = 0x00030,/*1.2*/ + DPCD_ADDRESS_GUID_END = 0x0003f,/*1.2*/ + + DPCD_ADDRESS_PSR_SUPPORT_VER = 0x00070, + DPCD_ADDRESS_PSR_CAPABILITY = 0x00071, + + DPCD_ADDRESS_DWN_STRM_PORT0_CAPS = 0x00080,/*1.2a*/ + + /* Link Configuration Field */ + DPCD_ADDRESS_LINK_BW_SET = 0x00100, + DPCD_ADDRESS_LANE_COUNT_SET = 0x00101, + DPCD_ADDRESS_TRAINING_PATTERN_SET = 0x00102, + DPCD_ADDRESS_LANE0_SET = 0x00103, + DPCD_ADDRESS_LANE1_SET = 0x00104, + DPCD_ADDRESS_LANE2_SET = 0x00105, + DPCD_ADDRESS_LANE3_SET = 0x00106, + DPCD_ADDRESS_DOWNSPREAD_CNTL = 0x00107, + DPCD_ADDRESS_I2C_SPEED_CNTL = 0x00109,/*1.2*/ + + DPCD_ADDRESS_EDP_CONFIG_SET = 0x0010A, + DPCD_ADDRESS_LINK_QUAL_LANE0_SET = 0x0010B, + DPCD_ADDRESS_LINK_QUAL_LANE1_SET = 0x0010C, + DPCD_ADDRESS_LINK_QUAL_LANE2_SET = 0x0010D, + DPCD_ADDRESS_LINK_QUAL_LANE3_SET = 0x0010E, + + DPCD_ADDRESS_LANE0_SET2 = 0x0010F,/*1.2*/ + DPCD_ADDRESS_LANE2_SET2 = 0x00110,/*1.2*/ + + DPCD_ADDRESS_MSTM_CNTL = 0x00111,/*1.2*/ + + DPCD_ADDRESS_PSR_ENABLE_CFG = 0x0170, + + /* Payload Table Configuration Field 1.2 */ + DPCD_ADDRESS_PAYLOAD_ALLOCATE_SET = 0x001C0, + DPCD_ADDRESS_PAYLOAD_ALLOCATE_START_TIMESLOT = 0x001C1, + DPCD_ADDRESS_PAYLOAD_ALLOCATE_TIMESLOT_COUNT = 0x001C2, + + DPCD_ADDRESS_SINK_COUNT = 0x0200, + DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR = 0x0201, + + /* Link / Sink Status Field */ + DPCD_ADDRESS_LANE_01_STATUS = 0x00202, + DPCD_ADDRESS_LANE_23_STATUS = 0x00203, + DPCD_ADDRESS_LANE_ALIGN_STATUS_UPDATED = 0x0204, + DPCD_ADDRESS_SINK_STATUS = 0x0205, + + /* Adjust Request Field */ + DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1 = 0x0206, + DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3 = 0x0207, + DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2 = 0x020C, + + /* Test Request Field */ + DPCD_ADDRESS_TEST_REQUEST = 0x0218, + DPCD_ADDRESS_TEST_LINK_RATE = 0x0219, + DPCD_ADDRESS_TEST_LANE_COUNT = 0x0220, + DPCD_ADDRESS_TEST_PATTERN = 0x0221, + DPCD_ADDRESS_TEST_MISC1 = 0x0232, + + /* Phy Test Pattern Field */ + DPCD_ADDRESS_TEST_PHY_PATTERN = 0x0248, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0 = 0x0250, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_15_8 = 0x0251, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_23_16 = 0x0252, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_31_24 = 0x0253, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_39_32 = 0x0254, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_47_40 = 0x0255, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_55_48 = 0x0256, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_63_56 = 0x0257, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_71_64 = 0x0258, + DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 = 0x0259, + + /* Test Response Field*/ + DPCD_ADDRESS_TEST_RESPONSE = 0x0260, + + /* Audio Test Pattern Field 1.2*/ + DPCD_ADDRESS_TEST_AUDIO_MODE = 0x0271, + DPCD_ADDRESS_TEST_AUDIO_PATTERN_TYPE = 0x0272, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_1 = 0x0273, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_2 = 0x0274, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_3 = 0x0275, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_4 = 0x0276, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_5 = 0x0277, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_6 = 0x0278, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_7 = 0x0279, + DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_8 = 0x027A, + + /* Payload Table Status Field */ + DPCD_ADDRESS_PAYLOAD_TABLE_UPDATE_STATUS = 0x002C0,/*1.2*/ + DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT1 = 0x002C1,/*1.2*/ + DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT63 = 0x002FF,/*1.2*/ + + /* Source Device Specific Field */ + DPCD_ADDRESS_SOURCE_DEVICE_ID_START = 0x0300, + DPCD_ADDRESS_SOURCE_DEVICE_ID_END = 0x0301, + DPCD_ADDRESS_AMD_INTERNAL_DEBUG_START = 0x030C, + DPCD_ADDRESS_AMD_INTERNAL_DEBUG_END = 0x030F, + DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_START = 0x0310, + DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_END = 0x037F, + DPCD_ADDRESS_SOURCE_RESERVED_START = 0x0380, + DPCD_ADDRESS_SOURCE_RESERVED_END = 0x03FF, + + /* Sink Device Specific Field */ + DPCD_ADDRESS_SINK_DEVICE_ID_START = 0x0400, + DPCD_ADDRESS_SINK_DEVICE_ID_END = 0x0402, + DPCD_ADDRESS_SINK_DEVICE_STR_START = 0x0403, + DPCD_ADDRESS_SINK_DEVICE_STR_END = 0x0408, + DPCD_ADDRESS_SINK_REVISION_START = 0x409, + DPCD_ADDRESS_SINK_REVISION_END = 0x40B, + + /* Branch Device Specific Field */ + DPCD_ADDRESS_BRANCH_DEVICE_ID_START = 0x0500, + DPCD_ADDRESS_BRANCH_DEVICE_ID_END = 0x0502, + DPCD_ADDRESS_BRANCH_DEVICE_STR_START = 0x0503, + DPCD_ADDRESS_BRANCH_DEVICE_STR_END = 0x0508, + DPCD_ADDRESS_BRANCH_REVISION_START = 0x0509, + DPCD_ADDRESS_BRANCH_REVISION_END = 0x050B, + + DPCD_ADDRESS_POWER_STATE = 0x0600, + + /* EDP related */ + DPCD_ADDRESS_EDP_REV = 0x0700, + DPCD_ADDRESS_EDP_CAPABILITY = 0x0701, + DPCD_ADDRESS_EDP_BACKLIGHT_ADJUST_CAP = 0x0702, + DPCD_ADDRESS_EDP_GENERAL_CAP2 = 0x0703, + + DPCD_ADDRESS_EDP_DISPLAY_CONTROL = 0x0720, + DPCD_ADDRESS_SUPPORTED_LINK_RATES = 0x00010, /* edp 1.4 */ + DPCD_ADDRESS_EDP_BACKLIGHT_SET = 0x0721, + DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_MSB = 0x0722, + DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_LSB = 0x0723, + DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT = 0x0724, + DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MIN = 0x0725, + DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MAX = 0x0726, + DPCD_ADDRESS_EDP_BACKLIGHT_CONTROL_STATUS = 0x0727, + DPCD_ADDRESS_EDP_BACKLIGHT_FREQ_SET = 0x0728, + DPCD_ADDRESS_EDP_REVERVED = 0x0729, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MSB = 0x072A, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MID = 0x072B, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_LSB = 0x072C, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MSB = 0x072D, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MID = 0x072E, + DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_LSB = 0x072F, + + DPCD_ADDRESS_EDP_DBC_MINIMUM_BRIGHTNESS_SET = 0x0732, + DPCD_ADDRESS_EDP_DBC_MAXIMUM_BRIGHTNESS_SET = 0x0733, + + /* Sideband MSG Buffers 1.2 */ + DPCD_ADDRESS_DOWN_REQ_START = 0x01000, + DPCD_ADDRESS_DOWN_REQ_END = 0x011ff, + + DPCD_ADDRESS_UP_REP_START = 0x01200, + DPCD_ADDRESS_UP_REP_END = 0x013ff, + + DPCD_ADDRESS_DOWN_REP_START = 0x01400, + DPCD_ADDRESS_DOWN_REP_END = 0x015ff, + + DPCD_ADDRESS_UP_REQ_START = 0x01600, + DPCD_ADDRESS_UP_REQ_END = 0x017ff, + + /* ESI (Event Status Indicator) Field 1.2 */ + DPCD_ADDRESS_SINK_COUNT_ESI = 0x02002, + DPCD_ADDRESS_DEVICE_IRQ_ESI0 = 0x02003, + DPCD_ADDRESS_DEVICE_IRQ_ESI1 = 0x02004, + /*@todo move dpcd_address_Lane01Status back here*/ + + DPCD_ADDRESS_PSR_ERROR_STATUS = 0x2006, + DPCD_ADDRESS_PSR_EVENT_STATUS = 0x2007, + DPCD_ADDRESS_PSR_SINK_STATUS = 0x2008, + DPCD_ADDRESS_PSR_DBG_REGISTER0 = 0x2009, + DPCD_ADDRESS_PSR_DBG_REGISTER1 = 0x200A, + + DPCD_ADDRESS_DP13_DPCD_REV = 0x2200, + DPCD_ADDRESS_DP13_MAX_LINK_RATE = 0x2201, + + /* Travis specific addresses */ + DPCD_ADDRESS_TRAVIS_SINK_DEV_SEL = 0x5f0, + DPCD_ADDRESS_TRAVIS_SINK_ACCESS_OFFSET = 0x5f1, + DPCD_ADDRESS_TRAVIS_SINK_ACCESS_REG = 0x5f2, +}; + +enum dpcd_revision { + DPCD_REV_10 = 0x10, + DPCD_REV_11 = 0x11, + DPCD_REV_12 = 0x12, + DPCD_REV_13 = 0x13, + DPCD_REV_14 = 0x14 +}; + +enum dp_pwr_state { + DP_PWR_STATE_D0 = 1,/* direct HW translation! */ + DP_PWR_STATE_D3 +}; + +/* these are the types stored at DOWNSTREAMPORT_PRESENT */ +enum dpcd_downstream_port_type { + DOWNSTREAM_DP = 0, + DOWNSTREAM_VGA, + DOWNSTREAM_DVI_HDMI, + DOWNSTREAM_NONDDC /* has no EDID (TV,CV) */ +}; + +enum dpcd_link_test_patterns { + LINK_TEST_PATTERN_NONE = 0, + LINK_TEST_PATTERN_COLOR_RAMP, + LINK_TEST_PATTERN_VERTICAL_BARS, + LINK_TEST_PATTERN_COLOR_SQUARES +}; + +enum dpcd_test_color_format { + TEST_COLOR_FORMAT_RGB = 0, + TEST_COLOR_FORMAT_YCBCR422, + TEST_COLOR_FORMAT_YCBCR444 +}; + +enum dpcd_test_bit_depth { + TEST_BIT_DEPTH_6 = 0, + TEST_BIT_DEPTH_8, + TEST_BIT_DEPTH_10, + TEST_BIT_DEPTH_12, + TEST_BIT_DEPTH_16 +}; + +/* PHY (encoder) test patterns +The order of test patterns follows DPCD register PHY_TEST_PATTERN (0x248) +*/ +enum dpcd_phy_test_patterns { + PHY_TEST_PATTERN_NONE = 0, + PHY_TEST_PATTERN_D10_2, + PHY_TEST_PATTERN_SYMBOL_ERROR, + PHY_TEST_PATTERN_PRBS7, + PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */ + PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE/* For DP1.2 only */ +}; + +enum dpcd_test_dyn_range { + TEST_DYN_RANGE_VESA = 0, + TEST_DYN_RANGE_CEA +}; + +enum dpcd_audio_test_pattern { + AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0,/* direct HW translation */ + AUDIO_TEST_PATTERN_SAWTOOTH +}; + +enum dpcd_audio_sampling_rate { + AUDIO_SAMPLING_RATE_32KHZ = 0,/* direct HW translation */ + AUDIO_SAMPLING_RATE_44_1KHZ, + AUDIO_SAMPLING_RATE_48KHZ, + AUDIO_SAMPLING_RATE_88_2KHZ, + AUDIO_SAMPLING_RATE_96KHZ, + AUDIO_SAMPLING_RATE_176_4KHZ, + AUDIO_SAMPLING_RATE_192KHZ +}; + +enum dpcd_audio_channels { + AUDIO_CHANNELS_1 = 0,/* direct HW translation */ + AUDIO_CHANNELS_2, + AUDIO_CHANNELS_3, + AUDIO_CHANNELS_4, + AUDIO_CHANNELS_5, + AUDIO_CHANNELS_6, + AUDIO_CHANNELS_7, + AUDIO_CHANNELS_8, + + AUDIO_CHANNELS_COUNT +}; + +enum dpcd_audio_test_pattern_periods { + DPCD_AUDIO_TEST_PATTERN_PERIOD_NOTUSED = 0,/* direct HW translation */ + DPCD_AUDIO_TEST_PATTERN_PERIOD_3, + DPCD_AUDIO_TEST_PATTERN_PERIOD_6, + DPCD_AUDIO_TEST_PATTERN_PERIOD_12, + DPCD_AUDIO_TEST_PATTERN_PERIOD_24, + DPCD_AUDIO_TEST_PATTERN_PERIOD_48, + DPCD_AUDIO_TEST_PATTERN_PERIOD_96, + DPCD_AUDIO_TEST_PATTERN_PERIOD_192, + DPCD_AUDIO_TEST_PATTERN_PERIOD_384, + DPCD_AUDIO_TEST_PATTERN_PERIOD_768, + DPCD_AUDIO_TEST_PATTERN_PERIOD_1536 +}; + +/* This enum is for programming DPCD TRAINING_PATTERN_SET */ +enum dpcd_training_patterns { + DPCD_TRAINING_PATTERN_VIDEOIDLE = 0,/* direct HW translation! */ + DPCD_TRAINING_PATTERN_1, + DPCD_TRAINING_PATTERN_2, + DPCD_TRAINING_PATTERN_3, + DPCD_TRAINING_PATTERN_4 = 7 +}; + +/* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus +It defines the possible PSR states. */ +enum dpcd_psr_sink_states { + PSR_SINK_STATE_INACTIVE = 0, + PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SOURCE_TIMING = 1, + PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB = 2, + PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SINK_TIMING = 3, + PSR_SINK_STATE_ACTIVE_CAPTURE_TIMING_RESYNC = 4, + PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7, +}; + +/* This enum defines the Panel's eDP revision at DPCD 700h + * 00h = eDP v1.1 or lower + * 01h = eDP v1.2 + * 02h = eDP v1.3 (PSR support starts here) + * 03h = eDP v1.4 + * If unknown revision, treat as eDP v1.1, meaning least functionality set. + * This enum has values matched to eDP spec, thus values should not change. + */ +enum dpcd_edp_revision { + DPCD_EDP_REVISION_EDP_V1_1 = 0, + DPCD_EDP_REVISION_EDP_V1_2 = 1, + DPCD_EDP_REVISION_EDP_V1_3 = 2, + DPCD_EDP_REVISION_EDP_V1_4 = 3, + DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1, +}; + +union dpcd_rev { + struct { + uint8_t MINOR:4; + uint8_t MAJOR:4; + } bits; + uint8_t raw; +}; + +union max_lane_count { + struct { + uint8_t MAX_LANE_COUNT:5; + uint8_t POST_LT_ADJ_REQ_SUPPORTED:1; + uint8_t TPS3_SUPPORTED:1; + uint8_t ENHANCED_FRAME_CAP:1; + } bits; + uint8_t raw; +}; + +union max_down_spread { + struct { + uint8_t MAX_DOWN_SPREAD:1; + uint8_t RESERVED:5; + uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1; + uint8_t TPS4_SUPPORTED:1; + } bits; + uint8_t raw; +}; + +union mstm_cap { + struct { + uint8_t MST_CAP:1; + uint8_t RESERVED:7; + } bits; + uint8_t raw; +}; + +union lane_count_set { + struct { + uint8_t LANE_COUNT_SET:5; + uint8_t POST_LT_ADJ_REQ_GRANTED:1; + uint8_t RESERVED:1; + uint8_t ENHANCED_FRAMING:1; + } bits; + uint8_t raw; +}; + +union lane_status { + struct { + uint8_t CR_DONE_0:1; + uint8_t CHANNEL_EQ_DONE_0:1; + uint8_t SYMBOL_LOCKED_0:1; + uint8_t RESERVED0:1; + uint8_t CR_DONE_1:1; + uint8_t CHANNEL_EQ_DONE_1:1; + uint8_t SYMBOL_LOCKED_1:1; + uint8_t RESERVED_1:1; + } bits; + uint8_t raw; +}; + +union device_service_irq { + struct { + uint8_t REMOTE_CONTROL_CMD_PENDING:1; + uint8_t AUTOMATED_TEST:1; + uint8_t CP_IRQ:1; + uint8_t MCCS_IRQ:1; + uint8_t DOWN_REP_MSG_RDY:1; + uint8_t UP_REQ_MSG_RDY:1; + uint8_t SINK_SPECIFIC:1; + uint8_t reserved:1; + } bits; + uint8_t raw; +}; + +union sink_count { + struct { + uint8_t SINK_COUNT:6; + uint8_t CPREADY:1; + uint8_t RESERVED:1; + } bits; + uint8_t raw; +}; + +union lane_align_status_updated { + struct { + uint8_t INTERLANE_ALIGN_DONE:1; + uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; + uint8_t RESERVED:4; + uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; + uint8_t LINK_STATUS_UPDATED:1; + } bits; + uint8_t raw; +}; + +union lane_adjust { + struct { + uint8_t VOLTAGE_SWING_LANE:2; + uint8_t PRE_EMPHASIS_LANE:2; + uint8_t RESERVED:4; + } bits; + uint8_t raw; +}; + +union dpcd_training_pattern { + struct { + uint8_t TRAINING_PATTERN_SET:4; + uint8_t RECOVERED_CLOCK_OUT_EN:1; + uint8_t SCRAMBLING_DISABLE:1; + uint8_t SYMBOL_ERROR_COUNT_SEL:2; + } v1_4; + struct { + uint8_t TRAINING_PATTERN_SET:2; + uint8_t LINK_QUAL_PATTERN_SET:2; + uint8_t RESERVED:4; + } v1_3; + uint8_t raw; +}; + +/* Training Lane is used to configure downstream DP device's voltage swing +and pre-emphasis levels*/ +/* The DPCD addresses are from 0x103 to 0x106*/ +union dpcd_training_lane { + struct { + uint8_t VOLTAGE_SWING_SET:2; + uint8_t MAX_SWING_REACHED:1; + uint8_t PRE_EMPHASIS_SET:2; + uint8_t MAX_PRE_EMPHASIS_REACHED:1; + uint8_t RESERVED:2; + } bits; + uint8_t raw; +}; + +/* TMDS-converter related */ +union dwnstream_port_caps_byte0 { + struct { + uint8_t DWN_STRM_PORTX_TYPE:3; + uint8_t DWN_STRM_PORTX_HPD:1; + uint8_t RESERVERD:4; + } bits; + uint8_t raw; +}; + +/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/ +enum dpcd_downstream_port_detailed_type { + DOWN_STREAM_DETAILED_DP = 0, + DOWN_STREAM_DETAILED_VGA, + DOWN_STREAM_DETAILED_DVI, + DOWN_STREAM_DETAILED_HDMI, + DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/ + DOWN_STREAM_DETAILED_DP_PLUS_PLUS +}; + +union dwnstream_port_caps_byte2 { + struct { + uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; + uint8_t RESERVED:6; + } bits; + uint8_t raw; +}; + +union dp_downstream_port_present { + uint8_t byte; + struct { + uint8_t PORT_PRESENT:1; + uint8_t PORT_TYPE:2; + uint8_t FMT_CONVERSION:1; + uint8_t DETAILED_CAPS:1; + uint8_t RESERVED:3; + } fields; +}; + +union dwnstream_port_caps_byte3_dvi { + struct { + uint8_t RESERVED1:1; + uint8_t DUAL_LINK:1; + uint8_t HIGH_COLOR_DEPTH:1; + uint8_t RESERVED2:5; + } bits; + uint8_t raw; +}; + +union dwnstream_port_caps_byte3_hdmi { + struct { + uint8_t FRAME_SEQ_TO_FRAME_PACK:1; + uint8_t RESERVED:7; + } bits; + uint8_t raw; +}; + +/*4-byte structure for detailed capabilities of a down-stream port +(DP-to-TMDS converter).*/ + +union sink_status { + struct { + uint8_t RX_PORT0_STATUS:1; + uint8_t RX_PORT1_STATUS:1; + uint8_t RESERVED:6; + } bits; + uint8_t raw; +}; + +/*6-byte structure corresponding to 6 registers (200h-205h) +read during handling of HPD-IRQ*/ +union hpd_irq_data { + struct { + union sink_count sink_cnt;/* 200h */ + union device_service_irq device_service_irq;/* 201h */ + union lane_status lane01_status;/* 202h */ + union lane_status lane23_status;/* 203h */ + union lane_align_status_updated lane_status_updated;/* 204h */ + union sink_status sink_status; + } bytes; + uint8_t raw[6]; +}; + +union down_stream_port_count { + struct { + uint8_t DOWN_STR_PORT_COUNT:4; + uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/ + /*Bit 6 = MSA_TIMING_PAR_IGNORED + 0 = Sink device requires the MSA timing parameters + 1 = Sink device is capable of rendering incoming video + stream without MSA timing parameters*/ + uint8_t IGNORE_MSA_TIMING_PARAM:1; + /*Bit 7 = OUI Support + 0 = OUI not supported + 1 = OUI supported + (OUI and Device Identification mandatory for DP 1.2)*/ + uint8_t OUI_SUPPORT:1; + } bits; + uint8_t raw; +}; + +union down_spread_ctrl { + struct { + uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/ + /* Bits 4 = SPREAD_AMP. Spreading amplitude + 0 = Main link signal is not downspread + 1 = Main link signal is downspread <= 0.5% + with frequency in the range of 30kHz ~ 33kHz*/ + uint8_t SPREAD_AMP:1; + uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/ + /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN + 0 = Source device will send valid data for the MSA Timing Params + 1 = Source device may send invalid data for these MSA Timing Params*/ + uint8_t IGNORE_MSA_TIMING_PARAM:1; + } bits; + uint8_t raw; +}; + +union dpcd_edp_config { + struct { + uint8_t PANEL_MODE_EDP:1; + uint8_t FRAMING_CHANGE_ENABLE:1; + uint8_t RESERVED:5; + uint8_t PANEL_SELF_TEST_ENABLE:1; + } bits; + uint8_t raw; +}; + +struct dp_device_vendor_id { + uint8_t ieee_oui[3];/*24-bit IEEE OUI*/ + uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/ +}; + +struct dp_sink_hw_fw_revision { + uint8_t ieee_hw_rev; + uint8_t ieee_fw_rev[2]; +}; + +/*DPCD register of DP receiver capability field bits-*/ +union edp_configuration_cap { + struct { + uint8_t ALT_SCRAMBLER_RESET:1; + uint8_t FRAMING_CHANGE:1; + uint8_t RESERVED:1; + uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1; + uint8_t RESERVED2:4; + } bits; + uint8_t raw; +}; + +union training_aux_rd_interval { + struct { + uint8_t TRAINIG_AUX_RD_INTERVAL:7; + uint8_t EXT_RECIEVER_CAP_FIELD_PRESENT:1; + } bits; + uint8_t raw; +}; + +/* Automated test structures */ +union test_request { + struct { + uint8_t LINK_TRAINING :1; + uint8_t LINK_TEST_PATTRN :1; + uint8_t EDID_REAT :1; + uint8_t PHY_TEST_PATTERN :1; + uint8_t AUDIO_TEST_PATTERN :1; + uint8_t RESERVED :1; + uint8_t TEST_STEREO_3D :1; + } bits; + uint8_t raw; +}; + +union test_response { + struct { + uint8_t ACK :1; + uint8_t NO_ACK :1; + uint8_t RESERVED :6; + } bits; + uint8_t raw; +}; + +union phy_test_pattern { + struct { + /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 + * and 3 bits for DP1.2. + */ + uint8_t PATTERN :3; + /* BY speci, bit7:2 is 0 for DP1.1. */ + uint8_t RESERVED :5; + } bits; + uint8_t raw; +}; + +/* States of Compliance Test Specification (CTS DP1.2). */ +union compliance_test_state { + struct { + unsigned char STEREO_3D_RUNNING : 1; + unsigned char SET_TEST_PATTERN_PENDING : 1; + unsigned char RESERVED : 6; + } bits; + unsigned char raw; +}; + +union link_test_pattern { + struct { + /* dpcd_link_test_patterns */ + unsigned char PATTERN :2; + unsigned char RESERVED:6; + } bits; + unsigned char raw; +}; + +union test_misc { + struct dpcd_test_misc_bits { + unsigned char SYNC_CLOCK :1; + /* dpcd_test_color_format */ + unsigned char CLR_FORMAT :2; + /* dpcd_test_dyn_range */ + unsigned char DYN_RANGE :1; + unsigned char YCBCR :1; + /* dpcd_test_bit_depth */ + unsigned char BPC :3; + } bits; + unsigned char raw; +}; + +#endif /* __DAL_DPCD_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h new file mode 100644 index 000000000000..c28de167250f --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -0,0 +1,390 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_FIXED31_32_H__ +#define __DAL_FIXED31_32_H__ + +#include "os_types.h" + +/* + * @brief + * Arithmetic operations on real numbers + * represented as fixed-point numbers. + * There are: 1 bit for sign, + * 31 bit for integer part, + * 32 bits for fractional part. + * + * @note + * Currently, overflows and underflows are asserted; + * no special result returned. + */ + +struct fixed31_32 { + int64_t value; +}; + +/* + * @brief + * Useful constants + */ + +static const struct fixed31_32 dal_fixed31_32_zero = { 0 }; +static const struct fixed31_32 dal_fixed31_32_epsilon = { 1LL }; +static const struct fixed31_32 dal_fixed31_32_half = { 0x80000000LL }; +static const struct fixed31_32 dal_fixed31_32_one = { 0x100000000LL }; + +static const struct fixed31_32 dal_fixed31_32_pi = { 13493037705LL }; +static const struct fixed31_32 dal_fixed31_32_two_pi = { 26986075409LL }; +static const struct fixed31_32 dal_fixed31_32_e = { 11674931555LL }; +static const struct fixed31_32 dal_fixed31_32_ln2 = { 2977044471LL }; +static const struct fixed31_32 dal_fixed31_32_ln2_div_2 = { 1488522236LL }; + +/* + * @brief + * Initialization routines + */ + +/* + * @brief + * result = numerator / denominator + */ +struct fixed31_32 dal_fixed31_32_from_fraction( + int64_t numerator, + int64_t denominator); + +/* + * @brief + * result = arg + */ +struct fixed31_32 dal_fixed31_32_from_int( + int64_t arg); + +/* + * @brief + * Unary operators + */ + +/* + * @brief + * result = -arg + */ +struct fixed31_32 dal_fixed31_32_neg( + struct fixed31_32 arg); + +/* + * @brief + * result = abs(arg) := (arg >= 0) ? arg : -arg + */ +struct fixed31_32 dal_fixed31_32_abs( + struct fixed31_32 arg); + +/* + * @brief + * Binary relational operators + */ + +/* + * @brief + * result = arg1 < arg2 + */ +bool dal_fixed31_32_lt( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = arg1 <= arg2 + */ +bool dal_fixed31_32_le( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = arg1 == arg2 + */ +bool dal_fixed31_32_eq( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2 + */ +struct fixed31_32 dal_fixed31_32_min( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1 + */ +struct fixed31_32 dal_fixed31_32_max( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * | min_value, when arg <= min_value + * result = | arg, when min_value < arg < max_value + * | max_value, when arg >= max_value + */ +struct fixed31_32 dal_fixed31_32_clamp( + struct fixed31_32 arg, + struct fixed31_32 min_value, + struct fixed31_32 max_value); + +/* + * @brief + * Binary shift operators + */ + +/* + * @brief + * result = arg << shift + */ +struct fixed31_32 dal_fixed31_32_shl( + struct fixed31_32 arg, + uint8_t shift); + +/* + * @brief + * result = arg >> shift + */ +struct fixed31_32 dal_fixed31_32_shr( + struct fixed31_32 arg, + uint8_t shift); + +/* + * @brief + * Binary additive operators + */ + +/* + * @brief + * result = arg1 + arg2 + */ +struct fixed31_32 dal_fixed31_32_add( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = arg1 - arg2 + */ +struct fixed31_32 dal_fixed31_32_sub_int( + struct fixed31_32 arg1, + int32_t arg2); + +/* + * @brief + * result = arg1 - arg2 + */ +struct fixed31_32 dal_fixed31_32_sub( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * Binary multiplicative operators + */ + +/* + * @brief + * result = arg1 * arg2 + */ +struct fixed31_32 dal_fixed31_32_mul_int( + struct fixed31_32 arg1, + int32_t arg2); + +/* + * @brief + * result = arg1 * arg2 + */ +struct fixed31_32 dal_fixed31_32_mul( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * result = square(arg) := arg * arg + */ +struct fixed31_32 dal_fixed31_32_sqr( + struct fixed31_32 arg); + +/* + * @brief + * result = arg1 / arg2 + */ +struct fixed31_32 dal_fixed31_32_div_int( + struct fixed31_32 arg1, + int64_t arg2); + +/* + * @brief + * result = arg1 / arg2 + */ +struct fixed31_32 dal_fixed31_32_div( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * Reciprocal function + */ + +/* + * @brief + * result = reciprocal(arg) := 1 / arg + * + * @note + * No special actions taken in case argument is zero. + */ +struct fixed31_32 dal_fixed31_32_recip( + struct fixed31_32 arg); + +/* + * @brief + * Trigonometric functions + */ + +/* + * @brief + * result = sinc(arg) := sin(arg) / arg + * + * @note + * Argument specified in radians, + * internally it's normalized to [-2pi...2pi] range. + */ +struct fixed31_32 dal_fixed31_32_sinc( + struct fixed31_32 arg); + +/* + * @brief + * result = sin(arg) + * + * @note + * Argument specified in radians, + * internally it's normalized to [-2pi...2pi] range. + */ +struct fixed31_32 dal_fixed31_32_sin( + struct fixed31_32 arg); + +/* + * @brief + * result = cos(arg) + * + * @note + * Argument specified in radians + * and should be in [-2pi...2pi] range - + * passing arguments outside that range + * will cause incorrect result! + */ +struct fixed31_32 dal_fixed31_32_cos( + struct fixed31_32 arg); + +/* + * @brief + * Transcendent functions + */ + +/* + * @brief + * result = exp(arg) + * + * @note + * Currently, function is verified for abs(arg) <= 1. + */ +struct fixed31_32 dal_fixed31_32_exp( + struct fixed31_32 arg); + +/* + * @brief + * result = log(arg) + * + * @note + * Currently, abs(arg) should be less than 1. + * No normalization is done. + * Currently, no special actions taken + * in case of invalid argument(s). Take care! + */ +struct fixed31_32 dal_fixed31_32_log( + struct fixed31_32 arg); + +/* + * @brief + * Power function + */ + +/* + * @brief + * result = pow(arg1, arg2) + * + * @note + * Currently, abs(arg1) should be less than 1. Take care! + */ +struct fixed31_32 dal_fixed31_32_pow( + struct fixed31_32 arg1, + struct fixed31_32 arg2); + +/* + * @brief + * Rounding functions + */ + +/* + * @brief + * result = floor(arg) := greatest integer lower than or equal to arg + */ +int32_t dal_fixed31_32_floor( + struct fixed31_32 arg); + +/* + * @brief + * result = round(arg) := integer nearest to arg + */ +int32_t dal_fixed31_32_round( + struct fixed31_32 arg); + +/* + * @brief + * result = ceil(arg) := lowest integer greater than or equal to arg + */ +int32_t dal_fixed31_32_ceil( + struct fixed31_32 arg); + +/* the following two function are used in scaler hw programming to convert fixed + * point value to format 2 bits from integer part and 19 bits from fractional + * part. The same applies for u0d19, 0 bits from integer part and 19 bits from + * fractional + */ + +uint32_t dal_fixed31_32_u2d19( + struct fixed31_32 arg); + +uint32_t dal_fixed31_32_u0d19( + struct fixed31_32 arg); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/fixed32_32.h b/drivers/gpu/drm/amd/display/include/fixed32_32.h new file mode 100644 index 000000000000..c7ddd0e435eb --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/fixed32_32.h @@ -0,0 +1,83 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef __DAL_FIXED32_32_H__ +#define __DAL_FIXED32_32_H__ + +#include "os_types.h" + +struct fixed32_32 { + uint64_t value; +}; + +static const struct fixed32_32 dal_fixed32_32_zero = { 0 }; +static const struct fixed32_32 dal_fixed32_32_one = { 0x100000000LL }; +static const struct fixed32_32 dal_fixed32_32_half = { 0x80000000LL }; + +struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d); +struct fixed32_32 dal_fixed32_32_from_int(uint32_t value); +struct fixed32_32 dal_fixed32_32_add( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_add_int( + struct fixed32_32 lhs, + uint32_t rhs); +struct fixed32_32 dal_fixed32_32_sub( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_sub_int( + struct fixed32_32 lhs, + uint32_t rhs); +struct fixed32_32 dal_fixed32_32_mul( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_mul_int( + struct fixed32_32 lhs, + uint32_t rhs); +struct fixed32_32 dal_fixed32_32_div( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_div_int( + struct fixed32_32 lhs, + uint32_t rhs); +struct fixed32_32 dal_fixed32_32_min( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +struct fixed32_32 dal_fixed32_32_max( + struct fixed32_32 lhs, + struct fixed32_32 rhs); +bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs); +bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs); +bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs); +bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs); +bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs); +bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs); +bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs); +uint32_t dal_fixed32_32_ceil(struct fixed32_32 value); +uint32_t dal_fixed32_32_floor(struct fixed32_32 value); +uint32_t dal_fixed32_32_round(struct fixed32_32 value); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/gpio_interface.h b/drivers/gpu/drm/amd/display/include/gpio_interface.h new file mode 100644 index 000000000000..e4fd31024b92 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/gpio_interface.h @@ -0,0 +1,92 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_INTERFACE_H__ +#define __DAL_GPIO_INTERFACE_H__ + +#include "gpio_types.h" +#include "grph_object_defs.h" + +struct gpio; + +/* Open the handle for future use */ +enum gpio_result dal_gpio_open( + struct gpio *gpio, + enum gpio_mode mode); + +enum gpio_result dal_gpio_open_ex( + struct gpio *gpio, + enum gpio_mode mode); + +/* Get high or low from the pin */ +enum gpio_result dal_gpio_get_value( + const struct gpio *gpio, + uint32_t *value); + +/* Set pin high or low */ +enum gpio_result dal_gpio_set_value( + const struct gpio *gpio, + uint32_t value); + +/* Get current mode */ +enum gpio_mode dal_gpio_get_mode( + const struct gpio *gpio); + +/* Change mode of the handle */ +enum gpio_result dal_gpio_change_mode( + struct gpio *gpio, + enum gpio_mode mode); + +/* Get the GPIO id */ +enum gpio_id dal_gpio_get_id( + const struct gpio *gpio); + +/* Get the GPIO enum */ +uint32_t dal_gpio_get_enum( + const struct gpio *gpio); + +/* Set the GPIO pin configuration */ +enum gpio_result dal_gpio_set_config( + struct gpio *gpio, + const struct gpio_config_data *config_data); + +/* Obtain GPIO pin info */ +enum gpio_result dal_gpio_get_pin_info( + const struct gpio *gpio, + struct gpio_pin_info *pin_info); + +/* Obtain GPIO sync source */ +enum sync_source dal_gpio_get_sync_source( + const struct gpio *gpio); + +/* Obtain GPIO pin output state (active low or active high) */ +enum gpio_pin_output_state dal_gpio_get_output_state( + const struct gpio *gpio); + +/* Close the handle */ +void dal_gpio_close( + struct gpio *gpio); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/gpio_service_interface.h b/drivers/gpu/drm/amd/display/include/gpio_service_interface.h new file mode 100644 index 000000000000..f40259bade40 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/gpio_service_interface.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_SERVICE_INTERFACE_H__ +#define __DAL_GPIO_SERVICE_INTERFACE_H__ + +#include "gpio_types.h" +#include "gpio_interface.h" +#include "hw/gpio.h" + +struct gpio_service; + +struct gpio *dal_gpio_create( + struct gpio_service *service, + enum gpio_id id, + uint32_t en, + enum gpio_pin_output_state output_state); + +void dal_gpio_destroy( + struct gpio **ptr); + +struct gpio_service *dal_gpio_service_create( + enum dce_version dce_version_major, + enum dce_version dce_version_minor, + struct dc_context *ctx); + +struct gpio *dal_gpio_service_create_irq( + struct gpio_service *service, + uint32_t offset, + uint32_t mask); + +struct ddc *dal_gpio_create_ddc( + struct gpio_service *service, + uint32_t offset, + uint32_t mask, + struct gpio_ddc_hw_info *info); + + +void dal_gpio_destroy_ddc( + struct ddc **ddc); + +void dal_gpio_service_destroy( + struct gpio_service **ptr); + +enum dc_irq_source dal_irq_get_source( + const struct gpio *irq); + +enum dc_irq_source dal_irq_get_rx_source( + const struct gpio *irq); + +enum gpio_result dal_irq_setup_hpd_filter( + struct gpio *irq, + struct gpio_hpd_config *config); + +struct gpio *dal_gpio_create_irq( + struct gpio_service *service, + enum gpio_id id, + uint32_t en); + +void dal_gpio_destroy_irq( + struct gpio **ptr); + + +enum gpio_result dal_ddc_open( + struct ddc *ddc, + enum gpio_mode mode, + enum gpio_ddc_config_type config_type); + +enum gpio_result dal_ddc_change_mode( + struct ddc *ddc, + enum gpio_mode mode); + +enum gpio_ddc_line dal_ddc_get_line( + const struct ddc *ddc); + +enum gpio_result dal_ddc_set_config( + struct ddc *ddc, + enum gpio_ddc_config_type config_type); + +void dal_ddc_close( + struct ddc *ddc); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/gpio_types.h b/drivers/gpu/drm/amd/display/include/gpio_types.h new file mode 100644 index 000000000000..8dd46ed799e5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/gpio_types.h @@ -0,0 +1,332 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GPIO_TYPES_H__ +#define __DAL_GPIO_TYPES_H__ + +#define BUNDLE_A_MASK 0x00FFF000L +#define BUNDLE_B_MASK 0x00000FFFL + +/* + * gpio_result + * + * @brief + * The possible return codes that the GPIO object can return. + * These return codes can be generated + * directly by the GPIO object or from the GPIOPin object. + */ +enum gpio_result { + GPIO_RESULT_OK, + GPIO_RESULT_NULL_HANDLE, + GPIO_RESULT_INVALID_DATA, + GPIO_RESULT_DEVICE_BUSY, + GPIO_RESULT_OPEN_FAILED, + GPIO_RESULT_ALREADY_OPENED, + GPIO_RESULT_NON_SPECIFIC_ERROR +}; + +/* + * @brief + * Used to identify the specific GPIO device + * + * @notes + * These constants are used as indices in a vector. + * Thus they should start from zero and be contiguous. + */ +enum gpio_id { + GPIO_ID_UNKNOWN = (-1), + GPIO_ID_DDC_DATA, + GPIO_ID_DDC_CLOCK, + GPIO_ID_GENERIC, + GPIO_ID_HPD, + GPIO_ID_GPIO_PAD, + GPIO_ID_VIP_PAD, + GPIO_ID_SYNC, + GPIO_ID_GSL, /* global swap lock */ + GPIO_ID_COUNT, + GPIO_ID_MIN = GPIO_ID_DDC_DATA, + GPIO_ID_MAX = GPIO_ID_GSL +}; + +#define GPIO_ENUM_UNKNOWN \ + 32 + +struct gpio_pin_info { + uint32_t offset; + uint32_t offset_y; + uint32_t offset_en; + uint32_t offset_mask; + + uint32_t mask; + uint32_t mask_y; + uint32_t mask_en; + uint32_t mask_mask; +}; + +enum gpio_pin_output_state { + GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW, + GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH, + GPIO_PIN_OUTPUT_STATE_DEFAULT = GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW +}; + +enum gpio_generic { + GPIO_GENERIC_UNKNOWN = (-1), + GPIO_GENERIC_A, + GPIO_GENERIC_B, + GPIO_GENERIC_C, + GPIO_GENERIC_D, + GPIO_GENERIC_E, + GPIO_GENERIC_F, + GPIO_GENERIC_G, + GPIO_GENERIC_COUNT, + GPIO_GENERIC_MIN = GPIO_GENERIC_A, + GPIO_GENERIC_MAX = GPIO_GENERIC_B +}; + +enum gpio_hpd { + GPIO_HPD_UNKNOWN = (-1), + GPIO_HPD_1, + GPIO_HPD_2, + GPIO_HPD_3, + GPIO_HPD_4, + GPIO_HPD_5, + GPIO_HPD_6, + GPIO_HPD_COUNT, + GPIO_HPD_MIN = GPIO_HPD_1, + GPIO_HPD_MAX = GPIO_HPD_6 +}; + +enum gpio_gpio_pad { + GPIO_GPIO_PAD_UNKNOWN = (-1), + GPIO_GPIO_PAD_0, + GPIO_GPIO_PAD_1, + GPIO_GPIO_PAD_2, + GPIO_GPIO_PAD_3, + GPIO_GPIO_PAD_4, + GPIO_GPIO_PAD_5, + GPIO_GPIO_PAD_6, + GPIO_GPIO_PAD_7, + GPIO_GPIO_PAD_8, + GPIO_GPIO_PAD_9, + GPIO_GPIO_PAD_10, + GPIO_GPIO_PAD_11, + GPIO_GPIO_PAD_12, + GPIO_GPIO_PAD_13, + GPIO_GPIO_PAD_14, + GPIO_GPIO_PAD_15, + GPIO_GPIO_PAD_16, + GPIO_GPIO_PAD_17, + GPIO_GPIO_PAD_18, + GPIO_GPIO_PAD_19, + GPIO_GPIO_PAD_20, + GPIO_GPIO_PAD_21, + GPIO_GPIO_PAD_22, + GPIO_GPIO_PAD_23, + GPIO_GPIO_PAD_24, + GPIO_GPIO_PAD_25, + GPIO_GPIO_PAD_26, + GPIO_GPIO_PAD_27, + GPIO_GPIO_PAD_28, + GPIO_GPIO_PAD_29, + GPIO_GPIO_PAD_30, + GPIO_GPIO_PAD_COUNT, + GPIO_GPIO_PAD_MIN = GPIO_GPIO_PAD_0, + GPIO_GPIO_PAD_MAX = GPIO_GPIO_PAD_30 +}; + +enum gpio_vip_pad { + GPIO_VIP_PAD_UNKNOWN = (-1), + /* following never used - + * GPIO_ID_DDC_CLOCK::GPIO_DDC_LINE_VIP_PAD defined instead */ + GPIO_VIP_PAD_SCL, + /* following never used - + * GPIO_ID_DDC_DATA::GPIO_DDC_LINE_VIP_PAD defined instead */ + GPIO_VIP_PAD_SDA, + GPIO_VIP_PAD_VHAD, + GPIO_VIP_PAD_VPHCTL, + GPIO_VIP_PAD_VIPCLK, + GPIO_VIP_PAD_VID, + GPIO_VIP_PAD_VPCLK0, + GPIO_VIP_PAD_DVALID, + GPIO_VIP_PAD_PSYNC, + GPIO_VIP_PAD_COUNT, + GPIO_VIP_PAD_MIN = GPIO_VIP_PAD_SCL, + GPIO_VIP_PAD_MAX = GPIO_VIP_PAD_PSYNC +}; + +enum gpio_sync { + GPIO_SYNC_UNKNOWN = (-1), + GPIO_SYNC_HSYNC_A, + GPIO_SYNC_VSYNC_A, + GPIO_SYNC_HSYNC_B, + GPIO_SYNC_VSYNC_B, + GPIO_SYNC_COUNT, + GPIO_SYNC_MIN = GPIO_SYNC_HSYNC_A, + GPIO_SYNC_MAX = GPIO_SYNC_VSYNC_B +}; + +enum gpio_gsl { + GPIO_GSL_UNKNOWN = (-1), + GPIO_GSL_GENLOCK_CLOCK, + GPIO_GSL_GENLOCK_VSYNC, + GPIO_GSL_SWAPLOCK_A, + GPIO_GSL_SWAPLOCK_B, + GPIO_GSL_COUNT, + GPIO_GSL_MIN = GPIO_GSL_GENLOCK_CLOCK, + GPIO_GSL_MAX = GPIO_GSL_SWAPLOCK_B +}; + +/* + * @brief + * Unique Id for DDC handle. + * Values are meaningful (used as indexes to array) + */ +enum gpio_ddc_line { + GPIO_DDC_LINE_UNKNOWN = (-1), + GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_DDC2, + GPIO_DDC_LINE_DDC3, + GPIO_DDC_LINE_DDC4, + GPIO_DDC_LINE_DDC5, + GPIO_DDC_LINE_DDC6, + GPIO_DDC_LINE_DDC_VGA, + GPIO_DDC_LINE_VIP_PAD, + GPIO_DDC_LINE_I2C_PAD = GPIO_DDC_LINE_VIP_PAD, + GPIO_DDC_LINE_COUNT, + GPIO_DDC_LINE_MIN = GPIO_DDC_LINE_DDC1, + GPIO_DDC_LINE_MAX = GPIO_DDC_LINE_I2C_PAD +}; + +/* + * @brief + * Identifies the mode of operation to open a GPIO device. + * A GPIO device (pin) can be programmed in only one of these modes at a time. + */ +enum gpio_mode { + GPIO_MODE_UNKNOWN = (-1), + GPIO_MODE_INPUT, + GPIO_MODE_OUTPUT, + GPIO_MODE_FAST_OUTPUT, + GPIO_MODE_HARDWARE, + GPIO_MODE_INTERRUPT +}; + +/* + * @brief + * Identifies the source of the signal when GPIO is in HW mode. + * get_signal_source() will return GPIO_SYGNAL_SOURCE__UNKNOWN + * when one of the following holds: + * 1. GPIO is input GPIO + * 2. GPIO is not opened in HW mode + * 3. GPIO does not have fixed signal source + * (like DC_GenericA have mux instead fixed) + */ +enum gpio_signal_source { + GPIO_SIGNAL_SOURCE_UNKNOWN = (-1), + GPIO_SIGNAL_SOURCE_DACA_STEREO_SYNC, + GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC, + GPIO_SIGNAL_SOURCE_DACB_STEREO_SYNC, + GPIO_SIGNAL_SOURCE_DACA_HSYNC, + GPIO_SIGNAL_SOURCE_DACB_HSYNC, + GPIO_SIGNAL_SOURCE_DACA_VSYNC, + GPIO_SIGNAL_SOURCE_DACB_VSYNC, +}; + +enum gpio_stereo_source { + GPIO_STEREO_SOURCE_UNKNOWN = (-1), + GPIO_STEREO_SOURCE_D1, + GPIO_STEREO_SOURCE_D2, + GPIO_STEREO_SOURCE_D3, + GPIO_STEREO_SOURCE_D4, + GPIO_STEREO_SOURCE_D5, + GPIO_STEREO_SOURCE_D6 +}; + +/* + * GPIO config + */ + +enum gpio_config_type { + GPIO_CONFIG_TYPE_NONE, + GPIO_CONFIG_TYPE_DDC, + GPIO_CONFIG_TYPE_HPD, + GPIO_CONFIG_TYPE_GENERIC_MUX, + GPIO_CONFIG_TYPE_GSL_MUX, + GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE +}; + +/* DDC configuration */ + +enum gpio_ddc_config_type { + GPIO_DDC_CONFIG_TYPE_MODE_AUX, + GPIO_DDC_CONFIG_TYPE_MODE_I2C, + GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT, + GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT, + GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING +}; + +struct gpio_ddc_config { + enum gpio_ddc_config_type type; + bool data_en_bit_present; + bool clock_en_bit_present; +}; + +/* HPD configuration */ + +struct gpio_hpd_config { + uint32_t delay_on_connect; /* milliseconds */ + uint32_t delay_on_disconnect; /* milliseconds */ +}; + +struct gpio_generic_mux_config { + bool enable_output_from_mux; + enum gpio_signal_source mux_select; + enum gpio_stereo_source stereo_select; +}; + +enum gpio_gsl_mux_config_type { + GPIO_GSL_MUX_CONFIG_TYPE_DISABLE, + GPIO_GSL_MUX_CONFIG_TYPE_TIMING_SYNC, + GPIO_GSL_MUX_CONFIG_TYPE_FLIP_SYNC +}; + +struct gpio_gsl_mux_config { + enum gpio_gsl_mux_config_type type; + /* Actually sync_source type, + * however we want to avoid inter-component includes here */ + uint32_t gsl_group; +}; + +struct gpio_config_data { + enum gpio_config_type type; + union { + struct gpio_ddc_config ddc; + struct gpio_hpd_config hpd; + struct gpio_generic_mux_config generic_mux; + struct gpio_gsl_mux_config gsl_mux; + } config; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h new file mode 100644 index 000000000000..9c0bf6521dd9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -0,0 +1,407 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GRPH_OBJECT_CTRL_DEFS_H__ +#define __DAL_GRPH_OBJECT_CTRL_DEFS_H__ + +#include "grph_object_defs.h" + +/* + * ##################################################### + * ##################################################### + * + * These defines shared between asic_control/bios_parser and other + * DAL components + * + * ##################################################### + * ##################################################### + */ + +enum display_output_bit_depth { + PANEL_UNDEFINE = 0, + PANEL_6BIT_COLOR = 1, + PANEL_8BIT_COLOR = 2, + PANEL_10BIT_COLOR = 3, + PANEL_12BIT_COLOR = 4, + PANEL_16BIT_COLOR = 5, +}; + + +/* Device type as abstracted by ATOM BIOS */ +enum dal_device_type { + DEVICE_TYPE_UNKNOWN = 0, + DEVICE_TYPE_LCD, + DEVICE_TYPE_CRT, + DEVICE_TYPE_DFP, + DEVICE_TYPE_CV, + DEVICE_TYPE_TV, + DEVICE_TYPE_CF, + DEVICE_TYPE_WIRELESS +}; + +/* Device ID as abstracted by ATOM BIOS */ +struct device_id { + enum dal_device_type device_type:16; + uint32_t enum_id:16; /* 1 based enum */ +}; + +struct graphics_object_i2c_info { + struct gpio_info { + uint32_t clk_mask_register_index; + uint32_t clk_en_register_index; + uint32_t clk_y_register_index; + uint32_t clk_a_register_index; + uint32_t data_mask_register_index; + uint32_t data_en_register_index; + uint32_t data_y_register_index; + uint32_t data_a_register_index; + + uint32_t clk_mask_shift; + uint32_t clk_en_shift; + uint32_t clk_y_shift; + uint32_t clk_a_shift; + uint32_t data_mask_shift; + uint32_t data_en_shift; + uint32_t data_y_shift; + uint32_t data_a_shift; + } gpio_info; + + bool i2c_hw_assist; + uint32_t i2c_line; + uint32_t i2c_engine_id; + uint32_t i2c_slave_address; +}; + +struct graphics_object_hpd_info { + uint8_t hpd_int_gpio_uid; + uint8_t hpd_active; +}; + +struct connector_device_tag_info { + uint32_t acpi_device; + struct device_id dev_id; +}; + +struct device_timing { + struct misc_info { + uint32_t HORIZONTAL_CUT_OFF:1; + /* 0=Active High, 1=Active Low */ + uint32_t H_SYNC_POLARITY:1; + /* 0=Active High, 1=Active Low */ + uint32_t V_SYNC_POLARITY:1; + uint32_t VERTICAL_CUT_OFF:1; + uint32_t H_REPLICATION_BY2:1; + uint32_t V_REPLICATION_BY2:1; + uint32_t COMPOSITE_SYNC:1; + uint32_t INTERLACE:1; + uint32_t DOUBLE_CLOCK:1; + uint32_t RGB888:1; + uint32_t GREY_LEVEL:2; + uint32_t SPATIAL:1; + uint32_t TEMPORAL:1; + uint32_t API_ENABLED:1; + } misc_info; + + uint32_t pixel_clk; /* in KHz */ + uint32_t horizontal_addressable; + uint32_t horizontal_blanking_time; + uint32_t vertical_addressable; + uint32_t vertical_blanking_time; + uint32_t horizontal_sync_offset; + uint32_t horizontal_sync_width; + uint32_t vertical_sync_offset; + uint32_t vertical_sync_width; + uint32_t horizontal_border; + uint32_t vertical_border; +}; + +struct supported_refresh_rate { + uint32_t REFRESH_RATE_30HZ:1; + uint32_t REFRESH_RATE_40HZ:1; + uint32_t REFRESH_RATE_48HZ:1; + uint32_t REFRESH_RATE_50HZ:1; + uint32_t REFRESH_RATE_60HZ:1; +}; + +struct embedded_panel_info { + struct device_timing lcd_timing; + uint32_t ss_id; + struct supported_refresh_rate supported_rr; + uint32_t drr_enabled; + uint32_t min_drr_refresh_rate; + bool realtek_eDPToLVDS; +}; + +struct firmware_info { + struct pll_info { + uint32_t crystal_frequency; /* in KHz */ + uint32_t min_input_pxl_clk_pll_frequency; /* in KHz */ + uint32_t max_input_pxl_clk_pll_frequency; /* in KHz */ + uint32_t min_output_pxl_clk_pll_frequency; /* in KHz */ + uint32_t max_output_pxl_clk_pll_frequency; /* in KHz */ + } pll_info; + + struct firmware_feature { + uint32_t memory_clk_ss_percentage; + uint32_t engine_clk_ss_percentage; + } feature; + + uint32_t default_display_engine_pll_frequency; /* in KHz */ + uint32_t external_clock_source_frequency_for_dp; /* in KHz */ + uint32_t smu_gpu_pll_output_freq; /* in KHz */ + uint8_t min_allowed_bl_level; + uint8_t remote_display_config; + uint32_t default_memory_clk; /* in KHz */ + uint32_t default_engine_clk; /* in KHz */ + uint32_t dp_phy_ref_clk; /* in KHz - DCE12 only */ + uint32_t i2c_engine_ref_clk; /* in KHz - DCE12 only */ + + +}; + +struct step_and_delay_info { + uint32_t step; + uint32_t delay; + uint32_t recommended_ref_div; +}; + +struct spread_spectrum_info { + struct spread_spectrum_type { + bool CENTER_MODE:1; + bool EXTERNAL:1; + bool STEP_AND_DELAY_INFO:1; + } type; + + /* in unit of 0.01% (spreadPercentageDivider = 100), + otherwise in 0.001% units (spreadPercentageDivider = 1000); */ + uint32_t spread_spectrum_percentage; + uint32_t spread_percentage_divider; /* 100 or 1000 */ + uint32_t spread_spectrum_range; /* modulation freq (HZ)*/ + + union { + struct step_and_delay_info step_and_delay_info; + /* For mem/engine/uvd, Clock Out frequence (VCO ), + in unit of kHz. For TMDS/HDMI/LVDS, it is pixel clock, + for DP, it is link clock ( 270000 or 162000 ) */ + uint32_t target_clock_range; /* in KHz */ + }; + +}; + +struct graphics_object_encoder_cap_info { + uint32_t dp_hbr2_cap:1; + uint32_t dp_hbr2_validated:1; + /* + * TODO: added MST and HDMI 6G capable flags + */ + uint32_t reserved:15; +}; + +struct din_connector_info { + uint32_t gpio_id; + bool gpio_tv_active_state; +}; + +/* Invalid channel mapping */ +enum { INVALID_DDI_CHANNEL_MAPPING = 0x0 }; + +/** + * DDI PHY channel mapping reflecting XBAR setting + */ +union ddi_channel_mapping { + struct mapping { + uint8_t lane0:2; /* Mapping for lane 0 */ + uint8_t lane1:2; /* Mapping for lane 1 */ + uint8_t lane2:2; /* Mapping for lane 2 */ + uint8_t lane3:2; /* Mapping for lane 3 */ + } mapping; + uint8_t raw; +}; + +/** +* Transmitter output configuration description +*/ +struct transmitter_configuration_info { + /* DDI PHY ID for the transmitter */ + enum transmitter transmitter_phy_id; + /* DDI PHY channel mapping reflecting crossbar setting */ + union ddi_channel_mapping output_channel_mapping; +}; + +struct transmitter_configuration { + /* Configuration for the primary transmitter */ + struct transmitter_configuration_info primary_transmitter_config; + /* Secondary transmitter configuration for Dual-link DVI */ + struct transmitter_configuration_info secondary_transmitter_config; +}; + +/* These size should be sufficient to store info coming from BIOS */ +#define NUMBER_OF_UCHAR_FOR_GUID 16 +#define MAX_NUMBER_OF_EXT_DISPLAY_PATH 7 +#define NUMBER_OF_CSR_M3_ARB 10 +#define NUMBER_OF_DISP_CLK_VOLTAGE 4 +#define NUMBER_OF_AVAILABLE_SCLK 5 + +/* V6 */ +struct integrated_info { + struct clock_voltage_caps { + /* The Voltage Index indicated by FUSE, same voltage index + shared with SCLK DPM fuse table */ + uint32_t voltage_index; + /* Maximum clock supported with specified voltage index */ + uint32_t max_supported_clk; /* in KHz */ + } disp_clk_voltage[NUMBER_OF_DISP_CLK_VOLTAGE]; + + struct display_connection_info { + struct external_display_path { + /* A bit vector to show what devices are supported */ + uint32_t device_tag; + /* 16bit device ACPI id. */ + uint32_t device_acpi_enum; + /* A physical connector for displays to plug in, + using object connector definitions */ + struct graphics_object_id device_connector_id; + /* An index into external AUX/DDC channel LUT */ + uint8_t ext_aux_ddc_lut_index; + /* An index into external HPD pin LUT */ + uint8_t ext_hpd_pin_lut_index; + /* external encoder object id */ + struct graphics_object_id ext_encoder_obj_id; + /* XBAR mapping of the PHY channels */ + union ddi_channel_mapping channel_mapping; + } path[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; + + uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID]; + uint8_t checksum; + } ext_disp_conn_info; /* exiting long long time */ + + struct available_s_clk_list { + /* Maximum clock supported with specified voltage index */ + uint32_t supported_s_clk; /* in KHz */ + /* The Voltage Index indicated by FUSE for specified SCLK */ + uint32_t voltage_index; + /* The Voltage ID indicated by FUSE for specified SCLK */ + uint32_t voltage_id; + } avail_s_clk[NUMBER_OF_AVAILABLE_SCLK]; + + uint8_t memory_type; + uint8_t ma_channel_number; + uint32_t boot_up_engine_clock; /* in KHz */ + uint32_t dentist_vco_freq; /* in KHz */ + uint32_t boot_up_uma_clock; /* in KHz */ + uint32_t boot_up_req_display_vector; + uint32_t other_display_misc; + uint32_t gpu_cap_info; + uint32_t sb_mmio_base_addr; + uint32_t system_config; + uint32_t cpu_cap_info; + uint32_t max_nb_voltage; + uint32_t min_nb_voltage; + uint32_t boot_up_nb_voltage; + uint32_t ext_disp_conn_info_offset; + uint32_t csr_m3_arb_cntl_default[NUMBER_OF_CSR_M3_ARB]; + uint32_t csr_m3_arb_cntl_uvd[NUMBER_OF_CSR_M3_ARB]; + uint32_t csr_m3_arb_cntl_fs3d[NUMBER_OF_CSR_M3_ARB]; + uint32_t gmc_restore_reset_time; + uint32_t minimum_n_clk; + uint32_t idle_n_clk; + uint32_t ddr_dll_power_up_time; + uint32_t ddr_pll_power_up_time; + /* start for V6 */ + uint32_t pcie_clk_ss_type; + uint32_t lvds_ss_percentage; + uint32_t lvds_sspread_rate_in_10hz; + uint32_t hdmi_ss_percentage; + uint32_t hdmi_sspread_rate_in_10hz; + uint32_t dvi_ss_percentage; + uint32_t dvi_sspread_rate_in_10_hz; + uint32_t sclk_dpm_boost_margin; + uint32_t sclk_dpm_throttle_margin; + uint32_t sclk_dpm_tdp_limit_pg; + uint32_t sclk_dpm_tdp_limit_boost; + uint32_t boost_engine_clock; + uint32_t boost_vid_2bit; + uint32_t enable_boost; + uint32_t gnb_tdp_limit; + /* Start from V7 */ + uint32_t max_lvds_pclk_freq_in_single_link; + uint32_t lvds_misc; + uint32_t lvds_pwr_on_seq_dig_on_to_de_in_4ms; + uint32_t lvds_pwr_on_seq_de_to_vary_bl_in_4ms; + uint32_t lvds_pwr_off_seq_vary_bl_to_de_in4ms; + uint32_t lvds_pwr_off_seq_de_to_dig_on_in4ms; + uint32_t lvds_off_to_on_delay_in_4ms; + uint32_t lvds_pwr_on_seq_vary_bl_to_blon_in_4ms; + uint32_t lvds_pwr_off_seq_blon_to_vary_bl_in_4ms; + uint32_t lvds_reserved1; + uint32_t lvds_bit_depth_control_val; +}; + +/** +* Power source ids. +*/ +enum power_source { + POWER_SOURCE_AC = 0, + POWER_SOURCE_DC, + POWER_SOURCE_LIMITED_POWER, + POWER_SOURCE_LIMITED_POWER_2, + POWER_SOURCE_MAX +}; + +struct bios_event_info { + uint32_t thermal_state; + uint32_t backlight_level; + enum power_source powerSource; + bool has_thermal_state_changed; + bool has_power_source_changed; + bool has_forced_mode_changed; + bool forced_mode; + bool backlight_changed; +}; + +enum { + HDMI_PIXEL_CLOCK_IN_KHZ_297 = 297000, + TMDS_PIXEL_CLOCK_IN_KHZ_165 = 165000 +}; + +/* + * DFS-bypass flag + */ +/* Copy of SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS from atombios.h */ +enum { + DFS_BYPASS_ENABLE = 0x10 +}; + +enum { + INVALID_BACKLIGHT = -1 +}; + +struct panel_backlight_boundaries { + uint32_t min_signal_level; + uint32_t max_signal_level; +}; + + +#endif diff --git a/drivers/gpu/drm/amd/display/include/grph_object_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_defs.h new file mode 100644 index 000000000000..2941b882b0b6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/grph_object_defs.h @@ -0,0 +1,140 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GRPH_OBJECT_DEFS_H__ +#define __DAL_GRPH_OBJECT_DEFS_H__ + +#include "grph_object_id.h" + +/* ******************************************************************** + * ******************************************************************** + * + * These defines shared between All Graphics Objects + * + * ******************************************************************** + * ******************************************************************** + */ + +/* HPD unit id - HW direct translation */ +enum hpd_source_id { + HPD_SOURCEID1 = 0, + HPD_SOURCEID2, + HPD_SOURCEID3, + HPD_SOURCEID4, + HPD_SOURCEID5, + HPD_SOURCEID6, + + HPD_SOURCEID_COUNT, + HPD_SOURCEID_UNKNOWN +}; + +/* DDC unit id - HW direct translation */ +enum channel_id { + CHANNEL_ID_UNKNOWN = 0, + CHANNEL_ID_DDC1, + CHANNEL_ID_DDC2, + CHANNEL_ID_DDC3, + CHANNEL_ID_DDC4, + CHANNEL_ID_DDC5, + CHANNEL_ID_DDC6, + CHANNEL_ID_DDC_VGA, + CHANNEL_ID_I2C_PAD, + CHANNEL_ID_COUNT +}; + +#define DECODE_CHANNEL_ID(ch_id) \ + (ch_id) == CHANNEL_ID_DDC1 ? "CHANNEL_ID_DDC1" : \ + (ch_id) == CHANNEL_ID_DDC2 ? "CHANNEL_ID_DDC2" : \ + (ch_id) == CHANNEL_ID_DDC3 ? "CHANNEL_ID_DDC3" : \ + (ch_id) == CHANNEL_ID_DDC4 ? "CHANNEL_ID_DDC4" : \ + (ch_id) == CHANNEL_ID_DDC5 ? "CHANNEL_ID_DDC5" : \ + (ch_id) == CHANNEL_ID_DDC6 ? "CHANNEL_ID_DDC6" : \ + (ch_id) == CHANNEL_ID_DDC_VGA ? "CHANNEL_ID_DDC_VGA" : \ + (ch_id) == CHANNEL_ID_I2C_PAD ? "CHANNEL_ID_I2C_PAD" : "Invalid" + +enum transmitter { + TRANSMITTER_UNKNOWN = (-1L), + TRANSMITTER_UNIPHY_A, + TRANSMITTER_UNIPHY_B, + TRANSMITTER_UNIPHY_C, + TRANSMITTER_UNIPHY_D, + TRANSMITTER_UNIPHY_E, + TRANSMITTER_UNIPHY_F, + TRANSMITTER_NUTMEG_CRT, + TRANSMITTER_TRAVIS_CRT, + TRANSMITTER_TRAVIS_LCD, + TRANSMITTER_UNIPHY_G, + TRANSMITTER_COUNT +}; + +/* Generic source of the synchronisation input/output signal */ +/* Can be used for flow control, stereo sync, timing sync, frame sync, etc */ +enum sync_source { + SYNC_SOURCE_NONE = 0, + + /* Source based on controllers */ + SYNC_SOURCE_CONTROLLER0, + SYNC_SOURCE_CONTROLLER1, + SYNC_SOURCE_CONTROLLER2, + SYNC_SOURCE_CONTROLLER3, + SYNC_SOURCE_CONTROLLER4, + SYNC_SOURCE_CONTROLLER5, + + /* Source based on GSL group */ + SYNC_SOURCE_GSL_GROUP0, + SYNC_SOURCE_GSL_GROUP1, + SYNC_SOURCE_GSL_GROUP2, + + /* Source based on GSL IOs */ + /* These IOs normally used as GSL input/output */ + SYNC_SOURCE_GSL_IO_FIRST, + SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK = SYNC_SOURCE_GSL_IO_FIRST, + SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC, + SYNC_SOURCE_GSL_IO_SWAPLOCK_A, + SYNC_SOURCE_GSL_IO_SWAPLOCK_B, + SYNC_SOURCE_GSL_IO_LAST = SYNC_SOURCE_GSL_IO_SWAPLOCK_B, + + /* Source based on regular IOs */ + SYNC_SOURCE_IO_FIRST, + SYNC_SOURCE_IO_GENERIC_A = SYNC_SOURCE_IO_FIRST, + SYNC_SOURCE_IO_GENERIC_B, + SYNC_SOURCE_IO_GENERIC_C, + SYNC_SOURCE_IO_GENERIC_D, + SYNC_SOURCE_IO_GENERIC_E, + SYNC_SOURCE_IO_GENERIC_F, + SYNC_SOURCE_IO_HPD1, + SYNC_SOURCE_IO_HPD2, + SYNC_SOURCE_IO_HSYNC_A, + SYNC_SOURCE_IO_VSYNC_A, + SYNC_SOURCE_IO_HSYNC_B, + SYNC_SOURCE_IO_VSYNC_B, + SYNC_SOURCE_IO_LAST = SYNC_SOURCE_IO_VSYNC_B, + + /* Misc. flow control sources */ + SYNC_SOURCE_DUAL_GPU_PIN +}; + + +#endif diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h new file mode 100644 index 000000000000..e4aa4ddf9d2a --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h @@ -0,0 +1,256 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_GRPH_OBJECT_ID_H__ +#define __DAL_GRPH_OBJECT_ID_H__ + +/* Types of graphics objects */ +enum object_type { + OBJECT_TYPE_UNKNOWN = 0, + + /* Direct ATOM BIOS translation */ + OBJECT_TYPE_GPU, + OBJECT_TYPE_ENCODER, + OBJECT_TYPE_CONNECTOR, + OBJECT_TYPE_ROUTER, + OBJECT_TYPE_GENERIC, + + /* Driver specific */ + OBJECT_TYPE_AUDIO, + OBJECT_TYPE_CONTROLLER, + OBJECT_TYPE_CLOCK_SOURCE, + OBJECT_TYPE_ENGINE, + + OBJECT_TYPE_COUNT +}; + +/* Enumeration inside one type of graphics objects */ +enum object_enum_id { + ENUM_ID_UNKNOWN = 0, + ENUM_ID_1, + ENUM_ID_2, + ENUM_ID_3, + ENUM_ID_4, + ENUM_ID_5, + ENUM_ID_6, + ENUM_ID_7, + + ENUM_ID_COUNT +}; + +/* Generic object ids */ +enum generic_id { + GENERIC_ID_UNKNOWN = 0, + GENERIC_ID_MXM_OPM, + GENERIC_ID_GLSYNC, + GENERIC_ID_STEREO, + + GENERIC_ID_COUNT +}; + +/* Controller object ids */ +enum controller_id { + CONTROLLER_ID_UNDEFINED = 0, + CONTROLLER_ID_D0, + CONTROLLER_ID_D1, + CONTROLLER_ID_D2, + CONTROLLER_ID_D3, + CONTROLLER_ID_D4, + CONTROLLER_ID_D5, + CONTROLLER_ID_UNDERLAY0, + CONTROLLER_ID_MAX = CONTROLLER_ID_UNDERLAY0 +}; + +#define IS_UNDERLAY_CONTROLLER(ctrlr_id) (ctrlr_id >= CONTROLLER_ID_UNDERLAY0) + +/* + * ClockSource object ids. + * We maintain the order matching (more or less) ATOM BIOS + * to improve optimized acquire + */ +enum clock_source_id { + CLOCK_SOURCE_ID_UNDEFINED = 0, + CLOCK_SOURCE_ID_PLL0, + CLOCK_SOURCE_ID_PLL1, + CLOCK_SOURCE_ID_PLL2, + CLOCK_SOURCE_ID_EXTERNAL, /* ID (Phy) ref. clk. for DP */ + CLOCK_SOURCE_ID_DCPLL, + CLOCK_SOURCE_ID_DFS, /* DENTIST */ + CLOCK_SOURCE_ID_VCE, /* VCE does not need a real PLL */ + /* Used to distinguish between programming pixel clock and ID (Phy) clock */ + CLOCK_SOURCE_ID_DP_DTO, + + CLOCK_SOURCE_COMBO_PHY_PLL0, /*combo PHY PLL defines (DC 11.2 and up)*/ + CLOCK_SOURCE_COMBO_PHY_PLL1, + CLOCK_SOURCE_COMBO_PHY_PLL2, + CLOCK_SOURCE_COMBO_PHY_PLL3, + CLOCK_SOURCE_COMBO_PHY_PLL4, + CLOCK_SOURCE_COMBO_PHY_PLL5, + CLOCK_SOURCE_COMBO_DISPLAY_PLL0 +}; + +/* Encoder object ids */ +enum encoder_id { + ENCODER_ID_UNKNOWN = 0, + + /* Radeon Class Display Hardware */ + ENCODER_ID_INTERNAL_LVDS, + ENCODER_ID_INTERNAL_TMDS1, + ENCODER_ID_INTERNAL_TMDS2, + ENCODER_ID_INTERNAL_DAC1, + ENCODER_ID_INTERNAL_DAC2, /* TV/CV DAC */ + + /* External Third Party Encoders */ + ENCODER_ID_INTERNAL_LVTM1, /* not used for Radeon */ + ENCODER_ID_INTERNAL_HDMI, + + /* Kaledisope (KLDSCP) Class Display Hardware */ + ENCODER_ID_INTERNAL_KLDSCP_TMDS1, + ENCODER_ID_INTERNAL_KLDSCP_DAC1, + ENCODER_ID_INTERNAL_KLDSCP_DAC2, /* Shared with CV/TV and CRT */ + /* External TMDS (dual link) */ + ENCODER_ID_EXTERNAL_MVPU_FPGA, /* MVPU FPGA chip */ + ENCODER_ID_INTERNAL_DDI, + ENCODER_ID_INTERNAL_UNIPHY, + ENCODER_ID_INTERNAL_KLDSCP_LVTMA, + ENCODER_ID_INTERNAL_UNIPHY1, + ENCODER_ID_INTERNAL_UNIPHY2, + ENCODER_ID_EXTERNAL_NUTMEG, + ENCODER_ID_EXTERNAL_TRAVIS, + + ENCODER_ID_INTERNAL_WIRELESS, /* Internal wireless display encoder */ + ENCODER_ID_INTERNAL_UNIPHY3, + ENCODER_ID_INTERNAL_VIRTUAL, +}; + +/* Connector object ids */ +enum connector_id { + CONNECTOR_ID_UNKNOWN = 0, + CONNECTOR_ID_SINGLE_LINK_DVII = 1, + CONNECTOR_ID_DUAL_LINK_DVII = 2, + CONNECTOR_ID_SINGLE_LINK_DVID = 3, + CONNECTOR_ID_DUAL_LINK_DVID = 4, + CONNECTOR_ID_VGA = 5, + CONNECTOR_ID_HDMI_TYPE_A = 12, + CONNECTOR_ID_LVDS = 14, + CONNECTOR_ID_PCIE = 16, + CONNECTOR_ID_HARDCODE_DVI = 18, + CONNECTOR_ID_DISPLAY_PORT = 19, + CONNECTOR_ID_EDP = 20, + CONNECTOR_ID_MXM = 21, + CONNECTOR_ID_WIRELESS = 22, + CONNECTOR_ID_MIRACAST = 23, + + CONNECTOR_ID_VIRTUAL = 100 +}; + +/* Audio object ids */ +enum audio_id { + AUDIO_ID_UNKNOWN = 0, + AUDIO_ID_INTERNAL_AZALIA +}; + +/* Engine object ids */ +enum engine_id { + ENGINE_ID_DIGA, + ENGINE_ID_DIGB, + ENGINE_ID_DIGC, + ENGINE_ID_DIGD, + ENGINE_ID_DIGE, + ENGINE_ID_DIGF, + ENGINE_ID_DIGG, + ENGINE_ID_DACA, + ENGINE_ID_DACB, + ENGINE_ID_VCE, /* wireless display pseudo-encoder */ + ENGINE_ID_VIRTUAL, + + ENGINE_ID_COUNT, + ENGINE_ID_UNKNOWN = (-1L) +}; + +enum transmitter_color_depth { + TRANSMITTER_COLOR_DEPTH_24 = 0, /* 8 bits */ + TRANSMITTER_COLOR_DEPTH_30, /* 10 bits */ + TRANSMITTER_COLOR_DEPTH_36, /* 12 bits */ + TRANSMITTER_COLOR_DEPTH_48 /* 16 bits */ +}; + +/* + ***************************************************************************** + * graphics_object_id struct + * + * graphics_object_id is a very simple struct wrapping 32bit Graphics + * Object identication + * + * This struct should stay very simple + * No dependencies at all (no includes) + * No debug messages or asserts + * No #ifndef and preprocessor directives + * No grow in space (no more data member) + ***************************************************************************** + */ + +struct graphics_object_id { + uint32_t id:8; + uint32_t enum_id:4; + uint32_t type:4; + uint32_t reserved:16; /* for padding. total size should be u32 */ +}; + +/* some simple functions for convenient graphics_object_id handle */ + +static inline struct graphics_object_id dal_graphics_object_id_init( + uint32_t id, + enum object_enum_id enum_id, + enum object_type type) +{ + struct graphics_object_id result = { + id, enum_id, type, 0 + }; + + return result; +} + +bool dal_graphics_object_id_is_valid( + struct graphics_object_id id); +bool dal_graphics_object_id_is_equal( + struct graphics_object_id id1, + struct graphics_object_id id2); +uint32_t dal_graphics_object_id_to_uint( + struct graphics_object_id id); + +enum controller_id dal_graphics_object_id_get_controller_id( + struct graphics_object_id id); +enum clock_source_id dal_graphics_object_id_get_clock_source_id( + struct graphics_object_id id); +enum encoder_id dal_graphics_object_id_get_encoder_id( + struct graphics_object_id id); +enum connector_id dal_graphics_object_id_get_connector_id( + struct graphics_object_id id); +enum audio_id dal_graphics_object_id_get_audio_id( + struct graphics_object_id id); +enum engine_id dal_graphics_object_id_get_engine_id( + struct graphics_object_id id); +#endif diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h new file mode 100644 index 000000000000..9a78097e70f3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_SEQUENCER_TYPES_H__ +#define __DAL_HW_SEQUENCER_TYPES_H__ + +#include "signal_types.h" +#include "grph_object_defs.h" +#include "link_service_types.h" + +/* define the structure of Dynamic Refresh Mode */ +struct drr_params { + /* defines the minimum possible vertical dimension of display timing + * for CRTC as supported by the panel */ + uint32_t vertical_total_min; + /* defines the maximum possible vertical dimension of display timing + * for CRTC as supported by the panel */ + uint32_t vertical_total_max; +}; + +/* CRTC timing structure */ +struct hw_crtc_timing { + uint32_t h_total; + uint32_t h_addressable; + uint32_t h_overscan_left; + uint32_t h_overscan_right; + uint32_t h_sync_start; + uint32_t h_sync_width; + + uint32_t v_total; + uint32_t v_addressable; + uint32_t v_overscan_top; + uint32_t v_overscan_bottom; + uint32_t v_sync_start; + uint32_t v_sync_width; + + /* in KHz */ + uint32_t pixel_clock; + + struct { + uint32_t INTERLACED:1; + uint32_t DOUBLESCAN:1; + uint32_t PIXEL_REPETITION:4; /* 1...10 */ + uint32_t HSYNC_POSITIVE_POLARITY:1; + uint32_t VSYNC_POSITIVE_POLARITY:1; + /* frame should be packed for 3D + * (currently this refers to HDMI 1.4a FramePacking format */ + uint32_t HORZ_COUNT_BY_TWO:1; + uint32_t PACK_3D_FRAME:1; + /* 0 - left eye polarity, 1 - right eye polarity */ + uint32_t RIGHT_EYE_3D_POLARITY:1; + /* DVI-DL High-Color mode */ + uint32_t HIGH_COLOR_DL_MODE:1; + uint32_t Y_ONLY:1; + /* HDMI 2.0 - Support scrambling for TMDS character + * rates less than or equal to 340Mcsc */ + uint32_t LTE_340MCSC_SCRAMBLE:1; + } flags; +}; + +/* TODO hw_info_frame and hw_info_packet structures are same as in encoder + * merge it*/ +struct hw_info_packet { + bool valid; + uint8_t hb0; + uint8_t hb1; + uint8_t hb2; + uint8_t hb3; + uint8_t sb[28]; +}; + +struct hw_info_frame { + /* Auxiliary Video Information */ + struct hw_info_packet avi_info_packet; + struct hw_info_packet gamut_packet; + struct hw_info_packet vendor_info_packet; + /* Source Product Description */ + struct hw_info_packet spd_packet; + /* Video Stream Configuration */ + struct hw_info_packet vsc_packet; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/include/i2caux_interface.h b/drivers/gpu/drm/amd/display/include/i2caux_interface.h new file mode 100644 index 000000000000..d2ec04d1c592 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/i2caux_interface.h @@ -0,0 +1,89 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2CAUX_INTERFACE_H__ +#define __DAL_I2CAUX_INTERFACE_H__ + +#include "gpio_service_interface.h" + + +#define DEFAULT_AUX_MAX_DATA_SIZE 16 +#define AUX_MAX_DEFER_WRITE_RETRY 20 + +struct aux_payload { + /* set following flag to read/write I2C data, + * reset it to read/write DPCD data */ + bool i2c_over_aux; + /* set following flag to write data, + * reset it to read data */ + bool write; + uint32_t address; + uint8_t length; + uint8_t *data; +}; + +struct aux_command { + struct aux_payload *payloads; + uint8_t number_of_payloads; + + /* expressed in milliseconds + * zero means "use default value" */ + uint32_t defer_delay; + + /* zero means "use default value" */ + uint32_t max_defer_write_retry; +}; + +union aux_config { + struct { + uint32_t ALLOW_AUX_WHEN_HPD_LOW:1; + } bits; + uint32_t raw; +}; + +struct i2caux; + +struct i2caux *dal_i2caux_create( + struct dc_context *ctx); + +bool dal_i2caux_submit_i2c_command( + struct i2caux *i2caux, + struct ddc *ddc, + struct i2c_command *cmd); + +bool dal_i2caux_submit_aux_command( + struct i2caux *i2caux, + struct ddc *ddc, + struct aux_command *cmd); + +void dal_i2caux_configure_aux( + struct i2caux *i2caux, + struct ddc *ddc, + union aux_config cfg); + +void dal_i2caux_destroy( + struct i2caux **ptr); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/irq_interface.h b/drivers/gpu/drm/amd/display/include/irq_interface.h new file mode 100644 index 000000000000..077ded3fbedd --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/irq_interface.h @@ -0,0 +1,31 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_INTERFACE_H__ +#define __DAL_IRQ_INTERFACE_H__ + +#include "gpio_types.h" + +#endif diff --git a/drivers/gpu/drm/amd/display/include/irq_service_interface.h b/drivers/gpu/drm/amd/display/include/irq_service_interface.h new file mode 100644 index 000000000000..d6ebed524daf --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/irq_service_interface.h @@ -0,0 +1,51 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_INTERFACE_H__ +#define __DAL_IRQ_SERVICE_INTERFACE_H__ + +struct irq_service_init_data { + struct dc_context *ctx; +}; + +struct irq_service; + +void dal_irq_service_destroy(struct irq_service **irq_service); + +bool dal_irq_service_set( + struct irq_service *irq_service, + enum dc_irq_source source, + bool enable); + +bool dal_irq_service_ack( + struct irq_service *irq_service, + enum dc_irq_source source); + +enum dc_irq_source dal_irq_service_to_irq_source( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h new file mode 100644 index 000000000000..06e68426d430 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -0,0 +1,232 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_LINK_SERVICE_TYPES_H__ +#define __DAL_LINK_SERVICE_TYPES_H__ + +#include "grph_object_id.h" +#include "dpcd_defs.h" +#include "dal_types.h" +#include "irq_types.h" + +/*struct mst_mgr_callback_object;*/ +struct ddc; +struct irq_manager; + +enum { + MAX_CONTROLLER_NUM = 6 +}; + +enum link_service_type { + LINK_SERVICE_TYPE_LEGACY = 0, + LINK_SERVICE_TYPE_DP_SST, + LINK_SERVICE_TYPE_DP_MST, + LINK_SERVICE_TYPE_MAX +}; + +enum dpcd_value_mask { + DPCD_VALUE_MASK_MAX_LANE_COUNT_LANE_COUNT = 0x1F, + DPCD_VALUE_MASK_MAX_LANE_COUNT_TPS3_SUPPORTED = 0x40, + DPCD_VALUE_MASK_MAX_LANE_COUNT_ENHANCED_FRAME_EN = 0x80, + DPCD_VALUE_MASK_MAX_DOWNSPREAD = 0x01, + DPCD_VALUE_MASK_LANE_ALIGN_STATUS_INTERLANE_ALIGN_DONE = 0x01 +}; + +enum dp_power_state { + DP_POWER_STATE_D0 = 1, + DP_POWER_STATE_D3 +}; + +enum dpcd_downstream_port_types { + DPCD_DOWNSTREAM_DP, + DPCD_DOWNSTREAM_VGA, + DPCD_DOWNSTREAM_DVI_HDMI, + /* has no EDID (TV, CV) */ + DPCD_DOWNSTREAM_NON_DDC +}; + +enum edp_revision { + /* eDP version 1.1 or lower */ + EDP_REVISION_11 = 0x00, + /* eDP version 1.2 */ + EDP_REVISION_12 = 0x01, + /* eDP version 1.3 */ + EDP_REVISION_13 = 0x02 +}; + +enum { + LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/ +}; + +struct link_training_settings { + struct dc_link_settings link_settings; + struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]; + bool allow_invalid_msa_timing_param; +}; + +enum hw_dp_training_pattern { + HW_DP_TRAINING_PATTERN_1 = 0, + HW_DP_TRAINING_PATTERN_2, + HW_DP_TRAINING_PATTERN_3, + HW_DP_TRAINING_PATTERN_4 +}; + +/*TODO: Move this enum test harness*/ +/* Test patterns*/ +enum dp_test_pattern { + /* Input data is pass through Scrambler + * and 8b10b Encoder straight to output*/ + DP_TEST_PATTERN_VIDEO_MODE = 0, + /* phy test patterns*/ + DP_TEST_PATTERN_D102, + DP_TEST_PATTERN_SYMBOL_ERROR, + DP_TEST_PATTERN_PRBS7, + + DP_TEST_PATTERN_80BIT_CUSTOM, + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE, + + /* Link Training Patterns */ + DP_TEST_PATTERN_TRAINING_PATTERN1, + DP_TEST_PATTERN_TRAINING_PATTERN2, + DP_TEST_PATTERN_TRAINING_PATTERN3, + DP_TEST_PATTERN_TRAINING_PATTERN4, + + /* link test patterns*/ + DP_TEST_PATTERN_COLOR_SQUARES, + DP_TEST_PATTERN_COLOR_SQUARES_CEA, + DP_TEST_PATTERN_VERTICAL_BARS, + DP_TEST_PATTERN_HORIZONTAL_BARS, + DP_TEST_PATTERN_COLOR_RAMP, + + /* audio test patterns*/ + DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED, + DP_TEST_PATTERN_AUDIO_SAWTOOTH, + + DP_TEST_PATTERN_UNSUPPORTED +}; + +enum dp_panel_mode { + /* not required */ + DP_PANEL_MODE_DEFAULT, + /* standard mode for eDP */ + DP_PANEL_MODE_EDP, + /* external chips specific settings */ + DP_PANEL_MODE_SPECIAL +}; + +/** + * @brief LinkServiceInitOptions to set certain bits + */ +struct link_service_init_options { + uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1; +}; + +/** + * @brief data required to initialize LinkService + */ +struct link_service_init_data { + /* number of displays indices which the MST Mgr would manange*/ + uint32_t num_of_displays; + enum link_service_type link_type; + /*struct mst_mgr_callback_object*topology_change_callback;*/ + /* native aux access */ + struct ddc_service *dpcd_access_srv; + /* for calling HWSS to program HW */ + struct hw_sequencer *hwss; + /* the source which to register IRQ on */ + enum dc_irq_source irq_src_hpd_rx; + enum dc_irq_source irq_src_dp_sink; + /* other init options such as SW Workarounds */ + struct link_service_init_options init_options; + uint32_t connector_enum_id; + struct graphics_object_id connector_id; + struct dc_context *ctx; + struct topology_mgr *tm; +}; + +/* DPCD_ADDR_TRAINING_LANEx_SET registers value */ +union dpcd_training_lane_set { + struct { +#if defined(LITTLEENDIAN_CPU) + uint8_t VOLTAGE_SWING_SET:2; + uint8_t MAX_SWING_REACHED:1; + uint8_t PRE_EMPHASIS_SET:2; + uint8_t MAX_PRE_EMPHASIS_REACHED:1; + /* following is reserved in DP 1.1 */ + uint8_t POST_CURSOR2_SET:2; +#elif defined(BIGENDIAN_CPU) + uint8_t POST_CURSOR2_SET:2; + uint8_t MAX_PRE_EMPHASIS_REACHED:1; + uint8_t PRE_EMPHASIS_SET:2; + uint8_t MAX_SWING_REACHED:1; + uint8_t VOLTAGE_SWING_SET:2; +#else + #error ARCH not defined! +#endif + } bits; + + uint8_t raw; +}; + +/** + * @brief represent the 16 byte + * global unique identifier + */ +struct mst_guid { + uint8_t ids[16]; +}; + +/** + * @brief represents the relative address used + * to identify a node in MST topology network + */ +struct mst_rad { + /* number of links. rad[0] up to + * rad [linkCount - 1] are valid. */ + uint32_t rad_link_count; + /* relative address. rad[0] is the + * first device connected to the source. */ + uint8_t rad[15]; + /* extra 10 bytes for underscores; for e.g.:2_1_8*/ + int8_t rad_str[25]; +}; + +/* DP MST stream allocation (payload bandwidth number) */ +struct dp_mst_stream_allocation { + uint8_t vcp_id; + /* number of slots required for the DP stream in + * transport packet */ + uint8_t slot_count; +}; + +/* DP MST stream allocation table */ +struct dp_mst_stream_allocation_table { + /* number of DP video streams */ + int stream_count; + /* array of stream allocations */ + struct dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; +}; + +#endif /*__DAL_LINK_SERVICE_TYPES_H__*/ diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h new file mode 100644 index 000000000000..b58d30de8293 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -0,0 +1,140 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_LOGGER_INTERFACE_H__ +#define __DAL_LOGGER_INTERFACE_H__ + +#include "logger_types.h" + +struct dc_context; +struct dc_link; +struct dc_surface_update; + +/* + * + * DAL logger functionality + * + */ + +struct dal_logger *dal_logger_create(struct dc_context *ctx); + +uint32_t dal_logger_destroy(struct dal_logger **logger); + +void dm_logger_write( + struct dal_logger *logger, + enum dc_log_type log_type, + const char *msg, + ...); + +void dm_logger_append( + struct log_entry *entry, + const char *msg, + ...); + +void dm_logger_open( + struct dal_logger *logger, + struct log_entry *entry, + enum dc_log_type log_type); + +void dm_logger_close(struct log_entry *entry); + +void dc_conn_log(struct dc_context *ctx, + const struct dc_link *link, + uint8_t *hex_data, + int hex_data_count, + enum dc_log_type event, + const char *msg, + ...); + +void logger_write(struct dal_logger *logger, + enum dc_log_type log_type, + const char *msg, + void *paralist); + +void pre_surface_trace( + const struct dc *dc, + const struct dc_surface *const *surfaces, + int surface_count); + +void update_surface_trace( + const struct dc *dc, + const struct dc_surface_update *updates, + int surface_count); + +void post_surface_trace(const struct dc *dc); + + +/* Any function which is empty or have incomplete implementation should be + * marked by this macro. + * Note that the message will be printed exactly once for every function + * it is used in order to avoid repeating of the same message. */ +#define DAL_LOGGER_NOT_IMPL(fmt, ...) \ +{ \ + static bool print_not_impl = true; \ +\ + if (print_not_impl == true) { \ + print_not_impl = false; \ + dm_logger_write(ctx->logger, LOG_WARNING, \ + "DAL_NOT_IMPL: " fmt, ##__VA_ARGS__); \ + } \ +} + +/****************************************************************************** + * Convenience macros to save on typing. + *****************************************************************************/ + +#define DC_ERROR(...) \ + dm_logger_write(dc_ctx->logger, LOG_ERROR, \ + __VA_ARGS__); + +#define DC_SYNC_INFO(...) \ + dm_logger_write(dc_ctx->logger, LOG_SYNC, \ + __VA_ARGS__); + + +/* Connectivity log format: + * [time stamp] [drm] [Major_minor] [connector name] message..... + * eg: + * [ 26.590965] [drm] [Conn_LKTN] [DP-1] HBRx4 pass VS=0, PE=0^ + * [ 26.881060] [drm] [Conn_Mode] [DP-1] {2560x1080, 2784x1111@185580Khz}^ + */ + +#define CONN_DATA_DETECT(link, hex_data, hex_len, ...) \ + dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \ + LOG_EVENT_DETECTION, ##__VA_ARGS__) + +#define CONN_DATA_LINK_LOSS(link, hex_data, hex_len, ...) \ + dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \ + LOG_EVENT_LINK_LOSS, ##__VA_ARGS__) + +#define CONN_MSG_LT(link, ...) \ + dc_conn_log(link->ctx, &link->public, NULL, 0, \ + LOG_EVENT_LINK_TRAINING, ##__VA_ARGS__) + +#define CONN_MSG_MODE(link, ...) \ + dc_conn_log(link->ctx, &link->public, NULL, 0, \ + LOG_EVENT_MODE_SET, ##__VA_ARGS__) + +#endif /* __DAL_LOGGER_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h new file mode 100644 index 000000000000..babd6523b105 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -0,0 +1,95 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_LOGGER_TYPES_H__ +#define __DAL_LOGGER_TYPES_H__ + +#include "os_types.h" + +#define MAX_NAME_LEN 32 + +struct dal_logger; + +enum dc_log_type { + LOG_ERROR = 0, + LOG_WARNING, + LOG_DC, + LOG_SURFACE, + LOG_HW_HOTPLUG, + LOG_HW_LINK_TRAINING, + LOG_HW_SET_MODE, + LOG_HW_RESUME_S3, + LOG_HW_AUDIO, + LOG_HW_HPD_IRQ, + LOG_MST, + LOG_SCALER, + LOG_BIOS, + LOG_BANDWIDTH_CALCS, + LOG_BANDWIDTH_VALIDATION, + LOG_I2C_AUX, + LOG_SYNC, + LOG_BACKLIGHT, + LOG_FEATURE_OVERRIDE, + LOG_DETECTION_EDID_PARSER, + LOG_DETECTION_DP_CAPS, + LOG_RESOURCE, + LOG_DML, + LOG_EVENT_MODE_SET, + LOG_EVENT_DETECTION, + LOG_EVENT_LINK_TRAINING, + LOG_EVENT_LINK_LOSS, + LOG_EVENT_UNDERFLOW, + LOG_IF_TRACE, + + LOG_SECTION_TOTAL_COUNT +}; + +union logger_flags { + struct { + uint32_t ENABLE_CONSOLE:1; /* Print to console */ + uint32_t ENABLE_BUFFER:1; /* Print to buffer */ + uint32_t RESERVED:30; + } bits; + uint32_t value; +}; + +struct log_entry { + struct dal_logger *logger; + enum dc_log_type type; + + char *buf; + uint32_t buf_offset; + uint32_t max_buf_bytes; +}; + +/** +* Structure for enumerating log types +*/ +struct dc_log_type_info { + enum dc_log_type type; + char name[MAX_NAME_LEN]; +}; + +#endif /* __DAL_LOGGER_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/set_mode_types.h b/drivers/gpu/drm/amd/display/include/set_mode_types.h new file mode 100644 index 000000000000..d18210ff5b7a --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/set_mode_types.h @@ -0,0 +1,127 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_SET_MODE_TYPES_H__ +#define __DAL_SET_MODE_TYPES_H__ + +#include "dc_types.h" + +/* Info frame packet status */ +enum info_frame_flag { + INFO_PACKET_PACKET_INVALID = 0, + INFO_PACKET_PACKET_VALID = 1, + INFO_PACKET_PACKET_RESET = 2, + INFO_PACKET_PACKET_UPDATE_SCAN_TYPE = 8 +}; + +/* Info frame types */ +enum info_frame_type { + INFO_FRAME_GAMUT = 0x0A, + INFO_FRAME_VENDOR_INFO = 0x81, + INFO_FRAME_AVI = 0x82 +}; + +/* Info frame versions */ +enum info_frame_version { + INFO_FRAME_VERSION_1 = 1, + INFO_FRAME_VERSION_2 = 2, + INFO_FRAME_VERSION_3 = 3 +}; + +/* Info frame size */ +enum info_frame_size { + INFO_FRAME_SIZE_AVI = 13, + INFO_FRAME_SIZE_VENDOR = 25, + INFO_FRAME_SIZE_AUDIO = 10 +}; + +struct hdmi_info_frame_header { + uint8_t info_frame_type; + uint8_t version; + uint8_t length; +}; + +#pragma pack(push) +#pragma pack(1) + +struct info_packet_raw_data { + uint8_t hb0; + uint8_t hb1; + uint8_t hb2; + uint8_t sb[28]; /* sb0~sb27 */ +}; + +union hdmi_info_packet { + struct avi_info_frame { + struct hdmi_info_frame_header header; + + uint8_t CHECK_SUM:8; + + uint8_t S0_S1:2; + uint8_t B0_B1:2; + uint8_t A0:1; + uint8_t Y0_Y1_Y2:3; + + uint8_t R0_R3:4; + uint8_t M0_M1:2; + uint8_t C0_C1:2; + + uint8_t SC0_SC1:2; + uint8_t Q0_Q1:2; + uint8_t EC0_EC2:3; + uint8_t ITC:1; + + uint8_t VIC0_VIC7:8; + + uint8_t PR0_PR3:4; + uint8_t CN0_CN1:2; + uint8_t YQ0_YQ1:2; + + uint16_t bar_top; + uint16_t bar_bottom; + uint16_t bar_left; + uint16_t bar_right; + + uint8_t reserved[14]; + } bits; + + struct info_packet_raw_data packet_raw_data; +}; + +struct info_packet { + enum info_frame_flag flags; + union hdmi_info_packet info_packet_hdmi; +}; + +struct info_frame { + struct info_packet avi_info_packet; + struct info_packet gamut_packet; + struct info_packet vendor_info_packet; + struct info_packet spd_info_packet; +}; + +#pragma pack(pop) + +#endif /* __DAL_SET_MODE_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h new file mode 100644 index 000000000000..a50f7ed74a33 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -0,0 +1,59 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_SIGNAL_TYPES_H__ +#define __DC_SIGNAL_TYPES_H__ + +enum signal_type { + SIGNAL_TYPE_NONE = 0L, /* no signal */ + SIGNAL_TYPE_DVI_SINGLE_LINK = (1 << 0), + SIGNAL_TYPE_DVI_DUAL_LINK = (1 << 1), + SIGNAL_TYPE_HDMI_TYPE_A = (1 << 2), + SIGNAL_TYPE_LVDS = (1 << 3), + SIGNAL_TYPE_RGB = (1 << 4), + SIGNAL_TYPE_DISPLAY_PORT = (1 << 5), + SIGNAL_TYPE_DISPLAY_PORT_MST = (1 << 6), + SIGNAL_TYPE_EDP = (1 << 7), + SIGNAL_TYPE_WIRELESS = (1 << 8), /* Wireless Display */ + SIGNAL_TYPE_VIRTUAL = (1 << 9), /* Virtual Display */ + + SIGNAL_TYPE_COUNT = 10, + SIGNAL_TYPE_ALL = (1 << SIGNAL_TYPE_COUNT) - 1 +}; + +/* help functions for signal types manipulation */ +bool dc_is_hdmi_signal(enum signal_type signal); +bool dc_is_dp_sst_signal(enum signal_type signal); +bool dc_is_dp_signal(enum signal_type signal); +bool dc_is_dp_external_signal(enum signal_type signal); +bool dc_is_analog_signal(enum signal_type signal); +bool dc_is_embedded_signal(enum signal_type signal); +bool dc_is_dvi_signal(enum signal_type signal); +bool dc_is_dvi_single_link_signal(enum signal_type signal); +bool dc_is_dual_link_signal(enum signal_type signal); +bool dc_is_audio_capable_signal(enum signal_type signal); +bool dc_is_digital_encoder_compatible_signal(enum signal_type signal); + +#endif diff --git a/drivers/gpu/drm/amd/display/include/vector.h b/drivers/gpu/drm/amd/display/include/vector.h new file mode 100644 index 000000000000..8233b7c22a07 --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/vector.h @@ -0,0 +1,150 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_VECTOR_H__ +#define __DAL_VECTOR_H__ + +struct vector { + uint8_t *container; + uint32_t struct_size; + uint32_t count; + uint32_t capacity; + struct dc_context *ctx; +}; + +bool dal_vector_construct( + struct vector *vector, + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size); + +struct vector *dal_vector_create( + struct dc_context *ctx, + uint32_t capacity, + uint32_t struct_size); + +/* 'initial_value' is optional. If initial_value not supplied, + * each "structure" in the vector will contain zeros by default. */ +struct vector *dal_vector_presized_create( + struct dc_context *ctx, + uint32_t size, + void *initial_value, + uint32_t struct_size); + +void dal_vector_destruct( + struct vector *vector); + +void dal_vector_destroy( + struct vector **vector); + +uint32_t dal_vector_get_count( + const struct vector *vector); + +/* dal_vector_insert_at + * reallocate container if necessary + * then shell items at right and insert + * return if the container modified + * do not check that index belongs to container + * since the function is private and index is going to be calculated + * either with by function or as get_count+1 */ +bool dal_vector_insert_at( + struct vector *vector, + const void *what, + uint32_t position); + +bool dal_vector_append( + struct vector *vector, + const void *item); + +/* operator[] */ +void *dal_vector_at_index( + const struct vector *vector, + uint32_t index); + +void dal_vector_set_at_index( + const struct vector *vector, + const void *what, + uint32_t index); + +/* create a clone (copy) of a vector */ +struct vector *dal_vector_clone( + const struct vector *vector_other); + +/* dal_vector_remove_at_index + * Shifts elements on the right from remove position to the left, + * removing an element at position by overwrite means*/ +bool dal_vector_remove_at_index( + struct vector *vector, + uint32_t index); + +uint32_t dal_vector_capacity(const struct vector *vector); + +bool dal_vector_reserve(struct vector *vector, uint32_t capacity); + +void dal_vector_clear(struct vector *vector); + +/*************************************************************************** + * Macro definitions of TYPE-SAFE versions of vector set/get functions. + ***************************************************************************/ + +#define DAL_VECTOR_INSERT_AT(vector_type, type_t) \ + static bool vector_type##_vector_insert_at( \ + struct vector *vector, \ + type_t what, \ + uint32_t position) \ +{ \ + return dal_vector_insert_at(vector, what, position); \ +} + +#define DAL_VECTOR_APPEND(vector_type, type_t) \ + static bool vector_type##_vector_append( \ + struct vector *vector, \ + type_t item) \ +{ \ + return dal_vector_append(vector, item); \ +} + +/* Note: "type_t" is the ONLY token accepted by "checkpatch.pl" and by + * "checkcommit" as *return type*. + * For uniformity reasons "type_t" is used for all type-safe macro + * definitions here. */ +#define DAL_VECTOR_AT_INDEX(vector_type, type_t) \ + static type_t vector_type##_vector_at_index( \ + const struct vector *vector, \ + uint32_t index) \ +{ \ + return dal_vector_at_index(vector, index); \ +} + +#define DAL_VECTOR_SET_AT_INDEX(vector_type, type_t) \ + static void vector_type##_vector_set_at_index( \ + const struct vector *vector, \ + type_t what, \ + uint32_t index) \ +{ \ + dal_vector_set_at_index(vector, what, index); \ +} + +#endif /* __DAL_VECTOR_H__ */ diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c new file mode 100644 index 000000000000..cf030b18f6a9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -0,0 +1,2094 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "mod_color.h" +#include "core_types.h" +#include "fixed31_32.h" +#include "core_dc.h" + +#define MOD_COLOR_MAX_CONCURRENT_SINKS 32 +#define DIVIDER 10000 +/* S2D13 value in [-3.00...0.9999] */ +#define S2D13_MIN (-3 * DIVIDER) +#define S2D13_MAX (3 * DIVIDER) +#define S0D13_MIN (-1 * DIVIDER) +#define S0D13_MAX (1 * DIVIDER) + +struct sink_caps { + const struct dc_sink *sink; +}; + +struct gamut_calculation_matrix { + struct fixed31_32 MTransposed[9]; + struct fixed31_32 XYZtoRGB_Custom[9]; + struct fixed31_32 XYZtoRGB_Ref[9]; + struct fixed31_32 RGBtoXYZ_Final[9]; + + struct fixed31_32 MResult[9]; + struct fixed31_32 fXYZofWhiteRef[9]; + struct fixed31_32 fXYZofRGBRef[9]; +}; + +struct gamut_src_dst_matrix { + struct fixed31_32 rgbCoeffDst[9]; + struct fixed31_32 whiteCoeffDst[3]; + struct fixed31_32 rgbCoeffSrc[9]; + struct fixed31_32 whiteCoeffSrc[3]; +}; + +struct color_state { + bool user_enable_color_temperature; + int custom_color_temperature; + struct color_space_coordinates source_gamut; + struct color_space_coordinates destination_gamut; + struct color_range contrast; + struct color_range saturation; + struct color_range brightness; + struct color_range hue; + enum dc_quantization_range preferred_quantization_range; +}; + +struct core_color { + struct mod_color public; + struct dc *dc; + int num_sinks; + struct sink_caps *caps; + struct color_state *state; +}; + +#define MOD_COLOR_TO_CORE(mod_color)\ + container_of(mod_color, struct core_color, public) + +#define COLOR_REGISTRY_NAME "color_v1" + +/*Matrix Calculation Functions*/ +/** + ***************************************************************************** + * Function: transposeMatrix + * + * @brief + * rotate the matrix 90 degrees clockwise + * rows become a columns and columns to rows + * @param [ in ] M - source matrix + * @param [ in ] Rows - num of Rows of the original matrix + * @param [ in ] Cols - num of Cols of the original matrix + * @param [ out] MTransposed - result matrix + * @return void + * + ***************************************************************************** + */ +static void transpose_matrix(const struct fixed31_32 *M, unsigned int Rows, + unsigned int Cols, struct fixed31_32 *MTransposed) +{ + unsigned int i, j; + + for (i = 0; i < Rows; i++) { + for (j = 0; j < Cols; j++) + MTransposed[(j*Rows)+i] = M[(i*Cols)+j]; + } +} + +/** + ***************************************************************************** + * Function: multiplyMatrices + * + * @brief + * multiplies produce of two matrices: M = M1[ulRows1 x ulCols1] * + * M2[ulCols1 x ulCols2]. + * + * @param [ in ] M1 - first Matrix. + * @param [ in ] M2 - second Matrix. + * @param [ in ] Rows1 - num of Rows of the first Matrix + * @param [ in ] Cols1 - num of Cols of the first Matrix/Num of Rows + * of the second Matrix + * @param [ in ] Cols2 - num of Cols of the second Matrix + * @param [out ] mResult - resulting matrix. + * @return void + * + ***************************************************************************** + */ +static void multiply_matrices(struct fixed31_32 *mResult, + const struct fixed31_32 *M1, + const struct fixed31_32 *M2, unsigned int Rows1, + unsigned int Cols1, unsigned int Cols2) +{ + unsigned int i, j, k; + + for (i = 0; i < Rows1; i++) { + for (j = 0; j < Cols2; j++) { + mResult[(i * Cols2) + j] = dal_fixed31_32_zero; + for (k = 0; k < Cols1; k++) + mResult[(i * Cols2) + j] = + dal_fixed31_32_add + (mResult[(i * Cols2) + j], + dal_fixed31_32_mul(M1[(i * Cols1) + k], + M2[(k * Cols2) + j])); + } + } +} + +/** + ***************************************************************************** + * Function: cFind3X3Det + * + * @brief + * finds determinant of given 3x3 matrix + * + * @param [ in ] m - matrix + * @return determinate whioch could not be zero + * + ***************************************************************************** + */ +static struct fixed31_32 find_3X3_det(const struct fixed31_32 *m) +{ + struct fixed31_32 det, A1, A2, A3; + + A1 = dal_fixed31_32_mul(m[0], + dal_fixed31_32_sub(dal_fixed31_32_mul(m[4], m[8]), + dal_fixed31_32_mul(m[5], m[7]))); + A2 = dal_fixed31_32_mul(m[1], + dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[8]), + dal_fixed31_32_mul(m[5], m[6]))); + A3 = dal_fixed31_32_mul(m[2], + dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[7]), + dal_fixed31_32_mul(m[4], m[6]))); + det = dal_fixed31_32_add(dal_fixed31_32_sub(A1, A2), A3); + return det; +} + + +/** + ***************************************************************************** + * Function: computeInverseMatrix_3x3 + * + * @brief + * builds inverse matrix + * + * @param [ in ] m - matrix + * @param [ out ] im - result matrix + * @return true if success + * + ***************************************************************************** + */ +static bool compute_inverse_matrix_3x3(const struct fixed31_32 *m, + struct fixed31_32 *im) +{ + struct fixed31_32 determinant = find_3X3_det(m); + + if (dal_fixed31_32_eq(determinant, dal_fixed31_32_zero) == false) { + im[0] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[4], m[8]), + dal_fixed31_32_mul(m[5], m[7])), determinant); + im[1] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[1], m[8]), + dal_fixed31_32_mul(m[2], m[7])), determinant)); + im[2] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[1], m[5]), + dal_fixed31_32_mul(m[2], m[4])), determinant); + im[3] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[3], m[8]), + dal_fixed31_32_mul(m[5], m[6])), determinant)); + im[4] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[0], m[8]), + dal_fixed31_32_mul(m[2], m[6])), determinant); + im[5] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[0], m[5]), + dal_fixed31_32_mul(m[2], m[3])), determinant)); + im[6] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[3], m[7]), + dal_fixed31_32_mul(m[4], m[6])), determinant); + im[7] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[0], m[7]), + dal_fixed31_32_mul(m[1], m[6])), determinant)); + im[8] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_mul(m[0], m[4]), + dal_fixed31_32_mul(m[1], m[3])), determinant); + return true; + } + return false; +} + +/** + ***************************************************************************** + * Function: calculateXYZtoRGB_M3x3 + * + * @brief + * Calculates transformation matrix from XYZ coordinates to RBG + * + * @param [ in ] XYZofRGB - primaries XYZ + * @param [ in ] XYZofWhite - white point. + * @param [ out ] XYZtoRGB - RGB primires + * @return true if success + * + ***************************************************************************** + */ +static bool calculate_XYZ_to_RGB_3x3(const struct fixed31_32 *XYZofRGB, + const struct fixed31_32 *XYZofWhite, + struct fixed31_32 *XYZtoRGB) +{ + + struct fixed31_32 MInversed[9]; + struct fixed31_32 SVector[3]; + + /*1. Find Inverse matrix 3x3 of MTransposed*/ + if (!compute_inverse_matrix_3x3(XYZofRGB, MInversed)) + return false; + + /*2. Calculate vector: |Sr Sg Sb| = [MInversed] * |Wx Wy Wz|*/ + multiply_matrices(SVector, MInversed, XYZofWhite, 3, 3, 1); + + /*3. Calculate matrix XYZtoRGB 3x3*/ + XYZtoRGB[0] = dal_fixed31_32_mul(XYZofRGB[0], SVector[0]); + XYZtoRGB[1] = dal_fixed31_32_mul(XYZofRGB[1], SVector[1]); + XYZtoRGB[2] = dal_fixed31_32_mul(XYZofRGB[2], SVector[2]); + + XYZtoRGB[3] = dal_fixed31_32_mul(XYZofRGB[3], SVector[0]); + XYZtoRGB[4] = dal_fixed31_32_mul(XYZofRGB[4], SVector[1]); + XYZtoRGB[5] = dal_fixed31_32_mul(XYZofRGB[5], SVector[2]); + + XYZtoRGB[6] = dal_fixed31_32_mul(XYZofRGB[6], SVector[0]); + XYZtoRGB[7] = dal_fixed31_32_mul(XYZofRGB[7], SVector[1]); + XYZtoRGB[8] = dal_fixed31_32_mul(XYZofRGB[8], SVector[2]); + + return true; +} + +static bool gamut_to_color_matrix( + const struct fixed31_32 *pXYZofRGB,/*destination gamut*/ + const struct fixed31_32 *pXYZofWhite,/*destination of white point*/ + const struct fixed31_32 *pRefXYZofRGB,/*source gamut*/ + const struct fixed31_32 *pRefXYZofWhite,/*source of white point*/ + bool invert, + struct fixed31_32 *tempMatrix3X3) +{ + int i = 0; + struct gamut_calculation_matrix *matrix = + dm_alloc(sizeof(struct gamut_calculation_matrix)); + + struct fixed31_32 *pXYZtoRGB_Temp; + struct fixed31_32 *pXYZtoRGB_Final; + + matrix->fXYZofWhiteRef[0] = pRefXYZofWhite[0]; + matrix->fXYZofWhiteRef[1] = pRefXYZofWhite[1]; + matrix->fXYZofWhiteRef[2] = pRefXYZofWhite[2]; + + + matrix->fXYZofRGBRef[0] = pRefXYZofRGB[0]; + matrix->fXYZofRGBRef[1] = pRefXYZofRGB[1]; + matrix->fXYZofRGBRef[2] = pRefXYZofRGB[2]; + + matrix->fXYZofRGBRef[3] = pRefXYZofRGB[3]; + matrix->fXYZofRGBRef[4] = pRefXYZofRGB[4]; + matrix->fXYZofRGBRef[5] = pRefXYZofRGB[5]; + + matrix->fXYZofRGBRef[6] = pRefXYZofRGB[6]; + matrix->fXYZofRGBRef[7] = pRefXYZofRGB[7]; + matrix->fXYZofRGBRef[8] = pRefXYZofRGB[8]; + + /*default values - unity matrix*/ + while (i < 9) { + if (i == 0 || i == 4 || i == 8) + tempMatrix3X3[i] = dal_fixed31_32_one; + else + tempMatrix3X3[i] = dal_fixed31_32_zero; + i++; + } + + /*1. Decide about the order of calculation. + * bInvert == FALSE --> RGBtoXYZ_Ref * XYZtoRGB_Custom + * bInvert == TRUE --> RGBtoXYZ_Custom * XYZtoRGB_Ref */ + if (invert) { + pXYZtoRGB_Temp = matrix->XYZtoRGB_Custom; + pXYZtoRGB_Final = matrix->XYZtoRGB_Ref; + } else { + pXYZtoRGB_Temp = matrix->XYZtoRGB_Ref; + pXYZtoRGB_Final = matrix->XYZtoRGB_Custom; + } + + /*2. Calculate XYZtoRGB_Ref*/ + transpose_matrix(matrix->fXYZofRGBRef, 3, 3, matrix->MTransposed); + + if (!calculate_XYZ_to_RGB_3x3( + matrix->MTransposed, + matrix->fXYZofWhiteRef, + matrix->XYZtoRGB_Ref)) + goto function_fail; + + /*3. Calculate XYZtoRGB_Custom*/ + transpose_matrix(pXYZofRGB, 3, 3, matrix->MTransposed); + + if (!calculate_XYZ_to_RGB_3x3( + matrix->MTransposed, + pXYZofWhite, + matrix->XYZtoRGB_Custom)) + goto function_fail; + + /*4. Calculate RGBtoXYZ - + * inverse matrix 3x3 of XYZtoRGB_Ref or XYZtoRGB_Custom*/ + if (!compute_inverse_matrix_3x3(pXYZtoRGB_Temp, matrix->RGBtoXYZ_Final)) + goto function_fail; + + /*5. Calculate M(3x3) = RGBtoXYZ * XYZtoRGB*/ + multiply_matrices(matrix->MResult, matrix->RGBtoXYZ_Final, + pXYZtoRGB_Final, 3, 3, 3); + + for (i = 0; i < 9; i++) + tempMatrix3X3[i] = matrix->MResult[i]; + + dm_free(matrix); + + return true; + +function_fail: + dm_free(matrix); + return false; +} + +static bool build_gamut_remap_matrix + (struct color_space_coordinates gamut_description, + struct fixed31_32 *rgb_matrix, + struct fixed31_32 *white_point_matrix) +{ + struct fixed31_32 fixed_blueX = dal_fixed31_32_from_fraction + (gamut_description.blueX, DIVIDER); + struct fixed31_32 fixed_blueY = dal_fixed31_32_from_fraction + (gamut_description.blueY, DIVIDER); + struct fixed31_32 fixed_greenX = dal_fixed31_32_from_fraction + (gamut_description.greenX, DIVIDER); + struct fixed31_32 fixed_greenY = dal_fixed31_32_from_fraction + (gamut_description.greenY, DIVIDER); + struct fixed31_32 fixed_redX = dal_fixed31_32_from_fraction + (gamut_description.redX, DIVIDER); + struct fixed31_32 fixed_redY = dal_fixed31_32_from_fraction + (gamut_description.redY, DIVIDER); + struct fixed31_32 fixed_whiteX = dal_fixed31_32_from_fraction + (gamut_description.whiteX, DIVIDER); + struct fixed31_32 fixed_whiteY = dal_fixed31_32_from_fraction + (gamut_description.whiteY, DIVIDER); + + rgb_matrix[0] = dal_fixed31_32_div(fixed_redX, fixed_redY); + rgb_matrix[1] = dal_fixed31_32_one; + rgb_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_redX), + fixed_redY), fixed_redY); + + rgb_matrix[3] = dal_fixed31_32_div(fixed_greenX, fixed_greenY); + rgb_matrix[4] = dal_fixed31_32_one; + rgb_matrix[5] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_greenX), + fixed_greenY), fixed_greenY); + + rgb_matrix[6] = dal_fixed31_32_div(fixed_blueX, fixed_blueY); + rgb_matrix[7] = dal_fixed31_32_one; + rgb_matrix[8] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_blueX), + fixed_blueY), fixed_blueY); + + white_point_matrix[0] = dal_fixed31_32_div(fixed_whiteX, fixed_whiteY); + white_point_matrix[1] = dal_fixed31_32_one; + white_point_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub + (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_whiteX), + fixed_whiteY), fixed_whiteY); + + return true; +} + +static bool check_dc_support(const struct dc *dc) +{ + if (dc->stream_funcs.set_gamut_remap == NULL) + return false; + + return true; +} + +static uint16_t fixed_point_to_int_frac( + struct fixed31_32 arg, + uint8_t integer_bits, + uint8_t fractional_bits) +{ + int32_t numerator; + int32_t divisor = 1 << fractional_bits; + + uint16_t result; + + uint16_t d = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_abs( + arg)); + + if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) + numerator = (uint16_t)dal_fixed31_32_floor( + dal_fixed31_32_mul_int( + arg, + divisor)); + else { + numerator = dal_fixed31_32_floor( + dal_fixed31_32_sub( + dal_fixed31_32_from_int( + 1LL << integer_bits), + dal_fixed31_32_recip( + dal_fixed31_32_from_int( + divisor)))); + } + + if (numerator >= 0) + result = (uint16_t)numerator; + else + result = (uint16_t)( + (1 << (integer_bits + fractional_bits + 1)) + numerator); + + if ((result != 0) && dal_fixed31_32_lt( + arg, dal_fixed31_32_zero)) + result |= 1 << (integer_bits + fractional_bits); + + return result; +} + +/** +* convert_float_matrix +* This converts a double into HW register spec defined format S2D13. +* @param : +* @return None +*/ + +static void convert_float_matrix_legacy( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size) +{ + const struct fixed31_32 min_2_13 = + dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); + const struct fixed31_32 max_2_13 = + dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); + uint32_t i; + + for (i = 0; i < buffer_size; ++i) { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_2_13, + max_2_13), + 2, + 13); + + matrix[i] = (uint16_t)reg_value; + } +} + +static void convert_float_matrix( + uint16_t *matrix, + struct fixed31_32 *flt, + uint32_t buffer_size) +{ + const struct fixed31_32 min_0_13 = + dal_fixed31_32_from_fraction(S0D13_MIN, DIVIDER); + const struct fixed31_32 max_0_13 = + dal_fixed31_32_from_fraction(S0D13_MAX, DIVIDER); + const struct fixed31_32 min_2_13 = + dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); + const struct fixed31_32 max_2_13 = + dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); + uint32_t i; + uint16_t temp_matrix[12]; + + for (i = 0; i < buffer_size; ++i) { + if (i == 3 || i == 7 || i == 11) { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_0_13, + max_0_13), + 2, + 13); + + temp_matrix[i] = (uint16_t)reg_value; + } else { + uint32_t reg_value = + fixed_point_to_int_frac( + dal_fixed31_32_clamp( + flt[i], + min_2_13, + max_2_13), + 2, + 13); + + temp_matrix[i] = (uint16_t)reg_value; + } + } + + matrix[4] = temp_matrix[0]; + matrix[5] = temp_matrix[1]; + matrix[6] = temp_matrix[2]; + matrix[7] = temp_matrix[3]; + + matrix[8] = temp_matrix[4]; + matrix[9] = temp_matrix[5]; + matrix[10] = temp_matrix[6]; + matrix[11] = temp_matrix[7]; + + matrix[0] = temp_matrix[8]; + matrix[1] = temp_matrix[9]; + matrix[2] = temp_matrix[10]; + matrix[3] = temp_matrix[11]; +} + +static int get_hw_value_from_sw_value(int swVal, int swMin, + int swMax, int hwMin, int hwMax) +{ + int dSW = swMax - swMin; /*software adjustment range size*/ + int dHW = hwMax - hwMin; /*hardware adjustment range size*/ + int hwVal; /*HW adjustment value*/ + + /* error case, I preserve the behavior from the predecessor + *getHwStepFromSwHwMinMaxValue (removed in Feb 2013) + *which was the FP version that only computed SCLF (i.e. dHW/dSW). + *it would return 0 in this case so + *hwVal = hwMin from the formula given in @brief + */ + if (dSW == 0) + return hwMin; + + /*it's quite often that ranges match, + *e.g. for overlay colors currently (Feb 2013) + *only brightness has a different + *HW range, and in this case no multiplication or division is needed, + *and if minimums match, no calculation at all + */ + if (dSW != dHW) { + hwVal = (swVal - swMin)*dHW/dSW + hwMin; + } else { + hwVal = swVal; + if (swMin != hwMin) + hwVal += (hwMin - swMin); + } + + return hwVal; +} + +static void initialize_fix_point_color_values( + struct core_color *core_color, + unsigned int sink_index, + struct fixed31_32 *grph_cont, + struct fixed31_32 *grph_sat, + struct fixed31_32 *grph_bright, + struct fixed31_32 *sin_grph_hue, + struct fixed31_32 *cos_grph_hue) +{ + /* Hue adjustment could be negative. -45 ~ +45 */ + struct fixed31_32 hue = + dal_fixed31_32_mul( + dal_fixed31_32_from_fraction + (get_hw_value_from_sw_value + (core_color->state[sink_index].hue.current, + core_color->state[sink_index].hue.min, + core_color->state[sink_index].hue.max, + -30, 30), 180), + dal_fixed31_32_pi); + + *sin_grph_hue = dal_fixed31_32_sin(hue); + *cos_grph_hue = dal_fixed31_32_cos(hue); + + *grph_cont = + dal_fixed31_32_from_fraction(get_hw_value_from_sw_value + (core_color->state[sink_index].contrast.current, + core_color->state[sink_index].contrast.min, + core_color->state[sink_index].contrast.max, + 50, 150), 100); + *grph_sat = + dal_fixed31_32_from_fraction(get_hw_value_from_sw_value + (core_color->state[sink_index].saturation.current, + core_color->state[sink_index].saturation.min, + core_color->state[sink_index].saturation.max, + 0, 200), 100); + *grph_bright = + dal_fixed31_32_from_fraction(get_hw_value_from_sw_value + (core_color->state[sink_index].brightness.current, + core_color->state[sink_index].brightness.min, + core_color->state[sink_index].brightness.max, + -25, 25), 100); +} + + +/* Given a specific dc_sink* this function finds its equivalent + * on the dc_sink array and returns the corresponding index + */ +static unsigned int sink_index_from_sink(struct core_color *core_color, + const struct dc_sink *sink) +{ + unsigned int index = 0; + + for (index = 0; index < core_color->num_sinks; index++) + if (core_color->caps[index].sink == sink) + return index; + + /* Could not find sink requested */ + ASSERT(false); + return index; +} + +static void calculate_rgb_matrix_legacy(struct core_color *core_color, + unsigned int sink_index, + struct fixed31_32 *rgb_matrix) +{ + const struct fixed31_32 k1 = + dal_fixed31_32_from_fraction(701000, 1000000); + const struct fixed31_32 k2 = + dal_fixed31_32_from_fraction(236568, 1000000); + const struct fixed31_32 k3 = + dal_fixed31_32_from_fraction(-587000, 1000000); + const struct fixed31_32 k4 = + dal_fixed31_32_from_fraction(464432, 1000000); + const struct fixed31_32 k5 = + dal_fixed31_32_from_fraction(-114000, 1000000); + const struct fixed31_32 k6 = + dal_fixed31_32_from_fraction(-701000, 1000000); + const struct fixed31_32 k7 = + dal_fixed31_32_from_fraction(-299000, 1000000); + const struct fixed31_32 k8 = + dal_fixed31_32_from_fraction(-292569, 1000000); + const struct fixed31_32 k9 = + dal_fixed31_32_from_fraction(413000, 1000000); + const struct fixed31_32 k10 = + dal_fixed31_32_from_fraction(-92482, 1000000); + const struct fixed31_32 k11 = + dal_fixed31_32_from_fraction(-114000, 1000000); + const struct fixed31_32 k12 = + dal_fixed31_32_from_fraction(385051, 1000000); + const struct fixed31_32 k13 = + dal_fixed31_32_from_fraction(-299000, 1000000); + const struct fixed31_32 k14 = + dal_fixed31_32_from_fraction(886000, 1000000); + const struct fixed31_32 k15 = + dal_fixed31_32_from_fraction(-587000, 1000000); + const struct fixed31_32 k16 = + dal_fixed31_32_from_fraction(-741914, 1000000); + const struct fixed31_32 k17 = + dal_fixed31_32_from_fraction(886000, 1000000); + const struct fixed31_32 k18 = + dal_fixed31_32_from_fraction(-144086, 1000000); + + const struct fixed31_32 luma_r = + dal_fixed31_32_from_fraction(299, 1000); + const struct fixed31_32 luma_g = + dal_fixed31_32_from_fraction(587, 1000); + const struct fixed31_32 luma_b = + dal_fixed31_32_from_fraction(114, 1000); + + struct fixed31_32 grph_cont; + struct fixed31_32 grph_sat; + struct fixed31_32 grph_bright; + struct fixed31_32 sin_grph_hue; + struct fixed31_32 cos_grph_hue; + + initialize_fix_point_color_values( + core_color, sink_index, &grph_cont, &grph_sat, + &grph_bright, &sin_grph_hue, &cos_grph_hue); + + /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +*/ + /* Sin(GrphHue) * K2))*/ + /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)*/ + rgb_matrix[0] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k1), + dal_fixed31_32_mul(sin_grph_hue, k2)); + /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ + rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/ + rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/ + /* K2))*/ + rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]); + + /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/ + /* Sin(GrphHue) * K4))*/ + /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ + rgb_matrix[1] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k3), + dal_fixed31_32_mul(sin_grph_hue, k4)); + /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ + rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/ + rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/ + /* K4))*/ + rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]); + + /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/ + /* Sin(GrphHue) * K6))*/ + /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k5), + dal_fixed31_32_mul(sin_grph_hue, k6)); + /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]); + /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/ + /* K6))*/ + rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]); + + /* COEF_1_4 = GrphBright*/ + rgb_matrix[3] = grph_bright; + + /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/ + /* Sin(GrphHue) * K8))*/ + /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ + rgb_matrix[4] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k7), + dal_fixed31_32_mul(sin_grph_hue, k8)); + /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ + rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/ + rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/ + /* K8))*/ + rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]); + + /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/ + /* Sin(GrphHue) * K10))*/ + /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k9), + dal_fixed31_32_mul(sin_grph_hue, k10)); + /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/ + /* K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]); + + /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/ + /* Sin(GrphHue) * K12))*/ + /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k11), + dal_fixed31_32_mul(sin_grph_hue, k12)); + /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]); + /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/ + /* K12))*/ + rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]); + + /* COEF_2_4 = GrphBright*/ + rgb_matrix[7] = grph_bright; + + /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ + /* Sin(GrphHue) * K14))*/ + /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k13), + dal_fixed31_32_mul(sin_grph_hue, k14)); + /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/ + /* K14)) */ + rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]); + + /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/ + /* Sin(GrphHue) * K16)) */ + /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ + rgb_matrix[9] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k15), + dal_fixed31_32_mul(sin_grph_hue, k16)); + /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ + rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ + rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/ + /* K16)) */ + rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]); + + /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/ + /* Sin(GrphHue) * K18)) */ + /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k17), + dal_fixed31_32_mul(sin_grph_hue, k18)); + /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]); + /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/ + /* K18)) */ + rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]); + + /* COEF_3_4 = GrphBright */ + rgb_matrix[11] = grph_bright; +} + +static void calculate_rgb_limited_range_matrix(struct core_color *core_color, + unsigned int sink_index, struct fixed31_32 *rgb_matrix) +{ + struct fixed31_32 ideal[12]; + + static const int32_t matrix_[] = { + 85546875, 0, 0, 6250000, + 0, 85546875, 0, 6250000, + 0, 0, 85546875, 6250000 + }; + + uint32_t i = 0; + + do { + ideal[i] = dal_fixed31_32_from_fraction( + matrix_[i], + 100000000); + ++i; + } while (i != ARRAY_SIZE(matrix_)); + + + struct fixed31_32 grph_cont; + struct fixed31_32 grph_sat; + struct fixed31_32 grph_bright; + struct fixed31_32 sin_grph_hue; + struct fixed31_32 cos_grph_hue; + + initialize_fix_point_color_values( + core_color, sink_index, &grph_cont, &grph_sat, + &grph_bright, &sin_grph_hue, &cos_grph_hue); + + const struct fixed31_32 multiplier = + dal_fixed31_32_mul(grph_cont, grph_sat); + + rgb_matrix[8] = dal_fixed31_32_mul(ideal[0], grph_cont); + + rgb_matrix[9] = dal_fixed31_32_mul(ideal[1], grph_cont); + + rgb_matrix[10] = dal_fixed31_32_mul(ideal[2], grph_cont); + + rgb_matrix[11] = dal_fixed31_32_add( + ideal[3], + dal_fixed31_32_mul( + grph_bright, + dal_fixed31_32_from_fraction(86, 100))); + + rgb_matrix[0] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[8], + sin_grph_hue), + dal_fixed31_32_mul( + ideal[4], + cos_grph_hue))); + + rgb_matrix[1] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[9], + sin_grph_hue), + dal_fixed31_32_mul( + ideal[5], + cos_grph_hue))); + + rgb_matrix[2] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[10], + sin_grph_hue), + dal_fixed31_32_mul( + ideal[6], + cos_grph_hue))); + + rgb_matrix[3] = ideal[7]; + + rgb_matrix[4] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[8], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[4], + sin_grph_hue))); + + rgb_matrix[5] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[9], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[5], + sin_grph_hue))); + + rgb_matrix[6] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[10], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[6], + sin_grph_hue))); + + rgb_matrix[7] = ideal[11]; +} + +static void calculate_yuv_matrix(struct core_color *core_color, + unsigned int sink_index, + enum dc_color_space color_space, + struct fixed31_32 *yuv_matrix) +{ + struct fixed31_32 ideal[12]; + uint32_t i = 0; + + if ((color_space == COLOR_SPACE_YPBPR601) || + (color_space == COLOR_SPACE_YCBCR601) || + (color_space == COLOR_SPACE_YCBCR601_LIMITED)) { + static const int32_t matrix_[] = { + 25578516, 50216016, 9752344, 6250000, + -14764391, -28985609, 43750000, 50000000, + 43750000, -36635164, -7114836, 50000000 + }; + do { + ideal[i] = dal_fixed31_32_from_fraction( + matrix_[i], + 100000000); + ++i; + } while (i != ARRAY_SIZE(matrix_)); + } else { + static const int32_t matrix_[] = { + 18187266, 61183125, 6176484, 6250000, + -10025059, -33724941, 43750000, 50000000, + 43750000, -39738379, -4011621, 50000000 + }; + do { + ideal[i] = dal_fixed31_32_from_fraction( + matrix_[i], + 100000000); + ++i; + } while (i != ARRAY_SIZE(matrix_)); + } + + struct fixed31_32 grph_cont; + struct fixed31_32 grph_sat; + struct fixed31_32 grph_bright; + struct fixed31_32 sin_grph_hue; + struct fixed31_32 cos_grph_hue; + + initialize_fix_point_color_values( + core_color, sink_index, &grph_cont, &grph_sat, + &grph_bright, &sin_grph_hue, &cos_grph_hue); + + const struct fixed31_32 multiplier = + dal_fixed31_32_mul(grph_cont, grph_sat); + + yuv_matrix[0] = dal_fixed31_32_mul(ideal[0], grph_cont); + + yuv_matrix[1] = dal_fixed31_32_mul(ideal[1], grph_cont); + + yuv_matrix[2] = dal_fixed31_32_mul(ideal[2], grph_cont); + + yuv_matrix[4] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[4], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[8], + sin_grph_hue))); + + yuv_matrix[5] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[5], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[9], + sin_grph_hue))); + + yuv_matrix[6] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_add( + dal_fixed31_32_mul( + ideal[6], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[10], + sin_grph_hue))); + + yuv_matrix[7] = ideal[7]; + + yuv_matrix[8] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[8], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[4], + sin_grph_hue))); + + yuv_matrix[9] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[9], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[5], + sin_grph_hue))); + + yuv_matrix[10] = dal_fixed31_32_mul( + multiplier, + dal_fixed31_32_sub( + dal_fixed31_32_mul( + ideal[10], + cos_grph_hue), + dal_fixed31_32_mul( + ideal[6], + sin_grph_hue))); + + yuv_matrix[11] = ideal[11]; + + if ((color_space == COLOR_SPACE_YCBCR601_LIMITED) || + (color_space == COLOR_SPACE_YCBCR709_LIMITED)) { + yuv_matrix[3] = dal_fixed31_32_add(ideal[3], grph_bright); + } else { + yuv_matrix[3] = dal_fixed31_32_add( + ideal[3], + dal_fixed31_32_mul( + grph_bright, + dal_fixed31_32_from_fraction(86, 100))); + } +} + +static void calculate_csc_matrix(struct core_color *core_color, + unsigned int sink_index, + enum dc_color_space color_space, + uint16_t *csc_matrix) +{ + struct fixed31_32 fixed_csc_matrix[12]; + switch (color_space) { + case COLOR_SPACE_SRGB: + calculate_rgb_matrix_legacy + (core_color, sink_index, fixed_csc_matrix); + convert_float_matrix_legacy + (csc_matrix, fixed_csc_matrix, 12); + break; + case COLOR_SPACE_SRGB_LIMITED: + calculate_rgb_limited_range_matrix(core_color, sink_index, + fixed_csc_matrix); + convert_float_matrix(csc_matrix, fixed_csc_matrix, 12); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YPBPR709: + calculate_yuv_matrix(core_color, sink_index, color_space, + fixed_csc_matrix); + convert_float_matrix(csc_matrix, fixed_csc_matrix, 12); + break; + default: + calculate_rgb_matrix_legacy + (core_color, sink_index, fixed_csc_matrix); + convert_float_matrix_legacy + (csc_matrix, fixed_csc_matrix, 12); + break; + } +} + +struct mod_color *mod_color_create(struct dc *dc) +{ + int i = 0; + struct core_color *core_color = + dm_alloc(sizeof(struct core_color)); + struct core_dc *core_dc = DC_TO_CORE(dc); + struct persistent_data_flag flag; + + if (core_color == NULL) + goto fail_alloc_context; + + core_color->caps = dm_alloc(sizeof(struct sink_caps) * + MOD_COLOR_MAX_CONCURRENT_SINKS); + + if (core_color->caps == NULL) + goto fail_alloc_caps; + + for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) + core_color->caps[i].sink = NULL; + + core_color->state = dm_alloc(sizeof(struct color_state) * + MOD_COLOR_MAX_CONCURRENT_SINKS); + + /*hardcoded to sRGB with 6500 color temperature*/ + for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { + core_color->state[i].source_gamut.blueX = 1500; + core_color->state[i].source_gamut.blueY = 600; + core_color->state[i].source_gamut.greenX = 3000; + core_color->state[i].source_gamut.greenY = 6000; + core_color->state[i].source_gamut.redX = 6400; + core_color->state[i].source_gamut.redY = 3300; + core_color->state[i].source_gamut.whiteX = 3127; + core_color->state[i].source_gamut.whiteY = 3290; + + core_color->state[i].destination_gamut.blueX = 1500; + core_color->state[i].destination_gamut.blueY = 600; + core_color->state[i].destination_gamut.greenX = 3000; + core_color->state[i].destination_gamut.greenY = 6000; + core_color->state[i].destination_gamut.redX = 6400; + core_color->state[i].destination_gamut.redY = 3300; + core_color->state[i].destination_gamut.whiteX = 3127; + core_color->state[i].destination_gamut.whiteY = 3290; + + core_color->state[i].custom_color_temperature = 6500; + + core_color->state[i].contrast.current = 100; + core_color->state[i].contrast.min = 0; + core_color->state[i].contrast.max = 200; + + core_color->state[i].saturation.current = 100; + core_color->state[i].saturation.min = 0; + core_color->state[i].saturation.max = 200; + + core_color->state[i].brightness.current = 0; + core_color->state[i].brightness.min = -100; + core_color->state[i].brightness.max = 100; + + core_color->state[i].hue.current = 0; + core_color->state[i].hue.min = -30; + core_color->state[i].hue.max = 30; + } + + if (core_color->state == NULL) + goto fail_alloc_state; + + core_color->num_sinks = 0; + + if (dc == NULL) + goto fail_construct; + + core_color->dc = dc; + + if (!check_dc_support(dc)) + goto fail_construct; + + /* Create initial module folder in registry for color adjustment */ + flag.save_per_edid = true; + flag.save_per_link = false; + + dm_write_persistent_data(core_dc->ctx, NULL, COLOR_REGISTRY_NAME, NULL, + NULL, 0, &flag); + + return &core_color->public; + +fail_construct: + dm_free(core_color->state); + +fail_alloc_state: + dm_free(core_color->caps); + +fail_alloc_caps: + dm_free(core_color); + +fail_alloc_context: + return NULL; +} + +void mod_color_destroy(struct mod_color *mod_color) +{ + if (mod_color != NULL) { + int i; + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + dm_free(core_color->state); + + for (i = 0; i < core_color->num_sinks; i++) + dc_sink_release(core_color->caps[i].sink); + + dm_free(core_color->caps); + + dm_free(core_color); + } +} + +bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + bool persistent_color_temp_enable; + int persistent_custom_color_temp = 0; + struct color_space_coordinates persistent_source_gamut; + struct color_space_coordinates persistent_destination_gamut; + int persistent_brightness; + int persistent_contrast; + int persistent_hue; + int persistent_saturation; + enum dc_quantization_range persistent_quantization_range; + struct persistent_data_flag flag; + + if (core_color->num_sinks < MOD_COLOR_MAX_CONCURRENT_SINKS) { + dc_sink_retain(sink); + core_color->caps[core_color->num_sinks].sink = sink; + core_color->state[core_color->num_sinks]. + user_enable_color_temperature = true; + + /* get persistent data from registry */ + flag.save_per_edid = true; + flag.save_per_link = false; + + + if (dm_read_persistent_data(core_dc->ctx, sink, + COLOR_REGISTRY_NAME, + "enablecolortempadj", + &persistent_color_temp_enable, + sizeof(bool), &flag)) + core_color->state[core_color->num_sinks]. + user_enable_color_temperature = + persistent_color_temp_enable; + else + core_color->state[core_color->num_sinks]. + user_enable_color_temperature = true; + + if (dm_read_persistent_data(core_dc->ctx, sink, + COLOR_REGISTRY_NAME, + "customcolortemp", + &persistent_custom_color_temp, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + custom_color_temperature + = persistent_custom_color_temp; + else + core_color->state[core_color->num_sinks]. + custom_color_temperature = 6500; + + if (dm_read_persistent_data(core_dc->ctx, sink, + COLOR_REGISTRY_NAME, + "sourcegamut", + &persistent_source_gamut, + sizeof(struct color_space_coordinates), + &flag)) { + memcpy(&core_color->state[core_color->num_sinks]. + source_gamut, &persistent_source_gamut, + sizeof(struct color_space_coordinates)); + } else { + core_color->state[core_color->num_sinks]. + source_gamut.blueX = 1500; + core_color->state[core_color->num_sinks]. + source_gamut.blueY = 600; + core_color->state[core_color->num_sinks]. + source_gamut.greenX = 3000; + core_color->state[core_color->num_sinks]. + source_gamut.greenY = 6000; + core_color->state[core_color->num_sinks]. + source_gamut.redX = 6400; + core_color->state[core_color->num_sinks]. + source_gamut.redY = 3300; + core_color->state[core_color->num_sinks]. + source_gamut.whiteX = 3127; + core_color->state[core_color->num_sinks]. + source_gamut.whiteY = 3290; + } + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "destgamut", + &persistent_destination_gamut, + sizeof(struct color_space_coordinates), + &flag)) { + memcpy(&core_color->state[core_color->num_sinks]. + destination_gamut, + &persistent_destination_gamut, + sizeof(struct color_space_coordinates)); + } else { + core_color->state[core_color->num_sinks]. + destination_gamut.blueX = 1500; + core_color->state[core_color->num_sinks]. + destination_gamut.blueY = 600; + core_color->state[core_color->num_sinks]. + destination_gamut.greenX = 3000; + core_color->state[core_color->num_sinks]. + destination_gamut.greenY = 6000; + core_color->state[core_color->num_sinks]. + destination_gamut.redX = 6400; + core_color->state[core_color->num_sinks]. + destination_gamut.redY = 3300; + core_color->state[core_color->num_sinks]. + destination_gamut.whiteX = 3127; + core_color->state[core_color->num_sinks]. + destination_gamut.whiteY = 3290; + } + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "brightness", + &persistent_brightness, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + brightness.current = persistent_brightness; + else + core_color->state[core_color->num_sinks]. + brightness.current = 0; + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "contrast", + &persistent_contrast, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + contrast.current = persistent_contrast; + else + core_color->state[core_color->num_sinks]. + contrast.current = 100; + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "hue", + &persistent_hue, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + hue.current = persistent_hue; + else + core_color->state[core_color->num_sinks]. + hue.current = 0; + + if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, + "saturation", + &persistent_saturation, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + saturation.current = persistent_saturation; + else + core_color->state[core_color->num_sinks]. + saturation.current = 100; + + if (dm_read_persistent_data(core_dc->ctx, sink, + COLOR_REGISTRY_NAME, + "preferred_quantization_range", + &persistent_quantization_range, + sizeof(int), &flag)) + core_color->state[core_color->num_sinks]. + preferred_quantization_range = + persistent_quantization_range; + else + core_color->state[core_color->num_sinks]. + preferred_quantization_range = QUANTIZATION_RANGE_FULL; + + core_color->num_sinks++; + return true; + } + return false; +} + +bool mod_color_remove_sink(struct mod_color *mod_color, + const struct dc_sink *sink) +{ + int i = 0, j = 0; + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + for (i = 0; i < core_color->num_sinks; i++) { + if (core_color->caps[i].sink == sink) { + /* To remove this sink, shift everything after down */ + for (j = i; j < core_color->num_sinks - 1; j++) { + core_color->caps[j].sink = + core_color->caps[j + 1].sink; + + memcpy(&core_color->state[j], + &core_color->state[j + 1], + sizeof(struct color_state)); + } + + core_color->num_sinks--; + + dc_sink_release(sink); + + return true; + } + } + + return false; +} + +bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + struct gamut_src_dst_matrix *matrix = + dm_alloc(sizeof(struct gamut_src_dst_matrix)); + + unsigned int stream_index, sink_index, j; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "sourcegamut", + &core_color->state[sink_index]. + source_gamut, + sizeof(struct color_space_coordinates), + &flag); + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "destgamut", + &core_color->state[sink_index]. + destination_gamut, + sizeof(struct color_space_coordinates), + &flag); + + if (!build_gamut_remap_matrix + (core_color->state[sink_index].source_gamut, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc)) + goto function_fail; + + if (!build_gamut_remap_matrix + (core_color->state[sink_index]. + destination_gamut, + matrix->rgbCoeffDst, matrix->whiteCoeffDst)) + goto function_fail; + + struct fixed31_32 gamut_result[12]; + struct fixed31_32 temp_matrix[9]; + + if (!gamut_to_color_matrix( + matrix->rgbCoeffDst, + matrix->whiteCoeffDst, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc, + true, + temp_matrix)) + goto function_fail; + + gamut_result[0] = temp_matrix[0]; + gamut_result[1] = temp_matrix[1]; + gamut_result[2] = temp_matrix[2]; + gamut_result[3] = matrix->whiteCoeffSrc[0]; + gamut_result[4] = temp_matrix[3]; + gamut_result[5] = temp_matrix[4]; + gamut_result[6] = temp_matrix[5]; + gamut_result[7] = matrix->whiteCoeffSrc[1]; + gamut_result[8] = temp_matrix[6]; + gamut_result[9] = temp_matrix[7]; + gamut_result[10] = temp_matrix[8]; + gamut_result[11] = matrix->whiteCoeffSrc[2]; + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_stream->public.gamut_remap_matrix.enable_remap = true; + + for (j = 0; j < 12; j++) + core_stream->public. + gamut_remap_matrix.matrix[j] = + gamut_result[j]; + } + + dm_free(matrix); + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; + +function_fail: + dm_free(matrix); + return false; +} + +bool mod_color_adjust_source_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct gamut_space_coordinates *input_gamut_coordinates, + struct white_point_coodinates *input_white_point_coordinates) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + core_color->state[sink_index].source_gamut.blueX = + input_gamut_coordinates->blueX; + core_color->state[sink_index].source_gamut.blueY = + input_gamut_coordinates->blueY; + core_color->state[sink_index].source_gamut.greenX = + input_gamut_coordinates->greenX; + core_color->state[sink_index].source_gamut.greenY = + input_gamut_coordinates->greenY; + core_color->state[sink_index].source_gamut.redX = + input_gamut_coordinates->redX; + core_color->state[sink_index].source_gamut.redY = + input_gamut_coordinates->redY; + core_color->state[sink_index].source_gamut.whiteX = + input_white_point_coordinates->whiteX; + core_color->state[sink_index].source_gamut.whiteY = + input_white_point_coordinates->whiteY; + } + + if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) + return false; + + return true; +} + +bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct gamut_space_coordinates *input_gamut_coordinates, + struct white_point_coodinates *input_white_point_coordinates) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + core_color->state[sink_index].destination_gamut.blueX = + input_gamut_coordinates->blueX; + core_color->state[sink_index].destination_gamut.blueY = + input_gamut_coordinates->blueY; + core_color->state[sink_index].destination_gamut.greenX = + input_gamut_coordinates->greenX; + core_color->state[sink_index].destination_gamut.greenY = + input_gamut_coordinates->greenY; + core_color->state[sink_index].destination_gamut.redX = + input_gamut_coordinates->redX; + core_color->state[sink_index].destination_gamut.redY = + input_gamut_coordinates->redY; + core_color->state[sink_index].destination_gamut.whiteX = + input_white_point_coordinates->whiteX; + core_color->state[sink_index].destination_gamut.whiteY = + input_white_point_coordinates->whiteY; + } + + if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) + return false; + + return true; +} + +bool mod_color_set_white_point(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct white_point_coodinates *white_point) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; + stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + core_color->state[sink_index].source_gamut.whiteX = + white_point->whiteX; + core_color->state[sink_index].source_gamut.whiteY = + white_point->whiteY; + } + + if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) + return false; + + return true; +} + +bool mod_color_set_user_enable(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + bool user_enable) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + core_color->state[sink_index].user_enable_color_temperature + = user_enable; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "enablecolortempadj", + &user_enable, + sizeof(bool), + &flag); + } + return true; +} + +bool mod_color_get_user_enable(struct mod_color *mod_color, + const struct dc_sink *sink, + bool *user_enable) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *user_enable = core_color->state[sink_index]. + user_enable_color_temperature; + + return true; +} + +bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, + const struct dc_sink *sink, + int *color_temperature) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_temperature = core_color->state[sink_index]. + custom_color_temperature; + + return true; +} + +bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int color_temperature) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + core_color->state[sink_index].custom_color_temperature + = color_temperature; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "customcolortemp", + &color_temperature, + sizeof(int), + &flag); + } + return true; +} + +bool mod_color_get_color_saturation(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_saturation) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_saturation = core_color->state[sink_index].saturation; + + return true; +} + +bool mod_color_get_color_contrast(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_contrast) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_contrast = core_color->state[sink_index].contrast; + + return true; +} + +bool mod_color_get_color_brightness(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_brightness) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_brightness = core_color->state[sink_index].brightness; + + return true; +} + +bool mod_color_get_color_hue(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_hue) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *color_hue = core_color->state[sink_index].hue; + + return true; +} + +bool mod_color_get_source_gamut(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_space_coordinates *source_gamut) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + *source_gamut = core_color->state[sink_index].source_gamut; + + return true; +} + +bool mod_color_notify_mode_change(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + struct gamut_src_dst_matrix *matrix = + dm_alloc(sizeof(struct gamut_src_dst_matrix)); + + unsigned int stream_index, sink_index, j; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + if (!build_gamut_remap_matrix + (core_color->state[sink_index].source_gamut, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc)) + goto function_fail; + + if (!build_gamut_remap_matrix + (core_color->state[sink_index]. + destination_gamut, + matrix->rgbCoeffDst, matrix->whiteCoeffDst)) + goto function_fail; + + struct fixed31_32 gamut_result[12]; + struct fixed31_32 temp_matrix[9]; + + if (!gamut_to_color_matrix( + matrix->rgbCoeffDst, + matrix->whiteCoeffDst, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc, + true, + temp_matrix)) + goto function_fail; + + gamut_result[0] = temp_matrix[0]; + gamut_result[1] = temp_matrix[1]; + gamut_result[2] = temp_matrix[2]; + gamut_result[3] = matrix->whiteCoeffSrc[0]; + gamut_result[4] = temp_matrix[3]; + gamut_result[5] = temp_matrix[4]; + gamut_result[6] = temp_matrix[5]; + gamut_result[7] = matrix->whiteCoeffSrc[1]; + gamut_result[8] = temp_matrix[6]; + gamut_result[9] = temp_matrix[7]; + gamut_result[10] = temp_matrix[8]; + gamut_result[11] = matrix->whiteCoeffSrc[2]; + + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_stream->public.gamut_remap_matrix.enable_remap = true; + + for (j = 0; j < 12; j++) + core_stream->public. + gamut_remap_matrix.matrix[j] = + gamut_result[j]; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + } + + dm_free(matrix); + + return true; + +function_fail: + dm_free(matrix); + return false; +} + +bool mod_color_set_brightness(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int brightness_value) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_color->state[sink_index].brightness.current = + brightness_value; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "brightness", + &brightness_value, + sizeof(int), + &flag); + } + + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; +} + +bool mod_color_set_contrast(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int contrast_value) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_color->state[sink_index].contrast.current = + contrast_value; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "contrast", + &contrast_value, + sizeof(int), + &flag); + } + + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; +} + +bool mod_color_set_hue(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int hue_value) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_color->state[sink_index].hue.current = hue_value; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "hue", + &hue_value, + sizeof(int), + &flag); + } + + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; +} + +bool mod_color_set_saturation(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int saturation_value) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct core_stream *core_stream = + DC_STREAM_TO_CORE + (streams[stream_index]); + + core_color->state[sink_index].saturation.current = + saturation_value; + + calculate_csc_matrix(core_color, sink_index, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + + core_stream->public.csc_color_matrix.enable_adjustment = true; + + /* Write persistent data in registry*/ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + COLOR_REGISTRY_NAME, + "saturation", + &saturation_value, + sizeof(int), + &flag); + } + + core_color->dc->stream_funcs.set_gamut_remap + (core_color->dc, streams, num_streams); + + return true; +} + +bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, + const struct dc_sink *sink, + enum dc_quantization_range quantization_range) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct persistent_data_flag flag; + unsigned int sink_index; + + sink_index = sink_index_from_sink(core_color, sink); + if (core_color->state[sink_index]. + preferred_quantization_range != quantization_range) { + core_color->state[sink_index].preferred_quantization_range = + quantization_range; + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, + sink, + COLOR_REGISTRY_NAME, + "quantization_range", + &quantization_range, + sizeof(int), + &flag); + } + + return true; +} + +bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, + const struct dc_sink *sink, + enum dc_quantization_range *quantization_range) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + unsigned int sink_index; + + sink_index = sink_index_from_sink(core_color, sink); + *quantization_range = core_color->state[sink_index]. + preferred_quantization_range; + return true; +} diff --git a/drivers/gpu/drm/amd/display/modules/freesync/Makefile b/drivers/gpu/drm/amd/display/modules/freesync/Makefile new file mode 100644 index 000000000000..db8e0ff6d7a9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/freesync/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the 'freesync' sub-module of DAL. +# + +FREESYNC = freesync.o + +AMD_DAL_FREESYNC = $(addprefix $(AMDDALPATH)/modules/freesync/,$(FREESYNC)) +#$(info ************ DAL-FREE SYNC_MAKEFILE ************) + +AMD_DISPLAY_FILES += $(AMD_DAL_FREESYNC) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c new file mode 100644 index 000000000000..eb912baa0169 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -0,0 +1,1158 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "mod_freesync.h" +#include "core_types.h" +#include "core_dc.h" + +#define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 + +/* Refresh rate ramp at a fixed rate of 65 Hz/second */ +#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65) +/* Number of elements in the render times cache array */ +#define RENDER_TIMES_MAX_COUNT 20 +/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */ +#define BTR_EXIT_MARGIN 2000 + +#define FREESYNC_REGISTRY_NAME "freesync_v1" + +struct gradual_static_ramp { + bool ramp_is_active; + bool ramp_direction_is_up; + unsigned int ramp_current_frame_duration_in_ns; +}; + +struct time_cache { + /* video (48Hz feature) related */ + unsigned int update_duration_in_ns; + + /* BTR/fixed refresh related */ + unsigned int prev_time_stamp_in_us; + + unsigned int min_render_time_in_us; + unsigned int max_render_time_in_us; + + unsigned int render_times_index; + unsigned int render_times[RENDER_TIMES_MAX_COUNT]; +}; + +struct below_the_range { + bool btr_active; + bool program_btr; + + unsigned int mid_point_in_us; + + unsigned int inserted_frame_duration_in_us; + unsigned int frames_to_insert; + unsigned int frame_counter; +}; + +struct fixed_refresh { + bool fixed_refresh_active; + bool program_fixed_refresh; +}; + +struct freesync_state { + bool fullscreen; + bool static_screen; + bool video; + + unsigned int nominal_refresh_rate_in_micro_hz; + bool windowed_fullscreen; + + struct time_cache time; + + struct gradual_static_ramp static_ramp; + struct below_the_range btr; + struct fixed_refresh fixed_refresh; +}; + +struct freesync_entity { + const struct dc_stream *stream; + struct mod_freesync_caps *caps; + struct freesync_state state; + struct mod_freesync_user_enable user_enable; +}; + +struct core_freesync { + struct mod_freesync public; + struct dc *dc; + struct freesync_entity *map; + int num_entities; +}; + +#define MOD_FREESYNC_TO_CORE(mod_freesync)\ + container_of(mod_freesync, struct core_freesync, public) + +static bool check_dc_support(const struct dc *dc) +{ + if (dc->stream_funcs.adjust_vmin_vmax == NULL) + return false; + + return true; +} + +struct mod_freesync *mod_freesync_create(struct dc *dc) +{ + struct core_freesync *core_freesync = + dm_alloc(sizeof(struct core_freesync)); + + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct persistent_data_flag flag; + + int i = 0; + + if (core_freesync == NULL) + goto fail_alloc_context; + + core_freesync->map = dm_alloc(sizeof(struct freesync_entity) * + MOD_FREESYNC_MAX_CONCURRENT_STREAMS); + + if (core_freesync->map == NULL) + goto fail_alloc_map; + + for (i = 0; i < MOD_FREESYNC_MAX_CONCURRENT_STREAMS; i++) + core_freesync->map[i].stream = NULL; + + core_freesync->num_entities = 0; + + if (dc == NULL) + goto fail_construct; + + core_freesync->dc = dc; + + if (!check_dc_support(dc)) + goto fail_construct; + + /* Create initial module folder in registry for freesync enable data */ + flag.save_per_edid = true; + flag.save_per_link = false; + dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL, + 0, &flag); + + return &core_freesync->public; + +fail_construct: + dm_free(core_freesync->map); + +fail_alloc_map: + dm_free(core_freesync); + +fail_alloc_context: + return NULL; +} + +void mod_freesync_destroy(struct mod_freesync *mod_freesync) +{ + if (mod_freesync != NULL) { + int i; + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + for (i = 0; i < core_freesync->num_entities; i++) + if (core_freesync->map[i].stream) + dc_stream_release(core_freesync->map[i].stream); + + dm_free(core_freesync->map); + + dm_free(core_freesync); + } +} + +/* Given a specific dc_stream* this function finds its equivalent + * on the core_freesync->map and returns the corresponding index + */ +static unsigned int map_index_from_stream(struct core_freesync *core_freesync, + const struct dc_stream *stream) +{ + unsigned int index = 0; + + for (index = 0; index < core_freesync->num_entities; index++) { + if (core_freesync->map[index].stream == stream) { + return index; + } + } + /* Could not find stream requested */ + ASSERT(false); + return index; +} + +bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, struct mod_freesync_caps *caps) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + struct core_stream *core_stream = + DC_STREAM_TO_CORE(stream); + struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc); + + int persistent_freesync_enable = 0; + struct persistent_data_flag flag; + + flag.save_per_edid = true; + flag.save_per_link = false; + + if (core_freesync->num_entities < MOD_FREESYNC_MAX_CONCURRENT_STREAMS) { + + dc_stream_retain(stream); + + core_freesync->map[core_freesync->num_entities].stream = stream; + core_freesync->map[core_freesync->num_entities].caps = caps; + + core_freesync->map[core_freesync->num_entities].state. + fullscreen = false; + core_freesync->map[core_freesync->num_entities].state. + static_screen = false; + core_freesync->map[core_freesync->num_entities].state. + video = false; + core_freesync->map[core_freesync->num_entities].state.time. + update_duration_in_ns = 0; + core_freesync->map[core_freesync->num_entities].state. + static_ramp.ramp_is_active = false; + + /* get persistent data from registry */ + if (dm_read_persistent_data(core_dc->ctx, stream->sink, + FREESYNC_REGISTRY_NAME, + "userenable", &persistent_freesync_enable, + sizeof(int), &flag)) { + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_gaming = + (persistent_freesync_enable & 1) ? true : false; + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_static = + (persistent_freesync_enable & 2) ? true : false; + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_video = + (persistent_freesync_enable & 4) ? true : false; + } else { + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_gaming = false; + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_static = false; + core_freesync->map[core_freesync->num_entities].user_enable. + enable_for_video = false; + } + + if (caps->supported) + core_stream->public.ignore_msa_timing_param = 1; + + core_freesync->num_entities++; + return true; + } + return false; +} + +bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, + const struct dc_stream *stream) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + int i = 0; + unsigned int index = map_index_from_stream(core_freesync, stream); + dc_stream_release(core_freesync->map[index].stream); + core_freesync->map[index].stream = NULL; + /* To remove this entity, shift everything after down */ + for (i = index; i < core_freesync->num_entities - 1; i++) + core_freesync->map[i] = core_freesync->map[i + 1]; + core_freesync->num_entities--; + return true; +} + +static void update_stream_freesync_context(struct core_freesync *core_freesync, + const struct dc_stream *stream) +{ + unsigned int index; + struct freesync_context *ctx; + struct core_stream *core_stream; + + core_stream = DC_STREAM_TO_CORE(stream); + ctx = &core_stream->public.freesync_ctx; + + index = map_index_from_stream(core_freesync, stream); + + ctx->supported = core_freesync->map[index].caps->supported; + ctx->enabled = (core_freesync->map[index].user_enable.enable_for_gaming || + core_freesync->map[index].user_enable.enable_for_video || + core_freesync->map[index].user_enable.enable_for_static); + ctx->active = (core_freesync->map[index].state.fullscreen || + core_freesync->map[index].state.video || + core_freesync->map[index].state.static_ramp.ramp_is_active); + ctx->min_refresh_in_micro_hz = + core_freesync->map[index].caps->min_refresh_in_micro_hz; + ctx->nominal_refresh_in_micro_hz = core_freesync-> + map[index].state.nominal_refresh_rate_in_micro_hz; + +} + +static void update_stream(struct core_freesync *core_freesync, + const struct dc_stream *stream) +{ + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + + unsigned int index = map_index_from_stream(core_freesync, stream); + if (core_freesync->map[index].caps->supported) { + core_stream->public.ignore_msa_timing_param = 1; + update_stream_freesync_context(core_freesync, stream); + } +} + +static void calc_vmin_vmax(struct core_freesync *core_freesync, + const struct dc_stream *stream, int *vmin, int *vmax) +{ + unsigned int min_frame_duration_in_ns = 0, max_frame_duration_in_ns = 0; + unsigned int index = map_index_from_stream(core_freesync, stream); + + min_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].state. + nominal_refresh_rate_in_micro_hz))); + max_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].caps->min_refresh_in_micro_hz))); + + *vmax = div64_u64(div64_u64(((unsigned long long)( + max_frame_duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); + *vmin = div64_u64(div64_u64(((unsigned long long)( + min_frame_duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); +} + +static void calc_v_total_from_duration(const struct dc_stream *stream, + unsigned int duration_in_ns, int *v_total_nominal) +{ + *v_total_nominal = div64_u64(div64_u64(((unsigned long long)( + duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); +} + +static void calc_v_total_for_static_ramp(struct core_freesync *core_freesync, + const struct dc_stream *stream, + unsigned int index, int *v_total) +{ + unsigned int frame_duration = 0; + + struct gradual_static_ramp *static_ramp_variables = + &core_freesync->map[index].state.static_ramp; + + /* Calc ratio between new and current frame duration with 3 digit */ + unsigned int frame_duration_ratio = div64_u64(1000000, + (1000 + div64_u64(((unsigned long long)( + STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME) * + static_ramp_variables->ramp_current_frame_duration_in_ns), + 1000000000))); + + /* Calculate delta between new and current frame duration in ns */ + unsigned int frame_duration_delta = div64_u64(((unsigned long long)( + static_ramp_variables->ramp_current_frame_duration_in_ns) * + (1000 - frame_duration_ratio)), 1000); + + /* Adjust frame duration delta based on ratio between current and + * standard frame duration (frame duration at 60 Hz refresh rate). + */ + unsigned int ramp_rate_interpolated = div64_u64(((unsigned long long)( + frame_duration_delta) * static_ramp_variables-> + ramp_current_frame_duration_in_ns), 16666666); + + /* Going to a higher refresh rate (lower frame duration) */ + if (static_ramp_variables->ramp_direction_is_up) { + /* reduce frame duration */ + static_ramp_variables->ramp_current_frame_duration_in_ns -= + ramp_rate_interpolated; + + /* min frame duration */ + frame_duration = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].state. + nominal_refresh_rate_in_micro_hz))); + + /* adjust for frame duration below min */ + if (static_ramp_variables->ramp_current_frame_duration_in_ns <= + frame_duration) { + + static_ramp_variables->ramp_is_active = false; + static_ramp_variables-> + ramp_current_frame_duration_in_ns = + frame_duration; + } + /* Going to a lower refresh rate (larger frame duration) */ + } else { + /* increase frame duration */ + static_ramp_variables->ramp_current_frame_duration_in_ns += + ramp_rate_interpolated; + + /* max frame duration */ + frame_duration = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].caps->min_refresh_in_micro_hz))); + + /* adjust for frame duration above max */ + if (static_ramp_variables->ramp_current_frame_duration_in_ns >= + frame_duration) { + + static_ramp_variables->ramp_is_active = false; + static_ramp_variables-> + ramp_current_frame_duration_in_ns = + frame_duration; + } + } + + calc_v_total_from_duration(stream, static_ramp_variables-> + ramp_current_frame_duration_in_ns, v_total); +} + +static void reset_freesync_state_variables(struct freesync_state* state) +{ + state->static_ramp.ramp_is_active = false; + if (state->nominal_refresh_rate_in_micro_hz) + state->static_ramp.ramp_current_frame_duration_in_ns = + ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + state->nominal_refresh_rate_in_micro_hz))); + + state->btr.btr_active = false; + state->btr.frame_counter = 0; + state->btr.frames_to_insert = 0; + state->btr.inserted_frame_duration_in_us = 0; + state->btr.program_btr = false; + + state->fixed_refresh.fixed_refresh_active = false; + state->fixed_refresh.program_fixed_refresh = false; +} +/* + * Sets freesync mode on a stream depending on current freesync state. + */ +static bool set_freesync_on_streams(struct core_freesync *core_freesync, + const struct dc_stream **streams, int num_streams) +{ + int v_total_nominal = 0, v_total_min = 0, v_total_max = 0; + unsigned int stream_idx, map_index = 0; + struct freesync_state *state; + + if (num_streams == 0 || streams == NULL || num_streams > 1) + return false; + + for (stream_idx = 0; stream_idx < num_streams; stream_idx++) { + + map_index = map_index_from_stream(core_freesync, + streams[stream_idx]); + + state = &core_freesync->map[map_index].state; + + if (core_freesync->map[map_index].caps->supported) { + + /* Fullscreen has the topmost priority. If the + * fullscreen bit is set, we are in a fullscreen + * application where it should not matter if it is + * static screen. We should not check the static_screen + * or video bit. + * + * Special cases of fullscreen include btr and fixed + * refresh. We program btr on every flip and involves + * programming full range right before the last inserted frame. + * However, we do not want to program the full freesync range + * when fixed refresh is active, because we only program + * that logic once and this will override it. + */ + if (core_freesync->map[map_index].user_enable. + enable_for_gaming == true && + state->fullscreen == true && + state->fixed_refresh.fixed_refresh_active == false) { + /* Enable freesync */ + + calc_vmin_vmax(core_freesync, + streams[stream_idx], + &v_total_min, &v_total_max); + + /* Update the freesync context for the stream */ + update_stream_freesync_context(core_freesync, + streams[stream_idx]); + + core_freesync->dc->stream_funcs. + adjust_vmin_vmax(core_freesync->dc, streams, + num_streams, v_total_min, + v_total_max); + + return true; + + } else if (core_freesync->map[map_index].user_enable. + enable_for_video && state->video == true) { + /* Enable 48Hz feature */ + + calc_v_total_from_duration(streams[stream_idx], + state->time.update_duration_in_ns, + &v_total_nominal); + + /* Program only if v_total_nominal is in range*/ + if (v_total_nominal >= + streams[stream_idx]->timing.v_total) { + + /* Update the freesync context for + * the stream + */ + update_stream_freesync_context( + core_freesync, + streams[stream_idx]); + + core_freesync->dc->stream_funcs. + adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, v_total_nominal, + v_total_nominal); + } + return true; + + } else { + /* Disable freesync */ + v_total_nominal = streams[stream_idx]-> + timing.v_total; + + /* Update the freesync context for + * the stream + */ + update_stream_freesync_context( + core_freesync, + streams[stream_idx]); + + core_freesync->dc->stream_funcs. + adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, v_total_nominal, + v_total_nominal); + + /* Reset the cached variables */ + reset_freesync_state_variables(state); + + return true; + } + } else { + /* Disable freesync */ + v_total_nominal = streams[stream_idx]-> + timing.v_total; + /* + * we have to reset drr always even sink does + * not support freesync because a former stream has + * be programmed + */ + core_freesync->dc->stream_funcs. + adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, v_total_nominal, + v_total_nominal); + /* Reset the cached variables */ + reset_freesync_state_variables(state); + } + + } + + return false; +} + +static void set_static_ramp_variables(struct core_freesync *core_freesync, + unsigned int index, bool enable_static_screen) +{ + unsigned int frame_duration = 0; + + struct gradual_static_ramp *static_ramp_variables = + &core_freesync->map[index].state.static_ramp; + + /* If ramp is not active, set initial frame duration depending on + * whether we are enabling/disabling static screen mode. If the ramp is + * already active, ramp should continue in the opposite direction + * starting with the current frame duration + */ + if (!static_ramp_variables->ramp_is_active) { + + static_ramp_variables->ramp_is_active = true; + + if (enable_static_screen == true) { + /* Going to lower refresh rate, so start from max + * refresh rate (min frame duration) + */ + frame_duration = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].state. + nominal_refresh_rate_in_micro_hz))); + } else { + /* Going to higher refresh rate, so start from min + * refresh rate (max frame duration) + */ + frame_duration = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[index].caps->min_refresh_in_micro_hz))); + } + + static_ramp_variables-> + ramp_current_frame_duration_in_ns = frame_duration; + } + + /* If we are ENABLING static screen, refresh rate should go DOWN. + * If we are DISABLING static screen, refresh rate should go UP. + */ + static_ramp_variables->ramp_direction_is_up = !enable_static_screen; +} + +void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + unsigned int index, v_total = 0; + struct freesync_state *state; + + if (core_freesync->num_entities == 0) + return; + + index = map_index_from_stream(core_freesync, + streams[0]); + + if (core_freesync->map[index].caps->supported == false) + return; + + state = &core_freesync->map[index].state; + + /* Below the Range Logic */ + + /* Only execute if in fullscreen mode */ + if (state->fullscreen == true && + core_freesync->map[index].user_enable.enable_for_gaming) { + + if (state->btr.btr_active) + if (state->btr.frame_counter > 0) + + state->btr.frame_counter--; + + if (state->btr.frame_counter == 1) { + + /* Restore FreeSync */ + set_freesync_on_streams(core_freesync, streams, + num_streams); + } + } + + /* If in fullscreen freesync mode or in video, do not program + * static screen ramp values + */ + if (state->fullscreen == true || state->video == true) { + + state->static_ramp.ramp_is_active = false; + + return; + } + + /* Gradual Static Screen Ramping Logic */ + + /* Execute if ramp is active and user enabled freesync static screen*/ + if (state->static_ramp.ramp_is_active && + core_freesync->map[index].user_enable.enable_for_static) { + + calc_v_total_for_static_ramp(core_freesync, streams[0], + index, &v_total); + + /* Update the freesync context for the stream */ + update_stream_freesync_context(core_freesync, streams[0]); + + /* Program static screen ramp values */ + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, v_total, + v_total); + } +} + +void mod_freesync_update_state(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + struct mod_freesync_params *freesync_params) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + bool freesync_program_required = false; + unsigned int stream_index; + struct freesync_state *state; + + if (core_freesync->num_entities == 0) + return; + + for(stream_index = 0; stream_index < num_streams; stream_index++) { + + unsigned int map_index = map_index_from_stream(core_freesync, + streams[stream_index]); + + state = &core_freesync->map[map_index].state; + + switch (freesync_params->state){ + case FREESYNC_STATE_FULLSCREEN: + state->fullscreen = freesync_params->enable; + freesync_program_required = true; + state->windowed_fullscreen = + freesync_params->windowed_fullscreen; + break; + case FREESYNC_STATE_STATIC_SCREEN: + /* Static screen ramp is only enabled for embedded + * panels. Also change core variables only if there + * is a change. + */ + if (dc_is_embedded_signal( + streams[stream_index]->sink->sink_signal) && + state->static_screen != + freesync_params->enable) { + + /* Change the state flag */ + state->static_screen = freesync_params->enable; + + /* Change static screen ramp variables */ + set_static_ramp_variables(core_freesync, + map_index, + freesync_params->enable); + } + /* We program the ramp starting next VUpdate */ + break; + case FREESYNC_STATE_VIDEO: + /* Change core variables only if there is a change*/ + if(freesync_params->update_duration_in_ns != + state->time.update_duration_in_ns) { + + state->video = freesync_params->enable; + state->time.update_duration_in_ns = + freesync_params->update_duration_in_ns; + + freesync_program_required = true; + } + break; + } + } + + if (freesync_program_required) + /* Program freesync according to current state*/ + set_freesync_on_streams(core_freesync, streams, num_streams); +} + + +bool mod_freesync_get_state(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + struct mod_freesync_params *freesync_params) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + unsigned int index = map_index_from_stream(core_freesync, stream); + + if (core_freesync->map[index].state.fullscreen) { + freesync_params->state = FREESYNC_STATE_FULLSCREEN; + freesync_params->enable = true; + } else if (core_freesync->map[index].state.static_screen) { + freesync_params->state = FREESYNC_STATE_STATIC_SCREEN; + freesync_params->enable = true; + } else if (core_freesync->map[index].state.video) { + freesync_params->state = FREESYNC_STATE_VIDEO; + freesync_params->enable = true; + } else { + freesync_params->state = FREESYNC_STATE_NONE; + freesync_params->enable = false; + } + + freesync_params->update_duration_in_ns = + core_freesync->map[index].state.time.update_duration_in_ns; + + return true; +} + +bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + struct mod_freesync_user_enable *user_enable) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc); + + unsigned int stream_index, map_index; + int persistent_data = 0; + struct persistent_data_flag flag; + + flag.save_per_edid = true; + flag.save_per_link = false; + + for(stream_index = 0; stream_index < num_streams; + stream_index++){ + + map_index = map_index_from_stream(core_freesync, + streams[stream_index]); + + core_freesync->map[map_index].user_enable = *user_enable; + + /* Write persistent data in registry*/ + if (core_freesync->map[map_index].user_enable. + enable_for_gaming) + persistent_data = persistent_data | 1; + if (core_freesync->map[map_index].user_enable. + enable_for_static) + persistent_data = persistent_data | 2; + if (core_freesync->map[map_index].user_enable. + enable_for_video) + persistent_data = persistent_data | 4; + + dm_write_persistent_data(core_dc->ctx, + streams[stream_index]->sink, + FREESYNC_REGISTRY_NAME, + "userenable", + &persistent_data, + sizeof(int), + &flag); + } + + set_freesync_on_streams(core_freesync, streams, num_streams); + + return true; +} + +bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + struct mod_freesync_user_enable *user_enable) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + unsigned int index = map_index_from_stream(core_freesync, stream); + + *user_enable = core_freesync->map[index].user_enable; + + return true; +} + +void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams) +{ + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + unsigned int stream_index, map_index; + unsigned min_frame_duration_in_ns, max_frame_duration_in_ns; + struct freesync_state *state; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + + map_index = map_index_from_stream(core_freesync, + streams[stream_index]); + + state = &core_freesync->map[map_index].state; + + if (core_freesync->map[map_index].caps->supported) { + /* Update the field rate for new timing */ + state->nominal_refresh_rate_in_micro_hz = 1000000 * + div64_u64(div64_u64((streams[stream_index]-> + timing.pix_clk_khz * 1000), + streams[stream_index]->timing.v_total), + streams[stream_index]->timing.h_total); + + /* Update the stream */ + update_stream(core_freesync, streams[stream_index]); + + /* Determine whether BTR can be supported */ + min_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + state->nominal_refresh_rate_in_micro_hz))); + + max_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + core_freesync->map[map_index].caps->min_refresh_in_micro_hz))); + + if (max_frame_duration_in_ns >= + 2 * min_frame_duration_in_ns) + core_freesync->map[map_index].caps->btr_supported = true; + else + core_freesync->map[map_index].caps->btr_supported = false; + + /* Cache the time variables */ + state->time.max_render_time_in_us = + max_frame_duration_in_ns / 1000; + state->time.min_render_time_in_us = + min_frame_duration_in_ns / 1000; + state->btr.mid_point_in_us = + (max_frame_duration_in_ns + + min_frame_duration_in_ns) / 2000; + + } + } + + /* Program freesync according to current state*/ + set_freesync_on_streams(core_freesync, streams, num_streams); +} + +/* Add the timestamps to the cache and determine whether BTR programming + * is required, depending on the times calculated + */ +static void update_timestamps(struct core_freesync *core_freesync, + const struct dc_stream *stream, unsigned int map_index, + unsigned int last_render_time_in_us) +{ + struct freesync_state *state = &core_freesync->map[map_index].state; + + state->time.render_times[state->time.render_times_index] = + last_render_time_in_us; + state->time.render_times_index++; + + if (state->time.render_times_index >= RENDER_TIMES_MAX_COUNT) + state->time.render_times_index = 0; + + if (last_render_time_in_us + BTR_EXIT_MARGIN < + state->time.max_render_time_in_us) { + + /* Exit Below the Range */ + if (state->btr.btr_active) { + + state->btr.program_btr = true; + state->btr.btr_active = false; + state->btr.frame_counter = 0; + + /* Exit Fixed Refresh mode */ + } else if (state->fixed_refresh.fixed_refresh_active) { + + state->fixed_refresh.program_fixed_refresh = true; + state->fixed_refresh.fixed_refresh_active = false; + + } + + } else if (last_render_time_in_us > state->time.max_render_time_in_us) { + + /* Enter Below the Range */ + if (!state->btr.btr_active && + core_freesync->map[map_index].caps->btr_supported) { + + state->btr.program_btr = true; + state->btr.btr_active = true; + + /* Enter Fixed Refresh mode */ + } else if (!state->fixed_refresh.fixed_refresh_active && + !core_freesync->map[map_index].caps->btr_supported) { + + state->fixed_refresh.program_fixed_refresh = true; + state->fixed_refresh.fixed_refresh_active = true; + + } + } + + /* When Below the Range is active, must react on every frame */ + if (state->btr.btr_active) + state->btr.program_btr = true; +} + +static void apply_below_the_range(struct core_freesync *core_freesync, + const struct dc_stream *stream, unsigned int map_index, + unsigned int last_render_time_in_us) +{ + unsigned int inserted_frame_duration_in_us = 0; + unsigned int mid_point_frames_ceil = 0; + unsigned int mid_point_frames_floor = 0; + unsigned int frame_time_in_us = 0; + unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF; + unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF; + unsigned int frames_to_insert = 0; + unsigned int inserted_frame_v_total = 0; + unsigned int vmin = 0, vmax = 0; + unsigned int min_frame_duration_in_ns = 0; + struct freesync_state *state = &core_freesync->map[map_index].state; + + if (!state->btr.program_btr) + return; + + state->btr.program_btr = false; + + min_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + state->nominal_refresh_rate_in_micro_hz))); + + /* Program BTR */ + + /* BTR set to "not active" so disengage */ + if (!state->btr.btr_active) + + /* Restore FreeSync */ + set_freesync_on_streams(core_freesync, &stream, 1); + + /* BTR set to "active" so engage */ + else { + + /* Calculate number of midPoint frames that could fit within + * the render time interval- take ceil of this value + */ + mid_point_frames_ceil = (last_render_time_in_us + + state->btr.mid_point_in_us- 1) / + state->btr.mid_point_in_us; + + if (mid_point_frames_ceil > 0) { + + frame_time_in_us = last_render_time_in_us / + mid_point_frames_ceil; + delta_from_mid_point_in_us_1 = (state->btr.mid_point_in_us > + frame_time_in_us) ? + (state->btr.mid_point_in_us - frame_time_in_us): + (frame_time_in_us - state->btr.mid_point_in_us); + } + + /* Calculate number of midPoint frames that could fit within + * the render time interval- take floor of this value + */ + mid_point_frames_floor = last_render_time_in_us / + state->btr.mid_point_in_us; + + if (mid_point_frames_floor > 0) { + + frame_time_in_us = last_render_time_in_us / + mid_point_frames_floor; + delta_from_mid_point_in_us_2 = (state->btr.mid_point_in_us > + frame_time_in_us) ? + (state->btr.mid_point_in_us - frame_time_in_us): + (frame_time_in_us - state->btr.mid_point_in_us); + } + + /* Choose number of frames to insert based on how close it + * can get to the mid point of the variable range. + */ + if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) + frames_to_insert = mid_point_frames_ceil; + else + frames_to_insert = mid_point_frames_floor; + + /* Either we've calculated the number of frames to insert, + * or we need to insert min duration frames + */ + if (frames_to_insert > 0) + inserted_frame_duration_in_us = last_render_time_in_us / + frames_to_insert; + + if (inserted_frame_duration_in_us < + state->time.min_render_time_in_us) + + inserted_frame_duration_in_us = + state->time.min_render_time_in_us; + + /* We need the v_total_min from capability */ + calc_vmin_vmax(core_freesync, stream, &vmin, &vmax); + + inserted_frame_v_total = vmin; + if (min_frame_duration_in_ns / 1000) + inserted_frame_v_total = inserted_frame_duration_in_us * + vmin / (min_frame_duration_in_ns / 1000); + + /* Set length of inserted frames as v_total_max*/ + vmax = inserted_frame_v_total; + + /* Program V_TOTAL */ + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, &stream, + 1, vmin, + vmax); + + /* Cache the calculated variables */ + state->btr.inserted_frame_duration_in_us = + inserted_frame_duration_in_us; + state->btr.frames_to_insert = frames_to_insert; + state->btr.frame_counter = frames_to_insert; + + } +} + +static void apply_fixed_refresh(struct core_freesync *core_freesync, + const struct dc_stream *stream, unsigned int map_index) +{ + unsigned int vmin = 0, vmax = 0; + struct freesync_state *state = &core_freesync->map[map_index].state; + + if (!state->fixed_refresh.program_fixed_refresh) + return; + + state->fixed_refresh.program_fixed_refresh = false; + + /* Program Fixed Refresh */ + + /* Fixed Refresh set to "not active" so disengage */ + if (!state->fixed_refresh.fixed_refresh_active) { + set_freesync_on_streams(core_freesync, &stream, 1); + + /* Fixed Refresh set to "active" so engage (fix to max) */ + } else { + + calc_vmin_vmax(core_freesync, stream, &vmin, &vmax); + + vmax = vmin; + + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, &stream, + 1, vmin, + vmax); + } +} + +void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + unsigned int curr_time_stamp_in_us) +{ + unsigned int stream_index, map_index, last_render_time_in_us = 0; + struct core_freesync *core_freesync = + MOD_FREESYNC_TO_CORE(mod_freesync); + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + + map_index = map_index_from_stream(core_freesync, + streams[stream_index]); + + if (core_freesync->map[map_index].caps->supported) { + + last_render_time_in_us = curr_time_stamp_in_us - + core_freesync->map[map_index].state.time. + prev_time_stamp_in_us; + + /* Add the timestamps to the cache and determine + * whether BTR program is required + */ + update_timestamps(core_freesync, streams[stream_index], + map_index, last_render_time_in_us); + + if (core_freesync->map[map_index].state.fullscreen && + core_freesync->map[map_index].user_enable. + enable_for_gaming) { + + if (core_freesync->map[map_index].caps->btr_supported) { + + apply_below_the_range(core_freesync, + streams[stream_index], map_index, + last_render_time_in_us); + } else { + apply_fixed_refresh(core_freesync, + streams[stream_index], map_index); + } + } + + core_freesync->map[map_index].state.time. + prev_time_stamp_in_us = curr_time_stamp_in_us; + } + + } +} diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h new file mode 100644 index 000000000000..e54fe2cb8611 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -0,0 +1,179 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef MOD_COLOR_H_ +#define MOD_COLOR_H_ + +#include "dm_services.h" + +struct mod_color { + int dummy; +}; + +struct color_space_coordinates { + unsigned int redX; + unsigned int redY; + unsigned int greenX; + unsigned int greenY; + unsigned int blueX; + unsigned int blueY; + unsigned int whiteX; + unsigned int whiteY; +}; + +struct gamut_space_coordinates { + unsigned int redX; + unsigned int redY; + unsigned int greenX; + unsigned int greenY; + unsigned int blueX; + unsigned int blueY; +}; + +struct gamut_space_entry { + unsigned int index; + unsigned int redX; + unsigned int redY; + unsigned int greenX; + unsigned int greenY; + unsigned int blueX; + unsigned int blueY; + + int a0; + int a1; + int a2; + int a3; + int gamma; +}; + +struct white_point_coodinates { + unsigned int whiteX; + unsigned int whiteY; +}; + +struct white_point_coodinates_entry { + unsigned int index; + unsigned int whiteX; + unsigned int whiteY; +}; + +struct color_range { + int current; + int min; + int max; +}; + +struct mod_color *mod_color_create(struct dc *dc); + +void mod_color_destroy(struct mod_color *mod_color); + +bool mod_color_add_sink(struct mod_color *mod_color, + const struct dc_sink *sink); + +bool mod_color_remove_sink(struct mod_color *mod_color, + const struct dc_sink *sink); + +bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams); + +bool mod_color_set_white_point(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct white_point_coodinates *white_point); + +bool mod_color_adjust_source_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct gamut_space_coordinates *input_gamut_coordinates, + struct white_point_coodinates *input_white_point_coordinates); + +bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct gamut_space_coordinates *input_gamut_coordinates, + struct white_point_coodinates *input_white_point_coordinates); + +bool mod_color_get_user_enable(struct mod_color *mod_color, + const struct dc_sink *sink, + bool *user_enable); + +bool mod_color_set_user_enable(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + bool user_enable); + +bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, + const struct dc_sink *sink, + int *color_temperature); + +bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int color_temperature); + +bool mod_color_get_color_saturation(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_saturation); + +bool mod_color_get_color_contrast(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_contrast); + +bool mod_color_get_color_brightness(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_brightness); + +bool mod_color_get_color_hue(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_range *color_hue); + +bool mod_color_get_source_gamut(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_space_coordinates *source_gamut); + +bool mod_color_notify_mode_change(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams); + +bool mod_color_set_brightness(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int brightness_value); + +bool mod_color_set_contrast(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int contrast_value); + +bool mod_color_set_hue(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int hue_value); + +bool mod_color_set_saturation(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + int saturation_value); + +bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, + const struct dc_sink *sink, + enum dc_quantization_range quantization_range); + +bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, + const struct dc_sink *sink, + enum dc_quantization_range *quantization_range); + +#endif /* MOD_COLOR_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h new file mode 100644 index 000000000000..7abfe34dc2d9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -0,0 +1,149 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + + + +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef MOD_FREESYNC_H_ +#define MOD_FREESYNC_H_ + +#include "dm_services.h" + +struct mod_freesync *mod_freesync_create(struct dc *dc); +void mod_freesync_destroy(struct mod_freesync *mod_freesync); + +struct mod_freesync { + int dummy; +}; + +enum mod_freesync_state { + FREESYNC_STATE_NONE, + FREESYNC_STATE_FULLSCREEN, + FREESYNC_STATE_STATIC_SCREEN, + FREESYNC_STATE_VIDEO +}; + +enum mod_freesync_user_enable_mask { + FREESYNC_USER_ENABLE_STATIC = 0x1, + FREESYNC_USER_ENABLE_VIDEO = 0x2, + FREESYNC_USER_ENABLE_GAMING = 0x4 +}; + +struct mod_freesync_user_enable { + bool enable_for_static; + bool enable_for_video; + bool enable_for_gaming; +}; + +struct mod_freesync_caps { + bool supported; + unsigned int min_refresh_in_micro_hz; + unsigned int max_refresh_in_micro_hz; + + bool btr_supported; +}; + +struct mod_freesync_params { + enum mod_freesync_state state; + bool enable; + unsigned int update_duration_in_ns; + bool windowed_fullscreen; +}; + +/* + * Add stream to be tracked by module + */ +bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, struct mod_freesync_caps *caps); + +/* + * Remove stream to be tracked by module + */ +bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, + const struct dc_stream *stream); + +/* + * Build additional parameters for dc_stream when creating stream for + * sink to support freesync + */ +void mod_freesync_update_stream(struct mod_freesync *mod_freesync, + struct dc_stream *stream); + +/* + * Update the freesync state flags for each display and program + * freesync accordingly + */ +void mod_freesync_update_state(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + struct mod_freesync_params *freesync_params); + +bool mod_freesync_get_state(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + struct mod_freesync_params *freesync_params); + +bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + struct mod_freesync_user_enable *user_enable); + +bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + struct mod_freesync_user_enable *user_enable); + +void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams); + +void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams); + +void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, + const struct dc_stream **streams, int num_streams, + unsigned int curr_time_stamp); + +#endif diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h new file mode 100644 index 000000000000..a204e8d6cd23 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h @@ -0,0 +1,112 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef MODULES_INC_MOD_POWER_H_ +#define MODULES_INC_MOD_POWER_H_ + +#include "dm_services.h" + +struct mod_power { + int dummy; +}; + +/* VariBright related commands */ +enum varibright_command { + VariBright_Cmd__SetVBLevel = 0, + VariBright_Cmd__UserEnable, + VariBright_Cmd__PreDisplayConfigChange, + VariBright_Cmd__PostDisplayConfigChange, + VariBright_Cmd__SuspendABM, + VariBright_Cmd__ResumeABM, + + VariBright_Cmd__Unknown, +}; + +/* VariBright settings structure */ +struct varibright_info { + enum varibright_command cmd; + + unsigned int level; + bool enable; + bool activate; +}; + +enum dmcu_block_psr_reason { + /* This is a bitfield mask */ + dmcu_block_psr_reason_invalid = 0x0, + dmcu_block_psr_reason_vsync_int = 0x1, + dmcu_block_psr_reason_shared_primary = 0x2, + dmcu_block_psr_reason_unsupported_link_rate = 0x4 +}; + +struct mod_power *mod_power_create(struct dc *dc); + +void mod_power_destroy(struct mod_power *mod_power); + +bool mod_power_add_sink(struct mod_power *mod_power, + const struct dc_sink *sink); + +bool mod_power_remove_sink(struct mod_power *mod_power, + const struct dc_sink *sink); + +bool mod_power_set_backlight(struct mod_power *mod_power, + const struct dc_stream **streams, int num_streams, + unsigned int backlight_8bit); + +bool mod_power_get_backlight(struct mod_power *mod_power, + const struct dc_sink *sink, + unsigned int *backlight_8bit); + +void mod_power_initialize_backlight_caps + (struct mod_power *mod_power); + +unsigned int mod_power_backlight_level_percentage_to_signal + (struct mod_power *mod_power, unsigned int percentage); + +unsigned int mod_power_backlight_level_signal_to_percentage + (struct mod_power *mod_power, unsigned int signalLevel8bit); + +bool mod_power_get_panel_backlight_boundaries + (struct mod_power *mod_power, + unsigned int *min_backlight, + unsigned int *max_backlight, + unsigned int *output_ac_level_percentage, + unsigned int *output_dc_level_percentage); + +bool mod_power_set_smooth_brightness(struct mod_power *mod_power, + const struct dc_sink *sink, bool enable_brightness); + +bool mod_power_notify_mode_change(struct mod_power *mod_power, + const struct dc_stream *stream); + +bool mod_power_varibright_control(struct mod_power *mod_power, + struct varibright_info *input_varibright_info); + +bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason); + +bool mod_power_set_psr_enable(struct mod_power *mod_power, + bool psr_enable); + +#endif /* MODULES_INC_MOD_POWER_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/power/power.c b/drivers/gpu/drm/amd/display/modules/power/power.c new file mode 100644 index 000000000000..ea07e847da0a --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/power/power.c @@ -0,0 +1,784 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "mod_power.h" +#include "dm_services.h" +#include "dc.h" +#include "core_types.h" +#include "core_dc.h" + +#define MOD_POWER_MAX_CONCURRENT_SINKS 32 +#define SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS 500 + +struct sink_caps { + const struct dc_sink *sink; +}; + +struct backlight_state { + unsigned int backlight; + unsigned int frame_ramp; + bool smooth_brightness_enabled; +}; + +struct core_power { + struct mod_power public; + struct dc *dc; + int num_sinks; + struct sink_caps *caps; + struct backlight_state *state; +}; + +union dmcu_abm_set_bl_params { + struct { + unsigned int gradual_change : 1; /* [0:0] */ + unsigned int reserved : 15; /* [15:1] */ + unsigned int frame_ramp : 16; /* [31:16] */ + } bits; + unsigned int u32All; +}; + +/* Backlight cached properties */ +static unsigned int backlight_8bit_lut_array[101]; +static unsigned int ac_level_percentage; +static unsigned int dc_level_percentage; +static bool backlight_caps_valid; +/* we use lazy initialization of backlight capabilities cache */ +static bool backlight_caps_initialized; +/* AC/DC levels initialized later in separate context */ +static bool backlight_def_levels_valid; + +/* ABM cached properties */ +static unsigned int abm_level; +static bool abm_user_enable; +static bool abm_active; + +/*PSR cached properties*/ +static unsigned int block_psr; + +/* Defines default backlight curve F(x) = A(x*x) + Bx + C. + * + * Backlight curve should always satisfy F(0) = min, F(100) = max, + * so polynom coefficients are: + * A is 0.0255 - B/100 - min/10000 - (255-max)/10000 = (max - min)/10000 - B/100 + * B is adjustable factor to modify the curve. + * Bigger B results in less concave curve. B range is [0..(max-min)/100] + * C is backlight minimum + */ +static const unsigned int backlight_curve_coeff_a_factor = 10000; +static const unsigned int backlight_curve_coeff_b = 100; +static const unsigned int backlight_curve_coeff_b_factor = 100; + +/* Minimum and maximum backlight input signal levels */ +static const unsigned int default_min_backlight = 12; +static const unsigned int default_max_backlight = 255; + +/* Other backlight constants */ +static const unsigned int absolute_backlight_max = 255; + +#define MOD_POWER_TO_CORE(mod_power)\ + container_of(mod_power, struct core_power, public) + +static bool check_dc_support(const struct dc *dc) +{ + if (dc->stream_funcs.set_backlight == NULL) + return false; + + return true; +} + +/* Given a specific dc_sink* this function finds its equivalent + * on the dc_sink array and returns the corresponding index + */ +static unsigned int sink_index_from_sink(struct core_power *core_power, + const struct dc_sink *sink) +{ + unsigned int index = 0; + + for (index = 0; index < core_power->num_sinks; index++) + if (core_power->caps[index].sink == sink) + return index; + + /* Could not find sink requested */ + ASSERT(false); + return index; +} + +static unsigned int convertBL8to17(unsigned int backlight_8bit) +{ + unsigned int temp_ulong = backlight_8bit * 0x10101; + unsigned char temp_uchar = + (unsigned char)(((temp_ulong & 0x80) >> 7) & 1); + + temp_ulong = (temp_ulong >> 8) + temp_uchar; + + return temp_ulong; +} + +static uint16_t convertBL8to16(unsigned int backlight_8bit) +{ + return (uint16_t)((backlight_8bit * 0x10101) >> 8); +} + +/*This is used when OS wants to retrieve the current BL. + * We return the 8bit value to OS. + */ +static unsigned int convertBL17to8(unsigned int backlight_17bit) +{ + if (backlight_17bit & 0x10000) + return default_max_backlight; + else + return (backlight_17bit >> 8); +} + +struct mod_power *mod_power_create(struct dc *dc) +{ + struct core_power *core_power = + dm_alloc(sizeof(struct core_power)); + + struct core_dc *core_dc = DC_TO_CORE(dc); + + int i = 0; + + if (core_power == NULL) + goto fail_alloc_context; + + core_power->caps = dm_alloc(sizeof(struct sink_caps) * + MOD_POWER_MAX_CONCURRENT_SINKS); + + if (core_power->caps == NULL) + goto fail_alloc_caps; + + for (i = 0; i < MOD_POWER_MAX_CONCURRENT_SINKS; i++) + core_power->caps[i].sink = NULL; + + core_power->state = dm_alloc(sizeof(struct backlight_state) * + MOD_POWER_MAX_CONCURRENT_SINKS); + + if (core_power->state == NULL) + goto fail_alloc_state; + + core_power->num_sinks = 0; + backlight_caps_valid = false; + + if (dc == NULL) + goto fail_construct; + + core_power->dc = dc; + + if (!check_dc_support(dc)) + goto fail_construct; + + abm_user_enable = false; + abm_active = false; + + return &core_power->public; + +fail_construct: + dm_free(core_power->state); + +fail_alloc_state: + dm_free(core_power->caps); + +fail_alloc_caps: + dm_free(core_power); + +fail_alloc_context: + return NULL; +} + + +void mod_power_destroy(struct mod_power *mod_power) +{ + if (mod_power != NULL) { + int i; + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + dm_free(core_power->state); + + for (i = 0; i < core_power->num_sinks; i++) + dc_sink_release(core_power->caps[i].sink); + + dm_free(core_power->caps); + + dm_free(core_power); + } +} + +bool mod_power_add_sink(struct mod_power *mod_power, + const struct dc_sink *sink) +{ + if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + struct core_dc *core_dc = DC_TO_CORE(core_power->dc); + + if (core_power->num_sinks < MOD_POWER_MAX_CONCURRENT_SINKS) { + dc_sink_retain(sink); + core_power->caps[core_power->num_sinks].sink = sink; + core_power->state[core_power->num_sinks]. + smooth_brightness_enabled = false; + core_power->state[core_power->num_sinks]. + backlight = 100; + core_power->num_sinks++; + return true; + } + + return false; +} + +bool mod_power_remove_sink(struct mod_power *mod_power, + const struct dc_sink *sink) +{ + int i = 0, j = 0; + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + for (i = 0; i < core_power->num_sinks; i++) { + if (core_power->caps[i].sink == sink) { + /* To remove this sink, shift everything after down */ + for (j = i; j < core_power->num_sinks - 1; j++) { + core_power->caps[j].sink = + core_power->caps[j + 1].sink; + + memcpy(&core_power->state[j], + &core_power->state[j + 1], + sizeof(struct backlight_state)); + } + core_power->num_sinks--; + dc_sink_release(sink); + return true; + } + } + return false; +} + +bool mod_power_set_backlight(struct mod_power *mod_power, + const struct dc_stream **streams, int num_streams, + unsigned int backlight_8bit) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + unsigned int frame_ramp = 0; + + unsigned int stream_index, sink_index, vsync_rate_hz; + + union dmcu_abm_set_bl_params params; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + if (streams[stream_index]->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) { + core_power->state[sink_index].backlight = 0; + core_power->state[sink_index].frame_ramp = 0; + core_power->state[sink_index].smooth_brightness_enabled = false; + continue; + } + + sink_index = sink_index_from_sink(core_power, + streams[stream_index]->sink); + + vsync_rate_hz = div64_u64(div64_u64((streams[stream_index]-> + timing.pix_clk_khz * 1000), + streams[stream_index]->timing.v_total), + streams[stream_index]->timing.h_total); + + core_power->state[sink_index].backlight = backlight_8bit; + + if (core_power->state[sink_index].smooth_brightness_enabled) + frame_ramp = ((vsync_rate_hz * + SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS) + 500) + / 1000; + else + frame_ramp = 0; + + core_power->state[sink_index].frame_ramp = frame_ramp; + } + + params.u32All = 0; + params.bits.gradual_change = (frame_ramp > 0); + params.bits.frame_ramp = frame_ramp; + + core_power->dc->stream_funcs.set_backlight + (core_power->dc, backlight_8bit, params.u32All, streams[0]); + + return true; +} + +bool mod_power_get_backlight(struct mod_power *mod_power, + const struct dc_sink *sink, + unsigned int *backlight_8bit) +{ + if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + unsigned int sink_index = sink_index_from_sink(core_power, sink); + + *backlight_8bit = core_power->state[sink_index].backlight; + + return true; +} + +/* hard coded to default backlight curve. */ +void mod_power_initialize_backlight_caps(struct mod_power + *mod_power) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + struct core_dc *core_dc = DC_TO_CORE(core_power->dc); + unsigned int i; + + backlight_caps_initialized = true; + + struct dm_acpi_atif_backlight_caps *pExtCaps = NULL; + bool customCurvePresent = false; + bool customMinMaxPresent = false; + bool customDefLevelsPresent = false; + + /* Allocate memory for ATIF output + * (do not want to use 256 bytes on the stack) + */ + pExtCaps = (struct dm_acpi_atif_backlight_caps *) + (dm_alloc(sizeof(struct dm_acpi_atif_backlight_caps))); + if (pExtCaps == NULL) + return; + + /* Retrieve ACPI extended brightness caps */ + if (dm_query_extended_brightness_caps + (core_dc->ctx, AcpiDisplayType_LCD1, pExtCaps)) { + ac_level_percentage = pExtCaps->acLevelPercentage; + dc_level_percentage = pExtCaps->dcLevelPercentage; + customMinMaxPresent = true; + customDefLevelsPresent = true; + customCurvePresent = (pExtCaps->numOfDataPoints > 0); + + ASSERT(pExtCaps->numOfDataPoints <= 99); + } else { + dm_free(pExtCaps); + return; + } + + if (customMinMaxPresent) + backlight_8bit_lut_array[0] = pExtCaps->minInputSignal; + else + backlight_8bit_lut_array[0] = default_min_backlight; + + if (customMinMaxPresent) + backlight_8bit_lut_array[100] = pExtCaps->maxInputSignal; + else + backlight_8bit_lut_array[100] = default_max_backlight; + + ASSERT(backlight_8bit_lut_array[100] <= absolute_backlight_max); + ASSERT(backlight_8bit_lut_array[0] <= + backlight_8bit_lut_array[100]); + + /* Just to make sure we use valid values */ + if (backlight_8bit_lut_array[100] > absolute_backlight_max) + backlight_8bit_lut_array[100] = absolute_backlight_max; + if (backlight_8bit_lut_array[0] > backlight_8bit_lut_array[100]) { + unsigned int swap; + + swap = backlight_8bit_lut_array[0]; + backlight_8bit_lut_array[0] = backlight_8bit_lut_array[100]; + backlight_8bit_lut_array[100] = swap; + } + + /* Build backlight translation table for custom curve */ + if (customCurvePresent) { + unsigned int index = 1; + unsigned int numOfDataPoints = + (pExtCaps->numOfDataPoints <= 99 ? + pExtCaps->numOfDataPoints : 99); + + /* Filling translation table from data points - + * between every two provided data points we + * lineary interpolate missing values + */ + for (i = 0; i < numOfDataPoints; i++) { + /* Clamp signal level between min and max + * (since min and max might come other + * soruce like registry) + */ + unsigned int luminance = + pExtCaps->dataPoints[i].luminance; + unsigned int signalLevel = + pExtCaps->dataPoints[i].signalLevel; + + if (signalLevel < backlight_8bit_lut_array[0]) + signalLevel = backlight_8bit_lut_array[0]; + if (signalLevel > backlight_8bit_lut_array[100]) + signalLevel = backlight_8bit_lut_array[100]; + + /* Lineary interpolate missing values */ + if (index < luminance) { + unsigned int baseValue = + backlight_8bit_lut_array[index-1]; + unsigned int deltaSignal = + signalLevel - baseValue; + unsigned int deltaLuma = + luminance - index + 1; + unsigned int step = deltaSignal; + + for (; index < luminance; index++) { + backlight_8bit_lut_array[index] = + baseValue + (step / deltaLuma); + step += deltaSignal; + } + } + + /* Now [index == luminance], + * so we can add data point to the translation table + */ + backlight_8bit_lut_array[index++] = signalLevel; + } + + /* Complete the final segment of interpolation - + * between last datapoint and maximum value + */ + if (index < 100) { + unsigned int baseValue = + backlight_8bit_lut_array[index-1]; + unsigned int deltaSignal = + backlight_8bit_lut_array[100] - + baseValue; + unsigned int deltaLuma = 100 - index + 1; + unsigned int step = deltaSignal; + + for (; index < 100; index++) { + backlight_8bit_lut_array[index] = + baseValue + (step / deltaLuma); + step += deltaSignal; + } + } + /* Build backlight translation table based on default curve */ + } else { + unsigned int delta = + backlight_8bit_lut_array[100] - + backlight_8bit_lut_array[0]; + unsigned int coeffC = backlight_8bit_lut_array[0]; + unsigned int coeffB = + (backlight_curve_coeff_b < delta ? + backlight_curve_coeff_b : delta); + unsigned int coeffA = delta - coeffB; /* coeffB is B*100 */ + + for (i = 1; i < 100; i++) { + backlight_8bit_lut_array[i] = + (coeffA * i * i) / + backlight_curve_coeff_a_factor + + (coeffB * i) / + backlight_curve_coeff_b_factor + + coeffC; + } + } + + if (pExtCaps != NULL) + dm_free(pExtCaps); + + /* Successfully initialized */ + backlight_caps_valid = true; + backlight_def_levels_valid = customDefLevelsPresent; +} + +unsigned int mod_power_backlight_level_percentage_to_signal( + struct mod_power *mod_power, unsigned int percentage) +{ + /* Do lazy initialization of backlight capabilities*/ + if (!backlight_caps_initialized) + mod_power_initialize_backlight_caps(mod_power); + + /* Since the translation table is indexed by percentage, + * we simply return backlight value at given percent + */ + if (backlight_caps_valid && percentage <= 100) + return backlight_8bit_lut_array[percentage]; + + return -1; +} + +unsigned int mod_power_backlight_level_signal_to_percentage( + struct mod_power *mod_power, + unsigned int signalLevel8bit) +{ + unsigned int invalid_backlight = (unsigned int)(-1); + /* Do lazy initialization of backlight capabilities */ + if (!backlight_caps_initialized) + mod_power_initialize_backlight_caps(mod_power); + + /* If customer curve cannot convert to differentiated value near min + * it is important to report 0 for min signal to pass setting "Dimmed" + * setting in HCK brightness2 tests. + */ + if (signalLevel8bit <= backlight_8bit_lut_array[0]) + return 0; + + /* Since the translation table is indexed by percentage + * we need to do a binary search over the array + * Another option would be to guess entry based on linear distribution + * and then do linear search in correct direction + */ + if (backlight_caps_valid && signalLevel8bit <= + absolute_backlight_max) { + unsigned int min = 0; + unsigned int max = 100; + unsigned int mid = invalid_backlight; + + while (max >= min) { + mid = (min + max) / 2; /* floor of half range */ + + if (backlight_8bit_lut_array[mid] < signalLevel8bit) + min = mid + 1; + else if (backlight_8bit_lut_array[mid] > + signalLevel8bit) + max = mid - 1; + else + break; + + if (max == 0 || max == 1) + return invalid_backlight; + } + return mid; + } + + return invalid_backlight; +} + + +bool mod_power_get_panel_backlight_boundaries( + struct mod_power *mod_power, + unsigned int *min_backlight, + unsigned int *max_backlight, + unsigned int *output_ac_level_percentage, + unsigned int *output_dc_level_percentage) +{ + /* Do lazy initialization of backlight capabilities */ + if (!backlight_caps_initialized) + mod_power_initialize_backlight_caps(mod_power); + + /* If cache was successfully updated, + * copy the values to output structure and return success + */ + if (backlight_caps_valid) { + *min_backlight = backlight_8bit_lut_array[0]; + *max_backlight = backlight_8bit_lut_array[100]; + + *output_ac_level_percentage = ac_level_percentage; + *output_dc_level_percentage = dc_level_percentage; + + return true; + } + + return false; +} + +bool mod_power_set_smooth_brightness(struct mod_power *mod_power, + const struct dc_sink *sink, bool enable_brightness) +{ + if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + unsigned int sink_index = sink_index_from_sink(core_power, sink); + + core_power->state[sink_index].smooth_brightness_enabled + = enable_brightness; + return true; +} + +bool mod_power_notify_mode_change(struct mod_power *mod_power, + const struct dc_stream *stream) +{ + if (stream->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) + return false; + + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + unsigned int sink_index = sink_index_from_sink(core_power, + stream->sink); + unsigned int frame_ramp = core_power->state[sink_index].frame_ramp; + union dmcu_abm_set_bl_params params; + + params.u32All = 0; + params.bits.gradual_change = (frame_ramp > 0); + params.bits.frame_ramp = frame_ramp; + + core_power->dc->stream_funcs.set_backlight + (core_power->dc, + core_power->state[sink_index].backlight, + params.u32All, stream); + + core_power->dc->stream_funcs.setup_psr + (core_power->dc, stream); + + return true; +} + + +static bool mod_power_abm_feature_enable(struct mod_power + *mod_power, bool enable) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + if (abm_user_enable == enable) + return true; + + abm_user_enable = enable; + + if (enable) { + if (abm_level != 0 && abm_active) + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, abm_level); + } else { + if (abm_level != 0 && abm_active) { + abm_level = 0; + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, abm_level); + } + } + + return true; +} + +static bool mod_power_abm_activate(struct mod_power + *mod_power, bool activate) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + if (abm_active == activate) + return true; + + abm_active = activate; + + if (activate) { + if (abm_level != 0 && abm_user_enable) + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, abm_level); + } else { + if (abm_level != 0 && abm_user_enable) { + abm_level = 0; + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, abm_level); + } + } + + return true; +} + +static bool mod_power_abm_set_level(struct mod_power *mod_power, + unsigned int level) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + if (abm_level == level) + return true; + + if (abm_active && abm_user_enable && level == 0) + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, 0); + else if (abm_active && abm_user_enable && level != 0) + core_power->dc->stream_funcs.set_abm_level + (core_power->dc, level); + + abm_level = level; + + return true; +} + +bool mod_power_varibright_control(struct mod_power *mod_power, + struct varibright_info *input_varibright_info) +{ + switch (input_varibright_info->cmd) { + case VariBright_Cmd__SetVBLevel: + { + /* Set VariBright user level. */ + mod_power_abm_set_level(mod_power, + input_varibright_info->level); + } + break; + + case VariBright_Cmd__UserEnable: + { + /* Set VariBright user enable state. */ + mod_power_abm_feature_enable(mod_power, + input_varibright_info->enable); + } + break; + + case VariBright_Cmd__PostDisplayConfigChange: + { + /* Set VariBright user level. */ + mod_power_abm_set_level(mod_power, + input_varibright_info->level); + + /* Set VariBright user enable state. */ + mod_power_abm_feature_enable(mod_power, + input_varibright_info->enable); + + /* Set VariBright activate based on power state. */ + mod_power_abm_activate(mod_power, + input_varibright_info->activate); + } + break; + + default: + { + return false; + } + break; + } + + return true; +} + +bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason) +{ + if (block_enable) + block_psr |= reason; + else + block_psr &= ~reason; + + return true; +} + + +bool mod_power_set_psr_enable(struct mod_power *mod_power, + bool psr_enable) +{ + struct core_power *core_power = + MOD_POWER_TO_CORE(mod_power); + + if (block_psr == 0) + return core_power->dc->stream_funcs.set_psr_enable + (core_power->dc, psr_enable); + + return false; +} + + -- GitLab From 39cc5be276d4ea7d64531f6f207e57f27bdba47d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 13 Dec 2016 15:42:48 -0500 Subject: [PATCH 0065/2898] drm/amd/dc/dm: remove redundant display structs Now that the mc_access functions are gone, we no longer need separate structs for all the different dce families in dm. Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 60 ++----------------- 1 file changed, 4 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ae4ba7777839..fa55147d0c47 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1386,48 +1386,7 @@ static int amdgpu_notify_freesync(struct drm_device *dev, void *data, return r; } -#ifdef CONFIG_DRM_AMDGPU_CIK -static const struct amdgpu_display_funcs dm_dce_v8_0_display_funcs = { - .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ - .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ - .vblank_wait = NULL, - .backlight_set_level = - dm_set_backlight_level,/* called unconditionally */ - .backlight_get_level = - dm_get_backlight_level,/* called unconditionally */ - .hpd_sense = NULL,/* called unconditionally */ - .hpd_set_polarity = NULL, /* called unconditionally */ - .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ - .page_flip = dm_page_flip, /* called unconditionally */ - .page_flip_get_scanoutpos = - dm_crtc_get_scanoutpos,/* called unconditionally */ - .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ - .add_connector = NULL, /* VBIOS parsing. DAL does it. */ - .notify_freesync = amdgpu_notify_freesync, -}; -#endif - -static const struct amdgpu_display_funcs dm_dce_v10_0_display_funcs = { - .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ - .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ - .vblank_wait = NULL, - .backlight_set_level = - dm_set_backlight_level,/* called unconditionally */ - .backlight_get_level = - dm_get_backlight_level,/* called unconditionally */ - .hpd_sense = NULL,/* called unconditionally */ - .hpd_set_polarity = NULL, /* called unconditionally */ - .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ - .page_flip = dm_page_flip, /* called unconditionally */ - .page_flip_get_scanoutpos = - dm_crtc_get_scanoutpos,/* called unconditionally */ - .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ - .add_connector = NULL, /* VBIOS parsing. DAL does it. */ - .notify_freesync = amdgpu_notify_freesync, - -}; - -static const struct amdgpu_display_funcs dm_dce_v11_0_display_funcs = { +static const struct amdgpu_display_funcs dm_display_funcs = { .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ .vblank_wait = NULL, @@ -1491,52 +1450,41 @@ static int dm_early_init(void *handle) adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; -#ifdef CONFIG_DRM_AMDGPU_CIK - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v8_0_display_funcs; -#endif break; case CHIP_FIJI: case CHIP_TONGA: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 7; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v10_0_display_funcs; break; case CHIP_CARRIZO: adev->mode_info.num_crtc = 3; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; break; case CHIP_STONEY: adev->mode_info.num_crtc = 2; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; break; case CHIP_POLARIS11: adev->mode_info.num_crtc = 5; adev->mode_info.num_hpd = 5; adev->mode_info.num_dig = 5; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; break; case CHIP_POLARIS10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; - if (adev->mode_info.funcs == NULL) - adev->mode_info.funcs = &dm_dce_v11_0_display_funcs; break; default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); return -EINVAL; } + if (adev->mode_info.funcs == NULL) + adev->mode_info.funcs = &dm_display_funcs; + /* Note: Do NOT change adev->audio_endpt_rreg and * adev->audio_endpt_wreg because they are initialised in * amdgpu_device_init() */ -- GitLab From 56bc1c42610aa6328e6c4b222dc076acffb40243 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Wed, 7 Dec 2016 11:28:03 -0500 Subject: [PATCH 0066/2898] drm/amd/display: Fix hdmi not lighting up on Hawaii. Signed-off-by: Zeyu Fan Acked-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 86e55d028cbf..10b70ca29ba3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1233,7 +1233,7 @@ void dce110_link_encoder_enable_tmds_output( /* Enable the PHY */ cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.engine_id = enc->preferred_engine; cntl.transmitter = enc110->base.transmitter; cntl.pll_id = clock_source; if (hdmi) { -- GitLab From 8e545104aa05b5e0720fd2042e2f9729f9c13744 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 6 Dec 2016 12:59:52 -0500 Subject: [PATCH 0067/2898] drm/amd/display: Fix bugs causing Hawaii and Bonaire not light up. Signed-off-by: Zeyu Fan Acked-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../amd/display/dc/bios/dce110/command_table_helper_dce110.c | 2 +- .../amd/display/dc/bios/dce112/command_table_helper_dce112.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c index dff82dd11721..8049320e8b03 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -186,7 +186,7 @@ static uint8_t dig_encoder_sel_to_atom(enum engine_id id) break; } - return atom_dig_encoder_sel; + return 0; } static bool clock_source_id_to_atom( diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c index 8b72aa588b86..48e59963dad4 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -183,7 +183,7 @@ static uint8_t dig_encoder_sel_to_atom(enum engine_id id) break; } - return atom_dig_encoder_sel; + return 0; } static bool clock_source_id_to_atom( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 10b70ca29ba3..c73d6054cdda 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1281,7 +1281,7 @@ void dce110_link_encoder_enable_dp_output( configure_encoder(enc110, link_settings); cntl.action = TRANSMITTER_CONTROL_ENABLE; - cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.engine_id = enc->preferred_engine; cntl.transmitter = enc110->base.transmitter; cntl.pll_id = clock_source; cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; -- GitLab From ead964f24e111aa5ba6ec4c2ee15ae20f11a121a Mon Sep 17 00:00:00 2001 From: jimqu Date: Mon, 28 Nov 2016 08:05:46 +0800 Subject: [PATCH 0068/2898] drm/amd/display: Fix memory corruption issue. temp_flip_context is always same as current_context, and the current_context will be freed in dc_commit_targets(), but temp_flip_context will be used in dc_update_surfaces_for_target(). Signed-off-by: JimQu Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f7638f84421b..424a7d4b8731 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1096,8 +1096,12 @@ bool dc_commit_targets( resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); + if (core_dc->temp_flip_context != core_dc->current_context) { + dm_free(core_dc->temp_flip_context); + core_dc->temp_flip_context = core_dc->current_context; + } core_dc->current_context = context; + memset(core_dc->temp_flip_context, 0, sizeof(*core_dc->temp_flip_context)); return (result == DC_OK); -- GitLab From 1293b4339fb09693bdfc938495b671f0ac9bfae5 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Tue, 29 Nov 2016 17:56:05 -0500 Subject: [PATCH 0069/2898] drm/amd/display: Block 3D Timings - we don't yet support 3D timings in DAL3 - somehow a code path was being executed that resulted in HW programming for a 3D timing, which caused 3D displays to show half the desktop in one frame, and the other half of the desktop in the next frame - blocking all 3D timings in timing generator validation until we implement proper 3D timing support Signed-off-by: Joshua Aberback Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index b1c97125f6fb..12a258763ef1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1113,6 +1113,10 @@ bool dce110_timing_generator_validate_timing( if (!timing) return false; + /* Currently we don't support 3D, so block all 3D timings */ + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) + return false; + /* Check maximum number of pixels supported by Timing Generator * (Currently will never fail, in order to fail needs display which * needs more than 8192 horizontal and -- GitLab From 0971d745f68bcd6eeda1d1a7420142dc41fac798 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 30 Nov 2016 12:10:35 -0500 Subject: [PATCH 0070/2898] drm/amd/display: Update rgb limited range csc matrix calculation The issue causes hue adjustment for rgb limited range color space programmed wrong. Update calculation formula for rgb limited range Signed-off-by: Wenjing Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/color/color.c | 300 +++++++++++++----- 1 file changed, 216 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index cf030b18f6a9..30d09d358576 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -854,26 +854,60 @@ static void calculate_rgb_matrix_legacy(struct core_color *core_color, rgb_matrix[11] = grph_bright; } -static void calculate_rgb_limited_range_matrix(struct core_color *core_color, - unsigned int sink_index, struct fixed31_32 *rgb_matrix) +static void calculate_rgb_limited_range_matrix_legacy( + struct core_color *core_color, unsigned int sink_index, + struct fixed31_32 *rgb_matrix) { - struct fixed31_32 ideal[12]; - - static const int32_t matrix_[] = { - 85546875, 0, 0, 6250000, - 0, 85546875, 0, 6250000, - 0, 0, 85546875, 6250000 - }; - - uint32_t i = 0; + const struct fixed31_32 k1 = + dal_fixed31_32_from_fraction(701000, 1000000); + const struct fixed31_32 k2 = + dal_fixed31_32_from_fraction(236568, 1000000); + const struct fixed31_32 k3 = + dal_fixed31_32_from_fraction(-587000, 1000000); + const struct fixed31_32 k4 = + dal_fixed31_32_from_fraction(464432, 1000000); + const struct fixed31_32 k5 = + dal_fixed31_32_from_fraction(-114000, 1000000); + const struct fixed31_32 k6 = + dal_fixed31_32_from_fraction(-701000, 1000000); + const struct fixed31_32 k7 = + dal_fixed31_32_from_fraction(-299000, 1000000); + const struct fixed31_32 k8 = + dal_fixed31_32_from_fraction(-292569, 1000000); + const struct fixed31_32 k9 = + dal_fixed31_32_from_fraction(413000, 1000000); + const struct fixed31_32 k10 = + dal_fixed31_32_from_fraction(-92482, 1000000); + const struct fixed31_32 k11 = + dal_fixed31_32_from_fraction(-114000, 1000000); + const struct fixed31_32 k12 = + dal_fixed31_32_from_fraction(385051, 1000000); + const struct fixed31_32 k13 = + dal_fixed31_32_from_fraction(-299000, 1000000); + const struct fixed31_32 k14 = + dal_fixed31_32_from_fraction(886000, 1000000); + const struct fixed31_32 k15 = + dal_fixed31_32_from_fraction(-587000, 1000000); + const struct fixed31_32 k16 = + dal_fixed31_32_from_fraction(-741914, 1000000); + const struct fixed31_32 k17 = + dal_fixed31_32_from_fraction(886000, 1000000); + const struct fixed31_32 k18 = + dal_fixed31_32_from_fraction(-144086, 1000000); - do { - ideal[i] = dal_fixed31_32_from_fraction( - matrix_[i], - 100000000); - ++i; - } while (i != ARRAY_SIZE(matrix_)); + const struct fixed31_32 luma_r = + dal_fixed31_32_from_fraction(299, 1000); + const struct fixed31_32 luma_g = + dal_fixed31_32_from_fraction(587, 1000); + const struct fixed31_32 luma_b = + dal_fixed31_32_from_fraction(114, 1000); + const struct fixed31_32 luma_scale = + dal_fixed31_32_from_fraction(875855, 1000000); + const struct fixed31_32 rgb_scale = + dal_fixed31_32_from_fraction(85546875, 100000000); + const struct fixed31_32 rgb_bias = + dal_fixed31_32_from_fraction(625, 10000); struct fixed31_32 grph_cont; struct fixed31_32 grph_sat; @@ -885,84 +919,182 @@ static void calculate_rgb_limited_range_matrix(struct core_color *core_color, core_color, sink_index, &grph_cont, &grph_sat, &grph_bright, &sin_grph_hue, &cos_grph_hue); - const struct fixed31_32 multiplier = - dal_fixed31_32_mul(grph_cont, grph_sat); - - rgb_matrix[8] = dal_fixed31_32_mul(ideal[0], grph_cont); + /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +*/ + /* Sin(GrphHue) * K2))*/ + /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)*/ + rgb_matrix[0] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k1), + dal_fixed31_32_mul(sin_grph_hue, k2)); + /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ + rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/ + rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/ + /* K2))*/ + rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]); + /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + */ + /* Sin(GrphHue) * K2))*/ + rgb_matrix[0] = dal_fixed31_32_mul(luma_scale, rgb_matrix[0]); - rgb_matrix[9] = dal_fixed31_32_mul(ideal[1], grph_cont); + /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/ + /* Sin(GrphHue) * K4))*/ + /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ + rgb_matrix[1] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k3), + dal_fixed31_32_mul(sin_grph_hue, k4)); + /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ + rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/ + rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/ + /* K4))*/ + rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]); + /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K3 + */ + /* Sin(GrphHue) * K4))*/ + rgb_matrix[1] = dal_fixed31_32_mul(luma_scale, rgb_matrix[1]); - rgb_matrix[10] = dal_fixed31_32_mul(ideal[2], grph_cont); + /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/ + /* Sin(GrphHue) * K6))*/ + /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k5), + dal_fixed31_32_mul(sin_grph_hue, k6)); + /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]); + /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ + rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/ + /* K6))*/ + rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]); + /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * K5 + */ + /* Sin(GrphHue) * K6))*/ + rgb_matrix[2] = dal_fixed31_32_mul(luma_scale, rgb_matrix[2]); - rgb_matrix[11] = dal_fixed31_32_add( - ideal[3], - dal_fixed31_32_mul( - grph_bright, - dal_fixed31_32_from_fraction(86, 100))); + /* COEF_1_4 = RGBBias + RGBScale * GrphBright*/ + rgb_matrix[3] = dal_fixed31_32_add( + rgb_bias, + dal_fixed31_32_mul(rgb_scale, grph_bright)); - rgb_matrix[0] = dal_fixed31_32_mul( - multiplier, + /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/ + /* Sin(GrphHue) * K8))*/ + /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ + rgb_matrix[4] = dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[8], - sin_grph_hue), - dal_fixed31_32_mul( - ideal[4], - cos_grph_hue))); + dal_fixed31_32_mul(cos_grph_hue, k7), + dal_fixed31_32_mul(sin_grph_hue, k8)); + /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ + rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/ + rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/ + /* K8))*/ + rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]); + /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + */ + /* Sin(GrphHue) * K8))*/ + rgb_matrix[4] = dal_fixed31_32_mul(luma_scale, rgb_matrix[4]); - rgb_matrix[1] = dal_fixed31_32_mul( - multiplier, + /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/ + /* Sin(GrphHue) * K10))*/ + /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[9], - sin_grph_hue), - dal_fixed31_32_mul( - ideal[5], - cos_grph_hue))); + dal_fixed31_32_mul(cos_grph_hue, k9), + dal_fixed31_32_mul(sin_grph_hue, k10)); + /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/ + /* K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]); + /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K9 + */ + /* Sin(GrphHue) * K10))*/ + rgb_matrix[5] = dal_fixed31_32_mul(luma_scale, rgb_matrix[5]); - rgb_matrix[2] = dal_fixed31_32_mul( - multiplier, + /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/ + /* Sin(GrphHue) * K12))*/ + /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[10], - sin_grph_hue), - dal_fixed31_32_mul( - ideal[6], - cos_grph_hue))); + dal_fixed31_32_mul(cos_grph_hue, k11), + dal_fixed31_32_mul(sin_grph_hue, k12)); + /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]); + /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ + rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/ + /* K12))*/ + rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]); + /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * K11 +*/ + /* Sin(GrphHue) * K12)) */ + rgb_matrix[6] = dal_fixed31_32_mul(luma_scale, rgb_matrix[6]); - rgb_matrix[3] = ideal[7]; + /* COEF_2_4 = RGBBias + RGBScale * GrphBright*/ + rgb_matrix[7] = dal_fixed31_32_add( + rgb_bias, + dal_fixed31_32_mul(rgb_scale, grph_bright)); - rgb_matrix[4] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[8], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[4], - sin_grph_hue))); + /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ + /* Sin(GrphHue) * K14))*/ + /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k13), + dal_fixed31_32_mul(sin_grph_hue, k14)); + /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]); + /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ + rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]); + /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/ + /* K14)) */ + rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]); + /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ + /* Sin(GrphHue) * K14))*/ + rgb_matrix[8] = dal_fixed31_32_mul(luma_scale, rgb_matrix[8]); - rgb_matrix[5] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[9], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[5], - sin_grph_hue))); + /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/ + /* Sin(GrphHue) * K16)) */ + /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ + rgb_matrix[9] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k15), + dal_fixed31_32_mul(sin_grph_hue, k16)); + /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ + rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]); + /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ + rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]); + /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/ + /* K16)) */ + rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]); + /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K15 + */ + /* Sin(GrphHue) * K16))*/ + rgb_matrix[9] = dal_fixed31_32_mul(luma_scale, rgb_matrix[9]); - rgb_matrix[6] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[10], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[6], - sin_grph_hue))); + /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/ + /* Sin(GrphHue) * K18)) */ + /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = + dal_fixed31_32_add( + dal_fixed31_32_mul(cos_grph_hue, k17), + dal_fixed31_32_mul(sin_grph_hue, k18)); + /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]); + /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ + rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]); + /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/ + /* K18)) */ + rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]); + /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * */ + /* K17 + Sin(GrphHue) * K18))*/ + rgb_matrix[10] = dal_fixed31_32_mul(luma_scale, rgb_matrix[10]); - rgb_matrix[7] = ideal[11]; + /* COEF_3_4 = RGBBias + RGBScale * GrphBright */ + rgb_matrix[11] = dal_fixed31_32_add( + rgb_bias, + dal_fixed31_32_mul(rgb_scale, grph_bright)); } static void calculate_yuv_matrix(struct core_color *core_color, @@ -1110,9 +1242,9 @@ static void calculate_csc_matrix(struct core_color *core_color, (csc_matrix, fixed_csc_matrix, 12); break; case COLOR_SPACE_SRGB_LIMITED: - calculate_rgb_limited_range_matrix(core_color, sink_index, - fixed_csc_matrix); - convert_float_matrix(csc_matrix, fixed_csc_matrix, 12); + calculate_rgb_limited_range_matrix_legacy( + core_color, sink_index, fixed_csc_matrix); + convert_float_matrix_legacy(csc_matrix, fixed_csc_matrix, 12); break; case COLOR_SPACE_YCBCR601: case COLOR_SPACE_YCBCR709: -- GitLab From b32c34ae480b5f16e2a8efab56e39d58a191fd1e Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 1 Dec 2016 09:43:14 -0500 Subject: [PATCH 0071/2898] drm/amd/display: Removing extra newline Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/os_types.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index 459a2741eccb..7f0c282a1466 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -54,7 +54,6 @@ #define dm_min(x, y) min(x, y) #define dm_max(x, y) max(x, y) - #endif -- GitLab From f60ea68d43798d9c366a8a38d4602fb7f12786e7 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 1 Dec 2016 10:00:09 -0500 Subject: [PATCH 0072/2898] drm/amd/display: Remove obsolete LATEST_ATOM_BIOS_SUPPORT Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/Makefile | 1 - .../gpu/drm/amd/display/dc/bios/command_table.c | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 9ba677f0ff01..876614d37412 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -20,5 +20,4 @@ AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce80/command_table_helper_dce80.o ############################################################################### AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o -ccflags-y += -DLATEST_ATOM_BIOS_SUPPORT AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 51f6052eac96..d0eedb6235fe 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -115,11 +115,9 @@ static enum bp_result encoder_control_digx_v4( struct bios_parser *bp, struct bp_encoder_control *cntl); -#ifdef LATEST_ATOM_BIOS_SUPPORT static enum bp_result encoder_control_digx_v5( struct bios_parser *bp, struct bp_encoder_control *cntl); -#endif static void init_encoder_control_dig_v1(struct bios_parser *bp); @@ -136,11 +134,9 @@ static void init_dig_encoder_control(struct bios_parser *bp) bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4; break; -#ifdef LATEST_ATOM_BIOS_SUPPORT case 5: bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5; break; -#endif default: init_encoder_control_dig_v1(bp); @@ -290,7 +286,6 @@ static enum bp_result encoder_control_digx_v4( return result; } -#ifdef LATEST_ATOM_BIOS_SUPPORT static enum bp_result encoder_control_digx_v5( struct bios_parser *bp, struct bp_encoder_control *cntl) @@ -348,7 +343,6 @@ static enum bp_result encoder_control_digx_v5( return result; } -#endif /******************************************************************************* ******************************************************************************** @@ -829,7 +823,6 @@ static enum bp_result transmitter_control_v1_6( struct bp_transmitter_control *cntl) { enum bp_result result = BP_RESULT_FAILURE; -#ifdef LATEST_ATOM_BIOS_SUPPORT const struct command_table_helper *cmd = bp->cmd_helper; DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params; @@ -883,7 +876,6 @@ static enum bp_result transmitter_control_v1_6( if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params)) result = BP_RESULT_OK; -#endif return result; } @@ -1141,7 +1133,6 @@ static enum bp_result set_pixel_clock_v7( struct bp_pixel_clock_parameters *bp_params) { enum bp_result result = BP_RESULT_FAILURE; -#ifdef LATEST_ATOM_BIOS_SUPPORT PIXEL_CLOCK_PARAMETERS_V7 clk; uint8_t controller_id; uint32_t pll_id; @@ -1203,7 +1194,6 @@ static enum bp_result set_pixel_clock_v7( if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk)) result = BP_RESULT_OK; } -#endif return result; } @@ -2539,15 +2529,12 @@ static enum bp_result enable_disp_power_gating_v2_1( ** ******************************************************************************** *******************************************************************************/ -#ifdef LATEST_ATOM_BIOS_SUPPORT static enum bp_result set_dce_clock_v2_1( struct bios_parser *bp, struct bp_set_dce_clock_parameters *bp_params); -#endif static void init_set_dce_clock(struct bios_parser *bp) { -#ifdef LATEST_ATOM_BIOS_SUPPORT switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) { case 1: bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; @@ -2556,10 +2543,8 @@ static void init_set_dce_clock(struct bios_parser *bp) bp->cmd_tbl.set_dce_clock = NULL; break; } -#endif } -#ifdef LATEST_ATOM_BIOS_SUPPORT static enum bp_result set_dce_clock_v2_1( struct bios_parser *bp, struct bp_set_dce_clock_parameters *bp_params) @@ -2606,4 +2591,3 @@ static enum bp_result set_dce_clock_v2_1( return result; } -#endif -- GitLab From 22f050be1558a878f0fec34e8efbb89f5c17a5eb Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 30 Nov 2016 16:23:16 -0500 Subject: [PATCH 0073/2898] drm/amd/display: fix REG_SET_5 macro Signed-off-by: Roman Li Reviewed-by: Tony Cheng Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index 159b2c519f2b..dbc8424f7b69 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -84,7 +84,7 @@ #define REG_SET_5(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ f5, v5) \ - REG_SET_N(reg, 6, init_value, \ + REG_SET_N(reg, 5, init_value, \ FN(reg, f1), v1,\ FN(reg, f2), v2,\ FN(reg, f3), v3,\ -- GitLab From 197062bf12d7a516ea96e24859fe5981e30ea9ff Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 30 Nov 2016 16:15:47 -0500 Subject: [PATCH 0074/2898] drm/amd/display: refactor DCE11 DVVM - move to new programming style - clean up table to make it obvious what we are programming Signed-off-by: Tony Cheng Reviewed-by: Zeyu Fan Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_mem_input.c | 135 +++++++++++++++++- .../drm/amd/display/dc/dce/dce_mem_input.h | 59 +++++++- .../amd/display/dc/dce100/dce100_resource.c | 6 +- .../amd/display/dc/dce110/dce110_mem_input.c | 113 +-------------- .../amd/display/dc/dce110/dce110_mem_input.h | 11 -- .../display/dc/dce110/dce110_mem_input_v.c | 8 +- .../amd/display/dc/dce110/dce110_resource.c | 6 +- .../amd/display/dc/dce112/dce112_resource.c | 6 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 6 +- .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 +- 10 files changed, 201 insertions(+), 153 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 654731cccdcd..fd8a49afbec6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -35,6 +35,137 @@ #define FN(reg_name, field_name) \ mi->shifts->field_name, mi->masks->field_name +struct pte_setting { + unsigned int bpp; + unsigned int page_width; + unsigned int page_height; + unsigned char min_pte_before_flip_horiz_scan; + unsigned char min_pte_before_flip_vert_scan; + unsigned char pte_req_per_chunk; + unsigned char param_6; + unsigned char param_7; + unsigned char param_8; +}; + +enum mi_bits_per_pixel { + mi_bpp_8 = 0, + mi_bpp_16, + mi_bpp_32, + mi_bpp_64, + mi_bpp_count, +}; + +enum mi_tiling_format { + mi_tiling_linear = 0, + mi_tiling_1D, + mi_tiling_2D, + mi_tiling_count, +}; + +static const struct pte_setting pte_settings[mi_tiling_count][mi_bpp_count] = { + [mi_tiling_linear] = { + { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, + { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, + { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, + { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ + }, + [mi_tiling_1D] = { + { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ + { 16, 256, 8, 2, 0, 1, 0, 0, 0}, + { 32, 128, 8, 4, 0, 1, 0, 0, 0}, + { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ + }, + [mi_tiling_2D] = { + { 8, 64, 64, 8, 8, 1, 4, 0, 0}, + { 16, 64, 32, 8, 16, 1, 8, 0, 0}, + { 32, 32, 32, 16, 16, 1, 8, 0, 0}, + { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ + }, +}; + +static enum mi_bits_per_pixel get_mi_bpp( + enum surface_pixel_format format) +{ + if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) + return mi_bpp_64; + else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) + return mi_bpp_32; + else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555) + return mi_bpp_16; + else + return mi_bpp_8; +} + +static enum mi_tiling_format get_mi_tiling( + union dc_tiling_info *tiling_info) +{ + switch (tiling_info->gfx8.array_mode) { + case DC_ARRAY_1D_TILED_THIN1: + case DC_ARRAY_1D_TILED_THICK: + case DC_ARRAY_PRT_TILED_THIN1: + return mi_tiling_1D; + case DC_ARRAY_2D_TILED_THIN1: + case DC_ARRAY_2D_TILED_THICK: + case DC_ARRAY_2D_TILED_X_THICK: + case DC_ARRAY_PRT_2D_TILED_THIN1: + case DC_ARRAY_PRT_2D_TILED_THICK: + return mi_tiling_2D; + case DC_ARRAY_LINEAR_GENERAL: + case DC_ARRAY_LINEAR_ALLIGNED: + return mi_tiling_linear; + default: + return mi_tiling_2D; + } +} + +static bool is_vert_scan(enum dc_rotation_angle rotation) +{ + switch (rotation) { + case ROTATION_ANGLE_90: + case ROTATION_ANGLE_270: + return true; + default: + return false; + } +} + +static unsigned int log_2(unsigned int num) +{ + unsigned int result = 0; + + while ((num >>= 1) != 0) + result++; + + return result; +} + +void dce_mem_input_program_pte_vm(struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation) +{ + enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format); + enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info); + const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp]; + + unsigned int page_width = log_2(pte->page_width); + unsigned int page_height = log_2(pte->page_height); + unsigned int min_pte_before_flip = is_vert_scan(rotation) ? + pte->min_pte_before_flip_vert_scan : + pte->min_pte_before_flip_horiz_scan; + + REG_UPDATE(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, + GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, 0xff); + + REG_UPDATE_3(DVMM_PTE_CONTROL, + DVMM_PAGE_WIDTH, page_width, + DVMM_PAGE_HEIGHT, page_height, + DVMM_MIN_PTE_BEFORE_FLIP, min_pte_before_flip); + + REG_UPDATE_2(DVMM_PTE_ARB_CONTROL, + DVMM_PTE_REQ_PER_CHUNK, pte->pte_req_per_chunk, + DVMM_MAX_PTE_REQ_OUTSTANDING, 0xff); +} static void program_urgency_watermark(struct mem_input *mi, uint32_t wm_select, @@ -244,7 +375,7 @@ static void program_grph_pixel_format( GRPH_PRESCALE_B_SIGN, sign); } -bool dce_mem_input_program_surface_config(struct mem_input *mi, +void dce_mem_input_program_surface_config(struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -260,8 +391,6 @@ bool dce_mem_input_program_surface_config(struct mem_input *mi, if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) program_grph_pixel_format(mi, format); - - return true; } static uint32_t get_dmif_switch_time_us( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index d5930a925fcb..a366b3a5b79d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -42,10 +42,22 @@ SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\ SRI(DMIF_BUFFER_CONTROL, PIPE, id) -#define MI_REG_LIST(id)\ +#define MI_DCE_PTE_REG_LIST(id)\ + SRI(DVMM_PTE_CONTROL, DCP, id),\ + SRI(DVMM_PTE_ARB_CONTROL, DCP, id) + +#define MI_DCE8_REG_LIST(id)\ MI_DCE_BASE_REG_LIST(id),\ SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id) +#define MI_DCE11_2_REG_LIST(id)\ + MI_DCE8_REG_LIST(id),\ + SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id) + +#define MI_DCE11_REG_LIST(id)\ + MI_DCE11_2_REG_LIST(id),\ + MI_DCE_PTE_REG_LIST(id) + struct dce_mem_input_registers { /* DCP */ uint32_t GRPH_ENABLE; @@ -58,6 +70,9 @@ struct dce_mem_input_registers { uint32_t HW_ROTATION; uint32_t GRPH_SWAP_CNTL; uint32_t PRESCALE_GRPH_CONTROL; + uint32_t GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT; + uint32_t DVMM_PTE_CONTROL; + uint32_t DVMM_PTE_ARB_CONTROL; /* DMIF_PG */ uint32_t DPG_PIPE_ARBITRATION_CONTROL1; uint32_t DPG_WATERMARK_MASK_CONTROL; @@ -103,6 +118,16 @@ struct dce_mem_input_registers { SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh) +#define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, mask_sh) + +#define MI_DCP_PTE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH, mask_sh),\ + SFB(blk, DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT, mask_sh),\ + SFB(blk, DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP, mask_sh),\ + SFB(blk, DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK, mask_sh),\ + SFB(blk, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING, mask_sh) + #define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\ SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\ SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\ @@ -122,11 +147,19 @@ struct dce_mem_input_registers { SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh) -#define MI_DCE_MASK_SH_LIST(mask_sh)\ - MI_DCP_MASK_SH_LIST(mask_sh,),\ - MI_DMIF_PG_MASK_SH_LIST(mask_sh,),\ - MI_DMIF_PG_MASK_SH_DCE(mask_sh,),\ - MI_GFX8_TILE_MASK_SH_LIST(mask_sh,) +#define MI_DCE8_MASK_SH_LIST(mask_sh)\ + MI_DCP_MASK_SH_LIST(mask_sh, ),\ + MI_DMIF_PG_MASK_SH_LIST(mask_sh, ),\ + MI_DMIF_PG_MASK_SH_DCE(mask_sh, ),\ + MI_GFX8_TILE_MASK_SH_LIST(mask_sh, ) + +#define MI_DCE11_2_MASK_SH_LIST(mask_sh)\ + MI_DCE8_MASK_SH_LIST(mask_sh),\ + MI_DCP_DCE11_MASK_SH_LIST(mask_sh, ) + +#define MI_DCE11_MASK_SH_LIST(mask_sh)\ + MI_DCE11_2_MASK_SH_LIST(mask_sh),\ + MI_DCP_PTE_MASK_SH_LIST(mask_sh, ) #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ @@ -142,6 +175,12 @@ struct dce_mem_input_registers { type GRPH_PRESCALE_R_SIGN; \ type GRPH_PRESCALE_G_SIGN; \ type GRPH_PRESCALE_B_SIGN; \ + type GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT; \ + type DVMM_PAGE_WIDTH; \ + type DVMM_PAGE_HEIGHT; \ + type DVMM_MIN_PTE_BEFORE_FLIP; \ + type DVMM_PTE_REQ_PER_CHUNK; \ + type DVMM_MAX_PTE_REQ_OUTSTANDING; \ type GRPH_DEPTH; \ type GRPH_FORMAT; \ type GRPH_NUM_BANKS; \ @@ -191,7 +230,13 @@ struct dce_mem_input_wa { }; struct mem_input; -bool dce_mem_input_program_surface_config(struct mem_input *mi, + +void dce_mem_input_program_pte_vm(struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + +void dce_mem_input_program_surface_config(struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 16595dc875a1..9ace6d1cca79 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -481,7 +481,7 @@ static const struct resource_create_funcs res_create_funcs = { }; #define mi_inst_regs(id) { \ - MI_REG_LIST(id), \ + MI_DCE8_REG_LIST(id), \ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ } static const struct dce_mem_input_registers mi_regs[] = { @@ -494,12 +494,12 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT), + MI_DCE8_MASK_SH_LIST(__SHIFT), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK), + MI_DCE8_MASK_SH_LIST(_MASK), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index c0a68c6f585e..af9d682f8943 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -150,117 +150,6 @@ bool dce110_mem_input_program_surface_flip_and_addr( return true; } -/* Scatter Gather param tables */ -static const unsigned int dvmm_Hw_Setting_2DTiling[4][9] = { - { 8, 64, 64, 8, 8, 1, 4, 0, 0}, - { 16, 64, 32, 8, 16, 1, 8, 0, 0}, - { 32, 32, 32, 16, 16, 1, 8, 0, 0}, - { 64, 8, 32, 16, 16, 1, 8, 0, 0}, /* fake */ -}; - -static const unsigned int dvmm_Hw_Setting_1DTiling[4][9] = { - { 8, 512, 8, 1, 0, 1, 0, 0, 0}, /* 0 for invalid */ - { 16, 256, 8, 2, 0, 1, 0, 0, 0}, - { 32, 128, 8, 4, 0, 1, 0, 0, 0}, - { 64, 64, 8, 4, 0, 1, 0, 0, 0}, /* fake */ -}; - -static const unsigned int dvmm_Hw_Setting_Linear[4][9] = { - { 8, 4096, 1, 8, 0, 1, 0, 0, 0}, - { 16, 2048, 1, 8, 0, 1, 0, 0, 0}, - { 32, 1024, 1, 8, 0, 1, 0, 0, 0}, - { 64, 512, 1, 8, 0, 1, 0, 0, 0}, /* new for 64bpp from HW */ -}; - -/* Helper to get table entry from surface info */ -static const unsigned int *get_dvmm_hw_setting( - union dc_tiling_info *tiling_info, - enum surface_pixel_format format) -{ - enum bits_per_pixel { - bpp_8 = 0, - bpp_16, - bpp_32, - bpp_64 - } bpp; - - if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) - bpp = bpp_64; - else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) - bpp = bpp_32; - else if (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB1555) - bpp = bpp_16; - else - bpp = bpp_8; - - switch (tiling_info->gfx8.array_mode) { - case DC_ARRAY_1D_TILED_THIN1: - case DC_ARRAY_1D_TILED_THICK: - case DC_ARRAY_PRT_TILED_THIN1: - return dvmm_Hw_Setting_1DTiling[bpp]; - case DC_ARRAY_2D_TILED_THIN1: - case DC_ARRAY_2D_TILED_THICK: - case DC_ARRAY_2D_TILED_X_THICK: - case DC_ARRAY_PRT_2D_TILED_THIN1: - case DC_ARRAY_PRT_2D_TILED_THICK: - return dvmm_Hw_Setting_2DTiling[bpp]; - case DC_ARRAY_LINEAR_GENERAL: - case DC_ARRAY_LINEAR_ALLIGNED: - return dvmm_Hw_Setting_Linear[bpp]; - default: - return dvmm_Hw_Setting_2DTiling[bpp]; - } -} - -bool dce110_mem_input_program_pte_vm( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format); - - unsigned int page_width = 0; - unsigned int page_height = 0; - unsigned int temp_page_width = pte[1]; - unsigned int temp_page_height = pte[2]; - unsigned int min_pte_before_flip = 0; - uint32_t value = 0; - - while ((temp_page_width >>= 1) != 0) - page_width++; - while ((temp_page_height >>= 1) != 0) - page_height++; - - switch (rotation) { - case ROTATION_ANGLE_90: - case ROTATION_ANGLE_270: - min_pte_before_flip = pte[4]; - break; - default: - min_pte_before_flip = pte[3]; - break; - } - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT)); - set_reg_field_value(value, 0xff, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT), value); - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL)); - set_reg_field_value(value, page_width, DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); - set_reg_field_value(value, page_height, DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); - set_reg_field_value(value, min_pte_before_flip, DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_CONTROL), value); - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL)); - set_reg_field_value(value, pte[5], DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); - set_reg_field_value(value, 0xff, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmDVMM_PTE_ARB_CONTROL), value); - - return true; -} - static void program_urgency_watermark( const struct dc_context *ctx, const uint32_t offset, @@ -502,7 +391,7 @@ static struct mem_input_funcs dce110_mem_input_funcs = { .mem_input_program_surface_flip_and_addr = dce110_mem_input_program_surface_flip_and_addr, .mem_input_program_pte_vm = - dce110_mem_input_program_pte_vm, + dce_mem_input_program_pte_vm, .mem_input_program_surface_config = dce_mem_input_program_surface_config, .mem_input_is_flip_pending = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h index 83b2df93ce49..a80a20c09da4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h @@ -107,17 +107,6 @@ bool dce110_mem_input_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizontal_mirror); -/* - * dce110_mem_input_program_pte_vm - * - * This function will program pte vm registers. - */ -bool dce110_mem_input_program_pte_vm( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation); - /* * dce110_mem_input_is_flip_pending * diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index f0310bab4030..757e946d0837 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -584,7 +584,7 @@ static const unsigned int *get_dvmm_hw_setting( } } -bool dce110_mem_input_v_program_pte_vm( +void dce110_mem_input_v_program_pte_vm( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -655,11 +655,9 @@ bool dce110_mem_input_v_program_pte_vm( set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C); set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C); dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C), value); - - return true; } -bool dce110_mem_input_v_program_surface_config( +void dce110_mem_input_v_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -674,8 +672,6 @@ bool dce110_mem_input_v_program_surface_config( program_tiling(mem_input110, tiling_info, format); program_size_and_rotation(mem_input110, rotation, plane_size); program_pixel_format(mem_input110, format); - - return true; } static void program_urgency_watermark( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 959467fa421e..cac3dc425039 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -474,7 +474,7 @@ static const struct resource_create_funcs res_create_funcs = { }; #define mi_inst_regs(id) { \ - MI_REG_LIST(id), \ + MI_DCE11_REG_LIST(id), \ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ } static const struct dce_mem_input_registers mi_regs[] = { @@ -484,12 +484,12 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT), + MI_DCE11_MASK_SH_LIST(__SHIFT), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK), + MI_DCE11_MASK_SH_LIST(_MASK), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index bfb2c3fcd2cb..4e3273c0fa91 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -495,7 +495,7 @@ static const struct resource_create_funcs res_create_funcs = { .create_hwseq = dce112_hwseq_create, }; -#define mi_inst_regs(id) { MI_REG_LIST(id) } +#define mi_inst_regs(id) { MI_DCE11_2_REG_LIST(id) } static const struct dce_mem_input_registers mi_regs[] = { mi_inst_regs(0), mi_inst_regs(1), @@ -506,11 +506,11 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT) + MI_DCE11_2_MASK_SH_LIST(__SHIFT) }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK) + MI_DCE11_2_MASK_SH_LIST(_MASK) }; static struct mem_input *dce112_mem_input_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 06720407b6fc..3b626b7883d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -462,7 +462,7 @@ static const struct resource_create_funcs res_create_funcs = { }; #define mi_inst_regs(id) { \ - MI_REG_LIST(id), \ + MI_DCE8_REG_LIST(id), \ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ } static const struct dce_mem_input_registers mi_regs[] = { @@ -475,12 +475,12 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE_MASK_SH_LIST(__SHIFT), + MI_DCE8_MASK_SH_LIST(__SHIFT), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE_MASK_SH_LIST(_MASK), + MI_DCE8_MASK_SH_LIST(_MASK), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 78dab74edc2d..80566c844758 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -82,13 +82,13 @@ struct mem_input_funcs { const struct dc_plane_address *address, bool flip_immediate); - bool (*mem_input_program_pte_vm)( + void (*mem_input_program_pte_vm)( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation); - bool (*mem_input_program_surface_config)( + void (*mem_input_program_surface_config)( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, -- GitLab From 565968219c7a8feebd0b0b0b960563d9a3500ba5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 1 Dec 2016 13:37:25 -0500 Subject: [PATCH 0075/2898] drm/amd/display: Add missing GRPH register definition Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index a366b3a5b79d..022272d30fe4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -193,6 +193,7 @@ struct dce_mem_input_registers { type GRPH_ARRAY_MODE;\ type GRPH_COLOR_EXPANSION_MODE;\ type GRPH_SW_MODE; \ + type GRPH_SE_ENABLE; \ type GRPH_NUM_SHADER_ENGINES; \ type GRPH_NUM_PIPES; \ type PIXEL_DURATION; \ -- GitLab From 00d64d289fbba7f147b3a3a6fe88ca473ef6468d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 29 Nov 2016 17:22:27 -0500 Subject: [PATCH 0076/2898] drm/amd/display: remove dead display clock code Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../dc/gpu/dce110/display_clock_dce110.c | 468 +---------------- .../dc/gpu/dce110/display_clock_dce110.h | 1 - .../dc/gpu/dce112/display_clock_dce112.c | 477 +----------------- .../dc/gpu/dce112/display_clock_dce112.h | 18 - .../dc/gpu/dce80/display_clock_dce80.c | 476 +---------------- .../dc/gpu/dce80/display_clock_dce80.h | 1 - .../drm/amd/display/dc/gpu/display_clock.c | 122 ----- .../drm/amd/display/dc/gpu/display_clock.h | 28 - .../display/include/display_clock_interface.h | 85 ---- 9 files changed, 29 insertions(+), 1647 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c index 1bc39f12b6a1..cc13afa326ad 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -268,404 +268,6 @@ static void destroy(struct display_clock **base) *base = NULL; } -static uint32_t get_validation_clock(struct display_clock *dc) -{ - uint32_t clk = 0; - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - - switch (disp_clk->max_clks_state) { - case CLOCKS_STATE_ULTRA_LOW: - /*Currently not supported, it has 0 in table entry*/ - case CLOCKS_STATE_LOW: - clk = max_clks_by_state[CLOCKS_STATE_LOW]. - display_clk_khz; - break; - - case CLOCKS_STATE_NOMINAL: - clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. - display_clk_khz; - break; - - case CLOCKS_STATE_PERFORMANCE: - clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. - display_clk_khz; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Invalid clock state"); - /* just return the display engine clock for - * lowest supported state*/ - clk = max_clks_by_state[CLOCKS_STATE_LOW]. - display_clk_khz; - break; - } - return clk; -} - -static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) -{ - /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ - struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); - - if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) - return deep_color_factor; - - switch (params->deep_color_depth) { - case COLOR_DEPTH_101010: - /*deep color ratio for 30bpp is 30/24 = 1.25*/ - deep_color_factor = dal_fixed32_32_from_fraction(30, 24); - break; - - case COLOR_DEPTH_121212: - /* deep color ratio for 36bpp is 36/24 = 1.5*/ - deep_color_factor = dal_fixed32_32_from_fraction(36, 24); - break; - - case COLOR_DEPTH_161616: - /* deep color ratio for 48bpp is 48/24 = 2.0 */ - deep_color_factor = dal_fixed32_32_from_fraction(48, 24); - break; - default: - break; - } - return deep_color_factor; -} - -static struct fixed32_32 get_scaler_efficiency( - struct dc_context *ctx, - struct min_clock_params *params) -{ - struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); - - if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { - scaler_efficiency = - dal_fixed32_32_add( - dal_fixed32_32_from_fraction(35555, 10000), - dal_fixed32_32_from_fraction( - 55556, - 100000 * 10000)); - } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { - scaler_efficiency = - dal_fixed32_32_add( - dal_fixed32_32_from_fraction(34285, 10000), - dal_fixed32_32_from_fraction( - 71429, - 100000 * 10000)); - } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) - scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); - - return scaler_efficiency; -} - -static struct fixed32_32 get_lb_lines_in_per_line_out( - struct min_clock_params *params, - struct fixed32_32 v_scale_ratio) -{ - struct fixed32_32 two = dal_fixed32_32_from_int(2); - struct fixed32_32 four = dal_fixed32_32_from_int(4); - struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); - struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); - - if (params->line_buffer_prefetch_enabled) - return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); - else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) - return dal_fixed32_32_one; - else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) - return f4_to_3; - else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) - return f6_to_4; - else if (dal_fixed32_32_le(v_scale_ratio, two)) - return two; - else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) - return four; - else - return dal_fixed32_32_zero; -} - -static uint32_t get_actual_required_display_clk( - struct display_clock_dce110 *disp_clk, - uint32_t target_clk_khz) -{ - uint32_t disp_clk_khz = target_clk_khz; - uint32_t div = INVALID_DIVIDER; - uint32_t did = INVALID_DID; - uint32_t scaled_vco = - disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; - - ASSERT_CRITICAL(!!disp_clk_khz); - - if (disp_clk_khz) - div = scaled_vco / disp_clk_khz; - - did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); - - if (did != INVALID_DID) { - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, did); - - if ((div != INVALID_DIVIDER) && - (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) - if (disp_clk_khz > (scaled_vco / div)) - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, - did - 1); - - if (div != INVALID_DIVIDER) - disp_clk_khz = scaled_vco / div; - - } - /* We need to add 10KHz to this value because the accuracy in VBIOS is - in 10KHz units. So we need to always round the last digit up in order - to reach the next div level.*/ - return disp_clk_khz + 10; -} - -static uint32_t calc_single_display_min_clks( - struct display_clock *base, - struct min_clock_params *params, - bool set_clk) -{ - struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; - struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; - uint32_t pix_clk_khz = 0; - uint32_t lb_source_width = 0; - struct fixed32_32 deep_color_factor; - struct fixed32_32 scaler_efficiency; - struct fixed32_32 v_filter_init; - uint32_t v_filter_init_trunc; - uint32_t num_lines_at_frame_start = 3; - struct fixed32_32 v_filter_init_ceil; - struct fixed32_32 lines_per_lines_out_at_frame_start; - struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ - uint32_t src_wdth_rnd_to_chunks; - struct fixed32_32 scaling_coeff; - struct fixed32_32 h_blank_granularity_factor = - dal_fixed32_32_one; - struct fixed32_32 fx_disp_clk_mhz; - struct fixed32_32 line_time; - struct fixed32_32 disp_pipe_pix_throughput; - struct fixed32_32 fx_alt_disp_clk_mhz; - uint32_t disp_clk_khz; - uint32_t alt_disp_clk_khz; - struct display_clock_dce110 *disp_clk_110 = DCLCK110_FROM_BASE(base); - uint32_t max_clk_khz = get_validation_clock(base); - bool panning_allowed = false; /* TODO: receive this value from AS */ - - if (params == NULL) { - dm_logger_write(base->ctx->logger, LOG_WARNING, - "Invalid input parameter in %s", - __func__); - return 0; - } - - deep_color_factor = get_deep_color_factor(params); - scaler_efficiency = get_scaler_efficiency(base->ctx, params); - pix_clk_khz = params->requested_pixel_clock; - lb_source_width = params->source_view.width; - - if (0 != params->dest_view.height && 0 != params->dest_view.width) { - - h_scale_ratio = dal_fixed32_32_from_fraction( - params->source_view.width, - params->dest_view.width); - v_scale_ratio = dal_fixed32_32_from_fraction( - params->source_view.height, - params->dest_view.height); - } else { - dm_logger_write(base->ctx->logger, LOG_WARNING, - "Destination height or width is 0!\n"); - } - - v_filter_init = - dal_fixed32_32_add( - v_scale_ratio, - dal_fixed32_32_add_int( - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int( - v_scale_ratio, - params->timing_info.INTERLACED), - 2), - params->scaling_info.v_taps + 1)); - v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); - - v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); - - v_filter_init_ceil = dal_fixed32_32_from_fraction( - v_filter_init_trunc, 2); - v_filter_init_ceil = dal_fixed32_32_from_int( - dal_fixed32_32_ceil(v_filter_init_ceil)); - v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); - - lines_per_lines_out_at_frame_start = - dal_fixed32_32_div_int(v_filter_init_ceil, - num_lines_at_frame_start); - lb_lines_in_per_line_out = - get_lb_lines_in_per_line_out(params, v_scale_ratio); - - if (panning_allowed) - src_wdth_rnd_to_chunks = - ((lb_source_width - 1) / 128) * 128 + 256; - else - src_wdth_rnd_to_chunks = - ((lb_source_width + 127) / 128) * 128; - - scaling_coeff = - dal_fixed32_32_div( - dal_fixed32_32_from_int(params->scaling_info.v_taps), - scaler_efficiency); - - if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) - scaling_coeff = dal_fixed32_32_max( - dal_fixed32_32_from_int( - dal_fixed32_32_ceil( - dal_fixed32_32_from_fraction( - params->scaling_info.h_taps, - 4))), - dal_fixed32_32_max( - dal_fixed32_32_mul( - scaling_coeff, - h_scale_ratio), - dal_fixed32_32_one)); - - if (!params->line_buffer_prefetch_enabled && - dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && - dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { - uint32_t line_total_pixel = - params->timing_info.h_total + lb_source_width - 256; - h_blank_granularity_factor = dal_fixed32_32_div( - dal_fixed32_32_from_int(params->timing_info.h_total), - dal_fixed32_32_div( - dal_fixed32_32_from_fraction( - line_total_pixel, 2), - h_scale_ratio)); - } - - /* Calculate display clock with ramping. Ramping factor is 1.1*/ - fx_disp_clk_mhz = - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int(scaling_coeff, 11), - 10); - line_time = dal_fixed32_32_from_fraction( - params->timing_info.h_total * 1000, pix_clk_khz); - - disp_pipe_pix_throughput = dal_fixed32_32_mul( - lb_lines_in_per_line_out, h_blank_granularity_factor); - disp_pipe_pix_throughput = dal_fixed32_32_max( - disp_pipe_pix_throughput, - lines_per_lines_out_at_frame_start); - disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( - disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), - line_time); - - if (0 != params->timing_info.h_total) { - fx_disp_clk_mhz = - dal_fixed32_32_max( - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int( - scaling_coeff, pix_clk_khz), - 1000), - disp_pipe_pix_throughput); - fx_disp_clk_mhz = - dal_fixed32_32_mul( - fx_disp_clk_mhz, - dal_fixed32_32_from_fraction(11, 10)); - } - - fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, - dal_fixed32_32_mul(deep_color_factor, - dal_fixed32_32_from_fraction(11, 10))); - - /* Calculate display clock without ramping */ - fx_alt_disp_clk_mhz = scaling_coeff; - - if (0 != params->timing_info.h_total) { - fx_alt_disp_clk_mhz = dal_fixed32_32_max( - dal_fixed32_32_div_int(dal_fixed32_32_mul_int( - scaling_coeff, pix_clk_khz), - 1000), - dal_fixed32_32_div_int(dal_fixed32_32_mul_int( - disp_pipe_pix_throughput, 105), - 100)); - } - - if (set_clk && disp_clk_110->ss_on_gpu_pll && - disp_clk_110->gpu_pll_ss_divider) - fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, - dal_fixed32_32_add_int( - dal_fixed32_32_div_int( - dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk_110->gpu_pll_ss_percentage, - disp_clk_110->gpu_pll_ss_divider), 100), - 2), - 1)); - - /* convert to integer */ - disp_clk_khz = dal_fixed32_32_round( - dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); - alt_disp_clk_khz = dal_fixed32_32_round( - dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); - - if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) - disp_clk_khz = alt_disp_clk_khz; - - if (set_clk) { /* only compensate clock if we are going to set it.*/ - disp_clk_khz = get_actual_required_display_clk( - disp_clk_110, disp_clk_khz); - } - - disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; - - return disp_clk_khz; -} - -static uint32_t calculate_min_clock( - struct display_clock *base, - uint32_t path_num, - struct min_clock_params *params) -{ - uint32_t i; - uint32_t validation_clk_khz = - get_validation_clock(base); - uint32_t min_clk_khz = validation_clk_khz; - uint32_t max_clk_khz = 0; - struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); - - if (dc->use_max_disp_clk) - return min_clk_khz; - - if (params != NULL) { - uint32_t disp_clk_khz = 0; - - for (i = 0; i < path_num; ++i) { - - disp_clk_khz = calc_single_display_min_clks( - base, params, true); - - /* update the max required clock found*/ - if (disp_clk_khz > max_clk_khz) - max_clk_khz = disp_clk_khz; - - params++; - } - } - - min_clk_khz = max_clk_khz; - - if (min_clk_khz > validation_clk_khz) - min_clk_khz = validation_clk_khz; - else if (min_clk_khz < base->min_display_clk_threshold_khz) - min_clk_khz = base->min_display_clk_threshold_khz; - - if (dc->use_max_disp_clk) - min_clk_khz = get_validation_clock(base); - - return min_clk_khz; -} - static bool display_clock_integrated_info_construct( struct display_clock_dce110 *disp_clk) { @@ -741,38 +343,6 @@ static bool display_clock_integrated_info_construct( return true; } -static uint32_t get_clock(struct display_clock *dc) -{ - uint32_t disp_clock = get_validation_clock(dc); - uint32_t target_div = INVALID_DIVIDER; - uint32_t addr = mmDENTIST_DISPCLK_CNTL; - uint32_t value = 0; - uint32_t field = 0; - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - - if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) - return disp_clk->dfs_bypass_disp_clk; - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed - DID DENTIST_DISPCLK_WDIVIDER.*/ - value = dm_read_reg(dc->ctx, addr); - field = get_reg_field_value( - value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); - - /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - field); - - if (target_div != INVALID_DIVIDER) - /* Calculate the current DFS clock in KHz. - Should be okay up to 42.9 THz before overflowing.*/ - disp_clock = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - return disp_clock; -} - static enum clocks_state get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks) @@ -882,44 +452,15 @@ static void set_clock( psr_wait_loop(base->ctx, requested_clk_khz); } -static void set_clock_state( - struct display_clock *dc, - struct display_clock_state clk_state) -{ - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - - disp_clk->clock_state = clk_state; -} - -static struct display_clock_state get_clock_state( - struct display_clock *dc) -{ - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - - return disp_clk->clock_state; -} - -static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) -{ - return DCE110_DFS_BYPASS_THRESHOLD_KHZ; -} static const struct display_clock_funcs funcs = { .destroy = destroy, - .calculate_min_clock = calculate_min_clock, - .get_clock = get_clock, - .get_clock_state = get_clock_state, - .get_dfs_bypass_threshold = get_dfs_bypass_threshold, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, - .get_validation_clock = get_validation_clock, .set_clock = set_clock, - .set_clock_state = set_clock_state, - .set_dp_ref_clock_source = NULL, .set_min_clocks_state = set_min_clocks_state, - .store_max_clocks_state = store_max_clocks_state, - .validate = NULL, + .store_max_clocks_state = store_max_clocks_state }; static bool dal_display_clock_dce110_construct( @@ -929,8 +470,11 @@ static bool dal_display_clock_dce110_construct( struct display_clock *dc_base = &dc110->disp_clk_base; struct dc_bios *bp = ctx->dc_bios; - if (!dal_display_clock_construct_base(dc_base, ctx)) - return false; + dc_base->ctx = ctx; + dc_base->id = CLOCK_SOURCE_ID_DCPLL; + dc_base->min_display_clk_threshold_khz = 0; + + dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h index 0cdc7b52a09f..88b4bdd75e56 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h @@ -44,7 +44,6 @@ struct display_clock_dce110 { /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ uint32_t dfs_bypass_disp_clk; - struct display_clock_state clock_state; }; #define DCLCK110_FROM_BASE(dc_base) \ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index 9b7c9755e316..bf044260c0bb 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -242,406 +242,6 @@ void dispclk_dce112_destroy(struct display_clock **base) *base = NULL; } -uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc) -{ - uint32_t clk = 0; - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - - switch (disp_clk->max_clks_state) { - case CLOCKS_STATE_ULTRA_LOW: - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_ULTRA_LOW)-> - display_clk_khz; - - case CLOCKS_STATE_LOW: - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)-> - display_clk_khz; - break; - - case CLOCKS_STATE_NOMINAL: - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_NOMINAL)-> - display_clk_khz; - break; - - case CLOCKS_STATE_PERFORMANCE: - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_PERFORMANCE)-> - display_clk_khz; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Invalid clock state"); - /* just return the display engine clock for - * lowest supported state*/ - clk = (disp_clk->max_clks_by_state + CLOCKS_STATE_LOW)-> - display_clk_khz; - break; - } - return clk; -} - -static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) -{ - /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ - struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); - - if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) - return deep_color_factor; - - switch (params->deep_color_depth) { - case COLOR_DEPTH_101010: - /*deep color ratio for 30bpp is 30/24 = 1.25*/ - deep_color_factor = dal_fixed32_32_from_fraction(30, 24); - break; - - case COLOR_DEPTH_121212: - /* deep color ratio for 36bpp is 36/24 = 1.5*/ - deep_color_factor = dal_fixed32_32_from_fraction(36, 24); - break; - - case COLOR_DEPTH_161616: - /* deep color ratio for 48bpp is 48/24 = 2.0 */ - deep_color_factor = dal_fixed32_32_from_fraction(48, 24); - break; - default: - break; - } - return deep_color_factor; -} - -static struct fixed32_32 get_scaler_efficiency( - struct dc_context *ctx, - struct min_clock_params *params) -{ - struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3); - - if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) { - scaler_efficiency = - dal_fixed32_32_add( - dal_fixed32_32_from_fraction(35555, 10000), - dal_fixed32_32_from_fraction( - 55556, - 100000 * 10000)); - } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) { - scaler_efficiency = - dal_fixed32_32_add( - dal_fixed32_32_from_fraction(34285, 10000), - dal_fixed32_32_from_fraction( - 71429, - 100000 * 10000)); - } else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP) - scaler_efficiency = dal_fixed32_32_from_fraction(32, 10); - - return scaler_efficiency; -} - -static struct fixed32_32 get_lb_lines_in_per_line_out( - struct min_clock_params *params, - struct fixed32_32 v_scale_ratio) -{ - struct fixed32_32 two = dal_fixed32_32_from_int(2); - struct fixed32_32 four = dal_fixed32_32_from_int(4); - struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3); - struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4); - - if (params->line_buffer_prefetch_enabled) - return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one); - else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one)) - return dal_fixed32_32_one; - else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3)) - return f4_to_3; - else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4)) - return f6_to_4; - else if (dal_fixed32_32_le(v_scale_ratio, two)) - return two; - else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3))) - return four; - else - return dal_fixed32_32_zero; -} - -static uint32_t get_actual_required_display_clk( - struct display_clock_dce112 *disp_clk, - uint32_t target_clk_khz) -{ - uint32_t disp_clk_khz = target_clk_khz; - uint32_t div = INVALID_DIVIDER; - uint32_t did = INVALID_DID; - uint32_t scaled_vco = - disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; - - ASSERT_CRITICAL(!!disp_clk_khz); - - if (disp_clk_khz) - div = scaled_vco / disp_clk_khz; - - did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); - - if (did != INVALID_DID) { - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, did); - - if ((div != INVALID_DIVIDER) && - (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) - if (disp_clk_khz > (scaled_vco / div)) - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, - did - 1); - - if (div != INVALID_DIVIDER) - disp_clk_khz = scaled_vco / div; - - } - /* We need to add 10KHz to this value because the accuracy in VBIOS is - in 10KHz units. So we need to always round the last digit up in order - to reach the next div level.*/ - return disp_clk_khz + 10; -} - -static uint32_t calc_single_display_min_clks( - struct display_clock *base, - struct min_clock_params *params, - bool set_clk) -{ - struct fixed32_32 h_scale_ratio = dal_fixed32_32_one; - struct fixed32_32 v_scale_ratio = dal_fixed32_32_one; - uint32_t pix_clk_khz = 0; - uint32_t lb_source_width = 0; - struct fixed32_32 deep_color_factor; - struct fixed32_32 scaler_efficiency; - struct fixed32_32 v_filter_init; - uint32_t v_filter_init_trunc; - uint32_t num_lines_at_frame_start = 3; - struct fixed32_32 v_filter_init_ceil; - struct fixed32_32 lines_per_lines_out_at_frame_start; - struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/ - uint32_t src_wdth_rnd_to_chunks; - struct fixed32_32 scaling_coeff; - struct fixed32_32 h_blank_granularity_factor = - dal_fixed32_32_one; - struct fixed32_32 fx_disp_clk_mhz; - struct fixed32_32 line_time; - struct fixed32_32 disp_pipe_pix_throughput; - struct fixed32_32 fx_alt_disp_clk_mhz; - uint32_t disp_clk_khz; - uint32_t alt_disp_clk_khz; - struct display_clock_dce112 *disp_clk_110 = DCLCK112_FROM_BASE(base); - uint32_t max_clk_khz = dispclk_dce112_get_validation_clock(base); - bool panning_allowed = false; /* TODO: receive this value from AS */ - - if (params == NULL) { - dm_logger_write(base->ctx->logger, LOG_WARNING, - "Invalid input parameter in %s", - __func__); - return 0; - } - - deep_color_factor = get_deep_color_factor(params); - scaler_efficiency = get_scaler_efficiency(base->ctx, params); - pix_clk_khz = params->requested_pixel_clock; - lb_source_width = params->source_view.width; - - if (0 != params->dest_view.height && 0 != params->dest_view.width) { - - h_scale_ratio = dal_fixed32_32_from_fraction( - params->source_view.width, - params->dest_view.width); - v_scale_ratio = dal_fixed32_32_from_fraction( - params->source_view.height, - params->dest_view.height); - } else { - dm_logger_write(base->ctx->logger, LOG_WARNING, - "Destination height or width is 0!\n"); - } - - v_filter_init = - dal_fixed32_32_add( - v_scale_ratio, - dal_fixed32_32_add_int( - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int( - v_scale_ratio, - params->timing_info.INTERLACED), - 2), - params->scaling_info.v_taps + 1)); - v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2); - - v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); - - v_filter_init_ceil = dal_fixed32_32_from_fraction( - v_filter_init_trunc, 2); - v_filter_init_ceil = dal_fixed32_32_from_int( - dal_fixed32_32_ceil(v_filter_init_ceil)); - v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); - - lines_per_lines_out_at_frame_start = - dal_fixed32_32_div_int(v_filter_init_ceil, - num_lines_at_frame_start); - lb_lines_in_per_line_out = - get_lb_lines_in_per_line_out(params, v_scale_ratio); - - if (panning_allowed) - src_wdth_rnd_to_chunks = - ((lb_source_width - 1) / 128) * 128 + 256; - else - src_wdth_rnd_to_chunks = - ((lb_source_width + 127) / 128) * 128; - - scaling_coeff = - dal_fixed32_32_div( - dal_fixed32_32_from_int(params->scaling_info.v_taps), - scaler_efficiency); - - if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one)) - scaling_coeff = dal_fixed32_32_max( - dal_fixed32_32_from_int( - dal_fixed32_32_ceil( - dal_fixed32_32_from_fraction( - params->scaling_info.h_taps, - 4))), - dal_fixed32_32_max( - dal_fixed32_32_mul( - scaling_coeff, - h_scale_ratio), - dal_fixed32_32_one)); - - if (!params->line_buffer_prefetch_enabled && - dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 && - dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) { - uint32_t line_total_pixel = - params->timing_info.h_total + lb_source_width - 256; - h_blank_granularity_factor = dal_fixed32_32_div( - dal_fixed32_32_from_int(params->timing_info.h_total), - dal_fixed32_32_div( - dal_fixed32_32_from_fraction( - line_total_pixel, 2), - h_scale_ratio)); - } - - /* Calculate display clock with ramping. Ramping factor is 1.1*/ - fx_disp_clk_mhz = - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int(scaling_coeff, 11), - 10); - line_time = dal_fixed32_32_from_fraction( - params->timing_info.h_total * 1000, pix_clk_khz); - - disp_pipe_pix_throughput = dal_fixed32_32_mul( - lb_lines_in_per_line_out, h_blank_granularity_factor); - disp_pipe_pix_throughput = dal_fixed32_32_max( - disp_pipe_pix_throughput, - lines_per_lines_out_at_frame_start); - disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int( - disp_pipe_pix_throughput, src_wdth_rnd_to_chunks), - line_time); - - if (0 != params->timing_info.h_total) { - fx_disp_clk_mhz = - dal_fixed32_32_max( - dal_fixed32_32_div_int( - dal_fixed32_32_mul_int( - scaling_coeff, pix_clk_khz), - 1000), - disp_pipe_pix_throughput); - fx_disp_clk_mhz = - dal_fixed32_32_mul( - fx_disp_clk_mhz, - dal_fixed32_32_from_fraction(11, 10)); - } - - fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz, - dal_fixed32_32_mul(deep_color_factor, - dal_fixed32_32_from_fraction(11, 10))); - - /* Calculate display clock without ramping */ - fx_alt_disp_clk_mhz = scaling_coeff; - - if (0 != params->timing_info.h_total) { - fx_alt_disp_clk_mhz = dal_fixed32_32_max( - dal_fixed32_32_div_int(dal_fixed32_32_mul_int( - scaling_coeff, pix_clk_khz), - 1000), - dal_fixed32_32_div_int(dal_fixed32_32_mul_int( - disp_pipe_pix_throughput, 105), - 100)); - } - - if (set_clk && disp_clk_110->ss_on_gpu_pll && - disp_clk_110->gpu_pll_ss_divider) - fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz, - dal_fixed32_32_add_int( - dal_fixed32_32_div_int( - dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk_110->gpu_pll_ss_percentage, - disp_clk_110->gpu_pll_ss_divider), 100), - 2), - 1)); - - /* convert to integer */ - disp_clk_khz = dal_fixed32_32_round( - dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000)); - alt_disp_clk_khz = dal_fixed32_32_round( - dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000)); - - if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) - disp_clk_khz = alt_disp_clk_khz; - - if (set_clk) { /* only compensate clock if we are going to set it.*/ - disp_clk_khz = get_actual_required_display_clk( - disp_clk_110, disp_clk_khz); - } - - disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz; - - return disp_clk_khz; -} - -uint32_t dispclk_dce112_calculate_min_clock( - struct display_clock *base, - uint32_t path_num, - struct min_clock_params *params) -{ - uint32_t i; - uint32_t validation_clk_khz = - dispclk_dce112_get_validation_clock(base); - uint32_t min_clk_khz = validation_clk_khz; - uint32_t max_clk_khz = 0; - struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); - - if (dc->use_max_disp_clk) - return min_clk_khz; - - if (params != NULL) { - uint32_t disp_clk_khz = 0; - - for (i = 0; i < path_num; ++i) { - - disp_clk_khz = calc_single_display_min_clks( - base, params, true); - - /* update the max required clock found*/ - if (disp_clk_khz > max_clk_khz) - max_clk_khz = disp_clk_khz; - - params++; - } - } - - min_clk_khz = max_clk_khz; - - if (min_clk_khz > validation_clk_khz) - min_clk_khz = validation_clk_khz; - else if (min_clk_khz < base->min_display_clk_threshold_khz) - min_clk_khz = base->min_display_clk_threshold_khz; - - if (dc->use_max_disp_clk) - min_clk_khz = dispclk_dce112_get_validation_clock(base); - - return min_clk_khz; -} - static bool display_clock_integrated_info_construct( struct display_clock_dce112 *disp_clk) { @@ -655,8 +255,6 @@ static bool display_clock_integrated_info_construct( if (disp_clk->dentist_vco_freq_khz == 0) disp_clk->dentist_vco_freq_khz = 3600000; - disp_clk->crystal_freq_khz = 100000; - base->min_display_clk_threshold_khz = disp_clk->dentist_vco_freq_khz / 64; @@ -698,35 +296,6 @@ static bool display_clock_integrated_info_construct( return true; } -static uint32_t get_clock(struct display_clock *dc) -{ - uint32_t disp_clock = dispclk_dce112_get_validation_clock(dc); - uint32_t target_div = INVALID_DIVIDER; - uint32_t addr = mmDENTIST_DISPCLK_CNTL; - uint32_t value = 0; - uint32_t field = 0; - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed - DID DENTIST_DISPCLK_WDIVIDER.*/ - value = dm_read_reg(dc->ctx, addr); - field = get_reg_field_value( - value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); - - /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - field); - - if (target_div != INVALID_DIVIDER) - /* Calculate the current DFS clock in KHz. - Should be okay up to 42.9 THz before overflowing.*/ - disp_clock = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - return disp_clock; -} - enum clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks) @@ -797,45 +366,14 @@ void dispclk_dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); } -void dispclk_dce112_set_clock_state( - struct display_clock *dc, - struct display_clock_state clk_state) -{ - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - - disp_clk->clock_state = clk_state; -} - -struct display_clock_state dispclk_dce112_get_clock_state( - struct display_clock *dc) -{ - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - - return disp_clk->clock_state; -} - -uint32_t dispclk_dce112_get_dfs_bypass_threshold( - struct display_clock *dc) -{ - return dce112_DFS_BYPASS_THRESHOLD_KHZ; -} - static const struct display_clock_funcs funcs = { .destroy = dispclk_dce112_destroy, - .calculate_min_clock = dispclk_dce112_calculate_min_clock, - .get_clock = get_clock, - .get_clock_state = dispclk_dce112_get_clock_state, - .get_dfs_bypass_threshold = dispclk_dce112_get_dfs_bypass_threshold, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, .get_min_clocks_state = dispclk_dce112_get_min_clocks_state, .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, - .get_validation_clock = dispclk_dce112_get_validation_clock, .set_clock = dispclk_dce112_set_clock, - .set_clock_state = dispclk_dce112_set_clock_state, - .set_dp_ref_clock_source = NULL, .set_min_clocks_state = dispclk_dce112_set_min_clocks_state, .store_max_clocks_state = dispclk_dce112_store_max_clocks_state, - .validate = NULL, }; bool dal_display_clock_dce112_construct( @@ -844,11 +382,11 @@ bool dal_display_clock_dce112_construct( { struct display_clock *dc_base = &dc112->disp_clk_base; - /*if (NULL == as) - return false;*/ + dc_base->ctx = ctx; + dc_base->id = CLOCK_SOURCE_ID_DCPLL; + dc_base->min_display_clk_threshold_khz = 0; - if (!dal_display_clock_construct_base(dc_base, ctx)) - return false; + dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; @@ -870,12 +408,7 @@ bool dal_display_clock_dce112_construct( dc112->max_clks_state = CLOCKS_STATE_NOMINAL; dc112->disp_clk_base.min_display_clk_threshold_khz = - dc112->crystal_freq_khz; - - if (dc112->disp_clk_base.min_display_clk_threshold_khz < - (dc112->dentist_vco_freq_khz / 62)) - dc112->disp_clk_base.min_display_clk_threshold_khz = - (dc112->dentist_vco_freq_khz / 62); + (dc112->dentist_vco_freq_khz / 62); dal_divider_range_construct( ÷r_ranges[DIVIDER_RANGE_01], diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 937e17929b7c..5ab31185d29d 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -45,7 +45,6 @@ struct display_clock_dce112 { /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ uint32_t dfs_bypass_disp_clk; - struct display_clock_state clock_state; struct state_dependent_clocks *max_clks_by_state; }; @@ -75,17 +74,6 @@ bool dal_display_clock_dce112_construct( void dispclk_dce112_destroy(struct display_clock **base); -uint32_t dispclk_dce112_calculate_min_clock( - struct display_clock *base, - uint32_t path_num, - struct min_clock_params *params); - -struct display_clock_state dispclk_dce112_get_clock_state( - struct display_clock *dc); - -uint32_t dispclk_dce112_get_dfs_bypass_threshold( - struct display_clock *dc); - enum clocks_state dispclk_dce112_get_min_clocks_state( struct display_clock *base); @@ -93,16 +81,10 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks); -uint32_t dispclk_dce112_get_validation_clock(struct display_clock *dc); - void dispclk_dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz); -void dispclk_dce112_set_clock_state( - struct display_clock *dc, - struct display_clock_state clk_state); - bool dispclk_dce112_set_min_clocks_state( struct display_clock *base, enum clocks_state clocks_state); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c index eedcfd6232fc..89ee8bd96979 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -90,380 +90,6 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; #define FROM_DISPLAY_CLOCK(base) \ container_of(base, struct display_clock_dce80, disp_clk) -static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params) -{ - /* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/ - struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1); - - if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A) - return deep_color_factor; - - switch (params->deep_color_depth) { - case COLOR_DEPTH_101010: - /*deep color ratio for 30bpp is 30/24 = 1.25*/ - deep_color_factor = dal_fixed32_32_from_fraction(30, 24); - break; - - case COLOR_DEPTH_121212: - /* deep color ratio for 36bpp is 36/24 = 1.5*/ - deep_color_factor = dal_fixed32_32_from_fraction(36, 24); - break; - - case COLOR_DEPTH_161616: - /* deep color ratio for 48bpp is 48/24 = 2.0 */ - deep_color_factor = dal_fixed32_32_from_fraction(48, 24); - break; - default: - break; - } - return deep_color_factor; -} - -static uint32_t get_scaler_efficiency(struct min_clock_params *params) -{ - uint32_t scaler_efficiency = 3; - - switch (params->scaler_efficiency) { - case V_SCALER_EFFICIENCY_LB18BPP: - case V_SCALER_EFFICIENCY_LB24BPP: - scaler_efficiency = 4; - break; - - case V_SCALER_EFFICIENCY_LB30BPP: - case V_SCALER_EFFICIENCY_LB36BPP: - scaler_efficiency = 3; - break; - - default: - break; - } - - return scaler_efficiency; -} - -static uint32_t get_actual_required_display_clk( - struct display_clock_dce80 *disp_clk, - uint32_t target_clk_khz) -{ - uint32_t disp_clk_khz = target_clk_khz; - uint32_t div = INVALID_DIVIDER; - uint32_t did = INVALID_DID; - uint32_t scaled_vco = - disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR; - - ASSERT(disp_clk_khz); - - if (disp_clk_khz) - div = scaled_vco / disp_clk_khz; - - did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div); - - if (did != INVALID_DID) { - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, did); - - if ((div != INVALID_DIVIDER) && - (did > DIVIDER_RANGE_01_BASE_DIVIDER_ID)) - if (disp_clk_khz > (scaled_vco / div)) - div = dal_divider_range_get_divider( - divider_ranges, DIVIDER_RANGE_MAX, - did - 1); - - if (div != INVALID_DIVIDER) - disp_clk_khz = scaled_vco / div; - - } - /* We need to add 10KHz to this value because the accuracy in VBIOS is - in 10KHz units. So we need to always round the last digit up in order - to reach the next div level.*/ - return disp_clk_khz + 10; -} - -static uint32_t get_validation_clock(struct display_clock *dc) -{ - uint32_t clk = 0; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - switch (disp_clk->max_clks_state) { - case CLOCKS_STATE_ULTRA_LOW: - /*Currently not supported, it has 0 in table entry*/ - case CLOCKS_STATE_LOW: - clk = max_clks_by_state[CLOCKS_STATE_LOW]. - display_clk_khz; - break; - - case CLOCKS_STATE_NOMINAL: - clk = max_clks_by_state[CLOCKS_STATE_NOMINAL]. - display_clk_khz; - break; - - case CLOCKS_STATE_PERFORMANCE: - clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE]. - display_clk_khz; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State*/ - BREAK_TO_DEBUGGER(); - /* just return the display engine clock for - * lowest supported state*/ - clk = max_clks_by_state[CLOCKS_STATE_LOW]. - display_clk_khz; - break; - } - return clk; -} - -static uint32_t calc_single_display_min_clks( - struct display_clock *base, - struct min_clock_params *params, - bool set_clk) -{ - struct fixed32_32 h_scale = dal_fixed32_32_from_int(1); - struct fixed32_32 v_scale = dal_fixed32_32_from_int(1); - uint32_t pix_clk_khz = params->requested_pixel_clock; - uint32_t line_total = params->timing_info.h_total; - uint32_t max_clk_khz = get_validation_clock(base); - struct fixed32_32 deep_color_factor = get_deep_color_factor(params); - uint32_t scaler_efficiency = get_scaler_efficiency(params); - struct fixed32_32 v_filter_init; - uint32_t v_filter_init_trunc; - struct fixed32_32 v_filter_init_ceil; - struct fixed32_32 src_lines_per_dst_line; - uint32_t src_wdth_rnd_to_chunks; - struct fixed32_32 scaling_coeff; - struct fixed32_32 fx_disp_clk_khz; - struct fixed32_32 fx_alt_disp_clk_khz; - uint32_t disp_clk_khz; - uint32_t alt_disp_clk_khz; - struct display_clock_dce80 *dc = FROM_DISPLAY_CLOCK(base); - - if (0 != params->dest_view.height && 0 != params->dest_view.width) { - - h_scale = dal_fixed32_32_from_fraction( - params->source_view.width, - params->dest_view.width); - v_scale = dal_fixed32_32_from_fraction( - params->source_view.height, - params->dest_view.height); - } - - v_filter_init = dal_fixed32_32_from_fraction( - params->scaling_info.v_taps, 2u); - v_filter_init = dal_fixed32_32_add(v_filter_init, - dal_fixed32_32_div_int(v_scale, 2)); - v_filter_init = dal_fixed32_32_add(v_filter_init, - dal_fixed32_32_from_fraction(15, 10)); - - v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init); - - v_filter_init_ceil = dal_fixed32_32_from_fraction( - v_filter_init_trunc, 2); - v_filter_init_ceil = dal_fixed32_32_from_int( - dal_fixed32_32_ceil(v_filter_init_ceil)); - v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2); - v_filter_init_ceil = dal_fixed32_32_div_int(v_filter_init_ceil, 3); - v_filter_init_ceil = dal_fixed32_32_from_int( - dal_fixed32_32_ceil(v_filter_init_ceil)); - - src_lines_per_dst_line = dal_fixed32_32_max( - dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_scale)), - v_filter_init_ceil); - - src_wdth_rnd_to_chunks = - ((params->source_view.width - 1) / 128) * 128 + 256; - - scaling_coeff = dal_fixed32_32_max( - dal_fixed32_32_from_fraction(params->scaling_info.h_taps, 4), - dal_fixed32_32_mul( - dal_fixed32_32_from_fraction( - params->scaling_info.v_taps, - scaler_efficiency), - h_scale)); - - scaling_coeff = dal_fixed32_32_max(scaling_coeff, h_scale); - - fx_disp_clk_khz = dal_fixed32_32_mul( - scaling_coeff, dal_fixed32_32_from_fraction(11, 10)); - if (0 != line_total) { - struct fixed32_32 d_clk = dal_fixed32_32_mul_int( - src_lines_per_dst_line, src_wdth_rnd_to_chunks); - d_clk = dal_fixed32_32_div_int(d_clk, line_total); - d_clk = dal_fixed32_32_mul(d_clk, - dal_fixed32_32_from_fraction(11, 10)); - fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, d_clk); - } - - fx_disp_clk_khz = dal_fixed32_32_max(fx_disp_clk_khz, - dal_fixed32_32_mul(deep_color_factor, - dal_fixed32_32_from_fraction(11, 10))); - - fx_disp_clk_khz = dal_fixed32_32_mul_int(fx_disp_clk_khz, pix_clk_khz); - fx_disp_clk_khz = dal_fixed32_32_mul(fx_disp_clk_khz, - dal_fixed32_32_from_fraction(1005, 1000)); - - fx_alt_disp_clk_khz = scaling_coeff; - - if (0 != line_total) { - struct fixed32_32 d_clk = dal_fixed32_32_mul_int( - src_lines_per_dst_line, src_wdth_rnd_to_chunks); - d_clk = dal_fixed32_32_div_int(d_clk, line_total); - d_clk = dal_fixed32_32_mul(d_clk, - dal_fixed32_32_from_fraction(105, 100)); - fx_alt_disp_clk_khz = dal_fixed32_32_max( - fx_alt_disp_clk_khz, d_clk); - } - fx_alt_disp_clk_khz = dal_fixed32_32_max( - fx_alt_disp_clk_khz, fx_alt_disp_clk_khz); - - fx_alt_disp_clk_khz = dal_fixed32_32_mul_int( - fx_alt_disp_clk_khz, pix_clk_khz); - - /* convert to integer*/ - disp_clk_khz = dal_fixed32_32_floor(fx_disp_clk_khz); - alt_disp_clk_khz = dal_fixed32_32_floor(fx_alt_disp_clk_khz); - - if (set_clk) { /* only compensate clock if we are going to set it.*/ - disp_clk_khz = get_actual_required_display_clk( - dc, disp_clk_khz); - alt_disp_clk_khz = get_actual_required_display_clk( - dc, alt_disp_clk_khz); - } - - if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz)) - disp_clk_khz = alt_disp_clk_khz; - - return disp_clk_khz; - -} - -static uint32_t calc_cursor_bw_for_min_clks(struct min_clock_params *params) -{ - - struct fixed32_32 v_scale = dal_fixed32_32_from_int(1); - struct fixed32_32 v_filter_ceiling; - struct fixed32_32 src_lines_per_dst_line; - struct fixed32_32 cursor_bw; - - /* DCE8 Mode Support and Mode Set Architecture Specification Rev 1.3 - 6.3.3 Cursor data Throughput requirement on DISPCLK - The MCIF to DCP cursor data return throughput is one pixel per DISPCLK - shared among the display heads. - If (Total Cursor Bandwidth in pixels for All heads> DISPCLK) - The mode is not supported - Cursor Bandwidth in Pixels = Cursor Width * - (SourceLinesPerDestinationLine / Line Time) - Assuming that Cursor Width = 128 - */ - /*In the hardware doc they mention an Interlace Factor - It is not used here because we have already used it when - calculating destination view*/ - if (0 != params->dest_view.height) - v_scale = dal_fixed32_32_from_fraction( - params->source_view.height, - params->dest_view.height); - - { - /*Do: Vertical Filter Init = 0.5 + VTAPS/2 + VSR/2 * Interlace Factor*/ - /*Interlace Factor is included in verticalScaleRatio*/ - struct fixed32_32 v_filter = dal_fixed32_32_add( - dal_fixed32_32_from_fraction(params->scaling_info.v_taps, 2), - dal_fixed32_32_div_int(v_scale, 2)); - /*Do : Ceiling (Vertical Filter Init, 2)/3 )*/ - v_filter_ceiling = dal_fixed32_32_div_int(v_filter, 2); - v_filter_ceiling = dal_fixed32_32_mul_int( - dal_fixed32_32_from_int(dal_fixed32_32_ceil(v_filter_ceiling)), - 2); - v_filter_ceiling = dal_fixed32_32_div_int(v_filter_ceiling, 3); - } - /*Do : MAX( CeilCeiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/ - /*Do : SourceLinesPerDestinationLine = - * MAX( Ceiling (VSR), Ceiling (Vertical Filter Init, 2)/3 )*/ - src_lines_per_dst_line = dal_fixed32_32_max(v_scale, v_filter_ceiling); - - if ((params->requested_pixel_clock != 0) && - (params->timing_info.h_total != 0)) { - /* pixelClock is in units of KHz. Calc lineTime in us*/ - struct fixed32_32 inv_line_time = dal_fixed32_32_from_fraction( - params->requested_pixel_clock, - params->timing_info.h_total); - cursor_bw = dal_fixed32_32_mul( - dal_fixed32_32_mul_int(inv_line_time, 128), - src_lines_per_dst_line); - } - - /* convert to integer*/ - return dal_fixed32_32_floor(cursor_bw); -} - -static bool validate( - struct display_clock *dc, - struct min_clock_params *params) -{ - uint32_t max_clk_khz = get_validation_clock(dc); - uint32_t req_clk_khz; - - if (params == NULL) - return false; - - req_clk_khz = calc_single_display_min_clks(dc, params, false); - - return (req_clk_khz <= max_clk_khz); -} - -static uint32_t calculate_min_clock( - struct display_clock *dc, - uint32_t path_num, - struct min_clock_params *params) -{ - uint32_t i; - uint32_t validation_clk_khz = get_validation_clock(dc); - uint32_t min_clk_khz = validation_clk_khz; - uint32_t max_clk_khz = 0; - uint32_t total_cursor_bw = 0; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - if (disp_clk->use_max_disp_clk) - return min_clk_khz; - - if (params != NULL) { - uint32_t disp_clk_khz = 0; - - for (i = 0; i < path_num; ++i) { - disp_clk_khz = calc_single_display_min_clks( - dc, params, true); - - /* update the max required clock found*/ - if (disp_clk_khz > max_clk_khz) - max_clk_khz = disp_clk_khz; - - disp_clk_khz = calc_cursor_bw_for_min_clks(params); - - total_cursor_bw += disp_clk_khz; - - params++; - - } - } - - max_clk_khz = (total_cursor_bw > max_clk_khz) ? total_cursor_bw : - max_clk_khz; - - min_clk_khz = max_clk_khz; - - /*"Cursor data Throughput requirement on DISPCLK is now a factor, - * need to change the code */ - ASSERT(total_cursor_bw < validation_clk_khz); - - if (min_clk_khz > validation_clk_khz) - min_clk_khz = validation_clk_khz; - else if (min_clk_khz < dc->min_display_clk_threshold_khz) - min_clk_khz = dc->min_display_clk_threshold_khz; - - return min_clk_khz; -} - static void set_clock( struct display_clock *dc, uint32_t requested_clk_khz) @@ -493,54 +119,6 @@ static void set_clock( disp_clk->cur_min_clks_state = CLOCKS_STATE_NOMINAL; } -static uint32_t get_clock(struct display_clock *dc) -{ - uint32_t disp_clock = get_validation_clock(dc); - uint32_t target_div = INVALID_DIVIDER; - uint32_t addr = mmDENTIST_DISPCLK_CNTL; - uint32_t value = 0; - uint32_t field = 0; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk) - return disp_clk->dfs_bypass_disp_clk; - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed - DID DENTIST_DISPCLK_WDIVIDER.*/ - value = dm_read_reg(dc->ctx, addr); - field = get_reg_field_value( - value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER); - - /* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - field); - - if (target_div != INVALID_DIVIDER) - /* Calculate the current DFS clock in KHz. - Should be okay up to 42.9 THz before overflowing.*/ - disp_clock = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - return disp_clock; -} - -static void set_clock_state( - struct display_clock *dc, - struct display_clock_state clk_state) -{ - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - disp_clk->clock_state = clk_state; -} -static struct display_clock_state get_clock_state( - struct display_clock *dc) -{ - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - return disp_clk->clock_state; -} - static enum clocks_state get_min_clocks_state(struct display_clock *dc) { struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); @@ -818,11 +396,6 @@ static bool display_clock_integrated_info_construct( return true; } -static uint32_t get_dfs_bypass_threshold(struct display_clock *dc) -{ - return DCE80_DFS_BYPASS_THRESHOLD_KHZ; -} - static void destroy(struct display_clock **dc) { struct display_clock_dce80 *disp_clk; @@ -833,32 +406,34 @@ static void destroy(struct display_clock **dc) } static const struct display_clock_funcs funcs = { - .calculate_min_clock = calculate_min_clock, .destroy = destroy, - .get_clock = get_clock, - .get_clock_state = get_clock_state, - .get_dfs_bypass_threshold = get_dfs_bypass_threshold, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, - .get_validation_clock = get_validation_clock, .set_clock = set_clock, - .set_clock_state = set_clock_state, - .set_dp_ref_clock_source = - dal_display_clock_base_set_dp_ref_clock_source, .set_min_clocks_state = set_min_clocks_state, - .store_max_clocks_state = store_max_clocks_state, - .validate = validate, + .store_max_clocks_state = store_max_clocks_state }; -static bool display_clock_construct( - struct dc_context *ctx, - struct display_clock_dce80 *disp_clk) + +struct display_clock *dal_display_clock_dce80_create( + struct dc_context *ctx) { - struct display_clock *dc_base = &disp_clk->disp_clk; + struct display_clock_dce80 *disp_clk; + struct display_clock *dc_base; - if (!dal_display_clock_construct_base(dc_base, ctx)) - return false; + disp_clk = dm_alloc(sizeof(struct display_clock_dce80)); + + if (disp_clk == NULL) + return NULL; + + dc_base = &disp_clk->disp_clk; + + dc_base->ctx = ctx; + dc_base->id = CLOCK_SOURCE_ID_DCPLL; + dc_base->min_display_clk_threshold_khz = 0; + + dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; /* @@ -912,21 +487,6 @@ static bool display_clock_construct( DIVIDER_RANGE_03_STEP_SIZE, DIVIDER_RANGE_03_BASE_DIVIDER_ID, DIVIDER_RANGE_MAX_DIVIDER_ID); - return true; -} - -struct display_clock *dal_display_clock_dce80_create( - struct dc_context *ctx) -{ - struct display_clock_dce80 *disp_clk; - - disp_clk = dm_alloc(sizeof(struct display_clock_dce80)); - - if (disp_clk == NULL) - return NULL; - - if (display_clock_construct(ctx, disp_clk)) - return &disp_clk->disp_clk; dm_free(disp_clk); return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h index 944dd0380413..c675f1e30870 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -48,7 +48,6 @@ struct display_clock_dce80 { * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ uint32_t dfs_bypass_disp_clk; bool use_max_disp_clk; - struct display_clock_state clock_state; }; struct display_clock *dal_display_clock_dce80_create( diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c index bcc0a5132600..73d982732a67 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c @@ -26,49 +26,6 @@ #include "dm_services.h" #include "display_clock.h" -void dal_display_clock_base_set_dp_ref_clock_source( - struct display_clock *disp_clk, - enum clock_source_id clk_src) -{/*must be implemented in derived*/ - -} - -void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, - struct display_clock_state clk_state) -{ - /*Implemented only in DCE81*/ -} -struct display_clock_state dal_display_clock_base_get_clock_state( - struct display_clock *disp_clk) -{ - /*Implemented only in DCE81*/ - struct display_clock_state state = {0}; - return state; -} -uint32_t dal_display_clock_base_get_dfs_bypass_threshold( - struct display_clock *disp_clk) -{ - /*Implemented only in DCE81*/ - return 0; -} - -bool dal_display_clock_construct_base( - struct display_clock *base, - struct dc_context *ctx) -{ - base->ctx = ctx; - base->id = CLOCK_SOURCE_ID_DCPLL; - base->min_display_clk_threshold_khz = 0; - -/* Initially set current min clocks state to invalid since we - * cannot make any assumption about PPLIB's initial state. This will be updated - * by HWSS via SetMinClocksState() on first mode set prior to programming - * state dependent clocks.*/ - base->cur_min_clks_state = CLOCKS_STATE_INVALID; - - return true; -} - void dal_display_clock_destroy(struct display_clock **disp_clk) { if (!disp_clk || !*disp_clk) { @@ -81,26 +38,6 @@ void dal_display_clock_destroy(struct display_clock **disp_clk) *disp_clk = NULL; } -bool dal_display_clock_validate( - struct display_clock *disp_clk, - struct min_clock_params *params) -{ - return disp_clk->funcs->validate(disp_clk, params); -} - -uint32_t dal_display_clock_calculate_min_clock( - struct display_clock *disp_clk, - uint32_t path_num, - struct min_clock_params *params) -{ - return disp_clk->funcs->calculate_min_clock(disp_clk, path_num, params); -} - -uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_validation_clock(disp_clk); -} - void dal_display_clock_set_clock( struct display_clock *disp_clk, uint32_t requested_clock_khz) @@ -108,11 +45,6 @@ void dal_display_clock_set_clock( disp_clk->funcs->set_clock(disp_clk, requested_clock_khz); } -uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_clock(disp_clk); -} - bool dal_display_clock_get_min_clocks_state( struct display_clock *disp_clk, enum clocks_state *clocks_state) @@ -154,35 +86,6 @@ uint32_t dal_display_clock_get_dp_ref_clk_frequency( return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk); } -/*the second parameter of "switchreferenceclock" is - * a dummy argument for all pre dce 6.0 versions*/ - -void dal_display_clock_switch_reference_clock( - struct display_clock *disp_clk, - bool use_external_ref_clk, - uint32_t requested_clk_khz) -{ - /* TODO: requires Asic Control*/ - /* - struct ac_pixel_clk_params params; - struct asic_control *ac = - dal_adapter_service_get_asic_control(disp_clk->as); - dc_service_memset(¶ms, 0, sizeof(struct ac_pixel_clk_params)); - - params.tgt_pixel_clk_khz = requested_clk_khz; - params.flags.SET_EXTERNAL_REF_DIV_SRC = use_external_ref_clk; - params.pll_id = disp_clk->id; - dal_asic_control_program_display_engine_pll(ac, ¶ms); - */ -} - -void dal_display_clock_set_dp_ref_clock_source( - struct display_clock *disp_clk, - enum clock_source_id clk_src) -{ - disp_clk->funcs->set_dp_ref_clock_source(disp_clk, clk_src); -} - void dal_display_clock_store_max_clocks_state( struct display_clock *disp_clk, enum clocks_state max_clocks_state) @@ -190,28 +93,3 @@ void dal_display_clock_store_max_clocks_state( disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state); } -void dal_display_clock_set_clock_state( - struct display_clock *disp_clk, - struct display_clock_state clk_state) -{ - disp_clk->funcs->set_clock_state(disp_clk, clk_state); -} - -struct display_clock_state dal_display_clock_get_clock_state( - struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_clock_state(disp_clk); -} - -uint32_t dal_display_clock_get_dfs_bypass_threshold( - struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_dfs_bypass_threshold(disp_clk); -} - -void dal_display_clock_invalid_clock_state( - struct display_clock *disp_clk) -{ - disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h index 663580d18a09..4db8442e717a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h @@ -30,14 +30,8 @@ struct display_clock_funcs { void (*destroy)(struct display_clock **to_destroy); - bool (*validate)(struct display_clock *disp_clk, - struct min_clock_params *params); - uint32_t (*calculate_min_clock)(struct display_clock *disp_clk, - uint32_t path_num, struct min_clock_params *params); - uint32_t (*get_validation_clock)(struct display_clock *disp_clk); void (*set_clock)(struct display_clock *disp_clk, uint32_t requested_clock_khz); - uint32_t (*get_clock)(struct display_clock *disp_clk); enum clocks_state (*get_min_clocks_state)( struct display_clock *disp_clk); enum clocks_state (*get_required_clocks_state)( @@ -46,15 +40,8 @@ struct display_clock_funcs { bool (*set_min_clocks_state)(struct display_clock *disp_clk, enum clocks_state clocks_state); uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); - void (*set_dp_ref_clock_source)(struct display_clock *disp_clk, - enum clock_source_id clk_src); void (*store_max_clocks_state)(struct display_clock *disp_clk, enum clocks_state max_clocks_state); - void (*set_clock_state)(struct display_clock *disp_clk, - struct display_clock_state clk_state); - struct display_clock_state (*get_clock_state)( - struct display_clock *disp_clk); - uint32_t (*get_dfs_bypass_threshold)(struct display_clock *disp_clk); }; @@ -66,21 +53,6 @@ struct display_clock { enum clocks_state cur_min_clks_state; }; -void dal_display_clock_base_set_dp_ref_clock_source( - struct display_clock *disp_clk, - enum clock_source_id clk_src); -struct display_clock_state dal_display_clock_base_get_clock_state( - struct display_clock *disp_clk); -uint32_t dal_display_clock_base_get_dfs_bypass_threshold( - struct display_clock *disp_clk); -void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk, - struct display_clock_state clk_state); -bool dal_display_clock_construct_base( - struct display_clock *base, - struct dc_context *ctx); - -uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); - void dal_display_clock_store_max_clocks_state( struct display_clock *disp_clk, enum clocks_state max_clocks_state); diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index 2006fa21f54c..ef519a284e0f 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -30,60 +30,6 @@ #include "grph_object_defs.h" #include "signal_types.h" -/* Timing related information*/ -struct dc_timing_params { - uint32_t INTERLACED:1; - uint32_t HCOUNT_BY_TWO:1; - uint32_t PIXEL_REPETITION:4; /*< values 1 to 10 supported*/ - uint32_t PREFETCH:1; - - uint32_t h_total; - uint32_t h_addressable; - uint32_t h_sync_width; -}; - -/* Scaling related information*/ -struct dc_scaling_params { - uint32_t h_overscan_right; - uint32_t h_overscan_left; - uint32_t h_taps; - uint32_t v_taps; -}; - -/* VScalerEfficiency */ -enum v_scaler_efficiency { - V_SCALER_EFFICIENCY_LB36BPP = 0, - V_SCALER_EFFICIENCY_LB30BPP = 1, - V_SCALER_EFFICIENCY_LB24BPP = 2, - V_SCALER_EFFICIENCY_LB18BPP = 3 -}; - -/* Parameters required for minimum Engine - * and minimum Display clock calculations*/ -struct min_clock_params { - uint32_t id; - uint32_t requested_pixel_clock; /* in KHz */ - uint32_t actual_pixel_clock; /* in KHz */ - struct view source_view; - struct view dest_view; - struct dc_timing_params timing_info; - struct dc_scaling_params scaling_info; - enum signal_type signal_type; - enum dc_color_depth deep_color_depth; - enum v_scaler_efficiency scaler_efficiency; - bool line_buffer_prefetch_enabled; -}; - -/* Result of Minimum System and Display clock calculations. - * Minimum System clock and Display clock, source and path to be used - * for Display clock*/ -struct minimum_clocks_calculation_result { - uint32_t min_sclk_khz; - uint32_t min_dclk_khz; - uint32_t min_mclk_khz; - uint32_t min_deep_sleep_sclk; -}; - /* Enumeration of all clocks states */ enum clocks_state { CLOCKS_STATE_INVALID = 0, @@ -110,10 +56,6 @@ struct state_dependent_clocks { uint32_t pixel_clk_khz; }; -struct display_clock_state { - uint32_t DFS_BYPASS_ACTIVE:1; -}; - struct display_clock; struct display_clock *dal_display_clock_dce112_create( @@ -126,18 +68,9 @@ struct display_clock *dal_display_clock_dce80_create( struct dc_context *ctx); void dal_display_clock_destroy(struct display_clock **to_destroy); -bool dal_display_clock_validate( - struct display_clock *disp_clk, - struct min_clock_params *params); -uint32_t dal_display_clock_calculate_min_clock( - struct display_clock *disp_clk, - uint32_t path_num, - struct min_clock_params *params); -uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk); void dal_display_clock_set_clock( struct display_clock *disp_clk, uint32_t requested_clock_khz); -uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk); bool dal_display_clock_get_min_clocks_state( struct display_clock *disp_clk, enum clocks_state *clocks_state); @@ -150,26 +83,8 @@ bool dal_display_clock_set_min_clocks_state( enum clocks_state clocks_state); uint32_t dal_display_clock_get_dp_ref_clk_frequency( struct display_clock *disp_clk); -/*the second parameter of "switchreferenceclock" is - * a dummy argument for all pre dce 6.0 versions*/ -void dal_display_clock_switch_reference_clock( - struct display_clock *disp_clk, - bool use_external_ref_clk, - uint32_t requested_clock_khz); -void dal_display_clock_set_dp_ref_clock_source( - struct display_clock *disp_clk, - enum clock_source_id clk_src); void dal_display_clock_store_max_clocks_state( struct display_clock *disp_clk, enum clocks_state max_clocks_state); -void dal_display_clock_set_clock_state( - struct display_clock *disp_clk, - struct display_clock_state clk_state); -struct display_clock_state dal_display_clock_get_clock_state( - struct display_clock *disp_clk); -uint32_t dal_display_clock_get_dfs_bypass_threshold( - struct display_clock *disp_clk); -void dal_display_clock_invalid_clock_state( - struct display_clock *disp_clk); #endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- GitLab From 1a687574a71f187dedcab3ac6012b0889c5a4e99 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 10:49:51 -0500 Subject: [PATCH 0077/2898] drm/amd/display: restyle display clock calls part 1 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- .../amd/display/dc/dce100/dce100_resource.c | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 48 ++++--------------- .../amd/display/dc/dce110/dce110_resource.c | 2 +- .../amd/display/dc/dce112/dce112_resource.c | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 2 +- .../dc/gpu/dce112/display_clock_dce112.c | 1 - .../dc/gpu/dce112/display_clock_dce112.h | 1 - .../drm/amd/display/dc/gpu/display_clock.c | 20 -------- .../drm/amd/display/dc/gpu/display_clock.h | 30 ------------ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 - .../display/include/display_clock_interface.h | 35 ++++++++++---- 12 files changed, 42 insertions(+), 107 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 424a7d4b8731..70dc70685471 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1224,7 +1224,9 @@ bool dc_pre_update_surfaces_to_target( if (prev_disp_clk < context->bw_results.dispclk_khz) { pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); - core_dc->hwss.set_display_clock(context); + context->res_ctx.pool->display_clock->funcs->set_clock( + context->res_ctx.pool->display_clock, + context->bw_results.dispclk_khz * 115 / 100); core_dc->current_context->bw_results.dispclk_khz = context->bw_results.dispclk_khz; } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9ace6d1cca79..8f18a9403525 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -984,7 +984,7 @@ static bool construct( dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - dal_display_clock_store_max_clocks_state( + pool->base.display_clock->funcs->store_max_clocks_state( pool->base.display_clock, max_clocks_state); } { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1a682996b531..16ee49dba97b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -497,8 +497,8 @@ static void build_audio_output( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { audio_output->pll_info.dp_dto_source_clock_in_khz = - dal_display_clock_get_dp_ref_clk_frequency( - pipe_ctx->dis_clk); + pipe_ctx->dis_clk->funcs->get_dp_ref_clk_frequency( + pipe_ctx->dis_clk); } audio_output->pll_info.feed_back_divider = @@ -788,39 +788,6 @@ void dce110_enable_accelerated_mode(struct core_dc *dc) bios_set_scratch_acc_mode_change(dc->ctx->dc_bios); } -/** - * Call display_engine_clock_dce80 to perform the Dclk programming. - */ -void dce110_set_display_clock(struct validate_context *context) -{ - /* Program the display engine clock. - * Check DFS bypass mode support or not. DFSbypass feature is only when - * BIOS GPU info table reports support. */ - - if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) { - /*TODO: set_display_clock_dfs_bypass( - hws, - path_set, - context->res_ctx.pool->display_clock, - context->res_ctx.min_clocks.min_dclk_khz);*/ - } else { - /* - * TODO: need to either port work around from DAL2 function - * getActualRequiredDisplayClock or program displayclock without - * calling vbios. Currently temporily work - * around by increasing the displclk by 15 percent - */ - dal_display_clock_set_clock( - context->res_ctx.pool->display_clock, - context->bw_results.dispclk_khz * 115 / 100); - } - - - /* TODO: When changing display engine clock, DMCU WaitLoop must be - * reconfigured in order to maintain the same delays within DMCU - * programming sequences. */ -} - static uint32_t compute_pstate_blackout_duration( struct bw_fixed blackout_duration, const struct core_stream *stream) @@ -1267,8 +1234,10 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); if (context->bw_results.dispclk_khz - > dc->current_context->bw_results.dispclk_khz) - dc->hwss.set_display_clock(context); + > dc->current_context->bw_results.dispclk_khz) + context->res_ctx.pool->display_clock->funcs->set_clock( + context->res_ctx.pool->display_clock, + context->bw_results.dispclk_khz * 115 / 100); for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = @@ -1738,7 +1707,9 @@ static void dce110_set_bandwidth(struct core_dc *dc) program_wm_for_pipe(dc, pipe_ctx, dc->current_context); } - dc->hwss.set_display_clock(dc->current_context); + dc->current_context->res_ctx.pool->display_clock->funcs->set_clock( + dc->current_context->res_ctx.pool->display_clock, + dc->current_context->bw_results.dispclk_khz * 115 / 100); } static void dce110_program_front_end_for_pipe( @@ -1959,7 +1930,6 @@ static const struct hw_sequencer_funcs dce110_funcs = { .enable_display_power_gating = dce110_enable_display_power_gating, .power_down_front_end = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, - .set_display_clock = dce110_set_display_clock, .set_displaymarks = dce110_set_displaymarks, .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe, .set_bandwidth = dce110_set_bandwidth, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index cac3dc425039..a63112b2bd36 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1315,7 +1315,7 @@ static bool construct( dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - dal_display_clock_store_max_clocks_state( + pool->base.display_clock->funcs->store_max_clocks_state( pool->base.display_clock, max_clocks_state); } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 4e3273c0fa91..70616019ae47 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1315,7 +1315,7 @@ static bool construct( dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - dal_display_clock_store_max_clocks_state( + pool->base.display_clock->funcs->store_max_clocks_state( pool->base.display_clock, max_clocks_state); } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 3b626b7883d4..dfff2bfff13d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -978,7 +978,7 @@ static bool construct( dce80_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - dal_display_clock_store_max_clocks_state( + pool->base.display_clock->funcs->store_max_clocks_state( pool->base.display_clock, max_clocks_state); } diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index bf044260c0bb..665832b0718a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -383,7 +383,6 @@ bool dal_display_clock_dce112_construct( struct display_clock *dc_base = &dc112->disp_clk_base; dc_base->ctx = ctx; - dc_base->id = CLOCK_SOURCE_ID_DCPLL; dc_base->min_display_clk_threshold_khz = 0; dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 5ab31185d29d..47a149709d91 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -32,7 +32,6 @@ struct display_clock_dce112 { /* Max display block clocks state*/ enum clocks_state max_clks_state; bool use_max_disp_clk; - uint32_t crystal_freq_khz; uint32_t dentist_vco_freq_khz; /* Cache the status of DFS-bypass feature*/ bool dfs_bypass_enabled; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c index 73d982732a67..c70c6b25892e 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c @@ -38,13 +38,6 @@ void dal_display_clock_destroy(struct display_clock **disp_clk) *disp_clk = NULL; } -void dal_display_clock_set_clock( - struct display_clock *disp_clk, - uint32_t requested_clock_khz) -{ - disp_clk->funcs->set_clock(disp_clk, requested_clock_khz); -} - bool dal_display_clock_get_min_clocks_state( struct display_clock *disp_clk, enum clocks_state *clocks_state) @@ -80,16 +73,3 @@ bool dal_display_clock_set_min_clocks_state( return true; } -uint32_t dal_display_clock_get_dp_ref_clk_frequency( - struct display_clock *disp_clk) -{ - return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk); -} - -void dal_display_clock_store_max_clocks_state( - struct display_clock *disp_clk, - enum clocks_state max_clocks_state) -{ - disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state); -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h index 4db8442e717a..68d2ab0500a6 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h @@ -28,34 +28,4 @@ #include "include/display_clock_interface.h" -struct display_clock_funcs { - void (*destroy)(struct display_clock **to_destroy); - void (*set_clock)(struct display_clock *disp_clk, - uint32_t requested_clock_khz); - enum clocks_state (*get_min_clocks_state)( - struct display_clock *disp_clk); - enum clocks_state (*get_required_clocks_state)( - struct display_clock *disp_clk, - struct state_dependent_clocks *req_clocks); - bool (*set_min_clocks_state)(struct display_clock *disp_clk, - enum clocks_state clocks_state); - uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); - void (*store_max_clocks_state)(struct display_clock *disp_clk, - enum clocks_state max_clocks_state); - -}; - -struct display_clock { - struct dc_context *ctx; - const struct display_clock_funcs *funcs; - uint32_t min_display_clk_threshold_khz; - enum clock_source_id id; - - enum clocks_state cur_min_clks_state; -}; -void dal_display_clock_store_max_clocks_state( - struct display_clock *disp_clk, - enum clocks_state max_clocks_state); - - #endif /* __DAL_DISPLAY_CLOCK_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 35a556dd9054..50d499cc01a4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -132,8 +132,6 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, struct validate_context *context); - void (*set_display_clock)(struct validate_context *context); - void (*set_bandwidth)(struct core_dc *dc); void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index ef519a284e0f..f49253714b1e 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -56,7 +56,31 @@ struct state_dependent_clocks { uint32_t pixel_clk_khz; }; -struct display_clock; +struct display_clock { + struct dc_context *ctx; + const struct display_clock_funcs *funcs; + uint32_t min_display_clk_threshold_khz; + enum clock_source_id id; + + enum clocks_state cur_min_clks_state; +}; + +struct display_clock_funcs { + void (*destroy)(struct display_clock **to_destroy); + void (*set_clock)(struct display_clock *disp_clk, + uint32_t requested_clock_khz); + enum clocks_state (*get_min_clocks_state)( + struct display_clock *disp_clk); + enum clocks_state (*get_required_clocks_state)( + struct display_clock *disp_clk, + struct state_dependent_clocks *req_clocks); + bool (*set_min_clocks_state)(struct display_clock *disp_clk, + enum clocks_state clocks_state); + uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); + void (*store_max_clocks_state)(struct display_clock *disp_clk, + enum clocks_state max_clocks_state); + +}; struct display_clock *dal_display_clock_dce112_create( struct dc_context *ctx); @@ -68,9 +92,7 @@ struct display_clock *dal_display_clock_dce80_create( struct dc_context *ctx); void dal_display_clock_destroy(struct display_clock **to_destroy); -void dal_display_clock_set_clock( - struct display_clock *disp_clk, - uint32_t requested_clock_khz); + bool dal_display_clock_get_min_clocks_state( struct display_clock *disp_clk, enum clocks_state *clocks_state); @@ -81,10 +103,5 @@ bool dal_display_clock_get_required_clocks_state( bool dal_display_clock_set_min_clocks_state( struct display_clock *disp_clk, enum clocks_state clocks_state); -uint32_t dal_display_clock_get_dp_ref_clk_frequency( - struct display_clock *disp_clk); -void dal_display_clock_store_max_clocks_state( - struct display_clock *disp_clk, - enum clocks_state max_clocks_state); #endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- GitLab From 5d6d185f32eb0cce16caff13e716d08b594a6046 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 11:03:37 -0500 Subject: [PATCH 0078/2898] drm/amd/display: restyle display clock calls part 2 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 11 +-- .../amd/display/dc/dce100/dce100_resource.c | 4 +- .../display/dc/dce110/dce110_hw_sequencer.c | 13 ++-- .../amd/display/dc/dce110/dce110_resource.c | 4 +- .../amd/display/dc/dce112/dce112_resource.c | 4 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 4 +- drivers/gpu/drm/amd/display/dc/gpu/Makefile | 2 +- .../dc/gpu/dce110/display_clock_dce110.h | 2 +- .../dc/gpu/dce112/display_clock_dce112.h | 2 +- .../dc/gpu/dce80/display_clock_dce80.h | 2 +- .../drm/amd/display/dc/gpu/display_clock.c | 75 ------------------- .../drm/amd/display/dc/gpu/display_clock.h | 31 -------- .../display/include/display_clock_interface.h | 11 --- 13 files changed, 30 insertions(+), 135 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/display_clock.h diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 70a25546de1e..ab4efde2d030 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1223,12 +1223,13 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) if (link_settings.link_rate == max_link_rate) { cur_min_clock_state = CLOCKS_STATE_INVALID; - if (dal_display_clock_get_min_clocks_state( - pipe_ctx->dis_clk, &cur_min_clock_state)) { + if (pipe_ctx->dis_clk->funcs->get_min_clocks_state) { + cur_min_clock_state = + pipe_ctx->dis_clk->funcs->get_min_clocks_state( + pipe_ctx->dis_clk); if (cur_min_clock_state < CLOCKS_STATE_NOMINAL) - dal_display_clock_set_min_clocks_state( - pipe_ctx->dis_clk, - CLOCKS_STATE_NOMINAL); + pipe_ctx->dis_clk->funcs->set_min_clocks_state( + pipe_ctx->dis_clk, CLOCKS_STATE_NOMINAL); } else { } } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 8f18a9403525..fa88eb163ab8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -717,7 +717,9 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) - dal_display_clock_destroy(&pool->base.display_clock); + pool->base.display_clock->funcs->destroy( + &pool->base.display_clock); + pool->base.display_clock = NULL; if (pool->base.irqs != NULL) dal_irq_service_destroy(&pool->base.irqs); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 16ee49dba97b..ca71509af74d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1099,9 +1099,11 @@ static void apply_min_clocks( if (!pre_mode_set) { /* set clock_state without verification */ - if (dal_display_clock_set_min_clocks_state( - pipe_ctx->dis_clk, *clocks_state)) + if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { + pipe_ctx->dis_clk->funcs->set_min_clocks_state( + pipe_ctx->dis_clk, *clocks_state); return; + } /* TODOFPGA */ } @@ -1114,9 +1116,10 @@ static void apply_min_clocks( req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( dc, context, true); - if (dal_display_clock_get_required_clocks_state( - pipe_ctx->dis_clk, &req_clocks, clocks_state)) { - dal_display_clock_set_min_clocks_state( + if (pipe_ctx->dis_clk->funcs->get_required_clocks_state) { + *clocks_state = pipe_ctx->dis_clk->funcs->get_required_clocks_state( + pipe_ctx->dis_clk, &req_clocks); + pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, *clocks_state); } else { } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index a63112b2bd36..6c713396e6ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -700,7 +700,9 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) { - dal_display_clock_destroy(&pool->base.display_clock); + pool->base.display_clock->funcs->destroy( + &pool->base.display_clock); + pool->base.display_clock = NULL; } if (pool->base.irqs != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 70616019ae47..8792c4ed6e65 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -734,7 +734,9 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) { - dal_display_clock_destroy(&pool->base.display_clock); + pool->base.display_clock->funcs->destroy( + &pool->base.display_clock); + pool->base.display_clock = NULL; } if (pool->base.irqs != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index dfff2bfff13d..1e829f805d42 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -657,7 +657,9 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) { - dal_display_clock_destroy(&pool->base.display_clock); + pool->base.display_clock->funcs->destroy( + &pool->base.display_clock); + pool->base.display_clock = NULL; } if (pool->base.irqs != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile index fd17af1ce88e..0b99a7474950 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpu/Makefile @@ -3,7 +3,7 @@ # It provides the control and status of HW adapter resources, # that are global for the ASIC and sharable between pipes. -GPU = display_clock.o divider_range.o +GPU = divider_range.o AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h index 88b4bdd75e56..703cd656b5b0 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h @@ -25,7 +25,7 @@ #ifndef __DAL_DISPLAY_CLOCK_DCE110_H__ #define __DAL_DISPLAY_CLOCK_DCE110_H__ -#include "gpu/display_clock.h" +#include "display_clock_interface.h" struct display_clock_dce110 { struct display_clock disp_clk_base; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 47a149709d91..34afff9a00bc 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -25,7 +25,7 @@ #ifndef __DAL_DISPLAY_CLOCK_DCE112_H__ #define __DAL_DISPLAY_CLOCK_DCE112_H__ -#include "gpu/display_clock.h" +#include "display_clock_interface.h" struct display_clock_dce112 { struct display_clock disp_clk_base; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h index c675f1e30870..273a5d902840 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -25,7 +25,7 @@ #ifndef __DAL_DISPLAY_CLOCK_DCE80_H__ #define __DAL_DISPLAY_CLOCK_DCE80_H__ -#include "gpu/display_clock.h" +#include "display_clock_interface.h" struct display_clock_dce80 { struct display_clock disp_clk; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c deleted file mode 100644 index c70c6b25892e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "display_clock.h" - -void dal_display_clock_destroy(struct display_clock **disp_clk) -{ - if (!disp_clk || !*disp_clk) { - BREAK_TO_DEBUGGER(); - return; - } - - (*disp_clk)->funcs->destroy(disp_clk); - - *disp_clk = NULL; -} - -bool dal_display_clock_get_min_clocks_state( - struct display_clock *disp_clk, - enum clocks_state *clocks_state) -{ - if (!disp_clk->funcs->get_min_clocks_state) - return false; - - *clocks_state = disp_clk->funcs->get_min_clocks_state(disp_clk); - return true; -} - -bool dal_display_clock_get_required_clocks_state( - struct display_clock *disp_clk, - struct state_dependent_clocks *req_clocks, - enum clocks_state *clocks_state) -{ - if (!disp_clk->funcs->get_required_clocks_state) - return false; - - *clocks_state = disp_clk->funcs->get_required_clocks_state( - disp_clk, req_clocks); - return true; -} - -bool dal_display_clock_set_min_clocks_state( - struct display_clock *disp_clk, - enum clocks_state clocks_state) -{ - if (!disp_clk->funcs->set_min_clocks_state) - return false; - - disp_clk->funcs->set_min_clocks_state(disp_clk, clocks_state); - return true; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h deleted file mode 100644 index 68d2ab0500a6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/display_clock.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_DISPLAY_CLOCK_H__ -#define __DAL_DISPLAY_CLOCK_H__ - -#include "include/display_clock_interface.h" - -#endif /* __DAL_DISPLAY_CLOCK_H__*/ diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index f49253714b1e..a46ceebe2452 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -93,15 +93,4 @@ struct display_clock *dal_display_clock_dce80_create( void dal_display_clock_destroy(struct display_clock **to_destroy); -bool dal_display_clock_get_min_clocks_state( - struct display_clock *disp_clk, - enum clocks_state *clocks_state); -bool dal_display_clock_get_required_clocks_state( - struct display_clock *disp_clk, - struct state_dependent_clocks *req_clocks, - enum clocks_state *clocks_state); -bool dal_display_clock_set_min_clocks_state( - struct display_clock *disp_clk, - enum clocks_state clocks_state); - #endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- GitLab From 3bad7c5ccfacca7a893b2960d872878d75a151d7 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 14:26:37 -0500 Subject: [PATCH 0079/2898] drm/amd/display: remove store clock state Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce100/dce100_resource.c | 8 +-- .../amd/display/dc/dce110/dce110_resource.c | 8 +-- .../amd/display/dc/dce112/dce112_resource.c | 8 +-- .../drm/amd/display/dc/dce80/dce80_resource.c | 8 +-- .../dc/gpu/dce110/display_clock_dce110.c | 47 +++-------------- .../dc/gpu/dce110/display_clock_dce110.h | 2 - .../dc/gpu/dce112/display_clock_dce112.c | 50 +++---------------- .../dc/gpu/dce112/display_clock_dce112.h | 2 - .../dc/gpu/dce80/display_clock_dce80.c | 50 +++---------------- .../dc/gpu/dce80/display_clock_dce80.h | 2 - .../display/include/display_clock_interface.h | 5 +- 11 files changed, 29 insertions(+), 161 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index fa88eb163ab8..446f50bb4e0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -981,14 +981,10 @@ static bool construct( /* get static clock information for PPLIB or firmware, save * max_clock_state */ - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { - enum clocks_state max_clocks_state = + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - - pool->base.display_clock->funcs->store_max_clocks_state( - pool->base.display_clock, max_clocks_state); - } { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 6c713396e6ba..d5d888bdf882 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1312,15 +1312,11 @@ static bool construct( /* get static clock information for PPLIB or firmware, save * max_clock_state */ - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { - enum clocks_state max_clocks_state = + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - pool->base.display_clock->funcs->store_max_clocks_state( - pool->base.display_clock, max_clocks_state); - } - { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 8792c4ed6e65..9903c9a4b8a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1312,15 +1312,11 @@ static bool construct( /* get static clock information for PPLIB or firmware, save * max_clock_state */ - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { - enum clocks_state max_clocks_state = + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = dce110_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - pool->base.display_clock->funcs->store_max_clocks_state( - pool->base.display_clock, max_clocks_state); - } - { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 1e829f805d42..51721d10c811 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -975,15 +975,11 @@ static bool construct( } - if (dm_pp_get_static_clocks(ctx, &static_clk_info)) { - enum clocks_state max_clocks_state = + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = dce80_resource_convert_clock_state_pp_to_dc( static_clk_info.max_clocks_state); - pool->base.display_clock->funcs->store_max_clocks_state( - pool->base.display_clock, max_clocks_state); - } - { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c index cc13afa326ad..ad7ebc1b434c 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -103,38 +103,6 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; * static functions *****************************************************************************/ -/* - * store_max_clocks_state - * - * @brief - * Cache the clock state - * - * @param - * struct display_clock *base - [out] cach the state in this structure - * enum clocks_state max_clocks_state - [in] state to be stored - */ -static void store_max_clocks_state( - struct display_clock *base, - enum clocks_state max_clocks_state) -{ - struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); - - switch (max_clocks_state) { - case CLOCKS_STATE_LOW: - case CLOCKS_STATE_NOMINAL: - case CLOCKS_STATE_PERFORMANCE: - case CLOCKS_STATE_ULTRA_LOW: - dc->max_clks_state = max_clocks_state; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State!*/ - ASSERT_CRITICAL(false); - break; - } -} - static enum clocks_state get_min_clocks_state(struct display_clock *base) { return base->cur_min_clks_state; @@ -148,7 +116,7 @@ static bool set_min_clocks_state( struct dm_pp_power_level_change_request level_change_req = { DM_PP_POWER_LEVEL_INVALID}; - if (clocks_state > dc->max_clks_state) { + if (clocks_state > base->max_clks_state) { /*Requested state exceeds max supported state.*/ dm_logger_write(base->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); @@ -349,7 +317,7 @@ static enum clocks_state get_required_clocks_state( { int32_t i; struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - enum clocks_state low_req_clk = disp_clk->max_clks_state; + enum clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ @@ -363,7 +331,7 @@ static enum clocks_state get_required_clocks_state( * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= max_clks_by_state[i].display_clk_khz) && (req_clocks->pixel_clk_khz <= @@ -433,7 +401,7 @@ static void set_clock( base->min_display_clk_threshold_khz); pxl_clk_params.target_pixel_clock = requested_clk_khz; - pxl_clk_params.pll_id = base->id; + pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); @@ -459,8 +427,7 @@ static const struct display_clock_funcs funcs = { .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, .set_clock = set_clock, - .set_min_clocks_state = set_min_clocks_state, - .store_max_clocks_state = store_max_clocks_state + .set_min_clocks_state = set_min_clocks_state }; static bool dal_display_clock_dce110_construct( @@ -471,7 +438,6 @@ static bool dal_display_clock_dce110_construct( struct dc_bios *bp = ctx->dc_bios; dc_base->ctx = ctx; - dc_base->id = CLOCK_SOURCE_ID_DCPLL; dc_base->min_display_clk_threshold_khz = 0; dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; @@ -488,12 +454,11 @@ static bool dal_display_clock_dce110_construct( dc110->gpu_pll_ss_divider = 1000; dc110->ss_on_gpu_pll = false; - dc_base->id = CLOCK_SOURCE_ID_DFS; /* Initially set max clocks state to nominal. This should be updated by * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc110->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; dal_divider_range_construct( ÷r_ranges[DIVIDER_RANGE_01], diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h index 703cd656b5b0..50b51c41b0d9 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h @@ -29,8 +29,6 @@ struct display_clock_dce110 { struct display_clock disp_clk_base; - /* Max display block clocks state*/ - enum clocks_state max_clks_state; bool use_max_disp_clk; uint32_t dentist_vco_freq_khz; /* Cache the status of DFS-bypass feature*/ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index 665832b0718a..d8c8d8a1e2b3 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -72,41 +72,6 @@ enum divider_range_step_size { static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; #define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 -/***************************************************************************** - * static functions - *****************************************************************************/ - -/* - * store_max_clocks_state - * - * @brief - * Cache the clock state - * - * @param - * struct display_clock *base - [out] cach the state in this structure - * enum clocks_state max_clocks_state - [in] state to be stored - */ -void dispclk_dce112_store_max_clocks_state( - struct display_clock *base, - enum clocks_state max_clocks_state) -{ - struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); - - switch (max_clocks_state) { - case CLOCKS_STATE_LOW: - case CLOCKS_STATE_NOMINAL: - case CLOCKS_STATE_PERFORMANCE: - case CLOCKS_STATE_ULTRA_LOW: - dc->max_clks_state = max_clocks_state; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State!*/ - ASSERT_CRITICAL(false); - break; - } -} enum clocks_state dispclk_dce112_get_min_clocks_state( struct display_clock *base) @@ -122,7 +87,7 @@ bool dispclk_dce112_set_min_clocks_state( struct dm_pp_power_level_change_request level_change_req = { DM_PP_POWER_LEVEL_INVALID}; - if (clocks_state > dc->max_clks_state) { + if (clocks_state > base->max_clks_state) { /*Requested state exceeds max supported state.*/ dm_logger_write(base->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); @@ -302,7 +267,7 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( { int32_t i; struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - enum clocks_state low_req_clk = disp_clk->max_clks_state; + enum clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ @@ -316,7 +281,7 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= (disp_clk->max_clks_by_state + i)-> display_clk_khz) && @@ -333,7 +298,6 @@ void dispclk_dce112_set_clock( uint32_t requested_clk_khz) { struct bp_set_dce_clock_parameters dce_clk_params; - struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); struct dc_bios *bp = base->ctx->dc_bios; /* Prepare to program display clock*/ @@ -345,7 +309,7 @@ void dispclk_dce112_set_clock( base->min_display_clk_threshold_khz); dce_clk_params.target_clock_frequency = requested_clk_khz; - dce_clk_params.pll_id = dc->disp_clk_base.id; + dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; bp->funcs->set_dce_clock(bp, &dce_clk_params); @@ -372,8 +336,7 @@ static const struct display_clock_funcs funcs = { .get_min_clocks_state = dispclk_dce112_get_min_clocks_state, .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, .set_clock = dispclk_dce112_set_clock, - .set_min_clocks_state = dispclk_dce112_set_min_clocks_state, - .store_max_clocks_state = dispclk_dce112_store_max_clocks_state, + .set_min_clocks_state = dispclk_dce112_set_min_clocks_state }; bool dal_display_clock_dce112_construct( @@ -399,12 +362,11 @@ bool dal_display_clock_dce112_construct( dc112->gpu_pll_ss_divider = 1000; dc112->ss_on_gpu_pll = false; - dc_base->id = CLOCK_SOURCE_ID_DFS; /* Initially set max clocks state to nominal. This should be updated by * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc112->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; dc112->disp_clk_base.min_display_clk_threshold_khz = (dc112->dentist_vco_freq_khz / 62); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 34afff9a00bc..398af34720f7 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -29,8 +29,6 @@ struct display_clock_dce112 { struct display_clock disp_clk_base; - /* Max display block clocks state*/ - enum clocks_state max_clks_state; bool use_max_disp_clk; uint32_t dentist_vco_freq_khz; /* Cache the status of DFS-bypass feature*/ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c index 89ee8bd96979..b101f7de2d11 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -95,28 +95,20 @@ static void set_clock( uint32_t requested_clk_khz) { struct bp_pixel_clock_parameters pxl_clk_params; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); struct dc_bios *bp = dc->ctx->dc_bios; /* Prepare to program display clock*/ memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); pxl_clk_params.target_pixel_clock = requested_clk_khz; - pxl_clk_params.pll_id = dc->id; + pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); - if (disp_clk->dfs_bypass_enabled) { - - /* Cache the fixed display clock*/ - disp_clk->dfs_bypass_disp_clk = - pxl_clk_params.dfs_bypass_display_clock; - } - /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) - disp_clk->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + dc->cur_min_clks_state = CLOCKS_STATE_NOMINAL; } static enum clocks_state get_min_clocks_state(struct display_clock *dc) @@ -131,8 +123,7 @@ static enum clocks_state get_required_clocks_state struct state_dependent_clocks *req_clocks) { int32_t i; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - enum clocks_state low_req_clk = disp_clk->max_clks_state; + enum clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ @@ -144,7 +135,7 @@ static enum clocks_state get_required_clocks_state * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= max_clks_by_state[i].display_clk_khz) && (req_clocks->pixel_clk_khz <= @@ -158,12 +149,10 @@ static bool set_min_clocks_state( struct display_clock *dc, enum clocks_state clocks_state) { - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - struct dm_pp_power_level_change_request level_change_req = { DM_PP_POWER_LEVEL_INVALID}; - if (clocks_state > disp_clk->max_clks_state) { + if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); @@ -271,28 +260,6 @@ static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) return dp_ref_clk_khz; } -static void store_max_clocks_state( - struct display_clock *dc, - enum clocks_state max_clocks_state) -{ - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - switch (max_clocks_state) { - case CLOCKS_STATE_LOW: - case CLOCKS_STATE_NOMINAL: - case CLOCKS_STATE_PERFORMANCE: - case CLOCKS_STATE_ULTRA_LOW: - disp_clk->max_clks_state = max_clocks_state; - break; - - case CLOCKS_STATE_INVALID: - default: - /*Invalid Clocks State!*/ - BREAK_TO_DEBUGGER(); - break; - } -} - static void display_clock_ss_construct( struct display_clock_dce80 *disp_clk) { @@ -411,8 +378,7 @@ static const struct display_clock_funcs funcs = { .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, .set_clock = set_clock, - .set_min_clocks_state = set_min_clocks_state, - .store_max_clocks_state = store_max_clocks_state + .set_min_clocks_state = set_min_clocks_state }; @@ -430,7 +396,6 @@ struct display_clock *dal_display_clock_dce80_create( dc_base = &disp_clk->disp_clk; dc_base->ctx = ctx; - dc_base->id = CLOCK_SOURCE_ID_DCPLL; dc_base->min_display_clk_threshold_khz = 0; dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; @@ -450,12 +415,11 @@ struct display_clock *dal_display_clock_dce80_create( disp_clk->dfs_bypass_disp_clk = 0; disp_clk->use_max_disp_clk = true;/* false will hang the system! */ - disp_clk->disp_clk.id = CLOCK_SOURCE_ID_DFS; /* Initially set max clocks state to nominal. This should be updated by * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_Dce50::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - disp_clk->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; /* Initially set current min clocks state to invalid since we * cannot make any assumption about PPLIB's initial state. This will be updated * by HWSS via SetMinClocksState() on first mode set prior to programming diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h index 273a5d902840..1193398b5cea 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -37,8 +37,6 @@ struct display_clock_dce80 { uint32_t gpu_pll_ss_divider; /* Flag for Enabled SS on GPU PLL*/ bool ss_on_gpu_pll; - /* Max display block clocks state*/ - enum clocks_state max_clks_state; /* Current minimum display block clocks state*/ enum clocks_state cur_min_clks_state; /* DFS-bypass feature variable diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index a46ceebe2452..bc678a59a3c1 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -60,7 +60,8 @@ struct display_clock { struct dc_context *ctx; const struct display_clock_funcs *funcs; uint32_t min_display_clk_threshold_khz; - enum clock_source_id id; + /* Max display block clocks state*/ + enum clocks_state max_clks_state; enum clocks_state cur_min_clks_state; }; @@ -77,8 +78,6 @@ struct display_clock_funcs { bool (*set_min_clocks_state)(struct display_clock *disp_clk, enum clocks_state clocks_state); uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); - void (*store_max_clocks_state)(struct display_clock *disp_clk, - enum clocks_state max_clocks_state); }; -- GitLab From 95015be8f483afbdef32f24ac666c625a1480cc1 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 15:45:51 -0500 Subject: [PATCH 0080/2898] drm/amd/display: remove get_min_clocks_state Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 +---- .../dc/gpu/dce110/display_clock_dce110.c | 42 +++++++++-------- .../dc/gpu/dce112/display_clock_dce112.c | 45 ++++++++++--------- .../dc/gpu/dce112/display_clock_dce112.h | 2 +- .../dc/gpu/dce80/display_clock_dce80.c | 30 +++++++------ .../display/include/display_clock_interface.h | 2 - 6 files changed, 67 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ab4efde2d030..558eeefecbff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1208,7 +1208,6 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) struct core_link *link = stream->sink->link; struct dc_link_settings link_settings = {0}; enum dp_panel_mode panel_mode; - enum clocks_state cur_min_clock_state; enum dc_link_rate max_link_rate = LINK_RATE_HIGH2; /* get link settings for video mode timing */ @@ -1221,13 +1220,8 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) max_link_rate = LINK_RATE_HIGH3; if (link_settings.link_rate == max_link_rate) { - cur_min_clock_state = CLOCKS_STATE_INVALID; - - if (pipe_ctx->dis_clk->funcs->get_min_clocks_state) { - cur_min_clock_state = - pipe_ctx->dis_clk->funcs->get_min_clocks_state( - pipe_ctx->dis_clk); - if (cur_min_clock_state < CLOCKS_STATE_NOMINAL) + if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { + if (pipe_ctx->dis_clk->cur_min_clks_state < CLOCKS_STATE_NOMINAL) pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, CLOCKS_STATE_NOMINAL); } else { diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c index ad7ebc1b434c..83860208a9c5 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -103,25 +103,19 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; * static functions *****************************************************************************/ -static enum clocks_state get_min_clocks_state(struct display_clock *base) -{ - return base->cur_min_clks_state; -} - -static bool set_min_clocks_state( - struct display_clock *base, +static bool dce110_set_min_clocks_state( + struct display_clock *dc, enum clocks_state clocks_state) { - struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); struct dm_pp_power_level_change_request level_change_req = { DM_PP_POWER_LEVEL_INVALID}; - if (clocks_state > base->max_clks_state) { + if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ - dm_logger_write(base->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); return false; - } else if (clocks_state == base->cur_min_clks_state) { + } else if (clocks_state == dc->cur_min_clks_state) { /*if we're trying to set the same state, we can just return * since nothing needs to be done*/ return true; @@ -140,17 +134,28 @@ static bool set_min_clocks_state( case CLOCKS_STATE_PERFORMANCE: level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; break; + case CLOCKS_DPM_STATE_LEVEL_4: + level_change_req.power_level = DM_PP_POWER_LEVEL_4; + break; + case CLOCKS_DPM_STATE_LEVEL_5: + level_change_req.power_level = DM_PP_POWER_LEVEL_5; + break; + case CLOCKS_DPM_STATE_LEVEL_6: + level_change_req.power_level = DM_PP_POWER_LEVEL_6; + break; + case CLOCKS_DPM_STATE_LEVEL_7: + level_change_req.power_level = DM_PP_POWER_LEVEL_7; + break; case CLOCKS_STATE_INVALID: default: - dm_logger_write(base->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state invalid state"); return false; } /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request( - base->ctx, &level_change_req)) - base->cur_min_clks_state = clocks_state; + if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) + dc->cur_min_clks_state = clocks_state; return true; } @@ -384,7 +389,7 @@ static void psr_wait_loop(struct dc_context *ctx, unsigned int display_clk_khz) dm_write_reg(ctx, mmMASTER_COMM_CNTL_REG, masterComCntl); } -static void set_clock( +static void dce110_set_clock( struct display_clock *base, uint32_t requested_clk_khz) { @@ -424,10 +429,9 @@ static void set_clock( static const struct display_clock_funcs funcs = { .destroy = destroy, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, - .set_clock = set_clock, - .set_min_clocks_state = set_min_clocks_state + .set_clock = dce110_set_clock, + .set_min_clocks_state = dce110_set_min_clocks_state }; static bool dal_display_clock_dce110_construct( diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index d8c8d8a1e2b3..4488497c00fa 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -73,26 +73,19 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; #define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 -enum clocks_state dispclk_dce112_get_min_clocks_state( - struct display_clock *base) -{ - return base->cur_min_clks_state; -} - -bool dispclk_dce112_set_min_clocks_state( - struct display_clock *base, +static bool dce112_set_min_clocks_state( + struct display_clock *dc, enum clocks_state clocks_state) { - struct display_clock_dce112 *dc = DCLCK112_FROM_BASE(base); struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID}; + DM_PP_POWER_LEVEL_INVALID }; - if (clocks_state > base->max_clks_state) { + if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ - dm_logger_write(base->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state exceeds max supported state"); return false; - } else if (clocks_state == base->cur_min_clks_state) { + } else if (clocks_state == dc->cur_min_clks_state) { /*if we're trying to set the same state, we can just return * since nothing needs to be done*/ return true; @@ -111,17 +104,28 @@ bool dispclk_dce112_set_min_clocks_state( case CLOCKS_STATE_PERFORMANCE: level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; break; + case CLOCKS_DPM_STATE_LEVEL_4: + level_change_req.power_level = DM_PP_POWER_LEVEL_4; + break; + case CLOCKS_DPM_STATE_LEVEL_5: + level_change_req.power_level = DM_PP_POWER_LEVEL_5; + break; + case CLOCKS_DPM_STATE_LEVEL_6: + level_change_req.power_level = DM_PP_POWER_LEVEL_6; + break; + case CLOCKS_DPM_STATE_LEVEL_7: + level_change_req.power_level = DM_PP_POWER_LEVEL_7; + break; case CLOCKS_STATE_INVALID: default: - dm_logger_write(base->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "Requested state invalid state"); return false; } /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request( - base->ctx, &level_change_req)) - base->cur_min_clks_state = clocks_state; + if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) + dc->cur_min_clks_state = clocks_state; return true; } @@ -293,7 +297,7 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( return low_req_clk; } -void dispclk_dce112_set_clock( +void dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz) { @@ -333,10 +337,9 @@ void dispclk_dce112_set_clock( static const struct display_clock_funcs funcs = { .destroy = dispclk_dce112_destroy, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_min_clocks_state = dispclk_dce112_get_min_clocks_state, .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, - .set_clock = dispclk_dce112_set_clock, - .set_min_clocks_state = dispclk_dce112_set_min_clocks_state + .set_clock = dce112_set_clock, + .set_min_clocks_state = dce112_set_min_clocks_state }; bool dal_display_clock_dce112_construct( diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 398af34720f7..0246f930ac35 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -78,7 +78,7 @@ enum clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks); -void dispclk_dce112_set_clock( +void dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c index b101f7de2d11..6057042739bf 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -90,7 +90,7 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; #define FROM_DISPLAY_CLOCK(base) \ container_of(base, struct display_clock_dce80, disp_clk) -static void set_clock( +static void dce80_set_clock( struct display_clock *dc, uint32_t requested_clk_khz) { @@ -111,13 +111,6 @@ static void set_clock( dc->cur_min_clks_state = CLOCKS_STATE_NOMINAL; } -static enum clocks_state get_min_clocks_state(struct display_clock *dc) -{ - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - return disp_clk->cur_min_clks_state; -} - static enum clocks_state get_required_clocks_state (struct display_clock *dc, struct state_dependent_clocks *req_clocks) @@ -145,12 +138,12 @@ static enum clocks_state get_required_clocks_state return low_req_clk; } -static bool set_min_clocks_state( +static bool dce80_set_min_clocks_state( struct display_clock *dc, enum clocks_state clocks_state) { struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID}; + DM_PP_POWER_LEVEL_INVALID }; if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ @@ -176,6 +169,18 @@ static bool set_min_clocks_state( case CLOCKS_STATE_PERFORMANCE: level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; break; + case CLOCKS_DPM_STATE_LEVEL_4: + level_change_req.power_level = DM_PP_POWER_LEVEL_4; + break; + case CLOCKS_DPM_STATE_LEVEL_5: + level_change_req.power_level = DM_PP_POWER_LEVEL_5; + break; + case CLOCKS_DPM_STATE_LEVEL_6: + level_change_req.power_level = DM_PP_POWER_LEVEL_6; + break; + case CLOCKS_DPM_STATE_LEVEL_7: + level_change_req.power_level = DM_PP_POWER_LEVEL_7; + break; case CLOCKS_STATE_INVALID: default: dm_logger_write(dc->ctx->logger, LOG_WARNING, @@ -375,10 +380,9 @@ static void destroy(struct display_clock **dc) static const struct display_clock_funcs funcs = { .destroy = destroy, .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_min_clocks_state = get_min_clocks_state, .get_required_clocks_state = get_required_clocks_state, - .set_clock = set_clock, - .set_min_clocks_state = set_min_clocks_state + .set_clock = dce80_set_clock, + .set_min_clocks_state = dce80_set_min_clocks_state }; diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index bc678a59a3c1..f2deafbd8b12 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -70,8 +70,6 @@ struct display_clock_funcs { void (*destroy)(struct display_clock **to_destroy); void (*set_clock)(struct display_clock *disp_clk, uint32_t requested_clock_khz); - enum clocks_state (*get_min_clocks_state)( - struct display_clock *disp_clk); enum clocks_state (*get_required_clocks_state)( struct display_clock *disp_clk, struct state_dependent_clocks *req_clocks); -- GitLab From e9c58bb439bce021da205df09057fe6908ff54c5 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 30 Nov 2016 16:07:50 -0500 Subject: [PATCH 0081/2898] drm/amd/display: remove clocks_state enum Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +- .../amd/display/dc/dce100/dce100_resource.c | 3 +- .../display/dc/dce110/dce110_hw_sequencer.c | 4 +- .../amd/display/dc/dce110/dce110_resource.c | 44 +------------ .../amd/display/dc/dce110/dce110_resource.h | 3 - .../amd/display/dc/dce112/dce112_resource.c | 3 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 24 +++---- .../dc/gpu/dce110/display_clock_dce110.c | 62 +++++------------- .../dc/gpu/dce112/display_clock_dce112.c | 62 +++++------------- .../dc/gpu/dce112/display_clock_dce112.h | 8 +-- .../dc/gpu/dce80/display_clock_dce80.c | 64 +++++-------------- .../dc/gpu/dce80/display_clock_dce80.h | 2 +- .../display/include/display_clock_interface.h | 28 ++------ 13 files changed, 75 insertions(+), 236 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 558eeefecbff..47f22d46c0ca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1221,9 +1221,9 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) if (link_settings.link_rate == max_link_rate) { if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { - if (pipe_ctx->dis_clk->cur_min_clks_state < CLOCKS_STATE_NOMINAL) + if (pipe_ctx->dis_clk->cur_min_clks_state < DM_PP_CLOCKS_STATE_NOMINAL) pipe_ctx->dis_clk->funcs->set_min_clocks_state( - pipe_ctx->dis_clk, CLOCKS_STATE_NOMINAL); + pipe_ctx->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); } else { } } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 446f50bb4e0a..5716ce1e58f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -983,8 +983,7 @@ static bool construct( */ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = - dce110_resource_convert_clock_state_pp_to_dc( - static_clk_info.max_clocks_state); + static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; init_data.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ca71509af74d..6ad23f327631 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1084,7 +1084,7 @@ static uint32_t get_max_pixel_clock_for_all_paths( static void apply_min_clocks( struct core_dc *dc, struct validate_context *context, - enum clocks_state *clocks_state, + enum dm_pp_clocks_state *clocks_state, bool pre_mode_set) { struct state_dependent_clocks req_clocks = {0}; @@ -1193,7 +1193,7 @@ enum dc_status dce110_apply_ctx_to_hw( enum dc_status status; int i; bool programmed_audio_dto = false; - enum clocks_state clocks_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID; /* Reset old context */ /* look up the targets that have been removed since last commit */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index d5d888bdf882..8682c8b2a547 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1188,47 +1188,6 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) 1000); } -enum clocks_state dce110_resource_convert_clock_state_pp_to_dc( - enum dm_pp_clocks_state pp_clock_state) -{ - enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID; - - switch (pp_clock_state) { - case DM_PP_CLOCKS_STATE_INVALID: - dc_clocks_state = CLOCKS_STATE_INVALID; - break; - case DM_PP_CLOCKS_STATE_ULTRA_LOW: - dc_clocks_state = CLOCKS_STATE_ULTRA_LOW; - break; - case DM_PP_CLOCKS_STATE_LOW: - dc_clocks_state = CLOCKS_STATE_LOW; - break; - case DM_PP_CLOCKS_STATE_NOMINAL: - dc_clocks_state = CLOCKS_STATE_NOMINAL; - break; - case DM_PP_CLOCKS_STATE_PERFORMANCE: - dc_clocks_state = CLOCKS_STATE_PERFORMANCE; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7; - break; - default: - dc_clocks_state = CLOCKS_STATE_INVALID; - break; - } - - return dc_clocks_state; -} - const struct resource_caps *dce110_resource_cap( struct hw_asic_id *asic_id) { @@ -1314,8 +1273,7 @@ static bool construct( */ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = - dce110_resource_convert_clock_state_pp_to_dc( - static_clk_info.max_clocks_state); + static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h index 535623aa0052..0c357fdfa8bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -40,9 +40,6 @@ struct dce110_resource_pool { enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); -enum clocks_state dce110_resource_convert_clock_state_pp_to_dc( - enum dm_pp_clocks_state pp_clock_state); - void dce110_resource_build_bit_depth_reduction_params( const struct core_stream *stream, struct bit_depth_reduction_params *fmt_bit_depth); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 9903c9a4b8a1..c50a215172b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1314,8 +1314,7 @@ static bool construct( */ if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = - dce110_resource_convert_clock_state_pp_to_dc( - static_clk_info.max_clocks_state); + static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 51721d10c811..1d2a31e34617 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -857,41 +857,41 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_bandwidth = dce80_validate_bandwidth }; -static enum clocks_state dce80_resource_convert_clock_state_pp_to_dc( +static enum dm_pp_clocks_state dce80_resource_convert_clock_state_pp_to_dc( enum dm_pp_clocks_state pp_clock_state) { - enum clocks_state dc_clocks_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; switch (pp_clock_state) { case DM_PP_CLOCKS_STATE_INVALID: - dc_clocks_state = CLOCKS_STATE_INVALID; + dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; break; case DM_PP_CLOCKS_STATE_ULTRA_LOW: - dc_clocks_state = CLOCKS_STATE_ULTRA_LOW; + dc_clocks_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; break; case DM_PP_CLOCKS_STATE_LOW: - dc_clocks_state = CLOCKS_STATE_LOW; + dc_clocks_state = DM_PP_CLOCKS_STATE_LOW; break; case DM_PP_CLOCKS_STATE_NOMINAL: - dc_clocks_state = CLOCKS_STATE_NOMINAL; + dc_clocks_state = DM_PP_CLOCKS_STATE_NOMINAL; break; case DM_PP_CLOCKS_STATE_PERFORMANCE: - dc_clocks_state = CLOCKS_STATE_PERFORMANCE; + dc_clocks_state = DM_PP_CLOCKS_STATE_PERFORMANCE; break; case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_4; + dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_4; break; case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_5; + dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_5; break; case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_6; + dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_6; break; case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: - dc_clocks_state = CLOCKS_DPM_STATE_LEVEL_7; + dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_7; break; default: - dc_clocks_state = CLOCKS_STATE_INVALID; + dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; break; } diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c index 83860208a9c5..9dabaac2c550 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c @@ -105,10 +105,10 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; static bool dce110_set_min_clocks_state( struct display_clock *dc, - enum clocks_state clocks_state) + enum dm_pp_clocks_state clocks_state) { struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID}; + clocks_state }; if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ @@ -121,38 +121,6 @@ static bool dce110_set_min_clocks_state( return true; } - switch (clocks_state) { - case CLOCKS_STATE_ULTRA_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; - break; - case CLOCKS_STATE_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; - break; - case CLOCKS_STATE_NOMINAL: - level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; - break; - case CLOCKS_STATE_PERFORMANCE: - level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; - break; - case CLOCKS_DPM_STATE_LEVEL_4: - level_change_req.power_level = DM_PP_POWER_LEVEL_4; - break; - case CLOCKS_DPM_STATE_LEVEL_5: - level_change_req.power_level = DM_PP_POWER_LEVEL_5; - break; - case CLOCKS_DPM_STATE_LEVEL_6: - level_change_req.power_level = DM_PP_POWER_LEVEL_6; - break; - case CLOCKS_DPM_STATE_LEVEL_7: - level_change_req.power_level = DM_PP_POWER_LEVEL_7; - break; - case CLOCKS_STATE_INVALID: - default: - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state invalid state"); - return false; - } - /* get max clock state from PPLIB */ if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) dc->cur_min_clks_state = clocks_state; @@ -274,27 +242,27 @@ static bool display_clock_integrated_info_construct( /*update the maximum display clock for each power state*/ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum clocks_state clk_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; switch (i) { case 0: - clk_state = CLOCKS_STATE_ULTRA_LOW; + clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; break; case 1: - clk_state = CLOCKS_STATE_LOW; + clk_state = DM_PP_CLOCKS_STATE_LOW; break; case 2: - clk_state = CLOCKS_STATE_NOMINAL; + clk_state = DM_PP_CLOCKS_STATE_NOMINAL; break; case 3: - clk_state = CLOCKS_STATE_PERFORMANCE; + clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; break; default: - clk_state = CLOCKS_STATE_INVALID; + clk_state = DM_PP_CLOCKS_STATE_INVALID; break; } @@ -316,27 +284,27 @@ static bool display_clock_integrated_info_construct( return true; } -static enum clocks_state get_required_clocks_state( +static enum dm_pp_clocks_state get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks) { int32_t i; struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - enum clocks_state low_req_clk = dc->max_clks_state; + enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ dm_logger_write(dc->ctx->logger, LOG_WARNING, "%s: Invalid parameter", __func__); - return CLOCKS_STATE_INVALID; + return DM_PP_CLOCKS_STATE_INVALID; } /* Iterate from highest supported to lowest valid state, and update * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= max_clks_by_state[i].display_clk_khz) && (req_clocks->pixel_clk_khz <= @@ -420,7 +388,7 @@ static void dce110_set_clock( /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) - base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + base->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; psr_wait_loop(base->ctx, requested_clk_khz); } @@ -444,7 +412,7 @@ static bool dal_display_clock_dce110_construct( dc_base->ctx = ctx; dc_base->min_display_clk_threshold_khz = 0; - dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; + dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; @@ -462,7 +430,7 @@ static bool dal_display_clock_dce110_construct( * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; dal_divider_range_construct( ÷r_ranges[DIVIDER_RANGE_01], diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index 4488497c00fa..930548bdd8b2 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -75,10 +75,10 @@ static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; static bool dce112_set_min_clocks_state( struct display_clock *dc, - enum clocks_state clocks_state) + enum dm_pp_clocks_state clocks_state) { struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID }; + clocks_state }; if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ @@ -91,38 +91,6 @@ static bool dce112_set_min_clocks_state( return true; } - switch (clocks_state) { - case CLOCKS_STATE_ULTRA_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; - break; - case CLOCKS_STATE_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; - break; - case CLOCKS_STATE_NOMINAL: - level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; - break; - case CLOCKS_STATE_PERFORMANCE: - level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; - break; - case CLOCKS_DPM_STATE_LEVEL_4: - level_change_req.power_level = DM_PP_POWER_LEVEL_4; - break; - case CLOCKS_DPM_STATE_LEVEL_5: - level_change_req.power_level = DM_PP_POWER_LEVEL_5; - break; - case CLOCKS_DPM_STATE_LEVEL_6: - level_change_req.power_level = DM_PP_POWER_LEVEL_6; - break; - case CLOCKS_DPM_STATE_LEVEL_7: - level_change_req.power_level = DM_PP_POWER_LEVEL_7; - break; - case CLOCKS_STATE_INVALID: - default: - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state invalid state"); - return false; - } - /* get max clock state from PPLIB */ if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) dc->cur_min_clks_state = clocks_state; @@ -229,27 +197,27 @@ static bool display_clock_integrated_info_construct( /*update the maximum display clock for each power state*/ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum clocks_state clk_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; switch (i) { case 0: - clk_state = CLOCKS_STATE_ULTRA_LOW; + clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; break; case 1: - clk_state = CLOCKS_STATE_LOW; + clk_state = DM_PP_CLOCKS_STATE_LOW; break; case 2: - clk_state = CLOCKS_STATE_NOMINAL; + clk_state = DM_PP_CLOCKS_STATE_NOMINAL; break; case 3: - clk_state = CLOCKS_STATE_PERFORMANCE; + clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; break; default: - clk_state = CLOCKS_STATE_INVALID; + clk_state = DM_PP_CLOCKS_STATE_INVALID; break; } @@ -265,27 +233,27 @@ static bool display_clock_integrated_info_construct( return true; } -enum clocks_state dispclk_dce112_get_required_clocks_state( +enum dm_pp_clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks) { int32_t i; struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - enum clocks_state low_req_clk = dc->max_clks_state; + enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ dm_logger_write(dc->ctx->logger, LOG_WARNING, "%s: Invalid parameter", __func__); - return CLOCKS_STATE_INVALID; + return DM_PP_CLOCKS_STATE_INVALID; } /* Iterate from highest supported to lowest valid state, and update * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= (disp_clk->max_clks_by_state + i)-> display_clk_khz) && @@ -321,7 +289,7 @@ void dce112_set_clock( /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) - base->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + base->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; /*Program DP ref Clock*/ /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ @@ -351,7 +319,7 @@ bool dal_display_clock_dce112_construct( dc_base->ctx = ctx; dc_base->min_display_clk_threshold_khz = 0; - dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; + dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; @@ -369,7 +337,7 @@ bool dal_display_clock_dce112_construct( * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; dc112->disp_clk_base.min_display_clk_threshold_khz = (dc112->dentist_vco_freq_khz / 62); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index 0246f930ac35..b750bb1766bd 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -71,10 +71,10 @@ bool dal_display_clock_dce112_construct( void dispclk_dce112_destroy(struct display_clock **base); -enum clocks_state dispclk_dce112_get_min_clocks_state( +enum dm_pp_clocks_state dispclk_dce112_get_min_clocks_state( struct display_clock *base); -enum clocks_state dispclk_dce112_get_required_clocks_state( +enum dm_pp_clocks_state dispclk_dce112_get_required_clocks_state( struct display_clock *dc, struct state_dependent_clocks *req_clocks); @@ -84,10 +84,10 @@ void dce112_set_clock( bool dispclk_dce112_set_min_clocks_state( struct display_clock *base, - enum clocks_state clocks_state); + enum dm_pp_clocks_state clocks_state); void dispclk_dce112_store_max_clocks_state( struct display_clock *base, - enum clocks_state max_clocks_state); + enum dm_pp_clocks_state max_clocks_state); #endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c index 6057042739bf..9d7cb2cb161c 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c @@ -108,27 +108,27 @@ static void dce80_set_clock( /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) - dc->cur_min_clks_state = CLOCKS_STATE_NOMINAL; + dc->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; } -static enum clocks_state get_required_clocks_state +static enum dm_pp_clocks_state get_required_clocks_state (struct display_clock *dc, struct state_dependent_clocks *req_clocks) { int32_t i; - enum clocks_state low_req_clk = dc->max_clks_state; + enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; if (!req_clocks) { /* NULL pointer*/ BREAK_TO_DEBUGGER(); - return CLOCKS_STATE_INVALID; + return DM_PP_CLOCKS_STATE_INVALID; } /* Iterate from highest supported to lowest valid state, and update * lowest RequiredState with the lowest state that satisfies * all required clocks */ - for (i = dc->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) { + for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { if ((req_clocks->display_clk_khz <= max_clks_by_state[i].display_clk_khz) && (req_clocks->pixel_clk_khz <= @@ -140,10 +140,10 @@ static enum clocks_state get_required_clocks_state static bool dce80_set_min_clocks_state( struct display_clock *dc, - enum clocks_state clocks_state) + enum dm_pp_clocks_state clocks_state) { struct dm_pp_power_level_change_request level_change_req = { - DM_PP_POWER_LEVEL_INVALID }; + clocks_state }; if (clocks_state > dc->max_clks_state) { /*Requested state exceeds max supported state.*/ @@ -156,38 +156,6 @@ static bool dce80_set_min_clocks_state( return true; } - switch (clocks_state) { - case CLOCKS_STATE_ULTRA_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_ULTRA_LOW; - break; - case CLOCKS_STATE_LOW: - level_change_req.power_level = DM_PP_POWER_LEVEL_LOW; - break; - case CLOCKS_STATE_NOMINAL: - level_change_req.power_level = DM_PP_POWER_LEVEL_NOMINAL; - break; - case CLOCKS_STATE_PERFORMANCE: - level_change_req.power_level = DM_PP_POWER_LEVEL_PERFORMANCE; - break; - case CLOCKS_DPM_STATE_LEVEL_4: - level_change_req.power_level = DM_PP_POWER_LEVEL_4; - break; - case CLOCKS_DPM_STATE_LEVEL_5: - level_change_req.power_level = DM_PP_POWER_LEVEL_5; - break; - case CLOCKS_DPM_STATE_LEVEL_6: - level_change_req.power_level = DM_PP_POWER_LEVEL_6; - break; - case CLOCKS_DPM_STATE_LEVEL_7: - level_change_req.power_level = DM_PP_POWER_LEVEL_7; - break; - case CLOCKS_STATE_INVALID: - default: - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state invalid state"); - return false; - } - /* get max clock state from PPLIB */ if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) dc->cur_min_clks_state = clocks_state; @@ -326,27 +294,27 @@ static bool display_clock_integrated_info_construct( /*update the maximum display clock for each power state*/ for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum clocks_state clk_state = CLOCKS_STATE_INVALID; + enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; switch (i) { case 0: - clk_state = CLOCKS_STATE_ULTRA_LOW; + clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; break; case 1: - clk_state = CLOCKS_STATE_LOW; + clk_state = DM_PP_CLOCKS_STATE_LOW; break; case 2: - clk_state = CLOCKS_STATE_NOMINAL; + clk_state = DM_PP_CLOCKS_STATE_NOMINAL; break; case 3: - clk_state = CLOCKS_STATE_PERFORMANCE; + clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; break; default: - clk_state = CLOCKS_STATE_INVALID; + clk_state = DM_PP_CLOCKS_STATE_INVALID; break; } @@ -402,7 +370,7 @@ struct display_clock *dal_display_clock_dce80_create( dc_base->ctx = ctx; dc_base->min_display_clk_threshold_khz = 0; - dc_base->cur_min_clks_state = CLOCKS_STATE_INVALID; + dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; dc_base->funcs = &funcs; /* @@ -423,12 +391,12 @@ struct display_clock *dal_display_clock_dce80_create( * via a pplib call to DAL IRI eventually calling a * DisplayEngineClock_Dce50::StoreMaxClocksState(). This call will come in * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = CLOCKS_STATE_NOMINAL; + dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; /* Initially set current min clocks state to invalid since we * cannot make any assumption about PPLIB's initial state. This will be updated * by HWSS via SetMinClocksState() on first mode set prior to programming * state dependent clocks.*/ - disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID; + disp_clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; display_clock_ss_construct(disp_clk); diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h index 1193398b5cea..c155bb6a4321 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h @@ -38,7 +38,7 @@ struct display_clock_dce80 { /* Flag for Enabled SS on GPU PLL*/ bool ss_on_gpu_pll; /* Current minimum display block clocks state*/ - enum clocks_state cur_min_clks_state; + enum dm_pp_clocks_state cur_min_clks_state; /* DFS-bypass feature variable Cache the status of DFS-bypass feature*/ bool dfs_bypass_enabled; diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index f2deafbd8b12..6ba8c093793d 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -26,29 +26,11 @@ #ifndef __DISPLAY_CLOCK_INTERFACE_H__ #define __DISPLAY_CLOCK_INTERFACE_H__ +#include "dm_services_types.h" #include "hw_sequencer_types.h" #include "grph_object_defs.h" #include "signal_types.h" -/* Enumeration of all clocks states */ -enum clocks_state { - CLOCKS_STATE_INVALID = 0, - CLOCKS_STATE_ULTRA_LOW, - CLOCKS_STATE_LOW, - CLOCKS_STATE_NOMINAL, - CLOCKS_STATE_PERFORMANCE, - /* Starting from DCE11, Max 8 level DPM state supported */ - CLOCKS_DPM_STATE_LEVEL_INVALID = CLOCKS_STATE_INVALID, - CLOCKS_DPM_STATE_LEVEL_0 = CLOCKS_STATE_ULTRA_LOW, - CLOCKS_DPM_STATE_LEVEL_1 = CLOCKS_STATE_LOW, - CLOCKS_DPM_STATE_LEVEL_2 = CLOCKS_STATE_NOMINAL, - CLOCKS_DPM_STATE_LEVEL_3 = CLOCKS_STATE_PERFORMANCE, - CLOCKS_DPM_STATE_LEVEL_4 = CLOCKS_DPM_STATE_LEVEL_3 + 1, - CLOCKS_DPM_STATE_LEVEL_5 = CLOCKS_DPM_STATE_LEVEL_4 + 1, - CLOCKS_DPM_STATE_LEVEL_6 = CLOCKS_DPM_STATE_LEVEL_5 + 1, - CLOCKS_DPM_STATE_LEVEL_7 = CLOCKS_DPM_STATE_LEVEL_6 + 1, -}; - /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ struct state_dependent_clocks { @@ -61,20 +43,20 @@ struct display_clock { const struct display_clock_funcs *funcs; uint32_t min_display_clk_threshold_khz; /* Max display block clocks state*/ - enum clocks_state max_clks_state; + enum dm_pp_clocks_state max_clks_state; - enum clocks_state cur_min_clks_state; + enum dm_pp_clocks_state cur_min_clks_state; }; struct display_clock_funcs { void (*destroy)(struct display_clock **to_destroy); void (*set_clock)(struct display_clock *disp_clk, uint32_t requested_clock_khz); - enum clocks_state (*get_required_clocks_state)( + enum dm_pp_clocks_state (*get_required_clocks_state)( struct display_clock *disp_clk, struct state_dependent_clocks *req_clocks); bool (*set_min_clocks_state)(struct display_clock *disp_clk, - enum clocks_state clocks_state); + enum dm_pp_clocks_state dm_pp_clocks_state); uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); }; -- GitLab From 9a70eba7f2c65b408ee56c7219b0cb4ae588b2bc Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 1 Dec 2016 18:13:25 -0500 Subject: [PATCH 0082/2898] drm/amd/display: consolidate dce8-11.2 display clock code Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/Makefile | 3 +- .../gpu/drm/amd/display/dc/dce/dce_audio.c | 4 +- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 519 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dce/dce_clocks.h | 133 +++++ .../amd/display/dc/dce100/dce100_resource.c | 22 +- .../amd/display/dc/dce110/dce110_resource.c | 24 +- .../amd/display/dc/dce112/dce112_resource.c | 28 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 70 +-- .../drm/amd/display/dc/dm_services_types.h | 18 +- drivers/gpu/drm/amd/display/dc/gpu/Makefile | 15 - .../dc/gpu/dce110/display_clock_dce110.c | 516 ----------------- .../dc/gpu/dce110/display_clock_dce110.h | 50 -- .../dc/gpu/dce112/display_clock_dce112.c | 152 ----- .../dc/gpu/dce112/display_clock_dce112.h | 14 - .../dc/gpu/dce80/display_clock_dce80.c | 430 --------------- .../dc/gpu/dce80/display_clock_dce80.h | 54 -- .../display/include/display_clock_interface.h | 15 +- 17 files changed, 747 insertions(+), 1320 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index bfca38170329..6add5977fd39 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -6,7 +6,8 @@ # offset/shift/mask stored in dce_hw struct DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ -dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o +dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ +dce_clocks.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index dc44053e8575..2749c8fa4f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -888,7 +888,9 @@ static const struct audio_funcs funcs = { void dce_aud_destroy(struct audio **audio) { - dm_free(*audio); + struct dce_audio *aud = DCE_AUD(*audio); + + dm_free(aud); *audio = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c new file mode 100644 index 000000000000..77033fe8a8e5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -0,0 +1,519 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_clocks.h" +#include "dm_services.h" +#include "reg_helper.h" +#include "fixed32_32.h" +#include "bios_parser_interface.h" +#include "dc.h" + + +#define REG(reg) \ + (clk_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + clk_dce->clk_shift->field_name, clk_dce->clk_mask->field_name + +#define CTX \ + clk_dce->base.ctx + +/* Starting point for each divider range.*/ +enum divider_range_start { + DIVIDER_RANGE_01_START = 200, /* 2.00*/ + DIVIDER_RANGE_02_START = 1600, /* 16.00*/ + DIVIDER_RANGE_03_START = 3200, /* 32.00*/ + DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ +}; + +/* Ranges for divider identifiers (Divider ID or DID) + mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +enum divider_id_register_setting { + DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, + DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, + DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, + DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 +}; + +/* Step size between each divider within a range. + Incrementing the DENTIST_DISPCLK_WDIVIDER by one + will increment the divider by this much.*/ +enum divider_range_step_size { + DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ + DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ + DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +}; + + +static uint32_t dce_clocks_get_dp_ref_freq(struct display_clock *clk) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + int dprefclk_wdivider; + int dprefclk_src_sel; + int dp_ref_clk_khz = 600000; + int target_div = INVALID_DIVIDER; + + /* ASSERT DP Reference Clock source is from DFS*/ + REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); + ASSERT(dprefclk_src_sel == 0); + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dal_divider_range_get_divider( + clk_dce->divider_ranges, + DIVIDER_RANGE_MAX, + dprefclk_wdivider); + + if (target_div != INVALID_DIVIDER) { + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR + * clk_dce->dentist_vco_freq_khz) / target_div; + } + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) + if clock is spread for all cases: + -if SS enabled on DP Ref clock and HW de-spreading enabled with SW + calculations for DS_INCR/DS_MODULO (this is planned to be default case) + -if SS enabled on DP Ref clock and HW de-spreading enabled with HW + calculations (not planned to be used, but average clock should still + be valid) + -if SS enabled on DP Ref clock and HW de-spreading disabled + (should not be case with CIK) then SW should program all rates + generated according to average value (case as with previous ASICs) + */ + if (clk_dce->ss_on_gpu_pll && clk_dce->gpu_pll_ss_divider != 0) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + clk_dce->gpu_pll_ss_percentage, + clk_dce->gpu_pll_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} + +static enum dm_pp_clocks_state dce_get_required_clocks_state( + struct display_clock *clk, + struct state_dependent_clocks *req_clocks) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + int i; + enum dm_pp_clocks_state low_req_clk; + + /* Iterate from highest supported to lowest valid state, and update + * lowest RequiredState with the lowest state that satisfies + * all required clocks + */ + for (i = clk->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; i--) + if (req_clocks->display_clk_khz > + clk_dce->max_clks_by_state[i].display_clk_khz + || req_clocks->pixel_clk_khz > + clk_dce->max_clks_by_state[i].pixel_clk_khz) + break; + + low_req_clk = i + 1; + if (low_req_clk > clk->max_clks_state) { + dm_logger_write(clk->ctx->logger, LOG_WARNING, + "%s: clocks unsupported", __func__); + low_req_clk = DM_PP_CLOCKS_STATE_INVALID; + } + + return low_req_clk; +} + +static bool dce_clock_set_min_clocks_state( + struct display_clock *clk, + enum dm_pp_clocks_state clocks_state) +{ + struct dm_pp_power_level_change_request level_change_req = { + clocks_state }; + + if (clocks_state > clk->max_clks_state) { + /*Requested state exceeds max supported state.*/ + dm_logger_write(clk->ctx->logger, LOG_WARNING, + "Requested state exceeds max supported state"); + return false; + } else if (clocks_state == clk->cur_min_clks_state) { + /*if we're trying to set the same state, we can just return + * since nothing needs to be done*/ + return true; + } + + /* get max clock state from PPLIB */ + if (dm_pp_apply_power_level_change_request(clk->ctx, &level_change_req)) + clk->cur_min_clks_state = clocks_state; + + return true; +} + +static void dce_set_clock( + struct display_clock *clk, + uint32_t requested_clk_khz) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + struct bp_pixel_clock_parameters pxl_clk_params = { 0 }; + struct dc_bios *bp = clk->ctx->dc_bios; + + /* Make sure requested clock isn't lower than minimum threshold*/ + if (requested_clk_khz > 0) + requested_clk_khz = dm_max(requested_clk_khz, + clk_dce->dentist_vco_freq_khz / 64); + + /* Prepare to program display clock*/ + pxl_clk_params.target_pixel_clock = requested_clk_khz; + pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; + + bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); + + if (clk_dce->dfs_bypass_enabled) { + + /* Cache the fixed display clock*/ + clk_dce->dfs_bypass_disp_clk = + pxl_clk_params.dfs_bypass_display_clock; + } + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; +} + +#define PSR_SET_WAITLOOP 0x31 + +union dce110_dmcu_psr_config_data_wait_loop_reg1 { + struct { + unsigned int wait_loop:16; /* [15:0] */ + unsigned int reserved:16; /* [31:16] */ + } bits; + unsigned int u32; +}; + +static void dce_psr_wait_loop( + struct dce_disp_clk *clk_dce, unsigned int display_clk_khz) +{ + struct dc_context *ctx = clk_dce->base.ctx; + union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + + masterCmdData1.u32 = 0; + masterCmdData1.bits.wait_loop = display_clk_khz / 1000 / 7; + dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +static void dce_psr_set_clock( + struct display_clock *clk, + uint32_t requested_clk_khz) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + + dce_set_clock(clk, requested_clk_khz); + dce_psr_wait_loop(clk_dce, requested_clk_khz); +} + +static void polaris_set_clock( + struct display_clock *clk, + uint32_t requested_clk_khz) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + struct bp_set_dce_clock_parameters dce_clk_params; + struct dc_bios *bp = clk->ctx->dc_bios; + + /* Prepare to program display clock*/ + memset(&dce_clk_params, 0, sizeof(dce_clk_params)); + + /* Make sure requested clock isn't lower than minimum threshold*/ + if (requested_clk_khz > 0) + requested_clk_khz = dm_max(requested_clk_khz, + clk_dce->dentist_vco_freq_khz / 64); + + dce_clk_params.target_clock_frequency = requested_clk_khz; + dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; + dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; + + bp->funcs->set_dce_clock(bp, &dce_clk_params); + + /* from power down, we need mark the clock state as ClocksStateNominal + * from HWReset, so when resume we will call pplib voltage regulator.*/ + if (requested_clk_khz == 0) + clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; + + /*Program DP ref Clock*/ + /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ + dce_clk_params.target_clock_frequency = 0; + dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; + dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = 0; + + bp->funcs->set_dce_clock(bp, &dce_clk_params); +} + +static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) +{ + struct dc_debug *debug = &clk_dce->base.ctx->dc->debug; + struct dc_bios *bp = clk_dce->base.ctx->dc_bios; + struct integrated_info info = { 0 }; + struct firmware_info fw_info = { 0 }; + int i; + + if (bp->integrated_info) + info = *bp->integrated_info; + + clk_dce->dentist_vco_freq_khz = info.dentist_vco_freq; + if (clk_dce->dentist_vco_freq_khz == 0) { + bp->funcs->get_firmware_info(bp, &fw_info); + clk_dce->dentist_vco_freq_khz = + fw_info.smu_gpu_pll_output_freq; + if (clk_dce->dentist_vco_freq_khz == 0) + clk_dce->dentist_vco_freq_khz = 3600000; + } + + /*update the maximum display clock for each power state*/ + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; + + switch (i) { + case 0: + clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; + break; + + case 1: + clk_state = DM_PP_CLOCKS_STATE_LOW; + break; + + case 2: + clk_state = DM_PP_CLOCKS_STATE_NOMINAL; + break; + + case 3: + clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; + break; + + default: + clk_state = DM_PP_CLOCKS_STATE_INVALID; + break; + } + + /*Do not allow bad VBIOS/SBIOS to override with invalid values, + * check for > 100MHz*/ + if (info.disp_clk_voltage[i].max_supported_clk >= 100000) + clk_dce->max_clks_by_state[clk_state].display_clk_khz = + info.disp_clk_voltage[i].max_supported_clk; + } + + if (!debug->disable_dfs_bypass) + if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) + clk_dce->dfs_bypass_enabled = true; + + clk_dce->use_max_disp_clk = debug->max_disp_clk; +} + +static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) +{ + struct dc_bios *bp = clk_dce->base.ctx->dc_bios; + int ss_info_num = bp->funcs->get_ss_entry_number( + bp, AS_SIGNAL_TYPE_GPU_PLL); + + if (ss_info_num) { + struct spread_spectrum_info info = { 0 }; + enum bp_result result = bp->funcs->get_spread_spectrum_info( + bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info); + + /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS + * even if SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be sign + * that SS is enabled + */ + if (result == BP_RESULT_OK && + info.spread_spectrum_percentage != 0) { + clk_dce->ss_on_gpu_pll = true; + clk_dce->gpu_pll_ss_divider = info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + clk_dce->gpu_pll_ss_percentage = + info.spread_spectrum_percentage; + } + } + + } +} + +static const struct display_clock_funcs dce112_funcs = { + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .get_required_clocks_state = dce_get_required_clocks_state, + .set_min_clocks_state = dce_clock_set_min_clocks_state, + .set_clock = polaris_set_clock +}; + +static const struct display_clock_funcs dce110_funcs = { + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .get_required_clocks_state = dce_get_required_clocks_state, + .set_min_clocks_state = dce_clock_set_min_clocks_state, + .set_clock = dce_psr_set_clock +}; + +static const struct display_clock_funcs dce_funcs = { + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .get_required_clocks_state = dce_get_required_clocks_state, + .set_min_clocks_state = dce_clock_set_min_clocks_state, + .set_clock = dce_set_clock +}; + +static void dce_disp_clk_construct( + struct dce_disp_clk *clk_dce, + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct display_clock *base = &clk_dce->base; + + base->ctx = ctx; + base->funcs = &dce_funcs; + + clk_dce->regs = regs; + clk_dce->clk_shift = clk_shift; + clk_dce->clk_mask = clk_mask; + + clk_dce->dfs_bypass_disp_clk = 0; + clk_dce->gpu_pll_ss_percentage = 0; + clk_dce->gpu_pll_ss_divider = 1000; + clk_dce->ss_on_gpu_pll = false; + base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; + base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; + + dce_clock_read_integrated_info(clk_dce); + dce_clock_read_ss_info(clk_dce); + + dal_divider_range_construct( + &clk_dce->divider_ranges[DIVIDER_RANGE_01], + DIVIDER_RANGE_01_START, + DIVIDER_RANGE_01_STEP_SIZE, + DIVIDER_RANGE_01_BASE_DIVIDER_ID, + DIVIDER_RANGE_02_BASE_DIVIDER_ID); + dal_divider_range_construct( + &clk_dce->divider_ranges[DIVIDER_RANGE_02], + DIVIDER_RANGE_02_START, + DIVIDER_RANGE_02_STEP_SIZE, + DIVIDER_RANGE_02_BASE_DIVIDER_ID, + DIVIDER_RANGE_03_BASE_DIVIDER_ID); + dal_divider_range_construct( + &clk_dce->divider_ranges[DIVIDER_RANGE_03], + DIVIDER_RANGE_03_START, + DIVIDER_RANGE_03_STEP_SIZE, + DIVIDER_RANGE_03_BASE_DIVIDER_ID, + DIVIDER_RANGE_MAX_DIVIDER_ID); +} + +struct display_clock *dce_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + + if (clk_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_disp_clk_construct( + clk_dce, ctx, regs, clk_shift, clk_mask); + + return &clk_dce->base; +} + +struct display_clock *dce110_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + + if (clk_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_disp_clk_construct( + clk_dce, ctx, regs, clk_shift, clk_mask); + + clk_dce->base.funcs = &dce110_funcs; + + return &clk_dce->base; +} + +struct display_clock *dce112_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + + if (clk_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_disp_clk_construct( + clk_dce, ctx, regs, clk_shift, clk_mask); + + clk_dce->base.funcs = &dce112_funcs; + + return &clk_dce->base; +} + +void dce_disp_clk_destroy(struct display_clock **disp_clk) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(*disp_clk); + + dm_free(clk_dce); + *disp_clk = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h new file mode 100644 index 000000000000..e3b23749f0a2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -0,0 +1,133 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef _DCE_CLOCKS_H_ +#define _DCE_CLOCKS_H_ + +#include "display_clock_interface.h" +#include "../gpu/divider_range.h" + + +#define TO_DCE_CLOCKS(clocks)\ + container_of(clocks, struct dce_disp_clk, base) + +#define CLK_COMMON_REG_LIST_DCE_BASE() \ + .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ + .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL, \ + .MASTER_COMM_DATA_REG1 = mmMASTER_COMM_DATA_REG1, \ + .MASTER_COMM_CMD_REG = mmMASTER_COMM_CMD_REG, \ + .MASTER_COMM_CNTL_REG = mmMASTER_COMM_CNTL_REG + +#define CLK_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ + CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ + CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) + + +#define CLK_REG_FIELD_LIST(type) \ + type DPREFCLK_SRC_SEL; \ + type DENTIST_DPREFCLK_WDIVIDER; \ + type MASTER_COMM_CMD_REG_BYTE0; \ + type MASTER_COMM_INTERRUPT + +struct dce_disp_clk_shift { + CLK_REG_FIELD_LIST(uint8_t); +}; + +struct dce_disp_clk_mask { + CLK_REG_FIELD_LIST(uint32_t); +}; + +struct dce_disp_clk_registers { + uint32_t DPREFCLK_CNTL; + uint32_t DENTIST_DISPCLK_CNTL; + uint32_t MASTER_COMM_DATA_REG1; + uint32_t MASTER_COMM_CMD_REG; + uint32_t MASTER_COMM_CNTL_REG; +}; + +/* Array identifiers and count for the divider ranges.*/ +enum divider_range_count { + DIVIDER_RANGE_01 = 0, + DIVIDER_RANGE_02, + DIVIDER_RANGE_03, + DIVIDER_RANGE_MAX /* == 3*/ +}; + +struct dce_disp_clk { + struct display_clock base; + const struct dce_disp_clk_registers *regs; + const struct dce_disp_clk_shift *clk_shift; + const struct dce_disp_clk_mask *clk_mask; + + struct state_dependent_clocks max_clks_by_state[DM_PP_CLOCKS_MAX_STATES]; + struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + + bool use_max_disp_clk; + uint32_t dentist_vco_freq_khz; + + /* Cache the status of DFS-bypass feature*/ + bool dfs_bypass_enabled; + /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. + * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ + uint32_t dfs_bypass_disp_clk; + + /* Flag for Enabled SS on GPU PLL */ + bool ss_on_gpu_pll; + /* GPU PLL SS percentage (if down-spread enabled) */ + uint32_t gpu_pll_ss_percentage; + /* GPU PLL SS percentage Divider (100 or 1000) */ + uint32_t gpu_pll_ss_divider; + + +}; + + +struct display_clock *dce_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask); + +struct display_clock *dce110_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask); + +struct display_clock *dce112_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask); + +void dce_disp_clk_destroy(struct display_clock **disp_clk); + +#endif /* _DCE_CLOCKS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 5716ce1e58f4..c97416f7bc93 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -40,6 +40,7 @@ #include "dce110/dce110_ipp.h" #include "dce/dce_transform.h" #include "dce110/dce110_opp.h" +#include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" @@ -200,6 +201,18 @@ static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = { .reg_name = mm ## block ## id ## _ ## reg_name +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE100(id)\ @@ -717,9 +730,7 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.display_clock != NULL) - pool->base.display_clock->funcs->destroy( - &pool->base.display_clock); - pool->base.display_clock = NULL; + dce_disp_clk_destroy(&pool->base.display_clock); if (pool->base.irqs != NULL) dal_irq_service_destroy(&pool->base.irqs); @@ -970,7 +981,10 @@ static bool construct( } } - pool->base.display_clock = dal_display_clock_dce110_create(ctx); + pool->base.display_clock = dce_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8682c8b2a547..fa601f7f0b5a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -45,6 +45,7 @@ #include "dce110/dce110_transform_v.h" #include "dce110/dce110_opp.h" #include "dce110/dce110_opp_v.h" +#include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_hwseq.h" #include "dce110/dce110_hw_sequencer.h" @@ -187,6 +188,17 @@ static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = { #define SRI(reg_name, block, id)\ .reg_name = mm ## block ## id ## _ ## reg_name +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; #define transform_regs(id)\ [id] = {\ @@ -699,11 +711,8 @@ static void destruct(struct dce110_resource_pool *pool) } } - if (pool->base.display_clock != NULL) { - pool->base.display_clock->funcs->destroy( - &pool->base.display_clock); - pool->base.display_clock = NULL; - } + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); if (pool->base.irqs != NULL) { dal_irq_service_destroy(&pool->base.irqs); @@ -1261,7 +1270,10 @@ static bool construct( } } - pool->base.display_clock = dal_display_clock_dce110_create(ctx); + pool->base.display_clock = dce110_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index c50a215172b7..3a478300b848 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -41,6 +41,7 @@ #include "dce/dce_audio.h" #include "dce112/dce112_opp.h" #include "dce110/dce110_ipp.h" +#include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_hwseq.h" @@ -204,6 +205,19 @@ static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { #define SRI(reg_name, block, id)\ .reg_name = mm ## block ## id ## _ ## reg_name + +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -733,11 +747,8 @@ static void destruct(struct dce110_resource_pool *pool) } } - if (pool->base.display_clock != NULL) { - pool->base.display_clock->funcs->destroy( - &pool->base.display_clock); - pool->base.display_clock = NULL; - } + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); if (pool->base.irqs != NULL) { dal_irq_service_destroy(&pool->base.irqs); @@ -1299,9 +1310,10 @@ static bool construct( } } - pool->base.display_clock = dal_display_clock_dce112_create( - ctx); - + pool->base.display_clock = dce112_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 1d2a31e34617..517d42dfff0c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -45,6 +45,7 @@ #include "dce/dce_transform.h" #include "dce80/dce80_opp.h" #include "dce110/dce110_ipp.h" +#include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" @@ -215,6 +216,19 @@ static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { #define SRI(reg_name, block, id)\ .reg_name = mm ## block ## id ## _ ## reg_name + +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE_BASE(id)\ @@ -656,11 +670,8 @@ static void destruct(struct dce110_resource_pool *pool) } } - if (pool->base.display_clock != NULL) { - pool->base.display_clock->funcs->destroy( - &pool->base.display_clock); - pool->base.display_clock = NULL; - } + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); if (pool->base.irqs != NULL) { dal_irq_service_destroy(&pool->base.irqs); @@ -857,47 +868,6 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_bandwidth = dce80_validate_bandwidth }; -static enum dm_pp_clocks_state dce80_resource_convert_clock_state_pp_to_dc( - enum dm_pp_clocks_state pp_clock_state) -{ - enum dm_pp_clocks_state dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (pp_clock_state) { - case DM_PP_CLOCKS_STATE_INVALID: - dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; - break; - case DM_PP_CLOCKS_STATE_ULTRA_LOW: - dc_clocks_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - case DM_PP_CLOCKS_STATE_LOW: - dc_clocks_state = DM_PP_CLOCKS_STATE_LOW; - break; - case DM_PP_CLOCKS_STATE_NOMINAL: - dc_clocks_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - case DM_PP_CLOCKS_STATE_PERFORMANCE: - dc_clocks_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_4: - dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_4; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_5: - dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_5; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_6: - dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_6; - break; - case DM_PP_CLOCKS_DPM_STATE_LEVEL_7: - dc_clocks_state = DM_PP_CLOCKS_DPM_STATE_LEVEL_7; - break; - default: - dc_clocks_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - return dc_clocks_state; -} - static bool construct( uint8_t num_virtual_links, struct core_dc *dc, @@ -967,7 +937,10 @@ static bool construct( } } - pool->base.display_clock = dal_display_clock_dce80_create(ctx); + pool->base.display_clock = dce_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); @@ -977,8 +950,7 @@ static bool construct( if (dm_pp_get_static_clocks(ctx, &static_clk_info)) pool->base.display_clock->max_clks_state = - dce80_resource_convert_clock_state_pp_to_dc( - static_clk_info.max_clocks_state); + static_clk_info.max_clocks_state; { struct irq_service_init_data init_data; diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 44bad17fa318..460971dc3a70 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -43,15 +43,17 @@ enum dm_pp_clocks_state { /* Starting from DCE11, Max 8 levels of DPM state supported. */ DM_PP_CLOCKS_DPM_STATE_LEVEL_INVALID = DM_PP_CLOCKS_STATE_INVALID, - DM_PP_CLOCKS_DPM_STATE_LEVEL_0 = DM_PP_CLOCKS_STATE_ULTRA_LOW, - DM_PP_CLOCKS_DPM_STATE_LEVEL_1 = DM_PP_CLOCKS_STATE_LOW, - DM_PP_CLOCKS_DPM_STATE_LEVEL_2 = DM_PP_CLOCKS_STATE_NOMINAL, + DM_PP_CLOCKS_DPM_STATE_LEVEL_0, + DM_PP_CLOCKS_DPM_STATE_LEVEL_1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_2, /* to be backward compatible */ - DM_PP_CLOCKS_DPM_STATE_LEVEL_3 = DM_PP_CLOCKS_STATE_PERFORMANCE, - DM_PP_CLOCKS_DPM_STATE_LEVEL_4 = DM_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1, - DM_PP_CLOCKS_DPM_STATE_LEVEL_5 = DM_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1, - DM_PP_CLOCKS_DPM_STATE_LEVEL_6 = DM_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1, - DM_PP_CLOCKS_DPM_STATE_LEVEL_7 = DM_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1, + DM_PP_CLOCKS_DPM_STATE_LEVEL_3, + DM_PP_CLOCKS_DPM_STATE_LEVEL_4, + DM_PP_CLOCKS_DPM_STATE_LEVEL_5, + DM_PP_CLOCKS_DPM_STATE_LEVEL_6, + DM_PP_CLOCKS_DPM_STATE_LEVEL_7, + + DM_PP_CLOCKS_MAX_STATES }; struct dm_pp_gpu_clock_range { diff --git a/drivers/gpu/drm/amd/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile index 0b99a7474950..6ab4078405f2 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpu/Makefile @@ -9,24 +9,9 @@ AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) AMD_DISPLAY_FILES += $(AMD_DAL_GPU) -############################################################################### -# DCE 80 family -############################################################################### -GPU_DCE80 = display_clock_dce80.o - -AMD_DAL_GPU_DCE80 = $(addprefix $(AMDDALPATH)/dc/gpu/dce80/,$(GPU_DCE80)) - -AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE80) - - ############################################################################### # DCE 110 family ############################################################################### -GPU_DCE110 = display_clock_dce110.o - -AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110)) - -AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) GPU_DCE112 = display_clock_dce112.o diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c deleted file mode 100644 index 9dabaac2c550..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "include/bios_parser_interface.h" -#include "include/fixed32_32.h" -#include "include/logger_interface.h" - -#include "../divider_range.h" - -#include "display_clock_dce110.h" -#include "dc.h" - -#define FROM_DISPLAY_CLOCK(base) \ - container_of(base, struct display_clock_dce110, disp_clk_base) - -#define PSR_SET_WAITLOOP 0x31 - -static struct state_dependent_clocks max_clks_by_state[] = { -/*ClocksStateInvalid - should not be used*/ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, -/*ClocksStateLow*/ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, -/*ClocksStateNominal*/ -{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, -/*ClocksStatePerformance*/ -{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; - -/* Starting point for each divider range.*/ -enum divider_range_start { - DIVIDER_RANGE_01_START = 200, /* 2.00*/ - DIVIDER_RANGE_02_START = 1600, /* 16.00*/ - DIVIDER_RANGE_03_START = 3200, /* 32.00*/ - DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ -}; - -/* Array identifiers and count for the divider ranges.*/ -enum divider_range_count { - DIVIDER_RANGE_01 = 0, - DIVIDER_RANGE_02, - DIVIDER_RANGE_03, - DIVIDER_RANGE_MAX /* == 3*/ -}; - -/* Ranges for divider identifiers (Divider ID or DID) - mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -enum divider_id_register_setting { - DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, - DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, - DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, - DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 -}; - -/* Step size between each divider within a range. - Incrementing the DENTIST_DISPCLK_WDIVIDER by one - will increment the divider by this much.*/ -enum divider_range_step_size { - DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ - DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ - DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ -}; - -union dce110_dmcu_psr_config_data_wait_loop_reg1 { - struct { - unsigned int waitLoop:16; /* [15:0] */ - unsigned int reserved:16; /* [31:16] */ - } bits; - unsigned int u32All; -}; - -static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; - -#define DCE110_DFS_BYPASS_THRESHOLD_KHZ 400000 -/***************************************************************************** - * static functions - *****************************************************************************/ - -static bool dce110_set_min_clocks_state( - struct display_clock *dc, - enum dm_pp_clocks_state clocks_state) -{ - struct dm_pp_power_level_change_request level_change_req = { - clocks_state }; - - if (clocks_state > dc->max_clks_state) { - /*Requested state exceeds max supported state.*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state exceeds max supported state"); - return false; - } else if (clocks_state == dc->cur_min_clks_state) { - /*if we're trying to set the same state, we can just return - * since nothing needs to be done*/ - return true; - } - - /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) - dc->cur_min_clks_state = clocks_state; - - return true; -} - -static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) -{ - uint32_t dispclk_cntl_value; - uint32_t dp_ref_clk_cntl_value; - uint32_t dp_ref_clk_cntl_src_sel_value; - uint32_t dp_ref_clk_khz = 600000; - uint32_t target_div = INVALID_DIVIDER; - struct display_clock_dce110 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - /* ASSERT DP Reference Clock source is from DFS*/ - dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, - mmDPREFCLK_CNTL); - - dp_ref_clk_cntl_src_sel_value = - get_reg_field_value( - dp_ref_clk_cntl_value, - DPREFCLK_CNTL, DPREFCLK_SRC_SEL); - - ASSERT(dp_ref_clk_cntl_src_sel_value == 0); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently - * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ - dispclk_cntl_value = dm_read_reg(dc->ctx, - mmDENTIST_DISPCLK_CNTL); - - /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - get_reg_field_value(dispclk_cntl_value, - DENTIST_DISPCLK_CNTL, - DENTIST_DPREFCLK_WDIVIDER)); - - if (target_div != INVALID_DIVIDER) { - /* Calculate the current DFS clock, in kHz.*/ - dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - } - - /* SW will adjust DP REF Clock average value for all purposes - * (DP DTO / DP Audio DTO and DP GTC) - if clock is spread for all cases: - -if SS enabled on DP Ref clock and HW de-spreading enabled with SW - calculations for DS_INCR/DS_MODULO (this is planned to be default case) - -if SS enabled on DP Ref clock and HW de-spreading enabled with HW - calculations (not planned to be used, but average clock should still - be valid) - -if SS enabled on DP Ref clock and HW de-spreading disabled - (should not be case with CIK) then SW should program all rates - generated according to average value (case as with previous ASICs) - */ - if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { - struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk->gpu_pll_ss_percentage, - disp_clk->gpu_pll_ss_divider), 200); - struct fixed32_32 adj_dp_ref_clk_khz; - - ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, - ss_percentage); - adj_dp_ref_clk_khz = - dal_fixed32_32_mul_int( - ss_percentage, - dp_ref_clk_khz); - dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); - } - - return dp_ref_clk_khz; -} - -static void destroy(struct display_clock **base) -{ - struct display_clock_dce110 *dc110; - - dc110 = DCLCK110_FROM_BASE(*base); - - dm_free(dc110); - - *base = NULL; -} - -static bool display_clock_integrated_info_construct( - struct display_clock_dce110 *disp_clk) -{ - struct dc_debug *debug = &disp_clk->disp_clk_base.ctx->dc->debug; - struct dc_bios *bp = disp_clk->disp_clk_base.ctx->dc_bios; - struct integrated_info info; - struct firmware_info fw_info; - uint32_t i; - struct display_clock *base = &disp_clk->disp_clk_base; - - memset(&info, 0, sizeof(struct integrated_info)); - memset(&fw_info, 0, sizeof(struct firmware_info)); - - if (bp->integrated_info) - info = *bp->integrated_info; - - disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; - if (disp_clk->dentist_vco_freq_khz == 0) { - bp->funcs->get_firmware_info(bp, &fw_info); - disp_clk->dentist_vco_freq_khz = - fw_info.smu_gpu_pll_output_freq; - if (disp_clk->dentist_vco_freq_khz == 0) - disp_clk->dentist_vco_freq_khz = 3600000; - } - - base->min_display_clk_threshold_khz = - disp_clk->dentist_vco_freq_khz / 64; - - if (bp->integrated_info == NULL) - return false; - - /*update the maximum display clock for each power state*/ - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (i) { - case 0: - clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - - case 1: - clk_state = DM_PP_CLOCKS_STATE_LOW; - break; - - case 2: - clk_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - - case 3: - clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - - default: - clk_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - /*Do not allow bad VBIOS/SBIOS to override with invalid values, - * check for > 100MHz*/ - if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { - max_clks_by_state[clk_state].display_clk_khz = - info.disp_clk_voltage[i].max_supported_clk; - } - } - - disp_clk->dfs_bypass_enabled = false; - if (!debug->disable_dfs_bypass) - if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) - disp_clk->dfs_bypass_enabled = true; - - disp_clk->use_max_disp_clk = debug->max_disp_clk; - - return true; -} - -static enum dm_pp_clocks_state get_required_clocks_state( - struct display_clock *dc, - struct state_dependent_clocks *req_clocks) -{ - int32_t i; - struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc); - enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; - - if (!req_clocks) { - /* NULL pointer*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "%s: Invalid parameter", - __func__); - return DM_PP_CLOCKS_STATE_INVALID; - } - - /* Iterate from highest supported to lowest valid state, and update - * lowest RequiredState with the lowest state that satisfies - * all required clocks - */ - for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { - if ((req_clocks->display_clk_khz <= - max_clks_by_state[i].display_clk_khz) && - (req_clocks->pixel_clk_khz <= - max_clks_by_state[i].pixel_clk_khz)) - low_req_clk = i; - } - return low_req_clk; -} - -static void psr_wait_loop(struct dc_context *ctx, unsigned int display_clk_khz) -{ - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; - uint32_t masterCmd; - uint32_t masterComCntl; - union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - masterCmdData1.u32All = 0; - masterCmdData1.bits.waitLoop = display_clk_khz / 1000 / 7; - dm_write_reg(ctx, mmMASTER_COMM_DATA_REG1, masterCmdData1.u32All); - - /* setDMCUParam_Cmd */ - masterCmd = dm_read_reg(ctx, mmMASTER_COMM_CMD_REG); - set_reg_field_value( - masterCmd, - PSR_SET_WAITLOOP, - MASTER_COMM_CMD_REG, - MASTER_COMM_CMD_REG_BYTE0); - - dm_write_reg(ctx, mmMASTER_COMM_CMD_REG, masterCmd); - - /* notifyDMCUMsg */ - masterComCntl = dm_read_reg(ctx, mmMASTER_COMM_CNTL_REG); - set_reg_field_value( - masterComCntl, - 1, - MASTER_COMM_CNTL_REG, - MASTER_COMM_INTERRUPT); - dm_write_reg(ctx, mmMASTER_COMM_CNTL_REG, masterComCntl); -} - -static void dce110_set_clock( - struct display_clock *base, - uint32_t requested_clk_khz) -{ - struct bp_pixel_clock_parameters pxl_clk_params; - struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base); - struct dc_bios *bp = base->ctx->dc_bios; - - /* Prepare to program display clock*/ - memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); - - /* Make sure requested clock isn't lower than minimum threshold*/ - if (requested_clk_khz > 0) - requested_clk_khz = dm_max(requested_clk_khz, - base->min_display_clk_threshold_khz); - - pxl_clk_params.target_pixel_clock = requested_clk_khz; - pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - - bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); - - if (dc->dfs_bypass_enabled) { - - /* Cache the fixed display clock*/ - dc->dfs_bypass_disp_clk = - pxl_clk_params.dfs_bypass_display_clock; - } - - /* from power down, we need mark the clock state as ClocksStateNominal - * from HWReset, so when resume we will call pplib voltage regulator.*/ - if (requested_clk_khz == 0) - base->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - psr_wait_loop(base->ctx, requested_clk_khz); -} - - -static const struct display_clock_funcs funcs = { - .destroy = destroy, - .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_required_clocks_state = get_required_clocks_state, - .set_clock = dce110_set_clock, - .set_min_clocks_state = dce110_set_min_clocks_state -}; - -static bool dal_display_clock_dce110_construct( - struct display_clock_dce110 *dc110, - struct dc_context *ctx) -{ - struct display_clock *dc_base = &dc110->disp_clk_base; - struct dc_bios *bp = ctx->dc_bios; - - dc_base->ctx = ctx; - dc_base->min_display_clk_threshold_khz = 0; - - dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - dc_base->funcs = &funcs; - - dc110->dfs_bypass_disp_clk = 0; - - if (!display_clock_integrated_info_construct(dc110)) - dm_logger_write(dc_base->ctx->logger, LOG_WARNING, - "Cannot obtain VBIOS integrated info\n"); - - dc110->gpu_pll_ss_percentage = 0; - dc110->gpu_pll_ss_divider = 1000; - dc110->ss_on_gpu_pll = false; - -/* Initially set max clocks state to nominal. This should be updated by - * via a pplib call to DAL IRI eventually calling a - * DisplayEngineClock_Dce110::StoreMaxClocksState(). This call will come in - * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_01], - DIVIDER_RANGE_01_START, - DIVIDER_RANGE_01_STEP_SIZE, - DIVIDER_RANGE_01_BASE_DIVIDER_ID, - DIVIDER_RANGE_02_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_02], - DIVIDER_RANGE_02_START, - DIVIDER_RANGE_02_STEP_SIZE, - DIVIDER_RANGE_02_BASE_DIVIDER_ID, - DIVIDER_RANGE_03_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_03], - DIVIDER_RANGE_03_START, - DIVIDER_RANGE_03_STEP_SIZE, - DIVIDER_RANGE_03_BASE_DIVIDER_ID, - DIVIDER_RANGE_MAX_DIVIDER_ID); - - { - uint32_t ss_info_num = - bp->funcs->get_ss_entry_number(bp, - AS_SIGNAL_TYPE_GPU_PLL); - - if (ss_info_num) { - struct spread_spectrum_info info; - enum bp_result result; - - memset(&info, 0, sizeof(info)); - - result = bp->funcs->get_spread_spectrum_info(bp, - AS_SIGNAL_TYPE_GPU_PLL, - 0, - &info); - - /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS - * even if SS not enabled and in that case - * SSInfo.spreadSpectrumPercentage !=0 would be sign - * that SS is enabled - */ - if (result == BP_RESULT_OK && - info.spread_spectrum_percentage != 0) { - dc110->ss_on_gpu_pll = true; - dc110->gpu_pll_ss_divider = - info.spread_percentage_divider; - - if (info.type.CENTER_MODE == 0) { - /* Currently for DP Reference clock we - * need only SS percentage for - * downspread */ - dc110->gpu_pll_ss_percentage = - info.spread_spectrum_percentage; - } - } - - } - } - - return true; -} - -/***************************************************************************** - * public functions - *****************************************************************************/ - -struct display_clock *dal_display_clock_dce110_create( - struct dc_context *ctx) -{ - struct display_clock_dce110 *dc110; - - dc110 = dm_alloc(sizeof(struct display_clock_dce110)); - - if (dc110 == NULL) - return NULL; - - if (dal_display_clock_dce110_construct(dc110, ctx)) - return &dc110->disp_clk_base; - - dm_free(dc110); - - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h deleted file mode 100644 index 50b51c41b0d9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce110/display_clock_dce110.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DAL_DISPLAY_CLOCK_DCE110_H__ -#define __DAL_DISPLAY_CLOCK_DCE110_H__ - -#include "display_clock_interface.h" - -struct display_clock_dce110 { - struct display_clock disp_clk_base; - bool use_max_disp_clk; - uint32_t dentist_vco_freq_khz; - /* Cache the status of DFS-bypass feature*/ - bool dfs_bypass_enabled; - /* GPU PLL SS percentage (if down-spread enabled) */ - uint32_t gpu_pll_ss_percentage; - /* GPU PLL SS percentage Divider (100 or 1000) */ - uint32_t gpu_pll_ss_divider; - /* Flag for Enabled SS on GPU PLL */ - bool ss_on_gpu_pll; - /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. - * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - uint32_t dfs_bypass_disp_clk; -}; - -#define DCLCK110_FROM_BASE(dc_base) \ - container_of(dc_base, struct display_clock_dce110, disp_clk_base) - -#endif /* __DAL_DISPLAY_CLOCK_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c index 930548bdd8b2..e0d67fb6c633 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c @@ -71,102 +71,6 @@ enum divider_range_step_size { static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; -#define dce112_DFS_BYPASS_THRESHOLD_KHZ 400000 - -static bool dce112_set_min_clocks_state( - struct display_clock *dc, - enum dm_pp_clocks_state clocks_state) -{ - struct dm_pp_power_level_change_request level_change_req = { - clocks_state }; - - if (clocks_state > dc->max_clks_state) { - /*Requested state exceeds max supported state.*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state exceeds max supported state"); - return false; - } else if (clocks_state == dc->cur_min_clks_state) { - /*if we're trying to set the same state, we can just return - * since nothing needs to be done*/ - return true; - } - - /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) - dc->cur_min_clks_state = clocks_state; - - return true; -} - -static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) -{ - uint32_t dispclk_cntl_value; - uint32_t dp_ref_clk_cntl_value; - uint32_t dp_ref_clk_cntl_src_sel_value; - uint32_t dp_ref_clk_khz = 600000; - uint32_t target_div = INVALID_DIVIDER; - struct display_clock_dce112 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - /* ASSERT DP Reference Clock source is from DFS*/ - dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, - mmDPREFCLK_CNTL); - - dp_ref_clk_cntl_src_sel_value = - get_reg_field_value( - dp_ref_clk_cntl_value, - DPREFCLK_CNTL, DPREFCLK_SRC_SEL); - - ASSERT(dp_ref_clk_cntl_src_sel_value == 0); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently - * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ - dispclk_cntl_value = dm_read_reg(dc->ctx, - mmDENTIST_DISPCLK_CNTL); - - /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - get_reg_field_value(dispclk_cntl_value, - DENTIST_DISPCLK_CNTL, - DENTIST_DPREFCLK_WDIVIDER)); - - if (target_div != INVALID_DIVIDER) { - /* Calculate the current DFS clock, in kHz.*/ - dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - } - - /* SW will adjust DP REF Clock average value for all purposes - * (DP DTO / DP Audio DTO and DP GTC) - if clock is spread for all cases: - -if SS enabled on DP Ref clock and HW de-spreading enabled with SW - calculations for DS_INCR/DS_MODULO (this is planned to be default case) - -if SS enabled on DP Ref clock and HW de-spreading enabled with HW - calculations (not planned to be used, but average clock should still - be valid) - -if SS enabled on DP Ref clock and HW de-spreading disabled - (should not be case with CIK) then SW should program all rates - generated according to average value (case as with previous ASICs) - */ - if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { - struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk->gpu_pll_ss_percentage, - disp_clk->gpu_pll_ss_divider), 200); - struct fixed32_32 adj_dp_ref_clk_khz; - - ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, - ss_percentage); - adj_dp_ref_clk_khz = - dal_fixed32_32_mul_int( - ss_percentage, - dp_ref_clk_khz); - dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); - } - - return dp_ref_clk_khz; -} void dispclk_dce112_destroy(struct display_clock **base) { @@ -233,38 +137,6 @@ static bool display_clock_integrated_info_construct( return true; } -enum dm_pp_clocks_state dispclk_dce112_get_required_clocks_state( - struct display_clock *dc, - struct state_dependent_clocks *req_clocks) -{ - int32_t i; - struct display_clock_dce112 *disp_clk = DCLCK112_FROM_BASE(dc); - enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; - - if (!req_clocks) { - /* NULL pointer*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "%s: Invalid parameter", - __func__); - return DM_PP_CLOCKS_STATE_INVALID; - } - - /* Iterate from highest supported to lowest valid state, and update - * lowest RequiredState with the lowest state that satisfies - * all required clocks - */ - for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { - if ((req_clocks->display_clk_khz <= - (disp_clk->max_clks_by_state + i)-> - display_clk_khz) && - (req_clocks->pixel_clk_khz <= - (disp_clk->max_clks_by_state + i)-> - pixel_clk_khz)) - low_req_clk = i; - } - return low_req_clk; -} - void dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz) @@ -304,10 +176,7 @@ void dce112_set_clock( static const struct display_clock_funcs funcs = { .destroy = dispclk_dce112_destroy, - .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_required_clocks_state = dispclk_dce112_get_required_clocks_state, .set_clock = dce112_set_clock, - .set_min_clocks_state = dce112_set_min_clocks_state }; bool dal_display_clock_dce112_construct( @@ -406,24 +275,3 @@ bool dal_display_clock_dce112_construct( return true; } -/***************************************************************************** - * public functions - *****************************************************************************/ - -struct display_clock *dal_display_clock_dce112_create( - struct dc_context *ctx) -{ - struct display_clock_dce112 *dc112; - - dc112 = dm_alloc(sizeof(struct display_clock_dce112)); - - if (dc112 == NULL) - return NULL; - - if (dal_display_clock_dce112_construct(dc112, ctx)) - return &dc112->disp_clk_base; - - dm_free(dc112); - - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h index b750bb1766bd..0743c514a60f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h @@ -71,23 +71,9 @@ bool dal_display_clock_dce112_construct( void dispclk_dce112_destroy(struct display_clock **base); -enum dm_pp_clocks_state dispclk_dce112_get_min_clocks_state( - struct display_clock *base); - -enum dm_pp_clocks_state dispclk_dce112_get_required_clocks_state( - struct display_clock *dc, - struct state_dependent_clocks *req_clocks); - void dce112_set_clock( struct display_clock *base, uint32_t requested_clk_khz); -bool dispclk_dce112_set_min_clocks_state( - struct display_clock *base, - enum dm_pp_clocks_state clocks_state); - -void dispclk_dce112_store_max_clocks_state( - struct display_clock *base, - enum dm_pp_clocks_state max_clocks_state); #endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c deleted file mode 100644 index 9d7cb2cb161c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "include/bios_parser_interface.h" -#include "include/fixed32_32.h" -#include "include/logger_interface.h" - -#include "../divider_range.h" -#include "display_clock_dce80.h" -#include "dc.h" - -#define DCE80_DFS_BYPASS_THRESHOLD_KHZ 100000 - -/* Max clock values for each state indexed by "enum clocks_state": */ -static struct state_dependent_clocks max_clks_by_state[] = { -/* ClocksStateInvalid - should not be used */ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/* ClocksStateLow */ -{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, -/* ClocksStateNominal */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, -/* ClocksStatePerformance */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; - -/* Starting point for each divider range.*/ -enum divider_range_start { - DIVIDER_RANGE_01_START = 200, /* 2.00*/ - DIVIDER_RANGE_02_START = 1600, /* 16.00*/ - DIVIDER_RANGE_03_START = 3200, /* 32.00*/ - DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ -}; - -/* Ranges for divider identifiers (Divider ID or DID) - mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -enum divider_id_register_setting { - DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, - DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, - DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, - DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 -}; - -/* Step size between each divider within a range. - Incrementing the DENTIST_DISPCLK_WDIVIDER by one - will increment the divider by this much.*/ -enum divider_range_step_size { - DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ - DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ - DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ -}; - -/* Array identifiers and count for the divider ranges.*/ -enum divider_range_count { - DIVIDER_RANGE_01 = 0, - DIVIDER_RANGE_02, - DIVIDER_RANGE_03, - DIVIDER_RANGE_MAX /* == 3*/ -}; - -static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; - -#define FROM_DISPLAY_CLOCK(base) \ - container_of(base, struct display_clock_dce80, disp_clk) - -static void dce80_set_clock( - struct display_clock *dc, - uint32_t requested_clk_khz) -{ - struct bp_pixel_clock_parameters pxl_clk_params; - struct dc_bios *bp = dc->ctx->dc_bios; - - /* Prepare to program display clock*/ - memset(&pxl_clk_params, 0, sizeof(pxl_clk_params)); - - pxl_clk_params.target_pixel_clock = requested_clk_khz; - pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - - bp->funcs->program_display_engine_pll(bp, &pxl_clk_params); - - /* from power down, we need mark the clock state as ClocksStateNominal - * from HWReset, so when resume we will call pplib voltage regulator.*/ - if (requested_clk_khz == 0) - dc->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; -} - -static enum dm_pp_clocks_state get_required_clocks_state - (struct display_clock *dc, - struct state_dependent_clocks *req_clocks) -{ - int32_t i; - enum dm_pp_clocks_state low_req_clk = dc->max_clks_state; - - if (!req_clocks) { - /* NULL pointer*/ - BREAK_TO_DEBUGGER(); - return DM_PP_CLOCKS_STATE_INVALID; - } - - /* Iterate from highest supported to lowest valid state, and update - * lowest RequiredState with the lowest state that satisfies - * all required clocks - */ - for (i = dc->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; --i) { - if ((req_clocks->display_clk_khz <= - max_clks_by_state[i].display_clk_khz) && - (req_clocks->pixel_clk_khz <= - max_clks_by_state[i].pixel_clk_khz)) - low_req_clk = i; - } - return low_req_clk; -} - -static bool dce80_set_min_clocks_state( - struct display_clock *dc, - enum dm_pp_clocks_state clocks_state) -{ - struct dm_pp_power_level_change_request level_change_req = { - clocks_state }; - - if (clocks_state > dc->max_clks_state) { - /*Requested state exceeds max supported state.*/ - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "Requested state exceeds max supported state"); - return false; - } else if (clocks_state == dc->cur_min_clks_state) { - /*if we're trying to set the same state, we can just return - * since nothing needs to be done*/ - return true; - } - - /* get max clock state from PPLIB */ - if (dm_pp_apply_power_level_change_request(dc->ctx, &level_change_req)) - dc->cur_min_clks_state = clocks_state; - - return true; -} - -static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) -{ - uint32_t dispclk_cntl_value; - uint32_t dp_ref_clk_cntl_value; - uint32_t dp_ref_clk_cntl_src_sel_value; - uint32_t dp_ref_clk_khz = 600000; - uint32_t target_div = INVALID_DIVIDER; - struct display_clock_dce80 *disp_clk = FROM_DISPLAY_CLOCK(dc); - - /* ASSERT DP Reference Clock source is from DFS*/ - dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, - mmDPREFCLK_CNTL); - - dp_ref_clk_cntl_src_sel_value = - get_reg_field_value( - dp_ref_clk_cntl_value, - DPREFCLK_CNTL, DPREFCLK_SRC_SEL); - - ASSERT(dp_ref_clk_cntl_src_sel_value == 0); - - /* Read the mmDENTIST_DISPCLK_CNTL to get the currently - * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ - dispclk_cntl_value = dm_read_reg(dc->ctx, - mmDENTIST_DISPCLK_CNTL); - - /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dal_divider_range_get_divider( - divider_ranges, - DIVIDER_RANGE_MAX, - get_reg_field_value(dispclk_cntl_value, - DENTIST_DISPCLK_CNTL, - DENTIST_DPREFCLK_WDIVIDER)); - - if (target_div != INVALID_DIVIDER) { - /* Calculate the current DFS clock, in kHz.*/ - dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR - * disp_clk->dentist_vco_freq_khz) / target_div; - } - - /* SW will adjust DP REF Clock average value for all purposes - * (DP DTO / DP Audio DTO and DP GTC) - if clock is spread for all cases: - -if SS enabled on DP Ref clock and HW de-spreading enabled with SW - calculations for DS_INCR/DS_MODULO (this is planned to be default case) - -if SS enabled on DP Ref clock and HW de-spreading enabled with HW - calculations (not planned to be used, but average clock should still - be valid) - -if SS enabled on DP Ref clock and HW de-spreading disabled - (should not be case with CIK) then SW should program all rates - generated according to average value (case as with previous ASICs) - */ - if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { - struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( - dal_fixed32_32_from_fraction( - disp_clk->gpu_pll_ss_percentage, - disp_clk->gpu_pll_ss_divider), 200); - struct fixed32_32 adj_dp_ref_clk_khz; - - ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, - ss_percentage); - adj_dp_ref_clk_khz = - dal_fixed32_32_mul_int( - ss_percentage, - dp_ref_clk_khz); - dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); - } - - return dp_ref_clk_khz; -} - -static void display_clock_ss_construct( - struct display_clock_dce80 *disp_clk) -{ - struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios; - uint32_t ss_entry_num = bp->funcs->get_ss_entry_number(bp, - AS_SIGNAL_TYPE_GPU_PLL); - - /*Read SS Info from VBIOS SS Info table for DP Reference Clock spread.*/ - if (ss_entry_num > 0) {/* Should be only one entry */ - struct spread_spectrum_info ss_info; - enum bp_result res; - - memset(&ss_info, 0, sizeof(struct spread_spectrum_info)); - - res = bp->funcs->get_spread_spectrum_info(bp, - AS_SIGNAL_TYPE_GPU_PLL, 0, &ss_info); - - /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS even if - * SS not enabled and in that case - * SSInfo.spreadSpectrumPercentage !=0 would be - * sign that SS is enabled*/ - if (res == BP_RESULT_OK && ss_info.spread_spectrum_percentage != 0) { - disp_clk->ss_on_gpu_pll = true; - disp_clk->gpu_pll_ss_divider = - ss_info.spread_percentage_divider; - if (ss_info.type.CENTER_MODE == 0) - /* Currently we need only SS - * percentage for down-spread*/ - disp_clk->gpu_pll_ss_percentage = - ss_info.spread_spectrum_percentage; - } - } -} - -static bool display_clock_integrated_info_construct( - struct display_clock_dce80 *disp_clk) -{ - struct dc_debug *debug = &disp_clk->disp_clk.ctx->dc->debug; - struct dc_bios *bp = disp_clk->disp_clk.ctx->dc_bios; - struct integrated_info info = { { { 0 } } }; - struct firmware_info fw_info = { { 0 } }; - uint32_t i; - - if (bp->integrated_info) - info = *bp->integrated_info; - - disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; - if (disp_clk->dentist_vco_freq_khz == 0) { - bp->funcs->get_firmware_info(bp, &fw_info); - disp_clk->dentist_vco_freq_khz = - fw_info.smu_gpu_pll_output_freq; - if (disp_clk->dentist_vco_freq_khz == 0) - disp_clk->dentist_vco_freq_khz = 3600000; - } - disp_clk->disp_clk.min_display_clk_threshold_khz = - disp_clk->dentist_vco_freq_khz / 64; - - /* TODO: initialise disp_clk->dfs_bypass_disp_clk */ - - /*update the maximum display clock for each power state*/ - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (i) { - case 0: - clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - - case 1: - clk_state = DM_PP_CLOCKS_STATE_LOW; - break; - - case 2: - clk_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - - case 3: - clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - - default: - clk_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - /*Do not allow bad VBIOS/SBIOS to override with invalid values, - * check for > 100MHz*/ - if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { - max_clks_by_state[clk_state].display_clk_khz = - info.disp_clk_voltage[i].max_supported_clk; - } - } - - disp_clk->dfs_bypass_enabled = false; - if (!debug->disable_dfs_bypass) - if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) - disp_clk->dfs_bypass_enabled = true; - - disp_clk->use_max_disp_clk = debug->max_disp_clk; - - return true; -} - -static void destroy(struct display_clock **dc) -{ - struct display_clock_dce80 *disp_clk; - - disp_clk = FROM_DISPLAY_CLOCK(*dc); - dm_free(disp_clk); - *dc = NULL; -} - -static const struct display_clock_funcs funcs = { - .destroy = destroy, - .get_dp_ref_clk_frequency = get_dp_ref_clk_frequency, - .get_required_clocks_state = get_required_clocks_state, - .set_clock = dce80_set_clock, - .set_min_clocks_state = dce80_set_min_clocks_state -}; - - -struct display_clock *dal_display_clock_dce80_create( - struct dc_context *ctx) -{ - struct display_clock_dce80 *disp_clk; - struct display_clock *dc_base; - - disp_clk = dm_alloc(sizeof(struct display_clock_dce80)); - - if (disp_clk == NULL) - return NULL; - - dc_base = &disp_clk->disp_clk; - - dc_base->ctx = ctx; - dc_base->min_display_clk_threshold_khz = 0; - - dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - dc_base->funcs = &funcs; - /* - * set_dp_ref_clock_source - * set_clock_state - * get_clock_state - * get_dfs_bypass_threshold - */ - - disp_clk->gpu_pll_ss_percentage = 0; - disp_clk->gpu_pll_ss_divider = 1000; - disp_clk->ss_on_gpu_pll = false; - disp_clk->dfs_bypass_enabled = false; - disp_clk->dfs_bypass_disp_clk = 0; - disp_clk->use_max_disp_clk = true;/* false will hang the system! */ - -/* Initially set max clocks state to nominal. This should be updated by - * via a pplib call to DAL IRI eventually calling a - * DisplayEngineClock_Dce50::StoreMaxClocksState(). This call will come in - * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; -/* Initially set current min clocks state to invalid since we - * cannot make any assumption about PPLIB's initial state. This will be updated - * by HWSS via SetMinClocksState() on first mode set prior to programming - * state dependent clocks.*/ - disp_clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - display_clock_ss_construct(disp_clk); - - if (!display_clock_integrated_info_construct(disp_clk)) { - dm_logger_write(dc_base->ctx->logger, LOG_WARNING, - "Cannot obtain VBIOS integrated info"); - } - - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_01], - DIVIDER_RANGE_01_START, - DIVIDER_RANGE_01_STEP_SIZE, - DIVIDER_RANGE_01_BASE_DIVIDER_ID, - DIVIDER_RANGE_02_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_02], - DIVIDER_RANGE_02_START, - DIVIDER_RANGE_02_STEP_SIZE, - DIVIDER_RANGE_02_BASE_DIVIDER_ID, - DIVIDER_RANGE_03_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_03], - DIVIDER_RANGE_03_START, - DIVIDER_RANGE_03_STEP_SIZE, - DIVIDER_RANGE_03_BASE_DIVIDER_ID, - DIVIDER_RANGE_MAX_DIVIDER_ID); - - dm_free(disp_clk); - return NULL; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h b/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h deleted file mode 100644 index c155bb6a4321..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce80/display_clock_dce80.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DAL_DISPLAY_CLOCK_DCE80_H__ -#define __DAL_DISPLAY_CLOCK_DCE80_H__ - -#include "display_clock_interface.h" - -struct display_clock_dce80 { - struct display_clock disp_clk; - /* DFS input - GPUPLL VCO frequency - from VBIOS Firmware info. */ - uint32_t dentist_vco_freq_khz; - /* GPU PLL SS percentage (if down-spread enabled)*/ - uint32_t gpu_pll_ss_percentage; - /* GPU PLL SS percentage Divider (100 or 1000)*/ - uint32_t gpu_pll_ss_divider; - /* Flag for Enabled SS on GPU PLL*/ - bool ss_on_gpu_pll; - /* Current minimum display block clocks state*/ - enum dm_pp_clocks_state cur_min_clks_state; - /* DFS-bypass feature variable - Cache the status of DFS-bypass feature*/ - bool dfs_bypass_enabled; - /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. - * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - uint32_t dfs_bypass_disp_clk; - bool use_max_disp_clk; -}; - -struct display_clock *dal_display_clock_dce80_create( - struct dc_context *ctx); - -#endif /* __DAL_DISPLAY_CLOCK_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/include/display_clock_interface.h index 6ba8c093793d..53a01381c638 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/include/display_clock_interface.h @@ -41,10 +41,9 @@ struct state_dependent_clocks { struct display_clock { struct dc_context *ctx; const struct display_clock_funcs *funcs; - uint32_t min_display_clk_threshold_khz; - /* Max display block clocks state*/ - enum dm_pp_clocks_state max_clks_state; + int min_display_clk_threshold_khz; + enum dm_pp_clocks_state max_clks_state; enum dm_pp_clocks_state cur_min_clks_state; }; @@ -61,15 +60,7 @@ struct display_clock_funcs { }; -struct display_clock *dal_display_clock_dce112_create( - struct dc_context *ctx); - -struct display_clock *dal_display_clock_dce110_create( - struct dc_context *ctx); - -struct display_clock *dal_display_clock_dce80_create( - struct dc_context *ctx); - void dal_display_clock_destroy(struct display_clock **to_destroy); + #endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ -- GitLab From 8318a7eb988c62fa231c71538628ba85d4fbe7ef Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Dec 2016 10:55:32 -0500 Subject: [PATCH 0083/2898] drm/amd/display: add newline to generic_reg_wait timeout message Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 3a80b0c08ae4..c5ff7b6d733d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -138,7 +138,7 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, return reg_val; } - DC_ERR("REG_WAIT timeout %dus * %d tries - %s", + DC_ERR("REG_WAIT timeout %dus * %d tries - %s\n", delay_between_poll_us, time_out_num_tries, func_name); return reg_val; } -- GitLab From 85944914f1de9b12fb2867f8dd835835f08861a2 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Dec 2016 17:41:42 -0500 Subject: [PATCH 0084/2898] drm/amd/display: fix display clock integrated info read Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 77033fe8a8e5..846754c16831 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -342,7 +342,7 @@ static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) info.disp_clk_voltage[i].max_supported_clk; } - if (!debug->disable_dfs_bypass) + if (!debug->disable_dfs_bypass && bp->integrated_info) if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) clk_dce->dfs_bypass_enabled = true; -- GitLab From b007045674723f649e8a9cf0504dc987a141160d Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 30 Nov 2016 17:57:24 -0500 Subject: [PATCH 0085/2898] drm/amd/display: use rgb full range as default quantization for non HDMI Refactor the quantization decision to color module. Add the check if non HDMI, default quantization should be rgb full range. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/color/color.c | 88 +++++++++++++++++-- .../drm/amd/display/modules/inc/mod_color.h | 12 ++- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 30d09d358576..0610b82b6d84 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -2184,7 +2184,8 @@ bool mod_color_set_saturation(struct mod_color *mod_color, return true; } -bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, +bool mod_color_persist_user_preferred_quantization_range( + struct mod_color *mod_color, const struct dc_sink *sink, enum dc_quantization_range quantization_range) { @@ -2214,13 +2215,90 @@ bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, const struct dc_sink *sink, + const struct dc_crtc_timing *timing, enum dc_quantization_range *quantization_range) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index; + unsigned int sink_index = sink_index_from_sink(core_color, sink); + enum dc_quantization_range user_preferred_quantization_range = + core_color->state[sink_index]. + preferred_quantization_range; + bool rgb_full_range_supported = + mod_color_is_rgb_full_range_supported_for_timing( + sink, timing); + bool rgb_limited_range_supported = + mod_color_is_rgb_limited_range_supported_for_timing( + sink, timing); + + if (rgb_full_range_supported && rgb_limited_range_supported) + *quantization_range = user_preferred_quantization_range; + else if (rgb_full_range_supported && !rgb_limited_range_supported) + *quantization_range = QUANTIZATION_RANGE_FULL; + else if (!rgb_full_range_supported && rgb_limited_range_supported) + *quantization_range = QUANTIZATION_RANGE_LIMITED; + else + *quantization_range = QUANTIZATION_RANGE_UNKNOWN; - sink_index = sink_index_from_sink(core_color, sink); - *quantization_range = core_color->state[sink_index]. - preferred_quantization_range; return true; } + +bool mod_color_is_rgb_full_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing) +{ + bool result = false; + + if (!sink || !timing) + return result; + + if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) + if (timing->vic || timing->hdmi_vic) + if (timing->h_addressable == 640 && + timing->v_addressable == 480 && + (timing->pix_clk_khz == 25200 || + timing->pix_clk_khz == 25170 || + timing->pix_clk_khz == 25175)) + result = true; + else + /* don't support full range rgb */ + /* for HDMI CEA861 timings except VGA mode */ + result = false; + else + result = true; + else + result = true; + + return result; +} + +bool mod_color_is_rgb_limited_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing) +{ + bool result = false; + + if (!sink || !timing) + return result; + + if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) + if (timing->vic || timing->hdmi_vic) + if (timing->h_addressable == 640 && + timing->v_addressable == 480 && + (timing->pix_clk_khz == 25200 || + timing->pix_clk_khz == 25170 || + timing->pix_clk_khz == 25175)) + /* don't support rgb limited for */ + /* HDMI CEA VGA mode */ + result = false; + else + /* support rgb limited for non VGA CEA timing */ + result = true; + else + /* support rgb limited for non CEA HDMI timing */ + result = true; + else + /* don't support rgb limited for non HDMI signal */ + result = false; + + return result; +} diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index e54fe2cb8611..91abc173444a 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -168,12 +168,22 @@ bool mod_color_set_saturation(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, int saturation_value); -bool mod_color_set_preferred_quantization_range(struct mod_color *mod_color, +bool mod_color_persist_user_preferred_quantization_range( + struct mod_color *mod_color, const struct dc_sink *sink, enum dc_quantization_range quantization_range); bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, const struct dc_sink *sink, + const struct dc_crtc_timing *timing, enum dc_quantization_range *quantization_range); +bool mod_color_is_rgb_full_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing); + +bool mod_color_is_rgb_limited_range_supported_for_timing( + const struct dc_sink *sink, + const struct dc_crtc_timing *timing); + #endif /* MOD_COLOR_H_ */ -- GitLab From 13625c7bf328c9e201363eba3c3e5a15560c4ae9 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 29 Nov 2016 13:11:08 -0500 Subject: [PATCH 0086/2898] drm/amd/display: create scratch_val_ctx as temp w/a Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 ++++- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 70dc70685471..a3c5def507a9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -452,6 +452,8 @@ static void destruct(struct core_dc *dc) dm_free(dc->temp_flip_context); dc->temp_flip_context = NULL; + dm_free(dc->scratch_val_ctx); + dc->scratch_val_ctx = NULL; destroy_links(dc); @@ -490,6 +492,7 @@ static bool construct(struct core_dc *dc, dc->current_context = dm_alloc(sizeof(*dc->current_context)); dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); + dc->scratch_val_ctx = dm_alloc(sizeof(*dc->temp_flip_context)); if (!dc->current_context || !dc->temp_flip_context) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -1217,7 +1220,7 @@ bool dc_pre_update_surfaces_to_target( goto unexpected_fail; } resource_validate_ctx_destruct(context); - dm_free(context); + core_dc->scratch_val_ctx = context; context = temp_context; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 7d6dc8ea75ab..b5a5207a4df0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -24,6 +24,7 @@ struct core_dc { /* TODO: determine max number of targets*/ struct validate_context *current_context; struct validate_context *temp_flip_context; + struct validate_context *scratch_val_ctx; struct resource_pool *res_pool; /*Power State*/ -- GitLab From e91dbe3dee1acae4909bcc33288d47a779e8b27f Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Mon, 5 Dec 2016 18:20:51 -0500 Subject: [PATCH 0087/2898] drm/amd/display: Temporarily blocking interlacing mode until it's supported. Signed-off-by: Ding Wang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 12a258763ef1..e70704d1ba87 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1117,6 +1117,10 @@ bool dce110_timing_generator_validate_timing( if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) return false; + /* Temporarily blocking interlacing mode until it's supported */ + if (timing->flags.INTERLACE == 1) + return false; + /* Check maximum number of pixels supported by Timing Generator * (Currently will never fail, in order to fail needs display which * needs more than 8192 horizontal and -- GitLab From e11b86ad7d97671ec9543824de0529bd3f8d2db7 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Dec 2016 14:48:04 -0500 Subject: [PATCH 0088/2898] drm/amd/display: moving remaining functionality from gpu to dce_clocks Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/Makefile | 7 +- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 183 +++++++++++- .../gpu/drm/amd/display/dc/dce/dce_clocks.h | 36 ++- drivers/gpu/drm/amd/display/dc/gpu/Makefile | 21 -- .../dc/gpu/dce112/display_clock_dce112.c | 277 ------------------ .../dc/gpu/dce112/display_clock_dce112.h | 79 ----- .../drm/amd/display/dc/gpu/divider_range.c | 127 -------- .../drm/amd/display/dc/gpu/divider_range.h | 62 ---- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- .../inc/hw/display_clock.h} | 27 +- 10 files changed, 207 insertions(+), 614 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/Makefile delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.c delete mode 100644 drivers/gpu/drm/amd/display/dc/gpu/divider_range.h rename drivers/gpu/drm/amd/display/{include/display_clock_interface.h => dc/inc/hw/display_clock.h} (75%) diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 5fac034093e9..26e2b50e4954 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -2,8 +2,7 @@ # Makefile for Display Core (dc) component. # -DC_LIBS = basics bios calcs dce \ -gpio gpu i2caux irq virtual +DC_LIBS = basics bios calcs dce gpio i2caux irq virtual DC_LIBS += dce112 DC_LIBS += dce110 @@ -14,8 +13,8 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) -DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o dc_stream.o \ -dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o +DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o \ +dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 846754c16831..8e2519b1c9df 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -30,6 +30,8 @@ #include "bios_parser_interface.h" #include "dc.h" +#define TO_DCE_CLOCKS(clocks)\ + container_of(clocks, struct dce_disp_clk, base) #define REG(reg) \ (clk_dce->regs->reg) @@ -41,8 +43,45 @@ #define CTX \ clk_dce->base.ctx +/* Max clock values for each state indexed by "enum clocks_state": */ +static struct state_dependent_clocks dce80_max_clks_by_state[] = { +/* ClocksStateInvalid - should not be used */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateLow */ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, +/* ClocksStateNominal */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, +/* ClocksStatePerformance */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; + +static struct state_dependent_clocks dce110_max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; + +static struct state_dependent_clocks dce112_max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; + /* Starting point for each divider range.*/ -enum divider_range_start { +enum dce_divider_range_start { DIVIDER_RANGE_01_START = 200, /* 2.00*/ DIVIDER_RANGE_02_START = 1600, /* 16.00*/ DIVIDER_RANGE_03_START = 3200, /* 32.00*/ @@ -51,7 +90,7 @@ enum divider_range_start { /* Ranges for divider identifiers (Divider ID or DID) mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -enum divider_id_register_setting { +enum dce_divider_id_register_setting { DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, @@ -61,14 +100,114 @@ enum divider_id_register_setting { /* Step size between each divider within a range. Incrementing the DENTIST_DISPCLK_WDIVIDER by one will increment the divider by this much.*/ -enum divider_range_step_size { +enum dce_divider_range_step_size { DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ }; +static bool dce_divider_range_construct( + struct dce_divider_range *div_range, + int range_start, + int range_step, + int did_min, + int did_max) +{ + div_range->div_range_start = range_start; + div_range->div_range_step = range_step; + div_range->did_min = did_min; + div_range->did_max = did_max; + + if (div_range->div_range_step == 0) { + div_range->div_range_step = 1; + /*div_range_step cannot be zero*/ + BREAK_TO_DEBUGGER(); + } + /* Calculate this based on the other inputs.*/ + /* See DividerRange.h for explanation of */ + /* the relationship between divider id (DID) and a divider.*/ + /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ + /* Maximum divider identified in this range = + * (Number of Divider IDs)*Step size between dividers + * + The start of this range.*/ + div_range->div_range_end = (did_max - did_min) * range_step + + range_start; + return true; +} + +static int dce_divider_range_calc_divider( + struct dce_divider_range *div_range, + int did) +{ + /* Is this DID within our range?*/ + if ((did < div_range->did_min) || (did >= div_range->did_max)) + return INVALID_DIVIDER; + + return ((did - div_range->did_min) * div_range->div_range_step) + + div_range->div_range_start; + +} + +static int dce_divider_range_calc_did( + struct dce_divider_range *div_range, + int div) +{ + int did; + /* Check before dividing.*/ + if (div_range->div_range_step == 0) { + div_range->div_range_step = 1; + /*div_range_step cannot be zero*/ + BREAK_TO_DEBUGGER(); + } + /* Is this divider within our range?*/ + if ((div < div_range->div_range_start) + || (div >= div_range->div_range_end)) + return INVALID_DID; +/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ + did = div - div_range->div_range_start; + did += div_range->div_range_step - 1; + did /= div_range->div_range_step; + did += div_range->did_min; + return did; +} + +static int dce_divider_range_get_divider( + struct dce_divider_range *div_range, + int ranges_num, + int did) +{ + int div = INVALID_DIVIDER; + int i; -static uint32_t dce_clocks_get_dp_ref_freq(struct display_clock *clk) + for (i = 0; i < ranges_num; i++) { + /* Calculate divider with given divider ID*/ + div = dce_divider_range_calc_divider(&div_range[i], did); + /* Found a valid return divider*/ + if (div != INVALID_DIVIDER) + break; + } + return div; +} + +static int dce_divider_range_get_did( + struct dce_divider_range *div_range, + int ranges_num, + int divider) +{ + int did = INVALID_DID; + int i; + + for (i = 0; i < ranges_num; i++) { + /* CalcDid returns InvalidDid if a divider ID isn't found*/ + did = dce_divider_range_calc_did(&div_range[i], divider); + /* Found a valid return did*/ + if (did != INVALID_DID) + break; + } + return did; +} + +static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); int dprefclk_wdivider; @@ -85,7 +224,7 @@ static uint32_t dce_clocks_get_dp_ref_freq(struct display_clock *clk) REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ - target_div = dal_divider_range_get_divider( + target_div = dce_divider_range_get_divider( clk_dce->divider_ranges, DIVIDER_RANGE_MAX, dprefclk_wdivider); @@ -183,7 +322,7 @@ static bool dce_clock_set_min_clocks_state( static void dce_set_clock( struct display_clock *clk, - uint32_t requested_clk_khz) + int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_pixel_clock_parameters pxl_clk_params = { 0 }; @@ -245,7 +384,7 @@ static void dce_psr_wait_loop( static void dce_psr_set_clock( struct display_clock *clk, - uint32_t requested_clk_khz) + int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); @@ -253,9 +392,9 @@ static void dce_psr_set_clock( dce_psr_wait_loop(clk_dce, requested_clk_khz); } -static void polaris_set_clock( +static void dce112_set_clock( struct display_clock *clk, - uint32_t requested_clk_khz) + int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_set_dce_clock_parameters dce_clk_params; @@ -267,7 +406,7 @@ static void polaris_set_clock( /* Make sure requested clock isn't lower than minimum threshold*/ if (requested_clk_khz > 0) requested_clk_khz = dm_max(requested_clk_khz, - clk_dce->dentist_vco_freq_khz / 64); + clk_dce->dentist_vco_freq_khz / 62); dce_clk_params.target_clock_frequency = requested_clk_khz; dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; @@ -284,7 +423,9 @@ static void polaris_set_clock( /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ dce_clk_params.target_clock_frequency = 0; dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; - dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = 0; + dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = + (dce_clk_params.pll_id == + CLOCK_SOURCE_COMBO_DISPLAY_PLL0); bp->funcs->set_dce_clock(bp, &dce_clk_params); } @@ -386,7 +527,7 @@ static const struct display_clock_funcs dce112_funcs = { .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, .get_required_clocks_state = dce_get_required_clocks_state, .set_min_clocks_state = dce_clock_set_min_clocks_state, - .set_clock = polaris_set_clock + .set_clock = dce112_set_clock }; static const struct display_clock_funcs dce110_funcs = { @@ -429,19 +570,19 @@ static void dce_disp_clk_construct( dce_clock_read_integrated_info(clk_dce); dce_clock_read_ss_info(clk_dce); - dal_divider_range_construct( + dce_divider_range_construct( &clk_dce->divider_ranges[DIVIDER_RANGE_01], DIVIDER_RANGE_01_START, DIVIDER_RANGE_01_STEP_SIZE, DIVIDER_RANGE_01_BASE_DIVIDER_ID, DIVIDER_RANGE_02_BASE_DIVIDER_ID); - dal_divider_range_construct( + dce_divider_range_construct( &clk_dce->divider_ranges[DIVIDER_RANGE_02], DIVIDER_RANGE_02_START, DIVIDER_RANGE_02_STEP_SIZE, DIVIDER_RANGE_02_BASE_DIVIDER_ID, DIVIDER_RANGE_03_BASE_DIVIDER_ID); - dal_divider_range_construct( + dce_divider_range_construct( &clk_dce->divider_ranges[DIVIDER_RANGE_03], DIVIDER_RANGE_03_START, DIVIDER_RANGE_03_STEP_SIZE, @@ -462,6 +603,10 @@ struct display_clock *dce_disp_clk_create( return NULL; } + memcpy(clk_dce->max_clks_by_state, + dce80_max_clks_by_state, + sizeof(dce80_max_clks_by_state)); + dce_disp_clk_construct( clk_dce, ctx, regs, clk_shift, clk_mask); @@ -481,6 +626,10 @@ struct display_clock *dce110_disp_clk_create( return NULL; } + memcpy(clk_dce->max_clks_by_state, + dce110_max_clks_by_state, + sizeof(dce110_max_clks_by_state)); + dce_disp_clk_construct( clk_dce, ctx, regs, clk_shift, clk_mask); @@ -502,6 +651,10 @@ struct display_clock *dce112_disp_clk_create( return NULL; } + memcpy(clk_dce->max_clks_by_state, + dce112_max_clks_by_state, + sizeof(dce112_max_clks_by_state)); + dce_disp_clk_construct( clk_dce, ctx, regs, clk_shift, clk_mask); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index e3b23749f0a2..4ad6fe4c2841 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -27,12 +27,7 @@ #ifndef _DCE_CLOCKS_H_ #define _DCE_CLOCKS_H_ -#include "display_clock_interface.h" -#include "../gpu/divider_range.h" - - -#define TO_DCE_CLOCKS(clocks)\ - container_of(clocks, struct dce_disp_clk, base) +#include "display_clock.h" #define CLK_COMMON_REG_LIST_DCE_BASE() \ .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ @@ -74,13 +69,30 @@ struct dce_disp_clk_registers { }; /* Array identifiers and count for the divider ranges.*/ -enum divider_range_count { +enum dce_divider_range_count { DIVIDER_RANGE_01 = 0, DIVIDER_RANGE_02, DIVIDER_RANGE_03, DIVIDER_RANGE_MAX /* == 3*/ }; +enum dce_divider_error_types { + INVALID_DID = 0, + INVALID_DIVIDER = 1 +}; + +struct dce_divider_range { + int div_range_start; + /* The end of this range of dividers.*/ + int div_range_end; + /* The distance between each divider in this range.*/ + int div_range_step; + /* The divider id for the lowest divider.*/ + int did_min; + /* The divider id for the highest divider.*/ + int did_max; +}; + struct dce_disp_clk { struct display_clock base; const struct dce_disp_clk_registers *regs; @@ -88,23 +100,23 @@ struct dce_disp_clk { const struct dce_disp_clk_mask *clk_mask; struct state_dependent_clocks max_clks_by_state[DM_PP_CLOCKS_MAX_STATES]; - struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; + struct dce_divider_range divider_ranges[DIVIDER_RANGE_MAX]; bool use_max_disp_clk; - uint32_t dentist_vco_freq_khz; + int dentist_vco_freq_khz; /* Cache the status of DFS-bypass feature*/ bool dfs_bypass_enabled; /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - uint32_t dfs_bypass_disp_clk; + int dfs_bypass_disp_clk; /* Flag for Enabled SS on GPU PLL */ bool ss_on_gpu_pll; /* GPU PLL SS percentage (if down-spread enabled) */ - uint32_t gpu_pll_ss_percentage; + int gpu_pll_ss_percentage; /* GPU PLL SS percentage Divider (100 or 1000) */ - uint32_t gpu_pll_ss_divider; + int gpu_pll_ss_divider; }; diff --git a/drivers/gpu/drm/amd/display/dc/gpu/Makefile b/drivers/gpu/drm/amd/display/dc/gpu/Makefile deleted file mode 100644 index 6ab4078405f2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Makefile for the 'gpu' sub-component of DAL. -# It provides the control and status of HW adapter resources, -# that are global for the ASIC and sharable between pipes. - -GPU = divider_range.o - -AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) - -AMD_DISPLAY_FILES += $(AMD_DAL_GPU) - -############################################################################### -# DCE 110 family -############################################################################### - -GPU_DCE112 = display_clock_dce112.o - -AMD_DAL_GPU_DCE112 = $(addprefix $(AMDDALPATH)/dc/gpu/dce112/,$(GPU_DCE112)) - -AMD_DISPLAY_FILES += $(AMD_DAL_GPU_DCE110) $(AMD_DAL_GPU_DCE112) - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c deleted file mode 100644 index e0d67fb6c633..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -#include "include/bios_parser_interface.h" -#include "include/fixed32_32.h" -#include "include/logger_interface.h" - -#include "../divider_range.h" - -#include "display_clock_dce112.h" - -#define FROM_DISPLAY_CLOCK(base) \ - container_of(base, struct display_clock_dce112, disp_clk_base) - -static struct state_dependent_clocks max_clks_by_state[] = { -/*ClocksStateInvalid - should not be used*/ -{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, -/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ -{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 }, -/*ClocksStateLow*/ -{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 }, -/*ClocksStateNominal*/ -{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 }, -/*ClocksStatePerformance*/ -{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; - -/* Ranges for divider identifiers (Divider ID or DID) - mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ -enum divider_id_register_setting { - DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, - DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, - DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, - DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 -}; - -/* Step size between each divider within a range. - Incrementing the DENTIST_DISPCLK_WDIVIDER by one - will increment the divider by this much.*/ -enum divider_range_step_size { - DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ - DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ - DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ -}; - -static struct divider_range divider_ranges[DIVIDER_RANGE_MAX]; - - -void dispclk_dce112_destroy(struct display_clock **base) -{ - struct display_clock_dce112 *dc112; - - dc112 = DCLCK112_FROM_BASE(*base); - - dm_free(dc112); - - *base = NULL; -} - -static bool display_clock_integrated_info_construct( - struct display_clock_dce112 *disp_clk) -{ - struct integrated_info info; - uint32_t i; - struct display_clock *base = &disp_clk->disp_clk_base; - - memset(&info, 0, sizeof(struct integrated_info)); - - disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq; - if (disp_clk->dentist_vco_freq_khz == 0) - disp_clk->dentist_vco_freq_khz = 3600000; - - base->min_display_clk_threshold_khz = - disp_clk->dentist_vco_freq_khz / 64; - - /*update the maximum display clock for each power state*/ - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID; - - switch (i) { - case 0: - clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW; - break; - - case 1: - clk_state = DM_PP_CLOCKS_STATE_LOW; - break; - - case 2: - clk_state = DM_PP_CLOCKS_STATE_NOMINAL; - break; - - case 3: - clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE; - break; - - default: - clk_state = DM_PP_CLOCKS_STATE_INVALID; - break; - } - - /*Do not allow bad VBIOS/SBIOS to override with invalid values, - * check for > 100MHz*/ - if (info.disp_clk_voltage[i].max_supported_clk >= 100000) { - (disp_clk->max_clks_by_state + clk_state)-> - display_clk_khz = - info.disp_clk_voltage[i].max_supported_clk; - } - } - - return true; -} - -void dce112_set_clock( - struct display_clock *base, - uint32_t requested_clk_khz) -{ - struct bp_set_dce_clock_parameters dce_clk_params; - struct dc_bios *bp = base->ctx->dc_bios; - - /* Prepare to program display clock*/ - memset(&dce_clk_params, 0, sizeof(dce_clk_params)); - - /* Make sure requested clock isn't lower than minimum threshold*/ - if (requested_clk_khz > 0) - requested_clk_khz = dm_max(requested_clk_khz, - base->min_display_clk_threshold_khz); - - dce_clk_params.target_clock_frequency = requested_clk_khz; - dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; - - bp->funcs->set_dce_clock(bp, &dce_clk_params); - - /* from power down, we need mark the clock state as ClocksStateNominal - * from HWReset, so when resume we will call pplib voltage regulator.*/ - if (requested_clk_khz == 0) - base->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - /*Program DP ref Clock*/ - /*VBIOS will determine DPREFCLK frequency, so we don't set it*/ - dce_clk_params.target_clock_frequency = 0; - dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK; - dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = - (dce_clk_params.pll_id == - CLOCK_SOURCE_COMBO_DISPLAY_PLL0); - - bp->funcs->set_dce_clock(bp, &dce_clk_params); -} - -static const struct display_clock_funcs funcs = { - .destroy = dispclk_dce112_destroy, - .set_clock = dce112_set_clock, -}; - -bool dal_display_clock_dce112_construct( - struct display_clock_dce112 *dc112, - struct dc_context *ctx) -{ - struct display_clock *dc_base = &dc112->disp_clk_base; - - dc_base->ctx = ctx; - dc_base->min_display_clk_threshold_khz = 0; - - dc_base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; - - dc_base->funcs = &funcs; - - dc112->dfs_bypass_disp_clk = 0; - - if (!display_clock_integrated_info_construct(dc112)) - dm_logger_write(dc_base->ctx->logger, LOG_WARNING, - "Cannot obtain VBIOS integrated info\n"); - - dc112->gpu_pll_ss_percentage = 0; - dc112->gpu_pll_ss_divider = 1000; - dc112->ss_on_gpu_pll = false; - -/* Initially set max clocks state to nominal. This should be updated by - * via a pplib call to DAL IRI eventually calling a - * DisplayEngineClock_dce112::StoreMaxClocksState(). This call will come in - * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/ - dc_base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; - - dc112->disp_clk_base.min_display_clk_threshold_khz = - (dc112->dentist_vco_freq_khz / 62); - - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_01], - DIVIDER_RANGE_01_START, - DIVIDER_RANGE_01_STEP_SIZE, - DIVIDER_RANGE_01_BASE_DIVIDER_ID, - DIVIDER_RANGE_02_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_02], - DIVIDER_RANGE_02_START, - DIVIDER_RANGE_02_STEP_SIZE, - DIVIDER_RANGE_02_BASE_DIVIDER_ID, - DIVIDER_RANGE_03_BASE_DIVIDER_ID); - dal_divider_range_construct( - ÷r_ranges[DIVIDER_RANGE_03], - DIVIDER_RANGE_03_START, - DIVIDER_RANGE_03_STEP_SIZE, - DIVIDER_RANGE_03_BASE_DIVIDER_ID, - DIVIDER_RANGE_MAX_DIVIDER_ID); - - { - uint32_t ss_info_num = - ctx->dc_bios->funcs-> - get_ss_entry_number(ctx->dc_bios, AS_SIGNAL_TYPE_GPU_PLL); - - if (ss_info_num) { - struct spread_spectrum_info info; - bool result; - - memset(&info, 0, sizeof(info)); - - result = - (BP_RESULT_OK == ctx->dc_bios->funcs-> - get_spread_spectrum_info(ctx->dc_bios, - AS_SIGNAL_TYPE_GPU_PLL, 0, &info)) ? true : false; - - - /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS - * even if SS not enabled and in that case - * SSInfo.spreadSpectrumPercentage !=0 would be sign - * that SS is enabled - */ - if (result && info.spread_spectrum_percentage != 0) { - dc112->ss_on_gpu_pll = true; - dc112->gpu_pll_ss_divider = - info.spread_percentage_divider; - - if (info.type.CENTER_MODE == 0) { - /* Currently for DP Reference clock we - * need only SS percentage for - * downspread */ - dc112->gpu_pll_ss_percentage = - info.spread_spectrum_percentage; - } - } - - } - } - - dc112->use_max_disp_clk = true; - dc112->max_clks_by_state = max_clks_by_state; - - return true; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h b/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h deleted file mode 100644 index 0743c514a60f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/dce112/display_clock_dce112.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DAL_DISPLAY_CLOCK_DCE112_H__ -#define __DAL_DISPLAY_CLOCK_DCE112_H__ - -#include "display_clock_interface.h" - -struct display_clock_dce112 { - struct display_clock disp_clk_base; - bool use_max_disp_clk; - uint32_t dentist_vco_freq_khz; - /* Cache the status of DFS-bypass feature*/ - bool dfs_bypass_enabled; - /* GPU PLL SS percentage (if down-spread enabled) */ - uint32_t gpu_pll_ss_percentage; - /* GPU PLL SS percentage Divider (100 or 1000) */ - uint32_t gpu_pll_ss_divider; - /* Flag for Enabled SS on GPU PLL */ - bool ss_on_gpu_pll; - /* Cache the display clock returned by VBIOS if DFS-bypass is enabled. - * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ - uint32_t dfs_bypass_disp_clk; - struct state_dependent_clocks *max_clks_by_state; - -}; - -#define DCLCK112_FROM_BASE(dc_base) \ - container_of(dc_base, struct display_clock_dce112, disp_clk_base) - -/* Array identifiers and count for the divider ranges.*/ -enum divider_range_count { - DIVIDER_RANGE_01 = 0, - DIVIDER_RANGE_02, - DIVIDER_RANGE_03, - DIVIDER_RANGE_MAX /* == 3*/ -}; - -/* Starting point for each divider range.*/ -enum divider_range_start { - DIVIDER_RANGE_01_START = 200, /* 2.00*/ - DIVIDER_RANGE_02_START = 1600, /* 16.00*/ - DIVIDER_RANGE_03_START = 3200, /* 32.00*/ - DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ -}; - -bool dal_display_clock_dce112_construct( - struct display_clock_dce112 *dc112, - struct dc_context *ctx); - -void dispclk_dce112_destroy(struct display_clock **base); - -void dce112_set_clock( - struct display_clock *base, - uint32_t requested_clk_khz); - - -#endif /* __DAL_DISPLAY_CLOCK_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c deleted file mode 100644 index 59d44004411b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" -#include "divider_range.h" - -bool dal_divider_range_construct( - struct divider_range *div_range, - uint32_t range_start, - uint32_t range_step, - uint32_t did_min, - uint32_t did_max) -{ - div_range->div_range_start = range_start; - div_range->div_range_step = range_step; - div_range->did_min = did_min; - div_range->did_max = did_max; - - if (div_range->div_range_step == 0) { - div_range->div_range_step = 1; - /*div_range_step cannot be zero*/ - BREAK_TO_DEBUGGER(); - } - /* Calculate this based on the other inputs.*/ - /* See DividerRange.h for explanation of */ - /* the relationship between divider id (DID) and a divider.*/ - /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ - /* Maximum divider identified in this range = - * (Number of Divider IDs)*Step size between dividers - * + The start of this range.*/ - div_range->div_range_end = (did_max - did_min) * range_step - + range_start; - return true; -} - -static uint32_t dal_divider_range_calc_divider( - struct divider_range *div_range, - uint32_t did) -{ - /* Is this DID within our range?*/ - if ((did < div_range->did_min) || (did >= div_range->did_max)) - return INVALID_DIVIDER; - - return ((did - div_range->did_min) * div_range->div_range_step) - + div_range->div_range_start; - -} - -static uint32_t dal_divider_range_calc_did( - struct divider_range *div_range, - uint32_t div) -{ - uint32_t did; - /* Check before dividing.*/ - if (div_range->div_range_step == 0) { - div_range->div_range_step = 1; - /*div_range_step cannot be zero*/ - BREAK_TO_DEBUGGER(); - } - /* Is this divider within our range?*/ - if ((div < div_range->div_range_start) - || (div >= div_range->div_range_end)) - return INVALID_DID; -/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ - did = div - div_range->div_range_start; - did += div_range->div_range_step - 1; - did /= div_range->div_range_step; - did += div_range->did_min; - return did; -} - -uint32_t dal_divider_range_get_divider( - struct divider_range *div_range, - uint32_t ranges_num, - uint32_t did) -{ - uint32_t div = INVALID_DIVIDER; - uint32_t i; - - for (i = 0; i < ranges_num; i++) { - /* Calculate divider with given divider ID*/ - div = dal_divider_range_calc_divider(&div_range[i], did); - /* Found a valid return divider*/ - if (div != INVALID_DIVIDER) - break; - } - return div; -} -uint32_t dal_divider_range_get_did( - struct divider_range *div_range, - uint32_t ranges_num, - uint32_t divider) -{ - uint32_t did = INVALID_DID; - uint32_t i; - - for (i = 0; i < ranges_num; i++) { - /* CalcDid returns InvalidDid if a divider ID isn't found*/ - did = dal_divider_range_calc_did(&div_range[i], divider); - /* Found a valid return did*/ - if (did != INVALID_DID) - break; - } - return did; -} - diff --git a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h b/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h deleted file mode 100644 index e53522f652cc..000000000000 --- a/drivers/gpu/drm/amd/display/dc/gpu/divider_range.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_DIVIDER_RANGE_H__ -#define __DAL_DIVIDER_RANGE_H__ - -enum divider_error_types { - INVALID_DID = 0, - INVALID_DIVIDER = 1 -}; - -struct divider_range { - uint32_t div_range_start; - /* The end of this range of dividers.*/ - uint32_t div_range_end; - /* The distance between each divider in this range.*/ - uint32_t div_range_step; - /* The divider id for the lowest divider.*/ - uint32_t did_min; - /* The divider id for the highest divider.*/ - uint32_t did_max; -}; - -bool dal_divider_range_construct( - struct divider_range *div_range, - uint32_t range_start, - uint32_t range_step, - uint32_t did_min, - uint32_t did_max); - -uint32_t dal_divider_range_get_divider( - struct divider_range *div_range, - uint32_t ranges_num, - uint32_t did); -uint32_t dal_divider_range_get_did( - struct divider_range *div_range, - uint32_t ranges_num, - uint32_t divider); - -#endif /* __DAL_DIVIDER_RANGE_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index f2eb8945d5c4..0418e3e02c7a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -188,7 +188,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx); void core_link_disable_stream(struct pipe_ctx *pipe_ctx); /********** DAL Core*********************/ -#include "display_clock_interface.h" +#include "display_clock.h" #include "transform.h" struct resource_pool; diff --git a/drivers/gpu/drm/amd/display/include/display_clock_interface.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h similarity index 75% rename from drivers/gpu/drm/amd/display/include/display_clock_interface.h rename to drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 53a01381c638..e163f5818dd9 100644 --- a/drivers/gpu/drm/amd/display/include/display_clock_interface.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -1,5 +1,5 @@ /* - * Copyright 2012-15 Advanced Micro Devices, Inc. + * Copyright 2012-16 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,44 +23,39 @@ * */ -#ifndef __DISPLAY_CLOCK_INTERFACE_H__ -#define __DISPLAY_CLOCK_INTERFACE_H__ +#ifndef __DISPLAY_CLOCK_H__ +#define __DISPLAY_CLOCK_H__ #include "dm_services_types.h" -#include "hw_sequencer_types.h" -#include "grph_object_defs.h" -#include "signal_types.h" /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ struct state_dependent_clocks { - uint32_t display_clk_khz; - uint32_t pixel_clk_khz; + int display_clk_khz; + int pixel_clk_khz; }; struct display_clock { struct dc_context *ctx; const struct display_clock_funcs *funcs; - int min_display_clk_threshold_khz; enum dm_pp_clocks_state max_clks_state; enum dm_pp_clocks_state cur_min_clks_state; }; struct display_clock_funcs { - void (*destroy)(struct display_clock **to_destroy); void (*set_clock)(struct display_clock *disp_clk, - uint32_t requested_clock_khz); + int requested_clock_khz); + enum dm_pp_clocks_state (*get_required_clocks_state)( struct display_clock *disp_clk, struct state_dependent_clocks *req_clocks); + bool (*set_min_clocks_state)(struct display_clock *disp_clk, enum dm_pp_clocks_state dm_pp_clocks_state); - uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); -}; - -void dal_display_clock_destroy(struct display_clock **to_destroy); + int (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); +}; -#endif /* __DISPLAY_CLOCK_INTERFACE_H__ */ +#endif /* __DISPLAY_CLOCK_H__ */ -- GitLab From 49c07a99b2bdd6e6ed621f728d58d8535cc87a61 Mon Sep 17 00:00:00 2001 From: Arindam Nath Date: Mon, 5 Dec 2016 19:21:26 +0530 Subject: [PATCH 0089/2898] drm/amd/display: remove DM_NOT_IMPL messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some functions like dm_bandwidth_update are placeholders for future implementations. Right now, they simply print messages like "DM_NOT_IMPL: dm_bandwidth_update". This message even though informational, sometimes can create some confusion for users. Since these functions are only skeletons for future, we simply remove the rather un-unecessary messages from these functions. Signed-off-by: Arindam Nath Reviewed-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index fa55147d0c47..396dbd661183 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -48,10 +48,6 @@ #include "modules/inc/mod_freesync.h" -/* Debug facilities */ -#define AMDGPU_DM_NOT_IMPL(fmt, ...) \ - DRM_INFO("DM_NOT_IMPL: " fmt, ##__VA_ARGS__) - /* * dm_vblank_get_counter * @@ -1269,20 +1265,18 @@ void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) */ static void dm_bandwidth_update(struct amdgpu_device *adev) { - AMDGPU_DM_NOT_IMPL("%s\n", __func__); + /* TODO: implement later */ } static void dm_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder, u8 level) { /* TODO: translate amdgpu_encoder to display_index and call DAL */ - AMDGPU_DM_NOT_IMPL("%s\n", __func__); } static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder) { /* TODO: translate amdgpu_encoder to display_index and call DAL */ - AMDGPU_DM_NOT_IMPL("%s\n", __func__); return 0; } -- GitLab From a33fa99d8b8ec71a69e089e39ab1498d31169640 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 6 Dec 2016 11:26:08 -0500 Subject: [PATCH 0090/2898] drm/amd/display: Fix bunch of warnings in DC Some of those are potential bugs Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/calcs/bandwidth_calcs.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 5 +-- .../drm/amd/display/dc/dce/dce_clock_source.c | 5 --- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 41 ------------------- .../drm/amd/display/dc/dce/dce_transform.c | 2 - .../display/dc/dce110/dce110_transform_v.c | 3 +- 6 files changed, 5 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index 0b2bb3992f1a..3b0710ef4716 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -1709,7 +1709,7 @@ static void calculate_bandwidth( else { data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])); if (bw_ltn(data->adjusted_data_buffer_size[k], bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), (bw_add(vbios->blackout_duration, bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])))))) { - data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[i][j]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); + data->blackout_recovery_time = bw_max2(data->blackout_recovery_time, bw_div((bw_add(bw_mul(bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]), vbios->blackout_duration), bw_sub(bw_div(bw_mul(bw_mul(bw_mul((bw_add(bw_add(bw_mul(bw_int_to_fixed(2), vbios->mcifwrmc_urgent_latency), data->dmif_burst_time[data->y_clk_level][data->sclk_level]), data->mcifwr_burst_time[data->y_clk_level][data->sclk_level])), data->dispclk), bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), data->adjusted_data_buffer_size[k]))), (bw_sub(bw_div(bw_mul(bw_mul(data->dispclk, bw_int_to_fixed(data->bytes_per_pixel[k])), data->lines_interleaved_in_mem_access[k]), data->latency_hiding_lines[k]), bw_div(bw_mul(data->display_bandwidth[k], data->useful_bytes_per_request[k]), data->bytes_per_request[k]))))); } } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index bd53d27e5414..f552b0468186 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1834,11 +1834,10 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_vendor_info_packet( pipe_ctx->stream, &info_frame.vendor_info_packet); set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); - } - - else if (dc_is_dp_signal(signal)) + } else if (dc_is_dp_signal(signal)) { set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + } translate_info_frame(&info_frame, &pipe_ctx->encoder_info_frame); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 80ac5d9efa71..3d1c32122d69 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -465,7 +465,6 @@ static uint32_t dce110_get_pix_clk_dividers_helper ( struct pll_settings *pll_settings, struct pixel_clk_params *pix_clk_params) { - uint32_t addr = 0; uint32_t value = 0; uint32_t field = 0; uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; @@ -731,8 +730,6 @@ static void dce110_program_pixel_clk_resync( enum signal_type signal_type, enum dc_color_depth colordepth) { - uint32_t value = 0; - REG_UPDATE(RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, 0); /* @@ -772,8 +769,6 @@ static void dce112_program_pixel_clk_resync( enum dc_color_depth colordepth, bool enable_ycbcr420) { - uint32_t value = 0; - REG_UPDATE(PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 8e2519b1c9df..262612061c68 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -148,29 +148,6 @@ static int dce_divider_range_calc_divider( } -static int dce_divider_range_calc_did( - struct dce_divider_range *div_range, - int div) -{ - int did; - /* Check before dividing.*/ - if (div_range->div_range_step == 0) { - div_range->div_range_step = 1; - /*div_range_step cannot be zero*/ - BREAK_TO_DEBUGGER(); - } - /* Is this divider within our range?*/ - if ((div < div_range->div_range_start) - || (div >= div_range->div_range_end)) - return INVALID_DID; -/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/ - did = div - div_range->div_range_start; - did += div_range->div_range_step - 1; - did /= div_range->div_range_step; - did += div_range->did_min; - return did; -} - static int dce_divider_range_get_divider( struct dce_divider_range *div_range, int ranges_num, @@ -189,24 +166,6 @@ static int dce_divider_range_get_divider( return div; } -static int dce_divider_range_get_did( - struct dce_divider_range *div_range, - int ranges_num, - int divider) -{ - int did = INVALID_DID; - int i; - - for (i = 0; i < ranges_num; i++) { - /* CalcDid returns InvalidDid if a divider ID isn't found*/ - did = dce_divider_range_calc_did(&div_range[i], divider); - /* Found a valid return did*/ - if (did != INVALID_DID) - break; - } - return did; -} - static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index f47b6617f662..bbf4d97cb980 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -83,8 +83,6 @@ static bool setup_scaling_configuration( struct dce_transform *xfm_dce, const struct scaler_data *data) { - struct dc_context *ctx = xfm_dce->base.ctx; - if (data->taps.h_taps + data->taps.v_taps <= 2) { /* Set bypass */ REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index 7d8cf7a58f46..feb5f3c29804 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -621,7 +621,8 @@ static void dce110_xfmv_set_pixel_storage_depth( const struct bit_depth_reduction_params *bit_depth_params) { struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); - int pixel_depth, expan_mode; + int pixel_depth = 0; + int expan_mode = 0; uint32_t reg_data = 0; switch (depth) { -- GitLab From eaf9094475504effe1a798199a1a118299cf0f74 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 6 Dec 2016 12:01:23 -0500 Subject: [PATCH 0091/2898] drm/amd/display: Fix warning in freesync module Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index eb912baa0169..8892e8bec7c3 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -746,6 +746,9 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, freesync_program_required = true; } break; + case FREESYNC_STATE_NONE: + /* handle here to avoid warning */ + break; } } -- GitLab From 091a97e542cf9a9af6e48aa1324044433ea7341a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 6 Dec 2016 12:25:52 -0500 Subject: [PATCH 0092/2898] drm/amd/display: Fix warning. Set MAX_SURFACES to 3 Currently we never use more than 2 surfaces in all use cases. This avoids pushing dc_commit_surfaces_to_target beyond a stacksize of 1024. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5575484323b3..e1f2434ee95e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -34,7 +34,7 @@ #include "link_service_types.h" #define MAX_TARGETS 6 -#define MAX_SURFACES 6 +#define MAX_SURFACES 3 #define MAX_SINKS_PER_LINK 4 /******************************************************************************* -- GitLab From edbd58af6998217c5c1ab91cb6ca239c607cc9e0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 6 Dec 2016 22:12:09 -0500 Subject: [PATCH 0093/2898] drm/amd/display: fix indexing bug - is_new_pipe_surface should be addressed with pipe idx, not surface idx Signed-off-by: Tony Cheng Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a3c5def507a9..70b7673993b2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1334,7 +1334,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context = core_dc->temp_flip_context; int i, j; - bool is_new_pipe_surface[MAX_SURFACES]; + bool is_new_pipe_surface[MAX_PIPES]; const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; update_surface_trace(dc, updates, surface_count); @@ -1353,7 +1353,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda &context->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; } - for (j = 0; j < MAX_SURFACES; j++) + for (j = 0; j < MAX_PIPES; j++) is_new_pipe_surface[j] = true; for (i = 0 ; i < surface_count; i++) { @@ -1364,7 +1364,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (surface == pipe_ctx->surface) - is_new_pipe_surface[i] = false; + is_new_pipe_surface[j] = false; } } -- GitLab From f4c07f88cc30e77d2431b5bcf95a05e0ee6f3482 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 6 Dec 2016 21:22:17 -0500 Subject: [PATCH 0094/2898] drm/amd/display: avoid apply_clk_constraints for address update - dc_update_surfaces_for_target get called in ISR but apply_clk_constraints allocates memory Signed-off-by: Tony Cheng Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 70b7673993b2..522ef7047564 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1336,6 +1336,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda int i, j; bool is_new_pipe_surface[MAX_PIPES]; const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + bool need_apply_clk_constraints = false; update_surface_trace(dc, updates, surface_count); @@ -1405,6 +1406,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].plane_info || updates[i].scaling_info || is_new_pipe_surface[j]) { + need_apply_clk_constraints = true; if (updates[i].plane_info) { surface->public.color_space = -- GitLab From 922aa1e15e03ee2b32f50cd8a9d2c8376a19d22c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 7 Dec 2016 14:10:05 -0500 Subject: [PATCH 0095/2898] drm/amd/display: Fix refcount over dc_sink. Retain a dc_sink pointer until a new physical pointer arrives in case of new display connected. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 396dbd661183..e5ba23253814 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -737,9 +737,17 @@ void amdgpu_dm_update_connector_after_detect( mutex_lock(&dev->mode_config.mutex); if (sink) { - if (aconnector->dc_sink) + if (aconnector->dc_sink) { amdgpu_dm_remove_sink_from_freesync_module( connector); + /* retain and release bellow are used for + * bump up refcount for sink because the link don't point + * to it anymore after disconnect so on next crtc to connector + * reshuffle by UMD we will get into unwanted dc_sink release + */ + if (aconnector->dc_sink != aconnector->dc_em_sink) + dc_sink_release(aconnector->dc_sink); + } aconnector->dc_sink = sink; amdgpu_dm_add_sink_to_freesync_module( connector, aconnector->edid); @@ -747,6 +755,8 @@ void amdgpu_dm_update_connector_after_detect( amdgpu_dm_remove_sink_from_freesync_module(connector); if (!aconnector->dc_sink) aconnector->dc_sink = aconnector->dc_em_sink; + else if (aconnector->dc_sink != aconnector->dc_em_sink) + dc_sink_retain(aconnector->dc_sink); } mutex_unlock(&dev->mode_config.mutex); -- GitLab From 5ea81b91857882bb5bfa883fb27671133957a96c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 5 Dec 2016 18:03:04 -0500 Subject: [PATCH 0096/2898] drm/amd/display: fix up construction of scratch_val_ctx Signed-off-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++++++------ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 522ef7047564..8e1d695fcb77 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -450,11 +450,6 @@ static void destruct(struct core_dc *dc) { resource_validate_ctx_destruct(dc->current_context); - dm_free(dc->temp_flip_context); - dc->temp_flip_context = NULL; - dm_free(dc->scratch_val_ctx); - dc->scratch_val_ctx = NULL; - destroy_links(dc); dc_destroy_resource_pool(dc); @@ -473,6 +468,10 @@ static void destruct(struct core_dc *dc) dm_free(dc->current_context); dc->current_context = NULL; + dm_free(dc->temp_flip_context); + dc->temp_flip_context = NULL; + dm_free(dc->scratch_val_ctx); + dc->scratch_val_ctx = NULL; dm_free(dc->ctx); dc->ctx = NULL; @@ -492,7 +491,7 @@ static bool construct(struct core_dc *dc, dc->current_context = dm_alloc(sizeof(*dc->current_context)); dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); - dc->scratch_val_ctx = dm_alloc(sizeof(*dc->temp_flip_context)); + dc->scratch_val_ctx = dm_alloc(sizeof(*dc->scratch_val_ctx)); if (!dc->current_context || !dc->temp_flip_context) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -1220,6 +1219,7 @@ bool dc_pre_update_surfaces_to_target( goto unexpected_fail; } resource_validate_ctx_destruct(context); + ASSERT(core_dc->scratch_val_ctx == temp_context); core_dc->scratch_val_ctx = context; context = temp_context; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 0418e3e02c7a..3cf9bfb6decd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -312,7 +312,7 @@ struct validate_context { /* The output from BW and WM calculations. */ struct bw_calcs_output bw_results; - /* Note: this is a big structure, do *not* put on stack! */ + /* Note: these are big structures, do *not* put on stack! */ struct dm_pp_display_configuration pp_display_cfg; }; -- GitLab From 9474980ac470a20d244318db9a7c12be01437805 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 8 Dec 2016 09:47:11 -0500 Subject: [PATCH 0097/2898] drm/amd/display: Added timing sync trace. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++- .../gpu/drm/amd/display/dc/core/dc_debug.c | 32 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../display/dc/dce110/dce110_hw_sequencer.c | 1 - .../amd/display/include/logger_interface.h | 5 +++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8e1d695fcb77..de99d71f9042 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1488,8 +1488,10 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda core_dc->hwss.prepare_pipe_for_context( core_dc, pipe_ctx, context); } - if (apply_ctx) + if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + context_timing_trace(dc, &context->res_ctx); + } } for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 8ca0f1e0369a..78b8e0c5b4e7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -22,6 +22,13 @@ ##__VA_ARGS__); \ } while (0) +#define TIMING_TRACE(...) do {\ + if (dc->debug.timing_trace) \ + dm_logger_write(logger, \ + LOG_SYNC, \ + ##__VA_ARGS__); \ +} while (0) + void pre_surface_trace( const struct dc *dc, const struct dc_surface *const *surfaces, @@ -268,3 +275,28 @@ void post_surface_trace(const struct dc *dc) SURFACE_TRACE("post surface process.\n"); } + +void context_timing_trace( + const struct dc *dc, + struct resource_context *res_ctx) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + int h_pos = 0; + int v_pos = 0; + + if (pipe_ctx->stream == NULL) + continue; + + pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos, &v_pos); + TIMING_TRACE("Pipe_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", + pipe_ctx->pipe_idx, + pipe_ctx->stream->public.timing.h_total, + pipe_ctx->stream->public.timing.v_total, + h_pos, v_pos); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e1f2434ee95e..bb7cdde3e37b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -140,6 +140,7 @@ struct dc_debug { bool max_disp_clk; bool target_trace; bool surface_trace; + bool timing_trace; bool validation_trace; bool disable_stutter; bool disable_dcc; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6ad23f327631..99937facf645 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1892,7 +1892,6 @@ static void dce110_apply_ctx_for_surface( program_blender(dc, pipe_ctx); } - } static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index b58d30de8293..08a6911d3a3a 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -31,6 +31,7 @@ struct dc_context; struct dc_link; struct dc_surface_update; +struct resource_context; /* * @@ -85,6 +86,10 @@ void update_surface_trace( void post_surface_trace(const struct dc *dc); +void context_timing_trace( + const struct dc *dc, + struct resource_context *res_ctx); + /* Any function which is empty or have incomplete implementation should be * marked by this macro. -- GitLab From 89e8963036085e4e0e9a993d2e1bdbb931d53794 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Mon, 12 Dec 2016 10:32:24 -0500 Subject: [PATCH 0098/2898] drm/amd/display: Fix Gamma Adjustment - Gamma correction is not properly copied to the surface after refactor - Make sure gamma correction is copied with correct retain Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 ++++++++++++-- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 3 ++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index de99d71f9042..41df500817ad 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1302,8 +1302,8 @@ bool dc_commit_surfaces_to_target( for (i = 0; i < new_surface_count; i++) { updates[i].surface = new_surfaces[i]; - updates[i].gamma = (struct dc_gamma *)new_surfaces[i]->gamma_correction; - + updates[i].gamma = + (struct dc_gamma *)new_surfaces[i]->gamma_correction; flip_addr[i].address = new_surfaces[i]->address; flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; plane_info[i].color_space = new_surfaces[i]->color_space; @@ -1444,6 +1444,16 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda pipe_ctx->scl_data.recout.width -= 2; } } + + if (updates[i].gamma) { + if (surface->public.gamma_correction != NULL) + dc_gamma_release(surface->public. + gamma_correction); + + dc_gamma_retain(updates[i].gamma); + surface->public.gamma_correction = + updates[i].gamma; + } } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index b89d3b5d0ba0..06d8b326714a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -64,7 +64,8 @@ static bool construct(struct dc_context *ctx, struct surface *surface) static void destruct(struct surface *surface) { - + if (surface->protected.public.gamma_correction != NULL) + dc_gamma_release(surface->protected.public.gamma_correction); } /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bb7cdde3e37b..7733292d42f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -312,6 +312,7 @@ const struct dc_surface_status *dc_surface_get_status( void dc_surface_retain(const struct dc_surface *dc_surface); void dc_surface_release(const struct dc_surface *dc_surface); +void dc_gamma_retain(const struct dc_gamma *dc_gamma); void dc_gamma_release(const struct dc_gamma *dc_gamma); struct dc_gamma *dc_create_gamma(void); -- GitLab From 98d2cc2b03d937af36ce5ef227ae57232bbe8471 Mon Sep 17 00:00:00 2001 From: Andrew Wong Date: Mon, 12 Dec 2016 11:17:06 -0500 Subject: [PATCH 0099/2898] drm/amd/display: Change locking of registers when flipping frames. - Introduce GRPH_UPDATE_LOCK around programming surface flip. - Remove the now unused graphic surface lock. - Add macros to get and set four registers - both immediate and H Retrace should not be enabled at the same time Signed-off-by: Andrew Wong Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 +-------- drivers/gpu/drm/amd/display/dc/dc_helper.c | 14 ++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 11 +++-------- .../amd/display/dc/dce110/dce110_mem_input.c | 17 +++++++++++++++-- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 +-- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 13 +++++++++++++ 6 files changed, 47 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 41df500817ad..75b6e404d016 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1468,11 +1468,6 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda continue; if (updates[i].flip_addr) { - core_dc->hwss.pipe_control_lock( - core_dc->hwseq, - pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_SURFACE, - true); core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); } @@ -1485,7 +1480,6 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda core_dc->hwss.pipe_control_lock( core_dc->hwseq, pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_SURFACE | PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | PIPE_LOCK_CONTROL_BLENDER | @@ -1515,8 +1509,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda pipe_ctx->pipe_idx, PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | - PIPE_LOCK_CONTROL_BLENDER | - PIPE_LOCK_CONTROL_SURFACE, + PIPE_LOCK_CONTROL_BLENDER, false); } break; diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index c5ff7b6d733d..a950dd53bca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -65,6 +65,20 @@ uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, return reg_val; } +uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3, + uint8_t shift4, uint32_t mask4, uint32_t *field_value4) +{ + uint32_t reg_val = dm_read_reg(ctx, addr); + *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); + *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); + *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); + *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); + return reg_val; +} + uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, uint8_t shift1, uint32_t mask1, uint32_t *field_value1, uint8_t shift2, uint32_t mask2, uint32_t *field_value2, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index dd1cf5e6e949..cd9a371ae237 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -49,12 +49,11 @@ void dce_pipe_control_lock(struct dce_hwseq *hws, bool lock) { uint32_t lock_val = lock ? 1 : 0; - uint32_t dcp_grph, scl, dcp_grph_surf, blnd, update_lock_mode; + uint32_t dcp_grph, scl, blnd, update_lock_mode; - uint32_t val = REG_GET_5(BLND_V_UPDATE_LOCK[blnd_inst], + uint32_t val = REG_GET_4(BLND_V_UPDATE_LOCK[blnd_inst], BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, BLND_SCL_V_UPDATE_LOCK, &scl, - BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, &dcp_grph_surf, BLND_BLND_V_UPDATE_LOCK, &blnd, BLND_V_UPDATE_LOCK_MODE, &update_lock_mode); @@ -64,19 +63,15 @@ void dce_pipe_control_lock(struct dce_hwseq *hws, if (control_mask & PIPE_LOCK_CONTROL_SCL) scl = lock_val; - if (control_mask & PIPE_LOCK_CONTROL_SURFACE) - dcp_grph_surf = lock_val; - if (control_mask & PIPE_LOCK_CONTROL_BLENDER) blnd = lock_val; if (control_mask & PIPE_LOCK_CONTROL_MODE) update_lock_mode = lock_val; - REG_SET_5(BLND_V_UPDATE_LOCK[blnd_inst], val, + REG_SET_4(BLND_V_UPDATE_LOCK[blnd_inst], val, BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, BLND_SCL_V_UPDATE_LOCK, scl, - BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, dcp_grph_surf, BLND_BLND_V_UPDATE_LOCK, blnd, BLND_V_UPDATE_LOCK_MODE, update_lock_mode); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index af9d682f8943..a20feaedfca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -113,16 +113,25 @@ bool dce110_mem_input_program_surface_flip_and_addr( struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); uint32_t value = 0; + uint32_t value_old = 0; + uint32_t lock_value = 0; + + lock_value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); + set_reg_field_value(lock_value, 1, GRPH_UPDATE, GRPH_UPDATE_LOCK); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE), lock_value); value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL)); + value_old = value; if (flip_immediate) { - set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); + set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); } else { set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); } - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value); + if (value != value_old) { + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value); + } switch (address->type) { case PLN_ADDR_TYPE_GRAPHICS: @@ -147,6 +156,10 @@ bool dce110_mem_input_program_surface_flip_and_addr( if (flip_immediate) mem_input->current_address = *address; + lock_value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); + set_reg_field_value(lock_value, 0, GRPH_UPDATE, GRPH_UPDATE_LOCK); + dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE), lock_value); + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 50d499cc01a4..fcaf2c71e4eb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -40,8 +40,7 @@ enum pipe_lock_control { PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, PIPE_LOCK_CONTROL_BLENDER = 1 << 1, PIPE_LOCK_CONTROL_SCL = 1 << 2, - PIPE_LOCK_CONTROL_SURFACE = 1 << 3, - PIPE_LOCK_CONTROL_MODE = 1 << 4 + PIPE_LOCK_CONTROL_MODE = 1 << 3 }; struct dce_hwseq; diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index dbc8424f7b69..a07817472089 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -143,6 +143,13 @@ FN(reg_name, f2), v2, \ FN(reg_name, f3), v3) +#define REG_GET_4(reg_name, f1, v1, f2, v2, f3, v3, f4, v4) \ + generic_reg_get4(CTX, REG(reg_name), \ + FN(reg_name, f1), v1, \ + FN(reg_name, f2), v2, \ + FN(reg_name, f3), v3, \ + FN(reg_name, f4), v4) + #define REG_GET_5(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \ generic_reg_get5(CTX, REG(reg_name), \ FN(reg_name, f1), v1, \ @@ -280,6 +287,12 @@ uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, uint8_t shift2, uint32_t mask2, uint32_t *field_value2, uint8_t shift3, uint32_t mask3, uint32_t *field_value3); +uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + uint8_t shift2, uint32_t mask2, uint32_t *field_value2, + uint8_t shift3, uint32_t mask3, uint32_t *field_value3, + uint8_t shift4, uint32_t mask4, uint32_t *field_value4); + uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, uint8_t shift1, uint32_t mask1, uint32_t *field_value1, uint8_t shift2, uint32_t mask2, uint32_t *field_value2, -- GitLab From 4b5752c7422f36664cea2ed300b698b4755b6dc5 Mon Sep 17 00:00:00 2001 From: Andrew Wong Date: Mon, 12 Dec 2016 11:47:47 -0500 Subject: [PATCH 0100/2898] drm/amd/display: Retrieve windowed fullscreen state - Retrieve windowed fullscreen state when getting freesync params. Signed-off-by: Andrew Wong Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 8892e8bec7c3..6f4d169f4e4e 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -784,6 +784,9 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, freesync_params->update_duration_in_ns = core_freesync->map[index].state.time.update_duration_in_ns; + freesync_params->windowed_fullscreen = + core_freesync->map[index].state.windowed_fullscreen; + return true; } -- GitLab From 30018e9fa27506933f232aaacfc0145ccb094272 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 12 Dec 2016 13:54:56 -0500 Subject: [PATCH 0101/2898] drm/amd/display: Fix HDMI scaling corruption issue. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 5 +++++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index bbf4d97cb980..50a6a25561b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -83,6 +83,8 @@ static bool setup_scaling_configuration( struct dce_transform *xfm_dce, const struct scaler_data *data) { + REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0); + if (data->taps.h_taps + data->taps.v_taps <= 2) { /* Set bypass */ REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); @@ -285,6 +287,9 @@ static void dce_transform_set_scaler( LB_MEMORY_CONFIG, 0, LB_MEMORY_SIZE, xfm_dce->lb_memory_size); + /* Clear SCL_F_SHARP_CONTROL value to 0 */ + REG_WRITE(SCL_F_SHARP_CONTROL, 0); + /* 1. Program overscan */ program_overscan(xfm_dce, data); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index 897645e2889f..b2cf9bfb0094 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -53,6 +53,7 @@ SRI(SCL_MODE, SCL, id), \ SRI(SCL_TAP_CONTROL, SCL, id), \ SRI(SCL_CONTROL, SCL, id), \ + SRI(SCL_BYPASS_CONTROL, SCL, id), \ SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \ SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \ SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \ @@ -67,7 +68,8 @@ SRI(SCL_VERT_FILTER_INIT, SCL, id), \ SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \ SRI(LB_MEMORY_CTRL, LB, id), \ - SRI(SCL_UPDATE, SCL, id) + SRI(SCL_UPDATE, SCL, id), \ + SRI(SCL_F_SHARP_CONTROL, SCL, id) #define XFM_COMMON_REG_LIST_DCE100(id) \ XFM_COMMON_REG_LIST_DCE_BASE(id), \ @@ -116,6 +118,7 @@ XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \ + XFM_SF(SCL_BYPASS_CONTROL, SCL_BYPASS_MODE, mask_sh), \ XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \ XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \ XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \ @@ -181,6 +184,7 @@ type GAMUT_REMAP_C34; \ type GRPH_GAMUT_REMAP_MODE; \ type SCL_MODE; \ + type SCL_BYPASS_MODE; \ type SCL_PSCL_EN; \ type SCL_H_NUM_OF_TAPS; \ type SCL_V_NUM_OF_TAPS; \ @@ -241,6 +245,7 @@ struct dce_transform_registers { uint32_t SCL_MODE; uint32_t SCL_TAP_CONTROL; uint32_t SCL_CONTROL; + uint32_t SCL_BYPASS_CONTROL; uint32_t EXT_OVERSCAN_LEFT_RIGHT; uint32_t EXT_OVERSCAN_TOP_BOTTOM; uint32_t SCL_VERT_FILTER_CONTROL; @@ -258,6 +263,7 @@ struct dce_transform_registers { uint32_t SCL_AUTOMATIC_MODE_CONTROL; uint32_t LB_MEMORY_CTRL; uint32_t SCL_UPDATE; + uint32_t SCL_F_SHARP_CONTROL; }; struct init_int_and_frac { -- GitLab From 1e3d346f4fbb48f0a89134f4b834d3be2df3cc25 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Tue, 13 Dec 2016 14:23:16 -0600 Subject: [PATCH 0102/2898] drm/amd/display: re gamma programming Fix gamma update logic to avoid crash Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 75b6e404d016..9a35e3bb8283 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1445,7 +1445,8 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } - if (updates[i].gamma) { + if (updates[i].gamma && updates[i].gamma != + surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) dc_gamma_release(surface->public. gamma_correction); -- GitLab From 88499197de090c9bb391cc11bf9410b9f020092f Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 12 Dec 2016 14:20:45 -0500 Subject: [PATCH 0103/2898] drm/amd/display: Moved swizzle parameter translation to dc. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/conversion.c | 9 +++++++++ drivers/gpu/drm/amd/display/dc/basics/conversion.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 11 +---------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index ebe14e17cc2e..5682fea2080d 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -221,3 +221,12 @@ void calculate_adjustments_y_only( adjustments->brightness); } +unsigned int log_2(unsigned int num) +{ + unsigned int result = 0; + + while ((num >>= 1) != 0) + result++; + + return result; +} diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h index 18cbe41e80ff..b7fe431a7952 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.h +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -48,4 +48,6 @@ void calculate_adjustments_y_only( const struct dc_csc_adjustments *adjustments, struct fixed31_32 *matrix); +unsigned int log_2(unsigned int num); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index fd8a49afbec6..e9005e0048e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -25,6 +25,7 @@ #include "mem_input.h" #include "reg_helper.h" +#include "basics/conversion.h" #define CTX \ mi->ctx @@ -129,16 +130,6 @@ static bool is_vert_scan(enum dc_rotation_angle rotation) } } -static unsigned int log_2(unsigned int num) -{ - unsigned int result = 0; - - while ((num >>= 1) != 0) - result++; - - return result; -} - void dce_mem_input_program_pte_vm(struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, -- GitLab From fb735a9f29f94fcb29fee224b8da704a510a5a3a Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 13 Dec 2016 13:59:41 -0500 Subject: [PATCH 0104/2898] drm/amd/display: Add in/out transfer functions to DC Refactor part 1 of degamma/regamma programming. End goal is to have source and output transfer function in which dc can use to decide how to program the degamma and regamma HW. Gamma will be explicitly applied through dc_update_surfaces_for_target. Color module should build the logical curve with all adjustments applied and pass enough information for dc to program HW PWL. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 38 +++++++++-- .../gpu/drm/amd/display/dc/core/dc_surface.c | 64 +++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 40 +++++++++++- .../display/dc/dce110/dce110_hw_sequencer.c | 36 +++-------- .../gpu/drm/amd/display/dc/inc/core_types.h | 5 ++ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- 6 files changed, 135 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9a35e3bb8283..f20701a507da 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1455,6 +1455,34 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda surface->public.gamma_correction = updates[i].gamma; } + + if (updates[i].in_transfer_func && + updates[i].in_transfer_func != + surface->public.in_transfer_func) { + if (surface->public.in_transfer_func != NULL) + dc_transfer_func_release( + surface->public. + in_transfer_func); + + dc_transfer_func_retain( + updates[i].in_transfer_func); + surface->public.in_transfer_func = + updates[i].in_transfer_func; + } + + if (updates[i].out_transfer_func && + updates[i].out_transfer_func != + surface->public.out_transfer_func) { + if (surface->public.out_transfer_func != NULL) + dc_transfer_func_release( + surface->public. + out_transfer_func); + + dc_transfer_func_retain( + updates[i].out_transfer_func); + surface->public.out_transfer_func = + updates[i].out_transfer_func; + } } } @@ -1474,7 +1502,6 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].plane_info || updates[i].scaling_info || is_new_pipe_surface[j]) { - apply_ctx = true; if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { @@ -1489,9 +1516,12 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } - if (updates[i].gamma) - core_dc->hwss.prepare_pipe_for_context( - core_dc, pipe_ctx, context); + if (is_new_pipe_surface[j] || + updates[i].gamma || + updates[i].in_transfer_func || + updates[i].out_transfer_func) + core_dc->hwss.set_gamma_correction( + pipe_ctx, pipe_ctx->surface); } if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 06d8b326714a..8d2668406f3a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -45,11 +45,18 @@ struct gamma { int ref_count; }; +struct transfer_func { + struct core_transfer_func protected; + int ref_count; +}; + #define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) #define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) #define DC_GAMMA_TO_GAMMA(dc_gamma) \ container_of(dc_gamma, struct gamma, protected.public) +#define DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf) \ + container_of(dc_tf, struct transfer_func, protected.public) #define CORE_GAMMA_TO_GAMMA(core_gamma) \ container_of(core_gamma, struct gamma, protected) @@ -66,6 +73,12 @@ static void destruct(struct surface *surface) { if (surface->protected.public.gamma_correction != NULL) dc_gamma_release(surface->protected.public.gamma_correction); + if (surface->protected.public.in_transfer_func != NULL) + dc_transfer_func_release( + surface->protected.public.in_transfer_func); + if (surface->protected.public.out_transfer_func != NULL) + dc_transfer_func_release( + surface->protected.public.out_transfer_func); } /******************************************************************************* @@ -163,16 +176,6 @@ void dc_surface_release(const struct dc_surface *dc_surface) } } -static bool construct_gamma(struct gamma *gamma) -{ - return true; -} - -static void destruct_gamma(struct gamma *gamma) -{ - -} - void dc_gamma_retain(const struct dc_gamma *dc_gamma) { struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); @@ -185,10 +188,8 @@ void dc_gamma_release(const struct dc_gamma *dc_gamma) struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); --gamma->ref_count; - if (gamma->ref_count == 0) { - destruct_gamma(gamma); + if (gamma->ref_count == 0) dm_free(gamma); - } } struct dc_gamma *dc_create_gamma() @@ -198,17 +199,44 @@ struct dc_gamma *dc_create_gamma() if (gamma == NULL) goto alloc_fail; - if (false == construct_gamma(gamma)) - goto construct_fail; - dc_gamma_retain(&gamma->protected.public); return &gamma->protected.public; -construct_fail: - dm_free(gamma); +alloc_fail: + return NULL; +} + +void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf) +{ + struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); + + ++tf->ref_count; +} + +void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) +{ + struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); + --tf->ref_count; + + if (tf->ref_count == 0) + dm_free(tf); +} + +struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct transfer_func *tf = dm_alloc(sizeof(*tf)); + + if (tf == NULL) + goto alloc_fail; + + dc_transfer_func_retain(&tf->protected.public); + + return &tf->protected.public; alloc_fail: return NULL; } + diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7733292d42f8..aeb0c3be24d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -201,7 +201,8 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); enum { RGB_256X3X16 = 256, - FLOAT_GAMMA_RAMP_MAX = 1025 + FLOAT_GAMMA_RAMP_MAX = 1025, + TRANSFER_FUNC_POINTS = 1025 }; enum dc_gamma_ramp_type { @@ -236,6 +237,31 @@ struct dc_gamma { uint32_t size; }; +enum dc_transfer_func_type { + TF_TYPE_PREDEFINED, + TF_TYPE_DISTRIBUTED_POINTS, +}; + +struct dc_transfer_func_distributed_points { + uint16_t red[TRANSFER_FUNC_POINTS]; + uint16_t green[TRANSFER_FUNC_POINTS]; + uint16_t blue[TRANSFER_FUNC_POINTS]; + uint16_t end_exponent; + uint16_t x_point_at_y1; +}; + +enum dc_transfer_func_predefined { + TRANSFER_FUNCTION_SRGB, + TRANSFER_FUNCTION_BT709, + TRANSFER_FUNCTION_LINEAR, +}; + +struct dc_transfer_func { + enum dc_transfer_func_type type; + enum dc_transfer_func_predefined tf; + struct dc_transfer_func_distributed_points tf_pts; +}; + struct dc_surface { bool visible; bool flip_immediate; @@ -256,7 +282,11 @@ struct dc_surface { bool horizontal_mirror; enum plane_stereo_format stereo_format; + /* TO BE REMOVED AFTER BELOW TRANSFER FUNCTIONS IMPLEMENTED */ const struct dc_gamma *gamma_correction; + + const struct dc_transfer_func *in_transfer_func; + const struct dc_transfer_func *out_transfer_func; }; struct dc_plane_info { @@ -287,8 +317,12 @@ struct dc_surface_update { /* following updates require alloc/sleep/spin that is not isr safe, * null means no updates */ + /* gamma TO BE REMOVED */ struct dc_gamma *gamma; + struct dc_transfer_func *in_transfer_func; + struct dc_transfer_func *out_transfer_func; + }; /* @@ -316,6 +350,10 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma); void dc_gamma_release(const struct dc_gamma *dc_gamma); struct dc_gamma *dc_create_gamma(void); +void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); +void dc_transfer_func_release(const struct dc_transfer_func *dc_tf); +struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc); + /* * This structure holds a surface address. There could be multiple addresses * in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 99937facf645..f6984e9ed169 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -231,16 +231,20 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } -static bool set_gamma_ramp( - struct input_pixel_processor *ipp, - struct output_pixel_processor *opp, - const struct core_gamma *ramp, +static bool dce110_set_gamma_correction( + struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct output_pixel_processor *opp = pipe_ctx->opp; + const struct core_gamma *ramp = NULL; struct ipp_prescale_params prescale_params = { 0 }; struct pwl_params *regamma_params; bool result = false; + if (surface->public.gamma_correction) + ramp = DC_GAMMA_TO_CORE(surface->public.gamma_correction); + regamma_params = dm_alloc(sizeof(struct pwl_params)); if (regamma_params == NULL) goto regamma_alloc_fail; @@ -1842,33 +1846,13 @@ static void dce110_program_front_end_for_pipe( pipe_ctx->scl_data.recout.y); } - - -static void dce110_prepare_pipe_for_surface_commit( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) { - struct core_gamma *gamma = NULL; - - dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context); - - if (pipe_ctx->surface->public.gamma_correction) - gamma = DC_GAMMA_TO_CORE( - pipe_ctx->surface->public.gamma_correction); - - dc->hwss.set_gamma_correction( - pipe_ctx->ipp, - pipe_ctx->opp, - gamma, pipe_ctx->surface); -} - static void dce110_prepare_pipe_for_context( struct core_dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { dce110_power_on_pipe_if_needed(dc, pipe_ctx, context); - dce110_prepare_pipe_for_surface_commit(dc, pipe_ctx, context); + dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context); } static void dce110_apply_ctx_for_surface( @@ -1920,7 +1904,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, .update_pending_status = dce110_update_pending_status, - .set_gamma_correction = set_gamma_ramp, + .set_gamma_correction = dce110_set_gamma_correction, .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_timing_synchronization = dce110_enable_timing_synchronization, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 3cf9bfb6decd..a67d6756095d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -66,6 +66,11 @@ struct core_gamma { struct dc_context *ctx; }; +struct core_transfer_func { + struct dc_transfer_func public; + struct dc_context *ctx; +}; + void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index fcaf2c71e4eb..89a08342a51f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -78,9 +78,7 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx); bool (*set_gamma_correction)( - struct input_pixel_processor *ipp, - struct output_pixel_processor *opp, - const struct core_gamma *ramp, + struct pipe_ctx *pipe_ctx, const struct core_surface *surface); void (*power_down)(struct core_dc *dc); -- GitLab From ac58fff1551672c925b0ec2879c4653a69771ee2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 19 Apr 2017 13:15:18 -0400 Subject: [PATCH 0105/2898] drm/dp-helper: add missing defines needed by AMD display core. These are all the ones required by the AMD display core. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- include/drm/drm_dp_helper.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b17476a6909c..d9fab1e1818a 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -510,6 +510,8 @@ # define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 # define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 +#define DP_ADJUST_REQUEST_POST_CURSOR2 0x20c + #define DP_TEST_REQUEST 0x218 # define DP_TEST_LINK_TRAINING (1 << 0) # define DP_TEST_LINK_VIDEO_PATTERN (1 << 1) @@ -582,6 +584,8 @@ #define DP_TEST_REFRESH_RATE_NUMERATOR 0x234 +#define DP_TEST_MISC0 0x232 + #define DP_TEST_CRC_R_CR 0x240 #define DP_TEST_CRC_G_Y 0x242 #define DP_TEST_CRC_B_CB 0x244 @@ -590,6 +594,18 @@ # define DP_TEST_CRC_SUPPORTED (1 << 5) # define DP_TEST_COUNT_MASK 0xf +#define DP_TEST_PHY_PATTERN 0x248 +#define DP_TEST_80BIT_CUSTOM_PATTERN_7_0 0x250 +#define DP_TEST_80BIT_CUSTOM_PATTERN_15_8 0x251 +#define DP_TEST_80BIT_CUSTOM_PATTERN_23_16 0x252 +#define DP_TEST_80BIT_CUSTOM_PATTERN_31_24 0x253 +#define DP_TEST_80BIT_CUSTOM_PATTERN_39_32 0x254 +#define DP_TEST_80BIT_CUSTOM_PATTERN_47_40 0x255 +#define DP_TEST_80BIT_CUSTOM_PATTERN_55_48 0x256 +#define DP_TEST_80BIT_CUSTOM_PATTERN_63_56 0x257 +#define DP_TEST_80BIT_CUSTOM_PATTERN_71_64 0x258 +#define DP_TEST_80BIT_CUSTOM_PATTERN_79_72 0x259 + #define DP_TEST_RESPONSE 0x260 # define DP_TEST_ACK (1 << 0) # define DP_TEST_NAK (1 << 1) @@ -611,6 +627,7 @@ #define DP_SINK_OUI 0x400 #define DP_BRANCH_OUI 0x500 #define DP_BRANCH_ID 0x503 +#define DP_BRANCH_REVISION_START 0x509 #define DP_BRANCH_HW_REV 0x509 #define DP_BRANCH_SW_REV 0x50A @@ -738,6 +755,9 @@ #define DP_RECEIVER_ALPM_STATUS 0x200b /* eDP 1.4 */ # define DP_ALPM_LOCK_TIMEOUT_ERROR (1 << 0) +#define DP_DP13_DPCD_REV 0x2200 +#define DP_DP13_MAX_LINK_RATE 0x2201 + #define DP_DPRX_FEATURE_ENUMERATION_LIST 0x2210 /* DP 1.3 */ # define DP_GTC_CAP (1 << 0) /* DP 1.3 */ # define DP_SST_SPLIT_SDP_CAP (1 << 1) /* DP 1.4 */ -- GitLab From b264d3455d9c8ce0bea422a04a867f0a724c7770 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Wed, 14 Dec 2016 15:35:13 -0500 Subject: [PATCH 0106/2898] drm/amd/dal: Add POLARIS12 support (v2) v2: agd: squash in dm fix, rebase Signed-off-by: Jordan Lazare Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 3 ++- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 5 ++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e5ba23253814..2a7802c67eae 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1235,6 +1235,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_STONEY: case CHIP_POLARIS11: case CHIP_POLARIS10: + case CHIP_POLARIS12: if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); return -1; @@ -1472,6 +1473,7 @@ static int dm_early_init(void *handle) adev->mode_info.num_dig = 9; break; case CHIP_POLARIS11: + case CHIP_POLARIS12: adev->mode_info.num_crtc = 5; adev->mode_info.num_hpd = 5; adev->mode_info.num_dig = 5; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f552b0468186..343114b2680f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -60,7 +60,8 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) break; } if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || - ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) { + ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || + ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { dc_version = DCE_VERSION_11_2; } break; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 3a478300b848..85d8b31acd02 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1233,7 +1233,8 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) const struct resource_caps *dce112_resource_cap( struct hw_asic_id *asic_id) { - if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev)) + if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev) || + ASIC_REV_IS_POLARIS12_V(asic_id->hw_internal_rev)) return &polaris_11_resource_cap; else return &polaris_10_resource_cap; diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 119297e3bdc0..46f1e88f5e27 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -85,6 +85,7 @@ /* DCE112 */ #define VI_POLARIS10_P_A0 80 #define VI_POLARIS11_M_A0 90 +#define VI_POLARIS12_V_A0 100 #define VI_UNKNOWN 0xFF @@ -95,7 +96,9 @@ #define ASIC_REV_IS_POLARIS10_P(eChipRev) ((eChipRev >= VI_POLARIS10_P_A0) && \ (eChipRev < VI_POLARIS11_M_A0)) -#define ASIC_REV_IS_POLARIS11_M(eChipRev) (eChipRev >= VI_POLARIS11_M_A0) +#define ASIC_REV_IS_POLARIS11_M(eChipRev) ((eChipRev >= VI_POLARIS11_M_A0) && \ + (eChipRev < VI_POLARIS12_V_A0)) +#define ASIC_REV_IS_POLARIS12_V(eChipRev) (eChipRev >= VI_POLARIS12_V_A0) /* DCE11 */ #define CZ_CARRIZO_A0 0x01 -- GitLab From b90a2b23edeb1f5181c7baf0ecd305c7e6ab20b4 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 14 Dec 2016 16:05:22 -0500 Subject: [PATCH 0107/2898] drm/amd/display: Resolved HDMI assert in dal Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 842182ce93a8..0590e0a6cd07 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -94,12 +94,12 @@ static void dce110_update_generic_info_packet( /* poll dig_update_lock is not locked -> asic internal signal * assume otg master lock will unlock it */ - REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, - 1, 10, max_retries); +/* REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, + 0, 10, max_retries);*/ /* check if HW reading GSP memory */ REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, - 1, 10, max_retries); + 0, 10, max_retries); /* HW does is not reading GSP memory not reading too long -> * something wrong. clear GPS memory access and notify? -- GitLab From ea24af3e21192a719603ed02ec42e549e3c4a66a Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 14 Dec 2016 16:26:27 -0500 Subject: [PATCH 0108/2898] drm/amd/display: Refactor to move color helper into module Refactor part 2 - Moving color helper into color module The color module will need table defined in the helper in order to calculate the logical regamma curve, and also to fully handle gamut remapping. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/modules/color/color_helper.c | 199 ++++++++++++++++++ .../amd/display/modules/color/color_helper.h | 50 +++++ .../drm/amd/display/modules/inc/mod_color.h | 4 +- 3 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/modules/color/color_helper.c create mode 100644 drivers/gpu/drm/amd/display/modules/color/color_helper.h diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.c b/drivers/gpu/drm/amd/display/modules/color/color_helper.c new file mode 100644 index 000000000000..c47d2962c6d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.c @@ -0,0 +1,199 @@ + +/** + * @file + * @date Copyright (c) 2008 Advanced Micro Devices, Inc. (unpublished) + * + * @brief Helper functions for color gamut calculation + * + * @internal + * All rights reserved. This notice is intended as a precaution against + * inadvertent publication and does not imply publication or any waiver + * of confidentiality. The year included in the foregoing notice is the + * year of creation of the work. + */ + +#include "dm_services.h" +#include "dc.h" +#include "mod_color.h" +#include "color_helper.h" + +const struct gamut_space_entry predefined_gamuts[] = { + /* x_red y_red x_gr y_gr x_blue y_blue a0 a1 a2 a3 gamma */ + [gamut_type_bt709] = {6400, 3300, 3000, 6000, 1500, 600, 180000, 4500, 99, 99, 2200}, + [gamut_type_bt601] = {6400, 3300, 2900, 6000, 1500, 600, 180000, 4500, 99, 99, 2200}, + [gamut_type_adobe_rgb] = {6400, 3300, 2100, 7100, 1500, 600, 180000, 4500, 99, 99, 2200}, + [gamut_type_srgb] = {6400, 3300, 3000, 6000, 1500, 600, 31308, 12920, 55, 55, 2400}, + [gamut_type_bt2020] = {7080, 2920, 1700, 7970, 1310, 460, 180000, 4500, 99, 99, 2200} +}; + +const struct white_point_coodinates_entry predefined_white_points[] = { + [white_point_type_5000k_horizon] = {5000, 3473, 3561}, + [white_point_type_6500k_noon] = {6500, 3127, 3290}, + [white_point_type_7500k_north_sky] = {7500, 3022, 3129}, + [white_point_type_9300k] = {9300, 2866, 2950} +}; + +const unsigned int white_point_entries = 91; + +const struct white_point_coodinates_entry white_point_temps[] = { + /*001*/{1000, 6499, 3474}, + /*002*/{1100, 6361, 3594}, + /*003*/{1200, 6226, 3703}, + /*004*/{1300, 6095, 3801}, + /*005*/{1400, 5966, 3887}, + /*006*/{1500, 5841, 3962}, + /*007*/{1600, 5720, 4025}, + /*008*/{1700, 5601, 4076}, + /*009*/{1800, 5486, 4118}, + /*010*/{1900, 5375, 4150}, + /*011*/{2000, 5267, 4173}, + /*012*/{2100, 5162, 4188}, + /*013*/{2200, 5062, 4196}, + /*014*/{2300, 4965, 4198}, + /*015*/{2400, 4872, 4194}, + /*016*/{2500, 4782, 4186}, + /*017*/{2600, 4696, 4173}, + /*018*/{2700, 4614, 4158}, + /*019*/{2800, 4535, 4139}, + /*020*/{2900, 4460, 4118}, + /*021*/{3000, 4388, 4095}, + /*022*/{3100, 4320, 4070}, + /*023*/{3200, 4254, 4044}, + /*024*/{3300, 4192, 4018}, + /*025*/{3400, 4132, 3990}, + /*026*/{3500, 4075, 3962}, + /*027*/{3600, 4021, 3934}, + /*028*/{3700, 3969, 3905}, + /*029*/{3800, 3919, 3877}, + /*030*/{3900, 3872, 3849}, + /*031*/{4000, 3827, 3820}, + /*032*/{4100, 3784, 3793}, + /*033*/{4200, 3743, 3765}, + /*034*/{4300, 3704, 3738}, + /*035*/{4400, 3666, 3711}, + /*036*/{4500, 3631, 3685}, + /*037*/{4600, 3596, 3659}, + /*038*/{4700, 3563, 3634}, + /*039*/{4800, 3532, 3609}, + /*040*/{4900, 3502, 3585}, + /*041*/{5000, 3473, 3561}, + /*042*/{5100, 3446, 3538}, + /*043*/{5200, 3419, 3516}, + /*044*/{5300, 3394, 3494}, + /*045*/{5400, 3369, 3472}, + /*046*/{5500, 3346, 3451}, + /*047*/{5600, 3323, 3431}, + /*048*/{5700, 3302, 3411}, + /*049*/{5800, 3281, 3392}, + /*050*/{5900, 3261, 3373}, + /*051*/{6000, 3242, 3355}, + /*052*/{6100, 3223, 3337}, + /*053*/{6200, 3205, 3319}, + /*054*/{6300, 3188, 3302}, + /*055*/{6400, 3161, 3296}, + /*056*/{6500, 3127, 3290}, /* This is the real white point sRGB */ + /*057*/{6600, 3126, 3264}, + /*058*/{6700, 3125, 3238}, + /*059*/{6800, 3110, 3224}, + /*060*/{6900, 3097, 3209}, + /*061*/{7000, 3083, 3195}, + /*062*/{7100, 3070, 3181}, + /*063*/{7200, 3058, 3168}, + /*064*/{7300, 3045, 3154}, + /*065*/{7400, 3034, 3142}, + /*066*/{7500, 3022, 3129}, + /*067*/{7600, 3011, 3117}, + /*068*/{7700, 3000, 3105}, + /*069*/{7800, 2990, 3094}, + /*070*/{7900, 2980, 3082}, + /*071*/{8000, 2970, 3071}, + /*072*/{8100, 2961, 3061}, + /*073*/{8200, 2952, 3050}, + /*074*/{8300, 2943, 3040}, + /*075*/{8400, 2934, 3030}, + /*076*/{8500, 2926, 3020}, + /*077*/{8600, 2917, 3011}, + /*078*/{8700, 2910, 3001}, + /*079*/{8800, 2902, 2992}, + /*080*/{8900, 2894, 2983}, + /*081*/{9000, 2887, 2975}, + /*082*/{9100, 2880, 2966}, + /*083*/{9200, 2873, 2958}, + /*084*/{9300, 2866, 2950}, + /*085*/{9400, 2860, 2942}, + /*086*/{9500, 2853, 2934}, + /*087*/{9600, 2847, 2927}, + /*088*/{9700, 2841, 2919}, + /*089*/{9800, 2835, 2912}, + /*090*/{9900, 2829, 2905}, + /*091*/{10000, 2824, 2898} +}; + +bool mod_color_find_predefined_gamut( + struct gamut_space_coordinates *out_gamut, + enum predefined_gamut_type type) +{ + out_gamut->redX = predefined_gamuts[type].redX; + out_gamut->redY = predefined_gamuts[type].redY; + out_gamut->greenX = predefined_gamuts[type].greenX; + out_gamut->greenY = predefined_gamuts[type].greenY; + out_gamut->blueX = predefined_gamuts[type].blueX; + out_gamut->blueY = predefined_gamuts[type].blueY; + + return true; +} + +bool mod_color_find_predefined_white_point( + struct white_point_coodinates *out_white_point, + enum predefined_white_point_type type) +{ + out_white_point->whiteX = predefined_white_points[type].whiteX; + out_white_point->whiteY = predefined_white_points[type].whiteY; + + return true; +} + +bool mod_color_find_white_point_from_temperature( + struct white_point_coodinates *out_white_point, + unsigned int temperature) +{ + int i; + unsigned int found = false; + struct white_point_coodinates_entry temp_white_point = + white_point_temps[55]; + + if (temperature < 1000 || temperature > 10000) + return false; + + for (i = 0; i < white_point_entries; i++) { + if (temperature == white_point_temps[i].temperature) { + temp_white_point = white_point_temps[i]; + found = true; + break; + } + } + + out_white_point->whiteX = temp_white_point.whiteX; + out_white_point->whiteY = temp_white_point.whiteY; + + return found; +} + +bool mod_color_find_temperature_from_white_point( + struct white_point_coodinates *in_white_point, + unsigned int *out_temperature) +{ + unsigned int i; + *out_temperature = 6500; + + for (i = 0; i < white_point_entries; i++) { + if (in_white_point->whiteX == white_point_temps[i].whiteX && + in_white_point->whiteY == white_point_temps[i].whiteY) { + *out_temperature = white_point_temps[i].temperature; + return true; + } + } + + return false; +} + diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h new file mode 100644 index 000000000000..c0e6334b947e --- /dev/null +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.h @@ -0,0 +1,50 @@ +/** + * @file + * @date Copyright (c) 2008 Advanced Micro Devices, Inc. (unpublished) + * + * @brief Helper functions for color gamut calculation + * + * @internal + * All rights reserved. This notice is intended as a precaution against + * inadvertent publication and does not imply publication or any waiver + * of confidentiality. The year included in the foregoing notice is the + * year of creation of the work. + */ + +#ifndef COLOR_MOD_COLOR_HELPER_H_ +#define COLOR_MOD_COLOR_HELPER_H_ + +enum predefined_gamut_type { + gamut_type_bt709, + gamut_type_bt601, + gamut_type_adobe_rgb, + gamut_type_srgb, + gamut_type_bt2020, + gamut_type_unknown, +}; + +enum predefined_white_point_type { + white_point_type_5000k_horizon, + white_point_type_6500k_noon, + white_point_type_7500k_north_sky, + white_point_type_9300k, + white_point_type_unknown, +}; + +bool mod_color_find_predefined_gamut( + struct gamut_space_coordinates *out_gamut, + enum predefined_gamut_type type); + +bool mod_color_find_predefined_white_point( + struct white_point_coodinates *out_white_point, + unsigned int index); + +bool mod_color_find_white_point_from_temperature( + struct white_point_coodinates *out_white_point, + unsigned int temperature); + +bool mod_color_find_temperature_from_white_point( + struct white_point_coodinates *in_white_point, + unsigned int *out_temperature); + +#endif /* COLOR_MOD_COLOR_HELPER_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index 91abc173444a..787c2c0a0e14 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -28,6 +28,7 @@ #define MOD_COLOR_H_ #include "dm_services.h" +#include "color_helper.h" struct mod_color { int dummy; @@ -54,7 +55,6 @@ struct gamut_space_coordinates { }; struct gamut_space_entry { - unsigned int index; unsigned int redX; unsigned int redY; unsigned int greenX; @@ -75,7 +75,7 @@ struct white_point_coodinates { }; struct white_point_coodinates_entry { - unsigned int index; + unsigned int temperature; unsigned int whiteX; unsigned int whiteY; }; -- GitLab From aa66df58b2f272dad459c9f02fa3718d844b9fc6 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 15 Dec 2016 10:50:48 -0500 Subject: [PATCH 0109/2898] drm/amd/display: Add debug option to disable dmcu Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index aeb0c3be24d6..36f1c96605e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -147,6 +147,7 @@ struct dc_debug { bool disable_dfs_bypass; bool disable_power_gate; bool disable_clock_gate; + bool disable_dmcu; }; struct dc { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index c73d6054cdda..a8a2290d47db 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1821,6 +1821,9 @@ void dce110_link_encoder_init_dmcu_backlight_settings( uint32_t s2; uint32_t value; + if (enc->ctx->dc->debug.disable_dmcu) + return; + bl_pwm_cntl = REG_READ(BL_PWM_CNTL); /* It must not be 0, so we have to restore them -- GitLab From 9cdc4e7ce4cae74bbe64a0e0ed15655dfa50a8a1 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 15 Dec 2016 11:51:09 -0500 Subject: [PATCH 0110/2898] drm/amd/display: fix hotplug regression after code refactor The condition logic of REG_WAIT in dce110_stream_encoder_dp_blank() got inverted after refactoring. Signed-off-by: Roman Li Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 0590e0a6cd07..b74a29b40a66 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -635,7 +635,7 @@ static void dce110_stream_encoder_dp_blank( */ REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, - 1, + 0, 10, max_retries); ASSERT(retries <= max_retries); -- GitLab From 90e508ba253c9e43711a7bf16230cdb13d0b1440 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 15 Dec 2016 12:09:46 -0500 Subject: [PATCH 0111/2898] drm/amd/display: Refactor output transfer function to stream Refactor part 3 - Moving output transfer function from surface to stream Split HWSS to program degamma and regamma separately. Degamma should be dependent on input transfer function. And Regamma should depend on the desired output transfer function. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 11 ++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 23 ++++--- .../gpu/drm/amd/display/dc/core/dc_stream.c | 3 + .../gpu/drm/amd/display/dc/core/dc_surface.c | 6 +- drivers/gpu/drm/amd/display/dc/dc.h | 9 +-- .../display/dc/dce110/dce110_hw_sequencer.c | 65 +++++++++++++++---- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 7 +- 8 files changed, 97 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c073f4558cf4..364f2c970b6e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -513,6 +513,7 @@ static void fill_gamma_from_crtc( struct dc_gamma *gamma; struct drm_crtc_state *state = crtc->state; struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; + struct dc_transfer_func *input_tf; gamma = dc_create_gamma(); @@ -529,6 +530,16 @@ static void fill_gamma_from_crtc( gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); dc_surface->gamma_correction = gamma; + + input_tf = dc_create_transfer_func(); + + if (input_tf == NULL) + return; + + input_tf->type = TF_TYPE_PREDEFINED; + input_tf->tf = TRANSFER_FUNCTION_SRGB; + + dc_surface->in_transfer_func = input_tf; } static void fill_plane_attributes( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f20701a507da..df1bae8ea92b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1394,6 +1394,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct core_stream *stream = pipe_ctx->stream; if (pipe_ctx->surface != surface) continue; @@ -1472,15 +1473,14 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].out_transfer_func && updates[i].out_transfer_func != - surface->public.out_transfer_func) { - if (surface->public.out_transfer_func != NULL) + stream->public.out_transfer_func) { + if (stream->public.out_transfer_func != NULL) dc_transfer_func_release( - surface->public. + stream->public. out_transfer_func); - dc_transfer_func_retain( updates[i].out_transfer_func); - surface->public.out_transfer_func = + stream->public.out_transfer_func = updates[i].out_transfer_func; } } @@ -1516,12 +1516,19 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } + if (is_new_pipe_surface[j] || + updates[i].in_transfer_func) + core_dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->surface); + if (is_new_pipe_surface[j] || updates[i].gamma || - updates[i].in_transfer_func || updates[i].out_transfer_func) - core_dc->hwss.set_gamma_correction( - pipe_ctx, pipe_ctx->surface); + core_dc->hwss.set_output_transfer_func( + pipe_ctx, + pipe_ctx->surface, + pipe_ctx->stream); + } if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 8d6aa607e1f5..237436e22720 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -89,6 +89,9 @@ static bool construct(struct core_stream *stream, static void destruct(struct core_stream *stream) { dc_sink_release(&stream->sink->public); + if (stream->public.out_transfer_func != NULL) + dc_transfer_func_release( + stream->public.out_transfer_func); } void dc_stream_retain(const struct dc_stream *dc_stream) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 8d2668406f3a..3ec1f363e43e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -76,9 +76,6 @@ static void destruct(struct surface *surface) if (surface->protected.public.in_transfer_func != NULL) dc_transfer_func_release( surface->protected.public.in_transfer_func); - if (surface->protected.public.out_transfer_func != NULL) - dc_transfer_func_release( - surface->protected.public.out_transfer_func); } /******************************************************************************* @@ -223,9 +220,8 @@ void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) dm_free(tf); } -struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc) +struct dc_transfer_func *dc_create_transfer_func() { - struct core_dc *core_dc = DC_TO_CORE(dc); struct transfer_func *tf = dm_alloc(sizeof(*tf)); if (tf == NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 36f1c96605e8..ffea10c73275 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -254,6 +254,7 @@ struct dc_transfer_func_distributed_points { enum dc_transfer_func_predefined { TRANSFER_FUNCTION_SRGB, TRANSFER_FUNCTION_BT709, + TRANSFER_FUNCTION_PQ, TRANSFER_FUNCTION_LINEAR, }; @@ -287,7 +288,6 @@ struct dc_surface { const struct dc_gamma *gamma_correction; const struct dc_transfer_func *in_transfer_func; - const struct dc_transfer_func *out_transfer_func; }; struct dc_plane_info { @@ -353,7 +353,7 @@ struct dc_gamma *dc_create_gamma(void); void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); void dc_transfer_func_release(const struct dc_transfer_func *dc_tf); -struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc); +struct dc_transfer_func *dc_create_transfer_func(void); /* * This structure holds a surface address. There could be multiple addresses @@ -527,10 +527,11 @@ struct dc_stream { struct freesync_context freesync_ctx; - /* TODO: dithering */ - /* TODO: transfer function (CSC/regamma/gamut remap) */ + const struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; + + /* TODO: dithering */ /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f6984e9ed169..72017d5a8252 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -231,11 +231,61 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } -static bool dce110_set_gamma_correction( +static bool dce110_set_degamma( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; + const struct core_transfer_func *tf = NULL; + struct ipp_prescale_params prescale_params = { 0 }; + bool result = true; + + if (ipp == NULL) + return false; + + if (surface->public.in_transfer_func) + tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + + build_prescale_params(&prescale_params, surface); + ipp->funcs->ipp_program_prescale(ipp, &prescale_params); + + if (tf == NULL) { + /* Default case if no input transfer function specified */ + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_BYPASS); + } else if (tf->public.type == TF_TYPE_PREDEFINED) { + switch (tf->public.tf) { + case TRANSFER_FUNCTION_SRGB: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_HW_sRGB); + break; + case TRANSFER_FUNCTION_BT709: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_HW_xvYCC); + break; + case TRANSFER_FUNCTION_LINEAR: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_BYPASS); + break; + case TRANSFER_FUNCTION_PQ: + result = false; + break; + default: + result = false; + } + } else { + /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ + result = false; + } + + return result; +} + +static bool dce110_set_output_transfer_func( + struct pipe_ctx *pipe_ctx, + const struct core_surface *surface, /* Surface - To be removed */ + const struct core_stream *stream) +{ struct output_pixel_processor *opp = pipe_ctx->opp; const struct core_gamma *ramp = NULL; struct ipp_prescale_params prescale_params = { 0 }; @@ -253,20 +303,10 @@ static bool dce110_set_gamma_correction( opp->funcs->opp_power_on_regamma_lut(opp, true); - if (ipp) { - build_prescale_params(&prescale_params, surface); - ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - } - if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) { - opp->funcs->opp_program_regamma_pwl(opp, regamma_params); - if (ipp) - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { - if (ipp) - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); } @@ -1904,7 +1944,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, .update_pending_status = dce110_update_pending_status, - .set_gamma_correction = dce110_set_gamma_correction, + .set_input_transfer_func = dce110_set_degamma, + .set_output_transfer_func = dce110_set_output_transfer_func, .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, .enable_timing_synchronization = dce110_enable_timing_synchronization, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index a67d6756095d..c2d35c2c28bf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -55,6 +55,9 @@ struct core_target { #define DC_GAMMA_TO_CORE(dc_gamma) \ container_of(dc_gamma, struct core_gamma, public) +#define DC_TRANSFER_FUNC_TO_CORE(dc_transfer_func) \ + container_of(dc_transfer_func, struct core_transfer_func, public) + struct core_surface { struct dc_surface public; struct dc_surface_status status; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 89a08342a51f..0e803ca83bb9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -77,10 +77,15 @@ struct hw_sequencer_funcs { void (*update_pending_status)( struct pipe_ctx *pipe_ctx); - bool (*set_gamma_correction)( + bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, const struct core_surface *surface); + bool (*set_output_transfer_func)( + struct pipe_ctx *pipe_ctx, + const struct core_surface *surface, + const struct core_stream *stream); + void (*power_down)(struct core_dc *dc); void (*enable_accelerated_mode)(struct core_dc *dc); -- GitLab From cb9a5a90eee4a02ea529b3101645bb959efaf4a8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 15 Dec 2016 13:53:15 -0500 Subject: [PATCH 0112/2898] drm/amd/display: define reg helpers to update registers with 8 and 9 fields Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/inc/reg_helper.h | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index a07817472089..b595b94d2b69 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -112,6 +112,31 @@ FN(reg, f6), v6,\ FN(reg, f7), v7) +#define REG_SET_8(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, \ + f5, v5, f6, v6, f7, v7, f8, v8) \ + REG_SET_N(reg, 8, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2,\ + FN(reg, f3), v3,\ + FN(reg, f4), v4,\ + FN(reg, f5), v5,\ + FN(reg, f6), v6,\ + FN(reg, f7), v7,\ + FN(reg, f8), v8) + +#define REG_SET_9(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \ + v5, f6, v6, f7, v7, f8, v8, f9, v9) \ + REG_SET_N(reg, 9, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9) + #define REG_SET_10(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \ v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ REG_SET_N(reg, 10, init_value, \ -- GitLab From c5ea922237f7dda25c488810a7c1ee9deadc9684 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 16 Dec 2016 10:43:21 -0500 Subject: [PATCH 0113/2898] drm/amd/display: Refactor to move gamma correction to module Refactor part 4 - Moving input gamma correction programming into color module DM will translate to dc_gamma structure, but programming will be moved into the color module. Later, this will allow gamma correction to be added on top of in/out transfer function curves. Signed-off-by: Anthony Koo Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/color/color.c | 77 +++++++++++++++++++ .../drm/amd/display/modules/inc/mod_color.h | 4 + 2 files changed, 81 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 0610b82b6d84..6613ff9f4d28 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -69,6 +69,7 @@ struct color_state { struct color_range saturation; struct color_range brightness; struct color_range hue; + struct dc_gamma *gamma; enum dc_quantization_range preferred_quantization_range; }; @@ -1265,6 +1266,26 @@ static void calculate_csc_matrix(struct core_color *core_color, } } +static struct dc_surface *dc_stream_to_surface_from_pipe_ctx( + struct core_color *core_color, + const struct dc_stream *stream) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(core_color->dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct dc_surface *out_surface = NULL; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) { + out_surface = &core_dc->current_context->res_ctx. + pipe_ctx[i].surface->public; + break; + } + } + return out_surface; +} + struct mod_color *mod_color_create(struct dc *dc) { int i = 0; @@ -1369,6 +1390,10 @@ void mod_color_destroy(struct mod_color *mod_color) struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + for (i = 0; i < core_color->num_sinks; i++) + if (core_color->state[i].gamma) + dc_gamma_release(core_color->state[i].gamma); + dm_free(core_color->state); for (i = 0; i < core_color->num_sinks; i++) @@ -1552,6 +1577,9 @@ bool mod_color_remove_sink(struct mod_color *mod_color, for (i = 0; i < core_color->num_sinks; i++) { if (core_color->caps[i].sink == sink) { + if (core_color->state[i].gamma) + dc_gamma_release(core_color->state[i].gamma); + /* To remove this sink, shift everything after down */ for (j = i; j < core_color->num_sinks - 1; j++) { core_color->caps[j].sink = @@ -2184,6 +2212,55 @@ bool mod_color_set_saturation(struct mod_color *mod_color, return true; } +bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct dc_gamma *gamma) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + + struct dc_surface *surface = + dc_stream_to_surface_from_pipe_ctx(core_color, + streams[stream_index]); + + if (surface != NULL) { + struct dc_transfer_func *input_tf = + dc_create_transfer_func(core_color->dc); + struct dc_surface_update updates = {0}; + + if (input_tf != NULL) { + input_tf->type = TF_TYPE_PREDEFINED; + input_tf->tf = TRANSFER_FUNCTION_SRGB; + } + + if (core_color->state[sink_index].gamma != gamma) { + if (core_color->state[sink_index].gamma) + dc_gamma_release( + core_color->state[sink_index]. + gamma); + + dc_gamma_retain(gamma); + core_color->state[sink_index].gamma = gamma; + } + + updates.surface = surface; + updates.gamma = gamma; + updates.in_transfer_func = input_tf; + dc_update_surfaces_for_target(core_color->dc, &updates, + 1, NULL); + + if (input_tf != NULL) + dc_transfer_func_release(input_tf); + } + } + + return true; +} + bool mod_color_persist_user_preferred_quantization_range( struct mod_color *mod_color, const struct dc_sink *sink, diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index 787c2c0a0e14..fbf908141ba7 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -168,6 +168,10 @@ bool mod_color_set_saturation(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, int saturation_value); +bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct dc_gamma *gamma); + bool mod_color_persist_user_preferred_quantization_range( struct mod_color *mod_color, const struct dc_sink *sink, -- GitLab From e63d86dc9b59d72cf25c6bc75e641bceed4fcd40 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 16 Dec 2016 12:12:03 -0500 Subject: [PATCH 0114/2898] drm/amd/display: Implement PQ curve based on output transfer function Refactor part 5 - Regamma programming should be dependent on Output transfer function type Program sRGB gamma or PQ transfer function based on output transfer function. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/gamma_calcs.c | 93 ++++++++++++++++++- .../display/dc/dce110/dce110_hw_sequencer.c | 3 +- .../gpu/drm/amd/display/dc/inc/gamma_calcs.h | 3 +- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index 854796aa0c71..973be8f649cc 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -791,6 +791,82 @@ static inline struct fixed31_32 calculate_oem_mapped_value( max_index); } +static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) +{ + /* consts for PQ gamma formula. */ + const struct fixed31_32 m1 = + dal_fixed31_32_from_fraction(159301758, 1000000000); + const struct fixed31_32 m2 = + dal_fixed31_32_from_fraction(7884375, 100000); + const struct fixed31_32 c1 = + dal_fixed31_32_from_fraction(8359375, 10000000); + const struct fixed31_32 c2 = + dal_fixed31_32_from_fraction(188515625, 10000000); + const struct fixed31_32 c3 = + dal_fixed31_32_from_fraction(186875, 10000); + + struct fixed31_32 l_pow_m1; + struct fixed31_32 base; + + if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero)) + in_x = dal_fixed31_32_zero; + + l_pow_m1 = dal_fixed31_32_pow(in_x, m1); + base = dal_fixed31_32_div( + dal_fixed31_32_add(c1, + (dal_fixed31_32_mul(c2, l_pow_m1))), + dal_fixed31_32_add(dal_fixed31_32_one, + (dal_fixed31_32_mul(c3, l_pow_m1)))); + *out_y = dal_fixed31_32_pow(base, m2); +} + +static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma, + struct pwl_float_data *rgb_oem, + struct pixel_gamma_point *coeff128_oem, + const struct core_gamma *ramp, + const struct core_surface *surface, + uint32_t hw_points_num, + const struct hw_x_point *coordinate_x, + const struct gamma_pixel *axis_x, + struct dividers dividers) +{ + uint32_t i; + + struct pwl_float_data_ex *rgb = rgb_regamma; + const struct hw_x_point *coord_x = coordinate_x; + struct fixed31_32 x; + struct fixed31_32 output; + struct fixed31_32 scaling_factor = + dal_fixed31_32_from_fraction(8, 1000); + + /* use coord_x to retrieve coordinates chosen base on given user curve + * the x values are exponentially distributed and currently it is hard + * coded, the user curve shape is ignored. Need to recalculate coord_x + * based on input curve, translation from 256/1025 to 128 PWL points. + */ + for (i = 0; i <= hw_points_num; i++) { + /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125. + * FP 1.0 = 80nits + */ + x = dal_fixed31_32_mul(coord_x->adjusted_x, scaling_factor); + + compute_pq(x, &output); + + /* should really not happen? */ + if (dal_fixed31_32_lt(output, dal_fixed31_32_zero)) + output = dal_fixed31_32_zero; + else if (dal_fixed31_32_lt(dal_fixed31_32_one, output)) + output = dal_fixed31_32_one; + + rgb->r = output; + rgb->g = output; + rgb->b = output; + + ++coord_x; + ++rgb; + } +} + static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, struct pwl_float_data *rgb_oem, struct pixel_gamma_point *coeff128_oem, @@ -1286,7 +1362,8 @@ static bool convert_to_custom_float( bool calculate_regamma_params(struct pwl_params *params, const struct core_gamma *ramp, - const struct core_surface *surface) + const struct core_surface *surface, + const struct core_stream *stream) { struct gamma_curve *arr_curve_points = params->arr_curve_points; struct curve_points *arr_points = params->arr_points; @@ -1301,7 +1378,6 @@ bool calculate_regamma_params(struct pwl_params *params, struct pixel_gamma_point *coeff128_oem = NULL; struct pixel_gamma_point *coeff128 = NULL; - bool ret = false; coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); @@ -1341,9 +1417,16 @@ bool calculate_regamma_params(struct pwl_params *params, setup_distribution_points(arr_curve_points, arr_points, ¶ms->hw_points_num, coordinates_x); - build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, - ramp, surface, params->hw_points_num, - coordinates_x, axix_x_256, dividers); + if (stream->public.out_transfer_func && + stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { + build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem, + ramp, surface, params->hw_points_num, + coordinates_x, axix_x_256, dividers); + } else { + build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, + ramp, surface, params->hw_points_num, + coordinates_x, axix_x_256, dividers); + } map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user, coordinates_x, axix_x_256, &ramp->public, rgb_regamma, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 72017d5a8252..2f790753b559 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -303,7 +303,8 @@ static bool dce110_set_output_transfer_func( opp->funcs->opp_power_on_regamma_lut(opp, true); - if (ramp && calculate_regamma_params(regamma_params, ramp, surface)) { + if (ramp && calculate_regamma_params( + regamma_params, ramp, surface, stream)) { opp->funcs->opp_program_regamma_pwl(opp, regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h index e2c63fd4fe92..0712268856c2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h @@ -14,6 +14,7 @@ bool calculate_regamma_params(struct pwl_params *params, const struct core_gamma *ramp, - const struct core_surface *surface); + const struct core_surface *surface, + const struct core_stream *stream); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */ -- GitLab From ab3ee7a556343c9549ccbefb9d31039377806f28 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Wed, 14 Dec 2016 18:54:41 -0500 Subject: [PATCH 0115/2898] drm/amd/display: OPP refactor and consolidation for DCE. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 996 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 418 ++++++++ .../amd/display/dc/dce100/dce100_resource.c | 61 +- .../gpu/drm/amd/display/dc/dce110/Makefile | 4 +- .../drm/amd/display/dc/dce110/dce110_opp.c | 77 -- .../drm/amd/display/dc/dce110/dce110_opp.h | 149 --- .../amd/display/dc/dce110/dce110_opp_csc.c | 363 ------- .../amd/display/dc/dce110/dce110_opp_csc_v.c | 2 +- .../display/dc/dce110/dce110_opp_formatter.c | 627 ----------- .../display/dc/dce110/dce110_opp_regamma.c | 537 ---------- .../display/dc/dce110/dce110_opp_regamma_v.c | 2 +- .../drm/amd/display/dc/dce110/dce110_opp_v.c | 2 +- .../amd/display/dc/dce110/dce110_resource.c | 60 +- .../gpu/drm/amd/display/dc/dce112/Makefile | 3 +- .../drm/amd/display/dc/dce112/dce112_opp.c | 72 -- .../drm/amd/display/dc/dce112/dce112_opp.h | 48 - .../display/dc/dce112/dce112_opp_formatter.c | 215 ---- .../amd/display/dc/dce112/dce112_resource.c | 70 +- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 5 +- .../gpu/drm/amd/display/dc/dce80/dce80_opp.c | 136 --- .../gpu/drm/amd/display/dc/dce80/dce80_opp.h | 130 --- .../drm/amd/display/dc/dce80/dce80_opp_csc.c | 363 ------- .../display/dc/dce80/dce80_opp_formatter.c | 577 ---------- .../amd/display/dc/dce80/dce80_opp_regamma.c | 543 ---------- .../drm/amd/display/dc/dce80/dce80_resource.c | 45 +- 26 files changed, 1547 insertions(+), 3960 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_opp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index 6add5977fd39..5ad59a27738c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -7,7 +7,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ -dce_clocks.o +dce_clocks.o dce_opp.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c new file mode 100644 index 000000000000..80443a1cccd2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -0,0 +1,996 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "basics/conversion.h" + +#include "dce_opp.h" + +#include "gamma_types.h" + +#include "reg_helper.h" + +#define REG(reg)\ + (opp110->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + opp110->opp_shift->field_name, opp110->opp_mask->field_name + +#define CTX \ + opp110->base.ctx + +enum { + MAX_PWL_ENTRY = 128, + MAX_REGIONS_NUMBER = 16 +}; + +enum { + MAX_LUT_ENTRY = 256, + MAX_NUMBER_OF_ENTRIES = 256 +}; + + +enum { + OUTPUT_CSC_MATRIX_SIZE = 12 +}; + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + + + + + + + + + + + + + + + + + + +/* + ***************************************************************************** + * Function: regamma_config_regions_and_segments + * + * build regamma curve by using predefined hw points + * uses interface parameters ,like EDID coeff. + * + * @param : parameters interface parameters + * @return void + * + * @note + * + * @see + * + ***************************************************************************** + */ +static void regamma_config_regions_and_segments( + struct dce110_opp *opp110, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + uint32_t value = 0; + + { + REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); + } + { + REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); + + } + { + REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, + REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); + } + { + REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, + REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[2].custom_float_slope, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_y); + } + + curve = params->arr_curve_points; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } +} + +static void program_pwl( + struct dce110_opp *opp110, + const struct pwl_params *params) +{ + uint32_t value; + int retval; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 1); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); + + while (counter < max_tries) { + if (REG(DCFE_MEM_PWR_STATUS)) { + value = REG_READ(DCFE_MEM_PWR_STATUS); + REG_GET(DCFE_MEM_PWR_STATUS, + DCP_REGAMMA_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } else { + value = REG_READ(DCFE_MEM_LIGHT_SLEEP_CNTL); + REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } + } + + if (counter == max_tries) { + dm_logger_write(opp110->base.ctx->logger, LOG_WARNING, + "%s: regamma lut was not powered on " + "in a timely manner," + " programming still proceeds\n", + __func__); + } + } + + REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK, + REGAMMA_LUT_WRITE_EN_MASK, 7); + + REG_WRITE(REGAMMA_LUT_INDEX, 0); + + /* Program REGAMMA_LUT_DATA */ + { + uint32_t i = 0; + const struct pwl_result_data *rgb = params->rgb_resulted; + + while (i != params->hw_points_num) { + + REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 0); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); +} + +bool dce110_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + /* Setup regions */ + regamma_config_regions_and_segments(opp110, params); + + /* Program PWL */ + program_pwl(opp110, params); + + return true; +} + +void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE_2(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, power_on, + DCP_LUT_MEM_PWR_DIS, power_on); + else + REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, + DCP_LUT_LIGHT_SLEEP_DIS, power_on); + +} + +void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + REG_SET(REGAMMA_CONTROL, 0, + GRPH_REGAMMA_MODE, mode); +} + +/** + * set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE11 power saving reason. + */ +static void set_truncation( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + /*Disable truncation*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 0, + FMT_TRUNCATE_DEPTH, 0, + FMT_TRUNCATE_MODE, 0); + /* no 10bpc trunc on DCE11*/ + if (params->flags.TRUNCATE_ENABLED == 0 || + params->flags.TRUNCATE_DEPTH == 2) + return; + + /*Set truncation depth and Enable truncation*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_MODE, + FMT_TRUNCATE_MODE, params->flags.TRUNCATE_DEPTH); + +} + +/** + * set_spatial_dither + * 1) set spatial dithering mode: pattern of seed + * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp + * 3) set random seed + * 4) set random mode + * lfsr is reset every frame or not reset + * RGB dithering method + * 0: RGB data are all dithered with x^28+x^3+1 + * 1: R data is dithered with x^28+x^3+1 + * G data is dithered with x^28+X^9+1 + * B data is dithered with x^28+x^13+1 + * enable high pass filter or not + * 5) enable spatical dithering + */ +static void set_spatial_dither( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + /*Disable spatial (random) dithering*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_EN, 0, + FMT_SPATIAL_DITHER_DEPTH, 0, + FMT_SPATIAL_DITHER_MODE, 0); + + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_HIGHPASS_RANDOM_ENABLE, 0, + FMT_FRAME_RANDOM_ENABLE, 0, + FMT_RGB_RANDOM_ENABLE, 0); + + REG_UPDATE(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN, 0); + + /* no 10bpc on DCE11*/ + if (params->flags.SPATIAL_DITHER_ENABLED == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 2) + return; + + /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ + + if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX && + opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) { + if (params->flags.FRAME_RANDOM == 1) { + if (params->flags.SPATIAL_DITHER_DEPTH == 0 || + params->flags.SPATIAL_DITHER_DEPTH == 1) { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2); + } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1); + } else + return; + } else { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0); + } + } + /* Set seed for random values for + * spatial dithering for R,G,B channels + */ + REG_UPDATE(FMT_DITHER_RAND_R_SEED, + FMT_RAND_R_SEED, params->r_seed_value); + + REG_UPDATE(FMT_DITHER_RAND_G_SEED, + FMT_RAND_G_SEED, params->g_seed_value); + + REG_UPDATE(FMT_DITHER_RAND_B_SEED, + FMT_RAND_B_SEED, params->b_seed_value); + + /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero + * offset for the R/Cr channel, lower 4LSB + * is forced to zeros. Typically set to 0 + * RGB and 0x80000 YCbCr. + */ + /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero + * offset for the G/Y channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB + * and 0x80000 YCbCr. + */ + /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero + * offset for the B/Cb channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB and + * 0x80000 YCbCr. + */ + + /* Disable High pass filter + * Reset only at startup + * Set RGB data dithered with x^28+x^3+1 + */ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM, + FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM, + FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); + + /* Set spatial dithering bit depth + * Set spatial dithering mode + * (default is Seed patterrn AAAA...) + * Enable spatial dithering + */ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH, + FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE, + FMT_SPATIAL_DITHER_EN, 1); +} + +/** + * SetTemporalDither (Frame Modulation) + * 1) set temporal dither depth + * 2) select pattern: from hard-coded pattern or programmable pattern + * 3) select optimized strips for BGR or RGB LCD sub-pixel + * 4) set s matrix + * 5) set t matrix + * 6) set grey level for 0.25, 0.5, 0.75 + * 7) enable temporal dithering + */ + +static void set_temporal_dither( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + /*Disable temporal (frame modulation) dithering first*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN, 0, + FMT_TEMPORAL_DITHER_RESET, 0, + FMT_TEMPORAL_DITHER_OFFSET, 0); + + REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH, 0, + FMT_TEMPORAL_LEVEL, 0); + + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL, 0, + FMT_50FRC_SEL, 0, + FMT_75FRC_SEL, 0); + + /* no 10bpc dither on DCE11*/ + if (params->flags.FRAME_MODULATION_ENABLED == 0 || + params->flags.FRAME_MODULATION_DEPTH == 2) + return; + + /* Set temporal dithering depth*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH, + FMT_TEMPORAL_DITHER_RESET, 0, + FMT_TEMPORAL_DITHER_OFFSET, 0); + + /*Select legacy pattern based on FRC and Temporal level*/ + if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) { + REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0); + /*Set s matrix*/ + REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0); + /*Set t matrix*/ + REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0); + } + + /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ + REG_UPDATE(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL); + + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_25FRC_SEL, params->flags.FRC25, + FMT_50FRC_SEL, params->flags.FRC50, + FMT_75FRC_SEL, params->flags.FRC75); + + /*Enable bit reduction by temporal (frame modulation) dithering*/ + REG_UPDATE(FMT_BIT_DEPTH_CONTROL, + FMT_TEMPORAL_DITHER_EN, 1); +} + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +void dce110_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + uint32_t clamp_cntl_value = 0; + + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 0, + FMT_CLAMP_COLOR_FORMAT, 0); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + break; + case CLAMPING_LIMITED_RANGE_8BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 1); + break; + case CLAMPING_LIMITED_RANGE_10BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 2); + break; + case CLAMPING_LIMITED_RANGE_12BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 3); + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + /*Set clamp control*/ + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 7); + + /*set the defaults*/ + REG_SET_2(FMT_CLAMP_COMPONENT_R, 0, + FMT_CLAMP_LOWER_R, 0x10, + FMT_CLAMP_UPPER_R, 0xFEF); + + REG_SET_2(FMT_CLAMP_COMPONENT_G, 0, + FMT_CLAMP_LOWER_G, 0x10, + FMT_CLAMP_UPPER_G, 0xFEF); + + REG_SET_2(FMT_CLAMP_COMPONENT_B, 0, + FMT_CLAMP_LOWER_B, 0x10, + FMT_CLAMP_UPPER_B, 0xFEF); + break; + default: + break; + } +} + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void set_pixel_encoding( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS) + REG_UPDATE_3(FMT_CONTROL, + FMT_PIXEL_ENCODING, 0, + FMT_SUBSAMPLING_MODE, 0, + FMT_CBCR_BIT_REDUCTION_BYPASS, 0); + else + REG_UPDATE_2(FMT_CONTROL, + FMT_PIXEL_ENCODING, 0, + FMT_SUBSAMPLING_MODE, 0); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(FMT_CONTROL, + FMT_PIXEL_ENCODING, 1, + FMT_SUBSAMPLING_ORDER, 0); + } + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + REG_UPDATE_3(FMT_CONTROL, + FMT_PIXEL_ENCODING, 2, + FMT_SUBSAMPLING_MODE, 2, + FMT_CBCR_BIT_REDUCTION_BYPASS, 1); + } + +} + +void dce110_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + set_truncation(opp110, params); + set_spatial_dither(opp110, params); + set_temporal_dither(opp110, params); +} + +void dce110_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + dce110_opp_set_clamping(opp110, params); + set_pixel_encoding(opp110, params); +} + +static void program_formatter_420_memory(struct output_pixel_processor *opp) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint32_t fmt_mem_cntl_value; + + /* Program source select*/ + /* Use HW default source select for FMT_MEMORYx_CONTROL */ + /* Use that value for FMT_SRC_SELECT as well*/ + REG_GET(CONTROL, + FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value); + + REG_UPDATE(FMT_CONTROL, + FMT_SRC_SELECT, fmt_mem_cntl_value); + + /* Turn on the memory */ + REG_UPDATE(CONTROL, + FMT420_MEM0_PWR_FORCE, 0); +} + +void dce110_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + bool enable_dyn_exp = false; + + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 0, + FMT_DYNAMIC_EXP_MODE, 0); + /* From HW programming guide: + FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output + FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ + if (color_sp == COLOR_SPACE_SRGB) + enable_dyn_exp = true; + + /*00 - 10-bit -> 12-bit dynamic expansion*/ + /*01 - 8-bit -> 12-bit dynamic expansion*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (color_dpth) { + case COLOR_DEPTH_888: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_MODE, 1); + break; + case COLOR_DEPTH_101010: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_MODE, 0); + break; + case COLOR_DEPTH_121212: + break; + default: + break; + } + } +} + +static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + uint8_t counter = 10; + + /* clear previous phase lock status*/ + REG_UPDATE(FMT_CONTROL, + FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1); + + /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ + REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10); + +} + +void dce110_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + /* dithering is affected by , hence should be + * programmed afterwards */ + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_420_memory(opp); + + dce110_opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + dce110_opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_reset_dig_resync_fifo(opp); + + return; +} + +static void program_color_matrix( + struct dce110_opp *opp110, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + { + REG_SET_2(OUTPUT_CSC_C11_C12, 0, + OUTPUT_CSC_C11, tbl_entry->regval[0], + OUTPUT_CSC_C12, tbl_entry->regval[1]); + } + { + REG_SET_2(OUTPUT_CSC_C13_C14, 0, + OUTPUT_CSC_C11, tbl_entry->regval[2], + OUTPUT_CSC_C12, tbl_entry->regval[3]); + } + { + REG_SET_2(OUTPUT_CSC_C21_C22, 0, + OUTPUT_CSC_C11, tbl_entry->regval[4], + OUTPUT_CSC_C12, tbl_entry->regval[5]); + } + { + REG_SET_2(OUTPUT_CSC_C23_C24, 0, + OUTPUT_CSC_C11, tbl_entry->regval[6], + OUTPUT_CSC_C12, tbl_entry->regval[7]); + } + { + REG_SET_2(OUTPUT_CSC_C31_C32, 0, + OUTPUT_CSC_C11, tbl_entry->regval[8], + OUTPUT_CSC_C12, tbl_entry->regval[9]); + } + { + REG_SET_2(OUTPUT_CSC_C33_C34, 0, + OUTPUT_CSC_C11, tbl_entry->regval[10], + OUTPUT_CSC_C12, tbl_entry->regval[11]); + } +} + +static bool configure_graphics_mode( + struct dce110_opp *opp110, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + struct dc_context *ctx = opp110->base.ctx; + + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 4); + } else { + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 1); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 2); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 3); + break; + default: + return false; + } + } + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + break; + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 1); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YPBPR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 2); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YPBPR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 3); + break; + default: + return false; + } + + } else + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + + return true; +} + +void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix( + opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); +} + +void dce110_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file */ + program_color_matrix(opp110, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix */ + + configure_graphics_mode(opp110, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); +} + + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static const struct opp_funcs funcs = { + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce110_opp_program_fmt, + .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction +}; + +bool dce110_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce_opp_registers *regs, + const struct dce_opp_shift *opp_shift, + const struct dce_opp_mask *opp_mask) +{ + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; + + opp110->base.inst = inst; + + opp110->regs = regs; + opp110->opp_shift = opp_shift; + opp110->opp_mask = opp_mask; + + return true; +} + +void dce110_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free(FROM_DCE11_OPP(*opp)); + *opp = NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h new file mode 100644 index 000000000000..1c01a83ecc50 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -0,0 +1,418 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCE_H__ +#define __DC_OPP_DCE_H__ + +#include "dc_types.h" +#include "opp.h" +#include "core_types.h" + +#include "gamma_types.h" /* decprecated */ + +struct gamma_parameters; + +#define FROM_DCE11_OPP(opp)\ + container_of(opp, struct dce110_opp, base) + +enum dce110_opp_reg_type { + DCE110_OPP_REG_DCP = 0, + DCE110_OPP_REG_DCFE, + DCE110_OPP_REG_FMT, + + DCE110_OPP_REG_MAX +}; + +#define OPP_COMMON_REG_LIST_BASE(id) \ + SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \ + SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \ + SRI(REGAMMA_LUT_INDEX, DCP, id), \ + SRI(REGAMMA_LUT_DATA, DCP, id), \ + SRI(REGAMMA_CONTROL, DCP, id), \ + SRI(OUTPUT_CSC_C11_C12, DCP, id), \ + SRI(OUTPUT_CSC_C13_C14, DCP, id), \ + SRI(OUTPUT_CSC_C21_C22, DCP, id), \ + SRI(OUTPUT_CSC_C23_C24, DCP, id), \ + SRI(OUTPUT_CSC_C31_C32, DCP, id), \ + SRI(OUTPUT_CSC_C33_C34, DCP, id), \ + SRI(OUTPUT_CSC_CONTROL, DCP, id), \ + SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ + SRI(FMT_CONTROL, FMT, id), \ + SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI(FMT_CLAMP_CNTL, FMT, id), \ + SRI(FMT_CLAMP_COMPONENT_R, FMT, id), \ + SRI(FMT_CLAMP_COMPONENT_G, FMT, id), \ + SRI(FMT_CLAMP_COMPONENT_B, FMT, id) + +#define OPP_DCE_80_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id), \ + SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) + +#define OPP_DCE_100_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \ + SRI(DCFE_MEM_PWR_STATUS, CRTC, id), \ + SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) + +#define OPP_DCE_110_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ + SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) + +#define OPP_DCE_112_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ + SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ + SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \ + SRI(CONTROL, FMT_MEMORY, id) + +#define OPP_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ + OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + OPP_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ + OPP_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ + OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + OPP_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ + OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SRC_SELECT, mask_sh),\ + OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\ + OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_R, FMT_CLAMP_LOWER_R, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_R, FMT_CLAMP_UPPER_R, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_G, FMT_CLAMP_LOWER_G, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_G, FMT_CLAMP_UPPER_G, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_B, FMT_CLAMP_LOWER_B, mask_sh),\ + OPP_SF(FMT_CLAMP_COMPONENT_B, FMT_CLAMP_UPPER_B, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh) + +#define OPP_COMMON_MASK_SH_LIST_DCE_110(mask_sh)\ + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + +#define OPP_COMMON_MASK_SH_LIST_DCE_100(mask_sh)\ + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + +#define OPP_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ + OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\ + OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + +#define OPP_COMMON_MASK_SH_LIST_DCE_80(mask_sh)\ + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) + +#define OPP_REG_FIELD_LIST(type) \ + type DCP_REGAMMA_MEM_PWR_DIS; \ + type DCP_LUT_MEM_PWR_DIS; \ + type REGAMMA_LUT_LIGHT_SLEEP_DIS; \ + type DCP_LUT_LIGHT_SLEEP_DIS; \ + type REGAMMA_CNTLA_EXP_REGION_START; \ + type REGAMMA_CNTLA_EXP_REGION_START_SEGMENT; \ + type REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE; \ + type REGAMMA_CNTLA_EXP_REGION_END; \ + type REGAMMA_CNTLA_EXP_REGION_END_BASE; \ + type REGAMMA_CNTLA_EXP_REGION_END_SLOPE; \ + type REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET; \ + type REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS; \ + type REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET; \ + type REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS; \ + type DCP_REGAMMA_MEM_PWR_STATE; \ + type REGAMMA_LUT_MEM_PWR_STATE; \ + type REGAMMA_LUT_WRITE_EN_MASK; \ + type GRPH_REGAMMA_MODE; \ + type OUTPUT_CSC_C11; \ + type OUTPUT_CSC_C12; \ + type OUTPUT_CSC_GRPH_MODE; \ + type FMT_DYNAMIC_EXP_EN; \ + type FMT_DYNAMIC_EXP_MODE; \ + type FMT_TRUNCATE_EN; \ + type FMT_TRUNCATE_DEPTH; \ + type FMT_TRUNCATE_MODE; \ + type FMT_SPATIAL_DITHER_EN; \ + type FMT_SPATIAL_DITHER_DEPTH; \ + type FMT_SPATIAL_DITHER_MODE; \ + type FMT_TEMPORAL_DITHER_EN; \ + type FMT_TEMPORAL_DITHER_RESET; \ + type FMT_TEMPORAL_DITHER_OFFSET; \ + type FMT_TEMPORAL_DITHER_DEPTH; \ + type FMT_TEMPORAL_LEVEL; \ + type FMT_25FRC_SEL; \ + type FMT_50FRC_SEL; \ + type FMT_75FRC_SEL; \ + type FMT_HIGHPASS_RANDOM_ENABLE; \ + type FMT_FRAME_RANDOM_ENABLE; \ + type FMT_RGB_RANDOM_ENABLE; \ + type FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX; \ + type FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP; \ + type FMT_RAND_R_SEED; \ + type FMT_RAND_G_SEED; \ + type FMT_RAND_B_SEED; \ + type FMT420_MEM0_SOURCE_SEL; \ + type FMT420_MEM0_PWR_FORCE; \ + type FMT_SRC_SELECT; \ + type FMT_420_PIXEL_PHASE_LOCKED_CLEAR; \ + type FMT_420_PIXEL_PHASE_LOCKED; \ + type FMT_CLAMP_DATA_EN; \ + type FMT_CLAMP_COLOR_FORMAT; \ + type FMT_CLAMP_LOWER_R; \ + type FMT_CLAMP_UPPER_R; \ + type FMT_CLAMP_LOWER_G; \ + type FMT_CLAMP_UPPER_G; \ + type FMT_CLAMP_LOWER_B; \ + type FMT_CLAMP_UPPER_B; \ + type FMT_PIXEL_ENCODING; \ + type FMT_SUBSAMPLING_ORDER; \ + type FMT_SUBSAMPLING_MODE; \ + type FMT_CBCR_BIT_REDUCTION_BYPASS;\ + +struct dce_opp_shift { + OPP_REG_FIELD_LIST(uint8_t) +}; + +struct dce_opp_mask { + OPP_REG_FIELD_LIST(uint32_t) +}; + +struct dce_opp_registers { + uint32_t DCFE_MEM_PWR_CTRL; + uint32_t DCFE_MEM_LIGHT_SLEEP_CNTL; + uint32_t REGAMMA_CNTLA_START_CNTL; + uint32_t REGAMMA_CNTLA_SLOPE_CNTL; + uint32_t REGAMMA_CNTLA_END_CNTL1; + uint32_t REGAMMA_CNTLA_END_CNTL2; + uint32_t REGAMMA_CNTLA_REGION_0_1; + uint32_t REGAMMA_CNTLA_REGION_2_3; + uint32_t REGAMMA_CNTLA_REGION_4_5; + uint32_t REGAMMA_CNTLA_REGION_6_7; + uint32_t REGAMMA_CNTLA_REGION_8_9; + uint32_t REGAMMA_CNTLA_REGION_10_11; + uint32_t REGAMMA_CNTLA_REGION_12_13; + uint32_t REGAMMA_CNTLA_REGION_14_15; + uint32_t REGAMMA_LUT_WRITE_EN_MASK; + uint32_t REGAMMA_LUT_INDEX; + uint32_t DCFE_MEM_PWR_STATUS; + uint32_t REGAMMA_LUT_DATA; + uint32_t REGAMMA_CONTROL; + uint32_t OUTPUT_CSC_C11_C12; + uint32_t OUTPUT_CSC_C13_C14; + uint32_t OUTPUT_CSC_C21_C22; + uint32_t OUTPUT_CSC_C23_C24; + uint32_t OUTPUT_CSC_C31_C32; + uint32_t OUTPUT_CSC_C33_C34; + uint32_t OUTPUT_CSC_CONTROL; + uint32_t FMT_DYNAMIC_EXP_CNTL; + uint32_t FMT_BIT_DEPTH_CONTROL; + uint32_t FMT_CONTROL; + uint32_t FMT_DITHER_RAND_R_SEED; + uint32_t FMT_DITHER_RAND_G_SEED; + uint32_t FMT_DITHER_RAND_B_SEED; + uint32_t FMT_TEMPORAL_DITHER_PATTERN_CONTROL; + uint32_t FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX; + uint32_t FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX; + uint32_t CONTROL; + uint32_t FMT_CLAMP_CNTL; + uint32_t FMT_CLAMP_COMPONENT_R; + uint32_t FMT_CLAMP_COMPONENT_G; + uint32_t FMT_CLAMP_COMPONENT_B; +}; + +struct dce110_regamma { + struct gamma_curve arr_curve_points[16]; + struct curve_points arr_points[3]; + uint32_t hw_points_num; + struct hw_x_point *coordinates_x; + struct pwl_result_data *rgb_resulted; + + /* re-gamma curve */ + struct pwl_float_data_ex *rgb_regamma; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 256 */ + struct pixel_gamma_point *coeff128; + struct pixel_gamma_point *coeff128_oem; + /* coeff used to map user evenly distributed points + * to our hardware points (predefined) for gamma 1025 */ + struct pixel_gamma_point *coeff128_dx; + /* evenly distributed points, gamma 256 software points 0-255 */ + struct gamma_pixel *axis_x_256; + /* evenly distributed points, gamma 1025 software points 0-1025 */ + struct gamma_pixel *axis_x_1025; + /* OEM supplied gamma for regamma LUT */ + struct pwl_float_data *rgb_oem; + /* user supplied gamma */ + struct pwl_float_data *rgb_user; + uint32_t extra_points; + bool use_half_points; + struct fixed31_32 x_max1; + struct fixed31_32 x_max2; + struct fixed31_32 x_min; + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; +}; + +/* OPP RELATED */ +#define TO_DCE110_OPP(opp)\ + container_of(opp, struct dce110_opp, base) + +struct dce110_opp { + struct output_pixel_processor base; + const struct dce_opp_registers *regs; + const struct dce_opp_shift *opp_shift; + const struct dce_opp_mask *opp_mask; + struct dce110_regamma regamma; +}; + +bool dce110_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce_opp_registers *regs, + const struct dce_opp_shift *opp_shift, + const struct dce_opp_mask *opp_mask); + +void dce110_opp_destroy(struct output_pixel_processor **opp); + +/* REGAMMA RELATED */ +void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on); + +bool dce110_opp_program_regamma_pwl( + struct output_pixel_processor *opp, + const struct pwl_params *params); + +void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, + enum opp_regamma mode); + +void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry); + +void dce110_opp_set_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust); + +/* FORMATTER RELATED */ +void dce110_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params); + +void dce110_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params); + +void dce110_opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); + +void dce110_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping); + +void dce110_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c97416f7bc93..161d4eee4423 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -39,7 +39,7 @@ #include "dce110/dce110_mem_input_v.h" #include "dce110/dce110_ipp.h" #include "dce/dce_transform.h" -#include "dce110/dce110_opp.h" +#include "dce/dce_opp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" @@ -302,6 +302,29 @@ static const struct dce_stream_encoder_mask se_mask = { SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) }; +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_100_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_100(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_100(_MASK) +}; + + #define audio_regs(id)\ [id] = {\ AUD_COMMON_REG_LIST(id)\ @@ -348,35 +371,6 @@ static const struct dce110_clk_src_mask cs_mask = { #define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03 -static const struct dce110_opp_reg_offsets dce100_opp_reg_offsets[] = { -{ - .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT_CONTROL), - .dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE), - .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -} -}; - static const struct bios_registers bios_regs = { .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 }; @@ -615,8 +609,7 @@ struct link_encoder *dce100_link_encoder_create( struct output_pixel_processor *dce100_opp_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offset) + uint32_t inst) { struct dce110_opp *opp = dm_alloc(sizeof(struct dce110_opp)); @@ -625,7 +618,7 @@ struct output_pixel_processor *dce100_opp_create( return NULL; if (dce110_opp_construct(opp, - ctx, inst, offset)) + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) return &opp->base; BREAK_TO_DEBUGGER(); @@ -1052,7 +1045,7 @@ static bool construct( goto res_create_fail; } - pool->base.opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]); + pool->base.opps[i] = dce100_opp_create(ctx, i); if (pool->base.opps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile index cd7a9095fa06..9c42afcac325 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -3,8 +3,8 @@ # It provides the control and status of HW CRTC block. DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ -dce110_ipp_gamma.o dce110_opp.o dce110_opp_csc.o \ -dce110_timing_generator.o dce110_opp_formatter.o dce110_opp_regamma.o \ +dce110_ipp_gamma.o \ +dce110_timing_generator.o \ dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ dce110_resource.o \ dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c deleted file mode 100644 index 698ec2f55d0f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE11 register header files */ -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_opp.h" - -#include "gamma_types.h" - -enum { - MAX_LUT_ENTRY = 256, - MAX_NUMBER_OF_ENTRIES = 256 -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -static const struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, - .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, - .opp_set_csc_default = dce110_opp_set_csc_default, - .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode, - .opp_destroy = dce110_opp_destroy, - .opp_program_fmt = dce110_opp_program_fmt, -}; - -bool dce110_opp_construct(struct dce110_opp *opp110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets) -{ - opp110->base.funcs = &funcs; - - opp110->base.ctx = ctx; - - opp110->base.inst = inst; - - opp110->offsets = *offsets; - - return true; -} - -void dce110_opp_destroy(struct output_pixel_processor **opp) -{ - dm_free(FROM_DCE11_OPP(*opp)); - *opp = NULL; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h deleted file mode 100644 index 2fbb2415cc97..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp.h +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_OPP_DCE110_H__ -#define __DC_OPP_DCE110_H__ - -#include "dc_types.h" -#include "opp.h" -#include "core_types.h" - -#include "gamma_types.h" /* decprecated */ - -struct gamma_parameters; - -#define FROM_DCE11_OPP(opp)\ - container_of(opp, struct dce110_opp, base) - -enum dce110_opp_reg_type { - DCE110_OPP_REG_DCP = 0, - DCE110_OPP_REG_DCFE, - DCE110_OPP_REG_FMT, - - DCE110_OPP_REG_MAX -}; - -struct dce110_regamma { - struct gamma_curve arr_curve_points[16]; - struct curve_points arr_points[3]; - uint32_t hw_points_num; - struct hw_x_point *coordinates_x; - struct pwl_result_data *rgb_resulted; - - /* re-gamma curve */ - struct pwl_float_data_ex *rgb_regamma; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 256 */ - struct pixel_gamma_point *coeff128; - struct pixel_gamma_point *coeff128_oem; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 1025 */ - struct pixel_gamma_point *coeff128_dx; - /* evenly distributed points, gamma 256 software points 0-255 */ - struct gamma_pixel *axis_x_256; - /* evenly distributed points, gamma 1025 software points 0-1025 */ - struct gamma_pixel *axis_x_1025; - /* OEM supplied gamma for regamma LUT */ - struct pwl_float_data *rgb_oem; - /* user supplied gamma */ - struct pwl_float_data *rgb_user; - uint32_t extra_points; - bool use_half_points; - struct fixed31_32 x_max1; - struct fixed31_32 x_max2; - struct fixed31_32 x_min; - struct fixed31_32 divider1; - struct fixed31_32 divider2; - struct fixed31_32 divider3; -}; - -/* OPP RELATED */ -#define TO_DCE110_OPP(opp)\ - container_of(opp, struct dce110_opp, base) - -struct dce110_opp_reg_offsets { - uint32_t fmt_offset; - uint32_t fmt_mem_offset; - uint32_t dcp_offset; - uint32_t dcfe_offset; -}; - -struct dce110_opp { - struct output_pixel_processor base; - struct dce110_opp_reg_offsets offsets; - struct dce110_regamma regamma; -}; - -bool dce110_opp_construct(struct dce110_opp *opp110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets); - -void dce110_opp_destroy(struct output_pixel_processor **opp); - -/* REGAMMA RELATED */ -void dce110_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on); - -bool dce110_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params); - -void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode); - -void dce110_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); - -void dce110_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); - -/* FORMATTER RELATED */ -void dce110_opp_program_bit_depth_reduction( - struct output_pixel_processor *opp, - const struct bit_depth_reduction_params *params); - -void dce110_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params); - -void dce110_opp_set_dyn_expansion( - struct output_pixel_processor *opp, - enum dc_color_space color_sp, - enum dc_color_depth color_dpth, - enum signal_type signal); - -void dce110_opp_program_fmt( - struct output_pixel_processor *opp, - struct bit_depth_reduction_params *fmt_bit_depth, - struct clamping_and_pixel_encoding_params *clamping); - -void dce110_opp_set_clamping( - struct dce110_opp *opp110, - const struct clamping_and_pixel_encoding_params *params); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c deleted file mode 100644 index b46db202ddbb..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dce110_opp.h" -#include "basics/conversion.h" - -/* include DCE11 register header files */ -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#define DCP_REG(reg)\ - (reg + opp110->offsets.dcp_offset) - -enum { - OUTPUT_CSC_MATRIX_SIZE = 12 -}; - -static const struct out_csc_color_matrix global_color_matrix[] = { -{ COLOR_SPACE_SRGB, - { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, -{ COLOR_SPACE_SRGB_LIMITED, - { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, -{ COLOR_SPACE_YCBCR601, - { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, - 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, - 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, -/* TODO: correct values below */ -{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, - 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } -}; - -enum csc_color_mode { - /* 00 - BITS2:0 Bypass */ - CSC_COLOR_MODE_GRAPHICS_BYPASS, - /* 01 - hard coded coefficient TV RGB */ - CSC_COLOR_MODE_GRAPHICS_PREDEFINED, - /* 04 - programmable OUTPUT CSC coefficient */ - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, -}; - -static void program_color_matrix( - struct dce110_opp *opp110, - const struct out_csc_color_matrix *tbl_entry, - enum grph_color_adjust_option options) -{ - struct dc_context *ctx = opp110->base.ctx; - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[0], - OUTPUT_CSC_C11_C12, - OUTPUT_CSC_C11); - - set_reg_field_value( - value, - tbl_entry->regval[1], - OUTPUT_CSC_C11_C12, - OUTPUT_CSC_C12); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[2], - OUTPUT_CSC_C13_C14, - OUTPUT_CSC_C13); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[3], - OUTPUT_CSC_C13_C14, - OUTPUT_CSC_C14); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[4], - OUTPUT_CSC_C21_C22, - OUTPUT_CSC_C21); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[5], - OUTPUT_CSC_C21_C22, - OUTPUT_CSC_C22); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[6], - OUTPUT_CSC_C23_C24, - OUTPUT_CSC_C23); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[7], - OUTPUT_CSC_C23_C24, - OUTPUT_CSC_C24); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[8], - OUTPUT_CSC_C31_C32, - OUTPUT_CSC_C31); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[9], - OUTPUT_CSC_C31_C32, - OUTPUT_CSC_C32); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[10], - OUTPUT_CSC_C33_C34, - OUTPUT_CSC_C33); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[11], - OUTPUT_CSC_C33_C34, - OUTPUT_CSC_C34); - - dm_write_reg(ctx, addr, value); - } -} - -static bool configure_graphics_mode( - struct dce110_opp *opp110, - enum csc_color_mode config, - enum graphics_csc_adjust_type csc_adjust_type, - enum dc_color_space color_space) -{ - struct dc_context *ctx = opp110->base.ctx; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); - uint32_t value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - - if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { - if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { - set_reg_field_value( - value, - 4, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - } else { - - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - set_reg_field_value( - value, - 1, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - set_reg_field_value( - value, - 2, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - set_reg_field_value( - value, - 3, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - default: - return false; - } - } - } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - set_reg_field_value( - value, - 1, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - set_reg_field_value( - value, - 2, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - set_reg_field_value( - value, - 3, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - default: - return false; - } - - } else - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - - addr = DCP_REG(mmOUTPUT_CSC_CONTROL); - dm_write_reg(ctx, addr, value); - - return true; -} - -void dce110_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - - program_color_matrix( - opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); - - /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ - configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, - tbl_entry->color_space); -} - -void dce110_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_PREDEFINED; - - if (default_adjust->force_hw_default == false) { - const struct out_csc_color_matrix *elm; - /* currently parameter not in use */ - enum grph_color_adjust_option option = - GRPH_COLOR_MATRIX_HW_DEFAULT; - uint32_t i; - /* - * HW default false we program locally defined matrix - * HW default true we use predefined hw matrix and we - * do not need to program matrix - * OEM wants the HW default via runtime parameter. - */ - option = GRPH_COLOR_MATRIX_SW; - - for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { - elm = &global_color_matrix[i]; - if (elm->color_space != default_adjust->out_color_space) - continue; - /* program the matrix with default values from this - * file */ - program_color_matrix(opp110, elm, option); - config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - break; - } - } - - /* configure the what we programmed : - * 1. Default values from this file - * 2. Use hardware default from ROM_A and we do not need to program - * matrix */ - - configure_graphics_mode(opp110, config, - default_adjust->csc_adjust_type, - default_adjust->out_color_space); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c index 975466f6e424..6995a3de7564 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -24,7 +24,7 @@ */ #include "dm_services.h" -#include "dce110_opp.h" +#include "dce/dce_opp.h" #include "basics/conversion.h" /* include DCE11 register header files */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c deleted file mode 100644 index eac20775c23f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_formatter.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_opp.h" - -#define FMT_REG(reg)\ - (reg + opp110->offsets.fmt_offset) -/** - * set_truncation - * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp - * 2) enable truncation - * 3) HW remove 12bit FMT support for DCE11 power saving reason. - */ -static void set_truncation( - struct dce110_opp *opp110, - const struct bit_depth_reduction_params *params) -{ - uint32_t value = 0; - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - - /*Disable truncation*/ - value = dm_read_reg(opp110->base.ctx, addr); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); - - dm_write_reg(opp110->base.ctx, addr, value); - - /* no 10bpc trunc on DCE11*/ - if (params->flags.TRUNCATE_ENABLED == 0 || - params->flags.TRUNCATE_DEPTH == 2) - return; - - /*Set truncation depth and Enable truncation*/ - set_reg_field_value(value, 1, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); - set_reg_field_value(value, params->flags.TRUNCATE_MODE, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); - set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); - - dm_write_reg(opp110->base.ctx, addr, value); - -} - -/** - * set_spatial_dither - * 1) set spatial dithering mode: pattern of seed - * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp - * 3) set random seed - * 4) set random mode - * lfsr is reset every frame or not reset - * RGB dithering method - * 0: RGB data are all dithered with x^28+x^3+1 - * 1: R data is dithered with x^28+x^3+1 - * G data is dithered with x^28+X^9+1 - * B data is dithered with x^28+x^13+1 - * enable high pass filter or not - * 5) enable spatical dithering - */ -static void set_spatial_dither( - struct dce110_opp *opp110, - const struct bit_depth_reduction_params *params) -{ - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - uint32_t depth_cntl_value = 0; - uint32_t fmt_cntl_value = 0; - uint32_t dither_r_value = 0; - uint32_t dither_g_value = 0; - uint32_t dither_b_value = 0; - - /*Disable spatial (random) dithering*/ - depth_cntl_value = dm_read_reg(opp110->base.ctx, addr); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE); - - dm_write_reg(opp110->base.ctx, addr, depth_cntl_value); - - /* no 10bpc on DCE11*/ - if (params->flags.SPATIAL_DITHER_ENABLED == 0 || - params->flags.SPATIAL_DITHER_DEPTH == 2) - return; - - addr = FMT_REG(mmFMT_CONTROL); - fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); - /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ - if (params->flags.FRAME_RANDOM == 1) { - if (params->flags.SPATIAL_DITHER_DEPTH == 0 || - params->flags.SPATIAL_DITHER_DEPTH == 1) { - set_reg_field_value(fmt_cntl_value, 15, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); - set_reg_field_value(fmt_cntl_value, 2, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); - } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { - set_reg_field_value(fmt_cntl_value, 3, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); - set_reg_field_value(fmt_cntl_value, 1, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); - } else - return; - } else { - set_reg_field_value(fmt_cntl_value, 0, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX); - set_reg_field_value(fmt_cntl_value, 0, - FMT_CONTROL, - FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP); - } - - dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); - - /*Set seed for random values for - * spatial dithering for R,G,B channels*/ - addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED); - set_reg_field_value(dither_r_value, params->r_seed_value, - FMT_DITHER_RAND_R_SEED, - FMT_RAND_R_SEED); - dm_write_reg(opp110->base.ctx, addr, dither_r_value); - - addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED); - set_reg_field_value(dither_g_value, - params->g_seed_value, - FMT_DITHER_RAND_G_SEED, - FMT_RAND_G_SEED); - dm_write_reg(opp110->base.ctx, addr, dither_g_value); - - addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED); - set_reg_field_value(dither_b_value, params->b_seed_value, - FMT_DITHER_RAND_B_SEED, - FMT_RAND_B_SEED); - dm_write_reg(opp110->base.ctx, addr, dither_b_value); - - /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero - * offset for the R/Cr channel, lower 4LSB - * is forced to zeros. Typically set to 0 - * RGB and 0x80000 YCbCr. - */ - /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero - * offset for the G/Y channel, lower 4LSB is - * forced to zeros. Typically set to 0 RGB - * and 0x80000 YCbCr. - */ - /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero - * offset for the B/Cb channel, lower 4LSB is - * forced to zeros. Typically set to 0 RGB and - * 0x80000 YCbCr. - */ - - /*Set spatial dithering bit depth*/ - set_reg_field_value(depth_cntl_value, - params->flags.SPATIAL_DITHER_DEPTH, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_DEPTH); - - /* Set spatial dithering mode - * (default is Seed patterrn AAAA...) - */ - set_reg_field_value(depth_cntl_value, - params->flags.SPATIAL_DITHER_MODE, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_MODE); - - /*Reset only at startup*/ - set_reg_field_value(depth_cntl_value, - params->flags.FRAME_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_FRAME_RANDOM_ENABLE); - - /*Set RGB data dithered with x^28+x^3+1*/ - set_reg_field_value(depth_cntl_value, - params->flags.RGB_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_RGB_RANDOM_ENABLE); - - /*Disable High pass filter*/ - set_reg_field_value(depth_cntl_value, - params->flags.HIGHPASS_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_HIGHPASS_RANDOM_ENABLE); - - /*Enable spatial dithering*/ - set_reg_field_value(depth_cntl_value, - 1, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_EN); - - addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - dm_write_reg(opp110->base.ctx, addr, depth_cntl_value); - -} - -/** - * SetTemporalDither (Frame Modulation) - * 1) set temporal dither depth - * 2) select pattern: from hard-coded pattern or programmable pattern - * 3) select optimized strips for BGR or RGB LCD sub-pixel - * 4) set s matrix - * 5) set t matrix - * 6) set grey level for 0.25, 0.5, 0.75 - * 7) enable temporal dithering - */ -static void set_temporal_dither( - struct dce110_opp *opp110, - const struct bit_depth_reduction_params *params) -{ - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - uint32_t value; - - /*Disable temporal (frame modulation) dithering first*/ - value = dm_read_reg(opp110->base.ctx, addr); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_EN); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_RESET); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_OFFSET); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_DEPTH); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_LEVEL); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_25FRC_SEL); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_50FRC_SEL); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_75FRC_SEL); - - dm_write_reg(opp110->base.ctx, addr, value); - - /* no 10bpc dither on DCE11*/ - if (params->flags.FRAME_MODULATION_ENABLED == 0 || - params->flags.FRAME_MODULATION_DEPTH == 2) - return; - - /* Set temporal dithering depth*/ - set_reg_field_value(value, - params->flags.FRAME_MODULATION_DEPTH, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_DEPTH); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_RESET); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_OFFSET); - - /*Select legacy pattern based on FRC and Temporal level*/ - addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL); - dm_write_reg(opp110->base.ctx, addr, 0); - /*Set s matrix*/ - addr = FMT_REG( - mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); - dm_write_reg(opp110->base.ctx, addr, 0); - /*Set t matrix*/ - addr = FMT_REG( - mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); - dm_write_reg(opp110->base.ctx, addr, 0); - - /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ - set_reg_field_value(value, - params->flags.TEMPORAL_LEVEL, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_LEVEL); - - set_reg_field_value(value, - params->flags.FRC25, - FMT_BIT_DEPTH_CONTROL, - FMT_25FRC_SEL); - - set_reg_field_value(value, - params->flags.FRC50, - FMT_BIT_DEPTH_CONTROL, - FMT_50FRC_SEL); - - set_reg_field_value(value, - params->flags.FRC75, - FMT_BIT_DEPTH_CONTROL, - FMT_75FRC_SEL); - - /*Enable bit reduction by temporal (frame modulation) dithering*/ - set_reg_field_value(value, - 1, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_EN); - - addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - dm_write_reg(opp110->base.ctx, addr, value); - -} - -/** - * Set Clamping - * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) - * 1 for 8 bpc - * 2 for 10 bpc - * 3 for 12 bpc - * 7 for programable - * 2) Enable clamp if Limited range requested - */ -void dce110_opp_set_clamping( - struct dce110_opp *opp110, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t clamp_cntl_value = 0; - uint32_t red_clamp_value = 0; - uint32_t green_clamp_value = 0; - uint32_t blue_clamp_value = 0; - uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); - - clamp_cntl_value = dm_read_reg(opp110->base.ctx, addr); - - set_reg_field_value(clamp_cntl_value, - 0, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 0, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - switch (params->clamping_level) { - case CLAMPING_FULL_RANGE: - break; - - case CLAMPING_LIMITED_RANGE_8BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - - case CLAMPING_LIMITED_RANGE_10BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 2, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - case CLAMPING_LIMITED_RANGE_12BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 3, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 7, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - /*set the defaults*/ - set_reg_field_value(red_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_R, - FMT_CLAMP_LOWER_R); - - set_reg_field_value(red_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_R, - FMT_CLAMP_UPPER_R); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R); - dm_write_reg(opp110->base.ctx, addr, red_clamp_value); - - set_reg_field_value(green_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_G, - FMT_CLAMP_LOWER_G); - - set_reg_field_value(green_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_G, - FMT_CLAMP_UPPER_G); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G); - dm_write_reg(opp110->base.ctx, addr, green_clamp_value); - - set_reg_field_value(blue_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_B, - FMT_CLAMP_LOWER_B); - - set_reg_field_value(blue_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_B, - FMT_CLAMP_UPPER_B); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B); - dm_write_reg(opp110->base.ctx, addr, blue_clamp_value); - - break; - - default: - break; - } - - addr = FMT_REG(mmFMT_CLAMP_CNTL); - /*Set clamp control*/ - dm_write_reg(opp110->base.ctx, addr, clamp_cntl_value); - -} - -/** - * set_pixel_encoding - * - * Set Pixel Encoding - * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly - * 1: YCbCr 4:2:2 - */ -static void set_pixel_encoding( - struct dce110_opp *opp110, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t fmt_cntl_value; - uint32_t addr = FMT_REG(mmFMT_CONTROL); - - /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ - fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); - - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - set_reg_field_value(fmt_cntl_value, - 1, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /*00 - Pixels drop mode ,01 - Pixels average mode*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_MODE); - - /*00 - Cb before Cr ,01 - Cr before Cb*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_ORDER); - } - dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); - -} - -void dce110_opp_program_bit_depth_reduction( - struct output_pixel_processor *opp, - const struct bit_depth_reduction_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - set_truncation(opp110, params); - set_spatial_dither(opp110, params); - set_temporal_dither(opp110, params); -} - -void dce110_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - dce110_opp_set_clamping(opp110, params); - set_pixel_encoding(opp110, params); -} - -void dce110_opp_set_dyn_expansion( - struct output_pixel_processor *opp, - enum dc_color_space color_sp, - enum dc_color_depth color_dpth, - enum signal_type signal) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint32_t value; - bool enable_dyn_exp = false; - uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); - - value = dm_read_reg(opp->ctx, addr); - - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - - /* From HW programming guide: - FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output - FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ - if (color_sp == COLOR_SPACE_SRGB) - enable_dyn_exp = true; - - /*00 - 10-bit -> 12-bit dynamic expansion*/ - /*01 - 8-bit -> 12-bit dynamic expansion*/ - if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { - switch (color_dpth) { - case COLOR_DEPTH_888: - set_reg_field_value(value, enable_dyn_exp ? 1:0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 1, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - break; - case COLOR_DEPTH_101010: - set_reg_field_value(value, enable_dyn_exp ? 1:0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - break; - case COLOR_DEPTH_121212: - break; - default: - break; - } - } - - dm_write_reg(opp->ctx, addr, value); -} - -void dce110_opp_program_fmt( - struct output_pixel_processor *opp, - struct bit_depth_reduction_params *fmt_bit_depth, - struct clamping_and_pixel_encoding_params *clamping) -{ - /* dithering is affected by , hence should be - * programmed afterwards */ - dce110_opp_program_bit_depth_reduction( - opp, - fmt_bit_depth); - - dce110_opp_program_clamping_and_pixel_encoding( - opp, - clamping); - - return; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c deleted file mode 100644 index 62051abcfe2f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE11 register header files */ -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_opp.h" -#include "gamma_types.h" - -#define DCP_REG(reg)\ - (reg + opp110->offsets.dcp_offset) - -#define DCFE_REG(reg)\ - (reg + opp110->offsets.dcfe_offset) - -enum { - MAX_PWL_ENTRY = 128, - MAX_REGIONS_NUMBER = 16 - -}; - -/* - ***************************************************************************** - * Function: regamma_config_regions_and_segments - * - * build regamma curve by using predefined hw points - * uses interface parameters ,like EDID coeff. - * - * @param : parameters interface parameters - * @return void - * - * @note - * - * @see - * - ***************************************************************************** - */ -static void regamma_config_regions_and_segments( - struct dce110_opp *opp110, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - uint32_t value = 0; - - { - set_reg_field_value( - value, - params->arr_points[0].custom_float_x, - REGAMMA_CNTLA_START_CNTL, - REGAMMA_CNTLA_EXP_REGION_START); - - set_reg_field_value( - value, - 0, - REGAMMA_CNTLA_START_CNTL, - REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_START_CNTL), - value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[0].custom_float_slope, - REGAMMA_CNTLA_SLOPE_CNTL, - REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[1].custom_float_x, - REGAMMA_CNTLA_END_CNTL1, - REGAMMA_CNTLA_EXP_REGION_END); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[2].custom_float_slope, - REGAMMA_CNTLA_END_CNTL2, - REGAMMA_CNTLA_EXP_REGION_END_BASE); - - set_reg_field_value( - value, - params->arr_points[1].custom_float_y, - REGAMMA_CNTLA_END_CNTL2, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); - } - - curve = params->arr_curve_points; - - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); - - dm_write_reg( - opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_0_1), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_2_3), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_4_5), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_6_7), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_8_9), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_10_11), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_12_13), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), - value); - } -} - -static void program_pwl( - struct dce110_opp *opp110, - const struct pwl_params *params) -{ - uint32_t value; - - { - uint8_t max_tries = 10; - uint8_t counter = 0; - - /* Power on LUT memory */ - value = dm_read_reg(opp110->base.ctx, - DCFE_REG(mmDCFE_MEM_PWR_CTRL)); - - set_reg_field_value( - value, - 1, - DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS); - - dm_write_reg(opp110->base.ctx, - DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); - - while (counter < max_tries) { - value = - dm_read_reg( - opp110->base.ctx, - DCFE_REG(mmDCFE_MEM_PWR_STATUS)); - - if (get_reg_field_value( - value, - DCFE_MEM_PWR_STATUS, - DCP_REGAMMA_MEM_PWR_STATE) == 0) - break; - - ++counter; - } - - if (counter == max_tries) { - dm_logger_write(opp110->base.ctx->logger, LOG_WARNING, - "%s: regamma lut was not powered on " - "in a timely manner," - " programming still proceeds\n", - __func__); - } - } - - value = 0; - - set_reg_field_value( - value, - 7, - REGAMMA_LUT_WRITE_EN_MASK, - REGAMMA_LUT_WRITE_EN_MASK); - - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); - dm_write_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_LUT_INDEX), 0); - - /* Program REGAMMA_LUT_DATA */ - { - const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); - - uint32_t i = 0; - - const struct pwl_result_data *rgb = params->rgb_resulted; - - while (i != params->hw_points_num) { - dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); - dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); - dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); - - dm_write_reg(opp110->base.ctx, addr, - rgb->delta_red_reg); - dm_write_reg(opp110->base.ctx, addr, - rgb->delta_green_reg); - dm_write_reg(opp110->base.ctx, addr, - rgb->delta_blue_reg); - - ++rgb; - ++i; - } - } - - /* we are done with DCP LUT memory; re-enable low power mode */ - value = dm_read_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL)); - - set_reg_field_value( - value, - 0, - DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS); - - dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); -} - -bool dce110_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - /* Setup regions */ - regamma_config_regions_and_segments(opp110, params); - - /* Program PWL */ - program_pwl(opp110, params); - - return true; -} - -void dce110_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - uint32_t value = - dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL)); - - set_reg_field_value( - value, - power_on, - DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS); - - set_reg_field_value( - value, - power_on, - DCFE_MEM_PWR_CTRL, - DCP_LUT_MEM_PWR_DIS); - - dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); -} - -void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint32_t value = dm_read_reg(opp110->base.ctx, - DCP_REG(mmREGAMMA_CONTROL)); - - set_reg_field_value( - value, - mode, - REGAMMA_CONTROL, - GRPH_REGAMMA_MODE); - - dm_write_reg(opp110->base.ctx, DCP_REG(mmREGAMMA_CONTROL), - value); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 3b3a9175b2c3..81fcbc52e4ab 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -29,7 +29,7 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" -#include "dce110_opp.h" +#include "dce/dce_opp.h" #include "gamma_types.h" static void power_on_lut(struct output_pixel_processor *opp, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 4b32397529ec..dfd63a71d214 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -29,7 +29,7 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" -#include "dce110_opp.h" +#include "dce/dce_opp.h" #include "dce110_opp_v.h" #include "gamma_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index fa601f7f0b5a..d4e1ca933b40 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -43,7 +43,7 @@ #include "dce110/dce110_ipp.h" #include "dce/dce_transform.h" #include "dce110/dce110_transform_v.h" -#include "dce110/dce110_opp.h" +#include "dce/dce_opp.h" #include "dce110/dce110_opp_v.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" @@ -283,6 +283,28 @@ static const struct dce_stream_encoder_mask se_mask = { SE_COMMON_MASK_SH_LIST_DCE110(_MASK) }; +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_110_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_110(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_110(_MASK) +}; + #define audio_regs(id)\ [id] = {\ AUD_COMMON_REG_LIST(id)\ @@ -307,34 +329,7 @@ static const struct dce_aduio_mask audio_mask = { }; /* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */ -static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = { -{ - .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -} -}; + #define clk_src_regs(id)\ [id] = {\ @@ -603,8 +598,7 @@ struct link_encoder *dce110_link_encoder_create( static struct output_pixel_processor *dce110_opp_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets) + uint32_t inst) { struct dce110_opp *opp = dm_alloc(sizeof(struct dce110_opp)); @@ -613,7 +607,7 @@ static struct output_pixel_processor *dce110_opp_create( return NULL; if (dce110_opp_construct(opp, - ctx, inst, offsets)) + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) return &opp->base; BREAK_TO_DEBUGGER(); @@ -1329,7 +1323,7 @@ static bool construct( goto res_create_fail; } - pool->base.opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]); + pool->base.opps[i] = dce110_opp_create(ctx, i); if (pool->base.opps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile index 34fba0730bed..2d536fbc60c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile @@ -3,8 +3,7 @@ # It provides the control and status of HW CRTC block. DCE112 = dce112_compressor.o dce112_hw_sequencer.o \ -dce112_resource.o dce112_mem_input.o dce112_opp_formatter.o \ -dce112_opp.o +dce112_resource.o dce112_mem_input.o AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112)) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c deleted file mode 100644 index 23c2d1086b3b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE11 register header files */ -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -#include "dce112_opp.h" - -#include "gamma_types.h" - -enum { - MAX_LUT_ENTRY = 256, - MAX_NUMBER_OF_ENTRIES = 256 -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -static struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, - .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, - .opp_set_csc_default = dce110_opp_set_csc_default, - .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode, - .opp_destroy = dce110_opp_destroy, - .opp_program_fmt = dce112_opp_program_fmt, - .opp_program_bit_depth_reduction = - dce110_opp_program_bit_depth_reduction -}; - -bool dce112_opp_construct(struct dce110_opp *opp110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets) -{ - opp110->base.funcs = &funcs; - - opp110->base.ctx = ctx; - - opp110->base.inst = inst; - - opp110->offsets = *offsets; - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h deleted file mode 100644 index 9443b87776c6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_OPP_DCE112_H__ -#define __DC_OPP_DCE112_H__ - -#include "dc_types.h" -#include "opp.h" -#include "../dce110/dce110_opp.h" -#include "core_types.h" - -void dce112_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params); - -void dce112_opp_program_fmt( - struct output_pixel_processor *opp, - struct bit_depth_reduction_params *fmt_bit_depth, - struct clamping_and_pixel_encoding_params *clamping); - -bool dce112_opp_construct(struct dce110_opp *opp110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offsets); - - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c deleted file mode 100644 index 2d9072138834..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_opp_formatter.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -#include "dce112_opp.h" - -#define FMT_REG(reg)\ - (reg + opp110->offsets.fmt_offset) -#define FMT_MEM_REG(reg)\ - (reg + opp110->offsets.fmt_mem_offset) - -/** - * Set Clamping - * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) - * 1 for 8 bpc - * 2 for 10 bpc - * 3 for 12 bpc - * 7 for programable - * 2) Enable clamp if Limited range requested - */ - -/** - * set_pixel_encoding - * - * Set Pixel Encoding - * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly - * 1: YCbCr 4:2:2 - * 2: YCbCr 4:2:0 - */ -static void set_pixel_encoding( - struct dce110_opp *opp110, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t fmt_cntl_value; - uint32_t addr = FMT_REG(mmFMT_CONTROL); - - /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ - fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr); - - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /*00 - Pixels drop mode HW default*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_MODE); - - /* By default no bypass*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_CBCR_BIT_REDUCTION_BYPASS); - - if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - set_reg_field_value(fmt_cntl_value, - 1, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /*00 - Cb before Cr ,01 - Cr before Cb*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_ORDER); - } - - if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { - set_reg_field_value(fmt_cntl_value, - 2, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /* 02 - Subsampling mode, 3 taps*/ - set_reg_field_value(fmt_cntl_value, - 2, - FMT_CONTROL, - FMT_SUBSAMPLING_MODE); - - /* 00 - Enable CbCr bit reduction bypass to preserve precision*/ - set_reg_field_value(fmt_cntl_value, - 1, - FMT_CONTROL, - FMT_CBCR_BIT_REDUCTION_BYPASS); - } - dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value); - -} - -void dce112_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - dce110_opp_set_clamping(opp110, params); - set_pixel_encoding(opp110, params); -} - -static void program_formatter_420_memory(struct output_pixel_processor *opp) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint32_t fmt_cntl_value; - uint32_t fmt_mem_cntl_value; - uint32_t fmt_cntl_addr = FMT_REG(mmFMT_CONTROL); - uint32_t fmt_mem_cntl_addr = FMT_MEM_REG(mmFMT_MEMORY0_CONTROL); - - fmt_mem_cntl_value = dm_read_reg(opp110->base.ctx, fmt_mem_cntl_addr); - fmt_cntl_value = dm_read_reg(opp110->base.ctx, fmt_cntl_addr); - /* Program source select*/ - /* Use HW default source select for FMT_MEMORYx_CONTROL */ - /* Use that value for FMT_SRC_SELECT as well*/ - set_reg_field_value(fmt_cntl_value, - get_reg_field_value(fmt_mem_cntl_value, FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL), - FMT_CONTROL, - FMT_SRC_SELECT); - dm_write_reg(opp110->base.ctx, fmt_cntl_addr, fmt_cntl_value); - - /* Turn on the memory */ - set_reg_field_value(fmt_mem_cntl_value, - 0, - FMT_MEMORY0_CONTROL, - FMT420_MEM0_PWR_FORCE); - dm_write_reg(opp110->base.ctx, fmt_mem_cntl_addr, fmt_mem_cntl_value); -} - -static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint32_t value; - uint32_t addr = FMT_REG(mmFMT_CONTROL); - uint8_t counter = 10; - - - value = dm_read_reg(opp110->base.ctx, addr); - - /* clear previous phase lock status*/ - set_reg_field_value(value, - 1, - FMT_CONTROL, - FMT_420_PIXEL_PHASE_LOCKED_CLEAR); - dm_write_reg(opp110->base.ctx, addr, value); - - /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ - while (counter > 0) { - value = dm_read_reg(opp110->base.ctx, addr); - - if (get_reg_field_value( - value, - FMT_CONTROL, - FMT_420_PIXEL_PHASE_LOCKED) == 1) - break; - - msleep(10); - counter--; - } - - if (counter == 0) - dm_logger_write(opp->ctx->logger, LOG_ERROR, - "%s:opp program formattter reset dig resync info time out.\n", - __func__); -} - -void dce112_opp_program_fmt( - struct output_pixel_processor *opp, - struct bit_depth_reduction_params *fmt_bit_depth, - struct clamping_and_pixel_encoding_params *clamping) -{ - /* dithering is affected by , hence should be - * programmed afterwards */ - - if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) - program_formatter_420_memory(opp); - - dce110_opp_program_bit_depth_reduction( - opp, - fmt_bit_depth); - - dce112_opp_program_clamping_and_pixel_encoding( - opp, - clamping); - - if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) - program_formatter_reset_dig_resync_fifo(opp); - - return; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 85d8b31acd02..2711893b71e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -39,7 +39,7 @@ #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" #include "dce/dce_audio.h" -#include "dce112/dce112_opp.h" +#include "dce/dce_opp.h" #include "dce110/dce110_ipp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" @@ -306,6 +306,28 @@ static const struct dce_stream_encoder_mask se_mask = { SE_COMMON_MASK_SH_LIST_DCE112(_MASK) }; +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_112_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + #define audio_regs(id)\ [id] = {\ AUD_COMMON_REG_LIST(id)\ @@ -328,42 +350,6 @@ static const struct dce_aduio_mask audio_mask = { AUD_COMMON_MASK_SH_LIST(_MASK) }; - -static const struct dce110_opp_reg_offsets dce112_opp_reg_offsets[] = { -{ - .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY0_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY1_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY2_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY3_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY4_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .fmt_mem_offset = (mmFMT_MEMORY5_CONTROL - mmFMT_MEMORY0_CONTROL), - .dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL), - .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -} -}; - #define clk_src_regs(index, id)\ [index] = {\ CS_COMMON_REG_LIST_DCE_112(id),\ @@ -631,8 +617,7 @@ void dce112_ipp_destroy(struct input_pixel_processor **ipp) struct output_pixel_processor *dce112_opp_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_opp_reg_offsets *offset) + uint32_t inst) { struct dce110_opp *opp = dm_alloc(sizeof(struct dce110_opp)); @@ -640,8 +625,8 @@ struct output_pixel_processor *dce112_opp_create( if (!opp) return NULL; - if (dce112_opp_construct(opp, - ctx, inst, offset)) + if (dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) return &opp->base; BREAK_TO_DEBUGGER(); @@ -1381,8 +1366,7 @@ static bool construct( pool->base.opps[i] = dce112_opp_create( ctx, - i, - &dce112_opp_reg_offsets[i]); + i); if (pool->base.opps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 9979b8441a8d..0261d1bfccb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -2,9 +2,8 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE80 = dce80_ipp.o dce80_ipp_gamma.o dce80_opp.o \ - dce80_opp_formatter.o dce80_opp_regamma.o \ - dce80_timing_generator.o dce80_opp_csc.o\ +DCE80 = dce80_ipp.o dce80_ipp_gamma.o \ + dce80_timing_generator.o \ dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ dce80_resource.o diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c deleted file mode 100644 index b69e8a5d844d..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE8 register header files */ -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_opp.h" - -#define FROM_OPP(opp)\ - container_of(opp, struct dce80_opp, base) - -enum { - MAX_LUT_ENTRY = 256, - MAX_NUMBER_OF_ENTRIES = 256 -}; - -static const struct dce80_opp_reg_offsets reg_offsets[] = { -{ - .fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ .fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -}, -{ - .fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL), - .crtc_offset = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), - .dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), -} -}; - -static const struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce80_opp_power_on_regamma_lut, - .opp_set_csc_adjustment = dce80_opp_set_csc_adjustment, - .opp_set_csc_default = dce80_opp_set_csc_default, - .opp_set_dyn_expansion = dce80_opp_set_dyn_expansion, - .opp_program_regamma_pwl = dce80_opp_program_regamma_pwl, - .opp_set_regamma_mode = dce80_opp_set_regamma_mode, - .opp_destroy = dce80_opp_destroy, - .opp_program_fmt = dce110_opp_program_fmt, -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce80_opp_construct(struct dce80_opp *opp80, - struct dc_context *ctx, - uint32_t inst) -{ - if (inst >= ARRAY_SIZE(reg_offsets)) - return false; - - opp80->base.funcs = &funcs; - - opp80->base.ctx = ctx; - - opp80->base.inst = inst; - - opp80->offsets = reg_offsets[inst]; - - return true; -} - -void dce80_opp_destroy(struct output_pixel_processor **opp) -{ - dm_free(FROM_OPP(*opp)); - *opp = NULL; -} - -struct output_pixel_processor *dce80_opp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce80_opp *opp = - dm_alloc(sizeof(struct dce80_opp)); - - if (!opp) - return NULL; - - if (dce80_opp_construct(opp, - ctx, inst)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - dm_free(opp); - return NULL; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h deleted file mode 100644 index 965cce37f7e3..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp.h +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_OPP_DCE80_H__ -#define __DC_OPP_DCE80_H__ - -#include "dc_types.h" -#include "opp.h" -#include "gamma_types.h" -#include "../dce110/dce110_opp.h" - -struct gamma_parameters; - -struct dce80_regamma { - struct gamma_curve arr_curve_points[16]; - struct curve_points arr_points[3]; - uint32_t hw_points_num; - struct hw_x_point *coordinates_x; - struct pwl_result_data *rgb_resulted; - - /* re-gamma curve */ - struct pwl_float_data_ex *rgb_regamma; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 256 */ - struct pixel_gamma_point *coeff128; - struct pixel_gamma_point *coeff128_oem; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 1025 */ - struct pixel_gamma_point *coeff128_dx; - /* evenly distributed points, gamma 256 software points 0-255 */ - struct gamma_pixel *axis_x_256; - /* evenly distributed points, gamma 1025 software points 0-1025 */ - struct gamma_pixel *axis_x_1025; - /* OEM supplied gamma for regamma LUT */ - struct pwl_float_data *rgb_oem; - /* user supplied gamma */ - struct pwl_float_data *rgb_user; - uint32_t extra_points; - bool use_half_points; - struct fixed31_32 x_max1; - struct fixed31_32 x_max2; - struct fixed31_32 x_min; - struct fixed31_32 divider1; - struct fixed31_32 divider2; - struct fixed31_32 divider3; -}; - -/* OPP RELATED */ -#define TO_DCE80_OPP(opp)\ - container_of(opp, struct dce80_opp, base) - -struct dce80_opp_reg_offsets { - uint32_t fmt_offset; - uint32_t dcp_offset; - uint32_t crtc_offset; -}; - -struct dce80_opp { - struct output_pixel_processor base; - struct dce80_opp_reg_offsets offsets; - struct dce80_regamma regamma; -}; - -bool dce80_opp_construct(struct dce80_opp *opp80, - struct dc_context *ctx, - uint32_t inst); - -void dce80_opp_destroy(struct output_pixel_processor **opp); - -struct output_pixel_processor *dce80_opp_create( - struct dc_context *ctx, - uint32_t inst); - -/* REGAMMA RELATED */ -void dce80_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on); - -bool dce80_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *pamras); - -void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode); - -void dce80_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); - -void dce80_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); - -/* FORMATTER RELATED */ -void dce80_opp_program_bit_depth_reduction( - struct output_pixel_processor *opp, - const struct bit_depth_reduction_params *params); - -void dce80_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params); - -void dce80_opp_set_dyn_expansion( - struct output_pixel_processor *opp, - enum dc_color_space color_sp, - enum dc_color_depth color_dpth, - enum signal_type signal); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c deleted file mode 100644 index bdb9e0a77982..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_csc.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce80_opp.h" -#include "basics/conversion.h" - -/* include DCE8 register header files */ -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#define DCP_REG(reg)\ - (reg + opp80->offsets.dcp_offset) - -enum { - OUTPUT_CSC_MATRIX_SIZE = 12 -}; - -static const struct out_csc_color_matrix global_color_matrix[] = { -{ COLOR_SPACE_SRGB, - { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, -{ COLOR_SPACE_SRGB_LIMITED, - { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, -{ COLOR_SPACE_YCBCR601, - { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, - 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, - 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, -/* TODO: correct values below */ -{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, - 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } -}; - -enum csc_color_mode { - /* 00 - BITS2:0 Bypass */ - CSC_COLOR_MODE_GRAPHICS_BYPASS, - /* 01 - hard coded coefficient TV RGB */ - CSC_COLOR_MODE_GRAPHICS_PREDEFINED, - /* 04 - programmable OUTPUT CSC coefficient */ - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, -}; - -static void program_color_matrix( - struct dce80_opp *opp80, - const struct out_csc_color_matrix *tbl_entry, - enum grph_color_adjust_option options) -{ - struct dc_context *ctx = opp80->base.ctx; - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[0], - OUTPUT_CSC_C11_C12, - OUTPUT_CSC_C11); - - set_reg_field_value( - value, - tbl_entry->regval[1], - OUTPUT_CSC_C11_C12, - OUTPUT_CSC_C12); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[2], - OUTPUT_CSC_C13_C14, - OUTPUT_CSC_C13); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[3], - OUTPUT_CSC_C13_C14, - OUTPUT_CSC_C14); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[4], - OUTPUT_CSC_C21_C22, - OUTPUT_CSC_C21); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[5], - OUTPUT_CSC_C21_C22, - OUTPUT_CSC_C22); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[6], - OUTPUT_CSC_C23_C24, - OUTPUT_CSC_C23); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[7], - OUTPUT_CSC_C23_C24, - OUTPUT_CSC_C24); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[8], - OUTPUT_CSC_C31_C32, - OUTPUT_CSC_C31); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[9], - OUTPUT_CSC_C31_C32, - OUTPUT_CSC_C32); - - dm_write_reg(ctx, addr, value); - } - { - uint32_t value = 0; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34); - /* fixed S2.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[10], - OUTPUT_CSC_C33_C34, - OUTPUT_CSC_C33); - /* fixed S0.13 format */ - set_reg_field_value( - value, - tbl_entry->regval[11], - OUTPUT_CSC_C33_C34, - OUTPUT_CSC_C34); - - dm_write_reg(ctx, addr, value); - } -} - -static bool configure_graphics_mode( - struct dce80_opp *opp80, - enum csc_color_mode config, - enum graphics_csc_adjust_type csc_adjust_type, - enum dc_color_space color_space) -{ - struct dc_context *ctx = opp80->base.ctx; - uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL); - uint32_t value = dm_read_reg(ctx, addr); - - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - - if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { - if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { - set_reg_field_value( - value, - 4, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - } else { - - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - set_reg_field_value( - value, - 1, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - set_reg_field_value( - value, - 2, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - set_reg_field_value( - value, - 3, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - default: - return false; - } - } - } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - set_reg_field_value( - value, - 1, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - set_reg_field_value( - value, - 2, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - set_reg_field_value( - value, - 3, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - break; - default: - return false; - } - - } else - /* by pass */ - set_reg_field_value( - value, - 0, - OUTPUT_CSC_CONTROL, - OUTPUT_CSC_GRPH_MODE); - - addr = DCP_REG(mmOUTPUT_CSC_CONTROL); - dm_write_reg(ctx, addr, value); - - return true; -} - -void dce80_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - - program_color_matrix(opp80, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); - - /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ - configure_graphics_mode(opp80, config, GRAPHICS_CSC_ADJUST_TYPE_SW, - tbl_entry->color_space); -} - -void dce80_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_PREDEFINED; - - if (default_adjust->force_hw_default == false) { - const struct out_csc_color_matrix *elm; - /* currently parameter not in use */ - enum grph_color_adjust_option option = - GRPH_COLOR_MATRIX_HW_DEFAULT; - uint32_t i; - /* - * HW default false we program locally defined matrix - * HW default true we use predefined hw matrix and we - * do not need to program matrix - * OEM wants the HW default via runtime parameter. - */ - option = GRPH_COLOR_MATRIX_SW; - - for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { - elm = &global_color_matrix[i]; - if (elm->color_space != default_adjust->out_color_space) - continue; - /* program the matrix with default values from this - * file */ - program_color_matrix(opp80, elm, option); - config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - break; - } - } - - /* configure the what we programmed : - * 1. Default values from this file - * 2. Use hardware default from ROM_A and we do not need to program - * matrix */ - - configure_graphics_mode(opp80, config, - default_adjust->csc_adjust_type, - default_adjust->out_color_space); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c deleted file mode 100644 index 433296a4ed12..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_formatter.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_opp.h" - -#define FMT_REG(reg)\ - (reg + opp80->offsets.fmt_offset) - -/** - * set_truncation - * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp - * 2) enable truncation - * 3) HW remove 12bit FMT support for DCE8 power saving reason. - */ -static void set_truncation( - struct dce80_opp *opp80, - const struct bit_depth_reduction_params *params) -{ - uint32_t value = 0; - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - - /*Disable truncation*/ - value = dm_read_reg(opp80->base.ctx, addr); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); - set_reg_field_value(value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); - - dm_write_reg(opp80->base.ctx, addr, value); - - /* no 10bpc trunc on DCE8*/ - if (params->flags.TRUNCATE_ENABLED == 0 || - params->flags.TRUNCATE_DEPTH == 2) - return; - - /*Set truncation depth and Enable truncation*/ - set_reg_field_value(value, 1, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); - set_reg_field_value(value, params->flags.TRUNCATE_MODE, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); - set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, - FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); - - dm_write_reg(opp80->base.ctx, addr, value); - -} - -/** - * set_spatial_dither - * 1) set spatial dithering mode: pattern of seed - * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp - * 3) set random seed - * 4) set random mode - * lfsr is reset every frame or not reset - * RGB dithering method - * 0: RGB data are all dithered with x^28+x^3+1 - * 1: R data is dithered with x^28+x^3+1 - * G data is dithered with x^28+X^9+1 - * B data is dithered with x^28+x^13+1 - * enable high pass filter or not - * 5) enable spatical dithering - */ -static void set_spatial_dither( - struct dce80_opp *opp80, - const struct bit_depth_reduction_params *params) -{ - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - uint32_t depth_cntl_value = 0; - uint32_t dither_r_value = 0; - uint32_t dither_g_value = 0; - uint32_t dither_b_value = 0; - - /*Disable spatial (random) dithering*/ - depth_cntl_value = dm_read_reg(opp80->base.ctx, addr); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE); - set_reg_field_value(depth_cntl_value, 0, - FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE); - - dm_write_reg(opp80->base.ctx, addr, depth_cntl_value); - - /* no 10bpc on DCE8*/ - if (params->flags.SPATIAL_DITHER_ENABLED == 0 || - params->flags.SPATIAL_DITHER_DEPTH == 2) - return; - - /*Set seed for random values for - * spatial dithering for R,G,B channels*/ - addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED); - set_reg_field_value(dither_r_value, params->r_seed_value, - FMT_DITHER_RAND_R_SEED, - FMT_RAND_R_SEED); - dm_write_reg(opp80->base.ctx, addr, dither_r_value); - - addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED); - set_reg_field_value(dither_g_value, - params->g_seed_value, - FMT_DITHER_RAND_G_SEED, - FMT_RAND_G_SEED); - dm_write_reg(opp80->base.ctx, addr, dither_g_value); - - addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED); - set_reg_field_value(dither_b_value, params->b_seed_value, - FMT_DITHER_RAND_B_SEED, - FMT_RAND_B_SEED); - dm_write_reg(opp80->base.ctx, addr, dither_b_value); - - /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero - * offset for the R/Cr channel, lower 4LSB - * is forced to zeros. Typically set to 0 - * RGB and 0x80000 YCbCr. - */ - /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero - * offset for the G/Y channel, lower 4LSB is - * forced to zeros. Typically set to 0 RGB - * and 0x80000 YCbCr. - */ - /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero - * offset for the B/Cb channel, lower 4LSB is - * forced to zeros. Typically set to 0 RGB and - * 0x80000 YCbCr. - */ - - /*Set spatial dithering bit depth*/ - set_reg_field_value(depth_cntl_value, - params->flags.SPATIAL_DITHER_DEPTH, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_DEPTH); - - /* Set spatial dithering mode - * (default is Seed patterrn AAAA...) - */ - set_reg_field_value(depth_cntl_value, - params->flags.SPATIAL_DITHER_MODE, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_MODE); - - /*Reset only at startup*/ - set_reg_field_value(depth_cntl_value, - params->flags.FRAME_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_FRAME_RANDOM_ENABLE); - - /*Set RGB data dithered with x^28+x^3+1*/ - set_reg_field_value(depth_cntl_value, - params->flags.RGB_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_RGB_RANDOM_ENABLE); - - /*Disable High pass filter*/ - set_reg_field_value(depth_cntl_value, - params->flags.HIGHPASS_RANDOM, - FMT_BIT_DEPTH_CONTROL, - FMT_HIGHPASS_RANDOM_ENABLE); - - /*Enable spatial dithering*/ - set_reg_field_value(depth_cntl_value, - 1, - FMT_BIT_DEPTH_CONTROL, - FMT_SPATIAL_DITHER_EN); - - addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - dm_write_reg(opp80->base.ctx, addr, depth_cntl_value); - -} - -/** - * SetTemporalDither (Frame Modulation) - * 1) set temporal dither depth - * 2) select pattern: from hard-coded pattern or programmable pattern - * 3) select optimized strips for BGR or RGB LCD sub-pixel - * 4) set s matrix - * 5) set t matrix - * 6) set grey level for 0.25, 0.5, 0.75 - * 7) enable temporal dithering - */ -static void set_temporal_dither( - struct dce80_opp *opp80, - const struct bit_depth_reduction_params *params) -{ - uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - uint32_t value; - - /*Disable temporal (frame modulation) dithering first*/ - value = dm_read_reg(opp80->base.ctx, addr); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_EN); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_RESET); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_OFFSET); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_DEPTH); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_LEVEL); - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_25FRC_SEL); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_50FRC_SEL); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_75FRC_SEL); - - dm_write_reg(opp80->base.ctx, addr, value); - - /* no 10bpc dither on DCE8*/ - if (params->flags.FRAME_MODULATION_ENABLED == 0 || - params->flags.FRAME_MODULATION_DEPTH == 2) - return; - - /* Set temporal dithering depth*/ - set_reg_field_value(value, - params->flags.FRAME_MODULATION_DEPTH, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_DEPTH); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_RESET); - - set_reg_field_value(value, - 0, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_OFFSET); - - /*Select legacy pattern based on FRC and Temporal level*/ - addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL); - dm_write_reg(opp80->base.ctx, addr, 0); - /*Set s matrix*/ - addr = FMT_REG( - mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX); - dm_write_reg(opp80->base.ctx, addr, 0); - /*Set t matrix*/ - addr = FMT_REG( - mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX); - dm_write_reg(opp80->base.ctx, addr, 0); - - /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ - set_reg_field_value(value, - params->flags.TEMPORAL_LEVEL, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_LEVEL); - - set_reg_field_value(value, - params->flags.FRC25, - FMT_BIT_DEPTH_CONTROL, - FMT_25FRC_SEL); - - set_reg_field_value(value, - params->flags.FRC50, - FMT_BIT_DEPTH_CONTROL, - FMT_50FRC_SEL); - - set_reg_field_value(value, - params->flags.FRC75, - FMT_BIT_DEPTH_CONTROL, - FMT_75FRC_SEL); - - /*Enable bit reduction by temporal (frame modulation) dithering*/ - set_reg_field_value(value, - 1, - FMT_BIT_DEPTH_CONTROL, - FMT_TEMPORAL_DITHER_EN); - - addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); - dm_write_reg(opp80->base.ctx, addr, value); - -} - -/** - * Set Clamping - * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) - * 1 for 8 bpc - * 2 for 10 bpc - * 3 for 12 bpc - * 7 for programable - * 2) Enable clamp if Limited range requested - */ -static void set_clamping( - struct dce80_opp *opp80, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t clamp_cntl_value = 0; - uint32_t red_clamp_value = 0; - uint32_t green_clamp_value = 0; - uint32_t blue_clamp_value = 0; - uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL); - - clamp_cntl_value = dm_read_reg(opp80->base.ctx, addr); - - set_reg_field_value(clamp_cntl_value, - 0, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 0, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - switch (params->clamping_level) { - case CLAMPING_FULL_RANGE: - break; - - case CLAMPING_LIMITED_RANGE_8BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - - case CLAMPING_LIMITED_RANGE_10BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 2, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - case CLAMPING_LIMITED_RANGE_12BPC: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 3, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - break; - case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: - set_reg_field_value(clamp_cntl_value, - 1, - FMT_CLAMP_CNTL, - FMT_CLAMP_DATA_EN); - - set_reg_field_value(clamp_cntl_value, - 7, - FMT_CLAMP_CNTL, - FMT_CLAMP_COLOR_FORMAT); - - /*set the defaults*/ - set_reg_field_value(red_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_R, - FMT_CLAMP_LOWER_R); - - set_reg_field_value(red_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_R, - FMT_CLAMP_UPPER_R); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R); - dm_write_reg(opp80->base.ctx, addr, red_clamp_value); - - set_reg_field_value(green_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_G, - FMT_CLAMP_LOWER_G); - - set_reg_field_value(green_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_G, - FMT_CLAMP_UPPER_G); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G); - dm_write_reg(opp80->base.ctx, addr, green_clamp_value); - - set_reg_field_value(blue_clamp_value, - 0x10, - FMT_CLAMP_COMPONENT_B, - FMT_CLAMP_LOWER_B); - - set_reg_field_value(blue_clamp_value, - 0xFEF, - FMT_CLAMP_COMPONENT_B, - FMT_CLAMP_UPPER_B); - - addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B); - dm_write_reg(opp80->base.ctx, addr, blue_clamp_value); - - break; - - default: - break; - } - - addr = FMT_REG(mmFMT_CLAMP_CNTL); - /*Set clamp control*/ - dm_write_reg(opp80->base.ctx, addr, clamp_cntl_value); - -} - -/** - * set_pixel_encoding - * - * Set Pixel Encoding - * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly - * 1: YCbCr 4:2:2 - */ -static void set_pixel_encoding( - struct dce80_opp *opp80, - const struct clamping_and_pixel_encoding_params *params) -{ - uint32_t fmt_cntl_value; - uint32_t addr = FMT_REG(mmFMT_CONTROL); - - /*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/ - fmt_cntl_value = dm_read_reg(opp80->base.ctx, addr); - - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { - set_reg_field_value(fmt_cntl_value, - 1, - FMT_CONTROL, - FMT_PIXEL_ENCODING); - - /*00 - Pixels drop mode ,01 - Pixels average mode*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_MODE); - - /*00 - Cb before Cr ,01 - Cr before Cb*/ - set_reg_field_value(fmt_cntl_value, - 0, - FMT_CONTROL, - FMT_SUBSAMPLING_ORDER); - } - dm_write_reg(opp80->base.ctx, addr, fmt_cntl_value); - -} - -void dce80_opp_program_bit_depth_reduction( - struct output_pixel_processor *opp, - const struct bit_depth_reduction_params *params) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - - set_truncation(opp80, params); - set_spatial_dither(opp80, params); - set_temporal_dither(opp80, params); -} - -void dce80_opp_program_clamping_and_pixel_encoding( - struct output_pixel_processor *opp, - const struct clamping_and_pixel_encoding_params *params) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - - set_clamping(opp80, params); - set_pixel_encoding(opp80, params); -} - -void dce80_opp_set_dyn_expansion( - struct output_pixel_processor *opp, - enum dc_color_space color_sp, - enum dc_color_depth color_dpth, - enum signal_type signal) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - uint32_t value; - bool enable_dyn_exp = false; - uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL); - - value = dm_read_reg(opp->ctx, addr); - - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - - /* From HW programming guide: - FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output - FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ - if (color_sp == COLOR_SPACE_SRGB) - enable_dyn_exp = true; - - /*00 - 10-bit -> 12-bit dynamic expansion*/ - /*01 - 8-bit -> 12-bit dynamic expansion*/ - if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { - switch (color_dpth) { - case COLOR_DEPTH_888: - set_reg_field_value(value, enable_dyn_exp ? 1:0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 1, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - break; - case COLOR_DEPTH_101010: - set_reg_field_value(value, enable_dyn_exp ? 1:0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN); - set_reg_field_value(value, 0, - FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE); - break; - case COLOR_DEPTH_121212: - break; - default: - break; - } - } - - dm_write_reg(opp->ctx, addr, value); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c deleted file mode 100644 index 648e3ef35d91..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_opp_regamma.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -/* include DCE8 register header files */ -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_opp.h" -#include "gamma_types.h" - -#define DCP_REG(reg)\ - (reg + opp80->offsets.dcp_offset) - -#define DCFE_REG(reg)\ - (reg + opp80->offsets.crtc_offset) - -enum { - MAX_PWL_ENTRY = 128, - MAX_REGIONS_NUMBER = 16 - -}; - -struct curve_config { - uint32_t offset; - int8_t segments[MAX_REGIONS_NUMBER]; - int8_t begin; -}; - -/* - ***************************************************************************** - * Function: regamma_config_regions_and_segments - * - * build regamma curve by using predefined hw points - * uses interface parameters ,like EDID coeff. - * - * @param : parameters interface parameters - * @return void - * - * @note - * - * @see - * - ***************************************************************************** - */ -static void regamma_config_regions_and_segments( - struct dce80_opp *opp80, const struct pwl_params *params) -{ - const struct gamma_curve *curve; - uint32_t value = 0; - - { - set_reg_field_value( - value, - params->arr_points[0].custom_float_x, - REGAMMA_CNTLA_START_CNTL, - REGAMMA_CNTLA_EXP_REGION_START); - - set_reg_field_value( - value, - 0, - REGAMMA_CNTLA_START_CNTL, - REGAMMA_CNTLA_EXP_REGION_START_SEGMENT); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_START_CNTL), - value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[0].custom_float_slope, - REGAMMA_CNTLA_SLOPE_CNTL, - REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[1].custom_float_x, - REGAMMA_CNTLA_END_CNTL1, - REGAMMA_CNTLA_EXP_REGION_END); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value); - } - { - value = 0; - set_reg_field_value( - value, - params->arr_points[2].custom_float_slope, - REGAMMA_CNTLA_END_CNTL2, - REGAMMA_CNTLA_EXP_REGION_END_BASE); - - set_reg_field_value( - value, - params->arr_points[1].custom_float_y, - REGAMMA_CNTLA_END_CNTL2, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); - } - - curve = params->arr_curve_points; - - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_0_1, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS); - - dm_write_reg( - opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_0_1), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_2_3, - REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_2_3), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_4_5, - REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_4_5), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_6_7, - REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_6_7), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_8_9, - REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_8_9), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_10_11, - REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_10_11), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_12_13, - REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_12_13), - value); - } - - curve += 2; - { - value = 0; - set_reg_field_value( - value, - curve[0].offset, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET); - - set_reg_field_value( - value, - curve[0].segments_num, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS); - - set_reg_field_value( - value, - curve[1].offset, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET); - - set_reg_field_value( - value, - curve[1].segments_num, - REGAMMA_CNTLA_REGION_14_15, - REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CNTLA_REGION_14_15), - value); - } -} - -static void program_pwl( - struct dce80_opp *opp80, - const struct pwl_params *params) -{ - uint32_t value; - - { - uint8_t max_tries = 10; - uint8_t counter = 0; - - /* Power on LUT memory */ - value = dm_read_reg(opp80->base.ctx, - DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); - - set_reg_field_value( - value, - 1, - DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS); - - dm_write_reg(opp80->base.ctx, - DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value); - - while (counter < max_tries) { - value = - dm_read_reg( - opp80->base.ctx, - DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); - - if (get_reg_field_value( - value, - DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_MEM_PWR_STATE) == 0) - break; - - ++counter; - } - - if (counter == max_tries) { - dm_logger_write(opp80->base.ctx->logger, LOG_WARNING, - "%s: regamma lut was not powered on " - "in a timely manner," - " programming still proceeds\n", - __func__); - } - } - - value = 0; - - set_reg_field_value( - value, - 7, - REGAMMA_LUT_WRITE_EN_MASK, - REGAMMA_LUT_WRITE_EN_MASK); - - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value); - dm_write_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_LUT_INDEX), 0); - - /* Program REGAMMA_LUT_DATA */ - { - const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA); - - uint32_t i = 0; - - const struct pwl_result_data *rgb = - params->rgb_resulted; - - while (i != params->hw_points_num) { - dm_write_reg(opp80->base.ctx, addr, rgb->red_reg); - dm_write_reg(opp80->base.ctx, addr, rgb->green_reg); - dm_write_reg(opp80->base.ctx, addr, rgb->blue_reg); - - dm_write_reg(opp80->base.ctx, addr, - rgb->delta_red_reg); - dm_write_reg(opp80->base.ctx, addr, - rgb->delta_green_reg); - dm_write_reg(opp80->base.ctx, addr, - rgb->delta_blue_reg); - - ++rgb; - ++i; - } - } - - /* we are done with DCP LUT memory; re-enable low power mode */ - value = dm_read_reg(opp80->base.ctx, - DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); - - set_reg_field_value( - value, - 0, - DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS); - - dm_write_reg(opp80->base.ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), - value); -} - -void dce80_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - - uint32_t value = - dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL)); - - set_reg_field_value( - value, - power_on, - DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS); - - set_reg_field_value( - value, - power_on, - DCFE_MEM_LIGHT_SLEEP_CNTL, - DCP_LUT_LIGHT_SLEEP_DIS); - - dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_LIGHT_SLEEP_CNTL), value); -} - -bool dce80_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - - regamma_config_regions_and_segments(opp80, params); - - program_pwl(opp80, params); - - return true; -} - -void dce80_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode) -{ - struct dce80_opp *opp80 = TO_DCE80_OPP(opp); - uint32_t value = dm_read_reg(opp80->base.ctx, - DCP_REG(mmREGAMMA_CONTROL)); - - set_reg_field_value( - value, - mode, - REGAMMA_CONTROL, - GRPH_REGAMMA_MODE); - - dm_write_reg(opp80->base.ctx, DCP_REG(mmREGAMMA_CONTROL), value); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 517d42dfff0c..56a63d985440 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -43,7 +43,7 @@ #include "dce80/dce80_mem_input.h" #include "dce80/dce80_ipp.h" #include "dce/dce_transform.h" -#include "dce80/dce80_opp.h" +#include "dce/dce_opp.h" #include "dce110/dce110_ipp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" @@ -317,6 +317,28 @@ static const struct dce_stream_encoder_mask se_mask = { SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) }; +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_80_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) +}; + #define audio_regs(id)\ [id] = {\ AUD_COMMON_REG_LIST(id)\ @@ -419,6 +441,25 @@ static struct timing_generator *dce80_timing_generator_create( return NULL; } +static struct output_pixel_processor *dce80_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + static struct stream_encoder *dce80_stream_encoder_create( enum engine_id eng_id, struct dc_context *ctx) @@ -631,7 +672,7 @@ static void destruct(struct dce110_resource_pool *pool) for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) - dce80_opp_destroy(&pool->base.opps[i]); + dce110_opp_destroy(&pool->base.opps[i]); if (pool->base.transforms[i] != NULL) dce80_transform_destroy(&pool->base.transforms[i]); -- GitLab From 4a69244eb63794cc48ad3653e0f16f2eb096fcd7 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 16 Dec 2016 12:12:03 -0500 Subject: [PATCH 0116/2898] drm/amd/display: Fix distribution of segments for PQ For PQ case, redistribution of segments should be done differently for FP16 case in order to handle content above FP16 value of 1.0 Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/gamma_calcs.c | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index 973be8f649cc..729652a3763d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -387,6 +387,49 @@ static bool build_hw_curve_configuration( return result; } +static bool setup_distribution_points_pq( + struct gamma_curve *arr_curve_points, + struct curve_points *arr_points, + uint32_t *hw_points_num, + struct hw_x_point *coordinates_x, + enum surface_pixel_format format) +{ + struct curve_config cfg; + + cfg.offset = 0; + cfg.segments[0] = 2; + cfg.segments[1] = 2; + cfg.segments[2] = 2; + cfg.segments[3] = 2; + cfg.segments[4] = 2; + cfg.segments[5] = 2; + cfg.segments[6] = 3; + cfg.segments[7] = 4; + cfg.segments[8] = 4; + cfg.segments[9] = 4; + cfg.segments[10] = 4; + cfg.segments[11] = 5; + cfg.segments[12] = 5; + cfg.segments[13] = 5; + cfg.segments[14] = 5; + cfg.segments[15] = 5; + + if (format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || + format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) + cfg.begin = -11; + else + cfg.begin = -16; + + if (!build_hw_curve_configuration( + &cfg, arr_curve_points, + arr_points, + coordinates_x, hw_points_num)) { + ASSERT_CRITICAL(false); + return false; + } + return true; +} + static bool setup_distribution_points( struct gamma_curve *arr_curve_points, struct curve_points *arr_points, @@ -1414,15 +1457,17 @@ bool calculate_regamma_params(struct pwl_params *params, scale_gamma(rgb_user, ramp, dividers); - setup_distribution_points(arr_curve_points, arr_points, - ¶ms->hw_points_num, coordinates_x); - if (stream->public.out_transfer_func && stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { + setup_distribution_points_pq(arr_curve_points, arr_points, + ¶ms->hw_points_num, coordinates_x, + surface->public.format); build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem, ramp, surface, params->hw_points_num, coordinates_x, axix_x_256, dividers); } else { + setup_distribution_points(arr_curve_points, arr_points, + ¶ms->hw_points_num, coordinates_x); build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, ramp, surface, params->hw_points_num, coordinates_x, axix_x_256, dividers); -- GitLab From 538735e9e501056a4370d445bffec4ecb2a59ca4 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 16 Dec 2016 12:12:03 -0500 Subject: [PATCH 0117/2898] drm/amd/display: Fix programming of gamma end points Signed-off-by: Anthony Koo Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/gamma_calcs.c | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index 729652a3763d..5cd408dadb20 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -245,6 +245,8 @@ static bool build_hw_curve_configuration( uint32_t segments = 0; uint32_t max_number; + int8_t num_regions = 0; + bool result = false; if (!number_of_points) { @@ -273,6 +275,7 @@ static bool build_hw_curve_configuration( ASSERT(curve_config->segments[i] >= 0); segments += (1 << curve_config->segments[i]); + ++num_regions; ++i; } @@ -284,12 +287,14 @@ static bool build_hw_curve_configuration( uint32_t offset = 0; int8_t begin = curve_config->begin; int32_t region_number = 0; + struct fixed31_32 magic_number = + dal_fixed31_32_from_fraction(249, 1000); i = begin; while ((index < max_number) && (region_number < max_regions_number) && - (i <= 1)) { + (i < (begin + num_regions))) { int32_t j = 0; segments = curve_config->segments[region_number]; @@ -345,8 +350,7 @@ static bool build_hw_curve_configuration( divisor); points[index].x = region1; - - round_custom_float_6_12(points + index); + points[index].adjusted_x = region1; ++index; ++region_number; @@ -366,9 +370,10 @@ static bool build_hw_curve_configuration( ++i; } - points[index].x = region1; - - round_custom_float_6_12(points + index); + points[index].x = + dal_fixed31_32_add(region1, magic_number); + points[index].adjusted_x = + dal_fixed31_32_add(region1, magic_number); *number_of_points = index; @@ -1215,15 +1220,11 @@ static void rebuild_curve_configuration_magic( const struct hw_x_point *coordinates_x, uint32_t hw_points_num) { - const struct fixed31_32 magic_number = - dal_fixed31_32_from_fraction(249, 1000); - struct fixed31_32 y_r; struct fixed31_32 y_g; struct fixed31_32 y_b; struct fixed31_32 y1_min; - struct fixed31_32 y2_max; struct fixed31_32 y3_max; y_r = rgb_resulted[0].red; @@ -1238,29 +1239,31 @@ static void rebuild_curve_configuration_magic( arr_points[0].y, arr_points[0].x); - arr_points[1].x = dal_fixed31_32_add( - coordinates_x[hw_points_num - 1].adjusted_x, - magic_number); - - arr_points[2].x = arr_points[1].x; - - y_r = rgb_resulted[hw_points_num - 1].red; - y_g = rgb_resulted[hw_points_num - 1].green; - y_b = rgb_resulted[hw_points_num - 1].blue; - - y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); - - arr_points[1].y = y2_max; + /* this should be cleaned up as it's confusing my understanding (KK) is + * that REGAMMA_CNTLA_EXP_REGION_END is the X value for the region end + * REGAMMA_CNTLA_EXP_REGION_END_BASE is Y value for the above X + * REGAMMA_CNTLA_EXP_REGION_END_SLOPE is the slope beyond (X,Y) above + * currently when programming REGION_END = m_arrPoints[1].x, + * REGION_END_BASE = m_arrPoints[1].y, REGION_END_SLOPE=1 + * we don't use m_arrPoints[2] at all after this function, + * and its purpose isn't clear to me + */ + arr_points[1].x = coordinates_x[hw_points_num].adjusted_x; + arr_points[2].x = coordinates_x[hw_points_num].adjusted_x; y_r = rgb_resulted[hw_points_num].red; y_g = rgb_resulted[hw_points_num].green; y_b = rgb_resulted[hw_points_num].blue; + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + arr_points[1].y = y3_max; arr_points[2].y = y3_max; - arr_points[2].slope = dal_fixed31_32_one; + arr_points[2].slope = dal_fixed31_32_zero; } static bool convert_to_custom_float_format( -- GitLab From 1964cb736aaa094379d47aa1dc056a5531cecbd6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:05 +1000 Subject: [PATCH 0118/2898] drm/amd/display: remove dc hub - this seems unused. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 27 ------------------- drivers/gpu/drm/amd/display/dc/dc.h | 17 ------------ .../amd/display/dc/dce110/dce110_mem_input.c | 1 - .../amd/display/dc/dce80/dce80_mem_input.c | 1 - .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 2 -- 5 files changed, 48 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index df1bae8ea92b..891075e39ecf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1871,30 +1871,3 @@ const struct dc_stream_status *dc_stream_get_status( return &stream->status; } -bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) -{ - int i; - struct core_dc *core_dc = DC_TO_CORE(dc); - struct mem_input *mi = NULL; - - for (i = 0; i < core_dc->res_pool->pipe_count; i++) { - if (core_dc->res_pool->mis[i] != NULL) { - mi = core_dc->res_pool->mis[i]; - break; - } - } - if (mi == NULL) { - dm_error("no mem_input!\n"); - return false; - } - - if (mi->funcs->mem_input_update_dchub) - mi->funcs->mem_input_update_dchub(mi, dh_data); - else - ASSERT(mi->funcs->mem_input_update_dchub); - - - return true; - -} - diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ffea10c73275..f786a17de1fd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -159,21 +159,6 @@ struct dc { struct dc_debug debug; }; -enum frame_buffer_mode { - FRAME_BUFFER_MODE_LOCAL_ONLY = 0, - FRAME_BUFFER_MODE_ZFB_ONLY, - FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL, -} ; - -struct dchub_init_data { - bool dchub_initialzied; - bool dchub_info_valid; - int64_t zfb_phys_addr_base; - int64_t zfb_mc_base_addr; - uint64_t zfb_size_in_byte; - enum frame_buffer_mode fb_mode; -}; - struct dc_init_data { struct hw_asic_id asic_id; void *driver; /* ctx */ @@ -194,8 +179,6 @@ struct dc *dc_create(const struct dc_init_data *init_params); void dc_destroy(struct dc **dc); -bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); - /******************************************************************************* * Surface Interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index a20feaedfca4..1643fb5d4b04 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -409,7 +409,6 @@ static struct mem_input_funcs dce110_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, - .mem_input_update_dchub = NULL }; /*****************************************/ /* Constructor, Destructor */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c index ebb8df3cdf4a..704a7ce62080 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -54,7 +54,6 @@ static struct mem_input_funcs dce80_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, - .mem_input_update_dchub = NULL }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 80566c844758..2c0774f95c1c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -99,8 +99,6 @@ struct mem_input_funcs { bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); - void (*mem_input_update_dchub)(struct mem_input *mem_input, - struct dchub_init_data *dh_data); }; #endif -- GitLab From 55b99b4640d4898c140fef7073291918a6e32539 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:06 +1000 Subject: [PATCH 0119/2898] drm/amd/display: remove some unused wrappers Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 9d5125951acd..9c852a36a604 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -36,10 +36,6 @@ #include "amdgpu_dm_types.h" #include "amdgpu_pm.h" -#define dm_alloc(size) kzalloc(size, GFP_KERNEL) -#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) -#define dm_free(ptr) kfree(ptr) - /****************************************************************************** * IRQ Interfaces. *****************************************************************************/ -- GitLab From 2a0998846d2eadabf8c5770f66feb3cb04ad88b5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:07 +1000 Subject: [PATCH 0120/2898] drm/amd/display: drop register logger and pid/tgid getters While I'm sure this is useful I think we should bring it back later. It's usage of pid/tgid is incorrect, you have to get/put pid/tgids not store them away. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/amdgpu_dm/amdgpu_dm_services.c | 10 - .../gpu/drm/amd/display/dc/basics/Makefile | 2 +- .../amd/display/dc/basics/register_logger.c | 197 ------------------ drivers/gpu/drm/amd/display/dc/dm_services.h | 16 -- .../amd/display/include/dal_register_logger.h | 42 ---- 5 files changed, 1 insertion(+), 266 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/basics/register_logger.c delete mode 100644 drivers/gpu/drm/amd/display/include/dal_register_logger.h diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 9c852a36a604..565be0506059 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -447,13 +447,3 @@ void dal_notify_setmode_complete(struct dc_context *ctx, /*TODO*/ } /* End of calls to notification */ - -long dm_get_pid(void) -{ - return current->pid; -} - -long dm_get_tgid(void) -{ - return current->tgid; -} diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile index a263cadcc0df..065816209da1 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/Makefile +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -4,7 +4,7 @@ # subcomponents. BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \ - logger.o log_helpers.o register_logger.o signal_types.o vector.o + logger.o log_helpers.o signal_types.o vector.o AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) diff --git a/drivers/gpu/drm/amd/display/dc/basics/register_logger.c b/drivers/gpu/drm/amd/display/dc/basics/register_logger.c deleted file mode 100644 index b8d57d919fe4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/basics/register_logger.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/dal_types.h" -#include "include/logger_interface.h" -#include "logger.h" - -/****************************************************************************** - * Register Logger. - * A facility to create register R/W logs. - * Currently used for DAL Test. - *****************************************************************************/ - -/****************************************************************************** - * Private structures - *****************************************************************************/ -struct dal_reg_dump_stack_location { - const char *current_caller_func; - long current_pid; - long current_tgid; - uint32_t rw_count;/* register access counter for current function. */ -}; - -/* This the maximum number of nested calls to the 'reg_dump' facility. */ -#define DAL_REG_DUMP_STACK_MAX_SIZE 32 - -struct dal_reg_dump_stack { - int32_t stack_pointer; - struct dal_reg_dump_stack_location - stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE]; - uint32_t total_rw_count; /* Total count for *all* functions. */ -}; - -static struct dal_reg_dump_stack reg_dump_stack = {0}; - -/****************************************************************************** - * Private functions - *****************************************************************************/ - -/* Check if current process is the one which requested register dump. - * The reason for the check: - * mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter(). - * Which runs all the time when at least one display is connected. - * (Triggered by drm_mode_page_flip_ioctl()). */ -static bool is_reg_dump_process(void) -{ - uint32_t i; - - /* walk the list of our processes */ - for (i = 0; i < reg_dump_stack.stack_pointer; i++) { - struct dal_reg_dump_stack_location *stack_location - = ®_dump_stack.stack_locations[i]; - - if (stack_location->current_pid == dm_get_pid() - && stack_location->current_tgid == dm_get_tgid()) - return true; - } - - return false; -} - -static bool dal_reg_dump_stack_is_empty(void) -{ - if (reg_dump_stack.stack_pointer <= 0) - return true; - else - return false; -} - -static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void) -{ - struct dal_reg_dump_stack_location *current_location = NULL; - - if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) { - /* stack is full */ - dm_output_to_console("[REG_DUMP]: %s: stack is full!\n", - __func__); - } else { - current_location = - ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; - ++reg_dump_stack.stack_pointer; - } - - return current_location; -} - -static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void) -{ - struct dal_reg_dump_stack_location *current_location = NULL; - - if (dal_reg_dump_stack_is_empty()) { - /* stack is empty */ - dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n", - __func__); - } else { - --reg_dump_stack.stack_pointer; - current_location = - ®_dump_stack.stack_locations[reg_dump_stack.stack_pointer]; - } - - return current_location; -} - -/****************************************************************************** - * Public functions - *****************************************************************************/ - -void dal_reg_logger_push(const char *caller_func) -{ - struct dal_reg_dump_stack_location *free_stack_location; - - free_stack_location = dal_reg_dump_stack_push(); - - if (NULL == free_stack_location) - return; - - memset(free_stack_location, 0, sizeof(*free_stack_location)); - - free_stack_location->current_caller_func = caller_func; - free_stack_location->current_pid = dm_get_pid(); - free_stack_location->current_tgid = dm_get_tgid(); - - dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n", - caller_func, - free_stack_location->current_pid, - free_stack_location->current_tgid); -} - -void dal_reg_logger_pop(void) -{ - struct dal_reg_dump_stack_location *top_stack_location; - - top_stack_location = dal_reg_dump_stack_pop(); - - if (NULL == top_stack_location) { - dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n", - __func__); - return; - } - - dm_output_to_console( - "[REG_DUMP]:%s - end."\ - " Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n", - top_stack_location->current_caller_func, - reg_dump_stack.total_rw_count, - top_stack_location->rw_count, - dm_get_pid(), - dm_get_tgid()); - - memset(top_stack_location, 0, sizeof(*top_stack_location)); -} - -void dal_reg_logger_rw_count_increment(void) -{ - ++reg_dump_stack.total_rw_count; - - ++reg_dump_stack.stack_locations - [reg_dump_stack.stack_pointer - 1].rw_count; -} - -bool dal_reg_logger_should_dump_register(void) -{ - if (true == dal_reg_dump_stack_is_empty()) - return false; - - if (false == is_reg_dump_process()) - return false; - - return true; -} - -/****************************************************************************** - * End of File. - *****************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 7a3f10354830..f3f9a401160c 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -109,12 +109,6 @@ static inline uint32_t dm_read_reg_func( value = cgs_read_register(ctx->cgs_device, address); -#if defined(__DAL_REGISTER_LOGGER__) - if (true == dal_reg_logger_should_dump_register()) { - dal_reg_logger_rw_count_increment(); - DRM_INFO("%s DC_READ_REG: 0x%x 0x%x\n", func_name, address, value); - } -#endif return value; } @@ -127,13 +121,6 @@ static inline void dm_write_reg_func( uint32_t value, const char *func_name) { -#if defined(__DAL_REGISTER_LOGGER__) - if (true == dal_reg_logger_should_dump_register()) { - dal_reg_logger_rw_count_increment(); - DRM_INFO("%s DC_WRITE_REG: 0x%x 0x%x\n", func_name, address, value); - } -#endif - if (address == 0) { DC_ERR("invalid register write. address = 0"); return; @@ -418,7 +405,4 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); #define dm_log_to_buffer(buffer, size, fmt, args)\ vsnprintf(buffer, size, fmt, args) -long dm_get_pid(void); -long dm_get_tgid(void); - #endif /* __DM_SERVICES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_register_logger.h b/drivers/gpu/drm/amd/display/include/dal_register_logger.h deleted file mode 100644 index 00dfcd70cc37..000000000000 --- a/drivers/gpu/drm/amd/display/include/dal_register_logger.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_REGISTER_LOGGER__ -#define __DAL_REGISTER_LOGGER__ - -/**************** - * API functions - ***************/ - -/* dal_reg_logger_push - begin Register Logging */ -void dal_reg_logger_push(const char *caller_func); -/* dal_reg_logger_pop - stop Register Logging */ -void dal_reg_logger_pop(void); - -/* for internal use of the Logger only */ -void dal_reg_logger_rw_count_increment(void); -bool dal_reg_logger_should_dump_register(void); - -#endif /* __DAL_REGISTER_LOGGER__ */ -- GitLab From e285917063641f00086242d6c927ace9de24c357 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:08 +1000 Subject: [PATCH 0121/2898] drm/amd/display: drop get platform info Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/amdgpu_dm/amdgpu_dm_services.c | 7 ---- drivers/gpu/drm/amd/display/dc/dm_services.h | 32 ------------------- 2 files changed, 39 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 565be0506059..b842eafdf66c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -77,13 +77,6 @@ void dal_isr_release_lock(struct dc_context *ctx) * End-of-IRQ Interfaces. *****************************************************************************/ -bool dm_get_platform_info(struct dc_context *ctx, - struct platform_info_params *params) -{ - /*TODO*/ - return false; -} - bool dm_write_persistent_data(struct dc_context *ctx, const struct dc_sink *sink, const char *module_name, diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index f3f9a401160c..11a0abfd3418 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -282,38 +282,6 @@ bool dm_pp_get_static_clocks( /****** end of PP interfaces ******/ -enum platform_method { - PM_GET_AVAILABLE_METHODS = 1 << 0, - PM_GET_LID_STATE = 1 << 1, - PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2 -}; - -struct platform_info_params { - enum platform_method method; - void *data; -}; - -struct platform_info_brightness_caps { - uint8_t ac_level_percentage; - uint8_t dc_level_percentage; -}; - -struct platform_info_ext_brightness_caps { - struct platform_info_brightness_caps basic_caps; - struct data_point { - uint8_t luminance; - uint8_t signal_level; - } data_points[99]; - - uint8_t data_points_num; - uint8_t min_input_signal; - uint8_t max_input_signal; -}; - -bool dm_get_platform_info( - struct dc_context *ctx, - struct platform_info_params *params); - struct persistent_data_flag { bool save_per_link; bool save_per_edid; -- GitLab From 2c755dae303fa7eecc6400b2dcb544298d1e2e3e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:09 +1000 Subject: [PATCH 0122/2898] drm/amd/display: drop setmode complete notifier Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index b842eafdf66c..5af27aad2dad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -427,16 +427,3 @@ bool dm_pp_get_static_clocks( } /**** end of power component interfaces ****/ - -/* Calls to notification */ - -void dal_notify_setmode_complete(struct dc_context *ctx, - uint32_t h_total, - uint32_t v_total, - uint32_t h_active, - uint32_t v_active, - uint32_t pix_clk_in_khz) -{ - /*TODO*/ -} -/* End of calls to notification */ -- GitLab From eaca91eea60e5b0732b7e9ab213359d75f36901f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 19 Dec 2016 14:10:53 -0500 Subject: [PATCH 0123/2898] drm/amd/display: Move dpcd structs into dp_types header Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 + .../drm/amd/display/dc/core/dc_link_hwss.c | 1 + drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 359 ++++++++++++++++++ .../gpu/drm/amd/display/include/dpcd_defs.h | 358 ----------------- .../amd/display/include/link_service_types.h | 1 - 6 files changed, 361 insertions(+), 360 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 47f22d46c0ca..ecfca6204171 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -39,6 +39,7 @@ #include "resource.h" #include "fixed31_32.h" #include "include/asic_capability_interface.h" +#include "dpcd_defs.h" #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_enum.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index e89f5f176ec3..0c5f16cb1d54 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -13,6 +13,7 @@ #include "dm_helpers.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" +#include "dpcd_defs.h" enum dc_status core_link_read_dpcd( struct core_link* link, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f786a17de1fd..61456f96419e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -27,7 +27,6 @@ #define DC_INTERFACE_H_ #include "dc_types.h" -#include "dpcd_defs.h" #include "grph_object_defs.h" #include "logger_types.h" #include "gpio_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index befc4985fe54..1666f10a1e5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -102,4 +102,363 @@ struct dc_link_training_settings { struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]; }; + +union dpcd_rev { + struct { + uint8_t MINOR:4; + uint8_t MAJOR:4; + } bits; + uint8_t raw; +}; + +union max_lane_count { + struct { + uint8_t MAX_LANE_COUNT:5; + uint8_t POST_LT_ADJ_REQ_SUPPORTED:1; + uint8_t TPS3_SUPPORTED:1; + uint8_t ENHANCED_FRAME_CAP:1; + } bits; + uint8_t raw; +}; + +union max_down_spread { + struct { + uint8_t MAX_DOWN_SPREAD:1; + uint8_t RESERVED:5; + uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1; + uint8_t TPS4_SUPPORTED:1; + } bits; + uint8_t raw; +}; + +union mstm_cap { + struct { + uint8_t MST_CAP:1; + uint8_t RESERVED:7; + } bits; + uint8_t raw; +}; + +union lane_count_set { + struct { + uint8_t LANE_COUNT_SET:5; + uint8_t POST_LT_ADJ_REQ_GRANTED:1; + uint8_t RESERVED:1; + uint8_t ENHANCED_FRAMING:1; + } bits; + uint8_t raw; +}; + +union lane_status { + struct { + uint8_t CR_DONE_0:1; + uint8_t CHANNEL_EQ_DONE_0:1; + uint8_t SYMBOL_LOCKED_0:1; + uint8_t RESERVED0:1; + uint8_t CR_DONE_1:1; + uint8_t CHANNEL_EQ_DONE_1:1; + uint8_t SYMBOL_LOCKED_1:1; + uint8_t RESERVED_1:1; + } bits; + uint8_t raw; +}; + +union device_service_irq { + struct { + uint8_t REMOTE_CONTROL_CMD_PENDING:1; + uint8_t AUTOMATED_TEST:1; + uint8_t CP_IRQ:1; + uint8_t MCCS_IRQ:1; + uint8_t DOWN_REP_MSG_RDY:1; + uint8_t UP_REQ_MSG_RDY:1; + uint8_t SINK_SPECIFIC:1; + uint8_t reserved:1; + } bits; + uint8_t raw; +}; + +union sink_count { + struct { + uint8_t SINK_COUNT:6; + uint8_t CPREADY:1; + uint8_t RESERVED:1; + } bits; + uint8_t raw; +}; + +union lane_align_status_updated { + struct { + uint8_t INTERLANE_ALIGN_DONE:1; + uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; + uint8_t RESERVED:4; + uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; + uint8_t LINK_STATUS_UPDATED:1; + } bits; + uint8_t raw; +}; + +union lane_adjust { + struct { + uint8_t VOLTAGE_SWING_LANE:2; + uint8_t PRE_EMPHASIS_LANE:2; + uint8_t RESERVED:4; + } bits; + uint8_t raw; +}; + +union dpcd_training_pattern { + struct { + uint8_t TRAINING_PATTERN_SET:4; + uint8_t RECOVERED_CLOCK_OUT_EN:1; + uint8_t SCRAMBLING_DISABLE:1; + uint8_t SYMBOL_ERROR_COUNT_SEL:2; + } v1_4; + struct { + uint8_t TRAINING_PATTERN_SET:2; + uint8_t LINK_QUAL_PATTERN_SET:2; + uint8_t RESERVED:4; + } v1_3; + uint8_t raw; +}; + +/* Training Lane is used to configure downstream DP device's voltage swing +and pre-emphasis levels*/ +/* The DPCD addresses are from 0x103 to 0x106*/ +union dpcd_training_lane { + struct { + uint8_t VOLTAGE_SWING_SET:2; + uint8_t MAX_SWING_REACHED:1; + uint8_t PRE_EMPHASIS_SET:2; + uint8_t MAX_PRE_EMPHASIS_REACHED:1; + uint8_t RESERVED:2; + } bits; + uint8_t raw; +}; + +/* TMDS-converter related */ +union dwnstream_port_caps_byte0 { + struct { + uint8_t DWN_STRM_PORTX_TYPE:3; + uint8_t DWN_STRM_PORTX_HPD:1; + uint8_t RESERVERD:4; + } bits; + uint8_t raw; +}; + +/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/ +enum dpcd_downstream_port_detailed_type { + DOWN_STREAM_DETAILED_DP = 0, + DOWN_STREAM_DETAILED_VGA, + DOWN_STREAM_DETAILED_DVI, + DOWN_STREAM_DETAILED_HDMI, + DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/ + DOWN_STREAM_DETAILED_DP_PLUS_PLUS +}; + +union dwnstream_port_caps_byte2 { + struct { + uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; + uint8_t RESERVED:6; + } bits; + uint8_t raw; +}; + +union dp_downstream_port_present { + uint8_t byte; + struct { + uint8_t PORT_PRESENT:1; + uint8_t PORT_TYPE:2; + uint8_t FMT_CONVERSION:1; + uint8_t DETAILED_CAPS:1; + uint8_t RESERVED:3; + } fields; +}; + +union dwnstream_port_caps_byte3_dvi { + struct { + uint8_t RESERVED1:1; + uint8_t DUAL_LINK:1; + uint8_t HIGH_COLOR_DEPTH:1; + uint8_t RESERVED2:5; + } bits; + uint8_t raw; +}; + +union dwnstream_port_caps_byte3_hdmi { + struct { + uint8_t FRAME_SEQ_TO_FRAME_PACK:1; + uint8_t RESERVED:7; + } bits; + uint8_t raw; +}; + +/*4-byte structure for detailed capabilities of a down-stream port +(DP-to-TMDS converter).*/ + +union sink_status { + struct { + uint8_t RX_PORT0_STATUS:1; + uint8_t RX_PORT1_STATUS:1; + uint8_t RESERVED:6; + } bits; + uint8_t raw; +}; + +/*6-byte structure corresponding to 6 registers (200h-205h) +read during handling of HPD-IRQ*/ +union hpd_irq_data { + struct { + union sink_count sink_cnt;/* 200h */ + union device_service_irq device_service_irq;/* 201h */ + union lane_status lane01_status;/* 202h */ + union lane_status lane23_status;/* 203h */ + union lane_align_status_updated lane_status_updated;/* 204h */ + union sink_status sink_status; + } bytes; + uint8_t raw[6]; +}; + +union down_stream_port_count { + struct { + uint8_t DOWN_STR_PORT_COUNT:4; + uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/ + /*Bit 6 = MSA_TIMING_PAR_IGNORED + 0 = Sink device requires the MSA timing parameters + 1 = Sink device is capable of rendering incoming video + stream without MSA timing parameters*/ + uint8_t IGNORE_MSA_TIMING_PARAM:1; + /*Bit 7 = OUI Support + 0 = OUI not supported + 1 = OUI supported + (OUI and Device Identification mandatory for DP 1.2)*/ + uint8_t OUI_SUPPORT:1; + } bits; + uint8_t raw; +}; + +union down_spread_ctrl { + struct { + uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/ + /* Bits 4 = SPREAD_AMP. Spreading amplitude + 0 = Main link signal is not downspread + 1 = Main link signal is downspread <= 0.5% + with frequency in the range of 30kHz ~ 33kHz*/ + uint8_t SPREAD_AMP:1; + uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/ + /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN + 0 = Source device will send valid data for the MSA Timing Params + 1 = Source device may send invalid data for these MSA Timing Params*/ + uint8_t IGNORE_MSA_TIMING_PARAM:1; + } bits; + uint8_t raw; +}; + +union dpcd_edp_config { + struct { + uint8_t PANEL_MODE_EDP:1; + uint8_t FRAMING_CHANGE_ENABLE:1; + uint8_t RESERVED:5; + uint8_t PANEL_SELF_TEST_ENABLE:1; + } bits; + uint8_t raw; +}; + +struct dp_device_vendor_id { + uint8_t ieee_oui[3];/*24-bit IEEE OUI*/ + uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/ +}; + +struct dp_sink_hw_fw_revision { + uint8_t ieee_hw_rev; + uint8_t ieee_fw_rev[2]; +}; + +/*DPCD register of DP receiver capability field bits-*/ +union edp_configuration_cap { + struct { + uint8_t ALT_SCRAMBLER_RESET:1; + uint8_t FRAMING_CHANGE:1; + uint8_t RESERVED:1; + uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1; + uint8_t RESERVED2:4; + } bits; + uint8_t raw; +}; + +union training_aux_rd_interval { + struct { + uint8_t TRAINIG_AUX_RD_INTERVAL:7; + uint8_t EXT_RECIEVER_CAP_FIELD_PRESENT:1; + } bits; + uint8_t raw; +}; + +/* Automated test structures */ +union test_request { + struct { + uint8_t LINK_TRAINING :1; + uint8_t LINK_TEST_PATTRN :1; + uint8_t EDID_REAT :1; + uint8_t PHY_TEST_PATTERN :1; + uint8_t AUDIO_TEST_PATTERN :1; + uint8_t RESERVED :1; + uint8_t TEST_STEREO_3D :1; + } bits; + uint8_t raw; +}; + +union test_response { + struct { + uint8_t ACK :1; + uint8_t NO_ACK :1; + uint8_t RESERVED :6; + } bits; + uint8_t raw; +}; + +union phy_test_pattern { + struct { + /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 + * and 3 bits for DP1.2. + */ + uint8_t PATTERN :3; + /* BY speci, bit7:2 is 0 for DP1.1. */ + uint8_t RESERVED :5; + } bits; + uint8_t raw; +}; + +/* States of Compliance Test Specification (CTS DP1.2). */ +union compliance_test_state { + struct { + unsigned char STEREO_3D_RUNNING : 1; + unsigned char SET_TEST_PATTERN_PENDING : 1; + unsigned char RESERVED : 6; + } bits; + unsigned char raw; +}; + +union link_test_pattern { + struct { + /* dpcd_link_test_patterns */ + unsigned char PATTERN :2; + unsigned char RESERVED:6; + } bits; + unsigned char raw; +}; + +union test_misc { + struct dpcd_test_misc_bits { + unsigned char SYNC_CLOCK :1; + /* dpcd_test_color_format */ + unsigned char CLR_FORMAT :2; + /* dpcd_test_dyn_range */ + unsigned char DYN_RANGE :1; + unsigned char YCBCR :1; + /* dpcd_test_bit_depth */ + unsigned char BPC :3; + } bits; + unsigned char raw; +}; + #endif /* DC_DP_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index fbb2729148df..adfbd3380bd5 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -381,362 +381,4 @@ enum dpcd_edp_revision { DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1, }; -union dpcd_rev { - struct { - uint8_t MINOR:4; - uint8_t MAJOR:4; - } bits; - uint8_t raw; -}; - -union max_lane_count { - struct { - uint8_t MAX_LANE_COUNT:5; - uint8_t POST_LT_ADJ_REQ_SUPPORTED:1; - uint8_t TPS3_SUPPORTED:1; - uint8_t ENHANCED_FRAME_CAP:1; - } bits; - uint8_t raw; -}; - -union max_down_spread { - struct { - uint8_t MAX_DOWN_SPREAD:1; - uint8_t RESERVED:5; - uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1; - uint8_t TPS4_SUPPORTED:1; - } bits; - uint8_t raw; -}; - -union mstm_cap { - struct { - uint8_t MST_CAP:1; - uint8_t RESERVED:7; - } bits; - uint8_t raw; -}; - -union lane_count_set { - struct { - uint8_t LANE_COUNT_SET:5; - uint8_t POST_LT_ADJ_REQ_GRANTED:1; - uint8_t RESERVED:1; - uint8_t ENHANCED_FRAMING:1; - } bits; - uint8_t raw; -}; - -union lane_status { - struct { - uint8_t CR_DONE_0:1; - uint8_t CHANNEL_EQ_DONE_0:1; - uint8_t SYMBOL_LOCKED_0:1; - uint8_t RESERVED0:1; - uint8_t CR_DONE_1:1; - uint8_t CHANNEL_EQ_DONE_1:1; - uint8_t SYMBOL_LOCKED_1:1; - uint8_t RESERVED_1:1; - } bits; - uint8_t raw; -}; - -union device_service_irq { - struct { - uint8_t REMOTE_CONTROL_CMD_PENDING:1; - uint8_t AUTOMATED_TEST:1; - uint8_t CP_IRQ:1; - uint8_t MCCS_IRQ:1; - uint8_t DOWN_REP_MSG_RDY:1; - uint8_t UP_REQ_MSG_RDY:1; - uint8_t SINK_SPECIFIC:1; - uint8_t reserved:1; - } bits; - uint8_t raw; -}; - -union sink_count { - struct { - uint8_t SINK_COUNT:6; - uint8_t CPREADY:1; - uint8_t RESERVED:1; - } bits; - uint8_t raw; -}; - -union lane_align_status_updated { - struct { - uint8_t INTERLANE_ALIGN_DONE:1; - uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; - uint8_t RESERVED:4; - uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; - uint8_t LINK_STATUS_UPDATED:1; - } bits; - uint8_t raw; -}; - -union lane_adjust { - struct { - uint8_t VOLTAGE_SWING_LANE:2; - uint8_t PRE_EMPHASIS_LANE:2; - uint8_t RESERVED:4; - } bits; - uint8_t raw; -}; - -union dpcd_training_pattern { - struct { - uint8_t TRAINING_PATTERN_SET:4; - uint8_t RECOVERED_CLOCK_OUT_EN:1; - uint8_t SCRAMBLING_DISABLE:1; - uint8_t SYMBOL_ERROR_COUNT_SEL:2; - } v1_4; - struct { - uint8_t TRAINING_PATTERN_SET:2; - uint8_t LINK_QUAL_PATTERN_SET:2; - uint8_t RESERVED:4; - } v1_3; - uint8_t raw; -}; - -/* Training Lane is used to configure downstream DP device's voltage swing -and pre-emphasis levels*/ -/* The DPCD addresses are from 0x103 to 0x106*/ -union dpcd_training_lane { - struct { - uint8_t VOLTAGE_SWING_SET:2; - uint8_t MAX_SWING_REACHED:1; - uint8_t PRE_EMPHASIS_SET:2; - uint8_t MAX_PRE_EMPHASIS_REACHED:1; - uint8_t RESERVED:2; - } bits; - uint8_t raw; -}; - -/* TMDS-converter related */ -union dwnstream_port_caps_byte0 { - struct { - uint8_t DWN_STRM_PORTX_TYPE:3; - uint8_t DWN_STRM_PORTX_HPD:1; - uint8_t RESERVERD:4; - } bits; - uint8_t raw; -}; - -/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/ -enum dpcd_downstream_port_detailed_type { - DOWN_STREAM_DETAILED_DP = 0, - DOWN_STREAM_DETAILED_VGA, - DOWN_STREAM_DETAILED_DVI, - DOWN_STREAM_DETAILED_HDMI, - DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/ - DOWN_STREAM_DETAILED_DP_PLUS_PLUS -}; - -union dwnstream_port_caps_byte2 { - struct { - uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; - uint8_t RESERVED:6; - } bits; - uint8_t raw; -}; - -union dp_downstream_port_present { - uint8_t byte; - struct { - uint8_t PORT_PRESENT:1; - uint8_t PORT_TYPE:2; - uint8_t FMT_CONVERSION:1; - uint8_t DETAILED_CAPS:1; - uint8_t RESERVED:3; - } fields; -}; - -union dwnstream_port_caps_byte3_dvi { - struct { - uint8_t RESERVED1:1; - uint8_t DUAL_LINK:1; - uint8_t HIGH_COLOR_DEPTH:1; - uint8_t RESERVED2:5; - } bits; - uint8_t raw; -}; - -union dwnstream_port_caps_byte3_hdmi { - struct { - uint8_t FRAME_SEQ_TO_FRAME_PACK:1; - uint8_t RESERVED:7; - } bits; - uint8_t raw; -}; - -/*4-byte structure for detailed capabilities of a down-stream port -(DP-to-TMDS converter).*/ - -union sink_status { - struct { - uint8_t RX_PORT0_STATUS:1; - uint8_t RX_PORT1_STATUS:1; - uint8_t RESERVED:6; - } bits; - uint8_t raw; -}; - -/*6-byte structure corresponding to 6 registers (200h-205h) -read during handling of HPD-IRQ*/ -union hpd_irq_data { - struct { - union sink_count sink_cnt;/* 200h */ - union device_service_irq device_service_irq;/* 201h */ - union lane_status lane01_status;/* 202h */ - union lane_status lane23_status;/* 203h */ - union lane_align_status_updated lane_status_updated;/* 204h */ - union sink_status sink_status; - } bytes; - uint8_t raw[6]; -}; - -union down_stream_port_count { - struct { - uint8_t DOWN_STR_PORT_COUNT:4; - uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/ - /*Bit 6 = MSA_TIMING_PAR_IGNORED - 0 = Sink device requires the MSA timing parameters - 1 = Sink device is capable of rendering incoming video - stream without MSA timing parameters*/ - uint8_t IGNORE_MSA_TIMING_PARAM:1; - /*Bit 7 = OUI Support - 0 = OUI not supported - 1 = OUI supported - (OUI and Device Identification mandatory for DP 1.2)*/ - uint8_t OUI_SUPPORT:1; - } bits; - uint8_t raw; -}; - -union down_spread_ctrl { - struct { - uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/ - /* Bits 4 = SPREAD_AMP. Spreading amplitude - 0 = Main link signal is not downspread - 1 = Main link signal is downspread <= 0.5% - with frequency in the range of 30kHz ~ 33kHz*/ - uint8_t SPREAD_AMP:1; - uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/ - /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN - 0 = Source device will send valid data for the MSA Timing Params - 1 = Source device may send invalid data for these MSA Timing Params*/ - uint8_t IGNORE_MSA_TIMING_PARAM:1; - } bits; - uint8_t raw; -}; - -union dpcd_edp_config { - struct { - uint8_t PANEL_MODE_EDP:1; - uint8_t FRAMING_CHANGE_ENABLE:1; - uint8_t RESERVED:5; - uint8_t PANEL_SELF_TEST_ENABLE:1; - } bits; - uint8_t raw; -}; - -struct dp_device_vendor_id { - uint8_t ieee_oui[3];/*24-bit IEEE OUI*/ - uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/ -}; - -struct dp_sink_hw_fw_revision { - uint8_t ieee_hw_rev; - uint8_t ieee_fw_rev[2]; -}; - -/*DPCD register of DP receiver capability field bits-*/ -union edp_configuration_cap { - struct { - uint8_t ALT_SCRAMBLER_RESET:1; - uint8_t FRAMING_CHANGE:1; - uint8_t RESERVED:1; - uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1; - uint8_t RESERVED2:4; - } bits; - uint8_t raw; -}; - -union training_aux_rd_interval { - struct { - uint8_t TRAINIG_AUX_RD_INTERVAL:7; - uint8_t EXT_RECIEVER_CAP_FIELD_PRESENT:1; - } bits; - uint8_t raw; -}; - -/* Automated test structures */ -union test_request { - struct { - uint8_t LINK_TRAINING :1; - uint8_t LINK_TEST_PATTRN :1; - uint8_t EDID_REAT :1; - uint8_t PHY_TEST_PATTERN :1; - uint8_t AUDIO_TEST_PATTERN :1; - uint8_t RESERVED :1; - uint8_t TEST_STEREO_3D :1; - } bits; - uint8_t raw; -}; - -union test_response { - struct { - uint8_t ACK :1; - uint8_t NO_ACK :1; - uint8_t RESERVED :6; - } bits; - uint8_t raw; -}; - -union phy_test_pattern { - struct { - /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 - * and 3 bits for DP1.2. - */ - uint8_t PATTERN :3; - /* BY speci, bit7:2 is 0 for DP1.1. */ - uint8_t RESERVED :5; - } bits; - uint8_t raw; -}; - -/* States of Compliance Test Specification (CTS DP1.2). */ -union compliance_test_state { - struct { - unsigned char STEREO_3D_RUNNING : 1; - unsigned char SET_TEST_PATTERN_PENDING : 1; - unsigned char RESERVED : 6; - } bits; - unsigned char raw; -}; - -union link_test_pattern { - struct { - /* dpcd_link_test_patterns */ - unsigned char PATTERN :2; - unsigned char RESERVED:6; - } bits; - unsigned char raw; -}; - -union test_misc { - struct dpcd_test_misc_bits { - unsigned char SYNC_CLOCK :1; - /* dpcd_test_color_format */ - unsigned char CLR_FORMAT :2; - /* dpcd_test_dyn_range */ - unsigned char DYN_RANGE :1; - unsigned char YCBCR :1; - /* dpcd_test_bit_depth */ - unsigned char BPC :3; - } bits; - unsigned char raw; -}; - #endif /* __DAL_DPCD_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 06e68426d430..6160a467ba37 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -27,7 +27,6 @@ #define __DAL_LINK_SERVICE_TYPES_H__ #include "grph_object_id.h" -#include "dpcd_defs.h" #include "dal_types.h" #include "irq_types.h" -- GitLab From 3a340294f7e7a784c83f9cd72f49987cc7daaced Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:11 +1000 Subject: [PATCH 0124/2898] drm/amd/display: port to using drm dpcd defines We only keep one list of these defines in the kernel, so we should use it. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 +- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 144 +++++------ .../drm/amd/display/dc/core/dc_link_hwss.c | 2 +- .../gpu/drm/amd/display/include/dpcd_defs.h | 223 +----------------- 5 files changed, 79 insertions(+), 300 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ecfca6204171..b2fc290b5385 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1158,7 +1158,7 @@ static void dpcd_configure_panel_mode( /*set edp panel mode in receiver*/ core_link_read_dpcd( link, - DPCD_ADDRESS_EDP_CONFIG_SET, + DP_EDP_CONFIGURATION_SET, &edp_config_set.raw, sizeof(edp_config_set.raw)); @@ -1170,7 +1170,7 @@ static void dpcd_configure_panel_mode( panel_mode_edp; result = core_link_write_dpcd( link, - DPCD_ADDRESS_EDP_CONFIG_SET, + DP_EDP_CONFIGURATION_SET, &edp_config_set.raw, sizeof(edp_config_set.raw)); @@ -1191,13 +1191,13 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) struct core_link *link = stream->sink->link; union down_spread_ctrl downspread; - core_link_read_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); downspread.bits.IGNORE_MSA_TIMING_PARAM = (stream->public.ignore_msa_timing_param) ? 1 : 0; - core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 6379ccfdb06e..cd66941b2c59 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -872,7 +872,7 @@ void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( enum { DP_SINK_CAP_SIZE = - DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1 + DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV + 1 }; bool dal_ddc_service_query_ddc_data( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 2585ec332e58..7238bfe0a068 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -70,7 +70,7 @@ static void wait_for_training_aux_rd_interval( * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */ core_link_read_dpcd( link, - DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL, + DP_TRAINING_AUX_RD_INTERVAL, (uint8_t *)&training_rd_interval, sizeof(training_rd_interval)); @@ -93,14 +93,14 @@ static void dpcd_set_training_pattern( { core_link_write_dpcd( link, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, &dpcd_pattern.raw, 1); dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s\n %x pattern = %x\n", __func__, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, dpcd_pattern.v1_4.TRAINING_PATTERN_SET); } @@ -129,19 +129,19 @@ static void dpcd_set_link_settings( link_set_buffer[0] = rate; link_set_buffer[1] = lane_count_set.raw; - core_link_write_dpcd(link, DPCD_ADDRESS_LINK_BW_SET, + core_link_write_dpcd(link, DP_LINK_BW_SET, link_set_buffer, 2); - core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL, + core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n", __func__, - DPCD_ADDRESS_LINK_BW_SET, + DP_LINK_BW_SET, lt_settings->link_settings.link_rate, - DPCD_ADDRESS_LANE_COUNT_SET, + DP_LANE_COUNT_SET, lt_settings->link_settings.lane_count, - DPCD_ADDRESS_DOWNSPREAD_CNTL, + DP_DOWNSPREAD_CTRL, lt_settings->link_settings.link_spread); } @@ -186,7 +186,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( { union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; const uint32_t dpcd_base_lt_offset = - DPCD_ADDRESS_TRAINING_PATTERN_SET; + DP_TRAINING_PATTERN_SET; uint8_t dpcd_lt_buffer[5] = {0}; union dpcd_training_pattern dpcd_pattern = {{0}}; uint32_t lane; @@ -199,13 +199,13 @@ static void dpcd_set_lt_pattern_and_lane_settings( dpcd_pattern.v1_4.TRAINING_PATTERN_SET = hw_training_pattern_to_dpcd_training_pattern(link, pattern); - dpcd_lt_buffer[DPCD_ADDRESS_TRAINING_PATTERN_SET - dpcd_base_lt_offset] + dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - dpcd_base_lt_offset] = dpcd_pattern.raw; dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s\n %x pattern = %x\n", __func__, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, dpcd_pattern.v1_4.TRAINING_PATTERN_SET); /***************************************************************** @@ -233,7 +233,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( // 0x00103 - 0x00102 memmove( - &dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset], + &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - dpcd_base_lt_offset], dpcd_lane, size_in_bytes); @@ -241,7 +241,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( "%s:\n %x VS set = %x PE set = %x \ max VS Reached = %x max PE Reached = %x\n", __func__, - DPCD_ADDRESS_LANE0_SET, + DP_TRAINING_LANE0_SET, dpcd_lane[0].bits.VOLTAGE_SWING_SET, dpcd_lane[0].bits.PRE_EMPHASIS_SET, dpcd_lane[0].bits.MAX_SWING_REACHED, @@ -253,13 +253,13 @@ static void dpcd_set_lt_pattern_and_lane_settings( */ core_link_write_dpcd( link, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, &dpcd_pattern.raw, sizeof(dpcd_pattern.raw) ); core_link_write_dpcd( link, - DPCD_ADDRESS_LANE0_SET, + DP_TRAINING_LANE0_SET, (uint8_t *)(dpcd_lane), size_in_bytes); @@ -459,7 +459,7 @@ static void get_lane_status_and_drive_settings( core_link_read_dpcd( link, - DPCD_ADDRESS_LANE_01_STATUS, + DP_LANE0_1_STATUS, (uint8_t *)(dpcd_buf), sizeof(dpcd_buf)); @@ -478,15 +478,15 @@ static void get_lane_status_and_drive_settings( dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ", __func__, - DPCD_ADDRESS_LANE_01_STATUS, dpcd_buf[0], - DPCD_ADDRESS_LANE_23_STATUS, dpcd_buf[1]); + DP_LANE0_1_STATUS, dpcd_buf[0], + DP_LANE2_3_STATUS, dpcd_buf[1]); dm_logger_write(link->ctx->logger, LOG_HW_LINK_TRAINING, "%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n", __func__, - DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, + DP_ADJUST_REQUEST_LANE0_1, dpcd_buf[4], - DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3, + DP_ADJUST_REQUEST_LANE2_3, dpcd_buf[5]); /*copy to req_settings*/ @@ -552,7 +552,7 @@ static void dpcd_set_lane_settings( } core_link_write_dpcd(link, - DPCD_ADDRESS_LANE0_SET, + DP_TRAINING_LANE0_SET, (uint8_t *)(dpcd_lane), link_training_setting->link_settings.lane_count); @@ -579,7 +579,7 @@ static void dpcd_set_lane_settings( "%s\n %x VS set = %x PE set = %x \ max VS Reached = %x max PE Reached = %x\n", __func__, - DPCD_ADDRESS_LANE0_SET, + DP_TRAINING_LANE0_SET, dpcd_lane[0].bits.VOLTAGE_SWING_SET, dpcd_lane[0].bits.PRE_EMPHASIS_SET, dpcd_lane[0].bits.MAX_SWING_REACHED, @@ -935,7 +935,7 @@ static inline bool perform_link_training_int( core_link_write_dpcd( link, - DPCD_ADDRESS_LANE_COUNT_SET, + DP_LANE_COUNT_SET, &lane_count_set.raw, sizeof(lane_count_set)); @@ -1385,18 +1385,18 @@ static bool hpd_rx_irq_check_link_loss_status( */ dpcd_result = core_link_read_dpcd(link, - DPCD_ADDRESS_POWER_STATE, + DP_SET_POWER, &irq_reg_rx_power_state, sizeof(irq_reg_rx_power_state)); if (dpcd_result != DC_OK) { - irq_reg_rx_power_state = DP_PWR_STATE_D0; + irq_reg_rx_power_state = DP_SET_POWER_D0; dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, "%s: DPCD read failed to obtain power state.\n", __func__); } - if (irq_reg_rx_power_state == DP_PWR_STATE_D0) { + if (irq_reg_rx_power_state == DP_SET_POWER_D0) { /*2. Check that Link Status changed, before re-training.*/ @@ -1452,7 +1452,7 @@ static enum dc_status read_hpd_rx_irq_data( */ return core_link_read_dpcd( link, - DPCD_ADDRESS_SINK_COUNT, + DP_SINK_COUNT, irq_data->raw, sizeof(union hpd_irq_data)); } @@ -1536,12 +1536,12 @@ static void dp_test_send_link_training(struct core_link *link) core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_LANE_COUNT, + DP_TEST_LANE_COUNT, (unsigned char *)(&link_settings.lane_count), 1); core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_LINK_RATE, + DP_TEST_LINK_RATE, (unsigned char *)(&link_settings.link_rate), 1); @@ -1558,8 +1558,8 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) union lane_adjust dpcd_lane_adjustment[2]; unsigned char dpcd_post_cursor_2_adjustment = 0; unsigned char test_80_bit_pattern[ - (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 - - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; + (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; enum dp_test_pattern test_pattern; struct dc_link_training_settings link_settings; union lane_adjust dpcd_lane_adjust; @@ -1574,12 +1574,12 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) /* get phy test pattern and pattern parameters from DP receiver */ core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_PHY_PATTERN, + DP_TEST_PHY_PATTERN, &dpcd_test_pattern.raw, sizeof(dpcd_test_pattern)); core_link_read_dpcd( link, - DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1, + DP_ADJUST_REQUEST_LANE0_1, &dpcd_lane_adjustment[0].raw, sizeof(dpcd_lane_adjustment)); @@ -1591,7 +1591,7 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) */ core_link_read_dpcd( link, - DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2, + DP_ADJUST_REQUEST_POST_CURSOR2, &dpcd_post_cursor_2_adjustment, sizeof(dpcd_post_cursor_2_adjustment)); @@ -1620,7 +1620,7 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0, + DP_TEST_80BIT_CUSTOM_PATTERN_7_0, test_80_bit_pattern, sizeof(test_80_bit_pattern)); @@ -1660,8 +1660,8 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) test_pattern, &link_training_settings, test_80_bit_pattern, - (DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 - - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); + (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); } static void dp_test_send_link_test_pattern(struct core_link *link) @@ -1676,12 +1676,12 @@ static void dp_test_send_link_test_pattern(struct core_link *link) /* get link test pattern and pattern parameters */ core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_PATTERN, + DP_TEST_PATTERN, &dpcd_test_pattern.raw, sizeof(dpcd_test_pattern)); core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_MISC1, + DP_TEST_MISC0, &dpcd_test_params.raw, sizeof(dpcd_test_params)); @@ -1721,7 +1721,7 @@ static void handle_automated_test(struct core_link *link) core_link_read_dpcd( link, - DPCD_ADDRESS_TEST_REQUEST, + DP_TEST_REQUEST, &test_request.raw, sizeof(union test_request)); if (test_request.bits.LINK_TRAINING) { @@ -1729,7 +1729,7 @@ static void handle_automated_test(struct core_link *link) test_response.bits.ACK = 1; core_link_write_dpcd( link, - DPCD_ADDRESS_TEST_RESPONSE, + DP_TEST_RESPONSE, &test_response.raw, sizeof(test_response)); dp_test_send_link_training(link); @@ -1754,7 +1754,7 @@ static void handle_automated_test(struct core_link *link) if (test_response.bits.ACK) core_link_write_dpcd( link, - DPCD_ADDRESS_TEST_RESPONSE, + DP_TEST_RESPONSE, &test_response.raw, sizeof(test_response)); } @@ -1792,7 +1792,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) device_service_clear.bits.AUTOMATED_TEST = 1; core_link_write_dpcd( link, - DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR, + DP_DEVICE_SERVICE_IRQ_VECTOR, &device_service_clear.raw, sizeof(device_service_clear.raw)); device_service_clear.raw = 0; @@ -1872,12 +1872,12 @@ bool is_mst_supported(struct core_link *link) rev.raw = 0; cap.raw = 0; - st = core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, &rev.raw, + st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw, sizeof(rev)); if (st == DC_OK && rev.raw >= DPCD_REV_12) { - st = core_link_read_dpcd(link, DPCD_ADDRESS_MSTM_CAP, + st = core_link_read_dpcd(link, DP_MSTM_CAP, &cap.raw, sizeof(cap)); if (st == DC_OK && cap.bits.MST_CAP == 1) mst = true; @@ -1926,7 +1926,7 @@ static void get_active_converter_info( uint8_t det_caps[4]; union dwnstream_port_caps_byte0 *port_caps = (union dwnstream_port_caps_byte0 *)det_caps; - core_link_read_dpcd(link, DPCD_ADDRESS_DWN_STRM_PORT0_CAPS, + core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0, det_caps, sizeof(det_caps)); switch (port_caps->bits.DWN_STRM_PORTX_TYPE) { @@ -1962,7 +1962,7 @@ static void get_active_converter_info( /* read IEEE branch device id */ core_link_read_dpcd( link, - DPCD_ADDRESS_BRANCH_DEVICE_ID_START, + DP_BRANCH_OUI, (uint8_t *)&dp_id, sizeof(dp_id)); @@ -1982,7 +1982,7 @@ static void get_active_converter_info( core_link_read_dpcd( link, - DPCD_ADDRESS_BRANCH_REVISION_START, + DP_BRANCH_REVISION_START, (uint8_t *)&dp_hw_fw_revision, sizeof(dp_hw_fw_revision)); @@ -2000,16 +2000,16 @@ static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, if (!link->dpcd_caps.dpcd_rev.raw) { do { dp_receiver_power_ctrl(link, true); - core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, + core_link_read_dpcd(link, DP_DPCD_REV, dpcd_data, length); link->dpcd_caps.dpcd_rev.raw = dpcd_data[ - DPCD_ADDRESS_DPCD_REV - - DPCD_ADDRESS_DPCD_REV]; + DP_DPCD_REV - + DP_DPCD_REV]; } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw); } - ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - - DPCD_ADDRESS_DPCD_REV]; + ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT - + DP_DPCD_REV]; if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) { switch (link->dpcd_caps.branch_dev_id) { @@ -2037,14 +2037,14 @@ static void retrieve_psr_link_cap(struct core_link *link, { if (edp_revision >= EDP_REVISION_13) { core_link_read_dpcd(link, - DPCD_ADDRESS_PSR_SUPPORT_VER, + DP_PSR_SUPPORT, (uint8_t *)(&link->public.psr_caps), sizeof(link->public.psr_caps)); if (link->public.psr_caps.psr_version != 0) { unsigned char psr_capability = 0; core_link_read_dpcd(link, - DPCD_ADDRESS_PSR_CAPABILITY, + DP_PSR_CAPS, &psr_capability, sizeof(psr_capability)); /* Bit 0 determines whether fast link training is @@ -2064,7 +2064,7 @@ static void retrieve_psr_link_cap(struct core_link *link, static void retrieve_link_cap(struct core_link *link) { - uint8_t dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL - DPCD_ADDRESS_DPCD_REV + 1]; + uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1]; union down_stream_port_count down_strm_port_count; union edp_configuration_cap edp_config_cap; @@ -2078,30 +2078,30 @@ static void retrieve_link_cap(struct core_link *link) core_link_read_dpcd( link, - DPCD_ADDRESS_DPCD_REV, + DP_DPCD_REV, dpcd_data, sizeof(dpcd_data)); link->dpcd_caps.dpcd_rev.raw = - dpcd_data[DPCD_ADDRESS_DPCD_REV - DPCD_ADDRESS_DPCD_REV]; + dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; { union training_aux_rd_interval aux_rd_interval; aux_rd_interval.raw = - dpcd_data[DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL]; + dpcd_data[DP_TRAINING_AUX_RD_INTERVAL]; if (aux_rd_interval.bits.EXT_RECIEVER_CAP_FIELD_PRESENT == 1) { core_link_read_dpcd( link, - DPCD_ADDRESS_DP13_DPCD_REV, + DP_DP13_DPCD_REV, dpcd_data, sizeof(dpcd_data)); } } - ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT - - DPCD_ADDRESS_DPCD_REV]; + ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT - + DP_DPCD_REV]; get_active_converter_info(ds_port.byte, link); @@ -2111,21 +2111,21 @@ static void retrieve_link_cap(struct core_link *link) down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM; link->dpcd_caps.max_ln_count.raw = dpcd_data[ - DPCD_ADDRESS_MAX_LANE_COUNT - DPCD_ADDRESS_DPCD_REV]; + DP_MAX_LANE_COUNT - DP_DPCD_REV]; link->dpcd_caps.max_down_spread.raw = dpcd_data[ - DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV]; + DP_MAX_DOWNSPREAD - DP_DPCD_REV]; link->public.reported_link_cap.lane_count = link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; link->public.reported_link_cap.link_rate = dpcd_data[ - DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV]; + DP_MAX_LINK_RATE - DP_DPCD_REV]; link->public.reported_link_cap.link_spread = link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; edp_config_cap.raw = dpcd_data[ - DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV]; + DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV]; link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; @@ -2142,7 +2142,7 @@ static void retrieve_link_cap(struct core_link *link) /* read sink count */ core_link_read_dpcd(link, - DPCD_ADDRESS_SINK_COUNT, + DP_SINK_COUNT, &link->dpcd_caps.sink_count.raw, sizeof(link->dpcd_caps.sink_count.raw)); @@ -2151,7 +2151,7 @@ static void retrieve_link_cap(struct core_link *link) if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) { /* Read the Panel's eDP revision at DPCD 700h. */ core_link_read_dpcd(link, - DPCD_ADDRESS_EDP_REV, + DP_EDP_DPCD_REV, (uint8_t *)(&link->edp_revision), sizeof(link->edp_revision)); } @@ -2415,7 +2415,7 @@ bool dc_link_dp_set_test_pattern( (unsigned char)(pattern); core_link_write_dpcd(core_link, - DPCD_ADDRESS_LINK_QUAL_LANE0_SET, + DP_LINK_QUAL_LANE0_SET, link_qual_pattern, sizeof(link_qual_pattern)); } else if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || @@ -2428,12 +2428,12 @@ bool dc_link_dp_set_test_pattern( * setting test pattern for DP 1.1. */ core_link_read_dpcd(core_link, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, &training_pattern.raw, sizeof(training_pattern)); training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern; core_link_write_dpcd(core_link, - DPCD_ADDRESS_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_SET, &training_pattern.raw, sizeof(training_pattern)); } @@ -2452,7 +2452,7 @@ bool dc_link_dp_set_test_pattern( SET_TEST_PATTERN_PENDING = 0; test_response.bits.ACK = 1; core_link_write_dpcd(core_link, - DPCD_ADDRESS_TEST_RESPONSE, + DP_TEST_RESPONSE, &test_response.raw, sizeof(test_response)); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 0c5f16cb1d54..4febc8d2a96d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -49,7 +49,7 @@ void dp_receiver_power_ctrl(struct core_link *link, bool on) state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3; - core_link_write_dpcd(link, DPCD_ADDRESS_POWER_STATE, &state, + core_link_write_dpcd(link, DP_SET_POWER, &state, sizeof(state)); } diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index adfbd3380bd5..e6db9cee328a 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -26,223 +26,7 @@ #ifndef __DAL_DPCD_DEFS_H__ #define __DAL_DPCD_DEFS_H__ -enum dpcd_address { -/* addresses marked with 1.2 are only defined since DP 1.2 spec */ - - /* Reciever Capability Field */ - DPCD_ADDRESS_DPCD_REV = 0x00000, - DPCD_ADDRESS_MAX_LINK_RATE = 0x00001, - DPCD_ADDRESS_MAX_LANE_COUNT = 0x00002, - DPCD_ADDRESS_MAX_DOWNSPREAD = 0x00003, - DPCD_ADDRESS_NORP = 0x00004, - DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT = 0x00005, - DPCD_ADDRESS_MAIN_LINK_CHANNEL_CODING = 0x00006, - DPCD_ADDRESS_DOWNSTREAM_PORT_COUNT = 0x00007, - DPCD_ADDRESS_RECEIVE_PORT0_CAP0 = 0x00008, - DPCD_ADDRESS_RECEIVE_PORT0_CAP1 = 0x00009, - DPCD_ADDRESS_RECEIVE_PORT1_CAP0 = 0x0000A, - DPCD_ADDRESS_RECEIVE_PORT1_CAP1 = 0x0000B, - - DPCD_ADDRESS_I2C_SPEED_CNTL_CAP = 0x0000C,/*1.2*/ - DPCD_ADDRESS_EDP_CONFIG_CAP = 0x0000D,/*1.2*/ - DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL = 0x000E,/*1.2*/ - - DPCD_ADDRESS_MSTM_CAP = 0x00021,/*1.2*/ - - /* Audio Video Sync Data Feild */ - DPCD_ADDRESS_AV_GRANULARITY = 0x0023, - DPCD_ADDRESS_AUDIO_DECODE_LATENCY1 = 0x0024, - DPCD_ADDRESS_AUDIO_DECODE_LATENCY2 = 0x0025, - DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY1 = 0x0026, - DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY2 = 0x0027, - DPCD_ADDRESS_VIDEO_INTERLACED_LATENCY = 0x0028, - DPCD_ADDRESS_VIDEO_PROGRESSIVE_LATENCY = 0x0029, - DPCD_ADDRESS_AUDIO_DELAY_INSERT1 = 0x0002B, - DPCD_ADDRESS_AUDIO_DELAY_INSERT2 = 0x0002C, - DPCD_ADDRESS_AUDIO_DELAY_INSERT3 = 0x0002D, - - /* Audio capability */ - DPCD_ADDRESS_NUM_OF_AUDIO_ENDPOINTS = 0x00022, - - DPCD_ADDRESS_GUID_START = 0x00030,/*1.2*/ - DPCD_ADDRESS_GUID_END = 0x0003f,/*1.2*/ - - DPCD_ADDRESS_PSR_SUPPORT_VER = 0x00070, - DPCD_ADDRESS_PSR_CAPABILITY = 0x00071, - - DPCD_ADDRESS_DWN_STRM_PORT0_CAPS = 0x00080,/*1.2a*/ - - /* Link Configuration Field */ - DPCD_ADDRESS_LINK_BW_SET = 0x00100, - DPCD_ADDRESS_LANE_COUNT_SET = 0x00101, - DPCD_ADDRESS_TRAINING_PATTERN_SET = 0x00102, - DPCD_ADDRESS_LANE0_SET = 0x00103, - DPCD_ADDRESS_LANE1_SET = 0x00104, - DPCD_ADDRESS_LANE2_SET = 0x00105, - DPCD_ADDRESS_LANE3_SET = 0x00106, - DPCD_ADDRESS_DOWNSPREAD_CNTL = 0x00107, - DPCD_ADDRESS_I2C_SPEED_CNTL = 0x00109,/*1.2*/ - - DPCD_ADDRESS_EDP_CONFIG_SET = 0x0010A, - DPCD_ADDRESS_LINK_QUAL_LANE0_SET = 0x0010B, - DPCD_ADDRESS_LINK_QUAL_LANE1_SET = 0x0010C, - DPCD_ADDRESS_LINK_QUAL_LANE2_SET = 0x0010D, - DPCD_ADDRESS_LINK_QUAL_LANE3_SET = 0x0010E, - - DPCD_ADDRESS_LANE0_SET2 = 0x0010F,/*1.2*/ - DPCD_ADDRESS_LANE2_SET2 = 0x00110,/*1.2*/ - - DPCD_ADDRESS_MSTM_CNTL = 0x00111,/*1.2*/ - - DPCD_ADDRESS_PSR_ENABLE_CFG = 0x0170, - - /* Payload Table Configuration Field 1.2 */ - DPCD_ADDRESS_PAYLOAD_ALLOCATE_SET = 0x001C0, - DPCD_ADDRESS_PAYLOAD_ALLOCATE_START_TIMESLOT = 0x001C1, - DPCD_ADDRESS_PAYLOAD_ALLOCATE_TIMESLOT_COUNT = 0x001C2, - - DPCD_ADDRESS_SINK_COUNT = 0x0200, - DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR = 0x0201, - - /* Link / Sink Status Field */ - DPCD_ADDRESS_LANE_01_STATUS = 0x00202, - DPCD_ADDRESS_LANE_23_STATUS = 0x00203, - DPCD_ADDRESS_LANE_ALIGN_STATUS_UPDATED = 0x0204, - DPCD_ADDRESS_SINK_STATUS = 0x0205, - - /* Adjust Request Field */ - DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1 = 0x0206, - DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3 = 0x0207, - DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2 = 0x020C, - - /* Test Request Field */ - DPCD_ADDRESS_TEST_REQUEST = 0x0218, - DPCD_ADDRESS_TEST_LINK_RATE = 0x0219, - DPCD_ADDRESS_TEST_LANE_COUNT = 0x0220, - DPCD_ADDRESS_TEST_PATTERN = 0x0221, - DPCD_ADDRESS_TEST_MISC1 = 0x0232, - - /* Phy Test Pattern Field */ - DPCD_ADDRESS_TEST_PHY_PATTERN = 0x0248, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0 = 0x0250, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_15_8 = 0x0251, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_23_16 = 0x0252, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_31_24 = 0x0253, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_39_32 = 0x0254, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_47_40 = 0x0255, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_55_48 = 0x0256, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_63_56 = 0x0257, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_71_64 = 0x0258, - DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 = 0x0259, - - /* Test Response Field*/ - DPCD_ADDRESS_TEST_RESPONSE = 0x0260, - - /* Audio Test Pattern Field 1.2*/ - DPCD_ADDRESS_TEST_AUDIO_MODE = 0x0271, - DPCD_ADDRESS_TEST_AUDIO_PATTERN_TYPE = 0x0272, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_1 = 0x0273, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_2 = 0x0274, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_3 = 0x0275, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_4 = 0x0276, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_5 = 0x0277, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_6 = 0x0278, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_7 = 0x0279, - DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_8 = 0x027A, - - /* Payload Table Status Field */ - DPCD_ADDRESS_PAYLOAD_TABLE_UPDATE_STATUS = 0x002C0,/*1.2*/ - DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT1 = 0x002C1,/*1.2*/ - DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT63 = 0x002FF,/*1.2*/ - - /* Source Device Specific Field */ - DPCD_ADDRESS_SOURCE_DEVICE_ID_START = 0x0300, - DPCD_ADDRESS_SOURCE_DEVICE_ID_END = 0x0301, - DPCD_ADDRESS_AMD_INTERNAL_DEBUG_START = 0x030C, - DPCD_ADDRESS_AMD_INTERNAL_DEBUG_END = 0x030F, - DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_START = 0x0310, - DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_END = 0x037F, - DPCD_ADDRESS_SOURCE_RESERVED_START = 0x0380, - DPCD_ADDRESS_SOURCE_RESERVED_END = 0x03FF, - - /* Sink Device Specific Field */ - DPCD_ADDRESS_SINK_DEVICE_ID_START = 0x0400, - DPCD_ADDRESS_SINK_DEVICE_ID_END = 0x0402, - DPCD_ADDRESS_SINK_DEVICE_STR_START = 0x0403, - DPCD_ADDRESS_SINK_DEVICE_STR_END = 0x0408, - DPCD_ADDRESS_SINK_REVISION_START = 0x409, - DPCD_ADDRESS_SINK_REVISION_END = 0x40B, - - /* Branch Device Specific Field */ - DPCD_ADDRESS_BRANCH_DEVICE_ID_START = 0x0500, - DPCD_ADDRESS_BRANCH_DEVICE_ID_END = 0x0502, - DPCD_ADDRESS_BRANCH_DEVICE_STR_START = 0x0503, - DPCD_ADDRESS_BRANCH_DEVICE_STR_END = 0x0508, - DPCD_ADDRESS_BRANCH_REVISION_START = 0x0509, - DPCD_ADDRESS_BRANCH_REVISION_END = 0x050B, - - DPCD_ADDRESS_POWER_STATE = 0x0600, - - /* EDP related */ - DPCD_ADDRESS_EDP_REV = 0x0700, - DPCD_ADDRESS_EDP_CAPABILITY = 0x0701, - DPCD_ADDRESS_EDP_BACKLIGHT_ADJUST_CAP = 0x0702, - DPCD_ADDRESS_EDP_GENERAL_CAP2 = 0x0703, - - DPCD_ADDRESS_EDP_DISPLAY_CONTROL = 0x0720, - DPCD_ADDRESS_SUPPORTED_LINK_RATES = 0x00010, /* edp 1.4 */ - DPCD_ADDRESS_EDP_BACKLIGHT_SET = 0x0721, - DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_MSB = 0x0722, - DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_LSB = 0x0723, - DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT = 0x0724, - DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MIN = 0x0725, - DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MAX = 0x0726, - DPCD_ADDRESS_EDP_BACKLIGHT_CONTROL_STATUS = 0x0727, - DPCD_ADDRESS_EDP_BACKLIGHT_FREQ_SET = 0x0728, - DPCD_ADDRESS_EDP_REVERVED = 0x0729, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MSB = 0x072A, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MID = 0x072B, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_LSB = 0x072C, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MSB = 0x072D, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MID = 0x072E, - DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_LSB = 0x072F, - - DPCD_ADDRESS_EDP_DBC_MINIMUM_BRIGHTNESS_SET = 0x0732, - DPCD_ADDRESS_EDP_DBC_MAXIMUM_BRIGHTNESS_SET = 0x0733, - - /* Sideband MSG Buffers 1.2 */ - DPCD_ADDRESS_DOWN_REQ_START = 0x01000, - DPCD_ADDRESS_DOWN_REQ_END = 0x011ff, - - DPCD_ADDRESS_UP_REP_START = 0x01200, - DPCD_ADDRESS_UP_REP_END = 0x013ff, - - DPCD_ADDRESS_DOWN_REP_START = 0x01400, - DPCD_ADDRESS_DOWN_REP_END = 0x015ff, - - DPCD_ADDRESS_UP_REQ_START = 0x01600, - DPCD_ADDRESS_UP_REQ_END = 0x017ff, - - /* ESI (Event Status Indicator) Field 1.2 */ - DPCD_ADDRESS_SINK_COUNT_ESI = 0x02002, - DPCD_ADDRESS_DEVICE_IRQ_ESI0 = 0x02003, - DPCD_ADDRESS_DEVICE_IRQ_ESI1 = 0x02004, - /*@todo move dpcd_address_Lane01Status back here*/ - - DPCD_ADDRESS_PSR_ERROR_STATUS = 0x2006, - DPCD_ADDRESS_PSR_EVENT_STATUS = 0x2007, - DPCD_ADDRESS_PSR_SINK_STATUS = 0x2008, - DPCD_ADDRESS_PSR_DBG_REGISTER0 = 0x2009, - DPCD_ADDRESS_PSR_DBG_REGISTER1 = 0x200A, - - DPCD_ADDRESS_DP13_DPCD_REV = 0x2200, - DPCD_ADDRESS_DP13_MAX_LINK_RATE = 0x2201, - - /* Travis specific addresses */ - DPCD_ADDRESS_TRAVIS_SINK_DEV_SEL = 0x5f0, - DPCD_ADDRESS_TRAVIS_SINK_ACCESS_OFFSET = 0x5f1, - DPCD_ADDRESS_TRAVIS_SINK_ACCESS_REG = 0x5f2, -}; +#include enum dpcd_revision { DPCD_REV_10 = 0x10, @@ -252,11 +36,6 @@ enum dpcd_revision { DPCD_REV_14 = 0x14 }; -enum dp_pwr_state { - DP_PWR_STATE_D0 = 1,/* direct HW translation! */ - DP_PWR_STATE_D3 -}; - /* these are the types stored at DOWNSTREAMPORT_PRESENT */ enum dpcd_downstream_port_type { DOWNSTREAM_DP = 0, -- GitLab From b39474ef0925a748d0dd43521fc1192777afd329 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Dec 2016 16:41:12 +1000 Subject: [PATCH 0125/2898] drm/amd/display: assign correct enum for edp revision There are 2 edp enum revisions, no idea why, drop one, and just assign 1.1 to the default value. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/include/dpcd_defs.h | 16 ---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 7238bfe0a068..d32bf61b66e9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2129,7 +2129,7 @@ static void retrieve_link_cap(struct core_link *link) link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; - link->edp_revision = DPCD_EDP_REVISION_EDP_UNKNOWN; + link->edp_revision = EDP_REVISION_11; link->public.test_pattern_enabled = false; link->public.compliance_test_state.raw = 0; diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index e6db9cee328a..ea8f5867e834 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -144,20 +144,4 @@ enum dpcd_psr_sink_states { PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7, }; -/* This enum defines the Panel's eDP revision at DPCD 700h - * 00h = eDP v1.1 or lower - * 01h = eDP v1.2 - * 02h = eDP v1.3 (PSR support starts here) - * 03h = eDP v1.4 - * If unknown revision, treat as eDP v1.1, meaning least functionality set. - * This enum has values matched to eDP spec, thus values should not change. - */ -enum dpcd_edp_revision { - DPCD_EDP_REVISION_EDP_V1_1 = 0, - DPCD_EDP_REVISION_EDP_V1_2 = 1, - DPCD_EDP_REVISION_EDP_V1_3 = 2, - DPCD_EDP_REVISION_EDP_V1_4 = 3, - DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1, -}; - #endif /* __DAL_DPCD_DEFS_H__ */ -- GitLab From 5ce0183cdd00d9c9e57405fa5a06d2a97b747aeb Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Mon, 12 Dec 2016 16:57:40 -0500 Subject: [PATCH 0126/2898] drm/amd/display: Framework for degamma and regramma through color module Signed-off-by: Amy Zhang Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/color/color.c | 575 +++++++++++++++--- .../amd/display/modules/color/color_helper.h | 2 +- .../drm/amd/display/modules/inc/mod_color.h | 115 +++- 3 files changed, 598 insertions(+), 94 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 6613ff9f4d28..938867282d04 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -63,14 +63,18 @@ struct gamut_src_dst_matrix { struct color_state { bool user_enable_color_temperature; int custom_color_temperature; - struct color_space_coordinates source_gamut; - struct color_space_coordinates destination_gamut; struct color_range contrast; struct color_range saturation; struct color_range brightness; struct color_range hue; struct dc_gamma *gamma; enum dc_quantization_range preferred_quantization_range; + + struct color_gamut_data source_gamut; + struct color_gamut_data destination_gamut; + enum color_transfer_func input_transfer_function; + enum color_transfer_func output_transfer_function; + struct color_mastering_info mastering_info; }; struct core_color { @@ -79,6 +83,7 @@ struct core_color { int num_sinks; struct sink_caps *caps; struct color_state *state; + struct color_edid_caps *edid_caps; }; #define MOD_COLOR_TO_CORE(mod_color)\ @@ -1286,6 +1291,142 @@ static struct dc_surface *dc_stream_to_surface_from_pipe_ctx( return out_surface; } +static enum predefined_gamut_type color_space_to_predefined_gamut_types(enum + color_color_space color_space) +{ + switch (color_space) { + case color_space_bt709: + case color_space_xv_ycc_bt709: + return gamut_type_bt709; + case color_space_bt601: + case color_space_xv_ycc_bt601: + return gamut_type_bt601; + case color_space_adobe: + return gamut_type_adobe_rgb; + case color_space_srgb: + case color_space_sc_rgb_ms_ref: + return gamut_type_srgb; + case color_space_bt2020: + return gamut_type_bt2020; + case color_space_dci_p3: /* TODO */ + default: + return gamut_type_unknown; + } +} + +static enum predefined_white_point_type white_point_to_predefined_white_point + (enum color_white_point_type white_point) +{ + switch (white_point) { + case color_white_point_type_5000k_horizon: + return white_point_type_5000k_horizon; + case color_white_point_type_6500k_noon: + return white_point_type_6500k_noon; + case color_white_point_type_7500k_north_sky: + return white_point_type_7500k_north_sky; + case color_white_point_type_9300k: + return white_point_type_9300k; + default: + return white_point_type_unknown; + } +} + +static bool update_color_gamut_data(struct color_gamut_data *input_data, + struct color_gamut_data *output_data) +{ + bool output_custom_cs = false; + bool output_custom_wp = false; + + if (input_data == NULL || output_data == NULL) + return false; + + if (input_data->color_space == color_space_custom_coordinates) { + output_data->color_space = input_data->color_space; + output_data->gamut.redX = input_data->gamut.redX; + output_data->gamut.redY = input_data->gamut.redY; + output_data->gamut.greenX = input_data->gamut.greenX; + output_data->gamut.greenY = input_data->gamut.greenY; + output_data->gamut.blueX = input_data->gamut.blueX; + output_data->gamut.blueY = input_data->gamut.blueY; + } else { + struct gamut_space_coordinates gamut_coord; + enum predefined_gamut_type gamut_type = + color_space_to_predefined_gamut_types + (input_data->color_space); + + /* fall back to original color space if unknown */ + if (gamut_type == gamut_type_unknown) { + if (output_data->color_space == + color_space_custom_coordinates) { + output_custom_cs = true; + } else { + gamut_type = + color_space_to_predefined_gamut_types + (output_data->color_space); + /* fall back to sRGB if both unknown*/ + if (gamut_type == gamut_type_unknown) { + output_data->color_space = + color_space_srgb; + gamut_type = gamut_type_srgb; + } + } + } else { + output_data->color_space = input_data->color_space; + } + + if (!output_custom_cs) { + mod_color_find_predefined_gamut(&gamut_coord, + gamut_type); + output_data->gamut.redX = gamut_coord.redX; + output_data->gamut.redY = gamut_coord.redY; + output_data->gamut.greenX = gamut_coord.greenX; + output_data->gamut.greenY = gamut_coord.greenY; + output_data->gamut.blueX = gamut_coord.blueX; + output_data->gamut.blueY = gamut_coord.blueY; + } + } + + if (input_data->white_point == color_space_custom_coordinates) { + output_data->white_point = input_data->white_point; + output_data->gamut.whiteX = input_data->gamut.whiteX; + output_data->gamut.whiteY = input_data->gamut.whiteY; + } else { + struct white_point_coodinates white_point_coord; + enum predefined_white_point_type white_type = + white_point_to_predefined_white_point + (input_data->white_point); + + /* fall back to original white point if not found */ + if (white_type == white_point_type_unknown) { + if (output_data->white_point == + color_white_point_type_custom_coordinates) { + output_custom_wp = true; + } else { + white_type = + white_point_to_predefined_white_point + (output_data->white_point); + /* fall back to 6500 if both unknown*/ + if (white_type == white_point_type_unknown) { + output_data->white_point = + color_white_point_type_6500k_noon; + white_type = + white_point_type_6500k_noon; + } + } + } else { + output_data->white_point = input_data->white_point; + } + + if (!output_custom_wp) { + mod_color_find_predefined_white_point( + &white_point_coord, white_type); + output_data->gamut.whiteX = white_point_coord.whiteX; + output_data->gamut.whiteY = white_point_coord.whiteY; + } + } + return true; +} + struct mod_color *mod_color_create(struct dc *dc) { int i = 0; @@ -1311,23 +1452,36 @@ struct mod_color *mod_color_create(struct dc *dc) /*hardcoded to sRGB with 6500 color temperature*/ for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { - core_color->state[i].source_gamut.blueX = 1500; - core_color->state[i].source_gamut.blueY = 600; - core_color->state[i].source_gamut.greenX = 3000; - core_color->state[i].source_gamut.greenY = 6000; - core_color->state[i].source_gamut.redX = 6400; - core_color->state[i].source_gamut.redY = 3300; - core_color->state[i].source_gamut.whiteX = 3127; - core_color->state[i].source_gamut.whiteY = 3290; - - core_color->state[i].destination_gamut.blueX = 1500; - core_color->state[i].destination_gamut.blueY = 600; - core_color->state[i].destination_gamut.greenX = 3000; - core_color->state[i].destination_gamut.greenY = 6000; - core_color->state[i].destination_gamut.redX = 6400; - core_color->state[i].destination_gamut.redY = 3300; - core_color->state[i].destination_gamut.whiteX = 3127; - core_color->state[i].destination_gamut.whiteY = 3290; + core_color->state[i].source_gamut.color_space = + color_space_srgb; + core_color->state[i].source_gamut.white_point = + color_white_point_type_6500k_noon; + core_color->state[i].source_gamut.gamut.blueX = 1500; + core_color->state[i].source_gamut.gamut.blueY = 600; + core_color->state[i].source_gamut.gamut.greenX = 3000; + core_color->state[i].source_gamut.gamut.greenY = 6000; + core_color->state[i].source_gamut.gamut.redX = 6400; + core_color->state[i].source_gamut.gamut.redY = 3300; + core_color->state[i].source_gamut.gamut.whiteX = 3127; + core_color->state[i].source_gamut.gamut.whiteY = 3290; + + core_color->state[i].destination_gamut.color_space = + color_space_srgb; + core_color->state[i].destination_gamut.white_point = + color_white_point_type_6500k_noon; + core_color->state[i].destination_gamut.gamut.blueX = 1500; + core_color->state[i].destination_gamut.gamut.blueY = 600; + core_color->state[i].destination_gamut.gamut.greenX = 3000; + core_color->state[i].destination_gamut.gamut.greenY = 6000; + core_color->state[i].destination_gamut.gamut.redX = 6400; + core_color->state[i].destination_gamut.gamut.redY = 3300; + core_color->state[i].destination_gamut.gamut.whiteX = 3127; + core_color->state[i].destination_gamut.gamut.whiteY = 3290; + + core_color->state[i].input_transfer_function = + transfer_func_srgb; + core_color->state[i].output_transfer_function = + transfer_func_srgb; core_color->state[i].custom_color_temperature = 6500; @@ -1351,6 +1505,12 @@ struct mod_color *mod_color_create(struct dc *dc) if (core_color->state == NULL) goto fail_alloc_state; + core_color->edid_caps = dm_alloc(sizeof(struct color_edid_caps) * + MOD_COLOR_MAX_CONCURRENT_SINKS); + + if (core_color->edid_caps == NULL) + goto fail_alloc_edid_caps; + core_color->num_sinks = 0; if (dc == NULL) @@ -1371,6 +1531,9 @@ struct mod_color *mod_color_create(struct dc *dc) return &core_color->public; fail_construct: + dm_free(core_color->edid_caps); + +fail_alloc_edid_caps: dm_free(core_color->state); fail_alloc_state: @@ -1390,6 +1553,8 @@ void mod_color_destroy(struct mod_color *mod_color) struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + dm_free(core_color->edid_caps); + for (i = 0; i < core_color->num_sinks; i++) if (core_color->state[i].gamma) dc_gamma_release(core_color->state[i].gamma); @@ -1405,7 +1570,8 @@ void mod_color_destroy(struct mod_color *mod_color) } } -bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) +bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, + struct color_edid_caps *edid_caps) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); @@ -1426,6 +1592,11 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) core_color->state[core_color->num_sinks]. user_enable_color_temperature = true; + core_color->edid_caps[core_color->num_sinks].colorimetry_caps = + edid_caps->colorimetry_caps; + core_color->edid_caps[core_color->num_sinks].hdr_caps = + edid_caps->hdr_caps; + /* get persistent data from registry */ flag.save_per_edid = true; flag.save_per_link = false; @@ -1462,25 +1633,25 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) sizeof(struct color_space_coordinates), &flag)) { memcpy(&core_color->state[core_color->num_sinks]. - source_gamut, &persistent_source_gamut, + source_gamut.gamut, &persistent_source_gamut, sizeof(struct color_space_coordinates)); } else { core_color->state[core_color->num_sinks]. - source_gamut.blueX = 1500; + source_gamut.gamut.blueX = 1500; core_color->state[core_color->num_sinks]. - source_gamut.blueY = 600; + source_gamut.gamut.blueY = 600; core_color->state[core_color->num_sinks]. - source_gamut.greenX = 3000; + source_gamut.gamut.greenX = 3000; core_color->state[core_color->num_sinks]. - source_gamut.greenY = 6000; + source_gamut.gamut.greenY = 6000; core_color->state[core_color->num_sinks]. - source_gamut.redX = 6400; + source_gamut.gamut.redX = 6400; core_color->state[core_color->num_sinks]. - source_gamut.redY = 3300; + source_gamut.gamut.redY = 3300; core_color->state[core_color->num_sinks]. - source_gamut.whiteX = 3127; + source_gamut.gamut.whiteX = 3127; core_color->state[core_color->num_sinks]. - source_gamut.whiteY = 3290; + source_gamut.gamut.whiteY = 3290; } if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1489,26 +1660,26 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink) sizeof(struct color_space_coordinates), &flag)) { memcpy(&core_color->state[core_color->num_sinks]. - destination_gamut, + destination_gamut.gamut, &persistent_destination_gamut, sizeof(struct color_space_coordinates)); } else { core_color->state[core_color->num_sinks]. - destination_gamut.blueX = 1500; + destination_gamut.gamut.blueX = 1500; core_color->state[core_color->num_sinks]. - destination_gamut.blueY = 600; + destination_gamut.gamut.blueY = 600; core_color->state[core_color->num_sinks]. - destination_gamut.greenX = 3000; + destination_gamut.gamut.greenX = 3000; core_color->state[core_color->num_sinks]. - destination_gamut.greenY = 6000; + destination_gamut.gamut.greenY = 6000; core_color->state[core_color->num_sinks]. - destination_gamut.redX = 6400; + destination_gamut.gamut.redX = 6400; core_color->state[core_color->num_sinks]. - destination_gamut.redY = 3300; + destination_gamut.gamut.redY = 3300; core_color->state[core_color->num_sinks]. - destination_gamut.whiteX = 3127; + destination_gamut.gamut.whiteX = 3127; core_color->state[core_color->num_sinks]. - destination_gamut.whiteY = 3290; + destination_gamut.gamut.whiteY = 3290; } if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1588,6 +1759,10 @@ bool mod_color_remove_sink(struct mod_color *mod_color, memcpy(&core_color->state[j], &core_color->state[j + 1], sizeof(struct color_state)); + + memcpy(&core_color->edid_caps[j], + &core_color->edid_caps[j + 1], + sizeof(struct color_edid_caps)); } core_color->num_sinks--; @@ -1625,7 +1800,7 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, COLOR_REGISTRY_NAME, "sourcegamut", &core_color->state[sink_index]. - source_gamut, + source_gamut.gamut, sizeof(struct color_space_coordinates), &flag); @@ -1634,19 +1809,19 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, COLOR_REGISTRY_NAME, "destgamut", &core_color->state[sink_index]. - destination_gamut, + destination_gamut.gamut, sizeof(struct color_space_coordinates), &flag); if (!build_gamut_remap_matrix - (core_color->state[sink_index].source_gamut, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc)) + (core_color->state[sink_index].source_gamut.gamut, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc)) goto function_fail; if (!build_gamut_remap_matrix (core_color->state[sink_index]. - destination_gamut, + destination_gamut.gamut, matrix->rgbCoeffDst, matrix->whiteCoeffDst)) goto function_fail; @@ -1700,8 +1875,7 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, bool mod_color_adjust_source_gamut(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct gamut_space_coordinates *input_gamut_coordinates, - struct white_point_coodinates *input_white_point_coordinates) + struct color_gamut_data *input_gamut_data) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); @@ -1711,25 +1885,35 @@ bool mod_color_adjust_source_gamut(struct mod_color *mod_color, sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); - core_color->state[sink_index].source_gamut.blueX = - input_gamut_coordinates->blueX; - core_color->state[sink_index].source_gamut.blueY = - input_gamut_coordinates->blueY; - core_color->state[sink_index].source_gamut.greenX = - input_gamut_coordinates->greenX; - core_color->state[sink_index].source_gamut.greenY = - input_gamut_coordinates->greenY; - core_color->state[sink_index].source_gamut.redX = - input_gamut_coordinates->redX; - core_color->state[sink_index].source_gamut.redY = - input_gamut_coordinates->redY; - core_color->state[sink_index].source_gamut.whiteX = - input_white_point_coordinates->whiteX; - core_color->state[sink_index].source_gamut.whiteY = - input_white_point_coordinates->whiteY; + update_color_gamut_data(input_gamut_data, + &core_color->state[sink_index].source_gamut); } - if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) + if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) + return false; + + return true; +} + +bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct color_gamut_data *input_gamut_data, + enum color_transfer_func input_transfer_func) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + update_color_gamut_data(input_gamut_data, + &core_color->state[sink_index].source_gamut); + core_color->state[sink_index].input_transfer_function = + input_transfer_func; + } + + if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) return false; return true; @@ -1737,8 +1921,7 @@ bool mod_color_adjust_source_gamut(struct mod_color *mod_color, bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct gamut_space_coordinates *input_gamut_coordinates, - struct white_point_coodinates *input_white_point_coordinates) + struct color_gamut_data *input_gamut_data) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); @@ -1748,22 +1931,8 @@ bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); - core_color->state[sink_index].destination_gamut.blueX = - input_gamut_coordinates->blueX; - core_color->state[sink_index].destination_gamut.blueY = - input_gamut_coordinates->blueY; - core_color->state[sink_index].destination_gamut.greenX = - input_gamut_coordinates->greenX; - core_color->state[sink_index].destination_gamut.greenY = - input_gamut_coordinates->greenY; - core_color->state[sink_index].destination_gamut.redX = - input_gamut_coordinates->redX; - core_color->state[sink_index].destination_gamut.redY = - input_gamut_coordinates->redY; - core_color->state[sink_index].destination_gamut.whiteX = - input_white_point_coordinates->whiteX; - core_color->state[sink_index].destination_gamut.whiteY = - input_white_point_coordinates->whiteY; + update_color_gamut_data(input_gamut_data, + &core_color->state[sink_index].destination_gamut); } if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) @@ -1784,9 +1953,9 @@ bool mod_color_set_white_point(struct mod_color *mod_color, stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); - core_color->state[sink_index].source_gamut.whiteX = + core_color->state[sink_index].source_gamut.gamut.whiteX = white_point->whiteX; - core_color->state[sink_index].source_gamut.whiteY = + core_color->state[sink_index].source_gamut.gamut.whiteY = white_point->whiteY; } @@ -1796,6 +1965,39 @@ bool mod_color_set_white_point(struct mod_color *mod_color, return true; } + +bool mod_color_set_mastering_info(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct color_mastering_info *mastering_info) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + unsigned int stream_index, sink_index; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + memcpy(&core_color->state[sink_index].mastering_info, + mastering_info, + sizeof(struct color_mastering_info)); + } + return true; +} + +bool mod_color_get_mastering_info(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_mastering_info *mastering_info) +{ + struct core_color *core_color = + MOD_COLOR_TO_CORE(mod_color); + + unsigned int sink_index = sink_index_from_sink(core_color, sink); + + memcpy(mastering_info, &core_color->state[sink_index].mastering_info, + sizeof(struct color_mastering_info)); + + return true; +} + bool mod_color_set_user_enable(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, bool user_enable) @@ -1953,7 +2155,7 @@ bool mod_color_get_source_gamut(struct mod_color *mod_color, unsigned int sink_index = sink_index_from_sink(core_color, sink); - *source_gamut = core_color->state[sink_index].source_gamut; + *source_gamut = core_color->state[sink_index].source_gamut.gamut; return true; } @@ -1973,14 +2175,14 @@ bool mod_color_notify_mode_change(struct mod_color *mod_color, streams[stream_index]->sink); if (!build_gamut_remap_matrix - (core_color->state[sink_index].source_gamut, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc)) + (core_color->state[sink_index].source_gamut.gamut, + matrix->rgbCoeffSrc, + matrix->whiteCoeffSrc)) goto function_fail; if (!build_gamut_remap_matrix (core_color->state[sink_index]. - destination_gamut, + destination_gamut.gamut, matrix->rgbCoeffDst, matrix->whiteCoeffDst)) goto function_fail; @@ -2379,3 +2581,200 @@ bool mod_color_is_rgb_limited_range_supported_for_timing( return result; } + +bool mod_color_set_regamma(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams) +{ + /*TODO*/ + return true; +} + +bool mod_color_set_degamma(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + enum color_transfer_func transfer_function) +{ + /*TODO*/ + return true; +} + +bool mod_color_update_gamut_info(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams) +{ + struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); + unsigned int stream_index, sink_index; + bool should_defer = false; + bool is_hdr = false; + enum color_color_space source_color_space; + enum color_transfer_func input_transfer_function; + struct color_gamut_data new_gamut_source; + struct color_gamut_data new_gamut_destination; + + for (stream_index = 0; stream_index < num_streams; stream_index++) { + sink_index = sink_index_from_sink(core_color, + streams[stream_index]->sink); + source_color_space = + core_color->state[sink_index].source_gamut.color_space; + input_transfer_function = + core_color->state[sink_index].input_transfer_function; + new_gamut_source.color_space = source_color_space; + new_gamut_destination.color_space = + core_color->state[sink_index]. + destination_gamut.color_space; + + struct dc_surface *surface = + dc_stream_to_surface_from_pipe_ctx(core_color, + streams[stream_index]); + if (surface == NULL) + return false; + + if (surface->format == SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 || + surface->format == + SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010) { + + if (input_transfer_function == + transfer_func_pq2084 || + input_transfer_function == + transfer_func_pq2084_interim) { + /* For PQ and PQ interim, we bypass degamma+ + * remap+regamma, application needs to also + * handle gamut remapping + */ + /* TODO */ + is_hdr = true; + } else if (input_transfer_function == + transfer_func_linear_0_1 || + input_transfer_function == + transfer_func_linear_0_125) { + /* TF not supported in current surface format, + * but may be deferred to a later flip + */ + should_defer = true; + } else { + new_gamut_destination.color_space = + color_space_srgb; + } + } else if (surface->format == + SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || + surface->format == + SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F || + surface->format == + SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) { + if (input_transfer_function == + transfer_func_linear_0_125) { + /* Regamma PQ for HDR supported displays and + * 0-125 source + */ + if ((core_color->edid_caps[sink_index]. + hdr_caps) & smpte_st2084) + is_hdr = true; + + /* override for BT.2020 whenever PQ */ + if (core_color->state[sink_index]. + destination_gamut.color_space != + color_space_bt2020) { + if (streams[stream_index]->timing. + pixel_encoding == + PIXEL_ENCODING_RGB) { + if ((core_color-> + edid_caps[sink_index]. + colorimetry_caps) & bt_2020_rgb) + new_gamut_destination. + color_space = + color_space_bt2020; + } else { + if ((core_color-> + edid_caps[sink_index]. + colorimetry_caps) & bt_2020_ycc) + new_gamut_destination. + color_space = + color_space_bt2020; + } + } + } else if (input_transfer_function == + transfer_func_linear_0_1) { + new_gamut_destination.color_space = + color_space_srgb; + } else { + /* TF not supported in current surface format, + * but may be deferred to a later flip + */ + should_defer = true; + } + } + + /* 0. ---- CHECK DEFERRED ---- */ + if (should_defer) + return true; + + /* 1. ---- SET GAMUT SOURCE ---- */ + new_gamut_source.white_point = core_color->state[sink_index]. + source_gamut.white_point; + update_color_gamut_data(&new_gamut_source, + &core_color->state[sink_index].source_gamut); + + /* 2. ---- SET GAMUT DESTINATION ---- */ + new_gamut_destination.white_point = + core_color->state[sink_index]. + destination_gamut.white_point; + update_color_gamut_data(&new_gamut_destination, + &core_color->state[sink_index].destination_gamut); + + /* 3. ---- SET DEGAMMA ---- */ + struct dc_transfer_func *input_tf = NULL; + + input_tf = dc_create_transfer_func(core_color->dc); + + if (input_tf != NULL) { + input_tf->type = TF_TYPE_PREDEFINED; + + switch (input_transfer_function) { + case transfer_func_srgb: + input_tf->tf = TRANSFER_FUNCTION_SRGB; + break; + case transfer_func_linear_0_1: + case transfer_func_linear_0_125: + input_tf->tf = TRANSFER_FUNCTION_LINEAR; + break; + default: + dc_transfer_func_release(input_tf); + input_tf = NULL; + break; + } + } + + /* 4. ---- SET REGAMMA ---- */ + struct dc_transfer_func *output_tf = NULL; + + output_tf = dc_create_transfer_func(core_color->dc); + + if (output_tf != NULL) { + output_tf->type = TF_TYPE_PREDEFINED; + if (is_hdr) + output_tf->tf = TRANSFER_FUNCTION_PQ; + else + output_tf->tf = TRANSFER_FUNCTION_SRGB; + } + + /* 5. ---- TODO: UPDATE INFOPACKETS ---- */ + + if (!mod_color_update_gamut_to_stream( + mod_color, streams, num_streams)) + return false; + + struct dc_surface_update updates[4] = {0}; + + updates[0].surface = surface; + updates[0].gamma = core_color->state[sink_index].gamma; + updates[0].in_transfer_func = input_tf; + updates[0].out_transfer_func = output_tf; + + dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL); + + if (input_tf != NULL) + dc_transfer_func_release(input_tf); + + if (output_tf != NULL) + dc_transfer_func_release(output_tf); + } + return true; +} diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h index c0e6334b947e..b7a7ca4debd7 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.h +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.h @@ -37,7 +37,7 @@ bool mod_color_find_predefined_gamut( bool mod_color_find_predefined_white_point( struct white_point_coodinates *out_white_point, - unsigned int index); + enum predefined_white_point_type type); bool mod_color_find_white_point_from_temperature( struct white_point_coodinates *out_white_point, diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index fbf908141ba7..670b87fb8bd2 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -30,6 +30,79 @@ #include "dm_services.h" #include "color_helper.h" +enum color_transfer_func { + transfer_func_unknown, + transfer_func_srgb, + transfer_func_bt709, + transfer_func_pq2084, + transfer_func_pq2084_interim, + transfer_func_linear_0_1, + transfer_func_linear_0_125, + transfer_func_dolbyvision, + transfer_func_gamma_22, + transfer_func_gamma_26 +}; + +enum color_color_space { + color_space_unsupported, + color_space_srgb, + color_space_bt601, + color_space_bt709, + color_space_xv_ycc_bt601, + color_space_xv_ycc_bt709, + color_space_xr_rgb, + color_space_bt2020, + color_space_adobe, + color_space_dci_p3, + color_space_sc_rgb_ms_ref, + color_space_display_native, + color_space_app_ctrl, + color_space_dolby_vision, + color_space_custom_coordinates +}; + +enum color_white_point_type { + color_white_point_type_unknown, + color_white_point_type_5000k_horizon, + color_white_point_type_6500k_noon, + color_white_point_type_7500k_north_sky, + color_white_point_type_9300k, + color_white_point_type_custom_coordinates +}; + +enum colorimetry_support_flag { + xv_ycc_bt601 = 0x01, + xv_ycc_bt709 = 0x02, + s_ycc_601 = 0x04, + adobe_ycc_601 = 0x08, + adobe_rgb = 0x10, + bt_2020_c_ycc = 0x20, + bt_2020_ycc = 0x40, + bt_2020_rgb = 0x80 +}; + +enum hdr_tf_support_flag { + traditional_gamma_sdr = 0x01, + traditional_gamma_hdr = 0x02, + smpte_st2084 = 0x04 +}; + +struct color_mastering_info { + unsigned int chromaticity_green_x; + unsigned int chromaticity_green_y; + unsigned int chromaticity_blue_x; + unsigned int chromaticity_blue_y; + unsigned int chromaticity_red_x; + unsigned int chromaticity_red_y; + unsigned int chromaticity_white_point_x; + unsigned int chromaticity_white_point_y; + + unsigned int min_luminance; + unsigned int max_luminance; + unsigned int maximum_content_light_level; + unsigned int maximum_frame_average_light_level; +}; + struct mod_color { int dummy; }; @@ -86,12 +159,23 @@ struct color_range { int max; }; +struct color_gamut_data { + enum color_color_space color_space; + enum color_white_point_type white_point; + struct color_space_coordinates gamut; +}; + +struct color_edid_caps { + unsigned int colorimetry_caps; + unsigned int hdr_caps; +}; + struct mod_color *mod_color_create(struct dc *dc); void mod_color_destroy(struct mod_color *mod_color); bool mod_color_add_sink(struct mod_color *mod_color, - const struct dc_sink *sink); + const struct dc_sink *sink, struct color_edid_caps *edid_caps); bool mod_color_remove_sink(struct mod_color *mod_color, const struct dc_sink *sink); @@ -105,18 +189,29 @@ bool mod_color_set_white_point(struct mod_color *mod_color, bool mod_color_adjust_source_gamut(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct gamut_space_coordinates *input_gamut_coordinates, - struct white_point_coodinates *input_white_point_coordinates); + struct color_gamut_data *input_gamut_data); bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct gamut_space_coordinates *input_gamut_coordinates, - struct white_point_coodinates *input_white_point_coordinates); + struct color_gamut_data *input_gamut_data); + +bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct color_gamut_data *input_gamut_data, + enum color_transfer_func input_transfer_func); bool mod_color_get_user_enable(struct mod_color *mod_color, const struct dc_sink *sink, bool *user_enable); +bool mod_color_set_mastering_info(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + struct color_mastering_info *mastering_info); + +bool mod_color_get_mastering_info(struct mod_color *mod_color, + const struct dc_sink *sink, + struct color_mastering_info *mastering_info); + bool mod_color_set_user_enable(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, bool user_enable); @@ -190,4 +285,14 @@ bool mod_color_is_rgb_limited_range_supported_for_timing( const struct dc_sink *sink, const struct dc_crtc_timing *timing); +bool mod_color_set_regamma(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams); + +bool mod_color_set_degamma(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams, + enum color_transfer_func transfer_function); + +bool mod_color_update_gamut_info(struct mod_color *mod_color, + const struct dc_stream **streams, int num_streams); + #endif /* MOD_COLOR_H_ */ -- GitLab From 6f3f8d48664d0cecc559ea8c093838c13ba21192 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Mon, 19 Dec 2016 15:16:12 -0500 Subject: [PATCH 0127/2898] drm/amd/display: Fix Regamma end point 1. HW register programmed to wrong value 2. End slope for PQ case not calculated correctly Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/gamma_calcs.c | 34 +++++++++++++------ drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 4 +-- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index 5cd408dadb20..f33135b53a80 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -287,8 +287,6 @@ static bool build_hw_curve_configuration( uint32_t offset = 0; int8_t begin = curve_config->begin; int32_t region_number = 0; - struct fixed31_32 magic_number = - dal_fixed31_32_from_fraction(249, 1000); i = begin; @@ -370,10 +368,8 @@ static bool build_hw_curve_configuration( ++i; } - points[index].x = - dal_fixed31_32_add(region1, magic_number); - points[index].adjusted_x = - dal_fixed31_32_add(region1, magic_number); + points[index].x = region1; + points[index].adjusted_x = region1; *number_of_points = index; @@ -1218,7 +1214,8 @@ static void rebuild_curve_configuration_magic( struct curve_points *arr_points, struct pwl_result_data *rgb_resulted, const struct hw_x_point *coordinates_x, - uint32_t hw_points_num) + uint32_t hw_points_num, + enum dc_transfer_func_predefined tf) { struct fixed31_32 y_r; struct fixed31_32 y_g; @@ -1264,6 +1261,18 @@ static void rebuild_curve_configuration_magic( arr_points[2].y = y3_max; arr_points[2].slope = dal_fixed31_32_zero; + + /* for PQ, we want to have a straight line from last HW X point, and the + * slope to be such that we hit 1.0 at 10000 nits. + */ + if (tf == TRANSFER_FUNCTION_PQ) { + const struct fixed31_32 end_value = + dal_fixed31_32_from_int(125); + + arr_points[2].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + } } static bool convert_to_custom_float_format( @@ -1424,6 +1433,8 @@ bool calculate_regamma_params(struct pwl_params *params, struct pixel_gamma_point *coeff128_oem = NULL; struct pixel_gamma_point *coeff128 = NULL; + enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; + bool ret = false; coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); @@ -1452,6 +1463,9 @@ bool calculate_regamma_params(struct pwl_params *params, dividers.divider2 = dal_fixed31_32_from_int(2); dividers.divider3 = dal_fixed31_32_from_fraction(5, 2); + if (stream->public.out_transfer_func) + tf = stream->public.out_transfer_func->tf; + build_evenly_distributed_points( axix_x_256, 256, @@ -1460,8 +1474,7 @@ bool calculate_regamma_params(struct pwl_params *params, scale_gamma(rgb_user, ramp, dividers); - if (stream->public.out_transfer_func && - stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { + if (tf == TRANSFER_FUNCTION_PQ) { setup_distribution_points_pq(arr_curve_points, arr_points, ¶ms->hw_points_num, coordinates_x, surface->public.format); @@ -1486,7 +1499,8 @@ bool calculate_regamma_params(struct pwl_params *params, arr_points, rgb_resulted, coordinates_x, - params->hw_points_num); + params->hw_points_num, + tf); convert_to_custom_float(rgb_resulted, arr_points, params->hw_points_num); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 80443a1cccd2..653f93dd281f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -139,8 +139,8 @@ static void regamma_config_regions_and_segments( } { REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, - REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[2].custom_float_slope, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_y); + REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[2].custom_float_slope); } curve = params->arr_curve_points; -- GitLab From b76794d2e7198cf7c73f1b65dbc6dc796ac92685 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 19 Dec 2016 12:54:40 -0500 Subject: [PATCH 0128/2898] drm/amd/display: 4k split black out due to incorrect cursor - add handling to program both cursor for left and right pipe - add guard to disable cursor in case where cursor isn't visible to prevent pipe hang Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_target.c | 83 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 9 ++ .../drm/amd/display/dc/dce110/dce110_ipp.h | 3 +- .../amd/display/dc/dce110/dce110_ipp_cursor.c | 3 +- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 3 +- 5 files changed, 53 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c index 48eb7b0e0350..2531df74871a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_target.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c @@ -148,56 +148,49 @@ bool dc_target_set_cursor_attributes( struct dc_target *dc_target, const struct dc_cursor_attributes *attributes) { - uint8_t i, j; - struct core_target *target; - struct core_dc *core_dc; - struct resource_context *res_ctx; + int i, j; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); + struct resource_context *res_ctx = &core_dc->current_context->res_ctx; + bool ret = false; if (NULL == dc_target) { dm_error("DC: dc_target is NULL!\n"); return false; - } if (NULL == attributes) { dm_error("DC: attributes is NULL!\n"); return false; - } - target = DC_TARGET_TO_CORE(dc_target); - core_dc = DC_TO_CORE(target->ctx->dc); - res_ctx = &core_dc->current_context->res_ctx; + for (i = 0; i < dc_target->stream_count; i++) { + const struct dc_stream *stream = dc_target->streams[i]; - for (i = 0; i < target->public.stream_count; i++) { for (j = 0; j < MAX_PIPES; j++) { - struct input_pixel_processor *ipp = - res_ctx->pipe_ctx[j].ipp; + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j]; - if (res_ctx->pipe_ctx[j].stream != - DC_STREAM_TO_CORE(target->public.streams[i])) - continue; + if (&pipe_ctx->stream->public == stream) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; - /* As of writing of this code cursor is on the top - * plane so we only need to set it on first pipe we - * find. May need to make this code dce specific later. - */ - if (ipp->funcs->ipp_cursor_set_attributes( - ipp, attributes)) - return true; + if (ipp->funcs->ipp_cursor_set_attributes( + ipp, attributes)) + ret = true; + } } } - return false; + return ret; } bool dc_target_set_cursor_position( struct dc_target *dc_target, const struct dc_cursor_position *position) { - uint8_t i, j; - struct core_target *target; - struct core_dc *core_dc; - struct resource_context *res_ctx; + int i, j; + struct core_target *target = DC_TARGET_TO_CORE(dc_target); + struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); + struct resource_context *res_ctx = &core_dc->current_context->res_ctx; + bool ret = false; if (NULL == dc_target) { dm_error("DC: dc_target is NULL!\n"); @@ -209,29 +202,29 @@ bool dc_target_set_cursor_position( return false; } - target = DC_TARGET_TO_CORE(dc_target); - core_dc = DC_TO_CORE(target->ctx->dc); - res_ctx = &core_dc->current_context->res_ctx; + for (i = 0; i < dc_target->stream_count; i++) { + const struct dc_stream *stream = dc_target->streams[i]; - for (i = 0; i < target->public.stream_count; i++) { for (j = 0; j < MAX_PIPES; j++) { - struct input_pixel_processor *ipp = - res_ctx->pipe_ctx[j].ipp; - - if (res_ctx->pipe_ctx[j].stream != - DC_STREAM_TO_CORE(target->public.streams[i])) - continue; - - /* As of writing of this code cursor is on the top - * plane so we only need to set it on first pipe we - * find. May need to make this code dce specific later. - */ - ipp->funcs->ipp_cursor_set_position(ipp, position); - return true; + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j]; + + if (&pipe_ctx->stream->public == stream) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct dc_cursor_mi_param param = { + .pixel_clk_khz = stream->timing.pix_clk_khz, + .ref_clk_khz = 48000,/*todo refclk*/ + .viewport_x_start = pipe_ctx->scl_data.viewport.x, + .viewport_width = pipe_ctx->scl_data.viewport.width, + .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, + }; + + ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); + ret = true; + } } } - return false; + return ret; } uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target) diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 5605a5c96da7..bd603374a3c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -27,6 +27,7 @@ #define DC_HW_TYPES_H #include "os_types.h" +#include "fixed31_32.h" /****************************************************************************** * Data types for Virtual HW Layer of DAL3. @@ -359,6 +360,14 @@ struct dc_cursor_position { bool hot_spot_enable; }; +struct dc_cursor_mi_param { + unsigned int pixel_clk_khz; + unsigned int ref_clk_khz; + unsigned int viewport_x_start; + unsigned int viewport_width; + struct fixed31_32 h_scale_ratio; +}; + /* IPP related types */ /* Used by both ipp amd opp functions*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h index 60eebdecfa10..56fe3274407c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -54,7 +54,8 @@ void dce110_ipp_destroy(struct input_pixel_processor **ipp); /* CURSOR RELATED */ void dce110_ipp_cursor_set_position( struct input_pixel_processor *ipp, - const struct dc_cursor_position *position); + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param); bool dce110_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c index 95f6ca3ba5df..1cab12ba8447 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c @@ -72,7 +72,8 @@ static void program_address( void dce110_ipp_cursor_set_position( struct input_pixel_processor *ipp, - const struct dc_cursor_position *position) + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param) { struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 7e5f3e02a719..81de97568d11 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -83,7 +83,8 @@ struct ipp_funcs { /*** cursor ***/ void (*ipp_cursor_set_position)( struct input_pixel_processor *ipp, - const struct dc_cursor_position *position); + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param); bool (*ipp_cursor_set_attributes)( struct input_pixel_processor *ipp, -- GitLab From 540f7d8068a7278ee0604083aad3c88f0deab6ed Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 19 Dec 2016 18:54:15 -0500 Subject: [PATCH 0129/2898] drm/amd/display: add pitch to cursor attributes Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index bd603374a3c9..499f6b2a31f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -407,6 +407,7 @@ union dc_cursor_attribute_flags { struct dc_cursor_attributes { PHYSICAL_ADDRESS_LOC address; + uint32_t pitch; /* Width and height should correspond to cursor surface width x heigh */ uint32_t width; -- GitLab From ae799430c59edb6915e87c7c3ab972a931c796d3 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 19 Dec 2016 15:41:49 -0500 Subject: [PATCH 0130/2898] drm/amd/display: minor clock source refactor This should make it easier to share code with newer ASICs Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_clock_source.c | 68 +++++++++---------- .../drm/amd/display/dc/dce/dce_clock_source.h | 9 ++- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 3d1c32122d69..a38172bdcb5e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -465,7 +465,6 @@ static uint32_t dce110_get_pix_clk_dividers_helper ( struct pll_settings *pll_settings, struct pixel_clk_params *pix_clk_params) { - uint32_t value = 0; uint32_t field = 0; uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; @@ -473,7 +472,6 @@ static uint32_t dce110_get_pix_clk_dividers_helper ( * HW Dce80 spec: * 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB * 04 - HSYNCA, 05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */ - value = REG_READ(PLL_CNTL); REG_GET(PLL_CNTL, PLL_REF_DIV_SRC, &field); pll_settings->use_external_clk = (field > 1); @@ -807,51 +805,30 @@ static void dce112_program_pixel_clk_resync( } static bool dce110_program_pix_clk( - struct clock_source *clk_src, + struct clock_source *clock_source, struct pixel_clk_params *pix_clk_params, struct pll_settings *pll_settings) { - struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src); + struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); struct bp_pixel_clock_parameters bp_pc_params = {0}; /* First disable SS * ATOMBIOS will enable by default SS on PLL for DP, * do not disable it here */ - if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL && + if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL && !dc_is_dp_signal(pix_clk_params->signal_type) && - clk_src->ctx->dce_version <= DCE_VERSION_11_0) - disable_spread_spectrum(dce110_clk_src); + clock_source->ctx->dce_version <= DCE_VERSION_11_0) + disable_spread_spectrum(clk_src); /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ bp_pc_params.controller_id = pix_clk_params->controller_id; - bp_pc_params.pll_id = clk_src->id; + bp_pc_params.pll_id = clock_source->id; bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk; bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; bp_pc_params.signal_type = pix_clk_params->signal_type; - switch (clk_src->ctx->dce_version) { - case DCE_VERSION_11_2: - if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) { - bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = - pll_settings->use_external_clk; - bp_pc_params.flags.SET_XTALIN_REF_SRC = - !pll_settings->use_external_clk; - if (pix_clk_params->flags.SUPPORT_YCBCR420) { - bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2; - bp_pc_params.flags.SUPPORT_YUV_420 = 1; - } - } - if (dce110_clk_src->bios->funcs->set_pixel_clock( - dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) - return false; - /* Resync deep color DTO */ - if (clk_src->id != CLOCK_SOURCE_ID_DP_DTO) - dce112_program_pixel_clk_resync(dce110_clk_src, - pix_clk_params->signal_type, - pix_clk_params->color_depth, - pix_clk_params->flags.SUPPORT_YCBCR420); - break; + switch (clock_source->ctx->dce_version) { case DCE_VERSION_8_0: case DCE_VERSION_10_0: case DCE_VERSION_11_0: @@ -864,28 +841,49 @@ static bool dce110_program_pix_clk( bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC = pll_settings->use_external_clk; - if (dce110_clk_src->bios->funcs->set_pixel_clock( - dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + if (clk_src->bios->funcs->set_pixel_clock( + clk_src->bios, &bp_pc_params) != BP_RESULT_OK) return false; /* Enable SS * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock), * based on HW display PLL team, SS control settings should be programmed * during PLL Reset, but they do not have effect * until SS_EN is asserted.*/ - if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL + if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( pix_clk_params->signal_type)) { - if (!enable_spread_spectrum(dce110_clk_src, + if (!enable_spread_spectrum(clk_src, pix_clk_params->signal_type, pll_settings)) return false; /* Resync deep color DTO */ - dce110_program_pixel_clk_resync(dce110_clk_src, + dce110_program_pixel_clk_resync(clk_src, pix_clk_params->signal_type, pix_clk_params->color_depth); } break; + case DCE_VERSION_11_2: + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = + pll_settings->use_external_clk; + bp_pc_params.flags.SET_XTALIN_REF_SRC = + !pll_settings->use_external_clk; + if (pix_clk_params->flags.SUPPORT_YCBCR420) { + bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2; + bp_pc_params.flags.SUPPORT_YUV_420 = 1; + } + } + if (clk_src->bios->funcs->set_pixel_clock( + clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Resync deep color DTO */ + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) + dce112_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth, + pix_clk_params->flags.SUPPORT_YCBCR420); + break; default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 067e4ac0e67a..8ee00712ef8e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -41,6 +41,7 @@ #define CS_COMMON_REG_LIST_DCE_112(id) \ SRI(PIXCLK_RESYNC_CNTL, PHYPLL, id) + #define CS_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -48,11 +49,11 @@ CS_SF(PLL_CNTL, PLL_REF_DIV_SRC, mask_sh),\ CS_SF(PIXCLK1_RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, mask_sh),\ CS_SF(PLL_POST_DIV, PLL_POST_DIV_PIXCLK, mask_sh),\ - CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh),\ + CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh) #define CS_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ - CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh),\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) #define CS_REG_FIELD_LIST(type) \ type PLL_REF_DIV_SRC; \ @@ -61,6 +62,7 @@ type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \ type PLL_POST_DIV_PIXCLK; \ type PLL_REF_DIV; \ + type DP_DTO0_ENABLE; struct dce110_clk_src_shift { CS_REG_FIELD_LIST(uint8_t) @@ -74,6 +76,9 @@ struct dce110_clk_src_regs { uint32_t RESYNC_CNTL; uint32_t PIXCLK_RESYNC_CNTL; uint32_t PLL_CNTL; + uint32_t PHASE; + uint32_t MODULO; + uint32_t PIXEL_RATE_CNTL; }; struct dce110_clk_src { -- GitLab From 9cd09bfeb26e4ef51a6735f585784cd1b46a496c Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Mon, 19 Dec 2016 12:00:05 -0500 Subject: [PATCH 0131/2898] drm/amd/display: Add dcc param to surface Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 61456f96419e..478bdee52cd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -275,6 +275,7 @@ struct dc_surface { struct dc_plane_info { union plane_size plane_size; union dc_tiling_info tiling_info; + struct dc_plane_dcc_param dcc; enum surface_pixel_format format; enum dc_rotation_angle rotation; bool horizontal_mirror; -- GitLab From fafba6de3a142f46c78b937ae9783d2d0cab044d Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 20 Dec 2016 10:54:38 -0500 Subject: [PATCH 0132/2898] drm/amd/display: track cursor width in ipp Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 81de97568d11..e9ed167c9e41 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -35,8 +35,10 @@ /* IPP RELATED */ struct input_pixel_processor { struct dc_context *ctx; - uint32_t inst; + unsigned int inst; const struct ipp_funcs *funcs; + + unsigned int cusor_width; }; enum ipp_prescale_mode { -- GitLab From 3c25e920f011d785725985733ca2625defbf680f Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 20 Dec 2016 18:48:11 -0500 Subject: [PATCH 0133/2898] drm/amd/display: Reset gamma to NULL after release Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 938867282d04..6d1b20f6bf98 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -1748,8 +1748,10 @@ bool mod_color_remove_sink(struct mod_color *mod_color, for (i = 0; i < core_color->num_sinks; i++) { if (core_color->caps[i].sink == sink) { - if (core_color->state[i].gamma) + if (core_color->state[i].gamma) { dc_gamma_release(core_color->state[i].gamma); + core_color->state[i].gamma = NULL; + } /* To remove this sink, shift everything after down */ for (j = i; j < core_color->num_sinks - 1; j++) { -- GitLab From d7194cf6b8ddf0344e70834397d0b1af2cc5fe05 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Tue, 20 Dec 2016 20:24:24 -0500 Subject: [PATCH 0134/2898] drm/amd/display: Implement gamma correction using input LUT The dc_gamma in dc_surface will be programmed to the input LUT if provided. If dc_gamma is not provided in dc_surface regamma may be used to emulate gamma. Some refactor and cleanup included as well. Signed-off-by: Aric Cyr Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 17 +- .../drm/amd/display/dc/calcs/gamma_calcs.c | 29 +- drivers/gpu/drm/amd/display/dc/dc.h | 36 --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 10 + drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 2 - drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 4 - .../display/dc/dce110/dce110_hw_sequencer.c | 17 +- .../drm/amd/display/dc/dce110/dce110_ipp.c | 1 + .../drm/amd/display/dc/dce110/dce110_ipp.h | 11 +- .../amd/display/dc/dce110/dce110_ipp_gamma.c | 304 +++++------------- .../display/dc/dce110/dce110_opp_regamma_v.c | 1 - .../drm/amd/display/dc/dce110/dce110_opp_v.c | 2 - .../drm/amd/display/dc/dce110/dce110_opp_v.h | 4 - .../gpu/drm/amd/display/dc/dce80/dce80_ipp.c | 1 + .../gpu/drm/amd/display/dc/dce80/dce80_ipp.h | 2 - .../amd/display/dc/dce80/dce80_ipp_gamma.c | 5 - .../gpu/drm/amd/display/dc/inc/gamma_types.h | 38 --- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 4 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 - .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 - .../gpu/drm/amd/display/modules/color/color.c | 6 +- 21 files changed, 138 insertions(+), 359 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_types.h diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 364f2c970b6e..f969bfedb368 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -521,14 +521,11 @@ static void fill_gamma_from_crtc( return; for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { - gamma->gamma_ramp_rgb256x3x16.red[i] = lut[i].red; - gamma->gamma_ramp_rgb256x3x16.green[i] = lut[i].green; - gamma->gamma_ramp_rgb256x3x16.blue[i] = lut[i].blue; + gamma->red[i] = lut[i].red; + gamma->green[i] = lut[i].green; + gamma->blue[i] = lut[i].blue; } - gamma->type = GAMMA_RAMP_RBG256X3X16; - gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); - dc_surface->gamma_correction = gamma; input_tf = dc_create_transfer_func(); @@ -822,6 +819,12 @@ static void fill_stream_properties_from_drm_display_mode( stream->output_color_space = get_output_color_space(timing_out); + { + struct dc_transfer_func *tf = dc_create_transfer_func(); + tf->type = TF_TYPE_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + stream->out_transfer_func = tf; + } } static void fill_audio_info( @@ -3066,7 +3069,7 @@ static bool is_dp_capable_without_timing_msa( dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index, DP_DOWN_STREAM_PORT_COUNT, &dpcd_data, sizeof(dpcd_data)) ) - capable = dpcd_data & DP_MSA_TIMING_PAR_IGNORED? true:false; + capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; return capable; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index f33135b53a80..ca2234e4b7d2 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -573,7 +573,7 @@ static bool find_software_points( uint32_t *index_right, enum hw_point_position *pos) { - const uint32_t max_number = RGB_256X3X16 + 3; + const uint32_t max_number = INPUT_LUT_ENTRIES + 3; struct fixed31_32 left, right; @@ -686,12 +686,12 @@ static bool build_custom_gamma_mapping_coefficients_worker( return false; } - if (index_left >= RGB_256X3X16 + 3) { + if (index_left >= INPUT_LUT_ENTRIES + 3) { BREAK_TO_DEBUGGER(); return false; } - if (index_right >= RGB_256X3X16 + 3) { + if (index_right >= INPUT_LUT_ENTRIES + 3) { BREAK_TO_DEBUGGER(); return false; } @@ -958,20 +958,13 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb, const struct core_gamma *ramp, struct dividers dividers) { - const struct dc_gamma_ramp_rgb256x3x16 *gamma; + const struct dc_gamma *gamma = &ramp->public; const uint16_t max_driver = 0xFFFF; const uint16_t max_os = 0xFF00; uint16_t scaler = max_os; - uint32_t i; + uint32_t i = 0; struct pwl_float_data *rgb = pwl_rgb; - struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; - - if (ramp->public.type == GAMMA_RAMP_RBG256X3X16) - gamma = &ramp->public.gamma_ramp_rgb256x3x16; - else - return false; /* invalid option */ - - i = 0; + struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1; do { if ((gamma->red[i] > max_os) || @@ -981,7 +974,7 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb, break; } ++i; - } while (i != RGB_256X3X16); + } while (i != INPUT_LUT_ENTRIES); i = 0; @@ -995,7 +988,7 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb, ++rgb; ++i; - } while (i != RGB_256X3X16); + } while (i != INPUT_LUT_ENTRIES); rgb->r = dal_fixed31_32_mul(rgb_last->r, dividers.divider1); @@ -1110,7 +1103,7 @@ static bool calculate_interpolated_hardware_curve( return false; coeff = coeff128; - max_entries += RGB_256X3X16; + max_entries += INPUT_LUT_ENTRIES; /* TODO: float point case */ @@ -1440,13 +1433,13 @@ bool calculate_regamma_params(struct pwl_params *params, coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); if (!coordinates_x) goto coordinates_x_alloc_fail; - rgb_user = dm_alloc(sizeof(*rgb_user) * (FLOAT_GAMMA_RAMP_MAX + 3)); + rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3)); if (!rgb_user) goto rgb_user_alloc_fail; rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3)); if (!rgb_regamma) goto rgb_regamma_alloc_fail; - rgb_oem = dm_alloc(sizeof(*rgb_oem) * (FLOAT_GAMMA_RAMP_MAX + 3)); + rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3)); if (!rgb_oem) goto rgb_oem_alloc_fail; axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3)); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 478bdee52cd5..0ee6f41b6047 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -183,43 +183,9 @@ void dc_destroy(struct dc **dc); ******************************************************************************/ enum { - RGB_256X3X16 = 256, - FLOAT_GAMMA_RAMP_MAX = 1025, TRANSFER_FUNC_POINTS = 1025 }; -enum dc_gamma_ramp_type { - GAMMA_RAMP_RBG256X3X16, - GAMMA_RAMP_FLOAT, -}; - -struct float_rgb { - struct fixed32_32 red; - struct fixed32_32 green; - struct fixed32_32 blue; -}; - -struct dc_gamma_ramp_float { - struct float_rgb scale; - struct float_rgb offset; - struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX]; -}; - -struct dc_gamma_ramp_rgb256x3x16 { - uint16_t red[RGB_256X3X16]; - uint16_t green[RGB_256X3X16]; - uint16_t blue[RGB_256X3X16]; -}; - -struct dc_gamma { - enum dc_gamma_ramp_type type; - union { - struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16; - struct dc_gamma_ramp_float gamma_ramp_float; - }; - uint32_t size; -}; - enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, @@ -266,9 +232,7 @@ struct dc_surface { bool horizontal_mirror; enum plane_stereo_format stereo_format; - /* TO BE REMOVED AFTER BELOW TRANSFER FUNCTIONS IMPLEMENTED */ const struct dc_gamma *gamma_correction; - const struct dc_transfer_func *in_transfer_func; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 499f6b2a31f8..00958bdbb417 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -370,6 +370,16 @@ struct dc_cursor_mi_param { /* IPP related types */ +enum { + INPUT_LUT_ENTRIES = 256 +}; + +struct dc_gamma { + uint16_t red[INPUT_LUT_ENTRIES]; + uint16_t green[INPUT_LUT_ENTRIES]; + uint16_t blue[INPUT_LUT_ENTRIES]; +}; + /* Used by both ipp amd opp functions*/ /* TODO: to be consolidated with enum color_space */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 653f93dd281f..46b128708c7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -28,8 +28,6 @@ #include "dce_opp.h" -#include "gamma_types.h" - #include "reg_helper.h" #define REG(reg)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 1c01a83ecc50..f2828f044b96 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -29,10 +29,6 @@ #include "opp.h" #include "core_types.h" -#include "gamma_types.h" /* decprecated */ - -struct gamma_parameters; - #define FROM_DCE11_OPP(opp)\ container_of(opp, struct dce110_opp, base) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2f790753b559..e4cef9da5de1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -228,10 +228,11 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, break; default: ASSERT(false); + break; } } -static bool dce110_set_degamma( +static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { @@ -249,6 +250,9 @@ static bool dce110_set_degamma( build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); + if (surface->public.gamma_correction) + ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); + if (tf == NULL) { /* Default case if no input transfer function specified */ ipp->funcs->ipp_set_degamma(ipp, @@ -272,6 +276,7 @@ static bool dce110_set_degamma( break; default: result = false; + break; } } else { /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ @@ -303,8 +308,11 @@ static bool dce110_set_output_transfer_func( opp->funcs->opp_power_on_regamma_lut(opp, true); - if (ramp && calculate_regamma_params( - regamma_params, ramp, surface, stream)) { + if (stream->public.out_transfer_func && + stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && + stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); + } else if (ramp && calculate_regamma_params(regamma_params, ramp, surface, stream)) { opp->funcs->opp_program_regamma_pwl(opp, regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { @@ -1318,7 +1326,6 @@ enum dc_status dce110_apply_ctx_to_hw( * instead of per pipe. */ struct audio_output audio_output; - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; build_audio_output(pipe_ctx, &audio_output); @@ -1945,7 +1952,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, .update_pending_status = dce110_update_pending_status, - .set_input_transfer_func = dce110_set_degamma, + .set_input_transfer_func = dce110_set_input_transfer_func, .set_output_transfer_func = dce110_set_output_transfer_func, .power_down = dce110_power_down, .enable_accelerated_mode = dce110_enable_accelerated_mode, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c index dd69f6060bb9..86fa7657a756 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c @@ -35,6 +35,7 @@ static const struct ipp_funcs funcs = { .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, .ipp_cursor_set_position = dce110_ipp_cursor_set_position, .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_program_input_lut = dce110_ipp_program_input_lut, .ipp_set_degamma = dce110_ipp_set_degamma, }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h index 56fe3274407c..a374ef2c9d0b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -28,9 +28,6 @@ #include "ipp.h" -struct gamma_parameters; -struct dev_c_lut; - #define TO_DCE110_IPP(input_pixel_processor)\ container_of(input_pixel_processor, struct dce110_ipp, base) @@ -69,9 +66,9 @@ bool dce110_ipp_set_degamma( void dce110_ipp_program_prescale( struct input_pixel_processor *ipp, struct ipp_prescale_params *params); -/* - * Helper functions to be resused in other ASICs - */ -void dce110_helper_select_lut(struct dce110_ipp *ipp110); + +void dce110_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma); #endif /*__DC_IPP_DCE110_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c index 79a6a6dd72fc..c68914bf7af0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c @@ -32,21 +32,39 @@ #include "dce/dce_11_0_sh_mask.h" #include "dce110_ipp.h" -#include "gamma_types.h" #define DCP_REG(reg)\ - (reg + ipp110->offsets.dcp_offset) + (mm##reg + ipp110->offsets.dcp_offset) + +#define DCP_REG_SET_N(reg_name, n, ...) \ + generic_reg_update_ex(ipp110->base.ctx, \ + DCP_REG(reg_name), \ + 0, n, __VA_ARGS__) + +#define DCP_REG_SET(reg, field1, val1) \ + DCP_REG_SET_N(reg, 1, FD(reg##__##field1), val1) + +#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ + DCP_REG_SET_N(reg, 2, \ + FD(reg##__##field1), val1, \ + FD(reg##__##field2), val2) + +#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_SET_N(reg, 3, \ + FD(reg##__##field1), val1, \ + FD(reg##__##field2), val2, \ + FD(reg##__##field3), val3) + +#define DCP_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_ex(ipp110->base.ctx, \ + DCP_REG(reg_name), \ + dm_read_reg(ipp110->base.ctx, DCP_REG(reg_name)), \ + n, __VA_ARGS__) + +#define DCP_REG_UPDATE(reg, field, val) \ + DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) -enum { - MAX_INPUT_LUT_ENTRY = 256 -}; -/*PROTOTYPE DECLARATIONS*/ -static void set_lut_inc( - struct dce110_ipp *ipp110, - uint8_t inc, - bool is_float, - bool is_signed); bool dce110_ipp_set_degamma( struct input_pixel_processor *ipp, @@ -61,25 +79,11 @@ bool dce110_ipp_set_degamma( ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || mode == IPP_DEGAMMA_MODE_HW_sRGB); - set_reg_field_value( - value, - degamma_type, - DEGAMMA_CONTROL, - GRPH_DEGAMMA_MODE); - - set_reg_field_value( - value, - degamma_type, - DEGAMMA_CONTROL, - CURSOR_DEGAMMA_MODE); - - set_reg_field_value( - value, - degamma_type, + DCP_REG_SET_3( DEGAMMA_CONTROL, - CURSOR2_DEGAMMA_MODE); - - dm_write_reg(ipp110->base.ctx, DCP_REG(mmDEGAMMA_CONTROL), value); + GRPH_DEGAMMA_MODE, degamma_type, + CURSOR_DEGAMMA_MODE, degamma_type, + CURSOR2_DEGAMMA_MODE, degamma_type); return true; } @@ -90,214 +94,70 @@ void dce110_ipp_program_prescale( { struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - uint32_t prescale_control = 0; - uint32_t prescale_value = 0; - uint32_t legacy_lut_control = 0; + /* set to bypass mode first before change */ + DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, 1); - prescale_control = dm_read_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_GRPH_CONTROL)); + DCP_REG_SET_2(PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_SCALE_R, params->scale, + GRPH_PRESCALE_BIAS_R, params->bias); - if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + DCP_REG_SET_2(PRESCALE_VALUES_GRPH_G, + GRPH_PRESCALE_SCALE_G, params->scale, + GRPH_PRESCALE_BIAS_G, params->bias); - set_reg_field_value( - prescale_control, - 0, - PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS); - - /* - * If prescale is in use, then legacy lut should - * be bypassed - */ - legacy_lut_control = dm_read_reg(ipp110->base.ctx, - DCP_REG(mmINPUT_GAMMA_CONTROL)); - - set_reg_field_value( - legacy_lut_control, - 1, - INPUT_GAMMA_CONTROL, - GRPH_INPUT_GAMMA_MODE); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmINPUT_GAMMA_CONTROL), - legacy_lut_control); - } else { - set_reg_field_value( - prescale_control, - 1, - PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS); - } + DCP_REG_SET_2(PRESCALE_VALUES_GRPH_B, + GRPH_PRESCALE_SCALE_B, params->scale, + GRPH_PRESCALE_BIAS_B, params->bias); - set_reg_field_value( - prescale_value, - params->scale, - PRESCALE_VALUES_GRPH_R, - GRPH_PRESCALE_SCALE_R); - - set_reg_field_value( - prescale_value, - params->bias, - PRESCALE_VALUES_GRPH_R, - GRPH_PRESCALE_BIAS_R); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_GRPH_CONTROL), - prescale_control); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_VALUES_GRPH_R), - prescale_value); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_VALUES_GRPH_G), - prescale_value); - - dm_write_reg(ipp110->base.ctx, - DCP_REG(mmPRESCALE_VALUES_GRPH_B), - prescale_value); -} - -static void set_lut_inc( - struct dce110_ipp *ipp110, - uint8_t inc, - bool is_float, - bool is_signed) -{ - const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); - - uint32_t value = dm_read_reg(ipp110->base.ctx, addr); - - set_reg_field_value( - value, - inc, - DC_LUT_CONTROL, - DC_LUT_INC_R); - - set_reg_field_value( - value, - inc, - DC_LUT_CONTROL, - DC_LUT_INC_G); - - set_reg_field_value( - value, - inc, - DC_LUT_CONTROL, - DC_LUT_INC_B); - - set_reg_field_value( - value, - is_float, - DC_LUT_CONTROL, - DC_LUT_DATA_R_FLOAT_POINT_EN); - - set_reg_field_value( - value, - is_float, - DC_LUT_CONTROL, - DC_LUT_DATA_G_FLOAT_POINT_EN); - - set_reg_field_value( - value, - is_float, - DC_LUT_CONTROL, - DC_LUT_DATA_B_FLOAT_POINT_EN); - - set_reg_field_value( - value, - is_signed, - DC_LUT_CONTROL, - DC_LUT_DATA_R_SIGNED_EN); - - set_reg_field_value( - value, - is_signed, - DC_LUT_CONTROL, - DC_LUT_DATA_G_SIGNED_EN); - - set_reg_field_value( - value, - is_signed, - DC_LUT_CONTROL, - DC_LUT_DATA_B_SIGNED_EN); - - dm_write_reg(ipp110->base.ctx, addr, value); + if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + /* If prescale is in use, then legacy lut should be bypassed */ + DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 0); + DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 1); + } } -void dce110_helper_select_lut(struct dce110_ipp *ipp110) +static void dce110_helper_select_lut(struct dce110_ipp *ipp110) { - uint32_t value = 0; - - set_lut_inc(ipp110, 0, false, false); - - { - const uint32_t addr = DCP_REG(mmDC_LUT_WRITE_EN_MASK); - - value = dm_read_reg(ipp110->base.ctx, addr); - - /* enable all */ - set_reg_field_value( - value, - 0x7, - DC_LUT_WRITE_EN_MASK, - DC_LUT_WRITE_EN_MASK); - - dm_write_reg(ipp110->base.ctx, addr, value); - } - - { - const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE); - - value = dm_read_reg(ipp110->base.ctx, addr); + /* enable all */ + DCP_REG_SET(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, 0x7); - set_reg_field_value( - value, - 0, - DC_LUT_RW_MODE, - DC_LUT_RW_MODE); + /* 256 entry mode */ + DCP_REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); - dm_write_reg(ipp110->base.ctx, addr, value); - } - - { - const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL); + /* LUT-256, unsigned, integer, new u0.12 format */ + DCP_REG_SET_3(DC_LUT_CONTROL, + DC_LUT_DATA_R_FORMAT, 3, + DC_LUT_DATA_G_FORMAT, 3, + DC_LUT_DATA_B_FORMAT, 3); - value = dm_read_reg(ipp110->base.ctx, addr); + /* start from index 0 */ + DCP_REG_SET(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, 0); +} - /* 00 - new u0.12 */ - set_reg_field_value( - value, - 3, - DC_LUT_CONTROL, - DC_LUT_DATA_R_FORMAT); +void dce110_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - set_reg_field_value( - value, - 3, - DC_LUT_CONTROL, - DC_LUT_DATA_G_FORMAT); + dce110_helper_select_lut(ipp110); - set_reg_field_value( - value, - 3, - DC_LUT_CONTROL, - DC_LUT_DATA_B_FORMAT); + /* power on LUT memory and give it time to settle */ + DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1); + udelay(10); - dm_write_reg(ipp110->base.ctx, addr, value); + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]); + DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]); + DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]); } - { - const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX); - - value = dm_read_reg(ipp110->base.ctx, addr); + /* power off LUT memory */ + DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0); - set_reg_field_value( - value, - 0, - DC_LUT_RW_INDEX, - DC_LUT_RW_INDEX); - - dm_write_reg(ipp110->base.ctx, addr, value); - } + /* bypass prescale, enable legacy LUT */ + DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); + DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 81fcbc52e4ab..8164aa6bcb00 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -30,7 +30,6 @@ #include "dce/dce_11_0_sh_mask.h" #include "dce/dce_opp.h" -#include "gamma_types.h" static void power_on_lut(struct output_pixel_processor *opp, bool power_on, bool inputgamma, bool regamma) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index dfd63a71d214..0a9b384303d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -32,8 +32,6 @@ #include "dce/dce_opp.h" #include "dce110_opp_v.h" -#include "gamma_types.h" - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index dcdbf86fccc1..ac5937786ce3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -29,10 +29,6 @@ #include "opp.h" #include "core_types.h" -#include "gamma_types.h" /* decprecated */ - -struct gamma_parameters; - bool dce110_opp_v_construct(struct dce110_opp *opp110, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c index 86826c229d39..c195acb6e1a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c @@ -37,6 +37,7 @@ static const struct ipp_funcs funcs = { .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, .ipp_cursor_set_position = dce110_ipp_cursor_set_position, .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_program_input_lut = dce110_ipp_program_input_lut, .ipp_set_degamma = dce110_ipp_set_degamma, }; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h index d350138e5feb..06e8598d395f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h @@ -33,8 +33,6 @@ struct dce110_ipp; struct dce110_ipp_reg_offsets; -struct gamma_parameters; -struct dev_c_lut; bool dce80_ipp_construct( struct dce110_ipp *ipp, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c index eacb14e40d52..760168df5290 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c @@ -34,15 +34,10 @@ #include "dce80_ipp.h" #include "dce110/dce110_ipp.h" -#include "gamma_types.h" #define DCP_REG(reg)\ (reg + ipp80->offsets.dcp_offset) -enum { - MAX_INPUT_LUT_ENTRY = 256 -}; - /*PROTOTYPE DECLARATIONS*/ static void set_legacy_input_gamma_mode( diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h deleted file mode 100644 index 7948d2cc0715..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef GAMMA_TYPES_H_ - -#define GAMMA_TYPES_H_ - -#include "dc_types.h" - -/* TODO: Used in IPP and OPP */ - -struct dev_c_lut16 { - uint16_t red; - uint16_t green; - uint16_t blue; -}; -#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index e9ed167c9e41..0457bc7a44d4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -110,6 +110,10 @@ struct ipp_funcs { struct input_pixel_processor *ipp, struct ipp_prescale_params *params); + void (*ipp_program_input_lut)( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma); + /*** DEGAMMA RELATED ***/ bool (*ipp_set_degamma)( struct input_pixel_processor *ipp, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index e615997be20e..a1f31a4410a3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -30,7 +30,6 @@ #include "transform.h" struct fixed31_32; -struct gamma_parameters; /* TODO: Need cleanup */ enum clamping_range { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 0e803ca83bb9..895c446cebf9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -28,8 +28,6 @@ #include "core_types.h" #include "timing_generator.h" -struct gamma_parameters; - enum pipe_gating_control { PIPE_GATING_CONTROL_DISABLE = 0, PIPE_GATING_CONTROL_ENABLE, diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 6d1b20f6bf98..5c578aecf21c 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -2433,7 +2433,7 @@ bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, if (surface != NULL) { struct dc_transfer_func *input_tf = - dc_create_transfer_func(core_color->dc); + dc_create_transfer_func(); struct dc_surface_update updates = {0}; if (input_tf != NULL) { @@ -2724,7 +2724,7 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, /* 3. ---- SET DEGAMMA ---- */ struct dc_transfer_func *input_tf = NULL; - input_tf = dc_create_transfer_func(core_color->dc); + input_tf = dc_create_transfer_func(); if (input_tf != NULL) { input_tf->type = TF_TYPE_PREDEFINED; @@ -2747,7 +2747,7 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, /* 4. ---- SET REGAMMA ---- */ struct dc_transfer_func *output_tf = NULL; - output_tf = dc_create_transfer_func(core_color->dc); + output_tf = dc_create_transfer_func(); if (output_tf != NULL) { output_tf->type = TF_TYPE_PREDEFINED; -- GitLab From 0f4e66cd7dac538adca4b1cac8f36b90db1709e6 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 21 Dec 2016 11:16:48 -0500 Subject: [PATCH 0135/2898] drm/amd/display: don't crash if stream is NULL when trying to share clocks Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 343114b2680f..eac597d0c790 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -288,6 +288,11 @@ static bool is_sharable_clk_src( if (pipe_with_clk_src->clock_source == NULL) return false; + if (pipe_with_clk_src->stream == NULL) { + ASSERT(0); + return false; + } + if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) return false; -- GitLab From 80bd20967261d9438dc814f3e6e904aea053163b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 21 Dec 2016 11:13:48 -0500 Subject: [PATCH 0136/2898] drm/amd/display: reset transfer_func to NULL on release Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 +++- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 237436e22720..84e3fbbe23ac 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -89,9 +89,11 @@ static bool construct(struct core_stream *stream, static void destruct(struct core_stream *stream) { dc_sink_release(&stream->sink->public); - if (stream->public.out_transfer_func != NULL) + if (stream->public.out_transfer_func != NULL) { dc_transfer_func_release( stream->public.out_transfer_func); + stream->public.out_transfer_func = NULL; + } } void dc_stream_retain(const struct dc_stream *dc_stream) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 3ec1f363e43e..cf8fb9a8ce8e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -71,11 +71,15 @@ static bool construct(struct dc_context *ctx, struct surface *surface) static void destruct(struct surface *surface) { - if (surface->protected.public.gamma_correction != NULL) + if (surface->protected.public.gamma_correction != NULL) { dc_gamma_release(surface->protected.public.gamma_correction); - if (surface->protected.public.in_transfer_func != NULL) + surface->protected.public.gamma_correction = NULL; + } + if (surface->protected.public.in_transfer_func != NULL) { dc_transfer_func_release( surface->protected.public.in_transfer_func); + surface->protected.public.in_transfer_func = NULL; + } } /******************************************************************************* -- GitLab From 6680b6a1377f944e5369f456fe1b9d193dd4624b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 21 Dec 2016 16:48:51 -0500 Subject: [PATCH 0137/2898] drm/amd/display: Fixed crash Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 891075e39ecf..e6010abc9e0d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -167,24 +167,20 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); int i = 0; bool ret = false; - struct pipe_ctx *pipes; - unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == core_stream - && i != underlay_idx) { + struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.set_drr(&pipes, 1, vmin, vmax); + if (pipe->stream == core_stream && pipe->stream_enc) { + core_dc->hwss.set_drr(&pipe, 1, vmin, vmax); /* build and update the info frame */ - resource_build_info_frame(pipes); - core_dc->hwss.update_info_frame(pipes); + resource_build_info_frame(pipe); + core_dc->hwss.update_info_frame(pipe); ret = true; } } - return ret; } -- GitLab From 0347c854094c14469ca4be2192e93e773b164741 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 22 Dec 2016 10:25:57 -0500 Subject: [PATCH 0138/2898] drm/amd/display: Fix licensing header Signed-off-by: Harry Wentland Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/modules/color/color_helper.c | 31 +++++++++++++------ .../amd/display/modules/color/color_helper.h | 30 ++++++++++++------ 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.c b/drivers/gpu/drm/amd/display/modules/color/color_helper.c index c47d2962c6d4..ff6779cdd623 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.c @@ -1,15 +1,26 @@ - -/** - * @file - * @date Copyright (c) 2008 Advanced Micro Devices, Inc. (unpublished) +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. * - * @brief Helper functions for color gamut calculation + * Authors: AMD * - * @internal - * All rights reserved. This notice is intended as a precaution against - * inadvertent publication and does not imply publication or any waiver - * of confidentiality. The year included in the foregoing notice is the - * year of creation of the work. */ #include "dm_services.h" diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h index b7a7ca4debd7..76575c1dc043 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.h +++ b/drivers/gpu/drm/amd/display/modules/color/color_helper.h @@ -1,14 +1,26 @@ -/** - * @file - * @date Copyright (c) 2008 Advanced Micro Devices, Inc. (unpublished) +/* + * Copyright 2016 Advanced Micro Devices, Inc. * - * @brief Helper functions for color gamut calculation + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD * - * @internal - * All rights reserved. This notice is intended as a precaution against - * inadvertent publication and does not imply publication or any waiver - * of confidentiality. The year included in the foregoing notice is the - * year of creation of the work. */ #ifndef COLOR_MOD_COLOR_HELPER_H_ -- GitLab From 1c4e6bcefd0e70eae4f1145e334955b4b21ebb42 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 22 Dec 2016 10:48:19 -0500 Subject: [PATCH 0139/2898] drm/amd/display: Fixed split update bug. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e6010abc9e0d..5e60640df61b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1333,6 +1333,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda bool is_new_pipe_surface[MAX_PIPES]; const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; bool need_apply_clk_constraints = false; + bool can_skip_context_building = true; update_surface_trace(dc, updates, surface_count); @@ -1355,17 +1356,26 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda for (i = 0 ; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + bool existing_surface = false; new_surfaces[i] = updates[i].surface; + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (surface == pipe_ctx->surface) + if (surface == pipe_ctx->surface) { + existing_surface = true; is_new_pipe_surface[j] = false; + } } + + if (updates[i].plane_info || + updates[i].scaling_info || + !existing_surface) + can_skip_context_building = false; } - if (dc_target) { + if (!can_skip_context_building && dc_target) { struct core_target *target = DC_TARGET_TO_CORE(dc_target); if (core_dc->current_context->target_count == 0) -- GitLab From 8c737fcc24b01ef36da5f78aace70d444485abf9 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 22 Dec 2016 13:07:11 -0500 Subject: [PATCH 0140/2898] drm/amd/display: Fixed crash caused by unnecessary clock source in split pipe. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 20 +++++++++---------- .../display/dc/dce110/dce110_hw_sequencer.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index eac597d0c790..386b3cc14fbe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -211,27 +211,28 @@ bool resource_construct( void resource_unreference_clock_source( struct resource_context *res_ctx, - struct clock_source *clock_source) + struct clock_source **clock_source) { int i; for (i = 0; i < res_ctx->pool->clk_src_count; i++) { - if (res_ctx->pool->clock_sources[i] != clock_source) + if (res_ctx->pool->clock_sources[i] != *clock_source) continue; res_ctx->clock_source_ref_count[i]--; if (res_ctx->clock_source_ref_count[i] == 0) - clock_source->funcs->cs_power_down(clock_source); + (*clock_source)->funcs->cs_power_down(*clock_source); break; } - if (res_ctx->pool->dp_clock_source == clock_source) { + if (res_ctx->pool->dp_clock_source == *clock_source) { res_ctx->dp_clock_source_ref_count--; if (res_ctx->dp_clock_source_ref_count == 0) - clock_source->funcs->cs_power_down(clock_source); + (*clock_source)->funcs->cs_power_down(*clock_source); } + *clock_source = NULL; } void resource_reference_clock_source( @@ -288,11 +289,6 @@ static bool is_sharable_clk_src( if (pipe_with_clk_src->clock_source == NULL) return false; - if (pipe_with_clk_src->stream == NULL) { - ASSERT(0); - return false; - } - if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) return false; @@ -1148,6 +1144,10 @@ enum dc_status resource_map_pool_resources( pipe_ctx->stream = stream; copy_pipe_ctx(old_pipe_ctx, pipe_ctx); + /* Split pipe resource, do not acquire back end */ + if (!pipe_ctx->stream_enc) + continue; + set_stream_engine_in_use( &context->res_ctx, pipe_ctx->stream_enc); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e4cef9da5de1..6a7cb3e9294a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1028,7 +1028,7 @@ static void switch_dp_clock_sources( if (clk_src && clk_src != pipe_ctx->clock_source) { resource_unreference_clock_source( - res_ctx, pipe_ctx->clock_source); + res_ctx, &pipe_ctx->clock_source); pipe_ctx->clock_source = clk_src; resource_reference_clock_source(res_ctx, clk_src); @@ -1056,7 +1056,7 @@ static void reset_single_pipe_hw_ctx( pipe_ctx->mi->funcs->free_mem_input( pipe_ctx->mi, context->target_count); resource_unreference_clock_source( - &context->res_ctx, pipe_ctx->clock_source); + &context->res_ctx, &pipe_ctx->clock_source); dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 8dd676de6b07..adf297ec33b6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -94,7 +94,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx); void resource_unreference_clock_source( struct resource_context *res_ctx, - struct clock_source *clock_source); + struct clock_source **clock_source); void resource_reference_clock_source( struct resource_context *res_ctx, -- GitLab From db96c69ee78845c4f4cadea9fd282fb265253874 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 20 Dec 2016 18:01:30 -0500 Subject: [PATCH 0141/2898] drm/amd/display: Add refcount debug assert Signed-off-by: Andrey Grodzovsky Signed-off-by: Jordan Lazare Signed-off-by: Tony Cheng Reviewed-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 5 +++-- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 5 ++++- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 14 +++++++++++--- drivers/gpu/drm/amd/display/dc/core/dc_target.c | 4 +++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 67ae799b6f4f..9dff0bfd5b23 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -71,6 +71,7 @@ void dc_sink_retain(const struct dc_sink *dc_sink) { struct sink *sink = DC_SINK_TO_SINK(dc_sink); + ASSERT(sink->ref_count > 0); ++sink->ref_count; } @@ -78,6 +79,7 @@ void dc_sink_release(const struct dc_sink *dc_sink) { struct sink *sink = DC_SINK_TO_SINK(dc_sink); + ASSERT(sink->ref_count > 0); --sink->ref_count; if (sink->ref_count == 0) { @@ -96,8 +98,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) if (false == construct(sink, init_params)) goto construct_fail; - /* TODO should we move this outside to where the assignment actually happens? */ - dc_sink_retain(&sink->protected.public); + ++sink->ref_count; return &sink->protected.public; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 84e3fbbe23ac..39a6124aa85f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -99,6 +99,8 @@ static void destruct(struct core_stream *stream) void dc_stream_retain(const struct dc_stream *dc_stream) { struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); + + ASSERT(stream->ref_count > 0); stream->ref_count++; } @@ -108,6 +110,7 @@ void dc_stream_release(const struct dc_stream *public) struct core_stream *protected = DC_STREAM_TO_CORE(public); if (public != NULL) { + ASSERT(stream->ref_count > 0); stream->ref_count--; if (stream->ref_count == 0) { @@ -134,7 +137,7 @@ struct dc_stream *dc_create_stream_for_sink( if (false == construct(&stream->protected, dc_sink)) goto construct_fail; - dc_stream_retain(&stream->protected.public); + stream->ref_count++; return &stream->protected.public; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index cf8fb9a8ce8e..6b4c75a78fe8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -105,7 +105,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) if (false == construct(core_dc->ctx, surface)) goto construct_fail; - dc_surface_retain(&surface->protected.public); + ++surface->ref_count; return &surface->protected.public; @@ -162,6 +162,7 @@ void dc_surface_retain(const struct dc_surface *dc_surface) { struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + ASSERT(surface->ref_count > 0); ++surface->ref_count; } @@ -169,6 +170,7 @@ void dc_surface_release(const struct dc_surface *dc_surface) { struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + ASSERT(surface->ref_count > 0); --surface->ref_count; if (surface->ref_count == 0) { @@ -181,12 +183,15 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma) { struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + ASSERT(gamma->ref_count > 0); ++gamma->ref_count; } void dc_gamma_release(const struct dc_gamma *dc_gamma) { struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + + ASSERT(gamma->ref_count > 0); --gamma->ref_count; if (gamma->ref_count == 0) @@ -200,7 +205,7 @@ struct dc_gamma *dc_create_gamma() if (gamma == NULL) goto alloc_fail; - dc_gamma_retain(&gamma->protected.public); + ++gamma->ref_count; return &gamma->protected.public; @@ -212,12 +217,15 @@ void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf) { struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); + ASSERT(tf->ref_count > 0); ++tf->ref_count; } void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) { struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); + + ASSERT(tf->ref_count > 0); --tf->ref_count; if (tf->ref_count == 0) @@ -231,7 +239,7 @@ struct dc_transfer_func *dc_create_transfer_func() if (tf == NULL) goto alloc_fail; - dc_transfer_func_retain(&tf->protected.public); + ++tf->ref_count; return &tf->protected.public; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c index 2531df74871a..d4ecf2da26d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_target.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c @@ -71,6 +71,7 @@ void dc_target_retain(const struct dc_target *dc_target) { struct target *target = DC_TARGET_TO_TARGET(dc_target); + ASSERT(target->ref_count > 0); target->ref_count++; } @@ -81,6 +82,7 @@ void dc_target_release(const struct dc_target *dc_target) ASSERT(target->ref_count > 0); target->ref_count--; + if (target->ref_count == 0) { destruct(protected); dm_free(target); @@ -120,7 +122,7 @@ struct dc_target *dc_create_target_for_streams( construct(&target->protected, stream->ctx, dc_streams, stream_count); - dc_target_retain(&target->protected.public); + target->ref_count++; return &target->protected.public; -- GitLab From 6a1f8cabc651c20bc00d211aef24ea9174141515 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 15 Dec 2016 00:53:04 -0500 Subject: [PATCH 0142/2898] drm/amd/display: Pass adev to fill_plane_attr Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index f969bfedb368..da8bd66f99ee 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -411,6 +411,7 @@ static bool get_fb_info( return true; } static void fill_plane_attributes_from_fb( + struct amdgpu_device *adev, struct dc_surface *surface, const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) { @@ -455,6 +456,7 @@ static void fill_plane_attributes_from_fb( memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); + /* Fill GFX8 params */ if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { unsigned bankw, bankh, mtaspect, tile_split, num_banks; @@ -540,6 +542,7 @@ static void fill_gamma_from_crtc( } static void fill_plane_attributes( + struct amdgpu_device *adev, struct dc_surface *surface, struct drm_plane_state *state, bool addrReq) { @@ -549,6 +552,7 @@ static void fill_plane_attributes( fill_rects_from_plane_state(state, surface); fill_plane_attributes_from_fb( + crtc->dev->dev_private, surface, amdgpu_fb, addrReq); @@ -662,7 +666,11 @@ static void dm_dc_surface_commit( } /* Surface programming */ - fill_plane_attributes(dc_surface, crtc->primary->state, true); + fill_plane_attributes( + crtc->dev->dev_private, + dc_surface, + crtc->primary->state, + true); dc_surfaces[0] = dc_surface; @@ -3026,6 +3034,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, surface = dc_create_surface(dc); fill_plane_attributes( + crtc->dev->dev_private, surface, plane_state, false); -- GitLab From c89a58cd0d1cc940a29a00cc03e441f97fab56e1 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 22 Dec 2016 14:54:50 -0500 Subject: [PATCH 0143/2898] drm/amd/display: Allow multiple instance of DTO regs Signed-off-by: Tony Cheng Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 8ee00712ef8e..28984c79fc46 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -76,9 +76,13 @@ struct dce110_clk_src_regs { uint32_t RESYNC_CNTL; uint32_t PIXCLK_RESYNC_CNTL; uint32_t PLL_CNTL; - uint32_t PHASE; - uint32_t MODULO; - uint32_t PIXEL_RATE_CNTL; + + /* below are for DTO. + * todo: should probably use different struct to not waste space + */ + uint32_t PHASE[4]; + uint32_t MODULO[4]; + uint32_t PIXEL_RATE_CNTL[4]; }; struct dce110_clk_src { -- GitLab From 1646a6fe746d7e923774994d2020e1707dcda884 Mon Sep 17 00:00:00 2001 From: Andrew Wong Date: Thu, 22 Dec 2016 15:41:30 -0500 Subject: [PATCH 0144/2898] drm/amd/display: DAL3: HDR10 Infoframe encoding - Add HDR metadata struct - Add register programming calculations - Added HDR metadata to surface and update_surface - Add HDR info packet programming for DP port Signed-off-by: Andrew Wong Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++ .../gpu/drm/amd/display/dc/core/dc_resource.c | 115 +++++++++++++++++- .../gpu/drm/amd/display/dc/core/dc_stream.c | 1 - .../gpu/drm/amd/display/dc/core/dc_surface.c | 2 + drivers/gpu/drm/amd/display/dc/dc.h | 23 +++- .../amd/display/dc/dce/dce_stream_encoder.c | 20 ++- .../amd/display/dc/inc/hw/stream_encoder.h | 2 + .../amd/display/include/hw_sequencer_types.h | 3 +- .../gpu/drm/amd/display/modules/color/color.c | 16 ++- .../drm/amd/display/modules/inc/mod_color.h | 20 +-- 10 files changed, 176 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5e60640df61b..e368d660362f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1489,6 +1489,9 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda stream->public.out_transfer_func = updates[i].out_transfer_func; } + if (updates[i].hdr_static_metadata) + surface->public.hdr_static_ctx = + *(updates[i].hdr_static_metadata); } } @@ -1522,6 +1525,10 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } + if (updates[i].hdr_static_metadata) { + resource_build_info_frame(pipe_ctx); + core_dc->hwss.update_info_frame(pipe_ctx); + } if (is_new_pipe_surface[j] || updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 386b3cc14fbe..2b08f5ae5e33 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -32,7 +32,6 @@ #include "timing_generator.h" #include "transform.h" #include "set_mode_types.h" - #include "virtual/virtual_stream_encoder.h" #include "dce80/dce80_resource.h" @@ -1303,6 +1302,13 @@ static void translate_info_frame(const struct hw_info_frame *hw_info_frame, &hw_info_frame->vsc_packet, sizeof(struct hw_info_packet)); } + + if (hw_info_frame->hdrsmd_packet.valid) { + memmove( + &encoder_info_frame->hdrsmd, + &hw_info_frame->hdrsmd_packet, + sizeof(struct hw_info_packet)); + } } static void set_avi_info_frame( @@ -1720,6 +1726,108 @@ static void set_spd_info_packet(struct core_stream *stream, info_packet->valid = true; } +static void set_hdr_static_info_packet( + struct core_surface *surface, + struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + uint16_t i; + enum signal_type signal = stream->signal; + + if (!surface) + return; + + struct dc_hdr_static_metadata hdr_metadata = + surface->public.hdr_static_ctx; + + if (dc_is_hdmi_signal(signal)) { + info_packet->valid = true; + + info_packet->hb0 = 0x87; + info_packet->hb1 = 0x01; + info_packet->hb2 = 0x1A; + i = 1; + } else if (dc_is_dp_signal(signal)) { + info_packet->valid = true; + + info_packet->hb0 = 0x00; + info_packet->hb1 = 0x87; + info_packet->hb2 = 0x1D; + info_packet->hb3 = (0x13 << 2); + i = 2; + } + + uint32_t data; + + data = hdr_metadata.is_hdr; + info_packet->sb[i++] = data ? 0x02 : 0x00; + info_packet->sb[i++] = 0x00; + + data = hdr_metadata.chromaticity_green_x / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_green_y / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_blue_x / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_blue_y / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_red_x / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_red_y / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_white_point_x / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.chromaticity_white_point_y / 2; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.max_luminance; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.min_luminance; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.maximum_content_light_level; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + data = hdr_metadata.maximum_frame_average_light_level; + info_packet->sb[i++] = data & 0xFF; + info_packet->sb[i++] = (data & 0xFF00) >> 8; + + if (dc_is_hdmi_signal(signal)) { + uint32_t checksum = 0; + + checksum += info_packet->hb0; + checksum += info_packet->hb1; + checksum += info_packet->hb2; + + for (i = 1; i <= info_packet->hb2; i++) + checksum += info_packet->sb[i]; + + info_packet->sb[0] = 0x100 - checksum; + } else if (dc_is_dp_signal(signal)) { + info_packet->sb[0] = 0x01; + info_packet->sb[1] = 0x1A; + } +} + static void set_vsc_info_packet(struct core_stream *stream, struct hw_info_packet *info_packet) { @@ -1830,6 +1938,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) info_frame.vendor_info_packet.valid = false; info_frame.spd_packet.valid = false; info_frame.vsc_packet.valid = false; + info_frame.hdrsmd_packet.valid = false; signal = pipe_ctx->stream->signal; @@ -1840,9 +1949,13 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_vendor_info_packet( pipe_ctx->stream, &info_frame.vendor_info_packet); set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + set_hdr_static_info_packet(pipe_ctx->surface, + pipe_ctx->stream, &info_frame.hdrsmd_packet); } else if (dc_is_dp_signal(signal)) { set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); + set_hdr_static_info_packet(pipe_ctx->surface, + pipe_ctx->stream, &info_frame.hdrsmd_packet); } translate_info_frame(&info_frame, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 39a6124aa85f..cda67a78dbfd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -82,7 +82,6 @@ static bool construct(struct core_stream *stream, stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; stream->status.link = &stream->sink->link->public; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 6b4c75a78fe8..d962baa477f5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -66,6 +66,8 @@ struct transfer_func { static bool construct(struct dc_context *ctx, struct surface *surface) { surface->protected.ctx = ctx; + memset(&surface->protected.public.hdr_static_ctx, + 0, sizeof(struct dc_hdr_static_metadata)); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0ee6f41b6047..ef9a69759bd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -186,6 +186,25 @@ enum { TRANSFER_FUNC_POINTS = 1025 }; +struct dc_hdr_static_metadata { + bool is_hdr; + + /* display chromaticities and white point in units of 0.00001 */ + unsigned int chromaticity_green_x; + unsigned int chromaticity_green_y; + unsigned int chromaticity_blue_x; + unsigned int chromaticity_blue_y; + unsigned int chromaticity_red_x; + unsigned int chromaticity_red_y; + unsigned int chromaticity_white_point_x; + unsigned int chromaticity_white_point_y; + + uint32_t min_luminance; + uint32_t max_luminance; + uint32_t maximum_content_light_level; + uint32_t maximum_frame_average_light_level; +}; + enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, @@ -232,6 +251,8 @@ struct dc_surface { bool horizontal_mirror; enum plane_stereo_format stereo_format; + struct dc_hdr_static_metadata hdr_static_ctx; + const struct dc_gamma *gamma_correction; const struct dc_transfer_func *in_transfer_func; }; @@ -267,7 +288,7 @@ struct dc_surface_update { */ /* gamma TO BE REMOVED */ struct dc_gamma *gamma; - + struct dc_hdr_static_metadata *hdr_static_metadata; struct dc_transfer_func *in_transfer_func; struct dc_transfer_func *out_transfer_func; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index b74a29b40a66..82133ab3224d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -518,6 +518,7 @@ static void dce110_stream_encoder_update_hdmi_info_packets( dce110_update_hdmi_info_packet(enc110, 0, &info_frame->vendor); dce110_update_hdmi_info_packet(enc110, 1, &info_frame->gamut); dce110_update_hdmi_info_packet(enc110, 2, &info_frame->spd); + dce110_update_hdmi_info_packet(enc110, 3, &info_frame->hdrsmd); } } @@ -554,16 +555,25 @@ static void dce110_stream_encoder_update_dp_info_packets( struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); uint32_t value = REG_READ(DP_SEC_CNTL); - if (info_frame->vsc.valid) - dce110_update_generic_info_packet( + dce110_update_generic_info_packet( + enc110, + 0, /* packetIndex */ + &info_frame->vsc); + dce110_update_generic_info_packet( + enc110, + 2, /* packetIndex */ + &info_frame->spd); + dce110_update_generic_info_packet( enc110, - 0, /* packetIndex */ - &info_frame->vsc); + 3, /* packetIndex */ + &info_frame->hdrsmd); /* enable/disable transmission of packet(s). * If enabled, packet transmission begins on the next frame */ - REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); /* This bit is the master enable bit. * When enabling secondary stream engine, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 9caf2b365420..8b4a30459eeb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -31,6 +31,8 @@ struct encoder_info_frame { struct encoder_info_packet spd; /* video stream configuration */ struct encoder_info_packet vsc; + /* HDR Static MetaData */ + struct encoder_info_packet hdrsmd; }; struct encoder_unblank_param { diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 9a78097e70f3..6bbca1b4d736 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -88,7 +88,7 @@ struct hw_info_packet { uint8_t hb1; uint8_t hb2; uint8_t hb3; - uint8_t sb[28]; + uint8_t sb[32]; }; struct hw_info_frame { @@ -100,6 +100,7 @@ struct hw_info_frame { struct hw_info_packet spd_packet; /* Video Stream Configuration */ struct hw_info_packet vsc_packet; + struct hw_info_packet hdrsmd_packet; }; #endif diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 5c578aecf21c..599d9f9aa7ca 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -74,7 +74,7 @@ struct color_state { struct color_gamut_data destination_gamut; enum color_transfer_func input_transfer_function; enum color_transfer_func output_transfer_function; - struct color_mastering_info mastering_info; + struct dc_hdr_static_metadata mastering_info; }; struct core_color { @@ -1970,7 +1970,7 @@ bool mod_color_set_white_point(struct mod_color *mod_color, bool mod_color_set_mastering_info(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct color_mastering_info *mastering_info) + const struct dc_hdr_static_metadata *mastering_info) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); unsigned int stream_index, sink_index; @@ -1980,14 +1980,14 @@ bool mod_color_set_mastering_info(struct mod_color *mod_color, streams[stream_index]->sink); memcpy(&core_color->state[sink_index].mastering_info, mastering_info, - sizeof(struct color_mastering_info)); + sizeof(struct dc_hdr_static_metadata)); } return true; } bool mod_color_get_mastering_info(struct mod_color *mod_color, const struct dc_sink *sink, - struct color_mastering_info *mastering_info) + struct dc_hdr_static_metadata *mastering_info) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); @@ -1995,7 +1995,7 @@ bool mod_color_get_mastering_info(struct mod_color *mod_color, unsigned int sink_index = sink_index_from_sink(core_color, sink); memcpy(mastering_info, &core_color->state[sink_index].mastering_info, - sizeof(struct color_mastering_info)); + sizeof(struct dc_hdr_static_metadata)); return true; } @@ -2756,8 +2756,10 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, else output_tf->tf = TRANSFER_FUNCTION_SRGB; } + /* 5. ---- POPULATE HDR METADATA ---- */ + core_color->state[sink_index].mastering_info.is_hdr = is_hdr; - /* 5. ---- TODO: UPDATE INFOPACKETS ---- */ + /* 6. ---- TODO: UPDATE INFOPACKETS ---- */ if (!mod_color_update_gamut_to_stream( mod_color, streams, num_streams)) @@ -2769,6 +2771,8 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, updates[0].gamma = core_color->state[sink_index].gamma; updates[0].in_transfer_func = input_tf; updates[0].out_transfer_func = output_tf; + updates[0].hdr_static_metadata = + &core_color->state[sink_index].mastering_info; dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL); diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index 670b87fb8bd2..70349a88916c 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h @@ -87,22 +87,6 @@ enum hdr_tf_support_flag { smpte_st2084 = 0x04 }; -struct color_mastering_info { - unsigned int chromaticity_green_x; - unsigned int chromaticity_green_y; - unsigned int chromaticity_blue_x; - unsigned int chromaticity_blue_y; - unsigned int chromaticity_red_x; - unsigned int chromaticity_red_y; - unsigned int chromaticity_white_point_x; - unsigned int chromaticity_white_point_y; - - unsigned int min_luminance; - unsigned int max_luminance; - unsigned int maximum_content_light_level; - unsigned int maximum_frame_average_light_level; -}; - struct mod_color { int dummy; }; @@ -206,11 +190,11 @@ bool mod_color_get_user_enable(struct mod_color *mod_color, bool mod_color_set_mastering_info(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, - struct color_mastering_info *mastering_info); + const struct dc_hdr_static_metadata *mastering_info); bool mod_color_get_mastering_info(struct mod_color *mod_color, const struct dc_sink *sink, - struct color_mastering_info *mastering_info); + struct dc_hdr_static_metadata *mastering_info); bool mod_color_set_user_enable(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams, -- GitLab From dc0bcaf2cafaa7a6023055d13ebf7dcc8c6e00b5 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 23 Dec 2016 07:12:19 -0500 Subject: [PATCH 0145/2898] drm/amd/display: debug opt disable hdmi deep color Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ef9a69759bd5..823a87224498 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -147,6 +147,7 @@ struct dc_debug { bool disable_power_gate; bool disable_clock_gate; bool disable_dmcu; + bool disable_hdmi_deep_color; }; struct dc { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index a8a2290d47db..b439a9ee0228 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -993,6 +993,9 @@ bool dce110_link_encoder_construct( enc110->base.features.max_deep_color = COLOR_DEPTH_121212; enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212; + if (enc110->base.ctx->dc->debug.disable_hdmi_deep_color) + enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_888; + /* set the flag to indicate whether driver poll the I2C data pin * while doing the DP sink detect */ -- GitLab From e12078c56c24894b07cd3aae43788b90d6ea390e Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 23 Dec 2016 07:20:53 -0500 Subject: [PATCH 0146/2898] drm/amd/display: debug option to disable color module fucntionality Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e368d660362f..aca13d1cd4bb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1452,8 +1452,11 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } - if (updates[i].gamma && updates[i].gamma != - surface->public.gamma_correction) { + if (dc->debug.disable_color_module) + continue; /* skip below color updates */ + + if (updates[i].gamma && + updates[i].gamma != surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) dc_gamma_release(surface->public. gamma_correction); @@ -1464,8 +1467,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } if (updates[i].in_transfer_func && - updates[i].in_transfer_func != - surface->public.in_transfer_func) { + updates[i].in_transfer_func != surface->public.in_transfer_func) { if (surface->public.in_transfer_func != NULL) dc_transfer_func_release( surface->public. @@ -1478,8 +1480,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } if (updates[i].out_transfer_func && - updates[i].out_transfer_func != - stream->public.out_transfer_func) { + updates[i].out_transfer_func != stream->public.out_transfer_func) { if (stream->public.out_transfer_func != NULL) dc_transfer_func_release( stream->public. diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 823a87224498..23f41b690c02 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -148,6 +148,7 @@ struct dc_debug { bool disable_clock_gate; bool disable_dmcu; bool disable_hdmi_deep_color; + bool disable_color_module; }; struct dc { -- GitLab From f79d7749e7381b0ff9d26733f338ad767d75539c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 23 Dec 2016 10:53:24 -0500 Subject: [PATCH 0147/2898] drm/amd/display: Don't use target before null check It might blow up. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_target.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c index d4ecf2da26d2..2d25b00b4bff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_target.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_target.c @@ -151,9 +151,9 @@ bool dc_target_set_cursor_attributes( const struct dc_cursor_attributes *attributes) { int i, j; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); - struct resource_context *res_ctx = &core_dc->current_context->res_ctx; + struct core_target *target; + struct core_dc *core_dc; + struct resource_context *res_ctx; bool ret = false; if (NULL == dc_target) { @@ -165,6 +165,10 @@ bool dc_target_set_cursor_attributes( return false; } + target = DC_TARGET_TO_CORE(dc_target); + core_dc = DC_TO_CORE(target->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + for (i = 0; i < dc_target->stream_count; i++) { const struct dc_stream *stream = dc_target->streams[i]; -- GitLab From d5de97a2b9ec8ba249df6a3e29f20b56285a48dd Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 23 Dec 2016 10:39:22 -0500 Subject: [PATCH 0148/2898] drm/amd/display: Add missing function to fix crash for DP Test pattern 4 Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index b439a9ee0228..6481fb2028ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1472,6 +1472,9 @@ void dce110_link_encoder_dp_set_phy_pattern( case DP_TEST_PATTERN_TRAINING_PATTERN3: dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); break; + case DP_TEST_PATTERN_TRAINING_PATTERN4: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); + break; case DP_TEST_PATTERN_D102: set_dp_phy_pattern_d102(enc110); break; -- GitLab From aff20230b439921d6660eb2ef6d9f6c273d9b240 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 23 Dec 2016 10:18:08 -0500 Subject: [PATCH 0149/2898] drm/amd/display: Set gamma to NULL at release Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 9 +++++---- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/modules/color/color.c | 8 +++----- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index aca13d1cd4bb..12620df7056d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1458,7 +1458,7 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda if (updates[i].gamma && updates[i].gamma != surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) - dc_gamma_release(surface->public. + dc_gamma_release(&surface->public. gamma_correction); dc_gamma_retain(updates[i].gamma); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d962baa477f5..d607972b830b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -74,8 +74,7 @@ static bool construct(struct dc_context *ctx, struct surface *surface) static void destruct(struct surface *surface) { if (surface->protected.public.gamma_correction != NULL) { - dc_gamma_release(surface->protected.public.gamma_correction); - surface->protected.public.gamma_correction = NULL; + dc_gamma_release(&surface->protected.public.gamma_correction); } if (surface->protected.public.in_transfer_func != NULL) { dc_transfer_func_release( @@ -189,15 +188,17 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma) ++gamma->ref_count; } -void dc_gamma_release(const struct dc_gamma *dc_gamma) +void dc_gamma_release(const struct dc_gamma **dc_gamma) { - struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + struct gamma *gamma = DC_GAMMA_TO_GAMMA(*dc_gamma); ASSERT(gamma->ref_count > 0); --gamma->ref_count; if (gamma->ref_count == 0) dm_free(gamma); + + *dc_gamma = NULL; } struct dc_gamma *dc_create_gamma() diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 23f41b690c02..599f8b0894c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -318,7 +318,7 @@ void dc_surface_retain(const struct dc_surface *dc_surface); void dc_surface_release(const struct dc_surface *dc_surface); void dc_gamma_retain(const struct dc_gamma *dc_gamma); -void dc_gamma_release(const struct dc_gamma *dc_gamma); +void dc_gamma_release(const struct dc_gamma **dc_gamma); struct dc_gamma *dc_create_gamma(void); void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 599d9f9aa7ca..3611de90e1e9 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -1557,7 +1557,7 @@ void mod_color_destroy(struct mod_color *mod_color) for (i = 0; i < core_color->num_sinks; i++) if (core_color->state[i].gamma) - dc_gamma_release(core_color->state[i].gamma); + dc_gamma_release(&core_color->state[i].gamma); dm_free(core_color->state); @@ -1749,8 +1749,7 @@ bool mod_color_remove_sink(struct mod_color *mod_color, for (i = 0; i < core_color->num_sinks; i++) { if (core_color->caps[i].sink == sink) { if (core_color->state[i].gamma) { - dc_gamma_release(core_color->state[i].gamma); - core_color->state[i].gamma = NULL; + dc_gamma_release(&core_color->state[i].gamma); } /* To remove this sink, shift everything after down */ @@ -2444,8 +2443,7 @@ bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, if (core_color->state[sink_index].gamma != gamma) { if (core_color->state[sink_index].gamma) dc_gamma_release( - core_color->state[sink_index]. - gamma); + &core_color->state[sink_index].gamma); dc_gamma_retain(gamma); core_color->state[sink_index].gamma = gamma; -- GitLab From 5a7a1eebc6199a8e19cc6497cffb3e16d9d55333 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 23 Dec 2016 15:13:13 -0500 Subject: [PATCH 0150/2898] drm/amd/display: set HBR3 and TPS4 capable flags Signed-off-by: Hersen Wu Reviewed-by: Zeyu Fan Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 6481fb2028ee..ea4778b6e6d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1068,9 +1068,19 @@ bool dce110_link_encoder_construct( &bp_cap_info)) enc110->base.features.flags.bits.IS_HBR2_CAPABLE = bp_cap_info.DP_HBR2_CAP; + enc110->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + } + + /* TODO: check PPLIB maxPhyClockInKHz <= 540000, if yes, + * IS_HBR3_CAPABLE = 0. + */ + /* test pattern 3 support */ enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true; + /* test pattern 4 support */ + enc110->base.features.flags.bits.IS_TPS4_CAPABLE = true; enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE = false; /* -- GitLab From afed48a00c26cb6cbe2cfe72ce459dc3e13b42d4 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 23 Dec 2016 15:43:04 -0500 Subject: [PATCH 0151/2898] drm/amd/display: Fix color module crash when hotplug monitors. Assume we have two monitors, and monitor 0 is unplugged. This shifts the internal state of index 1 to index 0 by memcpy. This means there are two copies of the gamma pointer previously owned by state[1]. When hotplug occurs, this re-assigns the new display with state[1], which has some garbage left over from before, including the gamma pointer. We should correctly clear unused states and re-initialize correctly. Also, due to async nature of the hotplug and other events like commit, we also need to safe guard against sink that has been removed. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/color/color.c | 309 ++++++++++-------- 1 file changed, 175 insertions(+), 134 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 3611de90e1e9..74298c8aad8d 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ b/drivers/gpu/drm/amd/display/modules/color/color.c @@ -643,10 +643,10 @@ static void initialize_fix_point_color_values( /* Given a specific dc_sink* this function finds its equivalent * on the dc_sink array and returns the corresponding index */ -static unsigned int sink_index_from_sink(struct core_color *core_color, +static int sink_index_from_sink(struct core_color *core_color, const struct dc_sink *sink) { - unsigned int index = 0; + int index = 0; for (index = 0; index < core_color->num_sinks; index++) if (core_color->caps[index].sink == sink) @@ -654,7 +654,7 @@ static unsigned int sink_index_from_sink(struct core_color *core_color, /* Could not find sink requested */ ASSERT(false); - return index; + return -1; } static void calculate_rgb_matrix_legacy(struct core_color *core_color, @@ -1427,6 +1427,65 @@ static bool update_color_gamut_data(struct color_gamut_data *input_data, return true; } +void initialize_color_state(struct core_color *core_color, int index) +{ + core_color->state[index].user_enable_color_temperature = true; + + core_color->state[index].custom_color_temperature = 6500; + + core_color->state[index].contrast.current = 100; + core_color->state[index].contrast.min = 0; + core_color->state[index].contrast.max = 200; + + core_color->state[index].saturation.current = 100; + core_color->state[index].saturation.min = 0; + core_color->state[index].saturation.max = 200; + + core_color->state[index].brightness.current = 0; + core_color->state[index].brightness.min = -100; + core_color->state[index].brightness.max = 100; + + core_color->state[index].hue.current = 0; + core_color->state[index].hue.min = -30; + core_color->state[index].hue.max = 30; + + core_color->state[index].gamma = NULL; + + core_color->state[index].preferred_quantization_range = + QUANTIZATION_RANGE_FULL; + + core_color->state[index].source_gamut.color_space = + color_space_srgb; + core_color->state[index].source_gamut.white_point = + color_white_point_type_6500k_noon; + core_color->state[index].source_gamut.gamut.blueX = 1500; + core_color->state[index].source_gamut.gamut.blueY = 600; + core_color->state[index].source_gamut.gamut.greenX = 3000; + core_color->state[index].source_gamut.gamut.greenY = 6000; + core_color->state[index].source_gamut.gamut.redX = 6400; + core_color->state[index].source_gamut.gamut.redY = 3300; + core_color->state[index].source_gamut.gamut.whiteX = 3127; + core_color->state[index].source_gamut.gamut.whiteY = 3290; + + core_color->state[index].destination_gamut.color_space = + color_space_srgb; + core_color->state[index].destination_gamut.white_point = + color_white_point_type_6500k_noon; + core_color->state[index].destination_gamut.gamut.blueX = 1500; + core_color->state[index].destination_gamut.gamut.blueY = 600; + core_color->state[index].destination_gamut.gamut.greenX = 3000; + core_color->state[index].destination_gamut.gamut.greenY = 6000; + core_color->state[index].destination_gamut.gamut.redX = 6400; + core_color->state[index].destination_gamut.gamut.redY = 3300; + core_color->state[index].destination_gamut.gamut.whiteX = 3127; + core_color->state[index].destination_gamut.gamut.whiteY = 3290; + + core_color->state[index].input_transfer_function = + transfer_func_srgb; + core_color->state[index].output_transfer_function = + transfer_func_srgb; +} + struct mod_color *mod_color_create(struct dc *dc) { int i = 0; @@ -1452,54 +1511,7 @@ struct mod_color *mod_color_create(struct dc *dc) /*hardcoded to sRGB with 6500 color temperature*/ for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { - core_color->state[i].source_gamut.color_space = - color_space_srgb; - core_color->state[i].source_gamut.white_point = - color_white_point_type_6500k_noon; - core_color->state[i].source_gamut.gamut.blueX = 1500; - core_color->state[i].source_gamut.gamut.blueY = 600; - core_color->state[i].source_gamut.gamut.greenX = 3000; - core_color->state[i].source_gamut.gamut.greenY = 6000; - core_color->state[i].source_gamut.gamut.redX = 6400; - core_color->state[i].source_gamut.gamut.redY = 3300; - core_color->state[i].source_gamut.gamut.whiteX = 3127; - core_color->state[i].source_gamut.gamut.whiteY = 3290; - - core_color->state[i].destination_gamut.color_space = - color_space_srgb; - core_color->state[i].destination_gamut.white_point = - color_white_point_type_6500k_noon; - core_color->state[i].destination_gamut.gamut.blueX = 1500; - core_color->state[i].destination_gamut.gamut.blueY = 600; - core_color->state[i].destination_gamut.gamut.greenX = 3000; - core_color->state[i].destination_gamut.gamut.greenY = 6000; - core_color->state[i].destination_gamut.gamut.redX = 6400; - core_color->state[i].destination_gamut.gamut.redY = 3300; - core_color->state[i].destination_gamut.gamut.whiteX = 3127; - core_color->state[i].destination_gamut.gamut.whiteY = 3290; - - core_color->state[i].input_transfer_function = - transfer_func_srgb; - core_color->state[i].output_transfer_function = - transfer_func_srgb; - - core_color->state[i].custom_color_temperature = 6500; - - core_color->state[i].contrast.current = 100; - core_color->state[i].contrast.min = 0; - core_color->state[i].contrast.max = 200; - - core_color->state[i].saturation.current = 100; - core_color->state[i].saturation.min = 0; - core_color->state[i].saturation.max = 200; - - core_color->state[i].brightness.current = 0; - core_color->state[i].brightness.min = -100; - core_color->state[i].brightness.max = 100; - - core_color->state[i].hue.current = 0; - core_color->state[i].hue.min = -30; - core_color->state[i].hue.max = 30; + initialize_color_state(core_color, i); } if (core_color->state == NULL) @@ -1589,8 +1601,8 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, if (core_color->num_sinks < MOD_COLOR_MAX_CONCURRENT_SINKS) { dc_sink_retain(sink); core_color->caps[core_color->num_sinks].sink = sink; - core_color->state[core_color->num_sinks]. - user_enable_color_temperature = true; + + initialize_color_state(core_color, core_color->num_sinks); core_color->edid_caps[core_color->num_sinks].colorimetry_caps = edid_caps->colorimetry_caps; @@ -1601,7 +1613,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, flag.save_per_edid = true; flag.save_per_link = false; - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, "enablecolortempadj", @@ -1610,9 +1621,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, core_color->state[core_color->num_sinks]. user_enable_color_temperature = persistent_color_temp_enable; - else - core_color->state[core_color->num_sinks]. - user_enable_color_temperature = true; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1622,9 +1630,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, core_color->state[core_color->num_sinks]. custom_color_temperature = persistent_custom_color_temp; - else - core_color->state[core_color->num_sinks]. - custom_color_temperature = 6500; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1635,23 +1640,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, memcpy(&core_color->state[core_color->num_sinks]. source_gamut.gamut, &persistent_source_gamut, sizeof(struct color_space_coordinates)); - } else { - core_color->state[core_color->num_sinks]. - source_gamut.gamut.blueX = 1500; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.blueY = 600; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.greenX = 3000; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.greenY = 6000; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.redX = 6400; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.redY = 3300; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.whiteX = 3127; - core_color->state[core_color->num_sinks]. - source_gamut.gamut.whiteY = 3290; } if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1663,23 +1651,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, destination_gamut.gamut, &persistent_destination_gamut, sizeof(struct color_space_coordinates)); - } else { - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.blueX = 1500; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.blueY = 600; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.greenX = 3000; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.greenY = 6000; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.redX = 6400; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.redY = 3300; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.whiteX = 3127; - core_color->state[core_color->num_sinks]. - destination_gamut.gamut.whiteY = 3290; } if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1688,9 +1659,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, sizeof(int), &flag)) core_color->state[core_color->num_sinks]. brightness.current = persistent_brightness; - else - core_color->state[core_color->num_sinks]. - brightness.current = 0; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, "contrast", @@ -1698,9 +1666,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, sizeof(int), &flag)) core_color->state[core_color->num_sinks]. contrast.current = persistent_contrast; - else - core_color->state[core_color->num_sinks]. - contrast.current = 100; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, "hue", @@ -1708,9 +1673,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, sizeof(int), &flag)) core_color->state[core_color->num_sinks]. hue.current = persistent_hue; - else - core_color->state[core_color->num_sinks]. - hue.current = 0; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, "saturation", @@ -1718,9 +1680,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, sizeof(int), &flag)) core_color->state[core_color->num_sinks]. saturation.current = persistent_saturation; - else - core_color->state[core_color->num_sinks]. - saturation.current = 100; if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, @@ -1730,9 +1689,6 @@ bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, core_color->state[core_color->num_sinks]. preferred_quantization_range = persistent_quantization_range; - else - core_color->state[core_color->num_sinks]. - preferred_quantization_range = QUANTIZATION_RANGE_FULL; core_color->num_sinks++; return true; @@ -1751,6 +1707,10 @@ bool mod_color_remove_sink(struct mod_color *mod_color, if (core_color->state[i].gamma) { dc_gamma_release(&core_color->state[i].gamma); } + memset(&core_color->state[i], 0, + sizeof(struct color_state)); + memset(&core_color->edid_caps[i], 0, + sizeof(struct color_edid_caps)); /* To remove this sink, shift everything after down */ for (j = i; j < core_color->num_sinks - 1; j++) { @@ -1766,6 +1726,11 @@ bool mod_color_remove_sink(struct mod_color *mod_color, sizeof(struct color_edid_caps)); } + memset(&core_color->state[core_color->num_sinks - 1], 0, + sizeof(struct color_state)); + memset(&core_color->edid_caps[core_color->num_sinks - 1], 0, + sizeof(struct color_edid_caps)); + core_color->num_sinks--; dc_sink_release(sink); @@ -1786,11 +1751,14 @@ bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, struct gamut_src_dst_matrix *matrix = dm_alloc(sizeof(struct gamut_src_dst_matrix)); - unsigned int stream_index, sink_index, j; + unsigned int stream_index, j; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; /* Write persistent data in registry*/ flag.save_per_edid = true; @@ -1880,11 +1848,14 @@ bool mod_color_adjust_source_gamut(struct mod_color *mod_color, { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; update_color_gamut_data(input_gamut_data, &core_color->state[sink_index].source_gamut); @@ -1903,11 +1874,14 @@ bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; update_color_gamut_data(input_gamut_data, &core_color->state[sink_index].source_gamut); core_color->state[sink_index].input_transfer_function = @@ -1926,11 +1900,14 @@ bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; update_color_gamut_data(input_gamut_data, &core_color->state[sink_index].destination_gamut); @@ -1948,12 +1925,15 @@ bool mod_color_set_white_point(struct mod_color *mod_color, { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; core_color->state[sink_index].source_gamut.gamut.whiteX = white_point->whiteX; core_color->state[sink_index].source_gamut.gamut.whiteY = @@ -1972,11 +1952,14 @@ bool mod_color_set_mastering_info(struct mod_color *mod_color, const struct dc_hdr_static_metadata *mastering_info) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; memcpy(&core_color->state[sink_index].mastering_info, mastering_info, sizeof(struct dc_hdr_static_metadata)); @@ -1991,7 +1974,10 @@ bool mod_color_get_mastering_info(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; memcpy(mastering_info, &core_color->state[sink_index].mastering_info, sizeof(struct dc_hdr_static_metadata)); @@ -2007,11 +1993,14 @@ bool mod_color_set_user_enable(struct mod_color *mod_color, MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; core_color->state[sink_index].user_enable_color_temperature = user_enable; @@ -2037,7 +2026,10 @@ bool mod_color_get_user_enable(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *user_enable = core_color->state[sink_index]. user_enable_color_temperature; @@ -2052,7 +2044,10 @@ bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_temperature = core_color->state[sink_index]. custom_color_temperature; @@ -2068,11 +2063,14 @@ bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; core_color->state[sink_index].custom_color_temperature = color_temperature; @@ -2098,7 +2096,10 @@ bool mod_color_get_color_saturation(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_saturation = core_color->state[sink_index].saturation; @@ -2112,7 +2113,10 @@ bool mod_color_get_color_contrast(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_contrast = core_color->state[sink_index].contrast; @@ -2126,7 +2130,10 @@ bool mod_color_get_color_brightness(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_brightness = core_color->state[sink_index].brightness; @@ -2140,7 +2147,10 @@ bool mod_color_get_color_hue(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *color_hue = core_color->state[sink_index].hue; @@ -2154,7 +2164,10 @@ bool mod_color_get_source_gamut(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; *source_gamut = core_color->state[sink_index].source_gamut.gamut; @@ -2169,11 +2182,14 @@ bool mod_color_notify_mode_change(struct mod_color *mod_color, struct gamut_src_dst_matrix *matrix = dm_alloc(sizeof(struct gamut_src_dst_matrix)); - unsigned int stream_index, sink_index, j; + unsigned int stream_index, j; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; if (!build_gamut_remap_matrix (core_color->state[sink_index].source_gamut.gamut, @@ -2247,11 +2263,14 @@ bool mod_color_set_brightness(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct core_stream *core_stream = DC_STREAM_TO_CORE @@ -2291,11 +2310,14 @@ bool mod_color_set_contrast(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct core_stream *core_stream = DC_STREAM_TO_CORE @@ -2335,11 +2357,14 @@ bool mod_color_set_hue(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct core_stream *core_stream = DC_STREAM_TO_CORE @@ -2378,11 +2403,14 @@ bool mod_color_set_saturation(struct mod_color *mod_color, struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct core_stream *core_stream = DC_STREAM_TO_CORE @@ -2420,11 +2448,14 @@ bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, struct dc_gamma *gamma) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; struct dc_surface *surface = dc_stream_to_surface_from_pipe_ctx(core_color, @@ -2471,9 +2502,12 @@ bool mod_color_persist_user_preferred_quantization_range( struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); struct core_dc *core_dc = DC_TO_CORE(core_color->dc); struct persistent_data_flag flag; - unsigned int sink_index; + int sink_index; sink_index = sink_index_from_sink(core_color, sink); + if (sink_index == -1) + return false; + if (core_color->state[sink_index]. preferred_quantization_range != quantization_range) { core_color->state[sink_index].preferred_quantization_range = @@ -2498,7 +2532,11 @@ bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, enum dc_quantization_range *quantization_range) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int sink_index = sink_index_from_sink(core_color, sink); + int sink_index = sink_index_from_sink(core_color, sink); + + if (sink_index == -1) + return false; + enum dc_quantization_range user_preferred_quantization_range = core_color->state[sink_index]. preferred_quantization_range; @@ -2601,7 +2639,8 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, const struct dc_stream **streams, int num_streams) { struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index, sink_index; + unsigned int stream_index; + int sink_index; bool should_defer = false; bool is_hdr = false; enum color_color_space source_color_space; @@ -2612,6 +2651,8 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, for (stream_index = 0; stream_index < num_streams; stream_index++) { sink_index = sink_index_from_sink(core_color, streams[stream_index]->sink); + if (sink_index == -1) + continue; source_color_space = core_color->state[sink_index].source_gamut.color_space; input_transfer_function = -- GitLab From 649aa6f4fc40395153834ea78531e0cffd5ee49d Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 23 Dec 2016 11:08:43 -0500 Subject: [PATCH 0152/2898] drm/amd/display: enable option to disable HDR related updates. Signed-off-by: Tony Cheng Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 12620df7056d..69819d834543 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1526,6 +1526,9 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda } } + if (dc->debug.disable_color_module) + continue; /* skip below color updates */ + if (updates[i].hdr_static_metadata) { resource_build_info_frame(pipe_ctx); core_dc->hwss.update_info_frame(pipe_ctx); -- GitLab From 84773406bbe77c0be5abe3b616a78bfb34b128ad Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 29 Dec 2016 15:27:07 -0500 Subject: [PATCH 0153/2898] drm/amd/display: Remove unused color and power modules Signed-off-by: Harry Wentland Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/color/color.c | 2825 ----------------- .../amd/display/modules/color/color_helper.c | 210 -- .../amd/display/modules/color/color_helper.h | 62 - .../drm/amd/display/modules/inc/mod_color.h | 282 -- .../drm/amd/display/modules/inc/mod_power.h | 112 - .../gpu/drm/amd/display/modules/power/power.c | 784 ----- 6 files changed, 4275 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/modules/color/color.c delete mode 100644 drivers/gpu/drm/amd/display/modules/color/color_helper.c delete mode 100644 drivers/gpu/drm/amd/display/modules/color/color_helper.h delete mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_color.h delete mode 100644 drivers/gpu/drm/amd/display/modules/inc/mod_power.h delete mode 100644 drivers/gpu/drm/amd/display/modules/power/power.c diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c deleted file mode 100644 index 74298c8aad8d..000000000000 --- a/drivers/gpu/drm/amd/display/modules/color/color.c +++ /dev/null @@ -1,2825 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dc.h" -#include "mod_color.h" -#include "core_types.h" -#include "fixed31_32.h" -#include "core_dc.h" - -#define MOD_COLOR_MAX_CONCURRENT_SINKS 32 -#define DIVIDER 10000 -/* S2D13 value in [-3.00...0.9999] */ -#define S2D13_MIN (-3 * DIVIDER) -#define S2D13_MAX (3 * DIVIDER) -#define S0D13_MIN (-1 * DIVIDER) -#define S0D13_MAX (1 * DIVIDER) - -struct sink_caps { - const struct dc_sink *sink; -}; - -struct gamut_calculation_matrix { - struct fixed31_32 MTransposed[9]; - struct fixed31_32 XYZtoRGB_Custom[9]; - struct fixed31_32 XYZtoRGB_Ref[9]; - struct fixed31_32 RGBtoXYZ_Final[9]; - - struct fixed31_32 MResult[9]; - struct fixed31_32 fXYZofWhiteRef[9]; - struct fixed31_32 fXYZofRGBRef[9]; -}; - -struct gamut_src_dst_matrix { - struct fixed31_32 rgbCoeffDst[9]; - struct fixed31_32 whiteCoeffDst[3]; - struct fixed31_32 rgbCoeffSrc[9]; - struct fixed31_32 whiteCoeffSrc[3]; -}; - -struct color_state { - bool user_enable_color_temperature; - int custom_color_temperature; - struct color_range contrast; - struct color_range saturation; - struct color_range brightness; - struct color_range hue; - struct dc_gamma *gamma; - enum dc_quantization_range preferred_quantization_range; - - struct color_gamut_data source_gamut; - struct color_gamut_data destination_gamut; - enum color_transfer_func input_transfer_function; - enum color_transfer_func output_transfer_function; - struct dc_hdr_static_metadata mastering_info; -}; - -struct core_color { - struct mod_color public; - struct dc *dc; - int num_sinks; - struct sink_caps *caps; - struct color_state *state; - struct color_edid_caps *edid_caps; -}; - -#define MOD_COLOR_TO_CORE(mod_color)\ - container_of(mod_color, struct core_color, public) - -#define COLOR_REGISTRY_NAME "color_v1" - -/*Matrix Calculation Functions*/ -/** - ***************************************************************************** - * Function: transposeMatrix - * - * @brief - * rotate the matrix 90 degrees clockwise - * rows become a columns and columns to rows - * @param [ in ] M - source matrix - * @param [ in ] Rows - num of Rows of the original matrix - * @param [ in ] Cols - num of Cols of the original matrix - * @param [ out] MTransposed - result matrix - * @return void - * - ***************************************************************************** - */ -static void transpose_matrix(const struct fixed31_32 *M, unsigned int Rows, - unsigned int Cols, struct fixed31_32 *MTransposed) -{ - unsigned int i, j; - - for (i = 0; i < Rows; i++) { - for (j = 0; j < Cols; j++) - MTransposed[(j*Rows)+i] = M[(i*Cols)+j]; - } -} - -/** - ***************************************************************************** - * Function: multiplyMatrices - * - * @brief - * multiplies produce of two matrices: M = M1[ulRows1 x ulCols1] * - * M2[ulCols1 x ulCols2]. - * - * @param [ in ] M1 - first Matrix. - * @param [ in ] M2 - second Matrix. - * @param [ in ] Rows1 - num of Rows of the first Matrix - * @param [ in ] Cols1 - num of Cols of the first Matrix/Num of Rows - * of the second Matrix - * @param [ in ] Cols2 - num of Cols of the second Matrix - * @param [out ] mResult - resulting matrix. - * @return void - * - ***************************************************************************** - */ -static void multiply_matrices(struct fixed31_32 *mResult, - const struct fixed31_32 *M1, - const struct fixed31_32 *M2, unsigned int Rows1, - unsigned int Cols1, unsigned int Cols2) -{ - unsigned int i, j, k; - - for (i = 0; i < Rows1; i++) { - for (j = 0; j < Cols2; j++) { - mResult[(i * Cols2) + j] = dal_fixed31_32_zero; - for (k = 0; k < Cols1; k++) - mResult[(i * Cols2) + j] = - dal_fixed31_32_add - (mResult[(i * Cols2) + j], - dal_fixed31_32_mul(M1[(i * Cols1) + k], - M2[(k * Cols2) + j])); - } - } -} - -/** - ***************************************************************************** - * Function: cFind3X3Det - * - * @brief - * finds determinant of given 3x3 matrix - * - * @param [ in ] m - matrix - * @return determinate whioch could not be zero - * - ***************************************************************************** - */ -static struct fixed31_32 find_3X3_det(const struct fixed31_32 *m) -{ - struct fixed31_32 det, A1, A2, A3; - - A1 = dal_fixed31_32_mul(m[0], - dal_fixed31_32_sub(dal_fixed31_32_mul(m[4], m[8]), - dal_fixed31_32_mul(m[5], m[7]))); - A2 = dal_fixed31_32_mul(m[1], - dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[8]), - dal_fixed31_32_mul(m[5], m[6]))); - A3 = dal_fixed31_32_mul(m[2], - dal_fixed31_32_sub(dal_fixed31_32_mul(m[3], m[7]), - dal_fixed31_32_mul(m[4], m[6]))); - det = dal_fixed31_32_add(dal_fixed31_32_sub(A1, A2), A3); - return det; -} - - -/** - ***************************************************************************** - * Function: computeInverseMatrix_3x3 - * - * @brief - * builds inverse matrix - * - * @param [ in ] m - matrix - * @param [ out ] im - result matrix - * @return true if success - * - ***************************************************************************** - */ -static bool compute_inverse_matrix_3x3(const struct fixed31_32 *m, - struct fixed31_32 *im) -{ - struct fixed31_32 determinant = find_3X3_det(m); - - if (dal_fixed31_32_eq(determinant, dal_fixed31_32_zero) == false) { - im[0] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[4], m[8]), - dal_fixed31_32_mul(m[5], m[7])), determinant); - im[1] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[1], m[8]), - dal_fixed31_32_mul(m[2], m[7])), determinant)); - im[2] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[1], m[5]), - dal_fixed31_32_mul(m[2], m[4])), determinant); - im[3] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[3], m[8]), - dal_fixed31_32_mul(m[5], m[6])), determinant)); - im[4] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[0], m[8]), - dal_fixed31_32_mul(m[2], m[6])), determinant); - im[5] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[0], m[5]), - dal_fixed31_32_mul(m[2], m[3])), determinant)); - im[6] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[3], m[7]), - dal_fixed31_32_mul(m[4], m[6])), determinant); - im[7] = dal_fixed31_32_neg(dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[0], m[7]), - dal_fixed31_32_mul(m[1], m[6])), determinant)); - im[8] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_mul(m[0], m[4]), - dal_fixed31_32_mul(m[1], m[3])), determinant); - return true; - } - return false; -} - -/** - ***************************************************************************** - * Function: calculateXYZtoRGB_M3x3 - * - * @brief - * Calculates transformation matrix from XYZ coordinates to RBG - * - * @param [ in ] XYZofRGB - primaries XYZ - * @param [ in ] XYZofWhite - white point. - * @param [ out ] XYZtoRGB - RGB primires - * @return true if success - * - ***************************************************************************** - */ -static bool calculate_XYZ_to_RGB_3x3(const struct fixed31_32 *XYZofRGB, - const struct fixed31_32 *XYZofWhite, - struct fixed31_32 *XYZtoRGB) -{ - - struct fixed31_32 MInversed[9]; - struct fixed31_32 SVector[3]; - - /*1. Find Inverse matrix 3x3 of MTransposed*/ - if (!compute_inverse_matrix_3x3(XYZofRGB, MInversed)) - return false; - - /*2. Calculate vector: |Sr Sg Sb| = [MInversed] * |Wx Wy Wz|*/ - multiply_matrices(SVector, MInversed, XYZofWhite, 3, 3, 1); - - /*3. Calculate matrix XYZtoRGB 3x3*/ - XYZtoRGB[0] = dal_fixed31_32_mul(XYZofRGB[0], SVector[0]); - XYZtoRGB[1] = dal_fixed31_32_mul(XYZofRGB[1], SVector[1]); - XYZtoRGB[2] = dal_fixed31_32_mul(XYZofRGB[2], SVector[2]); - - XYZtoRGB[3] = dal_fixed31_32_mul(XYZofRGB[3], SVector[0]); - XYZtoRGB[4] = dal_fixed31_32_mul(XYZofRGB[4], SVector[1]); - XYZtoRGB[5] = dal_fixed31_32_mul(XYZofRGB[5], SVector[2]); - - XYZtoRGB[6] = dal_fixed31_32_mul(XYZofRGB[6], SVector[0]); - XYZtoRGB[7] = dal_fixed31_32_mul(XYZofRGB[7], SVector[1]); - XYZtoRGB[8] = dal_fixed31_32_mul(XYZofRGB[8], SVector[2]); - - return true; -} - -static bool gamut_to_color_matrix( - const struct fixed31_32 *pXYZofRGB,/*destination gamut*/ - const struct fixed31_32 *pXYZofWhite,/*destination of white point*/ - const struct fixed31_32 *pRefXYZofRGB,/*source gamut*/ - const struct fixed31_32 *pRefXYZofWhite,/*source of white point*/ - bool invert, - struct fixed31_32 *tempMatrix3X3) -{ - int i = 0; - struct gamut_calculation_matrix *matrix = - dm_alloc(sizeof(struct gamut_calculation_matrix)); - - struct fixed31_32 *pXYZtoRGB_Temp; - struct fixed31_32 *pXYZtoRGB_Final; - - matrix->fXYZofWhiteRef[0] = pRefXYZofWhite[0]; - matrix->fXYZofWhiteRef[1] = pRefXYZofWhite[1]; - matrix->fXYZofWhiteRef[2] = pRefXYZofWhite[2]; - - - matrix->fXYZofRGBRef[0] = pRefXYZofRGB[0]; - matrix->fXYZofRGBRef[1] = pRefXYZofRGB[1]; - matrix->fXYZofRGBRef[2] = pRefXYZofRGB[2]; - - matrix->fXYZofRGBRef[3] = pRefXYZofRGB[3]; - matrix->fXYZofRGBRef[4] = pRefXYZofRGB[4]; - matrix->fXYZofRGBRef[5] = pRefXYZofRGB[5]; - - matrix->fXYZofRGBRef[6] = pRefXYZofRGB[6]; - matrix->fXYZofRGBRef[7] = pRefXYZofRGB[7]; - matrix->fXYZofRGBRef[8] = pRefXYZofRGB[8]; - - /*default values - unity matrix*/ - while (i < 9) { - if (i == 0 || i == 4 || i == 8) - tempMatrix3X3[i] = dal_fixed31_32_one; - else - tempMatrix3X3[i] = dal_fixed31_32_zero; - i++; - } - - /*1. Decide about the order of calculation. - * bInvert == FALSE --> RGBtoXYZ_Ref * XYZtoRGB_Custom - * bInvert == TRUE --> RGBtoXYZ_Custom * XYZtoRGB_Ref */ - if (invert) { - pXYZtoRGB_Temp = matrix->XYZtoRGB_Custom; - pXYZtoRGB_Final = matrix->XYZtoRGB_Ref; - } else { - pXYZtoRGB_Temp = matrix->XYZtoRGB_Ref; - pXYZtoRGB_Final = matrix->XYZtoRGB_Custom; - } - - /*2. Calculate XYZtoRGB_Ref*/ - transpose_matrix(matrix->fXYZofRGBRef, 3, 3, matrix->MTransposed); - - if (!calculate_XYZ_to_RGB_3x3( - matrix->MTransposed, - matrix->fXYZofWhiteRef, - matrix->XYZtoRGB_Ref)) - goto function_fail; - - /*3. Calculate XYZtoRGB_Custom*/ - transpose_matrix(pXYZofRGB, 3, 3, matrix->MTransposed); - - if (!calculate_XYZ_to_RGB_3x3( - matrix->MTransposed, - pXYZofWhite, - matrix->XYZtoRGB_Custom)) - goto function_fail; - - /*4. Calculate RGBtoXYZ - - * inverse matrix 3x3 of XYZtoRGB_Ref or XYZtoRGB_Custom*/ - if (!compute_inverse_matrix_3x3(pXYZtoRGB_Temp, matrix->RGBtoXYZ_Final)) - goto function_fail; - - /*5. Calculate M(3x3) = RGBtoXYZ * XYZtoRGB*/ - multiply_matrices(matrix->MResult, matrix->RGBtoXYZ_Final, - pXYZtoRGB_Final, 3, 3, 3); - - for (i = 0; i < 9; i++) - tempMatrix3X3[i] = matrix->MResult[i]; - - dm_free(matrix); - - return true; - -function_fail: - dm_free(matrix); - return false; -} - -static bool build_gamut_remap_matrix - (struct color_space_coordinates gamut_description, - struct fixed31_32 *rgb_matrix, - struct fixed31_32 *white_point_matrix) -{ - struct fixed31_32 fixed_blueX = dal_fixed31_32_from_fraction - (gamut_description.blueX, DIVIDER); - struct fixed31_32 fixed_blueY = dal_fixed31_32_from_fraction - (gamut_description.blueY, DIVIDER); - struct fixed31_32 fixed_greenX = dal_fixed31_32_from_fraction - (gamut_description.greenX, DIVIDER); - struct fixed31_32 fixed_greenY = dal_fixed31_32_from_fraction - (gamut_description.greenY, DIVIDER); - struct fixed31_32 fixed_redX = dal_fixed31_32_from_fraction - (gamut_description.redX, DIVIDER); - struct fixed31_32 fixed_redY = dal_fixed31_32_from_fraction - (gamut_description.redY, DIVIDER); - struct fixed31_32 fixed_whiteX = dal_fixed31_32_from_fraction - (gamut_description.whiteX, DIVIDER); - struct fixed31_32 fixed_whiteY = dal_fixed31_32_from_fraction - (gamut_description.whiteY, DIVIDER); - - rgb_matrix[0] = dal_fixed31_32_div(fixed_redX, fixed_redY); - rgb_matrix[1] = dal_fixed31_32_one; - rgb_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_redX), - fixed_redY), fixed_redY); - - rgb_matrix[3] = dal_fixed31_32_div(fixed_greenX, fixed_greenY); - rgb_matrix[4] = dal_fixed31_32_one; - rgb_matrix[5] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_greenX), - fixed_greenY), fixed_greenY); - - rgb_matrix[6] = dal_fixed31_32_div(fixed_blueX, fixed_blueY); - rgb_matrix[7] = dal_fixed31_32_one; - rgb_matrix[8] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_blueX), - fixed_blueY), fixed_blueY); - - white_point_matrix[0] = dal_fixed31_32_div(fixed_whiteX, fixed_whiteY); - white_point_matrix[1] = dal_fixed31_32_one; - white_point_matrix[2] = dal_fixed31_32_div(dal_fixed31_32_sub - (dal_fixed31_32_sub(dal_fixed31_32_one, fixed_whiteX), - fixed_whiteY), fixed_whiteY); - - return true; -} - -static bool check_dc_support(const struct dc *dc) -{ - if (dc->stream_funcs.set_gamut_remap == NULL) - return false; - - return true; -} - -static uint16_t fixed_point_to_int_frac( - struct fixed31_32 arg, - uint8_t integer_bits, - uint8_t fractional_bits) -{ - int32_t numerator; - int32_t divisor = 1 << fractional_bits; - - uint16_t result; - - uint16_t d = (uint16_t)dal_fixed31_32_floor( - dal_fixed31_32_abs( - arg)); - - if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) - numerator = (uint16_t)dal_fixed31_32_floor( - dal_fixed31_32_mul_int( - arg, - divisor)); - else { - numerator = dal_fixed31_32_floor( - dal_fixed31_32_sub( - dal_fixed31_32_from_int( - 1LL << integer_bits), - dal_fixed31_32_recip( - dal_fixed31_32_from_int( - divisor)))); - } - - if (numerator >= 0) - result = (uint16_t)numerator; - else - result = (uint16_t)( - (1 << (integer_bits + fractional_bits + 1)) + numerator); - - if ((result != 0) && dal_fixed31_32_lt( - arg, dal_fixed31_32_zero)) - result |= 1 << (integer_bits + fractional_bits); - - return result; -} - -/** -* convert_float_matrix -* This converts a double into HW register spec defined format S2D13. -* @param : -* @return None -*/ - -static void convert_float_matrix_legacy( - uint16_t *matrix, - struct fixed31_32 *flt, - uint32_t buffer_size) -{ - const struct fixed31_32 min_2_13 = - dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); - const struct fixed31_32 max_2_13 = - dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); - uint32_t i; - - for (i = 0; i < buffer_size; ++i) { - uint32_t reg_value = - fixed_point_to_int_frac( - dal_fixed31_32_clamp( - flt[i], - min_2_13, - max_2_13), - 2, - 13); - - matrix[i] = (uint16_t)reg_value; - } -} - -static void convert_float_matrix( - uint16_t *matrix, - struct fixed31_32 *flt, - uint32_t buffer_size) -{ - const struct fixed31_32 min_0_13 = - dal_fixed31_32_from_fraction(S0D13_MIN, DIVIDER); - const struct fixed31_32 max_0_13 = - dal_fixed31_32_from_fraction(S0D13_MAX, DIVIDER); - const struct fixed31_32 min_2_13 = - dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER); - const struct fixed31_32 max_2_13 = - dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER); - uint32_t i; - uint16_t temp_matrix[12]; - - for (i = 0; i < buffer_size; ++i) { - if (i == 3 || i == 7 || i == 11) { - uint32_t reg_value = - fixed_point_to_int_frac( - dal_fixed31_32_clamp( - flt[i], - min_0_13, - max_0_13), - 2, - 13); - - temp_matrix[i] = (uint16_t)reg_value; - } else { - uint32_t reg_value = - fixed_point_to_int_frac( - dal_fixed31_32_clamp( - flt[i], - min_2_13, - max_2_13), - 2, - 13); - - temp_matrix[i] = (uint16_t)reg_value; - } - } - - matrix[4] = temp_matrix[0]; - matrix[5] = temp_matrix[1]; - matrix[6] = temp_matrix[2]; - matrix[7] = temp_matrix[3]; - - matrix[8] = temp_matrix[4]; - matrix[9] = temp_matrix[5]; - matrix[10] = temp_matrix[6]; - matrix[11] = temp_matrix[7]; - - matrix[0] = temp_matrix[8]; - matrix[1] = temp_matrix[9]; - matrix[2] = temp_matrix[10]; - matrix[3] = temp_matrix[11]; -} - -static int get_hw_value_from_sw_value(int swVal, int swMin, - int swMax, int hwMin, int hwMax) -{ - int dSW = swMax - swMin; /*software adjustment range size*/ - int dHW = hwMax - hwMin; /*hardware adjustment range size*/ - int hwVal; /*HW adjustment value*/ - - /* error case, I preserve the behavior from the predecessor - *getHwStepFromSwHwMinMaxValue (removed in Feb 2013) - *which was the FP version that only computed SCLF (i.e. dHW/dSW). - *it would return 0 in this case so - *hwVal = hwMin from the formula given in @brief - */ - if (dSW == 0) - return hwMin; - - /*it's quite often that ranges match, - *e.g. for overlay colors currently (Feb 2013) - *only brightness has a different - *HW range, and in this case no multiplication or division is needed, - *and if minimums match, no calculation at all - */ - if (dSW != dHW) { - hwVal = (swVal - swMin)*dHW/dSW + hwMin; - } else { - hwVal = swVal; - if (swMin != hwMin) - hwVal += (hwMin - swMin); - } - - return hwVal; -} - -static void initialize_fix_point_color_values( - struct core_color *core_color, - unsigned int sink_index, - struct fixed31_32 *grph_cont, - struct fixed31_32 *grph_sat, - struct fixed31_32 *grph_bright, - struct fixed31_32 *sin_grph_hue, - struct fixed31_32 *cos_grph_hue) -{ - /* Hue adjustment could be negative. -45 ~ +45 */ - struct fixed31_32 hue = - dal_fixed31_32_mul( - dal_fixed31_32_from_fraction - (get_hw_value_from_sw_value - (core_color->state[sink_index].hue.current, - core_color->state[sink_index].hue.min, - core_color->state[sink_index].hue.max, - -30, 30), 180), - dal_fixed31_32_pi); - - *sin_grph_hue = dal_fixed31_32_sin(hue); - *cos_grph_hue = dal_fixed31_32_cos(hue); - - *grph_cont = - dal_fixed31_32_from_fraction(get_hw_value_from_sw_value - (core_color->state[sink_index].contrast.current, - core_color->state[sink_index].contrast.min, - core_color->state[sink_index].contrast.max, - 50, 150), 100); - *grph_sat = - dal_fixed31_32_from_fraction(get_hw_value_from_sw_value - (core_color->state[sink_index].saturation.current, - core_color->state[sink_index].saturation.min, - core_color->state[sink_index].saturation.max, - 0, 200), 100); - *grph_bright = - dal_fixed31_32_from_fraction(get_hw_value_from_sw_value - (core_color->state[sink_index].brightness.current, - core_color->state[sink_index].brightness.min, - core_color->state[sink_index].brightness.max, - -25, 25), 100); -} - - -/* Given a specific dc_sink* this function finds its equivalent - * on the dc_sink array and returns the corresponding index - */ -static int sink_index_from_sink(struct core_color *core_color, - const struct dc_sink *sink) -{ - int index = 0; - - for (index = 0; index < core_color->num_sinks; index++) - if (core_color->caps[index].sink == sink) - return index; - - /* Could not find sink requested */ - ASSERT(false); - return -1; -} - -static void calculate_rgb_matrix_legacy(struct core_color *core_color, - unsigned int sink_index, - struct fixed31_32 *rgb_matrix) -{ - const struct fixed31_32 k1 = - dal_fixed31_32_from_fraction(701000, 1000000); - const struct fixed31_32 k2 = - dal_fixed31_32_from_fraction(236568, 1000000); - const struct fixed31_32 k3 = - dal_fixed31_32_from_fraction(-587000, 1000000); - const struct fixed31_32 k4 = - dal_fixed31_32_from_fraction(464432, 1000000); - const struct fixed31_32 k5 = - dal_fixed31_32_from_fraction(-114000, 1000000); - const struct fixed31_32 k6 = - dal_fixed31_32_from_fraction(-701000, 1000000); - const struct fixed31_32 k7 = - dal_fixed31_32_from_fraction(-299000, 1000000); - const struct fixed31_32 k8 = - dal_fixed31_32_from_fraction(-292569, 1000000); - const struct fixed31_32 k9 = - dal_fixed31_32_from_fraction(413000, 1000000); - const struct fixed31_32 k10 = - dal_fixed31_32_from_fraction(-92482, 1000000); - const struct fixed31_32 k11 = - dal_fixed31_32_from_fraction(-114000, 1000000); - const struct fixed31_32 k12 = - dal_fixed31_32_from_fraction(385051, 1000000); - const struct fixed31_32 k13 = - dal_fixed31_32_from_fraction(-299000, 1000000); - const struct fixed31_32 k14 = - dal_fixed31_32_from_fraction(886000, 1000000); - const struct fixed31_32 k15 = - dal_fixed31_32_from_fraction(-587000, 1000000); - const struct fixed31_32 k16 = - dal_fixed31_32_from_fraction(-741914, 1000000); - const struct fixed31_32 k17 = - dal_fixed31_32_from_fraction(886000, 1000000); - const struct fixed31_32 k18 = - dal_fixed31_32_from_fraction(-144086, 1000000); - - const struct fixed31_32 luma_r = - dal_fixed31_32_from_fraction(299, 1000); - const struct fixed31_32 luma_g = - dal_fixed31_32_from_fraction(587, 1000); - const struct fixed31_32 luma_b = - dal_fixed31_32_from_fraction(114, 1000); - - struct fixed31_32 grph_cont; - struct fixed31_32 grph_sat; - struct fixed31_32 grph_bright; - struct fixed31_32 sin_grph_hue; - struct fixed31_32 cos_grph_hue; - - initialize_fix_point_color_values( - core_color, sink_index, &grph_cont, &grph_sat, - &grph_bright, &sin_grph_hue, &cos_grph_hue); - - /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +*/ - /* Sin(GrphHue) * K2))*/ - /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)*/ - rgb_matrix[0] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k1), - dal_fixed31_32_mul(sin_grph_hue, k2)); - /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ - rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/ - rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/ - /* K2))*/ - rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]); - - /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/ - /* Sin(GrphHue) * K4))*/ - /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ - rgb_matrix[1] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k3), - dal_fixed31_32_mul(sin_grph_hue, k4)); - /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ - rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/ - rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/ - /* K4))*/ - rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]); - - /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/ - /* Sin(GrphHue) * K6))*/ - /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k5), - dal_fixed31_32_mul(sin_grph_hue, k6)); - /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]); - /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/ - /* K6))*/ - rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]); - - /* COEF_1_4 = GrphBright*/ - rgb_matrix[3] = grph_bright; - - /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/ - /* Sin(GrphHue) * K8))*/ - /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ - rgb_matrix[4] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k7), - dal_fixed31_32_mul(sin_grph_hue, k8)); - /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ - rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/ - rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/ - /* K8))*/ - rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]); - - /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/ - /* Sin(GrphHue) * K10))*/ - /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k9), - dal_fixed31_32_mul(sin_grph_hue, k10)); - /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/ - /* K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]); - - /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/ - /* Sin(GrphHue) * K12))*/ - /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k11), - dal_fixed31_32_mul(sin_grph_hue, k12)); - /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]); - /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/ - /* K12))*/ - rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]); - - /* COEF_2_4 = GrphBright*/ - rgb_matrix[7] = grph_bright; - - /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ - /* Sin(GrphHue) * K14))*/ - /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k13), - dal_fixed31_32_mul(sin_grph_hue, k14)); - /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/ - /* K14)) */ - rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]); - - /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/ - /* Sin(GrphHue) * K16)) */ - /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ - rgb_matrix[9] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k15), - dal_fixed31_32_mul(sin_grph_hue, k16)); - /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ - rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ - rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/ - /* K16)) */ - rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]); - - /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/ - /* Sin(GrphHue) * K18)) */ - /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k17), - dal_fixed31_32_mul(sin_grph_hue, k18)); - /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]); - /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/ - /* K18)) */ - rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]); - - /* COEF_3_4 = GrphBright */ - rgb_matrix[11] = grph_bright; -} - -static void calculate_rgb_limited_range_matrix_legacy( - struct core_color *core_color, unsigned int sink_index, - struct fixed31_32 *rgb_matrix) -{ - const struct fixed31_32 k1 = - dal_fixed31_32_from_fraction(701000, 1000000); - const struct fixed31_32 k2 = - dal_fixed31_32_from_fraction(236568, 1000000); - const struct fixed31_32 k3 = - dal_fixed31_32_from_fraction(-587000, 1000000); - const struct fixed31_32 k4 = - dal_fixed31_32_from_fraction(464432, 1000000); - const struct fixed31_32 k5 = - dal_fixed31_32_from_fraction(-114000, 1000000); - const struct fixed31_32 k6 = - dal_fixed31_32_from_fraction(-701000, 1000000); - const struct fixed31_32 k7 = - dal_fixed31_32_from_fraction(-299000, 1000000); - const struct fixed31_32 k8 = - dal_fixed31_32_from_fraction(-292569, 1000000); - const struct fixed31_32 k9 = - dal_fixed31_32_from_fraction(413000, 1000000); - const struct fixed31_32 k10 = - dal_fixed31_32_from_fraction(-92482, 1000000); - const struct fixed31_32 k11 = - dal_fixed31_32_from_fraction(-114000, 1000000); - const struct fixed31_32 k12 = - dal_fixed31_32_from_fraction(385051, 1000000); - const struct fixed31_32 k13 = - dal_fixed31_32_from_fraction(-299000, 1000000); - const struct fixed31_32 k14 = - dal_fixed31_32_from_fraction(886000, 1000000); - const struct fixed31_32 k15 = - dal_fixed31_32_from_fraction(-587000, 1000000); - const struct fixed31_32 k16 = - dal_fixed31_32_from_fraction(-741914, 1000000); - const struct fixed31_32 k17 = - dal_fixed31_32_from_fraction(886000, 1000000); - const struct fixed31_32 k18 = - dal_fixed31_32_from_fraction(-144086, 1000000); - - const struct fixed31_32 luma_r = - dal_fixed31_32_from_fraction(299, 1000); - const struct fixed31_32 luma_g = - dal_fixed31_32_from_fraction(587, 1000); - const struct fixed31_32 luma_b = - dal_fixed31_32_from_fraction(114, 1000); - const struct fixed31_32 luma_scale = - dal_fixed31_32_from_fraction(875855, 1000000); - - const struct fixed31_32 rgb_scale = - dal_fixed31_32_from_fraction(85546875, 100000000); - const struct fixed31_32 rgb_bias = - dal_fixed31_32_from_fraction(625, 10000); - - struct fixed31_32 grph_cont; - struct fixed31_32 grph_sat; - struct fixed31_32 grph_bright; - struct fixed31_32 sin_grph_hue; - struct fixed31_32 cos_grph_hue; - - initialize_fix_point_color_values( - core_color, sink_index, &grph_cont, &grph_sat, - &grph_bright, &sin_grph_hue, &cos_grph_hue); - - /* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +*/ - /* Sin(GrphHue) * K2))*/ - /* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)*/ - rgb_matrix[0] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k1), - dal_fixed31_32_mul(sin_grph_hue, k2)); - /* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */ - rgb_matrix[0] = dal_fixed31_32_mul(grph_sat, rgb_matrix[0]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2))*/ - rgb_matrix[0] = dal_fixed31_32_add(luma_r, rgb_matrix[0]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue)**/ - /* K2))*/ - rgb_matrix[0] = dal_fixed31_32_mul(grph_cont, rgb_matrix[0]); - /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + */ - /* Sin(GrphHue) * K2))*/ - rgb_matrix[0] = dal_fixed31_32_mul(luma_scale, rgb_matrix[0]); - - /* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +*/ - /* Sin(GrphHue) * K4))*/ - /* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ - rgb_matrix[1] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k3), - dal_fixed31_32_mul(sin_grph_hue, k4)); - /* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)*/ - rgb_matrix[1] = dal_fixed31_32_mul(grph_sat, rgb_matrix[1]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4))*/ - rgb_matrix[1] = dal_fixed31_32_add(luma_g, rgb_matrix[1]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue)**/ - /* K4))*/ - rgb_matrix[1] = dal_fixed31_32_mul(grph_cont, rgb_matrix[1]); - /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K3 + */ - /* Sin(GrphHue) * K4))*/ - rgb_matrix[1] = dal_fixed31_32_mul(luma_scale, rgb_matrix[1]); - - /* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +*/ - /* Sin(GrphHue) * K6))*/ - /* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k5), - dal_fixed31_32_mul(sin_grph_hue, k6)); - /* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = dal_fixed31_32_mul(grph_sat, rgb_matrix[2]); - /* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6)*/ - rgb_matrix[2] = dal_fixed31_32_add(luma_b, rgb_matrix[2]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue)**/ - /* K6))*/ - rgb_matrix[2] = dal_fixed31_32_mul(grph_cont, rgb_matrix[2]); - /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * K5 + */ - /* Sin(GrphHue) * K6))*/ - rgb_matrix[2] = dal_fixed31_32_mul(luma_scale, rgb_matrix[2]); - - /* COEF_1_4 = RGBBias + RGBScale * GrphBright*/ - rgb_matrix[3] = dal_fixed31_32_add( - rgb_bias, - dal_fixed31_32_mul(rgb_scale, grph_bright)); - - /* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +*/ - /* Sin(GrphHue) * K8))*/ - /* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ - rgb_matrix[4] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k7), - dal_fixed31_32_mul(sin_grph_hue, k8)); - /* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)*/ - rgb_matrix[4] = dal_fixed31_32_mul(grph_sat, rgb_matrix[4]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8))*/ - rgb_matrix[4] = dal_fixed31_32_add(luma_r, rgb_matrix[4]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue)**/ - /* K8))*/ - rgb_matrix[4] = dal_fixed31_32_mul(grph_cont, rgb_matrix[4]); - /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + */ - /* Sin(GrphHue) * K8))*/ - rgb_matrix[4] = dal_fixed31_32_mul(luma_scale, rgb_matrix[4]); - - /* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +*/ - /* Sin(GrphHue) * K10))*/ - /* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k9), - dal_fixed31_32_mul(sin_grph_hue, k10)); - /* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(grph_sat, rgb_matrix[5]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_add(luma_g, rgb_matrix[5]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue)**/ - /* K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(grph_cont, rgb_matrix[5]); - /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K9 + */ - /* Sin(GrphHue) * K10))*/ - rgb_matrix[5] = dal_fixed31_32_mul(luma_scale, rgb_matrix[5]); - - /* COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +*/ - /* Sin(GrphHue) * K12))*/ - /* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k11), - dal_fixed31_32_mul(sin_grph_hue, k12)); - /* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = dal_fixed31_32_mul(grph_sat, rgb_matrix[6]); - /* (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12))*/ - rgb_matrix[6] = dal_fixed31_32_add(luma_b, rgb_matrix[6]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue)**/ - /* K12))*/ - rgb_matrix[6] = dal_fixed31_32_mul(grph_cont, rgb_matrix[6]); - /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * K11 +*/ - /* Sin(GrphHue) * K12)) */ - rgb_matrix[6] = dal_fixed31_32_mul(luma_scale, rgb_matrix[6]); - - /* COEF_2_4 = RGBBias + RGBScale * GrphBright*/ - rgb_matrix[7] = dal_fixed31_32_add( - rgb_bias, - dal_fixed31_32_mul(rgb_scale, grph_bright)); - - /* COEF_3_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ - /* Sin(GrphHue) * K14))*/ - /* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k13), - dal_fixed31_32_mul(sin_grph_hue, k14)); - /* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = dal_fixed31_32_mul(grph_sat, rgb_matrix[8]); - /* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */ - rgb_matrix[8] = dal_fixed31_32_add(luma_r, rgb_matrix[8]); - /* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue)**/ - /* K14)) */ - rgb_matrix[8] = dal_fixed31_32_mul(grph_cont, rgb_matrix[8]); - /* LumaScale * GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K13 +*/ - /* Sin(GrphHue) * K14))*/ - rgb_matrix[8] = dal_fixed31_32_mul(luma_scale, rgb_matrix[8]); - - /* COEF_3_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +*/ - /* Sin(GrphHue) * K16)) */ - /* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */ - rgb_matrix[9] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k15), - dal_fixed31_32_mul(sin_grph_hue, k16)); - /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ - rgb_matrix[9] = dal_fixed31_32_mul(grph_sat, rgb_matrix[9]); - /* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */ - rgb_matrix[9] = dal_fixed31_32_add(luma_g, rgb_matrix[9]); - /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue)**/ - /* K16)) */ - rgb_matrix[9] = dal_fixed31_32_mul(grph_cont, rgb_matrix[9]); - /* LumaScale * GrphCont * (LumaG + GrphSat *(Cos(GrphHue) * K15 + */ - /* Sin(GrphHue) * K16))*/ - rgb_matrix[9] = dal_fixed31_32_mul(luma_scale, rgb_matrix[9]); - - /* COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +*/ - /* Sin(GrphHue) * K18)) */ - /* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = - dal_fixed31_32_add( - dal_fixed31_32_mul(cos_grph_hue, k17), - dal_fixed31_32_mul(sin_grph_hue, k18)); - /* GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = dal_fixed31_32_mul(grph_sat, rgb_matrix[10]); - /* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */ - rgb_matrix[10] = dal_fixed31_32_add(luma_b, rgb_matrix[10]); - /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue)**/ - /* K18)) */ - rgb_matrix[10] = dal_fixed31_32_mul(grph_cont, rgb_matrix[10]); - /* LumaScale * GrphCont * (LumaB + GrphSat *(Cos(GrphHue) * */ - /* K17 + Sin(GrphHue) * K18))*/ - rgb_matrix[10] = dal_fixed31_32_mul(luma_scale, rgb_matrix[10]); - - /* COEF_3_4 = RGBBias + RGBScale * GrphBright */ - rgb_matrix[11] = dal_fixed31_32_add( - rgb_bias, - dal_fixed31_32_mul(rgb_scale, grph_bright)); -} - -static void calculate_yuv_matrix(struct core_color *core_color, - unsigned int sink_index, - enum dc_color_space color_space, - struct fixed31_32 *yuv_matrix) -{ - struct fixed31_32 ideal[12]; - uint32_t i = 0; - - if ((color_space == COLOR_SPACE_YPBPR601) || - (color_space == COLOR_SPACE_YCBCR601) || - (color_space == COLOR_SPACE_YCBCR601_LIMITED)) { - static const int32_t matrix_[] = { - 25578516, 50216016, 9752344, 6250000, - -14764391, -28985609, 43750000, 50000000, - 43750000, -36635164, -7114836, 50000000 - }; - do { - ideal[i] = dal_fixed31_32_from_fraction( - matrix_[i], - 100000000); - ++i; - } while (i != ARRAY_SIZE(matrix_)); - } else { - static const int32_t matrix_[] = { - 18187266, 61183125, 6176484, 6250000, - -10025059, -33724941, 43750000, 50000000, - 43750000, -39738379, -4011621, 50000000 - }; - do { - ideal[i] = dal_fixed31_32_from_fraction( - matrix_[i], - 100000000); - ++i; - } while (i != ARRAY_SIZE(matrix_)); - } - - struct fixed31_32 grph_cont; - struct fixed31_32 grph_sat; - struct fixed31_32 grph_bright; - struct fixed31_32 sin_grph_hue; - struct fixed31_32 cos_grph_hue; - - initialize_fix_point_color_values( - core_color, sink_index, &grph_cont, &grph_sat, - &grph_bright, &sin_grph_hue, &cos_grph_hue); - - const struct fixed31_32 multiplier = - dal_fixed31_32_mul(grph_cont, grph_sat); - - yuv_matrix[0] = dal_fixed31_32_mul(ideal[0], grph_cont); - - yuv_matrix[1] = dal_fixed31_32_mul(ideal[1], grph_cont); - - yuv_matrix[2] = dal_fixed31_32_mul(ideal[2], grph_cont); - - yuv_matrix[4] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[4], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[8], - sin_grph_hue))); - - yuv_matrix[5] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[5], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[9], - sin_grph_hue))); - - yuv_matrix[6] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal[6], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[10], - sin_grph_hue))); - - yuv_matrix[7] = ideal[7]; - - yuv_matrix[8] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[8], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[4], - sin_grph_hue))); - - yuv_matrix[9] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[9], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[5], - sin_grph_hue))); - - yuv_matrix[10] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal[10], - cos_grph_hue), - dal_fixed31_32_mul( - ideal[6], - sin_grph_hue))); - - yuv_matrix[11] = ideal[11]; - - if ((color_space == COLOR_SPACE_YCBCR601_LIMITED) || - (color_space == COLOR_SPACE_YCBCR709_LIMITED)) { - yuv_matrix[3] = dal_fixed31_32_add(ideal[3], grph_bright); - } else { - yuv_matrix[3] = dal_fixed31_32_add( - ideal[3], - dal_fixed31_32_mul( - grph_bright, - dal_fixed31_32_from_fraction(86, 100))); - } -} - -static void calculate_csc_matrix(struct core_color *core_color, - unsigned int sink_index, - enum dc_color_space color_space, - uint16_t *csc_matrix) -{ - struct fixed31_32 fixed_csc_matrix[12]; - switch (color_space) { - case COLOR_SPACE_SRGB: - calculate_rgb_matrix_legacy - (core_color, sink_index, fixed_csc_matrix); - convert_float_matrix_legacy - (csc_matrix, fixed_csc_matrix, 12); - break; - case COLOR_SPACE_SRGB_LIMITED: - calculate_rgb_limited_range_matrix_legacy( - core_color, sink_index, fixed_csc_matrix); - convert_float_matrix_legacy(csc_matrix, fixed_csc_matrix, 12); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR601_LIMITED: - case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_YPBPR601: - case COLOR_SPACE_YPBPR709: - calculate_yuv_matrix(core_color, sink_index, color_space, - fixed_csc_matrix); - convert_float_matrix(csc_matrix, fixed_csc_matrix, 12); - break; - default: - calculate_rgb_matrix_legacy - (core_color, sink_index, fixed_csc_matrix); - convert_float_matrix_legacy - (csc_matrix, fixed_csc_matrix, 12); - break; - } -} - -static struct dc_surface *dc_stream_to_surface_from_pipe_ctx( - struct core_color *core_color, - const struct dc_stream *stream) -{ - int i; - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct dc_surface *out_surface = NULL; - - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) { - out_surface = &core_dc->current_context->res_ctx. - pipe_ctx[i].surface->public; - break; - } - } - return out_surface; -} - -static enum predefined_gamut_type color_space_to_predefined_gamut_types(enum - color_color_space color_space) -{ - switch (color_space) { - case color_space_bt709: - case color_space_xv_ycc_bt709: - return gamut_type_bt709; - case color_space_bt601: - case color_space_xv_ycc_bt601: - return gamut_type_bt601; - case color_space_adobe: - return gamut_type_adobe_rgb; - case color_space_srgb: - case color_space_sc_rgb_ms_ref: - return gamut_type_srgb; - case color_space_bt2020: - return gamut_type_bt2020; - case color_space_dci_p3: /* TODO */ - default: - return gamut_type_unknown; - } -} - -static enum predefined_white_point_type white_point_to_predefined_white_point - (enum color_white_point_type white_point) -{ - switch (white_point) { - case color_white_point_type_5000k_horizon: - return white_point_type_5000k_horizon; - case color_white_point_type_6500k_noon: - return white_point_type_6500k_noon; - case color_white_point_type_7500k_north_sky: - return white_point_type_7500k_north_sky; - case color_white_point_type_9300k: - return white_point_type_9300k; - default: - return white_point_type_unknown; - } -} - -static bool update_color_gamut_data(struct color_gamut_data *input_data, - struct color_gamut_data *output_data) -{ - bool output_custom_cs = false; - bool output_custom_wp = false; - - if (input_data == NULL || output_data == NULL) - return false; - - if (input_data->color_space == color_space_custom_coordinates) { - output_data->color_space = input_data->color_space; - output_data->gamut.redX = input_data->gamut.redX; - output_data->gamut.redY = input_data->gamut.redY; - output_data->gamut.greenX = input_data->gamut.greenX; - output_data->gamut.greenY = input_data->gamut.greenY; - output_data->gamut.blueX = input_data->gamut.blueX; - output_data->gamut.blueY = input_data->gamut.blueY; - } else { - struct gamut_space_coordinates gamut_coord; - enum predefined_gamut_type gamut_type = - color_space_to_predefined_gamut_types - (input_data->color_space); - - /* fall back to original color space if unknown */ - if (gamut_type == gamut_type_unknown) { - if (output_data->color_space == - color_space_custom_coordinates) { - output_custom_cs = true; - } else { - gamut_type = - color_space_to_predefined_gamut_types - (output_data->color_space); - /* fall back to sRGB if both unknown*/ - if (gamut_type == gamut_type_unknown) { - output_data->color_space = - color_space_srgb; - gamut_type = gamut_type_srgb; - } - } - } else { - output_data->color_space = input_data->color_space; - } - - if (!output_custom_cs) { - mod_color_find_predefined_gamut(&gamut_coord, - gamut_type); - output_data->gamut.redX = gamut_coord.redX; - output_data->gamut.redY = gamut_coord.redY; - output_data->gamut.greenX = gamut_coord.greenX; - output_data->gamut.greenY = gamut_coord.greenY; - output_data->gamut.blueX = gamut_coord.blueX; - output_data->gamut.blueY = gamut_coord.blueY; - } - } - - if (input_data->white_point == color_space_custom_coordinates) { - output_data->white_point = input_data->white_point; - output_data->gamut.whiteX = input_data->gamut.whiteX; - output_data->gamut.whiteY = input_data->gamut.whiteY; - } else { - struct white_point_coodinates white_point_coord; - enum predefined_white_point_type white_type = - white_point_to_predefined_white_point - (input_data->white_point); - - /* fall back to original white point if not found */ - if (white_type == white_point_type_unknown) { - if (output_data->white_point == - color_white_point_type_custom_coordinates) { - output_custom_wp = true; - } else { - white_type = - white_point_to_predefined_white_point - (output_data->white_point); - /* fall back to 6500 if both unknown*/ - if (white_type == white_point_type_unknown) { - output_data->white_point = - color_white_point_type_6500k_noon; - white_type = - white_point_type_6500k_noon; - } - } - } else { - output_data->white_point = input_data->white_point; - } - - if (!output_custom_wp) { - mod_color_find_predefined_white_point( - &white_point_coord, white_type); - output_data->gamut.whiteX = white_point_coord.whiteX; - output_data->gamut.whiteY = white_point_coord.whiteY; - } - } - return true; -} - -void initialize_color_state(struct core_color *core_color, int index) -{ - core_color->state[index].user_enable_color_temperature = true; - - core_color->state[index].custom_color_temperature = 6500; - - core_color->state[index].contrast.current = 100; - core_color->state[index].contrast.min = 0; - core_color->state[index].contrast.max = 200; - - core_color->state[index].saturation.current = 100; - core_color->state[index].saturation.min = 0; - core_color->state[index].saturation.max = 200; - - core_color->state[index].brightness.current = 0; - core_color->state[index].brightness.min = -100; - core_color->state[index].brightness.max = 100; - - core_color->state[index].hue.current = 0; - core_color->state[index].hue.min = -30; - core_color->state[index].hue.max = 30; - - core_color->state[index].gamma = NULL; - - core_color->state[index].preferred_quantization_range = - QUANTIZATION_RANGE_FULL; - - core_color->state[index].source_gamut.color_space = - color_space_srgb; - core_color->state[index].source_gamut.white_point = - color_white_point_type_6500k_noon; - core_color->state[index].source_gamut.gamut.blueX = 1500; - core_color->state[index].source_gamut.gamut.blueY = 600; - core_color->state[index].source_gamut.gamut.greenX = 3000; - core_color->state[index].source_gamut.gamut.greenY = 6000; - core_color->state[index].source_gamut.gamut.redX = 6400; - core_color->state[index].source_gamut.gamut.redY = 3300; - core_color->state[index].source_gamut.gamut.whiteX = 3127; - core_color->state[index].source_gamut.gamut.whiteY = 3290; - - core_color->state[index].destination_gamut.color_space = - color_space_srgb; - core_color->state[index].destination_gamut.white_point = - color_white_point_type_6500k_noon; - core_color->state[index].destination_gamut.gamut.blueX = 1500; - core_color->state[index].destination_gamut.gamut.blueY = 600; - core_color->state[index].destination_gamut.gamut.greenX = 3000; - core_color->state[index].destination_gamut.gamut.greenY = 6000; - core_color->state[index].destination_gamut.gamut.redX = 6400; - core_color->state[index].destination_gamut.gamut.redY = 3300; - core_color->state[index].destination_gamut.gamut.whiteX = 3127; - core_color->state[index].destination_gamut.gamut.whiteY = 3290; - - core_color->state[index].input_transfer_function = - transfer_func_srgb; - core_color->state[index].output_transfer_function = - transfer_func_srgb; -} - -struct mod_color *mod_color_create(struct dc *dc) -{ - int i = 0; - struct core_color *core_color = - dm_alloc(sizeof(struct core_color)); - struct core_dc *core_dc = DC_TO_CORE(dc); - struct persistent_data_flag flag; - - if (core_color == NULL) - goto fail_alloc_context; - - core_color->caps = dm_alloc(sizeof(struct sink_caps) * - MOD_COLOR_MAX_CONCURRENT_SINKS); - - if (core_color->caps == NULL) - goto fail_alloc_caps; - - for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) - core_color->caps[i].sink = NULL; - - core_color->state = dm_alloc(sizeof(struct color_state) * - MOD_COLOR_MAX_CONCURRENT_SINKS); - - /*hardcoded to sRGB with 6500 color temperature*/ - for (i = 0; i < MOD_COLOR_MAX_CONCURRENT_SINKS; i++) { - initialize_color_state(core_color, i); - } - - if (core_color->state == NULL) - goto fail_alloc_state; - - core_color->edid_caps = dm_alloc(sizeof(struct color_edid_caps) * - MOD_COLOR_MAX_CONCURRENT_SINKS); - - if (core_color->edid_caps == NULL) - goto fail_alloc_edid_caps; - - core_color->num_sinks = 0; - - if (dc == NULL) - goto fail_construct; - - core_color->dc = dc; - - if (!check_dc_support(dc)) - goto fail_construct; - - /* Create initial module folder in registry for color adjustment */ - flag.save_per_edid = true; - flag.save_per_link = false; - - dm_write_persistent_data(core_dc->ctx, NULL, COLOR_REGISTRY_NAME, NULL, - NULL, 0, &flag); - - return &core_color->public; - -fail_construct: - dm_free(core_color->edid_caps); - -fail_alloc_edid_caps: - dm_free(core_color->state); - -fail_alloc_state: - dm_free(core_color->caps); - -fail_alloc_caps: - dm_free(core_color); - -fail_alloc_context: - return NULL; -} - -void mod_color_destroy(struct mod_color *mod_color) -{ - if (mod_color != NULL) { - int i; - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - dm_free(core_color->edid_caps); - - for (i = 0; i < core_color->num_sinks; i++) - if (core_color->state[i].gamma) - dc_gamma_release(&core_color->state[i].gamma); - - dm_free(core_color->state); - - for (i = 0; i < core_color->num_sinks; i++) - dc_sink_release(core_color->caps[i].sink); - - dm_free(core_color->caps); - - dm_free(core_color); - } -} - -bool mod_color_add_sink(struct mod_color *mod_color, const struct dc_sink *sink, - struct color_edid_caps *edid_caps) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - bool persistent_color_temp_enable; - int persistent_custom_color_temp = 0; - struct color_space_coordinates persistent_source_gamut; - struct color_space_coordinates persistent_destination_gamut; - int persistent_brightness; - int persistent_contrast; - int persistent_hue; - int persistent_saturation; - enum dc_quantization_range persistent_quantization_range; - struct persistent_data_flag flag; - - if (core_color->num_sinks < MOD_COLOR_MAX_CONCURRENT_SINKS) { - dc_sink_retain(sink); - core_color->caps[core_color->num_sinks].sink = sink; - - initialize_color_state(core_color, core_color->num_sinks); - - core_color->edid_caps[core_color->num_sinks].colorimetry_caps = - edid_caps->colorimetry_caps; - core_color->edid_caps[core_color->num_sinks].hdr_caps = - edid_caps->hdr_caps; - - /* get persistent data from registry */ - flag.save_per_edid = true; - flag.save_per_link = false; - - if (dm_read_persistent_data(core_dc->ctx, sink, - COLOR_REGISTRY_NAME, - "enablecolortempadj", - &persistent_color_temp_enable, - sizeof(bool), &flag)) - core_color->state[core_color->num_sinks]. - user_enable_color_temperature = - persistent_color_temp_enable; - - if (dm_read_persistent_data(core_dc->ctx, sink, - COLOR_REGISTRY_NAME, - "customcolortemp", - &persistent_custom_color_temp, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - custom_color_temperature - = persistent_custom_color_temp; - - if (dm_read_persistent_data(core_dc->ctx, sink, - COLOR_REGISTRY_NAME, - "sourcegamut", - &persistent_source_gamut, - sizeof(struct color_space_coordinates), - &flag)) { - memcpy(&core_color->state[core_color->num_sinks]. - source_gamut.gamut, &persistent_source_gamut, - sizeof(struct color_space_coordinates)); - } - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "destgamut", - &persistent_destination_gamut, - sizeof(struct color_space_coordinates), - &flag)) { - memcpy(&core_color->state[core_color->num_sinks]. - destination_gamut.gamut, - &persistent_destination_gamut, - sizeof(struct color_space_coordinates)); - } - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "brightness", - &persistent_brightness, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - brightness.current = persistent_brightness; - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "contrast", - &persistent_contrast, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - contrast.current = persistent_contrast; - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "hue", - &persistent_hue, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - hue.current = persistent_hue; - - if (dm_read_persistent_data(core_dc->ctx, sink, COLOR_REGISTRY_NAME, - "saturation", - &persistent_saturation, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - saturation.current = persistent_saturation; - - if (dm_read_persistent_data(core_dc->ctx, sink, - COLOR_REGISTRY_NAME, - "preferred_quantization_range", - &persistent_quantization_range, - sizeof(int), &flag)) - core_color->state[core_color->num_sinks]. - preferred_quantization_range = - persistent_quantization_range; - - core_color->num_sinks++; - return true; - } - return false; -} - -bool mod_color_remove_sink(struct mod_color *mod_color, - const struct dc_sink *sink) -{ - int i = 0, j = 0; - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - for (i = 0; i < core_color->num_sinks; i++) { - if (core_color->caps[i].sink == sink) { - if (core_color->state[i].gamma) { - dc_gamma_release(&core_color->state[i].gamma); - } - memset(&core_color->state[i], 0, - sizeof(struct color_state)); - memset(&core_color->edid_caps[i], 0, - sizeof(struct color_edid_caps)); - - /* To remove this sink, shift everything after down */ - for (j = i; j < core_color->num_sinks - 1; j++) { - core_color->caps[j].sink = - core_color->caps[j + 1].sink; - - memcpy(&core_color->state[j], - &core_color->state[j + 1], - sizeof(struct color_state)); - - memcpy(&core_color->edid_caps[j], - &core_color->edid_caps[j + 1], - sizeof(struct color_edid_caps)); - } - - memset(&core_color->state[core_color->num_sinks - 1], 0, - sizeof(struct color_state)); - memset(&core_color->edid_caps[core_color->num_sinks - 1], 0, - sizeof(struct color_edid_caps)); - - core_color->num_sinks--; - - dc_sink_release(sink); - - return true; - } - } - - return false; -} - -bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - struct gamut_src_dst_matrix *matrix = - dm_alloc(sizeof(struct gamut_src_dst_matrix)); - - unsigned int stream_index, j; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "sourcegamut", - &core_color->state[sink_index]. - source_gamut.gamut, - sizeof(struct color_space_coordinates), - &flag); - - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "destgamut", - &core_color->state[sink_index]. - destination_gamut.gamut, - sizeof(struct color_space_coordinates), - &flag); - - if (!build_gamut_remap_matrix - (core_color->state[sink_index].source_gamut.gamut, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc)) - goto function_fail; - - if (!build_gamut_remap_matrix - (core_color->state[sink_index]. - destination_gamut.gamut, - matrix->rgbCoeffDst, matrix->whiteCoeffDst)) - goto function_fail; - - struct fixed31_32 gamut_result[12]; - struct fixed31_32 temp_matrix[9]; - - if (!gamut_to_color_matrix( - matrix->rgbCoeffDst, - matrix->whiteCoeffDst, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc, - true, - temp_matrix)) - goto function_fail; - - gamut_result[0] = temp_matrix[0]; - gamut_result[1] = temp_matrix[1]; - gamut_result[2] = temp_matrix[2]; - gamut_result[3] = matrix->whiteCoeffSrc[0]; - gamut_result[4] = temp_matrix[3]; - gamut_result[5] = temp_matrix[4]; - gamut_result[6] = temp_matrix[5]; - gamut_result[7] = matrix->whiteCoeffSrc[1]; - gamut_result[8] = temp_matrix[6]; - gamut_result[9] = temp_matrix[7]; - gamut_result[10] = temp_matrix[8]; - gamut_result[11] = matrix->whiteCoeffSrc[2]; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_stream->public.gamut_remap_matrix.enable_remap = true; - - for (j = 0; j < 12; j++) - core_stream->public. - gamut_remap_matrix.matrix[j] = - gamut_result[j]; - } - - dm_free(matrix); - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; - -function_fail: - dm_free(matrix); - return false; -} - -bool mod_color_adjust_source_gamut(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - update_color_gamut_data(input_gamut_data, - &core_color->state[sink_index].source_gamut); - } - - if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) - return false; - - return true; -} - -bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data, - enum color_transfer_func input_transfer_func) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - update_color_gamut_data(input_gamut_data, - &core_color->state[sink_index].source_gamut); - core_color->state[sink_index].input_transfer_function = - input_transfer_func; - } - - if (!mod_color_update_gamut_info(mod_color, streams, num_streams)) - return false; - - return true; -} - -bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - update_color_gamut_data(input_gamut_data, - &core_color->state[sink_index].destination_gamut); - } - - if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) - return false; - - return true; -} - -bool mod_color_set_white_point(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct white_point_coodinates *white_point) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; - stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - core_color->state[sink_index].source_gamut.gamut.whiteX = - white_point->whiteX; - core_color->state[sink_index].source_gamut.gamut.whiteY = - white_point->whiteY; - } - - if (!mod_color_update_gamut_to_stream(mod_color, streams, num_streams)) - return false; - - return true; -} - - -bool mod_color_set_mastering_info(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - const struct dc_hdr_static_metadata *mastering_info) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - memcpy(&core_color->state[sink_index].mastering_info, - mastering_info, - sizeof(struct dc_hdr_static_metadata)); - } - return true; -} - -bool mod_color_get_mastering_info(struct mod_color *mod_color, - const struct dc_sink *sink, - struct dc_hdr_static_metadata *mastering_info) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - memcpy(mastering_info, &core_color->state[sink_index].mastering_info, - sizeof(struct dc_hdr_static_metadata)); - - return true; -} - -bool mod_color_set_user_enable(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - bool user_enable) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - core_color->state[sink_index].user_enable_color_temperature - = user_enable; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "enablecolortempadj", - &user_enable, - sizeof(bool), - &flag); - } - return true; -} - -bool mod_color_get_user_enable(struct mod_color *mod_color, - const struct dc_sink *sink, - bool *user_enable) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *user_enable = core_color->state[sink_index]. - user_enable_color_temperature; - - return true; -} - -bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, - const struct dc_sink *sink, - int *color_temperature) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_temperature = core_color->state[sink_index]. - custom_color_temperature; - - return true; -} - -bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int color_temperature) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - core_color->state[sink_index].custom_color_temperature - = color_temperature; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "customcolortemp", - &color_temperature, - sizeof(int), - &flag); - } - return true; -} - -bool mod_color_get_color_saturation(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_saturation) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_saturation = core_color->state[sink_index].saturation; - - return true; -} - -bool mod_color_get_color_contrast(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_contrast) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_contrast = core_color->state[sink_index].contrast; - - return true; -} - -bool mod_color_get_color_brightness(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_brightness) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_brightness = core_color->state[sink_index].brightness; - - return true; -} - -bool mod_color_get_color_hue(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_hue) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *color_hue = core_color->state[sink_index].hue; - - return true; -} - -bool mod_color_get_source_gamut(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_space_coordinates *source_gamut) -{ - struct core_color *core_color = - MOD_COLOR_TO_CORE(mod_color); - - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - *source_gamut = core_color->state[sink_index].source_gamut.gamut; - - return true; -} - -bool mod_color_notify_mode_change(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - - struct gamut_src_dst_matrix *matrix = - dm_alloc(sizeof(struct gamut_src_dst_matrix)); - - unsigned int stream_index, j; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - if (!build_gamut_remap_matrix - (core_color->state[sink_index].source_gamut.gamut, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc)) - goto function_fail; - - if (!build_gamut_remap_matrix - (core_color->state[sink_index]. - destination_gamut.gamut, - matrix->rgbCoeffDst, matrix->whiteCoeffDst)) - goto function_fail; - - struct fixed31_32 gamut_result[12]; - struct fixed31_32 temp_matrix[9]; - - if (!gamut_to_color_matrix( - matrix->rgbCoeffDst, - matrix->whiteCoeffDst, - matrix->rgbCoeffSrc, - matrix->whiteCoeffSrc, - true, - temp_matrix)) - goto function_fail; - - gamut_result[0] = temp_matrix[0]; - gamut_result[1] = temp_matrix[1]; - gamut_result[2] = temp_matrix[2]; - gamut_result[3] = matrix->whiteCoeffSrc[0]; - gamut_result[4] = temp_matrix[3]; - gamut_result[5] = temp_matrix[4]; - gamut_result[6] = temp_matrix[5]; - gamut_result[7] = matrix->whiteCoeffSrc[1]; - gamut_result[8] = temp_matrix[6]; - gamut_result[9] = temp_matrix[7]; - gamut_result[10] = temp_matrix[8]; - gamut_result[11] = matrix->whiteCoeffSrc[2]; - - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_stream->public.gamut_remap_matrix.enable_remap = true; - - for (j = 0; j < 12; j++) - core_stream->public. - gamut_remap_matrix.matrix[j] = - gamut_result[j]; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - } - - dm_free(matrix); - - return true; - -function_fail: - dm_free(matrix); - return false; -} - -bool mod_color_set_brightness(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int brightness_value) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_color->state[sink_index].brightness.current = - brightness_value; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "brightness", - &brightness_value, - sizeof(int), - &flag); - } - - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; -} - -bool mod_color_set_contrast(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int contrast_value) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_color->state[sink_index].contrast.current = - contrast_value; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "contrast", - &contrast_value, - sizeof(int), - &flag); - } - - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; -} - -bool mod_color_set_hue(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int hue_value) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_color->state[sink_index].hue.current = hue_value; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "hue", - &hue_value, - sizeof(int), - &flag); - } - - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; -} - -bool mod_color_set_saturation(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int saturation_value) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct core_stream *core_stream = - DC_STREAM_TO_CORE - (streams[stream_index]); - - core_color->state[sink_index].saturation.current = - saturation_value; - - calculate_csc_matrix(core_color, sink_index, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); - - core_stream->public.csc_color_matrix.enable_adjustment = true; - - /* Write persistent data in registry*/ - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - streams[stream_index]->sink, - COLOR_REGISTRY_NAME, - "saturation", - &saturation_value, - sizeof(int), - &flag); - } - - core_color->dc->stream_funcs.set_gamut_remap - (core_color->dc, streams, num_streams); - - return true; -} - -bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct dc_gamma *gamma) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index; - int sink_index; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - - struct dc_surface *surface = - dc_stream_to_surface_from_pipe_ctx(core_color, - streams[stream_index]); - - if (surface != NULL) { - struct dc_transfer_func *input_tf = - dc_create_transfer_func(); - struct dc_surface_update updates = {0}; - - if (input_tf != NULL) { - input_tf->type = TF_TYPE_PREDEFINED; - input_tf->tf = TRANSFER_FUNCTION_SRGB; - } - - if (core_color->state[sink_index].gamma != gamma) { - if (core_color->state[sink_index].gamma) - dc_gamma_release( - &core_color->state[sink_index].gamma); - - dc_gamma_retain(gamma); - core_color->state[sink_index].gamma = gamma; - } - - updates.surface = surface; - updates.gamma = gamma; - updates.in_transfer_func = input_tf; - dc_update_surfaces_for_target(core_color->dc, &updates, - 1, NULL); - - if (input_tf != NULL) - dc_transfer_func_release(input_tf); - } - } - - return true; -} - -bool mod_color_persist_user_preferred_quantization_range( - struct mod_color *mod_color, - const struct dc_sink *sink, - enum dc_quantization_range quantization_range) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - struct core_dc *core_dc = DC_TO_CORE(core_color->dc); - struct persistent_data_flag flag; - int sink_index; - - sink_index = sink_index_from_sink(core_color, sink); - if (sink_index == -1) - return false; - - if (core_color->state[sink_index]. - preferred_quantization_range != quantization_range) { - core_color->state[sink_index].preferred_quantization_range = - quantization_range; - flag.save_per_edid = true; - flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, - sink, - COLOR_REGISTRY_NAME, - "quantization_range", - &quantization_range, - sizeof(int), - &flag); - } - - return true; -} - -bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, - const struct dc_sink *sink, - const struct dc_crtc_timing *timing, - enum dc_quantization_range *quantization_range) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - int sink_index = sink_index_from_sink(core_color, sink); - - if (sink_index == -1) - return false; - - enum dc_quantization_range user_preferred_quantization_range = - core_color->state[sink_index]. - preferred_quantization_range; - bool rgb_full_range_supported = - mod_color_is_rgb_full_range_supported_for_timing( - sink, timing); - bool rgb_limited_range_supported = - mod_color_is_rgb_limited_range_supported_for_timing( - sink, timing); - - if (rgb_full_range_supported && rgb_limited_range_supported) - *quantization_range = user_preferred_quantization_range; - else if (rgb_full_range_supported && !rgb_limited_range_supported) - *quantization_range = QUANTIZATION_RANGE_FULL; - else if (!rgb_full_range_supported && rgb_limited_range_supported) - *quantization_range = QUANTIZATION_RANGE_LIMITED; - else - *quantization_range = QUANTIZATION_RANGE_UNKNOWN; - - return true; -} - -bool mod_color_is_rgb_full_range_supported_for_timing( - const struct dc_sink *sink, - const struct dc_crtc_timing *timing) -{ - bool result = false; - - if (!sink || !timing) - return result; - - if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) - if (timing->vic || timing->hdmi_vic) - if (timing->h_addressable == 640 && - timing->v_addressable == 480 && - (timing->pix_clk_khz == 25200 || - timing->pix_clk_khz == 25170 || - timing->pix_clk_khz == 25175)) - result = true; - else - /* don't support full range rgb */ - /* for HDMI CEA861 timings except VGA mode */ - result = false; - else - result = true; - else - result = true; - - return result; -} - -bool mod_color_is_rgb_limited_range_supported_for_timing( - const struct dc_sink *sink, - const struct dc_crtc_timing *timing) -{ - bool result = false; - - if (!sink || !timing) - return result; - - if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) - if (timing->vic || timing->hdmi_vic) - if (timing->h_addressable == 640 && - timing->v_addressable == 480 && - (timing->pix_clk_khz == 25200 || - timing->pix_clk_khz == 25170 || - timing->pix_clk_khz == 25175)) - /* don't support rgb limited for */ - /* HDMI CEA VGA mode */ - result = false; - else - /* support rgb limited for non VGA CEA timing */ - result = true; - else - /* support rgb limited for non CEA HDMI timing */ - result = true; - else - /* don't support rgb limited for non HDMI signal */ - result = false; - - return result; -} - -bool mod_color_set_regamma(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams) -{ - /*TODO*/ - return true; -} - -bool mod_color_set_degamma(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - enum color_transfer_func transfer_function) -{ - /*TODO*/ - return true; -} - -bool mod_color_update_gamut_info(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams) -{ - struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color); - unsigned int stream_index; - int sink_index; - bool should_defer = false; - bool is_hdr = false; - enum color_color_space source_color_space; - enum color_transfer_func input_transfer_function; - struct color_gamut_data new_gamut_source; - struct color_gamut_data new_gamut_destination; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - sink_index = sink_index_from_sink(core_color, - streams[stream_index]->sink); - if (sink_index == -1) - continue; - source_color_space = - core_color->state[sink_index].source_gamut.color_space; - input_transfer_function = - core_color->state[sink_index].input_transfer_function; - new_gamut_source.color_space = source_color_space; - new_gamut_destination.color_space = - core_color->state[sink_index]. - destination_gamut.color_space; - - struct dc_surface *surface = - dc_stream_to_surface_from_pipe_ctx(core_color, - streams[stream_index]); - if (surface == NULL) - return false; - - if (surface->format == SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 || - surface->format == - SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010) { - - if (input_transfer_function == - transfer_func_pq2084 || - input_transfer_function == - transfer_func_pq2084_interim) { - /* For PQ and PQ interim, we bypass degamma+ - * remap+regamma, application needs to also - * handle gamut remapping - */ - /* TODO */ - is_hdr = true; - } else if (input_transfer_function == - transfer_func_linear_0_1 || - input_transfer_function == - transfer_func_linear_0_125) { - /* TF not supported in current surface format, - * but may be deferred to a later flip - */ - should_defer = true; - } else { - new_gamut_destination.color_space = - color_space_srgb; - } - } else if (surface->format == - SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || - surface->format == - SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F || - surface->format == - SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) { - if (input_transfer_function == - transfer_func_linear_0_125) { - /* Regamma PQ for HDR supported displays and - * 0-125 source - */ - if ((core_color->edid_caps[sink_index]. - hdr_caps) & smpte_st2084) - is_hdr = true; - - /* override for BT.2020 whenever PQ */ - if (core_color->state[sink_index]. - destination_gamut.color_space != - color_space_bt2020) { - if (streams[stream_index]->timing. - pixel_encoding == - PIXEL_ENCODING_RGB) { - if ((core_color-> - edid_caps[sink_index]. - colorimetry_caps) & bt_2020_rgb) - new_gamut_destination. - color_space = - color_space_bt2020; - } else { - if ((core_color-> - edid_caps[sink_index]. - colorimetry_caps) & bt_2020_ycc) - new_gamut_destination. - color_space = - color_space_bt2020; - } - } - } else if (input_transfer_function == - transfer_func_linear_0_1) { - new_gamut_destination.color_space = - color_space_srgb; - } else { - /* TF not supported in current surface format, - * but may be deferred to a later flip - */ - should_defer = true; - } - } - - /* 0. ---- CHECK DEFERRED ---- */ - if (should_defer) - return true; - - /* 1. ---- SET GAMUT SOURCE ---- */ - new_gamut_source.white_point = core_color->state[sink_index]. - source_gamut.white_point; - update_color_gamut_data(&new_gamut_source, - &core_color->state[sink_index].source_gamut); - - /* 2. ---- SET GAMUT DESTINATION ---- */ - new_gamut_destination.white_point = - core_color->state[sink_index]. - destination_gamut.white_point; - update_color_gamut_data(&new_gamut_destination, - &core_color->state[sink_index].destination_gamut); - - /* 3. ---- SET DEGAMMA ---- */ - struct dc_transfer_func *input_tf = NULL; - - input_tf = dc_create_transfer_func(); - - if (input_tf != NULL) { - input_tf->type = TF_TYPE_PREDEFINED; - - switch (input_transfer_function) { - case transfer_func_srgb: - input_tf->tf = TRANSFER_FUNCTION_SRGB; - break; - case transfer_func_linear_0_1: - case transfer_func_linear_0_125: - input_tf->tf = TRANSFER_FUNCTION_LINEAR; - break; - default: - dc_transfer_func_release(input_tf); - input_tf = NULL; - break; - } - } - - /* 4. ---- SET REGAMMA ---- */ - struct dc_transfer_func *output_tf = NULL; - - output_tf = dc_create_transfer_func(); - - if (output_tf != NULL) { - output_tf->type = TF_TYPE_PREDEFINED; - if (is_hdr) - output_tf->tf = TRANSFER_FUNCTION_PQ; - else - output_tf->tf = TRANSFER_FUNCTION_SRGB; - } - /* 5. ---- POPULATE HDR METADATA ---- */ - core_color->state[sink_index].mastering_info.is_hdr = is_hdr; - - /* 6. ---- TODO: UPDATE INFOPACKETS ---- */ - - if (!mod_color_update_gamut_to_stream( - mod_color, streams, num_streams)) - return false; - - struct dc_surface_update updates[4] = {0}; - - updates[0].surface = surface; - updates[0].gamma = core_color->state[sink_index].gamma; - updates[0].in_transfer_func = input_tf; - updates[0].out_transfer_func = output_tf; - updates[0].hdr_static_metadata = - &core_color->state[sink_index].mastering_info; - - dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL); - - if (input_tf != NULL) - dc_transfer_func_release(input_tf); - - if (output_tf != NULL) - dc_transfer_func_release(output_tf); - } - return true; -} diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.c b/drivers/gpu/drm/amd/display/modules/color/color_helper.c deleted file mode 100644 index ff6779cdd623..000000000000 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "dc.h" -#include "mod_color.h" -#include "color_helper.h" - -const struct gamut_space_entry predefined_gamuts[] = { - /* x_red y_red x_gr y_gr x_blue y_blue a0 a1 a2 a3 gamma */ - [gamut_type_bt709] = {6400, 3300, 3000, 6000, 1500, 600, 180000, 4500, 99, 99, 2200}, - [gamut_type_bt601] = {6400, 3300, 2900, 6000, 1500, 600, 180000, 4500, 99, 99, 2200}, - [gamut_type_adobe_rgb] = {6400, 3300, 2100, 7100, 1500, 600, 180000, 4500, 99, 99, 2200}, - [gamut_type_srgb] = {6400, 3300, 3000, 6000, 1500, 600, 31308, 12920, 55, 55, 2400}, - [gamut_type_bt2020] = {7080, 2920, 1700, 7970, 1310, 460, 180000, 4500, 99, 99, 2200} -}; - -const struct white_point_coodinates_entry predefined_white_points[] = { - [white_point_type_5000k_horizon] = {5000, 3473, 3561}, - [white_point_type_6500k_noon] = {6500, 3127, 3290}, - [white_point_type_7500k_north_sky] = {7500, 3022, 3129}, - [white_point_type_9300k] = {9300, 2866, 2950} -}; - -const unsigned int white_point_entries = 91; - -const struct white_point_coodinates_entry white_point_temps[] = { - /*001*/{1000, 6499, 3474}, - /*002*/{1100, 6361, 3594}, - /*003*/{1200, 6226, 3703}, - /*004*/{1300, 6095, 3801}, - /*005*/{1400, 5966, 3887}, - /*006*/{1500, 5841, 3962}, - /*007*/{1600, 5720, 4025}, - /*008*/{1700, 5601, 4076}, - /*009*/{1800, 5486, 4118}, - /*010*/{1900, 5375, 4150}, - /*011*/{2000, 5267, 4173}, - /*012*/{2100, 5162, 4188}, - /*013*/{2200, 5062, 4196}, - /*014*/{2300, 4965, 4198}, - /*015*/{2400, 4872, 4194}, - /*016*/{2500, 4782, 4186}, - /*017*/{2600, 4696, 4173}, - /*018*/{2700, 4614, 4158}, - /*019*/{2800, 4535, 4139}, - /*020*/{2900, 4460, 4118}, - /*021*/{3000, 4388, 4095}, - /*022*/{3100, 4320, 4070}, - /*023*/{3200, 4254, 4044}, - /*024*/{3300, 4192, 4018}, - /*025*/{3400, 4132, 3990}, - /*026*/{3500, 4075, 3962}, - /*027*/{3600, 4021, 3934}, - /*028*/{3700, 3969, 3905}, - /*029*/{3800, 3919, 3877}, - /*030*/{3900, 3872, 3849}, - /*031*/{4000, 3827, 3820}, - /*032*/{4100, 3784, 3793}, - /*033*/{4200, 3743, 3765}, - /*034*/{4300, 3704, 3738}, - /*035*/{4400, 3666, 3711}, - /*036*/{4500, 3631, 3685}, - /*037*/{4600, 3596, 3659}, - /*038*/{4700, 3563, 3634}, - /*039*/{4800, 3532, 3609}, - /*040*/{4900, 3502, 3585}, - /*041*/{5000, 3473, 3561}, - /*042*/{5100, 3446, 3538}, - /*043*/{5200, 3419, 3516}, - /*044*/{5300, 3394, 3494}, - /*045*/{5400, 3369, 3472}, - /*046*/{5500, 3346, 3451}, - /*047*/{5600, 3323, 3431}, - /*048*/{5700, 3302, 3411}, - /*049*/{5800, 3281, 3392}, - /*050*/{5900, 3261, 3373}, - /*051*/{6000, 3242, 3355}, - /*052*/{6100, 3223, 3337}, - /*053*/{6200, 3205, 3319}, - /*054*/{6300, 3188, 3302}, - /*055*/{6400, 3161, 3296}, - /*056*/{6500, 3127, 3290}, /* This is the real white point sRGB */ - /*057*/{6600, 3126, 3264}, - /*058*/{6700, 3125, 3238}, - /*059*/{6800, 3110, 3224}, - /*060*/{6900, 3097, 3209}, - /*061*/{7000, 3083, 3195}, - /*062*/{7100, 3070, 3181}, - /*063*/{7200, 3058, 3168}, - /*064*/{7300, 3045, 3154}, - /*065*/{7400, 3034, 3142}, - /*066*/{7500, 3022, 3129}, - /*067*/{7600, 3011, 3117}, - /*068*/{7700, 3000, 3105}, - /*069*/{7800, 2990, 3094}, - /*070*/{7900, 2980, 3082}, - /*071*/{8000, 2970, 3071}, - /*072*/{8100, 2961, 3061}, - /*073*/{8200, 2952, 3050}, - /*074*/{8300, 2943, 3040}, - /*075*/{8400, 2934, 3030}, - /*076*/{8500, 2926, 3020}, - /*077*/{8600, 2917, 3011}, - /*078*/{8700, 2910, 3001}, - /*079*/{8800, 2902, 2992}, - /*080*/{8900, 2894, 2983}, - /*081*/{9000, 2887, 2975}, - /*082*/{9100, 2880, 2966}, - /*083*/{9200, 2873, 2958}, - /*084*/{9300, 2866, 2950}, - /*085*/{9400, 2860, 2942}, - /*086*/{9500, 2853, 2934}, - /*087*/{9600, 2847, 2927}, - /*088*/{9700, 2841, 2919}, - /*089*/{9800, 2835, 2912}, - /*090*/{9900, 2829, 2905}, - /*091*/{10000, 2824, 2898} -}; - -bool mod_color_find_predefined_gamut( - struct gamut_space_coordinates *out_gamut, - enum predefined_gamut_type type) -{ - out_gamut->redX = predefined_gamuts[type].redX; - out_gamut->redY = predefined_gamuts[type].redY; - out_gamut->greenX = predefined_gamuts[type].greenX; - out_gamut->greenY = predefined_gamuts[type].greenY; - out_gamut->blueX = predefined_gamuts[type].blueX; - out_gamut->blueY = predefined_gamuts[type].blueY; - - return true; -} - -bool mod_color_find_predefined_white_point( - struct white_point_coodinates *out_white_point, - enum predefined_white_point_type type) -{ - out_white_point->whiteX = predefined_white_points[type].whiteX; - out_white_point->whiteY = predefined_white_points[type].whiteY; - - return true; -} - -bool mod_color_find_white_point_from_temperature( - struct white_point_coodinates *out_white_point, - unsigned int temperature) -{ - int i; - unsigned int found = false; - struct white_point_coodinates_entry temp_white_point = - white_point_temps[55]; - - if (temperature < 1000 || temperature > 10000) - return false; - - for (i = 0; i < white_point_entries; i++) { - if (temperature == white_point_temps[i].temperature) { - temp_white_point = white_point_temps[i]; - found = true; - break; - } - } - - out_white_point->whiteX = temp_white_point.whiteX; - out_white_point->whiteY = temp_white_point.whiteY; - - return found; -} - -bool mod_color_find_temperature_from_white_point( - struct white_point_coodinates *in_white_point, - unsigned int *out_temperature) -{ - unsigned int i; - *out_temperature = 6500; - - for (i = 0; i < white_point_entries; i++) { - if (in_white_point->whiteX == white_point_temps[i].whiteX && - in_white_point->whiteY == white_point_temps[i].whiteY) { - *out_temperature = white_point_temps[i].temperature; - return true; - } - } - - return false; -} - diff --git a/drivers/gpu/drm/amd/display/modules/color/color_helper.h b/drivers/gpu/drm/amd/display/modules/color/color_helper.h deleted file mode 100644 index 76575c1dc043..000000000000 --- a/drivers/gpu/drm/amd/display/modules/color/color_helper.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef COLOR_MOD_COLOR_HELPER_H_ -#define COLOR_MOD_COLOR_HELPER_H_ - -enum predefined_gamut_type { - gamut_type_bt709, - gamut_type_bt601, - gamut_type_adobe_rgb, - gamut_type_srgb, - gamut_type_bt2020, - gamut_type_unknown, -}; - -enum predefined_white_point_type { - white_point_type_5000k_horizon, - white_point_type_6500k_noon, - white_point_type_7500k_north_sky, - white_point_type_9300k, - white_point_type_unknown, -}; - -bool mod_color_find_predefined_gamut( - struct gamut_space_coordinates *out_gamut, - enum predefined_gamut_type type); - -bool mod_color_find_predefined_white_point( - struct white_point_coodinates *out_white_point, - enum predefined_white_point_type type); - -bool mod_color_find_white_point_from_temperature( - struct white_point_coodinates *out_white_point, - unsigned int temperature); - -bool mod_color_find_temperature_from_white_point( - struct white_point_coodinates *in_white_point, - unsigned int *out_temperature); - -#endif /* COLOR_MOD_COLOR_HELPER_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h deleted file mode 100644 index 70349a88916c..000000000000 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - - -#ifndef MOD_COLOR_H_ -#define MOD_COLOR_H_ - -#include "dm_services.h" -#include "color_helper.h" - -enum color_transfer_func { - transfer_func_unknown, - transfer_func_srgb, - transfer_func_bt709, - transfer_func_pq2084, - transfer_func_pq2084_interim, - transfer_func_linear_0_1, - transfer_func_linear_0_125, - transfer_func_dolbyvision, - transfer_func_gamma_22, - transfer_func_gamma_26 -}; - -enum color_color_space { - color_space_unsupported, - color_space_srgb, - color_space_bt601, - color_space_bt709, - color_space_xv_ycc_bt601, - color_space_xv_ycc_bt709, - color_space_xr_rgb, - color_space_bt2020, - color_space_adobe, - color_space_dci_p3, - color_space_sc_rgb_ms_ref, - color_space_display_native, - color_space_app_ctrl, - color_space_dolby_vision, - color_space_custom_coordinates -}; - -enum color_white_point_type { - color_white_point_type_unknown, - color_white_point_type_5000k_horizon, - color_white_point_type_6500k_noon, - color_white_point_type_7500k_north_sky, - color_white_point_type_9300k, - color_white_point_type_custom_coordinates -}; - -enum colorimetry_support_flag { - xv_ycc_bt601 = 0x01, - xv_ycc_bt709 = 0x02, - s_ycc_601 = 0x04, - adobe_ycc_601 = 0x08, - adobe_rgb = 0x10, - bt_2020_c_ycc = 0x20, - bt_2020_ycc = 0x40, - bt_2020_rgb = 0x80 -}; - -enum hdr_tf_support_flag { - traditional_gamma_sdr = 0x01, - traditional_gamma_hdr = 0x02, - smpte_st2084 = 0x04 -}; - -struct mod_color { - int dummy; -}; - -struct color_space_coordinates { - unsigned int redX; - unsigned int redY; - unsigned int greenX; - unsigned int greenY; - unsigned int blueX; - unsigned int blueY; - unsigned int whiteX; - unsigned int whiteY; -}; - -struct gamut_space_coordinates { - unsigned int redX; - unsigned int redY; - unsigned int greenX; - unsigned int greenY; - unsigned int blueX; - unsigned int blueY; -}; - -struct gamut_space_entry { - unsigned int redX; - unsigned int redY; - unsigned int greenX; - unsigned int greenY; - unsigned int blueX; - unsigned int blueY; - - int a0; - int a1; - int a2; - int a3; - int gamma; -}; - -struct white_point_coodinates { - unsigned int whiteX; - unsigned int whiteY; -}; - -struct white_point_coodinates_entry { - unsigned int temperature; - unsigned int whiteX; - unsigned int whiteY; -}; - -struct color_range { - int current; - int min; - int max; -}; - -struct color_gamut_data { - enum color_color_space color_space; - enum color_white_point_type white_point; - struct color_space_coordinates gamut; -}; - -struct color_edid_caps { - unsigned int colorimetry_caps; - unsigned int hdr_caps; -}; - -struct mod_color *mod_color_create(struct dc *dc); - -void mod_color_destroy(struct mod_color *mod_color); - -bool mod_color_add_sink(struct mod_color *mod_color, - const struct dc_sink *sink, struct color_edid_caps *edid_caps); - -bool mod_color_remove_sink(struct mod_color *mod_color, - const struct dc_sink *sink); - -bool mod_color_update_gamut_to_stream(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams); - -bool mod_color_set_white_point(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct white_point_coodinates *white_point); - -bool mod_color_adjust_source_gamut(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data); - -bool mod_color_adjust_destination_gamut(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data); - -bool mod_color_adjust_source_gamut_and_tf(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct color_gamut_data *input_gamut_data, - enum color_transfer_func input_transfer_func); - -bool mod_color_get_user_enable(struct mod_color *mod_color, - const struct dc_sink *sink, - bool *user_enable); - -bool mod_color_set_mastering_info(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - const struct dc_hdr_static_metadata *mastering_info); - -bool mod_color_get_mastering_info(struct mod_color *mod_color, - const struct dc_sink *sink, - struct dc_hdr_static_metadata *mastering_info); - -bool mod_color_set_user_enable(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - bool user_enable); - -bool mod_color_get_custom_color_temperature(struct mod_color *mod_color, - const struct dc_sink *sink, - int *color_temperature); - -bool mod_color_set_custom_color_temperature(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int color_temperature); - -bool mod_color_get_color_saturation(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_saturation); - -bool mod_color_get_color_contrast(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_contrast); - -bool mod_color_get_color_brightness(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_brightness); - -bool mod_color_get_color_hue(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_range *color_hue); - -bool mod_color_get_source_gamut(struct mod_color *mod_color, - const struct dc_sink *sink, - struct color_space_coordinates *source_gamut); - -bool mod_color_notify_mode_change(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams); - -bool mod_color_set_brightness(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int brightness_value); - -bool mod_color_set_contrast(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int contrast_value); - -bool mod_color_set_hue(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int hue_value); - -bool mod_color_set_saturation(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - int saturation_value); - -bool mod_color_set_input_gamma_correction(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - struct dc_gamma *gamma); - -bool mod_color_persist_user_preferred_quantization_range( - struct mod_color *mod_color, - const struct dc_sink *sink, - enum dc_quantization_range quantization_range); - -bool mod_color_get_preferred_quantization_range(struct mod_color *mod_color, - const struct dc_sink *sink, - const struct dc_crtc_timing *timing, - enum dc_quantization_range *quantization_range); - -bool mod_color_is_rgb_full_range_supported_for_timing( - const struct dc_sink *sink, - const struct dc_crtc_timing *timing); - -bool mod_color_is_rgb_limited_range_supported_for_timing( - const struct dc_sink *sink, - const struct dc_crtc_timing *timing); - -bool mod_color_set_regamma(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams); - -bool mod_color_set_degamma(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams, - enum color_transfer_func transfer_function); - -bool mod_color_update_gamut_info(struct mod_color *mod_color, - const struct dc_stream **streams, int num_streams); - -#endif /* MOD_COLOR_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h deleted file mode 100644 index a204e8d6cd23..000000000000 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef MODULES_INC_MOD_POWER_H_ -#define MODULES_INC_MOD_POWER_H_ - -#include "dm_services.h" - -struct mod_power { - int dummy; -}; - -/* VariBright related commands */ -enum varibright_command { - VariBright_Cmd__SetVBLevel = 0, - VariBright_Cmd__UserEnable, - VariBright_Cmd__PreDisplayConfigChange, - VariBright_Cmd__PostDisplayConfigChange, - VariBright_Cmd__SuspendABM, - VariBright_Cmd__ResumeABM, - - VariBright_Cmd__Unknown, -}; - -/* VariBright settings structure */ -struct varibright_info { - enum varibright_command cmd; - - unsigned int level; - bool enable; - bool activate; -}; - -enum dmcu_block_psr_reason { - /* This is a bitfield mask */ - dmcu_block_psr_reason_invalid = 0x0, - dmcu_block_psr_reason_vsync_int = 0x1, - dmcu_block_psr_reason_shared_primary = 0x2, - dmcu_block_psr_reason_unsupported_link_rate = 0x4 -}; - -struct mod_power *mod_power_create(struct dc *dc); - -void mod_power_destroy(struct mod_power *mod_power); - -bool mod_power_add_sink(struct mod_power *mod_power, - const struct dc_sink *sink); - -bool mod_power_remove_sink(struct mod_power *mod_power, - const struct dc_sink *sink); - -bool mod_power_set_backlight(struct mod_power *mod_power, - const struct dc_stream **streams, int num_streams, - unsigned int backlight_8bit); - -bool mod_power_get_backlight(struct mod_power *mod_power, - const struct dc_sink *sink, - unsigned int *backlight_8bit); - -void mod_power_initialize_backlight_caps - (struct mod_power *mod_power); - -unsigned int mod_power_backlight_level_percentage_to_signal - (struct mod_power *mod_power, unsigned int percentage); - -unsigned int mod_power_backlight_level_signal_to_percentage - (struct mod_power *mod_power, unsigned int signalLevel8bit); - -bool mod_power_get_panel_backlight_boundaries - (struct mod_power *mod_power, - unsigned int *min_backlight, - unsigned int *max_backlight, - unsigned int *output_ac_level_percentage, - unsigned int *output_dc_level_percentage); - -bool mod_power_set_smooth_brightness(struct mod_power *mod_power, - const struct dc_sink *sink, bool enable_brightness); - -bool mod_power_notify_mode_change(struct mod_power *mod_power, - const struct dc_stream *stream); - -bool mod_power_varibright_control(struct mod_power *mod_power, - struct varibright_info *input_varibright_info); - -bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason); - -bool mod_power_set_psr_enable(struct mod_power *mod_power, - bool psr_enable); - -#endif /* MODULES_INC_MOD_POWER_H_ */ diff --git a/drivers/gpu/drm/amd/display/modules/power/power.c b/drivers/gpu/drm/amd/display/modules/power/power.c deleted file mode 100644 index ea07e847da0a..000000000000 --- a/drivers/gpu/drm/amd/display/modules/power/power.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "mod_power.h" -#include "dm_services.h" -#include "dc.h" -#include "core_types.h" -#include "core_dc.h" - -#define MOD_POWER_MAX_CONCURRENT_SINKS 32 -#define SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS 500 - -struct sink_caps { - const struct dc_sink *sink; -}; - -struct backlight_state { - unsigned int backlight; - unsigned int frame_ramp; - bool smooth_brightness_enabled; -}; - -struct core_power { - struct mod_power public; - struct dc *dc; - int num_sinks; - struct sink_caps *caps; - struct backlight_state *state; -}; - -union dmcu_abm_set_bl_params { - struct { - unsigned int gradual_change : 1; /* [0:0] */ - unsigned int reserved : 15; /* [15:1] */ - unsigned int frame_ramp : 16; /* [31:16] */ - } bits; - unsigned int u32All; -}; - -/* Backlight cached properties */ -static unsigned int backlight_8bit_lut_array[101]; -static unsigned int ac_level_percentage; -static unsigned int dc_level_percentage; -static bool backlight_caps_valid; -/* we use lazy initialization of backlight capabilities cache */ -static bool backlight_caps_initialized; -/* AC/DC levels initialized later in separate context */ -static bool backlight_def_levels_valid; - -/* ABM cached properties */ -static unsigned int abm_level; -static bool abm_user_enable; -static bool abm_active; - -/*PSR cached properties*/ -static unsigned int block_psr; - -/* Defines default backlight curve F(x) = A(x*x) + Bx + C. - * - * Backlight curve should always satisfy F(0) = min, F(100) = max, - * so polynom coefficients are: - * A is 0.0255 - B/100 - min/10000 - (255-max)/10000 = (max - min)/10000 - B/100 - * B is adjustable factor to modify the curve. - * Bigger B results in less concave curve. B range is [0..(max-min)/100] - * C is backlight minimum - */ -static const unsigned int backlight_curve_coeff_a_factor = 10000; -static const unsigned int backlight_curve_coeff_b = 100; -static const unsigned int backlight_curve_coeff_b_factor = 100; - -/* Minimum and maximum backlight input signal levels */ -static const unsigned int default_min_backlight = 12; -static const unsigned int default_max_backlight = 255; - -/* Other backlight constants */ -static const unsigned int absolute_backlight_max = 255; - -#define MOD_POWER_TO_CORE(mod_power)\ - container_of(mod_power, struct core_power, public) - -static bool check_dc_support(const struct dc *dc) -{ - if (dc->stream_funcs.set_backlight == NULL) - return false; - - return true; -} - -/* Given a specific dc_sink* this function finds its equivalent - * on the dc_sink array and returns the corresponding index - */ -static unsigned int sink_index_from_sink(struct core_power *core_power, - const struct dc_sink *sink) -{ - unsigned int index = 0; - - for (index = 0; index < core_power->num_sinks; index++) - if (core_power->caps[index].sink == sink) - return index; - - /* Could not find sink requested */ - ASSERT(false); - return index; -} - -static unsigned int convertBL8to17(unsigned int backlight_8bit) -{ - unsigned int temp_ulong = backlight_8bit * 0x10101; - unsigned char temp_uchar = - (unsigned char)(((temp_ulong & 0x80) >> 7) & 1); - - temp_ulong = (temp_ulong >> 8) + temp_uchar; - - return temp_ulong; -} - -static uint16_t convertBL8to16(unsigned int backlight_8bit) -{ - return (uint16_t)((backlight_8bit * 0x10101) >> 8); -} - -/*This is used when OS wants to retrieve the current BL. - * We return the 8bit value to OS. - */ -static unsigned int convertBL17to8(unsigned int backlight_17bit) -{ - if (backlight_17bit & 0x10000) - return default_max_backlight; - else - return (backlight_17bit >> 8); -} - -struct mod_power *mod_power_create(struct dc *dc) -{ - struct core_power *core_power = - dm_alloc(sizeof(struct core_power)); - - struct core_dc *core_dc = DC_TO_CORE(dc); - - int i = 0; - - if (core_power == NULL) - goto fail_alloc_context; - - core_power->caps = dm_alloc(sizeof(struct sink_caps) * - MOD_POWER_MAX_CONCURRENT_SINKS); - - if (core_power->caps == NULL) - goto fail_alloc_caps; - - for (i = 0; i < MOD_POWER_MAX_CONCURRENT_SINKS; i++) - core_power->caps[i].sink = NULL; - - core_power->state = dm_alloc(sizeof(struct backlight_state) * - MOD_POWER_MAX_CONCURRENT_SINKS); - - if (core_power->state == NULL) - goto fail_alloc_state; - - core_power->num_sinks = 0; - backlight_caps_valid = false; - - if (dc == NULL) - goto fail_construct; - - core_power->dc = dc; - - if (!check_dc_support(dc)) - goto fail_construct; - - abm_user_enable = false; - abm_active = false; - - return &core_power->public; - -fail_construct: - dm_free(core_power->state); - -fail_alloc_state: - dm_free(core_power->caps); - -fail_alloc_caps: - dm_free(core_power); - -fail_alloc_context: - return NULL; -} - - -void mod_power_destroy(struct mod_power *mod_power) -{ - if (mod_power != NULL) { - int i; - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - dm_free(core_power->state); - - for (i = 0; i < core_power->num_sinks; i++) - dc_sink_release(core_power->caps[i].sink); - - dm_free(core_power->caps); - - dm_free(core_power); - } -} - -bool mod_power_add_sink(struct mod_power *mod_power, - const struct dc_sink *sink) -{ - if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) - return false; - - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - struct core_dc *core_dc = DC_TO_CORE(core_power->dc); - - if (core_power->num_sinks < MOD_POWER_MAX_CONCURRENT_SINKS) { - dc_sink_retain(sink); - core_power->caps[core_power->num_sinks].sink = sink; - core_power->state[core_power->num_sinks]. - smooth_brightness_enabled = false; - core_power->state[core_power->num_sinks]. - backlight = 100; - core_power->num_sinks++; - return true; - } - - return false; -} - -bool mod_power_remove_sink(struct mod_power *mod_power, - const struct dc_sink *sink) -{ - int i = 0, j = 0; - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - for (i = 0; i < core_power->num_sinks; i++) { - if (core_power->caps[i].sink == sink) { - /* To remove this sink, shift everything after down */ - for (j = i; j < core_power->num_sinks - 1; j++) { - core_power->caps[j].sink = - core_power->caps[j + 1].sink; - - memcpy(&core_power->state[j], - &core_power->state[j + 1], - sizeof(struct backlight_state)); - } - core_power->num_sinks--; - dc_sink_release(sink); - return true; - } - } - return false; -} - -bool mod_power_set_backlight(struct mod_power *mod_power, - const struct dc_stream **streams, int num_streams, - unsigned int backlight_8bit) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - unsigned int frame_ramp = 0; - - unsigned int stream_index, sink_index, vsync_rate_hz; - - union dmcu_abm_set_bl_params params; - - for (stream_index = 0; stream_index < num_streams; stream_index++) { - if (streams[stream_index]->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) { - core_power->state[sink_index].backlight = 0; - core_power->state[sink_index].frame_ramp = 0; - core_power->state[sink_index].smooth_brightness_enabled = false; - continue; - } - - sink_index = sink_index_from_sink(core_power, - streams[stream_index]->sink); - - vsync_rate_hz = div64_u64(div64_u64((streams[stream_index]-> - timing.pix_clk_khz * 1000), - streams[stream_index]->timing.v_total), - streams[stream_index]->timing.h_total); - - core_power->state[sink_index].backlight = backlight_8bit; - - if (core_power->state[sink_index].smooth_brightness_enabled) - frame_ramp = ((vsync_rate_hz * - SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS) + 500) - / 1000; - else - frame_ramp = 0; - - core_power->state[sink_index].frame_ramp = frame_ramp; - } - - params.u32All = 0; - params.bits.gradual_change = (frame_ramp > 0); - params.bits.frame_ramp = frame_ramp; - - core_power->dc->stream_funcs.set_backlight - (core_power->dc, backlight_8bit, params.u32All, streams[0]); - - return true; -} - -bool mod_power_get_backlight(struct mod_power *mod_power, - const struct dc_sink *sink, - unsigned int *backlight_8bit) -{ - if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) - return false; - - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - unsigned int sink_index = sink_index_from_sink(core_power, sink); - - *backlight_8bit = core_power->state[sink_index].backlight; - - return true; -} - -/* hard coded to default backlight curve. */ -void mod_power_initialize_backlight_caps(struct mod_power - *mod_power) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - struct core_dc *core_dc = DC_TO_CORE(core_power->dc); - unsigned int i; - - backlight_caps_initialized = true; - - struct dm_acpi_atif_backlight_caps *pExtCaps = NULL; - bool customCurvePresent = false; - bool customMinMaxPresent = false; - bool customDefLevelsPresent = false; - - /* Allocate memory for ATIF output - * (do not want to use 256 bytes on the stack) - */ - pExtCaps = (struct dm_acpi_atif_backlight_caps *) - (dm_alloc(sizeof(struct dm_acpi_atif_backlight_caps))); - if (pExtCaps == NULL) - return; - - /* Retrieve ACPI extended brightness caps */ - if (dm_query_extended_brightness_caps - (core_dc->ctx, AcpiDisplayType_LCD1, pExtCaps)) { - ac_level_percentage = pExtCaps->acLevelPercentage; - dc_level_percentage = pExtCaps->dcLevelPercentage; - customMinMaxPresent = true; - customDefLevelsPresent = true; - customCurvePresent = (pExtCaps->numOfDataPoints > 0); - - ASSERT(pExtCaps->numOfDataPoints <= 99); - } else { - dm_free(pExtCaps); - return; - } - - if (customMinMaxPresent) - backlight_8bit_lut_array[0] = pExtCaps->minInputSignal; - else - backlight_8bit_lut_array[0] = default_min_backlight; - - if (customMinMaxPresent) - backlight_8bit_lut_array[100] = pExtCaps->maxInputSignal; - else - backlight_8bit_lut_array[100] = default_max_backlight; - - ASSERT(backlight_8bit_lut_array[100] <= absolute_backlight_max); - ASSERT(backlight_8bit_lut_array[0] <= - backlight_8bit_lut_array[100]); - - /* Just to make sure we use valid values */ - if (backlight_8bit_lut_array[100] > absolute_backlight_max) - backlight_8bit_lut_array[100] = absolute_backlight_max; - if (backlight_8bit_lut_array[0] > backlight_8bit_lut_array[100]) { - unsigned int swap; - - swap = backlight_8bit_lut_array[0]; - backlight_8bit_lut_array[0] = backlight_8bit_lut_array[100]; - backlight_8bit_lut_array[100] = swap; - } - - /* Build backlight translation table for custom curve */ - if (customCurvePresent) { - unsigned int index = 1; - unsigned int numOfDataPoints = - (pExtCaps->numOfDataPoints <= 99 ? - pExtCaps->numOfDataPoints : 99); - - /* Filling translation table from data points - - * between every two provided data points we - * lineary interpolate missing values - */ - for (i = 0; i < numOfDataPoints; i++) { - /* Clamp signal level between min and max - * (since min and max might come other - * soruce like registry) - */ - unsigned int luminance = - pExtCaps->dataPoints[i].luminance; - unsigned int signalLevel = - pExtCaps->dataPoints[i].signalLevel; - - if (signalLevel < backlight_8bit_lut_array[0]) - signalLevel = backlight_8bit_lut_array[0]; - if (signalLevel > backlight_8bit_lut_array[100]) - signalLevel = backlight_8bit_lut_array[100]; - - /* Lineary interpolate missing values */ - if (index < luminance) { - unsigned int baseValue = - backlight_8bit_lut_array[index-1]; - unsigned int deltaSignal = - signalLevel - baseValue; - unsigned int deltaLuma = - luminance - index + 1; - unsigned int step = deltaSignal; - - for (; index < luminance; index++) { - backlight_8bit_lut_array[index] = - baseValue + (step / deltaLuma); - step += deltaSignal; - } - } - - /* Now [index == luminance], - * so we can add data point to the translation table - */ - backlight_8bit_lut_array[index++] = signalLevel; - } - - /* Complete the final segment of interpolation - - * between last datapoint and maximum value - */ - if (index < 100) { - unsigned int baseValue = - backlight_8bit_lut_array[index-1]; - unsigned int deltaSignal = - backlight_8bit_lut_array[100] - - baseValue; - unsigned int deltaLuma = 100 - index + 1; - unsigned int step = deltaSignal; - - for (; index < 100; index++) { - backlight_8bit_lut_array[index] = - baseValue + (step / deltaLuma); - step += deltaSignal; - } - } - /* Build backlight translation table based on default curve */ - } else { - unsigned int delta = - backlight_8bit_lut_array[100] - - backlight_8bit_lut_array[0]; - unsigned int coeffC = backlight_8bit_lut_array[0]; - unsigned int coeffB = - (backlight_curve_coeff_b < delta ? - backlight_curve_coeff_b : delta); - unsigned int coeffA = delta - coeffB; /* coeffB is B*100 */ - - for (i = 1; i < 100; i++) { - backlight_8bit_lut_array[i] = - (coeffA * i * i) / - backlight_curve_coeff_a_factor + - (coeffB * i) / - backlight_curve_coeff_b_factor + - coeffC; - } - } - - if (pExtCaps != NULL) - dm_free(pExtCaps); - - /* Successfully initialized */ - backlight_caps_valid = true; - backlight_def_levels_valid = customDefLevelsPresent; -} - -unsigned int mod_power_backlight_level_percentage_to_signal( - struct mod_power *mod_power, unsigned int percentage) -{ - /* Do lazy initialization of backlight capabilities*/ - if (!backlight_caps_initialized) - mod_power_initialize_backlight_caps(mod_power); - - /* Since the translation table is indexed by percentage, - * we simply return backlight value at given percent - */ - if (backlight_caps_valid && percentage <= 100) - return backlight_8bit_lut_array[percentage]; - - return -1; -} - -unsigned int mod_power_backlight_level_signal_to_percentage( - struct mod_power *mod_power, - unsigned int signalLevel8bit) -{ - unsigned int invalid_backlight = (unsigned int)(-1); - /* Do lazy initialization of backlight capabilities */ - if (!backlight_caps_initialized) - mod_power_initialize_backlight_caps(mod_power); - - /* If customer curve cannot convert to differentiated value near min - * it is important to report 0 for min signal to pass setting "Dimmed" - * setting in HCK brightness2 tests. - */ - if (signalLevel8bit <= backlight_8bit_lut_array[0]) - return 0; - - /* Since the translation table is indexed by percentage - * we need to do a binary search over the array - * Another option would be to guess entry based on linear distribution - * and then do linear search in correct direction - */ - if (backlight_caps_valid && signalLevel8bit <= - absolute_backlight_max) { - unsigned int min = 0; - unsigned int max = 100; - unsigned int mid = invalid_backlight; - - while (max >= min) { - mid = (min + max) / 2; /* floor of half range */ - - if (backlight_8bit_lut_array[mid] < signalLevel8bit) - min = mid + 1; - else if (backlight_8bit_lut_array[mid] > - signalLevel8bit) - max = mid - 1; - else - break; - - if (max == 0 || max == 1) - return invalid_backlight; - } - return mid; - } - - return invalid_backlight; -} - - -bool mod_power_get_panel_backlight_boundaries( - struct mod_power *mod_power, - unsigned int *min_backlight, - unsigned int *max_backlight, - unsigned int *output_ac_level_percentage, - unsigned int *output_dc_level_percentage) -{ - /* Do lazy initialization of backlight capabilities */ - if (!backlight_caps_initialized) - mod_power_initialize_backlight_caps(mod_power); - - /* If cache was successfully updated, - * copy the values to output structure and return success - */ - if (backlight_caps_valid) { - *min_backlight = backlight_8bit_lut_array[0]; - *max_backlight = backlight_8bit_lut_array[100]; - - *output_ac_level_percentage = ac_level_percentage; - *output_dc_level_percentage = dc_level_percentage; - - return true; - } - - return false; -} - -bool mod_power_set_smooth_brightness(struct mod_power *mod_power, - const struct dc_sink *sink, bool enable_brightness) -{ - if (sink->sink_signal == SIGNAL_TYPE_VIRTUAL) - return false; - - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - unsigned int sink_index = sink_index_from_sink(core_power, sink); - - core_power->state[sink_index].smooth_brightness_enabled - = enable_brightness; - return true; -} - -bool mod_power_notify_mode_change(struct mod_power *mod_power, - const struct dc_stream *stream) -{ - if (stream->sink->sink_signal == SIGNAL_TYPE_VIRTUAL) - return false; - - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - unsigned int sink_index = sink_index_from_sink(core_power, - stream->sink); - unsigned int frame_ramp = core_power->state[sink_index].frame_ramp; - union dmcu_abm_set_bl_params params; - - params.u32All = 0; - params.bits.gradual_change = (frame_ramp > 0); - params.bits.frame_ramp = frame_ramp; - - core_power->dc->stream_funcs.set_backlight - (core_power->dc, - core_power->state[sink_index].backlight, - params.u32All, stream); - - core_power->dc->stream_funcs.setup_psr - (core_power->dc, stream); - - return true; -} - - -static bool mod_power_abm_feature_enable(struct mod_power - *mod_power, bool enable) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - if (abm_user_enable == enable) - return true; - - abm_user_enable = enable; - - if (enable) { - if (abm_level != 0 && abm_active) - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, abm_level); - } else { - if (abm_level != 0 && abm_active) { - abm_level = 0; - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, abm_level); - } - } - - return true; -} - -static bool mod_power_abm_activate(struct mod_power - *mod_power, bool activate) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - if (abm_active == activate) - return true; - - abm_active = activate; - - if (activate) { - if (abm_level != 0 && abm_user_enable) - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, abm_level); - } else { - if (abm_level != 0 && abm_user_enable) { - abm_level = 0; - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, abm_level); - } - } - - return true; -} - -static bool mod_power_abm_set_level(struct mod_power *mod_power, - unsigned int level) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - if (abm_level == level) - return true; - - if (abm_active && abm_user_enable && level == 0) - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, 0); - else if (abm_active && abm_user_enable && level != 0) - core_power->dc->stream_funcs.set_abm_level - (core_power->dc, level); - - abm_level = level; - - return true; -} - -bool mod_power_varibright_control(struct mod_power *mod_power, - struct varibright_info *input_varibright_info) -{ - switch (input_varibright_info->cmd) { - case VariBright_Cmd__SetVBLevel: - { - /* Set VariBright user level. */ - mod_power_abm_set_level(mod_power, - input_varibright_info->level); - } - break; - - case VariBright_Cmd__UserEnable: - { - /* Set VariBright user enable state. */ - mod_power_abm_feature_enable(mod_power, - input_varibright_info->enable); - } - break; - - case VariBright_Cmd__PostDisplayConfigChange: - { - /* Set VariBright user level. */ - mod_power_abm_set_level(mod_power, - input_varibright_info->level); - - /* Set VariBright user enable state. */ - mod_power_abm_feature_enable(mod_power, - input_varibright_info->enable); - - /* Set VariBright activate based on power state. */ - mod_power_abm_activate(mod_power, - input_varibright_info->activate); - } - break; - - default: - { - return false; - } - break; - } - - return true; -} - -bool mod_power_block_psr(bool block_enable, enum dmcu_block_psr_reason reason) -{ - if (block_enable) - block_psr |= reason; - else - block_psr &= ~reason; - - return true; -} - - -bool mod_power_set_psr_enable(struct mod_power *mod_power, - bool psr_enable) -{ - struct core_power *core_power = - MOD_POWER_TO_CORE(mod_power); - - if (block_psr == 0) - return core_power->dc->stream_funcs.set_psr_enable - (core_power->dc, psr_enable); - - return false; -} - - -- GitLab From 886391680cce3b7c4543b88bbd4eb49c80c26532 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 23 Dec 2016 16:53:12 -0500 Subject: [PATCH 0154/2898] drm/amd/display: Fix link retraining hw sequence Signed-off-by: Zeyu Fan Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 15 +++--- .../drm/amd/display/dc/core/dc_link_hwss.c | 49 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 3 +- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 4 ++ 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 69819d834543..ad1ce600a165 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -357,17 +357,18 @@ static void perform_link_training(struct dc *dc, } static void set_preferred_link_settings(struct dc *dc, - struct dc_link_settings *link_setting) + struct dc_link_settings *link_setting, + const struct dc_link *link) { - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; + struct core_link *core_link = DC_LINK_TO_CORE(link); - for (i = 0; i < core_dc->link_count; i++) { - core_dc->links[i]->public.verified_link_cap.lane_count = + core_link->public.verified_link_cap.lane_count = link_setting->lane_count; - core_dc->links[i]->public.verified_link_cap.link_rate = + core_link->public.verified_link_cap.link_rate = link_setting->link_rate; - } + dp_retrain_link_physi(core_link, + link_setting, + false); } static void enable_hpd(const struct dc_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 4febc8d2a96d..f870a0e72074 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -200,7 +200,6 @@ void dp_set_hw_test_pattern( encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); } - void dp_retrain_link(struct core_link *link) { struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; @@ -221,3 +220,51 @@ void dp_retrain_link(struct core_link *link) } } } + +void dp_retrain_link_physi(struct core_link *link, + struct dc_link_settings *link_setting, + bool skip_video_pattern) +{ + struct pipe_ctx *pipes = + &link->dc->current_context->res_ctx.pipe_ctx[0]; + unsigned int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream != NULL && + pipes[i].stream->sink != NULL && + pipes[i].stream->sink->link != NULL && + pipes[i].stream_enc != NULL && + pipes[i].stream->sink->link == link) { + dm_delay_in_microseconds(link->ctx, 100); + + pipes[i].stream_enc->funcs->dp_blank( + pipes[i].stream_enc); + + dp_receiver_power_ctrl(link, false); + + link->link_enc->funcs->disable_output( + link->link_enc, + SIGNAL_TYPE_DISPLAY_PORT); + + /* Clear current link setting. + * memset(&link->public.cur_link_settings, 0, + * sizeof(link->public.cur_link_settings)); + */ + + link->link_enc->funcs->enable_dp_output( + link->link_enc, + link_setting, + pipes[i].clock_source->id); + + dp_receiver_power_ctrl(link, true); + + dc_link_dp_perform_link_training( + &link->public, + link_setting, + skip_video_pattern); + + link->dc->hwss.unblank_stream(&pipes[i], + link_setting); + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 599f8b0894c2..83d78c2dc24d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -117,7 +117,8 @@ struct dc_link_funcs { struct dc_link_settings *link_setting, bool skip_video_pattern); void (*set_preferred_link_settings)(struct dc *dc, - struct dc_link_settings *link_setting); + struct dc_link_settings *link_setting, + const struct dc_link *link); void (*enable_hpd)(const struct dc_link *link); void (*disable_hpd)(const struct dc_link *link); void (*set_test_pattern)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 662fa30d45f7..30831c54878b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -70,4 +70,8 @@ enum dp_panel_mode dp_get_panel_mode(struct core_link *link); void dp_retrain_link(struct core_link *link); +void dp_retrain_link_physi(struct core_link *link, + struct dc_link_settings *link_setting, + bool skip_video_pattern); + #endif /* __DC_LINK_HWSS_H__ */ -- GitLab From 73c7260292db3f506b2562cbb25c06adfe90ca99 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 29 Dec 2016 14:58:54 -0500 Subject: [PATCH 0155/2898] drm/amd/display: Fix link retraining hw sequence for auto test Signed-off-by: Hersen Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +-- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +-- .../drm/amd/display/dc/core/dc_link_hwss.c | 27 ++++--------------- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 4 +-- 4 files changed, 9 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ad1ce600a165..a7c6c980927e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -366,9 +366,7 @@ static void set_preferred_link_settings(struct dc *dc, link_setting->lane_count; core_link->public.verified_link_cap.link_rate = link_setting->link_rate; - dp_retrain_link_physi(core_link, - link_setting, - false); + dp_retrain_link_dp_test(core_link, link_setting, false); } static void enable_hpd(const struct dc_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index d32bf61b66e9..a661fc6a69dd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1532,7 +1532,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) static void dp_test_send_link_training(struct core_link *link) { - struct dc_link_settings link_settings; + struct dc_link_settings link_settings = {0}; core_link_read_dpcd( link, @@ -1549,7 +1549,7 @@ static void dp_test_send_link_training(struct core_link *link) link->public.verified_link_cap.lane_count = link_settings.lane_count; link->public.verified_link_cap.link_rate = link_settings.link_rate; - dp_retrain_link(link); + dp_retrain_link_dp_test(link, &link_settings, false); } static void dp_test_send_phy_test_pattern(struct core_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index f870a0e72074..e287584ade29 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -200,28 +200,7 @@ void dp_set_hw_test_pattern( encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); } -void dp_retrain_link(struct core_link *link) -{ - struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; - unsigned int i; - - for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream_enc != NULL) { - dm_delay_in_microseconds(link->ctx, 100); - pipes->stream_enc->funcs->dp_blank(pipes[i].stream_enc); - link->dc->hwss.disable_stream(&pipes[i]); - dc_link_dp_perform_link_training( - &link->public, - &link->public.verified_link_cap, - true); - link->dc->hwss.enable_stream(&pipes[i]); - link->dc->hwss.unblank_stream(&pipes[i], - &link->public.verified_link_cap); - } - } -} - -void dp_retrain_link_physi(struct core_link *link, +void dp_retrain_link_dp_test(struct core_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern) { @@ -240,6 +219,10 @@ void dp_retrain_link_physi(struct core_link *link, pipes[i].stream_enc->funcs->dp_blank( pipes[i].stream_enc); + /* disable any test pattern that might be active */ + dp_set_hw_test_pattern(link, + DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); + dp_receiver_power_ctrl(link, false); link->link_enc->funcs->disable_output( diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 30831c54878b..75d10e93b002 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -68,9 +68,7 @@ void dp_set_hw_test_pattern( enum dp_panel_mode dp_get_panel_mode(struct core_link *link); -void dp_retrain_link(struct core_link *link); - -void dp_retrain_link_physi(struct core_link *link, +void dp_retrain_link_dp_test(struct core_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern); -- GitLab From 4dfb0badee55bf163f4ce3307572cd4963c791d0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 29 Dec 2016 10:56:32 -0500 Subject: [PATCH 0156/2898] drm/amd/display: simplify link_encoder - remove unnecessary feature flags - remove wireless and VGA validation Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 +-- .../drm/amd/display/dc/dce/dce_link_encoder.c | 64 ++----------------- .../drm/amd/display/dc/inc/hw/link_encoder.h | 20 +----- .../display/dc/virtual/virtual_link_encoder.c | 4 -- 4 files changed, 6 insertions(+), 90 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b2fc290b5385..b0f316344e86 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -317,7 +317,6 @@ static bool is_dp_sink_present(struct core_link *link) { enum gpio_result gpio_result; uint32_t clock_pin = 0; - uint32_t data_pin = 0; struct ddc *ddc; @@ -353,12 +352,7 @@ static bool is_dp_sink_present(struct core_link *link) gpio_result = dal_gpio_get_value(ddc->pin_clock, &clock_pin); ASSERT(gpio_result == GPIO_RESULT_OK); - if (gpio_result == GPIO_RESULT_OK) - if (link->link_enc->features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN) - gpio_result = dal_gpio_get_value(ddc->pin_data, &data_pin); - - present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin); + present = (gpio_result == GPIO_RESULT_OK) && !clock_pin; dal_ddc_close(ddc); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index ea4778b6e6d8..aa6b3449913c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -67,11 +67,6 @@ #define HPD_REG(reg)\ (enc110->hpd_regs->reg) -/* For current ASICs pixel clock - 600MHz */ -#define MAX_ENCODER_CLK 600000 - -#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 594000 - #define DEFAULT_AUX_MAX_DATA_SIZE 16 #define AUX_MAX_DEFER_WRITE_RETRY 20 /* @@ -845,18 +840,15 @@ bool dce110_link_encoder_validate_dvi_output( { uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK; - if (enc110->base.features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK) - max_pixel_clock = enc110->base.features.max_pixel_clock; - if (signal == SIGNAL_TYPE_DVI_DUAL_LINK) - max_pixel_clock <<= 1; + max_pixel_clock *= 2; /* This handles the case of HDMI downgrade to DVI we don't want to * we don't want to cap the pixel clock if the DDI is not DVI. */ if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK && connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) - max_pixel_clock = enc110->base.features.max_pixel_clock; + max_pixel_clock = enc110->base.features.max_hdmi_pixel_clock; /* DVI only support RGB pixel encoding */ if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) @@ -893,9 +885,6 @@ static bool dce110_link_encoder_validate_hdmi_output( enum dc_color_depth max_deep_color = enc110->base.features.max_hdmi_deep_color; - if (max_deep_color > enc110->base.features.max_deep_color) - max_deep_color = enc110->base.features.max_deep_color; - if (max_deep_color < crtc_timing->display_color_depth) return false; @@ -903,8 +892,7 @@ static bool dce110_link_encoder_validate_hdmi_output( return false; if ((adjusted_pix_clk_khz == 0) || - (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock) || - (adjusted_pix_clk_khz > enc110->base.features.max_pixel_clock)) + (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock)) return false; /* DCE11 HW does not support 420 */ @@ -915,19 +903,6 @@ static bool dce110_link_encoder_validate_hdmi_output( return true; } -bool dce110_link_encoder_validate_rgb_output( - const struct dce110_link_encoder *enc110, - const struct dc_crtc_timing *crtc_timing) -{ - if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) - return false; - - if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) - return false; - - return true; -} - bool dce110_link_encoder_validate_dp_output( const struct dce110_link_encoder *enc110, const struct dc_crtc_timing *crtc_timing) @@ -949,21 +924,6 @@ bool dce110_link_encoder_validate_dp_output( return false; } -bool dce110_link_encoder_validate_wireless_output( - const struct dce110_link_encoder *enc110, - const struct dc_crtc_timing *crtc_timing) -{ - if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock) - return false; - - /* Wireless only supports YCbCr444 */ - if (crtc_timing->pixel_encoding == - PIXEL_ENCODING_YCBCR444) - return true; - - return false; -} - bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, @@ -985,12 +945,6 @@ bool dce110_link_encoder_construct( enc110->base.transmitter = init_data->transmitter; - enc110->base.features.flags.bits.IS_AUDIO_CAPABLE = true; - - enc110->base.features.max_pixel_clock = - MAX_ENCODER_CLK; - - enc110->base.features.max_deep_color = COLOR_DEPTH_121212; enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212; if (enc110->base.ctx->dc->debug.disable_hdmi_deep_color) @@ -1070,7 +1024,6 @@ bool dce110_link_encoder_construct( bp_cap_info.DP_HBR2_CAP; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; - } /* TODO: check PPLIB maxPhyClockInKHz <= 540000, if yes, @@ -1082,7 +1035,6 @@ bool dce110_link_encoder_construct( /* test pattern 4 support */ enc110->base.features.flags.bits.IS_TPS4_CAPABLE = true; - enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE = false; /* dal_adapter_service_is_feature_supported(as, FEATURE_SUPPORT_DP_Y_ONLY); @@ -1118,22 +1070,14 @@ bool dce110_link_encoder_validate_output_with_stream( &stream->public.timing, stream->phy_pix_clk); break; - case SIGNAL_TYPE_RGB: - is_valid = dce110_link_encoder_validate_rgb_output( - enc110, &stream->public.timing); - break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: case SIGNAL_TYPE_EDP: is_valid = dce110_link_encoder_validate_dp_output( enc110, &stream->public.timing); break; - case SIGNAL_TYPE_WIRELESS: - is_valid = dce110_link_encoder_validate_wireless_output( - enc110, &stream->public.timing); - break; default: - is_valid = true; + is_valid = false; break; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 77f8aa410898..49c4b6587456 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -33,34 +33,16 @@ struct encoder_init_data { struct encoder_feature_support { union { struct { - /* 1 - external encoder; 0 - internal encoder */ - uint32_t EXTERNAL_ENCODER:1; - uint32_t ANALOG_ENCODER:1; - uint32_t STEREO_SYNC:1; - /* check the DDC data pin - * when performing DP Sink detection */ - uint32_t DP_SINK_DETECT_POLL_DATA_PIN:1; - /* CPLIB authentication - * for external DP chip supported */ - uint32_t CPLIB_DP_AUTHENTICATION:1; uint32_t IS_HBR2_CAPABLE:1; uint32_t IS_HBR3_CAPABLE:1; - uint32_t IS_HBR2_VALIDATED:1; uint32_t IS_TPS3_CAPABLE:1; uint32_t IS_TPS4_CAPABLE:1; - uint32_t IS_AUDIO_CAPABLE:1; - uint32_t IS_VCE_SUPPORTED:1; - uint32_t IS_CONVERTER:1; - uint32_t IS_Y_ONLY_CAPABLE:1; uint32_t IS_YCBCR_CAPABLE:1; } bits; uint32_t raw; } flags; - /* maximum supported deep color depth */ - enum dc_color_depth max_deep_color; + enum dc_color_depth max_hdmi_deep_color; - /* maximum supported clock */ - unsigned int max_pixel_clock; unsigned int max_hdmi_pixel_clock; bool ycbcr420_supported; }; diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index bb4433ff3b6e..869dedca0b17 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -28,8 +28,6 @@ #include "virtual_link_encoder.h" -#define VIRTUAL_MAX_PIXEL_CLK_IN_KHZ 600000 - static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, struct pipe_ctx *pipe_ctx) { return true; } @@ -138,8 +136,6 @@ bool virtual_link_encoder_construct( enc->transmitter = init_data->transmitter; - enc->features.max_pixel_clock = VIRTUAL_MAX_PIXEL_CLK_IN_KHZ; - enc->output_signals = SIGNAL_TYPE_VIRTUAL; enc->preferred_engine = ENGINE_ID_VIRTUAL; -- GitLab From 7fc698a0c0e5901923a6d6c04a59aceefffe4c9b Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 3 Jan 2017 12:40:40 -0500 Subject: [PATCH 0157/2898] drm/amd/display: limit HBR3 support to Polaris and up - also fix YCbCr420 supported on Polaris and up Signed-off-by: Tony Cheng Reviewed-by: Hersen Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_link_encoder.c | 31 +++---------------- .../drm/amd/display/dc/dce/dce_link_encoder.h | 1 + .../amd/display/dc/dce100/dce100_resource.c | 11 +++++-- .../amd/display/dc/dce110/dce110_resource.c | 11 +++++-- .../amd/display/dc/dce112/dce112_resource.c | 15 +++++++-- .../drm/amd/display/dc/dce80/dce80_resource.c | 11 +++++-- 6 files changed, 46 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index aa6b3449913c..323493b9e129 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -927,10 +927,14 @@ bool dce110_link_encoder_validate_dp_output( bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, const struct dce110_link_enc_registers *link_regs, const struct dce110_link_enc_aux_registers *aux_regs, const struct dce110_link_enc_hpd_registers *hpd_regs) { + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enc110->base.funcs = &dce110_lnk_enc_funcs; enc110->base.ctx = init_data->ctx; enc110->base.id = init_data->encoder; @@ -941,12 +945,10 @@ bool dce110_link_encoder_construct( enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; - enc110->base.features.flags.raw = 0; + enc110->base.features = *enc_features; enc110->base.transmitter = init_data->transmitter; - enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_121212; - if (enc110->base.ctx->dc->debug.disable_hdmi_deep_color) enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_888; @@ -1013,10 +1015,6 @@ bool dce110_link_encoder_construct( init_data->channel); /* Override features with DCE-specific values */ - { - struct bp_encoder_cap_info bp_cap_info = {0}; - const struct dc_vbios_funcs *bp_funcs = enc110->base.ctx->dc_bios->funcs; - if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( enc110->base.ctx->dc_bios, enc110->base.id, &bp_cap_info)) @@ -1024,26 +1022,7 @@ bool dce110_link_encoder_construct( bp_cap_info.DP_HBR2_CAP; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; - } - - /* TODO: check PPLIB maxPhyClockInKHz <= 540000, if yes, - * IS_HBR3_CAPABLE = 0. - */ - /* test pattern 3 support */ - enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true; - /* test pattern 4 support */ - enc110->base.features.flags.bits.IS_TPS4_CAPABLE = true; - - /* - dal_adapter_service_is_feature_supported(as, - FEATURE_SUPPORT_DP_Y_ONLY); -*/ - enc110->base.features.flags.bits.IS_YCBCR_CAPABLE = true; - /* - dal_adapter_service_is_feature_supported(as, - FEATURE_SUPPORT_DP_YUV); - */ return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 1635b239402f..b3667df5250b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -236,6 +236,7 @@ struct dce110_abm_backlight_registers { bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, const struct dce110_link_enc_registers *link_regs, const struct dce110_link_enc_aux_registers *aux_regs, const struct dce110_link_enc_hpd_registers *hpd_regs); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 161d4eee4423..082f1f053a3a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -581,6 +581,14 @@ static struct input_pixel_processor *dce100_ipp_create( return NULL; } +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 300000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + struct link_encoder *dce100_link_encoder_create( const struct encoder_init_data *enc_init_data) { @@ -593,12 +601,11 @@ struct link_encoder *dce100_link_encoder_create( if (dce110_link_encoder_construct( enc110, enc_init_data, + &link_enc_feature, &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], &link_enc_hpd_regs[enc_init_data->hpd_source])) { - enc110->base.features.ycbcr420_supported = false; - enc110->base.features.max_hdmi_pixel_clock = 300000; return &enc110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index d4e1ca933b40..ae90da8c1b8c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -570,6 +570,14 @@ static struct input_pixel_processor *dce110_ipp_create( return NULL; } +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 594000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + struct link_encoder *dce110_link_encoder_create( const struct encoder_init_data *enc_init_data) { @@ -582,12 +590,11 @@ struct link_encoder *dce110_link_encoder_create( if (dce110_link_encoder_construct( enc110, enc_init_data, + &link_enc_feature, &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], &link_enc_hpd_regs[enc_init_data->hpd_source])) { - enc110->base.features.ycbcr420_supported = false; - enc110->base.features.max_hdmi_pixel_clock = 594000; return &enc110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 2711893b71e5..c63030e9f515 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -564,6 +564,18 @@ static struct transform *dce112_transform_create( dm_free(transform); return NULL; } + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .ycbcr420_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + struct link_encoder *dce112_link_encoder_create( const struct encoder_init_data *enc_init_data) { @@ -576,12 +588,11 @@ struct link_encoder *dce112_link_encoder_create( if (dce110_link_encoder_construct( enc110, enc_init_data, + &link_enc_feature, &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], &link_enc_hpd_regs[enc_init_data->hpd_source])) { - enc110->base.features.ycbcr420_supported = false; - enc110->base.features.max_hdmi_pixel_clock = 600000; return &enc110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 56a63d985440..e2bfa7efce1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -611,6 +611,14 @@ static struct input_pixel_processor *dce80_ipp_create( return NULL; } +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 297000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + struct link_encoder *dce80_link_encoder_create( const struct encoder_init_data *enc_init_data) { @@ -623,12 +631,11 @@ struct link_encoder *dce80_link_encoder_create( if (dce110_link_encoder_construct( enc110, enc_init_data, + &link_enc_feature, &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], &link_enc_hpd_regs[enc_init_data->hpd_source])) { - enc110->base.features.ycbcr420_supported = false; - enc110->base.features.max_hdmi_pixel_clock = 297000; return &enc110->base; } -- GitLab From 18f39f2d674e6556d169dcf1a42493c2a632c005 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Tue, 3 Jan 2017 13:46:45 -0500 Subject: [PATCH 0158/2898] drm/amd/display: fix gamma for dpms usecase For dpms usecase we need to set surface transfer function regardless of gamma set flag. Signed-off-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index da8bd66f99ee..8807b48bc110 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -515,7 +515,6 @@ static void fill_gamma_from_crtc( struct dc_gamma *gamma; struct drm_crtc_state *state = crtc->state; struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; - struct dc_transfer_func *input_tf; gamma = dc_create_gamma(); @@ -529,16 +528,6 @@ static void fill_gamma_from_crtc( } dc_surface->gamma_correction = gamma; - - input_tf = dc_create_transfer_func(); - - if (input_tf == NULL) - return; - - input_tf->type = TF_TYPE_PREDEFINED; - input_tf->tf = TRANSFER_FUNCTION_SRGB; - - dc_surface->in_transfer_func = input_tf; } static void fill_plane_attributes( @@ -549,6 +538,7 @@ static void fill_plane_attributes( const struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(state->fb); const struct drm_crtc *crtc = state->crtc; + struct dc_transfer_func *input_tf; fill_rects_from_plane_state(state, surface); fill_plane_attributes_from_fb( @@ -557,6 +547,16 @@ static void fill_plane_attributes( amdgpu_fb, addrReq); + input_tf = dc_create_transfer_func(); + + if (input_tf == NULL) + return; + + input_tf->type = TF_TYPE_PREDEFINED; + input_tf->tf = TRANSFER_FUNCTION_SRGB; + + surface->in_transfer_func = input_tf; + /* In case of gamma set, update gamma value */ if (state->crtc->state->gamma_lut) { fill_gamma_from_crtc(crtc, surface); -- GitLab From bf5cda339d3609408624afcb6f533f4eabc7d142 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 4 Jan 2017 10:22:35 -0500 Subject: [PATCH 0159/2898] drm/amd/display: Fix DP PHY test pre-emphasis not set properly Signed-off-by: Hersen Wu Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 15 +++++++++++---- .../gpu/drm/amd/display/dc/core/dc_link_hwss.c | 9 +++++---- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a7c6c980927e..25e7d7bc282b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -332,14 +332,21 @@ static bool setup_psr(struct dc *dc, const struct dc_stream *stream) } static void set_drive_settings(struct dc *dc, - struct link_training_settings *lt_settings) + struct link_training_settings *lt_settings, + const struct dc_link *link) { struct core_dc *core_dc = DC_TO_CORE(dc); int i; - for (i = 0; i < core_dc->link_count; i++) - dc_link_dp_set_drive_settings(&core_dc->links[i]->public, - lt_settings); + for (i = 0; i < core_dc->link_count; i++) { + if (&core_dc->links[i]->public == link) + break; + } + + if (i >= core_dc->link_count) + ASSERT_CRITICAL(false); + + dc_link_dp_set_drive_settings(&core_dc->links[i]->public, lt_settings); } static void perform_link_training(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index e287584ade29..da49be0672d7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -229,10 +229,9 @@ void dp_retrain_link_dp_test(struct core_link *link, link->link_enc, SIGNAL_TYPE_DISPLAY_PORT); - /* Clear current link setting. - * memset(&link->public.cur_link_settings, 0, - * sizeof(link->public.cur_link_settings)); - */ + /* Clear current link setting. */ + memset(&link->public.cur_link_settings, 0, + sizeof(link->public.cur_link_settings)); link->link_enc->funcs->enable_dp_output( link->link_enc, @@ -246,6 +245,8 @@ void dp_retrain_link_dp_test(struct core_link *link, link_setting, skip_video_pattern); + link->public.cur_link_settings = *link_setting; + link->dc->hwss.unblank_stream(&pipes[i], link_setting); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 83d78c2dc24d..64002268818a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -112,7 +112,8 @@ struct link_training_settings; struct dc_link_funcs { void (*set_drive_settings)(struct dc *dc, - struct link_training_settings *lt_settings); + struct link_training_settings *lt_settings, + const struct dc_link *link); void (*perform_link_training)(struct dc *dc, struct dc_link_settings *link_setting, bool skip_video_pattern); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 323493b9e129..cb5e5953b7ab 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1363,7 +1363,7 @@ void dce110_link_encoder_dp_set_lane_settings( cntl.pixel_clock = link_settings->link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - for (lane = 0; lane < link_settings->link_settings.lane_count; ++lane) { + for (lane = 0; lane < link_settings->link_settings.lane_count; lane++) { /* translate lane settings */ training_lane_set.bits.VOLTAGE_SWING_SET = -- GitLab From 7abcf6b5043a94e850d8f38b625fd022492e8303 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 29 Dec 2016 13:21:31 -0500 Subject: [PATCH 0160/2898] drm/amd/display: [MST] Fix startup sequence v3. Problem: MST topology discovery was started before fbdev init causing kernel panic on boot. Fix: Defer MST to late init hook, after fbdev strucutres already initilized. v2: Add explicit late_init hook function in DAL. v3: Change signature of detect_mst_link_for_all_connectors from void* to drm_dev* Signed-off-by: Andrey Grodzovsky Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2a7802c67eae..2af4ac0bffcb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -367,27 +367,39 @@ static int dm_sw_fini(void *handle) return 0; } -static void detect_link_for_all_connectors(struct drm_device *dev) +static int detect_mst_link_for_all_connectors(struct drm_device *dev) { struct amdgpu_connector *aconnector; struct drm_connector *connector; + int ret = 0; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { aconnector = to_amdgpu_connector(connector); - if (aconnector->dc_link->type == dc_connection_mst_branch) { - DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", - aconnector, aconnector->base.base.id); - - if (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) < 0) { - DRM_ERROR("DM_MST: Failed to start MST\n"); - ((struct dc_link *)aconnector->dc_link)->type = dc_connection_single; + if (aconnector->dc_link->type == dc_connection_mst_branch) { + DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", + aconnector, aconnector->base.base.id); + + ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true); + if (ret < 0) { + DRM_ERROR("DM_MST: Failed to start MST\n"); + ((struct dc_link *)aconnector->dc_link)->type = dc_connection_single; + return ret; } - } + } } drm_modeset_unlock(&dev->mode_config.connection_mutex); + return ret; +} + +static int dm_late_init(void *handle) +{ + struct drm_device *dev = ((struct amdgpu_device *)handle)->ddev; + int r = detect_mst_link_for_all_connectors(dev); + + return r; } static void s3_handle_mst(struct drm_device *dev, bool suspend) @@ -417,11 +429,8 @@ static int dm_hw_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* Create DAL display manager */ amdgpu_dm_init(adev); - amdgpu_dm_hpd_init(adev); - detect_link_for_all_connectors(adev->ddev); - return 0; } @@ -680,7 +689,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) static const struct amd_ip_funcs amdgpu_dm_funcs = { .name = "dm", .early_init = dm_early_init, - .late_init = NULL, + .late_init = dm_late_init, .sw_init = dm_sw_init, .sw_fini = dm_sw_fini, .hw_init = dm_hw_init, -- GitLab From 7a8b8b1403a115fe303e67d356df7520095222d4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Jan 2017 18:41:25 -0500 Subject: [PATCH 0161/2898] drm/amd/display: Remove unused function in gamma_calcs Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/gamma_calcs.c | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c index ca2234e4b7d2..fd300db833c7 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c @@ -185,45 +185,6 @@ static bool setup_custom_float( return true; } -static bool convert_to_custom_float_format_ex( - struct fixed31_32 value, - const struct custom_float_format *format, - struct custom_float_value *result) -{ - return build_custom_float( - value, format, - &result->negative, &result->mantissa, &result->exponenta) && - setup_custom_float( - format, result->negative, result->mantissa, result->exponenta, - &result->value); -} - -static bool round_custom_float_6_12( - struct hw_x_point *x) -{ - struct custom_float_format fmt; - - struct custom_float_value value; - - fmt.exponenta_bits = 6; - fmt.mantissa_bits = 12; - fmt.sign = true; - - if (!convert_to_custom_float_format_ex( - x->x, &fmt, &value)) - return false; - - x->adjusted_x = x->x; - - if (value.mantissa) { - BREAK_TO_DEBUGGER(); - - return false; - } - - return true; -} - static bool build_hw_curve_configuration( const struct curve_config *curve_config, struct gamma_curve *gamma_curve, -- GitLab From 5727c77cf8de2fd603780151b9c9e17828464360 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Jan 2017 18:43:04 -0500 Subject: [PATCH 0162/2898] drm/amd/display: Fix misleading indentation bug in link_encoder Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index cb5e5953b7ab..81144586995a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1017,11 +1017,12 @@ bool dce110_link_encoder_construct( /* Override features with DCE-specific values */ if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( enc110->base.ctx->dc_bios, enc110->base.id, - &bp_cap_info)) + &bp_cap_info)) { enc110->base.features.flags.bits.IS_HBR2_CAPABLE = bp_cap_info.DP_HBR2_CAP; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; + } return true; } -- GitLab From e5cf325b0c21e626c402b57a055f02c478e3df40 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Jan 2017 18:48:07 -0500 Subject: [PATCH 0163/2898] drm/amd/display: Fix warnings in DC Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++----- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 6 ------ .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 1 - drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c | 2 -- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2b08f5ae5e33..3e3379529b69 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1731,14 +1731,15 @@ static void set_hdr_static_info_packet( struct core_stream *stream, struct hw_info_packet *info_packet) { - uint16_t i; + uint16_t i = 0; enum signal_type signal = stream->signal; + struct dc_hdr_static_metadata hdr_metadata; + uint32_t data; if (!surface) return; - struct dc_hdr_static_metadata hdr_metadata = - surface->public.hdr_static_ctx; + hdr_metadata = surface->public.hdr_static_ctx; if (dc_is_hdmi_signal(signal)) { info_packet->valid = true; @@ -1757,8 +1758,6 @@ static void set_hdr_static_info_packet( i = 2; } - uint32_t data; - data = hdr_metadata.is_hdr; info_packet->sb[i++] = data ? 0x02 : 0x00; info_packet->sb[i++] = 0x00; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 46b128708c7e..167f523df657 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -119,7 +119,6 @@ static void regamma_config_regions_and_segments( const struct pwl_params *params) { const struct gamma_curve *curve; - uint32_t value = 0; { REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, @@ -565,8 +564,6 @@ void dce110_opp_set_clamping( struct dce110_opp *opp110, const struct clamping_and_pixel_encoding_params *params) { - uint32_t clamp_cntl_value = 0; - REG_SET_2(FMT_CLAMP_CNTL, 0, FMT_CLAMP_DATA_EN, 0, FMT_CLAMP_COLOR_FORMAT, 0); @@ -731,7 +728,6 @@ void dce110_opp_set_dyn_expansion( static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) { struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - uint8_t counter = 10; /* clear previous phase lock status*/ REG_UPDATE(FMT_CONTROL, @@ -810,8 +806,6 @@ static bool configure_graphics_mode( enum graphics_csc_adjust_type csc_adjust_type, enum dc_color_space color_space) { - struct dc_context *ctx = opp110->base.ctx; - REG_SET(OUTPUT_CSC_CONTROL, 0, OUTPUT_CSC_GRPH_MODE, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6a7cb3e9294a..2b61fdf3f03d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -293,7 +293,6 @@ static bool dce110_set_output_transfer_func( { struct output_pixel_processor *opp = pipe_ctx->opp; const struct core_gamma *ramp = NULL; - struct ipp_prescale_params prescale_params = { 0 }; struct pwl_params *regamma_params; bool result = false; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c index c68914bf7af0..f05cc9e981f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c @@ -72,8 +72,6 @@ bool dce110_ipp_set_degamma( { struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - uint32_t value = 0; - uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || -- GitLab From e66e4d64289b647f7787d257dd2be0055ae7df94 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Jan 2017 18:54:29 -0500 Subject: [PATCH 0164/2898] drm/amd/display: Fix wrong index bug in set_avi_info_frame Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 3e3379529b69..80fe6b9f9397 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1490,9 +1490,10 @@ static void set_avi_info_frame( info_packet->hb2 = info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; - for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++) + for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet. + info_packet_hdmi.packet_raw_data.sb); byte_index++) info_packet->sb[byte_index] = info_frame.avi_info_packet. - info_packet_hdmi.packet_raw_data.sb[byte_index]; + info_packet_hdmi.packet_raw_data.sb[byte_index]; info_packet->valid = true; } -- GitLab From 10bff005926af12aa7b1d97ea9bc948ccbaed1c9 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 5 Jan 2017 11:26:59 -0500 Subject: [PATCH 0165/2898] drm/amd/display: Check hdr support before setting. In case of programing info frame to some monitors don't support HDR, it will result in black screen or corruption when unplug monitor. By checking hdr flag to avoid unnecessary setting for monitors don't support HDR. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ .../amd/display/dc/dce/dce_stream_encoder.c | 27 +++++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 80fe6b9f9397..a82f2d6ea80f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1742,6 +1742,9 @@ static void set_hdr_static_info_packet( hdr_metadata = surface->public.hdr_static_ctx; + if (!hdr_metadata.is_hdr) + return; + if (dc_is_hdmi_signal(signal)) { info_packet->valid = true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 82133ab3224d..8156c6a8ff5d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -555,18 +555,23 @@ static void dce110_stream_encoder_update_dp_info_packets( struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); uint32_t value = REG_READ(DP_SEC_CNTL); - dce110_update_generic_info_packet( + if (info_frame->vsc.valid) + dce110_update_generic_info_packet( + enc110, + 0, /* packetIndex */ + &info_frame->vsc); + + if (info_frame->spd.valid) + dce110_update_generic_info_packet( enc110, - 0, /* packetIndex */ - &info_frame->vsc); - dce110_update_generic_info_packet( - enc110, - 2, /* packetIndex */ - &info_frame->spd); - dce110_update_generic_info_packet( - enc110, - 3, /* packetIndex */ - &info_frame->hdrsmd); + 2, /* packetIndex */ + &info_frame->spd); + + if (info_frame->hdrsmd.valid) + dce110_update_generic_info_packet( + enc110, + 3, /* packetIndex */ + &info_frame->hdrsmd); /* enable/disable transmission of packet(s). * If enabled, packet transmission begins on the next frame -- GitLab From e33a18f333e8b1abe892e5f5d516e89dffcb5cc3 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 5 Jan 2017 11:29:27 -0500 Subject: [PATCH 0166/2898] drm/amd/display: fix Infoframe byte 28-31 doesn't get written out to register Signed-off-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 8156c6a8ff5d..c510e95eb948 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -137,8 +137,8 @@ static void dce110_update_generic_info_packet( REG_WRITE(AFMT_GENERIC_3, *content++); REG_WRITE(AFMT_GENERIC_4, *content++); REG_WRITE(AFMT_GENERIC_5, *content++); - REG_WRITE(AFMT_GENERIC_6, *content); - REG_WRITE(AFMT_GENERIC_7, 0); + REG_WRITE(AFMT_GENERIC_6, *content++); + REG_WRITE(AFMT_GENERIC_7, *content); } if (!REG(AFMT_VBI_PACKET_CONTROL1)) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 8b4a30459eeb..cb369af29d69 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -19,7 +19,7 @@ struct encoder_info_packet { uint8_t hb1; uint8_t hb2; uint8_t hb3; - uint8_t sb[28]; + uint8_t sb[32]; }; struct encoder_info_frame { -- GitLab From c87af595c03e73cc3175cf282858af22b374e20c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 5 Jan 2017 12:59:34 -0500 Subject: [PATCH 0167/2898] drm/amd/display: remove HDMI deep color debug flag Signed-off-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 64002268818a..e8cb7a4dee80 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -149,7 +149,6 @@ struct dc_debug { bool disable_power_gate; bool disable_clock_gate; bool disable_dmcu; - bool disable_hdmi_deep_color; bool disable_color_module; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 81144586995a..c08337696cf8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -949,9 +949,6 @@ bool dce110_link_encoder_construct( enc110->base.transmitter = init_data->transmitter; - if (enc110->base.ctx->dc->debug.disable_hdmi_deep_color) - enc110->base.features.max_hdmi_deep_color = COLOR_DEPTH_888; - /* set the flag to indicate whether driver poll the I2C data pin * while doing the DP sink detect */ -- GitLab From 546b9b619bfe490ed7cf10c39827e4e578ba8135 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 6 Jan 2017 11:21:47 -0500 Subject: [PATCH 0168/2898] drm/amd/display: Don't fail validation for SIGNAL_TYPE_VIRTUAL Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index c08337696cf8..930ae1377ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1053,6 +1053,9 @@ bool dce110_link_encoder_validate_output_with_stream( is_valid = dce110_link_encoder_validate_dp_output( enc110, &stream->public.timing); break; + case SIGNAL_TYPE_VIRTUAL: + is_valid = true; + break; default: is_valid = false; break; -- GitLab From 2555039d129e4e637cbc6a1048d1005dd9c78b7a Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Tue, 10 Jan 2017 17:34:52 +0800 Subject: [PATCH 0169/2898] drm/amdgpu/virt: disable dc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Virtualization don't need the dc, disable it. Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Acked-by: Christian König Reviewed-by: Monk Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 226d10f288a3..2efb486e283d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2006,6 +2006,9 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) */ bool amdgpu_device_has_dc_support(struct amdgpu_device *adev) { + if (amdgpu_sriov_vf(adev)) + return false; + return amdgpu_device_asic_has_dc_support(adev->asic_type); } -- GitLab From cf388c0da8e978ed766b975ceccbf699e98bd476 Mon Sep 17 00:00:00 2001 From: Arindam Nath Date: Mon, 9 Jan 2017 11:50:27 +0530 Subject: [PATCH 0170/2898] drm/amd/display: fix cursor disappearing after resume Since during suspend, the cursor registers are cleared, once the system resumes back, the cursor remains disabled. cursor_set_attributes() only sets the cursor attributes along with cursor size and surface address, but does not enable the cursor back on. We need to save the current cursor location so that we can resume back to the same location. This is done in dm_crtc_cursor_move(), where we save the current cursor location into cursor_x and cursor_y. Later during resume we use these same values to set the cursor position along with cursor attributes. Signed-off-by: Arindam Nath Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 8807b48bc110..e1b5f7d7b6da 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -78,6 +78,11 @@ static void dm_set_cursor( uint32_t height) { struct dc_cursor_attributes attributes; + struct dc_cursor_position position; + struct drm_crtc *crtc = &amdgpu_crtc->base; + int x, y; + int xorigin = 0, yorigin = 0; + amdgpu_crtc->cursor_width = width; amdgpu_crtc->cursor_height = height; @@ -91,11 +96,41 @@ static void dm_set_cursor( attributes.rotation_angle = 0; attributes.attribute_flags.value = 0; + x = amdgpu_crtc->cursor_x; + y = amdgpu_crtc->cursor_y; + + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + position.enable = true; + position.x = x; + position.y = y; + + position.hot_spot_enable = true; + position.x_hotspot = xorigin; + position.y_hotspot = yorigin; + if (!dc_target_set_cursor_attributes( amdgpu_crtc->target, &attributes)) { DRM_ERROR("DC failed to set cursor attributes\n"); } + + if (!dc_target_set_cursor_position( + amdgpu_crtc->target, + &position)) { + DRM_ERROR("DC failed to set cursor position\n"); + } } static int dm_crtc_unpin_cursor_bo_old( @@ -274,6 +309,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, int xorigin = 0, yorigin = 0; struct dc_cursor_position position; + amdgpu_crtc->cursor_x = x; + amdgpu_crtc->cursor_y = y; + /* avivo cursor are offset into the total surface */ x += crtc->primary->state->src_x >> 16; y += crtc->primary->state->src_y >> 16; -- GitLab From b06b7680e341151c8c60b07ddc6f5e63e7392c17 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Thu, 5 Jan 2017 17:47:43 -0500 Subject: [PATCH 0171/2898] drm/amd/display: blank mechanism for supporting MPO blank/unblanck functionality apply_ctx_for_surface will update planes visibility by manipulating Blender and CRTC HW modules. Signed-off-by: Leon Elazar Reviewed-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 -- .../display/dc/dce110/dce110_hw_sequencer.c | 42 ++++++++++++++++--- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 25e7d7bc282b..2277f9bf4bb1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1246,10 +1246,6 @@ bool dc_pre_update_surfaces_to_target( core_dc, &context->res_ctx.pipe_ctx[j], context); - - if (!new_surfaces[i]->visible) - context->res_ctx.pipe_ctx[j].tg->funcs->set_blank( - context->res_ctx.pipe_ctx[j].tg, true); } unexpected_fail: diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2b61fdf3f03d..7c27a820e5be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1409,20 +1409,52 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) pipe_ctx->opp, &default_adjust); } -static void program_blender(const struct core_dc *dc, + +/******************************************************************************* + * In order to turn on/off specific surface we will program + * Blender + CRTC + * + * In case that we have two surfaces and they have a different visibility + * we can't turn off the CRTC since it will turn off the entire display + * + * |----------------------------------------------- | + * |bottom pipe|curr pipe | | | + * |Surface |Surface | Blender | CRCT | + * |visibility |visibility | Configuration| | + * |------------------------------------------------| + * | off | off | CURRENT_PIPE | blank | + * | off | on | CURRENT_PIPE | unblank | + * | on | off | OTHER_PIPE | unblank | + * | on | on | BLENDING | unblank | + * -------------------------------------------------| + * + ******************************************************************************/ +static void program_surface_visibility(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; + bool blank_target = false; if (pipe_ctx->bottom_pipe) { + + /* For now we are supporting only two pipes */ + ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); + if (pipe_ctx->bottom_pipe->surface->public.visible) { if (pipe_ctx->surface->public.visible) blender_mode = BLND_MODE_BLENDING; else blender_mode = BLND_MODE_OTHER_PIPE; - } - } + + } else if (!pipe_ctx->surface->public.visible) + blank_target = true; + + } else if (!pipe_ctx->surface->public.visible) + blank_target = true; + dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, blank_target); + } /** @@ -1495,7 +1527,7 @@ static void set_plane_config( pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; program_scaler(dc, pipe_ctx); - program_blender(dc, pipe_ctx); + program_surface_visibility(dc, pipe_ctx); mi->funcs->mem_input_program_surface_config( mi, @@ -1920,7 +1952,7 @@ static void dce110_apply_ctx_for_surface( continue; dce110_program_front_end_for_pipe(dc, pipe_ctx); - program_blender(dc, pipe_ctx); + program_surface_visibility(dc, pipe_ctx); } } -- GitLab From 4b5e7d620901778b24a2980bbc9941eff9b47f77 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 6 Jan 2017 16:23:18 -0500 Subject: [PATCH 0172/2898] drm/amd/display: set blank functionality 1. remove the sleep mechanism while set_blank true from the timing generator. Since Hw sequencer is the one that manages the flow he will be responsible for wait for blanck in a critical places. Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_hw_sequencer.c | 20 ++++++++++ .../display/dc/dce110/dce110_hw_sequencer.c | 12 +++--- .../dc/dce110/dce110_timing_generator.c | 28 +------------ .../dc/dce110/dce110_timing_generator.h | 2 +- .../dc/dce110/dce110_timing_generator_v.c | 39 +++---------------- .../amd/display/dc/inc/hw/timing_generator.h | 2 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++ 7 files changed, 37 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index d5cffa51ca96..9f462a299ff3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -91,3 +91,23 @@ void color_space_to_black_color( break; } } + +bool hwss_wait_for_blank_complete( + struct timing_generator *tg) +{ + int counter; + + for (counter = 0; counter < 100; counter++) { + if (tg->funcs->is_blanked(tg)) + break; + + msleep(1); + } + + if (counter == 100) { + dm_error("DC: failed to blank crtc!\n"); + return false; + } + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7c27a820e5be..965e47a5acfa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -623,7 +623,7 @@ static void program_scaler(const struct core_dc *dc, &pipe_ctx->scl_data); } -static enum dc_status prog_pixclk_crtc_otg( +static enum dc_status dce110_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, struct validate_context *context, struct core_dc *dc) @@ -641,6 +641,7 @@ static enum dc_status prog_pixclk_crtc_otg( pipe_ctx->tg->funcs->set_blank_color( pipe_ctx->tg, &black_color); + /* * Must blank CRTC after disabling power gating and before any * programming, otherwise CRTC will be hung in bad state @@ -1047,7 +1048,8 @@ static void reset_single_pipe_hw_ctx( struct validate_context *context) { core_link_disable_stream(pipe_ctx); - if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) { + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) { dm_error("DC: failed to blank crtc!\n"); BREAK_TO_DEBUGGER(); } @@ -1560,9 +1562,6 @@ static void update_plane_addr(const struct core_dc *dc, surface->public.flip_immediate); surface->status.requested_address = surface->public.address; - - if (surface->public.visible) - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false); } void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) @@ -1718,6 +1717,7 @@ static void init_hw(struct core_dc *dc) /* Blank controller using driver code instead of * command table. */ tg->funcs->set_blank(tg, true); + hwss_wait_for_blank_complete(tg); } for (i = 0; i < dc->res_pool->audio_count; i++) { @@ -2002,7 +2002,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_drr = set_drr, .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, - .prog_pixclk_crtc_otg = prog_pixclk_crtc_otg, + .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, }; bool dce110_hw_sequencer_construct(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index e70704d1ba87..f4b8576a0546 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1808,7 +1808,7 @@ bool dce110_tg_is_blanked(struct timing_generator *tg) return false; } -bool dce110_tg_set_blank(struct timing_generator *tg, +void dce110_tg_set_blank(struct timing_generator *tg, bool enable_blanking) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); @@ -1824,8 +1824,6 @@ bool dce110_tg_set_blank(struct timing_generator *tg, value = 0; if (enable_blanking) { - int counter; - set_reg_field_value( value, 1, @@ -1834,32 +1832,8 @@ bool dce110_tg_set_blank(struct timing_generator *tg, dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value); - for (counter = 0; counter < 100; counter++) { - value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL)); - - if (get_reg_field_value( - value, - CRTC_BLANK_CONTROL, - CRTC_BLANK_DATA_EN) == 1 && - get_reg_field_value( - value, - CRTC_BLANK_CONTROL, - CRTC_CURRENT_BLANK_STATE) == 1) - break; - - msleep(1); - } - - if (counter == 100) { - dm_logger_write(tg->ctx->logger, LOG_ERROR, - "timing generator %d blank timing out.\n", - tg110->controller_id); - return false; - } } else dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0); - - return true; } bool dce110_tg_validate_timing(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 39906502ad5c..dcb49fe452c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -257,7 +257,7 @@ void dce110_tg_program_timing(struct timing_generator *tg, bool dce110_tg_is_blanked(struct timing_generator *tg); -bool dce110_tg_set_blank(struct timing_generator *tg, +void dce110_tg_set_blank(struct timing_generator *tg, bool enable_blanking); bool dce110_tg_validate_timing(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 3bf3179e07c5..682a3de7ba48 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -72,12 +72,11 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg) return true; } -static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) +static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t value = dm_read_reg(tg->ctx, addr); - uint8_t counter = 100; set_reg_field_value( value, @@ -92,35 +91,9 @@ static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) CRTC_BLANK_DE_MODE); dm_write_reg(tg->ctx, addr, value); - - while (counter > 0) { - value = dm_read_reg(tg->ctx, addr); - - if (get_reg_field_value( - value, - CRTCV_BLANK_CONTROL, - CRTC_BLANK_DATA_EN) == 1 && - get_reg_field_value( - value, - CRTCV_BLANK_CONTROL, - CRTC_CURRENT_BLANK_STATE) == 1) - break; - - msleep(1); - counter--; - } - - if (!counter) { - dm_logger_write(tg->ctx->logger, LOG_ERROR, - "timing generator %d blank timing out.\n", - tg110->controller_id); - return false; - } - - return true; } -static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) +static void dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) { uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t value = dm_read_reg(tg->ctx, addr); @@ -138,8 +111,6 @@ static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg) CRTC_BLANK_DE_MODE); dm_write_reg(tg->ctx, addr, value); - - return true; } static bool dce110_timing_generator_v_is_in_vertical_blank( @@ -429,13 +400,13 @@ static void dce110_timing_generator_v_enable_advanced_request( dm_write_reg(tg->ctx, addr, value); } -static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg, +static void dce110_timing_generator_v_set_blank(struct timing_generator *tg, bool enable_blanking) { if (enable_blanking) - return dce110_timing_generator_v_blank_crtc(tg); + dce110_timing_generator_v_blank_crtc(tg); else - return dce110_timing_generator_v_unblank_crtc(tg); + dce110_timing_generator_v_unblank_crtc(tg); } static void dce110_timing_generator_v_program_timing(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 6ac609f6f89f..baa9445833fb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -129,7 +129,7 @@ struct timing_generator_funcs { uint32_t early_cntl); void (*wait_for_state)(struct timing_generator *tg, enum crtc_state state); - bool (*set_blank)(struct timing_generator *tg, + void (*set_blank)(struct timing_generator *tg, bool enable_blanking); bool (*is_blanked)(struct timing_generator *tg); void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 895c446cebf9..562c8978fe9c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -151,4 +151,7 @@ void color_space_to_black_color( enum dc_color_space colorspace, struct tg_color *black_color); +bool hwss_wait_for_blank_complete( + struct timing_generator *tg); + #endif /* __DC_HW_SEQUENCER_H__ */ -- GitLab From 2796eaee69ce139aa5ae8047bf3071650893ce1d Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Mon, 9 Jan 2017 14:43:08 -0500 Subject: [PATCH 0173/2898] drm/amd/display: When signal type of sink is none, use link type for stream Signed-off-by: Joshua Aberback Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a82f2d6ea80f..59770bc9c8fe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -984,19 +984,20 @@ static void update_stream_signal(struct core_stream *stream) { const struct dc_sink *dc_sink = stream->public.sink; - stream->signal = dc_sink->sink_signal; - /* For asic supports dual link DVI, we should adjust signal type - * based on timing pixel clock. If pixel clock more than 165Mhz, - * signal is dual link, otherwise, single link. - */ - if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || - dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) { - if (stream->public.timing.pix_clk_khz > - TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = stream->sink->link->public.connector_signal; + else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || + dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) + /* For asic supports dual link DVI, we should adjust signal type + * based on timing pixel clock. If pixel clock more than 165Mhz, + * signal is dual link, otherwise, single link. + */ + if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; else stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; - } + else + stream->signal = dc_sink->sink_signal; } bool resource_is_stream_unchanged( -- GitLab From 00c91d0d480a0c5f6507da80f7e13dab7e6b7c79 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Mon, 9 Jan 2017 16:26:58 -0500 Subject: [PATCH 0174/2898] drm/amd/display: Support 64-bit Polaris11 5k VSR - pass full asic_id info into bw_calc_init instead of only version enum - 64-bit Polaris11 needs an extra microsecond of dmif_urgent_latency - add helper to convert from asic_id.family to bw_calc version enum Signed-off-by: Joshua Aberback Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/calcs/bandwidth_calcs.c | 40 ++++++++++++++++--- .../amd/display/dc/dce110/dce110_resource.c | 5 +-- .../amd/display/dc/dce112/dce112_resource.c | 2 +- .../drm/amd/display/dc/inc/bandwidth_calcs.h | 2 +- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index 3b0710ef4716..aa187736b534 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -27,11 +27,34 @@ #include "bandwidth_calcs.h" #include "dc.h" #include "core_types.h" +#include "dal_asic_id.h" /******************************************************************************* * Private Functions ******************************************************************************/ +static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asic_id) +{ + switch (asic_id.chip_family) { + + case FAMILY_CZ: + if (ASIC_REV_IS_STONEY(asic_id.hw_internal_rev)) + return BW_CALCS_VERSION_STONEY; + return BW_CALCS_VERSION_CARRIZO; + + case FAMILY_VI: + if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev)) + // || ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev) + return BW_CALCS_VERSION_POLARIS10; + if (ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) + return BW_CALCS_VERSION_POLARIS11; + return BW_CALCS_VERSION_INVALID; + + default: + return BW_CALCS_VERSION_INVALID; + } +} + static void calculate_bandwidth( const struct bw_calcs_dceip *dceip, const struct bw_calcs_vbios *vbios, @@ -1954,18 +1977,20 @@ static void calculate_bandwidth( ******************************************************************************/ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, struct bw_calcs_vbios *bw_vbios, - enum bw_calcs_version version) + struct hw_asic_id asic_id) { struct bw_calcs_dceip dceip = { 0 }; struct bw_calcs_vbios vbios = { 0 }; + enum bw_calcs_version version = bw_calcs_version_from_asic_id(asic_id); + dceip.version = version; switch (version) { case BW_CALCS_VERSION_CARRIZO: vbios.memory_type = bw_def_gddr5; vbios.dram_channel_width_in_bits = 64; - vbios.number_of_dram_channels = 2; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; vbios.number_of_dram_banks = 8; vbios.high_yclk = bw_int_to_fixed(1600); vbios.mid_yclk = bw_int_to_fixed(1600); @@ -2075,7 +2100,7 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, case BW_CALCS_VERSION_POLARIS10: vbios.memory_type = bw_def_gddr5; vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = 8; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; vbios.number_of_dram_banks = 8; vbios.high_yclk = bw_int_to_fixed(6000); vbios.mid_yclk = bw_int_to_fixed(3200); @@ -2185,7 +2210,7 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, case BW_CALCS_VERSION_POLARIS11: vbios.memory_type = bw_def_gddr5; vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = 4; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; vbios.number_of_dram_banks = 8; vbios.high_yclk = bw_int_to_fixed(6000); vbios.mid_yclk = bw_int_to_fixed(3200); @@ -2206,7 +2231,10 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); vbios.data_return_bus_width = bw_int_to_fixed(32); vbios.trc = bw_int_to_fixed(48); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + if (vbios.number_of_dram_channels == 2) // 64-bit + vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + else + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); vbios.nbp_state_change_latency = bw_int_to_fixed(45); @@ -2295,7 +2323,7 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, case BW_CALCS_VERSION_STONEY: vbios.memory_type = bw_def_gddr5; vbios.dram_channel_width_in_bits = 64; - vbios.number_of_dram_channels = 1; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; vbios.number_of_dram_banks = 8; vbios.high_yclk = bw_int_to_fixed(1866); vbios.mid_yclk = bw_int_to_fixed(1866); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index ae90da8c1b8c..968ee99003fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1349,10 +1349,7 @@ static bool construct( if (!dce110_hw_sequencer_construct(dc)) goto res_create_fail; - if (ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev)) - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_STONEY); - else - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_CARRIZO); + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index c63030e9f515..7fca2eb188cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1394,7 +1394,7 @@ static bool construct( if (!dce112_hw_sequencer_construct(dc)) goto res_create_fail; - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, BW_CALCS_VERSION_POLARIS11); + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h index f9b871b6199b..16f06fa2d69c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h @@ -483,7 +483,7 @@ struct bw_calcs_output { void bw_calcs_init( struct bw_calcs_dceip *bw_dceip, struct bw_calcs_vbios *bw_vbios, - enum bw_calcs_version version); + struct hw_asic_id asic_id); /** * Return: -- GitLab From 7d7024ca202c502324dce683f2061b35d113a6aa Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 10 Jan 2017 08:35:47 +1000 Subject: [PATCH 0175/2898] drm/amd/display: drop min/max wrappers These aren't needed, and aren't really used in too many places. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 4 ++-- drivers/gpu/drm/amd/display/dc/os_types.h | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2277f9bf4bb1..a7348573ebca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -634,7 +634,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) full_pipe_count = core_dc->res_pool->pipe_count; if (core_dc->res_pool->underlay_pipe_index >= 0) full_pipe_count--; - core_dc->public.caps.max_targets = dm_min( + core_dc->public.caps.max_targets = min( full_pipe_count, core_dc->res_pool->stream_enc_count); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 262612061c68..dd922bdcc145 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -289,7 +289,7 @@ static void dce_set_clock( /* Make sure requested clock isn't lower than minimum threshold*/ if (requested_clk_khz > 0) - requested_clk_khz = dm_max(requested_clk_khz, + requested_clk_khz = max(requested_clk_khz, clk_dce->dentist_vco_freq_khz / 64); /* Prepare to program display clock*/ @@ -364,7 +364,7 @@ static void dce112_set_clock( /* Make sure requested clock isn't lower than minimum threshold*/ if (requested_clk_khz > 0) - requested_clk_khz = dm_max(requested_clk_khz, + requested_clk_khz = max(requested_clk_khz, clk_dce->dentist_vco_freq_khz / 62); dce_clk_params.target_clock_frequency = requested_clk_khz; diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index 7f0c282a1466..27ed2a61c3c8 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -52,8 +52,6 @@ #define dm_vlog(fmt, args) vprintk(fmt, args) -#define dm_min(x, y) min(x, y) -#define dm_max(x, y) max(x, y) #endif -- GitLab From 3e183c5f083125986dd0cd0ab609252349983f0e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 10 Jan 2017 09:33:32 +1000 Subject: [PATCH 0176/2898] drm/amd/display: start using linux hdmi header DAL has defines for things, and it doesn't even use them itself. Signed-off-by: Dave Airlie Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 18 +++++++-------- .../drm/amd/display/include/set_mode_types.h | 22 +------------------ 2 files changed, 9 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 59770bc9c8fe..4bb6b1d9c970 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1334,13 +1334,12 @@ static void set_avi_info_frame( /* Initialize header */ info_frame.avi_info_packet.info_packet_hdmi.bits.header. - info_frame_type = INFO_FRAME_AVI; + info_frame_type = HDMI_INFOFRAME_TYPE_AVI; /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall * not be used in HDMI 2.0 (Section 10.1) */ - info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = - INFO_FRAME_VERSION_2; + info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2; info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = - INFO_FRAME_SIZE_AVI; + HDMI_AVI_INFOFRAME_SIZE; /* * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built @@ -1473,10 +1472,9 @@ static void set_avi_info_frame( check_sum = &info_frame. avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; - *check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI - + INFO_FRAME_VERSION_2; + *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2; - for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++) + for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++) *check_sum += info_frame.avi_info_packet.info_packet_hdmi. packet_raw_data.sb[byte_index]; @@ -1588,7 +1586,7 @@ static void set_vendor_info_packet(struct core_stream *stream, info_packet->sb[5] = stream->public.timing.hdmi_vic; /* Header */ - info_packet->hb0 = 0x81; /* VSIF packet type. */ + info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ info_packet->hb1 = 0x01; /* Version */ /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ @@ -1629,7 +1627,7 @@ static void set_spd_info_packet(struct core_stream *stream, /* HB0 = Packet Type = 0x83 (Source Product * Descriptor InfoFrame) */ - info_packet->hb0 = 0x83; + info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD; /* HB1 = Version = 0x01 */ info_packet->hb1 = 0x01; @@ -1651,7 +1649,7 @@ static void set_spd_info_packet(struct core_stream *stream, /* HB1 = Packet Type = 0x83 (Source Product * Descriptor InfoFrame) */ - info_packet->hb1 = 0x83; + info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD; /* HB2 = [Bits 7:0 = Least significant eight bits - * For INFOFRAME, the value must be 1Bh] diff --git a/drivers/gpu/drm/amd/display/include/set_mode_types.h b/drivers/gpu/drm/amd/display/include/set_mode_types.h index d18210ff5b7a..fee2b6ffcfc1 100644 --- a/drivers/gpu/drm/amd/display/include/set_mode_types.h +++ b/drivers/gpu/drm/amd/display/include/set_mode_types.h @@ -27,6 +27,7 @@ #define __DAL_SET_MODE_TYPES_H__ #include "dc_types.h" +#include /* Info frame packet status */ enum info_frame_flag { @@ -36,27 +37,6 @@ enum info_frame_flag { INFO_PACKET_PACKET_UPDATE_SCAN_TYPE = 8 }; -/* Info frame types */ -enum info_frame_type { - INFO_FRAME_GAMUT = 0x0A, - INFO_FRAME_VENDOR_INFO = 0x81, - INFO_FRAME_AVI = 0x82 -}; - -/* Info frame versions */ -enum info_frame_version { - INFO_FRAME_VERSION_1 = 1, - INFO_FRAME_VERSION_2 = 2, - INFO_FRAME_VERSION_3 = 3 -}; - -/* Info frame size */ -enum info_frame_size { - INFO_FRAME_SIZE_AVI = 13, - INFO_FRAME_SIZE_VENDOR = 25, - INFO_FRAME_SIZE_AUDIO = 10 -}; - struct hdmi_info_frame_header { uint8_t info_frame_type; uint8_t version; -- GitLab From 0ea9e02af5572323f79b493ec8d6bfa55effb2f7 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Tue, 10 Jan 2017 12:47:37 -0500 Subject: [PATCH 0177/2898] drm/amd/display: Use DTO as clock on DP if not Use DVO as pixel clock for DP before enabling link PHY. Otherwise, when switching from HDMI passive dongle to DP on the same connector, the PHY PLL is used as pixel clock, and CRTC would stop working. Signed-off-by: Ding Wang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_link_hwss.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index da49be0672d7..55d96656e54b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -61,6 +61,31 @@ void dp_enable_link_phy( { struct link_encoder *link_enc = link->link_enc; + struct pipe_ctx *pipes = + link->dc->current_context->res_ctx.pipe_ctx; + struct clock_source *dp_cs = + link->dc->res_pool->dp_clock_source; + unsigned int i; + /* If the current pixel clock source is not DTO(happens after + * switching from HDMI passive dongle to DP on the same connector), + * switch the pixel clock source to DTO. + */ + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream != NULL && + pipes[i].stream->sink != NULL && + pipes[i].stream->sink->link == link) { + if (pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + pipes[i].clock_source = dp_cs; + pipes[i].pix_clk_params.requested_pix_clk = + pipes[i].stream->public.timing.pix_clk_khz; + pipes[i].clock_source->funcs->program_pix_clk( + pipes[i].clock_source, + &pipes[i].pix_clk_params, + &pipes[i].pll_settings); + } + } + } + if (dc_is_dp_sst_signal(signal)) { if (signal == SIGNAL_TYPE_EDP) { link_enc->funcs->power_control(link_enc, true); -- GitLab From 02dfc70737ae4eafee202d23d29c16213ee750fb Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Tue, 10 Jan 2017 14:05:49 -0500 Subject: [PATCH 0178/2898] drm/amd/display: Add Polaris12 to bw_calc Signed-off-by: Joshua Aberback Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index aa187736b534..54388c0e29e0 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -44,9 +44,9 @@ static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asi case FAMILY_VI: if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev)) - // || ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev) return BW_CALCS_VERSION_POLARIS10; - if (ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev)) + if (ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || + ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) return BW_CALCS_VERSION_POLARIS11; return BW_CALCS_VERSION_INVALID; -- GitLab From 624d7c4708b27be2dc095579394efadd80f090dd Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 9 Jan 2017 09:42:33 -0500 Subject: [PATCH 0179/2898] drm/amd/display: Pass visible flag into surface programming Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 3 ++- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h | 3 ++- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h | 3 ++- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 3 ++- 7 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index e9005e0048e6..130935fffba3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -372,7 +372,8 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror) + bool horizontal_mirror, + bool visible) { REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 022272d30fe4..f90d586656ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -243,7 +243,8 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); + bool horizontal_mirror, + bool visible); void dce_mem_input_allocate_dmif(struct mem_input *mi, uint32_t h_total, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 965e47a5acfa..751dbb88c265 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1538,7 +1538,8 @@ static void set_plane_config( &surface->public.plane_size, surface->public.rotation, NULL, - false); + false, + pipe_ctx->surface->public.visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( @@ -1877,8 +1878,9 @@ static void dce110_program_front_end_for_pipe( &surface->public.tiling_info, &surface->public.plane_size, surface->public.rotation, + NULL, false, - false); + pipe_ctx->surface->public.visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h index a80a20c09da4..4aec18c94c49 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h @@ -105,7 +105,8 @@ bool dce110_mem_input_program_surface_config( union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); + bool horizontal_mirror, + bool visible); /* * dce110_mem_input_is_flip_pending diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 757e946d0837..b12506adcba4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -664,7 +664,8 @@ void dce110_mem_input_v_program_surface_config( union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizotal_mirror) + bool horizotal_mirror, + bool visible) { struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h index 5b1796ccefc0..44cf066279c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h @@ -89,6 +89,7 @@ bool dce110_mem_input_v_program_surface_config( enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, - enum dc_rotation_angle rotation); + enum dc_rotation_angle rotation, + bool visible); #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 2c0774f95c1c..ed980aed1677 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -95,7 +95,8 @@ struct mem_input_funcs { union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); + bool horizontal_mirror, + bool visible); bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); -- GitLab From ab2541b67395088b9de8ebf3943ef9ef86bccc41 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Thu, 29 Dec 2016 15:27:12 -0500 Subject: [PATCH 0180/2898] drm/amd/display: Remove dc_target object dc_target does not fit well into DRM framework so removed it. This will prevent the driver from leveraging the pipe-split code for tiled displays, so will have to be handled at a higher level. Most places that used dc_target now directly use dc_stream instead. Signed-off-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 6 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 47 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 349 ++++++-------- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- drivers/gpu/drm/amd/display/dc/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 292 ++++++------ .../gpu/drm/amd/display/dc/core/dc_resource.c | 437 ++++++++---------- .../gpu/drm/amd/display/dc/core/dc_stream.c | 183 ++++++++ .../gpu/drm/amd/display/dc/core/dc_target.c | 333 ------------- drivers/gpu/drm/amd/display/dc/dc.h | 194 +++----- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 - .../amd/display/dc/dce100/dce100_resource.c | 89 ++-- .../display/dc/dce110/dce110_hw_sequencer.c | 8 +- .../amd/display/dc/dce110/dce110_resource.c | 103 ++--- .../amd/display/dc/dce112/dce112_resource.c | 144 +++--- .../amd/display/dc/dce112/dce112_resource.h | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 89 ++-- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 1 - .../gpu/drm/amd/display/dc/inc/core_types.h | 19 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 13 +- 20 files changed, 977 insertions(+), 1337 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_target.c diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 3a3adfa16ada..0d92126b4c4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -428,8 +428,8 @@ struct amdgpu_crtc { int otg_inst; uint32_t flip_flags; - /* After Set Mode target will be non-NULL */ - struct dc_target *target; + /* After Set Mode stream will be non-NULL */ + const struct dc_stream *stream; }; struct amdgpu_encoder_atom_dig { @@ -550,7 +550,7 @@ struct amdgpu_connector { const struct dc_sink *dc_sink; const struct dc_link *dc_link; const struct dc_sink *dc_em_sink; - const struct dc_target *target; + const struct dc_stream *stream; void *con_priv; bool dac_load_detect; bool detected_by_load; /* if the connection status was determined by load */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2af4ac0bffcb..214cd38b8135 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -68,12 +68,12 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; - if (NULL == acrtc->target) { - DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc); + if (NULL == acrtc->stream) { + DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); return 0; } - return dc_target_get_vblank_counter(acrtc->target); + return dc_stream_get_vblank_counter(acrtc->stream); } } @@ -85,12 +85,12 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; - if (NULL == acrtc->target) { - DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc); + if (NULL == acrtc->stream) { + DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); return 0; } - return dc_target_get_scanoutpos(acrtc->target, vbl, position); + return dc_stream_get_scanoutpos(acrtc->stream, vbl, position); } return 0; @@ -461,7 +461,7 @@ static int dm_suspend(void *handle) drm_modeset_lock_all(adev->ddev); list_for_each_entry(crtc, &adev->ddev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) + if (acrtc->stream) drm_crtc_vblank_off(crtc); } drm_modeset_unlock_all(adev->ddev); @@ -655,7 +655,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) drm_modeset_lock_all(ddev); list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) + if (acrtc->stream) drm_crtc_vblank_on(crtc); } drm_modeset_unlock_all(ddev); @@ -740,7 +740,7 @@ void amdgpu_dm_update_connector_after_detect( if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && aconnector->dc_em_sink) { - /* For S3 resume with headless use eml_sink to fake target + /* For S3 resume with headless use eml_sink to fake stream * because on resume connecotr->sink is set ti NULL */ mutex_lock(&dev->mode_config.mutex); @@ -1184,7 +1184,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) return -1; } - for (i = 0; i < dm->dc->caps.max_targets; i++) { + for (i = 0; i < dm->dc->caps.max_streams; i++) { acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); if (!acrtc) goto fail; @@ -1199,7 +1199,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) } } - dm->display_indexes_num = dm->dc->caps.max_targets; + dm->display_indexes_num = dm->dc->caps.max_streams; /* loops over all connectors on the board */ for (i = 0; i < link_cnt; i++) { @@ -1318,7 +1318,7 @@ static void dm_page_flip(struct amdgpu_device *adev, int crtc_id, u64 crtc_base, bool async) { struct amdgpu_crtc *acrtc; - struct dc_target *target; + const struct dc_stream *stream; struct dc_flip_addrs addr = { {0} }; /* @@ -1336,7 +1336,7 @@ static void dm_page_flip(struct amdgpu_device *adev, * a little longer to lock up all cores. * * The reason we should lock on dal_mutex is so that we can be sure - * nobody messes with acrtc->target after we read and check its value. + * nobody messes with acrtc->stream after we read and check its value. * * We might be able to fix our concurrency issues with a work queue * where we schedule all work items (mode_set, page_flip, etc.) and @@ -1345,14 +1345,14 @@ static void dm_page_flip(struct amdgpu_device *adev, */ acrtc = adev->mode_info.crtcs[crtc_id]; - target = acrtc->target; + stream = acrtc->stream; /* * Received a page flip call after the display has been reset. * Just return in this case. Everything should be clean-up on reset. */ - if (!target) { + if (!stream) { WARN_ON(1); return; } @@ -1368,7 +1368,7 @@ static void dm_page_flip(struct amdgpu_device *adev, dc_flip_surface_addrs( adev->dm.dc, - dc_target_get_status(target)->surfaces, + dc_stream_get_status(stream)->surfaces, &addr, 1); } @@ -1376,25 +1376,22 @@ static int amdgpu_notify_freesync(struct drm_device *dev, void *data, struct drm_file *filp) { struct mod_freesync_params freesync_params; - uint8_t num_targets; + uint8_t num_streams; uint8_t i; - struct dc_target *target; struct amdgpu_device *adev = dev->dev_private; int r = 0; /* Get freesync enable flag from DRM */ - num_targets = dc_get_current_target_count(adev->dm.dc); + num_streams = dc_get_current_stream_count(adev->dm.dc); - for (i = 0; i < num_targets; i++) { - - target = dc_get_target_at_index(adev->dm.dc, i); + for (i = 0; i < num_streams; i++) { + const struct dc_stream *stream; + stream = dc_get_stream_at_index(adev->dm.dc, i); mod_freesync_update_state(adev->dm.freesync_module, - target->streams, - target->stream_count, - &freesync_params); + &stream, 1, &freesync_params); } return r; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index e1b5f7d7b6da..c32fc6d26088 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -120,14 +120,14 @@ static void dm_set_cursor( position.x_hotspot = xorigin; position.y_hotspot = yorigin; - if (!dc_target_set_cursor_attributes( - amdgpu_crtc->target, + if (!dc_stream_set_cursor_attributes( + amdgpu_crtc->stream, &attributes)) { DRM_ERROR("DC failed to set cursor attributes\n"); } - if (!dc_target_set_cursor_position( - amdgpu_crtc->target, + if (!dc_stream_set_cursor_position( + amdgpu_crtc->stream, &position)) { DRM_ERROR("DC failed to set cursor position\n"); } @@ -260,10 +260,10 @@ static int dm_crtc_cursor_set( position.y = 0; position.hot_spot_enable = false; - if (amdgpu_crtc->target) { + if (amdgpu_crtc->stream) { /*set cursor visible false*/ - dc_target_set_cursor_position( - amdgpu_crtc->target, + dc_stream_set_cursor_position( + amdgpu_crtc->stream, &position); } /*unpin old cursor buffer and update cache*/ @@ -346,9 +346,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, position.x_hotspot = xorigin; position.y_hotspot = yorigin; - if (amdgpu_crtc->target) { - if (!dc_target_set_cursor_position( - amdgpu_crtc->target, + if (amdgpu_crtc->stream) { + if (!dc_stream_set_cursor_position( + amdgpu_crtc->stream, &position)) { DRM_ERROR("DC failed to set cursor position\n"); return -EINVAL; @@ -367,7 +367,7 @@ static void dm_crtc_cursor_reset(struct drm_crtc *crtc) __func__, amdgpu_crtc->cursor_bo); - if (amdgpu_crtc->cursor_bo && amdgpu_crtc->target) { + if (amdgpu_crtc->cursor_bo && amdgpu_crtc->stream) { dm_set_cursor( amdgpu_crtc, amdgpu_crtc->cursor_addr, @@ -635,7 +635,7 @@ static void update_stream_scaling_settings( struct amdgpu_device *adev = dm_state->base.crtc->dev->dev_private; enum amdgpu_rmx_type rmx_type; - struct rect src = { 0 }; /* viewport in target space*/ + struct rect src = { 0 }; /* viewport in composition space*/ struct rect dst = { 0 }; /* stream addressable area */ /* Full screen scaling by default */ @@ -684,11 +684,11 @@ static void dm_dc_surface_commit( struct dc_surface *dc_surface; const struct dc_surface *dc_surfaces[1]; const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct dc_target *dc_target = acrtc->target; + const struct dc_stream *dc_stream = acrtc->stream; - if (!dc_target) { + if (!dc_stream) { dm_error( - "%s: Failed to obtain target on crtc (%d)!\n", + "%s: Failed to obtain stream on crtc (%d)!\n", __func__, acrtc->crtc_id); goto fail; @@ -712,11 +712,11 @@ static void dm_dc_surface_commit( dc_surfaces[0] = dc_surface; - if (false == dc_commit_surfaces_to_target( + if (false == dc_commit_surfaces_to_stream( dc, dc_surfaces, 1, - dc_target)) { + dc_stream)) { dm_error( "%s: Failed to attach surface!\n", __func__); @@ -957,15 +957,14 @@ static void decide_crtc_timing_for_drm_display_mode( } } -static struct dc_target *create_target_for_sink( +static struct dc_stream *create_stream_for_sink( const struct amdgpu_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { struct drm_display_mode *preferred_mode = NULL; const struct drm_connector *drm_connector; - struct dc_target *target = NULL; - struct dc_stream *stream; + struct dc_stream *stream = NULL; struct drm_display_mode mode = *drm_mode; bool native_mode_found = false; @@ -1022,19 +1021,10 @@ static struct dc_target *create_target_for_sink( drm_connector, aconnector->dc_sink); - target = dc_create_target_for_streams(&stream, 1); - dc_stream_release(stream); - - if (NULL == target) { - DRM_ERROR("Failed to create target with streams!\n"); - goto target_create_fail; - } - +stream_create_fail: dm_state_null: drm_connector_null: -target_create_fail: -stream_create_fail: - return target; + return stream; } void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) @@ -1316,8 +1306,7 @@ int amdgpu_dm_connector_mode_valid( struct amdgpu_device *adev = connector->dev->dev_private; struct dc_validation_set val_set = { 0 }; /* TODO: Unhardcode stream count */ - struct dc_stream *streams[1]; - struct dc_target *target; + struct dc_stream *stream; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || @@ -1335,39 +1324,31 @@ int amdgpu_dm_connector_mode_valid( if (NULL == dc_sink) { DRM_ERROR("dc_sink is NULL!\n"); - goto stream_create_fail; + goto null_sink; } - streams[0] = dc_create_stream_for_sink(dc_sink); - - if (NULL == streams[0]) { + stream = dc_create_stream_for_sink(dc_sink); + if (NULL == stream) { DRM_ERROR("Failed to create stream for sink!\n"); goto stream_create_fail; } drm_mode_set_crtcinfo(mode, 0); - fill_stream_properties_from_drm_display_mode(streams[0], mode, connector); - - target = dc_create_target_for_streams(streams, 1); - val_set.target = target; - - if (NULL == val_set.target) { - DRM_ERROR("Failed to create target with stream!\n"); - goto target_create_fail; - } + fill_stream_properties_from_drm_display_mode(stream, mode, connector); + val_set.stream = stream; val_set.surface_count = 0; - streams[0]->src.width = mode->hdisplay; - streams[0]->src.height = mode->vdisplay; - streams[0]->dst = streams[0]->src; + stream->src.width = mode->hdisplay; + stream->src.height = mode->vdisplay; + stream->dst = stream->src; if (dc_validate_resources(adev->dm.dc, &val_set, 1)) result = MODE_OK; - dc_target_release(target); -target_create_fail: - dc_stream_release(streams[0]); + dc_stream_release(stream); + stream_create_fail: +null_sink: /* TODO: error handling*/ return result; } @@ -1562,15 +1543,14 @@ static void dm_plane_helper_cleanup_fb( } } -int dm_create_validation_set_for_target(struct drm_connector *connector, +int dm_create_validation_set_for_connector(struct drm_connector *connector, struct drm_display_mode *mode, struct dc_validation_set *val_set) { int result = MODE_ERROR; const struct dc_sink *dc_sink = to_amdgpu_connector(connector)->dc_sink; /* TODO: Unhardcode stream count */ - struct dc_stream *streams[1]; - struct dc_target *target; + struct dc_stream *stream; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -1581,35 +1561,24 @@ int dm_create_validation_set_for_target(struct drm_connector *connector, return result; } - streams[0] = dc_create_stream_for_sink(dc_sink); + stream = dc_create_stream_for_sink(dc_sink); - if (NULL == streams[0]) { + if (NULL == stream) { DRM_ERROR("Failed to create stream for sink!\n"); return result; } drm_mode_set_crtcinfo(mode, 0); - fill_stream_properties_from_drm_display_mode(streams[0], mode, connector); + fill_stream_properties_from_drm_display_mode(stream, mode, connector); - target = dc_create_target_for_streams(streams, 1); - val_set->target = target; + val_set->stream = stream; - if (NULL == val_set->target) { - DRM_ERROR("Failed to create target with stream!\n"); - goto fail; - } - - streams[0]->src.width = mode->hdisplay; - streams[0]->src.height = mode->vdisplay; - streams[0]->dst = streams[0]->src; + stream->src.width = mode->hdisplay; + stream->src.height = mode->vdisplay; + stream->dst = stream->src; return MODE_OK; - -fail: - dc_stream_release(streams[0]); - return result; - } static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { @@ -2262,23 +2231,21 @@ static bool is_scaling_state_different( return false; } -static void remove_target(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) +static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) { - int i; - /* * we evade vblanks and pflips on crtc that * should be changed */ manage_dm_interrupts(adev, acrtc, false); + /* this is the update mode case */ if (adev->dm.freesync_module) - for (i = 0; i < acrtc->target->stream_count; i++) - mod_freesync_remove_stream( - adev->dm.freesync_module, - acrtc->target->streams[i]); - dc_target_release(acrtc->target); - acrtc->target = NULL; + mod_freesync_remove_stream(adev->dm.freesync_module, + acrtc->stream); + + dc_stream_release(acrtc->stream); + acrtc->stream = NULL; acrtc->otg_inst = -1; acrtc->enabled = false; } @@ -2293,20 +2260,20 @@ int amdgpu_dm_atomic_commit( struct drm_plane *plane; struct drm_plane_state *new_plane_state; struct drm_plane_state *old_plane_state; - uint32_t i, j; + uint32_t i; int32_t ret = 0; - uint32_t commit_targets_count = 0; + uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; uint32_t flip_crtcs_count = 0; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; - struct dc_target *commit_targets[MAX_TARGETS]; - struct amdgpu_crtc *new_crtcs[MAX_TARGETS]; - struct dc_target *new_target; - struct drm_crtc *flip_crtcs[MAX_TARGETS]; - struct amdgpu_flip_work *work[MAX_TARGETS] = {0}; - struct amdgpu_bo *new_abo[MAX_TARGETS] = {0}; + const struct dc_stream *commit_streams[MAX_STREAMS]; + struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; + const struct dc_stream *new_stream; + struct drm_crtc *flip_crtcs[MAX_STREAMS]; + struct amdgpu_flip_work *work[MAX_STREAMS] = {0}; + struct amdgpu_bo *new_abo[MAX_STREAMS] = {0}; /* In this step all new fb would be pinned */ @@ -2422,19 +2389,19 @@ int amdgpu_dm_atomic_commit( case DM_COMMIT_ACTION_DPMS_ON: case DM_COMMIT_ACTION_SET: { struct dm_connector_state *dm_state = NULL; - new_target = NULL; + new_stream = NULL; if (aconnector) dm_state = to_dm_connector_state(aconnector->base.state); - new_target = create_target_for_sink( + new_stream = create_stream_for_sink( aconnector, &crtc->state->mode, dm_state); DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); - if (!new_target) { + if (!new_stream) { /* * this could happen because of issues with * userspace notifications delivery. @@ -2450,23 +2417,23 @@ int amdgpu_dm_atomic_commit( * have a sink to keep the pipe running so that * hw state is consistent with the sw state */ - DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n", + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); break; } - if (acrtc->target) - remove_target(adev, acrtc); + if (acrtc->stream) + remove_stream(adev, acrtc); /* * this loop saves set mode crtcs * we needed to enable vblanks once all - * resources acquired in dc after dc_commit_targets + * resources acquired in dc after dc_commit_streams */ new_crtcs[new_crtcs_count] = acrtc; new_crtcs_count++; - acrtc->target = new_target; + acrtc->stream = new_stream; acrtc->enabled = true; acrtc->hw_mode = crtc->state->mode; crtc->hwmode = crtc->state->mode; @@ -2483,10 +2450,8 @@ int amdgpu_dm_atomic_commit( dm_state = to_dm_connector_state(aconnector->base.state); /* Scaling update */ - update_stream_scaling_settings( - &crtc->state->mode, - dm_state, - acrtc->target->streams[0]); + update_stream_scaling_settings(&crtc->state->mode, + dm_state, acrtc->stream); break; } @@ -2494,8 +2459,8 @@ int amdgpu_dm_atomic_commit( case DM_COMMIT_ACTION_RESET: DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ - if (acrtc->target) - remove_target(adev, acrtc); + if (acrtc->stream) + remove_stream(adev, acrtc); break; } /* switch() */ } /* for_each_crtc_in_state() */ @@ -2504,20 +2469,20 @@ int amdgpu_dm_atomic_commit( struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) { - commit_targets[commit_targets_count] = acrtc->target; - ++commit_targets_count; + if (acrtc->stream) { + commit_streams[commit_streams_count] = acrtc->stream; + ++commit_streams_count; } } /* - * Add streams after required streams from new and replaced targets + * Add streams after required streams from new and replaced streams * are removed from freesync module */ if (adev->dm.freesync_module) { for (i = 0; i < new_crtcs_count; i++) { struct amdgpu_connector *aconnector = NULL; - new_target = new_crtcs[i]->target; + new_stream = new_crtcs[i]->stream; aconnector = amdgpu_dm_find_first_crct_matching_connector( state, @@ -2531,22 +2496,20 @@ int amdgpu_dm_atomic_commit( continue; } - for (j = 0; j < new_target->stream_count; j++) - mod_freesync_add_stream( - adev->dm.freesync_module, - new_target->streams[j], &aconnector->caps); + mod_freesync_add_stream(adev->dm.freesync_module, + new_stream, &aconnector->caps); } } - /* DC is optimized not to do anything if 'targets' didn't change. */ - dc_commit_targets(dm->dc, commit_targets, commit_targets_count); + /* DC is optimized not to do anything if 'streams' didn't change. */ + dc_commit_streams(dm->dc, commit_streams, commit_streams_count); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target != NULL) + if (acrtc->stream != NULL) acrtc->otg_inst = - dc_target_get_status(acrtc->target)->primary_otg_inst; + dc_stream_get_status(acrtc->stream)->primary_otg_inst; } /* update planes when needed */ @@ -2566,7 +2529,7 @@ int amdgpu_dm_atomic_commit( /* Surfaces are created under two scenarios: * 1. This commit is not a page flip. - * 2. This commit is a page flip, and targets are created. + * 2. This commit is a page flip, and streams are created. */ if (!page_flip_needed( plane_state, @@ -2618,13 +2581,9 @@ int amdgpu_dm_atomic_commit( */ struct amdgpu_crtc *acrtc = new_crtcs[i]; - if (adev->dm.freesync_module) { - for (j = 0; j < acrtc->target->stream_count; j++) - mod_freesync_notify_mode_change( - adev->dm.freesync_module, - acrtc->target->streams, - acrtc->target->stream_count); - } + if (adev->dm.freesync_module) + mod_freesync_notify_mode_change( + adev->dm.freesync_module, &acrtc->stream, 1); manage_dm_interrupts(adev, acrtc, true); dm_crtc_cursor_reset(&acrtc->base); @@ -2682,20 +2641,19 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct amdgpu_crtc *disconnected_acrtc; const struct dc_sink *sink; - struct dc_target *commit_targets[6]; - struct dc_target *current_target; - uint32_t commit_targets_count = 0; - int i; + const struct dc_stream *commit_streams[MAX_STREAMS]; + const struct dc_stream *current_stream; + uint32_t commit_streams_count = 0; if (!aconnector->dc_sink || !connector->state || !connector->encoder) return; disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); - if (!disconnected_acrtc || !disconnected_acrtc->target) + if (!disconnected_acrtc || !disconnected_acrtc->stream) return; - sink = disconnected_acrtc->target->streams[0]->sink; + sink = disconnected_acrtc->stream->sink; /* * If the previous sink is not released and different from the current, @@ -2706,8 +2664,8 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector struct dm_connector_state *dm_state = to_dm_connector_state(aconnector->base.state); - struct dc_target *new_target = - create_target_for_sink( + struct dc_stream *new_stream = + create_stream_for_sink( aconnector, &disconnected_acrtc->base.state->mode, dm_state); @@ -2720,56 +2678,51 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector manage_dm_interrupts(adev, disconnected_acrtc, false); /* this is the update mode case */ - current_target = disconnected_acrtc->target; + current_stream = disconnected_acrtc->stream; - disconnected_acrtc->target = new_target; + disconnected_acrtc->stream = new_stream; disconnected_acrtc->enabled = true; disconnected_acrtc->hw_mode = disconnected_acrtc->base.state->mode; - commit_targets_count = 0; + commit_streams_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) { - commit_targets[commit_targets_count] = acrtc->target; - ++commit_targets_count; + if (acrtc->stream) { + commit_streams[commit_streams_count] = acrtc->stream; + ++commit_streams_count; } } - /* DC is optimized not to do anything if 'targets' didn't change. */ - if (!dc_commit_targets(dc, commit_targets, - commit_targets_count)) { + /* DC is optimized not to do anything if 'streams' didn't change. */ + if (!dc_commit_streams(dc, commit_streams, + commit_streams_count)) { DRM_INFO("Failed to restore connector state!\n"); - dc_target_release(disconnected_acrtc->target); - disconnected_acrtc->target = current_target; + dc_stream_release(disconnected_acrtc->stream); + disconnected_acrtc->stream = current_stream; manage_dm_interrupts(adev, disconnected_acrtc, true); return; } if (adev->dm.freesync_module) { + mod_freesync_remove_stream(adev->dm.freesync_module, + current_stream); - for (i = 0; i < current_target->stream_count; i++) - mod_freesync_remove_stream( - adev->dm.freesync_module, - current_target->streams[i]); - - for (i = 0; i < new_target->stream_count; i++) - mod_freesync_add_stream( - adev->dm.freesync_module, - new_target->streams[i], - &aconnector->caps); + mod_freesync_add_stream(adev->dm.freesync_module, + new_stream, &aconnector->caps); } + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target != NULL) { + if (acrtc->stream != NULL) { acrtc->otg_inst = - dc_target_get_status(acrtc->target)->primary_otg_inst; + dc_stream_get_status(acrtc->stream)->primary_otg_inst; } } - dc_target_release(current_target); + dc_stream_release(current_stream); dm_dc_surface_commit(dc, &disconnected_acrtc->base); @@ -2782,13 +2735,13 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector static uint32_t add_val_sets_surface( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_target *target, + const struct dc_stream *stream, const struct dc_surface *surface) { uint32_t i = 0; while (i < set_count) { - if (val_sets[i].target == target) + if (val_sets[i].stream == stream) break; ++i; } @@ -2799,23 +2752,23 @@ static uint32_t add_val_sets_surface( return val_sets[i].surface_count; } -static uint32_t update_in_val_sets_target( +static uint32_t update_in_val_sets_stream( struct dc_validation_set *val_sets, struct drm_crtc **crtcs, uint32_t set_count, - const struct dc_target *old_target, - const struct dc_target *new_target, + const struct dc_stream *old_stream, + const struct dc_stream *new_stream, struct drm_crtc *crtc) { uint32_t i = 0; while (i < set_count) { - if (val_sets[i].target == old_target) + if (val_sets[i].stream == old_stream) break; ++i; } - val_sets[i].target = new_target; + val_sets[i].stream = new_stream; crtcs[i] = crtc; if (i == set_count) { @@ -2829,12 +2782,12 @@ static uint32_t update_in_val_sets_target( static uint32_t remove_from_val_sets( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_target *target) + const struct dc_stream *stream) { int i; for (i = 0; i < set_count; i++) - if (val_sets[i].target == target) + if (val_sets[i].stream == stream) break; if (i == set_count) { @@ -2861,10 +2814,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, int i, j; int ret; int set_count; - int new_target_count; - struct dc_validation_set set[MAX_TARGETS] = {{ 0 }}; - struct dc_target *new_targets[MAX_TARGETS] = { 0 }; - struct drm_crtc *crtc_set[MAX_TARGETS] = { 0 }; + int new_stream_count; + struct dc_validation_set set[MAX_STREAMS] = {{ 0 }}; + struct dc_stream *new_streams[MAX_STREAMS] = { 0 }; + struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; bool need_to_validate = false; @@ -2880,14 +2833,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = -EINVAL; /* copy existing configuration */ - new_target_count = 0; + new_stream_count = 0; set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->target) { - set[set_count].target = acrtc->target; + if (acrtc->stream) { + set[set_count].stream = acrtc->stream; crtc_set[set_count] = crtc; ++set_count; } @@ -2908,7 +2861,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, switch (action) { case DM_COMMIT_ACTION_DPMS_ON: case DM_COMMIT_ACTION_SET: { - struct dc_target *new_target = NULL; + struct dc_stream *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_state = NULL; @@ -2919,30 +2872,30 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dm_state = to_dm_connector_state(conn_state); } - new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state); + new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_state); /* - * we can have no target on ACTION_SET if a display + * we can have no stream on ACTION_SET if a display * was disconnected during S3, in this case it not and * error, the OS will be updated after detection, and * do the right thing on next atomic commit */ - if (!new_target) { - DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n", + if (!new_stream) { + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); break; } - new_targets[new_target_count] = new_target; - set_count = update_in_val_sets_target( + new_streams[new_stream_count] = new_stream; + set_count = update_in_val_sets_stream( set, crtc_set, set_count, - acrtc->target, - new_target, + acrtc->stream, + new_stream, crtc); - new_target_count++; + new_stream_count++; need_to_validate = true; break; } @@ -2952,7 +2905,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_state = NULL; struct dm_connector_state *old_dm_state = NULL; - struct dc_target *new_target; + struct dc_stream *new_stream; if (!aconnector) break; @@ -2970,24 +2923,24 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(dm_state, old_dm_state)) break; - new_target = create_target_for_sink(aconnector, &crtc_state->mode, dm_state); + new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_state); - if (!new_target) { - DRM_ERROR("%s: Failed to create new target for crtc %d\n", + if (!new_stream) { + DRM_ERROR("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); break; } - new_targets[new_target_count] = new_target; - set_count = update_in_val_sets_target( + new_streams[new_stream_count] = new_stream; + set_count = update_in_val_sets_stream( set, crtc_set, set_count, - acrtc->target, - new_target, + acrtc->stream, + new_stream, crtc); - new_target_count++; + new_stream_count++; need_to_validate = true; break; @@ -2995,11 +2948,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, case DM_COMMIT_ACTION_DPMS_OFF: case DM_COMMIT_ACTION_RESET: /* i.e. reset mode */ - if (acrtc->target) { + if (acrtc->stream) { set_count = remove_from_val_sets( set, set_count, - acrtc->target); + acrtc->stream); } break; } @@ -3035,7 +2988,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, /* Surfaces are created under two scenarios: * 1. This commit is not a page flip. - * 2. This commit is a page flip, and targets are created. + * 2. This commit is a page flip, and streams are created. */ crtc_state = drm_atomic_get_crtc_state(state, crtc); if (!page_flip_needed(plane_state, old_plane_state, @@ -3080,7 +3033,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, add_val_sets_surface( set, set_count, - set[i].target, + set[i].stream, surface); need_to_validate = true; @@ -3097,8 +3050,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dc_surface_release(set[i].surfaces[j]); } } - for (i = 0; i < new_target_count; i++) - dc_target_release(new_targets[i]); + for (i = 0; i < new_stream_count; i++) + dc_stream_release(new_streams[i]); if (ret != 0) DRM_ERROR("Atomic check failed.\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 4f7bd3bae44e..6ed1480a8bc3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -59,7 +59,7 @@ int amdgpu_dm_atomic_commit( int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state); -int dm_create_validation_set_for_target( +int dm_create_validation_set_for_stream( struct drm_connector *connector, struct drm_display_mode *mode, struct dc_validation_set *val_set); diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 26e2b50e4954..2df163bc83e9 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -13,7 +13,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) -DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o \ +DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a7348573ebca..7d4299b9ee1f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -49,15 +49,6 @@ #include "dm_helpers.h" #include "mem_input.h" -/******************************************************************************* - * Private structures - ******************************************************************************/ - -struct dc_target_sync_report { - uint32_t h_count; - uint32_t v_count; -}; - /******************************************************************************* * Private functions ******************************************************************************/ @@ -221,7 +212,7 @@ static void stream_update_scaling( struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *cur_ctx = core_dc->current_context; - int i, j; + int i; if (src) stream->public.src = *src; @@ -229,20 +220,18 @@ static void stream_update_scaling( if (dst) stream->public.dst = *dst; - for (i = 0; i < cur_ctx->target_count; i++) { - struct core_target *target = cur_ctx->targets[i]; - struct dc_target_status *status = &cur_ctx->target_status[i]; + for (i = 0; i < cur_ctx->stream_count; i++) { + struct core_stream *cur_stream = cur_ctx->streams[i]; - for (j = 0; j < target->public.stream_count; j++) { - if (target->public.streams[j] != dc_stream) - continue; + if (stream == cur_stream) { + struct dc_stream_status *status = &cur_ctx->stream_status[i]; if (status->surface_count) - if (!dc_commit_surfaces_to_target( + if (!dc_commit_surfaces_to_stream( &core_dc->public, status->surfaces, status->surface_count, - &target->public)) + &cur_stream->public)) /* Need to debug validation */ BREAK_TO_DEBUGGER(); @@ -634,7 +623,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) full_pipe_count = core_dc->res_pool->pipe_count; if (core_dc->res_pool->underlay_pipe_index >= 0) full_pipe_count--; - core_dc->public.caps.max_targets = min( + core_dc->public.caps.max_streams = min( full_pipe_count, core_dc->res_pool->stream_enc_count); @@ -675,20 +664,20 @@ static bool is_validation_required( const struct validate_context *context = dc->current_context; int i, j; - if (context->target_count != set_count) + if (context->stream_count != set_count) return true; for (i = 0; i < set_count; i++) { - if (set[i].surface_count != context->target_status[i].surface_count) + if (set[i].surface_count != context->stream_status[i].surface_count) return true; - if (!is_target_unchanged(DC_TARGET_TO_CORE(set[i].target), context->targets[i])) + if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i])) return true; for (j = 0; j < set[i].surface_count; j++) { struct dc_surface temp_surf = { 0 }; - temp_surf = *context->target_status[i].surfaces[j]; + temp_surf = *context->stream_status[i].surfaces[j]; temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; @@ -737,7 +726,7 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - const struct dc_target *dc_target) + const struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); enum dc_status result = DC_ERROR_UNEXPECTED; @@ -748,7 +737,7 @@ bool dc_validate_guaranteed( goto context_alloc_fail; result = core_dc->res_pool->funcs->validate_guaranteed( - core_dc, dc_target, context); + core_dc, stream, context); resource_validate_ctx_destruct(context); dm_free(context); @@ -838,18 +827,18 @@ static void program_timing_sync( } } -static bool targets_changed( +static bool streams_changed( struct core_dc *dc, - struct dc_target *targets[], - uint8_t target_count) + const struct dc_stream *streams[], + uint8_t stream_count) { uint8_t i; - if (target_count != dc->current_context->target_count) + if (stream_count != dc->current_context->stream_count) return true; - for (i = 0; i < dc->current_context->target_count; i++) { - if (&dc->current_context->targets[i]->public != targets[i]) + for (i = 0; i < dc->current_context->stream_count; i++) { + if (&dc->current_context->streams[i]->public != streams[i]) return true; } @@ -860,74 +849,72 @@ static void fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg) { - uint8_t i, j, k; - uint8_t num_cfgs = 0; - - for (i = 0; i < context->target_count; i++) { - const struct core_target *target = context->targets[i]; - - for (j = 0; j < target->public.stream_count; j++) { - const struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct dm_pp_single_disp_config *cfg = - &pp_display_cfg->disp_configs[num_cfgs]; - const struct pipe_ctx *pipe_ctx = NULL; - - for (k = 0; k < MAX_PIPES; k++) - if (stream == - context->res_ctx.pipe_ctx[k].stream) { - pipe_ctx = &context->res_ctx.pipe_ctx[k]; - break; - } + int j; + int num_cfgs = 0; - ASSERT(pipe_ctx != NULL); - - num_cfgs++; - cfg->signal = pipe_ctx->stream->signal; - cfg->pipe_idx = pipe_ctx->pipe_idx; - cfg->src_height = stream->public.src.height; - cfg->src_width = stream->public.src.width; - cfg->ddi_channel_mapping = - stream->sink->link->ddi_channel_mapping.raw; - cfg->transmitter = - stream->sink->link->link_enc->transmitter; - cfg->link_settings.lane_count = stream->sink->link->public.cur_link_settings.lane_count; - cfg->link_settings.link_rate = stream->sink->link->public.cur_link_settings.link_rate; - cfg->link_settings.link_spread = stream->sink->link->public.cur_link_settings.link_spread; - cfg->sym_clock = stream->phy_pix_clk; - /* Round v_refresh*/ - cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; - cfg->v_refresh /= stream->public.timing.h_total; - cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) - / stream->public.timing.v_total; - } + for (j = 0; j < context->stream_count; j++) { + int k; + + const struct core_stream *stream = context->streams[j]; + struct dm_pp_single_disp_config *cfg = + &pp_display_cfg->disp_configs[num_cfgs]; + const struct pipe_ctx *pipe_ctx = NULL; + + for (k = 0; k < MAX_PIPES; k++) + if (stream == context->res_ctx.pipe_ctx[k].stream) { + pipe_ctx = &context->res_ctx.pipe_ctx[k]; + break; + } + + ASSERT(pipe_ctx != NULL); + + num_cfgs++; + cfg->signal = pipe_ctx->stream->signal; + cfg->pipe_idx = pipe_ctx->pipe_idx; + cfg->src_height = stream->public.src.height; + cfg->src_width = stream->public.src.width; + cfg->ddi_channel_mapping = + stream->sink->link->ddi_channel_mapping.raw; + cfg->transmitter = + stream->sink->link->link_enc->transmitter; + cfg->link_settings.lane_count = + stream->sink->link->public.cur_link_settings.lane_count; + cfg->link_settings.link_rate = + stream->sink->link->public.cur_link_settings.link_rate; + cfg->link_settings.link_spread = + stream->sink->link->public.cur_link_settings.link_spread; + cfg->sym_clock = stream->phy_pix_clk; + /* Round v_refresh*/ + cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; + cfg->v_refresh /= stream->public.timing.h_total; + cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) + / stream->public.timing.v_total; } + pp_display_cfg->display_count = num_cfgs; } static uint32_t get_min_vblank_time_us(const struct validate_context *context) { - uint8_t i, j; + uint8_t j; uint32_t min_vertical_blank_time = -1; - for (i = 0; i < context->target_count; i++) { - const struct core_target *target = context->targets[i]; - - for (j = 0; j < target->public.stream_count; j++) { - const struct dc_stream *stream = - target->public.streams[j]; + for (j = 0; j < context->stream_count; j++) { + const struct dc_stream *stream = &context->streams[j]->public; uint32_t vertical_blank_in_pixels = 0; uint32_t vertical_blank_time = 0; vertical_blank_in_pixels = stream->timing.h_total * (stream->timing.v_total - stream->timing.v_addressable); + vertical_blank_time = vertical_blank_in_pixels * 1000 / stream->timing.pix_clk_khz; + if (min_vertical_blank_time > vertical_blank_time) min_vertical_blank_time = vertical_blank_time; } - } + return min_vertical_blank_time; } @@ -995,7 +982,7 @@ void pplib_apply_display_requirements( /* TODO: is this still applicable?*/ if (pp_display_cfg->display_count == 1) { const struct dc_crtc_timing *timing = - &context->targets[0]->public.streams[0]->timing; + &context->streams[0]->public.timing; pp_display_cfg->crtc_index = pp_display_cfg->disp_configs[0].pipe_idx; @@ -1011,34 +998,32 @@ void pplib_apply_display_requirements( } -bool dc_commit_targets( +bool dc_commit_streams( struct dc *dc, - struct dc_target *targets[], - uint8_t target_count) + const struct dc_stream *streams[], + uint8_t stream_count) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; - struct dc_validation_set set[MAX_TARGETS]; + struct dc_validation_set set[MAX_STREAMS]; int i, j, k; - if (false == targets_changed(core_dc, targets, target_count)) + if (false == streams_changed(core_dc, streams, stream_count)) return DC_OK; - dm_logger_write(core_dc->ctx->logger, LOG_DC, - "%s: %d targets\n", - __func__, - target_count); + dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", + __func__, stream_count); - for (i = 0; i < target_count; i++) { - struct dc_target *target = targets[i]; + for (i = 0; i < stream_count; i++) { + const struct dc_stream *stream = streams[i]; - dc_target_log(target, + dc_stream_log(stream, core_dc->ctx->logger, LOG_DC); - set[i].target = targets[i]; + set[i].stream = stream; set[i].surface_count = 0; } @@ -1047,7 +1032,7 @@ bool dc_commit_targets( if (context == NULL) goto context_alloc_fail; - result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, target_count, context); + result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, stream_count, context); if (result != DC_OK){ dm_logger_write(core_dc->ctx->logger, LOG_ERROR, "%s: Context validation failed! dc_status:%d\n", @@ -1068,13 +1053,12 @@ bool dc_commit_targets( program_timing_sync(core_dc, context); - for (i = 0; i < context->target_count; i++) { - struct dc_target *dc_target = &context->targets[i]->public; - struct core_sink *sink = DC_SINK_TO_CORE(dc_target->streams[0]->sink); + for (i = 0; i < context->stream_count; i++) { + const struct core_sink *sink = context->streams[i]->sink; - for (j = 0; j < context->target_status[i].surface_count; j++) { + for (j = 0; j < context->stream_status[i].surface_count; j++) { const struct dc_surface *dc_surface = - context->target_status[i].surfaces[j]; + context->stream_status[i].surfaces[j]; for (k = 0; k < context->res_ctx.pool->pipe_count; k++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[k]; @@ -1088,11 +1072,11 @@ bool dc_commit_targets( } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", - dc_target->streams[0]->timing.h_addressable, - dc_target->streams[0]->timing.v_addressable, - dc_target->streams[0]->timing.h_total, - dc_target->streams[0]->timing.v_total, - dc_target->streams[0]->timing.pix_clk_khz); + context->streams[i]->public.timing.h_addressable, + context->streams[i]->public.timing.v_addressable, + context->streams[i]->public.timing.h_total, + context->streams[i]->public.timing.v_total, + context->streams[i]->public.timing.pix_clk_khz); } pplib_apply_display_requirements(core_dc, @@ -1116,43 +1100,42 @@ bool dc_commit_targets( return (result == DC_OK); } -bool dc_pre_update_surfaces_to_target( +bool dc_pre_update_surfaces_to_stream( struct dc *dc, const struct dc_surface *const *new_surfaces, uint8_t new_surface_count, - struct dc_target *dc_target) + const struct dc_stream *dc_stream) { int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct dc_target_status *target_status = NULL; + struct dc_stream_status *stream_status = NULL; struct validate_context *context; struct validate_context *temp_context; bool ret = true; pre_surface_trace(dc, new_surfaces, new_surface_count); - if (core_dc->current_context->target_count == 0) + if (core_dc->current_context->stream_count == 0) return false; - /* Cannot commit surface to a target that is not commited */ - for (i = 0; i < core_dc->current_context->target_count; i++) - if (target == core_dc->current_context->targets[i]) + /* Cannot commit surface to a stream that is not commited */ + for (i = 0; i < core_dc->current_context->stream_count; i++) + if (dc_stream == &core_dc->current_context->streams[i]->public) break; - if (i == core_dc->current_context->target_count) + if (i == core_dc->current_context->stream_count) return false; - target_status = &core_dc->current_context->target_status[i]; + stream_status = &core_dc->current_context->stream_status[i]; - if (new_surface_count == target_status->surface_count) { + if (new_surface_count == stream_status->surface_count) { bool skip_pre = true; - for (i = 0; i < target_status->surface_count; i++) { + for (i = 0; i < stream_status->surface_count; i++) { struct dc_surface temp_surf = { 0 }; - temp_surf = *target_status->surfaces[i]; + temp_surf = *stream_status->surfaces[i]; temp_surf.clip_rect = new_surfaces[i]->clip_rect; temp_surf.dst_rect.x = new_surfaces[i]->dst_rect.x; temp_surf.dst_rect.y = new_surfaces[i]->dst_rect.y; @@ -1178,13 +1161,13 @@ bool dc_pre_update_surfaces_to_target( resource_validate_ctx_copy_construct(core_dc->current_context, context); dm_logger_write(core_dc->ctx->logger, LOG_DC, - "%s: commit %d surfaces to target 0x%x\n", + "%s: commit %d surfaces to stream 0x%x\n", __func__, new_surface_count, - dc_target); + dc_stream); if (!resource_attach_surfaces_to_context( - new_surfaces, new_surface_count, dc_target, context)) { + new_surfaces, new_surface_count, dc_stream, context)) { BREAK_TO_DEBUGGER(); ret = false; goto unexpected_fail; @@ -1256,7 +1239,7 @@ bool dc_pre_update_surfaces_to_target( return ret; } -bool dc_post_update_surfaces_to_target(struct dc *dc) +bool dc_post_update_surfaces_to_stream(struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); int i; @@ -1282,22 +1265,27 @@ bool dc_post_update_surfaces_to_target(struct dc *dc) return true; } -bool dc_commit_surfaces_to_target( +bool dc_commit_surfaces_to_stream( struct dc *dc, const struct dc_surface **new_surfaces, uint8_t new_surface_count, - struct dc_target *dc_target) + const struct dc_stream *dc_stream) { - struct dc_surface_update updates[MAX_SURFACES] = { 0 }; - struct dc_flip_addrs flip_addr[MAX_SURFACES] = { 0 }; - struct dc_plane_info plane_info[MAX_SURFACES] = { 0 }; - struct dc_scaling_info scaling_info[MAX_SURFACES] = { 0 }; + struct dc_surface_update updates[MAX_SURFACES]; + struct dc_flip_addrs flip_addr[MAX_SURFACES]; + struct dc_plane_info plane_info[MAX_SURFACES]; + struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; - if (!dc_pre_update_surfaces_to_target( - dc, new_surfaces, new_surface_count, dc_target)) + if (!dc_pre_update_surfaces_to_stream( + dc, new_surfaces, new_surface_count, dc_stream)) return false; + memset(updates, 0, sizeof(updates)); + memset(flip_addr, 0, sizeof(flip_addr)); + memset(plane_info, 0, sizeof(plane_info)); + memset(scaling_info, 0, sizeof(scaling_info)); + for (i = 0; i < new_surface_count; i++) { updates[i].surface = new_surfaces[i]; updates[i].gamma = @@ -1321,13 +1309,13 @@ bool dc_commit_surfaces_to_target( updates[i].plane_info = &plane_info[i]; updates[i].scaling_info = &scaling_info[i]; } - dc_update_surfaces_for_target(dc, updates, new_surface_count, dc_target); + dc_update_surfaces_for_stream(dc, updates, new_surface_count, dc_stream); - return dc_post_update_surfaces_to_target(dc); + return dc_post_update_surfaces_to_stream(dc); } -void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates, - int surface_count, struct dc_target *dc_target) +void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, + int surface_count, const struct dc_stream *dc_stream) { struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context = core_dc->temp_flip_context; @@ -1377,21 +1365,21 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda can_skip_context_building = false; } - if (!can_skip_context_building && dc_target) { - struct core_target *target = DC_TARGET_TO_CORE(dc_target); + if (!can_skip_context_building && dc_stream) { + const struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - if (core_dc->current_context->target_count == 0) + if (core_dc->current_context->stream_count == 0) return; - /* Cannot commit surface to a target that is not commited */ - for (i = 0; i < core_dc->current_context->target_count; i++) - if (target == core_dc->current_context->targets[i]) + /* Cannot commit surface to a stream that is not commited */ + for (i = 0; i < core_dc->current_context->stream_count; i++) + if (stream == core_dc->current_context->streams[i]) break; - if (i == core_dc->current_context->target_count) + if (i == core_dc->current_context->stream_count) return; if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, dc_target, context)) { + new_surfaces, surface_count, dc_stream, context)) { BREAK_TO_DEBUGGER(); return; } @@ -1578,17 +1566,17 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda core_dc->current_context = context; } -uint8_t dc_get_current_target_count(const struct dc *dc) +uint8_t dc_get_current_stream_count(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - return core_dc->current_context->target_count; + return core_dc->current_context->stream_count; } -struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i) +struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i) { struct core_dc *core_dc = DC_TO_CORE(dc); - if (i < core_dc->current_context->target_count) - return &(core_dc->current_context->targets[i]->public); + if (i < core_dc->current_context->stream_count) + return &(core_dc->current_context->streams[i]->public); return NULL; } @@ -1687,8 +1675,8 @@ void dc_set_power_state( core_dc->hwss.init_hw(core_dc); break; default: - /* NULL means "reset/release all DC targets" */ - dc_commit_targets(dc, NULL, 0); + /* NULL means "reset/release all DC streams" */ + dc_commit_streams(dc, NULL, 0); core_dc->hwss.power_down(core_dc); @@ -1882,11 +1870,3 @@ void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink } } -const struct dc_stream_status *dc_stream_get_status( - const struct dc_stream *dc_stream) -{ - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - - return &stream->status; -} - diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4bb6b1d9c970..1f87b948678b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -591,12 +591,12 @@ enum dc_status resource_build_scaling_params_for_context( return DC_OK; } -static void detach_surfaces_for_target( +static void detach_surfaces_for_stream( struct validate_context *context, - const struct dc_target *dc_target) + const struct dc_stream *dc_stream) { int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; @@ -646,15 +646,15 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( } /* - * A free_pipe for a target is defined here as a pipe with a stream that belongs - * to the target but has no surface attached yet + * A free_pipe for a stream is defined here as a pipe + * that has no surface attached yet */ -static struct pipe_ctx *acquire_free_pipe_for_target( +static struct pipe_ctx *acquire_free_pipe_for_stream( struct resource_context *res_ctx, - const struct dc_target *dc_target) + const struct dc_stream *dc_stream) { int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct pipe_ctx *head_pipe = NULL; @@ -688,12 +688,12 @@ static struct pipe_ctx *acquire_free_pipe_for_target( } -static void release_free_pipes_for_target( +static void release_free_pipes_for_stream( struct resource_context *res_ctx, - const struct dc_target *dc_target) + const struct dc_stream *dc_stream) { int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_target->streams[0]); + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == stream && @@ -706,12 +706,12 @@ static void release_free_pipes_for_target( bool resource_attach_surfaces_to_context( const struct dc_surface * const *surfaces, int surface_count, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { int i; struct pipe_ctx *tail_pipe; - struct dc_target_status *target_status = NULL; + struct dc_stream_status *stream_status = NULL; if (surface_count > MAX_SURFACE_NUM) { @@ -720,13 +720,13 @@ bool resource_attach_surfaces_to_context( return false; } - for (i = 0; i < context->target_count; i++) - if (&context->targets[i]->public == dc_target) { - target_status = &context->target_status[i]; + for (i = 0; i < context->stream_count; i++) + if (&context->streams[i]->public == dc_stream) { + stream_status = &context->stream_status[i]; break; } - if (target_status == NULL) { - dm_error("Existing target not found; failed to attach surfaces\n"); + if (stream_status == NULL) { + dm_error("Existing stream not found; failed to attach surfaces\n"); return false; } @@ -734,16 +734,16 @@ bool resource_attach_surfaces_to_context( for (i = 0; i < surface_count; i++) dc_surface_retain(surfaces[i]); - detach_surfaces_for_target(context, dc_target); + detach_surfaces_for_stream(context, dc_stream); /* release existing surfaces*/ - for (i = 0; i < target_status->surface_count; i++) - dc_surface_release(target_status->surfaces[i]); + for (i = 0; i < stream_status->surface_count; i++) + dc_surface_release(stream_status->surfaces[i]); - for (i = surface_count; i < target_status->surface_count; i++) - target_status->surfaces[i] = NULL; + for (i = surface_count; i < stream_status->surface_count; i++) + stream_status->surfaces[i] = NULL; - target_status->surface_count = 0; + stream_status->surface_count = 0; if (surface_count == 0) return true; @@ -751,11 +751,11 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); - struct pipe_ctx *free_pipe = acquire_free_pipe_for_target( - &context->res_ctx, dc_target); + struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( + &context->res_ctx, dc_stream); if (!free_pipe) { - target_status->surfaces[i] = NULL; + stream_status->surfaces[i] = NULL; return false; } @@ -769,13 +769,13 @@ bool resource_attach_surfaces_to_context( tail_pipe = free_pipe; } - release_free_pipes_for_target(&context->res_ctx, dc_target); + release_free_pipes_for_stream(&context->res_ctx, dc_stream); /* assign new surfaces*/ for (i = 0; i < surface_count; i++) - target_status->surfaces[i] = surfaces[i]; + stream_status->surfaces[i] = surfaces[i]; - target_status->surface_count = surface_count; + stream_status->surface_count = surface_count; return true; } @@ -819,25 +819,14 @@ static bool are_stream_backends_same( return true; } -bool is_target_unchanged( - const struct core_target *old_target, const struct core_target *target) +bool is_stream_unchanged( + const struct core_stream *old_stream, const struct core_stream *stream) { - int i; - - if (old_target == target) + if (old_stream == stream) return true; - if (old_target->public.stream_count != target->public.stream_count) - return false; - - for (i = 0; i < old_target->public.stream_count; i++) { - const struct core_stream *old_stream = DC_STREAM_TO_CORE( - old_target->public.streams[i]); - const struct core_stream *stream = DC_STREAM_TO_CORE( - target->public.streams[i]); - if (!are_stream_backends_same(old_stream, stream)) - return false; - } + if (!are_stream_backends_same(old_stream, stream)) + return false; return true; } @@ -851,23 +840,23 @@ bool resource_validate_attach_surfaces( int i, j; for (i = 0; i < set_count; i++) { - for (j = 0; j < old_context->target_count; j++) - if (is_target_unchanged( - old_context->targets[j], - context->targets[i])) { + for (j = 0; j < old_context->stream_count; j++) + if (is_stream_unchanged( + old_context->streams[j], + context->streams[i])) { if (!resource_attach_surfaces_to_context( - old_context->target_status[j].surfaces, - old_context->target_status[j].surface_count, - &context->targets[i]->public, + old_context->stream_status[j].surfaces, + old_context->stream_status[j].surface_count, + &context->streams[i]->public, context)) return false; - context->target_status[i] = old_context->target_status[j]; + context->stream_status[i] = old_context->stream_status[j]; } if (set[i].surface_count != 0) if (!resource_attach_surfaces_to_context( set[i].surfaces, set[i].surface_count, - &context->targets[i]->public, + &context->streams[i]->public, context)) return false; @@ -1001,20 +990,15 @@ static void update_stream_signal(struct core_stream *stream) } bool resource_is_stream_unchanged( - const struct validate_context *old_context, struct core_stream *stream) + const struct validate_context *old_context, const struct core_stream *stream) { - int i, j; - - for (i = 0; i < old_context->target_count; i++) { - struct core_target *old_target = old_context->targets[i]; + int i; - for (j = 0; j < old_target->public.stream_count; j++) { - struct core_stream *old_stream = - DC_STREAM_TO_CORE(old_target->public.streams[j]); + for (i = 0; i < old_context->stream_count; i++) { + const struct core_stream *old_stream = old_context->streams[i]; - if (are_stream_backends_same(old_stream, stream)) + if (are_stream_backends_same(old_stream, stream)) return true; - } } return false; @@ -1036,23 +1020,19 @@ static struct core_stream *find_pll_sharable_stream( const struct core_stream *stream_needs_pll, struct validate_context *context) { - int i, j; + int i; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream_has_pll = context->streams[i]; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream_has_pll = - DC_STREAM_TO_CORE(target->public.streams[j]); + /* We are looking for non dp, non virtual stream */ + if (resource_are_streams_timing_synchronizable( + stream_needs_pll, stream_has_pll) + && !dc_is_dp_signal(stream_has_pll->signal) + && stream_has_pll->sink->link->public.connector_signal + != SIGNAL_TYPE_VIRTUAL) + return stream_has_pll; - /* We are looking for non dp, non virtual stream */ - if (resource_are_streams_timing_synchronizable( - stream_needs_pll, stream_has_pll) - && !dc_is_dp_signal(stream_has_pll->signal) - && stream_has_pll->sink->link->public.connector_signal - != SIGNAL_TYPE_VIRTUAL) - return stream_has_pll; - } } return NULL; @@ -1091,25 +1071,20 @@ static void calculate_phy_pix_clks( const struct core_dc *dc, struct validate_context *context) { - int i, j; - - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + int i; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; - update_stream_signal(stream); + update_stream_signal(stream); - /* update actual pixel clock on all streams */ - if (dc_is_hdmi_signal(stream->signal)) - stream->phy_pix_clk = get_norm_pix_clk( - &stream->public.timing); - else - stream->phy_pix_clk = - stream->public.timing.pix_clk_khz; - } + /* update actual pixel clock on all streams */ + if (dc_is_hdmi_signal(stream->signal)) + stream->phy_pix_clk = get_norm_pix_clk( + &stream->public.timing); + else + stream->phy_pix_clk = + stream->public.timing.pix_clk_khz; } } @@ -1117,136 +1092,122 @@ enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context) { - int i, j, k; + int i, j; calculate_phy_pix_clks(dc, context); - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; - - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - - if (!resource_is_stream_unchanged(dc->current_context, stream)) - continue; - - /* mark resources used for stream that is already active */ - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; - const struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[k]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; - if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) - continue; + if (!resource_is_stream_unchanged(dc->current_context, stream)) + continue; - pipe_ctx->stream = stream; - copy_pipe_ctx(old_pipe_ctx, pipe_ctx); + /* mark resources used for stream that is already active */ + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; + const struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[j]; - /* Split pipe resource, do not acquire back end */ - if (!pipe_ctx->stream_enc) - continue; + if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) + continue; - set_stream_engine_in_use( - &context->res_ctx, - pipe_ctx->stream_enc); - - /* Switch to dp clock source only if there is - * no non dp stream that shares the same timing - * with the dp stream. - */ - if (dc_is_dp_signal(pipe_ctx->stream->signal) && - !find_pll_sharable_stream(stream, context)) - pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; + pipe_ctx->stream = stream; + copy_pipe_ctx(old_pipe_ctx, pipe_ctx); - resource_reference_clock_source( - &context->res_ctx, - pipe_ctx->clock_source); + /* Split pipe resource, do not acquire back end */ + if (!pipe_ctx->stream_enc) + continue; - set_audio_in_use(&context->res_ctx, - pipe_ctx->audio); - } + set_stream_engine_in_use( + &context->res_ctx, + pipe_ctx->stream_enc); + + /* Switch to dp clock source only if there is + * no non dp stream that shares the same timing + * with the dp stream. + */ + if (dc_is_dp_signal(pipe_ctx->stream->signal) && + !find_pll_sharable_stream(stream, context)) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); + + set_audio_in_use(&context->res_ctx, + pipe_ctx->audio); } } - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; - - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct pipe_ctx *pipe_ctx = NULL; - int pipe_idx = -1; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; - /* acquire new resources */ - pipe_idx = acquire_first_free_pipe( - &context->res_ctx, stream); - if (pipe_idx < 0) - return DC_NO_CONTROLLER_RESOURCE; - - - pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct pipe_ctx *pipe_ctx = NULL; + int pipe_idx = -1; - pipe_ctx->stream_enc = - find_first_free_match_stream_enc_for_link( - &context->res_ctx, stream); - - if (!pipe_ctx->stream_enc) - return DC_NO_STREAM_ENG_RESOURCE; - - set_stream_engine_in_use( + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + /* acquire new resources */ + pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream); + if (pipe_idx < 0) + return DC_NO_CONTROLLER_RESOURCE; + + + pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + pipe_ctx->stream_enc = + find_first_free_match_stream_enc_for_link( + &context->res_ctx, stream); + + if (!pipe_ctx->stream_enc) + return DC_NO_STREAM_ENG_RESOURCE; + + set_stream_engine_in_use( + &context->res_ctx, + pipe_ctx->stream_enc); + + /* TODO: Add check if ASIC support and EDID audio */ + if (!stream->sink->converter_disable_audio && + dc_is_audio_capable_signal(pipe_ctx->stream->signal) && + stream->public.audio_info.mode_count) { + pipe_ctx->audio = find_first_free_audio( + &context->res_ctx); + + /* + * Audio assigned in order first come first get. + * There are asics which has number of audio + * resources less then number of pipes + */ + if (pipe_ctx->audio) + set_audio_in_use( &context->res_ctx, - pipe_ctx->stream_enc); - - /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->converter_disable_audio && - dc_is_audio_capable_signal(pipe_ctx->stream->signal) && - stream->public.audio_info.mode_count) { - pipe_ctx->audio = find_first_free_audio( - &context->res_ctx); - - /* - * Audio assigned in order first come first get. - * There are asics which has number of audio - * resources less then number of pipes - */ - if (pipe_ctx->audio) - set_audio_in_use( - &context->res_ctx, - pipe_ctx->audio); - } - - if (j == 0) { - context->target_status[i].primary_otg_inst = - pipe_ctx->tg->inst; - } + pipe_ctx->audio); } + + context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst; } return DC_OK; } -/* first target in the context is used to populate the rest */ -void validate_guaranteed_copy_target( +/* first stream in the context is used to populate the rest */ +void validate_guaranteed_copy_streams( struct validate_context *context, - int max_targets) + int max_streams) { int i; - for (i = 1; i < max_targets; i++) { - context->targets[i] = context->targets[0]; + for (i = 1; i < max_streams; i++) { + context->streams[i] = context->streams[0]; copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], &context->res_ctx.pipe_ctx[i]); context->res_ctx.pipe_ctx[i].stream = context->res_ctx.pipe_ctx[0].stream; - dc_target_retain(&context->targets[i]->public); - context->target_count++; + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } } @@ -1875,18 +1836,19 @@ void resource_validate_ctx_destruct(struct validate_context *context) { int i, j; - for (i = 0; i < context->target_count; i++) { - for (j = 0; j < context->target_status[i].surface_count; j++) + for (i = 0; i < context->stream_count; i++) { + for (j = 0; j < context->stream_status[i].surface_count; j++) dc_surface_release( - context->target_status[i].surfaces[j]); + context->stream_status[i].surfaces[j]); - context->target_status[i].surface_count = 0; - dc_target_release(&context->targets[i]->public); + context->stream_status[i].surface_count = 0; + dc_stream_release(&context->streams[i]->public); + context->streams[i] = NULL; } } /* - * Copy src_ctx into dst_ctx and retain all surfaces and targets referenced + * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced * by the src_ctx */ void resource_validate_ctx_copy_construct( @@ -1908,11 +1870,11 @@ void resource_validate_ctx_copy_construct( } - for (i = 0; i < dst_ctx->target_count; i++) { - dc_target_retain(&dst_ctx->targets[i]->public); - for (j = 0; j < dst_ctx->target_status[i].surface_count; j++) + for (i = 0; i < dst_ctx->stream_count; i++) { + dc_stream_retain(&dst_ctx->streams[i]->public); + for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++) dc_surface_retain( - dst_ctx->target_status[i].surfaces[j]); + dst_ctx->stream_status[i].surfaces[j]); } } @@ -1968,53 +1930,48 @@ enum dc_status resource_map_clock_resources( const struct core_dc *dc, struct validate_context *context) { - int i, j, k; + int i, j; /* acquire new resources */ - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + const struct core_stream *stream = context->streams[i]; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; + + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + else { + pipe_ctx->clock_source = NULL; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (!dc->public.config.disable_disp_pll_sharing) + resource_find_used_clk_src_for_sharing( + &context->res_ctx, + pipe_ctx); - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + if (pipe_ctx->clock_source == NULL) pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; - else { - pipe_ctx->clock_source = NULL; - - if (!dc->public.config.disable_disp_pll_sharing) - resource_find_used_clk_src_for_sharing( - &context->res_ctx, - pipe_ctx); - - if (pipe_ctx->clock_source == NULL) - pipe_ctx->clock_source = - dc_resource_find_first_free_pll(&context->res_ctx); - } + dc_resource_find_first_free_pll(&context->res_ctx); + } - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; - resource_reference_clock_source( - &context->res_ctx, - pipe_ctx->clock_source); + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); - /* only one cs per stream regardless of mpo */ - break; - } + /* only one cs per stream regardless of mpo */ + break; } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index cda67a78dbfd..bc1f387d1992 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -27,6 +27,8 @@ #include "dc.h" #include "core_types.h" #include "resource.h" +#include "ipp.h" +#include "timing_generator.h" /******************************************************************************* * Private definitions @@ -146,3 +148,184 @@ struct dc_stream *dc_create_stream_for_sink( alloc_fail: return NULL; } + +const struct dc_stream_status *dc_stream_get_status( + const struct dc_stream *dc_stream) +{ + uint8_t i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); + + for (i = 0; i < dc->current_context->stream_count; i++) + if (stream == dc->current_context->streams[i]) + return &dc->current_context->stream_status[i]; + + return NULL; +} + +/** + * Update the cursor attributes and set cursor surface address + */ +bool dc_stream_set_cursor_attributes( + const struct dc_stream *dc_stream, + const struct dc_cursor_attributes *attributes) +{ + int i; + struct core_stream *stream; + struct core_dc *core_dc; + struct resource_context *res_ctx; + bool ret = false; + + if (NULL == dc_stream) { + dm_error("DC: dc_stream is NULL!\n"); + return false; + } + if (NULL == attributes) { + dm_error("DC: attributes is NULL!\n"); + return false; + } + + stream = DC_STREAM_TO_CORE(dc_stream); + core_dc = DC_TO_CORE(stream->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == stream) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; + + if (ipp->funcs->ipp_cursor_set_attributes( + ipp, attributes)) + ret = true; + } + } + + return ret; +} + +bool dc_stream_set_cursor_position( + const struct dc_stream *dc_stream, + const struct dc_cursor_position *position) +{ + int i; + struct core_stream *stream; + struct core_dc *core_dc; + struct resource_context *res_ctx; + bool ret = false; + + if (NULL == dc_stream) { + dm_error("DC: dc_stream is NULL!\n"); + return false; + } + + if (NULL == position) { + dm_error("DC: cursor position is NULL!\n"); + return false; + } + + stream = DC_STREAM_TO_CORE(dc_stream); + core_dc = DC_TO_CORE(stream->ctx->dc); + res_ctx = &core_dc->current_context->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == stream) { + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct dc_cursor_mi_param param = { + .pixel_clk_khz = dc_stream->timing.pix_clk_khz, + .ref_clk_khz = 48000,/*todo refclk*/ + .viewport_x_start = pipe_ctx->scl_data.viewport.x, + .viewport_width = pipe_ctx->scl_data.viewport.width, + .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, + }; + + ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); + ret = true; + } + } + + return ret; +} + +uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) +{ + uint8_t i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); + struct resource_context *res_ctx = + &core_dc->current_context->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct timing_generator *tg = res_ctx->pipe_ctx[i].tg; + + if (res_ctx->pipe_ctx[i].stream != stream) + continue; + + return tg->funcs->get_frame_count(tg); + } + + return 0; +} + +uint32_t dc_stream_get_scanoutpos( + const struct dc_stream *dc_stream, + uint32_t *vbl, + uint32_t *position) +{ + uint8_t i; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); + struct resource_context *res_ctx = + &core_dc->current_context->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct timing_generator *tg = res_ctx->pipe_ctx[i].tg; + + if (res_ctx->pipe_ctx[i].stream != stream) + continue; + + return tg->funcs->get_scanoutpos(tg, vbl, position); + } + + return 0; +} + + +void dc_stream_log( + const struct dc_stream *stream, + struct dal_logger *dm_logger, + enum dc_log_type log_type) +{ + const struct core_stream *core_stream = + DC_STREAM_TO_CORE(stream); + + dm_logger_write(dm_logger, + log_type, + "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n", + core_stream, + core_stream->public.src.x, + core_stream->public.src.y, + core_stream->public.src.width, + core_stream->public.src.height, + core_stream->public.dst.x, + core_stream->public.dst.y, + core_stream->public.dst.width, + core_stream->public.dst.height); + dm_logger_write(dm_logger, + log_type, + "\tpix_clk_khz: %d, h_total: %d, v_total: %d\n", + core_stream->public.timing.pix_clk_khz, + core_stream->public.timing.h_total, + core_stream->public.timing.v_total); + dm_logger_write(dm_logger, + log_type, + "\tsink name: %s, serial: %d\n", + core_stream->sink->public.edid_caps.display_name, + core_stream->sink->public.edid_caps.serial_number); + dm_logger_write(dm_logger, + log_type, + "\tlink: %d\n", + core_stream->sink->link->public.link_index); +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_target.c b/drivers/gpu/drm/amd/display/dc/core/dc_target.c deleted file mode 100644 index 2d25b00b4bff..000000000000 --- a/drivers/gpu/drm/amd/display/dc/core/dc_target.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "core_types.h" -#include "hw_sequencer.h" -#include "resource.h" -#include "ipp.h" -#include "timing_generator.h" - -struct target { - struct core_target protected; - int ref_count; -}; - -#define DC_TARGET_TO_TARGET(dc_target) \ - container_of(dc_target, struct target, protected.public) -#define CORE_TARGET_TO_TARGET(core_target) \ - container_of(core_target, struct target, protected) - -static void construct( - struct core_target *target, - struct dc_context *ctx, - struct dc_stream *dc_streams[], - uint8_t stream_count) -{ - uint8_t i; - for (i = 0; i < stream_count; i++) { - target->public.streams[i] = dc_streams[i]; - dc_stream_retain(dc_streams[i]); - } - - target->ctx = ctx; - target->public.stream_count = stream_count; -} - -static void destruct(struct core_target *core_target) -{ - int i; - - for (i = 0; i < core_target->public.stream_count; i++) { - dc_stream_release( - (struct dc_stream *)core_target->public.streams[i]); - core_target->public.streams[i] = NULL; - } -} - -void dc_target_retain(const struct dc_target *dc_target) -{ - struct target *target = DC_TARGET_TO_TARGET(dc_target); - - ASSERT(target->ref_count > 0); - target->ref_count++; -} - -void dc_target_release(const struct dc_target *dc_target) -{ - struct target *target = DC_TARGET_TO_TARGET(dc_target); - struct core_target *protected = DC_TARGET_TO_CORE(dc_target); - - ASSERT(target->ref_count > 0); - target->ref_count--; - - if (target->ref_count == 0) { - destruct(protected); - dm_free(target); - } -} - -const struct dc_target_status *dc_target_get_status( - const struct dc_target* dc_target) -{ - uint8_t i; - struct core_target* target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *dc = DC_TO_CORE(target->ctx->dc); - - for (i = 0; i < dc->current_context->target_count; i++) - if (target == dc->current_context->targets[i]) - return &dc->current_context->target_status[i]; - - return NULL; -} - -struct dc_target *dc_create_target_for_streams( - struct dc_stream *dc_streams[], - uint8_t stream_count) -{ - struct core_stream *stream; - struct target *target; - - if (0 == stream_count) - goto target_alloc_fail; - - stream = DC_STREAM_TO_CORE(dc_streams[0]); - - target = dm_alloc(sizeof(struct target)); - - if (NULL == target) - goto target_alloc_fail; - - construct(&target->protected, stream->ctx, dc_streams, stream_count); - - target->ref_count++; - - return &target->protected.public; - -target_alloc_fail: - return NULL; -} - -bool dc_target_is_connected_to_sink( - const struct dc_target * dc_target, - const struct dc_sink *dc_sink) -{ - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - uint8_t i; - for (i = 0; i < target->public.stream_count; i++) { - if (target->public.streams[i]->sink == dc_sink) - return true; - } - return false; -} - -/** - * Update the cursor attributes and set cursor surface address - */ -bool dc_target_set_cursor_attributes( - struct dc_target *dc_target, - const struct dc_cursor_attributes *attributes) -{ - int i, j; - struct core_target *target; - struct core_dc *core_dc; - struct resource_context *res_ctx; - bool ret = false; - - if (NULL == dc_target) { - dm_error("DC: dc_target is NULL!\n"); - return false; - } - if (NULL == attributes) { - dm_error("DC: attributes is NULL!\n"); - return false; - } - - target = DC_TARGET_TO_CORE(dc_target); - core_dc = DC_TO_CORE(target->ctx->dc); - res_ctx = &core_dc->current_context->res_ctx; - - for (i = 0; i < dc_target->stream_count; i++) { - const struct dc_stream *stream = dc_target->streams[i]; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j]; - - if (&pipe_ctx->stream->public == stream) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; - - if (ipp->funcs->ipp_cursor_set_attributes( - ipp, attributes)) - ret = true; - } - } - } - - return ret; -} - -bool dc_target_set_cursor_position( - struct dc_target *dc_target, - const struct dc_cursor_position *position) -{ - int i, j; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); - struct resource_context *res_ctx = &core_dc->current_context->res_ctx; - bool ret = false; - - if (NULL == dc_target) { - dm_error("DC: dc_target is NULL!\n"); - return false; - } - - if (NULL == position) { - dm_error("DC: cursor position is NULL!\n"); - return false; - } - - for (i = 0; i < dc_target->stream_count; i++) { - const struct dc_stream *stream = dc_target->streams[i]; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[j]; - - if (&pipe_ctx->stream->public == stream) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct dc_cursor_mi_param param = { - .pixel_clk_khz = stream->timing.pix_clk_khz, - .ref_clk_khz = 48000,/*todo refclk*/ - .viewport_x_start = pipe_ctx->scl_data.viewport.x, - .viewport_width = pipe_ctx->scl_data.viewport.width, - .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, - }; - - ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); - ret = true; - } - } - } - - return ret; -} - -uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target) -{ - uint8_t i, j; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); - struct resource_context *res_ctx = - &core_dc->current_context->res_ctx; - - for (i = 0; i < target->public.stream_count; i++) { - for (j = 0; j < MAX_PIPES; j++) { - struct timing_generator *tg = res_ctx->pipe_ctx[j].tg; - - if (res_ctx->pipe_ctx[j].stream != - DC_STREAM_TO_CORE(target->public.streams[i])) - continue; - - return tg->funcs->get_frame_count(tg); - } - } - - return 0; -} - -uint32_t dc_target_get_scanoutpos( - const struct dc_target *dc_target, - uint32_t *vbl, - uint32_t *position) -{ - uint8_t i, j; - struct core_target *target = DC_TARGET_TO_CORE(dc_target); - struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc); - struct resource_context *res_ctx = - &core_dc->current_context->res_ctx; - - for (i = 0; i < target->public.stream_count; i++) { - for (j = 0; j < MAX_PIPES; j++) { - struct timing_generator *tg = res_ctx->pipe_ctx[j].tg; - - if (res_ctx->pipe_ctx[j].stream != - DC_STREAM_TO_CORE(target->public.streams[i])) - continue; - - return tg->funcs->get_scanoutpos(tg, vbl, position); - } - } - - return 0; -} - -void dc_target_log( - const struct dc_target *dc_target, - struct dal_logger *dm_logger, - enum dc_log_type log_type) -{ - int i; - - const struct core_target *core_target = - CONST_DC_TARGET_TO_CORE(dc_target); - - dm_logger_write(dm_logger, - log_type, - "core_target 0x%x: stream_count=%d\n", - core_target, - core_target->public.stream_count); - - for (i = 0; i < core_target->public.stream_count; i++) { - const struct core_stream *core_stream = - DC_STREAM_TO_CORE(core_target->public.streams[i]); - - dm_logger_write(dm_logger, - log_type, - "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n", - core_stream, - core_stream->public.src.x, - core_stream->public.src.y, - core_stream->public.src.width, - core_stream->public.src.height, - core_stream->public.dst.x, - core_stream->public.dst.y, - core_stream->public.dst.width, - core_stream->public.dst.height); - dm_logger_write(dm_logger, - log_type, - "\tpix_clk_khz: %d, h_total: %d, v_total: %d\n", - core_stream->public.timing.pix_clk_khz, - core_stream->public.timing.h_total, - core_stream->public.timing.v_total); - dm_logger_write(dm_logger, - log_type, - "\tsink name: %s, serial: %d\n", - core_stream->sink->public.edid_caps.display_name, - core_stream->sink->public.edid_caps.serial_number); - dm_logger_write(dm_logger, - log_type, - "\tlink: %d\n", - core_stream->sink->link->public.link_index); - } -} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e8cb7a4dee80..b814e7b76bbc 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -32,8 +32,8 @@ #include "gpio_types.h" #include "link_service_types.h" -#define MAX_TARGETS 6 #define MAX_SURFACES 3 +#define MAX_STREAMS 6 #define MAX_SINKS_PER_LINK 4 /******************************************************************************* @@ -41,7 +41,7 @@ ******************************************************************************/ struct dc_caps { - uint32_t max_targets; + uint32_t max_streams; uint32_t max_links; uint32_t max_audios; uint32_t max_slave_planes; @@ -139,7 +139,6 @@ struct dc_config { struct dc_debug { bool surface_visual_confirm; bool max_disp_clk; - bool target_trace; bool surface_trace; bool timing_trace; bool validation_trace; @@ -351,95 +350,91 @@ void dc_flip_surface_addrs(struct dc *dc, uint32_t count); /* - * Set up surface attributes and associate to a target - * The surfaces parameter is an absolute set of all surface active for the target. - * If no surfaces are provided, the target will be blanked; no memory read. + * Set up surface attributes and associate to a stream + * The surfaces parameter is an absolute set of all surface active for the stream. + * If no surfaces are provided, the stream will be blanked; no memory read. * Any flip related attribute changes must be done through this interface. * * After this call: - * Surfaces attributes are programmed and configured to be composed into target. + * Surfaces attributes are programmed and configured to be composed into stream. * This does not trigger a flip. No surface address is programmed. */ -bool dc_commit_surfaces_to_target( +bool dc_commit_surfaces_to_stream( struct dc *dc, const struct dc_surface **dc_surfaces, uint8_t surface_count, - struct dc_target *dc_target); + const struct dc_stream *stream); -bool dc_pre_update_surfaces_to_target( +bool dc_pre_update_surfaces_to_stream( struct dc *dc, const struct dc_surface *const *new_surfaces, uint8_t new_surface_count, - struct dc_target *dc_target); + const struct dc_stream *stream); -bool dc_post_update_surfaces_to_target( +bool dc_post_update_surfaces_to_stream( struct dc *dc); -void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates, - int surface_count, struct dc_target *dc_target); +void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, + int surface_count, const struct dc_stream *stream); /******************************************************************************* - * Target Interfaces + * Stream Interfaces ******************************************************************************/ -#define MAX_STREAM_NUM 1 +struct dc_stream { + const struct dc_sink *sink; + struct dc_crtc_timing timing; -struct dc_target { - uint8_t stream_count; - const struct dc_stream *streams[MAX_STREAM_NUM]; -}; + enum dc_color_space output_color_space; -/* - * Target status is returned from dc_target_get_status in order to get the - * the IRQ source, current frame counter and currently attached surfaces. - */ -struct dc_target_status { - int primary_otg_inst; - int cur_frame_count; - int surface_count; - const struct dc_surface *surfaces[MAX_SURFACE_NUM]; -}; + struct rect src; /* composition area */ + struct rect dst; /* stream addressable area */ -struct dc_target *dc_create_target_for_streams( - struct dc_stream *dc_streams[], - uint8_t stream_count); + struct audio_info audio_info; + + bool ignore_msa_timing_param; + + struct freesync_context freesync_ctx; + + const struct dc_transfer_func *out_transfer_func; + struct colorspace_transform gamut_remap_matrix; + struct csc_transform csc_color_matrix; + + /* TODO: dithering */ + /* TODO: custom INFO packets */ + /* TODO: ABM info (DMCU) */ + /* TODO: PSR info */ + /* TODO: CEA VIC */ +}; /* - * Get the current target status. + * Log the current stream state. */ -const struct dc_target_status *dc_target_get_status( - const struct dc_target* dc_target); - -void dc_target_retain(const struct dc_target *dc_target); -void dc_target_release(const struct dc_target *dc_target); -void dc_target_log( - const struct dc_target *dc_target, +void dc_stream_log( + const struct dc_stream *stream, struct dal_logger *dc_logger, enum dc_log_type log_type); -uint8_t dc_get_current_target_count(const struct dc *dc); -struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i); +uint8_t dc_get_current_stream_count(const struct dc *dc); +struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i); -bool dc_target_is_connected_to_sink( - const struct dc_target *dc_target, - const struct dc_sink *dc_sink); - -uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target); +/* + * Return the current frame counter. + */ +uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream); /* TODO: Return parsed values rather than direct register read * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) * being refactored properly to be dce-specific */ -uint32_t dc_target_get_scanoutpos( - const struct dc_target *dc_target, - uint32_t *vbl, - uint32_t *position); +uint32_t dc_stream_get_scanoutpos( + const struct dc_stream *stream, uint32_t *vbl, uint32_t *position); /* - * Structure to store surface/target associations for validation + * Structure to store surface/stream associations for validation */ struct dc_validation_set { - const struct dc_target *target; + const struct dc_stream *stream; const struct dc_surface *surfaces[MAX_SURFACES]; uint8_t surface_count; }; @@ -456,8 +451,8 @@ bool dc_validate_resources( uint8_t set_count); /* - * This function takes a target and checks if it is guaranteed to be supported. - * Guaranteed means that MAX_COFUNC*target is supported. + * This function takes a stream and checks if it is guaranteed to be supported. + * Guaranteed means that MAX_COFUNC similar streams are supported. * * After this call: * No hardware is programmed for call. Only validation is done. @@ -465,49 +460,20 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - const struct dc_target *dc_target); + const struct dc_stream *stream); /* - * Set up streams and links associated to targets to drive sinks - * The targets parameter is an absolute set of all active targets. + * Set up streams and links associated to drive sinks + * The streams parameter is an absolute set of all active streams. * * After this call: * Phy, Encoder, Timing Generator are programmed and enabled. - * New targets are enabled with blank stream; no memory read. + * New streams are enabled with blank stream; no memory read. */ -bool dc_commit_targets( +bool dc_commit_streams( struct dc *dc, - struct dc_target *targets[], - uint8_t target_count); - -/******************************************************************************* - * Stream Interfaces - ******************************************************************************/ -struct dc_stream { - const struct dc_sink *sink; - struct dc_crtc_timing timing; - - enum dc_color_space output_color_space; - - struct rect src; /* viewport in target space*/ - struct rect dst; /* stream addressable area */ - - struct audio_info audio_info; - - bool ignore_msa_timing_param; - - struct freesync_context freesync_ctx; - - const struct dc_transfer_func *out_transfer_func; - struct colorspace_transform gamut_remap_matrix; - struct csc_transform csc_color_matrix; - - /* TODO: dithering */ - /* TODO: custom INFO packets */ - /* TODO: ABM info (DMCU) */ - /* TODO: PSR info */ - /* TODO: CEA VIC */ -}; + const struct dc_stream *streams[], + uint8_t stream_count); /** * Create a new default stream for the requested sink @@ -518,6 +484,10 @@ void dc_stream_retain(const struct dc_stream *dc_stream); void dc_stream_release(const struct dc_stream *dc_stream); struct dc_stream_status { + int primary_otg_inst; + int surface_count; + const struct dc_surface *surfaces[MAX_SURFACE_NUM]; + /* * link this stream passes through */ @@ -691,15 +661,15 @@ struct dc_sink_init_data { struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); /******************************************************************************* - * Cursor interfaces - To manages the cursor within a target + * Cursor interfaces - To manages the cursor within a stream ******************************************************************************/ /* TODO: Deprecated once we switch to dc_set_cursor_position */ -bool dc_target_set_cursor_attributes( - struct dc_target *dc_target, +bool dc_stream_set_cursor_attributes( + const struct dc_stream *stream, const struct dc_cursor_attributes *attributes); -bool dc_target_set_cursor_position( - struct dc_target *dc_target, +bool dc_stream_set_cursor_position( + const struct dc_stream *stream, const struct dc_cursor_position *position); /* Newer interfaces */ @@ -708,36 +678,6 @@ struct dc_cursor { struct dc_cursor_attributes attributes; }; -/* - * Create a new cursor with default values for a given target. - */ -struct dc_cursor *dc_create_cursor_for_target( - const struct dc *dc, - struct dc_target *dc_target); - -/** - * Commit cursor attribute changes such as pixel format and dimensions and - * surface address. - * - * After this call: - * Cursor address and format is programmed to the new values. - * Cursor position is unmodified. - */ -bool dc_commit_cursor( - const struct dc *dc, - struct dc_cursor *cursor); - -/* - * Optimized cursor position update - * - * After this call: - * Cursor position will be programmed as well as enable/disable bit. - */ -bool dc_set_cursor_position( - const struct dc *dc, - struct dc_cursor *cursor, - struct dc_cursor_position *pos); - /******************************************************************************* * Interrupt interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index ae9fcca121e6..242dd7b3b6b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -34,7 +34,6 @@ /* forward declarations */ struct dc_surface; -struct dc_target; struct dc_stream; struct dc_link; struct dc_sink; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 082f1f053a3a..ae0e7eac2c9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -741,53 +741,48 @@ static enum dc_status validate_mapped_resource( struct validate_context *context) { enum dc_status status = DC_OK; - uint8_t i, j, k; + uint8_t i, j; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_link *link = stream->sink->link; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); + /* TODO: validate audio ASIC caps, encoder */ + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); + resource_build_info_frame(pipe_ctx); - /* do not need to validate non root pipes */ - break; - } + /* do not need to validate non root pipes */ + break; } } @@ -818,9 +813,9 @@ static bool dce100_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].target->streams[0]->src.width + != set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].target->streams[0]->src.height) + != set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) @@ -846,9 +841,9 @@ enum dc_status dce100_validate_with_context( context->res_ctx.pool = dc->res_pool; for (i = 0; i < set_count; i++) { - context->targets[i] = DC_TARGET_TO_CORE(set[i].target); - dc_target_retain(&context->targets[i]->public); - context->target_count++; + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } result = resource_map_pool_resources(dc, context); @@ -858,7 +853,7 @@ enum dc_status dce100_validate_with_context( if (!resource_validate_attach_surfaces( set, set_count, dc->current_context, context)) { - DC_ERROR("Failed to attach surface to target!\n"); + DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -876,16 +871,16 @@ enum dc_status dce100_validate_with_context( enum dc_status dce100_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; context->res_ctx.pool = dc->res_pool; - context->targets[0] = DC_TARGET_TO_CORE(dc_target); - dc_target_retain(&context->targets[0]->public); - context->target_count++; + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; result = resource_map_pool_resources(dc, context); @@ -896,8 +891,8 @@ enum dc_status dce100_validate_guaranteed( result = validate_mapped_resource(dc, context); if (result == DC_OK) { - validate_guaranteed_copy_target( - context, dc->public.caps.max_targets); + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 751dbb88c265..415b12accd2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -753,7 +753,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->public.timing.h_total, stream->public.timing.v_total, stream->public.timing.pix_clk_khz, - context->target_count); + context->stream_count); return DC_OK; } @@ -1055,7 +1055,7 @@ static void reset_single_pipe_hw_ctx( } pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); pipe_ctx->mi->funcs->free_mem_input( - pipe_ctx->mi, context->target_count); + pipe_ctx->mi, context->stream_count); resource_unreference_clock_source( &context->res_ctx, &pipe_ctx->clock_source); @@ -1254,7 +1254,7 @@ enum dc_status dce110_apply_ctx_to_hw( dc->hwss.reset_hw_ctx_wrap(dc, context); /* Skip applying if no targets */ - if (context->target_count <= 0) + if (context->stream_count <= 0) return DC_OK; if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { @@ -1761,7 +1761,7 @@ static void dce110_power_on_pipe_if_needed( pipe_ctx->stream->public.timing.h_total, pipe_ctx->stream->public.timing.v_total, pipe_ctx->stream->public.timing.pix_clk_khz, - context->target_count); + context->stream_count); /* TODO unhardcode*/ color_space_to_black_color(dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 968ee99003fc..cfbb4ef21f8b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -817,58 +817,53 @@ static enum dc_status validate_mapped_resource( struct validate_context *context) { enum dc_status status = DC_OK; - uint8_t i, j, k; + uint8_t i, j; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_link *link = stream->sink->link; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (!is_surface_pixel_format_supported(pipe_ctx, - context->res_ctx.pool->underlay_pipe_index)) - return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; + if (!is_surface_pixel_format_supported(pipe_ctx, + context->res_ctx.pool->underlay_pipe_index)) + return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ + /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); + resource_build_info_frame(pipe_ctx); - /* do not need to validate non root pipes */ - break; - } + /* do not need to validate non root pipes */ + break; } } @@ -901,9 +896,9 @@ enum dc_status dce110_validate_bandwidth( dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: %dx%d@%d Bandwidth validation failed!\n", __func__, - context->targets[0]->public.streams[0]->timing.h_addressable, - context->targets[0]->public.streams[0]->timing.v_addressable, - context->targets[0]->public.streams[0]->timing.pix_clk_khz); + context->streams[0]->public.timing.h_addressable, + context->streams[0]->public.timing.v_addressable, + context->streams[0]->public.timing.pix_clk_khz); if (memcmp(&dc->current_context->bw_results, &context->bw_results, sizeof(context->bw_results))) { @@ -972,9 +967,9 @@ static bool dce110_validate_surface_sets( return false; if (set[i].surfaces[0]->src_rect.width - != set[i].target->streams[0]->src.width + != set[i].stream->src.width || set[i].surfaces[0]->src_rect.height - != set[i].target->streams[0]->src.height) + != set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) @@ -988,7 +983,7 @@ static bool dce110_validate_surface_sets( || set[i].surfaces[1]->src_rect.height > 1080) return false; - if (set[i].target->streams[0]->timing.pixel_encoding != PIXEL_ENCODING_RGB) + if (set[i].stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) return false; } } @@ -1012,9 +1007,9 @@ enum dc_status dce110_validate_with_context( context->res_ctx.pool = dc->res_pool; for (i = 0; i < set_count; i++) { - context->targets[i] = DC_TARGET_TO_CORE(set[i].target); - dc_target_retain(&context->targets[i]->public); - context->target_count++; + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } result = resource_map_pool_resources(dc, context); @@ -1024,7 +1019,7 @@ enum dc_status dce110_validate_with_context( if (!resource_validate_attach_surfaces( set, set_count, dc->current_context, context)) { - DC_ERROR("Failed to attach surface to target!\n"); + DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -1042,16 +1037,16 @@ enum dc_status dce110_validate_with_context( enum dc_status dce110_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; context->res_ctx.pool = dc->res_pool; - context->targets[0] = DC_TARGET_TO_CORE(dc_target); - dc_target_retain(&context->targets[0]->public); - context->target_count++; + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; result = resource_map_pool_resources(dc, context); @@ -1062,8 +1057,8 @@ enum dc_status dce110_validate_guaranteed( result = validate_mapped_resource(dc, context); if (result == DC_OK) { - validate_guaranteed_copy_target( - context, dc->public.caps.max_targets); + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 7fca2eb188cf..64fae91dd5eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -779,54 +779,49 @@ static enum dc_status validate_mapped_resource( struct validate_context *context) { enum dc_status status = DC_OK; - uint8_t i, j, k; + uint8_t i, j; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_link *link = stream->sink->link; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ + /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); + resource_build_info_frame(pipe_ctx); - /* do not need to validate non root pipes */ - break; - } + /* do not need to validate non root pipes */ + break; } } @@ -917,45 +912,40 @@ enum dc_status resource_map_phy_clock_resources( const struct core_dc *dc, struct validate_context *context) { - uint8_t i, j, k; + uint8_t i, j; /* acquire new resources */ - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) - pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; - else - pipe_ctx->clock_source = - find_matching_pll(&context->res_ctx, - stream); + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + context->res_ctx.pool->dp_clock_source; + else + pipe_ctx->clock_source = + find_matching_pll(&context->res_ctx, + stream); - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; - resource_reference_clock_source( - &context->res_ctx, - pipe_ctx->clock_source); + resource_reference_clock_source( + &context->res_ctx, + pipe_ctx->clock_source); - /* only one cs per stream regardless of mpo */ - break; - } + /* only one cs per stream regardless of mpo */ + break; } } @@ -976,9 +966,9 @@ static bool dce112_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].target->streams[0]->src.width + != set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].target->streams[0]->src.height) + != set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) @@ -1004,9 +994,9 @@ enum dc_status dce112_validate_with_context( context->res_ctx.pool = dc->res_pool; for (i = 0; i < set_count; i++) { - context->targets[i] = DC_TARGET_TO_CORE(set[i].target); - dc_target_retain(&context->targets[i]->public); - context->target_count++; + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } result = resource_map_pool_resources(dc, context); @@ -1016,7 +1006,7 @@ enum dc_status dce112_validate_with_context( if (!resource_validate_attach_surfaces( set, set_count, dc->current_context, context)) { - DC_ERROR("Failed to attach surface to target!\n"); + DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -1034,16 +1024,16 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; context->res_ctx.pool = dc->res_pool; - context->targets[0] = DC_TARGET_TO_CORE(dc_target); - dc_target_retain(&context->targets[0]->public); - context->target_count++; + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; result = resource_map_pool_resources(dc, context); @@ -1054,8 +1044,8 @@ enum dc_status dce112_validate_guaranteed( result = validate_mapped_resource(dc, context); if (result == DC_OK) { - validate_guaranteed_copy_target( - context, dc->public.caps.max_targets); + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index f21eb57857d4..faa8c45a3544 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -43,7 +43,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context); enum dc_status dce112_validate_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index e2bfa7efce1c..bee3a41ffe9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -731,54 +731,49 @@ static enum dc_status validate_mapped_resource( struct validate_context *context) { enum dc_status status = DC_OK; - uint8_t i, j, k; + uint8_t i, j; - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_link *link = stream->sink->link; - - if (resource_is_stream_unchanged(dc->current_context, stream)) - continue; + if (resource_is_stream_unchanged(dc->current_context, stream)) + continue; - for (k = 0; k < MAX_PIPES; k++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[k]; + for (j = 0; j < MAX_PIPES; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; - if (context->res_ctx.pipe_ctx[k].stream != stream) - continue; + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, + pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ + /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); + status = dc_link_validate_mode_timing(stream, + link, + &stream->public.timing); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); + resource_build_info_frame(pipe_ctx); - /* do not need to validate non root pipes */ - break; - } + /* do not need to validate non root pipes */ + break; } } @@ -810,9 +805,9 @@ static bool dce80_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].target->streams[0]->src.width + != set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].target->streams[0]->src.height) + != set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) @@ -838,9 +833,9 @@ enum dc_status dce80_validate_with_context( context->res_ctx.pool = dc->res_pool; for (i = 0; i < set_count; i++) { - context->targets[i] = DC_TARGET_TO_CORE(set[i].target); - dc_target_retain(&context->targets[i]->public); - context->target_count++; + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; } result = resource_map_pool_resources(dc, context); @@ -850,7 +845,7 @@ enum dc_status dce80_validate_with_context( if (!resource_validate_attach_surfaces( set, set_count, dc->current_context, context)) { - DC_ERROR("Failed to attach surface to target!\n"); + DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -868,16 +863,16 @@ enum dc_status dce80_validate_with_context( enum dc_status dce80_validate_guaranteed( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; context->res_ctx.pool = dc->res_pool; - context->targets[0] = DC_TARGET_TO_CORE(dc_target); - dc_target_retain(&context->targets[0]->public); - context->target_count++; + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; result = resource_map_pool_resources(dc, context); @@ -888,8 +883,8 @@ enum dc_status dce80_validate_guaranteed( result = validate_mapped_resource(dc, context); if (result == DC_OK) { - validate_guaranteed_copy_target( - context, dc->public.caps.max_targets); + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index b5a5207a4df0..7a6444dc2957 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -21,7 +21,6 @@ struct core_dc { uint8_t link_count; struct core_link *links[MAX_PIPES * 2]; - /* TODO: determine max number of targets*/ struct validate_context *current_context; struct validate_context *temp_flip_context; struct validate_context *scratch_val_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index c2d35c2c28bf..66bfcdb57c4c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,21 +32,10 @@ #include "dc_bios_types.h" struct core_stream; -/********* core_target *************/ - -#define CONST_DC_TARGET_TO_CORE(dc_target) \ - container_of(dc_target, const struct core_target, public) -#define DC_TARGET_TO_CORE(dc_target) \ - container_of(dc_target, struct core_target, public) #define MAX_PIPES 6 #define MAX_CLOCK_SOURCES 7 -struct core_target { - struct dc_target public; - - struct dc_context *ctx; -}; /********* core_surface **********/ #define DC_SURFACE_TO_CORE(dc_surface) \ @@ -215,7 +204,7 @@ struct resource_funcs { enum dc_status (*validate_guaranteed)( const struct core_dc *dc, - const struct dc_target *dc_target, + const struct dc_stream *stream, struct validate_context *context); enum dc_status (*validate_bandwidth)( @@ -312,9 +301,9 @@ struct resource_context { }; struct validate_context { - struct core_target *targets[MAX_PIPES]; - struct dc_target_status target_status[MAX_PIPES]; - uint8_t target_count; + struct core_stream *streams[MAX_PIPES]; + struct dc_stream_status stream_status[MAX_PIPES]; + uint8_t stream_count; struct resource_context res_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index adf297ec33b6..d96c64bb0a70 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -118,25 +118,26 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( bool resource_attach_surfaces_to_context( const struct dc_surface *const *surfaces, int surface_count, - const struct dc_target *dc_target, + const struct dc_stream *dc_stream, struct validate_context *context); struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx); bool resource_is_stream_unchanged( - const struct validate_context *old_context, struct core_stream *stream); + const struct validate_context *old_context, const struct core_stream *stream); + +bool is_stream_unchanged( + const struct core_stream *old_stream, const struct core_stream *stream); -bool is_target_unchanged( - const struct core_target *old_target, const struct core_target *target); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, const struct validate_context *old_context, struct validate_context *context); -void validate_guaranteed_copy_target( +void validate_guaranteed_copy_streams( struct validate_context *context, - int max_targets); + int max_streams); void resource_validate_ctx_update_pointer_after_copy( const struct validate_context *src_ctx, -- GitLab From 457b74cb3773a1950e49c2d4826d1b295c59bdf1 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 11 Jan 2017 15:52:06 -0500 Subject: [PATCH 0181/2898] drm/amd/display: Null check clock source. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 55d96656e54b..b0ac94d673c4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -74,7 +74,8 @@ void dp_enable_link_phy( if (pipes[i].stream != NULL && pipes[i].stream->sink != NULL && pipes[i].stream->sink->link == link) { - if (pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + if (pipes[i].clock_source != NULL && + pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { pipes[i].clock_source = dp_cs; pipes[i].pix_clk_params.requested_pix_clk = pipes[i].stream->public.timing.pix_clk_khz; -- GitLab From fcd2f4bf8bbe73ac860d1be275a22a54a8d8d385 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Thu, 5 Jan 2017 17:12:20 -0500 Subject: [PATCH 0182/2898] drm/amd/display: Output Transfer Function Regamma Refactor - Create translation function to translate logical format to hw format - Refactor to use transfer function in dc instead of input gamma Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/basics/fixpt31_32.c | 9 + drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 +- .../drm/amd/display/dc/calcs/gamma_calcs.c | 1481 ----------------- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +- drivers/gpu/drm/amd/display/dc/dc.h | 11 +- .../display/dc/dce110/dce110_hw_sequencer.c | 440 ++++- .../gpu/drm/amd/display/dc/inc/gamma_calcs.h | 20 - drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 2 - .../gpu/drm/amd/display/include/fixed31_32.h | 8 + 9 files changed, 466 insertions(+), 1517 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 5a6e46843502..546ed67c6f83 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -246,6 +246,15 @@ struct fixed31_32 dal_fixed31_32_add( return res; } +struct fixed31_32 dal_fixed31_32_add_int( + struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_add( + arg1, + dal_fixed31_32_from_int(arg2)); +} + struct fixed31_32 dal_fixed31_32_sub_int( struct fixed31_32 arg1, int32_t arg2) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 4001933e7808..4bb08aea6a03 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,7 +3,7 @@ # It calculates Bandwidth and Watermarks values for HW programming # -BW_CALCS = bandwidth_calcs.o bw_fixed.o gamma_calcs.o +BW_CALCS = bandwidth_calcs.o bw_fixed.o AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c deleted file mode 100644 index fd300db833c7..000000000000 --- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c +++ /dev/null @@ -1,1481 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "gamma_calcs.h" - -struct curve_config { - uint32_t offset; - int8_t segments[16]; - int8_t begin; -}; - -static bool build_custom_float( - struct fixed31_32 value, - const struct custom_float_format *format, - bool *negative, - uint32_t *mantissa, - uint32_t *exponenta) -{ - uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; - - const struct fixed31_32 mantissa_constant_plus_max_fraction = - dal_fixed31_32_from_fraction( - (1LL << (format->mantissa_bits + 1)) - 1, - 1LL << format->mantissa_bits); - - struct fixed31_32 mantiss; - - if (dal_fixed31_32_eq( - value, - dal_fixed31_32_zero)) { - *negative = false; - *mantissa = 0; - *exponenta = 0; - return true; - } - - if (dal_fixed31_32_lt( - value, - dal_fixed31_32_zero)) { - *negative = format->sign; - value = dal_fixed31_32_neg(value); - } else { - *negative = false; - } - - if (dal_fixed31_32_lt( - value, - dal_fixed31_32_one)) { - uint32_t i = 1; - - do { - value = dal_fixed31_32_shl(value, 1); - ++i; - } while (dal_fixed31_32_lt( - value, - dal_fixed31_32_one)); - - --i; - - if (exp_offset <= i) { - *mantissa = 0; - *exponenta = 0; - return true; - } - - *exponenta = exp_offset - i; - } else if (dal_fixed31_32_le( - mantissa_constant_plus_max_fraction, - value)) { - uint32_t i = 1; - - do { - value = dal_fixed31_32_shr(value, 1); - ++i; - } while (dal_fixed31_32_lt( - mantissa_constant_plus_max_fraction, - value)); - - *exponenta = exp_offset + i - 1; - } else { - *exponenta = exp_offset; - } - - mantiss = dal_fixed31_32_sub( - value, - dal_fixed31_32_one); - - if (dal_fixed31_32_lt( - mantiss, - dal_fixed31_32_zero) || - dal_fixed31_32_lt( - dal_fixed31_32_one, - mantiss)) - mantiss = dal_fixed31_32_zero; - else - mantiss = dal_fixed31_32_shl( - mantiss, - format->mantissa_bits); - - *mantissa = dal_fixed31_32_floor(mantiss); - - return true; -} - -static bool setup_custom_float( - const struct custom_float_format *format, - bool negative, - uint32_t mantissa, - uint32_t exponenta, - uint32_t *result) -{ - uint32_t i = 0; - uint32_t j = 0; - - uint32_t value = 0; - - /* verification code: - * once calculation is ok we can remove it - */ - - const uint32_t mantissa_mask = - (1 << (format->mantissa_bits + 1)) - 1; - - const uint32_t exponenta_mask = - (1 << (format->exponenta_bits + 1)) - 1; - - if (mantissa & ~mantissa_mask) { - BREAK_TO_DEBUGGER(); - mantissa = mantissa_mask; - } - - if (exponenta & ~exponenta_mask) { - BREAK_TO_DEBUGGER(); - exponenta = exponenta_mask; - } - - /* end of verification code */ - - while (i < format->mantissa_bits) { - uint32_t mask = 1 << i; - - if (mantissa & mask) - value |= mask; - - ++i; - } - - while (j < format->exponenta_bits) { - uint32_t mask = 1 << j; - - if (exponenta & mask) - value |= mask << i; - - ++j; - } - - if (negative && format->sign) - value |= 1 << (i + j); - - *result = value; - - return true; -} - -static bool build_hw_curve_configuration( - const struct curve_config *curve_config, - struct gamma_curve *gamma_curve, - struct curve_points *curve_points, - struct hw_x_point *points, - uint32_t *number_of_points) -{ - const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments); - - int8_t i; - - uint8_t segments_calculation[8] = { 0 }; - - struct fixed31_32 region1 = dal_fixed31_32_zero; - struct fixed31_32 region2; - struct fixed31_32 increment; - - uint32_t index = 0; - uint32_t segments = 0; - uint32_t max_number; - - int8_t num_regions = 0; - - bool result = false; - - if (!number_of_points) { - BREAK_TO_DEBUGGER(); - return false; - } - - max_number = *number_of_points; - - i = 0; - - while (i != max_regions_number) { - gamma_curve[i].offset = 0; - gamma_curve[i].segments_num = 0; - - ++i; - } - - i = 0; - - while (i != max_regions_number) { - /* number should go in uninterruptible sequence */ - if (curve_config->segments[i] == -1) - break; - - ASSERT(curve_config->segments[i] >= 0); - - segments += (1 << curve_config->segments[i]); - ++num_regions; - - ++i; - } - - if (segments > max_number) { - BREAK_TO_DEBUGGER(); - } else { - int32_t divisor; - uint32_t offset = 0; - int8_t begin = curve_config->begin; - int32_t region_number = 0; - - i = begin; - - while ((index < max_number) && - (region_number < max_regions_number) && - (i < (begin + num_regions))) { - int32_t j = 0; - - segments = curve_config->segments[region_number]; - divisor = 1 << segments; - - if (segments == -1) { - if (i > 0) { - region1 = dal_fixed31_32_shl( - dal_fixed31_32_one, - i - 1); - region2 = dal_fixed31_32_shl( - dal_fixed31_32_one, - i); - } else { - region1 = dal_fixed31_32_shr( - dal_fixed31_32_one, - -(i - 1)); - region2 = dal_fixed31_32_shr( - dal_fixed31_32_one, - -i); - } - - break; - } - - if (i > -1) { - region1 = dal_fixed31_32_shl( - dal_fixed31_32_one, - i); - region2 = dal_fixed31_32_shl( - dal_fixed31_32_one, - i + 1); - } else { - region1 = dal_fixed31_32_shr( - dal_fixed31_32_one, - -i); - region2 = dal_fixed31_32_shr( - dal_fixed31_32_one, - -(i + 1)); - } - - gamma_curve[region_number].offset = offset; - gamma_curve[region_number].segments_num = segments; - - offset += divisor; - - ++segments_calculation[segments]; - - increment = dal_fixed31_32_div_int( - dal_fixed31_32_sub( - region2, - region1), - divisor); - - points[index].x = region1; - points[index].adjusted_x = region1; - - ++index; - ++region_number; - - while ((index < max_number) && (j < divisor - 1)) { - region1 = dal_fixed31_32_add( - region1, - increment); - - points[index].x = region1; - points[index].adjusted_x = region1; - - ++index; - ++j; - } - - ++i; - } - - points[index].x = region1; - points[index].adjusted_x = region1; - - *number_of_points = index; - - result = true; - } - - curve_points[0].x = points[0].adjusted_x; - curve_points[0].offset = dal_fixed31_32_zero; - - curve_points[1].x = points[index - 1].adjusted_x; - curve_points[1].offset = dal_fixed31_32_zero; - - curve_points[2].x = points[index].adjusted_x; - curve_points[2].offset = dal_fixed31_32_zero; - - return result; -} - -static bool setup_distribution_points_pq( - struct gamma_curve *arr_curve_points, - struct curve_points *arr_points, - uint32_t *hw_points_num, - struct hw_x_point *coordinates_x, - enum surface_pixel_format format) -{ - struct curve_config cfg; - - cfg.offset = 0; - cfg.segments[0] = 2; - cfg.segments[1] = 2; - cfg.segments[2] = 2; - cfg.segments[3] = 2; - cfg.segments[4] = 2; - cfg.segments[5] = 2; - cfg.segments[6] = 3; - cfg.segments[7] = 4; - cfg.segments[8] = 4; - cfg.segments[9] = 4; - cfg.segments[10] = 4; - cfg.segments[11] = 5; - cfg.segments[12] = 5; - cfg.segments[13] = 5; - cfg.segments[14] = 5; - cfg.segments[15] = 5; - - if (format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || - format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) - cfg.begin = -11; - else - cfg.begin = -16; - - if (!build_hw_curve_configuration( - &cfg, arr_curve_points, - arr_points, - coordinates_x, hw_points_num)) { - ASSERT_CRITICAL(false); - return false; - } - return true; -} - -static bool setup_distribution_points( - struct gamma_curve *arr_curve_points, - struct curve_points *arr_points, - uint32_t *hw_points_num, - struct hw_x_point *coordinates_x) -{ - struct curve_config cfg; - - cfg.offset = 0; - cfg.segments[0] = 3; - cfg.segments[1] = 4; - cfg.segments[2] = 4; - cfg.segments[3] = 4; - cfg.segments[4] = 4; - cfg.segments[5] = 4; - cfg.segments[6] = 4; - cfg.segments[7] = 4; - cfg.segments[8] = 5; - cfg.segments[9] = 5; - cfg.segments[10] = 0; - cfg.segments[11] = -1; - cfg.segments[12] = -1; - cfg.segments[13] = -1; - cfg.segments[14] = -1; - cfg.segments[15] = -1; - - cfg.begin = -10; - - if (!build_hw_curve_configuration( - &cfg, arr_curve_points, - arr_points, - coordinates_x, hw_points_num)) { - ASSERT_CRITICAL(false); - return false; - } - return true; -} - -struct dividers { - struct fixed31_32 divider1; - struct fixed31_32 divider2; - struct fixed31_32 divider3; -}; - -static void build_regamma_coefficients(struct gamma_coefficients *coefficients) -{ - /* sRGB should apply 2.4 */ - static const int32_t numerator01[3] = { 31308, 31308, 31308 }; - static const int32_t numerator02[3] = { 12920, 12920, 12920 }; - static const int32_t numerator03[3] = { 55, 55, 55 }; - static const int32_t numerator04[3] = { 55, 55, 55 }; - static const int32_t numerator05[3] = { 2400, 2400, 2400 }; - - const int32_t *numerator1; - const int32_t *numerator2; - const int32_t *numerator3; - const int32_t *numerator4; - const int32_t *numerator5; - - uint32_t i = 0; - - numerator1 = numerator01; - numerator2 = numerator02; - numerator3 = numerator03; - numerator4 = numerator04; - numerator5 = numerator05; - - do { - coefficients->a0[i] = dal_fixed31_32_from_fraction( - numerator1[i], 10000000); - coefficients->a1[i] = dal_fixed31_32_from_fraction( - numerator2[i], 1000); - coefficients->a2[i] = dal_fixed31_32_from_fraction( - numerator3[i], 1000); - coefficients->a3[i] = dal_fixed31_32_from_fraction( - numerator4[i], 1000); - coefficients->user_gamma[i] = dal_fixed31_32_from_fraction( - numerator5[i], 1000); - - ++i; - } while (i != ARRAY_SIZE(coefficients->a0)); -} - -static struct fixed31_32 translate_from_linear_space( - struct fixed31_32 arg, - struct fixed31_32 a0, - struct fixed31_32 a1, - struct fixed31_32 a2, - struct fixed31_32 a3, - struct fixed31_32 gamma) -{ - const struct fixed31_32 one = dal_fixed31_32_from_int(1); - - if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0))) - return dal_fixed31_32_sub( - a2, - dal_fixed31_32_mul( - dal_fixed31_32_add( - one, - a3), - dal_fixed31_32_pow( - dal_fixed31_32_neg(arg), - dal_fixed31_32_recip(gamma)))); - else if (dal_fixed31_32_le(a0, arg)) - return dal_fixed31_32_sub( - dal_fixed31_32_mul( - dal_fixed31_32_add( - one, - a3), - dal_fixed31_32_pow( - arg, - dal_fixed31_32_recip(gamma))), - a2); - else - return dal_fixed31_32_mul( - arg, - a1); -} - -static inline struct fixed31_32 translate_from_linear_space_ex( - struct fixed31_32 arg, - struct gamma_coefficients *coeff, - uint32_t color_index) -{ - return translate_from_linear_space( - arg, - coeff->a0[color_index], - coeff->a1[color_index], - coeff->a2[color_index], - coeff->a3[color_index], - coeff->user_gamma[color_index]); -} - -static bool find_software_points( - const struct gamma_pixel *axis_x_256, - struct fixed31_32 hw_point, - enum channel_name channel, - uint32_t *index_to_start, - uint32_t *index_left, - uint32_t *index_right, - enum hw_point_position *pos) -{ - const uint32_t max_number = INPUT_LUT_ENTRIES + 3; - - struct fixed31_32 left, right; - - uint32_t i = *index_to_start; - - while (i < max_number) { - if (channel == CHANNEL_NAME_RED) { - left = axis_x_256[i].r; - - if (i < max_number - 1) - right = axis_x_256[i + 1].r; - else - right = axis_x_256[max_number - 1].r; - } else if (channel == CHANNEL_NAME_GREEN) { - left = axis_x_256[i].g; - - if (i < max_number - 1) - right = axis_x_256[i + 1].g; - else - right = axis_x_256[max_number - 1].g; - } else { - left = axis_x_256[i].b; - - if (i < max_number - 1) - right = axis_x_256[i + 1].b; - else - right = axis_x_256[max_number - 1].b; - } - - if (dal_fixed31_32_le(left, hw_point) && - dal_fixed31_32_le(hw_point, right)) { - *index_to_start = i; - *index_left = i; - - if (i < max_number - 1) - *index_right = i + 1; - else - *index_right = max_number - 1; - - *pos = HW_POINT_POSITION_MIDDLE; - - return true; - } else if ((i == *index_to_start) && - dal_fixed31_32_le(hw_point, left)) { - *index_to_start = i; - *index_left = i; - *index_right = i; - - *pos = HW_POINT_POSITION_LEFT; - - return true; - } else if ((i == max_number - 1) && - dal_fixed31_32_le(right, hw_point)) { - *index_to_start = i; - *index_left = i; - *index_right = i; - - *pos = HW_POINT_POSITION_RIGHT; - - return true; - } - - ++i; - } - - return false; -} - -static bool build_custom_gamma_mapping_coefficients_worker( - struct pixel_gamma_point *coeff, - const struct hw_x_point *coordinates_x, - const struct gamma_pixel *axis_x_256, - enum channel_name channel, - uint32_t number_of_points, - enum surface_pixel_format pixel_format) -{ - uint32_t i = 0; - - while (i <= number_of_points) { - struct fixed31_32 coord_x; - - uint32_t index_to_start = 0; - uint32_t index_left = 0; - uint32_t index_right = 0; - - enum hw_point_position hw_pos; - - struct gamma_point *point; - - struct fixed31_32 left_pos; - struct fixed31_32 right_pos; - - /* - * TODO: confirm enum in surface_pixel_format - * if (pixel_format == PIXEL_FORMAT_FP16) - *coord_x = coordinates_x[i].adjusted_x; - *else - */ - if (channel == CHANNEL_NAME_RED) - coord_x = coordinates_x[i].regamma_y_red; - else if (channel == CHANNEL_NAME_GREEN) - coord_x = coordinates_x[i].regamma_y_green; - else - coord_x = coordinates_x[i].regamma_y_blue; - - if (!find_software_points( - axis_x_256, coord_x, channel, - &index_to_start, &index_left, &index_right, &hw_pos)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (index_left >= INPUT_LUT_ENTRIES + 3) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (index_right >= INPUT_LUT_ENTRIES + 3) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (channel == CHANNEL_NAME_RED) { - point = &coeff[i].r; - - left_pos = axis_x_256[index_left].r; - right_pos = axis_x_256[index_right].r; - } else if (channel == CHANNEL_NAME_GREEN) { - point = &coeff[i].g; - - left_pos = axis_x_256[index_left].g; - right_pos = axis_x_256[index_right].g; - } else { - point = &coeff[i].b; - - left_pos = axis_x_256[index_left].b; - right_pos = axis_x_256[index_right].b; - } - - if (hw_pos == HW_POINT_POSITION_MIDDLE) - point->coeff = dal_fixed31_32_div( - dal_fixed31_32_sub( - coord_x, - left_pos), - dal_fixed31_32_sub( - right_pos, - left_pos)); - else if (hw_pos == HW_POINT_POSITION_LEFT) - point->coeff = dal_fixed31_32_zero; - else if (hw_pos == HW_POINT_POSITION_RIGHT) - point->coeff = dal_fixed31_32_from_int(2); - else { - BREAK_TO_DEBUGGER(); - return false; - } - - point->left_index = index_left; - point->right_index = index_right; - point->pos = hw_pos; - - ++i; - } - - return true; -} - -static inline bool build_oem_custom_gamma_mapping_coefficients( - struct pixel_gamma_point *coeff128_oem, - const struct hw_x_point *coordinates_x, - const struct gamma_pixel *axis_x_256, - uint32_t number_of_points, - enum surface_pixel_format pixel_format) -{ - int i; - - for (i = 0; i < 3; i++) { - if (!build_custom_gamma_mapping_coefficients_worker( - coeff128_oem, coordinates_x, axis_x_256, i, - number_of_points, pixel_format)) - return false; - } - return true; -} - -static struct fixed31_32 calculate_mapped_value( - struct pwl_float_data *rgb, - const struct pixel_gamma_point *coeff, - enum channel_name channel, - uint32_t max_index) -{ - const struct gamma_point *point; - - struct fixed31_32 result; - - if (channel == CHANNEL_NAME_RED) - point = &coeff->r; - else if (channel == CHANNEL_NAME_GREEN) - point = &coeff->g; - else - point = &coeff->b; - - if ((point->left_index < 0) || (point->left_index > max_index)) { - BREAK_TO_DEBUGGER(); - return dal_fixed31_32_zero; - } - - if ((point->right_index < 0) || (point->right_index > max_index)) { - BREAK_TO_DEBUGGER(); - return dal_fixed31_32_zero; - } - - if (point->pos == HW_POINT_POSITION_MIDDLE) - if (channel == CHANNEL_NAME_RED) - result = dal_fixed31_32_add( - dal_fixed31_32_mul( - point->coeff, - dal_fixed31_32_sub( - rgb[point->right_index].r, - rgb[point->left_index].r)), - rgb[point->left_index].r); - else if (channel == CHANNEL_NAME_GREEN) - result = dal_fixed31_32_add( - dal_fixed31_32_mul( - point->coeff, - dal_fixed31_32_sub( - rgb[point->right_index].g, - rgb[point->left_index].g)), - rgb[point->left_index].g); - else - result = dal_fixed31_32_add( - dal_fixed31_32_mul( - point->coeff, - dal_fixed31_32_sub( - rgb[point->right_index].b, - rgb[point->left_index].b)), - rgb[point->left_index].b); - else if (point->pos == HW_POINT_POSITION_LEFT) { - BREAK_TO_DEBUGGER(); - result = dal_fixed31_32_zero; - } else { - BREAK_TO_DEBUGGER(); - result = dal_fixed31_32_one; - } - - return result; -} - -static inline struct fixed31_32 calculate_oem_mapped_value( - struct pwl_float_data *rgb_oem, - const struct pixel_gamma_point *coeff, - uint32_t index, - enum channel_name channel, - uint32_t max_index) -{ - return calculate_mapped_value( - rgb_oem, - coeff + index, - channel, - max_index); -} - -static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) -{ - /* consts for PQ gamma formula. */ - const struct fixed31_32 m1 = - dal_fixed31_32_from_fraction(159301758, 1000000000); - const struct fixed31_32 m2 = - dal_fixed31_32_from_fraction(7884375, 100000); - const struct fixed31_32 c1 = - dal_fixed31_32_from_fraction(8359375, 10000000); - const struct fixed31_32 c2 = - dal_fixed31_32_from_fraction(188515625, 10000000); - const struct fixed31_32 c3 = - dal_fixed31_32_from_fraction(186875, 10000); - - struct fixed31_32 l_pow_m1; - struct fixed31_32 base; - - if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero)) - in_x = dal_fixed31_32_zero; - - l_pow_m1 = dal_fixed31_32_pow(in_x, m1); - base = dal_fixed31_32_div( - dal_fixed31_32_add(c1, - (dal_fixed31_32_mul(c2, l_pow_m1))), - dal_fixed31_32_add(dal_fixed31_32_one, - (dal_fixed31_32_mul(c3, l_pow_m1)))); - *out_y = dal_fixed31_32_pow(base, m2); -} - -static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma, - struct pwl_float_data *rgb_oem, - struct pixel_gamma_point *coeff128_oem, - const struct core_gamma *ramp, - const struct core_surface *surface, - uint32_t hw_points_num, - const struct hw_x_point *coordinate_x, - const struct gamma_pixel *axis_x, - struct dividers dividers) -{ - uint32_t i; - - struct pwl_float_data_ex *rgb = rgb_regamma; - const struct hw_x_point *coord_x = coordinate_x; - struct fixed31_32 x; - struct fixed31_32 output; - struct fixed31_32 scaling_factor = - dal_fixed31_32_from_fraction(8, 1000); - - /* use coord_x to retrieve coordinates chosen base on given user curve - * the x values are exponentially distributed and currently it is hard - * coded, the user curve shape is ignored. Need to recalculate coord_x - * based on input curve, translation from 256/1025 to 128 PWL points. - */ - for (i = 0; i <= hw_points_num; i++) { - /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125. - * FP 1.0 = 80nits - */ - x = dal_fixed31_32_mul(coord_x->adjusted_x, scaling_factor); - - compute_pq(x, &output); - - /* should really not happen? */ - if (dal_fixed31_32_lt(output, dal_fixed31_32_zero)) - output = dal_fixed31_32_zero; - else if (dal_fixed31_32_lt(dal_fixed31_32_one, output)) - output = dal_fixed31_32_one; - - rgb->r = output; - rgb->g = output; - rgb->b = output; - - ++coord_x; - ++rgb; - } -} - -static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, - struct pwl_float_data *rgb_oem, - struct pixel_gamma_point *coeff128_oem, - const struct core_gamma *ramp, - const struct core_surface *surface, - uint32_t hw_points_num, - const struct hw_x_point *coordinate_x, - const struct gamma_pixel *axis_x, - struct dividers dividers) -{ - uint32_t i; - - struct gamma_coefficients coeff; - struct pwl_float_data_ex *rgb = rgb_regamma; - const struct hw_x_point *coord_x = coordinate_x; - - build_regamma_coefficients(&coeff); - - /* Use opp110->regamma.coordinates_x to retrieve - * coordinates chosen base on given user curve (future task). - * The x values are exponentially distributed and currently - * it is hard-coded, the user curve shape is ignored. - * The future task is to recalculate opp110- - * regamma.coordinates_x based on input/user curve, - * translation from 256/1025 to 128 pwl points. - */ - - i = 0; - - while (i != hw_points_num + 1) { - rgb->r = translate_from_linear_space_ex( - coord_x->adjusted_x, &coeff, 0); - rgb->g = translate_from_linear_space_ex( - coord_x->adjusted_x, &coeff, 1); - rgb->b = translate_from_linear_space_ex( - coord_x->adjusted_x, &coeff, 2); - - ++coord_x; - ++rgb; - ++i; - } -} - -static bool scale_gamma(struct pwl_float_data *pwl_rgb, - const struct core_gamma *ramp, - struct dividers dividers) -{ - const struct dc_gamma *gamma = &ramp->public; - const uint16_t max_driver = 0xFFFF; - const uint16_t max_os = 0xFF00; - uint16_t scaler = max_os; - uint32_t i = 0; - struct pwl_float_data *rgb = pwl_rgb; - struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1; - - do { - if ((gamma->red[i] > max_os) || - (gamma->green[i] > max_os) || - (gamma->blue[i] > max_os)) { - scaler = max_driver; - break; - } - ++i; - } while (i != INPUT_LUT_ENTRIES); - - i = 0; - - do { - rgb->r = dal_fixed31_32_from_fraction( - gamma->red[i], scaler); - rgb->g = dal_fixed31_32_from_fraction( - gamma->green[i], scaler); - rgb->b = dal_fixed31_32_from_fraction( - gamma->blue[i], scaler); - - ++rgb; - ++i; - } while (i != INPUT_LUT_ENTRIES); - - rgb->r = dal_fixed31_32_mul(rgb_last->r, - dividers.divider1); - rgb->g = dal_fixed31_32_mul(rgb_last->g, - dividers.divider1); - rgb->b = dal_fixed31_32_mul(rgb_last->b, - dividers.divider1); - - ++rgb; - - rgb->r = dal_fixed31_32_mul(rgb_last->r, - dividers.divider2); - rgb->g = dal_fixed31_32_mul(rgb_last->g, - dividers.divider2); - rgb->b = dal_fixed31_32_mul(rgb_last->b, - dividers.divider2); - - ++rgb; - - rgb->r = dal_fixed31_32_mul(rgb_last->r, - dividers.divider3); - rgb->g = dal_fixed31_32_mul(rgb_last->g, - dividers.divider3); - rgb->b = dal_fixed31_32_mul(rgb_last->b, - dividers.divider3); - - return true; -} - -static void build_evenly_distributed_points( - struct gamma_pixel *points, - uint32_t numberof_points, - struct fixed31_32 max_value, - struct dividers dividers) -{ - struct gamma_pixel *p = points; - struct gamma_pixel *p_last = p + numberof_points - 1; - - uint32_t i = 0; - - do { - struct fixed31_32 value = dal_fixed31_32_div_int( - dal_fixed31_32_mul_int(max_value, i), - numberof_points - 1); - - p->r = value; - p->g = value; - p->b = value; - - ++p; - ++i; - } while (i != numberof_points); - - p->r = dal_fixed31_32_div(p_last->r, dividers.divider1); - p->g = dal_fixed31_32_div(p_last->g, dividers.divider1); - p->b = dal_fixed31_32_div(p_last->b, dividers.divider1); - - ++p; - - p->r = dal_fixed31_32_div(p_last->r, dividers.divider2); - p->g = dal_fixed31_32_div(p_last->g, dividers.divider2); - p->b = dal_fixed31_32_div(p_last->b, dividers.divider2); - - ++p; - - p->r = dal_fixed31_32_div(p_last->r, dividers.divider3); - p->g = dal_fixed31_32_div(p_last->g, dividers.divider3); - p->b = dal_fixed31_32_div(p_last->b, dividers.divider3); -} - -static inline void copy_rgb_regamma_to_coordinates_x( - struct hw_x_point *coordinates_x, - uint32_t hw_points_num, - const struct pwl_float_data_ex *rgb_ex) -{ - struct hw_x_point *coords = coordinates_x; - uint32_t i = 0; - const struct pwl_float_data_ex *rgb_regamma = rgb_ex; - - while (i <= hw_points_num) { - coords->regamma_y_red = rgb_regamma->r; - coords->regamma_y_green = rgb_regamma->g; - coords->regamma_y_blue = rgb_regamma->b; - - ++coords; - ++rgb_regamma; - ++i; - } -} - -static bool calculate_interpolated_hardware_curve( - struct pwl_result_data *rgb, - struct pixel_gamma_point *coeff128, - struct pwl_float_data *rgb_user, - const struct hw_x_point *coordinates_x, - const struct gamma_pixel *axis_x_256, - uint32_t number_of_points, - enum surface_pixel_format pixel_format) -{ - - const struct pixel_gamma_point *coeff; - struct pixel_gamma_point *coeff_128 = coeff128; - uint32_t max_entries = 3 - 1; - struct pwl_result_data *rgb_resulted = rgb; - - uint32_t i = 0; - - if (!build_oem_custom_gamma_mapping_coefficients( - coeff_128, coordinates_x, axis_x_256, - number_of_points, - pixel_format)) - return false; - - coeff = coeff128; - max_entries += INPUT_LUT_ENTRIES; - - /* TODO: float point case */ - - while (i <= number_of_points) { - rgb_resulted->red = calculate_mapped_value( - rgb_user, coeff, CHANNEL_NAME_RED, max_entries); - rgb_resulted->green = calculate_mapped_value( - rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries); - rgb_resulted->blue = calculate_mapped_value( - rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries); - - ++coeff; - ++rgb_resulted; - ++i; - } - - return true; -} - -static bool map_regamma_hw_to_x_user( - struct pixel_gamma_point *coeff128, - struct pwl_float_data *rgb_oem, - struct pwl_result_data *rgb_resulted, - struct pwl_float_data *rgb_user, - struct hw_x_point *coords_x, - const struct gamma_pixel *axis_x, - const struct dc_gamma *gamma, - const struct pwl_float_data_ex *rgb_regamma, - struct dividers dividers, - uint32_t hw_points_num, - const struct core_surface *surface) -{ - /* setup to spare calculated ideal regamma values */ - - struct pixel_gamma_point *coeff = coeff128; - - struct hw_x_point *coords = coords_x; - - copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma); - - return calculate_interpolated_hardware_curve( - rgb_resulted, coeff, rgb_user, coords, axis_x, - hw_points_num, surface->public.format); -} - -static void build_new_custom_resulted_curve( - struct pwl_result_data *rgb_resulted, - uint32_t hw_points_num) -{ - struct pwl_result_data *rgb = rgb_resulted; - struct pwl_result_data *rgb_plus_1 = rgb + 1; - - uint32_t i; - - i = 0; - - while (i != hw_points_num + 1) { - rgb->red = dal_fixed31_32_clamp( - rgb->red, dal_fixed31_32_zero, - dal_fixed31_32_one); - rgb->green = dal_fixed31_32_clamp( - rgb->green, dal_fixed31_32_zero, - dal_fixed31_32_one); - rgb->blue = dal_fixed31_32_clamp( - rgb->blue, dal_fixed31_32_zero, - dal_fixed31_32_one); - - ++rgb; - ++i; - } - - rgb = rgb_resulted; - - i = 1; - - while (i != hw_points_num + 1) { - if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) - rgb_plus_1->red = rgb->red; - if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) - rgb_plus_1->green = rgb->green; - if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) - rgb_plus_1->blue = rgb->blue; - - rgb->delta_red = dal_fixed31_32_sub( - rgb_plus_1->red, - rgb->red); - rgb->delta_green = dal_fixed31_32_sub( - rgb_plus_1->green, - rgb->green); - rgb->delta_blue = dal_fixed31_32_sub( - rgb_plus_1->blue, - rgb->blue); - - ++rgb_plus_1; - ++rgb; - ++i; - } -} - -static void rebuild_curve_configuration_magic( - struct curve_points *arr_points, - struct pwl_result_data *rgb_resulted, - const struct hw_x_point *coordinates_x, - uint32_t hw_points_num, - enum dc_transfer_func_predefined tf) -{ - struct fixed31_32 y_r; - struct fixed31_32 y_g; - struct fixed31_32 y_b; - - struct fixed31_32 y1_min; - struct fixed31_32 y3_max; - - y_r = rgb_resulted[0].red; - y_g = rgb_resulted[0].green; - y_b = rgb_resulted[0].blue; - - y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); - - arr_points[0].x = coordinates_x[0].adjusted_x; - arr_points[0].y = y1_min; - arr_points[0].slope = dal_fixed31_32_div( - arr_points[0].y, - arr_points[0].x); - - /* this should be cleaned up as it's confusing my understanding (KK) is - * that REGAMMA_CNTLA_EXP_REGION_END is the X value for the region end - * REGAMMA_CNTLA_EXP_REGION_END_BASE is Y value for the above X - * REGAMMA_CNTLA_EXP_REGION_END_SLOPE is the slope beyond (X,Y) above - * currently when programming REGION_END = m_arrPoints[1].x, - * REGION_END_BASE = m_arrPoints[1].y, REGION_END_SLOPE=1 - * we don't use m_arrPoints[2] at all after this function, - * and its purpose isn't clear to me - */ - arr_points[1].x = coordinates_x[hw_points_num].adjusted_x; - arr_points[2].x = coordinates_x[hw_points_num].adjusted_x; - - y_r = rgb_resulted[hw_points_num].red; - y_g = rgb_resulted[hw_points_num].green; - y_b = rgb_resulted[hw_points_num].blue; - - /* see comment above, m_arrPoints[1].y should be the Y value for the - * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) - */ - y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); - - arr_points[1].y = y3_max; - arr_points[2].y = y3_max; - - arr_points[2].slope = dal_fixed31_32_zero; - - /* for PQ, we want to have a straight line from last HW X point, and the - * slope to be such that we hit 1.0 at 10000 nits. - */ - if (tf == TRANSFER_FUNCTION_PQ) { - const struct fixed31_32 end_value = - dal_fixed31_32_from_int(125); - - arr_points[2].slope = dal_fixed31_32_div( - dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), - dal_fixed31_32_sub(end_value, arr_points[1].x)); - } -} - -static bool convert_to_custom_float_format( - struct fixed31_32 value, - const struct custom_float_format *format, - uint32_t *result) -{ - uint32_t mantissa; - uint32_t exponenta; - bool negative; - - return build_custom_float( - value, format, &negative, &mantissa, &exponenta) && - setup_custom_float( - format, negative, mantissa, exponenta, result); -} - -static bool convert_to_custom_float( - struct pwl_result_data *rgb_resulted, - struct curve_points *arr_points, - uint32_t hw_points_num) -{ - struct custom_float_format fmt; - - struct pwl_result_data *rgb = rgb_resulted; - - uint32_t i = 0; - - fmt.exponenta_bits = 6; - fmt.mantissa_bits = 12; - fmt.sign = true; - - if (!convert_to_custom_float_format( - arr_points[0].x, - &fmt, - &arr_points[0].custom_float_x)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[0].offset, - &fmt, - &arr_points[0].custom_float_offset)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[0].slope, - &fmt, - &arr_points[0].custom_float_slope)) { - BREAK_TO_DEBUGGER(); - return false; - } - - fmt.mantissa_bits = 10; - fmt.sign = false; - - if (!convert_to_custom_float_format( - arr_points[1].x, - &fmt, - &arr_points[1].custom_float_x)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[1].y, - &fmt, - &arr_points[1].custom_float_y)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - arr_points[2].slope, - &fmt, - &arr_points[2].custom_float_slope)) { - BREAK_TO_DEBUGGER(); - return false; - } - - fmt.mantissa_bits = 12; - fmt.sign = true; - - while (i != hw_points_num) { - if (!convert_to_custom_float_format( - rgb->red, - &fmt, - &rgb->red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->green, - &fmt, - &rgb->green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->blue, - &fmt, - &rgb->blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_red, - &fmt, - &rgb->delta_red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_green, - &fmt, - &rgb->delta_green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format( - rgb->delta_blue, - &fmt, - &rgb->delta_blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - ++rgb; - ++i; - } - - return true; -} - -bool calculate_regamma_params(struct pwl_params *params, - const struct core_gamma *ramp, - const struct core_surface *surface, - const struct core_stream *stream) -{ - struct gamma_curve *arr_curve_points = params->arr_curve_points; - struct curve_points *arr_points = params->arr_points; - struct pwl_result_data *rgb_resulted = params->rgb_resulted; - struct dividers dividers; - - struct hw_x_point *coordinates_x = NULL; - struct pwl_float_data *rgb_user = NULL ; - struct pwl_float_data_ex *rgb_regamma = NULL; - struct pwl_float_data *rgb_oem = NULL; - struct gamma_pixel *axix_x_256 = NULL; - struct pixel_gamma_point *coeff128_oem = NULL; - struct pixel_gamma_point *coeff128 = NULL; - - enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; - - bool ret = false; - - coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3)); - if (!coordinates_x) - goto coordinates_x_alloc_fail; - rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3)); - if (!rgb_user) - goto rgb_user_alloc_fail; - rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3)); - if (!rgb_regamma) - goto rgb_regamma_alloc_fail; - rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3)); - if (!rgb_oem) - goto rgb_oem_alloc_fail; - axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3)); - if (!axix_x_256) - goto axix_x_256_alloc_fail; - coeff128_oem = dm_alloc(sizeof(*coeff128_oem) * (256 + 3)); - if (!coeff128_oem) - goto coeff128_oem_alloc_fail; - coeff128 = dm_alloc(sizeof(*coeff128) * (256 + 3)); - if (!coeff128) - goto coeff128_alloc_fail; - - dividers.divider1 = dal_fixed31_32_from_fraction(3, 2); - dividers.divider2 = dal_fixed31_32_from_int(2); - dividers.divider3 = dal_fixed31_32_from_fraction(5, 2); - - if (stream->public.out_transfer_func) - tf = stream->public.out_transfer_func->tf; - - build_evenly_distributed_points( - axix_x_256, - 256, - dal_fixed31_32_one, - dividers); - - scale_gamma(rgb_user, ramp, dividers); - - if (tf == TRANSFER_FUNCTION_PQ) { - setup_distribution_points_pq(arr_curve_points, arr_points, - ¶ms->hw_points_num, coordinates_x, - surface->public.format); - build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem, - ramp, surface, params->hw_points_num, - coordinates_x, axix_x_256, dividers); - } else { - setup_distribution_points(arr_curve_points, arr_points, - ¶ms->hw_points_num, coordinates_x); - build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, - ramp, surface, params->hw_points_num, - coordinates_x, axix_x_256, dividers); - } - - map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user, - coordinates_x, axix_x_256, &ramp->public, rgb_regamma, - dividers, params->hw_points_num, surface); - - build_new_custom_resulted_curve(rgb_resulted, params->hw_points_num); - - rebuild_curve_configuration_magic( - arr_points, - rgb_resulted, - coordinates_x, - params->hw_points_num, - tf); - - convert_to_custom_float(rgb_resulted, arr_points, - params->hw_points_num); - - ret = true; - - dm_free(coeff128); -coeff128_alloc_fail: - dm_free(coeff128_oem); -coeff128_oem_alloc_fail: - dm_free(axix_x_256); -axix_x_256_alloc_fail: - dm_free(rgb_oem); -rgb_oem_alloc_fail: - dm_free(rgb_regamma); -rgb_regamma_alloc_fail: - dm_free(rgb_user); -rgb_user_alloc_fail: - dm_free(coordinates_x); -coordinates_x_alloc_fail: - return ret; - -} - diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7d4299b9ee1f..948f82a56472 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1519,23 +1519,23 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda if (dc->debug.disable_color_module) continue; /* skip below color updates */ - if (updates[i].hdr_static_metadata) { - resource_build_info_frame(pipe_ctx); - core_dc->hwss.update_info_frame(pipe_ctx); - } if (is_new_pipe_surface[j] || updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); if (is_new_pipe_surface[j] || - updates[i].gamma || updates[i].out_transfer_func) core_dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->surface, pipe_ctx->stream); + if (updates[i].hdr_static_metadata) { + resource_build_info_frame(pipe_ctx); + core_dc->hwss.update_info_frame(pipe_ctx); + } + } if (apply_ctx) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b814e7b76bbc..f53b41339951 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -213,11 +213,14 @@ enum dc_transfer_func_type { }; struct dc_transfer_func_distributed_points { - uint16_t red[TRANSFER_FUNC_POINTS]; - uint16_t green[TRANSFER_FUNC_POINTS]; - uint16_t blue[TRANSFER_FUNC_POINTS]; + struct fixed31_32 red[TRANSFER_FUNC_POINTS]; + struct fixed31_32 green[TRANSFER_FUNC_POINTS]; + struct fixed31_32 blue[TRANSFER_FUNC_POINTS]; + uint16_t end_exponent; - uint16_t x_point_at_y1; + uint16_t x_point_at_y1_red; + uint16_t x_point_at_y1_green; + uint16_t x_point_at_y1_blue; }; enum dc_transfer_func_predefined { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 415b12accd2c..6e70cf7b99ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -42,7 +42,6 @@ #include "stream_encoder.h" #include "link_encoder.h" #include "clock_source.h" -#include "gamma_calcs.h" #include "audio.h" #include "dce/dce_hwseq.h" @@ -286,6 +285,436 @@ static bool dce110_set_input_transfer_func( return result; } +static bool build_custom_float( + struct fixed31_32 value, + const struct custom_float_format *format, + bool *negative, + uint32_t *mantissa, + uint32_t *exponenta) +{ + uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; + + const struct fixed31_32 mantissa_constant_plus_max_fraction = + dal_fixed31_32_from_fraction( + (1LL << (format->mantissa_bits + 1)) - 1, + 1LL << format->mantissa_bits); + + struct fixed31_32 mantiss; + + if (dal_fixed31_32_eq( + value, + dal_fixed31_32_zero)) { + *negative = false; + *mantissa = 0; + *exponenta = 0; + return true; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_zero)) { + *negative = format->sign; + value = dal_fixed31_32_neg(value); + } else { + *negative = false; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shl(value, 1); + ++i; + } while (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)); + + --i; + + if (exp_offset <= i) { + *mantissa = 0; + *exponenta = 0; + return true; + } + + *exponenta = exp_offset - i; + } else if (dal_fixed31_32_le( + mantissa_constant_plus_max_fraction, + value)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shr(value, 1); + ++i; + } while (dal_fixed31_32_lt( + mantissa_constant_plus_max_fraction, + value)); + + *exponenta = exp_offset + i - 1; + } else { + *exponenta = exp_offset; + } + + mantiss = dal_fixed31_32_sub( + value, + dal_fixed31_32_one); + + if (dal_fixed31_32_lt( + mantiss, + dal_fixed31_32_zero) || + dal_fixed31_32_lt( + dal_fixed31_32_one, + mantiss)) + mantiss = dal_fixed31_32_zero; + else + mantiss = dal_fixed31_32_shl( + mantiss, + format->mantissa_bits); + + *mantissa = dal_fixed31_32_floor(mantiss); + + return true; +} + +static bool setup_custom_float( + const struct custom_float_format *format, + bool negative, + uint32_t mantissa, + uint32_t exponenta, + uint32_t *result) +{ + uint32_t i = 0; + uint32_t j = 0; + + uint32_t value = 0; + + /* verification code: + * once calculation is ok we can remove it + */ + + const uint32_t mantissa_mask = + (1 << (format->mantissa_bits + 1)) - 1; + + const uint32_t exponenta_mask = + (1 << (format->exponenta_bits + 1)) - 1; + + if (mantissa & ~mantissa_mask) { + BREAK_TO_DEBUGGER(); + mantissa = mantissa_mask; + } + + if (exponenta & ~exponenta_mask) { + BREAK_TO_DEBUGGER(); + exponenta = exponenta_mask; + } + + /* end of verification code */ + + while (i < format->mantissa_bits) { + uint32_t mask = 1 << i; + + if (mantissa & mask) + value |= mask; + + ++i; + } + + while (j < format->exponenta_bits) { + uint32_t mask = 1 << j; + + if (exponenta & mask) + value |= mask << i; + + ++j; + } + + if (negative && format->sign) + value |= 1 << (i + j); + + *result = value; + + return true; +} + +static bool convert_to_custom_float_format( + struct fixed31_32 value, + const struct custom_float_format *format, + uint32_t *result) +{ + uint32_t mantissa; + uint32_t exponenta; + bool negative; + + return build_custom_float( + value, format, &negative, &mantissa, &exponenta) && + setup_custom_float( + format, negative, mantissa, exponenta, result); +} + +static bool convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = true; + + if (!convert_to_custom_float_format( + arr_points[0].x, + &fmt, + &arr_points[0].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].offset, + &fmt, + &arr_points[0].custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].slope, + &fmt, + &arr_points[0].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format( + arr_points[1].x, + &fmt, + &arr_points[1].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[1].y, + &fmt, + &arr_points[1].custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[2].slope, + &fmt, + &arr_points[2].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 12; + fmt.sign = true; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format( + rgb->red, + &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->green, + &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->blue, + &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_red, + &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_green, + &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_blue, + &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} + +static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func + *output_tf, struct pwl_params *regamma_params) +{ + if (output_tf == NULL || regamma_params == NULL) + return false; + + struct gamma_curve *arr_curve_points = regamma_params->arr_curve_points; + struct curve_points *arr_points = regamma_params->arr_points; + struct pwl_result_data *rgb_resulted = regamma_params->rgb_resulted; + struct fixed31_32 y_r; + struct fixed31_32 y_g; + struct fixed31_32 y_b; + struct fixed31_32 y1_min; + struct fixed31_32 y3_max; + + int32_t segment_start, segment_end; + uint32_t hw_points, start_index; + uint32_t i, j; + + memset(regamma_params, 0, sizeof(struct pwl_params)); + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* 16 segments x 16 points + * segments are from 2^-11 to 2^5 + */ + segment_start = -11; + segment_end = 5; + + } else { + /* 10 segments x 16 points + * segment is from 2^-10 to 2^0 + */ + segment_start = -10; + segment_end = 0; + } + + hw_points = (segment_end - segment_start) * 16; + j = 0; + /* (segment + 25) * 32, every 2nd point */ + start_index = (segment_start + 25) * 32; + for (i = start_index; i <= 1025; i += 2) { + if (j > hw_points) + break; + rgb_resulted[j].red = output_tf->tf_pts.red[i]; + rgb_resulted[j].green = output_tf->tf_pts.green[i]; + rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; + j++; + } + + arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_start)); + arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + + y_r = rgb_resulted[0].red; + y_g = rgb_resulted[0].green; + y_b = rgb_resulted[0].blue; + + y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); + + arr_points[0].y = y1_min; + arr_points[0].slope = dal_fixed31_32_div( + arr_points[0].y, + arr_points[0].x); + + y_r = rgb_resulted[hw_points - 1].red; + y_g = rgb_resulted[hw_points - 1].green; + y_b = rgb_resulted[hw_points - 1].blue; + + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ + y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[1].y = y3_max; + arr_points[2].y = y3_max; + + arr_points[1].slope = dal_fixed31_32_zero; + arr_points[2].slope = dal_fixed31_32_zero; + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* for PQ, we want to have a straight line from last HW X point, + * and the slope to be such that we hit 1.0 at 10000 nits. + */ + const struct fixed31_32 end_value = + dal_fixed31_32_from_int(125); + + arr_points[1].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + arr_points[2].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + } + + regamma_params->hw_points_num = hw_points; + + for (i = 0; i < segment_end - segment_start; i++) { + regamma_params->arr_curve_points[i].offset = i * 16; + regamma_params->arr_curve_points[i].segments_num = 4; + } + + struct pwl_result_data *rgb = rgb_resulted; + struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1; + + i = 1; + + while (i != hw_points + 1) { + if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dal_fixed31_32_sub( + rgb_plus_1->red, + rgb->red); + rgb->delta_green = dal_fixed31_32_sub( + rgb_plus_1->green, + rgb->green); + rgb->delta_blue = dal_fixed31_32_sub( + rgb_plus_1->blue, + rgb->blue); + + ++rgb_plus_1; + ++rgb; + ++i; + } + + convert_to_custom_float(rgb_resulted, arr_points, hw_points); + + return true; +} + static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface, /* Surface - To be removed */ @@ -308,10 +737,13 @@ static bool dce110_set_output_transfer_func( opp->funcs->opp_power_on_regamma_lut(opp, true); if (stream->public.out_transfer_func && - stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { + stream->public.out_transfer_func->type == + TF_TYPE_PREDEFINED && + stream->public.out_transfer_func->tf == + TRANSFER_FUNCTION_SRGB) { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); - } else if (ramp && calculate_regamma_params(regamma_params, ramp, surface, stream)) { + } else if (dce110_translate_regamma_to_hw_format( + stream->public.out_transfer_func, regamma_params)) { opp->funcs->opp_program_regamma_pwl(opp, regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h deleted file mode 100644 index 0712268856c2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * gamma_calcs.h - * - * Created on: Feb 9, 2016 - * Author: yonsun - */ - -#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ -#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ - -#include "opp.h" -#include "core_types.h" -#include "dc.h" - -bool calculate_regamma_params(struct pwl_params *params, - const struct core_gamma *ramp, - const struct core_surface *surface, - const struct core_stream *stream); - -#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a1f31a4410a3..bef5e2cacbe3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -138,9 +138,7 @@ struct custom_float_value { struct hw_x_point { uint32_t custom_float_x; - uint32_t custom_float_x_adjusted; struct fixed31_32 x; - struct fixed31_32 adjusted_x; struct fixed31_32 regamma_y_red; struct fixed31_32 regamma_y_green; struct fixed31_32 regamma_y_blue; diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index c28de167250f..5a4364dfd2f7 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -190,6 +190,14 @@ struct fixed31_32 dal_fixed31_32_add( struct fixed31_32 arg1, struct fixed31_32 arg2); +/* + * @brief + * result = arg1 + arg2 + */ +struct fixed31_32 dal_fixed31_32_add_int( + struct fixed31_32 arg1, + int32_t arg2); + /* * @brief * result = arg1 - arg2 -- GitLab From 7a1c37e00a660b380fe258fed54fd5af6735814e Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 12 Jan 2017 14:24:11 -0500 Subject: [PATCH 0183/2898] drm/amd/display: Disable Modules at Runtime Add NULL check in modules Signed-off-by: Anthony Koo Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/modules/freesync/freesync.c | 94 +++++++++++++------ .../amd/display/modules/inc/mod_freesync.h | 7 -- 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 6f4d169f4e4e..e0703c588e47 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -205,11 +205,16 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_caps *caps) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - struct core_stream *core_stream = - DC_STREAM_TO_CORE(stream); - struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc); + struct core_stream *core_stream = NULL; + struct core_dc *core_dc = NULL; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + core_stream = DC_STREAM_TO_CORE(stream); + core_dc = DC_TO_CORE(core_freesync->dc); int persistent_freesync_enable = 0; struct persistent_data_flag flag; @@ -270,11 +275,16 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, const struct dc_stream *stream) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - int i = 0; - unsigned int index = map_index_from_stream(core_freesync, stream); + struct core_freesync *core_freesync = NULL; + unsigned int index = 0; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + dc_stream_release(core_freesync->map[index].stream); core_freesync->map[index].stream = NULL; /* To remove this entity, shift everything after down */ @@ -621,11 +631,14 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - unsigned int index, v_total = 0; struct freesync_state *state; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); if (core_freesync->num_entities == 0) return; @@ -691,11 +704,15 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams, struct mod_freesync_params *freesync_params) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); bool freesync_program_required = false; unsigned int stream_index; struct freesync_state *state; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); if (core_freesync->num_entities == 0) return; @@ -762,10 +779,14 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_params *freesync_params) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); + unsigned int index = NULL; + struct core_freesync *core_freesync = NULL; - unsigned int index = map_index_from_stream(core_freesync, stream); + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); if (core_freesync->map[index].state.fullscreen) { freesync_params->state = FREESYNC_STATE_FULLSCREEN; @@ -794,13 +815,17 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams, struct mod_freesync_user_enable *user_enable) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - struct core_dc *core_dc = DC_TO_CORE(core_freesync->dc); - unsigned int stream_index, map_index; int persistent_data = 0; struct persistent_data_flag flag; + struct core_dc *core_dc = NULL; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + core_dc = DC_TO_CORE(core_freesync->dc); flag.save_per_edid = true; flag.save_per_link = false; @@ -842,10 +867,14 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_user_enable *user_enable) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; - unsigned int index = map_index_from_stream(core_freesync, stream); + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); *user_enable = core_freesync->map[index].user_enable; @@ -855,12 +884,15 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams) { - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); - unsigned int stream_index, map_index; unsigned min_frame_duration_in_ns, max_frame_duration_in_ns; struct freesync_state *state; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); for (stream_index = 0; stream_index < num_streams; stream_index++) { @@ -1121,8 +1153,12 @@ void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, unsigned int curr_time_stamp_in_us) { unsigned int stream_index, map_index, last_render_time_in_us = 0; - struct core_freesync *core_freesync = - MOD_FREESYNC_TO_CORE(mod_freesync); + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); for (stream_index = 0; stream_index < num_streams; stream_index++) { diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 7abfe34dc2d9..783ff2ef3bee 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -109,13 +109,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, const struct dc_stream *stream); -/* - * Build additional parameters for dc_stream when creating stream for - * sink to support freesync - */ -void mod_freesync_update_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream); - /* * Update the freesync state flags for each display and program * freesync accordingly -- GitLab From cc0cb445ae56890a322abe2cc8df63b1ccab74fb Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Wed, 11 Jan 2017 14:33:36 -0500 Subject: [PATCH 0184/2898] drm/amd/display: Fixing some fallout from dc_target removal Also avoid allocating memory dce110_set_output_transfer_func if not needed Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_stream.c | 6 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 7 +++++ .../display/dc/dce110/dce110_hw_sequencer.c | 30 +++++-------------- .../display/dc/dce110/dce110_opp_regamma_v.c | 7 +++++ .../drm/amd/display/dc/dce110/dce110_opp_v.c | 6 +++- .../drm/amd/display/dc/dce110/dce110_opp_v.h | 4 +++ .../amd/display/dc/dce110/dce110_resource.c | 17 +++++++++-- .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 1 - drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 + 9 files changed, 49 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index bc1f387d1992..47816c5ee0e0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -192,7 +192,8 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream == stream) { + if ((pipe_ctx->stream == stream) && + (pipe_ctx->ipp != NULL)) { struct input_pixel_processor *ipp = pipe_ctx->ipp; if (ipp->funcs->ipp_cursor_set_attributes( @@ -231,7 +232,8 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream == stream) { + if ((pipe_ctx->stream == stream) && + (pipe_ctx->ipp != NULL)) { struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 167f523df657..061de9e8249d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -973,6 +973,10 @@ bool dce110_opp_construct(struct dce110_opp *opp110, opp110->base.inst = inst; + opp110->base.regamma_params = dm_alloc(sizeof(struct pwl_params)); + if (opp110->base.regamma_params == NULL) + return false; + opp110->regs = regs; opp110->opp_shift = opp_shift; opp110->opp_mask = opp_mask; @@ -982,6 +986,9 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp) { + dm_free((*opp)->regamma_params); + (*opp)->regamma_params = NULL; + dm_free(FROM_DCE11_OPP(*opp)); *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6e70cf7b99ef..1a9ba127b781 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -721,43 +721,27 @@ static bool dce110_set_output_transfer_func( const struct core_stream *stream) { struct output_pixel_processor *opp = pipe_ctx->opp; - const struct core_gamma *ramp = NULL; - struct pwl_params *regamma_params; - bool result = false; - - if (surface->public.gamma_correction) - ramp = DC_GAMMA_TO_CORE(surface->public.gamma_correction); - - regamma_params = dm_alloc(sizeof(struct pwl_params)); - if (regamma_params == NULL) - goto regamma_alloc_fail; - - regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; opp->funcs->opp_power_on_regamma_lut(opp, true); + opp->regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->public.out_transfer_func && - stream->public.out_transfer_func->type == + stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->public.out_transfer_func->tf == + stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); } else if (dce110_translate_regamma_to_hw_format( - stream->public.out_transfer_func, regamma_params)) { - opp->funcs->opp_program_regamma_pwl(opp, regamma_params); - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + stream->public.out_transfer_func, opp->regamma_params)) { + opp->funcs->opp_program_regamma_pwl(opp, opp->regamma_params); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); } opp->funcs->opp_power_on_regamma_lut(opp, false); - result = true; - - dm_free(regamma_params); - -regamma_alloc_fail: - return result; + return true; } static enum dc_status bios_parser_crtc_source_select( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 8164aa6bcb00..876445f14c85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -548,3 +548,10 @@ void dce110_opp_power_on_regamma_lut_v( dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); } + +void dce110_opp_set_regamma_mode_v( + struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + // TODO: need to implement the function +} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 0a9b384303d0..95b3d2eb8428 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -42,7 +42,7 @@ static const struct opp_funcs funcs = { .opp_set_csc_default = dce110_opp_v_set_csc_default, .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, .opp_destroy = dce110_opp_destroy, .opp_program_fmt = dce110_opp_program_fmt, .opp_program_bit_depth_reduction = @@ -56,6 +56,10 @@ bool dce110_opp_v_construct(struct dce110_opp *opp110, opp110->base.ctx = ctx; + opp110->base.regamma_params = dm_alloc(sizeof(struct pwl_params)); + if (opp110->base.regamma_params == NULL) + return false; + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index ac5937786ce3..cb26c515d30f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -49,4 +49,8 @@ void dce110_opp_power_on_regamma_lut_v( struct output_pixel_processor *opp, bool power_on); +void dce110_opp_set_regamma_mode_v( + struct output_pixel_processor *opp, + enum opp_regamma mode); + #endif /* __DC_OPP_DCE110_V_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index cfbb4ef21f8b..82cddb6425a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1114,14 +1114,22 @@ static const struct resource_funcs dce110_res_pool_funcs = { dce110_resource_build_bit_depth_reduction_params }; -static void underlay_create(struct dc_context *ctx, struct resource_pool *pool) +static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) { struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); - dce110_opp_v_construct(dce110_oppv, ctx); + if ((dce110_tgv == NULL) || + (dce110_xfmv == NULL) || + (dce110_miv == NULL) || + (dce110_oppv == NULL)) + return false; + + if (!dce110_opp_v_construct(dce110_oppv, ctx)) + return false; + dce110_timing_generator_v_construct(dce110_tgv, ctx); dce110_mem_input_v_construct(dce110_miv, ctx); dce110_transform_v_construct(dce110_xfmv, ctx); @@ -1135,6 +1143,8 @@ static void underlay_create(struct dc_context *ctx, struct resource_pool *pool) /* update the public caps to indicate an underlay is available */ ctx->dc->caps.max_slave_planes = 1; ctx->dc->caps.max_slave_planes = 1; + + return true; } static void bw_calcs_data_update_from_pplib(struct core_dc *dc) @@ -1334,7 +1344,8 @@ static bool construct( } } - underlay_create(ctx, &pool->base); + if (!underlay_create(ctx, &pool->base)) + goto res_create_fail; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 3b0e616f7066..b8735b27e9bc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -65,7 +65,6 @@ struct pwl_result_data { }; struct pwl_params { - uint32_t *data; struct gamma_curve arr_curve_points[16]; struct curve_points arr_points[3]; struct pwl_result_data rgb_resulted[256 + 3]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index bef5e2cacbe3..a10c4e296960 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -202,6 +202,7 @@ enum opp_regamma { struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; + struct pwl_params *regamma_params; const struct opp_funcs *funcs; }; -- GitLab From 721d30cf8363247c0c6cb44514e88a5811151c01 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 13 Jan 2017 10:10:26 -0500 Subject: [PATCH 0185/2898] drm/amd/display: No audio output heard from DP panel Signed-off-by: Hersen Wu Acked-by: Harry Wentland Reviewed-by: Eagle Yeh Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index bf97cd8c8221..c244887ba15e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -50,8 +50,8 @@ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ - SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ - SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ + SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, mask_sh),\ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh) -- GitLab From 858058da47a557b6c0211830d530045c1c8e62ab Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 9 Nov 2016 05:41:51 -0500 Subject: [PATCH 0186/2898] drm/amd/display: Use pflip prepare and submit parts (v2) Use new functions so flip failures can be gracefully handled v2: Avoid -EINVAL returned from amdgpu_crtc_prepare_flip in some error cases, it is not allowed according to expected return values for atomic_commit hook. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c32fc6d26088..ad08d6f7f094 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2267,7 +2267,6 @@ int amdgpu_dm_atomic_commit( uint32_t flip_crtcs_count = 0; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; - const struct dc_stream *commit_streams[MAX_STREAMS]; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; const struct dc_stream *new_stream; -- GitLab From f84a8161cb1652281746d113667427dbbf8bd5db Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 12 Jan 2017 23:18:33 -0500 Subject: [PATCH 0187/2898] drm/amd/display: mode change without breaking unaffected streams - include clock constraint logic in validate - in dc_commit_streams, include surfaces of unaffected streams Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 +++++++++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_status.h | 2 ++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 948f82a56472..9deddc8ee2d1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1007,7 +1007,7 @@ bool dc_commit_streams( struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; - struct dc_validation_set set[MAX_STREAMS]; + struct dc_validation_set set[MAX_STREAMS] = { 0 }; int i, j, k; if (false == streams_changed(core_dc, streams, stream_count)) @@ -1018,13 +1018,20 @@ bool dc_commit_streams( for (i = 0; i < stream_count; i++) { const struct dc_stream *stream = streams[i]; + const struct dc_stream_status *status = dc_stream_get_status(stream); + int j; dc_stream_log(stream, core_dc->ctx->logger, LOG_DC); set[i].stream = stream; - set[i].surface_count = 0; + + if (status) { + set[i].surface_count = status->surface_count; + for (j = 0; j < status->surface_count; j++) + set[i].surfaces[j] = status->surfaces[j]; + } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1f87b948678b..6037ee25598c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -585,7 +585,7 @@ enum dc_status resource_build_scaling_params_for_context( if (!resource_build_scaling_params( &context->res_ctx.pipe_ctx[i].surface->public, &context->res_ctx.pipe_ctx[i])) - return DC_FAIL_BANDWIDTH_VALIDATE; + return DC_FAIL_SCALING; } return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 32a2cc712000..147eb7cac701 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -40,6 +40,8 @@ enum dc_status { DC_EXCEED_DONGLE_MAX_CLK, DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED, DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */ + DC_FAIL_SCALING, + DC_FAIL_CLK_CONSTRAINT, DC_ERROR_UNEXPECTED = -1 }; -- GitLab From bf72726358adfedcf1c268690521891809332151 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 01:44:52 -0500 Subject: [PATCH 0188/2898] drm/amd/display: assert if mask is 0 in set_reg_field_value_ex - mask = 0 means something is wrong in caller and no register field will be updated Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 11a0abfd3418..052a43af1bd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -165,6 +165,7 @@ static inline uint32_t set_reg_field_value_ex( uint32_t mask, uint8_t shift) { + ASSERT(mask != 0); return (reg_value & ~mask) | (mask & (value << shift)); } -- GitLab From ac0e562c521228215d597fe3ef0c13f02077f700 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 11:46:53 -0500 Subject: [PATCH 0189/2898] drm/amd/display: remove un-used defines and dead code Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/basics/signal_types.c | 35 ------ .../drm/amd/display/dc/bios/command_table.c | 55 --------- .../drm/amd/display/dc/bios/command_table.h | 3 - drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 - .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- .../include/asic_capability_interface.h | 55 --------- .../display/include/asic_capability_types.h | 116 ------------------ .../amd/display/include/bios_parser_types.h | 8 -- .../amd/display/include/ddc_service_types.h | 7 -- .../drm/amd/display/include/irq_interface.h | 31 ----- .../amd/display/include/link_service_types.h | 75 ----------- .../drm/amd/display/include/signal_types.h | 3 - 12 files changed, 1 insertion(+), 390 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_interface.h delete mode 100644 drivers/gpu/drm/amd/display/include/asic_capability_types.h delete mode 100644 drivers/gpu/drm/amd/display/include/irq_interface.h diff --git a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c index 44447e07803a..247487c3db71 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c +++ b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c @@ -44,23 +44,6 @@ bool dc_is_dp_signal(enum signal_type signal) signal == SIGNAL_TYPE_DISPLAY_PORT_MST); } -bool dc_is_dp_external_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_DISPLAY_PORT_MST); -} - -bool dc_is_analog_signal(enum signal_type signal) -{ - switch (signal) { - case SIGNAL_TYPE_RGB: - return true; - break; - default: - return false; - } -} - bool dc_is_embedded_signal(enum signal_type signal) { return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); @@ -96,21 +79,3 @@ bool dc_is_audio_capable_signal(enum signal_type signal) signal == SIGNAL_TYPE_WIRELESS); } -/* - * @brief - * Returns whether the signal is compatible - * with other digital encoder signal types. - * This is true for DVI, LVDS, and HDMI signal types. - */ -bool dc_is_digital_encoder_compatible_signal(enum signal_type signal) -{ - switch (signal) { - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - case SIGNAL_TYPE_HDMI_TYPE_A: - case SIGNAL_TYPE_LVDS: - return true; - default: - return false; - } -} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index d0eedb6235fe..88aaf53cb8c4 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -56,7 +56,6 @@ static void init_dac_encoder_control(struct bios_parser *bp); static void init_dac_output_control(struct bios_parser *bp); static void init_blank_crtc(struct bios_parser *bp); static void init_set_crtc_timing(struct bios_parser *bp); -static void init_set_crtc_overscan(struct bios_parser *bp); static void init_select_crtc_source(struct bios_parser *bp); static void init_enable_crtc(struct bios_parser *bp); static void init_enable_crtc_mem_req(struct bios_parser *bp); @@ -77,7 +76,6 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) init_dac_output_control(bp); init_blank_crtc(bp); init_set_crtc_timing(bp); - init_set_crtc_overscan(bp); init_select_crtc_source(bp); init_enable_crtc(bp); init_enable_crtc_mem_req(bp); @@ -1931,59 +1929,6 @@ static enum bp_result set_crtc_using_dtd_timing_v3( return result; } -/******************************************************************************* - ******************************************************************************** - ** - ** SET CRTC OVERSCAN - ** - ******************************************************************************** - *******************************************************************************/ - -static enum bp_result set_crtc_overscan_v1( - struct bios_parser *bp, - struct bp_hw_crtc_overscan_parameters *bp_params); - -static void init_set_crtc_overscan(struct bios_parser *bp) -{ - switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_OverScan)) { - case 1: - bp->cmd_tbl.set_crtc_overscan = set_crtc_overscan_v1; - break; - default: - bp->cmd_tbl.set_crtc_overscan = NULL; - break; - } -} - -static enum bp_result set_crtc_overscan_v1( - struct bios_parser *bp, - struct bp_hw_crtc_overscan_parameters *bp_params) -{ - enum bp_result result = BP_RESULT_FAILURE; - SET_CRTC_OVERSCAN_PARAMETERS params = {0}; - uint8_t atom_controller_id; - - if (bp->cmd_helper->controller_id_to_atom( - bp_params->controller_id, &atom_controller_id)) - params.ucCRTC = atom_controller_id; - else - return BP_RESULT_BADINPUT; - - params.usOverscanRight = - cpu_to_le16((uint16_t)bp_params->h_overscan_right); - params.usOverscanLeft = - cpu_to_le16((uint16_t)bp_params->h_overscan_left); - params.usOverscanBottom = - cpu_to_le16((uint16_t)bp_params->v_overscan_bottom); - params.usOverscanTop = - cpu_to_le16((uint16_t)bp_params->v_overscan_top); - - if (EXEC_BIOS_CMD_TABLE(SetCRTC_OverScan, params)) - result = BP_RESULT_OK; - - return result; -} - /******************************************************************************* ******************************************************************************** ** diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h index e1cd21b6e968..b8e6ef06c0c7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h @@ -75,9 +75,6 @@ struct cmd_tbl { enum bp_result (*set_crtc_timing)( struct bios_parser *bp, struct bp_hw_crtc_timing_parameters *bp_params); - enum bp_result (*set_crtc_overscan)( - struct bios_parser *bp, - struct bp_hw_crtc_overscan_parameters *bp_params); enum bp_result (*select_crtc_source)( struct bios_parser *bp, struct bp_crtc_source_select *bp_params); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b0f316344e86..62cfc5cbe773 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -38,7 +38,6 @@ #include "hw_sequencer.h" #include "resource.h" #include "fixed31_32.h" -#include "include/asic_capability_interface.h" #include "dpcd_defs.h" #include "dce/dce_11_0_d.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index a661fc6a69dd..c9c1b48df384 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1922,7 +1922,7 @@ static void get_active_converter_info( break; } - if (link->dpcd_caps.dpcd_rev.raw >= DCS_DPCD_REV_11) { + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) { uint8_t det_caps[4]; union dwnstream_port_caps_byte0 *port_caps = (union dwnstream_port_caps_byte0 *)det_caps; diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_interface.h b/drivers/gpu/drm/amd/display/include/asic_capability_interface.h deleted file mode 100644 index 57cc72fdc560..000000000000 --- a/drivers/gpu/drm/amd/display/include/asic_capability_interface.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of enc software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and enc permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_ASIC_CAPABILITY_INTERFACE_H__ -#define __DAL_ASIC_CAPABILITY_INTERFACE_H__ - -/* Include */ -#include "include/asic_capability_types.h" - -/* Forward declaration */ -struct hw_asic_id; - -/* ASIC capability */ -struct asic_capability { - struct dc_context *ctx; - struct asic_caps caps; - struct asic_stereo_3d_caps stereo_3d_caps; - struct asic_bugs bugs; - uint32_t data[ASIC_DATA_MAX_NUMBER]; -}; - -/** - * Interfaces - */ - -/* Create and initialize ASIC capability */ -struct asic_capability *dal_asic_capability_create(struct hw_asic_id *init, - struct dc_context *ctx); - -/* Destroy ASIC capability and free memory space */ -void dal_asic_capability_destroy(struct asic_capability **cap); - -#endif /* __DAL_ASIC_CAPABILITY_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/asic_capability_types.h b/drivers/gpu/drm/amd/display/include/asic_capability_types.h deleted file mode 100644 index c44dae043599..000000000000 --- a/drivers/gpu/drm/amd/display/include/asic_capability_types.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DAL_ASIC_CAPABILITY_TYPES_H__ -#define __DAL_ASIC_CAPABILITY_TYPES_H__ - -/* - * ASIC Capabilities - */ -struct asic_caps { - bool CONSUMER_SINGLE_SELECTED_TIMING:1; - bool UNDERSCAN_ADJUST:1; - bool DELTA_SIGMA_SUPPORT:1; - bool PANEL_SELF_REFRESH_SUPPORTED:1; - bool IS_FUSION:1; - bool DP_MST_SUPPORTED:1; - bool UNDERSCAN_FOR_HDMI_ONLY:1; - bool DVI_CLOCK_SHARE_CAPABILITY:1; - bool SUPPORT_CEA861E_FINAL:1; - bool MIRABILIS_SUPPORTED:1; - bool MIRABILIS_ENABLED_BY_DEFAULT:1; - bool DEVICE_TAG_REMAP_SUPPORTED:1; - bool HEADLESS_NO_OPM_SUPPORTED:1; - bool WIRELESS_LIMIT_TO_720P:1; - bool WIRELESS_FULL_TIMING_ADJUSTMENT:1; - bool WIRELESS_TIMING_ADJUSTMENT:1; - bool WIRELESS_COMPRESSED_AUDIO:1; - bool VCE_SUPPORTED:1; - bool HPD_CHECK_FOR_EDID:1; - bool NEED_MC_TUNING:1; - bool SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT:1; - bool DFSBYPASS_DYNAMIC_SUPPORT:1; - bool SUPPORT_8BPP:1; -}; - -/* - * ASIC Stereo 3D Caps - */ -struct asic_stereo_3d_caps { - bool SUPPORTED:1; - bool DISPLAY_BASED_ON_WS:1; - bool HDMI_FRAME_PACK:1; - bool INTERLACE_FRAME_PACK:1; - bool DISPLAYPORT_FRAME_PACK:1; - bool DISPLAYPORT_FRAME_ALT:1; - bool INTERLEAVE:1; -}; - -/* - * ASIC Bugs - */ -struct asic_bugs { - bool MST_SYMBOL_MISALIGNMENT:1; - bool PSR_2X_LANE_GANGING:1; - bool LB_WA_IS_SUPPORTED:1; - bool ROM_REGISTER_ACCESS:1; - bool PSR_WA_OVERSCAN_CRC_ERROR:1; -}; - -/* - * ASIC Data - */ -enum asic_data { - ASIC_DATA_FIRST = 0, - ASIC_DATA_DCE_VERSION = ASIC_DATA_FIRST, - ASIC_DATA_DCE_VERSION_MINOR, - ASIC_DATA_LINEBUFFER_SIZE, - ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY, - ASIC_DATA_MC_LATENCY, - ASIC_DATA_MC_LATENCY_SLOW, - ASIC_DATA_MEMORYTYPE_MULTIPLIER, - ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR, - ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE, - ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY, - ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN, - ASIC_DATA_DOWNSCALE_LIMIT, - ASIC_DATA_MAX_NUMBER /* end of enum */ -}; - -/* - * ASIC Feature Flags - */ -struct asic_feature_flags { - union { - uint32_t raw; - struct { - uint32_t LEGACY_CLIENT:1; - uint32_t PACKED_PIXEL_FORMAT:1; - uint32_t WORKSTATION_STEREO:1; - uint32_t WORKSTATION:1; - } bits; - }; -}; - -#endif /* __DAL_ASIC_CAPABILITY_TYPES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index 9ab9065735f7..7de4fa5a0726 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -190,14 +190,6 @@ struct bp_hw_crtc_timing_parameters { } flags; }; -struct bp_hw_crtc_overscan_parameters { - enum controller_id controller_id; - uint32_t h_overscan_left; - uint32_t h_overscan_right; - uint32_t v_overscan_top; - uint32_t v_overscan_bottom; -}; - struct bp_adjust_pixel_clock_parameters { /* Input: Signal Type - to be converted to Encoder mode */ enum signal_type signal_type; diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index 0a6ba91e3eba..effe03b8f418 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -52,12 +52,6 @@ enum ddc_service_type { DDC_SERVICE_TYPE_DISPLAY_PORT_MST, }; -enum dcs_dpcd_revision { - DCS_DPCD_REV_10 = 0x10, - DCS_DPCD_REV_11 = 0x11, - DCS_DPCD_REV_12 = 0x12 -}; - /** * display sink capability */ @@ -97,7 +91,6 @@ struct display_sink_capability { uint32_t dp_link_rate; uint32_t dp_link_spead; - enum dcs_dpcd_revision dpcd_revision; /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ bool is_dp_hdmi_s3d_converter; diff --git a/drivers/gpu/drm/amd/display/include/irq_interface.h b/drivers/gpu/drm/amd/display/include/irq_interface.h deleted file mode 100644 index 077ded3fbedd..000000000000 --- a/drivers/gpu/drm/amd/display/include/irq_interface.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_IRQ_INTERFACE_H__ -#define __DAL_IRQ_INTERFACE_H__ - -#include "gpio_types.h" - -#endif diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 6160a467ba37..479e5fff8a00 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -38,34 +38,11 @@ enum { MAX_CONTROLLER_NUM = 6 }; -enum link_service_type { - LINK_SERVICE_TYPE_LEGACY = 0, - LINK_SERVICE_TYPE_DP_SST, - LINK_SERVICE_TYPE_DP_MST, - LINK_SERVICE_TYPE_MAX -}; - -enum dpcd_value_mask { - DPCD_VALUE_MASK_MAX_LANE_COUNT_LANE_COUNT = 0x1F, - DPCD_VALUE_MASK_MAX_LANE_COUNT_TPS3_SUPPORTED = 0x40, - DPCD_VALUE_MASK_MAX_LANE_COUNT_ENHANCED_FRAME_EN = 0x80, - DPCD_VALUE_MASK_MAX_DOWNSPREAD = 0x01, - DPCD_VALUE_MASK_LANE_ALIGN_STATUS_INTERLANE_ALIGN_DONE = 0x01 -}; - enum dp_power_state { DP_POWER_STATE_D0 = 1, DP_POWER_STATE_D3 }; -enum dpcd_downstream_port_types { - DPCD_DOWNSTREAM_DP, - DPCD_DOWNSTREAM_VGA, - DPCD_DOWNSTREAM_DVI_HDMI, - /* has no EDID (TV, CV) */ - DPCD_DOWNSTREAM_NON_DDC -}; - enum edp_revision { /* eDP version 1.1 or lower */ EDP_REVISION_11 = 0x00, @@ -135,36 +112,6 @@ enum dp_panel_mode { DP_PANEL_MODE_SPECIAL }; -/** - * @brief LinkServiceInitOptions to set certain bits - */ -struct link_service_init_options { - uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1; -}; - -/** - * @brief data required to initialize LinkService - */ -struct link_service_init_data { - /* number of displays indices which the MST Mgr would manange*/ - uint32_t num_of_displays; - enum link_service_type link_type; - /*struct mst_mgr_callback_object*topology_change_callback;*/ - /* native aux access */ - struct ddc_service *dpcd_access_srv; - /* for calling HWSS to program HW */ - struct hw_sequencer *hwss; - /* the source which to register IRQ on */ - enum dc_irq_source irq_src_hpd_rx; - enum dc_irq_source irq_src_dp_sink; - /* other init options such as SW Workarounds */ - struct link_service_init_options init_options; - uint32_t connector_enum_id; - struct graphics_object_id connector_id; - struct dc_context *ctx; - struct topology_mgr *tm; -}; - /* DPCD_ADDR_TRAINING_LANEx_SET registers value */ union dpcd_training_lane_set { struct { @@ -189,28 +136,6 @@ union dpcd_training_lane_set { uint8_t raw; }; -/** - * @brief represent the 16 byte - * global unique identifier - */ -struct mst_guid { - uint8_t ids[16]; -}; - -/** - * @brief represents the relative address used - * to identify a node in MST topology network - */ -struct mst_rad { - /* number of links. rad[0] up to - * rad [linkCount - 1] are valid. */ - uint32_t rad_link_count; - /* relative address. rad[0] is the - * first device connected to the source. */ - uint8_t rad[15]; - /* extra 10 bytes for underscores; for e.g.:2_1_8*/ - int8_t rad_str[25]; -}; /* DP MST stream allocation (payload bandwidth number) */ struct dp_mst_stream_allocation { diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index a50f7ed74a33..d87f84a56fcc 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -47,13 +47,10 @@ enum signal_type { bool dc_is_hdmi_signal(enum signal_type signal); bool dc_is_dp_sst_signal(enum signal_type signal); bool dc_is_dp_signal(enum signal_type signal); -bool dc_is_dp_external_signal(enum signal_type signal); -bool dc_is_analog_signal(enum signal_type signal); bool dc_is_embedded_signal(enum signal_type signal); bool dc_is_dvi_signal(enum signal_type signal); bool dc_is_dvi_single_link_signal(enum signal_type signal); bool dc_is_dual_link_signal(enum signal_type signal); bool dc_is_audio_capable_signal(enum signal_type signal); -bool dc_is_digital_encoder_compatible_signal(enum signal_type signal); #endif -- GitLab From 6235b23cb92ba5bf30430400b216ea2114afe777 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 18:57:57 -0500 Subject: [PATCH 0190/2898] drm/amd/display: remove hw_crtc_timing Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce/dce_stream_encoder.c | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../amd/display/dc/inc/hw/stream_encoder.h | 2 +- .../amd/display/include/hw_sequencer_types.h | 40 ------------------- 4 files changed, 3 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index c510e95eb948..7e6661bda970 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -681,7 +681,7 @@ static void dce110_stream_encoder_dp_unblank( uint64_t m_vid_l = n_vid; - m_vid_l *= param->crtc_timing.pixel_clock; + m_vid_l *= param->pixel_clk_khz; m_vid_l = div_u64(m_vid_l, param->link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1a9ba127b781..b51668e3bb52 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -886,7 +886,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct encoder_unblank_param params = { { 0 } }; /* only 3 items below are used by unblank */ - params.crtc_timing.pixel_clock = + params.pixel_clk_khz = pipe_ctx->stream->public.timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index cb369af29d69..674bebfe3bd2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -36,8 +36,8 @@ struct encoder_info_frame { }; struct encoder_unblank_param { - struct hw_crtc_timing crtc_timing; struct dc_link_settings link_settings; + unsigned int pixel_clk_khz; }; struct encoder_set_dp_phy_pattern_param { diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 6bbca1b4d736..f99a03266149 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -40,46 +40,6 @@ struct drr_params { uint32_t vertical_total_max; }; -/* CRTC timing structure */ -struct hw_crtc_timing { - uint32_t h_total; - uint32_t h_addressable; - uint32_t h_overscan_left; - uint32_t h_overscan_right; - uint32_t h_sync_start; - uint32_t h_sync_width; - - uint32_t v_total; - uint32_t v_addressable; - uint32_t v_overscan_top; - uint32_t v_overscan_bottom; - uint32_t v_sync_start; - uint32_t v_sync_width; - - /* in KHz */ - uint32_t pixel_clock; - - struct { - uint32_t INTERLACED:1; - uint32_t DOUBLESCAN:1; - uint32_t PIXEL_REPETITION:4; /* 1...10 */ - uint32_t HSYNC_POSITIVE_POLARITY:1; - uint32_t VSYNC_POSITIVE_POLARITY:1; - /* frame should be packed for 3D - * (currently this refers to HDMI 1.4a FramePacking format */ - uint32_t HORZ_COUNT_BY_TWO:1; - uint32_t PACK_3D_FRAME:1; - /* 0 - left eye polarity, 1 - right eye polarity */ - uint32_t RIGHT_EYE_3D_POLARITY:1; - /* DVI-DL High-Color mode */ - uint32_t HIGH_COLOR_DL_MODE:1; - uint32_t Y_ONLY:1; - /* HDMI 2.0 - Support scrambling for TMDS character - * rates less than or equal to 340Mcsc */ - uint32_t LTE_340MCSC_SCRAMBLE:1; - } flags; -}; - /* TODO hw_info_frame and hw_info_packet structures are same as in encoder * merge it*/ struct hw_info_packet { -- GitLab From 6e4d6beec6dae279ec7ac27c9034b2208898f382 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 20:36:14 -0500 Subject: [PATCH 0191/2898] drm/amd/display: remove hw_info_frame - construct using encoder_info_frame directly Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 124 ++++++------------ .../amd/display/include/hw_sequencer_types.h | 23 ---- 2 files changed, 40 insertions(+), 107 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6037ee25598c..fe79a2890247 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1211,70 +1211,27 @@ void validate_guaranteed_copy_streams( } } -static void translate_info_frame(const struct hw_info_frame *hw_info_frame, - struct encoder_info_frame *encoder_info_frame) +static void patch_gamut_packet_checksum( + struct encoder_info_packet *gamut_packet) { - memset( - encoder_info_frame, 0, sizeof(struct encoder_info_frame)); - /* For gamut we recalc checksum */ - if (hw_info_frame->gamut_packet.valid) { + if (gamut_packet->valid) { uint8_t chk_sum = 0; uint8_t *ptr; uint8_t i; - memmove( - &encoder_info_frame->gamut, - &hw_info_frame->gamut_packet, - sizeof(struct hw_info_packet)); - /*start of the Gamut data. */ - ptr = &encoder_info_frame->gamut.sb[3]; + ptr = &gamut_packet->sb[3]; - for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++) + for (i = 0; i <= gamut_packet->sb[1]; i++) chk_sum += ptr[i]; - encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum); - } - - if (hw_info_frame->avi_info_packet.valid) { - memmove( - &encoder_info_frame->avi, - &hw_info_frame->avi_info_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->vendor_info_packet.valid) { - memmove( - &encoder_info_frame->vendor, - &hw_info_frame->vendor_info_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->spd_packet.valid) { - memmove( - &encoder_info_frame->spd, - &hw_info_frame->spd_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->vsc_packet.valid) { - memmove( - &encoder_info_frame->vsc, - &hw_info_frame->vsc_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->hdrsmd_packet.valid) { - memmove( - &encoder_info_frame->hdrsmd, - &hw_info_frame->hdrsmd_packet, - sizeof(struct hw_info_packet)); + gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); } } static void set_avi_info_frame( - struct hw_info_packet *info_packet, + struct encoder_info_packet *info_packet, struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; @@ -1288,9 +1245,6 @@ static void set_avi_info_frame( uint8_t *check_sum = NULL; uint8_t byte_index = 0; - if (info_packet == NULL) - return; - color_space = pipe_ctx->stream->public.output_color_space; /* Initialize header */ @@ -1458,8 +1412,9 @@ static void set_avi_info_frame( info_packet->valid = true; } -static void set_vendor_info_packet(struct core_stream *stream, - struct hw_info_packet *info_packet) +static void set_vendor_info_packet( + struct encoder_info_packet *info_packet, + struct core_stream *stream) { uint32_t length = 0; bool hdmi_vic_mode = false; @@ -1467,9 +1422,6 @@ static void set_vendor_info_packet(struct core_stream *stream, uint32_t i = 0; enum dc_timing_3d_format format; - ASSERT_CRITICAL(stream != NULL); - ASSERT_CRITICAL(info_packet != NULL); - format = stream->public.timing.timing_3d_format; /* Can be different depending on packet content */ @@ -1567,8 +1519,9 @@ static void set_vendor_info_packet(struct core_stream *stream, info_packet->valid = true; } -static void set_spd_info_packet(struct core_stream *stream, - struct hw_info_packet *info_packet) +static void set_spd_info_packet( + struct encoder_info_packet *info_packet, + struct core_stream *stream) { /* SPD info packet for FreeSync */ @@ -1688,9 +1641,9 @@ static void set_spd_info_packet(struct core_stream *stream, } static void set_hdr_static_info_packet( + struct encoder_info_packet *info_packet, struct core_surface *surface, - struct core_stream *stream, - struct hw_info_packet *info_packet) + struct core_stream *stream) { uint16_t i = 0; enum signal_type signal = stream->signal; @@ -1791,8 +1744,9 @@ static void set_hdr_static_info_packet( } } -static void set_vsc_info_packet(struct core_stream *stream, - struct hw_info_packet *info_packet) +static void set_vsc_info_packet( + struct encoder_info_packet *info_packet, + struct core_stream *stream) { unsigned int vscPacketRevision = 0; unsigned int i; @@ -1894,36 +1848,38 @@ struct clock_source *dc_resource_find_first_free_pll( void resource_build_info_frame(struct pipe_ctx *pipe_ctx) { enum signal_type signal = SIGNAL_TYPE_NONE; - struct hw_info_frame info_frame = { { 0 } }; + struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame; /* default all packets to invalid */ - info_frame.avi_info_packet.valid = false; - info_frame.gamut_packet.valid = false; - info_frame.vendor_info_packet.valid = false; - info_frame.spd_packet.valid = false; - info_frame.vsc_packet.valid = false; - info_frame.hdrsmd_packet.valid = false; + info->avi.valid = false; + info->gamut.valid = false; + info->vendor.valid = false; + info->hdrsmd.valid = false; + info->vsc.valid = false; signal = pipe_ctx->stream->signal; /* HDMi and DP have different info packets*/ if (dc_is_hdmi_signal(signal)) { - set_avi_info_frame( - &info_frame.avi_info_packet, pipe_ctx); - set_vendor_info_packet( - pipe_ctx->stream, &info_frame.vendor_info_packet); - set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); - set_hdr_static_info_packet(pipe_ctx->surface, - pipe_ctx->stream, &info_frame.hdrsmd_packet); + set_avi_info_frame(&info->avi, pipe_ctx); + + set_vendor_info_packet(&info->vendor, pipe_ctx->stream); + + set_spd_info_packet(&info->spd, pipe_ctx->stream); + + set_hdr_static_info_packet(&info->hdrsmd, + pipe_ctx->surface, pipe_ctx->stream); + } else if (dc_is_dp_signal(signal)) { - set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); - set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet); - set_hdr_static_info_packet(pipe_ctx->surface, - pipe_ctx->stream, &info_frame.hdrsmd_packet); + set_vsc_info_packet(&info->vsc, pipe_ctx->stream); + + set_spd_info_packet(&info->spd, pipe_ctx->stream); + + set_hdr_static_info_packet(&info->hdrsmd, + pipe_ctx->surface, pipe_ctx->stream); } - translate_info_frame(&info_frame, - &pipe_ctx->encoder_info_frame); + patch_gamut_packet_checksum(&info->gamut); } enum dc_status resource_map_clock_resources( diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index f99a03266149..6f0475c25566 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -40,27 +40,4 @@ struct drr_params { uint32_t vertical_total_max; }; -/* TODO hw_info_frame and hw_info_packet structures are same as in encoder - * merge it*/ -struct hw_info_packet { - bool valid; - uint8_t hb0; - uint8_t hb1; - uint8_t hb2; - uint8_t hb3; - uint8_t sb[32]; -}; - -struct hw_info_frame { - /* Auxiliary Video Information */ - struct hw_info_packet avi_info_packet; - struct hw_info_packet gamut_packet; - struct hw_info_packet vendor_info_packet; - /* Source Product Description */ - struct hw_info_packet spd_packet; - /* Video Stream Configuration */ - struct hw_info_packet vsc_packet; - struct hw_info_packet hdrsmd_packet; -}; - #endif -- GitLab From a10eadfb152960a760c4f52c42607d27cb3f1543 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 20:48:21 -0500 Subject: [PATCH 0192/2898] drm/amd/display: remove SIGNAL_TYPE_WIRELESS Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/log_helpers.c | 1 - drivers/gpu/drm/amd/display/dc/basics/signal_types.c | 3 +-- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 1 - drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 1 - drivers/gpu/drm/amd/display/include/signal_types.h | 4 ---- 6 files changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index 61f36a7f322b..c4eddee8de1b 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -44,7 +44,6 @@ static const struct dc_signal_type_info signal_type_info_tbl[] = { {SIGNAL_TYPE_DISPLAY_PORT, "DP"}, {SIGNAL_TYPE_DISPLAY_PORT_MST, "MST"}, {SIGNAL_TYPE_EDP, "eDP"}, - {SIGNAL_TYPE_WIRELESS, "Wireless"}, {SIGNAL_TYPE_VIRTUAL, "Virtual"} }; diff --git a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c index 247487c3db71..534c803e7091 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c +++ b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c @@ -75,7 +75,6 @@ bool dc_is_audio_capable_signal(enum signal_type signal) { return (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == SIGNAL_TYPE_DISPLAY_PORT_MST || - dc_is_hdmi_signal(signal) || - signal == SIGNAL_TYPE_WIRELESS); + dc_is_hdmi_signal(signal)); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 62cfc5cbe773..f4f46d4f0cf0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1051,9 +1051,6 @@ static bool construct( if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD && link->public.connector_signal == SIGNAL_TYPE_RGB) continue; - if (link->device_tag.dev_id.device_type == DEVICE_TYPE_WIRELESS - && link->public.connector_signal != SIGNAL_TYPE_WIRELESS) - continue; break; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 930ae1377ab6..e9d1a54bffd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -941,7 +941,6 @@ bool dce110_link_encoder_construct( enc110->base.hpd_source = init_data->hpd_source; enc110->base.connector = init_data->connector; - enc110->base.input_signals = SIGNAL_TYPE_ALL; enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 49c4b6587456..ac4010b9c638 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -186,7 +186,6 @@ struct link_encoder { struct dc_context *ctx; struct graphics_object_id id; struct graphics_object_id connector; - uint32_t input_signals; uint32_t output_signals; enum engine_id preferred_engine; struct encoder_feature_support features; diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index d87f84a56fcc..1a2ca53c68cd 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -36,11 +36,7 @@ enum signal_type { SIGNAL_TYPE_DISPLAY_PORT = (1 << 5), SIGNAL_TYPE_DISPLAY_PORT_MST = (1 << 6), SIGNAL_TYPE_EDP = (1 << 7), - SIGNAL_TYPE_WIRELESS = (1 << 8), /* Wireless Display */ SIGNAL_TYPE_VIRTUAL = (1 << 9), /* Virtual Display */ - - SIGNAL_TYPE_COUNT = 10, - SIGNAL_TYPE_ALL = (1 << SIGNAL_TYPE_COUNT) - 1 }; /* help functions for signal types manipulation */ -- GitLab From 5e701406ed446a79787feede65c81b8d3cfbdfb8 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 20:56:08 -0500 Subject: [PATCH 0193/2898] drm/amd/display: remove dead code Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/bios/bios_parser.c | 76 ------------ .../drm/amd/display/dc/bios/command_table.c | 114 ------------------ .../drm/amd/display/dc/bios/command_table.h | 7 -- .../gpu/drm/amd/display/dc/dc_bios_types.h | 6 - .../amd/display/include/bios_parser_types.h | 20 --- 5 files changed, 223 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index ebd2e419f8f2..656c39ac0256 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -545,80 +545,6 @@ static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, return BP_RESULT_NORECORD; } -static uint32_t bios_parser_get_gpio_record( - struct dc_bios *dcb, - struct graphics_object_id id, - struct bp_gpio_cntl_info *gpio_record, - uint32_t record_size) -{ - struct bios_parser *bp = BP_FROM_DCB(dcb); - ATOM_COMMON_RECORD_HEADER *header = NULL; - ATOM_OBJECT_GPIO_CNTL_RECORD *record = NULL; - ATOM_OBJECT *object = get_bios_object(bp, id); - uint32_t offset; - uint32_t pins_number; - uint32_t i; - - if (!object) - return 0; - - /* Initialise offset */ - offset = le16_to_cpu(object->usRecordOffset) - + bp->object_info_tbl_offset; - - for (;;) { - /* Get record header */ - header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); - if (!header || header->ucRecordType == LAST_RECORD_TYPE || - !header->ucRecordSize) - break; - - /* If this is gpio control record - stop. We found the record */ - if (header->ucRecordType == ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE - && header->ucRecordSize - >= sizeof(ATOM_OBJECT_GPIO_CNTL_RECORD)) { - record = (ATOM_OBJECT_GPIO_CNTL_RECORD *) header; - break; - } - - /* Advance to next record */ - offset += header->ucRecordSize; - } - - /* If we did not find a record - return */ - if (!record) - return 0; - - /* Extract gpio IDs from bios record (make sure we do not exceed passed - * array size) */ - pins_number = (record->ucNumberOfPins < record_size ? - record->ucNumberOfPins : record_size); - for (i = 0; i < pins_number; i++) { - uint8_t output_state = ((record->asGpio[i].ucGPIO_PinState - & GPIO_PIN_OUTPUT_STATE_MASK) - >> GPIO_PIN_OUTPUT_STATE_SHIFT); - gpio_record[i].id = record->asGpio[i].ucGPIOID; - - switch (output_state) { - case GPIO_PIN_STATE_ACTIVE_LOW: - gpio_record[i].state = - GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW; - break; - - case GPIO_PIN_STATE_ACTIVE_HIGH: - gpio_record[i].state = - GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH; - break; - - default: - BREAK_TO_DEBUGGER(); /* Invalid Pin Output State */ - break; - } - } - - return pins_number; -} - enum bp_result bios_parser_get_device_tag_record( struct bios_parser *bp, ATOM_OBJECT *object, @@ -4064,8 +3990,6 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_dst_number = bios_parser_get_dst_number, - .get_gpio_record = bios_parser_get_gpio_record, - .get_src_obj = bios_parser_get_src_obj, .get_dst_obj = bios_parser_get_dst_obj, diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 88aaf53cb8c4..3f7b2dabc2b0 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -54,12 +54,10 @@ static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp); static void init_adjust_display_pll(struct bios_parser *bp); static void init_dac_encoder_control(struct bios_parser *bp); static void init_dac_output_control(struct bios_parser *bp); -static void init_blank_crtc(struct bios_parser *bp); static void init_set_crtc_timing(struct bios_parser *bp); static void init_select_crtc_source(struct bios_parser *bp); static void init_enable_crtc(struct bios_parser *bp); static void init_enable_crtc_mem_req(struct bios_parser *bp); -static void init_compute_memore_engine_pll(struct bios_parser *bp); static void init_external_encoder_control(struct bios_parser *bp); static void init_enable_disp_power_gating(struct bios_parser *bp); static void init_program_clock(struct bios_parser *bp); @@ -74,13 +72,11 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) init_adjust_display_pll(bp); init_dac_encoder_control(bp); init_dac_output_control(bp); - init_blank_crtc(bp); init_set_crtc_timing(bp); init_select_crtc_source(bp); init_enable_crtc(bp); init_enable_crtc_mem_req(bp); init_program_clock(bp); - init_compute_memore_engine_pll(bp); init_external_encoder_control(bp); init_enable_disp_power_gating(bp); init_set_dce_clock(bp); @@ -1673,66 +1669,6 @@ static enum bp_result dac2_output_control_v1( return result; } -/******************************************************************************* - ******************************************************************************** - ** - ** BLANK CRTC - ** - ******************************************************************************** - *******************************************************************************/ - -static enum bp_result blank_crtc_v1( - struct bios_parser *bp, - struct bp_blank_crtc_parameters *bp_params, - bool blank); - -static void init_blank_crtc(struct bios_parser *bp) -{ - switch (BIOS_CMD_TABLE_PARA_REVISION(BlankCRTC)) { - case 1: - bp->cmd_tbl.blank_crtc = blank_crtc_v1; - break; - default: - bp->cmd_tbl.blank_crtc = NULL; - break; - } -} - -static enum bp_result blank_crtc_v1( - struct bios_parser *bp, - struct bp_blank_crtc_parameters *bp_params, - bool blank) -{ - enum bp_result result = BP_RESULT_FAILURE; - BLANK_CRTC_PARAMETERS params = {0}; - uint8_t atom_controller_id; - - if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, - &atom_controller_id)) { - params.ucCRTC = (uint8_t)atom_controller_id; - - if (blank) - params.ucBlanking = ATOM_BLANKING; - else - params.ucBlanking = ATOM_BLANKING_OFF; - params.usBlackColorRCr = - cpu_to_le16((uint16_t)bp_params->black_color_rcr); - params.usBlackColorGY = - cpu_to_le16((uint16_t)bp_params->black_color_gy); - params.usBlackColorBCb = - cpu_to_le16((uint16_t)bp_params->black_color_bcb); - - if (EXEC_BIOS_CMD_TABLE(BlankCRTC, params)) - result = BP_RESULT_OK; - } else - /* Not support more than two CRTC as current ASIC, update this - * if needed. - */ - result = BP_RESULT_BADINPUT; - - return result; -} - /******************************************************************************* ******************************************************************************** ** @@ -2239,56 +2175,6 @@ static enum bp_result program_clock_v6( return result; } -/******************************************************************************* - ******************************************************************************** - ** - ** COMPUTE MEMORY ENGINE PLL - ** - ******************************************************************************** - *******************************************************************************/ - -static enum bp_result compute_memore_engine_pll_v4( - struct bios_parser *bp, - struct bp_display_clock_parameters *bp_params); - -static void init_compute_memore_engine_pll(struct bios_parser *bp) -{ - switch (BIOS_CMD_TABLE_PARA_REVISION(ComputeMemoryEnginePLL)) { - case 4: - bp->cmd_tbl.compute_memore_engine_pll = - compute_memore_engine_pll_v4; - break; - default: - bp->cmd_tbl.compute_memore_engine_pll = NULL; - break; - } -} - -static enum bp_result compute_memore_engine_pll_v4( - struct bios_parser *bp, - struct bp_display_clock_parameters *bp_params) -{ - enum bp_result result = BP_RESULT_FAILURE; - COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 params; - - memset(¶ms, 0, sizeof(params)); - - params.ulClock = cpu_to_le32(bp_params->target_display_clock / 10); - - /* Initialize this to the target clock in case this call fails */ - bp_params->actual_display_clock = bp_params->target_display_clock; - - if (EXEC_BIOS_CMD_TABLE(ComputeMemoryEnginePLL, params)) { - /* Convert from 10KHz units back to KHz */ - bp_params->actual_display_clock = - le32_to_cpu(params.ulClock) * 10; - bp_params->actual_post_divider_id = params.ucPostDiv; - result = BP_RESULT_OK; - } - - return result; -} - /******************************************************************************* ******************************************************************************** ** diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h index b8e6ef06c0c7..94f3d43a7471 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h @@ -68,10 +68,6 @@ struct cmd_tbl { enum bp_result (*dac2_output_control)( struct bios_parser *bp, bool enable); - enum bp_result (*blank_crtc)( - struct bios_parser *bp, - struct bp_blank_crtc_parameters *bp_params, - bool blank); enum bp_result (*set_crtc_timing)( struct bios_parser *bp, struct bp_hw_crtc_timing_parameters *bp_params); @@ -89,9 +85,6 @@ struct cmd_tbl { enum bp_result (*program_clock)( struct bios_parser *bp, struct bp_pixel_clock_parameters *bp_params); - enum bp_result (*compute_memore_engine_pll)( - struct bios_parser *bp, - struct bp_display_clock_parameters *bp_params); enum bp_result (*external_encoder_control)( struct bios_parser *bp, struct bp_external_encoder_control *cntl); diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 790c5bd51cb9..6e1291d5f51d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -51,12 +51,6 @@ struct dc_vbios_funcs { struct dc_bios *bios, struct graphics_object_id id); - uint32_t (*get_gpio_record)( - struct dc_bios *dcb, - struct graphics_object_id id, - struct bp_gpio_cntl_info *gpio_record, - uint32_t record_size); - enum bp_result (*get_src_obj)( struct dc_bios *bios, struct graphics_object_id object_id, uint32_t index, diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index 7de4fa5a0726..0840f69cde99 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -156,13 +156,6 @@ struct bp_transmitter_control { bool single_pll_mode; }; -struct bp_blank_crtc_parameters { - enum controller_id controller_id; - uint32_t black_color_rcr; - uint32_t black_color_gy; - uint32_t black_color_bcb; -}; - struct bp_hw_crtc_timing_parameters { enum controller_id controller_id; /* horizontal part */ @@ -252,14 +245,6 @@ struct bp_pixel_clock_parameters { } flags; }; -struct bp_display_clock_parameters { - uint32_t target_display_clock; /* KHz */ - /* Actual Display Clock set due to clock divider granularity KHz */ - uint32_t actual_display_clock; - /* Actual Post Divider ID used to generate the actual clock */ - uint32_t actual_post_divider_id; -}; - enum bp_dce_clock_type { DCECLOCK_TYPE_DISPLAY_CLOCK = 0, DCECLOCK_TYPE_DPREFCLK = 1 @@ -322,9 +307,4 @@ struct bp_encoder_cap_info { uint32_t RESERVED:30; }; -struct bp_gpio_cntl_info { - uint32_t id; - enum gpio_pin_output_state state; -}; - #endif /*__DAL_BIOS_PARSER_TYPES_H__ */ -- GitLab From f33ad37feb12639e3b4015d27840395793107d7b Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 14 Jan 2017 20:56:08 -0500 Subject: [PATCH 0194/2898] drm/amd/display: remove calculate_adjustments in conversion.h - these are moved to color module Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Aric Cyr Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/basics/conversion.c | 118 ------------------ .../drm/amd/display/dc/basics/conversion.h | 10 -- 2 files changed, 128 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index 5682fea2080d..a2e22ae12adb 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -103,124 +103,6 @@ void convert_float_matrix( } } -static void calculate_adjustments_common( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix) -{ - const struct fixed31_32 sin_hue = - dal_fixed31_32_sin(adjustments->hue); - const struct fixed31_32 cos_hue = - dal_fixed31_32_cos(adjustments->hue); - - const struct fixed31_32 multiplier = - dal_fixed31_32_mul( - adjustments->contrast, - adjustments->saturation); - - matrix[0] = dal_fixed31_32_mul( - ideal_matrix[0], - adjustments->contrast); - - matrix[1] = dal_fixed31_32_mul( - ideal_matrix[1], - adjustments->contrast); - - matrix[2] = dal_fixed31_32_mul( - ideal_matrix[2], - adjustments->contrast); - - matrix[4] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal_matrix[8], - sin_hue), - dal_fixed31_32_mul( - ideal_matrix[4], - cos_hue))); - - matrix[5] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal_matrix[9], - sin_hue), - dal_fixed31_32_mul( - ideal_matrix[5], - cos_hue))); - - matrix[6] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_add( - dal_fixed31_32_mul( - ideal_matrix[10], - sin_hue), - dal_fixed31_32_mul( - ideal_matrix[6], - cos_hue))); - - matrix[7] = ideal_matrix[7]; - - matrix[8] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal_matrix[8], - cos_hue), - dal_fixed31_32_mul( - ideal_matrix[4], - sin_hue))); - - matrix[9] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal_matrix[9], - cos_hue), - dal_fixed31_32_mul( - ideal_matrix[5], - sin_hue))); - - matrix[10] = dal_fixed31_32_mul( - multiplier, - dal_fixed31_32_sub( - dal_fixed31_32_mul( - ideal_matrix[10], - cos_hue), - dal_fixed31_32_mul( - ideal_matrix[6], - sin_hue))); - - matrix[11] = ideal_matrix[11]; -} - -void calculate_adjustments( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix) -{ - calculate_adjustments_common(ideal_matrix, adjustments, matrix); - - matrix[3] = dal_fixed31_32_add( - ideal_matrix[3], - dal_fixed31_32_mul( - adjustments->brightness, - dal_fixed31_32_from_fraction(86, 100))); -} - -void calculate_adjustments_y_only( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix) -{ - calculate_adjustments_common(ideal_matrix, adjustments, matrix); - - matrix[3] = dal_fixed31_32_add( - ideal_matrix[3], - adjustments->brightness); -} - unsigned int log_2(unsigned int num) { unsigned int result = 0; diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h index b7fe431a7952..189325f68cfd 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.h +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -38,16 +38,6 @@ void convert_float_matrix( struct fixed31_32 *flt, uint32_t buffer_size); -void calculate_adjustments( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix); - -void calculate_adjustments_y_only( - const struct fixed31_32 *ideal_matrix, - const struct dc_csc_adjustments *adjustments, - struct fixed31_32 *matrix); - unsigned int log_2(unsigned int num); #endif -- GitLab From e0d7ce783a88824cc7e3af0f1aa2d1076364cbf4 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 6 Jan 2017 15:55:47 -0500 Subject: [PATCH 0195/2898] drm/amd/display: enable clock gating and dchubp power gating also refactor to clean reduce loc to achieve same logic Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Yongqiang Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f53b41339951..e0143f9f0421 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -145,7 +145,8 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; - bool disable_power_gate; + bool disable_dpp_power_gate; + bool disable_hubp_power_gate; bool disable_clock_gate; bool disable_dmcu; bool disable_color_module; -- GitLab From 306dadf01aba27bed2daa49a782b22586af64c93 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 13 Jan 2017 16:19:36 -0500 Subject: [PATCH 0196/2898] drm/amd/display: Set default degamma to sRGB instead of bypass Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b51668e3bb52..ee393a168c84 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -255,7 +255,7 @@ static bool dce110_set_input_transfer_func( if (tf == NULL) { /* Default case if no input transfer function specified */ ipp->funcs->ipp_set_degamma(ipp, - IPP_DEGAMMA_MODE_BYPASS); + IPP_DEGAMMA_MODE_HW_sRGB); } else if (tf->public.type == TF_TYPE_PREDEFINED) { switch (tf->public.tf) { case TRANSFER_FUNCTION_SRGB: -- GitLab From 534db198866070fdb655423637afdce6cf0c05db Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 13 Jan 2017 16:49:26 -0500 Subject: [PATCH 0197/2898] drm/amd/display: HDR Enablement For Applications - Made sure dest color space is updated in stream and info frame - Optimized segment distribution algorithm for regamma mapping Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Aric Cyr Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 14 +++ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 6 +- .../display/dc/dce110/dce110_hw_sequencer.c | 94 +++++++++++++++---- .../gpu/drm/amd/display/dc/inc/hw/transform.h | 11 +++ 4 files changed, 107 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fe79a2890247..8b41c7708562 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1310,6 +1310,20 @@ static void set_avi_info_frame( info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = COLORIMETRY_NO_DATA; + if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || + color_space == COLOR_SPACE_2020_YCBCR) { + info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = + COLORIMETRYEX_BT2020RGBYCBCR; + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_EXTENDED; + } else if (color_space == COLOR_SPACE_ADOBERGB) { + info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = + COLORIMETRYEX_ADOBERGB; + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_EXTENDED; + } + /* TODO: un-hardcode aspect ratio */ aspect = stream->public.timing.aspect_ratio; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 00958bdbb417..a17e7bc96f9e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -444,7 +444,11 @@ enum dc_color_space { COLOR_SPACE_YCBCR601, COLOR_SPACE_YCBCR709, COLOR_SPACE_YCBCR601_LIMITED, - COLOR_SPACE_YCBCR709_LIMITED + COLOR_SPACE_YCBCR709_LIMITED, + COLOR_SPACE_2020_RGB_FULLRANGE, + COLOR_SPACE_2020_RGB_LIMITEDRANGE, + COLOR_SPACE_2020_YCBCR, + COLOR_SPACE_ADOBERGB, }; enum dc_quantization_range { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ee393a168c84..e9fd83e9af79 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -594,39 +594,88 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func struct fixed31_32 y3_max; int32_t segment_start, segment_end; - uint32_t hw_points, start_index; - uint32_t i, j; + uint32_t i, j, k, seg_distr[16], increment, start_index; + uint32_t hw_points = 0; memset(regamma_params, 0, sizeof(struct pwl_params)); if (output_tf->tf == TRANSFER_FUNCTION_PQ) { - /* 16 segments x 16 points + /* 16 segments * segments are from 2^-11 to 2^5 */ segment_start = -11; segment_end = 5; + seg_distr[0] = 2; + seg_distr[1] = 2; + seg_distr[2] = 2; + seg_distr[3] = 2; + seg_distr[4] = 2; + seg_distr[5] = 2; + seg_distr[6] = 3; + seg_distr[7] = 4; + seg_distr[8] = 4; + seg_distr[9] = 4; + seg_distr[10] = 4; + seg_distr[11] = 5; + seg_distr[12] = 5; + seg_distr[13] = 5; + seg_distr[14] = 5; + seg_distr[15] = 5; + } else { - /* 10 segments x 16 points + /* 10 segments * segment is from 2^-10 to 2^0 */ segment_start = -10; segment_end = 0; + + seg_distr[0] = 3; + seg_distr[1] = 4; + seg_distr[2] = 4; + seg_distr[3] = 4; + seg_distr[4] = 4; + seg_distr[5] = 4; + seg_distr[6] = 4; + seg_distr[7] = 4; + seg_distr[8] = 5; + seg_distr[9] = 5; + seg_distr[10] = -1; + seg_distr[11] = -1; + seg_distr[12] = -1; + seg_distr[13] = -1; + seg_distr[14] = -1; + seg_distr[15] = -1; + } + + for (k = 0; k < 16; k++) { + if (seg_distr[k] != -1) + hw_points += (1 << seg_distr[k]); } - hw_points = (segment_end - segment_start) * 16; j = 0; - /* (segment + 25) * 32, every 2nd point */ - start_index = (segment_start + 25) * 32; - for (i = start_index; i <= 1025; i += 2) { - if (j > hw_points) - break; - rgb_resulted[j].red = output_tf->tf_pts.red[i]; - rgb_resulted[j].green = output_tf->tf_pts.green[i]; - rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; - j++; + for (k = 0; k < (segment_end - segment_start); k++) { + increment = 32 / (1 << seg_distr[k]); + start_index = (segment_start + k + 25) * 32; + for (i = start_index; i < start_index + 32; i += increment) { + if (j == hw_points - 1) + break; + rgb_resulted[j].red = output_tf->tf_pts.red[i]; + rgb_resulted[j].green = output_tf->tf_pts.green[i]; + rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; + j++; + } } + /* last point */ + start_index = (segment_end + 25) * 32; + rgb_resulted[hw_points - 1].red = + output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = + output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = + output_tf->tf_pts.blue[start_index]; + arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), dal_fixed31_32_from_int(segment_start)); arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), @@ -677,11 +726,22 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func regamma_params->hw_points_num = hw_points; - for (i = 0; i < segment_end - segment_start; i++) { - regamma_params->arr_curve_points[i].offset = i * 16; - regamma_params->arr_curve_points[i].segments_num = 4; + i = 1; + for (k = 0; k < 16 && i < 16; k++) { + if (seg_distr[k] != -1) { + regamma_params->arr_curve_points[k].segments_num = + seg_distr[k]; + regamma_params->arr_curve_points[i].offset = + regamma_params->arr_curve_points[k]. + offset + (1 << seg_distr[k]); + } + i++; } + if (seg_distr[k] != -1) + regamma_params->arr_curve_points[k].segments_num = + seg_distr[k]; + struct pwl_result_data *rgb = rgb_resulted; struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index ef743b70b3e9..a510d3fe48ec 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -47,6 +47,17 @@ enum colorimetry { COLORIMETRY_EXTENDED = 3 }; +enum colorimetry_ext { + COLORIMETRYEX_XVYCC601 = 0, + COLORIMETRYEX_XVYCC709 = 1, + COLORIMETRYEX_SYCC601 = 2, + COLORIMETRYEX_ADOBEYCC601 = 3, + COLORIMETRYEX_ADOBERGB = 4, + COLORIMETRYEX_BT2020YCC = 5, + COLORIMETRYEX_BT2020RGBYCBCR = 6, + COLORIMETRYEX_RESERVED = 7 +}; + enum active_format_info { ACTIVE_FORMAT_NO_DATA = 0, ACTIVE_FORMAT_VALID = 1 -- GitLab From ab7044d0d17a8226a8b51e235e16204e696ae42a Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 16 Jan 2017 20:37:08 -0500 Subject: [PATCH 0198/2898] drm/amd/display: refactor clk_resync to avoid assertion - not all DCE has PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE bit defined. Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Yongqiang Sun Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_clock_source.c | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index a38172bdcb5e..78f43274a03a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -767,41 +767,44 @@ static void dce112_program_pixel_clk_resync( enum dc_color_depth colordepth, bool enable_ycbcr420) { - REG_UPDATE(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0); + uint32_t deep_color_cntl = 0; + uint32_t double_rate_enable = 0; + /* 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) 48 bit mode: TMDS clock = 2 x pixel clock (2:1) */ - if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) - return; + if (signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { + double_rate_enable = enable_ycbcr420 ? 1 : 0; - switch (colordepth) { - case COLOR_DEPTH_888: - REG_UPDATE_2(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 0, - PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); - break; - case COLOR_DEPTH_101010: - REG_UPDATE_2(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 1, - PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); - break; - case COLOR_DEPTH_121212: - REG_UPDATE_2(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 2, - PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); - break; - case COLOR_DEPTH_161616: - REG_UPDATE_2(PIXCLK_RESYNC_CNTL, - PHYPLLA_DCCG_DEEP_COLOR_CNTL, 3, - PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, enable_ycbcr420); - break; - default: - break; + switch (colordepth) { + case COLOR_DEPTH_888: + deep_color_cntl = 0; + break; + case COLOR_DEPTH_101010: + deep_color_cntl = 1; + break; + case COLOR_DEPTH_121212: + deep_color_cntl = 2; + break; + case COLOR_DEPTH_161616: + deep_color_cntl = 3; + break; + default: + break; + } } + + if (clk_src->cs_mask->PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE) + REG_UPDATE_2(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, deep_color_cntl, + PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, double_rate_enable); + else + REG_UPDATE(PIXCLK_RESYNC_CNTL, + PHYPLLA_DCCG_DEEP_COLOR_CNTL, deep_color_cntl); + } static bool dce110_program_pix_clk( -- GitLab From 031ec2764064d79b1e1d8c30a6785ed19184fb47 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 17 Jan 2017 11:18:55 -0500 Subject: [PATCH 0199/2898] drm/amd/display: Remove meta_pitch Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 8 ++------ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 ---- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 78b8e0c5b4e7..959c3f372e73 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -94,14 +94,12 @@ void pre_surface_trace( "surface->plane_size.grph.surface_size.y = %d;\n" "surface->plane_size.grph.surface_size.width = %d;\n" "surface->plane_size.grph.surface_size.height = %d;\n" - "surface->plane_size.grph.surface_pitch = %d;\n" - "surface->plane_size.grph.meta_pitch = %d;\n", + "surface->plane_size.grph.surface_pitch = %d;\n", surface->plane_size.grph.surface_size.x, surface->plane_size.grph.surface_size.y, surface->plane_size.grph.surface_size.width, surface->plane_size.grph.surface_size.height, - surface->plane_size.grph.surface_pitch, - surface->plane_size.grph.meta_pitch); + surface->plane_size.grph.surface_pitch); SURFACE_TRACE( @@ -176,7 +174,6 @@ void update_surface_trace( SURFACE_TRACE( "plane_info->color_space = %d;\n" "plane_info->format = %d;\n" - "plane_info->plane_size.grph.meta_pitch = %d;\n" "plane_info->plane_size.grph.surface_pitch = %d;\n" "plane_info->plane_size.grph.surface_size.height = %d;\n" "plane_info->plane_size.grph.surface_size.width = %d;\n" @@ -185,7 +182,6 @@ void update_surface_trace( "plane_info->rotation = %d;\n", update->plane_info->color_space, update->plane_info->format, - update->plane_info->plane_size.grph.meta_pitch, update->plane_info->plane_size.grph.surface_pitch, update->plane_info->plane_size.grph.surface_size.height, update->plane_info->plane_size.grph.surface_size.width, diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index a17e7bc96f9e..5c1b2f833fe2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -123,8 +123,6 @@ union plane_size { * is 32 pixel aligned. */ uint32_t surface_pitch; - - uint32_t meta_pitch; } grph; struct { @@ -134,7 +132,6 @@ union plane_size { * 32 pixel aligned. */ uint32_t luma_pitch; - uint32_t meta_luma_pitch; struct rect chroma_size; /* Graphic surface pitch in pixels. @@ -142,7 +139,6 @@ union plane_size { * 32 pixel aligned. */ uint32_t chroma_pitch; - uint32_t meta_chroma_pitch; } video; }; -- GitLab From 8693049a896c2c3a2bb74f0efde62318636beaef Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 16 Jan 2017 20:50:47 -0500 Subject: [PATCH 0200/2898] drm/amd/display: rename BGRA8888 to ABGR8888 DC actually support ABGR8888 instead of BGRA8888 (R/B swap rather than endian swap) , rename to avoid confusion Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Yongqiang Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index 54388c0e29e0..946379852b2a 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -2530,7 +2530,7 @@ static void populate_initial_data( data->bytes_per_pixel[num_displays + 4] = 2; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: @@ -2626,7 +2626,7 @@ static void populate_initial_data( data->bytes_per_pixel[num_displays + 4] = 2; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 8b41c7708562..ee1c3b029394 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -341,7 +341,7 @@ static enum pixel_format convert_pixel_format_to_dalsurface( case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: dal_pixel_format = PIXEL_FORMAT_ARGB8888; break; - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: dal_pixel_format = PIXEL_FORMAT_ARGB8888; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 5c1b2f833fe2..53c73de75da9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -174,7 +174,7 @@ enum surface_pixel_format { /*32 bpp*/ SURFACE_PIXEL_FORMAT_GRPH_ARGB8888, /*32 bpp swaped*/ - SURFACE_PIXEL_FORMAT_GRPH_BGRA8888, + SURFACE_PIXEL_FORMAT_GRPH_ABGR8888, SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010, /*swaped*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 130935fffba3..e14a21cedfd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -302,7 +302,7 @@ static void program_grph_pixel_format( uint32_t grph_depth, grph_format; uint32_t sign = 0, floating = 0; - if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 || + if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || /*todo: doesn't look like we handle BGRA here, * should problem swap endian*/ format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 || @@ -331,7 +331,7 @@ static void program_grph_pixel_format( grph_format = 1; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: grph_depth = 2; grph_format = 0; break; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e9fd83e9af79..6dbfc570b8c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -214,7 +214,7 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, switch (surface->public.format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: prescale_params->scale = 0x2020; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index b12506adcba4..aac47955e9bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -405,7 +405,7 @@ static void program_pixel_format( grph_format = 1; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: grph_depth = 2; grph_format = 0; break; -- GitLab From 009432e58159e640e942092ca68d78f589549d14 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 17 Jan 2017 15:14:11 -0500 Subject: [PATCH 0201/2898] drm/amd/display: Fix missing conditions in hw sequencer. Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index cd9a371ae237..0eee135bfa54 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -160,7 +160,7 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst) { - if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) { + if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO || clk_src->dp_clk_src) { REG_UPDATE(PIXEL_RATE_CNTL[tg_inst], DP_DTO0_ENABLE, 1); -- GitLab From b565ff86aaebee65141a4a441f782a05962d4c14 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Tue, 17 Jan 2017 16:16:04 -0500 Subject: [PATCH 0202/2898] drm/amd/display: Add missing MI masks This will fix the memory Input programing with MST tiled display. This Fix should fix connectivity problems with MST tiled Display Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index f90d586656ef..ec053c241901 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -92,6 +92,8 @@ struct dce_mem_input_registers { .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix #define MI_GFX8_TILE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_BANK_WIDTH, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\ -- GitLab From b10d51f8b094f73c6c27d389013304e59e3062b2 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 16 Jan 2017 16:16:22 -0500 Subject: [PATCH 0203/2898] drm/amd/display: Add interrupt entries for VBLANK isr. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../dc/irq/dce110/irq_service_dce110.c | 42 +++++++++++++++++++ .../display/dc/irq/dce80/irq_service_dce80.c | 22 ++++++++++ drivers/gpu/drm/amd/display/dc/irq_types.h | 8 ++++ 3 files changed, 72 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index f3eda1b4eebf..4c7c85d45518 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -33,6 +33,13 @@ #include "dce/dce_11_0_sh_mask.h" #include "ivsrcid/ivsrcid_vislands30.h" +#define VISLANDS30_IV_SRCID_D1_VBLANK 1 +#define VISLANDS30_IV_SRCID_D2_VBLANK 2 +#define VISLANDS30_IV_SRCID_D3_VBLANK 3 +#define VISLANDS30_IV_SRCID_D4_VBLANK 4 +#define VISLANDS30_IV_SRCID_D5_VBLANK 5 +#define VISLANDS30_IV_SRCID_D6_VBLANK 6 + static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) @@ -139,6 +146,22 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { .funcs = &vblank_irq_info_funcs\ } +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\ + .enable_mask =\ + LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + .enable_value = {\ + LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\ + .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\ + .ack_mask =\ + LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + .ack_value =\ + LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + #define dummy_irq_entry() \ {\ .funcs = &dummy_irq_info_funcs\ @@ -264,6 +287,13 @@ irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = { vupdate_int_entry(3), vupdate_int_entry(4), vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), + }; enum dc_irq_source to_dal_irq_source_dce110( @@ -272,6 +302,18 @@ enum dc_irq_source to_dal_irq_source_dce110( uint32_t ext_id) { switch (src_id) { + case VISLANDS30_IV_SRCID_D1_VBLANK: + return DC_IRQ_SOURCE_VBLANK1; + case VISLANDS30_IV_SRCID_D2_VBLANK: + return DC_IRQ_SOURCE_VBLANK2; + case VISLANDS30_IV_SRCID_D3_VBLANK: + return DC_IRQ_SOURCE_VBLANK3; + case VISLANDS30_IV_SRCID_D4_VBLANK: + return DC_IRQ_SOURCE_VBLANK4; + case VISLANDS30_IV_SRCID_D5_VBLANK: + return DC_IRQ_SOURCE_VBLANK5; + case VISLANDS30_IV_SRCID_D6_VBLANK: + return DC_IRQ_SOURCE_VBLANK6; case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: return DC_IRQ_SOURCE_VUPDATE1; case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT: diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index 8b4f45389783..dd09d2b6d4a7 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -143,6 +143,22 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { .funcs = &vblank_irq_info_funcs\ } +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\ + .enable_mask =\ + LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + .enable_value = {\ + LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\ + .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\ + .ack_mask =\ + LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + .ack_value =\ + LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + #define dummy_irq_entry() \ {\ .funcs = &dummy_irq_info_funcs\ @@ -246,6 +262,12 @@ irq_source_info_dce80[DAL_IRQ_SOURCES_NUMBER] = { vupdate_int_entry(3), vupdate_int_entry(4), vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), }; static const struct irq_service_funcs irq_service_funcs_dce80 = { diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h index e4b4b99a86fc..a506c2e939f5 100644 --- a/drivers/gpu/drm/amd/display/dc/irq_types.h +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -128,6 +128,13 @@ enum dc_irq_source { DC_IRQ_SOURCE_VUPDATE5, DC_IRQ_SOURCE_VUPDATE6, + DC_IRQ_SOURCE_VBLANK1, + DC_IRQ_SOURCE_VBLANK2, + DC_IRQ_SOURCE_VBLANK3, + DC_IRQ_SOURCE_VBLANK4, + DC_IRQ_SOURCE_VBLANK5, + DC_IRQ_SOURCE_VBLANK6, + DAL_IRQ_SOURCES_NUMBER }; @@ -135,6 +142,7 @@ enum irq_type { IRQ_TYPE_PFLIP = DC_IRQ_SOURCE_PFLIP1, IRQ_TYPE_VUPDATE = DC_IRQ_SOURCE_VUPDATE1, + IRQ_TYPE_VBLANK = DC_IRQ_SOURCE_VBLANK1, }; #define DAL_VALID_IRQ_SRC_NUM(src) \ -- GitLab From b57de80a51479f19a41f737ddd1ab18028bf9a43 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 19 Apr 2017 13:29:11 -0400 Subject: [PATCH 0204/2898] drm/amd/display: Register on VLBLANK ISR. Switch from VUPDATE to VBLANK. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++++++------ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 214cd38b8135..b85f34ba158c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -201,7 +201,7 @@ static void dm_crtc_high_irq(void *interrupt_params) uint8_t crtc_index = 0; struct amdgpu_crtc *acrtc; - acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE); + acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK); if (acrtc) crtc_index = acrtc->crtc_id; @@ -1026,9 +1026,10 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) * amdgpu_dm_irq_handler() will re-direct the interrupt to DC * for acknowledging and handling. */ - for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; - i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) { - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->crtc_irq); + /* Use VBLANK interrupt */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i+1, &adev->crtc_irq); + if (r) { DRM_ERROR("Failed to add crtc irq id!\n"); return r; @@ -1036,9 +1037,9 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; int_params.irq_source = - dc_interrupt_to_irq_source(dc, i, 0); + dc_interrupt_to_irq_source(dc, i+1, 0); - c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; + c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; c_irq_params->adev = adev; c_irq_params->irq_src = int_params.irq_source; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 1b54566f5da1..d6ebba012e15 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -105,7 +105,7 @@ struct amdgpu_display_manager { pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1]; struct common_irq_params - vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1]; + vblank_params[DC_IRQ_SOURCE_VBLANK6 - DC_IRQ_SOURCE_VBLANK1 + 1]; /* this spin lock synchronizes access to 'irq_handler_list_table' */ spinlock_t irq_handler_list_table_lock; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 20e074971bff..682e9c3ad8e5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -736,7 +736,7 @@ static int amdgpu_dm_set_crtc_irq_state(struct amdgpu_device *adev, source, crtc_id, state, - IRQ_TYPE_VUPDATE, + IRQ_TYPE_VBLANK, __func__); } -- GitLab From 3d761e7990a27dca7481d4f4e4d6b3751509ab11 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 19 Apr 2017 13:55:35 -0400 Subject: [PATCH 0205/2898] drm/amd/display: Clean index in irq init loop Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b85f34ba158c..0c50433d6ba3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1027,8 +1027,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) * for acknowledging and handling. */ /* Use VBLANK interrupt */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i+1, &adev->crtc_irq); + for (i = 1; i <= adev->mode_info.num_crtc; i++) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->crtc_irq); if (r) { DRM_ERROR("Failed to add crtc irq id!\n"); @@ -1037,7 +1037,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; int_params.irq_source = - dc_interrupt_to_irq_source(dc, i+1, 0); + dc_interrupt_to_irq_source(dc, i, 0); c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; @@ -1048,6 +1048,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) dm_crtc_high_irq, c_irq_params); } + /* Use GRPH_PFLIP interrupt */ for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->pageflip_irq); -- GitLab From adc9b14139de00b9fe016acc901a5fcf50145008 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 17 Jan 2017 17:40:13 -0500 Subject: [PATCH 0206/2898] drm/amd/display: add missing dcc update on flip call Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9deddc8ee2d1..f9b7fc85d71a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1429,6 +1429,8 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda updates[i].plane_info->tiling_info; surface->public.visible = updates[i].plane_info->visible; + surface->public.dcc = + updates[i].plane_info->dcc; } if (updates[i].scaling_info) { -- GitLab From f0e3db90a6fbee4acc921a4912a3e3460efb5cc0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 23 Jan 2017 11:49:24 -0500 Subject: [PATCH 0207/2898] drm/amd/display: Don't reserve pipe for underlay on ASIC without underlay Signed-off-by: Harry Wentland Acked-by: Jordan Lazare Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 ++ 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f9b7fc85d71a..270f8c5cfeda 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -621,7 +621,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) core_dc->hwss.init_hw(core_dc); full_pipe_count = core_dc->res_pool->pipe_count; - if (core_dc->res_pool->underlay_pipe_index >= 0) + if (core_dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) full_pipe_count--; core_dc->public.caps.max_streams = min( full_pipe_count, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index ae0e7eac2c9d..dc4f270ae44a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -934,7 +934,7 @@ static bool construct( pool->base.res_cap = &res_cap; pool->base.funcs = &dce100_res_pool_funcs; - pool->base.underlay_pipe_index = -1; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; bp = ctx->dc_bios; @@ -1004,7 +1004,7 @@ static bool construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = -1; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 40; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 64fae91dd5eb..fa8699d3b9ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1243,7 +1243,7 @@ static bool construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = -1; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 100; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index bee3a41ffe9f..fea60aa5d297 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -931,7 +931,7 @@ static bool construct( /************************************************* * Resource + asic cap harcoding * *************************************************/ - pool->base.underlay_pipe_index = -1; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 40; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 66bfcdb57c4c..b349b5768b6e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -230,6 +230,8 @@ struct audio_support{ bool hdmi_audio_native; }; +#define NO_UNDERLAY_PIPE -1 + struct resource_pool { struct mem_input *mis[MAX_PIPES]; struct input_pixel_processor *ipps[MAX_PIPES]; -- GitLab From cad3c7a99725f5f241ee7e8e1657c54c5b532d51 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 19 Jan 2017 18:58:33 -0500 Subject: [PATCH 0208/2898] drm/amd/display: Remove power gating debug flags They're not used anywhere Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e0143f9f0421..332ecf8b1157 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -145,8 +145,6 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; - bool disable_dpp_power_gate; - bool disable_hubp_power_gate; bool disable_clock_gate; bool disable_dmcu; bool disable_color_module; -- GitLab From 9c1a57d79dbc96e808ea81aa1385f2d9d03570a0 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Tue, 17 Jan 2017 16:16:04 -0500 Subject: [PATCH 0209/2898] drm/amd/display: check surface size is at least as large as stream Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 82cddb6425a0..0b8f8927162f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -967,9 +967,9 @@ static bool dce110_validate_surface_sets( return false; if (set[i].surfaces[0]->src_rect.width - != set[i].stream->src.width + < set[i].stream->src.width || set[i].surfaces[0]->src_rect.height - != set[i].stream->src.height) + < set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index fa8699d3b9ef..7c12185b1dbe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -966,9 +966,9 @@ static bool dce112_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].stream->src.width + < set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].stream->src.height) + < set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) -- GitLab From 4d35b093e635de739d0bdcbb57244424cb1abb61 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Tue, 17 Jan 2017 16:01:35 -0500 Subject: [PATCH 0210/2898] drm/amd/display: Proper de-allocation of OPP - refactor opp_destroy functions to dce common file - fixes memory leak, dce specific variations didn't free regamma_params - remove unused dce110_regamma structure Signed-off-by: Joshua Aberback Reviewed-by: Jun Lei Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 10 +++--- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 35 ------------------- .../amd/display/dc/dce100/dce100_resource.c | 26 +------------- .../amd/display/dc/dce112/dce112_resource.c | 26 +------------- 4 files changed, 8 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 061de9e8249d..62f01911639f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -986,10 +986,12 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp) { - dm_free((*opp)->regamma_params); - (*opp)->regamma_params = NULL; - - dm_free(FROM_DCE11_OPP(*opp)); + if (*opp) { + if ((*opp)->regamma_params) + dm_free((*opp)->regamma_params); + (*opp)->regamma_params = NULL; + dm_free(FROM_DCE11_OPP(*opp)); + } *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index f2828f044b96..a5afc0298d6f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -312,40 +312,6 @@ struct dce_opp_registers { uint32_t FMT_CLAMP_COMPONENT_B; }; -struct dce110_regamma { - struct gamma_curve arr_curve_points[16]; - struct curve_points arr_points[3]; - uint32_t hw_points_num; - struct hw_x_point *coordinates_x; - struct pwl_result_data *rgb_resulted; - - /* re-gamma curve */ - struct pwl_float_data_ex *rgb_regamma; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 256 */ - struct pixel_gamma_point *coeff128; - struct pixel_gamma_point *coeff128_oem; - /* coeff used to map user evenly distributed points - * to our hardware points (predefined) for gamma 1025 */ - struct pixel_gamma_point *coeff128_dx; - /* evenly distributed points, gamma 256 software points 0-255 */ - struct gamma_pixel *axis_x_256; - /* evenly distributed points, gamma 1025 software points 0-1025 */ - struct gamma_pixel *axis_x_1025; - /* OEM supplied gamma for regamma LUT */ - struct pwl_float_data *rgb_oem; - /* user supplied gamma */ - struct pwl_float_data *rgb_user; - uint32_t extra_points; - bool use_half_points; - struct fixed31_32 x_max1; - struct fixed31_32 x_max2; - struct fixed31_32 x_min; - struct fixed31_32 divider1; - struct fixed31_32 divider2; - struct fixed31_32 divider3; -}; - /* OPP RELATED */ #define TO_DCE110_OPP(opp)\ container_of(opp, struct dce110_opp, base) @@ -355,7 +321,6 @@ struct dce110_opp { const struct dce_opp_registers *regs; const struct dce_opp_shift *opp_shift; const struct dce_opp_mask *opp_mask; - struct dce110_regamma regamma; }; bool dce110_opp_construct(struct dce110_opp *opp110, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index dc4f270ae44a..6ae334b42fbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -633,30 +633,6 @@ struct output_pixel_processor *dce100_opp_create( return NULL; } -void dce100_opp_destroy(struct output_pixel_processor **opp) -{ - struct dce110_opp *dce110_opp; - - if (!opp || !*opp) - return; - - dce110_opp = FROM_DCE11_OPP(*opp); - - dm_free(dce110_opp->regamma.coeff128_dx); - dm_free(dce110_opp->regamma.coeff128_oem); - dm_free(dce110_opp->regamma.coeff128); - dm_free(dce110_opp->regamma.axis_x_1025); - dm_free(dce110_opp->regamma.axis_x_256); - dm_free(dce110_opp->regamma.coordinates_x); - dm_free(dce110_opp->regamma.rgb_regamma); - dm_free(dce110_opp->regamma.rgb_resulted); - dm_free(dce110_opp->regamma.rgb_oem); - dm_free(dce110_opp->regamma.rgb_user); - dm_free(dce110_opp); - - *opp = NULL; -} - struct clock_source *dce100_clock_source_create( struct dc_context *ctx, struct dc_bios *bios, @@ -692,7 +668,7 @@ static void destruct(struct dce110_resource_pool *pool) for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) - dce100_opp_destroy(&pool->base.opps[i]); + dce110_opp_destroy(&pool->base.opps[i]); if (pool->base.transforms[i] != NULL) dce100_transform_destroy(&pool->base.transforms[i]); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 7c12185b1dbe..cc826efac58d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -645,30 +645,6 @@ struct output_pixel_processor *dce112_opp_create( return NULL; } -void dce112_opp_destroy(struct output_pixel_processor **opp) -{ - struct dce110_opp *dce110_opp; - - if (!opp || !*opp) - return; - - dce110_opp = FROM_DCE11_OPP(*opp); - - dm_free(dce110_opp->regamma.coeff128_dx); - dm_free(dce110_opp->regamma.coeff128_oem); - dm_free(dce110_opp->regamma.coeff128); - dm_free(dce110_opp->regamma.axis_x_1025); - dm_free(dce110_opp->regamma.axis_x_256); - dm_free(dce110_opp->regamma.coordinates_x); - dm_free(dce110_opp->regamma.rgb_regamma); - dm_free(dce110_opp->regamma.rgb_resulted); - dm_free(dce110_opp->regamma.rgb_oem); - dm_free(dce110_opp->regamma.rgb_user); - - dm_free(dce110_opp); - *opp = NULL; -} - struct clock_source *dce112_clock_source_create( struct dc_context *ctx, struct dc_bios *bios, @@ -704,7 +680,7 @@ static void destruct(struct dce110_resource_pool *pool) for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) - dce112_opp_destroy(&pool->base.opps[i]); + dce110_opp_destroy(&pool->base.opps[i]); if (pool->base.transforms[i] != NULL) dce112_transform_destroy(&pool->base.transforms[i]); -- GitLab From dcbd4ee0fabcc1f6a40d67e8a8621e9ac5a382ac Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 19 Jan 2017 10:53:58 -0500 Subject: [PATCH 0211/2898] drm/amd/display: Change update surface condition, fix surface transition corruption. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 270f8c5cfeda..de6ef8713ea8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1497,7 +1497,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); - bool apply_ctx = false; for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1505,13 +1504,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda if (pipe_ctx->surface != surface) continue; - if (updates[i].flip_addr) { + if (updates[i].flip_addr && can_skip_context_building) { core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - } - - if (updates[i].plane_info || updates[i].scaling_info - || is_new_pipe_surface[j]) { - apply_ctx = true; + } else { if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( @@ -1546,7 +1541,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda } } - if (apply_ctx) { + if (!can_skip_context_building) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); context_timing_trace(dc, &context->res_ctx); } -- GitLab From 0be06fc29b31d92a22180deaf866ad5f97133a9e Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 19 Jan 2017 17:54:39 -0500 Subject: [PATCH 0212/2898] drm/amd/display: prevent setting cursor position with no surface Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 47816c5ee0e0..e1f579bcd789 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -232,8 +232,8 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if ((pipe_ctx->stream == stream) && - (pipe_ctx->ipp != NULL)) { + if (pipe_ctx->stream == stream && + pipe_ctx->ipp && pipe_ctx->surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, -- GitLab From fde2deae86220eb5c3f88bf5ee9ff47175810b34 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 19 Jan 2017 10:57:56 -0500 Subject: [PATCH 0213/2898] drm/amd/display: improve debug-ability - make failure status obvious Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/inc/core_status.h | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 147eb7cac701..23d52aea55dd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -29,19 +29,19 @@ enum dc_status { DC_OK = 1, - DC_NO_CONTROLLER_RESOURCE, - DC_NO_STREAM_ENG_RESOURCE, - DC_NO_CLOCK_SOURCE_RESOURCE, - DC_FAIL_CONTROLLER_VALIDATE, - DC_FAIL_ENC_VALIDATE, - DC_FAIL_ATTACH_SURFACES, - DC_FAIL_SURFACE_VALIDATE, - DC_NO_DP_LINK_BANDWIDTH, - DC_EXCEED_DONGLE_MAX_CLK, - DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED, - DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */ - DC_FAIL_SCALING, - DC_FAIL_CLK_CONSTRAINT, + DC_NO_CONTROLLER_RESOURCE = 2, + DC_NO_STREAM_ENG_RESOURCE = 3, + DC_NO_CLOCK_SOURCE_RESOURCE = 4, + DC_FAIL_CONTROLLER_VALIDATE = 5, + DC_FAIL_ENC_VALIDATE = 6, + DC_FAIL_ATTACH_SURFACES = 7, + DC_FAIL_SURFACE_VALIDATE = 8, + DC_NO_DP_LINK_BANDWIDTH = 9, + DC_EXCEED_DONGLE_MAX_CLK = 10, + DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, + DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ + DC_FAIL_SCALING = 13, + DC_FAIL_CLK_CONSTRAINT = 14, DC_ERROR_UNEXPECTED = -1 }; -- GitLab From e72f0acd369d3ddfa6e924279d4010bcdb3de31b Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 19 Jan 2017 23:57:09 -0500 Subject: [PATCH 0214/2898] drm/amd/display: refactor dc_update_surfaces_for_stream - reuse existing helper functions - helper function to make it more obvious which cases we can do optimize programming Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 367 +++++++++++++---------- 1 file changed, 212 insertions(+), 155 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index de6ef8713ea8..170936bb378a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1007,7 +1007,7 @@ bool dc_commit_streams( struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; - struct dc_validation_set set[MAX_STREAMS] = { 0 }; + struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; int i, j, k; if (false == streams_changed(core_dc, streams, stream_count)) @@ -1321,80 +1321,167 @@ bool dc_commit_surfaces_to_stream( return dc_post_update_surfaces_to_stream(dc); } -void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, - int surface_count, const struct dc_stream *dc_stream) +static bool is_surface_in_context( + const struct validate_context *context, + const struct dc_surface *surface) { - struct core_dc *core_dc = DC_TO_CORE(dc); - struct validate_context *context = core_dc->temp_flip_context; - int i, j; - bool is_new_pipe_surface[MAX_PIPES]; - const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; - bool need_apply_clk_constraints = false; - bool can_skip_context_building = true; + int j; - update_surface_trace(dc, updates, surface_count); + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - *context = *core_dc->current_context; + if (surface == &pipe_ctx->surface->public) { + return true; + } + } - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { - struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; + return false; +} - if (cur_pipe->top_pipe) - cur_pipe->top_pipe = - &context->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; +enum surface_update_type { + UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ + UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */ + UPDATE_TYPE_FULL, /* may need to shuffle resources */ +}; - if (cur_pipe->bottom_pipe) - cur_pipe->bottom_pipe = - &context->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; - } +static enum surface_update_type det_surface_update( + const struct core_dc *dc, + const struct dc_surface_update *u) +{ + const struct validate_context *context = dc->current_context; - for (j = 0; j < MAX_PIPES; j++) - is_new_pipe_surface[j] = true; + if (u->scaling_info || u->plane_info) + /* todo: not all scale and plane_info update need full update + * ie. check if following is the same + * scale ratio, view port, surface bpp etc + */ + return UPDATE_TYPE_FULL; /* may need bandwidth update */ - for (i = 0 ; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); - bool existing_surface = false; + if (!is_surface_in_context(context, u->surface)) + return UPDATE_TYPE_FULL; - new_surfaces[i] = updates[i].surface; + if (u->in_transfer_func || + u->out_transfer_func || + u->hdr_static_metadata) + return UPDATE_TYPE_MED; - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + return UPDATE_TYPE_FAST; +} - if (surface == pipe_ctx->surface) { - existing_surface = true; - is_new_pipe_surface[j] = false; - } - } +static enum surface_update_type check_update_surfaces_for_stream( + struct core_dc *dc, + struct dc_surface_update *updates, + int surface_count, + const struct dc_stream_status *stream_status) +{ + int i; + enum surface_update_type overall_type = UPDATE_TYPE_FAST; - if (updates[i].plane_info || - updates[i].scaling_info || - !existing_surface) - can_skip_context_building = false; + if (stream_status->surface_count != surface_count) + return UPDATE_TYPE_FULL; + + for (i = 0 ; i < surface_count; i++) { + enum surface_update_type type = + det_surface_update(dc, &updates[i]); + + if (type == UPDATE_TYPE_FULL) + return type; + + if (overall_type < type) + overall_type = type; } - if (!can_skip_context_building && dc_stream) { - const struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + return overall_type; +} - if (core_dc->current_context->stream_count == 0) - return; +enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; - /* Cannot commit surface to a stream that is not commited */ - for (i = 0; i < core_dc->current_context->stream_count; i++) - if (stream == core_dc->current_context->streams[i]) - break; - if (i == core_dc->current_context->stream_count) - return; +void dc_update_surfaces_for_stream(struct dc *dc, + struct dc_surface_update *updates, int surface_count, + const struct dc_stream *dc_stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct validate_context *context; + int i, j; + + enum surface_update_type update_type; + const struct dc_stream_status *stream_status; + + stream_status = dc_stream_get_status(dc_stream); + ASSERT(stream_status); + if (!stream_status) + return; /* Cannot commit surface to stream that is not committed */ + + update_type = check_update_surfaces_for_stream( + core_dc, updates, surface_count, stream_status); + + if (update_type >= update_surface_trace_level) + update_surface_trace(dc, updates, surface_count); + if (update_type >= UPDATE_TYPE_FULL) { + const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + + for (i = 0; i < surface_count; i++) + new_surfaces[i] = updates[i].surface; + + /* initialize scratch memory for building context */ + context = core_dc->temp_flip_context; + resource_validate_ctx_copy_construct( + core_dc->current_context, context); + + /* add surface to context */ if (!resource_attach_surfaces_to_context( new_surfaces, surface_count, dc_stream, context)) { BREAK_TO_DEBUGGER(); return; } + } else { + context = core_dc->current_context; } - for (i = 0; i < surface_count; i++) { + /* save update param into surface */ struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + if (updates[i].flip_addr) { + surface->public.address = updates[i].flip_addr->address; + surface->public.flip_immediate = + updates[i].flip_addr->flip_immediate; + } + + if (updates[i].scaling_info) { + surface->public.scaling_quality = + updates[i].scaling_info->scaling_quality; + surface->public.dst_rect = + updates[i].scaling_info->dst_rect; + surface->public.src_rect = + updates[i].scaling_info->src_rect; + surface->public.clip_rect = + updates[i].scaling_info->clip_rect; + } + + if (updates[i].plane_info) { + surface->public.color_space = + updates[i].plane_info->color_space; + surface->public.format = + updates[i].plane_info->format; + surface->public.plane_size = + updates[i].plane_info->plane_size; + surface->public.rotation = + updates[i].plane_info->rotation; + surface->public.horizontal_mirror = + updates[i].plane_info->horizontal_mirror; + surface->public.stereo_format = + updates[i].plane_info->stereo_format; + surface->public.tiling_info = + updates[i].plane_info->tiling_info; + surface->public.visible = + updates[i].plane_info->visible; + surface->public.dcc = + updates[i].plane_info->dcc; + } + + /* not sure if we still need this */ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct core_stream *stream = pipe_ctx->stream; @@ -1402,133 +1489,101 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda if (pipe_ctx->surface != surface) continue; - if (updates[i].flip_addr) { - surface->public.address = updates[i].flip_addr->address; - surface->public.flip_immediate = - updates[i].flip_addr->flip_immediate; - } - - if (updates[i].plane_info || updates[i].scaling_info - || is_new_pipe_surface[j]) { - need_apply_clk_constraints = true; - - if (updates[i].plane_info) { - surface->public.color_space = - updates[i].plane_info->color_space; - surface->public.format = - updates[i].plane_info->format; - surface->public.plane_size = - updates[i].plane_info->plane_size; - surface->public.rotation = - updates[i].plane_info->rotation; - surface->public.horizontal_mirror = - updates[i].plane_info->horizontal_mirror; - surface->public.stereo_format = - updates[i].plane_info->stereo_format; - surface->public.tiling_info = - updates[i].plane_info->tiling_info; - surface->public.visible = - updates[i].plane_info->visible; - surface->public.dcc = - updates[i].plane_info->dcc; - } - - if (updates[i].scaling_info) { - surface->public.scaling_quality = - updates[i].scaling_info->scaling_quality; - surface->public.dst_rect = - updates[i].scaling_info->dst_rect; - surface->public.src_rect = - updates[i].scaling_info->src_rect; - surface->public.clip_rect = - updates[i].scaling_info->clip_rect; - } - - resource_build_scaling_params(updates[i].surface, pipe_ctx); - if (dc->debug.surface_visual_confirm) { - pipe_ctx->scl_data.recout.height -= 2; - pipe_ctx->scl_data.recout.width -= 2; - } + resource_build_scaling_params(updates[i].surface, pipe_ctx); + if (dc->debug.surface_visual_confirm) { + pipe_ctx->scl_data.recout.height -= 2; + pipe_ctx->scl_data.recout.width -= 2; } + } - if (dc->debug.disable_color_module) - continue; /* skip below color updates */ + if (dc->debug.disable_color_module) + continue; /* skip below color updates */ - if (updates[i].gamma && - updates[i].gamma != surface->public.gamma_correction) { - if (surface->public.gamma_correction != NULL) - dc_gamma_release(&surface->public. - gamma_correction); + if (updates[i].gamma && + updates[i].gamma != surface->public.gamma_correction) { + if (surface->public.gamma_correction != NULL) + dc_gamma_release(&surface->public. + gamma_correction); - dc_gamma_retain(updates[i].gamma); - surface->public.gamma_correction = - updates[i].gamma; - } + dc_gamma_retain(updates[i].gamma); + surface->public.gamma_correction = + updates[i].gamma; + } - if (updates[i].in_transfer_func && - updates[i].in_transfer_func != surface->public.in_transfer_func) { - if (surface->public.in_transfer_func != NULL) - dc_transfer_func_release( - surface->public. - in_transfer_func); - - dc_transfer_func_retain( - updates[i].in_transfer_func); - surface->public.in_transfer_func = - updates[i].in_transfer_func; - } + if (updates[i].in_transfer_func && + updates[i].in_transfer_func != surface->public.in_transfer_func) { + if (surface->public.in_transfer_func != NULL) + dc_transfer_func_release( + surface->public. + in_transfer_func); + + dc_transfer_func_retain( + updates[i].in_transfer_func); + surface->public.in_transfer_func = + updates[i].in_transfer_func; + } - if (updates[i].out_transfer_func && - updates[i].out_transfer_func != stream->public.out_transfer_func) { - if (stream->public.out_transfer_func != NULL) - dc_transfer_func_release( - stream->public. - out_transfer_func); - dc_transfer_func_retain( - updates[i].out_transfer_func); - stream->public.out_transfer_func = - updates[i].out_transfer_func; - } - if (updates[i].hdr_static_metadata) - surface->public.hdr_static_ctx = - *(updates[i].hdr_static_metadata); + if (updates[i].out_transfer_func && + updates[i].out_transfer_func != dc_stream->out_transfer_func) { + if (dc_stream->out_transfer_func != NULL) + dc_transfer_func_release(dc_stream->out_transfer_func); + dc_transfer_func_retain(updates[i].out_transfer_func); + stream->public.out_transfer_func = updates[i].out_transfer_func; } + if (updates[i].hdr_static_metadata) + surface->public.hdr_static_ctx = + *(updates[i].hdr_static_metadata); } + + if (!surface_count) /* reset */ + core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); + for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx; + bool is_new_pipe_surface = true; if (pipe_ctx->surface != surface) continue; - if (updates[i].flip_addr && can_skip_context_building) { - core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - } else { + if (update_type != UPDATE_TYPE_FAST && + !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + core_dc->hwss.pipe_control_lock( + core_dc->hwseq, + pipe_ctx->pipe_idx, + PIPE_LOCK_CONTROL_GRAPHICS | + PIPE_LOCK_CONTROL_SCL | + PIPE_LOCK_CONTROL_BLENDER | + PIPE_LOCK_CONTROL_MODE, + true); + } - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc->hwseq, - pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_GRAPHICS | - PIPE_LOCK_CONTROL_SCL | - PIPE_LOCK_CONTROL_BLENDER | - PIPE_LOCK_CONTROL_MODE, - true); - } + if (update_type == UPDATE_TYPE_FULL) { + core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + } else if (updates[i].flip_addr) { + core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); } + if (update_type == UPDATE_TYPE_FAST) + continue; + + cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; + if (cur_pipe_ctx->surface == pipe_ctx->surface) + is_new_pipe_surface = false; + if (dc->debug.disable_color_module) continue; /* skip below color updates */ - if (is_new_pipe_surface[j] || + if (is_new_pipe_surface || updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); - if (is_new_pipe_surface[j] || + if (is_new_pipe_surface || updates[i].out_transfer_func) core_dc->hwss.set_output_transfer_func( pipe_ctx, @@ -1539,14 +1594,12 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda resource_build_info_frame(pipe_ctx); core_dc->hwss.update_info_frame(pipe_ctx); } - - } - if (!can_skip_context_building) { - core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); - context_timing_trace(dc, &context->res_ctx); } } + if (update_type == UPDATE_TYPE_FAST) + return; + for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1566,8 +1619,12 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda } } - core_dc->temp_flip_context = core_dc->current_context; - core_dc->current_context = context; + if (core_dc->current_context != context) { + resource_validate_ctx_destruct(core_dc->current_context); + core_dc->temp_flip_context = core_dc->current_context; + + core_dc->current_context = context; + } } uint8_t dc_get_current_stream_count(const struct dc *dc) -- GitLab From e4e354b02fa8b6d53ec65bd5dbd27d014e4e752f Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 19 Jan 2017 14:46:26 -0500 Subject: [PATCH 0215/2898] drm/amd/display: clean up redundant logic Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_surface.c | 23 +++++++------------ drivers/gpu/drm/amd/display/dc/dc.h | 1 - 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d607972b830b..21fedd447bd1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -121,26 +121,20 @@ const struct dc_surface_status *dc_surface_get_status( const struct dc_surface *dc_surface) { struct dc_surface_status *surface_status; - struct core_surface *core_surface; + struct core_surface *core_surface = DC_SURFACE_TO_CORE(dc_surface);; struct core_dc *core_dc; int i; - if (dc_surface == NULL) - return NULL; - - core_surface = DC_SURFACE_TO_CORE(dc_surface); - - if (core_surface == NULL || core_surface->ctx == NULL) - return NULL; + if (!dc_surface || + !core_surface->ctx || + !core_surface->ctx->dc) { + ASSERT(0); + return NULL; /* remove this if above assert never hit */ + } surface_status = &core_surface->status; - - if (core_surface->ctx == NULL || core_surface->ctx->dc == NULL) - return NULL; - core_dc = DC_TO_CORE(core_surface->ctx->dc); - if (core_dc->current_context == NULL) return NULL; @@ -149,8 +143,7 @@ const struct dc_surface_status *dc_surface_get_status( struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != - DC_SURFACE_TO_CORE(dc_surface)) + if (pipe_ctx->surface != core_surface) continue; core_dc->hwss.update_pending_status(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 332ecf8b1157..c3aca8d44d4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -335,7 +335,6 @@ struct dc_transfer_func *dc_create_transfer_func(void); struct dc_flip_addrs { struct dc_plane_address address; bool flip_immediate; - /* TODO: DCC format info */ /* TODO: add flip duration for FreeSync */ }; -- GitLab From 86e2e1bee07134f712cb6b807b7f0205057bd11e Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 20 Jan 2017 15:54:13 -0500 Subject: [PATCH 0216/2898] drm/amd/display: Check we got a stream in update_info_frame Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6dbfc570b8c6..ce56f23806bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -837,6 +837,11 @@ static enum dc_status bios_parser_crtc_source_select( void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) { + ASSERT(pipe_ctx->stream); + + if (pipe_ctx->stream_enc == NULL) + return; /* this is not root pipe */ + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_enc, -- GitLab From ed1519403227490d517c2d59755d68d3c31afa12 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 23 Jan 2017 17:10:04 -0500 Subject: [PATCH 0217/2898] drm/amd/display: Fixed 4K black issue by refactor update surface. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 170936bb378a..01d614781def 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1482,17 +1482,19 @@ void dc_update_surfaces_for_stream(struct dc *dc, } /* not sure if we still need this */ - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct core_stream *stream = pipe_ctx->stream; + if (update_type == UPDATE_TYPE_FULL) { + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct core_stream *stream = pipe_ctx->stream; - if (pipe_ctx->surface != surface) - continue; + if (pipe_ctx->surface != surface) + continue; - resource_build_scaling_params(updates[i].surface, pipe_ctx); - if (dc->debug.surface_visual_confirm) { - pipe_ctx->scl_data.recout.height -= 2; - pipe_ctx->scl_data.recout.width -= 2; + resource_build_scaling_params(updates[i].surface, pipe_ctx); + if (dc->debug.surface_visual_confirm) { + pipe_ctx->scl_data.recout.height -= 2; + pipe_ctx->scl_data.recout.width -= 2; + } } } @@ -1563,10 +1565,12 @@ void dc_update_surfaces_for_stream(struct dc *dc, } if (update_type == UPDATE_TYPE_FULL) { - core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); - } else if (updates[i].flip_addr) { + /* only apply for top pipe */ + if (!pipe_ctx->top_pipe) + core_dc->hwss.apply_ctx_for_surface(core_dc, + surface, context); + } else if (updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - } if (update_type == UPDATE_TYPE_FAST) continue; -- GitLab From 954815153b4b1213237d389be15d5448f67154ff Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 23 Jan 2017 17:51:17 -0500 Subject: [PATCH 0218/2898] drm/amd/display: enable color gamma programming Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ------ drivers/gpu/drm/amd/display/dc/dc.h | 1 - 2 files changed, 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 01d614781def..c627b907528c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1498,9 +1498,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if (dc->debug.disable_color_module) - continue; /* skip below color updates */ - if (updates[i].gamma && updates[i].gamma != surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) @@ -1579,9 +1576,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (cur_pipe_ctx->surface == pipe_ctx->surface) is_new_pipe_surface = false; - if (dc->debug.disable_color_module) - continue; /* skip below color updates */ - if (is_new_pipe_surface || updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c3aca8d44d4c..f485f70bf3ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -147,7 +147,6 @@ struct dc_debug { bool disable_dfs_bypass; bool disable_clock_gate; bool disable_dmcu; - bool disable_color_module; }; struct dc { -- GitLab From 23ae4f8e59c926df806ba837b2a2040984077641 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Tue, 24 Jan 2017 09:50:05 -0500 Subject: [PATCH 0219/2898] drm/amd/display: Fix Warnings - Remove mixed declarations and unused variables Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ce56f23806bc..c3e0865f3148 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -581,12 +581,10 @@ static bool convert_to_custom_float( static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, struct pwl_params *regamma_params) { - if (output_tf == NULL || regamma_params == NULL) - return false; - - struct gamma_curve *arr_curve_points = regamma_params->arr_curve_points; - struct curve_points *arr_points = regamma_params->arr_points; - struct pwl_result_data *rgb_resulted = regamma_params->rgb_resulted; + struct curve_points *arr_points; + struct pwl_result_data *rgb_resulted; + struct pwl_result_data *rgb; + struct pwl_result_data *rgb_plus_1; struct fixed31_32 y_r; struct fixed31_32 y_g; struct fixed31_32 y_b; @@ -594,8 +592,14 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func struct fixed31_32 y3_max; int32_t segment_start, segment_end; - uint32_t i, j, k, seg_distr[16], increment, start_index; - uint32_t hw_points = 0; + uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points; + + if (output_tf == NULL || regamma_params == NULL) + return false; + + arr_points = regamma_params->arr_points; + rgb_resulted = regamma_params->rgb_resulted; + hw_points = 0; memset(regamma_params, 0, sizeof(struct pwl_params)); @@ -742,8 +746,8 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func regamma_params->arr_curve_points[k].segments_num = seg_distr[k]; - struct pwl_result_data *rgb = rgb_resulted; - struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1; + rgb = rgb_resulted; + rgb_plus_1 = rgb_resulted + 1; i = 1; -- GitLab From 37d66a339b6f29251ebe0da78816d6d07554c617 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 20 Jan 2017 17:14:23 -0500 Subject: [PATCH 0220/2898] drm/amd/display: fix timing trace debug print Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c627b907528c..c863bffab989 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1563,9 +1563,11 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL) { /* only apply for top pipe */ - if (!pipe_ctx->top_pipe) + if (!pipe_ctx->top_pipe) { core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + context_timing_trace(dc, &context->res_ctx); + } } else if (updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 959c3f372e73..85ddf5fc4291 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -279,20 +279,26 @@ void context_timing_trace( int i; struct core_dc *core_dc = DC_TO_CORE(dc); struct dal_logger *logger = core_dc->ctx->logger; + int h_pos[MAX_PIPES], v_pos[MAX_PIPES]; for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - int h_pos = 0; - int v_pos = 0; if (pipe_ctx->stream == NULL) continue; - pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos, &v_pos); - TIMING_TRACE("Pipe_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", - pipe_ctx->pipe_idx, + pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos[i], &v_pos[i]); + } + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + TIMING_TRACE("OTG_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", + pipe_ctx->tg->inst, pipe_ctx->stream->public.timing.h_total, pipe_ctx->stream->public.timing.v_total, - h_pos, v_pos); + h_pos[i], v_pos[i]); } } -- GitLab From 17c06cab918e23b15dcf1618d9735a46fd1529f8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 24 Jan 2017 16:06:32 -0500 Subject: [PATCH 0221/2898] drm/amd/display: Make sure to update address without flip Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c863bffab989..75718151356d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1568,7 +1568,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, surface, context); context_timing_trace(dc, &context->res_ctx); } - } else if (updates[i].flip_addr) + } + + if (updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); if (update_type == UPDATE_TYPE_FAST) -- GitLab From 8fb234135027899e5a62e357baa7c43546a1d57b Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 24 Jan 2017 17:28:50 -0500 Subject: [PATCH 0222/2898] drm/amd/display: Rename atomic_commit parameter. This parameter name is misleading. It's previous meaning confuses with ASYNC (immidiate flip) which is totatlly different thing then nonblocking commit. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ad08d6f7f094..ad60a28975ca 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2253,7 +2253,7 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) int amdgpu_dm_atomic_commit( struct drm_device *dev, struct drm_atomic_state *state, - bool async) + bool nonblock) { struct amdgpu_device *adev = dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; @@ -2282,7 +2282,7 @@ int amdgpu_dm_atomic_commit( * we should not pin/unpin the fb here, it should be done in * amdgpu_crtc_flip and from the vblank irq handler. */ - if (!async) { + if (!nonblock) { ret = drm_atomic_helper_prepare_planes(dev, state); if (ret) return ret; @@ -2620,7 +2620,7 @@ int amdgpu_dm_atomic_commit( /* In this state all old framebuffers would be unpinned */ /* TODO: Revisit when we support true asynchronous commit.*/ - if (!async) + if (!nonblock) drm_atomic_helper_cleanup_planes(dev, state); drm_atomic_state_put(state); -- GitLab From c7141c47d371fbe6dfbdadf92cd4abb750111a62 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 25 Jan 2017 09:31:45 -0500 Subject: [PATCH 0223/2898] drm/amd/display: Fix compile warnings 1. Fix init of integer 2. Fix mixed declarations Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index e0703c588e47..1ee732768f6e 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -208,6 +208,8 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_stream *core_stream = NULL; struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; + int persistent_freesync_enable = 0; + struct persistent_data_flag flag; if (mod_freesync == NULL) return false; @@ -216,9 +218,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, core_stream = DC_STREAM_TO_CORE(stream); core_dc = DC_TO_CORE(core_freesync->dc); - int persistent_freesync_enable = 0; - struct persistent_data_flag flag; - flag.save_per_edid = true; flag.save_per_link = false; @@ -779,7 +778,7 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_params *freesync_params) { - unsigned int index = NULL; + unsigned int index = 0; struct core_freesync *core_freesync = NULL; if (mod_freesync == NULL) -- GitLab From 7ec6b963b17a51159c38e2446499a69edf5b20e5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 25 Jan 2017 14:51:39 -0500 Subject: [PATCH 0224/2898] drm/amd/display: Expose hw sequencer gamma function Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c3e0865f3148..6acb9faf29f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -578,7 +578,7 @@ static bool convert_to_custom_float( return true; } -static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func +bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, struct pwl_params *regamma_params) { struct curve_points *arr_points; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index a6b4d0d2429f..68632dd28155 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -58,5 +58,8 @@ void dce110_power_down(struct core_dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); +bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func + *output_tf, struct pwl_params *regamma_params); + #endif /* __DC_HWSS_DCE110_H__ */ -- GitLab From 75a74755763062b5dd722a19b3fe7a60813ee369 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Thu, 26 Jan 2017 18:03:16 -0500 Subject: [PATCH 0225/2898] drm/amd/display: DP compliance automation test fixes Fixes: 1. Removing pending flag since we are executing teh entire flow without context switches 2. Adding stream enablment - connection between DIG BE to DIG FE during test link training Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 19 +------------------ .../drm/amd/display/dc/core/dc_link_hwss.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 3 +-- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index c9c1b48df384..6fe5acbc16ca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1738,8 +1738,7 @@ static void handle_automated_test(struct core_link *link) } if (test_request.bits.LINK_TEST_PATTRN) { dp_test_send_link_test_pattern(link); - link->public.compliance_test_state.bits. - SET_TEST_PATTERN_PENDING = 1; + test_response.bits.ACK = 1; } if (test_request.bits.PHY_TEST_PATTERN) { dp_test_send_phy_test_pattern(link); @@ -2308,11 +2307,9 @@ bool dc_link_dp_set_test_pattern( unsigned int i; unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; union dpcd_training_pattern training_pattern; - union test_response test_response; enum dpcd_phy_test_patterns pattern; memset(&training_pattern, 0, sizeof(training_pattern)); - memset(&test_response, 0, sizeof(test_response)); for (i = 0; i < MAX_PIPES; i++) { if (pipes[i].stream->sink->link == core_link) { @@ -2442,20 +2439,6 @@ bool dc_link_dp_set_test_pattern( set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); /* Set Test Pattern state */ core_link->public.test_pattern_enabled = true; - - /* If this is called because of compliance test request, - * we respond ack here. - */ - if (core_link->public.compliance_test_state.bits. - SET_TEST_PATTERN_PENDING == 1) { - core_link->public.compliance_test_state.bits. - SET_TEST_PATTERN_PENDING = 0; - test_response.bits.ACK = 1; - core_link_write_dpcd(core_link, - DP_TEST_RESPONSE, - &test_response.raw, - sizeof(test_response)); - } } return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index b0ac94d673c4..3b814592fd70 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -251,6 +251,8 @@ void dp_retrain_link_dp_test(struct core_link *link, dp_receiver_power_ctrl(link, false); + link->dc->hwss.disable_stream(&pipes[i]); + link->link_enc->funcs->disable_output( link->link_enc, SIGNAL_TYPE_DISPLAY_PORT); @@ -273,6 +275,8 @@ void dp_retrain_link_dp_test(struct core_link *link, link->public.cur_link_settings = *link_setting; + link->dc->hwss.enable_stream(&pipes[i]); + link->dc->hwss.unblank_stream(&pipes[i], link_setting); } diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 1666f10a1e5c..cd2323a71760 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -432,8 +432,7 @@ union phy_test_pattern { union compliance_test_state { struct { unsigned char STEREO_3D_RUNNING : 1; - unsigned char SET_TEST_PATTERN_PENDING : 1; - unsigned char RESERVED : 6; + unsigned char RESERVED : 7; } bits; unsigned char raw; }; -- GitLab From bb9042da8e8ada796cfae7e432a54e872c5b1784 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 27 Jan 2017 10:29:01 -0500 Subject: [PATCH 0226/2898] drm/amd/display: Change power gating off sequence to fix hang Power off plane clear all the reg values includes cursor. When OS call set cursor position, cursor address reg is cleared, results in system hard hang. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 75718151356d..474c2d42525d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1254,9 +1254,12 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; i++) - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) { + core_dc->current_context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( - core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + } + if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, core_dc->current_context) != DC_OK) { -- GitLab From 5e7773a219f7821163ad2b17be0d02f8be8ce0c6 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Mon, 23 Jan 2017 16:55:20 -0500 Subject: [PATCH 0227/2898] drm/amd/display: DMCU Compile and Load Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 -- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 12 - drivers/gpu/drm/amd/display/dc/dc.h | 4 +- drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 214 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 157 +++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 127 +++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 91 ++++++++ .../drm/amd/display/dc/dce/dce_link_encoder.c | 40 +--- .../display/dc/dce110/dce110_hw_sequencer.c | 6 + .../amd/display/dc/dce110/dce110_resource.c | 52 +++++ .../amd/display/dc/dce112/dce112_resource.c | 51 +++++ .../gpu/drm/amd/display/dc/inc/core_types.h | 3 + drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 40 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 42 ++++ .../drm/amd/display/dc/inc/hw/link_encoder.h | 1 - 16 files changed, 788 insertions(+), 70 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_abm.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_abm.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/abm.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 474c2d42525d..152c694cc044 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -268,19 +268,6 @@ static bool init_dmcu_backlight_settings(struct dc *dc) return true; } - -static bool set_abm_level(struct dc *dc, unsigned int abm_level) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; - - for (i = 0; i < core_dc->link_count; i++) - dc_link_set_abm_level(&core_dc->links[i]->public, - abm_level); - - return true; -} - static bool set_psr_enable(struct dc *dc, bool enable) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -409,9 +396,6 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.init_dmcu_backlight_settings = init_dmcu_backlight_settings; - core_dc->public.stream_funcs.set_abm_level = - set_abm_level; - core_dc->public.stream_funcs.set_psr_enable = set_psr_enable; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f4f46d4f0cf0..84efc25d0e33 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1432,18 +1432,6 @@ bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link) return true; } -bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level) -{ - struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - - dm_logger_write(ctx->logger, LOG_BACKLIGHT, - "New abm level: %d (0x%X)\n", level, level); - - link->link_enc->funcs->set_dmcu_abm_level(link->link_enc, level); - return true; -} - bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) { struct core_link *link = DC_LINK_TO_CORE(dc_link); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f485f70bf3ef..8cb53b626641 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -103,7 +103,6 @@ struct dc_stream_funcs { bool (*set_backlight)(struct dc *dc, unsigned int backlight_level, unsigned int frame_ramp, const struct dc_stream *stream); bool (*init_dmcu_backlight_settings)(struct dc *dc); - bool (*set_abm_level)(struct dc *dc, unsigned int abm_level); bool (*set_psr_enable)(struct dc *dc, bool enable); bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream); }; @@ -575,8 +574,6 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link); -bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level); - bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_setup_psr(const struct dc_link *dc_link, @@ -730,4 +727,5 @@ bool dc_submit_i2c( uint32_t link_index, struct i2c_command *cmd); + #endif /* DC_INTERFACE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index 5ad59a27738c..05562553b656 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -7,7 +7,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ -dce_clocks.o dce_opp.o +dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c new file mode 100644 index 000000000000..ce49bee8e038 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -0,0 +1,214 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_abm.h" +#include "dm_services.h" +#include "reg_helper.h" +#include "fixed32_32.h" +#include "dc.h" + +#define TO_DCE_ABM(abm)\ + container_of(abm, struct dce_abm, base) + +#define REG(reg) \ + (abm_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + abm_dce->abm_shift->field_name, abm_dce->abm_mask->field_name + +#define CTX \ + abm_dce->base.ctx + +#define MCP_ABM_LEVEL_SET 0x65 + +static unsigned int get_current_backlight(struct dce_abm *abm_dce) +{ + uint64_t current_backlight; + uint32_t round_result; + uint32_t pwm_period_cntl, bl_period, bl_int_count; + uint32_t bl_pwm_cntl, bl_pwm, fractional_duty_cycle_en; + uint32_t bl_period_mask, bl_pwm_mask; + + pwm_period_cntl = REG_READ(BL_PWM_PERIOD_CNTL); + REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); + REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count); + + bl_pwm_cntl = REG_READ(BL_PWM_CNTL); + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, (uint32_t *)(&bl_pwm)); + REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en); + + if (bl_int_count == 0) + bl_int_count = 16; + + bl_period_mask = (1 << bl_int_count) - 1; + bl_period &= bl_period_mask; + + bl_pwm_mask = bl_period_mask << (16 - bl_int_count); + + if (fractional_duty_cycle_en == 0) + bl_pwm &= bl_pwm_mask; + else + bl_pwm &= 0xFFFF; + + current_backlight = bl_pwm << (1 + bl_int_count); + + if (bl_period == 0) + bl_period = 0xFFFF; + + current_backlight /= bl_period; + current_backlight = (current_backlight + 1) >> 1; + + current_backlight = (uint64_t)(current_backlight) * bl_period; + + round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); + + round_result = (round_result >> (bl_int_count-1)) & 1; + + current_backlight >>= bl_int_count; + current_backlight += round_result; + + return (uint32_t)(current_backlight); +} + +void dce_abm_init(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + unsigned int backlight = get_current_backlight(abm_dce); + + REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103); + REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101); + REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x103); + REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x101); + REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x101); + + REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0, + ABM1_HG_NUM_OF_BINS_SEL, 0, + ABM1_HG_VMAX_SEL, 1, + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0); + + REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0, + ABM1_IPCSC_COEFF_SEL_R, 2, + ABM1_IPCSC_COEFF_SEL_G, 4, + ABM1_IPCSC_COEFF_SEL_B, 2); + + REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL, + BL1_PWM_CURRENT_ABM_LEVEL, backlight); + + REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL, + BL1_PWM_TARGET_ABM_LEVEL, backlight); + + REG_UPDATE(BL1_PWM_USER_LEVEL, + BL1_PWM_USER_LEVEL, backlight); + + REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, + ABM1_LS_MIN_PIXEL_VALUE_THRES, 0, + ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000); + + REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0, + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1, + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1, + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); +} + +bool dce_abm_set_level(struct abm *abm, uint32_t level) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + struct dc_context *ctx = abm_dce->base.ctx; + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int value; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); + REG_GET(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, &value); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((value & abm_dce->abm_mask->MASTER_COMM_INTERRUPT) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_ABMLevel */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, + MASTER_COMM_CMD_REG_BYTE2, level); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + return true; +} + +static const struct abm_funcs dce_funcs = { + .abm_init = dce_abm_init, + .set_abm_level = dce_abm_set_level, +}; + +static void dce_abm_construct( + struct dce_abm *abm_dce, + struct dc_context *ctx, + const struct dce_abm_registers *regs, + const struct dce_abm_shift *abm_shift, + const struct dce_abm_mask *abm_mask) +{ + struct abm *base = &abm_dce->base; + + base->ctx = ctx; + base->funcs = &dce_funcs; + + abm_dce->regs = regs; + abm_dce->abm_shift = abm_shift; + abm_dce->abm_mask = abm_mask; +} + +struct abm *dce_abm_create( + struct dc_context *ctx, + const struct dce_abm_registers *regs, + const struct dce_abm_shift *abm_shift, + const struct dce_abm_mask *abm_mask) +{ + struct dce_abm *abm_dce = dm_alloc(sizeof(*abm_dce)); + + if (abm_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask); + + abm_dce->base.funcs = &dce_funcs; + + return &abm_dce->base; +} + +void dce_abm_destroy(struct abm **abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(*abm); + + dm_free(abm_dce); + *abm = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h new file mode 100644 index 000000000000..cf40e303cbcf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -0,0 +1,157 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef _DCE_ABM_H_ +#define _DCE_ABM_H_ + +#include "abm.h" + +#define ABM_COMMON_REG_LIST_DCE_BASE() \ + SR(BL_PWM_PERIOD_CNTL), \ + SR(BL_PWM_CNTL), \ + SR(MASTER_COMM_CNTL_REG), \ + SR(MASTER_COMM_CMD_REG) + +#define ABM_DCE110_COMMON_REG_LIST() \ + ABM_COMMON_REG_LIST_DCE_BASE(), \ + SR(DC_ABM1_HG_SAMPLE_RATE), \ + SR(DC_ABM1_LS_SAMPLE_RATE), \ + SR(BL1_PWM_BL_UPDATE_SAMPLE_RATE), \ + SR(DC_ABM1_HG_MISC_CTRL), \ + SR(DC_ABM1_IPCSC_COEFF_SEL), \ + SR(BL1_PWM_CURRENT_ABM_LEVEL), \ + SR(BL1_PWM_TARGET_ABM_LEVEL), \ + SR(BL1_PWM_USER_LEVEL), \ + SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ + SR(DC_ABM1_HGLS_REG_READ_PROGRESS) + +#define ABM_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, mask_sh), \ + ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \ + ABM_SF(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \ + ABM_SF(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \ + ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh) + +#define ABM_MASK_SH_LIST_DCE110(mask_sh) \ + ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + ABM_SF(DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ + ABM_SF(DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_VMAX_SEL, mask_sh), \ + ABM_SF(DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ + ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ + ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ + ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ + ABM_SF(BL1_PWM_CURRENT_ABM_LEVEL, \ + BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ + ABM_SF(BL1_PWM_TARGET_ABM_LEVEL, \ + BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ + ABM_SF(BL1_PWM_USER_LEVEL, \ + BL1_PWM_USER_LEVEL, mask_sh), \ + ABM_SF(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) + +#define ABM_REG_FIELD_LIST(type) \ + type ABM1_HG_NUM_OF_BINS_SEL; \ + type ABM1_HG_VMAX_SEL; \ + type ABM1_HG_BIN_BITWIDTH_SIZE_SEL; \ + type ABM1_IPCSC_COEFF_SEL_R; \ + type ABM1_IPCSC_COEFF_SEL_G; \ + type ABM1_IPCSC_COEFF_SEL_B; \ + type BL1_PWM_CURRENT_ABM_LEVEL; \ + type BL1_PWM_TARGET_ABM_LEVEL; \ + type BL1_PWM_USER_LEVEL; \ + type ABM1_LS_MIN_PIXEL_VALUE_THRES; \ + type ABM1_LS_MAX_PIXEL_VALUE_THRES; \ + type ABM1_HG_REG_READ_MISSED_FRAME_CLEAR; \ + type ABM1_LS_REG_READ_MISSED_FRAME_CLEAR; \ + type ABM1_BL_REG_READ_MISSED_FRAME_CLEAR; \ + type BL_PWM_PERIOD; \ + type BL_PWM_PERIOD_BITCNT; \ + type BL_ACTIVE_INT_FRAC_CNT; \ + type BL_PWM_FRACTIONAL_EN; \ + type MASTER_COMM_INTERRUPT; \ + type MASTER_COMM_CMD_REG_BYTE0; \ + type MASTER_COMM_CMD_REG_BYTE2 + +struct dce_abm_shift { + ABM_REG_FIELD_LIST(uint8_t); +}; + +struct dce_abm_mask { + ABM_REG_FIELD_LIST(uint32_t); +}; + +struct dce_abm_registers { + uint32_t BL_PWM_PERIOD_CNTL; + uint32_t BL_PWM_CNTL; + uint32_t DC_ABM1_HG_SAMPLE_RATE; + uint32_t DC_ABM1_LS_SAMPLE_RATE; + uint32_t BL1_PWM_BL_UPDATE_SAMPLE_RATE; + uint32_t DC_ABM1_HG_MISC_CTRL; + uint32_t DC_ABM1_IPCSC_COEFF_SEL; + uint32_t BL1_PWM_CURRENT_ABM_LEVEL; + uint32_t BL1_PWM_TARGET_ABM_LEVEL; + uint32_t BL1_PWM_USER_LEVEL; + uint32_t DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES; + uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS; + uint32_t MASTER_COMM_CNTL_REG; + uint32_t MASTER_COMM_CMD_REG; +}; + +struct dce_abm { + struct abm base; + const struct dce_abm_registers *regs; + const struct dce_abm_shift *abm_shift; + const struct dce_abm_mask *abm_mask; +}; + +struct abm *dce_abm_create( + struct dc_context *ctx, + const struct dce_abm_registers *regs, + const struct dce_abm_shift *abm_shift, + const struct dce_abm_mask *abm_mask); + +void dce_abm_destroy(struct abm **abm); + +#endif /* _DCE_ABM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c new file mode 100644 index 000000000000..eb0e95f57aa9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -0,0 +1,127 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_dmcu.h" +#include "dm_services.h" +#include "reg_helper.h" +#include "fixed32_32.h" +#include "dc.h" + +#define TO_DCE_DMCU(dmcu)\ + container_of(dmcu, struct dce_dmcu, base) + +#define REG(reg) \ + (dmcu_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + dmcu_dce->dmcu_shift->field_name, dmcu_dce->dmcu_mask->field_name + +#define CTX \ + dmcu_dce->base.ctx + +bool dce_dmcu_load_iram(struct dmcu *dmcu, + unsigned int start_offset, + const char *src, + unsigned int bytes) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int count = 0; + uint32_t status; + + /* Enable write access to IRAM */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 1, + IRAM_WR_ADDR_AUTO_INC, 1); + + do { + dm_delay_in_microseconds(dmcu->ctx, 2); + REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &status); + count++; + } while + ((status & dmcu_dce->dmcu_mask->DMCU_IRAM_MEM_PWR_STATE) && count < 10); + + REG_WRITE(DMCU_IRAM_WR_CTRL, start_offset); + + for (count = 0; count < bytes; count++) + REG_WRITE(DMCU_IRAM_WR_DATA, src[count]); + + /* Disable write access to IRAM to allow dynamic sleep state */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 0, + IRAM_WR_ADDR_AUTO_INC, 0); + + return true; +} + +static const struct dmcu_funcs dce_funcs = { + .load_iram = dce_dmcu_load_iram, +}; + +static void dce_dmcu_construct( + struct dce_dmcu *dmcu_dce, + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask) +{ + struct dmcu *base = &dmcu_dce->base; + + base->ctx = ctx; + base->funcs = &dce_funcs; + + dmcu_dce->regs = regs; + dmcu_dce->dmcu_shift = dmcu_shift; + dmcu_dce->dmcu_mask = dmcu_mask; +} + +struct dmcu *dce_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask) +{ + struct dce_dmcu *dmcu_dce = dm_alloc(sizeof(*dmcu_dce)); + + if (dmcu_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_dmcu_construct( + dmcu_dce, ctx, regs, dmcu_shift, dmcu_mask); + + dmcu_dce->base.funcs = &dce_funcs; + + return &dmcu_dce->base; +} + +void dce_dmcu_destroy(struct dmcu **dmcu) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu); + + dm_free(dmcu_dce); + *dmcu = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h new file mode 100644 index 000000000000..b026157a2eea --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -0,0 +1,91 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef _DCE_DMCU_H_ +#define _DCE_DMCU_H_ + +#include "dmcu.h" + +#define DMCU_COMMON_REG_LIST_DCE_BASE() \ + SR(DMCU_RAM_ACCESS_CTRL), \ + SR(DMCU_IRAM_WR_CTRL), \ + SR(DMCU_IRAM_WR_DATA) + +#define DMCU_DCE110_COMMON_REG_LIST() \ + DMCU_COMMON_REG_LIST_DCE_BASE(), \ + SR(DCI_MEM_PWR_STATUS) + +#define DMCU_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ + IRAM_HOST_ACCESS_EN, mask_sh), \ + DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ + IRAM_WR_ADDR_AUTO_INC, mask_sh) + +#define DMCU_MASK_SH_LIST_DCE110(mask_sh) \ + DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + DMCU_SF(DCI_MEM_PWR_STATUS, \ + DMCU_IRAM_MEM_PWR_STATE, mask_sh) + +#define DMCU_REG_FIELD_LIST(type) \ + type DMCU_IRAM_MEM_PWR_STATE; \ + type IRAM_HOST_ACCESS_EN; \ + type IRAM_WR_ADDR_AUTO_INC + +struct dce_dmcu_shift { + DMCU_REG_FIELD_LIST(uint8_t); +}; + +struct dce_dmcu_mask { + DMCU_REG_FIELD_LIST(uint32_t); +}; + +struct dce_dmcu_registers { + uint32_t DMCU_RAM_ACCESS_CTRL; + uint32_t DCI_MEM_PWR_STATUS; + uint32_t DMU_MEM_PWR_CNTL; + uint32_t DMCU_IRAM_WR_CTRL; + uint32_t DMCU_IRAM_WR_DATA; +}; + +struct dce_dmcu { + struct dmcu base; + const struct dce_dmcu_registers *regs; + const struct dce_dmcu_shift *dmcu_shift; + const struct dce_dmcu_mask *dmcu_mask; +}; + +struct dmcu *dce_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask); + +void dce_dmcu_destroy(struct dmcu **dmcu); + +#endif /* _DCE_ABM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index e9d1a54bffd3..f9325626c26e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -142,7 +142,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { dce110_link_encoder_set_dmcu_backlight_level, .init_dmcu_backlight_settings = dce110_link_encoder_init_dmcu_backlight_settings, - .set_dmcu_abm_level = dce110_link_encoder_set_dmcu_abm_level, .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable, .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr, .backlight_control = dce110_link_encoder_edp_backlight_control, @@ -1769,8 +1768,7 @@ void dce110_link_encoder_init_dmcu_backlight_settings( * Bios bug w/a - period resets to zero, * restoring to cache values which is always correct */ - REG_GET(BL_PWM_CNTL, - BL_ACTIVE_INT_FRAC_CNT, &value); + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); if (value == 0 || bl_pwm_cntl == 1) { if (stored_backlight_registers.vBL_PWM_CNTL != 0) { pwmCntl = stored_backlight_registers.vBL_PWM_CNTL; @@ -1810,36 +1808,6 @@ void dce110_link_encoder_init_dmcu_backlight_settings( /* Enable the backlight output */ REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); - -} - -void dce110_link_encoder_set_dmcu_abm_level( - struct link_encoder *enc, uint32_t level) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - /* setDMCUParam_ABMLevel */ - REG_UPDATE_2(MASTER_COMM_CMD_REG, - MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, - MASTER_COMM_CMD_REG_BYTE2, level); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) @@ -1856,10 +1824,8 @@ static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) do { dm_delay_in_microseconds(ctx, 2); - REG_GET(DCI_MEM_PWR_STATUS, - DMCU_IRAM_MEM_PWR_STATE, &value); - } while - (value != 0 && count++ < 10); + REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); + } while (value != 0 && count++ < 10); /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6acb9faf29f1..d67f1100c3d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -42,6 +42,7 @@ #include "stream_encoder.h" #include "link_encoder.h" #include "clock_source.h" +#include "abm.h" #include "audio.h" #include "dce/dce_hwseq.h" @@ -2166,6 +2167,7 @@ static void init_hw(struct core_dc *dc) int i; struct dc_bios *bp; struct transform *xfm; + struct abm *abm; bp = dc->ctx->dc_bios; for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -2210,6 +2212,10 @@ static void init_hw(struct core_dc *dc) struct audio *audio = dc->res_pool->audios[i]; audio->funcs->hw_init(audio); } + + abm = dc->res_pool->abm; + if (abm != NULL) + abm->funcs->abm_init(abm); } /* TODO: move this to apply_ctx_tohw some how?*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 0b8f8927162f..8dc69be15182 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -49,6 +49,8 @@ #include "dce/dce_clock_source.h" #include "dce/dce_hwseq.h" #include "dce110/dce110_hw_sequencer.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" #include "reg_helper.h" @@ -200,6 +202,30 @@ static const struct dce_disp_clk_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -712,6 +738,12 @@ static void destruct(struct dce110_resource_pool *pool) } } + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + if (pool->base.display_clock != NULL) dce_disp_clk_destroy(&pool->base.display_clock); @@ -1286,6 +1318,26 @@ static bool construct( goto res_create_fail; } + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + /* get static clock information for PPLIB or firmware, save * max_clock_state */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index cc826efac58d..7e99b2b96794 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -46,6 +46,8 @@ #include "dce/dce_hwseq.h" #include "dce112/dce112_hw_sequencer.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" #include "reg_helper.h" @@ -218,6 +220,30 @@ static const struct dce_disp_clk_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -719,6 +745,12 @@ static void destruct(struct dce110_resource_pool *pool) } } + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + if (pool->base.display_clock != NULL) dce_disp_clk_destroy(&pool->base.display_clock); @@ -1283,6 +1315,25 @@ static bool construct( goto res_create_fail; } + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } /* get static clock information for PPLIB or firmware, save * max_clock_state diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b349b5768b6e..1a81e83d1785 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -259,6 +259,9 @@ struct resource_pool { struct display_clock *display_clock; struct irq_service *irqs; + struct abm *abm; + struct dmcu *dmcu; + const struct resource_funcs *funcs; const struct resource_caps *res_cap; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h new file mode 100644 index 000000000000..9c9a6877387a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -0,0 +1,40 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_ABM_H__ +#define __DC_ABM_H__ + +#include "dm_services_types.h" + +struct abm { + struct dc_context *ctx; + const struct abm_funcs *funcs; +}; + +struct abm_funcs { + void (*abm_init)(struct abm *abm); + bool (*set_abm_level)(struct abm *abm, unsigned int abm_level); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h new file mode 100644 index 000000000000..62012f091836 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -0,0 +1,42 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_DMCU_H__ +#define __DC_DMCU_H__ + +#include "dm_services_types.h" + +struct dmcu { + struct dc_context *ctx; + const struct dmcu_funcs *funcs; +}; + +struct dmcu_funcs { + bool (*load_iram)(struct dmcu *dmcu, + unsigned int start_offset, + const char *src, + unsigned int bytes); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index ac4010b9c638..949eae6d5402 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -225,7 +225,6 @@ struct link_encoder_funcs { void (*set_dmcu_backlight_level)(struct link_encoder *enc, uint32_t level, uint32_t frame_ramp, uint32_t controller_id); void (*init_dmcu_backlight_settings)(struct link_encoder *enc); - void (*set_dmcu_abm_level)(struct link_encoder *enc, uint32_t level); void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable); void (*setup_dmcu_psr)(struct link_encoder *enc, struct psr_dmcu_context *psr_context); -- GitLab From 6728b30c974e38711f70dc38edf68503bf71c4a9 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 24 Jan 2017 15:19:42 -0500 Subject: [PATCH 0228/2898] drm/amd/display: Move backlight from encoder to ABM Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 34 --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 63 ++--- drivers/gpu/drm/amd/display/dc/dc.h | 5 - drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 264 +++++++++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 35 ++- .../drm/amd/display/dc/dce/dce_link_encoder.c | 260 ----------------- .../drm/amd/display/dc/dce/dce_link_encoder.h | 24 -- .../display/dc/dce110/dce110_hw_sequencer.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 5 + .../drm/amd/display/dc/inc/hw/link_encoder.h | 5 - .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 - .../display/dc/virtual/virtual_link_encoder.c | 13 - 12 files changed, 316 insertions(+), 400 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 152c694cc044..499ef561bbfc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -240,34 +240,6 @@ static void stream_update_scaling( } } -static bool set_backlight(struct dc *dc, unsigned int backlight_level, - unsigned int frame_ramp, const struct dc_stream *stream) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; - - if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) { - for (i = 0; i < core_dc->link_count; i++) - dc_link_set_backlight_level(&core_dc->links[i]->public, - backlight_level, frame_ramp, stream); - } - - return true; - -} - -static bool init_dmcu_backlight_settings(struct dc *dc) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; - - for (i = 0; i < core_dc->link_count; i++) - dc_link_init_dmcu_backlight_settings - (&core_dc->links[i]->public); - - return true; -} - static bool set_psr_enable(struct dc *dc, bool enable) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -390,12 +362,6 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; - core_dc->public.stream_funcs.set_backlight = - set_backlight; - - core_dc->public.stream_funcs.init_dmcu_backlight_settings = - init_dmcu_backlight_settings; - core_dc->public.stream_funcs.set_psr_enable = set_psr_enable; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 84efc25d0e33..2bceb3aa24b5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -37,6 +37,7 @@ #include "link_encoder.h" #include "hw_sequencer.h" #include "resource.h" +#include "abm.h" #include "fixed31_32.h" #include "dpcd_defs.h" @@ -1386,48 +1387,40 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream) { struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct core_stream *core_stream = NULL; + struct abm *abm = core_dc->res_pool->abm; unsigned int controller_id = 0; int i; - uint32_t dmcu_status; - dm_logger_write(ctx->logger, LOG_BACKLIGHT, - "New Backlight level: %d (0x%X)\n", level, level); + if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) + return false; - dmcu_status = dm_read_reg(ctx, mmDMCU_STATUS); + dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, + "New Backlight level: %d (0x%X)\n", level, level); - /* If DMCU is in reset state, DMCU is uninitialized */ - if (get_reg_field_value(dmcu_status, mmDMCU_STATUS, UC_IN_RESET)) { - link->link_enc->funcs->set_lcd_backlight_level(link->link_enc, - level); - } else { - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) - /* dmcu -1 for all controller id values, - * therefore +1 here - */ - controller_id = core_dc->current_context->res_ctx. - pipe_ctx[i].tg->inst + 1; + if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD) { + if (stream != NULL) { + core_stream = DC_STREAM_TO_CORE(stream); + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx. + pipe_ctx[i].stream + == core_stream) + /* DMCU -1 for all controller id values, + * therefore +1 here + */ + controller_id = + core_dc->current_context-> + res_ctx.pipe_ctx[i].tg->inst + + 1; + } } - - link->link_enc->funcs->set_dmcu_backlight_level - (link->link_enc, level, - frame_ramp, controller_id); + abm->funcs->set_backlight_level( + abm, + level, + frame_ramp, + controller_id); } - return true; -} - - -bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link) -{ - struct core_link *link = DC_LINK_TO_CORE(dc_link); - - if (link->link_enc->funcs->init_dmcu_backlight_settings != NULL) - link->link_enc->funcs-> - init_dmcu_backlight_settings(link->link_enc); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8cb53b626641..1308af59d839 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -100,9 +100,6 @@ struct dc_stream_funcs { const struct rect *dst); bool (*set_gamut_remap)(struct dc *dc, const struct dc_stream **stream, int num_streams); - bool (*set_backlight)(struct dc *dc, unsigned int backlight_level, - unsigned int frame_ramp, const struct dc_stream *stream); - bool (*init_dmcu_backlight_settings)(struct dc *dc); bool (*set_psr_enable)(struct dc *dc, bool enable); bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream); }; @@ -572,8 +569,6 @@ const struct graphics_object_id dc_get_link_id_at_index( bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream); -bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link); - bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_setup_psr(const struct dc_link *dc_link, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index ce49bee8e038..f4696bf14a70 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -29,6 +29,9 @@ #include "fixed32_32.h" #include "dc.h" +#include "atom.h" + + #define TO_DCE_ABM(abm)\ container_of(abm, struct dce_abm, base) @@ -43,6 +46,19 @@ abm_dce->base.ctx #define MCP_ABM_LEVEL_SET 0x65 +#define MCP_ABM_PIPE_SET 0x66 +#define MCP_BL_SET 0x67 + +struct abm_backlight_registers { + unsigned int BL_PWM_CNTL; + unsigned int BL_PWM_CNTL2; + unsigned int BL_PWM_PERIOD_CNTL; + unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; +}; + +/* registers setting needs to be save and restored used at InitBacklight */ +static struct abm_backlight_registers stored_backlight_registers = {0}; + static unsigned int get_current_backlight(struct dce_abm *abm_dce) { @@ -93,7 +109,147 @@ static unsigned int get_current_backlight(struct dce_abm *abm_dce) return (uint32_t)(current_backlight); } -void dce_abm_init(struct abm *abm) +static void driver_set_backlight_level(struct dce_abm *abm_dce, uint32_t level) +{ + uint32_t backlight_24bit; + uint32_t backlight_17bit; + uint32_t backlight_16bit; + uint32_t masked_pwm_period; + uint8_t rounding_bit; + uint8_t bit_count; + uint64_t active_duty_cycle; + uint32_t pwm_period_bitcnt; + + /* + * 1. Convert 8-bit value to 17 bit U1.16 format + * (1 integer, 16 fractional bits) + */ + + /* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value, + * effectively multiplying value by 256/255 + * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF + */ + backlight_24bit = level * 0x10101; + + /* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8 + * used for rounding, take most significant bit of fraction for + * rounding, e.g. for 0xEFEFEF, rounding bit is 1 + */ + rounding_bit = (backlight_24bit >> 7) & 1; + + /* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit + * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1 + */ + backlight_17bit = (backlight_24bit >> 8) + rounding_bit; + + /* + * 2. Find 16 bit backlight active duty cycle, where 0 <= backlight + * active duty cycle <= backlight period + */ + + /* 2.1 Apply bitmask for backlight period value based on value of BITCNT + */ + REG_GET_2(BL_PWM_PERIOD_CNTL, + BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt, + BL_PWM_PERIOD, &masked_pwm_period); + + if (pwm_period_bitcnt == 0) + bit_count = 16; + else + bit_count = pwm_period_bitcnt; + + /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ + masked_pwm_period = masked_pwm_period & ((1 << bit_count) - 1); + + /* 2.2 Calculate integer active duty cycle required upper 16 bits + * contain integer component, lower 16 bits contain fractional component + * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 + */ + active_duty_cycle = backlight_17bit * masked_pwm_period; + + /* 2.3 Calculate 16 bit active duty cycle from integer and fractional + * components shift by bitCount then mask 16 bits and add rounding bit + * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 + */ + backlight_16bit = active_duty_cycle >> bit_count; + backlight_16bit &= 0xFFFF; + backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; + + /* + * 3. Program register with updated value + */ + + /* 3.1 Lock group 2 backlight registers */ + + REG_UPDATE_2(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1, + BL_PWM_GRP1_REG_LOCK, 1); + + // 3.2 Write new active duty cycle + REG_UPDATE(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); + + /* 3.3 Unlock group 2 backlight registers */ + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 0); + + /* 5.4.4 Wait for pending bit to be cleared */ + REG_WAIT(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, + 0, 10, 1000); +} + +static void dmcu_set_backlight_level( + struct dce_abm *abm_dce, + uint32_t level, + uint32_t frame_ramp, + uint32_t controller_id) +{ + unsigned int backlight_16_bit = (level * 0x10101) >> 8; + unsigned int backlight_17_bit = backlight_16_bit + + (((backlight_16_bit & 0x80) >> 7) & 1); + uint32_t rampingBoundary = 0xFFFF; + uint32_t s2; + + /* set ramping boundary */ + REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary); + + /* setDMCUParam_Pipe */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, + MASTER_COMM_CMD_REG_BYTE1, controller_id); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, + 0, 100, 800); + + /* setDMCUParam_BL */ + REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17_bit); + + /* write ramp */ + if (controller_id == 0) + frame_ramp = 0; + REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* UpdateRequestedBacklightLevel */ + s2 = REG_READ(BIOS_SCRATCH_2); + + s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; + level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >> + ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); + + REG_WRITE(BIOS_SCRATCH_2, s2); +} + +static void dce_abm_init(struct abm *abm) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); unsigned int backlight = get_current_backlight(abm_dce); @@ -133,24 +289,13 @@ void dce_abm_init(struct abm *abm) ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); } -bool dce_abm_set_level(struct abm *abm, uint32_t level) +static bool dce_abm_set_level(struct abm *abm, uint32_t level) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); struct dc_context *ctx = abm_dce->base.ctx; - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int value; - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - REG_GET(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, &value); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((value & abm_dce->abm_mask->MASTER_COMM_INTERRUPT) && - dmcu_max_retry_on_wait_reg_ready > 0); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + 100, 800); /* setDMCUParam_ABMLevel */ REG_UPDATE_2(MASTER_COMM_CMD_REG, @@ -163,9 +308,98 @@ bool dce_abm_set_level(struct abm *abm, uint32_t level) return true; } +static bool dce_abm_init_backlight(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + uint32_t value; + + /* It must not be 0, so we have to restore them + * Bios bug w/a - period resets to zero, + * restoring to cache values which is always correct + */ + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); + if (value == 0 || value == 1) { + if (stored_backlight_registers.BL_PWM_CNTL != 0) { + REG_WRITE(BL_PWM_CNTL, + stored_backlight_registers.BL_PWM_CNTL); + REG_WRITE(BL_PWM_CNTL2, + stored_backlight_registers.BL_PWM_CNTL2); + REG_WRITE(BL_PWM_PERIOD_CNTL, + stored_backlight_registers.BL_PWM_PERIOD_CNTL); + REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, + BL_PWM_REF_DIV, + stored_backlight_registers. + LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } else { + /* TODO: Note: This should not really happen since VBIOS + * should have initialized PWM registers on boot. + */ + REG_WRITE(BL_PWM_CNTL, 0xC000FA00); + REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); + } + } else { + stored_backlight_registers.BL_PWM_CNTL = + REG_READ(BL_PWM_CNTL); + stored_backlight_registers.BL_PWM_CNTL2 = + REG_READ(BL_PWM_CNTL2); + stored_backlight_registers.BL_PWM_PERIOD_CNTL = + REG_READ(BL_PWM_PERIOD_CNTL); + + REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, + &stored_backlight_registers. + LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } + + /* Have driver take backlight control + * TakeBacklightControl(true) + */ + value = REG_READ(BIOS_SCRATCH_2); + value |= ATOM_S2_VRI_BRIGHT_ENABLE; + REG_WRITE(BIOS_SCRATCH_2, value); + + /* Enable the backlight output */ + REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); + + /* Unlock group 2 backlight registers */ + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 0); + + return true; +} + +static bool dce_abm_set_backlight_level( + struct abm *abm, + unsigned int backlight_level, + unsigned int frame_ramp, + unsigned int controller_id) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + unsigned int dmcu_uc_reset; + + dm_logger_write(abm->ctx->logger, LOG_BACKLIGHT, + "New Backlight level: %d (0x%X)\n", + backlight_level, backlight_level); + + REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); + + /* If DMCU is in reset state, DMCU is uninitialized */ + if (dmcu_uc_reset) { + driver_set_backlight_level(abm_dce, backlight_level); + } else { + dmcu_set_backlight_level(abm_dce, + backlight_level, + frame_ramp, + controller_id); + } + + return true; +} + static const struct abm_funcs dce_funcs = { .abm_init = dce_abm_init, .set_abm_level = dce_abm_set_level, + .init_backlight = dce_abm_init_backlight, + .set_backlight_level = dce_abm_set_backlight_level }; static void dce_abm_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index cf40e303cbcf..56087b36bdeb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -32,8 +32,13 @@ #define ABM_COMMON_REG_LIST_DCE_BASE() \ SR(BL_PWM_PERIOD_CNTL), \ SR(BL_PWM_CNTL), \ + SR(BL_PWM_CNTL2), \ + SR(BL_PWM_GRP1_REG_LOCK), \ + SR(LVTMA_PWRSEQ_REF_DIV), \ SR(MASTER_COMM_CNTL_REG), \ - SR(MASTER_COMM_CMD_REG) + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(DMCU_STATUS) #define ABM_DCE110_COMMON_REG_LIST() \ ABM_COMMON_REG_LIST_DCE_BASE(), \ @@ -46,7 +51,8 @@ SR(BL1_PWM_TARGET_ABM_LEVEL), \ SR(BL1_PWM_USER_LEVEL), \ SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ - SR(DC_ABM1_HGLS_REG_READ_PROGRESS) + SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ + SR(BIOS_SCRATCH_2) #define ABM_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -56,9 +62,16 @@ ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \ ABM_SF(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \ ABM_SF(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \ + ABM_SF(BL_PWM_CNTL, BL_PWM_EN, mask_sh), \ + ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, mask_sh), \ + ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, mask_sh), \ + ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, mask_sh), \ + ABM_SF(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, mask_sh), \ ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ - ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh) + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE1, mask_sh), \ + ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh), \ + ABM_SF(DMCU_STATUS, UC_IN_RESET, mask_sh) #define ABM_MASK_SH_LIST_DCE110(mask_sh) \ ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ @@ -91,6 +104,7 @@ ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) + #define ABM_REG_FIELD_LIST(type) \ type ABM1_HG_NUM_OF_BINS_SEL; \ type ABM1_HG_VMAX_SEL; \ @@ -112,7 +126,14 @@ type BL_PWM_FRACTIONAL_EN; \ type MASTER_COMM_INTERRUPT; \ type MASTER_COMM_CMD_REG_BYTE0; \ - type MASTER_COMM_CMD_REG_BYTE2 + type MASTER_COMM_CMD_REG_BYTE1; \ + type MASTER_COMM_CMD_REG_BYTE2; \ + type BL_PWM_REF_DIV; \ + type BL_PWM_EN; \ + type UC_IN_RESET; \ + type BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN; \ + type BL_PWM_GRP1_REG_LOCK; \ + type BL_PWM_GRP1_REG_UPDATE_PENDING struct dce_abm_shift { ABM_REG_FIELD_LIST(uint8_t); @@ -125,6 +146,8 @@ struct dce_abm_mask { struct dce_abm_registers { uint32_t BL_PWM_PERIOD_CNTL; uint32_t BL_PWM_CNTL; + uint32_t BL_PWM_CNTL2; + uint32_t LVTMA_PWRSEQ_REF_DIV; uint32_t DC_ABM1_HG_SAMPLE_RATE; uint32_t DC_ABM1_LS_SAMPLE_RATE; uint32_t BL1_PWM_BL_UPDATE_SAMPLE_RATE; @@ -137,6 +160,10 @@ struct dce_abm_registers { uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS; uint32_t MASTER_COMM_CNTL_REG; uint32_t MASTER_COMM_CMD_REG; + uint32_t MASTER_COMM_DATA_REG1; + uint32_t BIOS_SCRATCH_2; + uint32_t DMCU_STATUS; + uint32_t BL_PWM_GRP1_REG_LOCK; }; struct dce_abm { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index f9325626c26e..3847764688dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -38,15 +38,6 @@ #include "dce/dce_11_0_sh_mask.h" #include "dce/dce_11_0_enum.h" -#ifndef ATOM_S2_CURRENT_BL_LEVEL_MASK -#define ATOM_S2_CURRENT_BL_LEVEL_MASK 0x0000FF00L -#define ATOM_S2_VRI_BRIGHT_ENABLE 0x20000000L -#endif - -#ifndef ATOM_S2_CURRENT_BL_LEVEL_SHIFT -#define ATOM_S2_CURRENT_BL_LEVEL_SHIFT 8 -#endif - #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK #define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L #endif @@ -96,13 +87,6 @@ /* For current ASICs pixel clock - 600MHz */ #define MAX_ENCODER_CLOCK 600000 -/* Set the ABM Pipe */ -#define MCP_ABM_PIPE_SET 0x66 -/* Set the ABM level */ -#define MCP_ABM_LEVEL_SET 0x65 -/* Set backlight level */ -#define MCP_BL_SET 0x67 - /* PSR related commands */ #define PSR_ENABLE 0x20 #define PSR_EXIT 0x21 @@ -111,9 +95,6 @@ /*TODO: Used for psr wakeup for set backlight level*/ static unsigned int psr_crtc_offset; -/* registers setting needs to be save and restored used at InitBacklight */ -static struct dce110_abm_backlight_registers stored_backlight_registers; - enum { DP_MST_UPDATE_MAX_RETRY = 50 }; @@ -137,11 +118,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = dce110_link_encoder_update_mst_stream_allocation_table, - .set_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level, - .set_dmcu_backlight_level = - dce110_link_encoder_set_dmcu_backlight_level, - .init_dmcu_backlight_settings = - dce110_link_encoder_init_dmcu_backlight_settings, .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable, .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr, .backlight_control = dce110_link_encoder_edp_backlight_control, @@ -1574,242 +1550,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( } while (retries < DP_MST_UPDATE_MAX_RETRY); } -void dce110_link_encoder_set_lcd_backlight_level( - struct link_encoder *enc, - uint32_t level) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - - const uint32_t backlight_update_pending_max_retry = 1000; - - uint32_t backlight_lock; - - uint32_t i; - uint32_t backlight_24bit; - uint32_t backlight_17bit; - uint32_t backlight_16bit; - uint32_t masked_pwm_period; - uint8_t rounding_bit; - uint8_t bit_count; - uint64_t active_duty_cycle; - uint32_t pwm_period_bitcnt; - - backlight_lock = REG_READ(BL_PWM_GRP1_REG_LOCK); - - /* - * 1. Convert 8-bit value to 17 bit U1.16 format - * (1 integer, 16 fractional bits) - */ - - /* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value, - * effectively multiplying value by 256/255 - * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF - */ - backlight_24bit = level * 0x10101; - - /* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8 - * used for rounding, take most significant bit of fraction for - * rounding, e.g. for 0xEFEFEF, rounding bit is 1 - */ - rounding_bit = (backlight_24bit >> 7) & 1; - - /* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit - * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1 - */ - backlight_17bit = (backlight_24bit >> 8) + rounding_bit; - - /* - * 2. Find 16 bit backlight active duty cycle, where 0 <= backlight - * active duty cycle <= backlight period - */ - - /* 2.1 Apply bitmask for backlight period value based on value of BITCNT - */ - { - REG_GET(BL_PWM_PERIOD_CNTL, - BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt); - - if (pwm_period_bitcnt == 0) - bit_count = 16; - else - bit_count = pwm_period_bitcnt; - } - - /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ - masked_pwm_period = - REG_GET(BL_PWM_PERIOD_CNTL, - BL_PWM_PERIOD, &masked_pwm_period) - & ((1 << bit_count) - 1); - - /* 2.2 Calculate integer active duty cycle required upper 16 bits - * contain integer component, lower 16 bits contain fractional component - * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 - */ - active_duty_cycle = backlight_17bit * masked_pwm_period; - - /* 2.3 Calculate 16 bit active duty cycle from integer and fractional - * components shift by bitCount then mask 16 bits and add rounding bit - * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 - */ - backlight_16bit = active_duty_cycle >> bit_count; - backlight_16bit &= 0xFFFF; - backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; - - REG_UPDATE(BL_PWM_CNTL, - BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); - - /* - * 3. Program register with updated value - */ - - /* 3.1 Lock group 2 backlight registers */ - - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1); - - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_LOCK, 1); - - /* 3.3 Unlock group 2 backlight registers */ - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_LOCK, 0); - - /* 5.4.4 Wait for pending bit to be cleared */ - for (i = 0; i < backlight_update_pending_max_retry; ++i) { - REG_GET(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_UPDATE_PENDING, &backlight_lock); - if (!backlight_lock) - break; - - udelay(10); - } -} - -void dce110_link_encoder_set_dmcu_backlight_level( - struct link_encoder *enc, - uint32_t level, - uint32_t frame_ramp, - uint32_t controller_id) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int backlight_17bit = level * 0x10101; - unsigned char temp_uchar = - (unsigned char)(((backlight_17bit & 0x80) >> 7) & 1); - unsigned int regValue; - uint32_t rampingBoundary = 0xFFFF; - uint32_t s2; - - backlight_17bit = (backlight_17bit >> 8) + temp_uchar; - - /* set ramping boundary */ - REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary); - - /* setDMCUParam_Pipe */ - REG_UPDATE_2(MASTER_COMM_CMD_REG, - MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, - MASTER_COMM_CMD_REG_BYTE1, controller_id); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - /* setDMCUParam_BL */ - REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17bit); - - /* write ramp */ - REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp); - - /* setDMCUParam_Cmd */ - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - /* UpdateRequestedBacklightLevel */ - s2 = REG_READ(BIOS_SCRATCH_2); - - s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK; - level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >> - ATOM_S2_CURRENT_BL_LEVEL_SHIFT); - s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT); - - REG_WRITE(BIOS_SCRATCH_2, s2); -} - -void dce110_link_encoder_init_dmcu_backlight_settings( - struct link_encoder *enc) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - uint32_t bl_pwm_cntl; - uint32_t pwmCntl; - uint32_t pwmCntl2; - uint32_t periodCntl; - uint32_t s2; - uint32_t value; - - if (enc->ctx->dc->debug.disable_dmcu) - return; - - bl_pwm_cntl = REG_READ(BL_PWM_CNTL); - - /* It must not be 0, so we have to restore them - * Bios bug w/a - period resets to zero, - * restoring to cache values which is always correct - */ - REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); - if (value == 0 || bl_pwm_cntl == 1) { - if (stored_backlight_registers.vBL_PWM_CNTL != 0) { - pwmCntl = stored_backlight_registers.vBL_PWM_CNTL; - REG_WRITE(BL_PWM_CNTL, pwmCntl); - - pwmCntl2 = stored_backlight_registers.vBL_PWM_CNTL2; - REG_WRITE(BL_PWM_CNTL2, pwmCntl2); - - periodCntl = - stored_backlight_registers.vBL_PWM_PERIOD_CNTL; - REG_WRITE(BL_PWM_PERIOD_CNTL, periodCntl); - - REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, - BL_PWM_REF_DIV, - stored_backlight_registers. - vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } - } else { - stored_backlight_registers.vBL_PWM_CNTL = - REG_READ(BL_PWM_CNTL); - stored_backlight_registers.vBL_PWM_CNTL2 = - REG_READ(BL_PWM_CNTL2); - stored_backlight_registers.vBL_PWM_PERIOD_CNTL = - REG_READ(BL_PWM_PERIOD_CNTL); - - REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, - &stored_backlight_registers. - vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } - - /* Have driver take backlight control - * TakeBacklightControl(true) - */ - s2 = REG_READ(BIOS_SCRATCH_2); - s2 |= ATOM_S2_VRI_BRIGHT_ENABLE; - REG_WRITE(BIOS_SCRATCH_2, s2); - - /* Enable the backlight output */ - REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); -} - static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index b3667df5250b..053f72b91b3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -226,13 +226,6 @@ union dce110_dmcu_psr_config_data_reg3 { unsigned int u32All; }; -struct dce110_abm_backlight_registers { - unsigned int vBL_PWM_CNTL; - unsigned int vBL_PWM_CNTL2; - unsigned int vBL_PWM_PERIOD_CNTL; - unsigned int vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; -}; - bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, @@ -317,23 +310,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_set_lcd_backlight_level( - struct link_encoder *enc, - uint32_t level); - -void dce110_link_encoder_set_dmcu_backlight_level( - struct link_encoder *enc, - uint32_t level, - uint32_t frame_ramp, - uint32_t controller_id); - -void dce110_link_encoder_init_dmcu_backlight_settings( - struct link_encoder *enc); - -void dce110_link_encoder_set_dmcu_abm_level( - struct link_encoder *enc, - uint32_t level); - void dce110_link_encoder_set_dmcu_psr_enable( struct link_encoder *enc, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d67f1100c3d9..a1a5dc6fcb67 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2214,8 +2214,10 @@ static void init_hw(struct core_dc *dc) } abm = dc->res_pool->abm; - if (abm != NULL) + if (abm != NULL) { + abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); + } } /* TODO: move this to apply_ctx_tohw some how?*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index 9c9a6877387a..7d07b7922391 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -35,6 +35,11 @@ struct abm { struct abm_funcs { void (*abm_init)(struct abm *abm); bool (*set_abm_level)(struct abm *abm, unsigned int abm_level); + bool (*init_backlight)(struct abm *abm); + bool (*set_backlight_level)(struct abm *abm, + unsigned int backlight_level, + unsigned int frame_ramp, + unsigned int controller_id); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 949eae6d5402..7b37b963666e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -220,11 +220,6 @@ struct link_encoder_funcs { void (*update_mst_stream_allocation_table)( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); - void (*set_lcd_backlight_level) (struct link_encoder *enc, - uint32_t level); - void (*set_dmcu_backlight_level)(struct link_encoder *enc, - uint32_t level, uint32_t frame_ramp, uint32_t controller_id); - void (*init_dmcu_backlight_settings)(struct link_encoder *enc); void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable); void (*setup_dmcu_psr)(struct link_encoder *enc, struct psr_dmcu_context *psr_context); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 562c8978fe9c..758a568589bb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -94,10 +94,6 @@ struct hw_sequencer_funcs { int group_size, struct pipe_ctx *grouped_pipes[]); - /* backlight control */ - void (*encoder_set_lcd_backlight_level)( - struct link_encoder *enc, uint32_t level); - void (*enable_display_pipe_clock_gating)( struct dc_context *ctx, bool clock_gating); diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 869dedca0b17..12df49927f09 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -72,16 +72,6 @@ static void virtual_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table) {} -static void virtual_link_encoder_set_lcd_backlight_level( - struct link_encoder *enc, - uint32_t level) {} - -static void virtual_link_encoder_set_dmcu_backlight_level( - struct link_encoder *enc, - uint32_t level, - uint32_t frame_ramp, - uint32_t controller_id) {} - static void virtual_link_encoder_edp_backlight_control( struct link_encoder *enc, bool enable) {} @@ -115,9 +105,6 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = { .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = virtual_link_encoder_update_mst_stream_allocation_table, - .set_lcd_backlight_level = virtual_link_encoder_set_lcd_backlight_level, - .set_dmcu_backlight_level = - virtual_link_encoder_set_dmcu_backlight_level, .backlight_control = virtual_link_encoder_edp_backlight_control, .power_control = virtual_link_encoder_edp_power_control, .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, -- GitLab From 998166a6116bea93f6e1672177581b689b008bf7 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 24 Jan 2017 15:45:33 -0500 Subject: [PATCH 0229/2898] drm/amd/display: Make new pixel clock more obvious Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 499ef561bbfc..e05e4199e38a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1066,6 +1066,7 @@ bool dc_pre_update_surfaces_to_stream( int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; + int new_disp_clk; struct dc_stream_status *stream_status = NULL; struct validate_context *context; struct validate_context *temp_context; @@ -1150,6 +1151,7 @@ bool dc_pre_update_surfaces_to_stream( ret = false; goto unexpected_fail; } + new_disp_clk = context->bw_results.dispclk_khz; if (core_dc->res_pool->funcs->apply_clk_constraints) { temp_context = core_dc->res_pool->funcs->apply_clk_constraints( @@ -1166,7 +1168,7 @@ bool dc_pre_update_surfaces_to_stream( context = temp_context; } - if (prev_disp_clk < context->bw_results.dispclk_khz) { + if (prev_disp_clk < new_disp_clk) { pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); context->res_ctx.pool->display_clock->funcs->set_clock( -- GitLab From 90b9d7fa107d1bde344af6df81927c07cb882f5e Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 27 Jan 2017 17:22:46 -0500 Subject: [PATCH 0230/2898] drm/amd/display: Support ABM without PPlib Fix problem with loading IRAM Signed-off-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 7 ++++- .../drm/amd/display/dc/dce/dce_link_encoder.h | 26 +++---------------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index b026157a2eea..33c1754f04f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -30,6 +30,7 @@ #include "dmcu.h" #define DMCU_COMMON_REG_LIST_DCE_BASE() \ + SR(DMCU_CTRL), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_WR_CTRL), \ SR(DMCU_IRAM_WR_DATA) @@ -42,6 +43,8 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + DMCU_SF(DMCU_CTRL, \ + DMCU_ENABLE, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ IRAM_HOST_ACCESS_EN, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ @@ -55,7 +58,8 @@ #define DMCU_REG_FIELD_LIST(type) \ type DMCU_IRAM_MEM_PWR_STATE; \ type IRAM_HOST_ACCESS_EN; \ - type IRAM_WR_ADDR_AUTO_INC + type IRAM_WR_ADDR_AUTO_INC; \ + type DMCU_ENABLE struct dce_dmcu_shift { DMCU_REG_FIELD_LIST(uint8_t); @@ -66,6 +70,7 @@ struct dce_dmcu_mask { }; struct dce_dmcu_registers { + uint32_t DMCU_CTRL; uint32_t DMCU_RAM_ACCESS_CTRL; uint32_t DCI_MEM_PWR_STATUS; uint32_t DMU_MEM_PWR_CNTL; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 053f72b91b3c..8a07665e693b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -39,18 +39,13 @@ SRI(DC_HPD_CONTROL, HPD, id) #define LE_COMMON_REG_LIST_BASE(id) \ - SR(BL_PWM_CNTL), \ - SR(BL_PWM_GRP1_REG_LOCK), \ - SR(BL_PWM_PERIOD_CNTL), \ - SR(LVTMA_PWRSEQ_CNTL), \ - SR(LVTMA_PWRSEQ_STATE), \ - SR(BL_PWM_CNTL2), \ - SR(LVTMA_PWRSEQ_REF_DIV), \ SR(MASTER_COMM_DATA_REG1), \ SR(MASTER_COMM_DATA_REG2), \ SR(MASTER_COMM_DATA_REG3), \ SR(MASTER_COMM_CMD_REG), \ SR(MASTER_COMM_CNTL_REG), \ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_DATA), \ @@ -81,22 +76,16 @@ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(BIOS_SCRATCH_2), \ - SR(BL1_PWM_USER_LEVEL), \ SR(DCI_MEM_PWR_STATUS) #define LE_DCE110_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(BIOS_SCRATCH_2), \ - SR(BL1_PWM_USER_LEVEL), \ SR(DCI_MEM_PWR_STATUS) #define LE_DCE80_REG_LIST(id)\ - SR(BIOS_SCRATCH_2), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(BL1_PWM_USER_LEVEL), \ LE_COMMON_REG_LIST_BASE(id) @@ -110,24 +99,16 @@ struct dce110_link_enc_hpd_registers { }; struct dce110_link_enc_registers { - /* BL registers */ - uint32_t BL_PWM_CNTL; - uint32_t BL_PWM_GRP1_REG_LOCK; - uint32_t BL_PWM_PERIOD_CNTL; + /* Backlight registers */ uint32_t LVTMA_PWRSEQ_CNTL; uint32_t LVTMA_PWRSEQ_STATE; - uint32_t BL_PWM_CNTL2; - uint32_t LVTMA_PWRSEQ_REF_DIV; /* DMCU registers */ - uint32_t BL1_PWM_USER_LEVEL; - uint32_t ABM0_BL1_PWM_USER_LEVEL; uint32_t MASTER_COMM_DATA_REG1; uint32_t MASTER_COMM_DATA_REG2; uint32_t MASTER_COMM_DATA_REG3; uint32_t MASTER_COMM_CMD_REG; uint32_t MASTER_COMM_CNTL_REG; - uint32_t BIOS_SCRATCH_2; uint32_t DMCU_RAM_ACCESS_CTRL; uint32_t DCI_MEM_PWR_STATUS; uint32_t DMU_MEM_PWR_CNTL; @@ -136,7 +117,6 @@ struct dce110_link_enc_registers { uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; uint32_t SMU_INTERRUPT_CONTROL; - /* Common DP registers */ uint32_t DIG_BE_CNTL; uint32_t DIG_BE_EN_CNTL; -- GitLab From 70814f6f092a91a552eef9f4580c9ddc7cdcbb32 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 27 Jan 2017 17:50:03 -0500 Subject: [PATCH 0231/2898] drm/amd/display: Debug option to force enable ABM Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1308af59d839..d7f848495d8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -143,6 +143,7 @@ struct dc_debug { bool disable_dfs_bypass; bool disable_clock_gate; bool disable_dmcu; + bool force_abm_enable; }; struct dc { -- GitLab From 0f56b418ef497032a71358fb8c76d10f24fd5d58 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 25 Jan 2017 13:58:46 -0500 Subject: [PATCH 0232/2898] drm/amd/display: add dcfclk reporting to pplib Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 48 +++++++------------ .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e05e4199e38a..9d2f78f21748 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1065,7 +1065,7 @@ bool dc_pre_update_surfaces_to_stream( { int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); - uint32_t prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; + int prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; int new_disp_clk; struct dc_stream_status *stream_status = NULL; struct validate_context *context; @@ -1146,36 +1146,23 @@ bool dc_pre_update_surfaces_to_stream( } } - if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) { - BREAK_TO_DEBUGGER(); - ret = false; - goto unexpected_fail; - } - new_disp_clk = context->bw_results.dispclk_khz; - - if (core_dc->res_pool->funcs->apply_clk_constraints) { - temp_context = core_dc->res_pool->funcs->apply_clk_constraints( - core_dc, - context); - if (!temp_context) { - dm_error("%s:failed apply clk constraints\n", __func__); + if (core_dc->res_pool->funcs->validate_bandwidth) + if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) { + BREAK_TO_DEBUGGER(); ret = false; goto unexpected_fail; } - resource_validate_ctx_destruct(context); - ASSERT(core_dc->scratch_val_ctx == temp_context); - core_dc->scratch_val_ctx = context; - context = temp_context; - } + new_disp_clk = context->bw_results.dispclk_khz; - if (prev_disp_clk < new_disp_clk) { + if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) + && prev_disp_clk < new_disp_clk) { pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); context->res_ctx.pool->display_clock->funcs->set_clock( context->res_ctx.pool->display_clock, - context->bw_results.dispclk_khz * 115 / 100); - core_dc->current_context->bw_results.dispclk_khz = - context->bw_results.dispclk_khz; + new_disp_clk * 115 / 100); + core_dc->current_context->bw_results.dispclk_khz = new_disp_clk; + core_dc->current_context->dispclk_khz = new_disp_clk; } for (i = 0; i < new_surface_count; i++) @@ -1209,15 +1196,14 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) { core_dc->current_context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( - core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); + } + if (core_dc->res_pool->funcs->validate_bandwidth) + if (core_dc->res_pool->funcs->validate_bandwidth( + core_dc, core_dc->current_context) != DC_OK) { + BREAK_TO_DEBUGGER(); + return false; } - - - if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, core_dc->current_context) - != DC_OK) { - BREAK_TO_DEBUGGER(); - return false; - } core_dc->hwss.set_bandwidth(core_dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 1a81e83d1785..124df6795b34 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -316,6 +316,7 @@ struct validate_context { struct bw_calcs_output bw_results; /* Note: these are big structures, do *not* put on stack! */ struct dm_pp_display_configuration pp_display_cfg; + int dispclk_khz; }; #endif /* _CORE_TYPES_H_ */ -- GitLab From 3efeef11f471c1c5ee116cb00d27f426bfa969dc Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Mon, 30 Jan 2017 10:25:43 -0500 Subject: [PATCH 0233/2898] drm/amd/display: surface validation on dce100 Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 6ae334b42fbf..800b22e70c7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -789,9 +789,9 @@ static bool dce100_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].stream->src.width + < set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].stream->src.height) + < set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) -- GitLab From 71f7256e41ad036215a69e6bf561f7d4a541f150 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 30 Jan 2017 17:35:59 -0500 Subject: [PATCH 0234/2898] drm/amd/display: remove CV-specific timing standard Signed-off-by: Charlene Liu Reviewed-by: Jordan Lazare Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 5 ----- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 -- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 4 ---- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c | 5 ----- 4 files changed, 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 9f462a299ff3..6cd1e93b5084 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -66,11 +66,6 @@ void color_space_to_black_color( } switch (colorspace) { - case COLOR_SPACE_YPBPR601: - *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_TV]; - break; - - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR601: case COLOR_SPACE_YCBCR709: case COLOR_SPACE_YCBCR601_LIMITED: diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 53c73de75da9..21092f33c83b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -435,8 +435,6 @@ enum dc_color_space { COLOR_SPACE_UNKNOWN, COLOR_SPACE_SRGB, COLOR_SPACE_SRGB_LIMITED, - COLOR_SPACE_YPBPR601, - COLOR_SPACE_YPBPR709, COLOR_SPACE_YCBCR601, COLOR_SPACE_YCBCR709, COLOR_SPACE_YCBCR601_LIMITED, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 62f01911639f..9247afd4d42f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -827,14 +827,12 @@ static bool configure_graphics_mode( OUTPUT_CSC_GRPH_MODE, 1); break; case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: case COLOR_SPACE_YCBCR601_LIMITED: /* YCbCr601 */ REG_SET(OUTPUT_CSC_CONTROL, 0, OUTPUT_CSC_GRPH_MODE, 2); break; case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR709_LIMITED: /* YCbCr709 */ REG_SET(OUTPUT_CSC_CONTROL, 0, @@ -858,14 +856,12 @@ static bool configure_graphics_mode( OUTPUT_CSC_GRPH_MODE, 1); break; case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: case COLOR_SPACE_YCBCR601_LIMITED: /* YCbCr601 */ REG_SET(OUTPUT_CSC_CONTROL, 0, OUTPUT_CSC_GRPH_MODE, 2); break; case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR709_LIMITED: /* YCbCr709 */ REG_SET(OUTPUT_CSC_CONTROL, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c index 6995a3de7564..019effe4c99c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -383,8 +383,6 @@ static bool configure_graphics_mode_v( /* not supported for underlay on CZ */ return false; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: case COLOR_SPACE_YCBCR601_LIMITED: /* YCbCr601 */ set_reg_field_value( @@ -394,7 +392,6 @@ static bool configure_graphics_mode_v( OUTPUT_CSC_MODE); break; case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR709_LIMITED: /* YCbCr709 */ set_reg_field_value( @@ -421,7 +418,6 @@ static bool configure_graphics_mode_v( /* not supported for underlay on CZ */ return false; case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YPBPR601: case COLOR_SPACE_YCBCR601_LIMITED: /* YCbCr601 */ set_reg_field_value( @@ -431,7 +427,6 @@ static bool configure_graphics_mode_v( OUTPUT_CSC_MODE); break; case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YPBPR709: case COLOR_SPACE_YCBCR709_LIMITED: /* YCbCr709 */ set_reg_field_value( -- GitLab From ca709397b5bf904ef04eb981d3b50e8e93c15394 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Feb 2017 11:23:20 -0500 Subject: [PATCH 0235/2898] drm/amd/display: Fix 64-bit division Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index f4696bf14a70..7005ebb28d46 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -94,7 +94,7 @@ static unsigned int get_current_backlight(struct dce_abm *abm_dce) if (bl_period == 0) bl_period = 0xFFFF; - current_backlight /= bl_period; + current_backlight = div_u64(current_backlight, bl_period); current_backlight = (current_backlight + 1) >> 1; current_backlight = (uint64_t)(current_backlight) * bl_period; -- GitLab From b7e2439c7878f06edb70379454d57ce3d51d3feb Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 6 Feb 2017 12:37:44 +0800 Subject: [PATCH 0236/2898] drm/amd/display: mclk level can't be 0. Signed-off-by: Rex Zhu Acked-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 5af27aad2dad..1ddc56cfbdc4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -357,8 +357,8 @@ bool dm_pp_get_clock_levels_by_type( * Than means the previous one is the highest * non-boosted one. */ DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n", - dc_clks->num_levels, i + 1); - dc_clks->num_levels = i; + dc_clks->num_levels, i); + dc_clks->num_levels = i > 0 ? i : 1; break; } } @@ -366,8 +366,8 @@ bool dm_pp_get_clock_levels_by_type( for (i = 0; i < dc_clks->num_levels; i++) { if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) { DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n", - dc_clks->num_levels, i + 1); - dc_clks->num_levels = i; + dc_clks->num_levels, i); + dc_clks->num_levels = i > 0 ? i : 1; break; } } -- GitLab From 71021265a6f03893139f58f2bc50d2ad9adc3826 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 27 Jan 2017 15:44:26 -0500 Subject: [PATCH 0237/2898] drm/amd/display: Clear test pattern when enabling stream Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2bceb3aa24b5..ec5de329b091 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1846,6 +1846,11 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) return; } + /* turn off otg test pattern if enable */ + pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, + COLOR_DEPTH_UNDEFINED); + core_dc->hwss.enable_stream(pipe_ctx); if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) -- GitLab From 8fde5884f4a18dec81ab5d498bf7bf3c156f8dfb Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 31 Jan 2017 20:18:05 -0500 Subject: [PATCH 0238/2898] drm/amd/display: Fix YCbCr pixel format shows green issue Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ee1c3b029394..3d8a85e48b05 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1300,19 +1300,23 @@ static void set_avi_info_frame( info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; /* C0, C1 : Colorimetry */ - if (color_space == COLOR_SPACE_YCBCR709) + if (color_space == COLOR_SPACE_YCBCR709 || + color_space == COLOR_SPACE_YCBCR709_LIMITED) info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = COLORIMETRY_ITU709; - else if (color_space == COLOR_SPACE_YCBCR601) + else if (color_space == COLOR_SPACE_YCBCR601 || + color_space == COLOR_SPACE_YCBCR601_LIMITED) info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = COLORIMETRY_ITU601; - else + else { + if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB) + BREAK_TO_DEBUGGER(); info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = COLORIMETRY_NO_DATA; - + } if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || - color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || - color_space == COLOR_SPACE_2020_YCBCR) { + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || + color_space == COLOR_SPACE_2020_YCBCR) { info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = -- GitLab From cc4d99b8a888e16093b985d6a11fbd37ab92697c Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 1 Feb 2017 20:35:53 -0500 Subject: [PATCH 0239/2898] drm/amd/display: HDMI YCbCr422 12bpc pixel format issue Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 7 +++- .../gpu/drm/amd/display/dc/core/dc_resource.c | 30 ++++++++--------- .../drm/amd/display/dc/dce/dce_clock_source.c | 29 ++++++++--------- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 32 +++++++++++++++---- .../amd/display/dc/dce/dce_stream_encoder.c | 16 +++++++--- .../amd/display/dc/dce110/dce110_resource.c | 3 ++ .../gpu/drm/amd/display/dc/inc/clock_source.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 + 8 files changed, 76 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ec5de329b091..2b929393f68a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1267,6 +1267,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; struct core_link *link = stream->sink->link; + enum dc_color_depth display_color_depth; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( @@ -1277,10 +1278,14 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) memset(&stream->sink->link->public.cur_link_settings, 0, sizeof(struct dc_link_settings)); + display_color_depth = stream->public.timing.display_color_depth; + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + display_color_depth = COLOR_DEPTH_888; + link->link_enc->funcs->enable_tmds_output( link->link_enc, pipe_ctx->clock_source->id, - stream->public.timing.display_color_depth, + display_color_depth, pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A, pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK, stream->phy_pix_clk); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 3d8a85e48b05..856a33ad8ec1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1045,25 +1045,25 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) pix_clk /= 2; - - switch (timing->display_color_depth) { - case COLOR_DEPTH_888: - normalized_pix_clk = pix_clk; - break; - case COLOR_DEPTH_101010: - normalized_pix_clk = (pix_clk * 30) / 24; + if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + normalized_pix_clk = pix_clk; + break; + case COLOR_DEPTH_101010: + normalized_pix_clk = (pix_clk * 30) / 24; + break; + case COLOR_DEPTH_121212: + normalized_pix_clk = (pix_clk * 36) / 24; break; - case COLOR_DEPTH_121212: - normalized_pix_clk = (pix_clk * 36) / 24; + case COLOR_DEPTH_161616: + normalized_pix_clk = (pix_clk * 48) / 24; break; - case COLOR_DEPTH_161616: - normalized_pix_clk = (pix_clk * 48) / 24; - break; - default: - ASSERT(0); + default: + ASSERT(0); break; + } } - return normalized_pix_clk; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 78f43274a03a..a9f39218ce82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -390,25 +390,24 @@ static bool pll_adjust_pix_clk( struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = { 0 }; enum bp_result bp_result; - switch (pix_clk_params->signal_type) { case SIGNAL_TYPE_HDMI_TYPE_A: { requested_clk_khz = pix_clk_params->requested_pix_clk; - - switch (pix_clk_params->color_depth) { - case COLOR_DEPTH_101010: - requested_clk_khz = (requested_clk_khz * 5) >> 2; - break; /* x1.25*/ - case COLOR_DEPTH_121212: - requested_clk_khz = (requested_clk_khz * 6) >> 2; - break; /* x1.5*/ - case COLOR_DEPTH_161616: - requested_clk_khz = requested_clk_khz * 2; - break; /* x2.0*/ - default: - break; + if (pix_clk_params->pixel_encoding != PIXEL_ENCODING_YCBCR422) { + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_101010: + requested_clk_khz = (requested_clk_khz * 5) >> 2; + break; /* x1.25*/ + case COLOR_DEPTH_121212: + requested_clk_khz = (requested_clk_khz * 6) >> 2; + break; /* x1.5*/ + case COLOR_DEPTH_161616: + requested_clk_khz = requested_clk_khz * 2; + break; /* x2.0*/ + default: + break; + } } - actual_pix_clk_khz = requested_clk_khz; } break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 9247afd4d42f..a2f57cf603aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -366,19 +366,37 @@ static void set_truncation( FMT_TRUNCATE_EN, 0, FMT_TRUNCATE_DEPTH, 0, FMT_TRUNCATE_MODE, 0); - /* no 10bpc trunc on DCE11*/ + + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + /* 8bpc trunc on YCbCr422*/ + if (params->flags.TRUNCATE_DEPTH == 1) + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, 1, + FMT_TRUNCATE_MODE, 0); + else if (params->flags.TRUNCATE_DEPTH == 2) + /* 10bpc trunc on YCbCr422*/ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, 2, + FMT_TRUNCATE_MODE, 0); + return; + } + /* on other format-to do */ if (params->flags.TRUNCATE_ENABLED == 0 || - params->flags.TRUNCATE_DEPTH == 2) + params->flags.TRUNCATE_DEPTH == 2) return; - /*Set truncation depth and Enable truncation*/ REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, - FMT_TRUNCATE_EN, 1, - FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_MODE, - FMT_TRUNCATE_MODE, params->flags.TRUNCATE_DEPTH); - + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, + params->flags.TRUNCATE_MODE, + FMT_TRUNCATE_MODE, + params->flags.TRUNCATE_DEPTH); } + /** * set_spatial_dither * 1) set spatial dithering mode: pattern of seed diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 7e6661bda970..a28d9c7ba17e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -367,14 +367,20 @@ static void dce110_stream_encoder_hdmi_set_stream_attribute( HDMI_DEEP_COLOR_ENABLE, 1); break; case COLOR_DEPTH_121212: - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 2, - HDMI_DEEP_COLOR_ENABLE, 1); + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + } break; case COLOR_DEPTH_161616: REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 3, - HDMI_DEEP_COLOR_ENABLE, 1); + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8dc69be15182..4c108d0fb164 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -814,6 +814,9 @@ void dce110_resource_build_bit_depth_reduction_params( fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; + + fmt_bit_depth->pixel_encoding = + stream->public.timing.pixel_encoding; } return; diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h index c91c7815ec6e..47ef90495376 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h @@ -94,7 +94,7 @@ struct pixel_clk_params { enum dc_color_depth color_depth; struct csdp_ref_clk_ds_params de_spread_params; /*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/ - + enum dc_pixel_encoding pixel_encoding; struct pixel_clk_flags flags; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a10c4e296960..e01b831a7e7f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -86,6 +86,7 @@ struct bit_depth_reduction_params { uint32_t r_seed_value; uint32_t b_seed_value; uint32_t g_seed_value; + enum dc_pixel_encoding pixel_encoding; }; enum wide_gamut_regamma_mode { -- GitLab From ffbcd19a8856a63f4310c89b2af599409e3f2216 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Wed, 1 Feb 2017 12:54:15 -0600 Subject: [PATCH 0240/2898] drm/amd/display: Adding 10 bpcc video P010 format Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c | 5 +++++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 5 ++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c index 946379852b2a..ab8d1e931846 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c @@ -2534,6 +2534,8 @@ static void populate_initial_data( case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: data->bytes_per_pixel[num_displays + 4] = 4; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: @@ -2621,6 +2623,7 @@ static void populate_initial_data( } switch (pipe[i].surface->public.format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_RGB565: data->bytes_per_pixel[num_displays + 4] = 2; @@ -2630,6 +2633,8 @@ static void populate_initial_data( case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: data->bytes_per_pixel[num_displays + 4] = 4; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 856a33ad8ec1..e4e86110d45d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -358,11 +358,13 @@ static enum pixel_format convert_pixel_format_to_dalsurface( dal_pixel_format = PIXEL_FORMAT_FP16; break; case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - dal_pixel_format = PIXEL_FORMAT_420BPP12; - break; case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: dal_pixel_format = PIXEL_FORMAT_420BPP12; break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + dal_pixel_format = PIXEL_FORMAT_420BPP15; + break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: default: dal_pixel_format = PIXEL_FORMAT_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 21092f33c83b..75e16ac70f5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -195,6 +195,8 @@ enum surface_pixel_format { SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr = SURFACE_PIXEL_FORMAT_VIDEO_BEGIN, SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb, + SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr, + SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb, SURFACE_PIXEL_FORMAT_INVALID /*grow 444 video here if necessary */ @@ -212,13 +214,14 @@ enum pixel_format { PIXEL_FORMAT_FP16, /*video*/ PIXEL_FORMAT_420BPP12, + PIXEL_FORMAT_420BPP15, /*end of pixel format definition*/ PIXEL_FORMAT_INVALID, PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8, PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16, PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12, - PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP12, + PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP15, PIXEL_FORMAT_UNKNOWN }; -- GitLab From 94cd1f79b05994b712a2cf0563ac73be0323978b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 2 Feb 2017 15:21:45 -0500 Subject: [PATCH 0241/2898] drm/amd/display: Fixed color temperature corruption. Signed-off-by: Yongqiang Sun Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index b8735b27e9bc..dfe590198a33 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -65,7 +65,7 @@ struct pwl_result_data { }; struct pwl_params { - struct gamma_curve arr_curve_points[16]; + struct gamma_curve arr_curve_points[34]; struct curve_points arr_points[3]; struct pwl_result_data rgb_resulted[256 + 3]; uint32_t hw_points_num; -- GitLab From f7f3cfee084b0c68789e2b4231b0d3de3466a52b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 3 Feb 2017 11:45:43 -0500 Subject: [PATCH 0242/2898] drm/amd/display: fix crash with modesetting driver They might call commit with ACTION_NOTHING without a mode. We shouldn't crash but simply skip updating stream scaling settings since scaling obviously didn't change without a provided mode. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ad60a28975ca..fdb264c6e859 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -638,6 +638,10 @@ static void update_stream_scaling_settings( struct rect src = { 0 }; /* viewport in composition space*/ struct rect dst = { 0 }; /* stream addressable area */ + /* no mode. nothing to be done */ + if (!mode) + return; + /* Full screen scaling by default */ src.width = mode->hdisplay; src.height = mode->vdisplay; -- GitLab From a2b763cbd69e59854ed3ff9f79b7e8471748ea69 Mon Sep 17 00:00:00 2001 From: Krzysztof Nowicki Date: Fri, 27 Jan 2017 18:58:27 +0100 Subject: [PATCH 0243/2898] drm/amd/display: Fix MST physical ports always disconnected Remove a false assumption that a cached EDID will be present whenever the connector is in a connected state as this will only be true for logical MST ports. For physical ports the EDID will never be cached, which will cause them to always appear as disconnected. This reverts commit 4ff8a88888de271bfb7750b2a5c68163848e2bf1 Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index e4d94d4c215d..41988c89d471 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -127,14 +127,6 @@ dm_dp_mst_detect(struct drm_connector *connector, bool force) &master->mst_mgr, aconnector->port); - /* - * we do not want to make this connector connected until we have edid on - * it - */ - if (status == connector_status_connected && - !aconnector->port->cached_edid) - status = connector_status_disconnected; - return status; } -- GitLab From a99240d5f8e14fc081e2cccad6ac46b48cea7def Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 2 Feb 2017 17:08:19 -0500 Subject: [PATCH 0244/2898] drm/amd/display: use disp clock value in context rather than bw_results Signed-off-by: Dmytro Laktyushkin Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 ++++++-------- .../drm/amd/display/dc/dce100/dce100_resource.c | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 10 +++++----- .../drm/amd/display/dc/dce110/dce110_resource.c | 1 + .../drm/amd/display/dc/dce112/dce112_resource.c | 1 + .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9d2f78f21748..4c405f4b880e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -925,7 +925,7 @@ void pplib_apply_display_requirements( /* TODO: dce11.2*/ pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - pp_display_cfg->disp_clk_khz = context->bw_results.dispclk_khz; + pp_display_cfg->disp_clk_khz = context->dispclk_khz; fill_display_configs(context, pp_display_cfg); @@ -1065,8 +1065,7 @@ bool dc_pre_update_surfaces_to_stream( { int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); - int prev_disp_clk = core_dc->current_context->bw_results.dispclk_khz; - int new_disp_clk; + int prev_disp_clk = core_dc->current_context->dispclk_khz; struct dc_stream_status *stream_status = NULL; struct validate_context *context; struct validate_context *temp_context; @@ -1152,17 +1151,16 @@ bool dc_pre_update_surfaces_to_stream( ret = false; goto unexpected_fail; } - new_disp_clk = context->bw_results.dispclk_khz; if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) - && prev_disp_clk < new_disp_clk) { + && prev_disp_clk < context->dispclk_khz) { pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); context->res_ctx.pool->display_clock->funcs->set_clock( context->res_ctx.pool->display_clock, - new_disp_clk * 115 / 100); - core_dc->current_context->bw_results.dispclk_khz = new_disp_clk; - core_dc->current_context->dispclk_khz = new_disp_clk; + context->dispclk_khz * 115 / 100); + core_dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; + core_dc->current_context->dispclk_khz = context->dispclk_khz; } for (i = 0; i < new_surface_count; i++) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 800b22e70c7e..55501b381692 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -770,7 +770,7 @@ enum dc_status dce100_validate_bandwidth( struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ - context->bw_results.dispclk_khz = 681000; + context->dispclk_khz = 681000; return DC_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a1a5dc6fcb67..5e99f6c27c9a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1651,7 +1651,7 @@ static void apply_min_clocks( /* get the required state based on state dependent clocks: * display clock and pixel clock */ - req_clocks.display_clk_khz = context->bw_results.dispclk_khz; + req_clocks.display_clk_khz = context->dispclk_khz; req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( dc, context, true); @@ -1776,11 +1776,11 @@ enum dc_status dce110_apply_ctx_to_hw( /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); - if (context->bw_results.dispclk_khz - > dc->current_context->bw_results.dispclk_khz) + if (context->dispclk_khz + > dc->current_context->dispclk_khz) context->res_ctx.pool->display_clock->funcs->set_clock( context->res_ctx.pool->display_clock, - context->bw_results.dispclk_khz * 115 / 100); + context->dispclk_khz * 115 / 100); for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = @@ -2289,7 +2289,7 @@ static void dce110_set_bandwidth(struct core_dc *dc) dc->current_context->res_ctx.pool->display_clock->funcs->set_clock( dc->current_context->res_ctx.pool->display_clock, - dc->current_context->bw_results.dispclk_khz * 115 / 100); + dc->current_context->dispclk_khz * 115 / 100); } static void dce110_program_front_end_for_pipe( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 4c108d0fb164..ee4fda514de6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -926,6 +926,7 @@ enum dc_status dce110_validate_bandwidth( result = DC_FAIL_BANDWIDTH_VALIDATE; else result = DC_OK; + context->dispclk_khz = context->bw_results.dispclk_khz; if (result == DC_FAIL_BANDWIDTH_VALIDATE) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 7e99b2b96794..54af84ebf2bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -857,6 +857,7 @@ enum dc_status dce112_validate_bandwidth( result = DC_FAIL_BANDWIDTH_VALIDATE; else result = DC_OK; + context->dispclk_khz = context->bw_results.dispclk_khz; if (result == DC_FAIL_BANDWIDTH_VALIDATE) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index fea60aa5d297..3de8bfb47dce 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -785,7 +785,7 @@ enum dc_status dce80_validate_bandwidth( struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ - context->bw_results.dispclk_khz = 681000; + context->dispclk_khz = 681000; context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; return DC_OK; -- GitLab From 871ffb606a3eb9b29891b25228f569899bbd216c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 6 Feb 2017 15:07:19 -0500 Subject: [PATCH 0245/2898] drm/amd/display: fix psr status wait Signed-off-by: Dmytro Laktyushkin Reviewed-by: Eagle Yeh Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_link_encoder.c | 18 ++++++++++++--- .../drm/amd/display/dc/dce/dce_link_encoder.h | 22 +++++++++---------- drivers/gpu/drm/amd/display/dc/dm_services.h | 2 +- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 3847764688dd..60fdf58fc5cc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -38,6 +38,14 @@ #include "dce/dce_11_0_sh_mask.h" #include "dce/dce_11_0_enum.h" +#ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT +#define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT 0xa +#endif + +#ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK +#define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK 0x00000400L +#endif + #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK #define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L #endif @@ -1557,15 +1565,19 @@ static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) uint32_t count = 0; uint32_t psrStateOffset = 0xf0; - uint32_t value; + uint32_t value = -1; /* Enable write access to IRAM */ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); - do { + while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) { dm_delay_in_microseconds(ctx, 2); REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); - } while (value != 0 && count++ < 10); + } + while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) { + dm_delay_in_microseconds(ctx, 2); + REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value); + } /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 8a07665e693b..d382a6882d95 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -72,17 +72,17 @@ SRI(DP_DPHY_FAST_TRAINING, DP, id), \ SRI(DP_SEC_CNTL1, DP, id) - #define LE_COMMON_REG_LIST(id)\ - LE_COMMON_REG_LIST_BASE(id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) - - #define LE_DCE110_REG_LIST(id)\ - LE_COMMON_REG_LIST_BASE(id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) +#define LE_COMMON_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) + +#define LE_DCE110_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 052a43af1bd3..73c0f1f83999 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -103,7 +103,7 @@ static inline uint32_t dm_read_reg_func( uint32_t value; if (address == 0) { - DC_ERR("invalid register read. address = 0"); + DC_ERR("invalid register read; address = 0\n"); return 0; } -- GitLab From ab8812a3861efd3d60a4079711f2d1b08b8af50e Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 8 Feb 2017 11:28:33 -0500 Subject: [PATCH 0246/2898] drm/amd/display: Audio is not switching to DP when HDMI/DP hot plug/unplug Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 100 +++++++++++++----- 1 file changed, 75 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5e99f6c27c9a..6a5cec0d4e1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1732,7 +1732,6 @@ enum dc_status dce110_apply_ctx_to_hw( struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status status; int i; - bool programmed_audio_dto = false; enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID; /* Reset old context */ @@ -1782,6 +1781,80 @@ enum dc_status dce110_apply_ctx_to_hw( context->res_ctx.pool->display_clock, context->dispclk_khz * 115 / 100); + /* program audio wall clock. use HDMI as clock source if HDMI + * audio active. Otherwise, use DP as clock source + * first, loop to find any HDMI audio, if not, loop find DP audio + */ + /* Setup audio rate clock source */ + /* Issue: + * Audio lag happened on DP monitor when unplug a HDMI monitor + * + * Cause: + * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL + * is set to either dto0 or dto1, audio should work fine. + * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, + * set to dto0 will cause audio lag. + * + * Solution: + * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, + * find first available pipe with audio, setup audio wall DTO per topology + * instead of per pipe. + */ + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->top_pipe) + continue; + + if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) + continue; + + if (pipe_ctx->audio != NULL) { + struct audio_output audio_output; + + build_audio_output(pipe_ctx, &audio_output); + + pipe_ctx->audio->funcs->wall_dto_setup( + pipe_ctx->audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + break; + } + } + + /* no HDMI audio is found, try DP audio */ + if (i == context->res_ctx.pool->pipe_count) { + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == NULL) + continue; + + if (pipe_ctx->top_pipe) + continue; + + if (!dc_is_dp_signal(pipe_ctx->stream->signal)) + continue; + + if (pipe_ctx->audio != NULL) { + struct audio_output audio_output; + + build_audio_output(pipe_ctx, &audio_output); + + pipe_ctx->audio->funcs->wall_dto_setup( + pipe_ctx->audio, + pipe_ctx->stream->signal, + &audio_output.crtc_info, + &audio_output.pll_info); + break; + } + } + } + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; @@ -1797,21 +1870,7 @@ enum dc_status dce110_apply_ctx_to_hw( continue; if (context->res_ctx.pipe_ctx[i].audio != NULL) { - /* Setup audio rate clock source */ - /* Issue: - * Audio lag happened on DP monitor when unplug a HDMI monitor - * - * Cause: - * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL - * is set to either dto0 or dto1, audio should work fine. - * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, - * set to dto0 will cause audio lag. - * - * Solution: - * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, - * find first available pipe with audio, setup audio wall DTO per topology - * instead of per pipe. - */ + struct audio_output audio_output; build_audio_output(pipe_ctx, &audio_output); @@ -1833,15 +1892,6 @@ enum dc_status dce110_apply_ctx_to_hw( pipe_ctx->stream->signal, &audio_output.crtc_info, &pipe_ctx->stream->public.audio_info); - - if (!programmed_audio_dto) { - pipe_ctx->audio->funcs->wall_dto_setup( - pipe_ctx->audio, - pipe_ctx->stream->signal, - &audio_output.crtc_info, - &audio_output.pll_info); - programmed_audio_dto = true; - } } status = apply_single_controller_ctx_to_hw( -- GitLab From 67c3bd40b3b97cac40e01aaef712ccf4af5a48b1 Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Fri, 3 Feb 2017 14:19:41 -0500 Subject: [PATCH 0247/2898] drm/amd/display: handle unsupported sink types Signed-off-by: Reza Amini Reviewed-by: Wesley Chalmers Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 9dff0bfd5b23..0a805ea1159a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -53,6 +53,10 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa struct core_link *core_link = DC_LINK_TO_LINK(init_params->link); + if (!core_link) { + return false; + } + sink->protected.public.sink_signal = init_params->sink_signal; sink->protected.link = core_link; sink->protected.ctx = core_link->ctx; -- GitLab From e266fdf6944749e100b065b5a95c7bb33d2aa2d6 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Tue, 7 Feb 2017 10:41:37 -0600 Subject: [PATCH 0248/2898] drm/amd/display: Enable regamma 25 segments and use double buffer. Moved custom floating point calculation to the shared place between dce's. Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 +- .../drm/amd/display/dc/calcs/custom_float.c | 197 ++++++++++++++++++ .../display/dc/dce110/dce110_hw_sequencer.c | 171 +-------------- .../display/dc/dce110/dce110_hw_sequencer.h | 3 - .../gpu/drm/amd/display/dc/inc/custom_float.h | 40 ++++ 5 files changed, 240 insertions(+), 173 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/custom_float.c create mode 100644 drivers/gpu/drm/amd/display/dc/inc/custom_float.h diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 4bb08aea6a03..2f4c8e771b8f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,7 +3,7 @@ # It calculates Bandwidth and Watermarks values for HW programming # -BW_CALCS = bandwidth_calcs.o bw_fixed.o +BW_CALCS = bandwidth_calcs.o bw_fixed.o custom_float.o AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/custom_float.c b/drivers/gpu/drm/amd/display/dc/calcs/custom_float.c new file mode 100644 index 000000000000..7243c37f569e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/custom_float.c @@ -0,0 +1,197 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "custom_float.h" + + +static bool build_custom_float( + struct fixed31_32 value, + const struct custom_float_format *format, + bool *negative, + uint32_t *mantissa, + uint32_t *exponenta) +{ + uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; + + const struct fixed31_32 mantissa_constant_plus_max_fraction = + dal_fixed31_32_from_fraction( + (1LL << (format->mantissa_bits + 1)) - 1, + 1LL << format->mantissa_bits); + + struct fixed31_32 mantiss; + + if (dal_fixed31_32_eq( + value, + dal_fixed31_32_zero)) { + *negative = false; + *mantissa = 0; + *exponenta = 0; + return true; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_zero)) { + *negative = format->sign; + value = dal_fixed31_32_neg(value); + } else { + *negative = false; + } + + if (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shl(value, 1); + ++i; + } while (dal_fixed31_32_lt( + value, + dal_fixed31_32_one)); + + --i; + + if (exp_offset <= i) { + *mantissa = 0; + *exponenta = 0; + return true; + } + + *exponenta = exp_offset - i; + } else if (dal_fixed31_32_le( + mantissa_constant_plus_max_fraction, + value)) { + uint32_t i = 1; + + do { + value = dal_fixed31_32_shr(value, 1); + ++i; + } while (dal_fixed31_32_lt( + mantissa_constant_plus_max_fraction, + value)); + + *exponenta = exp_offset + i - 1; + } else { + *exponenta = exp_offset; + } + + mantiss = dal_fixed31_32_sub( + value, + dal_fixed31_32_one); + + if (dal_fixed31_32_lt( + mantiss, + dal_fixed31_32_zero) || + dal_fixed31_32_lt( + dal_fixed31_32_one, + mantiss)) + mantiss = dal_fixed31_32_zero; + else + mantiss = dal_fixed31_32_shl( + mantiss, + format->mantissa_bits); + + *mantissa = dal_fixed31_32_floor(mantiss); + + return true; +} + +static bool setup_custom_float( + const struct custom_float_format *format, + bool negative, + uint32_t mantissa, + uint32_t exponenta, + uint32_t *result) +{ + uint32_t i = 0; + uint32_t j = 0; + + uint32_t value = 0; + + /* verification code: + * once calculation is ok we can remove it + */ + + const uint32_t mantissa_mask = + (1 << (format->mantissa_bits + 1)) - 1; + + const uint32_t exponenta_mask = + (1 << (format->exponenta_bits + 1)) - 1; + + if (mantissa & ~mantissa_mask) { + BREAK_TO_DEBUGGER(); + mantissa = mantissa_mask; + } + + if (exponenta & ~exponenta_mask) { + BREAK_TO_DEBUGGER(); + exponenta = exponenta_mask; + } + + /* end of verification code */ + + while (i < format->mantissa_bits) { + uint32_t mask = 1 << i; + + if (mantissa & mask) + value |= mask; + + ++i; + } + + while (j < format->exponenta_bits) { + uint32_t mask = 1 << j; + + if (exponenta & mask) + value |= mask << i; + + ++j; + } + + if (negative && format->sign) + value |= 1 << (i + j); + + *result = value; + + return true; +} + +bool convert_to_custom_float_format( + struct fixed31_32 value, + const struct custom_float_format *format, + uint32_t *result) +{ + uint32_t mantissa; + uint32_t exponenta; + bool negative; + + return build_custom_float( + value, format, &negative, &mantissa, &exponenta) && + setup_custom_float( + format, negative, mantissa, exponenta, result); +} + + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6a5cec0d4e1f..88a2fa99f5da 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -49,6 +49,7 @@ /* include DCE11 register header files */ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" +#include "custom_float.h" struct dce110_hw_seq_reg_offsets { uint32_t crtc; @@ -286,174 +287,6 @@ static bool dce110_set_input_transfer_func( return result; } -static bool build_custom_float( - struct fixed31_32 value, - const struct custom_float_format *format, - bool *negative, - uint32_t *mantissa, - uint32_t *exponenta) -{ - uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; - - const struct fixed31_32 mantissa_constant_plus_max_fraction = - dal_fixed31_32_from_fraction( - (1LL << (format->mantissa_bits + 1)) - 1, - 1LL << format->mantissa_bits); - - struct fixed31_32 mantiss; - - if (dal_fixed31_32_eq( - value, - dal_fixed31_32_zero)) { - *negative = false; - *mantissa = 0; - *exponenta = 0; - return true; - } - - if (dal_fixed31_32_lt( - value, - dal_fixed31_32_zero)) { - *negative = format->sign; - value = dal_fixed31_32_neg(value); - } else { - *negative = false; - } - - if (dal_fixed31_32_lt( - value, - dal_fixed31_32_one)) { - uint32_t i = 1; - - do { - value = dal_fixed31_32_shl(value, 1); - ++i; - } while (dal_fixed31_32_lt( - value, - dal_fixed31_32_one)); - - --i; - - if (exp_offset <= i) { - *mantissa = 0; - *exponenta = 0; - return true; - } - - *exponenta = exp_offset - i; - } else if (dal_fixed31_32_le( - mantissa_constant_plus_max_fraction, - value)) { - uint32_t i = 1; - - do { - value = dal_fixed31_32_shr(value, 1); - ++i; - } while (dal_fixed31_32_lt( - mantissa_constant_plus_max_fraction, - value)); - - *exponenta = exp_offset + i - 1; - } else { - *exponenta = exp_offset; - } - - mantiss = dal_fixed31_32_sub( - value, - dal_fixed31_32_one); - - if (dal_fixed31_32_lt( - mantiss, - dal_fixed31_32_zero) || - dal_fixed31_32_lt( - dal_fixed31_32_one, - mantiss)) - mantiss = dal_fixed31_32_zero; - else - mantiss = dal_fixed31_32_shl( - mantiss, - format->mantissa_bits); - - *mantissa = dal_fixed31_32_floor(mantiss); - - return true; -} - -static bool setup_custom_float( - const struct custom_float_format *format, - bool negative, - uint32_t mantissa, - uint32_t exponenta, - uint32_t *result) -{ - uint32_t i = 0; - uint32_t j = 0; - - uint32_t value = 0; - - /* verification code: - * once calculation is ok we can remove it - */ - - const uint32_t mantissa_mask = - (1 << (format->mantissa_bits + 1)) - 1; - - const uint32_t exponenta_mask = - (1 << (format->exponenta_bits + 1)) - 1; - - if (mantissa & ~mantissa_mask) { - BREAK_TO_DEBUGGER(); - mantissa = mantissa_mask; - } - - if (exponenta & ~exponenta_mask) { - BREAK_TO_DEBUGGER(); - exponenta = exponenta_mask; - } - - /* end of verification code */ - - while (i < format->mantissa_bits) { - uint32_t mask = 1 << i; - - if (mantissa & mask) - value |= mask; - - ++i; - } - - while (j < format->exponenta_bits) { - uint32_t mask = 1 << j; - - if (exponenta & mask) - value |= mask << i; - - ++j; - } - - if (negative && format->sign) - value |= 1 << (i + j); - - *result = value; - - return true; -} - -static bool convert_to_custom_float_format( - struct fixed31_32 value, - const struct custom_float_format *format, - uint32_t *result) -{ - uint32_t mantissa; - uint32_t exponenta; - bool negative; - - return build_custom_float( - value, format, &negative, &mantissa, &exponenta) && - setup_custom_float( - format, negative, mantissa, exponenta, result); -} - static bool convert_to_custom_float( struct pwl_result_data *rgb_resulted, struct curve_points *arr_points, @@ -579,7 +412,7 @@ static bool convert_to_custom_float( return true; } -bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func +static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, struct pwl_params *regamma_params) { struct curve_points *arr_points; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 68632dd28155..a6b4d0d2429f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -58,8 +58,5 @@ void dce110_power_down(struct core_dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); -bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func - *output_tf, struct pwl_params *regamma_params); - #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/custom_float.h b/drivers/gpu/drm/amd/display/dc/inc/custom_float.h new file mode 100644 index 000000000000..f57239672216 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/custom_float.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef CUSTOM_FLOAT_H_ +#define CUSTOM_FLOAT_H_ + +#include "bw_fixed.h" +#include "hw_shared.h" +#include "opp.h" + + +bool convert_to_custom_float_format( + struct fixed31_32 value, + const struct custom_float_format *format, + uint32_t *result); + + +#endif //CUSTOM_FLOAT_H_ -- GitLab From 8f16f28936afcf68b92625d331a8ca760a386139 Mon Sep 17 00:00:00 2001 From: Sylvia Tsai Date: Thu, 9 Feb 2017 16:35:39 -0500 Subject: [PATCH 0249/2898] drm/amd/display: Set ignore_msa_timing flag for freesync modes - Set ignore_msa_timing_param to 1 only for modes that can support freesync Signed-off-by: Sylvia Tsai Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 1ee732768f6e..b00b1df71f3e 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -262,7 +262,11 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, enable_for_video = false; } - if (caps->supported) + unsigned int nom_refresh_rate_micro_hz = (unsigned int) + (((unsigned long long) core_stream->public.timing.pix_clk_khz) * 1000ULL * 1000ULL * 1000ULL + / core_stream->public.timing.h_total / core_stream->public.timing.v_total); + + if (caps->supported && nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) core_stream->public.ignore_msa_timing_param = 1; core_freesync->num_entities++; -- GitLab From 27e947b0e13835cb782aa267b7d77e1f5a028e87 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 10 Feb 2017 11:59:31 -0500 Subject: [PATCH 0250/2898] drm/amd/display: Fix program pix clk logic to unblock deep color set. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index a9f39218ce82..87eba4be3249 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -854,16 +854,16 @@ static bool dce110_program_pix_clk( if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( pix_clk_params->signal_type)) { - if (!enable_spread_spectrum(clk_src, pix_clk_params->signal_type, pll_settings)) return false; - /* Resync deep color DTO */ - dce110_program_pixel_clk_resync(clk_src, - pix_clk_params->signal_type, - pix_clk_params->color_depth); } + /* Resync deep color DTO */ + dce110_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth); + break; case DCE_VERSION_11_2: if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { -- GitLab From a37656b99aca947967f32931bfd5ba04133154d8 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 8 Feb 2017 22:13:52 -0500 Subject: [PATCH 0251/2898] drm/amd/display: report cursor size base on the ASIC Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 1 + 5 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d7f848495d8a..13e7134fccb8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,6 +47,8 @@ struct dc_caps { uint32_t max_slave_planes; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; + + unsigned int max_cursor_size; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 55501b381692..9ed7c06132fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -984,6 +984,7 @@ static bool construct( pool->base.pipe_count = res_cap.num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 40; + dc->public.caps.max_cursor_size = 128; for (i = 0; i < pool->base.pipe_count; i++) { pool->base.timing_generators[i] = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index ee4fda514de6..f6e546addbd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1274,6 +1274,7 @@ static bool construct( dc->public.caps.max_downscale_ratio = 150; dc->public.caps.i2c_speed_in_khz = 100; + dc->public.caps.max_cursor_size = 128; /************************************************* * Create resources * diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 54af84ebf2bc..526c106f6ebf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1256,6 +1256,7 @@ static bool construct( pool->base.pipe_count = pool->base.res_cap->num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 100; + dc->public.caps.max_cursor_size = 128; /************************************************* * Create resources * diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 3de8bfb47dce..272c7fc31406 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -935,6 +935,7 @@ static bool construct( pool->base.pipe_count = res_cap.num_timing_generator; dc->public.caps.max_downscale_ratio = 200; dc->public.caps.i2c_speed_in_khz = 40; + dc->public.caps.max_cursor_size = 128; /************************************************* * Create resources * -- GitLab From b3c64dff24e829c0b61b340fbaf0efaf20ce5d58 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 10 Feb 2017 17:51:27 -0500 Subject: [PATCH 0252/2898] drm/amd/display: color distortion after DPMS+ background color fix Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 88a2fa99f5da..0afb3c64b651 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1054,6 +1054,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (!pipe_ctx_old->stream) { core_link_enable_stream(pipe_ctx); + resource_build_info_frame(pipe_ctx); + dce110_update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) dce110_unblank_stream(pipe_ctx, &stream->sink->link->public.cur_link_settings); -- GitLab From 77f36b27127630f326d6967318159e938a4137dd Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 13 Feb 2017 11:49:07 -0500 Subject: [PATCH 0253/2898] drm/amd/display: Fix logic that causes segfault on DP display. Signed-off-by: Zeyu Fan Acked-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_clock_source.c | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 87eba4be3249..26742e038274 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -852,17 +852,19 @@ static bool dce110_program_pix_clk( * during PLL Reset, but they do not have effect * until SS_EN is asserted.*/ if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL - && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( - pix_clk_params->signal_type)) { - if (!enable_spread_spectrum(clk_src, - pix_clk_params->signal_type, - pll_settings)) - return false; + && !dc_is_dp_signal(pix_clk_params->signal_type)) { + + if (pix_clk_params->flags.ENABLE_SS) + if (!enable_spread_spectrum(clk_src, + pix_clk_params->signal_type, + pll_settings)) + return false; + + /* Resync deep color DTO */ + dce110_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth); } - /* Resync deep color DTO */ - dce110_program_pixel_clk_resync(clk_src, - pix_clk_params->signal_type, - pix_clk_params->color_depth); break; case DCE_VERSION_11_2: -- GitLab From 26ada804d62e5aedf16be8dfe2cb9bf4907815e5 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Tue, 14 Feb 2017 15:03:04 -0500 Subject: [PATCH 0254/2898] drm/amd/display: Fix missing fcn pointer on DCE8 Signed-off-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index e8fae0a7eeb4..eeccabd65a7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -141,12 +141,14 @@ static const struct timing_generator_funcs dce80_tg_funcs = { .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, .tear_down_global_swap_lock = dce110_timing_generator_tear_down_global_swap_lock, + .set_drr = dce110_timing_generator_set_drr, + .set_static_screen_control = + dce110_timing_generator_set_static_screen_control, + .set_test_pattern = dce110_timing_generator_set_test_pattern, /* DCE8.0 overrides */ .enable_advanced_request = dce80_timing_generator_enable_advanced_request, - .set_drr = - dce110_timing_generator_set_drr, }; bool dce80_timing_generator_construct( -- GitLab From 5866e7cf7d4f989cc17a781b8c4315345bc6de04 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Feb 2017 07:13:04 +0100 Subject: [PATCH 0255/2898] drm/amd/dc: fix semicolon.cocci warnings Remove unneeded semicolons. Generated by: scripts/coccinelle/misc/semicolon.cocci Signed-off-by: Julia Lawall Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index fdb264c6e859..dc0d8533521f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -938,11 +938,11 @@ static void copy_crtc_timing_for_drm_display_mode( dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; dst_mode->crtc_htotal = src_mode->crtc_htotal; dst_mode->crtc_hskew = src_mode->crtc_hskew; - dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start;; - dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end;; - dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start;; - dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end;; - dst_mode->crtc_vtotal = src_mode->crtc_vtotal;; + dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start; + dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end; + dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start; + dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end; + dst_mode->crtc_vtotal = src_mode->crtc_vtotal; } static void decide_crtc_timing_for_drm_display_mode( -- GitLab From 17a96033dae7e56cd48d1b3c952e0b4ca9384312 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Feb 2017 07:14:58 +0100 Subject: [PATCH 0256/2898] drm/amd/dc: fix semicolon.cocci warnings Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Signed-off-by: Julia Lawall Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e4e86110d45d..991828f503aa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -135,7 +135,7 @@ static void update_num_audio( break; default: DC_ERR("DC: unexpected audio fuse!\n"); - }; + } } bool resource_construct( -- GitLab From e166ad43d5c1312f258ef4adabe1fac2b9da7e18 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Feb 2017 07:19:36 +0100 Subject: [PATCH 0257/2898] drm/amd/dc: hw_sequencer: fix semicolon.cocci warnings Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Signed-off-by: Julia Lawall Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0afb3c64b651..9b6d251a1c22 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2070,7 +2070,7 @@ static void init_hw(struct core_dc *dc) true); } - dce_clock_gating_power_up(dc->hwseq, false);; + dce_clock_gating_power_up(dc->hwseq, false); /***************************************/ for (i = 0; i < dc->link_count; i++) { -- GitLab From 4a9054dda6df8e94b6a54a181277e25d189198c4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 14 Feb 2017 14:51:06 -0500 Subject: [PATCH 0258/2898] drm/amd/display: Fix 64-bit division, yet again Also make the code somewhat more readable. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index b00b1df71f3e..2026ef34b11b 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -210,6 +210,8 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; struct persistent_data_flag flag; + unsigned int nom_refresh_rate_micro_hz; + unsigned long long temp; if (mod_freesync == NULL) return false; @@ -262,11 +264,16 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, enable_for_video = false; } - unsigned int nom_refresh_rate_micro_hz = (unsigned int) - (((unsigned long long) core_stream->public.timing.pix_clk_khz) * 1000ULL * 1000ULL * 1000ULL - / core_stream->public.timing.h_total / core_stream->public.timing.v_total); + temp = core_stream->public.timing.pix_clk_khz; + temp *= 1000ULL * 1000ULL * 1000ULL; + temp = div_u64(temp, core_stream->public.timing.h_total); + temp = div_u64(temp, core_stream->public.timing.v_total); - if (caps->supported && nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) + nom_refresh_rate_micro_hz = (unsigned int) temp; + + if (caps->supported && + nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && + nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) core_stream->public.ignore_msa_timing_param = 1; core_freesync->num_entities++; -- GitLab From beed42b5bc68e9c37c4474393a2e3dbf6ed4c26b Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Tue, 14 Feb 2017 18:20:35 -0500 Subject: [PATCH 0259/2898] drm/amd/display: Don't attempt to program missing register fields on DCE8 When moving to a common dce/ infrastructure for all asics, some register fields do not exist in DCE8, and cause ASSERTS and debug spam. Instead, check to see whether a register field mask is valid before attempting to program the register field Signed-off-by: Jordan Lazare Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 29 ++++++++++++------- .../drm/amd/display/dc/dce/dce_transform.c | 12 ++++++-- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 0eee135bfa54..8eb755620c48 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -69,17 +69,22 @@ void dce_pipe_control_lock(struct dce_hwseq *hws, if (control_mask & PIPE_LOCK_CONTROL_MODE) update_lock_mode = lock_val; - REG_SET_4(BLND_V_UPDATE_LOCK[blnd_inst], val, + + REG_SET_2(BLND_V_UPDATE_LOCK[blnd_inst], val, BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, - BLND_SCL_V_UPDATE_LOCK, scl, - BLND_BLND_V_UPDATE_LOCK, blnd, - BLND_V_UPDATE_LOCK_MODE, update_lock_mode); + BLND_SCL_V_UPDATE_LOCK, scl); + + if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0) + REG_SET_2(BLND_V_UPDATE_LOCK[blnd_inst], val, + BLND_BLND_V_UPDATE_LOCK, blnd, + BLND_V_UPDATE_LOCK_MODE, update_lock_mode); - if (hws->wa.blnd_crtc_trigger) + if (hws->wa.blnd_crtc_trigger) { if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) { uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]); REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value); } + } } void dce_set_blender_mode(struct dce_hwseq *hws, @@ -111,11 +116,15 @@ void dce_set_blender_mode(struct dce_hwseq *hws, break; } - REG_UPDATE_4(BLND_CONTROL[blnd_inst], - BLND_FEEDTHROUGH_EN, feedthrough, - BLND_ALPHA_MODE, alpha_mode, - BLND_MODE, blnd_mode, - BLND_MULTIPLIED_MODE, multiplied_mode); + REG_UPDATE(BLND_CONTROL[blnd_inst], + BLND_MODE, blnd_mode); + + if (hws->masks->BLND_ALPHA_MODE != 0) { + REG_UPDATE_3(BLND_CONTROL[blnd_inst], + BLND_FEEDTHROUGH_EN, feedthrough, + BLND_ALPHA_MODE, alpha_mode, + BLND_MULTIPLIED_MODE, multiplied_mode); + } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index 50a6a25561b4..d8ffbff9a268 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -87,7 +87,10 @@ static bool setup_scaling_configuration( if (data->taps.h_taps + data->taps.v_taps <= 2) { /* Set bypass */ - REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); + if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0) + REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); + else + REG_UPDATE(SCL_MODE, SCL_MODE, 0); return false; } @@ -96,9 +99,12 @@ static bool setup_scaling_configuration( SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1); if (data->format <= PIXEL_FORMAT_GRPH_END) - REG_UPDATE_2(SCL_MODE, SCL_MODE, 1, SCL_PSCL_EN, 1); + REG_UPDATE(SCL_MODE, SCL_MODE, 1); else - REG_UPDATE_2(SCL_MODE, SCL_MODE, 2, SCL_PSCL_EN, 1); + REG_UPDATE(SCL_MODE, SCL_MODE, 2); + + if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0) + REG_UPDATE(SCL_MODE, SCL_PSCL_EN, 1); /* 1 - Replace out of bound pixels with edge */ REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1); -- GitLab From 7d4e9bf9835ad081fb5967336cace7f5aa8ffd6d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 21 Feb 2017 17:09:34 -0500 Subject: [PATCH 0260/2898] drm/amd/display: Remove LINUX_VERSION_CODE check Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0c50433d6ba3..d0706e550e84 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -886,14 +886,12 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector) process_count++; DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) /* handle HPD short pulse irq */ if (aconnector->mst_mgr.mst_state) drm_dp_mst_hpd_irq( &aconnector->mst_mgr, esi, &new_irq_handled); -#endif if (new_irq_handled) { /* ACK at DPCD to notify down stream */ -- GitLab From 5c1879b6b93898d65e05dfb47f947fa4f5a904a4 Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Mon, 13 Feb 2017 11:07:33 -0500 Subject: [PATCH 0261/2898] drm/amd/display: fix dc_commit_surfaces_to_stream for dcc Signed-off-by: Ken Chalmers Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4c405f4b880e..84412e752017 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1246,6 +1246,7 @@ bool dc_commit_surfaces_to_stream( plane_info[i].stereo_format = new_surfaces[i]->stereo_format; plane_info[i].tiling_info = new_surfaces[i]->tiling_info; plane_info[i].visible = new_surfaces[i]->visible; + plane_info[i].dcc = new_surfaces[i]->dcc; scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; scaling_info[i].src_rect = new_surfaces[i]->src_rect; scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; -- GitLab From 70063a5957126087f167ff3890784d7b3b36c844 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Thu, 16 Feb 2017 11:04:48 -0500 Subject: [PATCH 0262/2898] drm/amd/display: Add bypass case for PQ transfer function - Source and destination color space should be the same for app control case - Bypass degamma, regamma, and gamut remap - Add hdr supported check for info frame Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 991828f503aa..4d556b379524 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1675,7 +1675,7 @@ static void set_hdr_static_info_packet( hdr_metadata = surface->public.hdr_static_ctx; - if (!hdr_metadata.is_hdr) + if (!hdr_metadata.hdr_supported) return; if (dc_is_hdmi_signal(signal)) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 13e7134fccb8..71d7dde79ae0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -186,6 +186,7 @@ enum { }; struct dc_hdr_static_metadata { + bool hdr_supported; bool is_hdr; /* display chromaticities and white point in units of 0.00001 */ @@ -207,6 +208,7 @@ struct dc_hdr_static_metadata { enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, + TF_TYPE_BYPASS }; struct dc_transfer_func_distributed_points { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9b6d251a1c22..9c9183f96e04 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -279,6 +279,8 @@ static bool dce110_set_input_transfer_func( result = false; break; } + } else if (tf->public.type == TF_TYPE_BYPASS) { + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ result = false; @@ -428,7 +430,8 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func int32_t segment_start, segment_end; uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points; - if (output_tf == NULL || regamma_params == NULL) + if (output_tf == NULL || regamma_params == NULL || + output_tf->type == TF_TYPE_BYPASS) return false; arr_points = regamma_params->arr_points; -- GitLab From 2b230ea3e76f6238b31fd270cab76d55394f3293 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Thu, 16 Feb 2017 16:15:30 -0500 Subject: [PATCH 0263/2898] drm/amd/display: Add query_ddc_data function Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 25 ++++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 11 ++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 84412e752017..6516c275e0c7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1725,6 +1725,31 @@ bool dc_read_dpcd( return r == DDC_RESULT_SUCESSFULL; } +bool dc_query_ddc_data( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size) { + + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + + bool result = dal_ddc_service_query_ddc_data( + link->ddc, + address, + write_buf, + write_size, + read_buf, + read_size); + + return result; +} + + bool dc_write_dpcd( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 71d7dde79ae0..2d84b18f48b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -720,7 +720,16 @@ bool dc_write_dpcd( uint32_t link_index, uint32_t address, const uint8_t *data, - uint32_t size); + uint32_t size); + +bool dc_query_ddc_data( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size); bool dc_submit_i2c( struct dc *dc, -- GitLab From 185189dc51a5c968ce35b0e1f2b529736e789c9c Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Thu, 16 Feb 2017 18:34:50 -0500 Subject: [PATCH 0264/2898] drm/amd/display: Fix error where wrong payload size is given. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index cd66941b2c59..4e9465b630d1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -198,7 +198,7 @@ struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_ return NULL; if (dal_vector_construct( - &payloads->payloads, ctx, count, sizeof(struct aux_payloads))) + &payloads->payloads, ctx, count, sizeof(struct aux_payload))) return payloads; dm_free(payloads); -- GitLab From 87b58768eccd311fdc7694c09966754d5ce90538 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 16 Feb 2017 22:28:46 -0500 Subject: [PATCH 0265/2898] drm/amd/display: audio bug fix part 1: Add missing audio ACR Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_audio.c | 8 +- .../gpu/drm/amd/display/dc/dce/dce_audio.h | 2 + .../drm/amd/display/dc/dce/dce_link_encoder.c | 2 + .../amd/display/dc/dce/dce_stream_encoder.c | 81 +++++++++++++------ .../display/dc/dce110/dce110_hw_sequencer.c | 31 +++++++ .../amd/display/dc/dce110/dce110_resource.c | 1 + 6 files changed, 95 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 2749c8fa4f1f..596e039ee315 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -828,11 +828,9 @@ void dce_aud_wall_dto_setup( REG_UPDATE(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase); - /* DAL2 code separate DCCG_AUDIO_DTO_SEL and - DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different - location. merge together should not hurt */ - /*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1; - dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/ + REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1); + } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index c244887ba15e..b98ee2d2a9c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -93,6 +93,7 @@ struct dce_audio_shift { uint8_t DCCG_AUDIO_DTO0_PHASE; uint8_t DCCG_AUDIO_DTO1_MODULE; uint8_t DCCG_AUDIO_DTO1_PHASE; + uint8_t DCCG_AUDIO_DTO2_USE_512FBR_DTO; }; struct dce_aduio_mask { @@ -109,6 +110,7 @@ struct dce_aduio_mask { uint32_t DCCG_AUDIO_DTO0_PHASE; uint32_t DCCG_AUDIO_DTO1_MODULE; uint32_t DCCG_AUDIO_DTO1_PHASE; + uint32_t DCCG_AUDIO_DTO2_USE_512FBR_DTO; }; struct dce_audio { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 60fdf58fc5cc..305a9d86a5d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -871,6 +871,8 @@ static bool dce110_link_encoder_validate_hdmi_output( if (max_deep_color < crtc_timing->display_color_depth) return false; + if (crtc_timing->display_color_depth < COLOR_DEPTH_888) + return false; if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index a28d9c7ba17e..aba392ff5095 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -848,7 +848,7 @@ struct audio_clock_info { /* 148.5MHz/1.001*/ /* 148.5MHz*/ -static const struct audio_clock_info audio_clock_info_table[12] = { +static const struct audio_clock_info audio_clock_info_table[16] = { {2517, 4576, 28125, 7007, 31250, 6864, 28125}, {2518, 4576, 28125, 7007, 31250, 6864, 28125}, {2520, 4096, 25200, 6272, 28000, 6144, 25200}, @@ -860,37 +860,63 @@ static const struct audio_clock_info audio_clock_info_table[12] = { {7417, 11648, 210937, 17836, 234375, 11648, 140625}, {7425, 4096, 74250, 6272, 82500, 6144, 74250}, {14835, 11648, 421875, 8918, 234375, 5824, 140625}, - {14850, 4096, 148500, 6272, 165000, 6144, 148500} + {14850, 4096, 148500, 6272, 165000, 6144, 148500}, + {29670, 5824, 421875, 4459, 234375, 5824, 281250}, + {29700, 3072, 222750, 4704, 247500, 5120, 247500}, + {59340, 5824, 843750, 8918, 937500, 5824, 562500}, + {59400, 3072, 445500, 9408, 990000, 6144, 594000} }; -static const struct audio_clock_info audio_clock_info_table_36bpc[12] = { - {2517, 9152, 84375, 7007, 48875, 9152, 56250}, - {2518, 9152, 84375, 7007, 48875, 9152, 56250}, - {2520, 4096, 37800, 6272, 42000, 6144, 37800}, - {2700, 4096, 40500, 6272, 45000, 6144, 40500}, - {2702, 8192, 81081, 6272, 45045, 8192, 54054}, - {2703, 8192, 81081, 6272, 45045, 8192, 54054}, - {5400, 4096, 81000, 6272, 90000, 6144, 81000}, - {5405, 4096, 81081, 6272, 90090, 6144, 81081}, +static const struct audio_clock_info audio_clock_info_table_30bpc[14] = { + {2517, 9152, 70312, 14014, 78125, 9152, 46875}, + {2518, 9152, 70312, 14014, 78125, 9152, 46875}, + {2520, 4096, 31500, 6272, 35000, 6144, 31500}, + {2700, 4096, 33750, 6272, 37500, 6144, 33750}, + {2702, 8192, 67567, 12544, 75075, 8192, 45045}, + {2703, 8192, 67567, 12544, 75075, 8192, 45045}, + {5400, 4096, 67500, 6272, 75000, 6144, 67500}, + {5405, 8192, 135135, 6272, 75075, 8192, 90090}, + {7417, 11648, 263672, 17836, 292969, 11648, 175181}, + {7425, 8192, 185625, 6272, 103125, 12288, 185625}, + {14835, 11648, 527344, 17836, 585938, 11648, 351563}, + {14850, 4096, 185625, 6272, 206250, 6144, 185625}, + {29670, 11648, 527344, 17836, 585938, 11648, 703125}, + {29700, 6144, 556875, 4704, 309375, 5120, 309375} +}; +static const struct audio_clock_info audio_clock_info_table_36bpc[14] = { + {2517, 9152, 84375, 7007, 48875, 9152, 56250}, + {2518, 9152, 84375, 7007, 48875, 9152, 56250}, + {2520, 4096, 37800, 6272, 42000, 6144, 37800}, + {2700, 4096, 40500, 6272, 45000, 6144, 40500}, + {2702, 8192, 81081, 6272, 45045, 8192, 54054}, + {2703, 8192, 81081, 6272, 45045, 8192, 54054}, + {5400, 4096, 81000, 6272, 90000, 6144, 81000}, + {5405, 4096, 81081, 6272, 90090, 6144, 81081}, {7417, 11648, 316406, 17836, 351562, 11648, 210937}, - {7425, 4096, 111375, 6272, 123750, 6144, 111375}, + {7425, 4096, 111375, 6272, 123750, 6144, 111375}, {14835, 11648, 632812, 17836, 703125, 11648, 421875}, - {14850, 4096, 222750, 6272, 247500, 6144, 222750} + {14850, 4096, 222750, 6272, 247500, 6144, 222750}, + {29670, 5824, 632812, 8918, 703125, 5824, 421875}, + {29700, 4096, 445500, 4704, 371250, 5120, 371250} }; -static const struct audio_clock_info audio_clock_info_table_48bpc[12] = { - {2517, 4576, 56250, 7007, 62500, 6864, 56250}, - {2518, 4576, 56250, 7007, 62500, 6864, 56250}, - {2520, 4096, 50400, 6272, 56000, 6144, 50400}, - {2700, 4096, 54000, 6272, 60000, 6144, 54000}, - {2702, 4096, 54054, 6267, 60060, 8192, 54054}, - {2703, 4096, 54054, 6272, 60060, 8192, 54054}, - {5400, 4096, 108000, 6272, 120000, 6144, 108000}, - {5405, 4096, 108108, 6272, 120120, 6144, 108108}, +static const struct audio_clock_info audio_clock_info_table_48bpc[14] = { + {2517, 4576, 56250, 7007, 62500, 6864, 56250}, + {2518, 4576, 56250, 7007, 62500, 6864, 56250}, + {2520, 4096, 50400, 6272, 56000, 6144, 50400}, + {2700, 4096, 54000, 6272, 60000, 6144, 54000}, + {2702, 4096, 54054, 6267, 60060, 8192, 54054}, + {2703, 4096, 54054, 6272, 60060, 8192, 54054}, + {5400, 4096, 108000, 6272, 120000, 6144, 108000}, + {5405, 4096, 108108, 6272, 120120, 6144, 108108}, {7417, 11648, 421875, 17836, 468750, 11648, 281250}, - {7425, 4096, 148500, 6272, 165000, 6144, 148500}, - {14835, 11648, 843750, 8918, 468750, 11648, 281250}, - {14850, 4096, 297000, 6272, 330000, 6144, 297000} + {7425, 4096, 148500, 6272, 165000, 6144, 148500}, + {14835, 11648, 843750, 8918, 468750, 11648, 281250}, + {14850, 4096, 297000, 6272, 330000, 6144, 297000}, + {29670, 5824, 843750, 4459, 468750, 5824, 562500}, + {29700, 3072, 445500, 4704, 495000, 5120, 495000} + + }; union audio_cea_channels speakers_to_channels( @@ -973,6 +999,11 @@ bool get_audio_clock_info( audio_array_size = ARRAY_SIZE( audio_clock_info_table_36bpc); break; + case COLOR_DEPTH_101010: + clock_info = audio_clock_info_table_30bpc; + audio_array_size = ARRAY_SIZE( + audio_clock_info_table_30bpc); + break; default: clock_info = audio_clock_info_table; audio_array_size = ARRAY_SIZE( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9c9183f96e04..76a397d90adc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -868,6 +868,37 @@ static void build_audio_output( audio_output->crtc_info.calculated_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk; +/*for HDMI, audio ACR is with deep color ratio factor*/ + if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && + audio_output->crtc_info.requested_pixel_clock == + stream->public.timing.pix_clk_khz) { + if (pipe_ctx->pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + audio_output->crtc_info.requested_pixel_clock = + audio_output->crtc_info.requested_pixel_clock/2; + audio_output->crtc_info.calculated_pixel_clock = + pipe_ctx->pix_clk_params.requested_pix_clk/2; + } + + if (pipe_ctx->pix_clk_params.pixel_encoding != PIXEL_ENCODING_YCBCR422) { + switch (pipe_ctx->pix_clk_params.color_depth) { + case COLOR_DEPTH_888: + break; + case COLOR_DEPTH_101010: + audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 30) / 24; + break; + case COLOR_DEPTH_121212: + audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 36) / 24; + break; + case COLOR_DEPTH_161616: + audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 48) / 24; + break; + default: + ASSERT(0); + break; + } + } + } + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { audio_output->pll_info.dp_dto_source_clock_in_khz = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index f6e546addbd3..074fb978e076 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -776,6 +776,7 @@ static void get_pixel_clock_parameters( pixel_clk_params->flags.DISPLAY_BLANKED = 1; pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420); + pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; } void dce110_resource_build_bit_depth_reduction_params( -- GitLab From 896b3cb3f48e662abdaaaeb5a4e1001723081a19 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 17 Feb 2017 13:51:32 -0500 Subject: [PATCH 0266/2898] drm/amd/display: fix 12bpc truncate to 10bpc Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index a2f57cf603aa..121ccbb1ad2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -710,32 +710,32 @@ void dce110_opp_set_dyn_expansion( enum signal_type signal) { struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - bool enable_dyn_exp = false; REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, 0, FMT_DYNAMIC_EXP_MODE, 0); - /* From HW programming guide: - FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output - FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/ - if (color_sp == COLOR_SPACE_SRGB) - enable_dyn_exp = true; /*00 - 10-bit -> 12-bit dynamic expansion*/ /*01 - 8-bit -> 12-bit dynamic expansion*/ - if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + if (signal == SIGNAL_TYPE_HDMI_TYPE_A || + signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { switch (color_dpth) { case COLOR_DEPTH_888: REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, - FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_EN, 1, FMT_DYNAMIC_EXP_MODE, 1); break; case COLOR_DEPTH_101010: REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, - FMT_DYNAMIC_EXP_EN, enable_dyn_exp ? 1:0, + FMT_DYNAMIC_EXP_EN, 1, FMT_DYNAMIC_EXP_MODE, 0); break; case COLOR_DEPTH_121212: + REG_UPDATE_2( + FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/ + FMT_DYNAMIC_EXP_MODE, 0); break; default: break; -- GitLab From 181a888fcd723c4bc63f43aac50713c34ae9102e Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 17 Feb 2017 13:59:11 -0500 Subject: [PATCH 0267/2898] drm/amd/display: fix incorrect programming for YCbCr422 and YCbCr420 Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 12 +++++++++--- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 17 +++++++++-------- .../drm/amd/display/dc/dce110/dce110_resource.c | 3 +++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index aba392ff5095..e4092fd458a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -362,9 +362,15 @@ static void dce110_stream_encoder_hdmi_set_stream_attribute( REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); break; case COLOR_DEPTH_101010: - REG_UPDATE_2(HDMI_CONTROL, - HDMI_DEEP_COLOR_DEPTH, 1, - HDMI_DEEP_COLOR_ENABLE, 1); + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + } break; case COLOR_DEPTH_121212: if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 76a397d90adc..6915cc46754b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -861,10 +861,6 @@ static void build_audio_output( audio_output->crtc_info.requested_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk; - /* - * TODO - Investigate why calculated pixel clk has to be - * requested pixel clk - */ audio_output->crtc_info.calculated_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk; @@ -1044,15 +1040,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->public.timing.display_color_depth, pipe_ctx->stream->signal); + /* FPGA does not program backend */ + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { pipe_ctx->opp->funcs->opp_program_fmt( pipe_ctx->opp, &stream->bit_depth_params, &stream->clamping); - - /* FPGA does not program backend */ - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) return DC_OK; - + } /* TODO: move to stream encoder */ if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) { @@ -1065,6 +1060,12 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->sink->link->link_enc, pipe_ctx->stream->signal); +/*vbios crtc_source_selection and encoder_setup will override fmt_C*/ + pipe_ctx->opp->funcs->opp_program_fmt( + pipe_ctx->opp, + &stream->bit_depth_params, + &stream->clamping); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_enc, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 074fb978e076..478c8d27f3bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -777,6 +777,9 @@ static void get_pixel_clock_parameters( pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420); pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { + pixel_clk_params->color_depth = COLOR_DEPTH_888; + } } void dce110_resource_build_bit_depth_reduction_params( -- GitLab From b0fb632f9b511145dfe49b783dd99adc6c6f8687 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 12 Jan 2017 09:07:38 -0500 Subject: [PATCH 0268/2898] drm/amdgpu: Expose mode_config functions for DM Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 4 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_display.h | 33 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_display.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index e23b89cc6636..b1079930630e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -598,7 +598,7 @@ amdgpu_framebuffer_init(struct drm_device *dev, return 0; } -static struct drm_framebuffer * +struct drm_framebuffer * amdgpu_user_framebuffer_create(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) @@ -636,7 +636,7 @@ amdgpu_user_framebuffer_create(struct drm_device *dev, return &amdgpu_fb->base; } -static void amdgpu_output_poll_changed(struct drm_device *dev) +void amdgpu_output_poll_changed(struct drm_device *dev) { struct amdgpu_device *adev = dev->dev_private; amdgpu_fb_output_poll_changed(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h new file mode 100644 index 000000000000..3cc0ef0c055e --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __AMDGPU_DISPLAY_H__ +#define __AMDGPU_DISPLAY_H__ + +struct drm_framebuffer * +amdgpu_user_framebuffer_create(struct drm_device *dev, + struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd); + +void amdgpu_output_poll_changed(struct drm_device *dev); + +#endif -- GitLab From dd55d12c2675859fa4d4947dafc44515eedbccc4 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 29 Jan 2017 23:16:03 -0500 Subject: [PATCH 0269/2898] drm/amdgpu: Add a few members to support DAL atomic refactor. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 0d92126b4c4a..813108eab6fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -310,6 +310,9 @@ struct amdgpu_display_funcs { struct amdgpu_framebuffer { struct drm_framebuffer base; struct drm_gem_object *obj; + + /* caching for later use */ + uint64_t address; }; struct amdgpu_fbdev { @@ -430,6 +433,7 @@ struct amdgpu_crtc { uint32_t flip_flags; /* After Set Mode stream will be non-NULL */ const struct dc_stream *stream; + struct drm_pending_vblank_event *event; }; struct amdgpu_encoder_atom_dig { -- GitLab From 4ef3a67b6a1af2fc9030bc955200e764edfc37fb Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 15 Feb 2017 18:21:20 -0500 Subject: [PATCH 0270/2898] drm/amd/display: rename bandwidth_calcs.c to dce_calcs.c (v2) v2: agd: squash in the Makefile change as well. Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Eagle Yeh Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 +- .../drm/amd/display/dc/calcs/{bandwidth_calcs.c => dce_calcs.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/gpu/drm/amd/display/dc/calcs/{bandwidth_calcs.c => dce_calcs.c} (100%) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 2f4c8e771b8f..63a0edbc32e7 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,7 +3,7 @@ # It calculates Bandwidth and Watermarks values for HW programming # -BW_CALCS = bandwidth_calcs.o bw_fixed.o custom_float.o +BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/bandwidth_calcs.c rename to drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c -- GitLab From 4b679bc3cab09f2af44bd34dfc197939a4602aa8 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 22 Feb 2017 13:46:29 -0500 Subject: [PATCH 0271/2898] drm/amd/display: HDMI deep color mode audio issue Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 9 +++++-- .../gpu/drm/amd/display/dc/core/dc_stream.c | 11 +++++--- .../gpu/drm/amd/display/dc/dce/dce_audio.c | 9 +++++++ .../drm/amd/display/dc/dce/dce_clock_source.c | 1 - .../amd/display/dc/dce/dce_stream_encoder.c | 26 ++++--------------- .../display/dc/dce110/dce110_hw_sequencer.c | 18 ------------- 6 files changed, 28 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4d556b379524..407ce60f253e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1101,9 +1101,14 @@ enum dc_status resource_map_pool_resources( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - if (!resource_is_stream_unchanged(dc->current_context, stream)) + if (!resource_is_stream_unchanged(dc->current_context, stream)) { + if (stream != NULL && dc->current_context->streams[i] != NULL) { + stream->bit_depth_params = + dc->current_context->streams[i]->bit_depth_params; + stream->clamping = dc->current_context->streams[i]->clamping; continue; - + } + } /* mark resources used for stream that is already active */ for (j = 0; j < MAX_PIPES; j++) { struct pipe_ctx *pipe_ctx = diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index e1f579bcd789..4e1a933be021 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -305,7 +305,7 @@ void dc_stream_log( dm_logger_write(dm_logger, log_type, - "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n", + "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d, colorSpace:%d\n", core_stream, core_stream->public.src.x, core_stream->public.src.y, @@ -314,13 +314,16 @@ void dc_stream_log( core_stream->public.dst.x, core_stream->public.dst.y, core_stream->public.dst.width, - core_stream->public.dst.height); + core_stream->public.dst.height, + core_stream->public.output_color_space); dm_logger_write(dm_logger, log_type, - "\tpix_clk_khz: %d, h_total: %d, v_total: %d\n", + "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n", core_stream->public.timing.pix_clk_khz, core_stream->public.timing.h_total, - core_stream->public.timing.v_total); + core_stream->public.timing.v_total, + core_stream->public.timing.pixel_encoding, + core_stream->public.timing.display_color_depth); dm_logger_write(dm_logger, log_type, "\tsink name: %s, serial: %d\n", diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 596e039ee315..7f52e39ec92a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -773,6 +773,15 @@ void dce_aud_wall_dto_setup( crtc_info->calculated_pixel_clock, &clock_info); + dm_logger_write(audio->ctx->logger, LOG_HW_SET_MODE,\ + "\n************************%s:Input::requested_pixel_clock = %d"\ + "calculated_pixel_clock =%d\n"\ + "audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\ + crtc_info->requested_pixel_clock,\ + crtc_info->calculated_pixel_clock,\ + clock_info.audio_dto_module,\ + clock_info.audio_dto_phase); + /* On TN/SI, Program DTO source select and DTO select before programming DTO modulo and DTO phase. These bits must be programmed first, otherwise there will be no HDMI audio at boot diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 26742e038274..a2a2ecf8d077 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -874,7 +874,6 @@ static bool dce110_program_pix_clk( bp_pc_params.flags.SET_XTALIN_REF_SRC = !pll_settings->use_external_clk; if (pix_clk_params->flags.SUPPORT_YCBCR420) { - bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk / 2; bp_pc_params.flags.SUPPORT_YUV_420 = 1; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index e4092fd458a1..d6662fa2f4e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -873,22 +873,6 @@ static const struct audio_clock_info audio_clock_info_table[16] = { {59400, 3072, 445500, 9408, 990000, 6144, 594000} }; -static const struct audio_clock_info audio_clock_info_table_30bpc[14] = { - {2517, 9152, 70312, 14014, 78125, 9152, 46875}, - {2518, 9152, 70312, 14014, 78125, 9152, 46875}, - {2520, 4096, 31500, 6272, 35000, 6144, 31500}, - {2700, 4096, 33750, 6272, 37500, 6144, 33750}, - {2702, 8192, 67567, 12544, 75075, 8192, 45045}, - {2703, 8192, 67567, 12544, 75075, 8192, 45045}, - {5400, 4096, 67500, 6272, 75000, 6144, 67500}, - {5405, 8192, 135135, 6272, 75075, 8192, 90090}, - {7417, 11648, 263672, 17836, 292969, 11648, 175181}, - {7425, 8192, 185625, 6272, 103125, 12288, 185625}, - {14835, 11648, 527344, 17836, 585938, 11648, 351563}, - {14850, 4096, 185625, 6272, 206250, 6144, 185625}, - {29670, 11648, 527344, 17836, 585938, 11648, 703125}, - {29700, 6144, 556875, 4704, 309375, 5120, 309375} -}; static const struct audio_clock_info audio_clock_info_table_36bpc[14] = { {2517, 9152, 84375, 7007, 48875, 9152, 56250}, {2518, 9152, 84375, 7007, 48875, 9152, 56250}, @@ -1005,11 +989,6 @@ bool get_audio_clock_info( audio_array_size = ARRAY_SIZE( audio_clock_info_table_36bpc); break; - case COLOR_DEPTH_101010: - clock_info = audio_clock_info_table_30bpc; - audio_array_size = ARRAY_SIZE( - audio_clock_info_table_30bpc); - break; default: clock_info = audio_clock_info_table; audio_array_size = ARRAY_SIZE( @@ -1114,6 +1093,11 @@ static void dce110_se_setup_hdmi_audio( crtc_info->requested_pixel_clock, crtc_info->calculated_pixel_clock, &audio_clock_info)) { + dm_logger_write(enc->ctx->logger, LOG_HW_SET_MODE, + "\n*********************%s:Input::requested_pixel_clock = %d"\ + "calculated_pixel_clock = %d \n", __func__,\ + crtc_info->requested_pixel_clock,\ + crtc_info->calculated_pixel_clock); /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6915cc46754b..2f68bf20dfe2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -873,25 +873,7 @@ static void build_audio_output( audio_output->crtc_info.requested_pixel_clock/2; audio_output->crtc_info.calculated_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk/2; - } - if (pipe_ctx->pix_clk_params.pixel_encoding != PIXEL_ENCODING_YCBCR422) { - switch (pipe_ctx->pix_clk_params.color_depth) { - case COLOR_DEPTH_888: - break; - case COLOR_DEPTH_101010: - audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 30) / 24; - break; - case COLOR_DEPTH_121212: - audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 36) / 24; - break; - case COLOR_DEPTH_161616: - audio_output->crtc_info.calculated_pixel_clock = (audio_output->crtc_info.calculated_pixel_clock * 48) / 24; - break; - default: - ASSERT(0); - break; - } } } -- GitLab From d5b4f2bcff03c6cafb0a890360f1f8fbc99071a1 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 22 Feb 2017 18:26:20 -0500 Subject: [PATCH 0272/2898] drm/amd/display: 420 clock divided by 2 twice Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Krunoslav Kovac Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 478c8d27f3bd..cd3942df70a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -780,6 +780,9 @@ static void get_pixel_clock_parameters( if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { pixel_clk_params->color_depth = COLOR_DEPTH_888; } + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + pixel_clk_params->requested_pix_clk = pixel_clk_params->requested_pix_clk / 2; + } } void dce110_resource_build_bit_depth_reduction_params( -- GitLab From 3548f0731a2fa823bcb31b5ea662603926b85c43 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 17 Feb 2017 11:56:03 -0500 Subject: [PATCH 0273/2898] drm/amd/display: DMCU PSR Refactor - Move PSR programming from link encoder to dmcu Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 21 +- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 208 +++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 107 ++++++- .../drm/amd/display/dc/dce/dce_link_encoder.c | 280 +++--------------- .../drm/amd/display/dc/dce/dce_link_encoder.h | 73 +---- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 4 + .../drm/amd/display/dc/inc/hw/link_encoder.h | 9 +- 7 files changed, 376 insertions(+), 326 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2b929393f68a..8eb6b342a49d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -40,6 +40,7 @@ #include "abm.h" #include "fixed31_32.h" #include "dpcd_defs.h" +#include "dmcu.h" #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_enum.h" @@ -1433,28 +1434,33 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) { struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dmcu *dmcu = core_dc->res_pool->dmcu; + + if (dmcu != NULL && dc_link->psr_caps.psr_version > 0) + dmcu->funcs->set_psr_enable(dmcu, enable); - if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) - link->link_enc->funcs->set_dmcu_psr_enable(link->link_enc, - enable); return true; } bool dc_link_setup_psr(const struct dc_link *dc_link, const struct dc_stream *stream) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); struct dc_context *ctx = link->ctx; struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dmcu *dmcu = core_dc->res_pool->dmcu; struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct psr_dmcu_context psr_context = {0}; + struct psr_context psr_context = {0}; int i; psr_context.controllerId = CONTROLLER_ID_UNDEFINED; - if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) { + if (dc_link != NULL && + dmcu != NULL && + dc_link->psr_caps.psr_version > 0) { /* updateSinkPsrDpcdConfig*/ union dpcd_psr_configuration psr_configuration; @@ -1552,8 +1558,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, */ psr_context.frame_delay = 0; - link->link_enc->funcs->setup_dmcu_psr - (link->link_enc, &psr_context); + dmcu->funcs->setup_psr(dmcu, link, &psr_context); return true; } else return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index eb0e95f57aa9..44eeeeb888fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -23,6 +23,8 @@ * */ +#include "core_types.h" +#include "link_encoder.h" #include "dce_dmcu.h" #include "dm_services.h" #include "reg_helper.h" @@ -42,6 +44,12 @@ #define CTX \ dmcu_dce->base.ctx +/* PSR related commands */ +#define PSR_ENABLE 0x20 +#define PSR_EXIT 0x21 +#define PSR_SET 0x23 +#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L + bool dce_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, const char *src, @@ -76,8 +84,208 @@ bool dce_dmcu_load_iram(struct dmcu *dmcu, return true; } +static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + uint32_t count = 0; + uint32_t psrStateOffset = 0xf0; + uint32_t value = -1; + + /* Enable write access to IRAM */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); + + while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) { + dm_delay_in_microseconds(dmcu->ctx, 2); + REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); + } + while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) { + dm_delay_in_microseconds(dmcu->ctx, 2); + REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value); + } + + /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ + REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); + + /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ + *psr_state = REG_READ(DMCU_IRAM_RD_DATA); + + /* Disable write access to IRAM after finished using IRAM + * in order to allow dynamic sleep state + */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); +} + +static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + + unsigned int regValue; + + unsigned int retryCount; + uint32_t psr_state = 0; + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(dmcu->ctx, + dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_Cmd */ + if (enable) + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + PSR_ENABLE); + else + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + PSR_EXIT); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + for (retryCount = 0; retryCount <= 100; retryCount++) { + dce_get_dmcu_psr_state(dmcu, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + dm_delay_in_microseconds(dmcu->ctx, 10); + } +} + +static void dce_dmcu_setup_psr(struct dmcu *dmcu, + struct core_link *link, + struct psr_context *psr_context) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + unsigned int regValue; + + union dce_dmcu_psr_config_data_reg1 masterCmdData1; + union dce_dmcu_psr_config_data_reg2 masterCmdData2; + union dce_dmcu_psr_config_data_reg3 masterCmdData3; + + link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc, + psr_context->psrExitLinkTrainingRequired); + + /* Enable static screen interrupts for PSR supported display */ + /* Disable the interrupt coming from other displays. */ + REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 0, + STATIC_SCREEN2_INT_TO_UC_EN, 0, + STATIC_SCREEN3_INT_TO_UC_EN, 0, + STATIC_SCREEN4_INT_TO_UC_EN, 0); + + switch (psr_context->controllerId) { + /* Driver uses case 1 for unconfigured */ + case 1: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + case 2: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN2_INT_TO_UC_EN, 1); + break; + case 3: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN3_INT_TO_UC_EN, 1); + break; + case 4: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN4_INT_TO_UC_EN, 1); + break; + case 5: + /* CZ/NL only has 4 CRTC!! + * really valid. + * There is no interrupt enable mask for these instances. + */ + break; + case 6: + /* CZ/NL only has 4 CRTC!! + * These are here because they are defined in HW regspec, + * but not really valid. There is no interrupt enable mask + * for these instances. + */ + break; + default: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + } + + link->link_enc->funcs->psr_program_secondary_packet(link->link_enc, + psr_context->sdpTransmitLineNumDeadline); + + if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) + REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); + + /* waitDMCUReadyForCmd */ + do { + dm_delay_in_microseconds(dmcu->ctx, + dmcu_wait_reg_ready_interval); + regValue = REG_READ(MASTER_COMM_CNTL_REG); + dmcu_max_retry_on_wait_reg_ready--; + } while + /* expected value is 0, loop while not 0*/ + ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && + dmcu_max_retry_on_wait_reg_ready > 0); + + /* setDMCUParam_PSRHostConfigData */ + masterCmdData1.u32All = 0; + masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames; + masterCmdData1.bits.hyst_lines = psr_context->hyst_lines; + masterCmdData1.bits.rfb_update_auto_en = + psr_context->rfb_update_auto_en; + masterCmdData1.bits.dp_port_num = psr_context->transmitterId; + masterCmdData1.bits.dcp_sel = psr_context->controllerId; + masterCmdData1.bits.phy_type = psr_context->phyType; + masterCmdData1.bits.frame_cap_ind = + psr_context->psrFrameCaptureIndicationReq; + masterCmdData1.bits.aux_chan = psr_context->channel; + masterCmdData1.bits.aux_repeat = psr_context->aux_repeats; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), + masterCmdData1.u32All); + + masterCmdData2.u32All = 0; + masterCmdData2.bits.dig_fe = psr_context->engineId; + masterCmdData2.bits.dig_be = psr_context->transmitterId; + masterCmdData2.bits.skip_wait_for_pll_lock = + psr_context->skipPsrWaitForPllLock; + masterCmdData2.bits.frame_delay = psr_context->frame_delay; + masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId; + masterCmdData2.bits.num_of_controllers = + psr_context->numberOfControllers; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG2), + masterCmdData2.u32All); + + masterCmdData3.u32All = 0; + masterCmdData3.bits.psr_level = psr_context->psr_level.u32all; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG3), + masterCmdData3.u32All); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, PSR_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + static const struct dmcu_funcs dce_funcs = { .load_iram = dce_dmcu_load_iram, + .set_psr_enable = dce_dmcu_set_psr_enable, + .setup_psr = dce_dmcu_setup_psr, }; static void dce_dmcu_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 33c1754f04f1..7dc25386c2bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -33,7 +33,16 @@ SR(DMCU_CTRL), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_WR_CTRL), \ - SR(DMCU_IRAM_WR_DATA) + SR(DMCU_IRAM_WR_DATA), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(MASTER_COMM_DATA_REG2), \ + SR(MASTER_COMM_DATA_REG3), \ + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_CNTL_REG), \ + SR(DMCU_IRAM_RD_CTRL), \ + SR(DMCU_IRAM_RD_DATA), \ + SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ + SR(SMU_INTERRUPT_CONTROL) #define DMCU_DCE110_COMMON_REG_LIST() \ DMCU_COMMON_REG_LIST_DCE_BASE(), \ @@ -48,18 +57,41 @@ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ IRAM_HOST_ACCESS_EN, mask_sh), \ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ - IRAM_WR_ADDR_AUTO_INC, mask_sh) + IRAM_WR_ADDR_AUTO_INC, mask_sh), \ + DMCU_SF(MASTER_COMM_CMD_REG, \ + MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ + DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \ + STATIC_SCREEN1_INT_TO_UC_EN, mask_sh), \ + DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \ + STATIC_SCREEN2_INT_TO_UC_EN, mask_sh), \ + DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \ + STATIC_SCREEN3_INT_TO_UC_EN, mask_sh), \ + DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \ + STATIC_SCREEN4_INT_TO_UC_EN, mask_sh), \ + DMCU_SF(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, mask_sh) #define DMCU_MASK_SH_LIST_DCE110(mask_sh) \ DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ DMCU_SF(DCI_MEM_PWR_STATUS, \ - DMCU_IRAM_MEM_PWR_STATE, mask_sh) + DMCU_IRAM_MEM_PWR_STATE, mask_sh) #define DMCU_REG_FIELD_LIST(type) \ type DMCU_IRAM_MEM_PWR_STATE; \ type IRAM_HOST_ACCESS_EN; \ type IRAM_WR_ADDR_AUTO_INC; \ - type DMCU_ENABLE + type DMCU_ENABLE; \ + type MASTER_COMM_CMD_REG_BYTE0; \ + type MASTER_COMM_INTERRUPT; \ + type DPHY_RX_FAST_TRAINING_CAPABLE; \ + type DPHY_LOAD_BS_COUNT; \ + type STATIC_SCREEN1_INT_TO_UC_EN; \ + type STATIC_SCREEN2_INT_TO_UC_EN; \ + type STATIC_SCREEN3_INT_TO_UC_EN; \ + type STATIC_SCREEN4_INT_TO_UC_EN; \ + type DP_SEC_GSP0_LINE_NUM; \ + type DP_SEC_GSP0_PRIORITY; \ + type DC_SMU_INT_ENABLE struct dce_dmcu_shift { DMCU_REG_FIELD_LIST(uint8_t); @@ -76,6 +108,16 @@ struct dce_dmcu_registers { uint32_t DMU_MEM_PWR_CNTL; uint32_t DMCU_IRAM_WR_CTRL; uint32_t DMCU_IRAM_WR_DATA; + + uint32_t MASTER_COMM_DATA_REG1; + uint32_t MASTER_COMM_DATA_REG2; + uint32_t MASTER_COMM_DATA_REG3; + uint32_t MASTER_COMM_CMD_REG; + uint32_t MASTER_COMM_CNTL_REG; + uint32_t DMCU_IRAM_RD_CTRL; + uint32_t DMCU_IRAM_RD_DATA; + uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; + uint32_t SMU_INTERRUPT_CONTROL; }; struct dce_dmcu { @@ -85,6 +127,63 @@ struct dce_dmcu { const struct dce_dmcu_mask *dmcu_mask; }; +/******************************************************************* + * MASTER_COMM_DATA_REG1 Bit position Data + * 7:0 hyst_frames[7:0] + * 14:8 hyst_lines[6:0] + * 15 RFB_UPDATE_AUTO_EN + * 18:16 phy_num[2:0] + * 21:19 dcp_sel[2:0] + * 22 phy_type + * 23 frame_cap_ind + * 26:24 aux_chan[2:0] + * 30:27 aux_repeat[3:0] + * 31:31 reserved[31:31] + ******************************************************************/ +union dce_dmcu_psr_config_data_reg1 { + struct { + unsigned int timehyst_frames:8; /*[7:0]*/ + unsigned int hyst_lines:7; /*[14:8]*/ + unsigned int rfb_update_auto_en:1; /*[15:15]*/ + unsigned int dp_port_num:3; /*[18:16]*/ + unsigned int dcp_sel:3; /*[21:19]*/ + unsigned int phy_type:1; /*[22:22]*/ + unsigned int frame_cap_ind:1; /*[23:23]*/ + unsigned int aux_chan:3; /*[26:24]*/ + unsigned int aux_repeat:4; /*[30:27]*/ + unsigned int reserved:1; /*[31:31]*/ + } bits; + unsigned int u32All; +}; + +/******************************************************************* + * MASTER_COMM_DATA_REG2 + *******************************************************************/ +union dce_dmcu_psr_config_data_reg2 { + struct { + unsigned int dig_fe:3; /*[2:0]*/ + unsigned int dig_be:3; /*[5:3]*/ + unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/ + unsigned int reserved:9; /*[15:7]*/ + unsigned int frame_delay:8; /*[23:16]*/ + unsigned int smu_phy_id:4; /*[27:24]*/ + unsigned int num_of_controllers:4; /*[31:28]*/ + } bits; + unsigned int u32All; +}; + +/******************************************************************* + * MASTER_COMM_DATA_REG3 + *******************************************************************/ +union dce_dmcu_psr_config_data_reg3 { + struct { + unsigned int psr_level:16; /*[15:0]*/ + unsigned int link_rate:4; /*[19:16]*/ + unsigned int reserved:12; /*[31:20]*/ + } bits; + unsigned int u32All; +}; + struct dmcu *dce_dmcu_create( struct dc_context *ctx, const struct dce_dmcu_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 305a9d86a5d2..a1d35ad85605 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -95,14 +95,6 @@ /* For current ASICs pixel clock - 600MHz */ #define MAX_ENCODER_CLOCK 600000 -/* PSR related commands */ -#define PSR_ENABLE 0x20 -#define PSR_EXIT 0x21 -#define PSR_SET 0x23 - -/*TODO: Used for psr wakeup for set backlight level*/ -static unsigned int psr_crtc_offset; - enum { DP_MST_UPDATE_MAX_RETRY = 50 }; @@ -126,8 +118,9 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = dce110_link_encoder_update_mst_stream_allocation_table, - .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable, - .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr, + .psr_program_dp_dphy_fast_training = + dce110_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dce110_psr_program_secondary_packet, .backlight_control = dce110_link_encoder_edp_backlight_control, .power_control = dce110_link_encoder_edp_power_control, .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, @@ -136,7 +129,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .destroy = dce110_link_encoder_destroy }; - static enum bp_result link_transmitter_control( struct dce110_link_encoder *enc110, struct bp_transmitter_control *cntl) @@ -721,6 +713,40 @@ static bool is_panel_backlight_on(struct dce110_link_encoder *enc110) return value; } +void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc, + bool exit_link_training_required) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + if (exit_link_training_required) + REG_UPDATE(DP_DPHY_FAST_TRAINING, + DPHY_RX_FAST_TRAINING_CAPABLE, 1); + else { + REG_UPDATE(DP_DPHY_FAST_TRAINING, + DPHY_RX_FAST_TRAINING_CAPABLE, 0); + /*In DCE 11, we are able to pre-program a Force SR register + * to be able to trigger SR symbol after 5 idle patterns + * transmitted. Upon PSR Exit, DMCU can trigger + * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to + * DPHY_LOAD_BS_COUNT_START and the internal counter + * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be + * replaced by SR symbol once. + */ + + REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); + } +} + +void dce110_psr_program_secondary_packet(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + REG_UPDATE_2(DP_SEC_CNTL1, + DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline, + DP_SEC_GSP0_PRIORITY, 1); +} + /*todo: cloned in stream enc, fix*/ /* * @brief @@ -1560,238 +1586,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( } while (retries < DP_MST_UPDATE_MAX_RETRY); } -static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - - uint32_t count = 0; - uint32_t psrStateOffset = 0xf0; - uint32_t value = -1; - - /* Enable write access to IRAM */ - REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); - - while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) { - dm_delay_in_microseconds(ctx, 2); - REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); - } - while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) { - dm_delay_in_microseconds(ctx, 2); - REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value); - } - - /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ - REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); - - /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ - *psr_state = REG_READ(DMCU_IRAM_RD_DATA); - - /* Disable write access to IRAM after finished using IRAM - * in order to allow dynamic sleep state - */ - REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); -} - -void dce110_link_encoder_set_dmcu_psr_enable(struct link_encoder *enc, - bool enable) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - - unsigned int regValue; - - unsigned int retryCount; - uint32_t psr_state = 0; - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - /* setDMCUParam_Cmd */ - if (enable) - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_ENABLE); - else - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_EXIT); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - for (retryCount = 0; retryCount <= 100; retryCount++) { - get_dmcu_psr_state(enc, &psr_state); - if (enable) { - if (psr_state != 0) - break; - } else { - if (psr_state == 0) - break; - } - dm_delay_in_microseconds(ctx, 10); - } -} - -void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc, - struct psr_dmcu_context *psr_context) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - - unsigned int dmcu_max_retry_on_wait_reg_ready = 801; - unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; - - union dce110_dmcu_psr_config_data_reg1 masterCmdData1; - union dce110_dmcu_psr_config_data_reg2 masterCmdData2; - union dce110_dmcu_psr_config_data_reg3 masterCmdData3; - - if (psr_context->psrExitLinkTrainingRequired) - REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 1); - else { - REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 0); - /*In DCE 11, we are able to pre-program a Force SR register - * to be able to trigger SR symbol after 5 idle patterns - * transmitted. Upon PSR Exit, DMCU can trigger - * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to - * DPHY_LOAD_BS_COUNT_START and the internal counter - * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be - * replaced by SR symbol once. - */ - - REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5); - } - - /* Enable static screen interrupts for PSR supported display */ - /* Disable the interrupt coming from other displays. */ - REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN1_INT_TO_UC_EN, 0, - STATIC_SCREEN2_INT_TO_UC_EN, 0, - STATIC_SCREEN3_INT_TO_UC_EN, 0, - STATIC_SCREEN4_INT_TO_UC_EN, 0); - - switch (psr_context->controllerId) { - /* Driver uses case 1 for unconfigured */ - case 1: - psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN1_INT_TO_UC_EN, 1); - break; - case 2: - psr_crtc_offset = mmCRTC1_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN2_INT_TO_UC_EN, 1); - break; - case 3: - psr_crtc_offset = mmCRTC2_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN3_INT_TO_UC_EN, 1); - break; - case 4: - psr_crtc_offset = mmCRTC3_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN4_INT_TO_UC_EN, 1); - break; - case 5: - psr_crtc_offset = mmCRTC4_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - /* CZ/NL only has 4 CRTC!! - * really valid. - * There is no interrupt enable mask for these instances. - */ - break; - case 6: - psr_crtc_offset = mmCRTC5_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - /* CZ/NL only has 4 CRTC!! - * These are here because they are defined in HW regspec, - * but not really valid. There is no interrupt enable mask - * for these instances. - */ - break; - default: - psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL - - mmCRTC0_CRTC_STATIC_SCREEN_CONTROL; - - REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, - STATIC_SCREEN1_INT_TO_UC_EN, 1); - break; - } - - REG_UPDATE_2(DP_SEC_CNTL1, - DP_SEC_GSP0_LINE_NUM, psr_context->sdpTransmitLineNumDeadline, - DP_SEC_GSP0_PRIORITY, 1); - - if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) { - REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); - } - - /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); - - /* setDMCUParam_PSRHostConfigData */ - masterCmdData1.u32All = 0; - masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames; - masterCmdData1.bits.hyst_lines = psr_context->hyst_lines; - masterCmdData1.bits.rfb_update_auto_en = - psr_context->rfb_update_auto_en; - masterCmdData1.bits.dp_port_num = psr_context->transmitterId; - masterCmdData1.bits.dcp_sel = psr_context->controllerId; - masterCmdData1.bits.phy_type = psr_context->phyType; - masterCmdData1.bits.frame_cap_ind = - psr_context->psrFrameCaptureIndicationReq; - masterCmdData1.bits.aux_chan = psr_context->channel; - masterCmdData1.bits.aux_repeat = psr_context->aux_repeats; - dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), - masterCmdData1.u32All); - - masterCmdData2.u32All = 0; - masterCmdData2.bits.dig_fe = psr_context->engineId; - masterCmdData2.bits.dig_be = psr_context->transmitterId; - masterCmdData2.bits.skip_wait_for_pll_lock = - psr_context->skipPsrWaitForPllLock; - masterCmdData2.bits.frame_delay = psr_context->frame_delay; - masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId; - masterCmdData2.bits.num_of_controllers = - psr_context->numberOfControllers; - dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG2), - masterCmdData2.u32All); - - masterCmdData3.u32All = 0; - masterCmdData3.bits.psr_level = psr_context->psr_level.u32all; - dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG3), - masterCmdData3.u32All); - - /* setDMCUParam_Cmd */ - REG_UPDATE(MASTER_COMM_CMD_REG, - MASTER_COMM_CMD_REG_BYTE0, PSR_SET); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); -} - void dce110_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index d382a6882d95..f337d607e36c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -39,11 +39,6 @@ SRI(DC_HPD_CONTROL, HPD, id) #define LE_COMMON_REG_LIST_BASE(id) \ - SR(MASTER_COMM_DATA_REG1), \ - SR(MASTER_COMM_DATA_REG2), \ - SR(MASTER_COMM_DATA_REG3), \ - SR(MASTER_COMM_CMD_REG), \ - SR(MASTER_COMM_CNTL_REG), \ SR(LVTMA_PWRSEQ_CNTL), \ SR(LVTMA_PWRSEQ_STATE), \ SR(DMCU_RAM_ACCESS_CTRL), \ @@ -149,62 +144,6 @@ struct dce110_link_encoder { const struct dce110_link_enc_hpd_registers *hpd_regs; }; -/******************************************************************* -* MASTER_COMM_DATA_REG1 Bit position Data -* 7:0 hyst_frames[7:0] -* 14:8 hyst_lines[6:0] -* 15 RFB_UPDATE_AUTO_EN -* 18:16 phy_num[2:0] -* 21:19 dcp_sel[2:0] -* 22 phy_type -* 23 frame_cap_ind -* 26:24 aux_chan[2:0] -* 30:27 aux_repeat[3:0] -* 31:31 reserved[31:31] -*******************************************************************/ -union dce110_dmcu_psr_config_data_reg1 { - struct { - unsigned int timehyst_frames:8; /*[7:0]*/ - unsigned int hyst_lines:7; /*[14:8]*/ - unsigned int rfb_update_auto_en:1; /*[15:15]*/ - unsigned int dp_port_num:3; /*[18:16]*/ - unsigned int dcp_sel:3; /*[21:19]*/ - unsigned int phy_type:1; /*[22:22]*/ - unsigned int frame_cap_ind:1; /*[23:23]*/ - unsigned int aux_chan:3; /*[26:24]*/ - unsigned int aux_repeat:4; /*[30:27]*/ - unsigned int reserved:1; /*[31:31]*/ - } bits; - unsigned int u32All; -}; - -/******************************************************************* -* MASTER_COMM_DATA_REG2 -*******************************************************************/ -union dce110_dmcu_psr_config_data_reg2 { - struct { - unsigned int dig_fe:3; /*[2:0]*/ - unsigned int dig_be:3; /*[5:3]*/ - unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/ - unsigned int reserved:9; /*[15:7]*/ - unsigned int frame_delay:8; /*[23:16]*/ - unsigned int smu_phy_id:4; /*[27:24]*/ - unsigned int num_of_controllers:4; /*[31:28]*/ - } bits; - unsigned int u32All; -}; - -/******************************************************************* -* MASTER_COMM_DATA_REG3 -*******************************************************************/ -union dce110_dmcu_psr_config_data_reg3 { - struct { - unsigned int psr_level:16; /*[15:0]*/ - unsigned int link_rate:4; /*[19:16]*/ - unsigned int reserved:12; /*[31:20]*/ - } bits; - unsigned int u32All; -}; bool dce110_link_encoder_construct( struct dce110_link_encoder *enc110, @@ -290,12 +229,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_set_dmcu_psr_enable( - struct link_encoder *enc, bool enable); - -void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc, - struct psr_dmcu_context *psr_context); - void dce110_link_encoder_edp_backlight_control( struct link_encoder *enc, bool enable); @@ -317,4 +250,10 @@ void dce110_link_encoder_enable_hpd(struct link_encoder *enc); void dce110_link_encoder_disable_hpd(struct link_encoder *enc); +void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc, + bool exit_link_training_required); + +void dce110_psr_program_secondary_packet(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline); + #endif /* __DC_LINK_ENCODER__DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 62012f091836..656cfdc79891 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -37,6 +37,10 @@ struct dmcu_funcs { unsigned int start_offset, const char *src, unsigned int bytes); + void (*set_psr_enable)(struct dmcu *dmcu, bool enable); + void (*setup_psr)(struct dmcu *dmcu, + struct core_link *link, + struct psr_context *psr_context); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 7b37b963666e..7307f96c7679 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -116,7 +116,7 @@ union psr_sink_psr_status { unsigned char raw; }; -struct psr_dmcu_context { +struct psr_context { /* ddc line */ enum channel_id channel; /* Transmitter id */ @@ -220,9 +220,10 @@ struct link_encoder_funcs { void (*update_mst_stream_allocation_table)( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); - void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable); - void (*setup_dmcu_psr)(struct link_encoder *enc, - struct psr_dmcu_context *psr_context); + void (*psr_program_dp_dphy_fast_training)(struct link_encoder *enc, + bool exit_link_training_required); + void (*psr_program_secondary_packet)(struct link_encoder *enc, + unsigned int sdp_transmit_line_num_deadline); void (*backlight_control) (struct link_encoder *enc, bool enable); void (*power_control) (struct link_encoder *enc, -- GitLab From 5936223f7b51e122beb511265e2112777f7a887e Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Thu, 23 Feb 2017 14:07:29 -0500 Subject: [PATCH 0274/2898] drm/amd/display: Fix gamma colour corruption for 10 bit surfaces Gamma LUT shouldn't be used for 10-bit and above. Should instead be using prescale and bypassing input gamma. Signed-off-by: Jordan Lazare Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 15 +++- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 3 +- .../amd/display/dc/dce80/dce80_ipp_gamma.c | 71 ------------------- 3 files changed, 15 insertions(+), 74 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2f68bf20dfe2..2d2daa694a30 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -233,6 +233,19 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } + +/* Only use LUT for 8 bit formats */ +static bool use_lut(const struct core_surface *surface) +{ + switch (surface->public.format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + return true; + default: + return false; + } +} + static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) @@ -251,7 +264,7 @@ static bool dce110_set_input_transfer_func( build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (surface->public.gamma_correction) + if (surface->public.gamma_correction && use_lut(surface)) ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); if (tf == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 0261d1bfccb5..8d2c3dbfced1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -2,8 +2,7 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE80 = dce80_ipp.o dce80_ipp_gamma.o \ - dce80_timing_generator.o \ +DCE80 = dce80_ipp.o dce80_timing_generator.o \ dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ dce80_resource.o diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c deleted file mode 100644 index 760168df5290..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" - -#include "include/logger_interface.h" -#include "include/fixed31_32.h" -#include "basics/conversion.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_ipp.h" -#include "dce110/dce110_ipp.h" - -#define DCP_REG(reg)\ - (reg + ipp80->offsets.dcp_offset) - -/*PROTOTYPE DECLARATIONS*/ - -static void set_legacy_input_gamma_mode( - struct dce110_ipp *ipp80, - bool is_legacy); - -void dce80_ipp_set_legacy_input_gamma_mode( - struct input_pixel_processor *ipp, - bool is_legacy) -{ - struct dce110_ipp *ipp80 = TO_DCE80_IPP(ipp); - - set_legacy_input_gamma_mode(ipp80, is_legacy); -} - -static void set_legacy_input_gamma_mode( - struct dce110_ipp *ipp80, - bool is_legacy) -{ - const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL); - uint32_t value = dm_read_reg(ipp80->base.ctx, addr); - - set_reg_field_value( - value, - !is_legacy, - INPUT_GAMMA_CONTROL, - GRPH_INPUT_GAMMA_MODE); - - dm_write_reg(ipp80->base.ctx, addr, value); -} - -- GitLab From 227d2518997e122bb702d2110eafd337ad9ff078 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 23 Feb 2017 15:25:51 -0500 Subject: [PATCH 0275/2898] drm/amd/display: add scaler coefficients for 64 phase 5-8 taps Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_scl_filters.c | 608 ++++++++++++++++++ .../gpu/drm/amd/display/dc/inc/hw/transform.h | 4 + 2 files changed, 612 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c index 3aab86781be2..2cfdb835f1a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c @@ -452,6 +452,566 @@ const uint16_t filter_4tap_64p_183[132] = { 252, 1832, 1784, 220, 236, 1808, 1808, 236 }; +const uint16_t filter_5tap_64p_upscale[165] = { + 15936, 2496, 2496, 15936, 0, + 15948, 2404, 2580, 15924, 0, + 15960, 2312, 2664, 15912, 4, + 15976, 2220, 2748, 15904, 8, + 15992, 2128, 2832, 15896, 12, + 16004, 2036, 2912, 15888, 16, + 16020, 1944, 2992, 15880, 20, + 16036, 1852, 3068, 15876, 20, + 16056, 1760, 3140, 15876, 24, + 16072, 1668, 3216, 15872, 28, + 16088, 1580, 3284, 15872, 32, + 16104, 1492, 3352, 15876, 32, + 16120, 1404, 3420, 15876, 36, + 16140, 1316, 3480, 15884, 40, + 16156, 1228, 3540, 15892, 40, + 16172, 1144, 3600, 15900, 40, + 16188, 1060, 3652, 15908, 44, + 16204, 980, 3704, 15924, 44, + 16220, 900, 3756, 15936, 44, + 16236, 824, 3800, 15956, 44, + 16248, 744, 3844, 15972, 44, + 16264, 672, 3884, 15996, 44, + 16276, 600, 3920, 16020, 44, + 16292, 528, 3952, 16044, 40, + 16304, 460, 3980, 16072, 40, + 16316, 396, 4008, 16104, 36, + 16328, 332, 4032, 16136, 32, + 16336, 272, 4048, 16172, 28, + 16348, 212, 4064, 16208, 24, + 16356, 156, 4080, 16248, 16, + 16368, 100, 4088, 16292, 12, + 16376, 48, 4092, 16336, 4, + 0, 0, 4096, 0, 0 }; + +const uint16_t filter_5tap_64p_117[165] = { + 16056, 2372, 2372, 16056, 0, + 16052, 2312, 2432, 16060, 0, + 16052, 2252, 2488, 16064, 0, + 16052, 2188, 2548, 16072, 0, + 16052, 2124, 2600, 16076, 0, + 16052, 2064, 2656, 16088, 0, + 16052, 2000, 2708, 16096, 0, + 16056, 1932, 2760, 16108, 0, + 16060, 1868, 2808, 16120, 0, + 16064, 1804, 2856, 16132, 0, + 16068, 1740, 2904, 16148, 16380, + 16076, 1676, 2948, 16164, 16380, + 16080, 1612, 2992, 16180, 16376, + 16088, 1544, 3032, 16200, 16372, + 16096, 1480, 3072, 16220, 16372, + 16104, 1420, 3108, 16244, 16368, + 16112, 1356, 3144, 16268, 16364, + 16120, 1292, 3180, 16292, 16360, + 16128, 1232, 3212, 16320, 16356, + 16136, 1168, 3240, 16344, 16352, + 16144, 1108, 3268, 16376, 16344, + 16156, 1048, 3292, 20, 16340, + 16164, 988, 3316, 52, 16332, + 16172, 932, 3336, 88, 16328, + 16184, 872, 3356, 124, 16320, + 16192, 816, 3372, 160, 16316, + 16204, 760, 3388, 196, 16308, + 16212, 708, 3400, 236, 16300, + 16220, 656, 3412, 276, 16292, + 16232, 604, 3420, 320, 16284, + 16240, 552, 3424, 364, 16276, + 16248, 504, 3428, 408, 16268, + 16256, 456, 3428, 456, 16256 }; + +const uint16_t filter_5tap_64p_150[165] = { + 16368, 2064, 2064, 16368, 0, + 16352, 2028, 2100, 16380, 16380, + 16340, 1996, 2132, 12, 16376, + 16328, 1960, 2168, 24, 16376, + 16316, 1924, 2204, 44, 16372, + 16308, 1888, 2236, 60, 16368, + 16296, 1848, 2268, 76, 16364, + 16288, 1812, 2300, 96, 16360, + 16280, 1772, 2328, 116, 16356, + 16272, 1736, 2360, 136, 16352, + 16268, 1696, 2388, 160, 16348, + 16260, 1656, 2416, 180, 16344, + 16256, 1616, 2440, 204, 16340, + 16248, 1576, 2464, 228, 16336, + 16244, 1536, 2492, 252, 16332, + 16240, 1496, 2512, 276, 16324, + 16240, 1456, 2536, 304, 16320, + 16236, 1416, 2556, 332, 16316, + 16232, 1376, 2576, 360, 16312, + 16232, 1336, 2592, 388, 16308, + 16232, 1296, 2612, 416, 16300, + 16232, 1256, 2628, 448, 16296, + 16232, 1216, 2640, 480, 16292, + 16232, 1172, 2652, 512, 16288, + 16232, 1132, 2664, 544, 16284, + 16232, 1092, 2676, 576, 16280, + 16236, 1056, 2684, 608, 16272, + 16236, 1016, 2692, 644, 16268, + 16240, 976, 2700, 680, 16264, + 16240, 936, 2704, 712, 16260, + 16244, 900, 2708, 748, 16256, + 16248, 860, 2708, 788, 16252, + 16248, 824, 2708, 824, 16248 }; + +const uint16_t filter_5tap_64p_183[165] = { + 228, 1816, 1816, 228, 0, + 216, 1792, 1836, 248, 16380, + 200, 1772, 1860, 264, 16376, + 184, 1748, 1884, 280, 16376, + 168, 1728, 1904, 300, 16372, + 156, 1704, 1928, 316, 16368, + 144, 1680, 1948, 336, 16364, + 128, 1656, 1968, 356, 16364, + 116, 1632, 1988, 376, 16360, + 104, 1604, 2008, 396, 16356, + 96, 1580, 2024, 416, 16356, + 84, 1556, 2044, 440, 16352, + 72, 1528, 2060, 460, 16348, + 64, 1504, 2076, 484, 16348, + 52, 1476, 2092, 504, 16344, + 44, 1448, 2104, 528, 16344, + 36, 1424, 2120, 552, 16340, + 28, 1396, 2132, 576, 16340, + 20, 1368, 2144, 600, 16340, + 12, 1340, 2156, 624, 16336, + 4, 1312, 2168, 652, 16336, + 0, 1284, 2180, 676, 16336, + 16376, 1256, 2188, 700, 16332, + 16372, 1228, 2196, 728, 16332, + 16368, 1200, 2204, 752, 16332, + 16364, 1172, 2212, 780, 16332, + 16356, 1144, 2216, 808, 16332, + 16352, 1116, 2220, 836, 16332, + 16352, 1084, 2224, 860, 16332, + 16348, 1056, 2228, 888, 16336, + 16344, 1028, 2232, 916, 16336, + 16340, 1000, 2232, 944, 16336, + 16340, 972, 2232, 972, 16340 }; + +const uint16_t filter_6tap_64p_upscale[198] = { + 0, 0, 4092, 0, 0, 0, + 12, 16332, 4092, 52, 16368, 0, + 24, 16280, 4088, 108, 16356, 0, + 36, 16236, 4080, 168, 16340, 0, + 44, 16188, 4064, 228, 16324, 0, + 56, 16148, 4052, 292, 16308, 0, + 64, 16108, 4032, 356, 16292, 4, + 72, 16072, 4008, 424, 16276, 4, + 80, 16036, 3980, 492, 16256, 4, + 88, 16004, 3952, 564, 16240, 8, + 96, 15972, 3920, 636, 16220, 8, + 100, 15944, 3884, 712, 16204, 12, + 108, 15916, 3844, 788, 16184, 16, + 112, 15896, 3800, 864, 16164, 20, + 116, 15872, 3756, 944, 16144, 20, + 120, 15852, 3708, 1024, 16124, 24, + 120, 15836, 3656, 1108, 16104, 28, + 124, 15824, 3600, 1192, 16084, 32, + 124, 15808, 3544, 1276, 16064, 36, + 124, 15800, 3484, 1360, 16044, 40, + 128, 15792, 3420, 1448, 16024, 44, + 128, 15784, 3352, 1536, 16004, 48, + 124, 15780, 3288, 1624, 15988, 52, + 124, 15776, 3216, 1712, 15968, 56, + 124, 15776, 3144, 1800, 15948, 64, + 120, 15776, 3068, 1888, 15932, 68, + 120, 15780, 2992, 1976, 15912, 72, + 116, 15784, 2916, 2064, 15896, 76, + 112, 15792, 2836, 2152, 15880, 80, + 108, 15796, 2752, 2244, 15868, 84, + 104, 15804, 2672, 2328, 15852, 88, + 104, 15816, 2588, 2416, 15840, 92, + 100, 15828, 2504, 2504, 15828, 100 }; + +const uint16_t filter_6tap_64p_117[198] = { + 16168, 476, 3568, 476, 16168, 0, + 16180, 428, 3564, 528, 16156, 0, + 16192, 376, 3556, 584, 16144, 4, + 16204, 328, 3548, 636, 16128, 4, + 16216, 280, 3540, 692, 16116, 8, + 16228, 232, 3524, 748, 16104, 12, + 16240, 188, 3512, 808, 16092, 12, + 16252, 148, 3492, 864, 16080, 16, + 16264, 104, 3472, 924, 16068, 16, + 16276, 64, 3452, 984, 16056, 20, + 16284, 28, 3428, 1044, 16048, 24, + 16296, 16376, 3400, 1108, 16036, 24, + 16304, 16340, 3372, 1168, 16024, 28, + 16316, 16304, 3340, 1232, 16016, 32, + 16324, 16272, 3308, 1296, 16004, 32, + 16332, 16244, 3272, 1360, 15996, 36, + 16344, 16212, 3236, 1424, 15988, 36, + 16352, 16188, 3200, 1488, 15980, 40, + 16360, 16160, 3160, 1552, 15972, 40, + 16368, 16136, 3116, 1616, 15964, 40, + 16372, 16112, 3072, 1680, 15956, 44, + 16380, 16092, 3028, 1744, 15952, 44, + 0, 16072, 2980, 1808, 15948, 44, + 8, 16052, 2932, 1872, 15944, 48, + 12, 16036, 2880, 1936, 15940, 48, + 16, 16020, 2828, 2000, 15936, 48, + 20, 16008, 2776, 2064, 15936, 48, + 24, 15996, 2724, 2128, 15936, 48, + 28, 15984, 2668, 2192, 15936, 48, + 32, 15972, 2612, 2252, 15940, 44, + 36, 15964, 2552, 2316, 15940, 44, + 40, 15956, 2496, 2376, 15944, 44, + 40, 15952, 2436, 2436, 15952, 40 }; + +const uint16_t filter_6tap_64p_150[198] = { + 16148, 920, 2724, 920, 16148, 0, + 16152, 880, 2724, 956, 16148, 0, + 16152, 844, 2720, 996, 16144, 0, + 16156, 804, 2716, 1032, 16144, 0, + 16156, 768, 2712, 1072, 16144, 0, + 16160, 732, 2708, 1112, 16144, 16380, + 16164, 696, 2700, 1152, 16144, 16380, + 16168, 660, 2692, 1192, 16148, 16380, + 16172, 628, 2684, 1232, 16148, 16380, + 16176, 592, 2672, 1272, 16152, 16376, + 16180, 560, 2660, 1312, 16152, 16376, + 16184, 524, 2648, 1348, 16156, 16376, + 16192, 492, 2632, 1388, 16160, 16372, + 16196, 460, 2616, 1428, 16164, 16372, + 16200, 432, 2600, 1468, 16168, 16368, + 16204, 400, 2584, 1508, 16176, 16364, + 16212, 368, 2564, 1548, 16180, 16364, + 16216, 340, 2544, 1588, 16188, 16360, + 16220, 312, 2524, 1628, 16196, 16356, + 16228, 284, 2504, 1668, 16204, 16356, + 16232, 256, 2480, 1704, 16212, 16352, + 16240, 232, 2456, 1744, 16224, 16348, + 16244, 204, 2432, 1780, 16232, 16344, + 16248, 180, 2408, 1820, 16244, 16340, + 16256, 156, 2380, 1856, 16256, 16336, + 16260, 132, 2352, 1896, 16268, 16332, + 16268, 108, 2324, 1932, 16280, 16328, + 16272, 88, 2296, 1968, 16292, 16324, + 16276, 64, 2268, 2004, 16308, 16320, + 16284, 44, 2236, 2036, 16324, 16312, + 16288, 24, 2204, 2072, 16340, 16308, + 16292, 8, 2172, 2108, 16356, 16304, + 16300, 16372, 2140, 2140, 16372, 16300 }; + +const uint16_t filter_6tap_64p_183[198] = { + 16296, 1032, 2196, 1032, 16296, 0, + 16292, 1004, 2200, 1060, 16304, 16380, + 16288, 976, 2200, 1088, 16308, 16380, + 16284, 952, 2196, 1116, 16312, 16376, + 16284, 924, 2196, 1144, 16320, 16376, + 16280, 900, 2192, 1172, 16324, 16372, + 16276, 872, 2192, 1200, 16332, 16368, + 16276, 848, 2188, 1228, 16340, 16368, + 16272, 820, 2180, 1256, 16348, 16364, + 16272, 796, 2176, 1280, 16356, 16360, + 16268, 768, 2168, 1308, 16364, 16360, + 16268, 744, 2164, 1336, 16372, 16356, + 16268, 716, 2156, 1364, 16380, 16352, + 16264, 692, 2148, 1392, 4, 16352, + 16264, 668, 2136, 1420, 16, 16348, + 16264, 644, 2128, 1448, 28, 16344, + 16264, 620, 2116, 1472, 36, 16340, + 16264, 596, 2108, 1500, 48, 16340, + 16268, 572, 2096, 1524, 60, 16336, + 16268, 548, 2080, 1552, 72, 16332, + 16268, 524, 2068, 1576, 88, 16328, + 16268, 504, 2056, 1604, 100, 16324, + 16272, 480, 2040, 1628, 112, 16324, + 16272, 456, 2024, 1652, 128, 16320, + 16272, 436, 2008, 1680, 144, 16316, + 16276, 416, 1992, 1704, 156, 16312, + 16276, 392, 1976, 1724, 172, 16308, + 16280, 372, 1956, 1748, 188, 16308, + 16280, 352, 1940, 1772, 204, 16304, + 16284, 332, 1920, 1796, 224, 16300, + 16288, 312, 1900, 1816, 240, 16296, + 16288, 296, 1880, 1840, 256, 16296, + 16292, 276, 1860, 1860, 276, 16292 }; + +const uint16_t filter_7tap_64p_upscale[231] = { + 176, 15760, 2488, 2488, 15760, 176, 0, + 172, 15772, 2404, 2572, 15752, 180, 16380, + 168, 15784, 2324, 2656, 15740, 184, 16380, + 164, 15800, 2240, 2736, 15732, 188, 16376, + 160, 15812, 2152, 2816, 15728, 192, 16376, + 152, 15828, 2068, 2896, 15724, 192, 16376, + 148, 15848, 1984, 2972, 15720, 196, 16372, + 140, 15864, 1896, 3048, 15720, 196, 16372, + 136, 15884, 1812, 3124, 15720, 196, 16368, + 128, 15900, 1724, 3196, 15720, 196, 16368, + 120, 15920, 1640, 3268, 15724, 196, 16368, + 116, 15940, 1552, 3336, 15732, 196, 16364, + 108, 15964, 1468, 3400, 15740, 196, 16364, + 104, 15984, 1384, 3464, 15748, 192, 16364, + 96, 16004, 1300, 3524, 15760, 188, 16364, + 88, 16028, 1216, 3584, 15776, 184, 16364, + 84, 16048, 1132, 3640, 15792, 180, 16360, + 76, 16072, 1048, 3692, 15812, 176, 16360, + 68, 16092, 968, 3744, 15832, 168, 16360, + 64, 16116, 888, 3788, 15856, 160, 16360, + 56, 16140, 812, 3832, 15884, 152, 16360, + 52, 16160, 732, 3876, 15912, 144, 16360, + 44, 16184, 656, 3912, 15944, 136, 16364, + 40, 16204, 584, 3944, 15976, 124, 16364, + 32, 16228, 512, 3976, 16012, 116, 16364, + 28, 16248, 440, 4004, 16048, 104, 16364, + 24, 16268, 372, 4028, 16092, 88, 16368, + 20, 16288, 304, 4048, 16132, 76, 16368, + 12, 16308, 240, 4064, 16180, 60, 16372, + 8, 16328, 176, 4076, 16228, 48, 16372, + 4, 16348, 112, 4088, 16276, 32, 16376, + 0, 16364, 56, 4092, 16328, 16, 16380, + 0, 0, 0, 4096, 0, 0, 0 }; + +const uint16_t filter_7tap_64p_117[231] = { + 92, 15868, 2464, 2464, 15868, 92, 0, + 96, 15864, 2404, 2528, 15876, 88, 0, + 100, 15860, 2344, 2584, 15884, 84, 0, + 104, 15856, 2280, 2644, 15892, 76, 0, + 108, 15852, 2216, 2700, 15904, 72, 0, + 108, 15852, 2152, 2756, 15916, 64, 0, + 112, 15852, 2088, 2812, 15932, 60, 0, + 112, 15852, 2024, 2864, 15948, 52, 0, + 112, 15856, 1960, 2916, 15964, 44, 0, + 116, 15860, 1892, 2964, 15984, 36, 0, + 116, 15864, 1828, 3016, 16004, 24, 4, + 116, 15868, 1760, 3060, 16024, 16, 4, + 116, 15876, 1696, 3108, 16048, 8, 8, + 116, 15884, 1628, 3152, 16072, 16380, 8, + 112, 15892, 1564, 3192, 16100, 16372, 8, + 112, 15900, 1496, 3232, 16124, 16360, 12, + 112, 15908, 1428, 3268, 16156, 16348, 12, + 108, 15920, 1364, 3304, 16188, 16336, 16, + 108, 15928, 1300, 3340, 16220, 16324, 20, + 104, 15940, 1232, 3372, 16252, 16312, 20, + 104, 15952, 1168, 3400, 16288, 16300, 24, + 100, 15964, 1104, 3428, 16328, 16284, 28, + 96, 15980, 1040, 3452, 16364, 16272, 28, + 96, 15992, 976, 3476, 20, 16256, 32, + 92, 16004, 916, 3496, 64, 16244, 36, + 88, 16020, 856, 3516, 108, 16228, 40, + 84, 16032, 792, 3532, 152, 16216, 44, + 80, 16048, 732, 3544, 200, 16200, 48, + 80, 16064, 676, 3556, 248, 16184, 48, + 76, 16080, 616, 3564, 296, 16168, 52, + 72, 16092, 560, 3568, 344, 16156, 56, + 68, 16108, 504, 3572, 396, 16140, 60, + 64, 16124, 452, 3576, 452, 16124, 64 }; + +const uint16_t filter_7tap_64p_150[231] = { + 16224, 16380, 2208, 2208, 16380, 16224, 0, + 16232, 16360, 2172, 2236, 16, 16216, 0, + 16236, 16340, 2140, 2268, 40, 16212, 0, + 16244, 16324, 2104, 2296, 60, 16204, 4, + 16252, 16304, 2072, 2324, 84, 16196, 4, + 16256, 16288, 2036, 2352, 108, 16192, 4, + 16264, 16268, 2000, 2380, 132, 16184, 8, + 16272, 16252, 1960, 2408, 160, 16176, 8, + 16276, 16240, 1924, 2432, 184, 16172, 8, + 16284, 16224, 1888, 2456, 212, 16164, 8, + 16288, 16212, 1848, 2480, 240, 16160, 12, + 16296, 16196, 1812, 2500, 268, 16152, 12, + 16300, 16184, 1772, 2524, 296, 16144, 12, + 16308, 16172, 1736, 2544, 324, 16140, 12, + 16312, 16164, 1696, 2564, 356, 16136, 12, + 16320, 16152, 1656, 2584, 388, 16128, 12, + 16324, 16144, 1616, 2600, 416, 16124, 12, + 16328, 16136, 1576, 2616, 448, 16116, 12, + 16332, 16128, 1536, 2632, 480, 16112, 12, + 16340, 16120, 1496, 2648, 516, 16108, 12, + 16344, 16112, 1456, 2660, 548, 16104, 12, + 16348, 16104, 1416, 2672, 580, 16100, 12, + 16352, 16100, 1376, 2684, 616, 16096, 12, + 16356, 16096, 1336, 2696, 652, 16092, 12, + 16360, 16092, 1296, 2704, 688, 16088, 12, + 16364, 16088, 1256, 2712, 720, 16084, 12, + 16368, 16084, 1220, 2720, 760, 16084, 8, + 16368, 16080, 1180, 2724, 796, 16080, 8, + 16372, 16080, 1140, 2732, 832, 16080, 8, + 16376, 16076, 1100, 2732, 868, 16076, 4, + 16380, 16076, 1060, 2736, 908, 16076, 4, + 16380, 16076, 1020, 2740, 944, 16076, 0, + 0, 16076, 984, 2740, 984, 16076, 0 }; + +const uint16_t filter_7tap_64p_183[231] = { + 16216, 324, 1884, 1884, 324, 16216, 0, + 16220, 304, 1864, 1904, 344, 16216, 0, + 16224, 284, 1844, 1924, 364, 16216, 0, + 16224, 264, 1824, 1944, 384, 16212, 16380, + 16228, 248, 1804, 1960, 408, 16212, 16380, + 16228, 228, 1784, 1976, 428, 16208, 16380, + 16232, 212, 1760, 1996, 452, 16208, 16380, + 16236, 192, 1740, 2012, 472, 16208, 16376, + 16240, 176, 1716, 2028, 496, 16208, 16376, + 16240, 160, 1696, 2040, 516, 16208, 16376, + 16244, 144, 1672, 2056, 540, 16208, 16376, + 16248, 128, 1648, 2068, 564, 16208, 16372, + 16252, 112, 1624, 2084, 588, 16208, 16372, + 16256, 96, 1600, 2096, 612, 16208, 16368, + 16256, 84, 1576, 2108, 636, 16208, 16368, + 16260, 68, 1552, 2120, 660, 16208, 16368, + 16264, 56, 1524, 2132, 684, 16212, 16364, + 16268, 40, 1500, 2140, 712, 16212, 16364, + 16272, 28, 1476, 2152, 736, 16216, 16360, + 16276, 16, 1448, 2160, 760, 16216, 16356, + 16280, 4, 1424, 2168, 788, 16220, 16356, + 16284, 16376, 1396, 2176, 812, 16224, 16352, + 16288, 16368, 1372, 2184, 840, 16224, 16352, + 16292, 16356, 1344, 2188, 864, 16228, 16348, + 16292, 16344, 1320, 2196, 892, 16232, 16344, + 16296, 16336, 1292, 2200, 916, 16236, 16344, + 16300, 16324, 1264, 2204, 944, 16240, 16340, + 16304, 16316, 1240, 2208, 972, 16248, 16336, + 16308, 16308, 1212, 2212, 996, 16252, 16332, + 16312, 16300, 1184, 2216, 1024, 16256, 16332, + 16316, 16292, 1160, 2216, 1052, 16264, 16328, + 16316, 16284, 1132, 2216, 1076, 16268, 16324, + 16320, 16276, 1104, 2216, 1104, 16276, 16320 }; + +const uint16_t filter_8tap_64p_upscale[264] = { + 0, 0, 0, 4096, 0, 0, 0, 0, + 16376, 20, 16328, 4092, 56, 16364, 4, 0, + 16372, 36, 16272, 4088, 116, 16340, 12, 0, + 16364, 56, 16220, 4080, 180, 16320, 20, 0, + 16360, 76, 16172, 4064, 244, 16296, 24, 16380, + 16356, 92, 16124, 4048, 312, 16276, 32, 16380, + 16352, 108, 16080, 4032, 380, 16252, 40, 16380, + 16344, 124, 16036, 4008, 452, 16228, 48, 16380, + 16340, 136, 15996, 3980, 524, 16204, 56, 16380, + 16340, 152, 15956, 3952, 600, 16180, 64, 16376, + 16336, 164, 15920, 3920, 672, 16156, 76, 16376, + 16332, 176, 15888, 3884, 752, 16132, 84, 16376, + 16328, 188, 15860, 3844, 828, 16104, 92, 16372, + 16328, 200, 15828, 3800, 908, 16080, 100, 16372, + 16324, 208, 15804, 3756, 992, 16056, 108, 16372, + 16324, 216, 15780, 3708, 1072, 16032, 120, 16368, + 16320, 224, 15760, 3656, 1156, 16008, 128, 16368, + 16320, 232, 15740, 3604, 1240, 15984, 136, 16364, + 16320, 240, 15724, 3548, 1324, 15960, 144, 16364, + 16320, 244, 15708, 3488, 1412, 15936, 152, 16360, + 16320, 248, 15696, 3428, 1496, 15912, 160, 16360, + 16320, 252, 15688, 3364, 1584, 15892, 172, 16356, + 16320, 256, 15680, 3296, 1672, 15868, 180, 16352, + 16320, 256, 15672, 3228, 1756, 15848, 188, 16352, + 16320, 256, 15668, 3156, 1844, 15828, 192, 16348, + 16320, 260, 15668, 3084, 1932, 15808, 200, 16348, + 16320, 256, 15668, 3012, 2020, 15792, 208, 16344, + 16324, 256, 15668, 2936, 2108, 15772, 216, 16344, + 16324, 256, 15672, 2856, 2192, 15756, 220, 16340, + 16324, 252, 15676, 2776, 2280, 15740, 228, 16336, + 16328, 252, 15684, 2696, 2364, 15728, 232, 16336, + 16328, 248, 15692, 2616, 2448, 15716, 240, 16332, + 16332, 244, 15704, 2532, 2532, 15704, 244, 16332 }; + +const uint16_t filter_8tap_64p_117[264] = { + 116, 16100, 428, 3564, 428, 16100, 116, 0, + 112, 16116, 376, 3564, 484, 16084, 120, 16380, + 104, 16136, 324, 3560, 540, 16064, 124, 16380, + 100, 16152, 272, 3556, 600, 16048, 128, 16380, + 96, 16168, 220, 3548, 656, 16032, 136, 16376, + 88, 16188, 172, 3540, 716, 16016, 140, 16376, + 84, 16204, 124, 3528, 780, 16000, 144, 16376, + 80, 16220, 76, 3512, 840, 15984, 148, 16372, + 76, 16236, 32, 3496, 904, 15968, 152, 16372, + 68, 16252, 16376, 3480, 968, 15952, 156, 16372, + 64, 16268, 16332, 3456, 1032, 15936, 160, 16372, + 60, 16284, 16292, 3432, 1096, 15920, 164, 16368, + 56, 16300, 16252, 3408, 1164, 15908, 164, 16368, + 48, 16316, 16216, 3380, 1228, 15892, 168, 16368, + 44, 16332, 16180, 3348, 1296, 15880, 168, 16368, + 40, 16348, 16148, 3316, 1364, 15868, 172, 16364, + 36, 16360, 16116, 3284, 1428, 15856, 172, 16364, + 32, 16376, 16084, 3248, 1496, 15848, 176, 16364, + 28, 4, 16052, 3208, 1564, 15836, 176, 16364, + 24, 16, 16028, 3168, 1632, 15828, 176, 16364, + 20, 28, 16000, 3124, 1700, 15820, 176, 16364, + 16, 40, 15976, 3080, 1768, 15812, 176, 16364, + 12, 52, 15952, 3036, 1836, 15808, 176, 16364, + 8, 64, 15932, 2988, 1904, 15800, 176, 16364, + 4, 76, 15912, 2940, 1972, 15800, 172, 16364, + 4, 84, 15892, 2888, 2040, 15796, 172, 16364, + 0, 96, 15876, 2836, 2104, 15792, 168, 16364, + 16380, 104, 15864, 2780, 2172, 15792, 164, 16364, + 16380, 112, 15848, 2724, 2236, 15792, 160, 16364, + 16376, 120, 15836, 2668, 2300, 15796, 156, 16368, + 16376, 128, 15828, 2608, 2364, 15800, 152, 16368, + 16372, 136, 15816, 2548, 2428, 15804, 148, 16368, + 16372, 140, 15812, 2488, 2488, 15812, 140, 16372 }; + +const uint16_t filter_8tap_64p_150[264] = { + 16380, 16020, 1032, 2756, 1032, 16020, 16380, 0, + 0, 16020, 992, 2756, 1068, 16024, 16376, 0, + 4, 16020, 952, 2752, 1108, 16024, 16372, 0, + 8, 16020, 916, 2748, 1148, 16028, 16368, 0, + 12, 16020, 876, 2744, 1184, 16032, 16364, 4, + 16, 16020, 840, 2740, 1224, 16036, 16356, 4, + 20, 16024, 800, 2732, 1264, 16040, 16352, 4, + 20, 16024, 764, 2724, 1304, 16044, 16348, 8, + 24, 16028, 728, 2716, 1344, 16052, 16340, 8, + 28, 16028, 692, 2704, 1380, 16056, 16336, 12, + 28, 16032, 656, 2696, 1420, 16064, 16328, 12, + 32, 16036, 620, 2684, 1460, 16072, 16324, 12, + 36, 16040, 584, 2668, 1500, 16080, 16316, 16, + 36, 16044, 548, 2656, 1536, 16088, 16308, 16, + 36, 16048, 516, 2640, 1576, 16096, 16304, 20, + 40, 16052, 480, 2624, 1612, 16108, 16296, 20, + 40, 16060, 448, 2608, 1652, 16120, 16288, 20, + 44, 16064, 416, 2588, 1692, 16132, 16280, 24, + 44, 16068, 384, 2568, 1728, 16144, 16276, 24, + 44, 16076, 352, 2548, 1764, 16156, 16268, 28, + 44, 16080, 320, 2528, 1804, 16168, 16260, 28, + 44, 16088, 292, 2508, 1840, 16184, 16252, 28, + 44, 16096, 264, 2484, 1876, 16200, 16244, 32, + 48, 16100, 232, 2460, 1912, 16216, 16236, 32, + 48, 16108, 204, 2436, 1948, 16232, 16228, 32, + 48, 16116, 176, 2412, 1980, 16248, 16220, 36, + 48, 16124, 152, 2384, 2016, 16264, 16216, 36, + 44, 16128, 124, 2356, 2052, 16284, 16208, 36, + 44, 16136, 100, 2328, 2084, 16304, 16200, 40, + 44, 16144, 72, 2300, 2116, 16324, 16192, 40, + 44, 16152, 48, 2272, 2148, 16344, 16184, 40, + 44, 16160, 24, 2244, 2180, 16364, 16176, 40, + 44, 16168, 4, 2212, 2212, 4, 16168, 44 }; + +const uint16_t filter_8tap_64p_183[264] = { + 16264, 16264, 1164, 2244, 1164, 16264, 16264, 0, + 16268, 16256, 1136, 2240, 1188, 16272, 16260, 0, + 16272, 16248, 1108, 2240, 1216, 16280, 16256, 0, + 16276, 16240, 1080, 2236, 1240, 16292, 16252, 0, + 16280, 16232, 1056, 2236, 1268, 16300, 16248, 0, + 16284, 16224, 1028, 2232, 1292, 16312, 16244, 0, + 16288, 16216, 1000, 2228, 1320, 16324, 16240, 0, + 16292, 16212, 976, 2224, 1344, 16336, 16236, 0, + 16296, 16204, 948, 2220, 1372, 16348, 16232, 0, + 16300, 16200, 920, 2212, 1396, 16360, 16228, 4, + 16304, 16196, 896, 2204, 1424, 16372, 16224, 4, + 16308, 16188, 868, 2200, 1448, 0, 16220, 4, + 16312, 16184, 844, 2192, 1472, 12, 16216, 4, + 16316, 16180, 816, 2184, 1500, 28, 16212, 4, + 16320, 16176, 792, 2172, 1524, 40, 16208, 4, + 16324, 16172, 764, 2164, 1548, 56, 16204, 0, + 16328, 16172, 740, 2156, 1572, 72, 16200, 0, + 16328, 16168, 712, 2144, 1596, 88, 16196, 0, + 16332, 16164, 688, 2132, 1620, 100, 16192, 0, + 16336, 16164, 664, 2120, 1644, 120, 16192, 0, + 16340, 16160, 640, 2108, 1668, 136, 16188, 0, + 16344, 16160, 616, 2096, 1688, 152, 16184, 0, + 16344, 16160, 592, 2080, 1712, 168, 16180, 0, + 16348, 16156, 568, 2068, 1736, 188, 16176, 16380, + 16352, 16156, 544, 2052, 1756, 204, 16176, 16380, + 16352, 16156, 520, 2036, 1780, 224, 16172, 16380, + 16356, 16156, 496, 2024, 1800, 244, 16172, 16380, + 16360, 16156, 472, 2008, 1820, 260, 16168, 16376, + 16360, 16156, 452, 1988, 1840, 280, 16164, 16376, + 16364, 16156, 428, 1972, 1860, 300, 16164, 16376, + 16364, 16156, 408, 1956, 1880, 320, 16164, 16372, + 16368, 16160, 384, 1936, 1900, 344, 16160, 16372, + 16368, 16160, 364, 1920, 1920, 364, 16160, 16368 }; + const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio) { if (ratio.value < dal_fixed31_32_one.value) @@ -499,3 +1059,51 @@ const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio) else return filter_4tap_64p_183; } + +const uint16_t *get_filter_5tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_5tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_5tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_5tap_64p_150; + else + return filter_5tap_64p_183; +} + +const uint16_t *get_filter_6tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_6tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_6tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_6tap_64p_150; + else + return filter_6tap_64p_183; +} + +const uint16_t *get_filter_7tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_7tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_7tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_7tap_64p_150; + else + return filter_7tap_64p_183; +} + +const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio) +{ + if (ratio.value < dal_fixed31_32_one.value) + return filter_8tap_64p_upscale; + else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value) + return filter_8tap_64p_117; + else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value) + return filter_8tap_64p_150; + else + return filter_8tap_64p_183; +} diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index a510d3fe48ec..9c5cb0ee4243 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -186,5 +186,9 @@ const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio); const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio); const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_5tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_6tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_7tap_64p(struct fixed31_32 ratio); +const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio); #endif -- GitLab From 1781958ff41b28b3cd7b4a2ed691c932031c5515 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Thu, 23 Feb 2017 16:10:43 -0500 Subject: [PATCH 0276/2898] drm/amd/display: Surface Validation Fixes + Audio Mask 1. dc: Adding missing mask for audio register DCCG_AUDIO_DTO_SOURCE 2. Changing the surface validation to check the limits of the clip rect instead of the source rect. Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.h | 1 + drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index b98ee2d2a9c7..0dc5ff137c7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -48,6 +48,7 @@ #define AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)\ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO2_USE_512FBR_DTO, mask_sh),\ SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index cd3942df70a7..80b2359a3cb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1009,10 +1009,10 @@ static bool dce110_validate_surface_sets( if (set[i].surface_count > 2) return false; - if (set[i].surfaces[0]->src_rect.width - < set[i].stream->src.width - || set[i].surfaces[0]->src_rect.height - < set[i].stream->src.height) + if (set[i].surfaces[0]->clip_rect.width + > set[i].stream->src.width + || set[i].surfaces[0]->clip_rect.height + > set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 526c106f6ebf..ce6c69fd1041 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -975,9 +975,9 @@ static bool dce112_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - < set[i].stream->src.width + > set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - < set[i].stream->src.height) + > set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 272c7fc31406..fbbdd0ee2d4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -805,9 +805,9 @@ static bool dce80_validate_surface_sets( return false; if (set[i].surfaces[0]->clip_rect.width - != set[i].stream->src.width + > set[i].stream->src.width || set[i].surfaces[0]->clip_rect.height - != set[i].stream->src.height) + > set[i].stream->src.height) return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) -- GitLab From 0d70570f712e2db49396eaef61790bac2a08ec1c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 24 Feb 2017 11:21:11 -0500 Subject: [PATCH 0277/2898] drm/amd/display: Fix warnings in amdgpu_dm Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index dc0d8533521f..862bbd745bb9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -962,7 +962,7 @@ static void decide_crtc_timing_for_drm_display_mode( } static struct dc_stream *create_stream_for_sink( - const struct amdgpu_connector *aconnector, + struct amdgpu_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { -- GitLab From 648013696767f0266aa7bd44407786a99f7a7910 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 24 Feb 2017 11:31:23 -0500 Subject: [PATCH 0278/2898] drm/amd/display: Fix warnings in DC Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 -- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 1 - .../gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6516c275e0c7..e0d9572768cb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1068,7 +1068,6 @@ bool dc_pre_update_surfaces_to_stream( int prev_disp_clk = core_dc->current_context->dispclk_khz; struct dc_stream_status *stream_status = NULL; struct validate_context *context; - struct validate_context *temp_context; bool ret = true; pre_surface_trace(dc, new_surfaces, new_surface_count); @@ -1425,7 +1424,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL) { for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct core_stream *stream = pipe_ctx->stream; if (pipe_ctx->surface != surface) continue; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 21fedd447bd1..943895faee49 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -121,7 +121,7 @@ const struct dc_surface_status *dc_surface_get_status( const struct dc_surface *dc_surface) { struct dc_surface_status *surface_status; - struct core_surface *core_surface = DC_SURFACE_TO_CORE(dc_surface);; + struct core_surface *core_surface = DC_SURFACE_TO_CORE(dc_surface); struct core_dc *core_dc; int i; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 7005ebb28d46..45a3079c0973 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -292,7 +292,6 @@ static void dce_abm_init(struct abm *abm) static bool dce_abm_set_level(struct abm *abm, uint32_t level) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); - struct dc_context *ctx = abm_dce->base.ctx; REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 682a3de7ba48..c95b69446ced 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -74,7 +74,6 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg) static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg) { - struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t addr = mmCRTCV_BLANK_CONTROL; uint32_t value = dm_read_reg(tg->ctx, addr); -- GitLab From 45209ef7197bd4b5e7e224ff46fa9a3eca25c3bd Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 24 Feb 2017 14:19:40 -0500 Subject: [PATCH 0279/2898] drm/amd/display: remove apply_clk_constraints, used validate_bandwidth universally Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 50 ++++++++++++------- .../amd/display/dc/dce100/dce100_resource.c | 10 ++-- .../amd/display/dc/dce110/dce110_resource.c | 18 +++---- .../amd/display/dc/dce112/dce112_resource.c | 18 +++---- .../amd/display/dc/dce112/dce112_resource.h | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 4 +- .../gpu/drm/amd/display/dc/inc/core_status.h | 1 - .../gpu/drm/amd/display/dc/inc/core_types.h | 6 +-- 8 files changed, 59 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e0d9572768cb..da0f72071ef5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1144,12 +1144,11 @@ bool dc_pre_update_surfaces_to_stream( } } - if (core_dc->res_pool->funcs->validate_bandwidth) - if (core_dc->res_pool->funcs->validate_bandwidth(core_dc, context) != DC_OK) { - BREAK_TO_DEBUGGER(); - ret = false; - goto unexpected_fail; - } + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + BREAK_TO_DEBUGGER(); + ret = false; + goto unexpected_fail; + } if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) && prev_disp_clk < context->dispclk_khz) { @@ -1184,28 +1183,36 @@ bool dc_pre_update_surfaces_to_stream( bool dc_post_update_surfaces_to_stream(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct validate_context *context = dm_alloc(sizeof(struct validate_context)); + + if (!context) { + dm_error("%s: failed to create validate ctx\n", __func__); + return false; + } + resource_validate_ctx_copy_construct(core_dc->current_context, context); post_surface_trace(dc); - for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; i++) - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == NULL) { - core_dc->current_context->res_ctx.pipe_ctx[i].pipe_idx = i; + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( - core_dc, &core_dc->current_context->res_ctx.pipe_ctx[i]); - } - if (core_dc->res_pool->funcs->validate_bandwidth) - if (core_dc->res_pool->funcs->validate_bandwidth( - core_dc, core_dc->current_context) != DC_OK) { - BREAK_TO_DEBUGGER(); - return false; + core_dc, &context->res_ctx.pipe_ctx[i]); } + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + BREAK_TO_DEBUGGER(); + return false; + } core_dc->hwss.set_bandwidth(core_dc); - pplib_apply_display_requirements( - core_dc, core_dc->current_context, &core_dc->current_context->pp_display_cfg); + /*TODO: dce specific*/ + pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); + + resource_validate_ctx_destruct(core_dc->current_context); + core_dc->current_context = context; return true; } @@ -1472,6 +1479,11 @@ void dc_update_surfaces_for_stream(struct dc *dc, *(updates[i].hdr_static_metadata); } + if (update_type == UPDATE_TYPE_FULL && + !core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + BREAK_TO_DEBUGGER(); + return; + } if (!surface_count) /* reset */ core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9ed7c06132fe..fc85efafb104 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -765,14 +765,14 @@ static enum dc_status validate_mapped_resource( return DC_OK; } -enum dc_status dce100_validate_bandwidth( +bool dce100_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ context->dispclk_khz = 681000; - return DC_OK; + return false; } static bool dce100_validate_surface_sets( @@ -840,7 +840,8 @@ enum dc_status dce100_validate_with_context( result = resource_build_scaling_params_for_context(dc, context); if (result == DC_OK) - result = dce100_validate_bandwidth(dc, context); + if (!dce100_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } @@ -873,7 +874,8 @@ enum dc_status dce100_validate_guaranteed( } if (result == DC_OK) - result = dce100_validate_bandwidth(dc, context); + if (!dce100_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 80b2359a3cb4..b9d0b5eeca13 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -912,30 +912,28 @@ static enum dc_status validate_mapped_resource( return DC_OK; } -enum dc_status dce110_validate_bandwidth( +bool dce110_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { - enum dc_status result = DC_ERROR_UNEXPECTED; + bool result = false; dm_logger_write( dc->ctx->logger, LOG_BANDWIDTH_CALCS, "%s: start", __func__); - if (!bw_calcs( + if (bw_calcs( dc->ctx, &dc->bw_dceip, &dc->bw_vbios, context->res_ctx.pipe_ctx, context->res_ctx.pool->pipe_count, &context->bw_results)) - result = DC_FAIL_BANDWIDTH_VALIDATE; - else - result = DC_OK; + result = true; context->dispclk_khz = context->bw_results.dispclk_khz; - if (result == DC_FAIL_BANDWIDTH_VALIDATE) + if (!result) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: %dx%d@%d Bandwidth validation failed!\n", __func__, @@ -1073,7 +1071,8 @@ enum dc_status dce110_validate_with_context( result = resource_build_scaling_params_for_context(dc, context); if (result == DC_OK) - result = dce110_validate_bandwidth(dc, context); + if (!dce110_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } @@ -1106,7 +1105,8 @@ enum dc_status dce110_validate_guaranteed( } if (result == DC_OK) - result = dce110_validate_bandwidth(dc, context); + if (!dce110_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index ce6c69fd1041..32aa1b5bf1f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -836,30 +836,28 @@ static enum dc_status validate_mapped_resource( return DC_OK; } -enum dc_status dce112_validate_bandwidth( +bool dce112_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { - enum dc_status result = DC_ERROR_UNEXPECTED; + bool result = false; dm_logger_write( dc->ctx->logger, LOG_BANDWIDTH_CALCS, "%s: start", __func__); - if (!bw_calcs( + if (bw_calcs( dc->ctx, &dc->bw_dceip, &dc->bw_vbios, context->res_ctx.pipe_ctx, context->res_ctx.pool->pipe_count, &context->bw_results)) - result = DC_FAIL_BANDWIDTH_VALIDATE; - else - result = DC_OK; + result = true; context->dispclk_khz = context->bw_results.dispclk_khz; - if (result == DC_FAIL_BANDWIDTH_VALIDATE) + if (!result) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: Bandwidth validation failed!", __func__); @@ -1026,7 +1024,8 @@ enum dc_status dce112_validate_with_context( result = resource_build_scaling_params_for_context(dc, context); if (result == DC_OK) - result = dce112_validate_bandwidth(dc, context); + if (!dce112_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } @@ -1059,7 +1058,8 @@ enum dc_status dce112_validate_guaranteed( } if (result == DC_OK) - result = dce112_validate_bandwidth(dc, context); + if (!dce112_validate_bandwidth(dc, context)) + result = DC_FAIL_BANDWIDTH_VALIDATE; return result; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index faa8c45a3544..dc842aace766 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -46,7 +46,7 @@ enum dc_status dce112_validate_guaranteed( const struct dc_stream *dc_stream, struct validate_context *context); -enum dc_status dce112_validate_bandwidth( +bool dce112_validate_bandwidth( const struct core_dc *dc, struct validate_context *context); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index fbbdd0ee2d4c..a3e8182885b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -780,7 +780,7 @@ static enum dc_status validate_mapped_resource( return DC_OK; } -enum dc_status dce80_validate_bandwidth( +bool dce80_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { @@ -788,7 +788,7 @@ enum dc_status dce80_validate_bandwidth( context->dispclk_khz = 681000; context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; - return DC_OK; + return true; } static bool dce80_validate_surface_sets( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 23d52aea55dd..128617dabc4a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -41,7 +41,6 @@ enum dc_status { DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ DC_FAIL_SCALING = 13, - DC_FAIL_CLK_CONSTRAINT = 14, DC_ERROR_UNEXPECTED = -1 }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 124df6795b34..e8fe333c5918 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -207,11 +207,7 @@ struct resource_funcs { const struct dc_stream *stream, struct validate_context *context); - enum dc_status (*validate_bandwidth)( - const struct core_dc *dc, - struct validate_context *context); - - struct validate_context *(*apply_clk_constraints)( + bool (*validate_bandwidth)( const struct core_dc *dc, struct validate_context *context); -- GitLab From cf43759306002e29f025344504dc680a9a0b3ac8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 22 Feb 2017 17:52:22 -0500 Subject: [PATCH 0280/2898] drm/amd/display: bandwidth update fix Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 173 +---------- .../display/dc/dce100/dce100_hw_sequencer.c | 15 +- .../display/dc/dce110/dce110_hw_sequencer.c | 279 ++++++++++-------- .../amd/display/dc/dce80/dce80_hw_sequencer.c | 16 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 9 +- 5 files changed, 179 insertions(+), 313 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index da0f72071ef5..0ec2c4f39735 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -795,159 +795,6 @@ static bool streams_changed( return false; } -static void fill_display_configs( - const struct validate_context *context, - struct dm_pp_display_configuration *pp_display_cfg) -{ - int j; - int num_cfgs = 0; - - for (j = 0; j < context->stream_count; j++) { - int k; - - const struct core_stream *stream = context->streams[j]; - struct dm_pp_single_disp_config *cfg = - &pp_display_cfg->disp_configs[num_cfgs]; - const struct pipe_ctx *pipe_ctx = NULL; - - for (k = 0; k < MAX_PIPES; k++) - if (stream == context->res_ctx.pipe_ctx[k].stream) { - pipe_ctx = &context->res_ctx.pipe_ctx[k]; - break; - } - - ASSERT(pipe_ctx != NULL); - - num_cfgs++; - cfg->signal = pipe_ctx->stream->signal; - cfg->pipe_idx = pipe_ctx->pipe_idx; - cfg->src_height = stream->public.src.height; - cfg->src_width = stream->public.src.width; - cfg->ddi_channel_mapping = - stream->sink->link->ddi_channel_mapping.raw; - cfg->transmitter = - stream->sink->link->link_enc->transmitter; - cfg->link_settings.lane_count = - stream->sink->link->public.cur_link_settings.lane_count; - cfg->link_settings.link_rate = - stream->sink->link->public.cur_link_settings.link_rate; - cfg->link_settings.link_spread = - stream->sink->link->public.cur_link_settings.link_spread; - cfg->sym_clock = stream->phy_pix_clk; - /* Round v_refresh*/ - cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; - cfg->v_refresh /= stream->public.timing.h_total; - cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) - / stream->public.timing.v_total; - } - - pp_display_cfg->display_count = num_cfgs; -} - -static uint32_t get_min_vblank_time_us(const struct validate_context *context) -{ - uint8_t j; - uint32_t min_vertical_blank_time = -1; - - for (j = 0; j < context->stream_count; j++) { - const struct dc_stream *stream = &context->streams[j]->public; - uint32_t vertical_blank_in_pixels = 0; - uint32_t vertical_blank_time = 0; - - vertical_blank_in_pixels = stream->timing.h_total * - (stream->timing.v_total - - stream->timing.v_addressable); - - vertical_blank_time = vertical_blank_in_pixels - * 1000 / stream->timing.pix_clk_khz; - - if (min_vertical_blank_time > vertical_blank_time) - min_vertical_blank_time = vertical_blank_time; - } - - return min_vertical_blank_time; -} - -static int determine_sclk_from_bounding_box( - const struct core_dc *dc, - int required_sclk) -{ - int i; - - /* - * Some asics do not give us sclk levels, so we just report the actual - * required sclk - */ - if (dc->sclk_lvls.num_levels == 0) - return required_sclk; - - for (i = 0; i < dc->sclk_lvls.num_levels; i++) { - if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) - return dc->sclk_lvls.clocks_in_khz[i]; - } - /* - * even maximum level could not satisfy requirement, this - * is unexpected at this stage, should have been caught at - * validation time - */ - ASSERT(0); - return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; -} - -void pplib_apply_display_requirements( - struct core_dc *dc, - const struct validate_context *context, - struct dm_pp_display_configuration *pp_display_cfg) -{ - pp_display_cfg->all_displays_in_sync = - context->bw_results.all_displays_in_sync; - pp_display_cfg->nb_pstate_switch_disable = - context->bw_results.nbp_state_change_enable == false; - pp_display_cfg->cpu_cc6_disable = - context->bw_results.cpuc_state_change_enable == false; - pp_display_cfg->cpu_pstate_disable = - context->bw_results.cpup_state_change_enable == false; - pp_display_cfg->cpu_pstate_separation_time = - context->bw_results.blackout_recovery_time_us; - - pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk - / MEMORY_TYPE_MULTIPLIER; - - pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( - dc, - context->bw_results.required_sclk); - - pp_display_cfg->min_engine_clock_deep_sleep_khz - = context->bw_results.required_sclk_deep_sleep; - - pp_display_cfg->avail_mclk_switch_time_us = - get_min_vblank_time_us(context); - /* TODO: dce11.2*/ - pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - - pp_display_cfg->disp_clk_khz = context->dispclk_khz; - - fill_display_configs(context, pp_display_cfg); - - /* TODO: is this still applicable?*/ - if (pp_display_cfg->display_count == 1) { - const struct dc_crtc_timing *timing = - &context->streams[0]->public.timing; - - pp_display_cfg->crtc_index = - pp_display_cfg->disp_configs[0].pipe_idx; - pp_display_cfg->line_time_in_us = timing->h_total * 1000 - / timing->pix_clk_khz; - } - - if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( - struct dm_pp_display_configuration)) != 0) - dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); - - dc->prev_display_config = *pp_display_cfg; - -} - bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], @@ -1036,9 +883,6 @@ bool dc_commit_streams( context->streams[i]->public.timing.pix_clk_khz); } - pplib_apply_display_requirements(core_dc, - context, &context->pp_display_cfg); - resource_validate_ctx_destruct(core_dc->current_context); if (core_dc->temp_flip_context != core_dc->current_context) { @@ -1065,7 +909,6 @@ bool dc_pre_update_surfaces_to_stream( { int i, j; struct core_dc *core_dc = DC_TO_CORE(dc); - int prev_disp_clk = core_dc->current_context->dispclk_khz; struct dc_stream_status *stream_status = NULL; struct validate_context *context; bool ret = true; @@ -1150,16 +993,7 @@ bool dc_pre_update_surfaces_to_stream( goto unexpected_fail; } - if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment) - && prev_disp_clk < context->dispclk_khz) { - pplib_apply_display_requirements(core_dc, context, - &context->pp_display_cfg); - context->res_ctx.pool->display_clock->funcs->set_clock( - context->res_ctx.pool->display_clock, - context->dispclk_khz * 115 / 100); - core_dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; - core_dc->current_context->dispclk_khz = context->dispclk_khz; - } + core_dc->hwss.set_bandwidth(core_dc, context, false); for (i = 0; i < new_surface_count; i++) for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { @@ -1206,10 +1040,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) return false; } - core_dc->hwss.set_bandwidth(core_dc); - - /*TODO: dce specific*/ - pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg); + core_dc->hwss.set_bandwidth(core_dc, context, true); resource_validate_ctx_destruct(core_dc->current_context); core_dc->current_context = context; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index e2fe024e1182..bd8e19f1038b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -104,22 +104,18 @@ static bool dce100_enable_display_power_gating( return false; } -static void set_display_mark_for_pipe_if_needed(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - /* Do nothing until we have proper bandwitdth calcs */ -} - static void set_displaymarks( const struct core_dc *dc, struct validate_context *context) { /* Do nothing until we have proper bandwitdth calcs */ } -static void set_bandwidth(struct core_dc *dc) +static void set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed) { - /* Do nothing until we have proper bandwitdth calcs */ + dc->hwss.set_displaymarks(dc, context); } @@ -132,7 +128,6 @@ bool dce100_hw_sequencer_construct(struct core_dc *dc) /* TODO: dce80 is empty implementation at the moment*/ dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; dc->hwss.set_displaymarks = set_displaymarks; - dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed; dc->hwss.set_bandwidth = set_bandwidth; return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2d2daa694a30..d9dcb37a4f65 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1209,93 +1209,6 @@ static uint32_t compute_pstate_blackout_duration( return total_dest_line_time_ns; } -/* get the index of the pipe_ctx if there were no gaps in the pipe_ctx array*/ -int get_bw_result_idx( - struct resource_context *res_ctx, - int pipe_idx) -{ - int i, collapsed_idx; - - if (res_ctx->pipe_ctx[pipe_idx].top_pipe) - return 3; - - collapsed_idx = 0; - for (i = 0; i < pipe_idx; i++) { - if (res_ctx->pipe_ctx[i].stream) - collapsed_idx++; - } - - return collapsed_idx; -} - -static bool is_watermark_set_a_greater( - const struct bw_watermarks *set_a, - const struct bw_watermarks *set_b) -{ - if (set_a->a_mark > set_b->a_mark - || set_a->b_mark > set_b->b_mark - || set_a->c_mark > set_b->c_mark - || set_a->d_mark > set_b->d_mark) - return true; - return false; -} - -static bool did_watermarks_increase( - struct pipe_ctx *pipe_ctx, - struct validate_context *context, - struct validate_context *old_context) -{ - int collapsed_pipe_idx = get_bw_result_idx(&context->res_ctx, - pipe_ctx->pipe_idx); - int old_collapsed_pipe_idx = get_bw_result_idx(&old_context->res_ctx, - pipe_ctx->pipe_idx); - struct pipe_ctx *old_pipe_ctx = &old_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; - - if (!old_pipe_ctx->stream) - return true; - - if (is_watermark_set_a_greater( - &context->bw_results.nbp_state_change_wm_ns[collapsed_pipe_idx], - &old_context->bw_results.nbp_state_change_wm_ns[old_collapsed_pipe_idx])) - return true; - if (is_watermark_set_a_greater( - &context->bw_results.stutter_exit_wm_ns[collapsed_pipe_idx], - &old_context->bw_results.stutter_exit_wm_ns[old_collapsed_pipe_idx])) - return true; - if (is_watermark_set_a_greater( - &context->bw_results.urgent_wm_ns[collapsed_pipe_idx], - &old_context->bw_results.urgent_wm_ns[old_collapsed_pipe_idx])) - return true; - - return false; -} - -static void program_wm_for_pipe(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - int total_dest_line_time_ns = compute_pstate_blackout_duration( - dc->bw_vbios.blackout_duration, - pipe_ctx->stream); - int bw_result_idx = get_bw_result_idx(&context->res_ctx, - pipe_ctx->pipe_idx); - - pipe_ctx->mi->funcs->mem_input_program_display_marks( - pipe_ctx->mi, - context->bw_results.nbp_state_change_wm_ns[bw_result_idx], - context->bw_results.stutter_exit_wm_ns[bw_result_idx], - context->bw_results.urgent_wm_ns[bw_result_idx], - total_dest_line_time_ns); - - if (pipe_ctx->top_pipe) - pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( - pipe_ctx->mi, - context->bw_results.nbp_state_change_wm_ns[bw_result_idx + 1], - context->bw_results.stutter_exit_wm_ns[bw_result_idx + 1], - context->bw_results.urgent_wm_ns[bw_result_idx + 1], - total_dest_line_time_ns); -} - void dce110_set_displaymarks( const struct core_dc *dc, struct validate_context *context) @@ -1589,7 +1502,7 @@ static void reset_hw_ctx_wrap( } } -/*TODO: const validate_context*/ + enum dc_status dce110_apply_ctx_to_hw( struct core_dc *dc, struct validate_context *context) @@ -1768,7 +1681,7 @@ enum dc_status dce110_apply_ctx_to_hw( return status; } - dc->hwss.set_displaymarks(dc, context); + dc->hwss.set_bandwidth(dc, context, true); /* to save power */ apply_min_clocks(dc, context, &clocks_state, false); @@ -1777,6 +1690,7 @@ enum dc_status dce110_apply_ctx_to_hw( switch_dp_clock_sources(dc, &context->res_ctx); + return DC_OK; } @@ -2135,7 +2049,6 @@ static void init_hw(struct core_dc *dc) } } -/* TODO: move this to apply_ctx_tohw some how?*/ static void dce110_power_on_pipe_if_needed( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -2180,31 +2093,175 @@ static void dce110_power_on_pipe_if_needed( } } -static void dce110_increase_watermarks_for_pipe( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) +static void fill_display_configs( + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg) +{ + int j; + int num_cfgs = 0; + + for (j = 0; j < context->stream_count; j++) { + int k; + + const struct core_stream *stream = context->streams[j]; + struct dm_pp_single_disp_config *cfg = + &pp_display_cfg->disp_configs[num_cfgs]; + const struct pipe_ctx *pipe_ctx = NULL; + + for (k = 0; k < MAX_PIPES; k++) + if (stream == context->res_ctx.pipe_ctx[k].stream) { + pipe_ctx = &context->res_ctx.pipe_ctx[k]; + break; + } + + ASSERT(pipe_ctx != NULL); + + num_cfgs++; + cfg->signal = pipe_ctx->stream->signal; + cfg->pipe_idx = pipe_ctx->pipe_idx; + cfg->src_height = stream->public.src.height; + cfg->src_width = stream->public.src.width; + cfg->ddi_channel_mapping = + stream->sink->link->ddi_channel_mapping.raw; + cfg->transmitter = + stream->sink->link->link_enc->transmitter; + cfg->link_settings.lane_count = + stream->sink->link->public.cur_link_settings.lane_count; + cfg->link_settings.link_rate = + stream->sink->link->public.cur_link_settings.link_rate; + cfg->link_settings.link_spread = + stream->sink->link->public.cur_link_settings.link_spread; + cfg->sym_clock = stream->phy_pix_clk; + /* Round v_refresh*/ + cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; + cfg->v_refresh /= stream->public.timing.h_total; + cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) + / stream->public.timing.v_total; + } + + pp_display_cfg->display_count = num_cfgs; +} + +static uint32_t get_min_vblank_time_us(const struct validate_context *context) { - if (did_watermarks_increase(pipe_ctx, context, dc->current_context)) - program_wm_for_pipe(dc, pipe_ctx, context); + uint8_t j; + uint32_t min_vertical_blank_time = -1; + + for (j = 0; j < context->stream_count; j++) { + const struct dc_stream *stream = &context->streams[j]->public; + uint32_t vertical_blank_in_pixels = 0; + uint32_t vertical_blank_time = 0; + + vertical_blank_in_pixels = stream->timing.h_total * + (stream->timing.v_total + - stream->timing.v_addressable); + + vertical_blank_time = vertical_blank_in_pixels + * 1000 / stream->timing.pix_clk_khz; + + if (min_vertical_blank_time > vertical_blank_time) + min_vertical_blank_time = vertical_blank_time; + } + + return min_vertical_blank_time; } -static void dce110_set_bandwidth(struct core_dc *dc) +static int determine_sclk_from_bounding_box( + const struct core_dc *dc, + int required_sclk) { int i; - for (i = 0; i < dc->current_context->res_ctx.pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + /* + * Some asics do not give us sclk levels, so we just report the actual + * required sclk + */ + if (dc->sclk_lvls.num_levels == 0) + return required_sclk; - if (!pipe_ctx->stream) - continue; + for (i = 0; i < dc->sclk_lvls.num_levels; i++) { + if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk) + return dc->sclk_lvls.clocks_in_khz[i]; + } + /* + * even maximum level could not satisfy requirement, this + * is unexpected at this stage, should have been caught at + * validation time + */ + ASSERT(0); + return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1]; +} + +static void pplib_apply_display_requirements( + struct core_dc *dc, + struct validate_context *context) +{ + struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; + + pp_display_cfg->all_displays_in_sync = + context->bw_results.all_displays_in_sync; + pp_display_cfg->nb_pstate_switch_disable = + context->bw_results.nbp_state_change_enable == false; + pp_display_cfg->cpu_cc6_disable = + context->bw_results.cpuc_state_change_enable == false; + pp_display_cfg->cpu_pstate_disable = + context->bw_results.cpup_state_change_enable == false; + pp_display_cfg->cpu_pstate_separation_time = + context->bw_results.blackout_recovery_time_us; + + pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + / MEMORY_TYPE_MULTIPLIER; + + pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( + dc, + context->bw_results.required_sclk); + + pp_display_cfg->min_engine_clock_deep_sleep_khz + = context->bw_results.required_sclk_deep_sleep; + + pp_display_cfg->avail_mclk_switch_time_us = + get_min_vblank_time_us(context); + /* TODO: dce11.2*/ + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - program_wm_for_pipe(dc, pipe_ctx, dc->current_context); + pp_display_cfg->disp_clk_khz = context->dispclk_khz; + + fill_display_configs(context, pp_display_cfg); + + /* TODO: is this still applicable?*/ + if (pp_display_cfg->display_count == 1) { + const struct dc_crtc_timing *timing = + &context->streams[0]->public.timing; + + pp_display_cfg->crtc_index = + pp_display_cfg->disp_configs[0].pipe_idx; + pp_display_cfg->line_time_in_us = timing->h_total * 1000 + / timing->pix_clk_khz; + } + + if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( + struct dm_pp_display_configuration)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + + dc->prev_display_config = *pp_display_cfg; +} + +static void dce110_set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed) +{ + dc->hwss.set_displaymarks(dc, context); + + if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + context->res_ctx.pool->display_clock->funcs->set_clock( + context->res_ctx.pool->display_clock, + context->dispclk_khz * 115 / 100); + dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; + dc->current_context->dispclk_khz = context->dispclk_khz; } - dc->current_context->res_ctx.pool->display_clock->funcs->set_clock( - dc->current_context->res_ctx.pool->display_clock, - dc->current_context->dispclk_khz * 115 / 100); + pplib_apply_display_requirements(dc, context); } static void dce110_program_front_end_for_pipe( @@ -2335,15 +2392,6 @@ static void dce110_program_front_end_for_pipe( pipe_ctx->scl_data.recout.y); } -static void dce110_prepare_pipe_for_context( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - dce110_power_on_pipe_if_needed(dc, pipe_ctx, context); - dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context); -} - static void dce110_apply_ctx_for_surface( struct core_dc *dc, struct core_surface *surface, @@ -2388,7 +2436,7 @@ static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) static const struct hw_sequencer_funcs dce110_funcs = { .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, - .prepare_pipe_for_context = dce110_prepare_pipe_for_context, + .prepare_pipe_for_context = dce110_power_on_pipe_if_needed, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, @@ -2407,7 +2455,6 @@ static const struct hw_sequencer_funcs dce110_funcs = { .power_down_front_end = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, .set_displaymarks = dce110_set_displaymarks, - .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe, .set_bandwidth = dce110_set_bandwidth, .set_drr = set_drr, .set_static_screen_control = set_static_screen_control, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index c7a2b768bcd1..85a54d963f8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -106,23 +106,18 @@ static bool dce80_enable_display_power_gating( return false; } - -static void set_display_mark_for_pipe_if_needed(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - /* Do nothing until we have proper bandwitdth calcs */ -} - static void set_displaymarks( const struct core_dc *dc, struct validate_context *context) { /* Do nothing until we have proper bandwitdth calcs */ } -static void set_bandwidth(struct core_dc *dc) +static void set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed) { - /* Do nothing until we have proper bandwitdth calcs */ + dc->hwss.set_displaymarks(dc, context); } @@ -133,7 +128,6 @@ bool dce80_hw_sequencer_construct(struct core_dc *dc) dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating; dc->hwss.pipe_control_lock = dce_pipe_control_lock; dc->hwss.set_displaymarks = set_displaymarks; - dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed; dc->hwss.set_bandwidth = set_bandwidth; return true; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 758a568589bb..7b780c610631 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -124,11 +124,10 @@ struct hw_sequencer_funcs { const struct core_dc *dc, struct validate_context *context); - void (*increase_watermarks_for_pipe)(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context); - - void (*set_bandwidth)(struct core_dc *dc); + void (*set_bandwidth)( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed); void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax); -- GitLab From ce9c088051e198b19eb533b24c605b7cedbe5b9c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 22 Feb 2017 18:14:52 -0500 Subject: [PATCH 0281/2898] drm/amd/display: move visual confirm recout adjustment to scaler Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 --------- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 6 ++++++ .../gpu/drm/amd/display/dc/dce110/dce110_transform_v.c | 6 ++++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0ec2c4f39735..852932aec436 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -980,11 +980,6 @@ bool dc_pre_update_surfaces_to_stream( resource_build_scaling_params( new_surfaces[i], &context->res_ctx.pipe_ctx[j]); - - if (dc->debug.surface_visual_confirm) { - context->res_ctx.pipe_ctx[j].scl_data.recout.height -= 2; - context->res_ctx.pipe_ctx[j].scl_data.recout.width -= 2; - } } if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { @@ -1267,10 +1262,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, continue; resource_build_scaling_params(updates[i].surface, pipe_ctx); - if (dc->debug.surface_visual_confirm) { - pipe_ctx->scl_data.recout.height -= 2; - pipe_ctx->scl_data.recout.width -= 2; - } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index d8ffbff9a268..c861fd7b5767 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -27,6 +27,7 @@ #include "reg_helper.h" #include "opp.h" #include "basics/conversion.h" +#include "dc.h" #define REG(reg) \ (xfm_dce->regs->reg) @@ -121,6 +122,11 @@ static void program_overscan( int overscan_bottom = data->v_active - data->recout.y - data->recout.height; + if (xfm_dce->base.ctx->dc->debug.surface_visual_confirm) { + overscan_bottom += 2; + overscan_right += 2; + } + if (overscan_right < 0) { BREAK_TO_DEBUGGER(); overscan_right = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index feb5f3c29804..28963996693c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -25,6 +25,7 @@ #include "dce110_transform_v.h" #include "dm_services.h" +#include "dc.h" #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" @@ -232,6 +233,11 @@ static void program_overscan( int overscan_right = data->h_active - data->recout.x - data->recout.width; int overscan_bottom = data->v_active - data->recout.y - data->recout.height; + if (xfm_dce->base.ctx->dc->debug.surface_visual_confirm) { + overscan_bottom += 2; + overscan_right += 2; + } + if (overscan_right < 0) { BREAK_TO_DEBUGGER(); overscan_right = 0; -- GitLab From c2e218dda078f4e8d09d2493b01a7e256cfe38aa Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 24 Feb 2017 16:25:51 -0500 Subject: [PATCH 0282/2898] drm/amd/display: Some more warning fixes This doesn't show with gcc6 Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 8eb6b342a49d..d275fc88f71e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -928,7 +928,7 @@ static bool construct( { uint8_t i; struct gpio *hpd_gpio = NULL; - struct ddc_service_init_data ddc_service_init_data = { 0 }; + struct ddc_service_init_data ddc_service_init_data = { { 0 } }; struct dc_context *dc_ctx = init_params->ctx; struct encoder_init_data enc_init_data = { 0 }; struct integrated_info info = {{{ 0 }}}; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 6fe5acbc16ca..37efa40a9bca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1762,7 +1762,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) { struct core_link *link = DC_LINK_TO_LINK(dc_link); union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; - union device_service_irq device_service_clear = {0}; + union device_service_irq device_service_clear = { { 0 } }; enum dc_status result = DDC_RESULT_UNKNOWN; bool status = false; /* For use cases related to down stream connection status change, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index dd922bdcc145..3e3eefea3e82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -393,8 +393,8 @@ static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) { struct dc_debug *debug = &clk_dce->base.ctx->dc->debug; struct dc_bios *bp = clk_dce->base.ctx->dc_bios; - struct integrated_info info = { 0 }; - struct firmware_info fw_info = { 0 }; + struct integrated_info info = { { { 0 } } }; + struct firmware_info fw_info = { { 0 } }; int i; if (bp->integrated_info) @@ -456,7 +456,7 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) bp, AS_SIGNAL_TYPE_GPU_PLL); if (ss_info_num) { - struct spread_spectrum_info info = { 0 }; + struct spread_spectrum_info info = { { 0 } }; enum bp_result result = bp->funcs->get_spread_spectrum_info( bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info); -- GitLab From 3853c184ed9a258e2d720f98ef77112625300e36 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 28 Feb 2017 16:14:10 -0500 Subject: [PATCH 0283/2898] drm/amd/display: fix dce100_validate_bandwidth return value Signed-off-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index fc85efafb104..c72858a1452f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -772,7 +772,7 @@ bool dce100_validate_bandwidth( /* TODO implement when needed but for now hardcode max value*/ context->dispclk_khz = 681000; - return false; + return true; } static bool dce100_validate_surface_sets( -- GitLab From a49dcb88e8159b12d1af5f67d657388c4a1c96cb Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 12 Jan 2017 09:09:08 -0500 Subject: [PATCH 0284/2898] drm/amd/display: Use amdgpu mode funcs statically No need to assign them dynamically. This is much more readable. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d0706e550e84..21dcd6caf628 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -28,6 +28,7 @@ #include "vid.h" #include "amdgpu.h" +#include "amdgpu_display.h" #include "atom.h" #include "amdgpu_dm.h" #include "amdgpu_dm_types.h" @@ -715,6 +716,8 @@ const struct amdgpu_ip_block_version dm_ip_block = /* TODO: it is temporary non-const, should fixed later */ static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { + .fb_create = amdgpu_user_framebuffer_create, + .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = amdgpu_dm_atomic_commit }; @@ -1088,11 +1091,6 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev->mode_info.mode_config_initialized = true; - amdgpu_dm_mode_funcs.fb_create = - amdgpu_mode_funcs.fb_create; - amdgpu_dm_mode_funcs.output_poll_changed = - amdgpu_mode_funcs.output_poll_changed; - adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; adev->ddev->mode_config.max_width = 16384; -- GitLab From e7738c8a50ea426a57184ef2275b8163ab79febe Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 17 Jan 2017 20:24:03 -0500 Subject: [PATCH 0285/2898] drm/amd/display: Remove unused define from amdgpu_dm_types Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 6ed1480a8bc3..4faa1659f7f9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -59,11 +59,6 @@ int amdgpu_dm_atomic_commit( int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state); -int dm_create_validation_set_for_stream( - struct drm_connector *connector, - struct drm_display_mode *mode, - struct dc_validation_set *val_set); - void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( struct drm_connector *connector); -- GitLab From f0828115efa0406fbe0010b1d8c9c965fc718733 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 28 Feb 2017 15:23:38 -0500 Subject: [PATCH 0286/2898] drm/amd/display: freesync pipe split :VTotal_Min_Mask for Hflip/lock. Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 40 +++++++++++++------ .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 21 +++++----- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 15 +------ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 20 ++++++++-- .../amd/display/include/hw_sequencer_types.h | 1 + 5 files changed, 59 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 852932aec436..66a5b2745501 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1178,6 +1178,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, enum surface_update_type update_type; const struct dc_stream_status *stream_status; + unsigned int lock_mask = 0; stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); @@ -1313,6 +1314,23 @@ void dc_update_surfaces_for_stream(struct dc *dc, for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + if (pipe_ctx->surface != surface) + continue; + /*lock all the MCPP if blnd is enable for DRR*/ + if ((update_type == UPDATE_TYPE_FAST && + (dc_stream->freesync_ctx.enabled == true && + surface_count != context->res_ctx.pool->pipe_count)) && + !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + lock_mask = PIPE_LOCK_CONTROL_MPCC_ADDR; + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + lock_mask, + true); + } + } for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct pipe_ctx *cur_pipe_ctx; @@ -1320,16 +1338,16 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (pipe_ctx->surface != surface) continue; - if (update_type != UPDATE_TYPE_FAST && !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc->hwseq, - pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_GRAPHICS | + lock_mask = PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | PIPE_LOCK_CONTROL_BLENDER | - PIPE_LOCK_CONTROL_MODE, + PIPE_LOCK_CONTROL_MODE; + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + lock_mask, true); } @@ -1371,7 +1389,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if (update_type == UPDATE_TYPE_FAST) + if (update_type == UPDATE_TYPE_FAST && (lock_mask == 0)) return; for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { @@ -1381,11 +1399,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (updates[j].surface == &pipe_ctx->surface->public) { if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( - core_dc->hwseq, - pipe_ctx->pipe_idx, - PIPE_LOCK_CONTROL_GRAPHICS | - PIPE_LOCK_CONTROL_SCL | - PIPE_LOCK_CONTROL_BLENDER, + core_dc, + pipe_ctx, + lock_mask, false); } break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 8eb755620c48..1e1d60af8306 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -26,6 +26,7 @@ #include "dce_hwseq.h" #include "reg_helper.h" #include "hw_sequencer.h" +#include "core_dc.h" #define CTX \ hws->ctx @@ -43,15 +44,17 @@ void dce_enable_fe_clock(struct dce_hwseq *hws, DCFE_CLOCK_ENABLE, enable); } -void dce_pipe_control_lock(struct dce_hwseq *hws, - unsigned int blnd_inst, +void dce_pipe_control_lock(struct core_dc *dc, + struct pipe_ctx *pipe, enum pipe_lock_control control_mask, bool lock) { uint32_t lock_val = lock ? 1 : 0; - uint32_t dcp_grph, scl, blnd, update_lock_mode; - - uint32_t val = REG_GET_4(BLND_V_UPDATE_LOCK[blnd_inst], + uint32_t dcp_grph, scl, blnd, update_lock_mode, val; + struct dce_hwseq *hws = dc->hwseq; + if (control_mask & PIPE_LOCK_CONTROL_MPCC_ADDR) + return; + val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx], BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, BLND_SCL_V_UPDATE_LOCK, &scl, BLND_BLND_V_UPDATE_LOCK, &blnd, @@ -70,19 +73,19 @@ void dce_pipe_control_lock(struct dce_hwseq *hws, update_lock_mode = lock_val; - REG_SET_2(BLND_V_UPDATE_LOCK[blnd_inst], val, + REG_SET_2(BLND_V_UPDATE_LOCK[pipe->pipe_idx], val, BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, BLND_SCL_V_UPDATE_LOCK, scl); if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0) - REG_SET_2(BLND_V_UPDATE_LOCK[blnd_inst], val, + REG_SET_2(BLND_V_UPDATE_LOCK[pipe->pipe_idx], val, BLND_BLND_V_UPDATE_LOCK, blnd, BLND_V_UPDATE_LOCK_MODE, update_lock_mode); if (hws->wa.blnd_crtc_trigger) { if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) { - uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]); - REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value); + uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->pipe_idx]); + REG_WRITE(CRTC_H_BLANK_START_END[pipe->pipe_idx], value); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 4af8d560a7ee..9ef618443255 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -212,17 +212,6 @@ struct dce_hwseq_mask { HWSEQ_REG_FIED_LIST(uint32_t) }; -struct dce_hwseq_wa { - bool blnd_crtc_trigger; -}; - -struct dce_hwseq { - struct dc_context *ctx; - const struct dce_hwseq_registers *regs; - const struct dce_hwseq_shift *shifts; - const struct dce_hwseq_mask *masks; - struct dce_hwseq_wa wa; -}; enum blnd_mode { BLND_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */ @@ -233,8 +222,8 @@ enum blnd_mode { void dce_enable_fe_clock(struct dce_hwseq *hwss, unsigned int inst, bool enable); -void dce_pipe_control_lock(struct dce_hwseq *hws, - unsigned int blnd_inst, +void dce_pipe_control_lock(struct core_dc *dc, + struct pipe_ctx *pipe, enum pipe_lock_control control_mask, bool lock); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 7b780c610631..a902de52107f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -38,10 +38,22 @@ enum pipe_lock_control { PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, PIPE_LOCK_CONTROL_BLENDER = 1 << 1, PIPE_LOCK_CONTROL_SCL = 1 << 2, - PIPE_LOCK_CONTROL_MODE = 1 << 3 + PIPE_LOCK_CONTROL_MODE = 1 << 3, + PIPE_LOCK_CONTROL_MPCC_ADDR = 1 << 4 +}; + +struct dce_hwseq_wa { + bool blnd_crtc_trigger; +}; + +struct dce_hwseq { + struct dc_context *ctx; + const struct dce_hwseq_registers *regs; + const struct dce_hwseq_shift *shifts; + const struct dce_hwseq_mask *masks; + struct dce_hwseq_wa wa; }; -struct dce_hwseq; struct hw_sequencer_funcs { @@ -115,8 +127,8 @@ struct hw_sequencer_funcs { struct dc_link_settings *link_settings); void (*pipe_control_lock)( - struct dce_hwseq *hwseq, - unsigned int blnd_inst, + struct core_dc *dc, + struct pipe_ctx *pipe, enum pipe_lock_control control_mask, bool lock); diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 6f0475c25566..065a91a7002f 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -38,6 +38,7 @@ struct drr_params { /* defines the maximum possible vertical dimension of display timing * for CRTC as supported by the panel */ uint32_t vertical_total_max; + bool immediate_flip; }; #endif -- GitLab From 67a277055b98e998c34d311cc956f809a0f92504 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 16 Feb 2017 10:37:00 -0500 Subject: [PATCH 0287/2898] drm/amd/display: We don't support interlace and doublescan Don't tell DRM otherwise. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 862bbd745bb9..008c7a55e992 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1851,8 +1851,9 @@ void amdgpu_dm_connector_init_helper( aconnector->connector_id = link_index; aconnector->dc_link = link; - aconnector->base.interlace_allowed = true; - aconnector->base.doublescan_allowed = true; + aconnector->base.interlace_allowed = false; + aconnector->base.doublescan_allowed = false; + aconnector->base.stereo_allowed = false; aconnector->base.dpms = DRM_MODE_DPMS_OFF; aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ -- GitLab From 92a65e32ade943135a6e48ec756661c0896392d0 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 28 Feb 2017 19:49:15 -0500 Subject: [PATCH 0288/2898] drm/amd/display: extended the programming sequence to VFlip as well Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 66a5b2745501..efe50fd2be78 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1316,6 +1316,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx; + bool is_new_pipe_surface = true; + if (pipe_ctx->surface != surface) continue; /*lock all the MCPP if blnd is enable for DRR*/ @@ -1324,26 +1327,16 @@ void dc_update_surfaces_for_stream(struct dc *dc, surface_count != context->res_ctx.pool->pipe_count)) && !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { lock_mask = PIPE_LOCK_CONTROL_MPCC_ADDR; - core_dc->hwss.pipe_control_lock( - core_dc, - pipe_ctx, - lock_mask, - true); - } } - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx; - bool is_new_pipe_surface = true; - if (pipe_ctx->surface != surface) - continue; if (update_type != UPDATE_TYPE_FAST && !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { lock_mask = PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | PIPE_LOCK_CONTROL_BLENDER | PIPE_LOCK_CONTROL_MODE; + } + if (lock_mask != 0) { core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, @@ -1389,7 +1382,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if (update_type == UPDATE_TYPE_FAST && (lock_mask == 0)) + if ((update_type == UPDATE_TYPE_FAST) && lock_mask == 0) return; for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { -- GitLab From 54f5499a54fe671c56012684d5a68efbb4fe0b53 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 20 Apr 2017 15:57:05 -0400 Subject: [PATCH 0289/2898] drm/amd/display: Refactor atomic commit implementation. (v2) Modify amdgpu_dm_atomic_comit to implement atomic_comit_tail hook. Unify Buffer objects allocation and dealocation for surface updates and page flips. Simplify wait for fences and target_vbank logic for non blockiing commit. Remove hacky update surface to page flip synchronization we had and rely on atomic framework synchronization logic. v2: Add state->allow_modeset as indicator of page flip call. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 58 ++- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 343 ++++++++---------- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 7 +- 3 files changed, 203 insertions(+), 205 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 21dcd6caf628..da499ab7eab5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -149,7 +149,6 @@ static struct amdgpu_crtc *get_crtc_by_otg_inst( static void dm_pflip_high_irq(void *interrupt_params) { - struct amdgpu_flip_work *works; struct amdgpu_crtc *amdgpu_crtc; struct common_irq_params *irq_params = interrupt_params; struct amdgpu_device *adev = irq_params->adev; @@ -165,7 +164,6 @@ static void dm_pflip_high_irq(void *interrupt_params) } spin_lock_irqsave(&adev->ddev->event_lock, flags); - works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n", @@ -177,22 +175,24 @@ static void dm_pflip_high_irq(void *interrupt_params) return; } - /* page flip completed. clean up */ - amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; - amdgpu_crtc->pflip_works = NULL; /* wakeup usersapce */ - if (works->event) - drm_crtc_send_vblank_event(&amdgpu_crtc->base, - works->event); + if (amdgpu_crtc->event + && amdgpu_crtc->event->event.base.type + == DRM_EVENT_FLIP_COMPLETE) { + drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); + /* page flip completed. clean up */ + amdgpu_crtc->event = NULL; + } else + WARN_ON(1); + amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE, work: %p,\n", - __func__, amdgpu_crtc->crtc_id, amdgpu_crtc, works); + DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE\n", + __func__, amdgpu_crtc->crtc_id, amdgpu_crtc); drm_crtc_vblank_put(&amdgpu_crtc->base); - schedule_work(&works->unpin_work); } static void dm_crtc_high_irq(void *interrupt_params) @@ -719,7 +719,11 @@ static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, - .atomic_commit = amdgpu_dm_atomic_commit + .atomic_commit = drm_atomic_helper_commit +}; + +static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { + .atomic_commit_tail = amdgpu_dm_atomic_commit_tail }; void amdgpu_dm_update_connector_after_detect( @@ -1092,6 +1096,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev->mode_info.mode_config_initialized = true; adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; + adev->ddev->mode_config.helper_private = &amdgpu_dm_mode_config_helperfuncs; adev->ddev->mode_config.max_width = 16384; adev->ddev->mode_config.max_height = 16384; @@ -1345,6 +1350,14 @@ static void dm_page_flip(struct amdgpu_device *adev, acrtc = adev->mode_info.crtcs[crtc_id]; stream = acrtc->stream; + + if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { + DRM_ERROR("flip queue: acrtc %d, already busy\n", acrtc->crtc_id); + /* In commit tail framework this cannot happen */ + BUG_ON(0); + } + + /* * Received a page flip call after the display has been reset. * Just return in this case. Everything should be clean-up on reset. @@ -1359,15 +1372,28 @@ static void dm_page_flip(struct amdgpu_device *adev, addr.address.grph.addr.high_part = upper_32_bits(crtc_base); addr.flip_immediate = async; + + if (acrtc->base.state->event && + acrtc->base.state->event->event.base.type == + DRM_EVENT_FLIP_COMPLETE) { + acrtc->event = acrtc->base.state->event; + + /* Set the flip status */ + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + + /* Mark this event as consumed */ + acrtc->base.state->event = NULL; + } + + dc_flip_surface_addrs(adev->dm.dc, + dc_stream_get_status(stream)->surfaces, + &addr, 1); + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, addr.address.grph.addr.high_part, addr.address.grph.addr.low_part); - dc_flip_surface_addrs( - adev->dm.dc, - dc_stream_get_status(stream)->surfaces, - &addr, 1); } static int amdgpu_notify_freesync(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 008c7a55e992..956ff5a7b9b6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -687,8 +687,18 @@ static void dm_dc_surface_commit( { struct dc_surface *dc_surface; const struct dc_surface *dc_surfaces[1]; - const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); const struct dc_stream *dc_stream = acrtc->stream; + unsigned long flags; + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { + DRM_ERROR("dm_dc_surface_commit: acrtc %d, already busy\n", acrtc->crtc_id); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + /* In comit tail framework this cannot happen */ + BUG_ON(0); + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); if (!dc_stream) { dm_error( @@ -1427,6 +1437,7 @@ static void clear_unrelated_fields(struct drm_plane_state *state) state->fence = NULL; } +/*TODO update because event is always present now */ static bool page_flip_needed( const struct drm_plane_state *new_state, const struct drm_plane_state *old_state, @@ -1482,11 +1493,13 @@ static bool page_flip_needed( page_flip_required = memcmp(&old_state_tmp, &new_state_tmp, sizeof(old_state_tmp)) == 0 ? true:false; + if (new_state->crtc && page_flip_required == false) { acrtc_new = to_amdgpu_crtc(new_state->crtc); if (acrtc_new->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) page_flip_required = true; } + return page_flip_required; } @@ -1512,7 +1525,7 @@ static int dm_plane_helper_prepare_fb( if (unlikely(r != 0)) return r; - r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL); + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &afb->address); amdgpu_bo_unreserve(rbo); @@ -1521,6 +1534,7 @@ static int dm_plane_helper_prepare_fb( return r; } + amdgpu_bo_ref(rbo); return 0; } @@ -1544,7 +1558,10 @@ static void dm_plane_helper_cleanup_fb( } else { amdgpu_bo_unpin(rbo); amdgpu_bo_unreserve(rbo); + amdgpu_bo_unref(&rbo); } + + afb->address = 0; } int dm_create_validation_set_for_connector(struct drm_connector *connector, @@ -2135,51 +2152,6 @@ static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state) } } - -typedef bool (*predicate)(struct amdgpu_crtc *acrtc); - -static void wait_while_pflip_status(struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, predicate f) { - int count = 0; - while (f(acrtc)) { - /* Spin Wait*/ - msleep(1); - count++; - if (count == 1000) { - DRM_ERROR("%s - crtc:%d[%p], pflip_stat:%d, probable hang!\n", - __func__, acrtc->crtc_id, - acrtc, - acrtc->pflip_status); - - /* we do not expect to hit this case except on Polaris with PHY PLL - * 1. DP to HDMI passive dongle connected - * 2. unplug (headless) - * 3. plug in DP - * 3a. on plug in, DP will try verify link by training, and training - * would disable PHY PLL which HDMI rely on to drive TG - * 3b. this will cause flip interrupt cannot be generated, and we - * exit when timeout expired. however we do not have code to clean - * up flip, flip clean up will happen when the address is written - * with the restore mode change - */ - WARN_ON(1); - break; - } - } - - DRM_DEBUG_DRIVER("%s - Finished waiting for:%d msec, crtc:%d[%p], pflip_stat:%d \n", - __func__, - count, - acrtc->crtc_id, - acrtc, - acrtc->pflip_status); -} - -static bool pflip_in_progress_predicate(struct amdgpu_crtc *acrtc) -{ - return acrtc->pflip_status != AMDGPU_FLIP_NONE; -} - static void manage_dm_interrupts( struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, @@ -2201,8 +2173,6 @@ static void manage_dm_interrupts( &adev->pageflip_irq, irq_type); } else { - wait_while_pflip_status(adev, acrtc, - pflip_in_progress_predicate); amdgpu_irq_put( adev, @@ -2212,12 +2182,6 @@ static void manage_dm_interrupts( } } - -static bool pflip_pending_predicate(struct amdgpu_crtc *acrtc) -{ - return acrtc->pflip_status == AMDGPU_FLIP_PENDING; -} - static bool is_scaling_state_different( const struct dm_connector_state *dm_state, const struct dm_connector_state *old_dm_state) @@ -2255,116 +2219,94 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) acrtc->enabled = false; } -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) + +/* + * Executes flip + * + * Waits on all BO's fences and for proper vblank count + */ +static void amdgpu_dm_do_flip( + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + uint32_t target) +{ + unsigned long flags; + uint32_t target_vblank; + int r, vpos, hpos; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); + struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); + struct amdgpu_device *adev = crtc->dev->dev_private; + bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + + + /*TODO This might fail and hence better not used, wait + * explicitly on fences instead + * and in general should be called for + * blocking commit to as per framework helpers + * */ + r = amdgpu_bo_reserve(abo, true); + if (unlikely(r != 0)) { + DRM_ERROR("failed to reserve buffer before flip\n"); + BUG_ON(0); + } + + /* Wait for all fences on this FB */ + WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false, + MAX_SCHEDULE_TIMEOUT) < 0); + + amdgpu_bo_unreserve(abo); + + /* Wait for target vblank */ + /* Wait until we're out of the vertical blank period before the one + * targeted by the flip + */ + target_vblank = target - drm_crtc_vblank_count(crtc) + + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); + + while ((acrtc->enabled && + (amdgpu_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id, 0, + &vpos, &hpos, NULL, NULL, + &crtc->hwmode) + & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == + (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && + (int)(target_vblank - + amdgpu_get_vblank_counter_kms(adev->ddev, acrtc->crtc_id)) > 0)) { + usleep_range(1000, 1100); + } + + /* Flip */ + spin_lock_irqsave(&crtc->dev->event_lock, flags); + /* update crtc fb */ + crtc->primary->fb = fb; + + /* Do the flip (mmio) */ + adev->mode_info.funcs->page_flip(adev, acrtc->crtc_id, afb->address, async_flip); + + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", + acrtc->crtc_id); +} + +void amdgpu_dm_atomic_commit_tail( + struct drm_atomic_state *state) { + struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; struct drm_plane *plane; - struct drm_plane_state *new_plane_state; struct drm_plane_state *old_plane_state; uint32_t i; - int32_t ret = 0; uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; - uint32_t flip_crtcs_count = 0; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; const struct dc_stream *commit_streams[MAX_STREAMS]; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; const struct dc_stream *new_stream; - struct drm_crtc *flip_crtcs[MAX_STREAMS]; - struct amdgpu_flip_work *work[MAX_STREAMS] = {0}; - struct amdgpu_bo *new_abo[MAX_STREAMS] = {0}; - - /* In this step all new fb would be pinned */ - - /* - * TODO: Revisit when we support true asynchronous commit. - * Right now we receive async commit only from pageflip, in which case - * we should not pin/unpin the fb here, it should be done in - * amdgpu_crtc_flip and from the vblank irq handler. - */ - if (!nonblock) { - ret = drm_atomic_helper_prepare_planes(dev, state); - if (ret) - return ret; - } - - /* Page flip if needed */ - for_each_plane_in_state(state, plane, new_plane_state, i) { - struct drm_plane_state *old_plane_state = plane->state; - struct drm_crtc *crtc = new_plane_state->crtc; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_framebuffer *fb = new_plane_state->fb; - struct drm_crtc_state *crtc_state; + unsigned long flags; + bool wait_for_vblank = true; - if (!fb || !crtc) - continue; - - crtc_state = drm_atomic_get_crtc_state(state, crtc); - - if (!crtc_state->planes_changed || !crtc_state->active) - continue; - - if (page_flip_needed( - new_plane_state, - old_plane_state, - crtc_state->event, - false)) { - ret = amdgpu_crtc_prepare_flip(crtc, - fb, - crtc_state->event, - acrtc->flip_flags, - drm_crtc_vblank_count(crtc), - &work[flip_crtcs_count], - &new_abo[flip_crtcs_count]); - - if (ret) { - /* According to atomic_commit hook API, EINVAL is not allowed */ - if (unlikely(ret == -EINVAL)) - ret = -ENOMEM; - - DRM_ERROR("Atomic commit: Flip for crtc id %d: [%p], " - "failed, errno = %d\n", - acrtc->crtc_id, - acrtc, - ret); - /* cleanup all flip configurations which - * succeeded in this commit - */ - for (i = 0; i < flip_crtcs_count; i++) - amdgpu_crtc_cleanup_flip_ctx( - work[i], - new_abo[i]); - - return ret; - } - - flip_crtcs[flip_crtcs_count] = crtc; - flip_crtcs_count++; - } - } - - /* - * This is the point of no return - everything below never fails except - * when the hw goes bonghits. Which means we can commit the new state on - * the software side now. - */ - - drm_atomic_helper_swap_state(state, true); - - /* - * From this point state become old state really. New state is - * initialized to appropriate objects and could be accessed from there - */ - - /* - * there is no fences usage yet in state. We can skip the following line - * wait_for_fences(dev, state); - */ drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -2520,11 +2462,11 @@ int amdgpu_dm_atomic_commit( for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *dm_state = NULL; enum dm_commit_action action; + bool pflip_needed; if (!fb || !crtc || !crtc->state->active) continue; @@ -2535,12 +2477,14 @@ int amdgpu_dm_atomic_commit( * 1. This commit is not a page flip. * 2. This commit is a page flip, and streams are created. */ - if (!page_flip_needed( + pflip_needed = !state->allow_modeset && + page_flip_needed( plane_state, old_plane_state, - crtc->state->event, true) || - action == DM_COMMIT_ACTION_DPMS_ON || - action == DM_COMMIT_ACTION_SET) { + crtc->state->event, true); + if (!pflip_needed || + action == DM_COMMIT_ACTION_DPMS_ON || + action == DM_COMMIT_ACTION_SET) { list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->state->crtc == crtc) { @@ -2567,14 +2511,6 @@ int amdgpu_dm_atomic_commit( if (!dm_state) continue; - /* - * if flip is pending (ie, still waiting for fence to return - * before address is submitted) here, we cannot commit_surface - * as commit_surface will pre-maturely write out the future - * address. wait until flip is submitted before proceeding. - */ - wait_while_pflip_status(adev, acrtc, pflip_pending_predicate); - dm_dc_surface_commit(dm->dc, crtc); } } @@ -2594,43 +2530,77 @@ int amdgpu_dm_atomic_commit( } - /* Do actual flip */ - flip_crtcs_count = 0; for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; + bool pflip_needed; if (!fb || !crtc || !crtc->state->planes_changed || !crtc->state->active) continue; - - if (page_flip_needed( + pflip_needed = !state->allow_modeset && + page_flip_needed( plane_state, old_plane_state, crtc->state->event, - false)) { - amdgpu_crtc_submit_flip( - crtc, - fb, - work[flip_crtcs_count], - new_abo[i]); - flip_crtcs_count++; + false); + + if (pflip_needed) { + amdgpu_dm_do_flip( + crtc, + fb, + drm_crtc_vblank_count(crtc)); + + wait_for_vblank = + acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + false : true; /*clean up the flags for next usage*/ acrtc->flip_flags = 0; } } - /* In this state all old framebuffers would be unpinned */ - /* TODO: Revisit when we support true asynchronous commit.*/ - if (!nonblock) - drm_atomic_helper_cleanup_planes(dev, state); + /*TODO mark consumed event on all crtc assigned event + * in drm_atomic_helper_setup_commit just to signal completion + */ + spin_lock_irqsave(&adev->ddev->event_lock, flags); + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->base.state->event && + acrtc->base.state->event->event.base.type != DRM_EVENT_FLIP_COMPLETE) { + acrtc->event = acrtc->base.state->event; + acrtc->base.state->event = NULL; + } + } + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + + /* Signal HW programming completion */ + drm_atomic_helper_commit_hw_done(state); + + if (wait_for_vblank) + drm_atomic_helper_wait_for_vblanks(dev, state); + + /*TODO send vblank event on all crtc assigned event + * in drm_atomic_helper_setup_commit just to signal completion + */ + spin_lock_irqsave(&adev->ddev->event_lock, flags); + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - drm_atomic_state_put(state); + if (acrtc->event && + acrtc->event->event.base.type != DRM_EVENT_FLIP_COMPLETE) { + drm_send_event_locked(dev, &acrtc->event->base); + acrtc->event = NULL; + } + } + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - return ret; + /*TODO Is it to early if actual flip haven't happened yet ?*/ + /* Release old FB */ + drm_atomic_helper_cleanup_planes(dev, state); } /* * This functions handle all cases when set mode does not come upon hotplug. @@ -2982,6 +2952,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_connector_state *dm_state = NULL; enum dm_commit_action action; struct drm_crtc_state *crtc_state; + bool pflip_needed; if (!fb || !crtc || crtc_set[i] != crtc || @@ -2995,10 +2966,12 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * 2. This commit is a page flip, and streams are created. */ crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (!page_flip_needed(plane_state, old_plane_state, - crtc_state->event, true) || - action == DM_COMMIT_ACTION_DPMS_ON || - action == DM_COMMIT_ACTION_SET) { + pflip_needed = !state->allow_modeset && + page_flip_needed(plane_state, old_plane_state, + crtc_state->event, true); + if (!pflip_needed || + action == DM_COMMIT_ACTION_DPMS_ON || + action == DM_COMMIT_ACTION_SET) { struct dc_surface *surface; list_for_each_entry(connector, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 4faa1659f7f9..1bbeb87dc9d0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -52,10 +52,9 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); int amdgpu_dm_connector_get_modes(struct drm_connector *connector); -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool async); +void amdgpu_dm_atomic_commit_tail( + struct drm_atomic_state *state); + int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state); -- GitLab From 5f42aa394e50e4993ec370aca4bb36c3b6a81a60 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 13 Sep 2017 15:17:19 -0400 Subject: [PATCH 0290/2898] Revert "drm/amdgpu: Pulling old prepare and submit for flip back" This reverts commit 0eb4667a073e. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 138 ++++---------------- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 15 --- 2 files changed, 29 insertions(+), 124 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index b1079930630e..138beb550a58 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -138,52 +138,11 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) kfree(work); } - -static void amdgpu_flip_work_cleanup(struct amdgpu_flip_work *work) -{ - int i; - - amdgpu_bo_unref(&work->old_abo); - dma_fence_put(work->excl); - for (i = 0; i < work->shared_count; ++i) - dma_fence_put(work->shared[i]); - kfree(work->shared); - kfree(work); -} - -static void amdgpu_flip_cleanup_unreserve(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - amdgpu_bo_unreserve(new_abo); - amdgpu_flip_work_cleanup(work); -} - -static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) - DRM_ERROR("failed to unpin new abo in error path\n"); - amdgpu_flip_cleanup_unreserve(work, new_abo); -} - -void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - if (unlikely(amdgpu_bo_reserve(new_abo, true) != 0)) { - DRM_ERROR("failed to reserve new abo in error path\n"); - amdgpu_flip_work_cleanup(work); - return; - } - amdgpu_flip_cleanup_unpin(work, new_abo); -} - -int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct amdgpu_flip_work **work_p, - struct amdgpu_bo **new_abo_p) +int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, uint32_t target, + struct drm_modeset_acquire_ctx *ctx) { struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; @@ -196,7 +155,7 @@ int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, unsigned long flags; u64 tiling_flags; u64 base; - int r; + int i, r; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) @@ -257,80 +216,41 @@ int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); r = -EBUSY; goto pflip_cleanup; - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - *work_p = work; - *new_abo_p = new_abo; - - return 0; - -pflip_cleanup: - amdgpu_crtc_cleanup_flip_ctx(work, new_abo); - return r; - -unpin: - amdgpu_flip_cleanup_unpin(work, new_abo); - return r; - -unreserve: - amdgpu_flip_cleanup_unreserve(work, new_abo); - return r; -cleanup: - amdgpu_flip_work_cleanup(work); - return r; - -} - -void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - unsigned long flags; - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - spin_lock_irqsave(&crtc->dev->event_lock, flags); amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING; amdgpu_crtc->pflip_works = work; + + DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", + amdgpu_crtc->crtc_id, amdgpu_crtc, work); /* update crtc fb */ crtc->primary->fb = fb; spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - DRM_DEBUG_DRIVER( - "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", - amdgpu_crtc->crtc_id, amdgpu_crtc, work); - amdgpu_flip_work_func(&work->flip_work.work); -} - -int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct drm_modeset_acquire_ctx *ctx) -{ - struct amdgpu_bo *new_abo; - struct amdgpu_flip_work *work; - int r; + return 0; - r = amdgpu_crtc_prepare_flip(crtc, - fb, - event, - page_flip_flags, - target, - &work, - &new_abo); - if (r) - return r; +pflip_cleanup: + if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) { + DRM_ERROR("failed to reserve new abo in error path\n"); + goto cleanup; + } +unpin: + if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) { + DRM_ERROR("failed to unpin new abo in error path\n"); + } +unreserve: + amdgpu_bo_unreserve(new_abo); - amdgpu_crtc_submit_flip(crtc, fb, work, new_abo); +cleanup: + amdgpu_bo_unref(&work->old_abo); + dma_fence_put(work->excl); + for (i = 0; i < work->shared_count; ++i) + dma_fence_put(work->shared[i]); + kfree(work->shared); + kfree(work); - return 0; + return r; } int amdgpu_crtc_set_config(struct drm_mode_set *set, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 813108eab6fc..e5d2ce48cb1e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -670,21 +670,6 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx); -void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo); -int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct amdgpu_flip_work **work, - struct amdgpu_bo **new_abo); - -void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo); - extern const struct drm_mode_config_funcs amdgpu_mode_funcs; #endif -- GitLab From 92cc37fba0b54091b4dde4bced52c1b94d44e11f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 5 Feb 2017 21:48:19 -0500 Subject: [PATCH 0291/2898] drm/amd/display: Refactor headless to use atomic commit. (v2) Headless mode set needs to be synchronized against outstanding nonblocking commits. This achieved by building atomic state and commiting it. v2: rebase on 4.11 Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 140 ++++++++---------- 1 file changed, 61 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 956ff5a7b9b6..cfc86bc5dd2b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2602,6 +2602,65 @@ void amdgpu_dm_atomic_commit_tail( /* Release old FB */ drm_atomic_helper_cleanup_planes(dev, state); } + + +static int dm_force_atomic_commit(struct drm_connector *connector) +{ + int ret = 0; + struct drm_device *ddev = connector->dev; + struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); + struct amdgpu_crtc *disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + struct drm_plane *plane = disconnected_acrtc->base.primary; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_plane_state *plane_state; + + if (!state) + return -ENOMEM; + + state->acquire_ctx = ddev->mode_config.acquire_ctx; + + /* Construct an atomic state to restore previous display setting */ + + /* + * Attach connectors to drm_atomic_state + */ + conn_state = drm_atomic_get_connector_state(state, connector); + + ret = PTR_ERR_OR_ZERO(conn_state); + if (ret) + goto err; + + /* Attach crtc to drm_atomic_state*/ + crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base); + + ret = PTR_ERR_OR_ZERO(crtc_state); + if (ret) + goto err; + + /* force a restore */ + crtc_state->mode_changed = true; + + /* Attach plane to drm_atomic_state */ + plane_state = drm_atomic_get_plane_state(state, plane); + + ret = PTR_ERR_OR_ZERO(plane_state); + if (ret) + goto err; + + + /* Call commit internally with the state we just constructed */ + ret = drm_atomic_commit(state); + if (!ret) + return 0; + +err: + DRM_ERROR("Restoring old state failed with %i\n", ret); + drm_atomic_state_put(state); + + return ret; +} + /* * This functions handle all cases when set mode does not come upon hotplug. * This include when the same display is unplugged then plugged back into the @@ -2609,15 +2668,8 @@ void amdgpu_dm_atomic_commit_tail( */ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) { - struct drm_crtc *crtc; - struct amdgpu_device *adev = dev->dev_private; - struct dc *dc = adev->dm.dc; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct amdgpu_crtc *disconnected_acrtc; - const struct dc_sink *sink; - const struct dc_stream *commit_streams[MAX_STREAMS]; - const struct dc_stream *current_stream; - uint32_t commit_streams_count = 0; if (!aconnector->dc_sink || !connector->state || !connector->encoder) return; @@ -2627,83 +2679,13 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector if (!disconnected_acrtc || !disconnected_acrtc->stream) return; - sink = disconnected_acrtc->stream->sink; - /* * If the previous sink is not released and different from the current, * we deduce we are in a state where we can not rely on usermode call * to turn on the display, so we do it here */ - if (sink != aconnector->dc_sink) { - struct dm_connector_state *dm_state = - to_dm_connector_state(aconnector->base.state); - - struct dc_stream *new_stream = - create_stream_for_sink( - aconnector, - &disconnected_acrtc->base.state->mode, - dm_state); - - DRM_INFO("Headless hotplug, restoring connector state\n"); - /* - * we evade vblanks and pflips on crtc that - * should be changed - */ - manage_dm_interrupts(adev, disconnected_acrtc, false); - /* this is the update mode case */ - - current_stream = disconnected_acrtc->stream; - - disconnected_acrtc->stream = new_stream; - disconnected_acrtc->enabled = true; - disconnected_acrtc->hw_mode = disconnected_acrtc->base.state->mode; - - commit_streams_count = 0; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->stream) { - commit_streams[commit_streams_count] = acrtc->stream; - ++commit_streams_count; - } - } - - /* DC is optimized not to do anything if 'streams' didn't change. */ - if (!dc_commit_streams(dc, commit_streams, - commit_streams_count)) { - DRM_INFO("Failed to restore connector state!\n"); - dc_stream_release(disconnected_acrtc->stream); - disconnected_acrtc->stream = current_stream; - manage_dm_interrupts(adev, disconnected_acrtc, true); - return; - } - - if (adev->dm.freesync_module) { - mod_freesync_remove_stream(adev->dm.freesync_module, - current_stream); - - mod_freesync_add_stream(adev->dm.freesync_module, - new_stream, &aconnector->caps); - } - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->stream != NULL) { - acrtc->otg_inst = - dc_stream_get_status(acrtc->stream)->primary_otg_inst; - } - } - - dc_stream_release(current_stream); - - dm_dc_surface_commit(dc, &disconnected_acrtc->base); - - manage_dm_interrupts(adev, disconnected_acrtc, true); - dm_crtc_cursor_reset(&disconnected_acrtc->base); - - } + if (disconnected_acrtc->stream->sink != aconnector->dc_sink) + dm_force_atomic_commit(&aconnector->base); } static uint32_t add_val_sets_surface( -- GitLab From 2d60ded1325e0b4407aaa5396d1b331ea58f4f85 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 28 Feb 2017 16:45:46 -0500 Subject: [PATCH 0292/2898] drm/amd/display: Remove page_fleep_needed function. This function makes a lot of assumptions to try and deduce tha an atomic_commit came from FLIP ioctl. Those assumptions are not explicit contract with DRM API and might lead to wrong result as the code changes. Instead use drm_atomic_state.allow_modeset flag which explicitly is set to false only in atomic flip helper function, otherwise this flag is always true. P.S When we get to do actual atomic IOCTL this will have to be revised with the atomic call behavior. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 92 +------------------ 1 file changed, 3 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index cfc86bc5dd2b..098a801ae745 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1429,80 +1429,6 @@ static const struct drm_plane_funcs dm_plane_funcs = { .atomic_destroy_state = drm_atomic_helper_plane_destroy_state }; -static void clear_unrelated_fields(struct drm_plane_state *state) -{ - state->crtc = NULL; - state->fb = NULL; - state->state = NULL; - state->fence = NULL; -} - -/*TODO update because event is always present now */ -static bool page_flip_needed( - const struct drm_plane_state *new_state, - const struct drm_plane_state *old_state, - struct drm_pending_vblank_event *event, - bool commit_surface_required) -{ - struct drm_plane_state old_state_tmp; - struct drm_plane_state new_state_tmp; - - struct amdgpu_framebuffer *amdgpu_fb_old; - struct amdgpu_framebuffer *amdgpu_fb_new; - struct amdgpu_crtc *acrtc_new; - - uint64_t old_tiling_flags; - uint64_t new_tiling_flags; - - bool page_flip_required; - - if (!old_state) - return false; - - if (!old_state->fb) - return false; - - if (!new_state) - return false; - - if (!new_state->fb) - return false; - - old_state_tmp = *old_state; - new_state_tmp = *new_state; - - if (!event) - return false; - - amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb); - amdgpu_fb_new = to_amdgpu_framebuffer(new_state->fb); - - if (!get_fb_info(amdgpu_fb_old, &old_tiling_flags, NULL)) - return false; - - if (!get_fb_info(amdgpu_fb_new, &new_tiling_flags, NULL)) - return false; - - if (commit_surface_required == true && - old_tiling_flags != new_tiling_flags) - return false; - - clear_unrelated_fields(&old_state_tmp); - clear_unrelated_fields(&new_state_tmp); - - page_flip_required = memcmp(&old_state_tmp, - &new_state_tmp, - sizeof(old_state_tmp)) == 0 ? true:false; - - if (new_state->crtc && page_flip_required == false) { - acrtc_new = to_amdgpu_crtc(new_state->crtc); - if (acrtc_new->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) - page_flip_required = true; - } - - return page_flip_required; -} - static int dm_plane_helper_prepare_fb( struct drm_plane *plane, struct drm_plane_state *new_state) @@ -2477,11 +2403,7 @@ void amdgpu_dm_atomic_commit_tail( * 1. This commit is not a page flip. * 2. This commit is a page flip, and streams are created. */ - pflip_needed = !state->allow_modeset && - page_flip_needed( - plane_state, - old_plane_state, - crtc->state->event, true); + pflip_needed = !state->allow_modeset; if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON || action == DM_COMMIT_ACTION_SET) { @@ -2540,12 +2462,7 @@ void amdgpu_dm_atomic_commit_tail( if (!fb || !crtc || !crtc->state->planes_changed || !crtc->state->active) continue; - pflip_needed = !state->allow_modeset && - page_flip_needed( - plane_state, - old_plane_state, - crtc->state->event, - false); + pflip_needed = !state->allow_modeset; if (pflip_needed) { amdgpu_dm_do_flip( @@ -2927,7 +2844,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for (i = 0; i < set_count; i++) { for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_plane_state *old_plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; @@ -2948,9 +2864,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * 2. This commit is a page flip, and streams are created. */ crtc_state = drm_atomic_get_crtc_state(state, crtc); - pflip_needed = !state->allow_modeset && - page_flip_needed(plane_state, old_plane_state, - crtc_state->event, true); + pflip_needed = !state->allow_modeset; if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON || action == DM_COMMIT_ACTION_SET) { -- GitLab From d98e5cc2ddacb34e9cdf1c06dce2758198af0120 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 28 Feb 2017 21:30:32 -0500 Subject: [PATCH 0293/2898] drm/amd/display: clean up and simply locking logic always take update lock instead of using HW built in update lock trigger with write to primary_addr_lo. we will be a little more inefficient with the extra registers write to lock, but this simplify code and make it always correct. Will revisit locking optimization once update sequence mature Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 32 ++++++------------- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 3 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 - 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index efe50fd2be78..8f871924beb9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1321,22 +1321,22 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (pipe_ctx->surface != surface) continue; - /*lock all the MCPP if blnd is enable for DRR*/ - if ((update_type == UPDATE_TYPE_FAST && - (dc_stream->freesync_ctx.enabled == true && - surface_count != context->res_ctx.pool->pipe_count)) && - !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - lock_mask = PIPE_LOCK_CONTROL_MPCC_ADDR; + + if (update_type == UPDATE_TYPE_FULL) { + /* only apply for top pipe */ + if (!pipe_ctx->top_pipe) { + core_dc->hwss.apply_ctx_for_surface(core_dc, + surface, context); + context_timing_trace(dc, &context->res_ctx); + } } - if (update_type != UPDATE_TYPE_FAST && - !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { lock_mask = PIPE_LOCK_CONTROL_GRAPHICS | PIPE_LOCK_CONTROL_SCL | PIPE_LOCK_CONTROL_BLENDER | PIPE_LOCK_CONTROL_MODE; - } - if (lock_mask != 0) { + core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, @@ -1344,15 +1344,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, true); } - if (update_type == UPDATE_TYPE_FULL) { - /* only apply for top pipe */ - if (!pipe_ctx->top_pipe) { - core_dc->hwss.apply_ctx_for_surface(core_dc, - surface, context); - context_timing_trace(dc, &context->res_ctx); - } - } - if (updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); @@ -1382,9 +1373,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if ((update_type == UPDATE_TYPE_FAST) && lock_mask == 0) - return; - for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 1e1d60af8306..89a8274e12ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -52,8 +52,7 @@ void dce_pipe_control_lock(struct core_dc *dc, uint32_t lock_val = lock ? 1 : 0; uint32_t dcp_grph, scl, blnd, update_lock_mode, val; struct dce_hwseq *hws = dc->hwseq; - if (control_mask & PIPE_LOCK_CONTROL_MPCC_ADDR) - return; + val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx], BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, BLND_SCL_V_UPDATE_LOCK, &scl, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index a902de52107f..612910e720af 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -39,7 +39,6 @@ enum pipe_lock_control { PIPE_LOCK_CONTROL_BLENDER = 1 << 1, PIPE_LOCK_CONTROL_SCL = 1 << 2, PIPE_LOCK_CONTROL_MODE = 1 << 3, - PIPE_LOCK_CONTROL_MPCC_ADDR = 1 << 4 }; struct dce_hwseq_wa { -- GitLab From 773d1bcae744379a03f525bfc9249d8abf0550a8 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 28 Feb 2017 22:52:29 -0500 Subject: [PATCH 0294/2898] drm/amd/display: remove independent lock as we have no use case today Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 -------- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 19 +++++-------------- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 1 - .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 8 -------- 4 files changed, 5 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8f871924beb9..c34232c8c322 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1178,7 +1178,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, enum surface_update_type update_type; const struct dc_stream_status *stream_status; - unsigned int lock_mask = 0; stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); @@ -1332,15 +1331,9 @@ void dc_update_surfaces_for_stream(struct dc *dc, } if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - lock_mask = PIPE_LOCK_CONTROL_GRAPHICS | - PIPE_LOCK_CONTROL_SCL | - PIPE_LOCK_CONTROL_BLENDER | - PIPE_LOCK_CONTROL_MODE; - core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, - lock_mask, true); } @@ -1382,7 +1375,6 @@ void dc_update_surfaces_for_stream(struct dc *dc, core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, - lock_mask, false); } break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 89a8274e12ea..17cdd70a2c27 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -46,7 +46,6 @@ void dce_enable_fe_clock(struct dce_hwseq *hws, void dce_pipe_control_lock(struct core_dc *dc, struct pipe_ctx *pipe, - enum pipe_lock_control control_mask, bool lock) { uint32_t lock_val = lock ? 1 : 0; @@ -59,18 +58,10 @@ void dce_pipe_control_lock(struct core_dc *dc, BLND_BLND_V_UPDATE_LOCK, &blnd, BLND_V_UPDATE_LOCK_MODE, &update_lock_mode); - if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) - dcp_grph = lock_val; - - if (control_mask & PIPE_LOCK_CONTROL_SCL) - scl = lock_val; - - if (control_mask & PIPE_LOCK_CONTROL_BLENDER) - blnd = lock_val; - - if (control_mask & PIPE_LOCK_CONTROL_MODE) - update_lock_mode = lock_val; - + dcp_grph = lock_val; + scl = lock_val; + blnd = lock_val; + update_lock_mode = lock_val; REG_SET_2(BLND_V_UPDATE_LOCK[pipe->pipe_idx], val, BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph, @@ -82,7 +73,7 @@ void dce_pipe_control_lock(struct core_dc *dc, BLND_V_UPDATE_LOCK_MODE, update_lock_mode); if (hws->wa.blnd_crtc_trigger) { - if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) { + if (!lock) { uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->pipe_idx]); REG_WRITE(CRTC_H_BLANK_START_END[pipe->pipe_idx], value); } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 9ef618443255..70e0652be071 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -224,7 +224,6 @@ void dce_enable_fe_clock(struct dce_hwseq *hwss, void dce_pipe_control_lock(struct core_dc *dc, struct pipe_ctx *pipe, - enum pipe_lock_control control_mask, bool lock); void dce_set_blender_mode(struct dce_hwseq *hws, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 612910e720af..98a04cd46178 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -34,13 +34,6 @@ enum pipe_gating_control { PIPE_GATING_CONTROL_INIT }; -enum pipe_lock_control { - PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0, - PIPE_LOCK_CONTROL_BLENDER = 1 << 1, - PIPE_LOCK_CONTROL_SCL = 1 << 2, - PIPE_LOCK_CONTROL_MODE = 1 << 3, -}; - struct dce_hwseq_wa { bool blnd_crtc_trigger; }; @@ -128,7 +121,6 @@ struct hw_sequencer_funcs { void (*pipe_control_lock)( struct core_dc *dc, struct pipe_ctx *pipe, - enum pipe_lock_control control_mask, bool lock); void (*set_displaymarks)( -- GitLab From 3e337d15bf211ce1fe388d00a7f6a955550b3edf Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 1 Mar 2017 18:20:58 -0500 Subject: [PATCH 0295/2898] drm/amd/display: sometime VtotalMin less than VTotal (rounding issue) Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/freesync/freesync.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 2026ef34b11b..7a0731e2dbb0 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -905,7 +905,6 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); for (stream_index = 0; stream_index < num_streams; stream_index++) { - map_index = map_index_from_stream(core_freesync, streams[stream_index]); @@ -913,11 +912,12 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, if (core_freesync->map[map_index].caps->supported) { /* Update the field rate for new timing */ - state->nominal_refresh_rate_in_micro_hz = 1000000 * - div64_u64(div64_u64((streams[stream_index]-> - timing.pix_clk_khz * 1000), - streams[stream_index]->timing.v_total), - streams[stream_index]->timing.h_total); + unsigned long long temp; + temp = streams[stream_index]->timing.pix_clk_khz; + temp *= 1000ULL * 1000ULL * 1000ULL; + temp = div_u64(temp, streams[stream_index]->timing.h_total); + temp = div_u64(temp, streams[stream_index]->timing.v_total); + state->nominal_refresh_rate_in_micro_hz = (unsigned int) temp; /* Update the stream */ update_stream(core_freesync, streams[stream_index]); -- GitLab From 5869b0f6bc631d8c697018e7f1d873419da1dba2 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Wed, 1 Mar 2017 12:30:11 -0500 Subject: [PATCH 0296/2898] drm/amd/display: Adding FastUpdate functionality Exposing DC Api dc_check_update_surfaces_for_stream validation will return the answer which type of update is required, so upper layers can is it safe to call the update API fro high IRQ yes/no. Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 149 +++++++++++++++++++---- drivers/gpu/drm/amd/display/dc/dc.h | 12 ++ 2 files changed, 140 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c34232c8c322..27e31bd665ce 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1110,42 +1110,149 @@ static bool is_surface_in_context( return false; } -enum surface_update_type { - UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ - UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */ - UPDATE_TYPE_FULL, /* may need to shuffle resources */ -}; +static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) +{ + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + return 16; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + return 32; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + return 64; + default: + ASSERT_CRITICAL(false); + return -1; + } +} + +static enum surface_update_type get_plane_info_update_type( + const struct dc_surface_update *u) +{ + struct dc_plane_info temp_plane_info = { { { { 0 } } } }; + + if (!u->plane_info) + return UPDATE_TYPE_FAST; + + /* Copy all parameters that will cause a full update + * from current surface, the rest of the parameters + * from provided plane configuration. + * Perform memory compare and special validation + * for those that can cause fast/medium updates + */ + + /* Full update parameters */ + temp_plane_info.color_space = u->surface->color_space; + temp_plane_info.dcc = u->surface->dcc; + temp_plane_info.horizontal_mirror = u->surface->horizontal_mirror; + temp_plane_info.plane_size = u->surface->plane_size; + temp_plane_info.rotation = u->surface->rotation; + temp_plane_info.stereo_format = u->surface->stereo_format; + temp_plane_info.tiling_info = u->surface->tiling_info; + temp_plane_info.visible = u->surface->visible; + + /* Special Validation parameters */ + temp_plane_info.format = u->plane_info->format; + + if (memcmp(u->plane_info, &temp_plane_info, + sizeof(struct dc_plane_info)) != 0) + return UPDATE_TYPE_FULL; + + if (pixel_format_to_bpp(u->plane_info->format) != + pixel_format_to_bpp(u->surface->format)) { + return UPDATE_TYPE_FULL; + } else { + return UPDATE_TYPE_MED; + } +} + +static enum surface_update_type get_scaling_info_update_type( + const struct dc_surface_update *u) +{ + struct dc_scaling_info temp_scaling_info = { { 0 } }; + + if (!u->scaling_info) + return UPDATE_TYPE_FAST; + + /* Copy all parameters that will cause a full update + * from current surface, the rest of the parameters + * from provided plane configuration. + * Perform memory compare and special validation + * for those that can cause fast/medium updates + */ + + /* Full Update Parameters */ + temp_scaling_info.dst_rect = u->surface->dst_rect; + temp_scaling_info.src_rect = u->surface->src_rect; + temp_scaling_info.scaling_quality = u->surface->scaling_quality; + + /* Special validation required */ + temp_scaling_info.clip_rect = u->scaling_info->clip_rect; + + if (memcmp(u->scaling_info, &temp_scaling_info, + sizeof(struct dc_scaling_info)) != 0) + return UPDATE_TYPE_FULL; + + /* Check Clip rectangles if not equal + * difference is in offsets == > UPDATE_TYPE_FAST + * difference is in dimensions == > UPDATE_TYPE_FULL + */ + if (memcmp(&u->scaling_info->clip_rect, + &u->surface->clip_rect, sizeof(struct rect)) != 0) { + if ((u->scaling_info->clip_rect.height == + u->surface->clip_rect.height) && + (u->scaling_info->clip_rect.width == + u->surface->clip_rect.width)) { + return UPDATE_TYPE_FAST; + } else { + return UPDATE_TYPE_FULL; + } + } + + return UPDATE_TYPE_FAST; +} static enum surface_update_type det_surface_update( const struct core_dc *dc, const struct dc_surface_update *u) { const struct validate_context *context = dc->current_context; - - if (u->scaling_info || u->plane_info) - /* todo: not all scale and plane_info update need full update - * ie. check if following is the same - * scale ratio, view port, surface bpp etc - */ - return UPDATE_TYPE_FULL; /* may need bandwidth update */ + enum surface_update_type type = UPDATE_TYPE_FAST; + enum surface_update_type overall_type = UPDATE_TYPE_FAST; if (!is_surface_in_context(context, u->surface)) return UPDATE_TYPE_FULL; + type = get_plane_info_update_type(u); + if (overall_type < type) + overall_type = type; + + type = get_scaling_info_update_type(u); + if (overall_type < type) + overall_type = type; + if (u->in_transfer_func || u->out_transfer_func || - u->hdr_static_metadata) - return UPDATE_TYPE_MED; + u->hdr_static_metadata) { + if (overall_type < UPDATE_TYPE_MED) + overall_type = UPDATE_TYPE_MED; + } - return UPDATE_TYPE_FAST; + return overall_type; } -static enum surface_update_type check_update_surfaces_for_stream( - struct core_dc *dc, +enum surface_update_type dc_check_update_surfaces_for_stream( + struct dc *dc, struct dc_surface_update *updates, int surface_count, const struct dc_stream_status *stream_status) { + struct core_dc *core_dc = DC_TO_CORE(dc); int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; @@ -1154,7 +1261,7 @@ static enum surface_update_type check_update_surfaces_for_stream( for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = - det_surface_update(dc, &updates[i]); + det_surface_update(core_dc, &updates[i]); if (type == UPDATE_TYPE_FULL) return type; @@ -1184,8 +1291,8 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (!stream_status) return; /* Cannot commit surface to stream that is not committed */ - update_type = check_update_surfaces_for_stream( - core_dc, updates, surface_count, stream_status); + update_type = dc_check_update_surfaces_for_stream( + dc, updates, surface_count, stream_status); if (update_type >= update_surface_trace_level) update_surface_trace(dc, updates, surface_count); @@ -1321,7 +1428,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (pipe_ctx->surface != surface) continue; - if (update_type == UPDATE_TYPE_FULL) { + if (update_type >= UPDATE_TYPE_MED) { /* only apply for top pipe */ if (!pipe_ctx->top_pipe) { core_dc->hwss.apply_ctx_for_surface(core_dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2d84b18f48b0..69ae94bb209f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -379,6 +379,12 @@ bool dc_post_update_surfaces_to_stream( void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, int surface_count, const struct dc_stream *stream); +enum surface_update_type { + UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ + UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */ + UPDATE_TYPE_FULL, /* may need to shuffle resources */ +}; + /******************************************************************************* * Stream Interfaces ******************************************************************************/ @@ -498,6 +504,12 @@ struct dc_stream_status { const struct dc_stream_status *dc_stream_get_status( const struct dc_stream *dc_stream); +enum surface_update_type dc_check_update_surfaces_for_stream( + struct dc *dc, + struct dc_surface_update *updates, + int surface_count, + const struct dc_stream_status *stream_status); + /******************************************************************************* * Link Interfaces ******************************************************************************/ -- GitLab From ece4f358cb57c33089daaea1d86c62fa924060d1 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 1 Mar 2017 09:46:20 -0500 Subject: [PATCH 0297/2898] drm/amd/display: Simplify some DMCU waits Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 1 + .../gpu/drm/amd/display/dc/dce/dce_clocks.h | 1 - drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 46 ++++--------------- 3 files changed, 9 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 3e3eefea3e82..ac1febafcaa4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -387,6 +387,7 @@ static void dce112_set_clock( CLOCK_SOURCE_COMBO_DISPLAY_PLL0); bp->funcs->set_dce_clock(bp, &dce_clk_params); + } static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 4ad6fe4c2841..020ab9d5434d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -45,7 +45,6 @@ CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) - #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ type DENTIST_DPREFCLK_WDIVIDER; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 44eeeeb888fe..da7f86b61de4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -57,19 +57,13 @@ bool dce_dmcu_load_iram(struct dmcu *dmcu, { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); unsigned int count = 0; - uint32_t status; /* Enable write access to IRAM */ REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1, IRAM_WR_ADDR_AUTO_INC, 1); - do { - dm_delay_in_microseconds(dmcu->ctx, 2); - REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &status); - count++; - } while - ((status & dmcu_dce->dmcu_mask->DMCU_IRAM_MEM_PWR_STATE) && count < 10); + REG_WAIT(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); REG_WRITE(DMCU_IRAM_WR_CTRL, start_offset); @@ -88,21 +82,12 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); - uint32_t count = 0; uint32_t psrStateOffset = 0xf0; - uint32_t value = -1; /* Enable write access to IRAM */ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); - while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) { - dm_delay_in_microseconds(dmcu->ctx, 2); - REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value); - } - while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) { - dm_delay_in_microseconds(dmcu->ctx, 2); - REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value); - } + REG_WAIT(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); @@ -122,21 +107,13 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) unsigned int dmcu_max_retry_on_wait_reg_ready = 801; unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; - unsigned int retryCount; uint32_t psr_state = 0; /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(dmcu->ctx, - dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + dmcu_wait_reg_ready_interval, + dmcu_max_retry_on_wait_reg_ready); /* setDMCUParam_Cmd */ if (enable) @@ -170,7 +147,6 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, unsigned int dmcu_max_retry_on_wait_reg_ready = 801; unsigned int dmcu_wait_reg_ready_interval = 100; - unsigned int regValue; union dce_dmcu_psr_config_data_reg1 masterCmdData1; union dce_dmcu_psr_config_data_reg2 masterCmdData2; @@ -231,15 +207,9 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); /* waitDMCUReadyForCmd */ - do { - dm_delay_in_microseconds(dmcu->ctx, - dmcu_wait_reg_ready_interval); - regValue = REG_READ(MASTER_COMM_CNTL_REG); - dmcu_max_retry_on_wait_reg_ready--; - } while - /* expected value is 0, loop while not 0*/ - ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) && - dmcu_max_retry_on_wait_reg_ready > 0); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + dmcu_wait_reg_ready_interval, + dmcu_max_retry_on_wait_reg_ready); /* setDMCUParam_PSRHostConfigData */ masterCmdData1.u32All = 0; -- GitLab From e8c963d6d970220ab33f4197ab4dea18c1615e52 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 2 Mar 2017 21:18:03 -0500 Subject: [PATCH 0298/2898] drm/amd/display: refclock from bios firmwareInfoTable Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +++++++++- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + .../drm/amd/display/dc/dce/dce_clock_source.c | 17 ++++++----------- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 27e31bd665ce..302a10c86afb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -467,6 +467,8 @@ static bool construct(struct core_dc *dc, else { /* Create BIOS parser */ struct bp_init_data bp_init_data; + struct firmware_info fw_info = { { 0 } }; + bp_init_data.ctx = dc_ctx; bp_init_data.bios = init_params->asic_id.atombios_base_address; @@ -479,7 +481,13 @@ static bool construct(struct core_dc *dc, } dc_ctx->created_bios = true; - } + + if (dc_ctx->dc_bios->funcs->get_firmware_info( + dc_ctx->dc_bios, &fw_info) == BP_RESULT_OK) { + dc->ctx->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; + } else + ASSERT_CRITICAL(false); + } /* Create I2C AUX */ dc_ctx->i2caux = dal_i2caux_create(dc_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 4e1a933be021..365a19e5d11c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -237,7 +237,7 @@ bool dc_stream_set_cursor_position( struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, - .ref_clk_khz = 48000,/*todo refclk*/ + .ref_clk_khz = core_dc->ctx->ref_clock_inKhz, .viewport_x_start = pipe_ctx->scl_data.viewport.x, .viewport_width = pipe_ctx->scl_data.viewport.width, .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 242dd7b3b6b1..c428a0249488 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -91,6 +91,7 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; + unsigned int ref_clock_inKhz; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index a2a2ecf8d077..1d6a9da45ba6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1230,17 +1230,12 @@ bool dce110_clk_src_construct( goto unexpected_failure; } - if (clk_src->ref_freq_khz == 48000) { - calc_pll_cs_init_data_hdmi. - min_override_input_pxl_clk_pll_freq_khz = 24000; - calc_pll_cs_init_data_hdmi. - max_override_input_pxl_clk_pll_freq_khz = 48000; - } else if (clk_src->ref_freq_khz == 100000) { - calc_pll_cs_init_data_hdmi. - min_override_input_pxl_clk_pll_freq_khz = 25000; - calc_pll_cs_init_data_hdmi. - max_override_input_pxl_clk_pll_freq_khz = 50000; - } + + calc_pll_cs_init_data_hdmi. + min_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz/2; + calc_pll_cs_init_data_hdmi. + max_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz; + if (!calc_pll_max_vco_construct( &clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) { -- GitLab From 68339af3cb7fa32634170fe5cf5cba1335bb8cc9 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Fri, 3 Mar 2017 14:37:08 -0500 Subject: [PATCH 0299/2898] drm/amd/display: Memory leak fix during disable 1.current_context memory wasn't released at dc_post_update_surfaces_to_stream during context swap. Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 302a10c86afb..4fed2f25cd96 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1046,6 +1046,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) core_dc->hwss.set_bandwidth(core_dc, context, true); resource_validate_ctx_destruct(core_dc->current_context); + if (core_dc->current_context) + dm_free(core_dc->current_context); + core_dc->current_context = context; return true; -- GitLab From 5ac3d3c9b79fb607fc25268c8dbd220ac14f5ac6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 3 Mar 2017 13:44:35 -0500 Subject: [PATCH 0300/2898] drm/amd/display: move refclk from dc to resource_pool Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ------ .../gpu/drm/amd/display/dc/core/dc_resource.c | 25 +++++++++++++++---- .../gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 - .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4fed2f25cd96..f1ec27365f56 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -467,7 +467,6 @@ static bool construct(struct core_dc *dc, else { /* Create BIOS parser */ struct bp_init_data bp_init_data; - struct firmware_info fw_info = { { 0 } }; bp_init_data.ctx = dc_ctx; bp_init_data.bios = init_params->asic_id.atombios_base_address; @@ -481,12 +480,6 @@ static bool construct(struct core_dc *dc, } dc_ctx->created_bios = true; - - if (dc_ctx->dc_bios->funcs->get_firmware_info( - dc_ctx->dc_bios, &fw_info) == BP_RESULT_OK) { - dc->ctx->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; - } else - ASSERT_CRITICAL(false); } /* Create I2C AUX */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 407ce60f253e..f1b1dae5399e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -31,6 +31,7 @@ #include "opp.h" #include "timing_generator.h" #include "transform.h" +#include "core_types.h" #include "set_mode_types.h" #include "virtual/virtual_stream_encoder.h" @@ -77,25 +78,39 @@ struct resource_pool *dc_create_resource_pool( enum dce_version dc_version, struct hw_asic_id asic_id) { + struct resource_pool *res_pool = NULL; switch (dc_version) { case DCE_VERSION_8_0: - return dce80_create_resource_pool( + res_pool = dce80_create_resource_pool( num_virtual_links, dc); + break; case DCE_VERSION_10_0: - return dce100_create_resource_pool( + res_pool = dce100_create_resource_pool( num_virtual_links, dc); + break; case DCE_VERSION_11_0: - return dce110_create_resource_pool( + res_pool = dce110_create_resource_pool( num_virtual_links, dc, asic_id); + break; case DCE_VERSION_11_2: - return dce112_create_resource_pool( + res_pool = dce112_create_resource_pool( num_virtual_links, dc); + break; default: break; } + if (res_pool != NULL) { + struct firmware_info fw_info = { { 0 } }; + + if (dc->ctx->dc_bios->funcs->get_firmware_info( + dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) { + res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency; + } else + ASSERT_CRITICAL(false); + } - return false; + return res_pool; } void dc_destroy_resource_pool(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 365a19e5d11c..bafba1f13a1a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -237,7 +237,7 @@ bool dc_stream_set_cursor_position( struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, - .ref_clk_khz = core_dc->ctx->ref_clock_inKhz, + .ref_clk_khz = res_ctx->pool->ref_clock_inKhz, .viewport_x_start = pipe_ctx->scl_data.viewport.x, .viewport_width = pipe_ctx->scl_data.viewport.width, .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index c428a0249488..242dd7b3b6b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -91,7 +91,6 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; - unsigned int ref_clock_inKhz; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index e8fe333c5918..b29fca9dfeff 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -239,6 +239,7 @@ struct resource_pool { unsigned int pipe_count; unsigned int underlay_pipe_index; unsigned int stream_enc_count; + unsigned int ref_clock_inKhz; /* * reserved clock source for DP -- GitLab From c30267f5023aef44d4367c631c42f217a2ec37f6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 3 Mar 2017 15:16:03 -0500 Subject: [PATCH 0301/2898] drm/amd/display: TPS4 logic typo fix Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Wenjing Liu Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 37efa40a9bca..80002795adc2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -921,8 +921,8 @@ static inline bool perform_link_training_int( * If the upstream DPTX and downstream DPRX both support TPS4, * TPS4 must be used instead of POST_LT_ADJ_REQ. */ - if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 && - get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4) + if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 || + get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4) return status; if (status && -- GitLab From f196f0805b5b75f024481ab4dc65f60d86fe6441 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 3 Mar 2017 09:37:11 -0500 Subject: [PATCH 0302/2898] drm/amd/display: After program backend, also program front end regs. Issue: In case of two 4K@60 + one non-4k monitor, when unplug non-4k monitor, the remain two 4k monitor don't work properly. Reason: In that case, two 4k use two pipes and no split, when unplug happens, those two monitor will use 4 pipes and split, but on that time, frontend is not programed properly. Solution: After programed backend, front end should be programmed as per new pipe setting. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f1ec27365f56..a39b9987b9d6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -806,7 +806,7 @@ bool dc_commit_streams( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; - int i, j, k; + int i, j; if (false == streams_changed(core_dc, streams, stream_count)) return DC_OK; @@ -862,18 +862,10 @@ bool dc_commit_streams( const struct core_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].surface_count; j++) { - const struct dc_surface *dc_surface = - context->stream_status[i].surfaces[j]; - - for (k = 0; k < context->res_ctx.pool->pipe_count; k++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[k]; + struct core_surface *surface = + DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); - if (dc_surface != &pipe->surface->public - || !dc_surface->visible) - continue; - - pipe->tg->funcs->set_blank(pipe->tg, false); - } + core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", -- GitLab From 268cadbd653d3d9172975a46c79f458475f82cb5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 6 Mar 2017 14:58:59 -0500 Subject: [PATCH 0303/2898] drm/amd/display: Do not copy bottom pipe when map resource. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f1b1dae5399e..c38f71e45381 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1134,6 +1134,9 @@ enum dc_status resource_map_pool_resources( if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) continue; + if (old_pipe_ctx->top_pipe) + continue; + pipe_ctx->stream = stream; copy_pipe_ctx(old_pipe_ctx, pipe_ctx); -- GitLab From a36214858c9093086c1bf1415af6b67c220d711f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 20 Apr 2017 15:59:25 -0400 Subject: [PATCH 0304/2898] drm/amd/display: Switch to DRM helpers in s3. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 157 ++---------------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 5 + drivers/gpu/drm/amd/display/dc/core/dc.c | 8 +- drivers/gpu/drm/amd/display/dc/dc.h | 3 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 4 - 5 files changed, 21 insertions(+), 156 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index da499ab7eab5..a69ce27b8ed6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -451,28 +451,17 @@ static int dm_suspend(void *handle) struct amdgpu_device *adev = handle; struct amdgpu_display_manager *dm = &adev->dm; int ret = 0; - struct drm_crtc *crtc; s3_handle_mst(adev->ddev, true); - /* flash all pending vblank events and turn interrupt off - * before disabling CRTCs. They will be enabled back in - * dm_display_resume - */ - drm_modeset_lock_all(adev->ddev); - list_for_each_entry(crtc, &adev->ddev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->stream) - drm_crtc_vblank_off(crtc); - } - drm_modeset_unlock_all(adev->ddev); - amdgpu_dm_irq_suspend(adev); + adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); + dc_set_power_state( dm->dc, - DC_ACPI_CM_POWER_STATE_D3, - DC_VIDEO_POWER_SUSPEND); + DC_ACPI_CM_POWER_STATE_D3 + ); return ret; } @@ -504,120 +493,6 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( return NULL; } -static int dm_display_resume(struct drm_device *ddev) -{ - int ret = 0; - struct drm_connector *connector; - - struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); - struct drm_plane *plane; - struct drm_crtc *crtc; - struct amdgpu_connector *aconnector; - struct drm_connector_state *conn_state; - - if (!state) - return ENOMEM; - - state->acquire_ctx = ddev->mode_config.acquire_ctx; - - /* Construct an atomic state to restore previous display setting */ - - /* - * Attach connectors to drm_atomic_state - * Should be done in the first place in order to make connectors - * available in state during crtc state processing. It is used for - * making decision if crtc should be disabled in case sink got - * disconnected. - * - * Connectors state crtc with NULL dc_sink should be cleared, because it - * will fail validation during commit - */ - list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); - conn_state = drm_atomic_get_connector_state(state, connector); - - ret = PTR_ERR_OR_ZERO(conn_state); - if (ret) - goto err; - } - - /* Attach crtcs to drm_atomic_state*/ - list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { - struct drm_crtc_state *crtc_state = - drm_atomic_get_crtc_state(state, crtc); - - ret = PTR_ERR_OR_ZERO(crtc_state); - if (ret) - goto err; - - /* force a restore */ - crtc_state->mode_changed = true; - } - - - /* Attach planes to drm_atomic_state */ - list_for_each_entry(plane, &ddev->mode_config.plane_list, head) { - - struct drm_crtc *crtc; - struct drm_gem_object *obj; - struct drm_framebuffer *fb; - struct amdgpu_framebuffer *afb; - struct amdgpu_bo *rbo; - int r; - struct drm_plane_state *plane_state = drm_atomic_get_plane_state(state, plane); - - ret = PTR_ERR_OR_ZERO(plane_state); - if (ret) - goto err; - - crtc = plane_state->crtc; - fb = plane_state->fb; - - if (!crtc || !crtc->state || !crtc->state->active) - continue; - - if (!fb) { - DRM_DEBUG_KMS("No FB bound\n"); - return 0; - } - - /* - * Pin back the front buffers, cursor buffer was already pinned - * back in amdgpu_resume_kms - */ - - afb = to_amdgpu_framebuffer(fb); - - obj = afb->obj; - rbo = gem_to_amdgpu_bo(obj); - r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL); - - amdgpu_bo_unreserve(rbo); - - if (unlikely(r != 0)) { - DRM_ERROR("Failed to pin framebuffer\n"); - return r; - } - - } - - - /* Call commit internally with the state we just constructed */ - ret = drm_atomic_commit(state); - if (!ret) - return 0; - -err: - DRM_ERROR("Restoring old state failed with %i\n", ret); - drm_atomic_state_put(state); - - return ret; -} - static int dm_resume(void *handle) { struct amdgpu_device *adev = handle; @@ -626,8 +501,8 @@ static int dm_resume(void *handle) /* power on hardware */ dc_set_power_state( dm->dc, - DC_ACPI_CM_POWER_STATE_D0, - DC_VIDEO_POWER_ON); + DC_ACPI_CM_POWER_STATE_D0 + ); return 0; } @@ -638,8 +513,10 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) struct amdgpu_display_manager *dm = &adev->dm; struct amdgpu_connector *aconnector; struct drm_connector *connector; - int ret = 0; struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int ret = 0; + int i; /* program HPD filter */ dc_resume(dm->dc); @@ -653,14 +530,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) */ amdgpu_dm_irq_resume_early(adev); - drm_modeset_lock_all(ddev); - list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->stream) - drm_crtc_vblank_on(crtc); - } - drm_modeset_unlock_all(ddev); - /* Do detection*/ list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { @@ -678,9 +547,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) amdgpu_dm_update_connector_after_detect(aconnector); } - drm_modeset_lock_all(ddev); - ret = dm_display_resume(ddev); - drm_modeset_unlock_all(ddev); + /* Force mode set in atomic comit */ + for_each_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i) + crtc_state->active_changed = true; + + ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); amdgpu_dm_irq_resume(adev); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index d6ebba012e15..ee69179636a1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -128,6 +128,11 @@ struct amdgpu_display_manager { struct work_struct mst_hotplug_work; struct mod_freesync *freesync_module; + + /** + * Caches device atomic state for suspend/resume + */ + struct drm_atomic_state *cached_state; }; /* basic init/fini API */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a39b9987b9d6..edcb731a3aea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1589,21 +1589,15 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) void dc_set_power_state( struct dc *dc, - enum dc_acpi_cm_power_state power_state, - enum dc_video_power_state video_power_state) + enum dc_acpi_cm_power_state power_state) { struct core_dc *core_dc = DC_TO_CORE(dc); - core_dc->previous_power_state = core_dc->current_power_state; - core_dc->current_power_state = video_power_state; - switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: core_dc->hwss.init_hw(core_dc); break; default: - /* NULL means "reset/release all DC streams" */ - dc_commit_streams(dc, NULL, 0); core_dc->hwss.power_down(core_dc); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 69ae94bb209f..e2c2a0bf764d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -705,8 +705,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index( void dc_set_power_state( struct dc *dc, - enum dc_acpi_cm_power_state power_state, - enum dc_video_power_state video_power_state); + enum dc_acpi_cm_power_state power_state); void dc_resume(const struct dc *dc); /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 7a6444dc2957..8d87f490dc1c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -26,10 +26,6 @@ struct core_dc { struct validate_context *scratch_val_ctx; struct resource_pool *res_pool; - /*Power State*/ - enum dc_video_power_state previous_power_state; - enum dc_video_power_state current_power_state; - /* Display Engine Clock levels */ struct dm_pp_clock_levels sclk_lvls; -- GitLab From 4a9a5d62ec01755d36aa72782ff023da417b472a Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 7 Mar 2017 11:48:50 -0500 Subject: [PATCH 0305/2898] drm/amd/display: Refactor on dc_sink structure. Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 9 ++++----- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 -- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d275fc88f71e..5ca72afe8f6f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -675,10 +675,6 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) sink_init_data.link = &link->public; sink_init_data.sink_signal = sink_caps.signal; - sink_init_data.dongle_max_pix_clk = - sink_caps.max_hdmi_pixel_clock; - sink_init_data.converter_disable_audio = - converter_disable_audio; dc_sink = dc_sink_create(&sink_init_data); if (!dc_sink) { @@ -686,6 +682,9 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) return false; } + dc_sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + dc_sink->converter_disable_audio = converter_disable_audio; + sink = DC_SINK_TO_CORE(dc_sink); link->public.local_sink = &sink->public; @@ -1361,7 +1360,7 @@ enum dc_status dc_link_validate_mode_timing( struct core_link *link, const struct dc_crtc_timing *timing) { - uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; + uint32_t max_pix_clk = stream->sink->public.dongle_max_pix_clk; /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c38f71e45381..326019407cb1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1193,7 +1193,7 @@ enum dc_status resource_map_pool_resources( pipe_ctx->stream_enc); /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->converter_disable_audio && + if (!stream->sink->public.converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->public.audio_info.mode_count) { pipe_ctx->audio = find_first_free_audio( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 0a805ea1159a..8a204731301d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -60,8 +60,8 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa sink->protected.public.sink_signal = init_params->sink_signal; sink->protected.link = core_link; sink->protected.ctx = core_link->ctx; - sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk; - sink->protected.converter_disable_audio = + sink->protected.public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; + sink->protected.public.converter_disable_audio = init_params->converter_disable_audio; return true; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e2c2a0bf764d..c6c0cf500ae8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -653,6 +653,8 @@ struct dc_sink { enum signal_type sink_signal; struct dc_edid dc_edid; /* raw edid */ struct dc_edid_caps edid_caps; /* parse display caps */ + uint32_t dongle_max_pix_clk; + bool converter_disable_audio; }; void dc_sink_retain(const struct dc_sink *sink); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b29fca9dfeff..faec2292cc27 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -109,8 +109,6 @@ struct core_sink { /* not used for now */ struct core_link *link; struct dc_context *ctx; - uint32_t dongle_max_pix_clk; - bool converter_disable_audio; }; /************ link *****************/ -- GitLab From b2d0a103e6a0a823b46dd2d7f8c2de82c419e286 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 1 Mar 2017 18:27:17 -0500 Subject: [PATCH 0306/2898] drm/amd/display: add init calculation to scaler params Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 245 +++++++++++++++--- .../display/dc/dce110/dce110_hw_sequencer.c | 1 + .../gpu/drm/amd/display/dc/inc/hw/transform.h | 11 + drivers/gpu/drm/amd/display/dc/inc/resource.h | 4 +- 5 files changed, 229 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index edcb731a3aea..b9ca9688f8a3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -971,8 +971,7 @@ bool dc_pre_update_surfaces_to_stream( DC_SURFACE_TO_CORE(new_surfaces[i])) continue; - resource_build_scaling_params( - new_surfaces[i], &context->res_ctx.pipe_ctx[j]); + resource_build_scaling_params(&context->res_ctx.pipe_ctx[j]); } if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { @@ -1364,7 +1363,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, if (pipe_ctx->surface != surface) continue; - resource_build_scaling_params(updates[i].surface, pipe_ctx); + resource_build_scaling_params(pipe_ctx); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 326019407cb1..d4b338fa4ab9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -401,15 +401,17 @@ static void rect_swap_helper(struct rect *rect) rect->y = temp; } -static void calculate_viewport( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx) +static void calculate_viewport(struct pipe_ctx *pipe_ctx) { + const struct dc_surface *surface = &pipe_ctx->surface->public; + struct scaler_data *data = &pipe_ctx->scl_data; struct rect stream_src = pipe_ctx->stream->public.src; struct rect src = surface->src_rect; struct rect dst = surface->dst_rect; struct rect surface_clip = surface->clip_rect; struct rect clip = {0}; + int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 + || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; if (surface->rotation == ROTATION_ANGLE_90 || @@ -442,27 +444,45 @@ static void calculate_viewport( /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio * num_pixels = clip.num_pix * scl_ratio */ - pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) * + data->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width; - pipe_ctx->scl_data.viewport.width = clip.width * + data->viewport.width = clip.width * src.width / dst.width; - pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) * + data->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height; - pipe_ctx->scl_data.viewport.height = clip.height * + data->viewport.height = clip.height * src.height / dst.height; - /* Minimum viewport such that 420/422 chroma vp is non 0 */ - if (pipe_ctx->scl_data.viewport.width < 2) - pipe_ctx->scl_data.viewport.width = 2; - if (pipe_ctx->scl_data.viewport.height < 2) - pipe_ctx->scl_data.viewport.height = 2; + /* Round down, compensate in init */ + data->viewport_c.x = data->viewport.x / vpc_div; + data->viewport_c.y = data->viewport.y / vpc_div; + data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? + dal_fixed31_32_half : dal_fixed31_32_zero; + data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? + dal_fixed31_32_half : dal_fixed31_32_zero; + /* Round up, assume original video size always even dimensions */ + data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; + data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; + + /* Handle hsplit */ + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; + data->viewport.x += data->viewport.width; + data->viewport_c.x += data->viewport_c.width; + /* Floor primary pipe, ceil 2ndary pipe */ + data->viewport.width += data->viewport.width % 2; + data->viewport_c.width += data->viewport_c.width % 2; + } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; + } } -static void calculate_recout( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx) +static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { + const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; struct rect clip = surface->clip_rect; @@ -493,12 +513,26 @@ static void calculate_recout( pipe_ctx->scl_data.recout.height = stream->public.dst.y + stream->public.dst.height - pipe_ctx->scl_data.recout.y; + + /* Handle hsplit */ + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + pipe_ctx->scl_data.recout.width /= 2; + pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; + /* Floor primary pipe, ceil 2ndary pipe */ + pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; + } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + pipe_ctx->scl_data.recout.width /= 2; + } + + recout_skip->width = pipe_ctx->scl_data.recout.x - stream->public.dst.x - + surface->dst_rect.x * stream->public.dst.width / stream->public.src.width; + recout_skip->height = pipe_ctx->scl_data.recout.y - stream->public.dst.y - + surface->dst_rect.y * stream->public.dst.height / stream->public.src.height; } -static void calculate_scaling_ratios( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx) +static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { + const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; const uint32_t in_w = stream->public.src.width; const uint32_t in_h = stream->public.src.height; @@ -525,31 +559,179 @@ static void calculate_scaling_ratios( pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; - if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) { + if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12 + || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP15) { pipe_ctx->scl_data.ratios.horz_c.value /= 2; pipe_ctx->scl_data.ratios.vert_c.value /= 2; } } -bool resource_build_scaling_params( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx) +static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - bool res; + struct scaler_data *data = &pipe_ctx->scl_data; + struct rect src = pipe_ctx->surface->public.src_rect; + int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 + || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + + /* + * Init calculated according to formula: + * init = (scaling_ratio + number_of_taps + 1) / 2 + * init_bot = init + scaling_ratio + * init_c = init + truncated_vp_c_offset(from calculate viewport) + */ + data->inits.h = dal_fixed31_32_div_int( + dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2); + + data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int( + dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)); + + data->inits.v = dal_fixed31_32_div_int( + dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2); + + data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int( + dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)); + + + /* Adjust for viewport end clip-off */ + if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { + int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; + int int_part = dal_fixed31_32_floor(data->inits.h); + + data->viewport.width += int_part < vp_clip ? int_part : vp_clip; + } + if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { + int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; + int int_part = dal_fixed31_32_floor(data->inits.v); + + data->viewport.height += int_part < vp_clip ? int_part : vp_clip; + } + if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { + int vp_clip = (src.x + src.width) / vpc_div - + data->viewport_c.width - data->viewport_c.x; + int int_part = dal_fixed31_32_floor(data->inits.h_c); + + data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; + } + if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { + int vp_clip = (src.y + src.height) / vpc_div - + data->viewport_c.height - data->viewport_c.y; + int int_part = dal_fixed31_32_floor(data->inits.v_c); + + data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; + } + + /* Adjust for non-0 viewport offset */ + if (data->viewport.x) { + int int_part; + + data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( + data->ratios.horz, recout_skip->width)); + int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x; + if (int_part < data->taps.h_taps) { + int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? + (data->taps.h_taps - int_part) : data->viewport.x; + data->viewport.x -= int_adj; + data->viewport.width += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.h_taps) { + data->viewport.x += int_part - data->taps.h_taps; + data->viewport.width -= int_part - data->taps.h_taps; + int_part = data->taps.h_taps; + } + data->inits.h.value &= 0xffffffff; + data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); + } + + if (data->viewport_c.x) { + int int_part; + + data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( + data->ratios.horz_c, recout_skip->width)); + int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x; + if (int_part < data->taps.h_taps_c) { + int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? + (data->taps.h_taps_c - int_part) : data->viewport_c.x; + data->viewport_c.x -= int_adj; + data->viewport_c.width += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.h_taps_c) { + data->viewport_c.x += int_part - data->taps.h_taps_c; + data->viewport_c.width -= int_part - data->taps.h_taps_c; + int_part = data->taps.h_taps_c; + } + data->inits.h_c.value &= 0xffffffff; + data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); + } + + if (data->viewport.y) { + int int_part; + + data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( + data->ratios.vert, recout_skip->height)); + int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y; + if (int_part < data->taps.v_taps) { + int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? + (data->taps.v_taps - int_part) : data->viewport.y; + data->viewport.y -= int_adj; + data->viewport.height += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.v_taps) { + data->viewport.y += int_part - data->taps.v_taps; + data->viewport.height -= int_part - data->taps.v_taps; + int_part = data->taps.v_taps; + } + data->inits.v.value &= 0xffffffff; + data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); + } + + if (data->viewport_c.y) { + int int_part; + + data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( + data->ratios.vert_c, recout_skip->height)); + int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y; + if (int_part < data->taps.v_taps_c) { + int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? + (data->taps.v_taps_c - int_part) : data->viewport_c.y; + data->viewport_c.y -= int_adj; + data->viewport_c.height += int_adj; + int_part += int_adj; + } else if (int_part > data->taps.v_taps_c) { + data->viewport_c.y += int_part - data->taps.v_taps_c; + data->viewport_c.height -= int_part - data->taps.v_taps_c; + int_part = data->taps.v_taps_c; + } + data->inits.v_c.value &= 0xffffffff; + data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part); + } + + /* Interlaced inits based on final vert inits */ + data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); + data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); +} + +bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) +{ + const struct dc_surface *surface = &pipe_ctx->surface->public; struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + struct view recout_skip = { 0 }; + bool res = false; + /* Important: scaling ratio calculation requires pixel format, * lb depth calculation requires recout and taps require scaling ratios. + * Inits require viewport, taps, ratios and recout of split pipe */ - pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format); + pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( + pipe_ctx->surface->public.format); + + calculate_scaling_ratios(pipe_ctx); - calculate_viewport(surface, pipe_ctx); + calculate_viewport(pipe_ctx); if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16) return false; - calculate_scaling_ratios(surface, pipe_ctx); - - calculate_recout(surface, pipe_ctx); + calculate_recout(pipe_ctx, &recout_skip); /** * Setting line buffer pixel depth to 24bpp yields banding @@ -572,6 +754,9 @@ bool resource_build_scaling_params( pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); } + if (res) + calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); + dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, "%s: Viewport:\nheight:%d width:%d x:%d " "y:%d\n dst_rect:\nheight:%d width:%d x:%d " @@ -599,9 +784,7 @@ enum dc_status resource_build_scaling_params_for_context( for (i = 0; i < MAX_PIPES; i++) { if (context->res_ctx.pipe_ctx[i].surface != NULL && context->res_ctx.pipe_ctx[i].stream != NULL) - if (!resource_build_scaling_params( - &context->res_ctx.pipe_ctx[i].surface->public, - &context->res_ctx.pipe_ctx[i])) + if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) return DC_FAIL_SCALING; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d9dcb37a4f65..041830e05b67 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -927,6 +927,7 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, color->color_b_cb = color_value; break; case PIXEL_FORMAT_420BPP12: + case PIXEL_FORMAT_420BPP15: /* set boarder color to green */ color->color_g_y = color_value; break; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 9c5cb0ee4243..8325a0a47179 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -147,13 +147,24 @@ struct line_buffer_params { enum lb_pixel_depth depth; }; +struct scl_inits { + struct fixed31_32 h; + struct fixed31_32 h_c; + struct fixed31_32 v; + struct fixed31_32 v_bot; + struct fixed31_32 v_c; + struct fixed31_32 v_c_bot; +}; + struct scaler_data { int h_active; int v_active; struct scaling_taps taps; struct rect viewport; + struct rect viewport_c; struct rect recout; struct scaling_ratios ratios; + struct scl_inits inits; struct sharpness_adj sharpness; enum pixel_format format; struct line_buffer_params lb_params; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index d96c64bb0a70..eb9c96634578 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -82,9 +82,7 @@ enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context); -bool resource_build_scaling_params( - const struct dc_surface *surface, - struct pipe_ctx *pipe_ctx); +bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); enum dc_status resource_build_scaling_params_for_context( const struct core_dc *dc, -- GitLab From 9e6c74ceef866edf2cec380c8ce06ef73d56478d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 6 Mar 2017 14:57:28 -0500 Subject: [PATCH 0307/2898] drm/amd/display: fix hsplit viewport calculation for rotated/mirrored usecases Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d4b338fa4ab9..e34b52e28e52 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -412,6 +412,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) struct rect clip = {0}; int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + bool need_split = (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) + || (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface); if (surface->rotation == ROTATION_ANGLE_90 || @@ -466,17 +468,40 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; /* Handle hsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - data->viewport.width /= 2; - data->viewport_c.width /= 2; - data->viewport.x += data->viewport.width; - data->viewport_c.x += data->viewport_c.width; - /* Floor primary pipe, ceil 2ndary pipe */ - data->viewport.width += data->viewport.width % 2; - data->viewport_c.width += data->viewport_c.width % 2; - } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { - data->viewport.width /= 2; - data->viewport_c.width /= 2; + if (need_split && (surface->rotation == ROTATION_ANGLE_90 || + surface->rotation == ROTATION_ANGLE_270)) { + bool lower_view = (surface->rotation == ROTATION_ANGLE_270) ^ + (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface); + + if (lower_view) { + data->viewport.height /= 2; + data->viewport_c.height /= 2; + data->viewport.y += data->viewport.height; + data->viewport_c.y += data->viewport_c.height; + /* Ceil offset pipe */ + data->viewport.height += data->viewport.height % 2; + data->viewport_c.height += data->viewport_c.height % 2; + } else { + data->viewport.height /= 2; + data->viewport_c.height /= 2; + } + } else if (need_split) { + bool right_view = (surface->rotation == ROTATION_ANGLE_180) ^ + (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) ^ + surface->horizontal_mirror; + + if (right_view) { + data->viewport.width /= 2; + data->viewport_c.width /= 2; + data->viewport.x += data->viewport.width; + data->viewport_c.x += data->viewport_c.width; + /* Ceil offset pipe */ + data->viewport.width += data->viewport.width % 2; + data->viewport_c.width += data->viewport_c.width % 2; + } else { + data->viewport.width /= 2; + data->viewport_c.width /= 2; + } } } -- GitLab From 1fbd2cfc15988f90ce5bebbbeaf759f4d1c615e1 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 6 Mar 2017 18:02:30 -0500 Subject: [PATCH 0308/2898] drm/amd/display: fix viewport adjustment on rotated surface Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 133 +++++++++--------- 1 file changed, 69 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e34b52e28e52..01f15052bebf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -404,57 +404,47 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_stream *stream = &pipe_ctx->stream->public; struct scaler_data *data = &pipe_ctx->scl_data; - struct rect stream_src = pipe_ctx->stream->public.src; - struct rect src = surface->src_rect; - struct rect dst = surface->dst_rect; - struct rect surface_clip = surface->clip_rect; - struct rect clip = {0}; + struct rect clip = { 0 }; int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; - bool need_split = (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) - || (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface); - - - if (surface->rotation == ROTATION_ANGLE_90 || - surface->rotation == ROTATION_ANGLE_270) { - rect_swap_helper(&src); - rect_swap_helper(&dst); - rect_swap_helper(&surface_clip); - rect_swap_helper(&stream_src); - } + bool pri_split = pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->surface == pipe_ctx->surface; + bool sec_split = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->surface == pipe_ctx->surface; /* The actual clip is an intersection between stream * source and surface clip */ - clip.x = stream_src.x > surface_clip.x ? - stream_src.x : surface_clip.x; + clip.x = stream->src.x > surface->clip_rect.x ? + stream->src.x : surface->clip_rect.x; - clip.width = stream_src.x + stream_src.width < - surface_clip.x + surface_clip.width ? - stream_src.x + stream_src.width - clip.x : - surface_clip.x + surface_clip.width - clip.x ; + clip.width = stream->src.x + stream->src.width < + surface->clip_rect.x + surface->clip_rect.width ? + stream->src.x + stream->src.width - clip.x : + surface->clip_rect.x + surface->clip_rect.width - clip.x ; - clip.y = stream_src.y > surface_clip.y ? - stream_src.y : surface_clip.y; + clip.y = stream->src.y > surface->clip_rect.y ? + stream->src.y : surface->clip_rect.y; - clip.height = stream_src.y + stream_src.height < - surface_clip.y + surface_clip.height ? - stream_src.y + stream_src.height - clip.y : - surface_clip.y + surface_clip.height - clip.y ; + clip.height = stream->src.y + stream->src.height < + surface->clip_rect.y + surface->clip_rect.height ? + stream->src.y + stream->src.height - clip.y : + surface->clip_rect.y + surface->clip_rect.height - clip.y ; - /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio + /* offset = src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio * num_pixels = clip.num_pix * scl_ratio */ - data->viewport.x = src.x + (clip.x - dst.x) * - src.width / dst.width; + data->viewport.x = surface->src_rect.x + (clip.x - surface->dst_rect.x) * + surface->src_rect.width / surface->dst_rect.width; data->viewport.width = clip.width * - src.width / dst.width; + surface->src_rect.width / surface->dst_rect.width; - data->viewport.y = src.y + (clip.y - dst.y) * - src.height / dst.height; + data->viewport.y = surface->src_rect.y + (clip.y - surface->dst_rect.y) * + surface->src_rect.height / surface->dst_rect.height; data->viewport.height = clip.height * - src.height / dst.height; + surface->src_rect.height / surface->dst_rect.height; /* Round down, compensate in init */ data->viewport_c.x = data->viewport.x / vpc_div; @@ -468,27 +458,15 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; /* Handle hsplit */ - if (need_split && (surface->rotation == ROTATION_ANGLE_90 || - surface->rotation == ROTATION_ANGLE_270)) { - bool lower_view = (surface->rotation == ROTATION_ANGLE_270) ^ - (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface); - - if (lower_view) { - data->viewport.height /= 2; - data->viewport_c.height /= 2; - data->viewport.y += data->viewport.height; - data->viewport_c.y += data->viewport_c.height; - /* Ceil offset pipe */ - data->viewport.height += data->viewport.height % 2; - data->viewport_c.height += data->viewport_c.height % 2; - } else { - data->viewport.height /= 2; - data->viewport_c.height /= 2; - } - } else if (need_split) { - bool right_view = (surface->rotation == ROTATION_ANGLE_180) ^ - (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) ^ - surface->horizontal_mirror; + if (pri_split || sec_split) { + /* HMirror XOR Secondary_pipe XOR Rotation_180 */ + bool right_view = (sec_split != surface->horizontal_mirror) != + (surface->rotation == ROTATION_ANGLE_180); + + if (surface->rotation == ROTATION_ANGLE_90 + || surface->rotation == ROTATION_ANGLE_270) + /* Secondary_pipe XOR Rotation_270 */ + right_view = (surface->rotation == ROTATION_ANGLE_270) != sec_split; if (right_view) { data->viewport.width /= 2; @@ -503,6 +481,12 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport_c.width /= 2; } } + + if (surface->rotation == ROTATION_ANGLE_90 || + surface->rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&data->viewport_c); + rect_swap_helper(&data->viewport); + } } static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) @@ -559,10 +543,10 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; - const uint32_t in_w = stream->public.src.width; - const uint32_t in_h = stream->public.src.height; - const uint32_t out_w = stream->public.dst.width; - const uint32_t out_h = stream->public.dst.height; + const int in_w = stream->public.src.width; + const int in_h = stream->public.src.height; + const int out_w = stream->public.dst.width; + const int out_h = stream->public.dst.height; pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( surface->src_rect.width, @@ -598,6 +582,12 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&data->viewport_c); + rect_swap_helper(&data->viewport); + } + /* * Init calculated according to formula: * init = (scaling_ratio + number_of_taps + 1) / 2 @@ -620,28 +610,36 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r /* Adjust for viewport end clip-off */ if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; - int int_part = dal_fixed31_32_floor(data->inits.h); + int int_part = dal_fixed31_32_floor( + dal_fixed31_32_sub(data->inits.h, data->ratios.horz)); + int_part = int_part > 0 ? int_part : 0; data->viewport.width += int_part < vp_clip ? int_part : vp_clip; } if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; - int int_part = dal_fixed31_32_floor(data->inits.v); + int int_part = dal_fixed31_32_floor( + dal_fixed31_32_sub(data->inits.v, data->ratios.vert)); + int_part = int_part > 0 ? int_part : 0; data->viewport.height += int_part < vp_clip ? int_part : vp_clip; } if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { int vp_clip = (src.x + src.width) / vpc_div - data->viewport_c.width - data->viewport_c.x; - int int_part = dal_fixed31_32_floor(data->inits.h_c); + int int_part = dal_fixed31_32_floor( + dal_fixed31_32_sub(data->inits.h_c, data->ratios.horz_c)); + int_part = int_part > 0 ? int_part : 0; data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; } if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { int vp_clip = (src.y + src.height) / vpc_div - data->viewport_c.height - data->viewport_c.y; - int int_part = dal_fixed31_32_floor(data->inits.v_c); + int int_part = dal_fixed31_32_floor( + dal_fixed31_32_sub(data->inits.v_c, data->ratios.vert_c)); + int_part = int_part > 0 ? int_part : 0; data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; } @@ -733,6 +731,12 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r /* Interlaced inits based on final vert inits */ data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); + + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&data->viewport_c); + rect_swap_helper(&data->viewport); + } } bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) @@ -780,6 +784,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) } if (res) + /* May need to re-check lb size after this in some obscure scenario */ calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, -- GitLab From c0bc0bd587a6f98fd1e2264a4fc2af49039627b6 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Wed, 8 Mar 2017 14:04:16 -0500 Subject: [PATCH 0309/2898] drm/amd/display: Less log spam Signed-off-by: Jordan Lazare Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/logger.c | 4 +++- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 4 ++-- drivers/gpu/drm/amd/display/include/logger_types.h | 1 + 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index a5625a3badab..8f4497332bda 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -32,6 +32,7 @@ static const struct dc_log_type_info log_type_info_tbl[] = { {LOG_ERROR, "Error"}, {LOG_WARNING, "Warning"}, + {LOG_DEBUG, "Debug"}, {LOG_DC, "DC_Interface"}, {LOG_SURFACE, "Surface"}, {LOG_HW_HOTPLUG, "HW_Hotplug"}, @@ -80,12 +81,13 @@ static const struct dc_log_type_info log_type_info_tbl[] = { (1 << LOG_SYNC) | \ (1 << LOG_BANDWIDTH_VALIDATION) | \ (1 << LOG_MST) | \ - (1 << LOG_BIOS) | \ (1 << LOG_DETECTION_EDID_PARSER) | \ (1 << LOG_DETECTION_DP_CAPS) | \ (1 << LOG_BACKLIGHT)) | \ (1 << LOG_I2C_AUX) | \ (1 << LOG_IF_TRACE) /* | \ + (1 << LOG_DEBUG) | \ + (1 << LOG_BIOS) | \ (1 << LOG_SURFACE) | \ (1 << LOG_SCALER) | \ (1 << LOG_DML) | \ diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 656c39ac0256..50163a06a653 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -3299,7 +3299,7 @@ static enum bp_result patch_bios_image_from_ext_display_connection_info( opm_object, &ext_display_connection_info_tbl) != BP_RESULT_OK) { - dm_logger_write(bp->base.ctx->logger, LOG_BIOS, + dm_logger_write(bp->base.ctx->logger, LOG_WARNING, "%s: Failed to read Connection Info Table", __func__); return BP_RESULT_UNSUPPORTED; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 7f52e39ec92a..b94c1e5d85cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -773,8 +773,8 @@ void dce_aud_wall_dto_setup( crtc_info->calculated_pixel_clock, &clock_info); - dm_logger_write(audio->ctx->logger, LOG_HW_SET_MODE,\ - "\n************************%s:Input::requested_pixel_clock = %d"\ + dm_logger_write(audio->ctx->logger, LOG_HW_AUDIO,\ + "\n%s:Input::requested_pixel_clock = %d"\ "calculated_pixel_clock =%d\n"\ "audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\ crtc_info->requested_pixel_clock,\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index d6662fa2f4e1..f3e1a293351f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1093,8 +1093,8 @@ static void dce110_se_setup_hdmi_audio( crtc_info->requested_pixel_clock, crtc_info->calculated_pixel_clock, &audio_clock_info)) { - dm_logger_write(enc->ctx->logger, LOG_HW_SET_MODE, - "\n*********************%s:Input::requested_pixel_clock = %d"\ + dm_logger_write(enc->ctx->logger, LOG_HW_AUDIO, + "\n%s:Input::requested_pixel_clock = %d"\ "calculated_pixel_clock = %d \n", __func__,\ crtc_info->requested_pixel_clock,\ crtc_info->calculated_pixel_clock); diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index babd6523b105..832d17e1cc49 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -35,6 +35,7 @@ struct dal_logger; enum dc_log_type { LOG_ERROR = 0, LOG_WARNING, + LOG_DEBUG, LOG_DC, LOG_SURFACE, LOG_HW_HOTPLUG, -- GitLab From c802570ed5a679c3c58fdde4b23d494bd884efc9 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 8 Mar 2017 13:45:33 -0500 Subject: [PATCH 0310/2898] drm/amd/display: fix incorrect vp adjustment Viewport would be incorrectly adjusted when surface was used for multiple displays Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 01f15052bebf..6119973c7f0a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -494,6 +494,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; struct rect clip = surface->clip_rect; + int recout_full_x, recout_full_y; pipe_ctx->scl_data.recout.x = stream->public.dst.x; if (stream->public.src.x < clip.x) @@ -533,10 +534,21 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->scl_data.recout.width /= 2; } - recout_skip->width = pipe_ctx->scl_data.recout.x - stream->public.dst.x - - surface->dst_rect.x * stream->public.dst.width / stream->public.src.width; - recout_skip->height = pipe_ctx->scl_data.recout.y - stream->public.dst.y - - surface->dst_rect.y * stream->public.dst.height / stream->public.src.height; + /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream src offset) + * * 1/ stream scaling ratio) - (surf src offset * 1/ full scl + * ratio) + */ + recout_full_x = stream->public.dst.x + (surface->dst_rect.x - stream->public.src.x) + * stream->public.dst.width / stream->public.src.width - + surface->src_rect.x * surface->dst_rect.width / surface->src_rect.width + * stream->public.dst.width / stream->public.src.width; + recout_full_y = stream->public.dst.y + (surface->dst_rect.y - stream->public.src.y) + * stream->public.dst.height / stream->public.src.height - + surface->src_rect.y * surface->dst_rect.height / surface->src_rect.height + * stream->public.dst.height / stream->public.src.height; + + recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; + recout_skip->height = pipe_ctx->scl_data.recout.y - recout_full_y; } static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) -- GitLab From b7ad57b5791e6cbeeb2e0df3e2e2769d4128d144 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 28 Feb 2017 16:21:27 +0800 Subject: [PATCH 0311/2898] drm/amdgpu: get display info from DC when DC enabled. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 59 ++++++++++++++----------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 383204e911a4..1933253d2e0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -889,10 +889,6 @@ static int amdgpu_cgs_get_active_displays_info(struct cgs_device *cgs_device, struct cgs_display_info *info) { CGS_FUNC_ADEV; - struct amdgpu_crtc *amdgpu_crtc; - struct drm_device *ddev = adev->ddev; - struct drm_crtc *crtc; - uint32_t line_time_us, vblank_lines; struct cgs_mode_info *mode_info; if (info == NULL) @@ -906,30 +902,43 @@ static int amdgpu_cgs_get_active_displays_info(struct cgs_device *cgs_device, mode_info->ref_clock = adev->clock.spll.reference_freq; } - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, - &ddev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled) { - info->active_display_mask |= (1 << amdgpu_crtc->crtc_id); - info->display_count++; - } - if (mode_info != NULL && - crtc->enabled && amdgpu_crtc->enabled && - amdgpu_crtc->hw_mode.clock) { - line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) / - amdgpu_crtc->hw_mode.clock; - vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end - - amdgpu_crtc->hw_mode.crtc_vdisplay + - (amdgpu_crtc->v_border * 2); - mode_info->vblank_time_us = vblank_lines * line_time_us; - mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); - mode_info->ref_clock = adev->clock.spll.reference_freq; - mode_info = NULL; + if (!amdgpu_device_has_dc_support(adev)) { + struct amdgpu_crtc *amdgpu_crtc; + struct drm_device *ddev = adev->ddev; + struct drm_crtc *crtc; + uint32_t line_time_us, vblank_lines; + + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled) { + info->active_display_mask |= (1 << amdgpu_crtc->crtc_id); + info->display_count++; + } + if (mode_info != NULL && + crtc->enabled && amdgpu_crtc->enabled && + amdgpu_crtc->hw_mode.clock) { + line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) / + amdgpu_crtc->hw_mode.clock; + vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end - + amdgpu_crtc->hw_mode.crtc_vdisplay + + (amdgpu_crtc->v_border * 2); + mode_info->vblank_time_us = vblank_lines * line_time_us; + mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); + mode_info->ref_clock = adev->clock.spll.reference_freq; + mode_info = NULL; + } } } + } else { + info->display_count = adev->pm.pm_display_cfg.num_display; + if (mode_info != NULL) { + mode_info->vblank_time_us = adev->pm.pm_display_cfg.min_vblank_time; + mode_info->refresh_rate = adev->pm.pm_display_cfg.vrefresh; + mode_info->ref_clock = adev->clock.spll.reference_freq; + } } - return 0; } -- GitLab From ae79c310b1a6f97429a5784b65f125d9cc9c95b1 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:29:52 -0500 Subject: [PATCH 0312/2898] drm/amd/display: Add DCE12 bios parser support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/bios/bios_parser2.c | 2085 +++++++++++++++++ .../drm/amd/display/dc/bios/bios_parser2.h | 33 + .../dc/bios/bios_parser_types_internal2.h | 74 + .../drm/amd/display/dc/bios/command_table2.c | 813 +++++++ .../drm/amd/display/dc/bios/command_table2.h | 105 + .../display/dc/bios/command_table_helper2.c | 260 ++ .../display/dc/bios/command_table_helper2.h | 82 + .../dce112/command_table_helper2_dce112.c | 418 ++++ .../dce112/command_table_helper2_dce112.h | 34 + 9 files changed, 3904 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table2.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table2.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c new file mode 100644 index 000000000000..f6e77da7d302 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -0,0 +1,2085 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#define _BIOS_PARSER_2_ + +#include "ObjectID.h" +#include "atomfirmware.h" +#include "atomfirmwareid.h" + +#include "dc_bios_types.h" +#include "include/grph_object_ctrl_defs.h" +#include "include/bios_parser_interface.h" +#include "include/i2caux_interface.h" +#include "include/logger_interface.h" + +#include "command_table2.h" + +#include "bios_parser_helper.h" +#include "command_table_helper2.h" +#include "bios_parser2.h" +#include "bios_parser_types_internal2.h" +#include "bios_parser_interface.h" + +#define LAST_RECORD_TYPE 0xff + + +struct i2c_id_config_access { + uint8_t bfI2C_LineMux:4; + uint8_t bfHW_EngineID:3; + uint8_t bfHW_Capable:1; + uint8_t ucAccess; +}; + +static enum object_type object_type_from_bios_object_id( + uint32_t bios_object_id); + +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); + +static struct graphics_object_id object_id_from_bios_object_id( + uint32_t bios_object_id); + +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id); + +static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); + +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); + +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id); + +static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); + +static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, + struct atom_i2c_record *record, + struct graphics_object_i2c_info *info); + +static enum bp_result bios_parser_get_firmware_info( + struct dc_bios *dcb, + struct firmware_info *info); + +static enum bp_result bios_parser_get_encoder_cap_info( + struct dc_bios *dcb, + struct graphics_object_id object_id, + struct bp_encoder_cap_info *info); + +static enum bp_result get_firmware_info_v3_1( + struct bios_parser *bp, + struct firmware_info *info); + +static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp, + struct atom_display_object_path_v2 *object); + +static struct atom_encoder_caps_record *get_encoder_cap_record( + struct bios_parser *bp, + struct atom_display_object_path_v2 *object); + +#define BIOS_IMAGE_SIZE_OFFSET 2 +#define BIOS_IMAGE_SIZE_UNIT 512 + +#define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table) + + +static void destruct(struct bios_parser *bp) +{ + if (bp->base.bios_local_image) + dm_free(bp->base.bios_local_image); + + if (bp->base.integrated_info) + dm_free(bp->base.integrated_info); +} + +static void firmware_parser_destroy(struct dc_bios **dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(*dcb); + + if (!bp) { + BREAK_TO_DEBUGGER(); + return; + } + + destruct(bp); + + dm_free(bp); + *dcb = NULL; +} + +static void get_atom_data_table_revision( + struct atom_common_table_header *atom_data_tbl, + struct atom_data_revision *tbl_revision) +{ + if (!tbl_revision) + return; + + /* initialize the revision to 0 which is invalid revision */ + tbl_revision->major = 0; + tbl_revision->minor = 0; + + if (!atom_data_tbl) + return; + + tbl_revision->major = + (uint32_t) atom_data_tbl->format_revision & 0x3f; + tbl_revision->minor = + (uint32_t) atom_data_tbl->content_revision & 0x3f; +} + +static struct graphics_object_id object_id_from_bios_object_id( + uint32_t bios_object_id) +{ + enum object_type type; + enum object_enum_id enum_id; + struct graphics_object_id go_id = { 0 }; + + type = object_type_from_bios_object_id(bios_object_id); + + if (type == OBJECT_TYPE_UNKNOWN) + return go_id; + + enum_id = enum_id_from_bios_object_id(bios_object_id); + + if (enum_id == ENUM_ID_UNKNOWN) + return go_id; + + go_id = dal_graphics_object_id_init( + id_from_bios_object_id(type, bios_object_id), + enum_id, type); + + return go_id; +} + +static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) + >> OBJECT_TYPE_SHIFT; + enum object_type object_type; + + switch (bios_object_type) { + case GRAPH_OBJECT_TYPE_GPU: + object_type = OBJECT_TYPE_GPU; + break; + case GRAPH_OBJECT_TYPE_ENCODER: + object_type = OBJECT_TYPE_ENCODER; + break; + case GRAPH_OBJECT_TYPE_CONNECTOR: + object_type = OBJECT_TYPE_CONNECTOR; + break; + case GRAPH_OBJECT_TYPE_ROUTER: + object_type = OBJECT_TYPE_ROUTER; + break; + case GRAPH_OBJECT_TYPE_GENERIC: + object_type = OBJECT_TYPE_GENERIC; + break; + default: + object_type = OBJECT_TYPE_UNKNOWN; + break; + } + + return object_type; +} + +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_enum_id = + (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + enum object_enum_id id; + + switch (bios_enum_id) { + case GRAPH_OBJECT_ENUM_ID1: + id = ENUM_ID_1; + break; + case GRAPH_OBJECT_ENUM_ID2: + id = ENUM_ID_2; + break; + case GRAPH_OBJECT_ENUM_ID3: + id = ENUM_ID_3; + break; + case GRAPH_OBJECT_ENUM_ID4: + id = ENUM_ID_4; + break; + case GRAPH_OBJECT_ENUM_ID5: + id = ENUM_ID_5; + break; + case GRAPH_OBJECT_ENUM_ID6: + id = ENUM_ID_6; + break; + case GRAPH_OBJECT_ENUM_ID7: + id = ENUM_ID_7; + break; + default: + id = ENUM_ID_UNKNOWN; + break; + } + + return id; +} + +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id) +{ + switch (type) { + case OBJECT_TYPE_GPU: + return gpu_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_ENCODER: + return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_CONNECTOR: + return (uint32_t)connector_id_from_bios_object_id( + bios_object_id); + case OBJECT_TYPE_GENERIC: + return generic_id_from_bios_object_id(bios_object_id); + default: + return 0; + } +} + +uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) +{ + return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; +} + +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); + enum encoder_id id; + + switch (bios_encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + id = ENCODER_ID_INTERNAL_LVDS; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + id = ENCODER_ID_INTERNAL_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS2: + id = ENCODER_ID_INTERNAL_TMDS2; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + id = ENCODER_ID_INTERNAL_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + id = ENCODER_ID_INTERNAL_DAC2; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + id = ENCODER_ID_INTERNAL_LVTM1; + break; + case ENCODER_OBJECT_ID_HDMI_INTERNAL: + id = ENCODER_ID_INTERNAL_HDMI; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; + break; + case ENCODER_OBJECT_ID_MVPU_FPGA: + id = ENCODER_ID_EXTERNAL_MVPU_FPGA; + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + id = ENCODER_ID_INTERNAL_DDI; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + id = ENCODER_ID_INTERNAL_UNIPHY; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + id = ENCODER_ID_INTERNAL_UNIPHY1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + id = ENCODER_ID_INTERNAL_UNIPHY2; + break; + case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ + id = ENCODER_ID_EXTERNAL_NUTMEG; + break; + case ENCODER_OBJECT_ID_TRAVIS: + id = ENCODER_ID_EXTERNAL_TRAVIS; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + id = ENCODER_ID_INTERNAL_UNIPHY3; + break; + default: + id = ENCODER_ID_UNKNOWN; + ASSERT(0); + break; + } + + return id; +} + +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id) +{ + uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); + + enum connector_id id; + + switch (bios_connector_id) { + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: + id = CONNECTOR_ID_SINGLE_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: + id = CONNECTOR_ID_DUAL_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: + id = CONNECTOR_ID_SINGLE_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: + id = CONNECTOR_ID_DUAL_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_VGA: + id = CONNECTOR_ID_VGA; + break; + case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: + id = CONNECTOR_ID_HDMI_TYPE_A; + break; + case CONNECTOR_OBJECT_ID_LVDS: + id = CONNECTOR_ID_LVDS; + break; + case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: + id = CONNECTOR_ID_PCIE; + break; + case CONNECTOR_OBJECT_ID_HARDCODE_DVI: + id = CONNECTOR_ID_HARDCODE_DVI; + break; + case CONNECTOR_OBJECT_ID_DISPLAYPORT: + id = CONNECTOR_ID_DISPLAY_PORT; + break; + case CONNECTOR_OBJECT_ID_eDP: + id = CONNECTOR_ID_EDP; + break; + case CONNECTOR_OBJECT_ID_MXM: + id = CONNECTOR_ID_MXM; + break; + default: + id = CONNECTOR_ID_UNKNOWN; + break; + } + + return id; +} + +enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); + + enum generic_id id; + + switch (bios_generic_id) { + case GENERIC_OBJECT_ID_MXM_OPM: + id = GENERIC_ID_MXM_OPM; + break; + case GENERIC_OBJECT_ID_GLSYNC: + id = GENERIC_ID_GLSYNC; + break; + case GENERIC_OBJECT_ID_STEREO_PIN: + id = GENERIC_ID_STEREO; + break; + default: + id = GENERIC_ID_UNKNOWN; + break; + } + + return id; +} + +static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + unsigned int count = 0; + unsigned int i; + + for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) { + if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0 + && + bp->object_info_tbl.v1_4->display_path[i].display_objid != 0) + count++; + } + return count; +} + +static struct graphics_object_id bios_parser_get_encoder_id( + struct dc_bios *dcb, + uint32_t i) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct graphics_object_id object_id = dal_graphics_object_id_init( + 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + + if (bp->object_info_tbl.v1_4->number_of_path > i) + object_id = object_id_from_bios_object_id( + bp->object_info_tbl.v1_4->display_path[i].encoderobjid); + + return object_id; +} + +static struct graphics_object_id bios_parser_get_connector_id( + struct dc_bios *dcb, + uint8_t i) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct graphics_object_id object_id = dal_graphics_object_id_init( + 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); + struct object_info_table *tbl = &bp->object_info_tbl; + struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4; + + if (v1_4->number_of_path > i) { + /* If display_objid is generic object id, the encoderObj + * /extencoderobjId should be 0 + */ + if (v1_4->display_path[i].encoderobjid != 0 && + v1_4->display_path[i].display_objid != 0) + object_id = object_id_from_bios_object_id( + v1_4->display_path[i].display_objid); + } + + return object_id; +} + + +/* TODO: GetNumberOfSrc*/ + +static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb, + struct graphics_object_id id) +{ + /* connector has 1 Dest, encoder has 0 Dest */ + switch (id.type) { + case OBJECT_TYPE_ENCODER: + return 0; + case OBJECT_TYPE_CONNECTOR: + return 1; + default: + return 0; + } +} + +/* removed getSrcObjList, getDestObjList*/ + + +static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *src_object_id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + unsigned int i; + enum bp_result bp_result = BP_RESULT_BADINPUT; + struct graphics_object_id obj_id = {0}; + struct object_info_table *tbl = &bp->object_info_tbl; + + if (!src_object_id) + return bp_result; + + switch (object_id.type) { + /* Encoder's Source is GPU. BIOS does not provide GPU, since all + * displaypaths point to same GPU (0x1100). Hardcode GPU object type + */ + case OBJECT_TYPE_ENCODER: + /* TODO: since num of src must be less than 2. + * If found in for loop, should break. + * DAL2 implementation may be changed too + */ + for (i = 0; i < tbl->v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + tbl->v1_4->display_path[i].encoderobjid); + if (object_id.type == obj_id.type && + object_id.id == obj_id.id && + object_id.enum_id == + obj_id.enum_id) { + *src_object_id = + object_id_from_bios_object_id(0x1100); + /* break; */ + } + } + bp_result = BP_RESULT_OK; + break; + case OBJECT_TYPE_CONNECTOR: + for (i = 0; i < tbl->v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + tbl->v1_4->display_path[i].display_objid); + + if (object_id.type == obj_id.type && + object_id.id == obj_id.id && + object_id.enum_id == obj_id.enum_id) { + *src_object_id = + object_id_from_bios_object_id( + tbl->v1_4->display_path[i].encoderobjid); + /* break; */ + } + } + bp_result = BP_RESULT_OK; + break; + default: + break; + } + + return bp_result; +} + +static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb, + struct graphics_object_id object_id, uint32_t index, + struct graphics_object_id *dest_object_id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + unsigned int i; + enum bp_result bp_result = BP_RESULT_BADINPUT; + struct graphics_object_id obj_id = {0}; + struct object_info_table *tbl = &bp->object_info_tbl; + + if (!dest_object_id) + return BP_RESULT_BADINPUT; + + switch (object_id.type) { + case OBJECT_TYPE_ENCODER: + /* TODO: since num of src must be less than 2. + * If found in for loop, should break. + * DAL2 implementation may be changed too + */ + for (i = 0; i < tbl->v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + tbl->v1_4->display_path[i].encoderobjid); + if (object_id.type == obj_id.type && + object_id.id == obj_id.id && + object_id.enum_id == + obj_id.enum_id) { + *dest_object_id = + object_id_from_bios_object_id( + tbl->v1_4->display_path[i].display_objid); + /* break; */ + } + } + bp_result = BP_RESULT_OK; + break; + default: + break; + } + + return bp_result; +} + + +/* from graphics_object_id, find display path which includes the object_id */ +static struct atom_display_object_path_v2 *get_bios_object( + struct bios_parser *bp, + struct graphics_object_id id) +{ + unsigned int i; + struct graphics_object_id obj_id = {0}; + + switch (id.type) { + case OBJECT_TYPE_ENCODER: + for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + bp->object_info_tbl.v1_4->display_path[i].encoderobjid); + if (id.type == obj_id.type && + id.id == obj_id.id && + id.enum_id == obj_id.enum_id) + return + &bp->object_info_tbl.v1_4->display_path[i]; + } + case OBJECT_TYPE_CONNECTOR: + case OBJECT_TYPE_GENERIC: + /* Both Generic and Connector Object ID + * will be stored on display_objid + */ + for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) { + obj_id = object_id_from_bios_object_id( + bp->object_info_tbl.v1_4->display_path[i].display_objid + ); + if (id.type == obj_id.type && + id.id == obj_id.id && + id.enum_id == obj_id.enum_id) + return + &bp->object_info_tbl.v1_4->display_path[i]; + } + default: + return NULL; + } +} + +static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_i2c_info *info) +{ + uint32_t offset; + struct atom_display_object_path_v2 *object; + struct atom_common_record_header *header; + struct atom_i2c_record *record; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + offset = object->disp_recordoffset + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(struct atom_common_record_header, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (header->record_type == LAST_RECORD_TYPE || + !header->record_size) + break; + + if (header->record_type == ATOM_I2C_RECORD_TYPE + && sizeof(struct atom_i2c_record) <= + header->record_size) { + /* get the I2C info */ + record = (struct atom_i2c_record *) header; + + if (get_gpio_i2c_info(bp, record, info) == + BP_RESULT_OK) + return BP_RESULT_OK; + } + + offset += header->record_size; + } + + return BP_RESULT_NORECORD; +} + +static enum bp_result get_gpio_i2c_info( + struct bios_parser *bp, + struct atom_i2c_record *record, + struct graphics_object_i2c_info *info) +{ + struct atom_gpio_pin_lut_v2_1 *header; + uint32_t count = 0; + unsigned int table_index = 0; + + if (!info) + return BP_RESULT_BADINPUT; + + /* get the GPIO_I2C info */ + if (!DATA_TABLES(gpio_pin_lut)) + return BP_RESULT_BADBIOSTABLE; + + header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1, + DATA_TABLES(gpio_pin_lut)); + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (sizeof(struct atom_common_table_header) + + sizeof(struct atom_gpio_pin_assignment) > + le16_to_cpu(header->table_header.structuresize)) + return BP_RESULT_BADBIOSTABLE; + + /* TODO: is version change? */ + if (header->table_header.content_revision != 1) + return BP_RESULT_UNSUPPORTED; + + /* get data count */ + count = (le16_to_cpu(header->table_header.structuresize) + - sizeof(struct atom_common_table_header)) + / sizeof(struct atom_gpio_pin_assignment); + + table_index = record->i2c_id & I2C_HW_LANE_MUX; + + if (count < table_index) { + bool find_valid = false; + + for (table_index = 0; table_index < count; table_index++) { + if (((record->i2c_id & I2C_HW_CAP) == ( + header->gpio_pin[table_index].gpio_id & + I2C_HW_CAP)) && + ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == + (header->gpio_pin[table_index].gpio_id & + I2C_HW_ENGINE_ID_MASK)) && + ((record->i2c_id & I2C_HW_LANE_MUX) == + (header->gpio_pin[table_index].gpio_id & + I2C_HW_LANE_MUX))) { + /* still valid */ + find_valid = true; + break; + } + } + /* If we don't find the entry that we are looking for then + * we will return BP_Result_BadBiosTable. + */ + if (find_valid == false) + return BP_RESULT_BADBIOSTABLE; + } + + /* get the GPIO_I2C_INFO */ + info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false; + info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX; + info->i2c_engine_id = (record->i2c_id & I2C_HW_ENGINE_ID_MASK) >> 4; + info->i2c_slave_address = record->i2c_slave_addr; + + /* TODO: check how to get register offset for en, Y, etc. */ + info->gpio_info.clk_a_register_index = + le16_to_cpu( + header->gpio_pin[table_index].data_a_reg_index); + info->gpio_info.clk_a_shift = + header->gpio_pin[table_index].gpio_bitshift; + + return BP_RESULT_OK; +} + +static enum bp_result get_voltage_ddc_info_v4( + uint8_t *i2c_line, + uint32_t index, + struct atom_common_table_header *header, + uint8_t *address) +{ + enum bp_result result = BP_RESULT_NORECORD; + struct atom_voltage_objects_info_v4_1 *info = + (struct atom_voltage_objects_info_v4_1 *) address; + + uint8_t *voltage_current_object = + (uint8_t *) (&(info->voltage_object[0])); + + while ((address + le16_to_cpu(header->structuresize)) > + voltage_current_object) { + struct atom_i2c_voltage_object_v4 *object = + (struct atom_i2c_voltage_object_v4 *) + voltage_current_object; + + if (object->header.voltage_mode == + ATOM_INIT_VOLTAGE_REGULATOR) { + if (object->header.voltage_type == index) { + *i2c_line = object->i2c_id ^ 0x90; + result = BP_RESULT_OK; + break; + } + } + + voltage_current_object += + le16_to_cpu(object->header.object_size); + } + return result; +} + +static enum bp_result bios_parser_get_thermal_ddc_info( + struct dc_bios *dcb, + uint32_t i2c_channel_id, + struct graphics_object_i2c_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct i2c_id_config_access *config; + struct atom_i2c_record record; + + if (!info) + return BP_RESULT_BADINPUT; + + config = (struct i2c_id_config_access *) &i2c_channel_id; + + record.i2c_id = config->bfHW_Capable; + record.i2c_id |= config->bfI2C_LineMux; + record.i2c_id |= config->bfHW_EngineID; + + return get_gpio_i2c_info(bp, &record, info); +} + +static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, + uint32_t index, + struct graphics_object_i2c_info *info) +{ + uint8_t i2c_line = 0; + enum bp_result result = BP_RESULT_NORECORD; + uint8_t *voltage_info_address; + struct atom_common_table_header *header; + struct atom_data_revision revision = {0}; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!DATA_TABLES(voltageobject_info)) + return result; + + voltage_info_address = get_image(&bp->base, + DATA_TABLES(voltageobject_info), + sizeof(struct atom_common_table_header)); + + header = (struct atom_common_table_header *) voltage_info_address; + + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 4: + if (revision.minor != 1) + break; + result = get_voltage_ddc_info_v4(&i2c_line, index, header, + voltage_info_address); + break; + } + + if (result == BP_RESULT_OK) + result = bios_parser_get_thermal_ddc_info(dcb, + i2c_line, info); + + return result; +} + +static enum bp_result bios_parser_get_hpd_info( + struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_hpd_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_display_object_path_v2 *object; + struct atom_hpd_int_record *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_hpd_record(bp, object); + + if (record != NULL) { + info->hpd_int_gpio_uid = record->pin_id; + info->hpd_active = record->plugin_pin_state; + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static struct atom_hpd_int_record *get_hpd_record( + struct bios_parser *bp, + struct atom_display_object_path_v2 *object) +{ + struct atom_common_record_header *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = le16_to_cpu(object->disp_recordoffset) + + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(struct atom_common_record_header, offset); + + if (!header) + return NULL; + + if (header->record_type == LAST_RECORD_TYPE || + !header->record_size) + break; + + if (header->record_type == ATOM_HPD_INT_RECORD_TYPE + && sizeof(struct atom_hpd_int_record) <= + header->record_size) + return (struct atom_hpd_int_record *) header; + + offset += header->record_size; + } + + return NULL; +} + +/** + * bios_parser_get_gpio_pin_info + * Get GpioPin information of input gpio id + * + * @param gpio_id, GPIO ID + * @param info, GpioPin information structure + * @return Bios parser result code + * @note + * to get the GPIO PIN INFO, we need: + * 1. get the GPIO_ID from other object table, see GetHPDInfo() + * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, + * to get the registerA offset/mask + */ +static enum bp_result bios_parser_get_gpio_pin_info( + struct dc_bios *dcb, + uint32_t gpio_id, + struct gpio_pin_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_gpio_pin_lut_v2_1 *header; + uint32_t count = 0; + uint32_t i = 0; + + if (!DATA_TABLES(gpio_pin_lut)) + return BP_RESULT_BADBIOSTABLE; + + header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1, + DATA_TABLES(gpio_pin_lut)); + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (sizeof(struct atom_common_table_header) + + sizeof(struct atom_gpio_pin_lut_v2_1) + > le16_to_cpu(header->table_header.structuresize)) + return BP_RESULT_BADBIOSTABLE; + + if (header->table_header.content_revision != 1) + return BP_RESULT_UNSUPPORTED; + + /* Temporary hard code gpio pin info */ +#if defined(FOR_SIMNOW_BOOT) + { + struct atom_gpio_pin_assignment gpio_pin[8] = { + {0x5db5, 0, 0, 1, 0}, + {0x5db5, 8, 8, 2, 0}, + {0x5db5, 0x10, 0x10, 3, 0}, + {0x5db5, 0x18, 0x14, 4, 0}, + {0x5db5, 0x1A, 0x18, 5, 0}, + {0x5db5, 0x1C, 0x1C, 6, 0}, + }; + + count = 6; + memmove(header->gpio_pin, gpio_pin, sizeof(gpio_pin)); + } +#else + count = (le16_to_cpu(header->table_header.structuresize) + - sizeof(struct atom_common_table_header)) + / sizeof(struct atom_gpio_pin_assignment); +#endif + for (i = 0; i < count; ++i) { + if (header->gpio_pin[i].gpio_id != gpio_id) + continue; + + info->offset = + (uint32_t) le16_to_cpu( + header->gpio_pin[i].data_a_reg_index); + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask = (uint32_t) (1 << + header->gpio_pin[i].gpio_bitshift); + info->mask_y = info->mask + 2; + info->mask_en = info->mask + 1; + info->mask_mask = info->mask - 1; + + return BP_RESULT_OK; + } + + return BP_RESULT_NORECORD; +} + +static struct device_id device_type_from_device_id(uint16_t device_id) +{ + + struct device_id result_device_id; + + switch (device_id) { + case ATOM_DISPLAY_LCD1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_LCD; + result_device_id.enum_id = 1; + break; + + case ATOM_DISPLAY_DFP1_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 1; + break; + + case ATOM_DISPLAY_DFP2_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 2; + break; + + case ATOM_DISPLAY_DFP3_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 3; + break; + + case ATOM_DISPLAY_DFP4_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 4; + break; + + case ATOM_DISPLAY_DFP5_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 5; + break; + + case ATOM_DISPLAY_DFP6_SUPPORT: + result_device_id.device_type = DEVICE_TYPE_DFP; + result_device_id.enum_id = 6; + break; + + default: + BREAK_TO_DEBUGGER(); /* Invalid device Id */ + result_device_id.device_type = DEVICE_TYPE_UNKNOWN; + result_device_id.enum_id = 0; + } + return result_device_id; +} + +static enum bp_result bios_parser_get_device_tag( + struct dc_bios *dcb, + struct graphics_object_id connector_object_id, + uint32_t device_tag_index, + struct connector_device_tag_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_display_object_path_v2 *object; + + if (!info) + return BP_RESULT_BADINPUT; + + /* getBiosObject will return MXM object */ + object = get_bios_object(bp, connector_object_id); + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object id */ + return BP_RESULT_BADINPUT; + } + + info->acpi_device = 0; /* BIOS no longer provides this */ + info->dev_id = device_type_from_device_id(object->device_tag); + + return BP_RESULT_OK; +} + +static enum bp_result get_ss_info_v4_1( + struct bios_parser *bp, + uint32_t id, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL; + struct atom_smu_info_v3_1 *smu_tbl = NULL; + + if (!ss_info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + if (!DATA_TABLES(smu_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1, + DATA_TABLES(dce_info)); + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + smu_tbl = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); + if (!smu_tbl) + return BP_RESULT_BADBIOSTABLE; + + + ss_info->type.STEP_AND_DELAY_INFO = false; + ss_info->spread_percentage_divider = 1000; + /* BIOS no longer uses target clock. Always enable for now */ + ss_info->target_clock_range = 0xffffffff; + + switch (id) { + case AS_SIGNAL_TYPE_DVI: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->dvi_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->dvi_ss_rate_10hz * 10; + if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + case AS_SIGNAL_TYPE_HDMI: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->hdmi_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->hdmi_ss_rate_10hz * 10; + if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + /* TODO LVDS not support anymore? */ + case AS_SIGNAL_TYPE_DISPLAY_PORT: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->dp_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->dp_ss_rate_10hz * 10; + if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + case AS_SIGNAL_TYPE_GPU_PLL: + ss_info->spread_spectrum_percentage = + smu_tbl->gpuclk_ss_percentage; + ss_info->spread_spectrum_range = + smu_tbl->gpuclk_ss_rate_10hz * 10; + if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + default: + result = BP_RESULT_UNSUPPORTED; + } + + return result; +} + +/** + * bios_parser_get_spread_spectrum_info + * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or + * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info + * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info + * ver 3.1, + * there is only one entry for each signal /ss id. However, there is + * no planning of supporting multiple spread Sprectum entry for EverGreen + * @param [in] this + * @param [in] signal, ASSignalType to be converted to info index + * @param [in] index, number of entries that match the converted info index + * @param [out] ss_info, sprectrum information structure, + * @return Bios parser result code + */ +static enum bp_result bios_parser_get_spread_spectrum_info( + struct dc_bios *dcb, + enum as_signal_type signal, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_UNSUPPORTED; + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + + if (!ss_info) /* check for bad input */ + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_UNSUPPORTED; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(dce_info)); + get_atom_data_table_revision(header, &tbl_revision); + + switch (tbl_revision.major) { + case 4: + switch (tbl_revision.minor) { + case 1: + return get_ss_info_v4_1(bp, signal, index, ss_info); + default: + break; + } + break; + default: + break; + } + /* there can not be more then one entry for SS Info table */ + return result; +} + +static enum bp_result get_embedded_panel_info_v2_1( + struct bios_parser *bp, + struct embedded_panel_info *info) +{ + struct lcd_info_v2_1 *lvds; + + if (!info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(lcd_info)) + return BP_RESULT_UNSUPPORTED; + + lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info)); + + if (!lvds) + return BP_RESULT_BADBIOSTABLE; + + /* TODO: previous vv1_3, should v2_1 */ + if (!((lvds->table_header.format_revision == 2) + && (lvds->table_header.content_revision >= 1))) + return BP_RESULT_UNSUPPORTED; + + memset(info, 0, sizeof(struct embedded_panel_info)); + + /* We need to convert from 10KHz units into KHz units */ + info->lcd_timing.pixel_clk = + le16_to_cpu(lvds->lcd_timing.pixclk) * 10; + /* usHActive does not include borders, according to VBIOS team */ + info->lcd_timing.horizontal_addressable = + le16_to_cpu(lvds->lcd_timing.h_active); + /* usHBlanking_Time includes borders, so we should really be + * subtractingborders duing this translation, but LVDS generally + * doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders + */ + info->lcd_timing.horizontal_blanking_time = + le16_to_cpu(lvds->lcd_timing.h_blanking_time); + /* usVActive does not include borders, according to VBIOS team*/ + info->lcd_timing.vertical_addressable = + le16_to_cpu(lvds->lcd_timing.v_active); + /* usVBlanking_Time includes borders, so we should really be + * subtracting borders duing this translation, but LVDS generally + * doesn't have borders, so we should be okay leaving this as is for + * now. May need to revisit if we ever have LVDS with borders + */ + info->lcd_timing.vertical_blanking_time = + le16_to_cpu(lvds->lcd_timing.v_blanking_time); + info->lcd_timing.horizontal_sync_offset = + le16_to_cpu(lvds->lcd_timing.h_sync_offset); + info->lcd_timing.horizontal_sync_width = + le16_to_cpu(lvds->lcd_timing.h_sync_width); + info->lcd_timing.vertical_sync_offset = + le16_to_cpu(lvds->lcd_timing.v_sync_offset); + info->lcd_timing.vertical_sync_width = + le16_to_cpu(lvds->lcd_timing.v_syncwidth); + info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border; + info->lcd_timing.vertical_border = lvds->lcd_timing.v_border; + + /* not provided by VBIOS */ + info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0; + + info->lcd_timing.misc_info.H_SYNC_POLARITY = + ~(uint32_t) + (lvds->lcd_timing.miscinfo & ATOM_HSYNC_POLARITY); + info->lcd_timing.misc_info.V_SYNC_POLARITY = + ~(uint32_t) + (lvds->lcd_timing.miscinfo & ATOM_VSYNC_POLARITY); + + /* not provided by VBIOS */ + info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0; + + info->lcd_timing.misc_info.H_REPLICATION_BY2 = + lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2; + info->lcd_timing.misc_info.V_REPLICATION_BY2 = + lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2; + info->lcd_timing.misc_info.COMPOSITE_SYNC = + lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC; + info->lcd_timing.misc_info.INTERLACE = + lvds->lcd_timing.miscinfo & ATOM_INTERLACE; + + /* not provided by VBIOS*/ + info->lcd_timing.misc_info.DOUBLE_CLOCK = 0; + /* not provided by VBIOS*/ + info->ss_id = 0; + + info->realtek_eDPToLVDS = + (lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID ? 1:0); + + return BP_RESULT_OK; +} + +static enum bp_result bios_parser_get_embedded_panel_info( + struct dc_bios *dcb, + struct embedded_panel_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + + if (!DATA_TABLES(lcd_info)) + return BP_RESULT_FAILURE; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(lcd_info)); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + get_atom_data_table_revision(header, &tbl_revision); + + + switch (tbl_revision.major) { + case 2: + switch (tbl_revision.minor) { + case 1: + return get_embedded_panel_info_v2_1(bp, info); + default: + break; + } + default: + break; + } + + return BP_RESULT_FAILURE; +} + +static uint32_t get_support_mask_for_device_id(struct device_id device_id) +{ + enum dal_device_type device_type = device_id.device_type; + uint32_t enum_id = device_id.enum_id; + + switch (device_type) { + case DEVICE_TYPE_LCD: + switch (enum_id) { + case 1: + return ATOM_DISPLAY_LCD1_SUPPORT; + default: + break; + } + break; + case DEVICE_TYPE_DFP: + switch (enum_id) { + case 1: + return ATOM_DISPLAY_DFP1_SUPPORT; + case 2: + return ATOM_DISPLAY_DFP2_SUPPORT; + case 3: + return ATOM_DISPLAY_DFP3_SUPPORT; + case 4: + return ATOM_DISPLAY_DFP4_SUPPORT; + case 5: + return ATOM_DISPLAY_DFP5_SUPPORT; + case 6: + return ATOM_DISPLAY_DFP6_SUPPORT; + default: + break; + } + break; + default: + break; + }; + + /* Unidentified device ID, return empty support mask. */ + return 0; +} + +static bool bios_parser_is_device_id_supported( + struct dc_bios *dcb, + struct device_id id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + uint32_t mask = get_support_mask_for_device_id(id); + + return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) & + mask) != 0; +} + +static void bios_parser_post_init( + struct dc_bios *dcb) +{ + /* TODO for OPM module. Need implement later */ +} + +static uint32_t bios_parser_get_ss_entry_number( + struct dc_bios *dcb, + enum as_signal_type signal) +{ + /* TODO: DAL2 atomfirmware implementation does not need this. + * why DAL3 need this? + */ + return 1; +} + +static enum bp_result bios_parser_transmitter_control( + struct dc_bios *dcb, + struct bp_transmitter_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.transmitter_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.transmitter_control(bp, cntl); +} + +static enum bp_result bios_parser_encoder_control( + struct dc_bios *dcb, + struct bp_encoder_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.dig_encoder_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.dig_encoder_control(bp, cntl); +} + +static enum bp_result bios_parser_set_pixel_clock( + struct dc_bios *dcb, + struct bp_pixel_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_pixel_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_pixel_clock(bp, bp_params); +} + +static enum bp_result bios_parser_set_dce_clock( + struct dc_bios *dcb, + struct bp_set_dce_clock_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_dce_clock) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_dce_clock(bp, bp_params); +} + +static unsigned int bios_parser_get_smu_clock_info( + struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.get_smu_clock_info) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.get_smu_clock_info(bp); +} + +static enum bp_result bios_parser_program_crtc_timing( + struct dc_bios *dcb, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.set_crtc_timing) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.set_crtc_timing(bp, bp_params); +} + +static enum bp_result bios_parser_enable_crtc( + struct dc_bios *dcb, + enum controller_id id, + bool enable) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_crtc) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_crtc(bp, id, enable); +} + +static enum bp_result bios_parser_crtc_source_select( + struct dc_bios *dcb, + struct bp_crtc_source_select *bp_params) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.select_crtc_source) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.select_crtc_source(bp, bp_params); +} + +static enum bp_result bios_parser_enable_disp_power_gating( + struct dc_bios *dcb, + enum controller_id controller_id, + enum bp_pipe_control_action action) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_disp_power_gating) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id, + action); +} + +static bool bios_parser_is_accelerated_mode( + struct dc_bios *dcb) +{ + return bios_is_accelerated_mode(dcb); +} + + +/** + * bios_parser_set_scratch_critical_state + * + * @brief + * update critical state bit in VBIOS scratch register + * + * @param + * bool - to set or reset state + */ +static void bios_parser_set_scratch_critical_state( + struct dc_bios *dcb, + bool state) +{ + bios_set_scratch_critical_state(dcb, state); +} + +static enum bp_result bios_parser_get_firmware_info( + struct dc_bios *dcb, + struct firmware_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_BADBIOSTABLE; + struct atom_common_table_header *header; + + struct atom_data_revision revision; + + if (info && DATA_TABLES(firmwareinfo)) { + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(firmwareinfo)); + get_atom_data_table_revision(header, &revision); + switch (revision.major) { + case 3: + switch (revision.minor) { + case 1: + result = get_firmware_info_v3_1(bp, info); + break; + default: + break; + } + break; + default: + break; + } + } + + return result; +} + +static enum bp_result get_firmware_info_v3_1( + struct bios_parser *bp, + struct firmware_info *info) +{ + struct atom_firmware_info_v3_1 *firmware_info; + struct atom_display_controller_info_v4_1 *dce_info = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1, + DATA_TABLES(firmwareinfo)); + + dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1, + DATA_TABLES(dce_info)); + + if (!firmware_info || !dce_info) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + /* Pixel clock pll information. */ + /* We need to convert from 10KHz units into KHz units */ + info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10; + info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10; + + /* 27MHz for Vega10: */ + info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10; + + /* Hardcode frequency if BIOS gives no DCE Ref Clk */ + if (info->pll_info.crystal_frequency == 0) + info->pll_info.crystal_frequency = 27000; + + info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10; + info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10; + + /* Get GPU PLL VCO Clock */ + + if (bp->cmd_tbl.get_smu_clock_info != NULL) { + /* VBIOS gives in 10KHz */ + info->smu_gpu_pll_output_freq = + bp->cmd_tbl.get_smu_clock_info(bp) * 10; + } + + return BP_RESULT_OK; +} + +static enum bp_result bios_parser_get_encoder_cap_info( + struct dc_bios *dcb, + struct graphics_object_id object_id, + struct bp_encoder_cap_info *info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct atom_display_object_path_v2 *object; + struct atom_encoder_caps_record *record = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + object = get_bios_object(bp, object_id); + + if (!object) + return BP_RESULT_BADINPUT; + + record = get_encoder_cap_record(bp, object); + if (!record) + return BP_RESULT_NORECORD; + + info->DP_HBR2_CAP = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0; + info->DP_HBR2_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0; + info->DP_HBR3_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0; + info->HDMI_6GB_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0; + + return BP_RESULT_OK; +} + + +static struct atom_encoder_caps_record *get_encoder_cap_record( + struct bios_parser *bp, + struct atom_display_object_path_v2 *object) +{ + struct atom_common_record_header *header; + uint32_t offset; + + if (!object) { + BREAK_TO_DEBUGGER(); /* Invalid object */ + return NULL; + } + + offset = object->encoder_recordoffset + bp->object_info_tbl_offset; + + for (;;) { + header = GET_IMAGE(struct atom_common_record_header, offset); + + if (!header) + return NULL; + + offset += header->record_size; + + if (header->record_type == LAST_RECORD_TYPE || + !header->record_size) + break; + + if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE) + continue; + + if (sizeof(struct atom_encoder_caps_record) <= + header->record_size) + return (struct atom_encoder_caps_record *)header; + } + + return NULL; +} + +/* + * get_integrated_info_v11 + * + * @brief + * Get V8 integrated BIOS information + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result get_integrated_info_v11( + struct bios_parser *bp, + struct integrated_info *info) +{ + struct atom_integrated_system_info_v1_11 *info_v11; + uint32_t i; + + info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11, + DATA_TABLES(integratedsysteminfo)); + + if (info_v11 == NULL) + return BP_RESULT_BADBIOSTABLE; + + info->gpu_cap_info = + le32_to_cpu(info_v11->gpucapinfo); + /* + * system_config: Bit[0] = 0 : PCIE power gating disabled + * = 1 : PCIE power gating enabled + * Bit[1] = 0 : DDR-PLL shut down disabled + * = 1 : DDR-PLL shut down enabled + * Bit[2] = 0 : DDR-PLL power down disabled + * = 1 : DDR-PLL power down enabled + */ + info->system_config = le32_to_cpu(info_v11->system_config); + info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo); + info->memory_type = info_v11->memorytype; + info->ma_channel_number = info_v11->umachannelnumber; + info->lvds_ss_percentage = + le16_to_cpu(info_v11->lvds_ss_percentage); + info->lvds_sspread_rate_in_10hz = + le16_to_cpu(info_v11->lvds_ss_rate_10hz); + info->hdmi_ss_percentage = + le16_to_cpu(info_v11->hdmi_ss_percentage); + info->hdmi_sspread_rate_in_10hz = + le16_to_cpu(info_v11->hdmi_ss_rate_10hz); + info->dvi_ss_percentage = + le16_to_cpu(info_v11->dvi_ss_percentage); + info->dvi_sspread_rate_in_10_hz = + le16_to_cpu(info_v11->dvi_ss_rate_10hz); + info->lvds_misc = info_v11->lvds_misc; + for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { + info->ext_disp_conn_info.gu_id[i] = + info_v11->extdispconninfo.guid[i]; + } + + for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { + info->ext_disp_conn_info.path[i].device_connector_id = + object_id_from_bios_object_id( + le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid)); + + info->ext_disp_conn_info.path[i].ext_encoder_obj_id = + object_id_from_bios_object_id( + le16_to_cpu( + info_v11->extdispconninfo.path[i].ext_encoder_objid)); + + info->ext_disp_conn_info.path[i].device_tag = + le16_to_cpu( + info_v11->extdispconninfo.path[i].device_tag); + info->ext_disp_conn_info.path[i].device_acpi_enum = + le16_to_cpu( + info_v11->extdispconninfo.path[i].device_acpi_enum); + info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = + info_v11->extdispconninfo.path[i].auxddclut_index; + info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = + info_v11->extdispconninfo.path[i].hpdlut_index; + info->ext_disp_conn_info.path[i].channel_mapping.raw = + info_v11->extdispconninfo.path[i].channelmapping; + } + info->ext_disp_conn_info.checksum = + info_v11->extdispconninfo.checksum; + + /** TODO - review **/ + #if 0 + info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock) + * 10; + info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10; + info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; + + for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + /* Convert [10KHz] into [KHz] */ + info->disp_clk_voltage[i].max_supported_clk = + le32_to_cpu(info_v11->sDISPCLK_Voltage[i]. + ulMaximumSupportedCLK) * 10; + info->disp_clk_voltage[i].voltage_index = + le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex); + } + + info->boot_up_req_display_vector = + le32_to_cpu(info_v11->ulBootUpReqDisplayVector); + info->boot_up_nb_voltage = + le16_to_cpu(info_v11->usBootUpNBVoltage); + info->ext_disp_conn_info_offset = + le16_to_cpu(info_v11->usExtDispConnInfoOffset); + info->gmc_restore_reset_time = + le32_to_cpu(info_v11->ulGMCRestoreResetTime); + info->minimum_n_clk = + le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]); + for (i = 1; i < 4; ++i) + info->minimum_n_clk = + info->minimum_n_clk < + le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ? + info->minimum_n_clk : le32_to_cpu( + info_v11->ulNbpStateNClkFreq[i]); + + info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk); + info->ddr_dll_power_up_time = + le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime); + info->ddr_pll_power_up_time = + le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime); + info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType); + info->max_lvds_pclk_freq_in_single_link = + le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink); + info->max_lvds_pclk_freq_in_single_link = + le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink); + info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = + info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; + info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = + info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; + info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = + info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; + info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = + info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; + info->lvds_pwr_off_seq_de_to_dig_on_in4ms = + info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; + info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = + info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; + info->lvds_off_to_on_delay_in_4ms = + info_v11->ucLVDSOffToOnDelay_in4Ms; + info->lvds_bit_depth_control_val = + le32_to_cpu(info_v11->ulLCDBitDepthControlVal); + + for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { + /* Convert [10KHz] into [KHz] */ + info->avail_s_clk[i].supported_s_clk = + le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK) + * 10; + info->avail_s_clk[i].voltage_index = + le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex); + info->avail_s_clk[i].voltage_id = + le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID); + } + #endif /* TODO*/ + + return BP_RESULT_OK; +} + + +/* + * construct_integrated_info + * + * @brief + * Get integrated BIOS information based on table revision + * + * @param + * bios_parser *bp - [in]BIOS parser handler to get master data table + * integrated_info *info - [out] store and output integrated info + * + * @return + * enum bp_result - BP_RESULT_OK if information is available, + * BP_RESULT_BADBIOSTABLE otherwise. + */ +static enum bp_result construct_integrated_info( + struct bios_parser *bp, + struct integrated_info *info) +{ + enum bp_result result = BP_RESULT_BADBIOSTABLE; + + struct atom_common_table_header *header; + struct atom_data_revision revision; + + struct clock_voltage_caps temp = {0, 0}; + uint32_t i; + uint32_t j; + + if (info && DATA_TABLES(integratedsysteminfo)) { + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(integratedsysteminfo)); + + get_atom_data_table_revision(header, &revision); + + /* Don't need to check major revision as they are all 1 */ + switch (revision.minor) { + case 11: + result = get_integrated_info_v11(bp, info); + break; + default: + return result; + } + } + + if (result != BP_RESULT_OK) + return result; + + /* Sort voltage table from low to high*/ + for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { + for (j = i; j > 0; --j) { + if (info->disp_clk_voltage[j].max_supported_clk < + info->disp_clk_voltage[j-1].max_supported_clk + ) { + /* swap j and j - 1*/ + temp = info->disp_clk_voltage[j-1]; + info->disp_clk_voltage[j-1] = + info->disp_clk_voltage[j]; + info->disp_clk_voltage[j] = temp; + } + } + } + + return result; +} + +static struct integrated_info *bios_parser_create_integrated_info( + struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct integrated_info *info = NULL; + + info = dm_alloc(sizeof(struct integrated_info)); + + if (info == NULL) { + ASSERT_CRITICAL(0); + return NULL; + } + + if (construct_integrated_info(bp, info) == BP_RESULT_OK) + return info; + + dm_free(info); + + return NULL; +} + +static const struct dc_vbios_funcs vbios_funcs = { + .get_connectors_number = bios_parser_get_connectors_number, + + .get_encoder_id = bios_parser_get_encoder_id, + + .get_connector_id = bios_parser_get_connector_id, + + .get_dst_number = bios_parser_get_dst_number, + + .get_src_obj = bios_parser_get_src_obj, + + .get_dst_obj = bios_parser_get_dst_obj, + + .get_i2c_info = bios_parser_get_i2c_info, + + .get_voltage_ddc_info = bios_parser_get_voltage_ddc_info, + + .get_thermal_ddc_info = bios_parser_get_thermal_ddc_info, + + .get_hpd_info = bios_parser_get_hpd_info, + + .get_device_tag = bios_parser_get_device_tag, + + .get_firmware_info = bios_parser_get_firmware_info, + + .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info, + + .get_ss_entry_number = bios_parser_get_ss_entry_number, + + .get_embedded_panel_info = bios_parser_get_embedded_panel_info, + + .get_gpio_pin_info = bios_parser_get_gpio_pin_info, + + .get_encoder_cap_info = bios_parser_get_encoder_cap_info, + + .is_device_id_supported = bios_parser_is_device_id_supported, + + + + .is_accelerated_mode = bios_parser_is_accelerated_mode, + + .set_scratch_critical_state = bios_parser_set_scratch_critical_state, + + +/* COMMANDS */ + .encoder_control = bios_parser_encoder_control, + + .transmitter_control = bios_parser_transmitter_control, + + .enable_crtc = bios_parser_enable_crtc, + + .set_pixel_clock = bios_parser_set_pixel_clock, + + .set_dce_clock = bios_parser_set_dce_clock, + + .program_crtc_timing = bios_parser_program_crtc_timing, + + /* .blank_crtc = bios_parser_blank_crtc, */ + + .crtc_source_select = bios_parser_crtc_source_select, + + /* .external_encoder_control = bios_parser_external_encoder_control, */ + + .enable_disp_power_gating = bios_parser_enable_disp_power_gating, + + .post_init = bios_parser_post_init, + + .bios_parser_destroy = firmware_parser_destroy, + + .get_smu_clock_info = bios_parser_get_smu_clock_info, +}; + +static bool bios_parser_construct( + struct bios_parser *bp, + struct bp_init_data *init, + enum dce_version dce_version) +{ + uint16_t *rom_header_offset = NULL; + struct atom_rom_header_v2_2 *rom_header = NULL; + struct display_object_info_table_v1_4 *object_info_tbl; + struct atom_data_revision tbl_rev = {0}; + + if (!init) + return false; + + if (!init->bios) + return false; + + bp->base.funcs = &vbios_funcs; + bp->base.bios = init->bios; + bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT; + + bp->base.ctx = init->ctx; + + bp->base.bios_local_image = NULL; + + rom_header_offset = + GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER); + + if (!rom_header_offset) + return false; + + rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset); + + if (!rom_header) + return false; + + get_atom_data_table_revision(&rom_header->table_header, &tbl_rev); + if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2)) + return false; + + bp->master_data_tbl = + GET_IMAGE(struct atom_master_data_table_v2_1, + rom_header->masterdatatable_offset); + + if (!bp->master_data_tbl) + return false; + + bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo); + + if (!bp->object_info_tbl_offset) + return false; + + object_info_tbl = + GET_IMAGE(struct display_object_info_table_v1_4, + bp->object_info_tbl_offset); + + if (!object_info_tbl) + return false; + + get_atom_data_table_revision(&object_info_tbl->table_header, + &bp->object_info_tbl.revision); + + if (bp->object_info_tbl.revision.major == 1 + && bp->object_info_tbl.revision.minor >= 4) { + struct display_object_info_table_v1_4 *tbl_v1_4; + + tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4, + bp->object_info_tbl_offset); + if (!tbl_v1_4) + return false; + + bp->object_info_tbl.v1_4 = tbl_v1_4; + } else + return false; + + dal_firmware_parser_init_cmd_tbl(bp); + dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version); + + bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); + + return true; +} + +struct dc_bios *firmware_parser_create( + struct bp_init_data *init, + enum dce_version dce_version) +{ + struct bios_parser *bp = NULL; + + bp = dm_alloc(sizeof(struct bios_parser)); + if (!bp) + return NULL; + + if (bios_parser_construct(bp, init, dce_version)) + return &bp->base; + + dm_free(bp); + return NULL; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h new file mode 100644 index 000000000000..cb40546cdafe --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER2_H__ +#define __DAL_BIOS_PARSER2_H__ + +struct dc_bios *firmware_parser_create( + struct bp_init_data *init, + enum dce_version dce_version); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h new file mode 100644 index 000000000000..bf1f5c86e65c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h @@ -0,0 +1,74 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_BIOS_PARSER_TYPES_BIOS2_H__ +#define __DAL_BIOS_PARSER_TYPES_BIOS2_H__ + +#include "dc_bios_types.h" +#include "bios_parser_helper.h" + +/* use atomfirmware_bringup.h only. Not atombios.h anymore */ + +struct atom_data_revision { + uint32_t major; + uint32_t minor; +}; + +struct object_info_table { + struct atom_data_revision revision; + union { + struct display_object_info_table_v1_4 *v1_4; + }; +}; + +enum spread_spectrum_id { + SS_ID_UNKNOWN = 0, + SS_ID_DP1 = 0xf1, + SS_ID_DP2 = 0xf2, + SS_ID_LVLINK_2700MHZ = 0xf3, + SS_ID_LVLINK_1620MHZ = 0xf4 +}; + +struct bios_parser { + struct dc_bios base; + + struct object_info_table object_info_tbl; + uint32_t object_info_tbl_offset; + struct atom_master_data_table_v2_1 *master_data_tbl; + + + const struct bios_parser_helper *bios_helper; + + const struct command_table_helper *cmd_helper; + struct cmd_tbl cmd_tbl; + + bool remap_device_tags; +}; + +/* Bios Parser from DC Bios */ +#define BP_FROM_DCB(dc_bios) \ + container_of(dc_bios, struct bios_parser, base) + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c new file mode 100644 index 000000000000..36d158249182 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -0,0 +1,813 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "ObjectID.h" +#include "atomfirmware.h" +#include "atomfirmwareid.h" + +#include "include/bios_parser_interface.h" + +#include "command_table2.h" +#include "command_table_helper2.h" +#include "bios_parser_helper.h" +#include "bios_parser_types_internal2.h" + +#define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\ + (((char *)(&((\ + struct atom_master_list_of_##MasterOrData##_functions_v2_1 *)0)\ + ->FieldName)-(char *)0)/sizeof(uint16_t)) + +#define EXEC_BIOS_CMD_TABLE(fname, params)\ + (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname), \ + ¶ms) == 0) + +#define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\ + cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev) + +#define BIOS_CMD_TABLE_PARA_REVISION(fname)\ + bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \ + GET_INDEX_INTO_MASTER_TABLE(command, fname)) + +static void init_dig_encoder_control(struct bios_parser *bp); +static void init_transmitter_control(struct bios_parser *bp); +static void init_set_pixel_clock(struct bios_parser *bp); + +static void init_set_crtc_timing(struct bios_parser *bp); + +static void init_select_crtc_source(struct bios_parser *bp); +static void init_enable_crtc(struct bios_parser *bp); + +static void init_external_encoder_control(struct bios_parser *bp); +static void init_enable_disp_power_gating(struct bios_parser *bp); +static void init_set_dce_clock(struct bios_parser *bp); +static void init_get_smu_clock_info(struct bios_parser *bp); + +void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) +{ + init_dig_encoder_control(bp); + init_transmitter_control(bp); + init_set_pixel_clock(bp); + + init_set_crtc_timing(bp); + + init_select_crtc_source(bp); + init_enable_crtc(bp); + + init_external_encoder_control(bp); + init_enable_disp_power_gating(bp); + init_set_dce_clock(bp); + init_get_smu_clock_info(bp); +} + +static uint32_t bios_cmd_table_para_revision(void *cgs_device, + uint32_t index) +{ + uint8_t frev, crev; + + if (cgs_atom_get_cmd_table_revs(cgs_device, + index, + &frev, &crev) != 0) + return 0; + return crev; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** D I G E N C O D E R C O N T R O L + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result encoder_control_digx_v1_5( + struct bios_parser *bp, + struct bp_encoder_control *cntl); + +static void init_dig_encoder_control(struct bios_parser *bp) +{ + uint32_t version = + BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol); + + switch (version) { + case 5: + bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; + break; + default: + bp->cmd_tbl.dig_encoder_control = NULL; + break; + } +} + +static enum bp_result encoder_control_digx_v1_5( + struct bios_parser *bp, + struct bp_encoder_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct dig_encoder_stream_setup_parameters_v1_5 params = {0}; + + params.digid = (uint8_t)(cntl->engine_id); + params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action); + + params.pclk_10khz = cntl->pixel_clock / 10; + params.digmode = + (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom( + cntl->signal, + cntl->enable_dp_audio)); + params.lanenum = (uint8_t)(cntl->lanes_number); + + switch (cntl->color_depth) { + case COLOR_DEPTH_888: + params.bitpercolor = PANEL_8BIT_PER_COLOR; + break; + case COLOR_DEPTH_101010: + params.bitpercolor = PANEL_10BIT_PER_COLOR; + break; + case COLOR_DEPTH_121212: + params.bitpercolor = PANEL_12BIT_PER_COLOR; + break; + case COLOR_DEPTH_161616: + params.bitpercolor = PANEL_16BIT_PER_COLOR; + break; + default: + break; + } + + if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) + switch (cntl->color_depth) { + case COLOR_DEPTH_101010: + params.pclk_10khz = + (params.pclk_10khz * 30) / 24; + break; + case COLOR_DEPTH_121212: + params.pclk_10khz = + (params.pclk_10khz * 36) / 24; + break; + case COLOR_DEPTH_161616: + params.pclk_10khz = + (params.pclk_10khz * 48) / 24; + break; + default: + break; + } + + if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params)) + result = BP_RESULT_OK; + + return result; +} + +/***************************************************************************** + ****************************************************************************** + ** + ** TRANSMITTER CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl); + +static void init_transmitter_control(struct bios_parser *bp) +{ + uint8_t frev; + uint8_t crev; + + if (BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) != 0) + BREAK_TO_DEBUGGER(); + switch (crev) { + case 6: + bp->cmd_tbl.transmitter_control = transmitter_control_v1_6; + break; + default: + bp->cmd_tbl.transmitter_control = NULL; + break; + } +} + +static enum bp_result transmitter_control_v1_6( + struct bios_parser *bp, + struct bp_transmitter_control *cntl) +{ + enum bp_result result = BP_RESULT_FAILURE; + const struct command_table_helper *cmd = bp->cmd_helper; + struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } }; + + ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter); + ps.param.action = (uint8_t)cntl->action; + + if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) + ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings; + else + ps.param.mode_laneset.digmode = + cmd->signal_type_to_atom_dig_mode(cntl->signal); + + ps.param.lanenum = (uint8_t)cntl->lanes_number; + ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); + ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); + ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id; + ps.param.symclk_10khz = cntl->pixel_clock/10; + + + if (cntl->action == TRANSMITTER_CONTROL_ENABLE || + cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || + cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ + "************************%s:ps.param.symclk_10khz = %d\n",\ + __func__, ps.param.symclk_10khz); + } + + +/*color_depth not used any more, driver has deep color factor in the Phyclk*/ + if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps)) + result = BP_RESULT_OK; + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SET PIXEL CLOCK + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + +static void init_set_pixel_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) { + case 7: + bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; + break; + default: + bp->cmd_tbl.set_pixel_clock = NULL; + break; + } +} + + + +static enum bp_result set_pixel_clock_v7( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct set_pixel_clock_parameter_v1_7 clk; + uint8_t controller_id; + uint32_t pll_id; + + memset(&clk, 0, sizeof(clk)); + + if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id) + && bp->cmd_helper->controller_id_to_atom(bp_params-> + controller_id, &controller_id)) { + /* Note: VBIOS still wants to use ucCRTC name which is now + * 1 byte in ULONG + *typedef struct _CRTC_PIXEL_CLOCK_FREQ + *{ + * target the pixel clock to drive the CRTC timing. + * ULONG ulPixelClock:24; + * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to + * previous version. + * ATOM_CRTC1~6, indicate the CRTC controller to + * ULONG ucCRTC:8; + * drive the pixel clock. not used for DCPLL case. + *}CRTC_PIXEL_CLOCK_FREQ; + *union + *{ + * pixel clock and CRTC id frequency + * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; + * ULONG ulDispEngClkFreq; dispclk frequency + *}; + */ + clk.crtc_id = controller_id; + clk.pll_id = (uint8_t) pll_id; + clk.encoderobjid = + bp->cmd_helper->encoder_id_to_atom( + dal_graphics_object_id_get_encoder_id( + bp_params->encoder_object_id)); + + clk.encoder_mode = (uint8_t) bp-> + cmd_helper->encoder_mode_bp_to_atom( + bp_params->signal_type, false); + + /* We need to convert from KHz units into 10KHz units */ + clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock * + 10); + + clk.deep_color_ratio = + (uint8_t) bp->cmd_helper-> + transmitter_color_depth_to_atom( + bp_params->color_depth); + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ + "************************%s:program display clock = %d"\ + "colorDepth = %d\n", __func__,\ + bp_params->target_pixel_clock, bp_params->color_depth); + + if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL; + + if (bp_params->flags.PROGRAM_PHY_PLL_ONLY) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL; + + if (bp_params->flags.SUPPORT_YUV_420) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE; + + if (bp_params->flags.SET_XTALIN_REF_SRC) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN; + + if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK; + + if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK) + clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN; + + if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk)) + result = BP_RESULT_OK; + } + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SET CRTC TIMING + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + +static void init_set_crtc_timing(struct bios_parser *bp) +{ + uint32_t dtd_version = + BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming); + + switch (dtd_version) { + case 3: + bp->cmd_tbl.set_crtc_timing = + set_crtc_using_dtd_timing_v3; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } +} + +static enum bp_result set_crtc_using_dtd_timing_v3( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + struct set_crtc_using_dtd_timing_parameters params = {0}; + uint8_t atom_controller_id; + + if (bp->cmd_helper->controller_id_to_atom( + bp_params->controller_id, &atom_controller_id)) + params.crtc_id = atom_controller_id; + + /* bios usH_Size wants h addressable size */ + params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable); + /* bios usH_Blanking_Time wants borders included in blanking */ + params.h_blanking_time = + cpu_to_le16((uint16_t)(bp_params->h_total - + bp_params->h_addressable)); + /* bios usV_Size wants v addressable size */ + params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable); + /* bios usV_Blanking_Time wants borders included in blanking */ + params.v_blanking_time = + cpu_to_le16((uint16_t)(bp_params->v_total - + bp_params->v_addressable)); + /* bios usHSyncOffset is the offset from the end of h addressable, + * our horizontalSyncStart is the offset from the beginning + * of h addressable + */ + params.h_syncoffset = + cpu_to_le16((uint16_t)(bp_params->h_sync_start - + bp_params->h_addressable)); + params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width); + /* bios usHSyncOffset is the offset from the end of v addressable, + * our verticalSyncStart is the offset from the beginning of + * v addressable + */ + params.v_syncoffset = + cpu_to_le16((uint16_t)(bp_params->v_sync_start - + bp_params->v_addressable)); + params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width); + + /* we assume that overscan from original timing does not get bigger + * than 255 + * we will program all the borders in the Set CRTC Overscan call below + */ + + if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_HSYNC_POLARITY); + + if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_VSYNC_POLARITY); + + if (bp_params->flags.INTERLACE) { + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + ATOM_INTERLACE); + + /* original DAL code has this condition to apply this + * for non-TV/CV only + * due to complex MV testing for possible impact + * if ( pACParameters->signal != SignalType_YPbPr && + * pACParameters->signal != SignalType_Composite && + * pACParameters->signal != SignalType_SVideo) + */ + { + /* HW will deduct 0.5 line from 2nd feild. + * i.e. for 1080i, it is 2 lines for 1st field, + * 2.5 lines for the 2nd feild. we need input as 5 + * instead of 4. + * but it is 4 either from Edid data (spec CEA 861) + * or CEA timing table. + */ + params.v_syncoffset = + cpu_to_le16(le16_to_cpu(params.v_syncoffset) + + 1); + + } + } + + if (bp_params->flags.HORZ_COUNT_BY_TWO) + params.modemiscinfo = + cpu_to_le16(le16_to_cpu(params.modemiscinfo) | + 0x100); /* ATOM_DOUBLE_CLOCK_MODE */ + + if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** SELECT CRTC SOURCE + ** + ****************************************************************************** + *****************************************************************************/ + + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + +static void init_select_crtc_source(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) { + case 3: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; + break; + default: + bp->cmd_tbl.select_crtc_source = NULL; + break; + } +} + + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + bool result = BP_RESULT_FAILURE; + struct select_crtc_source_parameters_v2_3 params; + uint8_t atom_controller_id; + uint32_t atom_engine_id; + enum signal_type s = bp_params->signal; + + memset(¶ms, 0, sizeof(params)); + + if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, + &atom_controller_id)) + params.crtc_id = atom_controller_id; + else + return result; + + if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id, + &atom_engine_id)) + params.encoder_id = (uint8_t)atom_engine_id; + else + return result; + + if (s == SIGNAL_TYPE_EDP || + (s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal == + SIGNAL_TYPE_LVDS)) + s = SIGNAL_TYPE_LVDS; + + params.encode_mode = + bp->cmd_helper->encoder_mode_bp_to_atom( + s, bp_params->enable_dp_audio); + /* Needed for VBIOS Random Spatial Dithering feature */ + params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth); + + if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** ENABLE CRTC + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + +static void init_enable_crtc(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) { + case 1: + bp->cmd_tbl.enable_crtc = enable_crtc_v1; + break; + default: + bp->cmd_tbl.enable_crtc = NULL; + break; + } +} + +static enum bp_result enable_crtc_v1( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable) +{ + bool result = BP_RESULT_FAILURE; + struct enable_crtc_parameters params = {0}; + uint8_t id; + + if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) + params.crtc_id = id; + else + return BP_RESULT_BADINPUT; + + if (enable) + params.enable = ATOM_ENABLE; + else + params.enable = ATOM_DISABLE; + + if (EXEC_BIOS_CMD_TABLE(enablecrtc, params)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** DISPLAY PLL + ** + ****************************************************************************** + *****************************************************************************/ + + + +/****************************************************************************** + ****************************************************************************** + ** + ** EXTERNAL ENCODER CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + +static void init_external_encoder_control( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) { + case 3: + bp->cmd_tbl.external_encoder_control = + external_encoder_control_v3; + break; + default: + bp->cmd_tbl.external_encoder_control = NULL; + break; + } +} + +static enum bp_result external_encoder_control_v3( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl) +{ + /* TODO */ + return BP_RESULT_OK; +} + +/****************************************************************************** + ****************************************************************************** + ** + ** ENABLE DISPLAY POWER GATING + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + +static void init_enable_disp_power_gating( + struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) { + case 1: + bp->cmd_tbl.enable_disp_power_gating = + enable_disp_power_gating_v2_1; + break; + default: + bp->cmd_tbl.enable_disp_power_gating = NULL; + break; + } +} + +static enum bp_result enable_disp_power_gating_v2_1( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action) +{ + enum bp_result result = BP_RESULT_FAILURE; + + + struct enable_disp_power_gating_ps_allocation ps = { { 0 } }; + uint8_t atom_crtc_id; + + if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id)) + ps.param.disp_pipe_id = atom_crtc_id; + else + return BP_RESULT_BADINPUT; + + ps.param.enable = + bp->cmd_helper->disp_power_gating_action_to_atom(action); + + if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param)) + result = BP_RESULT_OK; + + return result; +} + +/****************************************************************************** +******************************************************************************* + ** + ** SET DCE CLOCK + ** +******************************************************************************* +*******************************************************************************/ + +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); + +static void init_set_dce_clock(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) { + case 1: + bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; + break; + default: + bp->cmd_tbl.set_dce_clock = NULL; + break; + } +} + +static enum bp_result set_dce_clock_v2_1( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + + struct set_dce_clock_ps_allocation_v2_1 params; + uint32_t atom_pll_id; + uint32_t atom_clock_type; + const struct command_table_helper *cmd = bp->cmd_helper; + + memset(¶ms, 0, sizeof(params)); + + if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) || + !cmd->dc_clock_type_to_atom(bp_params->clock_type, + &atom_clock_type)) + return BP_RESULT_BADINPUT; + + params.param.dceclksrc = atom_pll_id; + params.param.dceclktype = atom_clock_type; + + if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { + if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK; + + if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE; + + if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN; + + if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK) + params.param.dceclkflag |= + DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA; + } else + /* only program clock frequency if display clock is used; + * VBIOS will program DPREFCLK + * We need to convert from KHz units into 10KHz units + */ + params.param.dceclk_10khz = cpu_to_le32( + bp_params->target_clock_frequency / 10); + dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE, + "************************%s:target_clock_frequency = %d"\ + "clock_type = %d \n", __func__,\ + bp_params->target_clock_frequency,\ + bp_params->clock_type); + + if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) { + /* Convert from 10KHz units back to KHz */ + bp_params->target_clock_frequency = le32_to_cpu( + params.param.dceclk_10khz) * 10; + result = BP_RESULT_OK; + } + + return result; +} + + +/****************************************************************************** + ****************************************************************************** + ** + ** GET SMU CLOCK INFO + ** + ****************************************************************************** + *****************************************************************************/ + +static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp); + +static void init_get_smu_clock_info(struct bios_parser *bp) +{ + /* TODO add switch for table vrsion */ + bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1; + +} + +static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp) +{ + struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0}; + struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output; + + smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ; + + /* Get Specific Clock */ + if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) { + memmove(&smu_output, &smu_input, sizeof( + struct atom_get_smu_clock_info_parameters_v3_1)); + return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz; + } + + return 0; +} + diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h new file mode 100644 index 000000000000..59061b806df5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE2_H__ +#define __DAL_COMMAND_TABLE2_H__ + +struct bios_parser; +struct bp_encoder_control; + +struct cmd_tbl { + enum bp_result (*dig_encoder_control)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*encoder_control_dig1)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*encoder_control_dig2)( + struct bios_parser *bp, + struct bp_encoder_control *control); + enum bp_result (*transmitter_control)( + struct bios_parser *bp, + struct bp_transmitter_control *control); + enum bp_result (*set_pixel_clock)( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*enable_spread_spectrum_on_ppll)( + struct bios_parser *bp, + struct bp_spread_spectrum_parameters *bp_params, + bool enable); + enum bp_result (*adjust_display_pll)( + struct bios_parser *bp, + struct bp_adjust_pixel_clock_parameters *bp_params); + enum bp_result (*dac1_encoder_control)( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + enum bp_result (*dac2_encoder_control)( + struct bios_parser *bp, + bool enable, + uint32_t pixel_clock, + uint8_t dac_standard); + enum bp_result (*dac1_output_control)( + struct bios_parser *bp, + bool enable); + enum bp_result (*dac2_output_control)( + struct bios_parser *bp, + bool enable); + enum bp_result (*set_crtc_timing)( + struct bios_parser *bp, + struct bp_hw_crtc_timing_parameters *bp_params); + enum bp_result (*select_crtc_source)( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + enum bp_result (*enable_crtc)( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + enum bp_result (*enable_crtc_mem_req)( + struct bios_parser *bp, + enum controller_id controller_id, + bool enable); + enum bp_result (*program_clock)( + struct bios_parser *bp, + struct bp_pixel_clock_parameters *bp_params); + enum bp_result (*external_encoder_control)( + struct bios_parser *bp, + struct bp_external_encoder_control *cntl); + enum bp_result (*enable_disp_power_gating)( + struct bios_parser *bp, + enum controller_id crtc_id, + enum bp_pipe_control_action action); + enum bp_result (*set_dce_clock)( + struct bios_parser *bp, + struct bp_set_dce_clock_parameters *bp_params); + unsigned int (*get_smu_clock_info)( + struct bios_parser *bp); + +}; + +void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c new file mode 100644 index 000000000000..b0dcad260be6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -0,0 +1,260 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "ObjectID.h" +#include "atomfirmware.h" +#include "atomfirmwareid.h" + +#include "include/bios_parser_types.h" + +#include "command_table_helper2.h" + +bool dal_bios_parser_init_cmd_tbl_helper2( + const struct command_table_helper **h, + enum dce_version dce) +{ + switch (dce) { + case DCE_VERSION_8_0: + *h = dal_cmd_tbl_helper_dce80_get_table(); + return true; + + case DCE_VERSION_10_0: + *h = dal_cmd_tbl_helper_dce110_get_table(); + return true; + + case DCE_VERSION_11_0: + *h = dal_cmd_tbl_helper_dce110_get_table(); + return true; + + case DCE_VERSION_11_2: + *h = dal_cmd_tbl_helper_dce112_get_table2(); + return true; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + *h = dal_cmd_tbl_helper_dce112_get_table2(); + return true; +#endif + + default: + /* Unsupported DCE */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +/* real implementations */ + +bool dal_cmd_table_helper_controller_id_to_atom2( + enum controller_id id, + uint8_t *atom_id) +{ + if (atom_id == NULL) { + BREAK_TO_DEBUGGER(); + return false; + } + + switch (id) { + case CONTROLLER_ID_D0: + *atom_id = ATOM_CRTC1; + return true; + case CONTROLLER_ID_D1: + *atom_id = ATOM_CRTC2; + return true; + case CONTROLLER_ID_D2: + *atom_id = ATOM_CRTC3; + return true; + case CONTROLLER_ID_D3: + *atom_id = ATOM_CRTC4; + return true; + case CONTROLLER_ID_D4: + *atom_id = ATOM_CRTC5; + return true; + case CONTROLLER_ID_D5: + *atom_id = ATOM_CRTC6; + return true; + /* TODO :case CONTROLLER_ID_UNDERLAY0: + *atom_id = ATOM_UNDERLAY_PIPE0; + return true; + */ + case CONTROLLER_ID_UNDEFINED: + *atom_id = ATOM_CRTC_INVALID; + return true; + default: + /* Wrong controller id */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +/** +* translate_transmitter_bp_to_atom +* +* @brief +* Translate the Transmitter to the corresponding ATOM BIOS value +* +* @param +* input transmitter +* output digitalTransmitter +* // =00: Digital Transmitter1 ( UNIPHY linkAB ) +* // =01: Digital Transmitter2 ( UNIPHY linkCD ) +* // =02: Digital Transmitter3 ( UNIPHY linkEF ) +*/ +uint8_t dal_cmd_table_helper_transmitter_bp_to_atom2( + enum transmitter t) +{ + switch (t) { + case TRANSMITTER_UNIPHY_A: + case TRANSMITTER_UNIPHY_B: + case TRANSMITTER_TRAVIS_LCD: + return 0; + case TRANSMITTER_UNIPHY_C: + case TRANSMITTER_UNIPHY_D: + return 1; + case TRANSMITTER_UNIPHY_E: + case TRANSMITTER_UNIPHY_F: + return 2; + default: + /* Invalid Transmitter Type! */ + BREAK_TO_DEBUGGER(); + return 0; + } +} + +uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom2( + enum signal_type s, + bool enable_dp_audio) +{ + switch (s) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return ATOM_ENCODER_MODE_DVI; + case SIGNAL_TYPE_HDMI_TYPE_A: + return ATOM_ENCODER_MODE_HDMI; + case SIGNAL_TYPE_LVDS: + return ATOM_ENCODER_MODE_LVDS; + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_VIRTUAL: + if (enable_dp_audio) + return ATOM_ENCODER_MODE_DP_AUDIO; + else + return ATOM_ENCODER_MODE_DP; + case SIGNAL_TYPE_RGB: + return ATOM_ENCODER_MODE_CRT; + default: + return ATOM_ENCODER_MODE_CRT; + } +} + +bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src2( + enum clock_source_id id, + uint32_t *ref_clk_src_id) +{ + if (ref_clk_src_id == NULL) { + BREAK_TO_DEBUGGER(); + return false; + } + + switch (id) { + case CLOCK_SOURCE_ID_PLL1: + *ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL; + return true; + case CLOCK_SOURCE_ID_PLL2: + *ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL; + return true; + /*TODO:case CLOCK_SOURCE_ID_DCPLL: + *ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL; + return true; + */ + case CLOCK_SOURCE_ID_EXTERNAL: + *ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK; + return true; + case CLOCK_SOURCE_ID_UNDEFINED: + *ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID; + return true; + default: + /* Unsupported clock source id */ + BREAK_TO_DEBUGGER(); + return false; + } +} + +uint8_t dal_cmd_table_helper_encoder_id_to_atom2( + enum encoder_id id) +{ + switch (id) { + case ENCODER_ID_INTERNAL_LVDS: + return ENCODER_OBJECT_ID_INTERNAL_LVDS; + case ENCODER_ID_INTERNAL_TMDS1: + return ENCODER_OBJECT_ID_INTERNAL_TMDS1; + case ENCODER_ID_INTERNAL_TMDS2: + return ENCODER_OBJECT_ID_INTERNAL_TMDS2; + case ENCODER_ID_INTERNAL_DAC1: + return ENCODER_OBJECT_ID_INTERNAL_DAC1; + case ENCODER_ID_INTERNAL_DAC2: + return ENCODER_OBJECT_ID_INTERNAL_DAC2; + case ENCODER_ID_INTERNAL_LVTM1: + return ENCODER_OBJECT_ID_INTERNAL_LVTM1; + case ENCODER_ID_INTERNAL_HDMI: + return ENCODER_OBJECT_ID_HDMI_INTERNAL; + case ENCODER_ID_EXTERNAL_TRAVIS: + return ENCODER_OBJECT_ID_TRAVIS; + case ENCODER_ID_EXTERNAL_NUTMEG: + return ENCODER_OBJECT_ID_NUTMEG; + case ENCODER_ID_INTERNAL_KLDSCP_TMDS1: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; + case ENCODER_ID_INTERNAL_KLDSCP_DAC1: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; + case ENCODER_ID_INTERNAL_KLDSCP_DAC2: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; + case ENCODER_ID_EXTERNAL_MVPU_FPGA: + return ENCODER_OBJECT_ID_MVPU_FPGA; + case ENCODER_ID_INTERNAL_DDI: + return ENCODER_OBJECT_ID_INTERNAL_DDI; + case ENCODER_ID_INTERNAL_UNIPHY: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY; + case ENCODER_ID_INTERNAL_KLDSCP_LVTMA: + return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA; + case ENCODER_ID_INTERNAL_UNIPHY1: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1; + case ENCODER_ID_INTERNAL_UNIPHY2: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2; + case ENCODER_ID_INTERNAL_UNIPHY3: + return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3; + case ENCODER_ID_INTERNAL_WIRELESS: + return ENCODER_OBJECT_ID_INTERNAL_VCE; + case ENCODER_ID_INTERNAL_VIRTUAL: + return ENCODER_OBJECT_ID_NONE; + case ENCODER_ID_UNKNOWN: + return ENCODER_OBJECT_ID_NONE; + default: + /* Invalid encoder id */ + BREAK_TO_DEBUGGER(); + return ENCODER_OBJECT_ID_NONE; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h new file mode 100644 index 000000000000..9f587c91d843 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h @@ -0,0 +1,82 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER2_H__ +#define __DAL_COMMAND_TABLE_HELPER2_H__ + +#include "dce80/command_table_helper_dce80.h" +#include "dce110/command_table_helper_dce110.h" +#include "dce112/command_table_helper2_dce112.h" + +struct command_table_helper { + bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id); + uint8_t (*encoder_action_to_atom)( + enum bp_encoder_control_action action); + uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s, + bool enable_dp_audio); + bool (*engine_bp_to_atom)(enum engine_id engine_id, + uint32_t *atom_engine_id); + bool (*clock_source_id_to_atom)(enum clock_source_id id, + uint32_t *atom_pll_id); + bool (*clock_source_id_to_ref_clk_src)( + enum clock_source_id id, + uint32_t *ref_clk_src_id); + uint8_t (*transmitter_bp_to_atom)(enum transmitter t); + uint8_t (*encoder_id_to_atom)(enum encoder_id id); + uint8_t (*clock_source_id_to_atom_phy_clk_src_id)( + enum clock_source_id id); + uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s); + uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id); + uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id); + uint8_t (*phy_id_to_atom)(enum transmitter t); + uint8_t (*disp_power_gating_action_to_atom)( + enum bp_pipe_control_action action); + bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id, + uint32_t *atom_clock_type); + uint8_t (*transmitter_color_depth_to_atom)( + enum transmitter_color_depth id); +}; + +bool dal_bios_parser_init_cmd_tbl_helper2(const struct command_table_helper **h, + enum dce_version dce); + +bool dal_cmd_table_helper_controller_id_to_atom2( + enum controller_id id, + uint8_t *atom_id); + +uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom2( + enum signal_type s, + bool enable_dp_audio); + +bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src2( + enum clock_source_id id, + uint32_t *ref_clk_src_id); + +uint8_t dal_cmd_table_helper_transmitter_bp_to_atom2( + enum transmitter t); + +uint8_t dal_cmd_table_helper_encoder_id_to_atom2( + enum encoder_id id); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c new file mode 100644 index 000000000000..d342cdecba11 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c @@ -0,0 +1,418 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/bios_parser_types.h" + +#include "../command_table_helper2.h" + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGG_SEL; + break; + case ENGINE_ID_UNKNOWN: + /* No DIG_FRONT is associated to DIG_BACKEND */ + atom_dig_encoder_sel = 0; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL; + break; + } + + return 0; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_COMBO_PHY_PLL0: + *atom_pll_id = ATOM_COMBOPHY_PLL0; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL1: + *atom_pll_id = ATOM_COMBOPHY_PLL1; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL2: + *atom_pll_id = ATOM_COMBOPHY_PLL2; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL3: + *atom_pll_id = ATOM_COMBOPHY_PLL3; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL4: + *atom_pll_id = ATOM_COMBOPHY_PLL4; + break; + case CLOCK_SOURCE_COMBO_PHY_PLL5: + *atom_pll_id = ATOM_COMBOPHY_PLL5; + break; + case CLOCK_SOURCE_COMBO_DISPLAY_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_GCK_DFS; + break; + case CLOCK_SOURCE_ID_VCE: + *atom_pll_id = ATOM_DP_DTO; + break; + case CLOCK_SOURCE_ID_DP_DTO: + *atom_pll_id = ATOM_DP_DTO; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + /* Should not happen */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_STREAM_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +static bool dc_clock_type_to_atom( + enum bp_dce_clock_type id, + uint32_t *atom_clock_type) +{ + bool retCode = true; + + if (atom_clock_type != NULL) { + switch (id) { + case DCECLOCK_TYPE_DISPLAY_CLOCK: + *atom_clock_type = DCE_CLOCK_TYPE_DISPCLK; + break; + + case DCECLOCK_TYPE_DPREFCLK: + *atom_clock_type = DCE_CLOCK_TYPE_DPREFCLK; + break; + + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + } + + return retCode; +} + +static uint8_t transmitter_color_depth_to_atom(enum transmitter_color_depth id) +{ + uint8_t atomColorDepth = 0; + + switch (id) { + case TRANSMITTER_COLOR_DEPTH_24: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS; + break; + case TRANSMITTER_COLOR_DEPTH_30: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4; + break; + case TRANSMITTER_COLOR_DEPTH_36: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2; + break; + case TRANSMITTER_COLOR_DEPTH_48: + atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1; + break; + default: + ASSERT_CRITICAL(false); /* Unhandle action in driver! */ + break; + } + + return atomColorDepth; +} + +/* function table */ +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom2, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .clock_source_id_to_ref_clk_src = NULL, + .transmitter_bp_to_atom = NULL, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom2, + .encoder_mode_bp_to_atom = + dal_cmd_table_helper_encoder_mode_bp_to_atom2, + .dc_clock_type_to_atom = dc_clock_type_to_atom, + .transmitter_color_depth_to_atom = transmitter_color_depth_to_atom, +}; + +/* + * dal_cmd_tbl_helper_dce110_get_table + * + * @brief + * Initialize command table helper functions + * + * @param + * const struct command_table_helper **h - [out] struct of functions + * + */ +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2() +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h new file mode 100644 index 000000000000..abf28a06f5bc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER2_DCE112_H__ +#define __DAL_COMMAND_TABLE_HELPER2_DCE112_H__ + +struct command_table_helper; + +/* Initialize command table helper functions */ +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2(void); + +#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */ -- GitLab From ef40b2346563aa11575446c8e3b04af44c31abb5 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:32:06 -0500 Subject: [PATCH 0313/2898] drm/amd/display: Add DCE12 gpio support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../dc/gpio/dce120/hw_factory_dce120.c | 197 +++++++++ .../dc/gpio/dce120/hw_factory_dce120.h | 32 ++ .../dc/gpio/dce120/hw_translate_dce120.c | 408 ++++++++++++++++++ .../dc/gpio/dce120/hw_translate_dce120.h | 34 ++ 4 files changed, 671 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.h diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c new file mode 100644 index 000000000000..4ced9a7d63dd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c @@ -0,0 +1,197 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +#include "hw_factory_dce120.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#define block HPD +#define reg_num 0 + +/* set field name */ +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix + +/* set field name */ +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define REG(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define REGI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + + +/* fucntion table */ +static const struct hw_factory_funcs funcs = { + .create_ddc_data = dal_hw_ddc_create, + .create_ddc_clock = dal_hw_ddc_create, + .create_generic = NULL, + .create_hpd = dal_hw_hpd_create, + .create_sync = NULL, + .create_gsl = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; +/* + * dal_hw_factory_dce120_init + * + * @brief + * Initialize HW factory function pointers and pin info + * + * @param + * struct hw_factory *factory - [out] struct of function pointers + */ +void dal_hw_factory_dce120_init(struct hw_factory *factory) +{ + /*TODO check ASIC CAPs*/ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.h b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.h new file mode 100644 index 000000000000..db260c351f73 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCE120_H__ +#define __DAL_HW_FACTORY_DCE120_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_dce120_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DCE120_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c new file mode 100644 index 000000000000..af3843a69652 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c @@ -0,0 +1,408 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "hw_translate_dce120.h" + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define REG(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define REGI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case REG(DC_GPIO_GENERIC_A): + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* HPD */ + case REG(DC_GPIO_HPD_A): + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* SYNCA */ + case REG(DC_GPIO_SYNCA_A): + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* REG(DC_GPIO_GENLK_MASK */ + case REG(DC_GPIO_GENLK_A): + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case REG(DC_GPIO_DDC1_A): + *en = GPIO_DDC_LINE_DDC1; + return true; + case REG(DC_GPIO_DDC2_A): + *en = GPIO_DDC_LINE_DDC2; + return true; + case REG(DC_GPIO_DDC3_A): + *en = GPIO_DDC_LINE_DDC3; + return true; + case REG(DC_GPIO_DDC4_A): + *en = GPIO_DDC_LINE_DDC4; + return true; + case REG(DC_GPIO_DDC5_A): + *en = GPIO_DDC_LINE_DDC5; + return true; + case REG(DC_GPIO_DDC6_A): + *en = GPIO_DDC_LINE_DDC6; + return true; + case REG(DC_GPIO_DDCVGA_A): + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case REG(DC_GPIO_I2CPAD_A): + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case REG(DC_GPIO_PWRSEQ_A): + case REG(DC_GPIO_PAD_STRENGTH_1): + case REG(DC_GPIO_PAD_STRENGTH_2): + case REG(DC_GPIO_DEBUG): + return false; + /* UNEXPECTED */ + default: + ASSERT_CRITICAL(false); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC6: + info->offset = REG(DC_GPIO_DDC6_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = REG(DC_GPIO_I2CPAD_A); + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC6: + info->offset = REG(DC_GPIO_DDC6_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = REG(DC_GPIO_I2CPAD_A); + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = REG(DC_GPIO_GENERIC_A); + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = REG(DC_GPIO_HPD_A); + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = REG(DC_GPIO_SYNCA_A); + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = REG(DC_GPIO_SYNCA_A); + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_VIP_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +/* + * dal_hw_translate_dce120_init + * + * @brief + * Initialize Hw translate function pointers. + * + * @param + * struct hw_translate *tr - [out] struct of function pointers + * + */ +void dal_hw_translate_dce120_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.h b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.h new file mode 100644 index 000000000000..c21766894af3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCE120_H__ +#define __DAL_HW_TRANSLATE_DCE120_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_dce120_init(struct hw_translate *tr); + +#endif /* __DAL_HW_TRANSLATE_DCE120_H__ */ -- GitLab From c56fbb34717367bbd47fc795625100e53bed600f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:33:19 -0500 Subject: [PATCH 0314/2898] drm/amd/display: Add DCE12 i2c/aux support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/i2caux/dce120/i2caux_dce120.c | 125 ++++++++++++++++++ .../display/dc/i2caux/dce120/i2caux_dce120.h | 32 +++++ 2 files changed, 157 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c new file mode 100644 index 000000000000..91198295f1a4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c @@ -0,0 +1,125 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +#include "../dce110/i2c_hw_engine_dce110.h" +#include "../dce110/aux_engine_dce110.h" +#include "../dce110/i2caux_dce110.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK \ +} + +static const struct dce110_aux_registers dce120_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5), +}; + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_i2c_hw_engine_registers dce120_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +struct i2caux *dal_i2caux_dce120_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dce120_aux_regs, + dce120_hw_engine_regs, + &i2c_shift, + &i2c_mask)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h new file mode 100644 index 000000000000..b6ac47617c70 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-16 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCE120_H__ +#define __DAL_I2C_AUX_DCE120_H__ + +struct i2caux *dal_i2caux_dce120_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DCE120_H__ */ -- GitLab From 9a48d684482e32edd5d96b14aa5517689bf904a3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:34:18 -0500 Subject: [PATCH 0315/2898] drm/amd/display: Add DCE12 irq support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../dc/irq/dce120/irq_service_dce120.c | 293 ++++++++++++++++++ .../dc/irq/dce120/irq_service_dce120.h | 34 ++ 2 files changed, 327 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.h diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c new file mode 100644 index 000000000000..5a263b2efa51 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -0,0 +1,293 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "irq_service_dce120.h" +#include "../dce110/irq_service_dce110.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "ivsrcid/ivsrcid_vislands30.h" + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + HPD0_DC_HPD_INT_STATUS, + DC_HPD_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + HPD0_DC_HPD_INT_CONTROL, + DC_HPD_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SRI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ + .enable_reg = SRI(reg1, block, reg_num),\ + .enable_mask = \ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI(reg2, block, reg_num),\ + .ack_mask = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_rx_irq_info_funcs\ + } +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + IRQ_REG_ENTRY(DCP, reg_num, \ + GRPH_INTERRUPT_CONTROL, GRPH_PFLIP_INT_MASK, \ + GRPH_INTERRUPT_STATUS, GRPH_PFLIP_INT_CLEAR),\ + .status_reg = SRI(GRPH_INTERRUPT_STATUS, DCP, reg_num),\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + IRQ_REG_ENTRY(CRTC, reg_num,\ + CRTC_INTERRUPT_CONTROL, CRTC_V_UPDATE_INT_MSK,\ + CRTC_V_UPDATE_INT_STATUS, CRTC_V_UPDATE_INT_CLEAR),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + IRQ_REG_ENTRY(LB, reg_num,\ + LB_INTERRUPT_MASK, VBLANK_INTERRUPT_MASK,\ + LB_VBLANK_STATUS, VBLANK_ACK),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dce120[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(0), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_rx_int_entry(0), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + pflip_int_entry(4), + pflip_int_entry(5), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), +}; + +static const struct irq_service_funcs irq_service_funcs_dce120 = { + .to_dal_irq_source = to_dal_irq_source_dce110 +}; + +static bool construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!dal_irq_service_construct(irq_service, init_data)) + return false; + + irq_service->info = irq_source_info_dce120; + irq_service->funcs = &irq_service_funcs_dce120; + + return true; +} + +struct irq_service *dal_irq_service_dce120_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + + if (!irq_service) + return NULL; + + if (construct(irq_service, init_data)) + return irq_service; + + dm_free(irq_service); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.h b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.h new file mode 100644 index 000000000000..420c96e8fefc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCE120_H__ +#define __DAL_IRQ_SERVICE_DCE120_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dce120_create( + struct irq_service_init_data *init_data); + +#endif -- GitLab From b8fdfcc6a92cd1defa770eb75607d579ad9e2e4e Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 14:36:02 -0500 Subject: [PATCH 0316/2898] drm/amd/display: Add DCE12 core support Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce120/dce120_hw_sequencer.c | 197 +++ .../display/dc/dce120/dce120_hw_sequencer.h | 36 + .../drm/amd/display/dc/dce120/dce120_ipp.c | 58 + .../drm/amd/display/dc/dce120/dce120_ipp.h | 62 + .../amd/display/dc/dce120/dce120_ipp_cursor.c | 202 +++ .../amd/display/dc/dce120/dce120_ipp_gamma.c | 167 +++ .../amd/display/dc/dce120/dce120_mem_input.c | 340 +++++ .../amd/display/dc/dce120/dce120_mem_input.h | 37 + .../amd/display/dc/dce120/dce120_resource.c | 1099 ++++++++++++++++ .../amd/display/dc/dce120/dce120_resource.h | 39 + .../dc/dce120/dce120_timing_generator.c | 1109 +++++++++++++++++ .../dc/dce120/dce120_timing_generator.h | 41 + 12 files changed, 3387 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c new file mode 100644 index 000000000000..f5ffd8f6ed3b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -0,0 +1,197 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "dce120_hw_sequencer.h" + +#include "dce110/dce110_hw_sequencer.h" + +/* include DCE12.0 register header files */ +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" +#include "reg_helper.h" + +struct dce120_hw_seq_reg_offsets { + uint32_t crtc; +}; + +static const struct dce120_hw_seq_reg_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +}, +{ + .crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC0_CRTC_GSL_CONTROL), +} +}; + +#define HW_REG_CRTC(reg, id)\ + (reg + reg_offsets[id].crtc) + +#define CNTL_ID(controller_id)\ + controller_id +/******************************************************************************* + * Private definitions + ******************************************************************************/ +#if 0 +static void dce120_init_pte(struct dc_context *ctx, uint8_t controller_id) +{ + uint32_t addr; + uint32_t value = 0; + uint32_t chunk_int = 0; + uint32_t chunk_mul = 0; +/* + addr = mmDCP0_DVMM_PTE_CONTROL + controller_id * + (mmDCP1_DVMM_PTE_CONTROL- mmDCP0_DVMM_PTE_CONTROL); + + value = dm_read_reg(ctx, addr); + + set_reg_field_value( + value, 0, DCP, controller_id, + DVMM_PTE_CONTROL, + DVMM_USE_SINGLE_PTE); + + set_reg_field_value_soc15( + value, 1, DCP, controller_id, + DVMM_PTE_CONTROL, + DVMM_PTE_BUFFER_MODE0); + + set_reg_field_value_soc15( + value, 1, DCP, controller_id, + DVMM_PTE_CONTROL, + DVMM_PTE_BUFFER_MODE1); + + dm_write_reg(ctx, addr, value);*/ + + addr = mmDVMM_PTE_REQ; + value = dm_read_reg(ctx, addr); + + chunk_int = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + chunk_mul = get_reg_field_value( + value, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + if (chunk_int != 0x4 || chunk_mul != 0x4) { + + set_reg_field_value( + value, + 255, + DVMM_PTE_REQ, + MAX_PTEREQ_TO_ISSUE); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_INT); + + set_reg_field_value( + value, + 4, + DVMM_PTE_REQ, + HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER); + + dm_write_reg(ctx, addr, value); + } +} +#endif + +static bool dce120_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + /* disable for bringup */ +#if 0 + enum bp_result bp_result = BP_RESULT_OK; + enum bp_pipe_control_action cntl; + struct dc_context *ctx = dc->ctx; + + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + return true; + + if (power_gating == PIPE_GATING_CONTROL_INIT) + cntl = ASIC_PIPE_INIT; + else if (power_gating == PIPE_GATING_CONTROL_ENABLE) + cntl = ASIC_PIPE_ENABLE; + else + cntl = ASIC_PIPE_DISABLE; + + if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0) { + + bp_result = dcb->funcs->enable_disp_power_gating( + dcb, controller_id + 1, cntl); + + /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2 + * by default when command table is called + */ + dm_write_reg(ctx, + HW_REG_CRTC(mmCRTC0_CRTC_MASTER_UPDATE_MODE, controller_id), + 0); + } + + if (power_gating != PIPE_GATING_CONTROL_ENABLE) + dce120_init_pte(ctx, controller_id); + + if (bp_result == BP_RESULT_OK) + return true; + else + return false; +#endif + return false; +} + +bool dce120_hw_sequencer_construct(struct core_dc *dc) +{ + /* All registers used by dce11.2 match those in dce11 in offset and + * structure + */ + dce110_hw_sequencer_construct(dc); + dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h new file mode 100644 index 000000000000..3402413c7156 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h @@ -0,0 +1,36 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE120_H__ +#define __DC_HWSS_DCE120_H__ + +#include "core_types.h" + +struct core_dc; + +bool dce120_hw_sequencer_construct(struct core_dc *dc); + +#endif /* __DC_HWSS_DCE112_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c new file mode 100644 index 000000000000..f4505690e01a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c @@ -0,0 +1,58 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "dce120_ipp.h" + +static const struct ipp_funcs funcs = { + .ipp_cursor_set_attributes = dce120_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce120_ipp_cursor_set_position, + .ipp_program_prescale = dce120_ipp_program_prescale, + .ipp_program_input_lut = dce120_ipp_program_input_lut, + .ipp_set_degamma = dce120_ipp_set_degamma, +}; + +bool dce120_ipp_construct( + struct dce110_ipp *ipp, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + if (!dce110_ipp_construct(ipp, ctx, inst, offset)) { + ASSERT_CRITICAL(false); + return false; + } + + ipp->base.funcs = &funcs; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h new file mode 100644 index 000000000000..4b326bcb4600 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h @@ -0,0 +1,62 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_IPP_DCE120_H__ +#define __DC_IPP_DCE120_H__ + +#include "ipp.h" +#include "../dce110/dce110_ipp.h" + + +bool dce120_ipp_construct( + struct dce110_ipp *ipp, + struct dc_context *ctx, + enum controller_id id, + const struct dce110_ipp_reg_offsets *offset); + +/* CURSOR RELATED */ +void dce120_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param); + +bool dce120_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes); + +/* DEGAMMA RELATED */ +bool dce120_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode); + +void dce120_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params); + +void dce120_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma); + +#endif /*__DC_IPP_DCE120_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c new file mode 100644 index 000000000000..d520b5d7aa81 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c @@ -0,0 +1,202 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "../dce110/dce110_ipp.h" + + +#define DCP_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) + +#define DCP_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) + +#define DCP_REG_UPDATE(reg, field, val) \ + DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define DCP_REG_SET(reg, field, val) \ + DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ + DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +/* TODO: DAL3 does not implement cursor memory control + * MCIF_MEM_CONTROL, DMIF_CURSOR_MEM_CONTROL + */ +static void lock( + struct dce110_ipp *ipp110, bool lock) +{ + DCP_REG_UPDATE(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, lock); +} + +static bool program_control( + struct dce110_ipp *ipp110, + enum dc_cursor_color_format color_format, + bool enable_magnification, + bool inverse_transparent_clamping) +{ + uint32_t mode = 0; + + switch (color_format) { + case CURSOR_MODE_MONO: + mode = 0; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + mode = 1; + break; + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + mode = 2; + break; + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + mode = 3; + break; + default: + return false; + } + + DCP_REG_UPDATE_3( + DCP0_CUR_CONTROL, + CURSOR_MODE, mode, + CURSOR_2X_MAGNIFY, enable_magnification, + CUR_INV_TRANS_CLAMP, inverse_transparent_clamping); + + if (color_format == CURSOR_MODE_MONO) { + DCP_REG_SET_3( + DCP0_CUR_COLOR1, + CUR_COLOR1_BLUE, 0, + CUR_COLOR1_GREEN, 0, + CUR_COLOR1_RED, 0); + + DCP_REG_SET_3( + DCP0_CUR_COLOR2, + CUR_COLOR2_BLUE, 0xff, + CUR_COLOR2_GREEN, 0xff, + CUR_COLOR2_RED, 0xff); + } + return true; +} + +static void program_address( + struct dce110_ipp *ipp110, + PHYSICAL_ADDRESS_LOC address) +{ + /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor + * surface base address in byte. It is 4K byte aligned. + * The correct way to program cursor surface address is to first write + * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS + */ + + DCP_REG_SET( + DCP0_CUR_SURFACE_ADDRESS_HIGH, + CURSOR_SURFACE_ADDRESS_HIGH, address.high_part); + + DCP_REG_SET( + DCP0_CUR_SURFACE_ADDRESS, + CURSOR_SURFACE_ADDRESS, address.low_part); +} + +void dce120_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* lock cursor registers */ + lock(ipp110, true); + + /* Flag passed in structure differentiates cursor enable/disable. */ + /* Update if it differs from cached state. */ + DCP_REG_UPDATE(DCP0_CUR_CONTROL, CURSOR_EN, position->enable); + + DCP_REG_SET_2( + DCP0_CUR_POSITION, + CURSOR_X_POSITION, position->x, + CURSOR_Y_POSITION, position->y); + + if (position->hot_spot_enable) + DCP_REG_SET_2( + DCP0_CUR_HOT_SPOT, + CURSOR_HOT_SPOT_X, position->x_hotspot, + CURSOR_HOT_SPOT_Y, position->y_hotspot); + + /* unlock cursor registers */ + lock(ipp110, false); +} + +bool dce120_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + /* Lock cursor registers */ + lock(ipp110, true); + + /* Program cursor control */ + program_control( + ipp110, + attributes->color_format, + attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, + attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); + + /* Program hot spot coordinates */ + DCP_REG_SET_2( + DCP0_CUR_HOT_SPOT, + CURSOR_HOT_SPOT_X, attributes->x_hot, + CURSOR_HOT_SPOT_Y, attributes->y_hot); + + /* + * Program cursor size -- NOTE: HW spec specifies that HW register + * stores size as (height - 1, width - 1) + */ + DCP_REG_SET_2( + DCP0_CUR_SIZE, + CURSOR_WIDTH, attributes->width-1, + CURSOR_HEIGHT, attributes->height-1); + + /* Program cursor surface address */ + program_address(ipp110, attributes->address); + + /* Unlock Cursor registers. */ + lock(ipp110, false); + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c new file mode 100644 index 000000000000..7aa5a49c01e2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c @@ -0,0 +1,167 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/logger_interface.h" +#include "include/fixed31_32.h" +#include "basics/conversion.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "../dce110/dce110_ipp.h" + +#define DCP_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) + +#define DCP_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) + +#define DCP_REG_UPDATE(reg, field, val) \ + DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define DCP_REG_SET(reg, field, val) \ + DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ + DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + +bool dce120_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; + + ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || + mode == IPP_DEGAMMA_MODE_HW_sRGB); + + DCP_REG_SET_3( + DCP0_DEGAMMA_CONTROL, + GRPH_DEGAMMA_MODE, degamma_type, + CURSOR_DEGAMMA_MODE, degamma_type, + CURSOR2_DEGAMMA_MODE, degamma_type); + + return true; +} + +void dce120_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params) +{ + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* set to bypass mode first before change */ + DCP_REG_UPDATE( + DCP0_PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, + 1); + + DCP_REG_SET_2( + DCP0_PRESCALE_VALUES_GRPH_R, + GRPH_PRESCALE_SCALE_R, params->scale, + GRPH_PRESCALE_BIAS_R, params->bias); + + DCP_REG_SET_2( + DCP0_PRESCALE_VALUES_GRPH_G, + GRPH_PRESCALE_SCALE_G, params->scale, + GRPH_PRESCALE_BIAS_G, params->bias); + + DCP_REG_SET_2( + DCP0_PRESCALE_VALUES_GRPH_B, + GRPH_PRESCALE_SCALE_B, params->scale, + GRPH_PRESCALE_BIAS_B, params->bias); + + if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + DCP_REG_UPDATE(DCP0_PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, 0); + + /* If prescale is in use, then legacy lut should be bypassed */ + DCP_REG_UPDATE(DCP0_INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE, 1); + } +} + +static void dce120_helper_select_lut(struct dce110_ipp *ipp110) +{ + /* enable all */ + DCP_REG_SET( + DCP0_DC_LUT_WRITE_EN_MASK, + DC_LUT_WRITE_EN_MASK, + 0x7); + + /* 256 entry mode */ + DCP_REG_UPDATE(DCP0_DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); + + /* LUT-256, unsigned, integer, new u0.12 format */ + DCP_REG_SET_3( + DCP0_DC_LUT_CONTROL, + DC_LUT_DATA_R_FORMAT, 3, + DC_LUT_DATA_G_FORMAT, 3, + DC_LUT_DATA_B_FORMAT, 3); + + /* start from index 0 */ + DCP_REG_SET( + DCP0_DC_LUT_RW_INDEX, + DC_LUT_RW_INDEX, + 0); +} + +void dce120_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + + /* power on LUT memory */ + DCP_REG_SET(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1); + + dce120_helper_select_lut(ipp110); + + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]); + DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]); + DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]); + } + + /* power off LUT memory */ + DCP_REG_SET(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0); + + /* bypass prescale, enable legacy LUT */ + DCP_REG_UPDATE(DCP0_PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); + DCP_REG_UPDATE(DCP0_INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); +} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c new file mode 100644 index 000000000000..c0677211bd93 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c @@ -0,0 +1,340 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dce120_mem_input.h" + + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#define GENERAL_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(mem_input110->base.ctx, 0, reg_name, n, __VA_ARGS__) + +#define GENERAL_REG_UPDATE(reg, field, val) \ + GENERAL_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define GENERAL_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + GENERAL_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + + + +#define DCP_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.dcp, reg_name, n, __VA_ARGS__) + +#define DCP_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.dcp, reg_name, n, __VA_ARGS__) + +#define DCP_REG_UPDATE(reg, field, val) \ + DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define DCP_REG_SET(reg, field, val) \ + DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ + DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + + +#define DMIF_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.dmif, reg_name, n, __VA_ARGS__) + +#define DMIF_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.dmif, reg_name, n, __VA_ARGS__) + +#define DMIF_REG_UPDATE(reg, field, val) \ + DMIF_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define DMIF_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + DMIF_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DMIF_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + DMIF_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define DMIF_REG_SET(reg, field, val) \ + DMIF_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define DMIF_REG_SET_2(reg, field1, val1, field2, val2) \ + DMIF_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define DMIF_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + DMIF_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + + +#define PIPE_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.pipe, reg_name, n, __VA_ARGS__) + +#define PIPE_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.pipe, reg_name, n, __VA_ARGS__) + +#define PIPE_REG_UPDATE(reg, field, val) \ + PIPE_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define PIPE_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + PIPE_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define PIPE_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + PIPE_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define PIPE_REG_SET(reg, field, val) \ + PIPE_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define PIPE_REG_SET_2(reg, field1, val1, field2, val2) \ + PIPE_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define PIPE_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + PIPE_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + + +static void program_sec_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t temp; + + /*high register MUST be programmed first*/ + temp = address.high_part & + DCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; + + DCP_REG_SET( + DCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + temp); + + temp = address.low_part >> + DCP0_GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; + + DCP_REG_SET_2( + DCP0_GRPH_SECONDARY_SURFACE_ADDRESS, + GRPH_SECONDARY_SURFACE_ADDRESS, temp, + GRPH_SECONDARY_DFQ_ENABLE, 0); +} + +static void program_pri_addr( + struct dce110_mem_input *mem_input110, + PHYSICAL_ADDRESS_LOC address) +{ + uint32_t temp; + + /*high register MUST be programmed first*/ + temp = address.high_part & + DCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; + + DCP_REG_SET( + DCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + temp); + + temp = address.low_part >> + DCP0_GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; + + DCP_REG_SET( + DCP0_GRPH_PRIMARY_SURFACE_ADDRESS, + GRPH_PRIMARY_SURFACE_ADDRESS, + temp); +} + + +static bool mem_input_is_flip_pending(struct mem_input *mem_input) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + uint32_t value; + + value = dm_read_reg_soc15(mem_input110->base.ctx, + mmDCP0_GRPH_UPDATE, mem_input110->offsets.dcp); + + if (get_reg_field_value(value, DCP0_GRPH_UPDATE, + GRPH_SURFACE_UPDATE_PENDING)) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +static bool mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + + /* TODO: Figure out if two modes are needed: + * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 + * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 + */ + DCP_REG_UPDATE(DCP0_GRPH_UPDATE, + GRPH_UPDATE_LOCK, 1); + + if (flip_immediate) { + DCP_REG_UPDATE_2( + DCP0_GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, 1); + } else { + DCP_REG_UPDATE_2( + DCP0_GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0); + } + + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) + break; + program_pri_addr(mem_input110, address->grph.addr); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0 + || address->grph_stereo.right_addr.quad_part == 0) + break; + program_pri_addr(mem_input110, address->grph_stereo.left_addr); + program_sec_addr(mem_input110, address->grph_stereo.right_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + break; + } + + mem_input->request_address = *address; + + if (flip_immediate) + mem_input->current_address = *address; + + DCP_REG_UPDATE(DCP0_GRPH_UPDATE, + GRPH_UPDATE_LOCK, 0); + + return true; +} + +static void mem_input_update_dchub(struct mem_input *mi, + struct dchub_init_data *dh_data) +{ + struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mi); + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + GENERAL_REG_UPDATE_2( + DCHUB_FB_LOCATION, + FB_TOP, 0, + FB_BASE, 0x0FFFF); + + GENERAL_REG_UPDATE( + DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + GENERAL_REG_UPDATE( + DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + GENERAL_REG_UPDATE( + DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + GENERAL_REG_UPDATE( + DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + GENERAL_REG_UPDATE( + DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + GENERAL_REG_UPDATE( + DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + GENERAL_REG_UPDATE( + DCHUB_AGP_BASE, + AGP_BASE, 0); + + GENERAL_REG_UPDATE( + DCHUB_AGP_BOT, + AGP_BOT, 0x03FFFF); + + GENERAL_REG_UPDATE( + DCHUB_AGP_TOP, + AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + +static struct mem_input_funcs dce120_mem_input_funcs = { + .mem_input_program_display_marks = dce_mem_input_program_display_marks, + .allocate_mem_input = dce_mem_input_allocate_dmif, + .free_mem_input = dce_mem_input_free_dmif, + .mem_input_program_surface_flip_and_addr = + mem_input_program_surface_flip_and_addr, + .mem_input_program_pte_vm = dce_mem_input_program_pte_vm, + .mem_input_program_surface_config = + dce_mem_input_program_surface_config, + .mem_input_is_flip_pending = mem_input_is_flip_pending, + .mem_input_update_dchub = mem_input_update_dchub +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dce120_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets) +{ + /* supported stutter method + * STUTTER_MODE_ENHANCED + * STUTTER_MODE_QUAD_DMIF_BUFFER + * STUTTER_MODE_WATERMARK_NBP_STATE + */ + + if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) + return false; + + mem_input110->base.funcs = &dce120_mem_input_funcs; + mem_input110->offsets = *offsets; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h new file mode 100644 index 000000000000..379fd72155b9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h @@ -0,0 +1,37 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCE120_H__ +#define __DC_MEM_INPUT_DCE120_H__ + +#include "mem_input.h" +#include "dce110/dce110_mem_input.h" + +bool dce120_mem_input_construct( + struct dce110_mem_input *mem_input110, + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offsets); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c new file mode 100644 index 000000000000..9a1984b36592 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -0,0 +1,1099 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc.cls +* + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + + +#include "stream_encoder.h" +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dce120_resource.h" +#include "dce112/dce112_resource.h" + +#include "dce110/dce110_resource.h" +#include "../virtual/virtual_stream_encoder.h" +#include "dce120_timing_generator.h" +#include "irq/dce120/irq_service_dce120.h" +#include "dce/dce_opp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_clocks.h" +#include "dce120_ipp.h" +#include "dce110/dce110_mem_input.h" +#include "dce120/dce120_mem_input.h" + +#include "dce110/dce110_hw_sequencer.h" +#include "dce120/dce120_hw_sequencer.h" +#include "dce/dce_transform.h" + +#include "dce/dce_audio.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_hwseq.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" +#include "vega10/NBIO/nbio_6_1_offset.h" +#include "reg_helper.h" + +#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f + #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f + #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f + #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f + #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f + #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f + #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f + #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 +#endif + +enum dce120_clk_src_array_id { + DCE120_CLK_SRC_PLL0, + DCE120_CLK_SRC_PLL1, + DCE120_CLK_SRC_PLL2, + DCE120_CLK_SRC_PLL3, + DCE120_CLK_SRC_PLL4, + DCE120_CLK_SRC_PLL5, + + DCE120_CLK_SRC_TOTAL +}; + +static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + } +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define NBIO_BASE_INNER(seg) \ + NBIF_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + + +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE_BASE() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE120_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE120(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE120(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_120_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_120(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_120(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(index, id)\ +[index] = {\ + CS_COMMON_REG_LIST_DCE_112(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + +struct output_pixel_processor *dce120_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + dm_alloc(sizeof(struct dce110_opp)); + + if (!opp) + return NULL; + + if (dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) + return &opp->base; + + BREAK_TO_DEBUGGER(); + dm_free(opp); + return NULL; +} + +static const struct dce110_ipp_reg_offsets dce120_ipp_reg_offsets[] = { + { + .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL), + }, + { + .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL), + } +}; + +static const struct dce110_mem_input_reg_offsets dce120_mi_reg_offsets[] = { + { + .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + }, + { + .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), + .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL + - mmPIPE0_DMIF_BUFFER_CONTROL), + } +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 3, + .num_audio = 7, + .num_stream_encoder = 6, + .num_pll = 6, +}; + +static const struct dc_debug debug_defaults = { + .disable_clock_gate = true, +}; + +struct clock_source *dce120_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce120_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + + +bool dce120_hw_sequencer_create(struct core_dc *dc) +{ + /* All registers used by dce11.2 match those in dce11 in offset and + * structure + */ + dce120_hw_sequencer_construct(dc); + + /*TODO Move to separate file and Override what is needed */ + + return true; +} + +static struct timing_generator *dce120_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + dm_alloc(sizeof(struct dce110_timing_generator)); + + if (!tg110) + return NULL; + + if (dce120_timing_generator_construct(tg110, ctx, instance, offsets)) + return &tg110->base; + + BREAK_TO_DEBUGGER(); + dm_free(tg110); + return NULL; +} + +static void dce120_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE110_IPP(*ipp)); + *ipp = NULL; +} + +static void dce120_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static void destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce120_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce120_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) + dce120_clock_source_destroy( + &pool->base.clock_sources[i]); + } + + if (pool->base.dp_clock_source != NULL) + dce120_clock_source_destroy(&pool->base.dp_clock_source); + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + /* TODO: Registers are missing */ + /*REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/ +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .ycbcr420_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + +struct link_encoder *dce120_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +static struct input_pixel_processor *dce120_ipp_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_ipp_reg_offsets *offset) +{ + struct dce110_ipp *ipp = dm_alloc(sizeof(struct dce110_ipp)); + + if (!ipp) + return NULL; + + if (dce120_ipp_construct(ipp, ctx, inst, offset)) + return &ipp->base; + + BREAK_TO_DEBUGGER(); + dm_free(ipp); + return NULL; +} + +static struct stream_encoder *dce120_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE112_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE12_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE12_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce120_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce120_stream_encoder_create, + .create_hwseq = dce120_hwseq_create, +}; + +#define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) } +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE12_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE12_MASK_SH_LIST(_MASK) +}; + +static struct mem_input *dce120_mem_input_create( + struct dc_context *ctx, + uint32_t inst, + const struct dce110_mem_input_reg_offsets *offset) +{ + struct dce110_mem_input *mem_input110 = + dm_alloc(sizeof(struct dce110_mem_input)); + + if (!mem_input110) + return NULL; + + if (dce120_mem_input_construct(mem_input110, ctx, inst, offset)) { + struct mem_input *mi = &mem_input110->base; + + mi->regs = &mi_regs[inst]; + mi->shifts = &mi_shifts; + mi->masks = &mi_masks; + return mi; + } + + BREAK_TO_DEBUGGER(); + dm_free(mem_input110); + return NULL; +} + +static struct transform *dce120_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + dm_alloc(sizeof(struct dce_transform)); + + if (!transform) + return NULL; + + if (dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask)) { + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static void dce120_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + destruct(dce110_pool); + dm_free(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce120_res_pool_funcs = { + .destroy = dce120_destroy_resource_pool, + .link_enc_create = dce120_link_encoder_create, + .validate_with_context = dce112_validate_with_context, + .validate_guaranteed = dce112_validate_guaranteed, + .validate_bandwidth = dce112_validate_bandwidth +}; + +static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +{ + struct dm_pp_clock_levels_with_latency eng_clks = {0}; + struct dm_pp_clock_levels_with_latency mem_clks = {0}; + struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; + int i; + unsigned int clk; + unsigned int latency; + + /*do system clock*/ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &eng_clks) || eng_clks.num_levels == 0) { + + eng_clks.num_levels = 8; + clk = 300000; + + for (i = 0; i < eng_clks.num_levels; i++) { + eng_clks.data[i].clocks_in_khz = clk; + clk += 100000; + } + } + + /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ + dc->bw_vbios.high_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); + dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); + dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); + dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); + dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); + dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); + dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); + dc->bw_vbios.low_sclk = bw_frc_to_fixed( + eng_clks.data[0].clocks_in_khz, 1000); + + /*do memory clock*/ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &mem_clks) || mem_clks.num_levels == 0) { + + mem_clks.num_levels = 3; + clk = 250000; + latency = 45; + + for (i = 0; i < eng_clks.num_levels; i++) { + mem_clks.data[i].clocks_in_khz = clk; + mem_clks.data[i].latency_in_us = latency; + clk += 500000; + latency -= 5; + } + + } + + /* we don't need to call PPLIB for validation clock since they + * also give us the highest sclk and highest mclk (UMA clock). + * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): + * YCLK = UMACLK*m_memoryTypeMultiplier + */ + dc->bw_vbios.low_yclk = bw_frc_to_fixed( + mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); + dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, + 1000); + dc->bw_vbios.high_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, + 1000); + + /* Now notify PPLib/SMU about which Watermarks sets they should select + * depending on DPM state they are in. And update BW MGR GFX Engine and + * Memory clock member variables for Watermarks calculations for each + * Watermark Set + */ + clk_ranges.num_wm_sets = 4; + clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[0].wm_min_memg_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[1].wm_min_memg_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[2].wm_min_memg_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; + + clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[3].wm_min_memg_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); +} + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce120_res_pool_funcs; + + /* TODO: Fill more data from GreenlandAsicCapability.cpp */ + pool->base.pipe_count = 6; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 100; + dc->public.caps.max_cursor_size = 128; + dc->public.debug = debug_defaults; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCE120_CLK_SRC_PLL0] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL1] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL2] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL3] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL4] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL5] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto clk_src_create_fail; + } + } + + pool->base.display_clock = dce120_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto disp_clk_create_fail; + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + #if defined(CONFIG_DRM_AMD_DC_DCE12_0) + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce120_create(&init_data); + if (!pool->base.irqs) + goto irqs_create_fail; + #endif + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = + dce120_timing_generator_create( + ctx, + i, + &dce120_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto controller_create_fail; + } + + pool->base.mis[i] = dce120_mem_input_create(ctx, + i, &dce120_mi_reg_offsets[i]); + + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto controller_create_fail; + } + + pool->base.ipps[i] = dce120_ipp_create(ctx, i, + &dce120_ipp_reg_offsets[i]); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto controller_create_fail; + } + + pool->base.transforms[i] = dce120_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce120_opp_create( + ctx, + i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + } + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce120_hw_sequencer_create(dc)) + goto controller_create_fail; + + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +irqs_create_fail: +controller_create_fail: +disp_clk_create_fail: +clk_src_create_fail: +res_create_fail: + + destruct(pool); + + return false; +} + +struct resource_pool *dce120_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h new file mode 100644 index 000000000000..038c78dcc247 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h @@ -0,0 +1,39 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE120_H__ +#define __DC_RESOURCE_DCE120_H__ + +#include "core_types.h" + +struct core_dc; +struct resource_pool; + +struct resource_pool *dce120_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +#endif /* __DC_RESOURCE_DCE120_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c new file mode 100644 index 000000000000..d7e787b591a0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -0,0 +1,1109 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "vega10/DC/dce_12_0_offset.h" +#include "vega10/DC/dce_12_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "dc_types.h" +#include "dc_bios_types.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "dce120_timing_generator.h" + +#include "timing_generator.h" + +#define CRTC_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__) + +#define CRTC_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__) + +#define CRTC_REG_UPDATE(reg, field, val) \ + CRTC_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define CRTC_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + CRTC_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define CRTC_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +#define CRTC_REG_UPDATE_4(reg, field1, val1, field2, val2, field3, val3, field4, val4) \ + CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4) + +#define CRTC_REG_UPDATE_5(reg, field1, val1, field2, val2, field3, val3, field4, val4, field5, val5) \ + CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4, FD(reg##__##field5), val5) + +#define CRTC_REG_SET(reg, field, val) \ + CRTC_REG_SET_N(reg, 1, FD(reg##__##field), val) + +#define CRTC_REG_SET_2(reg, field1, val1, field2, val2) \ + CRTC_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define CRTC_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ + CRTC_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + +/** + ***************************************************************************** + * Function: is_in_vertical_blank + * + * @brief + * check the current status of CRTC to check if we are in Vertical Blank + * regioneased" state + * + * @return + * true if currently in blank region, false otherwise + * + ***************************************************************************** + */ +static bool dce120_timing_generator_is_in_vertical_blank( + struct timing_generator *tg) +{ + uint32_t field = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS, + tg110->offsets.crtc); + + field = get_reg_field_value(value, CRTC0_CRTC_STATUS, CRTC_V_BLANK); + return field == 1; +} + + +/* determine if given timing can be supported by TG */ +bool dce120_timing_generator_validate_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *timing, + enum signal_type signal) +{ + uint32_t interlace_factor = timing->flags.INTERLACE ? 2 : 1; + uint32_t v_blank = + (timing->v_total - timing->v_addressable - + timing->v_border_top - timing->v_border_bottom) * + interlace_factor; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + if (!dce110_timing_generator_validate_timing( + tg, + timing, + signal)) + return false; + + + if (v_blank < tg110->min_v_blank || + timing->h_sync_width < tg110->min_h_sync_width || + timing->v_sync_width < tg110->min_v_sync_width) + return false; + + return true; +} + +bool dce120_tg_validate_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + return dce120_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE); +} + +/******** HW programming ************/ +/* Disable/Enable Timing Generator */ +bool dce120_timing_generator_enable_crtc(struct timing_generator *tg) +{ + enum bp_result result; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + /* Set MASTER_UPDATE_MODE to 0 + * This is needed for DRR, and also suggested to be default value by Syed.*/ + + CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_MODE, + MASTER_UPDATE_MODE, 0); + + CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_LOCK, + UNDERFLOW_UPDATE_LOCK, 0); + + /* TODO API for AtomFirmware didn't change*/ + result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true); + + return result == BP_RESULT_OK; +} + +void dce120_timing_generator_set_early_control( + struct timing_generator *tg, + uint32_t early_cntl) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE(CRTC0_CRTC_CONTROL, + CRTC_HBLANK_EARLY_CONTROL, early_cntl); +} + +/**************** TG current status ******************/ + +/* return the current frame counter. Used by Linux kernel DRM */ +uint32_t dce120_timing_generator_get_vblank_counter( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS_FRAME_COUNT, + tg110->offsets.crtc); + uint32_t field = get_reg_field_value( + value, CRTC0_CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT); + + return field; +} + +/* Get current H and V position */ +void dce120_timing_generator_get_crtc_positions( + struct timing_generator *tg, + int32_t *h_position, + int32_t *v_position) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS_POSITION, + tg110->offsets.crtc); + + *h_position = get_reg_field_value( + value, CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); + + *v_position = get_reg_field_value( + value, CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT); +} + +/* wait until TG is in beginning of vertical blank region */ +void dce120_timing_generator_wait_for_vblank(struct timing_generator *tg) +{ + /* We want to catch beginning of VBlank here, so if the first try are + * in VBlank, we might be very close to Active, in this case wait for + * another frame + */ + while (dce120_timing_generator_is_in_vertical_blank(tg)) { + if (!tg->funcs->is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } + + while (!dce120_timing_generator_is_in_vertical_blank(tg)) { + if (!tg->funcs->is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/* wait until TG is in beginning of active region */ +void dce120_timing_generator_wait_for_vactive(struct timing_generator *tg) +{ + while (dce120_timing_generator_is_in_vertical_blank(tg)) { + if (!tg->funcs->is_counter_moving(tg)) { + /* error - no point to wait if counter is not moving */ + break; + } + } +} + +/*********** Timing Generator Synchronization routines ****/ + +/* Setups Global Swap Lock group, TimingServer or TimingClient*/ +void dce120_timing_generator_setup_global_swap_lock( + struct timing_generator *tg, + const struct dcp_gsl_params *gsl_params) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value_crtc_vtotal = + dm_read_reg_soc15(tg->ctx, + mmCRTC0_CRTC_V_TOTAL, + tg110->offsets.crtc); + /* Checkpoint relative to end of frame */ + uint32_t check_point = + get_reg_field_value(value_crtc_vtotal, + CRTC0_CRTC_V_TOTAL, + CRTC_V_TOTAL); + + + dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_GSL_WINDOW, tg110->offsets.crtc, 0); + + CRTC_REG_UPDATE_N(DCP0_DCP_GSL_CONTROL, 6, + /* This pipe will belong to GSL Group zero. */ + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 1, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), gsl_params->gsl_master == tg->inst, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY, + /* Keep signal low (pending high) during 6 lines. + * Also defines minimum interval before re-checking signal. */ + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY, + /* DCP_GSL_PURPOSE_SURFACE_FLIP */ + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 1); + + CRTC_REG_SET_2( + CRTC0_CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM, check_point - FLIP_READY_BACK_LOOKUP, + CRTC_GSL_FORCE_DELAY, VFLIP_READY_DELAY); +} + +/* Clear all the register writes done by setup_global_swap_lock */ +void dce120_timing_generator_tear_down_global_swap_lock( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + /* Settig HW default values from reg specs */ + CRTC_REG_SET_N(DCP0_DCP_GSL_CONTROL, 6, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 0, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), 0, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY, + /* DCP_GSL_PURPOSE_SURFACE_FLIP */ + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0, + FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0); + + CRTC_REG_SET_2( + CRTC0_CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM, 0, + CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/ +} + +/* Reset slave controllers on master VSync */ +void dce120_timing_generator_enable_reset_trigger( + struct timing_generator *tg, + int source) +{ + enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t rising_edge = 0; + uint32_t falling_edge = 0; + /* Setup trigger edge */ + uint32_t pol_value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_V_SYNC_A_CNTL, + tg110->offsets.crtc); + + /* Register spec has reversed definition: + * 0 for positive, 1 for negative */ + if (get_reg_field_value(pol_value, + CRTC0_CRTC_V_SYNC_A_CNTL, + CRTC_V_SYNC_A_POL) == 0) { + rising_edge = 1; + } else { + falling_edge = 1; + } + + /* TODO What about other sources ?*/ + trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0; + + CRTC_REG_UPDATE_N(CRTC0_CRTC_TRIGB_CNTL, 7, + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT), trig_src_select, + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT), TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL), rising_edge, + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL), falling_edge, + /* send every signal */ + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT), 0, + /* no delay */ + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY), 0, + /* clear trigger status */ + FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR), 1); + + CRTC_REG_UPDATE_3( + CRTC0_CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE, 2, + CRTC_FORCE_COUNT_NOW_TRIG_SEL, 1, + CRTC_FORCE_COUNT_NOW_CLEAR, 1); +} + +/* disabling trigger-reset */ +void dce120_timing_generator_disable_reset_trigger( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE_2( + CRTC0_CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_MODE, 0, + CRTC_FORCE_COUNT_NOW_CLEAR, 1); + + CRTC_REG_UPDATE_3( + CRTC0_CRTC_TRIGB_CNTL, + CRTC_TRIGB_SOURCE_SELECT, TRIGGER_SOURCE_SELECT_LOGIC_ZERO, + CRTC_TRIGB_POLARITY_SELECT, TRIGGER_POLARITY_SELECT_LOGIC_ZERO, + /* clear trigger status */ + CRTC_TRIGB_CLEAR, 1); + +} + +/* Checks whether CRTC triggered reset occurred */ +bool dce120_timing_generator_did_triggered_reset_occur( + struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL, + tg110->offsets.crtc); + + return get_reg_field_value(value, + CRTC0_CRTC_FORCE_COUNT_NOW_CNTL, + CRTC_FORCE_COUNT_NOW_OCCURRED) != 0; +} + + +/******** Stuff to move to other virtual HW objects *****************/ +/* Move to enable accelerated mode */ +void dce120_timing_generator_disable_vga(struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t offset = 0; + uint32_t value = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + switch (tg110->controller_id) { + case CONTROLLER_ID_D0: + addr = mmD1VGA_CONTROL; + offset = 0; + break; + case CONTROLLER_ID_D1: + addr = mmD2VGA_CONTROL; + offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D2: + addr = mmD3VGA_CONTROL; + offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D3: + addr = mmD4VGA_CONTROL; + offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D4: + addr = mmD1VGA_CONTROL; + offset = mmD1VGA_CONTROL - mmD1VGA_CONTROL; + break; + case CONTROLLER_ID_D5: + addr = mmD6VGA_CONTROL; + offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL; + break; + default: + break; + } + + value = dm_read_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset); + + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE); + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT); + set_reg_field_value( + value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT); + set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN); + + dm_write_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset, value); +} +/* TODO: Should we move it to transform */ +/* Fully program CRTC timing in timing generator */ +void dce120_timing_generator_program_blanking( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t tmp1 = 0; + uint32_t tmp2 = 0; + uint32_t vsync_offset = timing->v_border_bottom + + timing->v_front_porch; + uint32_t v_sync_start = timing->v_addressable + vsync_offset; + + uint32_t hsync_offset = timing->h_border_right + + timing->h_front_porch; + uint32_t h_sync_start = timing->h_addressable + hsync_offset; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE( + CRTC0_CRTC_H_TOTAL, + CRTC_H_TOTAL, + timing->h_total - 1); + + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL, + CRTC_V_TOTAL, + timing->v_total - 1); + + tmp1 = timing->h_total - + (h_sync_start + timing->h_border_left); + tmp2 = tmp1 + timing->h_addressable + + timing->h_border_left + timing->h_border_right; + + CRTC_REG_UPDATE_2( + CRTC0_CRTC_H_BLANK_START_END, + CRTC_H_BLANK_END, tmp1, + CRTC_H_BLANK_START, tmp2); + + tmp1 = timing->v_total - (v_sync_start + timing->v_border_top); + tmp2 = tmp1 + timing->v_addressable + timing->v_border_top + + timing->v_border_bottom; + + CRTC_REG_UPDATE_2( + CRTC0_CRTC_V_BLANK_START_END, + CRTC_V_BLANK_END, tmp1, + CRTC_V_BLANK_START, tmp2); +} + +/* TODO: Should we move it to opp? */ +/* Combine with below and move YUV/RGB color conversion to SW layer */ +void dce120_timing_generator_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE_3( + CRTC0_CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb, + CRTC_BLACK_COLOR_G_Y, black_color->color_g_y, + CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr); +} +/* Combine with above and move YUV/RGB color conversion to SW layer */ +void dce120_timing_generator_set_overscan_color_black( + struct timing_generator *tg, + const struct tg_color *color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = 0; + CRTC_REG_SET_3( + CRTC0_CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE, color->color_b_cb, + CRTC_OVERSCAN_COLOR_GREEN, color->color_g_y, + CRTC_OVERSCAN_COLOR_RED, color->color_r_cr); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_OVERSCAN_COLOR, + tg110->offsets.crtc); + + dm_write_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLACK_COLOR, + tg110->offsets.crtc, + value); + + /* This is desirable to have a constant DAC output voltage during the + * blank time that is higher than the 0 volt reference level that the + * DAC outputs when the NBLANK signal + * is asserted low, such as for output to an analog TV. */ + dm_write_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLANK_DATA_COLOR, + tg110->offsets.crtc, + value); + + /* TO DO we have to program EXT registers and we need to know LB DATA + * format because it is used when more 10 , i.e. 12 bits per color + * + * m_mmDxCRTC_OVERSCAN_COLOR_EXT + * m_mmDxCRTC_BLACK_COLOR_EXT + * m_mmDxCRTC_BLANK_DATA_COLOR_EXT + */ +} + +void dce120_timing_generator_set_drr( + struct timing_generator *tg, + const struct drr_params *params) +{ + + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN, params->vertical_total_min - 1); + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX, params->vertical_total_max - 1); + CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0); + CRTC_REG_UPDATE( + CRTC0_CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK, + 0x180); + + } else { + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN, 0); + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX, 0); + CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0, + FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0); + CRTC_REG_UPDATE( + CRTC0_CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK, + 0); + } +} + +uint32_t dce120_timing_generator_get_crtc_scanoutpos( + struct timing_generator *tg, + uint32_t *vbl, + uint32_t *position) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + *vbl = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_V_BLANK_START_END, + tg110->offsets.crtc); + + *position = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS_POSITION, + tg110->offsets.crtc); + + return 0; +} + +void dce120_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t v_sync_width_and_b_porch = + timing->v_total - timing->v_addressable - + timing->v_border_bottom - timing->v_front_porch; + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_START_LINE_CONTROL, + tg110->offsets.crtc); + + + if (enable) { + set_reg_field_value( + value, + 0, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 1, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + /* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency + * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines) + */ + if (v_sync_width_and_b_porch > 10) + set_reg_field_value( + value, + 10, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + else + set_reg_field_value( + value, + v_sync_width_and_b_porch, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + + dm_write_reg_soc15(tg->ctx, + mmCRTC0_CRTC_START_LINE_CONTROL, + tg110->offsets.crtc, + value); +} + +void dce120_tg_program_blank_color(struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = 0; + + CRTC_REG_UPDATE_3( + CRTC0_CRTC_BLACK_COLOR, + CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb, + CRTC_BLACK_COLOR_G_Y, black_color->color_g_y, + CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLACK_COLOR, + tg110->offsets.crtc); + dm_write_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLANK_DATA_COLOR, + tg110->offsets.crtc, + value); +} + +void dce120_tg_set_overscan_color(struct timing_generator *tg, + const struct tg_color *overscan_color) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_SET_3( + CRTC0_CRTC_OVERSCAN_COLOR, + CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb, + CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y, + CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr); +} + +void dce120_tg_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + if (use_vbios) + dce110_timing_generator_program_timing_generator(tg, timing); + else + dce120_timing_generator_program_blanking(tg, timing); +} + +bool dce120_tg_is_blanked(struct timing_generator *tg) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLANK_CONTROL, + tg110->offsets.crtc); + + if ( + get_reg_field_value( + value, + CRTC0_CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTC0_CRTC_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) + return true; + + return false; +} + +void dce120_tg_set_blank(struct timing_generator *tg, + bool enable_blanking) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_SET( + CRTC0_CRTC_DOUBLE_BUFFER_CONTROL, + CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 0); + + if (enable_blanking) { + CRTC_REG_SET( + CRTC0_CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN, 1); + + } else + dm_write_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_BLANK_CONTROL, + tg110->offsets.crtc, + 0); +} + +bool dce120_tg_validate_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing); + +void dce120_tg_wait_for_state(struct timing_generator *tg, + enum crtc_state state) +{ + switch (state) { + case CRTC_STATE_VBLANK: + dce120_timing_generator_wait_for_vblank(tg); + break; + + case CRTC_STATE_VACTIVE: + dce120_timing_generator_wait_for_vactive(tg); + break; + + default: + break; + } +} + +void dce120_tg_set_colors(struct timing_generator *tg, + const struct tg_color *blank_color, + const struct tg_color *overscan_color) +{ + if (blank_color != NULL) + dce120_tg_program_blank_color(tg, blank_color); + + if (overscan_color != NULL) + dce120_tg_set_overscan_color(tg, overscan_color); +} + +static void dce120_timing_generator_set_static_screen_control( + struct timing_generator *tg, + uint32_t value) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL, + CRTC_STATIC_SCREEN_EVENT_MASK, value, + CRTC_STATIC_SCREEN_FRAME_COUNT, 2); +} + +void dce120_timing_generator_set_test_pattern( + struct timing_generator *tg, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth) +{ + struct dc_context *ctx = tg->ctx; + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + enum test_pattern_color_format bit_depth; + enum test_pattern_dyn_range dyn_range; + enum test_pattern_mode mode; + /* color ramp generator mixes 16-bits color */ + uint32_t src_bpc = 16; + /* requested bpc */ + uint32_t dst_bpc; + uint32_t index; + /* RGB values of the color bars. + * Produce two RGB colors: RGB0 - white (all Fs) + * and RGB1 - black (all 0s) + * (three RGB components for two colors) + */ + uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, + 0x0000, 0x0000}; + /* dest color (converted to the specified color format) */ + uint16_t dst_color[6]; + uint32_t inc_base; + + /* translate to bit depth */ + switch (color_depth) { + case COLOR_DEPTH_666: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; + break; + case COLOR_DEPTH_888: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + case COLOR_DEPTH_101010: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; + break; + case COLOR_DEPTH_121212: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; + break; + default: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + } + + switch (test_pattern) { + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: + { + dyn_range = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? + TEST_PATTERN_DYN_RANGE_CEA : + TEST_PATTERN_DYN_RANGE_VESA); + mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; + + CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_VRES, 6, + CRTC_TEST_PATTERN_HRES, 6); + + CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN, 1, + CRTC_TEST_PATTERN_MODE, mode, + CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, + CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: + case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: + { + mode = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? + TEST_PATTERN_MODE_VERTICALBARS : + TEST_PATTERN_MODE_HORIZONTALBARS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* adjust color to the required colorFormat */ + for (index = 0; index < 6; index++) { + /* dst = 2^dstBpc * src / 2^srcBpc = src >> + * (srcBpc - dstBpc); + */ + dst_color[index] = + src_color[index] >> (src_bpc - dst_bpc); + /* CRTC_TEST_PATTERN_DATA has 16 bits, + * lowest 6 are hardwired to ZERO + * color bits should be left aligned aligned to MSB + * XXXXXXXXXX000000 for 10 bit, + * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 + */ + dst_color[index] <<= (16 - dst_bpc); + } + + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0); + + /* We have to write the mask before data, similar to pipeline. + * For example, for 8 bpc, if we want RGB0 to be magenta, + * and RGB1 to be cyan, + * we need to make 7 writes: + * MASK DATA + * 000001 00000000 00000000 set mask to R0 + * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 + * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 + * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 + * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 + * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 + * 100000 11111111 00000000 B1 255, 0xFF00 + * + * we will make a loop of 6 in which we prepare the mask, + * then write, then prepare the color for next write. + * first iteration will write mask only, + * but each next iteration color prepared in + * previous iteration will be written within new mask, + * the last component will written separately, + * mask is not changing between 6th and 7th write + * and color will be prepared by last iteration + */ + + /* write color, color values mask in CRTC_TEST_PATTERN_MASK + * is B1, G1, R1, B0, G0, R0 + */ + value = 0; + for (index = 0; index < 6; index++) { + /* prepare color mask, first write PATTERN_DATA + * will have all zeros + */ + set_reg_field_value( + value, + (1 << index), + CRTC0_CRTC_TEST_PATTERN_COLOR, + CRTC_TEST_PATTERN_MASK); + /* write color component */ + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value); + /* prepare next color component, + * will be written in the next iteration + */ + set_reg_field_value( + value, + dst_color[index], + CRTC0_CRTC_TEST_PATTERN_COLOR, + CRTC_TEST_PATTERN_DATA); + } + /* write last color component, + * it's been already prepared in the loop + */ + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value); + + /* enable test pattern */ + CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN, 1, + CRTC_TEST_PATTERN_MODE, mode, + CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0, + CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: + { + mode = (bit_depth == + TEST_PATTERN_COLOR_FORMAT_BPC_10 ? + TEST_PATTERN_MODE_DUALRAMP_RGB : + TEST_PATTERN_MODE_SINGLERAMP_RGB); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* increment for the first ramp for one color gradation + * 1 gradation for 6-bit color is 2^10 + * gradations in 16-bit color + */ + inc_base = (src_bpc - dst_bpc); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + { + CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0, inc_base, + CRTC_TEST_PATTERN_INC1, 0, + CRTC_TEST_PATTERN_HRES, 6, + CRTC_TEST_PATTERN_VRES, 6, + CRTC_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + { + CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0, inc_base, + CRTC_TEST_PATTERN_INC1, 0, + CRTC_TEST_PATTERN_HRES, 8, + CRTC_TEST_PATTERN_VRES, 6, + CRTC_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + { + CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS, + CRTC_TEST_PATTERN_INC0, inc_base, + CRTC_TEST_PATTERN_INC1, inc_base + 2, + CRTC_TEST_PATTERN_HRES, 8, + CRTC_TEST_PATTERN_VRES, 5, + CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); + } + break; + default: + break; + } + + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0); + + /* enable test pattern */ + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0); + + CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL, + CRTC_TEST_PATTERN_EN, 1, + CRTC_TEST_PATTERN_MODE, mode, + CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0, + CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: + { + value = 0; + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, value); + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value); + dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value); + } + break; + default: + break; + } +} + +static struct timing_generator_funcs dce120_tg_funcs = { + .validate_timing = dce120_tg_validate_timing, + .program_timing = dce120_tg_program_timing, + .enable_crtc = dce120_timing_generator_enable_crtc, + .disable_crtc = dce110_timing_generator_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = dce110_timing_generator_is_counter_moving, + /* never be called */ + .get_position = dce120_timing_generator_get_crtc_positions, + .get_frame_count = dce120_timing_generator_get_vblank_counter, + .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos, + .set_early_control = dce120_timing_generator_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = dce120_tg_wait_for_state, + .set_blank = dce120_tg_set_blank, + .is_blanked = dce120_tg_is_blanked, + /* never be called */ + .set_colors = dce120_tg_set_colors, + .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black, + .set_blank_color = dce120_timing_generator_program_blank_color, + .disable_vga = dce120_timing_generator_disable_vga, + .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur, + .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock, + .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger, + .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger, + .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock, + .enable_advanced_request = dce120_timing_generator_enable_advanced_request, + .set_drr = dce120_timing_generator_set_drr, + .set_static_screen_control = dce120_timing_generator_set_static_screen_control, + .set_test_pattern = dce120_timing_generator_set_test_pattern +}; + + +bool dce120_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + if (!tg110) + return false; + + tg110->controller_id = CONTROLLER_ID_D0 + instance; + tg110->base.inst = instance; + + tg110->offsets = *offsets; + + tg110->base.funcs = &dce120_tg_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + /*//CRTC requires a minimum HBLANK = 32 pixels and o + * Minimum HSYNC = 8 pixels*/ + tg110->min_h_blank = 32; + /*DCE12_CRTC_Block_ARch.doc*/ + tg110->min_h_front_porch = 0; + tg110->min_h_back_porch = 0; + + tg110->min_h_sync_width = 8; + tg110->min_v_sync_width = 1; + tg110->min_v_blank = 3; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h new file mode 100644 index 000000000000..243c0a3493da --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h @@ -0,0 +1,41 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCE120_H__ +#define __DC_TIMING_GENERATOR_DCE120_H__ + +#include "timing_generator.h" +#include "../include/grph_object_id.h" +#include "../include/hw_sequencer_types.h" +#include "dce110/dce110_timing_generator.h" + + +bool dce120_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets); + +#endif /* __DC_TIMING_GENERATOR_DCE120_H__ */ -- GitLab From 2c8ad2d5a20c8b7425b547dd4a969ffecad29b39 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:20:24 -0400 Subject: [PATCH 0317/2898] drm/amd/display: Enable DCE12 support This wires DCE12 support into DC and enables it. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 + drivers/gpu/drm/amd/display/Kconfig | 7 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 ++- .../display/amdgpu_dm/amdgpu_dm_services.c | 10 ++ .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 22 ++- drivers/gpu/drm/amd/display/dc/Makefile | 4 + drivers/gpu/drm/amd/display/dc/bios/Makefile | 8 + .../display/dc/bios/bios_parser_interface.c | 14 ++ .../gpu/drm/amd/display/dc/calcs/dce_calcs.c | 117 ++++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 29 ++++ .../gpu/drm/amd/display/dc/core/dc_debug.c | 11 ++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 19 +++ .../gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++ drivers/gpu/drm/amd/display/dc/dc.h | 27 ++++ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 46 ++++++ .../drm/amd/display/dc/dce/dce_clock_source.c | 6 + .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 149 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dce/dce_clocks.h | 20 +++ .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 8 + .../drm/amd/display/dc/dce/dce_link_encoder.h | 14 ++ .../drm/amd/display/dc/dce/dce_mem_input.c | 35 ++++ .../drm/amd/display/dc/dce/dce_mem_input.h | 34 ++++ drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 72 +++++++++ .../amd/display/dc/dce/dce_stream_encoder.h | 100 ++++++++++++ .../drm/amd/display/dc/dce/dce_transform.h | 68 ++++++++ .../display/dc/dce110/dce110_hw_sequencer.c | 53 ++++++- .../amd/display/dc/dce110/dce110_mem_input.c | 3 + .../dc/dce110/dce110_timing_generator.h | 3 + .../gpu/drm/amd/display/dc/dce120/Makefile | 12 ++ .../amd/display/dc/dce80/dce80_mem_input.c | 3 + drivers/gpu/drm/amd/display/dc/dm_services.h | 89 +++++++++++ .../drm/amd/display/dc/dm_services_types.h | 27 ++++ drivers/gpu/drm/amd/display/dc/gpio/Makefile | 11 ++ .../gpu/drm/amd/display/dc/gpio/hw_factory.c | 9 ++ .../drm/amd/display/dc/gpio/hw_translate.c | 9 +- .../gpu/drm/amd/display/dc/i2caux/Makefile | 11 ++ .../gpu/drm/amd/display/dc/i2caux/i2caux.c | 8 + .../drm/amd/display/dc/inc/bandwidth_calcs.h | 3 + .../drm/amd/display/dc/inc/hw/display_clock.h | 23 +++ .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 + drivers/gpu/drm/amd/display/dc/irq/Makefile | 12 ++ .../gpu/drm/amd/display/dc/irq/irq_service.c | 3 + .../gpu/drm/amd/display/include/dal_asic_id.h | 4 + .../gpu/drm/amd/display/include/dal_types.h | 3 + 44 files changed, 1143 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce120/Makefile diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2efb486e283d..96955c9b4cdf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1984,8 +1984,12 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_STONEY: case CHIP_POLARIS11: case CHIP_POLARIS10: + case CHIP_POLARIS12: case CHIP_TONGA: case CHIP_FIJI: +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case CHIP_VEGA10: +#endif #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) return amdgpu_dc != 0; #else diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 47c8e2940a91..32826a0eafe7 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,6 +17,13 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. +config DRM_AMD_DC_DCE12_0 + bool "Vega10 family" + depends on DRM_AMD_DC + help + Choose this option if you want to have + VG family for display engine. + config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" depends on DRM_AMD_DC diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a69ce27b8ed6..9157772a0af3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -888,6 +888,10 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) struct dc_interrupt_params int_params = {0}; int r; int i; + unsigned client_id = AMDGPU_IH_CLIENTID_LEGACY; + + if (adev->asic_type == CHIP_VEGA10) + client_id = AMDGPU_IH_CLIENTID_DCE; int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; @@ -904,7 +908,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) /* Use VBLANK interrupt */ for (i = 1; i <= adev->mode_info.num_crtc; i++) { - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->crtc_irq); + r = amdgpu_irq_add_id(adev, client_id, i, &adev->crtc_irq); if (r) { DRM_ERROR("Failed to add crtc irq id!\n"); @@ -927,7 +931,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) /* Use GRPH_PFLIP interrupt */ for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i, &adev->pageflip_irq); + r = amdgpu_irq_add_id(adev, client_id, i, &adev->pageflip_irq); if (r) { DRM_ERROR("Failed to add page flip irq id!\n"); return r; @@ -948,8 +952,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) } /* HPD */ - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, - &adev->hpd_irq); + r = amdgpu_irq_add_id(adev, client_id, + VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, &adev->hpd_irq); if (r) { DRM_ERROR("Failed to add hpd irq id!\n"); return r; @@ -1119,6 +1123,9 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_POLARIS11: case CHIP_POLARIS10: case CHIP_POLARIS12: +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case CHIP_VEGA10: +#endif if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); return -1; @@ -1312,6 +1319,7 @@ static const struct amdgpu_display_funcs dm_display_funcs = { }; + #if defined(CONFIG_DEBUG_KERNEL_DC) static ssize_t s3_debug_store( @@ -1384,6 +1392,13 @@ static int dm_early_init(void *handle) adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; break; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case CHIP_VEGA10: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; + break; +#endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 1ddc56cfbdc4..df53092abc39 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -402,6 +402,16 @@ bool dm_pp_notify_wm_clock_changes( return false; } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +bool dm_pp_notify_wm_clock_changes_soc15( + const struct dc_context *ctx, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges) +{ + /* TODO: to be implemented */ + return false; +} +#endif + bool dm_pp_apply_power_level_change_request( const struct dc_context *ctx, struct dm_pp_power_level_change_request *level_change_req) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 098a801ae745..01aaf968854d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -494,7 +494,7 @@ static void fill_plane_attributes_from_fb( memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); - /* Fill GFX8 params */ + /* Fill GFX params */ if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { unsigned bankw, bankh, mtaspect, tile_split, num_banks; @@ -523,6 +523,26 @@ static void fill_plane_attributes_from_fb( surface->tiling_info.gfx8.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); +#if defined (CONFIG_DRM_AMD_DC_DCE12_0) + if (adev->asic_type == CHIP_VEGA10) { + /* Fill GFX9 params */ + surface->tiling_info.gfx9.num_pipes = + adev->gfx.config.gb_addr_config_fields.num_pipes; + surface->tiling_info.gfx9.num_banks = + adev->gfx.config.gb_addr_config_fields.num_banks; + surface->tiling_info.gfx9.pipe_interleave = + adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; + surface->tiling_info.gfx9.num_shader_engines = + adev->gfx.config.gb_addr_config_fields.num_se; + surface->tiling_info.gfx9.max_compressed_frags = + adev->gfx.config.gb_addr_config_fields.max_compress_frags; + surface->tiling_info.gfx9.swizzle = + AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); + surface->tiling_info.gfx9.shaderEnable = 1; + } +#endif + + surface->plane_size.grph.surface_size.x = 0; surface->plane_size.grph.surface_size.y = 0; surface->plane_size.grph.surface_size.width = fb->width; diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 2df163bc83e9..a580cab6bf56 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -4,6 +4,10 @@ DC_LIBS = basics bios calcs dce gpio i2caux irq virtual +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +DC_LIBS += dce120 +endif + DC_LIBS += dce112 DC_LIBS += dce110 DC_LIBS += dce100 diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 876614d37412..770248429a81 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -4,6 +4,10 @@ BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +BIOS += command_table2.o command_table_helper2.o bios_parser2.o +endif + AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS)) AMD_DISPLAY_FILES += $(AMD_DAL_BIOS) @@ -21,3 +25,7 @@ AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce80/command_table_helper_dce80.o AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o + +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper2_dce112.o +endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c index 42272c35df2d..7fe2a791ef42 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c @@ -29,6 +29,10 @@ #include "bios_parser_interface.h" #include "bios_parser.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "bios_parser2.h" +#endif + struct dc_bios *dal_bios_parser_create( struct bp_init_data *init, @@ -36,7 +40,17 @@ struct dc_bios *dal_bios_parser_create( { struct dc_bios *bios = NULL; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + bios = firmware_parser_create(init, dce_version); + + if (bios == NULL) + /* TODO: remove dce_version from bios_parser. + * cannot remove today because dal enum to bp enum translation is dce specific + */ + bios = bios_parser_create(init, dce_version); +#else bios = bios_parser_create(init, dce_version); +#endif return bios; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index ab8d1e931846..aa98762346d2 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -50,6 +50,11 @@ static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asi return BW_CALCS_VERSION_POLARIS11; return BW_CALCS_VERSION_INVALID; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case FAMILY_AI: + return BW_CALCS_VERSION_VEGA10; +#endif + default: return BW_CALCS_VERSION_INVALID; } @@ -2430,6 +2435,118 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case BW_CALCS_VERSION_VEGA10: + vbios.memory_type = bw_def_hbm; + vbios.dram_channel_width_in_bits = 128; + vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; + vbios.number_of_dram_banks = 16; + vbios.high_yclk = bw_int_to_fixed(2400); + vbios.mid_yclk = bw_int_to_fixed(1700); + vbios.low_yclk = bw_int_to_fixed(1000); + vbios.low_sclk = bw_int_to_fixed(300); + vbios.mid1_sclk = bw_int_to_fixed(350); + vbios.mid2_sclk = bw_int_to_fixed(400); + vbios.mid3_sclk = bw_int_to_fixed(500); + vbios.mid4_sclk = bw_int_to_fixed(600); + vbios.mid5_sclk = bw_int_to_fixed(700); + vbios.mid6_sclk = bw_int_to_fixed(760); + vbios.high_sclk = bw_int_to_fixed(776); + vbios.low_voltage_max_dispclk = bw_int_to_fixed(460); + vbios.mid_voltage_max_dispclk = bw_int_to_fixed(670); + vbios.high_voltage_max_dispclk = bw_int_to_fixed(1133); + vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios.data_return_bus_width = bw_int_to_fixed(32); + vbios.trc = bw_int_to_fixed(48); + vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(75, 10); + vbios.stutter_self_refresh_entry_latency = bw_frc_to_fixed(19, 10); + vbios.nbp_state_change_latency = bw_int_to_fixed(39); + vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios.scatter_gather_enable = false; + vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios.cursor_width = 32; + vbios.average_compression_rate = 4; + vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 8; + vbios.blackout_duration = bw_int_to_fixed(0); /* us */ + vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip.large_cursor = false; + dceip.dmif_request_buffer_size = bw_int_to_fixed(2304); + dceip.dmif_pipe_en_fbc_chunk_tracker = true; + dceip.cursor_max_outstanding_group_num = 1; + dceip.lines_interleaved_into_lb = 2; + dceip.chunk_width = 256; + dceip.number_of_graphics_pipes = 6; + dceip.number_of_underlay_pipes = 0; + dceip.low_power_tiling_mode = 0; + dceip.display_write_back_supported = true; + dceip.argb_compression_support = true; + dceip.underlay_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35556, 10000); + dceip.underlay_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.underlay_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.underlay_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.graphics_vscaler_efficiency6_bit_per_component = + bw_frc_to_fixed(35, 10); + dceip.graphics_vscaler_efficiency8_bit_per_component = + bw_frc_to_fixed(34286, 10000); + dceip.graphics_vscaler_efficiency10_bit_per_component = + bw_frc_to_fixed(32, 10); + dceip.graphics_vscaler_efficiency12_bit_per_component = + bw_int_to_fixed(3); + dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip.max_dmif_buffer_allocated = 4; + dceip.graphics_dmif_size = 24576; + dceip.underlay_luma_dmif_size = 19456; + dceip.underlay_chroma_dmif_size = 23552; + dceip.pre_downscaler_enabled = true; + dceip.underlay_downscale_prefetch_enabled = false; + dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip.lb_size_per_component444 = bw_int_to_fixed(245952); + dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + bw_int_to_fixed(1); + dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.underlay420_chroma_lb_size_per_component = + bw_int_to_fixed(164352); + dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + 82176); + dceip.cursor_chunk_width = bw_int_to_fixed(64); + dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip.underlay_maximum_width_efficient_for_tiling = + bw_int_to_fixed(1920); + dceip.underlay_maximum_height_efficient_for_tiling = + bw_int_to_fixed(1080); + dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + bw_frc_to_fixed(3, 10); + dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + bw_int_to_fixed(25); + dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + 2); + dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + bw_int_to_fixed(128); + dceip.limit_excessive_outstanding_dmif_requests = true; + dceip.linear_mode_line_request_alternation_slice = + bw_int_to_fixed(64); + dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + 32; + dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip.request_efficiency = bw_frc_to_fixed(8, 10); + dceip.dispclk_per_request = bw_int_to_fixed(2); + dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + break; +#endif default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b9ca9688f8a3..28ed8eaee1ff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1815,3 +1815,32 @@ void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink } } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) +{ + int i; + struct core_dc *core_dc = DC_TO_CORE(dc); + struct mem_input *mi = NULL; + + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + if (core_dc->res_pool->mis[i] != NULL) { + mi = core_dc->res_pool->mis[i]; + break; + } + } + if (mi == NULL) { + dm_error("no mem_input!\n"); + return false; + } + + if (mi->funcs->mem_input_update_dchub) + mi->funcs->mem_input_update_dchub(mi, dh_data); + else + ASSERT(mi->funcs->mem_input_update_dchub); + + + return true; + +} +#endif + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 85ddf5fc4291..079558ab81c0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -141,6 +141,12 @@ void pre_surface_trace( surface->format, surface->rotation, surface->stereo_format); + +#if defined (CONFIG_DRM_AMD_DC_DCE12_0) + SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", + surface->tiling_info.gfx9.swizzle); +#endif + SURFACE_TRACE("\n"); } SURFACE_TRACE("\n"); @@ -221,6 +227,11 @@ void update_surface_trace( update->plane_info->tiling_info.gfx8.pipe_config, update->plane_info->tiling_info.gfx8.array_mode, update->plane_info->visible); + + #if defined (CONFIG_DRM_AMD_DC_DCE12_0) + SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", + update->plane_info->tiling_info.gfx9.swizzle); + #endif } if (update->scaling_info) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 5ca72afe8f6f..f13da7c227f4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1217,6 +1217,25 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); } else { +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + uint32_t dp_phyclk_in_khz; + const struct clocks_value clocks_value = + pipe_ctx->dis_clk->cur_clocks_value; + + /* 27mhz = 27000000hz= 27000khz */ + dp_phyclk_in_khz = link_settings.link_rate * 27000; + + if (((clocks_value.max_non_dp_phyclk_in_khz != 0) && + (dp_phyclk_in_khz > clocks_value.max_non_dp_phyclk_in_khz)) || + (dp_phyclk_in_khz > clocks_value.max_dp_phyclk_in_khz)) { + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, + dp_phyclk_in_khz, + false, + true); + } +#endif } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6119973c7f0a..77ef3304d2bc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -39,6 +39,9 @@ #include "dce100/dce100_resource.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/dce120_resource.h" +#endif enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) { @@ -65,6 +68,11 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) dc_version = DCE_VERSION_11_2; } break; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case FAMILY_AI: + dc_version = DCE_VERSION_12_0; + break; +#endif default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -97,6 +105,12 @@ struct resource_pool *dc_create_resource_pool( res_pool = dce112_create_resource_pool( num_virtual_links, dc); break; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + res_pool = dce120_create_resource_pool( + num_virtual_links, dc); + break; +#endif default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c6c0cf500ae8..bc15065e489b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,6 +55,9 @@ struct dc_caps { struct dc_dcc_surface_param { enum surface_pixel_format format; struct dc_size surface_size; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + enum swizzle_mode_values swizzle_mode; +#endif enum dc_scan_direction scan; }; @@ -143,6 +146,9 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + bool disable_pplib_clock_request; +#endif bool disable_clock_gate; bool disable_dmcu; bool force_abm_enable; @@ -157,6 +163,23 @@ struct dc { struct dc_debug debug; }; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +enum frame_buffer_mode { + FRAME_BUFFER_MODE_LOCAL_ONLY = 0, + FRAME_BUFFER_MODE_ZFB_ONLY, + FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL, +} ; + +struct dchub_init_data { + bool dchub_initialzied; + bool dchub_info_valid; + int64_t zfb_phys_addr_base; + int64_t zfb_mc_base_addr; + uint64_t zfb_size_in_byte; + enum frame_buffer_mode fb_mode; +}; +#endif + struct dc_init_data { struct hw_asic_id asic_id; void *driver; /* ctx */ @@ -177,6 +200,10 @@ struct dc *dc_create(const struct dc_init_data *init_params); void dc_destroy(struct dc **dc); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); +#endif + /******************************************************************************* * Surface Interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 75e16ac70f5f..63813404276d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -259,6 +259,36 @@ enum tile_mode_values { DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1, }; +#if defined (CONFIG_DRM_AMD_DC_DCE12_0) +enum swizzle_mode_values { + DC_SW_LINEAR = 0, + DC_SW_256B_S = 1, + DC_SW_256_D = 2, + DC_SW_256_R = 3, + DC_SW_4KB_S = 5, + DC_SW_4KB_D = 6, + DC_SW_4KB_R = 7, + DC_SW_64KB_S = 9, + DC_SW_64KB_D = 10, + DC_SW_64KB_R = 11, + DC_SW_VAR_S = 13, + DC_SW_VAR_D = 14, + DC_SW_VAR_R = 15, + DC_SW_64KB_S_T = 17, + DC_SW_64KB_D_T = 18, + DC_SW_4KB_S_X = 21, + DC_SW_4KB_D_X = 22, + DC_SW_4KB_R_X = 23, + DC_SW_64KB_S_X = 25, + DC_SW_64KB_D_X = 26, + DC_SW_64KB_R_X = 27, + DC_SW_VAR_S_X = 29, + DC_SW_VAR_D_X = 30, + DC_SW_VAR_R_X = 31, + DC_SW_MAX +}; +#endif + union dc_tiling_info { struct { @@ -323,6 +353,22 @@ union dc_tiling_info { enum array_mode_values array_mode; } gfx8; +#if defined (CONFIG_DRM_AMD_DC_DCE12_0) + struct { + unsigned int num_pipes; + unsigned int num_banks; + unsigned int pipe_interleave; + unsigned int num_shader_engines; + unsigned int num_rb_per_se; + unsigned int max_compressed_frags; + bool shaderEnable; + + enum swizzle_mode_values swizzle; + bool meta_linear; + bool rb_aligned; + bool pipe_aligned; + } gfx9; +#endif }; /* Rotation angle */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 1d6a9da45ba6..f53dc157db97 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -585,6 +585,9 @@ static uint32_t dce110_get_pix_clk_dividers( pll_settings, pix_clk_params); break; case DCE_VERSION_11_2: +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: +#endif dce112_get_pix_clk_dividers_helper(clk_src, pll_settings, pix_clk_params); break; @@ -868,6 +871,9 @@ static bool dce110_program_pix_clk( break; case DCE_VERSION_11_2: +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: +#endif if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = pll_settings->use_external_clk; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index ac1febafcaa4..9c743e51c091 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -80,6 +80,20 @@ static struct state_dependent_clocks dce112_max_clks_by_state[] = { /*ClocksStatePerformance*/ { .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +static struct state_dependent_clocks dce120_max_clks_by_state[] = { +/*ClocksStateInvalid - should not be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/*ClocksStateLow*/ +{ .display_clk_khz = 460000, .pixel_clk_khz = 400000 }, +/*ClocksStateNominal*/ +{ .display_clk_khz = 670000, .pixel_clk_khz = 600000 }, +/*ClocksStatePerformance*/ +{ .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; +#endif + /* Starting point for each divider range.*/ enum dce_divider_range_start { DIVIDER_RANGE_01_START = 200, /* 2.00*/ @@ -483,6 +497,103 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) } } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +static bool dce_apply_clock_voltage_request( + struct display_clock *clk, + enum dm_pp_clock_type clocks_type, + int clocks_in_khz, + bool pre_mode_set, + bool update_dp_phyclk) +{ + struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; + + switch (clocks_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + case DM_PP_CLOCK_TYPE_PIXELCLK: + case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: + break; + default: + BREAK_TO_DEBUGGER(); + return false; + } + + clock_voltage_req.clk_type = clocks_type; + clock_voltage_req.clocks_in_khz = clocks_in_khz; + + /* to pplib */ + if (pre_mode_set) { + switch (clocks_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + if (clocks_in_khz > clk->cur_clocks_value.dispclk_in_khz) { + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + clk->cur_clocks_value.dispclk_notify_pplib_done = true; + } else + clk->cur_clocks_value.dispclk_notify_pplib_done = false; + /* no matter incrase or decrase clock, update current clock value */ + clk->cur_clocks_value.dispclk_in_khz = clocks_in_khz; + break; + case DM_PP_CLOCK_TYPE_PIXELCLK: + if (clocks_in_khz > clk->cur_clocks_value.max_pixelclk_in_khz) { + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + clk->cur_clocks_value.pixelclk_notify_pplib_done = true; + } else + clk->cur_clocks_value.pixelclk_notify_pplib_done = false; + /* no matter incrase or decrase clock, update current clock value */ + clk->cur_clocks_value.max_pixelclk_in_khz = clocks_in_khz; + break; + case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: + if (clocks_in_khz > clk->cur_clocks_value.max_non_dp_phyclk_in_khz) { + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + clk->cur_clocks_value.phyclk_notigy_pplib_done = true; + } else + clk->cur_clocks_value.phyclk_notigy_pplib_done = false; + /* no matter incrase or decrase clock, update current clock value */ + clk->cur_clocks_value.max_non_dp_phyclk_in_khz = clocks_in_khz; + break; + default: + ASSERT(0); + break; + } + } else { + switch (clocks_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + if (!clk->cur_clocks_value.dispclk_notify_pplib_done) + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + break; + case DM_PP_CLOCK_TYPE_PIXELCLK: + if (!clk->cur_clocks_value.pixelclk_notify_pplib_done) + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + break; + case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: + if (!clk->cur_clocks_value.phyclk_notigy_pplib_done) + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + break; + default: + ASSERT(0); + break; + } + } + + if (update_dp_phyclk && (clocks_in_khz > + clk->cur_clocks_value.max_dp_phyclk_in_khz)) + clk->cur_clocks_value.max_dp_phyclk_in_khz = clocks_in_khz; + + return true; +} + +static const struct display_clock_funcs dce120_funcs = { + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .apply_clock_voltage_request = dce_apply_clock_voltage_request, + .set_clock = dce112_set_clock +}; +#endif + static const struct display_clock_funcs dce112_funcs = { .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, .get_required_clocks_state = dce_get_required_clocks_state, @@ -623,6 +734,44 @@ struct display_clock *dce112_disp_clk_create( return &clk_dce->base; } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +struct display_clock *dce120_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask) +{ + struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dm_pp_clock_levels_with_voltage clk_level_info = {0}; + + if (clk_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + memcpy(clk_dce->max_clks_by_state, + dce120_max_clks_by_state, + sizeof(dce120_max_clks_by_state)); + + dce_disp_clk_construct( + clk_dce, ctx, regs, clk_shift, clk_mask); + + clk_dce->base.funcs = &dce120_funcs; + + /* new in dce120 */ + if (!ctx->dc->debug.disable_pplib_clock_request && + dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clk_level_info) + && clk_level_info.num_levels) + clk_dce->max_displ_clk_in_khz = + clk_level_info.data[clk_level_info.num_levels - 1].clocks_in_khz; + else + clk_dce->max_displ_clk_in_khz = 1133000; + + return &clk_dce->base; +} +#endif + void dce_disp_clk_destroy(struct display_clock **disp_clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(*disp_clk); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 020ab9d5434d..18787f6d4e2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -45,6 +45,14 @@ CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define CLK_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ + CLK_SF(DCCG_DFS_DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ + CLK_SF(DCCG_DFS_DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ + CLK_SF(DCCG_DFS_MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + CLK_SF(DCCG_DFS_MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) +#endif + #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ type DENTIST_DPREFCLK_WDIVIDER; \ @@ -118,6 +126,10 @@ struct dce_disp_clk { int gpu_pll_ss_divider; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + /* max disp_clk from PPLIB for max validation display clock*/ + int max_displ_clk_in_khz; +#endif }; @@ -139,6 +151,14 @@ struct display_clock *dce112_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +struct display_clock *dce120_disp_clk_create( + struct dc_context *ctx, + const struct dce_disp_clk_registers *regs, + const struct dce_disp_clk_shift *clk_shift, + const struct dce_disp_clk_mask *clk_mask); +#endif + void dce_disp_clk_destroy(struct display_clock **disp_clk); #endif /* _DCE_CLOCKS_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 70e0652be071..ff7984b08095 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -186,6 +186,14 @@ struct dce_hwseq_registers { HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ + HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) +#endif + #define HWSEQ_REG_FIED_LIST(type) \ type DCFE_CLOCK_ENABLE; \ type DCFEV_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index f337d607e36c..f6a1006a6472 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -31,6 +31,13 @@ #define TO_DCE110_LINK_ENC(link_encoder)\ container_of(link_encoder, struct dce110_link_encoder, base) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +/* Not found regs in dce120 spec + * BIOS_SCRATCH_2 + * DP_DPHY_INTERNAL_CTRL + */ +#endif + #define AUX_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id) @@ -79,6 +86,13 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + #define LE_DCE120_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) +#endif + #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ LE_COMMON_REG_LIST_BASE(id) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index e14a21cedfd5..c494f712b5b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -187,6 +187,20 @@ static void program_nbp_watermark(struct mem_input *mi, REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, nbp_wm); } +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + if (REG(DPG_PIPE_LOW_POWER_CONTROL)) { + REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, + PSTATE_CHANGE_WATERMARK_MASK, wm_select); + + REG_UPDATE_3(DPG_PIPE_LOW_POWER_CONTROL, + PSTATE_CHANGE_ENABLE, 1, + PSTATE_CHANGE_URGENT_DURING_REQUEST, 1, + PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1); + + REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL, + PSTATE_CHANGE_WATERMARK, nbp_wm); + } +#endif } static void program_stutter_watermark(struct mem_input *mi, @@ -196,6 +210,12 @@ static void program_stutter_watermark(struct mem_input *mi, REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + if (REG(DPG_PIPE_STUTTER_CONTROL2)) + REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2, + STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); + else +#endif REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); } @@ -234,6 +254,21 @@ void dce_mem_input_program_display_marks(struct mem_input *mi, static void program_tiling(struct mem_input *mi, const union dc_tiling_info *info) { +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + if (mi->masks->GRPH_SW_MODE) { /* GFX9 */ + REG_UPDATE_6(GRPH_CONTROL, + GRPH_SW_MODE, info->gfx9.swizzle, + GRPH_NUM_BANKS, log_2(info->gfx9.num_banks), + GRPH_NUM_SHADER_ENGINES, log_2(info->gfx9.num_shader_engines), + GRPH_NUM_PIPES, log_2(info->gfx9.num_pipes), + GRPH_COLOR_EXPANSION_MODE, 1, + GRPH_SE_ENABLE, info->gfx9.shaderEnable); + /* TODO: DCP0_GRPH_CONTROL__GRPH_SE_ENABLE where to get info + GRPH_SE_ENABLE, 1, + GRPH_Z, 0); + */ + } +#endif if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ REG_UPDATE_9(GRPH_CONTROL, GRPH_NUM_BANKS, info->gfx8.num_banks, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index ec053c241901..9e18c2a34e85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -58,6 +58,15 @@ MI_DCE11_2_REG_LIST(id),\ MI_DCE_PTE_REG_LIST(id) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define MI_DCE12_REG_LIST(id)\ + MI_DCE_BASE_REG_LIST(id),\ + MI_DCE_PTE_REG_LIST(id),\ + SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id),\ + SRI(DPG_PIPE_STUTTER_CONTROL2, DMIF_PG, id),\ + SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id) +#endif + struct dce_mem_input_registers { /* DCP */ uint32_t GRPH_ENABLE; @@ -163,6 +172,31 @@ struct dce_mem_input_registers { MI_DCE11_2_MASK_SH_LIST(mask_sh),\ MI_DCP_PTE_MASK_SH_LIST(mask_sh, ) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define MI_GFX9_TILE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_CONTROL, GRPH_SW_MODE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_SE_ENABLE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_SHADER_ENGINES, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_PIPES, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh) + +#define MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL2, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\ + SFB(blk, DPG_WATERMARK_MASK_CONTROL, PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_WATERMARK, mask_sh) + +#define MI_DCE12_MASK_SH_LIST(mask_sh)\ + MI_DCP_MASK_SH_LIST(mask_sh, DCP0_),\ + MI_DCP_DCE11_MASK_SH_LIST(mask_sh, DCP0_),\ + MI_DCP_PTE_MASK_SH_LIST(mask_sh, DCP0_),\ + MI_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ + MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ + MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_) +#endif + #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ type GRPH_X_START; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index a5afc0298d6f..4784ced6fc80 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -107,6 +107,14 @@ enum dce110_opp_reg_type { SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \ SRI(CONTROL, FMT_MEMORY, id) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define OPP_DCE_120_REG_LIST(id) \ + OPP_COMMON_REG_LIST_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ + SRI(CONTROL, FMT_MEMORY, id) +#endif + #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -197,6 +205,70 @@ enum dce110_opp_reg_type { OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define OPP_COMMON_MASK_SH_LIST_DCE_120(mask_sh)\ + OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + OPP_SF(DCFE0_DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ + OPP_SF(DCP0_REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ + OPP_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ + OPP_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + OPP_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + OPP_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\ + OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\ + OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\ + OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\ + OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SRC_SELECT, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_R, FMT_CLAMP_LOWER_R, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_R, FMT_CLAMP_UPPER_R, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_G, FMT_CLAMP_LOWER_G, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_G, FMT_CLAMP_UPPER_G, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_B, FMT_CLAMP_LOWER_B, mask_sh),\ + OPP_SF(FMT0_FMT_CLAMP_COMPONENT_B, FMT_CLAMP_UPPER_B, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh) +#endif + #define OPP_REG_FIELD_LIST(type) \ type DCP_REGAMMA_MEM_PWR_DIS; \ type DCP_LUT_MEM_PWR_DIS; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index 458a37000956..c784c1b961c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -187,6 +187,91 @@ #define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh)\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\ + SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(DIG0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ + SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ + SE_SF(DIG0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ + SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ + SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) +#endif + +#define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) + #define SE_COMMON_MASK_SH_LIST_DCE80_100(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ @@ -209,6 +294,21 @@ SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define SE_COMMON_MASK_SH_LIST_DCE120(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_DYN_RANGE, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_YCBCR_RANGE, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) +#endif + struct dce_stream_encoder_shift { uint8_t AFMT_GENERIC_INDEX; uint8_t AFMT_GENERIC0_UPDATE; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index b2cf9bfb0094..aa6bc4fc80c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -153,6 +153,74 @@ XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define XFM_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MIN_G_Y, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MAX_G_Y, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MIN_R_CR, mask_sh), \ + XFM_SF(DCP0_OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR, mask_sh), \ + XFM_SF(DCP0_OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP0_DENORM_CONTROL, DENORM_MODE, mask_sh), \ + XFM_SF(LB0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh), \ + XFM_SF(LB0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ + XFM_SF(DCP0_GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \ + XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL0_SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \ + XFM_SF(SCL0_SCL_BYPASS_CONTROL, SCL_BYPASS_MODE, mask_sh), \ + XFM_SF(SCL0_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \ + XFM_SF(SCL0_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \ + XFM_SF(SCL0_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \ + XFM_SF(SCL0_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \ + XFM_SF(SCL0_VIEWPORT_START, VIEWPORT_X_START, mask_sh), \ + XFM_SF(SCL0_VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \ + XFM_SF(SCL0_VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \ + XFM_SF(SCL0_VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \ + XFM_SF(SCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh), \ + XFM_SF(SCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh), \ + XFM_SF(SCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \ + XFM_SF(SCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \ + XFM_SF(LB0_LB_MEMORY_CTRL, LB_MEMORY_CONFIG, mask_sh), \ + XFM_SF(LB0_LB_MEMORY_CTRL, LB_MEMORY_SIZE, mask_sh), \ + XFM_SF(SCL0_SCL_VERT_FILTER_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh), \ + XFM_SF(SCL0_SCL_HORZ_FILTER_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh), \ + XFM_SF(SCL0_SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \ + XFM_SF(LB0_LB_DATA_FORMAT, ALPHA_EN, mask_sh), \ + XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ + XFM_SF(DCFE0_DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ + XFM_SF(SCL0_SCL_MODE, SCL_PSCL_EN, mask_sh) +#endif + #define XFM_REG_FIELD_LIST(type) \ type OUT_CLAMP_MIN_B_CB; \ type OUT_CLAMP_MAX_B_CB; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 041830e05b67..66d5f346f195 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1396,9 +1396,12 @@ static uint32_t get_max_pixel_clock_for_all_paths( return max_pix_clk; } -/* - * Find clock state based on clock requested. if clock value is 0, simply +/* Find clock state based on clock requested. if clock value is 0, simply * set clock state as requested without finding clock state by clock value + *TODO: when dce120_hw_sequencer.c is created, override apply_min_clock. + * + * TODOFPGA remove TODO after implement dal_display_clock_get_cur_clocks_value + * etc support for dcn1.0 */ static void apply_min_clocks( struct core_dc *dc, @@ -1425,6 +1428,30 @@ static void apply_min_clocks( } /* TODOFPGA */ +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + /* TODO: This is incorrect. Figure out how to fix. */ + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAY_CLK, + pipe_ctx->dis_clk->cur_clocks_value.dispclk_in_khz, + pre_mode_set, + false); + + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_PIXELCLK, + pipe_ctx->dis_clk->cur_clocks_value.max_pixelclk_in_khz, + pre_mode_set, + false); + + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, + pipe_ctx->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz, + pre_mode_set, + false); + return; +#endif } /* get the required state based on state dependent clocks: @@ -1441,6 +1468,28 @@ static void apply_min_clocks( pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, *clocks_state); } else { +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAY_CLK, + req_clocks.display_clk_khz, + pre_mode_set, + false); + + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_PIXELCLK, + req_clocks.pixel_clk_khz, + pre_mode_set, + false); + + pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( + pipe_ctx->dis_clk, + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, + req_clocks.pixel_clk_khz, + pre_mode_set, + false); +#endif } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index 1643fb5d4b04..3ffb845f843a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -409,6 +409,9 @@ static struct mem_input_funcs dce110_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + .mem_input_update_dchub = NULL +#endif }; /*****************************************/ /* Constructor, Destructor */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index dcb49fe452c5..55f0a94e7cae 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -108,6 +108,9 @@ struct dce110_timing_generator { uint32_t min_h_front_porch; uint32_t min_h_back_porch; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + /* DCE 12 */ +#endif uint32_t min_h_sync_width; uint32_t min_v_sync_width; uint32_t min_v_blank; diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile new file mode 100644 index 000000000000..3c6b3fa98ddc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + + +DCE120 = dce120_resource.o dce120_timing_generator.o \ +dce120_ipp.o dce120_ipp_cursor.o dce120_ipp_gamma.o \ +dce120_mem_input.o dce120_hw_sequencer.o + +AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE120) \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c index 704a7ce62080..2f22931f457b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -54,6 +54,9 @@ static struct mem_input_funcs dce80_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + .mem_input_update_dchub = NULL +#endif }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 73c0f1f83999..bdc7cb045eed 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -192,6 +192,89 @@ unsigned int generic_reg_wait(const struct dc_context *ctx, unsigned int delay_between_poll_us, unsigned int time_out_num_tries, const char *func_name); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + +/* These macros need to be used with soc15 registers in order to retrieve + * the actual offset. + */ +#define REG_OFFSET(reg) (reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX]) +#define REG_BIF_OFFSET(reg) (reg + NBIF_BASE.instance[0].segment[reg##_BASE_IDX]) + +#define dm_write_reg_soc15(ctx, reg, inst_offset, value) \ + dm_write_reg_func(ctx, reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX] + inst_offset, value, __func__) + +#define dm_read_reg_soc15(ctx, reg, inst_offset) \ + dm_read_reg_func(ctx, reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX] + inst_offset, __func__) + +#define generic_reg_update_soc15(ctx, inst_offset, reg_name, n, ...)\ + generic_reg_update_ex(ctx, DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + mm##reg_name + inst_offset, \ + dm_read_reg_func(ctx, mm##reg_name + DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + inst_offset, __func__), \ + n, __VA_ARGS__) + +#define generic_reg_set_soc15(ctx, inst_offset, reg_name, n, ...)\ + generic_reg_update_ex(ctx, DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX] + mm##reg_name + inst_offset, 0, \ + n, __VA_ARGS__) + +#define get_reg_field_value_soc15(reg_value, block, reg_num, reg_name, reg_field)\ + get_reg_field_value_ex(\ + (reg_value),\ + block ## reg_num ## _ ## reg_name ## __ ## reg_field ## _MASK,\ + block ## reg_num ## _ ## reg_name ## __ ## reg_field ## __SHIFT) + +#define set_reg_field_value_soc15(reg_value, value, block, reg_num, reg_name, reg_field)\ + (reg_value) = set_reg_field_value_ex(\ + (reg_value),\ + (value),\ + block ## reg_num ## _ ## reg_name ## __ ## reg_field ## _MASK,\ + block ## reg_num ## _ ## reg_name ## __ ## reg_field ## __SHIFT) + +/* TODO get rid of this pos*/ +static inline bool wait_reg_func( + const struct dc_context *ctx, + uint32_t addr, + uint32_t mask, + uint8_t shift, + uint32_t condition_value, + unsigned int interval_us, + unsigned int timeout_us) +{ + uint32_t field_value; + uint32_t reg_val; + unsigned int count = 0; + + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + timeout_us *= 655; /* 6553 give about 30 second before time out */ + + do { + /* try once without sleeping */ + if (count > 0) { + if (interval_us >= 1000) + msleep(interval_us/1000); + else + udelay(interval_us); + } + reg_val = dm_read_reg(ctx, addr); + field_value = get_reg_field_value_ex(reg_val, mask, shift); + count += interval_us; + + } while (field_value != condition_value && count <= timeout_us); + + ASSERT(count <= timeout_us); + + return count <= timeout_us; +} + +#define wait_reg(ctx, inst_offset, reg_name, reg_field, condition_value)\ + wait_reg_func(\ + ctx,\ + mm##reg_name + inst_offset + DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX],\ + reg_name ## __ ## reg_field ## _MASK,\ + reg_name ## __ ## reg_field ## __SHIFT,\ + condition_value,\ + 20000,\ + 200000) + +#endif /************************************** * Power Play (PP) interfaces **************************************/ @@ -254,6 +337,12 @@ bool dm_pp_notify_wm_clock_changes( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +bool dm_pp_notify_wm_clock_changes_soc15( + const struct dc_context *ctx, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); +#endif + /* DAL calls this function to notify PP about completion of Mode Set. * For PP it means that current DCE clocks are those which were returned * by dc_service_pp_pre_dce_clock_change(), in the 'output' parameter. diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 460971dc3a70..8d2661583f21 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -141,6 +141,33 @@ struct dm_pp_wm_sets_with_clock_ranges { struct dm_pp_clock_range_for_wm_set wm_clk_ranges[MAX_WM_SETS]; }; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +struct dm_pp_clock_range_for_dmif_wm_set_soc15 { + enum dm_pp_wm_set_id wm_set_id; + uint32_t wm_min_dcfclk_clk_in_khz; + uint32_t wm_max_dcfclk_clk_in_khz; + uint32_t wm_min_memg_clk_in_khz; + uint32_t wm_max_mem_clk_in_khz; +}; + +struct dm_pp_clock_range_for_mcif_wm_set_soc15 { + enum dm_pp_wm_set_id wm_set_id; + uint32_t wm_min_socclk_clk_in_khz; + uint32_t wm_max_socclk_clk_in_khz; + uint32_t wm_min_memg_clk_in_khz; + uint32_t wm_max_mem_clk_in_khz; +}; + +struct dm_pp_wm_sets_with_clock_ranges_soc15 { + uint32_t num_wm_dmif_sets; + uint32_t num_wm_mcif_sets; + struct dm_pp_clock_range_for_dmif_wm_set_soc15 + wm_dmif_clocks_ranges[MAX_WM_SETS]; + struct dm_pp_clock_range_for_mcif_wm_set_soc15 + wm_mcif_clocks_ranges[MAX_WM_SETS]; +}; +#endif + #define MAX_DISPLAY_CONFIGS 6 struct dm_pp_display_configuration { diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index a15c257fd2fa..8cf12a8ca28f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -28,6 +28,17 @@ AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE110) +############################################################################### +# DCE 12x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +GPIO_DCE120 = hw_translate_dce120.o hw_factory_dce120.o + +AMD_DAL_GPIO_DCE120 = $(addprefix $(AMDDALPATH)/dc/gpio/dce120/,$(GPIO_DCE120)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE120) +endif + ############################################################################### # Diagnostics on FPGA ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index f1a6fa7391c6..66ea3b31b980 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -44,6 +44,10 @@ #include "dce110/hw_factory_dce110.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/hw_factory_dce120.h" +#endif + #include "diagnostics/hw_factory_diag.h" /* @@ -72,6 +76,11 @@ bool dal_hw_factory_init( case DCE_VERSION_11_2: dal_hw_factory_dce110_init(factory); return true; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + dal_hw_factory_dce120_init(factory); + return true; +#endif default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 23e097fa5ace..10e86447f179 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -42,7 +42,9 @@ #include "dce80/hw_translate_dce80.h" #include "dce110/hw_translate_dce110.h" - +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/hw_translate_dce120.h" +#endif #include "diagnostics/hw_translate_diag.h" /* @@ -68,6 +70,11 @@ bool dal_hw_translate_init( case DCE_VERSION_11_2: dal_hw_translate_dce110_init(translate); return true; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + dal_hw_translate_dce120_init(translate); + return true; +#endif default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile index 83dfc437aae4..99aa5d8fb9a7 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -47,6 +47,17 @@ AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) +############################################################################### +# DCE 120 family +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +I2CAUX_DCE120 = i2caux_dce120.o + +AMD_DAL_I2CAUX_DCE120 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce120/,$(I2CAUX_DCE120)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE120) +endif + ############################################################################### # Diagnostics on FPGA ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 5391655af23a..ea3bd75e0555 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -57,6 +57,10 @@ #include "dce112/i2caux_dce112.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/i2caux_dce120.h" +#endif + #include "diagnostics/i2caux_diag.h" /* @@ -80,6 +84,10 @@ struct i2caux *dal_i2caux_create( return dal_i2caux_dce110_create(ctx); case DCE_VERSION_10_0: return dal_i2caux_dce100_create(ctx); + #if defined(CONFIG_DRM_AMD_DC_DCE12_0) + case DCE_VERSION_12_0: + return dal_i2caux_dce120_create(ctx); + #endif default: BREAK_TO_DEBUGGER(); return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h index 16f06fa2d69c..a7eaecd32aea 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h @@ -40,6 +40,9 @@ enum bw_calcs_version { BW_CALCS_VERSION_POLARIS10, BW_CALCS_VERSION_POLARIS11, BW_CALCS_VERSION_STONEY, +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + BW_CALCS_VERSION_VEGA10 +#endif }; /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index e163f5818dd9..bf77aa6172e1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -28,6 +28,18 @@ #include "dm_services_types.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +struct clocks_value { + int dispclk_in_khz; + int max_pixelclk_in_khz; + int max_non_dp_phyclk_in_khz; + int max_dp_phyclk_in_khz; + bool dispclk_notify_pplib_done; + bool pixelclk_notify_pplib_done; + bool phyclk_notigy_pplib_done; +}; +#endif + /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ struct state_dependent_clocks { @@ -41,6 +53,9 @@ struct display_clock { enum dm_pp_clocks_state max_clks_state; enum dm_pp_clocks_state cur_min_clks_state; +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + struct clocks_value cur_clocks_value; +#endif }; struct display_clock_funcs { @@ -56,6 +71,14 @@ struct display_clock_funcs { int (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + bool (*apply_clock_voltage_request)( + struct display_clock *disp_clk, + enum dm_pp_clock_type clocks_type, + int clocks_in_khz, + bool pre_mode_set, + bool update_dp_phyclk); +#endif }; #endif /* __DISPLAY_CLOCK_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index ed980aed1677..6c0600696d02 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -100,6 +100,10 @@ struct mem_input_funcs { bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + void (*mem_input_update_dchub)(struct mem_input *mem_input, + struct dchub_init_data *dh_data); +#endif }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 02710333ce0a..140e49811dd1 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -26,3 +26,15 @@ IRQ_DCE11 = irq_service_dce110.o AMD_DAL_IRQ_DCE11 = $(addprefix $(AMDDALPATH)/dc/irq/dce110/,$(IRQ_DCE11)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE11) + +############################################################################### +# DCE 12x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCE12_0 +IRQ_DCE12 = irq_service_dce120.o + +AMD_DAL_IRQ_DCE12 = $(addprefix $(AMDDALPATH)/dc/irq/dce120/,$(IRQ_DCE12)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE12) +endif + diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index fbaa2fc00ddb..a1b6d83b1cbb 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -33,6 +33,9 @@ #include "dce80/irq_service_dce80.h" +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#include "dce120/irq_service_dce120.h" +#endif #include "reg_helper.h" #include "irq_service.h" diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 46f1e88f5e27..15c0b8c14b30 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -123,6 +123,10 @@ #define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */ #define FAMILY_CZ 135 /* Carrizo */ +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) +#define FAMILY_AI 141 +#endif + #define FAMILY_UNKNOWN 0xFF #endif /* __DAL_ASIC_ID_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index ada5b19e85eb..e24c1ef58d2f 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -38,6 +38,9 @@ enum dce_version { DCE_VERSION_10_0, DCE_VERSION_11_0, DCE_VERSION_11_2, +#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + DCE_VERSION_12_0, +#endif DCE_VERSION_MAX, }; -- GitLab From 85a51eeec7ed5bb1dab67e2691813418e9185add Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 7 Mar 2017 16:54:32 -0500 Subject: [PATCH 0318/2898] drm/amd/display: need to handle DCE_Info table ver4.2 Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Krunoslav Kovac Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/bios/bios_parser2.c | 79 ++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index f6e77da7d302..123942f4cbde 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1137,6 +1137,81 @@ static enum bp_result get_ss_info_v4_1( return result; } +static enum bp_result get_ss_info_v4_2( + struct bios_parser *bp, + uint32_t id, + uint32_t index, + struct spread_spectrum_info *ss_info) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; + struct atom_smu_info_v3_1 *smu_tbl = NULL; + + if (!ss_info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + if (!DATA_TABLES(smu_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2, + DATA_TABLES(dce_info)); + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + smu_tbl = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); + if (!smu_tbl) + return BP_RESULT_BADBIOSTABLE; + + + ss_info->type.STEP_AND_DELAY_INFO = false; + ss_info->spread_percentage_divider = 1000; + /* BIOS no longer uses target clock. Always enable for now */ + ss_info->target_clock_range = 0xffffffff; + + switch (id) { + case AS_SIGNAL_TYPE_DVI: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->dvi_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->dvi_ss_rate_10hz * 10; + if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + case AS_SIGNAL_TYPE_HDMI: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->hdmi_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->hdmi_ss_rate_10hz * 10; + if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + /* TODO LVDS not support anymore? */ + case AS_SIGNAL_TYPE_DISPLAY_PORT: + ss_info->spread_spectrum_percentage = + disp_cntl_tbl->dp_ss_percentage; + ss_info->spread_spectrum_range = + disp_cntl_tbl->dp_ss_rate_10hz * 10; + if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + case AS_SIGNAL_TYPE_GPU_PLL: + ss_info->spread_spectrum_percentage = + smu_tbl->gpuclk_ss_percentage; + ss_info->spread_spectrum_range = + smu_tbl->gpuclk_ss_rate_10hz * 10; + if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + ss_info->type.CENTER_MODE = true; + break; + default: + result = BP_RESULT_UNSUPPORTED; + } + + return result; +} + /** * bios_parser_get_spread_spectrum_info * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or @@ -1177,6 +1252,8 @@ static enum bp_result bios_parser_get_spread_spectrum_info( switch (tbl_revision.minor) { case 1: return get_ss_info_v4_1(bp, signal, index, ss_info); + case 2: + return get_ss_info_v4_2(bp, signal, index, ss_info); default: break; } @@ -1579,7 +1656,7 @@ static enum bp_result get_firmware_info_v3_1( /* Hardcode frequency if BIOS gives no DCE Ref Clk */ if (info->pll_info.crystal_frequency == 0) info->pll_info.crystal_frequency = 27000; - + /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/ info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10; info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10; -- GitLab From 7fc6ff772b22cad6fc5fe06b0dfa3f730559faf4 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Wed, 8 Mar 2017 14:04:16 -0500 Subject: [PATCH 0319/2898] drm/amd/display: Less log spam Signed-off-by: Jordan Lazare Acked-by: Harry Wentland Reviewed-by: Charlene Liu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 36d158249182..e33e6bfccb6d 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -238,8 +238,8 @@ static enum bp_result transmitter_control_v1_6( if (cntl->action == TRANSMITTER_CONTROL_ENABLE || cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { - dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ - "************************%s:ps.param.symclk_10khz = %d\n",\ + dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\ + "%s:ps.param.symclk_10khz = %d\n",\ __func__, ps.param.symclk_10khz); } @@ -328,8 +328,8 @@ static enum bp_result set_pixel_clock_v7( (uint8_t) bp->cmd_helper-> transmitter_color_depth_to_atom( bp_params->color_depth); - dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\ - "************************%s:program display clock = %d"\ + dm_logger_write(bp->base.ctx->logger, LOG_BIOS,\ + "%s:program display clock = %d"\ "colorDepth = %d\n", __func__,\ bp_params->target_pixel_clock, bp_params->color_depth); @@ -760,8 +760,8 @@ static enum bp_result set_dce_clock_v2_1( */ params.param.dceclk_10khz = cpu_to_le32( bp_params->target_clock_frequency / 10); - dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE, - "************************%s:target_clock_frequency = %d"\ + dm_logger_write(bp->base.ctx->logger, LOG_BIOS, + "%s:target_clock_frequency = %d"\ "clock_type = %d \n", __func__,\ bp_params->target_clock_frequency,\ bp_params->clock_type); -- GitLab From 8fa9ca2ec6919656db87391a1633692ee8d57c22 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:21:43 -0400 Subject: [PATCH 0320/2898] drm/amd/display: Remove DCE12 guards Signed-off-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 -- drivers/gpu/drm/amd/display/Kconfig | 7 ------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ---- .../amd/display/amdgpu_dm/amdgpu_dm_services.c | 2 -- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 -- drivers/gpu/drm/amd/display/dc/Makefile | 3 --- drivers/gpu/drm/amd/display/dc/bios/Makefile | 4 ---- .../display/dc/bios/bios_parser_interface.c | 10 +--------- .../display/dc/bios/command_table_helper2.c | 2 -- .../gpu/drm/amd/display/dc/calcs/dce_calcs.c | 4 ---- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 -- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 6 +----- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 -- .../gpu/drm/amd/display/dc/core/dc_resource.c | 6 ------ drivers/gpu/drm/amd/display/dc/dc.h | 8 -------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 ---- .../drm/amd/display/dc/dce/dce_clock_source.c | 4 ---- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 6 ------ .../gpu/drm/amd/display/dc/dce/dce_clocks.h | 6 ------ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 -- .../drm/amd/display/dc/dce/dce_link_encoder.h | 18 +++++++----------- .../gpu/drm/amd/display/dc/dce/dce_mem_input.c | 8 ++------ .../gpu/drm/amd/display/dc/dce/dce_mem_input.h | 4 ---- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 4 ---- .../amd/display/dc/dce/dce_stream_encoder.h | 4 ---- .../gpu/drm/amd/display/dc/dce/dce_transform.h | 2 -- .../display/dc/dce110/dce110_hw_sequencer.c | 5 ----- .../amd/display/dc/dce110/dce110_mem_input.c | 2 -- .../dc/dce110/dce110_timing_generator.h | 2 -- .../amd/display/dc/dce120/dce120_resource.c | 14 +++++--------- .../drm/amd/display/dc/dce80/dce80_mem_input.c | 2 -- drivers/gpu/drm/amd/display/dc/dm_services.h | 4 ---- .../gpu/drm/amd/display/dc/dm_services_types.h | 2 -- drivers/gpu/drm/amd/display/dc/gpio/Makefile | 2 -- .../gpu/drm/amd/display/dc/gpio/hw_factory.c | 4 ---- .../gpu/drm/amd/display/dc/gpio/hw_translate.c | 4 ---- drivers/gpu/drm/amd/display/dc/i2caux/Makefile | 2 -- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 4 ---- .../drm/amd/display/dc/inc/bandwidth_calcs.h | 2 -- .../drm/amd/display/dc/inc/hw/display_clock.h | 6 ------ .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 2 -- drivers/gpu/drm/amd/display/dc/irq/Makefile | 2 -- .../gpu/drm/amd/display/dc/irq/irq_service.c | 2 -- .../gpu/drm/amd/display/include/dal_asic_id.h | 2 -- .../gpu/drm/amd/display/include/dal_types.h | 2 -- 45 files changed, 16 insertions(+), 175 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 96955c9b4cdf..df95dd8439b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1987,9 +1987,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_POLARIS12: case CHIP_TONGA: case CHIP_FIJI: -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case CHIP_VEGA10: -#endif #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) return amdgpu_dc != 0; #else diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 32826a0eafe7..47c8e2940a91 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,13 +17,6 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. -config DRM_AMD_DC_DCE12_0 - bool "Vega10 family" - depends on DRM_AMD_DC - help - Choose this option if you want to have - VG family for display engine. - config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" depends on DRM_AMD_DC diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9157772a0af3..97d949affcfb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1123,9 +1123,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_POLARIS11: case CHIP_POLARIS10: case CHIP_POLARIS12: -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case CHIP_VEGA10: -#endif if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); return -1; @@ -1392,13 +1390,11 @@ static int dm_early_init(void *handle) adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; break; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case CHIP_VEGA10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; break; -#endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index df53092abc39..a8a53b85905a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -402,7 +402,6 @@ bool dm_pp_notify_wm_clock_changes( return false; } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool dm_pp_notify_wm_clock_changes_soc15( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges) @@ -410,7 +409,6 @@ bool dm_pp_notify_wm_clock_changes_soc15( /* TODO: to be implemented */ return false; } -#endif bool dm_pp_apply_power_level_change_request( const struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 01aaf968854d..1c1c643439b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -523,7 +523,6 @@ static void fill_plane_attributes_from_fb( surface->tiling_info.gfx8.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); -#if defined (CONFIG_DRM_AMD_DC_DCE12_0) if (adev->asic_type == CHIP_VEGA10) { /* Fill GFX9 params */ surface->tiling_info.gfx9.num_pipes = @@ -540,7 +539,6 @@ static void fill_plane_attributes_from_fb( AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); surface->tiling_info.gfx9.shaderEnable = 1; } -#endif surface->plane_size.grph.surface_size.x = 0; diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index a580cab6bf56..1a79762425ea 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -4,10 +4,7 @@ DC_LIBS = basics bios calcs dce gpio i2caux irq virtual -ifdef CONFIG_DRM_AMD_DC_DCE12_0 DC_LIBS += dce120 -endif - DC_LIBS += dce112 DC_LIBS += dce110 DC_LIBS += dce100 diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 770248429a81..a26cc605462d 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -4,9 +4,7 @@ BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o -ifdef CONFIG_DRM_AMD_DC_DCE12_0 BIOS += command_table2.o command_table_helper2.o bios_parser2.o -endif AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS)) @@ -26,6 +24,4 @@ AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o -ifdef CONFIG_DRM_AMD_DC_DCE12_0 AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper2_dce112.o -endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c index 7fe2a791ef42..0079a1e26efd 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_interface.c @@ -29,9 +29,7 @@ #include "bios_parser_interface.h" #include "bios_parser.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "bios_parser2.h" -#endif struct dc_bios *dal_bios_parser_create( @@ -40,17 +38,11 @@ struct dc_bios *dal_bios_parser_create( { struct dc_bios *bios = NULL; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bios = firmware_parser_create(init, dce_version); + /* Fall back to old bios parser for older asics */ if (bios == NULL) - /* TODO: remove dce_version from bios_parser. - * cannot remove today because dal enum to bp enum translation is dce specific - */ bios = bios_parser_create(init, dce_version); -#else - bios = bios_parser_create(init, dce_version); -#endif return bios; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index b0dcad260be6..1cc3df1d5698 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -53,11 +53,9 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCE_VERSION_11_2: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; -#endif default: /* Unsupported DCE */ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index aa98762346d2..c855e49eb116 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -50,10 +50,8 @@ static enum bw_calcs_version bw_calcs_version_from_asic_id(struct hw_asic_id asi return BW_CALCS_VERSION_POLARIS11; return BW_CALCS_VERSION_INVALID; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case FAMILY_AI: return BW_CALCS_VERSION_VEGA10; -#endif default: return BW_CALCS_VERSION_INVALID; @@ -2435,7 +2433,6 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case BW_CALCS_VERSION_VEGA10: vbios.memory_type = bw_def_hbm; vbios.dram_channel_width_in_bits = 128; @@ -2546,7 +2543,6 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; -#endif default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 28ed8eaee1ff..d6041e842347 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1815,7 +1815,6 @@ void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink } } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) { int i; @@ -1842,5 +1841,4 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) return true; } -#endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 079558ab81c0..fb48b8909e7f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -142,10 +142,8 @@ void pre_surface_trace( surface->rotation, surface->stereo_format); -#if defined (CONFIG_DRM_AMD_DC_DCE12_0) SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", surface->tiling_info.gfx9.swizzle); -#endif SURFACE_TRACE("\n"); } @@ -228,10 +226,8 @@ void update_surface_trace( update->plane_info->tiling_info.gfx8.array_mode, update->plane_info->visible); - #if defined (CONFIG_DRM_AMD_DC_DCE12_0) - SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", + SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", update->plane_info->tiling_info.gfx9.swizzle); - #endif } if (update->scaling_info) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f13da7c227f4..74dd272d7452 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1217,7 +1217,6 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); } else { -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) uint32_t dp_phyclk_in_khz; const struct clocks_value clocks_value = pipe_ctx->dis_clk->cur_clocks_value; @@ -1235,7 +1234,6 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) false, true); } -#endif } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 77ef3304d2bc..ad37d0efca2e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -39,9 +39,7 @@ #include "dce100/dce100_resource.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/dce120_resource.h" -#endif enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) { @@ -68,11 +66,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) dc_version = DCE_VERSION_11_2; } break; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case FAMILY_AI: dc_version = DCE_VERSION_12_0; break; -#endif default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -105,12 +101,10 @@ struct resource_pool *dc_create_resource_pool( res_pool = dce112_create_resource_pool( num_virtual_links, dc); break; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: res_pool = dce120_create_resource_pool( num_virtual_links, dc); break; -#endif default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bc15065e489b..106addc937ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,9 +55,7 @@ struct dc_caps { struct dc_dcc_surface_param { enum surface_pixel_format format; struct dc_size surface_size; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) enum swizzle_mode_values swizzle_mode; -#endif enum dc_scan_direction scan; }; @@ -146,9 +144,7 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool disable_pplib_clock_request; -#endif bool disable_clock_gate; bool disable_dmcu; bool force_abm_enable; @@ -163,7 +159,6 @@ struct dc { struct dc_debug debug; }; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) enum frame_buffer_mode { FRAME_BUFFER_MODE_LOCAL_ONLY = 0, FRAME_BUFFER_MODE_ZFB_ONLY, @@ -178,7 +173,6 @@ struct dchub_init_data { uint64_t zfb_size_in_byte; enum frame_buffer_mode fb_mode; }; -#endif struct dc_init_data { struct hw_asic_id asic_id; @@ -200,9 +194,7 @@ struct dc *dc_create(const struct dc_init_data *init_params); void dc_destroy(struct dc **dc); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); -#endif /******************************************************************************* * Surface Interfaces diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 63813404276d..33e3377f69fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -259,7 +259,6 @@ enum tile_mode_values { DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1, }; -#if defined (CONFIG_DRM_AMD_DC_DCE12_0) enum swizzle_mode_values { DC_SW_LINEAR = 0, DC_SW_256B_S = 1, @@ -287,7 +286,6 @@ enum swizzle_mode_values { DC_SW_VAR_R_X = 31, DC_SW_MAX }; -#endif union dc_tiling_info { @@ -353,7 +351,6 @@ union dc_tiling_info { enum array_mode_values array_mode; } gfx8; -#if defined (CONFIG_DRM_AMD_DC_DCE12_0) struct { unsigned int num_pipes; unsigned int num_banks; @@ -368,7 +365,6 @@ union dc_tiling_info { bool rb_aligned; bool pipe_aligned; } gfx9; -#endif }; /* Rotation angle */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index f53dc157db97..bd4524ef3a37 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -585,9 +585,7 @@ static uint32_t dce110_get_pix_clk_dividers( pll_settings, pix_clk_params); break; case DCE_VERSION_11_2: -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: -#endif dce112_get_pix_clk_dividers_helper(clk_src, pll_settings, pix_clk_params); break; @@ -871,9 +869,7 @@ static bool dce110_program_pix_clk( break; case DCE_VERSION_11_2: -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: -#endif if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = pll_settings->use_external_clk; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 9c743e51c091..263f8900e39c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -80,7 +80,6 @@ static struct state_dependent_clocks dce112_max_clks_by_state[] = { /*ClocksStatePerformance*/ { .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) static struct state_dependent_clocks dce120_max_clks_by_state[] = { /*ClocksStateInvalid - should not be used*/ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, @@ -92,7 +91,6 @@ static struct state_dependent_clocks dce120_max_clks_by_state[] = { { .display_clk_khz = 670000, .pixel_clk_khz = 600000 }, /*ClocksStatePerformance*/ { .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; -#endif /* Starting point for each divider range.*/ enum dce_divider_range_start { @@ -497,7 +495,6 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) } } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) static bool dce_apply_clock_voltage_request( struct display_clock *clk, enum dm_pp_clock_type clocks_type, @@ -592,7 +589,6 @@ static const struct display_clock_funcs dce120_funcs = { .apply_clock_voltage_request = dce_apply_clock_voltage_request, .set_clock = dce112_set_clock }; -#endif static const struct display_clock_funcs dce112_funcs = { .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, @@ -734,7 +730,6 @@ struct display_clock *dce112_disp_clk_create( return &clk_dce->base; } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct display_clock *dce120_disp_clk_create( struct dc_context *ctx, const struct dce_disp_clk_registers *regs, @@ -770,7 +765,6 @@ struct display_clock *dce120_disp_clk_create( return &clk_dce->base; } -#endif void dce_disp_clk_destroy(struct display_clock **disp_clk) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 18787f6d4e2a..2fd00e45395c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -45,13 +45,11 @@ CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define CLK_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ CLK_SF(DCCG_DFS_DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ CLK_SF(DCCG_DFS_DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ CLK_SF(DCCG_DFS_MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(DCCG_DFS_MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) -#endif #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ @@ -126,10 +124,8 @@ struct dce_disp_clk { int gpu_pll_ss_divider; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* max disp_clk from PPLIB for max validation display clock*/ int max_displ_clk_in_khz; -#endif }; @@ -151,13 +147,11 @@ struct display_clock *dce112_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct display_clock *dce120_disp_clk_create( struct dc_context *ctx, const struct dce_disp_clk_registers *regs, const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask); -#endif void dce_disp_clk_destroy(struct display_clock **disp_clk); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index ff7984b08095..c66585188ecd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -186,13 +186,11 @@ struct dce_hwseq_registers { HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) -#endif #define HWSEQ_REG_FIED_LIST(type) \ type DCFE_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index f6a1006a6472..25ba583dbb8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -31,12 +31,10 @@ #define TO_DCE110_LINK_ENC(link_encoder)\ container_of(link_encoder, struct dce110_link_encoder, base) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* Not found regs in dce120 spec * BIOS_SCRATCH_2 * DP_DPHY_INTERNAL_CTRL */ -#endif #define AUX_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ @@ -86,16 +84,14 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) - #define LE_DCE120_REG_LIST(id)\ - LE_COMMON_REG_LIST_BASE(id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) -#endif +#define LE_DCE120_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) - #define LE_DCE80_REG_LIST(id)\ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_COMMON_REG_LIST_BASE(id) +#define LE_DCE80_REG_LIST(id)\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + LE_COMMON_REG_LIST_BASE(id) struct dce110_link_enc_aux_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index c494f712b5b5..7acd87152811 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -187,7 +187,7 @@ static void program_nbp_watermark(struct mem_input *mi, REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, nbp_wm); } -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) + if (REG(DPG_PIPE_LOW_POWER_CONTROL)) { REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, PSTATE_CHANGE_WATERMARK_MASK, wm_select); @@ -200,7 +200,6 @@ static void program_nbp_watermark(struct mem_input *mi, REG_UPDATE(DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_WATERMARK, nbp_wm); } -#endif } static void program_stutter_watermark(struct mem_input *mi, @@ -210,12 +209,10 @@ static void program_stutter_watermark(struct mem_input *mi, REG_UPDATE(DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) if (REG(DPG_PIPE_STUTTER_CONTROL2)) REG_UPDATE(DPG_PIPE_STUTTER_CONTROL2, STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); else -#endif REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); } @@ -254,7 +251,6 @@ void dce_mem_input_program_display_marks(struct mem_input *mi, static void program_tiling(struct mem_input *mi, const union dc_tiling_info *info) { -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) if (mi->masks->GRPH_SW_MODE) { /* GFX9 */ REG_UPDATE_6(GRPH_CONTROL, GRPH_SW_MODE, info->gfx9.swizzle, @@ -268,7 +264,7 @@ static void program_tiling(struct mem_input *mi, GRPH_Z, 0); */ } -#endif + if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ REG_UPDATE_9(GRPH_CONTROL, GRPH_NUM_BANKS, info->gfx8.num_banks, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 9e18c2a34e85..6af533bdf98c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -58,14 +58,12 @@ MI_DCE11_2_REG_LIST(id),\ MI_DCE_PTE_REG_LIST(id) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define MI_DCE12_REG_LIST(id)\ MI_DCE_BASE_REG_LIST(id),\ MI_DCE_PTE_REG_LIST(id),\ SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id),\ SRI(DPG_PIPE_STUTTER_CONTROL2, DMIF_PG, id),\ SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id) -#endif struct dce_mem_input_registers { /* DCP */ @@ -172,7 +170,6 @@ struct dce_mem_input_registers { MI_DCE11_2_MASK_SH_LIST(mask_sh),\ MI_DCP_PTE_MASK_SH_LIST(mask_sh, ) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define MI_GFX9_TILE_MASK_SH_LIST(mask_sh, blk)\ SFB(blk, GRPH_CONTROL, GRPH_SW_MODE, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_SE_ENABLE, mask_sh),\ @@ -195,7 +192,6 @@ struct dce_mem_input_registers { MI_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_) -#endif #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 4784ced6fc80..03ce9ba50b64 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -107,13 +107,11 @@ enum dce110_opp_reg_type { SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \ SRI(CONTROL, FMT_MEMORY, id) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define OPP_DCE_120_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ SRI(CONTROL, FMT_MEMORY, id) -#endif #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -205,7 +203,6 @@ enum dce110_opp_reg_type { OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define OPP_COMMON_MASK_SH_LIST_DCE_120(mask_sh)\ OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ @@ -267,7 +264,6 @@ enum dce110_opp_reg_type { OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh) -#endif #define OPP_REG_FIELD_LIST(type) \ type DCP_REGAMMA_MEM_PWR_DIS; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index c784c1b961c6..c2f4050fc6dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -187,7 +187,6 @@ #define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh)\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\ SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\ @@ -267,7 +266,6 @@ SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) -#endif #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) @@ -294,7 +292,6 @@ SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define SE_COMMON_MASK_SH_LIST_DCE120(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\ @@ -307,7 +304,6 @@ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\ SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) -#endif struct dce_stream_encoder_shift { uint8_t AFMT_GENERIC_INDEX; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index aa6bc4fc80c5..da2a02434665 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -153,7 +153,6 @@ XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define XFM_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \ XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \ @@ -219,7 +218,6 @@ XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ XFM_SF(DCFE0_DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ XFM_SF(SCL0_SCL_MODE, SCL_PSCL_EN, mask_sh) -#endif #define XFM_REG_FIELD_LIST(type) \ type OUT_CLAMP_MIN_B_CB; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 66d5f346f195..cb7a673e15e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1427,8 +1427,6 @@ static void apply_min_clocks( return; } - /* TODOFPGA */ -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* TODO: This is incorrect. Figure out how to fix. */ pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( pipe_ctx->dis_clk, @@ -1451,7 +1449,6 @@ static void apply_min_clocks( pre_mode_set, false); return; -#endif } /* get the required state based on state dependent clocks: @@ -1468,7 +1465,6 @@ static void apply_min_clocks( pipe_ctx->dis_clk->funcs->set_min_clocks_state( pipe_ctx->dis_clk, *clocks_state); } else { -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( pipe_ctx->dis_clk, DM_PP_CLOCK_TYPE_DISPLAY_CLK, @@ -1489,7 +1485,6 @@ static void apply_min_clocks( req_clocks.pixel_clk_khz, pre_mode_set, false); -#endif } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index 3ffb845f843a..a20feaedfca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -409,9 +409,7 @@ static struct mem_input_funcs dce110_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) .mem_input_update_dchub = NULL -#endif }; /*****************************************/ /* Constructor, Destructor */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 55f0a94e7cae..378509b8e56c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -108,9 +108,7 @@ struct dce110_timing_generator { uint32_t min_h_front_porch; uint32_t min_h_back_porch; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* DCE 12 */ -#endif uint32_t min_h_sync_width; uint32_t min_v_sync_width; uint32_t min_v_blank; diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 9a1984b36592..efa58889058b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -909,6 +909,7 @@ static bool construct( { unsigned int i; struct dc_context *ctx = dc->ctx; + struct irq_service_init_data irq_init_data; ctx->dc_bios->regs = &bios_regs; @@ -997,15 +998,10 @@ static bool construct( goto res_create_fail; } - { - #if defined(CONFIG_DRM_AMD_DC_DCE12_0) - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce120_create(&init_data); - if (!pool->base.irqs) - goto irqs_create_fail; - #endif - } + irq_init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data); + if (!pool->base.irqs) + goto irqs_create_fail; for (i = 0; i < pool->base.pipe_count; i++) { pool->base.timing_generators[i] = diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c index 2f22931f457b..ebb8df3cdf4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -54,9 +54,7 @@ static struct mem_input_funcs dce80_mem_input_funcs = { dce_mem_input_program_surface_config, .mem_input_is_flip_pending = dce110_mem_input_is_flip_pending, -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) .mem_input_update_dchub = NULL -#endif }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index bdc7cb045eed..cf6ecfcadd5e 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -192,7 +192,6 @@ unsigned int generic_reg_wait(const struct dc_context *ctx, unsigned int delay_between_poll_us, unsigned int time_out_num_tries, const char *func_name); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) /* These macros need to be used with soc15 registers in order to retrieve * the actual offset. @@ -274,7 +273,6 @@ static inline bool wait_reg_func( 20000,\ 200000) -#endif /************************************** * Power Play (PP) interfaces **************************************/ @@ -337,11 +335,9 @@ bool dm_pp_notify_wm_clock_changes( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool dm_pp_notify_wm_clock_changes_soc15( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); -#endif /* DAL calls this function to notify PP about completion of Mode Set. * For PP it means that current DCE clocks are those which were returned diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 8d2661583f21..c631dec489e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -141,7 +141,6 @@ struct dm_pp_wm_sets_with_clock_ranges { struct dm_pp_clock_range_for_wm_set wm_clk_ranges[MAX_WM_SETS]; }; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct dm_pp_clock_range_for_dmif_wm_set_soc15 { enum dm_pp_wm_set_id wm_set_id; uint32_t wm_min_dcfclk_clk_in_khz; @@ -166,7 +165,6 @@ struct dm_pp_wm_sets_with_clock_ranges_soc15 { struct dm_pp_clock_range_for_mcif_wm_set_soc15 wm_mcif_clocks_ranges[MAX_WM_SETS]; }; -#endif #define MAX_DISPLAY_CONFIGS 6 diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index 8cf12a8ca28f..5e831aff4830 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -31,13 +31,11 @@ AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE110) ############################################################################### # DCE 12x ############################################################################### -ifdef CONFIG_DRM_AMD_DC_DCE12_0 GPIO_DCE120 = hw_translate_dce120.o hw_factory_dce120.o AMD_DAL_GPIO_DCE120 = $(addprefix $(AMDDALPATH)/dc/gpio/dce120/,$(GPIO_DCE120)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE120) -endif ############################################################################### # Diagnostics on FPGA diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 66ea3b31b980..29ba83d2c211 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -44,9 +44,7 @@ #include "dce110/hw_factory_dce110.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/hw_factory_dce120.h" -#endif #include "diagnostics/hw_factory_diag.h" @@ -76,11 +74,9 @@ bool dal_hw_factory_init( case DCE_VERSION_11_2: dal_hw_factory_dce110_init(factory); return true; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: dal_hw_factory_dce120_init(factory); return true; -#endif default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 10e86447f179..872edda54536 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -42,9 +42,7 @@ #include "dce80/hw_translate_dce80.h" #include "dce110/hw_translate_dce110.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/hw_translate_dce120.h" -#endif #include "diagnostics/hw_translate_diag.h" /* @@ -70,11 +68,9 @@ bool dal_hw_translate_init( case DCE_VERSION_11_2: dal_hw_translate_dce110_init(translate); return true; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: dal_hw_translate_dce120_init(translate); return true; -#endif default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile index 99aa5d8fb9a7..a636768d06d5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -50,13 +50,11 @@ AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) ############################################################################### # DCE 120 family ############################################################################### -ifdef CONFIG_DRM_AMD_DC_DCE12_0 I2CAUX_DCE120 = i2caux_dce120.o AMD_DAL_I2CAUX_DCE120 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce120/,$(I2CAUX_DCE120)) AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE120) -endif ############################################################################### # Diagnostics on FPGA diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index ea3bd75e0555..bd84b932aaae 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -57,9 +57,7 @@ #include "dce112/i2caux_dce112.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/i2caux_dce120.h" -#endif #include "diagnostics/i2caux_diag.h" @@ -84,10 +82,8 @@ struct i2caux *dal_i2caux_create( return dal_i2caux_dce110_create(ctx); case DCE_VERSION_10_0: return dal_i2caux_dce100_create(ctx); - #if defined(CONFIG_DRM_AMD_DC_DCE12_0) case DCE_VERSION_12_0: return dal_i2caux_dce120_create(ctx); - #endif default: BREAK_TO_DEBUGGER(); return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h index a7eaecd32aea..81fab9ef3637 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h @@ -40,9 +40,7 @@ enum bw_calcs_version { BW_CALCS_VERSION_POLARIS10, BW_CALCS_VERSION_POLARIS11, BW_CALCS_VERSION_STONEY, -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) BW_CALCS_VERSION_VEGA10 -#endif }; /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index bf77aa6172e1..79aa75c150ec 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -28,7 +28,6 @@ #include "dm_services_types.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct clocks_value { int dispclk_in_khz; int max_pixelclk_in_khz; @@ -38,7 +37,6 @@ struct clocks_value { bool pixelclk_notify_pplib_done; bool phyclk_notigy_pplib_done; }; -#endif /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ @@ -53,9 +51,7 @@ struct display_clock { enum dm_pp_clocks_state max_clks_state; enum dm_pp_clocks_state cur_min_clks_state; -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) struct clocks_value cur_clocks_value; -#endif }; struct display_clock_funcs { @@ -71,14 +67,12 @@ struct display_clock_funcs { int (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) bool (*apply_clock_voltage_request)( struct display_clock *disp_clk, enum dm_pp_clock_type clocks_type, int clocks_in_khz, bool pre_mode_set, bool update_dp_phyclk); -#endif }; #endif /* __DISPLAY_CLOCK_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 6c0600696d02..7ec4027700d8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -100,10 +100,8 @@ struct mem_input_funcs { bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) void (*mem_input_update_dchub)(struct mem_input *mem_input, struct dchub_init_data *dh_data); -#endif }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 140e49811dd1..222f36e3074f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -30,11 +30,9 @@ AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE11) ############################################################################### # DCE 12x ############################################################################### -ifdef CONFIG_DRM_AMD_DC_DCE12_0 IRQ_DCE12 = irq_service_dce120.o AMD_DAL_IRQ_DCE12 = $(addprefix $(AMDDALPATH)/dc/irq/dce120/,$(IRQ_DCE12)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE12) -endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index a1b6d83b1cbb..5255c14254df 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -33,9 +33,7 @@ #include "dce80/irq_service_dce80.h" -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #include "dce120/irq_service_dce120.h" -#endif #include "reg_helper.h" #include "irq_service.h" diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 15c0b8c14b30..6dab058f8f3c 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -123,9 +123,7 @@ #define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */ #define FAMILY_CZ 135 /* Carrizo */ -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) #define FAMILY_AI 141 -#endif #define FAMILY_UNKNOWN 0xFF diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index e24c1ef58d2f..0cefde14aa02 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -38,9 +38,7 @@ enum dce_version { DCE_VERSION_10_0, DCE_VERSION_11_0, DCE_VERSION_11_2, -#if defined(CONFIG_DRM_AMD_DC_DCE12_0) DCE_VERSION_12_0, -#endif DCE_VERSION_MAX, }; -- GitLab From ab587d4a654ea299bef20bf3d363f7faaea35e7d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Apr 2017 17:28:47 -0400 Subject: [PATCH 0321/2898] drm/amdgpu/soc15: enable dc on vega10 Add the DC display module to drive the DCE12 IP on vega10. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 245a18aeb389..3d9a51d6e1aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -535,6 +535,12 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#else +# warning "Enable CONFIG_DRM_AMD_DC for display support on SOC15." +#endif amdgpu_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_ip_block_add(adev, &sdma_v4_0_ip_block); amdgpu_ip_block_add(adev, &uvd_v7_0_ip_block); -- GitLab From a783e7b5182ba5df2916c7abda60b8e781bdb3aa Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Thu, 9 Mar 2017 14:38:15 -0500 Subject: [PATCH 0322/2898] drm/amd/display: adding new dc_update_surfaces_and_stream Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 +++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 29 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d6041e842347..228ef6b310e0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1268,6 +1268,27 @@ enum surface_update_type dc_check_update_surfaces_for_stream( return overall_type; } +void dc_update_surfaces_and_stream(struct dc *dc, + struct dc_surface_update *surface_updates, int surface_count, + const struct dc_stream *dc_stream, + struct dc_stream_update *stream_update) +{ + const struct dc_stream_status *stream_status; + + stream_status = dc_stream_get_status(dc_stream); + ASSERT(stream_status); + if (!stream_status) + return; /* Cannot update stream that is not committed */ + + if (stream_update) { + dc->stream_funcs.stream_update_scaling(dc, dc_stream, + &stream_update->src, &stream_update->dst); + } + + dc_update_surfaces_for_stream(dc, surface_updates, + surface_count, dc_stream); +} + enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_surfaces_for_stream(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 106addc937ca..b1bff597c0f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -433,6 +433,35 @@ struct dc_stream { /* TODO: CEA VIC */ }; +struct dc_stream_update { + + struct rect src; + + struct rect dst; + +}; + + +/* + * Setup stream attributes if no stream updates are provided + * there will be no impact on the stream parameters + * + * Set up surface attributes and associate to a stream + * The surfaces parameter is an absolute set of all surface active for the stream. + * If no surfaces are provided, the stream will be blanked; no memory read. + * Any flip related attribute changes must be done through this interface. + * + * After this call: + * Surfaces attributes are programmed and configured to be composed into stream. + * This does not trigger a flip. No surface address is programmed. + * + */ + +void dc_update_surfaces_and_stream(struct dc *dc, + struct dc_surface_update *surface_updates, int surface_count, + const struct dc_stream *dc_stream, + struct dc_stream_update *stream_update); + /* * Log the current stream state. */ -- GitLab From 1de8c33bbde4115561a5b2e684be7af66b3f085d Mon Sep 17 00:00:00 2001 From: Logatharshan Thothiralingam Date: Thu, 9 Mar 2017 11:37:26 -0500 Subject: [PATCH 0323/2898] drm/amd/display: Fixed bandwidth calculation error when converting fractions [Problem] VSR greyed out [Root cause] When converting fractions, we were using the integer function, which let to a large display clock and the view was not supported [Solution] Change the integer to fraction functions Signed-off-by: Logatharshan Thothiralingam Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index c855e49eb116..e47794398942 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -796,11 +796,11 @@ static void calculate_bandwidth( } else if (bw_leq(data->vsr[i], bw_int_to_fixed(1))) { data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_int_to_fixed(1); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(4 / 3))) { + } else if (bw_leq(data->vsr[i], + bw_frc_to_fixed(4, 3))) { data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(4), bw_int_to_fixed(3)); - } - else if (bw_leq(data->vsr[i], bw_int_to_fixed(6 / 4))) { + } else if (bw_leq(data->vsr[i], + bw_frc_to_fixed(6, 4))) { data->lb_lines_in_per_line_out_in_middle_of_frame[i] = bw_div(bw_int_to_fixed(6), bw_int_to_fixed(4)); } else if (bw_leq(data->vsr[i], bw_int_to_fixed(2))) { -- GitLab From faddcb360c04f007966ffe8eabe3786655ba6a1a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 14 Mar 2017 11:16:11 -0400 Subject: [PATCH 0324/2898] drm/amd/display: fix bw calc internal initialization error Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index e47794398942..4820660f51d6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -1341,12 +1341,12 @@ static void calculate_bandwidth( /*initialize variables*/ number_of_displays_enabled = 0; number_of_displays_enabled_with_margin = 0; - for (k = 0; k < maximum_number_of_surfaces; k++) { + for (k = 0; k <= maximum_number_of_surfaces - 1; k++) { if (data->enable[k]) { number_of_displays_enabled = number_of_displays_enabled + 1; } + data->display_pstate_change_enable[k] = 0; } - data->display_pstate_change_enable[maximum_number_of_surfaces - 1] = 0; for (i = 0; i <= 2; i++) { for (j = 0; j <= 7; j++) { data->min_dram_speed_change_margin[i][j] = bw_int_to_fixed(9999); -- GitLab From ee8f63e1781eb3e4acdcff5324ca29b723aded45 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Tue, 14 Mar 2017 11:54:31 -0400 Subject: [PATCH 0325/2898] drm/amd/display: changing the dc_update_surfaces_and_stream 1. Adding the ability to update the stream parameters during FULL_UPDATE type Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 129 +++++++++++------------ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 228ef6b310e0..26f227ddd025 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1245,6 +1245,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, struct dc_surface_update *updates, int surface_count, + struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1254,6 +1255,9 @@ enum surface_update_type dc_check_update_surfaces_for_stream( if (stream_status->surface_count != surface_count) return UPDATE_TYPE_FULL; + if (stream_update) + return UPDATE_TYPE_FULL; + for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = det_surface_update(core_dc, &updates[i]); @@ -1268,39 +1272,27 @@ enum surface_update_type dc_check_update_surfaces_for_stream( return overall_type; } -void dc_update_surfaces_and_stream(struct dc *dc, +void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *surface_updates, int surface_count, - const struct dc_stream *dc_stream, - struct dc_stream_update *stream_update) + const struct dc_stream *dc_stream) { - const struct dc_stream_status *stream_status; - - stream_status = dc_stream_get_status(dc_stream); - ASSERT(stream_status); - if (!stream_status) - return; /* Cannot update stream that is not committed */ - - if (stream_update) { - dc->stream_funcs.stream_update_scaling(dc, dc_stream, - &stream_update->src, &stream_update->dst); - } - - dc_update_surfaces_for_stream(dc, surface_updates, - surface_count, dc_stream); + dc_update_surfaces_and_stream(dc, surface_updates, surface_count, + dc_stream, NULL); } enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; -void dc_update_surfaces_for_stream(struct dc *dc, - struct dc_surface_update *updates, int surface_count, - const struct dc_stream *dc_stream) +void dc_update_surfaces_and_stream(struct dc *dc, + struct dc_surface_update *srf_updates, int surface_count, + const struct dc_stream *dc_stream, + struct dc_stream_update *stream_update) { struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context; int i, j; - enum surface_update_type update_type; const struct dc_stream_status *stream_status; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); @@ -1308,16 +1300,16 @@ void dc_update_surfaces_for_stream(struct dc *dc, return; /* Cannot commit surface to stream that is not committed */ update_type = dc_check_update_surfaces_for_stream( - dc, updates, surface_count, stream_status); + dc, srf_updates, surface_count, stream_update, stream_status); if (update_type >= update_surface_trace_level) - update_surface_trace(dc, updates, surface_count); + update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; for (i = 0; i < surface_count; i++) - new_surfaces[i] = updates[i].surface; + new_surfaces[i] = srf_updates[i].surface; /* initialize scratch memory for building context */ context = core_dc->temp_flip_context; @@ -1333,47 +1325,54 @@ void dc_update_surfaces_for_stream(struct dc *dc, } else { context = core_dc->current_context; } + + /* update current stream with the new updates */ + if (stream_update) { + stream->public.src = stream_update->src; + stream->public.dst = stream_update->dst; + } + + /* save update parameters into surface */ for (i = 0; i < surface_count; i++) { - /* save update param into surface */ - struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct core_surface *surface = + DC_SURFACE_TO_CORE(srf_updates[i].surface); - if (updates[i].flip_addr) { - surface->public.address = updates[i].flip_addr->address; + if (srf_updates[i].flip_addr) { + surface->public.address = srf_updates[i].flip_addr->address; surface->public.flip_immediate = - updates[i].flip_addr->flip_immediate; + srf_updates[i].flip_addr->flip_immediate; } - if (updates[i].scaling_info) { + if (srf_updates[i].scaling_info) { surface->public.scaling_quality = - updates[i].scaling_info->scaling_quality; + srf_updates[i].scaling_info->scaling_quality; surface->public.dst_rect = - updates[i].scaling_info->dst_rect; + srf_updates[i].scaling_info->dst_rect; surface->public.src_rect = - updates[i].scaling_info->src_rect; + srf_updates[i].scaling_info->src_rect; surface->public.clip_rect = - updates[i].scaling_info->clip_rect; + srf_updates[i].scaling_info->clip_rect; } - if (updates[i].plane_info) { + if (srf_updates[i].plane_info) { surface->public.color_space = - updates[i].plane_info->color_space; + srf_updates[i].plane_info->color_space; surface->public.format = - updates[i].plane_info->format; + srf_updates[i].plane_info->format; surface->public.plane_size = - updates[i].plane_info->plane_size; + srf_updates[i].plane_info->plane_size; surface->public.rotation = - updates[i].plane_info->rotation; + srf_updates[i].plane_info->rotation; surface->public.horizontal_mirror = - updates[i].plane_info->horizontal_mirror; + srf_updates[i].plane_info->horizontal_mirror; surface->public.stereo_format = - updates[i].plane_info->stereo_format; + srf_updates[i].plane_info->stereo_format; surface->public.tiling_info = - updates[i].plane_info->tiling_info; + srf_updates[i].plane_info->tiling_info; surface->public.visible = - updates[i].plane_info->visible; + srf_updates[i].plane_info->visible; surface->public.dcc = - updates[i].plane_info->dcc; + srf_updates[i].plane_info->dcc; } /* not sure if we still need this */ @@ -1388,40 +1387,40 @@ void dc_update_surfaces_for_stream(struct dc *dc, } } - if (updates[i].gamma && - updates[i].gamma != surface->public.gamma_correction) { + if (srf_updates[i].gamma && + srf_updates[i].gamma != surface->public.gamma_correction) { if (surface->public.gamma_correction != NULL) dc_gamma_release(&surface->public. gamma_correction); - dc_gamma_retain(updates[i].gamma); + dc_gamma_retain(srf_updates[i].gamma); surface->public.gamma_correction = - updates[i].gamma; + srf_updates[i].gamma; } - if (updates[i].in_transfer_func && - updates[i].in_transfer_func != surface->public.in_transfer_func) { + if (srf_updates[i].in_transfer_func && + srf_updates[i].in_transfer_func != surface->public.in_transfer_func) { if (surface->public.in_transfer_func != NULL) dc_transfer_func_release( surface->public. in_transfer_func); dc_transfer_func_retain( - updates[i].in_transfer_func); + srf_updates[i].in_transfer_func); surface->public.in_transfer_func = - updates[i].in_transfer_func; + srf_updates[i].in_transfer_func; } - if (updates[i].out_transfer_func && - updates[i].out_transfer_func != dc_stream->out_transfer_func) { + if (srf_updates[i].out_transfer_func && + srf_updates[i].out_transfer_func != dc_stream->out_transfer_func) { if (dc_stream->out_transfer_func != NULL) dc_transfer_func_release(dc_stream->out_transfer_func); - dc_transfer_func_retain(updates[i].out_transfer_func); - stream->public.out_transfer_func = updates[i].out_transfer_func; + dc_transfer_func_retain(srf_updates[i].out_transfer_func); + stream->public.out_transfer_func = srf_updates[i].out_transfer_func; } - if (updates[i].hdr_static_metadata) + if (srf_updates[i].hdr_static_metadata) surface->public.hdr_static_ctx = - *(updates[i].hdr_static_metadata); + *(srf_updates[i].hdr_static_metadata); } if (update_type == UPDATE_TYPE_FULL && @@ -1434,7 +1433,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface); + struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1460,7 +1459,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, true); } - if (updates[i].flip_addr) + if (srf_updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); if (update_type == UPDATE_TYPE_FAST) @@ -1471,18 +1470,18 @@ void dc_update_surfaces_for_stream(struct dc *dc, is_new_pipe_surface = false; if (is_new_pipe_surface || - updates[i].in_transfer_func) + srf_updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); if (is_new_pipe_surface || - updates[i].out_transfer_func) + srf_updates[i].out_transfer_func) core_dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->surface, pipe_ctx->stream); - if (updates[i].hdr_static_metadata) { + if (srf_updates[i].hdr_static_metadata) { resource_build_info_frame(pipe_ctx); core_dc->hwss.update_info_frame(pipe_ctx); } @@ -1493,7 +1492,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; for (j = 0; j < surface_count; j++) { - if (updates[j].surface == &pipe_ctx->surface->public) { + if (srf_updates[j].surface == &pipe_ctx->surface->public) { if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( core_dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b1bff597c0f7..8b033ba5df6e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -556,6 +556,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, struct dc_surface_update *updates, int surface_count, + struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status); /******************************************************************************* -- GitLab From cc04bf7e4f87730a35b14056e23852e010f079ff Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 14 Mar 2017 01:40:53 -0400 Subject: [PATCH 0326/2898] drm/amd/display: use extended receiver cap for dpcd ver Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 80002795adc2..282bb59ea2f3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2081,9 +2081,6 @@ static void retrieve_link_cap(struct core_link *link) dpcd_data, sizeof(dpcd_data)); - link->dpcd_caps.dpcd_rev.raw = - dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; - { union training_aux_rd_interval aux_rd_interval; @@ -2099,6 +2096,9 @@ static void retrieve_link_cap(struct core_link *link) } } + link->dpcd_caps.dpcd_rev.raw = + dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; + ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT - DP_DPCD_REV]; -- GitLab From 745cc746da42a3a8a48fb7a6b8c4ee2c3f2cdf8b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 14 Mar 2017 12:30:29 -0400 Subject: [PATCH 0327/2898] drm/amd/display: remove dc_pre_update_surfaces_to_stream from dc use Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 115 ++---------------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- .../display/dc/dce110/dce110_hw_sequencer.c | 45 ------- .../amd/display/dc/dce110/dce110_resource.c | 48 +++++++- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 - 6 files changed, 54 insertions(+), 169 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 26f227ddd025..6409d4d1d7f8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -900,106 +900,7 @@ bool dc_pre_update_surfaces_to_stream( uint8_t new_surface_count, const struct dc_stream *dc_stream) { - int i, j; - struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_stream_status *stream_status = NULL; - struct validate_context *context; - bool ret = true; - - pre_surface_trace(dc, new_surfaces, new_surface_count); - - if (core_dc->current_context->stream_count == 0) - return false; - - /* Cannot commit surface to a stream that is not commited */ - for (i = 0; i < core_dc->current_context->stream_count; i++) - if (dc_stream == &core_dc->current_context->streams[i]->public) - break; - - if (i == core_dc->current_context->stream_count) - return false; - - stream_status = &core_dc->current_context->stream_status[i]; - - if (new_surface_count == stream_status->surface_count) { - bool skip_pre = true; - - for (i = 0; i < stream_status->surface_count; i++) { - struct dc_surface temp_surf = { 0 }; - - temp_surf = *stream_status->surfaces[i]; - temp_surf.clip_rect = new_surfaces[i]->clip_rect; - temp_surf.dst_rect.x = new_surfaces[i]->dst_rect.x; - temp_surf.dst_rect.y = new_surfaces[i]->dst_rect.y; - - if (memcmp(&temp_surf, new_surfaces[i], sizeof(temp_surf)) != 0) { - skip_pre = false; - break; - } - } - - if (skip_pre) - return true; - } - - context = dm_alloc(sizeof(struct validate_context)); - - if (!context) { - dm_error("%s: failed to create validate ctx\n", __func__); - ret = false; - goto val_ctx_fail; - } - - resource_validate_ctx_copy_construct(core_dc->current_context, context); - - dm_logger_write(core_dc->ctx->logger, LOG_DC, - "%s: commit %d surfaces to stream 0x%x\n", - __func__, - new_surface_count, - dc_stream); - - if (!resource_attach_surfaces_to_context( - new_surfaces, new_surface_count, dc_stream, context)) { - BREAK_TO_DEBUGGER(); - ret = false; - goto unexpected_fail; - } - - for (i = 0; i < new_surface_count; i++) - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - if (context->res_ctx.pipe_ctx[j].surface != - DC_SURFACE_TO_CORE(new_surfaces[i])) - continue; - - resource_build_scaling_params(&context->res_ctx.pipe_ctx[j]); - } - - if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { - BREAK_TO_DEBUGGER(); - ret = false; - goto unexpected_fail; - } - - core_dc->hwss.set_bandwidth(core_dc, context, false); - - for (i = 0; i < new_surface_count; i++) - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { - if (context->res_ctx.pipe_ctx[j].surface != - DC_SURFACE_TO_CORE(new_surfaces[i])) - continue; - - core_dc->hwss.prepare_pipe_for_context( - core_dc, - &context->res_ctx.pipe_ctx[j], - context); - } - -unexpected_fail: - resource_validate_ctx_destruct(context); - dm_free(context); -val_ctx_fail: - - return ret; + return true; } bool dc_post_update_surfaces_to_stream(struct dc *dc) @@ -1050,10 +951,6 @@ bool dc_commit_surfaces_to_stream( struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; - if (!dc_pre_update_surfaces_to_stream( - dc, new_surfaces, new_surface_count, dc_stream)) - return false; - memset(updates, 0, sizeof(updates)); memset(flip_addr, 0, sizeof(flip_addr)); memset(plane_info, 0, sizeof(plane_info)); @@ -1423,10 +1320,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, *(srf_updates[i].hdr_static_metadata); } - if (update_type == UPDATE_TYPE_FULL && - !core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { - BREAK_TO_DEBUGGER(); - return; + if (update_type == UPDATE_TYPE_FULL) { + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + BREAK_TO_DEBUGGER(); + return; + } else + core_dc->hwss.set_bandwidth(core_dc, context, false); } if (!surface_count) /* reset */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ad37d0efca2e..6700d6b27a8a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -900,10 +900,11 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( * that has no surface attached yet */ static struct pipe_ctx *acquire_free_pipe_for_stream( - struct resource_context *res_ctx, + struct validate_context *context, const struct dc_stream *dc_stream) { int i; + struct resource_context *res_ctx = &context->res_ctx; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct pipe_ctx *head_pipe = NULL; @@ -934,7 +935,7 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer) return NULL; - return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream); + return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(context, stream); } @@ -1001,8 +1002,7 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); - struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( - &context->res_ctx, dc_stream); + struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(context, dc_stream); if (!free_pipe) { stream_status->surfaces[i] = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index cb7a673e15e9..e5e52c705954 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2094,50 +2094,6 @@ static void init_hw(struct core_dc *dc) } } -static void dce110_power_on_pipe_if_needed( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; - struct dc_bios *dcb = dc->ctx->dc_bios; - struct tg_color black_color = {0}; - - if (!old_pipe_ctx->stream && pipe_ctx->stream) { - dc->hwss.enable_display_power_gating( - dc, - pipe_ctx->pipe_idx, - dcb, PIPE_GATING_CONTROL_DISABLE); - - /* - * This is for powering on underlay, so crtc does not - * need to be enabled - */ - - pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, - &pipe_ctx->stream->public.timing, - false); - - pipe_ctx->tg->funcs->enable_advanced_request( - pipe_ctx->tg, - true, - &pipe_ctx->stream->public.timing); - - pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, - pipe_ctx->stream->public.timing.h_total, - pipe_ctx->stream->public.timing.v_total, - pipe_ctx->stream->public.timing.pix_clk_khz, - context->stream_count); - - /* TODO unhardcode*/ - color_space_to_black_color(dc, - COLOR_SPACE_YCBCR601, &black_color); - pipe_ctx->tg->funcs->set_blank_color( - pipe_ctx->tg, - &black_color); - } -} - static void fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg) @@ -2481,7 +2437,6 @@ static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) static const struct hw_sequencer_funcs dce110_funcs = { .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, - .prepare_pipe_for_context = dce110_power_on_pipe_if_needed, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index b9d0b5eeca13..e3002031c40d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1111,16 +1111,17 @@ enum dc_status dce110_validate_guaranteed( return result; } -static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer( - struct resource_context *res_ctx, +static struct pipe_ctx *dce110_acquire_underlay( + struct validate_context *context, struct core_stream *stream) { + struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); + struct resource_context *res_ctx = &context->res_ctx; unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; - if (res_ctx->pipe_ctx[underlay_idx].stream) { + if (res_ctx->pipe_ctx[underlay_idx].stream) return NULL; - } pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx]; pipe_ctx->mi = res_ctx->pool->mis[underlay_idx]; @@ -1132,8 +1133,43 @@ static struct pipe_ctx *dce110_acquire_idle_pipe_for_layer( pipe_ctx->stream = stream; - return pipe_ctx; + if (!dc->current_context->res_ctx.pipe_ctx[underlay_idx].stream) { + struct tg_color black_color = {0}; + struct dc_bios *dcb = dc->ctx->dc_bios; + + dc->hwss.enable_display_power_gating( + dc, + pipe_ctx->pipe_idx, + dcb, PIPE_GATING_CONTROL_DISABLE); + + /* + * This is for powering on underlay, so crtc does not + * need to be enabled + */ + + pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, + &stream->public.timing, + false); + + pipe_ctx->tg->funcs->enable_advanced_request( + pipe_ctx->tg, + true, + &stream->public.timing); + + pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, + stream->public.timing.h_total, + stream->public.timing.v_total, + stream->public.timing.pix_clk_khz, + context->stream_count); + + color_space_to_black_color(dc, + COLOR_SPACE_YCBCR601, &black_color); + pipe_ctx->tg->funcs->set_blank_color( + pipe_ctx->tg, + &black_color); + } + return pipe_ctx; } static void dce110_destroy_resource_pool(struct resource_pool **pool) @@ -1152,7 +1188,7 @@ static const struct resource_funcs dce110_res_pool_funcs = { .validate_with_context = dce110_validate_with_context, .validate_guaranteed = dce110_validate_guaranteed, .validate_bandwidth = dce110_validate_bandwidth, - .acquire_idle_pipe_for_layer = dce110_acquire_idle_pipe_for_layer, + .acquire_idle_pipe_for_layer = dce110_acquire_underlay, .build_bit_depth_reduction_params = dce110_resource_build_bit_depth_reduction_params }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index faec2292cc27..7f3c6da1ebd7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -210,7 +210,7 @@ struct resource_funcs { struct validate_context *context); struct pipe_ctx *(*acquire_idle_pipe_for_layer)( - struct resource_context *res_ctx, + struct validate_context *context, struct core_stream *stream); void (*build_bit_depth_reduction_params)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 98a04cd46178..bcb267295cb9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -57,11 +57,6 @@ struct hw_sequencer_funcs { void (*reset_hw_ctx_wrap)( struct core_dc *dc, struct validate_context *context); - void (*prepare_pipe_for_context)( - struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context); - void (*apply_ctx_for_surface)( struct core_dc *dc, struct core_surface *surface, -- GitLab From e73c1efca8c5fd4a53f6d725fc6ca18c65570d37 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 14 Mar 2017 16:41:50 -0400 Subject: [PATCH 0328/2898] drm/amd/display: Use stream_enc to get head pipe. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6700d6b27a8a..9f624e84f59b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -887,7 +887,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( int i; for (i = 0; i < res_ctx->pool->pipe_count; i++) { if (res_ctx->pipe_ctx[i].stream == stream && - !res_ctx->pipe_ctx[i].top_pipe) { + res_ctx->pipe_ctx[i].stream_enc) { return &res_ctx->pipe_ctx[i]; break; } -- GitLab From 3f8a944016674bdc64a4307a6898c3d919eb8768 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 14 Mar 2017 16:30:06 -0400 Subject: [PATCH 0329/2898] drm/amd/display: support CP2520 pattern 2 for HBR2 compliance - also some clean up Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_link_encoder.c | 149 +++++++----------- .../drm/amd/display/dc/dce/dce_link_encoder.h | 10 +- .../amd/display/dc/dce100/dce100_resource.c | 2 +- 3 files changed, 66 insertions(+), 95 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index a1d35ad85605..65cc64a17f41 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -169,9 +169,6 @@ static void disable_prbs_symbols( static void disable_prbs_mode( struct dce110_link_encoder *enc110) { - /* This register resides in DP back end block; - * transmitter is used for the offset */ - REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0); } @@ -216,9 +213,7 @@ static void set_dp_phy_pattern_d102( disable_prbs_symbols(enc110, true); - /* Disable PRBS mode, - * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - + /* Disable PRBS mode */ disable_prbs_mode(enc110); /* Program debug symbols to be output */ @@ -264,43 +259,54 @@ void dce110_link_encoder_set_dp_phy_pattern_training_pattern( enable_phy_bypass_mode(enc110, false); - /* Disable PRBS mode, - * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - + /* Disable PRBS mode */ disable_prbs_mode(enc110); } +static void setup_panel_mode( + struct dce110_link_encoder *enc110, + enum dp_panel_mode panel_mode) +{ + uint32_t value; + + ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); + value = REG_READ(DP_DPHY_INTERNAL_CTRL); + + switch (panel_mode) { + case DP_PANEL_MODE_EDP: + value = 0x1; + break; + case DP_PANEL_MODE_SPECIAL: + value = 0x11; + break; + default: + value = 0x0; + break; + } + + REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); +} + static void set_dp_phy_pattern_symbol_error( struct dce110_link_encoder *enc110) { /* Disable PHY Bypass mode to setup the test pattern */ - uint32_t value = 0x0; - enable_phy_bypass_mode(enc110, false); /* program correct panel mode*/ - { - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); - /*DCE 120 does not have this reg*/ - - REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); - } + setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT); /* A PRBS23 pattern is used for most DP electrical measurements. */ /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(enc110, false); /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */ - { - REG_UPDATE_2(DP_DPHY_PRBS_CNTL, - DPHY_PRBS_SEL, 1, - DPHY_PRBS_EN, 1); - } + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 1, + DPHY_PRBS_EN, 1); /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(enc110, true); } @@ -308,24 +314,19 @@ static void set_dp_phy_pattern_prbs7( struct dce110_link_encoder *enc110) { /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc110, false); /* A PRBS7 pattern is used for most DP electrical measurements. */ /* Enable PRBS symbols on the lanes */ - disable_prbs_symbols(enc110, false); /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */ - { - REG_UPDATE_2(DP_DPHY_PRBS_CNTL, - DPHY_PRBS_SEL, 0, - DPHY_PRBS_EN, 1); - } + REG_UPDATE_2(DP_DPHY_PRBS_CNTL, + DPHY_PRBS_SEL, 0, + DPHY_PRBS_EN, 1); /* Enable phy bypass mode to enable the test pattern */ - enable_phy_bypass_mode(enc110, true); } @@ -374,7 +375,7 @@ static void set_dp_phy_pattern_80bit_custom( enable_phy_bypass_mode(enc110, true); } -static void set_dp_phy_pattern_hbr2_compliance( +static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( struct dce110_link_encoder *enc110) { @@ -391,56 +392,34 @@ static void set_dp_phy_pattern_hbr2_compliance( enable_phy_bypass_mode(enc110, false); /* Setup DIG encoder in DP SST mode */ - enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT); - /* program correct panel mode*/ - { - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); - - REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0x0); - } + /* ensure normal panel mode. */ + setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT); /* no vbid after BS (SR) * DP_LINK_FRAMING_CNTL changed history Sandra Liu * 11000260 / 11000104 / 110000FC */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0xFC, + DP_VBID_DISABLE, 1, + DP_VID_ENHANCED_FRAME_MODE, 1); - /* TODO DP_LINK_FRAMING_CNTL should always use hardware default value - * output except output hbr2_compliance pattern for physical PHY - * measurement. This is not normal usage case. SW should reset this - * register to hardware default value after end use of HBR2 eye - */ - BREAK_TO_DEBUGGER(); - /* TODO: do we still need this, find out at compliance test - addr = mmDP_LINK_FRAMING_CNTL + fe_addr_offset; - - value = dal_read_reg(ctx, addr); - - set_reg_field_value(value, 0xFC, - DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL); - set_reg_field_value(value, 1, - DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE); - set_reg_field_value(value, 1, - DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE); - - dal_write_reg(ctx, addr, value); - */ /* swap every BS with SR */ - REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); - /*TODO add support for this test pattern - * support_dp_hbr2_eye_pattern - */ + /* select cp2520 pattern 2 */ + if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) + REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, + DP_DPHY_HBR2_PATTERN_CONTROL, 0x2); /* set link training complete */ set_link_training_complete(enc110, true); - /* do not enable video stream */ + /* disable video stream */ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc110, false); } @@ -448,41 +427,26 @@ static void set_dp_phy_pattern_passthrough_mode( struct dce110_link_encoder *enc110, enum dp_panel_mode panel_mode) { - uint32_t value; - /* program correct panel mode */ - { - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); - value = REG_READ(DP_DPHY_INTERNAL_CTRL); + setup_panel_mode(enc110, panel_mode); - switch (panel_mode) { - case DP_PANEL_MODE_EDP: - value = 0x1; - break; - case DP_PANEL_MODE_SPECIAL: - value = 0x11; - break; - default: - value = 0x0; - break; - } - - REG_WRITE(DP_DPHY_INTERNAL_CTRL, value); - } + /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT + * in case we were doing HBR2 compliance pattern before + */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0x2000, + DP_VBID_DISABLE, 0, + DP_VID_ENHANCED_FRAME_MODE, 1); REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF); /* set link training complete */ - set_link_training_complete(enc110, true); /* Disable PHY Bypass mode to setup the test pattern */ - enable_phy_bypass_mode(enc110, false); - /* Disable PRBS mode, - * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */ - + /* Disable PRBS mode */ disable_prbs_mode(enc110); } @@ -828,8 +792,7 @@ static void link_encoder_disable(struct dce110_link_encoder *enc110) REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); /* reset panel mode */ - ASSERT(REG(DP_DPHY_INTERNAL_CTRL)); - REG_WRITE(DP_DPHY_INTERNAL_CTRL, 0); + setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT); } static void hpd_initialize( @@ -1433,7 +1396,7 @@ void dce110_link_encoder_dp_set_phy_pattern( enc110, param->custom_pattern); break; case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - set_dp_phy_pattern_hbr2_compliance(enc110); + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110); break; case DP_TEST_PATTERN_VIDEO_MODE: { set_dp_phy_pattern_passthrough_mode( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 25ba583dbb8f..4e0b5d965355 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -78,22 +78,29 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) +#define LE_DCE100_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DCI_MEM_PWR_STATUS) + #define LE_DCE110_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SR(DCI_MEM_PWR_STATUS) #define LE_DCE120_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SR(DCI_MEM_PWR_STATUS) #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ LE_COMMON_REG_LIST_BASE(id) - struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; uint32_t AUX_DPHY_RX_CONTROL0; @@ -144,6 +151,7 @@ struct dce110_link_enc_registers { uint32_t DP_VID_STREAM_CNTL; uint32_t DP_DPHY_FAST_TRAINING; uint32_t DP_DPHY_BS_SR_SWAP_CNTL; + uint32_t DP_DPHY_HBR2_PATTERN_CONTROL; uint32_t DP_SEC_CNTL1; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c72858a1452f..b6f77f88be9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -265,7 +265,7 @@ static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { #define link_regs(id)\ [id] = {\ - LE_DCE110_REG_LIST(id)\ + LE_DCE100_REG_LIST(id)\ } static const struct dce110_link_enc_registers link_enc_regs[] = { -- GitLab From 0e19401f9506e710379396479c3824d80ccdc332 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 14 Mar 2017 19:16:36 -0400 Subject: [PATCH 0330/2898] drm/amd/display: support PHY compliance automation for CP2520 pattern 1/2/3 Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 55 ++++++++++--------- .../drm/amd/display/dc/dce/dce_link_encoder.c | 17 ++++-- .../gpu/drm/amd/display/include/dpcd_defs.h | 4 +- .../amd/display/include/link_service_types.h | 11 +++- 4 files changed, 53 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 282bb59ea2f3..4f6d1d2d5b9b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1599,19 +1599,25 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) switch (dpcd_test_pattern.bits.PATTERN) { case PHY_TEST_PATTERN_D10_2: test_pattern = DP_TEST_PATTERN_D102; - break; + break; case PHY_TEST_PATTERN_SYMBOL_ERROR: test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR; - break; + break; case PHY_TEST_PATTERN_PRBS7: test_pattern = DP_TEST_PATTERN_PRBS7; - break; + break; case PHY_TEST_PATTERN_80BIT_CUSTOM: test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; - break; - case PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; - break; + break; + case PHY_TEST_PATTERN_CP2520_1: + test_pattern = DP_TEST_PATTERN_CP2520_1; + break; + case PHY_TEST_PATTERN_CP2520_2: + test_pattern = DP_TEST_PATTERN_CP2520_2; + break; + case PHY_TEST_PATTERN_CP2520_3: + test_pattern = DP_TEST_PATTERN_CP2520_3; + break; default: test_pattern = DP_TEST_PATTERN_VIDEO_MODE; break; @@ -2202,16 +2208,9 @@ void dc_link_dp_disable_hpd(const struct dc_link *link) static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) { - if (test_pattern == DP_TEST_PATTERN_D102 || - test_pattern == DP_TEST_PATTERN_SYMBOL_ERROR || - test_pattern == DP_TEST_PATTERN_PRBS7 || - test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM || - test_pattern == DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE || - test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN1 || - test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN2 || - test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN3 || - test_pattern == DP_TEST_PATTERN_TRAINING_PATTERN4 || - test_pattern == DP_TEST_PATTERN_VIDEO_MODE) + if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern && + test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) || + test_pattern == DP_TEST_PATTERN_VIDEO_MODE) return true; else return false; @@ -2377,22 +2376,28 @@ bool dc_link_dp_set_test_pattern( switch (test_pattern) { case DP_TEST_PATTERN_VIDEO_MODE: pattern = PHY_TEST_PATTERN_NONE; - break; + break; case DP_TEST_PATTERN_D102: pattern = PHY_TEST_PATTERN_D10_2; - break; + break; case DP_TEST_PATTERN_SYMBOL_ERROR: pattern = PHY_TEST_PATTERN_SYMBOL_ERROR; - break; + break; case DP_TEST_PATTERN_PRBS7: pattern = PHY_TEST_PATTERN_PRBS7; - break; + break; case DP_TEST_PATTERN_80BIT_CUSTOM: pattern = PHY_TEST_PATTERN_80BIT_CUSTOM; - break; - case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - pattern = PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE; - break; + break; + case DP_TEST_PATTERN_CP2520_1: + pattern = PHY_TEST_PATTERN_CP2520_1; + break; + case DP_TEST_PATTERN_CP2520_2: + pattern = PHY_TEST_PATTERN_CP2520_2; + break; + case DP_TEST_PATTERN_CP2520_3: + pattern = PHY_TEST_PATTERN_CP2520_3; + break; default: return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 65cc64a17f41..ed46e9aaf357 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -376,7 +376,8 @@ static void set_dp_phy_pattern_80bit_custom( } static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( - struct dce110_link_encoder *enc110) + struct dce110_link_encoder *enc110, + unsigned int cp2520_pattern) { /* previously there is a register DP_HBR2_EYE_PATTERN @@ -408,10 +409,13 @@ static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( /* swap every BS with SR */ REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0); - /* select cp2520 pattern 2 */ + /* select cp2520 patterns */ if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, - DP_DPHY_HBR2_PATTERN_CONTROL, 0x2); + DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern); + else + /* pre-DCE11 can only generate CP2520 pattern 2 */ + ASSERT(cp2520_pattern == 2); /* set link training complete */ set_link_training_complete(enc110, true); @@ -1395,8 +1399,11 @@ void dce110_link_encoder_dp_set_phy_pattern( set_dp_phy_pattern_80bit_custom( enc110, param->custom_pattern); break; - case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE: - set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110); + case DP_TEST_PATTERN_CP2520_1: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1); + break; + case DP_TEST_PATTERN_CP2520_2: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2); break; case DP_TEST_PATTERN_VIDEO_MODE: { set_dp_phy_pattern_passthrough_mode( diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index ea8f5867e834..d8e52e3b8e3c 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -74,7 +74,9 @@ enum dpcd_phy_test_patterns { PHY_TEST_PATTERN_SYMBOL_ERROR, PHY_TEST_PATTERN_PRBS7, PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */ - PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE/* For DP1.2 only */ + PHY_TEST_PATTERN_CP2520_1, + PHY_TEST_PATTERN_CP2520_2, + PHY_TEST_PATTERN_CP2520_3, /* same as TPS4 */ }; enum dpcd_test_dyn_range { diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 479e5fff8a00..b2326017e4c7 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -75,19 +75,24 @@ enum dp_test_pattern { /* Input data is pass through Scrambler * and 8b10b Encoder straight to output*/ DP_TEST_PATTERN_VIDEO_MODE = 0, + /* phy test patterns*/ - DP_TEST_PATTERN_D102, + DP_TEST_PATTERN_PHY_PATTERN_BEGIN, + DP_TEST_PATTERN_D102 = DP_TEST_PATTERN_PHY_PATTERN_BEGIN, DP_TEST_PATTERN_SYMBOL_ERROR, DP_TEST_PATTERN_PRBS7, - DP_TEST_PATTERN_80BIT_CUSTOM, - DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE, + DP_TEST_PATTERN_CP2520_1, + DP_TEST_PATTERN_CP2520_2, + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE = DP_TEST_PATTERN_CP2520_2, /* Link Training Patterns */ DP_TEST_PATTERN_TRAINING_PATTERN1, DP_TEST_PATTERN_TRAINING_PATTERN2, DP_TEST_PATTERN_TRAINING_PATTERN3, DP_TEST_PATTERN_TRAINING_PATTERN4, + DP_TEST_PATTERN_CP2520_3 = DP_TEST_PATTERN_TRAINING_PATTERN4, + DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_TRAINING_PATTERN4, /* link test patterns*/ DP_TEST_PATTERN_COLOR_SQUARES, -- GitLab From 53d35dc60d386cdf1d04a318dc010524bf5607a3 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 16 Mar 2017 15:51:00 -0400 Subject: [PATCH 0331/2898] drm/amd/display: Fix the NULL pointer. (v2) ret value in amdgpu_dm_atomic_check was not rest to EINVAL after drm_atomic_add_affected_planes and by this making any subsequent validation failure pass when returning to atomic_check. v2: Add WARN_ON print for dc_commit_streams in amdgpu_dm_atomic_commit_tail since this should never fail. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 1c1c643439b8..7f2d17784a8e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2392,7 +2392,7 @@ void amdgpu_dm_atomic_commit_tail( } /* DC is optimized not to do anything if 'streams' didn't change. */ - dc_commit_streams(dm->dc, commit_streams, commit_streams_count); + WARN_ON(!dc_commit_streams(dm->dc, commit_streams, commit_streams_count)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -2858,6 +2858,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_atomic_add_affected_planes(state, crtc); if (ret) return ret; + + ret = -EINVAL; } for (i = 0; i < set_count; i++) { -- GitLab From d092bf65851802593ed331ff5a6309b625f36bea Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 8 Feb 2017 15:58:50 -0500 Subject: [PATCH 0332/2898] drm/amd/display: Fix gfx9 parameters reading for DC. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 7f2d17784a8e..8ae78c0653b6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -535,6 +535,8 @@ static void fill_plane_attributes_from_fb( adev->gfx.config.gb_addr_config_fields.num_se; surface->tiling_info.gfx9.max_compressed_frags = adev->gfx.config.gb_addr_config_fields.max_compress_frags; + surface->tiling_info.gfx9.num_rb_per_se = + adev->gfx.config.gb_addr_config_fields.num_rb_per_se; surface->tiling_info.gfx9.swizzle = AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); surface->tiling_info.gfx9.shaderEnable = 1; -- GitLab From 1034934584cf3e2f93da56cc00d6f1ffe2d2d5a9 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 22 Feb 2017 15:31:47 -0500 Subject: [PATCH 0333/2898] drm/amd/display: Unhardcode acrtc->max_cursor_{height,width} Signed-off-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 8ae78c0653b6..19c92aec2f58 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1615,8 +1615,8 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); - acrtc->max_cursor_width = 128; - acrtc->max_cursor_height = 128; + acrtc->max_cursor_width = dm->adev->dm.dc->caps.max_cursor_size; + acrtc->max_cursor_height = dm->adev->dm.dc->caps.max_cursor_size; acrtc->crtc_id = crtc_index; acrtc->base.enabled = false; -- GitLab From ce75805e0a63843af71a07e7e95443866e118af0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 22 Feb 2017 14:24:11 -0500 Subject: [PATCH 0334/2898] drm/amd/display: Unhardcode cursor size reported back to UMD. This will return back MAX cursor size for given ASIC. Signed-off-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 97d949affcfb..c559c71d558e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -311,8 +311,8 @@ int amdgpu_dm_init(struct amdgpu_device *adev) /* TODO: Add_display_info? */ /* TODO use dynamic cursor width */ - adev->ddev->mode_config.cursor_width = 128; - adev->ddev->mode_config.cursor_height = 128; + adev->ddev->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size; + adev->ddev->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size; if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) { DRM_ERROR( -- GitLab From 0702a01f97ec24b20bf20bf6f36250de08bcc8cb Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 22 Feb 2017 14:23:51 -0500 Subject: [PATCH 0335/2898] drm/amd/display: Set cursor pitch to cursor width (in pixels). Signed-off-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 19c92aec2f58..ee9239ab734c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -96,6 +96,8 @@ static void dm_set_cursor( attributes.rotation_angle = 0; attributes.attribute_flags.value = 0; + attributes.pitch = attributes.width; + x = amdgpu_crtc->cursor_x; y = amdgpu_crtc->cursor_y; -- GitLab From 00f02019990d9020321c446a04044b6ca05d20f8 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Fri, 17 Mar 2017 12:02:58 -0400 Subject: [PATCH 0336/2898] drm/amd/display: Fix applying surface to underlay pipe 1. Locking all pipes before doing any changes 2. Applying surface for both top and bottom pipes Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 34 +++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6409d4d1d7f8..c0889ad8357e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1331,32 +1331,41 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!surface_count) /* reset */ core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); + /* Lock pipes for provided surfaces */ for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx; - bool is_new_pipe_surface = true; if (pipe_ctx->surface != surface) continue; - - if (update_type >= UPDATE_TYPE_MED) { - /* only apply for top pipe */ - if (!pipe_ctx->top_pipe) { - core_dc->hwss.apply_ctx_for_surface(core_dc, - surface, context); - context_timing_trace(dc, &context->res_ctx); - } - } - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( core_dc, pipe_ctx, true); } + } + } + + /* Perform requested Updates */ + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + + if (update_type >= UPDATE_TYPE_MED) { + core_dc->hwss.apply_ctx_for_surface( + core_dc, surface, context); + context_timing_trace(dc, &context->res_ctx); + } + + for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx; + bool is_new_pipe_surface = true; + + if (pipe_ctx->surface != surface) + continue; if (srf_updates[i].flip_addr) core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); @@ -1387,6 +1396,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } + /* Unlock pipes */ for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; -- GitLab From 7e2fe3190dc2eb62d84069f18cbf3fbabf79ded7 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 17 Mar 2017 13:09:09 -0400 Subject: [PATCH 0337/2898] drm/amd/display: DP is hotplugged, HDMI with 4:2:0 corruption Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9f624e84f59b..875d1a63fcea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -297,8 +297,8 @@ bool resource_are_streams_timing_synchronizable( return false; if (stream1->phy_pix_clk != stream2->phy_pix_clk - && !dc_is_dp_signal(stream1->signal) - && !dc_is_dp_signal(stream2->signal)) + && (!dc_is_dp_signal(stream1->signal) + || !dc_is_dp_signal(stream2->signal))) return false; return true; @@ -1063,6 +1063,8 @@ static bool are_stream_backends_same( if (stream_a == NULL || stream_b == NULL) return false; + if (stream_a->public.timing.pixel_encoding != stream_b->public.timing.pixel_encoding) + return false; if (is_timing_changed(stream_a, stream_b)) return false; @@ -1072,8 +1074,8 @@ static bool are_stream_backends_same( bool is_stream_unchanged( const struct core_stream *old_stream, const struct core_stream *stream) { - if (old_stream == stream) - return true; + if (old_stream != stream) + return false; if (!are_stream_backends_same(old_stream, stream)) return false; @@ -1357,6 +1359,7 @@ enum dc_status resource_map_pool_resources( continue; } } + /* mark resources used for stream that is already active */ for (j = 0; j < MAX_PIPES; j++) { struct pipe_ctx *pipe_ctx = -- GitLab From 2fc67983fbc56b7b6bba64d4410e3bfeee467834 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 20 Mar 2017 14:49:53 -0400 Subject: [PATCH 0338/2898] drm/amd/display: remove redundant check Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 875d1a63fcea..61ca1e21ae66 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1063,8 +1063,6 @@ static bool are_stream_backends_same( if (stream_a == NULL || stream_b == NULL) return false; - if (stream_a->public.timing.pixel_encoding != stream_b->public.timing.pixel_encoding) - return false; if (is_timing_changed(stream_a, stream_b)) return false; @@ -1074,8 +1072,6 @@ static bool are_stream_backends_same( bool is_stream_unchanged( const struct core_stream *old_stream, const struct core_stream *stream) { - if (old_stream != stream) - return false; if (!are_stream_backends_same(old_stream, stream)) return false; -- GitLab From 3c8c9d6cd1f9c1d6ce53091a0b41fcf2ffc7e16f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 21 Mar 2017 15:16:04 -0400 Subject: [PATCH 0339/2898] drm/amd/display: using calculated values for VReady/Startup Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 9 +++++++++ drivers/gpu/drm/amd/display/dc/dm_services_types.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 1 - drivers/gpu/drm/amd/display/include/logger_types.h | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 33e3377f69fe..568b7f0569f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -28,6 +28,7 @@ #include "os_types.h" #include "fixed31_32.h" +#include "signal_types.h" /****************************************************************************** * Data types for Virtual HW Layer of DAL3. @@ -647,5 +648,13 @@ struct dc_crtc_timing { struct dc_crtc_timing_flags flags; }; +struct _dlg_otg_param { + int vstartup_start; + int vupdate_offset; + int vupdate_width; + int vready_offset; + enum signal_type signal; +}; + #endif /* DC_HW_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index c631dec489e7..f89395e0c107 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -180,6 +180,8 @@ struct dm_pp_display_configuration { uint32_t avail_mclk_switch_time_us; uint32_t avail_mclk_switch_time_in_disp_active_us; + uint32_t min_dcfclock_khz; + uint32_t min_dcfc_deep_sleep_clock_khz; uint32_t disp_clk_khz; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index baa9445833fb..62c19358254b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -96,7 +96,6 @@ enum crtc_state { CRTC_STATE_VBLANK = 0, CRTC_STATE_VACTIVE }; - struct timing_generator { const struct timing_generator_funcs *funcs; struct dc_bios *bp; diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 832d17e1cc49..982c67f7de43 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -63,6 +63,7 @@ enum dc_log_type { LOG_EVENT_LINK_LOSS, LOG_EVENT_UNDERFLOW, LOG_IF_TRACE, + LOG_HW_MARKS, LOG_SECTION_TOTAL_COUNT }; -- GitLab From 8c8953139c4b8e1be14d0b1a53dc1fd607727b59 Mon Sep 17 00:00:00 2001 From: xhdu Date: Tue, 21 Mar 2017 11:05:32 -0400 Subject: [PATCH 0340/2898] drm/amd/display: Add audio/video ContainerId implementation Leave hardcoded if no ContainerId provided by DM. Signed-off-by: Duke Du Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 39 ++++++++++++++++++- .../gpu/drm/amd/display/dc/core/dc_stream.c | 14 +++++-- drivers/gpu/drm/amd/display/dc/dc.h | 14 +++++++ 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 8a204731301d..da9955675fbf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -45,7 +45,10 @@ struct sink { static void destruct(struct sink *sink) { - + if (sink->protected.public.dc_container_id) { + dm_free(sink->protected.public.dc_container_id); + sink->protected.public.dc_container_id = NULL; + } } static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params) @@ -63,6 +66,7 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa sink->protected.public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; sink->protected.public.converter_disable_audio = init_params->converter_disable_audio; + sink->protected.public.dc_container_id = NULL; return true; } @@ -113,6 +117,39 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) return NULL; } +bool dc_sink_get_container_id(struct dc_sink *dc_sink, struct dc_container_id *container_id) +{ + if (dc_sink && container_id && dc_sink->dc_container_id) { + memmove(&container_id->guid, &dc_sink->dc_container_id->guid, + sizeof(container_id->guid)); + memmove(&container_id->portId, &dc_sink->dc_container_id->portId, + sizeof(container_id->portId)); + container_id->manufacturerName = dc_sink->dc_container_id->manufacturerName; + container_id->productCode = dc_sink->dc_container_id->productCode; + return true; + } + return false; +} + +bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container_id *container_id) +{ + if (dc_sink && container_id) { + if (!dc_sink->dc_container_id) + dc_sink->dc_container_id = dm_alloc(sizeof(*dc_sink->dc_container_id)); + + if (dc_sink->dc_container_id) { + memmove(&dc_sink->dc_container_id->guid, &container_id->guid, + sizeof(container_id->guid)); + memmove(&dc_sink->dc_container_id->portId, &container_id->portId, + sizeof(container_id->portId)); + dc_sink->dc_container_id->manufacturerName = container_id->manufacturerName; + dc_sink->dc_container_id->productCode = container_id->productCode; + return true; + } + } + return false; +} + /******************************************************************************* * Protected functions - visible only inside of DC (not visible in DM) ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index bafba1f13a1a..512a53bdc32f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -76,9 +76,17 @@ static bool construct(struct core_stream *stream, stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id; stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; - /* TODO - Unhardcode port_id */ - stream->public.audio_info.port_id[0] = 0x5558859e; - stream->public.audio_info.port_id[1] = 0xd989449; + if (dc_sink_data->dc_container_id != NULL) { + struct dc_container_id *dc_container_id = dc_sink_data->dc_container_id; + + stream->public.audio_info.port_id[0] = dc_container_id->portId[0]; + stream->public.audio_info.port_id[1] = dc_container_id->portId[1]; + } else { + /* TODO - WindowDM has implemented, + other DMs need Unhardcode port_id */ + stream->public.audio_info.port_id[0] = 0x5558859e; + stream->public.audio_info.port_id[1] = 0xd989449; + } /* EDID CAP translation for HDMI 2.0 */ stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8b033ba5df6e..b3d5b922aae4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -695,6 +695,17 @@ bool dc_link_dp_set_test_pattern( * Sink Interfaces - A sink corresponds to a display output device ******************************************************************************/ +struct dc_container_id { + // 128bit GUID in binary form + unsigned char guid[16]; + // 8 byte port ID -> ELD.PortID + unsigned int portId[2]; + // 128bit GUID in binary formufacturer name -> ELD.ManufacturerName + unsigned short manufacturerName; + // 2 byte product code -> ELD.ProductCode + unsigned short productCode; +}; + /* * The sink structure contains EDID and other display device properties */ @@ -702,6 +713,7 @@ struct dc_sink { enum signal_type sink_signal; struct dc_edid dc_edid; /* raw edid */ struct dc_edid_caps edid_caps; /* parse display caps */ + struct dc_container_id *dc_container_id; uint32_t dongle_max_pix_clk; bool converter_disable_audio; }; @@ -719,6 +731,8 @@ struct dc_sink_init_data { }; struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); +bool dc_sink_get_container_id(struct dc_sink *dc_sink, struct dc_container_id *container_id); +bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container_id *container_id); /******************************************************************************* * Cursor interfaces - To manages the cursor within a stream -- GitLab From 18f7a1e4083a5be0ce02df736d3f9a82246dd89b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 23 Mar 2017 10:34:06 -0400 Subject: [PATCH 0341/2898] drm/amd/display: Power on front end during set mode. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 3 +++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e5e52c705954..2a3a39e31717 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1722,6 +1722,9 @@ enum dc_status dce110_apply_ctx_to_hw( context, dc); + if (dc->hwss.power_on_front_end) + dc->hwss.power_on_front_end(dc, pipe_ctx, context); + if (DC_OK != status) return status; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index bcb267295cb9..077dc7573c52 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -104,6 +104,11 @@ struct hw_sequencer_funcs { enum pipe_gating_control power_gating); void (*power_down_front_end)(struct core_dc *dc, struct pipe_ctx *pipe); + + void (*power_on_front_end)(struct core_dc *dc, + struct pipe_ctx *pipe, + struct validate_context *context); + void (*update_info_frame)(struct pipe_ctx *pipe_ctx); void (*enable_stream)(struct pipe_ctx *pipe_ctx); -- GitLab From 5e141de45218d36a6b98c783834684fd0d617f7a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 21 Mar 2017 18:17:12 -0400 Subject: [PATCH 0342/2898] drm/amd/display: Rename bandwidth_calcs.h to dce_calcs.h Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- .../gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c | 2 +- drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- .../amd/display/dc/inc/{bandwidth_calcs.h => dce_calcs.h} | 8 +++++--- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 2 +- 7 files changed, 11 insertions(+), 9 deletions(-) rename drivers/gpu/drm/amd/display/dc/inc/{bandwidth_calcs.h => dce_calcs.h} (99%) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 4820660f51d6..5ac614f433f8 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -24,7 +24,7 @@ */ #include "dm_services.h" -#include "bandwidth_calcs.h" +#include "dce_calcs.h" #include "dc.h" #include "core_types.h" #include "dal_asic_id.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c0889ad8357e..b3891228b499 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -35,7 +35,7 @@ #include "clock_source.h" #include "dc_bios_types.h" -#include "bandwidth_calcs.h" +#include "dce_calcs.h" #include "bios_parser_interface.h" #include "include/irq_service_interface.h" #include "transform.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index aac47955e9bf..9c32b5bbdff5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -31,7 +31,7 @@ #include "gmc/gmc_8_2_sh_mask.h" #include "include/logger_interface.h" -#include "inc/bandwidth_calcs.h" +#include "inc/dce_calcs.h" #include "dce110_mem_input.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c index ebb8df3cdf4a..933e3d819f27 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c @@ -31,7 +31,7 @@ #include "gmc/gmc_7_1_sh_mask.h" #include "include/logger_interface.h" -#include "inc/bandwidth_calcs.h" +#include "inc/dce_calcs.h" #include "../dce110/dce110_mem_input.h" #include "dce80_mem_input.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 7f3c6da1ebd7..405608318ccc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -27,7 +27,7 @@ #define _CORE_TYPES_H_ #include "dc.h" -#include "bandwidth_calcs.h" +#include "dce_calcs.h" #include "ddc_service_types.h" #include "dc_bios_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h similarity index 99% rename from drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h rename to drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h index 81fab9ef3637..580dee95e57a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bandwidth_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2015-2017 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,12 +27,14 @@ * Bandwidth and Watermark calculations interface. * (Refer to "DCEx_mode_support.xlsm" from Perforce.) */ -#ifndef __BANDWIDTH_CALCS_H__ -#define __BANDWIDTH_CALCS_H__ +#ifndef __DCE_CALCS_H__ +#define __DCE_CALCS_H__ #include "bw_fixed.h" struct pipe_ctx; +struct core_dc; +struct validate_context; enum bw_calcs_version { BW_CALCS_VERSION_INVALID, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 7ec4027700d8..179f5ad70f48 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -27,7 +27,7 @@ #include "dc.h" #include "include/grph_object_id.h" -#include "inc/bandwidth_calcs.h" +#include "inc/dce_calcs.h" #include "dce/dce_mem_input.h" /* temporary */ -- GitLab From 667e1498a9d0e43849fa84c1c6874184b33aee5f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 23 Mar 2017 15:27:15 -0400 Subject: [PATCH 0343/2898] drm/amd/display: use CRTC_VERTICAL_INTERRUPT0 as VBLANK trigger. VBLANK interrupt is driven bu line buffer vcounter which is ahead of CRTC vcounter. Use an interrupt that fires at the actual CRTC vblank start boundry. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- .../dc/dce110/dce110_timing_generator.c | 46 ++++++++++++- .../dc/dce110/dce110_timing_generator.h | 3 + .../dc/dce120/dce120_timing_generator.c | 32 ++++++++- .../display/dc/dce80/dce80_timing_generator.c | 1 + .../amd/display/dc/inc/hw/timing_generator.h | 2 + .../dc/irq/dce110/irq_service_dce110.c | 68 +++++++++++++------ .../dc/irq/dce110/irq_service_dce110.h | 5 ++ .../dc/irq/dce120/irq_service_dce120.c | 11 +-- .../display/dc/irq/dce80/irq_service_dce80.c | 22 +++--- 9 files changed, 152 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index f4b8576a0546..006412be7a02 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1869,6 +1869,48 @@ void dce110_tg_set_colors(struct timing_generator *tg, dce110_tg_set_overscan_color(tg, overscan_color); } +/* Gets first line of blank region of the display timing for CRTC + * and programms is as a trigger to fire vertical interrupt + */ +bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t vbl = 0; + uint32_t val = 0; + uint32_t position, vbl_start; + + tg->funcs->get_scanoutpos( + tg, + &vbl, + &position); + + if (vbl == 0) + return false; + + vbl_start = + get_reg_field_value( + vbl, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + + set_reg_field_value( + val, + vbl_start, + CRTC_VERTICAL_INTERRUPT0_POSITION, + CRTC_VERTICAL_INTERRUPT0_LINE_START); + + /* Set interaval width for interrupt to fire to 1 scanline */ + set_reg_field_value( + val, + vbl_start + width, + CRTC_VERTICAL_INTERRUPT0_POSITION, + CRTC_VERTICAL_INTERRUPT0_LINE_END); + + dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERTICAL_INTERRUPT0_POSITION), val); + + return true; +} + static const struct timing_generator_funcs dce110_tg_funcs = { .validate_timing = dce110_tg_validate_timing, .program_timing = dce110_tg_program_timing, @@ -1901,8 +1943,8 @@ static const struct timing_generator_funcs dce110_tg_funcs = { dce110_timing_generator_set_drr, .set_static_screen_control = dce110_timing_generator_set_static_screen_control, - .set_test_pattern = dce110_timing_generator_set_test_pattern - + .set_test_pattern = dce110_timing_generator_set_test_pattern, + .arm_vert_intr = dce110_arm_vert_intr, }; bool dce110_timing_generator_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index 378509b8e56c..ca387b40fc67 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -271,4 +271,7 @@ void dce110_tg_set_colors(struct timing_generator *tg, const struct tg_color *blank_color, const struct tg_color *overscan_color); +bool dce110_arm_vert_intr( + struct timing_generator *tg, uint8_t width); + #endif /* __DC_TIMING_GENERATOR_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index d7e787b591a0..95cb1768aeb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -1039,6 +1039,35 @@ void dce120_timing_generator_set_test_pattern( } } +static bool dce120_arm_vert_intr( + struct timing_generator *tg, + uint8_t width) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t vbl, position, vbl_start; + + tg->funcs->get_scanoutpos( + tg, + &vbl, + &position); + + if (vbl == 0) + return false; + + vbl_start = + get_reg_field_value( + vbl, + CRTC0_CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + + CRTC_REG_SET_2( + CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION, + CRTC_VERTICAL_INTERRUPT0_LINE_START, vbl_start, + CRTC_VERTICAL_INTERRUPT0_LINE_END, vbl_start + width); + + return true; +} + static struct timing_generator_funcs dce120_tg_funcs = { .validate_timing = dce120_tg_validate_timing, .program_timing = dce120_tg_program_timing, @@ -1068,7 +1097,8 @@ static struct timing_generator_funcs dce120_tg_funcs = { .enable_advanced_request = dce120_timing_generator_enable_advanced_request, .set_drr = dce120_timing_generator_set_drr, .set_static_screen_control = dce120_timing_generator_set_static_screen_control, - .set_test_pattern = dce120_timing_generator_set_test_pattern + .set_test_pattern = dce120_timing_generator_set_test_pattern, + .arm_vert_intr = dce120_arm_vert_intr, }; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index eeccabd65a7a..1198f2fbf9c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -145,6 +145,7 @@ static const struct timing_generator_funcs dce80_tg_funcs = { .set_static_screen_control = dce110_timing_generator_set_static_screen_control, .set_test_pattern = dce110_timing_generator_set_test_pattern, + .arm_vert_intr = dce110_arm_vert_intr, /* DCE8.0 overrides */ .enable_advanced_request = diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 62c19358254b..51902a4f8798 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -156,6 +156,8 @@ struct timing_generator_funcs { enum controller_dp_test_pattern test_pattern, enum dc_color_depth color_depth); + bool (*arm_vert_intr)(struct timing_generator *tg, uint8_t width); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 4c7c85d45518..52361d1472fa 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -31,14 +31,10 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" + #include "ivsrcid/ivsrcid_vislands30.h" -#define VISLANDS30_IV_SRCID_D1_VBLANK 1 -#define VISLANDS30_IV_SRCID_D2_VBLANK 2 -#define VISLANDS30_IV_SRCID_D3_VBLANK 3 -#define VISLANDS30_IV_SRCID_D4_VBLANK 4 -#define VISLANDS30_IV_SRCID_D5_VBLANK 5 -#define VISLANDS30_IV_SRCID_D6_VBLANK 6 +#include "core_dc.h" static bool hpd_ack( struct irq_service *irq_service, @@ -83,7 +79,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = { }; static const struct irq_source_info_funcs vblank_irq_info_funcs = { - .set = NULL, + .set = dce110_vblank_set, .ack = NULL }; @@ -148,18 +144,19 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { #define vblank_int_entry(reg_num)\ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ - .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .enable_mask =\ - LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ .enable_value = {\ - LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ - ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\ - .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ + ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .ack_mask =\ - LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ .ack_value =\ - LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ - .funcs = &vblank_irq_info_funcs\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs,\ + .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\ } #define dummy_irq_entry() \ @@ -202,6 +199,35 @@ bool dal_irq_service_dummy_ack( return false; } + +bool dce110_vblank_set( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable) +{ + struct dc_context *dc_ctx = irq_service->ctx; + struct core_dc *core_dc = DC_TO_CORE(irq_service->ctx->dc); + enum dc_irq_source dal_irq_src = dc_interrupt_to_irq_source( + irq_service->ctx->dc, + info->src_id, + info->ext_id); + uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; + + struct timing_generator *tg = + core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].tg; + + if (enable) { + if (!tg->funcs->arm_vert_intr(tg, 2)) { + DC_ERROR("Failed to get VBLANK!\n"); + return false; + } + } + + dal_irq_service_set_generic(irq_service, info, enable); + return true; + +} + static const struct irq_source_info_funcs dummy_irq_info_funcs = { .set = dal_irq_service_dummy_set, .ack = dal_irq_service_dummy_ack @@ -302,17 +328,17 @@ enum dc_irq_source to_dal_irq_source_dce110( uint32_t ext_id) { switch (src_id) { - case VISLANDS30_IV_SRCID_D1_VBLANK: + case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK1; - case VISLANDS30_IV_SRCID_D2_VBLANK: + case VISLANDS30_IV_SRCID_D2_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK2; - case VISLANDS30_IV_SRCID_D3_VBLANK: + case VISLANDS30_IV_SRCID_D3_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK3; - case VISLANDS30_IV_SRCID_D4_VBLANK: + case VISLANDS30_IV_SRCID_D4_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK4; - case VISLANDS30_IV_SRCID_D5_VBLANK: + case VISLANDS30_IV_SRCID_D5_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK5; - case VISLANDS30_IV_SRCID_D6_VBLANK: + case VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0: return DC_IRQ_SOURCE_VBLANK6; case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: return DC_IRQ_SOURCE_VUPDATE1; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h index a84f360c6515..9237646c0959 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.h @@ -45,4 +45,9 @@ bool dal_irq_service_dummy_ack( struct irq_service *irq_service, const struct irq_source_info *info); +bool dce110_vblank_set( + struct irq_service *irq_service, + const struct irq_source_info *info, + bool enable); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c index 5a263b2efa51..3871633ac635 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -79,7 +79,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = { }; static const struct irq_source_info_funcs vblank_irq_info_funcs = { - .set = NULL, + .set = dce110_vblank_set, .ack = NULL }; @@ -144,10 +144,11 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { #define vblank_int_entry(reg_num)\ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ - IRQ_REG_ENTRY(LB, reg_num,\ - LB_INTERRUPT_MASK, VBLANK_INTERRUPT_MASK,\ - LB_VBLANK_STATUS, VBLANK_ACK),\ - .funcs = &vblank_irq_info_funcs\ + IRQ_REG_ENTRY(CRTC, reg_num,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL, CRTC_VERTICAL_INTERRUPT0_INT_ENABLE,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL, CRTC_VERTICAL_INTERRUPT0_CLEAR),\ + .funcs = &vblank_irq_info_funcs,\ + .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\ } #define dummy_irq_entry() \ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index dd09d2b6d4a7..7e8cb22f280f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -35,6 +35,9 @@ #include "ivsrcid/ivsrcid_vislands30.h" +#include "dc_types.h" +#include "inc/core_dc.h" + static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) @@ -78,7 +81,7 @@ static const struct irq_source_info_funcs pflip_irq_info_funcs = { }; static const struct irq_source_info_funcs vblank_irq_info_funcs = { - .set = NULL, + .set = dce110_vblank_set, .ack = NULL }; @@ -145,18 +148,19 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { #define vblank_int_entry(reg_num)\ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ - .enable_reg = mmLB ## reg_num ## _LB_INTERRUPT_MASK,\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .enable_mask =\ - LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ .enable_value = {\ - LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK,\ - ~LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK},\ - .ack_reg = mmLB ## reg_num ## _LB_VBLANK_STATUS,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\ + ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\ .ack_mask =\ - LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ .ack_value =\ - LB_VBLANK_STATUS__VBLANK_ACK_MASK,\ - .funcs = &vblank_irq_info_funcs\ + CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs,\ + .src_id = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 + reg_num\ } #define dummy_irq_entry() \ -- GitLab From e902915507bd20115e1e21bc99ea36ea7986cebc Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 23 Mar 2017 15:30:35 -0400 Subject: [PATCH 0344/2898] drm/amd/display: use CRTC_VERTICAL_INTERRUPT0 as a trigger for VBLANK. Register ISR hnadler on the new interrupt. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c559c71d558e..b08ec453b773 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -907,9 +907,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) * for acknowledging and handling. */ /* Use VBLANK interrupt */ - for (i = 1; i <= adev->mode_info.num_crtc; i++) { + for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) { r = amdgpu_irq_add_id(adev, client_id, i, &adev->crtc_irq); - if (r) { DRM_ERROR("Failed to add crtc irq id!\n"); return r; -- GitLab From fd8cc371ede63d69cf69bb3a8a9a005d91ae023f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 24 Mar 2017 16:54:02 -0400 Subject: [PATCH 0345/2898] drm/amd/display: voltage request related change Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Krunoslav Kovac Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_clock_source.c | 1 + .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 27 ++++++++++--------- .../drm/amd/display/dc/inc/hw/display_clock.h | 2 ++ .../drm/amd/display/include/logger_types.h | 1 + 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index bd4524ef3a37..8ddad3a877d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1035,6 +1035,7 @@ static void get_ss_info_from_atombios( } *spread_spectrum_data = ss_data; + dm_free(ss_data); dm_free(ss_info); return; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 263f8900e39c..b4fd02219c2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -495,6 +495,7 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) } } + static bool dce_apply_clock_voltage_request( struct display_clock *clk, enum dm_pp_clock_type clocks_type, @@ -502,6 +503,7 @@ static bool dce_apply_clock_voltage_request( bool pre_mode_set, bool update_dp_phyclk) { + bool send_request = false; struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; switch (clocks_type) { @@ -522,9 +524,8 @@ static bool dce_apply_clock_voltage_request( switch (clocks_type) { case DM_PP_CLOCK_TYPE_DISPLAY_CLK: if (clocks_in_khz > clk->cur_clocks_value.dispclk_in_khz) { - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); clk->cur_clocks_value.dispclk_notify_pplib_done = true; + send_request = true; } else clk->cur_clocks_value.dispclk_notify_pplib_done = false; /* no matter incrase or decrase clock, update current clock value */ @@ -532,9 +533,8 @@ static bool dce_apply_clock_voltage_request( break; case DM_PP_CLOCK_TYPE_PIXELCLK: if (clocks_in_khz > clk->cur_clocks_value.max_pixelclk_in_khz) { - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); clk->cur_clocks_value.pixelclk_notify_pplib_done = true; + send_request = true; } else clk->cur_clocks_value.pixelclk_notify_pplib_done = false; /* no matter incrase or decrase clock, update current clock value */ @@ -542,9 +542,8 @@ static bool dce_apply_clock_voltage_request( break; case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: if (clocks_in_khz > clk->cur_clocks_value.max_non_dp_phyclk_in_khz) { - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); clk->cur_clocks_value.phyclk_notigy_pplib_done = true; + send_request = true; } else clk->cur_clocks_value.phyclk_notigy_pplib_done = false; /* no matter incrase or decrase clock, update current clock value */ @@ -554,29 +553,30 @@ static bool dce_apply_clock_voltage_request( ASSERT(0); break; } + } else { switch (clocks_type) { case DM_PP_CLOCK_TYPE_DISPLAY_CLK: if (!clk->cur_clocks_value.dispclk_notify_pplib_done) - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); + send_request = true; break; case DM_PP_CLOCK_TYPE_PIXELCLK: if (!clk->cur_clocks_value.pixelclk_notify_pplib_done) - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); + send_request = true; break; case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: if (!clk->cur_clocks_value.phyclk_notigy_pplib_done) - dm_pp_apply_clock_for_voltage_request( - clk->ctx, &clock_voltage_req); + send_request = true; break; default: ASSERT(0); break; } } - + if (send_request) { + dm_pp_apply_clock_for_voltage_request( + clk->ctx, &clock_voltage_req); + } if (update_dp_phyclk && (clocks_in_khz > clk->cur_clocks_value.max_dp_phyclk_in_khz)) clk->cur_clocks_value.max_dp_phyclk_in_khz = clocks_in_khz; @@ -584,6 +584,7 @@ static bool dce_apply_clock_voltage_request( return true; } + static const struct display_clock_funcs dce120_funcs = { .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, .apply_clock_voltage_request = dce_apply_clock_voltage_request, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 79aa75c150ec..97f26b55535f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -28,6 +28,7 @@ #include "dm_services_types.h" + struct clocks_value { int dispclk_in_khz; int max_pixelclk_in_khz; @@ -38,6 +39,7 @@ struct clocks_value { bool phyclk_notigy_pplib_done; }; + /* Structure containing all state-dependent clocks * (dependent on "enum clocks_state") */ struct state_dependent_clocks { diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 982c67f7de43..dfc0f102b33d 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -64,6 +64,7 @@ enum dc_log_type { LOG_EVENT_UNDERFLOW, LOG_IF_TRACE, LOG_HW_MARKS, + LOG_PPLIB, LOG_SECTION_TOTAL_COUNT }; -- GitLab From 940c654e64e1ed70b49ec663f2370a8b4de6d2ac Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 24 Mar 2017 16:26:09 -0400 Subject: [PATCH 0346/2898] drm/amd/display: increase timeout for dmif dealloc In some use-cases, e.g. multiple 4K displays, exisitng wait time for reg update of 30msec timed out during mode setiing that sometimes resulted in system bad state as we continue without waiting for registry update complete. Increasing timeout to 35msec fixes that problem. Signed-off-by: Roman Li Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 7acd87152811..884f453d91b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -524,7 +524,7 @@ void dce_mem_input_free_dmif(struct mem_input *mi, REG_WAIT(DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, - 10, 0xBB8); + 10, 3500); if (mi->wa.single_head_rdreq_dmif_limit) { uint32_t eanble = (total_stream_num > 1) ? 0 : -- GitLab From dabb3979e1cdfddbc9121116cfcf69f01991e51d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 27 Mar 2017 09:59:38 -0400 Subject: [PATCH 0347/2898] drm/amd/display: Fix MPO exit and cursor issue. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 512a53bdc32f..bf209f7bbf98 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -215,7 +215,7 @@ bool dc_stream_set_cursor_attributes( bool dc_stream_set_cursor_position( const struct dc_stream *dc_stream, - const struct dc_cursor_position *position) + struct dc_cursor_position *position) { int i; struct core_stream *stream; @@ -251,6 +251,9 @@ bool dc_stream_set_cursor_position( .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, }; + if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + position->enable = false; + ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); ret = true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b3d5b922aae4..0731045f6084 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -744,7 +744,7 @@ bool dc_stream_set_cursor_attributes( bool dc_stream_set_cursor_position( const struct dc_stream *stream, - const struct dc_cursor_position *position); + struct dc_cursor_position *position); /* Newer interfaces */ struct dc_cursor { -- GitLab From fcbb5ad3fef1ee8461150e7213806cbb46b6f076 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 27 Mar 2017 12:39:22 -0400 Subject: [PATCH 0348/2898] drm/amd/display: use CP2520-3 for PHY compliance automation Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Hersen Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 3 +++ drivers/gpu/drm/amd/display/include/link_service_types.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index ed46e9aaf357..df116f86ab45 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1405,6 +1405,9 @@ void dce110_link_encoder_dp_set_phy_pattern( case DP_TEST_PATTERN_CP2520_2: set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2); break; + case DP_TEST_PATTERN_CP2520_3: + set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3); + break; case DP_TEST_PATTERN_VIDEO_MODE: { set_dp_phy_pattern_passthrough_mode( enc110, param->dp_panel_mode); diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index b2326017e4c7..fe8b5144e03f 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -85,13 +85,13 @@ enum dp_test_pattern { DP_TEST_PATTERN_CP2520_1, DP_TEST_PATTERN_CP2520_2, DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE = DP_TEST_PATTERN_CP2520_2, + DP_TEST_PATTERN_CP2520_3, /* Link Training Patterns */ DP_TEST_PATTERN_TRAINING_PATTERN1, DP_TEST_PATTERN_TRAINING_PATTERN2, DP_TEST_PATTERN_TRAINING_PATTERN3, DP_TEST_PATTERN_TRAINING_PATTERN4, - DP_TEST_PATTERN_CP2520_3 = DP_TEST_PATTERN_TRAINING_PATTERN4, DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_TRAINING_PATTERN4, /* link test patterns*/ -- GitLab From 7b779c991d9422f677dff70d701eae448c7c696a Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Mon, 27 Mar 2017 12:48:46 -0500 Subject: [PATCH 0349/2898] drm/amd/display: stereo support Frame sequential, top-bottom and side-by-side support. Signed-off-by: Vitaly Prosyak Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 61ca1e21ae66..8f53d7a9f4dd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -422,6 +422,11 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || + stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) { + pri_split = false; + sec_split = false; + } /* The actual clip is an intersection between stream * source and surface clip */ @@ -532,14 +537,27 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip stream->public.dst.y + stream->public.dst.height - pipe_ctx->scl_data.recout.y; - /* Handle hsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - pipe_ctx->scl_data.recout.width /= 2; - pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; - /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; - } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { - pipe_ctx->scl_data.recout.width /= 2; + /* Handle h & vsplit */ + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == + pipe_ctx->surface) { + if (stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM) { + pipe_ctx->scl_data.recout.height /= 2; + pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; + /* Floor primary pipe, ceil 2ndary pipe */ + pipe_ctx->scl_data.recout.height += pipe_ctx->scl_data.recout.height % 2; + } else { + pipe_ctx->scl_data.recout.width /= 2; + pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; + pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; + } + } else if (pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + if (stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM) + pipe_ctx->scl_data.recout.height /= 2; + else + pipe_ctx->scl_data.recout.width /= 2; } /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream src offset) -- GitLab From 4e3133c79dc4b7dc0ff81eb884d6cfe736fc49b1 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Mon, 27 Mar 2017 14:50:27 -0400 Subject: [PATCH 0350/2898] drm/amd/display: obtain usHBR3En bit from BP 1 ASICs using bios parser 1 don't check HBR3 capability as there is no such a bit usHBR3En in ATOM_ENCODER_CAP_RECORDER. Therefore, will use ATOM_ENCODER_CAP_RECORDER_V2 and thus obtain the usHBR3En bit. Signed-off-by: Ding Wang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 14 +++++++------- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 50163a06a653..47a467688073 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -88,7 +88,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, static struct device_id device_type_from_device_id(uint16_t device_id); static uint32_t signal_to_ss_id(enum as_signal_type signal); static uint32_t get_support_mask_for_device_id(struct device_id device_id); -static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( +static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( struct bios_parser *bp, ATOM_OBJECT *object); @@ -1837,7 +1837,7 @@ static enum bp_result bios_parser_get_encoder_cap_info( { struct bios_parser *bp = BP_FROM_DCB(dcb); ATOM_OBJECT *object; - ATOM_ENCODER_CAP_RECORD *record = NULL; + ATOM_ENCODER_CAP_RECORD_V2 *record = NULL; if (!info) return BP_RESULT_BADINPUT; @@ -1851,8 +1851,8 @@ static enum bp_result bios_parser_get_encoder_cap_info( if (!record) return BP_RESULT_NORECORD; - info->DP_HBR2_CAP = record->usHBR2Cap; info->DP_HBR2_EN = record->usHBR2En; + info->DP_HBR3_EN = record->usHBR3En; return BP_RESULT_OK; } @@ -1867,9 +1867,9 @@ static enum bp_result bios_parser_get_encoder_cap_info( * @return atom encoder cap record * * @note - * search all records to find the ATOM_ENCODER_CAP_RECORD record + * search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record */ -static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( +static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( struct bios_parser *bp, ATOM_OBJECT *object) { @@ -1899,8 +1899,8 @@ static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record( if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType) continue; - if (sizeof(ATOM_ENCODER_CAP_RECORD) <= header->ucRecordSize) - return (ATOM_ENCODER_CAP_RECORD *)header; + if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize) + return (ATOM_ENCODER_CAP_RECORD_V2 *)header; } return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index df116f86ab45..1a84ee0105da 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -993,7 +993,7 @@ bool dce110_link_encoder_construct( enc110->base.ctx->dc_bios, enc110->base.id, &bp_cap_info)) { enc110->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_CAP; + bp_cap_info.DP_HBR2_EN; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; } -- GitLab From d4e13b0db124345be93bc2ff39ecb48409da2c9b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:24:01 -0400 Subject: [PATCH 0351/2898] drm/amd/display: decouple per-crtc-plane model Current design has per-crtc-plane model. As a result, for asic's that support underlay, are unable to expose it to user space for modesetting. To enable this, the drm driver intialisation now runs for number of surfaces instead of stream/crtc. This patch plumbs surface capabilities to drm framework so that it can be effectively used by user space. Tests: (On Chromium OS for Stoney Only) * 'modetest -p' now shows additional plane with YUV capabilities in case of CZ and ST. * 'plane_test' fails with below error: [drm:amdgpu_dm_connector_atomic_set_property [amdgpu]] *ERROR* Unsupported screen depth 0 as ther is no support for YUYV * Checked multimonitor display works fine Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 8 ++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 67 ++++++++++++---- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 76 +++++++++++++------ .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 5 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/dc/dce100/dce100_resource.c | 2 + .../amd/display/dc/dce110/dce110_resource.c | 2 + .../amd/display/dc/dce112/dce112_resource.c | 2 + .../amd/display/dc/dce120/dce120_resource.c | 2 + .../drm/amd/display/dc/dce80/dce80_resource.c | 2 + 10 files changed, 127 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index e5d2ce48cb1e..362d9559f065 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -60,6 +60,7 @@ struct amdgpu_hpd; #define AMDGPU_MAX_HPD_PINS 6 #define AMDGPU_MAX_CRTCS 6 +#define AMDGPU_MAX_PLANES 6 #define AMDGPU_MAX_AFMT_BLOCKS 9 enum amdgpu_rmx_type { @@ -327,6 +328,7 @@ struct amdgpu_mode_info { struct card_info *atom_card_info; bool mode_config_initialized; struct amdgpu_crtc *crtcs[AMDGPU_MAX_CRTCS]; + struct amdgpu_plane *planes[AMDGPU_MAX_PLANES]; struct amdgpu_afmt *afmt[AMDGPU_MAX_AFMT_BLOCKS]; /* DVI-I properties */ struct drm_property *coherent_mode_property; @@ -356,6 +358,7 @@ struct amdgpu_mode_info { int num_dig; /* number of dig blocks */ int disp_priority; const struct amdgpu_display_funcs *funcs; + enum drm_plane_type *plane_type; }; #define AMDGPU_MAX_BL_LEVEL 0xFF @@ -436,6 +439,11 @@ struct amdgpu_crtc { struct drm_pending_vblank_event *event; }; +struct amdgpu_plane { + struct drm_plane base; + enum drm_plane_type plane_type; +}; + struct amdgpu_encoder_atom_dig { bool linkb; /* atom dig */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b08ec453b773..d76448d04423 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -49,6 +49,28 @@ #include "modules/inc/mod_freesync.h" +static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, +}; + +static enum drm_plane_type dm_surfaces_type_carizzo[AMDGPU_MAX_PLANES] = { + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_OVERLAY,/* YUV Capable Underlay */ +}; + +static enum drm_plane_type dm_surfaces_type_stoney[AMDGPU_MAX_PLANES] = { + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_PRIMARY, + DRM_PLANE_TYPE_OVERLAY, /* YUV Capable Underlay */ +}; + /* * dm_vblank_get_counter * @@ -1051,30 +1073,34 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) uint32_t i; struct amdgpu_connector *aconnector; struct amdgpu_encoder *aencoder; - struct amdgpu_crtc *acrtc; + struct amdgpu_mode_info *mode_info = &adev->mode_info; uint32_t link_cnt; link_cnt = dm->dc->caps.max_links; - if (amdgpu_dm_mode_config_init(dm->adev)) { DRM_ERROR("DM: Failed to initialize mode config\n"); - return -1; + goto fail; } - for (i = 0; i < dm->dc->caps.max_streams; i++) { - acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); - if (!acrtc) - goto fail; + for (i = 0; i < dm->dc->caps.max_surfaces; i++) { + mode_info->planes[i] = kzalloc(sizeof(struct amdgpu_plane), + GFP_KERNEL); + if (!mode_info->planes[i]) { + DRM_ERROR("KMS: Failed to allocate surface\n"); + goto fail_free_planes; + } + mode_info->planes[i]->plane_type = mode_info->plane_type[i]; + if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 1)) { + DRM_ERROR("KMS: Failed to initialize plane\n"); + goto fail_free_planes; + } + } - if (amdgpu_dm_crtc_init( - dm, - acrtc, - i)) { + for (i = 0; i < dm->dc->caps.max_streams; i++) + if (amdgpu_dm_crtc_init(dm, &mode_info->planes[i]->base, i)) { DRM_ERROR("KMS: Failed to initialize crtc\n"); - kfree(acrtc); - goto fail; + goto fail_free_planes; } - } dm->display_indexes_num = dm->dc->caps.max_streams; @@ -1125,12 +1151,12 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_VEGA10: if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); - return -1; + goto fail_free_encoder; } break; default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); - return -1; + goto fail_free_encoder; } drm_mode_config_reset(dm->ddev); @@ -1140,6 +1166,9 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) kfree(aencoder); fail_free_connector: kfree(aconnector); +fail_free_planes: + for (i = 0; i < dm->dc->caps.max_surfaces; i++) + kfree(mode_info->planes[i]); fail: return -1; } @@ -1361,33 +1390,39 @@ static int dm_early_init(void *handle) adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; + adev->mode_info.plane_type = dm_surfaces_type_default; break; case CHIP_FIJI: case CHIP_TONGA: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 7; + adev->mode_info.plane_type = dm_surfaces_type_default; break; case CHIP_CARRIZO: adev->mode_info.num_crtc = 3; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; + adev->mode_info.plane_type = dm_surfaces_type_carizzo; break; case CHIP_STONEY: adev->mode_info.num_crtc = 2; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; + adev->mode_info.plane_type = dm_surfaces_type_stoney; break; case CHIP_POLARIS11: case CHIP_POLARIS12: adev->mode_info.num_crtc = 5; adev->mode_info.num_hpd = 5; adev->mode_info.num_dig = 5; + adev->mode_info.plane_type = dm_surfaces_type_default; break; case CHIP_POLARIS10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; + adev->mode_info.plane_type = dm_surfaces_type_default; break; case CHIP_VEGA10: adev->mode_info.num_crtc = 6; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ee9239ab734c..1751f138c36a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1446,6 +1446,8 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { }; static const struct drm_plane_funcs dm_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state @@ -1577,38 +1579,67 @@ static uint32_t rgb_formats[] = { DRM_FORMAT_ABGR2101010, }; -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct amdgpu_crtc *acrtc, - uint32_t crtc_index) +static uint32_t yuv_formats[] = { + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, +}; + +int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs) { - int res = -ENOMEM; + int res = -EPERM; - struct drm_plane *primary_plane = - kzalloc(sizeof(*primary_plane), GFP_KERNEL); + switch (aplane->plane_type) { + case DRM_PLANE_TYPE_PRIMARY: + aplane->base.format_default = true; - if (!primary_plane) - goto fail_plane; + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + rgb_formats, + ARRAY_SIZE(rgb_formats), + NULL, aplane->plane_type, NULL); + break; + case DRM_PLANE_TYPE_OVERLAY: + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + yuv_formats, + ARRAY_SIZE(yuv_formats), + NULL, aplane->plane_type, NULL); + break; + case DRM_PLANE_TYPE_CURSOR: + DRM_ERROR("KMS: Cursor plane not implemented."); + break; + } - primary_plane->format_default = true; + drm_plane_helper_add(&aplane->base, &dm_plane_helper_funcs); - res = drm_universal_plane_init( - dm->adev->ddev, - primary_plane, - 0, - &dm_plane_funcs, - rgb_formats, - ARRAY_SIZE(rgb_formats), - NULL, - DRM_PLANE_TYPE_PRIMARY, NULL); + return res; +} - primary_plane->crtc = &acrtc->base; +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t crtc_index) +{ + struct amdgpu_crtc *acrtc; + int res = -ENOMEM; - drm_plane_helper_add(primary_plane, &dm_plane_helper_funcs); + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); + if (!acrtc) + goto fail; res = drm_crtc_init_with_planes( dm->ddev, &acrtc->base, - primary_plane, + plane, NULL, &amdgpu_dm_crtc_funcs, NULL); @@ -1628,8 +1659,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, return 0; fail: - kfree(primary_plane); -fail_plane: + kfree(acrtc); acrtc->crtc_id = -1; return res; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 1bbeb87dc9d0..ab6d51dbbf4b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -34,8 +34,11 @@ struct dc_validation_set; struct dc_surface; /*TODO Jodan Hersen use the one in amdgpu_dm*/ +int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs); int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct amdgpu_crtc *amdgpu_crtc, + struct drm_plane *plane, uint32_t link_index); int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, struct amdgpu_connector *amdgpu_connector, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0731045f6084..9dd8b2ad4c59 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,6 +45,7 @@ struct dc_caps { uint32_t max_links; uint32_t max_audios; uint32_t max_slave_planes; + uint32_t max_surfaces; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index b6f77f88be9c..d1685df09815 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -1035,6 +1035,8 @@ static bool construct( } } + dc->public.caps.max_surfaces = pool->base.pipe_count; + if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) goto res_create_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index e3002031c40d..065a2986b666 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1455,6 +1455,8 @@ static bool construct( if (!dce110_hw_sequencer_construct(dc)) goto res_create_fail; + dc->public.caps.max_surfaces = pool->base.pipe_count; + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 32aa1b5bf1f9..ece3ec72363d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1409,6 +1409,8 @@ static bool construct( &res_create_funcs)) goto res_create_fail; + dc->public.caps.max_surfaces = pool->base.pipe_count; + /* Create hardware sequencer */ if (!dce112_hw_sequencer_construct(dc)) goto res_create_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index efa58889058b..f677a77ca6e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -1060,6 +1060,8 @@ static bool construct( if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; + dc->public.caps.max_surfaces = pool->base.pipe_count; + bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index a3e8182885b2..752e0e7579b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -1043,6 +1043,8 @@ static bool construct( } } + dc->public.caps.max_surfaces = pool->base.pipe_count; + if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) goto res_create_fail; -- GitLab From f2a0f5e6b23d6649577081df3762e41abee04691 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 3 Apr 2017 13:36:26 -0400 Subject: [PATCH 0352/2898] drm/amd/display: Fix cleanup in amdgpu_dm_initialize_drm_device Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d76448d04423..1077af91884f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1071,15 +1071,15 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) { struct amdgpu_display_manager *dm = &adev->dm; uint32_t i; - struct amdgpu_connector *aconnector; - struct amdgpu_encoder *aencoder; + struct amdgpu_connector *aconnector = NULL; + struct amdgpu_encoder *aencoder = NULL; struct amdgpu_mode_info *mode_info = &adev->mode_info; uint32_t link_cnt; link_cnt = dm->dc->caps.max_links; if (amdgpu_dm_mode_config_init(dm->adev)) { DRM_ERROR("DM: Failed to initialize mode config\n"); - goto fail; + return -1; } for (i = 0; i < dm->dc->caps.max_surfaces; i++) { @@ -1116,7 +1116,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) - goto fail; + goto fail_free_planes; aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); if (!aencoder) { @@ -1130,7 +1130,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) { DRM_ERROR("KMS: Failed to initialize connector\n"); - goto fail_free_connector; + goto fail_free_encoder; } if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true)) @@ -1169,7 +1169,6 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) fail_free_planes: for (i = 0; i < dm->dc->caps.max_surfaces; i++) kfree(mode_info->planes[i]); -fail: return -1; } -- GitLab From 64d8b7806e40a1520d5eb47157ff4ee15efc3bf6 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 23 Mar 2017 14:54:40 +0530 Subject: [PATCH 0353/2898] drm/amd/display: update plane functionalities This patch introduces amdgpu_drm_plane_state structure, which subclasses drm_plane_state and holds data suitable for configuring hardware. It switches reset(), atomic_duplicate_state() & atomic_destroy_state() functions to new internal implementation, earlier they were pointing to drm core functions. TESTS(On Chromium OS on Stoney Only) * Builds without compilation errors. * 'plane_test' passes for XR24 format based Overlay plane. * Chromium OS ui comes up. Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 13 +++++ .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 54 +++++++++++++++++-- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 362d9559f065..bdae70e128c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -57,6 +57,7 @@ struct amdgpu_hpd; #define to_amdgpu_connector(x) container_of(x, struct amdgpu_connector, base) #define to_amdgpu_encoder(x) container_of(x, struct amdgpu_encoder, base) #define to_amdgpu_framebuffer(x) container_of(x, struct amdgpu_framebuffer, base) +#define to_amdgpu_plane(x) container_of(x, struct amdgpu_plane, base) #define AMDGPU_MAX_HPD_PINS 6 #define AMDGPU_MAX_CRTCS 6 @@ -439,6 +440,18 @@ struct amdgpu_crtc { struct drm_pending_vblank_event *event; }; +struct amdgpu_drm_plane_state { + struct drm_plane_state base; + unsigned int h_ratio; + unsigned int v_ratio; +}; + +static inline struct amdgpu_drm_plane_state * +to_amdgpu_plane_state(struct drm_plane_state *state) +{ + return container_of(state, struct amdgpu_drm_plane_state, base); +} + struct amdgpu_plane { struct drm_plane base; enum drm_plane_type plane_type; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 1751f138c36a..aa243584b2cc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1445,12 +1445,56 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { .atomic_check = dm_encoder_helper_atomic_check }; +static void dm_drm_plane_reset(struct drm_plane *plane) +{ + struct amdgpu_drm_plane_state *amdgpu_state; + + if (plane->state) { + amdgpu_state = to_amdgpu_plane_state(plane->state); + if (amdgpu_state->base.fb) + drm_framebuffer_unreference(amdgpu_state->base.fb); + kfree(amdgpu_state); + plane->state = NULL; + } + + amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); + if (amdgpu_state) { + plane->state = &amdgpu_state->base; + plane->state->plane = plane; + } +} + +static struct drm_plane_state * +dm_drm_plane_duplicate_state(struct drm_plane *plane) +{ + struct amdgpu_drm_plane_state *amdgpu_state; + struct amdgpu_drm_plane_state *copy; + + amdgpu_state = to_amdgpu_plane_state(plane->state); + copy = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); + if (!copy) + return NULL; + + __drm_atomic_helper_plane_duplicate_state(plane, ©->base); + return ©->base; +} + +static void dm_drm_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct amdgpu_drm_plane_state *old_amdgpu_state = + to_amdgpu_plane_state(old_state); + __drm_atomic_helper_plane_destroy_state(old_state); + kfree(old_amdgpu_state); +} + static const struct drm_plane_funcs dm_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .reset = drm_atomic_helper_plane_reset, - .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_plane_destroy_state + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = dm_drm_plane_reset, + .atomic_duplicate_state = dm_drm_plane_duplicate_state, + .atomic_destroy_state = dm_drm_plane_destroy_state, }; static int dm_plane_helper_prepare_fb( -- GitLab From 934d292316b5d3933d7fe6811c5d7a696c33910c Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Fri, 17 Mar 2017 15:24:09 -0400 Subject: [PATCH 0354/2898] drm/amd/display: remove surface validation against stream rect Surface information is by default copied from old context in dc_commit_stream. Thus unchange streams will not be affected. For new streams, we shouldn't validate the new mode against the surface configuration of old_context. Signed-off-by: Reza Amini Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 5 ----- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 5 ----- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 5 ----- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 5 ----- 4 files changed, 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index d1685df09815..7fae8537e18a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -788,11 +788,6 @@ static bool dce100_validate_surface_sets( if (set[i].surface_count > 1) return false; - if (set[i].surfaces[0]->clip_rect.width - < set[i].stream->src.width - || set[i].surfaces[0]->clip_rect.height - < set[i].stream->src.height) - return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 065a2986b666..b4ab438e1c97 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1007,11 +1007,6 @@ static bool dce110_validate_surface_sets( if (set[i].surface_count > 2) return false; - if (set[i].surfaces[0]->clip_rect.width - > set[i].stream->src.width - || set[i].surfaces[0]->clip_rect.height - > set[i].stream->src.height) - return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index ece3ec72363d..0a1ad2808129 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -972,11 +972,6 @@ static bool dce112_validate_surface_sets( if (set[i].surface_count > 1) return false; - if (set[i].surfaces[0]->clip_rect.width - > set[i].stream->src.width - || set[i].surfaces[0]->clip_rect.height - > set[i].stream->src.height) - return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 752e0e7579b9..ab8cee3e734e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -804,11 +804,6 @@ static bool dce80_validate_surface_sets( if (set[i].surface_count > 1) return false; - if (set[i].surfaces[0]->clip_rect.width - > set[i].stream->src.width - || set[i].surfaces[0]->clip_rect.height - > set[i].stream->src.height) - return false; if (set[i].surfaces[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; -- GitLab From e8d726b71c55fb5c20fcf76bdea93c148a4b11e5 Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Wed, 29 Mar 2017 12:05:15 -0400 Subject: [PATCH 0355/2898] drm/amd/display: refactor member referencing to improve readability Signed-off-by: Reza Amini Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 107 +++++++----------- 1 file changed, 39 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 8f53d7a9f4dd..069f588a9e02 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1519,17 +1519,16 @@ static void set_avi_info_frame( uint8_t cn0_cn1 = 0; uint8_t *check_sum = NULL; uint8_t byte_index = 0; + union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; color_space = pipe_ctx->stream->public.output_color_space; /* Initialize header */ - info_frame.avi_info_packet.info_packet_hdmi.bits.header. - info_frame_type = HDMI_INFOFRAME_TYPE_AVI; + hdmi_info->bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall * not be used in HDMI 2.0 (Section 10.1) */ - info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2; - info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = - HDMI_AVI_INFOFRAME_SIZE; + hdmi_info->bits.header.version = 2; + hdmi_info->bits.header.length = HDMI_AVI_INFOFRAME_SIZE; /* * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built @@ -1555,52 +1554,41 @@ static void set_avi_info_frame( /* Y0_Y1_Y2 : The pixel encoding */ /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ - info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 = - pixel_encoding; + hdmi_info->bits.Y0_Y1_Y2 = pixel_encoding; /* A0 = 1 Active Format Information valid */ - info_frame.avi_info_packet.info_packet_hdmi.bits.A0 = - ACTIVE_FORMAT_VALID; + hdmi_info->bits.A0 = ACTIVE_FORMAT_VALID; /* B0, B1 = 3; Bar info data is valid */ - info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 = - BAR_INFO_BOTH_VALID; + hdmi_info->bits.B0_B1 = BAR_INFO_BOTH_VALID; - info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 = - PICTURE_SCALING_UNIFORM; + hdmi_info->bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; /* S0, S1 : Underscan / Overscan */ /* TODO: un-hardcode scan type */ scan_type = SCANNING_TYPE_UNDERSCAN; - info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; + hdmi_info->bits.S0_S1 = scan_type; /* C0, C1 : Colorimetry */ if (color_space == COLOR_SPACE_YCBCR709 || color_space == COLOR_SPACE_YCBCR709_LIMITED) - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_ITU709; + hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709; else if (color_space == COLOR_SPACE_YCBCR601 || color_space == COLOR_SPACE_YCBCR601_LIMITED) - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_ITU601; + hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601; else { if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB) BREAK_TO_DEBUGGER(); - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_NO_DATA; + hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA; } if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || color_space == COLOR_SPACE_2020_YCBCR) { - info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = - COLORIMETRYEX_BT2020RGBYCBCR; - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_EXTENDED; + hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; + hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED; } else if (color_space == COLOR_SPACE_ADOBERGB) { - info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 = - COLORIMETRYEX_ADOBERGB; - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_EXTENDED; + hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; + hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED; } /* TODO: un-hardcode aspect ratio */ @@ -1609,93 +1597,76 @@ static void set_avi_info_frame( switch (aspect) { case ASPECT_RATIO_4_3: case ASPECT_RATIO_16_9: - info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect; + hdmi_info->bits.M0_M1 = aspect; break; case ASPECT_RATIO_NO_DATA: case ASPECT_RATIO_64_27: case ASPECT_RATIO_256_135: default: - info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0; + hdmi_info->bits.M0_M1 = 0; } /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ - info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 = - ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; + hdmi_info->bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; /* TODO: un-hardcode cn0_cn1 and itc */ cn0_cn1 = 0; itc = false; if (itc) { - info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1; - info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 = - cn0_cn1; + hdmi_info->bits.ITC = 1; + hdmi_info->bits.CN0_CN1 = cn0_cn1; } /* TODO : We should handle YCC quantization */ /* but we do not have matrix calculation */ if (color_space == COLOR_SPACE_SRGB) { - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_FULL_RANGE; - info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = - YYC_QUANTIZATION_FULL_RANGE; + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; } else if (color_space == COLOR_SPACE_SRGB_LIMITED) { - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_LIMITED_RANGE; - info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = - YYC_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; } else { - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_DEFAULT_RANGE; - info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = - YYC_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; } - info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 = + hdmi_info->bits.VIC0_VIC7 = stream->public.timing.vic; /* pixel repetition * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel * repetition start from 1 */ - info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0; + hdmi_info->bits.PR0_PR3 = 0; /* Bar Info * barTop: Line Number of End of Top Bar. * barBottom: Line Number of Start of Bottom Bar. * barLeft: Pixel Number of End of Left Bar. * barRight: Pixel Number of Start of Right Bar. */ - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top = - stream->public.timing.v_border_top; - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom = - (stream->public.timing.v_border_top + hdmi_info->bits.bar_top = stream->public.timing.v_border_top; + hdmi_info->bits.bar_bottom = (stream->public.timing.v_border_top - stream->public.timing.v_border_bottom + 1); - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left = - stream->public.timing.h_border_left; - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right = - (stream->public.timing.h_total + hdmi_info->bits.bar_left = stream->public.timing.h_border_left; + hdmi_info->bits.bar_right = (stream->public.timing.h_total - stream->public.timing.h_border_right + 1); /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ - check_sum = - &info_frame. - avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; + check_sum = &info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; + *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2; for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++) - *check_sum += info_frame.avi_info_packet.info_packet_hdmi. - packet_raw_data.sb[byte_index]; + *check_sum += hdmi_info->packet_raw_data.sb[byte_index]; /* one byte complement */ *check_sum = (uint8_t) (0x100 - *check_sum); /* Store in hw_path_mode */ - info_packet->hb0 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0; - info_packet->hb1 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1; - info_packet->hb2 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; + info_packet->hb0 = hdmi_info->packet_raw_data.hb0; + info_packet->hb1 = hdmi_info->packet_raw_data.hb1; + info_packet->hb2 = hdmi_info->packet_raw_data.hb2; for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet. info_packet_hdmi.packet_raw_data.sb); byte_index++) -- GitLab From bddd696ddd437ce15d278b2a5318ef44d3c171cd Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Wed, 29 Mar 2017 17:21:56 -0400 Subject: [PATCH 0356/2898] drm/amd/display: Temporary disable PSR for HBR2 & HBR3 Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 4f6d1d2d5b9b..b8c40e8bee5a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2165,7 +2165,8 @@ static void retrieve_link_cap(struct core_link *link) CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); /* TODO: Confirm if need retrieve_psr_link_cap */ - retrieve_psr_link_cap(link, link->edp_revision); + if (link->public.reported_link_cap.link_rate < LINK_RATE_HIGH2) + retrieve_psr_link_cap(link, link->edp_revision); } void detect_dp_sink_caps(struct core_link *link) -- GitLab From dff06ddd7f0d322a046fd4a34dec589fbb97adef Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 29 Mar 2017 16:24:19 -0400 Subject: [PATCH 0357/2898] drm/amd/display: fix dce_calc surface pitch setting for non underlay pipes Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 5ac614f433f8..627b7582394a 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2614,7 +2614,7 @@ static void populate_initial_data( data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); - data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); @@ -2712,7 +2712,7 @@ static void populate_initial_data( data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); if (pipe[i].surface) { data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); - data->pitch_in_pixels[num_displays + 4] = bw_int_to_fixed(pipe[i].surface->public.plane_size.grph.surface_pitch); + data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); -- GitLab From 9fb8de78ed01453ccc696a9f18cbfe41c60fd433 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 14 Feb 2017 13:50:17 -0500 Subject: [PATCH 0358/2898] drm/amd/display: Remove get_connector_for_link. We can keep a 1:1 relation between a link and a physical connector and hence skip the iteration. This function is used in context of only physical connetors. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 36 +++---------------- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 1 + drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index d4e01b51f949..bdf7c6075414 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -148,21 +148,6 @@ static struct amdgpu_connector *get_connector_for_sink( return NULL; } -static struct amdgpu_connector *get_connector_for_link( - struct drm_device *dev, - const struct dc_link *link) -{ - struct drm_connector *connector; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - if (aconnector->dc_link == link) - return aconnector; - } - - return NULL; -} - static void get_payload_table( struct amdgpu_connector *aconnector, struct dp_mst_stream_allocation_table *proposed_table) @@ -363,9 +348,7 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -388,9 +371,7 @@ void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, const struct dc_link *link) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -412,9 +393,7 @@ bool dm_helpers_dp_read_dpcd( uint32_t size) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -432,10 +411,7 @@ bool dm_helpers_dp_write_dpcd( const uint8_t *data, uint32_t size) { - - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -451,9 +427,7 @@ bool dm_helpers_submit_i2c( const struct dc_link *link, struct i2c_command *cmd) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; - struct amdgpu_connector *aconnector = get_connector_for_link(dev, link); + struct amdgpu_connector *aconnector = link->priv; struct i2c_msg *msgs; int i = 0; int num = cmd->number_of_payloads; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index aa243584b2cc..df7cc463b946 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2002,6 +2002,7 @@ int amdgpu_dm_connector_init( struct dc *dc = dm->dc; const struct dc_link *link = dc_get_link_at_index(dc, link_index); struct amdgpu_i2c_adapter *i2c; + ((struct dc_link *)link)->priv = aconnector; DRM_DEBUG_KMS("%s()\n", __func__); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9dd8b2ad4c59..6bb6ad23b31b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -592,6 +592,8 @@ struct dc_link { struct psr_caps psr_caps; bool test_pattern_enabled; union compliance_test_state compliance_test_state; + + void *priv; }; struct dpcd_caps { -- GitLab From 5c4e9806435d7da665af08b3071446b9617eb9cb Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 14 Feb 2017 15:47:24 -0500 Subject: [PATCH 0359/2898] drm/amd/display: Remove get_connector_for_sink. Keep 1:1 relation between MST sink and it's MST connector. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 27 +++---------------- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 7 ++++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index bdf7c6075414..bc0bfa9586ee 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -133,21 +133,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps( return result; } -static struct amdgpu_connector *get_connector_for_sink( - struct drm_device *dev, - const struct dc_sink *sink) -{ - struct drm_connector *connector; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - if (aconnector->dc_sink == sink) - return aconnector; - } - - return NULL; -} - static void get_payload_table( struct amdgpu_connector *aconnector, struct dp_mst_stream_allocation_table *proposed_table) @@ -194,8 +179,6 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( struct dp_mst_stream_allocation_table *proposed_table, bool enable) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; struct amdgpu_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; @@ -205,7 +188,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( int bpp = 0; int pbn = 0; - aconnector = get_connector_for_sink(dev, stream->sink); + aconnector = stream->sink->priv; if (!aconnector || !aconnector->mst_port) return false; @@ -284,13 +267,11 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( struct dc_context *ctx, const struct dc_stream *stream) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; struct amdgpu_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; int ret; - aconnector = get_connector_for_sink(dev, stream->sink); + aconnector = stream->sink->priv; if (!aconnector || !aconnector->mst_port) return false; @@ -313,14 +294,12 @@ bool dm_helpers_dp_mst_send_payload_allocation( const struct dc_stream *stream, bool enable) { - struct amdgpu_device *adev = ctx->driver_context; - struct drm_device *dev = adev->ddev; struct amdgpu_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; int ret; - aconnector = get_connector_for_sink(dev, stream->sink); + aconnector = stream->sink->priv; if (!aconnector || !aconnector->mst_port) return false; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 41988c89d471..069511bb6fab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -325,6 +325,7 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) struct drm_connector *connector; struct amdgpu_connector *aconnector; struct edid *edid; + struct dc_sink *dc_sink; drm_modeset_lock_all(dev); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -352,11 +353,15 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) aconnector->edid = edid; - aconnector->dc_sink = dc_link_add_remote_sink( + dc_sink = dc_link_add_remote_sink( aconnector->dc_link, (uint8_t *)edid, (edid->extensions + 1) * EDID_LENGTH, &init_params); + + dc_sink->priv = aconnector; + aconnector->dc_sink = dc_sink; + if (aconnector->dc_sink) amdgpu_dm_add_sink_to_freesync_module( connector, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6bb6ad23b31b..d2960552c78e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -719,6 +719,7 @@ struct dc_sink { struct dc_container_id *dc_container_id; uint32_t dongle_max_pix_clk; bool converter_disable_audio; + void *priv; }; void dc_sink_retain(const struct dc_sink *sink); -- GitLab From bb01672c79649de08fe335b55aea5315d781c443 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sat, 4 Mar 2017 20:56:46 -0500 Subject: [PATCH 0360/2898] drm/amd/display: Fix i2c write flag. I2C_M_RD was translated to write instead of read. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index bc0bfa9586ee..5b096be44e59 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -423,7 +423,7 @@ bool dm_helpers_submit_i2c( return false; for (i = 0; i < num; i++) { - msgs[i].flags = cmd->payloads[i].write ? I2C_M_RD : 0; + msgs[i].flags = cmd->payloads[i].write ? 0 : I2C_M_RD; msgs[i].addr = cmd->payloads[i].address; msgs[i].len = cmd->payloads[i].length; msgs[i].buf = cmd->payloads[i].data; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index df7cc463b946..c09af2b3350c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1948,7 +1948,7 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, cmd.speed = 100; for (i = 0; i < num; i++) { - cmd.payloads[i].write = (msgs[i].flags & I2C_M_RD); + cmd.payloads[i].write = !(msgs[i].flags & I2C_M_RD); cmd.payloads[i].address = msgs[i].addr; cmd.payloads[i].length = msgs[i].len; cmd.payloads[i].data = msgs[i].buf; -- GitLab From 7c7f5b15be6528b33d825ead6acb739d7d061a2e Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 28 Mar 2017 16:57:52 -0400 Subject: [PATCH 0361/2898] drm/amd/display: Refactor edid read. Allow Linux to use DRM provided EDID read functioality by moving DAL edid implementation to module hence removing this code from DC by this cleaning up DC code for upstream. v2: Removing ddc_service. No more need for it. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 47 +++ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 47 ++- .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 2 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 10 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 78 +++- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 53 +-- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 337 +----------------- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 30 +- drivers/gpu/drm/amd/display/dc/dc.h | 21 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 6 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 10 + .../gpu/drm/amd/display/dc/i2caux/i2caux.c | 9 +- .../gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 38 +- .../amd/display/include/ddc_service_types.h | 28 -- .../amd/display/include/i2caux_interface.h | 3 + 15 files changed, 254 insertions(+), 465 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 5b096be44e59..01d04fa2419e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -435,3 +435,50 @@ bool dm_helpers_submit_i2c( return result; } + +enum dc_edid_status dm_helpers_read_local_edid( + struct dc_context *ctx, + struct dc_link *link, + struct dc_sink *sink) +{ + struct amdgpu_connector *aconnector = link->priv; + struct i2c_adapter *ddc; + int retry = 3; + enum dc_edid_status edid_status; + struct edid *edid; + + if (link->aux_mode) + ddc = &aconnector->dm_dp_aux.aux.ddc; + else + ddc = &aconnector->i2c->base; + + /* some dongles read edid incorrectly the first time, + * do check sum and retry to make sure read correct edid. + */ + do { + + edid = drm_get_edid(&aconnector->base, ddc); + + if (!edid) + return EDID_NO_RESPONSE; + + sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1); + memmove(sink->dc_edid.raw_edid, (uint8_t *)edid, sink->dc_edid.length); + + /* We don't need the original edid anymore */ + kfree(edid); + + edid_status = dm_helpers_parse_edid_caps( + ctx, + &sink->dc_edid, + &sink->edid_caps); + + } while (edid_status == EDID_BAD_CHECKSUM && --retry > 0); + + if (edid_status != EDID_OK) + DRM_ERROR("EDID err: %d, on connector: %s", + edid_status, + aconnector->base.name); + + return edid_status; +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 069511bb6fab..187464ac27b3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -81,24 +81,43 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg struct drm_device *drm_dev = pci_get_drvdata(pdev); struct amdgpu_device *adev = drm_dev->dev_private; struct dc *dc = adev->dm.dc; + enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? I2C_MOT_TRUE : I2C_MOT_FALSE; bool res; - switch (msg->request) { + switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_READ: - res = dc_read_dpcd( - dc, - TO_DM_AUX(aux)->link_index, - msg->address, - msg->buffer, - msg->size); + res = dc_read_aux_dpcd( + dc, + TO_DM_AUX(aux)->link_index, + msg->address, + msg->buffer, + msg->size); break; case DP_AUX_NATIVE_WRITE: - res = dc_write_dpcd( - dc, - TO_DM_AUX(aux)->link_index, - msg->address, - msg->buffer, - msg->size); + res = dc_write_aux_dpcd( + dc, + TO_DM_AUX(aux)->link_index, + msg->address, + msg->buffer, + msg->size); + break; + case DP_AUX_I2C_READ: + res = dc_read_aux_i2c( + dc, + TO_DM_AUX(aux)->link_index, + mot, + msg->address, + msg->buffer, + msg->size); + break; + case DP_AUX_I2C_WRITE: + res = dc_write_aux_i2c( + dc, + TO_DM_AUX(aux)->link_index, + mot, + msg->address, + msg->buffer, + msg->size); break; default: return 0; @@ -418,7 +437,7 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { .register_connector = dm_dp_mst_register_connector }; -void amdgpu_dm_initialize_mst_connector( +void amdgpu_dm_initialize_dp_connector( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 6130d62ac65c..418061f3b46b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -29,7 +29,7 @@ struct amdgpu_display_manager; struct amdgpu_connector; -void amdgpu_dm_initialize_mst_connector( +void amdgpu_dm_initialize_dp_connector( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c09af2b3350c..345df1b6d82b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2047,7 +2047,7 @@ int amdgpu_dm_connector_init( if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_eDP) - amdgpu_dm_initialize_mst_connector(dm, aconnector); + amdgpu_dm_initialize_dp_connector(dm, aconnector); #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) @@ -3038,9 +3038,11 @@ static bool is_dp_capable_without_timing_msa( uint8_t dpcd_data; bool capable = false; if (amdgpu_connector->dc_link && - dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index, - DP_DOWN_STREAM_PORT_COUNT, - &dpcd_data, sizeof(dpcd_data)) ) + dc_read_aux_dpcd( + dc, + amdgpu_connector->dc_link->link_index, + DP_DOWN_STREAM_PORT_COUNT, + &dpcd_data, sizeof(dpcd_data))) capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; return capable; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b3891228b499..40a800155fe6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1553,7 +1553,7 @@ void dc_resume(const struct dc *dc) core_link_resume(core_dc->links[i]); } -bool dc_read_dpcd( +bool dc_read_aux_dpcd( struct dc *dc, uint32_t link_index, uint32_t address, @@ -1565,56 +1565,100 @@ bool dc_read_dpcd( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( link->ddc, + false, + I2C_MOT_UNDEF, address, data, size); return r == DDC_RESULT_SUCESSFULL; } -bool dc_query_ddc_data( +bool dc_write_aux_dpcd( struct dc *dc, uint32_t link_index, uint32_t address, - uint8_t *write_buf, - uint32_t write_size, - uint8_t *read_buf, - uint32_t read_size) { - + const uint8_t *data, + uint32_t size) +{ struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; - bool result = dal_ddc_service_query_ddc_data( + enum ddc_result r = dal_ddc_service_write_dpcd_data( link->ddc, + false, + I2C_MOT_UNDEF, address, - write_buf, - write_size, - read_buf, - read_size); - - return result; + data, + size); + return r == DDC_RESULT_SUCESSFULL; } +bool dc_read_aux_i2c( + struct dc *dc, + uint32_t link_index, + enum i2c_mot_mode mot, + uint32_t address, + uint8_t *data, + uint32_t size) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); -bool dc_write_dpcd( + struct core_link *link = core_dc->links[link_index]; + enum ddc_result r = dal_ddc_service_read_dpcd_data( + link->ddc, + true, + mot, + address, + data, + size); + return r == DDC_RESULT_SUCESSFULL; +} + +bool dc_write_aux_i2c( struct dc *dc, uint32_t link_index, + enum i2c_mot_mode mot, uint32_t address, const uint8_t *data, uint32_t size) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( link->ddc, + true, + mot, address, data, size); return r == DDC_RESULT_SUCESSFULL; } +bool dc_query_ddc_data( + struct dc *dc, + uint32_t link_index, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size) { + + struct core_dc *core_dc = DC_TO_CORE(dc); + + struct core_link *link = core_dc->links[link_index]; + + bool result = dal_ddc_service_query_ddc_data( + link->ddc, + address, + write_buf, + write_size, + read_buf, + read_size); + + return result; +} + bool dc_submit_i2c( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 74dd272d7452..0f825f6326ab 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -464,39 +464,6 @@ static void link_disconnect_sink(struct core_link *link) link->dpcd_sink_count = 0; } -static enum dc_edid_status read_edid( - struct core_link *link, - struct core_sink *sink) -{ - uint32_t edid_retry = 3; - enum dc_edid_status edid_status; - - /* some dongles read edid incorrectly the first time, - * do check sum and retry to make sure read correct edid. - */ - do { - sink->public.dc_edid.length = - dal_ddc_service_edid_query(link->ddc); - - if (0 == sink->public.dc_edid.length) - return EDID_NO_RESPONSE; - - dal_ddc_service_get_edid_buf(link->ddc, - sink->public.dc_edid.raw_edid); - edid_status = dm_helpers_parse_edid_caps( - sink->ctx, - &sink->public.dc_edid, - &sink->public.edid_caps); - --edid_retry; - if (edid_status == EDID_BAD_CHECKSUM) - dm_logger_write(link->ctx->logger, LOG_WARNING, - "Bad EDID checksum, retry remain: %d\n", - edid_retry); - } while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0); - - return edid_status; -} - static void detect_dp( struct core_link *link, struct display_sink_capability *sink_caps, @@ -673,6 +640,9 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) link->ddc, sink_caps.transaction_type); + link->public.aux_mode = dal_ddc_service_is_in_aux_transaction_mode( + link->ddc); + sink_init_data.link = &link->public; sink_init_data.sink_signal = sink_caps.signal; @@ -688,7 +658,10 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) sink = DC_SINK_TO_CORE(dc_sink); link->public.local_sink = &sink->public; - edid_status = read_edid(link, sink); + edid_status = dm_helpers_read_local_edid( + link->ctx, + &link->public, + &sink->public); switch (edid_status) { case EDID_BAD_CHECKSUM: @@ -1500,11 +1473,13 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, */ psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1; } - dal_ddc_service_write_dpcd_data( - link->ddc, - 368, - &psr_configuration.raw, - sizeof(psr_configuration.raw)); + + dm_helpers_dp_write_dpcd( + link->ctx, + dc_link, + 368, + &psr_configuration.raw, + sizeof(psr_configuration.raw)); psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; if (psr_context.channel == 0) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 4e9465b630d1..2f5a89c5b063 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -58,30 +58,6 @@ struct dp_hdmi_dongle_signature_data { uint8_t eot;/* end of transmition '\x4' */ }; -/* Address range from 0x00 to 0x1F.*/ -#define DP_ADAPTOR_TYPE2_SIZE 0x20 -#define DP_ADAPTOR_TYPE2_REG_ID 0x10 -#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D -/* Identifies adaptor as Dual-mode adaptor */ -#define DP_ADAPTOR_TYPE2_ID 0xA0 -/* MHz*/ -#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 -/* MHz*/ -#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 -/* kHZ*/ -#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 -/* kHZ*/ -#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 - -#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW - -enum edid_read_result { - EDID_READ_RESULT_EDID_MATCH = 0, - EDID_READ_RESULT_EDID_MISMATCH, - EDID_READ_RESULT_CHECKSUM_READ_ERR, - EDID_READ_RESULT_VENDOR_READ_ERR -}; - /* SCDC Address defines (HDMI 2.0)*/ #define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3 #define HDMI_SCDC_ADDRESS 0x54 @@ -392,7 +368,7 @@ static uint32_t defer_delay_converter_wa( #define DP_TRANSLATOR_DELAY 5 -static uint32_t get_defer_delay(struct ddc_service *ddc) +uint32_t get_defer_delay(struct ddc_service *ddc) { uint32_t defer_delay = 0; @@ -451,307 +427,6 @@ static bool i2c_read( &command); } -static uint8_t aux_read_edid_block( - struct ddc_service *ddc, - uint8_t address, - uint8_t index, - uint8_t *buf) -{ - struct aux_command cmd = { - .payloads = NULL, - .number_of_payloads = 0, - .defer_delay = get_defer_delay(ddc), - .max_defer_write_retry = 0 }; - - uint8_t retrieved = 0; - uint8_t base_offset = - (index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE; - uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; - - for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE; - retrieved += DEFAULT_AUX_MAX_DATA_SIZE) { - - uint8_t offset = base_offset + retrieved; - - struct aux_payload payloads[3] = { - { - .i2c_over_aux = true, - .write = true, - .address = DDC_EDID_SEGMENT_ADDRESS, - .length = 1, - .data = &segment }, - { - .i2c_over_aux = true, - .write = true, - .address = address, - .length = 1, - .data = &offset }, - { - .i2c_over_aux = true, - .write = false, - .address = address, - .length = DEFAULT_AUX_MAX_DATA_SIZE, - .data = &buf[retrieved] } }; - - if (segment == 0) { - cmd.payloads = &payloads[1]; - cmd.number_of_payloads = 2; - } else { - cmd.payloads = payloads; - cmd.number_of_payloads = 3; - } - - if (!dal_i2caux_submit_aux_command( - ddc->ctx->i2caux, - ddc->ddc_pin, - &cmd)) - /* cannot read, break*/ - break; - } - - /* Reset segment to 0. Needed by some panels */ - if (0 != segment) { - struct aux_payload payloads[1] = { { - .i2c_over_aux = true, - .write = true, - .address = DDC_EDID_SEGMENT_ADDRESS, - .length = 1, - .data = &segment } }; - bool result = false; - - segment = 0; - - cmd.number_of_payloads = ARRAY_SIZE(payloads); - cmd.payloads = payloads; - - result = dal_i2caux_submit_aux_command( - ddc->ctx->i2caux, - ddc->ddc_pin, - &cmd); - - if (false == result) - dm_logger_write( - ddc->ctx->logger, LOG_ERROR, - "%s: Writing of EDID Segment (0x30) failed!\n", - __func__); - } - - return retrieved; -} - -static uint8_t i2c_read_edid_block( - struct ddc_service *ddc, - uint8_t address, - uint8_t index, - uint8_t *buf) -{ - bool ret = false; - uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) * - DDC_EDID_BLOCK_SIZE; - uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; - - struct i2c_command cmd = { - .payloads = NULL, - .number_of_payloads = 0, - .engine = DDC_I2C_COMMAND_ENGINE, - .speed = ddc->ctx->dc->caps.i2c_speed_in_khz }; - - struct i2c_payload payloads[3] = { - { - .write = true, - .address = DDC_EDID_SEGMENT_ADDRESS, - .length = 1, - .data = &segment }, - { - .write = true, - .address = address, - .length = 1, - .data = &offset }, - { - .write = false, - .address = address, - .length = DDC_EDID_BLOCK_SIZE, - .data = buf } }; -/* - * Some I2C engines don't handle stop/start between write-offset and read-data - * commands properly. For those displays, we have to force the newer E-DDC - * behavior of repeated-start which can be enabled by runtime parameter. */ -/* Originally implemented for OnLive using NXP receiver chip */ - - if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) { - /* base block, use use DDC2B, submit as 2 commands */ - cmd.payloads = &payloads[1]; - cmd.number_of_payloads = 1; - - if (dm_helpers_submit_i2c( - ddc->ctx, - &ddc->link->public, - &cmd)) { - - cmd.payloads = &payloads[2]; - cmd.number_of_payloads = 1; - - ret = dm_helpers_submit_i2c( - ddc->ctx, - &ddc->link->public, - &cmd); - } - - } else { - /* - * extension block use E-DDC, submit as 1 command - * or if repeated-start is forced by runtime parameter - */ - if (segment != 0) { - /* include segment offset in command*/ - cmd.payloads = payloads; - cmd.number_of_payloads = 3; - } else { - /* we are reading first segment, - * segment offset is not required */ - cmd.payloads = &payloads[1]; - cmd.number_of_payloads = 2; - } - - ret = dm_helpers_submit_i2c( - ddc->ctx, - &ddc->link->public, - &cmd); - } - - return ret ? DDC_EDID_BLOCK_SIZE : 0; -} - -static uint32_t query_edid_block( - struct ddc_service *ddc, - uint8_t address, - uint8_t index, - uint8_t *buf, - uint32_t size) -{ - uint32_t size_retrieved = 0; - - if (size < DDC_EDID_BLOCK_SIZE) - return 0; - - if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { - size_retrieved = - aux_read_edid_block(ddc, address, index, buf); - } else { - size_retrieved = - i2c_read_edid_block(ddc, address, index, buf); - } - - return size_retrieved; -} - -#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261 -#define DDC_TEST_ACK_ADDRESS 0x260 -#define DDC_DPCD_EDID_TEST_ACK 0x04 -#define DDC_DPCD_EDID_TEST_MASK 0x04 -#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218 - -/* AG TODO GO throug DM callback here like for DPCD */ - -static void write_dp_edid_checksum( - struct ddc_service *ddc, - uint8_t checksum) -{ - uint8_t dpcd_data; - - dal_ddc_service_read_dpcd_data( - ddc, - DDC_DPCD_TEST_REQUEST_ADDRESS, - &dpcd_data, - 1); - - if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) { - - dal_ddc_service_write_dpcd_data( - ddc, - DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS, - &checksum, - 1); - - dpcd_data = DDC_DPCD_EDID_TEST_ACK; - - dal_ddc_service_write_dpcd_data( - ddc, - DDC_TEST_ACK_ADDRESS, - &dpcd_data, - 1); - } -} - -uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc) -{ - uint32_t bytes_read = 0; - uint32_t ext_cnt = 0; - - uint8_t address; - uint32_t i; - - for (address = DDC_EDID_ADDRESS_START; - address <= DDC_EDID_ADDRESS_END; ++address) { - - bytes_read = query_edid_block( - ddc, - address, - 0, - ddc->edid_buf, - sizeof(ddc->edid_buf) - bytes_read); - - if (bytes_read != DDC_EDID_BLOCK_SIZE) - continue; - - /* get the number of ext blocks*/ - ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET]; - - /* EDID 2.0, need to read 1 more block because EDID2.0 is - * 256 byte in size*/ - if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] == - DDC_EDID_20_SIGNATURE) - ext_cnt = 1; - - for (i = 0; i < ext_cnt; i++) { - /* read additional ext blocks accordingly */ - bytes_read += query_edid_block( - ddc, - address, - i+1, - &ddc->edid_buf[bytes_read], - sizeof(ddc->edid_buf) - bytes_read); - } - - /*this is special code path for DP compliance*/ - if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type) - write_dp_edid_checksum( - ddc, - ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) + - DDC_EDID1X_CHECKSUM_OFFSET]); - - /*remembers the address where we fetch the EDID from - * for later signature check use */ - ddc->address = address; - - break;/* already read edid, done*/ - } - - ddc->edid_buf_len = bytes_read; - return bytes_read; -} - -uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc) -{ - return ddc->edid_buf_len; -} - -void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf) -{ - memmove(edid_buf, - ddc->edid_buf, ddc->edid_buf_len); -} - void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( struct ddc_service *ddc, struct display_sink_capability *sink_cap) @@ -960,12 +635,14 @@ bool dal_ddc_service_query_ddc_data( enum ddc_result dal_ddc_service_read_dpcd_data( struct ddc_service *ddc, + bool i2c, + enum i2c_mot_mode mot, uint32_t address, uint8_t *data, uint32_t len) { struct aux_payload read_payload = { - .i2c_over_aux = false, + .i2c_over_aux = i2c, .write = false, .address = address, .length = len, @@ -976,6 +653,7 @@ enum ddc_result dal_ddc_service_read_dpcd_data( .number_of_payloads = 1, .defer_delay = 0, .max_defer_write_retry = 0, + .mot = mot }; if (len > DEFAULT_AUX_MAX_DATA_SIZE) { @@ -994,12 +672,14 @@ enum ddc_result dal_ddc_service_read_dpcd_data( enum ddc_result dal_ddc_service_write_dpcd_data( struct ddc_service *ddc, + bool i2c, + enum i2c_mot_mode mot, uint32_t address, const uint8_t *data, uint32_t len) { struct aux_payload write_payload = { - .i2c_over_aux = false, + .i2c_over_aux = i2c, .write = true, .address = address, .length = len, @@ -1010,6 +690,7 @@ enum ddc_result dal_ddc_service_write_dpcd_data( .number_of_payloads = 1, .defer_delay = 0, .max_defer_write_retry = 0, + .mot = mot }; if (len > DEFAULT_AUX_MAX_DATA_SIZE) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index b8c40e8bee5a..9f12ba87827a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1481,22 +1481,25 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) if (link->public.psr_caps.psr_version == 0) return false; - dal_ddc_service_read_dpcd_data( - link->ddc, - 368 /*DpcdAddress_PSR_Enable_Cfg*/, - &psr_configuration.raw, - sizeof(psr_configuration.raw)); + dm_helpers_dp_read_dpcd( + link->ctx, + &link->public, + 368,/*DpcdAddress_PSR_Enable_Cfg*/ + &psr_configuration.raw, + sizeof(psr_configuration.raw)); + if (psr_configuration.bits.ENABLE) { unsigned char dpcdbuf[3] = {0}; union psr_error_status psr_error_status; union psr_sink_psr_status psr_sink_psr_status; - dal_ddc_service_read_dpcd_data( - link->ddc, - 0x2006 /*DpcdAddress_PSR_Error_Status*/, - (unsigned char *) dpcdbuf, - sizeof(dpcdbuf)); + dm_helpers_dp_read_dpcd( + link->ctx, + &link->public, + 0x2006, /*DpcdAddress_PSR_Error_Status*/ + (unsigned char *) dpcdbuf, + sizeof(dpcdbuf)); /*DPCD 2006h ERROR STATUS*/ psr_error_status.raw = dpcdbuf[0]; @@ -1506,9 +1509,10 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) if (psr_error_status.bits.LINK_CRC_ERROR || psr_error_status.bits.RFB_STORAGE_ERROR) { /* Acknowledge and clear error bits */ - dal_ddc_service_write_dpcd_data( - link->ddc, - 8198 /*DpcdAddress_PSR_Error_Status*/, + dm_helpers_dp_write_dpcd( + link->ctx, + &link->public, + 8198,/*DpcdAddress_PSR_Error_Status*/ &psr_error_status.raw, sizeof(psr_error_status.raw)); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d2960552c78e..a27a6aba0df1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -594,6 +594,7 @@ struct dc_link { union compliance_test_state compliance_test_state; void *priv; + bool aux_mode; }; struct dpcd_caps { @@ -788,20 +789,36 @@ const struct ddc_service *dc_get_ddc_at_index( * DPCD access interfaces */ -bool dc_read_dpcd( +bool dc_read_aux_dpcd( struct dc *dc, uint32_t link_index, uint32_t address, uint8_t *data, uint32_t size); -bool dc_write_dpcd( +bool dc_write_aux_dpcd( struct dc *dc, uint32_t link_index, uint32_t address, const uint8_t *data, uint32_t size); +bool dc_read_aux_i2c( + struct dc *dc, + uint32_t link_index, + enum i2c_mot_mode mot, + uint32_t address, + uint8_t *data, + uint32_t size); + +bool dc_write_aux_i2c( + struct dc *dc, + uint32_t link_index, + enum i2c_mot_mode mot, + uint32_t address, + const uint8_t *data, + uint32_t size); + bool dc_query_ddc_data( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 242dd7b3b6b1..e0436e317341 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -489,4 +489,10 @@ struct psr_caps { unsigned int psr_sdp_transmit_line_num_deadline; }; +enum i2c_mot_mode { + I2C_MOT_UNDEF, + I2C_MOT_TRUE, + I2C_MOT_FALSE +}; + #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index d6c52d31f0f0..c15a25ce8049 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -98,4 +98,14 @@ bool dm_helpers_submit_i2c( struct i2c_command *cmd); + + + + +enum dc_edid_status dm_helpers_read_local_edid( + struct dc_context *ctx, + struct dc_link *link, + struct dc_sink *sink); + + #endif /* __DM_HELPERS__ */ diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index bd84b932aaae..0743265e933c 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -185,6 +185,7 @@ bool dal_i2caux_submit_aux_command( struct aux_engine *engine; uint8_t index_of_payload = 0; bool result; + bool mot; if (!ddc) { BREAK_TO_DEBUGGER(); @@ -207,12 +208,14 @@ bool dal_i2caux_submit_aux_command( result = true; while (index_of_payload < cmd->number_of_payloads) { - bool mot = (index_of_payload != cmd->number_of_payloads - 1); - struct aux_payload *payload = cmd->payloads + index_of_payload; - struct i2caux_transaction_request request = { 0 }; + if (cmd->mot == I2C_MOT_UNDEF) + mot = (index_of_payload != cmd->number_of_payloads - 1); + else + mot = (cmd->mot == I2C_MOT_TRUE); + request.operation = payload->write ? I2CAUX_TRANSACTION_WRITE : I2CAUX_TRANSACTION_READ; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h index 830fc3d039c9..9c2f670c3dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -31,6 +31,23 @@ #define EDID_SEGMENT_SIZE 256 +/* Address range from 0x00 to 0x1F.*/ +#define DP_ADAPTOR_TYPE2_SIZE 0x20 +#define DP_ADAPTOR_TYPE2_REG_ID 0x10 +#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D +/* Identifies adaptor as Dual-mode adaptor */ +#define DP_ADAPTOR_TYPE2_ID 0xA0 +/* MHz*/ +#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 +/* MHz*/ +#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 +/* kHZ*/ +#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 +/* kHZ*/ +#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 + +#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW + struct ddc_service; struct graphics_object_id; enum ddc_result; @@ -83,12 +100,6 @@ void dal_ddc_service_set_transaction_type( bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc); -uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc); - -uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc); - -void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf); - void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( struct ddc_service *ddc, struct display_sink_capability *sink_cap); @@ -103,12 +114,16 @@ bool dal_ddc_service_query_ddc_data( enum ddc_result dal_ddc_service_read_dpcd_data( struct ddc_service *ddc, + bool i2c, + enum i2c_mot_mode mot, uint32_t address, uint8_t *data, uint32_t len); enum ddc_result dal_ddc_service_write_dpcd_data( struct ddc_service *ddc, + bool i2c, + enum i2c_mot_mode mot, uint32_t address, const uint8_t *data, uint32_t len); @@ -130,16 +145,7 @@ void dal_ddc_service_set_ddc_pin( struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service); -enum ddc_result dal_ddc_service_read_dpcd_data( - struct ddc_service *ddc, - uint32_t address, - uint8_t *data, - uint32_t len); -enum ddc_result dal_ddc_service_write_dpcd_data( - struct ddc_service *ddc, - uint32_t address, - const uint8_t *data, - uint32_t len); +uint32_t get_defer_delay(struct ddc_service *ddc); #endif /* __DAL_DDC_SERVICE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index effe03b8f418..0ff2a899b8f7 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -115,34 +115,6 @@ struct av_sync_data { uint8_t aud_del_ins3;/* DPCD 0002Dh */ }; -/** EDID retrieval related constants, also used by MstMgr **/ - -#define DDC_EDID_SEGMENT_SIZE 256 -#define DDC_EDID_BLOCK_SIZE 128 -#define DDC_EDID_BLOCKS_PER_SEGMENT \ - (DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE) - -#define DDC_EDID_EXT_COUNT_OFFSET 0x7E - -#define DDC_EDID_ADDRESS_START 0x50 -#define DDC_EDID_ADDRESS_END 0x52 -#define DDC_EDID_SEGMENT_ADDRESS 0x30 - -/* signatures for Edid 1x */ -#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8 -#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4 -#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126 -#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2 -#define DDC_EDID1X_CHECKSUM_OFFSET 127 -/* signatures for Edid 20*/ -#define DDC_EDID_20_SIGNATURE_OFFSET 0 -#define DDC_EDID_20_SIGNATURE 0x20 - -#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1 -#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4 -#define DDC_EDID20_CHECKSUM_OFFSET 255 -#define DDC_EDID20_CHECKSUM_LEN 1 - /*DP to VGA converter*/ static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa"; /*DP to Dual link DVI converter*/ diff --git a/drivers/gpu/drm/amd/display/include/i2caux_interface.h b/drivers/gpu/drm/amd/display/include/i2caux_interface.h index d2ec04d1c592..13a3c82d118f 100644 --- a/drivers/gpu/drm/amd/display/include/i2caux_interface.h +++ b/drivers/gpu/drm/amd/display/include/i2caux_interface.h @@ -26,6 +26,7 @@ #ifndef __DAL_I2CAUX_INTERFACE_H__ #define __DAL_I2CAUX_INTERFACE_H__ +#include "dc_types.h" #include "gpio_service_interface.h" @@ -54,6 +55,8 @@ struct aux_command { /* zero means "use default value" */ uint32_t max_defer_write_retry; + + enum i2c_mot_mode mot; }; union aux_config { -- GitLab From 6848e9896b9c9a26a44ac6764ca4bb7351ae573e Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Thu, 30 Mar 2017 11:39:47 -0400 Subject: [PATCH 0362/2898] drm/amd/display: PSR Aux Channel and Static Screen Support Fix - Correct the aux channel selection according to DAL3 Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 0f825f6326ab..b878fb9697d7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1482,8 +1482,6 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, sizeof(psr_configuration.raw)); psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; - if (psr_context.channel == 0) - psr_context.channel = 1; psr_context.transmitterId = link->link_enc->transmitter; psr_context.engineId = link->link_enc->preferred_engine; -- GitLab From 28f72454320d2084cc082c8509135bdfd4012c10 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Thu, 30 Mar 2017 13:08:34 -0400 Subject: [PATCH 0363/2898] drm/amd/display: Fill in vrefresh and min_vblank_time for dce8/dce10 PPLib is now calling into DC to get vrefresh and min_vblank_time, but since full bandwidth calcs are missing for those generations, the pplib structures were never being filled. This change fills the currently required fields to prevent screen corruption. Signed-off-by: Jordan Lazare Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../display/dc/dce100/dce100_hw_sequencer.c | 21 +++++++++++++++++++ .../display/dc/dce100/dce100_hw_sequencer.h | 5 +++++ .../display/dc/dce110/dce110_hw_sequencer.c | 8 +++---- .../display/dc/dce110/dce110_hw_sequencer.h | 8 +++++++ .../amd/display/dc/dce80/dce80_hw_sequencer.c | 2 ++ 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index bd8e19f1038b..f11044e0245c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -104,6 +104,26 @@ static bool dce100_enable_display_power_gating( return false; } +void dce100_pplib_apply_display_requirements( + struct core_dc *dc, + struct validate_context *context) +{ + struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; + + pp_display_cfg->avail_mclk_switch_time_us = + dce110_get_min_vblank_time_us(context); + + dce110_fill_display_configs(context, pp_display_cfg); + + if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( + struct dm_pp_display_configuration)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + + dc->prev_display_config = *pp_display_cfg; +} + + + static void set_displaymarks( const struct core_dc *dc, struct validate_context *context) { @@ -116,6 +136,7 @@ static void set_bandwidth( bool decrease_allowed) { dc->hwss.set_displaymarks(dc, context); + dce100_pplib_apply_display_requirements(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index cf497ea605c8..f51d04a66a49 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -29,8 +29,13 @@ #include "core_types.h" struct core_dc; +struct validate_context; bool dce100_hw_sequencer_construct(struct core_dc *dc); +void dce100_pplib_apply_display_requirements( + struct core_dc *dc, + struct validate_context *context); + #endif /* __DC_HWSS_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2a3a39e31717..839c34409c63 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2097,7 +2097,7 @@ static void init_hw(struct core_dc *dc) } } -static void fill_display_configs( +void dce110_fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg) { @@ -2146,7 +2146,7 @@ static void fill_display_configs( pp_display_cfg->display_count = num_cfgs; } -static uint32_t get_min_vblank_time_us(const struct validate_context *context) +uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) { uint8_t j; uint32_t min_vertical_blank_time = -1; @@ -2224,13 +2224,13 @@ static void pplib_apply_display_requirements( = context->bw_results.required_sclk_deep_sleep; pp_display_cfg->avail_mclk_switch_time_us = - get_min_vblank_time_us(context); + dce110_get_min_vblank_time_us(context); /* TODO: dce11.2*/ pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; pp_display_cfg->disp_clk_khz = context->dispclk_khz; - fill_display_configs(context, pp_display_cfg); + dce110_fill_display_configs(context, pp_display_cfg); /* TODO: is this still applicable?*/ if (pp_display_cfg->display_count == 1) { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index a6b4d0d2429f..52462c17b2e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -30,6 +30,8 @@ #define GAMMA_HW_POINTS_NUM 256 struct core_dc; +struct validate_context; +struct dm_pp_display_configuration; bool dce110_hw_sequencer_construct(struct core_dc *dc); @@ -58,5 +60,11 @@ void dce110_power_down(struct core_dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); +void dce110_fill_display_configs( + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg); + +uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index 85a54d963f8d..9d4e7d8b836e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -31,6 +31,7 @@ #include "dce/dce_hwseq.h" #include "dce110/dce110_hw_sequencer.h" +#include "dce100/dce100_hw_sequencer.h" /* include DCE8 register header files */ #include "dce/dce_8_0_d.h" @@ -118,6 +119,7 @@ static void set_bandwidth( bool decrease_allowed) { dc->hwss.set_displaymarks(dc, context); + dce100_pplib_apply_display_requirements(dc, context); } -- GitLab From dd3f348f0013f2cb2508f72adb35285a34b2baf7 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 31 Mar 2017 13:53:42 -0400 Subject: [PATCH 0364/2898] drm/amd/display: Ignore visible flag when check surface update type. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 40a800155fe6..9a3507e743cf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1046,10 +1046,10 @@ static enum surface_update_type get_plane_info_update_type( temp_plane_info.rotation = u->surface->rotation; temp_plane_info.stereo_format = u->surface->stereo_format; temp_plane_info.tiling_info = u->surface->tiling_info; - temp_plane_info.visible = u->surface->visible; /* Special Validation parameters */ temp_plane_info.format = u->plane_info->format; + temp_plane_info.visible = u->plane_info->visible; if (memcmp(u->plane_info, &temp_plane_info, sizeof(struct dc_plane_info)) != 0) -- GitLab From 7160c74cd00bc0a5f143c24096e1a45c51f3d202 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Fri, 31 Mar 2017 17:14:20 -0400 Subject: [PATCH 0365/2898] drm/amd/display: Log clock source in error condition Signed-off-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 17cdd70a2c27..34c18712970c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -187,6 +187,7 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst], PIXEL_RATE_PLL_SOURCE, 1); } else { - DC_ERR("unknown clock source"); + DC_ERR("Unknown clock source. clk_src id: %d, TG_inst: %d", + clk_src->id, tg_inst); } } -- GitLab From 9faa423716b17b0c9ba92fd12737968de6918d88 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 31 Mar 2017 14:15:31 -0400 Subject: [PATCH 0366/2898] drm/amd/display: Fix s3 hang on resume. Avoid enabling CRTC_VERTICAL_INTERRUPT0 twice on resume. It's enabled once from within manage_dm_interrupts in mode set and another explicitly from amdgpu_dm_irq_resume_late. Seems it lead to CRTC hang. Signed-off-by: Andrey Grodzovsky Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 16 +++++++++++----- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1077af91884f..30148b4eabae 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -575,7 +575,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); - amdgpu_dm_irq_resume(adev); + amdgpu_dm_irq_resume_late(adev); return ret; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 682e9c3ad8e5..4aee146a848f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -504,8 +504,11 @@ int amdgpu_dm_irq_suspend( DRM_DEBUG_KMS("DM_IRQ: suspend\n"); - /* disable HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) { + /** + * Disable HW interrupt for HPD and HPDRX only since FLIP and VBLANK + * will be disabled from manage_dm_interrupts on disable CRTC. + */ + for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6RX; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) @@ -544,7 +547,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) return 0; } -int amdgpu_dm_irq_resume(struct amdgpu_device *adev) +int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) { int src; struct list_head *hnd_list_h, *hnd_list_l; @@ -554,8 +557,11 @@ int amdgpu_dm_irq_resume(struct amdgpu_device *adev) DRM_DEBUG_KMS("DM_IRQ: resume\n"); - /* re-enable HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) { + /** + * Renable HW interrupt for HPD and only since FLIP and VBLANK + * will be enabled from manage_dm_interrupts on enable CRTC. + */ + for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 9339861c8897..9d3007634266 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -117,6 +117,6 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev); * */ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev); -int amdgpu_dm_irq_resume(struct amdgpu_device *adev); +int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev); #endif /* __AMDGPU_DM_IRQ_H__ */ -- GitLab From 6f43fd6297c478995b6a9e61482272137ec36260 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:25:11 -0400 Subject: [PATCH 0367/2898] drm/amd/display: fix nullptr on vega initialization Signed-off-by: Jordan Lazare Reviewed-by: Tony Cheng Reviewed-by: Roman Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 30148b4eabae..a9b4eb0099ac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1427,6 +1427,7 @@ static int dm_early_init(void *handle) adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; + adev->mode_info.plane_type = dm_surfaces_type_default; break; default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); -- GitLab From 7df498fa4c241610ee22cfcfa648628d2ef908fd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 10 Apr 2017 15:37:32 -0400 Subject: [PATCH 0368/2898] drm/amd/display: Allow planes on all crtcs 4.9 kernel will always add the assigned crtc to possible_crtcs on a plane. This is no longer the case on newer kernels. Make sure we allow any plane on any crtc. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a9b4eb0099ac..1b39bf9b4278 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1090,7 +1090,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_planes; } mode_info->planes[i]->plane_type = mode_info->plane_type[i]; - if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 1)) { + if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 0xff)) { DRM_ERROR("KMS: Failed to initialize plane\n"); goto fail_free_planes; } -- GitLab From 664a2ed115f62422475a783e6db453483a316a80 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 27 Jan 2017 10:55:20 -0500 Subject: [PATCH 0369/2898] drm/amd/display: Fallback on legacy properties in atomic_get_properties We still rely on legacy properties. Fallback on legacy properties until we get to pull these into some atomic state. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 345df1b6d82b..2c48408849d8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1246,6 +1246,43 @@ struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( return NULL; } + +/** + * amdgpu_dm_atomic_get_property - fetch connector property value + * @connector: connector to fetch property for + * @state: state containing the property value + * @property: property to look up + * @val: pointer to write property value into + * + * The DRM core does not store shadow copies of properties for + * atomic-capable drivers. This entrypoint is used to fetch + * the current value of a driver-specific connector property. + */ +int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + int i; + + /* + * TODO: Get properties from atomic state or objs. Until it's ready, + * continue to look up all property values in the DRM's shadow copy + * in obj->properties->values[]. + * + * When the crtc/connector state work matures, this function should + * be updated to read the values out of the state structure instead. + */ + for (i = 0; i < connector->base.properties->count; i++) { + if (connector->base.properties->properties[i] == property) { + *val = connector->base.properties->values[i]; + return 0; + } + } + + return -EINVAL; +} + static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .reset = amdgpu_dm_connector_funcs_reset, .detect = amdgpu_dm_connector_detect, @@ -1253,7 +1290,8 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .destroy = amdgpu_dm_connector_destroy, .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - .atomic_set_property = amdgpu_dm_connector_atomic_set_property + .atomic_set_property = amdgpu_dm_connector_atomic_set_property, + .atomic_get_property = amdgpu_dm_connector_atomic_get_property, }; static struct drm_encoder *best_encoder(struct drm_connector *connector) -- GitLab From 32a1892a86a8f40c6f24807a9a0da31a322e4874 Mon Sep 17 00:00:00 2001 From: Pratik Vishwakarma Date: Thu, 6 Apr 2017 13:18:20 +0530 Subject: [PATCH 0370/2898] drm/amd/display: get_atomic_property missing for drm_connector_funcs DRM_IOCTL_MODE_GETCONNECTOR fails with EINVAL on enabling DRIVER_ATOMIC With this DRM_IOCTL_MODE_GETCONNECTOR returns all the connector properties. freesync_property and freesync_capable_property return 0 currently. TESTS(On Chromium OS on Stoney Only) * Builds without compilation errors. * 'atomictest' proceeds after applying patch and fails with vblank event timed out. * Chromium OS ui comes up. Signed-off-by: Pratik Vishwakarma Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 81 ++++++++++--------- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 6 ++ 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 2c48408849d8..ba1f3d40771a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1184,6 +1184,48 @@ int amdgpu_dm_connector_atomic_set_property( return ret; } +int amdgpu_dm_connector_atomic_get_property( + struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct dm_connector_state *dm_state = + to_dm_connector_state(state); + int ret = -EINVAL; + + if (property == dev->mode_config.scaling_mode_property) { + switch (dm_state->scaling) { + case RMX_CENTER: + *val = DRM_MODE_SCALE_CENTER; + break; + case RMX_ASPECT: + *val = DRM_MODE_SCALE_ASPECT; + break; + case RMX_FULL: + *val = DRM_MODE_SCALE_FULLSCREEN; + break; + case RMX_OFF: + default: + *val = DRM_MODE_SCALE_NONE; + break; + } + ret = 0; + } else if (property == adev->mode_info.underscan_hborder_property) { + *val = dm_state->underscan_hborder; + ret = 0; + } else if (property == adev->mode_info.underscan_vborder_property) { + *val = dm_state->underscan_vborder; + ret = 0; + } else if (property == adev->mode_info.underscan_property) { + *val = dm_state->underscan_enable; + ret = 0; + } + return ret; +} + void amdgpu_dm_connector_destroy(struct drm_connector *connector) { struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); @@ -1246,43 +1288,6 @@ struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( return NULL; } - -/** - * amdgpu_dm_atomic_get_property - fetch connector property value - * @connector: connector to fetch property for - * @state: state containing the property value - * @property: property to look up - * @val: pointer to write property value into - * - * The DRM core does not store shadow copies of properties for - * atomic-capable drivers. This entrypoint is used to fetch - * the current value of a driver-specific connector property. - */ -int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) -{ - int i; - - /* - * TODO: Get properties from atomic state or objs. Until it's ready, - * continue to look up all property values in the DRM's shadow copy - * in obj->properties->values[]. - * - * When the crtc/connector state work matures, this function should - * be updated to read the values out of the state structure instead. - */ - for (i = 0; i < connector->base.properties->count; i++) { - if (connector->base.properties->properties[i] == property) { - *val = connector->base.properties->values[i]; - return 0; - } - } - - return -EINVAL; -} - static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .reset = amdgpu_dm_connector_funcs_reset, .detect = amdgpu_dm_connector_detect, @@ -1291,7 +1296,7 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_set_property = amdgpu_dm_connector_atomic_set_property, - .atomic_get_property = amdgpu_dm_connector_atomic_get_property, + .atomic_get_property = amdgpu_dm_connector_atomic_get_property }; static struct drm_encoder *best_encoder(struct drm_connector *connector) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index ab6d51dbbf4b..b69c86826b1a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -71,6 +71,12 @@ int amdgpu_dm_connector_atomic_set_property( struct drm_property *property, uint64_t val); +int amdgpu_dm_connector_atomic_get_property( + struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val); + int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); void amdgpu_dm_connector_init_helper( -- GitLab From 753c66c91b5430816eedb67138017fd4e2143d52 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 24 Apr 2017 11:46:44 +0200 Subject: [PATCH 0371/2898] drm/amd/display: Fix race between vblank irq and pageflip irq. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since DC now uses CRTC_VERTICAL_INTERRUPT0 as VBLANK irq trigger and vblank interrupts actually happen earliest at start of vblank, instead of a bit before vblank, we no longer need some of the fudging logic to deal with too early vblank irq handling (grep for lb_vblank_lead_lines). This itself fixes a pageflip scheduling bug in DC, caused by uninitialized use of lb_vblank_lead_lines, with a wrong startup value of 0. Thanks to the new vblank irq trigger this value of zero is now actually correct for DC :). A new problem is that vblank irq's race against pflip irq's, and as both can fire at first line of vblank, it is no longer guaranteed that vblank irq handling (therefore -> drm_handle_vblank() -> drm_update_vblank_count()) executes before pflip irq handling for a given vblank interval when a pageflip completes. Therefore the vblank count and timestamps emitted to user-space as part of the pageflip completion event will be often stale and cause new timestamping and swap scheduling errors in user-space. This was observed with large frequency on R9 380 Tonga Pro. Fix this by enforcing a vblank count+timestamp update right before emitting the pageflip completion event from the pflip irq handler. The logic in core drm_update_vblank_count() makes sure that no redundant or conflicting updates happen, iow. the call turns into a no-op if it wasn't needed for that vblank, burning a few microseconds of cpu time though. Successfully tested on AMD R9 380 "Tonga Pro" (VI/DCE 10) with DC enabled on the current DC staging branch. Independent measurement of pageflip completion timing with special hardware measurement equipment now confirms correct pageflip timestamps and counts in the pageflip completion events. v2: Review comments by Michel, drop outdated paragraph about problem already fixed in 2nd patch of the series. Add acked/r-b by Harry and Michel. Signed-off-by: Mario Kleiner Acked-by: Harry Wentland (v1) Reviewed-by: Michel Dänzer Cc: Andrey Grodzovsky Cc: Alex Deucher Cc: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1b39bf9b4278..93f10bc772c4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -202,6 +202,9 @@ static void dm_pflip_high_irq(void *interrupt_params) if (amdgpu_crtc->event && amdgpu_crtc->event->event.base.type == DRM_EVENT_FLIP_COMPLETE) { + /* Update to correct count/ts if racing with vblank irq */ + drm_crtc_accurate_vblank_count(&amdgpu_crtc->base); + drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); /* page flip completed. clean up */ amdgpu_crtc->event = NULL; -- GitLab From 00d7930c5189a439ea4f3c1af071beb3134856d6 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 24 Apr 2017 18:54:20 +0200 Subject: [PATCH 0372/2898] drm/amd/display: Prevent premature pageflip when comitting in vblank. (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we do not program a hw pageflip inside vblank 'n' iff the atomic flip is comitted while inside the same vblank 'n'. We must defer such a flip by one refresh cycle to vblank 'n+1', unless this is a DRM_MODE_PAGE_FLIP_ASYNC async pageflip, which must always execute as soon as possible. Without this, pageflips programmed via X11 GLX_OML_sync_control extensions glXSwapBuffersMscOML(..., target_msc, ...); call and/or via DRI3/Present PresentPixmap(..., target_msc, ...); request will complete one vblank too early whenever target_msc > current_msc + 1, ie. more than 1 vblank in the future. In such a case, the call of the pageflip ioctl() would be triggered by a queued drmWaitVblank() vblank event, which itself gets dispatched inside the vblank one frame before the target_msc vblank. Testing with this patch does no longer show any problems with OML_sync_control swap scheduling or flip completion timestamps. Tested on R9 380 Tonga. v2: Add acked/r-b by Harry and Michel. v3: Feedback from Andrey: Must not wait an extra frame for DRM_MODE_PAGE_FLIP_ASYNC flips. Signed-off-by: Mario Kleiner Acked-by: Harry Wentland (v1) Reviewed-by: Michel Dänzer Reviewed-by: Andrey Grodzovsky Cc: Harry Wentland Cc: Alex Deucher Cc: Michel Dänzer Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ba1f3d40771a..4b0fc6b56969 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2305,6 +2305,9 @@ static void amdgpu_dm_do_flip( struct amdgpu_device *adev = crtc->dev->dev_private; bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + /* Prepare wait for target vblank early - before the fence-waits */ + target_vblank = target - drm_crtc_vblank_count(crtc) + + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); /*TODO This might fail and hence better not used, wait * explicitly on fences instead @@ -2323,13 +2326,9 @@ static void amdgpu_dm_do_flip( amdgpu_bo_unreserve(abo); - /* Wait for target vblank */ /* Wait until we're out of the vertical blank period before the one * targeted by the flip */ - target_vblank = target - drm_crtc_vblank_count(crtc) + - amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); - while ((acrtc->enabled && (amdgpu_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id, 0, &vpos, &hpos, NULL, NULL, @@ -2605,14 +2604,15 @@ void amdgpu_dm_atomic_commit_tail( pflip_needed = !state->allow_modeset; if (pflip_needed) { + wait_for_vblank = + acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + false : true; + amdgpu_dm_do_flip( - crtc, - fb, - drm_crtc_vblank_count(crtc)); + crtc, + fb, + drm_crtc_vblank_count(crtc) + wait_for_vblank); - wait_for_vblank = - acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? - false : true; /*clean up the flags for next usage*/ acrtc->flip_flags = 0; } -- GitLab From 035e0fe5485fc1881a3c24eaac86832d804242e9 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 31 Mar 2017 17:40:15 -0400 Subject: [PATCH 0373/2898] drm/amd/display: adding FCLK and DPPCLK clock types Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services_types.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index f89395e0c107..408141c6776e 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -71,7 +71,9 @@ enum dm_pp_clock_type { DM_PP_CLOCK_TYPE_DCFCLK, DM_PP_CLOCK_TYPE_SOCCLK, DM_PP_CLOCK_TYPE_PIXELCLK, - DM_PP_CLOCK_TYPE_DISPLAYPHYCLK + DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, + DM_PP_CLOCK_TYPE_DPPCLK, + DM_PP_CLOCK_TYPE_FCLK, }; #define DC_DECODE_PP_CLOCK_TYPE(clk_type) \ -- GitLab From 632550d71fcf78d495cfd1d321427e634b662f23 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 3 Apr 2017 11:54:11 -0400 Subject: [PATCH 0374/2898] drm/amd/display: Fix hotspot programming during set cursor position. - Remove x,y hotspot from dc_cursor_attributes. Only program it through setPosition. Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Zeyu Fan Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 5 ----- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 7 ------- .../drm/amd/display/dc/dce110/dce110_ipp_cursor.c | 11 ++++------- .../drm/amd/display/dc/dce120/dce120_ipp_cursor.c | 15 ++++----------- 4 files changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 4b0fc6b56969..58fda20f6b97 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -90,8 +90,6 @@ static void dm_set_cursor( attributes.address.low_part = lower_32_bits(gpu_addr); attributes.width = width; attributes.height = height; - attributes.x_hot = 0; - attributes.y_hot = 0; attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; attributes.rotation_angle = 0; attributes.attribute_flags.value = 0; @@ -118,7 +116,6 @@ static void dm_set_cursor( position.x = x; position.y = y; - position.hot_spot_enable = true; position.x_hotspot = xorigin; position.y_hotspot = yorigin; @@ -260,7 +257,6 @@ static int dm_crtc_cursor_set( position.enable = false; position.x = 0; position.y = 0; - position.hot_spot_enable = false; if (amdgpu_crtc->stream) { /*set cursor visible false*/ @@ -344,7 +340,6 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, position.x = x; position.y = y; - position.hot_spot_enable = true; position.x_hotspot = xorigin; position.y_hotspot = yorigin; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 568b7f0569f8..b785dd7b3a97 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -395,11 +395,6 @@ struct dc_cursor_position { */ bool enable; - /* - * This parameter indicates whether cursor hot spot should be - * programmed - */ - bool hot_spot_enable; }; struct dc_cursor_mi_param { @@ -464,8 +459,6 @@ struct dc_cursor_attributes { /* Width and height should correspond to cursor surface width x heigh */ uint32_t width; uint32_t height; - uint32_t x_hot; - uint32_t y_hot; enum dc_cursor_color_format color_format; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c index 1cab12ba8447..5b230b17fc5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c @@ -86,11 +86,10 @@ void dce110_ipp_cursor_set_position( program_position(ipp110, position->x, position->y); - if (position->hot_spot_enable) - program_hotspot( - ipp110, - position->x_hotspot, - position->y_hotspot); + program_hotspot( + ipp110, + position->x_hotspot, + position->y_hotspot); /* unlock cursor registers */ lock(ipp110, false); @@ -111,8 +110,6 @@ bool dce110_ipp_cursor_set_attributes( attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); - /* Program hot spot coordinates */ - program_hotspot(ipp110, attributes->x_hot, attributes->y_hot); /* * Program cursor size -- NOTE: HW spec specifies that HW register diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c index d520b5d7aa81..15671fd2cb9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c @@ -151,11 +151,10 @@ void dce120_ipp_cursor_set_position( CURSOR_X_POSITION, position->x, CURSOR_Y_POSITION, position->y); - if (position->hot_spot_enable) - DCP_REG_SET_2( - DCP0_CUR_HOT_SPOT, - CURSOR_HOT_SPOT_X, position->x_hotspot, - CURSOR_HOT_SPOT_Y, position->y_hotspot); + DCP_REG_SET_2( + DCP0_CUR_HOT_SPOT, + CURSOR_HOT_SPOT_X, position->x_hotspot, + CURSOR_HOT_SPOT_Y, position->y_hotspot); /* unlock cursor registers */ lock(ipp110, false); @@ -176,12 +175,6 @@ bool dce120_ipp_cursor_set_attributes( attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); - /* Program hot spot coordinates */ - DCP_REG_SET_2( - DCP0_CUR_HOT_SPOT, - CURSOR_HOT_SPOT_X, attributes->x_hot, - CURSOR_HOT_SPOT_Y, attributes->y_hot); - /* * Program cursor size -- NOTE: HW spec specifies that HW register * stores size as (height - 1, width - 1) -- GitLab From 6e5d1c829ba6a53bdd0f18a872a5178e9620ecab Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Tue, 4 Apr 2017 10:01:07 -0400 Subject: [PATCH 0375/2898] drm/amd/display: Memory was freed twice during disable 1. get_ss_info_from_atombios function was allocating the memory populating the provided pointer but them freeing the memory. Since the pointer was return as a valid value, we are trying to free the same memory during clock resource destruction Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 8ddad3a877d6..bd4524ef3a37 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1035,7 +1035,6 @@ static void get_ss_info_from_atombios( } *spread_spectrum_data = ss_data; - dm_free(ss_data); dm_free(ss_info); return; -- GitLab From 8b32076c27227cf5bed0c925c7a1a9680748424a Mon Sep 17 00:00:00 2001 From: Sylvia Tsai Date: Tue, 4 Apr 2017 17:28:17 -0400 Subject: [PATCH 0376/2898] drm/amd/display: Adding dm controlled signal type in dc_stream - Adding dm controlled signal type in dc_stream - Adding fallback to dvi signal when output signal is hdmi and the connector type is not Signed-off-by: Sylvia Tsai Acked-by: Harry Wentland Reviewed-by: Sylvia Tsai Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 30 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 069f588a9e02..2d40864b7b48 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1237,22 +1237,22 @@ static struct audio *find_first_free_audio(struct resource_context *res_ctx) static void update_stream_signal(struct core_stream *stream) { - const struct dc_sink *dc_sink = stream->public.sink; - - if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = stream->sink->link->public.connector_signal; - else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || - dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) - /* For asic supports dual link DVI, we should adjust signal type - * based on timing pixel clock. If pixel clock more than 165Mhz, - * signal is dual link, otherwise, single link. - */ - if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) - stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + if (stream->public.output_signal == SIGNAL_TYPE_NONE) { + const struct dc_sink *dc_sink = stream->public.sink; + + if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = + stream->sink->link-> + public.connector_signal; else - stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; - else - stream->signal = dc_sink->sink_signal; + stream->signal = dc_sink->sink_signal; + } else { + stream->signal = stream->public.output_signal; + } + + if (stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK && + stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; } bool resource_is_stream_unchanged( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a27a6aba0df1..97af8f63eec3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -411,6 +411,7 @@ enum surface_update_type { struct dc_stream { const struct dc_sink *sink; struct dc_crtc_timing timing; + enum signal_type output_signal; enum dc_color_space output_color_space; -- GitLab From 313bf4ff0180107b687dbd10dde8fd021247cd37 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 6 Apr 2017 16:21:58 -0400 Subject: [PATCH 0377/2898] drm/amd/display: Add same check as reset pipes for programing backend regs. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 839c34409c63..7430be502efd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1689,6 +1689,10 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream == pipe_ctx_old->stream) continue; + if (pipe_ctx->stream && pipe_ctx_old->stream + && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + continue; + if (pipe_ctx->top_pipe) continue; -- GitLab From fb9611d2167d73b7a7af66edb30893d22de9382d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 6 Apr 2017 16:23:14 -0400 Subject: [PATCH 0378/2898] drm/amd/display: change mpo surface update check condition. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9a3507e743cf..203cb9d0c89d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1024,7 +1024,8 @@ static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) } static enum surface_update_type get_plane_info_update_type( - const struct dc_surface_update *u) + const struct dc_surface_update *u, + int surface_index) { struct dc_plane_info temp_plane_info = { { { { 0 } } } }; @@ -1049,7 +1050,11 @@ static enum surface_update_type get_plane_info_update_type( /* Special Validation parameters */ temp_plane_info.format = u->plane_info->format; - temp_plane_info.visible = u->plane_info->visible; + + if (surface_index == 0) + temp_plane_info.visible = u->plane_info->visible; + else + temp_plane_info.visible = u->surface->visible; if (memcmp(u->plane_info, &temp_plane_info, sizeof(struct dc_plane_info)) != 0) @@ -1111,7 +1116,8 @@ static enum surface_update_type get_scaling_info_update_type( static enum surface_update_type det_surface_update( const struct core_dc *dc, - const struct dc_surface_update *u) + const struct dc_surface_update *u, + int surface_index) { const struct validate_context *context = dc->current_context; enum surface_update_type type = UPDATE_TYPE_FAST; @@ -1120,7 +1126,7 @@ static enum surface_update_type det_surface_update( if (!is_surface_in_context(context, u->surface)) return UPDATE_TYPE_FULL; - type = get_plane_info_update_type(u); + type = get_plane_info_update_type(u, surface_index); if (overall_type < type) overall_type = type; @@ -1157,7 +1163,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = - det_surface_update(core_dc, &updates[i]); + det_surface_update(core_dc, &updates[i], i); if (type == UPDATE_TYPE_FULL) return type; -- GitLab From b64875feb18a734739929e2af8a625b186bb6ec0 Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Mon, 10 Apr 2017 09:37:11 -0400 Subject: [PATCH 0379/2898] drm/amd/display: set NULL value during removal for remoteSink In MST case during removal of remote sink its descriptor pointer wasn't freed corectly. Signed-off-by: Leon Elazar Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 203cb9d0c89d..70dc02cf4dbb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1787,7 +1787,7 @@ void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1]; i++; } - + dc_link->remote_sinks[i] = NULL; dc_link->sink_count--; return; } -- GitLab From 07c84c7ad388c28ce69303182e06644ef30d3ac3 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Mon, 10 Apr 2017 14:02:23 -0400 Subject: [PATCH 0380/2898] drm/amd/display: Fix for tile MST - Set stream signal type to be SST when setting non-tile timing on MST tiled display. - Disable MST on sink after disabling MST link. - Enable MST on sink before enabling MST link. Signed-off-by: Ding Wang Acked-by: Harry Wentland Reviewed-by: Jun Lei Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +++ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 13 +++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 +++ drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 2 ++ 4 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b878fb9697d7..426f7f8187a6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1250,6 +1250,9 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) if (link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) return DC_OK; + /* set the sink to MST mode before enabling the link */ + dp_enable_mst_on_sink(link, true); + return enable_link_dp(pipe_ctx); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 9f12ba87827a..913b01cd7159 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2453,3 +2453,16 @@ bool dc_link_dp_set_test_pattern( return true; } + +void dp_enable_mst_on_sink(struct core_link *link, bool enable) +{ + unsigned char mstmCntl; + + core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); + if (enable) + mstmCntl |= DP_MST_EN; + else + mstmCntl &= (~DP_MST_EN); + + core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 3b814592fd70..316df150c1d9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -129,6 +129,9 @@ void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal) return; dp_disable_link_phy(link, signal); + + /* set the sink to SST mode after disabling the link */ + dp_enable_mst_on_sink(link, false); } bool dp_set_hw_training_pattern( diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index b0cf8e00059c..92c56e6f7588 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -57,4 +57,6 @@ void detect_dp_sink_caps(struct core_link *link); bool is_dp_active_dongle(const struct core_link *link); +void dp_enable_mst_on_sink(struct core_link *link, bool enable); + #endif /* __DC_LINK_DP_H__ */ -- GitLab From 209a885be018435a062403a08063672c9d77d8d1 Mon Sep 17 00:00:00 2001 From: Jordan Lazare Date: Tue, 11 Apr 2017 11:40:18 -0400 Subject: [PATCH 0381/2898] drm/amd/display: Fix missing irq refactor causing potential i2c race Signed-off-by: Jordan Lazare Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 58fda20f6b97..57560a83fda9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -32,8 +32,10 @@ #include #include + #include "amdgpu.h" #include "amdgpu_pm.h" +#include "dm_helpers.h" #include "dm_services_types.h" // We need to #undef FRAME_SIZE and DEPRECATED because they conflict @@ -3075,13 +3077,16 @@ static bool is_dp_capable_without_timing_msa( { uint8_t dpcd_data; bool capable = false; + if (amdgpu_connector->dc_link && - dc_read_aux_dpcd( - dc, - amdgpu_connector->dc_link->link_index, - DP_DOWN_STREAM_PORT_COUNT, - &dpcd_data, sizeof(dpcd_data))) + dm_helpers_dp_read_dpcd( + NULL, + amdgpu_connector->dc_link, + DP_DOWN_STREAM_PORT_COUNT, + &dpcd_data, + sizeof(dpcd_data))) { capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; + } return capable; } -- GitLab From 1ce71fcd5dddf4a3198a96e422122edc210847e9 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 11 Apr 2017 22:24:44 -0400 Subject: [PATCH 0382/2898] drm/amd/display: use full surface update when stream is NULL Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 70dc02cf4dbb..6576137ee189 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1155,7 +1155,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; - if (stream_status->surface_count != surface_count) + if (stream_status == NULL || stream_status->surface_count != surface_count) return UPDATE_TYPE_FULL; if (stream_update) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7430be502efd..1401331080c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1599,11 +1599,11 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); if (context->dispclk_khz - > dc->current_context->dispclk_khz) + > dc->current_context->dispclk_khz) { context->res_ctx.pool->display_clock->funcs->set_clock( context->res_ctx.pool->display_clock, context->dispclk_khz * 115 / 100); - + } /* program audio wall clock. use HDMI as clock source if HDMI * audio active. Otherwise, use DP as clock source * first, loop to find any HDMI audio, if not, loop find DP audio -- GitLab From 81c509633aa93442d58b895f773892b3e8d936cf Mon Sep 17 00:00:00 2001 From: Sylvia Tsai Date: Tue, 11 Apr 2017 15:15:28 -0400 Subject: [PATCH 0383/2898] drm/amd/display: Parse scanline registers They could differ between ASIC generations Signed-off-by: Sylvia Tsai Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++- .../gpu/drm/amd/display/dc/core/dc_stream.c | 21 +++++--- drivers/gpu/drm/amd/display/dc/dc.h | 7 ++- .../dc/dce110/dce110_timing_generator.c | 54 +++++++++---------- .../dc/dce110/dce110_timing_generator.h | 8 +-- .../dc/dce120/dce120_timing_generator.c | 42 +++++++-------- .../amd/display/dc/inc/hw/timing_generator.h | 8 +-- 7 files changed, 89 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 93f10bc772c4..84995a48ec61 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -103,6 +103,8 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, u32 *vbl, u32 *position) { + uint32_t v_blank_start, v_blank_end, h_position, v_position; + if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc)) return -EINVAL; else { @@ -113,7 +115,18 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, return 0; } - return dc_stream_get_scanoutpos(acrtc->stream, vbl, position); + /* + * TODO rework base driver to use values directly. + * for now parse it back into reg-format + */ + dc_stream_get_scanoutpos(acrtc->stream, + &v_blank_start, + &v_blank_end, + &h_position, + &v_position); + + *position = (v_position) || (h_position << 16); + *vbl = (v_blank_start) || (v_blank_end << 16); } return 0; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index bf209f7bbf98..3dbd6c0885d8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -282,12 +282,14 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) return 0; } -uint32_t dc_stream_get_scanoutpos( - const struct dc_stream *dc_stream, - uint32_t *vbl, - uint32_t *position) +bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) { uint8_t i; + bool ret = false; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = @@ -299,10 +301,17 @@ uint32_t dc_stream_get_scanoutpos( if (res_ctx->pipe_ctx[i].stream != stream) continue; - return tg->funcs->get_scanoutpos(tg, vbl, position); + tg->funcs->get_scanoutpos(tg, + v_blank_start, + v_blank_end, + h_position, + v_position); + + ret = true; + break; } - return 0; + return ret; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 97af8f63eec3..7d548b4d0299 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -484,8 +484,11 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream); * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) * being refactored properly to be dce-specific */ -uint32_t dc_stream_get_scanoutpos( - const struct dc_stream *stream, uint32_t *vbl, uint32_t *position); +bool dc_stream_get_scanoutpos(const struct dc_stream *stream, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); /* * Structure to store surface/stream associations for validation diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 006412be7a02..7070aaf9e433 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -574,29 +574,26 @@ void dce110_timing_generator_get_crtc_positions( * @param [out] vpos, hpos ***************************************************************************** */ -uint32_t dce110_timing_generator_get_crtc_scanoutpos( +void dce110_timing_generator_get_crtc_scanoutpos( struct timing_generator *tg, - uint32_t *vbl, - uint32_t *position) + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); - /* TODO 1: Update the implementation once caller is updated - * WARNING!! This function is returning the whole register value - * because the caller is expecting it instead of proper vertical and - * horizontal position. This should be a temporary implementation - * until the caller is updated. */ - /* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */ - - *vbl = dm_read_reg(tg->ctx, + uint32_t v_blank_start_end = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_V_BLANK_START_END)); - *position = dm_read_reg(tg->ctx, - CRTC_REG(mmCRTC_STATUS_POSITION)); + *v_blank_start = get_reg_field_value(v_blank_start_end, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + *v_blank_end = get_reg_field_value(v_blank_start_end, + CRTC_V_BLANK_START_END, + CRTC_V_BLANK_END); - /* @TODO: return value should indicate if current - * crtc is inside vblank*/ - return 0; + dce110_timing_generator_get_crtc_positions(tg, h_position, v_position); } /* TODO: is it safe to assume that mask/shift of Primary and Underlay @@ -1875,34 +1872,31 @@ void dce110_tg_set_colors(struct timing_generator *tg, bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); - uint32_t vbl = 0; + uint32_t v_blank_start = 0; + uint32_t v_blank_end = 0; uint32_t val = 0; - uint32_t position, vbl_start; + uint32_t h_position, v_position; tg->funcs->get_scanoutpos( tg, - &vbl, - &position); + &v_blank_start, + &v_blank_end, + &h_position, + &v_position); - if (vbl == 0) + if (v_blank_start == 0 || v_blank_end == 0) return false; - vbl_start = - get_reg_field_value( - vbl, - CRTC_V_BLANK_START_END, - CRTC_V_BLANK_START); - set_reg_field_value( val, - vbl_start, + v_blank_start, CRTC_VERTICAL_INTERRUPT0_POSITION, CRTC_VERTICAL_INTERRUPT0_LINE_START); - /* Set interaval width for interrupt to fire to 1 scanline */ + /* Set interval width for interrupt to fire to 1 scanline */ set_reg_field_value( val, - vbl_start + width, + v_blank_start + width, CRTC_VERTICAL_INTERRUPT0_POSITION, CRTC_VERTICAL_INTERRUPT0_LINE_END); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index ca387b40fc67..f14a4d91cd8e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -230,10 +230,12 @@ void dce110_timing_generator_set_static_screen_control( struct timing_generator *tg, uint32_t value); -uint32_t dce110_timing_generator_get_crtc_scanoutpos( +void dce110_timing_generator_get_crtc_scanoutpos( struct timing_generator *tg, - uint32_t *vbl, - uint32_t *position); + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); void dce110_timing_generator_enable_advanced_request( struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 95cb1768aeb5..1318df7ed47e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -576,24 +576,28 @@ void dce120_timing_generator_set_drr( } } -uint32_t dce120_timing_generator_get_crtc_scanoutpos( +void dce120_timing_generator_get_crtc_scanoutpos( struct timing_generator *tg, - uint32_t *vbl, - uint32_t *position) + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); - *vbl = dm_read_reg_soc15( + uint32_t v_blank_start_end = dm_read_reg_soc15( tg->ctx, mmCRTC0_CRTC_V_BLANK_START_END, tg110->offsets.crtc); - *position = dm_read_reg_soc15( - tg->ctx, - mmCRTC0_CRTC_STATUS_POSITION, - tg110->offsets.crtc); + *v_blank_start = get_reg_field_value(v_blank_start_end, + CRTC0_CRTC_V_BLANK_START_END, + CRTC_V_BLANK_START); + *v_blank_end = get_reg_field_value(v_blank_start_end, + CRTC0_CRTC_V_BLANK_START_END, + CRTC_V_BLANK_END); - return 0; + dce120_timing_generator_get_crtc_positions(tg, h_position, v_position); } void dce120_timing_generator_enable_advanced_request( @@ -1044,26 +1048,22 @@ static bool dce120_arm_vert_intr( uint8_t width) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); - uint32_t vbl, position, vbl_start; + uint32_t v_blank_start, v_blank_end, h_position, v_position; tg->funcs->get_scanoutpos( tg, - &vbl, - &position); + &v_blank_start, + &v_blank_end, + &h_position, + &v_position); - if (vbl == 0) + if (v_blank_start == 0 || v_blank_end == 0) return false; - vbl_start = - get_reg_field_value( - vbl, - CRTC0_CRTC_V_BLANK_START_END, - CRTC_V_BLANK_START); - CRTC_REG_SET_2( CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION, - CRTC_VERTICAL_INTERRUPT0_LINE_START, vbl_start, - CRTC_VERTICAL_INTERRUPT0_LINE_END, vbl_start + width); + CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start, + CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 51902a4f8798..b3deaf2d8173 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -120,10 +120,12 @@ struct timing_generator_funcs { int32_t *h_position, int32_t *v_position); uint32_t (*get_frame_count)(struct timing_generator *tg); - uint32_t (*get_scanoutpos)( + void (*get_scanoutpos)( struct timing_generator *tg, - uint32_t *vbl, - uint32_t *position); + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position); void (*set_early_control)(struct timing_generator *tg, uint32_t early_cntl); void (*wait_for_state)(struct timing_generator *tg, -- GitLab From ab3c179893fd44953008d1b1442973ecb1bb5c7e Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Fri, 31 Mar 2017 15:25:04 -0500 Subject: [PATCH 0384/2898] drm/amd/display: Add support for programming stereo sync Signed-off-by: Vitaly Prosyak Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 11 ++++++++--- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 12 ++++++++++++ .../drm/amd/display/dc/dce/dce_stream_encoder.h | 14 ++++++++++++-- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 7 +++++++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 5 +++++ .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 5 +++++ 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 03ce9ba50b64..e5045d21a05c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -174,7 +174,8 @@ enum dce110_opp_reg_type { OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ - OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_100(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ @@ -182,7 +183,8 @@ enum dce110_opp_reg_type { OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ - OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ @@ -195,7 +197,8 @@ enum dce110_opp_reg_type { OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ - OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh) + OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_80(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ @@ -244,6 +247,7 @@ enum dce110_opp_reg_type { OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ + OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh),\ OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\ OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\ OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\ @@ -308,6 +312,7 @@ enum dce110_opp_reg_type { type FMT_RGB_RANDOM_ENABLE; \ type FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX; \ type FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP; \ + type FMT_STEREOSYNC_OVERRIDE; \ type FMT_RAND_R_SEED; \ type FMT_RAND_G_SEED; \ type FMT_RAND_B_SEED; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index f3e1a293351f..9713def6e481 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1286,6 +1286,17 @@ void dce110_se_hdmi_audio_disable( dce110_se_enable_audio_clock(enc, false); } + +static void setup_stereo_sync( + struct stream_encoder *enc, + int tg_inst, bool enable) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, tg_inst); + REG_UPDATE(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, !enable); +} + + static const struct stream_encoder_funcs dce110_str_enc_funcs = { .dp_set_stream_attribute = dce110_stream_encoder_dp_set_stream_attribute, @@ -1316,6 +1327,7 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { .hdmi_audio_setup = dce110_se_hdmi_audio_setup, .hdmi_audio_disable = dce110_se_hdmi_audio_disable, + .setup_stereo_sync = setup_stereo_sync, }; bool dce110_stream_encoder_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index c2f4050fc6dc..850e12a8db61 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -151,6 +151,8 @@ SE_SF(DP_VID_N, DP_VID_N, mask_sh),\ SE_SF(DP_VID_M, DP_VID_M, mask_sh),\ SE_SF(DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ SE_SF(AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\ @@ -265,7 +267,9 @@ SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh) #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) @@ -281,7 +285,9 @@ SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh) + SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh) #define SE_COMMON_MASK_SH_LIST_DCE112(mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ @@ -416,6 +422,8 @@ struct dce_stream_encoder_shift { uint8_t AFMT_AUDIO_CLOCK_EN; uint8_t TMDS_PIXEL_ENCODING; uint8_t TMDS_COLOR_FORMAT; + uint8_t DIG_STEREOSYNC_SELECT; + uint8_t DIG_STEREOSYNC_GATE_EN; uint8_t DP_DB_DISABLE; uint8_t DP_MSA_MISC0; uint8_t DP_MSA_HTOTAL; @@ -543,6 +551,8 @@ struct dce_stream_encoder_mask { uint32_t AFMT_AUDIO_SAMPLE_SEND; uint32_t AFMT_AUDIO_CLOCK_EN; uint32_t TMDS_PIXEL_ENCODING; + uint32_t DIG_STEREOSYNC_SELECT; + uint32_t DIG_STEREOSYNC_GATE_EN; uint32_t TMDS_COLOR_FORMAT; uint32_t DP_DB_DISABLE; uint32_t DP_MSA_MISC0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1401331080c5..6bf03d680314 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1056,6 +1056,13 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->sink->link->link_enc, pipe_ctx->stream->signal); + if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) + pipe_ctx->stream_enc->funcs->setup_stereo_sync( + pipe_ctx->stream_enc, + pipe_ctx->tg->inst, + stream->public.timing.timing_3d_format != TIMING_3D_FORMAT_NONE); + + /*vbios crtc_source_selection and encoder_setup will override fmt_C*/ pipe_ctx->opp->funcs->opp_program_fmt( pipe_ctx->opp, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index e01b831a7e7f..521bd21eb5df 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -316,6 +316,11 @@ struct opp_funcs { struct hw_adjustment_range *range); void (*opp_destroy)(struct output_pixel_processor **opp); + + void (*opp_set_stereo_polarity)( + struct output_pixel_processor *opp, + bool enable, + bool rightEyePolarity); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 674bebfe3bd2..9fb27bd360ac 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -118,6 +118,11 @@ struct stream_encoder_funcs { void (*hdmi_audio_disable) ( struct stream_encoder *enc); + + void (*setup_stereo_sync) ( + struct stream_encoder *enc, + int tg_inst, + bool enable); }; #endif /* STREAM_ENCODER_H_ */ -- GitLab From 09e2d07f9d4d30f7d219b562d656d7c7611e2b65 Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Wed, 12 Apr 2017 11:05:08 -0400 Subject: [PATCH 0385/2898] drm/amd/display: FreeSync LFC MIN/MAX update on current frame - Update BTR/LFC logic so that V_TOTAL_MIN/MAX will take affect on current frame - Add in FreeSync update to MPO code path Signed-off-by: Eric Cook Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- .../amd/display/modules/freesync/freesync.c | 67 +++++++++++-------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 7a0731e2dbb0..94566c0a0e62 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -641,7 +641,8 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams) { - unsigned int index, v_total = 0; + unsigned int index, v_total, inserted_frame_v_total = 0; + unsigned int min_frame_duration_in_ns, vmax, vmin = 0; struct freesync_state *state; struct core_freesync *core_freesync = NULL; @@ -665,19 +666,48 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, /* Only execute if in fullscreen mode */ if (state->fullscreen == true && - core_freesync->map[index].user_enable.enable_for_gaming) { + core_freesync->map[index].user_enable.enable_for_gaming && + core_freesync->map[index].caps->btr_supported && + state->btr.btr_active) { + + /* TODO: pass in flag for Pre-DCE12 ASIC + * in order for frame variable duration to take affect, + * it needs to be done one VSYNC early, which is at + * frameCounter == 1. + * For DCE12 and newer updates to V_TOTAL_MIN/MAX + * will take affect on current frame + */ + if (state->btr.frames_to_insert == state->btr.frame_counter) { + + min_frame_duration_in_ns = ((unsigned int) (div64_u64( + (1000000000ULL * 1000000), + state->nominal_refresh_rate_in_micro_hz))); + + calc_vmin_vmax(core_freesync, *streams, &vmin, &vmax); - if (state->btr.btr_active) - if (state->btr.frame_counter > 0) + inserted_frame_v_total = vmin; - state->btr.frame_counter--; + if (min_frame_duration_in_ns / 1000) + inserted_frame_v_total = + state->btr.inserted_frame_duration_in_us * + vmin / (min_frame_duration_in_ns / 1000); - if (state->btr.frame_counter == 1) { + /* Set length of inserted frames as v_total_max*/ + vmax = inserted_frame_v_total; + vmin = inserted_frame_v_total; - /* Restore FreeSync */ - set_freesync_on_streams(core_freesync, streams, - num_streams); + /* Program V_TOTAL */ + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, streams, + num_streams, vmin, vmax); } + + if (state->btr.frame_counter > 0) + state->btr.frame_counter--; + + /* Restore FreeSync */ + if (state->btr.frame_counter == 0) + set_freesync_on_streams(core_freesync, streams, num_streams); } /* If in fullscreen freesync mode or in video, do not program @@ -1022,8 +1052,6 @@ static void apply_below_the_range(struct core_freesync *core_freesync, unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF; unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF; unsigned int frames_to_insert = 0; - unsigned int inserted_frame_v_total = 0; - unsigned int vmin = 0, vmax = 0; unsigned int min_frame_duration_in_ns = 0; struct freesync_state *state = &core_freesync->map[map_index].state; @@ -1101,23 +1129,6 @@ static void apply_below_the_range(struct core_freesync *core_freesync, inserted_frame_duration_in_us = state->time.min_render_time_in_us; - /* We need the v_total_min from capability */ - calc_vmin_vmax(core_freesync, stream, &vmin, &vmax); - - inserted_frame_v_total = vmin; - if (min_frame_duration_in_ns / 1000) - inserted_frame_v_total = inserted_frame_duration_in_us * - vmin / (min_frame_duration_in_ns / 1000); - - /* Set length of inserted frames as v_total_max*/ - vmax = inserted_frame_v_total; - - /* Program V_TOTAL */ - core_freesync->dc->stream_funcs.adjust_vmin_vmax( - core_freesync->dc, &stream, - 1, vmin, - vmax); - /* Cache the calculated variables */ state->btr.inserted_frame_duration_in_us = inserted_frame_duration_in_us; -- GitLab From 03e4173b44d514818c98555bc709a931ff9300ce Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 6 Apr 2017 16:48:48 -0400 Subject: [PATCH 0386/2898] drm/amd/display: Remove unused scratch_val_ctx Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 --- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6576137ee189..7b0b7356ae89 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -411,8 +411,6 @@ static void destruct(struct core_dc *dc) dc->current_context = NULL; dm_free(dc->temp_flip_context); dc->temp_flip_context = NULL; - dm_free(dc->scratch_val_ctx); - dc->scratch_val_ctx = NULL; dm_free(dc->ctx); dc->ctx = NULL; @@ -432,7 +430,6 @@ static bool construct(struct core_dc *dc, dc->current_context = dm_alloc(sizeof(*dc->current_context)); dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); - dc->scratch_val_ctx = dm_alloc(sizeof(*dc->scratch_val_ctx)); if (!dc->current_context || !dc->temp_flip_context) { dm_error("%s: failed to create validate ctx\n", __func__); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 8d87f490dc1c..ec3edbe20d85 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -23,7 +23,6 @@ struct core_dc { struct validate_context *current_context; struct validate_context *temp_flip_context; - struct validate_context *scratch_val_ctx; struct resource_pool *res_pool; /* Display Engine Clock levels */ -- GitLab From 6d9501e4ad2df6fc631e99d3cfd2afa09542393a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 6 Apr 2017 17:05:53 -0400 Subject: [PATCH 0387/2898] drm/amd/display: Get rid of temp_flip_context If we need to update our context we can allocate memory. No need to keep temporary memory for this. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 ++++++++++---------- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 1 - 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7b0b7356ae89..e8499e744595 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -409,8 +409,6 @@ static void destruct(struct core_dc *dc) dm_free(dc->current_context); dc->current_context = NULL; - dm_free(dc->temp_flip_context); - dc->temp_flip_context = NULL; dm_free(dc->ctx); dc->ctx = NULL; @@ -429,9 +427,8 @@ static bool construct(struct core_dc *dc, } dc->current_context = dm_alloc(sizeof(*dc->current_context)); - dc->temp_flip_context = dm_alloc(sizeof(*dc->temp_flip_context)); - if (!dc->current_context || !dc->temp_flip_context) { + if (!dc->current_context) { dm_error("%s: failed to create validate ctx\n", __func__); goto val_ctx_fail; } @@ -874,13 +871,9 @@ bool dc_commit_streams( } resource_validate_ctx_destruct(core_dc->current_context); + dm_free(core_dc->current_context); - if (core_dc->temp_flip_context != core_dc->current_context) { - dm_free(core_dc->temp_flip_context); - core_dc->temp_flip_context = core_dc->current_context; - } core_dc->current_context = context; - memset(core_dc->temp_flip_context, 0, sizeof(*core_dc->temp_flip_context)); return (result == DC_OK); @@ -1212,7 +1205,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, new_surfaces[i] = srf_updates[i].surface; /* initialize scratch memory for building context */ - context = core_dc->temp_flip_context; + context = dm_alloc(sizeof(*context)); resource_validate_ctx_copy_construct( core_dc->current_context, context); @@ -1220,7 +1213,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!resource_attach_surfaces_to_context( new_surfaces, surface_count, dc_stream, context)) { BREAK_TO_DEBUGGER(); - return; + goto fail; } } else { context = core_dc->current_context; @@ -1326,7 +1319,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL) { if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); - return; + goto fail; } else core_dc->hwss.set_bandwidth(core_dc, context, false); } @@ -1418,10 +1411,17 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (core_dc->current_context != context) { resource_validate_ctx_destruct(core_dc->current_context); - core_dc->temp_flip_context = core_dc->current_context; + dm_free(core_dc->current_context); core_dc->current_context = context; } + return; + +fail: + if (core_dc->current_context != context) { + resource_validate_ctx_destruct(context); + dm_free(context); + } } uint8_t dc_get_current_stream_count(const struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index ec3edbe20d85..f9363f642f92 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -22,7 +22,6 @@ struct core_dc { struct core_link *links[MAX_PIPES * 2]; struct validate_context *current_context; - struct validate_context *temp_flip_context; struct resource_pool *res_pool; /* Display Engine Clock levels */ -- GitLab From 2180e7cca4d5b93b9f150a83d83e27b7fb82a72f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 17 Apr 2017 11:39:19 -0400 Subject: [PATCH 0388/2898] drm/amd/display: update dce8 & 10 bw programming Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- .../display/dc/dce100/dce100_hw_sequencer.c | 28 +++++++++---------- .../display/dc/dce100/dce100_hw_sequencer.h | 7 +++-- .../amd/display/dc/dce100/dce100_resource.c | 1 + .../display/dc/dce110/dce110_hw_sequencer.c | 3 +- .../amd/display/dc/dce80/dce80_hw_sequencer.c | 19 +------------ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 --- 6 files changed, 21 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index f11044e0245c..dd6f0b1bd8ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -28,6 +28,8 @@ #include "core_types.h" #include "hw_sequencer.h" #include "dce100_hw_sequencer.h" +#include "resource.h" + #include "dce110/dce110_hw_sequencer.h" /* include DCE10 register header files */ @@ -104,7 +106,7 @@ static bool dce100_enable_display_power_gating( return false; } -void dce100_pplib_apply_display_requirements( +static void dce100_pplib_apply_display_requirements( struct core_dc *dc, struct validate_context *context) { @@ -112,6 +114,8 @@ void dce100_pplib_apply_display_requirements( pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); + pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + / MEMORY_TYPE_MULTIPLIER; dce110_fill_display_configs(context, pp_display_cfg); @@ -122,20 +126,18 @@ void dce100_pplib_apply_display_requirements( dc->prev_display_config = *pp_display_cfg; } - - -static void set_displaymarks( - const struct core_dc *dc, struct validate_context *context) -{ - /* Do nothing until we have proper bandwitdth calcs */ -} - -static void set_bandwidth( +void dce100_set_bandwidth( struct core_dc *dc, struct validate_context *context, bool decrease_allowed) { - dc->hwss.set_displaymarks(dc, context); + if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + context->res_ctx.pool->display_clock->funcs->set_clock( + context->res_ctx.pool->display_clock, + context->dispclk_khz * 115 / 100); + dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; + dc->current_context->dispclk_khz = context->dispclk_khz; + } dce100_pplib_apply_display_requirements(dc, context); } @@ -146,10 +148,8 @@ bool dce100_hw_sequencer_construct(struct core_dc *dc) { dce110_hw_sequencer_construct(dc); - /* TODO: dce80 is empty implementation at the moment*/ dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; - dc->hwss.set_displaymarks = set_displaymarks; - dc->hwss.set_bandwidth = set_bandwidth; + dc->hwss.set_bandwidth = dce100_set_bandwidth; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index f51d04a66a49..24433f0e770b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -33,9 +33,10 @@ struct validate_context; bool dce100_hw_sequencer_construct(struct core_dc *dc); -void dce100_pplib_apply_display_requirements( - struct core_dc *dc, - struct validate_context *context); +void dce100_set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed); #endif /* __DC_HWSS_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 7fae8537e18a..9b365597cec5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -771,6 +771,7 @@ bool dce100_validate_bandwidth( { /* TODO implement when needed but for now hardcode max value*/ context->dispclk_khz = 681000; + context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6bf03d680314..2fbf6ddcf3be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2266,7 +2266,7 @@ static void dce110_set_bandwidth( struct validate_context *context, bool decrease_allowed) { - dc->hwss.set_displaymarks(dc, context); + dce110_set_displaymarks(dc, context); if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { context->res_ctx.pool->display_clock->funcs->set_clock( @@ -2468,7 +2468,6 @@ static const struct hw_sequencer_funcs dce110_funcs = { .enable_display_power_gating = dce110_enable_display_power_gating, .power_down_front_end = dce110_power_down_fe, .pipe_control_lock = dce_pipe_control_lock, - .set_displaymarks = dce110_set_displaymarks, .set_bandwidth = dce110_set_bandwidth, .set_drr = set_drr, .set_static_screen_control = set_static_screen_control, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index 9d4e7d8b836e..4cba80ff6ca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -107,30 +107,13 @@ static bool dce80_enable_display_power_gating( return false; } -static void set_displaymarks( - const struct core_dc *dc, struct validate_context *context) -{ - /* Do nothing until we have proper bandwitdth calcs */ -} - -static void set_bandwidth( - struct core_dc *dc, - struct validate_context *context, - bool decrease_allowed) -{ - dc->hwss.set_displaymarks(dc, context); - dce100_pplib_apply_display_requirements(dc, context); -} - - bool dce80_hw_sequencer_construct(struct core_dc *dc) { dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating; dc->hwss.pipe_control_lock = dce_pipe_control_lock; - dc->hwss.set_displaymarks = set_displaymarks; - dc->hwss.set_bandwidth = set_bandwidth; + dc->hwss.set_bandwidth = dce100_set_bandwidth; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 077dc7573c52..9bfaaad09bea 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -123,10 +123,6 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe, bool lock); - void (*set_displaymarks)( - const struct core_dc *dc, - struct validate_context *context); - void (*set_bandwidth)( struct core_dc *dc, struct validate_context *context, -- GitLab From 129eed72823d25fa57aaf64a1cef6488fd21d0cd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 6 Apr 2017 16:22:33 -0400 Subject: [PATCH 0389/2898] drm/amd/display: pull commit_surfaces out of atomic_commit into helper function This should make things simpler when we try to rework this later when we pass validate_context from atomic_check to atomic_commit. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 113 ++++++++++-------- 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 57560a83fda9..d8718e2ac207 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2350,6 +2350,67 @@ static void amdgpu_dm_do_flip( acrtc->crtc_id); } +void dc_commit_surfaces(struct drm_atomic_state *state, + struct drm_device *dev, struct amdgpu_display_manager *dm) +{ + uint32_t i; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state; + + /* update planes when needed */ + for_each_plane_in_state(state, plane, old_plane_state, i) { + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct drm_framebuffer *fb = plane_state->fb; + struct drm_connector *connector; + struct dm_connector_state *dm_state = NULL; + enum dm_commit_action action; + bool pflip_needed; + + if (!fb || !crtc || !crtc->state->active) + continue; + + action = get_dm_commit_action(crtc->state); + + /* Surfaces are created under two scenarios: + * 1. This commit is not a page flip. + * 2. This commit is a page flip, and streams are created. + */ + pflip_needed = !state->allow_modeset; + if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON + || action == DM_COMMIT_ACTION_SET) { + list_for_each_entry(connector, + &dev->mode_config.connector_list, + head) { + if (connector->state->crtc == crtc) { + dm_state = to_dm_connector_state( + connector->state); + break; + } + } + + /* + * This situation happens in the following case: + * we are about to get set mode for connector who's only + * possible crtc (in encoder crtc mask) is used by + * another connector, that is why it will try to + * re-assing crtcs in order to make configuration + * supported. For our implementation we need to make all + * encoders support all crtcs, then this issue will + * never arise again. But to guard code from this issue + * check is left. + * + * Also it should be needed when used with actual + * drm_atomic_commit ioctl in future + */ + if (!dm_state) + continue; + + dm_dc_surface_commit(dm->dc, crtc); + } + } +} + void amdgpu_dm_atomic_commit_tail( struct drm_atomic_state *state) { @@ -2521,57 +2582,7 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed */ - for_each_plane_in_state(state, plane, old_plane_state, i) { - struct drm_plane_state *plane_state = plane->state; - struct drm_crtc *crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; - struct drm_connector *connector; - struct dm_connector_state *dm_state = NULL; - enum dm_commit_action action; - bool pflip_needed; - - if (!fb || !crtc || !crtc->state->active) - continue; - - action = get_dm_commit_action(crtc->state); - - /* Surfaces are created under two scenarios: - * 1. This commit is not a page flip. - * 2. This commit is a page flip, and streams are created. - */ - pflip_needed = !state->allow_modeset; - if (!pflip_needed || - action == DM_COMMIT_ACTION_DPMS_ON || - action == DM_COMMIT_ACTION_SET) { - list_for_each_entry(connector, - &dev->mode_config.connector_list, head) { - if (connector->state->crtc == crtc) { - dm_state = to_dm_connector_state( - connector->state); - break; - } - } - - /* - * This situation happens in the following case: - * we are about to get set mode for connector who's only - * possible crtc (in encoder crtc mask) is used by - * another connector, that is why it will try to - * re-assing crtcs in order to make configuration - * supported. For our implementation we need to make all - * encoders support all crtcs, then this issue will - * never arise again. But to guard code from this issue - * check is left. - * - * Also it should be needed when used with actual - * drm_atomic_commit ioctl in future - */ - if (!dm_state) - continue; - - dm_dc_surface_commit(dm->dc, crtc); - } - } + dc_commit_surfaces(state, dev, dm); for (i = 0; i < new_crtcs_count; i++) { /* -- GitLab From 927f6eff2aa40e73528619818374c271ddfadd3d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 6 Apr 2017 18:57:05 -0400 Subject: [PATCH 0390/2898] drm/amd/display: Copy ctx to current_context instead of assign Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e8499e744595..0d870e9c7c99 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -906,13 +906,13 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) resource_validate_ctx_copy_construct(core_dc->current_context, context); post_surface_trace(dc); - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL) { context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( core_dc, &context->res_ctx.pipe_ctx[i]); } + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); return false; @@ -920,11 +920,10 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) core_dc->hwss.set_bandwidth(core_dc, context, true); - resource_validate_ctx_destruct(core_dc->current_context); - if (core_dc->current_context) - dm_free(core_dc->current_context); + resource_validate_ctx_copy_construct(context, core_dc->current_context); - core_dc->current_context = context; + resource_validate_ctx_destruct(context); + dm_free(context); return true; } -- GitLab From 8122a253b34aec75a1fdc3fe61c97b9026a0bff6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 29 Mar 2017 11:15:14 -0400 Subject: [PATCH 0391/2898] drm/amd/display: Move resource_validate_ctx_destruct to dc.h This will be needed to clean up context once we add it to private atomic state. Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 22 +++++++++---------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 6 +++++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 6 ----- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0d870e9c7c99..5620fe361173 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -389,7 +389,7 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) static void destruct(struct core_dc *dc) { - resource_validate_ctx_destruct(dc->current_context); + dc_resource_validate_ctx_destruct(dc->current_context); destroy_links(dc); @@ -654,7 +654,7 @@ bool dc_validate_resources( result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, set_count, context); - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); dm_free(context); context_alloc_fail: @@ -684,7 +684,7 @@ bool dc_validate_guaranteed( result = core_dc->res_pool->funcs->validate_guaranteed( core_dc, stream, context); - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); dm_free(context); context_alloc_fail: @@ -838,7 +838,7 @@ bool dc_commit_streams( __func__, result); BREAK_TO_DEBUGGER(); - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); goto fail; } @@ -870,7 +870,7 @@ bool dc_commit_streams( context->streams[i]->public.timing.pix_clk_khz); } - resource_validate_ctx_destruct(core_dc->current_context); + dc_resource_validate_ctx_destruct(core_dc->current_context); dm_free(core_dc->current_context); core_dc->current_context = context; @@ -903,7 +903,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) dm_error("%s: failed to create validate ctx\n", __func__); return false; } - resource_validate_ctx_copy_construct(core_dc->current_context, context); + dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); post_surface_trace(dc); for (i = 0; i < context->res_ctx.pool->pipe_count; i++) @@ -920,9 +920,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) core_dc->hwss.set_bandwidth(core_dc, context, true); - resource_validate_ctx_copy_construct(context, core_dc->current_context); + dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); dm_free(context); return true; @@ -1205,7 +1205,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* initialize scratch memory for building context */ context = dm_alloc(sizeof(*context)); - resource_validate_ctx_copy_construct( + dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); /* add surface to context */ @@ -1409,7 +1409,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, } if (core_dc->current_context != context) { - resource_validate_ctx_destruct(core_dc->current_context); + dc_resource_validate_ctx_destruct(core_dc->current_context); dm_free(core_dc->current_context); core_dc->current_context = context; @@ -1418,7 +1418,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, fail: if (core_dc->current_context != context) { - resource_validate_ctx_destruct(context); + dc_resource_validate_ctx_destruct(context); dm_free(context); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2d40864b7b48..2e12a0ba5ddf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2050,7 +2050,7 @@ static void set_vsc_info_packet( /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ } -void resource_validate_ctx_destruct(struct validate_context *context) +void dc_resource_validate_ctx_destruct(struct validate_context *context) { int i, j; @@ -2069,7 +2069,7 @@ void resource_validate_ctx_destruct(struct validate_context *context) * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced * by the src_ctx */ -void resource_validate_ctx_copy_construct( +void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, struct validate_context *dst_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7d548b4d0299..7de2080e13ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -522,6 +522,12 @@ bool dc_validate_guaranteed( const struct dc *dc, const struct dc_stream *stream); +void dc_resource_validate_ctx_copy_construct( + const struct validate_context *src_ctx, + struct validate_context *dst_ctx); + +void dc_resource_validate_ctx_destruct(struct validate_context *context); + /* * Set up streams and links associated to drive sinks * The streams parameter is an absolute set of all active streams. diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index eb9c96634578..b1987cab9751 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -141,12 +141,6 @@ void resource_validate_ctx_update_pointer_after_copy( const struct validate_context *src_ctx, struct validate_context *dst_ctx); -void resource_validate_ctx_copy_construct( - const struct validate_context *src_ctx, - struct validate_context *dst_ctx); - -void resource_validate_ctx_destruct(struct validate_context *context); - enum dc_status resource_map_clock_resources( const struct core_dc *dc, struct validate_context *context); -- GitLab From 07d72b39bc861b644ea8f6037e0c6a9836050306 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 29 Mar 2017 11:22:05 -0400 Subject: [PATCH 0392/2898] drm/amd/display: Return context from validate_context This will allow us to carry it from check to commit Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 26 ++++++++++---- drivers/gpu/drm/amd/display/dc/core/dc.c | 36 ++++++++++++++----- drivers/gpu/drm/amd/display/dc/dc.h | 5 +++ 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index d8718e2ac207..fb3cc57c98d5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1384,6 +1384,7 @@ int amdgpu_dm_connector_mode_valid( /* TODO: Unhardcode stream count */ struct dc_stream *stream; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct validate_context *context; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -1418,8 +1419,13 @@ int amdgpu_dm_connector_mode_valid( stream->src.height = mode->vdisplay; stream->dst = stream->src; - if (dc_validate_resources(adev->dm.dc, &val_set, 1)) + context = dc_get_validate_context(adev->dm.dc, &val_set, 1); + + if (context) { result = MODE_OK; + dc_resource_validate_ctx_destruct(context); + dm_free(context); + } dc_stream_release(stream); @@ -2842,6 +2848,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; bool need_to_validate = false; + struct validate_context *context; ret = drm_atomic_helper_check(dev, state); @@ -3064,15 +3071,20 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } - if (need_to_validate == false || set_count == 0 || - dc_validate_resources(dc, set, set_count)) + context = dc_get_validate_context(dc, set, set_count); + + if (need_to_validate == false || set_count == 0 || context) ret = 0; - for (i = 0; i < set_count; i++) { - for (j = 0; j < set[i].surface_count; j++) { - dc_surface_release(set[i].surfaces[j]); - } + if (context) { + dc_resource_validate_ctx_destruct(context); + dm_free(context); } + + for (i = 0; i < set_count; i++) + for (j = 0; j < set[i].surface_count; j++) + dc_surface_release(set[i].surfaces[j]); + for (i = 0; i < new_stream_count; i++) dc_stream_release(new_streams[i]); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5620fe361173..64b5216fb920 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -635,7 +635,7 @@ static bool is_validation_required( return false; } -bool dc_validate_resources( +struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], uint8_t set_count) @@ -644,31 +644,51 @@ bool dc_validate_resources( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; - if (!is_validation_required(core_dc, set, set_count)) - return true; - context = dm_alloc(sizeof(struct validate_context)); if(context == NULL) goto context_alloc_fail; + if (!is_validation_required(core_dc, set, set_count)) { + dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); + return context; + } + result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, set_count, context); - dc_resource_validate_ctx_destruct(context); - dm_free(context); - context_alloc_fail: if (result != DC_OK) { dm_logger_write(core_dc->ctx->logger, LOG_WARNING, "%s:resource validation failed, dc_status:%d\n", __func__, result); + + dc_resource_validate_ctx_destruct(context); + dm_free(context); + context = NULL; } - return (result == DC_OK); + return context; } +bool dc_validate_resources( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count) +{ + struct validate_context *ctx; + + ctx = dc_get_validate_context(dc, set, set_count); + if (ctx) { + dc_resource_validate_ctx_destruct(ctx); + dm_free(ctx); + return true; + } + + return false; +} + bool dc_validate_guaranteed( const struct dc *dc, const struct dc_stream *stream) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7de2080e13ed..1b3fd79ce624 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -505,6 +505,11 @@ struct dc_validation_set { * After this call: * No hardware is programmed for call. Only validation is done. */ +struct validate_context *dc_get_validate_context( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count); + bool dc_validate_resources( const struct dc *dc, const struct dc_validation_set set[], -- GitLab From e6fbd5df0e4e1cf644ddfd50d1df27e5e4ad2220 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Wed, 26 Apr 2017 22:36:01 -0400 Subject: [PATCH 0393/2898] drm/amd/display: initialize YUV plane capabilities This patch populates the YUV surface configurations. Tests: (On Chromium OS for Stoney Only) builds without any errors. Signed-off-by: Shirish S Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 62 ++++++++++++++----- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index fb3cc57c98d5..225b8e6b673f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -462,9 +462,6 @@ static void fill_plane_attributes_from_fb( &tiling_flags, addReq == true ? &fb_location:NULL); - surface->address.type = PLN_ADDR_TYPE_GRAPHICS; - surface->address.grph.addr.low_part = lower_32_bits(fb_location); - surface->address.grph.addr.high_part = upper_32_bits(fb_location); switch (fb->format->format) { case DRM_FORMAT_C8: @@ -485,12 +482,55 @@ static void fill_plane_attributes_from_fb( case DRM_FORMAT_ABGR2101010: surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; break; + case DRM_FORMAT_YUV420: + surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; + break; + case DRM_FORMAT_YVU420: + surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; + break; default: DRM_ERROR("Unsupported screen format %s\n", drm_get_format_name(fb->format->format, &format_name)); return; } + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + surface->address.type = PLN_ADDR_TYPE_GRAPHICS; + surface->address.grph.addr.low_part = lower_32_bits(fb_location); + surface->address.grph.addr.high_part = upper_32_bits(fb_location); + surface->plane_size.grph.surface_size.x = 0; + surface->plane_size.grph.surface_size.y = 0; + surface->plane_size.grph.surface_size.width = fb->width; + surface->plane_size.grph.surface_size.height = fb->height; + surface->plane_size.grph.surface_pitch = + fb->pitches[0] / fb->format->cpp[0]; + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_SRGB; + + } else { + surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; + surface->address.video_progressive.luma_addr.low_part + = lower_32_bits(fb_location); + surface->address.video_progressive.chroma_addr.high_part + = upper_32_bits(fb_location); + surface->plane_size.video.luma_size.x = 0; + surface->plane_size.video.luma_size.y = 0; + surface->plane_size.video.luma_size.width = fb->width; + surface->plane_size.video.luma_size.height = fb->height; + /* TODO: unhardcode */ + surface->plane_size.video.luma_pitch = fb->pitches[0] / 4; + + surface->plane_size.video.chroma_size.x = 0; + surface->plane_size.video.chroma_size.y = 0; + surface->plane_size.video.chroma_size.width = fb->width; + surface->plane_size.video.chroma_size.height = fb->height; + surface->plane_size.video.chroma_pitch = + fb->pitches[0] / 4; + + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_YCBCR709; + } + memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); /* Fill GFX params */ @@ -541,20 +581,10 @@ static void fill_plane_attributes_from_fb( surface->tiling_info.gfx9.shaderEnable = 1; } - - surface->plane_size.grph.surface_size.x = 0; - surface->plane_size.grph.surface_size.y = 0; - surface->plane_size.grph.surface_size.width = fb->width; - surface->plane_size.grph.surface_size.height = fb->height; - surface->plane_size.grph.surface_pitch = - fb->pitches[0] / fb->format->cpp[0]; - surface->visible = true; surface->scaling_quality.h_taps_c = 0; surface->scaling_quality.v_taps_c = 0; - /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_SRGB; /* is this needed? is surface zeroed at allocation? */ surface->scaling_quality.h_taps = 0; surface->scaling_quality.v_taps = 0; @@ -1670,10 +1700,8 @@ static uint32_t rgb_formats[] = { }; static uint32_t yuv_formats[] = { - DRM_FORMAT_YUYV, - DRM_FORMAT_YVYU, - DRM_FORMAT_UYVY, - DRM_FORMAT_VYUY, + DRM_FORMAT_YUV420, + DRM_FORMAT_YVU420, }; int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, -- GitLab From 110ff5439a3e1d19acf02ec5b819e6802c4b8b83 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Tue, 25 Apr 2017 12:26:57 +0530 Subject: [PATCH 0394/2898] drm/amd/display: update the YUV plane offsets This patch updates the planes default offsets to the appropriate ones, and aligns the pitch to 64 bits. BUG=SWDEV-119421 TEST=Boots to UI on jadeite TEST= plane_test --format AR24 --size 500x50 -p --format YV12 --size 500x500 plane_test --format AR24 --size 500x50 -p --format YV12 --size 1280x720 plane_test --format AR24 --size 500x50 -p --format YV12 --size 1366x768 Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 225b8e6b673f..851fbd32fc8d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -511,21 +511,21 @@ static void fill_plane_attributes_from_fb( surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; surface->address.video_progressive.luma_addr.low_part = lower_32_bits(fb_location); - surface->address.video_progressive.chroma_addr.high_part - = upper_32_bits(fb_location); + surface->address.video_progressive.chroma_addr.low_part + = lower_32_bits(fb_location) + + (fb->width * fb->height); surface->plane_size.video.luma_size.x = 0; surface->plane_size.video.luma_size.y = 0; surface->plane_size.video.luma_size.width = fb->width; surface->plane_size.video.luma_size.height = fb->height; /* TODO: unhardcode */ - surface->plane_size.video.luma_pitch = fb->pitches[0] / 4; + surface->plane_size.video.luma_pitch = ALIGN(fb->width, 64); surface->plane_size.video.chroma_size.x = 0; surface->plane_size.video.chroma_size.y = 0; - surface->plane_size.video.chroma_size.width = fb->width; - surface->plane_size.video.chroma_size.height = fb->height; - surface->plane_size.video.chroma_pitch = - fb->pitches[0] / 4; + surface->plane_size.video.chroma_size.width = fb->width / 2; + surface->plane_size.video.chroma_size.height = fb->height / 2; + surface->plane_size.video.chroma_pitch = ALIGN(fb->width, 64) / 2; /* TODO: unhardcode */ surface->color_space = COLOR_SPACE_YCBCR709; -- GitLab From 0430d52b7680fd093c0db8cf41e6ee1d58bae96e Mon Sep 17 00:00:00 2001 From: Shirish S Date: Wed, 12 Apr 2017 16:23:25 +0530 Subject: [PATCH 0395/2898] drm/amd/display: make dc_commit_surfaces_to_stream() re-entrant dc_commit_surfaces_to_stream() function currently is handle's only one plane at a time. This will not work if multiple planes have to be set to a crtc. The functionality of dc_commit_surfaces_to_stream() with this patch is slit into 1. Accumulate and initialise all the surfaces that needs to be set to a crtc. 2. Update the intialised set of surfaces to the steam in one go. Hence dc_commit_surfaces_to_stream() is renamed to init_surfaces(). Once all the planes requested by user space are initialised, dc_commit_surfaces_to_stream() shall sequentially populates *updates, *flip_addr, *plane_info and *scaling_info for all surfaces. BUG: SWDEV-119421 TEST: (On Chromium OS for Stoney Only) * Chromium UI comes up, on both eDP & DP. * 'new_surface_count' now changes as per user input for e.g for all below run tests its 2, without this patch for the below tests it used to be 1 * Executed below tests to see YUV(underlay) & RGB planes on eDP plane_test --format XR24 --size 500x100 -p --format YV12 --size 500x500 plane_test --format AR24 --size 500x50 -p --format YV12 --size 150x150 plane_test --format AR24 --size 500x50 -p --format YV12 --size 1366x768 Signed-off-by: Harry Wentland Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 71 ++++++++++++------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 851fbd32fc8d..0f09e8b903d3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -730,19 +730,20 @@ static void update_stream_scaling_settings( } -static void dm_dc_surface_commit( - struct dc *dc, - struct drm_crtc *crtc) +static void add_surface(struct dc *dc, + struct drm_crtc *crtc, + struct drm_plane *plane, + const struct dc_surface **dc_surfaces) { struct dc_surface *dc_surface; - const struct dc_surface *dc_surfaces[1]; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); const struct dc_stream *dc_stream = acrtc->stream; unsigned long flags; spin_lock_irqsave(&crtc->dev->event_lock, flags); if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("dm_dc_surface_commit: acrtc %d, already busy\n", acrtc->crtc_id); + DRM_ERROR("add_surface: acrtc %d, already busy\n", + acrtc->crtc_id); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); /* In comit tail framework this cannot happen */ BUG_ON(0); @@ -770,22 +771,11 @@ static void dm_dc_surface_commit( fill_plane_attributes( crtc->dev->dev_private, dc_surface, - crtc->primary->state, + plane->state, true); - dc_surfaces[0] = dc_surface; - - if (false == dc_commit_surfaces_to_stream( - dc, - dc_surfaces, - 1, - dc_stream)) { - dm_error( - "%s: Failed to attach surface!\n", - __func__); - } + *dc_surfaces = dc_surface; - dc_surface_release(dc_surface); fail: return; } @@ -2385,11 +2375,16 @@ static void amdgpu_dm_do_flip( } void dc_commit_surfaces(struct drm_atomic_state *state, - struct drm_device *dev, struct amdgpu_display_manager *dm) + struct drm_device *dev, + struct amdgpu_display_manager *dm, + struct drm_crtc *pcrtc) { uint32_t i; struct drm_plane *plane; struct drm_plane_state *old_plane_state; + const struct dc_stream *dc_stream_attach; + const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + int planes_count = 0; /* update planes when needed */ for_each_plane_in_state(state, plane, old_plane_state, i) { @@ -2398,6 +2393,7 @@ void dc_commit_surfaces(struct drm_atomic_state *state, struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *dm_state = NULL; + struct amdgpu_crtc *acrtc_attach; enum dm_commit_action action; bool pflip_needed; @@ -2439,9 +2435,26 @@ void dc_commit_surfaces(struct drm_atomic_state *state, */ if (!dm_state) continue; + if (crtc == pcrtc) { + add_surface(dm->dc, crtc, plane, + &dc_surfaces_constructed[planes_count]); + acrtc_attach = to_amdgpu_crtc(crtc); + dc_stream_attach = acrtc_attach->stream; + planes_count++; + } + } + } - dm_dc_surface_commit(dm->dc, crtc); + if (planes_count) { + if (false == dc_commit_surfaces_to_stream(dm->dc, + dc_surfaces_constructed, + planes_count, + dc_stream_attach)) { + dm_error("%s: Failed to attach surface!\n", __func__); + return; } + for (i = 0; i < planes_count; i++) + dc_surface_release(dc_surfaces_constructed[i]); } } @@ -2453,10 +2466,10 @@ void amdgpu_dm_atomic_commit_tail( struct amdgpu_display_manager *dm = &adev->dm; struct drm_plane *plane; struct drm_plane_state *old_plane_state; - uint32_t i; + uint32_t i, j; uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; - struct drm_crtc *crtc; + struct drm_crtc *crtc, *pcrtc; struct drm_crtc_state *old_crtc_state; const struct dc_stream *commit_streams[MAX_STREAMS]; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; @@ -2615,8 +2628,9 @@ void amdgpu_dm_atomic_commit_tail( dc_stream_get_status(acrtc->stream)->primary_otg_inst; } - /* update planes when needed */ - dc_commit_surfaces(state, dev, dm); + /* update planes when needed per crtc*/ + for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) + dc_commit_surfaces(state, dev, dm, pcrtc); for (i = 0; i < new_crtcs_count; i++) { /* @@ -2793,15 +2807,18 @@ static uint32_t add_val_sets_surface( const struct dc_stream *stream, const struct dc_surface *surface) { - uint32_t i = 0; + uint32_t i = 0, j = 0; while (i < set_count) { - if (val_sets[i].stream == stream) + if (val_sets[i].stream == stream) { + while (val_sets[i].surfaces[j]) + j++; break; + } ++i; } - val_sets[i].surfaces[val_sets[i].surface_count] = surface; + val_sets[i].surfaces[j] = surface; val_sets[i].surface_count++; return val_sets[i].surface_count; -- GitLab From 89aed24c180be9be215923136faebcda0aa344a1 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 17 Apr 2017 19:02:19 -0400 Subject: [PATCH 0396/2898] drm/amd/display: Block YCbCr formats for eDP. Revert previous change. Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 1a84ee0105da..812c29982a2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1026,9 +1026,13 @@ bool dce110_link_encoder_validate_output_with_stream( break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: - case SIGNAL_TYPE_EDP: is_valid = dce110_link_encoder_validate_dp_output( - enc110, &stream->public.timing); + enc110, &stream->public.timing); + break; + case SIGNAL_TYPE_EDP: + is_valid = + (stream->public.timing. + pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; break; case SIGNAL_TYPE_VIRTUAL: is_valid = true; -- GitLab From 50f27269b8dd81d73c787dd18ba19a08bec128d3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 18 Apr 2017 15:43:22 -0400 Subject: [PATCH 0397/2898] drm/amd/display: Fix memory leak in post_update_surfaces Signed-off-by: Harry Wentland Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 64b5216fb920..b1f0a50171af 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -918,6 +918,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) int i; struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context = dm_alloc(sizeof(struct validate_context)); + bool result = true; if (!context) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -935,17 +936,19 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); - return false; + result = false; + goto cleanup; } core_dc->hwss.set_bandwidth(core_dc, context, true); dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); +cleanup: dc_resource_validate_ctx_destruct(context); dm_free(context); - return true; + return result; } bool dc_commit_surfaces_to_stream( -- GitLab From 974db151d48b6793fc2b708d1c3f9ceee735fc5a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 18 Apr 2017 16:51:39 -0400 Subject: [PATCH 0398/2898] drm/amd/display: remove unnecessary allocation for regamma_params inside opp Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 10 +--------- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 4 ---- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 2 +- 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 121ccbb1ad2d..f716a9e8784e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -987,10 +987,6 @@ bool dce110_opp_construct(struct dce110_opp *opp110, opp110->base.inst = inst; - opp110->base.regamma_params = dm_alloc(sizeof(struct pwl_params)); - if (opp110->base.regamma_params == NULL) - return false; - opp110->regs = regs; opp110->opp_shift = opp_shift; opp110->opp_mask = opp_mask; @@ -1000,12 +996,8 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp) { - if (*opp) { - if ((*opp)->regamma_params) - dm_free((*opp)->regamma_params); - (*opp)->regamma_params = NULL; + if (*opp) dm_free(FROM_DCE11_OPP(*opp)); - } *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2fbf6ddcf3be..6b249f5bf1da 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -637,7 +637,7 @@ static bool dce110_set_output_transfer_func( struct output_pixel_processor *opp = pipe_ctx->opp; opp->funcs->opp_power_on_regamma_lut(opp, true); - opp->regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; + opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->public.out_transfer_func && stream->public.out_transfer_func->type == @@ -646,8 +646,8 @@ static bool dce110_set_output_transfer_func( TRANSFER_FUNCTION_SRGB) { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); } else if (dce110_translate_regamma_to_hw_format( - stream->public.out_transfer_func, opp->regamma_params)) { - opp->funcs->opp_program_regamma_pwl(opp, opp->regamma_params); + stream->public.out_transfer_func, &opp->regamma_params)) { + opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 95b3d2eb8428..6f8b414cabbc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -56,10 +56,6 @@ bool dce110_opp_v_construct(struct dce110_opp *opp110, opp110->base.ctx = ctx; - opp110->base.regamma_params = dm_alloc(sizeof(struct pwl_params)); - if (opp110->base.regamma_params == NULL) - return false; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 521bd21eb5df..92c99c3b9002 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -203,7 +203,7 @@ enum opp_regamma { struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; - struct pwl_params *regamma_params; + struct pwl_params regamma_params; const struct opp_funcs *funcs; }; -- GitLab From d4e745e3dbf43ad14759615d0236f6378db1ad4a Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 18 Apr 2017 15:35:27 -0400 Subject: [PATCH 0399/2898] drm/amd/display: set correct v_total_min and v_total_max for dce. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c | 4 ++-- .../gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 7070aaf9e433..69ae3a83d2fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -393,12 +393,12 @@ void dce110_timing_generator_set_drr( params->vertical_total_min > 0) { set_reg_field_value(v_total_max, - params->vertical_total_max - 1, + params->vertical_total_max, CRTC_V_TOTAL_MAX, CRTC_V_TOTAL_MAX); set_reg_field_value(v_total_min, - params->vertical_total_min - 1, + params->vertical_total_min, CRTC_V_TOTAL_MIN, CRTC_V_TOTAL_MIN); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 1318df7ed47e..6e3e7b6bc58c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -540,10 +540,10 @@ void dce120_timing_generator_set_drr( CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL_MIN, - CRTC_V_TOTAL_MIN, params->vertical_total_min - 1); + CRTC_V_TOTAL_MIN, params->vertical_total_min); CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL_MAX, - CRTC_V_TOTAL_MAX, params->vertical_total_max - 1); + CRTC_V_TOTAL_MAX, params->vertical_total_max); CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6, FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1, FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1, -- GitLab From de37e273df49dd015f6c308668f223327f6cf8fc Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 18 Apr 2017 17:31:46 -0400 Subject: [PATCH 0400/2898] drm/amd/display: fix memory leak Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 +++++++++++------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b1f0a50171af..1dd9c736aedc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -918,7 +918,6 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) int i; struct core_dc *core_dc = DC_TO_CORE(dc); struct validate_context *context = dm_alloc(sizeof(struct validate_context)); - bool result = true; if (!context) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -927,28 +926,29 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); post_surface_trace(dc); + for (i = 0; i < context->res_ctx.pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL) { context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( core_dc, &context->res_ctx.pipe_ctx[i]); } - if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); - result = false; - goto cleanup; + dc_resource_validate_ctx_destruct(context); + dm_free(context); + return false; } core_dc->hwss.set_bandwidth(core_dc, context, true); - dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); - -cleanup: - dc_resource_validate_ctx_destruct(context); - dm_free(context); + if (core_dc->current_context) { + dc_resource_validate_ctx_destruct(core_dc->current_context); + dm_free(core_dc->current_context); + } + core_dc->current_context = context; - return result; + return true; } bool dc_commit_surfaces_to_stream( @@ -1440,10 +1440,8 @@ void dc_update_surfaces_and_stream(struct dc *dc, return; fail: - if (core_dc->current_context != context) { - dc_resource_validate_ctx_destruct(context); - dm_free(context); - } + dc_resource_validate_ctx_destruct(context); + dm_free(context); } uint8_t dc_get_current_stream_count(const struct dc *dc) -- GitLab From 15350179f2fc3c3b28774b4abcd35c45a5449052 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Tue, 18 Apr 2017 17:43:09 -0400 Subject: [PATCH 0401/2898] drm/amd/display: always retrieve PSR cap Signed-off-by: Amy Zhang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 913b01cd7159..4ef3fec44d2d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2169,8 +2169,7 @@ static void retrieve_link_cap(struct core_link *link) CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); /* TODO: Confirm if need retrieve_psr_link_cap */ - if (link->public.reported_link_cap.link_rate < LINK_RATE_HIGH2) - retrieve_psr_link_cap(link, link->edp_revision); + retrieve_psr_link_cap(link, link->edp_revision); } void detect_dp_sink_caps(struct core_link *link) -- GitLab From 6c626ffb1bfa2705e71376fe20bcdc6b89aace85 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 21 Apr 2017 11:00:43 -0400 Subject: [PATCH 0402/2898] drm/amd/display: Make sure v_total_min and max not less than v_total. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_timing_generator.c | 4 ++-- .../amd/display/dc/dce120/dce120_timing_generator.c | 4 ++-- .../gpu/drm/amd/display/modules/freesync/freesync.c | 12 ++++++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 69ae3a83d2fe..7070aaf9e433 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -393,12 +393,12 @@ void dce110_timing_generator_set_drr( params->vertical_total_min > 0) { set_reg_field_value(v_total_max, - params->vertical_total_max, + params->vertical_total_max - 1, CRTC_V_TOTAL_MAX, CRTC_V_TOTAL_MAX); set_reg_field_value(v_total_min, - params->vertical_total_min, + params->vertical_total_min - 1, CRTC_V_TOTAL_MIN, CRTC_V_TOTAL_MIN); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 6e3e7b6bc58c..1318df7ed47e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -540,10 +540,10 @@ void dce120_timing_generator_set_drr( CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL_MIN, - CRTC_V_TOTAL_MIN, params->vertical_total_min); + CRTC_V_TOTAL_MIN, params->vertical_total_min - 1); CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL_MAX, - CRTC_V_TOTAL_MAX, params->vertical_total_max); + CRTC_V_TOTAL_MAX, params->vertical_total_max - 1); CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6, FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1, FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1, diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 94566c0a0e62..5c6de723da5d 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -347,6 +347,7 @@ static void calc_vmin_vmax(struct core_freesync *core_freesync, { unsigned int min_frame_duration_in_ns = 0, max_frame_duration_in_ns = 0; unsigned int index = map_index_from_stream(core_freesync, stream); + uint32_t vtotal = stream->timing.v_total; min_frame_duration_in_ns = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), @@ -362,6 +363,17 @@ static void calc_vmin_vmax(struct core_freesync *core_freesync, *vmin = div64_u64(div64_u64(((unsigned long long)( min_frame_duration_in_ns) * stream->timing.pix_clk_khz), stream->timing.h_total), 1000000); + + /* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */ + if (*vmin < vtotal) { + ASSERT(false); + *vmin = vtotal; + } + + if (*vmax < vtotal) { + ASSERT(false); + *vmax = vtotal; + } } static void calc_v_total_from_duration(const struct dc_stream *stream, -- GitLab From 03f5c686c3900f74853539cdebe4c25190106402 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 21 Apr 2017 17:15:40 -0400 Subject: [PATCH 0403/2898] drm/amd/display: USB-c DP-HDMI dongle shows garbage on Sony TV Signed-off-by: Charlene Liu Acked-by: Harry Wentland Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 21 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 8 +++++-- drivers/gpu/drm/amd/display/dc/dc_types.h | 20 ++++++++++++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 4ef3fec44d2d..953e201dc6bc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1951,14 +1951,33 @@ static void get_active_converter_info( link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER; + link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type; if (ds_port.fields.DETAILED_CAPS) { union dwnstream_port_caps_byte3_hdmi hdmi_caps = {.raw = det_caps[3] }; + union dwnstream_port_caps_byte1 + hdmi_color_caps = {.raw = det_caps[2] }; + link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk = + det_caps[1] * 25000; - link->dpcd_caps.is_dp_hdmi_s3d_converter = + link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter = hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK; + link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through = + hdmi_caps.bits.YCrCr422_PASS_THROUGH; + link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through = + hdmi_caps.bits.YCrCr420_PASS_THROUGH; + link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter = + hdmi_caps.bits.YCrCr422_CONVERSION; + link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter = + hdmi_caps.bits.YCrCr420_CONVERSION; + + link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc = + hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT; + + link->dpcd_caps.dongle_caps.extendedCapValid = true; } + break; } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1b3fd79ce624..d35fa01024f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -623,7 +623,7 @@ struct dpcd_caps { union sink_count sink_count; /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ - bool is_dp_hdmi_s3d_converter; + struct dc_dongle_caps dongle_caps; bool allow_invalid_MSA_timing_param; bool panel_mode_edp; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index cd2323a71760..77e2de69cca3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -255,7 +255,7 @@ enum dpcd_downstream_port_detailed_type { DOWN_STREAM_DETAILED_DP_PLUS_PLUS }; -union dwnstream_port_caps_byte2 { +union dwnstream_port_caps_byte1 { struct { uint8_t MAX_BITS_PER_COLOR_COMPONENT:2; uint8_t RESERVED:6; @@ -287,7 +287,11 @@ union dwnstream_port_caps_byte3_dvi { union dwnstream_port_caps_byte3_hdmi { struct { uint8_t FRAME_SEQ_TO_FRAME_PACK:1; - uint8_t RESERVED:7; + uint8_t YCrCr422_PASS_THROUGH:1; + uint8_t YCrCr420_PASS_THROUGH:1; + uint8_t YCrCr422_CONVERSION:1; + uint8_t YCrCr420_CONVERSION:1; + uint8_t RESERVED:3; } bits; uint8_t raw; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index e0436e317341..2ba02b50bc18 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -338,6 +338,26 @@ enum { LAYER_INDEX_PRIMARY = -1, }; +enum dpcd_downstream_port_max_bpc { + DOWN_STREAM_MAX_8BPC = 0, + DOWN_STREAM_MAX_10BPC, + DOWN_STREAM_MAX_12BPC, + DOWN_STREAM_MAX_16BPC +}; +struct dc_dongle_caps { + /* dongle type (DP converter, CV smart dongle) */ + enum display_dongle_type dongle_type; + bool extendedCapValid; + /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, + indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ + bool is_dp_hdmi_s3d_converter; + bool is_dp_hdmi_ycbcr422_pass_through; + bool is_dp_hdmi_ycbcr420_pass_through; + bool is_dp_hdmi_ycbcr422_converter; + bool is_dp_hdmi_ycbcr420_converter; + uint32_t dp_hdmi_max_bpc; + uint32_t dp_hdmi_max_pixel_clk; +}; /* Scaling format */ enum scaling_transformation { SCALING_TRANSFORMATION_UNINITIALIZED, -- GitLab From beb16b6a0f921f66472e4946a4955f07942fa9d8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 21 Apr 2017 09:34:09 -0400 Subject: [PATCH 0404/2898] drm/amd/display: improve cursor programming reliability This change will cache cursor attributes and reprogram them when enabling cursor after power gating if the attributes were not yet reprogrammed Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_stream.c | 55 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- .../drm/amd/display/dc/dce110/dce110_ipp.h | 2 +- .../amd/display/dc/dce110/dce110_ipp_cursor.c | 4 +- .../drm/amd/display/dc/dce120/dce120_ipp.h | 2 +- .../amd/display/dc/dce120/dce120_ipp_cursor.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 4 +- 7 files changed, 32 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 3dbd6c0885d8..23627b14c16c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -182,7 +182,6 @@ bool dc_stream_set_cursor_attributes( struct core_stream *stream; struct core_dc *core_dc; struct resource_context *res_ctx; - bool ret = false; if (NULL == dc_stream) { dm_error("DC: dc_stream is NULL!\n"); @@ -200,28 +199,26 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if ((pipe_ctx->stream == stream) && - (pipe_ctx->ipp != NULL)) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; + if (pipe_ctx->stream != stream || !pipe_ctx->ipp) + continue; + if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + continue; - if (ipp->funcs->ipp_cursor_set_attributes( - ipp, attributes)) - ret = true; - } + pipe_ctx->ipp->funcs->ipp_cursor_set_attributes( + pipe_ctx->ipp, attributes); } - return ret; + return true; } bool dc_stream_set_cursor_position( const struct dc_stream *dc_stream, - struct dc_cursor_position *position) + const struct dc_cursor_position *position) { int i; struct core_stream *stream; struct core_dc *core_dc; struct resource_context *res_ctx; - bool ret = false; if (NULL == dc_stream) { dm_error("DC: dc_stream is NULL!\n"); @@ -239,27 +236,27 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct dc_cursor_position pos_cpy = *position; + struct dc_cursor_mi_param param = { + .pixel_clk_khz = dc_stream->timing.pix_clk_khz, + .ref_clk_khz = res_ctx->pool->ref_clock_inKhz, + .viewport_x_start = pipe_ctx->scl_data.viewport.x, + .viewport_width = pipe_ctx->scl_data.viewport.width, + .h_scale_ratio = pipe_ctx->scl_data.ratios.horz + }; + + if (pipe_ctx->stream != stream || + !pipe_ctx->ipp || !pipe_ctx->surface) + continue; - if (pipe_ctx->stream == stream && - pipe_ctx->ipp && pipe_ctx->surface) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct dc_cursor_mi_param param = { - .pixel_clk_khz = dc_stream->timing.pix_clk_khz, - .ref_clk_khz = res_ctx->pool->ref_clock_inKhz, - .viewport_x_start = pipe_ctx->scl_data.viewport.x, - .viewport_width = pipe_ctx->scl_data.viewport.width, - .h_scale_ratio = pipe_ctx->scl_data.ratios.horz, - }; - - if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) - position->enable = false; - - ipp->funcs->ipp_cursor_set_position(ipp, position, ¶m); - ret = true; - } + if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + pos_cpy.enable = false; + + ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); } - return ret; + return true; } uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d35fa01024f8..5629e3ca6336 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -764,7 +764,7 @@ bool dc_stream_set_cursor_attributes( bool dc_stream_set_cursor_position( const struct dc_stream *stream, - struct dc_cursor_position *position); + const struct dc_cursor_position *position); /* Newer interfaces */ struct dc_cursor { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h index a374ef2c9d0b..434fe2f5a9d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -54,7 +54,7 @@ void dce110_ipp_cursor_set_position( const struct dc_cursor_position *position, const struct dc_cursor_mi_param *param); -bool dce110_ipp_cursor_set_attributes( +void dce110_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c index 5b230b17fc5c..f712916563b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c @@ -95,7 +95,7 @@ void dce110_ipp_cursor_set_position( lock(ipp110, false); } -bool dce110_ipp_cursor_set_attributes( +void dce110_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes) { @@ -122,8 +122,6 @@ bool dce110_ipp_cursor_set_attributes( /* Unlock Cursor registers. */ lock(ipp110, false); - - return true; } static void enable( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h index 4b326bcb4600..7f645fde7064 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h @@ -42,7 +42,7 @@ void dce120_ipp_cursor_set_position( const struct dc_cursor_position *position, const struct dc_cursor_mi_param *param); -bool dce120_ipp_cursor_set_attributes( +void dce120_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c index 15671fd2cb9c..dc81d320f6e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c @@ -160,7 +160,7 @@ void dce120_ipp_cursor_set_position( lock(ipp110, false); } -bool dce120_ipp_cursor_set_attributes( +void dce120_ipp_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes) { @@ -189,7 +189,5 @@ bool dce120_ipp_cursor_set_attributes( /* Unlock Cursor registers. */ lock(ipp110, false); - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 0457bc7a44d4..7928e230eefb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -37,8 +37,6 @@ struct input_pixel_processor { struct dc_context *ctx; unsigned int inst; const struct ipp_funcs *funcs; - - unsigned int cusor_width; }; enum ipp_prescale_mode { @@ -88,7 +86,7 @@ struct ipp_funcs { const struct dc_cursor_position *position, const struct dc_cursor_mi_param *param); - bool (*ipp_cursor_set_attributes)( + void (*ipp_cursor_set_attributes)( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attributes); -- GitLab From d27383a2b5719be60ac86deae30e89755f868a07 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 21 Apr 2017 10:55:01 -0400 Subject: [PATCH 0405/2898] drm/amd/display: Make dc_link param const in set_drive_settings Signed-off-by: Zeyu Fan Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 953e201dc6bc..17286465e850 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -605,7 +605,7 @@ static bool is_max_vs_reached( } void dc_link_dp_set_drive_settings( - struct dc_link *link, + const struct dc_link *link, struct link_training_settings *lt_settings) { struct core_link *core_link = DC_LINK_TO_CORE(link); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5629e3ca6336..a2a9e4ed393c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -691,7 +691,7 @@ void dc_link_remove_remote_sink( void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink); void dc_link_dp_set_drive_settings( - struct dc_link *link, + const struct dc_link *link, struct link_training_settings *lt_settings); bool dc_link_dp_perform_link_training( -- GitLab From 94267b3df7ee00f21fa0ff7d618ca7e0574db5ed Mon Sep 17 00:00:00 2001 From: Sylvia Tsai Date: Fri, 21 Apr 2017 15:29:55 -0400 Subject: [PATCH 0406/2898] drm/amd/display: PSR Refactor - Refacotr PSR to follow correct module pattern - fix eDP only working on sink index 0. Signed-off-by: Sylvia Tsai Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 74 ++++++++----------- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 22 +++--- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 53 +------------ .../gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 17 ++++- drivers/gpu/drm/amd/display/dc/dc_types.h | 24 +++--- .../display/dc/dce110/dce110_hw_sequencer.c | 18 ++++- .../dc/dce110/dce110_timing_generator.c | 16 ---- .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- .../amd/display/modules/freesync/freesync.c | 14 +++- 11 files changed, 93 insertions(+), 150 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1dd9c736aedc..93c936d92f5a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -199,6 +199,32 @@ static bool set_gamut_remap(struct dc *dc, return ret; } +static void set_static_screen_events(struct dc *dc, + const struct dc_stream **stream, + int num_streams, + const struct dc_static_screen_events *events) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + int i = 0; + int j = 0; + struct pipe_ctx *pipes_affected[MAX_PIPES]; + int num_pipes_affected = 0; + + for (i = 0; i < num_streams; i++) { + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[i]); + + for (j = 0; j < MAX_PIPES; j++) { + if (core_dc->current_context->res_ctx.pipe_ctx[j].stream + == core_stream) { + pipes_affected[num_pipes_affected++] = + &core_dc->current_context->res_ctx.pipe_ctx[j]; + } + } + } + + core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); +} + /* This function is not expected to fail, proper implementation of * validation will prevent this from ever being called for unsupported * configurations. @@ -240,45 +266,6 @@ static void stream_update_scaling( } } -static bool set_psr_enable(struct dc *dc, bool enable) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i; - - for (i = 0; i < core_dc->link_count; i++) - dc_link_set_psr_enable(&core_dc->links[i]->public, - enable); - - return true; -} - - -static bool setup_psr(struct dc *dc, const struct dc_stream *stream) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct pipe_ctx *pipes; - int i; - unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; - - for (i = 0; i < core_dc->link_count; i++) { - if (core_stream->sink->link == core_dc->links[i]) - dc_link_setup_psr(&core_dc->links[i]->public, - stream); - } - - for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream && i != underlay_idx) { - pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.set_static_screen_control(&pipes, 1, - 0x182); - } - } - - return true; -} - static void set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link) @@ -359,15 +346,12 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) stream_adjust_vmin_vmax; } + core_dc->public.stream_funcs.set_static_screen_events = + set_static_screen_events; + core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; - core_dc->public.stream_funcs.set_psr_enable = - set_psr_enable; - - core_dc->public.stream_funcs.setup_psr = - setup_psr; - core_dc->public.link_funcs.set_drive_settings = set_drive_settings; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 426f7f8187a6..6f78403e2d64 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1430,14 +1430,14 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) struct core_dc *core_dc = DC_TO_CORE(ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; - if (dmcu != NULL && dc_link->psr_caps.psr_version > 0) + if (dmcu != NULL && link->psr_enabled) dmcu->funcs->set_psr_enable(dmcu, enable); return true; } bool dc_link_setup_psr(const struct dc_link *dc_link, - const struct dc_stream *stream) + const struct dc_stream *stream, struct psr_config *psr_config) { struct core_link *link = DC_LINK_TO_CORE(dc_link); struct dc_context *ctx = link->ctx; @@ -1449,10 +1449,8 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, psr_context.controllerId = CONTROLLER_ID_UNDEFINED; - if (dc_link != NULL && - dmcu != NULL && - dc_link->psr_caps.psr_version > 0) { + dmcu != NULL) { /* updateSinkPsrDpcdConfig*/ union dpcd_psr_configuration psr_configuration; @@ -1461,10 +1459,10 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, psr_configuration.bits.ENABLE = 1; psr_configuration.bits.CRC_VERIFICATION = 1; psr_configuration.bits.FRAME_CAPTURE_INDICATION = - dc_link->psr_caps.psr_frame_capture_indication_req; + psr_config->psr_frame_capture_indication_req; /* Check for PSR v2*/ - if (dc_link->psr_caps.psr_version == 0x2) { + if (psr_config->psr_version == 0x2) { /* For PSR v2 selective update. * Indicates whether sink should start capturing * immediately following active scan line, @@ -1512,14 +1510,13 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, stream->timing.v_total), stream->timing.h_total); - psr_context.psrSupportedDisplayConfig = - (dc_link->psr_caps.psr_version > 0) ? true : false; + psr_context.psrSupportedDisplayConfig = true; psr_context.psrExitLinkTrainingRequired = - dc_link->psr_caps.psr_exit_link_training_required; + psr_config->psr_exit_link_training_required; psr_context.sdpTransmitLineNumDeadline = - dc_link->psr_caps.psr_sdp_transmit_line_num_deadline; + psr_config->psr_sdp_transmit_line_num_deadline; psr_context.psrFrameCaptureIndicationReq = - dc_link->psr_caps.psr_frame_capture_indication_req; + psr_config->psr_frame_capture_indication_req; psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */ @@ -1550,6 +1547,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, */ psr_context.frame_delay = 0; + link->psr_enabled = true; dmcu->funcs->setup_psr(dmcu, link, &psr_context); return true; } else diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 17286465e850..f883fdb820c8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1478,7 +1478,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) { union dpcd_psr_configuration psr_configuration; - if (link->public.psr_caps.psr_version == 0) + if (!link->psr_enabled) return false; dm_helpers_dp_read_dpcd( @@ -2060,36 +2060,6 @@ static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, link->wa_flags.dp_keep_receiver_powered = false; } -static void retrieve_psr_link_cap(struct core_link *link, - enum edp_revision edp_revision) -{ - if (edp_revision >= EDP_REVISION_13) { - core_link_read_dpcd(link, - DP_PSR_SUPPORT, - (uint8_t *)(&link->public.psr_caps), - sizeof(link->public.psr_caps)); - if (link->public.psr_caps.psr_version != 0) { - unsigned char psr_capability = 0; - - core_link_read_dpcd(link, - DP_PSR_CAPS, - &psr_capability, - sizeof(psr_capability)); - /* Bit 0 determines whether fast link training is - * required on PSR exit. If set to 0, link training - * is required. If set to 1, sink must lock within - * five Idle Patterns after Main Link is turned on. - */ - link->public.psr_caps.psr_exit_link_training_required - = !(psr_capability & 0x1); - - psr_capability = (psr_capability >> 1) & 0x7; - link->public.psr_caps.psr_rfb_setup_time = - 55 * (6 - psr_capability); - } - } -} - static void retrieve_link_cap(struct core_link *link) { uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1]; @@ -2157,38 +2127,17 @@ static void retrieve_link_cap(struct core_link *link) link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; - link->edp_revision = EDP_REVISION_11; - link->public.test_pattern_enabled = false; link->public.compliance_test_state.raw = 0; - link->public.psr_caps.psr_exit_link_training_required = false; - link->public.psr_caps.psr_frame_capture_indication_req = false; - link->public.psr_caps.psr_rfb_setup_time = 0; - link->public.psr_caps.psr_sdp_transmit_line_num_deadline = 0; - link->public.psr_caps.psr_version = 0; - /* read sink count */ core_link_read_dpcd(link, DP_SINK_COUNT, &link->dpcd_caps.sink_count.raw, sizeof(link->dpcd_caps.sink_count.raw)); - /* Display control registers starting at DPCD 700h are only valid and - * enabled if this eDP config cap bit is set. */ - if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) { - /* Read the Panel's eDP revision at DPCD 700h. */ - core_link_read_dpcd(link, - DP_EDP_DPCD_REV, - (uint8_t *)(&link->edp_revision), - sizeof(link->edp_revision)); - } - /* Connectivity log: detection */ CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); - - /* TODO: Confirm if need retrieve_psr_link_cap */ - retrieve_psr_link_cap(link, link->edp_revision); } void detect_dp_sink_caps(struct core_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2e12a0ba5ddf..cdb98d5f7caa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2015,7 +2015,7 @@ static void set_vsc_info_packet( unsigned int vscPacketRevision = 0; unsigned int i; - if (stream->sink->link->public.psr_caps.psr_version != 0) { + if (stream->sink->link->psr_enabled) { vscPacketRevision = 2; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a2a9e4ed393c..d12aa726164e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -82,6 +82,12 @@ struct dc_surface_dcc_cap { }; }; +struct dc_static_screen_events { + bool cursor_update; + bool surface_update; + bool overlay_update; +}; + /* Forward declaration*/ struct dc; struct dc_surface; @@ -102,10 +108,14 @@ struct dc_stream_funcs { const struct dc_stream *dc_stream, const struct rect *src, const struct rect *dst); + bool (*set_gamut_remap)(struct dc *dc, const struct dc_stream **stream, int num_streams); - bool (*set_psr_enable)(struct dc *dc, bool enable); - bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream); + + void (*set_static_screen_events)(struct dc *dc, + const struct dc_stream **stream, + int num_streams, + const struct dc_static_screen_events *events); }; struct link_training_settings; @@ -604,7 +614,6 @@ struct dc_link { uint8_t ddc_hw_inst; uint8_t link_enc_hw_inst; - struct psr_caps psr_caps; bool test_pattern_enabled; union compliance_test_state compliance_test_state; @@ -657,7 +666,7 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_setup_psr(const struct dc_link *dc_link, - const struct dc_stream *stream); + const struct dc_stream *stream, struct psr_config *psr_config); /* Request DC to detect if there is a Panel connected. * boot - If this call is during initial boot. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 2ba02b50bc18..d2f3b9fd7a30 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -484,6 +484,15 @@ struct freesync_context { unsigned int nominal_refresh_in_micro_hz; }; +struct psr_config { + unsigned char psr_version; + unsigned int psr_rfb_setup_time; + bool psr_exit_link_training_required; + + bool psr_frame_capture_indication_req; + unsigned int psr_sdp_transmit_line_num_deadline; +}; + struct colorspace_transform { struct fixed31_32 matrix[12]; bool enable_remap; @@ -494,21 +503,6 @@ struct csc_transform { bool enable_adjustment; }; -struct psr_caps { - /* These parameters are from PSR capabilities reported by Sink DPCD */ - unsigned char psr_version; - unsigned int psr_rfb_setup_time; - bool psr_exit_link_training_required; - - /* These parameters are calculated in Driver, - * based on display timing and Sink capabilities. - * If VBLANK region is too small and Sink takes a long time - * to set up RFB, it may take an extra frame to enter PSR state. - */ - bool psr_frame_capture_indication_req; - unsigned int psr_sdp_transmit_line_num_deadline; -}; - enum i2c_mot_mode { I2C_MOT_UNDEF, I2C_MOT_TRUE, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6b249f5bf1da..6a93c96b9b26 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1005,6 +1005,10 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( pipe_ctx->tg, &stream->public.timing, true); + + pipe_ctx->tg->funcs->set_static_screen_control( + pipe_ctx->tg, + 0x182); } if (!pipe_ctx_old->stream) { @@ -1015,6 +1019,8 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( } } + + return DC_OK; } @@ -1114,6 +1120,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->public.timing.pix_clk_khz, context->stream_count); + pipe_ctx->stream->sink->link->psr_enabled = false; + return DC_OK; } @@ -1355,9 +1363,17 @@ static void set_drr(struct pipe_ctx **pipe_ctx, } static void set_static_screen_control(struct pipe_ctx **pipe_ctx, - int num_pipes, int value) + int num_pipes, const struct dc_static_screen_events *events) { unsigned int i; + unsigned int value = 0; + + if (events->overlay_update) + value |= 0x100; + if (events->surface_update) + value |= 0x80; + if (events->cursor_update) + value |= 0x2; for (i = 0; i < num_pipes; i++) pipe_ctx[i]->tg->funcs-> diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 7070aaf9e433..23760727f000 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -371,7 +371,6 @@ void dce110_timing_generator_set_drr( uint32_t v_total_min = 0; uint32_t v_total_max = 0; uint32_t v_total_cntl = 0; - uint32_t static_screen_cntl = 0; struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t addr = 0; @@ -385,9 +384,6 @@ void dce110_timing_generator_set_drr( addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); v_total_cntl = dm_read_reg(tg->ctx, addr); - addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); - static_screen_cntl = dm_read_reg(tg->ctx, addr); - if (params != NULL && params->vertical_total_max > 0 && params->vertical_total_min > 0) { @@ -430,20 +426,11 @@ void dce110_timing_generator_set_drr( 0, CRTC_V_TOTAL_CONTROL, CRTC_SET_V_TOTAL_MIN_MASK); - - set_reg_field_value(static_screen_cntl, - 0x180, - CRTC_STATIC_SCREEN_CONTROL, - CRTC_STATIC_SCREEN_EVENT_MASK); } else { set_reg_field_value(v_total_cntl, 0, CRTC_V_TOTAL_CONTROL, CRTC_SET_V_TOTAL_MIN_MASK); - set_reg_field_value(static_screen_cntl, - 0, - CRTC_STATIC_SCREEN_CONTROL, - CRTC_STATIC_SCREEN_EVENT_MASK); set_reg_field_value(v_total_min, 0, CRTC_V_TOTAL_MIN, @@ -478,9 +465,6 @@ void dce110_timing_generator_set_drr( addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL); dm_write_reg(tg->ctx, addr, v_total_cntl); - - addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL); - dm_write_reg(tg->ctx, addr, static_screen_cntl); } void dce110_timing_generator_set_static_screen_control( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 405608318ccc..2b43e18c65f5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -156,6 +156,7 @@ struct core_link { unsigned int dpcd_sink_count; enum edp_revision edp_revision; + bool psr_enabled; /* MST record stream using this link */ struct link_flags { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 9bfaaad09bea..b42e4a0ef18a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -132,7 +132,7 @@ struct hw_sequencer_funcs { int vmin, int vmax); void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, - int num_pipes, int value); + int num_pipes, const struct dc_static_screen_events *events); enum dc_status (*prog_pixclk_crtc_otg)( struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 5c6de723da5d..78b4f28d862c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -264,10 +264,10 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, enable_for_video = false; } - temp = core_stream->public.timing.pix_clk_khz; + temp = stream->timing.pix_clk_khz; temp *= 1000ULL * 1000ULL * 1000ULL; - temp = div_u64(temp, core_stream->public.timing.h_total); - temp = div_u64(temp, core_stream->public.timing.v_total); + temp = div_u64(temp, stream->timing.h_total); + temp = div_u64(temp, stream->timing.v_total); nom_refresh_rate_micro_hz = (unsigned int) temp; @@ -657,6 +657,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, unsigned int min_frame_duration_in_ns, vmax, vmin = 0; struct freesync_state *state; struct core_freesync *core_freesync = NULL; + struct dc_static_screen_events triggers = {0}; if (mod_freesync == NULL) return; @@ -749,6 +750,13 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, core_freesync->dc, streams, num_streams, v_total, v_total); + + triggers.overlay_update = true; + triggers.surface_update = true; + + core_freesync->dc->stream_funcs.set_static_screen_events( + core_freesync->dc, streams, num_streams, + &triggers); } } -- GitLab From e91b57334a4ef9355ffa397d767e8c3a2c690f22 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 23 Apr 2017 10:46:02 -0400 Subject: [PATCH 0407/2898] drm/amd/display: move tg_color to dc_hw_types Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 12 ++++++------ .../gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 12 ------------ 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index b785dd7b3a97..64d43dba8fd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -641,12 +641,12 @@ struct dc_crtc_timing { struct dc_crtc_timing_flags flags; }; -struct _dlg_otg_param { - int vstartup_start; - int vupdate_offset; - int vupdate_width; - int vready_offset; - enum signal_type signal; +#define MAX_TG_COLOR_VALUE 0x3FF +struct tg_color { + /* Maximum 10 bits color value */ + uint16_t color_r_cr; + uint16_t color_g_y; + uint16_t color_b_cb; }; #endif /* DC_HW_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index b3deaf2d8173..235cfe8d1ad4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -28,18 +28,6 @@ struct dc_bios; -/** - * These parameters are required as input when doing blanking/Unblanking -*/ -#define MAX_TG_COLOR_VALUE 0x3FF - -struct tg_color { - /* Maximum 10 bits color value */ - uint16_t color_r_cr; - uint16_t color_g_y; - uint16_t color_b_cb; -}; - /* Contains CRTC vertical/horizontal pixel counters */ struct crtc_position { uint32_t vertical_count; -- GitLab From 50db413d557c39de9a976e2c9826d4e86e721c7c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 23 Apr 2017 23:33:26 -0400 Subject: [PATCH 0408/2898] drm/amd/display: clarify delay param for REG_WAIT Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index b595b94d2b69..96fba1fb7697 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -185,10 +185,10 @@ /* macro to poll and wait for a register field to read back given value */ -#define REG_WAIT(reg_name, field, val, delay, max_try) \ +#define REG_WAIT(reg_name, field, val, delay_between_poll_us, max_try) \ generic_reg_wait(CTX, \ REG(reg_name), FN(reg_name, field), val,\ - delay, max_try, __func__) + delay_between_poll_us, max_try, __func__) /* macro to update (read, modify, write) register fields */ -- GitLab From 86b6a203b966ea54e3225b49e53769cf4c116905 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 24 Apr 2017 15:20:24 -0400 Subject: [PATCH 0409/2898] drm/amd/display: dce120 to dce ipp refactor Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 252 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h | 226 ++++++++++++++++ .../drm/amd/display/dc/dce/dce_transform.h | 2 +- .../drm/amd/display/dc/dce110/dce110_ipp.h | 2 +- .../amd/display/dc/dce110/dce110_ipp_gamma.c | 4 +- .../gpu/drm/amd/display/dc/dce120/Makefile | 1 - .../drm/amd/display/dc/dce120/dce120_ipp.c | 58 ---- .../drm/amd/display/dc/dce120/dce120_ipp.h | 62 ----- .../amd/display/dc/dce120/dce120_ipp_cursor.c | 193 -------------- .../amd/display/dc/dce120/dce120_ipp_gamma.c | 167 ------------ .../amd/display/dc/dce120/dce120_resource.c | 69 +++-- .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 3 + drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 5 +- 14 files changed, 521 insertions(+), 525 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile index 05562553b656..8abec0bed379 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile @@ -7,7 +7,7 @@ DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ -dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o +dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c new file mode 100644 index 000000000000..d6bf6067a309 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -0,0 +1,252 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dce_ipp.h" +#include "reg_helper.h" +#include "dm_services.h" + +#define REG(reg) \ + (ipp_dce->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + ipp_dce->ipp_shift->field_name, ipp_dce->ipp_mask->field_name + +#define CTX \ + ipp_dce->base.ctx + +static void dce_ipp_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *position, + const struct dc_cursor_mi_param *param) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + + /* lock cursor registers */ + REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, true); + + /* Flag passed in structure differentiates cursor enable/disable. */ + /* Update if it differs from cached state. */ + REG_UPDATE(CUR_CONTROL, CURSOR_EN, position->enable); + + REG_SET_2(CUR_POSITION, 0, + CURSOR_X_POSITION, position->x, + CURSOR_Y_POSITION, position->y); + + REG_SET_2(CUR_HOT_SPOT, 0, + CURSOR_HOT_SPOT_X, position->x_hotspot, + CURSOR_HOT_SPOT_Y, position->y_hotspot); + + /* unlock cursor registers */ + REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false); +} + +static void dce_ipp_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attributes) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + int mode; + + /* Lock cursor registers */ + REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, true); + + /* Program cursor control */ + switch (attributes->color_format) { + case CURSOR_MODE_MONO: + mode = 0; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + mode = 1; + break; + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + mode = 2; + break; + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + mode = 3; + break; + default: + BREAK_TO_DEBUGGER(); /* unsupported */ + mode = 0; + } + + REG_UPDATE_3(CUR_CONTROL, + CURSOR_MODE, mode, + CURSOR_2X_MAGNIFY, attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, + CUR_INV_TRANS_CLAMP, attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); + + if (attributes->color_format == CURSOR_MODE_MONO) { + REG_SET_3(CUR_COLOR1, 0, + CUR_COLOR1_BLUE, 0, + CUR_COLOR1_GREEN, 0, + CUR_COLOR1_RED, 0); + + REG_SET_3(CUR_COLOR2, 0, + CUR_COLOR2_BLUE, 0xff, + CUR_COLOR2_GREEN, 0xff, + CUR_COLOR2_RED, 0xff); + } + + /* + * Program cursor size -- NOTE: HW spec specifies that HW register + * stores size as (height - 1, width - 1) + */ + REG_SET_2(CUR_SIZE, 0, + CURSOR_WIDTH, attributes->width-1, + CURSOR_HEIGHT, attributes->height-1); + + /* Program cursor surface address */ + /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor + * surface base address in byte. It is 4K byte aligned. + * The correct way to program cursor surface address is to first write + * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS + */ + REG_SET(CUR_SURFACE_ADDRESS_HIGH, 0, + CURSOR_SURFACE_ADDRESS_HIGH, attributes->address.high_part); + + REG_SET(CUR_SURFACE_ADDRESS, 0, + CURSOR_SURFACE_ADDRESS, attributes->address.low_part); + + /* Unlock Cursor registers. */ + REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false); +} + +static void dce_ipp_program_prescale( + struct input_pixel_processor *ipp, + struct ipp_prescale_params *params) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + + /* set to bypass mode first before change */ + REG_UPDATE(PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, + 1); + + REG_SET_2(PRESCALE_VALUES_GRPH_R, 0, + GRPH_PRESCALE_SCALE_R, params->scale, + GRPH_PRESCALE_BIAS_R, params->bias); + + REG_SET_2(PRESCALE_VALUES_GRPH_G, 0, + GRPH_PRESCALE_SCALE_G, params->scale, + GRPH_PRESCALE_BIAS_G, params->bias); + + REG_SET_2(PRESCALE_VALUES_GRPH_B, 0, + GRPH_PRESCALE_SCALE_B, params->scale, + GRPH_PRESCALE_BIAS_B, params->bias); + + if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + REG_UPDATE(PRESCALE_GRPH_CONTROL, + GRPH_PRESCALE_BYPASS, 0); + + /* If prescale is in use, then legacy lut should be bypassed */ + REG_UPDATE(INPUT_GAMMA_CONTROL, + GRPH_INPUT_GAMMA_MODE, 1); + } +} + +static void dce_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + + /* power on LUT memory */ + REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 1); + + /* enable all */ + REG_SET(DC_LUT_WRITE_EN_MASK, 0, DC_LUT_WRITE_EN_MASK, 0x7); + + /* 256 entry mode */ + REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); + + /* LUT-256, unsigned, integer, new u0.12 format */ + REG_SET_3(DC_LUT_CONTROL, 0, + DC_LUT_DATA_R_FORMAT, 3, + DC_LUT_DATA_G_FORMAT, 3, + DC_LUT_DATA_B_FORMAT, 3); + + /* start from index 0 */ + REG_SET(DC_LUT_RW_INDEX, 0, + DC_LUT_RW_INDEX, 0); + + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->red[i]); + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->green[i]); + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->blue[i]); + } + + /* power off LUT memory */ + REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 0); + + /* bypass prescale, enable legacy LUT */ + REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); + REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); +} + +static void dce_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; + + ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || + mode == IPP_DEGAMMA_MODE_HW_sRGB); + + REG_SET_3(DEGAMMA_CONTROL, 0, + GRPH_DEGAMMA_MODE, degamma_type, + CURSOR_DEGAMMA_MODE, degamma_type, + CURSOR2_DEGAMMA_MODE, degamma_type); +} + +static const struct ipp_funcs dce_ipp_funcs = { + .ipp_cursor_set_attributes = dce_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce_ipp_cursor_set_position, + .ipp_program_prescale = dce_ipp_program_prescale, + .ipp_program_input_lut = dce_ipp_program_input_lut, + .ipp_set_degamma = dce_ipp_set_degamma +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +void dce_ipp_construct( + struct dce_ipp *ipp_dce, + struct dc_context *ctx, + int inst, + const struct dce_ipp_registers *regs, + const struct dce_ipp_shift *ipp_shift, + const struct dce_ipp_mask *ipp_mask) +{ + ipp_dce->base.ctx = ctx; + ipp_dce->base.inst = inst; + ipp_dce->base.funcs = &dce_ipp_funcs; + + ipp_dce->regs = regs; + ipp_dce->ipp_shift = ipp_shift; + ipp_dce->ipp_mask = ipp_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h new file mode 100644 index 000000000000..23f25b1b0e64 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h @@ -0,0 +1,226 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCE_DCE_IPP_H_ +#define _DCE_DCE_IPP_H_ + +#include "ipp.h" + +#define TO_DCE_IPP(ipp)\ + container_of(ipp, struct dce_ipp, base) + +#define IPP_COMMON_REG_LIST_DCE_BASE(id) \ + SRI(CUR_UPDATE, DCP, id), \ + SRI(CUR_CONTROL, DCP, id), \ + SRI(CUR_POSITION, DCP, id), \ + SRI(CUR_HOT_SPOT, DCP, id), \ + SRI(CUR_COLOR1, DCP, id), \ + SRI(CUR_COLOR2, DCP, id), \ + SRI(CUR_SIZE, DCP, id), \ + SRI(CUR_SURFACE_ADDRESS_HIGH, DCP, id), \ + SRI(CUR_SURFACE_ADDRESS, DCP, id), \ + SRI(PRESCALE_GRPH_CONTROL, DCP, id), \ + SRI(PRESCALE_VALUES_GRPH_R, DCP, id), \ + SRI(PRESCALE_VALUES_GRPH_G, DCP, id), \ + SRI(PRESCALE_VALUES_GRPH_B, DCP, id), \ + SRI(INPUT_GAMMA_CONTROL, DCP, id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ + SRI(DC_LUT_WRITE_EN_MASK, DCP, id), \ + SRI(DC_LUT_RW_MODE, DCP, id), \ + SRI(DC_LUT_CONTROL, DCP, id), \ + SRI(DC_LUT_RW_INDEX, DCP, id), \ + SRI(DC_LUT_SEQ_COLOR, DCP, id), \ + SRI(DEGAMMA_CONTROL, DCP, id) + +#define IPP_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + IPP_SF(CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_EN, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + IPP_SF(CUR_CONTROL, CUR_INV_TRANS_CLAMP, mask_sh), \ + IPP_SF(CUR_POSITION, CURSOR_X_POSITION, mask_sh), \ + IPP_SF(CUR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_BLUE, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_GREEN, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_RED, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_BLUE, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_GREEN, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_RED, mask_sh), \ + IPP_SF(CUR_SIZE, CURSOR_WIDTH, mask_sh), \ + IPP_SF(CUR_SIZE, CURSOR_HEIGHT, mask_sh), \ + IPP_SF(CUR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + IPP_SF(CUR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + IPP_SF(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_SCALE_R, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_BIAS_R, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_SCALE_G, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_BIAS_G, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \ + IPP_SF(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \ + IPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh), \ + IPP_SF(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_G_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_B_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, mask_sh), \ + IPP_SF(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, mask_sh), \ + IPP_SF(DEGAMMA_CONTROL, GRPH_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh) + +#define IPP_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ + IPP_SF(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \ + IPP_SF(DCP0_CUR_CONTROL, CURSOR_EN, mask_sh), \ + IPP_SF(DCP0_CUR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(DCP0_CUR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + IPP_SF(DCP0_CUR_CONTROL, CUR_INV_TRANS_CLAMP, mask_sh), \ + IPP_SF(DCP0_CUR_POSITION, CURSOR_X_POSITION, mask_sh), \ + IPP_SF(DCP0_CUR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + IPP_SF(DCP0_CUR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + IPP_SF(DCP0_CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_BLUE, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_GREEN, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_RED, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_BLUE, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_GREEN, mask_sh), \ + IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_RED, mask_sh), \ + IPP_SF(DCP0_CUR_SIZE, CURSOR_WIDTH, mask_sh), \ + IPP_SF(DCP0_CUR_SIZE, CURSOR_HEIGHT, mask_sh), \ + IPP_SF(DCP0_CUR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + IPP_SF(DCP0_CUR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + IPP_SF(DCP0_PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_SCALE_R, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_BIAS_R, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_SCALE_G, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_BIAS_G, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \ + IPP_SF(DCP0_PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \ + IPP_SF(DCP0_INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \ + IPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh), \ + IPP_SF(DCP0_DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(DCP0_DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \ + IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \ + IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_G_FORMAT, mask_sh), \ + IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_B_FORMAT, mask_sh), \ + IPP_SF(DCP0_DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, mask_sh), \ + IPP_SF(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, mask_sh), \ + IPP_SF(DCP0_DEGAMMA_CONTROL, GRPH_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DCP0_DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DCP0_DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh) + +#define IPP_REG_FIELD_LIST(type) \ + type CURSOR_UPDATE_LOCK; \ + type CURSOR_EN; \ + type CURSOR_X_POSITION; \ + type CURSOR_Y_POSITION; \ + type CURSOR_HOT_SPOT_X; \ + type CURSOR_HOT_SPOT_Y; \ + type CURSOR_MODE; \ + type CURSOR_2X_MAGNIFY; \ + type CUR_INV_TRANS_CLAMP; \ + type CUR_COLOR1_BLUE; \ + type CUR_COLOR1_GREEN; \ + type CUR_COLOR1_RED; \ + type CUR_COLOR2_BLUE; \ + type CUR_COLOR2_GREEN; \ + type CUR_COLOR2_RED; \ + type CURSOR_WIDTH; \ + type CURSOR_HEIGHT; \ + type CURSOR_SURFACE_ADDRESS_HIGH; \ + type CURSOR_SURFACE_ADDRESS; \ + type GRPH_PRESCALE_BYPASS; \ + type GRPH_PRESCALE_SCALE_R; \ + type GRPH_PRESCALE_BIAS_R; \ + type GRPH_PRESCALE_SCALE_G; \ + type GRPH_PRESCALE_BIAS_G; \ + type GRPH_PRESCALE_SCALE_B; \ + type GRPH_PRESCALE_BIAS_B; \ + type GRPH_INPUT_GAMMA_MODE; \ + type DCP_LUT_MEM_PWR_DIS; \ + type DC_LUT_WRITE_EN_MASK; \ + type DC_LUT_RW_MODE; \ + type DC_LUT_DATA_R_FORMAT; \ + type DC_LUT_DATA_G_FORMAT; \ + type DC_LUT_DATA_B_FORMAT; \ + type DC_LUT_RW_INDEX; \ + type DC_LUT_SEQ_COLOR; \ + type GRPH_DEGAMMA_MODE; \ + type CURSOR_DEGAMMA_MODE; \ + type CURSOR2_DEGAMMA_MODE + +struct dce_ipp_shift { + IPP_REG_FIELD_LIST(uint8_t); +}; + +struct dce_ipp_mask { + IPP_REG_FIELD_LIST(uint32_t); +}; + +struct dce_ipp_registers { + uint32_t CUR_UPDATE; + uint32_t CUR_CONTROL; + uint32_t CUR_POSITION; + uint32_t CUR_HOT_SPOT; + uint32_t CUR_COLOR1; + uint32_t CUR_COLOR2; + uint32_t CUR_SIZE; + uint32_t CUR_SURFACE_ADDRESS_HIGH; + uint32_t CUR_SURFACE_ADDRESS; + uint32_t PRESCALE_GRPH_CONTROL; + uint32_t PRESCALE_VALUES_GRPH_R; + uint32_t PRESCALE_VALUES_GRPH_G; + uint32_t PRESCALE_VALUES_GRPH_B; + uint32_t INPUT_GAMMA_CONTROL; + uint32_t DCFE_MEM_PWR_CTRL; + uint32_t DC_LUT_WRITE_EN_MASK; + uint32_t DC_LUT_RW_MODE; + uint32_t DC_LUT_CONTROL; + uint32_t DC_LUT_RW_INDEX; + uint32_t DC_LUT_SEQ_COLOR; + uint32_t DEGAMMA_CONTROL; +}; + +struct dce_ipp { + struct input_pixel_processor base; + const struct dce_ipp_registers *regs; + const struct dce_ipp_shift *ipp_shift; + const struct dce_ipp_mask *ipp_mask; +}; + +void dce_ipp_construct(struct dce_ipp *ipp_dce, + struct dc_context *ctx, + int inst, + const struct dce_ipp_registers *regs, + const struct dce_ipp_shift *ipp_shift, + const struct dce_ipp_mask *ipp_mask); + +#endif /* _DCE_DCE_IPP_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index da2a02434665..ca6c621151b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -369,7 +369,7 @@ struct dce_transform { bool prescaler_on; }; -bool dce_transform_construct(struct dce_transform *xfm110, +bool dce_transform_construct(struct dce_transform *xfm_dce, struct dc_context *ctx, uint32_t inst, const struct dce_transform_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h index 434fe2f5a9d7..8684e6a0ef4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h @@ -59,7 +59,7 @@ void dce110_ipp_cursor_set_attributes( const struct dc_cursor_attributes *attributes); /* DEGAMMA RELATED */ -bool dce110_ipp_set_degamma( +void dce110_ipp_set_degamma( struct input_pixel_processor *ipp, enum ipp_degamma_mode mode); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c index f05cc9e981f3..0bcd8a68d5e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c @@ -66,7 +66,7 @@ -bool dce110_ipp_set_degamma( +void dce110_ipp_set_degamma( struct input_pixel_processor *ipp, enum ipp_degamma_mode mode) { @@ -82,8 +82,6 @@ bool dce110_ipp_set_degamma( GRPH_DEGAMMA_MODE, degamma_type, CURSOR_DEGAMMA_MODE, degamma_type, CURSOR2_DEGAMMA_MODE, degamma_type); - - return true; } void dce110_ipp_program_prescale( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile index 3c6b3fa98ddc..826c12ee368c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile @@ -4,7 +4,6 @@ DCE120 = dce120_resource.o dce120_timing_generator.o \ -dce120_ipp.o dce120_ipp_cursor.o dce120_ipp_gamma.o \ dce120_mem_input.o dce120_hw_sequencer.o AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120)) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c deleted file mode 100644 index f4505690e01a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" - -#include "dce120_ipp.h" - -static const struct ipp_funcs funcs = { - .ipp_cursor_set_attributes = dce120_ipp_cursor_set_attributes, - .ipp_cursor_set_position = dce120_ipp_cursor_set_position, - .ipp_program_prescale = dce120_ipp_program_prescale, - .ipp_program_input_lut = dce120_ipp_program_input_lut, - .ipp_set_degamma = dce120_ipp_set_degamma, -}; - -bool dce120_ipp_construct( - struct dce110_ipp *ipp, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) -{ - if (!dce110_ipp_construct(ipp, ctx, inst, offset)) { - ASSERT_CRITICAL(false); - return false; - } - - ipp->base.funcs = &funcs; - - return true; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h deleted file mode 100644 index 7f645fde7064..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_IPP_DCE120_H__ -#define __DC_IPP_DCE120_H__ - -#include "ipp.h" -#include "../dce110/dce110_ipp.h" - - -bool dce120_ipp_construct( - struct dce110_ipp *ipp, - struct dc_context *ctx, - enum controller_id id, - const struct dce110_ipp_reg_offsets *offset); - -/* CURSOR RELATED */ -void dce120_ipp_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *position, - const struct dc_cursor_mi_param *param); - -void dce120_ipp_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attributes); - -/* DEGAMMA RELATED */ -bool dce120_ipp_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode); - -void dce120_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params); - -void dce120_ipp_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma); - -#endif /*__DC_IPP_DCE120_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c deleted file mode 100644 index dc81d320f6e5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_cursor.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" - -#include "../dce110/dce110_ipp.h" - - -#define DCP_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) - -#define DCP_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) - -#define DCP_REG_UPDATE(reg, field, val) \ - DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define DCP_REG_SET(reg, field, val) \ - DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ - DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -/* TODO: DAL3 does not implement cursor memory control - * MCIF_MEM_CONTROL, DMIF_CURSOR_MEM_CONTROL - */ -static void lock( - struct dce110_ipp *ipp110, bool lock) -{ - DCP_REG_UPDATE(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, lock); -} - -static bool program_control( - struct dce110_ipp *ipp110, - enum dc_cursor_color_format color_format, - bool enable_magnification, - bool inverse_transparent_clamping) -{ - uint32_t mode = 0; - - switch (color_format) { - case CURSOR_MODE_MONO: - mode = 0; - break; - case CURSOR_MODE_COLOR_1BIT_AND: - mode = 1; - break; - case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: - mode = 2; - break; - case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: - mode = 3; - break; - default: - return false; - } - - DCP_REG_UPDATE_3( - DCP0_CUR_CONTROL, - CURSOR_MODE, mode, - CURSOR_2X_MAGNIFY, enable_magnification, - CUR_INV_TRANS_CLAMP, inverse_transparent_clamping); - - if (color_format == CURSOR_MODE_MONO) { - DCP_REG_SET_3( - DCP0_CUR_COLOR1, - CUR_COLOR1_BLUE, 0, - CUR_COLOR1_GREEN, 0, - CUR_COLOR1_RED, 0); - - DCP_REG_SET_3( - DCP0_CUR_COLOR2, - CUR_COLOR2_BLUE, 0xff, - CUR_COLOR2_GREEN, 0xff, - CUR_COLOR2_RED, 0xff); - } - return true; -} - -static void program_address( - struct dce110_ipp *ipp110, - PHYSICAL_ADDRESS_LOC address) -{ - /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor - * surface base address in byte. It is 4K byte aligned. - * The correct way to program cursor surface address is to first write - * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS - */ - - DCP_REG_SET( - DCP0_CUR_SURFACE_ADDRESS_HIGH, - CURSOR_SURFACE_ADDRESS_HIGH, address.high_part); - - DCP_REG_SET( - DCP0_CUR_SURFACE_ADDRESS, - CURSOR_SURFACE_ADDRESS, address.low_part); -} - -void dce120_ipp_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *position, - const struct dc_cursor_mi_param *param) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* lock cursor registers */ - lock(ipp110, true); - - /* Flag passed in structure differentiates cursor enable/disable. */ - /* Update if it differs from cached state. */ - DCP_REG_UPDATE(DCP0_CUR_CONTROL, CURSOR_EN, position->enable); - - DCP_REG_SET_2( - DCP0_CUR_POSITION, - CURSOR_X_POSITION, position->x, - CURSOR_Y_POSITION, position->y); - - DCP_REG_SET_2( - DCP0_CUR_HOT_SPOT, - CURSOR_HOT_SPOT_X, position->x_hotspot, - CURSOR_HOT_SPOT_Y, position->y_hotspot); - - /* unlock cursor registers */ - lock(ipp110, false); -} - -void dce120_ipp_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attributes) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - /* Lock cursor registers */ - lock(ipp110, true); - - /* Program cursor control */ - program_control( - ipp110, - attributes->color_format, - attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, - attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); - - /* - * Program cursor size -- NOTE: HW spec specifies that HW register - * stores size as (height - 1, width - 1) - */ - DCP_REG_SET_2( - DCP0_CUR_SIZE, - CURSOR_WIDTH, attributes->width-1, - CURSOR_HEIGHT, attributes->height-1); - - /* Program cursor surface address */ - program_address(ipp110, attributes->address); - - /* Unlock Cursor registers. */ - lock(ipp110, false); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c deleted file mode 100644 index 7aa5a49c01e2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_ipp_gamma.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" -#include "include/fixed31_32.h" -#include "basics/conversion.h" - -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" - -#include "../dce110/dce110_ipp.h" - -#define DCP_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) - -#define DCP_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(ipp110->base.ctx, ipp110->offsets.dcp_offset, reg_name, n, __VA_ARGS__) - -#define DCP_REG_UPDATE(reg, field, val) \ - DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define DCP_REG_SET(reg, field, val) \ - DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ - DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - -bool dce120_ipp_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; - - ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || - mode == IPP_DEGAMMA_MODE_HW_sRGB); - - DCP_REG_SET_3( - DCP0_DEGAMMA_CONTROL, - GRPH_DEGAMMA_MODE, degamma_type, - CURSOR_DEGAMMA_MODE, degamma_type, - CURSOR2_DEGAMMA_MODE, degamma_type); - - return true; -} - -void dce120_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* set to bypass mode first before change */ - DCP_REG_UPDATE( - DCP0_PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS, - 1); - - DCP_REG_SET_2( - DCP0_PRESCALE_VALUES_GRPH_R, - GRPH_PRESCALE_SCALE_R, params->scale, - GRPH_PRESCALE_BIAS_R, params->bias); - - DCP_REG_SET_2( - DCP0_PRESCALE_VALUES_GRPH_G, - GRPH_PRESCALE_SCALE_G, params->scale, - GRPH_PRESCALE_BIAS_G, params->bias); - - DCP_REG_SET_2( - DCP0_PRESCALE_VALUES_GRPH_B, - GRPH_PRESCALE_SCALE_B, params->scale, - GRPH_PRESCALE_BIAS_B, params->bias); - - if (params->mode != IPP_PRESCALE_MODE_BYPASS) { - DCP_REG_UPDATE(DCP0_PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS, 0); - - /* If prescale is in use, then legacy lut should be bypassed */ - DCP_REG_UPDATE(DCP0_INPUT_GAMMA_CONTROL, - GRPH_INPUT_GAMMA_MODE, 1); - } -} - -static void dce120_helper_select_lut(struct dce110_ipp *ipp110) -{ - /* enable all */ - DCP_REG_SET( - DCP0_DC_LUT_WRITE_EN_MASK, - DC_LUT_WRITE_EN_MASK, - 0x7); - - /* 256 entry mode */ - DCP_REG_UPDATE(DCP0_DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); - - /* LUT-256, unsigned, integer, new u0.12 format */ - DCP_REG_SET_3( - DCP0_DC_LUT_CONTROL, - DC_LUT_DATA_R_FORMAT, 3, - DC_LUT_DATA_G_FORMAT, 3, - DC_LUT_DATA_B_FORMAT, 3); - - /* start from index 0 */ - DCP_REG_SET( - DCP0_DC_LUT_RW_INDEX, - DC_LUT_RW_INDEX, - 0); -} - -void dce120_ipp_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma) -{ - int i; - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* power on LUT memory */ - DCP_REG_SET(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1); - - dce120_helper_select_lut(ipp110); - - for (i = 0; i < INPUT_LUT_ENTRIES; i++) { - DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]); - DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]); - DCP_REG_SET(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]); - } - - /* power off LUT memory */ - DCP_REG_SET(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0); - - /* bypass prescale, enable legacy LUT */ - DCP_REG_UPDATE(DCP0_PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); - DCP_REG_UPDATE(DCP0_INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index f677a77ca6e0..207d07b29e81 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -40,7 +40,7 @@ #include "dce/dce_opp.h" #include "dce/dce_clock_source.h" #include "dce/dce_clocks.h" -#include "dce120_ipp.h" +#include "dce/dce_ipp.h" #include "dce110/dce110_mem_input.h" #include "dce120/dce120_mem_input.h" @@ -174,6 +174,28 @@ static const struct dce_abm_mask abm_mask = { ABM_MASK_SH_LIST_DCE110(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_COMMON_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -354,27 +376,6 @@ struct output_pixel_processor *dce120_opp_create( return NULL; } -static const struct dce110_ipp_reg_offsets dce120_ipp_reg_offsets[] = { - { - .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL), - }, - { - .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL), - } -}; - static const struct dce110_mem_input_reg_offsets dce120_mi_reg_offsets[] = { { .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), @@ -498,7 +499,7 @@ static struct timing_generator *dce120_timing_generator_create( static void dce120_ipp_destroy(struct input_pixel_processor **ipp) { - dm_free(TO_DCE110_IPP(*ipp)); + dm_free(TO_DCE_IPP(*ipp)); *ipp = NULL; } @@ -622,21 +623,18 @@ struct link_encoder *dce120_link_encoder_create( } static struct input_pixel_processor *dce120_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) + struct dc_context *ctx, uint32_t inst) { - struct dce110_ipp *ipp = dm_alloc(sizeof(struct dce110_ipp)); + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); - if (!ipp) + if (!ipp) { + BREAK_TO_DEBUGGER(); return NULL; + } - if (dce120_ipp_construct(ipp, ctx, inst, offset)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; } static struct stream_encoder *dce120_stream_encoder_create( @@ -1025,8 +1023,7 @@ static bool construct( goto controller_create_fail; } - pool->base.ipps[i] = dce120_ipp_create(ctx, i, - &dce120_ipp_reg_offsets[i]); + pool->base.ipps[i] = dce120_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index dfe590198a33..907e0a9a8474 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -26,6 +26,9 @@ #ifndef __DAL_HW_SHARED_H__ #define __DAL_HW_SHARED_H__ +#include "os_types.h" +#include "fixed31_32.h" + /****************************************************************************** * Data types shared between different Virtual HW blocks ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 7928e230eefb..2f3dc2e7f17a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2017 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,6 +27,7 @@ #define __DAL_IPP_H__ #include "hw_shared.h" +#include "dc_hw_types.h" #define MAXTRIX_COEFFICIENTS_NUMBER 12 #define MAXTRIX_COEFFICIENTS_WRAP_NUMBER (MAXTRIX_COEFFICIENTS_NUMBER + 4) @@ -113,7 +114,7 @@ struct ipp_funcs { const struct dc_gamma *gamma); /*** DEGAMMA RELATED ***/ - bool (*ipp_set_degamma)( + void (*ipp_set_degamma)( struct input_pixel_processor *ipp, enum ipp_degamma_mode mode); -- GitLab From e6303950ea7221e49cabb240383fa4e2bd035b0c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 24 Apr 2017 16:30:58 -0400 Subject: [PATCH 0410/2898] drm/amd/display: dce80, 100, 110 and 112 to dce ipp refactor Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 12 +- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h | 24 +- .../amd/display/dc/dce100/dce100_resource.c | 73 +++-- .../gpu/drm/amd/display/dc/dce110/Makefile | 4 +- .../drm/amd/display/dc/dce110/dce110_ipp.c | 63 ----- .../drm/amd/display/dc/dce110/dce110_ipp.h | 74 ------ .../amd/display/dc/dce110/dce110_ipp_cursor.c | 249 ------------------ .../amd/display/dc/dce110/dce110_ipp_gamma.c | 159 ----------- .../amd/display/dc/dce110/dce110_resource.c | 70 +++-- .../amd/display/dc/dce112/dce112_resource.c | 81 +++--- .../amd/display/dc/dce120/dce120_resource.c | 14 +- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_ipp.c | 65 ----- .../gpu/drm/amd/display/dc/dce80/dce80_ipp.h | 45 ---- .../drm/amd/display/dc/dce80/dce80_resource.c | 84 +++--- 15 files changed, 171 insertions(+), 848 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index d6bf6067a309..9e8f0a3593a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -174,7 +174,8 @@ static void dce_ipp_program_input_lut( struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); /* power on LUT memory */ - REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 1); + if (REG(DCFE_MEM_PWR_CTRL)) + REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 1); /* enable all */ REG_SET(DC_LUT_WRITE_EN_MASK, 0, DC_LUT_WRITE_EN_MASK, 0x7); @@ -199,7 +200,8 @@ static void dce_ipp_program_input_lut( } /* power off LUT memory */ - REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 0); + if (REG(DCFE_MEM_PWR_CTRL)) + REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 0); /* bypass prescale, enable legacy LUT */ REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); @@ -250,3 +252,9 @@ void dce_ipp_construct( ipp_dce->ipp_shift = ipp_shift; ipp_dce->ipp_mask = ipp_mask; } + +void dce_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCE_IPP(*ipp)); + *ipp = NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h index 23f25b1b0e64..ca04e97d44c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h @@ -23,8 +23,8 @@ * */ -#ifndef _DCE_DCE_IPP_H_ -#define _DCE_DCE_IPP_H_ +#ifndef _DCE_IPP_H_ +#define _DCE_IPP_H_ #include "ipp.h" @@ -46,7 +46,6 @@ SRI(PRESCALE_VALUES_GRPH_G, DCP, id), \ SRI(PRESCALE_VALUES_GRPH_B, DCP, id), \ SRI(INPUT_GAMMA_CONTROL, DCP, id), \ - SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ SRI(DC_LUT_WRITE_EN_MASK, DCP, id), \ SRI(DC_LUT_RW_MODE, DCP, id), \ SRI(DC_LUT_CONTROL, DCP, id), \ @@ -54,6 +53,14 @@ SRI(DC_LUT_SEQ_COLOR, DCP, id), \ SRI(DEGAMMA_CONTROL, DCP, id) +#define IPP_DCE100_REG_LIST_DCE_BASE(id) \ + IPP_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, CRTC, id) + +#define IPP_DCE110_REG_LIST_DCE_BASE(id) \ + IPP_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_PWR_CTRL, DCFE, id) + #define IPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -85,7 +92,6 @@ IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \ IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \ IPP_SF(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \ - IPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh), \ IPP_SF(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \ IPP_SF(DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \ IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \ @@ -97,7 +103,11 @@ IPP_SF(DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \ IPP_SF(DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh) -#define IPP_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ +#define IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + IPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh) + +#define IPP_DCE120_MASK_SH_LIST_SOC_BASE(mask_sh) \ IPP_SF(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \ IPP_SF(DCP0_CUR_CONTROL, CURSOR_EN, mask_sh), \ IPP_SF(DCP0_CUR_CONTROL, CURSOR_MODE, mask_sh), \ @@ -223,4 +233,6 @@ void dce_ipp_construct(struct dce_ipp *ipp_dce, const struct dce_ipp_shift *ipp_shift, const struct dce_ipp_mask *ipp_mask); -#endif /* _DCE_DCE_IPP_H_ */ +void dce_ipp_destroy(struct input_pixel_processor **ipp); + +#endif /* _DCE_IPP_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9b365597cec5..f65b785220e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -37,7 +37,7 @@ #include "dce/dce_stream_encoder.h" #include "dce110/dce110_mem_input.h" #include "dce110/dce110_mem_input_v.h" -#include "dce110/dce110_ipp.h" +#include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce/dce_opp.h" #include "dce/dce_clocks.h" @@ -168,30 +168,6 @@ static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = { } }; - -static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = { -{ - .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), -} -}; - - - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -213,6 +189,28 @@ static const struct dce_disp_clk_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE100_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE100(id)\ @@ -563,22 +561,18 @@ static struct transform *dce100_transform_create( } static struct input_pixel_processor *dce100_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offsets) + struct dc_context *ctx, uint32_t inst) { - struct dce110_ipp *ipp = - dm_alloc(sizeof(struct dce110_ipp)); + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); - if (!ipp) + if (!ipp) { + BREAK_TO_DEBUGGER(); return NULL; + } - if (dce110_ipp_construct(ipp, ctx, inst, offsets)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; } static const struct encoder_feature_support link_enc_feature = { @@ -674,7 +668,7 @@ static void destruct(struct dce110_resource_pool *pool) dce100_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce110_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); @@ -1005,8 +999,7 @@ static bool construct( goto res_create_fail; } - pool->base.ipps[i] = dce100_ipp_create(ctx, i, - &dce100_ipp_reg_offsets[i]); + pool->base.ipps[i] = dce100_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile index 9c42afcac325..c54bf0330701 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -2,9 +2,7 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ -dce110_ipp_gamma.o \ -dce110_timing_generator.o \ +DCE110 = dce110_timing_generator.o \ dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ dce110_resource.o \ dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c deleted file mode 100644 index 86fa7657a756..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_ipp.h" - -static const struct ipp_funcs funcs = { - .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, - .ipp_cursor_set_position = dce110_ipp_cursor_set_position, - .ipp_program_prescale = dce110_ipp_program_prescale, - .ipp_program_input_lut = dce110_ipp_program_input_lut, - .ipp_set_degamma = dce110_ipp_set_degamma, -}; - -bool dce110_ipp_construct( - struct dce110_ipp* ipp, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) -{ - ipp->base.ctx = ctx; - - ipp->base.inst = inst; - - ipp->offsets = *offset; - - ipp->base.funcs = &funcs; - - return true; -} - -void dce110_ipp_destroy(struct input_pixel_processor **ipp) -{ - dm_free(TO_DCE110_IPP(*ipp)); - *ipp = NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h deleted file mode 100644 index 8684e6a0ef4b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_IPP_DCE110_H__ -#define __DC_IPP_DCE110_H__ - -#include "ipp.h" - -#define TO_DCE110_IPP(input_pixel_processor)\ - container_of(input_pixel_processor, struct dce110_ipp, base) - -struct dce110_ipp_reg_offsets { - uint32_t dcp_offset; -}; - -struct dce110_ipp { - struct input_pixel_processor base; - struct dce110_ipp_reg_offsets offsets; -}; - -bool dce110_ipp_construct( - struct dce110_ipp* ipp, - struct dc_context *ctx, - enum controller_id id, - const struct dce110_ipp_reg_offsets *offset); - -void dce110_ipp_destroy(struct input_pixel_processor **ipp); - -/* CURSOR RELATED */ -void dce110_ipp_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *position, - const struct dc_cursor_mi_param *param); - -void dce110_ipp_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attributes); - -/* DEGAMMA RELATED */ -void dce110_ipp_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode); - -void dce110_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params); - -void dce110_ipp_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma); - -#endif /*__DC_IPP_DCE110_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c deleted file mode 100644 index f712916563b9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_cursor.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_ipp.h" - -#define CURSOR_COLOR_BLACK 0x00000000 -#define CURSOR_COLOR_WHITE 0xFFFFFFFF - -#define DCP_REG(reg)\ - (reg + ipp110->offsets.dcp_offset) - -static void enable( - struct dce110_ipp *ipp110, - bool enable); - -static void lock( - struct dce110_ipp *ipp110, - bool enable); - -static void program_position( - struct dce110_ipp *ipp110, - uint32_t x, - uint32_t y); - -static bool program_control( - struct dce110_ipp *ipp110, - enum dc_cursor_color_format color_format, - bool enable_magnification, - bool inverse_transparent_clamping); - -static void program_hotspot( - struct dce110_ipp *ipp110, - uint32_t x, - uint32_t y); - -static void program_size( - struct dce110_ipp *ipp110, - uint32_t width, - uint32_t height); - -static void program_address( - struct dce110_ipp *ipp110, - PHYSICAL_ADDRESS_LOC address); - -void dce110_ipp_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *position, - const struct dc_cursor_mi_param *param) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* lock cursor registers */ - lock(ipp110, true); - - /* Flag passed in structure differentiates cursor enable/disable. */ - /* Update if it differs from cached state. */ - enable(ipp110, position->enable); - - program_position(ipp110, position->x, position->y); - - program_hotspot( - ipp110, - position->x_hotspot, - position->y_hotspot); - - /* unlock cursor registers */ - lock(ipp110, false); -} - -void dce110_ipp_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attributes) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - /* Lock cursor registers */ - lock(ipp110, true); - - /* Program cursor control */ - program_control( - ipp110, - attributes->color_format, - attributes->attribute_flags.bits.ENABLE_MAGNIFICATION, - attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING); - - - /* - * Program cursor size -- NOTE: HW spec specifies that HW register - * stores size as (height - 1, width - 1) - */ - program_size(ipp110, attributes->width-1, attributes->height-1); - - /* Program cursor surface address */ - program_address(ipp110, attributes->address); - - /* Unlock Cursor registers. */ - lock(ipp110, false); -} - -static void enable( - struct dce110_ipp *ipp110, bool enable) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_CONTROL); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, enable, CUR_CONTROL, CURSOR_EN); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static void lock( - struct dce110_ipp *ipp110, bool lock) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_UPDATE); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, lock, CUR_UPDATE, CURSOR_UPDATE_LOCK); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static void program_position( - struct dce110_ipp *ipp110, - uint32_t x, - uint32_t y) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_POSITION); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, x, CUR_POSITION, CURSOR_X_POSITION); - set_reg_field_value(value, y, CUR_POSITION, CURSOR_Y_POSITION); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static bool program_control( - struct dce110_ipp *ipp110, - enum dc_cursor_color_format color_format, - bool enable_magnification, - bool inverse_transparent_clamping) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_CONTROL); - uint32_t mode = 0; - - switch (color_format) { - case CURSOR_MODE_MONO: - mode = 0; - break; - case CURSOR_MODE_COLOR_1BIT_AND: - mode = 1; - break; - case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: - mode = 2; - break; - case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: - mode = 3; - break; - default: - return false; - } - - set_reg_field_value(value, mode, CUR_CONTROL, CURSOR_MODE); - set_reg_field_value(value, enable_magnification, - CUR_CONTROL, CURSOR_2X_MAGNIFY); - set_reg_field_value(value, inverse_transparent_clamping, - CUR_CONTROL, CUR_INV_TRANS_CLAMP); - dm_write_reg(ipp110->base.ctx, addr, value); - - if (color_format == CURSOR_MODE_MONO) { - addr = DCP_REG(mmCUR_COLOR1); - dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_BLACK); - addr = DCP_REG(mmCUR_COLOR2); - dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_WHITE); - } - return true; -} - -static void program_hotspot( - struct dce110_ipp *ipp110, - uint32_t x, - uint32_t y) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_HOT_SPOT); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, x, CUR_HOT_SPOT, CURSOR_HOT_SPOT_X); - set_reg_field_value(value, y, CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static void program_size( - struct dce110_ipp *ipp110, - uint32_t width, - uint32_t height) -{ - uint32_t value = 0; - uint32_t addr = DCP_REG(mmCUR_SIZE); - - value = dm_read_reg(ipp110->base.ctx, addr); - set_reg_field_value(value, width, CUR_SIZE, CURSOR_WIDTH); - set_reg_field_value(value, height, CUR_SIZE, CURSOR_HEIGHT); - dm_write_reg(ipp110->base.ctx, addr, value); -} - -static void program_address( - struct dce110_ipp *ipp110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t addr = DCP_REG(mmCUR_SURFACE_ADDRESS_HIGH); - /* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor - * surface base address in byte. It is 4K byte aligned. - * The correct way to program cursor surface address is to first write - * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS */ - - dm_write_reg(ipp110->base.ctx, addr, address.high_part); - - addr = DCP_REG(mmCUR_SURFACE_ADDRESS); - dm_write_reg(ipp110->base.ctx, addr, address.low_part); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c deleted file mode 100644 index 0bcd8a68d5e5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" -#include "include/fixed31_32.h" -#include "basics/conversion.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "dce110_ipp.h" - -#define DCP_REG(reg)\ - (mm##reg + ipp110->offsets.dcp_offset) - -#define DCP_REG_SET_N(reg_name, n, ...) \ - generic_reg_update_ex(ipp110->base.ctx, \ - DCP_REG(reg_name), \ - 0, n, __VA_ARGS__) - -#define DCP_REG_SET(reg, field1, val1) \ - DCP_REG_SET_N(reg, 1, FD(reg##__##field1), val1) - -#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ - DCP_REG_SET_N(reg, 2, \ - FD(reg##__##field1), val1, \ - FD(reg##__##field2), val2) - -#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_SET_N(reg, 3, \ - FD(reg##__##field1), val1, \ - FD(reg##__##field2), val2, \ - FD(reg##__##field3), val3) - -#define DCP_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_ex(ipp110->base.ctx, \ - DCP_REG(reg_name), \ - dm_read_reg(ipp110->base.ctx, DCP_REG(reg_name)), \ - n, __VA_ARGS__) - -#define DCP_REG_UPDATE(reg, field, val) \ - DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - - - -void dce110_ipp_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; - - ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || - mode == IPP_DEGAMMA_MODE_HW_sRGB); - - DCP_REG_SET_3( - DEGAMMA_CONTROL, - GRPH_DEGAMMA_MODE, degamma_type, - CURSOR_DEGAMMA_MODE, degamma_type, - CURSOR2_DEGAMMA_MODE, degamma_type); -} - -void dce110_ipp_program_prescale( - struct input_pixel_processor *ipp, - struct ipp_prescale_params *params) -{ - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - /* set to bypass mode first before change */ - DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, - GRPH_PRESCALE_BYPASS, 1); - - DCP_REG_SET_2(PRESCALE_VALUES_GRPH_R, - GRPH_PRESCALE_SCALE_R, params->scale, - GRPH_PRESCALE_BIAS_R, params->bias); - - DCP_REG_SET_2(PRESCALE_VALUES_GRPH_G, - GRPH_PRESCALE_SCALE_G, params->scale, - GRPH_PRESCALE_BIAS_G, params->bias); - - DCP_REG_SET_2(PRESCALE_VALUES_GRPH_B, - GRPH_PRESCALE_SCALE_B, params->scale, - GRPH_PRESCALE_BIAS_B, params->bias); - - if (params->mode != IPP_PRESCALE_MODE_BYPASS) { - /* If prescale is in use, then legacy lut should be bypassed */ - DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 0); - DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 1); - } -} - -static void dce110_helper_select_lut(struct dce110_ipp *ipp110) -{ - /* enable all */ - DCP_REG_SET(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, 0x7); - - /* 256 entry mode */ - DCP_REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0); - - /* LUT-256, unsigned, integer, new u0.12 format */ - DCP_REG_SET_3(DC_LUT_CONTROL, - DC_LUT_DATA_R_FORMAT, 3, - DC_LUT_DATA_G_FORMAT, 3, - DC_LUT_DATA_B_FORMAT, 3); - - /* start from index 0 */ - DCP_REG_SET(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, 0); -} - -void dce110_ipp_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma) -{ - int i; - struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); - - dce110_helper_select_lut(ipp110); - - /* power on LUT memory and give it time to settle */ - DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1); - udelay(10); - - for (i = 0; i < INPUT_LUT_ENTRIES; i++) { - DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]); - DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]); - DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]); - } - - /* power off LUT memory */ - DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0); - - /* bypass prescale, enable legacy LUT */ - DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1); - DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0); -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index b4ab438e1c97..8dec9a5602a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -40,7 +40,7 @@ #include "dce/dce_stream_encoder.h" #include "dce110/dce110_mem_input.h" #include "dce110/dce110_mem_input_v.h" -#include "dce110/dce110_ipp.h" +#include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce110/dce110_transform_v.h" #include "dce/dce_opp.h" @@ -157,31 +157,6 @@ static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = { } }; - -static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = { -{ - .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), -} -}; - - - - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -226,6 +201,25 @@ static const struct dce_abm_mask abm_mask = { ABM_MASK_SH_LIST_DCE110(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -578,22 +572,18 @@ static struct transform *dce110_transform_create( } static struct input_pixel_processor *dce110_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offsets) + struct dc_context *ctx, uint32_t inst) { - struct dce110_ipp *ipp = - dm_alloc(sizeof(struct dce110_ipp)); + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); - if (!ipp) + if (!ipp) { + BREAK_TO_DEBUGGER(); return NULL; + } - if (dce110_ipp_construct(ipp, ctx, inst, offsets)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; } static const struct encoder_feature_support link_enc_feature = { @@ -705,7 +695,7 @@ static void destruct(struct dce110_resource_pool *pool) dce110_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce110_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); @@ -1414,7 +1404,7 @@ static bool construct( goto res_create_fail; } - pool->base.ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]); + pool->base.ipps[i] = dce110_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 0a1ad2808129..4bf75afd5721 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -40,7 +40,7 @@ #include "dce/dce_stream_encoder.h" #include "dce/dce_audio.h" #include "dce/dce_opp.h" -#include "dce110/dce110_ipp.h" +#include "dce/dce_ipp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" @@ -177,28 +177,6 @@ static const struct dce110_mem_input_reg_offsets dce112_mi_reg_offsets[] = { } }; -static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { -{ - .dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL), -} -}; - - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -244,6 +222,28 @@ static const struct dce_abm_mask abm_mask = { ABM_MASK_SH_LIST_DCE110(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE110(id)\ @@ -627,29 +627,19 @@ struct link_encoder *dce112_link_encoder_create( return NULL; } -struct input_pixel_processor *dce112_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) +static struct input_pixel_processor *dce112_ipp_create( + struct dc_context *ctx, uint32_t inst) { - struct dce110_ipp *ipp = - dm_alloc(sizeof(struct dce110_ipp)); + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); - if (!ipp) + if (!ipp) { + BREAK_TO_DEBUGGER(); return NULL; + } - if (dce110_ipp_construct(ipp, ctx, inst, offset)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; -} - -void dce112_ipp_destroy(struct input_pixel_processor **ipp) -{ - dm_free(TO_DCE110_IPP(*ipp)); - *ipp = NULL; + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; } struct output_pixel_processor *dce112_opp_create( @@ -712,7 +702,7 @@ static void destruct(struct dce110_resource_pool *pool) dce112_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce112_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); @@ -1370,10 +1360,7 @@ static bool construct( goto res_create_fail; } - pool->base.ipps[i] = dce112_ipp_create( - ctx, - i, - &ipp_reg_offsets[i]); + pool->base.ipps[i] = dce112_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 207d07b29e81..b6bdd1d52922 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -176,7 +176,7 @@ static const struct dce_abm_mask abm_mask = { #define ipp_regs(id)\ [id] = {\ - IPP_COMMON_REG_LIST_DCE_BASE(id)\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ } static const struct dce_ipp_registers ipp_regs[] = { @@ -189,11 +189,11 @@ static const struct dce_ipp_registers ipp_regs[] = { }; static const struct dce_ipp_shift ipp_shift = { - IPP_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) + IPP_DCE120_MASK_SH_LIST_SOC_BASE(__SHIFT) }; static const struct dce_ipp_mask ipp_mask = { - IPP_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) + IPP_DCE120_MASK_SH_LIST_SOC_BASE(_MASK) }; #define transform_regs(id)\ @@ -497,12 +497,6 @@ static struct timing_generator *dce120_timing_generator_create( return NULL; } -static void dce120_ipp_destroy(struct input_pixel_processor **ipp) -{ - dm_free(TO_DCE_IPP(*ipp)); - *ipp = NULL; -} - static void dce120_transform_destroy(struct transform **xfm) { dm_free(TO_DCE_TRANSFORM(*xfm)); @@ -521,7 +515,7 @@ static void destruct(struct dce110_resource_pool *pool) dce120_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce120_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 8d2c3dbfced1..1d54d5fa0fd2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -2,7 +2,7 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE80 = dce80_ipp.o dce80_timing_generator.o \ +DCE80 = dce80_timing_generator.o \ dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ dce80_resource.o diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c deleted file mode 100644 index c195acb6e1a6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/logger_interface.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dce80_ipp.h" - -#include "dce110/dce110_ipp.h" - -static const struct ipp_funcs funcs = { - .ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes, - .ipp_cursor_set_position = dce110_ipp_cursor_set_position, - .ipp_program_prescale = dce110_ipp_program_prescale, - .ipp_program_input_lut = dce110_ipp_program_input_lut, - .ipp_set_degamma = dce110_ipp_set_degamma, -}; - -bool dce80_ipp_construct( - struct dce110_ipp *ipp, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) -{ - ipp->base.ctx = ctx; - - ipp->base.inst = inst; - - ipp->offsets = *offset; - - ipp->base.funcs = &funcs; - - return true; -} - -void dce80_ipp_destroy(struct input_pixel_processor **ipp) -{ - dm_free(TO_DCE80_IPP(*ipp)); - *ipp = NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h deleted file mode 100644 index 06e8598d395f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_IPP_DCE80_H__ -#define __DC_IPP_DCE80_H__ - -#include "ipp.h" - -#define TO_DCE80_IPP(input_pixel_processor)\ - container_of(input_pixel_processor, struct dce110_ipp, base) - -struct dce110_ipp; -struct dce110_ipp_reg_offsets; - -bool dce80_ipp_construct( - struct dce110_ipp *ipp, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset); - -void dce80_ipp_destroy(struct input_pixel_processor **ipp); - -#endif /*__DC_IPP_DCE80_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index ab8cee3e734e..d49092986d54 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -41,10 +41,9 @@ #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" #include "dce80/dce80_mem_input.h" -#include "dce80/dce80_ipp.h" +#include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce/dce_opp.h" -#include "dce110/dce110_ipp.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" @@ -187,27 +186,6 @@ static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets[] = { } }; -static const struct dce110_ipp_reg_offsets ipp_reg_offsets[] = { -{ - .dcp_offset = (mmDCP0_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP1_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP2_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP3_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP4_CUR_CONTROL - mmDCP0_CUR_CONTROL), -}, -{ - .dcp_offset = (mmDCP5_CUR_CONTROL - mmDCP0_CUR_CONTROL), -} -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -229,6 +207,28 @@ static const struct dce_disp_clk_mask disp_clk_mask = { CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; +#define ipp_regs(id)\ +[id] = {\ + IPP_COMMON_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + #define transform_regs(id)\ [id] = {\ XFM_COMMON_REG_LIST_DCE_BASE(id)\ @@ -592,25 +592,6 @@ static struct transform *dce80_transform_create( return NULL; } -static struct input_pixel_processor *dce80_ipp_create( - struct dc_context *ctx, - uint32_t inst, - const struct dce110_ipp_reg_offsets *offset) -{ - struct dce110_ipp *ipp = - dm_alloc(sizeof(struct dce110_ipp)); - - if (!ipp) - return NULL; - - if (dce80_ipp_construct(ipp, ctx, inst, offset)) - return &ipp->base; - - BREAK_TO_DEBUGGER(); - dm_free(ipp); - return NULL; -} - static const struct encoder_feature_support link_enc_feature = { .max_hdmi_deep_color = COLOR_DEPTH_121212, .max_hdmi_pixel_clock = 297000, @@ -673,6 +654,21 @@ void dce80_clock_source_destroy(struct clock_source **clk_src) *clk_src = NULL; } +static struct input_pixel_processor *dce80_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + static void destruct(struct dce110_resource_pool *pool) { unsigned int i; @@ -685,7 +681,7 @@ static void destruct(struct dce110_resource_pool *pool) dce80_transform_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) - dce80_ipp_destroy(&pool->base.ipps[i]); + dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); @@ -1016,7 +1012,7 @@ static bool construct( goto res_create_fail; } - pool->base.ipps[i] = dce80_ipp_create(ctx, i, &ipp_reg_offsets[i]); + pool->base.ipps[i] = dce80_ipp_create(ctx, i); if (pool->base.ipps[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create input pixel processor!\n"); -- GitLab From 84f6739fc4d348440cd5684113260f728778312a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 24 Apr 2017 17:42:22 -0400 Subject: [PATCH 0411/2898] drm/amd/display: no need for return value from ipp_program_degamma_pwl Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 2f3dc2e7f17a..2d472d8ef555 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -118,7 +118,7 @@ struct ipp_funcs { struct input_pixel_processor *ipp, enum ipp_degamma_mode mode); - bool (*ipp_program_degamma_pwl)( + void (*ipp_program_degamma_pwl)( struct input_pixel_processor *ipp, const struct pwl_params *params); -- GitLab From 72ada5f76939ed00c07c584be7691a29d3c2c3da Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Tue, 18 Apr 2017 15:24:50 -0400 Subject: [PATCH 0412/2898] drm/amd/display: FreeSync Auto Sweep Support Implement core support to allow for FreeSync Auto Sweep to work Signed-off-by: Eric Cook Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 28 +++ .../gpu/drm/amd/display/dc/core/dc_debug.c | 5 +- drivers/gpu/drm/amd/display/dc/dc.h | 6 + .../display/dc/dce110/dce110_hw_sequencer.c | 13 + .../dc/dce110/dce110_timing_generator.c | 61 +++-- .../dc/dce110/dce110_timing_generator.h | 9 +- .../dc/dce110/dce110_timing_generator_v.c | 23 +- .../dc/dce120/dce120_timing_generator.c | 73 +++++- .../display/dc/dce80/dce80_timing_generator.c | 2 +- .../amd/display/dc/inc/hw/timing_generator.h | 10 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 + .../amd/display/modules/freesync/freesync.c | 227 ++++++++++++++---- .../amd/display/modules/inc/mod_freesync.h | 20 ++ 13 files changed, 357 insertions(+), 123 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 93c936d92f5a..2e74faef68e7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -175,6 +175,31 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, return ret; } +static bool stream_get_crtc_position(struct dc *dc, + const struct dc_stream **stream, int num_streams, + unsigned int *v_pos, unsigned int *nom_v_pos) +{ + /* TODO: Support multiple streams */ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + int i = 0; + bool ret = false; + struct crtc_position position; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe = + &core_dc->current_context->res_ctx.pipe_ctx[i]; + + if (pipe->stream == core_stream && pipe->stream_enc) { + core_dc->hwss.get_position(&pipe, 1, &position); + + *v_pos = position.vertical_count; + *nom_v_pos = position.nominal_vcount; + ret = true; + } + } + return ret; +} static bool set_gamut_remap(struct dc *dc, const struct dc_stream **stream, int num_streams) @@ -349,6 +374,9 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.set_static_screen_events = set_static_screen_events; + core_dc->public.stream_funcs.get_crtc_position = + stream_get_crtc_position; + core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index fb48b8909e7f..ee840e75ee1f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -287,6 +287,7 @@ void context_timing_trace( struct core_dc *core_dc = DC_TO_CORE(dc); struct dal_logger *logger = core_dc->ctx->logger; int h_pos[MAX_PIPES], v_pos[MAX_PIPES]; + struct crtc_position position; for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; @@ -294,7 +295,9 @@ void context_timing_trace( if (pipe_ctx->stream == NULL) continue; - pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos[i], &v_pos[i]); + pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &position); + h_pos[i] = position.horizontal_count; + v_pos[i] = position.vertical_count; } for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d12aa726164e..647c095e0ae9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -103,6 +103,12 @@ struct dc_stream_funcs { int num_streams, int vmin, int vmax); + bool (*get_crtc_position)(struct dc *dc, + const struct dc_stream **stream, + int num_streams, + unsigned int *v_pos, + unsigned int *nom_v_pos); + void (*stream_update_scaling)(const struct dc *dc, const struct dc_stream *dc_stream, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6a93c96b9b26..0e69aceb0bad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1362,6 +1362,18 @@ static void set_drr(struct pipe_ctx **pipe_ctx, } } +static void get_position(struct pipe_ctx **pipe_ctx, + int num_pipes, + struct crtc_position *position) +{ + int i = 0; + + /* TODO: handle pipes > 1 + */ + for (i = 0; i < num_pipes; i++) + pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position); +} + static void set_static_screen_control(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_events *events) { @@ -2486,6 +2498,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .pipe_control_lock = dce_pipe_control_lock, .set_bandwidth = dce110_set_bandwidth, .set_drr = set_drr, + .get_position = get_position, .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 23760727f000..ec599276ed2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -518,34 +518,38 @@ uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg) /** ***************************************************************************** - * Function: dce110_get_crtc_positions + * Function: dce110_timing_generator_get_position * * @brief * Returns CRTC vertical/horizontal counters * - * @param [out] v_position, h_position + * @param [out] position ***************************************************************************** */ - -void dce110_timing_generator_get_crtc_positions( - struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position) +void dce110_timing_generator_get_position(struct timing_generator *tg, + struct crtc_position *position) { uint32_t value; struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION)); - *h_position = get_reg_field_value( + position->horizontal_count = get_reg_field_value( value, CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); - *v_position = get_reg_field_value( + position->vertical_count = get_reg_field_value( value, CRTC_STATUS_POSITION, CRTC_VERT_COUNT); + + value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION)); + + position->nominal_vcount = get_reg_field_value( + value, + CRTC_NOM_VERT_POSITION, + CRTC_VERT_COUNT_NOM); } /** @@ -566,18 +570,23 @@ void dce110_timing_generator_get_crtc_scanoutpos( uint32_t *v_position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + struct crtc_position position; - uint32_t v_blank_start_end = dm_read_reg(tg->ctx, + uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_V_BLANK_START_END)); - *v_blank_start = get_reg_field_value(v_blank_start_end, + *v_blank_start = get_reg_field_value(value, CRTC_V_BLANK_START_END, CRTC_V_BLANK_START); - *v_blank_end = get_reg_field_value(v_blank_start_end, + *v_blank_end = get_reg_field_value(value, CRTC_V_BLANK_START_END, CRTC_V_BLANK_END); - dce110_timing_generator_get_crtc_positions(tg, h_position, v_position); + dce110_timing_generator_get_position( + tg, &position); + + *h_position = position.horizontal_count; + *v_position = position.vertical_count; } /* TODO: is it safe to assume that mask/shift of Primary and Underlay @@ -1344,15 +1353,13 @@ void dce110_timing_generator_tear_down_global_swap_lock( */ bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg) { - uint32_t h1 = 0; - uint32_t h2 = 0; - uint32_t v1 = 0; - uint32_t v2 = 0; + struct crtc_position position1, position2; - tg->funcs->get_position(tg, &h1, &v1); - tg->funcs->get_position(tg, &h2, &v2); + tg->funcs->get_position(tg, &position1); + tg->funcs->get_position(tg, &position2); - if (h1 == h2 && v1 == v2) + if (position1.horizontal_count == position2.horizontal_count && + position1.vertical_count == position2.vertical_count) return false; else return true; @@ -1750,18 +1757,6 @@ void dce110_tg_set_overscan_color(struct timing_generator *tg, dm_write_reg(ctx, addr, value); } -void dce110_tg_get_position(struct timing_generator *tg, - struct crtc_position *position) -{ - int32_t h_position; - int32_t v_position; - - dce110_timing_generator_get_crtc_positions(tg, &h_position, &v_position); - - position->horizontal_count = (uint32_t)h_position; - position->vertical_count = (uint32_t)v_position; -} - void dce110_tg_program_timing(struct timing_generator *tg, const struct dc_crtc_timing *timing, bool use_vbios) @@ -1895,7 +1890,7 @@ static const struct timing_generator_funcs dce110_tg_funcs = { .enable_crtc = dce110_timing_generator_enable_crtc, .disable_crtc = dce110_timing_generator_disable_crtc, .is_counter_moving = dce110_timing_generator_is_counter_moving, - .get_position = dce110_timing_generator_get_crtc_positions, + .get_position = dce110_timing_generator_get_position, .get_frame_count = dce110_timing_generator_get_vblank_counter, .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, .set_early_control = dce110_timing_generator_set_early_control, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index f14a4d91cd8e..a5d63c626ada 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -151,11 +151,9 @@ void dce110_timing_generator_set_early_control( uint32_t dce110_timing_generator_get_vblank_counter( struct timing_generator *tg); -/* Get current H and V position */ -void dce110_timing_generator_get_crtc_positions( +void dce110_timing_generator_get_position( struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position); + struct crtc_position *position); /* return true if TG counter is moving. false if TG is stopped */ bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg); @@ -251,9 +249,6 @@ void dce110_tg_program_blank_color(struct timing_generator *tg, void dce110_tg_set_overscan_color(struct timing_generator *tg, const struct tg_color *overscan_color); -void dce110_tg_get_position(struct timing_generator *tg, - struct crtc_position *position); - void dce110_tg_program_timing(struct timing_generator *tg, const struct dc_crtc_timing *timing, bool use_vbios); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index c95b69446ced..759c55bb4d15 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -570,24 +570,11 @@ static void dce110_timing_generator_v_set_early_control( dm_write_reg(tg->ctx, address, regval); } -static void dce110_timing_generator_v_get_crtc_positions( - struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position) +static void dce110_timing_generator_get_underlay_position(struct timing_generator *tg, + struct crtc_position *position) { - uint32_t value; - - value = dm_read_reg(tg->ctx, mmCRTCV_STATUS_POSITION); - - *h_position = get_reg_field_value( - value, - CRTCV_STATUS_POSITION, - CRTC_HORZ_COUNT); - - *v_position = get_reg_field_value( - value, - CRTCV_STATUS_POSITION, - CRTC_VERT_COUNT); + //Should never hit this case + ASSERT(false); } static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg) @@ -665,7 +652,7 @@ static const struct timing_generator_funcs dce110_tg_v_funcs = { .enable_crtc = dce110_timing_generator_v_enable_crtc, .disable_crtc = dce110_timing_generator_v_disable_crtc, .is_counter_moving = dce110_timing_generator_v_is_counter_moving, - .get_position = dce110_timing_generator_v_get_crtc_positions, + .get_position = dce110_timing_generator_get_underlay_position, .get_frame_count = dce110_timing_generator_v_get_vblank_counter, .set_early_control = dce110_timing_generator_v_set_early_control, .wait_for_state = dce110_timing_generator_v_wait_for_state, diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 1318df7ed47e..245356e72b36 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -180,10 +180,9 @@ uint32_t dce120_timing_generator_get_vblank_counter( } /* Get current H and V position */ -void dce120_timing_generator_get_crtc_positions( +void dce120_timing_generator_get_crtc_position( struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position) + struct crtc_position *position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t value = dm_read_reg_soc15( @@ -191,11 +190,19 @@ void dce120_timing_generator_get_crtc_positions( mmCRTC0_CRTC_STATUS_POSITION, tg110->offsets.crtc); - *h_position = get_reg_field_value( - value, CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); + position->horizontal_count = get_reg_field_value(value, + CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT); - *v_position = get_reg_field_value( - value, CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT); + position->vertical_count = get_reg_field_value(value, + CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_NOM_VERT_POSITION, + tg110->offsets.crtc); + + position->nominal_vcount = get_reg_field_value(value, + CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM); } /* wait until TG is in beginning of vertical blank region */ @@ -576,6 +583,49 @@ void dce120_timing_generator_set_drr( } } +/** + ***************************************************************************** + * Function: dce120_timing_generator_get_position + * + * @brief + * Returns CRTC vertical/horizontal counters + * + * @param [out] position + ***************************************************************************** + */ +void dce120_timing_generator_get_position(struct timing_generator *tg, + struct crtc_position *position) +{ + uint32_t value; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_STATUS_POSITION, + tg110->offsets.crtc); + + position->horizontal_count = get_reg_field_value( + value, + CRTC0_CRTC_STATUS_POSITION, + CRTC_HORZ_COUNT); + + position->vertical_count = get_reg_field_value( + value, + CRTC0_CRTC_STATUS_POSITION, + CRTC_VERT_COUNT); + + value = dm_read_reg_soc15( + tg->ctx, + mmCRTC0_CRTC_NOM_VERT_POSITION, + tg110->offsets.crtc); + + position->nominal_vcount = get_reg_field_value( + value, + CRTC0_CRTC_NOM_VERT_POSITION, + CRTC_VERT_COUNT_NOM); +} + + void dce120_timing_generator_get_crtc_scanoutpos( struct timing_generator *tg, uint32_t *v_blank_start, @@ -584,6 +634,7 @@ void dce120_timing_generator_get_crtc_scanoutpos( uint32_t *v_position) { struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + struct crtc_position position; uint32_t v_blank_start_end = dm_read_reg_soc15( tg->ctx, @@ -597,7 +648,11 @@ void dce120_timing_generator_get_crtc_scanoutpos( CRTC0_CRTC_V_BLANK_START_END, CRTC_V_BLANK_END); - dce120_timing_generator_get_crtc_positions(tg, h_position, v_position); + dce120_timing_generator_get_crtc_position( + tg, &position); + + *h_position = position.horizontal_count; + *v_position = position.vertical_count; } void dce120_timing_generator_enable_advanced_request( @@ -1076,7 +1131,7 @@ static struct timing_generator_funcs dce120_tg_funcs = { /* used by enable_timing_synchronization. Not need for FPGA */ .is_counter_moving = dce110_timing_generator_is_counter_moving, /* never be called */ - .get_position = dce120_timing_generator_get_crtc_positions, + .get_position = dce120_timing_generator_get_crtc_position, .get_frame_count = dce120_timing_generator_get_vblank_counter, .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos, .set_early_control = dce120_timing_generator_set_early_control, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index 1198f2fbf9c7..179a6d604838 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -121,7 +121,7 @@ static const struct timing_generator_funcs dce80_tg_funcs = { .enable_crtc = dce110_timing_generator_enable_crtc, .disable_crtc = dce110_timing_generator_disable_crtc, .is_counter_moving = dce110_timing_generator_is_counter_moving, - .get_position = dce110_timing_generator_get_crtc_positions, + .get_position = dce110_timing_generator_get_position, .get_frame_count = dce110_timing_generator_get_vblank_counter, .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, .set_early_control = dce110_timing_generator_set_early_control, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 235cfe8d1ad4..2c4a9d02b3c1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -30,9 +30,9 @@ struct dc_bios; /* Contains CRTC vertical/horizontal pixel counters */ struct crtc_position { - uint32_t vertical_count; - uint32_t horizontal_count; - uint32_t nominal_vcount; + int32_t vertical_count; + int32_t horizontal_count; + int32_t nominal_vcount; }; struct dcp_gsl_params { @@ -105,8 +105,8 @@ struct timing_generator_funcs { bool (*disable_crtc)(struct timing_generator *tg); bool (*is_counter_moving)(struct timing_generator *tg); void (*get_position)(struct timing_generator *tg, - int32_t *h_position, - int32_t *v_position); + struct crtc_position *position); + uint32_t (*get_frame_count)(struct timing_generator *tg); void (*get_scanoutpos)( struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index b42e4a0ef18a..afdb8605a30f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -131,6 +131,9 @@ struct hw_sequencer_funcs { void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax); + void (*get_position)(struct pipe_ctx **pipe_ctx, int num_pipes, + struct crtc_position *position); + void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_events *events); diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 78b4f28d862c..f6223e6b3536 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -76,6 +76,16 @@ struct fixed_refresh { bool program_fixed_refresh; }; +struct freesync_range { + unsigned int min_refresh; + unsigned int max_frame_duration; + unsigned int vmax; + + unsigned int max_refresh; + unsigned int min_frame_duration; + unsigned int vmin; +}; + struct freesync_state { bool fullscreen; bool static_screen; @@ -89,6 +99,7 @@ struct freesync_state { struct gradual_static_ramp static_ramp; struct below_the_range btr; struct fixed_refresh fixed_refresh; + struct freesync_range freesync_range; }; struct freesync_entity { @@ -342,8 +353,11 @@ static void update_stream(struct core_freesync *core_freesync, } } -static void calc_vmin_vmax(struct core_freesync *core_freesync, - const struct dc_stream *stream, int *vmin, int *vmax) +static void calc_freesync_range(struct core_freesync *core_freesync, + const struct dc_stream *stream, + struct freesync_state *state, + unsigned int min_refresh_in_uhz, + unsigned int max_refresh_in_uhz) { unsigned int min_frame_duration_in_ns = 0, max_frame_duration_in_ns = 0; unsigned int index = map_index_from_stream(core_freesync, stream); @@ -351,29 +365,50 @@ static void calc_vmin_vmax(struct core_freesync *core_freesync, min_frame_duration_in_ns = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), - core_freesync->map[index].state. - nominal_refresh_rate_in_micro_hz))); + max_refresh_in_uhz))); max_frame_duration_in_ns = ((unsigned int) (div64_u64( - (1000000000ULL * 1000000), - core_freesync->map[index].caps->min_refresh_in_micro_hz))); + (1000000000ULL * 1000000), + min_refresh_in_uhz))); + + state->freesync_range.min_refresh = min_refresh_in_uhz; + state->freesync_range.max_refresh = max_refresh_in_uhz; - *vmax = div64_u64(div64_u64(((unsigned long long)( - max_frame_duration_in_ns) * stream->timing.pix_clk_khz), - stream->timing.h_total), 1000000); - *vmin = div64_u64(div64_u64(((unsigned long long)( - min_frame_duration_in_ns) * stream->timing.pix_clk_khz), - stream->timing.h_total), 1000000); + state->freesync_range.max_frame_duration = max_frame_duration_in_ns; + state->freesync_range.min_frame_duration = min_frame_duration_in_ns; + + state->freesync_range.vmax = div64_u64(div64_u64(((unsigned long long)( + max_frame_duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); + state->freesync_range.vmin = div64_u64(div64_u64(((unsigned long long)( + min_frame_duration_in_ns) * stream->timing.pix_clk_khz), + stream->timing.h_total), 1000000); /* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */ - if (*vmin < vtotal) { + if (state->freesync_range.vmin < vtotal) { ASSERT(false); - *vmin = vtotal; + state->freesync_range.vmin = vtotal; } - if (*vmax < vtotal) { + if (state->freesync_range.vmax < vtotal) { ASSERT(false); - *vmax = vtotal; + state->freesync_range.vmax = vtotal; } + + /* Determine whether BTR can be supported */ + if (max_frame_duration_in_ns >= + 2 * min_frame_duration_in_ns) + core_freesync->map[index].caps->btr_supported = true; + else + core_freesync->map[index].caps->btr_supported = false; + + /* Cache the time variables */ + state->time.max_render_time_in_us = + max_frame_duration_in_ns / 1000; + state->time.min_render_time_in_us = + min_frame_duration_in_ns / 1000; + state->btr.mid_point_in_us = + (max_frame_duration_in_ns + + min_frame_duration_in_ns) / 2000; } static void calc_v_total_from_duration(const struct dc_stream *stream, @@ -518,9 +553,8 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync, state->fixed_refresh.fixed_refresh_active == false) { /* Enable freesync */ - calc_vmin_vmax(core_freesync, - streams[stream_idx], - &v_total_min, &v_total_max); + v_total_min = state->freesync_range.vmin; + v_total_max = state->freesync_range.vmax; /* Update the freesync context for the stream */ update_stream_freesync_context(core_freesync, @@ -696,7 +730,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, (1000000000ULL * 1000000), state->nominal_refresh_rate_in_micro_hz))); - calc_vmin_vmax(core_freesync, *streams, &vmin, &vmax); + vmin = state->freesync_range.vmin; inserted_frame_v_total = vmin; @@ -941,11 +975,120 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, return true; } +bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, + const struct dc_stream *streams, + unsigned int min_refresh, + unsigned int max_refresh) +{ + unsigned int index = 0; + struct core_freesync *core_freesync; + struct freesync_state *state; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, streams); + state = &core_freesync->map[index].state; + + if (min_refresh == 0 || max_refresh == 0) { + /* Restore defaults */ + calc_freesync_range(core_freesync, streams, state, + core_freesync->map[index].caps-> + min_refresh_in_micro_hz, + state->nominal_refresh_rate_in_micro_hz); + } else { + calc_freesync_range(core_freesync, streams, + state, + min_refresh, + max_refresh); + + /* Program vtotal min/max */ + core_freesync->dc->stream_funcs.adjust_vmin_vmax( + core_freesync->dc, &streams, 1, + state->freesync_range.vmin, + state->freesync_range.vmax); + } + + return true; +} + +bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *min_refresh, + unsigned int *max_refresh) +{ + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + + *min_refresh = + core_freesync->map[index].state.freesync_range.min_refresh; + *max_refresh = + core_freesync->map[index].state.freesync_range.max_refresh; + + return true; +} + +bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *vmin, + unsigned int *vmax) +{ + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + + *vmin = + core_freesync->map[index].state.freesync_range.vmin; + *vmax = + core_freesync->map[index].state.freesync_range.vmax; + + return true; +} + +bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *nom_v_pos, + unsigned int *v_pos) +{ + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; + struct crtc_position position; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + + if (core_freesync->dc->stream_funcs.get_crtc_position( + core_freesync->dc, &stream, 1, + &position.vertical_count, &position.nominal_vcount)) { + + *nom_v_pos = position.vertical_count; + *v_pos = position.nominal_vcount; + + return true; + } + + return false; +} + void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams) { unsigned int stream_index, map_index; - unsigned min_frame_duration_in_ns, max_frame_duration_in_ns; struct freesync_state *state; struct core_freesync *core_freesync = NULL; @@ -965,37 +1108,23 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, unsigned long long temp; temp = streams[stream_index]->timing.pix_clk_khz; temp *= 1000ULL * 1000ULL * 1000ULL; - temp = div_u64(temp, streams[stream_index]->timing.h_total); - temp = div_u64(temp, streams[stream_index]->timing.v_total); - state->nominal_refresh_rate_in_micro_hz = (unsigned int) temp; + temp = div_u64(temp, + streams[stream_index]->timing.h_total); + temp = div_u64(temp, + streams[stream_index]->timing.v_total); + state->nominal_refresh_rate_in_micro_hz = + (unsigned int) temp; /* Update the stream */ update_stream(core_freesync, streams[stream_index]); - /* Determine whether BTR can be supported */ - min_frame_duration_in_ns = ((unsigned int) (div64_u64( - (1000000000ULL * 1000000), - state->nominal_refresh_rate_in_micro_hz))); - - max_frame_duration_in_ns = ((unsigned int) (div64_u64( - (1000000000ULL * 1000000), - core_freesync->map[map_index].caps->min_refresh_in_micro_hz))); - - if (max_frame_duration_in_ns >= - 2 * min_frame_duration_in_ns) - core_freesync->map[map_index].caps->btr_supported = true; - else - core_freesync->map[map_index].caps->btr_supported = false; - - /* Cache the time variables */ - state->time.max_render_time_in_us = - max_frame_duration_in_ns / 1000; - state->time.min_render_time_in_us = - min_frame_duration_in_ns / 1000; - state->btr.mid_point_in_us = - (max_frame_duration_in_ns + - min_frame_duration_in_ns) / 2000; - + /* Calculate vmin/vmax and refresh rate for + * current mode + */ + calc_freesync_range(core_freesync, *streams, state, + core_freesync->map[stream_index].caps-> + min_refresh_in_micro_hz, + state->nominal_refresh_rate_in_micro_hz); } } @@ -1178,7 +1307,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, /* Fixed Refresh set to "active" so engage (fix to max) */ } else { - calc_vmin_vmax(core_freesync, stream, &vmin, &vmax); + vmin = state->freesync_range.vmin; vmax = vmin; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 783ff2ef3bee..3947cc412ad7 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -129,6 +129,26 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_user_enable *user_enable); +bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, + const struct dc_stream *streams, + unsigned int min_refresh, + unsigned int max_refresh); + +bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *min_refresh, + unsigned int *max_refresh); + +bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *vmin, + unsigned int *vmax); + +bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + unsigned int *nom_v_pos, + unsigned int *v_pos); + void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, const struct dc_stream **streams, int num_streams); -- GitLab From a2b8659db9b435853cb0dc78d225a492e7ee69d0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 22 Apr 2017 14:17:51 -0400 Subject: [PATCH 0413/2898] drm/amd/display: decouple resource_pool from resource_context to avoid null access in case res_ctx is used to access res_pool before it's fully constructed also make it clear which function has dependency on resource_pool Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 ++- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 143 ++++++++++-------- .../gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_surface.c | 3 +- .../display/dc/dce100/dce100_hw_sequencer.c | 4 +- .../amd/display/dc/dce100/dce100_resource.c | 8 +- .../display/dc/dce110/dce110_hw_sequencer.c | 42 ++--- .../amd/display/dc/dce110/dce110_resource.c | 25 ++- .../amd/display/dc/dce112/dce112_resource.c | 35 +++-- .../drm/amd/display/dc/dce80/dce80_resource.c | 8 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 15 +- 13 files changed, 161 insertions(+), 147 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2e74faef68e7..37986632f025 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -736,7 +736,7 @@ static void program_timing_sync( { int i, j; int group_index = 0; - int pipe_count = ctx->res_ctx.pool->pipe_count; + int pipe_count = core_dc->res_pool->pipe_count; struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; for (i = 0; i < pipe_count; i++) { @@ -939,7 +939,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) + for (i = 0; i < core_dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL) { context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( @@ -1015,7 +1015,7 @@ static bool is_surface_in_context( { int j; - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + for (j = 0; j < MAX_PIPES; j++) { const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (surface == &pipe_ctx->surface->public) { @@ -1245,7 +1245,8 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* add surface to context */ if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, dc_stream, context)) { + new_surfaces, surface_count, dc_stream, + context, core_dc->res_pool)) { BREAK_TO_DEBUGGER(); goto fail; } @@ -1304,7 +1305,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* not sure if we still need this */ if (update_type == UPDATE_TYPE_FULL) { - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (pipe_ctx->surface != surface) @@ -1365,7 +1366,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (pipe_ctx->surface != surface) @@ -1389,7 +1390,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, context_timing_trace(dc, &context->res_ctx); } - for (j = 0; j < context->res_ctx.pool->pipe_count; j++) { + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct pipe_ctx *cur_pipe_ctx; bool is_new_pipe_surface = true; @@ -1427,7 +1428,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, } /* Unlock pipes */ - for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) { + for (i = core_dc->res_pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; for (j = 0; j < surface_count; j++) { @@ -1571,8 +1572,6 @@ void dc_set_power_state( memset(core_dc->current_context, 0, sizeof(*core_dc->current_context)); - core_dc->current_context->res_ctx.pool = core_dc->res_pool; - break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index f883fdb820c8..4b9d3f12406f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2245,7 +2245,7 @@ static void set_crtc_test_pattern(struct core_link *link, case DP_TEST_PATTERN_VIDEO_MODE: { /* restore bitdepth reduction */ - link->dc->current_context->res_ctx.pool->funcs-> + link->dc->res_pool->funcs-> build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); pipe_ctx->stream->bit_depth_params = params; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index cdb98d5f7caa..43e5758719ca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -233,11 +233,12 @@ bool resource_construct( void resource_unreference_clock_source( struct resource_context *res_ctx, + const struct resource_pool *pool, struct clock_source **clock_source) { int i; - for (i = 0; i < res_ctx->pool->clk_src_count; i++) { - if (res_ctx->pool->clock_sources[i] != *clock_source) + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != *clock_source) continue; res_ctx->clock_source_ref_count[i]--; @@ -248,7 +249,7 @@ void resource_unreference_clock_source( break; } - if (res_ctx->pool->dp_clock_source == *clock_source) { + if (pool->dp_clock_source == *clock_source) { res_ctx->dp_clock_source_ref_count--; if (res_ctx->dp_clock_source_ref_count == 0) @@ -259,18 +260,19 @@ void resource_unreference_clock_source( void resource_reference_clock_source( struct resource_context *res_ctx, + const struct resource_pool *pool, struct clock_source *clock_source) { int i; - for (i = 0; i < res_ctx->pool->clk_src_count; i++) { - if (res_ctx->pool->clock_sources[i] != clock_source) + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != clock_source) continue; res_ctx->clock_source_ref_count[i]++; break; } - if (res_ctx->pool->dp_clock_source == clock_source) + if (pool->dp_clock_source == clock_source) res_ctx->dp_clock_source_ref_count++; } @@ -861,12 +863,13 @@ enum dc_status resource_build_scaling_params_for_context( static void detach_surfaces_for_stream( struct validate_context *context, + const struct resource_pool *pool, const struct dc_stream *dc_stream) { int i; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < pool->pipe_count; i++) { struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; if (cur_pipe->stream == stream) { cur_pipe->surface = NULL; @@ -876,7 +879,9 @@ static void detach_surfaces_for_stream( } } -struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx) +struct pipe_ctx *find_idle_secondary_pipe( + struct resource_context *res_ctx, + const struct resource_pool *pool) { int i; struct pipe_ctx *secondary_pipe = NULL; @@ -886,7 +891,7 @@ struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx) * assignment more consistent */ - for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + for (i = pool->pipe_count - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == NULL) { secondary_pipe = &res_ctx->pipe_ctx[i]; secondary_pipe->pipe_idx = i; @@ -903,7 +908,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( const struct core_stream *stream) { int i; - for (i = 0; i < res_ctx->pool->pipe_count; i++) { + for (i = 0; i < MAX_PIPES; i++) { if (res_ctx->pipe_ctx[i].stream == stream && res_ctx->pipe_ctx[i].stream_enc) { return &res_ctx->pipe_ctx[i]; @@ -919,6 +924,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( */ static struct pipe_ctx *acquire_free_pipe_for_stream( struct validate_context *context, + const struct resource_pool *pool, const struct dc_stream *dc_stream) { int i; @@ -938,7 +944,7 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( return head_pipe; /* Re-use pipe already acquired for this stream if available*/ - for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + for (i = pool->pipe_count - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == stream && !res_ctx->pipe_ctx[i].surface) { return &res_ctx->pipe_ctx[i]; @@ -950,10 +956,10 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( * to acquire an idle one to satisfy the request */ - if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer) + if (!pool->funcs->acquire_idle_pipe_for_layer) return NULL; - return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(context, stream); + return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream); } @@ -964,7 +970,7 @@ static void release_free_pipes_for_stream( int i; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) { + for (i = MAX_PIPES - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == stream && !res_ctx->pipe_ctx[i].surface) { res_ctx->pipe_ctx[i].stream = NULL; @@ -976,7 +982,8 @@ bool resource_attach_surfaces_to_context( const struct dc_surface * const *surfaces, int surface_count, const struct dc_stream *dc_stream, - struct validate_context *context) + struct validate_context *context, + const struct resource_pool *pool) { int i; struct pipe_ctx *tail_pipe; @@ -1003,7 +1010,7 @@ bool resource_attach_surfaces_to_context( for (i = 0; i < surface_count; i++) dc_surface_retain(surfaces[i]); - detach_surfaces_for_stream(context, dc_stream); + detach_surfaces_for_stream(context, pool, dc_stream); /* release existing surfaces*/ for (i = 0; i < stream_status->surface_count; i++) @@ -1020,7 +1027,8 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); - struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(context, dc_stream); + struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( + context, pool, dc_stream); if (!free_pipe) { stream_status->surfaces[i] = NULL; @@ -1101,7 +1109,8 @@ bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, const struct validate_context *old_context, - struct validate_context *context) + struct validate_context *context, + const struct resource_pool *pool) { int i, j; @@ -1114,7 +1123,7 @@ bool resource_validate_attach_surfaces( old_context->stream_status[j].surfaces, old_context->stream_status[j].surface_count, &context->streams[i]->public, - context)) + context, pool)) return false; context->stream_status[i] = old_context->stream_status[j]; } @@ -1123,7 +1132,7 @@ bool resource_validate_attach_surfaces( set[i].surfaces, set[i].surface_count, &context->streams[i]->public, - context)) + context, pool)) return false; } @@ -1136,12 +1145,13 @@ bool resource_validate_attach_surfaces( static void set_stream_engine_in_use( struct resource_context *res_ctx, + const struct resource_pool *pool, struct stream_encoder *stream_enc) { int i; - for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { - if (res_ctx->pool->stream_enc[i] == stream_enc) + for (i = 0; i < pool->stream_enc_count; i++) { + if (pool->stream_enc[i] == stream_enc) res_ctx->is_stream_enc_acquired[i] = true; } } @@ -1149,32 +1159,33 @@ static void set_stream_engine_in_use( /* TODO: release audio object */ static void set_audio_in_use( struct resource_context *res_ctx, + const struct resource_pool *pool, struct audio *audio) { int i; - for (i = 0; i < res_ctx->pool->audio_count; i++) { - if (res_ctx->pool->audios[i] == audio) { + for (i = 0; i < pool->audio_count; i++) { + if (pool->audios[i] == audio) res_ctx->is_audio_acquired[i] = true; - } } } static int acquire_first_free_pipe( struct resource_context *res_ctx, + const struct resource_pool *pool, struct core_stream *stream) { int i; - for (i = 0; i < res_ctx->pool->pipe_count; i++) { + for (i = 0; i < pool->pipe_count; i++) { if (!res_ctx->pipe_ctx[i].stream) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - pipe_ctx->tg = res_ctx->pool->timing_generators[i]; - pipe_ctx->mi = res_ctx->pool->mis[i]; - pipe_ctx->ipp = res_ctx->pool->ipps[i]; - pipe_ctx->xfm = res_ctx->pool->transforms[i]; - pipe_ctx->opp = res_ctx->pool->opps[i]; - pipe_ctx->dis_clk = res_ctx->pool->display_clock; + pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->mi = pool->mis[i]; + pipe_ctx->ipp = pool->ipps[i]; + pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->opp = pool->opps[i]; + pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; pipe_ctx->stream = stream; @@ -1186,21 +1197,22 @@ static int acquire_first_free_pipe( static struct stream_encoder *find_first_free_match_stream_enc_for_link( struct resource_context *res_ctx, + const struct resource_pool *pool, struct core_stream *stream) { int i; int j = -1; struct core_link *link = stream->sink->link; - for (i = 0; i < res_ctx->pool->stream_enc_count; i++) { + for (i = 0; i < pool->stream_enc_count; i++) { if (!res_ctx->is_stream_enc_acquired[i] && - res_ctx->pool->stream_enc[i]) { + pool->stream_enc[i]) { /* Store first available for MST second display * in daisy chain use case */ j = i; - if (res_ctx->pool->stream_enc[i]->id == + if (pool->stream_enc[i]->id == link->link_enc->preferred_engine) - return res_ctx->pool->stream_enc[i]; + return pool->stream_enc[i]; } } @@ -1218,17 +1230,19 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link( */ if (j >= 0 && dc_is_dp_signal(stream->signal)) - return res_ctx->pool->stream_enc[j]; + return pool->stream_enc[j]; return NULL; } -static struct audio *find_first_free_audio(struct resource_context *res_ctx) +static struct audio *find_first_free_audio( + struct resource_context *res_ctx, + const struct resource_pool *pool) { int i; - for (i = 0; i < res_ctx->pool->audio_count; i++) { + for (i = 0; i < pool->audio_count; i++) { if (res_ctx->is_audio_acquired[i] == false) { - return res_ctx->pool->audios[i]; + return pool->audios[i]; } } @@ -1358,6 +1372,7 @@ enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context) { + const struct resource_pool *pool = dc->res_pool; int i, j; calculate_phy_pix_clks(dc, context); @@ -1370,12 +1385,12 @@ enum dc_status resource_map_pool_resources( stream->bit_depth_params = dc->current_context->streams[i]->bit_depth_params; stream->clamping = dc->current_context->streams[i]->clamping; - continue; + continue; + } } - } /* mark resources used for stream that is already active */ - for (j = 0; j < MAX_PIPES; j++) { + for (j = 0; j < pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; const struct pipe_ctx *old_pipe_ctx = @@ -1395,7 +1410,7 @@ enum dc_status resource_map_pool_resources( continue; set_stream_engine_in_use( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->stream_enc); /* Switch to dp clock source only if there is @@ -1404,15 +1419,14 @@ enum dc_status resource_map_pool_resources( */ if (dc_is_dp_signal(pipe_ctx->stream->signal) && !find_pll_sharable_stream(stream, context)) - pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; + pipe_ctx->clock_source = pool->dp_clock_source; resource_reference_clock_source( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->clock_source); - set_audio_in_use(&context->res_ctx, - pipe_ctx->audio); + set_audio_in_use(&context->res_ctx, pool, + pipe_ctx->audio); } } @@ -1424,22 +1438,22 @@ enum dc_status resource_map_pool_resources( if (resource_is_stream_unchanged(dc->current_context, stream)) continue; /* acquire new resources */ - pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream); + pipe_idx = acquire_first_free_pipe( + &context->res_ctx, pool, stream); if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; - pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; pipe_ctx->stream_enc = find_first_free_match_stream_enc_for_link( - &context->res_ctx, stream); + &context->res_ctx, pool, stream); if (!pipe_ctx->stream_enc) return DC_NO_STREAM_ENG_RESOURCE; set_stream_engine_in_use( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->stream_enc); /* TODO: Add check if ASIC support and EDID audio */ @@ -1447,7 +1461,7 @@ enum dc_status resource_map_pool_resources( dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->public.audio_info.mode_count) { pipe_ctx->audio = find_first_free_audio( - &context->res_ctx); + &context->res_ctx, pool); /* * Audio assigned in order first come first get. @@ -1456,7 +1470,7 @@ enum dc_status resource_map_pool_resources( */ if (pipe_ctx->audio) set_audio_in_use( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->audio); } @@ -2077,7 +2091,7 @@ void dc_resource_validate_ctx_copy_construct( *dst_ctx = *src_ctx; - for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; if (cur_pipe->top_pipe) @@ -2097,13 +2111,14 @@ void dc_resource_validate_ctx_copy_construct( } struct clock_source *dc_resource_find_first_free_pll( - struct resource_context *res_ctx) + struct resource_context *res_ctx, + const struct resource_pool *pool) { int i; - for (i = 0; i < res_ctx->pool->clk_src_count; ++i) { + for (i = 0; i < pool->clk_src_count; ++i) { if (res_ctx->clock_source_ref_count[i] == 0) - return res_ctx->pool->clock_sources[i]; + return pool->clock_sources[i]; } return NULL; @@ -2151,6 +2166,7 @@ enum dc_status resource_map_clock_resources( struct validate_context *context) { int i, j; + const struct resource_pool *pool = dc->res_pool; /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { @@ -2168,8 +2184,7 @@ enum dc_status resource_map_clock_resources( if (dc_is_dp_signal(pipe_ctx->stream->signal) || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) - pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; + pipe_ctx->clock_source = pool->dp_clock_source; else { pipe_ctx->clock_source = NULL; @@ -2180,14 +2195,16 @@ enum dc_status resource_map_clock_resources( if (pipe_ctx->clock_source == NULL) pipe_ctx->clock_source = - dc_resource_find_first_free_pll(&context->res_ctx); + dc_resource_find_first_free_pll( + &context->res_ctx, + pool); } if (pipe_ctx->clock_source == NULL) return DC_NO_CLOCK_SOURCE_RESOURCE; resource_reference_clock_source( - &context->res_ctx, + &context->res_ctx, pool, pipe_ctx->clock_source); /* only one cs per stream regardless of mpo */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 23627b14c16c..99b6a1695f26 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -240,7 +240,7 @@ bool dc_stream_set_cursor_position( struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = dc_stream->timing.pix_clk_khz, - .ref_clk_khz = res_ctx->pool->ref_clock_inKhz, + .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz, .viewport_x_start = pipe_ctx->scl_data.viewport.x, .viewport_width = pipe_ctx->scl_data.viewport.width, .h_scale_ratio = pipe_ctx->scl_data.ratios.horz diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 943895faee49..aa6ac9596235 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -138,8 +138,7 @@ const struct dc_surface_status *dc_surface_get_status( if (core_dc->current_context == NULL) return NULL; - for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count; - i++) { + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index dd6f0b1bd8ae..30c197f378dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -132,8 +132,8 @@ void dce100_set_bandwidth( bool decrease_allowed) { if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { - context->res_ctx.pool->display_clock->funcs->set_clock( - context->res_ctx.pool->display_clock, + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, context->dispclk_khz * 115 / 100); dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; dc->current_context->dispclk_khz = context->dispclk_khz; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index f65b785220e2..f0700706d7c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -804,8 +804,6 @@ enum dc_status dce100_validate_with_context( if (!dce100_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - context->res_ctx.pool = dc->res_pool; - for (i = 0; i < set_count; i++) { context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); dc_stream_retain(&context->streams[i]->public); @@ -817,8 +815,8 @@ enum dc_status dce100_validate_with_context( if (result == DC_OK) result = resource_map_clock_resources(dc, context); - if (!resource_validate_attach_surfaces( - set, set_count, dc->current_context, context)) { + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -843,8 +841,6 @@ enum dc_status dce100_validate_guaranteed( { enum dc_status result = DC_ERROR_UNEXPECTED; - context->res_ctx.pool = dc->res_pool; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); dc_stream_retain(&context->streams[0]->public); context->stream_count++; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0e69aceb0bad..dc4c16416370 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1260,10 +1260,12 @@ void dce110_set_displaymarks( } } -static void set_safe_displaymarks(struct resource_context *res_ctx) +static void set_safe_displaymarks( + struct resource_context *res_ctx, + const struct resource_pool *pool) { int i; - int underlay_idx = res_ctx->pool->underlay_pipe_index; + int underlay_idx = pool->underlay_pipe_index; struct bw_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; struct bw_watermarks nbp_marks = { @@ -1308,9 +1310,11 @@ static void switch_dp_clock_sources( if (clk_src && clk_src != pipe_ctx->clock_source) { resource_unreference_clock_source( - res_ctx, &pipe_ctx->clock_source); + res_ctx, dc->res_pool, + &pipe_ctx->clock_source); pipe_ctx->clock_source = clk_src; - resource_reference_clock_source(res_ctx, clk_src); + resource_reference_clock_source( + res_ctx, dc->res_pool, clk_src); dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i); } @@ -1336,8 +1340,8 @@ static void reset_single_pipe_hw_ctx( pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); pipe_ctx->mi->funcs->free_mem_input( pipe_ctx->mi, context->stream_count); - resource_unreference_clock_source( - &context->res_ctx, &pipe_ctx->clock_source); + resource_unreference_clock_source(&context->res_ctx, dc->res_pool, + &pipe_ctx->clock_source); dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); @@ -1530,7 +1534,7 @@ static enum dc_status apply_ctx_to_hw_fpga( enum dc_status status = DC_ERROR_UNEXPECTED; int i; - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1561,7 +1565,7 @@ static void reset_hw_ctx_wrap( /* Reset old context */ /* look up the targets that have been removed since last commit */ - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1609,7 +1613,7 @@ enum dc_status dce110_apply_ctx_to_hw( dcb->funcs->set_scratch_critical_state(dcb, true); /* below is for real asic only */ - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1629,14 +1633,14 @@ enum dc_status dce110_apply_ctx_to_hw( PIPE_GATING_CONTROL_DISABLE); } - set_safe_displaymarks(&context->res_ctx); + set_safe_displaymarks(&context->res_ctx, dc->res_pool); /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); if (context->dispclk_khz > dc->current_context->dispclk_khz) { - context->res_ctx.pool->display_clock->funcs->set_clock( - context->res_ctx.pool->display_clock, + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, context->dispclk_khz * 115 / 100); } /* program audio wall clock. use HDMI as clock source if HDMI @@ -1658,7 +1662,7 @@ enum dc_status dce110_apply_ctx_to_hw( * find first available pipe with audio, setup audio wall DTO per topology * instead of per pipe. */ - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL) @@ -1685,8 +1689,8 @@ enum dc_status dce110_apply_ctx_to_hw( } /* no HDMI audio is found, try DP audio */ - if (i == context->res_ctx.pool->pipe_count) { - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + if (i == dc->res_pool->pipe_count) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL) @@ -1713,7 +1717,7 @@ enum dc_status dce110_apply_ctx_to_hw( } } - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -2297,8 +2301,8 @@ static void dce110_set_bandwidth( dce110_set_displaymarks(dc, context); if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { - context->res_ctx.pool->display_clock->funcs->set_clock( - context->res_ctx.pool->display_clock, + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, context->dispclk_khz * 115 / 100); dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; dc->current_context->dispclk_khz = context->dispclk_khz; @@ -2446,7 +2450,7 @@ static void dce110_apply_ctx_for_surface( if (!surface) return; - for (i = 0; i < context->res_ctx.pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->surface != surface) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8dec9a5602a9..122f2d03afc0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -866,7 +866,7 @@ static enum dc_status validate_mapped_resource( continue; if (!is_surface_pixel_format_supported(pipe_ctx, - context->res_ctx.pool->underlay_pipe_index)) + dc->res_pool->underlay_pipe_index)) return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; if (!pipe_ctx->tg->funcs->validate_timing( @@ -918,7 +918,7 @@ bool dce110_validate_bandwidth( &dc->bw_dceip, &dc->bw_vbios, context->res_ctx.pipe_ctx, - context->res_ctx.pool->pipe_count, + dc->res_pool->pipe_count, &context->bw_results)) result = true; context->dispclk_khz = context->bw_results.dispclk_khz; @@ -1030,8 +1030,6 @@ enum dc_status dce110_validate_with_context( if (!dce110_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - context->res_ctx.pool = dc->res_pool; - for (i = 0; i < set_count; i++) { context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); dc_stream_retain(&context->streams[i]->public); @@ -1043,8 +1041,8 @@ enum dc_status dce110_validate_with_context( if (result == DC_OK) result = resource_map_clock_resources(dc, context); - if (!resource_validate_attach_surfaces( - set, set_count, dc->current_context, context)) { + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -1069,8 +1067,6 @@ enum dc_status dce110_validate_guaranteed( { enum dc_status result = DC_ERROR_UNEXPECTED; - context->res_ctx.pool = dc->res_pool; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); dc_stream_retain(&context->streams[0]->public); context->stream_count++; @@ -1098,22 +1094,23 @@ enum dc_status dce110_validate_guaranteed( static struct pipe_ctx *dce110_acquire_underlay( struct validate_context *context, + const struct resource_pool *pool, struct core_stream *stream) { struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &context->res_ctx; - unsigned int underlay_idx = res_ctx->pool->underlay_pipe_index; + unsigned int underlay_idx = pool->underlay_pipe_index; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; if (res_ctx->pipe_ctx[underlay_idx].stream) return NULL; - pipe_ctx->tg = res_ctx->pool->timing_generators[underlay_idx]; - pipe_ctx->mi = res_ctx->pool->mis[underlay_idx]; + pipe_ctx->tg = pool->timing_generators[underlay_idx]; + pipe_ctx->mi = pool->mis[underlay_idx]; /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/ - pipe_ctx->xfm = res_ctx->pool->transforms[underlay_idx]; - pipe_ctx->opp = res_ctx->pool->opps[underlay_idx]; - pipe_ctx->dis_clk = res_ctx->pool->display_clock; + pipe_ctx->xfm = pool->transforms[underlay_idx]; + pipe_ctx->opp = pool->opps[underlay_idx]; + pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = underlay_idx; pipe_ctx->stream = stream; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 4bf75afd5721..4de51a86c9ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -749,22 +749,24 @@ static void destruct(struct dce110_resource_pool *pool) } } -static struct clock_source *find_matching_pll(struct resource_context *res_ctx, +static struct clock_source *find_matching_pll( + struct resource_context *res_ctx, + const struct resource_pool *pool, const struct core_stream *const stream) { switch (stream->sink->link->link_enc->transmitter) { case TRANSMITTER_UNIPHY_A: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL0]; + return pool->clock_sources[DCE112_CLK_SRC_PLL0]; case TRANSMITTER_UNIPHY_B: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL1]; + return pool->clock_sources[DCE112_CLK_SRC_PLL1]; case TRANSMITTER_UNIPHY_C: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL2]; + return pool->clock_sources[DCE112_CLK_SRC_PLL2]; case TRANSMITTER_UNIPHY_D: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL3]; + return pool->clock_sources[DCE112_CLK_SRC_PLL3]; case TRANSMITTER_UNIPHY_E: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL4]; + return pool->clock_sources[DCE112_CLK_SRC_PLL4]; case TRANSMITTER_UNIPHY_F: - return res_ctx->pool->clock_sources[DCE112_CLK_SRC_PLL5]; + return pool->clock_sources[DCE112_CLK_SRC_PLL5]; default: return NULL; }; @@ -842,7 +844,7 @@ bool dce112_validate_bandwidth( &dc->bw_dceip, &dc->bw_vbios, context->res_ctx.pipe_ctx, - context->res_ctx.pool->pipe_count, + dc->res_pool->pipe_count, &context->bw_results)) result = true; context->dispclk_khz = context->bw_results.dispclk_khz; @@ -928,17 +930,18 @@ enum dc_status resource_map_phy_clock_resources( if (dc_is_dp_signal(pipe_ctx->stream->signal) || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) pipe_ctx->clock_source = - context->res_ctx.pool->dp_clock_source; + dc->res_pool->dp_clock_source; else - pipe_ctx->clock_source = - find_matching_pll(&context->res_ctx, - stream); + pipe_ctx->clock_source = find_matching_pll( + &context->res_ctx, dc->res_pool, + stream); if (pipe_ctx->clock_source == NULL) return DC_NO_CLOCK_SOURCE_RESOURCE; resource_reference_clock_source( &context->res_ctx, + dc->res_pool, pipe_ctx->clock_source); /* only one cs per stream regardless of mpo */ @@ -983,8 +986,6 @@ enum dc_status dce112_validate_with_context( if (!dce112_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - context->res_ctx.pool = dc->res_pool; - for (i = 0; i < set_count; i++) { context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); dc_stream_retain(&context->streams[i]->public); @@ -996,8 +997,8 @@ enum dc_status dce112_validate_with_context( if (result == DC_OK) result = resource_map_phy_clock_resources(dc, context); - if (!resource_validate_attach_surfaces( - set, set_count, dc->current_context, context)) { + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -1022,8 +1023,6 @@ enum dc_status dce112_validate_guaranteed( { enum dc_status result = DC_ERROR_UNEXPECTED; - context->res_ctx.pool = dc->res_pool; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); dc_stream_retain(&context->streams[0]->public); context->stream_count++; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index d49092986d54..0aa128e5ed84 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -821,8 +821,6 @@ enum dc_status dce80_validate_with_context( if (!dce80_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - context->res_ctx.pool = dc->res_pool; - for (i = 0; i < set_count; i++) { context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); dc_stream_retain(&context->streams[i]->public); @@ -834,8 +832,8 @@ enum dc_status dce80_validate_with_context( if (result == DC_OK) result = resource_map_clock_resources(dc, context); - if (!resource_validate_attach_surfaces( - set, set_count, dc->current_context, context)) { + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } @@ -859,8 +857,6 @@ enum dc_status dce80_validate_guaranteed( { enum dc_status result = DC_ERROR_UNEXPECTED; - context->res_ctx.pool = dc->res_pool; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); dc_stream_retain(&context->streams[0]->public); context->stream_count++; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 2b43e18c65f5..f3fe850ffa13 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -212,6 +212,7 @@ struct resource_funcs { struct pipe_ctx *(*acquire_idle_pipe_for_layer)( struct validate_context *context, + const struct resource_pool *pool, struct core_stream *stream); void (*build_bit_depth_reduction_params)( @@ -293,7 +294,6 @@ struct pipe_ctx { }; struct resource_context { - const struct resource_pool *pool; struct pipe_ctx pipe_ctx[MAX_PIPES]; bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index b1987cab9751..89d34bed131b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -92,10 +92,12 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx); void resource_unreference_clock_source( struct resource_context *res_ctx, + const struct resource_pool *pool, struct clock_source **clock_source); void resource_reference_clock_source( struct resource_context *res_ctx, + const struct resource_pool *pool, struct clock_source *clock_source); bool resource_are_streams_timing_synchronizable( @@ -107,7 +109,8 @@ struct clock_source *resource_find_used_clk_src_for_sharing( struct pipe_ctx *pipe_ctx); struct clock_source *dc_resource_find_first_free_pll( - struct resource_context *res_ctx); + struct resource_context *res_ctx, + const struct resource_pool *pool); struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, @@ -117,9 +120,12 @@ bool resource_attach_surfaces_to_context( const struct dc_surface *const *surfaces, int surface_count, const struct dc_stream *dc_stream, - struct validate_context *context); + struct validate_context *context, + const struct resource_pool *pool); -struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx); +struct pipe_ctx *find_idle_secondary_pipe( + struct resource_context *res_ctx, + const struct resource_pool *pool); bool resource_is_stream_unchanged( const struct validate_context *old_context, const struct core_stream *stream); @@ -131,7 +137,8 @@ bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, const struct validate_context *old_context, - struct validate_context *context); + struct validate_context *context, + const struct resource_pool *pool); void validate_guaranteed_copy_streams( struct validate_context *context, -- GitLab From b92033b67879380baee9ebd14da78c7dc36e1ea5 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Wed, 12 Apr 2017 15:29:13 -0400 Subject: [PATCH 0414/2898] drm/amd/display: Define dithering options Signed-off-by: Ding Wang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 29 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 647c095e0ae9..dd8902d28ee1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -430,6 +430,7 @@ struct dc_stream { enum signal_type output_signal; enum dc_color_space output_color_space; + enum dc_dither_option dither_option; struct rect src; /* composition area */ struct rect dst; /* stream addressable area */ @@ -444,7 +445,6 @@ struct dc_stream { struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; - /* TODO: dithering */ /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 64d43dba8fd6..1a7ce061258f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -484,6 +484,35 @@ enum dc_color_space { COLOR_SPACE_ADOBERGB, }; +enum dc_dither_option { + DITHER_OPTION_DEFAULT, + DITHER_OPTION_DISABLE, + DITHER_OPTION_FM6, + DITHER_OPTION_FM8, + DITHER_OPTION_FM10, + DITHER_OPTION_SPATIAL6_FRAME_RANDOM, + DITHER_OPTION_SPATIAL8_FRAME_RANDOM, + DITHER_OPTION_SPATIAL10_FRAME_RANDOM, + DITHER_OPTION_SPATIAL6, + DITHER_OPTION_SPATIAL8, + DITHER_OPTION_SPATIAL10, + DITHER_OPTION_TRUN6, + DITHER_OPTION_TRUN8, + DITHER_OPTION_TRUN10, + DITHER_OPTION_TRUN10_SPATIAL8, + DITHER_OPTION_TRUN10_SPATIAL6, + DITHER_OPTION_TRUN10_FM8, + DITHER_OPTION_TRUN10_FM6, + DITHER_OPTION_TRUN10_SPATIAL8_FM6, + DITHER_OPTION_SPATIAL10_FM8, + DITHER_OPTION_SPATIAL10_FM6, + DITHER_OPTION_TRUN8_SPATIAL6, + DITHER_OPTION_TRUN8_FM6, + DITHER_OPTION_SPATIAL8_FM6, + DITHER_OPTION_MAX = DITHER_OPTION_SPATIAL8_FM6, + DITHER_OPTION_INVALID +}; + enum dc_quantization_range { QUANTIZATION_RANGE_UNKNOWN, QUANTIZATION_RANGE_FULL, -- GitLab From 1c29313b96fbe9606ecaab540800d20f2ae88adc Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 26 Apr 2017 10:54:45 -0400 Subject: [PATCH 0415/2898] drm/amd/display: fix crash caused by incorrect index being used for array Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index f6223e6b3536..d3d57008271b 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -1122,7 +1122,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, * current mode */ calc_freesync_range(core_freesync, *streams, state, - core_freesync->map[stream_index].caps-> + core_freesync->map[map_index].caps-> min_refresh_in_micro_hz, state->nominal_refresh_rate_in_micro_hz); } -- GitLab From 7cc9e7a68abef8d1303700bac6f58ab76bc9db7b Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Wed, 26 Apr 2017 11:51:38 -0400 Subject: [PATCH 0416/2898] drm/amd/display: Check for Zero Range in FreeSync Calc -check for min/max range in freesync calculation and handle it accordingly Signed-off-by: Eric Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index d3d57008271b..009cb797bcfa 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -363,6 +363,21 @@ static void calc_freesync_range(struct core_freesync *core_freesync, unsigned int index = map_index_from_stream(core_freesync, stream); uint32_t vtotal = stream->timing.v_total; + if ((min_refresh_in_uhz == 0) || (max_refresh_in_uhz == 0)) { + state->freesync_range.min_refresh = + state->nominal_refresh_rate_in_micro_hz; + state->freesync_range.max_refresh = + state->nominal_refresh_rate_in_micro_hz; + + state->freesync_range.max_frame_duration = 0; + state->freesync_range.min_frame_duration = 0; + + state->freesync_range.vmax = vtotal; + state->freesync_range.vmin = vtotal; + + return; + } + min_frame_duration_in_ns = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), max_refresh_in_uhz))); -- GitLab From 529cad0f945c9e60569e902062d2f2741e4fd71a Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Tue, 25 Apr 2017 10:03:27 -0400 Subject: [PATCH 0417/2898] drm/amd/display: Add function to set dither option Signed-off-by: Ding Wang Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 41 +++++++ .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 110 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 3 + .../amd/display/dc/dce110/dce110_resource.c | 48 +------- .../amd/display/dc/dce110/dce110_resource.h | 4 - .../amd/display/dc/dce112/dce112_resource.c | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 4 - drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 + 9 files changed, 160 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 37986632f025..738acf0cc7db 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -363,6 +363,44 @@ static void set_test_pattern( cust_pattern_size); } +void set_dither_option(const struct dc_stream *dc_stream, + enum dc_dither_option option) +{ + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct bit_depth_reduction_params params; + struct core_link *core_link = DC_LINK_TO_CORE(stream->status.link); + struct pipe_ctx *pipes = + core_link->dc->current_context->res_ctx.pipe_ctx; + + memset(¶ms, 0, sizeof(params)); + if (!stream) + return; + if (option > DITHER_OPTION_MAX) + return; + if (option == DITHER_OPTION_DEFAULT) { + switch (stream->public.timing.display_color_depth) { + case COLOR_DEPTH_666: + stream->public.dither_option = DITHER_OPTION_SPATIAL6; + break; + case COLOR_DEPTH_888: + stream->public.dither_option = DITHER_OPTION_SPATIAL8; + break; + case COLOR_DEPTH_101010: + stream->public.dither_option = DITHER_OPTION_SPATIAL10; + break; + default: + option = DITHER_OPTION_DISABLE; + } + } else { + stream->public.dither_option = option; + } + resource_build_bit_depth_reduction_params(stream, + ¶ms); + stream->bit_depth_params = params; + pipes->opp->funcs-> + opp_program_bit_depth_reduction(pipes->opp, ¶ms); +} + static void allocate_dc_stream_funcs(struct core_dc *core_dc) { core_dc->public.stream_funcs.stream_update_scaling = stream_update_scaling; @@ -380,6 +418,9 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; + core_dc->public.stream_funcs.set_dither_option = + set_dither_option; + core_dc->public.link_funcs.set_drive_settings = set_drive_settings; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 4b9d3f12406f..a0d192774a22 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -11,6 +11,7 @@ #include "dpcd_defs.h" #include "core_dc.h" +#include "resource.h" /* maximum pre emphasis level allowed for each voltage swing level*/ static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = { @@ -2245,8 +2246,7 @@ static void set_crtc_test_pattern(struct core_link *link, case DP_TEST_PATTERN_VIDEO_MODE: { /* restore bitdepth reduction */ - link->dc->res_pool->funcs-> - build_bit_depth_reduction_params(pipe_ctx->stream, + resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); pipe_ctx->stream->bit_depth_params = params; pipe_ctx->opp->funcs-> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 43e5758719ca..2de86f8364a3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2246,3 +2246,113 @@ bool pipe_need_reprogram( return false; } + +void resource_build_bit_depth_reduction_params(const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth) +{ + enum dc_dither_option option = stream->public.dither_option; + enum dc_pixel_encoding pixel_encoding = + stream->public.timing.pixel_encoding; + + memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); + + if (option == DITHER_OPTION_DISABLE) + return; + + if (option == DITHER_OPTION_TRUN6) { + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; + } else if (option == DITHER_OPTION_TRUN8 || + option == DITHER_OPTION_TRUN8_SPATIAL6 || + option == DITHER_OPTION_TRUN8_FM6) { + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; + } else if (option == DITHER_OPTION_TRUN10 || + option == DITHER_OPTION_TRUN10_SPATIAL6 || + option == DITHER_OPTION_TRUN10_SPATIAL8 || + option == DITHER_OPTION_TRUN10_FM8 || + option == DITHER_OPTION_TRUN10_FM6 || + option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; + } + + /* special case - Formatter can only reduce by 4 bits at most. + * When reducing from 12 to 6 bits, + * HW recommends we use trunc with round mode + * (if we did nothing, trunc to 10 bits would be used) + * note that any 12->10 bit reduction is ignored prior to DCE8, + * as the input was 10 bits. + */ + if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || + option == DITHER_OPTION_SPATIAL6 || + option == DITHER_OPTION_FM6) { + fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; + fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; + fmt_bit_depth->flags.TRUNCATE_MODE = 1; + } + + /* spatial dither + * note that spatial modes 1-3 are never used + */ + if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || + option == DITHER_OPTION_SPATIAL6 || + option == DITHER_OPTION_TRUN10_SPATIAL6 || + option == DITHER_OPTION_TRUN8_SPATIAL6) { + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; + fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; + fmt_bit_depth->flags.RGB_RANDOM = + (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; + } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || + option == DITHER_OPTION_SPATIAL8 || + option == DITHER_OPTION_SPATIAL8_FM6 || + option == DITHER_OPTION_TRUN10_SPATIAL8 || + option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; + fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; + fmt_bit_depth->flags.RGB_RANDOM = + (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; + } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || + option == DITHER_OPTION_SPATIAL10 || + option == DITHER_OPTION_SPATIAL10_FM8 || + option == DITHER_OPTION_SPATIAL10_FM6) { + fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; + fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; + fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; + fmt_bit_depth->flags.RGB_RANDOM = + (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; + } + + if (option == DITHER_OPTION_SPATIAL6 || + option == DITHER_OPTION_SPATIAL8 || + option == DITHER_OPTION_SPATIAL10) { + fmt_bit_depth->flags.FRAME_RANDOM = 0; + } else { + fmt_bit_depth->flags.FRAME_RANDOM = 1; + } + + ////////////////////// + //// temporal dither + ////////////////////// + if (option == DITHER_OPTION_FM6 || + option == DITHER_OPTION_SPATIAL8_FM6 || + option == DITHER_OPTION_SPATIAL10_FM6 || + option == DITHER_OPTION_TRUN10_FM6 || + option == DITHER_OPTION_TRUN8_FM6 || + option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { + fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; + fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; + } else if (option == DITHER_OPTION_FM8 || + option == DITHER_OPTION_SPATIAL10_FM8 || + option == DITHER_OPTION_TRUN10_FM8) { + fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; + fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; + } else if (option == DITHER_OPTION_FM10) { + fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; + fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; + } + + fmt_bit_depth->pixel_encoding = pixel_encoding; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index dd8902d28ee1..87675f032949 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -122,6 +122,9 @@ struct dc_stream_funcs { const struct dc_stream **stream, int num_streams, const struct dc_static_screen_events *events); + + void (*set_dither_option)(const struct dc_stream *stream, + enum dc_dither_option option); }; struct link_training_settings; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 122f2d03afc0..5b2b41efa5f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -775,50 +775,6 @@ static void get_pixel_clock_parameters( } } -void dce110_resource_build_bit_depth_reduction_params( - const struct core_stream *stream, - struct bit_depth_reduction_params *fmt_bit_depth) -{ - memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); - - /*TODO: Need to un-hardcode, refer to function with same name - * in dal2 hw_sequencer*/ - - fmt_bit_depth->flags.TRUNCATE_ENABLED = 0; - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0; - fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0; - - /* Diagnostics need consistent CRC of the image, that means - * dithering should not be enabled for Diagnostics. */ - if (IS_DIAG_DC(stream->ctx->dce_environment) == false) { - switch (stream->public.timing.display_color_depth) { - case COLOR_DEPTH_666: - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; - break; - case COLOR_DEPTH_888: - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; - break; - case COLOR_DEPTH_101010: - fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; - fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; - break; - default: - break; - } - fmt_bit_depth->flags.RGB_RANDOM = 1; - fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; - fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; - fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; - - fmt_bit_depth->pixel_encoding = - stream->public.timing.pixel_encoding; - } - - return; -} - enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); @@ -826,7 +782,7 @@ enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) pipe_ctx->clock_source, &pipe_ctx->pix_clk_params, &pipe_ctx->pll_settings); - dce110_resource_build_bit_depth_reduction_params(pipe_ctx->stream, + resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; @@ -1171,8 +1127,6 @@ static const struct resource_funcs dce110_res_pool_funcs = { .validate_guaranteed = dce110_validate_guaranteed, .validate_bandwidth = dce110_validate_bandwidth, .acquire_idle_pipe_for_layer = dce110_acquire_underlay, - .build_bit_depth_reduction_params = - dce110_resource_build_bit_depth_reduction_params }; static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h index 0c357fdfa8bc..8e2e85dd30b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -40,10 +40,6 @@ struct dce110_resource_pool { enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); -void dce110_resource_build_bit_depth_reduction_params( - const struct core_stream *stream, - struct bit_depth_reduction_params *fmt_bit_depth); - struct resource_pool *dce110_create_resource_pool( uint8_t num_virtual_links, struct core_dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 4de51a86c9ea..18c1b89a52be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1062,7 +1062,7 @@ static const struct resource_funcs dce112_res_pool_funcs = { .link_enc_create = dce112_link_encoder_create, .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, - .validate_bandwidth = dce112_validate_bandwidth + .validate_bandwidth = dce112_validate_bandwidth, }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index f3fe850ffa13..9e5e0ba5b10b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -214,10 +214,6 @@ struct resource_funcs { struct validate_context *context, const struct resource_pool *pool, struct core_stream *stream); - - void (*build_bit_depth_reduction_params)( - const struct core_stream *stream, - struct bit_depth_reduction_params *fmt_bit_depth); }; struct audio_support{ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 89d34bed131b..4e07b9fea669 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -160,5 +160,7 @@ bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx); +void resource_build_bit_depth_reduction_params(const struct core_stream *stream, + struct bit_depth_reduction_params *fmt_bit_depth); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ -- GitLab From 9e594f4c3f30c8ba43a1601268e82177fbd737c1 Mon Sep 17 00:00:00 2001 From: Eric Cook Date: Thu, 27 Apr 2017 12:20:34 -0400 Subject: [PATCH 0418/2898] drm/amd/display: Add support for FreeSync on eDP to module Signed-off-by: Eric Acked-by: Harry Wentland Reviewed-by: Anthony Koo Signed-off-by: Alex Deucher --- .../amd/display/modules/freesync/freesync.c | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 009cb797bcfa..82086a129a3b 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -109,11 +109,16 @@ struct freesync_entity { struct mod_freesync_user_enable user_enable; }; +struct freesync_registry_options { + unsigned int min_refresh_from_edid; +}; + struct core_freesync { struct mod_freesync public; struct dc *dc; struct freesync_entity *map; int num_entities; + struct freesync_registry_options opts; }; #define MOD_FREESYNC_TO_CORE(mod_freesync)\ @@ -136,7 +141,7 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) struct persistent_data_flag flag; - int i = 0; + int i, data = 0; if (core_freesync == NULL) goto fail_alloc_context; @@ -165,6 +170,12 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) flag.save_per_link = false; dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL, 0, &flag); + flag.save_per_edid = false; + flag.save_per_link = false; + if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, + "DalDrrSupport", &data, sizeof(data), &flag)) { + core_freesync->opts.min_refresh_from_edid = data; + } return &core_freesync->public; @@ -219,7 +230,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_stream *core_stream = NULL; struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; - int persistent_freesync_enable = 0; + int persistent_freesync_enable, stream_index = 0; struct persistent_data_flag flag; unsigned int nom_refresh_rate_micro_hz; unsigned long long temp; @@ -238,6 +249,26 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, dc_stream_retain(stream); + stream_index = map_index_from_stream(core_freesync, stream); + + temp = stream->timing.pix_clk_khz; + temp *= 1000ULL * 1000ULL * 1000ULL; + temp = div_u64(temp, stream->timing.h_total); + temp = div_u64(temp, stream->timing.v_total); + + nom_refresh_rate_micro_hz = (unsigned int) temp; + + if (core_freesync->opts.min_refresh_from_edid != 0 && + dc_is_embedded_signal( + stream[stream_index].sink->sink_signal)) { + caps->supported = true; + caps->min_refresh_in_micro_hz = + core_freesync->opts.min_refresh_from_edid * + 1000000; + caps->max_refresh_in_micro_hz = + nom_refresh_rate_micro_hz; + } + core_freesync->map[core_freesync->num_entities].stream = stream; core_freesync->map[core_freesync->num_entities].caps = caps; @@ -275,13 +306,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, enable_for_video = false; } - temp = stream->timing.pix_clk_khz; - temp *= 1000ULL * 1000ULL * 1000ULL; - temp = div_u64(temp, stream->timing.h_total); - temp = div_u64(temp, stream->timing.v_total); - - nom_refresh_rate_micro_hz = (unsigned int) temp; - if (caps->supported && nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) -- GitLab From cf4cde2b0b678ca1cf56d7b397c78b1bc3d3155b Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 28 Apr 2017 09:56:08 -0400 Subject: [PATCH 0419/2898] drm/amd/display: Disable cursor on video surface. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 99b6a1695f26..4ba446de4d00 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -250,6 +250,10 @@ bool dc_stream_set_cursor_position( !pipe_ctx->ipp || !pipe_ctx->surface) continue; + if (pipe_ctx->surface->public.address.type + == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) + pos_cpy.enable = false; + if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) pos_cpy.enable = false; -- GitLab From 9c3b2b50b3f03e876d5df1cf8940a79013091e9d Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 28 Apr 2017 07:54:34 -0400 Subject: [PATCH 0420/2898] drm/amd/display: move drr_params definition to TG Signed-off-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 7 +++++++ .../gpu/drm/amd/display/include/hw_sequencer_types.h | 11 ----------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 2c4a9d02b3c1..00cdaaae455c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -40,6 +40,13 @@ struct dcp_gsl_params { int gsl_master; }; +/* define the structure of Dynamic Refresh Mode */ +struct drr_params { + uint32_t vertical_total_min; + uint32_t vertical_total_max; + bool immediate_flip; +}; + #define LEFT_EYE_3D_PRIMARY_SURFACE 1 #define RIGHT_EYE_3D_PRIMARY_SURFACE 0 diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 065a91a7002f..8ba9f65276f5 100644 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h @@ -30,15 +30,4 @@ #include "grph_object_defs.h" #include "link_service_types.h" -/* define the structure of Dynamic Refresh Mode */ -struct drr_params { - /* defines the minimum possible vertical dimension of display timing - * for CRTC as supported by the panel */ - uint32_t vertical_total_min; - /* defines the maximum possible vertical dimension of display timing - * for CRTC as supported by the panel */ - uint32_t vertical_total_max; - bool immediate_flip; -}; - #endif -- GitLab From 7d091f7a4466cd7d7b778c126072b3dc46d8141f Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 28 Apr 2017 16:21:38 -0400 Subject: [PATCH 0421/2898] drm/amd/display: Get dprefclk ss percentage from vbios Signed-off-by: Hersen Wu Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/bios/bios_parser2.c | 40 ++++------------ .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 46 ++++++++++++++----- .../gpu/drm/amd/display/dc/dce/dce_clocks.h | 13 +++--- 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 123942f4cbde..682fc9b9b3f2 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1070,7 +1070,6 @@ static enum bp_result get_ss_info_v4_1( { enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL; - struct atom_smu_info_v3_1 *smu_tbl = NULL; if (!ss_info) return BP_RESULT_BADINPUT; @@ -1078,19 +1077,11 @@ static enum bp_result get_ss_info_v4_1( if (!DATA_TABLES(dce_info)) return BP_RESULT_BADBIOSTABLE; - if (!DATA_TABLES(smu_info)) - return BP_RESULT_BADBIOSTABLE; - disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1, DATA_TABLES(dce_info)); if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - smu_tbl = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); - if (!smu_tbl) - return BP_RESULT_BADBIOSTABLE; - - ss_info->type.STEP_AND_DELAY_INFO = false; ss_info->spread_percentage_divider = 1000; /* BIOS no longer uses target clock. Always enable for now */ @@ -1123,12 +1114,11 @@ static enum bp_result get_ss_info_v4_1( ss_info->type.CENTER_MODE = true; break; case AS_SIGNAL_TYPE_GPU_PLL: - ss_info->spread_spectrum_percentage = - smu_tbl->gpuclk_ss_percentage; - ss_info->spread_spectrum_range = - smu_tbl->gpuclk_ss_rate_10hz * 10; - if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) - ss_info->type.CENTER_MODE = true; + /* atom_firmware: DAL only get data from dce_info table. + * if data within smu_info is needed for DAL, VBIOS should + * copy it into dce_info + */ + result = BP_RESULT_UNSUPPORTED; break; default: result = BP_RESULT_UNSUPPORTED; @@ -1145,7 +1135,6 @@ static enum bp_result get_ss_info_v4_2( { enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; - struct atom_smu_info_v3_1 *smu_tbl = NULL; if (!ss_info) return BP_RESULT_BADINPUT; @@ -1153,19 +1142,11 @@ static enum bp_result get_ss_info_v4_2( if (!DATA_TABLES(dce_info)) return BP_RESULT_BADBIOSTABLE; - if (!DATA_TABLES(smu_info)) - return BP_RESULT_BADBIOSTABLE; - disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2, DATA_TABLES(dce_info)); if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - smu_tbl = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); - if (!smu_tbl) - return BP_RESULT_BADBIOSTABLE; - - ss_info->type.STEP_AND_DELAY_INFO = false; ss_info->spread_percentage_divider = 1000; /* BIOS no longer uses target clock. Always enable for now */ @@ -1198,12 +1179,11 @@ static enum bp_result get_ss_info_v4_2( ss_info->type.CENTER_MODE = true; break; case AS_SIGNAL_TYPE_GPU_PLL: - ss_info->spread_spectrum_percentage = - smu_tbl->gpuclk_ss_percentage; - ss_info->spread_spectrum_range = - smu_tbl->gpuclk_ss_rate_10hz * 10; - if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) - ss_info->type.CENTER_MODE = true; + /* atom_firmware: DAL only get data from dce_info table. + * if data within smu_info is needed for DAL, VBIOS should + * copy it into dce_info + */ + result = BP_RESULT_UNSUPPORTED; break; default: result = BP_RESULT_UNSUPPORTED; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index b4fd02219c2c..81cb138cdc38 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -218,11 +218,11 @@ static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) (should not be case with CIK) then SW should program all rates generated according to average value (case as with previous ASICs) */ - if (clk_dce->ss_on_gpu_pll && clk_dce->gpu_pll_ss_divider != 0) { + if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) { struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( dal_fixed32_32_from_fraction( - clk_dce->gpu_pll_ss_percentage, - clk_dce->gpu_pll_ss_divider), 200); + clk_dce->dprefclk_ss_percentage, + clk_dce->dprefclk_ss_divider), 200); struct fixed32_32 adj_dp_ref_clk_khz; ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, @@ -480,22 +480,44 @@ static void dce_clock_read_ss_info(struct dce_disp_clk *clk_dce) */ if (result == BP_RESULT_OK && info.spread_spectrum_percentage != 0) { - clk_dce->ss_on_gpu_pll = true; - clk_dce->gpu_pll_ss_divider = info.spread_percentage_divider; + clk_dce->ss_on_dprefclk = true; + clk_dce->dprefclk_ss_divider = info.spread_percentage_divider; if (info.type.CENTER_MODE == 0) { - /* Currently for DP Reference clock we + /* TODO: Currently for DP Reference clock we * need only SS percentage for * downspread */ - clk_dce->gpu_pll_ss_percentage = + clk_dce->dprefclk_ss_percentage = info.spread_spectrum_percentage; } + + return; } + result = bp->funcs->get_spread_spectrum_info( + bp, AS_SIGNAL_TYPE_DISPLAY_PORT, 0, &info); + + /* Based on VBIOS, VBIOS will keep entry for DPREFCLK SS + * even if SS not enabled and in that case + * SSInfo.spreadSpectrumPercentage !=0 would be sign + * that SS is enabled + */ + if (result == BP_RESULT_OK && + info.spread_spectrum_percentage != 0) { + clk_dce->ss_on_dprefclk = true; + clk_dce->dprefclk_ss_divider = info.spread_percentage_divider; + + if (info.type.CENTER_MODE == 0) { + /* Currently for DP Reference clock we + * need only SS percentage for + * downspread */ + clk_dce->dprefclk_ss_percentage = + info.spread_spectrum_percentage; + } + } } } - static bool dce_apply_clock_voltage_request( struct display_clock *clk, enum dm_pp_clock_type clocks_type, @@ -629,9 +651,11 @@ static void dce_disp_clk_construct( clk_dce->clk_mask = clk_mask; clk_dce->dfs_bypass_disp_clk = 0; - clk_dce->gpu_pll_ss_percentage = 0; - clk_dce->gpu_pll_ss_divider = 1000; - clk_dce->ss_on_gpu_pll = false; + + clk_dce->dprefclk_ss_percentage = 0; + clk_dce->dprefclk_ss_divider = 1000; + clk_dce->ss_on_dprefclk = false; + base->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; base->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 2fd00e45395c..29ff470086e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -116,13 +116,12 @@ struct dce_disp_clk { * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */ int dfs_bypass_disp_clk; - /* Flag for Enabled SS on GPU PLL */ - bool ss_on_gpu_pll; - /* GPU PLL SS percentage (if down-spread enabled) */ - int gpu_pll_ss_percentage; - /* GPU PLL SS percentage Divider (100 or 1000) */ - int gpu_pll_ss_divider; - + /* Flag for Enabled SS on DPREFCLK */ + bool ss_on_dprefclk; + /* DPREFCLK SS percentage (if down-spread enabled) */ + int dprefclk_ss_percentage; + /* DPREFCLK SS percentage Divider (100 or 1000) */ + int dprefclk_ss_divider; /* max disp_clk from PPLIB for max validation display clock*/ int max_displ_clk_in_khz; -- GitLab From ba624cddbc002816e376d588290a48f77ff4b06f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 3 May 2017 13:58:45 -0400 Subject: [PATCH 0422/2898] drm/amd/display: Assign stream to map before we need it Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 82086a129a3b..c5330f3cc1de 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -230,7 +230,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_stream *core_stream = NULL; struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; - int persistent_freesync_enable, stream_index = 0; + int persistent_freesync_enable = 0; struct persistent_data_flag flag; unsigned int nom_refresh_rate_micro_hz; unsigned long long temp; @@ -249,8 +249,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, dc_stream_retain(stream); - stream_index = map_index_from_stream(core_freesync, stream); - temp = stream->timing.pix_clk_khz; temp *= 1000ULL * 1000ULL * 1000ULL; temp = div_u64(temp, stream->timing.h_total); @@ -260,7 +258,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, if (core_freesync->opts.min_refresh_from_edid != 0 && dc_is_embedded_signal( - stream[stream_index].sink->sink_signal)) { + stream->sink->sink_signal)) { caps->supported = true; caps->min_refresh_in_micro_hz = core_freesync->opts.min_refresh_from_edid * -- GitLab From 03ea364c8e156b2bb5c64465718e8ebd75e3df22 Mon Sep 17 00:00:00 2001 From: Arindam Nath Date: Wed, 26 Apr 2017 17:39:56 +0530 Subject: [PATCH 0423/2898] drm/amd/display: fix resume hang because of DP short pulse There is a hard hang observed during resume from S3 when the system receives a DP short pulse interrupt. This is because there are two code paths contending for GPIO access for AUX channel transactions. One such path is through amdgpu_dm_display_resume() function which is invoked from the regular system resume code path. The other path is through handle_hpd_rx_irq(), which is invoked in response to system receiving DP short pulse interrupt. handle_hpd_rx_irq() guards against conflicting GPIO access using hpd_lock, but the GPIO access from amdgpu_dm_display_resume() remains unguarded. This patch makes sure we use hpd_lock inside amdgpu_dm_display_resume() to avoid race conditions for GPIO access. Signed-off-by: Arindam Nath Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 84995a48ec61..74e32246ff30 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -580,9 +580,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) if (aconnector->mst_port) continue; + mutex_lock(&aconnector->hpd_lock); dc_link_detect(aconnector->dc_link, false); aconnector->dc_sink = NULL; amdgpu_dm_update_connector_after_detect(aconnector); + mutex_unlock(&aconnector->hpd_lock); } /* Force mode set in atomic comit */ -- GitLab From 74c49c7ac14f3a7cc500be959709f3473a6a49e7 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:17:39 -0400 Subject: [PATCH 0424/2898] drm/amdgpu/display: Add calcs code for DCN Bandwidth and scaling calculations for DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/dcn_calc_auto.c | 3629 +++++++++++++++++ .../drm/amd/display/dc/calcs/dcn_calc_auto.h | 37 + .../drm/amd/display/dc/calcs/dcn_calc_math.c | 104 + .../drm/amd/display/dc/calcs/dcn_calc_math.h | 40 + .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1366 +++++++ .../gpu/drm/amd/display/dc/inc/dcn_calcs.h | 629 +++ 6 files changed, 5805 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h create mode 100644 drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c create mode 100644 drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c new file mode 100644 index 000000000000..21b83e403ef2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -0,0 +1,3629 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn_calc_auto.h" +#include "dcn_calc_math.h" + +/*REVISION#247*/ +void scaler_settings_calculation(struct dcn_bw_internal_vars *v) +{ + int k; + /*scaler settings calculation*/ + + /*scale ratio calculation*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->allow_different_hratio_vratio == dcn_bw_yes) { + if (v->source_scan[k] == dcn_bw_hor) { + v->h_ratio[k] = v->viewport_width[k] / v->scaler_rec_out_width[k]; + v->v_ratio[k] = v->viewport_height[k] / v->scaler_recout_height[k]; + } else { + v->h_ratio[k] = v->viewport_height[k] / v->scaler_rec_out_width[k]; + v->v_ratio[k] = v->viewport_width[k] / v->scaler_recout_height[k]; + } + } else { + if (v->source_scan[k] == dcn_bw_hor) { + v->h_ratio[k] = dcn_bw_max2( + v->viewport_width[k] / v->scaler_rec_out_width[k], + v->viewport_height[k] / v->scaler_recout_height[k]); + } else { + v->h_ratio[k] = dcn_bw_max2( + v->viewport_height[k] / v->scaler_rec_out_width[k], + v->viewport_width[k] / v->scaler_recout_height[k]); + } + v->v_ratio[k] = v->h_ratio[k]; + } + if (v->interlace_output[k] == 1.0) { + v->v_ratio[k] = 2.0 * v->v_ratio[k]; + } + if ((v->underscan_output[k] == 1.0)) { + v->h_ratio[k] = v->h_ratio[k] * v->under_scan_factor; + v->v_ratio[k] = v->v_ratio[k] * v->under_scan_factor; + } + } + /*scaler taps calculation*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->h_ratio[k] > 1.0) { + v->acceptable_quality_hta_ps = dcn_bw_min2( + v->max_hscl_taps, + 2.0 * dcn_bw_ceil2(v->h_ratio[k], 1.0)); + } else if (v->h_ratio[k] < 1.0) { + v->acceptable_quality_hta_ps = 4.0; + } else { + v->acceptable_quality_hta_ps = 1.0; + } + if (v->ta_pscalculation == dcn_bw_override) { + v->htaps[k] = v->override_hta_ps[k]; + } else { + v->htaps[k] = v->acceptable_quality_hta_ps; + } + if (v->v_ratio[k] > 1.0) { + v->acceptable_quality_vta_ps = dcn_bw_min2( + v->max_vscl_taps, + 2.0 * dcn_bw_ceil2(v->v_ratio[k], 1.0)); + } else if (v->v_ratio[k] < 1.0) { + v->acceptable_quality_vta_ps = 4.0; + } else { + v->acceptable_quality_vta_ps = 1.0; + } + if (v->ta_pscalculation == dcn_bw_override) { + v->vtaps[k] = v->override_vta_ps[k]; + } else { + v->vtaps[k] = v->acceptable_quality_vta_ps; + } + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + v->vta_pschroma[k] = 0.0; + v->hta_pschroma[k] = 0.0; + } else { + if (v->ta_pscalculation == dcn_bw_override) { + v->vta_pschroma[k] = v->override_vta_pschroma[k]; + v->hta_pschroma[k] = v->override_hta_pschroma[k]; + } else { + v->vta_pschroma[k] = v->acceptable_quality_vta_ps; + v->hta_pschroma[k] = v->acceptable_quality_hta_ps; + } + } + } +} +void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) +{ + int i, j, k; + /*mode support, voltage state and soc configuration*/ + + /*scale ratio support check*/ + + v->scale_ratio_support = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->h_ratio[k] > v->max_hscl_ratio || v->v_ratio[k] > v->max_vscl_ratio + || v->h_ratio[k] > v->htaps[k] || v->v_ratio[k] > v->vtaps[k] + || (v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16 + && (v->h_ratio[k] / 2.0 > v->hta_pschroma[k] + || v->v_ratio[k] / 2.0 + > v->vta_pschroma[k]))) { + v->scale_ratio_support = dcn_bw_no; + } + } + /*source format, pixel format and scan support check*/ + + v->source_format_pixel_and_scan_support = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_surface_mode[k] == dcn_bw_sw_linear + && v->source_scan[k] != dcn_bw_hor) + || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x + || v->source_surface_mode[k] == dcn_bw_sw_var_d + || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) + && v->source_pixel_format[k] != dcn_bw_rgb_sub_64)) { + v->source_format_pixel_and_scan_support = dcn_bw_no; + } + } + /*bandwidth support check*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->source_scan[k] == dcn_bw_hor) { + v->swath_width_ysingle_dpp[k] = v->viewport_width[k]; + } else { + v->swath_width_ysingle_dpp[k] = v->viewport_height[k]; + } + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->byte_per_pixel_in_dety[k] = 8.0; + v->byte_per_pixel_in_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + v->byte_per_pixel_in_dety[k] = 4.0; + v->byte_per_pixel_in_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + v->byte_per_pixel_in_dety[k] = 2.0; + v->byte_per_pixel_in_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->byte_per_pixel_in_dety[k] = 1.0; + v->byte_per_pixel_in_detc[k] = 2.0; + } else { + v->byte_per_pixel_in_dety[k] = 4.0f / 3; + v->byte_per_pixel_in_detc[k] = 8.0f / 3; + } + } + v->total_read_bandwidth_consumed_gbyte_per_second = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->read_bandwidth[k] = v->swath_width_ysingle_dpp[k] + * (dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) * v->v_ratio[k] + + dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0 + * v->v_ratio[k] / 2) + / (v->htotal[k] / v->pixel_clock[k]); + if (v->dcc_enable[k] == dcn_bw_yes) { + v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256); + } + if (v->pte_enable == dcn_bw_yes && v->source_scan[k] != dcn_bw_hor + && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x)) { + v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 64); + } else if (v->pte_enable == dcn_bw_yes && v->source_scan[k] == dcn_bw_hor + && (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32) + && (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x)) { + v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256); + } else if (v->pte_enable == dcn_bw_yes) { + v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 512); + } + v->total_read_bandwidth_consumed_gbyte_per_second = + v->total_read_bandwidth_consumed_gbyte_per_second + + v->read_bandwidth[k] / 1000.0; + } + v->total_write_bandwidth_consumed_gbyte_per_second = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444) { + v->write_bandwidth[k] = v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k]) * 4.0; + } else if (v->output[k] == dcn_bw_writeback) { + v->write_bandwidth[k] = v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k]) * 1.5; + } else { + v->write_bandwidth[k] = 0.0; + } + v->total_write_bandwidth_consumed_gbyte_per_second = + v->total_write_bandwidth_consumed_gbyte_per_second + + v->write_bandwidth[k] / 1000.0; + } + v->total_bandwidth_consumed_gbyte_per_second = + v->total_read_bandwidth_consumed_gbyte_per_second + + v->total_write_bandwidth_consumed_gbyte_per_second; + v->dcc_enabled_in_any_plane = dcn_bw_no; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->dcc_enabled_in_any_plane = dcn_bw_yes; + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + v->return_bw_todcn_per_state = + dcn_bw_min2( + v->return_bus_width * v->dcfclk_per_state[i], + v->fabric_and_dram_bandwidth_per_state[i] * 1000.0 + * v->percent_of_ideal_drambw_received_after_urg_latency + / 100.0); + v->return_bw_per_state[i] = v->return_bw_todcn_per_state; + if (v->dcc_enabled_in_any_plane == dcn_bw_yes + && v->return_bw_todcn_per_state + > v->dcfclk_per_state[i] * v->return_bus_width + / 4.0) { + v->return_bw_per_state[i] = + dcn_bw_min2( + v->return_bw_per_state[i], + v->return_bw_todcn_per_state * 4.0 + * (1.0 + - v->urgent_latency + / ((v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + / (v->return_bw_todcn_per_state + - v->dcfclk_per_state[i] + * v->return_bus_width + / 4.0) + + v->urgent_latency))); + } + v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] + * v->urgent_latency + / (v->return_bw_todcn_per_state * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 + && v->critical_point < 4.0) { + v->return_bw_per_state[i] = + dcn_bw_min2( + v->return_bw_per_state[i], + dcn_bw_pow( + 4.0 + * v->return_bw_todcn_per_state + * (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + * v->return_bus_width + * v->dcfclk_per_state[i] + * v->urgent_latency + / (v->return_bw_todcn_per_state + * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0), + 2)); + } + v->return_bw_todcn_per_state = dcn_bw_min2( + v->return_bus_width * v->dcfclk_per_state[i], + v->fabric_and_dram_bandwidth_per_state[i] * 1000.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes + && v->return_bw_todcn_per_state + > v->dcfclk_per_state[i] * v->return_bus_width + / 4.0) { + v->return_bw_per_state[i] = + dcn_bw_min2( + v->return_bw_per_state[i], + v->return_bw_todcn_per_state * 4.0 + * (1.0 + - v->urgent_latency + / ((v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + / (v->return_bw_todcn_per_state + - v->dcfclk_per_state[i] + * v->return_bus_width + / 4.0) + + v->urgent_latency))); + } + v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] + * v->urgent_latency + / (v->return_bw_todcn_per_state * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 + && v->critical_point < 4.0) { + v->return_bw_per_state[i] = + dcn_bw_min2( + v->return_bw_per_state[i], + dcn_bw_pow( + 4.0 + * v->return_bw_todcn_per_state + * (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + * v->return_bus_width + * v->dcfclk_per_state[i] + * v->urgent_latency + / (v->return_bw_todcn_per_state + * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0), + 2)); + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + if ((v->total_read_bandwidth_consumed_gbyte_per_second * 1000.0 + <= v->return_bw_per_state[i]) + && (v->total_bandwidth_consumed_gbyte_per_second * 1000.0 + <= v->fabric_and_dram_bandwidth_per_state[i] + * 1000.0 + * v->percent_of_ideal_drambw_received_after_urg_latency + / 100.0)) { + v->bandwidth_support[i] = dcn_bw_yes; + } else { + v->bandwidth_support[i] = dcn_bw_no; + } + } + /*writeback latency support check*/ + + v->writeback_latency_support = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444 + && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) + * 4.0 + > (v->writeback_luma_buffer_size + + v->writeback_chroma_buffer_size) + * 1024.0 / v->write_back_latency) { + v->writeback_latency_support = dcn_bw_no; + } else if (v->output[k] == dcn_bw_writeback + && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) + > dcn_bw_min2( + v->writeback_luma_buffer_size, + 2.0 + * v->writeback_chroma_buffer_size) + * 1024.0 / v->write_back_latency) { + v->writeback_latency_support = dcn_bw_no; + } + } + /*re-ordering buffer support check*/ + + for (i = 0; i <= number_of_states_plus_one; i++) { + v->urgent_round_trip_and_out_of_order_latency_per_state[i] = + (v->round_trip_ping_latency_cycles + 32.0) / v->dcfclk_per_state[i] + + v->urgent_out_of_order_return_per_channel + * v->number_of_channels + / v->return_bw_per_state[i]; + if ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 + / v->return_bw_per_state[i] + > v->urgent_round_trip_and_out_of_order_latency_per_state[i]) { + v->rob_support[i] = dcn_bw_yes; + } else { + v->rob_support[i] = dcn_bw_no; + } + } + /*display io support check*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_dp && v->dsc_capability == dcn_bw_yes) { + if (v->output_format[k] == dcn_bw_420) { + v->required_output_bw = v->pixel_clock[k] / 2.0; + } else { + v->required_output_bw = v->pixel_clock[k]; + } + } else if (v->output_format[k] == dcn_bw_420) { + v->required_output_bw = v->pixel_clock[k] * 3.0 / 2.0; + } else { + v->required_output_bw = v->pixel_clock[k] * 3.0; + } + if (v->output[k] == dcn_bw_hdmi) { + v->required_phyclk[k] = v->required_output_bw / 3.0; + } else if (v->output[k] == dcn_bw_dp) { + v->required_phyclk[k] = v->required_output_bw / 4.0; + } else { + v->required_phyclk[k] = 0.0; + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + v->dio_support[i] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->required_phyclk[k] > v->phyclk_per_state[i] + || (v->output[k] == dcn_bw_hdmi + && v->required_phyclk[k] > 600.0)) { + v->dio_support[i] = dcn_bw_no; + } + } + } + /*total available writeback support check*/ + + v->total_number_of_active_writeback = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback) { + v->total_number_of_active_writeback = v->total_number_of_active_writeback + + 1.0; + } + } + if (v->total_number_of_active_writeback <= v->max_num_writeback) { + v->total_available_writeback_support = dcn_bw_yes; + } else { + v->total_available_writeback_support = dcn_bw_no; + } + /*maximum dispclk/dppclk support check*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->h_ratio[k] > 1.0) { + v->pscl_factor[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput * v->h_ratio[k] + / dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); + } else { + v->pscl_factor[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput); + } + if (v->byte_per_pixel_in_detc[k] == 0.0) { + v->pscl_factor_chroma[k] = 0.0; + v->min_dppclk_using_single_dpp[k] = + v->pixel_clock[k] + * dcn_bw_max3( + v->vtaps[k] / 6.0 + * dcn_bw_min2( + 1.0, + v->h_ratio[k]), + v->h_ratio[k] + * v->v_ratio[k] + / v->pscl_factor[k], + 1.0); + } else { + if (v->h_ratio[k] / 2.0 > 1.0) { + v->pscl_factor_chroma[k] = + dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput + * v->h_ratio[k] + / 2.0 + / dcn_bw_ceil2( + v->hta_pschroma[k] + / 6.0, + 1.0)); + } else { + v->pscl_factor_chroma[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput); + } + v->min_dppclk_using_single_dpp[k] = + v->pixel_clock[k] + * dcn_bw_max5( + v->vtaps[k] / 6.0 + * dcn_bw_min2( + 1.0, + v->h_ratio[k]), + v->h_ratio[k] + * v->v_ratio[k] + / v->pscl_factor[k], + v->vta_pschroma[k] / 6.0 + * dcn_bw_min2( + 1.0, + v->h_ratio[k] + / 2.0), + v->h_ratio[k] + * v->v_ratio[k] + / 4.0 + / v->pscl_factor_chroma[k], + 1.0); + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->read256_block_height_y[k] = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->read256_block_height_y[k] = 4.0; + } else { + v->read256_block_height_y[k] = 8.0; + } + v->read256_block_width_y[k] = 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + / v->read256_block_height_y[k]; + v->read256_block_height_c[k] = 0.0; + v->read256_block_width_c[k] = 0.0; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->read256_block_height_y[k] = 1.0; + v->read256_block_height_c[k] = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->read256_block_height_y[k] = 16.0; + v->read256_block_height_c[k] = 8.0; + } else { + v->read256_block_height_y[k] = 8.0; + v->read256_block_height_c[k] = 8.0; + } + v->read256_block_width_y[k] = 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + / v->read256_block_height_y[k]; + v->read256_block_width_c[k] = 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) + / v->read256_block_height_c[k]; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->max_swath_height_y[k] = v->read256_block_height_y[k]; + v->max_swath_height_c[k] = v->read256_block_height_c[k]; + } else { + v->max_swath_height_y[k] = v->read256_block_width_y[k]; + v->max_swath_height_c[k] = v->read256_block_width_c[k]; + } + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear + || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + && (v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_var_s + || v->source_surface_mode[k] + == dcn_bw_sw_var_s_x) + && v->source_scan[k] == dcn_bw_hor)) { + v->min_swath_height_y[k] = v->max_swath_height_y[k]; + } else { + v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; + } + v->min_swath_height_c[k] = v->max_swath_height_c[k]; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->min_swath_height_y[k] = v->max_swath_height_y[k]; + v->min_swath_height_c[k] = v->max_swath_height_c[k]; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 + && v->source_scan[k] == dcn_bw_hor) { + v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed + == dcn_bw_yes) { + v->min_swath_height_c[k] = v->max_swath_height_c[k]; + } else { + v->min_swath_height_c[k] = v->max_swath_height_c[k] / 2.0; + } + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 + && v->source_scan[k] == dcn_bw_hor) { + v->min_swath_height_c[k] = v->max_swath_height_c[k] / 2.0; + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed + == dcn_bw_yes) { + v->min_swath_height_y[k] = v->max_swath_height_y[k]; + } else { + v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; + } + } else { + v->min_swath_height_y[k] = v->max_swath_height_y[k]; + v->min_swath_height_c[k] = v->max_swath_height_c[k]; + } + } + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->maximum_swath_width = 8192.0; + } else { + v->maximum_swath_width = 5120.0; + } + v->number_of_dpp_required_for_det_size = + dcn_bw_ceil2( + v->swath_width_ysingle_dpp[k] + / dcn_bw_min2( + v->maximum_swath_width, + v->det_buffer_size_in_kbyte + * 1024.0 + / 2.0 + / (v->byte_per_pixel_in_dety[k] + * v->min_swath_height_y[k] + + v->byte_per_pixel_in_detc[k] + / 2.0 + * v->min_swath_height_c[k])), + 1.0); + if (v->byte_per_pixel_in_detc[k] == 0.0) { + v->number_of_dpp_required_for_lb_size = dcn_bw_ceil2( + (v->vtaps[k] + + dcn_bw_max2( + dcn_bw_ceil2(v->v_ratio[k], 1.0) + - 2, + 0.0)) + * v->swath_width_ysingle_dpp[k] + / dcn_bw_max2(v->h_ratio[k], 1.0) + * v->lb_bit_per_pixel[k] + / v->line_buffer_size, + 1.0); + } else { + v->number_of_dpp_required_for_lb_size = + dcn_bw_max2( + dcn_bw_ceil2( + (v->vtaps[k] + + dcn_bw_max2( + dcn_bw_ceil2( + v->v_ratio[k], + 1.0) + - 2, + 0.0)) + * v->swath_width_ysingle_dpp[k] + / dcn_bw_max2( + v->h_ratio[k], + 1.0) + * v->lb_bit_per_pixel[k] + / v->line_buffer_size, + 1.0), + dcn_bw_ceil2( + (v->vta_pschroma[k] + + dcn_bw_max2( + dcn_bw_ceil2( + v->v_ratio[k] + / 2.0, + 1.0) + - 2, + 0.0)) + * v->swath_width_ysingle_dpp[k] + / 2.0 + / dcn_bw_max2( + v->h_ratio[k] + / 2.0, + 1.0) + * v->lb_bit_per_pixel[k] + / v->line_buffer_size, + 1.0)); + } + v->number_of_dpp_required_for_det_and_lb_size[k] = dcn_bw_max2( + v->number_of_dpp_required_for_det_size, + v->number_of_dpp_required_for_lb_size); + } + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->total_number_of_active_dpp[i][j] = 0.0; + v->required_dispclk[i][j] = 0.0; + v->dispclk_dppclk_support[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->min_dispclk_using_single_dpp = dcn_bw_max2( + v->pixel_clock[k], + v->min_dppclk_using_single_dpp[k] * (j + 1)) + * (1.0 + v->downspreading / 100.0); + if (v->odm_capability == dcn_bw_yes) { + v->min_dispclk_using_dual_dpp = dcn_bw_max2( + v->pixel_clock[k] / 2.0, + v->min_dppclk_using_single_dpp[k] / 2.0 + * (j + 1)) + * (1.0 + v->downspreading / 100.0); + } else { + v->min_dispclk_using_dual_dpp = dcn_bw_max2( + v->pixel_clock[k], + v->min_dppclk_using_single_dpp[k] / 2.0 + * (j + 1)) + * (1.0 + v->downspreading / 100.0); + } + if (i < number_of_states) { + v->min_dispclk_using_single_dpp = + v->min_dispclk_using_single_dpp + * (1.0 + + v->dispclk_ramping_margin + / 100.0); + v->min_dispclk_using_dual_dpp = + v->min_dispclk_using_dual_dpp + * (1.0 + + v->dispclk_ramping_margin + / 100.0); + } + if (v->min_dispclk_using_single_dpp + <= dcn_bw_min2( + v->max_dispclk[i], + (j + 1) * v->max_dppclk[i]) + && v->number_of_dpp_required_for_det_and_lb_size[k] + <= 1.0) { + v->no_of_dpp[i][j][k] = 1.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_single_dpp); + } else if (v->min_dispclk_using_dual_dpp + <= dcn_bw_min2( + v->max_dispclk[i], + (j + 1) * v->max_dppclk[i])) { + v->no_of_dpp[i][j][k] = 2.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_dual_dpp); + } else { + v->no_of_dpp[i][j][k] = 2.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_dual_dpp); + v->dispclk_dppclk_support[i][j] = dcn_bw_no; + } + v->total_number_of_active_dpp[i][j] = + v->total_number_of_active_dpp[i][j] + + v->no_of_dpp[i][j][k]; + } + if (v->total_number_of_active_dpp[i][j] > v->max_num_dpp) { + v->total_number_of_active_dpp[i][j] = 0.0; + v->required_dispclk[i][j] = 0.0; + v->dispclk_dppclk_support[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->min_dispclk_using_single_dpp = dcn_bw_max2( + v->pixel_clock[k], + v->min_dppclk_using_single_dpp[k] * (j + 1)) + * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_dual_dpp = dcn_bw_max2( + v->pixel_clock[k], + v->min_dppclk_using_single_dpp[k] / 2.0 + * (j + 1)) + * (1.0 + v->downspreading / 100.0); + if (i < number_of_states) { + v->min_dispclk_using_single_dpp = + v->min_dispclk_using_single_dpp + * (1.0 + + v->dispclk_ramping_margin + / 100.0); + v->min_dispclk_using_dual_dpp = + v->min_dispclk_using_dual_dpp + * (1.0 + + v->dispclk_ramping_margin + / 100.0); + } + if (v->number_of_dpp_required_for_det_and_lb_size[k] + <= 1.0) { + v->no_of_dpp[i][j][k] = 1.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_single_dpp); + if (v->min_dispclk_using_single_dpp + > dcn_bw_min2( + v->max_dispclk[i], + (j + 1) + * v->max_dppclk[i])) { + v->dispclk_dppclk_support[i][j] = dcn_bw_no; + } + } else { + v->no_of_dpp[i][j][k] = 2.0; + v->required_dispclk[i][j] = dcn_bw_max2( + v->required_dispclk[i][j], + v->min_dispclk_using_dual_dpp); + if (v->min_dispclk_using_dual_dpp + > dcn_bw_min2( + v->max_dispclk[i], + (j + 1) + * v->max_dppclk[i])) { + v->dispclk_dppclk_support[i][j] = dcn_bw_no; + } + } + v->total_number_of_active_dpp[i][j] = + v->total_number_of_active_dpp[i][j] + + v->no_of_dpp[i][j][k]; + } + } + } + } + /*viewport size check*/ + + v->viewport_size_support = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->number_of_dpp_required_for_det_and_lb_size[k] > 2.0) { + v->viewport_size_support = dcn_bw_no; + } + } + /*total available pipes support check*/ + + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + if (v->total_number_of_active_dpp[i][j] <= v->max_num_dpp) { + v->total_available_pipes_support[i][j] = dcn_bw_yes; + } else { + v->total_available_pipes_support[i][j] = dcn_bw_no; + } + } + } + /*urgent latency support check*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->swath_width_yper_state[i][j][k] = v->swath_width_ysingle_dpp[k] + / v->no_of_dpp[i][j][k]; + v->swath_width_granularity_y = 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + / v->max_swath_height_y[k]; + v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2( + v->swath_width_yper_state[i][j][k] - 1.0, + v->swath_width_granularity_y) + + v->swath_width_granularity_y) + * v->byte_per_pixel_in_dety[k] + * v->max_swath_height_y[k]; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_y = dcn_bw_ceil2( + v->rounded_up_max_swath_size_bytes_y, + 256.0) + 256; + } + if (v->max_swath_height_c[k] > 0.0) { + v->swath_width_granularity_c = + 256.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / v->max_swath_height_c[k]; + } + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2( + v->swath_width_yper_state[i][j][k] / 2.0 - 1.0, + v->swath_width_granularity_c) + + v->swath_width_granularity_c) + * v->byte_per_pixel_in_detc[k] + * v->max_swath_height_c[k]; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2( + v->rounded_up_max_swath_size_bytes_c, + 256.0) + 256; + } + if (v->rounded_up_max_swath_size_bytes_y + + v->rounded_up_max_swath_size_bytes_c + <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { + v->swath_height_yper_state[i][j][k] = + v->max_swath_height_y[k]; + v->swath_height_cper_state[i][j][k] = + v->max_swath_height_c[k]; + } else { + v->swath_height_yper_state[i][j][k] = + v->min_swath_height_y[k]; + v->swath_height_cper_state[i][j][k] = + v->min_swath_height_c[k]; + } + if (v->byte_per_pixel_in_detc[k] == 0.0) { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 + / v->byte_per_pixel_in_dety[k] + / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = 0.0; + } else if (v->swath_height_yper_state[i][j][k] + <= v->swath_height_cper_state[i][j][k]) { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 + / 2.0 / v->byte_per_pixel_in_dety[k] + / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = + v->det_buffer_size_in_kbyte * 1024.0 / 2.0 + / v->byte_per_pixel_in_detc[k] + / (v->swath_width_yper_state[i][j][k] + / 2.0); + } else { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 + * 2.0 / 3.0 / v->byte_per_pixel_in_dety[k] + / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = + v->det_buffer_size_in_kbyte * 1024.0 / 3.0 + / v->byte_per_pixel_in_dety[k] + / (v->swath_width_yper_state[i][j][k] + / 2.0); + } + v->effective_lb_latency_hiding_source_lines_luma = + dcn_bw_min2( + v->max_line_buffer_lines, + dcn_bw_floor2( + v->line_buffer_size + / v->lb_bit_per_pixel[k] + / (v->swath_width_yper_state[i][j][k] + / dcn_bw_max2( + v->h_ratio[k], + 1.0)), + 1.0)) + - (v->vtaps[k] - 1.0); + v->effective_lb_latency_hiding_source_lines_chroma = + dcn_bw_min2( + v->max_line_buffer_lines, + dcn_bw_floor2( + v->line_buffer_size + / v->lb_bit_per_pixel[k] + / (v->swath_width_yper_state[i][j][k] + / 2.0 + / dcn_bw_max2( + v->h_ratio[k] + / 2.0, + 1.0)), + 1.0)) + - (v->vta_pschroma[k] - 1.0); + v->effective_detlb_lines_luma = + dcn_bw_floor2( + v->lines_in_det_luma + + dcn_bw_min2( + v->lines_in_det_luma + * v->required_dispclk[i][j] + * v->byte_per_pixel_in_dety[k] + * v->pscl_factor[k] + / v->return_bw_per_state[i], + v->effective_lb_latency_hiding_source_lines_luma), + v->swath_height_yper_state[i][j][k]); + v->effective_detlb_lines_chroma = + dcn_bw_floor2( + v->lines_in_det_chroma + + dcn_bw_min2( + v->lines_in_det_chroma + * v->required_dispclk[i][j] + * v->byte_per_pixel_in_detc[k] + * v->pscl_factor_chroma[k] + / v->return_bw_per_state[i], + v->effective_lb_latency_hiding_source_lines_chroma), + v->swath_height_cper_state[i][j][k]); + if (v->byte_per_pixel_in_detc[k] == 0.0) { + v->urgent_latency_support_us_per_state[i][j][k] = + v->effective_detlb_lines_luma + * (v->htotal[k] + / v->pixel_clock[k]) + / v->v_ratio[k] + - v->effective_detlb_lines_luma + * v->swath_width_yper_state[i][j][k] + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / (v->return_bw_per_state[i] + / v->no_of_dpp[i][j][k]); + } else { + v->urgent_latency_support_us_per_state[i][j][k] = + dcn_bw_min2( + v->effective_detlb_lines_luma + * (v->htotal[k] + / v->pixel_clock[k]) + / v->v_ratio[k] + - v->effective_detlb_lines_luma + * v->swath_width_yper_state[i][j][k] + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / (v->return_bw_per_state[i] + / v->no_of_dpp[i][j][k]), + v->effective_detlb_lines_chroma + * (v->htotal[k] + / v->pixel_clock[k]) + / (v->v_ratio[k] + / 2.0) + - v->effective_detlb_lines_chroma + * v->swath_width_yper_state[i][j][k] + / 2.0 + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / (v->return_bw_per_state[i] + / v->no_of_dpp[i][j][k])); + } + } + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->urgent_latency_support[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->urgent_latency_support_us_per_state[i][j][k] + < v->urgent_latency / 1.0) { + v->urgent_latency_support[i][j] = dcn_bw_no; + } + } + } + } + /*prefetch check*/ + + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->total_number_of_dcc_active_dpp[i][j] = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->total_number_of_dcc_active_dpp[i][j] = + v->total_number_of_dcc_active_dpp[i][j] + + v->no_of_dpp[i][j][k]; + } + } + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->projected_dcfclk_deep_sleep = 8.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->projected_dcfclk_deep_sleep = dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + v->pixel_clock[k] / 16.0); + if (v->byte_per_pixel_in_detc[k] == 0.0) { + if (v->v_ratio[k] <= 1.0) { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 64.0 + * v->h_ratio[k] + * v->pixel_clock[k] + / v->no_of_dpp[i][j][k]); + } else { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 64.0 + * v->pscl_factor[k] + * v->required_dispclk[i][j] + / (1 + + j)); + } + } else { + if (v->v_ratio[k] <= 1.0) { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 32.0 + * v->h_ratio[k] + * v->pixel_clock[k] + / v->no_of_dpp[i][j][k]); + } else { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 32.0 + * v->pscl_factor[k] + * v->required_dispclk[i][j] + / (1 + + j)); + } + if (v->v_ratio[k] / 2.0 <= 1.0) { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 32.0 + * v->h_ratio[k] + / 2.0 + * v->pixel_clock[k] + / v->no_of_dpp[i][j][k]); + } else { + v->projected_dcfclk_deep_sleep = + dcn_bw_max2( + v->projected_dcfclk_deep_sleep, + 1.1 + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 32.0 + * v->pscl_factor_chroma[k] + * v->required_dispclk[i][j] + / (1 + + j)); + } + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->meta_req_height_y = 8.0 * v->read256_block_height_y[k]; + v->meta_req_width_y = + 64.0 * 256.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / v->meta_req_height_y; + v->meta_surface_width_y = dcn_bw_ceil2( + v->viewport_width[k] / v->no_of_dpp[i][j][k] + - 1.0, + v->meta_req_width_y) + v->meta_req_width_y; + v->meta_surface_height_y = dcn_bw_ceil2( + v->viewport_height[k] - 1.0, + v->meta_req_height_y) + + v->meta_req_height_y; + if (v->pte_enable == dcn_bw_yes) { + v->meta_pte_bytes_per_frame_y = + (dcn_bw_ceil2( + (v->meta_surface_width_y + * v->meta_surface_height_y + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 256.0 + - 4096.0) + / 8.0 + / 4096.0, + 1.0) + 1) * 64.0; + } else { + v->meta_pte_bytes_per_frame_y = 0.0; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->meta_row_bytes_y = + v->meta_surface_width_y + * v->meta_req_height_y + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 256.0; + } else { + v->meta_row_bytes_y = + v->meta_surface_height_y + * v->meta_req_width_y + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / 256.0; + } + } else { + v->meta_pte_bytes_per_frame_y = 0.0; + v->meta_row_bytes_y = 0.0; + } + if (v->pte_enable == dcn_bw_yes) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->macro_tile_block_size_bytes_y = 256.0; + v->macro_tile_block_height_y = 1.0; + } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d_x) { + v->macro_tile_block_size_bytes_y = 4096.0; + v->macro_tile_block_height_y = 4.0 + * v->read256_block_height_y[k]; + } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_block_size_bytes_y = 64.0 * 1024; + v->macro_tile_block_height_y = 16.0 + * v->read256_block_height_y[k]; + } else { + v->macro_tile_block_size_bytes_y = 256.0 * 1024; + v->macro_tile_block_height_y = 32.0 + * v->read256_block_height_y[k]; + } + if (v->macro_tile_block_size_bytes_y <= 65536.0) { + v->data_pte_req_height_y = + v->macro_tile_block_height_y; + } else { + v->data_pte_req_height_y = 16.0 + * v->read256_block_height_y[k]; + } + v->data_pte_req_width_y = + 4096.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + / v->data_pte_req_height_y + * 8; + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->dpte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + * dcn_bw_min2( + 128.0, + dcn_bw_pow( + 2.0, + dcn_bw_floor2( + dcn_bw_log( + v->pte_buffer_size_in_requests + * v->data_pte_req_width_y + / (v->viewport_width[k] + / v->no_of_dpp[i][j][k]), + 2.0), + 1.0))) + - 1.0) + / v->data_pte_req_width_y, + 1.0) + + 1); + } else if (v->source_scan[k] == dcn_bw_hor) { + v->dpte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + - 1.0) + / v->data_pte_req_width_y, + 1.0) + + 1); + } else { + v->dpte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_height[k] + - 1.0) + / v->data_pte_req_height_y, + 1.0) + + 1); + } + } else { + v->dpte_bytes_per_row_y = 0.0; + } + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->meta_req_height_c = 8.0 + * v->read256_block_height_c[k]; + v->meta_req_width_c = + 64.0 * 256.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / v->meta_req_height_c; + v->meta_surface_width_c = + dcn_bw_ceil2( + v->viewport_width[k] + / v->no_of_dpp[i][j][k] + / 2.0 + - 1.0, + v->meta_req_width_c) + + v->meta_req_width_c; + v->meta_surface_height_c = dcn_bw_ceil2( + v->viewport_height[k] / 2.0 - 1.0, + v->meta_req_height_c) + + v->meta_req_height_c; + if (v->pte_enable == dcn_bw_yes) { + v->meta_pte_bytes_per_frame_c = + (dcn_bw_ceil2( + (v->meta_surface_width_c + * v->meta_surface_height_c + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 256.0 + - 4096.0) + / 8.0 + / 4096.0, + 1.0) + 1) + * 64.0; + } else { + v->meta_pte_bytes_per_frame_c = 0.0; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->meta_row_bytes_c = + v->meta_surface_width_c + * v->meta_req_height_c + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 256.0; + } else { + v->meta_row_bytes_c = + v->meta_surface_height_c + * v->meta_req_width_c + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 256.0; + } + } else { + v->meta_pte_bytes_per_frame_c = 0.0; + v->meta_row_bytes_c = 0.0; + } + if (v->pte_enable == dcn_bw_yes) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->macro_tile_block_size_bytes_c = 256.0; + v->macro_tile_block_height_c = 1.0; + } else if (v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d_x) { + v->macro_tile_block_size_bytes_c = 4096.0; + v->macro_tile_block_height_c = + 4.0 + * v->read256_block_height_c[k]; + } else if (v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_block_size_bytes_c = 64.0 + * 1024; + v->macro_tile_block_height_c = + 16.0 + * v->read256_block_height_c[k]; + } else { + v->macro_tile_block_size_bytes_c = 256.0 + * 1024; + v->macro_tile_block_height_c = + 32.0 + * v->read256_block_height_c[k]; + } + v->macro_tile_block_width_c = + v->macro_tile_block_size_bytes_c + / dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / v->macro_tile_block_height_c; + if (v->macro_tile_block_size_bytes_c <= 65536.0) { + v->data_pte_req_height_c = + v->macro_tile_block_height_c; + } else { + v->data_pte_req_height_c = + 16.0 + * v->read256_block_height_c[k]; + } + v->data_pte_req_width_c = + 4096.0 + / dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / v->data_pte_req_height_c + * 8; + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->dpte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + / 2.0 + * dcn_bw_min2( + 128.0, + dcn_bw_pow( + 2.0, + dcn_bw_floor2( + dcn_bw_log( + v->pte_buffer_size_in_requests + * v->data_pte_req_width_c + / (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + / 2.0), + 2.0), + 1.0))) + - 1.0) + / v->data_pte_req_width_c, + 1.0) + + 1); + } else if (v->source_scan[k] == dcn_bw_hor) { + v->dpte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_width[k] + / v->no_of_dpp[i][j][k] + / 2.0 + - 1.0) + / v->data_pte_req_width_c, + 1.0) + + 1); + } else { + v->dpte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_height[k] + / 2.0 + - 1.0) + / v->data_pte_req_height_c, + 1.0) + + 1); + } + } else { + v->dpte_bytes_per_row_c = 0.0; + } + } else { + v->dpte_bytes_per_row_c = 0.0; + v->meta_pte_bytes_per_frame_c = 0.0; + v->meta_row_bytes_c = 0.0; + } + v->dpte_bytes_per_row[k] = v->dpte_bytes_per_row_y + + v->dpte_bytes_per_row_c; + v->meta_pte_bytes_per_frame[k] = v->meta_pte_bytes_per_frame_y + + v->meta_pte_bytes_per_frame_c; + v->meta_row_bytes[k] = v->meta_row_bytes_y + v->meta_row_bytes_c; + v->v_init_y = (v->v_ratio[k] + v->vtaps[k] + 1.0 + + v->interlace_output[k] * 0.5 * v->v_ratio[k]) + / 2.0; + v->prefill_y[k] = dcn_bw_floor2(v->v_init_y, 1.0); + v->max_num_sw_y[k] = + dcn_bw_ceil2( + (v->prefill_y[k] - 1.0) + / v->swath_height_yper_state[i][j][k], + 1.0) + 1; + if (v->prefill_y[k] > 1.0) { + v->max_partial_sw_y = dcn_bw_mod( + (v->prefill_y[k] - 2.0), + v->swath_height_yper_state[i][j][k]); + } else { + v->max_partial_sw_y = + dcn_bw_mod( + (v->prefill_y[k] + + v->swath_height_yper_state[i][j][k] + - 2.0), + v->swath_height_yper_state[i][j][k]); + } + v->max_partial_sw_y = dcn_bw_max2(1.0, v->max_partial_sw_y); + v->prefetch_lines_y[k] = v->max_num_sw_y[k] + * v->swath_height_yper_state[i][j][k] + + v->max_partial_sw_y; + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + v->v_init_c = (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 + + v->interlace_output[k] * 0.5 + * v->v_ratio[k] / 2.0) + / 2.0; + v->prefill_c[k] = dcn_bw_floor2(v->v_init_c, 1.0); + v->max_num_sw_c[k] = + dcn_bw_ceil2( + (v->prefill_c[k] - 1.0) + / v->swath_height_cper_state[i][j][k], + 1.0) + 1; + if (v->prefill_c[k] > 1.0) { + v->max_partial_sw_c = + dcn_bw_mod( + (v->prefill_c[k] + - 2.0), + v->swath_height_cper_state[i][j][k]); + } else { + v->max_partial_sw_c = + dcn_bw_mod( + (v->prefill_c[k] + + v->swath_height_cper_state[i][j][k] + - 2.0), + v->swath_height_cper_state[i][j][k]); + } + v->max_partial_sw_c = dcn_bw_max2(1.0, v->max_partial_sw_c); + v->prefetch_lines_c[k] = v->max_num_sw_c[k] + * v->swath_height_cper_state[i][j][k] + + v->max_partial_sw_c; + } else { + v->prefetch_lines_c[k] = 0.0; + } + v->dst_x_after_scaler = 90.0 * v->pixel_clock[k] + / (v->required_dispclk[i][j] / (j + 1)) + + 42.0 * v->pixel_clock[k] + / v->required_dispclk[i][j]; + if (v->no_of_dpp[i][j][k] > 1.0) { + v->dst_x_after_scaler = v->dst_x_after_scaler + + v->scaler_rec_out_width[k] / 2.0; + } + if (v->output_format[k] == dcn_bw_420) { + v->dst_y_after_scaler = 1.0; + } else { + v->dst_y_after_scaler = 0.0; + } + v->time_calc = 24.0 / v->projected_dcfclk_deep_sleep; + v->v_update_offset[k] = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->total_repeater_delay = v->max_inter_dcn_tile_repeaters + * (2.0 / (v->required_dispclk[i][j] / (j + 1)) + + 3.0 / v->required_dispclk[i][j]); + v->v_update_width[k] = (14.0 / v->projected_dcfclk_deep_sleep + + 12.0 / (v->required_dispclk[i][j] / (j + 1)) + + v->total_repeater_delay) * v->pixel_clock[k]; + v->v_ready_offset[k] = + dcn_bw_max2( + 150.0 + / (v->required_dispclk[i][j] + / (j + + 1)), + v->total_repeater_delay + + 20.0 + / v->projected_dcfclk_deep_sleep + + 10.0 + / (v->required_dispclk[i][j] + / (j + + 1))) + * v->pixel_clock[k]; + v->time_setup = (v->v_update_offset[k] + v->v_update_width[k] + + v->v_ready_offset[k]) / v->pixel_clock[k]; + v->extra_latency = + v->urgent_round_trip_and_out_of_order_latency_per_state[i] + + (v->total_number_of_active_dpp[i][j] + * v->pixel_chunk_size_in_kbyte + + v->total_number_of_dcc_active_dpp[i][j] + * v->meta_chunk_size) + * 1024.0 + / v->return_bw_per_state[i]; + if (v->pte_enable == dcn_bw_yes) { + v->extra_latency = v->extra_latency + + v->total_number_of_active_dpp[i][j] + * v->pte_chunk_size * 1024.0 + / v->return_bw_per_state[i]; + } + if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == dcn_bw_yes) { + v->maximum_vstartup = v->vtotal[k] - v->vactive[k] - 1.0; + } else { + v->maximum_vstartup = v->v_sync_plus_back_porch[k] - 1.0; + } + v->line_times_for_prefetch[k] = v->maximum_vstartup + - v->urgent_latency + / (v->htotal[k] / v->pixel_clock[k]) + - (v->time_calc + v->time_setup) + / (v->htotal[k] / v->pixel_clock[k]) + - (v->dst_y_after_scaler + + v->dst_x_after_scaler + / v->htotal[k]); + v->line_times_for_prefetch[k] = dcn_bw_floor2( + 4.0 * (v->line_times_for_prefetch[k] + 0.125), + 1.0) / 4; + v->prefetch_bw[k] = + (v->meta_pte_bytes_per_frame[k] + + 2.0 * v->meta_row_bytes[k] + + 2.0 * v->dpte_bytes_per_row[k] + + v->prefetch_lines_y[k] + * v->swath_width_yper_state[i][j][k] + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + + v->prefetch_lines_c[k] + * v->swath_width_yper_state[i][j][k] + / 2.0 + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0)) + / (v->line_times_for_prefetch[k] + * v->htotal[k] + / v->pixel_clock[k]); + } + v->bw_available_for_immediate_flip = v->return_bw_per_state[i]; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->bw_available_for_immediate_flip = + v->bw_available_for_immediate_flip + - dcn_bw_max2( + v->read_bandwidth[k], + v->prefetch_bw[k]); + } + v->total_immediate_flip_bytes[k] = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->total_immediate_flip_bytes[k] = + v->total_immediate_flip_bytes[k] + + v->meta_pte_bytes_per_frame[k] + + v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]; + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { + v->time_for_meta_pte_with_immediate_flip = + dcn_bw_max5( + v->meta_pte_bytes_per_frame[k] + / v->prefetch_bw[k], + v->meta_pte_bytes_per_frame[k] + * v->total_immediate_flip_bytes[k] + / (v->bw_available_for_immediate_flip + * (v->meta_pte_bytes_per_frame[k] + + v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k])), + v->extra_latency, + v->urgent_latency, + v->htotal[k] + / v->pixel_clock[k] + / 4.0); + v->time_for_meta_pte_without_immediate_flip = dcn_bw_max3( + v->meta_pte_bytes_per_frame[k] + / v->prefetch_bw[k], + v->extra_latency, + v->htotal[k] / v->pixel_clock[k] / 4.0); + } else { + v->time_for_meta_pte_with_immediate_flip = v->htotal[k] + / v->pixel_clock[k] / 4.0; + v->time_for_meta_pte_without_immediate_flip = v->htotal[k] + / v->pixel_clock[k] / 4.0; + } + if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) { + v->time_for_meta_and_dpte_row_with_immediate_flip = + dcn_bw_max5( + (v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]) + / v->prefetch_bw[k], + (v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]) + * v->total_immediate_flip_bytes[k] + / (v->bw_available_for_immediate_flip + * (v->meta_pte_bytes_per_frame[k] + + v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k])), + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_meta_pte_with_immediate_flip, + v->extra_latency, + 2.0 * v->urgent_latency); + v->time_for_meta_and_dpte_row_without_immediate_flip = + dcn_bw_max3( + (v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]) + / v->prefetch_bw[k], + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_meta_pte_without_immediate_flip, + v->extra_latency); + } else { + v->time_for_meta_and_dpte_row_with_immediate_flip = + dcn_bw_max2( + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_meta_pte_with_immediate_flip, + v->extra_latency + - v->time_for_meta_pte_with_immediate_flip); + v->time_for_meta_and_dpte_row_without_immediate_flip = + dcn_bw_max2( + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_meta_pte_without_immediate_flip, + v->extra_latency + - v->time_for_meta_pte_without_immediate_flip); + } + v->lines_for_meta_pte_with_immediate_flip[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_meta_pte_with_immediate_flip + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->lines_for_meta_pte_without_immediate_flip[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_meta_pte_without_immediate_flip + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->lines_for_meta_and_dpte_row_with_immediate_flip[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_meta_and_dpte_row_with_immediate_flip + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->lines_for_meta_and_dpte_row_without_immediate_flip[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_meta_and_dpte_row_without_immediate_flip + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = + v->line_times_for_prefetch[k] + - v->lines_for_meta_pte_with_immediate_flip[k] + - v->lines_for_meta_and_dpte_row_with_immediate_flip[k]; + v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = + v->line_times_for_prefetch[k] + - v->lines_for_meta_pte_without_immediate_flip[k] + - v->lines_for_meta_and_dpte_row_without_immediate_flip[k]; + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + > 0.0) { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = + v->prefetch_lines_y[k] + / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; + if ((v->swath_height_yper_state[i][j][k] > 4.0)) { + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + - (v->prefill_y[k] - 3.0) / 2.0 + > 0.0) { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = + dcn_bw_max2( + v->v_ratio_pre_ywith_immediate_flip[i][j][k], + (v->max_num_sw_y[k] + * v->swath_height_yper_state[i][j][k]) + / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + - (v->prefill_y[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = + 999999.0; + } + } + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = + v->prefetch_lines_c[k] + / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; + if ((v->swath_height_cper_state[i][j][k] > 4.0)) { + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + - (v->prefill_c[k] - 3.0) / 2.0 + > 0.0) { + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = + dcn_bw_max2( + v->v_ratio_pre_cwith_immediate_flip[i][j][k], + (v->max_num_sw_c[k] + * v->swath_height_cper_state[i][j][k]) + / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + - (v->prefill_c[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = + 999999.0; + } + } + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = + v->no_of_dpp[i][j][k] + * (v->prefetch_lines_y[k] + / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + + v->prefetch_lines_c[k] + / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 2.0) + * v->swath_width_yper_state[i][j][k] + / (v->htotal[k] + / v->pixel_clock[k]); + } else { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = 999999.0; + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = 999999.0; + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = + 999999.0; + } + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + > 0.0) { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = + v->prefetch_lines_y[k] + / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; + if ((v->swath_height_yper_state[i][j][k] > 4.0)) { + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + - (v->prefill_y[k] - 3.0) / 2.0 + > 0.0) { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = + dcn_bw_max2( + v->v_ratio_pre_ywithout_immediate_flip[i][j][k], + (v->max_num_sw_y[k] + * v->swath_height_yper_state[i][j][k]) + / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + - (v->prefill_y[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = + 999999.0; + } + } + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = + v->prefetch_lines_c[k] + / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; + if ((v->swath_height_cper_state[i][j][k] > 4.0)) { + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + - (v->prefill_c[k] - 3.0) / 2.0 + > 0.0) { + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = + dcn_bw_max2( + v->v_ratio_pre_cwithout_immediate_flip[i][j][k], + (v->max_num_sw_c[k] + * v->swath_height_cper_state[i][j][k]) + / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + - (v->prefill_c[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = + 999999.0; + } + } + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = + v->no_of_dpp[i][j][k] + * (v->prefetch_lines_y[k] + / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + * dcn_bw_ceil2( + v->byte_per_pixel_in_dety[k], + 1.0) + + v->prefetch_lines_c[k] + / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip + * dcn_bw_ceil2( + v->byte_per_pixel_in_detc[k], + 2.0) + / 2.0) + * v->swath_width_yper_state[i][j][k] + / (v->htotal[k] + / v->pixel_clock[k]); + } else { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = 999999.0; + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = 999999.0; + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = + 999999.0; + } + } + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip + + dcn_bw_max2( + v->read_bandwidth[k], + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k]) + + dcn_bw_max2( + v->meta_pte_bytes_per_frame[k] + / (v->lines_for_meta_pte_with_immediate_flip[k] + * v->htotal[k] + / v->pixel_clock[k]), + (v->meta_row_bytes[k] + + v->dpte_bytes_per_row[k]) + / (v->lines_for_meta_and_dpte_row_with_immediate_flip[k] + * v->htotal[k] + / v->pixel_clock[k])); + } else { + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip + + dcn_bw_max2( + v->read_bandwidth[k], + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); + } + } + v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = + v->maximum_read_bandwidth_with_prefetch_without_immediate_flip + + dcn_bw_max2( + v->read_bandwidth[k], + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); + } + v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_yes; + if (v->maximum_read_bandwidth_with_prefetch_with_immediate_flip + > v->return_bw_per_state[i]) { + v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->line_times_for_prefetch[k] < 2.0 + || v->lines_for_meta_pte_with_immediate_flip[k] + >= 8.0 + || v->lines_for_meta_and_dpte_row_with_immediate_flip[k] + >= 16.0) { + v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; + } + } + v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_yes; + if (v->maximum_read_bandwidth_with_prefetch_without_immediate_flip + > v->return_bw_per_state[i]) { + v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_no; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->line_times_for_prefetch[k] < 2.0 + || v->lines_for_meta_pte_without_immediate_flip[k] + >= 8.0 + || v->lines_for_meta_and_dpte_row_without_immediate_flip[k] + >= 16.0) { + v->prefetch_supported_without_immediate_flip[i][j] = + dcn_bw_no; + } + } + } + } + for (i = 0; i <= number_of_states_plus_one; i++) { + for (j = 0; j <= 1; j++) { + v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10) + && (v->v_ratio_pre_ywith_immediate_flip[i][j][k] + > 4.0 + || v->v_ratio_pre_cwith_immediate_flip[i][j][k] + > 4.0)) + || ((v->source_pixel_format[k] + == dcn_bw_yuv420_sub_8 + || v->source_pixel_format[k] + == dcn_bw_yuv420_sub_10) + && (v->v_ratio_pre_ywithout_immediate_flip[i][j][k] + > 4.0 + || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] + > 4.0)))) { + v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = + dcn_bw_no; + } + } + v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = dcn_bw_yes; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->v_ratio_pre_ywithout_immediate_flip[i][j][k] > 4.0 + || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] + > 4.0)) { + v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = + dcn_bw_no; + } + } + } + } + /*mode support, voltage state and soc configuration*/ + + for (i = number_of_states_plus_one; i >= 0; i--) { + for (j = 0; j <= 1; j++) { + if (v->scale_ratio_support == dcn_bw_yes + && v->source_format_pixel_and_scan_support == dcn_bw_yes + && v->viewport_size_support == dcn_bw_yes + && v->bandwidth_support[i] == dcn_bw_yes + && v->dio_support[i] == dcn_bw_yes + && v->urgent_latency_support[i][j] == dcn_bw_yes + && v->rob_support[i] == dcn_bw_yes + && v->dispclk_dppclk_support[i][j] == dcn_bw_yes + && v->total_available_pipes_support[i][j] == dcn_bw_yes + && v->total_available_writeback_support == dcn_bw_yes + && v->writeback_latency_support == dcn_bw_yes) { + if (v->prefetch_supported_with_immediate_flip[i][j] == dcn_bw_yes + && v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] + == dcn_bw_yes) { + v->mode_support_with_immediate_flip[i][j] = dcn_bw_yes; + } else { + v->mode_support_with_immediate_flip[i][j] = dcn_bw_no; + } + if (v->prefetch_supported_without_immediate_flip[i][j] == dcn_bw_yes + && v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] + == dcn_bw_yes) { + v->mode_support_without_immediate_flip[i][j] = dcn_bw_yes; + } else { + v->mode_support_without_immediate_flip[i][j] = dcn_bw_no; + } + } else { + v->mode_support_with_immediate_flip[i][j] = dcn_bw_no; + v->mode_support_without_immediate_flip[i][j] = dcn_bw_no; + } + } + } + for (i = number_of_states_plus_one; i >= 0; i--) { + if ((i == number_of_states_plus_one + || v->mode_support_with_immediate_flip[i][1] == dcn_bw_yes + || v->mode_support_with_immediate_flip[i][0] == dcn_bw_yes) + && i >= v->voltage_override_level) { + v->voltage_level_with_immediate_flip = i; + } + } + for (i = number_of_states_plus_one; i >= 0; i--) { + if ((i == number_of_states_plus_one + || v->mode_support_without_immediate_flip[i][1] == dcn_bw_yes + || v->mode_support_without_immediate_flip[i][0] == dcn_bw_yes) + && i >= v->voltage_override_level) { + v->voltage_level_without_immediate_flip = i; + } + } + if (v->voltage_level_with_immediate_flip == number_of_states_plus_one) { + v->immediate_flip_supported = dcn_bw_no; + v->voltage_level = v->voltage_level_without_immediate_flip; + } else { + v->immediate_flip_supported = dcn_bw_yes; + v->voltage_level = v->voltage_level_with_immediate_flip; + } + v->dcfclk = v->dcfclk_per_state[v->voltage_level]; + v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_per_state[v->voltage_level]; + for (j = 0; j <= 1; j++) { + v->required_dispclk_per_ratio[j] = v->required_dispclk[v->voltage_level][j]; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->dpp_per_plane_per_ratio[j][k] = v->no_of_dpp[v->voltage_level][j][k]; + } + v->dispclk_dppclk_support_per_ratio[j] = + v->dispclk_dppclk_support[v->voltage_level][j]; + } + v->max_phyclk = v->phyclk_per_state[v->voltage_level]; +} +void display_pipe_configuration(struct dcn_bw_internal_vars *v) +{ + int j, k; + /*display pipe configuration*/ + + for (j = 0; j <= 1; j++) { + v->total_number_of_active_dpp_per_ratio[j] = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->total_number_of_active_dpp_per_ratio[j] = + v->total_number_of_active_dpp_per_ratio[j] + + v->dpp_per_plane_per_ratio[j][k]; + } + } + if ((v->dispclk_dppclk_support_per_ratio[0] == dcn_bw_yes + && v->dispclk_dppclk_support_per_ratio[1] == dcn_bw_no) + || (v->dispclk_dppclk_support_per_ratio[0] + == v->dispclk_dppclk_support_per_ratio[1] + && (v->total_number_of_active_dpp_per_ratio[0] + < v->total_number_of_active_dpp_per_ratio[1] + || (((v->total_number_of_active_dpp_per_ratio[0] + == v->total_number_of_active_dpp_per_ratio[1]) + && v->required_dispclk_per_ratio[0] + <= 0.5 + * v->required_dispclk_per_ratio[1]))))) { + v->dispclk_dppclk_ratio = 1; + v->final_error_message = v->error_message[0]; + } else { + v->dispclk_dppclk_ratio = 2; + v->final_error_message = v->error_message[1]; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->dpp_per_plane[k] = v->dpp_per_plane_per_ratio[v->dispclk_dppclk_ratio - 1][k]; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->byte_per_pix_dety = 8.0; + v->byte_per_pix_detc = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + v->byte_per_pix_dety = 4.0; + v->byte_per_pix_detc = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + v->byte_per_pix_dety = 2.0; + v->byte_per_pix_detc = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->byte_per_pix_dety = 1.0; + v->byte_per_pix_detc = 2.0; + } else { + v->byte_per_pix_dety = 4.0f / 3; + v->byte_per_pix_detc = 8.0f / 3; + } + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->read256_bytes_block_height_y = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->read256_bytes_block_height_y = 4.0; + } else { + v->read256_bytes_block_height_y = 8.0; + } + v->read256_bytes_block_width_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) + / v->read256_bytes_block_height_y; + v->read256_bytes_block_height_c = 0.0; + v->read256_bytes_block_width_c = 0.0; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->read256_bytes_block_height_y = 1.0; + v->read256_bytes_block_height_c = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->read256_bytes_block_height_y = 16.0; + v->read256_bytes_block_height_c = 8.0; + } else { + v->read256_bytes_block_height_y = 8.0; + v->read256_bytes_block_height_c = 8.0; + } + v->read256_bytes_block_width_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) + / v->read256_bytes_block_height_y; + v->read256_bytes_block_width_c = 256.0 / dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) + / v->read256_bytes_block_height_c; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->maximum_swath_height_y = v->read256_bytes_block_height_y; + v->maximum_swath_height_c = v->read256_bytes_block_height_c; + } else { + v->maximum_swath_height_y = v->read256_bytes_block_width_y; + v->maximum_swath_height_c = v->read256_bytes_block_width_c; + } + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear + || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + && (v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] + == dcn_bw_sw_var_s + || v->source_surface_mode[k] + == dcn_bw_sw_var_s_x) + && v->source_scan[k] == dcn_bw_hor)) { + v->minimum_swath_height_y = v->maximum_swath_height_y; + } else { + v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; + } + v->minimum_swath_height_c = v->maximum_swath_height_c; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->minimum_swath_height_y = v->maximum_swath_height_y; + v->minimum_swath_height_c = v->maximum_swath_height_c; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 + && v->source_scan[k] == dcn_bw_hor) { + v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed + == dcn_bw_yes) { + v->minimum_swath_height_c = v->maximum_swath_height_c; + } else { + v->minimum_swath_height_c = v->maximum_swath_height_c / 2.0; + } + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 + && v->source_scan[k] == dcn_bw_hor) { + v->minimum_swath_height_c = v->maximum_swath_height_c / 2.0; + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed + == dcn_bw_yes) { + v->minimum_swath_height_y = v->maximum_swath_height_y; + } else { + v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; + } + } else { + v->minimum_swath_height_y = v->maximum_swath_height_y; + v->minimum_swath_height_c = v->maximum_swath_height_c; + } + } + if (v->source_scan[k] == dcn_bw_hor) { + v->swath_width = v->viewport_width[k] / v->dpp_per_plane[k]; + } else { + v->swath_width = v->viewport_height[k] / v->dpp_per_plane[k]; + } + v->swath_width_granularity_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) + / v->maximum_swath_height_y; + v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2( + v->swath_width - 1.0, + v->swath_width_granularity_y) + v->swath_width_granularity_y) + * v->byte_per_pix_dety * v->maximum_swath_height_y; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_y = dcn_bw_ceil2( + v->rounded_up_max_swath_size_bytes_y, + 256.0) + 256; + } + if (v->maximum_swath_height_c > 0.0) { + v->swath_width_granularity_c = 256.0 / dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) + / v->maximum_swath_height_c; + } + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2( + v->swath_width / 2.0 - 1.0, + v->swath_width_granularity_c) + v->swath_width_granularity_c) + * v->byte_per_pix_detc * v->maximum_swath_height_c; + if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { + v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2( + v->rounded_up_max_swath_size_bytes_c, + 256.0) + 256; + } + if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c + <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { + v->swath_height_y[k] = v->maximum_swath_height_y; + v->swath_height_c[k] = v->maximum_swath_height_c; + } else { + v->swath_height_y[k] = v->minimum_swath_height_y; + v->swath_height_c[k] = v->minimum_swath_height_c; + } + if (v->swath_height_c[k] == 0.0) { + v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0; + v->det_buffer_size_c[k] = 0.0; + } else if (v->swath_height_y[k] <= v->swath_height_c[k]) { + v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0 / 2.0; + v->det_buffer_size_c[k] = v->det_buffer_size_in_kbyte * 1024.0 / 2.0; + } else { + v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0 * 2.0 / 3.0; + v->det_buffer_size_c[k] = v->det_buffer_size_in_kbyte * 1024.0 / 3.0; + } + } +} +void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation( + struct dcn_bw_internal_vars *v) +{ + int k; + /*dispclk and dppclk calculation*/ + + v->dispclk_with_ramping = 0.0; + v->dispclk_without_ramping = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->h_ratio[k] > 1.0) { + v->pscl_throughput[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput * v->h_ratio[k] + / dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); + } else { + v->pscl_throughput[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput); + } + v->dppclk_using_single_dpp_luma = v->pixel_clock[k] + * dcn_bw_max3( + v->vtaps[k] / 6.0 * dcn_bw_min2(1.0, v->h_ratio[k]), + v->h_ratio[k] * v->v_ratio[k] + / v->pscl_throughput[k], + 1.0); + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->pscl_throughput_chroma[k] = 0.0; + v->dppclk_using_single_dpp = v->dppclk_using_single_dpp_luma; + } else { + if (v->h_ratio[k] > 1.0) { + v->pscl_throughput_chroma[k] = + dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput + * v->h_ratio[k] + / 2.0 + / dcn_bw_ceil2( + v->hta_pschroma[k] + / 6.0, + 1.0)); + } else { + v->pscl_throughput_chroma[k] = dcn_bw_min2( + v->max_dchub_topscl_throughput, + v->max_pscl_tolb_throughput); + } + v->dppclk_using_single_dpp_chroma = + v->pixel_clock[k] + * dcn_bw_max3( + v->vta_pschroma[k] / 6.0 + * dcn_bw_min2( + 1.0, + v->h_ratio[k] + / 2.0), + v->h_ratio[k] + * v->v_ratio[k] + / 4.0 + / v->pscl_throughput_chroma[k], + 1.0); + v->dppclk_using_single_dpp = dcn_bw_max2( + v->dppclk_using_single_dpp_luma, + v->dppclk_using_single_dpp_chroma); + } + if (v->odm_capable == dcn_bw_yes) { + v->dispclk_with_ramping = + dcn_bw_max2( + v->dispclk_with_ramping, + dcn_bw_max2( + v->dppclk_using_single_dpp + / v->dpp_per_plane[k] + * v->dispclk_dppclk_ratio, + v->pixel_clock[k] + / v->dpp_per_plane[k]) + * (1.0 + + v->downspreading + / 100.0) + * (1.0 + + v->dispclk_ramping_margin + / 100.0)); + v->dispclk_without_ramping = dcn_bw_max2( + v->dispclk_without_ramping, + dcn_bw_max2( + v->dppclk_using_single_dpp + / v->dpp_per_plane[k] + * v->dispclk_dppclk_ratio, + v->pixel_clock[k] / v->dpp_per_plane[k]) + * (1.0 + v->downspreading / 100.0)); + } else { + v->dispclk_with_ramping = + dcn_bw_max2( + v->dispclk_with_ramping, + dcn_bw_max2( + v->dppclk_using_single_dpp + / v->dpp_per_plane[k] + * v->dispclk_dppclk_ratio, + v->pixel_clock[k]) + * (1.0 + + v->downspreading + / 100.0) + * (1.0 + + v->dispclk_ramping_margin + / 100.0)); + v->dispclk_without_ramping = dcn_bw_max2( + v->dispclk_without_ramping, + dcn_bw_max2( + v->dppclk_using_single_dpp + / v->dpp_per_plane[k] + * v->dispclk_dppclk_ratio, + v->pixel_clock[k]) + * (1.0 + v->downspreading / 100.0)); + } + } + if (v->dispclk_without_ramping > v->max_dispclk[number_of_states]) { + v->dispclk = v->dispclk_without_ramping; + } else if (v->dispclk_with_ramping > v->max_dispclk[number_of_states]) { + v->dispclk = v->max_dispclk[number_of_states]; + } else { + v->dispclk = v->dispclk_with_ramping; + } + v->dppclk = v->dispclk / v->dispclk_dppclk_ratio; + /*urgent watermark*/ + + v->return_bandwidth_to_dcn = dcn_bw_min2( + v->return_bus_width * v->dcfclk, + v->fabric_and_dram_bandwidth * 1000.0 + * v->percent_of_ideal_drambw_received_after_urg_latency + / 100.0); + v->dcc_enabled_any_plane = dcn_bw_no; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->dcc_enabled_any_plane = dcn_bw_yes; + } + } + v->return_bw = v->return_bandwidth_to_dcn; + if (v->dcc_enabled_any_plane == dcn_bw_yes + && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { + v->return_bw = + dcn_bw_min2( + v->return_bw, + v->return_bandwidth_to_dcn * 4.0 + * (1.0 + - v->urgent_latency + / ((v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + / (v->return_bandwidth_to_dcn + - v->dcfclk + * v->return_bus_width + / 4.0) + + v->urgent_latency))); + } + v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency + / (v->return_bandwidth_to_dcn * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 + && v->critical_compression < 4.0) { + v->return_bw = + dcn_bw_min2( + v->return_bw, + dcn_bw_pow( + 4.0 * v->return_bandwidth_to_dcn + * (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + * v->return_bus_width + * v->dcfclk + * v->urgent_latency + / (v->return_bandwidth_to_dcn + * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0), + 2)); + } + v->return_bandwidth_to_dcn = dcn_bw_min2( + v->return_bus_width * v->dcfclk, + v->fabric_and_dram_bandwidth * 1000.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes + && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { + v->return_bw = + dcn_bw_min2( + v->return_bw, + v->return_bandwidth_to_dcn * 4.0 + * (1.0 + - v->urgent_latency + / ((v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + / (v->return_bandwidth_to_dcn + - v->dcfclk + * v->return_bus_width + / 4.0) + + v->urgent_latency))); + } + v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency + / (v->return_bandwidth_to_dcn * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 + && v->critical_compression < 4.0) { + v->return_bw = + dcn_bw_min2( + v->return_bw, + dcn_bw_pow( + 4.0 * v->return_bandwidth_to_dcn + * (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0 + * v->return_bus_width + * v->dcfclk + * v->urgent_latency + / (v->return_bandwidth_to_dcn + * v->urgent_latency + + (v->rob_buffer_size_in_kbyte + - v->pixel_chunk_size_in_kbyte) + * 1024.0), + 2)); + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->source_scan[k] == dcn_bw_hor) { + v->swath_width_y[k] = v->viewport_width[k] / v->dpp_per_plane[k]; + } else { + v->swath_width_y[k] = v->viewport_height[k] / v->dpp_per_plane[k]; + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->byte_per_pixel_dety[k] = 8.0; + v->byte_per_pixel_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + v->byte_per_pixel_dety[k] = 4.0; + v->byte_per_pixel_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + v->byte_per_pixel_dety[k] = 2.0; + v->byte_per_pixel_detc[k] = 0.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->byte_per_pixel_dety[k] = 1.0; + v->byte_per_pixel_detc[k] = 2.0; + } else { + v->byte_per_pixel_dety[k] = 4.0f / 3; + v->byte_per_pixel_detc[k] = 8.0f / 3; + } + } + v->total_data_read_bandwidth = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->read_bandwidth_plane_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k]; + v->read_bandwidth_plane_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] + * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k] / 2.0; + v->total_data_read_bandwidth = v->total_data_read_bandwidth + + v->read_bandwidth_plane_luma[k] + + v->read_bandwidth_plane_chroma[k]; + } + v->total_active_dpp = 0.0; + v->total_dcc_active_dpp = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->total_active_dpp = v->total_active_dpp + v->dpp_per_plane[k]; + if (v->dcc_enable[k] == dcn_bw_yes) { + v->total_dcc_active_dpp = v->total_dcc_active_dpp + v->dpp_per_plane[k]; + } + } + v->urgent_round_trip_and_out_of_order_latency = (v->round_trip_ping_latency_cycles + 32.0) + / v->dcfclk + + v->urgent_out_of_order_return_per_channel * v->number_of_channels + / v->return_bw; + v->last_pixel_of_line_extra_watermark = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->v_ratio[k] <= 1.0) { + v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] + * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } else { + v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] + / v->pscl_throughput[k] / v->dppclk; + } + v->data_fabric_line_delivery_time_luma = + v->swath_width_y[k] * v->swath_height_y[k] + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + / (v->return_bw * v->read_bandwidth_plane_luma[k] + / v->dpp_per_plane[k] + / v->total_data_read_bandwidth); + v->last_pixel_of_line_extra_watermark = dcn_bw_max2( + v->last_pixel_of_line_extra_watermark, + v->data_fabric_line_delivery_time_luma + - v->display_pipe_line_delivery_time_luma[k]); + if (v->byte_per_pixel_detc[k] == 0.0) { + v->display_pipe_line_delivery_time_chroma[k] = 0.0; + } else { + if (v->v_ratio[k] / 2.0 <= 1.0) { + v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] + / 2.0 * v->dpp_per_plane[k] / (v->h_ratio[k] / 2.0) + / v->pixel_clock[k]; + } else { + v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] + / 2.0 / v->pscl_throughput_chroma[k] / v->dppclk; + } + v->data_fabric_line_delivery_time_chroma = v->swath_width_y[k] / 2.0 + * v->swath_height_c[k] + * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / (v->return_bw * v->read_bandwidth_plane_chroma[k] + / v->dpp_per_plane[k] + / v->total_data_read_bandwidth); + v->last_pixel_of_line_extra_watermark = + dcn_bw_max2( + v->last_pixel_of_line_extra_watermark, + v->data_fabric_line_delivery_time_chroma + - v->display_pipe_line_delivery_time_chroma[k]); + } + } + v->urgent_extra_latency = v->urgent_round_trip_and_out_of_order_latency + + (v->total_active_dpp * v->pixel_chunk_size_in_kbyte + + v->total_dcc_active_dpp * v->meta_chunk_size) * 1024.0 + / v->return_bw; + if (v->pte_enable == dcn_bw_yes) { + v->urgent_extra_latency = v->urgent_extra_latency + + v->total_active_dpp * v->pte_chunk_size * 1024.0 / v->return_bw; + } + v->urgent_watermark = v->urgent_latency + v->last_pixel_of_line_extra_watermark + + v->urgent_extra_latency; + v->ptemeta_urgent_watermark = v->urgent_watermark + 2.0 * v->urgent_latency; + /*nb p-state/dram clock change watermark*/ + + v->dram_clock_change_watermark = v->dram_clock_change_latency + v->urgent_watermark; + v->total_active_writeback = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback) { + v->total_active_writeback = v->total_active_writeback + 1.0; + } + } + if (v->total_active_writeback <= 1.0) { + v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency + + v->write_back_latency; + } else { + v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency + + v->write_back_latency + + v->writeback_chunk_size * 1024.0 / 32.0 / v->socclk; + } + /*stutter efficiency*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->lines_in_dety[k] = v->det_buffer_size_y[k] / v->byte_per_pixel_dety[k] + / v->swath_width_y[k]; + v->lines_in_dety_rounded_down_to_swath[k] = dcn_bw_floor2( + v->lines_in_dety[k], + v->swath_height_y[k]); + v->full_det_buffering_time_y[k] = v->lines_in_dety_rounded_down_to_swath[k] + * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k]; + if (v->byte_per_pixel_detc[k] > 0.0) { + v->lines_in_detc[k] = v->det_buffer_size_c[k] / v->byte_per_pixel_detc[k] + / (v->swath_width_y[k] / 2.0); + v->lines_in_detc_rounded_down_to_swath[k] = dcn_bw_floor2( + v->lines_in_detc[k], + v->swath_height_c[k]); + v->full_det_buffering_time_c[k] = v->lines_in_detc_rounded_down_to_swath[k] + * (v->htotal[k] / v->pixel_clock[k]) + / (v->v_ratio[k] / 2.0); + } else { + v->lines_in_detc[k] = 0.0; + v->lines_in_detc_rounded_down_to_swath[k] = 0.0; + v->full_det_buffering_time_c[k] = 999999.0; + } + } + v->min_full_det_buffering_time = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->full_det_buffering_time_y[k] < v->min_full_det_buffering_time) { + v->min_full_det_buffering_time = v->full_det_buffering_time_y[k]; + v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] + / v->pixel_clock[k]; + } + if (v->full_det_buffering_time_c[k] < v->min_full_det_buffering_time) { + v->min_full_det_buffering_time = v->full_det_buffering_time_c[k]; + v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] + / v->pixel_clock[k]; + } + } + v->average_read_bandwidth_gbyte_per_second = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->average_read_bandwidth_gbyte_per_second = + v->average_read_bandwidth_gbyte_per_second + + v->read_bandwidth_plane_luma[k] + / v->dcc_rate[k] / 1000.0 + + v->read_bandwidth_plane_chroma[k] + / v->dcc_rate[k] / 1000.0; + } else { + v->average_read_bandwidth_gbyte_per_second = + v->average_read_bandwidth_gbyte_per_second + + v->read_bandwidth_plane_luma[k] / 1000.0 + + v->read_bandwidth_plane_chroma[k] + / 1000.0; + } + if (v->dcc_enable[k] == dcn_bw_yes) { + v->average_read_bandwidth_gbyte_per_second = + v->average_read_bandwidth_gbyte_per_second + + v->read_bandwidth_plane_luma[k] / 1000.0 + / 256.0 + + v->read_bandwidth_plane_chroma[k] / 1000.0 + / 256.0; + } + if (v->pte_enable == dcn_bw_yes) { + v->average_read_bandwidth_gbyte_per_second = + v->average_read_bandwidth_gbyte_per_second + + v->read_bandwidth_plane_luma[k] / 1000.0 + / 512.0 + + v->read_bandwidth_plane_chroma[k] / 1000.0 + / 512.0; + } + } + v->part_of_burst_that_fits_in_rob = dcn_bw_min2( + v->min_full_det_buffering_time * v->total_data_read_bandwidth, + v->rob_buffer_size_in_kbyte * 1024.0 * v->total_data_read_bandwidth + / (v->average_read_bandwidth_gbyte_per_second * 1000.0)); + v->stutter_burst_time = v->part_of_burst_that_fits_in_rob + * (v->average_read_bandwidth_gbyte_per_second * 1000.0) + / v->total_data_read_bandwidth / v->return_bw + + (v->min_full_det_buffering_time * v->total_data_read_bandwidth + - v->part_of_burst_that_fits_in_rob) / (v->dcfclk * 64.0); + if (v->total_active_writeback == 0.0) { + v->stutter_efficiency_not_including_vblank = (1.0 + - (v->sr_exit_time + v->stutter_burst_time) + / v->min_full_det_buffering_time) * 100.0; + } else { + v->stutter_efficiency_not_including_vblank = 0.0; + } + v->smallest_vblank = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->synchronized_vblank == dcn_bw_yes || v->number_of_active_planes == 1) { + v->v_blank_time = (v->vtotal[k] - v->vactive[k]) * v->htotal[k] + / v->pixel_clock[k]; + } else { + v->v_blank_time = 0.0; + } + v->smallest_vblank = dcn_bw_min2(v->smallest_vblank, v->v_blank_time); + } + v->stutter_efficiency = (v->stutter_efficiency_not_including_vblank / 100.0 + * (v->frame_time_for_min_full_det_buffering_time - v->smallest_vblank) + + v->smallest_vblank) / v->frame_time_for_min_full_det_buffering_time + * 100.0; + /*dcfclk deep sleep*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->byte_per_pixel_detc[k] > 0.0) { + v->dcfclk_deep_sleep_per_plane[k] = + dcn_bw_max2( + 1.1 * v->swath_width_y[k] + * dcn_bw_ceil2( + v->byte_per_pixel_dety[k], + 1.0) / 32.0 + / v->display_pipe_line_delivery_time_luma[k], + 1.1 * v->swath_width_y[k] / 2.0 + * dcn_bw_ceil2( + v->byte_per_pixel_detc[k], + 2.0) / 32.0 + / v->display_pipe_line_delivery_time_chroma[k]); + } else { + v->dcfclk_deep_sleep_per_plane[k] = 1.1 * v->swath_width_y[k] + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 64.0 + / v->display_pipe_line_delivery_time_luma[k]; + } + v->dcfclk_deep_sleep_per_plane[k] = dcn_bw_max2( + v->dcfclk_deep_sleep_per_plane[k], + v->pixel_clock[k] / 16.0); + } + v->dcf_clk_deep_sleep = 8.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->dcf_clk_deep_sleep = dcn_bw_max2( + v->dcf_clk_deep_sleep, + v->dcfclk_deep_sleep_per_plane[k]); + } + /*stutter watermark*/ + + v->stutter_exit_watermark = v->sr_exit_time + v->last_pixel_of_line_extra_watermark + + v->urgent_extra_latency + 10.0 / v->dcf_clk_deep_sleep; + v->stutter_enter_plus_exit_watermark = v->sr_enter_plus_exit_time + + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency; + /*urgent latency supported*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->effective_det_plus_lb_lines_luma = + dcn_bw_floor2( + v->lines_in_dety[k] + + dcn_bw_min2( + v->lines_in_dety[k] + * v->dppclk + * v->byte_per_pixel_dety[k] + * v->pscl_throughput[k] + / (v->return_bw + / v->dpp_per_plane[k]), + v->effective_lb_latency_hiding_source_lines_luma), + v->swath_height_y[k]); + v->urgent_latency_support_us_luma = v->effective_det_plus_lb_lines_luma + * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] + - v->effective_det_plus_lb_lines_luma * v->swath_width_y[k] + * v->byte_per_pixel_dety[k] + / (v->return_bw / v->dpp_per_plane[k]); + if (v->byte_per_pixel_detc[k] > 0.0) { + v->effective_det_plus_lb_lines_chroma = + dcn_bw_floor2( + v->lines_in_detc[k] + + dcn_bw_min2( + v->lines_in_detc[k] + * v->dppclk + * v->byte_per_pixel_detc[k] + * v->pscl_throughput_chroma[k] + / (v->return_bw + / v->dpp_per_plane[k]), + v->effective_lb_latency_hiding_source_lines_chroma), + v->swath_height_c[k]); + v->urgent_latency_support_us_chroma = v->effective_det_plus_lb_lines_chroma + * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) + - v->effective_det_plus_lb_lines_chroma + * (v->swath_width_y[k] / 2.0) + * v->byte_per_pixel_detc[k] + / (v->return_bw / v->dpp_per_plane[k]); + v->urgent_latency_support_us[k] = dcn_bw_min2( + v->urgent_latency_support_us_luma, + v->urgent_latency_support_us_chroma); + } else { + v->urgent_latency_support_us[k] = v->urgent_latency_support_us_luma; + } + } + v->min_urgent_latency_support_us = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->min_urgent_latency_support_us = dcn_bw_min2( + v->min_urgent_latency_support_us, + v->urgent_latency_support_us[k]); + } + /*non-urgent latency tolerance*/ + + v->non_urgent_latency_tolerance = v->min_urgent_latency_support_us - v->urgent_watermark; + /*prefetch*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 + || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->block_height256_bytes_y = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + v->block_height256_bytes_y = 4.0; + } else { + v->block_height256_bytes_y = 8.0; + } + v->block_height256_bytes_c = 0.0; + } else { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->block_height256_bytes_y = 1.0; + v->block_height256_bytes_c = 1.0; + } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + v->block_height256_bytes_y = 16.0; + v->block_height256_bytes_c = 8.0; + } else { + v->block_height256_bytes_y = 8.0; + v->block_height256_bytes_c = 8.0; + } + } + if (v->dcc_enable[k] == dcn_bw_yes) { + v->meta_request_width_y = 64.0 * 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + / (8.0 * v->block_height256_bytes_y); + v->meta_surf_width_y = dcn_bw_ceil2( + v->swath_width_y[k] - 1.0, + v->meta_request_width_y) + v->meta_request_width_y; + v->meta_surf_height_y = dcn_bw_ceil2( + v->viewport_height[k] - 1.0, + 8.0 * v->block_height256_bytes_y) + + 8.0 * v->block_height256_bytes_y; + if (v->pte_enable == dcn_bw_yes) { + v->meta_pte_bytes_frame_y = + (dcn_bw_ceil2( + (v->meta_surf_width_y + * v->meta_surf_height_y + * dcn_bw_ceil2( + v->byte_per_pixel_dety[k], + 1.0) + / 256.0 - 4096.0) + / 8.0 / 4096.0, + 1.0) + 1) * 64.0; + } else { + v->meta_pte_bytes_frame_y = 0.0; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->meta_row_byte_y = v->meta_surf_width_y * 8.0 + * v->block_height256_bytes_y + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; + } else { + v->meta_row_byte_y = v->meta_surf_height_y * v->meta_request_width_y + * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; + } + } else { + v->meta_pte_bytes_frame_y = 0.0; + v->meta_row_byte_y = 0.0; + } + if (v->pte_enable == dcn_bw_yes) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->macro_tile_size_byte_y = 256.0; + v->macro_tile_height_y = 1.0; + } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { + v->macro_tile_size_byte_y = 4096.0; + v->macro_tile_height_y = 4.0 * v->block_height256_bytes_y; + } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_size_byte_y = 64.0 * 1024; + v->macro_tile_height_y = 16.0 * v->block_height256_bytes_y; + } else { + v->macro_tile_size_byte_y = 256.0 * 1024; + v->macro_tile_height_y = 32.0 * v->block_height256_bytes_y; + } + if (v->macro_tile_size_byte_y <= 65536.0) { + v->pixel_pte_req_height_y = v->macro_tile_height_y; + } else { + v->pixel_pte_req_height_y = 16.0 * v->block_height256_bytes_y; + } + v->pixel_pte_req_width_y = 4096.0 / dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + / v->pixel_pte_req_height_y * 8; + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->pixel_pte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->swath_width_y[k] + * dcn_bw_min2( + 128.0, + dcn_bw_pow( + 2.0, + dcn_bw_floor2( + dcn_bw_log( + v->pte_buffer_size_in_requests + * v->pixel_pte_req_width_y + / v->swath_width_y[k], + 2.0), + 1.0))) + - 1.0) + / v->pixel_pte_req_width_y, + 1.0) + 1); + } else if (v->source_scan[k] == dcn_bw_hor) { + v->pixel_pte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->swath_width_y[k] + - 1.0) + / v->pixel_pte_req_width_y, + 1.0) + 1); + } else { + v->pixel_pte_bytes_per_row_y = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_height[k] + - 1.0) + / v->pixel_pte_req_height_y, + 1.0) + 1); + } + } else { + v->pixel_pte_bytes_per_row_y = 0.0; + } + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + if (v->dcc_enable[k] == dcn_bw_yes) { + v->meta_request_width_c = 64.0 * 256.0 + / dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / (8.0 * v->block_height256_bytes_c); + v->meta_surf_width_c = dcn_bw_ceil2( + v->swath_width_y[k] / 2.0 - 1.0, + v->meta_request_width_c) + v->meta_request_width_c; + v->meta_surf_height_c = dcn_bw_ceil2( + v->viewport_height[k] / 2.0 - 1.0, + 8.0 * v->block_height256_bytes_c) + + 8.0 * v->block_height256_bytes_c; + if (v->pte_enable == dcn_bw_yes) { + v->meta_pte_bytes_frame_c = + (dcn_bw_ceil2( + (v->meta_surf_width_c + * v->meta_surf_height_c + * dcn_bw_ceil2( + v->byte_per_pixel_detc[k], + 2.0) + / 256.0 + - 4096.0) + / 8.0 + / 4096.0, + 1.0) + 1) * 64.0; + } else { + v->meta_pte_bytes_frame_c = 0.0; + } + if (v->source_scan[k] == dcn_bw_hor) { + v->meta_row_byte_c = v->meta_surf_width_c * 8.0 + * v->block_height256_bytes_c + * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / 256.0; + } else { + v->meta_row_byte_c = v->meta_surf_height_c + * v->meta_request_width_c + * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / 256.0; + } + } else { + v->meta_pte_bytes_frame_c = 0.0; + v->meta_row_byte_c = 0.0; + } + if (v->pte_enable == dcn_bw_yes) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->macro_tile_size_bytes_c = 256.0; + v->macro_tile_height_c = 1.0; + } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d + || v->source_surface_mode[k] + == dcn_bw_sw_4_kb_d_x) { + v->macro_tile_size_bytes_c = 4096.0; + v->macro_tile_height_c = 4.0 * v->block_height256_bytes_c; + } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d + || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t + || v->source_surface_mode[k] + == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_size_bytes_c = 64.0 * 1024; + v->macro_tile_height_c = 16.0 * v->block_height256_bytes_c; + } else { + v->macro_tile_size_bytes_c = 256.0 * 1024; + v->macro_tile_height_c = 32.0 * v->block_height256_bytes_c; + } + if (v->macro_tile_size_bytes_c <= 65536.0) { + v->pixel_pte_req_height_c = v->macro_tile_height_c; + } else { + v->pixel_pte_req_height_c = 16.0 + * v->block_height256_bytes_c; + } + v->pixel_pte_req_width_c = 4096.0 + / dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) + / v->pixel_pte_req_height_c * 8; + if (v->source_surface_mode[k] == dcn_bw_sw_linear) { + v->pixel_pte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->swath_width_y[k] + / 2.0 + * dcn_bw_min2( + 128.0, + dcn_bw_pow( + 2.0, + dcn_bw_floor2( + dcn_bw_log( + v->pte_buffer_size_in_requests + * v->pixel_pte_req_width_c + / (v->swath_width_y[k] + / 2.0), + 2.0), + 1.0))) + - 1.0) + / v->pixel_pte_req_width_c, + 1.0) + 1); + } else if (v->source_scan[k] == dcn_bw_hor) { + v->pixel_pte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->swath_width_y[k] + / 2.0 + - 1.0) + / v->pixel_pte_req_width_c, + 1.0) + 1); + } else { + v->pixel_pte_bytes_per_row_c = + 64.0 + * (dcn_bw_ceil2( + (v->viewport_height[k] + / 2.0 + - 1.0) + / v->pixel_pte_req_height_c, + 1.0) + 1); + } + } else { + v->pixel_pte_bytes_per_row_c = 0.0; + } + } else { + v->pixel_pte_bytes_per_row_c = 0.0; + v->meta_pte_bytes_frame_c = 0.0; + v->meta_row_byte_c = 0.0; + } + v->pixel_pte_bytes_per_row[k] = v->pixel_pte_bytes_per_row_y + + v->pixel_pte_bytes_per_row_c; + v->meta_pte_bytes_frame[k] = v->meta_pte_bytes_frame_y + v->meta_pte_bytes_frame_c; + v->meta_row_byte[k] = v->meta_row_byte_y + v->meta_row_byte_c; + v->v_init_pre_fill_y[k] = dcn_bw_floor2( + (v->v_ratio[k] + v->vtaps[k] + 1.0 + + v->interlace_output[k] * 0.5 * v->v_ratio[k]) + / 2.0, + 1.0); + v->max_num_swath_y[k] = dcn_bw_ceil2( + (v->v_init_pre_fill_y[k] - 1.0) / v->swath_height_y[k], + 1.0) + 1; + if (v->v_init_pre_fill_y[k] > 1.0) { + v->max_partial_swath_y = dcn_bw_mod( + (v->v_init_pre_fill_y[k] - 2.0), + v->swath_height_y[k]); + } else { + v->max_partial_swath_y = dcn_bw_mod( + (v->v_init_pre_fill_y[k] + v->swath_height_y[k] - 2.0), + v->swath_height_y[k]); + } + v->max_partial_swath_y = dcn_bw_max2(1.0, v->max_partial_swath_y); + v->prefetch_source_lines_y[k] = v->max_num_swath_y[k] * v->swath_height_y[k] + + v->max_partial_swath_y; + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 + && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + v->v_init_pre_fill_c[k] = dcn_bw_floor2( + (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 + + v->interlace_output[k] * 0.5 + * v->v_ratio[k] / 2.0) + / 2.0, + 1.0); + v->max_num_swath_c[k] = dcn_bw_ceil2( + (v->v_init_pre_fill_c[k] - 1.0) / v->swath_height_c[k], + 1.0) + 1; + if (v->v_init_pre_fill_c[k] > 1.0) { + v->max_partial_swath_c = dcn_bw_mod( + (v->v_init_pre_fill_c[k] - 2.0), + v->swath_height_c[k]); + } else { + v->max_partial_swath_c = dcn_bw_mod( + (v->v_init_pre_fill_c[k] + v->swath_height_c[k] + - 2.0), + v->swath_height_c[k]); + } + v->max_partial_swath_c = dcn_bw_max2(1.0, v->max_partial_swath_c); + } else { + v->max_num_swath_c[k] = 0.0; + v->max_partial_swath_c = 0.0; + } + v->prefetch_source_lines_c[k] = v->max_num_swath_c[k] * v->swath_height_c[k] + + v->max_partial_swath_c; + } + v->t_calc = 24.0 / v->dcf_clk_deep_sleep; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == dcn_bw_yes) { + v->max_vstartup_lines[k] = v->vtotal[k] - v->vactive[k] - 1.0; + } else { + v->max_vstartup_lines[k] = v->v_sync_plus_back_porch[k] - 1.0; + } + } + v->next_prefetch_mode = 0.0; + do { + v->v_startup_lines = 13.0; + do { + v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = + dcn_bw_yes; + v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = + dcn_bw_no; + v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = + dcn_bw_no; + v->v_ratio_prefetch_more_than4 = dcn_bw_no; + v->destination_line_times_for_prefetch_less_than2 = dcn_bw_no; + v->prefetch_mode = v->next_prefetch_mode; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->dstx_after_scaler = 90.0 * v->pixel_clock[k] / v->dppclk + + 42.0 * v->pixel_clock[k] / v->dispclk; + if (v->dpp_per_plane[k] > 1.0) { + v->dstx_after_scaler = v->dstx_after_scaler + + v->scaler_rec_out_width[k] / 2.0; + } + if (v->output_format[k] == dcn_bw_420) { + v->dsty_after_scaler = 1.0; + } else { + v->dsty_after_scaler = 0.0; + } + v->v_update_offset_pix = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->total_repeater_delay_time = v->max_inter_dcn_tile_repeaters + * (2.0 / v->dppclk + 3.0 / v->dispclk); + v->v_update_width_pix = (14.0 / v->dcf_clk_deep_sleep + + 12.0 / v->dppclk + v->total_repeater_delay_time) + * v->pixel_clock[k]; + v->v_ready_offset_pix = dcn_bw_max2( + 150.0 / v->dppclk, + v->total_repeater_delay_time + + 20.0 / v->dcf_clk_deep_sleep + + 10.0 / v->dppclk) + * v->pixel_clock[k]; + v->t_setup = (v->v_update_offset_pix + v->v_update_width_pix + + v->v_ready_offset_pix) / v->pixel_clock[k]; + v->v_startup[k] = dcn_bw_min2( + v->v_startup_lines, + v->max_vstartup_lines[k]); + if (v->prefetch_mode == 0.0) { + v->t_wait = dcn_bw_max3( + v->dram_clock_change_latency + + v->urgent_latency, + v->sr_enter_plus_exit_time, + v->urgent_latency); + } else if (v->prefetch_mode == 1.0) { + v->t_wait = dcn_bw_max2( + v->sr_enter_plus_exit_time, + v->urgent_latency); + } else { + v->t_wait = v->urgent_latency; + } + v->destination_lines_for_prefetch[k] = + dcn_bw_floor2( + 4.0 + * (v->v_startup[k] + - v->t_wait + / (v->htotal[k] + / v->pixel_clock[k]) + - (v->t_calc + + v->t_setup) + / (v->htotal[k] + / v->pixel_clock[k]) + - (v->dsty_after_scaler + + v->dstx_after_scaler + / v->htotal[k]) + + 0.125), + 1.0) / 4; + if (v->destination_lines_for_prefetch[k] > 0.0) { + v->prefetch_bandwidth[k] = + (v->meta_pte_bytes_frame[k] + + 2.0 * v->meta_row_byte[k] + + 2.0 + * v->pixel_pte_bytes_per_row[k] + + v->prefetch_source_lines_y[k] + * v->swath_width_y[k] + * dcn_bw_ceil2( + v->byte_per_pixel_dety[k], + 1.0) + + v->prefetch_source_lines_c[k] + * v->swath_width_y[k] + / 2.0 + * dcn_bw_ceil2( + v->byte_per_pixel_detc[k], + 2.0)) + / (v->destination_lines_for_prefetch[k] + * v->htotal[k] + / v->pixel_clock[k]); + } else { + v->prefetch_bandwidth[k] = 999999.0; + } + } + v->bandwidth_available_for_immediate_flip = v->return_bw; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->bandwidth_available_for_immediate_flip = + v->bandwidth_available_for_immediate_flip + - dcn_bw_max2( + v->read_bandwidth_plane_luma[k] + + v->read_bandwidth_plane_chroma[k], + v->prefetch_bandwidth[k]); + } + v->tot_immediate_flip_bytes = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->immediate_flip_supported == dcn_bw_yes + && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] + != dcn_bw_yuv420_sub_10)) { + v->tot_immediate_flip_bytes = v->tot_immediate_flip_bytes + + v->meta_pte_bytes_frame[k] + + v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]; + } + } + v->max_rd_bandwidth = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { + if (v->immediate_flip_supported == dcn_bw_yes + && (v->source_pixel_format[k] + != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] + != dcn_bw_yuv420_sub_10)) { + v->time_for_fetching_meta_pte = + dcn_bw_max5( + v->meta_pte_bytes_frame[k] + / v->prefetch_bandwidth[k], + v->meta_pte_bytes_frame[k] + * v->tot_immediate_flip_bytes + / (v->bandwidth_available_for_immediate_flip + * (v->meta_pte_bytes_frame[k] + + v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k])), + v->urgent_extra_latency, + v->urgent_latency, + v->htotal[k] + / v->pixel_clock[k] + / 4.0); + } else { + v->time_for_fetching_meta_pte = + dcn_bw_max3( + v->meta_pte_bytes_frame[k] + / v->prefetch_bandwidth[k], + v->urgent_extra_latency, + v->htotal[k] + / v->pixel_clock[k] + / 4.0); + } + } else { + v->time_for_fetching_meta_pte = v->htotal[k] + / v->pixel_clock[k] / 4.0; + } + v->destination_lines_to_request_vm_inv_blank[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_fetching_meta_pte + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + if ((v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes)) { + if (v->immediate_flip_supported == dcn_bw_yes + && (v->source_pixel_format[k] + != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] + != dcn_bw_yuv420_sub_10)) { + v->time_for_fetching_row_in_vblank = + dcn_bw_max5( + (v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]) + / v->prefetch_bandwidth[k], + (v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]) + * v->tot_immediate_flip_bytes + / (v->bandwidth_available_for_immediate_flip + * (v->meta_pte_bytes_frame[k] + + v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k])), + v->urgent_extra_latency, + 2.0 + * v->urgent_latency, + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_fetching_meta_pte); + } else { + v->time_for_fetching_row_in_vblank = + dcn_bw_max3( + (v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]) + / v->prefetch_bandwidth[k], + v->urgent_extra_latency, + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_fetching_meta_pte); + } + } else { + v->time_for_fetching_row_in_vblank = + dcn_bw_max2( + v->urgent_extra_latency + - v->time_for_fetching_meta_pte, + v->htotal[k] + / v->pixel_clock[k] + - v->time_for_fetching_meta_pte); + } + v->destination_lines_to_request_row_in_vblank[k] = + dcn_bw_floor2( + 4.0 + * (v->time_for_fetching_row_in_vblank + / (v->htotal[k] + / v->pixel_clock[k]) + + 0.125), + 1.0) / 4; + v->lines_to_request_prefetch_pixel_data = + v->destination_lines_for_prefetch[k] + - v->destination_lines_to_request_vm_inv_blank[k] + - v->destination_lines_to_request_row_in_vblank[k]; + if (v->lines_to_request_prefetch_pixel_data > 0.0) { + v->v_ratio_prefetch_y[k] = v->prefetch_source_lines_y[k] + / v->lines_to_request_prefetch_pixel_data; + if ((v->swath_height_y[k] > 4.0)) { + if (v->lines_to_request_prefetch_pixel_data + > (v->v_init_pre_fill_y[k] - 3.0) + / 2.0) { + v->v_ratio_prefetch_y[k] = + dcn_bw_max2( + v->v_ratio_prefetch_y[k], + v->max_num_swath_y[k] + * v->swath_height_y[k] + / (v->lines_to_request_prefetch_pixel_data + - (v->v_init_pre_fill_y[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_prefetch_y[k] = 999999.0; + } + } + } else { + v->v_ratio_prefetch_y[k] = 999999.0; + } + v->v_ratio_prefetch_y[k] = dcn_bw_max2(v->v_ratio_prefetch_y[k], 1.0); + if (v->lines_to_request_prefetch_pixel_data > 0.0) { + v->v_ratio_prefetch_c[k] = v->prefetch_source_lines_c[k] + / v->lines_to_request_prefetch_pixel_data; + if ((v->swath_height_c[k] > 4.0)) { + if (v->lines_to_request_prefetch_pixel_data + > (v->v_init_pre_fill_c[k] - 3.0) + / 2.0) { + v->v_ratio_prefetch_c[k] = + dcn_bw_max2( + v->v_ratio_prefetch_c[k], + v->max_num_swath_c[k] + * v->swath_height_c[k] + / (v->lines_to_request_prefetch_pixel_data + - (v->v_init_pre_fill_c[k] + - 3.0) + / 2.0)); + } else { + v->v_ratio_prefetch_c[k] = 999999.0; + } + } + } else { + v->v_ratio_prefetch_c[k] = 999999.0; + } + v->v_ratio_prefetch_c[k] = dcn_bw_max2(v->v_ratio_prefetch_c[k], 1.0); + if (v->lines_to_request_prefetch_pixel_data > 0.0) { + v->required_prefetch_pix_data_bw = + v->dpp_per_plane[k] + * (v->prefetch_source_lines_y[k] + / v->lines_to_request_prefetch_pixel_data + * dcn_bw_ceil2( + v->byte_per_pixel_dety[k], + 1.0) + + v->prefetch_source_lines_c[k] + / v->lines_to_request_prefetch_pixel_data + * dcn_bw_ceil2( + v->byte_per_pixel_detc[k], + 2.0) + / 2.0) + * v->swath_width_y[k] + / (v->htotal[k] + / v->pixel_clock[k]); + } else { + v->required_prefetch_pix_data_bw = 999999.0; + } + v->max_rd_bandwidth = + v->max_rd_bandwidth + + dcn_bw_max2( + v->read_bandwidth_plane_luma[k] + + v->read_bandwidth_plane_chroma[k], + v->required_prefetch_pix_data_bw); + if (v->immediate_flip_supported == dcn_bw_yes + && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 + && v->source_pixel_format[k] + != dcn_bw_yuv420_sub_10)) { + v->max_rd_bandwidth = + v->max_rd_bandwidth + + dcn_bw_max2( + v->meta_pte_bytes_frame[k] + / (v->destination_lines_to_request_vm_inv_blank[k] + * v->htotal[k] + / v->pixel_clock[k]), + (v->meta_row_byte[k] + + v->pixel_pte_bytes_per_row[k]) + / (v->destination_lines_to_request_row_in_vblank[k] + * v->htotal[k] + / v->pixel_clock[k])); + } + if (v->v_ratio_prefetch_y[k] > 4.0 + || v->v_ratio_prefetch_c[k] > 4.0) { + v->v_ratio_prefetch_more_than4 = dcn_bw_yes; + } + if (v->destination_lines_for_prefetch[k] < 2.0) { + v->destination_line_times_for_prefetch_less_than2 = + dcn_bw_yes; + } + if (v->max_vstartup_lines[k] > v->v_startup_lines) { + if (v->required_prefetch_pix_data_bw + > (v->read_bandwidth_plane_luma[k] + + v->read_bandwidth_plane_chroma[k])) { + v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = + dcn_bw_no; + } + if (v->v_ratio_prefetch_y[k] > 4.0 + || v->v_ratio_prefetch_c[k] > 4.0) { + v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = + dcn_bw_yes; + } + if (v->destination_lines_for_prefetch[k] < 2.0) { + v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = + dcn_bw_yes; + } + } + } + if (v->max_rd_bandwidth <= v->return_bw + && v->v_ratio_prefetch_more_than4 == dcn_bw_no + && v->destination_line_times_for_prefetch_less_than2 + == dcn_bw_no) { + v->prefetch_mode_supported = dcn_bw_yes; + } else { + v->prefetch_mode_supported = dcn_bw_no; + } + v->v_startup_lines = v->v_startup_lines + 1.0; + } while (!(v->prefetch_mode_supported == dcn_bw_yes + || (v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw + == dcn_bw_yes + && v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 + == dcn_bw_no + && v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 + == dcn_bw_no))); + v->next_prefetch_mode = v->next_prefetch_mode + 1.0; + } while (!(v->prefetch_mode_supported == dcn_bw_yes || v->prefetch_mode == 2.0)); + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->v_ratio_prefetch_y[k] <= 1.0) { + v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] + * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } else { + v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] + / v->pscl_throughput[k] / v->dppclk; + } + if (v->byte_per_pixel_detc[k] == 0.0) { + v->display_pipe_line_delivery_time_chroma_prefetch[k] = 0.0; + } else { + if (v->v_ratio_prefetch_c[k] <= 1.0) { + v->display_pipe_line_delivery_time_chroma_prefetch[k] = + v->swath_width_y[k] * v->dpp_per_plane[k] + / v->h_ratio[k] / v->pixel_clock[k]; + } else { + v->display_pipe_line_delivery_time_chroma_prefetch[k] = + v->swath_width_y[k] / v->pscl_throughput[k] + / v->dppclk; + } + } + } + /*min ttuv_blank*/ + + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->prefetch_mode == 0.0) { + v->allow_dram_clock_change_during_vblank[k] = dcn_bw_yes; + v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_yes; + v->min_ttuv_blank[k] = v->t_calc + + dcn_bw_max3( + v->dram_clock_change_watermark, + v->stutter_enter_plus_exit_watermark, + v->urgent_watermark); + } else if (v->prefetch_mode == 1.0) { + v->allow_dram_clock_change_during_vblank[k] = dcn_bw_no; + v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_yes; + v->min_ttuv_blank[k] = v->t_calc + + dcn_bw_max2( + v->stutter_enter_plus_exit_watermark, + v->urgent_watermark); + } else { + v->allow_dram_clock_change_during_vblank[k] = dcn_bw_no; + v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_no; + v->min_ttuv_blank[k] = v->t_calc + v->urgent_watermark; + } + } + /*nb p-state/dram clock change support*/ + + v->active_dp_ps = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->active_dp_ps = v->active_dp_ps + v->dpp_per_plane[k]; + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + v->lb_latency_hiding_source_lines_y = + dcn_bw_min2( + v->max_line_buffer_lines, + dcn_bw_floor2( + v->line_buffer_size + / v->lb_bit_per_pixel[k] + / (v->swath_width_y[k] + / dcn_bw_max2( + v->h_ratio[k], + 1.0)), + 1.0)) - (v->vtaps[k] - 1.0); + v->lb_latency_hiding_source_lines_c = + dcn_bw_min2( + v->max_line_buffer_lines, + dcn_bw_floor2( + v->line_buffer_size + / v->lb_bit_per_pixel[k] + / (v->swath_width_y[k] + / 2.0 + / dcn_bw_max2( + v->h_ratio[k] + / 2.0, + 1.0)), + 1.0)) - (v->vta_pschroma[k] - 1.0); + v->effective_lb_latency_hiding_y = v->lb_latency_hiding_source_lines_y + / v->v_ratio[k] * (v->htotal[k] / v->pixel_clock[k]); + v->effective_lb_latency_hiding_c = v->lb_latency_hiding_source_lines_c + / (v->v_ratio[k] / 2.0) * (v->htotal[k] / v->pixel_clock[k]); + if (v->swath_width_y[k] > 2.0 * v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_y = v->dpp_output_buffer_pixels + / v->swath_width_y[k]; + } else if (v->swath_width_y[k] > v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_y = 0.5; + } else { + v->dpp_output_buffer_lines_y = 1.0; + } + if (v->swath_width_y[k] / 2.0 > 2.0 * v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_c = v->dpp_output_buffer_pixels + / (v->swath_width_y[k] / 2.0); + } else if (v->swath_width_y[k] / 2.0 > v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_c = 0.5; + } else { + v->dpp_output_buffer_lines_c = 1.0; + } + v->dppopp_buffering_y = (v->htotal[k] / v->pixel_clock[k]) + * (v->dpp_output_buffer_lines_y + v->opp_output_buffer_lines); + v->max_det_buffering_time_y = v->full_det_buffering_time_y[k] + + (v->lines_in_dety[k] - v->lines_in_dety_rounded_down_to_swath[k]) + / v->swath_height_y[k] + * (v->htotal[k] / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_y = v->dppopp_buffering_y + + v->effective_lb_latency_hiding_y + v->max_det_buffering_time_y + - v->dram_clock_change_watermark; + if (v->active_dp_ps > 1.0) { + v->active_dram_clock_change_latency_margin_y = + v->active_dram_clock_change_latency_margin_y + - (1.0 - 1.0 / (v->active_dp_ps - 1.0)) + * v->swath_height_y[k] + * (v->htotal[k] + / v->pixel_clock[k]); + } + if (v->byte_per_pixel_detc[k] > 0.0) { + v->dppopp_buffering_c = + (v->htotal[k] / v->pixel_clock[k]) + * (v->dpp_output_buffer_lines_c + + v->opp_output_buffer_lines); + v->max_det_buffering_time_c = v->full_det_buffering_time_c[k] + + (v->lines_in_detc[k] + - v->lines_in_detc_rounded_down_to_swath[k]) + / v->swath_height_c[k] + * (v->htotal[k] / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_c = v->dppopp_buffering_c + + v->effective_lb_latency_hiding_c + + v->max_det_buffering_time_c + - v->dram_clock_change_watermark; + if (v->active_dp_ps > 1.0) { + v->active_dram_clock_change_latency_margin_c = + v->active_dram_clock_change_latency_margin_c + - (1.0 + - 1.0 + / (v->active_dp_ps + - 1.0)) + * v->swath_height_c[k] + * (v->htotal[k] + / v->pixel_clock[k]); + } + v->active_dram_clock_change_latency_margin[k] = dcn_bw_min2( + v->active_dram_clock_change_latency_margin_y, + v->active_dram_clock_change_latency_margin_c); + } else { + v->active_dram_clock_change_latency_margin[k] = + v->active_dram_clock_change_latency_margin_y; + } + if (v->output_format[k] == dcn_bw_444) { + v->writeback_dram_clock_change_latency_margin = + (v->writeback_luma_buffer_size + + v->writeback_chroma_buffer_size) * 1024.0 + / (v->scaler_rec_out_width[k] + / (v->htotal[k] + / v->pixel_clock[k]) + * 4.0) + - v->writeback_dram_clock_change_watermark; + } else { + v->writeback_dram_clock_change_latency_margin = dcn_bw_min2( + v->writeback_luma_buffer_size, + 2.0 * v->writeback_chroma_buffer_size) * 1024.0 + / (v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k])) + - v->writeback_dram_clock_change_watermark; + } + if (v->output[k] == dcn_bw_writeback) { + v->active_dram_clock_change_latency_margin[k] = dcn_bw_min2( + v->active_dram_clock_change_latency_margin[k], + v->writeback_dram_clock_change_latency_margin); + } + } + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->allow_dram_clock_change_during_vblank[k] == dcn_bw_yes) { + v->v_blank_dram_clock_change_latency_margin[k] = (v->vtotal[k] + - v->scaler_recout_height[k]) + * (v->htotal[k] / v->pixel_clock[k]) + - dcn_bw_max2( + v->dram_clock_change_watermark, + v->writeback_dram_clock_change_watermark); + } else { + v->v_blank_dram_clock_change_latency_margin[k] = 0.0; + } + } + v->min_active_dram_clock_change_margin = 999999.0; + v->v_blank_of_min_active_dram_clock_change_margin = 999999.0; + v->second_min_active_dram_clock_change_margin = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->active_dram_clock_change_latency_margin[k] + < v->min_active_dram_clock_change_margin) { + v->second_min_active_dram_clock_change_margin = + v->min_active_dram_clock_change_margin; + v->min_active_dram_clock_change_margin = + v->active_dram_clock_change_latency_margin[k]; + v->v_blank_of_min_active_dram_clock_change_margin = + v->v_blank_dram_clock_change_latency_margin[k]; + } else if (v->active_dram_clock_change_latency_margin[k] + < v->second_min_active_dram_clock_change_margin) { + v->second_min_active_dram_clock_change_margin = + v->active_dram_clock_change_latency_margin[k]; + } + } + v->min_vblank_dram_clock_change_margin = 999999.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->min_vblank_dram_clock_change_margin + > v->v_blank_dram_clock_change_latency_margin[k]) { + v->min_vblank_dram_clock_change_margin = + v->v_blank_dram_clock_change_latency_margin[k]; + } + } + if (v->synchronized_vblank == dcn_bw_yes || v->number_of_active_planes == 1) { + v->dram_clock_change_margin = dcn_bw_max2( + v->min_active_dram_clock_change_margin, + v->min_vblank_dram_clock_change_margin); + } else if (v->v_blank_of_min_active_dram_clock_change_margin + > v->min_active_dram_clock_change_margin) { + v->dram_clock_change_margin = dcn_bw_min2( + v->second_min_active_dram_clock_change_margin, + v->v_blank_of_min_active_dram_clock_change_margin); + } else { + v->dram_clock_change_margin = v->min_active_dram_clock_change_margin; + } + if (v->min_active_dram_clock_change_margin > 0.0) { + v->dram_clock_change_support = dcn_bw_supported_in_v_active; + } else if (v->dram_clock_change_margin > 0.0) { + v->dram_clock_change_support = dcn_bw_supported_in_v_blank; + } else { + v->dram_clock_change_support = dcn_bw_not_supported; + } + /*maximum bandwidth used*/ + + v->wr_bandwidth = 0.0; + for (k = 0; k <= v->number_of_active_planes - 1; k++) { + if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444) { + v->wr_bandwidth = v->wr_bandwidth + + v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k]) * 4.0; + } else if (v->output[k] == dcn_bw_writeback) { + v->wr_bandwidth = v->wr_bandwidth + + v->scaler_rec_out_width[k] + / (v->htotal[k] / v->pixel_clock[k]) * 1.5; + } + } + v->max_used_bw = v->max_rd_bandwidth + v->wr_bandwidth; +} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h new file mode 100644 index 000000000000..03f06f682ead --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN_CALC_AUTO_H_ +#define _DCN_CALC_AUTO_H_ + +#include "dcn_calcs.h" + +void scaler_settings_calculation(struct dcn_bw_internal_vars *v); +void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v); +void display_pipe_configuration(struct dcn_bw_internal_vars *v); +void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation( + struct dcn_bw_internal_vars *v); + +#endif /* _DCN_CALC_AUTO_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c new file mode 100644 index 000000000000..a18474437990 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -0,0 +1,104 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dcn_calc_math.h" + +float dcn_bw_mod(const float arg1, const float arg2) +{ + return arg1 - arg1 * ((int) (arg1 / arg2)); +} + +float dcn_bw_min2(const float arg1, const float arg2) +{ + return arg1 < arg2 ? arg1 : arg2; +} + +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} +float dcn_bw_max2(const float arg1, const float arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + +float dcn_bw_floor2(const float arg, const float significance) +{ + if (significance == 0) + return 0; + return ((int) (arg / significance)) * significance; +} + +float dcn_bw_ceil2(const float arg, const float significance) +{ + float flr = dcn_bw_floor2(arg, significance); + if (significance == 0) + return 0; + return flr + 0.00001 >= arg ? arg : flr + significance; +} + +float dcn_bw_max3(float v1, float v2, float v3) +{ + return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); +} + +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) +{ + return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); +} + +float dcn_bw_pow(float a, float exp) +{ + float temp; + /*ASSERT(exp == (int)exp);*/ + if ((int)exp == 0) + return 1; + temp = dcn_bw_pow(a, (int)(exp / 2)); + if (((int)exp % 2) == 0) { + return temp * temp; + } else { + if ((int)exp > 0) + return a * temp * temp; + else + return (temp * temp) / a; + } +} + +float dcn_bw_log(float a, float b) +{ + int * const exp_ptr = (int *)(&a); + int x = *exp_ptr; + const int log_2 = ((x >> 23) & 255) - 128; + x &= ~(255 << 23); + x += 127 << 23; + *exp_ptr = x; + + a = ((-1.0f / 3) * a + 2) * a - 2.0f / 3; + + if (b > 2.00001 || b < 1.99999) + return (a + log_2) / dcn_bw_log(b, 2); + else + return (a + log_2); +} diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h new file mode 100644 index 000000000000..f46ab0e24ca1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN_CALC_MATH_H_ +#define _DCN_CALC_MATH_H_ + +float dcn_bw_mod(const float arg1, const float arg2); +float dcn_bw_min2(const float arg1, const float arg2); +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2); +float dcn_bw_max2(const float arg1, const float arg2); +float dcn_bw_floor2(const float arg, const float significance); +float dcn_bw_ceil2(const float arg, const float significance); +float dcn_bw_max3(float v1, float v2, float v3); +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5); +float dcn_bw_pow(float a, float exp); +float dcn_bw_log(float a, float b); + +#endif /* _DCN_CALC_MATH_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c new file mode 100644 index 000000000000..eb81edf3afa9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -0,0 +1,1366 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn_calcs.h" +#include "dcn_calc_auto.h" +#include "dc.h" +#include "core_dc.h" +#include "dal_asic_id.h" + +#include "resource.h" +#include "dcn10/dcn10_resource.h" +#include "dcn_calc_math.h" + +/* Defaults from spreadsheet rev#247 */ +const struct dcn_soc_bounding_box dcn10_soc_defaults = { + .sr_exit_time = 17, /*us*/ /*update based on HW Request for 118773*/ + .sr_enter_plus_exit_time = 19, /*us*/ + .urgent_latency = 4, /*us*/ + .write_back_latency = 12, /*us*/ + .percent_of_ideal_drambw_received_after_urg_latency = 80, /*%*/ + .max_request_size = 256, /*bytes*/ + .dcfclkv_max0p9 = 600, /*MHz*/ + .dcfclkv_nom0p8 = 600, /*MHz*/ + .dcfclkv_mid0p72 = 300, /*MHz*/ + .dcfclkv_min0p65 = 300, /*MHz*/ + .max_dispclk_vmax0p9 = 1086, /*MHz*/ + .max_dispclk_vnom0p8 = 661, /*MHz*/ + .max_dispclk_vmid0p72 = 608, /*MHz*/ + .max_dispclk_vmin0p65 = 608, /*MHz*/ + .max_dppclk_vmax0p9 = 661, /*MHz*/ + .max_dppclk_vnom0p8 = 661, /*MHz*/ + .max_dppclk_vmid0p72 = 435, /*MHz*/ + .max_dppclk_vmin0p65 = 435, /*MHz*/ + .socclk = 208, /*MHz*/ + .fabric_and_dram_bandwidth_vmax0p9 = 38.4f, /*GB/s*/ + .fabric_and_dram_bandwidth_vnom0p8 = 34.1f, /*GB/s*/ + .fabric_and_dram_bandwidth_vmid0p72 = 29.8f, /*GB/s*/ + .fabric_and_dram_bandwidth_vmin0p65 = 12.8f, /*GB/s*/ + .phyclkv_max0p9 = 810, /*MHz*/ + .phyclkv_nom0p8 = 810, /*MHz*/ + .phyclkv_mid0p72 = 540, /*MHz*/ + .phyclkv_min0p65 = 540, /*MHz*/ + .downspreading = 0.5f, /*%*/ + .round_trip_ping_latency_cycles = 128, /*DCFCLK Cycles*/ + .urgent_out_of_order_return_per_channel = 256, /*bytes*/ + .number_of_channels = 2, + .vmm_page_size = 4096, /*bytes*/ + .dram_clock_change_latency = 17, /*us*/ + .return_bus_width = 64, /*bytes*/ +}; + +const struct dcn_ip_params dcn10_ip_defaults = { + .rob_buffer_size_in_kbyte = 64, + .det_buffer_size_in_kbyte = 164, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_in_kbyte = 8, + .pte_enable = dcn_bw_yes, + .pte_chunk_size = 2, /*kbytes*/ + .meta_chunk_size = 2, /*kbytes*/ + .writeback_chunk_size = 2, /*kbytes*/ + .odm_capability = dcn_bw_no, + .dsc_capability = dcn_bw_no, + .line_buffer_size = 589824, /*bit*/ + .max_line_buffer_lines = 12, + .is_line_buffer_bpp_fixed = dcn_bw_no, + .line_buffer_fixed_bpp = dcn_bw_na, + .writeback_luma_buffer_size = 12, /*kbytes*/ + .writeback_chroma_buffer_size = 8, /*kbytes*/ + .max_num_dpp = 4, + .max_num_writeback = 2, + .max_dchub_topscl_throughput = 4, /*pixels/dppclk*/ + .max_pscl_tolb_throughput = 2, /*pixels/dppclk*/ + .max_lb_tovscl_throughput = 4, /*pixels/dppclk*/ + .max_vscl_tohscl_throughput = 4, /*pixels/dppclk*/ + .max_hscl_ratio = 4, + .max_vscl_ratio = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .pte_buffer_size_in_requests = 42, + .dispclk_ramping_margin = 1, /*%*/ + .under_scan_factor = 1.11f, + .max_inter_dcn_tile_repeaters = 8, + .can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = dcn_bw_no, + .bug_forcing_luma_and_chroma_request_to_same_size_fixed = dcn_bw_no, + .dcfclk_cstate_latency = 10 /*TODO clone of something else? sr_enter_plus_exit_time?*/ +}; + +static enum dcn_bw_defs tl_sw_mode_to_bw_defs(enum swizzle_mode_values sw_mode) +{ + switch (sw_mode) { + case DC_SW_LINEAR: + return dcn_bw_sw_linear; + case DC_SW_4KB_S: + return dcn_bw_sw_4_kb_s; + case DC_SW_4KB_D: + return dcn_bw_sw_4_kb_d; + case DC_SW_64KB_S: + return dcn_bw_sw_64_kb_s; + case DC_SW_64KB_D: + return dcn_bw_sw_64_kb_d; + case DC_SW_VAR_S: + return dcn_bw_sw_var_s; + case DC_SW_VAR_D: + return dcn_bw_sw_var_d; + case DC_SW_64KB_S_T: + return dcn_bw_sw_64_kb_s_t; + case DC_SW_64KB_D_T: + return dcn_bw_sw_64_kb_d_t; + case DC_SW_4KB_S_X: + return dcn_bw_sw_4_kb_s_x; + case DC_SW_4KB_D_X: + return dcn_bw_sw_4_kb_d_x; + case DC_SW_64KB_S_X: + return dcn_bw_sw_64_kb_s_x; + case DC_SW_64KB_D_X: + return dcn_bw_sw_64_kb_d_x; + case DC_SW_VAR_S_X: + return dcn_bw_sw_var_s_x; + case DC_SW_VAR_D_X: + return dcn_bw_sw_var_d_x; + case DC_SW_256B_S: + case DC_SW_256_D: + case DC_SW_256_R: + case DC_SW_4KB_R: + case DC_SW_64KB_R: + case DC_SW_VAR_R: + case DC_SW_4KB_R_X: + case DC_SW_64KB_R_X: + case DC_SW_VAR_R_X: + default: + BREAK_TO_DEBUGGER(); /*not in formula*/ + return dcn_bw_sw_4_kb_s; + } +} + +static int tl_lb_bpp_to_int(enum lb_pixel_depth depth) +{ + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + return 18; + case LB_PIXEL_DEPTH_24BPP: + return 24; + case LB_PIXEL_DEPTH_30BPP: + return 30; + case LB_PIXEL_DEPTH_36BPP: + return 36; + default: + return 30; + } +} + +static enum dcn_bw_defs tl_pixel_format_to_bw_defs(enum surface_pixel_format format) +{ + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + return dcn_bw_rgb_sub_16; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + return dcn_bw_rgb_sub_32; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + return dcn_bw_rgb_sub_64; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + return dcn_bw_yuv420_sub_8; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + return dcn_bw_yuv420_sub_10; + default: + return dcn_bw_rgb_sub_32; + } +} + +static void pipe_ctx_to_e2e_pipe_params ( + const struct pipe_ctx *pipe, + struct _vcs_dpi_display_pipe_params_st *input) +{ + input->src.is_hsplit = false; + if (pipe->top_pipe != NULL && pipe->top_pipe->surface == pipe->surface) + input->src.is_hsplit = true; + else if (pipe->bottom_pipe != NULL && pipe->bottom_pipe->surface == pipe->surface) + input->src.is_hsplit = true; + + input->src.dcc = pipe->surface->public.dcc.enable; + input->src.dcc_rate = 1; + input->src.meta_pitch = pipe->surface->public.dcc.grph.meta_pitch; + input->src.source_scan = dm_horz; + input->src.sw_mode = pipe->surface->public.tiling_info.gfx9.swizzle; + + input->src.viewport_width = pipe->scl_data.viewport.width; + input->src.viewport_height = pipe->scl_data.viewport.height; + input->src.data_pitch = pipe->scl_data.viewport.width; + input->src.data_pitch_c = pipe->scl_data.viewport.width; + input->src.cur0_src_width = 128; /* TODO: Cursor calcs, not curently stored */ + input->src.cur0_bpp = 32; + + switch (pipe->surface->public.tiling_info.gfx9.swizzle) { + /* for 4/8/16 high tiles */ + case DC_SW_LINEAR: + input->src.is_display_sw = 1; + input->src.macro_tile_size = dm_4k_tile; + break; + case DC_SW_4KB_S: + case DC_SW_4KB_S_X: + input->src.is_display_sw = 0; + input->src.macro_tile_size = dm_4k_tile; + break; + case DC_SW_64KB_S: + case DC_SW_64KB_S_X: + input->src.is_display_sw = 0; + input->src.macro_tile_size = dm_64k_tile; + break; + case DC_SW_VAR_S: + case DC_SW_VAR_S_X: + input->src.is_display_sw = 0; + input->src.macro_tile_size = dm_256k_tile; + break; + + /* For 64bpp 2 high tiles */ + case DC_SW_4KB_D: + case DC_SW_4KB_D_X: + input->src.is_display_sw = 1; + input->src.macro_tile_size = dm_4k_tile; + break; + case DC_SW_64KB_D: + case DC_SW_64KB_D_X: + input->src.is_display_sw = 1; + input->src.macro_tile_size = dm_64k_tile; + break; + case DC_SW_VAR_D: + case DC_SW_VAR_D_X: + input->src.is_display_sw = 1; + input->src.macro_tile_size = dm_256k_tile; + break; + + /* Unsupported swizzle modes for dcn */ + case DC_SW_256B_S: + default: + ASSERT(0); /* Not supported */ + break; + } + + switch (pipe->surface->public.rotation) { + case ROTATION_ANGLE_0: + case ROTATION_ANGLE_180: + input->src.source_scan = dm_horz; + break; + case ROTATION_ANGLE_90: + case ROTATION_ANGLE_270: + input->src.source_scan = dm_vert; + break; + default: + ASSERT(0); /* Not supported */ + break; + } + + /* TODO: Fix pixel format mappings */ + switch (pipe->surface->public.format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + input->src.source_format = dm_420_8; + input->src.viewport_width_c = input->src.viewport_width / 2; + input->src.viewport_height_c = input->src.viewport_height / 2; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + input->src.source_format = dm_420_10; + input->src.viewport_width_c = input->src.viewport_width / 2; + input->src.viewport_height_c = input->src.viewport_height / 2; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + input->src.source_format = dm_444_64; + input->src.viewport_width_c = input->src.viewport_width; + input->src.viewport_height_c = input->src.viewport_height; + break; + default: + input->src.source_format = dm_444_32; + input->src.viewport_width_c = input->src.viewport_width; + input->src.viewport_height_c = input->src.viewport_height; + break; + } + + input->scale_taps.htaps = pipe->scl_data.taps.h_taps; + input->scale_ratio_depth.hscl_ratio = pipe->scl_data.ratios.horz.value/4294967296.0; + input->scale_ratio_depth.vscl_ratio = pipe->scl_data.ratios.vert.value/4294967296.0; + input->scale_ratio_depth.vinit = pipe->scl_data.inits.v.value/4294967296.0; + if (input->scale_ratio_depth.vinit < 1.0) + input->scale_ratio_depth.vinit = 1; + input->scale_taps.vtaps = pipe->scl_data.taps.v_taps; + input->scale_taps.vtaps_c = pipe->scl_data.taps.v_taps_c; + input->scale_taps.htaps_c = pipe->scl_data.taps.h_taps_c; + input->scale_ratio_depth.hscl_ratio_c = pipe->scl_data.ratios.horz_c.value/4294967296.0; + input->scale_ratio_depth.vscl_ratio_c = pipe->scl_data.ratios.vert_c.value/4294967296.0; + input->scale_ratio_depth.vinit_c = pipe->scl_data.inits.v_c.value/4294967296.0; + if (input->scale_ratio_depth.vinit_c < 1.0) + input->scale_ratio_depth.vinit_c = 1; + switch (pipe->scl_data.lb_params.depth) { + case LB_PIXEL_DEPTH_30BPP: + input->scale_ratio_depth.lb_depth = 30; break; + case LB_PIXEL_DEPTH_36BPP: + input->scale_ratio_depth.lb_depth = 36; break; + default: + input->scale_ratio_depth.lb_depth = 24; break; + } + + + input->dest.vactive = pipe->stream->public.timing.v_addressable; + + input->dest.recout_width = pipe->scl_data.recout.width; + input->dest.recout_height = pipe->scl_data.recout.height; + + input->dest.full_recout_width = pipe->scl_data.recout.width; + input->dest.full_recout_height = pipe->scl_data.recout.height; + + input->dest.htotal = pipe->stream->public.timing.h_total; + input->dest.hblank_start = input->dest.htotal - pipe->stream->public.timing.h_front_porch; + input->dest.hblank_end = input->dest.hblank_start + - pipe->stream->public.timing.h_addressable + - pipe->stream->public.timing.h_border_left + - pipe->stream->public.timing.h_border_right; + + input->dest.vtotal = pipe->stream->public.timing.v_total; + input->dest.vblank_start = input->dest.vtotal - pipe->stream->public.timing.v_front_porch; + input->dest.vblank_end = input->dest.vblank_start + - pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_border_bottom + - pipe->stream->public.timing.v_border_top; + + input->dest.vsync_plus_back_porch = pipe->stream->public.timing.v_total + - pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_front_porch; + input->dest.pixel_rate_mhz = pipe->stream->public.timing.pix_clk_khz/1000.0; + input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; + input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; + input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; + input->dest.vupdate_width = pipe->pipe_dlg_param.vupdate_width; + +} + +static void dcn_bw_calc_rq_dlg_ttu( + const struct core_dc *dc, + const struct dcn_bw_internal_vars *v, + struct pipe_ctx *pipe) +{ + struct display_mode_lib *dml = (struct display_mode_lib *)(&dc->dml); + struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &pipe->dlg_regs; + struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &pipe->ttu_regs; + struct _vcs_dpi_display_rq_regs_st *rq_regs = &pipe->rq_regs; + struct _vcs_dpi_display_rq_params_st rq_param = {0}; + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; + struct _vcs_dpi_display_e2e_pipe_params_st input = { { { 0 } } }; + float total_active_bw = 0; + float total_prefetch_bw = 0; + int total_flip_bytes = 0; + int i; + + for (i = 0; i < number_of_planes; i++) { + total_active_bw += v->read_bandwidth[i]; + total_prefetch_bw += v->prefetch_bandwidth[i]; + total_flip_bytes += v->total_immediate_flip_bytes[i]; + } + dlg_sys_param.total_flip_bw = v->return_bw - dcn_bw_max2(total_active_bw, total_prefetch_bw); + if (dlg_sys_param.total_flip_bw < 0.0) + dlg_sys_param.total_flip_bw = 0; + + dlg_sys_param.t_mclk_wm_us = v->dram_clock_change_watermark; + dlg_sys_param.t_sr_wm_us = v->stutter_enter_plus_exit_watermark; + dlg_sys_param.t_urg_wm_us = v->urgent_watermark; + dlg_sys_param.t_extra_us = v->urgent_extra_latency; + dlg_sys_param.deepsleep_dcfclk_mhz = v->dcf_clk_deep_sleep; + dlg_sys_param.total_flip_bytes = total_flip_bytes; + + pipe_ctx_to_e2e_pipe_params(pipe, &input.pipe); + input.clks_cfg.dcfclk_mhz = v->dcfclk; + input.clks_cfg.dispclk_mhz = v->dispclk; + input.clks_cfg.dppclk_mhz = v->dppclk; + input.clks_cfg.refclk_mhz = dc->res_pool->ref_clock_inKhz/1000; + input.clks_cfg.socclk_mhz = v->socclk; + input.clks_cfg.voltage = v->voltage_level; +// dc->dml.logger = pool->base.logger; + + /*todo: soc->sr_enter_plus_exit_time??*/ + dlg_sys_param.t_srx_delay_us = dc->dcn_ip.dcfclk_cstate_latency / v->dcf_clk_deep_sleep; + + dml_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); + extract_rq_regs(dml, rq_regs, rq_param); + dml_rq_dlg_get_dlg_params( + dml, + dlg_regs, + ttu_regs, + rq_param.dlg, + dlg_sys_param, + input, + true, + true, + v->pte_enable == dcn_bw_yes, + pipe->surface->public.flip_immediate); +} + +static void dcn_dml_wm_override( + const struct dcn_bw_internal_vars *v, + struct display_mode_lib *dml, + struct validate_context *context, + const struct resource_pool *pool) +{ + int i, in_idx, active_count; + + struct _vcs_dpi_display_e2e_pipe_params_st *input = dm_alloc(pool->pipe_count * + sizeof(struct _vcs_dpi_display_e2e_pipe_params_st)); + struct wm { + double urgent; + struct _vcs_dpi_cstate_pstate_watermarks_st cpstate; + double pte_meta_urgent; + } a; + + + for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream || !pipe->surface) + continue; + + input[in_idx].clks_cfg.dcfclk_mhz = v->dcfclk; + input[in_idx].clks_cfg.dispclk_mhz = v->dispclk; + input[in_idx].clks_cfg.dppclk_mhz = v->dppclk; + input[in_idx].clks_cfg.refclk_mhz = pool->ref_clock_inKhz / 1000; + input[in_idx].clks_cfg.socclk_mhz = v->socclk; + input[in_idx].clks_cfg.voltage = v->voltage_level; + pipe_ctx_to_e2e_pipe_params(pipe, &input[in_idx].pipe); + dml_rq_dlg_get_rq_reg( + dml, + &pipe->rq_regs, + input[in_idx].pipe.src); + in_idx++; + } + active_count = in_idx; + + a.urgent = dml_wm_urgent_e2e(dml, input, active_count); + a.cpstate = dml_wm_cstate_pstate_e2e(dml, input, active_count); + a.pte_meta_urgent = dml_wm_pte_meta_urgent(dml, a.urgent); + + context->watermarks.a.cstate_pstate.cstate_exit_ns = + a.cpstate.cstate_exit_us * 1000; + context->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + a.cpstate.cstate_enter_plus_exit_us * 1000; + context->watermarks.a.cstate_pstate.pstate_change_ns = + a.cpstate.pstate_change_us * 1000; + context->watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; + context->watermarks.a.urgent_ns = a.urgent * 1000; + context->watermarks.b = context->watermarks.a; + context->watermarks.c = context->watermarks.a; + context->watermarks.d = context->watermarks.a; + + + for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream || !pipe->surface) + continue; + + dml_rq_dlg_get_dlg_reg(dml, + &pipe->dlg_regs, + &pipe->ttu_regs, + input, active_count, + in_idx, + true, + true, + v->pte_enable == dcn_bw_yes, + pipe->surface->public.flip_immediate); + in_idx++; + } + dm_free(input); +} + +static void split_stream_across_pipes( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct pipe_ctx *primary_pipe, + struct pipe_ctx *secondary_pipe) +{ + if (!primary_pipe->surface) + return; + + secondary_pipe->stream = primary_pipe->stream; + secondary_pipe->tg = primary_pipe->tg; + + secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; + secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; + secondary_pipe->xfm = pool->transforms[secondary_pipe->pipe_idx]; + secondary_pipe->opp = pool->opps[secondary_pipe->pipe_idx]; + if (primary_pipe->bottom_pipe) { + secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; + secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; + } + primary_pipe->bottom_pipe = secondary_pipe; + secondary_pipe->top_pipe = primary_pipe; + secondary_pipe->surface = primary_pipe->surface; + secondary_pipe->pipe_dlg_param = primary_pipe->pipe_dlg_param; + + resource_build_scaling_params(primary_pipe); + resource_build_scaling_params(secondary_pipe); +} + +static void calc_wm_sets_and_perf_params( + struct validate_context *context, + struct dcn_bw_internal_vars *v) +{ + /* Calculate set A last to keep internal var state consistent for required config */ + if (v->voltage_level < 2) { + v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_vnom0p8; + dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); + + context->watermarks.b.cstate_pstate.cstate_exit_ns = + v->stutter_exit_watermark * 1000; + context->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = + v->stutter_enter_plus_exit_watermark * 1000; + context->watermarks.b.cstate_pstate.pstate_change_ns = + v->dram_clock_change_watermark * 1000; + context->watermarks.b.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->watermarks.b.urgent_ns = v->urgent_watermark * 1000; + + v->dcfclk_per_state[1] = v->dcfclkv_nom0p8; + v->dcfclk_per_state[0] = v->dcfclkv_nom0p8; + v->dcfclk = v->dcfclkv_nom0p8; + dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); + + context->watermarks.c.cstate_pstate.cstate_exit_ns = + v->stutter_exit_watermark * 1000; + context->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = + v->stutter_enter_plus_exit_watermark * 1000; + context->watermarks.c.cstate_pstate.pstate_change_ns = + v->dram_clock_change_watermark * 1000; + context->watermarks.c.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->watermarks.c.urgent_ns = v->urgent_watermark * 1000; + } + + if (v->voltage_level < 3) { + v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_vmax0p9; + v->dcfclk_per_state[2] = v->dcfclkv_max0p9; + v->dcfclk_per_state[1] = v->dcfclkv_max0p9; + v->dcfclk_per_state[0] = v->dcfclkv_max0p9; + v->dcfclk = v->dcfclkv_max0p9; + dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); + + context->watermarks.d.cstate_pstate.cstate_exit_ns = + v->stutter_exit_watermark * 1000; + context->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = + v->stutter_enter_plus_exit_watermark * 1000; + context->watermarks.d.cstate_pstate.pstate_change_ns = + v->dram_clock_change_watermark * 1000; + context->watermarks.d.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->watermarks.d.urgent_ns = v->urgent_watermark * 1000; + } + + v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vmid0p72; + v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vmin0p65; + v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_per_state[v->voltage_level]; + v->dcfclk_per_state[2] = v->dcfclkv_nom0p8; + v->dcfclk_per_state[1] = v->dcfclkv_mid0p72; + v->dcfclk_per_state[0] = v->dcfclkv_min0p65; + v->dcfclk = v->dcfclk_per_state[v->voltage_level]; + dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); + + context->watermarks.a.cstate_pstate.cstate_exit_ns = + v->stutter_exit_watermark * 1000; + context->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + v->stutter_enter_plus_exit_watermark * 1000; + context->watermarks.a.cstate_pstate.pstate_change_ns = + v->dram_clock_change_watermark * 1000; + context->watermarks.a.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->watermarks.a.urgent_ns = v->urgent_watermark * 1000; + if (v->voltage_level >= 2) { + context->watermarks.b = context->watermarks.a; + context->watermarks.c = context->watermarks.a; + } + if (v->voltage_level >= 3) + context->watermarks.d = context->watermarks.a; +} + +static void dcn_bw_apply_registry_override(struct core_dc *dc) +{ + kernel_fpu_begin(); + if (dc->public.debug.sr_exit_time_ns) + dc->dcn_soc.sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; + if (dc->public.debug.sr_enter_plus_exit_time_ns) + dc->dcn_soc.sr_enter_plus_exit_time = + dc->public.debug.sr_enter_plus_exit_time_ns / 1000.0; + if (dc->public.debug.urgent_latency_ns) + dc->dcn_soc.urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; + if (dc->public.debug.percent_of_ideal_drambw) + dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency = + dc->public.debug.percent_of_ideal_drambw; + if (dc->public.debug.dram_clock_change_latency_ns) + dc->dcn_soc.dram_clock_change_latency = + dc->public.debug.dram_clock_change_latency_ns / 1000.0; + kernel_fpu_end(); +} + +bool dcn_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context) +{ + const struct resource_pool *pool = dc->res_pool; + struct dcn_bw_internal_vars *v = &context->dcn_bw_vars; + int i, input_idx; + int vesa_sync_start, asic_blank_end, asic_blank_start; + + dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public)); + + memset(v, 0, sizeof(*v)); + kernel_fpu_begin(); + v->sr_exit_time = dc->dcn_soc.sr_exit_time; + v->sr_enter_plus_exit_time = dc->dcn_soc.sr_enter_plus_exit_time; + v->urgent_latency = dc->dcn_soc.urgent_latency; + v->write_back_latency = dc->dcn_soc.write_back_latency; + v->percent_of_ideal_drambw_received_after_urg_latency = + dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency; + + v->dcfclkv_min0p65 = dc->dcn_soc.dcfclkv_min0p65; + v->dcfclkv_mid0p72 = dc->dcn_soc.dcfclkv_mid0p72; + v->dcfclkv_nom0p8 = dc->dcn_soc.dcfclkv_nom0p8; + v->dcfclkv_max0p9 = dc->dcn_soc.dcfclkv_max0p9; + + v->max_dispclk_vmin0p65 = dc->dcn_soc.max_dispclk_vmin0p65; + v->max_dispclk_vmid0p72 = dc->dcn_soc.max_dispclk_vmid0p72; + v->max_dispclk_vnom0p8 = dc->dcn_soc.max_dispclk_vnom0p8; + v->max_dispclk_vmax0p9 = dc->dcn_soc.max_dispclk_vmax0p9; + + v->max_dppclk_vmin0p65 = dc->dcn_soc.max_dppclk_vmin0p65; + v->max_dppclk_vmid0p72 = dc->dcn_soc.max_dppclk_vmid0p72; + v->max_dppclk_vnom0p8 = dc->dcn_soc.max_dppclk_vnom0p8; + v->max_dppclk_vmax0p9 = dc->dcn_soc.max_dppclk_vmax0p9; + + v->socclk = dc->dcn_soc.socclk; + + v->fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65; + v->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72; + v->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9; + + v->phyclkv_min0p65 = dc->dcn_soc.phyclkv_min0p65; + v->phyclkv_mid0p72 = dc->dcn_soc.phyclkv_mid0p72; + v->phyclkv_nom0p8 = dc->dcn_soc.phyclkv_nom0p8; + v->phyclkv_max0p9 = dc->dcn_soc.phyclkv_max0p9; + + v->downspreading = dc->dcn_soc.downspreading; + v->round_trip_ping_latency_cycles = dc->dcn_soc.round_trip_ping_latency_cycles; + v->urgent_out_of_order_return_per_channel = dc->dcn_soc.urgent_out_of_order_return_per_channel; + v->number_of_channels = dc->dcn_soc.number_of_channels; + v->vmm_page_size = dc->dcn_soc.vmm_page_size; + v->dram_clock_change_latency = dc->dcn_soc.dram_clock_change_latency; + v->return_bus_width = dc->dcn_soc.return_bus_width; + + v->rob_buffer_size_in_kbyte = dc->dcn_ip.rob_buffer_size_in_kbyte; + v->det_buffer_size_in_kbyte = dc->dcn_ip.det_buffer_size_in_kbyte; + v->dpp_output_buffer_pixels = dc->dcn_ip.dpp_output_buffer_pixels; + v->opp_output_buffer_lines = dc->dcn_ip.opp_output_buffer_lines; + v->pixel_chunk_size_in_kbyte = dc->dcn_ip.pixel_chunk_size_in_kbyte; + v->pte_enable = dc->dcn_ip.pte_enable; + v->pte_chunk_size = dc->dcn_ip.pte_chunk_size; + v->meta_chunk_size = dc->dcn_ip.meta_chunk_size; + v->writeback_chunk_size = dc->dcn_ip.writeback_chunk_size; + v->odm_capability = dc->dcn_ip.odm_capability; + v->dsc_capability = dc->dcn_ip.dsc_capability; + v->line_buffer_size = dc->dcn_ip.line_buffer_size; + v->is_line_buffer_bpp_fixed = dc->dcn_ip.is_line_buffer_bpp_fixed; + v->line_buffer_fixed_bpp = dc->dcn_ip.line_buffer_fixed_bpp; + v->max_line_buffer_lines = dc->dcn_ip.max_line_buffer_lines; + v->writeback_luma_buffer_size = dc->dcn_ip.writeback_luma_buffer_size; + v->writeback_chroma_buffer_size = dc->dcn_ip.writeback_chroma_buffer_size; + v->max_num_dpp = dc->dcn_ip.max_num_dpp; + v->max_num_writeback = dc->dcn_ip.max_num_writeback; + v->max_dchub_topscl_throughput = dc->dcn_ip.max_dchub_topscl_throughput; + v->max_pscl_tolb_throughput = dc->dcn_ip.max_pscl_tolb_throughput; + v->max_lb_tovscl_throughput = dc->dcn_ip.max_lb_tovscl_throughput; + v->max_vscl_tohscl_throughput = dc->dcn_ip.max_vscl_tohscl_throughput; + v->max_hscl_ratio = dc->dcn_ip.max_hscl_ratio; + v->max_vscl_ratio = dc->dcn_ip.max_vscl_ratio; + v->max_hscl_taps = dc->dcn_ip.max_hscl_taps; + v->max_vscl_taps = dc->dcn_ip.max_vscl_taps; + v->under_scan_factor = dc->dcn_ip.under_scan_factor; + v->pte_buffer_size_in_requests = dc->dcn_ip.pte_buffer_size_in_requests; + v->dispclk_ramping_margin = dc->dcn_ip.dispclk_ramping_margin; + v->max_inter_dcn_tile_repeaters = dc->dcn_ip.max_inter_dcn_tile_repeaters; + v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = + dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + v->bug_forcing_luma_and_chroma_request_to_same_size_fixed = + dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed; + + v->voltage[5] = dcn_bw_no_support; + v->voltage[4] = dcn_bw_v_max0p9; + v->voltage[3] = dcn_bw_v_max0p9; + v->voltage[2] = dcn_bw_v_nom0p8; + v->voltage[1] = dcn_bw_v_mid0p72; + v->voltage[0] = dcn_bw_v_min0p65; + v->fabric_and_dram_bandwidth_per_state[5] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[4] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[3] = v->fabric_and_dram_bandwidth_vmax0p9; + v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vmid0p72; + v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vmin0p65; + v->dcfclk_per_state[5] = v->dcfclkv_max0p9; + v->dcfclk_per_state[4] = v->dcfclkv_max0p9; + v->dcfclk_per_state[3] = v->dcfclkv_max0p9; + v->dcfclk_per_state[2] = v->dcfclkv_nom0p8; + v->dcfclk_per_state[1] = v->dcfclkv_mid0p72; + v->dcfclk_per_state[0] = v->dcfclkv_min0p65; + v->max_dispclk[5] = v->max_dispclk_vmax0p9; + v->max_dispclk[4] = v->max_dispclk_vmax0p9; + v->max_dispclk[3] = v->max_dispclk_vmax0p9; + v->max_dispclk[2] = v->max_dispclk_vnom0p8; + v->max_dispclk[1] = v->max_dispclk_vmid0p72; + v->max_dispclk[0] = v->max_dispclk_vmin0p65; + v->max_dppclk[5] = v->max_dppclk_vmax0p9; + v->max_dppclk[4] = v->max_dppclk_vmax0p9; + v->max_dppclk[3] = v->max_dppclk_vmax0p9; + v->max_dppclk[2] = v->max_dppclk_vnom0p8; + v->max_dppclk[1] = v->max_dppclk_vmid0p72; + v->max_dppclk[0] = v->max_dppclk_vmin0p65; + v->phyclk_per_state[5] = v->phyclkv_max0p9; + v->phyclk_per_state[4] = v->phyclkv_max0p9; + v->phyclk_per_state[3] = v->phyclkv_max0p9; + v->phyclk_per_state[2] = v->phyclkv_nom0p8; + v->phyclk_per_state[1] = v->phyclkv_mid0p72; + v->phyclk_per_state[0] = v->phyclkv_min0p65; + + if (dc->public.debug.use_max_voltage) { + v->max_dppclk[1] = v->max_dppclk_vnom0p8; + v->max_dppclk[0] = v->max_dppclk_vnom0p8; + } + + if (v->voltage_override == dcn_bw_v_max0p9) { + v->voltage_override_level = number_of_states - 1; + } else if (v->voltage_override == dcn_bw_v_nom0p8) { + v->voltage_override_level = number_of_states - 2; + } else if (v->voltage_override == dcn_bw_v_mid0p72) { + v->voltage_override_level = number_of_states - 3; + } else { + v->voltage_override_level = 0; + } + v->synchronized_vblank = dcn_bw_no; + v->ta_pscalculation = dcn_bw_override; + v->allow_different_hratio_vratio = dcn_bw_yes; + + + for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->stream) + continue; + /* skip all but first of split pipes */ + if (pipe->top_pipe && pipe->top_pipe->surface == pipe->surface) + continue; + + v->underscan_output[input_idx] = false; /* taken care of in recout already*/ + v->interlace_output[input_idx] = false; + + v->htotal[input_idx] = pipe->stream->public.timing.h_total; + v->vtotal[input_idx] = pipe->stream->public.timing.v_total; + v->v_sync_plus_back_porch[input_idx] = pipe->stream->public.timing.v_total + - pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_front_porch; + v->vactive[input_idx] = pipe->stream->public.timing.v_addressable; + v->pixel_clock[input_idx] = pipe->stream->public.timing.pix_clk_khz / 1000.0f; + + + if (!pipe->surface){ + v->dcc_enable[input_idx] = dcn_bw_yes; + v->source_pixel_format[input_idx] = dcn_bw_rgb_sub_32; + v->source_surface_mode[input_idx] = dcn_bw_sw_4_kb_s; + v->lb_bit_per_pixel[input_idx] = 30; + v->viewport_width[input_idx] = pipe->stream->public.timing.h_addressable; + v->viewport_height[input_idx] = pipe->stream->public.timing.v_addressable; + v->scaler_rec_out_width[input_idx] = pipe->stream->public.timing.h_addressable; + v->scaler_recout_height[input_idx] = pipe->stream->public.timing.v_addressable; + v->override_hta_ps[input_idx] = 1; + v->override_vta_ps[input_idx] = 1; + v->override_hta_pschroma[input_idx] = 1; + v->override_vta_pschroma[input_idx] = 1; + v->source_scan[input_idx] = dcn_bw_hor; + + } else { + v->viewport_height[input_idx] = pipe->scl_data.viewport.height; + v->viewport_width[input_idx] = pipe->scl_data.viewport.width; + v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width; + v->scaler_recout_height[input_idx] = pipe->scl_data.recout.height; + if (pipe->bottom_pipe && pipe->bottom_pipe->surface == pipe->surface) { + if (pipe->surface->public.rotation % 2 == 0) { + int viewport_end = pipe->scl_data.viewport.width + + pipe->scl_data.viewport.x; + int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.width + + pipe->bottom_pipe->scl_data.viewport.x; + + if (viewport_end > viewport_b_end) + v->viewport_width[input_idx] = viewport_end + - pipe->bottom_pipe->scl_data.viewport.x; + else + v->viewport_width[input_idx] = viewport_b_end + - pipe->scl_data.viewport.x; + } else { + int viewport_end = pipe->scl_data.viewport.height + + pipe->scl_data.viewport.y; + int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.height + + pipe->bottom_pipe->scl_data.viewport.y; + + if (viewport_end > viewport_b_end) + v->viewport_height[input_idx] = viewport_end + - pipe->bottom_pipe->scl_data.viewport.y; + else + v->viewport_height[input_idx] = viewport_b_end + - pipe->scl_data.viewport.y; + } + v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width + + pipe->bottom_pipe->scl_data.recout.width; + } + + v->dcc_enable[input_idx] = pipe->surface->public.dcc.enable ? dcn_bw_yes : dcn_bw_no; + v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs( + pipe->surface->public.format); + v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs( + pipe->surface->public.tiling_info.gfx9.swizzle); + v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->scl_data.lb_params.depth); + v->override_hta_ps[input_idx] = pipe->scl_data.taps.h_taps; + v->override_vta_ps[input_idx] = pipe->scl_data.taps.v_taps; + v->override_hta_pschroma[input_idx] = pipe->scl_data.taps.h_taps_c; + v->override_vta_pschroma[input_idx] = pipe->scl_data.taps.v_taps_c; + v->source_scan[input_idx] = (pipe->surface->public.rotation % 2) ? dcn_bw_vert : dcn_bw_hor; + } + if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) + v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp; + v->dcc_rate[input_idx] = 1; /*TODO: Worst case? does this change?*/ + v->output_format[input_idx] = dcn_bw_444; + v->output[input_idx] = dcn_bw_dp; + + input_idx++; + } + v->number_of_active_planes = input_idx; + + scaler_settings_calculation(v); + mode_support_and_system_configuration(v); + + if (v->voltage_level != 5) { + float bw_consumed = v->total_bandwidth_consumed_gbyte_per_second; + if (bw_consumed < v->fabric_and_dram_bandwidth_vmin0p65) + bw_consumed = v->fabric_and_dram_bandwidth_vmin0p65; + else if (bw_consumed < v->fabric_and_dram_bandwidth_vmid0p72) + bw_consumed = v->fabric_and_dram_bandwidth_vmid0p72; + else if (bw_consumed < v->fabric_and_dram_bandwidth_vnom0p8) + bw_consumed = v->fabric_and_dram_bandwidth_vnom0p8; + else + bw_consumed = v->fabric_and_dram_bandwidth_vmax0p9; + + display_pipe_configuration(v); + calc_wm_sets_and_perf_params(context, v); + context->fclk_khz = (int)(bw_consumed * 1000000 / + (ddr4_dram_factor_single_Channel * v->number_of_channels)); + context->dram_ccm_us = (int)(v->dram_clock_change_margin); + context->min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); + context->dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); + context->dcfclk_khz = (int)(v->dcfclk * 1000); + context->dispclk_khz = (int)(v->dispclk * 1000); + if (dc->public.debug.max_disp_clk == true) + context->dispclk_khz = (int)(dc->dcn_soc.max_dispclk_vmax0p9 * 1000); + context->dppclk_khz = (int)(v->dppclk * 1000); + context->dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; + + for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + /* skip inactive pipe */ + if (!pipe->stream) + continue; + /* skip all but first of split pipes */ + if (pipe->top_pipe && pipe->top_pipe->surface == pipe->surface) + continue; + + pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; + pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; + pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; + pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; + + pipe->pipe_dlg_param.htotal = pipe->stream->public.timing.h_total; + pipe->pipe_dlg_param.vtotal = pipe->stream->public.timing.v_total; + vesa_sync_start = pipe->stream->public.timing.v_addressable + + pipe->stream->public.timing.v_border_bottom + + pipe->stream->public.timing.v_front_porch; + + asic_blank_end = (pipe->stream->public.timing.v_total - + vesa_sync_start - + pipe->stream->public.timing.v_border_top) + * (pipe->stream->public.timing.flags.INTERLACE ? 1 : 0); + + asic_blank_start = asic_blank_end + + (pipe->stream->public.timing.v_border_top + + pipe->stream->public.timing.v_addressable + + pipe->stream->public.timing.v_border_bottom) + * (pipe->stream->public.timing.flags.INTERLACE ? 1 : 0); + + pipe->pipe_dlg_param.vblank_start = asic_blank_start; + pipe->pipe_dlg_param.vblank_end = asic_blank_end; + + if (pipe->surface) { + struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; + + if (v->dpp_per_plane[input_idx] == 2 || + (pipe->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM || + pipe->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE)) { + if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { + /* update previously split pipe */ + hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; + hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; + hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; + hsplit_pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; + + hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->public.timing.h_total; + hsplit_pipe->pipe_dlg_param.vtotal = pipe->stream->public.timing.v_total; + hsplit_pipe->pipe_dlg_param.vblank_start = pipe->pipe_dlg_param.vblank_start; + hsplit_pipe->pipe_dlg_param.vblank_end = pipe->pipe_dlg_param.vblank_end; + } else { + /* pipe not split previously needs split */ + hsplit_pipe = find_idle_secondary_pipe(&context->res_ctx, pool); + ASSERT(hsplit_pipe); + split_stream_across_pipes( + &context->res_ctx, pool, + pipe, hsplit_pipe); + } + + dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); + } else if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { + /* merge previously split pipe */ + if (pipe->bottom_pipe->bottom_pipe) + pipe->bottom_pipe->bottom_pipe->top_pipe = pipe; + memset(pipe->bottom_pipe, 0, sizeof(*pipe->bottom_pipe)); + pipe->bottom_pipe = pipe->bottom_pipe->bottom_pipe; + resource_build_scaling_params(pipe); + } + /* for now important to do this after pipe split for building e2e params */ + dcn_bw_calc_rq_dlg_ttu(dc, v, pipe); + } + + input_idx++; + } + if (dc->public.debug.use_dml_wm) + dcn_dml_wm_override(v, (struct display_mode_lib *) + &dc->dml, context, pool); + } + + kernel_fpu_end(); + return v->voltage_level != 5; +} + +unsigned int dcn_find_normalized_clock_vdd_Level( + const struct core_dc *dc, + enum dm_pp_clock_type clocks_type, + int clocks_in_khz) +{ + int vdd_level = dcn_bw_v_min0p65; + + if (clocks_in_khz == 0)/*todo some clock not in the considerations*/ + return vdd_level; + + switch (clocks_type) { + case DM_PP_CLOCK_TYPE_DISPLAY_CLK: + if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmax0p9*1000) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vnom0p8*1000) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmid0p72*1000) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmin0p65*1000) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + break; + case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: + if (clocks_in_khz > dc->dcn_soc.phyclkv_max0p9*1000) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.phyclkv_nom0p8*1000) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.phyclkv_mid0p72*1000) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.phyclkv_min0p65*1000) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + break; + + case DM_PP_CLOCK_TYPE_DPPCLK: + if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmax0p9*1000) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vnom0p8*1000) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmid0p72*1000) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmin0p65*1000) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + break; + + case DM_PP_CLOCK_TYPE_MEMORY_CLK: + { + unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); + if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9*1000000/factor) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8*1000000/factor) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72*1000000/factor) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65*1000000/factor) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + } + break; + + case DM_PP_CLOCK_TYPE_DCFCLK: + if (clocks_in_khz > dc->dcn_soc.dcfclkv_max0p9*1000) { + vdd_level = dcn_bw_v_max0p91; + BREAK_TO_DEBUGGER(); + } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_nom0p8*1000) { + vdd_level = dcn_bw_v_max0p9; + } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_mid0p72*1000) { + vdd_level = dcn_bw_v_nom0p8; + } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_min0p65*1000) { + vdd_level = dcn_bw_v_mid0p72; + } else + vdd_level = dcn_bw_v_min0p65; + break; + + default: + break; + } + return vdd_level; +} + +unsigned int dcn_find_dcfclk_suits_all( + const struct core_dc *dc, + struct clocks_value *clocks) +{ + unsigned vdd_level, vdd_level_temp; + unsigned dcf_clk; + + /*find a common supported voltage level*/ + vdd_level = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_DISPLAY_CLK, clocks->dispclk_in_khz); + vdd_level_temp = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, clocks->phyclk_in_khz); + + vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); + vdd_level_temp = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_DPPCLK, clocks->dppclk_in_khz); + vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); + + vdd_level_temp = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_MEMORY_CLK, clocks->dcfclock_in_khz); + vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); + vdd_level_temp = dcn_find_normalized_clock_vdd_Level( + dc, DM_PP_CLOCK_TYPE_DCFCLK, clocks->dcfclock_in_khz); + + /*find that level conresponding dcfclk*/ + vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); + if (vdd_level == dcn_bw_v_max0p91) { + BREAK_TO_DEBUGGER(); + dcf_clk = dc->dcn_soc.dcfclkv_max0p9*1000; + } else if (vdd_level == dcn_bw_v_max0p9) + dcf_clk = dc->dcn_soc.dcfclkv_max0p9*1000; + else if (vdd_level == dcn_bw_v_nom0p8) + dcf_clk = dc->dcn_soc.dcfclkv_nom0p8*1000; + else if (vdd_level == dcn_bw_v_mid0p72) + dcf_clk = dc->dcn_soc.dcfclkv_mid0p72*1000; + else + dcf_clk = dc->dcn_soc.dcfclkv_min0p65*1000; + + dm_logger_write(dc->ctx->logger, LOG_HW_MARKS, + "\tdcf_clk for voltage = %d\n", dcf_clk); + return dcf_clk; +} + +void dcn_bw_update_from_pplib(struct core_dc *dc) +{ + struct dc_context *ctx = dc->ctx; + struct dm_pp_clock_levels_with_latency clks = {0}; + struct dm_pp_clock_levels_with_voltage clks2 = {0}; + + kernel_fpu_begin(); + dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc.number_of_channels && dc->dcn_soc.number_of_channels < 3); + if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc.number_of_channels = 2; + + if (dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks2) && + clks2.num_levels >= 3) { + dc->dcn_soc.max_dispclk_vmin0p65 = clks2.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dispclk_vmid0p72 = clks2.data[clks2.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dispclk_vnom0p8 = clks2.data[clks2.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dispclk_vmax0p9 = clks2.data[clks2.num_levels - 1].clocks_in_khz / 1000.0; + } else + BREAK_TO_DEBUGGER(); +/* + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks) && + clks.num_levels != 0) { + //this is to get DRAM data_rate + //FabricAndDRAMBandwidth = min(64*FCLK , Data rate * single_Channel_Width * number of channels); + }*/ + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && + clks.num_levels != 0) { + ASSERT(clks.num_levels >= 3); + dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc.number_of_channels * + (clks.data[0].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + if (clks.num_levels > 2) { + dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * + (clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + } else { + dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * + (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + } + dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc.number_of_channels * + (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc.number_of_channels * + (clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + } else + BREAK_TO_DEBUGGER(); + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_DCFCLK, &clks) && + clks.num_levels >= 3) { + dc->dcn_soc.dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc.dcfclkv_mid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc.dcfclkv_nom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc.dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; + } else + BREAK_TO_DEBUGGER(); + if (dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, &clks2) && + clks2.num_levels >= 3) { + dc->dcn_soc.phyclkv_min0p65 = clks2.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc.phyclkv_mid0p72 = clks2.data[clks2.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc.phyclkv_nom0p8 = clks2.data[clks2.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc.phyclkv_max0p9 = clks2.data[clks2.num_levels - 1].clocks_in_khz / 1000.0; + } else + BREAK_TO_DEBUGGER(); + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_DPPCLK, &clks) && + clks.num_levels >= 3) { + dc->dcn_soc.max_dppclk_vmin0p65 = clks.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dppclk_vmid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dppclk_vnom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc.max_dppclk_vmax0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; + } + + if (dm_pp_get_clock_levels_by_type_with_latency( + ctx, DM_PP_CLOCK_TYPE_SOCCLK, &clks) && + clks.num_levels >= 3) { + dc->dcn_soc.socclk = clks.data[0].clocks_in_khz / 1000.0; + } else + BREAK_TO_DEBUGGER(); + kernel_fpu_end(); +} + +void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) +{ + struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0}; + int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, + nom_dcfclk_khz, min_dcfclk_khz, socclk_khz; + const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ + unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); + + kernel_fpu_begin(); + max_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; + nom_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; + min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / factor; + max_dcfclk_khz = dc->dcn_soc.dcfclkv_max0p9 * 1000; + nom_dcfclk_khz = dc->dcn_soc.dcfclkv_nom0p8 * 1000; + min_dcfclk_khz = dc->dcn_soc.dcfclkv_min0p65 * 1000; + socclk_khz = dc->dcn_soc.socclk * 1000; + kernel_fpu_end(); + + /* Now notify PPLib/SMU about which Watermarks sets they should select + * depending on DPM state they are in. And update BW MGR GFX Engine and + * Memory clock member variables for Watermarks calculations for each + * Watermark Set + */ + /* SOCCLK does not affect anytihng but writeback for DCN so for now we dont + * care what the value is, hence min to overdrive level + */ + clk_ranges.num_wm_dmif_sets = 4; + clk_ranges.num_wm_mcif_sets = 4; + clk_ranges.wm_dmif_clocks_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_dmif_clocks_ranges[0].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = nom_dcfclk_khz - 1; + clk_ranges.wm_dmif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = nom_fclk_khz - 1; + clk_ranges.wm_mcif_clocks_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_mcif_clocks_ranges[0].wm_min_socclk_clk_in_khz = socclk_khz; + clk_ranges.wm_mcif_clocks_ranges[0].wm_max_socclk_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = nom_fclk_khz - 1; + + clk_ranges.wm_dmif_clocks_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = nom_dcfclk_khz - 1; + clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = nom_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_mcif_clocks_ranges[1].wm_min_socclk_clk_in_khz = socclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_max_socclk_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = nom_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = max_fclk_khz; + + + clk_ranges.wm_dmif_clocks_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = nom_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_mcif_clocks_ranges[2].wm_min_socclk_clk_in_khz = socclk_khz; + clk_ranges.wm_mcif_clocks_ranges[2].wm_max_socclk_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = max_fclk_khz; + + clk_ranges.wm_dmif_clocks_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = max_dcfclk_khz + 1; + clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = overdrive; + clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz + 1; + clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_mcif_clocks_ranges[3].wm_min_socclk_clk_in_khz = socclk_khz; + clk_ranges.wm_mcif_clocks_ranges[3].wm_max_socclk_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz + 1; + clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = overdrive; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges); +} + +void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) +{ + kernel_fpu_begin(); + dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc.socclk; + dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc.socclk; + dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc.socclk; + dc->dml.soc.vmax.socclk_mhz = dc->dcn_soc.socclk; + + dc->dml.soc.vmin.dcfclk_mhz = dc->dcn_soc.dcfclkv_min0p65; + dc->dml.soc.vmid.dcfclk_mhz = dc->dcn_soc.dcfclkv_mid0p72; + dc->dml.soc.vnom.dcfclk_mhz = dc->dcn_soc.dcfclkv_nom0p8; + dc->dml.soc.vmax.dcfclk_mhz = dc->dcn_soc.dcfclkv_max0p9; + + dc->dml.soc.vmin.dispclk_mhz = dc->dcn_soc.max_dispclk_vmin0p65; + dc->dml.soc.vmid.dispclk_mhz = dc->dcn_soc.max_dispclk_vmid0p72; + dc->dml.soc.vnom.dispclk_mhz = dc->dcn_soc.max_dispclk_vnom0p8; + dc->dml.soc.vmax.dispclk_mhz = dc->dcn_soc.max_dispclk_vmax0p9; + + dc->dml.soc.vmin.dppclk_mhz = dc->dcn_soc.max_dppclk_vmin0p65; + dc->dml.soc.vmid.dppclk_mhz = dc->dcn_soc.max_dppclk_vmid0p72; + dc->dml.soc.vnom.dppclk_mhz = dc->dcn_soc.max_dppclk_vnom0p8; + dc->dml.soc.vmax.dppclk_mhz = dc->dcn_soc.max_dppclk_vmax0p9; + + dc->dml.soc.vmin.phyclk_mhz = dc->dcn_soc.phyclkv_min0p65; + dc->dml.soc.vmid.phyclk_mhz = dc->dcn_soc.phyclkv_mid0p72; + dc->dml.soc.vnom.phyclk_mhz = dc->dcn_soc.phyclkv_nom0p8; + dc->dml.soc.vmax.phyclk_mhz = dc->dcn_soc.phyclkv_max0p9; + + dc->dml.soc.vmin.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65; + dc->dml.soc.vmid.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72; + dc->dml.soc.vnom.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8; + dc->dml.soc.vmax.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9; + + dc->dml.soc.sr_exit_time_us = dc->dcn_soc.sr_exit_time; + dc->dml.soc.sr_enter_plus_exit_time_us = dc->dcn_soc.sr_enter_plus_exit_time; + dc->dml.soc.urgent_latency_us = dc->dcn_soc.urgent_latency; + dc->dml.soc.writeback_latency_us = dc->dcn_soc.write_back_latency; + dc->dml.soc.ideal_dram_bw_after_urgent_percent = + dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency; + dc->dml.soc.max_request_size_bytes = dc->dcn_soc.max_request_size; + dc->dml.soc.downspread_percent = dc->dcn_soc.downspreading; + dc->dml.soc.round_trip_ping_latency_dcfclk_cycles = + dc->dcn_soc.round_trip_ping_latency_cycles; + dc->dml.soc.urgent_out_of_order_return_per_channel_bytes = + dc->dcn_soc.urgent_out_of_order_return_per_channel; + dc->dml.soc.num_chans = dc->dcn_soc.number_of_channels; + dc->dml.soc.vmm_page_size_bytes = dc->dcn_soc.vmm_page_size; + dc->dml.soc.dram_clock_change_latency_us = dc->dcn_soc.dram_clock_change_latency; + dc->dml.soc.return_bus_width_bytes = dc->dcn_soc.return_bus_width; + + dc->dml.ip.rob_buffer_size_kbytes = dc->dcn_ip.rob_buffer_size_in_kbyte; + dc->dml.ip.det_buffer_size_kbytes = dc->dcn_ip.det_buffer_size_in_kbyte; + dc->dml.ip.dpp_output_buffer_pixels = dc->dcn_ip.dpp_output_buffer_pixels; + dc->dml.ip.opp_output_buffer_lines = dc->dcn_ip.opp_output_buffer_lines; + dc->dml.ip.pixel_chunk_size_kbytes = dc->dcn_ip.pixel_chunk_size_in_kbyte; + dc->dml.ip.pte_enable = dc->dcn_ip.pte_enable == dcn_bw_yes; + dc->dml.ip.pte_chunk_size_kbytes = dc->dcn_ip.pte_chunk_size; + dc->dml.ip.meta_chunk_size_kbytes = dc->dcn_ip.meta_chunk_size; + dc->dml.ip.writeback_chunk_size_kbytes = dc->dcn_ip.writeback_chunk_size; + dc->dml.ip.line_buffer_size_bits = dc->dcn_ip.line_buffer_size; + dc->dml.ip.max_line_buffer_lines = dc->dcn_ip.max_line_buffer_lines; + dc->dml.ip.IsLineBufferBppFixed = dc->dcn_ip.is_line_buffer_bpp_fixed == dcn_bw_yes; + dc->dml.ip.LineBufferFixedBpp = dc->dcn_ip.line_buffer_fixed_bpp; + dc->dml.ip.writeback_luma_buffer_size_kbytes = dc->dcn_ip.writeback_luma_buffer_size; + dc->dml.ip.writeback_chroma_buffer_size_kbytes = dc->dcn_ip.writeback_chroma_buffer_size; + dc->dml.ip.max_num_dpp = dc->dcn_ip.max_num_dpp; + dc->dml.ip.max_num_wb = dc->dcn_ip.max_num_writeback; + dc->dml.ip.max_dchub_pscl_bw_pix_per_clk = dc->dcn_ip.max_dchub_topscl_throughput; + dc->dml.ip.max_pscl_lb_bw_pix_per_clk = dc->dcn_ip.max_pscl_tolb_throughput; + dc->dml.ip.max_lb_vscl_bw_pix_per_clk = dc->dcn_ip.max_lb_tovscl_throughput; + dc->dml.ip.max_vscl_hscl_bw_pix_per_clk = dc->dcn_ip.max_vscl_tohscl_throughput; + dc->dml.ip.max_hscl_ratio = dc->dcn_ip.max_hscl_ratio; + dc->dml.ip.max_vscl_ratio = dc->dcn_ip.max_vscl_ratio; + dc->dml.ip.max_hscl_taps = dc->dcn_ip.max_hscl_taps; + dc->dml.ip.max_vscl_taps = dc->dcn_ip.max_vscl_taps; + /*pte_buffer_size_in_requests missing in dml*/ + dc->dml.ip.dispclk_ramp_margin_percent = dc->dcn_ip.dispclk_ramping_margin; + dc->dml.ip.underscan_factor = dc->dcn_ip.under_scan_factor; + dc->dml.ip.max_inter_dcn_tile_repeaters = dc->dcn_ip.max_inter_dcn_tile_repeaters; + dc->dml.ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = + dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes; + dc->dml.ip.bug_forcing_LC_req_same_size_fixed = + dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes; + dc->dml.ip.dcfclk_cstate_latency = dc->dcn_ip.dcfclk_cstate_latency; + kernel_fpu_end(); +} diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h new file mode 100644 index 000000000000..499bc1127696 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -0,0 +1,629 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/** + * Bandwidth and Watermark calculations interface. + * (Refer to "DCEx_mode_support.xlsm" from Perforce.) + */ +#ifndef __DCN_CALCS_H__ +#define __DCN_CALCS_H__ + +#include "bw_fixed.h" +#include "display_clock.h" +#include "../dml/display_mode_lib.h" + +struct core_dc; +struct validate_context; + +/******************************************************************************* + * DCN data structures. + ******************************************************************************/ + +#define number_of_planes 6 +#define number_of_planes_minus_one 5 +#define number_of_states 4 +#define number_of_states_plus_one 5 + +#define ddr4_dram_width 64 +#define ddr4_dram_factor_single_Channel 16 +enum dcn_bw_defs { + dcn_bw_v_min0p65, + dcn_bw_v_mid0p72, + dcn_bw_v_nom0p8, + dcn_bw_v_max0p9, + dcn_bw_v_max0p91, + dcn_bw_no_support = 5, + dcn_bw_yes, + dcn_bw_hor, + dcn_bw_vert, + dcn_bw_override, + dcn_bw_rgb_sub_64, + dcn_bw_rgb_sub_32, + dcn_bw_rgb_sub_16, + dcn_bw_no, + dcn_bw_sw_linear, + dcn_bw_sw_4_kb_d, + dcn_bw_sw_4_kb_d_x, + dcn_bw_sw_64_kb_d, + dcn_bw_sw_64_kb_d_t, + dcn_bw_sw_64_kb_d_x, + dcn_bw_sw_var_d, + dcn_bw_sw_var_d_x, + dcn_bw_yuv420_sub_8, + dcn_bw_sw_4_kb_s, + dcn_bw_sw_4_kb_s_x, + dcn_bw_sw_64_kb_s, + dcn_bw_sw_64_kb_s_t, + dcn_bw_sw_64_kb_s_x, + dcn_bw_writeback, + dcn_bw_444, + dcn_bw_dp, + dcn_bw_420, + dcn_bw_hdmi, + dcn_bw_sw_var_s, + dcn_bw_sw_var_s_x, + dcn_bw_yuv420_sub_10, + dcn_bw_supported_in_v_active, + dcn_bw_supported_in_v_blank, + dcn_bw_not_supported, + dcn_bw_na, +}; + +/*bounding box parameters*/ +/*mode parameters*/ +/*system configuration*/ +/* display configuration*/ +struct dcn_bw_internal_vars { + float voltage[number_of_states_plus_one + 1]; + float max_dispclk[number_of_states_plus_one + 1]; + float max_dppclk[number_of_states_plus_one + 1]; + float dcfclk_per_state[number_of_states_plus_one + 1]; + float phyclk_per_state[number_of_states_plus_one + 1]; + float fabric_and_dram_bandwidth_per_state[number_of_states_plus_one + 1]; + float sr_exit_time; + float sr_enter_plus_exit_time; + float dram_clock_change_latency; + float urgent_latency; + float write_back_latency; + float percent_of_ideal_drambw_received_after_urg_latency; + float dcfclkv_max0p9; + float dcfclkv_nom0p8; + float dcfclkv_mid0p72; + float dcfclkv_min0p65; + float max_dispclk_vmax0p9; + float max_dppclk_vmax0p9; + float max_dispclk_vnom0p8; + float max_dppclk_vnom0p8; + float max_dispclk_vmid0p72; + float max_dppclk_vmid0p72; + float max_dispclk_vmin0p65; + float max_dppclk_vmin0p65; + float socclk; + float fabric_and_dram_bandwidth_vmax0p9; + float fabric_and_dram_bandwidth_vnom0p8; + float fabric_and_dram_bandwidth_vmid0p72; + float fabric_and_dram_bandwidth_vmin0p65; + float round_trip_ping_latency_cycles; + float urgent_out_of_order_return_per_channel; + float number_of_channels; + float vmm_page_size; + float return_bus_width; + float rob_buffer_size_in_kbyte; + float det_buffer_size_in_kbyte; + float dpp_output_buffer_pixels; + float opp_output_buffer_lines; + float pixel_chunk_size_in_kbyte; + float pte_chunk_size; + float meta_chunk_size; + float writeback_chunk_size; + enum dcn_bw_defs odm_capability; + enum dcn_bw_defs dsc_capability; + float line_buffer_size; + enum dcn_bw_defs is_line_buffer_bpp_fixed; + float line_buffer_fixed_bpp; + float max_line_buffer_lines; + float writeback_luma_buffer_size; + float writeback_chroma_buffer_size; + float max_num_dpp; + float max_num_writeback; + float max_dchub_topscl_throughput; + float max_pscl_tolb_throughput; + float max_lb_tovscl_throughput; + float max_vscl_tohscl_throughput; + float max_hscl_ratio; + float max_vscl_ratio; + float max_hscl_taps; + float max_vscl_taps; + float under_scan_factor; + float phyclkv_max0p9; + float phyclkv_nom0p8; + float phyclkv_mid0p72; + float phyclkv_min0p65; + float pte_buffer_size_in_requests; + float dispclk_ramping_margin; + float downspreading; + float max_inter_dcn_tile_repeaters; + enum dcn_bw_defs can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + enum dcn_bw_defs bug_forcing_luma_and_chroma_request_to_same_size_fixed; + int mode; + float viewport_width[number_of_planes_minus_one + 1]; + float htotal[number_of_planes_minus_one + 1]; + float vtotal[number_of_planes_minus_one + 1]; + float v_sync_plus_back_porch[number_of_planes_minus_one + 1]; + float vactive[number_of_planes_minus_one + 1]; + float pixel_clock[number_of_planes_minus_one + 1]; /*MHz*/ + float viewport_height[number_of_planes_minus_one + 1]; + enum dcn_bw_defs dcc_enable[number_of_planes_minus_one + 1]; + float dcc_rate[number_of_planes_minus_one + 1]; + enum dcn_bw_defs source_scan[number_of_planes_minus_one + 1]; + float lb_bit_per_pixel[number_of_planes_minus_one + 1]; + enum dcn_bw_defs source_pixel_format[number_of_planes_minus_one + 1]; + enum dcn_bw_defs source_surface_mode[number_of_planes_minus_one + 1]; + enum dcn_bw_defs output_format[number_of_planes_minus_one + 1]; + enum dcn_bw_defs output[number_of_planes_minus_one + 1]; + float scaler_rec_out_width[number_of_planes_minus_one + 1]; + float scaler_recout_height[number_of_planes_minus_one + 1]; + float underscan_output[number_of_planes_minus_one + 1]; + float interlace_output[number_of_planes_minus_one + 1]; + float override_hta_ps[number_of_planes_minus_one + 1]; + float override_vta_ps[number_of_planes_minus_one + 1]; + float override_hta_pschroma[number_of_planes_minus_one + 1]; + float override_vta_pschroma[number_of_planes_minus_one + 1]; + float urgent_latency_support_us[number_of_planes_minus_one + 1]; + float h_ratio[number_of_planes_minus_one + 1]; + float v_ratio[number_of_planes_minus_one + 1]; + float htaps[number_of_planes_minus_one + 1]; + float vtaps[number_of_planes_minus_one + 1]; + float hta_pschroma[number_of_planes_minus_one + 1]; + float vta_pschroma[number_of_planes_minus_one + 1]; + enum dcn_bw_defs pte_enable; + enum dcn_bw_defs synchronized_vblank; + enum dcn_bw_defs ta_pscalculation; + int voltage_override_level; + int number_of_active_planes; + int voltage_level; + enum dcn_bw_defs immediate_flip_supported; + float dcfclk; + float max_phyclk; + float fabric_and_dram_bandwidth; + float dpp_per_plane_per_ratio[1 + 1][number_of_planes_minus_one + 1]; + enum dcn_bw_defs dispclk_dppclk_support_per_ratio[1 + 1]; + float required_dispclk_per_ratio[1 + 1]; + enum dcn_bw_defs error_message[1 + 1]; + int dispclk_dppclk_ratio; + float dpp_per_plane[number_of_planes_minus_one + 1]; + float det_buffer_size_y[number_of_planes_minus_one + 1]; + float det_buffer_size_c[number_of_planes_minus_one + 1]; + float swath_height_y[number_of_planes_minus_one + 1]; + float swath_height_c[number_of_planes_minus_one + 1]; + enum dcn_bw_defs final_error_message; + float frequency; + float header_line; + float header; + enum dcn_bw_defs voltage_override; + enum dcn_bw_defs allow_different_hratio_vratio; + float acceptable_quality_hta_ps; + float acceptable_quality_vta_ps; + float no_of_dpp[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float swath_width_yper_state[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float swath_height_yper_state[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float swath_height_cper_state[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float urgent_latency_support_us_per_state[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float v_ratio_pre_ywith_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float v_ratio_pre_cwith_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float required_prefetch_pixel_data_bw_with_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float v_ratio_pre_ywithout_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float v_ratio_pre_cwithout_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + float required_prefetch_pixel_data_bw_without_immediate_flip[number_of_states_plus_one + 1][1 + 1][number_of_planes_minus_one + 1]; + enum dcn_bw_defs prefetch_supported_with_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs prefetch_supported_without_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs v_ratio_in_prefetch_supported_with_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs v_ratio_in_prefetch_supported_without_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + float required_dispclk[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs dispclk_dppclk_support[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs total_available_pipes_support[number_of_states_plus_one + 1][1 + 1]; + float total_number_of_active_dpp[number_of_states_plus_one + 1][1 + 1]; + float total_number_of_dcc_active_dpp[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs urgent_latency_support[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs mode_support_with_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + enum dcn_bw_defs mode_support_without_immediate_flip[number_of_states_plus_one + 1][1 + 1]; + float return_bw_per_state[number_of_states_plus_one + 1]; + enum dcn_bw_defs dio_support[number_of_states_plus_one + 1]; + float urgent_round_trip_and_out_of_order_latency_per_state[number_of_states_plus_one + 1]; + enum dcn_bw_defs rob_support[number_of_states_plus_one + 1]; + enum dcn_bw_defs bandwidth_support[number_of_states_plus_one + 1]; + float prefetch_bw[number_of_planes_minus_one + 1]; + float meta_pte_bytes_per_frame[number_of_planes_minus_one + 1]; + float meta_row_bytes[number_of_planes_minus_one + 1]; + float dpte_bytes_per_row[number_of_planes_minus_one + 1]; + float prefetch_lines_y[number_of_planes_minus_one + 1]; + float prefetch_lines_c[number_of_planes_minus_one + 1]; + float max_num_sw_y[number_of_planes_minus_one + 1]; + float max_num_sw_c[number_of_planes_minus_one + 1]; + float line_times_for_prefetch[number_of_planes_minus_one + 1]; + float lines_for_meta_pte_with_immediate_flip[number_of_planes_minus_one + 1]; + float lines_for_meta_pte_without_immediate_flip[number_of_planes_minus_one + 1]; + float lines_for_meta_and_dpte_row_with_immediate_flip[number_of_planes_minus_one + 1]; + float lines_for_meta_and_dpte_row_without_immediate_flip[number_of_planes_minus_one + 1]; + float min_dppclk_using_single_dpp[number_of_planes_minus_one + 1]; + float swath_width_ysingle_dpp[number_of_planes_minus_one + 1]; + float byte_per_pixel_in_dety[number_of_planes_minus_one + 1]; + float byte_per_pixel_in_detc[number_of_planes_minus_one + 1]; + float number_of_dpp_required_for_det_and_lb_size[number_of_planes_minus_one + 1]; + float required_phyclk[number_of_planes_minus_one + 1]; + float read256_block_height_y[number_of_planes_minus_one + 1]; + float read256_block_width_y[number_of_planes_minus_one + 1]; + float read256_block_height_c[number_of_planes_minus_one + 1]; + float read256_block_width_c[number_of_planes_minus_one + 1]; + float max_swath_height_y[number_of_planes_minus_one + 1]; + float max_swath_height_c[number_of_planes_minus_one + 1]; + float min_swath_height_y[number_of_planes_minus_one + 1]; + float min_swath_height_c[number_of_planes_minus_one + 1]; + float read_bandwidth[number_of_planes_minus_one + 1]; + float write_bandwidth[number_of_planes_minus_one + 1]; + float pscl_factor[number_of_planes_minus_one + 1]; + float pscl_factor_chroma[number_of_planes_minus_one + 1]; + enum dcn_bw_defs scale_ratio_support; + enum dcn_bw_defs source_format_pixel_and_scan_support; + float total_read_bandwidth_consumed_gbyte_per_second; + float total_write_bandwidth_consumed_gbyte_per_second; + float total_bandwidth_consumed_gbyte_per_second; + enum dcn_bw_defs dcc_enabled_in_any_plane; + float return_bw_todcn_per_state; + float critical_point; + enum dcn_bw_defs writeback_latency_support; + float required_output_bw; + float total_number_of_active_writeback; + enum dcn_bw_defs total_available_writeback_support; + float maximum_swath_width; + float number_of_dpp_required_for_det_size; + float number_of_dpp_required_for_lb_size; + float min_dispclk_using_single_dpp; + float min_dispclk_using_dual_dpp; + enum dcn_bw_defs viewport_size_support; + float swath_width_granularity_y; + float rounded_up_max_swath_size_bytes_y; + float swath_width_granularity_c; + float rounded_up_max_swath_size_bytes_c; + float lines_in_det_luma; + float lines_in_det_chroma; + float effective_lb_latency_hiding_source_lines_luma; + float effective_lb_latency_hiding_source_lines_chroma; + float effective_detlb_lines_luma; + float effective_detlb_lines_chroma; + float projected_dcfclk_deep_sleep; + float meta_req_height_y; + float meta_req_width_y; + float meta_surface_width_y; + float meta_surface_height_y; + float meta_pte_bytes_per_frame_y; + float meta_row_bytes_y; + float macro_tile_block_size_bytes_y; + float macro_tile_block_height_y; + float data_pte_req_height_y; + float data_pte_req_width_y; + float dpte_bytes_per_row_y; + float meta_req_height_c; + float meta_req_width_c; + float meta_surface_width_c; + float meta_surface_height_c; + float meta_pte_bytes_per_frame_c; + float meta_row_bytes_c; + float macro_tile_block_size_bytes_c; + float macro_tile_block_height_c; + float macro_tile_block_width_c; + float data_pte_req_height_c; + float data_pte_req_width_c; + float dpte_bytes_per_row_c; + float v_init_y; + float max_partial_sw_y; + float v_init_c; + float max_partial_sw_c; + float dst_x_after_scaler; + float dst_y_after_scaler; + float time_calc; + float v_update_offset[number_of_planes_minus_one + 1]; + float total_repeater_delay; + float v_update_width[number_of_planes_minus_one + 1]; + float v_ready_offset[number_of_planes_minus_one + 1]; + float time_setup; + float extra_latency; + float maximum_vstartup; + float bw_available_for_immediate_flip; + float total_immediate_flip_bytes[number_of_planes_minus_one + 1]; + float time_for_meta_pte_with_immediate_flip; + float time_for_meta_pte_without_immediate_flip; + float time_for_meta_and_dpte_row_with_immediate_flip; + float time_for_meta_and_dpte_row_without_immediate_flip; + float line_times_to_request_prefetch_pixel_data_with_immediate_flip; + float line_times_to_request_prefetch_pixel_data_without_immediate_flip; + float maximum_read_bandwidth_with_prefetch_with_immediate_flip; + float maximum_read_bandwidth_with_prefetch_without_immediate_flip; + float voltage_level_with_immediate_flip; + float voltage_level_without_immediate_flip; + float total_number_of_active_dpp_per_ratio[1 + 1]; + float byte_per_pix_dety; + float byte_per_pix_detc; + float read256_bytes_block_height_y; + float read256_bytes_block_width_y; + float read256_bytes_block_height_c; + float read256_bytes_block_width_c; + float maximum_swath_height_y; + float maximum_swath_height_c; + float minimum_swath_height_y; + float minimum_swath_height_c; + float swath_width; + float prefetch_bandwidth[number_of_planes_minus_one + 1]; + float v_init_pre_fill_y[number_of_planes_minus_one + 1]; + float v_init_pre_fill_c[number_of_planes_minus_one + 1]; + float max_num_swath_y[number_of_planes_minus_one + 1]; + float max_num_swath_c[number_of_planes_minus_one + 1]; + float prefill_y[number_of_planes_minus_one + 1]; + float prefill_c[number_of_planes_minus_one + 1]; + float v_startup[number_of_planes_minus_one + 1]; + enum dcn_bw_defs allow_dram_clock_change_during_vblank[number_of_planes_minus_one + 1]; + float allow_dram_self_refresh_during_vblank[number_of_planes_minus_one + 1]; + float v_ratio_prefetch_y[number_of_planes_minus_one + 1]; + float v_ratio_prefetch_c[number_of_planes_minus_one + 1]; + float destination_lines_for_prefetch[number_of_planes_minus_one + 1]; + float destination_lines_to_request_vm_inv_blank[number_of_planes_minus_one + 1]; + float destination_lines_to_request_row_in_vblank[number_of_planes_minus_one + 1]; + float min_ttuv_blank[number_of_planes_minus_one + 1]; + float byte_per_pixel_dety[number_of_planes_minus_one + 1]; + float byte_per_pixel_detc[number_of_planes_minus_one + 1]; + float swath_width_y[number_of_planes_minus_one + 1]; + float lines_in_dety[number_of_planes_minus_one + 1]; + float lines_in_dety_rounded_down_to_swath[number_of_planes_minus_one + 1]; + float lines_in_detc[number_of_planes_minus_one + 1]; + float lines_in_detc_rounded_down_to_swath[number_of_planes_minus_one + 1]; + float full_det_buffering_time_y[number_of_planes_minus_one + 1]; + float full_det_buffering_time_c[number_of_planes_minus_one + 1]; + float active_dram_clock_change_latency_margin[number_of_planes_minus_one + 1]; + float v_blank_dram_clock_change_latency_margin[number_of_planes_minus_one + 1]; + float dcfclk_deep_sleep_per_plane[number_of_planes_minus_one + 1]; + float read_bandwidth_plane_luma[number_of_planes_minus_one + 1]; + float read_bandwidth_plane_chroma[number_of_planes_minus_one + 1]; + float display_pipe_line_delivery_time_luma[number_of_planes_minus_one + 1]; + float display_pipe_line_delivery_time_chroma[number_of_planes_minus_one + 1]; + float display_pipe_line_delivery_time_luma_prefetch[number_of_planes_minus_one + 1]; + float display_pipe_line_delivery_time_chroma_prefetch[number_of_planes_minus_one + 1]; + float pixel_pte_bytes_per_row[number_of_planes_minus_one + 1]; + float meta_pte_bytes_frame[number_of_planes_minus_one + 1]; + float meta_row_byte[number_of_planes_minus_one + 1]; + float prefetch_source_lines_y[number_of_planes_minus_one + 1]; + float prefetch_source_lines_c[number_of_planes_minus_one + 1]; + float pscl_throughput[number_of_planes_minus_one + 1]; + float pscl_throughput_chroma[number_of_planes_minus_one + 1]; + float output_bpphdmi[number_of_planes_minus_one + 1]; + float output_bppdp4_lane_hbr[number_of_planes_minus_one + 1]; + float output_bppdp4_lane_hbr2[number_of_planes_minus_one + 1]; + float output_bppdp4_lane_hbr3[number_of_planes_minus_one + 1]; + float max_vstartup_lines[number_of_planes_minus_one + 1]; + float dispclk_with_ramping; + float dispclk_without_ramping; + float dppclk_using_single_dpp_luma; + float dppclk_using_single_dpp; + float dppclk_using_single_dpp_chroma; + enum dcn_bw_defs odm_capable; + float dispclk; + float dppclk; + float return_bandwidth_to_dcn; + enum dcn_bw_defs dcc_enabled_any_plane; + float return_bw; + float critical_compression; + float total_data_read_bandwidth; + float total_active_dpp; + float total_dcc_active_dpp; + float urgent_round_trip_and_out_of_order_latency; + float last_pixel_of_line_extra_watermark; + float data_fabric_line_delivery_time_luma; + float data_fabric_line_delivery_time_chroma; + float urgent_extra_latency; + float urgent_watermark; + float ptemeta_urgent_watermark; + float dram_clock_change_watermark; + float total_active_writeback; + float writeback_dram_clock_change_watermark; + float min_full_det_buffering_time; + float frame_time_for_min_full_det_buffering_time; + float average_read_bandwidth_gbyte_per_second; + float part_of_burst_that_fits_in_rob; + float stutter_burst_time; + float stutter_efficiency_not_including_vblank; + float smallest_vblank; + float v_blank_time; + float stutter_efficiency; + float dcf_clk_deep_sleep; + float stutter_exit_watermark; + float stutter_enter_plus_exit_watermark; + float effective_det_plus_lb_lines_luma; + float urgent_latency_support_us_luma; + float effective_det_plus_lb_lines_chroma; + float urgent_latency_support_us_chroma; + float min_urgent_latency_support_us; + float non_urgent_latency_tolerance; + float block_height256_bytes_y; + float block_height256_bytes_c; + float meta_request_width_y; + float meta_surf_width_y; + float meta_surf_height_y; + float meta_pte_bytes_frame_y; + float meta_row_byte_y; + float macro_tile_size_byte_y; + float macro_tile_height_y; + float pixel_pte_req_height_y; + float pixel_pte_req_width_y; + float pixel_pte_bytes_per_row_y; + float meta_request_width_c; + float meta_surf_width_c; + float meta_surf_height_c; + float meta_pte_bytes_frame_c; + float meta_row_byte_c; + float macro_tile_size_bytes_c; + float macro_tile_height_c; + float pixel_pte_req_height_c; + float pixel_pte_req_width_c; + float pixel_pte_bytes_per_row_c; + float max_partial_swath_y; + float max_partial_swath_c; + float t_calc; + float next_prefetch_mode; + float v_startup_lines; + enum dcn_bw_defs planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw; + enum dcn_bw_defs planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4; + enum dcn_bw_defs planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2; + enum dcn_bw_defs v_ratio_prefetch_more_than4; + enum dcn_bw_defs destination_line_times_for_prefetch_less_than2; + float prefetch_mode; + float dstx_after_scaler; + float dsty_after_scaler; + float v_update_offset_pix; + float total_repeater_delay_time; + float v_update_width_pix; + float v_ready_offset_pix; + float t_setup; + float t_wait; + float bandwidth_available_for_immediate_flip; + float tot_immediate_flip_bytes; + float max_rd_bandwidth; + float time_for_fetching_meta_pte; + float time_for_fetching_row_in_vblank; + float lines_to_request_prefetch_pixel_data; + float required_prefetch_pix_data_bw; + enum dcn_bw_defs prefetch_mode_supported; + float active_dp_ps; + float lb_latency_hiding_source_lines_y; + float lb_latency_hiding_source_lines_c; + float effective_lb_latency_hiding_y; + float effective_lb_latency_hiding_c; + float dpp_output_buffer_lines_y; + float dpp_output_buffer_lines_c; + float dppopp_buffering_y; + float max_det_buffering_time_y; + float active_dram_clock_change_latency_margin_y; + float dppopp_buffering_c; + float max_det_buffering_time_c; + float active_dram_clock_change_latency_margin_c; + float writeback_dram_clock_change_latency_margin; + float min_active_dram_clock_change_margin; + float v_blank_of_min_active_dram_clock_change_margin; + float second_min_active_dram_clock_change_margin; + float min_vblank_dram_clock_change_margin; + float dram_clock_change_margin; + float dram_clock_change_support; + float wr_bandwidth; + float max_used_bw; +}; + +struct dcn_soc_bounding_box { + float sr_exit_time; /*us*/ + float sr_enter_plus_exit_time; /*us*/ + float urgent_latency; /*us*/ + float write_back_latency; /*us*/ + float percent_of_ideal_drambw_received_after_urg_latency; /*%*/ + int max_request_size; /*bytes*/ + float dcfclkv_max0p9; /*MHz*/ + float dcfclkv_nom0p8; /*MHz*/ + float dcfclkv_mid0p72; /*MHz*/ + float dcfclkv_min0p65; /*MHz*/ + float max_dispclk_vmax0p9; /*MHz*/ + float max_dispclk_vmid0p72; /*MHz*/ + float max_dispclk_vnom0p8; /*MHz*/ + float max_dispclk_vmin0p65; /*MHz*/ + float max_dppclk_vmax0p9; /*MHz*/ + float max_dppclk_vnom0p8; /*MHz*/ + float max_dppclk_vmid0p72; /*MHz*/ + float max_dppclk_vmin0p65; /*MHz*/ + float socclk; /*MHz*/ + float fabric_and_dram_bandwidth_vmax0p9; /*GB/s*/ + float fabric_and_dram_bandwidth_vnom0p8; /*GB/s*/ + float fabric_and_dram_bandwidth_vmid0p72; /*GB/s*/ + float fabric_and_dram_bandwidth_vmin0p65; /*GB/s*/ + float phyclkv_max0p9; /*MHz*/ + float phyclkv_nom0p8; /*MHz*/ + float phyclkv_mid0p72; /*MHz*/ + float phyclkv_min0p65; /*MHz*/ + float downspreading; /*%*/ + int round_trip_ping_latency_cycles; /*DCFCLK Cycles*/ + int urgent_out_of_order_return_per_channel; /*bytes*/ + int number_of_channels; + int vmm_page_size; /*bytes*/ + float dram_clock_change_latency; /*us*/ + int return_bus_width; /*bytes*/ +}; +extern const struct dcn_soc_bounding_box dcn10_soc_defaults; + +struct dcn_ip_params { + float rob_buffer_size_in_kbyte; + float det_buffer_size_in_kbyte; + float dpp_output_buffer_pixels; + float opp_output_buffer_lines; + float pixel_chunk_size_in_kbyte; + enum dcn_bw_defs pte_enable; + int pte_chunk_size; /*kbytes*/ + int meta_chunk_size; /*kbytes*/ + int writeback_chunk_size; /*kbytes*/ + enum dcn_bw_defs odm_capability; + enum dcn_bw_defs dsc_capability; + int line_buffer_size; /*bit*/ + int max_line_buffer_lines; + enum dcn_bw_defs is_line_buffer_bpp_fixed; + int line_buffer_fixed_bpp; + int writeback_luma_buffer_size; /*kbytes*/ + int writeback_chroma_buffer_size; /*kbytes*/ + int max_num_dpp; + int max_num_writeback; + int max_dchub_topscl_throughput; /*pixels/dppclk*/ + int max_pscl_tolb_throughput; /*pixels/dppclk*/ + int max_lb_tovscl_throughput; /*pixels/dppclk*/ + int max_vscl_tohscl_throughput; /*pixels/dppclk*/ + float max_hscl_ratio; + float max_vscl_ratio; + int max_hscl_taps; + int max_vscl_taps; + int pte_buffer_size_in_requests; + float dispclk_ramping_margin; /*%*/ + float under_scan_factor; + int max_inter_dcn_tile_repeaters; + enum dcn_bw_defs can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + enum dcn_bw_defs bug_forcing_luma_and_chroma_request_to_same_size_fixed; + int dcfclk_cstate_latency; +}; +extern const struct dcn_ip_params dcn10_ip_defaults; + +bool dcn_validate_bandwidth( + const struct core_dc *dc, + struct validate_context *context); + +unsigned int dcn_find_dcfclk_suits_all( + const struct core_dc *dc, + struct clocks_value *clocks); + +void dcn_bw_update_from_pplib(struct core_dc *dc); +void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc); +void dcn_bw_sync_calcs_and_dml(struct core_dc *dc); + +#endif /* __DCN_CALCS_H__ */ + -- GitLab From 70ccab604049bbb995a57ab3b7fe8a3c2fdbb736 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:19:06 -0400 Subject: [PATCH 0425/2898] drm/amdgpu/display: Add core dc support for DCN Core display support for DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 10 + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1866 +++++++++++++++++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.h | 38 + .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 883 ++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 549 +++++ .../amd/display/dc/dcn10/dcn10_mem_input.c | 1102 ++++++++++ .../amd/display/dc/dcn10/dcn10_mem_input.h | 553 +++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 376 ++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 135 ++ .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 801 +++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 622 ++++++ .../drm/amd/display/dc/dcn10/dcn10_resource.c | 1475 +++++++++++++ .../drm/amd/display/dc/dcn10/dcn10_resource.h | 47 + .../display/dc/dcn10/dcn10_timing_generator.c | 1202 +++++++++++ .../display/dc/dcn10/dcn10_timing_generator.h | 335 +++ .../amd/display/dc/dcn10/dcn10_transform.c | 1057 ++++++++++ .../amd/display/dc/dcn10/dcn10_transform.h | 416 ++++ 17 files changed, 11467 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile new file mode 100644 index 000000000000..2c43ad7a6f3f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for DCN. + +DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ + dcn10_transform.o dcn10_opp.o dcn10_timing_generator.o \ + dcn10_mem_input.o dcn10_mpc.o + +AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCN10) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c new file mode 100644 index 000000000000..fb4eb4364bc7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -0,0 +1,1866 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_dc.h" +#include "core_types.h" +#include "core_status.h" +#include "resource.h" +#include "hw_sequencer.h" +#include "dcn10_hw_sequencer.h" +#include "dce110/dce110_hw_sequencer.h" +#include "abm.h" + +#include "dcn10/dcn10_transform.h" +#include "dcn10/dcn10_mpc.h" +#include "dcn10/dcn10_timing_generator.h" + +#include "mem_input.h" +#include "timing_generator.h" +#include "opp.h" +#include "ipp.h" + +#include "dc_bios_types.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "custom_float.h" + + +struct dcn10_hwseq_reg_offsets { + uint32_t dchubp; + uint32_t dpp; + uint32_t otg; + uint32_t vtg; + uint32_t fmt; +}; + +/* TODO: move to resource */ +static const struct dcn10_hwseq_reg_offsets reg_offsets[] = { + { + .dchubp = (mmHUBP0_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), + .dpp = (mmCM0_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), + .otg = (mmOTG0_OTG_CONTROL - mmOTG0_OTG_CONTROL), + .vtg = (mmVTG0_CONTROL - mmVTG0_CONTROL), + .fmt = (mmFMT0_FMT_BIT_DEPTH_CONTROL - + mmFMT0_FMT_BIT_DEPTH_CONTROL), + }, + { + .dchubp = (mmHUBP1_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), + .dpp = (mmCM1_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), + .otg = (mmOTG1_OTG_CONTROL - mmOTG0_OTG_CONTROL), + .vtg = (mmVTG1_CONTROL - mmVTG0_CONTROL), + .fmt = (mmFMT1_FMT_BIT_DEPTH_CONTROL - + mmFMT0_FMT_BIT_DEPTH_CONTROL), + }, + { + .dchubp = (mmHUBP2_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), + .dpp = (mmCM2_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), + .otg = (mmOTG2_OTG_CONTROL - mmOTG0_OTG_CONTROL), + .vtg = (mmVTG2_CONTROL - mmVTG0_CONTROL), + .fmt = (mmFMT2_FMT_BIT_DEPTH_CONTROL - + mmFMT0_FMT_BIT_DEPTH_CONTROL), + }, + { + .dchubp = (mmHUBP3_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), + .dpp = (mmCM3_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), + .otg = (mmOTG3_OTG_CONTROL - mmOTG0_OTG_CONTROL), + .vtg = (mmVTG3_CONTROL - mmVTG0_CONTROL), + .fmt = (mmFMT3_FMT_BIT_DEPTH_CONTROL - + mmFMT0_FMT_BIT_DEPTH_CONTROL), + } +}; + +#define HWSEQ_REG_UPDATE_N(reg_name, n, ...) \ + generic_reg_update_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__) + +#define HWSEQ_REG_SET_N(reg_name, n, ...) \ + generic_reg_set_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__) + +#define HWSEQ_REG_UPDATE(reg, field, val) \ + HWSEQ_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) + +#define HWSEQ_REG_UPDATE_2(reg, field1, val1, field2, val2) \ + HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) + +#define HWSEQ_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ + HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) + + +#define HWSEQ_REG_SET(reg, field, val) \ + HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val) + +/* TODO should be moved to OTG */ +static void lock_otg_master_update( + struct dc_context *ctx, + uint8_t inst) +{ + uint32_t inst_offset = reg_offsets[inst].otg; + + HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0, + OTG_MASTER_UPDATE_LOCK_SEL, inst); + + /* unlock master locker */ + HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, + OTG_MASTER_UPDATE_LOCK, 1); + + /* wait for unlock happens */ + if (!wait_reg(ctx, inst_offset, OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1)) + BREAK_TO_DEBUGGER(); + +} + +static bool unlock_master_tg_and_wait( + struct dc_context *ctx, + uint8_t inst) +{ + uint32_t inst_offset = reg_offsets[inst].otg; + + HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_SYNC_STATUS, + VUPDATE_NO_LOCK_EVENT_CLEAR, 1); + HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, 0); + + if (!wait_reg(ctx, inst_offset, OTG0_OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, 1)) { + dm_logger_write(ctx->logger, LOG_ERROR, + "wait for VUPDATE_NO_LOCK_EVENT_OCCURRED failed\n"); + BREAK_TO_DEBUGGER(); + return false; + } + return true; +} + +/* TODO: should be moved to OTG ? */ +static void unlock_otg_master( + struct dc_context *ctx, + uint8_t inst) +{ + uint32_t inst_offset = reg_offsets[inst].otg; + + /* unlock master locker */ + HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, + OTG_MASTER_UPDATE_LOCK, 0); +} + + +static void wait_no_outstanding_request( + struct dc_context *ctx, + uint8_t plane_id) +{ + uint32_t inst_offset = reg_offsets[plane_id].dchubp; + + if (!wait_reg(ctx, inst_offset, HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1)) + BREAK_TO_DEBUGGER(); +} + +static void disable_clocks( + struct dc_context *ctx, + uint8_t plane_id) +{ + uint32_t inst_offset = reg_offsets[plane_id].dchubp; + + generic_reg_update_soc15(ctx, inst_offset, HUBP0_HUBP_CLK_CNTL, 1, + FD(HUBP0_HUBP_CLK_CNTL__HUBP_CLOCK_ENABLE), 0); + + inst_offset = reg_offsets[plane_id].dpp; + generic_reg_update_soc15(ctx, inst_offset, DPP_TOP0_DPP_CONTROL, 1, + FD(DPP_TOP0_DPP_CONTROL__DPP_CLOCK_ENABLE), 0); +} + +/* TODO: This is one time program during system boot up, + * this should be done within BIOS or CAIL + */ +static void dchubp_map_fb_to_mc(struct dc_context *ctx) +{ + /* TODO: do not know where to program + * DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB + */ + /* + * TODO: For real ASIC, FB_OFFSET may be need change to the same value + * as FB_BASE. Need re-visit this for real ASIC. + */ + dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_BASE, 0, 0x80); + dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_OFFSET, 0, 0); + dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_TOP, 0, 0xFF); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG0, 7, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_DATA_RESPONSE_STATUS_CLEAR), 0, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_ERROR_CLEAR), 0, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_FLUSH_REQ_CREDIT_EN), 0, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_EN), 0, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_PORT_CONTROL), 1, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_UNIT_ID_BITMASK), 0xd3, + FD(DCHUBBUB_SDPIF_CFG0__SDPIF_CREDIT_DISCONNECT_DELAY), 0xc); + + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG1, 4, + FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_IO), 0, + FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_VC), 6, + FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_IO), 1, + FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_VC), 6); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_BASE, 1, + FD(DCHUBBUB_SDPIF_FB_BASE__SDPIF_FB_BASE), 0x000080); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_TOP, 1, + FD(DCHUBBUB_SDPIF_FB_TOP__SDPIF_FB_TOP), 0x0000ff); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BOT, 1, + FD(DCHUBBUB_SDPIF_AGP_BOT__SDPIF_AGP_BOT), 0x0000040); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_TOP, 1, + FD(DCHUBBUB_SDPIF_AGP_TOP__SDPIF_AGP_TOP), 0x00001ff); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BASE, 1, + FD(DCHUBBUB_SDPIF_AGP_BASE__SDPIF_AGP_BASE), 0x0000080); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_TOP, 1, + FD(DCHUBBUB_SDPIF_APER_TOP__SDPIF_APER_TOP), 0x00007ff); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_DEF_0, 1, + FD(DCHUBBUB_SDPIF_APER_DEF_0__SDPIF_APER_DEF_0), 0xdeadbeef); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_0, 2, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_EN_0), 0, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_RELOC_LO_0), 0x90000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_0, 1, + FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_0__SDPIF_MARC_LENGTH_LO_0), 0x10000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_1, 1, + FD(DCHUBBUB_SDPIF_MARC_BASE_LO_1__SDPIF_MARC_BASE_LO_1), 0x10000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_1, 2, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_EN_1), 0, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_RELOC_LO_1), 0xa0000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_1, 1, + FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_1__SDPIF_MARC_LENGTH_LO_1), 0x10000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_2, 1, + FD(DCHUBBUB_SDPIF_MARC_BASE_LO_2__SDPIF_MARC_BASE_LO_2), 0x20000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_2, 2, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_EN_2), 0, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_RELOC_LO_2), 0xb0000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_2, 1, + FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_2__SDPIF_MARC_LENGTH_LO_2), 0x10000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_3, 1, + FD(DCHUBBUB_SDPIF_MARC_BASE_LO_3__SDPIF_MARC_BASE_LO_3), 0x30000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_3, 2, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_EN_3), 0, + FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_RELOC_LO_3), 0xc0000); + + generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_3, 1, + FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_3__SDPIF_MARC_LENGTH_LO_3), 0x10000); + + /* TODO: Is DCN_VM_SYSTEM_APERTURE address one time programming? + * Are all 4 hubp programmed with the same address? + */ + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); + + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); + + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); + + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); + dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); +} + +/* TODO: This is one time program during system boot up, + * this should be done within BIOS + */ +static void dchubup_setup_timer(struct dc_context *ctx) +{ + dm_write_reg_soc15(ctx, mmREFCLK_CNTL, 0, 0); + + generic_reg_update_soc15(ctx, 0, DCHUBBUB_GLOBAL_TIMER_CNTL, 1, + FD(DCHUBBUB_GLOBAL_TIMER_CNTL__DCHUBBUB_GLOBAL_TIMER_ENABLE), 1); +} + +/* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG + * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. + * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG + */ +static void select_vtg( + struct dc_context *ctx, + uint8_t plane_id, + uint8_t inst) +{ + uint32_t inst_offset = reg_offsets[plane_id].dchubp; + + HWSEQ_REG_UPDATE(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, inst); +} + +static void enable_dcfclk( + struct dc_context *ctx, + uint8_t plane_id, + uint32_t requested_pix_clk, + bool dppclk_div) +{ + uint32_t inst_offset = reg_offsets[plane_id].dchubp; + + HWSEQ_REG_UPDATE(HUBP0_HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, 1); +} + +static void enable_dppclk( + struct dc_context *ctx, + uint8_t plane_id, + uint32_t requested_pix_clk, + bool dppclk_div) +{ + uint32_t inst_offset = reg_offsets[plane_id].dpp; + + dm_logger_write(ctx->logger, LOG_SURFACE, + "dppclk_rate_control for pipe %d programed to %d\n", + plane_id, + dppclk_div); + + /* TODO: find condition for DPP clock to DISPCLK or 1/2 DISPCLK */ + if (dppclk_div) { + /* 1/2 DISPCLK*/ + HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL, + DPPCLK_RATE_CONTROL, 1, + DPP_CLOCK_ENABLE, 1); + } else { + /* DISPCLK */ + HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL, + DPPCLK_RATE_CONTROL, 0, + DPP_CLOCK_ENABLE, 1); + } +} + +static void enable_power_gating_plane( + struct dc_context *ctx, + bool enable) +{ + uint32_t inst_offset = 0; /* each register only has one instance */ + bool force_on = 1; /* disable power gating */ + + if (enable) + force_on = 0; + + /* DCHUBP0/1/2/3 */ + HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on); + + /* DPP0/1/2/3 */ + HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); + HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); + + if (ctx->dc->debug.disable_clock_gate) { + /* probably better to just write entire register to 0xffff to + * ensure all clock gating is disabled + */ + HWSEQ_REG_UPDATE_3(DCCG_GATE_DISABLE_CNTL, + DISPCLK_R_DCCG_GATE_DISABLE, 1, + DPREFCLK_R_DCCG_GATE_DISABLE, 1, + REFCLK_R_DIG_GATE_DISABLE, 1); + HWSEQ_REG_UPDATE(DCFCLK_CNTL, + DCFCLK_GATE_DIS, 1); + } + +} + +static void dpp_pg_control( + struct dc_context *ctx, + unsigned int dpp_inst, + bool power_on) +{ + uint32_t inst_offset = 0; + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + + if (ctx->dc->debug.disable_dpp_power_gate) + return; + + switch (dpp_inst) { + case 0: /* DPP0 */ + HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, + DOMAIN1_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN1_PG_STATUS, + DOMAIN1_PGFSM_PWR_STATUS, pwr_status); + break; + case 1: /* DPP1 */ + HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, + DOMAIN3_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN3_PG_STATUS, + DOMAIN3_PGFSM_PWR_STATUS, pwr_status); + break; + case 2: /* DPP2 */ + HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, + DOMAIN5_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN5_PG_STATUS, + DOMAIN5_PGFSM_PWR_STATUS, pwr_status); + break; + case 3: /* DPP3 */ + HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, + DOMAIN7_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN7_PG_STATUS, + DOMAIN7_PGFSM_PWR_STATUS, pwr_status); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } +} + +static void hubp_pg_control( + struct dc_context *ctx, + unsigned int hubp_inst, + bool power_on) +{ + uint32_t inst_offset = 0; + uint32_t power_gate = power_on ? 0 : 1; + uint32_t pwr_status = power_on ? 0 : 2; + + if (ctx->dc->debug.disable_hubp_power_gate) + return; + + switch (hubp_inst) { + case 0: /* DCHUBP0 */ + HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, + DOMAIN0_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN0_PG_STATUS, + DOMAIN0_PGFSM_PWR_STATUS, pwr_status); + break; + case 1: /* DCHUBP1 */ + HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, + DOMAIN2_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN2_PG_STATUS, + DOMAIN2_PGFSM_PWR_STATUS, pwr_status); + break; + case 2: /* DCHUBP2 */ + HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, + DOMAIN4_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN4_PG_STATUS, + DOMAIN4_PGFSM_PWR_STATUS, pwr_status); + break; + case 3: /* DCHUBP3 */ + HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, + DOMAIN6_POWER_GATE, power_gate); + + wait_reg(ctx, 0, DOMAIN6_PG_STATUS, + DOMAIN6_PGFSM_PWR_STATUS, pwr_status); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } +} + +static void power_on_plane( + struct dc_context *ctx, + uint8_t plane_id, + uint8_t inst) +{ + uint32_t inst_offset = 0; + + /* disable clock power gating */ + + /* DCCG_GATE_DISABLE_CNTL only has one instance */ + HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, + DISPCLK_DCCG_GATE_DISABLE, 1, + DPPCLK_GATE_DISABLE, 1); + /* DCFCLK_CNTL only has one instance */ + HWSEQ_REG_UPDATE(DCFCLK_CNTL, + DCFCLK_GATE_DIS, 1); + + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 1); + dpp_pg_control(ctx, plane_id, true); + hubp_pg_control(ctx, plane_id, true); + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 0); + + if (ctx->dc->debug.disable_clock_gate) { + HWSEQ_REG_UPDATE(DCCG_GATE_DISABLE_CNTL, + DISPCLK_DCCG_GATE_DISABLE, 0); + } else { + /* DCCG_GATE_DISABLE_CNTL only has one instance. inst_offset = 0 */ + HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, + DISPCLK_DCCG_GATE_DISABLE, 0, + DPPCLK_GATE_DISABLE, 0); + /* DCFCLK_CNTL only has one instance. inst_offset = 0 */ + HWSEQ_REG_UPDATE(DCFCLK_CNTL, + DCFCLK_GATE_DIS, 0); + } +} + +/* fully check bios enabledisplaypowergating table. dal only need dce init + * other power, clock gate register will be handle by dal itself. + * further may be put within init_hw + */ +static bool dcn10_enable_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) +{ + /* TODOFPGA */ +#if 0 + if (power_gating != PIPE_GATING_CONTROL_ENABLE) + dce110_init_pte(ctx); +#endif + + return true; +} + +static void bios_golden_init(struct core_dc *dc) +{ + struct dc_bios *bp = dc->ctx->dc_bios; + int i; + + /* initialize dcn global */ + bp->funcs->enable_disp_power_gating(bp, + CONTROLLER_ID_D0, ASIC_PIPE_INIT); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + /* initialize dcn per pipe */ + bp->funcs->enable_disp_power_gating(bp, + CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE); + } +} + +static void init_hw(struct core_dc *dc) +{ + int i; + struct dc_bios *bp; + struct transform *xfm; + struct abm *abm; + + bp = dc->ctx->dc_bios; + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + /* TODO: this will be moved to Diag or BIOS */ + dchubup_setup_timer(dc->ctx); + + /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface + * between dc and kmd + */ + dchubp_map_fb_to_mc(dc->ctx); + + enable_power_gating_plane(dc->ctx, true); + return; + } + /* end of FPGA. Below if real ASIC */ + + bios_golden_init(dc); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + xfm = dc->res_pool->transforms[i]; + xfm->funcs->transform_reset(xfm); + + /* TODOFPGA: may need later */ +#if 0 + xfm->funcs->transform_power_up(xfm); + dc->hwss.enable_display_pipe_clock_gating( + dc->ctx, + true); +#endif + } + /* TODOFPGA: light sleep */ +#if 0 + dc->hwss.clock_gating_power_up(dc->ctx, false); +#endif + + for (i = 0; i < dc->link_count; i++) { + /* Power up AND update implementation according to the + * required signal (which may be different from the + * default signal on connector). + */ + struct core_link *link = dc->links[i]; + + link->link_enc->funcs->hw_init(link->link_enc); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = + dc->res_pool->timing_generators[i]; + + tg->funcs->disable_vga(tg); + + /* Blank controller using driver code instead of + * command table. + */ + tg->funcs->set_blank(tg, true); + hwss_wait_for_blank_complete(tg); + } + + for (i = 0; i < dc->res_pool->audio_count; i++) { + struct audio *audio = dc->res_pool->audios[i]; + + audio->funcs->hw_init(audio); + } + + abm = dc->res_pool->abm; + if (abm != NULL) { + abm->funcs->init_backlight(abm); + abm->funcs->abm_init(abm); + } + + /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ + generic_reg_set_soc15(dc->ctx, 0, DIO_MEM_PWR_CTRL, 7, + FD(DIO_MEM_PWR_CTRL__HDMI0_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI1_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI2_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI3_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI4_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE), 0, + FD(DIO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE), 0); + + /* This power gating should be one-time program for DAL. + * It can only change by registry key + * TODO: new task will for this. + * if power gating is disable, power_on_plane and power_off_plane + * should be skip. Otherwise, hand will be met in power_off_plane + */ + + enable_power_gating_plane(dc->ctx, true); +} + +static enum dc_status dcn10_prog_pixclk_crtc_otg( + struct pipe_ctx *pipe_ctx, + struct validate_context *context, + struct core_dc *dc) +{ + struct core_stream *stream = pipe_ctx->stream; + enum dc_color_space color_space; + struct tg_color black_color = {0}; + bool enableStereo = stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? + false:true; + bool rightEyePolarity = stream->public.timing.flags.RIGHT_EYE_3D_POLARITY; + + + /* by upper caller loop, pipe0 is parent pipe and be called first. + * back end is set up by for pipe0. Other children pipe share back end + * with pipe 0. No program is needed. + */ + if (pipe_ctx->top_pipe != NULL) + return DC_OK; + + /* TODO check if timing_changed, disable stream if timing changed */ + + /* HW program guide assume display already disable + * by unplug sequence. OTG assume stop. + */ + pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, true); + + if (false == pipe_ctx->clock_source->funcs->program_pix_clk( + pipe_ctx->clock_source, + &pipe_ctx->pix_clk_params, + &pipe_ctx->pll_settings)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; + pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; + pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; + pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; + + pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + + pipe_ctx->tg->funcs->program_timing( + pipe_ctx->tg, + &stream->public.timing, + true); + + pipe_ctx->opp->funcs->opp_set_stereo_polarity( + pipe_ctx->opp, + enableStereo, + rightEyePolarity); + +#if 0 /* move to after enable_crtc */ + /* TODO: OPP FMT, ABM. etc. should be done here. */ + /* or FPGA now. instance 0 only. TODO: move to opp.c */ + + inst_offset = reg_offsets[pipe_ctx->tg->inst].fmt; + + pipe_ctx->opp->funcs->opp_program_fmt( + pipe_ctx->opp, + &stream->bit_depth_params, + &stream->clamping); +#endif + /* program otg blank color */ + color_space = stream->public.output_color_space; + color_space_to_black_color(dc, color_space, &black_color); + pipe_ctx->tg->funcs->set_blank_color( + pipe_ctx->tg, + &black_color); + + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + hwss_wait_for_blank_complete(pipe_ctx->tg); + + /* VTG is within DCHUB command block. DCFCLK is always on */ + if (false == pipe_ctx->tg->funcs->enable_crtc(pipe_ctx->tg)) { + BREAK_TO_DEBUGGER(); + return DC_ERROR_UNEXPECTED; + } + + /* TODO program crtc source select for non-virtual signal*/ + /* TODO program FMT */ + /* TODO setup link_enc */ + /* TODO set stream attributes */ + /* TODO program audio */ + /* TODO enable stream if timing changed */ + /* TODO unblank stream if DP */ + + return DC_OK; +} + +static void reset_back_end_for_pipe( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + int i; + struct dc_bios *bp; + + bp = dc->ctx->dc_bios; + + if (pipe_ctx->stream_enc == NULL) { + pipe_ctx->stream = NULL; + return; + } + + /* TODOFPGA break core_link_disable_stream into 2 functions: + * disable_stream and disable_link. disable_link will disable PHYPLL + * which is used by otg. Move disable_link after disable_crtc + */ + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + core_link_disable_stream(pipe_ctx); + + /* by upper caller loop, parent pipe: pipe0, will be reset last. + * back end share by all pipes and will be disable only when disable + * parent pipe. + */ + if (pipe_ctx->top_pipe == NULL) { + pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); + + pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, false); + } + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + resource_unreference_clock_source( + &context->res_ctx, dc->res_pool, + &pipe_ctx->clock_source); + + for (i = 0; i < dc->res_pool->pipe_count; i++) + if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe_ctx) + break; + + if (i == dc->res_pool->pipe_count) + return; + + pipe_ctx->stream = NULL; +} + +static void reset_front_end_for_pipe( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); + struct mpc_tree_cfg *tree_cfg = NULL; + + if (!pipe_ctx->surface) + return; + + lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); + + /* TODO: build stream pipes group id. For now, use stream otg + * id as pipe group id + */ + tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + + if (pipe_ctx->top_pipe == NULL) + dcn10_delete_mpc_tree(mpc, tree_cfg); + else { + if (dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) + pipe_ctx->top_pipe->bottom_pipe = NULL; + else { + dm_logger_write(dc->ctx->logger, LOG_RESOURCE, + "%s: failed to find dpp to be removed!\n", + __func__); + } + } + + pipe_ctx->top_pipe = NULL; + pipe_ctx->bottom_pipe = NULL; + pipe_ctx->mpc_idx = -1; + + unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); + + pipe_ctx->mi->funcs->disable_request(pipe_ctx->mi); + + wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); + + wait_mpcc_idle(mpc, pipe_ctx->pipe_idx); + + disable_clocks(dc->ctx, pipe_ctx->pipe_idx); + + pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm); + + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset front end for pipe %d\n", + pipe_ctx->pipe_idx); + + pipe_ctx->surface = NULL; +} + +static void reset_hw_ctx(struct core_dc *dc, + struct validate_context *context, + void (*reset)(struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context)) +{ + int i; + + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx_old->stream) + continue; + + if (!pipe_ctx->stream || + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + reset(dc, pipe_ctx_old, dc->current_context); + } +} + +static void reset_hw_ctx_wrap( + struct core_dc *dc, + struct validate_context *context) +{ + /* Reset Front End*/ + reset_hw_ctx(dc, context, reset_front_end_for_pipe); + /* Reset Back End*/ + reset_hw_ctx(dc, context, reset_back_end_for_pipe); + + memcpy(context->res_ctx.mpc_tree, + dc->current_context->res_ctx.mpc_tree, + sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); +} + +static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, + PHYSICAL_ADDRESS_LOC *addr) +{ + struct core_surface *surface = pipe_ctx->surface; + bool sec_split = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->surface == pipe_ctx->surface; + if (sec_split && surface->public.address.type == PLN_ADDR_TYPE_GRPH_STEREO && + (pipe_ctx->stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_SIDE_BY_SIDE || + pipe_ctx->stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { + *addr = surface->public.address.grph_stereo.left_addr; + surface->public.address.grph_stereo.left_addr =\ + surface->public.address.grph_stereo.right_addr; + return true; + } + return false; +} + +static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) +{ + bool addr_patched = false; + PHYSICAL_ADDRESS_LOC addr; + struct core_surface *surface = pipe_ctx->surface; + + if (surface == NULL) + return; + addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); + pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( + pipe_ctx->mi, + &surface->public.address, + surface->public.flip_immediate); + surface->status.requested_address = surface->public.address; + if (addr_patched) + pipe_ctx->surface->public.address.grph_stereo.left_addr = addr; +} + +static bool dcn10_set_input_transfer_func( + struct pipe_ctx *pipe_ctx, + const struct core_surface *surface) +{ + struct input_pixel_processor *ipp = pipe_ctx->ipp; + const struct core_transfer_func *tf = NULL; + bool result = true; + + if (ipp == NULL) + return false; + + if (surface->public.in_transfer_func) + tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + + if (tf == NULL) + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + else if (tf->public.type == TF_TYPE_PREDEFINED) { + switch (tf->public.tf) { + case TRANSFER_FUNCTION_SRGB: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_HW_sRGB); + break; + case TRANSFER_FUNCTION_BT709: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_HW_xvYCC); + break; + case TRANSFER_FUNCTION_LINEAR: + ipp->funcs->ipp_set_degamma(ipp, + IPP_DEGAMMA_MODE_BYPASS); + break; + case TRANSFER_FUNCTION_PQ: + result = false; + break; + default: + result = false; + break; + } + } else if (tf->public.type == TF_TYPE_BYPASS) { + ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + } else { + /*TF_TYPE_DISTRIBUTED_POINTS*/ + result = false; + } + + return result; +} +/*modify the method to handle rgb for arr_points*/ +static bool convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points *arr_points, + uint32_t hw_points_num) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = false; + + if (!convert_to_custom_float_format( + arr_points[0].x, + &fmt, + &arr_points[0].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].offset, + &fmt, + &arr_points[0].custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[0].slope, + &fmt, + &arr_points[0].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format( + arr_points[1].x, + &fmt, + &arr_points[1].custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[1].y, + &fmt, + &arr_points[1].custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + arr_points[1].slope, + &fmt, + &arr_points[1].custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + fmt.mantissa_bits = 12; + fmt.sign = true; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format( + rgb->red, + &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->green, + &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->blue, + &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_red, + &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_green, + &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format( + rgb->delta_blue, + &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} +#define MAX_REGIONS_NUMBER 34 +#define MAX_LOW_POINT 25 +#define NUMBER_SEGMENTS 32 + +static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func + *output_tf, struct pwl_params *regamma_params) +{ + struct curve_points *arr_points; + struct pwl_result_data *rgb_resulted; + struct pwl_result_data *rgb; + struct pwl_result_data *rgb_plus_1; + struct fixed31_32 y_r; + struct fixed31_32 y_g; + struct fixed31_32 y_b; + struct fixed31_32 y1_min; + struct fixed31_32 y3_max; + + int32_t segment_start, segment_end; + int32_t i; + uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; + + if (output_tf == NULL || regamma_params == NULL || + output_tf->type == TF_TYPE_BYPASS) + return false; + + arr_points = regamma_params->arr_points; + rgb_resulted = regamma_params->rgb_resulted; + hw_points = 0; + + memset(regamma_params, 0, sizeof(struct pwl_params)); + memset(seg_distr, 0, sizeof(seg_distr)); + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* 32 segments + * segments are from 2^-25 to 2^7 + */ + for (i = 0; i < 32 ; i++) + seg_distr[i] = 3; + + segment_start = -25; + segment_end = 7; + } else { + /* 10 segments + * segment is from 2^-10 to 2^0 + * There are less than 256 points, for optimization + */ + seg_distr[0] = 3; + seg_distr[1] = 4; + seg_distr[2] = 4; + seg_distr[3] = 4; + seg_distr[4] = 4; + seg_distr[5] = 4; + seg_distr[6] = 4; + seg_distr[7] = 4; + seg_distr[8] = 5; + seg_distr[9] = 5; + + segment_start = -10; + segment_end = 0; + } + + for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++) + seg_distr[i] = -1; + + for (k = 0; k < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) + hw_points += (1 << seg_distr[k]); + } + + j = 0; + for (k = 0; k < (segment_end - segment_start); k++) { + increment = NUMBER_SEGMENTS / (1 << seg_distr[k]); + start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS; + for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) { + if (j == hw_points - 1) + break; + rgb_resulted[j].red = output_tf->tf_pts.red[i]; + rgb_resulted[j].green = output_tf->tf_pts.green[i]; + rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; + j++; + } + } + + /* last point */ + start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS; + rgb_resulted[hw_points - 1].red = + output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = + output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = + output_tf->tf_pts.blue[start_index]; + + arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_start)); + arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2), + dal_fixed31_32_from_int(segment_end)); + + y_r = rgb_resulted[0].red; + y_g = rgb_resulted[0].green; + y_b = rgb_resulted[0].blue; + + y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); + + arr_points[0].y = y1_min; + arr_points[0].slope = dal_fixed31_32_div( + arr_points[0].y, + arr_points[0].x); + y_r = rgb_resulted[hw_points - 1].red; + y_g = rgb_resulted[hw_points - 1].green; + y_b = rgb_resulted[hw_points - 1].blue; + + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ + y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); + + arr_points[1].y = y3_max; + arr_points[2].y = y3_max; + + arr_points[1].slope = dal_fixed31_32_zero; + arr_points[2].slope = dal_fixed31_32_zero; + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* for PQ, we want to have a straight line from last HW X point, + * and the slope to be such that we hit 1.0 at 10000 nits. + */ + const struct fixed31_32 end_value = + dal_fixed31_32_from_int(125); + + arr_points[1].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + arr_points[2].slope = dal_fixed31_32_div( + dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y), + dal_fixed31_32_sub(end_value, arr_points[1].x)); + } + + regamma_params->hw_points_num = hw_points; + + i = 1; + for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) { + regamma_params->arr_curve_points[k].segments_num = + seg_distr[k]; + regamma_params->arr_curve_points[i].offset = + regamma_params->arr_curve_points[k]. + offset + (1 << seg_distr[k]); + } + i++; + } + + if (seg_distr[k] != -1) + regamma_params->arr_curve_points[k].segments_num = + seg_distr[k]; + + rgb = rgb_resulted; + rgb_plus_1 = rgb_resulted + 1; + + i = 1; + + while (i != hw_points + 1) { + if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dal_fixed31_32_sub( + rgb_plus_1->red, + rgb->red); + rgb->delta_green = dal_fixed31_32_sub( + rgb_plus_1->green, + rgb->green); + rgb->delta_blue = dal_fixed31_32_sub( + rgb_plus_1->blue, + rgb->blue); + + ++rgb_plus_1; + ++rgb; + ++i; + } + + convert_to_custom_float(rgb_resulted, arr_points, hw_points); + + return true; +} + +static bool dcn10_set_output_transfer_func( + struct pipe_ctx *pipe_ctx, + const struct core_surface *surface, + const struct core_stream *stream) +{ + struct output_pixel_processor *opp = pipe_ctx->opp; + + opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + + if (stream->public.out_transfer_func && + stream->public.out_transfer_func->type == + TF_TYPE_PREDEFINED && + stream->public.out_transfer_func->tf == + TRANSFER_FUNCTION_SRGB) { + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); + } else if (dcn10_translate_regamma_to_hw_format( + stream->public.out_transfer_func, &opp->regamma_params)) { + opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + } else { + opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); + } + + return true; +} + +static void dcn10_pipe_control_lock( + struct core_dc *dc, + struct pipe_ctx *pipe, + bool lock) +{ + struct dce_hwseq *hws = hws = dc->hwseq; + + /* use TG master update lock to lock everything on the TG + * therefore only top pipe need to lock + */ + if (pipe->top_pipe) + return; + + if (lock) + dcn10_lock(pipe->tg); + else + dcn10_unlock(pipe->tg); +} + +static bool wait_for_reset_trigger_to_occur( + struct dc_context *dc_ctx, + struct timing_generator *tg) +{ + bool rc = false; + + /* To avoid endless loop we wait at most + * frames_to_wait_on_triggered_reset frames for the reset to occur. */ + const uint32_t frames_to_wait_on_triggered_reset = 10; + int i; + + for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { + + if (!tg->funcs->is_counter_moving(tg)) { + DC_ERROR("TG counter is not moving!\n"); + break; + } + + if (tg->funcs->did_triggered_reset_occur(tg)) { + rc = true; + /* usually occurs at i=1 */ + DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", + i); + break; + } + + /* Wait for one frame. */ + tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); + tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); + } + + if (false == rc) + DC_ERROR("GSL: Timeout on reset trigger!\n"); + + return rc; +} + +static void dcn10_enable_timing_synchronization( + struct core_dc *dc, + int group_index, + int group_size, + struct pipe_ctx *grouped_pipes[]) +{ + struct dc_context *dc_ctx = dc->ctx; + int i; + + DC_SYNC_INFO("Setting up OTG reset trigger\n"); + + for (i = 1; i < group_size; i++) + grouped_pipes[i]->tg->funcs->enable_reset_trigger( + grouped_pipes[i]->tg, grouped_pipes[0]->tg->inst); + + + DC_SYNC_INFO("Waiting for trigger\n"); + + /* Need to get only check 1 pipe for having reset as all the others are + * synchronized. Look at last pipe programmed to reset. + */ + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->tg); + for (i = 1; i < group_size; i++) + grouped_pipes[i]->tg->funcs->disable_reset_trigger( + grouped_pipes[i]->tg); + + DC_SYNC_INFO("Sync complete\n"); +} + +static void dcn10_power_on_fe( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + struct dc_surface *dc_surface = &pipe_ctx->surface->public; + + /* power up DCHUP and DPP from pseudo code pipe_move.c */ + /*TODO: function: power_on_plane. If already power up, skip + */ + { + power_on_plane(dc->ctx, + pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + + /* enable DCFCLK current DCHUB */ + enable_dcfclk(dc->ctx, + pipe_ctx->pipe_idx, + pipe_ctx->pix_clk_params.requested_pix_clk, + context->dppclk_div); + + if (dc_surface) { + dm_logger_write(dc->ctx->logger, LOG_DC, + "Pipe:%d 0x%x: addr hi:0x%x, " + "addr low:0x%x, " + "src: %d, %d, %d," + " %d; dst: %d, %d, %d, %d;\n", + pipe_ctx->pipe_idx, + dc_surface, + dc_surface->address.grph.addr.high_part, + dc_surface->address.grph.addr.low_part, + dc_surface->src_rect.x, + dc_surface->src_rect.y, + dc_surface->src_rect.width, + dc_surface->src_rect.height, + dc_surface->dst_rect.x, + dc_surface->dst_rect.y, + dc_surface->dst_rect.width, + dc_surface->dst_rect.height); + + dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, + "Pipe %d: width, height, x, y\n" + "viewport:%d, %d, %d, %d\n" + "recout: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->scl_data.viewport.width, + pipe_ctx->scl_data.viewport.height, + pipe_ctx->scl_data.viewport.x, + pipe_ctx->scl_data.viewport.y, + pipe_ctx->scl_data.recout.width, + pipe_ctx->scl_data.recout.height, + pipe_ctx->scl_data.recout.x, + pipe_ctx->scl_data.recout.y); + } + } + +} + +static void program_gamut_remap(struct pipe_ctx *pipe_ctx) +{ + struct xfm_grph_csc_adjustment adjust; + memset(&adjust, 0, sizeof(adjust)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + + if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + adjust.temperature_matrix[0] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[0]; + adjust.temperature_matrix[1] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[1]; + adjust.temperature_matrix[2] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[2]; + adjust.temperature_matrix[3] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[4]; + adjust.temperature_matrix[4] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[5]; + adjust.temperature_matrix[5] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[6]; + adjust.temperature_matrix[6] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[8]; + adjust.temperature_matrix[7] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[9]; + adjust.temperature_matrix[8] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[10]; + } + + pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); +} + +static void update_dchubp_dpp( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + struct mem_input *mi = pipe_ctx->mi; + struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct core_surface *surface = pipe_ctx->surface; + union plane_size size = surface->public.plane_size; + struct mpc_tree_cfg *tree_cfg = NULL; + struct default_adjustment ocsc = {0}; + enum dc_color_space color_space; + struct tg_color black_color = {0}; + struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); + + /* depends on DML calculation, DPP clock value may change dynamically */ + enable_dppclk( + dc->ctx, + pipe_ctx->pipe_idx, + pipe_ctx->pix_clk_params.requested_pix_clk, + context->dppclk_div); + + select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + + update_plane_addr(dc, pipe_ctx); + + mi->funcs->mem_input_setup( + mi, + &pipe_ctx->dlg_regs, + &pipe_ctx->ttu_regs, + &pipe_ctx->rq_regs, + &pipe_ctx->pipe_dlg_param); + + size.grph.surface_size = pipe_ctx->scl_data.viewport; + + if (dc->public.config.gpu_vm_support) + mi->funcs->mem_input_program_pte_vm( + pipe_ctx->mi, + surface->public.format, + &surface->public.tiling_info, + surface->public.rotation); + + ipp->funcs->ipp_setup(ipp, + surface->public.format, + 1, + IPP_OUTPUT_FORMAT_12_BIT_FIX); + + /* mpc TODO un-hardcode object ids + * for pseudo code pipe_move.c : + * add_plane_mpcc(added_plane_inst, mpcc_inst, ...); + * Do we want to cache the tree_cfg? + */ + + /* TODO: build stream pipes group id. For now, use stream otg + * id as pipe group id + */ + pipe_ctx->mpc_idx = pipe_ctx->tg->inst; + tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + /* enable when bottom pipe is present and + * it does not share a surface with current pipe + */ + if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) { + pipe_ctx->scl_data.lb_params.alpha_en = 1; + tree_cfg->mode = TOP_BLND; + } else { + pipe_ctx->scl_data.lb_params.alpha_en = 0; + tree_cfg->mode = TOP_PASSTHRU; + } + if (!pipe_ctx->top_pipe) { + /* primary pipe, set mpc tree index 0 only */ + tree_cfg->num_pipes = 1; + tree_cfg->opp_id = pipe_ctx->tg->inst; + tree_cfg->dpp[0] = pipe_ctx->pipe_idx; + tree_cfg->mpcc[0] = pipe_ctx->pipe_idx; + dcn10_set_mpc_tree(mpc, tree_cfg); + } else { + /* TODO: add position is hard code to 1 for now + * If more than 2 pipes are supported, calculate position + */ + dcn10_add_dpp(mpc, tree_cfg, + pipe_ctx->pipe_idx, pipe_ctx->pipe_idx, 1); + } + + color_space = pipe_ctx->stream->public.output_color_space; + color_space_to_black_color(dc, color_space, &black_color); + dcn10_set_mpc_background_color(mpc, pipe_ctx->pipe_idx, &black_color); + + pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + /* scaler configuration */ + pipe_ctx->xfm->funcs->transform_set_scaler( + pipe_ctx->xfm, &pipe_ctx->scl_data); + + /*gamut remap*/ + program_gamut_remap(pipe_ctx); + + /*TODO add adjustments parameters*/ + ocsc.out_color_space = pipe_ctx->stream->public.output_color_space; + pipe_ctx->opp->funcs->opp_set_csc_default(pipe_ctx->opp, &ocsc); + + mi->funcs->mem_input_program_surface_config( + mi, + surface->public.format, + &surface->public.tiling_info, + &size, + surface->public.rotation, + &surface->public.dcc, + surface->public.horizontal_mirror, + surface->public.visible); + + /* Only support one plane for now. */ + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !surface->public.visible); + +} + +static void program_all_pipe_in_tree( + struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct validate_context *context) +{ + unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; + + if (pipe_ctx->surface->public.visible || pipe_ctx->top_pipe == NULL) { + dcn10_power_on_fe(dc, pipe_ctx, context); + + /* lock otg_master_update to process all pipes associated with + * this OTG. this is done only one time. + */ + if (pipe_ctx->top_pipe == NULL) { + /* watermark is for all pipes */ + pipe_ctx->mi->funcs->program_watermarks( + pipe_ctx->mi, &context->watermarks, ref_clk_mhz); + lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); + } + pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; + pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; + pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; + pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; + pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + pipe_ctx->tg->funcs->program_global_sync( + pipe_ctx->tg); + update_dchubp_dpp(dc, pipe_ctx, context); + } + + if (pipe_ctx->bottom_pipe != NULL) + program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); +} + +static void dcn10_pplib_apply_display_requirements( + struct core_dc *dc, + struct validate_context *context) +{ + struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; + + pp_display_cfg->all_displays_in_sync = false;/*todo*/ + pp_display_cfg->nb_pstate_switch_disable = false; + pp_display_cfg->min_engine_clock_khz = context->dcfclk_khz; + pp_display_cfg->min_memory_clock_khz = context->fclk_khz; + pp_display_cfg->min_engine_clock_deep_sleep_khz = context->dcfclk_deep_sleep_khz; + pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->dcfclk_deep_sleep_khz; + pp_display_cfg->avail_mclk_switch_time_us = + context->dram_ccm_us > 0 ? context->dram_ccm_us : 0; + pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = + context->min_active_dram_ccm_us > 0 ? context->min_active_dram_ccm_us : 0; + pp_display_cfg->min_dcfclock_khz = context->dcfclk_khz; + pp_display_cfg->disp_clk_khz = context->dispclk_khz; + dce110_fill_display_configs(context, pp_display_cfg); + + if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( + struct dm_pp_display_configuration)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + + dc->prev_display_config = *pp_display_cfg; +} + +static void dcn10_apply_ctx_for_surface( + struct core_dc *dc, + struct core_surface *surface, + struct validate_context *context) +{ + int i; + + memcpy(context->res_ctx.mpc_tree, + dc->current_context->res_ctx.mpc_tree, + sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->surface) + continue; + + /* looking for top pipe to program */ + if (!pipe_ctx->top_pipe) + program_all_pipe_in_tree(dc, pipe_ctx, context); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->surface || pipe_ctx->top_pipe) + continue; + + /* unlock master update lock */ + unlock_otg_master(dc->ctx, pipe_ctx->tg->inst); + } + + /* reset unused pipe */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[i]; + + if ((!pipe_ctx->surface && old_pipe_ctx->surface) + || (!pipe_ctx->stream && old_pipe_ctx->stream)) + reset_front_end_for_pipe(dc, + old_pipe_ctx, dc->current_context); + } +} + +static void dcn10_set_bandwidth( + struct core_dc *dc, + struct validate_context *context, + bool decrease_allowed) +{ + struct dm_pp_clock_for_voltage_req clock; + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + return; + + if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, + context->dispclk_khz); + dc->current_context->dispclk_khz = context->dispclk_khz; + } + if (decrease_allowed || context->dcfclk_khz > dc->current_context->dcfclk_khz) { + clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock.clocks_in_khz = context->dcfclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + } + if (decrease_allowed || context->fclk_khz > dc->current_context->fclk_khz) { + clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; + clock.clocks_in_khz = context->fclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->fclk_khz = clock.clocks_in_khz ; + } + dcn10_pplib_apply_display_requirements(dc, context); +} + +static void dcn10_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) +{ + struct dc_context *ctx = dc->ctx; + uint32_t inst_offset = 0; + + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 1); + dpp_pg_control(ctx, pipe->pipe_idx, false); + hubp_pg_control(ctx, pipe->pipe_idx, false); + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 0); + + if (pipe->xfm) + pipe->xfm->funcs->transform_reset(pipe->xfm); + memset(&pipe->scl_data, 0, sizeof(pipe->scl_data)); +} + +static void set_drr(struct pipe_ctx **pipe_ctx, + int num_pipes, int vmin, int vmax) +{ + int i = 0; + struct drr_params params = {0}; + + params.vertical_total_max = vmax; + params.vertical_total_min = vmin; + + /* TODO: If multiple pipes are to be supported, you need + * some GSL stuff + */ + for (i = 0; i < num_pipes; i++) { + pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, ¶ms); + } +} + +static void get_position(struct pipe_ctx **pipe_ctx, + int num_pipes, + struct crtc_position *position) +{ + int i = 0; + + /* TODO: handle pipes > 1 + */ + for (i = 0; i < num_pipes; i++) + pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position); +} + +static void set_static_screen_control(struct pipe_ctx **pipe_ctx, + int num_pipes, const struct dc_static_screen_events *events) +{ + unsigned int i; + unsigned int value = 0; + + if (events->surface_update) + value |= 0x80; + if (events->cursor_update) + value |= 0x2; + + for (i = 0; i < num_pipes; i++) + pipe_ctx[i]->tg->funcs-> + set_static_screen_control(pipe_ctx[i]->tg, value); +} + +static void set_plane_config( + const struct core_dc *dc, + struct pipe_ctx *pipe_ctx, + struct resource_context *res_ctx) +{ + /* TODO */ + program_gamut_remap(pipe_ctx); +} + +static const struct hw_sequencer_funcs dcn10_funcs = { + .init_hw = init_hw, + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, + .set_plane_config = set_plane_config, + .update_plane_addr = update_plane_addr, + .update_pending_status = dce110_update_pending_status, + .set_input_transfer_func = dcn10_set_input_transfer_func, + .set_output_transfer_func = dcn10_set_output_transfer_func, + .power_down = dce110_power_down, + .enable_accelerated_mode = dce110_enable_accelerated_mode, + .enable_timing_synchronization = dcn10_enable_timing_synchronization, + .update_info_frame = dce110_update_info_frame, + .enable_stream = dce110_enable_stream, + .disable_stream = dce110_disable_stream, + .unblank_stream = dce110_unblank_stream, + .enable_display_pipe_clock_gating = NULL, /* TODOFPGA */ + .enable_display_power_gating = dcn10_enable_display_power_gating, + .power_down_front_end = dcn10_power_down_fe, + .power_on_front_end = dcn10_power_on_fe, + .pipe_control_lock = dcn10_pipe_control_lock, + .set_bandwidth = dcn10_set_bandwidth, + .reset_hw_ctx_wrap = reset_hw_ctx_wrap, + .prog_pixclk_crtc_otg = dcn10_prog_pixclk_crtc_otg, + .set_drr = set_drr, + .get_position = get_position, + .set_static_screen_control = set_static_screen_control +}; + + +bool dcn10_hw_sequencer_construct(struct core_dc *dc) +{ + dc->hwss = dcn10_funcs; + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h new file mode 100644 index 000000000000..c3aff2eb8d68 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -0,0 +1,38 @@ +/* +* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCN10_H__ +#define __DC_HWSS_DCN10_H__ + +#include "core_types.h" + +struct core_dc; + +bool dcn10_hw_sequencer_construct(struct core_dc *dc); +extern void fill_display_configs( + const struct validate_context *context, + struct dm_pp_display_configuration *pp_display_cfg); + +#endif /* __DC_HWSS_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c new file mode 100644 index 000000000000..3062b7de4fe2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -0,0 +1,883 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn10_ipp.h" +#include "reg_helper.h" + +#define REG(reg) \ + (ippn10->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + ippn10->ipp_shift->field_name, ippn10->ipp_mask->field_name + +#define CTX \ + ippn10->base.ctx + + +struct dcn10_input_csc_matrix { + enum dc_color_space color_space; + uint32_t regval[12]; +}; + +static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { + {COLOR_SPACE_SRGB, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_SRGB_LIMITED, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_YCBCR601, + {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, + 0, 0x2000, 0x38b4, 0xe3a6} }, + {COLOR_SPACE_YCBCR601_LIMITED, + {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, + 0, 0x2568, 0x40de, 0xdd3a} }, + {COLOR_SPACE_YCBCR709, + {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, + 0x2000, 0x3b61, 0xe24f} }, + + {COLOR_SPACE_YCBCR709_LIMITED, + {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, + 0x2568, 0x43ee, 0xdbb2} } +}; + +enum dcn10_input_csc_select { + INPUT_CSC_SELECT_BYPASS = 0, + INPUT_CSC_SELECT_ICSC, + INPUT_CSC_SELECT_COMA +}; + +static void dcn10_program_input_csc( + struct input_pixel_processor *ipp, + enum dc_color_space color_space, + enum dcn10_input_csc_select select) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + int i; + int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); + const uint32_t *regval = NULL; + uint32_t selection = 1; + + if (select == INPUT_CSC_SELECT_BYPASS) { + REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0); + return; + } + + for (i = 0; i < arr_size; i++) + if (dcn10_input_csc_matrix[i].color_space == color_space) { + regval = dcn10_input_csc_matrix[i].regval; + break; + } + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + if (select == INPUT_CSC_SELECT_COMA) + selection = 2; + REG_SET(CM_ICSC_CONTROL, 0, + CM_ICSC_MODE, selection); + + if (select == INPUT_CSC_SELECT_ICSC) { + /*R*/ + REG_SET_2(CM_ICSC_C11_C12, 0, + CM_ICSC_C11, regval[0], + CM_ICSC_C12, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C13_C14, 0, + CM_ICSC_C13, regval[0], + CM_ICSC_C14, regval[1]); + /*G*/ + regval += 2; + REG_SET_2(CM_ICSC_C21_C22, 0, + CM_ICSC_C21, regval[0], + CM_ICSC_C22, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C23_C24, 0, + CM_ICSC_C23, regval[0], + CM_ICSC_C24, regval[1]); + /*B*/ + regval += 2; + REG_SET_2(CM_ICSC_C31_C32, 0, + CM_ICSC_C31, regval[0], + CM_ICSC_C32, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C33_C34, 0, + CM_ICSC_C33, regval[0], + CM_ICSC_C34, regval[1]); + } else { + /*R*/ + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + /*G*/ + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + /*B*/ + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + } +} + +/*program de gamma RAM B*/ +static void dcn10_ipp_program_degamma_lutb_settings( + struct input_pixel_processor *ipp, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0, + CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0, + CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0, + CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0, + CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0, + CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0, + CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); + + curve = params->arr_curve_points; + REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0, + CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0, + CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0, + CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0, + CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0, + CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0, + CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0, + CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0, + CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program de gamma RAM A*/ +static void dcn10_ipp_program_degamma_luta_settings( + struct input_pixel_processor *ipp, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0, + CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0, + CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0, + CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0, + CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0, + CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0, + CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); + + curve = params->arr_curve_points; + REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0, + CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0, + CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0, + CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0, + CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0, + CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0, + CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0, + CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0, + CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); +} + +static void ipp_power_on_degamma_lut( + struct input_pixel_processor *ipp, + bool power_on) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_SET(CM_MEM_PWR_CTRL, 0, + SHARED_MEM_PWR_DIS, power_on == true ? 0:1); + +} + +static void ipp_program_degamma_lut( + struct input_pixel_processor *ipp, + const struct pwl_result_data *rgb, + uint32_t num, + bool is_ram_a) +{ + uint32_t i; + + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); + REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, + CM_DGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, + is_ram_a == true ? 0:1); + + REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0); + for (i = 0 ; i < num; i++) { + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg); + + } + +} + +static void dcn10_ipp_enable_cm_block( + struct input_pixel_processor *ipp) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1); + REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); +} + + +static void dcn10_ipp_full_bypass(struct input_pixel_processor *ipp) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + /* Input pixel format: ARGB8888 */ + REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, 0x8); + + /* Zero expansion */ + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + ALPHA_EN, 0, + FORMAT_EXPANSION_MODE, 0); + + /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ + REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); + + /* Setting degamma bypass for now */ + REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); + REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); +} + +static void dcn10_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + dcn10_ipp_enable_cm_block(ipp); + + switch (mode) { + case IPP_DEGAMMA_MODE_BYPASS: + /* Setting de gamma bypass for now */ + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0); + break; + case IPP_DEGAMMA_MODE_HW_sRGB: + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1); + break; + case IPP_DEGAMMA_MODE_HW_xvYCC: + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } +} + +static bool dcn10_cursor_program_control( + struct dcn10_ipp *ippn10, + bool pixel_data_invert, + enum dc_cursor_color_format color_format) +{ + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + + REG_UPDATE_2(CURSOR0_CONTROL, + CUR0_MODE, color_format, + CUR0_INVERT_MODE, 0); + + if (color_format == CURSOR_MODE_MONO) { + /* todo: clarify what to program these to */ + REG_UPDATE(CURSOR0_COLOR0, + CUR0_COLOR0, 0x00000000); + REG_UPDATE(CURSOR0_COLOR1, + CUR0_COLOR1, 0xFFFFFFFF); + } + + /* TODO: Fixed vs float */ + + REG_UPDATE_3(FORMAT_CONTROL, + CNVC_BYPASS, 0, + ALPHA_EN, 1, + FORMAT_EXPANSION_MODE, 0); + + REG_UPDATE(CURSOR0_CONTROL, + CUR0_EXPANSION_MODE, 0); + + if (0 /*attributes->attribute_flags.bits.MIN_MAX_INVERT*/) { + REG_UPDATE(CURSOR0_CONTROL, + CUR0_MAX, + 0 /* TODO */); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_MIN, + 0 /* TODO */); + } + + return true; +} + +enum cursor_pitch { + CURSOR_PITCH_64_PIXELS = 0, + CURSOR_PITCH_128_PIXELS, + CURSOR_PITCH_256_PIXELS +}; + +enum cursor_lines_per_chunk { + CURSOR_LINE_PER_CHUNK_2 = 1, + CURSOR_LINE_PER_CHUNK_4, + CURSOR_LINE_PER_CHUNK_8, + CURSOR_LINE_PER_CHUNK_16 +}; + +static enum cursor_pitch dcn10_get_cursor_pitch( + unsigned int pitch) +{ + enum cursor_pitch hw_pitch; + + switch (pitch) { + case 64: + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + case 128: + hw_pitch = CURSOR_PITCH_128_PIXELS; + break; + case 256: + hw_pitch = CURSOR_PITCH_256_PIXELS; + break; + default: + DC_ERR("Invalid cursor pitch of %d. " + "Only 64/128/256 is supported on DCN.\n", pitch); + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + } + return hw_pitch; +} + +static enum cursor_lines_per_chunk dcn10_get_lines_per_chunk( + unsigned int cur_width, + enum dc_cursor_color_format format) +{ + enum cursor_lines_per_chunk line_per_chunk; + + if (format == CURSOR_MODE_MONO) + /* impl B. expansion in CUR Buffer reader */ + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 32) + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 64) + line_per_chunk = CURSOR_LINE_PER_CHUNK_8; + else if (cur_width <= 128) + line_per_chunk = CURSOR_LINE_PER_CHUNK_4; + else + line_per_chunk = CURSOR_LINE_PER_CHUNK_2; + + return line_per_chunk; +} + +static void dcn10_cursor_set_attributes( + struct input_pixel_processor *ipp, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + enum cursor_pitch hw_pitch = dcn10_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = dcn10_get_lines_per_chunk( + attr->width, attr->color_format); + + ippn10->curs_attr = *attr; + + REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, + CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); + REG_UPDATE(CURSOR_SURFACE_ADDRESS, + CURSOR_SURFACE_ADDRESS, attr->address.low_part); + + REG_UPDATE_2(CURSOR_SIZE, + CURSOR_WIDTH, attr->width, + CURSOR_HEIGHT, attr->height); + + REG_UPDATE_3(CURSOR_CONTROL, + CURSOR_MODE, attr->color_format, + CURSOR_PITCH, hw_pitch, + CURSOR_LINES_PER_CHUNK, lpc); + + dcn10_cursor_program_control(ippn10, + attr->attribute_flags.bits.INVERT_PIXEL_DATA, + attr->color_format); +} + +static void dcn10_cursor_set_position( + struct input_pixel_processor *ipp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; + + dst_x_offset *= param->ref_clk_khz; + dst_x_offset /= param->pixel_clk_khz; + + ASSERT(param->h_scale_ratio.value); + + if (param->h_scale_ratio.value) + dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( + dal_fixed31_32_from_int(dst_x_offset), + param->h_scale_ratio)); + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)ippn10->curs_attr.width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) + dcn10_cursor_set_attributes(ipp, &ippn10->curs_attr); + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, cur_en); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, cur_en); + + REG_SET_2(CURSOR_POSITION, 0, + CURSOR_X_POSITION, pos->x, + CURSOR_Y_POSITION, pos->y); + + REG_SET_2(CURSOR_HOT_SPOT, 0, + CURSOR_HOT_SPOT_X, pos->x_hotspot, + CURSOR_HOT_SPOT_Y, pos->y_hotspot); + + REG_SET(CURSOR_DST_OFFSET, 0, + CURSOR_DST_X_OFFSET, dst_x_offset); + /* TODO Handle surface pixel formats other than 4:4:4 */ +} + +enum pixel_format_description { + PIXEL_FORMAT_FIXED = 0, + PIXEL_FORMAT_FIXED16, + PIXEL_FORMAT_FLOAT + +}; + +static void dcn10_setup_format_flags(enum surface_pixel_format input_format,\ + enum pixel_format_description *fmt) +{ + + if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || + input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) + *fmt = PIXEL_FORMAT_FLOAT; + else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) + *fmt = PIXEL_FORMAT_FIXED16; + else + *fmt = PIXEL_FORMAT_FIXED; +} + +static void dcn10_ipp_set_degamma_format_float(struct input_pixel_processor *ipp, + bool is_float) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + if (is_float) { + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1); + } else { + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2); + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0); + } +} + + +static void dcn10_ipp_cnv_setup ( + struct input_pixel_processor *ipp, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format cnv_out_format) +{ + uint32_t pixel_format; + uint32_t alpha_en; + enum pixel_format_description fmt ; + enum dc_color_space color_space; + enum dcn10_input_csc_select select; + bool is_float; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + bool force_disable_cursor = false; + + dcn10_setup_format_flags(input_format, &fmt); + alpha_en = 1; + pixel_format = 0; + color_space = COLOR_SPACE_SRGB; + select = INPUT_CSC_SELECT_BYPASS; + is_float = false; + + switch (fmt) { + case PIXEL_FORMAT_FIXED: + case PIXEL_FORMAT_FIXED16: + /*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/ + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode, + OUTPUT_FP, 0); + break; + case PIXEL_FORMAT_FLOAT: + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode, + OUTPUT_FP, 1); + is_float = true; + break; + default: + + break; + } + + dcn10_ipp_set_degamma_format_float(ipp, is_float); + + switch (input_format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + pixel_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + pixel_format = 3; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + pixel_format = 8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + pixel_format = 10; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + force_disable_cursor = false; + pixel_format = 65; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + force_disable_cursor = true; + pixel_format = 64; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + force_disable_cursor = true; + pixel_format = 67; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + force_disable_cursor = true; + pixel_format = 66; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + pixel_format = 22; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + pixel_format = 24; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + pixel_format = 25; + break; + default: + break; + } + REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, pixel_format); + REG_UPDATE(FORMAT_CONTROL, ALPHA_EN, alpha_en); + + dcn10_program_input_csc(ipp, color_space, select); + + if (force_disable_cursor) { + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, 0); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, 0); + } +} + + +static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, + bool *ram_a_inuse) +{ + bool ret = false; + uint32_t status_reg = 0; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + status_reg = (REG_READ(CM_IGAM_LUT_RW_CONTROL) & 0x0F00) >>16; + if (status_reg == 9) { + *ram_a_inuse = true; + ret = true; + } else if (status_reg == 10) { + *ram_a_inuse = false; + ret = true; + } + return ret; +} + +static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, + bool use_ram_a) +{ + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + if (use_ram_a) + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); + else + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4); + +} + +static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, + const struct pwl_params *params) +{ + bool is_ram_a = true; + + ipp_power_on_degamma_lut(ipp, true); + dcn10_ipp_enable_cm_block(ipp); + dcn10_degamma_ram_inuse(ipp, &is_ram_a); + if (is_ram_a == true) + dcn10_ipp_program_degamma_lutb_settings(ipp, params); + else + dcn10_ipp_program_degamma_luta_settings(ipp, params); + + ipp_program_degamma_lut(ipp, params->rgb_resulted, + params->hw_points_num, !is_ram_a); + dcn10_degamma_ram_select(ipp, !is_ram_a); +} + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) +{ + dm_free(TO_DCN10_IPP(*ipp)); + *ipp = NULL; +} + +static const struct ipp_funcs dcn10_ipp_funcs = { + .ipp_cursor_set_attributes = dcn10_cursor_set_attributes, + .ipp_cursor_set_position = dcn10_cursor_set_position, + .ipp_set_degamma = dcn10_ipp_set_degamma, + .ipp_full_bypass = dcn10_ipp_full_bypass, + .ipp_setup = dcn10_ipp_cnv_setup, + .ipp_program_degamma_pwl = dcn10_ipp_set_degamma_pwl, + .ipp_destroy = dcn10_ipp_destroy +}; + +void dcn10_ipp_construct( + struct dcn10_ipp *ippn10, + struct dc_context *ctx, + int inst, + const struct dcn10_ipp_registers *regs, + const struct dcn10_ipp_shift *ipp_shift, + const struct dcn10_ipp_mask *ipp_mask) +{ + ippn10->base.ctx = ctx; + ippn10->base.inst = inst; + ippn10->base.funcs = &dcn10_ipp_funcs; + + ippn10->regs = regs; + ippn10->ipp_shift = ipp_shift; + ippn10->ipp_mask = ipp_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h new file mode 100644 index 000000000000..a4ea4e774c72 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -0,0 +1,549 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN10_IPP_H_ +#define _DCN10_IPP_H_ + +#include "ipp.h" + +#define TO_DCN10_IPP(ipp)\ + container_of(ipp, struct dcn10_ipp, base) + +#define IPP_DCN10_REG_LIST(id) \ + SRI(CM_ICSC_CONTROL, CM, id), \ + SRI(CM_ICSC_C11_C12, CM, id), \ + SRI(CM_ICSC_C13_C14, CM, id), \ + SRI(CM_ICSC_C21_C22, CM, id), \ + SRI(CM_ICSC_C23_C24, CM, id), \ + SRI(CM_ICSC_C31_C32, CM, id), \ + SRI(CM_ICSC_C33_C34, CM, id), \ + SRI(CM_COMA_C11_C12, CM, id), \ + SRI(CM_COMA_C13_C14, CM, id), \ + SRI(CM_COMA_C21_C22, CM, id), \ + SRI(CM_COMA_C23_C24, CM, id), \ + SRI(CM_COMA_C31_C32, CM, id), \ + SRI(CM_COMA_C33_C34, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_B, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_B, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_G, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_G, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_R, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_R, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_0_1, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_2_3, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_4_5, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_6_7, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_8_9, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_10_11, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_12_13, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_14_15, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_B, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_B, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_G, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_G, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_R, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_R, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_0_1, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_2_3, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_4_5, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_6_7, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_8_9, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_10_11, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ + SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ + SRI(CM_DGAM_LUT_INDEX, CM, id), \ + SRI(CM_DGAM_LUT_DATA, CM, id), \ + SRI(CM_CONTROL, CM, id), \ + SRI(CM_DGAM_CONTROL, CM, id), \ + SRI(CM_IGAM_CONTROL, CM, id), \ + SRI(DPP_CONTROL, DPP_TOP, id), \ + SRI(CURSOR_SETTINS, HUBPREQ, id), \ + SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR1, CNVC_CUR, id), \ + SRI(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ + SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ + SRI(CURSOR_SIZE, CURSOR, id), \ + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CURSOR_POSITION, CURSOR, id), \ + SRI(CURSOR_HOT_SPOT, CURSOR, id), \ + SRI(CURSOR_DST_OFFSET, CURSOR, id) + +#define IPP_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define IPP_DCN10_MASK_SH_LIST(mask_sh) \ + IPP_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C13, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C14, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C21, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C22, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C23, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C24, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C31, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ + IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ + IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ + IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ + IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ + IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh), \ + IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh), \ + IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh), \ + IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh), \ + IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh), \ + IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh), \ + IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh), \ + IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh), \ + IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_B, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_G, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_R, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_B, CM_DGAM_RAMB_EXP_REGION_END_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_G, CM_DGAM_RAMB_EXP_REGION_END_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_R, CM_DGAM_RAMB_EXP_REGION_END_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_B, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_G, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_R, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_B, CM_DGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_G, CM_DGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_R, CM_DGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ + IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ + IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ + IPP_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ + IPP_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ + IPP_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ + IPP_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ + IPP_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ + IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ + IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ + IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ + IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_INVERT_MODE, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MAX, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MIN, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, mask_sh), \ + IPP_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh) + +#define IPP_DCN10_REG_FIELD_LIST(type) \ + type CM_ICSC_MODE; \ + type CM_ICSC_C11; \ + type CM_ICSC_C12; \ + type CM_ICSC_C13; \ + type CM_ICSC_C14; \ + type CM_ICSC_C21; \ + type CM_ICSC_C22; \ + type CM_ICSC_C23; \ + type CM_ICSC_C24; \ + type CM_ICSC_C31; \ + type CM_ICSC_C32; \ + type CM_ICSC_C33; \ + type CM_ICSC_C34; \ + type CM_COMA_C11; \ + type CM_COMA_C12; \ + type CM_COMA_C13; \ + type CM_COMA_C14; \ + type CM_COMA_C21; \ + type CM_COMA_C22; \ + type CM_COMA_C23; \ + type CM_COMA_C24; \ + type CM_COMA_C31; \ + type CM_COMA_C32; \ + type CM_COMA_C33; \ + type CM_COMA_C34; \ + type CM_DGAM_RAMB_EXP_REGION_START_B; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_DGAM_RAMB_EXP_REGION_START_G; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_DGAM_RAMB_EXP_REGION_START_R; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION_START_B; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_DGAM_RAMA_EXP_REGION_START_G; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_DGAM_RAMA_EXP_REGION_START_R; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type SHARED_MEM_PWR_DIS; \ + type CM_IGAM_LUT_HOST_EN; \ + type CM_DGAM_LUT_WRITE_EN_MASK; \ + type CM_DGAM_LUT_WRITE_SEL; \ + type CM_DGAM_LUT_INDEX; \ + type CM_DGAM_LUT_DATA; \ + type DPP_CLOCK_ENABLE; \ + type CM_BYPASS_EN; \ + type CNVC_SURFACE_PIXEL_FORMAT; \ + type CNVC_BYPASS; \ + type ALPHA_EN; \ + type FORMAT_EXPANSION_MODE; \ + type CM_DGAM_LUT_MODE; \ + type CM_IGAM_LUT_MODE; \ + type CURSOR0_DST_Y_OFFSET; \ + type CURSOR0_CHUNK_HDL_ADJUST; \ + type CUR0_MODE; \ + type CUR0_INVERT_MODE; \ + type CUR0_COLOR0; \ + type CUR0_COLOR1; \ + type CUR0_EXPANSION_MODE; \ + type CUR0_MAX; \ + type CUR0_MIN; \ + type CURSOR_SURFACE_ADDRESS_HIGH; \ + type CURSOR_SURFACE_ADDRESS; \ + type CURSOR_WIDTH; \ + type CURSOR_HEIGHT; \ + type CURSOR_MODE; \ + type CURSOR_PITCH; \ + type CURSOR_LINES_PER_CHUNK; \ + type CURSOR_ENABLE; \ + type CUR0_ENABLE; \ + type CURSOR_X_POSITION; \ + type CURSOR_Y_POSITION; \ + type CURSOR_HOT_SPOT_X; \ + type CURSOR_HOT_SPOT_Y; \ + type CURSOR_DST_X_OFFSET; \ + type CM_IGAM_INPUT_FORMAT; \ + type OUTPUT_FP + +struct dcn10_ipp_shift { + IPP_DCN10_REG_FIELD_LIST(uint8_t); +}; + +struct dcn10_ipp_mask { + IPP_DCN10_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_ipp_registers { + uint32_t CM_ICSC_CONTROL; + uint32_t CM_ICSC_C11_C12; + uint32_t CM_ICSC_C13_C14; + uint32_t CM_ICSC_C21_C22; + uint32_t CM_ICSC_C23_C24; + uint32_t CM_ICSC_C31_C32; + uint32_t CM_ICSC_C33_C34; + uint32_t CM_COMA_C11_C12; + uint32_t CM_COMA_C13_C14; + uint32_t CM_COMA_C21_C22; + uint32_t CM_COMA_C23_C24; + uint32_t CM_COMA_C31_C32; + uint32_t CM_COMA_C33_C34; + uint32_t CM_DGAM_RAMB_START_CNTL_B; + uint32_t CM_DGAM_RAMB_START_CNTL_G; + uint32_t CM_DGAM_RAMB_START_CNTL_R; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_DGAM_RAMB_END_CNTL1_B; + uint32_t CM_DGAM_RAMB_END_CNTL2_B; + uint32_t CM_DGAM_RAMB_END_CNTL1_G; + uint32_t CM_DGAM_RAMB_END_CNTL2_G; + uint32_t CM_DGAM_RAMB_END_CNTL1_R; + uint32_t CM_DGAM_RAMB_END_CNTL2_R; + uint32_t CM_DGAM_RAMB_REGION_0_1; + uint32_t CM_DGAM_RAMB_REGION_2_3; + uint32_t CM_DGAM_RAMB_REGION_4_5; + uint32_t CM_DGAM_RAMB_REGION_6_7; + uint32_t CM_DGAM_RAMB_REGION_8_9; + uint32_t CM_DGAM_RAMB_REGION_10_11; + uint32_t CM_DGAM_RAMB_REGION_12_13; + uint32_t CM_DGAM_RAMB_REGION_14_15; + uint32_t CM_DGAM_RAMA_START_CNTL_B; + uint32_t CM_DGAM_RAMA_START_CNTL_G; + uint32_t CM_DGAM_RAMA_START_CNTL_R; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_DGAM_RAMA_END_CNTL1_B; + uint32_t CM_DGAM_RAMA_END_CNTL2_B; + uint32_t CM_DGAM_RAMA_END_CNTL1_G; + uint32_t CM_DGAM_RAMA_END_CNTL2_G; + uint32_t CM_DGAM_RAMA_END_CNTL1_R; + uint32_t CM_DGAM_RAMA_END_CNTL2_R; + uint32_t CM_DGAM_RAMA_REGION_0_1; + uint32_t CM_DGAM_RAMA_REGION_2_3; + uint32_t CM_DGAM_RAMA_REGION_4_5; + uint32_t CM_DGAM_RAMA_REGION_6_7; + uint32_t CM_DGAM_RAMA_REGION_8_9; + uint32_t CM_DGAM_RAMA_REGION_10_11; + uint32_t CM_DGAM_RAMA_REGION_12_13; + uint32_t CM_DGAM_RAMA_REGION_14_15; + uint32_t CM_MEM_PWR_CTRL; + uint32_t CM_IGAM_LUT_RW_CONTROL; + uint32_t CM_DGAM_LUT_WRITE_EN_MASK; + uint32_t CM_DGAM_LUT_INDEX; + uint32_t CM_DGAM_LUT_DATA; + uint32_t CM_CONTROL; + uint32_t CM_DGAM_CONTROL; + uint32_t CM_IGAM_CONTROL; + uint32_t DPP_CONTROL; + uint32_t CURSOR_SETTINS; + uint32_t CNVC_SURFACE_PIXEL_FORMAT; + uint32_t CURSOR0_CONTROL; + uint32_t CURSOR0_COLOR0; + uint32_t CURSOR0_COLOR1; + uint32_t FORMAT_CONTROL; + uint32_t CURSOR_SURFACE_ADDRESS_HIGH; + uint32_t CURSOR_SURFACE_ADDRESS; + uint32_t CURSOR_SIZE; + uint32_t CURSOR_CONTROL; + uint32_t CURSOR_POSITION; + uint32_t CURSOR_HOT_SPOT; + uint32_t CURSOR_DST_OFFSET; +}; + +struct dcn10_ipp { + struct input_pixel_processor base; + + const struct dcn10_ipp_registers *regs; + const struct dcn10_ipp_shift *ipp_shift; + const struct dcn10_ipp_mask *ipp_mask; + + struct dc_cursor_attributes curs_attr; +}; + +void dcn10_ipp_construct(struct dcn10_ipp *ippn10, + struct dc_context *ctx, + int inst, + const struct dcn10_ipp_registers *regs, + const struct dcn10_ipp_shift *ipp_shift, + const struct dcn10_ipp_mask *ipp_mask); + +#endif /* _DCN10_IPP_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c new file mode 100644 index 000000000000..bf89608b30e4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -0,0 +1,1102 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "dm_services.h" +#include "dce_calcs.h" +#include "dcn10_mem_input.h" +#include "reg_helper.h" +#include "basics/conversion.h" + +#define REG(reg)\ + mi->mi_regs->reg + +#define CTX \ + mi->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + mi->mi_shift->field_name, mi->mi_mask->field_name + +static void set_blank(struct dcn10_mem_input *mi, bool blank) +{ + uint32_t blank_en = blank ? 1 : 0; + + REG_UPDATE_2(DCHUBP_CNTL, + HUBP_BLANK_EN, blank_en, + HUBP_TTU_DISABLE, blank_en); +} + + +static void disable_request(struct mem_input *mem_input) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + /* To disable the requestors, set blank_en to 1 */ + set_blank(mi, true); +} + +static void vready_workaround(struct mem_input *mem_input, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) +{ + uint32_t value = 0; + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + /* set HBUBREQ_DEBUG_DB[12] = 1 */ + value = REG_READ(HUBPREQ_DEBUG_DB); + + /* hack mode disable */ + value |= 0x100; + value &= ~0x1000; + + if ((pipe_dest->vstartup_start - 2*(pipe_dest->vready_offset+pipe_dest->vupdate_width + + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { + /* if (eco_fix_needed(otg_global_sync_timing) + * set HBUBREQ_DEBUG_DB[12] = 1 */ + value |= 0x1000; + } + + REG_WRITE(HUBPREQ_DEBUG_DB, value); +} + +static void program_tiling( + struct dcn10_mem_input *mi, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format) +{ + REG_UPDATE_6(DCSURF_ADDR_CONFIG, + NUM_PIPES, log_2(info->gfx9.num_pipes), + NUM_BANKS, log_2(info->gfx9.num_banks), + PIPE_INTERLEAVE, info->gfx9.pipe_interleave, + NUM_SE, log_2(info->gfx9.num_shader_engines), + NUM_RB_PER_SE, log_2(info->gfx9.num_rb_per_se), + MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags)); + + REG_UPDATE_4(DCSURF_TILING_CONFIG, + SW_MODE, info->gfx9.swizzle, + META_LINEAR, info->gfx9.meta_linear, + RB_ALIGNED, info->gfx9.rb_aligned, + PIPE_ALIGNED, info->gfx9.pipe_aligned); +} + +static void program_size_and_rotation( + struct dcn10_mem_input *mi, + enum dc_rotation_angle rotation, + enum surface_pixel_format format, + const union plane_size *plane_size, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror) +{ + uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c, mirror; + + /* Program data and meta surface pitch (calculation from addrlib) + * 444 or 420 luma + */ + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + pitch = plane_size->video.luma_pitch - 1; + meta_pitch = dcc->video.meta_pitch_l - 1; + pitch_c = plane_size->video.chroma_pitch - 1; + meta_pitch_c = dcc->video.meta_pitch_c - 1; + } else { + pitch = plane_size->grph.surface_pitch - 1; + meta_pitch = dcc->grph.meta_pitch - 1; + pitch_c = 0; + meta_pitch_c = 0; + } + + if (!dcc->enable) { + meta_pitch = 0; + meta_pitch_c = 0; + } + + REG_UPDATE_2(DCSURF_SURFACE_PITCH, + PITCH, pitch, META_PITCH, meta_pitch); + + if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + REG_UPDATE_2(DCSURF_SURFACE_PITCH_C, + PITCH_C, pitch_c, META_PITCH_C, meta_pitch_c); + + if (horizontal_mirror) + mirror = 1; + else + mirror = 0; + + + /* Program rotation angle and horz mirror - no mirror */ + if (rotation == ROTATION_ANGLE_0) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 0, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_90) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 1, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_180) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 2, + H_MIRROR_EN, mirror); + else if (rotation == ROTATION_ANGLE_270) + REG_UPDATE_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, 3, + H_MIRROR_EN, mirror); +} + +static void program_pixel_format( + struct dcn10_mem_input *mi, + enum surface_pixel_format format) +{ + uint32_t red_bar = 3; + uint32_t blue_bar = 2; + + /* swap for ABGR format */ + if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS + || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) { + red_bar = 2; + blue_bar = 3; + } + + REG_UPDATE_2(HUBPRET_CONTROL, + CROSSBAR_SRC_CB_B, blue_bar, + CROSSBAR_SRC_CR_R, red_bar); + + /* Mapping is same as ipp programming (cnvc) */ + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 1); + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 3); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 8); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 10); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 22); + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/ + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 24); + break; + + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 65); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 64); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 67); + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + REG_UPDATE(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, 66); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + /* don't see the need of program the xbar in DCN 1.0 */ +} + +static bool mem_input_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + /* program flip type */ + + REG_UPDATE(DCSURF_FLIP_CONTROL, + SURFACE_FLIP_TYPE, flip_immediate); + + /* REG_UPDATE(FLIP_CONTROL, SURFACE_UPDATE_LOCK, 1); */ + + + /* program high first and then the low addr, order matters! */ + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) + break; + + if (address->grph.meta_addr.quad_part != 0) { + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph.meta_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + PRIMARY_META_SURFACE_ADDRESS, + address->grph.meta_addr.low_part); + } + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph.addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + PRIMARY_SURFACE_ADDRESS, + address->grph.addr.low_part); + + + /* DCN1.0 does not support const color + * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 + * base on address->grph.dcc_const_color + * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma + * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma + */ + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + if (address->video_progressive.luma_addr.quad_part == 0 + || address->video_progressive.chroma_addr.quad_part == 0) + break; + + if (address->video_progressive.luma_meta_addr.quad_part != 0) { + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_meta_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + PRIMARY_META_SURFACE_ADDRESS, + address->video_progressive.luma_meta_addr.low_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_meta_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, + PRIMARY_META_SURFACE_ADDRESS_C, + address->video_progressive.chroma_meta_addr.low_part); + } + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + PRIMARY_SURFACE_ADDRESS, + address->video_progressive.luma_addr.low_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_C, + PRIMARY_SURFACE_ADDRESS_C, + address->video_progressive.chroma_addr.low_part); + + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0) + break; + if (address->grph_stereo.right_addr.quad_part == 0) + break; + if (address->grph_stereo.right_meta_addr.quad_part != 0) { + + REG_UPDATE(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, + SECONDARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_meta_addr.high_part); + + REG_UPDATE(DCSURF_SECONDARY_META_SURFACE_ADDRESS, + SECONDARY_META_SURFACE_ADDRESS, + address->grph_stereo.right_meta_addr.low_part); + } + if (address->grph_stereo.left_meta_addr.quad_part != 0) { + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_meta_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + PRIMARY_META_SURFACE_ADDRESS, + address->grph_stereo.left_meta_addr.low_part); + } + + REG_UPDATE(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, + SECONDARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_addr.high_part); + + REG_UPDATE(DCSURF_SECONDARY_SURFACE_ADDRESS, + SECONDARY_SURFACE_ADDRESS, + address->grph_stereo.right_addr.low_part); + + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + PRIMARY_SURFACE_ADDRESS, + address->grph_stereo.left_addr.low_part); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + /* REG_UPDATE(FLIP_CONTROL, SURFACE_UPDATE_LOCK, 0); */ + + mem_input->request_address = *address; + + if (flip_immediate) + mem_input->current_address = *address; + + return true; +} + +static void program_control(struct dcn10_mem_input *mi, + struct dc_plane_dcc_param *dcc) +{ + uint32_t dcc_en = dcc->enable ? 1 : 0; + uint32_t dcc_ind_64b_blk = dcc->grph.independent_64b_blks ? 1 : 0; + + REG_UPDATE_2(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_DCC_EN, dcc_en, + PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); + +} + +static void mem_input_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror, + bool visible) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + program_control(mi, dcc); + program_tiling(mi, tiling_info, format); + program_size_and_rotation( + mi, rotation, format, plane_size, dcc, horizontal_mirror); + program_pixel_format(mi, format); + + set_blank(mi, !visible); +} + +static void program_requestor( + struct mem_input *mem_input, + struct _vcs_dpi_display_rq_regs_st *rq_regs) +{ + + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + REG_UPDATE(HUBPRET_CONTROL, + DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); + REG_SET_4(DCN_EXPANSION_MODE, 0, + DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode, + PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode, + MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode, + CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode); + REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0, + CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size, + MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size, + META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size, + MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size, + DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size, + MPTE_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size, + SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height, + PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear); + REG_SET_8(DCHUBP_REQ_SIZE_CONFIG_C, 0, + CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size, + MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size, + META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size, + MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size, + DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size, + MPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.mpte_group_size, + SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height, + PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear); +} + + +static void program_deadline( + struct mem_input *mem_input, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + /* DLG - Per hubp */ + REG_SET_2(BLANK_OFFSET_0, 0, + REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end, + DLG_V_BLANK_END, dlg_attr->dlg_vblank_end); + + REG_SET(BLANK_OFFSET_1, 0, + MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start); + + REG_SET(DST_DIMENSIONS, 0, + REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal); + + REG_SET_2(DST_AFTER_SCALER, 0, + REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, + DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); + + REG_SET_2(PREFETCH_SETTINS, 0, + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); + + REG_SET_2(VBLANK_PARAMETERS_0, 0, + DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, + DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); + + REG_SET(REF_FREQ_TO_PIX_FREQ, 0, + REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); + + /* DLG - Per luma/chroma */ + REG_SET(VBLANK_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); + + REG_SET(VBLANK_PARAMETERS_3, 0, + REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); + + REG_SET(NOM_PARAMETERS_0, 0, + DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l); + + REG_SET(NOM_PARAMETERS_1, 0, + REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l); + + REG_SET(NOM_PARAMETERS_4, 0, + DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l); + + REG_SET(NOM_PARAMETERS_5, 0, + REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); + + REG_SET_2(PER_LINE_DELIVERY_PRE, 0, + REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, + REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); + + REG_SET_2(PER_LINE_DELIVERY, 0, + REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, + REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); + + REG_SET(PREFETCH_SETTINS_C, 0, + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); + + REG_SET(VBLANK_PARAMETERS_2, 0, + REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); + + REG_SET(VBLANK_PARAMETERS_4, 0, + REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); + + REG_SET(NOM_PARAMETERS_2, 0, + DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c); + + REG_SET(NOM_PARAMETERS_3, 0, + REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c); + + REG_SET(NOM_PARAMETERS_6, 0, + DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c); + + REG_SET(NOM_PARAMETERS_7, 0, + REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c); + + /* TTU - per hubp */ + REG_SET_2(DCN_TTU_QOS_WM, 0, + QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, + QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); + + REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, + MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, + QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); + + /* TTU - per luma/chroma */ + /* Assumed surf0 is luma and 1 is chroma */ + + REG_SET_3(DCN_SURF0_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); + + REG_SET(DCN_SURF0_TTU_CNTL1, 0, + REFCYC_PER_REQ_DELIVERY_PRE, + ttu_attr->refcyc_per_req_delivery_pre_l); + + REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, + REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, + QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, + QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); + + REG_SET(DCN_SURF1_TTU_CNTL1, 0, + REFCYC_PER_REQ_DELIVERY_PRE, + ttu_attr->refcyc_per_req_delivery_pre_c); +} + +static void mem_input_setup( + struct mem_input *mem_input, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) +{ + /* otg is locked when this func is called. Register are double buffered. + * disable the requestors is not needed + */ + /* disable_request(mem_input); */ + program_requestor(mem_input, rq_regs); + program_deadline(mem_input, dlg_attr, ttu_attr); + vready_workaround(mem_input, pipe_dest); +} + +static uint32_t convert_and_clamp( + uint32_t wm_ns, + uint32_t refclk_mhz, + uint32_t clamp_value) +{ + uint32_t ret_val = 0; + ret_val = wm_ns * refclk_mhz; + ret_val /= 1000; + + if (ret_val > clamp_value) + ret_val = clamp_value; + + return ret_val; +} + +static void program_watermarks( + struct mem_input *mem_input, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + /* + * Need to clamp to max of the register values (i.e. no wrap) + * for dcn1, all wm registers are 21-bit wide + */ + uint32_t prog_wm_value; + + /* Repeat for water mark set A, B, C and D. */ + /* clock state A */ + prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); + + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); + + + /* clock state B */ + prog_wm_value = convert_and_clamp( + watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state C */ + prog_wm_value = convert_and_clamp( + watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state D */ + prog_wm_value = convert_and_clamp( + watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->d.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); + dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, + DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); + REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, + DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); + +#if 0 + REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); +#endif +} + +static void mem_input_program_display_marks( + struct mem_input *mem_input, + struct bw_watermarks nbp, + struct bw_watermarks stutter, + struct bw_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + /* only for dce + * dcn use only program_watermarks + */ +} + +bool mem_input_is_flip_pending(struct mem_input *mem_input) +{ + uint32_t update_pending = 0; + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + REG_GET(DCSURF_FLIP_CONTROL, + SURFACE_UPDATE_PENDING, &update_pending); + + if (update_pending) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +static void mem_input_update_dchub( + struct mem_input *mem_input, + struct dchub_init_data *dh_data) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, + SDPIF_FB_TOP, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, + SDPIF_FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, 0X03FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + +struct vm_system_aperture_param { + PHYSICAL_ADDRESS_LOC sys_default; + PHYSICAL_ADDRESS_LOC sys_low; + PHYSICAL_ADDRESS_LOC sys_high; +}; + +static void read_vm_system_aperture_settings(struct dcn10_mem_input *mi, + struct vm_system_aperture_param *apt) +{ + PHYSICAL_ADDRESS_LOC physical_page_number; + uint32_t logical_addr_low; + uint32_t logical_addr_high; + + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, + PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, + PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); + + REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + LOGICAL_ADDR, &logical_addr_low); + + REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + LOGICAL_ADDR, &logical_addr_high); + + apt->sys_default.quad_part = physical_page_number.quad_part << 12; + apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; + apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; +} + +static void set_vm_system_aperture_settings(struct dcn10_mem_input *mi, + struct vm_system_aperture_param *apt) +{ + PHYSICAL_ADDRESS_LOC mc_vm_apt_default; + PHYSICAL_ADDRESS_LOC mc_vm_apt_low; + PHYSICAL_ADDRESS_LOC mc_vm_apt_high; + + mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; + mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 12; + mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; + + REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, 1, /* 1 = system physical memory */ + MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); + + REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mc_vm_apt_low.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mc_vm_apt_low.low_part); + + REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, + MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mc_vm_apt_high.high_part); + REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, + MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); +} + +struct vm_context0_param { + PHYSICAL_ADDRESS_LOC pte_base; + PHYSICAL_ADDRESS_LOC pte_start; + PHYSICAL_ADDRESS_LOC pte_end; + PHYSICAL_ADDRESS_LOC fault_default; +}; + +/* Temporary read settings, future will get values from kmd directly */ +static void read_vm_context0_settings(struct dcn10_mem_input *mi, + struct vm_context0_param *vm0) +{ + PHYSICAL_ADDRESS_LOC fb_base; + PHYSICAL_ADDRESS_LOC fb_offset; + uint32_t fb_base_value; + uint32_t fb_offset_value; + + REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); + REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, + PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, + PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); + + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, + PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, + PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); + + /* + * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. + * Therefore we need to do + * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE + */ + fb_base.quad_part = (uint64_t)fb_base_value << 24; + fb_offset.quad_part = (uint64_t)fb_offset_value << 24; + vm0->pte_base.quad_part += fb_base.quad_part; + vm0->pte_base.quad_part -= fb_offset.quad_part; +} + +static void set_vm_context0_settings(struct dcn10_mem_input *mi, + const struct vm_context0_param *vm0) +{ + /* pte base */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, vm0->pte_base.low_part); + + /* pte start */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, vm0->pte_start.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, vm0->pte_start.low_part); + + /* pte end */ + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->pte_end.high_part); + REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, 0, + VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); + + /* fault handling */ + REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, + VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->fault_default.high_part); + /* VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, 0 */ + REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); +} + +void dcn_mem_input_program_pte_vm(struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct vm_system_aperture_param apt = { {{ 0 } } }; + struct vm_context0_param vm0 = { { { 0 } } }; + + + read_vm_system_aperture_settings(mi, &apt); + read_vm_context0_settings(mi, &vm0); + + set_vm_system_aperture_settings(mi, &apt); + set_vm_context0_settings(mi, &vm0); + + /* control: enable VM PTE*/ + REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, + ENABLE_L1_TLB, 1, + SYSTEM_ACCESS_MODE, 3); +} + +static struct mem_input_funcs dcn10_mem_input_funcs = { + .mem_input_program_display_marks = mem_input_program_display_marks, + .allocate_mem_input = NULL, + .free_mem_input = NULL, + .disable_request = disable_request, + .mem_input_program_surface_flip_and_addr = + mem_input_program_surface_flip_and_addr, + .mem_input_program_surface_config = + mem_input_program_surface_config, + .mem_input_is_flip_pending = mem_input_is_flip_pending, + .mem_input_setup = mem_input_setup, + .program_watermarks = program_watermarks, + .mem_input_update_dchub = mem_input_update_dchub, + .mem_input_program_pte_vm = dcn_mem_input_program_pte_vm, +}; + + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dcn10_mem_input_construct( + struct dcn10_mem_input *mi, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_mi_registers *mi_regs, + const struct dcn_mi_shift *mi_shift, + const struct dcn_mi_mask *mi_mask) +{ + mi->base.funcs = &dcn10_mem_input_funcs; + mi->base.ctx = ctx; + mi->mi_regs = mi_regs; + mi->mi_shift = mi_shift; + mi->mi_mask = mi_mask; + mi->base.inst = inst; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h new file mode 100644 index 000000000000..4a5eb6ae3524 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -0,0 +1,553 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MEM_INPUT_DCN10_H__ +#define __DC_MEM_INPUT_DCN10_H__ + +#include "mem_input.h" + +#define TO_DCN10_MEM_INPUT(mi)\ + container_of(mi, struct dcn10_mem_input, base) + + +#define MI_DCN10_REG_LIST(id)\ + SRI(DCHUBP_CNTL, HUBP, id),\ + SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ + SRI(DCSURF_ADDR_CONFIG, HUBP, id),\ + SRI(DCSURF_TILING_CONFIG, HUBP, id),\ + SRI(DCSURF_SURFACE_PITCH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_PITCH_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_CONFIG, HUBP, id),\ + SRI(DCSURF_FLIP_CONTROL, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SECONDARY_META_SURFACE_ADDRESS, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_CONTROL, HUBPREQ, id),\ + SRI(HUBPRET_CONTROL, HUBPRET, id),\ + SRI(DCN_EXPANSION_MODE, HUBPREQ, id),\ + SRI(DCHUBP_REQ_SIZE_CONFIG, HUBP, id),\ + SRI(DCHUBP_REQ_SIZE_CONFIG_C, HUBP, id),\ + SRI(BLANK_OFFSET_0, HUBPREQ, id),\ + SRI(BLANK_OFFSET_1, HUBPREQ, id),\ + SRI(DST_DIMENSIONS, HUBPREQ, id),\ + SRI(DST_AFTER_SCALER, HUBPREQ, id),\ + SRI(PREFETCH_SETTINS, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_0, HUBPREQ, id),\ + SRI(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_1, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_3, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_0, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_1, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_4, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_5, HUBPREQ, id),\ + SRI(PER_LINE_DELIVERY_PRE, HUBPREQ, id),\ + SRI(PER_LINE_DELIVERY, HUBPREQ, id),\ + SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_2, HUBPREQ, id),\ + SRI(VBLANK_PARAMETERS_4, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_2, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_3, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_6, HUBPREQ, id),\ + SRI(NOM_PARAMETERS_7, HUBPREQ, id),\ + SRI(DCN_TTU_QOS_WM, HUBPREQ, id),\ + SRI(DCN_GLOBAL_TTU_CNTL, HUBPREQ, id),\ + SRI(DCN_SURF0_TTU_CNTL0, HUBPREQ, id),\ + SRI(DCN_SURF0_TTU_CNTL1, HUBPREQ, id),\ + SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ + SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ + SR(DCHUBBUB_SDPIF_FB_TOP),\ + SR(DCHUBBUB_SDPIF_FB_BASE),\ + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SR(DCHUBBUB_SDPIF_AGP_BASE),\ + SR(DCHUBBUB_SDPIF_AGP_BOT),\ + SR(DCHUBBUB_SDPIF_AGP_TOP),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ + SR(DCHUBBUB_ARB_SAT_LEVEL),\ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ + /* todo: get these from GVM instead of reading registers ourselves */\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ + GC_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ + GC_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ + GC_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ + GC_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ + GC_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ + GC_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ + GC_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) + +struct dcn_mi_registers { + uint32_t DCHUBP_CNTL; + uint32_t HUBPREQ_DEBUG_DB; + uint32_t DCSURF_ADDR_CONFIG; + uint32_t DCSURF_TILING_CONFIG; + uint32_t DCSURF_SURFACE_PITCH; + uint32_t DCSURF_SURFACE_PITCH_C; + uint32_t DCSURF_SURFACE_CONFIG; + uint32_t DCSURF_FLIP_CONTROL; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS; + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH; + uint32_t DCSURF_SECONDARY_META_SURFACE_ADDRESS; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C; + uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; + uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; + uint32_t DCSURF_SURFACE_CONTROL; + uint32_t HUBPRET_CONTROL; + uint32_t DCN_EXPANSION_MODE; + uint32_t DCHUBP_REQ_SIZE_CONFIG; + uint32_t DCHUBP_REQ_SIZE_CONFIG_C; + uint32_t BLANK_OFFSET_0; + uint32_t BLANK_OFFSET_1; + uint32_t DST_DIMENSIONS; + uint32_t DST_AFTER_SCALER; + uint32_t PREFETCH_SETTINS; + uint32_t VBLANK_PARAMETERS_0; + uint32_t REF_FREQ_TO_PIX_FREQ; + uint32_t VBLANK_PARAMETERS_1; + uint32_t VBLANK_PARAMETERS_3; + uint32_t NOM_PARAMETERS_0; + uint32_t NOM_PARAMETERS_1; + uint32_t NOM_PARAMETERS_4; + uint32_t NOM_PARAMETERS_5; + uint32_t PER_LINE_DELIVERY_PRE; + uint32_t PER_LINE_DELIVERY; + uint32_t PREFETCH_SETTINS_C; + uint32_t VBLANK_PARAMETERS_2; + uint32_t VBLANK_PARAMETERS_4; + uint32_t NOM_PARAMETERS_2; + uint32_t NOM_PARAMETERS_3; + uint32_t NOM_PARAMETERS_6; + uint32_t NOM_PARAMETERS_7; + uint32_t DCN_TTU_QOS_WM; + uint32_t DCN_GLOBAL_TTU_CNTL; + uint32_t DCN_SURF0_TTU_CNTL0; + uint32_t DCN_SURF0_TTU_CNTL1; + uint32_t DCN_SURF1_TTU_CNTL0; + uint32_t DCN_SURF1_TTU_CNTL1; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB; + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB; + uint32_t DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB; + uint32_t DCN_VM_MX_L1_TLB_CNTL; + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; + uint32_t DCHUBBUB_SDPIF_FB_TOP; + uint32_t DCHUBBUB_SDPIF_FB_BASE; + uint32_t DCHUBBUB_SDPIF_FB_OFFSET; + uint32_t DCHUBBUB_SDPIF_AGP_BASE; + uint32_t DCHUBBUB_SDPIF_AGP_BOT; + uint32_t DCHUBBUB_SDPIF_AGP_TOP; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; + uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; + uint32_t DCHUBBUB_ARB_SAT_LEVEL; + uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; + + /* GC registers. read only. temporary hack */ + uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; + uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32; + uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32; + uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32; + uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32; + uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; + uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; + uint32_t MC_VM_SYSTEM_APERTURE_LOW_ADDR; + uint32_t MC_VM_SYSTEM_APERTURE_HIGH_ADDR; +}; + +#define MI_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define MI_DCN10_MASK_SH_LIST(mask_sh)\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_SE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_RB_PER_SE, mask_sh),\ + MI_SF(HUBP0_DCSURF_ADDR_CONFIG, MAX_COMPRESSED_FRAGS, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, SW_MODE, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, META_LINEAR, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, RB_ALIGNED, mask_sh),\ + MI_SF(HUBP0_DCSURF_TILING_CONFIG, PIPE_ALIGNED, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, META_PITCH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, PITCH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, META_PITCH_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, ROTATION_ANGLE, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ + MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_PENDING, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS, SECONDARY_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, PRIMARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS, PRIMARY_META_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, SECONDARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS, SECONDARY_META_SURFACE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ + MI_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, DRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, PRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, MRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_EXPANSION_MODE, CRQ_EXPANSION_MODE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, META_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_META_CHUNK_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, DPTE_GROUP_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MPTE_GROUP_SIZE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, PTE_ROW_HEIGHT_LINEAR, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, META_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_META_CHUNK_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, DPTE_GROUP_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MPTE_GROUP_SIZE_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, SWATH_HEIGHT_C, mask_sh),\ + MI_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, PTE_ROW_HEIGHT_LINEAR_C, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_0, REFCYC_H_BLANK_END, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_0, DLG_V_BLANK_END, mask_sh),\ + MI_SF(HUBPREQ0_BLANK_OFFSET_1, MIN_DST_Y_NEXT_START, mask_sh),\ + MI_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ + MI_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ + MI_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_1, REFCYC_PER_PTE_GROUP_VBLANK_L, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_3, REFCYC_PER_META_CHUNK_VBLANK_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_0, DST_Y_PER_PTE_ROW_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_1, REFCYC_PER_PTE_GROUP_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_4, DST_Y_PER_META_ROW_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_5, REFCYC_PER_META_CHUNK_NOM_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ + MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ + MI_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_2, DST_Y_PER_PTE_ROW_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_3, REFCYC_PER_PTE_GROUP_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_6, DST_Y_PER_META_ROW_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_NOM_PARAMETERS_7, REFCYC_PER_META_CHUNK_NOM_C, mask_sh),\ + MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_LOW_WM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_HIGH_WM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, mask_sh),\ + MI_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, QoS_LEVEL_FLIP, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, REFCYC_PER_REQ_DELIVERY, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_FB_TOP, SDPIF_FB_TOP, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh),\ + MI_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh),\ + MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ + MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh),\ + /* todo: get these from GVM instead of reading registers ourselves */\ + MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, PAGE_DIRECTORY_ENTRY_HI32, mask_sh),\ + MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, PAGE_DIRECTORY_ENTRY_LO32, mask_sh),\ + MI_SF(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, LOGICAL_PAGE_NUMBER_HI4, mask_sh),\ + MI_SF(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, LOGICAL_PAGE_NUMBER_LO32, mask_sh),\ + MI_SF(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, PHYSICAL_PAGE_ADDR_HI4, mask_sh),\ + MI_SF(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ + MI_SF(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ + MI_SF(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ + MI_SF(MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) + +#define DCN_MI_REG_FIELD_LIST(type) \ + type HUBP_BLANK_EN;\ + type HUBP_TTU_DISABLE;\ + type NUM_PIPES;\ + type NUM_BANKS;\ + type PIPE_INTERLEAVE;\ + type NUM_SE;\ + type NUM_RB_PER_SE;\ + type MAX_COMPRESSED_FRAGS;\ + type SW_MODE;\ + type META_LINEAR;\ + type RB_ALIGNED;\ + type PIPE_ALIGNED;\ + type PITCH;\ + type META_PITCH;\ + type PITCH_C;\ + type META_PITCH_C;\ + type ROTATION_ANGLE;\ + type H_MIRROR_EN;\ + type SURFACE_PIXEL_FORMAT;\ + type SURFACE_FLIP_TYPE;\ + type SURFACE_UPDATE_PENDING;\ + type PRIMARY_SURFACE_ADDRESS_HIGH;\ + type PRIMARY_SURFACE_ADDRESS;\ + type SECONDARY_SURFACE_ADDRESS_HIGH;\ + type SECONDARY_SURFACE_ADDRESS;\ + type PRIMARY_META_SURFACE_ADDRESS_HIGH;\ + type PRIMARY_META_SURFACE_ADDRESS;\ + type SECONDARY_META_SURFACE_ADDRESS_HIGH;\ + type SECONDARY_META_SURFACE_ADDRESS;\ + type PRIMARY_SURFACE_ADDRESS_HIGH_C;\ + type PRIMARY_SURFACE_ADDRESS_C;\ + type PRIMARY_META_SURFACE_ADDRESS_HIGH_C;\ + type PRIMARY_META_SURFACE_ADDRESS_C;\ + type PRIMARY_SURFACE_DCC_EN;\ + type PRIMARY_SURFACE_DCC_IND_64B_BLK;\ + type DET_BUF_PLANE1_BASE_ADDRESS;\ + type CROSSBAR_SRC_CB_B;\ + type CROSSBAR_SRC_CR_R;\ + type DRQ_EXPANSION_MODE;\ + type PRQ_EXPANSION_MODE;\ + type MRQ_EXPANSION_MODE;\ + type CRQ_EXPANSION_MODE;\ + type CHUNK_SIZE;\ + type MIN_CHUNK_SIZE;\ + type META_CHUNK_SIZE;\ + type MIN_META_CHUNK_SIZE;\ + type DPTE_GROUP_SIZE;\ + type MPTE_GROUP_SIZE;\ + type SWATH_HEIGHT;\ + type PTE_ROW_HEIGHT_LINEAR;\ + type CHUNK_SIZE_C;\ + type MIN_CHUNK_SIZE_C;\ + type META_CHUNK_SIZE_C;\ + type MIN_META_CHUNK_SIZE_C;\ + type DPTE_GROUP_SIZE_C;\ + type MPTE_GROUP_SIZE_C;\ + type SWATH_HEIGHT_C;\ + type PTE_ROW_HEIGHT_LINEAR_C;\ + type REFCYC_H_BLANK_END;\ + type DLG_V_BLANK_END;\ + type MIN_DST_Y_NEXT_START;\ + type REFCYC_PER_HTOTAL;\ + type REFCYC_X_AFTER_SCALER;\ + type DST_Y_AFTER_SCALER;\ + type DST_Y_PREFETCH;\ + type VRATIO_PREFETCH;\ + type DST_Y_PER_VM_VBLANK;\ + type DST_Y_PER_ROW_VBLANK;\ + type REF_FREQ_TO_PIX_FREQ;\ + type REFCYC_PER_PTE_GROUP_VBLANK_L;\ + type REFCYC_PER_META_CHUNK_VBLANK_L;\ + type DST_Y_PER_PTE_ROW_NOM_L;\ + type REFCYC_PER_PTE_GROUP_NOM_L;\ + type DST_Y_PER_META_ROW_NOM_L;\ + type REFCYC_PER_META_CHUNK_NOM_L;\ + type REFCYC_PER_LINE_DELIVERY_PRE_L;\ + type REFCYC_PER_LINE_DELIVERY_PRE_C;\ + type REFCYC_PER_LINE_DELIVERY_L;\ + type REFCYC_PER_LINE_DELIVERY_C;\ + type VRATIO_PREFETCH_C;\ + type REFCYC_PER_PTE_GROUP_VBLANK_C;\ + type REFCYC_PER_META_CHUNK_VBLANK_C;\ + type DST_Y_PER_PTE_ROW_NOM_C;\ + type REFCYC_PER_PTE_GROUP_NOM_C;\ + type DST_Y_PER_META_ROW_NOM_C;\ + type REFCYC_PER_META_CHUNK_NOM_C;\ + type QoS_LEVEL_LOW_WM;\ + type QoS_LEVEL_HIGH_WM;\ + type MIN_TTU_VBLANK;\ + type QoS_LEVEL_FLIP;\ + type REFCYC_PER_REQ_DELIVERY;\ + type QoS_LEVEL_FIXED;\ + type QoS_RAMP_DISABLE;\ + type REFCYC_PER_REQ_DELIVERY_PRE;\ + type VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB;\ + type VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB;\ + type VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB;\ + type VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\ + type ENABLE_L1_TLB;\ + type SYSTEM_ACCESS_MODE;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB;\ + type SDPIF_FB_TOP;\ + type SDPIF_FB_BASE;\ + type SDPIF_FB_OFFSET;\ + type SDPIF_AGP_BASE;\ + type SDPIF_AGP_BOT;\ + type SDPIF_AGP_TOP;\ + type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ + type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ + type DCHUBBUB_ARB_SAT_LEVEL;\ + type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ + /* todo: get these from GVM instead of reading registers ourselves */\ + type PAGE_DIRECTORY_ENTRY_HI32;\ + type PAGE_DIRECTORY_ENTRY_LO32;\ + type LOGICAL_PAGE_NUMBER_HI4;\ + type LOGICAL_PAGE_NUMBER_LO32;\ + type PHYSICAL_PAGE_ADDR_HI4;\ + type PHYSICAL_PAGE_ADDR_LO32;\ + type PHYSICAL_PAGE_NUMBER_MSB;\ + type PHYSICAL_PAGE_NUMBER_LSB;\ + type LOGICAL_ADDR + +struct dcn_mi_shift { + DCN_MI_REG_FIELD_LIST(uint8_t); +}; + +struct dcn_mi_mask { + DCN_MI_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_mem_input { + struct mem_input base; + const struct dcn_mi_registers *mi_regs; + const struct dcn_mi_shift *mi_shift; + const struct dcn_mi_mask *mi_mask; +}; + +bool dcn10_mem_input_construct( + struct dcn10_mem_input *mi, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_mi_registers *mi_regs, + const struct dcn_mi_shift *mi_shift, + const struct dcn_mi_mask *mi_mask); + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c new file mode 100644 index 000000000000..cb22cd130e1a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -0,0 +1,376 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dcn10_mpc.h" + +#define REG(reg)\ + mpc->mpc_regs->reg + +#define CTX \ + mpc->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + mpc->mpc_shift->field_name, mpc->mpc_mask->field_name + +/* Internal function to set mpc output mux */ +static void set_output_mux(struct dcn10_mpc *mpc, + uint8_t opp_id, + uint8_t mpcc_id) +{ + if (mpcc_id != 0xf) + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + OPP_PIPE_CLOCK_EN, 1); + + REG_SET(MUX[opp_id], 0, + MPC_OUT_MUX, mpcc_id); + +/* TODO: Move to post when ready. + if (mpcc_id == 0xf) { + MPCC_REG_UPDATE(OPP_PIPE0_OPP_PIPE_CONTROL, + OPP_PIPE_CLOCK_EN, 0); + } +*/ +} + +static void set_blend_mode(struct dcn10_mpc *mpc, + enum blend_mode mode, + uint8_t mpcc_id) +{ + /* Enable per-pixel alpha on this pipe */ + if (mode == TOP_BLND) + REG_UPDATE_3(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, 0, + MPCC_ALPHA_MULTIPLIED_MODE, 0, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, 0); + else + REG_UPDATE_3(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, 0, + MPCC_ALPHA_MULTIPLIED_MODE, 1, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, 1); +} + +void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, + unsigned int mpcc_inst, + struct tg_color *bg_color) +{ + /* mpc color is 12 bit. tg_color is 10 bit */ + /* todo: might want to use 16 bit to represent color and have each + * hw block translate to correct color depth. + */ + uint32_t bg_r_cr = bg_color->color_r_cr << 2; + uint32_t bg_g_y = bg_color->color_g_y << 2; + uint32_t bg_b_cb = bg_color->color_b_cb << 2; + + REG_SET(MPCC_BG_R_CR[mpcc_inst], 0, + MPCC_BG_R_CR, bg_r_cr); + REG_SET(MPCC_BG_G_Y[mpcc_inst], 0, + MPCC_BG_G_Y, bg_g_y); + REG_SET(MPCC_BG_B_CB[mpcc_inst], 0, + MPCC_BG_B_CB, bg_b_cb); +} + +/* This function programs MPC tree configuration + * Assume it is the initial time to setup MPC tree_configure, means + * the instance of dpp/mpcc/opp specified in structure tree_cfg are + * in idle status. + * Before invoke this function, ensure that master lock of OPTC specified + * by opp_id is set. + * + * tree_cfg[in] - new MPC_TREE_CFG + */ + +void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg) +{ + int i; + + for (i = 0; i < tree_cfg->num_pipes; i++) { + uint8_t mpcc_inst = tree_cfg->mpcc[i]; + + REG_SET(MPCC_OPP_ID[mpcc_inst], 0, + MPCC_OPP_ID, tree_cfg->opp_id); + + REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, + MPCC_TOP_SEL, tree_cfg->dpp[i]); + + if (i == tree_cfg->num_pipes-1) { + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xF); + + /* MPCC_CONTROL->MPCC_MODE */ + REG_UPDATE(MPCC_CONTROL[mpcc_inst], + MPCC_MODE, tree_cfg->mode); + } else { + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, tree_cfg->dpp[i+1]); + + /* MPCC_CONTROL->MPCC_MODE */ + REG_UPDATE(MPCC_CONTROL[mpcc_inst], + MPCC_MODE, 3); + } + + if (i == 0) + set_output_mux( + mpc, tree_cfg->opp_id, mpcc_inst); + + set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); + } +} + +void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, + uint8_t dpp_idx, + uint8_t mpcc_idx, + uint8_t opp_idx) +{ + struct mpc_tree_cfg tree_cfg = { 0 }; + + tree_cfg.num_pipes = 1; + tree_cfg.opp_id = opp_idx; + tree_cfg.mode = TOP_PASSTHRU; + /* TODO: FPGA bring up one MPC has only 1 DPP and 1 MPCC + * For blend case, need fill mode DPP and cascade MPCC + */ + tree_cfg.dpp[0] = dpp_idx; + tree_cfg.mpcc[0] = mpcc_idx; + dcn10_set_mpc_tree(mpc, &tree_cfg); +} + +/* + * This is the function to remove current MPC tree specified by tree_cfg + * Before invoke this function, ensure that master lock of OPTC specified + * by opp_id is set. + * + *tree_cfg[in/out] - current MPC_TREE_CFG + */ +void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg) +{ + int i; + + for (i = 0; i < tree_cfg->num_pipes; i++) { + uint8_t mpcc_inst = tree_cfg->mpcc[i]; + + REG_SET(MPCC_OPP_ID[mpcc_inst], 0, + MPCC_OPP_ID, 0xf); + + REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, + MPCC_TOP_SEL, 0xf); + + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xF); + + /* add remove dpp/mpcc pair into pending list + * TODO FPGA AddToPendingList if empty from pseudo code + */ + tree_cfg->dpp[i] = 0xf; + tree_cfg->mpcc[i] = 0xf; + } + set_output_mux(mpc, tree_cfg->opp_id, 0xf); + tree_cfg->opp_id = 0xf; + tree_cfg->num_pipes = 0; +} + +/* TODO FPGA: how to handle DPP? + * Function to remove one of pipe from MPC configure tree by dpp idx + * Before invoke this function, ensure that master lock of OPTC specified + * by opp_id is set + * This function can be invoke multiple times to remove more than 1 dpps. + * + * tree_cfg[in/out] - current MPC_TREE_CFG + * idx[in] - index of dpp from tree_cfg to be removed. + */ +bool dcn10_remove_dpp(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + uint8_t idx) +{ + int i; + bool found = false; + + /* find dpp_idx from dpp array of tree_cfg */ + for (i = 0; i < tree_cfg->num_pipes; i++) { + if (tree_cfg->dpp[i] == idx) { + found = true; + break; + } + } + + if (found) { + /* add remove dpp/mpcc pair into pending list */ + + /* TODO FPGA AddToPendingList if empty from pseudo code + * AddToPendingList(tree_cfg->dpp[i],tree_cfg->mpcc[i]); + */ + uint8_t mpcc_inst = tree_cfg->mpcc[i]; + + REG_SET(MPCC_OPP_ID[mpcc_inst], 0, + MPCC_OPP_ID, 0xf); + + REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, + MPCC_TOP_SEL, 0xf); + + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xF); + + if (i == 0) { + if (tree_cfg->num_pipes > 1) + set_output_mux(mpc, + tree_cfg->opp_id, tree_cfg->mpcc[i+1]); + else + set_output_mux(mpc, tree_cfg->opp_id, 0xf); + } else if (i == tree_cfg->num_pipes-1) { + mpcc_inst = tree_cfg->mpcc[i - 1]; + + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xF); + + REG_UPDATE(MPCC_CONTROL[mpcc_inst], + MPCC_MODE, tree_cfg->mode); + } else { + mpcc_inst = tree_cfg->mpcc[i - 1]; + + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); + } + set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); + + /* update tree_cfg structure */ + while (i < tree_cfg->num_pipes - 1) { + tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; + tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; + i++; + } + tree_cfg->num_pipes--; + } + return found; +} + +/* TODO FPGA: how to handle DPP? + * Function to add DPP/MPCC pair into MPC configure tree by position. + * Before invoke this function, ensure that master lock of OPTC specified + * by opp_id is set + * This function can be invoke multiple times to add more than 1 pipes. + * + * tree_cfg[in/out] - current MPC_TREE_CFG + * dpp_idx[in] - index of an idle dpp insatnce to be added. + * mpcc_idx[in] - index of an idle mpcc instance to be added. + * poistion[in] - position of dpp/mpcc pair to be added into current tree_cfg + * 0 means insert to the most top layer of MPC tree + */ +void dcn10_add_dpp(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + uint8_t dpp_idx, + uint8_t mpcc_idx, + uint8_t position) +{ + uint8_t temp; + uint8_t temp1; + + REG_SET(MPCC_OPP_ID[mpcc_idx], 0, + MPCC_OPP_ID, tree_cfg->opp_id); + + REG_SET(MPCC_TOP_SEL[mpcc_idx], 0, + MPCC_TOP_SEL, dpp_idx); + + if (position == 0) { + /* idle dpp/mpcc is added to the top layer of tree */ + REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, + MPCC_BOT_SEL, tree_cfg->mpcc[0]); + REG_UPDATE(MPCC_CONTROL[mpcc_idx], + MPCC_MODE, 3); + + /* opp will get new output. from new added mpcc */ + set_output_mux(mpc, tree_cfg->opp_id, mpcc_idx); + + set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); + + } else if (position == tree_cfg->num_pipes) { + /* idle dpp/mpcc is added to the bottom layer of tree */ + + /* get instance of previous bottom mpcc, set to middle layer */ + temp = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; + + REG_SET(MPCC_BOT_SEL[temp], 0, + MPCC_BOT_SEL, mpcc_idx); + + REG_UPDATE(MPCC_CONTROL[temp], + MPCC_MODE, 3); + + /* mpcc_idx become new bottom mpcc*/ + REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, + MPCC_BOT_SEL, 0xf); + + REG_UPDATE(MPCC_CONTROL[mpcc_idx], + MPCC_MODE, tree_cfg->mode); + + set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); + } else { + /* idle dpp/mpcc is added to middle of tree */ + temp = tree_cfg->mpcc[position - 1]; + temp1 = tree_cfg->mpcc[position]; + + /* new mpcc instance temp1 is added right after temp*/ + REG_SET(MPCC_BOT_SEL[temp], 0, + MPCC_BOT_SEL, mpcc_idx); + + /* mpcc_idx connect previous temp+1 to new mpcc */ + REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, + MPCC_BOT_SEL, temp1); + + /* temp TODO: may not need*/ + REG_UPDATE(MPCC_CONTROL[temp], + MPCC_MODE, 3); + + set_blend_mode(mpc, tree_cfg->mode, temp); + } + + /* update tree_cfg structure */ + temp = tree_cfg->num_pipes - 1; + + /* + * iterating from the last mpc/dpp pair to the one being added, shift + * them down one position + */ + while (temp > position) { + tree_cfg->dpp[temp + 1] = tree_cfg->dpp[temp]; + tree_cfg->mpcc[temp + 1] = tree_cfg->mpcc[temp]; + temp--; + } + + /* insert the new mpc/dpp pair into the tree_cfg*/ + tree_cfg->dpp[position] = dpp_idx; + tree_cfg->mpcc[position] = mpcc_idx; + tree_cfg->num_pipes++; +} + +void wait_mpcc_idle(struct dcn10_mpc *mpc, + uint8_t mpcc_id) +{ + REG_WAIT(MPCC_STATUS[mpcc_id], + MPCC_IDLE, 1, + 1000, 1000); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h new file mode 100644 index 000000000000..6550b93c9254 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -0,0 +1,135 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MPC_DCN10_H__ +#define __DC_MPC_DCN10_H__ + +#include "mpc.h" + +#define TO_DCN10_MPC(mpc_base)\ + container_of(mpc_base, struct dcn10_mpc, base) + +#define MAX_MPCC 4 +#define MAX_MPC_OUT 4 +#define MAX_OPP 4 + +#define MPC_COMMON_REG_LIST_DCN1_0(inst) \ + SRII(MPCC_TOP_SEL, MPCC, inst),\ + SRII(MPCC_BOT_SEL, MPCC, inst),\ + SRII(MPCC_CONTROL, MPCC, inst),\ + SRII(MPCC_STATUS, MPCC, inst),\ + SRII(MPCC_OPP_ID, MPCC, inst),\ + SRII(MPCC_BG_G_Y, MPCC, inst),\ + SRII(MPCC_BG_R_CR, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst),\ + SRII(MUX, MPC_OUT, inst),\ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, inst) + +struct dcn_mpc_registers { + uint32_t MPCC_TOP_SEL[MAX_MPCC]; + uint32_t MPCC_BOT_SEL[MAX_MPCC]; + uint32_t MPCC_CONTROL[MAX_MPCC]; + uint32_t MPCC_STATUS[MAX_MPCC]; + uint32_t MPCC_OPP_ID[MAX_MPCC]; + uint32_t MPCC_BG_G_Y[MAX_MPCC]; + uint32_t MPCC_BG_R_CR[MAX_MPCC]; + uint32_t MPCC_BG_B_CB[MAX_MPCC]; + uint32_t MUX[MAX_MPC_OUT]; + uint32_t OPP_PIPE_CONTROL[MAX_OPP]; +}; + +#define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ + SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_BLND_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\ + SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\ + SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ + SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ + SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\ + SF(OPP_PIPE0_OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh) + +#define MPC_REG_FIELD_LIST(type) \ + type MPCC_TOP_SEL;\ + type MPCC_BOT_SEL;\ + type MPCC_MODE;\ + type MPCC_ALPHA_BLND_MODE;\ + type MPCC_ALPHA_MULTIPLIED_MODE;\ + type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\ + type MPCC_IDLE;\ + type MPCC_OPP_ID;\ + type MPCC_BG_G_Y;\ + type MPCC_BG_R_CR;\ + type MPCC_BG_B_CB;\ + type MPC_OUT_MUX;\ + type OPP_PIPE_CLOCK_EN;\ + +struct dcn_mpc_shift { + MPC_REG_FIELD_LIST(uint8_t) +}; + +struct dcn_mpc_mask { + MPC_REG_FIELD_LIST(uint32_t) +}; + +struct dcn10_mpc { + struct mpc base; + const struct dcn_mpc_registers *mpc_regs; + const struct dcn_mpc_shift *mpc_shift; + const struct dcn_mpc_mask *mpc_mask; +}; + +void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, + uint8_t dpp_idx, + uint8_t mpcc_idx, + uint8_t opp_idx); + +void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg); + +bool dcn10_remove_dpp(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + uint8_t idx); + +void dcn10_add_dpp(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + uint8_t dpp_idx, + uint8_t mpcc_idx, + uint8_t position); + +void wait_mpcc_idle(struct dcn10_mpc *mpc, + uint8_t mpcc_id); + +void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, + struct mpc_tree_cfg *tree_cfg); + +void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, + unsigned int mpcc_inst, + struct tg_color *bg_color); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c new file mode 100644 index 000000000000..fce08e5235e6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -0,0 +1,801 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dcn10_opp.h" +#include "reg_helper.h" + +#define REG(reg) \ + (oppn10->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + oppn10->opp_shift->field_name, oppn10->opp_mask->field_name + +#define CTX \ + oppn10->base.ctx + +static void opp_set_regamma_mode( + struct output_pixel_processor *opp, + enum opp_regamma mode) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + uint32_t re_mode = 0; + uint32_t obuf_bypass = 0; /* need for pipe split */ + uint32_t obuf_hupscale = 0; + + switch (mode) { + case OPP_REGAMMA_BYPASS: + re_mode = 0; + break; + case OPP_REGAMMA_SRGB: + re_mode = 1; + break; + case OPP_REGAMMA_3_6: + re_mode = 2; + break; + case OPP_REGAMMA_USER: + re_mode = oppn10->is_write_to_ram_a_safe ? 3 : 4; + oppn10->is_write_to_ram_a_safe = !oppn10->is_write_to_ram_a_safe; + break; + default: + break; + } + + REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode); + REG_UPDATE_2(OBUF_CONTROL, + OBUF_BYPASS, obuf_bypass, + OBUF_H_2X_UPSCALE_EN, obuf_hupscale); +} + +/************* FORMATTER ************/ + +/** + * set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE11 power saving reason. + */ +static void set_truncation( + struct dcn10_opp *oppn10, + const struct bit_depth_reduction_params *params) +{ + REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, params->flags.TRUNCATE_ENABLED, + FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_DEPTH, + FMT_TRUNCATE_MODE, params->flags.TRUNCATE_MODE); +} + +static void set_spatial_dither( + struct dcn10_opp *oppn10, + const struct bit_depth_reduction_params *params) +{ + /*Disable spatial (random) dithering*/ + REG_UPDATE_7(FMT_BIT_DEPTH_CONTROL, + FMT_SPATIAL_DITHER_EN, 0, + FMT_SPATIAL_DITHER_MODE, 0, + FMT_SPATIAL_DITHER_DEPTH, 0, + FMT_TEMPORAL_DITHER_EN, 0, + FMT_HIGHPASS_RANDOM_ENABLE, 0, + FMT_FRAME_RANDOM_ENABLE, 0, + FMT_RGB_RANDOM_ENABLE, 0); + + + /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ + if (params->flags.FRAME_RANDOM == 1) { + if (params->flags.SPATIAL_DITHER_DEPTH == 0 || params->flags.SPATIAL_DITHER_DEPTH == 1) { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2); + } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1); + } else { + return; + } + } else { + REG_UPDATE_2(FMT_CONTROL, + FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0, + FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0); + } + + /*Set seed for random values for + * spatial dithering for R,G,B channels*/ + + REG_SET(FMT_DITHER_RAND_R_SEED, 0, + FMT_RAND_R_SEED, params->r_seed_value); + + REG_SET(FMT_DITHER_RAND_G_SEED, 0, + FMT_RAND_G_SEED, params->g_seed_value); + + REG_SET(FMT_DITHER_RAND_B_SEED, 0, + FMT_RAND_B_SEED, params->b_seed_value); + + /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero + * offset for the R/Cr channel, lower 4LSB + * is forced to zeros. Typically set to 0 + * RGB and 0x80000 YCbCr. + */ + /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero + * offset for the G/Y channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB + * and 0x80000 YCbCr. + */ + /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero + * offset for the B/Cb channel, lower 4LSB is + * forced to zeros. Typically set to 0 RGB and + * 0x80000 YCbCr. + */ + + REG_UPDATE_6(FMT_BIT_DEPTH_CONTROL, + /*Enable spatial dithering*/ + FMT_SPATIAL_DITHER_EN, params->flags.SPATIAL_DITHER_ENABLED, + /* Set spatial dithering mode + * (default is Seed patterrn AAAA...) + */ + FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE, + /*Set spatial dithering bit depth*/ + FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH, + /*Disable High pass filter*/ + FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM, + /*Reset only at startup*/ + FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM, + /*Set RGB data dithered with x^28+x^3+1*/ + FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); +} + +static void opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + set_truncation(oppn10, params); + set_spatial_dither(oppn10, params); + /* TODO + * set_temporal_dither(oppn10, params); + */ +} + +/** + * set_pixel_encoding + * + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void set_pixel_encoding( + struct dcn10_opp *oppn10, + const struct clamping_and_pixel_encoding_params *params) +{ + switch (params->pixel_encoding) { + + case PIXEL_ENCODING_RGB: + case PIXEL_ENCODING_YCBCR444: + REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 0); + break; + case PIXEL_ENCODING_YCBCR422: + REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 1); + break; + case PIXEL_ENCODING_YCBCR420: + REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 2); + break; + default: + break; + } +} + +/** + * Set Clamping + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +static void opp_set_clamping( + struct dcn10_opp *oppn10, + const struct clamping_and_pixel_encoding_params *params) +{ + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 0, + FMT_CLAMP_COLOR_FORMAT, 0); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 0); + break; + case CLAMPING_LIMITED_RANGE_8BPC: + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 1); + break; + case CLAMPING_LIMITED_RANGE_10BPC: + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 2); + + break; + case CLAMPING_LIMITED_RANGE_12BPC: + REG_UPDATE_2(FMT_CLAMP_CNTL, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 3); + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + /* TODO */ + default: + break; + } + +} + +static void opp_set_dyn_expansion( + struct output_pixel_processor *opp, + enum dc_color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 0, + FMT_DYNAMIC_EXP_MODE, 0); + + /*00 - 10-bit -> 12-bit dynamic expansion*/ + /*01 - 8-bit -> 12-bit dynamic expansion*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A || + signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + switch (color_dpth) { + case COLOR_DEPTH_888: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 1, + FMT_DYNAMIC_EXP_MODE, 1); + break; + case COLOR_DEPTH_101010: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 1, + FMT_DYNAMIC_EXP_MODE, 0); + break; + case COLOR_DEPTH_121212: + REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, + FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/ + FMT_DYNAMIC_EXP_MODE, 0); + break; + default: + break; + } + } +} + +static void opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + opp_set_clamping(oppn10, params); + set_pixel_encoding(oppn10, params); +} + +static void opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + REG_UPDATE(FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, 0); + + /* dithering is affected by , hence should be + * programmed afterwards */ + opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + return; +} + +static void opp_set_output_csc_default( + struct output_pixel_processor *opp, + const struct default_adjustment *default_adjust) +{ + + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + uint32_t ocsc_mode = 0; + + if (default_adjust != NULL) { + switch (default_adjust->out_color_space) { + case COLOR_SPACE_SRGB: + ocsc_mode = 0; + break; + case COLOR_SPACE_SRGB_LIMITED: + ocsc_mode = 1; + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + ocsc_mode = 2; + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + ocsc_mode = 3; + break; + case COLOR_SPACE_UNKNOWN: + default: + break; + } + } + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + +} +/*program re gamma RAM B*/ +static void opp_program_regamma_lutb_settings( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, + CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, + CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, + CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, + CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, + CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, + CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, + CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, + CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, + CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, + CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, + CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, + CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, + CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, + CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, + CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, + CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, + CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + +} + +/*program re gamma RAM A*/ +static void opp_program_regamma_luta_settings( + struct output_pixel_processor *opp, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, + CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, + CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, + CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, + CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, + CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, + CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, + CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, + CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, + CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, + CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, + CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, + CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, + CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, + CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, + CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, + CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, + CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} + +static void opp_configure_regamma_lut( + struct output_pixel_processor *opp, + bool is_ram_a) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); +} + +static void opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + REG_SET(CM_MEM_PWR_CTRL, 0, + RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); + +} + +static void opp_program_regamma_lut( + struct output_pixel_processor *opp, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + for (i = 0 ; i < num; i++) { + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); + + } + +} + +static bool opp_set_regamma_pwl( + struct output_pixel_processor *opp, const struct pwl_params *params) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + opp_power_on_regamma_lut(opp, true); + opp_configure_regamma_lut(opp, oppn10->is_write_to_ram_a_safe); + + if (oppn10->is_write_to_ram_a_safe) + opp_program_regamma_luta_settings(opp, params); + else + opp_program_regamma_lutb_settings(opp, params); + + opp_program_regamma_lut( + opp, params->rgb_resulted, params->hw_points_num); + + return true; +} + +static void opp_set_stereo_polarity( + struct output_pixel_processor *opp, + bool enable, bool rightEyePolarity) +{ + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + + REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, enable); +} + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +static void dcn10_opp_destroy(struct output_pixel_processor **opp) +{ + dm_free(TO_DCN10_OPP(*opp)); + *opp = NULL; +} + +static struct opp_funcs dcn10_opp_funcs = { + .opp_power_on_regamma_lut = opp_power_on_regamma_lut, + .opp_set_csc_adjustment = NULL, + .opp_set_csc_default = opp_set_output_csc_default, + .opp_set_dyn_expansion = opp_set_dyn_expansion, + .opp_program_regamma_pwl = opp_set_regamma_pwl, + .opp_set_regamma_mode = opp_set_regamma_mode, + .opp_program_fmt = opp_program_fmt, + .opp_program_bit_depth_reduction = opp_program_bit_depth_reduction, + .opp_set_stereo_polarity = opp_set_stereo_polarity, + .opp_destroy = dcn10_opp_destroy +}; + +void dcn10_opp_construct(struct dcn10_opp *oppn10, + struct dc_context *ctx, + uint32_t inst, + const struct dcn10_opp_registers *regs, + const struct dcn10_opp_shift *opp_shift, + const struct dcn10_opp_mask *opp_mask) +{ + oppn10->base.ctx = ctx; + oppn10->base.inst = inst; + oppn10->base.funcs = &dcn10_opp_funcs; + + oppn10->regs = regs; + oppn10->opp_shift = opp_shift; + oppn10->opp_mask = opp_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h new file mode 100644 index 000000000000..113e0bc349c3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -0,0 +1,622 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_OPP_DCN10_H__ +#define __DC_OPP_DCN10_H__ + +#include "opp.h" + +#define TO_DCN10_OPP(opp)\ + container_of(opp, struct dcn10_opp, base) + +#define OPP_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define OPP_DCN10_REG_LIST(id) \ + SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ + SRI(CM_RGAM_CONTROL, CM, id), \ + SRI(OBUF_CONTROL, DSCL, id), \ + SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ + SRI(FMT_CONTROL, FMT, id), \ + SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI(FMT_CLAMP_CNTL, FMT, id), \ + SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ + SRI(CM_OCSC_CONTROL, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_B, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_B, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_G, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_G, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_R, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_R, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_0_1, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_2_3, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_4_5, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_6_7, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_8_9, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_10_11, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_12_13, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_14_15, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_16_17, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_18_19, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_20_21, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_22_23, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_24_25, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_26_27, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_28_29, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_30_31, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_32_33, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_B, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_B, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_G, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_G, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_R, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_R, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_0_1, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_2_3, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_4_5, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_6_7, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_8_9, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_10_11, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_12_13, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_14_15, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_16_17, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_18_19, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_20_21, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_22_23, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_24_25, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_26_27, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ + SRI(CM_RGAM_LUT_INDEX, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_RGAM_LUT_DATA, CM, id) + +#define OPP_DCN10_MASK_SH_LIST(mask_sh) \ + OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ + OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ + OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh), \ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh), \ + OPP_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_B, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_G, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_R, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_B, CM_RGAM_RAMB_EXP_REGION_END_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_G, CM_RGAM_RAMB_EXP_REGION_END_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_R, CM_RGAM_RAMB_EXP_REGION_END_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_B, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_G, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_R, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_B, CM_RGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_G, CM_RGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_R, CM_RGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ + OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ + OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, mask_sh), \ + OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_SEL, mask_sh), \ + OPP_SF(CM0_CM_RGAM_LUT_INDEX, CM_RGAM_LUT_INDEX, mask_sh), \ + OPP_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ + OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) + +#define OPP_DCN10_REG_FIELD_LIST(type) \ + type CM_RGAM_LUT_MODE; \ + type OBUF_BYPASS; \ + type OBUF_H_2X_UPSCALE_EN; \ + type FMT_TRUNCATE_EN; \ + type FMT_TRUNCATE_DEPTH; \ + type FMT_TRUNCATE_MODE; \ + type FMT_SPATIAL_DITHER_EN; \ + type FMT_SPATIAL_DITHER_MODE; \ + type FMT_SPATIAL_DITHER_DEPTH; \ + type FMT_TEMPORAL_DITHER_EN; \ + type FMT_HIGHPASS_RANDOM_ENABLE; \ + type FMT_FRAME_RANDOM_ENABLE; \ + type FMT_RGB_RANDOM_ENABLE; \ + type FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX; \ + type FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP; \ + type FMT_RAND_R_SEED; \ + type FMT_RAND_G_SEED; \ + type FMT_RAND_B_SEED; \ + type FMT_PIXEL_ENCODING; \ + type FMT_CLAMP_DATA_EN; \ + type FMT_CLAMP_COLOR_FORMAT; \ + type FMT_DYNAMIC_EXP_EN; \ + type FMT_DYNAMIC_EXP_MODE; \ + type FMT_MAP420MEM_PWR_FORCE; \ + type CM_OCSC_MODE; \ + type CM_RGAM_RAMB_EXP_REGION_START_B; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_RGAM_RAMB_EXP_REGION_START_G; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_RGAM_RAMB_EXP_REGION_START_R; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION_START_B; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_RGAM_RAMA_EXP_REGION_START_G; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_RGAM_RAMA_EXP_REGION_START_R; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ + type CM_RGAM_LUT_WRITE_EN_MASK; \ + type CM_RGAM_LUT_WRITE_SEL; \ + type CM_RGAM_LUT_INDEX; \ + type RGAM_MEM_PWR_FORCE; \ + type CM_RGAM_LUT_DATA; \ + type FMT_STEREOSYNC_OVERRIDE + +struct dcn10_opp_shift { + OPP_DCN10_REG_FIELD_LIST(uint8_t); +}; + +struct dcn10_opp_mask { + OPP_DCN10_REG_FIELD_LIST(uint32_t); +}; + +struct dcn10_opp_registers { + uint32_t CM_RGAM_LUT_WRITE_EN_MASK; + uint32_t CM_RGAM_CONTROL; + uint32_t OBUF_CONTROL; + uint32_t FMT_BIT_DEPTH_CONTROL; + uint32_t FMT_CONTROL; + uint32_t FMT_DITHER_RAND_R_SEED; + uint32_t FMT_DITHER_RAND_G_SEED; + uint32_t FMT_DITHER_RAND_B_SEED; + uint32_t FMT_CLAMP_CNTL; + uint32_t FMT_DYNAMIC_EXP_CNTL; + uint32_t FMT_MAP420_MEMORY_CONTROL; + uint32_t CM_OCSC_CONTROL; + uint32_t CM_RGAM_RAMB_START_CNTL_B; + uint32_t CM_RGAM_RAMB_START_CNTL_G; + uint32_t CM_RGAM_RAMB_START_CNTL_R; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_RGAM_RAMB_END_CNTL1_B; + uint32_t CM_RGAM_RAMB_END_CNTL2_B; + uint32_t CM_RGAM_RAMB_END_CNTL1_G; + uint32_t CM_RGAM_RAMB_END_CNTL2_G; + uint32_t CM_RGAM_RAMB_END_CNTL1_R; + uint32_t CM_RGAM_RAMB_END_CNTL2_R; + uint32_t CM_RGAM_RAMB_REGION_0_1; + uint32_t CM_RGAM_RAMB_REGION_2_3; + uint32_t CM_RGAM_RAMB_REGION_4_5; + uint32_t CM_RGAM_RAMB_REGION_6_7; + uint32_t CM_RGAM_RAMB_REGION_8_9; + uint32_t CM_RGAM_RAMB_REGION_10_11; + uint32_t CM_RGAM_RAMB_REGION_12_13; + uint32_t CM_RGAM_RAMB_REGION_14_15; + uint32_t CM_RGAM_RAMB_REGION_16_17; + uint32_t CM_RGAM_RAMB_REGION_18_19; + uint32_t CM_RGAM_RAMB_REGION_20_21; + uint32_t CM_RGAM_RAMB_REGION_22_23; + uint32_t CM_RGAM_RAMB_REGION_24_25; + uint32_t CM_RGAM_RAMB_REGION_26_27; + uint32_t CM_RGAM_RAMB_REGION_28_29; + uint32_t CM_RGAM_RAMB_REGION_30_31; + uint32_t CM_RGAM_RAMB_REGION_32_33; + uint32_t CM_RGAM_RAMA_START_CNTL_B; + uint32_t CM_RGAM_RAMA_START_CNTL_G; + uint32_t CM_RGAM_RAMA_START_CNTL_R; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_RGAM_RAMA_END_CNTL1_B; + uint32_t CM_RGAM_RAMA_END_CNTL2_B; + uint32_t CM_RGAM_RAMA_END_CNTL1_G; + uint32_t CM_RGAM_RAMA_END_CNTL2_G; + uint32_t CM_RGAM_RAMA_END_CNTL1_R; + uint32_t CM_RGAM_RAMA_END_CNTL2_R; + uint32_t CM_RGAM_RAMA_REGION_0_1; + uint32_t CM_RGAM_RAMA_REGION_2_3; + uint32_t CM_RGAM_RAMA_REGION_4_5; + uint32_t CM_RGAM_RAMA_REGION_6_7; + uint32_t CM_RGAM_RAMA_REGION_8_9; + uint32_t CM_RGAM_RAMA_REGION_10_11; + uint32_t CM_RGAM_RAMA_REGION_12_13; + uint32_t CM_RGAM_RAMA_REGION_14_15; + uint32_t CM_RGAM_RAMA_REGION_16_17; + uint32_t CM_RGAM_RAMA_REGION_18_19; + uint32_t CM_RGAM_RAMA_REGION_20_21; + uint32_t CM_RGAM_RAMA_REGION_22_23; + uint32_t CM_RGAM_RAMA_REGION_24_25; + uint32_t CM_RGAM_RAMA_REGION_26_27; + uint32_t CM_RGAM_RAMA_REGION_28_29; + uint32_t CM_RGAM_RAMA_REGION_30_31; + uint32_t CM_RGAM_RAMA_REGION_32_33; + uint32_t CM_RGAM_LUT_INDEX; + uint32_t CM_MEM_PWR_CTRL; + uint32_t CM_RGAM_LUT_DATA; +}; + +struct dcn10_opp { + struct output_pixel_processor base; + + const struct dcn10_opp_registers *regs; + const struct dcn10_opp_shift *opp_shift; + const struct dcn10_opp_mask *opp_mask; + + bool is_write_to_ram_a_safe; +}; + +void dcn10_opp_construct(struct dcn10_opp *oppn10, + struct dc_context *ctx, + uint32_t inst, + const struct dcn10_opp_registers *regs, + const struct dcn10_opp_shift *opp_shift, + const struct dcn10_opp_mask *opp_mask); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c new file mode 100644 index 000000000000..7aa438cd2b1a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -0,0 +1,1475 @@ +/* +* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn10/dcn10_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn10/dcn10_mpc.h" +#include "irq/dcn10/irq_service_dcn10.h" +#include "dcn10/dcn10_transform.h" +#include "dcn10/dcn10_timing_generator.h" +#include "dcn10/dcn10_hw_sequencer.h" +#include "dce110/dce110_hw_sequencer.h" +#include "dcn10/dcn10_opp.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_clocks.h" +#include "dce/dce_clock_source.h" +#include "dcn10/dcn10_mem_input.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "../virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" + +#include "vega10/soc15ip.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" + +#include "raven1/NBIO/nbio_7_0_offset.h" + +#include "raven1/MMHUB/mmhub_9_1_offset.h" +#include "raven1/MMHUB/mmhub_9_1_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" + +#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f + #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f + #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f + #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f + #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f + #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f + #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f + #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 +#endif + + +enum dcn10_clk_src_array_id { + DCN10_CLK_SRC_PLL0, + DCN10_CLK_SRC_PLL1, + DCN10_CLK_SRC_PLL2, + DCN10_CLK_SRC_PLL3, + DCN10_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIF_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* GC */ +#define GC_BASE_INNER(seg) \ + GC_BASE__INST0_SEG ## seg + +#define GC_BASE(seg) \ + GC_BASE_INNER(seg) + +#define GC_SR(reg_name)\ + .reg_name = GC_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +static const struct dce_disp_clk_registers disp_clk_regs = { + CLK_DCN10_REG_LIST() +}; + +static const struct dce_disp_clk_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_disp_clk_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCN10_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCN10(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCN10_REG_LIST(0) +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN10(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN_REG_LIST(id),\ + .TMDS_CNTL = 0,\ + .AFMT_AVI_INFO0 = 0,\ + .AFMT_AVI_INFO1 = 0,\ + .AFMT_AVI_INFO2 = 0,\ + .AFMT_AVI_INFO3 = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN10(_MASK), + .AFMT_GENERIC0_UPDATE = 0, + .AFMT_GENERIC2_UPDATE = 0, + .DP_DYN_RANGE = 0, + .DP_YCBCR_RANGE = 0, + .HDMI_AVI_INFO_SEND = 0, + .HDMI_AVI_INFO_CONT = 0, + .HDMI_AVI_INFO_LINE = 0, + .DP_SEC_AVI_ENABLE = 0, + .AFMT_AVI_INFO_VERSION = 0 +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_aduio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCN10_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_DCN10_REG_LIST(id),\ +} + +static const struct dcn10_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), +}; + +static const struct dcn10_ipp_shift ipp_shift = { + IPP_DCN10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_ipp_mask ipp_mask = { + IPP_DCN10_MASK_SH_LIST(_MASK), +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCN10_REG_LIST(id),\ +} + +static const struct dcn10_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), +}; + +static const struct dcn10_opp_shift opp_shift = { + OPP_DCN10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_opp_mask opp_mask = { + OPP_DCN10_MASK_SH_LIST(_MASK), +}; + +#define tf_regs(id)\ +[id] = {\ + TF_REG_LIST_DCN(id),\ +} + +static const struct dcn_transform_registers tf_regs[] = { + tf_regs(0), + tf_regs(1), + tf_regs(2), + tf_regs(3), +}; + +static const struct dcn_transform_shift tf_shift = { + TF_REG_LIST_SH_MASK_DCN(__SHIFT) +}; + +static const struct dcn_transform_mask tf_mask = { + TF_REG_LIST_SH_MASK_DCN(_MASK), +}; + + +static const struct dcn_mpc_registers mpc_regs = { + MPC_COMMON_REG_LIST_DCN1_0(0), + MPC_COMMON_REG_LIST_DCN1_0(1), + MPC_COMMON_REG_LIST_DCN1_0(2), + MPC_COMMON_REG_LIST_DCN1_0(3), +}; + +static const struct dcn_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), +}; + +#define tg_regs(id)\ +[id] = {TG_COMMON_REG_LIST_DCN1_0(id)} + +static const struct dcn_tg_registers tg_regs[] = { + tg_regs(0), + tg_regs(1), + tg_regs(2), + tg_regs(3), +}; + +static const struct dcn_tg_shift tg_shift = { + TG_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn_tg_mask tg_mask = { + TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define mi_regs(id)\ +[id] = {\ + MI_DCN10_REG_LIST(id)\ +} + + +static const struct dcn_mi_registers mi_regs[] = { + mi_regs(0), + mi_regs(1), + mi_regs(2), + mi_regs(3), +}; + +static const struct dcn_mi_shift mi_shift = { + MI_DCN10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn_mi_mask mi_mask = { + MI_DCN10_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN1_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + + +static const struct resource_caps res_cap = { + .num_timing_generator = 4, + .num_video_plane = 4, + .num_audio = 4, + .num_stream_encoder = 4, + .num_pll = 4, +}; + +static const struct dc_debug debug_defaults_drv = { + .disable_dcc = false, + .disable_dpp_power_gate = false, + .disable_hubp_power_gate = false, + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + .use_dml_wm = false, + .use_max_voltage = true +#endif +}; + +static const struct dc_debug debug_defaults_diags = { + .disable_dpp_power_gate = false, + .disable_hubp_power_gate = false, + .disable_clock_gate = true, + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = true, +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, + .use_dml_wm = false, + .use_max_voltage = false +#endif +}; + +static void dcn10_transform_destroy(struct transform **xfm) +{ + dm_free(TO_DCN10_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dcn10_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn10_transform *transform = + dm_alloc(sizeof(struct dcn10_transform)); + + if (!transform) + return NULL; + + if (dcn10_transform_construct(transform, ctx, + &tf_regs[inst], &tf_shift, &tf_mask)) + return &transform->base; + + BREAK_TO_DEBUGGER(); + dm_free(transform); + return NULL; +} + +static struct input_pixel_processor *dcn10_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_ipp *ipp = + dm_alloc(sizeof(struct dcn10_ipp)); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn10_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + + +static struct output_pixel_processor *dcn10_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_opp *opp = + dm_alloc(sizeof(struct dcn10_opp)); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn10_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct mpc *dcn10_mpc_create( + struct dc_context *ctx) +{ + struct dcn10_mpc *mpc = dm_alloc(sizeof(struct dcn10_mpc)); + + if (!mpc) + return NULL; + + mpc->base.ctx = ctx; + mpc->mpc_regs = &mpc_regs; + mpc->mpc_shift = &mpc_shift; + mpc->mpc_mask = &mpc_mask; + + return &mpc->base; +} + +static void dcn10_mpc_destroy(struct mpc **mpc_base) +{ + if (*mpc_base) + dm_free(TO_DCN10_MPC(*mpc_base)); + + *mpc_base = NULL; +} + +static struct timing_generator *dcn10_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct dcn10_timing_generator *tgn10 = + dm_alloc(sizeof(struct dcn10_timing_generator)); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &tg_regs[instance]; + tgn10->tg_shift = &tg_shift; + tgn10->tg_mask = &tg_mask; + + dcn10_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .ycbcr420_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true, + .flags.bits.IS_YCBCR_CAPABLE = true +}; + +struct link_encoder *dcn10_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + dm_alloc(sizeof(struct dce110_link_encoder)); + + if (!enc110) + return NULL; + + if (dce110_link_encoder_construct( + enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source])) { + + return &enc110->base; + } + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +struct clock_source *dcn10_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + dm_alloc(sizeof(struct dce110_clk_src)); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + /* TODO: Registers are missing */ + /*REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/ +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct stream_encoder *dcn10_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + dm_alloc(sizeof(struct dce110_stream_encoder)); + + if (!enc110) + return NULL; + + if (dce110_stream_encoder_construct( + enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask)) + return &enc110->base; + + BREAK_TO_DEBUGGER(); + dm_free(enc110); + return NULL; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN1_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN1_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN1_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dcn10_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dcn10_stream_encoder_create, + .create_hwseq = dcn10_hwseq_create, +}; + +static const struct resource_create_funcs res_create_maximus_funcs = { + .read_dce_straps = NULL, + .create_audio = NULL, + .create_stream_encoder = NULL, + .create_hwseq = dcn10_hwseq_create, +}; + +void dcn10_clock_source_destroy(struct clock_source **clk_src) +{ + dm_free(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void destruct(struct dcn10_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + /* TODO: free dcn version of stream encoder once implemented + * rather than using virtual stream encoder + */ + dm_free(pool->base.stream_enc[i]); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dcn10_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + dm_free(TO_DCN10_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + + if (pool->base.timing_generators[i] != NULL) { + dm_free(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn10_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn10_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + if (pool->base.mpc != NULL) + dcn10_mpc_destroy(&pool->base.mpc); + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.display_clock != NULL) + dce_disp_clk_destroy(&pool->base.display_clock); +} + +static struct mem_input *dcn10_mem_input_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn10_mem_input *mem_inputn10 = + dm_alloc(sizeof(struct dcn10_mem_input)); + + if (!mem_inputn10) + return NULL; + + if (dcn10_mem_input_construct(mem_inputn10, ctx, inst, + &mi_regs[inst], &mi_shift, &mi_mask)) + return &mem_inputn10->base; + + BREAK_TO_DEBUGGER(); + dm_free(mem_inputn10); + return NULL; +} + +static void get_pixel_clock_parameters( + const struct pipe_ctx *pipe_ctx, + struct pixel_clk_params *pixel_clk_params) +{ + const struct core_stream *stream = pipe_ctx->stream; + pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; + pixel_clk_params->signal_type = pipe_ctx->stream->signal; + pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; + /* TODO: un-hardcode*/ + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->public.timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; + pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; + + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + pixel_clk_params->color_depth = COLOR_DEPTH_888; + + if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + pixel_clk_params->requested_pix_clk /= 2; + + if (stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING || + stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_SW_FRAME_PACKING || + stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA) + pixel_clk_params->requested_pix_clk *= 2; +} + +static void build_clamping_params(struct core_stream *stream) +{ + stream->clamping.clamping_level = CLAMPING_FULL_RANGE; + stream->clamping.c_depth = stream->public.timing.display_color_depth; + stream->clamping.pixel_encoding = stream->public.timing.pixel_encoding; +} + +static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +{ + + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); + + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( + pipe_ctx->clock_source, + &pipe_ctx->pix_clk_params, + &pipe_ctx->pll_settings); + + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; + + resource_build_bit_depth_reduction_params(pipe_ctx->stream, + &pipe_ctx->stream->bit_depth_params); + build_clamping_params(pipe_ctx->stream); + + return DC_OK; +} + +static enum dc_status validate_mapped_resource( + const struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = DC_OK; + uint8_t i, j; + + for (i = 0; i < context->stream_count; i++) { + struct core_stream *stream = context->streams[i]; + struct core_link *link = stream->sink->link; + + if (resource_is_stream_unchanged(dc->current_context, stream)) { + if (stream != NULL && dc->current_context->streams[i] != NULL) { + /* todo: shouldn't have to copy missing parameter here */ + resource_build_bit_depth_reduction_params(stream, + &stream->bit_depth_params); + stream->clamping.pixel_encoding = + stream->public.timing.pixel_encoding; + + resource_build_bit_depth_reduction_params(stream, + &stream->bit_depth_params); + build_clamping_params(stream); + + continue; + } + } + + for (j = 0; j < dc->res_pool->pipe_count ; j++) { + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[j]; + + if (context->res_ctx.pipe_ctx[j].stream != stream) + continue; + + + if (!pipe_ctx->tg->funcs->validate_timing( + pipe_ctx->tg, &stream->public.timing)) + return DC_FAIL_CONTROLLER_VALIDATE; + + status = build_pipe_hw_param(pipe_ctx); + + if (status != DC_OK) + return status; + + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, pipe_ctx)) + return DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + status = dc_link_validate_mode_timing( + stream, link, &stream->public.timing); + + if (status != DC_OK) + return status; + + + /* do not need to validate non root pipes */ + break; + } + } + + return DC_OK; +} + +enum dc_status dcn10_validate_with_context( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + enum dc_status result = DC_OK; + int i; + + if (set_count == 0) + return result; + + for (i = 0; i < set_count; i++) { + context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); + dc_stream_retain(&context->streams[i]->public); + context->stream_count++; + } + + result = resource_map_pool_resources(dc, context); + if (result != DC_OK) + return result; + + result = resource_map_phy_clock_resources(dc, context); + if (result != DC_OK) + return result; + + result = validate_mapped_resource(dc, context); + if (result != DC_OK) + return result; + + if (!resource_validate_attach_surfaces(set, set_count, + dc->current_context, context, dc->res_pool)) + return DC_FAIL_ATTACH_SURFACES; + + result = resource_build_scaling_params_for_context(dc, context); + if (result != DC_OK) + return result; + + if (!dcn_validate_bandwidth(dc, context)) + return DC_FAIL_BANDWIDTH_VALIDATE; + + return result; +} + +enum dc_status dcn10_validate_guaranteed( + const struct core_dc *dc, + const struct dc_stream *dc_stream, + struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + context->streams[0] = DC_STREAM_TO_CORE(dc_stream); + dc_stream_retain(&context->streams[0]->public); + context->stream_count++; + + result = resource_map_pool_resources(dc, context); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, context); + + if (result == DC_OK) + result = validate_mapped_resource(dc, context); + + if (result == DC_OK) { + validate_guaranteed_copy_streams( + context, dc->public.caps.max_streams); + result = resource_build_scaling_params_for_context(dc, context); + } + if (result == DC_OK && !dcn_validate_bandwidth(dc, context)) + return DC_FAIL_BANDWIDTH_VALIDATE; + + return result; +} + +static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( + struct validate_context *context, + const struct resource_pool *pool, + struct core_stream *stream) +{ + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); + struct pipe_ctx *idle_pipe = find_idle_secondary_pipe(res_ctx, pool); + + if (!head_pipe) + ASSERT(0); + + if (!idle_pipe) + return false; + + idle_pipe->stream = head_pipe->stream; + idle_pipe->tg = head_pipe->tg; + + idle_pipe->mi = pool->mis[idle_pipe->pipe_idx]; + idle_pipe->ipp = pool->ipps[idle_pipe->pipe_idx]; + idle_pipe->xfm = pool->transforms[idle_pipe->pipe_idx]; + idle_pipe->opp = pool->opps[idle_pipe->pipe_idx]; + + return idle_pipe; +} + +enum dcc_control { + dcc_control__256_256_xxx, + dcc_control__128_128_xxx, + dcc_control__256_64_64, +}; + +enum segment_order { + segment_order__na, + segment_order__contiguous, + segment_order__non_contiguous, +}; + +static bool dcc_support_pixel_format( + enum surface_pixel_format format, + unsigned int *bytes_per_element) +{ + /* DML: get_bytes_per_element */ + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + *bytes_per_element = 2; + return true; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + *bytes_per_element = 4; + return true; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + *bytes_per_element = 8; + return true; + default: + return false; + } +} + +static bool dcc_support_swizzle( + enum swizzle_mode_values swizzle, + unsigned int bytes_per_element, + enum segment_order *segment_order_horz, + enum segment_order *segment_order_vert) +{ + bool standard_swizzle = false; + bool display_swizzle = false; + + switch (swizzle) { + case DC_SW_4KB_S: + case DC_SW_64KB_S: + case DC_SW_VAR_S: + case DC_SW_4KB_S_X: + case DC_SW_64KB_S_X: + case DC_SW_VAR_S_X: + standard_swizzle = true; + break; + case DC_SW_4KB_D: + case DC_SW_64KB_D: + case DC_SW_VAR_D: + case DC_SW_4KB_D_X: + case DC_SW_64KB_D_X: + case DC_SW_VAR_D_X: + display_swizzle = true; + break; + default: + break; + }; + + if (bytes_per_element == 1 && standard_swizzle) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__na; + return true; + } + if (bytes_per_element == 2 && standard_swizzle) { + *segment_order_horz = segment_order__non_contiguous; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 4 && standard_swizzle) { + *segment_order_horz = segment_order__non_contiguous; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 8 && standard_swizzle) { + *segment_order_horz = segment_order__na; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 8 && display_swizzle) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__non_contiguous; + return true; + } + + return false; +} + +static void get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + /* copied from DML. might want to refactor DML to leverage from DML */ + /* DML : get_blk256_size */ + if (bytes_per_element == 1) { + *blk256_width = 16; + *blk256_height = 16; + } else if (bytes_per_element == 2) { + *blk256_width = 16; + *blk256_height = 8; + } else if (bytes_per_element == 4) { + *blk256_width = 8; + *blk256_height = 8; + } else if (bytes_per_element == 8) { + *blk256_width = 8; + *blk256_height = 4; + } +} + +static void det_request_size( + unsigned int height, + unsigned int width, + unsigned int bpe, + bool *req128_horz_wc, + bool *req128_vert_wc) +{ + unsigned int detile_buf_size = 164 * 1024; /* 164KB for DCN1.0 */ + + unsigned int blk256_height = 0; + unsigned int blk256_width = 0; + unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc; + + get_blk256_size(&blk256_width, &blk256_height, bpe); + + swath_bytes_horz_wc = height * blk256_height * bpe; + swath_bytes_vert_wc = width * blk256_width * bpe; + + *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ? + false : /* full 256B request */ + true; /* half 128b request */ + + *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ? + false : /* full 256B request */ + true; /* half 128b request */ +} + +static bool get_dcc_compression_cap(const struct dc *dc, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output) +{ + /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */ + enum dcc_control dcc_control; + unsigned int bpe; + enum segment_order segment_order_horz, segment_order_vert; + bool req128_horz_wc, req128_vert_wc; + + memset(output, 0, sizeof(*output)); + + if (dc->debug.disable_dcc) + return false; + + if (!dcc_support_pixel_format(input->format, + &bpe)) + return false; + + if (!dcc_support_swizzle(input->swizzle_mode, bpe, + &segment_order_horz, &segment_order_vert)) + return false; + + det_request_size(input->surface_size.height, input->surface_size.width, + bpe, &req128_horz_wc, &req128_vert_wc); + + if (!req128_horz_wc && !req128_vert_wc) { + dcc_control = dcc_control__256_256_xxx; + } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { + if (!req128_horz_wc) + dcc_control = dcc_control__256_256_xxx; + else if (segment_order_horz == segment_order__contiguous) + dcc_control = dcc_control__128_128_xxx; + else + dcc_control = dcc_control__256_64_64; + } else if (input->scan == SCAN_DIRECTION_VERTICAL) { + if (!req128_vert_wc) + dcc_control = dcc_control__256_256_xxx; + else if (segment_order_vert == segment_order__contiguous) + dcc_control = dcc_control__128_128_xxx; + else + dcc_control = dcc_control__256_64_64; + } else { + if ((req128_horz_wc && + segment_order_horz == segment_order__non_contiguous) || + (req128_vert_wc && + segment_order_vert == segment_order__non_contiguous)) + /* access_dir not known, must use most constraining */ + dcc_control = dcc_control__256_64_64; + else + /* reg128 is true for either horz and vert + * but segment_order is contiguous + */ + dcc_control = dcc_control__128_128_xxx; + } + + switch (dcc_control) { + case dcc_control__256_256_xxx: + output->grph.rgb.max_uncompressed_blk_size = 256; + output->grph.rgb.max_compressed_blk_size = 256; + output->grph.rgb.independent_64b_blks = false; + break; + case dcc_control__128_128_xxx: + output->grph.rgb.max_uncompressed_blk_size = 128; + output->grph.rgb.max_compressed_blk_size = 128; + output->grph.rgb.independent_64b_blks = false; + break; + case dcc_control__256_64_64: + output->grph.rgb.max_uncompressed_blk_size = 256; + output->grph.rgb.max_compressed_blk_size = 64; + output->grph.rgb.independent_64b_blks = true; + break; + } + output->capable = true; + output->const_color_support = false; + + return true; +} + + +static void dcn10_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn10_resource_pool *dcn10_pool = TO_DCN10_RES_POOL(*pool); + + destruct(dcn10_pool); + dm_free(dcn10_pool); + *pool = NULL; +} + + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = get_dcc_compression_cap +}; + +static struct resource_funcs dcn10_res_pool_funcs = { + .destroy = dcn10_destroy_resource_pool, + .link_enc_create = dcn10_link_encoder_create, + .validate_with_context = dcn10_validate_with_context, + .validate_guaranteed = dcn10_validate_guaranteed, + .validate_bandwidth = dcn_validate_bandwidth, + .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, +}; + +static bool construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dcn10_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dcn10_res_pool_funcs; + + /* + * TODO fill in from actual raven resource when we create + * more than virtual encoder + */ + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + /* TODO: Hardcode to correct number of functional controllers */ + pool->base.pipe_count = 4; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 100; + dc->public.caps.max_cursor_size = 256; + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->public.debug = debug_defaults_drv; + else + dc->public.debug = debug_defaults_diags; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCN10_CLK_SRC_PLL0] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN10_CLK_SRC_PLL1] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN10_CLK_SRC_PLL2] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN10_CLK_SRC_PLL3] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + + pool->base.clk_src_count = DCN10_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + /* todo: not reuse phy_pll registers */ + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto clock_source_create_fail; + } + } + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + pool->base.display_clock = dce120_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto disp_clk_create_fail; + } + } + + pool->base.dmcu = dcn10_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + dml_init_instance(&dc->dml, DML_PROJECT_RAVEN1); + dc->dcn_ip = dcn10_ip_defaults; + dc->dcn_soc = dcn10_soc_defaults; + if (!dc->public.debug.disable_pplib_clock_request) + dcn_bw_update_from_pplib(dc); + dcn_bw_sync_calcs_and_dml(dc); + if (!dc->public.debug.disable_pplib_wm_range) + dcn_bw_notify_pplib_of_wm_ranges(dc); + + { + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn10_create(&init_data); + if (!pool->base.irqs) + goto irqs_create_fail; + #endif + } + + /* mem input -> ipp -> transform -> opp -> TG */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.mis[i] = dcn10_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto mi_create_fail; + } + + pool->base.ipps[i] = dcn10_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto ipp_create_fail; + } + + pool->base.transforms[i] = dcn10_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto transform_create_fail; + } + + pool->base.opps[i] = dcn10_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto opp_create_fail; + } + + pool->base.timing_generators[i] = dcn10_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto otg_create_fail; + } + } + + pool->base.mpc = dcn10_mpc_create(ctx); + + if (!resource_construct(num_virtual_links, dc, &pool->base, + (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? + &res_create_funcs : &res_create_maximus_funcs))) + goto res_create_fail; + + dcn10_hw_sequencer_construct(dc); + dc->public.caps.max_surfaces = pool->base.pipe_count; + + dc->public.cap_funcs = cap_funcs; + + return true; + +disp_clk_create_fail: +otg_create_fail: +opp_create_fail: +transform_create_fail: +ipp_create_fail: +mi_create_fail: +irqs_create_fail: +res_create_fail: +clock_source_create_fail: + + destruct(pool); + + return false; +} + +struct resource_pool *dcn10_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dcn10_resource_pool *pool = + dm_alloc(sizeof(struct dcn10_resource_pool)); + + if (!pool) + return NULL; + + if (construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h new file mode 100644 index 000000000000..5f84dbd0bdea --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h @@ -0,0 +1,47 @@ +/* +* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCN10_H__ +#define __DC_RESOURCE_DCN10_H__ + +#include "core_types.h" + +#define TO_DCN10_RES_POOL(pool)\ + container_of(pool, struct dcn10_resource_pool, base) + +struct core_dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +struct dcn10_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn10_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + + +#endif /* __DC_RESOURCE_DCN10_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c new file mode 100644 index 000000000000..d7072132d456 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -0,0 +1,1202 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dcn10_timing_generator.h" + +#define REG(reg)\ + tgn10->tg_regs->reg + +#define CTX \ + tgn10->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + tgn10->tg_shift->field_name, tgn10->tg_mask->field_name + +#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 + +/** +* apply_front_porch_workaround TODO FPGA still need? +* +* This is a workaround for a bug that has existed since R5xx and has not been +* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. +*/ +static void tg_apply_front_porch_workaround( + struct timing_generator *tg, + struct dc_crtc_timing *timing) +{ + if (timing->flags.INTERLACE == 1) { + if (timing->v_front_porch < 2) + timing->v_front_porch = 2; + } else { + if (timing->v_front_porch < 1) + timing->v_front_porch = 1; + } +} + +static void dcn10_program_global_sync( + struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + if (tg->dlg_otg_param.vstartup_start == 0) { + BREAK_TO_DEBUGGER(); + return; + } + + REG_SET(OTG_VSTARTUP_PARAM, 0, + VSTARTUP_START, tg->dlg_otg_param.vstartup_start); + + REG_SET_2(OTG_VUPDATE_PARAM, 0, + VUPDATE_OFFSET, tg->dlg_otg_param.vupdate_offset, + VUPDATE_WIDTH, tg->dlg_otg_param.vupdate_width); + + REG_SET(OTG_VREADY_PARAM, 0, + VREADY_OFFSET, tg->dlg_otg_param.vready_offset); +} + +struct crtc_stereo_flags { + uint8_t PROGRAM_STEREO :1; + uint8_t PROGRAM_POLARITY :1; + uint8_t RIGHT_EYE_POLARITY :1; + uint8_t FRAME_PACKED :1; + uint8_t DISABLE_STEREO_DP_SYNC :1; +}; + +static void dcn10_enable_stereo(struct timing_generator *tg, + const struct crtc_stereo_flags *flags, + const struct dc_crtc_timing *timing) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + uint32_t active_width = timing->h_addressable; + uint32_t space1_size = timing->v_total - timing->v_addressable; + + if (flags) { + uint32_t stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; + + if (flags->PROGRAM_STEREO) + REG_UPDATE_3(OTG_STEREO_CONTROL, + OTG_STEREO_EN, stereo_en, + OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, + OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); + + if (flags->PROGRAM_POLARITY) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_STEREO_EYE_FLAG_POLARITY, + flags->RIGHT_EYE_POLARITY == 0 ? 0:1); + + if (flags->DISABLE_STEREO_DP_SYNC) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); + + if (flags->PROGRAM_STEREO && flags->FRAME_PACKED) + REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, + OTG_3D_STRUCTURE_EN, 1, + OTG_3D_STRUCTURE_V_UPDATE_MODE, 1, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1); + + } + + REG_UPDATE(OPPBUF_CONTROL, + OPPBUF_ACTIVE_WIDTH, active_width); + + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, + OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); + + return; +} + +static void dcn10_disable_stereo(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_SET(OTG_STEREO_CONTROL, 0, + OTG_STEREO_EN, 0); + + REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0, + OTG_3D_STRUCTURE_EN, 0, + OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); + + REG_UPDATE(OPPBUF_CONTROL, + OPPBUF_ACTIVE_WIDTH, 0); + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, + OPPBUF_3D_VACT_SPACE1_SIZE, 0); + return; +} + +static bool is_frame_alternate_stereo(enum dc_timing_3d_format fmt) +{ + bool ret = false; + if (fmt == TIMING_3D_FORMAT_FRAME_ALTERNATE || + fmt == TIMING_3D_FORMAT_INBAND_FA || + fmt == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || + fmt == TIMING_3D_FORMAT_SIDEBAND_FA) + ret = true; + return ret; +} + +static void dcn10_do_stereo(struct timing_generator *tg, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct crtc_stereo_flags stereo_flags = {0}; + if (dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_NONE || + dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || + dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) + dcn10_disable_stereo(tg); + else { + stereo_flags.PROGRAM_STEREO = 1; + stereo_flags.PROGRAM_POLARITY = 1; + stereo_flags.DISABLE_STEREO_DP_SYNC = 0; + stereo_flags.RIGHT_EYE_POLARITY = + dc_crtc_timing->flags.RIGHT_EYE_3D_POLARITY; + if (dc_crtc_timing->timing_3d_format == + TIMING_3D_FORMAT_HW_FRAME_PACKING) + stereo_flags.FRAME_PACKED = 1; + + if (is_frame_alternate_stereo( + dc_crtc_timing->timing_3d_format) || + dc_crtc_timing->timing_3d_format == + TIMING_3D_FORMAT_HW_FRAME_PACKING) + dcn10_enable_stereo(tg, &stereo_flags, dc_crtc_timing); + } +} + +/** + * program_timing_generator used by mode timing set + * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. + * Including SYNC. Call BIOS command table to program Timings. + */ +static void tg_program_timing_generator( + struct timing_generator *tg, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct dc_crtc_timing patched_crtc_timing; + uint32_t vesa_sync_start; + uint32_t asic_blank_end; + uint32_t asic_blank_start; + uint32_t v_total; + uint32_t v_sync_end; + uint32_t v_init, v_fp2; + uint32_t h_sync_polarity, v_sync_polarity; + uint32_t interlace_factor; + uint32_t start_point = 0; + uint32_t field_num = 0; + uint32_t h_div_2; + + + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + patched_crtc_timing = *dc_crtc_timing; + tg_apply_front_porch_workaround(tg, &patched_crtc_timing); + + /* Load horizontal timing */ + + /* CRTC_H_TOTAL = vesa.h_total - 1 */ + REG_SET(OTG_H_TOTAL, 0, + OTG_H_TOTAL, patched_crtc_timing.h_total - 1); + + /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */ + REG_UPDATE_2(OTG_H_SYNC_A, + OTG_H_SYNC_A_START, 0, + OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width); + + /* asic_h_blank_end = HsyncWidth + HbackPorch = + * vesa. usHorizontalTotal - vesa. usHorizontalSyncStart - + * vesa.h_left_border + */ + vesa_sync_start = patched_crtc_timing.h_addressable + + patched_crtc_timing.h_border_right + + patched_crtc_timing.h_front_porch; + + asic_blank_end = patched_crtc_timing.h_total - + vesa_sync_start - + patched_crtc_timing.h_border_left; + + /* h_blank_start = v_blank_end + v_active */ + asic_blank_start = asic_blank_end + + patched_crtc_timing.h_border_left + + patched_crtc_timing.h_addressable + + patched_crtc_timing.h_border_right; + + REG_UPDATE_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, asic_blank_start, + OTG_H_BLANK_END, asic_blank_end); + + /* h_sync polarity */ + h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? + 0 : 1; + + REG_UPDATE(OTG_H_SYNC_A_CNTL, + OTG_H_SYNC_A_POL, h_sync_polarity); + + /* Load vertical timing */ + + /* CRTC_V_TOTAL = v_total - 1 */ + if (patched_crtc_timing.flags.INTERLACE) { + interlace_factor = 2; + v_total = 2 * patched_crtc_timing.v_total; + } else { + interlace_factor = 1; + v_total = patched_crtc_timing.v_total - 1; + } + REG_SET(OTG_V_TOTAL, 0, + OTG_V_TOTAL, v_total); + + /* v_sync_start = 0, v_sync_end = v_sync_width */ + v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor; + + REG_UPDATE_2(OTG_V_SYNC_A, + OTG_V_SYNC_A_START, 0, + OTG_V_SYNC_A_END, v_sync_end); + + vesa_sync_start = patched_crtc_timing.v_addressable + + patched_crtc_timing.v_border_bottom + + patched_crtc_timing.v_front_porch; + + asic_blank_end = (patched_crtc_timing.v_total - + vesa_sync_start - + patched_crtc_timing.v_border_top) + * interlace_factor; + + /* v_blank_start = v_blank_end + v_active */ + asic_blank_start = asic_blank_end + + (patched_crtc_timing.v_border_top + + patched_crtc_timing.v_addressable + + patched_crtc_timing.v_border_bottom) + * interlace_factor; + + REG_UPDATE_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, asic_blank_start, + OTG_V_BLANK_END, asic_blank_end); + + + /* v_sync polarity */ + v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? + 0 : 1; + + REG_UPDATE(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, v_sync_polarity); + + v_init = asic_blank_start; + if (tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || + tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + tg->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { + v_init = asic_blank_start; + start_point = 1; + if (patched_crtc_timing.flags.INTERLACE == 1) + field_num = 1; + } + if (v_init < 0) + v_init = 0; + v_fp2 = 0; + if (tg->dlg_otg_param.vstartup_start > asic_blank_end) + v_fp2 = tg->dlg_otg_param.vstartup_start > asic_blank_end; + + /* Interlace */ + if (patched_crtc_timing.flags.INTERLACE == 1) { + REG_UPDATE(OTG_INTERLACE_CONTROL, + OTG_INTERLACE_ENABLE, 1); + v_init = v_init / 2; + if ((tg->dlg_otg_param.vstartup_start/2)*2 > asic_blank_end) + v_fp2 = v_fp2 / 2; + } + else + REG_UPDATE(OTG_INTERLACE_CONTROL, + OTG_INTERLACE_ENABLE, 0); + + + /* VTG enable set to 0 first VInit */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + REG_UPDATE_2(CONTROL, + VTG0_FP2, v_fp2, + VTG0_VCOUNT_INIT, v_init); + + /* original code is using VTG offset to address OTG reg, seems wrong */ + REG_UPDATE_2(OTG_CONTROL, + OTG_START_POINT_CNTL, start_point, + OTG_FIELD_NUMBER_CNTL, field_num); + + dcn10_program_global_sync(tg); + + /* TODO + * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 + * program_horz_count_by_2 + * for DVI 30bpp mode, 0 otherwise + * program_horz_count_by_2(tg, &patched_crtc_timing); + */ + + /* Enable stereo - only when we need to pack 3D frame. Other types + * of stereo handled in explicit call + */ + h_div_2 = (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ? + 1 : 0; + + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_BY2, h_div_2); + + /* Enable crtc stereo frame pack tested... todo more + */ + dcn10_do_stereo(tg, &patched_crtc_timing); +} + +/** tg_program_blanking + * Only programmed part of OTG_H, OTG_V register for set_plane_config + * Assume other OTG registers are programmed by video mode set already. + * This function is for underlay. DCN will have new sequence. + * This function will be removed. Need remove it from set_plane_config + */ + +static void tg_program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + bool use_vbios) +{ + tg_program_timing_generator(tg, timing); +} + +/** + * unblank_crtc + * Call ASIC Control Object to UnBlank CRTC. + */ +static void tg_unblank_crtc(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_UPDATE_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, 0, + OTG_BLANK_DE_MODE, 0); +} + +/** + * blank_crtc + * Call ASIC Control Object to Blank CRTC. + */ + +static void tg_blank_crtc(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_UPDATE_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, 1, + OTG_BLANK_DE_MODE, 0); + + /* todo: why are we waiting for BLANK_DATA_EN? shouldn't we be waiting + * for status? + */ + REG_WAIT(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, 1, + 20000, 200000); + + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 0); +} + +static void tg_set_blank(struct timing_generator *tg, + bool enable_blanking) +{ + if (enable_blanking) + tg_blank_crtc(tg); + else + tg_unblank_crtc(tg); +} + +static bool tg_is_blanked(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t blank_en; + uint32_t blank_state; + + REG_GET_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, &blank_en, + OTG_CURRENT_BLANK_STATE, &blank_state); + + return blank_en && blank_state; +} + +static void enable_optc_clock(struct timing_generator *tg, bool enable) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + if (enable) { + REG_UPDATE(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_EN, 1); + + REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_ON, 1, + 20000, 200000); + + /* Enable clock */ + REG_UPDATE(OTG_CLOCK_CONTROL, + OTG_CLOCK_EN, 1); + + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_CLOCK_ON, 1, + 20000, 200000); + } else { + REG_UPDATE_2(OTG_CLOCK_CONTROL, + OTG_CLOCK_GATE_DIS, 0, + OTG_CLOCK_EN, 0); + + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_CLOCK_ON, 0, + 20000, 200000); + + REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_GATE_DIS, 0, + OPTC_INPUT_CLK_EN, 0); + + REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_ON, 0, + 20000, 200000); + } +} + +/** + * Enable CRTC + * Enable CRTC - call ASIC Control Object to enable Timing generator. + */ +static bool tg_enable_crtc(struct timing_generator *tg) +{ + /* TODO FPGA wait for answer + * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE + * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK + */ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + /* opp instance for OTG. For DCN1.0, ODM is remoed. + * OPP and OPTC should 1:1 mapping + */ + REG_UPDATE(OPTC_DATA_SOURCE_SELECT, + OPTC_SRC_SEL, tg->inst); + + /* VTG enable first is for HW workaround */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 1); + + /* Enable CRTC */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 3, + OTG_MASTER_EN, 1); + + return true; +} + +/* disable_crtc - call ASIC Control Object to disable Timing generator. */ +static bool tg_disable_crtc(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + /* disable otg request until end of the first line + * in the vertical blank region + */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 3, + OTG_MASTER_EN, 0); + + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_BUSY, 0, + 2000, 20000); + + return true; +} + + +static void tg_program_blank_color( + struct timing_generator *tg, + const struct tg_color *black_color) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_SET_3(OTG_BLACK_COLOR, 0, + OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, + OTG_BLACK_COLOR_G_Y, black_color->color_g_y, + OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); +} + +/** + * dcn10_dcn10_timing_generator_disable_vga + * Turn OFF VGA Mode and Timing - DxVGA_CONTROL + * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors; + */ +/* TODO FPGA FPGA setup is done by Diag which does not enable VGA mode. + * VGA is disable by ASIC default. This function is not needed for + * FPGA story. + * usage: + * init_hw within dc.c + * disable_vga_and_power_gate_all_controllers within dce110_hw_sequencer.c + * We may move init_hw into DC specific so that we can remove + * .disable_vga from upper layer stack + */ +static void dcn10_timing_generator_disable_vga( + struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + switch (tgn10->base.inst) { + case 0: + REG_WRITE(D1VGA_CONTROL, 0); + break; + case 1: + REG_WRITE(D2VGA_CONTROL, 0); + break; + case 2: + REG_WRITE(D2VGA_CONTROL, 0); + break; + case 3: + REG_WRITE(D4VGA_CONTROL, 0); + break; + default: + break; + } +} + +static bool tg_validate_timing( + struct timing_generator *tg, + const struct dc_crtc_timing *timing) +{ + uint32_t interlace_factor; + uint32_t v_blank; + uint32_t h_blank; + uint32_t min_v_blank; + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + ASSERT(timing != NULL); + + interlace_factor = timing->flags.INTERLACE ? 2 : 1; + v_blank = (timing->v_total - timing->v_addressable - + timing->v_border_top - timing->v_border_bottom) * + interlace_factor; + + h_blank = (timing->h_total - timing->h_addressable - + timing->h_border_right - + timing->h_border_left); + + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && + timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && + timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && + timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && + timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE) + return false; + + /* Temporarily blocking interlacing mode until it's supported */ + if (timing->flags.INTERLACE == 1) + return false; + + /* Check maximum number of pixels supported by Timing Generator + * (Currently will never fail, in order to fail needs display which + * needs more than 8192 horizontal and + * more than 8192 vertical total pixels) + */ + if (timing->h_total > tgn10->max_h_total || + timing->v_total > tgn10->max_v_total) + return false; + + + if (h_blank < tgn10->min_h_blank) + return false; + + if (timing->h_sync_width < tgn10->min_h_sync_width || + timing->v_sync_width < tgn10->min_v_sync_width) + return false; + + min_v_blank = timing->flags.INTERLACE?tgn10->min_v_blank_interlace:tgn10->min_v_blank; + + if (v_blank < min_v_blank) + return false; + + return true; + +} + +/* + * get_vblank_counter + * + * @brief + * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which + * holds the counter of frames. + * + * @param + * struct timing_generator *tg - [in] timing generator which controls the + * desired CRTC + * + * @return + * Counter of frames, which should equal to number of vblanks. + */ +static uint32_t tg_get_vblank_counter(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t frame_count; + + REG_GET(OTG_STATUS_FRAME_COUNT, + OTG_FRAME_COUNT, &frame_count); + + return frame_count; +} + +void dcn10_lock(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); +} + +void dcn10_unlock(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 0); + + /* why are we waiting here? */ + REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, + OTG_UPDATE_PENDING, 0, + 20000, 200000); +} + +static void dcn10_get_position(struct timing_generator *tg, + struct crtc_position *position) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_GET_2(OTG_STATUS_POSITION, + OTG_HORZ_COUNT, &position->horizontal_count, + OTG_VERT_COUNT, &position->vertical_count); + + REG_GET(OTG_NOM_VERT_POSITION, + OTG_VERT_COUNT_NOM, &position->nominal_vcount); +} + +bool dcn10_is_counter_moving(struct timing_generator *tg) +{ + struct crtc_position position1, position2; + + tg->funcs->get_position(tg, &position1); + tg->funcs->get_position(tg, &position2); + + if (position1.horizontal_count == position2.horizontal_count && + position1.vertical_count == position2.vertical_count) + return false; + else + return true; +} + +static bool dcn10_did_triggered_reset_occur( + struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t occurred; + + REG_GET(OTG_FORCE_COUNT_NOW_CNTL, + OTG_FORCE_COUNT_NOW_OCCURRED, &occurred); + + return occurred != 0; +} + +static void dcn10_enable_reset_trigger(struct timing_generator *tg, int source_tg_inst) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t falling_edge; + + REG_GET(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, &falling_edge); + + if (falling_edge) + REG_SET_3(OTG_TRIGA_CNTL, 0, + /* vsync signal from selected OTG pipe based + * on OTG_TRIG_SOURCE_PIPE_SELECT setting + */ + OTG_TRIGA_SOURCE_SELECT, 20, + OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, + /* always detect falling edge */ + OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1); + else + REG_SET_3(OTG_TRIGA_CNTL, 0, + /* vsync signal from selected OTG pipe based + * on OTG_TRIG_SOURCE_PIPE_SELECT setting + */ + OTG_TRIGA_SOURCE_SELECT, 20, + OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, + /* always detect rising edge */ + OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1); + + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + /* force H count to H_TOTAL and V count to V_TOTAL in + * progressive mode and V_TOTAL-1 in interlaced mode + */ + OTG_FORCE_COUNT_NOW_MODE, 2); +} + +static void dcn10_disable_reset_trigger(struct timing_generator *tg) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_WRITE(OTG_TRIGA_CNTL, 0); + + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + OTG_FORCE_COUNT_NOW_CLEAR, 1); +} + +static void dcn10_wait_for_state(struct timing_generator *tg, + enum crtc_state state) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + switch (state) { + case CRTC_STATE_VBLANK: + REG_WAIT(OTG_STATUS, + OTG_V_BLANK, 1, + 100, 100000); /* 1 vupdate at 10hz */ + break; + + case CRTC_STATE_VACTIVE: + REG_WAIT(OTG_STATUS, + OTG_V_ACTIVE_DISP, 1, + 100, 100000); /* 1 vupdate at 10hz */ + break; + + default: + break; + } +} + +static void set_early_control( + struct timing_generator *tg, + uint32_t early_cntl) +{ + /* asic design change, do not need this control + * empty for share caller logic + */ +} + + +static void set_static_screen_control( + struct timing_generator *tg, + uint32_t value) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + /* Bit 8 is no longer applicable in RV for PSR case, + * set bit 8 to 0 if given + */ + if ((value & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN) + != 0) + value = value & + ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN; + + REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0, + OTG_STATIC_SCREEN_EVENT_MASK, value, + OTG_STATIC_SCREEN_FRAME_COUNT, 2); +} + + +/** + ***************************************************************************** + * Function: set_drr + * + * @brief + * Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. + * + ***************************************************************************** + */ +void dcn10_timing_generator_set_drr( + struct timing_generator *tg, + const struct drr_params *params) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + REG_SET(OTG_V_TOTAL_MAX, 0, + OTG_V_TOTAL_MAX, params->vertical_total_max - 1); + + REG_SET(OTG_V_TOTAL_MIN, 0, + OTG_V_TOTAL_MIN, params->vertical_total_min - 1); + + REG_UPDATE_5(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK_EN, 0, + OTG_SET_V_TOTAL_MIN_MASK, 0); + } else { + REG_SET(OTG_V_TOTAL_MIN, 0, + OTG_V_TOTAL_MIN, 0); + + REG_SET(OTG_V_TOTAL_MAX, 0, + OTG_V_TOTAL_MAX, 0); + + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_SET_V_TOTAL_MIN_MASK, 0, + OTG_V_TOTAL_MIN_SEL, 0, + OTG_V_TOTAL_MAX_SEL, 0, + OTG_FORCE_LOCK_ON_EVENT, 0); + } +} + +static void dcn10_timing_generator_set_test_pattern( + struct timing_generator *tg, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + enum test_pattern_color_format bit_depth; + enum test_pattern_dyn_range dyn_range; + enum test_pattern_mode mode; + uint32_t pattern_mask; + uint32_t pattern_data; + /* color ramp generator mixes 16-bits color */ + uint32_t src_bpc = 16; + /* requested bpc */ + uint32_t dst_bpc; + uint32_t index; + /* RGB values of the color bars. + * Produce two RGB colors: RGB0 - white (all Fs) + * and RGB1 - black (all 0s) + * (three RGB components for two colors) + */ + uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, + 0x0000, 0x0000}; + /* dest color (converted to the specified color format) */ + uint16_t dst_color[6]; + uint32_t inc_base; + + /* translate to bit depth */ + switch (color_depth) { + case COLOR_DEPTH_666: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; + break; + case COLOR_DEPTH_888: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + case COLOR_DEPTH_101010: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; + break; + case COLOR_DEPTH_121212: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; + break; + default: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + } + + switch (test_pattern) { + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: + { + dyn_range = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? + TEST_PATTERN_DYN_RANGE_CEA : + TEST_PATTERN_DYN_RANGE_VESA); + mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; + + REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_HRES, 6); + + REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: + case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: + { + mode = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? + TEST_PATTERN_MODE_VERTICALBARS : + TEST_PATTERN_MODE_HORIZONTALBARS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* adjust color to the required colorFormat */ + for (index = 0; index < 6; index++) { + /* dst = 2^dstBpc * src / 2^srcBpc = src >> + * (srcBpc - dstBpc); + */ + dst_color[index] = + src_color[index] >> (src_bpc - dst_bpc); + /* CRTC_TEST_PATTERN_DATA has 16 bits, + * lowest 6 are hardwired to ZERO + * color bits should be left aligned aligned to MSB + * XXXXXXXXXX000000 for 10 bit, + * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 + */ + dst_color[index] <<= (16 - dst_bpc); + } + + REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); + + /* We have to write the mask before data, similar to pipeline. + * For example, for 8 bpc, if we want RGB0 to be magenta, + * and RGB1 to be cyan, + * we need to make 7 writes: + * MASK DATA + * 000001 00000000 00000000 set mask to R0 + * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 + * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 + * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 + * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 + * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 + * 100000 11111111 00000000 B1 255, 0xFF00 + * + * we will make a loop of 6 in which we prepare the mask, + * then write, then prepare the color for next write. + * first iteration will write mask only, + * but each next iteration color prepared in + * previous iteration will be written within new mask, + * the last component will written separately, + * mask is not changing between 6th and 7th write + * and color will be prepared by last iteration + */ + + /* write color, color values mask in CRTC_TEST_PATTERN_MASK + * is B1, G1, R1, B0, G0, R0 + */ + pattern_data = 0; + for (index = 0; index < 6; index++) { + /* prepare color mask, first write PATTERN_DATA + * will have all zeros + */ + pattern_mask = (1 << index); + + /* write color component */ + REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, + OTG_TEST_PATTERN_MASK, pattern_mask, + OTG_TEST_PATTERN_DATA, pattern_data); + + /* prepare next color component, + * will be written in the next iteration + */ + pattern_data = dst_color[index]; + } + /* write last color component, + * it's been already prepared in the loop + */ + REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, + OTG_TEST_PATTERN_MASK, pattern_mask, + OTG_TEST_PATTERN_DATA, pattern_data); + + /* enable test pattern */ + REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: + { + mode = (bit_depth == + TEST_PATTERN_COLOR_FORMAT_BPC_10 ? + TEST_PATTERN_MODE_DUALRAMP_RGB : + TEST_PATTERN_MODE_SINGLERAMP_RGB); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* increment for the first ramp for one color gradation + * 1 gradation for 6-bit color is 2^10 + * gradations in 16-bit color + */ + inc_base = (src_bpc - dst_bpc); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, 0, + OTG_TEST_PATTERN_HRES, 6, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, 0, + OTG_TEST_PATTERN_HRES, 8, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, inc_base + 2, + OTG_TEST_PATTERN_HRES, 8, + OTG_TEST_PATTERN_VRES, 5, + OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); + } + break; + default: + break; + } + + REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); + + /* enable test pattern */ + REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); + + REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: + { + REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); + REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); + REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); + } + break; + default: + break; + + } +} + +void dcn10_timing_generator_get_crtc_scanoutpos( + struct timing_generator *tg, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + struct crtc_position position; + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, v_blank_start, + OTG_V_BLANK_END, v_blank_end); + + dcn10_get_position(tg, &position); + + *h_position = position.horizontal_count; + *v_position = position.vertical_count; +} + +static struct timing_generator_funcs dcn10_tg_funcs = { + .validate_timing = tg_validate_timing, + .program_timing = tg_program_timing, + .program_global_sync = dcn10_program_global_sync, + .enable_crtc = tg_enable_crtc, + .disable_crtc = tg_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = dcn10_is_counter_moving, + /* never be called */ + .get_position = dcn10_get_position, + .get_frame_count = tg_get_vblank_counter, + .get_scanoutpos = dcn10_timing_generator_get_crtc_scanoutpos, + .set_early_control = set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = dcn10_wait_for_state, + .set_blank = tg_set_blank, + .is_blanked = tg_is_blanked, + /* never be called */ + .set_colors = NULL, + /* this function will be called by .progam_scaler. dcn and dce + * scaler top level functions are different. .program_scaler is + * not need for dcn. within program_scaler, dcn will return + * early before set_overscan_blank_color is reached + */ + .set_overscan_blank_color = NULL, + .set_blank_color = tg_program_blank_color, + /* dcn10_timing_generator_disable_vga */ + .disable_vga = dcn10_timing_generator_disable_vga, + .did_triggered_reset_occur = dcn10_did_triggered_reset_occur, + .enable_reset_trigger = dcn10_enable_reset_trigger, + .disable_reset_trigger = dcn10_disable_reset_trigger, + .lock = dcn10_lock, + .unlock = dcn10_unlock, + /* dcn10_timing_generator_enable_advanced_request*/ + .enable_advanced_request = NULL, + .enable_optc_clock = enable_optc_clock, + .set_drr = dcn10_timing_generator_set_drr, + .set_static_screen_control = set_static_screen_control, + .set_test_pattern = dcn10_timing_generator_set_test_pattern +}; + +void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) +{ + tgn10->base.funcs = &dcn10_tg_funcs; + + tgn10->max_h_total = tgn10->tg_mask->OTG_H_TOTAL + 1; + tgn10->max_v_total = tgn10->tg_mask->OTG_V_TOTAL + 1; + + tgn10->min_h_blank = 32; + tgn10->min_v_blank = 3; + tgn10->min_v_blank_interlace = 5; + tgn10->min_h_sync_width = 8; + tgn10->min_v_sync_width = 1; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h new file mode 100644 index 000000000000..85a763af1956 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -0,0 +1,335 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCN10_H__ +#define __DC_TIMING_GENERATOR_DCN10_H__ + +#include "timing_generator.h" + +#define DCN10TG_FROM_TG(tg)\ + container_of(tg, struct dcn10_timing_generator, base) + +#define TG_COMMON_REG_LIST_DCN1_0(inst) \ + SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ + SRI(OTG_VUPDATE_PARAM, OTG, inst),\ + SRI(OTG_VREADY_PARAM, OTG, inst),\ + SRI(OTG_BLANK_CONTROL, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ + SRI(OTG_H_TOTAL, OTG, inst),\ + SRI(OTG_H_BLANK_START_END, OTG, inst),\ + SRI(OTG_H_SYNC_A, OTG, inst),\ + SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_H_TIMING_CNTL, OTG, inst),\ + SRI(OTG_V_TOTAL, OTG, inst),\ + SRI(OTG_V_BLANK_START_END, OTG, inst),\ + SRI(OTG_V_SYNC_A, OTG, inst),\ + SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_INTERLACE_CONTROL, OTG, inst),\ + SRI(OTG_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_CONTROL, OTG, inst),\ + SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MIN, OTG, inst),\ + SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ + SRI(OTG_TRIGA_CNTL, OTG, inst),\ + SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ + SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ + SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ + SRI(OTG_STATUS, OTG, inst),\ + SRI(OTG_STATUS_POSITION, OTG, inst),\ + SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ + SRI(OTG_BLACK_COLOR, OTG, inst),\ + SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ + SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ + SRI(OTG_TEST_PATTERN_COLOR, OTG, inst),\ + SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ + SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPPBUF_CONTROL, OPPBUF, inst),\ + SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ + SRI(CONTROL, VTG, inst),\ + SR(D1VGA_CONTROL),\ + SR(D2VGA_CONTROL),\ + SR(D3VGA_CONTROL),\ + SR(D4VGA_CONTROL),\ + +struct dcn_tg_registers { + uint32_t OTG_VSTARTUP_PARAM; + uint32_t OTG_VUPDATE_PARAM; + uint32_t OTG_VREADY_PARAM; + uint32_t OTG_BLANK_CONTROL; + uint32_t OTG_MASTER_UPDATE_LOCK; + uint32_t OTG_DOUBLE_BUFFER_CONTROL; + uint32_t OTG_H_TOTAL; + uint32_t OTG_H_BLANK_START_END; + uint32_t OTG_H_SYNC_A; + uint32_t OTG_H_SYNC_A_CNTL; + uint32_t OTG_H_TIMING_CNTL; + uint32_t OTG_V_TOTAL; + uint32_t OTG_V_BLANK_START_END; + uint32_t OTG_V_SYNC_A; + uint32_t OTG_V_SYNC_A_CNTL; + uint32_t OTG_INTERLACE_CONTROL; + uint32_t OTG_CONTROL; + uint32_t OTG_STEREO_CONTROL; + uint32_t OTG_3D_STRUCTURE_CONTROL; + uint32_t OTG_V_TOTAL_MAX; + uint32_t OTG_V_TOTAL_MIN; + uint32_t OTG_V_TOTAL_CONTROL; + uint32_t OTG_TRIGA_CNTL; + uint32_t OTG_FORCE_COUNT_NOW_CNTL; + uint32_t OTG_STATIC_SCREEN_CONTROL; + uint32_t OTG_STATUS_FRAME_COUNT; + uint32_t OTG_STATUS; + uint32_t OTG_STATUS_POSITION; + uint32_t OTG_NOM_VERT_POSITION; + uint32_t OTG_BLACK_COLOR; + uint32_t OTG_TEST_PATTERN_PARAMETERS; + uint32_t OTG_TEST_PATTERN_CONTROL; + uint32_t OTG_TEST_PATTERN_COLOR; + uint32_t OTG_CLOCK_CONTROL; + uint32_t OPTC_INPUT_CLOCK_CONTROL; + uint32_t OPTC_DATA_SOURCE_SELECT; + uint32_t OPPBUF_CONTROL; + uint32_t OPPBUF_3D_PARAMETERS_0; + uint32_t CONTROL; + /*todo: move VGA to HWSS */ + uint32_t D1VGA_CONTROL; + uint32_t D2VGA_CONTROL; + uint32_t D3VGA_CONTROL; + uint32_t D4VGA_CONTROL; +}; + +#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_B_CB, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_G_Y, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_R_CR, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh),\ + SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ + SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + +#define TG_REG_FIELD_LIST(type) \ + type VSTARTUP_START;\ + type VUPDATE_OFFSET;\ + type VUPDATE_WIDTH;\ + type VREADY_OFFSET;\ + type OTG_BLANK_DATA_EN;\ + type OTG_BLANK_DE_MODE;\ + type OTG_CURRENT_BLANK_STATE;\ + type OTG_MASTER_UPDATE_LOCK;\ + type OTG_UPDATE_PENDING;\ + type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ + type OTG_H_TOTAL;\ + type OTG_H_BLANK_START;\ + type OTG_H_BLANK_END;\ + type OTG_H_SYNC_A_START;\ + type OTG_H_SYNC_A_END;\ + type OTG_H_SYNC_A_POL;\ + type OTG_H_TIMING_DIV_BY2;\ + type OTG_V_TOTAL;\ + type OTG_V_BLANK_START;\ + type OTG_V_BLANK_END;\ + type OTG_V_SYNC_A_START;\ + type OTG_V_SYNC_A_END;\ + type OTG_V_SYNC_A_POL;\ + type OTG_INTERLACE_ENABLE;\ + type OTG_MASTER_EN;\ + type OTG_START_POINT_CNTL;\ + type OTG_DISABLE_POINT_CNTL;\ + type OTG_FIELD_NUMBER_CNTL;\ + type OTG_STEREO_EN;\ + type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\ + type OTG_STEREO_SYNC_OUTPUT_POLARITY;\ + type OTG_STEREO_EYE_FLAG_POLARITY;\ + type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\ + type OTG_3D_STRUCTURE_EN;\ + type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ + type OTG_3D_STRUCTURE_STEREO_SEL_OVR;\ + type OTG_V_TOTAL_MAX;\ + type OTG_V_TOTAL_MIN;\ + type OTG_V_TOTAL_MIN_SEL;\ + type OTG_V_TOTAL_MAX_SEL;\ + type OTG_FORCE_LOCK_ON_EVENT;\ + type OTG_SET_V_TOTAL_MIN_MASK_EN;\ + type OTG_SET_V_TOTAL_MIN_MASK;\ + type OTG_FORCE_COUNT_NOW_CLEAR;\ + type OTG_FORCE_COUNT_NOW_MODE;\ + type OTG_FORCE_COUNT_NOW_OCCURRED;\ + type OTG_TRIGA_SOURCE_SELECT;\ + type OTG_TRIGA_SOURCE_PIPE_SELECT;\ + type OTG_TRIGA_RISING_EDGE_DETECT_CNTL;\ + type OTG_TRIGA_FALLING_EDGE_DETECT_CNTL;\ + type OTG_STATIC_SCREEN_EVENT_MASK;\ + type OTG_STATIC_SCREEN_FRAME_COUNT;\ + type OTG_FRAME_COUNT;\ + type OTG_V_BLANK;\ + type OTG_V_ACTIVE_DISP;\ + type OTG_HORZ_COUNT;\ + type OTG_VERT_COUNT;\ + type OTG_VERT_COUNT_NOM;\ + type OTG_BLACK_COLOR_B_CB;\ + type OTG_BLACK_COLOR_G_Y;\ + type OTG_BLACK_COLOR_R_CR;\ + type OTG_TEST_PATTERN_INC0;\ + type OTG_TEST_PATTERN_INC1;\ + type OTG_TEST_PATTERN_VRES;\ + type OTG_TEST_PATTERN_HRES;\ + type OTG_TEST_PATTERN_RAMP0_OFFSET;\ + type OTG_TEST_PATTERN_EN;\ + type OTG_TEST_PATTERN_MODE;\ + type OTG_TEST_PATTERN_DYNAMIC_RANGE;\ + type OTG_TEST_PATTERN_COLOR_FORMAT;\ + type OTG_TEST_PATTERN_MASK;\ + type OTG_TEST_PATTERN_DATA;\ + type OTG_BUSY;\ + type OTG_CLOCK_EN;\ + type OTG_CLOCK_ON;\ + type OTG_CLOCK_GATE_DIS;\ + type OPTC_INPUT_CLK_EN;\ + type OPTC_INPUT_CLK_ON;\ + type OPTC_INPUT_CLK_GATE_DIS;\ + type OPTC_SRC_SEL;\ + type OPPBUF_ACTIVE_WIDTH;\ + type OPPBUF_3D_VACT_SPACE1_SIZE;\ + type VTG0_ENABLE;\ + type VTG0_FP2;\ + type VTG0_VCOUNT_INIT;\ + +struct dcn_tg_shift { + TG_REG_FIELD_LIST(uint8_t) +}; + +struct dcn_tg_mask { + TG_REG_FIELD_LIST(uint32_t) +}; + +struct dcn10_timing_generator { + struct timing_generator base; + + const struct dcn_tg_registers *tg_regs; + const struct dcn_tg_shift *tg_shift; + const struct dcn_tg_mask *tg_mask; + + enum controller_id controller_id; + + uint32_t max_h_total; + uint32_t max_v_total; + + uint32_t min_h_blank; + + uint32_t min_h_sync_width; + uint32_t min_v_sync_width; + uint32_t min_v_blank; + uint32_t min_v_blank_interlace; +}; + +void dcn10_timing_generator_init(struct dcn10_timing_generator *tg); + +void dcn10_timing_generator_set_drr(struct timing_generator *tg, + const struct drr_params *params); + +void dcn10_unlock(struct timing_generator *tg); +void dcn10_lock(struct timing_generator *tg); +#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c new file mode 100644 index 000000000000..3718fb5a3238 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -0,0 +1,1057 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "core_types.h" + +#include "include/grph_object_id.h" +#include "include/fixed31_32.h" +#include "include/logger_interface.h" + +#include "reg_helper.h" +#include "dcn10_transform.h" +#include "basics/conversion.h" + +#define NUM_PHASES 64 +#define HORZ_MAX_TAPS 8 +#define VERT_MAX_TAPS 8 + +#define BLACK_OFFSET_RGB_Y 0x0 +#define BLACK_OFFSET_CBCR 0x8000 + +#define REG(reg)\ + xfm->tf_regs->reg + +#define CTX \ + xfm->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + xfm->tf_shift->field_name, xfm->tf_mask->field_name + + +enum dcn10_coef_filter_type_sel { + SCL_COEF_LUMA_VERT_FILTER = 0, + SCL_COEF_LUMA_HORZ_FILTER = 1, + SCL_COEF_CHROMA_VERT_FILTER = 2, + SCL_COEF_CHROMA_HORZ_FILTER = 3, + SCL_COEF_ALPHA_VERT_FILTER = 4, + SCL_COEF_ALPHA_HORZ_FILTER = 5 +}; + +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + +enum dscl_autocal_mode { + AUTOCAL_MODE_OFF = 0, + + /* Autocal calculate the scaling ratio and initial phase and the + * DSCL_MODE_SEL must be set to 1 + */ + AUTOCAL_MODE_AUTOSCALE = 1, + /* Autocal perform auto centering without replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOCENTER = 2, + /* Autocal perform auto centering and auto replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOREPLICATE = 3 +}; + +enum dscl_mode_sel { + DSCL_MODE_SCALING_444_BYPASS = 0, + DSCL_MODE_SCALING_444_RGB_ENABLE = 1, + DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2, + DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3, + DSCL_MODE_SCALING_420_LUMA_BYPASS = 4, + DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5, + DSCL_MODE_DSCL_BYPASS = 6 +}; + +enum gamut_remap_select { + GAMUT_REMAP_BYPASS = 0, + GAMUT_REMAP_COEFF, + GAMUT_REMAP_COMA_COEFF, + GAMUT_REMAP_COMB_COEFF +}; + +static void transform_set_overscan( + struct dcn10_transform *xfm, + const struct scaler_data *data) +{ + uint32_t left = data->recout.x; + uint32_t top = data->recout.y; + + int right = data->h_active - data->recout.x - data->recout.width; + int bottom = data->v_active - data->recout.y - data->recout.height; + + if (right < 0) { + BREAK_TO_DEBUGGER(); + right = 0; + } + if (bottom < 0) { + BREAK_TO_DEBUGGER(); + bottom = 0; + } + + REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0, + EXT_OVERSCAN_LEFT, left, + EXT_OVERSCAN_RIGHT, right); + + REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0, + EXT_OVERSCAN_BOTTOM, bottom, + EXT_OVERSCAN_TOP, top); +} + +static void transform_set_otg_blank( + struct dcn10_transform *xfm, const struct scaler_data *data) +{ + uint32_t h_blank_start = data->h_active; + uint32_t h_blank_end = 0; + uint32_t v_blank_start = data->v_active; + uint32_t v_blank_end = 0; + + REG_SET_2(OTG_H_BLANK, 0, + OTG_H_BLANK_START, h_blank_start, + OTG_H_BLANK_END, h_blank_end); + + REG_SET_2(OTG_V_BLANK, 0, + OTG_V_BLANK_START, v_blank_start, + OTG_V_BLANK_END, v_blank_end); +} + +static enum dscl_mode_sel get_dscl_mode(const struct scaler_data *data) +{ + const long long one = dal_fixed31_32_one.value; + bool ycbcr = false; + bool format420 = false; + + if (data->format == PIXEL_FORMAT_FP16) + return DSCL_MODE_DSCL_BYPASS; + + if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && data->format <= PIXEL_FORMAT_VIDEO_END) + ycbcr = true; + + if (data->format == PIXEL_FORMAT_420BPP12 || + data->format == PIXEL_FORMAT_420BPP15) + format420 = true; + + if (data->ratios.horz.value == one + && data->ratios.vert.value == one + && data->ratios.horz_c.value == one + && data->ratios.vert_c.value == one) + return DSCL_MODE_SCALING_444_BYPASS; + + if (!format420) { + if (ycbcr) + return DSCL_MODE_SCALING_444_YCBCR_ENABLE; + else + return DSCL_MODE_SCALING_444_RGB_ENABLE; + } + if (data->ratios.horz.value == one && data->ratios.vert.value == one) + return DSCL_MODE_SCALING_420_LUMA_BYPASS; + if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one) + return DSCL_MODE_SCALING_420_CHROMA_BYPASS; + + return DSCL_MODE_SCALING_420_YCBCR_ENABLE; +} + +static int get_pixel_depth_val(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 0; /* 10 bpc */ + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 1; /* 8 bpc */ + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 2; /* 6 bpc */ + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 3; /* 12 bpc */ + else { + ASSERT(0); + return -1; /* Unsupported */ + } +} + +static void transform_set_lb( + struct dcn10_transform *xfm, + const struct line_buffer_params *lb_params, + enum lb_memory_config mem_size_config) +{ + uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; + REG_SET_7(LB_DATA_FORMAT, 0, + PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ + PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ + PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ + DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ + DITHER_EN, 0, /* Dithering enable: Disabled */ + INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ + ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + + REG_SET_2(LB_MEMORY_CTRL, 0, + MEMORY_CONFIG, mem_size_config, + LB_MAX_PARTITIONS, 63); +} + +static void transform_set_scaler_filter( + struct dcn10_transform *xfm, + uint32_t taps, + enum dcn10_coef_filter_type_sel filter_type, + const uint16_t *filter) +{ + const int tap_pairs = (taps + 1) / 2; + int phase; + int pair; + uint16_t odd_coef, even_coef; + + REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0, + SCL_COEF_RAM_TAP_PAIR_IDX, 0, + SCL_COEF_RAM_PHASE, 0, + SCL_COEF_RAM_FILTER_TYPE, filter_type); + + for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) { + for (pair = 0; pair < tap_pairs; pair++) { + even_coef = filter[phase * taps + 2 * pair]; + if ((pair * 2 + 1) < taps) + odd_coef = filter[phase * taps + 2 * pair + 1]; + else + odd_coef = 0; + + REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, + /* Even tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_EVEN_TAP_COEF, even_coef, + /* Write/read control for even coefficient */ + SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1, + /* Odd tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_ODD_TAP_COEF, odd_coef, + /* Write/read control for odd coefficient */ + SCL_COEF_RAM_ODD_TAP_COEF_EN, 1); + } + } + +} + +#if 0 +bool transform_set_pixel_storage_depth( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dcn10_transform *xfm110 = TO_DCN10_TRANSFORM(xfm); + bool ret = true; + uint32_t value; + enum dc_color_depth color_depth; + + value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + color_depth = COLOR_DEPTH_666; + set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_24BPP: + color_depth = COLOR_DEPTH_888; + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_30BPP: + color_depth = COLOR_DEPTH_101010; + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_36BPP: + color_depth = COLOR_DEPTH_121212; + set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + default: + ret = false; + break; + } + + if (ret == true) { + set_denormalization(xfm110, color_depth); + ret = program_bit_depth_reduction(xfm110, color_depth, + bit_depth_params); + + set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); + dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); + if (!(xfm110->lb_pixel_depth_supported & depth)) { + /* We should use unsupported capabilities + * unless it is required by w/a + */ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } + } + + return ret; +} +#endif + +static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +{ + if (taps == 8) + return get_filter_8tap_64p(ratio); + else if (taps == 7) + return get_filter_7tap_64p(ratio); + else if (taps == 6) + return get_filter_6tap_64p(ratio); + else if (taps == 5) + return get_filter_5tap_64p(ratio); + else if (taps == 4) + return get_filter_4tap_64p(ratio); + else if (taps == 3) + return get_filter_3tap_64p(ratio); + else if (taps == 2) + return filter_2tap_64p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static void transform_set_scl_filter( + struct dcn10_transform *xfm, + const struct scaler_data *scl_data, + bool chroma_coef_mode) +{ + bool h_2tap_hardcode_coef_en = false; + bool v_2tap_hardcode_coef_en = false; + bool h_2tap_sharp_en = false; + bool v_2tap_sharp_en = false; + uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz; + uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert; + bool coef_ram_current; + const uint16_t *filter_h = NULL; + const uint16_t *filter_v = NULL; + const uint16_t *filter_h_c = NULL; + const uint16_t *filter_v_c = NULL; + + h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 + && scl_data->taps.h_taps_c < 3 + && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); + v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 + && scl_data->taps.v_taps_c < 3 + && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); + + h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; + v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; + + REG_UPDATE_6(DSCL_2TAP_CONTROL, + SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en, + SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en, + SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor, + SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en, + SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en, + SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor); + + if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { + bool filter_updated = false; + + filter_h = get_filter_coeffs_64p( + scl_data->taps.h_taps, scl_data->ratios.horz); + filter_v = get_filter_coeffs_64p( + scl_data->taps.v_taps, scl_data->ratios.vert); + + filter_updated = (filter_h && (filter_h != xfm->filter_h)) + || (filter_v && (filter_v != xfm->filter_v)); + + if (chroma_coef_mode) { + filter_h_c = get_filter_coeffs_64p( + scl_data->taps.h_taps_c, scl_data->ratios.horz_c); + filter_v_c = get_filter_coeffs_64p( + scl_data->taps.v_taps_c, scl_data->ratios.vert_c); + filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) + || (filter_v_c && (filter_v_c != xfm->filter_v_c)); + } + + if (filter_updated) { + uint32_t scl_mode = REG_READ(SCL_MODE); + + if (!h_2tap_hardcode_coef_en && filter_h) { + transform_set_scaler_filter( + xfm, scl_data->taps.h_taps, + SCL_COEF_LUMA_HORZ_FILTER, filter_h); + } + xfm->filter_h = filter_h; + if (!v_2tap_hardcode_coef_en && filter_v) { + transform_set_scaler_filter( + xfm, scl_data->taps.v_taps, + SCL_COEF_LUMA_VERT_FILTER, filter_v); + } + xfm->filter_v = filter_v; + if (chroma_coef_mode) { + if (!h_2tap_hardcode_coef_en && filter_h_c) { + transform_set_scaler_filter( + xfm, scl_data->taps.h_taps_c, + SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); + } + if (!v_2tap_hardcode_coef_en && filter_v_c) { + transform_set_scaler_filter( + xfm, scl_data->taps.v_taps_c, + SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); + } + } + xfm->filter_h_c = filter_h_c; + xfm->filter_v_c = filter_v_c; + + coef_ram_current = get_reg_field_value_ex( + scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, + xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); + + /* Swap coefficient RAM and set chroma coefficient mode */ + REG_SET_2(SCL_MODE, scl_mode, + SCL_COEF_RAM_SELECT, !coef_ram_current, + SCL_CHROMA_COEF_MODE, chroma_coef_mode); + } + } +} + +static void transform_set_viewport( + struct dcn10_transform *xfm, + const struct rect *viewport, + const struct rect *viewport_c) +{ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, + PRI_VIEWPORT_WIDTH, viewport->width, + PRI_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, + PRI_VIEWPORT_X_START, viewport->x, + PRI_VIEWPORT_Y_START, viewport->y); + + /*for stereo*/ + REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, + SEC_VIEWPORT_WIDTH, viewport->width, + SEC_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, + SEC_VIEWPORT_X_START, viewport->x, + SEC_VIEWPORT_Y_START, viewport->y); + + /* DC supports NV12 only at the moment */ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, + PRI_VIEWPORT_WIDTH_C, viewport_c->width, + PRI_VIEWPORT_HEIGHT_C, viewport_c->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, + PRI_VIEWPORT_X_START_C, viewport_c->x, + PRI_VIEWPORT_Y_START_C, viewport_c->y); +} + +static int get_lb_depth_bpc(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 10; + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 8; + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 6; + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 12; + else { + BREAK_TO_DEBUGGER(); + return -1; /* Unsupported */ + } +} + +static void calc_lb_num_partitions( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c) +{ + int line_size = scl_data->viewport.width < scl_data->recout.width ? + scl_data->viewport.width : scl_data->recout.width; + int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? + scl_data->viewport_c.width : scl_data->recout.width; + int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); + int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ + int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; + + if (lb_config == LB_MEMORY_CONFIG_1) { + lb_memory_size = 816; + lb_memory_size_c = 816; + lb_memory_size_a = 984; + } else if (lb_config == LB_MEMORY_CONFIG_2) { + lb_memory_size = 1088; + lb_memory_size_c = 1088; + lb_memory_size_a = 1312; + } else if (lb_config == LB_MEMORY_CONFIG_3) { + lb_memory_size = 816 + 1088 + 848 + 848 + 848; + lb_memory_size_c = 816 + 1088; + lb_memory_size_a = 984 + 1312 + 456; + } else { + lb_memory_size = 816 + 1088 + 848; + lb_memory_size_c = 816 + 1088 + 848; + lb_memory_size_a = 984 + 1312 + 456; + } + *num_part_y = lb_memory_size / memory_line_size_y; + *num_part_c = lb_memory_size_c / memory_line_size_c; + num_partitions_a = lb_memory_size_a / memory_line_size_a; + + if (scl_data->lb_params.alpha_en + && (num_partitions_a < *num_part_y)) + *num_part_y = num_partitions_a; + + if (*num_part_y > 64) + *num_part_y = 64; + if (*num_part_c > 64) + *num_part_c = 64; + +} + +static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +{ + if (ceil_vratio > 2) + return vtaps <= (num_partitions - ceil_vratio + 2); + else + return vtaps <= num_partitions; +} + +/*find first match configuration which meets the min required lb size*/ +static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) +{ + int num_part_y, num_part_c; + int vtaps = scl_data->taps.v_taps; + int vtaps_c = scl_data->taps.v_taps_c; + int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); + int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_1; + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_2; + + if (scl_data->format == PIXEL_FORMAT_420BPP12 + || scl_data->format == PIXEL_FORMAT_420BPP15) { + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_3; + } + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); + + /*Ensure we can support the requested number of vtaps*/ + ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); + + return LB_MEMORY_CONFIG_0; +} + +void transform_set_scaler_auto_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode(scl_data); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + transform_set_overscan(xfm, scl_data); + + transform_set_otg_blank(xfm, scl_data); + + REG_UPDATE(SCL_MODE, DSCL_MODE, get_dscl_mode(scl_data)); + + transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + + lb_config = find_lb_memory_config(scl_data); + transform_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* TODO: v_min */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + transform_set_scl_filter(xfm, scl_data, ycbcr); +} + +/* Program gamut remap in bypass mode */ +void transform_set_gamut_remap_bypass(struct dcn10_transform *xfm) +{ + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + /* Gamut remap in bypass */ +} + +static void transform_set_recout( + struct dcn10_transform *xfm, const struct rect *recout) +{ + REG_SET_2(RECOUT_START, 0, + /* First pixel of RECOUT */ + RECOUT_START_X, recout->x, + /* First line of RECOUT */ + RECOUT_START_Y, recout->y); + + REG_SET_2(RECOUT_SIZE, 0, + /* Number of RECOUT horizontal pixels */ + RECOUT_WIDTH, recout->width, + /* Number of RECOUT vertical lines */ + RECOUT_HEIGHT, recout->height + - xfm->base.ctx->dc->debug.surface_visual_confirm * 2); +} + +static void transform_set_manual_ratio_init( + struct dcn10_transform *xfm, const struct scaler_data *data) +{ + uint32_t init_frac = 0; + uint32_t init_int = 0; + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, + SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, + SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5); + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0, + SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0, + SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5); + + /* + * 0.24 format for fraction, first five bits zeroed + */ + init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5; + init_int = dal_fixed31_32_floor(data->inits.h); + REG_SET_2(SCL_HORZ_FILTER_INIT, 0, + SCL_H_INIT_FRAC, init_frac, + SCL_H_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.h_c); + REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0, + SCL_H_INIT_FRAC_C, init_frac, + SCL_H_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5; + init_int = dal_fixed31_32_floor(data->inits.v); + REG_SET_2(SCL_VERT_FILTER_INIT, 0, + SCL_V_INIT_FRAC, init_frac, + SCL_V_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, + SCL_V_INIT_FRAC_BOT, init_frac, + SCL_V_INIT_INT_BOT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c); + REG_SET_2(SCL_VERT_FILTER_INIT_C, 0, + SCL_V_INIT_FRAC_C, init_frac, + SCL_V_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, + SCL_V_INIT_FRAC_BOT_C, init_frac, + SCL_V_INIT_INT_BOT_C, init_int); +} + +/* Main function to program scaler and line buffer in manual scaling mode */ +static void transform_set_scaler_manual_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode(scl_data); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + /* Recout */ + transform_set_recout(xfm, &scl_data->recout); + + /* MPC Size */ + REG_SET_2(MPC_SIZE, 0, + /* Number of horizontal pixels of MPC */ + MPC_WIDTH, scl_data->h_active, + /* Number of vertical lines of MPC */ + MPC_HEIGHT, scl_data->v_active); + + /* SCL mode */ + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); + + /* Viewport */ + transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + /* LB */ + lb_config = find_lb_memory_config(scl_data); + transform_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* Autocal off */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_OFF, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + /* Manually calculate scale ratio and init values */ + transform_set_manual_ratio_init(xfm, scl_data); + + /* HTaps/VTaps */ + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + transform_set_scl_filter(xfm, scl_data, ycbcr); +} + +#define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) + + +static bool transform_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps) +{ + uint32_t pixel_width; + + if (scl_data->viewport.width > scl_data->recout.width) + pixel_width = scl_data->recout.width; + else + pixel_width = scl_data->viewport.width; + + /* TODO: add lb check */ + + /* No support for programming ratio of 4, drop to 3.99999.. */ + if (scl_data->ratios.horz.value == (4ll << 32)) + scl_data->ratios.horz.value--; + if (scl_data->ratios.vert.value == (4ll << 32)) + scl_data->ratios.vert.value--; + if (scl_data->ratios.horz_c.value == (4ll << 32)) + scl_data->ratios.horz_c.value--; + if (scl_data->ratios.vert_c.value == (4ll << 32)) + scl_data->ratios.vert_c.value--; + + /* Set default taps if none are provided */ + if (in_taps->h_taps == 0) + scl_data->taps.h_taps = 4; + else + scl_data->taps.h_taps = in_taps->h_taps; + if (in_taps->v_taps == 0) + scl_data->taps.v_taps = 4; + else + scl_data->taps.v_taps = in_taps->v_taps; + if (in_taps->v_taps_c == 0) + scl_data->taps.v_taps_c = 2; + else + scl_data->taps.v_taps_c = in_taps->v_taps_c; + if (in_taps->h_taps_c == 0) + scl_data->taps.h_taps_c = 2; + /* Only 1 and even h_taps_c are supported by hw */ + else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1) + scl_data->taps.h_taps_c = in_taps->h_taps_c - 1; + else + scl_data->taps.h_taps_c = in_taps->h_taps_c; + + if (IDENTITY_RATIO(scl_data->ratios.horz)) + scl_data->taps.h_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert)) + scl_data->taps.v_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.horz_c)) + scl_data->taps.h_taps_c = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert_c)) + scl_data->taps.v_taps_c = 1; + + return true; +} + +static void transform_reset(struct transform *xfm_base) +{ + struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + + xfm->filter_h_c = NULL; + xfm->filter_v_c = NULL; + xfm->filter_h = NULL; + xfm->filter_v = NULL; + + /* set boundary mode to 0 */ + REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); +} + +static void program_gamut_remap( + struct dcn10_transform *xfm, + const uint16_t *regval, + enum gamut_remap_select select) +{ + uint16_t selection = 0; + + if (regval == NULL || select == GAMUT_REMAP_BYPASS) { + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + return; + } + switch (select) { + case GAMUT_REMAP_COEFF: + selection = 1; + break; + case GAMUT_REMAP_COMA_COEFF: + selection = 2; + break; + case GAMUT_REMAP_COMB_COEFF: + selection = 3; + break; + default: + break; + } + + + if (select == GAMUT_REMAP_COEFF) { + + REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, + CM_GAMUT_REMAP_C11, regval[0], + CM_GAMUT_REMAP_C12, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, + CM_GAMUT_REMAP_C13, regval[0], + CM_GAMUT_REMAP_C14, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, + CM_GAMUT_REMAP_C21, regval[0], + CM_GAMUT_REMAP_C22, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, + CM_GAMUT_REMAP_C23, regval[0], + CM_GAMUT_REMAP_C24, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, + CM_GAMUT_REMAP_C31, regval[0], + CM_GAMUT_REMAP_C32, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, + CM_GAMUT_REMAP_C33, regval[0], + CM_GAMUT_REMAP_C34, regval[1]); + + } else if (select == GAMUT_REMAP_COMA_COEFF) { + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + + } else { + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, regval[0], + CM_COMB_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, regval[0], + CM_COMB_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, regval[0], + CM_COMB_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, regval[0], + CM_COMB_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, regval[0], + CM_COMB_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, regval[0], + CM_COMB_C34, regval[1]); + } + + REG_SET( + CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, selection); + +} + +static void dcn_transform_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + struct dcn10_transform *dcn_xfm = TO_DCN10_TRANSFORM(xfm); + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + /* Bypass if type is bypass or hw */ + program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); + else { + struct fixed31_32 arr_matrix[12]; + uint16_t arr_reg_val[12]; + + arr_matrix[0] = adjust->temperature_matrix[0]; + arr_matrix[1] = adjust->temperature_matrix[1]; + arr_matrix[2] = adjust->temperature_matrix[2]; + arr_matrix[3] = dal_fixed31_32_zero; + + arr_matrix[4] = adjust->temperature_matrix[3]; + arr_matrix[5] = adjust->temperature_matrix[4]; + arr_matrix[6] = adjust->temperature_matrix[5]; + arr_matrix[7] = dal_fixed31_32_zero; + + arr_matrix[8] = adjust->temperature_matrix[6]; + arr_matrix[9] = adjust->temperature_matrix[7]; + arr_matrix[10] = adjust->temperature_matrix[8]; + arr_matrix[11] = dal_fixed31_32_zero; + + convert_float_matrix( + arr_reg_val, arr_matrix, 12); + + program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); + } +} + +static struct transform_funcs dcn10_transform_funcs = { + + .transform_reset = transform_reset, + .transform_set_scaler = transform_set_scaler_manual_scale, + .transform_get_optimal_number_of_taps = + transform_get_optimal_number_of_taps, + .transform_set_gamut_remap = dcn_transform_set_gamut_remap +}; + +/*****************************************/ +/* Constructor, Destructor */ +/*****************************************/ + +bool dcn10_transform_construct( + struct dcn10_transform *xfm, + struct dc_context *ctx, + const struct dcn_transform_registers *tf_regs, + const struct dcn_transform_shift *tf_shift, + const struct dcn_transform_mask *tf_mask) +{ + xfm->base.ctx = ctx; + + xfm->base.funcs = &dcn10_transform_funcs; + + xfm->tf_regs = tf_regs; + xfm->tf_shift = tf_shift; + xfm->tf_mask = tf_mask; + + xfm->lb_pixel_depth_supported = + LB_PIXEL_DEPTH_18BPP | + LB_PIXEL_DEPTH_24BPP | + LB_PIXEL_DEPTH_30BPP; + + xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; + xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h new file mode 100644 index 000000000000..7c0089d4293b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h @@ -0,0 +1,416 @@ +/* Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_TRANSFORM_DCN10_H__ +#define __DAL_TRANSFORM_DCN10_H__ + +#include "transform.h" + +#define TO_DCN10_TRANSFORM(transform)\ + container_of(transform, struct dcn10_transform, base) + +/* TODO: Use correct number of taps. Using polaris values for now */ +#define LB_TOTAL_NUMBER_OF_ENTRIES 5124 +#define LB_BITS_PER_ENTRY 144 + +#define TF_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define TF_REG_LIST_DCN(id) \ + SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ + SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI(OTG_H_BLANK, DSCL, id), \ + SRI(OTG_V_BLANK, DSCL, id), \ + SRI(SCL_MODE, DSCL, id), \ + SRI(LB_DATA_FORMAT, DSCL, id), \ + SRI(LB_MEMORY_CTRL, DSCL, id), \ + SRI(DSCL_AUTOCAL, DSCL, id), \ + SRI(SCL_BLACK_OFFSET, DSCL, id), \ + SRI(DSCL_CONTROL, DSCL, id), \ + SRI(SCL_TAP_CONTROL, DSCL, id), \ + SRI(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ + SRI(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ + SRI(DSCL_2TAP_CONTROL, DSCL, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ + SRI(CM_GAMUT_REMAP_CONTROL, CM, id), \ + SRI(MPC_SIZE, DSCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI(SCL_HORZ_FILTER_INIT, DSCL, id), \ + SRI(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_BOT, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ + SRI(RECOUT_START, DSCL, id), \ + SRI(RECOUT_SIZE, DSCL, id), \ + SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ + SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ + SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ + SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ + SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ + SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ + SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ + SRI(CM_COMA_C11_C12, CM, id),\ + SRI(CM_COMA_C13_C14, CM, id),\ + SRI(CM_COMA_C21_C22, CM, id),\ + SRI(CM_COMA_C23_C24, CM, id),\ + SRI(CM_COMA_C31_C32, CM, id),\ + SRI(CM_COMA_C33_C34, CM, id),\ + SRI(CM_COMB_C11_C12, CM, id),\ + SRI(CM_COMB_C13_C14, CM, id),\ + SRI(CM_COMB_C21_C22, CM, id),\ + SRI(CM_COMB_C23_C24, CM, id),\ + SRI(CM_COMB_C31_C32, CM, id),\ + SRI(CM_COMB_C33_C34, CM, id) + + + +#define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, ALPHA_EN, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\ + TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_RGB_Y, mask_sh),\ + TF_SF(DSCL0_SCL_BLACK_OFFSET, SCL_BLACK_OFFSET_CBCR, mask_sh),\ + TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ + TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ + TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh),\ + TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh),\ + TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh),\ + TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh),\ + TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh),\ + TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh),\ + TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh),\ + TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh),\ + TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh),\ + TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh),\ + TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh),\ + TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh),\ + TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh),\ + TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh),\ + TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh),\ + TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh),\ + TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh),\ + TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh),\ + TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh),\ + TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh),\ + TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh),\ + TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh),\ + TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh),\ + TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh) + + +#define TF_REG_FIELD_LIST(type) \ + type EXT_OVERSCAN_LEFT; \ + type EXT_OVERSCAN_RIGHT; \ + type EXT_OVERSCAN_BOTTOM; \ + type EXT_OVERSCAN_TOP; \ + type OTG_H_BLANK_START; \ + type OTG_H_BLANK_END; \ + type OTG_V_BLANK_START; \ + type OTG_V_BLANK_END; \ + type PIXEL_DEPTH; \ + type PIXEL_EXPAN_MODE; \ + type PIXEL_REDUCE_MODE; \ + type DYNAMIC_PIXEL_DEPTH; \ + type DITHER_EN; \ + type INTERLEAVE_EN; \ + type ALPHA_EN; \ + type MEMORY_CONFIG; \ + type LB_MAX_PARTITIONS; \ + type AUTOCAL_MODE; \ + type AUTOCAL_NUM_PIPE; \ + type AUTOCAL_PIPE_ID; \ + type SCL_BLACK_OFFSET_RGB_Y; \ + type SCL_BLACK_OFFSET_CBCR; \ + type SCL_BOUNDARY_MODE; \ + type SCL_V_NUM_TAPS; \ + type SCL_H_NUM_TAPS; \ + type SCL_V_NUM_TAPS_C; \ + type SCL_H_NUM_TAPS_C; \ + type SCL_COEF_RAM_TAP_PAIR_IDX; \ + type SCL_COEF_RAM_PHASE; \ + type SCL_COEF_RAM_FILTER_TYPE; \ + type SCL_COEF_RAM_EVEN_TAP_COEF; \ + type SCL_COEF_RAM_EVEN_TAP_COEF_EN; \ + type SCL_COEF_RAM_ODD_TAP_COEF; \ + type SCL_COEF_RAM_ODD_TAP_COEF_EN; \ + type SCL_H_2TAP_HARDCODE_COEF_EN; \ + type SCL_H_2TAP_SHARP_EN; \ + type SCL_H_2TAP_SHARP_FACTOR; \ + type SCL_V_2TAP_HARDCODE_COEF_EN; \ + type SCL_V_2TAP_SHARP_EN; \ + type SCL_V_2TAP_SHARP_FACTOR; \ + type SCL_COEF_RAM_SELECT; \ + type PRI_VIEWPORT_WIDTH; \ + type PRI_VIEWPORT_HEIGHT; \ + type PRI_VIEWPORT_X_START; \ + type PRI_VIEWPORT_Y_START; \ + type SEC_VIEWPORT_WIDTH; \ + type SEC_VIEWPORT_HEIGHT; \ + type SEC_VIEWPORT_X_START; \ + type SEC_VIEWPORT_Y_START; \ + type PRI_VIEWPORT_WIDTH_C; \ + type PRI_VIEWPORT_HEIGHT_C; \ + type PRI_VIEWPORT_X_START_C; \ + type PRI_VIEWPORT_Y_START_C; \ + type DSCL_MODE; \ + type RECOUT_START_X; \ + type RECOUT_START_Y; \ + type RECOUT_WIDTH; \ + type RECOUT_HEIGHT; \ + type MPC_WIDTH; \ + type MPC_HEIGHT; \ + type SCL_H_SCALE_RATIO; \ + type SCL_V_SCALE_RATIO; \ + type SCL_H_SCALE_RATIO_C; \ + type SCL_V_SCALE_RATIO_C; \ + type SCL_H_INIT_FRAC; \ + type SCL_H_INIT_INT; \ + type SCL_H_INIT_FRAC_C; \ + type SCL_H_INIT_INT_C; \ + type SCL_V_INIT_FRAC; \ + type SCL_V_INIT_INT; \ + type SCL_V_INIT_FRAC_BOT; \ + type SCL_V_INIT_INT_BOT; \ + type SCL_V_INIT_FRAC_C; \ + type SCL_V_INIT_INT_C; \ + type SCL_V_INIT_FRAC_BOT_C; \ + type SCL_V_INIT_INT_BOT_C; \ + type SCL_CHROMA_COEF_MODE; \ + type SCL_COEF_RAM_SELECT_CURRENT; \ + type CM_GAMUT_REMAP_MODE; \ + type CM_GAMUT_REMAP_C11; \ + type CM_GAMUT_REMAP_C12; \ + type CM_GAMUT_REMAP_C13; \ + type CM_GAMUT_REMAP_C14; \ + type CM_GAMUT_REMAP_C21; \ + type CM_GAMUT_REMAP_C22; \ + type CM_GAMUT_REMAP_C23; \ + type CM_GAMUT_REMAP_C24; \ + type CM_GAMUT_REMAP_C31; \ + type CM_GAMUT_REMAP_C32; \ + type CM_GAMUT_REMAP_C33; \ + type CM_GAMUT_REMAP_C34; \ + type CM_COMA_C11; \ + type CM_COMA_C12; \ + type CM_COMA_C13; \ + type CM_COMA_C14; \ + type CM_COMA_C21; \ + type CM_COMA_C22; \ + type CM_COMA_C23; \ + type CM_COMA_C24; \ + type CM_COMA_C31; \ + type CM_COMA_C32; \ + type CM_COMA_C33; \ + type CM_COMA_C34; \ + type CM_COMB_C11; \ + type CM_COMB_C12; \ + type CM_COMB_C13; \ + type CM_COMB_C14; \ + type CM_COMB_C21; \ + type CM_COMB_C22; \ + type CM_COMB_C23; \ + type CM_COMB_C24; \ + type CM_COMB_C31; \ + type CM_COMB_C32; \ + type CM_COMB_C33; \ + type CM_COMB_C34 + +struct dcn_transform_shift { + TF_REG_FIELD_LIST(uint8_t); +}; + +struct dcn_transform_mask { + TF_REG_FIELD_LIST(uint32_t); +}; + +struct dcn_transform_registers { + uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; + uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; + uint32_t OTG_H_BLANK; + uint32_t OTG_V_BLANK; + uint32_t SCL_MODE; + uint32_t LB_DATA_FORMAT; + uint32_t LB_MEMORY_CTRL; + uint32_t DSCL_AUTOCAL; + uint32_t SCL_BLACK_OFFSET; + uint32_t DSCL_CONTROL; + uint32_t SCL_TAP_CONTROL; + uint32_t SCL_COEF_RAM_TAP_SELECT; + uint32_t SCL_COEF_RAM_TAP_DATA; + uint32_t DSCL_2TAP_CONTROL; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; + uint32_t DCSURF_PRI_VIEWPORT_START; + uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; + uint32_t DCSURF_SEC_VIEWPORT_START; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; + uint32_t DCSURF_PRI_VIEWPORT_START_C; + uint32_t MPC_SIZE; + uint32_t SCL_HORZ_FILTER_SCALE_RATIO; + uint32_t SCL_VERT_FILTER_SCALE_RATIO; + uint32_t SCL_HORZ_FILTER_SCALE_RATIO_C; + uint32_t SCL_VERT_FILTER_SCALE_RATIO_C; + uint32_t SCL_HORZ_FILTER_INIT; + uint32_t SCL_HORZ_FILTER_INIT_C; + uint32_t SCL_VERT_FILTER_INIT; + uint32_t SCL_VERT_FILTER_INIT_BOT; + uint32_t SCL_VERT_FILTER_INIT_C; + uint32_t SCL_VERT_FILTER_INIT_BOT_C; + uint32_t RECOUT_START; + uint32_t RECOUT_SIZE; + uint32_t CM_GAMUT_REMAP_CONTROL; + uint32_t CM_GAMUT_REMAP_C11_C12; + uint32_t CM_GAMUT_REMAP_C13_C14; + uint32_t CM_GAMUT_REMAP_C21_C22; + uint32_t CM_GAMUT_REMAP_C23_C24; + uint32_t CM_GAMUT_REMAP_C31_C32; + uint32_t CM_GAMUT_REMAP_C33_C34; + uint32_t CM_COMA_C11_C12; + uint32_t CM_COMA_C13_C14; + uint32_t CM_COMA_C21_C22; + uint32_t CM_COMA_C23_C24; + uint32_t CM_COMA_C31_C32; + uint32_t CM_COMA_C33_C34; + uint32_t CM_COMB_C11_C12; + uint32_t CM_COMB_C13_C14; + uint32_t CM_COMB_C21_C22; + uint32_t CM_COMB_C23_C24; + uint32_t CM_COMB_C31_C32; + uint32_t CM_COMB_C33_C34; +}; + +struct dcn10_transform { + struct transform base; + + const struct dcn_transform_registers *tf_regs; + const struct dcn_transform_shift *tf_shift; + const struct dcn_transform_mask *tf_mask; + + const uint16_t *filter_v; + const uint16_t *filter_h; + const uint16_t *filter_v_c; + const uint16_t *filter_h_c; + int lb_pixel_depth_supported; + int lb_memory_size; + int lb_bits_per_entry; +}; + +bool dcn10_transform_construct(struct dcn10_transform *xfm110, + struct dc_context *ctx, + const struct dcn_transform_registers *tf_regs, + const struct dcn_transform_shift *tf_shift, + const struct dcn_transform_mask *tf_mask); +#endif -- GitLab From 061bfa06a42a9f6cd192bae61a4bf0e746eccb39 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:20:38 -0400 Subject: [PATCH 0426/2898] drm/amdgpu/display: Add dml support for DCN Display mode lib handles clock, watermark, and bandwidth calculations for DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 22 + .../gpu/drm/amd/display/dc/dml/dc_features.h | 557 ++++ .../amd/display/dc/dml/display_mode_enums.h | 111 + .../drm/amd/display/dc/dml/display_mode_lib.c | 147 ++ .../drm/amd/display/dc/dml/display_mode_lib.h | 52 + .../amd/display/dc/dml/display_mode_structs.h | 429 +++ .../amd/display/dc/dml/display_mode_support.c | 2326 +++++++++++++++++ .../amd/display/dc/dml/display_mode_support.h | 199 ++ .../amd/display/dc/dml/display_pipe_clocks.c | 367 +++ .../amd/display/dc/dml/display_pipe_clocks.h | 41 + .../amd/display/dc/dml/display_rq_dlg_calc.c | 2254 ++++++++++++++++ .../amd/display/dc/dml/display_rq_dlg_calc.h | 139 + .../display/dc/dml/display_rq_dlg_helpers.c | 320 +++ .../display/dc/dml/display_rq_dlg_helpers.h | 66 + .../amd/display/dc/dml/display_watermark.c | 1281 +++++++++ .../amd/display/dc/dml/display_watermark.h | 98 + .../drm/amd/display/dc/dml/dml_common_defs.c | 148 ++ .../drm/amd/display/dc/dml/dml_common_defs.h | 51 + .../drm/amd/display/dc/dml/soc_bounding_box.c | 73 + .../drm/amd/display/dc/dml/soc_bounding_box.h | 36 + 20 files changed, 8717 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dc_features.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile new file mode 100644 index 000000000000..9d7791d00e97 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for the 'utils' sub-component of DAL. +# It provides the general basic services required by other DAL +# subcomponents. + +CFLAGS_display_mode_lib.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_pipe_clocks.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 + + +DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ + display_rq_dlg_helpers.o display_watermark.o \ + soc_bounding_box.o dml_common_defs.o display_mode_support.o + +AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DML) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h new file mode 100644 index 000000000000..745c04cb764a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h @@ -0,0 +1,557 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DC_FEATURES_H__ +#define __DC_FEATURES_H__ + +#define DC__PRESENT 1 +#define DC__PRESENT__1 1 +#define DC__NUM_DPP 4 +#define DC__NUM_DPP__4 1 +#define DC__NUM_DPP__0_PRESENT 1 +#define DC__NUM_DPP__1_PRESENT 1 +#define DC__NUM_DPP__2_PRESENT 1 +#define DC__NUM_DPP__3_PRESENT 1 +#define DC__NUM_DPP__MAX 8 +#define DC__NUM_DPP__MAX__8 1 +#define DC__PIPE_10BIT 0 +#define DC__PIPE_10BIT__0 1 +#define DC__PIPE_10BIT__MAX 1 +#define DC__PIPE_10BIT__MAX__1 1 +#define DC__NUM_OPP 4 +#define DC__NUM_OPP__4 1 +#define DC__NUM_OPP__0_PRESENT 1 +#define DC__NUM_OPP__1_PRESENT 1 +#define DC__NUM_OPP__2_PRESENT 1 +#define DC__NUM_OPP__3_PRESENT 1 +#define DC__NUM_OPP__MAX 6 +#define DC__NUM_OPP__MAX__6 1 +#define DC__NUM_DSC 0 +#define DC__NUM_DSC__0 1 +#define DC__NUM_DSC__MAX 6 +#define DC__NUM_DSC__MAX__6 1 +#define DC__NUM_ABM 1 +#define DC__NUM_ABM__1 1 +#define DC__NUM_ABM__0_PRESENT 1 +#define DC__NUM_ABM__MAX 2 +#define DC__NUM_ABM__MAX__2 1 +#define DC__ODM_PRESENT 0 +#define DC__ODM_PRESENT__0 1 +#define DC__NUM_OTG 4 +#define DC__NUM_OTG__4 1 +#define DC__NUM_OTG__0_PRESENT 1 +#define DC__NUM_OTG__1_PRESENT 1 +#define DC__NUM_OTG__2_PRESENT 1 +#define DC__NUM_OTG__3_PRESENT 1 +#define DC__NUM_OTG__MAX 6 +#define DC__NUM_OTG__MAX__6 1 +#define DC__NUM_DWB 2 +#define DC__NUM_DWB__2 1 +#define DC__NUM_DWB__0_PRESENT 1 +#define DC__NUM_DWB__1_PRESENT 1 +#define DC__NUM_DWB__MAX 2 +#define DC__NUM_DWB__MAX__2 1 +#define DC__NUM_DIG 4 +#define DC__NUM_DIG__4 1 +#define DC__NUM_DIG__0_PRESENT 1 +#define DC__NUM_DIG__1_PRESENT 1 +#define DC__NUM_DIG__2_PRESENT 1 +#define DC__NUM_DIG__3_PRESENT 1 +#define DC__NUM_DIG__MAX 6 +#define DC__NUM_DIG__MAX__6 1 +#define DC__NUM_AUX 4 +#define DC__NUM_AUX__4 1 +#define DC__NUM_AUX__0_PRESENT 1 +#define DC__NUM_AUX__1_PRESENT 1 +#define DC__NUM_AUX__2_PRESENT 1 +#define DC__NUM_AUX__3_PRESENT 1 +#define DC__NUM_AUX__MAX 6 +#define DC__NUM_AUX__MAX__6 1 +#define DC__NUM_AUDIO_STREAMS 4 +#define DC__NUM_AUDIO_STREAMS__4 1 +#define DC__NUM_AUDIO_STREAMS__0_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__1_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__2_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__3_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__MAX 8 +#define DC__NUM_AUDIO_STREAMS__MAX__8 1 +#define DC__NUM_AUDIO_ENDPOINTS 6 +#define DC__NUM_AUDIO_ENDPOINTS__6 1 +#define DC__NUM_AUDIO_ENDPOINTS__0_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__1_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__2_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__3_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__4_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__5_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__MAX 8 +#define DC__NUM_AUDIO_ENDPOINTS__MAX__8 1 +#define DC__NUM_AUDIO_INPUT_STREAMS 0 +#define DC__NUM_AUDIO_INPUT_STREAMS__0 1 +#define DC__NUM_AUDIO_INPUT_STREAMS__MAX 8 +#define DC__NUM_AUDIO_INPUT_STREAMS__MAX__8 1 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS 0 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__0 1 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__MAX 8 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__MAX__8 1 +#define DC__NUM_CURSOR 1 +#define DC__NUM_CURSOR__1 1 +#define DC__NUM_CURSOR__0_PRESENT 1 +#define DC__NUM_CURSOR__MAX 2 +#define DC__NUM_CURSOR__MAX__2 1 +#define DC__DIGITAL_BYPASS_PRESENT 0 +#define DC__DIGITAL_BYPASS_PRESENT__0 1 +#define DC__HCID_HWMAJVER 1 +#define DC__HCID_HWMAJVER__1 1 +#define DC__HCID_HWMINVER 0 +#define DC__HCID_HWMINVER__0 1 +#define DC__HCID_HWREV 0 +#define DC__HCID_HWREV__0 1 +#define DC__ROMSTRAP_PRESENT 0 +#define DC__ROMSTRAP_PRESENT__0 1 +#define DC__NUM_RBBMIF_DECODES 30 +#define DC__NUM_RBBMIF_DECODES__30 1 +#define DC__NUM_DBG_REGS 36 +#define DC__NUM_DBG_REGS__36 1 +#define DC__NUM_PIPES_UNDERLAY 0 +#define DC__NUM_PIPES_UNDERLAY__0 1 +#define DC__NUM_PIPES_UNDERLAY__MAX 2 +#define DC__NUM_PIPES_UNDERLAY__MAX__2 1 +#define DC__NUM_VCE_ENGINE 1 +#define DC__NUM_VCE_ENGINE__1 1 +#define DC__NUM_VCE_ENGINE__0_PRESENT 1 +#define DC__NUM_VCE_ENGINE__MAX 2 +#define DC__NUM_VCE_ENGINE__MAX__2 1 +#define DC__OTG_EXTERNAL_SYNC_PRESENT 0 +#define DC__OTG_EXTERNAL_SYNC_PRESENT__0 1 +#define DC__OTG_CRC_PRESENT 1 +#define DC__OTG_CRC_PRESENT__1 1 +#define DC__VIP_PRESENT 0 +#define DC__VIP_PRESENT__0 1 +#define DC__DTMTEST_PRESENT 0 +#define DC__DTMTEST_PRESENT__0 1 +#define DC__POWER_GATE_PRESENT 1 +#define DC__POWER_GATE_PRESENT__1 1 +#define DC__MEM_PG 1 +#define DC__MEM_PG__1 1 +#define DC__FMT_SRC_SEL_PRESENT 0 +#define DC__FMT_SRC_SEL_PRESENT__0 1 +#define DC__DIG_FEATURES__HDMI_PRESENT 1 +#define DC__DIG_FEATURES__HDMI_PRESENT__1 1 +#define DC__DIG_FEATURES__DP_PRESENT 1 +#define DC__DIG_FEATURES__DP_PRESENT__1 1 +#define DC__DIG_FEATURES__DP_MST_PRESENT 1 +#define DC__DIG_FEATURES__DP_MST_PRESENT__1 1 +#define DC__DIG_LP_FEATURES__HDMI_PRESENT 0 +#define DC__DIG_LP_FEATURES__HDMI_PRESENT__0 1 +#define DC__DIG_LP_FEATURES__DP_PRESENT 1 +#define DC__DIG_LP_FEATURES__DP_PRESENT__1 1 +#define DC__DIG_LP_FEATURES__DP_MST_PRESENT 0 +#define DC__DIG_LP_FEATURES__DP_MST_PRESENT__0 1 +#define DC__DIG_RESYNC_FIFO_SIZE 14 +#define DC__DIG_RESYNC_FIFO_SIZE__14 1 +#define DC__DIG_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__12_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__13_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DIG_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__DAC_RESYNC_FIFO_SIZE 12 +#define DC__DAC_RESYNC_FIFO_SIZE__12 1 +#define DC__DAC_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DAC_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__DVO_RESYNC_FIFO_SIZE 12 +#define DC__DVO_RESYNC_FIFO_SIZE__12 1 +#define DC__DVO_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DVO_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__MEM_CDC_PRESENT 1 +#define DC__MEM_CDC_PRESENT__1 1 +#define DC__NUM_HPD 4 +#define DC__NUM_HPD__4 1 +#define DC__NUM_HPD__0_PRESENT 1 +#define DC__NUM_HPD__1_PRESENT 1 +#define DC__NUM_HPD__2_PRESENT 1 +#define DC__NUM_HPD__3_PRESENT 1 +#define DC__NUM_HPD__MAX 6 +#define DC__NUM_HPD__MAX__6 1 +#define DC__NUM_DDC_PAIRS 4 +#define DC__NUM_DDC_PAIRS__4 1 +#define DC__NUM_DDC_PAIRS__0_PRESENT 1 +#define DC__NUM_DDC_PAIRS__1_PRESENT 1 +#define DC__NUM_DDC_PAIRS__2_PRESENT 1 +#define DC__NUM_DDC_PAIRS__3_PRESENT 1 +#define DC__NUM_DDC_PAIRS__MAX 6 +#define DC__NUM_DDC_PAIRS__MAX__6 1 +#define DC__NUM_AUDIO_PLL 0 +#define DC__NUM_AUDIO_PLL__0 1 +#define DC__NUM_AUDIO_PLL__MAX 2 +#define DC__NUM_AUDIO_PLL__MAX__2 1 +#define DC__NUM_PIXEL_PLL 1 +#define DC__NUM_PIXEL_PLL__1 1 +#define DC__NUM_PIXEL_PLL__0_PRESENT 1 +#define DC__NUM_PIXEL_PLL__MAX 4 +#define DC__NUM_PIXEL_PLL__MAX__4 1 +#define DC__NUM_CASCADED_PLL 0 +#define DC__NUM_CASCADED_PLL__0 1 +#define DC__NUM_CASCADED_PLL__MAX 3 +#define DC__NUM_CASCADED_PLL__MAX__3 1 +#define DC__PIXCLK_FROM_PHYPLL 1 +#define DC__PIXCLK_FROM_PHYPLL__1 1 +#define DC__NB_STUTTER_MODE_PRESENT 0 +#define DC__NB_STUTTER_MODE_PRESENT__0 1 +#define DC__I2S0_AND_SPDIF0_PRESENT 0 +#define DC__I2S0_AND_SPDIF0_PRESENT__0 1 +#define DC__I2S1_PRESENT 0 +#define DC__I2S1_PRESENT__0 1 +#define DC__SPDIF1_PRESENT 0 +#define DC__SPDIF1_PRESENT__0 1 +#define DC__DSI_PRESENT 0 +#define DC__DSI_PRESENT__0 1 +#define DC__DACA_PRESENT 0 +#define DC__DACA_PRESENT__0 1 +#define DC__DACB_PRESENT 0 +#define DC__DACB_PRESENT__0 1 +#define DC__NUM_PIPES 4 +#define DC__NUM_PIPES__4 1 +#define DC__NUM_PIPES__0_PRESENT 1 +#define DC__NUM_PIPES__1_PRESENT 1 +#define DC__NUM_PIPES__2_PRESENT 1 +#define DC__NUM_PIPES__3_PRESENT 1 +#define DC__NUM_PIPES__MAX 6 +#define DC__NUM_PIPES__MAX__6 1 +#define DC__NUM_DIG_LP 0 +#define DC__NUM_DIG_LP__0 1 +#define DC__NUM_DIG_LP__MAX 2 +#define DC__NUM_DIG_LP__MAX__2 1 +#define DC__DPDEBUG_PRESENT 0 +#define DC__DPDEBUG_PRESENT__0 1 +#define DC__DISPLAY_WB_PRESENT 1 +#define DC__DISPLAY_WB_PRESENT__1 1 +#define DC__NUM_CWB 0 +#define DC__NUM_CWB__0 1 +#define DC__NUM_CWB__MAX 2 +#define DC__NUM_CWB__MAX__2 1 +#define DC__MVP_PRESENT 0 +#define DC__MVP_PRESENT__0 1 +#define DC__DVO_PRESENT 0 +#define DC__DVO_PRESENT__0 1 +#define DC__ABM_PRESENT 0 +#define DC__ABM_PRESENT__0 1 +#define DC__BPHYC_PLL_PRESENT 0 +#define DC__BPHYC_PLL_PRESENT__0 1 +#define DC__BPHYC_UNIPHY_PRESENT 0 +#define DC__BPHYC_UNIPHY_PRESENT__0 1 +#define DC__PHY_BROADCAST_PRESENT 0 +#define DC__PHY_BROADCAST_PRESENT__0 1 +#define DC__NUM_OF_DCRX_SD 0 +#define DC__NUM_OF_DCRX_SD__0 1 +#define DC__DVO_17BIT_MAPPING 0 +#define DC__DVO_17BIT_MAPPING__0 1 +#define DC__AVSYNC_PRESENT 0 +#define DC__AVSYNC_PRESENT__0 1 +#define DC__NUM_OF_DCRX_PORTS 0 +#define DC__NUM_OF_DCRX_PORTS__0 1 +#define DC__NUM_OF_DCRX_PORTS__MAX 1 +#define DC__NUM_OF_DCRX_PORTS__MAX__1 1 +#define DC__NUM_PHY 4 +#define DC__NUM_PHY__4 1 +#define DC__NUM_PHY__0_PRESENT 1 +#define DC__NUM_PHY__1_PRESENT 1 +#define DC__NUM_PHY__2_PRESENT 1 +#define DC__NUM_PHY__3_PRESENT 1 +#define DC__NUM_PHY__MAX 7 +#define DC__NUM_PHY__MAX__7 1 +#define DC__NUM_PHY_LP 0 +#define DC__NUM_PHY_LP__0 1 +#define DC__NUM_PHY_LP__MAX 2 +#define DC__NUM_PHY_LP__MAX__2 1 +#define DC__SYNC_CELL vid_sync_gf14lpp +#define DC__SYNC_CELL__VID_SYNC_GF14LPP 1 +#define DC__USE_NEW_VSS 1 +#define DC__USE_NEW_VSS__1 1 +#define DC__SYNC_CELL_DISPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DISPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DVOCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DVOCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_PIXCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_PIXCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_SYMCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_SYMCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DPPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DPPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DPREFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DPREFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_REFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_REFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_PCIE_REFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_PCIE_REFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_MVPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_MVPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_SCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_SCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DCEFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DCEFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_AMCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_AMCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DSICLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DSICLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_BYTECLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_BYTECLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_ESCCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_ESCCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DB_CLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DB_CLK_NUM_LATCHES__6 1 +#define UNIPHYA_PRESENT 1 +#define UNIPHYA_PRESENT__1 1 +#define DC__UNIPHYA_PRESENT 1 +#define DC__UNIPHYA_PRESENT__1 1 +#define UNIPHYB_PRESENT 1 +#define UNIPHYB_PRESENT__1 1 +#define DC__UNIPHYB_PRESENT 1 +#define DC__UNIPHYB_PRESENT__1 1 +#define UNIPHYC_PRESENT 1 +#define UNIPHYC_PRESENT__1 1 +#define DC__UNIPHYC_PRESENT 1 +#define DC__UNIPHYC_PRESENT__1 1 +#define UNIPHYD_PRESENT 1 +#define UNIPHYD_PRESENT__1 1 +#define DC__UNIPHYD_PRESENT 1 +#define DC__UNIPHYD_PRESENT__1 1 +#define UNIPHYE_PRESENT 0 +#define UNIPHYE_PRESENT__0 1 +#define DC__UNIPHYE_PRESENT 0 +#define DC__UNIPHYE_PRESENT__0 1 +#define UNIPHYF_PRESENT 0 +#define UNIPHYF_PRESENT__0 1 +#define DC__UNIPHYF_PRESENT 0 +#define DC__UNIPHYF_PRESENT__0 1 +#define UNIPHYG_PRESENT 0 +#define UNIPHYG_PRESENT__0 1 +#define DC__UNIPHYG_PRESENT 0 +#define DC__UNIPHYG_PRESENT__0 1 +#define DC__TMDS_LINK tmds_link_dual +#define DC__TMDS_LINK__TMDS_LINK_DUAL 1 +#define DC__WBSCL_PIXBW 8 +#define DC__WBSCL_PIXBW__8 1 +#define DC__DWB_CSC_PRESENT 0 +#define DC__DWB_CSC_PRESENT__0 1 +#define DC__DWB_LUMA_SCL_PRESENT 0 +#define DC__DWB_LUMA_SCL_PRESENT__0 1 +#define DC__DENTIST_INTERFACE_PRESENT 1 +#define DC__DENTIST_INTERFACE_PRESENT__1 1 +#define DC__GENERICA_PRESENT 1 +#define DC__GENERICA_PRESENT__1 1 +#define DC__GENERICB_PRESENT 1 +#define DC__GENERICB_PRESENT__1 1 +#define DC__GENERICC_PRESENT 0 +#define DC__GENERICC_PRESENT__0 1 +#define DC__GENERICD_PRESENT 0 +#define DC__GENERICD_PRESENT__0 1 +#define DC__GENERICE_PRESENT 0 +#define DC__GENERICE_PRESENT__0 1 +#define DC__GENERICF_PRESENT 0 +#define DC__GENERICF_PRESENT__0 1 +#define DC__GENERICG_PRESENT 0 +#define DC__GENERICG_PRESENT__0 1 +#define DC__UNIPHY_VOLTAGE_MODE 1 +#define DC__UNIPHY_VOLTAGE_MODE__1 1 +#define DC__BLON_TYPE dedicated +#define DC__BLON_TYPE__DEDICATED 1 +#define DC__UNIPHY_STAGGER_CH_PRESENT 1 +#define DC__UNIPHY_STAGGER_CH_PRESENT__1 1 +#define DC__XDMA_PRESENT 0 +#define DC__XDMA_PRESENT__0 1 +#define XDMA__PRESENT 0 +#define XDMA__PRESENT__0 1 +#define DC__DP_MEM_PG 0 +#define DC__DP_MEM_PG__0 1 +#define DP__MEM_PG 0 +#define DP__MEM_PG__0 1 +#define DC__AFMT_MEM_PG 0 +#define DC__AFMT_MEM_PG__0 1 +#define AFMT__MEM_PG 0 +#define AFMT__MEM_PG__0 1 +#define DC__HDMI_MEM_PG 0 +#define DC__HDMI_MEM_PG__0 1 +#define HDMI__MEM_PG 0 +#define HDMI__MEM_PG__0 1 +#define DC__I2C_MEM_PG 0 +#define DC__I2C_MEM_PG__0 1 +#define I2C__MEM_PG 0 +#define I2C__MEM_PG__0 1 +#define DC__DSCL_MEM_PG 0 +#define DC__DSCL_MEM_PG__0 1 +#define DSCL__MEM_PG 0 +#define DSCL__MEM_PG__0 1 +#define DC__CM_MEM_PG 0 +#define DC__CM_MEM_PG__0 1 +#define CM__MEM_PG 0 +#define CM__MEM_PG__0 1 +#define DC__OBUF_MEM_PG 0 +#define DC__OBUF_MEM_PG__0 1 +#define OBUF__MEM_PG 0 +#define OBUF__MEM_PG__0 1 +#define DC__WBIF_MEM_PG 1 +#define DC__WBIF_MEM_PG__1 1 +#define WBIF__MEM_PG 1 +#define WBIF__MEM_PG__1 1 +#define DC__VGA_MEM_PG 0 +#define DC__VGA_MEM_PG__0 1 +#define VGA__MEM_PG 0 +#define VGA__MEM_PG__0 1 +#define DC__FMT_MEM_PG 0 +#define DC__FMT_MEM_PG__0 1 +#define FMT__MEM_PG 0 +#define FMT__MEM_PG__0 1 +#define DC__ODM_MEM_PG 0 +#define DC__ODM_MEM_PG__0 1 +#define ODM__MEM_PG 0 +#define ODM__MEM_PG__0 1 +#define DC__DSI_MEM_PG 0 +#define DC__DSI_MEM_PG__0 1 +#define DSI__MEM_PG 0 +#define DSI__MEM_PG__0 1 +#define DC__AZ_MEM_PG 1 +#define DC__AZ_MEM_PG__1 1 +#define AZ__MEM_PG 1 +#define AZ__MEM_PG__1 1 +#define DC__WBSCL_MEM1P1024X64QS_MEM_PG 1 +#define DC__WBSCL_MEM1P1024X64QS_MEM_PG__1 1 +#define WBSCL_MEM1P1024X64QS__MEM_PG 1 +#define WBSCL_MEM1P1024X64QS__MEM_PG__1 1 +#define DC__WBSCL_MEM1P528X64QS_MEM_PG 1 +#define DC__WBSCL_MEM1P528X64QS_MEM_PG__1 1 +#define WBSCL_MEM1P528X64QS__MEM_PG 1 +#define WBSCL_MEM1P528X64QS__MEM_PG__1 1 +#define DC__DMCU_MEM1P1024X32BQS_MEM_PG 1 +#define DC__DMCU_MEM1P1024X32BQS_MEM_PG__1 1 +#define DMCU_MEM1P1024X32BQS__MEM_PG 1 +#define DMCU_MEM1P1024X32BQS__MEM_PG__1 1 +#define DC__HUBBUB_SDP_TAG_INT_MEM_PG 0 +#define DC__HUBBUB_SDP_TAG_INT_MEM_PG__0 1 +#define HUBBUB_SDP_TAG_INT__MEM_PG 0 +#define HUBBUB_SDP_TAG_INT__MEM_PG__0 1 +#define DC__HUBBUB_SDP_TAG_EXT_MEM_PG 0 +#define DC__HUBBUB_SDP_TAG_EXT_MEM_PG__0 1 +#define HUBBUB_SDP_TAG_EXT__MEM_PG 0 +#define HUBBUB_SDP_TAG_EXT__MEM_PG__0 1 +#define DC__HUBBUB_RET_ZERO_MEM_PG 0 +#define DC__HUBBUB_RET_ZERO_MEM_PG__0 1 +#define HUBBUB_RET_ZERO__MEM_PG 0 +#define HUBBUB_RET_ZERO__MEM_PG__0 1 +#define DC__HUBBUB_RET_ROB_MEM_PG 0 +#define DC__HUBBUB_RET_ROB_MEM_PG__0 1 +#define HUBBUB_RET_ROB__MEM_PG 0 +#define HUBBUB_RET_ROB__MEM_PG__0 1 +#define DC__HUBPRET_CUR_ROB_MEM_PG 0 +#define DC__HUBPRET_CUR_ROB_MEM_PG__0 1 +#define HUBPRET_CUR_ROB__MEM_PG 0 +#define HUBPRET_CUR_ROB__MEM_PG__0 1 +#define DC__HUBPRET_CUR_CDC_MEM_PG 0 +#define DC__HUBPRET_CUR_CDC_MEM_PG__0 1 +#define HUBPRET_CUR_CDC__MEM_PG 0 +#define HUBPRET_CUR_CDC__MEM_PG__0 1 +#define DC__HUBPREQ_MPTE_MEM_PG 0 +#define DC__HUBPREQ_MPTE_MEM_PG__0 1 +#define HUBPREQ_MPTE__MEM_PG 0 +#define HUBPREQ_MPTE__MEM_PG__0 1 +#define DC__HUBPREQ_META_MEM_PG 0 +#define DC__HUBPREQ_META_MEM_PG__0 1 +#define HUBPREQ_META__MEM_PG 0 +#define HUBPREQ_META__MEM_PG__0 1 +#define DC__HUBPREQ_DPTE_MEM_PG 0 +#define DC__HUBPREQ_DPTE_MEM_PG__0 1 +#define HUBPREQ_DPTE__MEM_PG 0 +#define HUBPREQ_DPTE__MEM_PG__0 1 +#define DC__HUBPRET_DET_MEM_PG 0 +#define DC__HUBPRET_DET_MEM_PG__0 1 +#define HUBPRET_DET__MEM_PG 0 +#define HUBPRET_DET__MEM_PG__0 1 +#define DC__HUBPRET_PIX_CDC_MEM_PG 0 +#define DC__HUBPRET_PIX_CDC_MEM_PG__0 1 +#define HUBPRET_PIX_CDC__MEM_PG 0 +#define HUBPRET_PIX_CDC__MEM_PG__0 1 +#define DC__TOP_BLKS__DCCG 1 +#define DC__TOP_BLKS__DCHUBBUB 1 +#define DC__TOP_BLKS__DCHUBP 1 +#define DC__TOP_BLKS__HDA 1 +#define DC__TOP_BLKS__DIO 1 +#define DC__TOP_BLKS__DCIO 1 +#define DC__TOP_BLKS__DMU 1 +#define DC__TOP_BLKS__DPP 1 +#define DC__TOP_BLKS__MPC 1 +#define DC__TOP_BLKS__OPP 1 +#define DC__TOP_BLKS__OPTC 1 +#define DC__TOP_BLKS__MMHUBBUB 1 +#define DC__TOP_BLKS__WB 1 +#define DC__TOP_BLKS__MAX 13 +#define DC__TOP_BLKS__MAX__13 1 +#define DC__DCHUBP_DPP_SF_PIXEL_CREDITS 9 +#define DC__DCHUBP_DPP_SF_PIXEL_CREDITS__9 1 +#define DC__DPP_MPC_SF_PIXEL_CREDITS 9 +#define DC__DPP_MPC_SF_PIXEL_CREDITS__9 1 +#define DC__MPC_OPP_SF_PIXEL_CREDITS 8 +#define DC__MPC_OPP_SF_PIXEL_CREDITS__8 1 +#define DC__OPP_OPTC_SF_PIXEL_CREDITS 8 +#define DC__OPP_OPTC_SF_PIXEL_CREDITS__8 1 +#define DC__SFR_SFT_ROUND_TRIP_DELAY 5 +#define DC__SFR_SFT_ROUND_TRIP_DELAY__5 1 +#define DC__REPEATER_PROJECT_MAX 8 +#define DC__REPEATER_PROJECT_MAX__8 1 +#define DC__SURFACE_422_CAPABLE 0 +#define DC__SURFACE_422_CAPABLE__0 1 +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h new file mode 100644 index 000000000000..143a3d418de0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -0,0 +1,111 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_MODE_ENUMS_H__ +#define __DISPLAY_MODE_ENUMS_H__ +enum output_encoder_class { + dm_dp = 0, + dm_hdmi = 1, + dm_wb = 2 +}; +enum output_format_class { + dm_444 = 0, + dm_420 = 1 +}; +enum source_format_class { + dm_444_16 = 0, + dm_444_32 = 1, + dm_444_64 = 2, + dm_420_8 = 3, + dm_420_10 = 4, + dm_422_8 = 5, + dm_422_10 = 6 +}; +enum output_bpc_class { + dm_out_6 = 0, + dm_out_8 = 1, + dm_out_10 = 2, + dm_out_12 = 3, + dm_out_16 = 4 +}; +enum scan_direction_class { + dm_horz = 0, + dm_vert = 1 +}; +enum dm_swizzle_mode { + dm_sw_linear = 0, + dm_sw_256b_s = 1, + dm_sw_256b_d = 2, + dm_sw_SPARE_0 = 3, + dm_sw_SPARE_1 = 4, + dm_sw_4kb_s = 5, + dm_sw_4kb_d = 6, + dm_sw_SPARE_2 = 7, + dm_sw_SPARE_3 = 8, + dm_sw_64kb_s = 9, + dm_sw_64kb_d = 10, + dm_sw_SPARE_4 = 11, + dm_sw_SPARE_5 = 12, + dm_sw_var_s = 13, + dm_sw_var_d = 14, + dm_sw_SPARE_6 = 15, + dm_sw_SPARE_7 = 16, + dm_sw_64kb_s_t = 17, + dm_sw_64kb_d_t = 18, + dm_sw_SPARE_10 = 19, + dm_sw_SPARE_11 = 20, + dm_sw_4kb_s_x = 21, + dm_sw_4kb_d_x = 22, + dm_sw_SPARE_12 = 23, + dm_sw_SPARE_13 = 24, + dm_sw_64kb_s_x = 25, + dm_sw_64kb_d_x = 26, + dm_sw_SPARE_14 = 27, + dm_sw_SPARE_15 = 28, + dm_sw_var_s_x = 29, + dm_sw_var_d_x = 30 +}; +enum lb_depth { + dm_lb_10 = 30, + dm_lb_8 = 24, + dm_lb_6 = 18, + dm_lb_12 = 36 +}; +enum voltage_state { + dm_vmin = 0, + dm_vmid = 1, + dm_vnom = 2, + dm_vmax = 3, + dm_vmax_exceeded = 4 +}; +enum source_macro_tile_size { + dm_4k_tile = 0, + dm_64k_tile = 1, + dm_256k_tile = 2 +}; +enum cursor_bpp { + dm_cur_2bit = 0, + dm_cur_32bit = 1 +}; +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c new file mode 100644 index 000000000000..c02c5522613b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -0,0 +1,147 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_mode_lib.h" + +static void set_soc_bounding_box(struct _vcs_dpi_soc_bounding_box_st *soc, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + soc->sr_exit_time_us = 9.0; + soc->sr_enter_plus_exit_time_us = 11.0; + soc->urgent_latency_us = 4.0; + soc->writeback_latency_us = 12.0; + soc->ideal_dram_bw_after_urgent_percent = 80.0; + soc->max_request_size_bytes = 256; + + soc->vmin.dcfclk_mhz = 300.0; + soc->vmin.dispclk_mhz = 608.0; + soc->vmin.dppclk_mhz = 435.0; + soc->vmin.dram_bw_per_chan_gbps = 12.8; + soc->vmin.phyclk_mhz = 540.0; + soc->vmin.socclk_mhz = 208.0; + + soc->vmid.dcfclk_mhz = 600.0; + soc->vmid.dispclk_mhz = 661.0; + soc->vmid.dppclk_mhz = 661.0; + soc->vmid.dram_bw_per_chan_gbps = 12.8; + soc->vmid.phyclk_mhz = 540.0; + soc->vmid.socclk_mhz = 208.0; + + soc->vnom.dcfclk_mhz = 600.0; + soc->vnom.dispclk_mhz = 661.0; + soc->vnom.dppclk_mhz = 661.0; + soc->vnom.dram_bw_per_chan_gbps = 38.4; + soc->vnom.phyclk_mhz = 810; + soc->vnom.socclk_mhz = 208.0; + + soc->vmax.dcfclk_mhz = 600.0; + soc->vmax.dispclk_mhz = 1086.0; + soc->vmax.dppclk_mhz = 661.0; + soc->vmax.dram_bw_per_chan_gbps = 38.4; + soc->vmax.phyclk_mhz = 810.0; + soc->vmax.socclk_mhz = 208.0; + + soc->downspread_percent = 0.5; + soc->dram_page_open_time_ns = 50.0; + soc->dram_rw_turnaround_time_ns = 17.5; + soc->dram_return_buffer_per_channel_bytes = 8192; + soc->round_trip_ping_latency_dcfclk_cycles = 128; + soc->urgent_out_of_order_return_per_channel_bytes = 256; + soc->channel_interleave_bytes = 256; + soc->num_banks = 8; + soc->num_chans = 2; + soc->vmm_page_size_bytes = 4096; + soc->dram_clock_change_latency_us = 17.0; + soc->writeback_dram_clock_change_latency_us = 23.0; + soc->return_bus_width_bytes = 64; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +static void set_ip_params(struct _vcs_dpi_ip_params_st *ip, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + ip->rob_buffer_size_kbytes = 64; + ip->det_buffer_size_kbytes = 164; + ip->dpte_buffer_size_in_pte_reqs = 42; + ip->dpp_output_buffer_pixels = 2560; + ip->opp_output_buffer_lines = 1; + ip->pixel_chunk_size_kbytes = 8; + ip->pte_enable = 1; + ip->pte_chunk_size_kbytes = 2; + ip->meta_chunk_size_kbytes = 2; + ip->writeback_chunk_size_kbytes = 2; + ip->line_buffer_size_bits = 589824; + ip->max_line_buffer_lines = 12; + ip->IsLineBufferBppFixed = 0; + ip->LineBufferFixedBpp = -1; + ip->writeback_luma_buffer_size_kbytes = 12; + ip->writeback_chroma_buffer_size_kbytes = 8; + ip->max_num_dpp = 4; + ip->max_num_wb = 2; + ip->max_dchub_pscl_bw_pix_per_clk = 4; + ip->max_pscl_lb_bw_pix_per_clk = 2; + ip->max_lb_vscl_bw_pix_per_clk = 4; + ip->max_vscl_hscl_bw_pix_per_clk = 4; + ip->max_hscl_ratio = 4; + ip->max_vscl_ratio = 4; + ip->hscl_mults = 4; + ip->vscl_mults = 4; + ip->max_hscl_taps = 8; + ip->max_vscl_taps = 8; + ip->dispclk_ramp_margin_percent = 1; + ip->underscan_factor = 1.10; + ip->min_vblank_lines = 14; + ip->dppclk_delay_subtotal = 90; + ip->dispclk_delay_subtotal = 42; + ip->dcfclk_cstate_latency = 10; + ip->max_inter_dcn_tile_repeaters = 8; + ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = 0; + ip->bug_forcing_LC_req_same_size_fixed = 0; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +static void set_mode_evaluation(struct _vcs_dpi_mode_evaluation_st *me, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + me->voltage_override = dm_vmin; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) +{ + if (lib->project != project) { + set_soc_bounding_box(&lib->soc, project); + set_ip_params(&lib->ip, project); + set_mode_evaluation(&lib->me, project); + lib->project = project; + } +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h new file mode 100644 index 000000000000..e2e311138358 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_MODE_LIB_H__ +#define __DISPLAY_MODE_LIB_H__ + +#include "dml_common_defs.h" +#include "soc_bounding_box.h" +#include "display_watermark.h" +#include "display_pipe_clocks.h" +#include "display_rq_dlg_calc.h" +#include "display_mode_support.h" + +enum dml_project { + DML_PROJECT_UNDEFINED, + DML_PROJECT_RAVEN1 +}; + +struct display_mode_lib { + struct _vcs_dpi_ip_params_st ip; + struct _vcs_dpi_soc_bounding_box_st soc; + struct _vcs_dpi_mode_evaluation_st me; + enum dml_project project; + struct dml_ms_internal_vars vars; + struct _vcs_dpi_wm_calc_pipe_params_st wm_param[DC__NUM_PIPES__MAX]; + struct dal_logger *logger; +}; + +void dml_init_instance(struct display_mode_lib *lib, enum dml_project project); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h new file mode 100644 index 000000000000..e589a5eadb6a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -0,0 +1,429 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_MODE_STRUCTS_H__ +#define __DISPLAY_MODE_STRUCTS_H__ + +struct _vcs_dpi_voltage_scaling_st { + double dcfclk_mhz; + double dispclk_mhz; + double dppclk_mhz; + double dram_bw_per_chan_gbps; + double phyclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_soc_bounding_box_st { + double sr_exit_time_us; + double sr_enter_plus_exit_time_us; + double urgent_latency_us; + double writeback_latency_us; + double ideal_dram_bw_after_urgent_percent; + unsigned int max_request_size_bytes; + struct _vcs_dpi_voltage_scaling_st vmin; + struct _vcs_dpi_voltage_scaling_st vmid; + struct _vcs_dpi_voltage_scaling_st vnom; + struct _vcs_dpi_voltage_scaling_st vmax; + double downspread_percent; + double dram_page_open_time_ns; + double dram_rw_turnaround_time_ns; + double dram_return_buffer_per_channel_bytes; + unsigned int round_trip_ping_latency_dcfclk_cycles; + unsigned int urgent_out_of_order_return_per_channel_bytes; + unsigned int channel_interleave_bytes; + unsigned int num_banks; + unsigned int num_chans; + unsigned int vmm_page_size_bytes; + double dram_clock_change_latency_us; + double writeback_dram_clock_change_latency_us; + unsigned int return_bus_width_bytes; +}; + +struct _vcs_dpi_ip_params_st { + unsigned int rob_buffer_size_kbytes; + unsigned int det_buffer_size_kbytes; + unsigned int dpte_buffer_size_in_pte_reqs; + unsigned int dpp_output_buffer_pixels; + unsigned int opp_output_buffer_lines; + unsigned int pixel_chunk_size_kbytes; + unsigned char pte_enable; + unsigned int pte_chunk_size_kbytes; + unsigned int meta_chunk_size_kbytes; + unsigned int writeback_chunk_size_kbytes; + unsigned int line_buffer_size_bits; + unsigned int max_line_buffer_lines; + unsigned int IsLineBufferBppFixed; + unsigned int LineBufferFixedBpp; + unsigned int writeback_luma_buffer_size_kbytes; + unsigned int writeback_chroma_buffer_size_kbytes; + unsigned int max_num_dpp; + unsigned int max_num_wb; + unsigned int max_dchub_pscl_bw_pix_per_clk; + unsigned int max_pscl_lb_bw_pix_per_clk; + unsigned int max_lb_vscl_bw_pix_per_clk; + unsigned int max_vscl_hscl_bw_pix_per_clk; + double max_hscl_ratio; + double max_vscl_ratio; + unsigned int hscl_mults; + unsigned int vscl_mults; + unsigned int max_hscl_taps; + unsigned int max_vscl_taps; + double dispclk_ramp_margin_percent; + double underscan_factor; + unsigned int min_vblank_lines; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int dcfclk_cstate_latency; + unsigned int max_inter_dcn_tile_repeaters; + unsigned int can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + unsigned int bug_forcing_LC_req_same_size_fixed; +}; + +struct _vcs_dpi_display_pipe_source_params_st { + int source_format; + unsigned char dcc; + unsigned int dcc_rate; + unsigned char vm; + int source_scan; + int sw_mode; + int macro_tile_size; + unsigned char is_display_sw; + unsigned int viewport_width; + unsigned int viewport_height; + unsigned int viewport_width_c; + unsigned int viewport_height_c; + unsigned int data_pitch; + unsigned int data_pitch_c; + unsigned int meta_pitch; + unsigned int meta_pitch_c; + unsigned int cur0_src_width; + int cur0_bpp; + unsigned char is_hsplit; + unsigned int hsplit_grp; +}; + +struct _vcs_dpi_display_output_params_st { + int output_bpc; + int output_type; + int output_format; + int output_standard; +}; + +struct _vcs_dpi_display_bandwidth_st { + double total_bw_consumed_gbps; + double guaranteed_urgent_return_bw_gbps; +}; + +struct _vcs_dpi_scaler_ratio_depth_st { + double hscl_ratio; + double vscl_ratio; + double hscl_ratio_c; + double vscl_ratio_c; + double vinit; + double vinit_c; + double vinit_bot; + double vinit_bot_c; + int lb_depth; +}; + +struct _vcs_dpi_scaler_taps_st { + unsigned int htaps; + unsigned int vtaps; + unsigned int htaps_c; + unsigned int vtaps_c; +}; + +struct _vcs_dpi_display_pipe_dest_params_st { + unsigned int recout_width; + unsigned int recout_height; + unsigned int full_recout_width; + unsigned int full_recout_height; + unsigned int hblank_start; + unsigned int hblank_end; + unsigned int vblank_start; + unsigned int vblank_end; + unsigned int htotal; + unsigned int vtotal; + unsigned int vactive; + unsigned int vstartup_start; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int vsync_plus_back_porch; + unsigned char interlaced; + unsigned char underscan; + double pixel_rate_mhz; + unsigned char syncronized_vblank_all_planes; +}; + +struct _vcs_dpi_display_pipe_params_st { + struct _vcs_dpi_display_pipe_source_params_st src; + struct _vcs_dpi_display_pipe_dest_params_st dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps; +}; + +struct _vcs_dpi_display_clocks_and_cfg_st { + int voltage; + double dppclk_mhz; + double refclk_mhz; + double dispclk_mhz; + double dcfclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_display_e2e_pipe_params_st { + struct _vcs_dpi_display_pipe_params_st pipe; + struct _vcs_dpi_display_output_params_st dout; + struct _vcs_dpi_display_clocks_and_cfg_st clks_cfg; +}; + +struct _vcs_dpi_dchub_buffer_sizing_st { + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int detail_buffer_size_y; +}; + +struct _vcs_dpi_watermarks_perf_st { + double stutter_eff_in_active_region_percent; + double urgent_latency_supported_us; + double non_urgent_latency_supported_us; + double dram_clock_change_margin_us; + double dram_access_eff_percent; +}; + +struct _vcs_dpi_cstate_pstate_watermarks_st { + double cstate_exit_us; + double cstate_enter_plus_exit_us; + double pstate_change_us; +}; + +struct _vcs_dpi_wm_calc_pipe_params_st { + unsigned int num_dpp; + int voltage; + int output_type; + double dcfclk_mhz; + double socclk_mhz; + double dppclk_mhz; + double pixclk_mhz; + unsigned char interlace_en; + unsigned char pte_enable; + unsigned char dcc_enable; + double dcc_rate; + double bytes_per_pixel_c; + double bytes_per_pixel_y; + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int det_buffer_size_y; + double h_ratio; + double v_ratio; + unsigned int h_taps; + unsigned int h_total; + unsigned int v_total; + unsigned int v_active; + unsigned int e2e_index; + double display_pipe_line_delivery_time; + double read_bw; + unsigned int lines_in_det_y; + unsigned int lines_in_det_y_rounded_down_to_swath; + double full_det_buffering_time; + double dcfclk_deepsleep_mhz_per_plane; +}; + +struct _vcs_dpi_vratio_pre_st { + double vratio_pre_l; + double vratio_pre_c; +}; + +struct _vcs_dpi_display_data_rq_misc_params_st { + unsigned int full_swath_bytes; + unsigned int stored_swath_bytes; + unsigned int blk256_height; + unsigned int blk256_width; + unsigned int req_height; + unsigned int req_width; +}; + +struct _vcs_dpi_display_data_rq_sizing_params_st { + unsigned int chunk_bytes; + unsigned int min_chunk_bytes; + unsigned int meta_chunk_bytes; + unsigned int min_meta_chunk_bytes; + unsigned int mpte_group_bytes; + unsigned int dpte_group_bytes; +}; + +struct _vcs_dpi_display_data_rq_dlg_params_st { + unsigned int swath_width_ub; + unsigned int swath_height; + unsigned int req_per_swath_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int dpte_req_per_row_ub; + unsigned int dpte_groups_per_row_ub; + unsigned int dpte_row_height; + unsigned int dpte_bytes_per_row_ub; + unsigned int meta_chunks_per_row_ub; + unsigned int meta_req_per_row_ub; + unsigned int meta_row_height; + unsigned int meta_bytes_per_row_ub; +}; + +struct _vcs_dpi_display_cur_rq_dlg_params_st { + unsigned char enable; + unsigned int swath_height; + unsigned int req_per_line; +}; + +struct _vcs_dpi_display_rq_dlg_params_st { + struct _vcs_dpi_display_data_rq_dlg_params_st rq_l; + struct _vcs_dpi_display_data_rq_dlg_params_st rq_c; + struct _vcs_dpi_display_cur_rq_dlg_params_st rq_cur0; +}; + +struct _vcs_dpi_display_rq_sizing_params_st { + struct _vcs_dpi_display_data_rq_sizing_params_st rq_l; + struct _vcs_dpi_display_data_rq_sizing_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_misc_params_st { + struct _vcs_dpi_display_data_rq_misc_params_st rq_l; + struct _vcs_dpi_display_data_rq_misc_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_params_st { + unsigned char yuv420; + unsigned char yuv420_10bpc; + struct _vcs_dpi_display_rq_misc_params_st misc; + struct _vcs_dpi_display_rq_sizing_params_st sizing; + struct _vcs_dpi_display_rq_dlg_params_st dlg; +}; + +struct _vcs_dpi_display_dlg_regs_st { + unsigned int refcyc_h_blank_end; + unsigned int dlg_vblank_end; + unsigned int min_dst_y_next_start; + unsigned int refcyc_per_htotal; + unsigned int refcyc_x_after_scaler; + unsigned int dst_y_after_scaler; + unsigned int dst_y_prefetch; + unsigned int dst_y_per_vm_vblank; + unsigned int dst_y_per_row_vblank; + unsigned int ref_freq_to_pix_freq; + unsigned int vratio_prefetch; + unsigned int vratio_prefetch_c; + unsigned int refcyc_per_pte_group_vblank_l; + unsigned int refcyc_per_pte_group_vblank_c; + unsigned int refcyc_per_meta_chunk_vblank_l; + unsigned int refcyc_per_meta_chunk_vblank_c; + unsigned int dst_y_per_pte_row_nom_l; + unsigned int dst_y_per_pte_row_nom_c; + unsigned int refcyc_per_pte_group_nom_l; + unsigned int refcyc_per_pte_group_nom_c; + unsigned int dst_y_per_meta_row_nom_l; + unsigned int dst_y_per_meta_row_nom_c; + unsigned int refcyc_per_meta_chunk_nom_l; + unsigned int refcyc_per_meta_chunk_nom_c; + unsigned int refcyc_per_line_delivery_pre_l; + unsigned int refcyc_per_line_delivery_pre_c; + unsigned int refcyc_per_line_delivery_l; + unsigned int refcyc_per_line_delivery_c; + unsigned int chunk_hdl_adjust_cur0; +}; + +struct _vcs_dpi_display_ttu_regs_st { + unsigned int qos_level_low_wm; + unsigned int qos_level_high_wm; + unsigned int min_ttu_vblank; + unsigned int qos_level_flip; + unsigned int refcyc_per_req_delivery_l; + unsigned int refcyc_per_req_delivery_c; + unsigned int refcyc_per_req_delivery_cur0; + unsigned int refcyc_per_req_delivery_pre_l; + unsigned int refcyc_per_req_delivery_pre_c; + unsigned int refcyc_per_req_delivery_pre_cur0; + unsigned int qos_level_fixed_l; + unsigned int qos_level_fixed_c; + unsigned int qos_level_fixed_cur0; + unsigned int qos_ramp_disable_l; + unsigned int qos_ramp_disable_c; + unsigned int qos_ramp_disable_cur0; +}; + +struct _vcs_dpi_display_data_rq_regs_st { + unsigned int chunk_size; + unsigned int min_chunk_size; + unsigned int meta_chunk_size; + unsigned int min_meta_chunk_size; + unsigned int dpte_group_size; + unsigned int mpte_group_size; + unsigned int swath_height; + unsigned int pte_row_height_linear; +}; + +struct _vcs_dpi_display_rq_regs_st { + struct _vcs_dpi_display_data_rq_regs_st rq_regs_l; + struct _vcs_dpi_display_data_rq_regs_st rq_regs_c; + unsigned int drq_expansion_mode; + unsigned int prq_expansion_mode; + unsigned int mrq_expansion_mode; + unsigned int crq_expansion_mode; + unsigned int plane1_base_address; +}; + +struct _vcs_dpi_display_dlg_sys_params_st { + double t_mclk_wm_us; + double t_urg_wm_us; + double t_sr_wm_us; + double t_extra_us; + double t_srx_delay_us; + double deepsleep_dcfclk_mhz; + double total_flip_bw; + unsigned int total_flip_bytes; +}; + +struct _vcs_dpi_display_dlg_prefetch_param_st { + double prefetch_bw; + unsigned int flip_bytes; +}; + +struct _vcs_dpi_display_pipe_clock_st { + double dcfclk_mhz; + double dispclk_mhz; + double dppclk_mhz[4]; + unsigned char dppclk_div[4]; +}; + +struct _vcs_dpi_display_arb_params_st { + int max_req_outstanding; + int min_req_outstanding; + int sat_level_us; +}; + +struct _vcs_dpi_mode_evaluation_st { + int voltage_override; +}; + +#endif /*__DISPLAY_MODE_STRUCTS_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c new file mode 100644 index 000000000000..3b4ee74527f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -0,0 +1,2326 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_mode_support.h" +#include "display_mode_lib.h" + +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes) +{ + struct _vcs_dpi_ip_params_st *ip; + struct _vcs_dpi_soc_bounding_box_st *soc; + struct _vcs_dpi_mode_evaluation_st *me; + struct dml_ms_internal_vars *v; + int num_planes, i, j, ij, k, ijk; + + ip = &(mode_lib->ip); + soc = &(mode_lib->soc); + me = &(mode_lib->me); + v = &(mode_lib->vars); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); + + //instantiating variables to zero + v->MacroTileBlockWidthC = 0; + v->SwathWidthGranularityC = 0; + + v->DCFCLKPerState[5] = 0; + v->DCFCLKPerState[4] = 0; + v->DCFCLKPerState[3] = 0; + v->DCFCLKPerState[2] = 0; + v->DCFCLKPerState[1] = 0; + v->DCFCLKPerState[0] = 0; + + if (soc->vmin.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; + } + + if (soc->vmid.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; + } + + if (soc->vnom.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; + } + + if (soc->vmax.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; + } + + v->FabricAndDRAMBandwidthPerState[5] = 0; + v->FabricAndDRAMBandwidthPerState[4] = 0; + v->FabricAndDRAMBandwidthPerState[3] = 0; + v->FabricAndDRAMBandwidthPerState[2] = 0; + v->FabricAndDRAMBandwidthPerState[1] = 0; + v->FabricAndDRAMBandwidthPerState[0] = 0; + + if (soc->vmin.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; + } + + if (soc->vmid.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; + } + + if (soc->vnom.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; + } + + if (soc->vmax.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; + } + + v->PHYCLKPerState[5] = 0; + v->PHYCLKPerState[4] = 0; + v->PHYCLKPerState[3] = 0; + v->PHYCLKPerState[2] = 0; + v->PHYCLKPerState[1] = 0; + v->PHYCLKPerState[0] = 0; + + if (soc->vmin.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; + } + + if (soc->vmid.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; + } + + if (soc->vnom.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; + } + + if (soc->vmax.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; + } + + v->MaxDispclk[5] = 0; + v->MaxDispclk[4] = 0; + v->MaxDispclk[3] = 0; + v->MaxDispclk[2] = 0; + v->MaxDispclk[1] = 0; + v->MaxDispclk[0] = 0; + + if (soc->vmin.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmin.dispclk_mhz; + v->MaxDispclk[4] = soc->vmin.dispclk_mhz; + v->MaxDispclk[3] = soc->vmin.dispclk_mhz; + v->MaxDispclk[2] = soc->vmin.dispclk_mhz; + v->MaxDispclk[1] = soc->vmin.dispclk_mhz; + v->MaxDispclk[0] = soc->vmin.dispclk_mhz; + } + + if (soc->vmid.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmid.dispclk_mhz; + v->MaxDispclk[4] = soc->vmid.dispclk_mhz; + v->MaxDispclk[3] = soc->vmid.dispclk_mhz; + v->MaxDispclk[2] = soc->vmid.dispclk_mhz; + v->MaxDispclk[1] = soc->vmid.dispclk_mhz; + } + + if (soc->vnom.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vnom.dispclk_mhz; + v->MaxDispclk[4] = soc->vnom.dispclk_mhz; + v->MaxDispclk[3] = soc->vnom.dispclk_mhz; + v->MaxDispclk[2] = soc->vnom.dispclk_mhz; + } + + if (soc->vmax.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmax.dispclk_mhz; + v->MaxDispclk[4] = soc->vmax.dispclk_mhz; + v->MaxDispclk[3] = soc->vmax.dispclk_mhz; + } + + v->MaxDppclk[5] = 0; + v->MaxDppclk[4] = 0; + v->MaxDppclk[3] = 0; + v->MaxDppclk[2] = 0; + v->MaxDppclk[1] = 0; + v->MaxDppclk[0] = 0; + + if (soc->vmin.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmin.dppclk_mhz; + v->MaxDppclk[4] = soc->vmin.dppclk_mhz; + v->MaxDppclk[3] = soc->vmin.dppclk_mhz; + v->MaxDppclk[2] = soc->vmin.dppclk_mhz; + v->MaxDppclk[1] = soc->vmin.dppclk_mhz; + v->MaxDppclk[0] = soc->vmin.dppclk_mhz; + } + + if (soc->vmid.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmid.dppclk_mhz; + v->MaxDppclk[4] = soc->vmid.dppclk_mhz; + v->MaxDppclk[3] = soc->vmid.dppclk_mhz; + v->MaxDppclk[2] = soc->vmid.dppclk_mhz; + v->MaxDppclk[1] = soc->vmid.dppclk_mhz; + } + + if (soc->vnom.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vnom.dppclk_mhz; + v->MaxDppclk[4] = soc->vnom.dppclk_mhz; + v->MaxDppclk[3] = soc->vnom.dppclk_mhz; + v->MaxDppclk[2] = soc->vnom.dppclk_mhz; + } + + if (soc->vmax.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmax.dppclk_mhz; + v->MaxDppclk[4] = soc->vmax.dppclk_mhz; + v->MaxDppclk[3] = soc->vmax.dppclk_mhz; + } + + if (me->voltage_override == dm_vmax) { + v->VoltageOverrideLevel = NumberOfStates - 1; + } else if (me->voltage_override == dm_vnom) { + v->VoltageOverrideLevel = NumberOfStates - 2; + } else if (me->voltage_override == dm_vmid) { + v->VoltageOverrideLevel = NumberOfStates - 3; + } else { + v->VoltageOverrideLevel = 0; + } + + // Scale Ratio Support Check + + v->ScaleRatioSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio + || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio + || scale_ratio_depth.hscl_ratio > scale_taps.htaps + || scale_ratio_depth.vscl_ratio > scale_taps.vtaps + || (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16 + && ((scale_ratio_depth.hscl_ratio / 2 + > scale_taps.htaps_c) + || (scale_ratio_depth.vscl_ratio / 2 + > scale_taps.vtaps_c)))) + + { + v->ScaleRatioSupport = 0; + } + } + + // Source Format, Pixel Format and Scan Support Check + + v->SourceFormatPixelAndScanSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) + || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x + || src.sw_mode == dm_sw_var_d + || src.sw_mode == dm_sw_var_d_x) + && (src.source_format != dm_444_64))) { + v->SourceFormatPixelAndScanSupport = 0; + } + } + + // Bandwidth Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_scan == dm_horz) { + v->SwathWidthYSingleDPP[k] = src.viewport_width; + } else { + v->SwathWidthYSingleDPP[k] = src.viewport_height; + } + + if (src.source_format == dm_444_64) { + v->BytePerPixelInDETY[k] = 8; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_32) { + v->BytePerPixelInDETY[k] = 4; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_16) { + v->BytePerPixelInDETY[k] = 2; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_420_8) { + v->BytePerPixelInDETY[k] = 1; + v->BytePerPixelInDETC[k] = 2; + } else { + v->BytePerPixelInDETY[k] = 4.00 / 3.00; + v->BytePerPixelInDETC[k] = 8.00 / 3.00; + } + } + + v->TotalReadBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + + v->ReadBandwidth[k] = + v->SwathWidthYSingleDPP[k] + * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + * scale_ratio_depth.vscl_ratio + + (dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) / 2) + * (scale_ratio_depth.vscl_ratio + / 2)) + / (dest.htotal / dest.pixel_rate_mhz); + + if (src.dcc == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } + + if (ip->pte_enable == 1 && src.source_scan != dm_horz + && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); + } else if (ip->pte_enable == 1 && src.source_scan == dm_horz + && (src.source_format == dm_444_64 || src.source_format == dm_444_32) + && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } else if (ip->pte_enable == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); + } + + v->TotalReadBandwidthConsumedGBytePerSecond = + v->TotalReadBandwidthConsumedGBytePerSecond + + v->ReadBandwidth[k] / 1000; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 4; + } else if (dout.output_type == dm_wb) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 1.5; + } else { + v->WriteBandwidth[k] = 0; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = + v->TotalWriteBandwidthConsumedGBytePerSecond + + v->WriteBandwidth[k] / 1000; + } + + v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond + + v->TotalWriteBandwidthConsumedGBytePerSecond; + + v->DCCEnabledInAnyPlane = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.dcc == 1) { + v->DCCEnabledInAnyPlane = 1; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent / 100); + + v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000); + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) + && (v->TotalBandwidthConsumedGBytePerSecond * 1000 + <= v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent + / 100)) { + v->BandwidthSupport[i] = 1; + } else { + v->BandwidthSupport[i] = 0; + } + } + + // Writeback Latency support check + + v->WritebackLatencySupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444 + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) + > ((ip->writeback_luma_buffer_size_kbytes + + ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } else if (dout.output_type == dm_wb + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) + > (dml_min( + ip->writeback_luma_buffer_size_kbytes, + 2 + * ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } + } + + // Re-ordering Buffer Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = + (soc->round_trip_ping_latency_dcfclk_cycles + 32) + / v->DCFCLKPerState[i] + + soc->urgent_out_of_order_return_per_channel_bytes + * soc->num_chans + / v->ReturnBWPerState[i]; + + if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 + / v->ReturnBWPerState[i] + > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { + v->ROBSupport[i] = 1; + } else { + v->ROBSupport[i] = 0; + } + } + + // Display IO Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_format == dm_420) { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; + } else { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3; + } + + if (dout.output_type == dm_hdmi) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; + } else if (dout.output_type == dm_dp) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; + } else { + v->RequiredPHYCLK[k] = 0; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->DIOSupport[i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + + if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) + || (dout.output_type == dm_hdmi + && v->RequiredPHYCLK[k] > 600)) { + v->DIOSupport[i] = 0; + } + } + } + + // Total Available Writeback Support Check + + v->TotalNumberOfActiveWriteback = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb) { + v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; + } + } + + if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { + v->TotalAvailableWritebackSupport = 1; + } else { + v->TotalAvailableWritebackSupport = 0; + } + + // Maximum DISPCLK/DPPCLK Support check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (scale_ratio_depth.hscl_ratio > 1) { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio + / dml_ceil_ex(scale_taps.htaps / 6, 1)); + } else { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->PSCL_FACTOR_CHROMA[k] = 0; + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + scale_taps.vtaps / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + dml_max( + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k], + 1)); + + } else { + if (scale_ratio_depth.hscl_ratio / 2 > 1) { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio / 2 + / dml_ceil_ex( + scale_taps.htaps_c + / 6, + 1)); + } else { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + dml_max( + scale_taps.vtaps + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k]), + dml_max( + dml_max( + scale_taps.vtaps_c + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio + / 2), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / 4 + / v->PSCL_FACTOR_CHROMA[k]), + 1)); + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + } else if (src.source_format == dm_444_64) { + v->Read256BlockHeightY[k] = 4; + } else { + v->Read256BlockHeightY[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockHeightC[k] = 0; + v->Read256BlockWidthC[k] = 0; + } else { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + v->Read256BlockHeightC[k] = 1; + } else if (src.source_format == dm_420_8) { + v->Read256BlockHeightY[k] = 16; + v->Read256BlockHeightC[k] = 8; + } else { + v->Read256BlockHeightY[k] = 8; + v->Read256BlockHeightC[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->Read256BlockHeightC[k]; + } + + if (src.source_scan == dm_horz) { + v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; + } else { + v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; + } + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear + || (src.source_format == dm_444_64 + && (src.sw_mode == dm_sw_4kb_s + || src.sw_mode + == dm_sw_4kb_s_x + || src.sw_mode + == dm_sw_64kb_s + || src.sw_mode + == dm_sw_64kb_s_t + || src.sw_mode + == dm_sw_64kb_s_x + || src.sw_mode + == dm_sw_var_s + || src.sw_mode + == dm_sw_var_s_x) + && src.source_scan == dm_horz)) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + if (src.sw_mode == dm_sw_linear) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + } + } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } + } + + if (src.sw_mode == dm_sw_linear) { + v->MaximumSwathWidth = 8192; + } else { + v->MaximumSwathWidth = 5120; + } + + v->NumberOfDPPRequiredForDETSize = + dml_ceil_ex( + v->SwathWidthYSingleDPP[k] + / dml_min( + v->MaximumSwathWidth, + ip->det_buffer_size_kbytes + * 1024 + / 2 + / (v->BytePerPixelInDETY[k] + * v->MinSwathHeightY[k] + + v->BytePerPixelInDETC[k] + / 2 + * v->MinSwathHeightC[k])), + 1); + + if (v->BytePerPixelInDETC[k] == 0) { + v->NumberOfDPPRequiredForLBSize = + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1); + } else { + v->NumberOfDPPRequiredForLBSize = + dml_max( + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1), + dml_ceil_ex( + (scale_taps.vtaps_c + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio + / 2, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1)); + } + + v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( + v->NumberOfDPPRequiredForDETSize, + v->NumberOfDPPRequiredForLBSize); + + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->MinDispclkUsingSingleDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i]) + && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + } else if (v->MinDispclkUsingDualDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i])) { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = + 0; + } + + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + + i] + v->NoOfDPP[ijk]; + } + + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + > ip->max_num_dpp) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + if (v->MinDispclkUsingSingleDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + if (v->MinDispclkUsingDualDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j + * NumberOfStatesPlusTwo + i] + + v->NoOfDPP[ijk]; + } + } + } + } + + // Viewport Size Check + + v->ViewportSizeSupport = 1; + + for (k = 0; k < num_planes; k++) { + if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { + v->ViewportSizeSupport = 0; + } + } + + // Total Available Pipes Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + <= ip->max_num_dpp) { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; + } else { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; + } + } + } + + // Urgent Latency Support Check + + for (j = 0; j < 2; j++) { + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + ij = j * NumberOfStatesPlusTwo + i; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] + / v->NoOfDPP[ijk]; + + v->SwathWidthGranularityY = 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MaxSwathHeightY[k]; + v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] - 1, + v->SwathWidthGranularityY) + + v->SwathWidthGranularityY) + * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesY, + 256) + 256; + } + if (v->MaxSwathHeightC[k] > 0) { + v->SwathWidthGranularityC = 256 + / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->MaxSwathHeightC[k]; + } + v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] / 2 - 1, + v->SwathWidthGranularityC) + + v->SwathWidthGranularityC) + * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesC, + 256) + 256; + } + + if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC + <= ip->det_buffer_size_kbytes * 1024 / 2) { + v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; + } else { + v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + + v->LinesInDETChroma = 0; + } else if (v->SwathHeightYPerState[ijk] + <= v->SwathHeightCPerState[ijk]) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETC[k] + / (v->SwathWidthYPerState[ijk] / 2); + } else { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 + / 3 / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 + / v->BytePerPixelInDETY[k] + / (v->SwathWidthYPerState[ijk] / 2); + } + + v->EffectiveLBLatencyHidingSourceLinesLuma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1)), + 1)) + - (scale_taps.vtaps - 1); + + v->EffectiveLBLatencyHidingSourceLinesChroma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1)), + 1)) + - (scale_taps.vtaps_c - 1); + + v->EffectiveDETLBLinesLuma = + dml_floor_ex( + v->LinesInDETLuma + + dml_min( + v->LinesInDETLuma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETY[k] + * v->PSCL_FACTOR[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesLuma), + v->SwathHeightYPerState[ijk]); + + v->EffectiveDETLBLinesChroma = + dml_floor_ex( + v->LinesInDETChroma + + dml_min( + v->LinesInDETChroma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETC[k] + * v->PSCL_FACTOR_CHROMA[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesChroma), + v->SwathHeightCPerState[ijk]); + + if (v->BytePerPixelInDETC[k] == 0) { + v->UrgentLatencySupportUsPerState[ijk] = + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]); + } else { + v->UrgentLatencySupportUsPerState[ijk] = + dml_min( + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]), + v->EffectiveDETLBLinesChroma + * (dest.htotal + / dest.pixel_rate_mhz) + / (scale_ratio_depth.vscl_ratio + / 2) + - v->EffectiveDETLBLinesChroma + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk])); + } + + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->UrgentLatencySupport[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->UrgentLatencySupportUsPerState[ijk] + < soc->urgent_latency_us / 1) { + v->UrgentLatencySupport[ij] = 0; + } + } + } + } + + // Prefetch Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->TotalNumberOfDCCActiveDPP[ij] = 0; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->TotalNumberOfDCCActiveDPP[ij] = + v->TotalNumberOfDCCActiveDPP[ij] + + v->NoOfDPP[ijk]; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = 8; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = dml_max( + v->ProjectedDCFCLKDeepSleep, + dest.pixel_rate_mhz / 16); + if (v->BytePerPixelInDETC[k] == 0) { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } else { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * scale_ratio_depth.hscl_ratio + / 2 + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * v->PSCL_FACTOR_CHROMA[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; + v->MetaReqWidthY = 64 * 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MetaReqHeightY; + v->MetaSurfaceWidthY = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] - 1, + v->MetaReqWidthY) + v->MetaReqWidthY; + v->MetaSurfaceHeightY = dml_ceil_ex( + src.viewport_height - 1, + v->MetaReqHeightY) + v->MetaReqHeightY; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameY = + (dml_ceil_ex( + (v->MetaSurfaceWidthY + * v->MetaSurfaceHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) * 64; + } else { + v->MetaPteBytesPerFrameY = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesY = + v->MetaSurfaceWidthY + * v->MetaReqHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } else { + v->MetaRowBytesY = + v->MetaSurfaceHeightY + * v->MetaReqWidthY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } + } else { + v->MetaPteBytesPerFrameY = 0; + v->MetaRowBytesY = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesY = 256; + v->MacroTileBlockHeightY = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesY = 4096; + v->MacroTileBlockHeightY = 4 + * v->Read256BlockHeightY[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesY = 64 * 1024; + v->MacroTileBlockHeightY = 16 + * v->Read256BlockHeightY[k]; + } else { + v->MacroTileBlockSizeBytesY = 256 * 1024; + v->MacroTileBlockHeightY = 32 + * v->Read256BlockHeightY[k]; + } + if (v->MacroTileBlockSizeBytesY <= 65536) { + v->DataPTEReqHeightY = v->MacroTileBlockHeightY; + } else { + v->DataPTEReqHeightY = 16 + * v->Read256BlockHeightY[k]; + } + v->DataPTEReqWidthY = 4096 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->DataPTEReqHeightY * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthY + / (src.viewport_width + / v->NoOfDPP[ijk]), + 2), + 1))) + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_height + - 1) + / v->DataPTEReqHeightY, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowY = 0; + } + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + if (src.dcc == 1) { + v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; + v->MetaReqWidthC = + 64 * 256 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MetaReqHeightC; + v->MetaSurfaceWidthC = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] + / 2 - 1, + v->MetaReqWidthC) + + v->MetaReqWidthC; + v->MetaSurfaceHeightC = dml_ceil_ex( + src.viewport_height / 2 - 1, + v->MetaReqHeightC) + + v->MetaReqHeightC; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameC = + (dml_ceil_ex( + (v->MetaSurfaceWidthC + * v->MetaSurfaceHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) + * 64; + } else { + v->MetaPteBytesPerFrameC = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesC = + v->MetaSurfaceWidthC + * v->MetaReqHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } else { + v->MetaRowBytesC = + v->MetaSurfaceHeightC + * v->MetaReqWidthC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } + } else { + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesC = 256; + v->MacroTileBlockHeightC = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesC = 4096; + v->MacroTileBlockHeightC = 4 + * v->Read256BlockHeightC[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesC = 64 * 1024; + v->MacroTileBlockHeightC = 16 + * v->Read256BlockHeightC[k]; + } else { + v->MacroTileBlockSizeBytesC = 256 * 1024; + v->MacroTileBlockHeightC = 32 + * v->Read256BlockHeightC[k]; + } + v->MacroTileBlockWidthC = + v->MacroTileBlockSizeBytesC + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MacroTileBlockHeightC; + if (v->MacroTileBlockSizeBytesC <= 65536) { + v->DataPTEReqHeightC = + v->MacroTileBlockHeightC; + } else { + v->DataPTEReqHeightC = 16 + * v->Read256BlockHeightC[k]; + } + v->DataPTEReqWidthC = + 4096 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->DataPTEReqHeightC + * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthC + / (src.viewport_width + / v->NoOfDPP[ijk] + / 2), + 2), + 1))) + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_height + / 2 + - 1) + / v->DataPTEReqHeightC, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowC = 0; + } + } else { + v->DPTEBytesPerRowC = 0; + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; + v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY + + v->MetaPteBytesPerFrameC; + v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; + + v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio) + / 2.0; + v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); + v->MaxNumSwY[k] = dml_ceil_ex( + (v->PrefillY[k] - 1.0) + / v->SwathHeightYPerState[ijk], + 1) + 1.0; + + if (v->PrefillY[k] > 1) { + v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } else { + v->MaxPartialSwY = ((int) (v->PrefillY[k] + + v->SwathHeightYPerState[ijk] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } + v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); + + v->PrefetchLinesY[k] = v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + v->VInitC = + (scale_ratio_depth.vscl_ratio / 2 + + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio + / 2) / 2.0; + v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); + v->MaxNumSwC[k] = + dml_ceil_ex( + (v->PrefillC[k] - 1.0) + / v->SwathHeightCPerState[ijk], + 1) + 1.0; + if (v->PrefillC[k] > 1) { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } else { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] + + v->SwathHeightCPerState[ijk] + - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } + v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); + + v->PrefetchLinesC[k] = v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk] + + v->MaxPartialSwC; + } else { + v->PrefetchLinesC[k] = 0; + } + + v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz + / (v->RequiredDISPCLK[ij] / (j + 1)) + + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; + if (v->NoOfDPP[ijk] > 1) { + v->dst_x_after_scaler = v->dst_x_after_scaler + + dest.recout_width / 2.0; + } + + if (dout.output_format == dm_420) { + v->dst_y_after_scaler = 1; + } else { + v->dst_y_after_scaler = 0; + } + + v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; + + v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); + v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters + * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) + + 3 / v->RequiredDISPCLK[ij]); + v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep + + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) + + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; + v->VReadyOffset = + dml_max( + 150 + / (v->RequiredDISPCLK[ij] + / (j + + 1)), + v->TotalRepeaterDelay + + 20 + / v->ProjectedDCFCLKDeepSleep + + 10 + / (v->RequiredDISPCLK[ij] + / (j + + 1))) + * dest.pixel_rate_mhz; + + v->TimeSetup = + (v->VUpdateOffset + v->VUpdateWidth + + v->VReadyOffset) + / dest.pixel_rate_mhz; + + v->ExtraLatency = + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] + + (v->TotalNumberOfActiveDPP[ij] + * ip->pixel_chunk_size_kbytes + + v->TotalNumberOfDCCActiveDPP[ij] + * ip->meta_chunk_size_kbytes) + * 1024 + / v->ReturnBWPerState[i]; + + if (ip->pte_enable == 1) { + v->ExtraLatency = v->ExtraLatency + + v->TotalNumberOfActiveDPP[ij] + * ip->pte_chunk_size_kbytes + * 1024 + / v->ReturnBWPerState[i]; + } + + if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == 1) { + v->MaximumVStartup = dest.vtotal - dest.vactive - 1; + } else { + v->MaximumVStartup = dest.vsync_plus_back_porch - 1; + } + + v->LineTimesForPrefetch[k] = + v->MaximumVStartup + - soc->urgent_latency_us + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->TimeCalc + v->TimeSetup) + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->dst_y_after_scaler + + v->dst_x_after_scaler + / dest.htotal); + + v->LineTimesForPrefetch[k] = dml_floor_ex( + 4.0 * (v->LineTimesForPrefetch[k] + 0.125), + 1) / 4; + + v->PrefetchBW[k] = + (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] + + 2 * v->DPTEBytesPerRow[k] + + v->PrefetchLinesY[k] + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2)) + / (v->LineTimesForPrefetch[k] + * dest.htotal + / dest.pixel_rate_mhz); + } + + v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; + + for (k = 0; k < num_planes; k++) { + v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip + - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); + } + + v->TotalImmediateFlipBytes = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes + + v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]; + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (ip->pte_enable == 1 && src.dcc == 1) { + v->TimeForMetaPTEWithImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->MetaPTEBytesPerFrame[k] + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + v->ExtraLatency, + dml_max( + soc->urgent_latency_us, + dest.htotal + / dest.pixel_rate_mhz + / 4)))); + + v->TimeForMetaPTEWithoutImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->ExtraLatency, + dest.htotal + / dest.pixel_rate_mhz + / 4)); + } else { + v->TimeForMetaPTEWithImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + } + + if (ip->pte_enable == 1 || src.dcc == 1) { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + dml_max( + v->ExtraLatency, + 2 + * soc->urgent_latency_us)))); + + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency)); + } else { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithImmediateFlip); + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithoutImmediateFlip); + } + + v->LinesForMetaPTEWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaPTEWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; + + v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithoutImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; + + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = 999999; + v->VRatioPreCWithImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + 999999; + } + + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithoutImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithoutImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithoutImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; + v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) + + dml_max( + v->MetaPTEBytesPerFrame[k] + / (v->LinesForMetaPTEWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz), + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz)); + } else { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + } + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + + v->PrefetchSupportedWithImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + + v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (((src.source_format != dm_420_8 + && src.source_format != dm_420_10) + && (v->VRatioPreYWithImmediateFlip[ijk] > 4 + || v->VRatioPreCWithImmediateFlip[ijk] + > 4)) + || ((src.source_format == dm_420_8 + || src.source_format == dm_420_10) + && (v->VRatioPreYWithoutImmediateFlip[ijk] + > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] + > 4))) { + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + // Mode Support, Voltage State and SOC Configuration + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 + && v->ViewportSizeSupport == 1 + && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 + && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 + && v->DISPCLK_DPPCLK_Support[ij] == 1 + && v->TotalAvailablePipesSupport[ij] == 1 + && v->TotalAvailableWritebackSupport == 1 + && v->WritebackLatencySupport == 1) { + if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] + == 1) { + v->ModeSupportWithImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + } + if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] + == 1) { + v->ModeSupportWithoutImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithImmediateFlip = i; + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithoutImmediateFlip = i; + } + } + + if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { + v->ImmediateFlipSupported = 0; + v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; + } else { + v->ImmediateFlipSupported = 1; + v->VoltageLevel = v->VoltageLevelWithImmediateFlip; + } + + v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; + v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; + + for (j = 0; j < 2; j++) { + v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + (int) v->VoltageLevel]; + for (k = 0; k < num_planes; k++) { + v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + + ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); + + return (v->VoltageLevel); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h new file mode 100644 index 000000000000..ead4942f998c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h @@ -0,0 +1,199 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_MODE_SUPPORT_H__ +#define __DISPLAY_MODE_SUPPORT_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +#define NumberOfStates 4 +#define NumberOfStatesPlusTwo (NumberOfStates+2) + +struct dml_ms_internal_vars { + double ScaleRatioSupport; + double SourceFormatPixelAndScanSupport; + double TotalReadBandwidthConsumedGBytePerSecond; + double TotalWriteBandwidthConsumedGBytePerSecond; + double TotalBandwidthConsumedGBytePerSecond; + double DCCEnabledInAnyPlane; + double ReturnBWToDCNPerState; + double CriticalPoint; + double WritebackLatencySupport; + double RequiredOutputBW; + double TotalNumberOfActiveWriteback; + double TotalAvailableWritebackSupport; + double MaximumSwathWidth; + double NumberOfDPPRequiredForDETSize; + double NumberOfDPPRequiredForLBSize; + double MinDispclkUsingSingleDPP; + double MinDispclkUsingDualDPP; + double ViewportSizeSupport; + double SwathWidthGranularityY; + double RoundedUpMaxSwathSizeBytesY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesC; + double LinesInDETLuma; + double LinesInDETChroma; + double EffectiveLBLatencyHidingSourceLinesLuma; + double EffectiveLBLatencyHidingSourceLinesChroma; + double EffectiveDETLBLinesLuma; + double EffectiveDETLBLinesChroma; + double ProjectedDCFCLKDeepSleep; + double MetaReqHeightY; + double MetaReqWidthY; + double MetaSurfaceWidthY; + double MetaSurfaceHeightY; + double MetaPteBytesPerFrameY; + double MetaRowBytesY; + double MacroTileBlockSizeBytesY; + double MacroTileBlockHeightY; + double DataPTEReqHeightY; + double DataPTEReqWidthY; + double DPTEBytesPerRowY; + double MetaReqHeightC; + double MetaReqWidthC; + double MetaSurfaceWidthC; + double MetaSurfaceHeightC; + double MetaPteBytesPerFrameC; + double MetaRowBytesC; + double MacroTileBlockSizeBytesC; + double MacroTileBlockHeightC; + double MacroTileBlockWidthC; + double DataPTEReqHeightC; + double DataPTEReqWidthC; + double DPTEBytesPerRowC; + double VInitY; + double MaxPartialSwY; + double VInitC; + double MaxPartialSwC; + double dst_x_after_scaler; + double dst_y_after_scaler; + double TimeCalc; + double VUpdateOffset; + double TotalRepeaterDelay; + double VUpdateWidth; + double VReadyOffset; + double TimeSetup; + double ExtraLatency; + double MaximumVStartup; + double BWAvailableForImmediateFlip; + double TotalImmediateFlipBytes; + double TimeForMetaPTEWithImmediateFlip; + double TimeForMetaPTEWithoutImmediateFlip; + double TimeForMetaAndDPTERowWithImmediateFlip; + double TimeForMetaAndDPTERowWithoutImmediateFlip; + double LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + double LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + double MaximumReadBandwidthWithPrefetchWithImmediateFlip; + double MaximumReadBandwidthWithPrefetchWithoutImmediateFlip; + double VoltageOverrideLevel; + double VoltageLevelWithImmediateFlip; + double VoltageLevelWithoutImmediateFlip; + double ImmediateFlipSupported; + double VoltageLevel; + double DCFCLK; + double FabricAndDRAMBandwidth; + double SwathWidthYSingleDPP[DC__NUM_PIPES__MAX]; + double BytePerPixelInDETY[DC__NUM_PIPES__MAX]; + double BytePerPixelInDETC[DC__NUM_PIPES__MAX]; + double ReadBandwidth[DC__NUM_PIPES__MAX]; + double WriteBandwidth[DC__NUM_PIPES__MAX]; + double DCFCLKPerState[NumberOfStatesPlusTwo]; + double FabricAndDRAMBandwidthPerState[NumberOfStatesPlusTwo]; + double ReturnBWPerState[NumberOfStatesPlusTwo]; + double BandwidthSupport[NumberOfStatesPlusTwo]; + double UrgentRoundTripAndOutOfOrderLatencyPerState[NumberOfStatesPlusTwo]; + double ROBSupport[NumberOfStatesPlusTwo]; + double RequiredPHYCLK[DC__NUM_PIPES__MAX]; + double DIOSupport[NumberOfStatesPlusTwo]; + double PHYCLKPerState[NumberOfStatesPlusTwo]; + double PSCL_FACTOR[DC__NUM_PIPES__MAX]; + double PSCL_FACTOR_CHROMA[DC__NUM_PIPES__MAX]; + double MinDPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; + double Read256BlockHeightY[DC__NUM_PIPES__MAX]; + double Read256BlockWidthY[DC__NUM_PIPES__MAX]; + double Read256BlockHeightC[DC__NUM_PIPES__MAX]; + double Read256BlockWidthC[DC__NUM_PIPES__MAX]; + double MaxSwathHeightY[DC__NUM_PIPES__MAX]; + double MaxSwathHeightC[DC__NUM_PIPES__MAX]; + double MinSwathHeightY[DC__NUM_PIPES__MAX]; + double MinSwathHeightC[DC__NUM_PIPES__MAX]; + double NumberOfDPPRequiredForDETAndLBSize[DC__NUM_PIPES__MAX]; + double TotalNumberOfActiveDPP[NumberOfStatesPlusTwo * 2]; + double RequiredDISPCLK[NumberOfStatesPlusTwo * 2]; + double DISPCLK_DPPCLK_Support[NumberOfStatesPlusTwo * 2]; + double MaxDispclk[NumberOfStatesPlusTwo]; + double MaxDppclk[NumberOfStatesPlusTwo]; + double NoOfDPP[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double TotalAvailablePipesSupport[NumberOfStatesPlusTwo * 2]; + double SwathWidthYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double SwathHeightYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double SwathHeightCPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double DETBufferSizeYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double UrgentLatencySupportUsPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double UrgentLatencySupport[NumberOfStatesPlusTwo * 2]; + double TotalNumberOfDCCActiveDPP[NumberOfStatesPlusTwo * 2]; + double DPTEBytesPerRow[DC__NUM_PIPES__MAX]; + double MetaPTEBytesPerFrame[DC__NUM_PIPES__MAX]; + double MetaRowBytes[DC__NUM_PIPES__MAX]; + double PrefillY[DC__NUM_PIPES__MAX]; + double MaxNumSwY[DC__NUM_PIPES__MAX]; + double PrefetchLinesY[DC__NUM_PIPES__MAX]; + double PrefillC[DC__NUM_PIPES__MAX]; + double MaxNumSwC[DC__NUM_PIPES__MAX]; + double PrefetchLinesC[DC__NUM_PIPES__MAX]; + double LineTimesForPrefetch[DC__NUM_PIPES__MAX]; + double PrefetchBW[DC__NUM_PIPES__MAX]; + double LinesForMetaPTEWithImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaPTEWithoutImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaAndDPTERowWithImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaAndDPTERowWithoutImmediateFlip[DC__NUM_PIPES__MAX]; + double VRatioPreYWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double VRatioPreCWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double RequiredPrefetchPixelDataBWWithImmediateFlip[NumberOfStatesPlusTwo * 2 + * DC__NUM_PIPES__MAX]; + double VRatioPreYWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double VRatioPreCWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double RequiredPrefetchPixelDataBWWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 + * DC__NUM_PIPES__MAX]; + double PrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double PrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double VRatioInPrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double VRatioInPrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double ModeSupportWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double ModeSupportWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double RequiredDISPCLKPerRatio[2]; + double DPPPerPlanePerRatio[2 * DC__NUM_PIPES__MAX]; + double DISPCLK_DPPCLK_SupportPerRatio[2]; + struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; +}; + +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c new file mode 100644 index 000000000000..2e4dc57cafa0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c @@ -0,0 +1,367 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_pipe_clocks.h" +#include "display_mode_lib.h" +#include "soc_bounding_box.h" + +static enum voltage_state power_state( + struct display_mode_lib *mode_lib, + double dispclk, + double dppclk) +{ + enum voltage_state state1; + enum voltage_state state2; + + if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) + state1 = dm_vmin; + else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) + state1 = dm_vnom; + else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) + state1 = dm_vmax; + else + state1 = dm_vmax_exceeded; + + if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) + state2 = dm_vmin; + else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) + state2 = dm_vnom; + else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) + state2 = dm_vmax; + else + state2 = dm_vmax_exceeded; + + if (state1 > state2) + return state1; + else + return state2; +} + +static unsigned int dpp_in_grp( + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + unsigned int hsplit_grp) +{ + unsigned int num_dpp = 0; + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.is_hsplit) { + if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { + num_dpp++; + } + } + } + + if (0 == num_dpp) + num_dpp = 1; + + return num_dpp; +} + +static void calculate_pipe_clk_requirement( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp, + double *dppclk, + double *dispclk, + bool *dppdiv) +{ + double pscl_throughput = 0.0; + double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; + double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; + double max_htaps = e2e->pipe.scale_taps.htaps; + double max_vtaps = e2e->pipe.scale_taps.vtaps; + double dpp_clock_divider = (double) num_dpp_in_grp; + double dispclk_dppclk_ratio; + double dispclk_ramp_margin_percent; + + if (max_hratio > 1.0) { + double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) + / dml_ceil(max_htaps / 6.0); + pscl_throughput = dml_min( + pscl_to_lb, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } else { + pscl_throughput = dml_min( + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } + + DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); + DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); + *dppclk = dml_max( + max_vtaps / 6.0 * dml_min(1.0, max_hratio), + max_hratio * max_vratio / pscl_throughput); + DTRACE("pixel rate multiplier: %f", *dppclk); + *dppclk = dml_max(*dppclk, 1.0); + DTRACE("pixel rate multiplier clamped: %f", *dppclk); + *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; + + *dppclk = *dppclk / dpp_clock_divider; + DTRACE("dppclk after split: %f", *dppclk); + + if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { + dispclk_dppclk_ratio = 2.0; + *dppdiv = true; + } else { + dispclk_dppclk_ratio = 1.0; + *dppdiv = false; + } + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + /* Comment this out because of Gabes possible bug in spreadsheet, + * just to make other cases evident during debug + * + *if(e2e->clks_cfg.voltage == dm_vmax) + * dispclk_ramp_margin_percent = 0.0; + */ + + /* account for ramping margin and downspread */ + *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + return; +} + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp) +{ + double dppclk = 0; + double dispclk = 0; + bool dppdiv = 0; + + calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); + + if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { + return false; + } + + return true; +} + +static void get_plane_clks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dppclks, + double *dispclks, + bool *dppdiv) +{ + /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated + * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to + * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently + * and we would expect the same result on any split pipes, which would be handled + */ + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + double num_dpp_in_grp; + double dispclk_ramp_margin_percent; + double dispclk_margined; + + if (e2e[i].pipe.src.is_hsplit) + num_dpp_in_grp = (double) dpp_in_grp( + e2e, + num_pipes, + e2e[i].pipe.src.hsplit_grp); + else + num_dpp_in_grp = 1; + + calculate_pipe_clk_requirement( + mode_lib, + &e2e[i], + num_dpp_in_grp, + &dppclks[i], + &dispclks[i], + &dppdiv[i]); + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); + + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > power_state(mode_lib, dispclk_margined, dispclk_margined) + && dispclk_margined > dppclks[i]) { + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > e2e[0].clks_cfg.voltage) { + dispclks[i] = dispclk_margined; + dppclks[i] = dispclk_margined; + dppdiv[i] = false; + } + } + + DTRACE("p%d: dispclk: %f", i, dispclks[i]); + } +} + +static void get_dcfclk( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dcfclk_mhz) +{ + double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; + double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; + double swath_width_y[DC__NUM_PIPES__MAX]; + unsigned int i; + double total_read_bandwidth_gbps = 0.0; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.source_scan == dm_horz) { + swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; + } else { + swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; + } + + switch (e2e[i].pipe.src.source_format) { + case dm_444_64: + bytes_per_pixel_det_y[i] = 8.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_32: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_16: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_8: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_10: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_420_8: + bytes_per_pixel_det_y[i] = 1.0; + bytes_per_pixel_det_c[i] = 2.0; + break; + case dm_420_10: + bytes_per_pixel_det_y[i] = 4.0 / 3.0; + bytes_per_pixel_det_c[i] = 8.0 / 3.0; + break; + default: + BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ + } + } + + for (i = 0; i < num_pipes; i++) { + double read_bandwidth_plane_mbps = 0.0; + read_bandwidth_plane_mbps = (double) swath_width_y[i] + * ((double) bytes_per_pixel_det_y[i] + + (double) bytes_per_pixel_det_c[i] / 2.0) + / ((double) e2e[i].pipe.dest.htotal + / (double) e2e[i].pipe.dest.pixel_rate_mhz) + * e2e[i].pipe.scale_ratio_depth.vscl_ratio; + + if (e2e[i].pipe.src.dcc) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); + } + + if (e2e[i].pipe.src.vm) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); + } + + total_read_bandwidth_gbps = total_read_bandwidth_gbps + + read_bandwidth_plane_mbps / 1000.0; + } + + DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); + + (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; + + DTRACE( + "minimum theoretical dcfclk without stutter and full utilization = %f MHz", + (*dcfclk_mhz)); + +} + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + struct _vcs_dpi_display_pipe_clock_st clocks; + double max_dispclk = 0.0; + double dcfclk; + double dispclks[DC__NUM_PIPES__MAX]; + double dppclks[DC__NUM_PIPES__MAX]; + bool dppdiv[DC__NUM_PIPES__MAX]; + unsigned int i; + + DTRACE("Calculating pipe clocks..."); + + /* this is the theoretical minimum, have to adjust based on valid values for soc */ + get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); + + /* if(dcfclk > soc.vnom.dcfclk_mhz) + * dcfclk = soc.vmax.dcfclk_mhz; + * else if(dcfclk > soc.vmin.dcfclk_mhz) + * dcfclk = soc.vnom.dcfclk_mhz; + * else + * dcfclk = soc.vmin.dcfclk_mhz; + */ + + dcfclk = dml_socbb_voltage_scaling( + &mode_lib->soc, + (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; + clocks.dcfclk_mhz = dcfclk; + + get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); + + for (i = 0; i < num_pipes; i++) { + max_dispclk = dml_max(max_dispclk, dispclks[i]); + } + + clocks.dispclk_mhz = max_dispclk; + DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); + DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); + + for (i = 0; i < num_pipes; i++) { + if (dppclks[i] * 2 < max_dispclk) + dppdiv[i] = 1; + + if (dppdiv[i]) + clocks.dppclk_div[i] = 1; + else + clocks.dppclk_div[i] = 0; + + clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); + DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + } + + return clocks; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h new file mode 100644 index 000000000000..aed5f33bb04f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_PIPE_CLOCKS_H__ +#define __DISPLAY_PIPE_CLOCKS_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c new file mode 100644 index 000000000000..9fccbbffe129 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -0,0 +1,2254 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "display_rq_dlg_calc.h" +#include "display_mode_lib.h" + +static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) +{ + unsigned int ret_val = 0; + + if (source_format == dm_444_16) { + if (!is_chroma) + ret_val = 2; + } else if (source_format == dm_444_32) { + if (!is_chroma) + ret_val = 4; + } else if (source_format == dm_444_64) { + if (!is_chroma) + ret_val = 8; + } else if (source_format == dm_420_8) { + if (is_chroma) + ret_val = 2; + else + ret_val = 1; + } else if (source_format == dm_420_10) { + if (is_chroma) + ret_val = 4; + else + ret_val = 2; + } + return ret_val; +} + +static bool is_dual_plane(enum source_format_class source_format) +{ + bool ret_val = 0; + + if ((source_format == dm_420_8) || (source_format == dm_420_10)) + ret_val = 1; + + return ret_val; +} + +static void get_blk256_size( + unsigned int *blk256_width, + unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + if (bytes_per_element == 1) { + *blk256_width = 16; + *blk256_height = 16; + } else if (bytes_per_element == 2) { + *blk256_width = 16; + *blk256_height = 8; + } else if (bytes_per_element == 4) { + *blk256_width = 8; + *blk256_height = 8; + } else if (bytes_per_element == 8) { + *blk256_width = 8; + *blk256_height = 4; + } +} + +static double get_refcyc_per_delivery( + struct display_mode_lib *mode_lib, + double refclk_freq_in_mhz, + double pclk_freq_in_mhz, + int unsigned recout_width, + double vratio, + double hscale_pixel_rate, + int unsigned delivery_width, + int unsigned req_per_swath_ub) +{ + double refcyc_per_delivery = 0.0; + if (vratio <= 1.0) { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; + } else { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width + / (double) hscale_pixel_rate / (double) req_per_swath_ub; + } + + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); + DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); + DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); + DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + + return refcyc_per_delivery; + +} + +static double get_vratio_pre( + struct display_mode_lib *mode_lib, + unsigned int max_num_sw, + unsigned int max_partial_sw, + unsigned int swath_height, + double vinit, + double l_sw) +{ + double prefill = dml_floor(vinit); + double vratio_pre = 1.0; + + vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; + + if (swath_height > 4) { + double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); + if (tmp0 > vratio_pre) + vratio_pre = tmp0; + } + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); + + if (vratio_pre < 1.0) { + DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); + vratio_pre = 1.0; + } + + if (vratio_pre > 4.0) { + DTRACE( + "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", + __func__, + vratio_pre); + vratio_pre = 4.0; + } + + return vratio_pre; +} + +static void get_swath_need( + struct display_mode_lib *mode_lib, + unsigned int *max_num_sw, + unsigned int *max_partial_sw, + unsigned int swath_height, + double vinit) +{ + double prefill = dml_floor(vinit); + unsigned int max_partial_sw_int; + + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + + ASSERT(prefill > 0.0 && prefill <= 8.0); + + *max_num_sw = (int unsigned) (dml_ceil((prefill - 1.0) / (double) swath_height) + 1.0); /* prefill has to be >= 1 */ + max_partial_sw_int = + (prefill == 1) ? + (swath_height - 1) : + ((int unsigned) (prefill - 2.0) % swath_height); + *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); +} + +static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) +{ + if (tile_size == dm_256k_tile) + return (256 * 1024); + else if (tile_size == dm_64k_tile) + return (64 * 1024); + else + return (4 * 1024); +} + +static void extract_rq_sizing_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("DLG: %s: rq_sizing param", __func__); + print__data_rq_sizing_params_st(mode_lib, rq_sizing); + + rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + + if (rq_sizing.min_chunk_bytes == 0) + rq_regs->min_chunk_size = 0; + else + rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + + rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; + if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->min_meta_chunk_size = 0; + else + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + + rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; +} + +void extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param) +{ + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + unsigned int detile_buf_plane1_addr = 0; + + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + if (rq_param.yuv420) + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + + /* FIXME: take the max between luma, chroma chunk size? + * okay for now, as we are setting chunk_bytes to 8kb anyways + */ + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + rq_regs->drq_expansion_mode = 0; + } else { + rq_regs->drq_expansion_mode = 2; + } + rq_regs->prq_expansion_mode = 1; + rq_regs->mrq_expansion_mode = 1; + rq_regs->crq_expansion_mode = 1; + + if (rq_param.yuv420) { + if ((double) rq_param.misc.rq_l.stored_swath_bytes + / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + } else { + detile_buf_plane1_addr = dml_round_to_multiple( + (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + 256, + 0) / 64.0; /* 2/3 to chroma */ + } + } + rq_regs->plane1_base_address = detile_buf_plane1_addr; +} + +static void handle_det_buf_split( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + unsigned int total_swath_bytes = 0; + unsigned int swath_bytes_l = 0; + unsigned int swath_bytes_c = 0; + unsigned int full_swath_bytes_packed_l = 0; + unsigned int full_swath_bytes_packed_c = 0; + bool req128_l = 0; + bool req128_c = 0; + bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param.source_scan == dm_vert); + unsigned int log2_swath_height_l = 0; + unsigned int log2_swath_height_c = 0; + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + + full_swath_bytes_packed_l = rq_param->misc.rq_l.full_swath_bytes; + full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; + + if (rq_param->yuv420_10bpc) { + full_swath_bytes_packed_l = dml_round_to_multiple( + rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + full_swath_bytes_packed_c = dml_round_to_multiple( + rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + } + + if (rq_param->yuv420) { + total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; + + if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + req128_l = 0; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l; + swath_bytes_c = full_swath_bytes_packed_c; + } else { /*128b request (for luma only for yuv420 8bpc) */ + req128_l = 1; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l / 2; + swath_bytes_c = full_swath_bytes_packed_c; + } + + /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) + * TODO: Remove after rtl fix + */ + if (req128_l == 1) { + req128_c = 1; + DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); + } + + /* Note: assumption, the config that pass in will fit into + * the detiled buffer. + */ + } else { + total_swath_bytes = 2 * full_swath_bytes_packed_l; + + if (total_swath_bytes <= detile_buf_size_in_bytes) + req128_l = 0; + else + req128_l = 1; + + swath_bytes_l = total_swath_bytes; + swath_bytes_c = 0; + } + rq_param->misc.rq_l.stored_swath_bytes = swath_bytes_l; + rq_param->misc.rq_c.stored_swath_bytes = swath_bytes_c; + + if (surf_linear) { + log2_swath_height_l = 0; + log2_swath_height_c = 0; + } else if (!surf_vert) { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; + } else { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; + rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; + + DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); + DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); + DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); + DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); +} + +/* Need refactor. */ +void dml_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + bool surf_linear = (tiling == dm_sw_linear); + bool surf_vert = (source_scan == dm_vert); + + unsigned int bytes_per_element = get_bytes_per_element( + (enum source_format_class) source_format, + is_chroma); + unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int blk256_width = 0; + unsigned int blk256_height = 0; + + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int log2_meta_row_height; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int dpte_req_width; + + if (surf_linear) { + blk256_width = 256; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (tiling != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + log2_meta_row_height = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) + log2_meta_row_height = log2_meta_req_height; + else + log2_meta_row_height = log2_meta_req_width; + + *o_meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + dpte_req_width = 0; /* 64b dpte req width in data element */ + + if (surf_linear) { + log2_vmpg_height = 0; /* one line high */ + } else { + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + } + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + } else { + /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + } + } + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + } + + *o_dpte_row_height = 1 << log2_dpte_row_height; +} + +static void get_surf_rq_param( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, + struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, + struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + bool surf_linear; + bool surf_vert; + unsigned int bytes_per_element; + unsigned int log2_bytes_per_element; + unsigned int blk256_width; + unsigned int blk256_height; + unsigned int log2_blk256_width; + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int meta_req_width; + unsigned int meta_req_height; + unsigned int log2_meta_row_height; + unsigned int meta_row_width_ub; + unsigned int log2_meta_chunk_bytes; + unsigned int log2_meta_chunk_height; + unsigned int log2_meta_chunk_width; + unsigned int log2_min_meta_chunk_bytes; + unsigned int min_meta_chunk_width; + unsigned int meta_chunk_width; + unsigned int meta_chunk_per_row_int; + unsigned int meta_row_remainder; + unsigned int meta_chunk_threshold; + unsigned int meta_blk_bytes; + unsigned int meta_blk_height; + unsigned int meta_blk_width; + unsigned int meta_surface_bytes; + unsigned int vmpg_bytes; + unsigned int meta_pte_req_per_frame_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int log2_dpte_group_width; + unsigned int dpte_row_width_ub; + unsigned int dpte_row_height; + unsigned int dpte_req_height; + unsigned int dpte_req_width; + unsigned int dpte_group_width; + unsigned int log2_dpte_group_bytes; + unsigned int log2_dpte_group_length; + unsigned int func_meta_row_height, func_dpte_row_height; + + /* FIXME check if ppe apply for both luma and chroma in 422 case */ + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + + rq_sizing_param->mpte_group_bytes = 2048; + + surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + surf_vert = (pipe_src_param.source_scan == dm_vert); + + bytes_per_element = get_bytes_per_element( + (enum source_format_class) pipe_src_param.source_format, + is_chroma); + log2_bytes_per_element = dml_log2(bytes_per_element); + blk256_width = 0; + blk256_height = 0; + + if (surf_linear) { + blk256_width = 256 / bytes_per_element; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); + DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); + DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); + DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + + log2_blk256_width = dml_log2((double) blk256_width); + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = + surf_linear ? 256 : get_blk_size_bytes( + (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (pipe_src_param.sw_mode != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + if (!surf_vert) { + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_width - 1, blk256_width, 1) + + blk256_width; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; + } else { + rq_dlg_param->swath_width_ub = dml_round_to_multiple( + vp_height - 1, + blk256_height, + 1) + blk256_height; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; + } + + if (!surf_vert) + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_height + * bytes_per_element; + else + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_width + * bytes_per_element; + + rq_misc_param->blk256_height = blk256_height; + rq_misc_param->blk256_width = blk256_width; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + meta_req_width = 1 << log2_meta_req_width; + meta_req_height = 1 << log2_meta_req_height; + log2_meta_row_height = 0; + meta_row_width_ub = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) { + log2_meta_row_height = log2_meta_req_height; + meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) + + meta_req_width; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_width; + } else { + log2_meta_row_height = log2_meta_req_width; + meta_row_width_ub = dml_round_to_multiple(vp_height - 1, meta_req_height, 1) + + meta_req_height; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_height; + } + rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); + log2_meta_chunk_height = log2_meta_row_height; + + /*full sized meta chunk width in unit of data elements */ + log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height; + log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); + min_meta_chunk_width = 1 + << (log2_min_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height); + meta_chunk_width = 1 << log2_meta_chunk_width; + meta_chunk_per_row_int = (unsigned int) (meta_row_width_ub / meta_chunk_width); + meta_row_remainder = meta_row_width_ub % meta_chunk_width; + meta_chunk_threshold = 0; + meta_blk_bytes = 4096; + meta_blk_height = blk256_height * 64; + meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; + meta_surface_bytes = meta_pitch + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + + meta_blk_height) * bytes_per_element / 256; + vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; + meta_pte_req_per_frame_ub = (dml_round_to_multiple( + meta_surface_bytes - vmpg_bytes, + 8 * vmpg_bytes, + 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; + + DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); + DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); + DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); + DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); + DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + + if (!surf_vert) + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; + else + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_height; + + if (meta_row_remainder <= meta_chunk_threshold) + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 1; + else + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; + + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + log2_dpte_group_width = 0; + dpte_row_width_ub = 0; + dpte_row_height = 0; + dpte_req_height = 0; /* 64b dpte req height in data element */ + dpte_req_width = 0; /* 64b dpte req width in data element */ + dpte_group_width = 0; + log2_dpte_group_bytes = 0; + log2_dpte_group_length = 0; + + if (surf_linear) { + log2_vmpg_height = 0; /* one line high */ + } else { + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + } + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + /* Ensure we only have the 3 shapes */ + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_height = 1 << log2_dpte_req_height; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + + /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + */ + dpte_row_width_ub = dml_round_to_multiple( + data_pitch * dpte_row_height - 1, + dpte_req_width, + 1) + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) + + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + dpte_row_width_ub = dml_round_to_multiple(vp_height - 1, dpte_req_height, 1) + + dpte_req_height; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; + } + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + + /* the dpte_group_bytes is reduced for the specific case of vertical + * access of a tile surface that has dpte request of 8x1 ptes. + */ + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + rq_sizing_param->dpte_group_bytes = 512; + else + /*full size */ + rq_sizing_param->dpte_group_bytes = 2048; + + /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); + log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + + /* full sized data pte group width in elements */ + if (!surf_vert) + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; + else + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + + dpte_group_width = 1 << log2_dpte_group_width; + + /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + * the upper bound for the dpte groups per row is as follows. + */ + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( + (double) dpte_row_width_ub / dpte_group_width); + + dml_rq_dlg_get_row_heights( + mode_lib, + &func_dpte_row_height, + &func_meta_row_height, + vp_width, + data_pitch, + pipe_src_param.source_format, + pipe_src_param.sw_mode, + pipe_src_param.macro_tile_size, + pipe_src_param.source_scan, + is_chroma); + + /* Just a check to make sure this function and the new one give the same + * result. The standalone get_row_heights() function is based off of the + * code in this function so the same changes need to be made to both. + */ + if (rq_dlg_param->meta_row_height != func_meta_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->meta_row_height = %d", + rq_dlg_param->meta_row_height); + DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); + ASSERT(0); + } + + if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->dpte_row_height = %d", + rq_dlg_param->dpte_row_height); + DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); + ASSERT(0); + } +} + +void dml_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + /* get param for luma surface */ + rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 + || pipe_src_param.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_l), + &(rq_param->dlg.rq_l), + &(rq_param->misc.rq_l), + pipe_src_param, + 0); + + if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { + /* get param for chroma surface */ + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_c), + &(rq_param->dlg.rq_c), + &(rq_param->misc.rq_c), + pipe_src_param, + 1); + } + + /* calculate how to split the det buffer space between luma and chroma */ + handle_det_buf_split(mode_lib, rq_param, pipe_src_param); + print__rq_params_st(mode_lib, *rq_param); +} + +void dml_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + struct _vcs_dpi_display_rq_params_st rq_param = {0}; + + memset(rq_regs, 0, sizeof(*rq_regs)); + + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_src_param); + extract_rq_regs(mode_lib, rq_regs, rq_param); + + print__rq_regs_st(mode_lib, *rq_regs); +} + +/* TODO: Need refactor, so this is used by dml_rq_dlg_get_dlg_params as well + * The problem is that there are some intermediate terms that would need by + * some dlg calculation (i.e. rest of prefetch and active prog guide calculation) + */ +void dml_rq_dlg_get_dlg_params_prefetch( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en) +{ + /* Prefetch */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + const double prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + double min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + double t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + + bool dcc_en = e2e_pipe_param.pipe.src.dcc; + bool dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + unsigned int bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + unsigned int bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double line_time_in_us = (htotal / pclk_freq_in_mhz); + double vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + double vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + double vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + double vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; + unsigned int swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; + unsigned int swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + unsigned int dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + unsigned int vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + unsigned int vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + unsigned int vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + const unsigned int dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + const unsigned int dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz + / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + unsigned int dst_y_after_scaler = 0; + unsigned int dst_x_after_scaler = 0; + + unsigned int vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + int unsigned vm_bytes; + int unsigned meta_row_bytes; + int unsigned max_num_sw_l; + int unsigned max_num_sw_c; + int unsigned max_partial_sw_l; + int unsigned max_partial_sw_c; + + double max_vinit_l; + double max_vinit_c; + int unsigned lsw_l; + int unsigned lsw_c; + int unsigned sw_bytes_ub_l; + int unsigned sw_bytes_ub_c; + int unsigned sw_bytes; + int unsigned dpte_row_bytes; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + + DTRACE("DLG: %s: urgent_latency_us = %3.2f", __func__, mode_lib->soc.urgent_latency_us); + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_param->prefetch_bw = + (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + prefetch_param->flip_bytes = (vm_bytes + dpte_row_bytes + meta_row_bytes); +} + +/* Note: currently taken in as is. + * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. + */ +void dml_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + /* Timing */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; + unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; + unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double ref_freq_to_pix_freq; + double prefetch_xy_calc_in_dcfclk; + double min_dcfclk_mhz; + double t_calc_us; + double min_ttu_vblank; + double min_dst_y_ttu_vblank; + int unsigned dlg_vblank_start; + bool dcc_en; + bool dual_plane; + bool mode_422; + unsigned int access_dir; + unsigned int bytes_per_element_l; + unsigned int bytes_per_element_c; + unsigned int vp_height_l; + unsigned int vp_width_l; + unsigned int vp_height_c; + unsigned int vp_width_c; + unsigned int htaps_l; + unsigned int htaps_c; + double hratios_l; + double hratios_c; + double vratio_l; + double vratio_c; + double line_time_in_us; + double vinit_l; + double vinit_c; + double vinit_bot_l; + double vinit_bot_c; + unsigned int swath_height_l; + unsigned int swath_width_ub_l; + unsigned int dpte_bytes_per_row_ub_l; + unsigned int dpte_groups_per_row_ub_l; + unsigned int meta_pte_bytes_per_frame_ub_l; + unsigned int meta_bytes_per_row_ub_l; + unsigned int swath_height_c; + unsigned int swath_width_ub_c; + unsigned int dpte_bytes_per_row_ub_c; + unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; + unsigned int dst_x_after_scaler; + unsigned int dst_y_after_scaler; + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + int unsigned vm_bytes; + int unsigned meta_row_bytes; + int unsigned max_num_sw_l; + int unsigned max_num_sw_c; + int unsigned max_partial_sw_l; + int unsigned max_partial_sw_c; + double max_vinit_l; + double max_vinit_c; + int unsigned lsw_l; + int unsigned lsw_c; + int unsigned sw_bytes_ub_l; + int unsigned sw_bytes_ub_c; + int unsigned sw_bytes; + int unsigned dpte_row_bytes; + double prefetch_bw; + double flip_bw; + double t_vm_us; + double t_r0_us; + double dst_y_per_vm_vblank; + double dst_y_per_row_vblank; + double min_dst_y_per_vm_vblank; + double min_dst_y_per_row_vblank; + double lsw; + double vratio_pre_l; + double vratio_pre_c; + unsigned int req_per_swath_ub_l; + unsigned int req_per_swath_ub_c; + unsigned int meta_row_height_l; + unsigned int swath_width_pixels_ub_l; + unsigned int swath_width_pixels_ub_c; + unsigned int scaler_rec_in_width_l; + unsigned int scaler_rec_in_width_c; + unsigned int dpte_row_height_l; + unsigned int dpte_row_height_c; + double hscale_pixel_rate_l; + double hscale_pixel_rate_c; + double min_hratio_fact_l; + double min_hratio_fact_c; + double refcyc_per_line_delivery_pre_l; + double refcyc_per_line_delivery_pre_c; + double refcyc_per_line_delivery_l; + double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; + double refcyc_per_req_delivery_pre_c; + double refcyc_per_req_delivery_l; + double refcyc_per_req_delivery_c; + double refcyc_per_req_delivery_pre_cur0; + double refcyc_per_req_delivery_cur0; + int unsigned full_recout_width; + double hratios_cur0; + unsigned int cur0_src_width; + enum cursor_bpp cur0_bpp; + unsigned int cur0_req_size; + unsigned int cur0_req_width; + double cur0_width_ub; + double cur0_req_per_width; + double hactive_cur0; + + memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); + memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); + + DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); + DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); + DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); + DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); + + /* ------------------------- */ + /* Section 1.5.2.1: OTG dependent Params */ + /* ------------------------- */ + DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); + DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); + + ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = + (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); + disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal + * dml_pow(2, 8)); + disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end + * (double) ref_freq_to_pix_freq); + ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ + + prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + min_ttu_vblank = dlg_sys_param.t_urg_wm_us; + if (cstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); + if (pstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); + min_ttu_vblank = min_ttu_vblank + t_calc_us; + + min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; + dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; + + disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start + + min_dst_y_ttu_vblank) * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); + + DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); + DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); + DTRACE( + "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + __func__, + min_dst_y_ttu_vblank); + DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); + DTRACE( + "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + __func__, + disp_dlg_regs->min_dst_y_next_start); + DTRACE( + "DLG: %s: ref_freq_to_pix_freq = %3.2f", + __func__, + ref_freq_to_pix_freq); + + /* ------------------------- */ + /* Section 1.5.2.2: Prefetch, Active and TTU */ + /* ------------------------- */ + /* Prefetch Calc */ + /* Source */ + dcc_en = e2e_pipe_param.pipe.src.dcc; + dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + mode_422 = 0; /* FIXME */ + access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ + bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + vp_height_l = e2e_pipe_param.pipe.src.viewport_height; + vp_width_l = e2e_pipe_param.pipe.src.viewport_width; + vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; + vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; + + /* Scaling */ + htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; + htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; + hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; + vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; + vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + + line_time_in_us = (htotal / pclk_freq_in_mhz); + vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + swath_height_l = rq_dlg_param.rq_l.swath_height; + swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; + meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + swath_height_c = rq_dlg_param.rq_c.swath_height; + swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; + + meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; + vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + + vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + DTRACE( + "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + __func__, + vblank_start, + vblank_end); + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + dst_x_after_scaler = 0; + dst_y_after_scaler = 0; + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + DTRACE( + "DLG: %s: soc.urgent_latency_us = %3.2f", + __func__, + mode_lib->soc.urgent_latency_us); + + DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); + if (dual_plane) + DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); + + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) + / (double) dlg_sys_param.total_flip_bytes; + t_vm_us = line_time_in_us / 4.0; + if (vm_en && dcc_en) { + t_vm_us = dml_max( + dlg_sys_param.t_extra_us, + dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); + + if (iflip_en && !dual_plane) { + t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); + if (flip_bw > 0.) + t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); + } + } + + t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); + + if (vm_en || dcc_en) { + t_r0_us = dml_max( + (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, + dlg_sys_param.t_extra_us); + t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); + + if (iflip_en && !dual_plane) { + t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); + if (flip_bw > 0.) + t_r0_us = dml_max( + (dpte_row_bytes + meta_row_bytes) / flip_bw, + t_r0_us); + } + } + + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->dst_y_after_scaler); + DTRACE( + "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->refcyc_x_after_scaler); + + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", + __func__, + disp_dlg_regs->dst_y_prefetch); + + dst_y_per_vm_vblank = 0.0; + dst_y_per_row_vblank = 0.0; + + dst_y_per_vm_vblank = t_vm_us / line_time_in_us; + dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125)) / 4.0; + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + + dst_y_per_row_vblank = t_r0_us / line_time_in_us; + dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125)) / 4.0; + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + + DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); + DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); + + DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); + DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); + DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); + DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); + DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); + DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); + DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); + DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + + min_dst_y_per_vm_vblank = 8.0; + min_dst_y_per_row_vblank = 16.0; + if (htotal <= 75) { + min_vblank = 300; + min_dst_y_per_vm_vblank = 100.0; + min_dst_y_per_row_vblank = 100.0; + } + + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); + ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); + + ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); + lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); + + DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); + + vratio_pre_l = get_vratio_pre( + mode_lib, + max_num_sw_l, + max_partial_sw_l, + swath_height_l, + max_vinit_l, + lsw); + vratio_pre_c = 1.0; + if (dual_plane) + vratio_pre_c = get_vratio_pre( + mode_lib, + max_num_sw_c, + max_partial_sw_c, + swath_height_c, + max_vinit_c, + lsw); + + DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); + DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); + + ASSERT(vratio_pre_l <= 4.0); + if (vratio_pre_l >= 4.0) + disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + + ASSERT(vratio_pre_c <= 4.0); + if (vratio_pre_c >= 4.0) + disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_c = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + /* Active */ + req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + swath_width_pixels_ub_l = 0; + swath_width_pixels_ub_c = 0; + scaler_rec_in_width_l = 0; + scaler_rec_in_width_c = 0; + dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (mode_422) { + swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_c = swath_width_ub_c * 2; + } else { + swath_width_pixels_ub_l = swath_width_ub_l * 1; + swath_width_pixels_ub_c = swath_width_ub_c * 1; + } + + hscale_pixel_rate_l = 0.; + hscale_pixel_rate_c = 0.; + min_hratio_fact_l = 1.0; + min_hratio_fact_c = 1.0; + + if (htaps_l <= 1) + min_hratio_fact_l = 2.0; + else if (htaps_l <= 6) { + if ((hratios_l * 2.0) > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l * 2.0; + } else { + if (hratios_l > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l; + } + + hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; + + if (htaps_c <= 1) + min_hratio_fact_c = 2.0; + else if (htaps_c <= 6) { + if ((hratios_c * 2.0) > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c * 2.0; + } else { + if (hratios_c > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c; + } + + hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; + + refcyc_per_line_delivery_pre_l = 0.; + refcyc_per_line_delivery_pre_c = 0.; + refcyc_per_line_delivery_l = 0.; + refcyc_per_line_delivery_c = 0.; + + refcyc_per_req_delivery_pre_l = 0.; + refcyc_per_req_delivery_pre_c = 0.; + refcyc_per_req_delivery_l = 0.; + refcyc_per_req_delivery_c = 0.; + refcyc_per_req_delivery_pre_cur0 = 0.; + refcyc_per_req_delivery_cur0 = 0.; + + full_recout_width = 0; + if (e2e_pipe_param.pipe.src.is_hsplit) { + if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { + DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); + full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + } else + full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + } else + full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + refcyc_per_line_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); + DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + __func__, + refcyc_per_line_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + __func__, + refcyc_per_line_delivery_l); + + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_l); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_l); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + refcyc_per_line_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + __func__, + refcyc_per_line_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + __func__, + refcyc_per_line_delivery_c); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_c); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_c); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + } + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + + /* TTU - Luma / Chroma */ + if (access_dir) { /* vertical access */ + scaler_rec_in_width_l = vp_height_l; + scaler_rec_in_width_c = vp_height_c; + } else { + scaler_rec_in_width_l = vp_width_l; + scaler_rec_in_width_c = vp_width_c; + } + + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + refcyc_per_req_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + __func__, + refcyc_per_req_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + __func__, + refcyc_per_req_delivery_l); + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + refcyc_per_req_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + __func__, + refcyc_per_req_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + __func__, + refcyc_per_req_delivery_c); + + disp_ttu_regs->refcyc_per_req_delivery_pre_c = + (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); + } + + /* TTU - Cursor */ + hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ + cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; + cur0_req_size = 0; + cur0_req_width = 0; + cur0_width_ub = 0.0; + cur0_req_per_width = 0.0; + hactive_cur0 = 0.0; + + ASSERT(cur0_src_width <= 256); + + if (cur0_src_width > 0) { + unsigned int cur0_bit_per_pixel = 0; + + if (cur0_bpp == dm_cur_2bit) { + cur0_req_size = 64; /* byte */ + cur0_bit_per_pixel = 2; + } else { /* 32bit */ + cur0_bit_per_pixel = 32; + if (cur0_src_width >= 1 && cur0_src_width <= 16) + cur0_req_size = 64; + else if (cur0_src_width >= 17 && cur0_src_width <= 31) + cur0_req_size = 128; + else + cur0_req_size = 256; + } + + cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); + cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width) + * (double) cur0_req_width; + cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; + hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + + if (vratio_pre_l <= 1.0) { + refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); + DTRACE( + "DLG: %s: cur0_width_ub = %3.2f", + __func__, + cur0_width_ub); + DTRACE( + "DLG: %s: cur0_req_per_width = %3.2f", + __func__, + cur0_req_per_width); + DTRACE( + "DLG: %s: hactive_cur0 = %3.2f", + __func__, + hactive_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_pre_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_cur0); + + disp_ttu_regs->refcyc_per_req_delivery_cur0 = + (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); + } else { + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; + disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + } + + /* TTU - Misc */ + disp_ttu_regs->qos_level_low_wm = 0; + ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); + disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal + * ref_freq_to_pix_freq); + ASSERT(disp_ttu_regs->qos_level_high_wm < dml_pow(2, 14)); + + disp_ttu_regs->qos_level_flip = 14; + disp_ttu_regs->qos_level_fixed_l = 8; + disp_ttu_regs->qos_level_fixed_c = 8; + disp_ttu_regs->qos_level_fixed_cur0 = 8; + disp_ttu_regs->qos_ramp_disable_l = 0; + disp_ttu_regs->qos_ramp_disable_c = 0; + disp_ttu_regs->qos_ramp_disable_cur0 = 0; + + disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; + ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); + + print__ttu_regs_st(mode_lib, *disp_ttu_regs); + print__dlg_regs_st(mode_lib, *disp_dlg_regs); +} + +void dml_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + const int unsigned num_pipes, + const int unsigned pipe_idx, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + struct _vcs_dpi_display_rq_params_st rq_param = {0}; + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; + struct _vcs_dpi_wm_calc_pipe_params_st *wm_param = mode_lib->wm_param; + struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; + struct _vcs_dpi_display_dlg_prefetch_param_st prefetch_param; + double total_ret_bw; + double total_active_bw; + double total_prefetch_bw; + int unsigned total_flip_bytes; + int unsigned num_planes; + int i; + + memset(wm_param, 0, sizeof(mode_lib->wm_param)); + + /* Get watermark and Tex. */ + DTRACE("DLG: Start calculating system setting related parameters. num_pipes=%d", num_pipes); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e_pipe_param, num_pipes, wm_param); + + cstate_pstate_wm = dml_wm_cstate_pstate_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_mclk_wm_us = cstate_pstate_wm.pstate_change_us; + dlg_sys_param.t_sr_wm_us = cstate_pstate_wm.cstate_enter_plus_exit_us; + dlg_sys_param.t_urg_wm_us = dml_wm_urgent_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency + / dml_wm_dcfclk_deepsleep_mhz_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_extra_us = dml_wm_urgent_extra(mode_lib, wm_param, num_planes); + dlg_sys_param.deepsleep_dcfclk_mhz = dml_wm_dcfclk_deepsleep_mhz_e2e( + mode_lib, + e2e_pipe_param, + num_pipes); + + print__dlg_sys_params_st(mode_lib, dlg_sys_param); + + DTRACE("DLG: Start calculating total prefetch bw. num_planes=%d", num_planes); + total_ret_bw = dml_wm_calc_return_bw(mode_lib, wm_param, num_planes); + total_active_bw = dml_wm_calc_total_data_read_bw(mode_lib, wm_param, num_planes); + total_prefetch_bw = 0.0; + total_flip_bytes = 0; + + for (i = 0; i < num_pipes; i++) { + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[i].pipe.src); + dml_rq_dlg_get_dlg_params_prefetch( + mode_lib, + &prefetch_param, + rq_param.dlg, + dlg_sys_param, + e2e_pipe_param[i], + cstate_en, + pstate_en, + vm_en); + total_prefetch_bw += prefetch_param.prefetch_bw; + total_flip_bytes += prefetch_param.flip_bytes; + DTRACE( + "DLG: pipe=%d, total_prefetch_bw=%3.2f total_flip_bytes=%d", + i, + total_prefetch_bw, + total_flip_bytes); + } + + dlg_sys_param.total_flip_bw = total_ret_bw - dml_max(total_active_bw, total_prefetch_bw); + + DTRACE("DLG: Done calculating total prefetch bw"); + DTRACE("DLG: num_pipes = %d", num_pipes); + DTRACE("DLG: total_ret_bw = %3.2f", total_ret_bw); + DTRACE("DLG: total_active_bw = %3.2f", total_active_bw); + DTRACE("DLG: total_prefetch_bw = %3.2f", total_prefetch_bw); + DTRACE("DLG: total_flip_bw = %3.2f", dlg_sys_param.total_flip_bw); + + if (dlg_sys_param.total_flip_bw < 0.0 && iflip_en) { + DTRACE("WARNING_DLG Insufficient bw for immediate flip!"); + dlg_sys_param.total_flip_bw = 0; + } + + dlg_sys_param.total_flip_bytes = total_flip_bytes; + DTRACE("DLG: total_flip_bytes = %d", dlg_sys_param.total_flip_bytes); + DTRACE("DLG: Done calculating system setting related parameters."); + + /* system parameter calculation done */ + + DTRACE("DLG: Calculation for pipe[%d] start", pipe_idx); + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe.src); + dml_rq_dlg_get_dlg_params( + mode_lib, + dlg_regs, + ttu_regs, + rq_param.dlg, + dlg_sys_param, + e2e_pipe_param[pipe_idx], + cstate_en, + pstate_en, + vm_en, + iflip_en); + DTRACE("DLG: Calculation for pipe[%d] end", pipe_idx); +} + +void dml_rq_dlg_get_arb_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_arb_params_st *arb_param) +{ + memset(arb_param, 0, sizeof(*arb_param)); + arb_param->max_req_outstanding = 256; + arb_param->min_req_outstanding = 68; + arb_param->sat_level_us = 60; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h new file mode 100644 index 000000000000..e63b13fb2887 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h @@ -0,0 +1,139 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_RQ_DLG_CALC_H__ +#define __DISPLAY_RQ_DLG_CALC_H__ + +#include "dml_common_defs.h" +#include "display_rq_dlg_helpers.h" + +struct display_mode_lib; + +void extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param); +/* Function: dml_rq_dlg_get_rq_params + * Calculate requestor related parameters that register definition agnostic + * (i.e. this layer does try to separate real values from register defintion) + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) + */ +void dml_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + +/* Function: dml_rq_dlg_get_rq_reg + * Main entry point for test to get the register values out of this DML class. + * This function calls and fucntions to calculate + * and then populate the rq_regs struct + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_regs - struct that holds all the RQ registers field value. + * See also: + */ +void dml_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + +/* Function: dml_rq_dlg_get_dlg_params + * Calculate deadline related parameters + */ +void dml_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +/* Function: dml_rq_dlg_get_dlg_param_prefetch + * For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw + * for ALL pipes and use this info to calculate the prefetch programming. + * Output: prefetch_param.prefetch_bw and flip_bytes + */ +void dml_rq_dlg_get_dlg_params_prefetch( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en); + +/* Function: dml_rq_dlg_get_dlg_reg + * Calculate and return DLG and TTU register struct given the system setting + * Output: + * dlg_regs - output DLG register struct + * ttu_regs - output DLG TTU register struct + * Input: + * e2e_pipe_param - "compacted" array of e2e pipe param struct + * num_pipes - num of active "pipe" or "route" + * pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg + * cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. + * Added for legacy or unrealistic timing tests. + */ +void dml_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +/* Function: dml_rq_dlg_get_row_heights + * Calculate dpte and meta row heights + */ +void dml_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma); + +/* Function: dml_rq_dlg_get_arb_params */ +void dml_rq_dlg_get_arb_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_arb_params_st *arb_param); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c new file mode 100644 index 000000000000..3dc11366cd36 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -0,0 +1,320 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_rq_dlg_helpers.h" + +void print__rq_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st rq_param) +{ + DTRACE("RQ_DLG_CALC: *************************** "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_l); + DTRACE("RQ_DLG_CALC: === "); + print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_c); + + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_c); + + DTRACE("RQ_DLG_CALC: "); + print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_c); + DTRACE("RQ_DLG_CALC: *************************** "); +} + +void print__data_rq_sizing_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST"); + DTRACE("RQ_DLG_CALC: chunk_bytes = %0d", rq_sizing.chunk_bytes); + DTRACE("RQ_DLG_CALC: min_chunk_bytes = %0d", rq_sizing.min_chunk_bytes); + DTRACE("RQ_DLG_CALC: meta_chunk_bytes = %0d", rq_sizing.meta_chunk_bytes); + DTRACE("RQ_DLG_CALC: min_meta_chunk_bytes = %0d", rq_sizing.min_meta_chunk_bytes); + DTRACE("RQ_DLG_CALC: mpte_group_bytes = %0d", rq_sizing.mpte_group_bytes); + DTRACE("RQ_DLG_CALC: dpte_group_bytes = %0d", rq_sizing.dpte_group_bytes); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: swath_width_ub = %0d", rq_dlg_param.swath_width_ub); + DTRACE("RQ_DLG_CALC: swath_height = %0d", rq_dlg_param.swath_height); + DTRACE("RQ_DLG_CALC: req_per_swath_ub = %0d", rq_dlg_param.req_per_swath_ub); + DTRACE( + "RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d", + rq_dlg_param.meta_pte_bytes_per_frame_ub); + DTRACE( + "RQ_DLG_CALC: dpte_req_per_row_ub = %0d", + rq_dlg_param.dpte_req_per_row_ub); + DTRACE( + "RQ_DLG_CALC: dpte_groups_per_row_ub = %0d", + rq_dlg_param.dpte_groups_per_row_ub); + DTRACE("RQ_DLG_CALC: dpte_row_height = %0d", rq_dlg_param.dpte_row_height); + DTRACE( + "RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d", + rq_dlg_param.dpte_bytes_per_row_ub); + DTRACE( + "RQ_DLG_CALC: meta_chunks_per_row_ub = %0d", + rq_dlg_param.meta_chunks_per_row_ub); + DTRACE( + "RQ_DLG_CALC: meta_req_per_row_ub = %0d", + rq_dlg_param.meta_req_per_row_ub); + DTRACE("RQ_DLG_CALC: meta_row_height = %0d", rq_dlg_param.meta_row_height); + DTRACE( + "RQ_DLG_CALC: meta_bytes_per_row_ub = %0d", + rq_dlg_param.meta_bytes_per_row_ub); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_misc_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST"); + DTRACE("RQ_DLG_CALC: full_swath_bytes = %0d", rq_misc_param.full_swath_bytes); + DTRACE("RQ_DLG_CALC: stored_swath_bytes = %0d", rq_misc_param.stored_swath_bytes); + DTRACE("RQ_DLG_CALC: blk256_width = %0d", rq_misc_param.blk256_width); + DTRACE("RQ_DLG_CALC: blk256_height = %0d", rq_misc_param.blk256_height); + DTRACE("RQ_DLG_CALC: req_width = %0d", rq_misc_param.req_width); + DTRACE("RQ_DLG_CALC: req_height = %0d", rq_misc_param.req_height); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_c); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__dlg_sys_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: t_mclk_wm_us = %3.2f", dlg_sys_param.t_mclk_wm_us); + DTRACE("RQ_DLG_CALC: t_urg_wm_us = %3.2f", dlg_sys_param.t_urg_wm_us); + DTRACE("RQ_DLG_CALC: t_sr_wm_us = %3.2f", dlg_sys_param.t_sr_wm_us); + DTRACE("RQ_DLG_CALC: t_extra_us = %3.2f", dlg_sys_param.t_extra_us); + DTRACE("RQ_DLG_CALC: t_srx_delay_us = %3.2f", dlg_sys_param.t_srx_delay_us); + DTRACE("RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f", dlg_sys_param.deepsleep_dcfclk_mhz); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st rq_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST"); + DTRACE("RQ_DLG_CALC: chunk_size = 0x%0x", rq_regs.chunk_size); + DTRACE("RQ_DLG_CALC: min_chunk_size = 0x%0x", rq_regs.min_chunk_size); + DTRACE("RQ_DLG_CALC: meta_chunk_size = 0x%0x", rq_regs.meta_chunk_size); + DTRACE("RQ_DLG_CALC: min_meta_chunk_size = 0x%0x", rq_regs.min_meta_chunk_size); + DTRACE("RQ_DLG_CALC: dpte_group_size = 0x%0x", rq_regs.dpte_group_size); + DTRACE("RQ_DLG_CALC: mpte_group_size = 0x%0x", rq_regs.mpte_group_size); + DTRACE("RQ_DLG_CALC: swath_height = 0x%0x", rq_regs.swath_height); + DTRACE("RQ_DLG_CALC: pte_row_height_linear = 0x%0x", rq_regs.pte_row_height_linear); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st rq_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_REGS_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_c); + DTRACE("RQ_DLG_CALC: drq_expansion_mode = 0x%0x", rq_regs.drq_expansion_mode); + DTRACE("RQ_DLG_CALC: prq_expansion_mode = 0x%0x", rq_regs.prq_expansion_mode); + DTRACE("RQ_DLG_CALC: mrq_expansion_mode = 0x%0x", rq_regs.mrq_expansion_mode); + DTRACE("RQ_DLG_CALC: crq_expansion_mode = 0x%0x", rq_regs.crq_expansion_mode); + DTRACE("RQ_DLG_CALC: plane1_base_address = 0x%0x", rq_regs.plane1_base_address); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__dlg_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st dlg_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DLG_REGS_ST "); + DTRACE( + "RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x", + dlg_regs.refcyc_h_blank_end); + DTRACE("RQ_DLG_CALC: dlg_vblank_end = 0x%0x", dlg_regs.dlg_vblank_end); + DTRACE( + "RQ_DLG_CALC: min_dst_y_next_start = 0x%0x", + dlg_regs.min_dst_y_next_start); + DTRACE( + "RQ_DLG_CALC: refcyc_per_htotal = 0x%0x", + dlg_regs.refcyc_per_htotal); + DTRACE( + "RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x", + dlg_regs.refcyc_x_after_scaler); + DTRACE( + "RQ_DLG_CALC: dst_y_after_scaler = 0x%0x", + dlg_regs.dst_y_after_scaler); + DTRACE("RQ_DLG_CALC: dst_y_prefetch = 0x%0x", dlg_regs.dst_y_prefetch); + DTRACE( + "RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x", + dlg_regs.dst_y_per_vm_vblank); + DTRACE( + "RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x", + dlg_regs.dst_y_per_row_vblank); + DTRACE( + "RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x", + dlg_regs.ref_freq_to_pix_freq); + DTRACE("RQ_DLG_CALC: vratio_prefetch = 0x%0x", dlg_regs.vratio_prefetch); + DTRACE( + "RQ_DLG_CALC: vratio_prefetch_c = 0x%0x", + dlg_regs.vratio_prefetch_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x", + dlg_regs.refcyc_per_pte_group_vblank_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x", + dlg_regs.refcyc_per_pte_group_vblank_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_vblank_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_vblank_c); + DTRACE( + "RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x", + dlg_regs.dst_y_per_pte_row_nom_l); + DTRACE( + "RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x", + dlg_regs.dst_y_per_pte_row_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x", + dlg_regs.refcyc_per_pte_group_nom_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x", + dlg_regs.refcyc_per_pte_group_nom_c); + DTRACE( + "RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x", + dlg_regs.dst_y_per_meta_row_nom_l); + DTRACE( + "RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x", + dlg_regs.dst_y_per_meta_row_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_nom_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x", + dlg_regs.refcyc_per_line_delivery_pre_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x", + dlg_regs.refcyc_per_line_delivery_pre_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x", + dlg_regs.refcyc_per_line_delivery_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x", + dlg_regs.refcyc_per_line_delivery_c); + DTRACE( + "RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x", + dlg_regs.chunk_hdl_adjust_cur0); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__ttu_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_ttu_regs_st ttu_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_TTU_REGS_ST "); + DTRACE( + "RQ_DLG_CALC: qos_level_low_wm = 0x%0x", + ttu_regs.qos_level_low_wm); + DTRACE( + "RQ_DLG_CALC: qos_level_high_wm = 0x%0x", + ttu_regs.qos_level_high_wm); + DTRACE("RQ_DLG_CALC: min_ttu_vblank = 0x%0x", ttu_regs.min_ttu_vblank); + DTRACE("RQ_DLG_CALC: qos_level_flip = 0x%0x", ttu_regs.qos_level_flip); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x", + ttu_regs.refcyc_per_req_delivery_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x", + ttu_regs.refcyc_per_req_delivery_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x", + ttu_regs.refcyc_per_req_delivery_cur0); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_cur0); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_l = 0x%0x", + ttu_regs.qos_level_fixed_l); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x", + ttu_regs.qos_ramp_disable_l); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_c = 0x%0x", + ttu_regs.qos_level_fixed_c); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x", + ttu_regs.qos_ramp_disable_c); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x", + ttu_regs.qos_level_fixed_cur0); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x", + ttu_regs.qos_ramp_disable_cur0); + DTRACE("RQ_DLG_CALC: ===================================== "); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h new file mode 100644 index 000000000000..7403ccaf637b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_RQ_DLG_HELPERS_H__ +#define __DISPLAY_RQ_DLG_HELPERS_H__ + +#include "dml_common_defs.h" +#include "display_mode_lib.h" + +/* Function: Printer functions + * Print various struct + */ +void print__rq_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st rq_param); +void print__data_rq_sizing_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing); +void print__data_rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param); +void print__data_rq_misc_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param); +void print__rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param); +void print__dlg_sys_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param); + +void print__data_rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st data_rq_regs); +void print__rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st rq_regs); +void print__dlg_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st dlg_regs); +void print__ttu_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_ttu_regs_st ttu_regs); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c new file mode 100644 index 000000000000..390f09391433 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c @@ -0,0 +1,1281 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "display_watermark.h" +#include "display_mode_lib.h" + +static void get_bytes_per_pixel( + enum source_format_class format, + struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + switch (format) { + case dm_444_64: + plane->bytes_per_pixel_y = 8.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_444_32: + plane->bytes_per_pixel_y = 4.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_444_16: + plane->bytes_per_pixel_y = 2.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_422_10: + plane->bytes_per_pixel_y = 4.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_422_8: + plane->bytes_per_pixel_y = 2.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_420_8: + plane->bytes_per_pixel_y = 1.0; + plane->bytes_per_pixel_c = 2.0; + break; + case dm_420_10: + plane->bytes_per_pixel_y = 4.0 / 3; + plane->bytes_per_pixel_c = 8.0 / 3; + break; + default: + BREAK_TO_DEBUGGER(); /* invalid format in get_bytes_per_pixel */ + } +} + +static unsigned int get_swath_width_y( + struct _vcs_dpi_display_pipe_source_params_st *src_param, + unsigned int num_dpp) +{ + unsigned int val; + + /* note that we don't divide by num_dpp here because we have an interface which has already split + * any viewports + */ + if (src_param->source_scan == dm_horz) { + val = src_param->viewport_width; + } else { + val = src_param->viewport_height; + } + + return val; +} + +static void get_swath_height( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_pipe_source_params_st *src_param, + struct _vcs_dpi_wm_calc_pipe_params_st *plane, + unsigned int swath_width_y) +{ + double buffer_width; + + if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 + || src_param->source_format == dm_444_16) { + if (src_param->sw_mode == dm_sw_linear) { + plane->swath_height_y = 1; + } else if (src_param->source_format == dm_444_64) { + plane->swath_height_y = 4; + } else { + plane->swath_height_y = 8; + } + + if (src_param->source_scan != dm_horz) { + plane->swath_height_y = 256 / (unsigned int) plane->bytes_per_pixel_y + / plane->swath_height_y; + } + + plane->swath_height_c = 0; + + } else { + if (src_param->sw_mode == dm_sw_linear) { + plane->swath_height_y = 1; + plane->swath_height_c = 1; + } else if (src_param->source_format == dm_420_8) { + plane->swath_height_y = 16; + plane->swath_height_c = 8; + } else { + plane->swath_height_y = 8; + plane->swath_height_c = 8; + } + + if (src_param->source_scan != dm_horz) { + double bytes_per_pixel_c_ceil; + + plane->swath_height_y = 256 / dml_ceil(plane->bytes_per_pixel_y) + / plane->swath_height_y; + + bytes_per_pixel_c_ceil = dml_ceil_2(plane->bytes_per_pixel_c); + + plane->swath_height_c = 256 / bytes_per_pixel_c_ceil + / plane->swath_height_c; + } + } + + /* use swath height min if buffer isn't big enough */ + + buffer_width = ((double) mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0) + / (plane->bytes_per_pixel_y * (double) plane->swath_height_y + + (plane->bytes_per_pixel_c / 2.0 + * (double) plane->swath_height_c)); + + if ((double) swath_width_y <= buffer_width) { + /* do nothing, just keep code structure from Gabes vba */ + } else { + /* substitute swath height with swath height min */ + if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 + || src_param->source_format == dm_444_16) { + if ((src_param->sw_mode == dm_sw_linear) + || (src_param->source_format == dm_444_64 + && (src_param->sw_mode == dm_sw_4kb_s + || src_param->sw_mode + == dm_sw_4kb_s_x + || src_param->sw_mode + == dm_sw_64kb_s + || src_param->sw_mode + == dm_sw_64kb_s_t + || src_param->sw_mode + == dm_sw_64kb_s_x + || src_param->sw_mode + == dm_sw_var_s + || src_param->sw_mode + == dm_sw_var_s_x) + && src_param->source_scan == dm_horz)) { + /* do nothing, just keep code structure from Gabes vba */ + } else { + plane->swath_height_y = plane->swath_height_y / 2; + } + } else { + if (src_param->sw_mode == dm_sw_linear) { + /* do nothing, just keep code structure from Gabes vba */ + } else if (src_param->source_format == dm_420_8 + && src_param->source_scan == dm_horz) { + plane->swath_height_y = plane->swath_height_y / 2; + } else if (src_param->source_format == dm_420_10 + && src_param->source_scan == dm_horz) { + plane->swath_height_c = plane->swath_height_c / 2; + } + } + } + + if (plane->swath_height_c == 0) { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0; + } else if (plane->swath_height_c <= plane->swath_height_y) { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0; + } else { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 * 2.0 / 3.0; + } +} + +static void calc_display_pipe_line_delivery_time( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].v_ratio <= 1.0) { + planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y + * planes[i].num_dpp / planes[i].h_ratio + / planes[i].pixclk_mhz; + } else { + double dchub_pscl_bw_per_clk; + + if (planes[i].h_ratio > 1) { + double num_hscl_kernels; + + num_hscl_kernels = dml_ceil((double) planes[i].h_taps / 6); + dchub_pscl_bw_per_clk = + dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + mode_lib->ip.max_pscl_lb_bw_pix_per_clk + * planes[i].h_ratio + / num_hscl_kernels); + } else { + dchub_pscl_bw_per_clk = + dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); + } + + planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y + / dchub_pscl_bw_per_clk / planes[i].dppclk_mhz; + } + } +} + +static double calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 0.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + double swath_width_y_plane = planes[i].swath_width_y * planes[i].num_dpp; + + planes[i].read_bw = swath_width_y_plane + * (dml_ceil(planes[i].bytes_per_pixel_y) + + dml_ceil_2(planes[i].bytes_per_pixel_c) / 2) + / (planes[i].h_total / planes[i].pixclk_mhz) * planes[i].v_ratio; + + val += planes[i].read_bw; + + DTRACE("plane[%d] start", i); + DTRACE("read_bw = %f", planes[i].read_bw); + DTRACE("plane[%d] end", i); + } + + return val; +} + +double dml_wm_calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + return calc_total_data_read_bw(mode_lib, planes, num_planes); +} + +static double calc_dcfclk_mhz( + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double dcfclk_mhz = -1.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == planes[i].dcfclk_mhz); + dcfclk_mhz = planes[i].dcfclk_mhz; + } + + return dcfclk_mhz; +} + +static enum voltage_state find_voltage( + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + int voltage = -1; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + ASSERT(voltage == -1 || voltage == planes[i].voltage); + voltage = planes[i].voltage; + } + + return (enum voltage_state) voltage; +} + +static bool find_dcc_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + return true; + } + } + + return false; +} + +static double calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + struct _vcs_dpi_soc_bounding_box_st *soc; + double return_bw_mbps; + double dcfclk_mhz; + double return_bus_bw; + enum voltage_state voltage; + double return_bw_to_dcn; + bool dcc_enable; + double rob_chunk_diff; + double urgent_latency_traffic; + double critical_compression; + struct _vcs_dpi_voltage_scaling_st state; + + soc = &mode_lib->soc; + + dcfclk_mhz = calc_dcfclk_mhz(planes, num_planes); + return_bus_bw = dcfclk_mhz * soc->return_bus_width_bytes; + + DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); + DTRACE("INTERMEDIATE return_bus_bw = %f", return_bus_bw); + + voltage = find_voltage(planes, num_planes); + return_bw_to_dcn = dml_socbb_return_bw_mhz(soc, voltage); + + dcc_enable = find_dcc_enable(planes, num_planes); + + return_bw_mbps = return_bw_to_dcn; + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + + rob_chunk_diff = + (mode_lib->ip.rob_buffer_size_kbytes - mode_lib->ip.pixel_chunk_size_kbytes) + * 1024.0; + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + + if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { + double dcc_return_bw = + return_bw_to_dcn * 4.0 + * (1.0 + - soc->urgent_latency_us + / (rob_chunk_diff + / (return_bw_to_dcn + - return_bus_bw + / 4.0) + + soc->urgent_latency_us)); + return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); + DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); + } + + urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + critical_compression = 2.0 * urgent_latency_traffic + / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); + DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); + + if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { + double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff + * urgent_latency_traffic); + crit_return_bw = crit_return_bw + / dml_pow( + return_bw_to_dcn * soc->urgent_latency_us + + rob_chunk_diff, + 2); + DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); + return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); + } + + /* Gabe does this again for some reason using the value of return_bw_mpbs from the previous calculation + * and a lightly different return_bw_to_dcn + */ + + state = dml_socbb_voltage_scaling(soc, voltage); + return_bw_to_dcn = dml_min( + soc->return_bus_width_bytes * dcfclk_mhz, + state.dram_bw_per_chan_gbps * 1000.0 * (double) soc->num_chans); + + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + + if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { + double dcc_return_bw = + return_bw_to_dcn * 4.0 + * (1.0 + - soc->urgent_latency_us + / (rob_chunk_diff + / (return_bw_to_dcn + - return_bus_bw + / 4.0) + + soc->urgent_latency_us)); + return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); + DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); + } + + urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + critical_compression = 2.0 * urgent_latency_traffic + / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); + DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); + + /* problem here? */ + if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { + double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff + * urgent_latency_traffic); + crit_return_bw = crit_return_bw + / dml_pow( + return_bw_to_dcn * soc->urgent_latency_us + + rob_chunk_diff, + 2); + DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); + DTRACE("INTERMEDIATE return_bw_to_dcn = %f", return_bw_to_dcn); + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + + return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); + } + + DTRACE("INTERMEDIATE final return_bw_mbps = %f", return_bw_mbps); + return return_bw_mbps; +} + +double dml_wm_calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + return calc_return_bw(mode_lib, planes, num_planes); +} + +static double calc_last_pixel_of_line_extra_wm_us( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 0.0; + double total_data_read_bw = calc_total_data_read_bw(mode_lib, planes, num_planes); + int voltage = -1; + unsigned int i; + double return_bw_mbps; + + for (i = 0; i < num_planes; i++) { + /* voltage mode must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == planes[i].voltage); + voltage = planes[i].voltage; + } + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + for (i = 0; i < num_planes; i++) { + double bytes_pp_y = dml_ceil(planes[i].bytes_per_pixel_y); + double bytes_pp_c = dml_ceil_2(planes[i].bytes_per_pixel_c); + double swath_bytes_y = (double) planes[i].swath_width_y + * (double) planes[i].swath_height_y * (double) bytes_pp_y; + double swath_bytes_c = ((double) planes[i].swath_width_y / 2.0) + * (double) planes[i].swath_height_c * (double) bytes_pp_c; + double data_fabric_line_delivery_time = (swath_bytes_y + swath_bytes_c) + / (return_bw_mbps * planes[i].read_bw / (double) planes[i].num_dpp + / total_data_read_bw); + + DTRACE( + "bytes_pp_y = %f, swath_width_y = %f, swath_height_y = %f, swath_bytes_y = %f", + bytes_pp_y, + (double) planes[i].swath_width_y, + (double) planes[i].swath_height_y, + swath_bytes_y); + DTRACE( + "bytes_pp_c = %f, swath_width_c = %f, swath_height_c = %f, swath_bytes_c = %f", + bytes_pp_c, + ((double) planes[i].swath_width_y / 2.0), + (double) planes[i].swath_height_c, + swath_bytes_c); + DTRACE( + "return_bw_mbps = %f, read_bw = %f, num_dpp = %d, total_data_read_bw = %f", + return_bw_mbps, + planes[i].read_bw, + planes[i].num_dpp, + total_data_read_bw); + DTRACE("data_fabric_line_delivery_time = %f", data_fabric_line_delivery_time); + DTRACE( + "display_pipe_line_delivery_time = %f", + planes[i].display_pipe_line_delivery_time); + + val = dml_max( + val, + data_fabric_line_delivery_time + - planes[i].display_pipe_line_delivery_time); + } + + DTRACE("last_pixel_of_line_extra_wm is %f us", val); + return val; +} + +static bool calc_pte_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].pte_enable) { + return true; + } + } + + return false; +} + +static void calc_lines_in_det_y(struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + plane->lines_in_det_y = plane->det_buffer_size_y / plane->bytes_per_pixel_y + / plane->swath_width_y; + plane->lines_in_det_y_rounded_down_to_swath = dml_floor( + (double) plane->lines_in_det_y / plane->swath_height_y) + * plane->swath_height_y; + plane->full_det_buffering_time = plane->lines_in_det_y_rounded_down_to_swath + * (plane->h_total / plane->pixclk_mhz); +} + +/* CHECKME: not obviously 1:1 with calculation described in architectural + * document or spreadsheet */ +static void calc_dcfclk_deepsleep_mhz_per_plane( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + double bus_width_per_pixel; + + if (plane->swath_height_c == 0) { + bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 64; + } else { + double bus_width_per_pixel_c; + + bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 32; + bus_width_per_pixel_c = dml_ceil(plane->bytes_per_pixel_c) / 32; + if (bus_width_per_pixel < bus_width_per_pixel_c) + bus_width_per_pixel = bus_width_per_pixel_c; + } + + if (plane->v_ratio <= 1) { + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->pixclk_mhz / plane->num_dpp + * plane->h_ratio * bus_width_per_pixel; + } else if (plane->h_ratio > 1) { + double num_hscl_kernels = dml_ceil((double) plane->h_taps / 6); + double dchub_pscl_bw_per_clk = dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + mode_lib->ip.max_pscl_lb_bw_pix_per_clk * plane->h_ratio + / num_hscl_kernels); + + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz + * dchub_pscl_bw_per_clk * bus_width_per_pixel; + } else { + double dchub_pscl_bw_per_clk = dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); + + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz + * dchub_pscl_bw_per_clk * bus_width_per_pixel; + } + + plane->dcfclk_deepsleep_mhz_per_plane = dml_max( + plane->dcfclk_deepsleep_mhz_per_plane, + plane->pixclk_mhz / 16); +} + +/* Implementation of expected stutter efficiency from DCN1_Display_Mode.docx */ +double dml_wm_expected_stutter_eff_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + double min_full_det_buffering_time_us; + double frame_time_for_min_full_det_buffering_time_us = 0.0; + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + unsigned int i; + double total_data_read_bw_mbps; + double average_read_bw_gbps; + double min_full_det_buffer_size_bytes; + double rob_fill_size_bytes; + double part_of_burst_that_fits_in_rob; + int voltage; + double dcfclk_mhz; + unsigned int total_writeback; + double return_bw_mbps; + double stutter_burst_time_us; + double stutter_eff_not_including_vblank; + double smallest_vblank_us; + double stutter_eff; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + DTRACE("calculating expected stutter efficiency"); + + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); + + for (i = 0; i < num_planes; i++) { + calc_lines_in_det_y(&planes[i]); + + DTRACE("swath width y plane %d = %d", i, planes[i].swath_width_y); + DTRACE("swath height y plane %d = %d", i, planes[i].swath_height_y); + DTRACE( + "bytes per pixel det y plane %d = %f", + i, + planes[i].bytes_per_pixel_y); + DTRACE( + "bytes per pixel det c plane %d = %f", + i, + planes[i].bytes_per_pixel_c); + DTRACE( + "det buffer size plane %d = %d", + i, + planes[i].det_buffer_size_y); + DTRACE("lines in det plane %d = %d", i, planes[i].lines_in_det_y); + DTRACE( + "lines in det rounded to swaths plane %d = %d", + i, + planes[i].lines_in_det_y_rounded_down_to_swath); + } + + min_full_det_buffering_time_us = 9999.0; + for (i = 0; i < num_planes; i++) { + if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { + min_full_det_buffering_time_us = planes[i].full_det_buffering_time; + frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total + * planes[i].h_total / planes[i].pixclk_mhz; + } + } + + DTRACE("INTERMEDIATE: min_full_det_buffering_time_us = %f", min_full_det_buffering_time_us); + + total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); + + average_read_bw_gbps = 0.0; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; + } else { + average_read_bw_gbps += planes[i].read_bw / 1000; + } + + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 256; + } + + if (planes[i].pte_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 512; + } + } + + min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; + rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps + / (average_read_bw_gbps * 1000); + part_of_burst_that_fits_in_rob = dml_min( + min_full_det_buffer_size_bytes, + rob_fill_size_bytes); + + voltage = -1; + dcfclk_mhz = -1.0; + total_writeback = 0; + + for (i = 0; i < num_pipes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); + voltage = e2e[i].clks_cfg.voltage; + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); + dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + + if (e2e[i].dout.output_type == dm_wb) + total_writeback++; + } + + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + DTRACE("INTERMEDIATE: part_of_burst_that_fits_in_rob = %f", part_of_burst_that_fits_in_rob); + DTRACE("INTERMEDIATE: average_read_bw_gbps = %f", average_read_bw_gbps); + DTRACE("INTERMEDIATE: total_data_read_bw_mbps = %f", total_data_read_bw_mbps); + DTRACE("INTERMEDIATE: return_bw_mbps = %f", return_bw_mbps); + + stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) + / total_data_read_bw_mbps / return_bw_mbps + + (min_full_det_buffering_time_us * total_data_read_bw_mbps + - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); + DTRACE("INTERMEDIATE: stutter_burst_time_us = %f", stutter_burst_time_us); + + if (total_writeback == 0) { + stutter_eff_not_including_vblank = (1.0 + - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) + / min_full_det_buffering_time_us)) * 100.0; + } else { + stutter_eff_not_including_vblank = 0.0; + } + + DTRACE("stutter_efficiency_not_including_vblank = %f", stutter_eff_not_including_vblank); + + smallest_vblank_us = 9999.0; + + for (i = 0; i < num_pipes; i++) { + double vblank_us; + if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { + vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 + - e2e[i].pipe.dest.vblank_start + + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) + / e2e[i].pipe.dest.pixel_rate_mhz; + } else { + vblank_us = 0.0; + } + + smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); + } + + DTRACE("smallest vblank = %f us", smallest_vblank_us); + + stutter_eff = 100.0 + * (((stutter_eff_not_including_vblank / 100.0) + * (frame_time_for_min_full_det_buffering_time_us + - smallest_vblank_us) + smallest_vblank_us) + / frame_time_for_min_full_det_buffering_time_us); + + DTRACE("stutter_efficiency = %f", stutter_eff); + + return stutter_eff_not_including_vblank; +} + +double dml_wm_expected_stutter_eff_e2e_with_vblank( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + double min_full_det_buffering_time_us; + double frame_time_for_min_full_det_buffering_time_us = 0.0; + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + unsigned int i; + double total_data_read_bw_mbps; + double average_read_bw_gbps; + double min_full_det_buffer_size_bytes; + double rob_fill_size_bytes; + double part_of_burst_that_fits_in_rob; + int voltage; + double dcfclk_mhz; + unsigned int total_writeback; + double return_bw_mbps; + double stutter_burst_time_us; + double stutter_eff_not_including_vblank; + double smallest_vblank_us; + double stutter_eff; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); + + for (i = 0; i < num_planes; i++) { + calc_lines_in_det_y(&planes[i]); + } + + min_full_det_buffering_time_us = 9999.0; + for (i = 0; i < num_planes; i++) { + if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { + min_full_det_buffering_time_us = planes[i].full_det_buffering_time; + frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total + * planes[i].h_total / planes[i].pixclk_mhz; + } + } + + total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); + average_read_bw_gbps = 0.0; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; + } else { + average_read_bw_gbps += planes[i].read_bw / 1000; + } + + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 256; + } + + if (planes[i].pte_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 512; + } + } + + min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; + rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps + / (average_read_bw_gbps * 1000); + part_of_burst_that_fits_in_rob = dml_min( + min_full_det_buffer_size_bytes, + rob_fill_size_bytes); + + voltage = -1; + dcfclk_mhz = -1.0; + total_writeback = 0; + + for (i = 0; i < num_pipes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); + voltage = e2e[i].clks_cfg.voltage; + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); + dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + + if (e2e[i].dout.output_type == dm_wb) + total_writeback++; + } + + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) + / total_data_read_bw_mbps / return_bw_mbps + + (min_full_det_buffering_time_us * total_data_read_bw_mbps + - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); + + if (total_writeback == 0) { + stutter_eff_not_including_vblank = (1.0 + - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) + / min_full_det_buffering_time_us)) * 100.0; + } else { + stutter_eff_not_including_vblank = 0.0; + } + + smallest_vblank_us = 9999.0; + + for (i = 0; i < num_pipes; i++) { + double vblank_us; + if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { + vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 + - e2e[i].pipe.dest.vblank_start + + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) + / e2e[i].pipe.dest.pixel_rate_mhz; + } else { + vblank_us = 0.0; + } + + smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); + } + + stutter_eff = 100.0 + * (((stutter_eff_not_including_vblank / 100.0) + * (frame_time_for_min_full_det_buffering_time_us + - smallest_vblank_us) + smallest_vblank_us) + / frame_time_for_min_full_det_buffering_time_us); + + + return stutter_eff; +} + +double urgent_extra_calc( + struct display_mode_lib *mode_lib, + double dcfclk_mhz, + double return_bw_mbps, + unsigned int total_active_dpp, + unsigned int total_dcc_active_dpp) +{ + double urgent_extra_latency_us = 0.0; + double urgent_round_trip_ooo_latency_us; + + urgent_round_trip_ooo_latency_us = + (((double) mode_lib->soc.round_trip_ping_latency_dcfclk_cycles + 32) + / dcfclk_mhz) + + (((double) (mode_lib->soc.urgent_out_of_order_return_per_channel_bytes + * mode_lib->soc.num_chans)) / return_bw_mbps); + + DTRACE( + "INTERMEDIATE round_trip_ping_latency_dcfclk_cycles = %d", + mode_lib->soc.round_trip_ping_latency_dcfclk_cycles); + DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); + DTRACE( + "INTERMEDIATE urgent_out_of_order_return_per_channel_bytes = %d", + mode_lib->soc.urgent_out_of_order_return_per_channel_bytes); + + urgent_extra_latency_us = urgent_round_trip_ooo_latency_us + + ((double) total_active_dpp * mode_lib->ip.pixel_chunk_size_kbytes + + (double) total_dcc_active_dpp + * mode_lib->ip.meta_chunk_size_kbytes) + * 1024.0 / return_bw_mbps; /* to us */ + + DTRACE( + "INTERMEDIATE urgent_round_trip_ooo_latency_us = %f", + urgent_round_trip_ooo_latency_us); + DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); + DTRACE( + "INTERMEDIATE pixel_chunk_size_kbytes = %d", + mode_lib->ip.pixel_chunk_size_kbytes); + DTRACE("INTERMEDIATE total_dcc_active_dpp = %d", total_dcc_active_dpp); + DTRACE( + "INTERMEDIATE meta_chunk_size_kbyte = %d", + mode_lib->ip.meta_chunk_size_kbytes); + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + + return urgent_extra_latency_us; +} + +double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib) +{ + unsigned int total_active_dpp = DC__NUM_DPP; + unsigned int total_dcc_active_dpp = total_active_dpp; + double urgent_extra_latency_us = 0.0; + double dcfclk_mhz = 0.0; + double return_bw_mbps = 0.0; + int voltage = dm_vmin; + + /* use minimum voltage */ + return_bw_mbps = dml_socbb_return_bw_mhz(&mode_lib->soc, (enum voltage_state) voltage); + /* use minimum dcfclk */ + dcfclk_mhz = mode_lib->soc.vmin.dcfclk_mhz; + /* use max dpps and dpps with dcc */ + + urgent_extra_latency_us = urgent_extra_calc( + mode_lib, + dcfclk_mhz, + return_bw_mbps, + total_active_dpp, + total_dcc_active_dpp); + + DTRACE("urgent extra max = %f", urgent_extra_latency_us); + return urgent_extra_latency_us; +} + +double dml_wm_urgent_extra( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int total_active_dpp = 0; + unsigned int total_dcc_active_dpp = 0; + double urgent_extra_latency_us = 0.0; + double dcfclk_mhz = 0.0; + double return_bw_mbps = 0.0; + int voltage = -1; + bool pte_enable = false; + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + /* num_dpp must be greater than 0 */ + ASSERT(pipes[i].num_dpp > 0); + + /* voltage mode must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == pipes[i].voltage); + voltage = pipes[i].voltage; + + /* dcfclk for all pipes must be the same */ + ASSERT(dcfclk_mhz == 0.0 || dcfclk_mhz == pipes[i].dcfclk_mhz); + dcfclk_mhz = pipes[i].dcfclk_mhz; + + total_active_dpp += pipes[i].num_dpp; + + if (pipes[i].dcc_enable) { + total_dcc_active_dpp += pipes[i].num_dpp; + } + } + + DTRACE("total active dpps %d", total_active_dpp); + DTRACE("total active dpps with dcc %d", total_dcc_active_dpp); + DTRACE("voltage state is %d", voltage); + + return_bw_mbps = calc_return_bw(mode_lib, pipes, num_pipes); + + DTRACE("return_bandwidth is %f MBps", return_bw_mbps); + + pte_enable = calc_pte_enable(pipes, num_pipes); + + /* calculate the maximum extra latency just for comparison purposes */ + /* dml_wm_urgent_extra_max(); */ + urgent_extra_latency_us = urgent_extra_calc( + mode_lib, + dcfclk_mhz, + return_bw_mbps, + total_active_dpp, + total_dcc_active_dpp); + + DTRACE("INTERMEDIATE urgent_extra_latency_us_before_pte = %f", urgent_extra_latency_us); + + if (pte_enable) { + urgent_extra_latency_us += total_active_dpp * mode_lib->ip.pte_chunk_size_kbytes + * 1024.0 / return_bw_mbps; + + DTRACE("INTERMEDIATE pte_enable = true"); + DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); + DTRACE( + "INTERMEDIATE pte_chunk_size_kbytes = %d", + mode_lib->ip.pte_chunk_size_kbytes); + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + } + + return urgent_extra_latency_us; +} + +double dml_wm_urgent_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + double urgent_wm; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + + urgent_wm = dml_wm_urgent(mode_lib, wm, combined_pipes); + + return urgent_wm; +} + +double dml_wm_urgent( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double urgent_watermark; + double urgent_extra_latency_us; + double last_pixel_of_line_extra_wm_us = 0.0; + + DTRACE("calculating urgent watermark"); + calc_display_pipe_line_delivery_time(mode_lib, planes, num_planes); + urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, planes, num_planes); + + last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( + mode_lib, + planes, + num_planes); + + urgent_watermark = mode_lib->soc.urgent_latency_us + last_pixel_of_line_extra_wm_us + + urgent_extra_latency_us; + + DTRACE("INTERMEDIATE urgent_latency_us = %f", mode_lib->soc.urgent_latency_us); + DTRACE("INTERMEDIATE last_pixel_of_line_extra_wm_us = %f", last_pixel_of_line_extra_wm_us); + DTRACE("INTERMEDIATE urgent_extra_latency_us = %f", urgent_extra_latency_us); + + DTRACE("urgent_watermark_us = %f", urgent_watermark); + return urgent_watermark; +} + +double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us) +{ + double val; + + val = urgent_wm_us + 2.0 * mode_lib->soc.urgent_latency_us; + DTRACE("pte_meta_urgent_watermark_us = %f", val); + + return val; +} + +double dml_wm_dcfclk_deepsleep_mhz_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + double val; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + num_planes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, planes); + + val = dml_wm_dcfclk_deepsleep_mhz(mode_lib, planes, num_planes); + + return val; +} + +double dml_wm_dcfclk_deepsleep_mhz( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 8.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + calc_dcfclk_deepsleep_mhz_per_plane(mode_lib, &planes[i]); + + if (val < planes[i].dcfclk_deepsleep_mhz_per_plane) { + val = planes[i].dcfclk_deepsleep_mhz_per_plane; + } + + DTRACE("plane[%d] start", i); + DTRACE("dcfclk_deepsleep_per_plane = %f", planes[i].dcfclk_deepsleep_mhz_per_plane); + DTRACE("plane[%d] end", i); + } + + DTRACE("dcfclk_deepsleep_mhz = %f", val); + + return val; +} + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + cstate_pstate_wm = dml_wm_cstate_pstate(mode_lib, wm, combined_pipes); + + + return cstate_pstate_wm; +} + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_cstate_pstate_watermarks_st wm; + double urgent_extra_latency_us; + double urgent_watermark_us; + double last_pixel_of_line_extra_wm_us; + double dcfclk_deepsleep_freq; + + DTRACE("calculating cstate and pstate watermarks"); + urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, pipes, num_pipes); + urgent_watermark_us = dml_wm_urgent(mode_lib, pipes, num_pipes); + + last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( + mode_lib, + pipes, + num_pipes); + dcfclk_deepsleep_freq = dml_wm_dcfclk_deepsleep_mhz(mode_lib, pipes, num_pipes); + + wm.cstate_exit_us = mode_lib->soc.sr_exit_time_us + last_pixel_of_line_extra_wm_us + + urgent_extra_latency_us + + mode_lib->ip.dcfclk_cstate_latency / dcfclk_deepsleep_freq; + wm.cstate_enter_plus_exit_us = mode_lib->soc.sr_enter_plus_exit_time_us + + last_pixel_of_line_extra_wm_us + urgent_extra_latency_us; + wm.pstate_change_us = mode_lib->soc.dram_clock_change_latency_us + urgent_watermark_us; + + DTRACE("stutter_exit_watermark_us = %f", wm.cstate_exit_us); + DTRACE("stutter_enter_plus_exit_watermark_us = %f", wm.cstate_enter_plus_exit_us); + DTRACE("dram_clock_change_watermark_us = %f", wm.pstate_change_us); + + return wm; +} + +double dml_wm_writeback_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + + + return dml_wm_writeback_pstate(mode_lib, wm, combined_pipes); +} + +double dml_wm_writeback_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int total_active_wb = 0; + double wm = 0.0; + double socclk_mhz = 0.0; + unsigned int i; + + DTRACE("calculating wb pstate watermark"); + for (i = 0; i < num_pipes; i++) { + if (pipes[i].output_type == dm_wb) + total_active_wb++; + ASSERT(socclk_mhz == 0.0 || socclk_mhz == pipes[i].socclk_mhz); + socclk_mhz = pipes[i].socclk_mhz; + } + + DTRACE("total wb outputs %d", total_active_wb); + DTRACE("socclk frequency %f Mhz", socclk_mhz); + + if (total_active_wb <= 1) { + wm = mode_lib->soc.writeback_dram_clock_change_latency_us; + } else { + wm = mode_lib->soc.writeback_dram_clock_change_latency_us + + (mode_lib->ip.writeback_chunk_size_kbytes * 1024.0) / 32.0 + / socclk_mhz; + } + + DTRACE("wb pstate watermark %f us", wm); + return wm; +} + +unsigned int dml_wm_e2e_to_wm( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + struct _vcs_dpi_wm_calc_pipe_params_st *wm) +{ + unsigned int num_planes = 0; + bool visited[DC__NUM_PIPES]; + unsigned int i, j; + + for (i = 0; i < num_pipes; i++) { + visited[i] = false; + } + + for (i = 0; i < num_pipes; i++) { + unsigned int num_dpp = 1; + + if (visited[i]) { + continue; + } + + visited[i] = true; + + if (e2e[i].pipe.src.is_hsplit) { + for (j = i + 1; j < num_pipes; j++) { + if (e2e[j].pipe.src.is_hsplit && !visited[j] + && (e2e[i].pipe.src.hsplit_grp + == e2e[j].pipe.src.hsplit_grp)) { + num_dpp++; + visited[j] = true; + } + } + } + + wm[num_planes].num_dpp = num_dpp; + wm[num_planes].voltage = e2e[i].clks_cfg.voltage; + wm[num_planes].output_type = e2e[i].dout.output_type; + wm[num_planes].dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + wm[num_planes].socclk_mhz = e2e[i].clks_cfg.socclk_mhz; + wm[num_planes].dppclk_mhz = e2e[i].clks_cfg.dppclk_mhz; + wm[num_planes].pixclk_mhz = e2e[i].pipe.dest.pixel_rate_mhz; + + wm[num_planes].pte_enable = e2e[i].pipe.src.vm; + wm[num_planes].dcc_enable = e2e[i].pipe.src.dcc; + wm[num_planes].dcc_rate = e2e[i].pipe.src.dcc_rate; + + get_bytes_per_pixel( + (enum source_format_class) e2e[i].pipe.src.source_format, + &wm[num_planes]); + wm[num_planes].swath_width_y = get_swath_width_y(&e2e[i].pipe.src, num_dpp); + get_swath_height( + mode_lib, + &e2e[i].pipe.src, + &wm[num_planes], + wm[num_planes].swath_width_y); + + wm[num_planes].interlace_en = e2e[i].pipe.dest.interlaced; + wm[num_planes].h_ratio = e2e[i].pipe.scale_ratio_depth.hscl_ratio; + wm[num_planes].v_ratio = e2e[i].pipe.scale_ratio_depth.vscl_ratio; + if (wm[num_planes].interlace_en) { + wm[num_planes].v_ratio = 2 * wm[num_planes].v_ratio; + } + wm[num_planes].h_taps = e2e[i].pipe.scale_taps.htaps; + wm[num_planes].h_total = e2e[i].pipe.dest.htotal; + wm[num_planes].v_total = e2e[i].pipe.dest.vtotal; + wm[num_planes].v_active = e2e[i].pipe.dest.vactive; + wm[num_planes].e2e_index = i; + num_planes++; + } + + for (i = 0; i < num_planes; i++) { + DTRACE("plane[%d] start", i); + DTRACE("voltage = %d", wm[i].voltage); + DTRACE("v_active = %d", wm[i].v_active); + DTRACE("h_total = %d", wm[i].h_total); + DTRACE("v_total = %d", wm[i].v_total); + DTRACE("pixclk_mhz = %f", wm[i].pixclk_mhz); + DTRACE("dcfclk_mhz = %f", wm[i].dcfclk_mhz); + DTRACE("dppclk_mhz = %f", wm[i].dppclk_mhz); + DTRACE("h_ratio = %f", wm[i].h_ratio); + DTRACE("v_ratio = %f", wm[i].v_ratio); + DTRACE("interlaced = %d", wm[i].interlace_en); + DTRACE("h_taps = %d", wm[i].h_taps); + DTRACE("num_dpp = %d", wm[i].num_dpp); + DTRACE("swath_width_y = %d", wm[i].swath_width_y); + DTRACE("swath_height_y = %d", wm[i].swath_height_y); + DTRACE("swath_height_c = %d", wm[i].swath_height_c); + DTRACE("det_buffer_size_y = %d", wm[i].det_buffer_size_y); + DTRACE("dcc_rate = %f", wm[i].dcc_rate); + DTRACE("dcc_enable = %s", wm[i].dcc_enable ? "true" : "false"); + DTRACE("pte_enable = %s", wm[i].pte_enable ? "true" : "false"); + DTRACE("plane[%d] end", i); + } + + return num_planes; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h new file mode 100644 index 000000000000..94cde8b55e08 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h @@ -0,0 +1,98 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_WATERMARK_H__ +#define __DISPLAY_WATERMARK_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +double dml_wm_urgent_extra( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib); + +double dml_wm_urgent_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_urgent( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); +double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us); +double dml_wm_dcfclk_deepsleep_mhz_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_dcfclk_deepsleep_mhz( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); + +double dml_wm_writeback_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_writeback_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); + +double dml_wm_expected_stutter_eff_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); +double dml_wm_expected_stutter_eff_e2e_with_vblank( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); + +unsigned int dml_wm_e2e_to_wm( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + struct _vcs_dpi_wm_calc_pipe_params_st *wm); + +double dml_wm_calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); +double dml_wm_calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c new file mode 100644 index 000000000000..21349a022de3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -0,0 +1,148 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dml_common_defs.h" +#include "../calcs/dcn_calc_math.h" + +double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +double dml_ceil(double a) +{ + return (double) dcn_bw_ceil2(a, 1); +} + +double dml_floor(double a) +{ + return (double) dcn_bw_floor2(a, 1); +} + +double dml_round(double a) +{ + double round_pt = 0.5; + double ceil = dml_ceil(a); + double floor = dml_floor(a); + + if (a - floor >= round_pt) + return ceil; + else + return floor; +} + +int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + +unsigned int dml_round_to_multiple( + unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} + +double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + +bool dml_util_is_420(enum source_format_class sorce_format) +{ + bool val = false; + + switch (sorce_format) { + case dm_444_16: + val = false; + break; + case dm_444_32: + val = false; + break; + case dm_444_64: + val = false; + break; + case dm_420_8: + val = true; + break; + case dm_420_10: + val = true; + break; + case dm_422_8: + val = false; + break; + case dm_422_10: + val = false; + break; + default: + BREAK_TO_DEBUGGER(); + } + + return val; +} + +double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h new file mode 100644 index 000000000000..c5340d41eedb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DC_COMMON_DEFS_H__ +#define __DC_COMMON_DEFS_H__ + +#include "dm_services.h" +#include "dc_features.h" +#include "display_mode_structs.h" +#include "display_mode_enums.h" + +#define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); + +double dml_min(double a, double b); +double dml_max(double a, double b); +bool dml_util_is_420(enum source_format_class sorce_format); +double dml_ceil_ex(double x, double granularity); +double dml_floor_ex(double x, double granularity); +double dml_log(double x, double base); +double dml_ceil(double a); +double dml_floor(double a); +double dml_round(double a); +int dml_log2(double x); +double dml_pow(double a, int exp); +unsigned int dml_round_to_multiple( + unsigned int num, unsigned int multiple, bool up); +double dml_fmod(double f, int val); +double dml_ceil_2(double f); + +#endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c new file mode 100644 index 000000000000..cb143d3d40f0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "soc_bounding_box.h" +#include "display_mode_lib.h" + +void dml_socbb_set_latencies( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_soc_bounding_box_st *from_box) +{ + struct _vcs_dpi_soc_bounding_box_st *to_box = &mode_lib->soc; + + to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; + to_box->sr_exit_time_us = from_box->sr_exit_time_us; + to_box->sr_enter_plus_exit_time_us = from_box->sr_enter_plus_exit_time_us; + to_box->urgent_latency_us = from_box->urgent_latency_us; + to_box->writeback_latency_us = from_box->writeback_latency_us; + DTRACE("box.dram_clock_change_latency_us: %f", from_box->dram_clock_change_latency_us); + DTRACE("box.sr_exit_time_us: %f", from_box->sr_exit_time_us); + DTRACE("box.sr_enter_plus_exit_time_us: %f", from_box->sr_enter_plus_exit_time_us); + DTRACE("box.urgent_latency_us: %f", from_box->urgent_latency_us); + DTRACE("box.writeback_latency_us: %f", from_box->writeback_latency_us); + +} + +struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling( + struct _vcs_dpi_soc_bounding_box_st *box, + enum voltage_state voltage) +{ + switch (voltage) { + case dm_vmin: + return box->vmin; + case dm_vnom: + return box->vnom; + case dm_vmax: + default: + return box->vmax; + } +} + +double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage) +{ + double return_bw; + + struct _vcs_dpi_voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); + + return_bw = dml_min( + ((double) box->return_bus_width_bytes) * state.dcfclk_mhz, + state.dram_bw_per_chan_gbps * 1000.0 * (double) box->num_chans + * box->ideal_dram_bw_after_urgent_percent / 100.0); + return return_bw; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h new file mode 100644 index 000000000000..7bbae33f163e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __SOC_BOUNDING_BOX_H__ +#define __SOC_BOUNDING_BOX_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +void dml_socbb_set_latencies(struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box); +struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); +double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); + +#endif -- GitLab From 981ab3f1dc3949b45e317e343dfc232a102847aa Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:21:44 -0400 Subject: [PATCH 0427/2898] drm/amdgpu/display: Add gpio support for DCN GPIOs are used for i2c and other things. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/gpio/dcn10/hw_factory_dcn10.c | 192 +++++++++ .../display/dc/gpio/dcn10/hw_factory_dcn10.h | 32 ++ .../dc/gpio/dcn10/hw_translate_dcn10.c | 408 ++++++++++++++++++ .../dc/gpio/dcn10/hw_translate_dcn10.h | 34 ++ 4 files changed, 666 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.h diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c new file mode 100644 index 000000000000..409763c70ce5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c @@ -0,0 +1,192 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" + +#include "hw_factory_dcn10.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#define block HPD +#define reg_num 0 + +/* set field name */ +#define SF_HPD(reg_name, field_name, post_fix)\ + .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define REG(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define REGI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + + +/* fucntion table */ +static const struct hw_factory_funcs funcs = { + .create_ddc_data = dal_hw_ddc_create, + .create_ddc_clock = dal_hw_ddc_create, + .create_generic = NULL, + .create_hpd = dal_hw_hpd_create, + .create_sync = NULL, + .create_gsl = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; +/* + * dal_hw_factory_dcn10_init + * + * @brief + * Initialize HW factory function pointers and pin info + * + * @param + * struct hw_factory *factory - [out] struct of function pointers + */ +void dal_hw_factory_dcn10_init(struct hw_factory *factory) +{ + /*TODO check ASIC CAPs*/ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.h new file mode 100644 index 000000000000..2cc7a585b1f8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCN10_H__ +#define __DAL_HW_FACTORY_DCN10_H__ + +/* Initialize HW factory function pointers and pin info */ +void dal_hw_factory_dcn10_init(struct hw_factory *factory); + +#endif /* __DAL_HW_FACTORY_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c new file mode 100644 index 000000000000..64a6915b846b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.c @@ -0,0 +1,408 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +/* + * Pre-requisites: headers required by header of this unit + */ + +#include "hw_translate_dcn10.h" + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define REG(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define REGI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case REG(DC_GPIO_GENERIC_A): + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* HPD */ + case REG(DC_GPIO_HPD_A): + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* SYNCA */ + case REG(DC_GPIO_SYNCA_A): + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* REG(DC_GPIO_GENLK_MASK */ + case REG(DC_GPIO_GENLK_A): + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + ASSERT_CRITICAL(false); + return false; + } + break; + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case REG(DC_GPIO_DDC1_A): + *en = GPIO_DDC_LINE_DDC1; + return true; + case REG(DC_GPIO_DDC2_A): + *en = GPIO_DDC_LINE_DDC2; + return true; + case REG(DC_GPIO_DDC3_A): + *en = GPIO_DDC_LINE_DDC3; + return true; + case REG(DC_GPIO_DDC4_A): + *en = GPIO_DDC_LINE_DDC4; + return true; + case REG(DC_GPIO_DDC5_A): + *en = GPIO_DDC_LINE_DDC5; + return true; + case REG(DC_GPIO_DDC6_A): + *en = GPIO_DDC_LINE_DDC6; + return true; + case REG(DC_GPIO_DDCVGA_A): + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case REG(DC_GPIO_I2CPAD_A): + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case REG(DC_GPIO_PWRSEQ_A): + case REG(DC_GPIO_PAD_STRENGTH_1): + case REG(DC_GPIO_PAD_STRENGTH_2): + case REG(DC_GPIO_DEBUG): + return false; + /* UNEXPECTED */ + default: + ASSERT_CRITICAL(false); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC6: + info->offset = REG(DC_GPIO_DDC6_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = REG(DC_GPIO_I2CPAD_A); + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = REG(DC_GPIO_DDC1_A); + break; + case GPIO_DDC_LINE_DDC2: + info->offset = REG(DC_GPIO_DDC2_A); + break; + case GPIO_DDC_LINE_DDC3: + info->offset = REG(DC_GPIO_DDC3_A); + break; + case GPIO_DDC_LINE_DDC4: + info->offset = REG(DC_GPIO_DDC4_A); + break; + case GPIO_DDC_LINE_DDC5: + info->offset = REG(DC_GPIO_DDC5_A); + break; + case GPIO_DDC_LINE_DDC6: + info->offset = REG(DC_GPIO_DDC6_A); + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = REG(DC_GPIO_DDCVGA_A); + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = REG(DC_GPIO_I2CPAD_A); + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = REG(DC_GPIO_GENERIC_A); + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = REG(DC_GPIO_HPD_A); + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = REG(DC_GPIO_SYNCA_A); + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = REG(DC_GPIO_SYNCA_A); + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = REG(DC_GPIO_GENLK_A); + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + ASSERT_CRITICAL(false); + result = false; + } + break; + case GPIO_ID_VIP_PAD: + default: + ASSERT_CRITICAL(false); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +/* function table */ +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +/* + * dal_hw_translate_dcn10_init + * + * @brief + * Initialize Hw translate function pointers. + * + * @param + * struct hw_translate *tr - [out] struct of function pointers + * + */ +void dal_hw_translate_dcn10_init(struct hw_translate *tr) +{ + tr->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.h new file mode 100644 index 000000000000..9edef53c80a0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCN10_H__ +#define __DAL_HW_TRANSLATE_DCN10_H__ + +struct hw_translate; + +/* Initialize Hw translate function pointers */ +void dal_hw_translate_dcn10_init(struct hw_translate *tr); + +#endif /* __DAL_HW_TRANSLATE_DCN10_H__ */ -- GitLab From f690b1d58002f3adf8c6a3e5b59c637a1cfe3361 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:26:37 -0400 Subject: [PATCH 0428/2898] drm/amdgpu/display: Add i2c/aux support for DCN Implement support for i2c and aux on DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/i2caux/dcn10/i2caux_dcn10.c | 125 ++++++++++++++++++ .../display/dc/i2caux/dcn10/i2caux_dcn10.h | 32 +++++ 2 files changed, 157 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c create mode 100644 drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c new file mode 100644 index 000000000000..9f17d2e4376b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c @@ -0,0 +1,125 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/i2caux_interface.h" +#include "../i2caux.h" +#include "../engine.h" +#include "../i2c_engine.h" +#include "../i2c_sw_engine.h" +#include "../i2c_hw_engine.h" + +#include "../dce110/aux_engine_dce110.h" +#include "../dce110/i2c_hw_engine_dce110.h" +#include "../dce110/i2caux_dce110.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name +/* macros to expend register list macro defined in HW object header file + * end *********************/ + +#define aux_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK \ +} + +#define hw_engine_regs(id)\ +{\ + I2C_HW_ENGINE_COMMON_REG_LIST(id) \ +} + +static const struct dce110_aux_registers dcn10_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5), +}; + +static const struct dce110_i2c_hw_engine_registers dcn10_hw_engine_regs[] = { + hw_engine_regs(1), + hw_engine_regs(2), + hw_engine_regs(3), + hw_engine_regs(4), + hw_engine_regs(5), + hw_engine_regs(6) +}; + +static const struct dce110_i2c_hw_engine_shift i2c_shift = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce110_i2c_hw_engine_mask i2c_mask = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +struct i2caux *dal_i2caux_dcn10_create( + struct dc_context *ctx) +{ + struct i2caux_dce110 *i2caux_dce110 = + dm_alloc(sizeof(struct i2caux_dce110)); + + if (!i2caux_dce110) { + ASSERT_CRITICAL(false); + return NULL; + } + + if (dal_i2caux_dce110_construct( + i2caux_dce110, + ctx, + dcn10_aux_regs, + dcn10_hw_engine_regs, + &i2c_shift, + &i2c_mask)) + return &i2caux_dce110->base; + + ASSERT_CRITICAL(false); + + dm_free(i2caux_dce110); + + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h new file mode 100644 index 000000000000..aeb4a86463d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_I2C_AUX_DCN10_H__ +#define __DAL_I2C_AUX_DCN10_H__ + +struct i2caux *dal_i2caux_dcn10_create( + struct dc_context *ctx); + +#endif /* __DAL_I2C_AUX_DCN10_H__ */ -- GitLab From 1909bed5b4ff407130fb9d896565661add3bcdee Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:28:56 -0400 Subject: [PATCH 0429/2898] drm/amdgpu/display: Add irq support for DCN DCN code for display interrupts. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/irq/dcn10/irq_service_dcn10.c | 361 ++++++++++++++++++ .../display/dc/irq/dcn10/irq_service_dcn10.h | 34 ++ 2 files changed, 395 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.h diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c new file mode 100644 index 000000000000..7577e2903787 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -0,0 +1,361 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "../dce110/irq_service_dce110.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "irq_service_dcn10.h" + +#include "ivsrcid/irqsrcs_dcn_1_0.h" + +enum dc_irq_source to_dal_irq_source_dcn10( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + switch (src_id) { + case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK1; + case DCN_1_0__SRCID__DC_D2_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK2; + case DCN_1_0__SRCID__DC_D3_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK3; + case DCN_1_0__SRCID__DC_D4_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK4; + case DCN_1_0__SRCID__DC_D5_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK5; + case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK6; + case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP1; + case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP2; + case DCN_1_0__SRCID__HUBP2_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP3; + case DCN_1_0__SRCID__HUBP3_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP4; + case DCN_1_0__SRCID__HUBP4_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP5; + case DCN_1_0__SRCID__HUBP5_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP6; + + case DCN_1_0__SRCID__DC_HPD1_INT: + /* generic src_id for all HPD and HPDRX interrupts */ + switch (ext_id) { + case DCN_1_0__CTXID__DC_HPD1_INT: + return DC_IRQ_SOURCE_HPD1; + case DCN_1_0__CTXID__DC_HPD2_INT: + return DC_IRQ_SOURCE_HPD2; + case DCN_1_0__CTXID__DC_HPD3_INT: + return DC_IRQ_SOURCE_HPD3; + case DCN_1_0__CTXID__DC_HPD4_INT: + return DC_IRQ_SOURCE_HPD4; + case DCN_1_0__CTXID__DC_HPD5_INT: + return DC_IRQ_SOURCE_HPD5; + case DCN_1_0__CTXID__DC_HPD6_INT: + return DC_IRQ_SOURCE_HPD6; + case DCN_1_0__CTXID__DC_HPD1_RX_INT: + return DC_IRQ_SOURCE_HPD1RX; + case DCN_1_0__CTXID__DC_HPD2_RX_INT: + return DC_IRQ_SOURCE_HPD2RX; + case DCN_1_0__CTXID__DC_HPD3_RX_INT: + return DC_IRQ_SOURCE_HPD3RX; + case DCN_1_0__CTXID__DC_HPD4_RX_INT: + return DC_IRQ_SOURCE_HPD4RX; + case DCN_1_0__CTXID__DC_HPD5_RX_INT: + return DC_IRQ_SOURCE_HPD5RX; + case DCN_1_0__CTXID__DC_HPD6_RX_INT: + return DC_IRQ_SOURCE_HPD6RX; + default: + return DC_IRQ_SOURCE_INVALID; + } + break; + + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + HPD0_DC_HPD_INT_STATUS, + DC_HPD_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + HPD0_DC_HPD_INT_CONTROL, + DC_HPD_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SRI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ + .enable_reg = SRI(reg1, block, reg_num),\ + .enable_mask = \ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI(reg2, block, reg_num),\ + .ack_mask = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_rx_irq_info_funcs\ + } +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + IRQ_REG_ENTRY(HUBPREQ, reg_num,\ + DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK,\ + DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_CLEAR),\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_EVENT_CLEAR),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VSTARTUP_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VSTARTUP_EVENT_CLEAR),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dcn10[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(0), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_rx_int_entry(0), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + [DC_IRQ_SOURCE_PFLIP4] = dummy_irq_entry(), + [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), +}; + +static const struct irq_service_funcs irq_service_funcs_dcn10 = { + .to_dal_irq_source = to_dal_irq_source_dcn10 +}; + +static bool construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + if (!dal_irq_service_construct(irq_service, init_data)) + return false; + + irq_service->info = irq_source_info_dcn10; + irq_service->funcs = &irq_service_funcs_dcn10; + + return true; +} + +struct irq_service *dal_irq_service_dcn10_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + + if (!irq_service) + return NULL; + + if (construct(irq_service, init_data)) + return irq_service; + + dm_free(irq_service); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.h b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.h new file mode 100644 index 000000000000..fd2ca4d0c316 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCN10_H__ +#define __DAL_IRQ_SERVICE_DCN10_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dcn10_create( + struct irq_service_init_data *init_data); + +#endif -- GitLab From ff5ef99248662ef98a64c11c5370ecd9fbbf57a6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Jun 2017 16:27:42 -0400 Subject: [PATCH 0430/2898] drm/amdgpu/display: Enable DCN in DC Enable DCN in DC. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 7 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 115 +++++++- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 3 +- drivers/gpu/drm/amd/display/dc/Makefile | 5 + .../display/dc/bios/command_table_helper2.c | 5 + drivers/gpu/drm/amd/display/dc/calcs/Makefile | 8 + .../gpu/drm/amd/display/dc/core/dc_resource.c | 19 ++ drivers/gpu/drm/amd/display/dc/dc.h | 18 ++ drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 49 ++++ .../drm/amd/display/dc/dce/dce_clock_source.c | 31 ++ .../drm/amd/display/dc/dce/dce_clock_source.h | 21 ++ .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 15 + .../gpu/drm/amd/display/dc/dce/dce_clocks.h | 9 + drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 245 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 21 ++ .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 15 + .../drm/amd/display/dc/dce/dce_link_encoder.h | 16 +- .../amd/display/dc/dce/dce_stream_encoder.c | 264 ++++++++++++++++++ .../amd/display/dc/dce/dce_stream_encoder.h | 69 +++++ .../display/dc/dce110/dce110_hw_sequencer.c | 29 ++ drivers/gpu/drm/amd/display/dc/dm_services.h | 4 + .../drm/amd/display/dc/dm_services_types.h | 1 + drivers/gpu/drm/amd/display/dc/gpio/Makefile | 11 + .../gpu/drm/amd/display/dc/gpio/hw_factory.c | 9 +- .../drm/amd/display/dc/gpio/hw_translate.c | 9 + .../gpu/drm/amd/display/dc/i2caux/Makefile | 11 + .../gpu/drm/amd/display/dc/i2caux/i2caux.c | 8 + drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 5 + .../gpu/drm/amd/display/dc/inc/core_types.h | 26 ++ .../drm/amd/display/dc/inc/hw/display_clock.h | 7 + drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 1 + .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 41 +++ drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 110 ++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 + .../amd/display/dc/inc/hw/timing_generator.h | 16 ++ drivers/gpu/drm/amd/display/dc/irq/Makefile | 10 + .../gpu/drm/amd/display/dc/irq/irq_service.c | 5 + .../gpu/drm/amd/display/include/dal_asic_id.h | 13 + .../gpu/drm/amd/display/include/dal_types.h | 5 +- 39 files changed, 1250 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 47c8e2940a91..5c3bb3581842 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,6 +17,13 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. +config DRM_AMD_DC_DCN1_0 + bool "DCN 1.0 Raven family" + depends on DRM_AMD_DC + help + Choose this option if you want to have + RV family for display engine + config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" depends on DRM_AMD_DC diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 74e32246ff30..4ec86ed5622f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -49,6 +49,16 @@ #include "modules/inc/mod_freesync.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "ivsrcid/irqsrcs_dcn_1_0.h" + +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" +#include "vega10/soc15ip.h" + +#include "soc15_common.h" +#endif + static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, @@ -930,7 +940,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) int i; unsigned client_id = AMDGPU_IH_CLIENTID_LEGACY; - if (adev->asic_type == CHIP_VEGA10) + if (adev->asic_type == CHIP_VEGA10 || + adev->asic_type == CHIP_RAVEN) client_id = AMDGPU_IH_CLIENTID_DCE; int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; @@ -1003,6 +1014,92 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev) return 0; } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +/* Register IRQ sources and initialize IRQ callbacks */ +static int dcn10_register_irq_handlers(struct amdgpu_device *adev) +{ + struct dc *dc = adev->dm.dc; + struct common_irq_params *c_irq_params; + struct dc_interrupt_params int_params = {0}; + int r; + int i; + + int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; + int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; + + /* Actions of amdgpu_irq_add_id(): + * 1. Register a set() function with base driver. + * Base driver will call set() function to enable/disable an + * interrupt in DC hardware. + * 2. Register amdgpu_dm_irq_handler(). + * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts + * coming from DC hardware. + * amdgpu_dm_irq_handler() will re-direct the interrupt to DC + * for acknowledging and handling. + * */ + + /* Use VSTARTUP interrupt */ + for (i = DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP; + i <= DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP + adev->mode_info.num_crtc - 1; + i++) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, i, &adev->crtc_irq); + + if (r) { + DRM_ERROR("Failed to add crtc irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_crtc_high_irq, c_irq_params); + } + + /* Use GRPH_PFLIP interrupt */ + for (i = DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT; + i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + adev->mode_info.num_crtc - 1; + i++) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, i, &adev->pageflip_irq); + if (r) { + DRM_ERROR("Failed to add page flip irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_pflip_high_irq, c_irq_params); + + } + + /* HPD */ + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT, + &adev->hpd_irq); + if (r) { + DRM_ERROR("Failed to add hpd irq id!\n"); + return r; + } + + register_hpd_handlers(adev); + + return 0; +} +#endif + static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) { int r; @@ -1172,6 +1269,14 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_encoder; } break; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case CHIP_RAVEN: + if (dcn10_register_irq_handlers(dm->adev)) { + DRM_ERROR("DM: Failed to initialize IRQ\n"); + goto fail_free_encoder; + } + break; +#endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); goto fail_free_encoder; @@ -1447,6 +1552,14 @@ static int dm_early_init(void *handle) adev->mode_info.num_dig = 6; adev->mode_info.plane_type = dm_surfaces_type_default; break; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case CHIP_RAVEN: + adev->mode_info.num_crtc = 4; + adev->mode_info.num_hpd = 4; + adev->mode_info.num_dig = 4; + adev->mode_info.plane_type = dm_surfaces_type_default; + break; +#endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0f09e8b903d3..bca6769e7481 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -562,7 +562,8 @@ static void fill_plane_attributes_from_fb( surface->tiling_info.gfx8.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); - if (adev->asic_type == CHIP_VEGA10) { + if (adev->asic_type == CHIP_VEGA10 || + adev->asic_type == CHIP_RAVEN) { /* Fill GFX9 params */ surface->tiling_info.gfx9.num_pipes = adev->gfx.config.gb_addr_config_fields.num_pipes; diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 1a79762425ea..4f83e3011743 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -4,7 +4,12 @@ DC_LIBS = basics bios calcs dce gpio i2caux irq virtual +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +DC_LIBS += dcn10 dml +endif + DC_LIBS += dce120 + DC_LIBS += dce112 DC_LIBS += dce110 DC_LIBS += dce100 diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 1cc3df1d5698..84b1f515aa47 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -53,6 +53,11 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCE_VERSION_11_2: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + *h = dal_cmd_tbl_helper_dce112_get_table2(); + return true; +#endif case DCE_VERSION_12_0: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 63a0edbc32e7..a095472bf4b5 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,8 +3,16 @@ # It calculates Bandwidth and Watermarks values for HW programming # +CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 + BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +BW_CALCS += dcn_calcs.o dcn_calc_math.o dcn_calc_auto.o +endif + AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) AMD_DISPLAY_FILES += $(AMD_DAL_BW_CALCS) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2de86f8364a3..ae8b221c85aa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -39,6 +39,9 @@ #include "dce100/dce100_resource.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/dcn10_resource.h" +#endif #include "dce120/dce120_resource.h" enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) @@ -69,6 +72,11 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) case FAMILY_AI: dc_version = DCE_VERSION_12_0; break; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case FAMILY_RV: + dc_version = DCN_VERSION_1_0; + break; +#endif default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -105,6 +113,13 @@ struct resource_pool *dc_create_resource_pool( res_pool = dce120_create_resource_pool( num_virtual_links, dc); break; + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + res_pool = dcn10_create_resource_pool( + num_virtual_links, dc); + break; +#endif default: break; } @@ -1188,6 +1203,10 @@ static int acquire_first_free_pipe( pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + pipe_ctx->mpc_idx = -1; +#endif + pipe_ctx->stream = stream; return i; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 87675f032949..d74bbdce1090 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -94,7 +94,13 @@ struct dc_surface; struct validate_context; struct dc_cap_funcs { +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + bool (*get_dcc_compression_cap)(const struct dc *dc, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output); +#else int i; +#endif }; struct dc_stream_funcs { @@ -164,6 +170,18 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + bool disable_dpp_power_gate; + bool disable_hubp_power_gate; + bool disable_pplib_wm_range; + bool use_dml_wm; + bool use_max_voltage; + int sr_exit_time_ns; + int sr_enter_plus_exit_time_ns; + int urgent_latency_ns; + int percent_of_ideal_drambw; + int dram_clock_change_latency_ns; +#endif bool disable_pplib_clock_request; bool disable_clock_gate; bool disable_dmcu; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index 56087b36bdeb..e0abd2d49370 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -54,6 +54,22 @@ SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ SR(BIOS_SCRATCH_2) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define ABM_DCN10_REG_LIST(id)\ + ABM_COMMON_REG_LIST_DCE_BASE(), \ + SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ + SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \ + SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ + SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_USER_LEVEL, ABM, id), \ + SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ + SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + NBIO_SR(BIOS_SCRATCH_2) +#endif + #define ABM_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -105,6 +121,39 @@ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define ABM_MASK_SH_LIST_DCN10(mask_sh) \ + ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_VMAX_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \ + BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \ + BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \ + BL1_PWM_USER_LEVEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) +#endif + #define ABM_REG_FIELD_LIST(type) \ type ABM1_HG_NUM_OF_BINS_SEL; \ type ABM1_HG_VMAX_SEL; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index bd4524ef3a37..142b3a01c204 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -586,6 +586,9 @@ static uint32_t dce110_get_pix_clk_dividers( break; case DCE_VERSION_11_2: case DCE_VERSION_12_0: +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: +#endif dce112_get_pix_clk_dividers_helper(clk_src, pll_settings, pix_clk_params); break; @@ -815,6 +818,31 @@ static bool dce110_program_pix_clk( struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); struct bp_pixel_clock_parameters bp_pc_params = {0}; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) { + unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + unsigned dp_dto_ref_kHz = 600000; + /* DPREF clock from FPGA TODO: Does FPGA have this value? */ + unsigned clock_kHz = pll_settings->actual_pix_clk; + + /* For faster simulation, if mode pixe clock less than 290MHz, + * pixel clock can be hard coded to 290Mhz. For 4K mode, pixel clock + * is greater than 500Mhz, need real pixel clock + * clock_kHz = 290000; + */ + /* TODO: un-hardcode when we can set display clock properly*/ + /*clock_kHz = pix_clk_params->requested_pix_clk;*/ + clock_kHz = 290000; + + /* Set DTO values: phase = target clock, modulo = reference clock */ + REG_WRITE(PHASE[inst], clock_kHz); + REG_WRITE(MODULO[inst], dp_dto_ref_kHz); + + /* Enable DTO */ + REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1); + return true; + } +#endif /* First disable SS * ATOMBIOS will enable by default SS on PLL for DP, * do not disable it here @@ -870,6 +898,9 @@ static bool dce110_program_pix_clk( break; case DCE_VERSION_11_2: case DCE_VERSION_12_0: +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: +#endif if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = pll_settings->use_external_clk; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 28984c79fc46..e8bc98b3b622 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -55,6 +55,27 @@ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \ + SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\ + SRII(PHASE, DP_DTO, 0),\ + SRII(PHASE, DP_DTO, 1),\ + SRII(PHASE, DP_DTO, 2),\ + SRII(PHASE, DP_DTO, 3),\ + SRII(MODULO, DP_DTO, 0),\ + SRII(MODULO, DP_DTO, 1),\ + SRII(MODULO, DP_DTO, 2),\ + SRII(MODULO, DP_DTO, 3),\ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1), \ + SRII(PIXEL_RATE_CNTL, OTG, 2), \ + SRII(PIXEL_RATE_CNTL, OTG, 3) + +#define CS_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ + CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) +#endif + #define CS_REG_FIELD_LIST(type) \ type PLL_REF_DIV_SRC; \ type DCCG_DEEP_COLOR_CNTL1; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 81cb138cdc38..6e56d8308d66 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -29,6 +29,10 @@ #include "fixed32_32.h" #include "bios_parser_interface.h" #include "dc.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn_calcs.h" +#include "core_dc.h" +#endif #define TO_DCE_CLOCKS(clocks)\ container_of(clocks, struct dce_disp_clk, base) @@ -400,6 +404,10 @@ static void dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + dce_psr_wait_loop(clk_dce, requested_clk_khz); +#endif + } static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) @@ -596,6 +604,13 @@ static bool dce_apply_clock_voltage_request( } } if (send_request) { +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + /*use dcfclk request voltage*/ + clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock_voltage_req.clocks_in_khz = + dcn_find_dcfclk_suits_all(core_dc, &clk->cur_clocks_value); +#endif dm_pp_apply_clock_for_voltage_request( clk->ctx, &clock_voltage_req); } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 29ff470086e5..103e905291a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -45,6 +45,15 @@ CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define CLK_DCN10_REG_LIST()\ + SR(DPREFCLK_CNTL), \ + SR(DENTIST_DISPCLK_CNTL), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_CNTL_REG) +#endif + #define CLK_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ CLK_SF(DCCG_DFS_DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ CLK_SF(DCCG_DFS_DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index da7f86b61de4..c58328cd787b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -252,12 +252,234 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +bool dcn10_dmcu_load_iram(struct dmcu *dmcu, + unsigned int start_offset, + const char *src, + unsigned int bytes) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int count = 0; + + REG_UPDATE(DMCU_CTRL, DMCU_ENABLE, 1); + + /* Enable write access to IRAM */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 1, + IRAM_WR_ADDR_AUTO_INC, 1); + + REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); + + REG_WRITE(DMCU_IRAM_WR_CTRL, start_offset); + + for (count = 0; count < bytes; count++) + REG_WRITE(DMCU_IRAM_WR_DATA, src[count]); + + /* Disable write access to IRAM to allow dynamic sleep state */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 0, + IRAM_WR_ADDR_AUTO_INC, 0); + + return true; +} + +static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + uint32_t psrStateOffset = 0xf0; + + /* Enable write access to IRAM */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1); + + REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); + + /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ + REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset); + + /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ + *psr_state = REG_READ(DMCU_IRAM_RD_DATA); + + /* Disable write access to IRAM after finished using IRAM + * in order to allow dynamic sleep state + */ + REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); +} + +static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + + unsigned int retryCount; + uint32_t psr_state = 0; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + dmcu_wait_reg_ready_interval, + dmcu_max_retry_on_wait_reg_ready); + + /* setDMCUParam_Cmd */ + if (enable) + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + PSR_ENABLE); + else + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + PSR_EXIT); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* Below loops 1000 x 500us = 500 ms. + * Exit PSR may need to wait 1-2 frames to power up. Timeout after at + * least a few frames. Should never hit the max retry assert below. + */ + for (retryCount = 0; retryCount <= 1000; retryCount++) { + dcn10_get_dmcu_psr_state(dmcu, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + dm_delay_in_microseconds(dmcu->ctx, 500); + } + + /* assert if max retry hit */ + ASSERT(retryCount <= 1000); +} + +static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, + struct core_link *link, + struct psr_context *psr_context) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + + unsigned int dmcu_max_retry_on_wait_reg_ready = 801; + unsigned int dmcu_wait_reg_ready_interval = 100; + + union dce_dmcu_psr_config_data_reg1 masterCmdData1; + union dce_dmcu_psr_config_data_reg2 masterCmdData2; + union dce_dmcu_psr_config_data_reg3 masterCmdData3; + + link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc, + psr_context->psrExitLinkTrainingRequired); + + /* Enable static screen interrupts for PSR supported display */ + /* Disable the interrupt coming from other displays. */ + REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 0, + STATIC_SCREEN2_INT_TO_UC_EN, 0, + STATIC_SCREEN3_INT_TO_UC_EN, 0, + STATIC_SCREEN4_INT_TO_UC_EN, 0); + + switch (psr_context->controllerId) { + /* Driver uses case 1 for unconfigured */ + case 1: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + case 2: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN2_INT_TO_UC_EN, 1); + break; + case 3: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN3_INT_TO_UC_EN, 1); + break; + case 4: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN4_INT_TO_UC_EN, 1); + break; + case 5: + /* CZ/NL only has 4 CRTC!! + * really valid. + * There is no interrupt enable mask for these instances. + */ + break; + case 6: + /* CZ/NL only has 4 CRTC!! + * These are here because they are defined in HW regspec, + * but not really valid. There is no interrupt enable mask + * for these instances. + */ + break; + default: + REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK, + STATIC_SCREEN1_INT_TO_UC_EN, 1); + break; + } + + link->link_enc->funcs->psr_program_secondary_packet(link->link_enc, + psr_context->sdpTransmitLineNumDeadline); + + if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) + REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1); + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + dmcu_wait_reg_ready_interval, + dmcu_max_retry_on_wait_reg_ready); + + /* setDMCUParam_PSRHostConfigData */ + masterCmdData1.u32All = 0; + masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames; + masterCmdData1.bits.hyst_lines = psr_context->hyst_lines; + masterCmdData1.bits.rfb_update_auto_en = + psr_context->rfb_update_auto_en; + masterCmdData1.bits.dp_port_num = psr_context->transmitterId; + masterCmdData1.bits.dcp_sel = psr_context->controllerId; + masterCmdData1.bits.phy_type = psr_context->phyType; + masterCmdData1.bits.frame_cap_ind = + psr_context->psrFrameCaptureIndicationReq; + masterCmdData1.bits.aux_chan = psr_context->channel; + masterCmdData1.bits.aux_repeat = psr_context->aux_repeats; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), + masterCmdData1.u32All); + + masterCmdData2.u32All = 0; + masterCmdData2.bits.dig_fe = psr_context->engineId; + masterCmdData2.bits.dig_be = psr_context->transmitterId; + masterCmdData2.bits.skip_wait_for_pll_lock = + psr_context->skipPsrWaitForPllLock; + masterCmdData2.bits.frame_delay = psr_context->frame_delay; + masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId; + masterCmdData2.bits.num_of_controllers = + psr_context->numberOfControllers; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG2), + masterCmdData2.u32All); + + masterCmdData3.u32All = 0; + masterCmdData3.bits.psr_level = psr_context->psr_level.u32all; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG3), + masterCmdData3.u32All); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, PSR_SET); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +#endif + static const struct dmcu_funcs dce_funcs = { .load_iram = dce_dmcu_load_iram, .set_psr_enable = dce_dmcu_set_psr_enable, .setup_psr = dce_dmcu_setup_psr, }; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +static const struct dmcu_funcs dcn10_funcs = { + .load_iram = dcn10_dmcu_load_iram, + .set_psr_enable = dcn10_dmcu_set_psr_enable, + .setup_psr = dcn10_dmcu_setup_psr, +}; +#endif + static void dce_dmcu_construct( struct dce_dmcu *dmcu_dce, struct dc_context *ctx, @@ -296,6 +518,29 @@ struct dmcu *dce_dmcu_create( return &dmcu_dce->base; } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +struct dmcu *dcn10_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask) +{ + struct dce_dmcu *dmcu_dce = dm_alloc(sizeof(*dmcu_dce)); + + if (dmcu_dce == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_dmcu_construct( + dmcu_dce, ctx, regs, dmcu_shift, dmcu_mask); + + dmcu_dce->base.funcs = &dcn10_funcs; + + return &dmcu_dce->base; +} +#endif + void dce_dmcu_destroy(struct dmcu **dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 7dc25386c2bf..584682ba1f77 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -48,6 +48,12 @@ DMCU_COMMON_REG_LIST_DCE_BASE(), \ SR(DCI_MEM_PWR_STATUS) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define DMCU_DCN10_REG_LIST()\ + DMCU_COMMON_REG_LIST_DCE_BASE(), \ + SR(DMU_MEM_PWR_CNTL) +#endif + #define DMCU_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -76,6 +82,13 @@ DMCU_SF(DCI_MEM_PWR_STATUS, \ DMCU_IRAM_MEM_PWR_STATE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define DMCU_MASK_SH_LIST_DCN10(mask_sh) \ + DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + DMCU_SF(DMU_MEM_PWR_CNTL, \ + DMCU_IRAM_MEM_PWR_STATE, mask_sh) +#endif + #define DMCU_REG_FIELD_LIST(type) \ type DMCU_IRAM_MEM_PWR_STATE; \ type IRAM_HOST_ACCESS_EN; \ @@ -190,6 +203,14 @@ struct dmcu *dce_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +struct dmcu *dcn10_dmcu_create( + struct dc_context *ctx, + const struct dce_dmcu_registers *regs, + const struct dce_dmcu_shift *dmcu_shift, + const struct dce_dmcu_mask *dmcu_mask); +#endif + void dce_dmcu_destroy(struct dmcu **dmcu); #endif /* _DCE_ABM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index c66585188ecd..dd13f47b6446 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -121,6 +121,12 @@ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ HWSEQ_PHYPLL_REG_LIST(CRTC) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN1_REG_LIST()\ + HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ + HWSEQ_PHYPLL_REG_LIST(OTG) +#endif + struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFEV_CLOCK_CONTROL; @@ -129,6 +135,9 @@ struct dce_hwseq_registers { uint32_t BLND_CONTROL[6]; uint32_t BLNDV_CONTROL; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /* DCE + DCN */ +#endif uint32_t CRTC_H_BLANK_START_END[6]; uint32_t PIXEL_RATE_CNTL[6]; uint32_t PHYPLL_PIXEL_RATE_CNTL[6]; @@ -192,6 +201,12 @@ struct dce_hwseq_registers { HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, OTG0_) +#endif + #define HWSEQ_REG_FIED_LIST(type) \ type DCFE_CLOCK_ENABLE; \ type DCFEV_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 4e0b5d965355..8b04996d5b89 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -78,6 +78,10 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) +#define LE_DCE80_REG_LIST(id)\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + LE_COMMON_REG_LIST_BASE(id) + #define LE_DCE100_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ @@ -97,9 +101,15 @@ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SR(DCI_MEM_PWR_STATUS) -#define LE_DCE80_REG_LIST(id)\ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_COMMON_REG_LIST_BASE(id) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define LE_DCN10_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ + SR(DMU_MEM_PWR_CNTL) +#endif + struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 9713def6e481..a065e4ae6cba 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -147,6 +147,46 @@ static void dce110_update_generic_info_packet( AFMT_GENERIC0_UPDATE, (packet_index == 0), AFMT_GENERIC2_UPDATE, (packet_index == 2)); } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (REG(AFMT_VBI_PACKET_CONTROL1)) { + switch (packet_index) { + case 0: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC0_FRAME_UPDATE, 1); + break; + case 1: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC1_FRAME_UPDATE, 1); + break; + case 2: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC2_FRAME_UPDATE, 1); + break; + case 3: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC3_FRAME_UPDATE, 1); + break; + case 4: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC4_FRAME_UPDATE, 1); + break; + case 5: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC5_FRAME_UPDATE, 1); + break; + case 6: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC6_FRAME_UPDATE, 1); + break; + case 7: + REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, + AFMT_GENERIC7_FRAME_UPDATE, 1); + break; + default: + break; + } + } +#endif } static void dce110_update_hdmi_info_packet( @@ -202,6 +242,36 @@ static void dce110_update_hdmi_info_packet( HDMI_GENERIC1_SEND, send, HDMI_GENERIC1_LINE, line); break; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case 4: + if (REG(HDMI_GENERIC_PACKET_CONTROL2)) + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 5: + if (REG(HDMI_GENERIC_PACKET_CONTROL2)) + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; + case 6: + if (REG(HDMI_GENERIC_PACKET_CONTROL3)) + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send, + HDMI_GENERIC0_LINE, line); + break; + case 7: + if (REG(HDMI_GENERIC_PACKET_CONTROL3)) + REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send, + HDMI_GENERIC1_LINE, line); + break; +#endif default: /* invalid HW packet index */ dm_logger_write( @@ -218,9 +288,24 @@ static void dce110_stream_encoder_dp_set_stream_attribute( struct dc_crtc_timing *crtc_timing, enum dc_color_space output_color_space) { +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + uint32_t h_active_start; + uint32_t v_active_start; + uint32_t misc0 = 0; + uint32_t misc1 = 0; + uint32_t h_blank; + uint32_t h_back_porch; + uint8_t synchronous_clock = 0; /* asynchronous mode */ + uint8_t colorimetry_bpc; +#endif struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (REG(DP_DB_CNTL)) + REG_UPDATE(DP_DB_CNTL, DP_DB_DISABLE, 1); +#endif + /* set pixel encoding */ switch (crtc_timing->pixel_encoding) { case PIXEL_ENCODING_YCBCR422: @@ -249,6 +334,10 @@ static void dce110_stream_encoder_dp_set_stream_attribute( if (enc110->se_mask->DP_VID_M_DOUBLE_VALUE_EN) REG_UPDATE(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, 1); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (enc110->se_mask->DP_VID_N_MUL) + REG_UPDATE(DP_VID_TIMING, DP_VID_N_MUL, 1); +#endif break; default: REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, @@ -256,6 +345,11 @@ static void dce110_stream_encoder_dp_set_stream_attribute( break; } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (REG(DP_MSA_MISC)) + misc1 = REG_READ(DP_MSA_MISC); +#endif + /* set color depth */ switch (crtc_timing->display_color_depth) { @@ -289,6 +383,128 @@ static void dce110_stream_encoder_dp_set_stream_attribute( DP_DYN_RANGE, 0, DP_YCBCR_RANGE, 0); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_666: + colorimetry_bpc = 0; + break; + case COLOR_DEPTH_888: + colorimetry_bpc = 1; + break; + case COLOR_DEPTH_101010: + colorimetry_bpc = 2; + break; + case COLOR_DEPTH_121212: + colorimetry_bpc = 3; + break; + default: + colorimetry_bpc = 0; + break; + } + + misc0 = misc0 | synchronous_clock; + misc0 = colorimetry_bpc << 5; + + if (REG(DP_MSA_TIMING_PARAM1)) { + switch (output_color_space) { + case COLOR_SPACE_SRGB: + misc0 = misc0 | 0x0;; + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_SRGB_LIMITED: + misc0 = misc0 | 0x8; /* bit3=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_YCBCR601: + misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/; + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_YCBCR709: + misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_ADOBERGB: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + /* do nothing */ + break; + } + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (REG(DP_MSA_COLORIMETRY)) + REG_SET(DP_MSA_COLORIMETRY, 0, DP_MSA_MISC0, misc0); + + if (REG(DP_MSA_MISC)) + REG_WRITE(DP_MSA_MISC, misc1); /* MSA_MISC1 */ + + /* dcn new register + * dc_crtc_timing is vesa dmt struct. data from edid + */ + if (REG(DP_MSA_TIMING_PARAM1)) + REG_SET_2(DP_MSA_TIMING_PARAM1, 0, + DP_MSA_HTOTAL, crtc_timing->h_total, + DP_MSA_VTOTAL, crtc_timing->v_total); +#endif + + /* calcuate from vesa timing parameters + * h_active_start related to leading edge of sync + */ + + h_blank = crtc_timing->h_total - crtc_timing->h_border_left - + crtc_timing->h_addressable - crtc_timing->h_border_right; + + h_back_porch = h_blank - crtc_timing->h_front_porch - + crtc_timing->h_sync_width; + + /* start at begining of left border */ + h_active_start = crtc_timing->h_sync_width + h_back_porch; + + + v_active_start = crtc_timing->v_total - crtc_timing->v_border_top - + crtc_timing->v_addressable - crtc_timing->v_border_bottom - + crtc_timing->v_front_porch; + + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /* start at begining of left border */ + if (REG(DP_MSA_TIMING_PARAM2)) + REG_SET_2(DP_MSA_TIMING_PARAM2, 0, + DP_MSA_HSTART, h_active_start, + DP_MSA_VSTART, v_active_start); + + if (REG(DP_MSA_TIMING_PARAM3)) + REG_SET_4(DP_MSA_TIMING_PARAM3, 0, + DP_MSA_HSYNCWIDTH, + crtc_timing->h_sync_width, + DP_MSA_HSYNCPOLARITY, + !crtc_timing->flags.HSYNC_POSITIVE_POLARITY, + DP_MSA_VSYNCWIDTH, + crtc_timing->v_sync_width, + DP_MSA_VSYNCPOLARITY, + !crtc_timing->flags.VSYNC_POSITIVE_POLARITY); + + /* HWDITH include border or overscan */ + if (REG(DP_MSA_TIMING_PARAM4)) + REG_SET_2(DP_MSA_TIMING_PARAM4, 0, + DP_MSA_HWIDTH, crtc_timing->h_border_left + + crtc_timing->h_addressable + crtc_timing->h_border_right, + DP_MSA_VHEIGHT, crtc_timing->v_border_top + + crtc_timing->v_addressable + crtc_timing->v_border_bottom); +#endif + } +#endif } static void dce110_stream_encoder_set_stream_attribute_helper( @@ -533,6 +749,19 @@ static void dce110_stream_encoder_update_hdmi_info_packets( dce110_update_hdmi_info_packet(enc110, 3, &info_frame->hdrsmd); } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (enc110->se_mask->HDMI_DB_DISABLE) { + /* for bring up, disable dp double TODO */ + if (REG(HDMI_DB_CONTROL)) + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + + dce110_update_hdmi_info_packet(enc110, 0, &info_frame->avi); + dce110_update_hdmi_info_packet(enc110, 1, &info_frame->vendor); + dce110_update_hdmi_info_packet(enc110, 2, &info_frame->gamut); + dce110_update_hdmi_info_packet(enc110, 3, &info_frame->spd); + dce110_update_hdmi_info_packet(enc110, 4, &info_frame->hdrsmd); + } +#endif } static void dce110_stream_encoder_stop_hdmi_info_packets( @@ -558,6 +787,26 @@ static void dce110_stream_encoder_stop_hdmi_info_packets( HDMI_GENERIC1_LINE, 0, HDMI_GENERIC1_SEND, 0); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /* stop generic packets 2 & 3 on HDMI */ + if (REG(HDMI_GENERIC_PACKET_CONTROL2)) + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); + + if (REG(HDMI_GENERIC_PACKET_CONTROL3)) + REG_SET_6(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_LINE, 0, + HDMI_GENERIC1_SEND, 0); +#endif } static void dce110_stream_encoder_update_dp_info_packets( @@ -621,6 +870,21 @@ static void dce110_stream_encoder_stop_dp_info_packets( DP_SEC_STREAM_ENABLE, 0); } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (enc110->se_mask->DP_SEC_GSP7_ENABLE) { + REG_SET_10(DP_SEC_CNTL, 0, + DP_SEC_GSP0_ENABLE, 0, + DP_SEC_GSP1_ENABLE, 0, + DP_SEC_GSP2_ENABLE, 0, + DP_SEC_GSP3_ENABLE, 0, + DP_SEC_GSP4_ENABLE, 0, + DP_SEC_GSP5_ENABLE, 0, + DP_SEC_GSP6_ENABLE, 0, + DP_SEC_GSP7_ENABLE, 0, + DP_SEC_MPG_ENABLE, 0, + DP_SEC_STREAM_ENABLE, 0); + } +#endif /* this register shared with audio info frame. * therefore we need to keep master enabled * if at least one of the fields is not 0 */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index 850e12a8db61..0b548cb3af14 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -97,6 +97,23 @@ SE_COMMON_REG_LIST_DCE_BASE(id), \ SRI(AFMT_CNTL, DIG, id) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define SE_DCN_REG_LIST(id)\ + SE_COMMON_REG_LIST_BASE(id),\ + SRI(AFMT_CNTL, DIG, id),\ + SRI(AFMT_VBI_PACKET_CONTROL1, DIG, id),\ + SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI(DP_DB_CNTL, DP, id), \ + SRI(DP_MSA_MISC, DP, id), \ + SRI(DP_MSA_COLORIMETRY, DP, id), \ + SRI(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI(HDMI_DB_CONTROL, DIG, id) +#endif + #define SE_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -311,6 +328,48 @@ SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\ + SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE_PENDING, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh) +#endif + struct dce_stream_encoder_shift { uint8_t AFMT_GENERIC_INDEX; uint8_t AFMT_GENERIC0_UPDATE; @@ -625,6 +684,16 @@ struct dce110_stream_enc_registers { uint32_t HDMI_ACR_48_0; uint32_t HDMI_ACR_48_1; uint32_t TMDS_CNTL; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + uint32_t DP_DB_CNTL; + uint32_t DP_MSA_MISC; + uint32_t DP_MSA_COLORIMETRY; + uint32_t DP_MSA_TIMING_PARAM1; + uint32_t DP_MSA_TIMING_PARAM2; + uint32_t DP_MSA_TIMING_PARAM3; + uint32_t DP_MSA_TIMING_PARAM4; + uint32_t HDMI_DB_CONTROL; +#endif }; struct dce110_stream_encoder { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index dc4c16416370..c89df8acb458 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -947,6 +947,12 @@ static void program_scaler(const struct core_dc *dc, { struct tg_color color = {0}; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /* TOFPGA */ + if (pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth == NULL) + return; +#endif + if (dc->public.debug.surface_visual_confirm) get_surface_visual_confirm_color(pipe_ctx, &color); else @@ -1113,6 +1119,9 @@ static enum dc_status apply_single_controller_ctx_to_hw( program_scaler(dc, pipe_ctx); /* mst support - use total stream count */ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (pipe_ctx->mi->funcs->allocate_mem_input != NULL) +#endif pipe_ctx->mi->funcs->allocate_mem_input( pipe_ctx->mi, stream->public.timing.h_total, @@ -1637,6 +1646,26 @@ enum dc_status dce110_apply_ctx_to_hw( /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (context->fclk_khz + > dc->current_context->fclk_khz) { + struct dm_pp_clock_for_voltage_req clock; + + clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; + clock.clocks_in_khz = context->fclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->fclk_khz = clock.clocks_in_khz; + } + if (context->dcfclk_khz + > dc->current_context->dcfclk_khz) { + struct dm_pp_clock_for_voltage_req clock; + + clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock.clocks_in_khz = context->dcfclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->dcfclk_khz = clock.clocks_in_khz; + } +#endif if (context->dispclk_khz > dc->current_context->dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index cf6ecfcadd5e..fb61e333aefd 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -75,6 +75,10 @@ BREAK_TO_DEBUGGER(); \ } while (0) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include +#endif + #define dm_alloc(size) kzalloc(size, GFP_KERNEL) #define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) #define dm_free(ptr) kfree(ptr) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 408141c6776e..b28304531d8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -69,6 +69,7 @@ enum dm_pp_clock_type { DM_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */ DM_PP_CLOCK_TYPE_MEMORY_CLK, DM_PP_CLOCK_TYPE_DCFCLK, + DM_PP_CLOCK_TYPE_DCEFCLK, DM_PP_CLOCK_TYPE_SOCCLK, DM_PP_CLOCK_TYPE_PIXELCLK, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index 5e831aff4830..70d01a9e9676 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -37,6 +37,17 @@ AMD_DAL_GPIO_DCE120 = $(addprefix $(AMDDALPATH)/dc/gpio/dce120/,$(GPIO_DCE120)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE120) +############################################################################### +# DCN 1x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +GPIO_DCN10 = hw_translate_dcn10.o hw_factory_dcn10.o + +AMD_DAL_GPIO_DCN10 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn10/,$(GPIO_DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN10) +endif + ############################################################################### # Diagnostics on FPGA ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 29ba83d2c211..8a8b619a60a8 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -43,8 +43,10 @@ #include "dce80/hw_factory_dce80.h" #include "dce110/hw_factory_dce110.h" - #include "dce120/hw_factory_dce120.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/hw_factory_dcn10.h" +#endif #include "diagnostics/hw_factory_diag.h" @@ -77,6 +79,11 @@ bool dal_hw_factory_init( case DCE_VERSION_12_0: dal_hw_factory_dce120_init(factory); return true; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + dal_hw_factory_dcn10_init(factory); + return true; +#endif default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 872edda54536..36c082bda4ae 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -43,6 +43,10 @@ #include "dce80/hw_translate_dce80.h" #include "dce110/hw_translate_dce110.h" #include "dce120/hw_translate_dce120.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/hw_translate_dcn10.h" +#endif + #include "diagnostics/hw_translate_diag.h" /* @@ -71,6 +75,11 @@ bool dal_hw_translate_init( case DCE_VERSION_12_0: dal_hw_translate_dce120_init(translate); return true; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + dal_hw_translate_dcn10_init(translate); + return true; +#endif default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile index a636768d06d5..55603400acd9 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/Makefile +++ b/drivers/gpu/drm/amd/display/dc/i2caux/Makefile @@ -47,6 +47,17 @@ AMD_DAL_I2CAUX_DCE112 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce112/,$(I2CAUX_DCE AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112) +############################################################################### +# DCN 1.0 family +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +I2CAUX_DCN1 = i2caux_dcn10.o + +AMD_DAL_I2CAUX_DCN1 = $(addprefix $(AMDDALPATH)/dc/i2caux/dcn10/,$(I2CAUX_DCN1)) + +AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCN1) +endif + ############################################################################### # DCE 120 family ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 0743265e933c..983645b1be78 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -59,6 +59,10 @@ #include "dce120/i2caux_dce120.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/i2caux_dcn10.h" +#endif + #include "diagnostics/i2caux_diag.h" /* @@ -84,6 +88,10 @@ struct i2caux *dal_i2caux_create( return dal_i2caux_dce100_create(ctx); case DCE_VERSION_12_0: return dal_i2caux_dce120_create(ctx); + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) + case DCN_VERSION_1_0: + return dal_i2caux_dcn10_create(ctx); + #endif default: BREAK_TO_DEBUGGER(); return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index f9363f642f92..392cff2cd558 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -30,6 +30,11 @@ struct core_dc { /* Inputs into BW and WM calculations. */ struct bw_calcs_dceip bw_dceip; struct bw_calcs_vbios bw_vbios; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct dcn_soc_bounding_box dcn_soc; + struct dcn_ip_params dcn_ip; + struct display_mode_lib dml; +#endif /* HW functions */ struct hw_sequencer_funcs hwss; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 9e5e0ba5b10b..c1273d6142c4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -28,8 +28,11 @@ #include "dc.h" #include "dce_calcs.h" +#include "dcn_calcs.h" #include "ddc_service_types.h" #include "dc_bios_types.h" +#include "mem_input.h" +#include "mpc.h" struct core_stream; @@ -254,6 +257,7 @@ struct resource_pool { struct abm *abm; struct dmcu *dmcu; + struct mpc *mpc; const struct resource_funcs *funcs; const struct resource_caps *res_cap; @@ -287,10 +291,20 @@ struct pipe_ctx { struct pipe_ctx *top_pipe; struct pipe_ctx *bottom_pipe; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + uint8_t mpc_idx; + struct _vcs_dpi_display_dlg_regs_st dlg_regs; + struct _vcs_dpi_display_ttu_regs_st ttu_regs; + struct _vcs_dpi_display_rq_regs_st rq_regs; + struct _vcs_dpi_display_pipe_dest_params_st pipe_dlg_param; +#endif }; struct resource_context { struct pipe_ctx pipe_ctx[MAX_PIPES]; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct mpc_tree_cfg mpc_tree[MAX_PIPES]; +#endif bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; @@ -309,6 +323,18 @@ struct validate_context { /* Note: these are big structures, do *not* put on stack! */ struct dm_pp_display_configuration pp_display_cfg; int dispclk_khz; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + int dppclk_khz; + bool dppclk_div; + int dcfclk_khz; + int dcfclk_deep_sleep_khz; + int socclk_khz; + int fclk_khz; + int dram_ccm_us; + int min_active_dram_ccm_us; + struct dcn_watermark_set watermarks; + struct dcn_bw_internal_vars dcn_bw_vars; +#endif }; #endif /* _CORE_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 97f26b55535f..240ab11d1d30 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -37,6 +37,13 @@ struct clocks_value { bool dispclk_notify_pplib_done; bool pixelclk_notify_pplib_done; bool phyclk_notigy_pplib_done; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + int dcfclock_in_khz; + int dppclk_in_khz; + int mclk_in_khz; + int phyclk_in_khz; + int common_vdd_level; +#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 2d472d8ef555..0f952e5b3ae8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -122,6 +122,7 @@ struct ipp_funcs { struct input_pixel_processor *ipp, const struct pwl_params *params); + void (*ipp_destroy)(struct input_pixel_processor **ipp); }; #endif /* __DAL_IPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 179f5ad70f48..0880ce98c90c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -31,6 +31,30 @@ #include "dce/dce_mem_input.h" /* temporary */ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dml/display_mode_structs.h" + +struct cstate_pstate_watermarks_st { + uint32_t cstate_exit_ns; + uint32_t cstate_enter_plus_exit_ns; + uint32_t pstate_change_ns; +}; + +struct dcn_watermarks { + uint32_t pte_meta_urgent_ns; + uint32_t urgent_ns; + struct cstate_pstate_watermarks_st cstate_pstate; +}; + +struct dcn_watermark_set { + struct dcn_watermarks a; + struct dcn_watermarks b; + struct dcn_watermarks c; + struct dcn_watermarks d; +}; + +#endif + struct stutter_modes { bool enhanced; bool quad_dmif_buffer; @@ -52,6 +76,23 @@ struct mem_input { }; struct mem_input_funcs { +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + void (*program_watermarks)( + struct mem_input *mem_input, + struct dcn_watermark_set *watermarks, + unsigned int refclk_period_ns); + + void (*mem_input_setup)( + struct mem_input *mem_input, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); + + void (*disable_request)(struct mem_input *mem_input); + +#endif + void (*mem_input_program_display_marks)( struct mem_input *mem_input, struct bw_watermarks nbp, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h new file mode 100644 index 000000000000..2e86ebe5eeda --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -0,0 +1,110 @@ +/* Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_MPC_H__ +#define __DC_MPC_H__ + +/* define the maximum number of pipes + * MAX_NUM_PIPPES = MAX_PIPES defined in core_type.h + */ +enum { + MAX_NUM_PIPPES = 6 +}; + +enum blend_mode { + DIGI_BYPASS = 0, /* digital bypass */ + TOP_PASSTHRU, /* top layer pass through */ + TOP_BLND /* top layer blend */ +}; + +/* This structure define the mpc tree configuration + * num_pipes - number of pipes of the tree + * opp_id - instance id of OPP to drive MPC + * dpp- array of DPP index + * mpcc - array of MPCC index + * mode - the most bottom layer MPCC mode control. + * All other layers need to be program to 3 + * + * The connection will be: + * mpcc[num_pipes-1]->mpcc[num_pipes-2]->...->mpcc[1]->mpcc[0]->OPP[opp_id] + * dpp[0]->mpcc[0] + * dpp[1]->mpcc[1] + * ... + * dpp[num_pipes-1]->mpcc[num_pipes-1] + * mpcc[0] is the most top layer of MPC tree, + * mpcc[num_pipes-1] is the most bottom layer. + */ + +struct mpc_tree_cfg { + uint8_t num_pipes; + uint8_t opp_id; + /* dpp pipes for blend */ + uint8_t dpp[MAX_NUM_PIPPES]; + /* mpcc insatnces for blend */ + uint8_t mpcc[MAX_NUM_PIPPES]; + enum blend_mode mode; +}; + +struct mpcc_blnd_cfg { + /* 0- perpixel alpha, 1- perpixel alpha combined with global gain, + * 2- global alpha + */ + uint8_t alpha_mode; + uint8_t global_gain; + uint8_t global_alpha; + bool overlap_only; + bool pre_multiplied_alpha; +}; + +struct mpcc_sm_cfg { + bool enable; + /* 0-single plane, 2-row subsampling, 4-column subsampling, + * 6-checkboard subsampling + */ + uint8_t sm_mode; + bool frame_alt; /* 0- disable, 1- enable */ + bool field_alt; /* 0- disable, 1- enable */ + /* 0-no force, 2-force frame polarity from top, + * 3-force frame polarity from bottom + */ + uint8_t force_next_frame_porlarity; + /* 0-no force, 2-force field polarity from top, + * 3-force field polarity from bottom + */ + uint8_t force_next_field_polarity; +}; + +struct mpcc_vupdate_lock_cfg { + bool cfg_lock; + bool adr_lock; + bool adr_cfg_lock; + bool cur0_lock; + bool cur1_lock; +}; + +struct mpc { + struct dc_context *ctx; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 92c99c3b9002..64d43257db96 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -27,6 +27,7 @@ #define __DAL_OPP_H__ #include "hw_shared.h" +#include "dc_hw_types.h" #include "transform.h" struct fixed31_32; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 00cdaaae455c..9f130affb31c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -91,10 +91,22 @@ enum crtc_state { CRTC_STATE_VBLANK = 0, CRTC_STATE_VACTIVE }; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +struct _dlg_otg_param { + int vstartup_start; + int vupdate_offset; + int vupdate_width; + int vready_offset; + enum signal_type signal; +}; +#endif struct timing_generator { const struct timing_generator_funcs *funcs; struct dc_bios *bp; struct dc_context *ctx; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct _dlg_otg_param dlg_otg_param; +#endif int inst; }; @@ -155,6 +167,10 @@ struct timing_generator_funcs { bool (*arm_vert_intr)(struct timing_generator *tg, uint8_t width); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + void (*program_global_sync)(struct timing_generator *tg); + void (*enable_optc_clock)(struct timing_generator *tg, bool enable); +#endif }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 222f36e3074f..c7e93f7223bd 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -36,3 +36,13 @@ AMD_DAL_IRQ_DCE12 = $(addprefix $(AMDDALPATH)/dc/irq/dce120/,$(IRQ_DCE12)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE12) +############################################################################### +# DCN 1x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_DCN1_0 +IRQ_DCN1 = irq_service_dcn10.o + +AMD_DAL_IRQ_DCN1 = $(addprefix $(AMDDALPATH)/dc/irq/dcn10/,$(IRQ_DCN1)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN1) +endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index 5255c14254df..0a1fae4ef83a 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -35,6 +35,11 @@ #include "dce120/irq_service_dce120.h" + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include "dcn10/irq_service_dcn10.h" +#endif + #include "reg_helper.h" #include "irq_service.h" diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 6dab058f8f3c..3d2ed5c83734 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -109,6 +109,19 @@ #define ASIC_REV_IS_STONEY(rev) \ ((rev >= STONEY_A0) && (rev < CZ_UNKNOWN)) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +/* DCN1_0 */ +#define INTERNAL_REV_RAVEN_A0 0x00 /* First spin of Raven */ +#define RAVEN_A0 0x01 +#define RAVEN_UNKNOWN 0xFF + +#define ASIC_REV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) +#endif + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define FAMILY_RV 142 /* DCN 1*/ +#endif + /* * ASIC chip ID */ diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index 0cefde14aa02..50a2a3ebf36d 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -39,7 +39,10 @@ enum dce_version { DCE_VERSION_11_0, DCE_VERSION_11_2, DCE_VERSION_12_0, - DCE_VERSION_MAX, +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + DCN_VERSION_1_0, +#endif + DCN_VERSION_MAX }; #endif /* __DAL_TYPES_H__ */ -- GitLab From fd187853857d46dce082e8bca210795a5f2d38a5 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Mon, 6 Mar 2017 14:01:11 +0800 Subject: [PATCH 0431/2898] drm/amdgpu: enable dcn1.0 dc support on raven Signed-off-by: Hawking Zhang Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index df95dd8439b6..27d46a907bd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1993,6 +1993,10 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) #else return amdgpu_dc > 0; #endif +#endif +#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_DCN1_0) + case CHIP_RAVEN: + return amdgpu_dc != 0; #endif default: return false; -- GitLab From 8e863620aaecdb86920035c6d8863a4642147c35 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 11 May 2017 09:48:31 +0800 Subject: [PATCH 0432/2898] drm/amdgpu/display: fix semicolon.cocci warnings drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_stream_encoder.c:411:23-24: Unneeded semicolon drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_stream_encoder.c:420:39-40: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci CC: Harry Wentland Signed-off-by: Fengguang Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index a065e4ae6cba..daab81bd1773 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -408,7 +408,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( if (REG(DP_MSA_TIMING_PARAM1)) { switch (output_color_space) { case COLOR_SPACE_SRGB: - misc0 = misc0 | 0x0;; + misc0 = misc0 | 0x0; misc1 = misc1 & ~0x80; /* bit7 = 0*/ break; case COLOR_SPACE_SRGB_LIMITED: @@ -417,7 +417,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( break; case COLOR_SPACE_YCBCR601: misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ - misc1 = misc1 & ~0x80; /* bit7 = 0*/; + misc1 = misc1 & ~0x80; /* bit7 = 0*/ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) -- GitLab From 2801b0a84ef66604fed6754d8d7858b45e2a443a Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 11 May 2017 09:48:31 +0800 Subject: [PATCH 0433/2898] drm/amdgpu/display: fix semicolon.cocci warnings drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_resource.c:1085:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci CC: Harry Wentland Signed-off-by: Fengguang Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 7aa438cd2b1a..121eb3009445 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1082,7 +1082,7 @@ static bool dcc_support_swizzle( break; default: break; - }; + } if (bytes_per_element == 1 && standard_swizzle) { *segment_order_horz = segment_order__contiguous; -- GitLab From 15a27de250a5e5a2dec7c0bf004db0511353e3f3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 10 May 2017 15:56:17 -0400 Subject: [PATCH 0434/2898] drm/amd/display: Don't call PSR func if DMCU is off Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 ------- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 23 ++++++++++++------- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 11 ++++++--- drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 1 + 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 6f78403e2d64..95d042a15409 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -46,14 +46,6 @@ #include "dce/dce_11_0_enum.h" #include "dce/dce_11_0_sh_mask.h" -#ifndef mmDMCU_STATUS__UC_IN_RESET__SHIFT -#define mmDMCU_STATUS__UC_IN_RESET__SHIFT 0x0 -#endif - -#ifndef mmDMCU_STATUS__UC_IN_RESET_MASK -#define mmDMCU_STATUS__UC_IN_RESET_MASK 0x00000001L -#endif - #define LINK_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ __VA_ARGS__) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 45a3079c0973..393c43559825 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -366,6 +366,16 @@ static bool dce_abm_init_backlight(struct abm *abm) return true; } +static bool is_dmcu_initialized(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + unsigned int dmcu_uc_reset; + + REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); + + return !dmcu_uc_reset; +} + static bool dce_abm_set_backlight_level( struct abm *abm, unsigned int backlight_level, @@ -373,23 +383,19 @@ static bool dce_abm_set_backlight_level( unsigned int controller_id) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); - unsigned int dmcu_uc_reset; dm_logger_write(abm->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", backlight_level, backlight_level); - REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset); - /* If DMCU is in reset state, DMCU is uninitialized */ - if (dmcu_uc_reset) { - driver_set_backlight_level(abm_dce, backlight_level); - } else { + if (is_dmcu_initialized(abm)) dmcu_set_backlight_level(abm_dce, backlight_level, frame_ramp, controller_id); - } + else + driver_set_backlight_level(abm_dce, backlight_level); return true; } @@ -398,7 +404,8 @@ static const struct abm_funcs dce_funcs = { .abm_init = dce_abm_init, .set_abm_level = dce_abm_set_level, .init_backlight = dce_abm_init_backlight, - .set_backlight_level = dce_abm_set_backlight_level + .set_backlight_level = dce_abm_set_backlight_level, + .is_dmcu_initialized = is_dmcu_initialized }; static void dce_abm_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 6e56d8308d66..8bc0d0ff3a2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -29,11 +29,15 @@ #include "fixed32_32.h" #include "bios_parser_interface.h" #include "dc.h" +#include "core_dc.h" +#include "dce_abm.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dcn_calcs.h" #include "core_dc.h" #endif + + #define TO_DCE_CLOCKS(clocks)\ container_of(clocks, struct dce_disp_clk, base) @@ -374,6 +378,8 @@ static void dce112_set_clock( struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_set_dce_clock_parameters dce_clk_params; struct dc_bios *bp = clk->ctx->dc_bios; + struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + struct abm *abm = core_dc->res_pool->abm; /* Prepare to program display clock*/ memset(&dce_clk_params, 0, sizeof(dce_clk_params)); @@ -404,9 +410,8 @@ static void dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - dce_psr_wait_loop(clk_dce, requested_clk_khz); -#endif + if (abm->funcs->is_dmcu_initialized(abm)) + dce_psr_wait_loop(clk_dce, requested_clk_khz); } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index 7d07b7922391..ceabbd3bf5f8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -40,6 +40,7 @@ struct abm_funcs { unsigned int backlight_level, unsigned int frame_ramp, unsigned int controller_id); + bool (*is_dmcu_initialized)(struct abm *abm); }; #endif -- GitLab From 46df790c6b569faffb4cc93889745a7827283749 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 30 Apr 2017 09:20:55 -0400 Subject: [PATCH 0435/2898] drm/amd/display: i2c/aux Remove link index. Link index is an unnecessery level of inderection when calling from kernel i2c/aux transfer into DAL. Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 6 +-- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 38 +++++++++---------- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 22 +++++++---- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 +++------- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 28 +++++++------- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +- drivers/gpu/drm/amd/display/dc/dc.h | 9 +---- .../gpu/drm/amd/display/dc/inc/core_types.h | 1 - 8 files changed, 61 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index bdae70e128c4..be51ac56552c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -546,13 +546,13 @@ enum amdgpu_connector_dither { struct amdgpu_dm_dp_aux { struct drm_dp_aux aux; - uint32_t link_index; + struct ddc_service *ddc_service; }; struct amdgpu_i2c_adapter { struct i2c_adapter base; - struct amdgpu_display_manager *dm; - uint32_t link_index; + + struct ddc_service *ddc_service; }; #define TO_DM_AUX(x) container_of((x), struct amdgpu_dm_dp_aux, aux) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 187464ac27b3..77907baa522a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -33,6 +33,8 @@ #include "dc.h" #include "dm_helpers.h" +#include "dc_link_ddc.h" + /* #define TRACE_DPCD */ #ifdef TRACE_DPCD @@ -77,43 +79,41 @@ void log_dpcd(uint8_t type, static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { - struct pci_dev *pdev = to_pci_dev(aux->dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct amdgpu_device *adev = drm_dev->dev_private; - struct dc *dc = adev->dm.dc; enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? I2C_MOT_TRUE : I2C_MOT_FALSE; - bool res; + enum ddc_result res; switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_READ: - res = dc_read_aux_dpcd( - dc, - TO_DM_AUX(aux)->link_index, + res = dal_ddc_service_read_dpcd_data( + TO_DM_AUX(aux)->ddc_service, + false, + I2C_MOT_UNDEF, msg->address, msg->buffer, msg->size); break; case DP_AUX_NATIVE_WRITE: - res = dc_write_aux_dpcd( - dc, - TO_DM_AUX(aux)->link_index, + res = dal_ddc_service_write_dpcd_data( + TO_DM_AUX(aux)->ddc_service, + false, + I2C_MOT_UNDEF, msg->address, msg->buffer, msg->size); break; case DP_AUX_I2C_READ: - res = dc_read_aux_i2c( - dc, - TO_DM_AUX(aux)->link_index, + res = dal_ddc_service_read_dpcd_data( + TO_DM_AUX(aux)->ddc_service, + true, mot, msg->address, msg->buffer, msg->size); break; case DP_AUX_I2C_WRITE: - res = dc_write_aux_i2c( - dc, - TO_DM_AUX(aux)->link_index, + res = dal_ddc_service_write_dpcd_data( + TO_DM_AUX(aux)->ddc_service, + true, mot, msg->address, msg->buffer, @@ -128,7 +128,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg msg->address, msg->buffer, msg->size, - res); + r == DDC_RESULT_SUCESSFULL); #endif return msg->size; @@ -444,7 +444,7 @@ void amdgpu_dm_initialize_dp_connector( aconnector->dm_dp_aux.aux.name = "dmdc"; aconnector->dm_dp_aux.aux.dev = dm->adev->dev; aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer; - aconnector->dm_dp_aux.link_index = aconnector->connector_id; + aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc; drm_dp_aux_register(&aconnector->dm_dp_aux.aux); aconnector->mst_mgr.cbs = &dm_mst_cbs; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index bca6769e7481..6bd8048ba21e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -50,6 +50,8 @@ #include "modules/inc/mod_freesync.h" +#include "i2caux_interface.h" + struct dm_connector_state { struct drm_connector_state base; @@ -1999,6 +2001,7 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); + struct ddc_service *ddc_service = i2c->ddc_service; struct i2c_command cmd; int i; int result = -EIO; @@ -2019,11 +2022,13 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, cmd.payloads[i].data = msgs[i].buf; } - if (dc_submit_i2c(i2c->dm->dc, i2c->link_index, &cmd)) + if (dal_i2caux_submit_i2c_command( + ddc_service->ctx->i2caux, + ddc_service->ddc_pin, + &cmd)) result = num; kfree(cmd.payloads); - return result; } @@ -2037,19 +2042,22 @@ static const struct i2c_algorithm amdgpu_dm_i2c_algo = { .functionality = amdgpu_dm_i2c_func, }; -struct amdgpu_i2c_adapter *create_i2c(unsigned int link_index, struct amdgpu_display_manager *dm, int *res) +static struct amdgpu_i2c_adapter *create_i2c( + struct ddc_service *ddc_service, + int link_index, + int *res) { + struct amdgpu_device *adev = ddc_service->ctx->driver_context; struct amdgpu_i2c_adapter *i2c; i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); - i2c->dm = dm; i2c->base.owner = THIS_MODULE; i2c->base.class = I2C_CLASS_DDC; - i2c->base.dev.parent = &dm->adev->pdev->dev; + i2c->base.dev.parent = &adev->pdev->dev; i2c->base.algo = &amdgpu_dm_i2c_algo; snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); - i2c->link_index = link_index; i2c_set_adapdata(&i2c->base, i2c); + i2c->ddc_service = ddc_service; return i2c; } @@ -2071,7 +2079,7 @@ int amdgpu_dm_connector_init( DRM_DEBUG_KMS("%s()\n", __func__); - i2c = create_i2c(link->link_index, dm, &res); + i2c = create_i2c(link->ddc, link->link_index, &res); aconnector->i2c = i2c; res = i2c_add_adapter(&i2c->base); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 738acf0cc7db..d063a252ccd9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1525,13 +1525,6 @@ const struct graphics_object_id dc_get_link_id_at_index( return core_dc->links[link_index]->link_id; } -const struct ddc_service *dc_get_ddc_at_index( - struct dc *dc, uint32_t link_index) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - return core_dc->links[link_index]->ddc; -} - enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index) { @@ -1639,7 +1632,7 @@ bool dc_read_aux_dpcd( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->ddc, + link->public.ddc, false, I2C_MOT_UNDEF, address, @@ -1659,7 +1652,7 @@ bool dc_write_aux_dpcd( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->ddc, + link->public.ddc, false, I2C_MOT_UNDEF, address, @@ -1680,7 +1673,7 @@ bool dc_read_aux_i2c( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->ddc, + link->public.ddc, true, mot, address, @@ -1701,7 +1694,7 @@ bool dc_write_aux_i2c( struct core_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->ddc, + link->public.ddc, true, mot, address, @@ -1724,7 +1717,7 @@ bool dc_query_ddc_data( struct core_link *link = core_dc->links[link_index]; bool result = dal_ddc_service_query_ddc_data( - link->ddc, + link->public.ddc, address, write_buf, write_size, @@ -1742,7 +1735,7 @@ bool dc_submit_i2c( struct core_dc *core_dc = DC_TO_CORE(dc); struct core_link *link = core_dc->links[link_index]; - struct ddc_service *ddc = link->ddc; + struct ddc_service *ddc = link->public.ddc; return dal_i2caux_submit_i2c_command( ddc->ctx->i2caux, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 95d042a15409..97cfd5bd3853 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -66,8 +66,8 @@ static void destruct(struct core_link *link) { int i; - if (link->ddc) - dal_ddc_service_destroy(&link->ddc); + if (link->public.ddc) + dal_ddc_service_destroy(&link->public.ddc); if(link->link_enc) link->link_enc->funcs->destroy(&link->link_enc); @@ -320,7 +320,7 @@ static bool is_dp_sink_present(struct core_link *link) ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || (connector_id == CONNECTOR_ID_EDP)); - ddc = dal_ddc_service_get_ddc_pin(link->ddc); + ddc = dal_ddc_service_get_ddc_pin(link->public.ddc); if (!ddc) { BREAK_TO_DEBUGGER(); @@ -526,7 +526,7 @@ static void detect_dp( } } else { /* DP passive dongles */ - sink_caps->signal = dp_passive_dongle_detection(link->ddc, + sink_caps->signal = dp_passive_dongle_detection(link->public.ddc, sink_caps, audio_support); } @@ -629,11 +629,11 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) link->dpcd_sink_count = 1; dal_ddc_service_set_transaction_type( - link->ddc, + link->public.ddc, sink_caps.transaction_type); link->public.aux_mode = dal_ddc_service_is_in_aux_transaction_mode( - link->ddc); + link->public.ddc); sink_init_data.link = &link->public; sink_init_data.sink_signal = sink_caps.signal; @@ -784,7 +784,7 @@ static enum channel_id get_ddc_line(struct core_link *link) struct ddc *ddc; enum channel_id channel = CHANNEL_ID_UNKNOWN; - ddc = dal_ddc_service_get_ddc_pin(link->ddc); + ddc = dal_ddc_service_get_ddc_pin(link->public.ddc); if (ddc) { switch (dal_ddc_get_line(ddc)) { @@ -971,16 +971,16 @@ static bool construct( ddc_service_init_data.ctx = link->ctx; ddc_service_init_data.id = link->link_id; ddc_service_init_data.link = link; - link->ddc = dal_ddc_service_create(&ddc_service_init_data); + link->public.ddc = dal_ddc_service_create(&ddc_service_init_data); - if (NULL == link->ddc) { + if (link->public.ddc == NULL) { DC_ERROR("Failed to create ddc_service!\n"); goto ddc_create_fail; } link->public.ddc_hw_inst = dal_ddc_get_line( - dal_ddc_service_get_ddc_pin(link->ddc)); + dal_ddc_service_get_ddc_pin(link->public.ddc)); enc_init_data.ctx = dc_ctx; bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder); @@ -1049,7 +1049,7 @@ static bool construct( device_tag_fail: link->link_enc->funcs->destroy(&link->link_enc); link_enc_create_fail: - dal_ddc_service_destroy(&link->ddc); + dal_ddc_service_destroy(&link->public.ddc); ddc_create_fail: create_fail: @@ -1256,7 +1256,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( - stream->sink->link->ddc, + stream->sink->link->public.ddc, stream->phy_pix_clk, stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); @@ -1276,7 +1276,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) stream->phy_pix_clk); if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) - dal_ddc_service_read_scdc_data(link->ddc); + dal_ddc_service_read_scdc_data(link->public.ddc); } /****************************enable_link***********************************/ @@ -1474,7 +1474,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, &psr_configuration.raw, sizeof(psr_configuration.raw)); - psr_context.channel = link->ddc->ddc_pin->hw_info.ddc_channel; + psr_context.channel = link->public.ddc->ddc_pin->hw_info.ddc_channel; psr_context.transmitterId = link->link_enc->transmitter; psr_context.engineId = link->link_enc->preferred_engine; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index a0d192774a22..98048fe6239e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1913,7 +1913,7 @@ static void get_active_converter_info( /* decode converter info*/ if (!ds_port.fields.PORT_PRESENT) { link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; - ddc_service_set_dongle_type(link->ddc, + ddc_service_set_dongle_type(link->public.ddc, link->dpcd_caps.dongle_type); return; } @@ -1983,7 +1983,7 @@ static void get_active_converter_info( } } - ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); + ddc_service_set_dongle_type(link->public.ddc, link->dpcd_caps.dongle_type); { struct dp_device_vendor_id dp_id; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d74bbdce1090..c7e503a91f45 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -646,6 +646,8 @@ struct dc_link { void *priv; bool aux_mode; + + struct ddc_service *ddc; }; struct dpcd_caps { @@ -829,13 +831,6 @@ void dc_set_power_state( enum dc_acpi_cm_power_state power_state); void dc_resume(const struct dc *dc); -/******************************************************************************* - * DDC Interfaces - ******************************************************************************/ - -const struct ddc_service *dc_get_ddc_at_index( - struct dc *dc, uint32_t link_index); - /* * DPCD access interfaces */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index c1273d6142c4..fcda3c7db818 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -151,7 +151,6 @@ struct core_link { struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/ struct link_encoder *link_enc; - struct ddc_service *ddc; struct graphics_object_id link_id; union ddi_channel_mapping ddi_channel_mapping; struct connector_device_tag_info device_tag; -- GitLab From 56dcade33fd3c1681a43ebc250523249be3adbb0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 9 May 2017 10:41:42 -0400 Subject: [PATCH 0436/2898] drm/amd/display: Keep DVI_SINGLE_LINK signal if low clk If user is using DVI->HDMI dongle dual link signal might pose a problem. Keep single link signal type if clk is lower than max tmds clk. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ae8b221c85aa..9588217e0220 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1283,9 +1283,12 @@ static void update_stream_signal(struct core_stream *stream) stream->signal = stream->public.output_signal; } - if (stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK && - stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) - stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + if (dc_is_dvi_signal(stream->signal)) { + if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + else + stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + } } bool resource_is_stream_unchanged( -- GitLab From 64b44524d4b28349217718ff641b02ec5ecf7b26 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 2 May 2017 16:58:39 -0400 Subject: [PATCH 0437/2898] drm/amd/display: bw debug options now apply to dml as well Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index eb81edf3afa9..22d98ef69a77 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -614,23 +614,49 @@ static void calc_wm_sets_and_perf_params( context->watermarks.d = context->watermarks.a; } -static void dcn_bw_apply_registry_override(struct core_dc *dc) +static bool dcn_bw_apply_registry_override(struct core_dc *dc) { + bool updated = false; + kernel_fpu_begin(); - if (dc->public.debug.sr_exit_time_ns) + if ((int)(dc->dcn_soc.sr_exit_time * 1000) != dc->public.debug.sr_exit_time_ns + && dc->public.debug.sr_exit_time_ns) { + updated = true; dc->dcn_soc.sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; - if (dc->public.debug.sr_enter_plus_exit_time_ns) + } + + if ((int)(dc->dcn_soc.sr_enter_plus_exit_time * 1000) + != dc->public.debug.sr_enter_plus_exit_time_ns + && dc->public.debug.sr_enter_plus_exit_time_ns) { + updated = true; dc->dcn_soc.sr_enter_plus_exit_time = dc->public.debug.sr_enter_plus_exit_time_ns / 1000.0; - if (dc->public.debug.urgent_latency_ns) + } + + if ((int)(dc->dcn_soc.urgent_latency * 1000) != dc->public.debug.urgent_latency_ns + && dc->public.debug.urgent_latency_ns) { + updated = true; dc->dcn_soc.urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; - if (dc->public.debug.percent_of_ideal_drambw) + } + + if ((int)(dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency * 1000) + != dc->public.debug.percent_of_ideal_drambw + && dc->public.debug.percent_of_ideal_drambw) { + updated = true; dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency = dc->public.debug.percent_of_ideal_drambw; - if (dc->public.debug.dram_clock_change_latency_ns) + } + + if ((int)(dc->dcn_soc.dram_clock_change_latency * 1000) + != dc->public.debug.dram_clock_change_latency_ns + && dc->public.debug.dram_clock_change_latency_ns) { + updated = true; dc->dcn_soc.dram_clock_change_latency = dc->public.debug.dram_clock_change_latency_ns / 1000.0; + } kernel_fpu_end(); + + return updated; } bool dcn_validate_bandwidth( @@ -642,7 +668,8 @@ bool dcn_validate_bandwidth( int i, input_idx; int vesa_sync_start, asic_blank_end, asic_blank_start; - dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public)); + if (dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public))) + dcn_bw_sync_calcs_and_dml(DC_TO_CORE(&dc->public)); memset(v, 0, sizeof(*v)); kernel_fpu_begin(); -- GitLab From 8d1b404744d0040d2d85c1ff7737a38f29770826 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 3 May 2017 10:25:51 -0400 Subject: [PATCH 0438/2898] drm/amd/display: Only apply ctx for specific surface. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index fb4eb4364bc7..ece8c96f3636 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1689,19 +1689,21 @@ static void dcn10_apply_ctx_for_surface( { int i; - memcpy(context->res_ctx.mpc_tree, - dc->current_context->res_ctx.mpc_tree, - sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); - for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->surface) + if (!pipe_ctx->surface || pipe_ctx->surface != surface) continue; + /* looking for top pipe to program */ - if (!pipe_ctx->top_pipe) + if (!pipe_ctx->top_pipe) { + memcpy(context->res_ctx.mpc_tree, + dc->current_context->res_ctx.mpc_tree, + sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); + program_all_pipe_in_tree(dc, pipe_ctx, context); + } } for (i = 0; i < dc->res_pool->pipe_count; i++) { -- GitLab From a90fbf78a617901181c09aa670e6d9f46f9d13ce Mon Sep 17 00:00:00 2001 From: Leon Elazar Date: Fri, 24 Mar 2017 15:46:24 -0400 Subject: [PATCH 0439/2898] drm/amd/display: Allow MPO on Raven Signed-off-by: Leon Elazar Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 121eb3009445..41613ab5ca69 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1292,6 +1292,8 @@ static bool construct( dc->public.caps.i2c_speed_in_khz = 100; dc->public.caps.max_cursor_size = 256; + dc->public.caps.max_slave_planes = 1; + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) dc->public.debug = debug_defaults_drv; else -- GitLab From c282ca3390d3327e0f8004d33acb9b022245a958 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 3 May 2017 15:19:07 -0400 Subject: [PATCH 0440/2898] drm/amd/display: use signal type to decide whether to set backlight Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 97cfd5bd3853..5d374cb8128b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1389,7 +1389,7 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", level, level); - if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD) { + if (dc_is_embedded_signal(dc_link->connector_signal)) { if (stream != NULL) { core_stream = DC_STREAM_TO_CORE(stream); for (i = 0; i < MAX_PIPES; i++) { -- GitLab From cbfd33fd976eb2679c154e44fa34428a43ac8b44 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 2 May 2017 17:01:10 -0400 Subject: [PATCH 0441/2898] drm/amd/display: do not set_mpc_tree if tree is already setup Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ece8c96f3636..41a6fa507982 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -828,7 +828,7 @@ static void reset_front_end_for_pipe( /* TODO: build stream pipes group id. For now, use stream otg * id as pipe group id */ - tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + tree_cfg = &dc->current_context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; if (pipe_ctx->top_pipe == NULL) dcn10_delete_mpc_tree(mpc, tree_cfg); @@ -1523,6 +1523,8 @@ static void update_dchubp_dpp( struct tg_color black_color = {0}; struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); + struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + /* depends on DML calculation, DPP clock value may change dynamically */ enable_dppclk( dc->ctx, @@ -1566,6 +1568,7 @@ static void update_dchubp_dpp( */ pipe_ctx->mpc_idx = pipe_ctx->tg->inst; tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + /* enable when bottom pipe is present and * it does not share a surface with current pipe */ @@ -1576,21 +1579,29 @@ static void update_dchubp_dpp( pipe_ctx->scl_data.lb_params.alpha_en = 0; tree_cfg->mode = TOP_PASSTHRU; } - if (!pipe_ctx->top_pipe) { + if (!pipe_ctx->top_pipe && !cur_pipe_ctx->bottom_pipe) { /* primary pipe, set mpc tree index 0 only */ tree_cfg->num_pipes = 1; tree_cfg->opp_id = pipe_ctx->tg->inst; tree_cfg->dpp[0] = pipe_ctx->pipe_idx; tree_cfg->mpcc[0] = pipe_ctx->pipe_idx; - dcn10_set_mpc_tree(mpc, tree_cfg); - } else { - /* TODO: add position is hard code to 1 for now - * If more than 2 pipes are supported, calculate position - */ + } + + if (!cur_pipe_ctx->top_pipe && !pipe_ctx->top_pipe) { + + if (!cur_pipe_ctx->bottom_pipe) + dcn10_set_mpc_tree(mpc, tree_cfg); + + } else if (!cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe) { + dcn10_add_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx, pipe_ctx->pipe_idx, 1); + } else { + /* nothing to be done here */ + ASSERT(cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe); } + color_space = pipe_ctx->stream->public.output_color_space; color_space_to_black_color(dc, color_space, &black_color); dcn10_set_mpc_background_color(mpc, pipe_ctx->pipe_idx, &black_color); @@ -1641,13 +1652,18 @@ static void program_all_pipe_in_tree( pipe_ctx->mi, &context->watermarks, ref_clk_mhz); lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); } + pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + pipe_ctx->tg->funcs->program_global_sync( pipe_ctx->tg); + + + update_dchubp_dpp(dc, pipe_ctx, context); } -- GitLab From c0ba5ec70eff5cf0e4337b3864c94fa6b128c8d7 Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Thu, 4 May 2017 13:34:55 -0400 Subject: [PATCH 0442/2898] drm/amd/display: Continue with stream enable if DP link training fails. Not necessarily a fatal problem - some monitors will recover and show the stream anyway if link training fails. Signed-off-by: Ken Chalmers Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 21 +++++++++++++++---- .../gpu/drm/amd/display/dc/inc/core_status.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 5d374cb8128b..ffc0eeaad175 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1225,7 +1225,7 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) status = DC_OK; } else - status = DC_ERROR_UNEXPECTED; + status = DC_FAIL_DP_LINK_TRAINING; enable_stream_features(pipe_ctx); @@ -1833,9 +1833,22 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) { struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); - if (DC_OK != enable_link(pipe_ctx)) { - BREAK_TO_DEBUGGER(); - return; + enum dc_status status = enable_link(pipe_ctx); + + if (status != DC_OK) { + dm_logger_write(pipe_ctx->stream->ctx->logger, + LOG_WARNING, "enabling link %u failed: %d\n", + pipe_ctx->stream->sink->link->public.link_index, + status); + + /* Abort stream enable *unless* the failure was due to + * DP link training - some DP monitors will recover and + * show the stream anyway. + */ + if (status != DC_FAIL_DP_LINK_TRAINING) { + BREAK_TO_DEBUGGER(); + return; + } } /* turn off otg test pattern if enable */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 128617dabc4a..b5759c0e5a2f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -41,6 +41,7 @@ enum dc_status { DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ DC_FAIL_SCALING = 13, + DC_FAIL_DP_LINK_TRAINING = 14, DC_ERROR_UNEXPECTED = -1 }; -- GitLab From fe626734711b5f402fca9df5d33cb0663b6c2fe5 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 4 May 2017 14:09:09 -0400 Subject: [PATCH 0443/2898] drm/amd/display: Implement support for backlight optimization - Add functionality to get real hw backlight level as opposed to user level, meaning the level that takes into account backlight ramping over time and backlight reduction due to Varibright - Add backlight optimization which allows for a second OS state that is able to control ABM Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 13 +++++++++++-- drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 393c43559825..cefffe164fe0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -60,7 +60,7 @@ struct abm_backlight_registers { static struct abm_backlight_registers stored_backlight_registers = {0}; -static unsigned int get_current_backlight(struct dce_abm *abm_dce) +static unsigned int get_current_backlight_16_bit(struct dce_abm *abm_dce) { uint64_t current_backlight; uint32_t round_result; @@ -252,7 +252,7 @@ static void dmcu_set_backlight_level( static void dce_abm_init(struct abm *abm) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); - unsigned int backlight = get_current_backlight(abm_dce); + unsigned int backlight = get_current_backlight_16_bit(abm_dce); REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103); REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101); @@ -289,6 +289,14 @@ static void dce_abm_init(struct abm *abm) ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1); } +static unsigned int dce_abm_get_current_backlight_8_bit(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL); + + return (backlight >> 8); +} + static bool dce_abm_set_level(struct abm *abm, uint32_t level) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); @@ -405,6 +413,7 @@ static const struct abm_funcs dce_funcs = { .set_abm_level = dce_abm_set_level, .init_backlight = dce_abm_init_backlight, .set_backlight_level = dce_abm_set_backlight_level, + .get_current_backlight_8_bit = dce_abm_get_current_backlight_8_bit, .is_dmcu_initialized = is_dmcu_initialized }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index ceabbd3bf5f8..da465b3e98e8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -40,6 +40,7 @@ struct abm_funcs { unsigned int backlight_level, unsigned int frame_ramp, unsigned int controller_id); + unsigned int (*get_current_backlight_8_bit)(struct abm *abm); bool (*is_dmcu_initialized)(struct abm *abm); }; -- GitLab From f3e4341871bee5c91ffbf9d90c4f5af380759e33 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 3 May 2017 14:21:37 -0400 Subject: [PATCH 0444/2898] drm/amd/display: ifdef some code only needed for DCN Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 2 ++ 3 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index fcda3c7db818..919c6632ee3e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -31,8 +31,10 @@ #include "dcn_calcs.h" #include "ddc_service_types.h" #include "dc_bios_types.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mem_input.h" #include "mpc.h" +#endif struct core_stream; @@ -256,7 +258,9 @@ struct resource_pool { struct abm *abm; struct dmcu *dmcu; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct mpc *mpc; +#endif const struct resource_funcs *funcs; const struct resource_caps *res_cap; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 0f952e5b3ae8..1298d306db69 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -122,7 +122,9 @@ struct ipp_funcs { struct input_pixel_processor *ipp, const struct pwl_params *params); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) void (*ipp_destroy)(struct input_pixel_processor **ipp); +#endif }; #endif /* __DAL_IPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 64d43257db96..a101f4b5e0c7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -27,7 +27,9 @@ #define __DAL_OPP_H__ #include "hw_shared.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dc_hw_types.h" +#endif #include "transform.h" struct fixed31_32; -- GitLab From 3273d3bfe58094d9c7b52448399e20f496475afe Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 5 May 2017 11:30:06 -0400 Subject: [PATCH 0445/2898] drm/amd/display: Fix race. Problem : A race between two adjecent page flips makes the earlier one to release an alocated frame buffer for the subsequent one - since there are 2 frambuffer swapped back and forth between flips, the 'new' fb of the later flip is actually the 'previous' fb for the earlier flip. Fix: Don't set fb->address = 0 in cleanup hook, this is unnecessery and erases the newly cached adress that was set in prepare_fb of the second flip. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 6bd8048ba21e..9c0dc9d07626 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1622,9 +1622,7 @@ static void dm_plane_helper_cleanup_fb( amdgpu_bo_unpin(rbo); amdgpu_bo_unreserve(rbo); amdgpu_bo_unref(&rbo); - } - - afb->address = 0; + }; } int dm_create_validation_set_for_connector(struct drm_connector *connector, -- GitLab From ac5c294719909bd5d2d3f8c74f894bdda5744916 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 5 May 2017 15:07:55 -0400 Subject: [PATCH 0446/2898] drm/amd/display: prevent assert on error of 1 in calc_freesync_range Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index c5330f3cc1de..05a086c7b31a 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -422,12 +422,14 @@ static void calc_freesync_range(struct core_freesync *core_freesync, /* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */ if (state->freesync_range.vmin < vtotal) { - ASSERT(false); + /* Error of 1 is permissible */ + ASSERT((state->freesync_range.vmin + 1) >= vtotal); state->freesync_range.vmin = vtotal; } if (state->freesync_range.vmax < vtotal) { - ASSERT(false); + /* Error of 1 is permissible */ + ASSERT((state->freesync_range.vmax + 1) >= vtotal); state->freesync_range.vmax = vtotal; } -- GitLab From 9037d802a97812cb8d614b48f817a5532cf1558c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 2 May 2017 17:29:48 -0400 Subject: [PATCH 0447/2898] drm/amd/display: refactor bw related variable structure in val_ctx Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dce_calcs.c | 18 ++--- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 79 +++++++++---------- drivers/gpu/drm/amd/display/dc/core/dc.c | 20 +---- .../drm/amd/display/dc/dce/dce_mem_input.c | 6 +- .../drm/amd/display/dc/dce/dce_mem_input.h | 12 +-- .../display/dc/dce100/dce100_hw_sequencer.c | 9 +-- .../amd/display/dc/dce100/dce100_resource.c | 4 +- .../display/dc/dce110/dce110_hw_sequencer.c | 65 ++++++++------- .../amd/display/dc/dce110/dce110_mem_input.c | 12 +-- .../amd/display/dc/dce110/dce110_mem_input.h | 6 +- .../display/dc/dce110/dce110_mem_input_v.c | 30 +++---- .../display/dc/dce110/dce110_mem_input_v.h | 6 +- .../amd/display/dc/dce110/dce110_resource.c | 63 ++++++++------- .../amd/display/dc/dce112/dce112_resource.c | 63 ++++++++------- .../drm/amd/display/dc/dce80/dce80_resource.c | 4 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 38 ++++----- .../amd/display/dc/dcn10/dcn10_mem_input.c | 6 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 58 +++++++++++--- .../gpu/drm/amd/display/dc/inc/dce_calcs.h | 29 +------ .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 20 +++-- 20 files changed, 270 insertions(+), 278 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 627b7582394a..87666987429e 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2557,7 +2557,7 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, */ static bool is_display_configuration_supported( const struct bw_calcs_vbios *vbios, - const struct bw_calcs_output *calcs_output) + const struct dce_bw_output *calcs_output) { uint32_t int_max_clk; @@ -2568,7 +2568,7 @@ static bool is_display_configuration_supported( int_max_clk = bw_fixed_to_int(vbios->high_sclk); int_max_clk *= 1000; /* MHz to kHz */ - if (calcs_output->required_sclk > int_max_clk) + if (calcs_output->sclk_khz > int_max_clk) return false; return true; @@ -2790,7 +2790,7 @@ bool bw_calcs(struct dc_context *ctx, const struct bw_calcs_vbios *vbios, const struct pipe_ctx pipe[], int pipe_count, - struct bw_calcs_output *calcs_output) + struct dce_bw_output *calcs_output) { struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data)); @@ -2831,20 +2831,20 @@ bool bw_calcs(struct dc_context *ctx, bw_int_to_fixed(1000))); calcs_output->blackout_recovery_time_us = bw_fixed_to_int(data->blackout_recovery_time); - calcs_output->required_sclk = + calcs_output->sclk_khz = bw_fixed_to_int(bw_mul(data->required_sclk, bw_int_to_fixed(1000))); - calcs_output->required_sclk_deep_sleep = + calcs_output->sclk_deep_sleep_khz = bw_fixed_to_int(bw_mul(data->sclk_deep_sleep, bw_int_to_fixed(1000))); if (yclk_lvl == 0) - calcs_output->required_yclk = bw_fixed_to_int( + calcs_output->yclk_khz = bw_fixed_to_int( bw_mul(low_yclk, bw_int_to_fixed(1000))); else if (yclk_lvl == 1) - calcs_output->required_yclk = bw_fixed_to_int( + calcs_output->yclk_khz = bw_fixed_to_int( bw_mul(mid_yclk, bw_int_to_fixed(1000))); else - calcs_output->required_yclk = bw_fixed_to_int( + calcs_output->yclk_khz = bw_fixed_to_int( bw_mul(high_yclk, bw_int_to_fixed(1000))); /* units: nanosecond, 16bit storage. */ @@ -3245,7 +3245,7 @@ bool bw_calcs(struct dc_context *ctx, calcs_output->cpup_state_change_enable = true; calcs_output->stutter_mode_enable = true; calcs_output->dispclk_khz = 0; - calcs_output->required_sclk = 0; + calcs_output->sclk_khz = 0; } dm_free(data); diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 22d98ef69a77..1b9edfda2b98 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -470,17 +470,17 @@ static void dcn_dml_wm_override( a.cpstate = dml_wm_cstate_pstate_e2e(dml, input, active_count); a.pte_meta_urgent = dml_wm_pte_meta_urgent(dml, a.urgent); - context->watermarks.a.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = a.cpstate.cstate_exit_us * 1000; - context->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = a.cpstate.cstate_enter_plus_exit_us * 1000; - context->watermarks.a.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = a.cpstate.pstate_change_us * 1000; - context->watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; - context->watermarks.a.urgent_ns = a.urgent * 1000; - context->watermarks.b = context->watermarks.a; - context->watermarks.c = context->watermarks.a; - context->watermarks.d = context->watermarks.a; + context->bw.dcn.watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; + context->bw.dcn.watermarks.a.urgent_ns = a.urgent * 1000; + context->bw.dcn.watermarks.b = context->bw.dcn.watermarks.a; + context->bw.dcn.watermarks.c = context->bw.dcn.watermarks.a; + context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { @@ -543,28 +543,28 @@ static void calc_wm_sets_and_perf_params( v->fabric_and_dram_bandwidth = v->fabric_and_dram_bandwidth_vnom0p8; dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); - context->watermarks.b.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = v->stutter_exit_watermark * 1000; - context->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = v->stutter_enter_plus_exit_watermark * 1000; - context->watermarks.b.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = v->dram_clock_change_watermark * 1000; - context->watermarks.b.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; - context->watermarks.b.urgent_ns = v->urgent_watermark * 1000; + context->bw.dcn.watermarks.b.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->bw.dcn.watermarks.b.urgent_ns = v->urgent_watermark * 1000; v->dcfclk_per_state[1] = v->dcfclkv_nom0p8; v->dcfclk_per_state[0] = v->dcfclkv_nom0p8; v->dcfclk = v->dcfclkv_nom0p8; dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); - context->watermarks.c.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = v->stutter_exit_watermark * 1000; - context->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = v->stutter_enter_plus_exit_watermark * 1000; - context->watermarks.c.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = v->dram_clock_change_watermark * 1000; - context->watermarks.c.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; - context->watermarks.c.urgent_ns = v->urgent_watermark * 1000; + context->bw.dcn.watermarks.c.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->bw.dcn.watermarks.c.urgent_ns = v->urgent_watermark * 1000; } if (v->voltage_level < 3) { @@ -578,14 +578,14 @@ static void calc_wm_sets_and_perf_params( v->dcfclk = v->dcfclkv_max0p9; dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); - context->watermarks.d.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = v->stutter_exit_watermark * 1000; - context->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = v->stutter_enter_plus_exit_watermark * 1000; - context->watermarks.d.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = v->dram_clock_change_watermark * 1000; - context->watermarks.d.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; - context->watermarks.d.urgent_ns = v->urgent_watermark * 1000; + context->bw.dcn.watermarks.d.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->bw.dcn.watermarks.d.urgent_ns = v->urgent_watermark * 1000; } v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vnom0p8; @@ -598,20 +598,20 @@ static void calc_wm_sets_and_perf_params( v->dcfclk = v->dcfclk_per_state[v->voltage_level]; dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v); - context->watermarks.a.cstate_pstate.cstate_exit_ns = + context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = v->stutter_exit_watermark * 1000; - context->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = + context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = v->stutter_enter_plus_exit_watermark * 1000; - context->watermarks.a.cstate_pstate.pstate_change_ns = + context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = v->dram_clock_change_watermark * 1000; - context->watermarks.a.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; - context->watermarks.a.urgent_ns = v->urgent_watermark * 1000; + context->bw.dcn.watermarks.a.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000; + context->bw.dcn.watermarks.a.urgent_ns = v->urgent_watermark * 1000; if (v->voltage_level >= 2) { - context->watermarks.b = context->watermarks.a; - context->watermarks.c = context->watermarks.a; + context->bw.dcn.watermarks.b = context->bw.dcn.watermarks.a; + context->bw.dcn.watermarks.c = context->bw.dcn.watermarks.a; } if (v->voltage_level >= 3) - context->watermarks.d = context->watermarks.a; + context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; } static bool dcn_bw_apply_registry_override(struct core_dc *dc) @@ -916,17 +916,16 @@ bool dcn_validate_bandwidth( display_pipe_configuration(v); calc_wm_sets_and_perf_params(context, v); - context->fclk_khz = (int)(bw_consumed * 1000000 / + context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / (ddr4_dram_factor_single_Channel * v->number_of_channels)); - context->dram_ccm_us = (int)(v->dram_clock_change_margin); - context->min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); - context->dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); - context->dcfclk_khz = (int)(v->dcfclk * 1000); - context->dispclk_khz = (int)(v->dispclk * 1000); + context->bw.dcn.calc_clk.dram_ccm_us = (int)(v->dram_clock_change_margin); + context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); + context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); + context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); if (dc->public.debug.max_disp_clk == true) - context->dispclk_khz = (int)(dc->dcn_soc.max_dispclk_vmax0p9 * 1000); - context->dppclk_khz = (int)(v->dppclk * 1000); - context->dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; + context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc.max_dispclk_vmax0p9 * 1000); + context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d063a252ccd9..b30d4bc7b040 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -970,13 +970,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; struct core_dc *core_dc = DC_TO_CORE(dc); - struct validate_context *context = dm_alloc(sizeof(struct validate_context)); - - if (!context) { - dm_error("%s: failed to create validate ctx\n", __func__); - return false; - } - dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); + struct validate_context *context = core_dc->current_context; post_surface_trace(dc); @@ -986,21 +980,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) core_dc->hwss.power_down_front_end( core_dc, &context->res_ctx.pipe_ctx[i]); } - if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { - BREAK_TO_DEBUGGER(); - dc_resource_validate_ctx_destruct(context); - dm_free(context); - return false; - } core_dc->hwss.set_bandwidth(core_dc, context, true); - if (core_dc->current_context) { - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); - } - core_dc->current_context = context; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 884f453d91b0..9da539db287c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -218,9 +218,9 @@ static void program_stutter_watermark(struct mem_input *mi, } void dce_mem_input_program_display_marks(struct mem_input *mi, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 6af533bdf98c..be37f52e9ba1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -25,6 +25,10 @@ #ifndef __DCE_MEM_INPUT_H__ #define __DCE_MEM_INPUT_H__ +#include "dc_hw_types.h" +struct dce_watermarks; +struct mem_input; + #define MI_DCE_BASE_REG_LIST(id)\ SRI(GRPH_ENABLE, DCP, id),\ SRI(GRPH_CONTROL, DCP, id),\ @@ -262,8 +266,6 @@ struct dce_mem_input_wa { uint8_t single_head_rdreq_dmif_limit; }; -struct mem_input; - void dce_mem_input_program_pte_vm(struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -288,9 +290,9 @@ void dce_mem_input_free_dmif(struct mem_input *mi, uint32_t total_stream_num); void dce_mem_input_program_display_marks(struct mem_input *mi, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); #endif /*__DCE_MEM_INPUT_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index 30c197f378dc..843f50a08e21 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -114,7 +114,7 @@ static void dce100_pplib_apply_display_requirements( pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); - pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz / MEMORY_TYPE_MULTIPLIER; dce110_fill_display_configs(context, pp_display_cfg); @@ -131,12 +131,11 @@ void dce100_set_bandwidth( struct validate_context *context, bool decrease_allowed) { - if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, - context->dispclk_khz * 115 / 100); - dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; - dc->current_context->dispclk_khz = context->dispclk_khz; + context->bw.dce.dispclk_khz * 115 / 100); + dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; } dce100_pplib_apply_display_requirements(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index f0700706d7c9..254f9e4d0fc8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -764,8 +764,8 @@ bool dce100_validate_bandwidth( struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ - context->dispclk_khz = 681000; - context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; + context->bw.dce.dispclk_khz = 681000; + context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c89df8acb458..41aeceba5ae5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1252,17 +1252,17 @@ void dce110_set_displaymarks( dc->bw_vbios.blackout_duration, pipe_ctx->stream); pipe_ctx->mi->funcs->mem_input_program_display_marks( pipe_ctx->mi, - context->bw_results.nbp_state_change_wm_ns[num_pipes], - context->bw_results.stutter_exit_wm_ns[num_pipes], - context->bw_results.urgent_wm_ns[num_pipes], + context->bw.dce.nbp_state_change_wm_ns[num_pipes], + context->bw.dce.stutter_exit_wm_ns[num_pipes], + context->bw.dce.urgent_wm_ns[num_pipes], total_dest_line_time_ns); if (i == underlay_idx) { num_pipes++; pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( pipe_ctx->mi, - context->bw_results.nbp_state_change_wm_ns[num_pipes], - context->bw_results.stutter_exit_wm_ns[num_pipes], - context->bw_results.urgent_wm_ns[num_pipes], + context->bw.dce.nbp_state_change_wm_ns[num_pipes], + context->bw.dce.stutter_exit_wm_ns[num_pipes], + context->bw.dce.urgent_wm_ns[num_pipes], total_dest_line_time_ns); } num_pipes++; @@ -1275,9 +1275,9 @@ static void set_safe_displaymarks( { int i; int underlay_idx = pool->underlay_pipe_index; - struct bw_watermarks max_marks = { + struct dce_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK }; - struct bw_watermarks nbp_marks = { + struct dce_watermarks nbp_marks = { SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; for (i = 0; i < MAX_PIPES; i++) { @@ -1502,7 +1502,7 @@ static void apply_min_clocks( /* get the required state based on state dependent clocks: * display clock and pixel clock */ - req_clocks.display_clk_khz = context->dispclk_khz; + req_clocks.display_clk_khz = context->bw.dce.dispclk_khz; req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( dc, context, true); @@ -1647,30 +1647,30 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (context->fclk_khz - > dc->current_context->fclk_khz) { + if (context->bw.dcn.calc_clk.fclk_khz + > dc->current_context->bw.dcn.calc_clk.fclk_khz) { struct dm_pp_clock_for_voltage_req clock; clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; - clock.clocks_in_khz = context->fclk_khz; + clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->fclk_khz = clock.clocks_in_khz; + dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; } - if (context->dcfclk_khz - > dc->current_context->dcfclk_khz) { + if (context->bw.dcn.calc_clk.dcfclk_khz + > dc->current_context->bw.dcn.calc_clk.dcfclk_khz) { struct dm_pp_clock_for_voltage_req clock; clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock.clocks_in_khz = context->dcfclk_khz; + clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->dcfclk_khz = clock.clocks_in_khz; + dc->current_context->bw.dcn.calc_clk.dcfclk_khz = clock.clocks_in_khz; } #endif - if (context->dispclk_khz - > dc->current_context->dispclk_khz) { + if (context->bw.dce.dispclk_khz + > dc->current_context->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, - context->dispclk_khz * 115 / 100); + context->bw.dce.dispclk_khz * 115 / 100); } /* program audio wall clock. use HDMI as clock source if HDMI * audio active. Otherwise, use DP as clock source @@ -2275,32 +2275,32 @@ static void pplib_apply_display_requirements( struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; pp_display_cfg->all_displays_in_sync = - context->bw_results.all_displays_in_sync; + context->bw.dce.all_displays_in_sync; pp_display_cfg->nb_pstate_switch_disable = - context->bw_results.nbp_state_change_enable == false; + context->bw.dce.nbp_state_change_enable == false; pp_display_cfg->cpu_cc6_disable = - context->bw_results.cpuc_state_change_enable == false; + context->bw.dce.cpuc_state_change_enable == false; pp_display_cfg->cpu_pstate_disable = - context->bw_results.cpup_state_change_enable == false; + context->bw.dce.cpup_state_change_enable == false; pp_display_cfg->cpu_pstate_separation_time = - context->bw_results.blackout_recovery_time_us; + context->bw.dce.blackout_recovery_time_us; - pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk + pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz / MEMORY_TYPE_MULTIPLIER; pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( dc, - context->bw_results.required_sclk); + context->bw.dce.sclk_khz); pp_display_cfg->min_engine_clock_deep_sleep_khz - = context->bw_results.required_sclk_deep_sleep; + = context->bw.dce.sclk_deep_sleep_khz; pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); /* TODO: dce11.2*/ pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - pp_display_cfg->disp_clk_khz = context->dispclk_khz; + pp_display_cfg->disp_clk_khz = context->bw.dce.dispclk_khz; dce110_fill_display_configs(context, pp_display_cfg); @@ -2329,12 +2329,11 @@ static void dce110_set_bandwidth( { dce110_set_displaymarks(dc, context); - if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, - context->dispclk_khz * 115 / 100); - dc->current_context->bw_results.dispclk_khz = context->dispclk_khz; - dc->current_context->dispclk_khz = context->dispclk_khz; + context->bw.dce.dispclk_khz * 115 / 100); + dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; } pplib_apply_display_requirements(dc, context); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c index a20feaedfca4..45e1a8d15d9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c @@ -166,7 +166,7 @@ bool dce110_mem_input_program_surface_flip_and_addr( static void program_urgency_watermark( const struct dc_context *ctx, const uint32_t offset, - struct bw_watermarks marks_low, + struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { /* register value */ @@ -224,7 +224,7 @@ static void program_urgency_watermark( static void program_stutter_watermark( const struct dc_context *ctx, const uint32_t offset, - struct bw_watermarks marks) + struct dce_watermarks marks) { /* register value */ uint32_t stutter_cntl = 0; @@ -289,7 +289,7 @@ static void program_stutter_watermark( static void program_nbp_watermark( const struct dc_context *ctx, const uint32_t offset, - struct bw_watermarks marks) + struct dce_watermarks marks) { uint32_t value; uint32_t addr; @@ -372,9 +372,9 @@ static void program_nbp_watermark( void dce110_mem_input_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h index 4aec18c94c49..5f10f266f096 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h @@ -55,9 +55,9 @@ bool dce110_mem_input_construct( */ void dce110_mem_input_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 9c32b5bbdff5..02739d3efa97 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -679,7 +679,7 @@ static void program_urgency_watermark( const struct dc_context *ctx, const uint32_t urgency_addr, const uint32_t wm_addr, - struct bw_watermarks marks_low, + struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { /* register value */ @@ -734,7 +734,7 @@ static void program_urgency_watermark( static void program_urgency_watermark_l( const struct dc_context *ctx, - struct bw_watermarks marks_low, + struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { program_urgency_watermark( @@ -747,7 +747,7 @@ static void program_urgency_watermark_l( static void program_urgency_watermark_c( const struct dc_context *ctx, - struct bw_watermarks marks_low, + struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { program_urgency_watermark( @@ -762,7 +762,7 @@ static void program_stutter_watermark( const struct dc_context *ctx, const uint32_t stutter_addr, const uint32_t wm_addr, - struct bw_watermarks marks) + struct dce_watermarks marks) { /* register value */ uint32_t stutter_cntl = 0; @@ -822,7 +822,7 @@ static void program_stutter_watermark( static void program_stutter_watermark_l( const struct dc_context *ctx, - struct bw_watermarks marks) + struct dce_watermarks marks) { program_stutter_watermark(ctx, mmDPGV0_PIPE_STUTTER_CONTROL, @@ -832,7 +832,7 @@ static void program_stutter_watermark_l( static void program_stutter_watermark_c( const struct dc_context *ctx, - struct bw_watermarks marks) + struct dce_watermarks marks) { program_stutter_watermark(ctx, mmDPGV1_PIPE_STUTTER_CONTROL, @@ -844,7 +844,7 @@ static void program_nbp_watermark( const struct dc_context *ctx, const uint32_t wm_mask_ctrl_addr, const uint32_t nbp_pstate_ctrl_addr, - struct bw_watermarks marks) + struct dce_watermarks marks) { uint32_t value; @@ -926,7 +926,7 @@ static void program_nbp_watermark( static void program_nbp_watermark_l( const struct dc_context *ctx, - struct bw_watermarks marks) + struct dce_watermarks marks) { program_nbp_watermark(ctx, mmDPGV0_WATERMARK_MASK_CONTROL, @@ -936,7 +936,7 @@ static void program_nbp_watermark_l( static void program_nbp_watermark_c( const struct dc_context *ctx, - struct bw_watermarks marks) + struct dce_watermarks marks) { program_nbp_watermark(ctx, mmDPGV1_WATERMARK_MASK_CONTROL, @@ -946,9 +946,9 @@ static void program_nbp_watermark_c( void dce110_mem_input_v_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { program_urgency_watermark_l( @@ -968,9 +968,9 @@ void dce110_mem_input_v_program_display_marks( void dce110_mem_input_program_chroma_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { program_urgency_watermark_c( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h index 44cf066279c0..b2667eefa3d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h @@ -38,9 +38,9 @@ bool dce110_mem_input_v_construct( */ void dce110_mem_input_v_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 5b2b41efa5f0..041d11968566 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -875,9 +875,8 @@ bool dce110_validate_bandwidth( &dc->bw_vbios, context->res_ctx.pipe_ctx, dc->res_pool->pipe_count, - &context->bw_results)) + &context->bw.dce)) result = true; - context->dispclk_khz = context->bw_results.dispclk_khz; if (!result) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, @@ -887,8 +886,8 @@ bool dce110_validate_bandwidth( context->streams[0]->public.timing.v_addressable, context->streams[0]->public.timing.pix_clk_khz); - if (memcmp(&dc->current_context->bw_results, - &context->bw_results, sizeof(context->bw_results))) { + if (memcmp(&dc->current_context->bw.dce, + &context->bw.dce, sizeof(context->bw.dce))) { struct log_entry log_entry; dm_logger_open( dc->ctx->logger, @@ -898,43 +897,43 @@ bool dce110_validate_bandwidth( "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d\n", __func__, - context->bw_results.nbp_state_change_wm_ns[0].b_mark, - context->bw_results.nbp_state_change_wm_ns[0].a_mark, - context->bw_results.urgent_wm_ns[0].b_mark, - context->bw_results.urgent_wm_ns[0].a_mark, - context->bw_results.stutter_exit_wm_ns[0].b_mark, - context->bw_results.stutter_exit_wm_ns[0].a_mark); + context->bw.dce.nbp_state_change_wm_ns[0].b_mark, + context->bw.dce.nbp_state_change_wm_ns[0].a_mark, + context->bw.dce.urgent_wm_ns[0].b_mark, + context->bw.dce.urgent_wm_ns[0].a_mark, + context->bw.dce.stutter_exit_wm_ns[0].b_mark, + context->bw.dce.stutter_exit_wm_ns[0].a_mark); dm_logger_append(&log_entry, "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d\n", - context->bw_results.nbp_state_change_wm_ns[1].b_mark, - context->bw_results.nbp_state_change_wm_ns[1].a_mark, - context->bw_results.urgent_wm_ns[1].b_mark, - context->bw_results.urgent_wm_ns[1].a_mark, - context->bw_results.stutter_exit_wm_ns[1].b_mark, - context->bw_results.stutter_exit_wm_ns[1].a_mark); + context->bw.dce.nbp_state_change_wm_ns[1].b_mark, + context->bw.dce.nbp_state_change_wm_ns[1].a_mark, + context->bw.dce.urgent_wm_ns[1].b_mark, + context->bw.dce.urgent_wm_ns[1].a_mark, + context->bw.dce.stutter_exit_wm_ns[1].b_mark, + context->bw.dce.stutter_exit_wm_ns[1].a_mark); dm_logger_append(&log_entry, "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", - context->bw_results.nbp_state_change_wm_ns[2].b_mark, - context->bw_results.nbp_state_change_wm_ns[2].a_mark, - context->bw_results.urgent_wm_ns[2].b_mark, - context->bw_results.urgent_wm_ns[2].a_mark, - context->bw_results.stutter_exit_wm_ns[2].b_mark, - context->bw_results.stutter_exit_wm_ns[2].a_mark, - context->bw_results.stutter_mode_enable); + context->bw.dce.nbp_state_change_wm_ns[2].b_mark, + context->bw.dce.nbp_state_change_wm_ns[2].a_mark, + context->bw.dce.urgent_wm_ns[2].b_mark, + context->bw.dce.urgent_wm_ns[2].a_mark, + context->bw.dce.stutter_exit_wm_ns[2].b_mark, + context->bw.dce.stutter_exit_wm_ns[2].a_mark, + context->bw.dce.stutter_mode_enable); dm_logger_append(&log_entry, "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", - context->bw_results.cpuc_state_change_enable, - context->bw_results.cpup_state_change_enable, - context->bw_results.nbp_state_change_enable, - context->bw_results.all_displays_in_sync, - context->bw_results.dispclk_khz, - context->bw_results.required_sclk, - context->bw_results.required_sclk_deep_sleep, - context->bw_results.required_yclk, - context->bw_results.blackout_recovery_time_us); + context->bw.dce.cpuc_state_change_enable, + context->bw.dce.cpup_state_change_enable, + context->bw.dce.nbp_state_change_enable, + context->bw.dce.all_displays_in_sync, + context->bw.dce.dispclk_khz, + context->bw.dce.sclk_khz, + context->bw.dce.sclk_deep_sleep_khz, + context->bw.dce.yclk_khz, + context->bw.dce.blackout_recovery_time_us); dm_logger_close(&log_entry); } return result; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 18c1b89a52be..0ed2616dd5cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -845,17 +845,16 @@ bool dce112_validate_bandwidth( &dc->bw_vbios, context->res_ctx.pipe_ctx, dc->res_pool->pipe_count, - &context->bw_results)) + &context->bw.dce)) result = true; - context->dispclk_khz = context->bw_results.dispclk_khz; if (!result) dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: Bandwidth validation failed!", __func__); - if (memcmp(&dc->current_context->bw_results, - &context->bw_results, sizeof(context->bw_results))) { + if (memcmp(&dc->current_context->bw.dce, + &context->bw.dce, sizeof(context->bw.dce))) { struct log_entry log_entry; dm_logger_open( dc->ctx->logger, @@ -865,43 +864,43 @@ bool dce112_validate_bandwidth( "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d\n", __func__, - context->bw_results.nbp_state_change_wm_ns[0].b_mark, - context->bw_results.nbp_state_change_wm_ns[0].a_mark, - context->bw_results.urgent_wm_ns[0].b_mark, - context->bw_results.urgent_wm_ns[0].a_mark, - context->bw_results.stutter_exit_wm_ns[0].b_mark, - context->bw_results.stutter_exit_wm_ns[0].a_mark); + context->bw.dce.nbp_state_change_wm_ns[0].b_mark, + context->bw.dce.nbp_state_change_wm_ns[0].a_mark, + context->bw.dce.urgent_wm_ns[0].b_mark, + context->bw.dce.urgent_wm_ns[0].a_mark, + context->bw.dce.stutter_exit_wm_ns[0].b_mark, + context->bw.dce.stutter_exit_wm_ns[0].a_mark); dm_logger_append(&log_entry, "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d\n", - context->bw_results.nbp_state_change_wm_ns[1].b_mark, - context->bw_results.nbp_state_change_wm_ns[1].a_mark, - context->bw_results.urgent_wm_ns[1].b_mark, - context->bw_results.urgent_wm_ns[1].a_mark, - context->bw_results.stutter_exit_wm_ns[1].b_mark, - context->bw_results.stutter_exit_wm_ns[1].a_mark); + context->bw.dce.nbp_state_change_wm_ns[1].b_mark, + context->bw.dce.nbp_state_change_wm_ns[1].a_mark, + context->bw.dce.urgent_wm_ns[1].b_mark, + context->bw.dce.urgent_wm_ns[1].a_mark, + context->bw.dce.stutter_exit_wm_ns[1].b_mark, + context->bw.dce.stutter_exit_wm_ns[1].a_mark); dm_logger_append(&log_entry, "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n", - context->bw_results.nbp_state_change_wm_ns[2].b_mark, - context->bw_results.nbp_state_change_wm_ns[2].a_mark, - context->bw_results.urgent_wm_ns[2].b_mark, - context->bw_results.urgent_wm_ns[2].a_mark, - context->bw_results.stutter_exit_wm_ns[2].b_mark, - context->bw_results.stutter_exit_wm_ns[2].a_mark, - context->bw_results.stutter_mode_enable); + context->bw.dce.nbp_state_change_wm_ns[2].b_mark, + context->bw.dce.nbp_state_change_wm_ns[2].a_mark, + context->bw.dce.urgent_wm_ns[2].b_mark, + context->bw.dce.urgent_wm_ns[2].a_mark, + context->bw.dce.stutter_exit_wm_ns[2].b_mark, + context->bw.dce.stutter_exit_wm_ns[2].a_mark, + context->bw.dce.stutter_mode_enable); dm_logger_append(&log_entry, "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n", - context->bw_results.cpuc_state_change_enable, - context->bw_results.cpup_state_change_enable, - context->bw_results.nbp_state_change_enable, - context->bw_results.all_displays_in_sync, - context->bw_results.dispclk_khz, - context->bw_results.required_sclk, - context->bw_results.required_sclk_deep_sleep, - context->bw_results.required_yclk, - context->bw_results.blackout_recovery_time_us); + context->bw.dce.cpuc_state_change_enable, + context->bw.dce.cpup_state_change_enable, + context->bw.dce.nbp_state_change_enable, + context->bw.dce.all_displays_in_sync, + context->bw.dce.dispclk_khz, + context->bw.dce.sclk_khz, + context->bw.dce.sclk_deep_sleep_khz, + context->bw.dce.yclk_khz, + context->bw.dce.blackout_recovery_time_us); dm_logger_close(&log_entry); } return result; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 0aa128e5ed84..5735914a8737 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -781,8 +781,8 @@ bool dce80_validate_bandwidth( struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ - context->dispclk_khz = 681000; - context->bw_results.required_yclk = 250000 * MEMORY_TYPE_MULTIPLIER; + context->bw.dce.dispclk_khz = 681000; + context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 41a6fa507982..a62c4e72f21a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1428,7 +1428,7 @@ static void dcn10_power_on_fe( enable_dcfclk(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, - context->dppclk_div); + context->bw.dcn.calc_clk.dppclk_div); if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1530,7 +1530,7 @@ static void update_dchubp_dpp( dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, - context->dppclk_div); + context->bw.dcn.calc_clk.dppclk_div); select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst); @@ -1649,7 +1649,7 @@ static void program_all_pipe_in_tree( if (pipe_ctx->top_pipe == NULL) { /* watermark is for all pipes */ pipe_ctx->mi->funcs->program_watermarks( - pipe_ctx->mi, &context->watermarks, ref_clk_mhz); + pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); } @@ -1679,16 +1679,16 @@ static void dcn10_pplib_apply_display_requirements( pp_display_cfg->all_displays_in_sync = false;/*todo*/ pp_display_cfg->nb_pstate_switch_disable = false; - pp_display_cfg->min_engine_clock_khz = context->dcfclk_khz; - pp_display_cfg->min_memory_clock_khz = context->fclk_khz; - pp_display_cfg->min_engine_clock_deep_sleep_khz = context->dcfclk_deep_sleep_khz; - pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->dcfclk_deep_sleep_khz; + pp_display_cfg->min_engine_clock_khz = context->bw.dcn.calc_clk.dcfclk_khz; + pp_display_cfg->min_memory_clock_khz = context->bw.dcn.calc_clk.fclk_khz; + pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; + pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; pp_display_cfg->avail_mclk_switch_time_us = - context->dram_ccm_us > 0 ? context->dram_ccm_us : 0; + context->bw.dcn.calc_clk.dram_ccm_us > 0 ? context->bw.dcn.calc_clk.dram_ccm_us : 0; pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = - context->min_active_dram_ccm_us > 0 ? context->min_active_dram_ccm_us : 0; - pp_display_cfg->min_dcfclock_khz = context->dcfclk_khz; - pp_display_cfg->disp_clk_khz = context->dispclk_khz; + context->bw.dcn.calc_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.calc_clk.min_active_dram_ccm_us : 0; + pp_display_cfg->min_dcfclock_khz = context->bw.dcn.calc_clk.dcfclk_khz; + pp_display_cfg->disp_clk_khz = context->bw.dcn.calc_clk.dispclk_khz; dce110_fill_display_configs(context, pp_display_cfg); if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( @@ -1755,22 +1755,22 @@ static void dcn10_set_bandwidth( if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) return; - if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz > dc->current_context->bw.dcn.calc_clk.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, - context->dispclk_khz); - dc->current_context->dispclk_khz = context->dispclk_khz; + context->bw.dcn.calc_clk.dispclk_khz); + dc->current_context->bw.dcn.calc_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; } - if (decrease_allowed || context->dcfclk_khz > dc->current_context->dcfclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz > dc->current_context->bw.dcn.calc_clk.dcfclk_khz) { clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock.clocks_in_khz = context->dcfclk_khz; + clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); } - if (decrease_allowed || context->fclk_khz > dc->current_context->fclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.calc_clk.fclk_khz) { clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; - clock.clocks_in_khz = context->fclk_khz; + clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->fclk_khz = clock.clocks_in_khz ; + dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; } dcn10_pplib_apply_display_requirements(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index bf89608b30e4..50b24456d495 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -820,9 +820,9 @@ static void program_watermarks( static void mem_input_program_display_marks( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { /* only for dce diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 919c6632ee3e..46bd0318e6be 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -31,8 +31,8 @@ #include "dcn_calcs.h" #include "ddc_service_types.h" #include "dc_bios_types.h" -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mem_input.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" #endif @@ -312,7 +312,48 @@ struct resource_context { bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; uint8_t dp_clock_source_ref_count; - }; +}; + +struct dce_bw_output { + bool cpuc_state_change_enable; + bool cpup_state_change_enable; + bool stutter_mode_enable; + bool nbp_state_change_enable; + bool all_displays_in_sync; + struct dce_watermarks urgent_wm_ns[MAX_PIPES]; + struct dce_watermarks stutter_exit_wm_ns[MAX_PIPES]; + struct dce_watermarks nbp_state_change_wm_ns[MAX_PIPES]; + int sclk_khz; + int sclk_deep_sleep_khz; + int yclk_khz; + int dispclk_khz; + int blackout_recovery_time_us; +}; + +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 +struct dcn_bw_clocks { + int dispclk_khz; + bool dppclk_div; + int dcfclk_khz; + int dcfclk_deep_sleep_khz; + int fclk_khz; + int dram_ccm_us; + int min_active_dram_ccm_us; +}; + +struct dcn_bw_output { + struct dcn_bw_clocks cur_clk; + struct dcn_bw_clocks calc_clk; + struct dcn_watermark_set watermarks; +}; +#endif + +union bw_context { +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct dcn_bw_output dcn; +#endif + struct dce_bw_output dce; +}; struct validate_context { struct core_stream *streams[MAX_PIPES]; @@ -322,20 +363,11 @@ struct validate_context { struct resource_context res_ctx; /* The output from BW and WM calculations. */ - struct bw_calcs_output bw_results; + union bw_context bw; + /* Note: these are big structures, do *not* put on stack! */ struct dm_pp_display_configuration pp_display_cfg; - int dispclk_khz; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - int dppclk_khz; - bool dppclk_div; - int dcfclk_khz; - int dcfclk_deep_sleep_khz; - int socclk_khz; - int fclk_khz; - int dram_ccm_us; - int min_active_dram_ccm_us; - struct dcn_watermark_set watermarks; struct dcn_bw_internal_vars dcn_bw_vars; #endif }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h index 580dee95e57a..36c48f7d3f56 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h @@ -35,6 +35,7 @@ struct pipe_ctx; struct core_dc; struct validate_context; +struct dce_bw_output; enum bw_calcs_version { BW_CALCS_VERSION_INVALID, @@ -454,32 +455,6 @@ struct bw_calcs_data { struct bw_fixed dmif_required_sclk_for_urgent_latency[6]; }; -/******************************************************************************* - * Output data structures. - ******************************************************************************/ -struct bw_watermarks { - uint32_t a_mark; - uint32_t b_mark; - uint32_t c_mark; - uint32_t d_mark; -}; - -struct bw_calcs_output { - bool cpuc_state_change_enable; - bool cpup_state_change_enable; - bool stutter_mode_enable; - bool nbp_state_change_enable; - bool all_displays_in_sync; - struct bw_watermarks urgent_wm_ns[6]; - struct bw_watermarks stutter_exit_wm_ns[6]; - struct bw_watermarks nbp_state_change_wm_ns[6]; - uint32_t required_sclk; - uint32_t required_sclk_deep_sleep; - uint32_t required_yclk; - uint32_t dispclk_khz; - int blackout_recovery_time_us; -}; - /** * Initialize structures with data which will NOT change at runtime. */ @@ -500,7 +475,7 @@ bool bw_calcs( const struct bw_calcs_vbios *vbios, const struct pipe_ctx *pipe, int pipe_count, - struct bw_calcs_output *calcs_output); + struct dce_bw_output *calcs_output); #endif /* __BANDWIDTH_CALCS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 0880ce98c90c..c4aea24d4574 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -27,7 +27,6 @@ #include "dc.h" #include "include/grph_object_id.h" -#include "inc/dce_calcs.h" #include "dce/dce_mem_input.h" /* temporary */ @@ -55,6 +54,13 @@ struct dcn_watermark_set { #endif +struct dce_watermarks { + int a_mark; + int b_mark; + int c_mark; + int d_mark; +}; + struct stutter_modes { bool enhanced; bool quad_dmif_buffer; @@ -95,16 +101,16 @@ struct mem_input_funcs { void (*mem_input_program_display_marks)( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); void (*mem_input_program_chroma_display_marks)( struct mem_input *mem_input, - struct bw_watermarks nbp, - struct bw_watermarks stutter, - struct bw_watermarks urgent, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); void (*allocate_mem_input)( -- GitLab From c66a54dc4a8403ab269568b3f964b0efd4052932 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 3 May 2017 11:40:40 -0400 Subject: [PATCH 0448/2898] drm/amd/display: switch to using calc_clk and cur_clk for dcn bw setting Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 50 ++++++++++------ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 59 +++++++++++++++---- 2 files changed, 79 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 41aeceba5ae5..150c8a4e7b61 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1647,24 +1647,38 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (context->bw.dcn.calc_clk.fclk_khz - > dc->current_context->bw.dcn.calc_clk.fclk_khz) { - struct dm_pp_clock_for_voltage_req clock; - - clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; - clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; - dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; - } - if (context->bw.dcn.calc_clk.dcfclk_khz - > dc->current_context->bw.dcn.calc_clk.dcfclk_khz) { - struct dm_pp_clock_for_voltage_req clock; - - clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; - dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.calc_clk.dcfclk_khz = clock.clocks_in_khz; - } + if (resource_parse_asic_id(dc->ctx->asic_id) == DCN_VERSION_1_0) { + if (context->bw.dcn.calc_clk.fclk_khz + > dc->current_context->bw.dcn.cur_clk.fclk_khz) { + struct dm_pp_clock_for_voltage_req clock; + + clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; + clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + } + if (context->bw.dcn.calc_clk.dcfclk_khz + > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { + struct dm_pp_clock_for_voltage_req clock; + + clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; + dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + } + if (context->bw.dcn.calc_clk.dispclk_khz + > dc->current_context->bw.dcn.cur_clk.dispclk_khz) { + dc->res_pool->display_clock->funcs->set_clock( + dc->res_pool->display_clock, + context->bw.dcn.calc_clk.dispclk_khz); + dc->current_context->bw.dcn.cur_clk.dispclk_khz = + context->bw.dcn.calc_clk.dispclk_khz; + context->bw.dcn.cur_clk.dispclk_khz = + context->bw.dcn.calc_clk.dispclk_khz; + } + } else #endif if (context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a62c4e72f21a..f5638ad6e9fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1429,6 +1429,9 @@ static void dcn10_power_on_fe( pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); + dc->current_context->bw.dcn.cur_clk.dppclk_div = + context->bw.dcn.calc_clk.dppclk_div; + context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1531,6 +1534,9 @@ static void update_dchubp_dpp( pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); + dc->current_context->bw.dcn.cur_clk.dppclk_div = + context->bw.dcn.calc_clk.dppclk_div; + context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst); @@ -1679,16 +1685,16 @@ static void dcn10_pplib_apply_display_requirements( pp_display_cfg->all_displays_in_sync = false;/*todo*/ pp_display_cfg->nb_pstate_switch_disable = false; - pp_display_cfg->min_engine_clock_khz = context->bw.dcn.calc_clk.dcfclk_khz; - pp_display_cfg->min_memory_clock_khz = context->bw.dcn.calc_clk.fclk_khz; - pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; - pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; + pp_display_cfg->min_engine_clock_khz = context->bw.dcn.cur_clk.dcfclk_khz; + pp_display_cfg->min_memory_clock_khz = context->bw.dcn.cur_clk.fclk_khz; + pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz; + pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz; pp_display_cfg->avail_mclk_switch_time_us = - context->bw.dcn.calc_clk.dram_ccm_us > 0 ? context->bw.dcn.calc_clk.dram_ccm_us : 0; + context->bw.dcn.cur_clk.dram_ccm_us > 0 ? context->bw.dcn.cur_clk.dram_ccm_us : 0; pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = - context->bw.dcn.calc_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.calc_clk.min_active_dram_ccm_us : 0; - pp_display_cfg->min_dcfclock_khz = context->bw.dcn.calc_clk.dcfclk_khz; - pp_display_cfg->disp_clk_khz = context->bw.dcn.calc_clk.dispclk_khz; + context->bw.dcn.cur_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.cur_clk.min_active_dram_ccm_us : 0; + pp_display_cfg->min_dcfclock_khz = context->bw.dcn.cur_clk.dcfclk_khz; + pp_display_cfg->disp_clk_khz = context->bw.dcn.cur_clk.dispclk_khz; dce110_fill_display_configs(context, pp_display_cfg); if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof( @@ -1755,22 +1761,51 @@ static void dcn10_set_bandwidth( if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) return; - if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz > dc->current_context->bw.dcn.calc_clk.dispclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz + > dc->current_context->bw.dcn.cur_clk.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dcn.calc_clk.dispclk_khz); - dc->current_context->bw.dcn.calc_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; + dc->current_context->bw.dcn.cur_clk.dispclk_khz = + context->bw.dcn.calc_clk.dispclk_khz; } - if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz > dc->current_context->bw.dcn.calc_clk.dcfclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz + > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); + dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; } - if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.calc_clk.fclk_khz) { + if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz + > dc->current_context->bw.dcn.cur_clk.fclk_khz) { clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; + context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + } + if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz + > dc->current_context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) { + dc->current_context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; + context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz = + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; + } + /* Decrease in freq is increase in period so opposite comparison for dram_ccm */ + if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us + < dc->current_context->bw.dcn.cur_clk.dram_ccm_us) { + dc->current_context->bw.dcn.calc_clk.dram_ccm_us = + context->bw.dcn.calc_clk.dram_ccm_us; + context->bw.dcn.cur_clk.dram_ccm_us = + context->bw.dcn.calc_clk.dram_ccm_us; + } + if (decrease_allowed || context->bw.dcn.calc_clk.min_active_dram_ccm_us + < dc->current_context->bw.dcn.cur_clk.min_active_dram_ccm_us) { + dc->current_context->bw.dcn.calc_clk.min_active_dram_ccm_us = + context->bw.dcn.calc_clk.min_active_dram_ccm_us; + context->bw.dcn.cur_clk.min_active_dram_ccm_us = + context->bw.dcn.calc_clk.min_active_dram_ccm_us; } dcn10_pplib_apply_display_requirements(dc, context); } -- GitLab From d4b4597384eac0e2d293912cf4cebded27246301 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 5 May 2017 16:33:11 -0400 Subject: [PATCH 0449/2898] drm/amd/display: Add 64KB_S_T and 64KB_D_T swizzle mode. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1b9edfda2b98..26587bcdba96 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -236,6 +236,7 @@ static void pipe_ctx_to_e2e_pipe_params ( break; case DC_SW_64KB_S: case DC_SW_64KB_S_X: + case DC_SW_64KB_S_T: input->src.is_display_sw = 0; input->src.macro_tile_size = dm_64k_tile; break; @@ -253,6 +254,7 @@ static void pipe_ctx_to_e2e_pipe_params ( break; case DC_SW_64KB_D: case DC_SW_64KB_D_X: + case DC_SW_64KB_D_T: input->src.is_display_sw = 1; input->src.macro_tile_size = dm_64k_tile; break; -- GitLab From e61a04f1af6187caebcad69ff72b571179b3dde9 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 27 Apr 2017 17:13:34 -0400 Subject: [PATCH 0450/2898] drm/amd/display: Use MED update type if clip position changes Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b30d4bc7b040..3c2554381a25 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1143,7 +1143,7 @@ static enum surface_update_type get_scaling_info_update_type( return UPDATE_TYPE_FULL; /* Check Clip rectangles if not equal - * difference is in offsets == > UPDATE_TYPE_FAST + * difference is in offsets == > UPDATE_TYPE_MED * difference is in dimensions == > UPDATE_TYPE_FULL */ if (memcmp(&u->scaling_info->clip_rect, @@ -1152,7 +1152,7 @@ static enum surface_update_type get_scaling_info_update_type( u->surface->clip_rect.height) && (u->scaling_info->clip_rect.width == u->surface->clip_rect.width)) { - return UPDATE_TYPE_FAST; + return UPDATE_TYPE_MED; } else { return UPDATE_TYPE_FULL; } @@ -1326,8 +1326,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, srf_updates[i].plane_info->dcc; } - /* not sure if we still need this */ - if (update_type == UPDATE_TYPE_FULL) { + if (update_type >= UPDATE_TYPE_MED) { for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; -- GitLab From ca3cba9c605348988223f69a83d1c1e7dde7583a Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 8 May 2017 17:46:57 -0400 Subject: [PATCH 0451/2898] drm/amd/display: single channel bandwidth verses dual channel bandwidth DPM0, FCLK=MCLK, single channel bandwidth = dual channel bandwidth for the rest of the DPM levels, single channel bandwidth = 1/2 dual channel bandwidth Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 26587bcdba96..6d8bc6c74a73 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -920,6 +920,10 @@ bool dcn_validate_bandwidth( calc_wm_sets_and_perf_params(context, v); context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / (ddr4_dram_factor_single_Channel * v->number_of_channels)); + if (bw_consumed == v->fabric_and_dram_bandwidth_vmin0p65) { + context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / 32); + } + context->bw.dcn.calc_clk.dram_ccm_us = (int)(v->dram_clock_change_margin); context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); @@ -1178,8 +1182,7 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && clks.num_levels != 0) { ASSERT(clks.num_levels >= 3); - dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc.number_of_channels * - (clks.data[0].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; + dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 32 * (clks.data[0].clocks_in_khz / 1000.0) / 1000.0; if (clks.num_levels > 2) { dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * (clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; @@ -1240,7 +1243,7 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) kernel_fpu_begin(); max_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; nom_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; - min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / factor; + min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; max_dcfclk_khz = dc->dcn_soc.dcfclkv_max0p9 * 1000; nom_dcfclk_khz = dc->dcn_soc.dcfclkv_nom0p8 * 1000; min_dcfclk_khz = dc->dcn_soc.dcfclkv_min0p65 * 1000; -- GitLab From d5c40d5368876d701811faa65c341198cb958cb0 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 8 May 2017 11:26:43 -0400 Subject: [PATCH 0452/2898] drm/amd/display: enable watermark range reporting to pplib Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 41613ab5ca69..4e5b225a2a08 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -432,7 +432,7 @@ static const struct dc_debug debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, + .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, .use_max_voltage = true -- GitLab From 6838161c723d061c85e20057dbf0a2a9378c4e59 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Tue, 9 May 2017 12:00:24 -0400 Subject: [PATCH 0453/2898] drm/amd/display: fix freesync not working on raven Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/freesync/freesync.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 05a086c7b31a..9a073bc55144 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -1130,6 +1130,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, unsigned int stream_index, map_index; struct freesync_state *state; struct core_freesync *core_freesync = NULL; + struct dc_static_screen_events triggers = {0}; if (mod_freesync == NULL) return; @@ -1157,6 +1158,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, /* Update the stream */ update_stream(core_freesync, streams[stream_index]); + /* Calculate vmin/vmax and refresh rate for * current mode */ @@ -1164,6 +1166,14 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, core_freesync->map[map_index].caps-> min_refresh_in_micro_hz, state->nominal_refresh_rate_in_micro_hz); + + /* Update mask */ + triggers.overlay_update = true; + triggers.surface_update = true; + + core_freesync->dc->stream_funcs.set_static_screen_events( + core_freesync->dc, streams, num_streams, + &triggers); } } -- GitLab From f46661dd42f3648b92eca73ba2c48f5d9a418b1b Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Tue, 9 May 2017 14:45:54 -0400 Subject: [PATCH 0454/2898] drm/amd/display: Move output transfer function to stream updates Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 46 ++++++++++++------- drivers/gpu/drm/amd/display/dc/dc.h | 14 ++---- .../display/dc/dce110/dce110_hw_sequencer.c | 1 - .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 - 5 files changed, 37 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 3c2554381a25..1e6952bde25b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -201,11 +201,10 @@ static bool stream_get_crtc_position(struct dc *dc, return ret; } -static bool set_gamut_remap(struct dc *dc, - const struct dc_stream **stream, int num_streams) +static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i = 0; bool ret = false; struct pipe_ctx *pipes; @@ -1182,7 +1181,6 @@ static enum surface_update_type det_surface_update( overall_type = type; if (u->in_transfer_func || - u->out_transfer_func || u->hdr_static_metadata) { if (overall_type < UPDATE_TYPE_MED) overall_type = UPDATE_TYPE_MED; @@ -1279,8 +1277,28 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* update current stream with the new updates */ if (stream_update) { - stream->public.src = stream_update->src; - stream->public.dst = stream_update->dst; + if ((stream_update->src.height != 0) && + (stream_update->src.width != 0)) + stream->public.src = stream_update->src; + + if ((stream_update->dst.height != 0) && + (stream_update->dst.width != 0)) + stream->public.dst = stream_update->dst; + + if (stream_update->out_transfer_func && + stream_update->out_transfer_func != + dc_stream->out_transfer_func) { + if (stream_update->out_transfer_func->type != + TF_TYPE_UNKNOWN) { + if (dc_stream->out_transfer_func != NULL) + dc_transfer_func_release + (dc_stream->out_transfer_func); + dc_transfer_func_retain(stream_update-> + out_transfer_func); + stream->public.out_transfer_func = + stream_update->out_transfer_func; + } + } } /* save update parameters into surface */ @@ -1361,13 +1379,6 @@ void dc_update_surfaces_and_stream(struct dc *dc, srf_updates[i].in_transfer_func; } - if (srf_updates[i].out_transfer_func && - srf_updates[i].out_transfer_func != dc_stream->out_transfer_func) { - if (dc_stream->out_transfer_func != NULL) - dc_transfer_func_release(dc_stream->out_transfer_func); - dc_transfer_func_retain(srf_updates[i].out_transfer_func); - stream->public.out_transfer_func = srf_updates[i].out_transfer_func; - } if (srf_updates[i].hdr_static_metadata) surface->public.hdr_static_ctx = *(srf_updates[i].hdr_static_metadata); @@ -1436,11 +1447,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, pipe_ctx, pipe_ctx->surface); if (is_new_pipe_surface || - srf_updates[i].out_transfer_func) + (stream_update != NULL && + stream_update->out_transfer_func != + NULL)) { core_dc->hwss.set_output_transfer_func( - pipe_ctx, - pipe_ctx->surface, - pipe_ctx->stream); + pipe_ctx, pipe_ctx->stream); + } if (srf_updates[i].hdr_static_metadata) { resource_build_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c7e503a91f45..7dd145b6e927 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -122,7 +122,7 @@ struct dc_stream_funcs { const struct rect *dst); bool (*set_gamut_remap)(struct dc *dc, - const struct dc_stream **stream, int num_streams); + const struct dc_stream *stream); void (*set_static_screen_events)(struct dc *dc, const struct dc_stream **stream, @@ -265,7 +265,8 @@ struct dc_hdr_static_metadata { enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, - TF_TYPE_BYPASS + TF_TYPE_BYPASS, + TF_TYPE_UNKNOWN }; struct dc_transfer_func_distributed_points { @@ -349,11 +350,8 @@ struct dc_surface_update { */ /* gamma TO BE REMOVED */ struct dc_gamma *gamma; - struct dc_hdr_static_metadata *hdr_static_metadata; struct dc_transfer_func *in_transfer_func; - struct dc_transfer_func *out_transfer_func; - - + struct dc_hdr_static_metadata *hdr_static_metadata; }; /* * This structure is filled in by dc_surface_get_status and contains @@ -473,11 +471,9 @@ struct dc_stream { }; struct dc_stream_update { - struct rect src; - struct rect dst; - + struct dc_transfer_func *out_transfer_func; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 150c8a4e7b61..8a663003017c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -631,7 +631,6 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface, /* Surface - To be removed */ const struct core_stream *stream) { struct output_pixel_processor *opp = pipe_ctx->opp; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f5638ad6e9fc..6cb3924225da 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1301,11 +1301,13 @@ static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface, const struct core_stream *stream) { struct output_pixel_processor *opp = pipe_ctx->opp; + if (opp == NULL) + return false; + opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->public.out_transfer_func && diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index afdb8605a30f..b53e1206dfb3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -80,7 +80,6 @@ struct hw_sequencer_funcs { bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface, const struct core_stream *stream); void (*power_down)(struct core_dc *dc); -- GitLab From 6a4c32dac559a90b83c5f268b02c1a94df411159 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 5 May 2017 14:57:12 -0400 Subject: [PATCH 0455/2898] drm/amd/display: DCE12 num_timing_generators should be 6 We should also use it to determine pipe count. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index b6bdd1d52922..b13abb025e1b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -426,7 +426,7 @@ static const struct bios_registers bios_regs = { }; static const struct resource_caps res_cap = { - .num_timing_generator = 3, + .num_timing_generator = 6, .num_audio = 7, .num_stream_encoder = 6, .num_pll = 6, @@ -909,7 +909,7 @@ static bool construct( pool->base.funcs = &dce120_res_pool_funcs; /* TODO: Fill more data from GreenlandAsicCapability.cpp */ - pool->base.pipe_count = 6; + pool->base.pipe_count = res_cap.num_timing_generator; pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; dc->public.caps.max_downscale_ratio = 200; -- GitLab From 86006a7f54c7fb59ccb3061d7a3dcd3c0443b4fe Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 9 May 2017 16:39:26 -0400 Subject: [PATCH 0456/2898] drm/amd/display: fix scaling calculation for proper surface input format Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 60 ++++++++++++------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 20 +++---- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9588217e0220..7ca03d1ad163 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -431,6 +431,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) const struct dc_surface *surface = &pipe_ctx->surface->public; const struct dc_stream *stream = &pipe_ctx->stream->public; struct scaler_data *data = &pipe_ctx->scl_data; + struct rect surf_src = surface->src_rect; struct rect clip = { 0 }; int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; @@ -444,6 +445,11 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) pri_split = false; sec_split = false; } + + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + rect_swap_helper(&surf_src); + /* The actual clip is an intersection between stream * source and surface clip */ @@ -463,18 +469,18 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) stream->src.y + stream->src.height - clip.y : surface->clip_rect.y + surface->clip_rect.height - clip.y ; - /* offset = src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio + /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio * num_pixels = clip.num_pix * scl_ratio */ - data->viewport.x = surface->src_rect.x + (clip.x - surface->dst_rect.x) * - surface->src_rect.width / surface->dst_rect.width; + data->viewport.x = surf_src.x + (clip.x - surface->dst_rect.x) * + surf_src.width / surface->dst_rect.width; data->viewport.width = clip.width * - surface->src_rect.width / surface->dst_rect.width; + surf_src.width / surface->dst_rect.width; - data->viewport.y = surface->src_rect.y + (clip.y - surface->dst_rect.y) * - surface->src_rect.height / surface->dst_rect.height; + data->viewport.y = surf_src.y + (clip.y - surface->dst_rect.y) * + surf_src.height / surface->dst_rect.height; data->viewport.height = clip.height * - surface->src_rect.height / surface->dst_rect.height; + surf_src.height / surface->dst_rect.height; /* Round down, compensate in init */ data->viewport_c.x = data->viewport.x / vpc_div; @@ -523,16 +529,21 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip { const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; - struct rect clip = surface->clip_rect; + struct rect surf_src = surface->src_rect; + struct rect surf_clip = surface->clip_rect; int recout_full_x, recout_full_y; + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + rect_swap_helper(&surf_src); + pipe_ctx->scl_data.recout.x = stream->public.dst.x; - if (stream->public.src.x < clip.x) - pipe_ctx->scl_data.recout.x += (clip.x + if (stream->public.src.x < surf_clip.x) + pipe_ctx->scl_data.recout.x += (surf_clip.x - stream->public.src.x) * stream->public.dst.width / stream->public.src.width; - pipe_ctx->scl_data.recout.width = clip.width * + pipe_ctx->scl_data.recout.width = surf_clip.width * stream->public.dst.width / stream->public.src.width; if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > stream->public.dst.x + stream->public.dst.width) @@ -541,12 +552,12 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip - pipe_ctx->scl_data.recout.x; pipe_ctx->scl_data.recout.y = stream->public.dst.y; - if (stream->public.src.y < clip.y) - pipe_ctx->scl_data.recout.y += (clip.y + if (stream->public.src.y < surf_clip.y) + pipe_ctx->scl_data.recout.y += (surf_clip.y - stream->public.src.y) * stream->public.dst.height / stream->public.src.height; - pipe_ctx->scl_data.recout.height = clip.height * + pipe_ctx->scl_data.recout.height = surf_clip.height * stream->public.dst.height / stream->public.src.height; if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > stream->public.dst.y + stream->public.dst.height) @@ -569,7 +580,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; } } else if (pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { if (stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.recout.height /= 2; @@ -577,17 +588,17 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->scl_data.recout.width /= 2; } - /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream src offset) - * * 1/ stream scaling ratio) - (surf src offset * 1/ full scl + /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) + * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ recout_full_x = stream->public.dst.x + (surface->dst_rect.x - stream->public.src.x) * stream->public.dst.width / stream->public.src.width - - surface->src_rect.x * surface->dst_rect.width / surface->src_rect.width + surf_src.x * surface->dst_rect.width / surf_src.width * stream->public.dst.width / stream->public.src.width; recout_full_y = stream->public.dst.y + (surface->dst_rect.y - stream->public.src.y) * stream->public.dst.height / stream->public.src.height - - surface->src_rect.y * surface->dst_rect.height / surface->src_rect.height + surf_src.y * surface->dst_rect.height / surf_src.height * stream->public.dst.height / stream->public.src.height; recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; @@ -598,16 +609,21 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = &pipe_ctx->surface->public; struct core_stream *stream = pipe_ctx->stream; + struct rect surf_src = surface->src_rect; const int in_w = stream->public.src.width; const int in_h = stream->public.src.height; const int out_w = stream->public.dst.width; const int out_h = stream->public.dst.height; + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + rect_swap_helper(&surf_src); + pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( - surface->src_rect.width, + surf_src.width, surface->dst_rect.width); pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( - surface->src_rect.height, + surf_src.height, surface->dst_rect.height); if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE) @@ -637,8 +653,10 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + rect_swap_helper(&src); rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); } diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 1a7ce061258f..58a3bcd5131f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -99,15 +99,15 @@ struct dc_plane_address { }; struct dc_size { - uint32_t width; - uint32_t height; + int width; + int height; }; struct rect { int x; int y; - uint32_t width; - uint32_t height; + int width; + int height; }; union plane_size { @@ -123,7 +123,7 @@ union plane_size { * In LINEAR_GENERAL mode, pitch * is 32 pixel aligned. */ - uint32_t surface_pitch; + int surface_pitch; } grph; struct { @@ -132,14 +132,14 @@ union plane_size { * In LINEAR_GENERAL mode, pitch is * 32 pixel aligned. */ - uint32_t luma_pitch; + int luma_pitch; struct rect chroma_size; /* Graphic surface pitch in pixels. * In LINEAR_GENERAL mode, pitch is * 32 pixel aligned. */ - uint32_t chroma_pitch; + int chroma_pitch; } video; }; @@ -148,15 +148,15 @@ struct dc_plane_dcc_param { union { struct { - uint32_t meta_pitch; + int meta_pitch; bool independent_64b_blks; } grph; struct { - uint32_t meta_pitch_l; + int meta_pitch_l; bool independent_64b_blks_l; - uint32_t meta_pitch_c; + int meta_pitch_c; bool independent_64b_blks_c; } video; }; -- GitLab From 0e12c3f6a0a4e73c6b6d11b7aebf20b7026ef18f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 10 May 2017 11:35:07 -0400 Subject: [PATCH 0457/2898] drm/amd/display: add yuv pixel formats to pixel_format_to_bpp() Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1e6952bde25b..bc9808180346 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1051,8 +1051,13 @@ static bool is_surface_in_context( static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) { switch (format) { + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + return 12; case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: return 16; case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: -- GitLab From b71a061801cb431d23854e0b6a6b7c04fa1f4c83 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 10 May 2017 18:05:02 -0400 Subject: [PATCH 0458/2898] drm/amd/display: fix scaling info based surface update type check Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 47 +++++++----------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index bc9808180346..6d56cb0c29cc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1122,45 +1122,24 @@ static enum surface_update_type get_plane_info_update_type( static enum surface_update_type get_scaling_info_update_type( const struct dc_surface_update *u) { - struct dc_scaling_info temp_scaling_info = { { 0 } }; - if (!u->scaling_info) return UPDATE_TYPE_FAST; - /* Copy all parameters that will cause a full update - * from current surface, the rest of the parameters - * from provided plane configuration. - * Perform memory compare and special validation - * for those that can cause fast/medium updates - */ - - /* Full Update Parameters */ - temp_scaling_info.dst_rect = u->surface->dst_rect; - temp_scaling_info.src_rect = u->surface->src_rect; - temp_scaling_info.scaling_quality = u->surface->scaling_quality; - - /* Special validation required */ - temp_scaling_info.clip_rect = u->scaling_info->clip_rect; - - if (memcmp(u->scaling_info, &temp_scaling_info, - sizeof(struct dc_scaling_info)) != 0) + if (u->scaling_info->src_rect.width != u->surface->src_rect.width + || u->scaling_info->src_rect.height != u->surface->src_rect.height + || u->scaling_info->clip_rect.width != u->surface->clip_rect.width + || u->scaling_info->clip_rect.height != u->surface->clip_rect.height + || u->scaling_info->dst_rect.width != u->surface->dst_rect.width + || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) return UPDATE_TYPE_FULL; - /* Check Clip rectangles if not equal - * difference is in offsets == > UPDATE_TYPE_MED - * difference is in dimensions == > UPDATE_TYPE_FULL - */ - if (memcmp(&u->scaling_info->clip_rect, - &u->surface->clip_rect, sizeof(struct rect)) != 0) { - if ((u->scaling_info->clip_rect.height == - u->surface->clip_rect.height) && - (u->scaling_info->clip_rect.width == - u->surface->clip_rect.width)) { - return UPDATE_TYPE_MED; - } else { - return UPDATE_TYPE_FULL; - } - } + if (u->scaling_info->src_rect.x != u->surface->src_rect.x + || u->scaling_info->src_rect.y != u->surface->src_rect.y + || u->scaling_info->clip_rect.x != u->surface->clip_rect.x + || u->scaling_info->clip_rect.y != u->surface->clip_rect.y + || u->scaling_info->dst_rect.x != u->surface->dst_rect.x + || u->scaling_info->dst_rect.y != u->surface->dst_rect.y) + return UPDATE_TYPE_MED; return UPDATE_TYPE_FAST; } -- GitLab From 81e2b2de3d9eb1313aae3f8ddcd1952c39fb8d97 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 10 May 2017 18:24:24 -0400 Subject: [PATCH 0459/2898] drm/amd/display: add explanation for surface_update_type Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7dd145b6e927..9a19d6f5a6a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -434,9 +434,35 @@ bool dc_post_update_surfaces_to_stream( void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, int surface_count, const struct dc_stream *stream); +/* Surface update type is used by dc_update_surfaces_and_stream + * The update type is determined at the very beginning of the function based + * on parameters passed in and decides how much programming (or updating) is + * going to be done during the call. + * + * UPDATE_TYPE_FAST is used for really fast updates that do not require much + * logical calculations or hardware register programming. This update MUST be + * ISR safe on windows. Currently fast update will only be used to flip surface + * address. + * + * UPDATE_TYPE_MED is used for slower updates which require significant hw + * re-programming however do not affect bandwidth consumption or clock + * requirements. At present, this is the level at which front end updates + * that do not require us to run bw_calcs happen. These are in/out transfer func + * updates, viewport offset changes, recout size changes and pixel depth changes. + * This update can be done at ISR, but we want to minimize how often this happens. + * + * UPDATE_TYPE_FULL is slow. Really slow. This requires us to recalculate our + * bandwidth and clocks, possibly rearrange some pipes and reprogram anything front + * end related. Any time viewport dimensions, recout dimensions, scaling ratios or + * gamma need to be adjusted or pipe needs to be turned on (or disconnected) we do + * a full update. This cannot be done at ISR level and should be a rare event. + * Unless someone is stress testing mpo enter/exit, playing with colour or adjusting + * underscan we don't expect to see this call at all. + */ + enum surface_update_type { UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ - UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */ + UPDATE_TYPE_MED, /* ISR safe, most of programming needed, no bw/clk change*/ UPDATE_TYPE_FULL, /* may need to shuffle resources */ }; -- GitLab From ce923dc323afa7274364d2af84a708442f9c9b59 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 15 May 2017 14:23:09 -0400 Subject: [PATCH 0460/2898] drm/amd/display: Remove duplicate entry from log_mask As pointed out by kbuild test robot and Julia Lawall. CC: Julia Lawall CC: Alex Deucher Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/logger.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 8f4497332bda..4be83703b809 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -81,7 +81,6 @@ static const struct dc_log_type_info log_type_info_tbl[] = { (1 << LOG_SYNC) | \ (1 << LOG_BANDWIDTH_VALIDATION) | \ (1 << LOG_MST) | \ - (1 << LOG_DETECTION_EDID_PARSER) | \ (1 << LOG_DETECTION_DP_CAPS) | \ (1 << LOG_BACKLIGHT)) | \ (1 << LOG_I2C_AUX) | \ -- GitLab From 747be97f4ea7de8078739f04e241b5819015f035 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Thu, 11 May 2017 17:13:20 -0400 Subject: [PATCH 0461/2898] drm/amd/display: Program CSC Mode For BT2020 - Add BT2020 color space in the set output csc default Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index fce08e5235e6..148e192f5f76 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -338,9 +338,11 @@ static void opp_set_output_csc_default( if (default_adjust != NULL) { switch (default_adjust->out_color_space) { case COLOR_SPACE_SRGB: + case COLOR_SPACE_2020_RGB_FULLRANGE: ocsc_mode = 0; break; case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: ocsc_mode = 1; break; case COLOR_SPACE_YCBCR601: @@ -349,6 +351,7 @@ static void opp_set_output_csc_default( break; case COLOR_SPACE_YCBCR709: case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_YCBCR: ocsc_mode = 3; break; case COLOR_SPACE_UNKNOWN: -- GitLab From 4b28b76bfe14430a91de74a5cf9215f3c108acf9 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 11 May 2017 17:15:14 -0400 Subject: [PATCH 0462/2898] drm/amd/display: fix mpo blanking out on one of planes being set not visible Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_mem_input.c | 3 +- .../drm/amd/display/dc/dce/dce_mem_input.h | 3 +- .../display/dc/dce110/dce110_hw_sequencer.c | 10 +++-- .../display/dc/dce110/dce110_mem_input_v.c | 3 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 41 ++++++++++++++++--- .../amd/display/dc/dcn10/dcn10_mem_input.c | 20 ++------- .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 8 ++-- 7 files changed, 51 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 9da539db287c..0552fc5f7ecc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -403,8 +403,7 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible) + bool horizontal_mirror) { REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index be37f52e9ba1..4977f5f6e7e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -277,8 +277,7 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible); + bool horizontal_mirror); void dce_mem_input_allocate_dmif(struct mem_input *mi, uint32_t h_total, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 8a663003017c..20ad1cb263db 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1986,8 +1986,9 @@ static void set_plane_config( &surface->public.plane_size, surface->public.rotation, NULL, - false, - pipe_ctx->surface->public.visible); + false); + if (mi->funcs->set_blank) + mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( @@ -2432,8 +2433,9 @@ static void dce110_program_front_end_for_pipe( &surface->public.plane_size, surface->public.rotation, NULL, - false, - pipe_ctx->surface->public.visible); + false); + if (mi->funcs->set_blank) + mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 02739d3efa97..78dd3ae3af5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -664,8 +664,7 @@ void dce110_mem_input_v_program_surface_config( union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizotal_mirror, - bool visible) + bool horizotal_mirror) { struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6cb3924225da..28b47bed72cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -848,7 +848,7 @@ static void reset_front_end_for_pipe( unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); - pipe_ctx->mi->funcs->disable_request(pipe_ctx->mi); + pipe_ctx->mi->funcs->set_blank(pipe_ctx->mi, true); wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); @@ -1513,6 +1513,35 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); } +static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx->surface->public.visible) + return true; + if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) + return true; + return false; +} + +static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx->surface->public.visible) + return true; + if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) + return true; + return false; +} + +static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) +{ + if (pipe_ctx->surface->public.visible) + return true; + if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) + return true; + if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) + return true; + return false; +} + static void update_dchubp_dpp( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -1633,12 +1662,9 @@ static void update_dchubp_dpp( &size, surface->public.rotation, &surface->public.dcc, - surface->public.horizontal_mirror, - surface->public.visible); - - /* Only support one plane for now. */ - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !surface->public.visible); + surface->public.horizontal_mirror); + mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); } static void program_all_pipe_in_tree( @@ -1669,10 +1695,13 @@ static void program_all_pipe_in_tree( pipe_ctx->tg->funcs->program_global_sync( pipe_ctx->tg); + pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); update_dchubp_dpp(dc, pipe_ctx, context); + + /* Only support one plane for now. */ } if (pipe_ctx->bottom_pipe != NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 50b24456d495..587ded13140b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -38,8 +38,9 @@ #define FN(reg_name, field_name) \ mi->mi_shift->field_name, mi->mi_mask->field_name -static void set_blank(struct dcn10_mem_input *mi, bool blank) +static void dcn_mi_set_blank(struct mem_input *mem_input, bool blank) { + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; REG_UPDATE_2(DCHUBP_CNTL, @@ -47,15 +48,6 @@ static void set_blank(struct dcn10_mem_input *mi, bool blank) HUBP_TTU_DISABLE, blank_en); } - -static void disable_request(struct mem_input *mem_input) -{ - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - - /* To disable the requestors, set blank_en to 1 */ - set_blank(mi, true); -} - static void vready_workaround(struct mem_input *mem_input, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { @@ -402,8 +394,7 @@ static void mem_input_program_surface_config( union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible) + bool horizontal_mirror) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -412,8 +403,6 @@ static void mem_input_program_surface_config( program_size_and_rotation( mi, rotation, format, plane_size, dcc, horizontal_mirror); program_pixel_format(mi, format); - - set_blank(mi, !visible); } static void program_requestor( @@ -573,7 +562,6 @@ static void mem_input_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - /* disable_request(mem_input); */ program_requestor(mem_input, rq_regs); program_deadline(mem_input, dlg_attr, ttu_attr); vready_workaround(mem_input, pipe_dest); @@ -1065,7 +1053,6 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_display_marks = mem_input_program_display_marks, .allocate_mem_input = NULL, .free_mem_input = NULL, - .disable_request = disable_request, .mem_input_program_surface_flip_and_addr = mem_input_program_surface_flip_and_addr, .mem_input_program_surface_config = @@ -1075,6 +1062,7 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .program_watermarks = program_watermarks, .mem_input_update_dchub = mem_input_update_dchub, .mem_input_program_pte_vm = dcn_mem_input_program_pte_vm, + .set_blank = dcn_mi_set_blank, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index c4aea24d4574..79fbc60e21c9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -94,9 +94,6 @@ struct mem_input_funcs { struct _vcs_dpi_display_ttu_regs_st *ttu_regs, struct _vcs_dpi_display_rq_regs_st *rq_regs, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); - - void (*disable_request)(struct mem_input *mem_input); - #endif void (*mem_input_program_display_marks)( @@ -142,13 +139,14 @@ struct mem_input_funcs { union plane_size *plane_size, enum dc_rotation_angle rotation, struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible); + bool horizontal_mirror); bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); void (*mem_input_update_dchub)(struct mem_input *mem_input, struct dchub_init_data *dh_data); + + void (*set_blank)(struct mem_input *mi, bool blank); }; #endif -- GitLab From e806208dc1daebf3b236d0188709d943cf0d9f16 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 12 May 2017 16:19:15 -0400 Subject: [PATCH 0463/2898] drm/amd/display: Fix slow FPS. Typo in expresion. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4ec86ed5622f..a2c00c0bf007 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -135,8 +135,8 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, &h_position, &v_position); - *position = (v_position) || (h_position << 16); - *vbl = (v_blank_start) || (v_blank_end << 16); + *position = v_position | (h_position << 16); + *vbl = v_blank_start | (v_blank_end << 16); } return 0; -- GitLab From aa7397dfd4cd2e31f007ad3adc08823afb40c25b Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 12 May 2017 15:54:29 -0400 Subject: [PATCH 0464/2898] drm/amd/display: Disable ABM when eDP is disabled - Add immediate ABM disable when eDP is disabled - Fix purple screen when ABM is mistakenly enabled on non eDP display Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 16 ++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 21 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 1 + 4 files changed, 40 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ffc0eeaad175..59977640f938 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1415,6 +1415,22 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, return true; } + +bool dc_link_set_abm_disable(const struct dc_link *dc_link) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct abm *abm = core_dc->res_pool->abm; + + if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) + return false; + + abm->funcs->set_abm_immediate_disable(abm); + + return true; +} + + bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) { struct core_link *link = DC_LINK_TO_CORE(dc_link); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9a19d6f5a6a3..0610805cdb05 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -714,6 +714,8 @@ const struct graphics_object_id dc_get_link_id_at_index( bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream); +bool dc_link_set_abm_disable(const struct dc_link *dc_link); + bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_setup_psr(const struct dc_link *dc_link, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index cefffe164fe0..b4fa78292ad2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -49,6 +49,8 @@ #define MCP_ABM_PIPE_SET 0x66 #define MCP_BL_SET 0x67 +#define MCP_DISABLE_ABM_IMMEDIATELY 255 + struct abm_backlight_registers { unsigned int BL_PWM_CNTL; unsigned int BL_PWM_CNTL2; @@ -315,6 +317,24 @@ static bool dce_abm_set_level(struct abm *abm, uint32_t level) return true; } +static bool dce_abm_immediate_disable(struct abm *abm) +{ + struct dce_abm *abm_dce = TO_DCE_ABM(abm); + + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, + 100, 800); + + /* setDMCUParam_ABMLevel */ + REG_UPDATE_2(MASTER_COMM_CMD_REG, + MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, + MASTER_COMM_CMD_REG_BYTE2, MCP_DISABLE_ABM_IMMEDIATELY); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + return true; +} + static bool dce_abm_init_backlight(struct abm *abm) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); @@ -414,6 +434,7 @@ static const struct abm_funcs dce_funcs = { .init_backlight = dce_abm_init_backlight, .set_backlight_level = dce_abm_set_backlight_level, .get_current_backlight_8_bit = dce_abm_get_current_backlight_8_bit, + .set_abm_immediate_disable = dce_abm_immediate_disable, .is_dmcu_initialized = is_dmcu_initialized }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index da465b3e98e8..c93b9b9a817c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -35,6 +35,7 @@ struct abm { struct abm_funcs { void (*abm_init)(struct abm *abm); bool (*set_abm_level)(struct abm *abm, unsigned int abm_level); + bool (*set_abm_immediate_disable)(struct abm *abm); bool (*init_backlight)(struct abm *abm); bool (*set_backlight_level)(struct abm *abm, unsigned int backlight_level, -- GitLab From c34892144d38eddb4499ac425c24455b1e34dd61 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 15 May 2017 08:31:51 -0400 Subject: [PATCH 0465/2898] drm/amd/display: dce 8 - 12 mem_input refactor to new style Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_mem_input.c | 306 ++++++++++-- .../drm/amd/display/dc/dce/dce_mem_input.h | 115 +++-- .../amd/display/dc/dce100/dce100_resource.c | 78 +--- .../gpu/drm/amd/display/dc/dce110/Makefile | 3 +- .../amd/display/dc/dce110/dce110_mem_input.c | 437 ------------------ .../amd/display/dc/dce110/dce110_mem_input.h | 121 ----- .../display/dc/dce110/dce110_mem_input_v.c | 155 +++---- .../display/dc/dce110/dce110_mem_input_v.h | 66 +-- .../amd/display/dc/dce110/dce110_resource.c | 58 +-- .../gpu/drm/amd/display/dc/dce112/Makefile | 2 +- .../amd/display/dc/dce112/dce112_mem_input.c | 54 --- .../amd/display/dc/dce112/dce112_mem_input.h | 38 -- .../amd/display/dc/dce112/dce112_resource.c | 77 +-- .../gpu/drm/amd/display/dc/dce120/Makefile | 2 +- .../amd/display/dc/dce120/dce120_mem_input.c | 340 -------------- .../amd/display/dc/dce120/dce120_mem_input.h | 37 -- .../amd/display/dc/dce120/dce120_resource.c | 75 +-- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 3 +- .../amd/display/dc/dce80/dce80_mem_input.c | 83 ---- .../amd/display/dc/dce80/dce80_mem_input.h | 36 -- .../drm/amd/display/dc/dce80/dce80_resource.c | 78 +--- .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 8 - 22 files changed, 476 insertions(+), 1696 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 0552fc5f7ecc..718688c41f7b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -23,18 +23,18 @@ * */ -#include "mem_input.h" +#include "dce_mem_input.h" #include "reg_helper.h" #include "basics/conversion.h" #define CTX \ - mi->ctx + dce_mi->base.ctx #define REG(reg)\ - mi->regs->reg + dce_mi->regs->reg #undef FN #define FN(reg_name, field_name) \ - mi->shifts->field_name, mi->masks->field_name + dce_mi->shifts->field_name, dce_mi->masks->field_name struct pte_setting { unsigned int bpp; @@ -130,11 +130,13 @@ static bool is_vert_scan(enum dc_rotation_angle rotation) } } -void dce_mem_input_program_pte_vm(struct mem_input *mi, +static void dce_mi_program_pte_vm( + struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); enum mi_bits_per_pixel mi_bpp = get_mi_bpp(format); enum mi_tiling_format mi_tiling = get_mi_tiling(tiling_info); const struct pte_setting *pte = &pte_settings[mi_tiling][mi_bpp]; @@ -158,7 +160,8 @@ void dce_mem_input_program_pte_vm(struct mem_input *mi, DVMM_MAX_PTE_REQ_OUTSTANDING, 0xff); } -static void program_urgency_watermark(struct mem_input *mi, +static void program_urgency_watermark( + struct dce_mem_input *dce_mi, uint32_t wm_select, uint32_t urgency_low_wm, uint32_t urgency_high_wm) @@ -171,7 +174,8 @@ static void program_urgency_watermark(struct mem_input *mi, URGENCY_HIGH_WATERMARK, urgency_high_wm); } -static void program_nbp_watermark(struct mem_input *mi, +static void program_nbp_watermark( + struct dce_mem_input *dce_mi, uint32_t wm_select, uint32_t nbp_wm) { @@ -202,7 +206,8 @@ static void program_nbp_watermark(struct mem_input *mi, } } -static void program_stutter_watermark(struct mem_input *mi, +static void program_stutter_watermark( + struct dce_mem_input *dce_mi, uint32_t wm_select, uint32_t stutter_mark) { @@ -217,41 +222,67 @@ static void program_stutter_watermark(struct mem_input *mi, STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); } -void dce_mem_input_program_display_marks(struct mem_input *mi, +static void dce_mi_program_display_marks( + struct mem_input *mi, struct dce_watermarks nbp, struct dce_watermarks stutter, struct dce_watermarks urgent, uint32_t total_dest_line_time_ns) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; - program_urgency_watermark(mi, 0, /* set a */ + program_urgency_watermark(dce_mi, 2, /* set a */ urgent.a_mark, total_dest_line_time_ns); - program_urgency_watermark(mi, 1, /* set b */ + program_urgency_watermark(dce_mi, 1, /* set d */ + urgent.d_mark, total_dest_line_time_ns); + + REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE, stutter_en, + STUTTER_IGNORE_FBC, 1); + program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */ + program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */ + + program_stutter_watermark(dce_mi, 2, stutter.a_mark); /* set a */ + program_stutter_watermark(dce_mi, 1, stutter.d_mark); /* set d */ +} + +static void dce120_mi_program_display_marks(struct mem_input *mi, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); + uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; + + program_urgency_watermark(dce_mi, 0, /* set a */ + urgent.a_mark, total_dest_line_time_ns); + program_urgency_watermark(dce_mi, 1, /* set b */ urgent.b_mark, total_dest_line_time_ns); - program_urgency_watermark(mi, 2, /* set c */ + program_urgency_watermark(dce_mi, 2, /* set c */ urgent.c_mark, total_dest_line_time_ns); - program_urgency_watermark(mi, 3, /* set d */ + program_urgency_watermark(dce_mi, 3, /* set d */ urgent.d_mark, total_dest_line_time_ns); REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, stutter_en, STUTTER_IGNORE_FBC, 1); - program_nbp_watermark(mi, 0, nbp.a_mark); /* set a */ - program_nbp_watermark(mi, 1, nbp.b_mark); /* set b */ - program_nbp_watermark(mi, 2, nbp.c_mark); /* set c */ - program_nbp_watermark(mi, 3, nbp.d_mark); /* set d */ - - program_stutter_watermark(mi, 0, stutter.a_mark); /* set a */ - program_stutter_watermark(mi, 1, stutter.b_mark); /* set b */ - program_stutter_watermark(mi, 2, stutter.c_mark); /* set c */ - program_stutter_watermark(mi, 3, stutter.d_mark); /* set d */ + program_nbp_watermark(dce_mi, 0, nbp.a_mark); /* set a */ + program_nbp_watermark(dce_mi, 1, nbp.b_mark); /* set b */ + program_nbp_watermark(dce_mi, 2, nbp.c_mark); /* set c */ + program_nbp_watermark(dce_mi, 3, nbp.d_mark); /* set d */ + + program_stutter_watermark(dce_mi, 0, stutter.a_mark); /* set a */ + program_stutter_watermark(dce_mi, 1, stutter.b_mark); /* set b */ + program_stutter_watermark(dce_mi, 2, stutter.c_mark); /* set c */ + program_stutter_watermark(dce_mi, 3, stutter.d_mark); /* set d */ } -static void program_tiling(struct mem_input *mi, - const union dc_tiling_info *info) +static void program_tiling( + struct dce_mem_input *dce_mi, const union dc_tiling_info *info) { - if (mi->masks->GRPH_SW_MODE) { /* GFX9 */ + if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */ REG_UPDATE_6(GRPH_CONTROL, GRPH_SW_MODE, info->gfx9.swizzle, GRPH_NUM_BANKS, log_2(info->gfx9.num_banks), @@ -265,7 +296,7 @@ static void program_tiling(struct mem_input *mi, */ } - if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ + if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ REG_UPDATE_9(GRPH_CONTROL, GRPH_NUM_BANKS, info->gfx8.num_banks, GRPH_BANK_WIDTH, info->gfx8.bank_width, @@ -285,7 +316,7 @@ static void program_tiling(struct mem_input *mi, static void program_size_and_rotation( - struct mem_input *mi, + struct dce_mem_input *dce_mi, enum dc_rotation_angle rotation, const union plane_size *plane_size) { @@ -326,7 +357,7 @@ static void program_size_and_rotation( } static void program_grph_pixel_format( - struct mem_input *mi, + struct dce_mem_input *dce_mi, enum surface_pixel_format format) { uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ @@ -397,7 +428,8 @@ static void program_grph_pixel_format( GRPH_PRESCALE_B_SIGN, sign); } -void dce_mem_input_program_surface_config(struct mem_input *mi, +static void dce_mi_program_surface_config( + struct mem_input *mi, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -405,14 +437,15 @@ void dce_mem_input_program_surface_config(struct mem_input *mi, struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); - program_tiling(mi, tiling_info); - program_size_and_rotation(mi, rotation, plane_size); + program_tiling(dce_mi, tiling_info); + program_size_and_rotation(dce_mi, rotation, plane_size); if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - program_grph_pixel_format(mi, format); + program_grph_pixel_format(dce_mi, format); } static uint32_t get_dmif_switch_time_us( @@ -461,12 +494,14 @@ static uint32_t get_dmif_switch_time_us( return frame_time; } -void dce_mem_input_allocate_dmif(struct mem_input *mi, +static void dce_mi_allocate_dmif( + struct mem_input *mi, uint32_t h_total, uint32_t v_total, uint32_t pix_clk_khz, uint32_t total_stream_num) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); const uint32_t retry_delay = 10; uint32_t retry_count = get_dmif_switch_time_us( h_total, @@ -497,18 +532,20 @@ void dce_mem_input_allocate_dmif(struct mem_input *mi, PIXEL_DURATION, pix_dur); } - if (mi->wa.single_head_rdreq_dmif_limit) { + if (dce_mi->wa.single_head_rdreq_dmif_limit) { uint32_t eanble = (total_stream_num > 1) ? 0 : - mi->wa.single_head_rdreq_dmif_limit; + dce_mi->wa.single_head_rdreq_dmif_limit; REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, ENABLE, eanble); } } -void dce_mem_input_free_dmif(struct mem_input *mi, +static void dce_mi_free_dmif( + struct mem_input *mi, uint32_t total_stream_num) { + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); uint32_t buffers_allocated; uint32_t dmif_buffer_control; @@ -525,11 +562,204 @@ void dce_mem_input_free_dmif(struct mem_input *mi, DMIF_BUFFERS_ALLOCATION_COMPLETED, 1, 10, 3500); - if (mi->wa.single_head_rdreq_dmif_limit) { + if (dce_mi->wa.single_head_rdreq_dmif_limit) { uint32_t eanble = (total_stream_num > 1) ? 0 : - mi->wa.single_head_rdreq_dmif_limit; + dce_mi->wa.single_head_rdreq_dmif_limit; REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT, ENABLE, eanble); } } + + +static void program_sec_addr( + struct dce_mem_input *dce_mi, + PHYSICAL_ADDRESS_LOC address) +{ + /*high register MUST be programmed first*/ + REG_SET(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0, + GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, + address.high_part); + + REG_SET_2(GRPH_SECONDARY_SURFACE_ADDRESS, 0, + GRPH_SECONDARY_SURFACE_ADDRESS, address.low_part >> 8, + GRPH_SECONDARY_DFQ_ENABLE, 0); +} + +static void program_pri_addr( + struct dce_mem_input *dce_mi, + PHYSICAL_ADDRESS_LOC address) +{ + /*high register MUST be programmed first*/ + REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, + address.high_part); + + REG_SET(GRPH_PRIMARY_SURFACE_ADDRESS, 0, + GRPH_PRIMARY_SURFACE_ADDRESS, + address.low_part >> 8); +} + + +static bool dce_mi_is_flip_pending(struct mem_input *mem_input) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); + uint32_t update_pending; + + REG_GET(GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, &update_pending); + if (update_pending) + return true; + + mem_input->current_address = mem_input->request_address; + return false; +} + +static bool dce_mi_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); + + /* TODO: Figure out if two modes are needed: + * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 + * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 + */ + REG_UPDATE(GRPH_UPDATE, + GRPH_UPDATE_LOCK, 1); + + if (flip_immediate) { + REG_UPDATE_2(GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, 1); + } else { + REG_UPDATE_2(GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0); + } + + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) + break; + program_pri_addr(dce_mi, address->grph.addr); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0 + || address->grph_stereo.right_addr.quad_part == 0) + break; + program_pri_addr(dce_mi, address->grph_stereo.left_addr); + program_sec_addr(dce_mi, address->grph_stereo.right_addr); + break; + default: + /* not supported */ + BREAK_TO_DEBUGGER(); + break; + } + + mem_input->request_address = *address; + + if (flip_immediate) + mem_input->current_address = *address; + + REG_UPDATE(GRPH_UPDATE, + GRPH_UPDATE_LOCK, 0); + + return true; +} + +static void dce_mi_update_dchub(struct mem_input *mi, + struct dchub_init_data *dh_data) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE_2(DCHUB_FB_LOCATION, + FB_TOP, 0, + FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, 0); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, 0x03FFFF); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + +static struct mem_input_funcs dce_mi_funcs = { + .mem_input_program_display_marks = dce_mi_program_display_marks, + .allocate_mem_input = dce_mi_allocate_dmif, + .free_mem_input = dce_mi_free_dmif, + .mem_input_program_surface_flip_and_addr = + dce_mi_program_surface_flip_and_addr, + .mem_input_program_pte_vm = dce_mi_program_pte_vm, + .mem_input_program_surface_config = + dce_mi_program_surface_config, + .mem_input_is_flip_pending = dce_mi_is_flip_pending, + .mem_input_update_dchub = dce_mi_update_dchub +}; + + +void dce_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask) +{ + dce_mi->base.ctx = ctx; + + dce_mi->base.inst = inst; + dce_mi->base.funcs = &dce_mi_funcs; + + dce_mi->regs = regs; + dce_mi->shifts = mi_shift; + dce_mi->masks = mi_mask; + +} + +void dce112_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask) +{ + dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); + dce_mi->base.funcs->mem_input_program_display_marks = dce120_mi_program_display_marks; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 4977f5f6e7e2..55481f5adcdf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -26,8 +26,10 @@ #define __DCE_MEM_INPUT_H__ #include "dc_hw_types.h" -struct dce_watermarks; -struct mem_input; +#include "mem_input.h" + +#define TO_DCE_MEM_INPUT(mem_input)\ + container_of(mem_input, struct dce_mem_input, base) #define MI_DCE_BASE_REG_LIST(id)\ SRI(GRPH_ENABLE, DCP, id),\ @@ -40,6 +42,12 @@ struct mem_input; SRI(HW_ROTATION, DCP, id),\ SRI(GRPH_SWAP_CNTL, DCP, id),\ SRI(PRESCALE_GRPH_CONTROL, DCP, id),\ + SRI(GRPH_UPDATE, DCP, id),\ + SRI(GRPH_FLIP_CONTROL, DCP, id),\ + SRI(GRPH_PRIMARY_SURFACE_ADDRESS, DCP, id),\ + SRI(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, DCP, id),\ + SRI(GRPH_SECONDARY_SURFACE_ADDRESS, DCP, id),\ + SRI(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, DCP, id),\ SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\ SRI(DPG_WATERMARK_MASK_CONTROL, DMIF_PG, id),\ SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\ @@ -67,7 +75,11 @@ struct mem_input; MI_DCE_PTE_REG_LIST(id),\ SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id),\ SRI(DPG_PIPE_STUTTER_CONTROL2, DMIF_PG, id),\ - SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id) + SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id),\ + SR(DCHUB_FB_LOCATION),\ + SR(DCHUB_AGP_BASE),\ + SR(DCHUB_AGP_BOT),\ + SR(DCHUB_AGP_TOP) struct dce_mem_input_registers { /* DCP */ @@ -84,6 +96,12 @@ struct dce_mem_input_registers { uint32_t GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT; uint32_t DVMM_PTE_CONTROL; uint32_t DVMM_PTE_ARB_CONTROL; + uint32_t GRPH_UPDATE; + uint32_t GRPH_FLIP_CONTROL; + uint32_t GRPH_PRIMARY_SURFACE_ADDRESS; + uint32_t GRPH_PRIMARY_SURFACE_ADDRESS_HIGH; + uint32_t GRPH_SECONDARY_SURFACE_ADDRESS; + uint32_t GRPH_SECONDARY_SURFACE_ADDRESS_HIGH; /* DMIF_PG */ uint32_t DPG_PIPE_ARBITRATION_CONTROL1; uint32_t DPG_WATERMARK_MASK_CONTROL; @@ -96,6 +114,11 @@ struct dce_mem_input_registers { uint32_t DMIF_BUFFER_CONTROL; /* MC_HUB */ uint32_t MC_HUB_RDREQ_DMIF_LIMIT; + /*DCHUB*/ + uint32_t DCHUB_FB_LOCATION; + uint32_t DCHUB_AGP_BASE; + uint32_t DCHUB_AGP_BOT; + uint32_t DCHUB_AGP_TOP; }; /* Set_Filed_for_Block */ @@ -129,9 +152,16 @@ struct dce_mem_input_registers { SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\ SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\ - SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh) + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh),\ + SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS, GRPH_SECONDARY_SURFACE_ADDRESS, mask_sh),\ + SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS, GRPH_PRIMARY_SURFACE_ADDRESS, mask_sh),\ + SFB(blk, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, mask_sh),\ + SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh) #define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN, mask_sh),\ SFB(blk, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, mask_sh) #define MI_DCP_PTE_MASK_SH_LIST(mask_sh, blk)\ @@ -189,13 +219,22 @@ struct dce_mem_input_registers { SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_WATERMARK, mask_sh) +#define MI_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ + SF(DCHUB_FB_LOCATION, FB_TOP, mask_sh),\ + SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\ + SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ + SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ + SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh) + #define MI_DCE12_MASK_SH_LIST(mask_sh)\ MI_DCP_MASK_SH_LIST(mask_sh, DCP0_),\ + SF(DCP0_GRPH_SECONDARY_SURFACE_ADDRESS, GRPH_SECONDARY_DFQ_ENABLE, mask_sh),\ MI_DCP_DCE11_MASK_SH_LIST(mask_sh, DCP0_),\ MI_DCP_PTE_MASK_SH_LIST(mask_sh, DCP0_),\ MI_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\ - MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_) + MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_),\ + MI_GFX9_DCHUB_MASK_SH_LIST(mask_sh) #define MI_REG_FIELD_LIST(type) \ type GRPH_ENABLE; \ @@ -232,6 +271,15 @@ struct dce_mem_input_registers { type GRPH_SE_ENABLE; \ type GRPH_NUM_SHADER_ENGINES; \ type GRPH_NUM_PIPES; \ + type GRPH_SECONDARY_SURFACE_ADDRESS_HIGH; \ + type GRPH_SECONDARY_SURFACE_ADDRESS; \ + type GRPH_SECONDARY_DFQ_ENABLE; \ + type GRPH_PRIMARY_SURFACE_ADDRESS_HIGH; \ + type GRPH_PRIMARY_SURFACE_ADDRESS; \ + type GRPH_SURFACE_UPDATE_PENDING; \ + type GRPH_SURFACE_UPDATE_IMMEDIATE_EN; \ + type GRPH_SURFACE_UPDATE_H_RETRACE_EN; \ + type GRPH_UPDATE_LOCK; \ type PIXEL_DURATION; \ type URGENCY_WATERMARK_MASK; \ type PSTATE_CHANGE_WATERMARK_MASK; \ @@ -253,6 +301,11 @@ struct dce_mem_input_registers { type DMIF_BUFFERS_ALLOCATED; \ type DMIF_BUFFERS_ALLOCATION_COMPLETED; \ type ENABLE; /* MC_HUB_RDREQ_DMIF_LIMIT */\ + type FB_BASE; \ + type FB_TOP; \ + type AGP_BASE; \ + type AGP_TOP; \ + type AGP_BOT; \ struct dce_mem_input_shift { MI_REG_FIELD_LIST(uint8_t) @@ -266,32 +319,30 @@ struct dce_mem_input_wa { uint8_t single_head_rdreq_dmif_limit; }; -void dce_mem_input_program_pte_vm(struct mem_input *mi, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation); - -void dce_mem_input_program_surface_config(struct mem_input *mi, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - union plane_size *plane_size, - enum dc_rotation_angle rotation, - struct dc_plane_dcc_param *dcc, - bool horizontal_mirror); - -void dce_mem_input_allocate_dmif(struct mem_input *mi, - uint32_t h_total, - uint32_t v_total, - uint32_t pix_clk_khz, - uint32_t total_stream_num); - -void dce_mem_input_free_dmif(struct mem_input *mi, - uint32_t total_stream_num); - -void dce_mem_input_program_display_marks(struct mem_input *mi, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns); +struct dce_mem_input { + struct mem_input base; + + const struct dce_mem_input_registers *regs; + const struct dce_mem_input_shift *shifts; + const struct dce_mem_input_mask *masks; + + struct dce_mem_input_wa wa; +}; + +void dce_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask); + +void dce112_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask); #endif /*__DCE_MEM_INPUT_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 254f9e4d0fc8..8f1fe95dd76c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -35,8 +35,8 @@ #include "irq/dce110/irq_service_dce110.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" -#include "dce110/dce110_mem_input.h" -#include "dce110/dce110_mem_input_v.h" + +#include "dce/dce_mem_input.h" #include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce/dce_opp.h" @@ -123,51 +123,6 @@ static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = { } }; -static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = { - { - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -510,28 +465,18 @@ static const struct dce_mem_input_mask mi_masks = { static struct mem_input *dce100_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offset) + uint32_t inst) { - struct dce110_mem_input *mem_input110 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input110) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { - struct mem_input *mi = &mem_input110->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - mi->wa.single_head_rdreq_dmif_limit = 2; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input110); - return NULL; + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 2; + return &dce_mi->base; } static void dce100_transform_destroy(struct transform **xfm) @@ -671,7 +616,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -986,8 +931,7 @@ static bool construct( goto res_create_fail; } - pool->base.mis[i] = dce100_mem_input_create(ctx, i, - &dce100_mi_reg_offsets[i]); + pool->base.mis[i] = dce100_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile index c54bf0330701..98d956e2f218 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -3,8 +3,7 @@ # It provides the control and status of HW CRTC block. DCE110 = dce110_timing_generator.o \ -dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ -dce110_resource.o \ +dce110_compressor.o dce110_hw_sequencer.o dce110_resource.o \ dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ dce110_mem_input_v.o dce110_opp_v.o dce110_transform_v.o diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c deleted file mode 100644 index 45e1a8d15d9b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" -/* TODO: this needs to be looked at, used by Stella's workaround*/ -#include "gmc/gmc_8_2_d.h" -#include "gmc/gmc_8_2_sh_mask.h" - -#include "include/logger_interface.h" - -#include "dce110_mem_input.h" - -#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) -#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) -#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) - -static void program_sec_addr( - struct dce110_mem_input *mem_input110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t value = 0; - uint32_t temp; - - /*high register MUST be programmed first*/ - temp = address.high_part & - GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; - set_reg_field_value(value, temp, - GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, - GRPH_SECONDARY_SURFACE_ADDRESS_HIGH); - dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH), value); - - value = 0; - temp = address.low_part >> - GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; - set_reg_field_value(value, temp, - GRPH_SECONDARY_SURFACE_ADDRESS, - GRPH_SECONDARY_SURFACE_ADDRESS); - dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS), value); -} - -static void program_pri_addr( - struct dce110_mem_input *mem_input110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t value = 0; - uint32_t temp; - - /*high register MUST be programmed first*/ - temp = address.high_part & - GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; - set_reg_field_value(value, temp, - GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, - GRPH_PRIMARY_SURFACE_ADDRESS_HIGH); - dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH), value); - - value = 0; - temp = address.low_part >> - GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; - set_reg_field_value(value, temp, - GRPH_PRIMARY_SURFACE_ADDRESS, - GRPH_PRIMARY_SURFACE_ADDRESS); - dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS), value); -} - -bool dce110_mem_input_is_flip_pending(struct mem_input *mem_input) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - uint32_t value; - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); - - if (get_reg_field_value(value, GRPH_UPDATE, - GRPH_SURFACE_UPDATE_PENDING)) - return true; - - mem_input->current_address = mem_input->request_address; - return false; -} - -bool dce110_mem_input_program_surface_flip_and_addr( - struct mem_input *mem_input, - const struct dc_plane_address *address, - bool flip_immediate) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - - uint32_t value = 0; - uint32_t value_old = 0; - uint32_t lock_value = 0; - - lock_value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); - set_reg_field_value(lock_value, 1, GRPH_UPDATE, GRPH_UPDATE_LOCK); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE), lock_value); - - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL)); - value_old = value; - if (flip_immediate) { - set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); - set_reg_field_value(value, 1, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); - } else { - set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN); - set_reg_field_value(value, 0, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN); - } - if (value != value_old) { - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_FLIP_CONTROL), value); - } - - switch (address->type) { - case PLN_ADDR_TYPE_GRAPHICS: - if (address->grph.addr.quad_part == 0) - break; - program_pri_addr(mem_input110, address->grph.addr); - break; - case PLN_ADDR_TYPE_GRPH_STEREO: - if (address->grph_stereo.left_addr.quad_part == 0 - || address->grph_stereo.right_addr.quad_part == 0) - break; - program_pri_addr(mem_input110, address->grph_stereo.left_addr); - program_sec_addr(mem_input110, address->grph_stereo.right_addr); - break; - default: - /* not supported */ - BREAK_TO_DEBUGGER(); - break; - } - - mem_input->request_address = *address; - if (flip_immediate) - mem_input->current_address = *address; - - lock_value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE)); - set_reg_field_value(lock_value, 0, GRPH_UPDATE, GRPH_UPDATE_LOCK); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_UPDATE), lock_value); - - return true; -} - -static void program_urgency_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct dce_watermarks marks_low, - uint32_t total_dest_line_time_ns) -{ - /* register value */ - uint32_t urgency_cntl = 0; - uint32_t wm_mask_cntl = 0; - - uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL; - uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - - /*Write mask to enable reading/writing of watermark set A*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 1, - DPG_WATERMARK_MASK_CONTROL, - URGENCY_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - urgency_cntl = dm_read_reg(ctx, urgency_addr); - - set_reg_field_value( - urgency_cntl, - marks_low.d_mark, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_LOW_WATERMARK); - - set_reg_field_value( - urgency_cntl, - total_dest_line_time_ns, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_HIGH_WATERMARK); - dm_write_reg(ctx, urgency_addr, urgency_cntl); - - /*Write mask to enable reading/writing of watermark set B*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 2, - DPG_WATERMARK_MASK_CONTROL, - URGENCY_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - urgency_cntl = dm_read_reg(ctx, urgency_addr); - - set_reg_field_value(urgency_cntl, - marks_low.a_mark, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_LOW_WATERMARK); - - set_reg_field_value(urgency_cntl, - total_dest_line_time_ns, - DPG_PIPE_URGENCY_CONTROL, - URGENCY_HIGH_WATERMARK); - dm_write_reg(ctx, urgency_addr, urgency_cntl); -} - -static void program_stutter_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct dce_watermarks marks) -{ - /* register value */ - uint32_t stutter_cntl = 0; - uint32_t wm_mask_cntl = 0; - - uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL; - uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - - /*Write mask to enable reading/writing of watermark set A*/ - - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 1, - DPG_WATERMARK_MASK_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - stutter_cntl = dm_read_reg(ctx, stutter_addr); - - if (ctx->dc->debug.disable_stutter) { - set_reg_field_value(stutter_cntl, - 0, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE); - } else { - set_reg_field_value(stutter_cntl, - 1, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE); - } - - set_reg_field_value(stutter_cntl, - 1, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_IGNORE_FBC); - - /*Write watermark set A*/ - set_reg_field_value(stutter_cntl, - marks.d_mark, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK); - dm_write_reg(ctx, stutter_addr, stutter_cntl); - - /*Write mask to enable reading/writing of watermark set B*/ - wm_mask_cntl = dm_read_reg(ctx, wm_addr); - set_reg_field_value(wm_mask_cntl, - 2, - DPG_WATERMARK_MASK_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK); - dm_write_reg(ctx, wm_addr, wm_mask_cntl); - - stutter_cntl = dm_read_reg(ctx, stutter_addr); - - /*Write watermark set B*/ - set_reg_field_value(stutter_cntl, - marks.a_mark, - DPG_PIPE_STUTTER_CONTROL, - STUTTER_EXIT_SELF_REFRESH_WATERMARK); - dm_write_reg(ctx, stutter_addr, stutter_cntl); -} - -static void program_nbp_watermark( - const struct dc_context *ctx, - const uint32_t offset, - struct dce_watermarks marks) -{ - uint32_t value; - uint32_t addr; - /* Write mask to enable reading/writing of watermark set A */ - addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_WATERMARK_MASK_CONTROL, - NB_PSTATE_CHANGE_WATERMARK_MASK); - dm_write_reg(ctx, addr, value); - - addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_ENABLE); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); - dm_write_reg(ctx, addr, value); - - /* Write watermark set A */ - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - marks.d_mark, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_WATERMARK); - dm_write_reg(ctx, addr, value); - - /* Write mask to enable reading/writing of watermark set B */ - addr = offset + mmDPG_WATERMARK_MASK_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 2, - DPG_WATERMARK_MASK_CONTROL, - NB_PSTATE_CHANGE_WATERMARK_MASK); - dm_write_reg(ctx, addr, value); - - addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL; - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_ENABLE); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_URGENT_DURING_REQUEST); - set_reg_field_value( - value, - 1, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST); - dm_write_reg(ctx, addr, value); - - /* Write watermark set B */ - value = dm_read_reg(ctx, addr); - set_reg_field_value( - value, - marks.a_mark, - DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, - NB_PSTATE_CHANGE_WATERMARK); - dm_write_reg(ctx, addr, value); -} - -void dce110_mem_input_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns) -{ - struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input); - - program_urgency_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - urgent, - total_dest_line_time_ns); - - program_nbp_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - nbp); - - program_stutter_watermark( - mem_input->ctx, - bm_dce110->offsets.dmif, - stutter); -} - -static struct mem_input_funcs dce110_mem_input_funcs = { - .mem_input_program_display_marks = - dce110_mem_input_program_display_marks, - .allocate_mem_input = dce_mem_input_allocate_dmif, - .free_mem_input = dce_mem_input_free_dmif, - .mem_input_program_surface_flip_and_addr = - dce110_mem_input_program_surface_flip_and_addr, - .mem_input_program_pte_vm = - dce_mem_input_program_pte_vm, - .mem_input_program_surface_config = - dce_mem_input_program_surface_config, - .mem_input_is_flip_pending = - dce110_mem_input_is_flip_pending, - .mem_input_update_dchub = NULL -}; -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce110_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) -{ - /* supported stutter method - * STUTTER_MODE_ENHANCED - * STUTTER_MODE_QUAD_DMIF_BUFFER - * STUTTER_MODE_WATERMARK_NBP_STATE - */ - mem_input110->base.funcs = &dce110_mem_input_funcs; - mem_input110->base.ctx = ctx; - - mem_input110->base.inst = inst; - - mem_input110->offsets = *offsets; - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h deleted file mode 100644 index 5f10f266f096..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCE110_H__ -#define __DC_MEM_INPUT_DCE110_H__ - -#include "mem_input.h" - -#define TO_DCE110_MEM_INPUT(mi)\ - container_of(mi, struct dce110_mem_input, base) - -struct dce110_mem_input_reg_offsets { - uint32_t dcp; - uint32_t dmif; - uint32_t pipe; -}; - -struct dce110_mem_input { - struct mem_input base; - struct dce110_mem_input_reg_offsets offsets; -}; - -bool dce110_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets); - -/* - * dce110_mem_input_program_display_marks - * - * This function will program nbp stutter and urgency watermarks to minimum - * allowable values - */ -void dce110_mem_input_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns); - -/* - * dce110_allocate_mem_input - * - * This function will allocate a dmif buffer and program required - * pixel duration for pipe - */ -void dce110_allocate_mem_input( - struct mem_input *mem_input, - uint32_t h_total,/* for current stream */ - uint32_t v_total,/* for current stream */ - uint32_t pix_clk_khz,/* for current stream */ - uint32_t total_stream_num); - -/* - * dce110_free_mem_input - * - * This function will deallocate a dmif buffer from pipe - */ -void dce110_free_mem_input( - struct mem_input *mem_input, - uint32_t total_stream_num); - -/* - * dce110_mem_input_program_surface_flip_and_addr - * - * This function programs hsync/vsync mode and surface address - */ -bool dce110_mem_input_program_surface_flip_and_addr( - struct mem_input *mem_input, - const struct dc_plane_address *address, - bool flip_immediate); - -/* - * dce110_mem_input_program_surface_config - * - * This function will program surface tiling, size, rotation and pixel format - * to corresponding dcp registers. - */ -bool dce110_mem_input_program_surface_config( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - union plane_size *plane_size, - enum dc_rotation_angle rotation, - struct dc_plane_dcc_param *dcc, - bool horizontal_mirror, - bool visible); - -/* - * dce110_mem_input_is_flip_pending - * - * This function will wait until the surface update-pending bit is cleared. - * This is necessary when a flip immediate call is requested as we shouldn't - * return until the flip has actually occurred. - */ -bool dce110_mem_input_is_flip_pending( - struct mem_input *mem_input); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 78dd3ae3af5f..9777a4d961d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -33,29 +33,17 @@ #include "include/logger_interface.h" #include "inc/dce_calcs.h" -#include "dce110_mem_input.h" - -#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) -/*#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif)*/ -/*#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe)*/ - -static const struct dce110_mem_input_reg_offsets dce110_mi_v_reg_offsets[] = { - { - .dcp = 0, - .dmif = 0, - .pipe = 0, - } -}; +#include "dce/dce_mem_input.h" static void set_flip_control( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, bool immediate) { uint32_t value = 0; value = dm_read_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_FLIP_CONTROL)); + mmUNP_FLIP_CONTROL); set_reg_field_value(value, 1, UNP_FLIP_CONTROL, @@ -63,13 +51,13 @@ static void set_flip_control( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_FLIP_CONTROL), + mmUNP_FLIP_CONTROL, value); } /* chroma part */ static void program_pri_addr_c( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, PHYSICAL_ADDRESS_LOC address) { uint32_t value = 0; @@ -84,7 +72,7 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MAS dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C), + mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C, value); temp = 0; @@ -98,13 +86,13 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MAS dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C), + mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C, value); } /* luma part */ static void program_pri_addr_l( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, PHYSICAL_ADDRESS_LOC address) { uint32_t value = 0; @@ -120,7 +108,7 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MAS dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L), + mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, value); temp = 0; @@ -134,12 +122,12 @@ UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MAS dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L), + mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, value); } static void program_addr( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, const struct dc_plane_address *addr) { switch (addr->type) { @@ -162,19 +150,19 @@ static void program_addr( } } -static void enable(struct dce110_mem_input *mem_input110) +static void enable(struct dce_mem_input *mem_input110) { uint32_t value = 0; - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_ENABLE)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_ENABLE); set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE); dm_write_reg(mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_ENABLE), + mmUNP_GRPH_ENABLE, value); } static void program_tiling( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) { @@ -239,7 +227,7 @@ static void program_tiling( } static void program_size_and_rotation( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, enum dc_rotation_angle rotation, const union plane_size *plane_size) { @@ -277,7 +265,7 @@ static void program_size_and_rotation( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PITCH_L), + mmUNP_GRPH_PITCH_L, value); value = 0; @@ -285,7 +273,7 @@ static void program_size_and_rotation( UNP_GRPH_PITCH_C, GRPH_PITCH_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_PITCH_C), + mmUNP_GRPH_PITCH_C, value); value = 0; @@ -293,7 +281,7 @@ static void program_size_and_rotation( UNP_GRPH_X_START_L, GRPH_X_START_L); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_X_START_L), + mmUNP_GRPH_X_START_L, value); value = 0; @@ -301,7 +289,7 @@ static void program_size_and_rotation( UNP_GRPH_X_START_C, GRPH_X_START_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_X_START_C), + mmUNP_GRPH_X_START_C, value); value = 0; @@ -309,7 +297,7 @@ static void program_size_and_rotation( UNP_GRPH_Y_START_L, GRPH_Y_START_L); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_Y_START_L), + mmUNP_GRPH_Y_START_L, value); value = 0; @@ -317,7 +305,7 @@ static void program_size_and_rotation( UNP_GRPH_Y_START_C, GRPH_Y_START_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_Y_START_C), + mmUNP_GRPH_Y_START_C, value); value = 0; @@ -326,7 +314,7 @@ static void program_size_and_rotation( UNP_GRPH_X_END_L, GRPH_X_END_L); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_X_END_L), + mmUNP_GRPH_X_END_L, value); value = 0; @@ -335,7 +323,7 @@ static void program_size_and_rotation( UNP_GRPH_X_END_C, GRPH_X_END_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_X_END_C), + mmUNP_GRPH_X_END_C, value); value = 0; @@ -344,7 +332,7 @@ static void program_size_and_rotation( UNP_GRPH_Y_END_L, GRPH_Y_END_L); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_Y_END_L), + mmUNP_GRPH_Y_END_L, value); value = 0; @@ -353,7 +341,7 @@ static void program_size_and_rotation( UNP_GRPH_Y_END_C, GRPH_Y_END_C); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_Y_END_C), + mmUNP_GRPH_Y_END_C, value); value = 0; @@ -378,12 +366,12 @@ static void program_size_and_rotation( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_HW_ROTATION), + mmUNP_HW_ROTATION, value); } static void program_pixel_format( - struct dce110_mem_input *mem_input110, + struct dce_mem_input *mem_input110, enum surface_pixel_format format) { if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { @@ -393,7 +381,7 @@ static void program_pixel_format( value = dm_read_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL)); + mmUNP_GRPH_CONTROL); switch (format) { case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: @@ -440,12 +428,12 @@ static void program_pixel_format( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL), + mmUNP_GRPH_CONTROL, value); value = dm_read_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + mmUNP_GRPH_CONTROL_EXP); /* VIDEO FORMAT 0 */ set_reg_field_value( @@ -455,7 +443,7 @@ static void program_pixel_format( VIDEO_FORMAT); dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL_EXP), + mmUNP_GRPH_CONTROL_EXP, value); } else { @@ -465,7 +453,7 @@ static void program_pixel_format( value = dm_read_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL_EXP)); + mmUNP_GRPH_CONTROL_EXP); switch (format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: @@ -487,17 +475,17 @@ static void program_pixel_format( dm_write_reg( mem_input110->base.ctx, - DCP_REG(mmUNP_GRPH_CONTROL_EXP), + mmUNP_GRPH_CONTROL_EXP, value); } } -bool dce110_mem_input_v_is_surface_pending(struct mem_input *mem_input) +bool dce_mem_input_v_is_surface_pending(struct mem_input *mem_input) { - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); uint32_t value; - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_GRPH_UPDATE)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_UPDATE); if (get_reg_field_value(value, UNP_GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING)) @@ -507,12 +495,12 @@ bool dce110_mem_input_v_is_surface_pending(struct mem_input *mem_input) return false; } -bool dce110_mem_input_v_program_surface_flip_and_addr( +bool dce_mem_input_v_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate) { - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); set_flip_control(mem_input110, flip_immediate); program_addr(mem_input110, @@ -584,13 +572,13 @@ static const unsigned int *get_dvmm_hw_setting( } } -void dce110_mem_input_v_program_pte_vm( +void dce_mem_input_v_program_pte_vm( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation) { - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); const unsigned int *pte = get_dvmm_hw_setting(tiling_info, format, false); const unsigned int *pte_chroma = get_dvmm_hw_setting(tiling_info, format, true); @@ -628,36 +616,36 @@ void dce110_mem_input_v_program_pte_vm( break; } - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT); /* TODO: un-hardcode requestlimit */ set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L); set_reg_field_value(value, 0xff, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT, UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT, value); - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL); set_reg_field_value(value, page_width, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH); set_reg_field_value(value, page_height, UNP_DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT); set_reg_field_value(value, min_pte_before_flip, UNP_DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL, value); - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL); set_reg_field_value(value, pte[5], UNP_DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK); set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL, value); - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL_C); set_reg_field_value(value, page_width_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_WIDTH_C); set_reg_field_value(value, page_height_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_PAGE_HEIGHT_C); set_reg_field_value(value, min_pte_before_flip_chroma, UNP_DVMM_PTE_CONTROL_C, DVMM_MIN_PTE_BEFORE_FLIP_C); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_CONTROL_C), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_CONTROL_C, value); - value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C)); + value = dm_read_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL_C); set_reg_field_value(value, pte_chroma[5], UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_PTE_REQ_PER_CHUNK_C); set_reg_field_value(value, 0xff, UNP_DVMM_PTE_ARB_CONTROL_C, DVMM_MAX_PTE_REQ_OUTSTANDING_C); - dm_write_reg(mem_input110->base.ctx, DCP_REG(mmUNP_DVMM_PTE_ARB_CONTROL_C), value); + dm_write_reg(mem_input110->base.ctx, mmUNP_DVMM_PTE_ARB_CONTROL_C, value); } -void dce110_mem_input_v_program_surface_config( +void dce_mem_input_v_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -666,7 +654,7 @@ void dce110_mem_input_v_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizotal_mirror) { - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); + struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input); enable(mem_input110); program_tiling(mem_input110, tiling_info, format); @@ -943,7 +931,7 @@ static void program_nbp_watermark_c( marks); } -void dce110_mem_input_v_program_display_marks( +void dce_mem_input_v_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -965,7 +953,7 @@ void dce110_mem_input_v_program_display_marks( } -void dce110_mem_input_program_chroma_display_marks( +void dce_mem_input_program_chroma_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -1036,42 +1024,29 @@ void dce110_free_mem_input_v( static struct mem_input_funcs dce110_mem_input_v_funcs = { .mem_input_program_display_marks = - dce110_mem_input_v_program_display_marks, + dce_mem_input_v_program_display_marks, .mem_input_program_chroma_display_marks = - dce110_mem_input_program_chroma_display_marks, + dce_mem_input_program_chroma_display_marks, .allocate_mem_input = dce110_allocate_mem_input_v, .free_mem_input = dce110_free_mem_input_v, .mem_input_program_surface_flip_and_addr = - dce110_mem_input_v_program_surface_flip_and_addr, + dce_mem_input_v_program_surface_flip_and_addr, .mem_input_program_pte_vm = - dce110_mem_input_v_program_pte_vm, + dce_mem_input_v_program_pte_vm, .mem_input_program_surface_config = - dce110_mem_input_v_program_surface_config, + dce_mem_input_v_program_surface_config, .mem_input_is_flip_pending = - dce110_mem_input_v_is_surface_pending + dce_mem_input_v_is_surface_pending }; /*****************************************/ /* Constructor, Destructor */ /*****************************************/ -bool dce110_mem_input_v_construct( - struct dce110_mem_input *mem_input110, +void dce110_mem_input_v_construct( + struct dce_mem_input *dce_mi, struct dc_context *ctx) { - mem_input110->base.funcs = &dce110_mem_input_v_funcs; - mem_input110->base.ctx = ctx; - - mem_input110->base.inst = 0; - - mem_input110->offsets = dce110_mi_v_reg_offsets[0]; - - return true; + dce_mi->base.funcs = &dce110_mem_input_v_funcs; + dce_mi->base.ctx = ctx; } -#if 0 -void dce110_mem_input_v_destroy(struct mem_input **mem_input) -{ - dm_free(TO_DCE110_MEM_INPUT(*mem_input)); - *mem_input = NULL; -} -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h index b2667eefa3d0..f01d4a607fea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.h @@ -26,70 +26,10 @@ #define __DC_MEM_INPUT_V_DCE110_H__ #include "mem_input.h" -#include "dce110_mem_input.h" +#include "dce/dce_mem_input.h" -bool dce110_mem_input_v_construct( - struct dce110_mem_input *mem_input110, +void dce110_mem_input_v_construct( + struct dce_mem_input *dce_mi, struct dc_context *ctx); -/* - * This function will program nbp stutter and urgency watermarks to minimum - * allowable values - */ -void dce110_mem_input_v_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns); - -/* - * This function will allocate a dmif buffer and program required - * pixel duration for pipe - */ -void dce110_allocate_mem_v_input( - struct mem_input *mem_input, - uint32_t h_total,/* for current stream */ - uint32_t v_total,/* for current stream */ - uint32_t pix_clk_khz,/* for current stream */ - uint32_t total_stream_num); - -/* - * This function will deallocate a dmif buffer from pipe - */ -void dce110_free_mem_v_input( - struct mem_input *mem_input, - uint32_t total_stream_num); - -/* - * This function programs hsync/vsync mode and surface address - */ -bool dce110_mem_input_v_program_surface_flip_and_addr( - struct mem_input *mem_input, - const struct dc_plane_address *address, - bool flip_immediate); - -/* - * dce110_mem_input_v_program_scatter_gather - * - * This function will program scatter gather registers. - */ -bool dce110_mem_input_v_program_pte_vm( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation); - -/* - * This function will program surface tiling, size, rotation and pixel format - * to corresponding dcp registers. - */ -bool dce110_mem_input_v_program_surface_config( - struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - union plane_size *plane_size, - enum dc_rotation_angle rotation, - bool visible); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 041d11968566..3ed5b9445535 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -38,7 +38,7 @@ #include "dce110/dce110_timing_generator_v.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" -#include "dce110/dce110_mem_input.h" +#include "dce/dce_mem_input.h" #include "dce110/dce110_mem_input_v.h" #include "dce/dce_ipp.h" #include "dce/dce_transform.h" @@ -133,30 +133,6 @@ static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = { } }; -static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = { - { - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -520,30 +496,21 @@ static const struct dce_mem_input_mask mi_masks = { .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; + static struct mem_input *dce110_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offset) + uint32_t inst) { - struct dce110_mem_input *mem_input110 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input110) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce110_mem_input_construct(mem_input110, ctx, inst, offset)) { - struct mem_input *mi = &mem_input110->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - mi->wa.single_head_rdreq_dmif_limit = 3; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input110); - return NULL; + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 3; + return &dce_mi->base; } static void dce110_transform_destroy(struct transform **xfm) @@ -698,7 +665,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -1132,7 +1099,7 @@ static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) { struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); - struct dce110_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); + struct dce_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); if ((dce110_tgv == NULL) || @@ -1345,8 +1312,7 @@ static bool construct( goto res_create_fail; } - pool->base.mis[i] = dce110_mem_input_create(ctx, i, - &dce110_mi_reg_offsets[i]); + pool->base.mis[i] = dce110_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile index 2d536fbc60c4..265ac4310d85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile @@ -3,7 +3,7 @@ # It provides the control and status of HW CRTC block. DCE112 = dce112_compressor.o dce112_hw_sequencer.o \ -dce112_resource.o dce112_mem_input.o +dce112_resource.o AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112)) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c deleted file mode 100644 index c29007dafe21..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" -#include "dce112_mem_input.h" - - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - - -#define DCP_REG(reg) (reg + mem_input110->offsets.dcp) -#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif) -#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe) - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce112_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) -{ - if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) - return false; - - mem_input110->base.funcs->mem_input_program_display_marks = - dce_mem_input_program_display_marks; - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h deleted file mode 100644 index de2aaf0f9a8e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_mem_input.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCE112_H__ -#define __DC_MEM_INPUT_DCE112_H__ - -#include "mem_input.h" -#include "dce110/dce110_mem_input.h" - -bool dce112_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets); - - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 0ed2616dd5cd..f405d6eecaa5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -32,9 +32,10 @@ #include "include/irq_service_interface.h" #include "dce110/dce110_resource.h" #include "dce110/dce110_timing_generator.h" -#include "dce112/dce112_mem_input.h" #include "irq/dce110/irq_service_dce110.h" + +#include "dce/dce_mem_input.h" #include "dce/dce_transform.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" @@ -132,51 +133,6 @@ static const struct dce110_timing_generator_offsets dce112_tg_offsets[] = { } }; -static const struct dce110_mem_input_reg_offsets dce112_mi_reg_offsets[] = { - { - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -541,27 +497,17 @@ static const struct dce_mem_input_mask mi_masks = { static struct mem_input *dce112_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offset) + uint32_t inst) { - struct dce110_mem_input *mem_input110 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input110) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce112_mem_input_construct(mem_input110, ctx, inst, offset)) { - struct mem_input *mi = &mem_input110->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input110); - return NULL; + dce112_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + return &dce_mi->base; } static void dce112_transform_destroy(struct transform **xfm) @@ -705,7 +651,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -1347,10 +1293,7 @@ static bool construct( goto res_create_fail; } - pool->base.mis[i] = dce112_mem_input_create( - ctx, - i, - &dce112_mi_reg_offsets[i]); + pool->base.mis[i] = dce112_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile index 826c12ee368c..1779b963525c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile @@ -4,7 +4,7 @@ DCE120 = dce120_resource.o dce120_timing_generator.o \ -dce120_mem_input.o dce120_hw_sequencer.o +dce120_hw_sequencer.o AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120)) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c deleted file mode 100644 index c0677211bd93..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" -#include "dce120_mem_input.h" - - -#include "vega10/DC/dce_12_0_offset.h" -#include "vega10/DC/dce_12_0_sh_mask.h" -#include "vega10/soc15ip.h" - -#define GENERAL_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(mem_input110->base.ctx, 0, reg_name, n, __VA_ARGS__) - -#define GENERAL_REG_UPDATE(reg, field, val) \ - GENERAL_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define GENERAL_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - GENERAL_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - - - -#define DCP_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.dcp, reg_name, n, __VA_ARGS__) - -#define DCP_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.dcp, reg_name, n, __VA_ARGS__) - -#define DCP_REG_UPDATE(reg, field, val) \ - DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - DCP_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define DCP_REG_SET(reg, field, val) \ - DCP_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \ - DCP_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DCP_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - - -#define DMIF_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.dmif, reg_name, n, __VA_ARGS__) - -#define DMIF_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.dmif, reg_name, n, __VA_ARGS__) - -#define DMIF_REG_UPDATE(reg, field, val) \ - DMIF_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define DMIF_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - DMIF_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DMIF_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - DMIF_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define DMIF_REG_SET(reg, field, val) \ - DMIF_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define DMIF_REG_SET_2(reg, field1, val1, field2, val2) \ - DMIF_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define DMIF_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - DMIF_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - - -#define PIPE_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(mem_input110->base.ctx, mem_input110->offsets.pipe, reg_name, n, __VA_ARGS__) - -#define PIPE_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(mem_input110->base.ctx, mem_input110->offsets.pipe, reg_name, n, __VA_ARGS__) - -#define PIPE_REG_UPDATE(reg, field, val) \ - PIPE_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define PIPE_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - PIPE_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define PIPE_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - PIPE_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - -#define PIPE_REG_SET(reg, field, val) \ - PIPE_REG_SET_N(reg, 1, FD(reg##__##field), val) - -#define PIPE_REG_SET_2(reg, field1, val1, field2, val2) \ - PIPE_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define PIPE_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \ - PIPE_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - - -static void program_sec_addr( - struct dce110_mem_input *mem_input110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t temp; - - /*high register MUST be programmed first*/ - temp = address.high_part & - DCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK; - - DCP_REG_SET( - DCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, - GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, - temp); - - temp = address.low_part >> - DCP0_GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT; - - DCP_REG_SET_2( - DCP0_GRPH_SECONDARY_SURFACE_ADDRESS, - GRPH_SECONDARY_SURFACE_ADDRESS, temp, - GRPH_SECONDARY_DFQ_ENABLE, 0); -} - -static void program_pri_addr( - struct dce110_mem_input *mem_input110, - PHYSICAL_ADDRESS_LOC address) -{ - uint32_t temp; - - /*high register MUST be programmed first*/ - temp = address.high_part & - DCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK; - - DCP_REG_SET( - DCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, - GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, - temp); - - temp = address.low_part >> - DCP0_GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT; - - DCP_REG_SET( - DCP0_GRPH_PRIMARY_SURFACE_ADDRESS, - GRPH_PRIMARY_SURFACE_ADDRESS, - temp); -} - - -static bool mem_input_is_flip_pending(struct mem_input *mem_input) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - uint32_t value; - - value = dm_read_reg_soc15(mem_input110->base.ctx, - mmDCP0_GRPH_UPDATE, mem_input110->offsets.dcp); - - if (get_reg_field_value(value, DCP0_GRPH_UPDATE, - GRPH_SURFACE_UPDATE_PENDING)) - return true; - - mem_input->current_address = mem_input->request_address; - return false; -} - -static bool mem_input_program_surface_flip_and_addr( - struct mem_input *mem_input, - const struct dc_plane_address *address, - bool flip_immediate) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input); - - /* TODO: Figure out if two modes are needed: - * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 - * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 - */ - DCP_REG_UPDATE(DCP0_GRPH_UPDATE, - GRPH_UPDATE_LOCK, 1); - - if (flip_immediate) { - DCP_REG_UPDATE_2( - DCP0_GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, - GRPH_SURFACE_UPDATE_H_RETRACE_EN, 1); - } else { - DCP_REG_UPDATE_2( - DCP0_GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, - GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0); - } - - switch (address->type) { - case PLN_ADDR_TYPE_GRAPHICS: - if (address->grph.addr.quad_part == 0) - break; - program_pri_addr(mem_input110, address->grph.addr); - break; - case PLN_ADDR_TYPE_GRPH_STEREO: - if (address->grph_stereo.left_addr.quad_part == 0 - || address->grph_stereo.right_addr.quad_part == 0) - break; - program_pri_addr(mem_input110, address->grph_stereo.left_addr); - program_sec_addr(mem_input110, address->grph_stereo.right_addr); - break; - default: - /* not supported */ - BREAK_TO_DEBUGGER(); - break; - } - - mem_input->request_address = *address; - - if (flip_immediate) - mem_input->current_address = *address; - - DCP_REG_UPDATE(DCP0_GRPH_UPDATE, - GRPH_UPDATE_LOCK, 0); - - return true; -} - -static void mem_input_update_dchub(struct mem_input *mi, - struct dchub_init_data *dh_data) -{ - struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mi); - /* TODO: port code from dal2 */ - switch (dh_data->fb_mode) { - case FRAME_BUFFER_MODE_ZFB_ONLY: - /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ - GENERAL_REG_UPDATE_2( - DCHUB_FB_LOCATION, - FB_TOP, 0, - FB_BASE, 0x0FFFF); - - GENERAL_REG_UPDATE( - DCHUB_AGP_BASE, - AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - GENERAL_REG_UPDATE( - DCHUB_AGP_BOT, - AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - GENERAL_REG_UPDATE( - DCHUB_AGP_TOP, - AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - GENERAL_REG_UPDATE( - DCHUB_AGP_BASE, - AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - GENERAL_REG_UPDATE( - DCHUB_AGP_BOT, - AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - GENERAL_REG_UPDATE( - DCHUB_AGP_TOP, - AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_LOCAL_ONLY: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - GENERAL_REG_UPDATE( - DCHUB_AGP_BASE, - AGP_BASE, 0); - - GENERAL_REG_UPDATE( - DCHUB_AGP_BOT, - AGP_BOT, 0x03FFFF); - - GENERAL_REG_UPDATE( - DCHUB_AGP_TOP, - AGP_TOP, 0); - break; - default: - break; - } - - dh_data->dchub_initialzied = true; - dh_data->dchub_info_valid = false; -} - -static struct mem_input_funcs dce120_mem_input_funcs = { - .mem_input_program_display_marks = dce_mem_input_program_display_marks, - .allocate_mem_input = dce_mem_input_allocate_dmif, - .free_mem_input = dce_mem_input_free_dmif, - .mem_input_program_surface_flip_and_addr = - mem_input_program_surface_flip_and_addr, - .mem_input_program_pte_vm = dce_mem_input_program_pte_vm, - .mem_input_program_surface_config = - dce_mem_input_program_surface_config, - .mem_input_is_flip_pending = mem_input_is_flip_pending, - .mem_input_update_dchub = mem_input_update_dchub -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce120_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) -{ - /* supported stutter method - * STUTTER_MODE_ENHANCED - * STUTTER_MODE_QUAD_DMIF_BUFFER - * STUTTER_MODE_WATERMARK_NBP_STATE - */ - - if (!dce110_mem_input_construct(mem_input110, ctx, inst, offsets)) - return false; - - mem_input110->base.funcs = &dce120_mem_input_funcs; - mem_input110->offsets = *offsets; - - return true; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h deleted file mode 100644 index 379fd72155b9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_mem_input.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCE120_H__ -#define __DC_MEM_INPUT_DCE120_H__ - -#include "mem_input.h" -#include "dce110/dce110_mem_input.h" - -bool dce120_mem_input_construct( - struct dce110_mem_input *mem_input110, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index b13abb025e1b..1276dabfb208 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -41,8 +41,7 @@ #include "dce/dce_clock_source.h" #include "dce/dce_clocks.h" #include "dce/dce_ipp.h" -#include "dce110/dce110_mem_input.h" -#include "dce120/dce120_mem_input.h" +#include "dce/dce_mem_input.h" #include "dce110/dce110_hw_sequencer.h" #include "dce120/dce120_hw_sequencer.h" @@ -376,51 +375,6 @@ struct output_pixel_processor *dce120_opp_create( return NULL; } -static const struct dce110_mem_input_reg_offsets dce120_mi_reg_offsets[] = { - { - .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - static const struct bios_registers bios_regs = { .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) }; @@ -518,7 +472,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -708,27 +662,17 @@ static const struct dce_mem_input_mask mi_masks = { static struct mem_input *dce120_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offset) + uint32_t inst) { - struct dce110_mem_input *mem_input110 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input110) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce120_mem_input_construct(mem_input110, ctx, inst, offset)) { - struct mem_input *mi = &mem_input110->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input110); - return NULL; + dce112_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + return &dce_mi->base; } static struct transform *dce120_transform_create( @@ -1007,8 +951,7 @@ static bool construct( goto controller_create_fail; } - pool->base.mis[i] = dce120_mem_input_create(ctx, - i, &dce120_mi_reg_offsets[i]); + pool->base.mis[i] = dce120_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 1d54d5fa0fd2..c1105895e5fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -2,8 +2,7 @@ # Makefile for the 'controller' sub-component of DAL. # It provides the control and status of HW CRTC block. -DCE80 = dce80_timing_generator.o \ - dce80_compressor.o dce80_mem_input.o dce80_hw_sequencer.o \ +DCE80 = dce80_timing_generator.o dce80_compressor.o dce80_hw_sequencer.o \ dce80_resource.o AMD_DAL_DCE80 = $(addprefix $(AMDDALPATH)/dc/dce80/,$(DCE80)) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c deleted file mode 100644 index 933e3d819f27..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "dm_services.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" -/* TODO: this needs to be looked at, used by Stella's workaround*/ -#include "gmc/gmc_7_1_d.h" -#include "gmc/gmc_7_1_sh_mask.h" - -#include "include/logger_interface.h" -#include "inc/dce_calcs.h" - -#include "../dce110/dce110_mem_input.h" -#include "dce80_mem_input.h" - -#define MAX_WATERMARK 0xFFFF -#define SAFE_NBP_MARK 0x7FFF - -#define DCP_REG(reg) (reg + mem_input80->offsets.dcp) -#define DMIF_REG(reg) (reg + mem_input80->offsets.dmif) -#define PIPE_REG(reg) (reg + mem_input80->offsets.pipe) - -static struct mem_input_funcs dce80_mem_input_funcs = { - .mem_input_program_display_marks = - dce110_mem_input_program_display_marks, - .allocate_mem_input = dce_mem_input_allocate_dmif, - .free_mem_input = dce_mem_input_free_dmif, - .mem_input_program_surface_flip_and_addr = - dce110_mem_input_program_surface_flip_and_addr, - .mem_input_program_surface_config = - dce_mem_input_program_surface_config, - .mem_input_is_flip_pending = - dce110_mem_input_is_flip_pending, - .mem_input_update_dchub = NULL -}; - -/*****************************************/ -/* Constructor, Destructor */ -/*****************************************/ - -bool dce80_mem_input_construct( - struct dce110_mem_input *mem_input80, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) -{ - /* supported stutter method - * STUTTER_MODE_ENHANCED - * STUTTER_MODE_QUAD_DMIF_BUFFER - */ - mem_input80->base.funcs = &dce80_mem_input_funcs; - mem_input80->base.ctx = ctx; - - mem_input80->base.inst = inst; - - mem_input80->offsets = *offsets; - - return true; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h deleted file mode 100644 index 357b9e2e9f1e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_mem_input.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_MEM_INPUT_DCE80_H__ -#define __DC_MEM_INPUT_DCE80_H__ - -#include "mem_input.h" - -bool dce80_mem_input_construct( - struct dce110_mem_input *mem_input80, - struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 5735914a8737..095e437ce112 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -35,12 +35,12 @@ #include "include/irq_service_interface.h" #include "irq/dce80/irq_service_dce80.h" #include "dce110/dce110_timing_generator.h" -#include "dce110/dce110_mem_input.h" #include "dce110/dce110_resource.h" #include "dce80/dce80_timing_generator.h" +#include "dce/dce_mem_input.h" #include "dce/dce_link_encoder.h" #include "dce/dce_stream_encoder.h" -#include "dce80/dce80_mem_input.h" +#include "dce/dce_mem_input.h" #include "dce/dce_ipp.h" #include "dce/dce_transform.h" #include "dce/dce_opp.h" @@ -141,51 +141,6 @@ static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = { } }; -static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets[] = { - { - .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE0_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE1_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE2_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE3_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE4_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - }, - { - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - .pipe = (mmPIPE5_DMIF_BUFFER_CONTROL - - mmPIPE0_DMIF_BUFFER_CONTROL), - } -}; - /* set register offset */ #define SR(reg_name)\ .reg_name = mm ## reg_name @@ -541,28 +496,18 @@ static const struct dce_mem_input_mask mi_masks = { static struct mem_input *dce80_mem_input_create( struct dc_context *ctx, - uint32_t inst, - const struct dce110_mem_input_reg_offsets *offsets) + uint32_t inst) { - struct dce110_mem_input *mem_input80 = - dm_alloc(sizeof(struct dce110_mem_input)); + struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); - if (!mem_input80) + if (!dce_mi) { + BREAK_TO_DEBUGGER(); return NULL; - - if (dce80_mem_input_construct(mem_input80, ctx, inst, offsets)) { - struct mem_input *mi = &mem_input80->base; - - mi->regs = &mi_regs[inst]; - mi->shifts = &mi_shifts; - mi->masks = &mi_masks; - mi->wa.single_head_rdreq_dmif_limit = 2; - return mi; } - BREAK_TO_DEBUGGER(); - dm_free(mem_input80); - return NULL; + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 2; + return &dce_mi->base; } static void dce80_transform_destroy(struct transform **xfm) @@ -684,7 +629,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE110_MEM_INPUT(pool->base.mis[i])); + dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -1000,8 +945,7 @@ static bool construct( goto res_create_fail; } - pool->base.mis[i] = dce80_mem_input_create(ctx, i, - &dce80_mi_reg_offsets[i]); + pool->base.mis[i] = dce80_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create memory input!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 79fbc60e21c9..bd0dfeb2afa2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -28,8 +28,6 @@ #include "dc.h" #include "include/grph_object_id.h" -#include "dce/dce_mem_input.h" /* temporary */ - #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dml/display_mode_structs.h" @@ -51,7 +49,6 @@ struct dcn_watermark_set { struct dcn_watermarks c; struct dcn_watermarks d; }; - #endif struct dce_watermarks { @@ -74,11 +71,6 @@ struct mem_input { struct dc_plane_address current_address; uint32_t inst; struct stutter_modes stutter_mode; - - const struct dce_mem_input_registers *regs; - const struct dce_mem_input_shift *shifts; - const struct dce_mem_input_mask *masks; - struct dce_mem_input_wa wa; }; struct mem_input_funcs { -- GitLab From 3379da831b4032e3d7cac2cb199293e59f0c9e9f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 15 May 2017 13:59:31 -0400 Subject: [PATCH 0466/2898] drm/amd/display: Use dc_update_surfaces_for_stream for flip. Today we use special interface for flip because of fear of cuncurency issues over dc->current_ctx. This should be no longer an issue when flipping on multiple CRTCs concurently since for fast update (as flip is) no new context is created and the exsisitng is not destroyed. For full updates case when removing or adding streams on once CRTC while flipping on another Adding all current active CRTC's states to the atomic commit in amdgpu_dm_atomic_check will garntee that any such full update commit will wait for completion of any outstanding flip. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++--- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 23 ++++++++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a2c00c0bf007..7e28f9870b86 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1349,6 +1349,7 @@ static void dm_page_flip(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc; const struct dc_stream *stream; struct dc_flip_addrs addr = { {0} }; + struct dc_surface_update surface_updates[1] = { {0} }; /* * TODO risk of concurrency issues @@ -1411,9 +1412,11 @@ static void dm_page_flip(struct amdgpu_device *adev, acrtc->base.state->event = NULL; } - dc_flip_surface_addrs(adev->dm.dc, - dc_stream_get_status(stream)->surfaces, - &addr, 1); + surface_updates->surface = dc_stream_get_status(stream)->surfaces[0]; + surface_updates->flip_addr = &addr; + + + dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, stream); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 9c0dc9d07626..7d989b6738e4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2901,6 +2901,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; bool need_to_validate = false; struct validate_context *context; + bool wait_4_prev_commits = false; ret = drm_atomic_helper_check(dev, state); @@ -2977,6 +2978,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; + wait_4_prev_commits = true; break; } @@ -3022,6 +3024,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; + wait_4_prev_commits = true; break; } @@ -3033,6 +3036,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, set, set_count, acrtc->stream); + wait_4_prev_commits = true; } break; } @@ -3125,9 +3129,26 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, context = dc_get_validate_context(dc, set, set_count); - if (need_to_validate == false || set_count == 0 || context) + if (need_to_validate == false || set_count == 0 || context) { + ret = 0; + if (wait_4_prev_commits) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_crtc_state *crtc_state; + + if (acrtc->stream) { + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + break; + } + } + } + } + } + if (context) { dc_resource_validate_ctx_destruct(context); dm_free(context); -- GitLab From b802acc7f3266e43905dfeee865bf1acc4e00bce Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 15 May 2017 14:47:02 -0400 Subject: [PATCH 0467/2898] drm/amd/display: Clean unused interface. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 ------------------------ drivers/gpu/drm/amd/display/dc/dc.h | 12 ----------- 2 files changed, 38 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6d56cb0c29cc..b5ba822df55e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1515,32 +1515,6 @@ const struct audio **dc_get_audios(struct dc *dc) return (const struct audio **)core_dc->res_pool->audios; } -void dc_flip_surface_addrs( - struct dc *dc, - const struct dc_surface *const surfaces[], - struct dc_flip_addrs flip_addrs[], - uint32_t count) -{ - struct core_dc *core_dc = DC_TO_CORE(dc); - int i, j; - - for (i = 0; i < count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); - - surface->public.address = flip_addrs[i].address; - surface->public.flip_immediate = flip_addrs[i].flip_immediate; - - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; - - if (pipe_ctx->surface != surface) - continue; - - core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - } - } -} - enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0610805cdb05..f2efa32fe4ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -393,18 +393,6 @@ struct dc_flip_addrs { /* TODO: add flip duration for FreeSync */ }; -/* - * Optimized flip address update function. - * - * After this call: - * Surface addresses and flip attributes are programmed. - * Surface flip occur at next configured time (h_sync or v_sync flip) - */ -void dc_flip_surface_addrs(struct dc *dc, - const struct dc_surface *const surfaces[], - struct dc_flip_addrs flip_addrs[], - uint32_t count); - /* * Set up surface attributes and associate to a stream * The surfaces parameter is an absolute set of all surface active for the stream. -- GitLab From d3ec0562085918ba889af3d565b4104adcd4947f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 16 May 2017 09:55:20 -0400 Subject: [PATCH 0468/2898] drm/amd/display: Fix dcn10 cursor set position hang Calling dcn10_cursor_set_position() before dcn10_cursor_set_attributes() with invalid (0-value) attributes can cause the ASIC to hang. This fix checks that address.quadpart is non-zero within set_position before calling set_attributes. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 3062b7de4fe2..082c98c11293 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -614,6 +614,16 @@ static void dcn10_cursor_set_position( uint32_t cur_en = pos->enable ? 1 : 0; uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; + /* + * Guard aganst cursor_set_position() from being called with invalid + * attributes + * + * TODO: Look at combining cursor_set_position() and + * cursor_set_attributes() into cursor_update() + */ + if (ippn10->curs_attr.address.quad_part == 0) + return; + dst_x_offset *= param->ref_clk_khz; dst_x_offset /= param->pixel_clk_khz; -- GitLab From 1185da086903e87259fd54c20c04098bcefa9da3 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 17 May 2017 10:59:53 -0400 Subject: [PATCH 0469/2898] drm/amd/display: add missing GRPH_UPDATE_LOCK field macro for dce_mem_input Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 55481f5adcdf..9d083cd79b4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -158,6 +158,7 @@ struct dce_mem_input_registers { SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS, GRPH_PRIMARY_SURFACE_ADDRESS, mask_sh),\ SFB(blk, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, mask_sh),\ + SFB(blk, GRPH_UPDATE, GRPH_UPDATE_LOCK, mask_sh),\ SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh) #define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ -- GitLab From bdc79f8e5dfaeb83dd3a1b609aff25712250cc1e Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 15 May 2017 18:55:38 -0400 Subject: [PATCH 0470/2898] drm/amd/display: Unify loop for surface update and page flip. Remove extra loop we have for page flips and do flips in same loop we do for surface create/update. Add documentation for synchronization between commits on different crtcs. Rename function to have DM prefix. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 88 +++++++++---------- 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 7d989b6738e4..d6ea2d5726dd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2381,10 +2381,11 @@ static void amdgpu_dm_do_flip( acrtc->crtc_id); } -void dc_commit_surfaces(struct drm_atomic_state *state, +static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_device *dev, struct amdgpu_display_manager *dm, - struct drm_crtc *pcrtc) + struct drm_crtc *pcrtc, + bool *wait_for_vblank) { uint32_t i; struct drm_plane *plane; @@ -2397,10 +2398,11 @@ void dc_commit_surfaces(struct drm_atomic_state *state, for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; + struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *dm_state = NULL; - struct amdgpu_crtc *acrtc_attach; + enum dm_commit_action action; bool pflip_needed; @@ -2409,13 +2411,13 @@ void dc_commit_surfaces(struct drm_atomic_state *state, action = get_dm_commit_action(crtc->state); - /* Surfaces are created under two scenarios: - * 1. This commit is not a page flip. - * 2. This commit is a page flip, and streams are created. + /* + * TODO - TO decide if it's a flip or surface update + * stop relying on allow_modeset flag and query DC + * using dc_check_update_surfaces_for_stream. */ pflip_needed = !state->allow_modeset; - if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON - || action == DM_COMMIT_ACTION_SET) { + if (!pflip_needed) { list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -2445,11 +2447,23 @@ void dc_commit_surfaces(struct drm_atomic_state *state, if (crtc == pcrtc) { add_surface(dm->dc, crtc, plane, &dc_surfaces_constructed[planes_count]); - acrtc_attach = to_amdgpu_crtc(crtc); dc_stream_attach = acrtc_attach->stream; planes_count++; } + } else if (crtc->state->planes_changed) { + *wait_for_vblank = + acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + false : true; + + amdgpu_dm_do_flip( + crtc, + fb, + drm_crtc_vblank_count(crtc) + *wait_for_vblank); + + /*clean up the flags for next usage*/ + acrtc_attach->flip_flags = 0; } + } if (planes_count) { @@ -2471,8 +2485,6 @@ void amdgpu_dm_atomic_commit_tail( struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; - struct drm_plane *plane; - struct drm_plane_state *old_plane_state; uint32_t i, j; uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; @@ -2637,7 +2649,7 @@ void amdgpu_dm_atomic_commit_tail( /* update planes when needed per crtc*/ for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) - dc_commit_surfaces(state, dev, dm, pcrtc); + amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); for (i = 0; i < new_crtcs_count; i++) { /* @@ -2651,34 +2663,6 @@ void amdgpu_dm_atomic_commit_tail( manage_dm_interrupts(adev, acrtc, true); dm_crtc_cursor_reset(&acrtc->base); - - } - - for_each_plane_in_state(state, plane, old_plane_state, i) { - struct drm_plane_state *plane_state = plane->state; - struct drm_crtc *crtc = plane_state->crtc; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_framebuffer *fb = plane_state->fb; - bool pflip_needed; - - if (!fb || !crtc || !crtc->state->planes_changed || - !crtc->state->active) - continue; - pflip_needed = !state->allow_modeset; - - if (pflip_needed) { - wait_for_vblank = - acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? - false : true; - - amdgpu_dm_do_flip( - crtc, - fb, - drm_crtc_vblank_count(crtc) + wait_for_vblank); - - /*clean up the flags for next usage*/ - acrtc->flip_flags = 0; - } } @@ -2901,7 +2885,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; bool need_to_validate = false; struct validate_context *context; - bool wait_4_prev_commits = false; + /* + * This bool will be set for true for any modeset/reset + * or surface update which implies non fast surfae update. + */ + bool wait_for_prev_commits = false; ret = drm_atomic_helper_check(dev, state); @@ -2978,7 +2966,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; - wait_4_prev_commits = true; + wait_for_prev_commits = true; break; } @@ -3024,7 +3012,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; - wait_4_prev_commits = true; + wait_for_prev_commits = true; break; } @@ -3036,7 +3024,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, set, set_count, acrtc->stream); - wait_4_prev_commits = true; + wait_for_prev_commits = true; } break; } @@ -3132,8 +3120,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (need_to_validate == false || set_count == 0 || context) { ret = 0; - - if (wait_4_prev_commits) { + /* + * For full updates case when + * removing/adding/updateding streams on once CRTC while flipping + * on another CRTC, + * Adding all current active CRTC's states to the atomic commit in + * amdgpu_dm_atomic_check will guarantee that any such full update commit + * will wait for completion of any outstanding flip using DRMs + * synchronization events. + */ + if (wait_for_prev_commits) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_crtc_state *crtc_state; -- GitLab From 1f7f3aec125724da30ff1c2f2d359340feb0d9e1 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 16 May 2017 21:27:01 -0400 Subject: [PATCH 0471/2898] drm/amd/display: read VM settings from MMHUB instead of GC, as after GFX off, GC can be power gated any time Signed-off-by: Tony Cheng Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_mem_input.h | 24 +++++++++---------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 14 +++++------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 4a5eb6ae3524..20bd0f5d7b17 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -130,18 +130,18 @@ SR(DCHUBBUB_ARB_SAT_LEVEL),\ SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ /* todo: get these from GVM instead of reading registers ourselves */\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ - GC_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ - GC_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ - GC_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ - GC_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ - GC_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ - GC_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ - GC_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ + MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ + MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) struct dcn_mi_registers { uint32_t DCHUBP_CNTL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4e5b225a2a08..7fdc5860857b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -122,15 +122,15 @@ enum dcn10_clk_src_array_id { .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ mm ## reg_name -/* GC */ -#define GC_BASE_INNER(seg) \ - GC_BASE__INST0_SEG ## seg +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg -#define GC_BASE(seg) \ - GC_BASE_INNER(seg) +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) -#define GC_SR(reg_name)\ - .reg_name = GC_BASE(mm ## reg_name ## _BASE_IDX) + \ +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ mm ## reg_name /* macros to expend register list macro defined in HW object header file -- GitLab From ccaf31ec714b596d1edb92b1ed4ccc4abf1f645c Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 17 May 2017 12:07:30 -0400 Subject: [PATCH 0472/2898] drm/amd/display: Fix 5th display lightup on Vega10 - fixing bug in calculation of reg offset for D5VGA_CONTROL Signed-off-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 245356e72b36..dc8eeac6ac96 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -410,7 +410,7 @@ void dce120_timing_generator_disable_vga(struct timing_generator *tg) break; case CONTROLLER_ID_D4: addr = mmD1VGA_CONTROL; - offset = mmD1VGA_CONTROL - mmD1VGA_CONTROL; + offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D5: addr = mmD6VGA_CONTROL; -- GitLab From 430ef426bc43b59a7444c08d664e24a7cf89710e Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 17 May 2017 16:05:40 -0400 Subject: [PATCH 0473/2898] drm/amd/display: make dc_get_validate_context re-entrant Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 44 ++----------------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 30 ++++++------- .../amd/display/dc/dce100/dce100_resource.c | 22 +++++----- .../amd/display/dc/dce110/dce110_resource.c | 22 +++++----- .../amd/display/dc/dce112/dce112_resource.c | 27 +++++++----- .../amd/display/dc/dce112/dce112_resource.h | 3 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 22 +++++----- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 24 +++++----- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 9 ++-- 10 files changed, 92 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b5ba822df55e..0aafcc088284 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -653,40 +653,6 @@ void dc_destroy(struct dc **dc) *dc = NULL; } -static bool is_validation_required( - const struct core_dc *dc, - const struct dc_validation_set set[], - int set_count) -{ - const struct validate_context *context = dc->current_context; - int i, j; - - if (context->stream_count != set_count) - return true; - - for (i = 0; i < set_count; i++) { - - if (set[i].surface_count != context->stream_status[i].surface_count) - return true; - if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i])) - return true; - - for (j = 0; j < set[i].surface_count; j++) { - struct dc_surface temp_surf = { 0 }; - - temp_surf = *context->stream_status[i].surfaces[j]; - temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; - temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; - temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; - - if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0) - return true; - } - } - - return false; -} - struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], @@ -700,13 +666,8 @@ struct validate_context *dc_get_validate_context( if(context == NULL) goto context_alloc_fail; - if (!is_validation_required(core_dc, set, set_count)) { - dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); - return context; - } - result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, set_count, context); + core_dc, set, set_count, context, NULL); context_alloc_fail: if (result != DC_OK) { @@ -903,7 +864,8 @@ bool dc_commit_streams( if (context == NULL) goto context_alloc_fail; - result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, stream_count, context); + result = core_dc->res_pool->funcs->validate_with_context( + core_dc, set, stream_count, context, core_dc->current_context); if (result != DC_OK){ dm_logger_write(core_dc->ctx->logger, LOG_ERROR, "%s: Context validation failed! dc_status:%d\n", diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7ca03d1ad163..ec5045734378 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1148,7 +1148,7 @@ bool resource_validate_attach_surfaces( int i, j; for (i = 0; i < set_count; i++) { - for (j = 0; j < old_context->stream_count; j++) + for (j = 0; old_context && j < old_context->stream_count; j++) if (is_stream_unchanged( old_context->streams[j], context->streams[i])) { @@ -1387,9 +1387,7 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) return normalized_pix_clk; } -static void calculate_phy_pix_clks( - const struct core_dc *dc, - struct validate_context *context) +static void calculate_phy_pix_clks(struct validate_context *context) { int i; @@ -1410,21 +1408,22 @@ static void calculate_phy_pix_clks( enum dc_status resource_map_pool_resources( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { const struct resource_pool *pool = dc->res_pool; int i, j; - calculate_phy_pix_clks(dc, context); + calculate_phy_pix_clks(context); - for (i = 0; i < context->stream_count; i++) { + for (i = 0; old_context && i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - if (!resource_is_stream_unchanged(dc->current_context, stream)) { - if (stream != NULL && dc->current_context->streams[i] != NULL) { + if (!resource_is_stream_unchanged(old_context, stream)) { + if (stream != NULL && old_context->streams[i] != NULL) { stream->bit_depth_params = - dc->current_context->streams[i]->bit_depth_params; - stream->clamping = dc->current_context->streams[i]->clamping; + old_context->streams[i]->bit_depth_params; + stream->clamping = old_context->streams[i]->clamping; continue; } } @@ -1434,7 +1433,7 @@ enum dc_status resource_map_pool_resources( struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; const struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[j]; + &old_context->res_ctx.pipe_ctx[j]; if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) continue; @@ -1475,7 +1474,7 @@ enum dc_status resource_map_pool_resources( struct pipe_ctx *pipe_ctx = NULL; int pipe_idx = -1; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; /* acquire new resources */ pipe_idx = acquire_first_free_pipe( @@ -2203,7 +2202,8 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) enum dc_status resource_map_clock_resources( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { int i, j; const struct resource_pool *pool = dc->res_pool; @@ -2212,7 +2212,7 @@ enum dc_status resource_map_clock_resources( for (i = 0; i < context->stream_count; i++) { const struct core_stream *stream = context->streams[i]; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 8f1fe95dd76c..716f664f40ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -653,7 +653,8 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -662,7 +663,7 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -740,7 +741,8 @@ enum dc_status dce100_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -755,19 +757,19 @@ enum dc_status dce100_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, old_context); if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) { + old_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -790,13 +792,13 @@ enum dc_status dce100_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 3ed5b9445535..45759b9f15e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -769,7 +769,8 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -778,7 +779,7 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -943,7 +944,8 @@ enum dc_status dce110_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -958,19 +960,19 @@ enum dc_status dce110_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, old_context); if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) { + old_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -993,13 +995,13 @@ enum dc_status dce110_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index f405d6eecaa5..80f067343a91 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -722,7 +722,8 @@ static struct clock_source *find_matching_pll( static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -731,7 +732,7 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -854,7 +855,8 @@ bool dce112_validate_bandwidth( enum dc_status resource_map_phy_clock_resources( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { uint8_t i, j; @@ -862,7 +864,7 @@ enum dc_status resource_map_phy_clock_resources( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -922,7 +924,8 @@ enum dc_status dce112_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -937,19 +940,19 @@ enum dc_status dce112_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context); + result = resource_map_phy_clock_resources(dc, context, old_context); if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) { + old_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -972,13 +975,13 @@ enum dc_status dce112_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context); + result = resource_map_phy_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index dc842aace766..c6c0bbac5335 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -39,7 +39,8 @@ enum dc_status dce112_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 095e437ce112..5861b3fdf7d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -669,7 +669,8 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -678,7 +679,7 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) + if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; for (j = 0; j < MAX_PIPES; j++) { @@ -757,7 +758,8 @@ enum dc_status dce80_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -772,19 +774,19 @@ enum dc_status dce80_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, old_context); if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) { + old_context, context, dc->res_pool)) { DC_ERROR("Failed to attach surface to stream!\n"); return DC_FAIL_ATTACH_SURFACES; } if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -806,13 +808,13 @@ enum dc_status dce80_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_clock_resources(dc, context); + result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 7fdc5860857b..94cd7a9b0b19 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -853,7 +853,8 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) static enum dc_status validate_mapped_resource( const struct core_dc *dc, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status status = DC_OK; uint8_t i, j; @@ -862,8 +863,8 @@ static enum dc_status validate_mapped_resource( struct core_stream *stream = context->streams[i]; struct core_link *link = stream->sink->link; - if (resource_is_stream_unchanged(dc->current_context, stream)) { - if (stream != NULL && dc->current_context->streams[i] != NULL) { + if (old_context && resource_is_stream_unchanged(old_context, stream)) { + if (stream != NULL && old_context->streams[i] != NULL) { /* todo: shouldn't have to copy missing parameter here */ resource_build_bit_depth_reduction_params(stream, &stream->bit_depth_params); @@ -920,7 +921,8 @@ enum dc_status dcn10_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct validate_context *context, + struct validate_context *old_context) { enum dc_status result = DC_OK; int i; @@ -934,20 +936,20 @@ enum dc_status dcn10_validate_with_context( context->stream_count++; } - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, old_context); if (result != DC_OK) return result; - result = resource_map_phy_clock_resources(dc, context); + result = resource_map_phy_clock_resources(dc, context, old_context); if (result != DC_OK) return result; - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, old_context); if (result != DC_OK) return result; if (!resource_validate_attach_surfaces(set, set_count, - dc->current_context, context, dc->res_pool)) + old_context, context, dc->res_pool)) return DC_FAIL_ATTACH_SURFACES; result = resource_build_scaling_params_for_context(dc, context); @@ -971,13 +973,13 @@ enum dc_status dcn10_validate_guaranteed( dc_stream_retain(&context->streams[0]->public); context->stream_count++; - result = resource_map_pool_resources(dc, context); + result = resource_map_pool_resources(dc, context, NULL); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context); + result = resource_map_phy_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context); + result = validate_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 46bd0318e6be..d8a378dabb43 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -203,7 +203,8 @@ struct resource_funcs { const struct core_dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); enum dc_status (*validate_guaranteed)( const struct core_dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 4e07b9fea669..7cac24d4ae86 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -80,7 +80,8 @@ void dc_destroy_resource_pool(struct core_dc *dc); enum dc_status resource_map_pool_resources( const struct core_dc *dc, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); @@ -150,11 +151,13 @@ void resource_validate_ctx_update_pointer_after_copy( enum dc_status resource_map_clock_resources( const struct core_dc *dc, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); enum dc_status resource_map_phy_clock_resources( const struct core_dc *dc, - struct validate_context *context); + struct validate_context *context, + struct validate_context *old_context); bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, -- GitLab From afc8935ef0fc04c87cd7e7749ff28c32be4f712a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 17 May 2017 16:56:56 -0400 Subject: [PATCH 0474/2898] drm/amd/display: revert dc_get_validate_context re-entrancy fix Apply dc_get_validate_context re-entrancy fix to dc_validate_resources instead Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 71 +++++++++++++++++++++--- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0aafcc088284..773f0efc449b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -653,6 +653,40 @@ void dc_destroy(struct dc **dc) *dc = NULL; } +static bool is_validation_required( + const struct core_dc *dc, + const struct dc_validation_set set[], + int set_count) +{ + const struct validate_context *context = dc->current_context; + int i, j; + + if (context->stream_count != set_count) + return true; + + for (i = 0; i < set_count; i++) { + + if (set[i].surface_count != context->stream_status[i].surface_count) + return true; + if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i])) + return true; + + for (j = 0; j < set[i].surface_count; j++) { + struct dc_surface temp_surf = { 0 }; + + temp_surf = *context->stream_status[i].surfaces[j]; + temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; + temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; + temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; + + if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0) + return true; + } + } + + return false; +} + struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], @@ -663,11 +697,16 @@ struct validate_context *dc_get_validate_context( struct validate_context *context; context = dm_alloc(sizeof(struct validate_context)); - if(context == NULL) + if (context == NULL) goto context_alloc_fail; + if (!is_validation_required(core_dc, set, set_count)) { + dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); + return context; + } + result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, set_count, context, NULL); + core_dc, set, set_count, context, core_dc->current_context); context_alloc_fail: if (result != DC_OK) { @@ -690,16 +729,30 @@ bool dc_validate_resources( const struct dc_validation_set set[], uint8_t set_count) { - struct validate_context *ctx; + struct core_dc *core_dc = DC_TO_CORE(dc); + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; - ctx = dc_get_validate_context(dc, set, set_count); - if (ctx) { - dc_resource_validate_ctx_destruct(ctx); - dm_free(ctx); - return true; + context = dm_alloc(sizeof(struct validate_context)); + if (context == NULL) + goto context_alloc_fail; + + result = core_dc->res_pool->funcs->validate_with_context( + core_dc, set, set_count, context, NULL); + +context_alloc_fail: + if (result != DC_OK) { + dm_logger_write(core_dc->ctx->logger, LOG_WARNING, + "%s:resource validation failed, dc_status:%d\n", + __func__, + result); } - return false; + dc_resource_validate_ctx_destruct(context); + dm_free(context); + context = NULL; + + return result == DC_OK; } bool dc_validate_guaranteed( -- GitLab From 98489c026edc48d9c783f783cc82f2e8811e0ee4 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 16 May 2017 13:52:28 -0400 Subject: [PATCH 0475/2898] drm/amd/display: Refactor use_lut() from dce110 to dce use_lut() checks if the input surface's pixel format is compatible with a 256 entry LUT. This function can be used across different versions and not just dce11. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 12 ++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 ++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 17 ++--------------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 34c18712970c..cc3178acfc54 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -191,3 +191,15 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, clk_src->id, tg_inst); } } + +/* Only use LUT for 8 bit formats */ +bool dce_use_lut(const struct core_surface *surface) +{ + switch (surface->public.format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + return true; + default: + return false; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index dd13f47b6446..112f9c85c142 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -256,4 +256,6 @@ void dce_clock_gating_power_up(struct dce_hwseq *hws, void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst); + +bool dce_use_lut(const struct core_surface *surface); #endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 20ad1cb263db..65c691569eb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -28,10 +28,10 @@ #include "core_types.h" #include "core_status.h" #include "resource.h" -#include "hw_sequencer.h" #include "dm_helpers.h" #include "dce110_hw_sequencer.h" #include "dce110_timing_generator.h" +#include "dce/dce_hwseq.h" #include "bios/bios_parser_helper.h" #include "timing_generator.h" @@ -233,19 +233,6 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, } } - -/* Only use LUT for 8 bit formats */ -static bool use_lut(const struct core_surface *surface) -{ - switch (surface->public.format) { - case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: - return true; - default: - return false; - } -} - static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) @@ -264,7 +251,7 @@ static bool dce110_set_input_transfer_func( build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (surface->public.gamma_correction && use_lut(surface)) + if (surface->public.gamma_correction && dce_use_lut(surface)) ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); if (tf == NULL) { -- GitLab From 5aff86c1b3259f1443e0b35b74eb6dfd5b35791b Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 16 May 2017 16:07:30 -0400 Subject: [PATCH 0476/2898] drm/amd/display: Implement input gamma LUT 1. Implemented dcn10_ipp_program_input_lut(), following the existing interface. 2. Added missing registers as needed 3. Change to REG_GET for *ram_select() funcs. 4. Removed gamma table init from DiagsDM::make_surface() for resolving CRC errors. Reason: Legacy LUT will be deprecated soon for Raven in favor of degamma/regamma. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 82 ++++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 22 +++++ 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 28b47bed72cf..62a77f48d437 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -29,9 +29,9 @@ #include "core_types.h" #include "core_status.h" #include "resource.h" -#include "hw_sequencer.h" #include "dcn10_hw_sequencer.h" #include "dce110/dce110_hw_sequencer.h" +#include "dce/dce_hwseq.h" #include "abm.h" #include "dcn10/dcn10_transform.h" @@ -952,6 +952,10 @@ static bool dcn10_set_input_transfer_func( if (surface->public.in_transfer_func) tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + if (surface->public.gamma_correction && dce_use_lut(surface)) + ipp->funcs->ipp_program_input_lut(ipp, + surface->public.gamma_correction); + if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); else if (tf->public.type == TF_TYPE_PREDEFINED) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 082c98c11293..1e7a55d9e9ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -814,7 +814,9 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, uint32_t status_reg = 0; struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - status_reg = (REG_READ(CM_IGAM_LUT_RW_CONTROL) & 0x0F00) >>16; + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + if (status_reg == 9) { *ram_a_inuse = true; ret = true; @@ -825,6 +827,28 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, return ret; } +static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, + bool *ram_a_inuse) +{ + bool in_use = false; + uint32_t status_reg = 0; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + + // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB + if (status_reg == 1 || status_reg == 3 || status_reg == 4) { + *ram_a_inuse = true; + in_use = true; + // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB + } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) { + *ram_a_inuse = false; + in_use = true; + } + return in_use; +} + static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, bool use_ram_a) { @@ -855,6 +879,61 @@ static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, dcn10_degamma_ram_select(ipp, !is_ram_a); } +/* + * Input gamma LUT currently supports 256 values only. This means input color + * can have a maximum of 8 bits per channel (= 256 possible values) in order to + * have a one-to-one mapping with the LUT. Truncation will occur with color + * values greater than 8 bits. + * + * In the future, this function should support additional input gamma methods, + * such as piecewise linear mapping, and input gamma bypass. + */ +void dcn10_ipp_program_input_lut( + struct input_pixel_processor *ipp, + const struct dc_gamma *gamma) +{ + int i; + struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); + bool rama_occupied = false; + uint32_t ram_num; + // Power on LUT memory. + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); + dcn10_ipp_enable_cm_block(ipp); + // Determine whether to use RAM A or RAM B + dcn10_ingamma_ram_inuse(ipp, &rama_occupied); + if (!rama_occupied) + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); + else + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1); + // RW mode is 256-entry LUT + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0); + // IGAM Input format should be 8 bits per channel. + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0); + // Do not mask any R,G,B values + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7); + // LUT-256, unsigned, integer, new u0.12 format + REG_UPDATE_3( + CM_IGAM_CONTROL, + CM_IGAM_LUT_FORMAT_R, 3, + CM_IGAM_LUT_FORMAT_G, 3, + CM_IGAM_LUT_FORMAT_B, 3); + // Start at index 0 of IGAM LUT + REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); + for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->red[i]); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->green[i]); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + gamma->blue[i]); + } + // Power off LUT memory + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); + // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2); + REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num); +} + /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -869,6 +948,7 @@ static const struct ipp_funcs dcn10_ipp_funcs = { .ipp_cursor_set_attributes = dcn10_cursor_set_attributes, .ipp_cursor_set_position = dcn10_cursor_set_position, .ipp_set_degamma = dcn10_ipp_set_degamma, + .ipp_program_input_lut = dcn10_ipp_program_input_lut, .ipp_full_bypass = dcn10_ipp_full_bypass, .ipp_setup = dcn10_ipp_cnv_setup, .ipp_program_degamma_pwl = dcn10_ipp_set_degamma_pwl, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index a4ea4e774c72..511993519740 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -87,6 +87,8 @@ SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ + SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ + SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_DGAM_LUT_INDEX, CM, id), \ SRI(CM_DGAM_LUT_DATA, CM, id), \ @@ -238,7 +240,13 @@ IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ @@ -251,6 +259,9 @@ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ @@ -404,7 +415,16 @@ type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ type SHARED_MEM_PWR_DIS; \ + type CM_IGAM_LUT_FORMAT_R; \ + type CM_IGAM_LUT_FORMAT_G; \ + type CM_IGAM_LUT_FORMAT_B; \ type CM_IGAM_LUT_HOST_EN; \ + type CM_IGAM_LUT_RW_INDEX; \ + type CM_IGAM_LUT_RW_MODE; \ + type CM_IGAM_LUT_WRITE_EN_MASK; \ + type CM_IGAM_LUT_SEL; \ + type CM_IGAM_LUT_SEQ_COLOR; \ + type CM_IGAM_DGAM_CONFIG_STATUS; \ type CM_DGAM_LUT_WRITE_EN_MASK; \ type CM_DGAM_LUT_WRITE_SEL; \ type CM_DGAM_LUT_INDEX; \ @@ -507,6 +527,8 @@ struct dcn10_ipp_registers { uint32_t CM_DGAM_RAMA_REGION_14_15; uint32_t CM_MEM_PWR_CTRL; uint32_t CM_IGAM_LUT_RW_CONTROL; + uint32_t CM_IGAM_LUT_RW_INDEX; + uint32_t CM_IGAM_LUT_SEQ_COLOR; uint32_t CM_DGAM_LUT_WRITE_EN_MASK; uint32_t CM_DGAM_LUT_INDEX; uint32_t CM_DGAM_LUT_DATA; -- GitLab From 7b9454f51ec1e04f7842a9412df568f98371b01c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 17 May 2017 18:05:36 -0400 Subject: [PATCH 0477/2898] drm/amd/display: Add missed wait_for_prev_commits. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index d6ea2d5726dd..b76f0f7e5594 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -3111,6 +3111,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, surface); need_to_validate = true; + wait_for_prev_commits = true; } } } -- GitLab From 0a5c357a85e99eae6b1914272bc2cf8f49cf511b Mon Sep 17 00:00:00 2001 From: Ayyappa Chandolu Date: Fri, 12 May 2017 17:05:55 +0530 Subject: [PATCH 0478/2898] drm/amd/display: Fix ASSR enablement on DP to EDP converter ASSR mode is not enable when we connect eDP panel via DP to eDP converter. connector_signal is coming as SIGNAL_TYPE_DISPLAY_PORT. Present code ignoring panel_mode_edp for SIGNAL_TYPE_DISPLAY_PORT. Added checking panel_mode_edp for all signals. Signed-off-by: Ayyappa Chandolu Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 316df150c1d9..4f46ff14fb69 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -203,10 +203,10 @@ enum dp_panel_mode dp_get_panel_mode(struct core_link *link) default: break; } + } - if (link->dpcd_caps.panel_mode_edp) { - return DP_PANEL_MODE_EDP; - } + if (link->dpcd_caps.panel_mode_edp) { + return DP_PANEL_MODE_EDP; } return DP_PANEL_MODE_DEFAULT; -- GitLab From a4b0a5b84827b1bceb99c3c2aa354073cc5bfb53 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:00 -0400 Subject: [PATCH 0479/2898] drm/amd/display: Tidy up dce120_timing_generator_enable_advanced_request() Simplify the function by removing identical looking code blocks. Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../dc/dce120/dce120_timing_generator.c | 37 ++++++------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index dc8eeac6ac96..13cc0d49e007 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -669,36 +669,23 @@ void dce120_timing_generator_enable_advanced_request( mmCRTC0_CRTC_START_LINE_CONTROL, tg110->offsets.crtc); - - if (enable) { - set_reg_field_value( - value, - 0, - CRTC0_CRTC_START_LINE_CONTROL, - CRTC_LEGACY_REQUESTOR_EN); - } else { - set_reg_field_value( - value, - 1, - CRTC0_CRTC_START_LINE_CONTROL, - CRTC_LEGACY_REQUESTOR_EN); - } + set_reg_field_value( + value, + enable ? 0 : 1, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); /* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines) */ if (v_sync_width_and_b_porch > 10) - set_reg_field_value( - value, - 10, - CRTC0_CRTC_START_LINE_CONTROL, - CRTC_ADVANCED_START_LINE_POSITION); - else - set_reg_field_value( - value, - v_sync_width_and_b_porch, - CRTC0_CRTC_START_LINE_CONTROL, - CRTC_ADVANCED_START_LINE_POSITION); + v_sync_width_and_b_porch = 10; + + set_reg_field_value( + value, + v_sync_width_and_b_porch, + CRTC0_CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_START_LINE_CONTROL, -- GitLab From 78178dea7a92a611262edad73a548ffe7087a347 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:01 -0400 Subject: [PATCH 0480/2898] drm/amd/display: Fix indentation in dce120_tg_program_timing() Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 13cc0d49e007..1c25dc66ff4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -733,9 +733,9 @@ void dce120_tg_program_timing(struct timing_generator *tg, bool use_vbios) { if (use_vbios) - dce110_timing_generator_program_timing_generator(tg, timing); - else - dce120_timing_generator_program_blanking(tg, timing); + dce110_timing_generator_program_timing_generator(tg, timing); + else + dce120_timing_generator_program_blanking(tg, timing); } bool dce120_tg_is_blanked(struct timing_generator *tg) -- GitLab From 7b7d68659e3007a30d04d51e1c8bbd1fa8b6de3e Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:02 -0400 Subject: [PATCH 0481/2898] drm/amd/display: Make dce120_tg_is_blanked() more legible Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce120/dce120_timing_generator.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 1c25dc66ff4f..1e2843e5d97e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -746,15 +746,14 @@ bool dce120_tg_is_blanked(struct timing_generator *tg) mmCRTC0_CRTC_BLANK_CONTROL, tg110->offsets.crtc); - if ( - get_reg_field_value( - value, - CRTC0_CRTC_BLANK_CONTROL, - CRTC_BLANK_DATA_EN) == 1 && - get_reg_field_value( - value, - CRTC0_CRTC_BLANK_CONTROL, - CRTC_CURRENT_BLANK_STATE) == 1) + if (get_reg_field_value( + value, + CRTC0_CRTC_BLANK_CONTROL, + CRTC_BLANK_DATA_EN) == 1 && + get_reg_field_value( + value, + CRTC0_CRTC_BLANK_CONTROL, + CRTC_CURRENT_BLANK_STATE) == 1) return true; return false; -- GitLab From cedaf3073a33a95e276371783b20a14e208e184c Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:03 -0400 Subject: [PATCH 0482/2898] drm/amd/display: Clean up indentation in dce120_tg_set_blank() Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce120/dce120_timing_generator.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 1e2843e5d97e..c208196864ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -768,17 +768,11 @@ void dce120_tg_set_blank(struct timing_generator *tg, CRTC0_CRTC_DOUBLE_BUFFER_CONTROL, CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 0); - if (enable_blanking) { - CRTC_REG_SET( - CRTC0_CRTC_BLANK_CONTROL, - CRTC_BLANK_DATA_EN, 1); - - } else - dm_write_reg_soc15( - tg->ctx, - mmCRTC0_CRTC_BLANK_CONTROL, - tg110->offsets.crtc, - 0); + if (enable_blanking) + CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1); + else + dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL, + tg110->offsets.crtc, 0); } bool dce120_tg_validate_timing(struct timing_generator *tg, -- GitLab From 76fd8eb8e2282c695c43683802772caa187bf41b Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:04 -0400 Subject: [PATCH 0483/2898] drm/amd/display: Tidy up dce120_clock_source_create() Also change sizeof to be automatic based on type declaration. Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 1276dabfb208..ec485353ea4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -398,13 +398,13 @@ struct clock_source *dce120_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + dm_alloc(sizeof(*clk_src)); if (!clk_src) return NULL; if (dce110_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { + regs, &cs_shift, &cs_mask)) { clk_src->base.dp_clk_src = dp_clk_src; return &clk_src->base; } -- GitLab From 0b3454b7c49bfc6aa7a1096d1aa9d059201a73a7 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 16 May 2017 10:22:05 -0400 Subject: [PATCH 0484/2898] drm/amd/display: Tidy up mem_input_program_surface_flip_and_addr() Signed-off-by: Tom St Denis Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_mem_input.c | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 718688c41f7b..673371e5f9f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -625,18 +625,12 @@ static bool dce_mi_program_surface_flip_and_addr( * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 */ - REG_UPDATE(GRPH_UPDATE, - GRPH_UPDATE_LOCK, 1); - - if (flip_immediate) { - REG_UPDATE_2(GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, - GRPH_SURFACE_UPDATE_H_RETRACE_EN, 1); - } else { - REG_UPDATE_2(GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, - GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0); - } + REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1); + + REG_UPDATE_2( + GRPH_FLIP_CONTROL, + GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, + GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0); switch (address->type) { case PLN_ADDR_TYPE_GRAPHICS: @@ -645,8 +639,8 @@ static bool dce_mi_program_surface_flip_and_addr( program_pri_addr(dce_mi, address->grph.addr); break; case PLN_ADDR_TYPE_GRPH_STEREO: - if (address->grph_stereo.left_addr.quad_part == 0 - || address->grph_stereo.right_addr.quad_part == 0) + if (address->grph_stereo.left_addr.quad_part == 0 || + address->grph_stereo.right_addr.quad_part == 0) break; program_pri_addr(dce_mi, address->grph_stereo.left_addr); program_sec_addr(dce_mi, address->grph_stereo.right_addr); @@ -662,8 +656,7 @@ static bool dce_mi_program_surface_flip_and_addr( if (flip_immediate) mem_input->current_address = *address; - REG_UPDATE(GRPH_UPDATE, - GRPH_UPDATE_LOCK, 0); + REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 0); return true; } -- GitLab From f1000642e48166322194529a6d0f2452934acf2a Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 18 May 2017 11:03:17 -0400 Subject: [PATCH 0485/2898] drm/amd/display: Query for update plane type. Use DC interface to query for plane update type so in case of FULL update you flush any outstanding commits. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b76f0f7e5594..a5b7c054d853 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2867,6 +2867,61 @@ static uint32_t remove_from_val_sets( return set_count; } + +static enum surface_update_type amdgpu_dm_check_surfaces_update_type( + struct dc *dc, + const struct dc_surface **new_surfaces, + uint8_t new_surface_count, + const struct dc_stream *dc_stream) +{ + struct dc_surface_update srf_updates[MAX_SURFACES]; + struct dc_flip_addrs flip_addr[MAX_SURFACES]; + struct dc_plane_info plane_info[MAX_SURFACES]; + struct dc_scaling_info scaling_info[MAX_SURFACES]; + int i; + const struct dc_stream_status *stream_status = + dc_stream_get_status(dc_stream); + enum surface_update_type update_type; + + ASSERT(stream_status); + + + memset(srf_updates, 0, sizeof(srf_updates)); + memset(flip_addr, 0, sizeof(flip_addr)); + memset(plane_info, 0, sizeof(plane_info)); + memset(scaling_info, 0, sizeof(scaling_info)); + + for (i = 0; i < new_surface_count; i++) { + srf_updates[i].surface = new_surfaces[i]; + srf_updates[i].gamma = + (struct dc_gamma *)new_surfaces[i]->gamma_correction; + flip_addr[i].address = new_surfaces[i]->address; + flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; + plane_info[i].color_space = new_surfaces[i]->color_space; + plane_info[i].format = new_surfaces[i]->format; + plane_info[i].plane_size = new_surfaces[i]->plane_size; + plane_info[i].rotation = new_surfaces[i]->rotation; + plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror; + plane_info[i].stereo_format = new_surfaces[i]->stereo_format; + plane_info[i].tiling_info = new_surfaces[i]->tiling_info; + plane_info[i].visible = new_surfaces[i]->visible; + plane_info[i].dcc = new_surfaces[i]->dcc; + scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; + scaling_info[i].src_rect = new_surfaces[i]->src_rect; + scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; + scaling_info[i].clip_rect = new_surfaces[i]->clip_rect; + + srf_updates[i].flip_addr = &flip_addr[i]; + srf_updates[i].plane_info = &plane_info[i]; + srf_updates[i].scaling_info = &scaling_info[i]; + } + + update_type = dc_check_update_surfaces_for_stream( + dc, srf_updates, new_surface_count, NULL, stream_status); + + return update_type; +} + int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { @@ -3111,13 +3166,25 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, surface); need_to_validate = true; - wait_for_prev_commits = true; } } } context = dc_get_validate_context(dc, set, set_count); + for (i = 0; i < set_count; i++) { + for (j = 0; j < set[i].surface_count; j++) { + if (amdgpu_dm_check_surfaces_update_type( + dc, + set[i].surfaces, + set[i].surface_count, + set[i].stream) > UPDATE_TYPE_MED) { + wait_for_prev_commits = true; + break; + } + } + } + if (need_to_validate == false || set_count == 0 || context) { ret = 0; -- GitLab From 83dc211702cb18e62741379fef48f2629b1c983c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 18 May 2017 13:35:22 -0400 Subject: [PATCH 0486/2898] drm/amd/display: Remove redundant condition. You cannot have modeset and flip in the same call for same CRTC, in such case it will be set mode and set plane, not a flip. Signed-off-by: Andrey Grodzovsky Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index a5b7c054d853..b3a4605858c1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -3115,15 +3115,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, action = get_dm_commit_action(crtc->state); - /* Surfaces are created under two scenarios: - * 1. This commit is not a page flip. - * 2. This commit is a page flip, and streams are created. - */ crtc_state = drm_atomic_get_crtc_state(state, crtc); pflip_needed = !state->allow_modeset; - if (!pflip_needed || - action == DM_COMMIT_ACTION_DPMS_ON || - action == DM_COMMIT_ACTION_SET) { + if (!pflip_needed) { struct dc_surface *surface; list_for_each_entry(connector, -- GitLab From 89c872e595c48ccf357bbabcc9918bdef9de7ac8 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 18 May 2017 19:03:15 -0400 Subject: [PATCH 0487/2898] drm/amd/display: fix YUV surface address programming sequence need to program DCSURF_PRIMARY_SURFACE_ADDRESS last as HW automatically latch rest of addr regs on write when SURFACE_UPDATE_LOCK is not used Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_mem_input.c | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 587ded13140b..a52c614ec5b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -237,16 +237,23 @@ static bool mem_input_program_surface_flip_and_addr( struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); /* program flip type */ - REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, flip_immediate); - /* REG_UPDATE(FLIP_CONTROL, SURFACE_UPDATE_LOCK, 1); */ - - - /* program high first and then the low addr, order matters! */ + /* HW automatically latch rest of address register on write to + * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used + * + * program high first and then the low addr, order matters! + */ switch (address->type) { case PLN_ADDR_TYPE_GRAPHICS: + /* DCN1.0 does not support const color + * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 + * base on address->grph.dcc_const_color + * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma + * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma + */ + if (address->grph.addr.quad_part == 0) break; @@ -268,14 +275,6 @@ static bool mem_input_program_surface_flip_and_addr( REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, address->grph.addr.low_part); - - - /* DCN1.0 does not support const color - * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 - * base on address->grph.dcc_const_color - * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma - * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma - */ break; case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: if (address->video_progressive.luma_addr.quad_part == 0 @@ -301,14 +300,6 @@ static bool mem_input_program_surface_flip_and_addr( address->video_progressive.chroma_meta_addr.low_part); } - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, - PRIMARY_SURFACE_ADDRESS_HIGH, - address->video_progressive.luma_addr.high_part); - - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, - PRIMARY_SURFACE_ADDRESS, - address->video_progressive.luma_addr.low_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, address->video_progressive.chroma_addr.high_part); @@ -317,6 +308,14 @@ static bool mem_input_program_surface_flip_and_addr( PRIMARY_SURFACE_ADDRESS_C, address->video_progressive.chroma_addr.low_part); + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_addr.high_part); + + REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + PRIMARY_SURFACE_ADDRESS, + address->video_progressive.luma_addr.low_part); + break; case PLN_ADDR_TYPE_GRPH_STEREO: if (address->grph_stereo.left_addr.quad_part == 0) @@ -365,7 +364,6 @@ static bool mem_input_program_surface_flip_and_addr( BREAK_TO_DEBUGGER(); break; } - /* REG_UPDATE(FLIP_CONTROL, SURFACE_UPDATE_LOCK, 0); */ mem_input->request_address = *address; -- GitLab From a7562ab35ee96810e9e4c41969a375f1c3f249ae Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 18 May 2017 17:02:43 -0400 Subject: [PATCH 0488/2898] drm/amd/display: remove GRPH_SURFACE_UPDATE_IMMEDIATE_EN field programming This is causing asserts for dce 8 and 10 since they do not contain this field. It is also unnecessary for later DCEs as it is left in it's default state of 0 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 7 +------ drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 2 -- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 673371e5f9f0..157f4e1680e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -621,15 +621,10 @@ static bool dce_mi_program_surface_flip_and_addr( { struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mem_input); - /* TODO: Figure out if two modes are needed: - * non-XDMA Mode: GRPH_SURFACE_UPDATE_IMMEDIATE_EN = 1 - * XDMA Mode: GRPH_SURFACE_UPDATE_H_RETRACE_EN = 1 - */ REG_UPDATE(GRPH_UPDATE, GRPH_UPDATE_LOCK, 1); - REG_UPDATE_2( + REG_UPDATE( GRPH_FLIP_CONTROL, - GRPH_SURFACE_UPDATE_IMMEDIATE_EN, 0, GRPH_SURFACE_UPDATE_H_RETRACE_EN, flip_immediate ? 1 : 0); switch (address->type) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index 9d083cd79b4c..05d39c0cbe87 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -162,7 +162,6 @@ struct dce_mem_input_registers { SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh) #define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ - SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_IMMEDIATE_EN, mask_sh),\ SFB(blk, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, mask_sh) #define MI_DCP_PTE_MASK_SH_LIST(mask_sh, blk)\ @@ -278,7 +277,6 @@ struct dce_mem_input_registers { type GRPH_PRIMARY_SURFACE_ADDRESS_HIGH; \ type GRPH_PRIMARY_SURFACE_ADDRESS; \ type GRPH_SURFACE_UPDATE_PENDING; \ - type GRPH_SURFACE_UPDATE_IMMEDIATE_EN; \ type GRPH_SURFACE_UPDATE_H_RETRACE_EN; \ type GRPH_UPDATE_LOCK; \ type PIXEL_DURATION; \ -- GitLab From d9e8887860c93cf5b8785d7d35a411a1636cfcaf Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 18 May 2017 16:56:45 -0400 Subject: [PATCH 0489/2898] drm/amd/display: fix flip register write sequence Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_mem_input.c | 56 +++++++++---------- .../amd/display/dc/dcn10/dcn10_mem_input.h | 2 + 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index a52c614ec5b4..da2f99dcd766 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -237,7 +237,7 @@ static bool mem_input_program_surface_flip_and_addr( struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); /* program flip type */ - REG_UPDATE(DCSURF_FLIP_CONTROL, + REG_SET(DCSURF_FLIP_CONTROL, 0, SURFACE_FLIP_TYPE, flip_immediate); /* HW automatically latch rest of address register on write to @@ -258,21 +258,20 @@ static bool mem_input_program_surface_flip_and_addr( break; if (address->grph.meta_addr.quad_part != 0) { - - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH, address->grph.meta_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, PRIMARY_META_SURFACE_ADDRESS, address->grph.meta_addr.low_part); } - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, PRIMARY_SURFACE_ADDRESS_HIGH, address->grph.addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, PRIMARY_SURFACE_ADDRESS, address->grph.addr.low_part); break; @@ -282,40 +281,38 @@ static bool mem_input_program_surface_flip_and_addr( break; if (address->video_progressive.luma_meta_addr.quad_part != 0) { + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_meta_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->video_progressive.chroma_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH, address->video_progressive.luma_meta_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, PRIMARY_META_SURFACE_ADDRESS, address->video_progressive.luma_meta_addr.low_part); - - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, - PRIMARY_META_SURFACE_ADDRESS_HIGH_C, - address->video_progressive.chroma_meta_addr.high_part); - - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, - PRIMARY_META_SURFACE_ADDRESS_C, - address->video_progressive.chroma_meta_addr.low_part); } - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, PRIMARY_SURFACE_ADDRESS_HIGH_C, address->video_progressive.chroma_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_C, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, PRIMARY_SURFACE_ADDRESS_C, address->video_progressive.chroma_addr.low_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, PRIMARY_SURFACE_ADDRESS_HIGH, address->video_progressive.luma_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, PRIMARY_SURFACE_ADDRESS, address->video_progressive.luma_addr.low_part); - break; case PLN_ADDR_TYPE_GRPH_STEREO: if (address->grph_stereo.left_addr.quad_part == 0) @@ -324,39 +321,38 @@ static bool mem_input_program_surface_flip_and_addr( break; if (address->grph_stereo.right_meta_addr.quad_part != 0) { - REG_UPDATE(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, SECONDARY_META_SURFACE_ADDRESS_HIGH, address->grph_stereo.right_meta_addr.high_part); - REG_UPDATE(DCSURF_SECONDARY_META_SURFACE_ADDRESS, + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, SECONDARY_META_SURFACE_ADDRESS, address->grph_stereo.right_meta_addr.low_part); } if (address->grph_stereo.left_meta_addr.quad_part != 0) { - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH, address->grph_stereo.left_meta_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_META_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, PRIMARY_META_SURFACE_ADDRESS, address->grph_stereo.left_meta_addr.low_part); } - REG_UPDATE(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, SECONDARY_SURFACE_ADDRESS_HIGH, address->grph_stereo.right_addr.high_part); - REG_UPDATE(DCSURF_SECONDARY_SURFACE_ADDRESS, + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, SECONDARY_SURFACE_ADDRESS, address->grph_stereo.right_addr.low_part); - - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, PRIMARY_SURFACE_ADDRESS_HIGH, address->grph_stereo.left_addr.high_part); - REG_UPDATE(DCSURF_PRIMARY_SURFACE_ADDRESS, + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, PRIMARY_SURFACE_ADDRESS, address->grph_stereo.left_addr.low_part); break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 20bd0f5d7b17..48b313b213c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -282,6 +282,7 @@ struct dcn_mi_registers { MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_PENDING, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ @@ -414,6 +415,7 @@ struct dcn_mi_registers { type H_MIRROR_EN;\ type SURFACE_PIXEL_FORMAT;\ type SURFACE_FLIP_TYPE;\ + type SURFACE_UPDATE_LOCK;\ type SURFACE_UPDATE_PENDING;\ type PRIMARY_SURFACE_ADDRESS_HIGH;\ type PRIMARY_SURFACE_ADDRESS;\ -- GitLab From 5aa35c1a16d505c0aee7fa5bebf829f9bef32c34 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 18 May 2017 11:40:53 -0400 Subject: [PATCH 0490/2898] drm/amd/display: Remove unused addr var in TG Signed-off-by: Harry Wentland Reviewed-by: Sun peng Li Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce120/dce120_timing_generator.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index c208196864ad..03b21e9a1156 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -386,34 +386,27 @@ bool dce120_timing_generator_did_triggered_reset_occur( /* Move to enable accelerated mode */ void dce120_timing_generator_disable_vga(struct timing_generator *tg) { - uint32_t addr = 0; uint32_t offset = 0; uint32_t value = 0; struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); switch (tg110->controller_id) { case CONTROLLER_ID_D0: - addr = mmD1VGA_CONTROL; offset = 0; break; case CONTROLLER_ID_D1: - addr = mmD2VGA_CONTROL; offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D2: - addr = mmD3VGA_CONTROL; offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D3: - addr = mmD4VGA_CONTROL; offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D4: - addr = mmD1VGA_CONTROL; offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL; break; case CONTROLLER_ID_D5: - addr = mmD6VGA_CONTROL; offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL; break; default: -- GitLab From c14833c6728e587d33777d416a9d0c21d3785ff8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 19 May 2017 17:15:23 -0400 Subject: [PATCH 0491/2898] drm/amd/display: No need to assert on stream_status This will be NULL on a new stream. DC handles it gracefully. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b3a4605858c1..3c1baa29f36f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2883,9 +2883,6 @@ static enum surface_update_type amdgpu_dm_check_surfaces_update_type( dc_stream_get_status(dc_stream); enum surface_update_type update_type; - ASSERT(stream_status); - - memset(srf_updates, 0, sizeof(srf_updates)); memset(flip_addr, 0, sizeof(flip_addr)); memset(plane_info, 0, sizeof(plane_info)); -- GitLab From 21de3396b44a67429c6b6a3f2d697fb261c76054 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 22 May 2017 13:11:15 +0800 Subject: [PATCH 0492/2898] drm/amd/display: call amdgpu_dm_fini when hw_fini. to free up drm mode_config info. fix issue: unload amdgpu, can't load amdgpu again. [drm:drm_debugfs_init [drm]] *ERROR* Cannot create /sys/kernel/debug/dri/0 [drm:drm_minor_register [drm]] *ERROR* DRM: Failed to initialize /sys/kernel/debug/dri. Signed-off-by: Rex Zhu Acked-by: Alex Deucher Reviewed-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ++--- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7e28f9870b86..74415fdf7ed8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -395,9 +395,8 @@ void amdgpu_dm_fini(struct amdgpu_device *adev) adev->dm.freesync_module = NULL; } /* DC Destroy TODO: Replace destroy DAL */ - { + if (adev->dm.dc) dc_destroy(&adev->dm.dc); - } return; } @@ -490,7 +489,7 @@ static int dm_hw_fini(void *handle) amdgpu_dm_hpd_fini(adev); amdgpu_dm_irq_fini(adev); - + amdgpu_dm_fini(adev); return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 773f0efc449b..b428c7c6559b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1541,7 +1541,12 @@ enum dc_irq_source dc_interrupt_to_irq_source( void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_dc *core_dc; + + if (dc == NULL) + return; + core_dc = DC_TO_CORE(dc); + dal_irq_service_set(core_dc->res_pool->irqs, src, enable); } -- GitLab From 0bf954c154d7a8989afb6c138d63ca846bab47db Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 2 Jun 2017 14:54:26 -0400 Subject: [PATCH 0493/2898] drm/amdgpu/soc15: enable DC ip module for Raven Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 3d9a51d6e1aa..c2611eca8495 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -554,6 +554,12 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#else +# warning "Enable CONFIG_DRM_AMD_DC for display support on SOC15." +#endif amdgpu_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_ip_block_add(adev, &sdma_v4_0_ip_block); amdgpu_ip_block_add(adev, &vcn_v1_0_ip_block); -- GitLab From 93b8ca9b8711ec2536060897f0f05db41dd810f5 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 30 May 2017 16:49:59 -0400 Subject: [PATCH 0494/2898] drm/amdgpu: Enable DRIVER_ATOMIC flag for DAL. This flag is needed to pass several of IGT test cases. Signed-off-by: Andrey Grodzovsky Acked-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 27d46a907bd9..a350fc9b2a70 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2071,6 +2071,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg; adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg; + if (amdgpu_device_has_dc_support(adev)) + adev->ddev->driver->driver_features |= DRIVER_ATOMIC; + DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n", amdgpu_asic_name[adev->asic_type], pdev->vendor, pdev->device, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 2484dac08050..90fa8e8bc6fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -348,7 +348,8 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) drm_fb_helper_single_add_all_connectors(&rfbdev->helper); /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(adev->ddev); + if (!amdgpu_device_has_dc_support(adev)) + drm_helper_disable_unused_functions(adev->ddev); drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); return 0; -- GitLab From e73b59b7e0cdecf0663b76f77b770c88b2d61604 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 19 May 2017 13:01:35 -0400 Subject: [PATCH 0495/2898] drm/amd/display: add always_scale debug flag to dc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/dcn10/dcn10_transform.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f2efa32fe4ac..3b35487897b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -181,6 +181,7 @@ struct dc_debug { int urgent_latency_ns; int percent_of_ideal_drambw; int dram_clock_change_latency_ns; + int always_scale; #endif bool disable_pplib_clock_request; bool disable_clock_gate; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index 3718fb5a3238..609805877508 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -157,7 +157,8 @@ static void transform_set_otg_blank( OTG_V_BLANK_END, v_blank_end); } -static enum dscl_mode_sel get_dscl_mode(const struct scaler_data *data) +static enum dscl_mode_sel get_dscl_mode( + const struct scaler_data *data, bool dbg_always_scale) { const long long one = dal_fixed31_32_one.value; bool ycbcr = false; @@ -177,7 +178,8 @@ static enum dscl_mode_sel get_dscl_mode(const struct scaler_data *data) if (data->ratios.horz.value == one && data->ratios.vert.value == one && data->ratios.horz_c.value == one - && data->ratios.vert_c.value == one) + && data->ratios.vert_c.value == one + && !dbg_always_scale) return DSCL_MODE_SCALING_444_BYPASS; if (!format420) { @@ -603,7 +605,8 @@ void transform_set_scaler_auto_scale( { enum lb_memory_config lb_config; struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode(scl_data); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; @@ -611,7 +614,7 @@ void transform_set_scaler_auto_scale( transform_set_otg_blank(xfm, scl_data); - REG_UPDATE(SCL_MODE, DSCL_MODE, get_dscl_mode(scl_data)); + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); @@ -740,7 +743,8 @@ static void transform_set_scaler_manual_scale( { enum lb_memory_config lb_config; struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode(scl_data); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; -- GitLab From c1473558e617d886276e4a8b3c139b681d90d67c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 19 May 2017 17:40:50 -0400 Subject: [PATCH 0496/2898] drm/amd/display: program scaler not called. Scaler code in case of UPDATE_TYPE_MED was not called since new pipe context and current context are the same. Signed-off-by: Andrey Grodzovsky Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 23 +++++++++++++++++-- .../display/dc/dce110/dce110_hw_sequencer.c | 6 ++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b428c7c6559b..4900e8073c69 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1011,12 +1011,23 @@ bool dc_commit_surfaces_to_stream( struct dc_plane_info plane_info[MAX_SURFACES]; struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; + bool ret; + struct dc_stream_update *stream_update = + dm_alloc(sizeof(struct dc_stream_update)); + + if (!stream_update) { + BREAK_TO_DEBUGGER(); + return false; + } memset(updates, 0, sizeof(updates)); memset(flip_addr, 0, sizeof(flip_addr)); memset(plane_info, 0, sizeof(plane_info)); memset(scaling_info, 0, sizeof(scaling_info)); + stream_update->src = dc_stream->src; + stream_update->dst = dc_stream->dst; + for (i = 0; i < new_surface_count; i++) { updates[i].surface = new_surfaces[i]; updates[i].gamma = @@ -1041,9 +1052,17 @@ bool dc_commit_surfaces_to_stream( updates[i].plane_info = &plane_info[i]; updates[i].scaling_info = &scaling_info[i]; } - dc_update_surfaces_for_stream(dc, updates, new_surface_count, dc_stream); - return dc_post_update_surfaces_to_stream(dc); + dc_update_surfaces_and_stream( + dc, + updates, + new_surface_count, + dc_stream, stream_update); + + ret = dc_post_update_surfaces_to_stream(dc); + + dm_free(stream_update); + return ret; } static bool is_surface_in_context( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 65c691569eb7..7dd4b02b5938 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2408,10 +2408,8 @@ static void dce110_program_front_end_for_pipe( pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; - if (old_pipe && memcmp(&old_pipe->scl_data, - &pipe_ctx->scl_data, - sizeof(struct scaler_data)) != 0) - program_scaler(dc, pipe_ctx); + + program_scaler(dc, pipe_ctx); mi->funcs->mem_input_program_surface_config( mi, -- GitLab From bf2e2e2e0ea9ace6ed11423497664656943ec55f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 18 May 2017 22:13:19 -0400 Subject: [PATCH 0497/2898] drm/amd/display: Limit DCN to x86 arch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DCN bw calcs currently rely on the following gcc options: -mhard-float -msse -mpreferred-stack-boundary=4 We probably shouldn't really try building this on architectures other than x86. CC: Alex Deucher CC: Christian König CC: Michel Dänzer CC: Tony Cheng CC: Dmytro Laktyushkin Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 2 +- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 5c3bb3581842..89fc8e738668 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -19,7 +19,7 @@ config DRM_AMD_DC_PRE_VEGA config DRM_AMD_DC_DCN1_0 bool "DCN 1.0 Raven family" - depends on DRM_AMD_DC + depends on DRM_AMD_DC && X86 help Choose this option if you want to have RV family for display engine diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index a095472bf4b5..2e4ce0918c02 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,9 +3,11 @@ # It calculates Bandwidth and Watermarks values for HW programming # +ifeq ($(ARCH),x86) CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 +endif BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o -- GitLab From ccaa73897109c521a9fda82a50c988e9cba947e7 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 22 May 2017 17:55:38 -0400 Subject: [PATCH 0498/2898] drm/amd/display: Fix handling of scaling and underscan. Summury of changes: 1: Both in check and commit Connector properties were handled as part of for_each(crtc) loop while they shoud have been handled in a dedicated for_each(connector) loop since they are connector properties. Moved. 2: Removed hacky plane add in amdgpu_dm_connector_atomic_set_property to force iteration on plane forconnector property. This was causing double call to commit_surface_for_stream both in crtc loop and plane loop. 3: Remove middleman DC interface and call dc_commit_surfaces_to_stream directly to increase code clarity. Remove it from atomic_commit. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 205 +++++++++--------- 1 file changed, 99 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 3c1baa29f36f..4da5a7154cea 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -682,9 +682,8 @@ struct amdgpu_connector *aconnector_from_drm_crtc_id( static void update_stream_scaling_settings( const struct drm_display_mode *mode, const struct dm_connector_state *dm_state, - const struct dc_stream *stream) + struct dc_stream *stream) { - struct amdgpu_device *adev = dm_state->base.crtc->dev->dev_private; enum amdgpu_rmx_type rmx_type; struct rect src = { 0 }; /* viewport in composition space*/ @@ -726,7 +725,8 @@ static void update_stream_scaling_settings( dst.height -= dm_state->underscan_vborder; } - adev->dm.dc->stream_funcs.stream_update_scaling(adev->dm.dc, stream, &src, &dst); + stream->src = src; + stream->dst = dst; DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", dst.x, dst.y, dst.width, dst.height); @@ -1135,9 +1135,6 @@ int amdgpu_dm_connector_atomic_set_property( struct dm_connector_state *dm_new_state = to_dm_connector_state(connector_state); - struct drm_crtc_state *new_crtc_state; - struct drm_crtc *crtc; - int i; int ret = -EINVAL; if (property == dev->mode_config.scaling_mode_property) { @@ -1175,32 +1172,6 @@ int amdgpu_dm_connector_atomic_set_property( ret = 0; } - for_each_crtc_in_state( - connector_state->state, - crtc, - new_crtc_state, - i) { - - if (crtc == connector_state->crtc) { - struct drm_plane_state *plane_state; - - /* - * Bit of magic done here. We need to ensure - * that planes get update after mode is set. - * So, we need to add primary plane to state, - * and this way atomic_update would be called - * for it - */ - plane_state = - drm_atomic_get_plane_state( - connector_state->state, - crtc->primary); - - if (!plane_state) - return -EINVAL; - } - } - return ret; } @@ -2401,28 +2372,19 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; - struct dm_connector_state *dm_state = NULL; - - enum dm_commit_action action; + struct dm_connector_state *con_state = NULL; bool pflip_needed; if (!fb || !crtc || !crtc->state->active) continue; - action = get_dm_commit_action(crtc->state); - - /* - * TODO - TO decide if it's a flip or surface update - * stop relying on allow_modeset flag and query DC - * using dc_check_update_surfaces_for_stream. - */ pflip_needed = !state->allow_modeset; if (!pflip_needed) { list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->state->crtc == crtc) { - dm_state = to_dm_connector_state( + con_state = to_dm_connector_state( connector->state); break; } @@ -2442,8 +2404,10 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, * Also it should be needed when used with actual * drm_atomic_commit ioctl in future */ - if (!dm_state) + if (!con_state) continue; + + if (crtc == pcrtc) { add_surface(dm->dc, crtc, plane, &dc_surfaces_constructed[planes_count]); @@ -2495,7 +2459,8 @@ void amdgpu_dm_atomic_commit_tail( const struct dc_stream *new_stream; unsigned long flags; bool wait_for_vblank = true; - + struct drm_connector *connector; + struct drm_connector_state *old_conn_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -2575,21 +2540,6 @@ void amdgpu_dm_atomic_commit_tail( break; } - - case DM_COMMIT_ACTION_NOTHING: { - struct dm_connector_state *dm_state = NULL; - - if (!aconnector) - break; - - dm_state = to_dm_connector_state(aconnector->base.state); - - /* Scaling update */ - update_stream_scaling_settings(&crtc->state->mode, - dm_state, acrtc->stream); - - break; - } case DM_COMMIT_ACTION_DPMS_OFF: case DM_COMMIT_ACTION_RESET: DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); @@ -2597,9 +2547,48 @@ void amdgpu_dm_atomic_commit_tail( if (acrtc->stream) remove_stream(adev, acrtc); break; + + /*TODO retire */ + case DM_COMMIT_ACTION_NOTHING: + continue; } /* switch() */ } /* for_each_crtc_in_state() */ + /* Handle scaling and undersacn changes*/ + for_each_connector_in_state(state, connector, old_conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_new_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_old_state = + to_dm_connector_state(old_conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + const struct dc_stream_status *status = NULL; + + /* Skip any modesets/resets */ + if (!acrtc || + get_dm_commit_action(acrtc->base.state) != DM_COMMIT_ACTION_NOTHING) + continue; + + /* Skip any thing not scale or underscan chnages */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + update_stream_scaling_settings(&con_new_state->base.crtc->mode, + con_new_state, (struct dc_stream *)acrtc->stream); + + status = dc_stream_get_status(acrtc->stream); + WARN_ON(!status); + WARN_ON(!status->surface_count); + + /*TODO How it works with MPO ?*/ + if (!dc_commit_surfaces_to_stream( + dm->dc, + (const struct dc_surface **)status->surfaces, + status->surface_count, + acrtc->stream)) + dm_error("%s: Failed to update stream scaling!\n", __func__); + } + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -2937,6 +2926,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; bool need_to_validate = false; struct validate_context *context; + struct drm_connector *connector; + struct drm_connector_state *conn_state; /* * This bool will be set for true for any modeset/reset * or surface update which implies non fast surfae update. @@ -3022,52 +3013,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, break; } - case DM_COMMIT_ACTION_NOTHING: { - const struct drm_connector *drm_connector = NULL; - struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_state = NULL; - struct dm_connector_state *old_dm_state = NULL; - struct dc_stream *new_stream; - - if (!aconnector) - break; - - for_each_connector_in_state( - state, drm_connector, conn_state, j) { - if (&aconnector->base == drm_connector) - break; - } - - old_dm_state = to_dm_connector_state(drm_connector->state); - dm_state = to_dm_connector_state(conn_state); - - /* Support underscan adjustment*/ - if (!is_scaling_state_different(dm_state, old_dm_state)) - break; - - new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_state); - - if (!new_stream) { - DRM_ERROR("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - break; - } - - new_streams[new_stream_count] = new_stream; - set_count = update_in_val_sets_stream( - set, - crtc_set, - set_count, - acrtc->stream, - new_stream, - crtc); - - new_stream_count++; - need_to_validate = true; - wait_for_prev_commits = true; - - break; - } case DM_COMMIT_ACTION_DPMS_OFF: case DM_COMMIT_ACTION_RESET: /* i.e. reset mode */ @@ -3079,6 +3024,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, wait_for_prev_commits = true; } break; + + /*TODO retire */ + case DM_COMMIT_ACTION_NOTHING: + continue; } /* @@ -3095,6 +3044,50 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = -EINVAL; } + /* Check scaling and undersacn changes*/ + for_each_connector_in_state(state, connector, conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_old_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_new_state = + to_dm_connector_state(conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + struct dc_stream *new_stream; + + /* Skip any modesets/resets */ + if (!acrtc || + get_dm_commit_action(acrtc->base.state) != DM_COMMIT_ACTION_NOTHING) + continue; + + /* Skip any thing not scale or underscan chnages */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + new_stream = create_stream_for_sink( + aconnector, + &acrtc->base.state->mode, + con_new_state); + + if (!new_stream) { + DRM_ERROR("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + continue; + } + + new_streams[new_stream_count] = new_stream; + set_count = update_in_val_sets_stream( + set, + crtc_set, + set_count, + acrtc->stream, + new_stream, + &acrtc->base); + + new_stream_count++; + need_to_validate = true; + wait_for_prev_commits = true; + } + for (i = 0; i < set_count; i++) { for_each_plane_in_state(state, plane, plane_state, j) { struct drm_crtc *crtc = plane_state->crtc; -- GitLab From 893a2dd4a3ffceb3b3fa88353d8270de06195b10 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 22 May 2017 20:25:48 -0400 Subject: [PATCH 0499/2898] drm/amd/display: Clean unused interface. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 42 ------------------------ drivers/gpu/drm/amd/display/dc/dc.h | 6 ---- 2 files changed, 48 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4900e8073c69..f5349970b594 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -249,47 +249,6 @@ static void set_static_screen_events(struct dc *dc, core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); } -/* This function is not expected to fail, proper implementation of - * validation will prevent this from ever being called for unsupported - * configurations. - */ -static void stream_update_scaling( - const struct dc *dc, - const struct dc_stream *dc_stream, - const struct rect *src, - const struct rect *dst) -{ - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - struct core_dc *core_dc = DC_TO_CORE(dc); - struct validate_context *cur_ctx = core_dc->current_context; - int i; - - if (src) - stream->public.src = *src; - - if (dst) - stream->public.dst = *dst; - - for (i = 0; i < cur_ctx->stream_count; i++) { - struct core_stream *cur_stream = cur_ctx->streams[i]; - - if (stream == cur_stream) { - struct dc_stream_status *status = &cur_ctx->stream_status[i]; - - if (status->surface_count) - if (!dc_commit_surfaces_to_stream( - &core_dc->public, - status->surfaces, - status->surface_count, - &cur_stream->public)) - /* Need to debug validation */ - BREAK_TO_DEBUGGER(); - - return; - } - } -} - static void set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link) @@ -402,7 +361,6 @@ void set_dither_option(const struct dc_stream *dc_stream, static void allocate_dc_stream_funcs(struct core_dc *core_dc) { - core_dc->public.stream_funcs.stream_update_scaling = stream_update_scaling; if (core_dc->hwss.set_drr != NULL) { core_dc->public.stream_funcs.adjust_vmin_vmax = stream_adjust_vmin_vmax; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3b35487897b7..0d3b73a37df1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -115,12 +115,6 @@ struct dc_stream_funcs { unsigned int *v_pos, unsigned int *nom_v_pos); - - void (*stream_update_scaling)(const struct dc *dc, - const struct dc_stream *dc_stream, - const struct rect *src, - const struct rect *dst); - bool (*set_gamut_remap)(struct dc *dc, const struct dc_stream *stream); -- GitLab From 29eba8e88f3665b5099d0c4ef7180b631846aa0b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 23 May 2017 17:15:54 -0400 Subject: [PATCH 0500/2898] drm/amd/display: Add disable_psr debug flag Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0d3b73a37df1..ce052d12a104 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -180,6 +180,7 @@ struct dc_debug { bool disable_pplib_clock_request; bool disable_clock_gate; bool disable_dmcu; + bool disable_psr; bool force_abm_enable; }; -- GitLab From c7dbdf1535a34741a8805d04a9ae75a887d8b581 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Tue, 23 May 2017 15:26:57 -0400 Subject: [PATCH 0501/2898] drm/amd/display: Allow update stream without surface Passing NULL as surfaceUpdates to dc_update_surfaces_and_stream now updates just the stream. Code that is dependent on srf_updates was moved below the NULL check. Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 58 +++++++++++++----------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f5349970b594..c33e31c9e3e1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1223,33 +1223,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!stream_status) return; /* Cannot commit surface to stream that is not committed */ - update_type = dc_check_update_surfaces_for_stream( - dc, srf_updates, surface_count, stream_update, stream_status); - - if (update_type >= update_surface_trace_level) - update_surface_trace(dc, srf_updates, surface_count); - - if (update_type >= UPDATE_TYPE_FULL) { - const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; - - for (i = 0; i < surface_count; i++) - new_surfaces[i] = srf_updates[i].surface; - - /* initialize scratch memory for building context */ - context = dm_alloc(sizeof(*context)); - dc_resource_validate_ctx_copy_construct( - core_dc->current_context, context); - - /* add surface to context */ - if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, dc_stream, - context, core_dc->res_pool)) { - BREAK_TO_DEBUGGER(); - goto fail; - } - } else { - context = core_dc->current_context; - } + context = core_dc->current_context; /* update current stream with the new updates */ if (stream_update) { @@ -1277,6 +1251,36 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } + /* only proceed if we need to make a surface update */ + if (!srf_updates) + return; + + update_type = dc_check_update_surfaces_for_stream( + dc, srf_updates, surface_count, stream_update, stream_status); + + if (update_type >= update_surface_trace_level) + update_surface_trace(dc, srf_updates, surface_count); + + if (update_type >= UPDATE_TYPE_FULL) { + const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + + for (i = 0; i < surface_count; i++) + new_surfaces[i] = srf_updates[i].surface; + + /* initialize scratch memory for building context */ + context = dm_alloc(sizeof(*context)); + dc_resource_validate_ctx_copy_construct( + core_dc->current_context, context); + + /* add surface to context */ + if (!resource_attach_surfaces_to_context( + new_surfaces, surface_count, dc_stream, + context, core_dc->res_pool)) { + BREAK_TO_DEBUGGER(); + goto fail; + } + } + /* save update parameters into surface */ for (i = 0; i < surface_count; i++) { struct core_surface *surface = -- GitLab From 72dfad50179bb8c813d7c3a7ce149dafc4586fe6 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 19 May 2017 15:52:00 -0400 Subject: [PATCH 0502/2898] drm/amd/display: Add FORCE_HDR timing flag Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 58a3bcd5131f..b6e677786cbc 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -635,6 +635,8 @@ struct dc_crtc_timing_flags { uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */ uint32_t DTD_COUNTER :5; /* values 1 to 16 */ + uint32_t FORCE_HDR :1; + /* HDMI 2.0 - Support scrambling for TMDS character * rates less than or equal to 340Mcsc */ uint32_t LTE_340MCSC_SCRAMBLE:1; -- GitLab From ece22899a46551dcd8e9f3296ce1ec8ac9e07dc4 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 24 May 2017 14:53:50 -0400 Subject: [PATCH 0503/2898] drm/amd/display: Disable PSR entry abort to prevent intermittent freezes Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 59977640f938..79f3947a3ee1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1550,6 +1550,11 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, */ psr_context.psr_level.bits.SKIP_SMU_NOTIFICATION = 1; + /* Complete PSR entry before aborting to prevent intermittent + * freezes on certain eDPs + */ + psr_context.psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; + /* Controls additional delay after remote frame capture before * continuing power down, default = 0 */ -- GitLab From afdbd4ccfd36eb18ce89b504d79bb3051cdab839 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Wed, 24 May 2017 11:01:32 -0400 Subject: [PATCH 0504/2898] drm/amd/display: fix NULL pointer in dm_commit_surfaces Check if adding surface is failed to prevent NULL pointer deref. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 4da5a7154cea..810373480ed5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2411,6 +2411,10 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, if (crtc == pcrtc) { add_surface(dm->dc, crtc, plane, &dc_surfaces_constructed[planes_count]); + if (dc_surfaces_constructed[planes_count] == NULL) { + dm_error("%s: Failed to add surface!\n", __func__); + continue; + } dc_stream_attach = acrtc_attach->stream; planes_count++; } -- GitLab From 4c92c92d77cdbfb46925d498addf19e5aebe46b8 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 24 May 2017 11:59:39 -0400 Subject: [PATCH 0505/2898] drm/amd/display: Get rid of get_dm_commit_action Use drm_atomic_crtc_needs_modeset instead. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 127 ++++++------------ 1 file changed, 44 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 810373480ed5..3747c99f3a8d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2164,57 +2164,23 @@ int amdgpu_dm_encoder_init( return res; } -enum dm_commit_action { - DM_COMMIT_ACTION_NOTHING, - DM_COMMIT_ACTION_RESET, - DM_COMMIT_ACTION_DPMS_ON, - DM_COMMIT_ACTION_DPMS_OFF, - DM_COMMIT_ACTION_SET -}; - -static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state) +static bool modeset_required(struct drm_crtc_state *crtc_state) { - /* mode changed means either actually mode changed or enabled changed */ - /* active changed means dpms changed */ - - DRM_DEBUG_KMS("crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n", - state->enable, - state->active, - state->planes_changed, - state->mode_changed, - state->active_changed, - state->connectors_changed); - - if (state->mode_changed) { - /* if it is got disabled - call reset mode */ - if (!state->enable) - return DM_COMMIT_ACTION_RESET; + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; - if (state->active) - return DM_COMMIT_ACTION_SET; - else - return DM_COMMIT_ACTION_RESET; - } else { - /* ! mode_changed */ + if (!crtc_state->enable) + return false; - /* if it is remain disable - skip it */ - if (!state->enable) - return DM_COMMIT_ACTION_NOTHING; + return crtc_state->active; +} - if (state->active && state->connectors_changed) - return DM_COMMIT_ACTION_SET; +static bool modereset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; - if (state->active_changed) { - if (state->active) { - return DM_COMMIT_ACTION_DPMS_ON; - } else { - return DM_COMMIT_ACTION_DPMS_OFF; - } - } else { - /* ! active_changed */ - return DM_COMMIT_ACTION_NOTHING; - } - } + return !crtc_state->enable || !crtc_state->active; } static void manage_dm_interrupts( @@ -2467,12 +2433,10 @@ void amdgpu_dm_atomic_commit_tail( struct drm_connector_state *old_conn_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); - /* update changed items */ for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc; struct amdgpu_connector *aconnector = NULL; - enum dm_commit_action action; struct drm_crtc_state *new_state = crtc->state; acrtc = to_amdgpu_crtc(crtc); @@ -2483,15 +2447,23 @@ void amdgpu_dm_atomic_commit_tail( crtc, false); + DRM_DEBUG_KMS( + "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " + "planes_changed:%d, mode_changed:%d,active_changed:%d," + "connectors_changed:%d\n", + acrtc->crtc_id, + new_state->enable, + new_state->active, + new_state->planes_changed, + new_state->mode_changed, + new_state->active_changed, + new_state->connectors_changed); + /* handles headless hotplug case, updating new_state and * aconnector as needed */ - action = get_dm_commit_action(new_state); - - switch (action) { - case DM_COMMIT_ACTION_DPMS_ON: - case DM_COMMIT_ACTION_SET: { + if (modeset_required(new_state)) { struct dm_connector_state *dm_state = NULL; new_stream = NULL; @@ -2541,21 +2513,13 @@ void amdgpu_dm_atomic_commit_tail( acrtc->enabled = true; acrtc->hw_mode = crtc->state->mode; crtc->hwmode = crtc->state->mode; + } else if (modereset_required(new_state)) { - break; - } - case DM_COMMIT_ACTION_DPMS_OFF: - case DM_COMMIT_ACTION_RESET: DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ if (acrtc->stream) remove_stream(adev, acrtc); - break; - - /*TODO retire */ - case DM_COMMIT_ACTION_NOTHING: - continue; - } /* switch() */ + } } /* for_each_crtc_in_state() */ /* Handle scaling and undersacn changes*/ @@ -2569,8 +2533,7 @@ void amdgpu_dm_atomic_commit_tail( const struct dc_stream_status *status = NULL; /* Skip any modesets/resets */ - if (!acrtc || - get_dm_commit_action(acrtc->base.state) != DM_COMMIT_ACTION_NOTHING) + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) continue; /* Skip any thing not scale or underscan chnages */ @@ -2966,17 +2929,25 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; - enum dm_commit_action action; acrtc = to_amdgpu_crtc(crtc); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); - action = get_dm_commit_action(crtc_state); + DRM_DEBUG_KMS( + "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " + "planes_changed:%d, mode_changed:%d,active_changed:%d," + "connectors_changed:%d\n", + acrtc->crtc_id, + crtc_state->enable, + crtc_state->active, + crtc_state->planes_changed, + crtc_state->mode_changed, + crtc_state->active_changed, + crtc_state->connectors_changed); + + if (modeset_required(crtc_state)) { - switch (action) { - case DM_COMMIT_ACTION_DPMS_ON: - case DM_COMMIT_ACTION_SET: { struct dc_stream *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_state = NULL; @@ -3014,11 +2985,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; wait_for_prev_commits = true; - break; - } - case DM_COMMIT_ACTION_DPMS_OFF: - case DM_COMMIT_ACTION_RESET: + } else if (modereset_required(crtc_state)) { + /* i.e. reset mode */ if (acrtc->stream) { set_count = remove_from_val_sets( @@ -3027,11 +2996,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, acrtc->stream); wait_for_prev_commits = true; } - break; - - /*TODO retire */ - case DM_COMMIT_ACTION_NOTHING: - continue; } /* @@ -3059,8 +3023,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc_stream *new_stream; /* Skip any modesets/resets */ - if (!acrtc || - get_dm_commit_action(acrtc->base.state) != DM_COMMIT_ACTION_NOTHING) + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) continue; /* Skip any thing not scale or underscan chnages */ @@ -3098,7 +3061,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *dm_state = NULL; - enum dm_commit_action action; struct drm_crtc_state *crtc_state; bool pflip_needed; @@ -3107,7 +3069,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, !crtc->state->planes_changed || !crtc->state->active) continue; - action = get_dm_commit_action(crtc->state); crtc_state = drm_atomic_get_crtc_state(state, crtc); pflip_needed = !state->allow_modeset; -- GitLab From 7fa4fcba7ab4f29f88b503e0e840f4c3bf774dc0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 25 May 2017 11:44:53 -0400 Subject: [PATCH 0506/2898] drm/amd/display: Don't guard x86 in Makefile make-kpkg doesn't seem to like it Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 2e4ce0918c02..a095472bf4b5 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -3,11 +3,9 @@ # It calculates Bandwidth and Watermarks values for HW programming # -ifeq ($(ARCH),x86) CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 -endif BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o -- GitLab From e4bf0a0eed7e0e3bb7f0be2788cf0a5ecc16b068 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 25 May 2017 10:55:54 -0400 Subject: [PATCH 0507/2898] drm/amd/display: create_links bug with empty DDI slot Signed-off-by: Hersen Wu Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 7 ++++--- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 682fc9b9b3f2..fcd3b72287c8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -410,6 +410,9 @@ enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) return id; } +/* BIOS oject table displaypath is per connector. + * There is extra path not for connector. BIOS fill its encoderid as 0 + */ static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) { struct bios_parser *bp = BP_FROM_DCB(dcb); @@ -417,9 +420,7 @@ static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) unsigned int i; for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) { - if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0 - && - bp->object_info_tbl.v1_4->display_path[i].display_objid != 0) + if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0) count++; } return count; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c33e31c9e3e1..323a5e706908 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -97,6 +97,7 @@ static bool create_links( struct core_link *link; link_init_params.ctx = dc->ctx; + /* next BIOS object table connector */ link_init_params.connector_index = i; link_init_params.link_index = dc->link_count; link_init_params.dc = dc; @@ -106,8 +107,6 @@ static bool create_links( dc->links[dc->link_count] = link; link->dc = dc; ++dc->link_count; - } else { - dm_error("DC: failed to create link!\n"); } } -- GitLab From 0a1c73ec8e4834d72441ae77f436869fd5179d8f Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 25 May 2017 14:40:21 +0530 Subject: [PATCH 0508/2898] drm/amd/display: re-order the luma chroma addres updation The DCE engine triggers scan as soon as the luma address is updated, since it is updated before chroma address the chroma data is not scanned out properly or in order. This patch fixes this by re-ordering the same. BUG: SWDEV-119421 TEST: (On Chromium OS for Stoney Only) * Executed below tests to see YUV(underlay) & RGB planes on eDP plane_test --format XR24 --size 500x100 -p --format NV12 --size 500x500 * Chroma data is scanned properly. Signed-off-by: Shirish S Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c index 9777a4d961d5..a06c6024deb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c @@ -137,12 +137,12 @@ static void program_addr( addr->grph.addr); break; case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: - program_pri_addr_l( - mem_input110, - addr->video_progressive.luma_addr); program_pri_addr_c( mem_input110, addr->video_progressive.chroma_addr); + program_pri_addr_l( + mem_input110, + addr->video_progressive.luma_addr); break; default: /* not supported */ -- GitLab From 630e3573853ff8644daf1ae32a503984110afe28 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Fri, 19 May 2017 08:32:23 -0500 Subject: [PATCH 0509/2898] drm/amd/display: default spd packet to invalid Signed-off-by: Jeff Smith Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ec5045734378..6202b4b3e597 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2172,6 +2172,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) info->avi.valid = false; info->gamut.valid = false; info->vendor.valid = false; + info->spd.valid = false; info->hdrsmd.valid = false; info->vsc.valid = false; -- GitLab From f0c16087fba728c36bc33fe462b35ca4ada7f5ca Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 25 May 2017 14:36:47 +0530 Subject: [PATCH 0510/2898] drm/amd/display: update NV12/NV21 as the YUV format This patch updates the YUV format supported to NV12 and NV21 and hence updates the offsets. BUG: SWDEV-119421 TEST: (On Chromium OS for Stoney Only) * Executed below tests to see YUV(underlay) & RGB planes on eDP plane_test --format XR24 --size 500x100 -p --format NV12 --size 500x500 Signed-off-by: Shirish S Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 3747c99f3a8d..1fc8bbfcb4b9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -456,6 +456,7 @@ static void fill_plane_attributes_from_fb( { uint64_t tiling_flags; uint64_t fb_location = 0; + unsigned int awidth; const struct drm_framebuffer *fb = &amdgpu_fb->base; struct drm_format_name_buf format_name; @@ -484,10 +485,10 @@ static void fill_plane_attributes_from_fb( case DRM_FORMAT_ABGR2101010: surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; break; - case DRM_FORMAT_YUV420: + case DRM_FORMAT_NV21: surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; break; - case DRM_FORMAT_YVU420: + case DRM_FORMAT_NV12: surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; break; default: @@ -510,24 +511,25 @@ static void fill_plane_attributes_from_fb( surface->color_space = COLOR_SPACE_SRGB; } else { + awidth = ALIGN(fb->width, 64); surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; surface->address.video_progressive.luma_addr.low_part = lower_32_bits(fb_location); surface->address.video_progressive.chroma_addr.low_part = lower_32_bits(fb_location) + - (fb->width * fb->height); + (awidth * fb->height); surface->plane_size.video.luma_size.x = 0; surface->plane_size.video.luma_size.y = 0; - surface->plane_size.video.luma_size.width = fb->width; + surface->plane_size.video.luma_size.width = awidth; surface->plane_size.video.luma_size.height = fb->height; /* TODO: unhardcode */ - surface->plane_size.video.luma_pitch = ALIGN(fb->width, 64); + surface->plane_size.video.luma_pitch = awidth; surface->plane_size.video.chroma_size.x = 0; surface->plane_size.video.chroma_size.y = 0; - surface->plane_size.video.chroma_size.width = fb->width / 2; - surface->plane_size.video.chroma_size.height = fb->height / 2; - surface->plane_size.video.chroma_pitch = ALIGN(fb->width, 64) / 2; + surface->plane_size.video.chroma_size.width = awidth; + surface->plane_size.video.chroma_size.height = fb->height; + surface->plane_size.video.chroma_pitch = awidth / 2; /* TODO: unhardcode */ surface->color_space = COLOR_SPACE_YCBCR709; @@ -1662,8 +1664,8 @@ static uint32_t rgb_formats[] = { }; static uint32_t yuv_formats[] = { - DRM_FORMAT_YUV420, - DRM_FORMAT_YVU420, + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, }; int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, -- GitLab From 30406ff85324bc64bf8a9bf5b3f4e75c23ea4abf Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 25 May 2017 18:00:37 -0400 Subject: [PATCH 0511/2898] drm/amd/display: Don't commit surfaces if no stream Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 1fc8bbfcb4b9..7db04a487c21 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2549,6 +2549,9 @@ void amdgpu_dm_atomic_commit_tail( WARN_ON(!status); WARN_ON(!status->surface_count); + if (!acrtc->stream) + continue; + /*TODO How it works with MPO ?*/ if (!dc_commit_surfaces_to_stream( dm->dc, @@ -2606,8 +2609,12 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed per crtc*/ - for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) - amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc); + + if (acrtc->stream) + amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + } for (i = 0; i < new_crtcs_count; i++) { /* -- GitLab From 259873e1ff3198d80f2dd50e3ab4249ad289e4c2 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 25 May 2017 18:39:49 -0400 Subject: [PATCH 0512/2898] drm/amd/display: stop adjusting scl taps when scl ratio is one on dcn Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_transform.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index 609805877508..d9815a991682 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -851,14 +851,16 @@ static bool transform_get_optimal_number_of_taps( else scl_data->taps.h_taps_c = in_taps->h_taps_c; - if (IDENTITY_RATIO(scl_data->ratios.horz)) - scl_data->taps.h_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert)) - scl_data->taps.v_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.horz_c)) - scl_data->taps.h_taps_c = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert_c)) - scl_data->taps.v_taps_c = 1; + if (!xfm->ctx->dc->debug.always_scale) { + if (IDENTITY_RATIO(scl_data->ratios.horz)) + scl_data->taps.h_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert)) + scl_data->taps.v_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.horz_c)) + scl_data->taps.h_taps_c = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert_c)) + scl_data->taps.v_taps_c = 1; + } return true; } -- GitLab From 5d11e9fca5b45191b531d8fa3b9dd6de1156fc2b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 29 May 2017 18:29:33 -0400 Subject: [PATCH 0513/2898] drm/amd/display: allow taking split pipes during resource mapping Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6202b4b3e597..124fcac63eba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1406,6 +1406,42 @@ static void calculate_phy_pix_clks(struct validate_context *context) } } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +static int acquire_first_split_pipe( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct core_stream *stream) +{ + int i; + + for (i = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->top_pipe && + pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + int mpc_idx = pipe_ctx->mpc_idx; + + pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; + pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; + + memset(pipe_ctx, 0, sizeof(*pipe_ctx)); + pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->mi = pool->mis[i]; + pipe_ctx->ipp = pool->ipps[i]; + pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->opp = pool->opps[i]; + pipe_ctx->dis_clk = pool->display_clock; + pipe_ctx->pipe_idx = i; + pipe_ctx->mpc_idx = mpc_idx; + + pipe_ctx->stream = stream; + return i; + } + } + return -1; +} +#endif + enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context, @@ -1477,8 +1513,11 @@ enum dc_status resource_map_pool_resources( if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; /* acquire new resources */ - pipe_idx = acquire_first_free_pipe( - &context->res_ctx, pool, stream); + pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (pipe_idx < 0) + acquire_first_split_pipe(&context->res_ctx, pool, stream); +#endif if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; -- GitLab From 05a19c39cb0adcb0f73b7418b9afead49d2406d4 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 29 May 2017 18:26:28 -0400 Subject: [PATCH 0514/2898] drm/amd/display: fix surface attachment handling of pipe split Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 124fcac63eba..e6e3b181a3dc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -894,24 +894,6 @@ enum dc_status resource_build_scaling_params_for_context( return DC_OK; } -static void detach_surfaces_for_stream( - struct validate_context *context, - const struct resource_pool *pool, - const struct dc_stream *dc_stream) -{ - int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); - - for (i = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i]; - if (cur_pipe->stream == stream) { - cur_pipe->surface = NULL; - cur_pipe->top_pipe = NULL; - cur_pipe->bottom_pipe = NULL; - } - } -} - struct pipe_ctx *find_idle_secondary_pipe( struct resource_context *res_ctx, const struct resource_pool *pool) @@ -1004,9 +986,11 @@ static void release_free_pipes_for_stream( struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); for (i = MAX_PIPES - 1; i >= 0; i--) { + /* never release the topmost pipe*/ if (res_ctx->pipe_ctx[i].stream == stream && + res_ctx->pipe_ctx[i].top_pipe && !res_ctx->pipe_ctx[i].surface) { - res_ctx->pipe_ctx[i].stream = NULL; + memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx)); } } } @@ -1021,6 +1005,7 @@ bool resource_attach_surfaces_to_context( int i; struct pipe_ctx *tail_pipe; struct dc_stream_status *stream_status = NULL; + struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); if (surface_count > MAX_SURFACE_NUM) { @@ -1043,7 +1028,12 @@ bool resource_attach_surfaces_to_context( for (i = 0; i < surface_count; i++) dc_surface_retain(surfaces[i]); - detach_surfaces_for_stream(context, pool, dc_stream); + /* detach surfaces from pipes */ + for (i = 0; i < pool->pipe_count; i++) + if (context->res_ctx.pipe_ctx[i].stream == stream) { + context->res_ctx.pipe_ctx[i].surface = NULL; + context->res_ctx.pipe_ctx[i].bottom_pipe = NULL; + } /* release existing surfaces*/ for (i = 0; i < stream_status->surface_count; i++) @@ -1052,11 +1042,6 @@ bool resource_attach_surfaces_to_context( for (i = surface_count; i < stream_status->surface_count; i++) stream_status->surfaces[i] = NULL; - stream_status->surface_count = 0; - - if (surface_count == 0) - return true; - tail_pipe = NULL; for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); -- GitLab From 0f9a536fe036eed82b563b0da5b2c57a9455b679 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 30 May 2017 13:38:10 -0400 Subject: [PATCH 0515/2898] drm/amd/display: fix mpo + split pipe aquisition failure Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 80 ++++++++++--------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e6e3b181a3dc..e4a6636fd829 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -995,6 +995,43 @@ static void release_free_pipes_for_stream( } } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +static int acquire_first_split_pipe( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct core_stream *stream) +{ + int i; + + for (i = 0; i < pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->top_pipe && + pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + int mpc_idx = pipe_ctx->mpc_idx; + + pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; + if (pipe_ctx->bottom_pipe) + pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; + + memset(pipe_ctx, 0, sizeof(*pipe_ctx)); + pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->mi = pool->mis[i]; + pipe_ctx->ipp = pool->ipps[i]; + pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->opp = pool->opps[i]; + pipe_ctx->dis_clk = pool->display_clock; + pipe_ctx->pipe_idx = i; + pipe_ctx->mpc_idx = mpc_idx; + + pipe_ctx->stream = stream; + return i; + } + } + return -1; +} +#endif + bool resource_attach_surfaces_to_context( const struct dc_surface * const *surfaces, int surface_count, @@ -1048,6 +1085,13 @@ bool resource_attach_surfaces_to_context( struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( context, pool, dc_stream); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (!free_pipe) { + int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); + if (pipe_idx >= 0) + free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; + } +#endif if (!free_pipe) { stream_status->surfaces[i] = NULL; return false; @@ -1391,42 +1435,6 @@ static void calculate_phy_pix_clks(struct validate_context *context) } } -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -static int acquire_first_split_pipe( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct core_stream *stream) -{ - int i; - - for (i = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - - if (pipe_ctx->top_pipe && - pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - int mpc_idx = pipe_ctx->mpc_idx; - - pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; - pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; - - memset(pipe_ctx, 0, sizeof(*pipe_ctx)); - pipe_ctx->tg = pool->timing_generators[i]; - pipe_ctx->mi = pool->mis[i]; - pipe_ctx->ipp = pool->ipps[i]; - pipe_ctx->xfm = pool->transforms[i]; - pipe_ctx->opp = pool->opps[i]; - pipe_ctx->dis_clk = pool->display_clock; - pipe_ctx->pipe_idx = i; - pipe_ctx->mpc_idx = mpc_idx; - - pipe_ctx->stream = stream; - return i; - } - } - return -1; -} -#endif - enum dc_status resource_map_pool_resources( const struct core_dc *dc, struct validate_context *context, -- GitLab From 2ea5e9a8bda7472037fb34b75f7033cfc4afa674 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 2 Apr 2017 11:55:41 -0400 Subject: [PATCH 0516/2898] drm/amd/display: Universal cursor plane hook-up. Switch from legacy cursor to DRM cursor plane. Cursor is not an actual plane but more of a subplane of each pipe. Bind a DRM cursor plane instance to each CRTC. Eliminate seperate FB object allocation for cursor and clean dm_crtc_cursor_set. Signed-off-by: Andrey Grodzovsky Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 242 +++++++----------- 1 file changed, 91 insertions(+), 151 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 7db04a487c21..068ed85bdc6d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -136,127 +136,27 @@ static void dm_set_cursor( } } -static int dm_crtc_unpin_cursor_bo_old( - struct amdgpu_crtc *amdgpu_crtc) -{ - struct amdgpu_bo *robj; - int ret = 0; - - if (NULL != amdgpu_crtc && NULL != amdgpu_crtc->cursor_bo) { - robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - - ret = amdgpu_bo_reserve(robj, false); - - if (likely(ret == 0)) { - ret = amdgpu_bo_unpin(robj); - - if (unlikely(ret != 0)) { - DRM_ERROR( - "%s: unpin failed (ret=%d), bo %p\n", - __func__, - ret, - amdgpu_crtc->cursor_bo); - } - - amdgpu_bo_unreserve(robj); - } else { - DRM_ERROR( - "%s: reserve failed (ret=%d), bo %p\n", - __func__, - ret, - amdgpu_crtc->cursor_bo); - } - - drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo); - amdgpu_crtc->cursor_bo = NULL; - } - - return ret; -} - -static int dm_crtc_pin_cursor_bo_new( - struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - struct amdgpu_bo **ret_obj) -{ - struct amdgpu_crtc *amdgpu_crtc; - struct amdgpu_bo *robj; - struct drm_gem_object *obj; - int ret = -EINVAL; - - if (NULL != crtc) { - struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; - uint64_t gpu_addr; - - amdgpu_crtc = to_amdgpu_crtc(crtc); - - obj = drm_gem_object_lookup(file_priv, handle); - - if (!obj) { - DRM_ERROR( - "Cannot find cursor object %x for crtc %d\n", - handle, - amdgpu_crtc->crtc_id); - goto release; - } - robj = gem_to_amdgpu_bo(obj); - - ret = amdgpu_bo_reserve(robj, false); - - if (unlikely(ret != 0)) { - drm_gem_object_unreference_unlocked(obj); - DRM_ERROR("dm_crtc_pin_cursor_bo_new ret %x, handle %x\n", - ret, handle); - goto release; - } - - ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, 0, - adev->mc.visible_vram_size, - &gpu_addr); - - if (ret == 0) { - amdgpu_crtc->cursor_addr = gpu_addr; - *ret_obj = robj; - } - amdgpu_bo_unreserve(robj); - if (ret) - drm_gem_object_unreference_unlocked(obj); - - } -release: - - return ret; -} - static int dm_crtc_cursor_set( struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, + uint64_t address, uint32_t width, uint32_t height) { - struct amdgpu_bo *new_cursor_bo; struct dc_cursor_position position; int ret; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; - new_cursor_bo = NULL; DRM_DEBUG_KMS( - "%s: crtc_id=%d with handle %d and size %d to %d, bo_object %p\n", + "%s: crtc_id=%d with size %d to %d \n", __func__, amdgpu_crtc->crtc_id, - handle, width, - height, - amdgpu_crtc->cursor_bo); + height); - if (!handle) { + if (!address) { /* turn off cursor */ position.enable = false; position.x = 0; @@ -268,8 +168,6 @@ static int dm_crtc_cursor_set( amdgpu_crtc->stream, &position); } - /*unpin old cursor buffer and update cache*/ - ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); goto release; } @@ -283,21 +181,9 @@ static int dm_crtc_cursor_set( height); goto release; } - /*try to pin new cursor bo*/ - ret = dm_crtc_pin_cursor_bo_new(crtc, file_priv, handle, &new_cursor_bo); - /*if map not successful then return an error*/ - if (ret) - goto release; /*program new cursor bo to hardware*/ - dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height); - - /*un map old, not used anymore cursor bo , - * return memory and mapping back */ - dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); - - /*assign new cursor bo to our internal cache*/ - amdgpu_crtc->cursor_bo = &new_cursor_bo->gem_base; + dm_set_cursor(amdgpu_crtc, address, width, height); release: return ret; @@ -359,23 +245,6 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, return 0; } -static void dm_crtc_cursor_reset(struct drm_crtc *crtc) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - DRM_DEBUG_KMS( - "%s: with cursor_bo %p\n", - __func__, - amdgpu_crtc->cursor_bo); - - if (amdgpu_crtc->cursor_bo && amdgpu_crtc->stream) { - dm_set_cursor( - amdgpu_crtc, - amdgpu_crtc->cursor_addr, - amdgpu_crtc->cursor_width, - amdgpu_crtc->cursor_height); - } -} static bool fill_rects_from_plane_state( const struct drm_plane_state *state, struct dc_surface *surface) @@ -1094,8 +963,6 @@ void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) /* Implemented only the options currently availible for the driver */ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .reset = drm_atomic_helper_crtc_reset, - .cursor_set = dm_crtc_cursor_set, - .cursor_move = dm_crtc_cursor_move, .destroy = amdgpu_dm_crtc_destroy, .gamma_set = drm_atomic_helper_legacy_gamma_set, .set_config = drm_atomic_helper_set_config, @@ -1571,6 +1438,18 @@ static int dm_plane_helper_prepare_fb( } amdgpu_bo_ref(rbo); + + /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer + * prepare and cleanup in drm_atomic_helper_prepare_planes + * and drm_atomic_helper_cleanup_planes because fb doens't in s3. + * IN 4.10 kernel this code should be removed and amdgpu_device_suspend + * code touching fram buffers should be avoided for DC. + */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_state->crtc); + + acrtc->cursor_bo = obj; + } return 0; } @@ -1668,6 +1547,10 @@ static uint32_t yuv_formats[] = { DRM_FORMAT_NV21, }; +static const u32 cursor_formats[] = { + DRM_FORMAT_ARGB8888 +}; + int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, unsigned long possible_crtcs) @@ -1698,7 +1581,14 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, NULL, aplane->plane_type, NULL); break; case DRM_PLANE_TYPE_CURSOR: - DRM_ERROR("KMS: Cursor plane not implemented."); + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + cursor_formats, + ARRAY_SIZE(cursor_formats), + NULL, aplane->plane_type, NULL); break; } @@ -1711,9 +1601,18 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, uint32_t crtc_index) { - struct amdgpu_crtc *acrtc; + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_plane *cursor_plane; + int res = -ENOMEM; + cursor_plane = kzalloc(sizeof(*cursor_plane), GFP_KERNEL); + if (!cursor_plane) + goto fail; + + cursor_plane->base.type = DRM_PLANE_TYPE_CURSOR; + res = amdgpu_dm_plane_init(dm, cursor_plane, 0); + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); if (!acrtc) goto fail; @@ -1722,7 +1621,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, dm->ddev, &acrtc->base, plane, - NULL, + &cursor_plane->base, &amdgpu_dm_crtc_funcs, NULL); if (res) @@ -1740,12 +1639,17 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, drm_mode_crtc_set_gamma_size(&acrtc->base, 256); return 0; + fail: - kfree(acrtc); + if (acrtc) + kfree(acrtc); + if (cursor_plane) + kfree(cursor_plane); acrtc->crtc_id = -1; return res; } + static int to_drm_connector_type(enum signal_type st) { switch (st) { @@ -2252,6 +2156,34 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) acrtc->enabled = false; } +static void handle_cursor_update( + struct drm_plane *plane, + struct drm_plane_state *old_plane_state) +{ + if (!plane->state->fb && !old_plane_state->fb) + return; + + /* Check if it's a cursor on/off update or just cursor move*/ + if (plane->state->fb == old_plane_state->fb) + dm_crtc_cursor_move( + plane->state->crtc, + plane->state->crtc_x, + plane->state->crtc_y); + else { + struct amdgpu_framebuffer *afb = + to_amdgpu_framebuffer(plane->state->fb); + dm_crtc_cursor_set( + (!!plane->state->fb) ? + plane->state->crtc : + old_plane_state->crtc, + (!!plane->state->fb) ? + afb->address : + 0, + plane->state->crtc_w, + plane->state->crtc_h); + } +} + /* * Executes flip @@ -2343,6 +2275,11 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct dm_connector_state *con_state = NULL; bool pflip_needed; + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + handle_cursor_update(plane, old_plane_state); + continue; + } + if (!fb || !crtc || !crtc->state->active) continue; @@ -2627,7 +2564,6 @@ void amdgpu_dm_atomic_commit_tail( adev->dm.freesync_module, &acrtc->stream, 1); manage_dm_interrupts(adev, acrtc, true); - dm_crtc_cursor_reset(&acrtc->base); } @@ -3007,18 +2943,19 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /* - * TODO revisit when removing commit action - * and looking at atomic flags directly + * Hack: Commit needs planes right now, specifically for gamma + * TODO rework commit to check CRTC for gamma change */ + if (crtc_state->color_mgmt_changed) { - /* commit needs planes right now (for gamma, eg.) */ - /* TODO rework commit to chack crtc for gamma change */ - ret = drm_atomic_add_affected_planes(state, crtc); - if (ret) - return ret; + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + return ret; - ret = -EINVAL; + ret = -EINVAL; + } } /* Check scaling and undersacn changes*/ @@ -3073,6 +3010,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_crtc_state *crtc_state; bool pflip_needed; + /*TODO Implement atomic check for cursor plane */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; if (!fb || !crtc || crtc_set[i] != crtc || !crtc->state->planes_changed || !crtc->state->active) -- GitLab From 7db4dede6425fba7177468123e5149916dd45fd4 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Tue, 30 May 2017 16:16:57 -0400 Subject: [PATCH 0517/2898] drm/amd/display: Add function to get PSR state Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 13 +++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 1 + 4 files changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 79f3947a3ee1..318aaa762f31 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1444,6 +1444,19 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) return true; } +bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state) +{ + struct core_link *link = DC_LINK_TO_CORE(dc_link); + struct dc_context *ctx = link->ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dmcu *dmcu = core_dc->res_pool->dmcu; + + if (dmcu != NULL && link->psr_enabled) + dmcu->funcs->get_psr_state(dmcu, psr_state); + + return true; +} + bool dc_link_setup_psr(const struct dc_link *dc_link, const struct dc_stream *stream, struct psr_config *psr_config) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ce052d12a104..328bfcb7dbb8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -702,6 +702,8 @@ bool dc_link_set_abm_disable(const struct dc_link *dc_link); bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); +bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); + bool dc_link_setup_psr(const struct dc_link *dc_link, const struct dc_stream *stream, struct psr_config *psr_config); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index c58328cd787b..03b51e256e21 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -470,6 +470,7 @@ static const struct dmcu_funcs dce_funcs = { .load_iram = dce_dmcu_load_iram, .set_psr_enable = dce_dmcu_set_psr_enable, .setup_psr = dce_dmcu_setup_psr, + .get_psr_state = dce_get_dmcu_psr_state }; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -477,6 +478,7 @@ static const struct dmcu_funcs dcn10_funcs = { .load_iram = dcn10_dmcu_load_iram, .set_psr_enable = dcn10_dmcu_set_psr_enable, .setup_psr = dcn10_dmcu_setup_psr, + .get_psr_state = dcn10_get_dmcu_psr_state }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 656cfdc79891..dff0babb5cf7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -41,6 +41,7 @@ struct dmcu_funcs { void (*setup_psr)(struct dmcu *dmcu, struct core_link *link, struct psr_context *psr_context); + void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); }; #endif -- GitLab From 1605b3bef8454a8906333f7a0ca0fb177422100d Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 5 Apr 2017 12:02:45 -0400 Subject: [PATCH 0518/2898] drm/amd/display: Remove redundant member from amdgpu_plane. Signed-off-by: Andrey Grodzovsky Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 74415fdf7ed8..6b25a7ba2f7d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1203,7 +1203,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) DRM_ERROR("KMS: Failed to allocate surface\n"); goto fail_free_planes; } - mode_info->planes[i]->plane_type = mode_info->plane_type[i]; + mode_info->planes[i]->base.type = mode_info->plane_type[i]; if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 0xff)) { DRM_ERROR("KMS: Failed to initialize plane\n"); goto fail_free_planes; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 068ed85bdc6d..b99f6ef499d1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1557,7 +1557,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, { int res = -EPERM; - switch (aplane->plane_type) { + switch (aplane->base.type) { case DRM_PLANE_TYPE_PRIMARY: aplane->base.format_default = true; @@ -1568,7 +1568,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, &dm_plane_funcs, rgb_formats, ARRAY_SIZE(rgb_formats), - NULL, aplane->plane_type, NULL); + NULL, aplane->base.type, NULL); break; case DRM_PLANE_TYPE_OVERLAY: res = drm_universal_plane_init( @@ -1578,7 +1578,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, &dm_plane_funcs, yuv_formats, ARRAY_SIZE(yuv_formats), - NULL, aplane->plane_type, NULL); + NULL, aplane->base.type, NULL); break; case DRM_PLANE_TYPE_CURSOR: res = drm_universal_plane_init( @@ -1588,7 +1588,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, &dm_plane_funcs, cursor_formats, ARRAY_SIZE(cursor_formats), - NULL, aplane->plane_type, NULL); + NULL, aplane->base.type, NULL); break; } -- GitLab From 5970f2aecc558ce2e04565ff082d9b78144fc714 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 30 May 2017 15:26:14 -0400 Subject: [PATCH 0519/2898] drm/amd/display: Enable DCN clock gating Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 68 +++++++++++++++---- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 4 -- 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 62a77f48d437..24c1a0f5febe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -516,12 +516,14 @@ static void power_on_plane( /* disable clock power gating */ /* DCCG_GATE_DISABLE_CNTL only has one instance */ - HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, - DISPCLK_DCCG_GATE_DISABLE, 1, - DPPCLK_GATE_DISABLE, 1); - /* DCFCLK_CNTL only has one instance */ - HWSEQ_REG_UPDATE(DCFCLK_CNTL, - DCFCLK_GATE_DIS, 1); + if (ctx->dc->debug.disable_clock_gate) { + HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, + DISPCLK_DCCG_GATE_DISABLE, 1, + DPPCLK_GATE_DISABLE, 1); + /* DCFCLK_CNTL only has one instance */ + HWSEQ_REG_UPDATE(DCFCLK_CNTL, + DCFCLK_GATE_DIS, 1); + } HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, 1); @@ -533,14 +535,6 @@ static void power_on_plane( if (ctx->dc->debug.disable_clock_gate) { HWSEQ_REG_UPDATE(DCCG_GATE_DISABLE_CNTL, DISPCLK_DCCG_GATE_DISABLE, 0); - } else { - /* DCCG_GATE_DISABLE_CNTL only has one instance. inst_offset = 0 */ - HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, - DISPCLK_DCCG_GATE_DISABLE, 0, - DPPCLK_GATE_DISABLE, 0); - /* DCFCLK_CNTL only has one instance. inst_offset = 0 */ - HWSEQ_REG_UPDATE(DCFCLK_CNTL, - DCFCLK_GATE_DIS, 0); } } @@ -666,14 +660,58 @@ static void init_hw(struct core_dc *dc) FD(DIO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE), 0, FD(DIO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE), 0); + if (!dc->public.debug.disable_clock_gate) { + /* enable all DCN clock gating */ + generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL, 19, + FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__SOCCLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_R_DCCG_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DPPCLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__AOMCLK0_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__AOMCLK1_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__AOMCLK2_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__AUDIO_DTO2_CLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GTC_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__UNB_DB_CLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__REFCLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__REFCLK_R_DIG_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__DSICLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__BYTECLK_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL__ESCCLK_GATE_DISABLE), 0); + + generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL2, 14, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_FE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_GATE_DISABLE), 0, + FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_GATE_DISABLE), 0); + + generic_reg_update_soc15(dc->ctx, 0, DCFCLK_CNTL, 1, + FD(DCFCLK_CNTL__DCFCLK_GATE_DIS), 0); + } + /* This power gating should be one-time program for DAL. * It can only change by registry key * TODO: new task will for this. * if power gating is disable, power_on_plane and power_off_plane * should be skip. Otherwise, hand will be met in power_off_plane */ - enable_power_gating_plane(dc->ctx, true); + + } static enum dc_status dcn10_prog_pixclk_crtc_otg( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 94cd7a9b0b19..660cb43fd3bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -426,8 +426,6 @@ static const struct resource_caps res_cap = { static const struct dc_debug debug_defaults_drv = { .disable_dcc = false, - .disable_dpp_power_gate = false, - .disable_hubp_power_gate = false, .disable_dmcu = true, .force_abm_enable = false, .timing_trace = false, @@ -440,8 +438,6 @@ static const struct dc_debug debug_defaults_drv = { }; static const struct dc_debug debug_defaults_diags = { - .disable_dpp_power_gate = false, - .disable_hubp_power_gate = false, .disable_clock_gate = true, .disable_dmcu = true, .force_abm_enable = false, -- GitLab From 9c42df59e44fd44cd84fe9ccd64f9f2942164d0f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 1 Jun 2017 15:29:42 -0400 Subject: [PATCH 0520/2898] drm/amd/display: Remove unsupported RGB formats Do not broadcast (to DRM) unsupported RGB formats. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b99f6ef499d1..165f91fa1206 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1527,11 +1527,6 @@ static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { * check will succeed, and let DC to implement proper check */ static uint32_t rgb_formats[] = { - DRM_FORMAT_XRGB4444, - DRM_FORMAT_ARGB4444, - DRM_FORMAT_RGBA4444, - DRM_FORMAT_ARGB1555, - DRM_FORMAT_RGB565, DRM_FORMAT_RGB888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, -- GitLab From e7b1322e15ea66c135ff98c1eb15fc542ef79c89 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 1 Jun 2017 15:40:04 -0400 Subject: [PATCH 0521/2898] drm/amd/display: Don't update surface if dimensions are 0 Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 323a5e706908..976229eb2492 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1250,8 +1250,15 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } - /* only proceed if we need to make a surface update */ - if (!srf_updates) + /* do not perform surface update if surface has invalid dimensions + * (all zero) and no scaling_info is provided + */ + if (surface_count > 0 && + srf_updates->surface->src_rect.width == 0 && + srf_updates->surface->src_rect.height == 0 && + srf_updates->surface->dst_rect.width == 0 && + srf_updates->surface->dst_rect.height == 0 && + !srf_updates->scaling_info) return; update_type = dc_check_update_surfaces_for_stream( -- GitLab From dcf6c1456ef555c4a1c0d28326a7bac2fc6923de Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 1 Jun 2017 12:27:00 -0400 Subject: [PATCH 0522/2898] drm/amd/display: clean up mpc programing during fe reset Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 24c1a0f5febe..877e2b6a7dd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -868,16 +868,10 @@ static void reset_front_end_for_pipe( */ tree_cfg = &dc->current_context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; - if (pipe_ctx->top_pipe == NULL) - dcn10_delete_mpc_tree(mpc, tree_cfg); - else { - if (dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) - pipe_ctx->top_pipe->bottom_pipe = NULL; - else { - dm_logger_write(dc->ctx->logger, LOG_RESOURCE, - "%s: failed to find dpp to be removed!\n", - __func__); - } + if (!dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) { + dm_logger_write(dc->ctx->logger, LOG_RESOURCE, + "%s: failed to find dpp to be removed!\n", + __func__); } pipe_ctx->top_pipe = NULL; -- GitLab From 556ee1b75c94cd88710e2fa8c83e2dc22717fc4f Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 1 Jun 2017 16:54:53 -0400 Subject: [PATCH 0523/2898] drm/amd/display: Add assertion for invalid surface dimensions Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 976229eb2492..f5102b644942 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1258,8 +1258,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, srf_updates->surface->src_rect.height == 0 && srf_updates->surface->dst_rect.width == 0 && srf_updates->surface->dst_rect.height == 0 && - !srf_updates->scaling_info) + !srf_updates->scaling_info) { + ASSERT(false); return; + } update_type = dc_check_update_surfaces_for_stream( dc, srf_updates, surface_count, stream_update, stream_status); -- GitLab From 1e25ed30796b89140653c60ac20ea1c8254c9e91 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 1 Jun 2017 15:49:16 -0400 Subject: [PATCH 0524/2898] drm/amd/display: remove disable_clk_gate debug flag for DCN Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 30 ------------------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 1 - 2 files changed, 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 877e2b6a7dd5..0e677f9db96a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -397,19 +397,6 @@ static void enable_power_gating_plane( HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); - - if (ctx->dc->debug.disable_clock_gate) { - /* probably better to just write entire register to 0xffff to - * ensure all clock gating is disabled - */ - HWSEQ_REG_UPDATE_3(DCCG_GATE_DISABLE_CNTL, - DISPCLK_R_DCCG_GATE_DISABLE, 1, - DPREFCLK_R_DCCG_GATE_DISABLE, 1, - REFCLK_R_DIG_GATE_DISABLE, 1); - HWSEQ_REG_UPDATE(DCFCLK_CNTL, - DCFCLK_GATE_DIS, 1); - } - } static void dpp_pg_control( @@ -513,29 +500,12 @@ static void power_on_plane( { uint32_t inst_offset = 0; - /* disable clock power gating */ - - /* DCCG_GATE_DISABLE_CNTL only has one instance */ - if (ctx->dc->debug.disable_clock_gate) { - HWSEQ_REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL, - DISPCLK_DCCG_GATE_DISABLE, 1, - DPPCLK_GATE_DISABLE, 1); - /* DCFCLK_CNTL only has one instance */ - HWSEQ_REG_UPDATE(DCFCLK_CNTL, - DCFCLK_GATE_DIS, 1); - } - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, 1); dpp_pg_control(ctx, plane_id, true); hubp_pg_control(ctx, plane_id, true); HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, 0); - - if (ctx->dc->debug.disable_clock_gate) { - HWSEQ_REG_UPDATE(DCCG_GATE_DISABLE_CNTL, - DISPCLK_DCCG_GATE_DISABLE, 0); - } } /* fully check bios enabledisplaypowergating table. dal only need dce init diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 660cb43fd3bc..e527d10b3e1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -438,7 +438,6 @@ static const struct dc_debug debug_defaults_drv = { }; static const struct dc_debug debug_defaults_diags = { - .disable_clock_gate = true, .disable_dmcu = true, .force_abm_enable = false, .timing_trace = true, -- GitLab From 8eee20139a63c6b53abc71c9a937f2b2047176c2 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 2 Jun 2017 06:15:57 -0400 Subject: [PATCH 0525/2898] drm/amd/display: disable forced stutter disable after programming watermark vbios will disable stutter pre-OS. driver re-enable after programming watermark Signed-off-by: Tony Cheng Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 5 +++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index da2f99dcd766..3e3fcf2395ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -582,6 +582,7 @@ static void program_watermarks( unsigned int refclk_mhz) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + uint32_t force_en = mem_input->ctx->dc->debug.disable_stutter ? 1 : 0; /* * Need to clamp to max of the register values (i.e. no wrap) * for dcn1, all wm registers are 21-bit wide @@ -793,6 +794,10 @@ static void program_watermarks( REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); + #if 0 REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 48b313b213c0..37683d072b42 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -127,6 +127,7 @@ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ SR(DCHUBBUB_ARB_SAT_LEVEL),\ SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ /* todo: get these from GVM instead of reading registers ourselves */\ @@ -239,6 +240,7 @@ struct dcn_mi_registers { uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; + uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; uint32_t DCHUBBUB_ARB_SAT_LEVEL; uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; @@ -381,6 +383,8 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh),\ MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh),\ MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh),\ /* todo: get these from GVM instead of reading registers ourselves */\ @@ -515,6 +519,8 @@ struct dcn_mi_registers { type SDPIF_AGP_TOP;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ type DCHUBBUB_ARB_SAT_LEVEL;\ type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ /* todo: get these from GVM instead of reading registers ourselves */\ -- GitLab From 1a2c82a2f161f68deb5f0519c315bfc92ede8e01 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Jun 2017 19:00:45 -0400 Subject: [PATCH 0526/2898] drm/amd/display: fix mpc alpha programming Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 78 +++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 201 +++++++----------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 6 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 19 +- 4 files changed, 115 insertions(+), 189 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 0e677f9db96a..447f6bf4644c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -125,14 +125,8 @@ static void lock_otg_master_update( HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, inst); - /* unlock master locker */ HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, 1); - - /* wait for unlock happens */ - if (!wait_reg(ctx, inst_offset, OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1)) - BREAK_TO_DEBUGGER(); - } static bool unlock_master_tg_and_wait( @@ -1562,8 +1556,9 @@ static void update_dchubp_dpp( enum dc_color_space color_space; struct tg_color black_color = {0}; struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); - - struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + struct pipe_ctx *temp_pipe; + int i; + int tree_pos = 0; /* depends on DML calculation, DPP clock value may change dynamically */ enable_dppclk( @@ -1609,41 +1604,30 @@ static void update_dchubp_dpp( /* TODO: build stream pipes group id. For now, use stream otg * id as pipe group id */ - pipe_ctx->mpc_idx = pipe_ctx->tg->inst; - tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; - - /* enable when bottom pipe is present and - * it does not share a surface with current pipe - */ - if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) { + /*pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->surface->public.per_pixel_alpha;*/ + if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) pipe_ctx->scl_data.lb_params.alpha_en = 1; - tree_cfg->mode = TOP_BLND; - } else { + else pipe_ctx->scl_data.lb_params.alpha_en = 0; - tree_cfg->mode = TOP_PASSTHRU; - } - if (!pipe_ctx->top_pipe && !cur_pipe_ctx->bottom_pipe) { - /* primary pipe, set mpc tree index 0 only */ - tree_cfg->num_pipes = 1; + pipe_ctx->mpc_idx = pipe_ctx->tg->inst; + tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; + if (tree_cfg->num_pipes == 0) { tree_cfg->opp_id = pipe_ctx->tg->inst; - tree_cfg->dpp[0] = pipe_ctx->pipe_idx; - tree_cfg->mpcc[0] = pipe_ctx->pipe_idx; + for (i = 0; i < MAX_PIPES; i++) { + tree_cfg->dpp[i] = 0xf; + tree_cfg->mpcc[i] = 0xf; + } } - if (!cur_pipe_ctx->top_pipe && !pipe_ctx->top_pipe) { - - if (!cur_pipe_ctx->bottom_pipe) - dcn10_set_mpc_tree(mpc, tree_cfg); - - } else if (!cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe) { - - dcn10_add_dpp(mpc, tree_cfg, - pipe_ctx->pipe_idx, pipe_ctx->pipe_idx, 1); - } else { - /* nothing to be done here */ - ASSERT(cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe); - } + for (temp_pipe = pipe_ctx->top_pipe; + temp_pipe != NULL; temp_pipe = temp_pipe->top_pipe) + tree_pos++; + tree_cfg->dpp[tree_pos] = pipe_ctx->pipe_idx; + tree_cfg->mpcc[tree_pos] = pipe_ctx->pipe_idx; + tree_cfg->per_pixel_alpha[tree_pos] = pipe_ctx->scl_data.lb_params.alpha_en; + tree_cfg->num_pipes = tree_pos + 1; + dcn10_set_mpc_tree(mpc, tree_cfg); color_space = pipe_ctx->stream->public.output_color_space; color_space_to_black_color(dc, color_space, &black_color); @@ -1680,18 +1664,15 @@ static void program_all_pipe_in_tree( { unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; - if (pipe_ctx->surface->public.visible || pipe_ctx->top_pipe == NULL) { - dcn10_power_on_fe(dc, pipe_ctx, context); + if (pipe_ctx->top_pipe == NULL) { /* lock otg_master_update to process all pipes associated with * this OTG. this is done only one time. */ - if (pipe_ctx->top_pipe == NULL) { - /* watermark is for all pipes */ - pipe_ctx->mi->funcs->program_watermarks( - pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); - lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); - } + /* watermark is for all pipes */ + pipe_ctx->mi->funcs->program_watermarks( + pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); + lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; @@ -1702,12 +1683,11 @@ static void program_all_pipe_in_tree( pipe_ctx->tg->funcs->program_global_sync( pipe_ctx->tg); pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); + } - - + if (pipe_ctx->surface->public.visible) { + dcn10_power_on_fe(dc, pipe_ctx, context); update_dchubp_dpp(dc, pipe_ctx, context); - - /* Only support one plane for now. */ } if (pipe_ctx->bottom_pipe != NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index cb22cd130e1a..58f80114e36b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -36,6 +36,9 @@ #define FN(reg_name, field_name) \ mpc->mpc_shift->field_name, mpc->mpc_mask->field_name +#define MODE_TOP_ONLY 1 +#define MODE_BLEND 3 + /* Internal function to set mpc output mux */ static void set_output_mux(struct dcn10_mpc *mpc, uint8_t opp_id, @@ -45,32 +48,7 @@ static void set_output_mux(struct dcn10_mpc *mpc, REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); - REG_SET(MUX[opp_id], 0, - MPC_OUT_MUX, mpcc_id); - -/* TODO: Move to post when ready. - if (mpcc_id == 0xf) { - MPCC_REG_UPDATE(OPP_PIPE0_OPP_PIPE_CONTROL, - OPP_PIPE_CLOCK_EN, 0); - } -*/ -} - -static void set_blend_mode(struct dcn10_mpc *mpc, - enum blend_mode mode, - uint8_t mpcc_id) -{ - /* Enable per-pixel alpha on this pipe */ - if (mode == TOP_BLND) - REG_UPDATE_3(MPCC_CONTROL[mpcc_id], - MPCC_ALPHA_BLND_MODE, 0, - MPCC_ALPHA_MULTIPLIED_MODE, 0, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, 0); - else - REG_UPDATE_3(MPCC_CONTROL[mpcc_id], - MPCC_ALPHA_BLND_MODE, 0, - MPCC_ALPHA_MULTIPLIED_MODE, 1, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, 1); + REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); } void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, @@ -121,44 +99,27 @@ void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, MPCC_BOT_SEL, 0xF); - /* MPCC_CONTROL->MPCC_MODE */ REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, tree_cfg->mode); + MPCC_MODE, MODE_TOP_ONLY); } else { REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, MPCC_BOT_SEL, tree_cfg->dpp[i+1]); - /* MPCC_CONTROL->MPCC_MODE */ REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, 3); + MPCC_MODE, MODE_BLEND); } if (i == 0) set_output_mux( mpc, tree_cfg->opp_id, mpcc_inst); - set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); + REG_UPDATE_2(MPCC_CONTROL[mpcc_inst], + MPCC_ALPHA_BLND_MODE, + tree_cfg->per_pixel_alpha[i] ? 0 : 2, + MPCC_ALPHA_MULTIPLIED_MODE, 0); } } -void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, - uint8_t dpp_idx, - uint8_t mpcc_idx, - uint8_t opp_idx) -{ - struct mpc_tree_cfg tree_cfg = { 0 }; - - tree_cfg.num_pipes = 1; - tree_cfg.opp_id = opp_idx; - tree_cfg.mode = TOP_PASSTHRU; - /* TODO: FPGA bring up one MPC has only 1 DPP and 1 MPCC - * For blend case, need fill mode DPP and cascade MPCC - */ - tree_cfg.dpp[0] = dpp_idx; - tree_cfg.mpcc[0] = mpcc_idx; - dcn10_set_mpc_tree(mpc, &tree_cfg); -} - /* * This is the function to remove current MPC tree specified by tree_cfg * Before invoke this function, ensure that master lock of OPTC specified @@ -188,6 +149,7 @@ void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, */ tree_cfg->dpp[i] = 0xf; tree_cfg->mpcc[i] = 0xf; + tree_cfg->per_pixel_alpha[i] = false; } set_output_mux(mpc, tree_cfg->opp_id, 0xf); tree_cfg->opp_id = 0xf; @@ -208,6 +170,7 @@ bool dcn10_remove_dpp(struct dcn10_mpc *mpc, uint8_t idx) { int i; + uint8_t mpcc_inst; bool found = false; /* find dpp_idx from dpp array of tree_cfg */ @@ -218,54 +181,53 @@ bool dcn10_remove_dpp(struct dcn10_mpc *mpc, } } - if (found) { - /* add remove dpp/mpcc pair into pending list */ + if (!found) { + BREAK_TO_DEBUGGER(); + return false; + } + mpcc_inst = tree_cfg->mpcc[i]; - /* TODO FPGA AddToPendingList if empty from pseudo code - * AddToPendingList(tree_cfg->dpp[i],tree_cfg->mpcc[i]); - */ - uint8_t mpcc_inst = tree_cfg->mpcc[i]; + REG_SET(MPCC_OPP_ID[mpcc_inst], 0, + MPCC_OPP_ID, 0xf); - REG_SET(MPCC_OPP_ID[mpcc_inst], 0, - MPCC_OPP_ID, 0xf); + REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, + MPCC_TOP_SEL, 0xf); - REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, - MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, 0xf); + + if (i == 0) { + if (tree_cfg->num_pipes > 1) + set_output_mux(mpc, + tree_cfg->opp_id, tree_cfg->mpcc[i+1]); + else + set_output_mux(mpc, tree_cfg->opp_id, 0xf); + } else if (i == tree_cfg->num_pipes-1) { + mpcc_inst = tree_cfg->mpcc[i - 1]; REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, MPCC_BOT_SEL, 0xF); - if (i == 0) { - if (tree_cfg->num_pipes > 1) - set_output_mux(mpc, - tree_cfg->opp_id, tree_cfg->mpcc[i+1]); - else - set_output_mux(mpc, tree_cfg->opp_id, 0xf); - } else if (i == tree_cfg->num_pipes-1) { - mpcc_inst = tree_cfg->mpcc[i - 1]; - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xF); - - REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, tree_cfg->mode); - } else { - mpcc_inst = tree_cfg->mpcc[i - 1]; + /* prev mpc is now last, set to top only*/ + REG_UPDATE(MPCC_CONTROL[mpcc_inst], + MPCC_MODE, MODE_TOP_ONLY); + } else { + mpcc_inst = tree_cfg->mpcc[i - 1]; - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); - } - set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); + REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, + MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); + } - /* update tree_cfg structure */ - while (i < tree_cfg->num_pipes - 1) { - tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; - tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; - i++; - } - tree_cfg->num_pipes--; + /* update tree_cfg structure */ + while (i < tree_cfg->num_pipes - 1) { + tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; + tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; + tree_cfg->per_pixel_alpha[i] = tree_cfg->per_pixel_alpha[i+1]; + i++; } - return found; + tree_cfg->num_pipes--; + + return true; } /* TODO FPGA: how to handle DPP? @@ -284,14 +246,14 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, struct mpc_tree_cfg *tree_cfg, uint8_t dpp_idx, uint8_t mpcc_idx, + uint8_t per_pixel_alpha, uint8_t position) { - uint8_t temp; - uint8_t temp1; + uint8_t prev; + uint8_t next; REG_SET(MPCC_OPP_ID[mpcc_idx], 0, MPCC_OPP_ID, tree_cfg->opp_id); - REG_SET(MPCC_TOP_SEL[mpcc_idx], 0, MPCC_TOP_SEL, dpp_idx); @@ -299,70 +261,71 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, /* idle dpp/mpcc is added to the top layer of tree */ REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, MPCC_BOT_SEL, tree_cfg->mpcc[0]); - REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, 3); + /* bottom mpc is always top only */ + REG_UPDATE(MPCC_CONTROL[mpcc_idx], + MPCC_MODE, MODE_TOP_ONLY); /* opp will get new output. from new added mpcc */ set_output_mux(mpc, tree_cfg->opp_id, mpcc_idx); - set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); - } else if (position == tree_cfg->num_pipes) { /* idle dpp/mpcc is added to the bottom layer of tree */ /* get instance of previous bottom mpcc, set to middle layer */ - temp = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; + prev = tree_cfg->mpcc[position - 1]; - REG_SET(MPCC_BOT_SEL[temp], 0, + REG_SET(MPCC_BOT_SEL[prev], 0, MPCC_BOT_SEL, mpcc_idx); - REG_UPDATE(MPCC_CONTROL[temp], - MPCC_MODE, 3); + /* all mpcs other than bottom need to blend */ + REG_UPDATE(MPCC_CONTROL[prev], + MPCC_MODE, MODE_BLEND); /* mpcc_idx become new bottom mpcc*/ REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, MPCC_BOT_SEL, 0xf); + /* bottom mpc is always top only */ REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, tree_cfg->mode); - - set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); + MPCC_MODE, MODE_TOP_ONLY); } else { /* idle dpp/mpcc is added to middle of tree */ - temp = tree_cfg->mpcc[position - 1]; - temp1 = tree_cfg->mpcc[position]; + prev = tree_cfg->mpcc[position - 1]; /* mpc a */ + next = tree_cfg->mpcc[position]; /* mpc b */ - /* new mpcc instance temp1 is added right after temp*/ - REG_SET(MPCC_BOT_SEL[temp], 0, + /* connect mpc inserted below mpc a*/ + REG_SET(MPCC_BOT_SEL[prev], 0, MPCC_BOT_SEL, mpcc_idx); - /* mpcc_idx connect previous temp+1 to new mpcc */ - REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, - MPCC_BOT_SEL, temp1); + /* blend on mpc being inserted */ + REG_UPDATE(MPCC_CONTROL[mpcc_idx], + MPCC_MODE, MODE_BLEND); - /* temp TODO: may not need*/ - REG_UPDATE(MPCC_CONTROL[temp], - MPCC_MODE, 3); + /* Connect mpc b below one inserted */ + REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, + MPCC_BOT_SEL, next); - set_blend_mode(mpc, tree_cfg->mode, temp); } - - /* update tree_cfg structure */ - temp = tree_cfg->num_pipes - 1; + /* premultiplied mode only if alpha is on for the layer*/ + REG_UPDATE_2(MPCC_CONTROL[mpcc_idx], + MPCC_ALPHA_BLND_MODE, + tree_cfg->per_pixel_alpha[position] ? 0 : 2, + MPCC_ALPHA_MULTIPLIED_MODE, 0); /* * iterating from the last mpc/dpp pair to the one being added, shift * them down one position */ - while (temp > position) { - tree_cfg->dpp[temp + 1] = tree_cfg->dpp[temp]; - tree_cfg->mpcc[temp + 1] = tree_cfg->mpcc[temp]; - temp--; + for (next = tree_cfg->num_pipes; next > position; next--) { + tree_cfg->dpp[next] = tree_cfg->dpp[next - 1]; + tree_cfg->mpcc[next] = tree_cfg->mpcc[next - 1]; + tree_cfg->per_pixel_alpha[next] = tree_cfg->per_pixel_alpha[next - 1]; } /* insert the new mpc/dpp pair into the tree_cfg*/ tree_cfg->dpp[position] = dpp_idx; tree_cfg->mpcc[position] = mpcc_idx; + tree_cfg->per_pixel_alpha[position] = per_pixel_alpha; tree_cfg->num_pipes++; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 6550b93c9254..3e4eb655e913 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -105,11 +105,6 @@ struct dcn10_mpc { const struct dcn_mpc_mask *mpc_mask; }; -void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, - uint8_t dpp_idx, - uint8_t mpcc_idx, - uint8_t opp_idx); - void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, struct mpc_tree_cfg *tree_cfg); @@ -121,6 +116,7 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, struct mpc_tree_cfg *tree_cfg, uint8_t dpp_idx, uint8_t mpcc_idx, + uint8_t per_pixel_alpha, uint8_t position); void wait_mpcc_idle(struct dcn10_mpc *mpc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 2e86ebe5eeda..ec1a201747f2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -25,19 +25,6 @@ #ifndef __DC_MPC_H__ #define __DC_MPC_H__ -/* define the maximum number of pipes - * MAX_NUM_PIPPES = MAX_PIPES defined in core_type.h - */ -enum { - MAX_NUM_PIPPES = 6 -}; - -enum blend_mode { - DIGI_BYPASS = 0, /* digital bypass */ - TOP_PASSTHRU, /* top layer pass through */ - TOP_BLND /* top layer blend */ -}; - /* This structure define the mpc tree configuration * num_pipes - number of pipes of the tree * opp_id - instance id of OPP to drive MPC @@ -60,10 +47,10 @@ struct mpc_tree_cfg { uint8_t num_pipes; uint8_t opp_id; /* dpp pipes for blend */ - uint8_t dpp[MAX_NUM_PIPPES]; + uint8_t dpp[6]; /* mpcc insatnces for blend */ - uint8_t mpcc[MAX_NUM_PIPPES]; - enum blend_mode mode; + uint8_t mpcc[6]; + bool per_pixel_alpha[6]; }; struct mpcc_blnd_cfg { -- GitLab From 9f72f51d701cd2dd87a157d972650924fe91ec80 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 31 May 2017 16:53:01 -0400 Subject: [PATCH 0527/2898] drm/amd/display: Refactor to call set PSR wait loop in dce_dmcu instead of dce_clocks Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 52 ++++----- drivers/gpu/drm/amd/display/dc/dc.h | 3 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 101 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 41 ++----- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 66 +++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 8 ++ drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 3 + .../drm/amd/display/dc/inc/hw/link_encoder.h | 101 ------------------ 8 files changed, 213 insertions(+), 162 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 318aaa762f31..b2c8b572d57f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1458,17 +1458,17 @@ bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state) } bool dc_link_setup_psr(const struct dc_link *dc_link, - const struct dc_stream *stream, struct psr_config *psr_config) + const struct dc_stream *stream, struct psr_config *psr_config, + struct psr_context *psr_context) { struct core_link *link = DC_LINK_TO_CORE(dc_link); struct dc_context *ctx = link->ctx; struct core_dc *core_dc = DC_TO_CORE(ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct psr_context psr_context = {0}; int i; - psr_context.controllerId = CONTROLLER_ID_UNDEFINED; + psr_context->controllerId = CONTROLLER_ID_UNDEFINED; if (dc_link != NULL && dmcu != NULL) { @@ -1503,9 +1503,9 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, &psr_configuration.raw, sizeof(psr_configuration.raw)); - psr_context.channel = link->public.ddc->ddc_pin->hw_info.ddc_channel; - psr_context.transmitterId = link->link_enc->transmitter; - psr_context.engineId = link->link_enc->preferred_engine; + psr_context->channel = link->public.ddc->ddc_pin->hw_info.ddc_channel; + psr_context->transmitterId = link->link_enc->transmitter; + psr_context->engineId = link->link_enc->preferred_engine; for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_context->res_ctx.pipe_ctx[i].stream @@ -1513,7 +1513,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, /* dmcu -1 for all controller id values, * therefore +1 here */ - psr_context.controllerId = + psr_context->controllerId = core_dc->current_context->res_ctx. pipe_ctx[i].tg->inst + 1; break; @@ -1521,60 +1521,60 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, } /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/ - psr_context.phyType = PHY_TYPE_UNIPHY; + psr_context->phyType = PHY_TYPE_UNIPHY; /*PhyId is associated with the transmitter id*/ - psr_context.smuPhyId = link->link_enc->transmitter; + psr_context->smuPhyId = link->link_enc->transmitter; - psr_context.crtcTimingVerticalTotal = stream->timing.v_total; - psr_context.vsyncRateHz = div64_u64(div64_u64((stream-> + psr_context->crtcTimingVerticalTotal = stream->timing.v_total; + psr_context->vsyncRateHz = div64_u64(div64_u64((stream-> timing.pix_clk_khz * 1000), stream->timing.v_total), stream->timing.h_total); - psr_context.psrSupportedDisplayConfig = true; - psr_context.psrExitLinkTrainingRequired = + psr_context->psrSupportedDisplayConfig = true; + psr_context->psrExitLinkTrainingRequired = psr_config->psr_exit_link_training_required; - psr_context.sdpTransmitLineNumDeadline = + psr_context->sdpTransmitLineNumDeadline = psr_config->psr_sdp_transmit_line_num_deadline; - psr_context.psrFrameCaptureIndicationReq = + psr_context->psrFrameCaptureIndicationReq = psr_config->psr_frame_capture_indication_req; - psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */ + psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */ - psr_context.numberOfControllers = + psr_context->numberOfControllers = link->dc->res_pool->res_cap->num_timing_generator; - psr_context.rfb_update_auto_en = true; + psr_context->rfb_update_auto_en = true; /* 2 frames before enter PSR. */ - psr_context.timehyst_frames = 2; + psr_context->timehyst_frames = 2; /* half a frame * (units in 100 lines, i.e. a value of 1 represents 100 lines) */ - psr_context.hyst_lines = stream->timing.v_total / 2 / 100; - psr_context.aux_repeats = 10; + psr_context->hyst_lines = stream->timing.v_total / 2 / 100; + psr_context->aux_repeats = 10; - psr_context.psr_level.u32all = 0; + psr_context->psr_level.u32all = 0; /* SMU will perform additional powerdown sequence. * For unsupported ASICs, set psr_level flag to skip PSR * static screen notification to SMU. * (Always set for DAL2, did not check ASIC) */ - psr_context.psr_level.bits.SKIP_SMU_NOTIFICATION = 1; + psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION = 1; /* Complete PSR entry before aborting to prevent intermittent * freezes on certain eDPs */ - psr_context.psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; + psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1; /* Controls additional delay after remote frame capture before * continuing power down, default = 0 */ - psr_context.frame_delay = 0; + psr_context->frame_delay = 0; link->psr_enabled = true; - dmcu->funcs->setup_psr(dmcu, link, &psr_context); + dmcu->funcs->setup_psr(dmcu, link, psr_context); return true; } else return false; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 328bfcb7dbb8..a20ba01d9e7b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -705,7 +705,8 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); bool dc_link_setup_psr(const struct dc_link *dc_link, - const struct dc_stream *stream, struct psr_config *psr_config); + const struct dc_stream *stream, struct psr_config *psr_config, + struct psr_context *psr_context); /* Request DC to detect if there is a Panel connected. * boot - If this call is during initial boot. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index d2f3b9fd7a30..06354c36c499 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -31,6 +31,7 @@ #include "dc_dp_types.h" #include "dc_hw_types.h" #include "dal_types.h" +#include "grph_object_defs.h" /* forward declarations */ struct dc_surface; @@ -493,6 +494,106 @@ struct psr_config { unsigned int psr_sdp_transmit_line_num_deadline; }; +union dmcu_psr_level { + struct { + unsigned int SKIP_CRC:1; + unsigned int SKIP_DP_VID_STREAM_DISABLE:1; + unsigned int SKIP_PHY_POWER_DOWN:1; + unsigned int SKIP_AUX_ACK_CHECK:1; + unsigned int SKIP_CRTC_DISABLE:1; + unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1; + unsigned int SKIP_SMU_NOTIFICATION:1; + unsigned int SKIP_AUTO_STATE_ADVANCE:1; + unsigned int DISABLE_PSR_ENTRY_ABORT:1; + unsigned int RESERVED:23; + } bits; + unsigned int u32all; +}; + +enum physical_phy_id { + PHYLD_0, + PHYLD_1, + PHYLD_2, + PHYLD_3, + PHYLD_4, + PHYLD_5, + PHYLD_6, + PHYLD_7, + PHYLD_8, + PHYLD_9, + PHYLD_COUNT, + PHYLD_UNKNOWN = (-1L) +}; + +enum phy_type { + PHY_TYPE_UNKNOWN = 1, + PHY_TYPE_PCIE_PHY = 2, + PHY_TYPE_UNIPHY = 3, +}; + +struct psr_context { + /* ddc line */ + enum channel_id channel; + /* Transmitter id */ + enum transmitter transmitterId; + /* Engine Id is used for Dig Be source select */ + enum engine_id engineId; + /* Controller Id used for Dig Fe source select */ + enum controller_id controllerId; + /* Pcie or Uniphy */ + enum phy_type phyType; + /* Physical PHY Id used by SMU interpretation */ + enum physical_phy_id smuPhyId; + /* Vertical total pixels from crtc timing. + * This is used for static screen detection. + * ie. If we want to detect half a frame, + * we use this to determine the hyst lines. + */ + unsigned int crtcTimingVerticalTotal; + /* PSR supported from panel capabilities and + * current display configuration + */ + bool psrSupportedDisplayConfig; + /* Whether fast link training is supported by the panel */ + bool psrExitLinkTrainingRequired; + /* If RFB setup time is greater than the total VBLANK time, + * it is not possible for the sink to capture the video frame + * in the same frame the SDP is sent. In this case, + * the frame capture indication bit should be set and an extra + * static frame should be transmitted to the sink. + */ + bool psrFrameCaptureIndicationReq; + /* Set the last possible line SDP may be transmitted without violating + * the RFB setup time or entering the active video frame. + */ + unsigned int sdpTransmitLineNumDeadline; + /* The VSync rate in Hz used to calculate the + * step size for smooth brightness feature + */ + unsigned int vsyncRateHz; + unsigned int skipPsrWaitForPllLock; + unsigned int numberOfControllers; + /* Unused, for future use. To indicate that first changed frame from + * state3 shouldn't result in psr_inactive, but rather to perform + * an automatic single frame rfb_update. + */ + bool rfb_update_auto_en; + /* Number of frame before entering static screen */ + unsigned int timehyst_frames; + /* Partial frames before entering static screen */ + unsigned int hyst_lines; + /* # of repeated AUX transaction attempts to make before + * indicating failure to the driver + */ + unsigned int aux_repeats; + /* Controls hw blocks to power down during PSR active state */ + union dmcu_psr_level psr_level; + /* Controls additional delay after remote frame capture before + * continuing powerd own + */ + unsigned int frame_delay; +}; + struct colorspace_transform { struct fixed31_32 matrix[12]; bool enable_remap; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 8bc0d0ff3a2e..04cd70172cc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -31,6 +31,7 @@ #include "dc.h" #include "core_dc.h" #include "dce_abm.h" +#include "dmcu.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dcn_calcs.h" #include "core_dc.h" @@ -331,44 +332,18 @@ static void dce_set_clock( clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; } -#define PSR_SET_WAITLOOP 0x31 - -union dce110_dmcu_psr_config_data_wait_loop_reg1 { - struct { - unsigned int wait_loop:16; /* [15:0] */ - unsigned int reserved:16; /* [31:16] */ - } bits; - unsigned int u32; -}; - -static void dce_psr_wait_loop( - struct dce_disp_clk *clk_dce, unsigned int display_clk_khz) -{ - struct dc_context *ctx = clk_dce->base.ctx; - union dce110_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; - - /* waitDMCUReadyForCmd */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); - - masterCmdData1.u32 = 0; - masterCmdData1.bits.wait_loop = display_clk_khz / 1000 / 7; - dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); - - /* setDMCUParam_Cmd */ - REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP); - - /* notifyDMCUMsg */ - REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); -} - static void dce_psr_set_clock( struct display_clock *clk, int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + struct dc_context *ctx = clk_dce->base.ctx; + struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dmcu *dmcu = core_dc->res_pool->dmcu; dce_set_clock(clk, requested_clk_khz); - dce_psr_wait_loop(clk_dce, requested_clk_khz); + + dmcu->funcs->set_psr_wait_loop(dmcu, requested_clk_khz / 1000 / 7); } static void dce112_set_clock( @@ -380,6 +355,7 @@ static void dce112_set_clock( struct dc_bios *bp = clk->ctx->dc_bios; struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); struct abm *abm = core_dc->res_pool->abm; + struct dmcu *dmcu = core_dc->res_pool->dmcu; /* Prepare to program display clock*/ memset(&dce_clk_params, 0, sizeof(dce_clk_params)); @@ -411,7 +387,8 @@ static void dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); if (abm->funcs->is_dmcu_initialized(abm)) - dce_psr_wait_loop(clk_dce, requested_clk_khz); + dmcu->funcs->set_psr_wait_loop(dmcu, + requested_clk_khz / 1000 / 7); } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 03b51e256e21..0fe3ee8e29d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -48,7 +48,9 @@ #define PSR_ENABLE 0x20 #define PSR_EXIT 0x21 #define PSR_SET 0x23 +#define PSR_SET_WAITLOOP 0x31 #define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L +unsigned int cached_wait_loop_number = 0; bool dce_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, @@ -252,6 +254,34 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } +static void dce_psr_wait_loop( + struct dmcu *dmcu, + unsigned int wait_loop_number) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + + masterCmdData1.u32 = 0; + masterCmdData1.bits.wait_loop = wait_loop_number; + cached_wait_loop_number = wait_loop_number; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +static void dce_get_psr_wait_loop(unsigned int *psr_wait_loop_number) +{ + *psr_wait_loop_number = cached_wait_loop_number; + return; +} + #if defined(CONFIG_DRM_AMD_DC_DCN1_0) bool dcn10_dmcu_load_iram(struct dmcu *dmcu, unsigned int start_offset, @@ -464,13 +494,43 @@ static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); } +static void dcn10_psr_wait_loop( + struct dmcu *dmcu, + unsigned int wait_loop_number) +{ + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + + masterCmdData1.u32 = 0; + masterCmdData1.bits.wait_loop = wait_loop_number; + cached_wait_loop_number = wait_loop_number; + dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1), masterCmdData1.u32); + + /* setDMCUParam_Cmd */ + REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_SET_WAITLOOP); + + /* notifyDMCUMsg */ + REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +} + +static void dcn10_get_psr_wait_loop(unsigned int *psr_wait_loop_number) +{ + *psr_wait_loop_number = cached_wait_loop_number; + return; +} + #endif static const struct dmcu_funcs dce_funcs = { .load_iram = dce_dmcu_load_iram, .set_psr_enable = dce_dmcu_set_psr_enable, .setup_psr = dce_dmcu_setup_psr, - .get_psr_state = dce_get_dmcu_psr_state + .get_psr_state = dce_get_dmcu_psr_state, + .set_psr_wait_loop = dce_psr_wait_loop, + .get_psr_wait_loop = dce_get_psr_wait_loop }; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -478,7 +538,9 @@ static const struct dmcu_funcs dcn10_funcs = { .load_iram = dcn10_dmcu_load_iram, .set_psr_enable = dcn10_dmcu_set_psr_enable, .setup_psr = dcn10_dmcu_setup_psr, - .get_psr_state = dcn10_get_dmcu_psr_state + .get_psr_state = dcn10_get_dmcu_psr_state, + .set_psr_wait_loop = dcn10_psr_wait_loop, + .get_psr_wait_loop = dcn10_get_psr_wait_loop }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 584682ba1f77..c421a0250016 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -197,6 +197,14 @@ union dce_dmcu_psr_config_data_reg3 { unsigned int u32All; }; +union dce_dmcu_psr_config_data_wait_loop_reg1 { + struct { + unsigned int wait_loop:16; /* [15:0] */ + unsigned int reserved:16; /* [31:16] */ + } bits; + unsigned int u32; +}; + struct dmcu *dce_dmcu_create( struct dc_context *ctx, const struct dce_dmcu_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index dff0babb5cf7..6067f464d805 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -42,6 +42,9 @@ struct dmcu_funcs { struct core_link *link, struct psr_context *psr_context); void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); + void (*set_psr_wait_loop)(struct dmcu *dmcu, + unsigned int wait_loop_number); + void (*get_psr_wait_loop)(unsigned int *psr_wait_loop_number); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 7307f96c7679..d330d38aff16 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -47,43 +47,6 @@ struct encoder_feature_support { bool ycbcr420_supported; }; -enum physical_phy_id { - PHYLD_0, - PHYLD_1, - PHYLD_2, - PHYLD_3, - PHYLD_4, - PHYLD_5, - PHYLD_6, - PHYLD_7, - PHYLD_8, - PHYLD_9, - PHYLD_COUNT, - PHYLD_UNKNOWN = (-1L) -}; - -enum phy_type { - PHY_TYPE_UNKNOWN = 1, - PHY_TYPE_PCIE_PHY = 2, - PHY_TYPE_UNIPHY = 3, -}; - -union dmcu_psr_level { - struct { - unsigned int SKIP_CRC:1; - unsigned int SKIP_DP_VID_STREAM_DISABLE:1; - unsigned int SKIP_PHY_POWER_DOWN:1; - unsigned int SKIP_AUX_ACK_CHECK:1; - unsigned int SKIP_CRTC_DISABLE:1; - unsigned int SKIP_AUX_RFB_CAPTURE_CHECK:1; - unsigned int SKIP_SMU_NOTIFICATION:1; - unsigned int SKIP_AUTO_STATE_ADVANCE:1; - unsigned int DISABLE_PSR_ENTRY_ABORT:1; - unsigned int RESERVED:23; - } bits; - unsigned int u32all; -}; - union dpcd_psr_configuration { struct { unsigned char ENABLE : 1; @@ -116,70 +79,6 @@ union psr_sink_psr_status { unsigned char raw; }; -struct psr_context { - /* ddc line */ - enum channel_id channel; - /* Transmitter id */ - enum transmitter transmitterId; - /* Engine Id is used for Dig Be source select */ - enum engine_id engineId; - /* Controller Id used for Dig Fe source select */ - enum controller_id controllerId; - /* Pcie or Uniphy */ - enum phy_type phyType; - /* Physical PHY Id used by SMU interpretation */ - enum physical_phy_id smuPhyId; - /* Vertical total pixels from crtc timing. - * This is used for static screen detection. - * ie. If we want to detect half a frame, - * we use this to determine the hyst lines. - */ - unsigned int crtcTimingVerticalTotal; - /* PSR supported from panel capabilities and - * current display configuration - */ - bool psrSupportedDisplayConfig; - /* Whether fast link training is supported by the panel */ - bool psrExitLinkTrainingRequired; - /* If RFB setup time is greater than the total VBLANK time, - * it is not possible for the sink to capture the video frame - * in the same frame the SDP is sent. In this case, - * the frame capture indication bit should be set and an extra - * static frame should be transmitted to the sink. - */ - bool psrFrameCaptureIndicationReq; - /* Set the last possible line SDP may be transmitted without violating - * the RFB setup time or entering the active video frame. - */ - unsigned int sdpTransmitLineNumDeadline; - /* The VSync rate in Hz used to calculate the - * step size for smooth brightness feature - */ - unsigned int vsyncRateHz; - unsigned int skipPsrWaitForPllLock; - unsigned int numberOfControllers; - /* Unused, for future use. To indicate that first changed frame from - * state3 shouldn't result in psr_inactive, but rather to perform - * an automatic single frame rfb_update. - */ - bool rfb_update_auto_en; - /* Number of frame before entering static screen */ - unsigned int timehyst_frames; - /* Partial frames before entering static screen */ - unsigned int hyst_lines; - /* # of repeated AUX transaction attempts to make before - * indicating failure to the driver - */ - unsigned int aux_repeats; - /* Controls hw blocks to power down during PSR active state */ - union dmcu_psr_level psr_level; - /* Controls additional delay after remote frame capture before - * continuing powerd own - */ - unsigned int frame_delay; -}; - - struct link_encoder { const struct link_encoder_funcs *funcs; int32_t aux_channel_offset; -- GitLab From fc82c5cb306d6f201cdee2c4c092ff49c6929634 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Fri, 2 Jun 2017 16:33:47 -0400 Subject: [PATCH 0528/2898] drm/amd/display: Fix DRR Enable on Desktop - Block PSR in Full screen apps to prevent incorrect static screen curser events - Reprogram static screen events when update freesync state - Program static ramp variable active after other values are programmed - Correct wrong assigning of the nominal and current vcount Signed-off-by: Amy Zhang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/modules/freesync/freesync.c | 89 ++++++++++++------- .../amd/display/modules/inc/mod_freesync.h | 3 +- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 9a073bc55144..f79c47951f90 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -257,8 +257,10 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, nom_refresh_rate_micro_hz = (unsigned int) temp; if (core_freesync->opts.min_refresh_from_edid != 0 && - dc_is_embedded_signal( - stream->sink->sink_signal)) { + dc_is_embedded_signal(stream->sink->sink_signal) + && (nom_refresh_rate_micro_hz - + core_freesync->opts.min_refresh_from_edid * + 1000000) >= 10000000) { caps->supported = true; caps->min_refresh_in_micro_hz = core_freesync->opts.min_refresh_from_edid * @@ -683,44 +685,47 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, unsigned int index, bool enable_static_screen) { unsigned int frame_duration = 0; - + unsigned int nominal_refresh_rate = core_freesync->map[index].state. + nominal_refresh_rate_in_micro_hz; + unsigned int min_refresh_rate= core_freesync->map[index].caps-> + min_refresh_in_micro_hz; struct gradual_static_ramp *static_ramp_variables = &core_freesync->map[index].state.static_ramp; + /* If we are ENABLING static screen, refresh rate should go DOWN. + * If we are DISABLING static screen, refresh rate should go UP. + */ + if (enable_static_screen) + static_ramp_variables->ramp_direction_is_up = false; + else + static_ramp_variables->ramp_direction_is_up = true; + /* If ramp is not active, set initial frame duration depending on * whether we are enabling/disabling static screen mode. If the ramp is * already active, ramp should continue in the opposite direction * starting with the current frame duration */ if (!static_ramp_variables->ramp_is_active) { - - static_ramp_variables->ramp_is_active = true; - if (enable_static_screen == true) { /* Going to lower refresh rate, so start from max * refresh rate (min frame duration) */ frame_duration = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), - core_freesync->map[index].state. - nominal_refresh_rate_in_micro_hz))); + nominal_refresh_rate))); } else { /* Going to higher refresh rate, so start from min * refresh rate (max frame duration) */ frame_duration = ((unsigned int) (div64_u64( (1000000000ULL * 1000000), - core_freesync->map[index].caps->min_refresh_in_micro_hz))); + min_refresh_rate))); } - static_ramp_variables-> ramp_current_frame_duration_in_ns = frame_duration; - } - /* If we are ENABLING static screen, refresh rate should go DOWN. - * If we are DISABLING static screen, refresh rate should go UP. - */ - static_ramp_variables->ramp_direction_is_up = !enable_static_screen; + static_ramp_variables->ramp_is_active = true; + } } void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, @@ -841,6 +846,7 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, unsigned int stream_index; struct freesync_state *state; struct core_freesync *core_freesync = NULL; + struct dc_static_screen_events triggers = {0}; if (mod_freesync == NULL) return; @@ -902,6 +908,14 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, } } + /* Update mask */ + triggers.overlay_update = true; + triggers.surface_update = true; + + core_freesync->dc->stream_funcs.set_static_screen_events( + core_freesync->dc, streams, num_streams, + &triggers); + if (freesync_program_required) /* Program freesync according to current state*/ set_freesync_on_streams(core_freesync, streams, num_streams); @@ -1017,7 +1031,8 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *streams, unsigned int min_refresh, - unsigned int max_refresh) + unsigned int max_refresh, + struct mod_freesync_caps *caps) { unsigned int index = 0; struct core_freesync *core_freesync; @@ -1030,7 +1045,10 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, index = map_index_from_stream(core_freesync, streams); state = &core_freesync->map[index].state; - if (min_refresh == 0 || max_refresh == 0) { + if (max_refresh == 0) + max_refresh = state->nominal_refresh_rate_in_micro_hz; + + if (min_refresh == 0) { /* Restore defaults */ calc_freesync_range(core_freesync, streams, state, core_freesync->map[index].caps-> @@ -1049,6 +1067,17 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, state->freesync_range.vmax); } + if (min_refresh != 0 && + dc_is_embedded_signal(streams->sink->sink_signal) && + (max_refresh - min_refresh >= 10000000)) { + caps->supported = true; + caps->min_refresh_in_micro_hz = min_refresh; + caps->max_refresh_in_micro_hz = max_refresh; + } + + /* Update the stream */ + update_stream(core_freesync, streams); + return true; } @@ -1115,8 +1144,8 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, core_freesync->dc, &stream, 1, &position.vertical_count, &position.nominal_vcount)) { - *nom_v_pos = position.vertical_count; - *v_pos = position.nominal_vcount; + *nom_v_pos = position.nominal_vcount; + *v_pos = position.vertical_count; return true; } @@ -1131,6 +1160,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, struct freesync_state *state; struct core_freesync *core_freesync = NULL; struct dc_static_screen_events triggers = {0}; + unsigned long long temp = 0; if (mod_freesync == NULL) return; @@ -1143,22 +1173,21 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, state = &core_freesync->map[map_index].state; + /* Update the field rate for new timing */ + temp = streams[stream_index]->timing.pix_clk_khz; + temp *= 1000ULL * 1000ULL * 1000ULL; + temp = div_u64(temp, + streams[stream_index]->timing.h_total); + temp = div_u64(temp, + streams[stream_index]->timing.v_total); + state->nominal_refresh_rate_in_micro_hz = + (unsigned int) temp; + if (core_freesync->map[map_index].caps->supported) { - /* Update the field rate for new timing */ - unsigned long long temp; - temp = streams[stream_index]->timing.pix_clk_khz; - temp *= 1000ULL * 1000ULL * 1000ULL; - temp = div_u64(temp, - streams[stream_index]->timing.h_total); - temp = div_u64(temp, - streams[stream_index]->timing.v_total); - state->nominal_refresh_rate_in_micro_hz = - (unsigned int) temp; /* Update the stream */ update_stream(core_freesync, streams[stream_index]); - /* Calculate vmin/vmax and refresh rate for * current mode */ diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 3947cc412ad7..f7f5a2cd7914 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -132,7 +132,8 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *streams, unsigned int min_refresh, - unsigned int max_refresh); + unsigned int max_refresh, + struct mod_freesync_caps *caps); bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *stream, -- GitLab From 909e8c9e417945f313b68ed6c5a559fe5266be8b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 5 Jun 2017 16:54:33 -0400 Subject: [PATCH 0529/2898] drm/amd/display: fix single link black screen Don't fall back to dual link DVI mode if the connector is single Link only. Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e4a6636fd829..b7f31b985b4f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1204,6 +1204,7 @@ bool resource_validate_attach_surfaces( /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 +#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 static void set_stream_engine_in_use( struct resource_context *res_ctx, @@ -1331,7 +1332,8 @@ static void update_stream_signal(struct core_stream *stream) } if (dc_is_dvi_signal(stream->signal)) { - if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ) + if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && + stream->public.sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; else stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; -- GitLab From a235bd9f1ea0c610a5cddfb79f98b651dc8dc5bd Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 5 Jun 2017 17:56:05 -0400 Subject: [PATCH 0530/2898] drm/amd/display: Add function to log connectivity Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/basics/log_helpers.c | 3 +++ drivers/gpu/drm/amd/display/dc/dm_helpers.h | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 01d04fa2419e..64db62e609eb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -322,6 +322,12 @@ bool dm_helpers_dp_mst_send_payload_allocation( return true; } +bool dm_helpers_dc_conn_log(struct dc_context*ctx, const char *msg) +{ + return true; +} + + bool dm_helpers_dp_mst_start_top_mgr( struct dc_context *ctx, const struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index c4eddee8de1b..1268be9ebaf3 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -26,6 +26,7 @@ #include "core_types.h" #include "logger.h" #include "include/logger_interface.h" +#include "dm_helpers.h" #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) @@ -94,6 +95,8 @@ void dc_conn_log(struct dc_context *ctx, dm_logger_append(&entry, "%2.2X ", hex_data[i]); dm_logger_append(&entry, "^\n"); + dm_helpers_dc_conn_log(ctx, entry.buf); dm_logger_close(&entry); + va_end(args); } diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index c15a25ce8049..9fb606c49217 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -68,6 +68,10 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot); +bool dm_helpers_dc_conn_log( + struct dc_context*ctx, + const char *msg); + void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, const struct dc_link *link); -- GitLab From 1bf56e62cc4fbff6d701b798da05a91f78aa12e9 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Fri, 2 Jun 2017 17:25:49 -0400 Subject: [PATCH 0531/2898] drm/amd/display: Call program_gamut explicitly instead of entire set_plane This fixes on boot crush on Vega, Polaris with Dal3. Signed-off-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +- .../display/dc/dce110/dce110_hw_sequencer.c | 42 +++++++++++++++++++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f5102b644942..657e10bae93f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -213,8 +213,7 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) == core_stream) { pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.set_plane_config(core_dc, pipes, - &core_dc->current_context->res_ctx); + core_dc->hwss.program_gamut_remap(pipes); ret = true; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7dd4b02b5938..616533e25534 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1894,6 +1894,47 @@ static void program_surface_visibility(const struct core_dc *dc, } +static void program_gamut_remap(struct pipe_ctx *pipe_ctx) +{ + struct xfm_grph_csc_adjustment adjust; + memset(&adjust, 0, sizeof(adjust)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + + if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + adjust.temperature_matrix[0] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[0]; + adjust.temperature_matrix[1] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[1]; + adjust.temperature_matrix[2] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[2]; + adjust.temperature_matrix[3] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[4]; + adjust.temperature_matrix[4] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[5]; + adjust.temperature_matrix[5] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[6]; + adjust.temperature_matrix[6] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[8]; + adjust.temperature_matrix[7] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[9]; + adjust.temperature_matrix[8] = + pipe_ctx->stream-> + public.gamut_remap_matrix.matrix[10]; + } + + pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); +} + /** * TODO REMOVE, USE UPDATE INSTEAD */ @@ -2509,6 +2550,7 @@ static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) } static const struct hw_sequencer_funcs dce110_funcs = { + .program_gamut_remap = program_gamut_remap, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 447f6bf4644c..107f82df3053 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1899,6 +1899,7 @@ static void set_plane_config( } static const struct hw_sequencer_funcs dcn10_funcs = { + .program_gamut_remap = program_gamut_remap, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index b53e1206dfb3..6f8733ec9b16 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,6 +67,9 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx); + void (*program_gamut_remap)( + struct pipe_ctx *pipe_ctx); + void (*update_plane_addr)( const struct core_dc *dc, struct pipe_ctx *pipe_ctx); -- GitLab From ba326a9185f1c56d86e51dd89589e4eff42f02eb Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 2 Jun 2017 19:01:37 -0400 Subject: [PATCH 0532/2898] drm/amd/display: propagate surface alpha setting from OS to DC Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++++- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 ++++------ 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 657e10bae93f..fb5bacb50ebc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -998,6 +998,7 @@ bool dc_commit_surfaces_to_stream( plane_info[i].stereo_format = new_surfaces[i]->stereo_format; plane_info[i].tiling_info = new_surfaces[i]->tiling_info; plane_info[i].visible = new_surfaces[i]->visible; + plane_info[i].per_pixel_alpha = new_surfaces[i]->per_pixel_alpha; plane_info[i].dcc = new_surfaces[i]->dcc; scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; scaling_info[i].src_rect = new_surfaces[i]->src_rect; @@ -1068,7 +1069,7 @@ static enum surface_update_type get_plane_info_update_type( const struct dc_surface_update *u, int surface_index) { - struct dc_plane_info temp_plane_info = { { { { 0 } } } }; + struct dc_plane_info temp_plane_info = { 0 }; if (!u->plane_info) return UPDATE_TYPE_FAST; @@ -1091,6 +1092,7 @@ static enum surface_update_type get_plane_info_update_type( /* Special Validation parameters */ temp_plane_info.format = u->plane_info->format; + temp_plane_info.per_pixel_alpha = u->plane_info->per_pixel_alpha; if (surface_index == 0) temp_plane_info.visible = u->plane_info->visible; @@ -1327,6 +1329,8 @@ void dc_update_surfaces_and_stream(struct dc *dc, srf_updates[i].plane_info->tiling_info; surface->public.visible = srf_updates[i].plane_info->visible; + surface->public.per_pixel_alpha = + srf_updates[i].plane_info->per_pixel_alpha; surface->public.dcc = srf_updates[i].plane_info->dcc; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index ee840e75ee1f..c60b59f41693 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -221,10 +221,12 @@ void update_surface_trace( SURFACE_TRACE( "plane_info->tiling_info.gfx8.pipe_config = %d;\n" "plane_info->tiling_info.gfx8.array_mode = %d;\n" - "plane_info->visible = %d;\n", + "plane_info->visible = %d;\n" + "plane_info->per_pixel_alpha = %d;\n", update->plane_info->tiling_info.gfx8.pipe_config, update->plane_info->tiling_info.gfx8.array_mode, - update->plane_info->visible); + update->plane_info->visible, + update->plane_info->per_pixel_alpha); SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", update->plane_info->tiling_info.gfx9.swizzle); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a20ba01d9e7b..7191b2519334 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -290,6 +290,7 @@ struct dc_transfer_func { }; struct dc_surface { + bool per_pixel_alpha; bool visible; bool flip_immediate; struct dc_plane_address address; @@ -316,6 +317,7 @@ struct dc_surface { }; struct dc_plane_info { + bool per_pixel_alpha; union plane_size plane_size; union dc_tiling_info tiling_info; struct dc_plane_dcc_param dcc; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 06354c36c499..5269796b2a8e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -97,7 +97,7 @@ struct dc_context { #define MAX_EDID_BUFFER_SIZE 512 #define EDID_BLOCK_SIZE 128 -#define MAX_SURFACE_NUM 2 +#define MAX_SURFACE_NUM 4 #define NUM_PIXEL_FORMATS 10 #include "dc_ddc_types.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 107f82df3053..0a346aafacce 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1559,7 +1559,9 @@ static void update_dchubp_dpp( struct pipe_ctx *temp_pipe; int i; int tree_pos = 0; + bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; + /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ enable_dppclk( dc->ctx, @@ -1604,11 +1606,7 @@ static void update_dchubp_dpp( /* TODO: build stream pipes group id. For now, use stream otg * id as pipe group id */ - /*pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->surface->public.per_pixel_alpha;*/ - if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) - pipe_ctx->scl_data.lb_params.alpha_en = 1; - else - pipe_ctx->scl_data.lb_params.alpha_en = 0; + pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->mpc_idx = pipe_ctx->tg->inst; tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; if (tree_cfg->num_pipes == 0) { @@ -1625,7 +1623,7 @@ static void update_dchubp_dpp( tree_cfg->dpp[tree_pos] = pipe_ctx->pipe_idx; tree_cfg->mpcc[tree_pos] = pipe_ctx->pipe_idx; - tree_cfg->per_pixel_alpha[tree_pos] = pipe_ctx->scl_data.lb_params.alpha_en; + tree_cfg->per_pixel_alpha[tree_pos] = per_pixel_alpha; tree_cfg->num_pipes = tree_pos + 1; dcn10_set_mpc_tree(mpc, tree_cfg); -- GitLab From fea0f581ab529e194d424452a6f7ecd88c5a2116 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 6 Jun 2017 16:30:51 -0400 Subject: [PATCH 0533/2898] drm/amd/display: Temporary disable BTR FreeSync support for now Reduce timer tick interval for the static screen Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/freesync/freesync.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index f79c47951f90..7109742bd67c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -436,11 +436,14 @@ static void calc_freesync_range(struct core_freesync *core_freesync, } /* Determine whether BTR can be supported */ - if (max_frame_duration_in_ns >= - 2 * min_frame_duration_in_ns) - core_freesync->map[index].caps->btr_supported = true; - else - core_freesync->map[index].caps->btr_supported = false; + //if (max_frame_duration_in_ns >= + // 2 * min_frame_duration_in_ns) + // core_freesync->map[index].caps->btr_supported = true; + //else + // core_freesync->map[index].caps->btr_supported = false; + + /* Temp, keep btr disabled */ + core_freesync->map[index].caps->btr_supported = false; /* Cache the time variables */ state->time.max_render_time_in_us = -- GitLab From 2f1e8efd10315c516f07ed80484be8a1de143a8d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 6 Jun 2017 16:41:00 -0400 Subject: [PATCH 0534/2898] drm/amd/display: Use surface update inuse for pending check. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_mem_input.c | 10 ++++++ .../amd/display/dc/dcn10/dcn10_mem_input.h | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 3e3fcf2395ae..8ad70625a746 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -821,13 +821,23 @@ bool mem_input_is_flip_pending(struct mem_input *mem_input) { uint32_t update_pending = 0; struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dc_plane_address earliest_inuse_address; REG_GET(DCSURF_FLIP_CONTROL, SURFACE_UPDATE_PENDING, &update_pending); + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, + SURFACE_EARLIEST_INUSE_ADDRESS, &earliest_inuse_address.grph.addr.low_part); + + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, + SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &earliest_inuse_address.grph.addr.high_part); + if (update_pending) return true; + if (earliest_inuse_address.grph.addr.quad_part != mem_input->request_address.grph.addr.quad_part) + return true; + mem_input->current_address = mem_input->request_address; return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 37683d072b42..9e2f1bb69958 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -52,6 +52,14 @@ SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id),\ SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id),\ SRI(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_INUSE_HIGH_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_C, HUBPREQ, id),\ + SRI(DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, HUBPREQ, id),\ SRI(DCSURF_SURFACE_CONTROL, HUBPREQ, id),\ SRI(HUBPRET_CONTROL, HUBPRET, id),\ SRI(DCN_EXPANSION_MODE, HUBPREQ, id),\ @@ -165,6 +173,14 @@ struct dcn_mi_registers { uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_C; uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C; uint32_t DCSURF_PRIMARY_META_SURFACE_ADDRESS_C; + uint32_t DCSURF_SURFACE_INUSE; + uint32_t DCSURF_SURFACE_INUSE_HIGH; + uint32_t DCSURF_SURFACE_INUSE_C; + uint32_t DCSURF_SURFACE_INUSE_HIGH_C; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_C; + uint32_t DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C; uint32_t DCSURF_SURFACE_CONTROL; uint32_t HUBPRET_CONTROL; uint32_t DCN_EXPANSION_MODE; @@ -297,6 +313,14 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE, SURFACE_INUSE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH, SURFACE_INUSE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_C, SURFACE_INUSE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH_C, SURFACE_INUSE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ @@ -433,6 +457,14 @@ struct dcn_mi_registers { type PRIMARY_SURFACE_ADDRESS_C;\ type PRIMARY_META_SURFACE_ADDRESS_HIGH_C;\ type PRIMARY_META_SURFACE_ADDRESS_C;\ + type SURFACE_INUSE_ADDRESS;\ + type SURFACE_INUSE_ADDRESS_HIGH;\ + type SURFACE_INUSE_ADDRESS_C;\ + type SURFACE_INUSE_ADDRESS_HIGH_C;\ + type SURFACE_EARLIEST_INUSE_ADDRESS;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_C;\ + type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C;\ type PRIMARY_SURFACE_DCC_EN;\ type PRIMARY_SURFACE_DCC_IND_64B_BLK;\ type DET_BUF_PLANE1_BASE_ADDRESS;\ -- GitLab From 11589813e6dfd72093d0e7f53114d6478f689d91 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 7 Jun 2017 15:02:34 -0400 Subject: [PATCH 0535/2898] drm/amd/display: fix enable_optc_clock reg_wait timeouts Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 8 +++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 8 ++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index a950dd53bca4..87fd5b9c8a16 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -135,6 +135,9 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t reg_val; int i; + if (ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) + time_out_num_tries *= 20; + for (i = 0; i <= time_out_num_tries; i++) { if (i) { if (0 < delay_between_poll_us && delay_between_poll_us < 1000) @@ -152,7 +155,10 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, return reg_val; } - DC_ERR("REG_WAIT timeout %dus * %d tries - %s\n", + dm_error("REG_WAIT timeout %dus * %d tries - %s\n", delay_between_poll_us, time_out_num_tries, func_name); + if (ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + BREAK_TO_DEBUGGER(); + return reg_val; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index d7072132d456..c5a636c750fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -449,7 +449,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 1, - 20000, 200000); + 2000, 500); /* Enable clock */ REG_UPDATE(OTG_CLOCK_CONTROL, @@ -457,7 +457,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 1, - 20000, 200000); + 2000, 500); } else { REG_UPDATE_2(OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, 0, @@ -465,7 +465,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 0, - 20000, 200000); + 2000, 500); REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, 0, @@ -473,7 +473,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 0, - 20000, 200000); + 2000, 500); } } -- GitLab From c9742685c24acd6d71cdda3067bfc2f512fe2b7c Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 7 Jun 2017 13:53:30 -0400 Subject: [PATCH 0536/2898] drm/amd/display: add bw logging for dcn Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 138 ++++++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- .../gpu/drm/amd/display/dc/core/dc_debug.c | 38 +++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 260 ++++++++++++++---- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 + .../amd/display/include/logger_interface.h | 4 + 7 files changed, 398 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6d8bc6c74a73..f0f688b99d37 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1312,6 +1312,144 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) { kernel_fpu_begin(); + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "sr_exit_time: %d ns\n" + "sr_enter_plus_exit_time: %d ns\n" + "urgent_latency: %d ns\n" + "write_back_latency: %d ns\n" + "percent_of_ideal_drambw_received_after_urg_latency: %d %\n" + "max_request_size: %d bytes\n" + "dcfclkv_max0p9: %d kHz\n" + "dcfclkv_nom0p8: %d kHz\n" + "dcfclkv_mid0p72: %d kHz\n" + "dcfclkv_min0p65: %d kHz\n" + "max_dispclk_vmax0p9: %d kHz\n" + "max_dispclk_vnom0p8: %d kHz\n" + "max_dispclk_vmid0p72: %d kHz\n" + "max_dispclk_vmin0p65: %d kHz\n" + "max_dppclk_vmax0p9: %d kHz\n" + "max_dppclk_vnom0p8: %d kHz\n" + "max_dppclk_vmid0p72: %d kHz\n" + "max_dppclk_vmin0p65: %d kHz\n" + "socclk: %d kHz\n" + "fabric_and_dram_bandwidth_vmax0p9: %d MB/s\n" + "fabric_and_dram_bandwidth_vnom0p8: %d MB/s\n" + "fabric_and_dram_bandwidth_vmid0p72: %d MB/s\n" + "fabric_and_dram_bandwidth_vmin0p65: %d MB/s\n" + "phyclkv_max0p9: %d kHz\n" + "phyclkv_nom0p8: %d kHz\n" + "phyclkv_mid0p72: %d kHz\n" + "phyclkv_min0p65: %d kHz\n" + "downspreading: %d %\n" + "round_trip_ping_latency_cycles: %d DCFCLK Cycles\n" + "urgent_out_of_order_return_per_channel: %d Bytes\n" + "number_of_channels: %d\n" + "vmm_page_size: %d Bytes\n" + "dram_clock_change_latency: %d ns\n" + "return_bus_width: %d Bytes\n", + dc->dcn_soc.sr_exit_time * 1000, + dc->dcn_soc.sr_enter_plus_exit_time * 1000, + dc->dcn_soc.urgent_latency * 1000, + dc->dcn_soc.write_back_latency * 1000, + dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency, + dc->dcn_soc.max_request_size, + dc->dcn_soc.dcfclkv_max0p9 * 1000, + dc->dcn_soc.dcfclkv_nom0p8 * 1000, + dc->dcn_soc.dcfclkv_mid0p72 * 1000, + dc->dcn_soc.dcfclkv_min0p65 * 1000, + dc->dcn_soc.max_dispclk_vmax0p9 * 1000, + dc->dcn_soc.max_dispclk_vnom0p8 * 1000, + dc->dcn_soc.max_dispclk_vmid0p72 * 1000, + dc->dcn_soc.max_dispclk_vmin0p65 * 1000, + dc->dcn_soc.max_dppclk_vmax0p9 * 1000, + dc->dcn_soc.max_dppclk_vnom0p8 * 1000, + dc->dcn_soc.max_dppclk_vmid0p72 * 1000, + dc->dcn_soc.max_dppclk_vmin0p65 * 1000, + dc->dcn_soc.socclk * 1000, + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000, + dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000, + dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 * 1000, + dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000, + dc->dcn_soc.phyclkv_max0p9 * 1000, + dc->dcn_soc.phyclkv_nom0p8 * 1000, + dc->dcn_soc.phyclkv_mid0p72 * 1000, + dc->dcn_soc.phyclkv_min0p65 * 1000, + dc->dcn_soc.downspreading * 100, + dc->dcn_soc.round_trip_ping_latency_cycles, + dc->dcn_soc.urgent_out_of_order_return_per_channel, + dc->dcn_soc.number_of_channels, + dc->dcn_soc.vmm_page_size, + dc->dcn_soc.dram_clock_change_latency * 1000, + dc->dcn_soc.return_bus_width); + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "rob_buffer_size_in_kbyte: %d\n" + "det_buffer_size_in_kbyte: %d\n" + "dpp_output_buffer_pixels: %d\n" + "opp_output_buffer_lines: %d\n" + "pixel_chunk_size_in_kbyte: %d\n" + "pte_enable: %d\n" + "pte_chunk_size: %d kbytes\n" + "meta_chunk_size: %d kbytes\n" + "writeback_chunk_size: %d kbytes\n" + "odm_capability: %d\n" + "dsc_capability: %d\n" + "line_buffer_size: %d bits\n" + "max_line_buffer_lines: %d\n" + "is_line_buffer_bpp_fixed: %d\n" + "line_buffer_fixed_bpp: %d\n" + "writeback_luma_buffer_size: %d kbytes\n" + "writeback_chroma_buffer_size: %d kbytes\n" + "max_num_dpp: %d\n" + "max_num_writeback: %d\n" + "max_dchub_topscl_throughput: %d pixels/dppclk\n" + "max_pscl_tolb_throughput: %d pixels/dppclk\n" + "max_lb_tovscl_throughput: %d pixels/dppclk\n" + "max_vscl_tohscl_throughput: %d pixels/dppclk\n" + "max_hscl_ratio: %d\n" + "max_vscl_ratio: %d\n" + "max_hscl_taps: %d\n" + "max_vscl_taps: %d\n" + "pte_buffer_size_in_requests: %d\n" + "dispclk_ramping_margin: %d %\n" + "under_scan_factor: %d %\n" + "max_inter_dcn_tile_repeaters: %d\n" + "can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one: %d\n" + "bug_forcing_luma_and_chroma_request_to_same_size_fixed: %d\n" + "dcfclk_cstate_latency: %d\n", + dc->dcn_ip.rob_buffer_size_in_kbyte, + dc->dcn_ip.det_buffer_size_in_kbyte, + dc->dcn_ip.dpp_output_buffer_pixels, + dc->dcn_ip.opp_output_buffer_lines, + dc->dcn_ip.pixel_chunk_size_in_kbyte, + dc->dcn_ip.pte_enable, + dc->dcn_ip.pte_chunk_size, + dc->dcn_ip.meta_chunk_size, + dc->dcn_ip.writeback_chunk_size, + dc->dcn_ip.odm_capability, + dc->dcn_ip.dsc_capability, + dc->dcn_ip.line_buffer_size, + dc->dcn_ip.max_line_buffer_lines, + dc->dcn_ip.is_line_buffer_bpp_fixed, + dc->dcn_ip.line_buffer_fixed_bpp, + dc->dcn_ip.writeback_luma_buffer_size, + dc->dcn_ip.writeback_chroma_buffer_size, + dc->dcn_ip.max_num_dpp, + dc->dcn_ip.max_num_writeback, + dc->dcn_ip.max_dchub_topscl_throughput, + dc->dcn_ip.max_pscl_tolb_throughput, + dc->dcn_ip.max_lb_tovscl_throughput, + dc->dcn_ip.max_vscl_tohscl_throughput, + dc->dcn_ip.max_hscl_ratio, + dc->dcn_ip.max_vscl_ratio, + dc->dcn_ip.max_hscl_taps, + dc->dcn_ip.max_vscl_taps, + dc->dcn_ip.pte_buffer_size_in_requests, + dc->dcn_ip.dispclk_ramping_margin, + dc->dcn_ip.under_scan_factor * 100, + dc->dcn_ip.max_inter_dcn_tile_repeaters, + dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one, + dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed, + dc->dcn_ip.dcfclk_cstate_latency); dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc.socclk; dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc.socclk; dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc.socclk; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index fb5bacb50ebc..47870a640f37 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1379,8 +1379,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { BREAK_TO_DEBUGGER(); goto fail; - } else + } else { core_dc->hwss.set_bandwidth(core_dc, context, false); + context_clock_trace(dc, context); + } } if (!surface_count) /* reset */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index c60b59f41693..ad556e9b0754 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -29,6 +29,13 @@ ##__VA_ARGS__); \ } while (0) +#define CLOCK_TRACE(...) do {\ + if (dc->debug.clock_trace) \ + dm_logger_write(logger, \ + LOG_BANDWIDTH_CALCS, \ + ##__VA_ARGS__); \ +} while (0) + void pre_surface_trace( const struct dc *dc, const struct dc_surface *const *surfaces, @@ -314,3 +321,34 @@ void context_timing_trace( h_pos[i], v_pos[i]); } } + +void context_clock_trace( + const struct dc *dc, + struct validate_context *context) +{ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dal_logger *logger = core_dc->ctx->logger; + + CLOCK_TRACE("Current: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n" + "dcfclk_deep_sleep_khz:%d fclk_khz:%d\n" + "dram_ccm_us:%d min_active_dram_ccm_us:%d\n", + context->bw.dcn.calc_clk.dispclk_khz, + context->bw.dcn.calc_clk.dppclk_div, + context->bw.dcn.calc_clk.dcfclk_khz, + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz, + context->bw.dcn.calc_clk.fclk_khz, + context->bw.dcn.calc_clk.dram_ccm_us, + context->bw.dcn.calc_clk.min_active_dram_ccm_us); + CLOCK_TRACE("Calculated: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n" + "dcfclk_deep_sleep_khz:%d fclk_khz:%d\n" + "dram_ccm_us:%d min_active_dram_ccm_us:%d\n", + context->bw.dcn.calc_clk.dispclk_khz, + context->bw.dcn.calc_clk.dppclk_div, + context->bw.dcn.calc_clk.dcfclk_khz, + context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz, + context->bw.dcn.calc_clk.fclk_khz, + context->bw.dcn.calc_clk.dram_ccm_us, + context->bw.dcn.calc_clk.min_active_dram_ccm_us); +#endif +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7191b2519334..e08e532cafb8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -160,6 +160,7 @@ struct dc_debug { bool max_disp_clk; bool surface_trace; bool timing_trace; + bool clock_trace; bool validation_trace; bool disable_stutter; bool disable_dcc; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 0a346aafacce..93a34e2ef175 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1412,6 +1412,128 @@ static void dcn10_enable_timing_synchronization( DC_SYNC_INFO("Sync complete\n"); } +static void print_rq_dlg_ttu( + struct core_dc *core_dc, + struct pipe_ctx *pipe_ctx) +{ + dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== DML TTU Output parameters [%d] ==============\n" + "qos_level_low_wm: %d, \n" + "qos_level_high_wm: %d, \n" + "min_ttu_vblank: %d, \n" + "qos_level_flip: %d, \n" + "refcyc_per_req_delivery_l: %d, \n" + "qos_level_fixed_l: %d, \n" + "qos_ramp_disable_l: %d, \n" + "refcyc_per_req_delivery_pre_l: %d, \n" + "refcyc_per_req_delivery_c: %d, \n" + "qos_level_fixed_c: %d, \n" + "qos_ramp_disable_c: %d, \n" + "refcyc_per_req_delivery_pre_c: %d\n" + "=============================================================\n", + pipe_ctx->pipe_idx, + pipe_ctx->ttu_regs.qos_level_low_wm, + pipe_ctx->ttu_regs.qos_level_high_wm, + pipe_ctx->ttu_regs.min_ttu_vblank, + pipe_ctx->ttu_regs.qos_level_flip, + pipe_ctx->ttu_regs.refcyc_per_req_delivery_l, + pipe_ctx->ttu_regs.qos_level_fixed_l, + pipe_ctx->ttu_regs.qos_ramp_disable_l, + pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_l, + pipe_ctx->ttu_regs.refcyc_per_req_delivery_c, + pipe_ctx->ttu_regs.qos_level_fixed_c, + pipe_ctx->ttu_regs.qos_ramp_disable_c, + pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c + ); + + dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== DML DLG Output parameters [%d] ==============\n" + "refcyc_h_blank_end: %d, \n" + "dlg_vblank_end: %d, \n" + "min_dst_y_next_start: %d, \n" + "refcyc_per_htotal: %d, \n" + "refcyc_x_after_scaler: %d, \n" + "dst_y_after_scaler: %d, \n" + "dst_y_prefetch: %d, \n" + "dst_y_per_vm_vblank: %d, \n" + "dst_y_per_row_vblank: %d, \n" + "ref_freq_to_pix_freq: %d, \n" + "vratio_prefetch: %d, \n" + "refcyc_per_pte_group_vblank_l: %d, \n" + "refcyc_per_meta_chunk_vblank_l: %d, \n" + "dst_y_per_pte_row_nom_l: %d, \n" + "refcyc_per_pte_group_nom_l: %d, \n", + pipe_ctx->pipe_idx, + pipe_ctx->dlg_regs.refcyc_h_blank_end, + pipe_ctx->dlg_regs.dlg_vblank_end, + pipe_ctx->dlg_regs.min_dst_y_next_start, + pipe_ctx->dlg_regs.refcyc_per_htotal, + pipe_ctx->dlg_regs.refcyc_x_after_scaler, + pipe_ctx->dlg_regs.dst_y_after_scaler, + pipe_ctx->dlg_regs.dst_y_prefetch, + pipe_ctx->dlg_regs.dst_y_per_vm_vblank, + pipe_ctx->dlg_regs.dst_y_per_row_vblank, + pipe_ctx->dlg_regs.ref_freq_to_pix_freq, + pipe_ctx->dlg_regs.vratio_prefetch, + pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_l, + pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_l, + pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_l, + pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l + ); + + dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\ndst_y_per_meta_row_nom_l: %d, \n" + "refcyc_per_meta_chunk_nom_l: %d, \n" + "refcyc_per_line_delivery_pre_l: %d, \n" + "refcyc_per_line_delivery_l: %d, \n" + "vratio_prefetch_c: %d, \n" + "refcyc_per_pte_group_vblank_c: %d, \n" + "refcyc_per_meta_chunk_vblank_c: %d, \n" + "dst_y_per_pte_row_nom_c: %d, \n" + "refcyc_per_pte_group_nom_c: %d, \n" + "dst_y_per_meta_row_nom_c: %d, \n" + "refcyc_per_meta_chunk_nom_c: %d, \n" + "refcyc_per_line_delivery_pre_c: %d, \n" + "refcyc_per_line_delivery_c: %d \n" + "========================================================\n", + pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_l, + pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_l, + pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_l, + pipe_ctx->dlg_regs.refcyc_per_line_delivery_l, + pipe_ctx->dlg_regs.vratio_prefetch_c, + pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_c, + pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_c, + pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_c, + pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_c, + pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_c, + pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_c, + pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_c, + pipe_ctx->dlg_regs.refcyc_per_line_delivery_c + ); + + dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== DML RQ Output parameters [%d] ==============\n" + "chunk_size: %d \n" + "min_chunk_size: %d \n" + "meta_chunk_size: %d \n" + "min_meta_chunk_size: %d \n" + "dpte_group_size: %d \n" + "mpte_group_size: %d \n" + "swath_height: %d \n" + "pte_row_height_linear: %d \n" + "========================================================\n", + pipe_ctx->pipe_idx, + pipe_ctx->rq_regs.rq_regs_l.chunk_size, + pipe_ctx->rq_regs.rq_regs_l.min_chunk_size, + pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size, + pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size, + pipe_ctx->rq_regs.rq_regs_l.dpte_group_size, + pipe_ctx->rq_regs.rq_regs_l.mpte_group_size, + pipe_ctx->rq_regs.rq_regs_l.swath_height, + pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear + ); +} + static void dcn10_power_on_fe( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -1419,57 +1541,52 @@ static void dcn10_power_on_fe( { struct dc_surface *dc_surface = &pipe_ctx->surface->public; - /* power up DCHUP and DPP from pseudo code pipe_move.c */ - /*TODO: function: power_on_plane. If already power up, skip - */ - { - power_on_plane(dc->ctx, - pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + power_on_plane(dc->ctx, + pipe_ctx->pipe_idx, pipe_ctx->tg->inst); - /* enable DCFCLK current DCHUB */ - enable_dcfclk(dc->ctx, + /* enable DCFCLK current DCHUB */ + enable_dcfclk(dc->ctx, + pipe_ctx->pipe_idx, + pipe_ctx->pix_clk_params.requested_pix_clk, + context->bw.dcn.calc_clk.dppclk_div); + dc->current_context->bw.dcn.cur_clk.dppclk_div = + context->bw.dcn.calc_clk.dppclk_div; + context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; + + if (dc_surface) { + dm_logger_write(dc->ctx->logger, LOG_DC, + "Pipe:%d 0x%x: addr hi:0x%x, " + "addr low:0x%x, " + "src: %d, %d, %d," + " %d; dst: %d, %d, %d, %d;\n", pipe_ctx->pipe_idx, - pipe_ctx->pix_clk_params.requested_pix_clk, - context->bw.dcn.calc_clk.dppclk_div); - dc->current_context->bw.dcn.cur_clk.dppclk_div = - context->bw.dcn.calc_clk.dppclk_div; - context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; - - if (dc_surface) { - dm_logger_write(dc->ctx->logger, LOG_DC, - "Pipe:%d 0x%x: addr hi:0x%x, " - "addr low:0x%x, " - "src: %d, %d, %d," - " %d; dst: %d, %d, %d, %d;\n", - pipe_ctx->pipe_idx, - dc_surface, - dc_surface->address.grph.addr.high_part, - dc_surface->address.grph.addr.low_part, - dc_surface->src_rect.x, - dc_surface->src_rect.y, - dc_surface->src_rect.width, - dc_surface->src_rect.height, - dc_surface->dst_rect.x, - dc_surface->dst_rect.y, - dc_surface->dst_rect.width, - dc_surface->dst_rect.height); - - dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, - "Pipe %d: width, height, x, y\n" - "viewport:%d, %d, %d, %d\n" - "recout: %d, %d, %d, %d\n", - pipe_ctx->pipe_idx, - pipe_ctx->scl_data.viewport.width, - pipe_ctx->scl_data.viewport.height, - pipe_ctx->scl_data.viewport.x, - pipe_ctx->scl_data.viewport.y, - pipe_ctx->scl_data.recout.width, - pipe_ctx->scl_data.recout.height, - pipe_ctx->scl_data.recout.x, - pipe_ctx->scl_data.recout.y); - } + dc_surface, + dc_surface->address.grph.addr.high_part, + dc_surface->address.grph.addr.low_part, + dc_surface->src_rect.x, + dc_surface->src_rect.y, + dc_surface->src_rect.width, + dc_surface->src_rect.height, + dc_surface->dst_rect.x, + dc_surface->dst_rect.y, + dc_surface->dst_rect.width, + dc_surface->dst_rect.height); + + dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, + "Pipe %d: width, height, x, y\n" + "viewport:%d, %d, %d, %d\n" + "recout: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->scl_data.viewport.width, + pipe_ctx->scl_data.viewport.height, + pipe_ctx->scl_data.viewport.x, + pipe_ctx->scl_data.viewport.y, + pipe_ctx->scl_data.recout.width, + pipe_ctx->scl_data.recout.height, + pipe_ctx->scl_data.recout.x, + pipe_ctx->scl_data.recout.y); + print_rq_dlg_ttu(dc, pipe_ctx); } - } static void program_gamut_remap(struct pipe_ctx *pipe_ctx) @@ -1743,6 +1860,53 @@ static void dcn10_apply_ctx_for_surface( } } + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\n============== Watermark parameters ==============\n" + "a.urgent_ns: %d \n" + "a.cstate_enter_plus_exit: %d \n" + "a.cstate_exit: %d \n" + "a.pstate_change: %d \n" + "a.pte_meta_urgent: %d \n" + "b.urgent_ns: %d \n" + "b.cstate_enter_plus_exit: %d \n" + "b.cstate_exit: %d \n" + "b.pstate_change: %d \n" + "b.pte_meta_urgent: %d \n", + context->bw.dcn.watermarks.a.urgent_ns, + context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns, + context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns, + context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns, + context->bw.dcn.watermarks.a.pte_meta_urgent_ns, + context->bw.dcn.watermarks.b.urgent_ns, + context->bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns, + context->bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns, + context->bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns, + context->bw.dcn.watermarks.b.pte_meta_urgent_ns + ); + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, + "\nc.urgent_ns: %d \n" + "c.cstate_enter_plus_exit: %d \n" + "c.cstate_exit: %d \n" + "c.pstate_change: %d \n" + "c.pte_meta_urgent: %d \n" + "d.urgent_ns: %d \n" + "d.cstate_enter_plus_exit: %d \n" + "d.cstate_exit: %d \n" + "d.pstate_change: %d \n" + "d.pte_meta_urgent: %d \n" + "========================================================\n", + context->bw.dcn.watermarks.c.urgent_ns, + context->bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns, + context->bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns, + context->bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns, + context->bw.dcn.watermarks.c.pte_meta_urgent_ns, + context->bw.dcn.watermarks.d.urgent_ns, + context->bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns, + context->bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns, + context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns, + context->bw.dcn.watermarks.d.pte_meta_urgent_ns + ); + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index e527d10b3e1f..6ada9a262721 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -429,6 +429,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_dmcu = true, .force_abm_enable = false, .timing_trace = false, + .clock_trace = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -441,6 +442,7 @@ static const struct dc_debug debug_defaults_diags = { .disable_dmcu = true, .force_abm_enable = false, .timing_trace = true, + .clock_trace = true, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 08a6911d3a3a..b75c343f8680 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -32,6 +32,7 @@ struct dc_context; struct dc_link; struct dc_surface_update; struct resource_context; +struct validate_context; /* * @@ -90,6 +91,9 @@ void context_timing_trace( const struct dc *dc, struct resource_context *res_ctx); +void context_clock_trace( + const struct dc *dc, + struct validate_context *context); /* Any function which is empty or have incomplete implementation should be * marked by this macro. -- GitLab From 9edba5574d8253b739f4c78d880c80f94578859b Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Wed, 7 Jun 2017 12:23:59 -0500 Subject: [PATCH 0537/2898] drm/amd/display: RV stereo support HDMI frame pack and DP frame alternate in band Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 21 +- .../display/dc/dcn10/dcn10_timing_generator.c | 184 ++++++++---------- .../display/dc/dcn10/dcn10_timing_generator.h | 5 + .../amd/display/dc/inc/hw/timing_generator.h | 12 ++ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + 5 files changed, 124 insertions(+), 102 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e08e532cafb8..fb86808dd309 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -361,6 +361,7 @@ struct dc_surface_status { struct dc_plane_address requested_address; struct dc_plane_address current_address; bool is_flip_pending; + bool is_right_eye; }; /* @@ -476,7 +477,7 @@ struct dc_stream { const struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; - + enum view_3d_format view_format; /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ @@ -591,6 +592,15 @@ bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], uint8_t stream_count); +/* + * Enable stereo when commit_streams is not required, + * for example, frame alternate. + */ +bool dc_enable_stereo( + struct dc *dc, + struct validate_context *context, + const struct dc_stream *streams[], + uint8_t stream_count); /** * Create a new default stream for the requested sink @@ -777,6 +787,14 @@ struct dc_container_id { unsigned short productCode; }; +struct stereo_3d_features { + bool supported ; + bool allTimings ; + bool cloneMode ; + bool scaling ; + bool singleFrameSWPacked; +}; + /* * The sink structure contains EDID and other display device properties */ @@ -788,6 +806,7 @@ struct dc_sink { uint32_t dongle_max_pix_clk; bool converter_disable_audio; void *priv; + struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX]; }; void dc_sink_retain(const struct dc_sink *sink); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index c5a636c750fa..bc3934d75b46 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -78,112 +78,22 @@ static void dcn10_program_global_sync( VREADY_OFFSET, tg->dlg_otg_param.vready_offset); } -struct crtc_stereo_flags { - uint8_t PROGRAM_STEREO :1; - uint8_t PROGRAM_POLARITY :1; - uint8_t RIGHT_EYE_POLARITY :1; - uint8_t FRAME_PACKED :1; - uint8_t DISABLE_STEREO_DP_SYNC :1; -}; - -static void dcn10_enable_stereo(struct timing_generator *tg, - const struct crtc_stereo_flags *flags, - const struct dc_crtc_timing *timing) -{ - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - - uint32_t active_width = timing->h_addressable; - uint32_t space1_size = timing->v_total - timing->v_addressable; - - if (flags) { - uint32_t stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; - - if (flags->PROGRAM_STEREO) - REG_UPDATE_3(OTG_STEREO_CONTROL, - OTG_STEREO_EN, stereo_en, - OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, - OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); - - if (flags->PROGRAM_POLARITY) - REG_UPDATE(OTG_STEREO_CONTROL, - OTG_STEREO_EYE_FLAG_POLARITY, - flags->RIGHT_EYE_POLARITY == 0 ? 0:1); - - if (flags->DISABLE_STEREO_DP_SYNC) - REG_UPDATE(OTG_STEREO_CONTROL, - OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); - - if (flags->PROGRAM_STEREO && flags->FRAME_PACKED) - REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, - OTG_3D_STRUCTURE_EN, 1, - OTG_3D_STRUCTURE_V_UPDATE_MODE, 1, - OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1); - - } - - REG_UPDATE(OPPBUF_CONTROL, - OPPBUF_ACTIVE_WIDTH, active_width); - - REG_UPDATE(OPPBUF_3D_PARAMETERS_0, - OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); - - return; -} - static void dcn10_disable_stereo(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); REG_SET(OTG_STEREO_CONTROL, 0, - OTG_STEREO_EN, 0); + OTG_STEREO_EN, 0); REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0, - OTG_3D_STRUCTURE_EN, 0, - OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, - OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); + OTG_3D_STRUCTURE_EN, 0, + OTG_3D_STRUCTURE_V_UPDATE_MODE, 0, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); REG_UPDATE(OPPBUF_CONTROL, - OPPBUF_ACTIVE_WIDTH, 0); + OPPBUF_ACTIVE_WIDTH, 0); REG_UPDATE(OPPBUF_3D_PARAMETERS_0, - OPPBUF_3D_VACT_SPACE1_SIZE, 0); - return; -} - -static bool is_frame_alternate_stereo(enum dc_timing_3d_format fmt) -{ - bool ret = false; - if (fmt == TIMING_3D_FORMAT_FRAME_ALTERNATE || - fmt == TIMING_3D_FORMAT_INBAND_FA || - fmt == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || - fmt == TIMING_3D_FORMAT_SIDEBAND_FA) - ret = true; - return ret; -} - -static void dcn10_do_stereo(struct timing_generator *tg, - const struct dc_crtc_timing *dc_crtc_timing) -{ - struct crtc_stereo_flags stereo_flags = {0}; - if (dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_NONE || - dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || - dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) - dcn10_disable_stereo(tg); - else { - stereo_flags.PROGRAM_STEREO = 1; - stereo_flags.PROGRAM_POLARITY = 1; - stereo_flags.DISABLE_STEREO_DP_SYNC = 0; - stereo_flags.RIGHT_EYE_POLARITY = - dc_crtc_timing->flags.RIGHT_EYE_3D_POLARITY; - if (dc_crtc_timing->timing_3d_format == - TIMING_3D_FORMAT_HW_FRAME_PACKING) - stereo_flags.FRAME_PACKED = 1; - - if (is_frame_alternate_stereo( - dc_crtc_timing->timing_3d_format) || - dc_crtc_timing->timing_3d_format == - TIMING_3D_FORMAT_HW_FRAME_PACKING) - dcn10_enable_stereo(tg, &stereo_flags, dc_crtc_timing); - } + OPPBUF_3D_VACT_SPACE1_SIZE, 0); } /** @@ -361,9 +271,8 @@ static void tg_program_timing_generator( REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, h_div_2); - /* Enable crtc stereo frame pack tested... todo more - */ - dcn10_do_stereo(tg, &patched_crtc_timing); + dcn10_disable_stereo( tg); + } /** tg_program_blanking @@ -605,7 +514,8 @@ static bool tg_validate_timing( timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && - timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE) + timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && + timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) return false; /* Temporarily blocking interlacing mode until it's supported */ @@ -1145,6 +1055,76 @@ void dcn10_timing_generator_get_crtc_scanoutpos( *v_position = position.vertical_count; } + + +static void dcn10_enable_stereo(struct timing_generator *tg, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) +{ + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + uint32_t active_width = timing->h_addressable; + uint32_t space1_size = timing->v_total - timing->v_addressable; + + if (flags) { + uint32_t stereo_en; + stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; + + if (flags->PROGRAM_STEREO) + REG_UPDATE_3(OTG_STEREO_CONTROL, + OTG_STEREO_EN, stereo_en, + OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, + OTG_STEREO_SYNC_OUTPUT_POLARITY, 0); + + if (flags->PROGRAM_POLARITY) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_STEREO_EYE_FLAG_POLARITY, + flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); + + if (flags->DISABLE_STEREO_DP_SYNC) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); + + if (flags->PROGRAM_STEREO && flags->FRAME_PACKED) + REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, + OTG_3D_STRUCTURE_EN, 1, + OTG_3D_STRUCTURE_V_UPDATE_MODE, 1, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1); + + } + + REG_UPDATE(OPPBUF_CONTROL, + OPPBUF_ACTIVE_WIDTH, active_width); + + REG_UPDATE(OPPBUF_3D_PARAMETERS_0, + OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); +} + +static void dcn10_program_stereo(struct timing_generator *tg, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) +{ + if (flags->PROGRAM_STEREO) + dcn10_enable_stereo(tg, timing, flags); + else + dcn10_disable_stereo(tg); +} + + +static bool dcn10_is_stereo_left_eye(struct timing_generator *tg) +{ + bool ret = false; + uint32_t left_eye = 0; + struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + + REG_GET(OTG_STEREO_STATUS, + OTG_STEREO_CURRENT_EYE, &left_eye); + if (left_eye == 1) + ret = true; + else + ret = false; + + return ret; +} + static struct timing_generator_funcs dcn10_tg_funcs = { .validate_timing = tg_validate_timing, .program_timing = tg_program_timing, @@ -1183,7 +1163,9 @@ static struct timing_generator_funcs dcn10_tg_funcs = { .enable_optc_clock = enable_optc_clock, .set_drr = dcn10_timing_generator_set_drr, .set_static_screen_control = set_static_screen_control, - .set_test_pattern = dcn10_timing_generator_set_test_pattern + .set_test_pattern = dcn10_timing_generator_set_test_pattern, + .program_stereo = dcn10_program_stereo, + .is_stereo_left_eye = dcn10_is_stereo_left_eye }; void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 85a763af1956..c880fa587790 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -51,6 +51,7 @@ SRI(OTG_CONTROL, OTG, inst),\ SRI(OTG_STEREO_CONTROL, OTG, inst),\ SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_STATUS, OTG, inst),\ SRI(OTG_V_TOTAL_MAX, OTG, inst),\ SRI(OTG_V_TOTAL_MIN, OTG, inst),\ SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ @@ -96,6 +97,7 @@ struct dcn_tg_registers { uint32_t OTG_CONTROL; uint32_t OTG_STEREO_CONTROL; uint32_t OTG_3D_STRUCTURE_CONTROL; + uint32_t OTG_STEREO_STATUS; uint32_t OTG_V_TOTAL_MAX; uint32_t OTG_V_TOTAL_MIN; uint32_t OTG_V_TOTAL_CONTROL; @@ -157,6 +159,8 @@ struct dcn_tg_registers { SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ @@ -243,6 +247,7 @@ struct dcn_tg_registers { type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\ type OTG_STEREO_SYNC_OUTPUT_POLARITY;\ type OTG_STEREO_EYE_FLAG_POLARITY;\ + type OTG_STEREO_CURRENT_EYE;\ type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\ type OTG_3D_STRUCTURE_EN;\ type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 9f130affb31c..2b72d1d8012f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -100,6 +100,15 @@ struct _dlg_otg_param { enum signal_type signal; }; #endif + +struct crtc_stereo_flags { + uint8_t PROGRAM_STEREO : 1; + uint8_t PROGRAM_POLARITY : 1; + uint8_t RIGHT_EYE_POLARITY : 1; + uint8_t FRAME_PACKED : 1; + uint8_t DISABLE_STEREO_DP_SYNC : 1; +}; + struct timing_generator { const struct timing_generator_funcs *funcs; struct dc_bios *bp; @@ -171,6 +180,9 @@ struct timing_generator_funcs { void (*program_global_sync)(struct timing_generator *tg); void (*enable_optc_clock)(struct timing_generator *tg, bool enable); #endif + void (*program_stereo)(struct timing_generator *tg, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); + bool (*is_stereo_left_eye)(struct timing_generator *tg); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 6f8733ec9b16..52884815c67b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -143,6 +143,10 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, struct validate_context *context, struct core_dc *dc); + + void (*setup_stereo)( + struct pipe_ctx *pipe_ctx, + struct core_dc *dc); }; void color_space_to_black_color( -- GitLab From 4c6e75989e8edd2bf9c22a70b2a838547cc6c6f3 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 8 Jun 2017 14:26:40 -0400 Subject: [PATCH 0538/2898] drm/amd/display: disable dcc when reset front end. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 ++ .../drm/amd/display/dc/dcn10/dcn10_mem_input.c | 15 +++++++++++---- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 93a34e2ef175..f2b581faa9b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -825,6 +825,8 @@ static void reset_front_end_for_pipe( if (!pipe_ctx->surface) return; + pipe_ctx->mi->funcs->dcc_control(pipe_ctx->mi, false, false); + lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); /* TODO: build stream pipes group id. For now, use stream otg diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 8ad70625a746..a58993aa400f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -369,16 +369,22 @@ static bool mem_input_program_surface_flip_and_addr( return true; } -static void program_control(struct dcn10_mem_input *mi, - struct dc_plane_dcc_param *dcc) +static void dcc_control(struct mem_input *mem_input, bool enable, + bool independent_64b_blks) { - uint32_t dcc_en = dcc->enable ? 1 : 0; - uint32_t dcc_ind_64b_blk = dcc->grph.independent_64b_blks ? 1 : 0; + uint32_t dcc_en = enable ? 1 : 0; + uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); REG_UPDATE_2(DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, dcc_en, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); +} +static void program_control(struct dcn10_mem_input *mi, + struct dc_plane_dcc_param *dcc) +{ + dcc_control(&mi->base, dcc->enable, dcc->grph.independent_64b_blks); } static void mem_input_program_surface_config( @@ -1072,6 +1078,7 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_update_dchub = mem_input_update_dchub, .mem_input_program_pte_vm = dcn_mem_input_program_pte_vm, .set_blank = dcn_mi_set_blank, + .dcc_control = dcc_control, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index bd0dfeb2afa2..64b810d48d07 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -86,6 +86,9 @@ struct mem_input_funcs { struct _vcs_dpi_display_ttu_regs_st *ttu_regs, struct _vcs_dpi_display_rq_regs_st *rq_regs, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); + + void (*dcc_control)(struct mem_input *mem_input, bool enable, + bool independent_64b_blks); #endif void (*mem_input_program_display_marks)( -- GitLab From f0558542a72e72919dae2ac2187847ec312c2bcb Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 1 Jun 2017 18:35:54 -0400 Subject: [PATCH 0539/2898] drm/amd/display: redesign mpc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1 + .../gpu/drm/amd/display/dc/core/dc_resource.c | 10 +- drivers/gpu/drm/amd/display/dc/dc_helper.c | 10 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 105 ++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 336 ++++-------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 102 +++--- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 73 ++-- .../gpu/drm/amd/display/dc/inc/core_types.h | 12 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 81 +---- 9 files changed, 228 insertions(+), 502 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index f0f688b99d37..66f0595a4c20 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -517,6 +517,7 @@ static void split_stream_across_pipes( secondary_pipe->stream = primary_pipe->stream; secondary_pipe->tg = primary_pipe->tg; + secondary_pipe->mpcc = pool->mpcc[secondary_pipe->pipe_idx]; secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->xfm = pool->transforms[secondary_pipe->pipe_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index b7f31b985b4f..c51ec617eff7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1008,8 +1008,6 @@ static int acquire_first_split_pipe( if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - int mpc_idx = pipe_ctx->mpc_idx; - pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; if (pipe_ctx->bottom_pipe) pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; @@ -1021,8 +1019,8 @@ static int acquire_first_split_pipe( pipe_ctx->xfm = pool->transforms[i]; pipe_ctx->opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; + pipe_ctx->mpcc = pool->mpcc[i]; pipe_ctx->pipe_idx = i; - pipe_ctx->mpc_idx = mpc_idx; pipe_ctx->stream = stream; return i; @@ -1243,6 +1241,9 @@ static int acquire_first_free_pipe( if (!res_ctx->pipe_ctx[i].stream) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + pipe_ctx->mpcc = pool->mpcc[i]; +#endif pipe_ctx->tg = pool->timing_generators[i]; pipe_ctx->mi = pool->mis[i]; pipe_ctx->ipp = pool->ipps[i]; @@ -1251,9 +1252,6 @@ static int acquire_first_free_pipe( pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - pipe_ctx->mpc_idx = -1; -#endif pipe_ctx->stream = stream; return i; diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 87fd5b9c8a16..8ed1440d2b01 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -135,8 +135,11 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t reg_val; int i; - if (ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) - time_out_num_tries *= 20; + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { + /* 35 seconds */ + delay_between_poll_us = 35000; + time_out_num_tries = 1000; + } for (i = 0; i <= time_out_num_tries; i++) { if (i) { @@ -157,7 +160,8 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, dm_error("REG_WAIT timeout %dus * %d tries - %s\n", delay_between_poll_us, time_out_num_tries, func_name); - if (ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + + if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) BREAK_TO_DEBUGGER(); return reg_val; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f2b581faa9b7..f509dfd97f23 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -592,9 +592,19 @@ static void init_hw(struct core_dc *dc) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct timing_generator *tg = dc->res_pool->timing_generators[i]; + struct mpcc *mpcc = + dc->res_pool->mpcc[i]; + struct mpcc_cfg mpcc_cfg; + + lock_otg_master_update(dc->ctx, tg->inst); + mpcc_cfg.opp_id = 0xf; + mpcc_cfg.top_dpp_id = 0xf; + mpcc_cfg.bot_mpcc_id = 0xf; + mpcc_cfg.top_of_tree = true; + mpcc->funcs->set(mpcc, &mpcc_cfg); + unlock_otg_master(dc->ctx, tg->inst); tg->funcs->disable_vga(tg); - /* Blank controller using driver code instead of * command table. */ @@ -819,8 +829,7 @@ static void reset_front_end_for_pipe( struct pipe_ctx *pipe_ctx, struct validate_context *context) { - struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); - struct mpc_tree_cfg *tree_cfg = NULL; + struct mpcc_cfg mpcc_cfg; if (!pipe_ctx->surface) return; @@ -829,20 +838,14 @@ static void reset_front_end_for_pipe( lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); - /* TODO: build stream pipes group id. For now, use stream otg - * id as pipe group id - */ - tree_cfg = &dc->current_context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; - - if (!dcn10_remove_dpp(mpc, tree_cfg, pipe_ctx->pipe_idx)) { - dm_logger_write(dc->ctx->logger, LOG_RESOURCE, - "%s: failed to find dpp to be removed!\n", - __func__); - } + mpcc_cfg.opp_id = 0xf; + mpcc_cfg.top_dpp_id = 0xf; + mpcc_cfg.bot_mpcc_id = 0xf; + mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; + pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); pipe_ctx->top_pipe = NULL; pipe_ctx->bottom_pipe = NULL; - pipe_ctx->mpc_idx = -1; unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); @@ -850,8 +853,6 @@ static void reset_front_end_for_pipe( wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); - wait_mpcc_idle(mpc, pipe_ctx->pipe_idx); - disable_clocks(dc->ctx, pipe_ctx->pipe_idx); pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm); @@ -893,14 +894,10 @@ static void reset_hw_ctx_wrap( reset_hw_ctx(dc, context, reset_front_end_for_pipe); /* Reset Back End*/ reset_hw_ctx(dc, context, reset_back_end_for_pipe); - - memcpy(context->res_ctx.mpc_tree, - dc->current_context->res_ctx.mpc_tree, - sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); } -static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, - PHYSICAL_ADDRESS_LOC *addr) +static bool patch_address_for_sbs_tb_stereo( + struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { struct core_surface *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && @@ -1670,14 +1667,10 @@ static void update_dchubp_dpp( struct input_pixel_processor *ipp = pipe_ctx->ipp; struct core_surface *surface = pipe_ctx->surface; union plane_size size = surface->public.plane_size; - struct mpc_tree_cfg *tree_cfg = NULL; struct default_adjustment ocsc = {0}; - enum dc_color_space color_space; struct tg_color black_color = {0}; - struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); - struct pipe_ctx *temp_pipe; - int i; - int tree_pos = 0; + struct mpcc_cfg mpcc_cfg; + struct pipe_ctx *top_pipe; bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ @@ -1716,39 +1709,23 @@ static void update_dchubp_dpp( 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); - /* mpc TODO un-hardcode object ids - * for pseudo code pipe_move.c : - * add_plane_mpcc(added_plane_inst, mpcc_inst, ...); - * Do we want to cache the tree_cfg? - */ - - /* TODO: build stream pipes group id. For now, use stream otg - * id as pipe group id - */ pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; - pipe_ctx->mpc_idx = pipe_ctx->tg->inst; - tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; - if (tree_cfg->num_pipes == 0) { - tree_cfg->opp_id = pipe_ctx->tg->inst; - for (i = 0; i < MAX_PIPES; i++) { - tree_cfg->dpp[i] = 0xf; - tree_cfg->mpcc[i] = 0xf; - } - } - - for (temp_pipe = pipe_ctx->top_pipe; - temp_pipe != NULL; temp_pipe = temp_pipe->top_pipe) - tree_pos++; - - tree_cfg->dpp[tree_pos] = pipe_ctx->pipe_idx; - tree_cfg->mpcc[tree_pos] = pipe_ctx->pipe_idx; - tree_cfg->per_pixel_alpha[tree_pos] = per_pixel_alpha; - tree_cfg->num_pipes = tree_pos + 1; - dcn10_set_mpc_tree(mpc, tree_cfg); + for (top_pipe = pipe_ctx; top_pipe != NULL; top_pipe = top_pipe->top_pipe) + mpcc_cfg.opp_id = top_pipe->opp->inst; + mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx; + if (pipe_ctx->bottom_pipe) + mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst; + else + mpcc_cfg.bot_mpcc_id = 0xf; + mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; + mpcc_cfg.per_pixel_alpha = per_pixel_alpha; + if (!dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].surface) + pipe_ctx->mpcc->funcs->wait_for_idle(pipe_ctx->mpcc); + pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); - color_space = pipe_ctx->stream->public.output_color_space; - color_space_to_black_color(dc, color_space, &black_color); - dcn10_set_mpc_background_color(mpc, pipe_ctx->pipe_idx, &black_color); + color_space_to_black_color( + dc, pipe_ctx->stream->public.output_color_space, &black_color); + pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color); pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ @@ -1853,13 +1830,8 @@ static void dcn10_apply_ctx_for_surface( /* looking for top pipe to program */ - if (!pipe_ctx->top_pipe) { - memcpy(context->res_ctx.mpc_tree, - dc->current_context->res_ctx.mpc_tree, - sizeof(struct mpc_tree_cfg) * dc->res_pool->pipe_count); - + if (!pipe_ctx->top_pipe) program_all_pipe_in_tree(dc, pipe_ctx, context); - } } dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, @@ -1927,8 +1899,7 @@ static void dcn10_apply_ctx_for_surface( if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) - reset_front_end_for_pipe(dc, - old_pipe_ctx, dc->current_context); + reset_front_end_for_pipe(dc, old_pipe_ctx, dc->current_context); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 58f80114e36b..19af0ee86191 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -27,34 +27,26 @@ #include "dcn10_mpc.h" #define REG(reg)\ - mpc->mpc_regs->reg + mpcc10->mpcc_regs->reg #define CTX \ - mpc->base.ctx + mpcc10->base.ctx #undef FN #define FN(reg_name, field_name) \ - mpc->mpc_shift->field_name, mpc->mpc_mask->field_name + mpcc10->mpcc_shift->field_name, mpcc10->mpcc_mask->field_name #define MODE_TOP_ONLY 1 #define MODE_BLEND 3 +#define BLND_PP_ALPHA 0 +#define BLND_GLOBAL_ALPHA 2 -/* Internal function to set mpc output mux */ -static void set_output_mux(struct dcn10_mpc *mpc, - uint8_t opp_id, - uint8_t mpcc_id) -{ - if (mpcc_id != 0xf) - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], - OPP_PIPE_CLOCK_EN, 1); - - REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); -} -void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, - unsigned int mpcc_inst, - struct tg_color *bg_color) +void dcn10_mpcc_set_bg_color( + struct mpcc *mpcc, + struct tg_color *bg_color) { + struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); /* mpc color is 12 bit. tg_color is 10 bit */ /* todo: might want to use 16 bit to represent color and have each * hw block translate to correct color depth. @@ -63,277 +55,89 @@ void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, uint32_t bg_g_y = bg_color->color_g_y << 2; uint32_t bg_b_cb = bg_color->color_b_cb << 2; - REG_SET(MPCC_BG_R_CR[mpcc_inst], 0, + REG_SET(MPCC_BG_R_CR, 0, MPCC_BG_R_CR, bg_r_cr); - REG_SET(MPCC_BG_G_Y[mpcc_inst], 0, + REG_SET(MPCC_BG_G_Y, 0, MPCC_BG_G_Y, bg_g_y); - REG_SET(MPCC_BG_B_CB[mpcc_inst], 0, + REG_SET(MPCC_BG_B_CB, 0, MPCC_BG_B_CB, bg_b_cb); } -/* This function programs MPC tree configuration - * Assume it is the initial time to setup MPC tree_configure, means - * the instance of dpp/mpcc/opp specified in structure tree_cfg are - * in idle status. - * Before invoke this function, ensure that master lock of OPTC specified - * by opp_id is set. - * - * tree_cfg[in] - new MPC_TREE_CFG - */ - -void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg) +static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) { - int i; - - for (i = 0; i < tree_cfg->num_pipes; i++) { - uint8_t mpcc_inst = tree_cfg->mpcc[i]; - - REG_SET(MPCC_OPP_ID[mpcc_inst], 0, - MPCC_OPP_ID, tree_cfg->opp_id); - - REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, - MPCC_TOP_SEL, tree_cfg->dpp[i]); - - if (i == tree_cfg->num_pipes-1) { - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xF); - - REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, MODE_TOP_ONLY); - } else { - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, tree_cfg->dpp[i+1]); - - REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, MODE_BLEND); - } - - if (i == 0) - set_output_mux( - mpc, tree_cfg->opp_id, mpcc_inst); - - REG_UPDATE_2(MPCC_CONTROL[mpcc_inst], - MPCC_ALPHA_BLND_MODE, - tree_cfg->per_pixel_alpha[i] ? 0 : 2, - MPCC_ALPHA_MULTIPLIED_MODE, 0); - } + ASSERT(mpcc10->opp_id == 0xf || opp_id == mpcc10->opp_id); + mpcc10->opp_id = opp_id; + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); + REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); } -/* - * This is the function to remove current MPC tree specified by tree_cfg - * Before invoke this function, ensure that master lock of OPTC specified - * by opp_id is set. - * - *tree_cfg[in/out] - current MPC_TREE_CFG - */ -void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg) +static void reset_output_mux(struct dcn10_mpcc *mpcc10) { - int i; - - for (i = 0; i < tree_cfg->num_pipes; i++) { - uint8_t mpcc_inst = tree_cfg->mpcc[i]; - - REG_SET(MPCC_OPP_ID[mpcc_inst], 0, - MPCC_OPP_ID, 0xf); - - REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, - MPCC_TOP_SEL, 0xf); - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xF); - - /* add remove dpp/mpcc pair into pending list - * TODO FPGA AddToPendingList if empty from pseudo code - */ - tree_cfg->dpp[i] = 0xf; - tree_cfg->mpcc[i] = 0xf; - tree_cfg->per_pixel_alpha[i] = false; - } - set_output_mux(mpc, tree_cfg->opp_id, 0xf); - tree_cfg->opp_id = 0xf; - tree_cfg->num_pipes = 0; + REG_SET(MUX[mpcc10->opp_id], 0, MPC_OUT_MUX, 0xf); + REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->opp_id], OPP_PIPE_CLOCK_EN, 0); + mpcc10->opp_id = 0xf; } -/* TODO FPGA: how to handle DPP? - * Function to remove one of pipe from MPC configure tree by dpp idx - * Before invoke this function, ensure that master lock of OPTC specified - * by opp_id is set - * This function can be invoke multiple times to remove more than 1 dpps. - * - * tree_cfg[in/out] - current MPC_TREE_CFG - * idx[in] - index of dpp from tree_cfg to be removed. - */ -bool dcn10_remove_dpp(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - uint8_t idx) +static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) { - int i; - uint8_t mpcc_inst; - bool found = false; - - /* find dpp_idx from dpp array of tree_cfg */ - for (i = 0; i < tree_cfg->num_pipes; i++) { - if (tree_cfg->dpp[i] == idx) { - found = true; - break; - } - } - - if (!found) { - BREAK_TO_DEBUGGER(); - return false; - } - mpcc_inst = tree_cfg->mpcc[i]; - - REG_SET(MPCC_OPP_ID[mpcc_inst], 0, - MPCC_OPP_ID, 0xf); - - REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, - MPCC_TOP_SEL, 0xf); - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xf); - - if (i == 0) { - if (tree_cfg->num_pipes > 1) - set_output_mux(mpc, - tree_cfg->opp_id, tree_cfg->mpcc[i+1]); + struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); + int alpha_blnd_mode = cfg->per_pixel_alpha ? + BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; + int mpcc_mode = cfg->bot_mpcc_id != 0xf ? + MODE_BLEND : MODE_TOP_ONLY; + + REG_SET(MPCC_OPP_ID, 0, + MPCC_OPP_ID, cfg->opp_id); + + REG_SET(MPCC_TOP_SEL, 0, + MPCC_TOP_SEL, cfg->top_dpp_id); + + REG_SET(MPCC_BOT_SEL, 0, + MPCC_BOT_SEL, cfg->bot_mpcc_id); + + REG_SET_4(MPCC_CONTROL, 0xffffffff, + MPCC_MODE, mpcc_mode, + MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, + MPCC_ALPHA_MULTIPLIED_MODE, 0/*TODO: cfg->per_pixel_alpha*/, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, cfg->top_of_tree); + + if (cfg->top_of_tree) { + if (cfg->opp_id != 0xf) + set_output_mux(mpcc10, cfg->opp_id, mpcc->inst); else - set_output_mux(mpc, tree_cfg->opp_id, 0xf); - } else if (i == tree_cfg->num_pipes-1) { - mpcc_inst = tree_cfg->mpcc[i - 1]; - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, 0xF); - - /* prev mpc is now last, set to top only*/ - REG_UPDATE(MPCC_CONTROL[mpcc_inst], - MPCC_MODE, MODE_TOP_ONLY); - } else { - mpcc_inst = tree_cfg->mpcc[i - 1]; - - REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, - MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); + reset_output_mux(mpcc10); } - - /* update tree_cfg structure */ - while (i < tree_cfg->num_pipes - 1) { - tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; - tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; - tree_cfg->per_pixel_alpha[i] = tree_cfg->per_pixel_alpha[i+1]; - i++; - } - tree_cfg->num_pipes--; - - return true; } -/* TODO FPGA: how to handle DPP? - * Function to add DPP/MPCC pair into MPC configure tree by position. - * Before invoke this function, ensure that master lock of OPTC specified - * by opp_id is set - * This function can be invoke multiple times to add more than 1 pipes. - * - * tree_cfg[in/out] - current MPC_TREE_CFG - * dpp_idx[in] - index of an idle dpp insatnce to be added. - * mpcc_idx[in] - index of an idle mpcc instance to be added. - * poistion[in] - position of dpp/mpcc pair to be added into current tree_cfg - * 0 means insert to the most top layer of MPC tree - */ -void dcn10_add_dpp(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - uint8_t dpp_idx, - uint8_t mpcc_idx, - uint8_t per_pixel_alpha, - uint8_t position) +static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) { - uint8_t prev; - uint8_t next; - - REG_SET(MPCC_OPP_ID[mpcc_idx], 0, - MPCC_OPP_ID, tree_cfg->opp_id); - REG_SET(MPCC_TOP_SEL[mpcc_idx], 0, - MPCC_TOP_SEL, dpp_idx); - - if (position == 0) { - /* idle dpp/mpcc is added to the top layer of tree */ - REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, - MPCC_BOT_SEL, tree_cfg->mpcc[0]); + struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); - /* bottom mpc is always top only */ - REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, MODE_TOP_ONLY); - /* opp will get new output. from new added mpcc */ - set_output_mux(mpc, tree_cfg->opp_id, mpcc_idx); - - } else if (position == tree_cfg->num_pipes) { - /* idle dpp/mpcc is added to the bottom layer of tree */ - - /* get instance of previous bottom mpcc, set to middle layer */ - prev = tree_cfg->mpcc[position - 1]; - - REG_SET(MPCC_BOT_SEL[prev], 0, - MPCC_BOT_SEL, mpcc_idx); - - /* all mpcs other than bottom need to blend */ - REG_UPDATE(MPCC_CONTROL[prev], - MPCC_MODE, MODE_BLEND); - - /* mpcc_idx become new bottom mpcc*/ - REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, - MPCC_BOT_SEL, 0xf); - - /* bottom mpc is always top only */ - REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, MODE_TOP_ONLY); - } else { - /* idle dpp/mpcc is added to middle of tree */ - prev = tree_cfg->mpcc[position - 1]; /* mpc a */ - next = tree_cfg->mpcc[position]; /* mpc b */ - - /* connect mpc inserted below mpc a*/ - REG_SET(MPCC_BOT_SEL[prev], 0, - MPCC_BOT_SEL, mpcc_idx); + REG_WAIT(MPCC_STATUS, MPCC_IDLE, 1, 1000, 1000); +} - /* blend on mpc being inserted */ - REG_UPDATE(MPCC_CONTROL[mpcc_idx], - MPCC_MODE, MODE_BLEND); - /* Connect mpc b below one inserted */ - REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, - MPCC_BOT_SEL, next); +const struct mpcc_funcs dcn10_mpcc_funcs = { + .set = dcn10_mpcc_set, + .wait_for_idle = dcn10_mpcc_wait_idle, + .set_bg_color = dcn10_mpcc_set_bg_color, +}; - } - /* premultiplied mode only if alpha is on for the layer*/ - REG_UPDATE_2(MPCC_CONTROL[mpcc_idx], - MPCC_ALPHA_BLND_MODE, - tree_cfg->per_pixel_alpha[position] ? 0 : 2, - MPCC_ALPHA_MULTIPLIED_MODE, 0); +void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, + struct dc_context *ctx, + const struct dcn_mpcc_registers *mpcc_regs, + const struct dcn_mpcc_shift *mpcc_shift, + const struct dcn_mpcc_mask *mpcc_mask, + int inst) +{ + mpcc10->base.ctx = ctx; - /* - * iterating from the last mpc/dpp pair to the one being added, shift - * them down one position - */ - for (next = tree_cfg->num_pipes; next > position; next--) { - tree_cfg->dpp[next] = tree_cfg->dpp[next - 1]; - tree_cfg->mpcc[next] = tree_cfg->mpcc[next - 1]; - tree_cfg->per_pixel_alpha[next] = tree_cfg->per_pixel_alpha[next - 1]; - } + mpcc10->base.inst = inst; + mpcc10->base.funcs = &dcn10_mpcc_funcs; - /* insert the new mpc/dpp pair into the tree_cfg*/ - tree_cfg->dpp[position] = dpp_idx; - tree_cfg->mpcc[position] = mpcc_idx; - tree_cfg->per_pixel_alpha[position] = per_pixel_alpha; - tree_cfg->num_pipes++; -} + mpcc10->mpcc_regs = mpcc_regs; + mpcc10->mpcc_shift = mpcc_shift; + mpcc10->mpcc_mask = mpcc_mask; -void wait_mpcc_idle(struct dcn10_mpc *mpc, - uint8_t mpcc_id) -{ - REG_WAIT(MPCC_STATUS[mpcc_id], - MPCC_IDLE, 1, - 1000, 1000); + mpcc10->opp_id = inst; } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 3e4eb655e913..0f9f1b97d238 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -22,45 +22,45 @@ * */ -#ifndef __DC_MPC_DCN10_H__ -#define __DC_MPC_DCN10_H__ +#ifndef __DC_MPCC_DCN10_H__ +#define __DC_MPCC_DCN10_H__ #include "mpc.h" -#define TO_DCN10_MPC(mpc_base)\ - container_of(mpc_base, struct dcn10_mpc, base) +#define TO_DCN10_MPCC(mpcc_base) \ + container_of(mpcc_base, struct dcn10_mpcc, base) -#define MAX_MPCC 4 -#define MAX_MPC_OUT 4 #define MAX_OPP 4 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MPCC_TOP_SEL, MPCC, inst),\ - SRII(MPCC_BOT_SEL, MPCC, inst),\ - SRII(MPCC_CONTROL, MPCC, inst),\ - SRII(MPCC_STATUS, MPCC, inst),\ - SRII(MPCC_OPP_ID, MPCC, inst),\ - SRII(MPCC_BG_G_Y, MPCC, inst),\ - SRII(MPCC_BG_R_CR, MPCC, inst),\ - SRII(MPCC_BG_B_CB, MPCC, inst),\ - SRII(MPCC_BG_B_CB, MPCC, inst),\ SRII(MUX, MPC_OUT, inst),\ SRII(OPP_PIPE_CONTROL, OPP_PIPE, inst) -struct dcn_mpc_registers { - uint32_t MPCC_TOP_SEL[MAX_MPCC]; - uint32_t MPCC_BOT_SEL[MAX_MPCC]; - uint32_t MPCC_CONTROL[MAX_MPCC]; - uint32_t MPCC_STATUS[MAX_MPCC]; - uint32_t MPCC_OPP_ID[MAX_MPCC]; - uint32_t MPCC_BG_G_Y[MAX_MPCC]; - uint32_t MPCC_BG_R_CR[MAX_MPCC]; - uint32_t MPCC_BG_B_CB[MAX_MPCC]; - uint32_t MUX[MAX_MPC_OUT]; +#define MPCC_COMMON_REG_LIST_DCN1_0(inst) \ + SRI(MPCC_TOP_SEL, MPCC, inst),\ + SRI(MPCC_BOT_SEL, MPCC, inst),\ + SRI(MPCC_CONTROL, MPCC, inst),\ + SRI(MPCC_STATUS, MPCC, inst),\ + SRI(MPCC_OPP_ID, MPCC, inst),\ + SRI(MPCC_BG_G_Y, MPCC, inst),\ + SRI(MPCC_BG_R_CR, MPCC, inst),\ + SRI(MPCC_BG_B_CB, MPCC, inst),\ + SRI(MPCC_BG_B_CB, MPCC, inst) + +struct dcn_mpcc_registers { + uint32_t MPCC_TOP_SEL; + uint32_t MPCC_BOT_SEL; + uint32_t MPCC_CONTROL; + uint32_t MPCC_STATUS; + uint32_t MPCC_OPP_ID; + uint32_t MPCC_BG_G_Y; + uint32_t MPCC_BG_R_CR; + uint32_t MPCC_BG_B_CB; uint32_t OPP_PIPE_CONTROL[MAX_OPP]; + uint32_t MUX[MAX_OPP]; }; -#define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ +#define MPCC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\ @@ -75,7 +75,7 @@ struct dcn_mpc_registers { SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\ SF(OPP_PIPE0_OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh) -#define MPC_REG_FIELD_LIST(type) \ +#define MPCC_REG_FIELD_LIST(type) \ type MPCC_TOP_SEL;\ type MPCC_BOT_SEL;\ type MPCC_MODE;\ @@ -90,42 +90,28 @@ struct dcn_mpc_registers { type MPC_OUT_MUX;\ type OPP_PIPE_CLOCK_EN;\ -struct dcn_mpc_shift { - MPC_REG_FIELD_LIST(uint8_t) +struct dcn_mpcc_shift { + MPCC_REG_FIELD_LIST(uint8_t) }; -struct dcn_mpc_mask { - MPC_REG_FIELD_LIST(uint32_t) +struct dcn_mpcc_mask { + MPCC_REG_FIELD_LIST(uint32_t) }; -struct dcn10_mpc { - struct mpc base; - const struct dcn_mpc_registers *mpc_regs; - const struct dcn_mpc_shift *mpc_shift; - const struct dcn_mpc_mask *mpc_mask; -}; - -void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg); - -bool dcn10_remove_dpp(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - uint8_t idx); +struct dcn10_mpcc { + struct mpcc base; + const struct dcn_mpcc_registers *mpcc_regs; + const struct dcn_mpcc_shift *mpcc_shift; + const struct dcn_mpcc_mask *mpcc_mask; -void dcn10_add_dpp(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg, - uint8_t dpp_idx, - uint8_t mpcc_idx, - uint8_t per_pixel_alpha, - uint8_t position); - -void wait_mpcc_idle(struct dcn10_mpc *mpc, - uint8_t mpcc_id); + int opp_id; +}; -void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, - struct mpc_tree_cfg *tree_cfg); +void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, + struct dc_context *ctx, + const struct dcn_mpcc_registers *mpcc_regs, + const struct dcn_mpcc_shift *mpcc_shift, + const struct dcn_mpcc_mask *mpcc_mask, + int inst); -void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, - unsigned int mpcc_inst, - struct tg_color *bg_color); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 6ada9a262721..142ac0613d5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -336,19 +336,28 @@ static const struct dcn_transform_mask tf_mask = { }; -static const struct dcn_mpc_registers mpc_regs = { - MPC_COMMON_REG_LIST_DCN1_0(0), - MPC_COMMON_REG_LIST_DCN1_0(1), - MPC_COMMON_REG_LIST_DCN1_0(2), - MPC_COMMON_REG_LIST_DCN1_0(3), +#define mpcc_regs(id)\ +[id] = {\ + MPCC_COMMON_REG_LIST_DCN1_0(id),\ + MPC_COMMON_REG_LIST_DCN1_0(0),\ + MPC_COMMON_REG_LIST_DCN1_0(1),\ + MPC_COMMON_REG_LIST_DCN1_0(2),\ + MPC_COMMON_REG_LIST_DCN1_0(3),\ +} + +static const struct dcn_mpcc_registers mpcc_regs[] = { + mpcc_regs(0), + mpcc_regs(1), + mpcc_regs(2), + mpcc_regs(3), }; -static const struct dcn_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +static const struct dcn_mpcc_shift mpcc_shift = { + MPCC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) }; -static const struct dcn_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), +static const struct dcn_mpcc_mask mpcc_mask = { + MPCC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), }; #define tg_regs(id)\ @@ -509,28 +518,22 @@ static struct output_pixel_processor *dcn10_opp_create( return &opp->base; } -static struct mpc *dcn10_mpc_create( - struct dc_context *ctx) +static struct mpcc *dcn10_mpcc_create( + struct dc_context *ctx, + int inst) { - struct dcn10_mpc *mpc = dm_alloc(sizeof(struct dcn10_mpc)); + struct dcn10_mpcc *mpcc10 = dm_alloc(sizeof(struct dcn10_mpcc)); - if (!mpc) + if (!mpcc10) return NULL; - mpc->base.ctx = ctx; - mpc->mpc_regs = &mpc_regs; - mpc->mpc_shift = &mpc_shift; - mpc->mpc_mask = &mpc_mask; + dcn10_mpcc_construct(mpcc10, ctx, + &mpcc_regs[inst], + &mpcc_shift, + &mpcc_mask, + inst); - return &mpc->base; -} - -static void dcn10_mpc_destroy(struct mpc **mpc_base) -{ - if (*mpc_base) - dm_free(TO_DCN10_MPC(*mpc_base)); - - *mpc_base = NULL; + return &mpcc10->base; } static struct timing_generator *dcn10_timing_generator_create( @@ -736,6 +739,11 @@ static void destruct(struct dcn10_resource_pool *pool) dm_free(DCN10TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } + + if (pool->base.mpcc[i] != NULL) { + dm_free(TO_DCN10_MPCC(pool->base.mpcc[i])); + pool->base.mpcc[i] = NULL; + } } for (i = 0; i < pool->base.stream_enc_count; i++) { @@ -760,9 +768,6 @@ static void destruct(struct dcn10_resource_pool *pool) pool->base.dp_clock_source = NULL; } - if (pool->base.mpc != NULL) - dcn10_mpc_destroy(&pool->base.mpc); - if (pool->base.abm != NULL) dce_abm_destroy(&pool->base.abm); @@ -1007,6 +1012,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream = head_pipe->stream; idle_pipe->tg = head_pipe->tg; + idle_pipe->mpcc = pool->mpcc[idle_pipe->pipe_idx]; idle_pipe->mi = pool->mis[idle_pipe->pipe_idx]; idle_pipe->ipp = pool->ipps[idle_pipe->pipe_idx]; idle_pipe->xfm = pool->transforms[idle_pipe->pipe_idx]; @@ -1427,10 +1433,14 @@ static bool construct( dm_error("DC: failed to create tg!\n"); goto otg_create_fail; } + pool->base.mpcc[i] = dcn10_mpcc_create(ctx, i); + if (pool->base.mpcc[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpcc!\n"); + goto mpcc_create_fail; + } } - pool->base.mpc = dcn10_mpc_create(ctx); - if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) @@ -1444,6 +1454,7 @@ static bool construct( return true; disp_clk_create_fail: +mpcc_create_fail: otg_create_fail: opp_create_fail: transform_create_fail: diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d8a378dabb43..030841889803 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -236,6 +236,9 @@ struct resource_pool { struct output_pixel_processor *opps[MAX_PIPES]; struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct mpcc *mpcc[MAX_PIPES]; +#endif unsigned int pipe_count; unsigned int underlay_pipe_index; @@ -259,9 +262,6 @@ struct resource_pool { struct abm *abm; struct dmcu *dmcu; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - struct mpc *mpc; -#endif const struct resource_funcs *funcs; const struct resource_caps *res_cap; @@ -295,8 +295,9 @@ struct pipe_ctx { struct pipe_ctx *top_pipe; struct pipe_ctx *bottom_pipe; + #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - uint8_t mpc_idx; + struct mpcc *mpcc; struct _vcs_dpi_display_dlg_regs_st dlg_regs; struct _vcs_dpi_display_ttu_regs_st ttu_regs; struct _vcs_dpi_display_rq_regs_st rq_regs; @@ -306,9 +307,6 @@ struct pipe_ctx { struct resource_context { struct pipe_ctx pipe_ctx[MAX_PIPES]; -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct mpc_tree_cfg mpc_tree[MAX_PIPES]; -#endif bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index ec1a201747f2..38d158746cc5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -22,76 +22,29 @@ * */ -#ifndef __DC_MPC_H__ -#define __DC_MPC_H__ +#ifndef __DC_MPCC_H__ +#define __DC_MPCC_H__ -/* This structure define the mpc tree configuration - * num_pipes - number of pipes of the tree - * opp_id - instance id of OPP to drive MPC - * dpp- array of DPP index - * mpcc - array of MPCC index - * mode - the most bottom layer MPCC mode control. - * All other layers need to be program to 3 - * - * The connection will be: - * mpcc[num_pipes-1]->mpcc[num_pipes-2]->...->mpcc[1]->mpcc[0]->OPP[opp_id] - * dpp[0]->mpcc[0] - * dpp[1]->mpcc[1] - * ... - * dpp[num_pipes-1]->mpcc[num_pipes-1] - * mpcc[0] is the most top layer of MPC tree, - * mpcc[num_pipes-1] is the most bottom layer. - */ - -struct mpc_tree_cfg { - uint8_t num_pipes; - uint8_t opp_id; - /* dpp pipes for blend */ - uint8_t dpp[6]; - /* mpcc insatnces for blend */ - uint8_t mpcc[6]; - bool per_pixel_alpha[6]; -}; +#include "dc_hw_types.h" -struct mpcc_blnd_cfg { - /* 0- perpixel alpha, 1- perpixel alpha combined with global gain, - * 2- global alpha - */ - uint8_t alpha_mode; - uint8_t global_gain; - uint8_t global_alpha; - bool overlap_only; - bool pre_multiplied_alpha; +struct mpcc_cfg { + int top_dpp_id; + int bot_mpcc_id; + int opp_id; + bool per_pixel_alpha; + bool top_of_tree; }; -struct mpcc_sm_cfg { - bool enable; - /* 0-single plane, 2-row subsampling, 4-column subsampling, - * 6-checkboard subsampling - */ - uint8_t sm_mode; - bool frame_alt; /* 0- disable, 1- enable */ - bool field_alt; /* 0- disable, 1- enable */ - /* 0-no force, 2-force frame polarity from top, - * 3-force frame polarity from bottom - */ - uint8_t force_next_frame_porlarity; - /* 0-no force, 2-force field polarity from top, - * 3-force field polarity from bottom - */ - uint8_t force_next_field_polarity; -}; - -struct mpcc_vupdate_lock_cfg { - bool cfg_lock; - bool adr_lock; - bool adr_cfg_lock; - bool cur0_lock; - bool cur1_lock; +struct mpcc { + const struct mpcc_funcs *funcs; + struct dc_context *ctx; + int inst; }; -struct mpc { - struct dc_context *ctx; +struct mpcc_funcs { + void (*set)(struct mpcc *mpcc, struct mpcc_cfg *cfg); + void (*wait_for_idle)(struct mpcc *mpcc); + void (*set_bg_color)( struct mpcc *mpcc, struct tg_color *bg_color); }; #endif -- GitLab From ad32734699da4dd185405637459bf915a4f4cff6 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 5 Jun 2017 15:08:10 -0400 Subject: [PATCH 0540/2898] drm/amd/display: w/a for ycbcr output pre-multiplied alpha corruption Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 28 +++++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f509dfd97f23..f41230013309 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1658,6 +1658,28 @@ static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) return false; } +static bool is_rgb_cspace(enum dc_color_space output_color_space) +{ + switch (output_color_space) { + case COLOR_SPACE_SRGB: + case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_ADOBERGB: + return true; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR601_LIMITED: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_YCBCR: + return false; + default: + /* Add a case to switch */ + BREAK_TO_DEBUGGER(); + return false; + } +} + static void update_dchubp_dpp( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -1719,6 +1741,12 @@ static void update_dchubp_dpp( mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; mpcc_cfg.per_pixel_alpha = per_pixel_alpha; + /* DCN1.0 has output CM before MPC which seems to screw with + * pre-multiplied alpha. + */ + mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( + pipe_ctx->stream->public.output_color_space) + && per_pixel_alpha; if (!dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].surface) pipe_ctx->mpcc->funcs->wait_for_idle(pipe_ctx->mpcc); pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 19af0ee86191..b1c590d4f454 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -98,7 +98,7 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) REG_SET_4(MPCC_CONTROL, 0xffffffff, MPCC_MODE, mpcc_mode, MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, - MPCC_ALPHA_MULTIPLIED_MODE, 0/*TODO: cfg->per_pixel_alpha*/, + MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, MPCC_BLND_ACTIVE_OVERLAP_ONLY, cfg->top_of_tree); if (cfg->top_of_tree) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 38d158746cc5..51bc8ef5ef79 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -32,6 +32,7 @@ struct mpcc_cfg { int bot_mpcc_id; int opp_id; bool per_pixel_alpha; + bool pre_multiplied_alpha; bool top_of_tree; }; -- GitLab From 561f3a4db315d639b93adf86eedbb8405dd81fbe Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 29 May 2017 18:30:17 -0400 Subject: [PATCH 0541/2898] drm/amd/display: enable pipe split Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 142ac0613d5b..a2276803c0d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -443,7 +443,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, - .use_max_voltage = true + .use_max_voltage = false #endif }; -- GitLab From aed8b319180f18402ed90929f85e2b3e5b81e71d Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 8 Jun 2017 11:55:06 +0530 Subject: [PATCH 0542/2898] drm/amd/display: remove get_position() of underlay get_position() returns CRTC vertical/horizontal counters, hence it is not applicable for underlay which is plane and not attached to one crtc. This patch hence removes the callback from dce110_tg_v_funcs and hence fixes a bug in dc_debug.c where in get_position() for underlay pipe is called un-conditionally. Witout this patch get_position() is called in case one has to update underlay plane's data, since callback implmented with an ASSERT(), the old_surface_count and new_surface_count mismatches; causing only one plane update which is not right and also assert makes the rendering slow. Signed-off-by: Shirish S Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 9 +++++++-- .../amd/display/dc/dce110/dce110_timing_generator_v.c | 9 +-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index ad556e9b0754..9a5df3a848b5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -297,11 +297,16 @@ void context_timing_trace( struct dal_logger *logger = core_dc->ctx->logger; int h_pos[MAX_PIPES], v_pos[MAX_PIPES]; struct crtc_position position; + unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index; + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - - if (pipe_ctx->stream == NULL) + /* get_position() returns CRTC vertical/horizontal counter + * hence not applicable for underlay pipe + */ + if (pipe_ctx->stream == NULL + || pipe_ctx->pipe_idx == underlay_idx) continue; pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &position); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 759c55bb4d15..93ca6ae48cb9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -570,13 +570,6 @@ static void dce110_timing_generator_v_set_early_control( dm_write_reg(tg->ctx, address, regval); } -static void dce110_timing_generator_get_underlay_position(struct timing_generator *tg, - struct crtc_position *position) -{ - //Should never hit this case - ASSERT(false); -} - static uint32_t dce110_timing_generator_v_get_vblank_counter(struct timing_generator *tg) { uint32_t addr = mmCRTCV_STATUS_FRAME_COUNT; @@ -652,7 +645,7 @@ static const struct timing_generator_funcs dce110_tg_v_funcs = { .enable_crtc = dce110_timing_generator_v_enable_crtc, .disable_crtc = dce110_timing_generator_v_disable_crtc, .is_counter_moving = dce110_timing_generator_v_is_counter_moving, - .get_position = dce110_timing_generator_get_underlay_position, + .get_position = NULL, /* Not to be implemented for underlay*/ .get_frame_count = dce110_timing_generator_v_get_vblank_counter, .set_early_control = dce110_timing_generator_v_set_early_control, .wait_for_state = dce110_timing_generator_v_wait_for_state, -- GitLab From 7f5c22d1652327b64375e88b184b0df502c7bdc7 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Thu, 8 Jun 2017 15:55:02 -0500 Subject: [PATCH 0543/2898] drm/amd/display: RV stereo support HDMI frame pack and DP frame alternate in band Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 25 +++++++ .../gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++-- .../display/dc/dce110/dce110_hw_sequencer.c | 6 ++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 69 ++++++++++++++++++- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 4 -- .../display/dc/dcn10/dcn10_timing_generator.c | 2 - 7 files changed, 105 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 66f0595a4c20..2b62efce73c5 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -972,9 +972,7 @@ bool dcn_validate_bandwidth( if (pipe->surface) { struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; - if (v->dpp_per_plane[input_idx] == 2 || - (pipe->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM || - pipe->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE)) { + if (v->dpp_per_plane[input_idx] == 2) { if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { /* update previously split pipe */ hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 47870a640f37..e518aeddfa58 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -832,6 +832,30 @@ static bool streams_changed( return false; } +bool dc_enable_stereo( + struct dc *dc, + struct validate_context *context, + const struct dc_stream *streams[], + uint8_t stream_count) +{ + bool ret = true; + int i, j; + struct pipe_ctx *pipe; + struct core_dc *core_dc = DC_TO_CORE(dc); + for (i = 0; i < MAX_PIPES; i++) { + if (context != NULL) + pipe = &context->res_ctx.pipe_ctx[i]; + else + pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; + for (j = 0 ; pipe && j < stream_count; j++) { + if (streams[j] && streams[j] == &pipe->stream->public && + core_dc->hwss.setup_stereo) + core_dc->hwss.setup_stereo(pipe, core_dc); + } + } + return ret; +} + bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], @@ -903,6 +927,7 @@ bool dc_commit_streams( DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + dc_enable_stereo(dc, context, streams, stream_count); } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c51ec617eff7..90eb839f5414 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -440,8 +440,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; - if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || - stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) { + if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || + stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { pri_split = false; sec_split = false; } @@ -568,8 +568,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip /* Handle h & vsplit */ if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - if (stream->public.timing.timing_3d_format == - TIMING_3D_FORMAT_TOP_AND_BOTTOM) { + if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { pipe_ctx->scl_data.recout.height /= 2; pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; /* Floor primary pipe, ceil 2ndary pipe */ @@ -581,8 +580,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip } } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { - if (stream->public.timing.timing_3d_format == - TIMING_3D_FORMAT_TOP_AND_BOTTOM) + if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.recout.height /= 2; else pipe_ctx->scl_data.recout.width /= 2; @@ -626,7 +624,7 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) surf_src.height, surface->dst_rect.height); - if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE) + if (stream->public.view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) pipe_ctx->scl_data.ratios.horz.value *= 2; else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.ratios.vert.value *= 2; @@ -1772,6 +1770,8 @@ static void set_vendor_info_packet( enum dc_timing_3d_format format; format = stream->public.timing.timing_3d_format; + if (stream->public.view_format == VIEW_3D_FORMAT_NONE) + format = TIMING_3D_FORMAT_NONE; /* Can be different depending on packet content */ length = 5; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 616533e25534..ac99d283bf0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2057,6 +2057,11 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; surface->status.current_address = pipe_ctx->mi->current_address; + if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + pipe_ctx->tg->funcs->is_stereo_left_eye) { + surface->status.is_right_eye =\ + !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg); + } } void dce110_power_down(struct core_dc *dc) @@ -2576,6 +2581,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, + .setup_stereo = NULL }; bool dce110_hw_sequencer_construct(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f41230013309..edcd7369cf9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -896,8 +896,9 @@ static void reset_hw_ctx_wrap( reset_hw_ctx(dc, context, reset_back_end_for_pipe); } -static bool patch_address_for_sbs_tb_stereo( - struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) + +static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, + PHYSICAL_ADDRESS_LOC *addr) { struct core_surface *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && @@ -912,6 +913,7 @@ static bool patch_address_for_sbs_tb_stereo( surface->public.address.grph_stereo.right_addr; return true; } + return false; } @@ -2061,6 +2063,66 @@ static void set_plane_config( program_gamut_remap(pipe_ctx); } +static void dcn10_config_stereo_parameters(struct core_stream *stream,\ + struct crtc_stereo_flags *flags) +{ + enum view_3d_format view_format = stream->public.view_format; + enum dc_timing_3d_format timing_3d_format =\ + stream->public.timing.timing_3d_format; + bool non_stereo_timing = false; + + if (timing_3d_format == TIMING_3D_FORMAT_NONE || + timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || + timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) + non_stereo_timing = true; + + if (non_stereo_timing == false && + view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) { + + flags->PROGRAM_STEREO = 1; + flags->PROGRAM_POLARITY = 1; + if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA || + timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || + timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) { + enum display_dongle_type dongle = \ + stream->sink->link->public.ddc->dongle_type; + if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER || + dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER || + dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER) + flags->DISABLE_STEREO_DP_SYNC = 1; + } + flags->RIGHT_EYE_POLARITY =\ + stream->public.timing.flags.RIGHT_EYE_3D_POLARITY; + if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) + flags->FRAME_PACKED = 1; + } + + return; +} + +static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, + struct core_dc *dc) +{ + struct crtc_stereo_flags flags = { 0 }; + struct core_stream *stream = pipe_ctx->stream; + + dcn10_config_stereo_parameters(stream, &flags); + + pipe_ctx->opp->funcs->opp_set_stereo_polarity( + pipe_ctx->opp, + flags.PROGRAM_STEREO == 1 ? true:false, + stream->public.timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); + + pipe_ctx->tg->funcs->program_stereo( + pipe_ctx->tg, + &stream->public.timing, + &flags); + + + + return; +} + static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .init_hw = init_hw, @@ -2088,7 +2150,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .prog_pixclk_crtc_otg = dcn10_prog_pixclk_crtc_otg, .set_drr = set_drr, .get_position = get_position, - .set_static_screen_control = set_static_screen_control + .set_static_screen_control = set_static_screen_control, + .setup_stereo = dcn10_setup_stereo }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index a2276803c0d0..77fc251d45ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -821,10 +821,6 @@ static void get_pixel_clock_parameters( if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) pixel_clk_params->requested_pix_clk /= 2; - if (stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING || - stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_SW_FRAME_PACKING || - stream->public.timing. timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA) - pixel_clk_params->requested_pix_clk *= 2; } static void build_clamping_params(struct core_stream *stream) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index bc3934d75b46..83efbec77357 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -271,8 +271,6 @@ static void tg_program_timing_generator( REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, h_div_2); - dcn10_disable_stereo( tg); - } /** tg_program_blanking -- GitLab From 3f6d743598ef24002f0babd3aa06c7fe104b7dc5 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 9 Jun 2017 11:32:06 -0400 Subject: [PATCH 0544/2898] drm/amd/display: DAL3 RV get DPREFCLK SpreadspectrumInfo from smu_info Signed-off-by: Hersen Wu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/bios/bios_parser2.c | 14 +++++++-- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 29 ++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index fcd3b72287c8..3a69f9c5d20a 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1136,6 +1136,7 @@ static enum bp_result get_ss_info_v4_2( { enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; + struct atom_smu_info_v3_1 *smu_info = NULL; if (!ss_info) return BP_RESULT_BADINPUT; @@ -1143,11 +1144,18 @@ static enum bp_result get_ss_info_v4_2( if (!DATA_TABLES(dce_info)) return BP_RESULT_BADBIOSTABLE; + if (!DATA_TABLES(smu_info)) + return BP_RESULT_BADBIOSTABLE; + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2, DATA_TABLES(dce_info)); if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; + smu_info = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info)); + if (!smu_info) + return BP_RESULT_BADBIOSTABLE; + ss_info->type.STEP_AND_DELAY_INFO = false; ss_info->spread_percentage_divider = 1000; /* BIOS no longer uses target clock. Always enable for now */ @@ -1173,10 +1181,10 @@ static enum bp_result get_ss_info_v4_2( /* TODO LVDS not support anymore? */ case AS_SIGNAL_TYPE_DISPLAY_PORT: ss_info->spread_spectrum_percentage = - disp_cntl_tbl->dp_ss_percentage; + smu_info->gpuclk_ss_percentage; ss_info->spread_spectrum_range = - disp_cntl_tbl->dp_ss_rate_10hz * 10; - if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) + smu_info->gpuclk_ss_rate_10hz * 10; + if (smu_info->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE) ss_info->type.CENTER_MODE = true; break; case AS_SIGNAL_TYPE_GPU_PLL: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 04cd70172cc7..84b0860190d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -246,6 +246,33 @@ static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) return dp_ref_clk_khz; } +/* TODO: This is DCN DPREFCLK: it could be program by DENTIST by VBIOS + * or CLK0_CLK11 by SMU. For DCE120, it is wlays 600Mhz. Will re-visit + * clock implementation + */ +static int dce_clocks_get_dp_ref_freq_wrkaround(struct display_clock *clk) +{ + struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); + int dp_ref_clk_khz = 600000; + + if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) { + struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( + dal_fixed32_32_from_fraction( + clk_dce->dprefclk_ss_percentage, + clk_dce->dprefclk_ss_divider), 200); + struct fixed32_32 adj_dp_ref_clk_khz; + + ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, + ss_percentage); + adj_dp_ref_clk_khz = + dal_fixed32_32_mul_int( + ss_percentage, + dp_ref_clk_khz); + dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); + } + + return dp_ref_clk_khz; +} static enum dm_pp_clocks_state dce_get_required_clocks_state( struct display_clock *clk, struct state_dependent_clocks *req_clocks) @@ -605,7 +632,7 @@ static bool dce_apply_clock_voltage_request( static const struct display_clock_funcs dce120_funcs = { - .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq, + .get_dp_ref_clk_frequency = dce_clocks_get_dp_ref_freq_wrkaround, .apply_clock_voltage_request = dce_apply_clock_voltage_request, .set_clock = dce112_set_clock }; -- GitLab From 70470154104e935eed36478169550eda577dcdb3 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Sun, 4 Jun 2017 09:11:56 -0400 Subject: [PATCH 0545/2898] drm/amd/display: Get rid of seperate flip function. This code is remanant of pre atomic age when flip was a standalone IOCTL. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 97 ------------------- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 37 ++++++- 2 files changed, 34 insertions(+), 100 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6b25a7ba2f7d..df4cccb4be7a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1328,102 +1328,6 @@ static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder) return 0; } -/****************************************************************************** - * Page Flip functions - ******************************************************************************/ - -/** - * dm_page_flip - called by amdgpu_flip_work_func(), which is triggered - * via DRM IOCTL, by user mode. - * - * @adev: amdgpu_device pointer - * @crtc_id: crtc to cleanup pageflip on - * @crtc_base: new address of the crtc (GPU MC address) - * - * Does the actual pageflip (surface address update). - */ -static void dm_page_flip(struct amdgpu_device *adev, - int crtc_id, u64 crtc_base, bool async) -{ - struct amdgpu_crtc *acrtc; - const struct dc_stream *stream; - struct dc_flip_addrs addr = { {0} }; - struct dc_surface_update surface_updates[1] = { {0} }; - - /* - * TODO risk of concurrency issues - * - * This should guarded by the dal_mutex but we can't do this since the - * caller uses a spin_lock on event_lock. - * - * If we wait on the dal_mutex a second page flip interrupt might come, - * spin on the event_lock, disabling interrupts while it does so. At - * this point the core can no longer be pre-empted and return to the - * thread that waited on the dal_mutex and we're deadlocked. - * - * With multiple cores the same essentially happens but might just take - * a little longer to lock up all cores. - * - * The reason we should lock on dal_mutex is so that we can be sure - * nobody messes with acrtc->stream after we read and check its value. - * - * We might be able to fix our concurrency issues with a work queue - * where we schedule all work items (mode_set, page_flip, etc.) and - * execute them one by one. Care needs to be taken to still deal with - * any potential concurrency issues arising from interrupt calls. - */ - - acrtc = adev->mode_info.crtcs[crtc_id]; - stream = acrtc->stream; - - - if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("flip queue: acrtc %d, already busy\n", acrtc->crtc_id); - /* In commit tail framework this cannot happen */ - BUG_ON(0); - } - - - /* - * Received a page flip call after the display has been reset. - * Just return in this case. Everything should be clean-up on reset. - */ - - if (!stream) { - WARN_ON(1); - return; - } - - addr.address.grph.addr.low_part = lower_32_bits(crtc_base); - addr.address.grph.addr.high_part = upper_32_bits(crtc_base); - addr.flip_immediate = async; - - - if (acrtc->base.state->event && - acrtc->base.state->event->event.base.type == - DRM_EVENT_FLIP_COMPLETE) { - acrtc->event = acrtc->base.state->event; - - /* Set the flip status */ - acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; - - /* Mark this event as consumed */ - acrtc->base.state->event = NULL; - } - - surface_updates->surface = dc_stream_get_status(stream)->surfaces[0]; - surface_updates->flip_addr = &addr; - - - dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, stream); - - DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", - __func__, - addr.address.grph.addr.high_part, - addr.address.grph.addr.low_part); - -} - static int amdgpu_notify_freesync(struct drm_device *dev, void *data, struct drm_file *filp) { @@ -1460,7 +1364,6 @@ static const struct amdgpu_display_funcs dm_display_funcs = { .hpd_sense = NULL,/* called unconditionally */ .hpd_set_polarity = NULL, /* called unconditionally */ .hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */ - .page_flip = dm_page_flip, /* called unconditionally */ .page_flip_get_scanoutpos = dm_crtc_get_scanoutpos,/* called unconditionally */ .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 165f91fa1206..6c4d0d1d4367 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2198,6 +2198,8 @@ static void amdgpu_dm_do_flip( struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); struct amdgpu_device *adev = crtc->dev->dev_private; bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + struct dc_flip_addrs addr = { {0} }; + struct dc_surface_update surface_updates[1] = { {0} }; /* Prepare wait for target vblank early - before the fence-waits */ target_vblank = target - drm_crtc_vblank_count(crtc) + @@ -2211,7 +2213,7 @@ static void amdgpu_dm_do_flip( r = amdgpu_bo_reserve(abo, true); if (unlikely(r != 0)) { DRM_ERROR("failed to reserve buffer before flip\n"); - BUG_ON(0); + WARN_ON(1); } /* Wait for all fences on this FB */ @@ -2239,8 +2241,37 @@ static void amdgpu_dm_do_flip( /* update crtc fb */ crtc->primary->fb = fb; - /* Do the flip (mmio) */ - adev->mode_info.funcs->page_flip(adev, acrtc->crtc_id, afb->address, async_flip); + WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); + WARN_ON(!acrtc->stream); + + addr.address.grph.addr.low_part = lower_32_bits(afb->address); + addr.address.grph.addr.high_part = upper_32_bits(afb->address); + addr.flip_immediate = async_flip; + + + if (acrtc->base.state->event && + acrtc->base.state->event->event.base.type == + DRM_EVENT_FLIP_COMPLETE) { + acrtc->event = acrtc->base.state->event; + + /* Set the flip status */ + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + + /* Mark this event as consumed */ + acrtc->base.state->event = NULL; + } + + surface_updates->surface = dc_stream_get_status(acrtc->stream)->surfaces[0]; + surface_updates->flip_addr = &addr; + + + dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, acrtc->stream); + + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", + __func__, + addr.address.grph.addr.high_part, + addr.address.grph.addr.low_part); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", -- GitLab From 1159898a88db33877bd8378714c6f647afab7f9b Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 7 Jun 2017 18:28:43 -0400 Subject: [PATCH 0546/2898] drm/amd/display: Handle commit plane with no FB. 1) Always call flip ISR, for any surface comit, not only for page flip. 2) For events not signaled in flip ISR, handle them in end of commit_tail. 3)Fix race condition between subsequent atomic calls by removing current state access AFTER drm_atomic_helper_commit_hw_done was called. After this call a pending next commit will swap in his own state into objects and proceed. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 127 +++++++++--------- 2 files changed, 70 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index df4cccb4be7a..98e0dbe2a4de 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -222,15 +222,15 @@ static void dm_pflip_high_irq(void *interrupt_params) /* wakeup usersapce */ - if (amdgpu_crtc->event - && amdgpu_crtc->event->event.base.type - == DRM_EVENT_FLIP_COMPLETE) { + if (amdgpu_crtc->event) { /* Update to correct count/ts if racing with vblank irq */ drm_crtc_accurate_vblank_count(&amdgpu_crtc->base); drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event); + /* page flip completed. clean up */ amdgpu_crtc->event = NULL; + } else WARN_ON(1); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 6c4d0d1d4367..b19536d0e045 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2180,6 +2180,24 @@ static void handle_cursor_update( } +static void prepare_flip_isr(struct amdgpu_crtc *acrtc) +{ + + assert_spin_locked(&acrtc->base.dev->event_lock); + WARN_ON(acrtc->event); + + acrtc->event = acrtc->base.state->event; + + /* Set the flip status */ + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + + /* Mark this event as consumed */ + acrtc->base.state->event = NULL; + + DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", + acrtc->crtc_id); +} + /* * Executes flip * @@ -2249,17 +2267,8 @@ static void amdgpu_dm_do_flip( addr.flip_immediate = async_flip; - if (acrtc->base.state->event && - acrtc->base.state->event->event.base.type == - DRM_EVENT_FLIP_COMPLETE) { - acrtc->event = acrtc->base.state->event; - - /* Set the flip status */ - acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; - - /* Mark this event as consumed */ - acrtc->base.state->event = NULL; - } + if (acrtc->base.state->event) + prepare_flip_isr(acrtc); surface_updates->surface = dc_stream_get_status(acrtc->stream)->surfaces[0]; surface_updates->flip_addr = &addr; @@ -2274,8 +2283,6 @@ static void amdgpu_dm_do_flip( spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", - acrtc->crtc_id); } static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, @@ -2289,13 +2296,13 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_plane_state *old_plane_state; const struct dc_stream *dc_stream_attach; const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); int planes_count = 0; /* update planes when needed */ for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; - struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(crtc); struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; struct dm_connector_state *con_state = NULL; @@ -2306,7 +2313,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, continue; } - if (!fb || !crtc || !crtc->state->active) + if (!fb || !crtc || pcrtc != crtc || !crtc->state->active) continue; pflip_needed = !state->allow_modeset; @@ -2339,17 +2346,21 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, continue; - if (crtc == pcrtc) { - add_surface(dm->dc, crtc, plane, - &dc_surfaces_constructed[planes_count]); - if (dc_surfaces_constructed[planes_count] == NULL) { - dm_error("%s: Failed to add surface!\n", __func__); - continue; - } - dc_stream_attach = acrtc_attach->stream; - planes_count++; + + add_surface(dm->dc, crtc, plane, + &dc_surfaces_constructed[planes_count]); + if (dc_surfaces_constructed[planes_count] == NULL) { + dm_error("%s: Failed to add surface!\n", __func__); + continue; } + dc_stream_attach = acrtc_attach->stream; + planes_count++; + } else if (crtc->state->planes_changed) { + /* Assume even ONE crtc with immediate flip means + * entire can't wait for VBLANK + * TODO Check if it's correct + */ *wait_for_vblank = acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? false : true; @@ -2359,6 +2370,8 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, fb, drm_crtc_vblank_count(crtc) + *wait_for_vblank); + /*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */ + /*clean up the flags for next usage*/ acrtc_attach->flip_flags = 0; } @@ -2366,15 +2379,27 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, } if (planes_count) { + unsigned long flags; + + if (pcrtc->state->event) { + + drm_crtc_vblank_get(pcrtc); + + spin_lock_irqsave(&pcrtc->dev->event_lock, flags); + prepare_flip_isr(acrtc_attach); + spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); + } + if (false == dc_commit_surfaces_to_stream(dm->dc, dc_surfaces_constructed, planes_count, - dc_stream_attach)) { + dc_stream_attach)) dm_error("%s: Failed to attach surface!\n", __func__); - return; - } + for (i = 0; i < planes_count; i++) dc_surface_release(dc_surfaces_constructed[i]); + } else { + /*TODO BUG Here should go disable planes on CRTC. */ } } @@ -2405,7 +2430,6 @@ void amdgpu_dm_atomic_commit_tail( struct drm_crtc_state *new_state = crtc->state; acrtc = to_amdgpu_crtc(crtc); - aconnector = amdgpu_dm_find_first_crct_matching_connector( state, @@ -2571,14 +2595,6 @@ void amdgpu_dm_atomic_commit_tail( dc_stream_get_status(acrtc->stream)->primary_otg_inst; } - /* update planes when needed per crtc*/ - for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc); - - if (acrtc->stream) - amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); - } - for (i = 0; i < new_crtcs_count; i++) { /* * loop to enable interrupts on newly arrived crtc @@ -2592,19 +2608,27 @@ void amdgpu_dm_atomic_commit_tail( manage_dm_interrupts(adev, acrtc, true); } + /* update planes when needed per crtc*/ + for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc); + + if (acrtc->stream) + amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + } + - /*TODO mark consumed event on all crtc assigned event - * in drm_atomic_helper_setup_commit just to signal completion + /* + * send vblank event on all events not handled in flip and + * mark consumed event for drm_atomic_helper_commit_hw_done */ spin_lock_irqsave(&adev->ddev->event_lock, flags); for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->base.state->event && - acrtc->base.state->event->event.base.type != DRM_EVENT_FLIP_COMPLETE) { - acrtc->event = acrtc->base.state->event; - acrtc->base.state->event = NULL; - } + if (acrtc->base.state->event) + drm_send_event_locked(dev, &crtc->state->event->base); + + acrtc->base.state->event = NULL; } spin_unlock_irqrestore(&adev->ddev->event_lock, flags); @@ -2614,23 +2638,6 @@ void amdgpu_dm_atomic_commit_tail( if (wait_for_vblank) drm_atomic_helper_wait_for_vblanks(dev, state); - /*TODO send vblank event on all crtc assigned event - * in drm_atomic_helper_setup_commit just to signal completion - */ - spin_lock_irqsave(&adev->ddev->event_lock, flags); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->event && - acrtc->event->event.base.type != DRM_EVENT_FLIP_COMPLETE) { - drm_send_event_locked(dev, &acrtc->event->base); - acrtc->event = NULL; - } - } - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - - /*TODO Is it to early if actual flip haven't happened yet ?*/ - /* Release old FB */ drm_atomic_helper_cleanup_planes(dev, state); } -- GitLab From c8210d5ae37b3c0e5dc2a91095dd1147c524977d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 9 Jun 2017 10:12:36 -0400 Subject: [PATCH 0547/2898] drm/amd/display: Don't call DCN clk code for Vega Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 10 ++++++---- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 84b0860190d7..4e3f4e5e46a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -614,11 +614,13 @@ static bool dce_apply_clock_voltage_request( } if (send_request) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); - /*use dcfclk request voltage*/ - clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock_voltage_req.clocks_in_khz = + if (clk->ctx->dce_version == DCN_VERSION_1_0) { + struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + /*use dcfclk request voltage*/ + clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; + clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(core_dc, &clk->cur_clocks_value); + } #endif dm_pp_apply_clock_for_voltage_request( clk->ctx, &clock_voltage_req); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ac99d283bf0a..7c509811efa6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1633,7 +1633,7 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (resource_parse_asic_id(dc->ctx->asic_id) == DCN_VERSION_1_0) { + if (dc->ctx->dce_version == DCN_VERSION_1_0) { if (context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.cur_clk.fclk_khz) { struct dm_pp_clock_for_voltage_req clock; -- GitLab From b6d6103bbb21ed51acf0168529d867df1ecde445 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Mon, 12 Jun 2017 11:03:26 -0500 Subject: [PATCH 0548/2898] drm/amd/display: RV stereo support Re-organize 3d declarations Signed-off-by: Vitaly Prosyak Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 8 +--- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 43 +++++++++++--------- drivers/gpu/drm/amd/display/dc/dc_types.h | 9 ++++ 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index fb86808dd309..a78af1ef1315 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -787,13 +787,7 @@ struct dc_container_id { unsigned short productCode; }; -struct stereo_3d_features { - bool supported ; - bool allTimings ; - bool cloneMode ; - bool scaling ; - bool singleFrameSWPacked; -}; + /* * The sink structure contains EDID and other display device properties diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index b6e677786cbc..94fb93066784 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -551,27 +551,7 @@ enum dc_timing_standard { TIMING_STANDARD_MAX }; -enum dc_timing_3d_format { - TIMING_3D_FORMAT_NONE, - TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/ - TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/ - TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/ - /* for active DP-HDMI dongle*/ - TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/ - TIMING_3D_FORMAT_HW_FRAME_PACKING, - TIMING_3D_FORMAT_SW_FRAME_PACKING, - TIMING_3D_FORMAT_ROW_INTERLEAVE, - TIMING_3D_FORMAT_COLUMN_INTERLEAVE, - TIMING_3D_FORMAT_PIXEL_INTERLEAVE, - TIMING_3D_FORMAT_SIDE_BY_SIDE, - TIMING_3D_FORMAT_TOP_AND_BOTTOM, - TIMING_3D_FORMAT_SBS_SW_PACKED, - /* Side-by-side, packed by application/driver into 2D frame*/ - TIMING_3D_FORMAT_TB_SW_PACKED, - /* Top-and-bottom, packed by application/driver into 2D frame*/ - TIMING_3D_FORMAT_MAX, -}; enum dc_color_depth { COLOR_DEPTH_UNDEFINED, @@ -643,6 +623,29 @@ struct dc_crtc_timing_flags { }; +enum dc_timing_3d_format { + TIMING_3D_FORMAT_NONE, + TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/ + TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/ + TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/ + /* for active DP-HDMI dongle*/ + TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/ + TIMING_3D_FORMAT_HW_FRAME_PACKING, + TIMING_3D_FORMAT_SW_FRAME_PACKING, + TIMING_3D_FORMAT_ROW_INTERLEAVE, + TIMING_3D_FORMAT_COLUMN_INTERLEAVE, + TIMING_3D_FORMAT_PIXEL_INTERLEAVE, + TIMING_3D_FORMAT_SIDE_BY_SIDE, + TIMING_3D_FORMAT_TOP_AND_BOTTOM, + TIMING_3D_FORMAT_SBS_SW_PACKED, + /* Side-by-side, packed by application/driver into 2D frame*/ + TIMING_3D_FORMAT_TB_SW_PACKED, + /* Top-and-bottom, packed by application/driver into 2D frame*/ + + TIMING_3D_FORMAT_MAX, +}; + + struct dc_crtc_timing { uint32_t h_total; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 5269796b2a8e..9662f2c68f83 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -272,6 +272,15 @@ enum dc_timing_source { TIMING_SOURCE_COUNT }; + +struct stereo_3d_features { + bool supported ; + bool allTimings ; + bool cloneMode ; + bool scaling ; + bool singleFrameSWPacked; +}; + enum dc_timing_support_method { TIMING_SUPPORT_METHOD_UNDEFINED, TIMING_SUPPORT_METHOD_EXPLICIT, -- GitLab From 7a0963345f859058fa866dd28fe13ca5eff22a87 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 13 Jun 2017 11:54:10 -0400 Subject: [PATCH 0549/2898] drm/amd/display: Save hpd_src for dc_link Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b2c8b572d57f..fed38fbab452 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -987,6 +987,9 @@ static bool construct( enc_init_data.connector = link->link_id; enc_init_data.channel = get_ddc_line(link); enc_init_data.hpd_source = get_hpd_line(link); + + link->public.hpd_src = enc_init_data.hpd_source; + enc_init_data.transmitter = translate_encoder_to_transmitter(enc_init_data.encoder); link->link_enc = link->dc->res_pool->funcs->link_enc_create( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a78af1ef1315..6d918391435a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -658,6 +658,9 @@ struct dc_link { struct dc_lane_settings cur_lane_setting; uint8_t ddc_hw_inst; + + uint8_t hpd_src; + uint8_t link_enc_hw_inst; bool test_pattern_enabled; -- GitLab From 80b4c5a8c1e1856848a440a63accbe029ea3b51b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 13 Jun 2017 16:31:49 -0400 Subject: [PATCH 0550/2898] drm/amd/display: fix dc_check_update_surfaces_for_stream memcmp sequence Signed-off-by: Dmytro Laktyushkin Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e518aeddfa58..f5f365b418c2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1094,11 +1094,13 @@ static enum surface_update_type get_plane_info_update_type( const struct dc_surface_update *u, int surface_index) { - struct dc_plane_info temp_plane_info = { 0 }; + struct dc_plane_info temp_plane_info; if (!u->plane_info) return UPDATE_TYPE_FAST; + temp_plane_info = *u->plane_info; + /* Copy all parameters that will cause a full update * from current surface, the rest of the parameters * from provided plane configuration. @@ -1115,10 +1117,6 @@ static enum surface_update_type get_plane_info_update_type( temp_plane_info.stereo_format = u->surface->stereo_format; temp_plane_info.tiling_info = u->surface->tiling_info; - /* Special Validation parameters */ - temp_plane_info.format = u->plane_info->format; - temp_plane_info.per_pixel_alpha = u->plane_info->per_pixel_alpha; - if (surface_index == 0) temp_plane_info.visible = u->plane_info->visible; else -- GitLab From ebf055f95b4782e681c0040461a33c0210e65a5d Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 14 Jun 2017 10:19:57 -0400 Subject: [PATCH 0551/2898] drm/amd/display: fix issues with incorrectly detecting UPDATE_TYPE_FULL This is due to how structures are being packed with padding added. Structure field initialization doesn't clear the padding bytes, which cause our memcmp to give incorrect result. Move smaller structure parameters to end of structure. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +- drivers/gpu/drm/amd/display/dc/dc.h | 75 +++++++++++++----------- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f5f365b418c2..a8f34a92cee2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -628,7 +628,8 @@ static bool is_validation_required( return true; for (j = 0; j < set[i].surface_count; j++) { - struct dc_surface temp_surf = { 0 }; + struct dc_surface temp_surf; + memset(&temp_surf, 0, sizeof(temp_surf)); temp_surf = *context->stream_status[i].surfaces[j]; temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; @@ -1095,6 +1096,7 @@ static enum surface_update_type get_plane_info_update_type( int surface_index) { struct dc_plane_info temp_plane_info; + memset(&temp_plane_info, 0, sizeof(temp_plane_info)); if (!u->plane_info) return UPDATE_TYPE_FAST; @@ -1294,7 +1296,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { - const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 }; + const struct dc_surface *new_surfaces[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) new_surfaces[i] = srf_updates[i].surface; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6d918391435a..36b3b123d3c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -54,8 +54,8 @@ struct dc_caps { struct dc_dcc_surface_param { - enum surface_pixel_format format; struct dc_size surface_size; + enum surface_pixel_format format; enum swizzle_mode_values swizzle_mode; enum dc_scan_direction scan; }; @@ -67,9 +67,6 @@ struct dc_dcc_setting { }; struct dc_surface_dcc_cap { - bool capable; - bool const_color_support; - union { struct { struct dc_dcc_setting rgb; @@ -80,6 +77,9 @@ struct dc_surface_dcc_cap { struct dc_dcc_setting chroma; } video; }; + + bool capable; + bool const_color_support; }; struct dc_static_screen_events { @@ -201,12 +201,12 @@ enum frame_buffer_mode { } ; struct dchub_init_data { - bool dchub_initialzied; - bool dchub_info_valid; int64_t zfb_phys_addr_base; int64_t zfb_mc_base_addr; uint64_t zfb_size_in_byte; enum frame_buffer_mode fb_mode; + bool dchub_initialzied; + bool dchub_info_valid; }; struct dc_init_data { @@ -240,9 +240,6 @@ enum { }; struct dc_hdr_static_metadata { - bool hdr_supported; - bool is_hdr; - /* display chromaticities and white point in units of 0.00001 */ unsigned int chromaticity_green_x; unsigned int chromaticity_green_y; @@ -257,6 +254,9 @@ struct dc_hdr_static_metadata { uint32_t max_luminance; uint32_t maximum_content_light_level; uint32_t maximum_frame_average_light_level; + + bool hdr_supported; + bool is_hdr; }; enum dc_transfer_func_type { @@ -285,15 +285,12 @@ enum dc_transfer_func_predefined { }; struct dc_transfer_func { + struct dc_transfer_func_distributed_points tf_pts; enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; - struct dc_transfer_func_distributed_points tf_pts; }; struct dc_surface { - bool per_pixel_alpha; - bool visible; - bool flip_immediate; struct dc_plane_address address; struct scaling_taps scaling_quality; @@ -303,38 +300,42 @@ struct dc_surface { union plane_size plane_size; union dc_tiling_info tiling_info; + struct dc_plane_dcc_param dcc; - enum dc_color_space color_space; + struct dc_hdr_static_metadata hdr_static_ctx; + + const struct dc_gamma *gamma_correction; + const struct dc_transfer_func *in_transfer_func; + enum dc_color_space color_space; enum surface_pixel_format format; enum dc_rotation_angle rotation; - bool horizontal_mirror; enum plane_stereo_format stereo_format; - struct dc_hdr_static_metadata hdr_static_ctx; - - const struct dc_gamma *gamma_correction; - const struct dc_transfer_func *in_transfer_func; + bool per_pixel_alpha; + bool visible; + bool flip_immediate; + bool horizontal_mirror; }; struct dc_plane_info { - bool per_pixel_alpha; union plane_size plane_size; union dc_tiling_info tiling_info; struct dc_plane_dcc_param dcc; enum surface_pixel_format format; enum dc_rotation_angle rotation; - bool horizontal_mirror; enum plane_stereo_format stereo_format; enum dc_color_space color_space; /*todo: wrong place, fits in scaling info*/ + bool horizontal_mirror; bool visible; + bool per_pixel_alpha; }; struct dc_scaling_info { - struct rect src_rect; - struct rect dst_rect; - struct rect clip_rect; - struct scaling_taps scaling_quality; + struct rect src_rect; + struct rect dst_rect; + struct rect clip_rect; + struct scaling_taps scaling_quality; }; struct dc_surface_update { @@ -460,24 +461,26 @@ enum surface_update_type { struct dc_stream { const struct dc_sink *sink; struct dc_crtc_timing timing; - enum signal_type output_signal; - - enum dc_color_space output_color_space; - enum dc_dither_option dither_option; struct rect src; /* composition area */ struct rect dst; /* stream addressable area */ struct audio_info audio_info; - bool ignore_msa_timing_param; - struct freesync_context freesync_ctx; const struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; + + enum signal_type output_signal; + + enum dc_color_space output_color_space; + enum dc_dither_option dither_option; + enum view_3d_format view_format; + + bool ignore_msa_timing_param; /* TODO: custom INFO packets */ /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ @@ -667,9 +670,10 @@ struct dc_link { union compliance_test_state compliance_test_state; void *priv; - bool aux_mode; struct ddc_service *ddc; + + bool aux_mode; }; struct dpcd_caps { @@ -685,12 +689,13 @@ struct dpcd_caps { indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ struct dc_dongle_caps dongle_caps; - bool allow_invalid_MSA_timing_param; - bool panel_mode_edp; uint32_t sink_dev_id; uint32_t branch_dev_id; int8_t branch_dev_name[6]; int8_t branch_hw_revision; + + bool allow_invalid_MSA_timing_param; + bool panel_mode_edp; }; struct dc_link_status { @@ -801,9 +806,9 @@ struct dc_sink { struct dc_edid_caps edid_caps; /* parse display caps */ struct dc_container_id *dc_container_id; uint32_t dongle_max_pix_clk; - bool converter_disable_audio; void *priv; struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX]; + bool converter_disable_audio; }; void dc_sink_retain(const struct dc_sink *sink); -- GitLab From 7950f0f9815a2dc2e3e1cc2d341d486ac2ae8bae Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 13 Jun 2017 17:08:22 -0400 Subject: [PATCH 0552/2898] drm/amd/display: fix dc_post_update_surfaces_to_stream Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 35 +++++++------------ drivers/gpu/drm/amd/display/dc/dc.h | 9 +---- .../display/dc/dce110/dce110_hw_sequencer.c | 11 ++---- 3 files changed, 17 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a8f34a92cee2..909d38522361 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -953,15 +953,6 @@ bool dc_commit_streams( return (result == DC_OK); } -bool dc_pre_update_surfaces_to_stream( - struct dc *dc, - const struct dc_surface *const *new_surfaces, - uint8_t new_surface_count, - const struct dc_stream *dc_stream) -{ - return true; -} - bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; @@ -971,14 +962,19 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); for (i = 0; i < core_dc->res_pool->pipe_count; i++) - if (context->res_ctx.pipe_ctx[i].stream == NULL) { + if (context->res_ctx.pipe_ctx[i].stream == NULL + || context->res_ctx.pipe_ctx[i].surface == NULL) { context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end( core_dc, &context->res_ctx.pipe_ctx[i]); } + /* 3rd param should be true, temp w/a for RV*/ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version != DCN_VERSION_1_0); +#else core_dc->hwss.set_bandwidth(core_dc, context, true); - +#endif return true; } @@ -1262,17 +1258,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (stream_update->out_transfer_func && stream_update->out_transfer_func != - dc_stream->out_transfer_func) { - if (stream_update->out_transfer_func->type != - TF_TYPE_UNKNOWN) { - if (dc_stream->out_transfer_func != NULL) - dc_transfer_func_release - (dc_stream->out_transfer_func); - dc_transfer_func_retain(stream_update-> - out_transfer_func); - stream->public.out_transfer_func = - stream_update->out_transfer_func; - } + dc_stream->out_transfer_func) { + if (dc_stream->out_transfer_func != NULL) + dc_transfer_func_release(dc_stream->out_transfer_func); + dc_transfer_func_retain(stream_update->out_transfer_func); + stream->public.out_transfer_func = + stream_update->out_transfer_func; } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 36b3b123d3c7..52c36007382f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -262,8 +262,7 @@ struct dc_hdr_static_metadata { enum dc_transfer_func_type { TF_TYPE_PREDEFINED, TF_TYPE_DISTRIBUTED_POINTS, - TF_TYPE_BYPASS, - TF_TYPE_UNKNOWN + TF_TYPE_BYPASS }; struct dc_transfer_func_distributed_points { @@ -411,12 +410,6 @@ bool dc_commit_surfaces_to_stream( uint8_t surface_count, const struct dc_stream *stream); -bool dc_pre_update_surfaces_to_stream( - struct dc *dc, - const struct dc_surface *const *new_surfaces, - uint8_t new_surface_count, - const struct dc_stream *stream); - bool dc_post_update_surfaces_to_stream( struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7c509811efa6..a83d260cda45 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2538,17 +2538,12 @@ static void dce110_apply_ctx_for_surface( static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) { - int i; - - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe) - break; - - if (i == dc->res_pool->pipe_count) + /* Do not power down fe when stream is active on dce*/ + if (pipe->stream) return; dc->hwss.enable_display_power_gating( - dc, i, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); + dc, pipe->pipe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); if (pipe->xfm) pipe->xfm->funcs->transform_reset(pipe->xfm); memset(&pipe->scl_data, 0, sizeof(struct scaler_data)); -- GitLab From f19d5f3520d67cee4a98721032c1b7aee7942f20 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 13 Jun 2017 17:14:51 -0400 Subject: [PATCH 0553/2898] drm/amd/display: do full fe reprogram on full update Fixes MPO entry in 2x4k scenario on raven Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 81 ++++++++++++++++-------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 909d38522361..18fde5081742 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1404,15 +1404,18 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!surface_count) /* reset */ core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); - /* Lock pipes for provided surfaces */ + /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->surface != surface) + if (update_type != UPDATE_TYPE_FULL && pipe_ctx->surface != surface) + continue; + if (!pipe_ctx->surface || pipe_ctx->top_pipe) continue; + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { core_dc->hwss.pipe_control_lock( core_dc, @@ -1420,22 +1423,49 @@ void dc_update_surfaces_and_stream(struct dc *dc, true); } } + if (update_type == UPDATE_TYPE_FULL) + break; } + /* Full fe update*/ + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; + bool is_new_pipe_surface = cur_pipe_ctx->surface != pipe_ctx->surface; + struct dc_cursor_position position = { 0 }; + + if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->surface) + continue; + + if (!pipe_ctx->top_pipe) + core_dc->hwss.apply_ctx_for_surface( + core_dc, pipe_ctx->surface, context); + + /* TODO: this is a hack w/a for switching from mpo to pipe split */ + dc_stream_set_cursor_position(&pipe_ctx->stream->public, &position); + + if (is_new_pipe_surface) { + core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); + core_dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->surface); + core_dc->hwss.set_output_transfer_func( + pipe_ctx, pipe_ctx->stream); + } + } + + if (update_type > UPDATE_TYPE_FAST) + context_timing_trace(dc, &context->res_ctx); + /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); - if (update_type >= UPDATE_TYPE_MED) { - core_dc->hwss.apply_ctx_for_surface( - core_dc, surface, context); - context_timing_trace(dc, &context->res_ctx); - } + if (update_type == UPDATE_TYPE_MED) + core_dc->hwss.apply_ctx_for_surface( + core_dc, surface, context); for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx; - bool is_new_pipe_surface = true; if (pipe_ctx->surface != surface) continue; @@ -1446,19 +1476,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; - if (cur_pipe_ctx->surface == pipe_ctx->surface) - is_new_pipe_surface = false; - - if (is_new_pipe_surface || - srf_updates[i].in_transfer_func) + if (srf_updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); - if (is_new_pipe_surface || - (stream_update != NULL && - stream_update->out_transfer_func != - NULL)) { + if (stream_update != NULL && + stream_update->out_transfer_func != NULL) { core_dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->stream); } @@ -1475,15 +1498,19 @@ void dc_update_surfaces_and_stream(struct dc *dc, struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; for (j = 0; j < surface_count; j++) { - if (srf_updates[j].surface == &pipe_ctx->surface->public) { - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc, - pipe_ctx, - false); - } - break; + if (update_type != UPDATE_TYPE_FULL && + srf_updates[j].surface != &pipe_ctx->surface->public) + continue; + if (!pipe_ctx->surface || pipe_ctx->top_pipe) + continue; + + if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + false); } + break; } } -- GitLab From 90f095c13efe2aed108ebd4754dd629946b68168 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 16 Jun 2017 11:27:59 -0400 Subject: [PATCH 0554/2898] drm/amd/display: add pipe split disable regkey Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 2b62efce73c5..0aa6662650cc 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -791,7 +791,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[1] = v->phyclkv_mid0p72; v->phyclk_per_state[0] = v->phyclkv_min0p65; - if (dc->public.debug.use_max_voltage) { + if (dc->public.debug.disable_pipe_split) { v->max_dppclk[1] = v->max_dppclk_vnom0p8; v->max_dppclk[0] = v->max_dppclk_vnom0p8; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 52c36007382f..62493c4a47d1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -170,7 +170,7 @@ struct dc_debug { bool disable_hubp_power_gate; bool disable_pplib_wm_range; bool use_dml_wm; - bool use_max_voltage; + bool disable_pipe_split; int sr_exit_time_ns; int sr_enter_plus_exit_time_ns; int urgent_latency_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 77fc251d45ba..c7840e0e3ae5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -443,7 +443,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, - .use_max_voltage = false + .disable_pipe_split = false #endif }; @@ -456,7 +456,7 @@ static const struct dc_debug debug_defaults_diags = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, .use_dml_wm = false, - .use_max_voltage = false + .disable_pipe_split = false #endif }; -- GitLab From 0604b36c77e31a05b1bd18d53cac2c9350500bcb Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 22 Jun 2017 17:37:22 -0400 Subject: [PATCH 0555/2898] drm/amd/display: Create dm_plane_state. Hook up dc_surface creation/destruction to dm_plane_state. Rename amdgpu_drm_plane_state to dm_plane_state and do minor cleanups. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 14 ++-- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 79 ++++++++++++++----- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index be51ac56552c..190905e08c38 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -59,6 +59,8 @@ struct amdgpu_hpd; #define to_amdgpu_framebuffer(x) container_of(x, struct amdgpu_framebuffer, base) #define to_amdgpu_plane(x) container_of(x, struct amdgpu_plane, base) +#define to_dm_plane_state(x) container_of(x, struct dm_plane_state, base); + #define AMDGPU_MAX_HPD_PINS 6 #define AMDGPU_MAX_CRTCS 6 #define AMDGPU_MAX_PLANES 6 @@ -440,16 +442,18 @@ struct amdgpu_crtc { struct drm_pending_vblank_event *event; }; -struct amdgpu_drm_plane_state { +/* TODO rename to dc_plane_state */ +struct dc_surface; + +struct dm_plane_state { struct drm_plane_state base; - unsigned int h_ratio; - unsigned int v_ratio; + struct dc_surface* dc_surface; }; -static inline struct amdgpu_drm_plane_state * +static inline struct dm_plane_state * to_amdgpu_plane_state(struct drm_plane_state *state) { - return container_of(state, struct amdgpu_drm_plane_state, base); + return container_of(state, struct dm_plane_state, base); } struct amdgpu_plane { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b19536d0e045..83baa48ba907 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1356,45 +1356,82 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { static void dm_drm_plane_reset(struct drm_plane *plane) { - struct amdgpu_drm_plane_state *amdgpu_state; + struct dm_plane_state *amdgpu_state = NULL; + struct amdgpu_device *adev = plane->dev->dev_private; - if (plane->state) { - amdgpu_state = to_amdgpu_plane_state(plane->state); - if (amdgpu_state->base.fb) - drm_framebuffer_unreference(amdgpu_state->base.fb); - kfree(amdgpu_state); - plane->state = NULL; - } + if (plane->state) + plane->funcs->atomic_destroy_state(plane, plane->state); amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); + if (amdgpu_state) { plane->state = &amdgpu_state->base; plane->state->plane = plane; + plane->state->rotation = DRM_MODE_ROTATE_0; + + amdgpu_state->dc_surface = dc_create_surface(adev->dm.dc); + WARN_ON(!amdgpu_state->dc_surface); } + else + WARN_ON(1); } static struct drm_plane_state * dm_drm_plane_duplicate_state(struct drm_plane *plane) { - struct amdgpu_drm_plane_state *amdgpu_state; - struct amdgpu_drm_plane_state *copy; + struct dm_plane_state *dm_plane_state, *old_dm_plane_state; + struct amdgpu_device *adev = plane->dev->dev_private; + + old_dm_plane_state = to_dm_plane_state(plane->state); + dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); + if (!dm_plane_state) + return NULL; + + if (old_dm_plane_state->dc_surface) { + struct dc_surface *dc_surface = dc_create_surface(adev->dm.dc); + if (WARN_ON(!dc_surface)) + return NULL; + + __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); + + memcpy(dc_surface, old_dm_plane_state->dc_surface, sizeof(*dc_surface)); + + if (old_dm_plane_state->dc_surface->gamma_correction) + dc_gamma_retain(dc_surface->gamma_correction); - amdgpu_state = to_amdgpu_plane_state(plane->state); - copy = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); - if (!copy) + if (old_dm_plane_state->dc_surface->in_transfer_func) + dc_transfer_func_retain(dc_surface->in_transfer_func); + + dm_plane_state->dc_surface = dc_surface; + + /*TODO Check for inferred values to be reset */ + } + else { + WARN_ON(1); return NULL; + } - __drm_atomic_helper_plane_duplicate_state(plane, ©->base); - return ©->base; + return &dm_plane_state->base; } -static void dm_drm_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *old_state) +void dm_drm_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) { - struct amdgpu_drm_plane_state *old_amdgpu_state = - to_amdgpu_plane_state(old_state); - __drm_atomic_helper_plane_destroy_state(old_state); - kfree(old_amdgpu_state); + struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); + + if (dm_plane_state->dc_surface) { + struct dc_surface *dc_surface = dm_plane_state->dc_surface; + + if (dc_surface->gamma_correction) + dc_gamma_release(&dc_surface->gamma_correction); + + if (dc_surface->in_transfer_func) + dc_transfer_func_release(dc_surface->in_transfer_func); + + dc_surface_release(dc_surface); + } + + drm_atomic_helper_plane_destroy_state(plane, state); } static const struct drm_plane_funcs dm_plane_funcs = { -- GitLab From 80c62d3a112af59ada6c3a5fc1de16021d7ad790 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 19 Jun 2017 11:38:15 -0400 Subject: [PATCH 0556/2898] drm/amd/display: MST atomic_get_property missing. Missing function implementation was leading to EINVAL in UMD thus not adding MST connector to X topology and hence not getting set mode for it. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 77907baa522a..ec91a52c002f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -168,7 +168,8 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .reset = amdgpu_dm_connector_funcs_reset, .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - .atomic_set_property = amdgpu_dm_connector_atomic_set_property + .atomic_set_property = amdgpu_dm_connector_atomic_set_property, + .atomic_get_property = amdgpu_dm_connector_atomic_get_property }; static int dm_dp_mst_get_modes(struct drm_connector *connector) -- GitLab From 03c8a5feeecf95ca1dfabb5b231016c0e76a187c Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 20 Jun 2017 10:42:33 -0400 Subject: [PATCH 0557/2898] drm/amd/display: Add global lock function. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 66 ++++++++++++++----- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 83baa48ba907..db38dd0a0c1f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2890,6 +2890,49 @@ static enum surface_update_type amdgpu_dm_check_surfaces_update_type( return update_type; } +/*` + * Grabs all modesetting locks to serialize against any blocking commits, + * Waits for completion of all non blocking commits. + */ +static void aquire_global_lock( + struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_commit *commit; + long ret; + + /* Adding all modeset locks to aquire_ctx will + * ensure that when the framework release it the + * extra locks we are locking here will get released to + */ + drm_modeset_lock_all_ctx(dev, state->acquire_ctx); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + spin_lock(&crtc->commit_lock); + commit = list_first_entry_or_null(&crtc->commit_list, + struct drm_crtc_commit, commit_entry); + if (commit) + drm_crtc_commit_get(commit); + spin_unlock(&crtc->commit_lock); + + if (!commit) + continue; + + /* Make sure all pending HW programming completed and + * page flips done + */ + ret = wait_for_completion_timeout(&commit->hw_done, + 10*HZ); + ret = wait_for_completion_timeout(&commit->flip_done, + 10*HZ); + if (ret == 0) + DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n", + crtc->base.id, crtc->name); + drm_crtc_commit_put(commit); + } +} + int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { @@ -3146,7 +3189,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dc, set[i].surfaces, set[i].surface_count, - set[i].stream) > UPDATE_TYPE_MED) { + set[i].stream) > UPDATE_TYPE_FAST) { wait_for_prev_commits = true; break; } @@ -3160,25 +3203,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * For full updates case when * removing/adding/updateding streams on once CRTC while flipping * on another CRTC, - * Adding all current active CRTC's states to the atomic commit in - * amdgpu_dm_atomic_check will guarantee that any such full update commit + * acquiring global lock will guarantee that any such full + * update commit * will wait for completion of any outstanding flip using DRMs * synchronization events. */ - if (wait_for_prev_commits) { - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_crtc_state *crtc_state; - - if (acrtc->stream) { - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); - break; - } - } - } - } + if (wait_for_prev_commits) + aquire_global_lock(dev, state); + } if (context) { -- GitLab From 92af86fa7cba07aeec2f5f455b5ad981aff6013d Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 20 Jun 2017 10:56:35 -0400 Subject: [PATCH 0558/2898] drm/amd/display: Remove check update type function. Due to using dc_commit_surface_to_stream instead of build stream and surface updates any surface commit today is evlauted to full. Until we fix this and can corretly evluate type of surface update, anything which is not page flip or cursor update will be treted as full update chnage and global lock will be aquired. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 80 ++----------------- 1 file changed, 8 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index db38dd0a0c1f..7e0e6b2f22f6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2838,63 +2838,11 @@ static uint32_t remove_from_val_sets( return set_count; } - -static enum surface_update_type amdgpu_dm_check_surfaces_update_type( - struct dc *dc, - const struct dc_surface **new_surfaces, - uint8_t new_surface_count, - const struct dc_stream *dc_stream) -{ - struct dc_surface_update srf_updates[MAX_SURFACES]; - struct dc_flip_addrs flip_addr[MAX_SURFACES]; - struct dc_plane_info plane_info[MAX_SURFACES]; - struct dc_scaling_info scaling_info[MAX_SURFACES]; - int i; - const struct dc_stream_status *stream_status = - dc_stream_get_status(dc_stream); - enum surface_update_type update_type; - - memset(srf_updates, 0, sizeof(srf_updates)); - memset(flip_addr, 0, sizeof(flip_addr)); - memset(plane_info, 0, sizeof(plane_info)); - memset(scaling_info, 0, sizeof(scaling_info)); - - for (i = 0; i < new_surface_count; i++) { - srf_updates[i].surface = new_surfaces[i]; - srf_updates[i].gamma = - (struct dc_gamma *)new_surfaces[i]->gamma_correction; - flip_addr[i].address = new_surfaces[i]->address; - flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; - plane_info[i].color_space = new_surfaces[i]->color_space; - plane_info[i].format = new_surfaces[i]->format; - plane_info[i].plane_size = new_surfaces[i]->plane_size; - plane_info[i].rotation = new_surfaces[i]->rotation; - plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror; - plane_info[i].stereo_format = new_surfaces[i]->stereo_format; - plane_info[i].tiling_info = new_surfaces[i]->tiling_info; - plane_info[i].visible = new_surfaces[i]->visible; - plane_info[i].dcc = new_surfaces[i]->dcc; - scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; - scaling_info[i].src_rect = new_surfaces[i]->src_rect; - scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; - scaling_info[i].clip_rect = new_surfaces[i]->clip_rect; - - srf_updates[i].flip_addr = &flip_addr[i]; - srf_updates[i].plane_info = &plane_info[i]; - srf_updates[i].scaling_info = &scaling_info[i]; - } - - update_type = dc_check_update_surfaces_for_stream( - dc, srf_updates, new_surface_count, NULL, stream_status); - - return update_type; -} - /*` * Grabs all modesetting locks to serialize against any blocking commits, * Waits for completion of all non blocking commits. */ -static void aquire_global_lock( +static void do_aquire_global_lock( struct drm_device *dev, struct drm_atomic_state *state) { @@ -2957,7 +2905,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * This bool will be set for true for any modeset/reset * or surface update which implies non fast surfae update. */ - bool wait_for_prev_commits = false; + bool aquire_global_lock = false; ret = drm_atomic_helper_check(dev, state); @@ -3042,7 +2990,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; - wait_for_prev_commits = true; + aquire_global_lock = true; } else if (modereset_required(crtc_state)) { @@ -3052,7 +3000,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, set, set_count, acrtc->stream); - wait_for_prev_commits = true; + aquire_global_lock = true; } } @@ -3111,7 +3059,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_stream_count++; need_to_validate = true; - wait_for_prev_commits = true; + aquire_global_lock = true; } for (i = 0; i < set_count; i++) { @@ -3177,25 +3125,13 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, surface); need_to_validate = true; + aquire_global_lock = true; } } } context = dc_get_validate_context(dc, set, set_count); - for (i = 0; i < set_count; i++) { - for (j = 0; j < set[i].surface_count; j++) { - if (amdgpu_dm_check_surfaces_update_type( - dc, - set[i].surfaces, - set[i].surface_count, - set[i].stream) > UPDATE_TYPE_FAST) { - wait_for_prev_commits = true; - break; - } - } - } - if (need_to_validate == false || set_count == 0 || context) { ret = 0; @@ -3208,8 +3144,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * will wait for completion of any outstanding flip using DRMs * synchronization events. */ - if (wait_for_prev_commits) - aquire_global_lock(dev, state); + if (aquire_global_lock) + do_aquire_global_lock(dev, state); } -- GitLab From cb26f8925c50aa244ac34a72ac232e4c7dbd6f98 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 20 Jun 2017 17:24:23 -0400 Subject: [PATCH 0559/2898] drm/amd/display: use different sr latencies for dpm0 dcn bw calc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 0aa6662650cc..9cb08365e2b6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -906,6 +906,16 @@ bool dcn_validate_bandwidth( scaler_settings_calculation(v); mode_support_and_system_configuration(v); + if (v->voltage_level == 0) { + struct core_dc *dc_core = DC_TO_CORE(&dc->public); + + v->sr_enter_plus_exit_time = 9.466f; + v->sr_exit_time = 7.849f; + dc_core->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; + dc_core->dml.soc.sr_exit_time_us = v->sr_exit_time; + mode_support_and_system_configuration(v); + } + if (v->voltage_level != 5) { float bw_consumed = v->total_bandwidth_consumed_gbyte_per_second; if (bw_consumed < v->fabric_and_dram_bandwidth_vmin0p65) @@ -1013,6 +1023,14 @@ bool dcn_validate_bandwidth( &dc->dml, context, pool); } + if (v->voltage_level == 0) { + struct core_dc *dc_core = DC_TO_CORE(&dc->public); + + dc_core->dml.soc.sr_enter_plus_exit_time_us = + dc_core->dcn_soc.sr_enter_plus_exit_time; + dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc.sr_exit_time; + } + kernel_fpu_end(); return v->voltage_level != 5; } -- GitLab From 139cb65c5202ba5074d52226931a7d4aaa3307bc Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 21 Jun 2017 09:35:35 -0400 Subject: [PATCH 0560/2898] drm/amd/display: make variable latency into a regkey option Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 11 ++++++++--- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 9cb08365e2b6..3ec702fecfd1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -906,11 +906,16 @@ bool dcn_validate_bandwidth( scaler_settings_calculation(v); mode_support_and_system_configuration(v); - if (v->voltage_level == 0) { + if (v->voltage_level == 0 && + (dc->public.debug.sr_exit_time_dpm0_ns + || dc->public.debug.sr_enter_plus_exit_time_dpm0_ns)) { struct core_dc *dc_core = DC_TO_CORE(&dc->public); - v->sr_enter_plus_exit_time = 9.466f; - v->sr_exit_time = 7.849f; + if (dc->public.debug.sr_enter_plus_exit_time_dpm0_ns) + v->sr_enter_plus_exit_time = + dc->public.debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f; + if (dc->public.debug.sr_exit_time_dpm0_ns) + v->sr_exit_time = dc->public.debug.sr_exit_time_dpm0_ns / 1000.0f; dc_core->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; dc_core->dml.soc.sr_exit_time_us = v->sr_exit_time; mode_support_and_system_configuration(v); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 62493c4a47d1..cb70b6d8be10 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -171,6 +171,8 @@ struct dc_debug { bool disable_pplib_wm_range; bool use_dml_wm; bool disable_pipe_split; + int sr_exit_time_dpm0_ns; + int sr_enter_plus_exit_time_dpm0_ns; int sr_exit_time_ns; int sr_enter_plus_exit_time_ns; int urgent_latency_ns; -- GitLab From 5634fb6078dd9b9f794e93eef2fef52150cdc827 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 15 Jun 2017 14:10:43 -0400 Subject: [PATCH 0561/2898] drm/amd/display: dcn bw_calc_auto update rev 247 to 250 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/dcn_calc_auto.c | 3535 +++++------------ 1 file changed, 897 insertions(+), 2638 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index 21b83e403ef2..bb2f8ad6a988 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -27,32 +27,27 @@ #include "dcn_calc_auto.h" #include "dcn_calc_math.h" -/*REVISION#247*/ +/*REVISION#250*/ void scaler_settings_calculation(struct dcn_bw_internal_vars *v) { int k; - /*scaler settings calculation*/ - - /*scale ratio calculation*/ - for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->allow_different_hratio_vratio == dcn_bw_yes) { if (v->source_scan[k] == dcn_bw_hor) { v->h_ratio[k] = v->viewport_width[k] / v->scaler_rec_out_width[k]; v->v_ratio[k] = v->viewport_height[k] / v->scaler_recout_height[k]; - } else { + } + else { v->h_ratio[k] = v->viewport_height[k] / v->scaler_rec_out_width[k]; v->v_ratio[k] = v->viewport_width[k] / v->scaler_recout_height[k]; } - } else { + } + else { if (v->source_scan[k] == dcn_bw_hor) { - v->h_ratio[k] = dcn_bw_max2( - v->viewport_width[k] / v->scaler_rec_out_width[k], - v->viewport_height[k] / v->scaler_recout_height[k]); - } else { - v->h_ratio[k] = dcn_bw_max2( - v->viewport_height[k] / v->scaler_rec_out_width[k], - v->viewport_width[k] / v->scaler_recout_height[k]); + v->h_ratio[k] =dcn_bw_max2(v->viewport_width[k] / v->scaler_rec_out_width[k], v->viewport_height[k] / v->scaler_recout_height[k]); + } + else { + v->h_ratio[k] =dcn_bw_max2(v->viewport_height[k] / v->scaler_rec_out_width[k], v->viewport_width[k] / v->scaler_recout_height[k]); } v->v_ratio[k] = v->h_ratio[k]; } @@ -68,66 +63,64 @@ void scaler_settings_calculation(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->h_ratio[k] > 1.0) { - v->acceptable_quality_hta_ps = dcn_bw_min2( - v->max_hscl_taps, - 2.0 * dcn_bw_ceil2(v->h_ratio[k], 1.0)); - } else if (v->h_ratio[k] < 1.0) { + v->acceptable_quality_hta_ps =dcn_bw_min2(v->max_hscl_taps, 2.0 *dcn_bw_ceil2(v->h_ratio[k], 1.0)); + } + else if (v->h_ratio[k] < 1.0) { v->acceptable_quality_hta_ps = 4.0; - } else { + } + else { v->acceptable_quality_hta_ps = 1.0; } if (v->ta_pscalculation == dcn_bw_override) { v->htaps[k] = v->override_hta_ps[k]; - } else { + } + else { v->htaps[k] = v->acceptable_quality_hta_ps; } if (v->v_ratio[k] > 1.0) { - v->acceptable_quality_vta_ps = dcn_bw_min2( - v->max_vscl_taps, - 2.0 * dcn_bw_ceil2(v->v_ratio[k], 1.0)); - } else if (v->v_ratio[k] < 1.0) { + v->acceptable_quality_vta_ps =dcn_bw_min2(v->max_vscl_taps, 2.0 *dcn_bw_ceil2(v->v_ratio[k], 1.0)); + } + else if (v->v_ratio[k] < 1.0) { v->acceptable_quality_vta_ps = 4.0; - } else { + } + else { v->acceptable_quality_vta_ps = 1.0; } if (v->ta_pscalculation == dcn_bw_override) { v->vtaps[k] = v->override_vta_ps[k]; - } else { + } + else { v->vtaps[k] = v->acceptable_quality_vta_ps; } - if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { v->vta_pschroma[k] = 0.0; v->hta_pschroma[k] = 0.0; - } else { + } + else { if (v->ta_pscalculation == dcn_bw_override) { v->vta_pschroma[k] = v->override_vta_pschroma[k]; v->hta_pschroma[k] = v->override_hta_pschroma[k]; - } else { + } + else { v->vta_pschroma[k] = v->acceptable_quality_vta_ps; v->hta_pschroma[k] = v->acceptable_quality_hta_ps; } } } } + void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) { - int i, j, k; + int i; + int j; + int k; /*mode support, voltage state and soc configuration*/ /*scale ratio support check*/ v->scale_ratio_support = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->h_ratio[k] > v->max_hscl_ratio || v->v_ratio[k] > v->max_vscl_ratio - || v->h_ratio[k] > v->htaps[k] || v->v_ratio[k] > v->vtaps[k] - || (v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16 - && (v->h_ratio[k] / 2.0 > v->hta_pschroma[k] - || v->v_ratio[k] / 2.0 - > v->vta_pschroma[k]))) { + if (v->h_ratio[k] > v->max_hscl_ratio || v->v_ratio[k] > v->max_vscl_ratio || v->h_ratio[k] > v->htaps[k] || v->v_ratio[k] > v->vtaps[k] || (v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16 && (v->h_ratio[k] / 2.0 > v->hta_pschroma[k] || v->v_ratio[k] / 2.0 > v->vta_pschroma[k]))) { v->scale_ratio_support = dcn_bw_no; } } @@ -135,16 +128,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->source_format_pixel_and_scan_support = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_surface_mode[k] == dcn_bw_sw_linear - && v->source_scan[k] != dcn_bw_hor) - || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x - || v->source_surface_mode[k] == dcn_bw_sw_var_d - || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) - && v->source_pixel_format[k] != dcn_bw_rgb_sub_64)) { + if ((v->source_surface_mode[k] == dcn_bw_sw_linear && !v->source_scan[k] == dcn_bw_hor) || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_var_d || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) && !v->source_pixel_format[k] == dcn_bw_rgb_sub_64)) { v->source_format_pixel_and_scan_support = dcn_bw_no; } } @@ -153,77 +137,62 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->source_scan[k] == dcn_bw_hor) { v->swath_width_ysingle_dpp[k] = v->viewport_width[k]; - } else { + } + else { v->swath_width_ysingle_dpp[k] = v->viewport_height[k]; } if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->byte_per_pixel_in_dety[k] = 8.0; v->byte_per_pixel_in_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { v->byte_per_pixel_in_dety[k] = 4.0; v->byte_per_pixel_in_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { v->byte_per_pixel_in_dety[k] = 2.0; v->byte_per_pixel_in_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->byte_per_pixel_in_dety[k] = 1.0; v->byte_per_pixel_in_detc[k] = 2.0; - } else { - v->byte_per_pixel_in_dety[k] = 4.0f / 3; - v->byte_per_pixel_in_detc[k] = 8.0f / 3; + } + else { + v->byte_per_pixel_in_dety[k] = 4.0f / 3.0f; + v->byte_per_pixel_in_detc[k] = 8.0f / 3.0f; } } v->total_read_bandwidth_consumed_gbyte_per_second = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->read_bandwidth[k] = v->swath_width_ysingle_dpp[k] - * (dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) * v->v_ratio[k] - + dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0 - * v->v_ratio[k] / 2) - / (v->htotal[k] / v->pixel_clock[k]); + v->read_bandwidth[k] = v->swath_width_ysingle_dpp[k] * (dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) * v->v_ratio[k] +dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0 * v->v_ratio[k] / 2) / (v->htotal[k] / v->pixel_clock[k]); if (v->dcc_enable[k] == dcn_bw_yes) { v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256); } - if (v->pte_enable == dcn_bw_yes && v->source_scan[k] != dcn_bw_hor - && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x)) { + if (v->pte_enable == dcn_bw_yes && v->source_scan[k] != dcn_bw_hor && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x)) { v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 64); - } else if (v->pte_enable == dcn_bw_yes && v->source_scan[k] == dcn_bw_hor - && (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32) - && (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x)) { + } + else if (v->pte_enable == dcn_bw_yes && v->source_scan[k] == dcn_bw_hor && (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32) && (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x)) { v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256); - } else if (v->pte_enable == dcn_bw_yes) { + } + else if (v->pte_enable == dcn_bw_yes) { v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 512); } - v->total_read_bandwidth_consumed_gbyte_per_second = - v->total_read_bandwidth_consumed_gbyte_per_second - + v->read_bandwidth[k] / 1000.0; + v->total_read_bandwidth_consumed_gbyte_per_second = v->total_read_bandwidth_consumed_gbyte_per_second + v->read_bandwidth[k] / 1000.0; } v->total_write_bandwidth_consumed_gbyte_per_second = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444) { - v->write_bandwidth[k] = v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k]) * 4.0; - } else if (v->output[k] == dcn_bw_writeback) { - v->write_bandwidth[k] = v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k]) * 1.5; - } else { + v->write_bandwidth[k] = v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 4.0; + } + else if (v->output[k] == dcn_bw_writeback) { + v->write_bandwidth[k] = v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 1.5; + } + else { v->write_bandwidth[k] = 0.0; } - v->total_write_bandwidth_consumed_gbyte_per_second = - v->total_write_bandwidth_consumed_gbyte_per_second - + v->write_bandwidth[k] / 1000.0; + v->total_write_bandwidth_consumed_gbyte_per_second = v->total_write_bandwidth_consumed_gbyte_per_second + v->write_bandwidth[k] / 1000.0; } - v->total_bandwidth_consumed_gbyte_per_second = - v->total_read_bandwidth_consumed_gbyte_per_second - + v->total_write_bandwidth_consumed_gbyte_per_second; + v->total_bandwidth_consumed_gbyte_per_second = v->total_read_bandwidth_consumed_gbyte_per_second + v->total_write_bandwidth_consumed_gbyte_per_second; v->dcc_enabled_in_any_plane = dcn_bw_no; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { @@ -231,119 +200,29 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) } } for (i = 0; i <= number_of_states_plus_one; i++) { - v->return_bw_todcn_per_state = - dcn_bw_min2( - v->return_bus_width * v->dcfclk_per_state[i], - v->fabric_and_dram_bandwidth_per_state[i] * 1000.0 - * v->percent_of_ideal_drambw_received_after_urg_latency - / 100.0); + v->return_bw_todcn_per_state =dcn_bw_min2(v->return_bus_width * v->dcfclk_per_state[i], v->fabric_and_dram_bandwidth_per_state[i] * 1000.0 * v->percent_of_ideal_drambw_received_after_urg_latency / 100.0); v->return_bw_per_state[i] = v->return_bw_todcn_per_state; - if (v->dcc_enabled_in_any_plane == dcn_bw_yes - && v->return_bw_todcn_per_state - > v->dcfclk_per_state[i] * v->return_bus_width - / 4.0) { - v->return_bw_per_state[i] = - dcn_bw_min2( - v->return_bw_per_state[i], - v->return_bw_todcn_per_state * 4.0 - * (1.0 - - v->urgent_latency - / ((v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - / (v->return_bw_todcn_per_state - - v->dcfclk_per_state[i] - * v->return_bus_width - / 4.0) - + v->urgent_latency))); - } - v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] - * v->urgent_latency - / (v->return_bw_todcn_per_state * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0); - if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 - && v->critical_point < 4.0) { - v->return_bw_per_state[i] = - dcn_bw_min2( - v->return_bw_per_state[i], - dcn_bw_pow( - 4.0 - * v->return_bw_todcn_per_state - * (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - * v->return_bus_width - * v->dcfclk_per_state[i] - * v->urgent_latency - / (v->return_bw_todcn_per_state - * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0), - 2)); - } - v->return_bw_todcn_per_state = dcn_bw_min2( - v->return_bus_width * v->dcfclk_per_state[i], - v->fabric_and_dram_bandwidth_per_state[i] * 1000.0); - if (v->dcc_enabled_in_any_plane == dcn_bw_yes - && v->return_bw_todcn_per_state - > v->dcfclk_per_state[i] * v->return_bus_width - / 4.0) { - v->return_bw_per_state[i] = - dcn_bw_min2( - v->return_bw_per_state[i], - v->return_bw_todcn_per_state * 4.0 - * (1.0 - - v->urgent_latency - / ((v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - / (v->return_bw_todcn_per_state - - v->dcfclk_per_state[i] - * v->return_bus_width - / 4.0) - + v->urgent_latency))); - } - v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] - * v->urgent_latency - / (v->return_bw_todcn_per_state * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0); - if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 - && v->critical_point < 4.0) { - v->return_bw_per_state[i] = - dcn_bw_min2( - v->return_bw_per_state[i], - dcn_bw_pow( - 4.0 - * v->return_bw_todcn_per_state - * (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - * v->return_bus_width - * v->dcfclk_per_state[i] - * v->urgent_latency - / (v->return_bw_todcn_per_state - * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0), - 2)); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->return_bw_todcn_per_state > v->dcfclk_per_state[i] * v->return_bus_width / 4.0) { + v->return_bw_per_state[i] =dcn_bw_min2(v->return_bw_per_state[i], v->return_bw_todcn_per_state * 4.0 * (1.0 - v->urgent_latency / ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / (v->return_bw_todcn_per_state - v->dcfclk_per_state[i] * v->return_bus_width / 4.0) + v->urgent_latency))); + } + v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] * v->urgent_latency / (v->return_bw_todcn_per_state * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 && v->critical_point < 4.0) { + v->return_bw_per_state[i] =dcn_bw_min2(v->return_bw_per_state[i], dcn_bw_pow(4.0 * v->return_bw_todcn_per_state * (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 * v->return_bus_width * v->dcfclk_per_state[i] * v->urgent_latency / (v->return_bw_todcn_per_state * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0), 2)); + } + v->return_bw_todcn_per_state =dcn_bw_min2(v->return_bus_width * v->dcfclk_per_state[i], v->fabric_and_dram_bandwidth_per_state[i] * 1000.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->return_bw_todcn_per_state > v->dcfclk_per_state[i] * v->return_bus_width / 4.0) { + v->return_bw_per_state[i] =dcn_bw_min2(v->return_bw_per_state[i], v->return_bw_todcn_per_state * 4.0 * (1.0 - v->urgent_latency / ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / (v->return_bw_todcn_per_state - v->dcfclk_per_state[i] * v->return_bus_width / 4.0) + v->urgent_latency))); + } + v->critical_point = 2.0 * v->return_bus_width * v->dcfclk_per_state[i] * v->urgent_latency / (v->return_bw_todcn_per_state * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_in_any_plane == dcn_bw_yes && v->critical_point > 1.0 && v->critical_point < 4.0) { + v->return_bw_per_state[i] =dcn_bw_min2(v->return_bw_per_state[i], dcn_bw_pow(4.0 * v->return_bw_todcn_per_state * (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 * v->return_bus_width * v->dcfclk_per_state[i] * v->urgent_latency / (v->return_bw_todcn_per_state * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0), 2)); } } for (i = 0; i <= number_of_states_plus_one; i++) { - if ((v->total_read_bandwidth_consumed_gbyte_per_second * 1000.0 - <= v->return_bw_per_state[i]) - && (v->total_bandwidth_consumed_gbyte_per_second * 1000.0 - <= v->fabric_and_dram_bandwidth_per_state[i] - * 1000.0 - * v->percent_of_ideal_drambw_received_after_urg_latency - / 100.0)) { + if ((v->total_read_bandwidth_consumed_gbyte_per_second * 1000.0 <= v->return_bw_per_state[i]) && (v->total_bandwidth_consumed_gbyte_per_second * 1000.0 <= v->fabric_and_dram_bandwidth_per_state[i] * 1000.0 * v->percent_of_ideal_drambw_received_after_urg_latency / 100.0)) { v->bandwidth_support[i] = dcn_bw_yes; - } else { + } + else { v->bandwidth_support[i] = dcn_bw_no; } } @@ -351,36 +230,21 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->writeback_latency_support = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444 - && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) - * 4.0 - > (v->writeback_luma_buffer_size - + v->writeback_chroma_buffer_size) - * 1024.0 / v->write_back_latency) { + if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444 && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 4.0 > (v->writeback_luma_buffer_size + v->writeback_chroma_buffer_size) * 1024.0 / v->write_back_latency) { v->writeback_latency_support = dcn_bw_no; - } else if (v->output[k] == dcn_bw_writeback - && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) - > dcn_bw_min2( - v->writeback_luma_buffer_size, - 2.0 - * v->writeback_chroma_buffer_size) - * 1024.0 / v->write_back_latency) { + } + else if (v->output[k] == dcn_bw_writeback && v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) >dcn_bw_min2(v->writeback_luma_buffer_size, 2.0 * v->writeback_chroma_buffer_size) * 1024.0 / v->write_back_latency) { v->writeback_latency_support = dcn_bw_no; } } /*re-ordering buffer support check*/ for (i = 0; i <= number_of_states_plus_one; i++) { - v->urgent_round_trip_and_out_of_order_latency_per_state[i] = - (v->round_trip_ping_latency_cycles + 32.0) / v->dcfclk_per_state[i] - + v->urgent_out_of_order_return_per_channel - * v->number_of_channels - / v->return_bw_per_state[i]; - if ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 - / v->return_bw_per_state[i] - > v->urgent_round_trip_and_out_of_order_latency_per_state[i]) { + v->urgent_round_trip_and_out_of_order_latency_per_state[i] = (v->round_trip_ping_latency_cycles + 32.0) / v->dcfclk_per_state[i] + v->urgent_out_of_order_return_per_channel * v->number_of_channels / v->return_bw_per_state[i]; + if ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / v->return_bw_per_state[i] > v->urgent_round_trip_and_out_of_order_latency_per_state[i]) { v->rob_support[i] = dcn_bw_yes; - } else { + } + else { v->rob_support[i] = dcn_bw_no; } } @@ -390,28 +254,31 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) if (v->output[k] == dcn_bw_dp && v->dsc_capability == dcn_bw_yes) { if (v->output_format[k] == dcn_bw_420) { v->required_output_bw = v->pixel_clock[k] / 2.0; - } else { + } + else { v->required_output_bw = v->pixel_clock[k]; } - } else if (v->output_format[k] == dcn_bw_420) { + } + else if (v->output_format[k] == dcn_bw_420) { v->required_output_bw = v->pixel_clock[k] * 3.0 / 2.0; - } else { + } + else { v->required_output_bw = v->pixel_clock[k] * 3.0; } if (v->output[k] == dcn_bw_hdmi) { v->required_phyclk[k] = v->required_output_bw / 3.0; - } else if (v->output[k] == dcn_bw_dp) { + } + else if (v->output[k] == dcn_bw_dp) { v->required_phyclk[k] = v->required_output_bw / 4.0; - } else { + } + else { v->required_phyclk[k] = 0.0; } } for (i = 0; i <= number_of_states_plus_one; i++) { v->dio_support[i] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->required_phyclk[k] > v->phyclk_per_state[i] - || (v->output[k] == dcn_bw_hdmi - && v->required_phyclk[k] > 600.0)) { + if (v->required_phyclk[k] > v->phyclk_per_state[i] || (v->output[k] == dcn_bw_hdmi && v->required_phyclk[k] > 600.0)) { v->dio_support[i] = dcn_bw_no; } } @@ -421,244 +288,128 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->total_number_of_active_writeback = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->output[k] == dcn_bw_writeback) { - v->total_number_of_active_writeback = v->total_number_of_active_writeback - + 1.0; + v->total_number_of_active_writeback = v->total_number_of_active_writeback + 1.0; } } if (v->total_number_of_active_writeback <= v->max_num_writeback) { v->total_available_writeback_support = dcn_bw_yes; - } else { + } + else { v->total_available_writeback_support = dcn_bw_no; } /*maximum dispclk/dppclk support check*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->h_ratio[k] > 1.0) { - v->pscl_factor[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput * v->h_ratio[k] - / dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); - } else { - v->pscl_factor[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput); + v->pscl_factor[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput * v->h_ratio[k] /dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); + } + else { + v->pscl_factor[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput); } if (v->byte_per_pixel_in_detc[k] == 0.0) { v->pscl_factor_chroma[k] = 0.0; - v->min_dppclk_using_single_dpp[k] = - v->pixel_clock[k] - * dcn_bw_max3( - v->vtaps[k] / 6.0 - * dcn_bw_min2( - 1.0, - v->h_ratio[k]), - v->h_ratio[k] - * v->v_ratio[k] - / v->pscl_factor[k], - 1.0); - } else { + v->min_dppclk_using_single_dpp[k] = v->pixel_clock[k] *dcn_bw_max3(v->vtaps[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k]), v->h_ratio[k] * v->v_ratio[k] / v->pscl_factor[k], 1.0); + } + else { if (v->h_ratio[k] / 2.0 > 1.0) { - v->pscl_factor_chroma[k] = - dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput - * v->h_ratio[k] - / 2.0 - / dcn_bw_ceil2( - v->hta_pschroma[k] - / 6.0, - 1.0)); - } else { - v->pscl_factor_chroma[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput); - } - v->min_dppclk_using_single_dpp[k] = - v->pixel_clock[k] - * dcn_bw_max5( - v->vtaps[k] / 6.0 - * dcn_bw_min2( - 1.0, - v->h_ratio[k]), - v->h_ratio[k] - * v->v_ratio[k] - / v->pscl_factor[k], - v->vta_pschroma[k] / 6.0 - * dcn_bw_min2( - 1.0, - v->h_ratio[k] - / 2.0), - v->h_ratio[k] - * v->v_ratio[k] - / 4.0 - / v->pscl_factor_chroma[k], - 1.0); + v->pscl_factor_chroma[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput * v->h_ratio[k] / 2.0 /dcn_bw_ceil2(v->hta_pschroma[k] / 6.0, 1.0)); + } + else { + v->pscl_factor_chroma[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput); + } + v->min_dppclk_using_single_dpp[k] = v->pixel_clock[k] *dcn_bw_max5(v->vtaps[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k]), v->h_ratio[k] * v->v_ratio[k] / v->pscl_factor[k], v->vta_pschroma[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k] / 2.0), v->h_ratio[k] * v->v_ratio[k] / 4.0 / v->pscl_factor_chroma[k], 1.0); } } for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->read256_block_height_y[k] = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->read256_block_height_y[k] = 4.0; - } else { + } + else { v->read256_block_height_y[k] = 8.0; } - v->read256_block_width_y[k] = 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) - / v->read256_block_height_y[k]; + v->read256_block_width_y[k] = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->read256_block_height_y[k]; v->read256_block_height_c[k] = 0.0; v->read256_block_width_c[k] = 0.0; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->read256_block_height_y[k] = 1.0; v->read256_block_height_c[k] = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->read256_block_height_y[k] = 16.0; v->read256_block_height_c[k] = 8.0; - } else { + } + else { v->read256_block_height_y[k] = 8.0; v->read256_block_height_c[k] = 8.0; } - v->read256_block_width_y[k] = 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) - / v->read256_block_height_y[k]; - v->read256_block_width_c[k] = 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) - / v->read256_block_height_c[k]; + v->read256_block_width_y[k] = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->read256_block_height_y[k]; + v->read256_block_width_c[k] = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->read256_block_height_c[k]; } if (v->source_scan[k] == dcn_bw_hor) { v->max_swath_height_y[k] = v->read256_block_height_y[k]; v->max_swath_height_c[k] = v->read256_block_height_c[k]; - } else { + } + else { v->max_swath_height_y[k] = v->read256_block_width_y[k]; v->max_swath_height_c[k] = v->read256_block_width_c[k]; } - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { - if (v->source_surface_mode[k] == dcn_bw_sw_linear - || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - && (v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_var_s - || v->source_surface_mode[k] - == dcn_bw_sw_var_s_x) - && v->source_scan[k] == dcn_bw_hor)) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_var_s || v->source_surface_mode[k] == dcn_bw_sw_var_s_x) && v->source_scan[k] == dcn_bw_hor)) { v->min_swath_height_y[k] = v->max_swath_height_y[k]; - } else { + } + else { v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; } v->min_swath_height_c[k] = v->max_swath_height_c[k]; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->min_swath_height_y[k] = v->max_swath_height_y[k]; v->min_swath_height_c[k] = v->max_swath_height_c[k]; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 - && v->source_scan[k] == dcn_bw_hor) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 && v->source_scan[k] == dcn_bw_hor) { v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; - if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed - == dcn_bw_yes) { + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes) { v->min_swath_height_c[k] = v->max_swath_height_c[k]; - } else { + } + else { v->min_swath_height_c[k] = v->max_swath_height_c[k] / 2.0; } - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 - && v->source_scan[k] == dcn_bw_hor) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 && v->source_scan[k] == dcn_bw_hor) { v->min_swath_height_c[k] = v->max_swath_height_c[k] / 2.0; - if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed - == dcn_bw_yes) { + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes) { v->min_swath_height_y[k] = v->max_swath_height_y[k]; - } else { + } + else { v->min_swath_height_y[k] = v->max_swath_height_y[k] / 2.0; } - } else { + } + else { v->min_swath_height_y[k] = v->max_swath_height_y[k]; v->min_swath_height_c[k] = v->max_swath_height_c[k]; } } if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->maximum_swath_width = 8192.0; - } else { + } + else { v->maximum_swath_width = 5120.0; } - v->number_of_dpp_required_for_det_size = - dcn_bw_ceil2( - v->swath_width_ysingle_dpp[k] - / dcn_bw_min2( - v->maximum_swath_width, - v->det_buffer_size_in_kbyte - * 1024.0 - / 2.0 - / (v->byte_per_pixel_in_dety[k] - * v->min_swath_height_y[k] - + v->byte_per_pixel_in_detc[k] - / 2.0 - * v->min_swath_height_c[k])), - 1.0); + v->number_of_dpp_required_for_det_size =dcn_bw_ceil2(v->swath_width_ysingle_dpp[k] /dcn_bw_min2(v->maximum_swath_width, v->det_buffer_size_in_kbyte * 1024.0 / 2.0 / (v->byte_per_pixel_in_dety[k] * v->min_swath_height_y[k] + v->byte_per_pixel_in_detc[k] / 2.0 * v->min_swath_height_c[k])), 1.0); if (v->byte_per_pixel_in_detc[k] == 0.0) { - v->number_of_dpp_required_for_lb_size = dcn_bw_ceil2( - (v->vtaps[k] - + dcn_bw_max2( - dcn_bw_ceil2(v->v_ratio[k], 1.0) - - 2, - 0.0)) - * v->swath_width_ysingle_dpp[k] - / dcn_bw_max2(v->h_ratio[k], 1.0) - * v->lb_bit_per_pixel[k] - / v->line_buffer_size, - 1.0); - } else { - v->number_of_dpp_required_for_lb_size = - dcn_bw_max2( - dcn_bw_ceil2( - (v->vtaps[k] - + dcn_bw_max2( - dcn_bw_ceil2( - v->v_ratio[k], - 1.0) - - 2, - 0.0)) - * v->swath_width_ysingle_dpp[k] - / dcn_bw_max2( - v->h_ratio[k], - 1.0) - * v->lb_bit_per_pixel[k] - / v->line_buffer_size, - 1.0), - dcn_bw_ceil2( - (v->vta_pschroma[k] - + dcn_bw_max2( - dcn_bw_ceil2( - v->v_ratio[k] - / 2.0, - 1.0) - - 2, - 0.0)) - * v->swath_width_ysingle_dpp[k] - / 2.0 - / dcn_bw_max2( - v->h_ratio[k] - / 2.0, - 1.0) - * v->lb_bit_per_pixel[k] - / v->line_buffer_size, - 1.0)); - } - v->number_of_dpp_required_for_det_and_lb_size[k] = dcn_bw_max2( - v->number_of_dpp_required_for_det_size, - v->number_of_dpp_required_for_lb_size); + v->number_of_dpp_required_for_lb_size =dcn_bw_ceil2((v->vtaps[k] +dcn_bw_max2(dcn_bw_ceil2(v->v_ratio[k], 1.0) - 2, 0.0)) * v->swath_width_ysingle_dpp[k] /dcn_bw_max2(v->h_ratio[k], 1.0) * v->lb_bit_per_pixel[k] / v->line_buffer_size, 1.0); + } + else { + v->number_of_dpp_required_for_lb_size =dcn_bw_max2(dcn_bw_ceil2((v->vtaps[k] +dcn_bw_max2(dcn_bw_ceil2(v->v_ratio[k], 1.0) - 2, 0.0)) * v->swath_width_ysingle_dpp[k] /dcn_bw_max2(v->h_ratio[k], 1.0) * v->lb_bit_per_pixel[k] / v->line_buffer_size, 1.0),dcn_bw_ceil2((v->vta_pschroma[k] +dcn_bw_max2(dcn_bw_ceil2(v->v_ratio[k] / 2.0, 1.0) - 2, 0.0)) * v->swath_width_ysingle_dpp[k] / 2.0 /dcn_bw_max2(v->h_ratio[k] / 2.0, 1.0) * v->lb_bit_per_pixel[k] / v->line_buffer_size, 1.0)); + } + v->number_of_dpp_required_for_det_and_lb_size[k] =dcn_bw_max2(v->number_of_dpp_required_for_det_size, v->number_of_dpp_required_for_lb_size); } for (i = 0; i <= number_of_states_plus_one; i++) { for (j = 0; j <= 1; j++) { @@ -666,119 +417,58 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->required_dispclk[i][j] = 0.0; v->dispclk_dppclk_support[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->min_dispclk_using_single_dpp = dcn_bw_max2( - v->pixel_clock[k], - v->min_dppclk_using_single_dpp[k] * (j + 1)) - * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_single_dpp =dcn_bw_max2(v->pixel_clock[k], v->min_dppclk_using_single_dpp[k] * (j + 1)) * (1.0 + v->downspreading / 100.0); if (v->odm_capability == dcn_bw_yes) { - v->min_dispclk_using_dual_dpp = dcn_bw_max2( - v->pixel_clock[k] / 2.0, - v->min_dppclk_using_single_dpp[k] / 2.0 - * (j + 1)) - * (1.0 + v->downspreading / 100.0); - } else { - v->min_dispclk_using_dual_dpp = dcn_bw_max2( - v->pixel_clock[k], - v->min_dppclk_using_single_dpp[k] / 2.0 - * (j + 1)) - * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_dual_dpp =dcn_bw_max2(v->pixel_clock[k] / 2.0, v->min_dppclk_using_single_dpp[k] / 2.0 * (j + 1)) * (1.0 + v->downspreading / 100.0); + } + else { + v->min_dispclk_using_dual_dpp =dcn_bw_max2(v->pixel_clock[k], v->min_dppclk_using_single_dpp[k] / 2.0 * (j + 1)) * (1.0 + v->downspreading / 100.0); } if (i < number_of_states) { - v->min_dispclk_using_single_dpp = - v->min_dispclk_using_single_dpp - * (1.0 - + v->dispclk_ramping_margin - / 100.0); - v->min_dispclk_using_dual_dpp = - v->min_dispclk_using_dual_dpp - * (1.0 - + v->dispclk_ramping_margin - / 100.0); - } - if (v->min_dispclk_using_single_dpp - <= dcn_bw_min2( - v->max_dispclk[i], - (j + 1) * v->max_dppclk[i]) - && v->number_of_dpp_required_for_det_and_lb_size[k] - <= 1.0) { + v->min_dispclk_using_single_dpp = v->min_dispclk_using_single_dpp * (1.0 + v->dispclk_ramping_margin / 100.0); + v->min_dispclk_using_dual_dpp = v->min_dispclk_using_dual_dpp * (1.0 + v->dispclk_ramping_margin / 100.0); + } + if (v->min_dispclk_using_single_dpp <=dcn_bw_min2(v->max_dispclk[i], (j + 1) * v->max_dppclk[i]) && v->number_of_dpp_required_for_det_and_lb_size[k] <= 1.0) { v->no_of_dpp[i][j][k] = 1.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_single_dpp); - } else if (v->min_dispclk_using_dual_dpp - <= dcn_bw_min2( - v->max_dispclk[i], - (j + 1) * v->max_dppclk[i])) { + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_single_dpp); + } + else if (v->min_dispclk_using_dual_dpp <=dcn_bw_min2(v->max_dispclk[i], (j + 1) * v->max_dppclk[i])) { v->no_of_dpp[i][j][k] = 2.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_dual_dpp); - } else { + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_dual_dpp); + } + else { v->no_of_dpp[i][j][k] = 2.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_dual_dpp); + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_dual_dpp); v->dispclk_dppclk_support[i][j] = dcn_bw_no; } - v->total_number_of_active_dpp[i][j] = - v->total_number_of_active_dpp[i][j] - + v->no_of_dpp[i][j][k]; + v->total_number_of_active_dpp[i][j] = v->total_number_of_active_dpp[i][j] + v->no_of_dpp[i][j][k]; } if (v->total_number_of_active_dpp[i][j] > v->max_num_dpp) { v->total_number_of_active_dpp[i][j] = 0.0; v->required_dispclk[i][j] = 0.0; v->dispclk_dppclk_support[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->min_dispclk_using_single_dpp = dcn_bw_max2( - v->pixel_clock[k], - v->min_dppclk_using_single_dpp[k] * (j + 1)) - * (1.0 + v->downspreading / 100.0); - v->min_dispclk_using_dual_dpp = dcn_bw_max2( - v->pixel_clock[k], - v->min_dppclk_using_single_dpp[k] / 2.0 - * (j + 1)) - * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_single_dpp =dcn_bw_max2(v->pixel_clock[k], v->min_dppclk_using_single_dpp[k] * (j + 1)) * (1.0 + v->downspreading / 100.0); + v->min_dispclk_using_dual_dpp =dcn_bw_max2(v->pixel_clock[k], v->min_dppclk_using_single_dpp[k] / 2.0 * (j + 1)) * (1.0 + v->downspreading / 100.0); if (i < number_of_states) { - v->min_dispclk_using_single_dpp = - v->min_dispclk_using_single_dpp - * (1.0 - + v->dispclk_ramping_margin - / 100.0); - v->min_dispclk_using_dual_dpp = - v->min_dispclk_using_dual_dpp - * (1.0 - + v->dispclk_ramping_margin - / 100.0); + v->min_dispclk_using_single_dpp = v->min_dispclk_using_single_dpp * (1.0 + v->dispclk_ramping_margin / 100.0); + v->min_dispclk_using_dual_dpp = v->min_dispclk_using_dual_dpp * (1.0 + v->dispclk_ramping_margin / 100.0); } - if (v->number_of_dpp_required_for_det_and_lb_size[k] - <= 1.0) { + if (v->number_of_dpp_required_for_det_and_lb_size[k] <= 1.0) { v->no_of_dpp[i][j][k] = 1.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_single_dpp); - if (v->min_dispclk_using_single_dpp - > dcn_bw_min2( - v->max_dispclk[i], - (j + 1) - * v->max_dppclk[i])) { + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_single_dpp); + if (v->min_dispclk_using_single_dpp >dcn_bw_min2(v->max_dispclk[i], (j + 1) * v->max_dppclk[i])) { v->dispclk_dppclk_support[i][j] = dcn_bw_no; } - } else { + } + else { v->no_of_dpp[i][j][k] = 2.0; - v->required_dispclk[i][j] = dcn_bw_max2( - v->required_dispclk[i][j], - v->min_dispclk_using_dual_dpp); - if (v->min_dispclk_using_dual_dpp - > dcn_bw_min2( - v->max_dispclk[i], - (j + 1) - * v->max_dppclk[i])) { + v->required_dispclk[i][j] =dcn_bw_max2(v->required_dispclk[i][j], v->min_dispclk_using_dual_dpp); + if (v->min_dispclk_using_dual_dpp >dcn_bw_min2(v->max_dispclk[i], (j + 1) * v->max_dppclk[i])) { v->dispclk_dppclk_support[i][j] = dcn_bw_no; } } - v->total_number_of_active_dpp[i][j] = - v->total_number_of_active_dpp[i][j] - + v->no_of_dpp[i][j][k]; + v->total_number_of_active_dpp[i][j] = v->total_number_of_active_dpp[i][j] + v->no_of_dpp[i][j][k]; } } } @@ -797,7 +487,8 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (j = 0; j <= 1; j++) { if (v->total_number_of_active_dpp[i][j] <= v->max_num_dpp) { v->total_available_pipes_support[i][j] = dcn_bw_yes; - } else { + } + else { v->total_available_pipes_support[i][j] = dcn_bw_no; } } @@ -807,167 +498,48 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { for (i = 0; i <= number_of_states_plus_one; i++) { for (j = 0; j <= 1; j++) { - v->swath_width_yper_state[i][j][k] = v->swath_width_ysingle_dpp[k] - / v->no_of_dpp[i][j][k]; - v->swath_width_granularity_y = 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) - / v->max_swath_height_y[k]; - v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2( - v->swath_width_yper_state[i][j][k] - 1.0, - v->swath_width_granularity_y) - + v->swath_width_granularity_y) - * v->byte_per_pixel_in_dety[k] - * v->max_swath_height_y[k]; + v->swath_width_yper_state[i][j][k] = v->swath_width_ysingle_dpp[k] / v->no_of_dpp[i][j][k]; + v->swath_width_granularity_y = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->max_swath_height_y[k]; + v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2(v->swath_width_yper_state[i][j][k] - 1.0, v->swath_width_granularity_y) + v->swath_width_granularity_y) * v->byte_per_pixel_in_dety[k] * v->max_swath_height_y[k]; if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_y = dcn_bw_ceil2( - v->rounded_up_max_swath_size_bytes_y, - 256.0) + 256; + v->rounded_up_max_swath_size_bytes_y =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_y, 256.0) + 256; } if (v->max_swath_height_c[k] > 0.0) { - v->swath_width_granularity_c = - 256.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / v->max_swath_height_c[k]; - } - v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2( - v->swath_width_yper_state[i][j][k] / 2.0 - 1.0, - v->swath_width_granularity_c) - + v->swath_width_granularity_c) - * v->byte_per_pixel_in_detc[k] - * v->max_swath_height_c[k]; + v->swath_width_granularity_c = 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->max_swath_height_c[k]; + } + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2(v->swath_width_yper_state[i][j][k] / 2.0 - 1.0, v->swath_width_granularity_c) + v->swath_width_granularity_c) * v->byte_per_pixel_in_detc[k] * v->max_swath_height_c[k]; if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2( - v->rounded_up_max_swath_size_bytes_c, - 256.0) + 256; - } - if (v->rounded_up_max_swath_size_bytes_y - + v->rounded_up_max_swath_size_bytes_c - <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { - v->swath_height_yper_state[i][j][k] = - v->max_swath_height_y[k]; - v->swath_height_cper_state[i][j][k] = - v->max_swath_height_c[k]; - } else { - v->swath_height_yper_state[i][j][k] = - v->min_swath_height_y[k]; - v->swath_height_cper_state[i][j][k] = - v->min_swath_height_c[k]; + v->rounded_up_max_swath_size_bytes_c =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_c, 256.0) + 256; + } + if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { + v->swath_height_yper_state[i][j][k] = v->max_swath_height_y[k]; + v->swath_height_cper_state[i][j][k] = v->max_swath_height_c[k]; + } + else { + v->swath_height_yper_state[i][j][k] = v->min_swath_height_y[k]; + v->swath_height_cper_state[i][j][k] = v->min_swath_height_c[k]; } if (v->byte_per_pixel_in_detc[k] == 0.0) { - v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 - / v->byte_per_pixel_in_dety[k] - / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 / v->byte_per_pixel_in_dety[k] / v->swath_width_yper_state[i][j][k]; v->lines_in_det_chroma = 0.0; - } else if (v->swath_height_yper_state[i][j][k] - <= v->swath_height_cper_state[i][j][k]) { - v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 - / 2.0 / v->byte_per_pixel_in_dety[k] - / v->swath_width_yper_state[i][j][k]; - v->lines_in_det_chroma = - v->det_buffer_size_in_kbyte * 1024.0 / 2.0 - / v->byte_per_pixel_in_detc[k] - / (v->swath_width_yper_state[i][j][k] - / 2.0); - } else { - v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 - * 2.0 / 3.0 / v->byte_per_pixel_in_dety[k] - / v->swath_width_yper_state[i][j][k]; - v->lines_in_det_chroma = - v->det_buffer_size_in_kbyte * 1024.0 / 3.0 - / v->byte_per_pixel_in_dety[k] - / (v->swath_width_yper_state[i][j][k] - / 2.0); - } - v->effective_lb_latency_hiding_source_lines_luma = - dcn_bw_min2( - v->max_line_buffer_lines, - dcn_bw_floor2( - v->line_buffer_size - / v->lb_bit_per_pixel[k] - / (v->swath_width_yper_state[i][j][k] - / dcn_bw_max2( - v->h_ratio[k], - 1.0)), - 1.0)) - - (v->vtaps[k] - 1.0); - v->effective_lb_latency_hiding_source_lines_chroma = - dcn_bw_min2( - v->max_line_buffer_lines, - dcn_bw_floor2( - v->line_buffer_size - / v->lb_bit_per_pixel[k] - / (v->swath_width_yper_state[i][j][k] - / 2.0 - / dcn_bw_max2( - v->h_ratio[k] - / 2.0, - 1.0)), - 1.0)) - - (v->vta_pschroma[k] - 1.0); - v->effective_detlb_lines_luma = - dcn_bw_floor2( - v->lines_in_det_luma - + dcn_bw_min2( - v->lines_in_det_luma - * v->required_dispclk[i][j] - * v->byte_per_pixel_in_dety[k] - * v->pscl_factor[k] - / v->return_bw_per_state[i], - v->effective_lb_latency_hiding_source_lines_luma), - v->swath_height_yper_state[i][j][k]); - v->effective_detlb_lines_chroma = - dcn_bw_floor2( - v->lines_in_det_chroma - + dcn_bw_min2( - v->lines_in_det_chroma - * v->required_dispclk[i][j] - * v->byte_per_pixel_in_detc[k] - * v->pscl_factor_chroma[k] - / v->return_bw_per_state[i], - v->effective_lb_latency_hiding_source_lines_chroma), - v->swath_height_cper_state[i][j][k]); + } + else if (v->swath_height_yper_state[i][j][k] <= v->swath_height_cper_state[i][j][k]) { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 / 2.0 / v->byte_per_pixel_in_dety[k] / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = v->det_buffer_size_in_kbyte * 1024.0 / 2.0 / v->byte_per_pixel_in_detc[k] / (v->swath_width_yper_state[i][j][k] / 2.0); + } + else { + v->lines_in_det_luma = v->det_buffer_size_in_kbyte * 1024.0 * 2.0 / 3.0 / v->byte_per_pixel_in_dety[k] / v->swath_width_yper_state[i][j][k]; + v->lines_in_det_chroma = v->det_buffer_size_in_kbyte * 1024.0 / 3.0 / v->byte_per_pixel_in_dety[k] / (v->swath_width_yper_state[i][j][k] / 2.0); + } + v->effective_lb_latency_hiding_source_lines_luma =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_yper_state[i][j][k] /dcn_bw_max2(v->h_ratio[k], 1.0)), 1.0)) - (v->vtaps[k] - 1.0); + v->effective_lb_latency_hiding_source_lines_chroma =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_yper_state[i][j][k] / 2.0 /dcn_bw_max2(v->h_ratio[k] / 2.0, 1.0)), 1.0)) - (v->vta_pschroma[k] - 1.0); + v->effective_detlb_lines_luma =dcn_bw_floor2(v->lines_in_det_luma +dcn_bw_min2(v->lines_in_det_luma * v->required_dispclk[i][j] * v->byte_per_pixel_in_dety[k] * v->pscl_factor[k] / v->return_bw_per_state[i], v->effective_lb_latency_hiding_source_lines_luma), v->swath_height_yper_state[i][j][k]); + v->effective_detlb_lines_chroma =dcn_bw_floor2(v->lines_in_det_chroma +dcn_bw_min2(v->lines_in_det_chroma * v->required_dispclk[i][j] * v->byte_per_pixel_in_detc[k] * v->pscl_factor_chroma[k] / v->return_bw_per_state[i], v->effective_lb_latency_hiding_source_lines_chroma), v->swath_height_cper_state[i][j][k]); if (v->byte_per_pixel_in_detc[k] == 0.0) { - v->urgent_latency_support_us_per_state[i][j][k] = - v->effective_detlb_lines_luma - * (v->htotal[k] - / v->pixel_clock[k]) - / v->v_ratio[k] - - v->effective_detlb_lines_luma - * v->swath_width_yper_state[i][j][k] - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / (v->return_bw_per_state[i] - / v->no_of_dpp[i][j][k]); - } else { - v->urgent_latency_support_us_per_state[i][j][k] = - dcn_bw_min2( - v->effective_detlb_lines_luma - * (v->htotal[k] - / v->pixel_clock[k]) - / v->v_ratio[k] - - v->effective_detlb_lines_luma - * v->swath_width_yper_state[i][j][k] - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / (v->return_bw_per_state[i] - / v->no_of_dpp[i][j][k]), - v->effective_detlb_lines_chroma - * (v->htotal[k] - / v->pixel_clock[k]) - / (v->v_ratio[k] - / 2.0) - - v->effective_detlb_lines_chroma - * v->swath_width_yper_state[i][j][k] - / 2.0 - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / (v->return_bw_per_state[i] - / v->no_of_dpp[i][j][k])); + v->urgent_latency_support_us_per_state[i][j][k] = v->effective_detlb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_detlb_lines_luma * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k]); + } + else { + v->urgent_latency_support_us_per_state[i][j][k] =dcn_bw_min2(v->effective_detlb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_detlb_lines_luma * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k]), v->effective_detlb_lines_chroma * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) - v->effective_detlb_lines_chroma * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / (v->return_bw_per_state[i] / v->no_of_dpp[i][j][k])); } } } @@ -976,8 +548,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (j = 0; j <= 1; j++) { v->urgent_latency_support[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->urgent_latency_support_us_per_state[i][j][k] - < v->urgent_latency / 1.0) { + if (v->urgent_latency_support_us_per_state[i][j][k] < v->urgent_latency / 1.0) { v->urgent_latency_support[i][j] = dcn_bw_no; } } @@ -990,9 +561,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->total_number_of_dcc_active_dpp[i][j] = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { - v->total_number_of_dcc_active_dpp[i][j] = - v->total_number_of_dcc_active_dpp[i][j] - + v->no_of_dpp[i][j][k]; + v->total_number_of_dcc_active_dpp[i][j] = v->total_number_of_dcc_active_dpp[i][j] + v->no_of_dpp[i][j][k]; } } } @@ -1001,143 +570,50 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (j = 0; j <= 1; j++) { v->projected_dcfclk_deep_sleep = 8.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->projected_dcfclk_deep_sleep = dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - v->pixel_clock[k] / 16.0); + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, v->pixel_clock[k] / 16.0); if (v->byte_per_pixel_in_detc[k] == 0.0) { if (v->v_ratio[k] <= 1.0) { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 64.0 - * v->h_ratio[k] - * v->pixel_clock[k] - / v->no_of_dpp[i][j][k]); - } else { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 64.0 - * v->pscl_factor[k] - * v->required_dispclk[i][j] - / (1 - + j)); + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 64.0 * v->h_ratio[k] * v->pixel_clock[k] / v->no_of_dpp[i][j][k]); + } + else { + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 64.0 * v->pscl_factor[k] * v->required_dispclk[i][j] / (1 + j)); } - } else { + } + else { if (v->v_ratio[k] <= 1.0) { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 32.0 - * v->h_ratio[k] - * v->pixel_clock[k] - / v->no_of_dpp[i][j][k]); - } else { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 32.0 - * v->pscl_factor[k] - * v->required_dispclk[i][j] - / (1 - + j)); + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 32.0 * v->h_ratio[k] * v->pixel_clock[k] / v->no_of_dpp[i][j][k]); + } + else { + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 32.0 * v->pscl_factor[k] * v->required_dispclk[i][j] / (1 + j)); } if (v->v_ratio[k] / 2.0 <= 1.0) { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 32.0 - * v->h_ratio[k] - / 2.0 - * v->pixel_clock[k] - / v->no_of_dpp[i][j][k]); - } else { - v->projected_dcfclk_deep_sleep = - dcn_bw_max2( - v->projected_dcfclk_deep_sleep, - 1.1 - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 32.0 - * v->pscl_factor_chroma[k] - * v->required_dispclk[i][j] - / (1 - + j)); + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 32.0 * v->h_ratio[k] / 2.0 * v->pixel_clock[k] / v->no_of_dpp[i][j][k]); + } + else { + v->projected_dcfclk_deep_sleep =dcn_bw_max2(v->projected_dcfclk_deep_sleep, 1.1 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 32.0 * v->pscl_factor_chroma[k] * v->required_dispclk[i][j] / (1 + j)); } } } for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { v->meta_req_height_y = 8.0 * v->read256_block_height_y[k]; - v->meta_req_width_y = - 64.0 * 256.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / v->meta_req_height_y; - v->meta_surface_width_y = dcn_bw_ceil2( - v->viewport_width[k] / v->no_of_dpp[i][j][k] - - 1.0, - v->meta_req_width_y) + v->meta_req_width_y; - v->meta_surface_height_y = dcn_bw_ceil2( - v->viewport_height[k] - 1.0, - v->meta_req_height_y) - + v->meta_req_height_y; + v->meta_req_width_y = 64.0 * 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->meta_req_height_y; + v->meta_surface_width_y =dcn_bw_ceil2(v->viewport_width[k] / v->no_of_dpp[i][j][k] - 1.0, v->meta_req_width_y) + v->meta_req_width_y; + v->meta_surface_height_y =dcn_bw_ceil2(v->viewport_height[k] - 1.0, v->meta_req_height_y) + v->meta_req_height_y; if (v->pte_enable == dcn_bw_yes) { - v->meta_pte_bytes_per_frame_y = - (dcn_bw_ceil2( - (v->meta_surface_width_y - * v->meta_surface_height_y - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 256.0 - - 4096.0) - / 8.0 - / 4096.0, - 1.0) + 1) * 64.0; - } else { + v->meta_pte_bytes_per_frame_y = (dcn_bw_ceil2((v->meta_surface_width_y * v->meta_surface_height_y *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 256.0 - 4096.0) / 8.0 / 4096.0, 1.0) + 1) * 64.0; + } + else { v->meta_pte_bytes_per_frame_y = 0.0; } if (v->source_scan[k] == dcn_bw_hor) { - v->meta_row_bytes_y = - v->meta_surface_width_y - * v->meta_req_height_y - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 256.0; - } else { - v->meta_row_bytes_y = - v->meta_surface_height_y - * v->meta_req_width_y - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / 256.0; + v->meta_row_bytes_y = v->meta_surface_width_y * v->meta_req_height_y *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 256.0; } - } else { + else { + v->meta_row_bytes_y = v->meta_surface_height_y * v->meta_req_width_y *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / 256.0; + } + } + else { v->meta_pte_bytes_per_frame_y = 0.0; v->meta_row_bytes_y = 0.0; } @@ -1145,153 +621,59 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->macro_tile_block_size_bytes_y = 256.0; v->macro_tile_block_height_y = 1.0; - } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { v->macro_tile_block_size_bytes_y = 4096.0; - v->macro_tile_block_height_y = 4.0 - * v->read256_block_height_y[k]; - } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_block_height_y = 4.0 * v->read256_block_height_y[k]; + } + else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { v->macro_tile_block_size_bytes_y = 64.0 * 1024; - v->macro_tile_block_height_y = 16.0 - * v->read256_block_height_y[k]; - } else { + v->macro_tile_block_height_y = 16.0 * v->read256_block_height_y[k]; + } + else { v->macro_tile_block_size_bytes_y = 256.0 * 1024; - v->macro_tile_block_height_y = 32.0 - * v->read256_block_height_y[k]; + v->macro_tile_block_height_y = 32.0 * v->read256_block_height_y[k]; } if (v->macro_tile_block_size_bytes_y <= 65536.0) { - v->data_pte_req_height_y = - v->macro_tile_block_height_y; - } else { - v->data_pte_req_height_y = 16.0 - * v->read256_block_height_y[k]; + v->data_pte_req_height_y = v->macro_tile_block_height_y; + } + else { + v->data_pte_req_height_y = 16.0 * v->read256_block_height_y[k]; } - v->data_pte_req_width_y = - 4096.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - / v->data_pte_req_height_y - * 8; + v->data_pte_req_width_y = 4096.0 /dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) / v->data_pte_req_height_y * 8; if (v->source_surface_mode[k] == dcn_bw_sw_linear) { - v->dpte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - * dcn_bw_min2( - 128.0, - dcn_bw_pow( - 2.0, - dcn_bw_floor2( - dcn_bw_log( - v->pte_buffer_size_in_requests - * v->data_pte_req_width_y - / (v->viewport_width[k] - / v->no_of_dpp[i][j][k]), - 2.0), - 1.0))) - - 1.0) - / v->data_pte_req_width_y, - 1.0) - + 1); - } else if (v->source_scan[k] == dcn_bw_hor) { - v->dpte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - - 1.0) - / v->data_pte_req_width_y, - 1.0) - + 1); - } else { - v->dpte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_height[k] - - 1.0) - / v->data_pte_req_height_y, - 1.0) - + 1); + v->dpte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->viewport_width[k] / v->no_of_dpp[i][j][k] *dcn_bw_min2(128.0, dcn_bw_pow(2.0,dcn_bw_floor2(dcn_bw_log(v->pte_buffer_size_in_requests * v->data_pte_req_width_y / (v->viewport_width[k] / v->no_of_dpp[i][j][k]), 2.0), 1.0))) - 1.0) / v->data_pte_req_width_y, 1.0) + 1); + } + else if (v->source_scan[k] == dcn_bw_hor) { + v->dpte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->viewport_width[k] / v->no_of_dpp[i][j][k] - 1.0) / v->data_pte_req_width_y, 1.0) + 1); + } + else { + v->dpte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->viewport_height[k] - 1.0) / v->data_pte_req_height_y, 1.0) + 1); } - } else { + } + else { v->dpte_bytes_per_row_y = 0.0; } - if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { if (v->dcc_enable[k] == dcn_bw_yes) { - v->meta_req_height_c = 8.0 - * v->read256_block_height_c[k]; - v->meta_req_width_c = - 64.0 * 256.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / v->meta_req_height_c; - v->meta_surface_width_c = - dcn_bw_ceil2( - v->viewport_width[k] - / v->no_of_dpp[i][j][k] - / 2.0 - - 1.0, - v->meta_req_width_c) - + v->meta_req_width_c; - v->meta_surface_height_c = dcn_bw_ceil2( - v->viewport_height[k] / 2.0 - 1.0, - v->meta_req_height_c) - + v->meta_req_height_c; + v->meta_req_height_c = 8.0 * v->read256_block_height_c[k]; + v->meta_req_width_c = 64.0 * 256.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->meta_req_height_c; + v->meta_surface_width_c =dcn_bw_ceil2(v->viewport_width[k] / v->no_of_dpp[i][j][k] / 2.0 - 1.0, v->meta_req_width_c) + v->meta_req_width_c; + v->meta_surface_height_c =dcn_bw_ceil2(v->viewport_height[k] / 2.0 - 1.0, v->meta_req_height_c) + v->meta_req_height_c; if (v->pte_enable == dcn_bw_yes) { - v->meta_pte_bytes_per_frame_c = - (dcn_bw_ceil2( - (v->meta_surface_width_c - * v->meta_surface_height_c - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 256.0 - - 4096.0) - / 8.0 - / 4096.0, - 1.0) + 1) - * 64.0; - } else { + v->meta_pte_bytes_per_frame_c = (dcn_bw_ceil2((v->meta_surface_width_c * v->meta_surface_height_c *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 256.0 - 4096.0) / 8.0 / 4096.0, 1.0) + 1) * 64.0; + } + else { v->meta_pte_bytes_per_frame_c = 0.0; } if (v->source_scan[k] == dcn_bw_hor) { - v->meta_row_bytes_c = - v->meta_surface_width_c - * v->meta_req_height_c - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 256.0; - } else { - v->meta_row_bytes_c = - v->meta_surface_height_c - * v->meta_req_width_c - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 256.0; + v->meta_row_bytes_c = v->meta_surface_width_c * v->meta_req_height_c *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 256.0; } - } else { + else { + v->meta_row_bytes_c = v->meta_surface_height_c * v->meta_req_width_c *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 256.0; + } + } + else { v->meta_pte_bytes_per_frame_c = 0.0; v->meta_row_bytes_c = 0.0; } @@ -1299,593 +681,221 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->macro_tile_block_size_bytes_c = 256.0; v->macro_tile_block_height_c = 1.0; - } else if (v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { v->macro_tile_block_size_bytes_c = 4096.0; - v->macro_tile_block_height_c = - 4.0 - * v->read256_block_height_c[k]; - } else if (v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_x) { - v->macro_tile_block_size_bytes_c = 64.0 - * 1024; - v->macro_tile_block_height_c = - 16.0 - * v->read256_block_height_c[k]; - } else { - v->macro_tile_block_size_bytes_c = 256.0 - * 1024; - v->macro_tile_block_height_c = - 32.0 - * v->read256_block_height_c[k]; + v->macro_tile_block_height_c = 4.0 * v->read256_block_height_c[k]; + } + else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { + v->macro_tile_block_size_bytes_c = 64.0 * 1024; + v->macro_tile_block_height_c = 16.0 * v->read256_block_height_c[k]; } - v->macro_tile_block_width_c = - v->macro_tile_block_size_bytes_c - / dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / v->macro_tile_block_height_c; + else { + v->macro_tile_block_size_bytes_c = 256.0 * 1024; + v->macro_tile_block_height_c = 32.0 * v->read256_block_height_c[k]; + } + v->macro_tile_block_width_c = v->macro_tile_block_size_bytes_c /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->macro_tile_block_height_c; if (v->macro_tile_block_size_bytes_c <= 65536.0) { - v->data_pte_req_height_c = - v->macro_tile_block_height_c; - } else { - v->data_pte_req_height_c = - 16.0 - * v->read256_block_height_c[k]; + v->data_pte_req_height_c = v->macro_tile_block_height_c; + } + else { + v->data_pte_req_height_c = 16.0 * v->read256_block_height_c[k]; } - v->data_pte_req_width_c = - 4096.0 - / dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / v->data_pte_req_height_c - * 8; + v->data_pte_req_width_c = 4096.0 /dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / v->data_pte_req_height_c * 8; if (v->source_surface_mode[k] == dcn_bw_sw_linear) { - v->dpte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - / 2.0 - * dcn_bw_min2( - 128.0, - dcn_bw_pow( - 2.0, - dcn_bw_floor2( - dcn_bw_log( - v->pte_buffer_size_in_requests - * v->data_pte_req_width_c - / (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - / 2.0), - 2.0), - 1.0))) - - 1.0) - / v->data_pte_req_width_c, - 1.0) - + 1); - } else if (v->source_scan[k] == dcn_bw_hor) { - v->dpte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_width[k] - / v->no_of_dpp[i][j][k] - / 2.0 - - 1.0) - / v->data_pte_req_width_c, - 1.0) - + 1); - } else { - v->dpte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_height[k] - / 2.0 - - 1.0) - / v->data_pte_req_height_c, - 1.0) - + 1); + v->dpte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->viewport_width[k] / v->no_of_dpp[i][j][k] / 2.0 * dcn_bw_min2(128.0, dcn_bw_pow(2.0,dcn_bw_floor2(dcn_bw_log(v->pte_buffer_size_in_requests * v->data_pte_req_width_c / (v->viewport_width[k] / v->no_of_dpp[i][j][k] / 2.0), 2.0), 1.0))) - 1.0) / v->data_pte_req_width_c, 1.0) + 1); } - } else { + else if (v->source_scan[k] == dcn_bw_hor) { + v->dpte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->viewport_width[k] / v->no_of_dpp[i][j][k] / 2.0 - 1.0) / v->data_pte_req_width_c, 1.0) + 1); + } + else { + v->dpte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->viewport_height[k] / 2.0 - 1.0) / v->data_pte_req_height_c, 1.0) + 1); + } + } + else { v->dpte_bytes_per_row_c = 0.0; } - } else { + } + else { v->dpte_bytes_per_row_c = 0.0; v->meta_pte_bytes_per_frame_c = 0.0; v->meta_row_bytes_c = 0.0; } - v->dpte_bytes_per_row[k] = v->dpte_bytes_per_row_y - + v->dpte_bytes_per_row_c; - v->meta_pte_bytes_per_frame[k] = v->meta_pte_bytes_per_frame_y - + v->meta_pte_bytes_per_frame_c; + v->dpte_bytes_per_row[k] = v->dpte_bytes_per_row_y + v->dpte_bytes_per_row_c; + v->meta_pte_bytes_per_frame[k] = v->meta_pte_bytes_per_frame_y + v->meta_pte_bytes_per_frame_c; v->meta_row_bytes[k] = v->meta_row_bytes_y + v->meta_row_bytes_c; - v->v_init_y = (v->v_ratio[k] + v->vtaps[k] + 1.0 - + v->interlace_output[k] * 0.5 * v->v_ratio[k]) - / 2.0; - v->prefill_y[k] = dcn_bw_floor2(v->v_init_y, 1.0); - v->max_num_sw_y[k] = - dcn_bw_ceil2( - (v->prefill_y[k] - 1.0) - / v->swath_height_yper_state[i][j][k], - 1.0) + 1; + v->v_init_y = (v->v_ratio[k] + v->vtaps[k] + 1.0 + v->interlace_output[k] * 0.5 * v->v_ratio[k]) / 2.0; + v->prefill_y[k] =dcn_bw_floor2(v->v_init_y, 1.0); + v->max_num_sw_y[k] =dcn_bw_ceil2((v->prefill_y[k] - 1.0) / v->swath_height_yper_state[i][j][k], 1.0) + 1; if (v->prefill_y[k] > 1.0) { - v->max_partial_sw_y = dcn_bw_mod( - (v->prefill_y[k] - 2.0), - v->swath_height_yper_state[i][j][k]); - } else { - v->max_partial_sw_y = - dcn_bw_mod( - (v->prefill_y[k] - + v->swath_height_yper_state[i][j][k] - - 2.0), - v->swath_height_yper_state[i][j][k]); - } - v->max_partial_sw_y = dcn_bw_max2(1.0, v->max_partial_sw_y); - v->prefetch_lines_y[k] = v->max_num_sw_y[k] - * v->swath_height_yper_state[i][j][k] - + v->max_partial_sw_y; - if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { - v->v_init_c = (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 - + v->interlace_output[k] * 0.5 - * v->v_ratio[k] / 2.0) - / 2.0; - v->prefill_c[k] = dcn_bw_floor2(v->v_init_c, 1.0); - v->max_num_sw_c[k] = - dcn_bw_ceil2( - (v->prefill_c[k] - 1.0) - / v->swath_height_cper_state[i][j][k], - 1.0) + 1; + v->max_partial_sw_y =dcn_bw_mod((v->prefill_y[k] - 2.0), v->swath_height_yper_state[i][j][k]); + } + else { + v->max_partial_sw_y =dcn_bw_mod((v->prefill_y[k] + v->swath_height_yper_state[i][j][k] - 2.0), v->swath_height_yper_state[i][j][k]); + } + v->max_partial_sw_y =dcn_bw_max2(1.0, v->max_partial_sw_y); + v->prefetch_lines_y[k] = v->max_num_sw_y[k] * v->swath_height_yper_state[i][j][k] + v->max_partial_sw_y; + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + v->v_init_c = (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 + v->interlace_output[k] * 0.5 * v->v_ratio[k] / 2.0) / 2.0; + v->prefill_c[k] =dcn_bw_floor2(v->v_init_c, 1.0); + v->max_num_sw_c[k] =dcn_bw_ceil2((v->prefill_c[k] - 1.0) / v->swath_height_cper_state[i][j][k], 1.0) + 1; if (v->prefill_c[k] > 1.0) { - v->max_partial_sw_c = - dcn_bw_mod( - (v->prefill_c[k] - - 2.0), - v->swath_height_cper_state[i][j][k]); - } else { - v->max_partial_sw_c = - dcn_bw_mod( - (v->prefill_c[k] - + v->swath_height_cper_state[i][j][k] - - 2.0), - v->swath_height_cper_state[i][j][k]); + v->max_partial_sw_c =dcn_bw_mod((v->prefill_c[k] - 2.0), v->swath_height_cper_state[i][j][k]); + } + else { + v->max_partial_sw_c =dcn_bw_mod((v->prefill_c[k] + v->swath_height_cper_state[i][j][k] - 2.0), v->swath_height_cper_state[i][j][k]); } - v->max_partial_sw_c = dcn_bw_max2(1.0, v->max_partial_sw_c); - v->prefetch_lines_c[k] = v->max_num_sw_c[k] - * v->swath_height_cper_state[i][j][k] - + v->max_partial_sw_c; - } else { + v->max_partial_sw_c =dcn_bw_max2(1.0, v->max_partial_sw_c); + v->prefetch_lines_c[k] = v->max_num_sw_c[k] * v->swath_height_cper_state[i][j][k] + v->max_partial_sw_c; + } + else { v->prefetch_lines_c[k] = 0.0; } - v->dst_x_after_scaler = 90.0 * v->pixel_clock[k] - / (v->required_dispclk[i][j] / (j + 1)) - + 42.0 * v->pixel_clock[k] - / v->required_dispclk[i][j]; + v->dst_x_after_scaler = 90.0 * v->pixel_clock[k] / (v->required_dispclk[i][j] / (j + 1)) + 42.0 * v->pixel_clock[k] / v->required_dispclk[i][j]; if (v->no_of_dpp[i][j][k] > 1.0) { - v->dst_x_after_scaler = v->dst_x_after_scaler - + v->scaler_rec_out_width[k] / 2.0; + v->dst_x_after_scaler = v->dst_x_after_scaler + v->scaler_rec_out_width[k] / 2.0; } if (v->output_format[k] == dcn_bw_420) { v->dst_y_after_scaler = 1.0; - } else { + } + else { v->dst_y_after_scaler = 0.0; } v->time_calc = 24.0 / v->projected_dcfclk_deep_sleep; - v->v_update_offset[k] = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); - v->total_repeater_delay = v->max_inter_dcn_tile_repeaters - * (2.0 / (v->required_dispclk[i][j] / (j + 1)) - + 3.0 / v->required_dispclk[i][j]); - v->v_update_width[k] = (14.0 / v->projected_dcfclk_deep_sleep - + 12.0 / (v->required_dispclk[i][j] / (j + 1)) - + v->total_repeater_delay) * v->pixel_clock[k]; - v->v_ready_offset[k] = - dcn_bw_max2( - 150.0 - / (v->required_dispclk[i][j] - / (j - + 1)), - v->total_repeater_delay - + 20.0 - / v->projected_dcfclk_deep_sleep - + 10.0 - / (v->required_dispclk[i][j] - / (j - + 1))) - * v->pixel_clock[k]; - v->time_setup = (v->v_update_offset[k] + v->v_update_width[k] - + v->v_ready_offset[k]) / v->pixel_clock[k]; - v->extra_latency = - v->urgent_round_trip_and_out_of_order_latency_per_state[i] - + (v->total_number_of_active_dpp[i][j] - * v->pixel_chunk_size_in_kbyte - + v->total_number_of_dcc_active_dpp[i][j] - * v->meta_chunk_size) - * 1024.0 - / v->return_bw_per_state[i]; + v->v_update_offset[k] =dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->total_repeater_delay = v->max_inter_dcn_tile_repeaters * (2.0 / (v->required_dispclk[i][j] / (j + 1)) + 3.0 / v->required_dispclk[i][j]); + v->v_update_width[k] = (14.0 / v->projected_dcfclk_deep_sleep + 12.0 / (v->required_dispclk[i][j] / (j + 1)) + v->total_repeater_delay) * v->pixel_clock[k]; + v->v_ready_offset[k] =dcn_bw_max2(150.0 / (v->required_dispclk[i][j] / (j + 1)), v->total_repeater_delay + 20.0 / v->projected_dcfclk_deep_sleep + 10.0 / (v->required_dispclk[i][j] / (j + 1))) * v->pixel_clock[k]; + v->time_setup = (v->v_update_offset[k] + v->v_update_width[k] + v->v_ready_offset[k]) / v->pixel_clock[k]; + v->extra_latency = v->urgent_round_trip_and_out_of_order_latency_per_state[i] + (v->total_number_of_active_dpp[i][j] * v->pixel_chunk_size_in_kbyte + v->total_number_of_dcc_active_dpp[i][j] * v->meta_chunk_size) * 1024.0 / v->return_bw_per_state[i]; if (v->pte_enable == dcn_bw_yes) { - v->extra_latency = v->extra_latency - + v->total_number_of_active_dpp[i][j] - * v->pte_chunk_size * 1024.0 - / v->return_bw_per_state[i]; + v->extra_latency = v->extra_latency + v->total_number_of_active_dpp[i][j] * v->pte_chunk_size * 1024.0 / v->return_bw_per_state[i]; } - if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one - == dcn_bw_yes) { + if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes) { v->maximum_vstartup = v->vtotal[k] - v->vactive[k] - 1.0; - } else { + } + else { v->maximum_vstartup = v->v_sync_plus_back_porch[k] - 1.0; } - v->line_times_for_prefetch[k] = v->maximum_vstartup - - v->urgent_latency - / (v->htotal[k] / v->pixel_clock[k]) - - (v->time_calc + v->time_setup) - / (v->htotal[k] / v->pixel_clock[k]) - - (v->dst_y_after_scaler - + v->dst_x_after_scaler - / v->htotal[k]); - v->line_times_for_prefetch[k] = dcn_bw_floor2( - 4.0 * (v->line_times_for_prefetch[k] + 0.125), - 1.0) / 4; - v->prefetch_bw[k] = - (v->meta_pte_bytes_per_frame[k] - + 2.0 * v->meta_row_bytes[k] - + 2.0 * v->dpte_bytes_per_row[k] - + v->prefetch_lines_y[k] - * v->swath_width_yper_state[i][j][k] - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - + v->prefetch_lines_c[k] - * v->swath_width_yper_state[i][j][k] - / 2.0 - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0)) - / (v->line_times_for_prefetch[k] - * v->htotal[k] - / v->pixel_clock[k]); + v->line_times_for_prefetch[k] = v->maximum_vstartup - v->urgent_latency / (v->htotal[k] / v->pixel_clock[k]) - (v->time_calc + v->time_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dst_y_after_scaler + v->dst_x_after_scaler / v->htotal[k]); + v->line_times_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->line_times_for_prefetch[k] + 0.125), 1.0) / 4; + v->prefetch_bw[k] = (v->meta_pte_bytes_per_frame[k] + 2.0 * v->meta_row_bytes[k] + 2.0 * v->dpte_bytes_per_row[k] + v->prefetch_lines_y[k] * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0)) / (v->line_times_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]); } v->bw_available_for_immediate_flip = v->return_bw_per_state[i]; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->bw_available_for_immediate_flip = - v->bw_available_for_immediate_flip - - dcn_bw_max2( - v->read_bandwidth[k], - v->prefetch_bw[k]); + v->bw_available_for_immediate_flip = v->bw_available_for_immediate_flip -dcn_bw_max2(v->read_bandwidth[k], v->prefetch_bw[k]); } - v->total_immediate_flip_bytes[k] = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { - v->total_immediate_flip_bytes[k] = - v->total_immediate_flip_bytes[k] - + v->meta_pte_bytes_per_frame[k] - + v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]; + v->total_immediate_flip_bytes[k] = 0.0; + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->total_immediate_flip_bytes[k] = v->total_immediate_flip_bytes[k] + v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]; } } for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { - v->time_for_meta_pte_with_immediate_flip = - dcn_bw_max5( - v->meta_pte_bytes_per_frame[k] - / v->prefetch_bw[k], - v->meta_pte_bytes_per_frame[k] - * v->total_immediate_flip_bytes[k] - / (v->bw_available_for_immediate_flip - * (v->meta_pte_bytes_per_frame[k] - + v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k])), - v->extra_latency, - v->urgent_latency, - v->htotal[k] - / v->pixel_clock[k] - / 4.0); - v->time_for_meta_pte_without_immediate_flip = dcn_bw_max3( - v->meta_pte_bytes_per_frame[k] - / v->prefetch_bw[k], - v->extra_latency, - v->htotal[k] / v->pixel_clock[k] / 4.0); - } else { - v->time_for_meta_pte_with_immediate_flip = v->htotal[k] - / v->pixel_clock[k] / 4.0; - v->time_for_meta_pte_without_immediate_flip = v->htotal[k] - / v->pixel_clock[k] / 4.0; + v->time_for_meta_pte_with_immediate_flip =dcn_bw_max5(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->meta_pte_bytes_per_frame[k] * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->extra_latency, v->urgent_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); + v->time_for_meta_pte_without_immediate_flip =dcn_bw_max3(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->extra_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); + } + else { + v->time_for_meta_pte_with_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0; + v->time_for_meta_pte_without_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0; } if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) { - v->time_for_meta_and_dpte_row_with_immediate_flip = - dcn_bw_max5( - (v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]) - / v->prefetch_bw[k], - (v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]) - * v->total_immediate_flip_bytes[k] - / (v->bw_available_for_immediate_flip - * (v->meta_pte_bytes_per_frame[k] - + v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k])), - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_meta_pte_with_immediate_flip, - v->extra_latency, - 2.0 * v->urgent_latency); - v->time_for_meta_and_dpte_row_without_immediate_flip = - dcn_bw_max3( - (v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]) - / v->prefetch_bw[k], - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_meta_pte_without_immediate_flip, - v->extra_latency); - } else { - v->time_for_meta_and_dpte_row_with_immediate_flip = - dcn_bw_max2( - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_meta_pte_with_immediate_flip, - v->extra_latency - - v->time_for_meta_pte_with_immediate_flip); - v->time_for_meta_and_dpte_row_without_immediate_flip = - dcn_bw_max2( - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_meta_pte_without_immediate_flip, - v->extra_latency - - v->time_for_meta_pte_without_immediate_flip); - } - v->lines_for_meta_pte_with_immediate_flip[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_meta_pte_with_immediate_flip - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->lines_for_meta_pte_without_immediate_flip[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_meta_pte_without_immediate_flip - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->lines_for_meta_and_dpte_row_with_immediate_flip[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_meta_and_dpte_row_with_immediate_flip - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->lines_for_meta_and_dpte_row_without_immediate_flip[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_meta_and_dpte_row_without_immediate_flip - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = - v->line_times_for_prefetch[k] - - v->lines_for_meta_pte_with_immediate_flip[k] - - v->lines_for_meta_and_dpte_row_with_immediate_flip[k]; - v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = - v->line_times_for_prefetch[k] - - v->lines_for_meta_pte_without_immediate_flip[k] - - v->lines_for_meta_and_dpte_row_without_immediate_flip[k]; - if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - > 0.0) { - v->v_ratio_pre_ywith_immediate_flip[i][j][k] = - v->prefetch_lines_y[k] - / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; + v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max5((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], (v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency, 2.0 * v->urgent_latency); + v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max3((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency); + } + else { + v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency - v->time_for_meta_pte_with_immediate_flip); + v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency - v->time_for_meta_pte_without_immediate_flip); + } + v->lines_for_meta_pte_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_for_meta_pte_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_for_meta_and_dpte_row_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_for_meta_and_dpte_row_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_with_immediate_flip[k] - v->lines_for_meta_and_dpte_row_with_immediate_flip[k]; + v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_without_immediate_flip[k] - v->lines_for_meta_and_dpte_row_without_immediate_flip[k]; + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip > 0.0) { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = v->prefetch_lines_y[k] / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; if ((v->swath_height_yper_state[i][j][k] > 4.0)) { - if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - - (v->prefill_y[k] - 3.0) / 2.0 - > 0.0) { - v->v_ratio_pre_ywith_immediate_flip[i][j][k] = - dcn_bw_max2( - v->v_ratio_pre_ywith_immediate_flip[i][j][k], - (v->max_num_sw_y[k] - * v->swath_height_yper_state[i][j][k]) - / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - - (v->prefill_y[k] - - 3.0) - / 2.0)); - } else { - v->v_ratio_pre_ywith_immediate_flip[i][j][k] = - 999999.0; + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - (v->prefill_y[k] - 3.0) / 2.0 > 0.0) { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] =dcn_bw_max2(v->v_ratio_pre_ywith_immediate_flip[i][j][k], (v->max_num_sw_y[k] * v->swath_height_yper_state[i][j][k]) / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - (v->prefill_y[k] - 3.0) / 2.0)); + } + else { + v->v_ratio_pre_ywith_immediate_flip[i][j][k] = 999999.0; } } - v->v_ratio_pre_cwith_immediate_flip[i][j][k] = - v->prefetch_lines_c[k] - / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = v->prefetch_lines_c[k] / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip; if ((v->swath_height_cper_state[i][j][k] > 4.0)) { - if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - - (v->prefill_c[k] - 3.0) / 2.0 - > 0.0) { - v->v_ratio_pre_cwith_immediate_flip[i][j][k] = - dcn_bw_max2( - v->v_ratio_pre_cwith_immediate_flip[i][j][k], - (v->max_num_sw_c[k] - * v->swath_height_cper_state[i][j][k]) - / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - - (v->prefill_c[k] - - 3.0) - / 2.0)); - } else { - v->v_ratio_pre_cwith_immediate_flip[i][j][k] = - 999999.0; + if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - (v->prefill_c[k] - 3.0) / 2.0 > 0.0) { + v->v_ratio_pre_cwith_immediate_flip[i][j][k] =dcn_bw_max2(v->v_ratio_pre_cwith_immediate_flip[i][j][k], (v->max_num_sw_c[k] * v->swath_height_cper_state[i][j][k]) / (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - (v->prefill_c[k] - 3.0) / 2.0)); + } + else { + v->v_ratio_pre_cwith_immediate_flip[i][j][k] = 999999.0; } } - v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = - v->no_of_dpp[i][j][k] - * (v->prefetch_lines_y[k] - / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - + v->prefetch_lines_c[k] - / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 2.0) - * v->swath_width_yper_state[i][j][k] - / (v->htotal[k] - / v->pixel_clock[k]); - } else { + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = v->no_of_dpp[i][j][k] * (v->prefetch_lines_y[k] / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] / v->line_times_to_request_prefetch_pixel_data_with_immediate_flip *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0) * v->swath_width_yper_state[i][j][k] / (v->htotal[k] / v->pixel_clock[k]); + } + else { v->v_ratio_pre_ywith_immediate_flip[i][j][k] = 999999.0; v->v_ratio_pre_cwith_immediate_flip[i][j][k] = 999999.0; - v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = - 999999.0; - } - if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - > 0.0) { - v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = - v->prefetch_lines_y[k] - / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; + v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k] = 999999.0; + } + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip > 0.0) { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = v->prefetch_lines_y[k] / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; if ((v->swath_height_yper_state[i][j][k] > 4.0)) { - if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - - (v->prefill_y[k] - 3.0) / 2.0 - > 0.0) { - v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = - dcn_bw_max2( - v->v_ratio_pre_ywithout_immediate_flip[i][j][k], - (v->max_num_sw_y[k] - * v->swath_height_yper_state[i][j][k]) - / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - - (v->prefill_y[k] - - 3.0) - / 2.0)); - } else { - v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = - 999999.0; + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - (v->prefill_y[k] - 3.0) / 2.0 > 0.0) { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] =dcn_bw_max2(v->v_ratio_pre_ywithout_immediate_flip[i][j][k], (v->max_num_sw_y[k] * v->swath_height_yper_state[i][j][k]) / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - (v->prefill_y[k] - 3.0) / 2.0)); + } + else { + v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = 999999.0; } } - v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = - v->prefetch_lines_c[k] - / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = v->prefetch_lines_c[k] / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip; if ((v->swath_height_cper_state[i][j][k] > 4.0)) { - if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - - (v->prefill_c[k] - 3.0) / 2.0 - > 0.0) { - v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = - dcn_bw_max2( - v->v_ratio_pre_cwithout_immediate_flip[i][j][k], - (v->max_num_sw_c[k] - * v->swath_height_cper_state[i][j][k]) - / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - - (v->prefill_c[k] - - 3.0) - / 2.0)); - } else { - v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = - 999999.0; + if (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - (v->prefill_c[k] - 3.0) / 2.0 > 0.0) { + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] =dcn_bw_max2(v->v_ratio_pre_cwithout_immediate_flip[i][j][k], (v->max_num_sw_c[k] * v->swath_height_cper_state[i][j][k]) / (v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - (v->prefill_c[k] - 3.0) / 2.0)); + } + else { + v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = 999999.0; } } - v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = - v->no_of_dpp[i][j][k] - * (v->prefetch_lines_y[k] - / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - * dcn_bw_ceil2( - v->byte_per_pixel_in_dety[k], - 1.0) - + v->prefetch_lines_c[k] - / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip - * dcn_bw_ceil2( - v->byte_per_pixel_in_detc[k], - 2.0) - / 2.0) - * v->swath_width_yper_state[i][j][k] - / (v->htotal[k] - / v->pixel_clock[k]); - } else { + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = v->no_of_dpp[i][j][k] * (v->prefetch_lines_y[k] / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] / v->line_times_to_request_prefetch_pixel_data_without_immediate_flip *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0) / 2.0) * v->swath_width_yper_state[i][j][k] / (v->htotal[k] / v->pixel_clock[k]); + } + else { v->v_ratio_pre_ywithout_immediate_flip[i][j][k] = 999999.0; v->v_ratio_pre_cwithout_immediate_flip[i][j][k] = 999999.0; - v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = - 999999.0; + v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k] = 999999.0; } } v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { - v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = - v->maximum_read_bandwidth_with_prefetch_with_immediate_flip - + dcn_bw_max2( - v->read_bandwidth[k], - v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k]) - + dcn_bw_max2( - v->meta_pte_bytes_per_frame[k] - / (v->lines_for_meta_pte_with_immediate_flip[k] - * v->htotal[k] - / v->pixel_clock[k]), - (v->meta_row_bytes[k] - + v->dpte_bytes_per_row[k]) - / (v->lines_for_meta_and_dpte_row_with_immediate_flip[k] - * v->htotal[k] - / v->pixel_clock[k])); - } else { - v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = - v->maximum_read_bandwidth_with_prefetch_with_immediate_flip - + dcn_bw_max2( - v->read_bandwidth[k], - v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = v->maximum_read_bandwidth_with_prefetch_with_immediate_flip +dcn_bw_max2(v->read_bandwidth[k], v->required_prefetch_pixel_data_bw_with_immediate_flip[i][j][k]) +dcn_bw_max2(v->meta_pte_bytes_per_frame[k] / (v->lines_for_meta_pte_with_immediate_flip[k] * v->htotal[k] / v->pixel_clock[k]), (v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / (v->lines_for_meta_and_dpte_row_with_immediate_flip[k] * v->htotal[k] / v->pixel_clock[k])); + } + else { + v->maximum_read_bandwidth_with_prefetch_with_immediate_flip = v->maximum_read_bandwidth_with_prefetch_with_immediate_flip +dcn_bw_max2(v->read_bandwidth[k], v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); } } v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = - v->maximum_read_bandwidth_with_prefetch_without_immediate_flip - + dcn_bw_max2( - v->read_bandwidth[k], - v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); + v->maximum_read_bandwidth_with_prefetch_without_immediate_flip = v->maximum_read_bandwidth_with_prefetch_without_immediate_flip +dcn_bw_max2(v->read_bandwidth[k], v->required_prefetch_pixel_data_bw_without_immediate_flip[i][j][k]); } v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_yes; - if (v->maximum_read_bandwidth_with_prefetch_with_immediate_flip - > v->return_bw_per_state[i]) { + if (v->maximum_read_bandwidth_with_prefetch_with_immediate_flip > v->return_bw_per_state[i]) { v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; } for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->line_times_for_prefetch[k] < 2.0 - || v->lines_for_meta_pte_with_immediate_flip[k] - >= 8.0 - || v->lines_for_meta_and_dpte_row_with_immediate_flip[k] - >= 16.0) { + if (v->line_times_for_prefetch[k] < 2.0 || v->lines_for_meta_pte_with_immediate_flip[k] >= 8.0 || v->lines_for_meta_and_dpte_row_with_immediate_flip[k] >= 16.0) { v->prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; } } v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_yes; - if (v->maximum_read_bandwidth_with_prefetch_without_immediate_flip - > v->return_bw_per_state[i]) { + if (v->maximum_read_bandwidth_with_prefetch_without_immediate_flip > v->return_bw_per_state[i]) { v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_no; } for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->line_times_for_prefetch[k] < 2.0 - || v->lines_for_meta_pte_without_immediate_flip[k] - >= 8.0 - || v->lines_for_meta_and_dpte_row_without_immediate_flip[k] - >= 16.0) { - v->prefetch_supported_without_immediate_flip[i][j] = - dcn_bw_no; + if (v->line_times_for_prefetch[k] < 2.0 || v->lines_for_meta_pte_without_immediate_flip[k] >= 8.0 || v->lines_for_meta_and_dpte_row_without_immediate_flip[k] >= 16.0) { + v->prefetch_supported_without_immediate_flip[i][j] = dcn_bw_no; } } } @@ -1894,31 +904,14 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (j = 0; j <= 1; j++) { v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10) - && (v->v_ratio_pre_ywith_immediate_flip[i][j][k] - > 4.0 - || v->v_ratio_pre_cwith_immediate_flip[i][j][k] - > 4.0)) - || ((v->source_pixel_format[k] - == dcn_bw_yuv420_sub_8 - || v->source_pixel_format[k] - == dcn_bw_yuv420_sub_10) - && (v->v_ratio_pre_ywithout_immediate_flip[i][j][k] - > 4.0 - || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] - > 4.0)))) { - v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = - dcn_bw_no; + if ((((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10) && (v->v_ratio_pre_ywith_immediate_flip[i][j][k] > 4.0 || v->v_ratio_pre_cwith_immediate_flip[i][j][k] > 4.0)) || ((v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 || v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) && (v->v_ratio_pre_ywithout_immediate_flip[i][j][k] > 4.0 || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] > 4.0)))) { + v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] = dcn_bw_no; } } v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->v_ratio_pre_ywithout_immediate_flip[i][j][k] > 4.0 - || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] - > 4.0)) { - v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = - dcn_bw_no; + if ((v->v_ratio_pre_ywithout_immediate_flip[i][j][k] > 4.0 || v->v_ratio_pre_cwithout_immediate_flip[i][j][k] > 4.0)) { + v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] = dcn_bw_no; } } } @@ -1927,57 +920,41 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (i = number_of_states_plus_one; i >= 0; i--) { for (j = 0; j <= 1; j++) { - if (v->scale_ratio_support == dcn_bw_yes - && v->source_format_pixel_and_scan_support == dcn_bw_yes - && v->viewport_size_support == dcn_bw_yes - && v->bandwidth_support[i] == dcn_bw_yes - && v->dio_support[i] == dcn_bw_yes - && v->urgent_latency_support[i][j] == dcn_bw_yes - && v->rob_support[i] == dcn_bw_yes - && v->dispclk_dppclk_support[i][j] == dcn_bw_yes - && v->total_available_pipes_support[i][j] == dcn_bw_yes - && v->total_available_writeback_support == dcn_bw_yes - && v->writeback_latency_support == dcn_bw_yes) { - if (v->prefetch_supported_with_immediate_flip[i][j] == dcn_bw_yes - && v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] - == dcn_bw_yes) { + if (v->scale_ratio_support == dcn_bw_yes && v->source_format_pixel_and_scan_support == dcn_bw_yes && v->viewport_size_support == dcn_bw_yes && v->bandwidth_support[i] == dcn_bw_yes && v->dio_support[i] == dcn_bw_yes && v->urgent_latency_support[i][j] == dcn_bw_yes && v->rob_support[i] == dcn_bw_yes && v->dispclk_dppclk_support[i][j] == dcn_bw_yes && v->total_available_pipes_support[i][j] == dcn_bw_yes && v->total_available_writeback_support == dcn_bw_yes && v->writeback_latency_support == dcn_bw_yes) { + if (v->prefetch_supported_with_immediate_flip[i][j] == dcn_bw_yes && v->v_ratio_in_prefetch_supported_with_immediate_flip[i][j] == dcn_bw_yes) { v->mode_support_with_immediate_flip[i][j] = dcn_bw_yes; - } else { + } + else { v->mode_support_with_immediate_flip[i][j] = dcn_bw_no; } - if (v->prefetch_supported_without_immediate_flip[i][j] == dcn_bw_yes - && v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] - == dcn_bw_yes) { + if (v->prefetch_supported_without_immediate_flip[i][j] == dcn_bw_yes && v->v_ratio_in_prefetch_supported_without_immediate_flip[i][j] == dcn_bw_yes) { v->mode_support_without_immediate_flip[i][j] = dcn_bw_yes; - } else { + } + else { v->mode_support_without_immediate_flip[i][j] = dcn_bw_no; } - } else { + } + else { v->mode_support_with_immediate_flip[i][j] = dcn_bw_no; v->mode_support_without_immediate_flip[i][j] = dcn_bw_no; } } } for (i = number_of_states_plus_one; i >= 0; i--) { - if ((i == number_of_states_plus_one - || v->mode_support_with_immediate_flip[i][1] == dcn_bw_yes - || v->mode_support_with_immediate_flip[i][0] == dcn_bw_yes) - && i >= v->voltage_override_level) { + if ((i == number_of_states_plus_one || v->mode_support_with_immediate_flip[i][1] == dcn_bw_yes || v->mode_support_with_immediate_flip[i][0] == dcn_bw_yes) && i >= v->voltage_override_level) { v->voltage_level_with_immediate_flip = i; } } for (i = number_of_states_plus_one; i >= 0; i--) { - if ((i == number_of_states_plus_one - || v->mode_support_without_immediate_flip[i][1] == dcn_bw_yes - || v->mode_support_without_immediate_flip[i][0] == dcn_bw_yes) - && i >= v->voltage_override_level) { + if ((i == number_of_states_plus_one || v->mode_support_without_immediate_flip[i][1] == dcn_bw_yes || v->mode_support_without_immediate_flip[i][0] == dcn_bw_yes) && i >= v->voltage_override_level) { v->voltage_level_without_immediate_flip = i; } } if (v->voltage_level_with_immediate_flip == number_of_states_plus_one) { v->immediate_flip_supported = dcn_bw_no; v->voltage_level = v->voltage_level_without_immediate_flip; - } else { + } + else { v->immediate_flip_supported = dcn_bw_yes; v->voltage_level = v->voltage_level_with_immediate_flip; } @@ -1988,38 +965,27 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) for (k = 0; k <= v->number_of_active_planes - 1; k++) { v->dpp_per_plane_per_ratio[j][k] = v->no_of_dpp[v->voltage_level][j][k]; } - v->dispclk_dppclk_support_per_ratio[j] = - v->dispclk_dppclk_support[v->voltage_level][j]; + v->dispclk_dppclk_support_per_ratio[j] = v->dispclk_dppclk_support[v->voltage_level][j]; } v->max_phyclk = v->phyclk_per_state[v->voltage_level]; } void display_pipe_configuration(struct dcn_bw_internal_vars *v) { - int j, k; + int j; + int k; /*display pipe configuration*/ for (j = 0; j <= 1; j++) { v->total_number_of_active_dpp_per_ratio[j] = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->total_number_of_active_dpp_per_ratio[j] = - v->total_number_of_active_dpp_per_ratio[j] - + v->dpp_per_plane_per_ratio[j][k]; - } - } - if ((v->dispclk_dppclk_support_per_ratio[0] == dcn_bw_yes - && v->dispclk_dppclk_support_per_ratio[1] == dcn_bw_no) - || (v->dispclk_dppclk_support_per_ratio[0] - == v->dispclk_dppclk_support_per_ratio[1] - && (v->total_number_of_active_dpp_per_ratio[0] - < v->total_number_of_active_dpp_per_ratio[1] - || (((v->total_number_of_active_dpp_per_ratio[0] - == v->total_number_of_active_dpp_per_ratio[1]) - && v->required_dispclk_per_ratio[0] - <= 0.5 - * v->required_dispclk_per_ratio[1]))))) { + v->total_number_of_active_dpp_per_ratio[j] = v->total_number_of_active_dpp_per_ratio[j] + v->dpp_per_plane_per_ratio[j][k]; + } + } + if ((v->dispclk_dppclk_support_per_ratio[0] == dcn_bw_yes && v->dispclk_dppclk_support_per_ratio[1] == dcn_bw_no) || (v->dispclk_dppclk_support_per_ratio[0] == v->dispclk_dppclk_support_per_ratio[1] && (v->total_number_of_active_dpp_per_ratio[0] < v->total_number_of_active_dpp_per_ratio[1] || (((v->total_number_of_active_dpp_per_ratio[0] == v->total_number_of_active_dpp_per_ratio[1]) && v->required_dispclk_per_ratio[0] <= 0.5 * v->required_dispclk_per_ratio[1]))))) { v->dispclk_dppclk_ratio = 1; v->final_error_message = v->error_message[0]; - } else { + } + else { v->dispclk_dppclk_ratio = 2; v->final_error_message = v->error_message[1]; } @@ -2030,159 +996,139 @@ void display_pipe_configuration(struct dcn_bw_internal_vars *v) if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->byte_per_pix_dety = 8.0; v->byte_per_pix_detc = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { v->byte_per_pix_dety = 4.0; v->byte_per_pix_detc = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { v->byte_per_pix_dety = 2.0; v->byte_per_pix_detc = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->byte_per_pix_dety = 1.0; v->byte_per_pix_detc = 2.0; - } else { - v->byte_per_pix_dety = 4.0f / 3; - v->byte_per_pix_detc = 8.0f / 3; } - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + else { + v->byte_per_pix_dety = 4.0f / 3.0f; + v->byte_per_pix_detc = 8.0f / 3.0f; + } + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->read256_bytes_block_height_y = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->read256_bytes_block_height_y = 4.0; - } else { + } + else { v->read256_bytes_block_height_y = 8.0; } - v->read256_bytes_block_width_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) - / v->read256_bytes_block_height_y; + v->read256_bytes_block_width_y = 256.0 /dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) / v->read256_bytes_block_height_y; v->read256_bytes_block_height_c = 0.0; v->read256_bytes_block_width_c = 0.0; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->read256_bytes_block_height_y = 1.0; v->read256_bytes_block_height_c = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->read256_bytes_block_height_y = 16.0; v->read256_bytes_block_height_c = 8.0; - } else { + } + else { v->read256_bytes_block_height_y = 8.0; v->read256_bytes_block_height_c = 8.0; } - v->read256_bytes_block_width_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) - / v->read256_bytes_block_height_y; - v->read256_bytes_block_width_c = 256.0 / dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) - / v->read256_bytes_block_height_c; + v->read256_bytes_block_width_y = 256.0 /dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) / v->read256_bytes_block_height_y; + v->read256_bytes_block_width_c = 256.0 /dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) / v->read256_bytes_block_height_c; } if (v->source_scan[k] == dcn_bw_hor) { v->maximum_swath_height_y = v->read256_bytes_block_height_y; v->maximum_swath_height_c = v->read256_bytes_block_height_c; - } else { + } + else { v->maximum_swath_height_y = v->read256_bytes_block_width_y; v->maximum_swath_height_c = v->read256_bytes_block_width_c; } - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { - if (v->source_surface_mode[k] == dcn_bw_sw_linear - || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - && (v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] - == dcn_bw_sw_var_s - || v->source_surface_mode[k] - == dcn_bw_sw_var_s_x) - && v->source_scan[k] == dcn_bw_hor)) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if (v->source_surface_mode[k] == dcn_bw_sw_linear || (v->source_pixel_format[k] == dcn_bw_rgb_sub_64 && (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_var_s || v->source_surface_mode[k] == dcn_bw_sw_var_s_x) && v->source_scan[k] == dcn_bw_hor)) { v->minimum_swath_height_y = v->maximum_swath_height_y; - } else { + } + else { v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; } v->minimum_swath_height_c = v->maximum_swath_height_c; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->minimum_swath_height_y = v->maximum_swath_height_y; v->minimum_swath_height_c = v->maximum_swath_height_c; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 - && v->source_scan[k] == dcn_bw_hor) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8 && v->source_scan[k] == dcn_bw_hor) { v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; - if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed - == dcn_bw_yes) { + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes) { v->minimum_swath_height_c = v->maximum_swath_height_c; - } else { + } + else { v->minimum_swath_height_c = v->maximum_swath_height_c / 2.0; } - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 - && v->source_scan[k] == dcn_bw_hor) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10 && v->source_scan[k] == dcn_bw_hor) { v->minimum_swath_height_c = v->maximum_swath_height_c / 2.0; - if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed - == dcn_bw_yes) { + if (v->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes) { v->minimum_swath_height_y = v->maximum_swath_height_y; - } else { + } + else { v->minimum_swath_height_y = v->maximum_swath_height_y / 2.0; } - } else { + } + else { v->minimum_swath_height_y = v->maximum_swath_height_y; v->minimum_swath_height_c = v->maximum_swath_height_c; } } if (v->source_scan[k] == dcn_bw_hor) { v->swath_width = v->viewport_width[k] / v->dpp_per_plane[k]; - } else { + } + else { v->swath_width = v->viewport_height[k] / v->dpp_per_plane[k]; } - v->swath_width_granularity_y = 256.0 / dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) - / v->maximum_swath_height_y; - v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2( - v->swath_width - 1.0, - v->swath_width_granularity_y) + v->swath_width_granularity_y) - * v->byte_per_pix_dety * v->maximum_swath_height_y; + v->swath_width_granularity_y = 256.0 /dcn_bw_ceil2(v->byte_per_pix_dety, 1.0) / v->maximum_swath_height_y; + v->rounded_up_max_swath_size_bytes_y = (dcn_bw_ceil2(v->swath_width - 1.0, v->swath_width_granularity_y) + v->swath_width_granularity_y) * v->byte_per_pix_dety * v->maximum_swath_height_y; if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_y = dcn_bw_ceil2( - v->rounded_up_max_swath_size_bytes_y, - 256.0) + 256; + v->rounded_up_max_swath_size_bytes_y =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_y, 256.0) + 256; } if (v->maximum_swath_height_c > 0.0) { - v->swath_width_granularity_c = 256.0 / dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) - / v->maximum_swath_height_c; + v->swath_width_granularity_c = 256.0 /dcn_bw_ceil2(v->byte_per_pix_detc, 2.0) / v->maximum_swath_height_c; } - v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2( - v->swath_width / 2.0 - 1.0, - v->swath_width_granularity_c) + v->swath_width_granularity_c) - * v->byte_per_pix_detc * v->maximum_swath_height_c; + v->rounded_up_max_swath_size_bytes_c = (dcn_bw_ceil2(v->swath_width / 2.0 - 1.0, v->swath_width_granularity_c) + v->swath_width_granularity_c) * v->byte_per_pix_detc * v->maximum_swath_height_c; if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_10) { - v->rounded_up_max_swath_size_bytes_c = dcn_bw_ceil2( - v->rounded_up_max_swath_size_bytes_c, - 256.0) + 256; + v->rounded_up_max_swath_size_bytes_c =dcn_bw_ceil2(v->rounded_up_max_swath_size_bytes_c, 256.0) + 256; } - if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c - <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { + if (v->rounded_up_max_swath_size_bytes_y + v->rounded_up_max_swath_size_bytes_c <= v->det_buffer_size_in_kbyte * 1024.0 / 2.0) { v->swath_height_y[k] = v->maximum_swath_height_y; v->swath_height_c[k] = v->maximum_swath_height_c; - } else { + } + else { v->swath_height_y[k] = v->minimum_swath_height_y; v->swath_height_c[k] = v->minimum_swath_height_c; } if (v->swath_height_c[k] == 0.0) { v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0; v->det_buffer_size_c[k] = 0.0; - } else if (v->swath_height_y[k] <= v->swath_height_c[k]) { + } + else if (v->swath_height_y[k] <= v->swath_height_c[k]) { v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0 / 2.0; v->det_buffer_size_c[k] = v->det_buffer_size_in_kbyte * 1024.0 / 2.0; - } else { + } + else { v->det_buffer_size_y[k] = v->det_buffer_size_in_kbyte * 1024.0 * 2.0 / 3.0; v->det_buffer_size_c[k] = v->det_buffer_size_in_kbyte * 1024.0 / 3.0; } } } -void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation( - struct dcn_bw_internal_vars *v) +void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(struct dcn_bw_internal_vars *v) { int k; /*dispclk and dppclk calculation*/ @@ -2191,123 +1137,48 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->dispclk_without_ramping = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->h_ratio[k] > 1.0) { - v->pscl_throughput[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput * v->h_ratio[k] - / dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); - } else { - v->pscl_throughput[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput); - } - v->dppclk_using_single_dpp_luma = v->pixel_clock[k] - * dcn_bw_max3( - v->vtaps[k] / 6.0 * dcn_bw_min2(1.0, v->h_ratio[k]), - v->h_ratio[k] * v->v_ratio[k] - / v->pscl_throughput[k], - 1.0); - if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->pscl_throughput[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput * v->h_ratio[k] /dcn_bw_ceil2(v->htaps[k] / 6.0, 1.0)); + } + else { + v->pscl_throughput[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput); + } + v->dppclk_using_single_dpp_luma = v->pixel_clock[k] *dcn_bw_max3(v->vtaps[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k]), v->h_ratio[k] * v->v_ratio[k] / v->pscl_throughput[k], 1.0); + if ((v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { v->pscl_throughput_chroma[k] = 0.0; v->dppclk_using_single_dpp = v->dppclk_using_single_dpp_luma; - } else { + } + else { if (v->h_ratio[k] > 1.0) { - v->pscl_throughput_chroma[k] = - dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput - * v->h_ratio[k] - / 2.0 - / dcn_bw_ceil2( - v->hta_pschroma[k] - / 6.0, - 1.0)); - } else { - v->pscl_throughput_chroma[k] = dcn_bw_min2( - v->max_dchub_topscl_throughput, - v->max_pscl_tolb_throughput); - } - v->dppclk_using_single_dpp_chroma = - v->pixel_clock[k] - * dcn_bw_max3( - v->vta_pschroma[k] / 6.0 - * dcn_bw_min2( - 1.0, - v->h_ratio[k] - / 2.0), - v->h_ratio[k] - * v->v_ratio[k] - / 4.0 - / v->pscl_throughput_chroma[k], - 1.0); - v->dppclk_using_single_dpp = dcn_bw_max2( - v->dppclk_using_single_dpp_luma, - v->dppclk_using_single_dpp_chroma); + v->pscl_throughput_chroma[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput * v->h_ratio[k] / 2.0 /dcn_bw_ceil2(v->hta_pschroma[k] / 6.0, 1.0)); + } + else { + v->pscl_throughput_chroma[k] =dcn_bw_min2(v->max_dchub_topscl_throughput, v->max_pscl_tolb_throughput); + } + v->dppclk_using_single_dpp_chroma = v->pixel_clock[k] *dcn_bw_max3(v->vta_pschroma[k] / 6.0 *dcn_bw_min2(1.0, v->h_ratio[k] / 2.0), v->h_ratio[k] * v->v_ratio[k] / 4.0 / v->pscl_throughput_chroma[k], 1.0); + v->dppclk_using_single_dpp =dcn_bw_max2(v->dppclk_using_single_dpp_luma, v->dppclk_using_single_dpp_chroma); } if (v->odm_capable == dcn_bw_yes) { - v->dispclk_with_ramping = - dcn_bw_max2( - v->dispclk_with_ramping, - dcn_bw_max2( - v->dppclk_using_single_dpp - / v->dpp_per_plane[k] - * v->dispclk_dppclk_ratio, - v->pixel_clock[k] - / v->dpp_per_plane[k]) - * (1.0 - + v->downspreading - / 100.0) - * (1.0 - + v->dispclk_ramping_margin - / 100.0)); - v->dispclk_without_ramping = dcn_bw_max2( - v->dispclk_without_ramping, - dcn_bw_max2( - v->dppclk_using_single_dpp - / v->dpp_per_plane[k] - * v->dispclk_dppclk_ratio, - v->pixel_clock[k] / v->dpp_per_plane[k]) - * (1.0 + v->downspreading / 100.0)); - } else { - v->dispclk_with_ramping = - dcn_bw_max2( - v->dispclk_with_ramping, - dcn_bw_max2( - v->dppclk_using_single_dpp - / v->dpp_per_plane[k] - * v->dispclk_dppclk_ratio, - v->pixel_clock[k]) - * (1.0 - + v->downspreading - / 100.0) - * (1.0 - + v->dispclk_ramping_margin - / 100.0)); - v->dispclk_without_ramping = dcn_bw_max2( - v->dispclk_without_ramping, - dcn_bw_max2( - v->dppclk_using_single_dpp - / v->dpp_per_plane[k] - * v->dispclk_dppclk_ratio, - v->pixel_clock[k]) - * (1.0 + v->downspreading / 100.0)); + v->dispclk_with_ramping =dcn_bw_max2(v->dispclk_with_ramping,dcn_bw_max2(v->dppclk_using_single_dpp / v->dpp_per_plane[k] * v->dispclk_dppclk_ratio, v->pixel_clock[k] / v->dpp_per_plane[k]) * (1.0 + v->downspreading / 100.0) * (1.0 + v->dispclk_ramping_margin / 100.0)); + v->dispclk_without_ramping =dcn_bw_max2(v->dispclk_without_ramping,dcn_bw_max2(v->dppclk_using_single_dpp / v->dpp_per_plane[k] * v->dispclk_dppclk_ratio, v->pixel_clock[k] / v->dpp_per_plane[k]) * (1.0 + v->downspreading / 100.0)); + } + else { + v->dispclk_with_ramping =dcn_bw_max2(v->dispclk_with_ramping,dcn_bw_max2(v->dppclk_using_single_dpp / v->dpp_per_plane[k] * v->dispclk_dppclk_ratio, v->pixel_clock[k]) * (1.0 + v->downspreading / 100.0) * (1.0 + v->dispclk_ramping_margin / 100.0)); + v->dispclk_without_ramping =dcn_bw_max2(v->dispclk_without_ramping,dcn_bw_max2(v->dppclk_using_single_dpp / v->dpp_per_plane[k] * v->dispclk_dppclk_ratio, v->pixel_clock[k]) * (1.0 + v->downspreading / 100.0)); } } if (v->dispclk_without_ramping > v->max_dispclk[number_of_states]) { v->dispclk = v->dispclk_without_ramping; - } else if (v->dispclk_with_ramping > v->max_dispclk[number_of_states]) { + } + else if (v->dispclk_with_ramping > v->max_dispclk[number_of_states]) { v->dispclk = v->max_dispclk[number_of_states]; - } else { + } + else { v->dispclk = v->dispclk_with_ramping; } v->dppclk = v->dispclk / v->dispclk_dppclk_ratio; /*urgent watermark*/ - v->return_bandwidth_to_dcn = dcn_bw_min2( - v->return_bus_width * v->dcfclk, - v->fabric_and_dram_bandwidth * 1000.0 - * v->percent_of_ideal_drambw_received_after_urg_latency - / 100.0); + v->return_bandwidth_to_dcn =dcn_bw_min2(v->return_bus_width * v->dcfclk, v->fabric_and_dram_bandwidth * 1000.0 * v->percent_of_ideal_drambw_received_after_urg_latency / 100.0); v->dcc_enabled_any_plane = dcn_bw_no; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { @@ -2315,95 +1186,26 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan } } v->return_bw = v->return_bandwidth_to_dcn; - if (v->dcc_enabled_any_plane == dcn_bw_yes - && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { - v->return_bw = - dcn_bw_min2( - v->return_bw, - v->return_bandwidth_to_dcn * 4.0 - * (1.0 - - v->urgent_latency - / ((v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - / (v->return_bandwidth_to_dcn - - v->dcfclk - * v->return_bus_width - / 4.0) - + v->urgent_latency))); - } - v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency - / (v->return_bandwidth_to_dcn * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) * 1024.0); - if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 - && v->critical_compression < 4.0) { - v->return_bw = - dcn_bw_min2( - v->return_bw, - dcn_bw_pow( - 4.0 * v->return_bandwidth_to_dcn - * (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - * v->return_bus_width - * v->dcfclk - * v->urgent_latency - / (v->return_bandwidth_to_dcn - * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0), - 2)); - } - v->return_bandwidth_to_dcn = dcn_bw_min2( - v->return_bus_width * v->dcfclk, - v->fabric_and_dram_bandwidth * 1000.0); - if (v->dcc_enabled_any_plane == dcn_bw_yes - && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { - v->return_bw = - dcn_bw_min2( - v->return_bw, - v->return_bandwidth_to_dcn * 4.0 - * (1.0 - - v->urgent_latency - / ((v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - / (v->return_bandwidth_to_dcn - - v->dcfclk - * v->return_bus_width - / 4.0) - + v->urgent_latency))); - } - v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency - / (v->return_bandwidth_to_dcn * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) * 1024.0); - if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 - && v->critical_compression < 4.0) { - v->return_bw = - dcn_bw_min2( - v->return_bw, - dcn_bw_pow( - 4.0 * v->return_bandwidth_to_dcn - * (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0 - * v->return_bus_width - * v->dcfclk - * v->urgent_latency - / (v->return_bandwidth_to_dcn - * v->urgent_latency - + (v->rob_buffer_size_in_kbyte - - v->pixel_chunk_size_in_kbyte) - * 1024.0), - 2)); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { + v->return_bw =dcn_bw_min2(v->return_bw, v->return_bandwidth_to_dcn * 4.0 * (1.0 - v->urgent_latency / ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / (v->return_bandwidth_to_dcn - v->dcfclk * v->return_bus_width / 4.0) + v->urgent_latency))); + } + v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency / (v->return_bandwidth_to_dcn * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 && v->critical_compression < 4.0) { + v->return_bw =dcn_bw_min2(v->return_bw, dcn_bw_pow(4.0 * v->return_bandwidth_to_dcn * (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 * v->return_bus_width * v->dcfclk * v->urgent_latency / (v->return_bandwidth_to_dcn * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0), 2)); + } + v->return_bandwidth_to_dcn =dcn_bw_min2(v->return_bus_width * v->dcfclk, v->fabric_and_dram_bandwidth * 1000.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->return_bandwidth_to_dcn > v->dcfclk * v->return_bus_width / 4.0) { + v->return_bw =dcn_bw_min2(v->return_bw, v->return_bandwidth_to_dcn * 4.0 * (1.0 - v->urgent_latency / ((v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 / (v->return_bandwidth_to_dcn - v->dcfclk * v->return_bus_width / 4.0) + v->urgent_latency))); + } + v->critical_compression = 2.0 * v->return_bus_width * v->dcfclk * v->urgent_latency / (v->return_bandwidth_to_dcn * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0); + if (v->dcc_enabled_any_plane == dcn_bw_yes && v->critical_compression > 1.0 && v->critical_compression < 4.0) { + v->return_bw =dcn_bw_min2(v->return_bw, dcn_bw_pow(4.0 * v->return_bandwidth_to_dcn * (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0 * v->return_bus_width * v->dcfclk * v->urgent_latency / (v->return_bandwidth_to_dcn * v->urgent_latency + (v->rob_buffer_size_in_kbyte - v->pixel_chunk_size_in_kbyte) * 1024.0), 2)); } for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->source_scan[k] == dcn_bw_hor) { v->swath_width_y[k] = v->viewport_width[k] / v->dpp_per_plane[k]; - } else { + } + else { v->swath_width_y[k] = v->viewport_height[k] / v->dpp_per_plane[k]; } } @@ -2411,31 +1213,29 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->byte_per_pixel_dety[k] = 8.0; v->byte_per_pixel_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) { v->byte_per_pixel_dety[k] = 4.0; v->byte_per_pixel_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) { v->byte_per_pixel_dety[k] = 2.0; v->byte_per_pixel_detc[k] = 0.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->byte_per_pixel_dety[k] = 1.0; v->byte_per_pixel_detc[k] = 2.0; - } else { - v->byte_per_pixel_dety[k] = 4.0f / 3; - v->byte_per_pixel_detc[k] = 8.0f / 3; + } + else { + v->byte_per_pixel_dety[k] = 4.0f / 3.0f; + v->byte_per_pixel_detc[k] = 8.0f / 3.0f; } } v->total_data_read_bandwidth = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->read_bandwidth_plane_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) - / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k]; - v->read_bandwidth_plane_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] - * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k] / 2.0; - v->total_data_read_bandwidth = v->total_data_read_bandwidth - + v->read_bandwidth_plane_luma[k] - + v->read_bandwidth_plane_chroma[k]; + v->read_bandwidth_plane_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k]; + v->read_bandwidth_plane_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k] / 2.0; + v->total_data_read_bandwidth = v->total_data_read_bandwidth + v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k]; } v->total_active_dpp = 0.0; v->total_dcc_active_dpp = 0.0; @@ -2445,63 +1245,36 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->total_dcc_active_dpp = v->total_dcc_active_dpp + v->dpp_per_plane[k]; } } - v->urgent_round_trip_and_out_of_order_latency = (v->round_trip_ping_latency_cycles + 32.0) - / v->dcfclk - + v->urgent_out_of_order_return_per_channel * v->number_of_channels - / v->return_bw; + v->urgent_round_trip_and_out_of_order_latency = (v->round_trip_ping_latency_cycles + 32.0) / v->dcfclk + v->urgent_out_of_order_return_per_channel * v->number_of_channels / v->return_bw; v->last_pixel_of_line_extra_watermark = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->v_ratio[k] <= 1.0) { - v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] - * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; - } else { - v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] - / v->pscl_throughput[k] / v->dppclk; - } - v->data_fabric_line_delivery_time_luma = - v->swath_width_y[k] * v->swath_height_y[k] - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) - / (v->return_bw * v->read_bandwidth_plane_luma[k] - / v->dpp_per_plane[k] - / v->total_data_read_bandwidth); - v->last_pixel_of_line_extra_watermark = dcn_bw_max2( - v->last_pixel_of_line_extra_watermark, - v->data_fabric_line_delivery_time_luma - - v->display_pipe_line_delivery_time_luma[k]); + v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } + else { + v->display_pipe_line_delivery_time_luma[k] = v->swath_width_y[k] / v->pscl_throughput[k] / v->dppclk; + } + v->data_fabric_line_delivery_time_luma = v->swath_width_y[k] * v->swath_height_y[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / (v->return_bw * v->read_bandwidth_plane_luma[k] / v->dpp_per_plane[k] / v->total_data_read_bandwidth); + v->last_pixel_of_line_extra_watermark =dcn_bw_max2(v->last_pixel_of_line_extra_watermark, v->data_fabric_line_delivery_time_luma - v->display_pipe_line_delivery_time_luma[k]); if (v->byte_per_pixel_detc[k] == 0.0) { v->display_pipe_line_delivery_time_chroma[k] = 0.0; - } else { + } + else { if (v->v_ratio[k] / 2.0 <= 1.0) { - v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] - / 2.0 * v->dpp_per_plane[k] / (v->h_ratio[k] / 2.0) - / v->pixel_clock[k]; - } else { - v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] - / 2.0 / v->pscl_throughput_chroma[k] / v->dppclk; - } - v->data_fabric_line_delivery_time_chroma = v->swath_width_y[k] / 2.0 - * v->swath_height_c[k] - * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / (v->return_bw * v->read_bandwidth_plane_chroma[k] - / v->dpp_per_plane[k] - / v->total_data_read_bandwidth); - v->last_pixel_of_line_extra_watermark = - dcn_bw_max2( - v->last_pixel_of_line_extra_watermark, - v->data_fabric_line_delivery_time_chroma - - v->display_pipe_line_delivery_time_chroma[k]); - } - } - v->urgent_extra_latency = v->urgent_round_trip_and_out_of_order_latency - + (v->total_active_dpp * v->pixel_chunk_size_in_kbyte - + v->total_dcc_active_dpp * v->meta_chunk_size) * 1024.0 - / v->return_bw; + v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] / (v->h_ratio[k] / 2.0) / v->pixel_clock[k]; + } + else { + v->display_pipe_line_delivery_time_chroma[k] = v->swath_width_y[k] / 2.0 / v->pscl_throughput_chroma[k] / v->dppclk; + } + v->data_fabric_line_delivery_time_chroma = v->swath_width_y[k] / 2.0 * v->swath_height_c[k] *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / (v->return_bw * v->read_bandwidth_plane_chroma[k] / v->dpp_per_plane[k] / v->total_data_read_bandwidth); + v->last_pixel_of_line_extra_watermark =dcn_bw_max2(v->last_pixel_of_line_extra_watermark, v->data_fabric_line_delivery_time_chroma - v->display_pipe_line_delivery_time_chroma[k]); + } + } + v->urgent_extra_latency = v->urgent_round_trip_and_out_of_order_latency + (v->total_active_dpp * v->pixel_chunk_size_in_kbyte + v->total_dcc_active_dpp * v->meta_chunk_size) * 1024.0 / v->return_bw; if (v->pte_enable == dcn_bw_yes) { - v->urgent_extra_latency = v->urgent_extra_latency - + v->total_active_dpp * v->pte_chunk_size * 1024.0 / v->return_bw; + v->urgent_extra_latency = v->urgent_extra_latency + v->total_active_dpp * v->pte_chunk_size * 1024.0 / v->return_bw; } - v->urgent_watermark = v->urgent_latency + v->last_pixel_of_line_extra_watermark - + v->urgent_extra_latency; + v->urgent_watermark = v->urgent_latency + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency; v->ptemeta_urgent_watermark = v->urgent_watermark + 2.0 * v->urgent_latency; /*nb p-state/dram clock change watermark*/ @@ -2513,33 +1286,23 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan } } if (v->total_active_writeback <= 1.0) { - v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency - + v->write_back_latency; - } else { - v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency - + v->write_back_latency - + v->writeback_chunk_size * 1024.0 / 32.0 / v->socclk; + v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency + v->write_back_latency; + } + else { + v->writeback_dram_clock_change_watermark = v->dram_clock_change_latency + v->write_back_latency + v->writeback_chunk_size * 1024.0 / 32.0 / v->socclk; } /*stutter efficiency*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->lines_in_dety[k] = v->det_buffer_size_y[k] / v->byte_per_pixel_dety[k] - / v->swath_width_y[k]; - v->lines_in_dety_rounded_down_to_swath[k] = dcn_bw_floor2( - v->lines_in_dety[k], - v->swath_height_y[k]); - v->full_det_buffering_time_y[k] = v->lines_in_dety_rounded_down_to_swath[k] - * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k]; + v->lines_in_dety[k] = v->det_buffer_size_y[k] / v->byte_per_pixel_dety[k] / v->swath_width_y[k]; + v->lines_in_dety_rounded_down_to_swath[k] =dcn_bw_floor2(v->lines_in_dety[k], v->swath_height_y[k]); + v->full_det_buffering_time_y[k] = v->lines_in_dety_rounded_down_to_swath[k] * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k]; if (v->byte_per_pixel_detc[k] > 0.0) { - v->lines_in_detc[k] = v->det_buffer_size_c[k] / v->byte_per_pixel_detc[k] - / (v->swath_width_y[k] / 2.0); - v->lines_in_detc_rounded_down_to_swath[k] = dcn_bw_floor2( - v->lines_in_detc[k], - v->swath_height_c[k]); - v->full_det_buffering_time_c[k] = v->lines_in_detc_rounded_down_to_swath[k] - * (v->htotal[k] / v->pixel_clock[k]) - / (v->v_ratio[k] / 2.0); - } else { + v->lines_in_detc[k] = v->det_buffer_size_c[k] / v->byte_per_pixel_detc[k] / (v->swath_width_y[k] / 2.0); + v->lines_in_detc_rounded_down_to_swath[k] =dcn_bw_floor2(v->lines_in_detc[k], v->swath_height_c[k]); + v->full_det_buffering_time_c[k] = v->lines_in_detc_rounded_down_to_swath[k] * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0); + } + else { v->lines_in_detc[k] = 0.0; v->lines_in_detc_rounded_down_to_swath[k] = 0.0; v->full_det_buffering_time_c[k] = 999999.0; @@ -2549,166 +1312,83 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->full_det_buffering_time_y[k] < v->min_full_det_buffering_time) { v->min_full_det_buffering_time = v->full_det_buffering_time_y[k]; - v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] - / v->pixel_clock[k]; + v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] / v->pixel_clock[k]; } if (v->full_det_buffering_time_c[k] < v->min_full_det_buffering_time) { v->min_full_det_buffering_time = v->full_det_buffering_time_c[k]; - v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] - / v->pixel_clock[k]; + v->frame_time_for_min_full_det_buffering_time = v->vtotal[k] * v->htotal[k] / v->pixel_clock[k]; } } v->average_read_bandwidth_gbyte_per_second = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->dcc_enable[k] == dcn_bw_yes) { - v->average_read_bandwidth_gbyte_per_second = - v->average_read_bandwidth_gbyte_per_second - + v->read_bandwidth_plane_luma[k] - / v->dcc_rate[k] / 1000.0 - + v->read_bandwidth_plane_chroma[k] - / v->dcc_rate[k] / 1000.0; - } else { - v->average_read_bandwidth_gbyte_per_second = - v->average_read_bandwidth_gbyte_per_second - + v->read_bandwidth_plane_luma[k] / 1000.0 - + v->read_bandwidth_plane_chroma[k] - / 1000.0; + v->average_read_bandwidth_gbyte_per_second = v->average_read_bandwidth_gbyte_per_second + v->read_bandwidth_plane_luma[k] / v->dcc_rate[k] / 1000.0 + v->read_bandwidth_plane_chroma[k] / v->dcc_rate[k] / 1000.0; + } + else { + v->average_read_bandwidth_gbyte_per_second = v->average_read_bandwidth_gbyte_per_second + v->read_bandwidth_plane_luma[k] / 1000.0 + v->read_bandwidth_plane_chroma[k] / 1000.0; } if (v->dcc_enable[k] == dcn_bw_yes) { - v->average_read_bandwidth_gbyte_per_second = - v->average_read_bandwidth_gbyte_per_second - + v->read_bandwidth_plane_luma[k] / 1000.0 - / 256.0 - + v->read_bandwidth_plane_chroma[k] / 1000.0 - / 256.0; + v->average_read_bandwidth_gbyte_per_second = v->average_read_bandwidth_gbyte_per_second + v->read_bandwidth_plane_luma[k] / 1000.0 / 256.0 + v->read_bandwidth_plane_chroma[k] / 1000.0 / 256.0; } if (v->pte_enable == dcn_bw_yes) { - v->average_read_bandwidth_gbyte_per_second = - v->average_read_bandwidth_gbyte_per_second - + v->read_bandwidth_plane_luma[k] / 1000.0 - / 512.0 - + v->read_bandwidth_plane_chroma[k] / 1000.0 - / 512.0; - } - } - v->part_of_burst_that_fits_in_rob = dcn_bw_min2( - v->min_full_det_buffering_time * v->total_data_read_bandwidth, - v->rob_buffer_size_in_kbyte * 1024.0 * v->total_data_read_bandwidth - / (v->average_read_bandwidth_gbyte_per_second * 1000.0)); - v->stutter_burst_time = v->part_of_burst_that_fits_in_rob - * (v->average_read_bandwidth_gbyte_per_second * 1000.0) - / v->total_data_read_bandwidth / v->return_bw - + (v->min_full_det_buffering_time * v->total_data_read_bandwidth - - v->part_of_burst_that_fits_in_rob) / (v->dcfclk * 64.0); + v->average_read_bandwidth_gbyte_per_second = v->average_read_bandwidth_gbyte_per_second + v->read_bandwidth_plane_luma[k] / 1000.0 / 512.0 + v->read_bandwidth_plane_chroma[k] / 1000.0 / 512.0; + } + } + v->part_of_burst_that_fits_in_rob =dcn_bw_min2(v->min_full_det_buffering_time * v->total_data_read_bandwidth, v->rob_buffer_size_in_kbyte * 1024.0 * v->total_data_read_bandwidth / (v->average_read_bandwidth_gbyte_per_second * 1000.0)); + v->stutter_burst_time = v->part_of_burst_that_fits_in_rob * (v->average_read_bandwidth_gbyte_per_second * 1000.0) / v->total_data_read_bandwidth / v->return_bw + (v->min_full_det_buffering_time * v->total_data_read_bandwidth - v->part_of_burst_that_fits_in_rob) / (v->dcfclk * 64.0); if (v->total_active_writeback == 0.0) { - v->stutter_efficiency_not_including_vblank = (1.0 - - (v->sr_exit_time + v->stutter_burst_time) - / v->min_full_det_buffering_time) * 100.0; - } else { + v->stutter_efficiency_not_including_vblank = (1.0 - (v->sr_exit_time + v->stutter_burst_time) / v->min_full_det_buffering_time) * 100.0; + } + else { v->stutter_efficiency_not_including_vblank = 0.0; } v->smallest_vblank = 999999.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->synchronized_vblank == dcn_bw_yes || v->number_of_active_planes == 1) { - v->v_blank_time = (v->vtotal[k] - v->vactive[k]) * v->htotal[k] - / v->pixel_clock[k]; - } else { + v->v_blank_time = (v->vtotal[k] - v->vactive[k]) * v->htotal[k] / v->pixel_clock[k]; + } + else { v->v_blank_time = 0.0; } - v->smallest_vblank = dcn_bw_min2(v->smallest_vblank, v->v_blank_time); + v->smallest_vblank =dcn_bw_min2(v->smallest_vblank, v->v_blank_time); } - v->stutter_efficiency = (v->stutter_efficiency_not_including_vblank / 100.0 - * (v->frame_time_for_min_full_det_buffering_time - v->smallest_vblank) - + v->smallest_vblank) / v->frame_time_for_min_full_det_buffering_time - * 100.0; + v->stutter_efficiency = (v->stutter_efficiency_not_including_vblank / 100.0 * (v->frame_time_for_min_full_det_buffering_time - v->smallest_vblank) + v->smallest_vblank) / v->frame_time_for_min_full_det_buffering_time * 100.0; /*dcfclk deep sleep*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->byte_per_pixel_detc[k] > 0.0) { - v->dcfclk_deep_sleep_per_plane[k] = - dcn_bw_max2( - 1.1 * v->swath_width_y[k] - * dcn_bw_ceil2( - v->byte_per_pixel_dety[k], - 1.0) / 32.0 - / v->display_pipe_line_delivery_time_luma[k], - 1.1 * v->swath_width_y[k] / 2.0 - * dcn_bw_ceil2( - v->byte_per_pixel_detc[k], - 2.0) / 32.0 - / v->display_pipe_line_delivery_time_chroma[k]); - } else { - v->dcfclk_deep_sleep_per_plane[k] = 1.1 * v->swath_width_y[k] - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 64.0 - / v->display_pipe_line_delivery_time_luma[k]; - } - v->dcfclk_deep_sleep_per_plane[k] = dcn_bw_max2( - v->dcfclk_deep_sleep_per_plane[k], - v->pixel_clock[k] / 16.0); + v->dcfclk_deep_sleep_per_plane[k] =dcn_bw_max2(1.1 * v->swath_width_y[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 32.0 / v->display_pipe_line_delivery_time_luma[k], 1.1 * v->swath_width_y[k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 32.0 / v->display_pipe_line_delivery_time_chroma[k]); + } + else { + v->dcfclk_deep_sleep_per_plane[k] = 1.1 * v->swath_width_y[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 64.0 / v->display_pipe_line_delivery_time_luma[k]; + } + v->dcfclk_deep_sleep_per_plane[k] =dcn_bw_max2(v->dcfclk_deep_sleep_per_plane[k], v->pixel_clock[k] / 16.0); } v->dcf_clk_deep_sleep = 8.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->dcf_clk_deep_sleep = dcn_bw_max2( - v->dcf_clk_deep_sleep, - v->dcfclk_deep_sleep_per_plane[k]); + v->dcf_clk_deep_sleep =dcn_bw_max2(v->dcf_clk_deep_sleep, v->dcfclk_deep_sleep_per_plane[k]); } /*stutter watermark*/ - v->stutter_exit_watermark = v->sr_exit_time + v->last_pixel_of_line_extra_watermark - + v->urgent_extra_latency + 10.0 / v->dcf_clk_deep_sleep; - v->stutter_enter_plus_exit_watermark = v->sr_enter_plus_exit_time - + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency; + v->stutter_exit_watermark = v->sr_exit_time + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency + 10.0 / v->dcf_clk_deep_sleep; + v->stutter_enter_plus_exit_watermark = v->sr_enter_plus_exit_time + v->last_pixel_of_line_extra_watermark + v->urgent_extra_latency; /*urgent latency supported*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->effective_det_plus_lb_lines_luma = - dcn_bw_floor2( - v->lines_in_dety[k] - + dcn_bw_min2( - v->lines_in_dety[k] - * v->dppclk - * v->byte_per_pixel_dety[k] - * v->pscl_throughput[k] - / (v->return_bw - / v->dpp_per_plane[k]), - v->effective_lb_latency_hiding_source_lines_luma), - v->swath_height_y[k]); - v->urgent_latency_support_us_luma = v->effective_det_plus_lb_lines_luma - * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - - v->effective_det_plus_lb_lines_luma * v->swath_width_y[k] - * v->byte_per_pixel_dety[k] - / (v->return_bw / v->dpp_per_plane[k]); + v->effective_det_plus_lb_lines_luma =dcn_bw_floor2(v->lines_in_dety[k] +dcn_bw_min2(v->lines_in_dety[k] * v->dppclk * v->byte_per_pixel_dety[k] * v->pscl_throughput[k] / (v->return_bw / v->dpp_per_plane[k]), v->effective_lb_latency_hiding_source_lines_luma), v->swath_height_y[k]); + v->urgent_latency_support_us_luma = v->effective_det_plus_lb_lines_luma * (v->htotal[k] / v->pixel_clock[k]) / v->v_ratio[k] - v->effective_det_plus_lb_lines_luma * v->swath_width_y[k] * v->byte_per_pixel_dety[k] / (v->return_bw / v->dpp_per_plane[k]); if (v->byte_per_pixel_detc[k] > 0.0) { - v->effective_det_plus_lb_lines_chroma = - dcn_bw_floor2( - v->lines_in_detc[k] - + dcn_bw_min2( - v->lines_in_detc[k] - * v->dppclk - * v->byte_per_pixel_detc[k] - * v->pscl_throughput_chroma[k] - / (v->return_bw - / v->dpp_per_plane[k]), - v->effective_lb_latency_hiding_source_lines_chroma), - v->swath_height_c[k]); - v->urgent_latency_support_us_chroma = v->effective_det_plus_lb_lines_chroma - * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) - - v->effective_det_plus_lb_lines_chroma - * (v->swath_width_y[k] / 2.0) - * v->byte_per_pixel_detc[k] - / (v->return_bw / v->dpp_per_plane[k]); - v->urgent_latency_support_us[k] = dcn_bw_min2( - v->urgent_latency_support_us_luma, - v->urgent_latency_support_us_chroma); - } else { + v->effective_det_plus_lb_lines_chroma =dcn_bw_floor2(v->lines_in_detc[k] +dcn_bw_min2(v->lines_in_detc[k] * v->dppclk * v->byte_per_pixel_detc[k] * v->pscl_throughput_chroma[k] / (v->return_bw / v->dpp_per_plane[k]), v->effective_lb_latency_hiding_source_lines_chroma), v->swath_height_c[k]); + v->urgent_latency_support_us_chroma = v->effective_det_plus_lb_lines_chroma * (v->htotal[k] / v->pixel_clock[k]) / (v->v_ratio[k] / 2.0) - v->effective_det_plus_lb_lines_chroma * (v->swath_width_y[k] / 2.0) * v->byte_per_pixel_detc[k] / (v->return_bw / v->dpp_per_plane[k]); + v->urgent_latency_support_us[k] =dcn_bw_min2(v->urgent_latency_support_us_luma, v->urgent_latency_support_us_chroma); + } + else { v->urgent_latency_support_us[k] = v->urgent_latency_support_us_luma; } } v->min_urgent_latency_support_us = 999999.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->min_urgent_latency_support_us = dcn_bw_min2( - v->min_urgent_latency_support_us, - v->urgent_latency_support_us[k]); + v->min_urgent_latency_support_us =dcn_bw_min2(v->min_urgent_latency_support_us, v->urgent_latency_support_us[k]); } /*non-urgent latency tolerance*/ @@ -2716,63 +1396,50 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan /*prefetch*/ for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 - || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { + if ((v->source_pixel_format[k] == dcn_bw_rgb_sub_64 || v->source_pixel_format[k] == dcn_bw_rgb_sub_32 || v->source_pixel_format[k] == dcn_bw_rgb_sub_16)) { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->block_height256_bytes_y = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { + } + else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) { v->block_height256_bytes_y = 4.0; - } else { + } + else { v->block_height256_bytes_y = 8.0; } v->block_height256_bytes_c = 0.0; - } else { + } + else { if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->block_height256_bytes_y = 1.0; v->block_height256_bytes_c = 1.0; - } else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { + } + else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) { v->block_height256_bytes_y = 16.0; v->block_height256_bytes_c = 8.0; - } else { + } + else { v->block_height256_bytes_y = 8.0; v->block_height256_bytes_c = 8.0; } } if (v->dcc_enable[k] == dcn_bw_yes) { - v->meta_request_width_y = 64.0 * 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) - / (8.0 * v->block_height256_bytes_y); - v->meta_surf_width_y = dcn_bw_ceil2( - v->swath_width_y[k] - 1.0, - v->meta_request_width_y) + v->meta_request_width_y; - v->meta_surf_height_y = dcn_bw_ceil2( - v->viewport_height[k] - 1.0, - 8.0 * v->block_height256_bytes_y) - + 8.0 * v->block_height256_bytes_y; + v->meta_request_width_y = 64.0 * 256.0 /dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / (8.0 * v->block_height256_bytes_y); + v->meta_surf_width_y =dcn_bw_ceil2(v->swath_width_y[k] - 1.0, v->meta_request_width_y) + v->meta_request_width_y; + v->meta_surf_height_y =dcn_bw_ceil2(v->viewport_height[k] - 1.0, 8.0 * v->block_height256_bytes_y) + 8.0 * v->block_height256_bytes_y; if (v->pte_enable == dcn_bw_yes) { - v->meta_pte_bytes_frame_y = - (dcn_bw_ceil2( - (v->meta_surf_width_y - * v->meta_surf_height_y - * dcn_bw_ceil2( - v->byte_per_pixel_dety[k], - 1.0) - / 256.0 - 4096.0) - / 8.0 / 4096.0, - 1.0) + 1) * 64.0; - } else { + v->meta_pte_bytes_frame_y = (dcn_bw_ceil2((v->meta_surf_width_y * v->meta_surf_height_y *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0 - 4096.0) / 8.0 / 4096.0, 1.0) + 1) * 64.0; + } + else { v->meta_pte_bytes_frame_y = 0.0; } if (v->source_scan[k] == dcn_bw_hor) { - v->meta_row_byte_y = v->meta_surf_width_y * 8.0 - * v->block_height256_bytes_y - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; - } else { - v->meta_row_byte_y = v->meta_surf_height_y * v->meta_request_width_y - * dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; - } - } else { + v->meta_row_byte_y = v->meta_surf_width_y * 8.0 * v->block_height256_bytes_y *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; + } + else { + v->meta_row_byte_y = v->meta_surf_height_y * v->meta_request_width_y *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / 256.0; + } + } + else { v->meta_pte_bytes_frame_y = 0.0; v->meta_row_byte_y = 0.0; } @@ -2780,112 +1447,58 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->macro_tile_size_byte_y = 256.0; v->macro_tile_height_y = 1.0; - } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { v->macro_tile_size_byte_y = 4096.0; v->macro_tile_height_y = 4.0 * v->block_height256_bytes_y; - } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { v->macro_tile_size_byte_y = 64.0 * 1024; v->macro_tile_height_y = 16.0 * v->block_height256_bytes_y; - } else { + } + else { v->macro_tile_size_byte_y = 256.0 * 1024; v->macro_tile_height_y = 32.0 * v->block_height256_bytes_y; } if (v->macro_tile_size_byte_y <= 65536.0) { v->pixel_pte_req_height_y = v->macro_tile_height_y; - } else { + } + else { v->pixel_pte_req_height_y = 16.0 * v->block_height256_bytes_y; } - v->pixel_pte_req_width_y = 4096.0 / dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) - / v->pixel_pte_req_height_y * 8; + v->pixel_pte_req_width_y = 4096.0 /dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / v->pixel_pte_req_height_y * 8; if (v->source_surface_mode[k] == dcn_bw_sw_linear) { - v->pixel_pte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->swath_width_y[k] - * dcn_bw_min2( - 128.0, - dcn_bw_pow( - 2.0, - dcn_bw_floor2( - dcn_bw_log( - v->pte_buffer_size_in_requests - * v->pixel_pte_req_width_y - / v->swath_width_y[k], - 2.0), - 1.0))) - - 1.0) - / v->pixel_pte_req_width_y, - 1.0) + 1); - } else if (v->source_scan[k] == dcn_bw_hor) { - v->pixel_pte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->swath_width_y[k] - - 1.0) - / v->pixel_pte_req_width_y, - 1.0) + 1); - } else { - v->pixel_pte_bytes_per_row_y = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_height[k] - - 1.0) - / v->pixel_pte_req_height_y, - 1.0) + 1); - } - } else { + v->pixel_pte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->swath_width_y[k] *dcn_bw_min2(128.0, dcn_bw_pow(2.0,dcn_bw_floor2(dcn_bw_log(v->pte_buffer_size_in_requests * v->pixel_pte_req_width_y / v->swath_width_y[k], 2.0), 1.0))) - 1.0) / v->pixel_pte_req_width_y, 1.0) + 1); + } + else if (v->source_scan[k] == dcn_bw_hor) { + v->pixel_pte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->swath_width_y[k] - 1.0) / v->pixel_pte_req_width_y, 1.0) + 1); + } + else { + v->pixel_pte_bytes_per_row_y = 64.0 * (dcn_bw_ceil2((v->viewport_height[k] - 1.0) / v->pixel_pte_req_height_y, 1.0) + 1); + } + } + else { v->pixel_pte_bytes_per_row_y = 0.0; } - if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { if (v->dcc_enable[k] == dcn_bw_yes) { - v->meta_request_width_c = 64.0 * 256.0 - / dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / (8.0 * v->block_height256_bytes_c); - v->meta_surf_width_c = dcn_bw_ceil2( - v->swath_width_y[k] / 2.0 - 1.0, - v->meta_request_width_c) + v->meta_request_width_c; - v->meta_surf_height_c = dcn_bw_ceil2( - v->viewport_height[k] / 2.0 - 1.0, - 8.0 * v->block_height256_bytes_c) - + 8.0 * v->block_height256_bytes_c; + v->meta_request_width_c = 64.0 * 256.0 /dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / (8.0 * v->block_height256_bytes_c); + v->meta_surf_width_c =dcn_bw_ceil2(v->swath_width_y[k] / 2.0 - 1.0, v->meta_request_width_c) + v->meta_request_width_c; + v->meta_surf_height_c =dcn_bw_ceil2(v->viewport_height[k] / 2.0 - 1.0, 8.0 * v->block_height256_bytes_c) + 8.0 * v->block_height256_bytes_c; if (v->pte_enable == dcn_bw_yes) { - v->meta_pte_bytes_frame_c = - (dcn_bw_ceil2( - (v->meta_surf_width_c - * v->meta_surf_height_c - * dcn_bw_ceil2( - v->byte_per_pixel_detc[k], - 2.0) - / 256.0 - - 4096.0) - / 8.0 - / 4096.0, - 1.0) + 1) * 64.0; - } else { + v->meta_pte_bytes_frame_c = (dcn_bw_ceil2((v->meta_surf_width_c * v->meta_surf_height_c *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 256.0 - 4096.0) / 8.0 / 4096.0, 1.0) + 1) * 64.0; + } + else { v->meta_pte_bytes_frame_c = 0.0; } if (v->source_scan[k] == dcn_bw_hor) { - v->meta_row_byte_c = v->meta_surf_width_c * 8.0 - * v->block_height256_bytes_c - * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / 256.0; - } else { - v->meta_row_byte_c = v->meta_surf_height_c - * v->meta_request_width_c - * dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / 256.0; - } - } else { + v->meta_row_byte_c = v->meta_surf_width_c * 8.0 * v->block_height256_bytes_c *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 256.0; + } + else { + v->meta_row_byte_c = v->meta_surf_height_c * v->meta_request_width_c *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 256.0; + } + } + else { v->meta_pte_bytes_frame_c = 0.0; v->meta_row_byte_c = 0.0; } @@ -2893,143 +1506,81 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan if (v->source_surface_mode[k] == dcn_bw_sw_linear) { v->macro_tile_size_bytes_c = 256.0; v->macro_tile_height_c = 1.0; - } else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d - || v->source_surface_mode[k] - == dcn_bw_sw_4_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_4_kb_s || v->source_surface_mode[k] == dcn_bw_sw_4_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x) { v->macro_tile_size_bytes_c = 4096.0; v->macro_tile_height_c = 4.0 * v->block_height256_bytes_c; - } else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d - || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t - || v->source_surface_mode[k] - == dcn_bw_sw_64_kb_d_x) { + } + else if (v->source_surface_mode[k] == dcn_bw_sw_64_kb_s || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_s_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x) { v->macro_tile_size_bytes_c = 64.0 * 1024; v->macro_tile_height_c = 16.0 * v->block_height256_bytes_c; - } else { + } + else { v->macro_tile_size_bytes_c = 256.0 * 1024; v->macro_tile_height_c = 32.0 * v->block_height256_bytes_c; } if (v->macro_tile_size_bytes_c <= 65536.0) { v->pixel_pte_req_height_c = v->macro_tile_height_c; - } else { - v->pixel_pte_req_height_c = 16.0 - * v->block_height256_bytes_c; } - v->pixel_pte_req_width_c = 4096.0 - / dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) - / v->pixel_pte_req_height_c * 8; + else { + v->pixel_pte_req_height_c = 16.0 * v->block_height256_bytes_c; + } + v->pixel_pte_req_width_c = 4096.0 /dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / v->pixel_pte_req_height_c * 8; if (v->source_surface_mode[k] == dcn_bw_sw_linear) { - v->pixel_pte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->swath_width_y[k] - / 2.0 - * dcn_bw_min2( - 128.0, - dcn_bw_pow( - 2.0, - dcn_bw_floor2( - dcn_bw_log( - v->pte_buffer_size_in_requests - * v->pixel_pte_req_width_c - / (v->swath_width_y[k] - / 2.0), - 2.0), - 1.0))) - - 1.0) - / v->pixel_pte_req_width_c, - 1.0) + 1); - } else if (v->source_scan[k] == dcn_bw_hor) { - v->pixel_pte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->swath_width_y[k] - / 2.0 - - 1.0) - / v->pixel_pte_req_width_c, - 1.0) + 1); - } else { - v->pixel_pte_bytes_per_row_c = - 64.0 - * (dcn_bw_ceil2( - (v->viewport_height[k] - / 2.0 - - 1.0) - / v->pixel_pte_req_height_c, - 1.0) + 1); - } - } else { + v->pixel_pte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->swath_width_y[k] / 2.0 * dcn_bw_min2(128.0, dcn_bw_pow(2.0,dcn_bw_floor2(dcn_bw_log(v->pte_buffer_size_in_requests * v->pixel_pte_req_width_c / (v->swath_width_y[k] / 2.0), 2.0), 1.0))) - 1.0) / v->pixel_pte_req_width_c, 1.0) + 1); + } + else if (v->source_scan[k] == dcn_bw_hor) { + v->pixel_pte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->swath_width_y[k] / 2.0 - 1.0) / v->pixel_pte_req_width_c, 1.0) + 1); + } + else { + v->pixel_pte_bytes_per_row_c = 64.0 * (dcn_bw_ceil2((v->viewport_height[k] / 2.0 - 1.0) / v->pixel_pte_req_height_c, 1.0) + 1); + } + } + else { v->pixel_pte_bytes_per_row_c = 0.0; } - } else { + } + else { v->pixel_pte_bytes_per_row_c = 0.0; v->meta_pte_bytes_frame_c = 0.0; v->meta_row_byte_c = 0.0; } - v->pixel_pte_bytes_per_row[k] = v->pixel_pte_bytes_per_row_y - + v->pixel_pte_bytes_per_row_c; + v->pixel_pte_bytes_per_row[k] = v->pixel_pte_bytes_per_row_y + v->pixel_pte_bytes_per_row_c; v->meta_pte_bytes_frame[k] = v->meta_pte_bytes_frame_y + v->meta_pte_bytes_frame_c; v->meta_row_byte[k] = v->meta_row_byte_y + v->meta_row_byte_c; - v->v_init_pre_fill_y[k] = dcn_bw_floor2( - (v->v_ratio[k] + v->vtaps[k] + 1.0 - + v->interlace_output[k] * 0.5 * v->v_ratio[k]) - / 2.0, - 1.0); - v->max_num_swath_y[k] = dcn_bw_ceil2( - (v->v_init_pre_fill_y[k] - 1.0) / v->swath_height_y[k], - 1.0) + 1; + v->v_init_pre_fill_y[k] =dcn_bw_floor2((v->v_ratio[k] + v->vtaps[k] + 1.0 + v->interlace_output[k] * 0.5 * v->v_ratio[k]) / 2.0, 1.0); + v->max_num_swath_y[k] =dcn_bw_ceil2((v->v_init_pre_fill_y[k] - 1.0) / v->swath_height_y[k], 1.0) + 1; if (v->v_init_pre_fill_y[k] > 1.0) { - v->max_partial_swath_y = dcn_bw_mod( - (v->v_init_pre_fill_y[k] - 2.0), - v->swath_height_y[k]); - } else { - v->max_partial_swath_y = dcn_bw_mod( - (v->v_init_pre_fill_y[k] + v->swath_height_y[k] - 2.0), - v->swath_height_y[k]); - } - v->max_partial_swath_y = dcn_bw_max2(1.0, v->max_partial_swath_y); - v->prefetch_source_lines_y[k] = v->max_num_swath_y[k] * v->swath_height_y[k] - + v->max_partial_swath_y; - if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 - && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { - v->v_init_pre_fill_c[k] = dcn_bw_floor2( - (v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 - + v->interlace_output[k] * 0.5 - * v->v_ratio[k] / 2.0) - / 2.0, - 1.0); - v->max_num_swath_c[k] = dcn_bw_ceil2( - (v->v_init_pre_fill_c[k] - 1.0) / v->swath_height_c[k], - 1.0) + 1; + v->max_partial_swath_y =dcn_bw_mod((v->v_init_pre_fill_y[k] - 2.0), v->swath_height_y[k]); + } + else { + v->max_partial_swath_y =dcn_bw_mod((v->v_init_pre_fill_y[k] + v->swath_height_y[k] - 2.0), v->swath_height_y[k]); + } + v->max_partial_swath_y =dcn_bw_max2(1.0, v->max_partial_swath_y); + v->prefetch_source_lines_y[k] = v->max_num_swath_y[k] * v->swath_height_y[k] + v->max_partial_swath_y; + if ((v->source_pixel_format[k] != dcn_bw_rgb_sub_64 && v->source_pixel_format[k] != dcn_bw_rgb_sub_32 && v->source_pixel_format[k] != dcn_bw_rgb_sub_16)) { + v->v_init_pre_fill_c[k] =dcn_bw_floor2((v->v_ratio[k] / 2.0 + v->vtaps[k] + 1.0 + v->interlace_output[k] * 0.5 * v->v_ratio[k] / 2.0) / 2.0, 1.0); + v->max_num_swath_c[k] =dcn_bw_ceil2((v->v_init_pre_fill_c[k] - 1.0) / v->swath_height_c[k], 1.0) + 1; if (v->v_init_pre_fill_c[k] > 1.0) { - v->max_partial_swath_c = dcn_bw_mod( - (v->v_init_pre_fill_c[k] - 2.0), - v->swath_height_c[k]); - } else { - v->max_partial_swath_c = dcn_bw_mod( - (v->v_init_pre_fill_c[k] + v->swath_height_c[k] - - 2.0), - v->swath_height_c[k]); - } - v->max_partial_swath_c = dcn_bw_max2(1.0, v->max_partial_swath_c); - } else { + v->max_partial_swath_c =dcn_bw_mod((v->v_init_pre_fill_c[k] - 2.0), v->swath_height_c[k]); + } + else { + v->max_partial_swath_c =dcn_bw_mod((v->v_init_pre_fill_c[k] + v->swath_height_c[k] - 2.0), v->swath_height_c[k]); + } + v->max_partial_swath_c =dcn_bw_max2(1.0, v->max_partial_swath_c); + } + else { v->max_num_swath_c[k] = 0.0; v->max_partial_swath_c = 0.0; } - v->prefetch_source_lines_c[k] = v->max_num_swath_c[k] * v->swath_height_c[k] - + v->max_partial_swath_c; + v->prefetch_source_lines_c[k] = v->max_num_swath_c[k] * v->swath_height_c[k] + v->max_partial_swath_c; } v->t_calc = 24.0 / v->dcf_clk_deep_sleep; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one - == dcn_bw_yes) { + if (v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes) { v->max_vstartup_lines[k] = v->vtotal[k] - v->vactive[k] - 1.0; - } else { + } + else { v->max_vstartup_lines[k] = v->v_sync_plus_back_porch[k] - 1.0; } } @@ -3037,373 +1588,167 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan do { v->v_startup_lines = 13.0; do { - v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = - dcn_bw_yes; - v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = - dcn_bw_no; - v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = - dcn_bw_no; + v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = dcn_bw_yes; + v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = dcn_bw_no; + v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = dcn_bw_no; v->v_ratio_prefetch_more_than4 = dcn_bw_no; v->destination_line_times_for_prefetch_less_than2 = dcn_bw_no; v->prefetch_mode = v->next_prefetch_mode; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->dstx_after_scaler = 90.0 * v->pixel_clock[k] / v->dppclk - + 42.0 * v->pixel_clock[k] / v->dispclk; + v->dstx_after_scaler = 90.0 * v->pixel_clock[k] / v->dppclk + 42.0 * v->pixel_clock[k] / v->dispclk; if (v->dpp_per_plane[k] > 1.0) { - v->dstx_after_scaler = v->dstx_after_scaler - + v->scaler_rec_out_width[k] / 2.0; + v->dstx_after_scaler = v->dstx_after_scaler + v->scaler_rec_out_width[k] / 2.0; } if (v->output_format[k] == dcn_bw_420) { v->dsty_after_scaler = 1.0; - } else { + } + else { v->dsty_after_scaler = 0.0; } - v->v_update_offset_pix = dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); - v->total_repeater_delay_time = v->max_inter_dcn_tile_repeaters - * (2.0 / v->dppclk + 3.0 / v->dispclk); - v->v_update_width_pix = (14.0 / v->dcf_clk_deep_sleep - + 12.0 / v->dppclk + v->total_repeater_delay_time) - * v->pixel_clock[k]; - v->v_ready_offset_pix = dcn_bw_max2( - 150.0 / v->dppclk, - v->total_repeater_delay_time - + 20.0 / v->dcf_clk_deep_sleep - + 10.0 / v->dppclk) - * v->pixel_clock[k]; - v->t_setup = (v->v_update_offset_pix + v->v_update_width_pix - + v->v_ready_offset_pix) / v->pixel_clock[k]; - v->v_startup[k] = dcn_bw_min2( - v->v_startup_lines, - v->max_vstartup_lines[k]); + v->v_update_offset_pix =dcn_bw_ceil2(v->htotal[k] / 4.0, 1.0); + v->total_repeater_delay_time = v->max_inter_dcn_tile_repeaters * (2.0 / v->dppclk + 3.0 / v->dispclk); + v->v_update_width_pix = (14.0 / v->dcf_clk_deep_sleep + 12.0 / v->dppclk + v->total_repeater_delay_time) * v->pixel_clock[k]; + v->v_ready_offset_pix =dcn_bw_max2(150.0 / v->dppclk, v->total_repeater_delay_time + 20.0 / v->dcf_clk_deep_sleep + 10.0 / v->dppclk) * v->pixel_clock[k]; + v->t_setup = (v->v_update_offset_pix + v->v_update_width_pix + v->v_ready_offset_pix) / v->pixel_clock[k]; + v->v_startup[k] =dcn_bw_min2(v->v_startup_lines, v->max_vstartup_lines[k]); if (v->prefetch_mode == 0.0) { - v->t_wait = dcn_bw_max3( - v->dram_clock_change_latency - + v->urgent_latency, - v->sr_enter_plus_exit_time, - v->urgent_latency); - } else if (v->prefetch_mode == 1.0) { - v->t_wait = dcn_bw_max2( - v->sr_enter_plus_exit_time, - v->urgent_latency); - } else { + v->t_wait =dcn_bw_max3(v->dram_clock_change_latency + v->urgent_latency, v->sr_enter_plus_exit_time, v->urgent_latency); + } + else if (v->prefetch_mode == 1.0) { + v->t_wait =dcn_bw_max2(v->sr_enter_plus_exit_time, v->urgent_latency); + } + else { v->t_wait = v->urgent_latency; } - v->destination_lines_for_prefetch[k] = - dcn_bw_floor2( - 4.0 - * (v->v_startup[k] - - v->t_wait - / (v->htotal[k] - / v->pixel_clock[k]) - - (v->t_calc - + v->t_setup) - / (v->htotal[k] - / v->pixel_clock[k]) - - (v->dsty_after_scaler - + v->dstx_after_scaler - / v->htotal[k]) - + 0.125), - 1.0) / 4; + v->destination_lines_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->v_startup[k] - v->t_wait / (v->htotal[k] / v->pixel_clock[k]) - (v->t_calc + v->t_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dsty_after_scaler + v->dstx_after_scaler / v->htotal[k]) + 0.125), 1.0) / 4; if (v->destination_lines_for_prefetch[k] > 0.0) { - v->prefetch_bandwidth[k] = - (v->meta_pte_bytes_frame[k] - + 2.0 * v->meta_row_byte[k] - + 2.0 - * v->pixel_pte_bytes_per_row[k] - + v->prefetch_source_lines_y[k] - * v->swath_width_y[k] - * dcn_bw_ceil2( - v->byte_per_pixel_dety[k], - 1.0) - + v->prefetch_source_lines_c[k] - * v->swath_width_y[k] - / 2.0 - * dcn_bw_ceil2( - v->byte_per_pixel_detc[k], - 2.0)) - / (v->destination_lines_for_prefetch[k] - * v->htotal[k] - / v->pixel_clock[k]); - } else { + v->prefetch_bandwidth[k] = (v->meta_pte_bytes_frame[k] + 2.0 * v->meta_row_byte[k] + 2.0 * v->pixel_pte_bytes_per_row[k] + v->prefetch_source_lines_y[k] * v->swath_width_y[k] *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + v->prefetch_source_lines_c[k] * v->swath_width_y[k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0)) / (v->destination_lines_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]); + } + else { v->prefetch_bandwidth[k] = 999999.0; } } v->bandwidth_available_for_immediate_flip = v->return_bw; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->bandwidth_available_for_immediate_flip = - v->bandwidth_available_for_immediate_flip - - dcn_bw_max2( - v->read_bandwidth_plane_luma[k] - + v->read_bandwidth_plane_chroma[k], - v->prefetch_bandwidth[k]); + v->bandwidth_available_for_immediate_flip = v->bandwidth_available_for_immediate_flip -dcn_bw_max2(v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k], v->prefetch_bandwidth[k]); } v->tot_immediate_flip_bytes = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->immediate_flip_supported == dcn_bw_yes - && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] - != dcn_bw_yuv420_sub_10)) { - v->tot_immediate_flip_bytes = v->tot_immediate_flip_bytes - + v->meta_pte_bytes_frame[k] - + v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]; + if (v->immediate_flip_supported == dcn_bw_yes && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->tot_immediate_flip_bytes = v->tot_immediate_flip_bytes + v->meta_pte_bytes_frame[k] + v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]; } } v->max_rd_bandwidth = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) { - if (v->immediate_flip_supported == dcn_bw_yes - && (v->source_pixel_format[k] - != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] - != dcn_bw_yuv420_sub_10)) { - v->time_for_fetching_meta_pte = - dcn_bw_max5( - v->meta_pte_bytes_frame[k] - / v->prefetch_bandwidth[k], - v->meta_pte_bytes_frame[k] - * v->tot_immediate_flip_bytes - / (v->bandwidth_available_for_immediate_flip - * (v->meta_pte_bytes_frame[k] - + v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k])), - v->urgent_extra_latency, - v->urgent_latency, - v->htotal[k] - / v->pixel_clock[k] - / 4.0); - } else { - v->time_for_fetching_meta_pte = - dcn_bw_max3( - v->meta_pte_bytes_frame[k] - / v->prefetch_bandwidth[k], - v->urgent_extra_latency, - v->htotal[k] - / v->pixel_clock[k] - / 4.0); + if (v->immediate_flip_supported == dcn_bw_yes && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->time_for_fetching_meta_pte =dcn_bw_max5(v->meta_pte_bytes_frame[k] / v->prefetch_bandwidth[k], v->meta_pte_bytes_frame[k] * v->tot_immediate_flip_bytes / (v->bandwidth_available_for_immediate_flip * (v->meta_pte_bytes_frame[k] + v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k])), v->urgent_extra_latency, v->urgent_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); + } + else { + v->time_for_fetching_meta_pte =dcn_bw_max3(v->meta_pte_bytes_frame[k] / v->prefetch_bandwidth[k], v->urgent_extra_latency, v->htotal[k] / v->pixel_clock[k] / 4.0); } - } else { - v->time_for_fetching_meta_pte = v->htotal[k] - / v->pixel_clock[k] / 4.0; - } - v->destination_lines_to_request_vm_inv_blank[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_fetching_meta_pte - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; + } + else { + v->time_for_fetching_meta_pte = v->htotal[k] / v->pixel_clock[k] / 4.0; + } + v->destination_lines_to_request_vm_inv_blank[k] =dcn_bw_floor2(4.0 * (v->time_for_fetching_meta_pte / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; if ((v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes)) { - if (v->immediate_flip_supported == dcn_bw_yes - && (v->source_pixel_format[k] - != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] - != dcn_bw_yuv420_sub_10)) { - v->time_for_fetching_row_in_vblank = - dcn_bw_max5( - (v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]) - / v->prefetch_bandwidth[k], - (v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]) - * v->tot_immediate_flip_bytes - / (v->bandwidth_available_for_immediate_flip - * (v->meta_pte_bytes_frame[k] - + v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k])), - v->urgent_extra_latency, - 2.0 - * v->urgent_latency, - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_fetching_meta_pte); - } else { - v->time_for_fetching_row_in_vblank = - dcn_bw_max3( - (v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]) - / v->prefetch_bandwidth[k], - v->urgent_extra_latency, - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_fetching_meta_pte); + if (v->immediate_flip_supported == dcn_bw_yes && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->time_for_fetching_row_in_vblank =dcn_bw_max5((v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]) / v->prefetch_bandwidth[k], (v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]) * v->tot_immediate_flip_bytes / (v->bandwidth_available_for_immediate_flip * (v->meta_pte_bytes_frame[k] + v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k])), v->urgent_extra_latency, 2.0 * v->urgent_latency, v->htotal[k] / v->pixel_clock[k] - v->time_for_fetching_meta_pte); + } + else { + v->time_for_fetching_row_in_vblank =dcn_bw_max3((v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]) / v->prefetch_bandwidth[k], v->urgent_extra_latency, v->htotal[k] / v->pixel_clock[k] - v->time_for_fetching_meta_pte); } - } else { - v->time_for_fetching_row_in_vblank = - dcn_bw_max2( - v->urgent_extra_latency - - v->time_for_fetching_meta_pte, - v->htotal[k] - / v->pixel_clock[k] - - v->time_for_fetching_meta_pte); - } - v->destination_lines_to_request_row_in_vblank[k] = - dcn_bw_floor2( - 4.0 - * (v->time_for_fetching_row_in_vblank - / (v->htotal[k] - / v->pixel_clock[k]) - + 0.125), - 1.0) / 4; - v->lines_to_request_prefetch_pixel_data = - v->destination_lines_for_prefetch[k] - - v->destination_lines_to_request_vm_inv_blank[k] - - v->destination_lines_to_request_row_in_vblank[k]; + } + else { + v->time_for_fetching_row_in_vblank =dcn_bw_max2(v->urgent_extra_latency - v->time_for_fetching_meta_pte, v->htotal[k] / v->pixel_clock[k] - v->time_for_fetching_meta_pte); + } + v->destination_lines_to_request_row_in_vblank[k] =dcn_bw_floor2(4.0 * (v->time_for_fetching_row_in_vblank / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4; + v->lines_to_request_prefetch_pixel_data = v->destination_lines_for_prefetch[k] - v->destination_lines_to_request_vm_inv_blank[k] - v->destination_lines_to_request_row_in_vblank[k]; if (v->lines_to_request_prefetch_pixel_data > 0.0) { - v->v_ratio_prefetch_y[k] = v->prefetch_source_lines_y[k] - / v->lines_to_request_prefetch_pixel_data; + v->v_ratio_prefetch_y[k] = v->prefetch_source_lines_y[k] / v->lines_to_request_prefetch_pixel_data; if ((v->swath_height_y[k] > 4.0)) { - if (v->lines_to_request_prefetch_pixel_data - > (v->v_init_pre_fill_y[k] - 3.0) - / 2.0) { - v->v_ratio_prefetch_y[k] = - dcn_bw_max2( - v->v_ratio_prefetch_y[k], - v->max_num_swath_y[k] - * v->swath_height_y[k] - / (v->lines_to_request_prefetch_pixel_data - - (v->v_init_pre_fill_y[k] - - 3.0) - / 2.0)); - } else { + if (v->lines_to_request_prefetch_pixel_data > (v->v_init_pre_fill_y[k] - 3.0) / 2.0) { + v->v_ratio_prefetch_y[k] =dcn_bw_max2(v->v_ratio_prefetch_y[k], v->max_num_swath_y[k] * v->swath_height_y[k] / (v->lines_to_request_prefetch_pixel_data - (v->v_init_pre_fill_y[k] - 3.0) / 2.0)); + } + else { v->v_ratio_prefetch_y[k] = 999999.0; } } - } else { + } + else { v->v_ratio_prefetch_y[k] = 999999.0; } - v->v_ratio_prefetch_y[k] = dcn_bw_max2(v->v_ratio_prefetch_y[k], 1.0); + v->v_ratio_prefetch_y[k] =dcn_bw_max2(v->v_ratio_prefetch_y[k], 1.0); if (v->lines_to_request_prefetch_pixel_data > 0.0) { - v->v_ratio_prefetch_c[k] = v->prefetch_source_lines_c[k] - / v->lines_to_request_prefetch_pixel_data; + v->v_ratio_prefetch_c[k] = v->prefetch_source_lines_c[k] / v->lines_to_request_prefetch_pixel_data; if ((v->swath_height_c[k] > 4.0)) { - if (v->lines_to_request_prefetch_pixel_data - > (v->v_init_pre_fill_c[k] - 3.0) - / 2.0) { - v->v_ratio_prefetch_c[k] = - dcn_bw_max2( - v->v_ratio_prefetch_c[k], - v->max_num_swath_c[k] - * v->swath_height_c[k] - / (v->lines_to_request_prefetch_pixel_data - - (v->v_init_pre_fill_c[k] - - 3.0) - / 2.0)); - } else { + if (v->lines_to_request_prefetch_pixel_data > (v->v_init_pre_fill_c[k] - 3.0) / 2.0) { + v->v_ratio_prefetch_c[k] =dcn_bw_max2(v->v_ratio_prefetch_c[k], v->max_num_swath_c[k] * v->swath_height_c[k] / (v->lines_to_request_prefetch_pixel_data - (v->v_init_pre_fill_c[k] - 3.0) / 2.0)); + } + else { v->v_ratio_prefetch_c[k] = 999999.0; } } - } else { + } + else { v->v_ratio_prefetch_c[k] = 999999.0; } - v->v_ratio_prefetch_c[k] = dcn_bw_max2(v->v_ratio_prefetch_c[k], 1.0); + v->v_ratio_prefetch_c[k] =dcn_bw_max2(v->v_ratio_prefetch_c[k], 1.0); if (v->lines_to_request_prefetch_pixel_data > 0.0) { - v->required_prefetch_pix_data_bw = - v->dpp_per_plane[k] - * (v->prefetch_source_lines_y[k] - / v->lines_to_request_prefetch_pixel_data - * dcn_bw_ceil2( - v->byte_per_pixel_dety[k], - 1.0) - + v->prefetch_source_lines_c[k] - / v->lines_to_request_prefetch_pixel_data - * dcn_bw_ceil2( - v->byte_per_pixel_detc[k], - 2.0) - / 2.0) - * v->swath_width_y[k] - / (v->htotal[k] - / v->pixel_clock[k]); - } else { + v->required_prefetch_pix_data_bw = v->dpp_per_plane[k] * (v->prefetch_source_lines_y[k] / v->lines_to_request_prefetch_pixel_data *dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) + v->prefetch_source_lines_c[k] / v->lines_to_request_prefetch_pixel_data *dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / 2.0) * v->swath_width_y[k] / (v->htotal[k] / v->pixel_clock[k]); + } + else { v->required_prefetch_pix_data_bw = 999999.0; } - v->max_rd_bandwidth = - v->max_rd_bandwidth - + dcn_bw_max2( - v->read_bandwidth_plane_luma[k] - + v->read_bandwidth_plane_chroma[k], - v->required_prefetch_pix_data_bw); - if (v->immediate_flip_supported == dcn_bw_yes - && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 - && v->source_pixel_format[k] - != dcn_bw_yuv420_sub_10)) { - v->max_rd_bandwidth = - v->max_rd_bandwidth - + dcn_bw_max2( - v->meta_pte_bytes_frame[k] - / (v->destination_lines_to_request_vm_inv_blank[k] - * v->htotal[k] - / v->pixel_clock[k]), - (v->meta_row_byte[k] - + v->pixel_pte_bytes_per_row[k]) - / (v->destination_lines_to_request_row_in_vblank[k] - * v->htotal[k] - / v->pixel_clock[k])); - } - if (v->v_ratio_prefetch_y[k] > 4.0 - || v->v_ratio_prefetch_c[k] > 4.0) { + v->max_rd_bandwidth = v->max_rd_bandwidth +dcn_bw_max2(v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k], v->required_prefetch_pix_data_bw); + if (v->immediate_flip_supported == dcn_bw_yes && (v->source_pixel_format[k] != dcn_bw_yuv420_sub_8 && v->source_pixel_format[k] != dcn_bw_yuv420_sub_10)) { + v->max_rd_bandwidth = v->max_rd_bandwidth +dcn_bw_max2(v->meta_pte_bytes_frame[k] / (v->destination_lines_to_request_vm_inv_blank[k] * v->htotal[k] / v->pixel_clock[k]), (v->meta_row_byte[k] + v->pixel_pte_bytes_per_row[k]) / (v->destination_lines_to_request_row_in_vblank[k] * v->htotal[k] / v->pixel_clock[k])); + } + if (v->v_ratio_prefetch_y[k] > 4.0 || v->v_ratio_prefetch_c[k] > 4.0) { v->v_ratio_prefetch_more_than4 = dcn_bw_yes; } if (v->destination_lines_for_prefetch[k] < 2.0) { - v->destination_line_times_for_prefetch_less_than2 = - dcn_bw_yes; + v->destination_line_times_for_prefetch_less_than2 = dcn_bw_yes; } if (v->max_vstartup_lines[k] > v->v_startup_lines) { - if (v->required_prefetch_pix_data_bw - > (v->read_bandwidth_plane_luma[k] - + v->read_bandwidth_plane_chroma[k])) { - v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = - dcn_bw_no; + if (v->required_prefetch_pix_data_bw > (v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k])) { + v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw = dcn_bw_no; } - if (v->v_ratio_prefetch_y[k] > 4.0 - || v->v_ratio_prefetch_c[k] > 4.0) { - v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = - dcn_bw_yes; + if (v->v_ratio_prefetch_y[k] > 4.0 || v->v_ratio_prefetch_c[k] > 4.0) { + v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 = dcn_bw_yes; } if (v->destination_lines_for_prefetch[k] < 2.0) { - v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = - dcn_bw_yes; + v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 = dcn_bw_yes; } } } - if (v->max_rd_bandwidth <= v->return_bw - && v->v_ratio_prefetch_more_than4 == dcn_bw_no - && v->destination_line_times_for_prefetch_less_than2 - == dcn_bw_no) { + if (v->max_rd_bandwidth <= v->return_bw && v->v_ratio_prefetch_more_than4 == dcn_bw_no && v->destination_line_times_for_prefetch_less_than2 == dcn_bw_no) { v->prefetch_mode_supported = dcn_bw_yes; - } else { + } + else { v->prefetch_mode_supported = dcn_bw_no; } v->v_startup_lines = v->v_startup_lines + 1.0; - } while (!(v->prefetch_mode_supported == dcn_bw_yes - || (v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw - == dcn_bw_yes - && v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 - == dcn_bw_no - && v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 - == dcn_bw_no))); + } while (!(v->prefetch_mode_supported == dcn_bw_yes || (v->planes_with_room_to_increase_vstartup_prefetch_bw_less_than_active_bw == dcn_bw_yes && v->planes_with_room_to_increase_vstartup_vratio_prefetch_more_than4 == dcn_bw_no && v->planes_with_room_to_increase_vstartup_destination_line_times_for_prefetch_less_than2 == dcn_bw_no))); v->next_prefetch_mode = v->next_prefetch_mode + 1.0; } while (!(v->prefetch_mode_supported == dcn_bw_yes || v->prefetch_mode == 2.0)); for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->v_ratio_prefetch_y[k] <= 1.0) { - v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] - * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; - } else { - v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] - / v->pscl_throughput[k] / v->dppclk; + v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } + else { + v->display_pipe_line_delivery_time_luma_prefetch[k] = v->swath_width_y[k] / v->pscl_throughput[k] / v->dppclk; } if (v->byte_per_pixel_detc[k] == 0.0) { v->display_pipe_line_delivery_time_chroma_prefetch[k] = 0.0; - } else { + } + else { if (v->v_ratio_prefetch_c[k] <= 1.0) { - v->display_pipe_line_delivery_time_chroma_prefetch[k] = - v->swath_width_y[k] * v->dpp_per_plane[k] - / v->h_ratio[k] / v->pixel_clock[k]; - } else { - v->display_pipe_line_delivery_time_chroma_prefetch[k] = - v->swath_width_y[k] / v->pscl_throughput[k] - / v->dppclk; + v->display_pipe_line_delivery_time_chroma_prefetch[k] = v->swath_width_y[k] * v->dpp_per_plane[k] / v->h_ratio[k] / v->pixel_clock[k]; + } + else { + v->display_pipe_line_delivery_time_chroma_prefetch[k] = v->swath_width_y[k] / v->pscl_throughput[k] / v->dppclk; } } } @@ -3413,19 +1758,14 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan if (v->prefetch_mode == 0.0) { v->allow_dram_clock_change_during_vblank[k] = dcn_bw_yes; v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_yes; - v->min_ttuv_blank[k] = v->t_calc - + dcn_bw_max3( - v->dram_clock_change_watermark, - v->stutter_enter_plus_exit_watermark, - v->urgent_watermark); - } else if (v->prefetch_mode == 1.0) { + v->min_ttuv_blank[k] = v->t_calc +dcn_bw_max3(v->dram_clock_change_watermark, v->stutter_enter_plus_exit_watermark, v->urgent_watermark); + } + else if (v->prefetch_mode == 1.0) { v->allow_dram_clock_change_during_vblank[k] = dcn_bw_no; v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_yes; - v->min_ttuv_blank[k] = v->t_calc - + dcn_bw_max2( - v->stutter_enter_plus_exit_watermark, - v->urgent_watermark); - } else { + v->min_ttuv_blank[k] = v->t_calc +dcn_bw_max2(v->stutter_enter_plus_exit_watermark, v->urgent_watermark); + } + else { v->allow_dram_clock_change_during_vblank[k] = dcn_bw_no; v->allow_dram_self_refresh_during_vblank[k] = dcn_bw_no; v->min_ttuv_blank[k] = v->t_calc + v->urgent_watermark; @@ -3438,131 +1778,61 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->active_dp_ps = v->active_dp_ps + v->dpp_per_plane[k]; } for (k = 0; k <= v->number_of_active_planes - 1; k++) { - v->lb_latency_hiding_source_lines_y = - dcn_bw_min2( - v->max_line_buffer_lines, - dcn_bw_floor2( - v->line_buffer_size - / v->lb_bit_per_pixel[k] - / (v->swath_width_y[k] - / dcn_bw_max2( - v->h_ratio[k], - 1.0)), - 1.0)) - (v->vtaps[k] - 1.0); - v->lb_latency_hiding_source_lines_c = - dcn_bw_min2( - v->max_line_buffer_lines, - dcn_bw_floor2( - v->line_buffer_size - / v->lb_bit_per_pixel[k] - / (v->swath_width_y[k] - / 2.0 - / dcn_bw_max2( - v->h_ratio[k] - / 2.0, - 1.0)), - 1.0)) - (v->vta_pschroma[k] - 1.0); - v->effective_lb_latency_hiding_y = v->lb_latency_hiding_source_lines_y - / v->v_ratio[k] * (v->htotal[k] / v->pixel_clock[k]); - v->effective_lb_latency_hiding_c = v->lb_latency_hiding_source_lines_c - / (v->v_ratio[k] / 2.0) * (v->htotal[k] / v->pixel_clock[k]); + v->lb_latency_hiding_source_lines_y =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_y[k] /dcn_bw_max2(v->h_ratio[k], 1.0)), 1.0)) - (v->vtaps[k] - 1.0); + v->lb_latency_hiding_source_lines_c =dcn_bw_min2(v->max_line_buffer_lines,dcn_bw_floor2(v->line_buffer_size / v->lb_bit_per_pixel[k] / (v->swath_width_y[k] / 2.0 /dcn_bw_max2(v->h_ratio[k] / 2.0, 1.0)), 1.0)) - (v->vta_pschroma[k] - 1.0); + v->effective_lb_latency_hiding_y = v->lb_latency_hiding_source_lines_y / v->v_ratio[k] * (v->htotal[k] / v->pixel_clock[k]); + v->effective_lb_latency_hiding_c = v->lb_latency_hiding_source_lines_c / (v->v_ratio[k] / 2.0) * (v->htotal[k] / v->pixel_clock[k]); if (v->swath_width_y[k] > 2.0 * v->dpp_output_buffer_pixels) { - v->dpp_output_buffer_lines_y = v->dpp_output_buffer_pixels - / v->swath_width_y[k]; - } else if (v->swath_width_y[k] > v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_y = v->dpp_output_buffer_pixels / v->swath_width_y[k]; + } + else if (v->swath_width_y[k] > v->dpp_output_buffer_pixels) { v->dpp_output_buffer_lines_y = 0.5; - } else { + } + else { v->dpp_output_buffer_lines_y = 1.0; } if (v->swath_width_y[k] / 2.0 > 2.0 * v->dpp_output_buffer_pixels) { - v->dpp_output_buffer_lines_c = v->dpp_output_buffer_pixels - / (v->swath_width_y[k] / 2.0); - } else if (v->swath_width_y[k] / 2.0 > v->dpp_output_buffer_pixels) { + v->dpp_output_buffer_lines_c = v->dpp_output_buffer_pixels / (v->swath_width_y[k] / 2.0); + } + else if (v->swath_width_y[k] / 2.0 > v->dpp_output_buffer_pixels) { v->dpp_output_buffer_lines_c = 0.5; - } else { + } + else { v->dpp_output_buffer_lines_c = 1.0; } - v->dppopp_buffering_y = (v->htotal[k] / v->pixel_clock[k]) - * (v->dpp_output_buffer_lines_y + v->opp_output_buffer_lines); - v->max_det_buffering_time_y = v->full_det_buffering_time_y[k] - + (v->lines_in_dety[k] - v->lines_in_dety_rounded_down_to_swath[k]) - / v->swath_height_y[k] - * (v->htotal[k] / v->pixel_clock[k]); - v->active_dram_clock_change_latency_margin_y = v->dppopp_buffering_y - + v->effective_lb_latency_hiding_y + v->max_det_buffering_time_y - - v->dram_clock_change_watermark; + v->dppopp_buffering_y = (v->htotal[k] / v->pixel_clock[k]) * (v->dpp_output_buffer_lines_y + v->opp_output_buffer_lines); + v->max_det_buffering_time_y = v->full_det_buffering_time_y[k] + (v->lines_in_dety[k] - v->lines_in_dety_rounded_down_to_swath[k]) / v->swath_height_y[k] * (v->htotal[k] / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_y = v->dppopp_buffering_y + v->effective_lb_latency_hiding_y + v->max_det_buffering_time_y - v->dram_clock_change_watermark; if (v->active_dp_ps > 1.0) { - v->active_dram_clock_change_latency_margin_y = - v->active_dram_clock_change_latency_margin_y - - (1.0 - 1.0 / (v->active_dp_ps - 1.0)) - * v->swath_height_y[k] - * (v->htotal[k] - / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_y = v->active_dram_clock_change_latency_margin_y - (1.0 - 1.0 / (v->active_dp_ps - 1.0)) * v->swath_height_y[k] * (v->htotal[k] / v->pixel_clock[k]); } if (v->byte_per_pixel_detc[k] > 0.0) { - v->dppopp_buffering_c = - (v->htotal[k] / v->pixel_clock[k]) - * (v->dpp_output_buffer_lines_c - + v->opp_output_buffer_lines); - v->max_det_buffering_time_c = v->full_det_buffering_time_c[k] - + (v->lines_in_detc[k] - - v->lines_in_detc_rounded_down_to_swath[k]) - / v->swath_height_c[k] - * (v->htotal[k] / v->pixel_clock[k]); - v->active_dram_clock_change_latency_margin_c = v->dppopp_buffering_c - + v->effective_lb_latency_hiding_c - + v->max_det_buffering_time_c - - v->dram_clock_change_watermark; + v->dppopp_buffering_c = (v->htotal[k] / v->pixel_clock[k]) * (v->dpp_output_buffer_lines_c + v->opp_output_buffer_lines); + v->max_det_buffering_time_c = v->full_det_buffering_time_c[k] + (v->lines_in_detc[k] - v->lines_in_detc_rounded_down_to_swath[k]) / v->swath_height_c[k] * (v->htotal[k] / v->pixel_clock[k]); + v->active_dram_clock_change_latency_margin_c = v->dppopp_buffering_c + v->effective_lb_latency_hiding_c + v->max_det_buffering_time_c - v->dram_clock_change_watermark; if (v->active_dp_ps > 1.0) { - v->active_dram_clock_change_latency_margin_c = - v->active_dram_clock_change_latency_margin_c - - (1.0 - - 1.0 - / (v->active_dp_ps - - 1.0)) - * v->swath_height_c[k] - * (v->htotal[k] - / v->pixel_clock[k]); - } - v->active_dram_clock_change_latency_margin[k] = dcn_bw_min2( - v->active_dram_clock_change_latency_margin_y, - v->active_dram_clock_change_latency_margin_c); - } else { - v->active_dram_clock_change_latency_margin[k] = - v->active_dram_clock_change_latency_margin_y; + v->active_dram_clock_change_latency_margin_c = v->active_dram_clock_change_latency_margin_c - (1.0 - 1.0 / (v->active_dp_ps - 1.0)) * v->swath_height_c[k] * (v->htotal[k] / v->pixel_clock[k]); + } + v->active_dram_clock_change_latency_margin[k] =dcn_bw_min2(v->active_dram_clock_change_latency_margin_y, v->active_dram_clock_change_latency_margin_c); + } + else { + v->active_dram_clock_change_latency_margin[k] = v->active_dram_clock_change_latency_margin_y; } if (v->output_format[k] == dcn_bw_444) { - v->writeback_dram_clock_change_latency_margin = - (v->writeback_luma_buffer_size - + v->writeback_chroma_buffer_size) * 1024.0 - / (v->scaler_rec_out_width[k] - / (v->htotal[k] - / v->pixel_clock[k]) - * 4.0) - - v->writeback_dram_clock_change_watermark; - } else { - v->writeback_dram_clock_change_latency_margin = dcn_bw_min2( - v->writeback_luma_buffer_size, - 2.0 * v->writeback_chroma_buffer_size) * 1024.0 - / (v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k])) - - v->writeback_dram_clock_change_watermark; + v->writeback_dram_clock_change_latency_margin = (v->writeback_luma_buffer_size + v->writeback_chroma_buffer_size) * 1024.0 / (v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 4.0) - v->writeback_dram_clock_change_watermark; + } + else { + v->writeback_dram_clock_change_latency_margin =dcn_bw_min2(v->writeback_luma_buffer_size, 2.0 * v->writeback_chroma_buffer_size) * 1024.0 / (v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k])) - v->writeback_dram_clock_change_watermark; } if (v->output[k] == dcn_bw_writeback) { - v->active_dram_clock_change_latency_margin[k] = dcn_bw_min2( - v->active_dram_clock_change_latency_margin[k], - v->writeback_dram_clock_change_latency_margin); + v->active_dram_clock_change_latency_margin[k] =dcn_bw_min2(v->active_dram_clock_change_latency_margin[k], v->writeback_dram_clock_change_latency_margin); } } for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->allow_dram_clock_change_during_vblank[k] == dcn_bw_yes) { - v->v_blank_dram_clock_change_latency_margin[k] = (v->vtotal[k] - - v->scaler_recout_height[k]) - * (v->htotal[k] / v->pixel_clock[k]) - - dcn_bw_max2( - v->dram_clock_change_watermark, - v->writeback_dram_clock_change_watermark); - } else { + v->v_blank_dram_clock_change_latency_margin[k] = (v->vtotal[k] - v->scaler_recout_height[k]) * (v->htotal[k] / v->pixel_clock[k]) -dcn_bw_max2(v->dram_clock_change_watermark, v->writeback_dram_clock_change_watermark); + } + else { v->v_blank_dram_clock_change_latency_margin[k] = 0.0; } } @@ -3570,45 +1840,37 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->v_blank_of_min_active_dram_clock_change_margin = 999999.0; v->second_min_active_dram_clock_change_margin = 999999.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->active_dram_clock_change_latency_margin[k] - < v->min_active_dram_clock_change_margin) { - v->second_min_active_dram_clock_change_margin = - v->min_active_dram_clock_change_margin; - v->min_active_dram_clock_change_margin = - v->active_dram_clock_change_latency_margin[k]; - v->v_blank_of_min_active_dram_clock_change_margin = - v->v_blank_dram_clock_change_latency_margin[k]; - } else if (v->active_dram_clock_change_latency_margin[k] - < v->second_min_active_dram_clock_change_margin) { - v->second_min_active_dram_clock_change_margin = - v->active_dram_clock_change_latency_margin[k]; + if (v->active_dram_clock_change_latency_margin[k] < v->min_active_dram_clock_change_margin) { + v->second_min_active_dram_clock_change_margin = v->min_active_dram_clock_change_margin; + v->min_active_dram_clock_change_margin = v->active_dram_clock_change_latency_margin[k]; + v->v_blank_of_min_active_dram_clock_change_margin = v->v_blank_dram_clock_change_latency_margin[k]; + } + else if (v->active_dram_clock_change_latency_margin[k] < v->second_min_active_dram_clock_change_margin) { + v->second_min_active_dram_clock_change_margin = v->active_dram_clock_change_latency_margin[k]; } } v->min_vblank_dram_clock_change_margin = 999999.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if (v->min_vblank_dram_clock_change_margin - > v->v_blank_dram_clock_change_latency_margin[k]) { - v->min_vblank_dram_clock_change_margin = - v->v_blank_dram_clock_change_latency_margin[k]; + if (v->min_vblank_dram_clock_change_margin > v->v_blank_dram_clock_change_latency_margin[k]) { + v->min_vblank_dram_clock_change_margin = v->v_blank_dram_clock_change_latency_margin[k]; } } if (v->synchronized_vblank == dcn_bw_yes || v->number_of_active_planes == 1) { - v->dram_clock_change_margin = dcn_bw_max2( - v->min_active_dram_clock_change_margin, - v->min_vblank_dram_clock_change_margin); - } else if (v->v_blank_of_min_active_dram_clock_change_margin - > v->min_active_dram_clock_change_margin) { - v->dram_clock_change_margin = dcn_bw_min2( - v->second_min_active_dram_clock_change_margin, - v->v_blank_of_min_active_dram_clock_change_margin); - } else { + v->dram_clock_change_margin =dcn_bw_max2(v->min_active_dram_clock_change_margin, v->min_vblank_dram_clock_change_margin); + } + else if (v->v_blank_of_min_active_dram_clock_change_margin > v->min_active_dram_clock_change_margin) { + v->dram_clock_change_margin =dcn_bw_min2(v->second_min_active_dram_clock_change_margin, v->v_blank_of_min_active_dram_clock_change_margin); + } + else { v->dram_clock_change_margin = v->min_active_dram_clock_change_margin; } if (v->min_active_dram_clock_change_margin > 0.0) { v->dram_clock_change_support = dcn_bw_supported_in_v_active; - } else if (v->dram_clock_change_margin > 0.0) { + } + else if (v->dram_clock_change_margin > 0.0) { v->dram_clock_change_support = dcn_bw_supported_in_v_blank; - } else { + } + else { v->dram_clock_change_support = dcn_bw_not_supported; } /*maximum bandwidth used*/ @@ -3616,13 +1878,10 @@ void dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performan v->wr_bandwidth = 0.0; for (k = 0; k <= v->number_of_active_planes - 1; k++) { if (v->output[k] == dcn_bw_writeback && v->output_format[k] == dcn_bw_444) { - v->wr_bandwidth = v->wr_bandwidth - + v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k]) * 4.0; - } else if (v->output[k] == dcn_bw_writeback) { - v->wr_bandwidth = v->wr_bandwidth - + v->scaler_rec_out_width[k] - / (v->htotal[k] / v->pixel_clock[k]) * 1.5; + v->wr_bandwidth = v->wr_bandwidth + v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 4.0; + } + else if (v->output[k] == dcn_bw_writeback) { + v->wr_bandwidth = v->wr_bandwidth + v->scaler_rec_out_width[k] / (v->htotal[k] / v->pixel_clock[k]) * 1.5; } } v->max_used_bw = v->max_rd_bandwidth + v->wr_bandwidth; -- GitLab From f0129a537b52da851abd26f8296f3ffd1e5dc424 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 21 Jun 2017 15:44:23 -0400 Subject: [PATCH 0562/2898] drm/amd/display: Refine globallock. Switch to wait_for_completion_interruptible_timeout wait since the lock is called from IOCTL context and can be interrupted by a signal. Global lock function might return EDEADLK or EINTR which is not an error and just singals to user mode to restart the call. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 7e0e6b2f22f6..0b7786d11995 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2842,7 +2842,7 @@ static uint32_t remove_from_val_sets( * Grabs all modesetting locks to serialize against any blocking commits, * Waits for completion of all non blocking commits. */ -static void do_aquire_global_lock( +static int do_aquire_global_lock( struct drm_device *dev, struct drm_atomic_state *state) { @@ -2854,7 +2854,9 @@ static void do_aquire_global_lock( * ensure that when the framework release it the * extra locks we are locking here will get released to */ - drm_modeset_lock_all_ctx(dev, state->acquire_ctx); + ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx); + if (ret) + return ret; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { spin_lock(&crtc->commit_lock); @@ -2870,15 +2872,20 @@ static void do_aquire_global_lock( /* Make sure all pending HW programming completed and * page flips done */ - ret = wait_for_completion_timeout(&commit->hw_done, - 10*HZ); - ret = wait_for_completion_timeout(&commit->flip_done, - 10*HZ); + ret = wait_for_completion_interruptible_timeout(&commit->hw_done, 10*HZ); + + if (ret > 0) + ret = wait_for_completion_interruptible_timeout( + &commit->flip_done, 10*HZ); + if (ret == 0) - DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n", - crtc->base.id, crtc->name); + DRM_ERROR("[CRTC:%d:%s] cleanup_done or flip_done " + "timed out\n", crtc->base.id, crtc->name); + drm_crtc_commit_put(commit); } + + return ret < 0 ? ret : 0; } int amdgpu_dm_atomic_check(struct drm_device *dev, @@ -3145,7 +3152,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * synchronization events. */ if (aquire_global_lock) - do_aquire_global_lock(dev, state); + ret = do_aquire_global_lock(dev, state); } @@ -3161,8 +3168,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for (i = 0; i < new_stream_count; i++) dc_stream_release(new_streams[i]); - if (ret != 0) - DRM_ERROR("Atomic check failed.\n"); + if (ret != 0) { + if (ret == -EDEADLK) + DRM_DEBUG_KMS("Atomic check stopped due to to deadlock, retrying.\n"); + else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) + DRM_DEBUG_KMS("Atomic check stopped due to to signal, retrying.\n"); + else + DRM_ERROR("Atomic check failed.\n"); + } return ret; } -- GitLab From afa80d64d20ac13528c261e1233ac3982609fd2f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 21 Jun 2017 17:27:59 -0400 Subject: [PATCH 0563/2898] drm/amd/display: fix bw_calc_auto translation error The compiler was warning about conditions that will never evaluate to true. The problem was that the VBA translater didn't translate the conditions correctly. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index bb2f8ad6a988..fb5d8db33a82 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -128,7 +128,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->source_format_pixel_and_scan_support = dcn_bw_yes; for (k = 0; k <= v->number_of_active_planes - 1; k++) { - if ((v->source_surface_mode[k] == dcn_bw_sw_linear && !v->source_scan[k] == dcn_bw_hor) || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_var_d || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) && !v->source_pixel_format[k] == dcn_bw_rgb_sub_64)) { + if ((v->source_surface_mode[k] == dcn_bw_sw_linear && v->source_scan[k] != dcn_bw_hor) || ((v->source_surface_mode[k] == dcn_bw_sw_4_kb_d || v->source_surface_mode[k] == dcn_bw_sw_4_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_t || v->source_surface_mode[k] == dcn_bw_sw_64_kb_d_x || v->source_surface_mode[k] == dcn_bw_sw_var_d || v->source_surface_mode[k] == dcn_bw_sw_var_d_x) && v->source_pixel_format[k] != dcn_bw_rgb_sub_64)) { v->source_format_pixel_and_scan_support = dcn_bw_no; } } -- GitLab From 92f3ac403d132400b7147bb4262fea4ad254aa3d Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Fri, 16 Jun 2017 15:59:17 -0400 Subject: [PATCH 0564/2898] drm/amd/display: Workaround IGT multiplane restriction IGT currently does not properly commit changes on planes with multiple possible CRTC's. Set one valid CRTC for each plane for now, plus one underlay plane on Carizzo and Stoney that is valid for all CRTCs. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 98e0dbe2a4de..f018de2e7dfe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1189,6 +1189,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) struct amdgpu_encoder *aencoder = NULL; struct amdgpu_mode_info *mode_info = &adev->mode_info; uint32_t link_cnt; + unsigned long possible_crtcs; link_cnt = dm->dc->caps.max_links; if (amdgpu_dm_mode_config_init(dm->adev)) { @@ -1204,7 +1205,18 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_planes; } mode_info->planes[i]->base.type = mode_info->plane_type[i]; - if (amdgpu_dm_plane_init(dm, mode_info->planes[i], 0xff)) { + + /* + * HACK: IGT tests expect that each plane can only have one + * one possible CRTC. For now, set one CRTC for each + * plane that is not an underlay, but still allow multiple + * CRTCs for underlay planes. + */ + possible_crtcs = 1 << i; + if (i >= dm->dc->caps.max_streams) + possible_crtcs = 0xff; + + if (amdgpu_dm_plane_init(dm, mode_info->planes[i], possible_crtcs)) { DRM_ERROR("KMS: Failed to initialize plane\n"); goto fail_free_planes; } -- GitLab From 4c0732bf7f37f488a37111051ebca388135bf7b5 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 22 Jun 2017 11:45:13 -0400 Subject: [PATCH 0565/2898] drm/amd/display: Global lock typos fix. Fix typos. Signed-off-by: Andrey Grodzovsky Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0b7786d11995..6f08fab1cce7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2879,7 +2879,7 @@ static int do_aquire_global_lock( &commit->flip_done, 10*HZ); if (ret == 0) - DRM_ERROR("[CRTC:%d:%s] cleanup_done or flip_done " + DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done " "timed out\n", crtc->base.id, crtc->name); drm_crtc_commit_put(commit); @@ -3170,9 +3170,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret != 0) { if (ret == -EDEADLK) - DRM_DEBUG_KMS("Atomic check stopped due to to deadlock, retrying.\n"); + DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_KMS("Atomic check stopped due to to signal, retrying.\n"); + DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); else DRM_ERROR("Atomic check failed.\n"); } -- GitLab From a95e7d737e1bc20eb311548f4e307e2155c5ca64 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 23 Jun 2017 13:56:55 -0400 Subject: [PATCH 0566/2898] drm/amd/display: Disable pipe split. Signed-off-by: Yongqiang Sun Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index c7840e0e3ae5..eebaffca8e75 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -443,7 +443,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, - .disable_pipe_split = false + .disable_pipe_split = true #endif }; -- GitLab From 866294f80582e252913c72b5e0f1792f6133424d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 21 Jun 2017 16:48:06 -0400 Subject: [PATCH 0567/2898] drm/amd/display: Don't program scaler if we have no surface If we don't have a surface in dc_commit_streams scl_data won't get populated in resource_build_scaling_params_for_context. In this case we shouldn't attempt to program the scaler. Signed-off-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a83d260cda45..0bab85b27a85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1099,10 +1099,12 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; /* program_scaler and allocate_mem_input are not new asic */ - if (!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data, - &pipe_ctx->scl_data, - sizeof(struct scaler_data)) != 0) + if ((!pipe_ctx_old || + memcmp(&pipe_ctx_old->scl_data, &pipe_ctx->scl_data, + sizeof(struct scaler_data)) != 0) && + pipe_ctx->surface) { program_scaler(dc, pipe_ctx); + } /* mst support - use total stream count */ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- GitLab From e5f2038ef12cf5606ec3d7c79e2539cafcb409dd Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Sat, 24 Jun 2017 16:01:37 -0400 Subject: [PATCH 0568/2898] drm/amd/display: w/a no color space info for HDMI when build AVI Signed-off-by: Charlene Liu Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 90eb839f5414..f0183d5f0d0d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1605,6 +1605,9 @@ static void set_avi_info_frame( union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; color_space = pipe_ctx->stream->public.output_color_space; + if (color_space == COLOR_SPACE_UNKNOWN) + color_space = (stream->public.timing.pixel_encoding == PIXEL_ENCODING_RGB)? + COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; /* Initialize header */ hdmi_info->bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; -- GitLab From 2782488ae6c0b53d57435aa6dc358e61550393d2 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 27 Jun 2017 10:02:48 -0400 Subject: [PATCH 0569/2898] drm/amd/display: Clean up unused function. Signed-off-by: Andrey Grodzovsky Reviewed-by: Leo Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 190905e08c38..2d34f9bb5d47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -450,12 +450,6 @@ struct dm_plane_state { struct dc_surface* dc_surface; }; -static inline struct dm_plane_state * -to_amdgpu_plane_state(struct drm_plane_state *state) -{ - return container_of(state, struct dm_plane_state, base); -} - struct amdgpu_plane { struct drm_plane base; enum drm_plane_type plane_type; -- GitLab From cf5a4c11a1561db5c31a2783611aa6d5dbb67225 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 28 Jun 2017 11:03:11 -0400 Subject: [PATCH 0570/2898] drm/amd/display: Move dm_plane_state definition to DAL header. Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 8 -------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 6 ++++++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 2d34f9bb5d47..2bb2fc2a6566 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -442,14 +442,6 @@ struct amdgpu_crtc { struct drm_pending_vblank_event *event; }; -/* TODO rename to dc_plane_state */ -struct dc_surface; - -struct dm_plane_state { - struct drm_plane_state base; - struct dc_surface* dc_surface; -}; - struct amdgpu_plane { struct drm_plane base; enum drm_plane_type plane_type; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index b69c86826b1a..6411dd1819dd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -33,6 +33,12 @@ struct amdgpu_display_manager; struct dc_validation_set; struct dc_surface; +struct dm_plane_state { + struct drm_plane_state base; + struct dc_surface *dc_surface; +}; + + /*TODO Jodan Hersen use the one in amdgpu_dm*/ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, -- GitLab From d7ec53d9dd0086644aa97d22463976b04b51307e Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 4 Jul 2017 13:28:57 -0400 Subject: [PATCH 0571/2898] drm/amd/display: Move kms_atomic support flag to dm_early_init. Signed-off-by: Andrey Grodzovsky Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ---- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index a350fc9b2a70..2368792b7d67 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2071,10 +2071,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->audio_endpt_rreg = &amdgpu_block_invalid_rreg; adev->audio_endpt_wreg = &amdgpu_block_invalid_wreg; - if (amdgpu_device_has_dc_support(adev)) - adev->ddev->driver->driver_features |= DRIVER_ATOMIC; - - DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n", amdgpu_asic_name[adev->asic_type], pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device, pdev->revision); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f018de2e7dfe..8062f8c18114 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1421,6 +1421,7 @@ static int dm_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + adev->ddev->driver->driver_features |= DRIVER_ATOMIC; amdgpu_dm_set_irq_funcs(adev); switch (adev->asic_type) { -- GitLab From a67297d4c8d0bfac39a0fa166e98dcf54db1d7c2 Mon Sep 17 00:00:00 2001 From: Xiaojie Yuan Date: Tue, 4 Jul 2017 14:21:58 +0800 Subject: [PATCH 0572/2898] drm/amd/display: Fix misuse of plane state destroy helper drm_plane_state is subclassed by dm_plane_state, so atomic driver should use __drm_atomic_helper_plane_destroy_state() to destroy a state. drm_atomic_helper_plane_destroy_state() frees drm_plane_state which is allocated inside dm_plane_state, this is problematic. Fixes: 95ae03a ("drm/amd/display: Create dm_plane_state.") Signed-off-by: Xiaojie Yuan Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 6f08fab1cce7..64cb635b4137 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1431,7 +1431,8 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, dc_surface_release(dc_surface); } - drm_atomic_helper_plane_destroy_state(plane, state); + __drm_atomic_helper_plane_destroy_state(state); + kfree(dm_plane_state); } static const struct drm_plane_funcs dm_plane_funcs = { -- GitLab From 061d34994597284b4228b7468762772fbdbcfa4c Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Mon, 26 Jun 2017 13:02:30 -0400 Subject: [PATCH 0573/2898] drm/amd/display: RV stereo support Fix moving directly from frame packed to frame sequential mode: disable OTG_3D_STRUCTURE_EN if the stereo mode is not frame packed. Signed-off-by: Ken Chalmers Reviewed-by: Vitaly Prosyak Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 83efbec77357..58fb29ff5677 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -1082,11 +1082,11 @@ static void dcn10_enable_stereo(struct timing_generator *tg, REG_UPDATE(OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); - if (flags->PROGRAM_STEREO && flags->FRAME_PACKED) + if (flags->PROGRAM_STEREO) REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL, - OTG_3D_STRUCTURE_EN, 1, - OTG_3D_STRUCTURE_V_UPDATE_MODE, 1, - OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1); + OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED, + OTG_3D_STRUCTURE_V_UPDATE_MODE, flags->FRAME_PACKED, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); } -- GitLab From e29088b2932a11db6155212ca19c75029bc137aa Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 25 Jul 2017 18:00:44 -0400 Subject: [PATCH 0574/2898] drm/amd/display: Move drm_get_vblank from legacy code Previously, we assumed that allow_modeset=false => page flip. This assumption breaks when an atomic commit is submitted with allow_modeset set to false, since the legacy flip code is never called (the legacy code grabs the vblank reference). Fix: Move drm_vblank_get() from amdgpu_atomic_helper_page_flip() to amdgpu_dm_commit_surfaces(). Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 64cb635b4137..0978fe3e5663 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2383,8 +2383,6 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, if (!con_state) continue; - - add_surface(dm->dc, crtc, plane, &dc_surfaces_constructed[planes_count]); if (dc_surfaces_constructed[planes_count] == NULL) { @@ -2403,6 +2401,10 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? false : true; + /* TODO: Needs rework for multiplane flip */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + drm_crtc_vblank_get(crtc); + amdgpu_dm_do_flip( crtc, fb, -- GitLab From b3663f705a522b7807a1916c94a24448c6a40abc Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 27 Jun 2017 11:12:37 -0400 Subject: [PATCH 0575/2898] drm/amd/display: Make mode_config_funcs const Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8062f8c18114..353165c6da1e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -634,8 +634,7 @@ const struct amdgpu_ip_block_version dm_ip_block = .funcs = &amdgpu_dm_funcs, }; -/* TODO: it is temporary non-const, should fixed later */ -static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { +static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, -- GitLab From ba6bf832b25ca7369ed3d4c0b0651bb43c9e644a Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 27 Jun 2017 17:24:00 -0400 Subject: [PATCH 0576/2898] drm/amd/display: Create dm_crtc_state stubs. These stubs are initial only since we need to flatten DC objects (steran at least) to implement deep copy. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 74 ++++++++++++++++++- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 10 +++ 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0978fe3e5663..3711176bd070 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -960,15 +960,83 @@ void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) kfree(crtc); } +static void dm_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct dm_crtc_state *cur = to_dm_crtc_state(state); + + if (cur->dc_stream) { + /* TODO Destroy dc_stream objects are stream object is flattened */ + dm_free(cur->dc_stream); + } else + WARN_ON(1); + + __drm_atomic_helper_crtc_destroy_state(state); + + + kfree(state); +} + +static void dm_crtc_reset_state(struct drm_crtc *crtc) +{ + struct dm_crtc_state *state; + + if (crtc->state) + dm_crtc_destroy_state(crtc, crtc->state); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (WARN_ON(!state)) + return; + + + crtc->state = &state->base; + crtc->state->crtc = crtc; + + state->dc_stream = dm_alloc(sizeof(*state->dc_stream)); + WARN_ON(!state->dc_stream); +} + +static struct drm_crtc_state * +dm_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct dm_crtc_state *state, *cur; + struct dc_stream *dc_stream; + + if (WARN_ON(!crtc->state)) + return NULL; + + cur = to_dm_crtc_state(crtc->state); + if (WARN_ON(!cur->dc_stream)) + return NULL; + + dc_stream = dm_alloc(sizeof(*dc_stream)); + if (WARN_ON(!dc_stream)) + return NULL; + + state = dm_alloc(sizeof(*state)); + if (WARN_ON(!state)) { + dm_free(dc_stream); + return NULL; + } + + __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); + + state->dc_stream = dc_stream; + + /* TODO Duplicate dc_stream after objects are stream object is flattened */ + + return &state->base; +} + /* Implemented only the options currently availible for the driver */ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { - .reset = drm_atomic_helper_crtc_reset, + .reset = dm_crtc_reset_state, .destroy = amdgpu_dm_crtc_destroy, .gamma_set = drm_atomic_helper_legacy_gamma_set, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .atomic_duplicate_state = dm_crtc_duplicate_state, + .atomic_destroy_state = dm_crtc_destroy_state, }; static enum drm_connector_status diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 6411dd1819dd..109172576499 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -32,6 +32,16 @@ struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; struct dc_surface; +/* TODO rename to dc_stream_state */ +struct dc_stream; + + +struct dm_crtc_state { + struct drm_crtc_state base; + struct dc_stream *dc_stream; +}; + +#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) struct dm_plane_state { struct drm_plane_state base; -- GitLab From f71f2772cb001d087e260c96f46d1fde022d2e03 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Mon, 26 Jun 2017 16:47:27 -0400 Subject: [PATCH 0577/2898] drm/amd/display: Add clock info struct Signed-off-by: Corbin McElhanney Reviewed-by: Logatharshan Thothiralingam Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services_types.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index b28304531d8a..4c04ec587308 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -271,4 +271,10 @@ struct dm_pp_static_clock_info { enum dm_pp_clocks_state max_clocks_state; }; +struct dtn_min_clk_info { + uint32_t disp_clk_khz; + uint32_t min_engine_clock_khz; + uint32_t min_memory_clock_khz; +}; + #endif -- GitLab From 7f524a0d838d8d9334003b956b73729f27a1315a Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 23 Jun 2017 13:35:53 -0400 Subject: [PATCH 0578/2898] drm/amd/display: remove unneeded FBC hw programming code - Removed uneeded FBC code. - Initial placeholder for FBC implementation on stoney/carrizo Signed-off-by: Bhawanpreet Lakha Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_compressor.c | 534 +++--------------- .../amd/display/dc/dce110/dce110_compressor.h | 3 + .../gpu/drm/amd/display/dc/inc/compressor.h | 46 +- 3 files changed, 137 insertions(+), 446 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 518150a414e2..5fe83045d1a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -94,199 +94,8 @@ enum fbc_idle_force { FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000, }; -static uint32_t lpt_size_alignment(struct dce110_compressor *cp110) -{ - /*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */ - return cp110->base.raw_size * cp110->base.banks_num * - cp110->base.dram_channels_num; -} - -static uint32_t lpt_memory_control_config(struct dce110_compressor *cp110, - uint32_t lpt_control) -{ - /*LPT MC Config */ - if (cp110->base.options.bits.LPT_MC_CONFIG == 1) { - /* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS): - * 00 - 1 CHANNEL - * 01 - 2 CHANNELS - * 02 - 4 OR 6 CHANNELS - * (Only for discrete GPU, N/A for CZ) - * 03 - 8 OR 12 CHANNELS - * (Only for discrete GPU, N/A for CZ) */ - switch (cp110->base.dram_channels_num) { - case 2: - set_reg_field_value( - lpt_control, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_PIPES); - break; - case 1: - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_PIPES); - break; - default: - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: Invalid LPT NUM_PIPES!!!", - __func__); - break; - } - - /* The mapping for LPT NUM_BANKS is in - * GRPH_CONTROL.GRPH_NUM_BANKS register field - * Specifies the number of memory banks for tiling - * purposes. Only applies to 2D and 3D tiling modes. - * POSSIBLE VALUES: - * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK - * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK - * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK - * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */ - switch (cp110->base.banks_num) { - case 16: - set_reg_field_value( - lpt_control, - 3, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_BANKS); - break; - case 8: - set_reg_field_value( - lpt_control, - 2, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_BANKS); - break; - case 4: - set_reg_field_value( - lpt_control, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_BANKS); - break; - case 2: - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_NUM_BANKS); - break; - default: - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: Invalid LPT NUM_BANKS!!!", - __func__); - break; - } - - /* The mapping is in DMIF_ADDR_CALC. - * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for - * Carrizo specifies the memory interleave per pipe. - * It effectively specifies the location of pipe bits in - * the memory address. - * POSSIBLE VALUES: - * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte - * interleave - * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte - * interleave - */ - switch (cp110->base.channel_interleave_size) { - case 256: /*256B */ - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); - break; - case 512: /*512B */ - set_reg_field_value( - lpt_control, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE); - break; - default: - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: Invalid LPT INTERLEAVE_SIZE!!!", - __func__); - break; - } - /* The mapping for LOW_POWER_TILING_ROW_SIZE is in - * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field - * for Carrizo. Specifies the size of dram row in bytes. - * This should match up with NOOFCOLS field in - * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns). - * This register DMIF_ADDR_CALC is not used by the - * hardware as it is only used for addrlib assertions. - * POSSIBLE VALUES: - * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row - * boundary - * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row - * boundary - * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row - * boundary */ - switch (cp110->base.raw_size) { - case 4096: /*4 KB */ - set_reg_field_value( - lpt_control, - 2, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ROW_SIZE); - break; - case 2048: - set_reg_field_value( - lpt_control, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ROW_SIZE); - break; - case 1024: - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ROW_SIZE); - break; - default: - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: Invalid LPT ROW_SIZE!!!", - __func__); - break; - } - } else { - dm_logger_write( - cp110->base.ctx->logger, LOG_WARNING, - "%s: LPT MC Configuration is not provided", - __func__); - } - - return lpt_control; -} - -static bool is_source_bigger_than_epanel_size( - struct dce110_compressor *cp110, - uint32_t source_view_width, - uint32_t source_view_height) -{ - if (cp110->base.embedded_panel_h_size != 0 && - cp110->base.embedded_panel_v_size != 0 && - ((source_view_width * source_view_height) > - (cp110->base.embedded_panel_h_size * - cp110->base.embedded_panel_v_size))) - return true; - - return false; -} - -static uint32_t align_to_chunks_number_per_line( - struct dce110_compressor *cp110, - uint32_t pixels) +static uint32_t align_to_chunks_number_per_line(uint32_t pixels) { return 256 * ((pixels + 255) / 256); } @@ -372,25 +181,11 @@ void dce110_compressor_enable_fbc( struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); if (compressor->options.bits.FBC_SUPPORT && - (compressor->options.bits.DUMMY_BACKEND == 0) && - (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) && - (!is_source_bigger_than_epanel_size( - cp110, - params->source_view_width, - params->source_view_height))) { + (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL))) { uint32_t addr; uint32_t value; - /* Before enabling FBC first need to enable LPT if applicable - * LPT state should always be changed (enable/disable) while FBC - * is disabled */ - if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) && - (params->source_view_width * - params->source_view_height <= - dce11_one_lpt_channel_max_resolution)) { - dce110_compressor_enable_lpt(compressor); - } addr = mmFBC_CNTL; value = dm_read_reg(compressor->ctx, addr); @@ -432,11 +227,6 @@ void dce110_compressor_disable_fbc(struct compressor *compressor) compressor->attached_inst = 0; compressor->is_enabled = false; - /* Whenever disabling FBC make sure LPT is disabled if LPT - * supported */ - if (compressor->options.bits.LPT_SUPPORT) - dce110_compressor_disable_lpt(compressor); - wait_for_fbc_state_changed(cp110, false); } } @@ -469,17 +259,6 @@ bool dce110_compressor_is_fbc_enabled_in_hw( return false; } -bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *compressor) -{ - /* Check the hardware register */ - uint32_t value = dm_read_reg(compressor->ctx, - mmLOW_POWER_TILING_CONTROL); - - return get_reg_field_value( - value, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ENABLE); -} void dce110_compressor_program_compressed_surface_address_and_pitch( struct compressor *compressor, @@ -499,17 +278,6 @@ void dce110_compressor_program_compressed_surface_address_and_pitch( dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0); - if (compressor->options.bits.LPT_SUPPORT) { - uint32_t lpt_alignment = lpt_size_alignment(cp110); - - if (lpt_alignment != 0) { - compressed_surf_address_low_part = - ((compressed_surf_address_low_part - + (lpt_alignment - 1)) / lpt_alignment) - * lpt_alignment; - } - } - /* Write address, HIGH has to be first. */ dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH), @@ -518,9 +286,7 @@ void dce110_compressor_program_compressed_surface_address_and_pitch( DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), compressed_surf_address_low_part); - fbc_pitch = align_to_chunks_number_per_line( - cp110, - params->source_view_width); + fbc_pitch = align_to_chunks_number_per_line(params->source_view_width); if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1) fbc_pitch = fbc_pitch / 8; @@ -543,197 +309,6 @@ void dce110_compressor_program_compressed_surface_address_and_pitch( } -void dce110_compressor_disable_lpt(struct compressor *compressor) -{ - struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); - uint32_t value; - uint32_t addr; - uint32_t inx; - - /* Disable all pipes LPT Stutter */ - for (inx = 0; inx < 3; inx++) { - value = - dm_read_reg( - compressor->ctx, - DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); - set_reg_field_value( - value, - 0, - DPG_PIPE_STUTTER_CONTROL_NONLPTCH, - STUTTER_ENABLE_NONLPTCH); - dm_write_reg( - compressor->ctx, - DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), - value); - } - /* Disable Underlay pipe LPT Stutter */ - addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 0, - DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, - STUTTER_ENABLE_NONLPTCH); - dm_write_reg(compressor->ctx, addr, value); - - /* Disable LPT */ - addr = mmLOW_POWER_TILING_CONTROL; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ENABLE); - dm_write_reg(compressor->ctx, addr, value); - - /* Clear selection of Channel(s) containing Compressed Surface */ - addr = mmGMCON_LPT_TARGET; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 0xFFFFFFFF, - GMCON_LPT_TARGET, - STCTRL_LPT_TARGET); - dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value); -} - -void dce110_compressor_enable_lpt(struct compressor *compressor) -{ - struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); - uint32_t value; - uint32_t addr; - uint32_t value_control; - uint32_t channels; - - /* Enable LPT Stutter from Display pipe */ - value = dm_read_reg(compressor->ctx, - DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH)); - set_reg_field_value( - value, - 1, - DPG_PIPE_STUTTER_CONTROL_NONLPTCH, - STUTTER_ENABLE_NONLPTCH); - dm_write_reg(compressor->ctx, - DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value); - - /* Enable Underlay pipe LPT Stutter */ - addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 1, - DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH, - STUTTER_ENABLE_NONLPTCH); - dm_write_reg(compressor->ctx, addr, value); - - /* Selection of Channel(s) containing Compressed Surface: 0xfffffff - * will disable LPT. - * STCTRL_LPT_TARGETn corresponds to channel n. */ - addr = mmLOW_POWER_TILING_CONTROL; - value_control = dm_read_reg(compressor->ctx, addr); - channels = get_reg_field_value(value_control, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_MODE); - - addr = mmGMCON_LPT_TARGET; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - channels + 1, /* not mentioned in programming guide, - but follow DCE8.1 */ - GMCON_LPT_TARGET, - STCTRL_LPT_TARGET); - dm_write_reg(compressor->ctx, addr, value); - - /* Enable LPT */ - addr = mmLOW_POWER_TILING_CONTROL; - value = dm_read_reg(compressor->ctx, addr); - set_reg_field_value( - value, - 1, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ENABLE); - dm_write_reg(compressor->ctx, addr, value); -} - -void dce110_compressor_program_lpt_control( - struct compressor *compressor, - struct compr_addr_and_pitch_params *params) -{ - struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); - uint32_t rows_per_channel; - uint32_t lpt_alignment; - uint32_t source_view_width; - uint32_t source_view_height; - uint32_t lpt_control = 0; - - if (!compressor->options.bits.LPT_SUPPORT) - return; - - lpt_control = dm_read_reg(compressor->ctx, - mmLOW_POWER_TILING_CONTROL); - - /* POSSIBLE VALUES for Low Power Tiling Mode: - * 00 - Use channel 0 - * 01 - Use Channel 0 and 1 - * 02 - Use Channel 0,1,2,3 - * 03 - reserved */ - switch (compressor->lpt_channels_num) { - /* case 2: - * Use Channel 0 & 1 / Not used for DCE 11 */ - case 1: - /*Use Channel 0 for LPT for DCE 11 */ - set_reg_field_value( - lpt_control, - 0, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_MODE); - break; - default: - dm_logger_write( - compressor->ctx->logger, LOG_WARNING, - "%s: Invalid selected DRAM channels for LPT!!!", - __func__); - break; - } - - lpt_control = lpt_memory_control_config(cp110, lpt_control); - - /* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on - * FBC compressed surface pitch. - * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height * - * Surface Pitch) / (Row Size * Number of Channels * - * Number of Banks)). */ - rows_per_channel = 0; - lpt_alignment = lpt_size_alignment(cp110); - source_view_width = - align_to_chunks_number_per_line( - cp110, - params->source_view_width); - source_view_height = (params->source_view_height + 1) & (~0x1); - - if (lpt_alignment != 0) { - rows_per_channel = source_view_width * source_view_height * 4; - rows_per_channel = - (rows_per_channel % lpt_alignment) ? - (rows_per_channel / lpt_alignment + 1) : - rows_per_channel / lpt_alignment; - } - - set_reg_field_value( - lpt_control, - rows_per_channel, - LOW_POWER_TILING_CONTROL, - LOW_POWER_TILING_ROWS_PER_CHAN); - - dm_write_reg(compressor->ctx, - mmLOW_POWER_TILING_CONTROL, lpt_control); -} - -/* - * DCE 11 Frame Buffer Compression Implementation - */ - void dce110_compressor_set_fbc_invalidation_triggers( struct compressor *compressor, uint32_t fbc_trigger) @@ -792,21 +367,20 @@ void dce110_compressor_set_fbc_invalidation_triggers( } bool dce110_compressor_construct(struct dce110_compressor *compressor, - struct dc_context *ctx) + struct dc_context *ctx) { - struct dc_bios *bp = ctx->dc_bios; - struct embedded_panel_info panel_info; compressor->base.options.bits.FBC_SUPPORT = true; - compressor->base.options.bits.LPT_SUPPORT = true; - /* For DCE 11 always use one DRAM channel for LPT */ + + /* for dce 11 always use one dram channel for lpt */ compressor->base.lpt_channels_num = 1; compressor->base.options.bits.DUMMY_BACKEND = false; - /* Check if this system has more than 1 DRAM channel; if only 1 then LPT - * should not be supported */ - if (compressor->base.memory_bus_width == 64) - compressor->base.options.bits.LPT_SUPPORT = false; + /* + * check if this system has more than 1 dram channel; if only 1 then lpt + * should not be supported + */ + compressor->base.options.bits.CLK_GATING_DISABLED = false; @@ -826,13 +400,6 @@ bool dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.attached_inst = 0; compressor->base.is_enabled = false; - if (BP_RESULT_OK == - bp->funcs->get_embedded_panel_info(bp, &panel_info)) { - compressor->base.embedded_panel_h_size = - panel_info.lcd_timing.horizontal_addressable; - compressor->base.embedded_panel_v_size = - panel_info.lcd_timing.vertical_addressable; - } return true; } @@ -857,3 +424,82 @@ void dce110_compressor_destroy(struct compressor **compressor) dm_free(TO_DCE110_COMPRESSOR(*compressor)); *compressor = NULL; } + +bool dce110_get_required_compressed_surfacesize(struct fbc_input_info fbc_input_info, + struct fbc_requested_compressed_size size) +{ + bool result = false; + + unsigned int max_x = FBC_MAX_X, max_y = FBC_MAX_Y; + + get_max_support_fbc_buffersize(&max_x, &max_y); + + if (fbc_input_info.dynamic_fbc_buffer_alloc == 0) { + /* + * For DCE11 here use Max HW supported size: HW Support up to 3840x2400 resolution + * or 18000 chunks. + */ + size.preferred_size = size.min_size = align_to_chunks_number_per_line(max_x) * max_y * 4; /* (For FBC when LPT not supported). */ + size.preferred_size_alignment = size.min_size_alignment = 0x100; /* For FBC when LPT not supported */ + size.bits.preferred_must_be_framebuffer_pool = 1; + size.bits.min_must_be_framebuffer_pool = 1; + + result = true; + } + /* + * Maybe to add registry key support with optional size here to override above + * for debugging purposes + */ + + return result; +} + + +void get_max_support_fbc_buffersize(unsigned int *max_x, unsigned int *max_y) +{ + *max_x = FBC_MAX_X; + *max_y = FBC_MAX_Y; + + /* if (m_smallLocalFrameBufferMemory == 1) + * { + * *max_x = FBC_MAX_X_SG; + * *max_y = FBC_MAX_Y_SG; + * } + */ +} + + +unsigned int controller_id_to_index(enum controller_id controller_id) +{ + unsigned int index = 0; + + switch (controller_id) { + case CONTROLLER_ID_D0: + index = 0; + break; + case CONTROLLER_ID_D1: + index = 1; + break; + case CONTROLLER_ID_D2: + index = 2; + break; + case CONTROLLER_ID_D3: + index = 3; + break; + default: + break; + } + return index; +} + + +static const struct compressor_funcs dce110_compressor_funcs = { + .power_up_fbc = dce110_compressor_power_up_fbc, + .enable_fbc = dce110_compressor_enable_fbc, + .disable_fbc = dce110_compressor_disable_fbc, + .set_fbc_invalidation_triggers = dce110_compressor_set_fbc_invalidation_triggers, + .surface_address_and_pitch = dce110_compressor_program_compressed_surface_address_and_pitch, + .is_fbc_enabled_in_hw = dce110_compressor_is_fbc_enabled_in_hw +}; + + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h index 22af5be51581..ff21c86df828 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h @@ -75,4 +75,7 @@ void dce110_compressor_program_lpt_control(struct compressor *cp, bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *cp); +void get_max_support_fbc_buffersize(unsigned int *max_x, unsigned int *max_y); + #endif + diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h index af292596b101..5fdc2fc10231 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/compressor.h +++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.h @@ -45,6 +45,7 @@ union fbc_physical_address { }; struct compr_addr_and_pitch_params { + enum controller_id controller_id; uint32_t inst; uint32_t source_view_width; uint32_t source_view_height; @@ -52,14 +53,32 @@ struct compr_addr_and_pitch_params { enum fbc_hw_max_resolution_supported { FBC_MAX_X = 3840, - FBC_MAX_Y = 2400 + FBC_MAX_Y = 2400, + FBC_MAX_X_SG = 1920, + FBC_MAX_Y_SG = 1080, }; +struct compressor; + +struct compressor_funcs { + + void (*power_up_fbc)(struct compressor *cp); + void (*enable_fbc)(struct compressor *cp, uint32_t paths_num, + struct compr_addr_and_pitch_params *params); + void (*disable_fbc)(struct compressor *cp); + void (*set_fbc_invalidation_triggers)(struct compressor *cp, + uint32_t fbc_trigger); + void (*surface_address_and_pitch)( + struct compressor *cp, + struct compr_addr_and_pitch_params *params); + bool (*is_fbc_enabled_in_hw)(struct compressor *cp, + uint32_t *fbc_mapped_crtc_id); +}; struct compressor { struct dc_context *ctx; uint32_t attached_inst; bool is_enabled; - + const struct compressor_funcs funcs; union { uint32_t raw; struct { @@ -90,4 +109,27 @@ struct compressor { enum fbc_compress_ratio min_compress_ratio; }; +struct fbc_input_info { + bool dynamic_fbc_buffer_alloc; + unsigned int source_view_width; + unsigned int source_view_height; + unsigned int num_of_active_targets; +}; + + +struct fbc_requested_compressed_size { + unsigned int preferred_size; + unsigned int preferred_size_alignment; + unsigned int min_size; + unsigned int min_size_alignment; + union { + struct { + /* Above preferedSize must be allocated in FB pool */ + unsigned int preferred_must_be_framebuffer_pool : 1; + /* Above minSize must be allocated in FB pool */ + unsigned int min_must_be_framebuffer_pool : 1; + } bits; + unsigned int flags; + }; +}; #endif -- GitLab From cfe4645e17f8dbe680c35c439d000313f2648482 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 14 Jun 2017 18:58:04 -0400 Subject: [PATCH 0579/2898] drm/amd/display: fix dcn pipe reset sequence This change fixes dcn10 front end reset sequence. Previously we would reset front end during flip which led to issues in certain MPO and 4k/5k scenarios. We would also never properly power gate our front end. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 +- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 19 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 22 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 7 + drivers/gpu/drm/amd/display/dc/dc.h | 3 - .../display/dc/dce110/dce110_hw_sequencer.c | 17 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 226 ++++++++---------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 17 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 4 +- .../display/dc/dcn10/dcn10_timing_generator.c | 6 +- .../display/dc/dcn10/dcn10_timing_generator.h | 4 + drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 1 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- 13 files changed, 155 insertions(+), 175 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 3711176bd070..a6f27ceaf4af 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2380,7 +2380,7 @@ static void amdgpu_dm_do_flip( surface_updates->flip_addr = &addr; - dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, acrtc->stream); + dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc->stream, NULL); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 3ec702fecfd1..00961bc37200 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -511,12 +511,14 @@ static void split_stream_across_pipes( struct pipe_ctx *primary_pipe, struct pipe_ctx *secondary_pipe) { + int pipe_idx = secondary_pipe->pipe_idx; + if (!primary_pipe->surface) return; - secondary_pipe->stream = primary_pipe->stream; - secondary_pipe->tg = primary_pipe->tg; + *secondary_pipe = *primary_pipe; + secondary_pipe->pipe_idx = pipe_idx; secondary_pipe->mpcc = pool->mpcc[secondary_pipe->pipe_idx]; secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; @@ -528,8 +530,6 @@ static void split_stream_across_pipes( } primary_pipe->bottom_pipe = secondary_pipe; secondary_pipe->top_pipe = primary_pipe; - secondary_pipe->surface = primary_pipe->surface; - secondary_pipe->pipe_dlg_param = primary_pipe->pipe_dlg_param; resource_build_scaling_params(primary_pipe); resource_build_scaling_params(secondary_pipe); @@ -1011,10 +1011,13 @@ bool dcn_validate_bandwidth( dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); } else if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { /* merge previously split pipe */ - if (pipe->bottom_pipe->bottom_pipe) - pipe->bottom_pipe->bottom_pipe->top_pipe = pipe; - memset(pipe->bottom_pipe, 0, sizeof(*pipe->bottom_pipe)); - pipe->bottom_pipe = pipe->bottom_pipe->bottom_pipe; + pipe->bottom_pipe = hsplit_pipe->bottom_pipe; + if (hsplit_pipe->bottom_pipe) + hsplit_pipe->bottom_pipe->top_pipe = pipe; + hsplit_pipe->surface = NULL; + hsplit_pipe->stream = NULL; + hsplit_pipe->top_pipe = NULL; + hsplit_pipe->bottom_pipe = NULL; resource_build_scaling_params(pipe); } /* for now important to do this after pipe split for building e2e params */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 18fde5081742..2f481ef55490 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -963,11 +963,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) for (i = 0; i < core_dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL - || context->res_ctx.pipe_ctx[i].surface == NULL) { - context->res_ctx.pipe_ctx[i].pipe_idx = i; - core_dc->hwss.power_down_front_end( - core_dc, &context->res_ctx.pipe_ctx[i]); - } + || context->res_ctx.pipe_ctx[i].surface == NULL) + core_dc->hwss.power_down_front_end(core_dc, i); /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -989,7 +986,6 @@ bool dc_commit_surfaces_to_stream( struct dc_plane_info plane_info[MAX_SURFACES]; struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; - bool ret; struct dc_stream_update *stream_update = dm_alloc(sizeof(struct dc_stream_update)); @@ -1038,10 +1034,10 @@ bool dc_commit_surfaces_to_stream( new_surface_count, dc_stream, stream_update); - ret = dc_post_update_surfaces_to_stream(dc); + dc_post_update_surfaces_to_stream(dc); dm_free(stream_update); - return ret; + return true; } static bool is_surface_in_context( @@ -1217,14 +1213,6 @@ enum surface_update_type dc_check_update_surfaces_for_stream( return overall_type; } -void dc_update_surfaces_for_stream(struct dc *dc, - struct dc_surface_update *surface_updates, int surface_count, - const struct dc_stream *dc_stream) -{ - dc_update_surfaces_and_stream(dc, surface_updates, surface_count, - dc_stream, NULL); -} - enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_surfaces_and_stream(struct dc *dc, @@ -1401,7 +1389,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } - if (!surface_count) /* reset */ + if (surface_count == 0) core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); /* Lock pipes for provided surfaces, or all active if full update*/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f0183d5f0d0d..fb033b69e2bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1096,6 +1096,10 @@ bool resource_attach_surfaces_to_context( free_pipe->surface = surface; if (tail_pipe) { + free_pipe->tg = tail_pipe->tg; + free_pipe->stream_enc = tail_pipe->stream_enc; + free_pipe->audio = tail_pipe->audio; + free_pipe->clock_source = tail_pipe->clock_source; free_pipe->top_pipe = tail_pipe; tail_pipe->bottom_pipe = free_pipe; } @@ -2300,6 +2304,9 @@ bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx) { + if (!pipe_ctx_old->stream) + return false; + if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) return true; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cb70b6d8be10..18f6858e4992 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -415,9 +415,6 @@ bool dc_commit_surfaces_to_stream( bool dc_post_update_surfaces_to_stream( struct dc *dc); -void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates, - int surface_count, const struct dc_stream *stream); - /* Surface update type is used by dc_update_surfaces_and_stream * The update type is determined at the very beginning of the function based * on parameters passed in and decides how much programming (or updating) is diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0bab85b27a85..fd1cb7fe45bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1185,8 +1185,7 @@ static void disable_vga_and_power_gate_all_controllers( enable_display_pipe_clock_gating(ctx, true); - dc->hwss.power_down_front_end( - dc, &dc->current_context->res_ctx.pipe_ctx[i]); + dc->hwss.power_down_front_end(dc, i); } } @@ -1340,7 +1339,7 @@ static void reset_single_pipe_hw_ctx( resource_unreference_clock_source(&context->res_ctx, dc->res_pool, &pipe_ctx->clock_source); - dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); + dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx->pipe_idx); pipe_ctx->stream = NULL; } @@ -2538,17 +2537,17 @@ static void dce110_apply_ctx_for_surface( } } -static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) +static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) { /* Do not power down fe when stream is active on dce*/ - if (pipe->stream) + if (dc->current_context->res_ctx.pipe_ctx[fe_idx].stream) return; dc->hwss.enable_display_power_gating( - dc, pipe->pipe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); - if (pipe->xfm) - pipe->xfm->funcs->transform_reset(pipe->xfm); - memset(&pipe->scl_data, 0, sizeof(struct scaler_data)); + dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); + + dc->res_pool->transforms[fe_idx]->funcs->transform_reset( + dc->res_pool->transforms[fe_idx]); } static const struct hw_sequencer_funcs dce110_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index edcd7369cf9d..d0bddfd64c67 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -116,18 +116,6 @@ static const struct dcn10_hwseq_reg_offsets reg_offsets[] = { HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val) /* TODO should be moved to OTG */ -static void lock_otg_master_update( - struct dc_context *ctx, - uint8_t inst) -{ - uint32_t inst_offset = reg_offsets[inst].otg; - - HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0, - OTG_MASTER_UPDATE_LOCK_SEL, inst); - - HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, - OTG_MASTER_UPDATE_LOCK, 1); -} static bool unlock_master_tg_and_wait( struct dc_context *ctx, @@ -148,19 +136,6 @@ static bool unlock_master_tg_and_wait( return true; } -/* TODO: should be moved to OTG ? */ -static void unlock_otg_master( - struct dc_context *ctx, - uint8_t inst) -{ - uint32_t inst_offset = reg_offsets[inst].otg; - - /* unlock master locker */ - HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, - OTG_MASTER_UPDATE_LOCK, 0); -} - - static void wait_no_outstanding_request( struct dc_context *ctx, uint8_t plane_id) @@ -489,8 +464,7 @@ static void hubp_pg_control( static void power_on_plane( struct dc_context *ctx, - uint8_t plane_id, - uint8_t inst) + int plane_id) { uint32_t inst_offset = 0; @@ -500,6 +474,8 @@ static void power_on_plane( hubp_pg_control(ctx, plane_id, true); HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, 0); + dm_logger_write(ctx->logger, LOG_DC, + "Un-gated front end for pipe %d\n", plane_id); } /* fully check bios enabledisplaypowergating table. dal only need dce init @@ -596,13 +572,13 @@ static void init_hw(struct core_dc *dc) dc->res_pool->mpcc[i]; struct mpcc_cfg mpcc_cfg; - lock_otg_master_update(dc->ctx, tg->inst); + tg->funcs->lock(tg); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = true; mpcc->funcs->set(mpcc, &mpcc_cfg); - unlock_otg_master(dc->ctx, tg->inst); + tg->funcs->unlock(tg); tg->funcs->disable_vga(tg); /* Blank controller using driver code instead of @@ -822,56 +798,85 @@ static void reset_back_end_for_pipe( return; pipe_ctx->stream = NULL; + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset back end for pipe %d, tg:%d\n", + pipe_ctx->pipe_idx, pipe_ctx->tg->inst); } -static void reset_front_end_for_pipe( +static void reset_front_end( struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) + int fe_idx) { struct mpcc_cfg mpcc_cfg; + struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct transform *xfm = dc->res_pool->transforms[fe_idx]; + struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; + struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - if (!pipe_ctx->surface) + /*Already reset*/ + if (mpcc->opp_id == 0xf) return; - pipe_ctx->mi->funcs->dcc_control(pipe_ctx->mi, false, false); - - lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); + mi->funcs->dcc_control(mi, false, false); + tg->funcs->lock(tg); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; - pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); - - pipe_ctx->top_pipe = NULL; - pipe_ctx->bottom_pipe = NULL; + mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; + mpcc->funcs->set(mpcc, &mpcc_cfg); - unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); + unlock_master_tg_and_wait(dc->ctx, tg->inst); + mpcc->funcs->wait_for_idle(mpcc); + mi->funcs->set_blank(mi, true); + wait_no_outstanding_request(dc->ctx, fe_idx); + disable_clocks(dc->ctx, fe_idx); - pipe_ctx->mi->funcs->set_blank(pipe_ctx->mi, true); + xfm->funcs->transform_reset(xfm); - wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset front end %d\n", + fe_idx); +} - disable_clocks(dc->ctx, pipe_ctx->pipe_idx); +static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) +{ + struct dc_context *ctx = dc->ctx; + uint32_t inst_offset = 0; - pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm); + reset_front_end(dc, fe_idx); + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 1); + dpp_pg_control(ctx, fe_idx, false); + hubp_pg_control(ctx, fe_idx, false); + HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, - "Reset front end for pipe %d\n", - pipe_ctx->pipe_idx); - - pipe_ctx->surface = NULL; + "Power gated front end %d\n", fe_idx); } -static void reset_hw_ctx(struct core_dc *dc, - struct validate_context *context, - void (*reset)(struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context)) +static void reset_hw_ctx_wrap( + struct core_dc *dc, + struct validate_context *context) { int i; + /* Reset Front End*/ + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + /*if (!pipe_ctx_old->stream) + continue;*/ + + if (!pipe_ctx->stream || !pipe_ctx->surface) + dcn10_power_down_fe(dc, i); + else if (pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + reset_front_end(dc, i); + } + /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; @@ -882,23 +887,13 @@ static void reset_hw_ctx(struct core_dc *dc, if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - reset(dc, pipe_ctx_old, dc->current_context); + reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_context); } } -static void reset_hw_ctx_wrap( - struct core_dc *dc, - struct validate_context *context) -{ - /* Reset Front End*/ - reset_hw_ctx(dc, context, reset_front_end_for_pipe); - /* Reset Back End*/ - reset_hw_ctx(dc, context, reset_back_end_for_pipe); -} - -static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, - PHYSICAL_ADDRESS_LOC *addr) +static bool patch_address_for_sbs_tb_stereo( + struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { struct core_surface *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && @@ -936,8 +931,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct } static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, - const struct core_surface *surface) + struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct core_transfer_func *tf = NULL; @@ -950,8 +944,8 @@ static bool dcn10_set_input_transfer_func( tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); if (surface->public.gamma_correction && dce_use_lut(surface)) - ipp->funcs->ipp_program_input_lut(ipp, - surface->public.gamma_correction); + ipp->funcs->ipp_program_input_lut(ipp, + surface->public.gamma_correction); if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); @@ -1333,8 +1327,6 @@ static void dcn10_pipe_control_lock( struct pipe_ctx *pipe, bool lock) { - struct dce_hwseq *hws = hws = dc->hwseq; - /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ @@ -1342,9 +1334,9 @@ static void dcn10_pipe_control_lock( return; if (lock) - dcn10_lock(pipe->tg); + pipe->tg->funcs->lock(pipe->tg); else - dcn10_unlock(pipe->tg); + pipe->tg->funcs->unlock(pipe->tg); } static bool wait_for_reset_trigger_to_occur( @@ -1543,7 +1535,7 @@ static void dcn10_power_on_fe( struct dc_surface *dc_surface = &pipe_ctx->surface->public; power_on_plane(dc->ctx, - pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + pipe_ctx->pipe_idx); /* enable DCFCLK current DCHUB */ enable_dcfclk(dc->ctx, @@ -1694,7 +1686,6 @@ static void update_dchubp_dpp( struct default_adjustment ocsc = {0}; struct tg_color black_color = {0}; struct mpcc_cfg mpcc_cfg; - struct pipe_ctx *top_pipe; bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ @@ -1734,14 +1725,13 @@ static void update_dchubp_dpp( IPP_OUTPUT_FORMAT_12_BIT_FIX); pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; - for (top_pipe = pipe_ctx; top_pipe != NULL; top_pipe = top_pipe->top_pipe) - mpcc_cfg.opp_id = top_pipe->opp->inst; mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx; if (pipe_ctx->bottom_pipe) mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst; else mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; + mpcc_cfg.opp_id = pipe_ctx->tg->inst; + mpcc_cfg.top_of_tree = pipe_ctx->pipe_idx == pipe_ctx->tg->inst; mpcc_cfg.per_pixel_alpha = per_pixel_alpha; /* DCN1.0 has output CM before MPC which seems to screw with * pre-multiplied alpha. @@ -1749,8 +1739,6 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->public.output_color_space) && per_pixel_alpha; - if (!dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].surface) - pipe_ctx->mpcc->funcs->wait_for_idle(pipe_ctx->mpcc); pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); color_space_to_black_color( @@ -1796,7 +1784,7 @@ static void program_all_pipe_in_tree( /* watermark is for all pipes */ pipe_ctx->mi->funcs->program_watermarks( pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); - lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); + pipe_ctx->tg->funcs->lock(pipe_ctx->tg); pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; @@ -1852,13 +1840,41 @@ static void dcn10_apply_ctx_for_surface( { int i; + /* reset unused mpcc */ + /*for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[i]; + + if ((!pipe_ctx->surface && old_pipe_ctx->surface) + || (!pipe_ctx->stream && old_pipe_ctx->stream)) { + struct mpcc_cfg mpcc_cfg; + + mpcc_cfg.opp_id = 0xf; + mpcc_cfg.top_dpp_id = 0xf; + mpcc_cfg.bot_mpcc_id = 0xf; + mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; + old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + + old_pipe_ctx->top_pipe = NULL; + old_pipe_ctx->bottom_pipe = NULL; + old_pipe_ctx->surface = NULL; + + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset mpcc for pipe %d\n", + old_pipe_ctx->pipe_idx); + } + }*/ + + if (!surface) + return; + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->surface || pipe_ctx->surface != surface) + if (pipe_ctx->surface != surface) continue; - /* looking for top pipe to program */ if (!pipe_ctx->top_pipe) program_all_pipe_in_tree(dc, pipe_ctx, context); @@ -1910,27 +1926,6 @@ static void dcn10_apply_ctx_for_surface( context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns, context->bw.dcn.watermarks.d.pte_meta_urgent_ns ); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (!pipe_ctx->surface || pipe_ctx->top_pipe) - continue; - - /* unlock master update lock */ - unlock_otg_master(dc->ctx, pipe_ctx->tg->inst); - } - - /* reset unused pipe */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[i]; - - if ((!pipe_ctx->surface && old_pipe_ctx->surface) - || (!pipe_ctx->stream && old_pipe_ctx->stream)) - reset_front_end_for_pipe(dc, old_pipe_ctx, dc->current_context); - } } static void dcn10_set_bandwidth( @@ -1992,23 +1987,6 @@ static void dcn10_set_bandwidth( dcn10_pplib_apply_display_requirements(dc, context); } -static void dcn10_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) -{ - struct dc_context *ctx = dc->ctx; - uint32_t inst_offset = 0; - - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, - IP_REQUEST_EN, 1); - dpp_pg_control(ctx, pipe->pipe_idx, false); - hubp_pg_control(ctx, pipe->pipe_idx, false); - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, - IP_REQUEST_EN, 0); - - if (pipe->xfm) - pipe->xfm->funcs->transform_reset(pipe->xfm); - memset(&pipe->scl_data, 0, sizeof(pipe->scl_data)); -} - static void set_drr(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index b1c590d4f454..7af04bce3599 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -65,17 +65,17 @@ void dcn10_mpcc_set_bg_color( static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) { - ASSERT(mpcc10->opp_id == 0xf || opp_id == mpcc10->opp_id); - mpcc10->opp_id = opp_id; + ASSERT(mpcc10->base.opp_id == 0xf || opp_id == mpcc10->base.opp_id); + mpcc10->base.opp_id = opp_id; REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); } static void reset_output_mux(struct dcn10_mpcc *mpcc10) { - REG_SET(MUX[mpcc10->opp_id], 0, MPC_OUT_MUX, 0xf); - REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->opp_id], OPP_PIPE_CLOCK_EN, 0); - mpcc10->opp_id = 0xf; + REG_SET(MUX[mpcc10->base.opp_id], 0, MPC_OUT_MUX, 0xf); + REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->base.opp_id], OPP_PIPE_CLOCK_EN, 0); + mpcc10->base.opp_id = 0xf; } static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) @@ -104,16 +104,17 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) if (cfg->top_of_tree) { if (cfg->opp_id != 0xf) set_output_mux(mpcc10, cfg->opp_id, mpcc->inst); - else + else if (mpcc->opp_id != 0xf) reset_output_mux(mpcc10); } + mpcc10->base.opp_id = cfg->opp_id; } static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) { struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); - REG_WAIT(MPCC_STATUS, MPCC_IDLE, 1, 1000, 1000); + REG_WAIT(MPCC_STATUS, MPCC_BUSY, 0, 1000, 1000); } @@ -139,5 +140,5 @@ void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, mpcc10->mpcc_shift = mpcc_shift; mpcc10->mpcc_mask = mpcc_mask; - mpcc10->opp_id = inst; + mpcc10->base.opp_id = inst; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 0f9f1b97d238..fff267455a3d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -68,6 +68,7 @@ struct dcn_mpcc_registers { SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\ SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\ SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\ SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ @@ -83,6 +84,7 @@ struct dcn_mpcc_registers { type MPCC_ALPHA_MULTIPLIED_MODE;\ type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\ type MPCC_IDLE;\ + type MPCC_BUSY;\ type MPCC_OPP_ID;\ type MPCC_BG_G_Y;\ type MPCC_BG_R_CR;\ @@ -103,8 +105,6 @@ struct dcn10_mpcc { const struct dcn_mpcc_registers *mpcc_regs; const struct dcn_mpcc_shift *mpcc_shift; const struct dcn_mpcc_mask *mpcc_mask; - - int opp_id; }; void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 58fb29ff5677..802ace2e5212 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -575,6 +575,8 @@ void dcn10_lock(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, tg->inst); REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 1); } @@ -587,9 +589,9 @@ void dcn10_unlock(struct timing_generator *tg) OTG_MASTER_UPDATE_LOCK, 0); /* why are we waiting here? */ - REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, + /*REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, 0, - 20000, 200000); + 20000, 200000);*/ } static void dcn10_get_position(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index c880fa587790..3b2a20a4b957 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -37,6 +37,7 @@ SRI(OTG_VREADY_PARAM, OTG, inst),\ SRI(OTG_BLANK_CONTROL, OTG, inst),\ SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ SRI(OTG_H_TOTAL, OTG, inst),\ SRI(OTG_H_BLANK_START_END, OTG, inst),\ @@ -83,6 +84,7 @@ struct dcn_tg_registers { uint32_t OTG_VREADY_PARAM; uint32_t OTG_BLANK_CONTROL; uint32_t OTG_MASTER_UPDATE_LOCK; + uint32_t OTG_GLOBAL_CONTROL0; uint32_t OTG_DOUBLE_BUFFER_CONTROL; uint32_t OTG_H_TOTAL; uint32_t OTG_H_BLANK_START_END; @@ -134,6 +136,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ @@ -224,6 +227,7 @@ struct dcn_tg_registers { type OTG_CURRENT_BLANK_STATE;\ type OTG_MASTER_UPDATE_LOCK;\ type OTG_UPDATE_PENDING;\ + type OTG_MASTER_UPDATE_LOCK_SEL;\ type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ type OTG_H_TOTAL;\ type OTG_H_BLANK_START;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 51bc8ef5ef79..55c9c305a259 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -40,6 +40,7 @@ struct mpcc { const struct mpcc_funcs *funcs; struct dc_context *ctx; int inst; + int opp_id; }; struct mpcc_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 52884815c67b..642ae5e4ee1c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -105,7 +105,7 @@ struct hw_sequencer_funcs { struct dc_bios *dcb, enum pipe_gating_control power_gating); - void (*power_down_front_end)(struct core_dc *dc, struct pipe_ctx *pipe); + void (*power_down_front_end)(struct core_dc *dc, int fe_idx); void (*power_on_front_end)(struct core_dc *dc, struct pipe_ctx *pipe, -- GitLab From dc0ea008168bfbc61a7915eb6ffb1cc48ce5e9cc Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 28 Jun 2017 11:05:00 -0400 Subject: [PATCH 0580/2898] drm/amd/display: Move dm_plane_state to DAL header. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 109172576499..bf20d57a99e0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -36,6 +36,11 @@ struct dc_surface; struct dc_stream; +struct dm_plane_state { + struct drm_plane_state base; + struct dc_surface *dc_surface; +}; + struct dm_crtc_state { struct drm_crtc_state base; struct dc_stream *dc_stream; @@ -43,12 +48,6 @@ struct dm_crtc_state { #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) -struct dm_plane_state { - struct drm_plane_state base; - struct dc_surface *dc_surface; -}; - - /*TODO Jodan Hersen use the one in amdgpu_dm*/ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, -- GitLab From d09fec0f94376b1c0048215e14838295730ed6d3 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 27 Jun 2017 13:27:00 -0400 Subject: [PATCH 0581/2898] drm/amd/display: add hyst frames for fixed refresh Signed-off-by: Anthony Koo Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/modules/freesync/freesync.c | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 7109742bd67c..c7da90f2d8e7 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -37,6 +37,9 @@ #define RENDER_TIMES_MAX_COUNT 20 /* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */ #define BTR_EXIT_MARGIN 2000 +/* Number of consecutive frames to check before entering/exiting fixed refresh*/ +#define FIXED_REFRESH_ENTER_FRAME_COUNT 5 +#define FIXED_REFRESH_EXIT_FRAME_COUNT 5 #define FREESYNC_REGISTRY_NAME "freesync_v1" @@ -72,8 +75,9 @@ struct below_the_range { }; struct fixed_refresh { - bool fixed_refresh_active; - bool program_fixed_refresh; + bool fixed_active; + bool program_fixed; + unsigned int frame_counter; }; struct freesync_range { @@ -168,8 +172,8 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) /* Create initial module folder in registry for freesync enable data */ flag.save_per_edid = true; flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL, - 0, &flag); + dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, + NULL, NULL, 0, &flag); flag.save_per_edid = false; flag.save_per_link = false; if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, @@ -422,7 +426,7 @@ static void calc_freesync_range(struct core_freesync *core_freesync, min_frame_duration_in_ns) * stream->timing.pix_clk_khz), stream->timing.h_total), 1000000); - /* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */ + /* vmin/vmax cannot be less than vtotal */ if (state->freesync_range.vmin < vtotal) { /* Error of 1 is permissible */ ASSERT((state->freesync_range.vmin + 1) >= vtotal); @@ -553,8 +557,8 @@ static void reset_freesync_state_variables(struct freesync_state* state) state->btr.inserted_frame_duration_in_us = 0; state->btr.program_btr = false; - state->fixed_refresh.fixed_refresh_active = false; - state->fixed_refresh.program_fixed_refresh = false; + state->fixed_refresh.fixed_active = false; + state->fixed_refresh.program_fixed = false; } /* * Sets freesync mode on a stream depending on current freesync state. @@ -594,7 +598,7 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync, if (core_freesync->map[map_index].user_enable. enable_for_gaming == true && state->fullscreen == true && - state->fixed_refresh.fixed_refresh_active == false) { + state->fixed_refresh.fixed_active == false) { /* Enable freesync */ v_total_min = state->freesync_range.vmin; @@ -1240,29 +1244,39 @@ static void update_timestamps(struct core_freesync *core_freesync, state->btr.frame_counter = 0; /* Exit Fixed Refresh mode */ - } else if (state->fixed_refresh.fixed_refresh_active) { + } else if (state->fixed_refresh.fixed_active) { - state->fixed_refresh.program_fixed_refresh = true; - state->fixed_refresh.fixed_refresh_active = false; + state->fixed_refresh.frame_counter++; + if (state->fixed_refresh.frame_counter > + FIXED_REFRESH_EXIT_FRAME_COUNT) { + state->fixed_refresh.frame_counter = 0; + state->fixed_refresh.program_fixed = true; + state->fixed_refresh.fixed_active = false; + } } } else if (last_render_time_in_us > state->time.max_render_time_in_us) { /* Enter Below the Range */ if (!state->btr.btr_active && - core_freesync->map[map_index].caps->btr_supported) { + core_freesync->map[map_index].caps->btr_supported) { state->btr.program_btr = true; state->btr.btr_active = true; /* Enter Fixed Refresh mode */ - } else if (!state->fixed_refresh.fixed_refresh_active && + } else if (!state->fixed_refresh.fixed_active && !core_freesync->map[map_index].caps->btr_supported) { - state->fixed_refresh.program_fixed_refresh = true; - state->fixed_refresh.fixed_refresh_active = true; + state->fixed_refresh.frame_counter++; + if (state->fixed_refresh.frame_counter > + FIXED_REFRESH_ENTER_FRAME_COUNT) { + state->fixed_refresh.frame_counter = 0; + state->fixed_refresh.program_fixed = true; + state->fixed_refresh.fixed_active = true; + } } } @@ -1316,7 +1330,8 @@ static void apply_below_the_range(struct core_freesync *core_freesync, frame_time_in_us = last_render_time_in_us / mid_point_frames_ceil; - delta_from_mid_point_in_us_1 = (state->btr.mid_point_in_us > + delta_from_mid_point_in_us_1 = + (state->btr.mid_point_in_us > frame_time_in_us) ? (state->btr.mid_point_in_us - frame_time_in_us): (frame_time_in_us - state->btr.mid_point_in_us); @@ -1332,7 +1347,8 @@ static void apply_below_the_range(struct core_freesync *core_freesync, frame_time_in_us = last_render_time_in_us / mid_point_frames_floor; - delta_from_mid_point_in_us_2 = (state->btr.mid_point_in_us > + delta_from_mid_point_in_us_2 = + (state->btr.mid_point_in_us > frame_time_in_us) ? (state->btr.mid_point_in_us - frame_time_in_us): (frame_time_in_us - state->btr.mid_point_in_us); @@ -1374,15 +1390,15 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, unsigned int vmin = 0, vmax = 0; struct freesync_state *state = &core_freesync->map[map_index].state; - if (!state->fixed_refresh.program_fixed_refresh) + if (!state->fixed_refresh.program_fixed) return; - state->fixed_refresh.program_fixed_refresh = false; + state->fixed_refresh.program_fixed = false; /* Program Fixed Refresh */ /* Fixed Refresh set to "not active" so disengage */ - if (!state->fixed_refresh.fixed_refresh_active) { + if (!state->fixed_refresh.fixed_active) { set_freesync_on_streams(core_freesync, &stream, 1); /* Fixed Refresh set to "active" so engage (fix to max) */ -- GitLab From 1663ae1c4288da81b9f1668d204aa8ed55ebf849 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 27 Jun 2017 16:34:27 -0400 Subject: [PATCH 0582/2898] drm/amd/display: Connect DC resource to FBC compressor - Connected DC resource to FBC compressor, - Initial Implementation of FBC for Stoney/Carrizo - Code is currently guarded with "ENABLE_FBC" compile time flag Signed-off-by: Bhawanpreet Lakha Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 +++++ .../amd/display/dc/dce110/dce110_compressor.c | 78 ++++++++++--------- .../amd/display/dc/dce110/dce110_compressor.h | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 15 ++++ .../amd/display/dc/dce110/dce110_resource.c | 10 +++ .../gpu/drm/amd/display/dc/inc/compressor.h | 6 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 6 ++ 7 files changed, 94 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2f481ef55490..51e4cb30f858 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -843,6 +843,11 @@ bool dc_enable_stereo( int i, j; struct pipe_ctx *pipe; struct core_dc *core_dc = DC_TO_CORE(dc); + +#ifdef ENABLE_FBC + struct compressor *fbc_compressor = core_dc->fbc_compressor; +#endif + for (i = 0; i < MAX_PIPES; i++) { if (context != NULL) pipe = &context->res_ctx.pipe_ctx[i]; @@ -854,6 +859,14 @@ bool dc_enable_stereo( core_dc->hwss.setup_stereo(pipe, core_dc); } } + +#ifdef ENABLE_FBC + if (fbc_compressor != NULL && + fbc_compressor->funcs->is_fbc_enabled_in_hw(core_dc->fbc_compressor, + &pipe->tg->inst)) + fbc_compressor->funcs->disable_fbc(fbc_compressor); + +#endif return ret; } @@ -1232,6 +1245,12 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!stream_status) return; /* Cannot commit surface to stream that is not committed */ +#ifdef ENABLE_FBC + if (srf_updates->flip_addr) { + if (srf_updates->flip_addr->address.grph.addr.low_part == 0) + ASSERT(0); + } +#endif context = core_dc->current_context; /* update current stream with the new updates */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 5fe83045d1a6..1e59f4e31a6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -175,7 +175,6 @@ void dce110_compressor_power_up_fbc(struct compressor *compressor) void dce110_compressor_enable_fbc( struct compressor *compressor, - uint32_t paths_num, struct compr_addr_and_pitch_params *params) { struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); @@ -366,43 +365,6 @@ void dce110_compressor_set_fbc_invalidation_triggers( dm_write_reg(compressor->ctx, addr, value); } -bool dce110_compressor_construct(struct dce110_compressor *compressor, - struct dc_context *ctx) -{ - - compressor->base.options.bits.FBC_SUPPORT = true; - - /* for dce 11 always use one dram channel for lpt */ - compressor->base.lpt_channels_num = 1; - compressor->base.options.bits.DUMMY_BACKEND = false; - - /* - * check if this system has more than 1 dram channel; if only 1 then lpt - * should not be supported - */ - - - compressor->base.options.bits.CLK_GATING_DISABLED = false; - - compressor->base.ctx = ctx; - compressor->base.embedded_panel_h_size = 0; - compressor->base.embedded_panel_v_size = 0; - compressor->base.memory_bus_width = ctx->asic_id.vram_width; - compressor->base.allocated_size = 0; - compressor->base.preferred_requested_size = 0; - compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; - compressor->base.options.raw = 0; - compressor->base.banks_num = 0; - compressor->base.raw_size = 0; - compressor->base.channel_interleave_size = 0; - compressor->base.dram_channels_num = 0; - compressor->base.lpt_channels_num = 0; - compressor->base.attached_inst = 0; - compressor->base.is_enabled = false; - - return true; -} - struct compressor *dce110_compressor_create(struct dc_context *ctx) { struct dce110_compressor *cp110 = @@ -503,3 +465,43 @@ static const struct compressor_funcs dce110_compressor_funcs = { }; +bool dce110_compressor_construct(struct dce110_compressor *compressor, + struct dc_context *ctx) +{ + + compressor->base.options.bits.FBC_SUPPORT = true; + + /* for dce 11 always use one dram channel for lpt */ + compressor->base.lpt_channels_num = 1; + compressor->base.options.bits.DUMMY_BACKEND = false; + + /* + * check if this system has more than 1 dram channel; if only 1 then lpt + * should not be supported + */ + + + compressor->base.options.bits.CLK_GATING_DISABLED = false; + + compressor->base.ctx = ctx; + compressor->base.embedded_panel_h_size = 0; + compressor->base.embedded_panel_v_size = 0; + compressor->base.memory_bus_width = ctx->asic_id.vram_width; + compressor->base.allocated_size = 0; + compressor->base.preferred_requested_size = 0; + compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; + compressor->base.options.raw = 0; + compressor->base.banks_num = 0; + compressor->base.raw_size = 0; + compressor->base.channel_interleave_size = 0; + compressor->base.dram_channels_num = 0; + compressor->base.lpt_channels_num = 0; + compressor->base.attached_inst = 0; + compressor->base.is_enabled = false; +#ifdef ENABLE_FBC + compressor->base.funcs = &dce110_compressor_funcs; + +#endif + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h index ff21c86df828..460cb77b8d75 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h @@ -50,7 +50,7 @@ void dce110_compressor_destroy(struct compressor **cp); /* FBC RELATED */ void dce110_compressor_power_up_fbc(struct compressor *cp); -void dce110_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num, +void dce110_compressor_enable_fbc(struct compressor *cp, struct compr_addr_and_pitch_params *params); void dce110_compressor_disable_fbc(struct compressor *cp); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index fd1cb7fe45bc..72d5f753949d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -33,6 +33,10 @@ #include "dce110_timing_generator.h" #include "dce/dce_hwseq.h" +#ifdef ENABLE_FBC +#include "dce110_compressor.h" +#endif + #include "bios/bios_parser_helper.h" #include "timing_generator.h" #include "mem_input.h" @@ -1166,6 +1170,10 @@ static void power_down_all_hw_blocks(struct core_dc *dc) power_down_controllers(dc); power_down_clock_sources(dc); + +#ifdef ENABLE_FBC + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); +#endif } static void disable_vga_and_power_gate_all_controllers( @@ -1630,6 +1638,10 @@ enum dc_status dce110_apply_ctx_to_hw( } set_safe_displaymarks(&context->res_ctx, dc->res_pool); + +#ifdef ENABLE_FBC + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); +#endif /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); @@ -2215,6 +2227,9 @@ static void init_hw(struct core_dc *dc) abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); } +#ifdef ENABLE_FBC + dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); +#endif } void dce110_fill_display_configs( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 45759b9f15e5..8b7bc1cc2b7b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -52,6 +52,10 @@ #include "dce/dce_abm.h" #include "dce/dce_dmcu.h" +#ifdef ENABLE_FBC +#include "dce110/dce110_compressor.h" +#endif + #include "reg_helper.h" #include "dce/dce_11_0_d.h" @@ -1347,6 +1351,12 @@ static bool construct( } } +#ifdef ENABLE_FBC + dc->fbc_compressor = dce110_compressor_create(ctx); + + + +#endif if (!underlay_create(ctx, &pool->base)) goto res_create_fail; diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h index 5fdc2fc10231..24cca18f3c8f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/compressor.h +++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.h @@ -45,7 +45,7 @@ union fbc_physical_address { }; struct compr_addr_and_pitch_params { - enum controller_id controller_id; + /* enum controller_id controller_id; */ uint32_t inst; uint32_t source_view_width; uint32_t source_view_height; @@ -63,7 +63,7 @@ struct compressor; struct compressor_funcs { void (*power_up_fbc)(struct compressor *cp); - void (*enable_fbc)(struct compressor *cp, uint32_t paths_num, + void (*enable_fbc)(struct compressor *cp, struct compr_addr_and_pitch_params *params); void (*disable_fbc)(struct compressor *cp); void (*set_fbc_invalidation_triggers)(struct compressor *cp, @@ -78,7 +78,7 @@ struct compressor { struct dc_context *ctx; uint32_t attached_inst; bool is_enabled; - const struct compressor_funcs funcs; + const struct compressor_funcs *funcs; union { uint32_t raw; struct { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 392cff2cd558..785236a44aee 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -10,6 +10,7 @@ #include "core_types.h" #include "hw_sequencer.h" +#include "compressor.h" #define DC_TO_CORE(dc)\ container_of(dc, struct core_dc, public) @@ -44,6 +45,11 @@ struct core_dc { * to compare to see if display config changed */ struct dm_pp_display_configuration prev_display_config; + + /* FBC compressor */ +#ifdef ENABLE_FBC + struct compressor *fbc_compressor; +#endif }; #endif /* __CORE_DC_H__ */ -- GitLab From 9ff1bb090b40949cddfbb904e613395ad2633fc7 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Fri, 23 Jun 2017 17:45:50 -0400 Subject: [PATCH 0583/2898] drm/amd/display: Add extra mode and clock info to DTN logs Adds some additional information to logs in dc_commit_streams to better match Dal2. Also adds a new function, dc_raw_log, that has the same functionality as dc_conn_log, but does not attach display specific prefixes to the log output. Finally, adds a new DC log type, LOG_DTN, that logs to LogMinor_DispConnect_dtn in DM. This new log type and dc_raw_log are used to generate clock info in the logs to match Dal2. Signed-off-by: Corbin McElhanney Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 2 +- .../drm/amd/display/dc/basics/log_helpers.c | 30 ++++++++++++++++++- .../gpu/drm/amd/display/dc/basics/logger.c | 6 ++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++++- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 3 +- .../amd/display/include/logger_interface.h | 5 ++++ .../drm/amd/display/include/logger_types.h | 1 + 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 64db62e609eb..df4d221e46c1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -322,7 +322,7 @@ bool dm_helpers_dp_mst_send_payload_allocation( return true; } -bool dm_helpers_dc_conn_log(struct dc_context*ctx, const char *msg) +bool dm_helpers_dc_conn_log(struct dc_context *ctx, struct log_entry *entry, enum dc_log_type event) { return true; } diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index 1268be9ebaf3..070ae6f680e1 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -95,7 +95,35 @@ void dc_conn_log(struct dc_context *ctx, dm_logger_append(&entry, "%2.2X ", hex_data[i]); dm_logger_append(&entry, "^\n"); - dm_helpers_dc_conn_log(ctx, entry.buf); + dm_helpers_dc_conn_log(ctx, &entry, event); + dm_logger_close(&entry); + + va_end(args); +} + +void dc_raw_log(struct dc_context *ctx, + enum dc_log_type event, + const char *msg, + ...) +{ + va_list args; + struct log_entry entry = { 0 }; + + dm_logger_open(ctx->logger, &entry, event); + + va_start(args, msg); + entry.buf_offset += dm_log_to_buffer( + &entry.buf[entry.buf_offset], + LOG_MAX_LINE_SIZE - entry.buf_offset, + msg, args); + + if (entry.buf[strlen(entry.buf) - 1] == '\n') { + entry.buf[strlen(entry.buf) - 1] = '\0'; + entry.buf_offset--; + } + + dm_logger_append(&entry, "^\n"); + dm_helpers_dc_conn_log(ctx, &entry, event); dm_logger_close(&entry); va_end(args); diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 4be83703b809..0b17374b1535 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -59,7 +59,8 @@ static const struct dc_log_type_info log_type_info_tbl[] = { {LOG_EVENT_LINK_TRAINING, "LKTN"}, {LOG_EVENT_LINK_LOSS, "LinkLoss"}, {LOG_EVENT_UNDERFLOW, "Underflow"}, - {LOG_IF_TRACE, "InterfaceTrace"} + {LOG_IF_TRACE, "InterfaceTrace"}, + {LOG_DTN, "DTN"} }; @@ -84,7 +85,8 @@ static const struct dc_log_type_info log_type_info_tbl[] = { (1 << LOG_DETECTION_DP_CAPS) | \ (1 << LOG_BACKLIGHT)) | \ (1 << LOG_I2C_AUX) | \ - (1 << LOG_IF_TRACE) /* | \ + (1 << LOG_IF_TRACE) | \ + (1 << LOG_DTN) /* | \ (1 << LOG_DEBUG) | \ (1 << LOG_BIOS) | \ (1 << LOG_SURFACE) | \ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 51e4cb30f858..c113c1a259d4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -944,9 +944,14 @@ bool dc_commit_streams( dc_enable_stereo(dc, context, streams, stream_count); } - CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", + CONN_MSG_MODE(sink->link, "{%ux%u, %ux%u@%u, %ux%u@%uKhz}", + context->streams[i]->public.src.width, + context->streams[i]->public.src.height, context->streams[i]->public.timing.h_addressable, context->streams[i]->public.timing.v_addressable, + context->streams[i]->public.timing.pix_clk_khz * 1000 / + context->streams[i]->public.timing.h_total / + context->streams[i]->public.timing.v_total, // Refresh rate context->streams[i]->public.timing.h_total, context->streams[i]->public.timing.v_total, context->streams[i]->public.timing.pix_clk_khz); diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 9fb606c49217..a831421c7ea0 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -70,7 +70,8 @@ bool dm_helpers_dp_mst_start_top_mgr( bool dm_helpers_dc_conn_log( struct dc_context*ctx, - const char *msg); + struct log_entry *entry, + enum dc_log_type event); void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index b75c343f8680..ce5fef243b09 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -70,6 +70,11 @@ void dc_conn_log(struct dc_context *ctx, const char *msg, ...); +void dc_raw_log(struct dc_context *ctx, + enum dc_log_type event, + const char *msg, + ...); + void logger_write(struct dal_logger *logger, enum dc_log_type log_type, const char *msg, diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index dfc0f102b33d..42ffb93e3172 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -37,6 +37,7 @@ enum dc_log_type { LOG_WARNING, LOG_DEBUG, LOG_DC, + LOG_DTN, LOG_SURFACE, LOG_HW_HOTPLUG, LOG_HW_LINK_TRAINING, -- GitLab From b1a4eb992c1712981f36bb0213879c426d524f76 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 26 Jun 2017 15:13:18 -0400 Subject: [PATCH 0584/2898] drm/amd/display: enable diags compilation Signed-off-by: Dmytro Laktyushkin Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 8 +--- .../gpu/drm/amd/display/dc/dce/dce_clocks.h | 41 +++---------------- .../amd/display/dc/dce120/dce120_resource.c | 17 +------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 22 ++-------- .../amd/display/dc/dcn10/dcn10_transform.h | 23 ++++++----- drivers/gpu/drm/amd/display/dc/inc/resource.h | 1 + 6 files changed, 27 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 4e3f4e5e46a0..f30cd4dff554 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -781,11 +781,7 @@ struct display_clock *dce112_disp_clk_create( return &clk_dce->base; } -struct display_clock *dce120_disp_clk_create( - struct dc_context *ctx, - const struct dce_disp_clk_registers *regs, - const struct dce_disp_clk_shift *clk_shift, - const struct dce_disp_clk_mask *clk_mask) +struct display_clock *dce120_disp_clk_create(struct dc_context *ctx) { struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); struct dm_pp_clock_levels_with_voltage clk_level_info = {0}; @@ -800,7 +796,7 @@ struct display_clock *dce120_disp_clk_create( sizeof(dce120_max_clks_by_state)); dce_disp_clk_construct( - clk_dce, ctx, regs, clk_shift, clk_mask); + clk_dce, ctx, NULL, NULL, NULL); clk_dce->base.funcs = &dce120_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h index 103e905291a3..0e717e0dc8f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h @@ -31,55 +31,30 @@ #define CLK_COMMON_REG_LIST_DCE_BASE() \ .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ - .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL, \ - .MASTER_COMM_DATA_REG1 = mmMASTER_COMM_DATA_REG1, \ - .MASTER_COMM_CMD_REG = mmMASTER_COMM_CMD_REG, \ - .MASTER_COMM_CNTL_REG = mmMASTER_COMM_CNTL_REG + .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL #define CLK_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix #define CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ - CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ - CLK_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ - CLK_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#define CLK_DCN10_REG_LIST()\ - SR(DPREFCLK_CNTL), \ - SR(DENTIST_DISPCLK_CNTL), \ - SR(MASTER_COMM_DATA_REG1), \ - SR(MASTER_COMM_CMD_REG), \ - SR(MASTER_COMM_CNTL_REG) -#endif - -#define CLK_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ - CLK_SF(DCCG_DFS_DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ - CLK_SF(DCCG_DFS_DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh), \ - CLK_SF(DCCG_DFS_MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ - CLK_SF(DCCG_DFS_MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) + CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh) #define CLK_REG_FIELD_LIST(type) \ type DPREFCLK_SRC_SEL; \ - type DENTIST_DPREFCLK_WDIVIDER; \ - type MASTER_COMM_CMD_REG_BYTE0; \ - type MASTER_COMM_INTERRUPT + type DENTIST_DPREFCLK_WDIVIDER; struct dce_disp_clk_shift { - CLK_REG_FIELD_LIST(uint8_t); + CLK_REG_FIELD_LIST(uint8_t) }; struct dce_disp_clk_mask { - CLK_REG_FIELD_LIST(uint32_t); + CLK_REG_FIELD_LIST(uint32_t) }; struct dce_disp_clk_registers { uint32_t DPREFCLK_CNTL; uint32_t DENTIST_DISPCLK_CNTL; - uint32_t MASTER_COMM_DATA_REG1; - uint32_t MASTER_COMM_CMD_REG; - uint32_t MASTER_COMM_CNTL_REG; }; /* Array identifiers and count for the divider ranges.*/ @@ -155,11 +130,7 @@ struct display_clock *dce112_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask); -struct display_clock *dce120_disp_clk_create( - struct dc_context *ctx, - const struct dce_disp_clk_registers *regs, - const struct dce_disp_clk_shift *clk_shift, - const struct dce_disp_clk_mask *clk_mask); +struct display_clock *dce120_disp_clk_create(struct dc_context *ctx); void dce_disp_clk_destroy(struct display_clock **disp_clk); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index ec485353ea4f..82481247a812 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -137,18 +137,6 @@ static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { * end *********************/ -static const struct dce_disp_clk_registers disp_clk_regs = { - CLK_COMMON_REG_LIST_DCE_BASE() -}; - -static const struct dce_disp_clk_shift disp_clk_shift = { - CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_disp_clk_mask disp_clk_mask = { - CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - static const struct dce_dmcu_registers dmcu_regs = { DMCU_DCE110_COMMON_REG_LIST() }; @@ -904,10 +892,7 @@ static bool construct( } } - pool->base.display_clock = dce120_disp_clk_create(ctx, - &disp_clk_regs, - &disp_clk_shift, - &disp_clk_mask); + pool->base.display_clock = dce120_disp_clk_create(ctx); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index eebaffca8e75..a0dd75dc1c6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -136,17 +136,6 @@ enum dcn10_clk_src_array_id { /* macros to expend register list macro defined in HW object header file * end *********************/ -static const struct dce_disp_clk_registers disp_clk_regs = { - CLK_DCN10_REG_LIST() -}; - -static const struct dce_disp_clk_shift disp_clk_shift = { - CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_disp_clk_mask disp_clk_mask = { - CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; static const struct dce_dmcu_registers dmcu_regs = { DMCU_DCN10_REG_LIST() @@ -317,7 +306,7 @@ static const struct dcn10_opp_mask opp_mask = { #define tf_regs(id)\ [id] = {\ - TF_REG_LIST_DCN(id),\ + TF_REG_LIST_DCN10(id),\ } static const struct dcn_transform_registers tf_regs[] = { @@ -328,11 +317,11 @@ static const struct dcn_transform_registers tf_regs[] = { }; static const struct dcn_transform_shift tf_shift = { - TF_REG_LIST_SH_MASK_DCN(__SHIFT) + TF_REG_LIST_SH_MASK_DCN10(__SHIFT) }; static const struct dcn_transform_mask tf_mask = { - TF_REG_LIST_SH_MASK_DCN(_MASK), + TF_REG_LIST_SH_MASK_DCN10(_MASK), }; @@ -1338,10 +1327,7 @@ static bool construct( } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - pool->base.display_clock = dce120_disp_clk_create(ctx, - &disp_clk_regs, - &disp_clk_shift, - &disp_clk_mask); + pool->base.display_clock = dce120_disp_clk_create(ctx); if (pool->base.display_clock == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h index 7c0089d4293b..cd312bd7055b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h @@ -58,7 +58,6 @@ SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ - SRI(CM_GAMUT_REMAP_CONTROL, CM, id), \ SRI(MPC_SIZE, DSCL, id), \ SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ @@ -71,7 +70,10 @@ SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ SRI(RECOUT_START, DSCL, id), \ - SRI(RECOUT_SIZE, DSCL, id), \ + SRI(RECOUT_SIZE, DSCL, id) + +#define TF_REG_LIST_DCN10(id) \ + TF_REG_LIST_DCN(id), \ SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ @@ -92,8 +94,6 @@ SRI(CM_COMB_C31_C32, CM, id),\ SRI(CM_COMB_C33_C34, CM, id) - - #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ @@ -103,11 +103,6 @@ TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, ALPHA_EN, mask_sh),\ TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ @@ -172,7 +167,15 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ - TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh) + +#define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ + TF_REG_LIST_SH_MASK_DCN(mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 7cac24d4ae86..04e5fd1d8c89 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -42,6 +42,7 @@ struct resource_caps { int num_audio; int num_stream_encoder; int num_pll; + int num_dwb; }; struct resource_straps { -- GitLab From 1c604cd862d4f069cb3bbafb4e35db614a57b096 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 14:27:18 -0400 Subject: [PATCH 0585/2898] drm/amd/display: Change max OPP Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index fff267455a3d..6a90a8bc09f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -30,7 +30,7 @@ #define TO_DCN10_MPCC(mpcc_base) \ container_of(mpcc_base, struct dcn10_mpcc, base) -#define MAX_OPP 4 +#define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ SRII(MUX, MPC_OUT, inst),\ -- GitLab From abe07e80836fb25a5bcfda573413a68be82439c6 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Wed, 28 Jun 2017 17:21:42 -0400 Subject: [PATCH 0586/2898] drm/amd/display: Add DC interface for custom CSC matrix Signed-off-by: Yue Hin Lau Reviewed-by: Vitaly Prosyak Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 ++++ drivers/gpu/drm/amd/display/dc/dc.h | 3 + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 23 ++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 117 +++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 76 ++++++++++++ .../amd/display/dc/dcn10/dcn10_transform.c | 5 +- .../gpu/drm/amd/display/dc/inc/hw/transform.h | 1 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 + 8 files changed, 252 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c113c1a259d4..a9ddd0756b3b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -221,6 +221,29 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) return ret; } +static bool program_csc_matrix(struct dc *dc, const struct dc_stream *stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + int i = 0; + bool ret = false; + struct pipe_ctx *pipes; + + for (i = 0; i < MAX_PIPES; i++) { + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + == core_stream) { + + pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; + core_dc->hwss.program_csc_matrix(pipes, + core_stream->public.output_color_space, + core_stream->public.csc_color_matrix.matrix); + ret = true; + } + } + + return ret; +} + static void set_static_screen_events(struct dc *dc, const struct dc_stream **stream, int num_streams, @@ -373,6 +396,9 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) core_dc->public.stream_funcs.set_gamut_remap = set_gamut_remap; + core_dc->public.stream_funcs.program_csc_matrix = + program_csc_matrix; + core_dc->public.stream_funcs.set_dither_option = set_dither_option; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 18f6858e4992..3e2ed3d15379 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -118,6 +118,9 @@ struct dc_stream_funcs { bool (*set_gamut_remap)(struct dc *dc, const struct dc_stream *stream); + bool (*program_csc_matrix)(struct dc *dc, + const struct dc_stream *stream); + void (*set_static_screen_events)(struct dc *dc, const struct dc_stream **stream, int num_streams, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d0bddfd64c67..f404e4e5e4ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1623,6 +1623,28 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); } + +static void program_csc_matrix(struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix) +{ + int i; + struct out_csc_color_matrix tbl_entry; + + if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + == true) { + enum dc_color_space color_space = + pipe_ctx->stream->public.output_color_space; + + //uint16_t matrix[12]; + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + + tbl_entry.color_space = color_space; + //tbl_entry.regval = matrix; + pipe_ctx->opp->funcs->opp_set_csc_adjustment(pipe_ctx->opp, &tbl_entry); + } +} static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { if (pipe_ctx->surface->public.visible) @@ -2103,6 +2125,7 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, + .program_csc_matrix = program_csc_matrix, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 148e192f5f76..a07401004f44 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -713,6 +713,48 @@ static void opp_power_on_regamma_lut( } +void opp_set_output_csc_adjustment( + struct output_pixel_processor *opp, + const struct out_csc_color_matrix *tbl_entry) +{ + + struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); + //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + + uint32_t ocsc_mode = 4; + + /** + *if (tbl_entry != NULL) { + * switch (tbl_entry->color_space) { + * case COLOR_SPACE_SRGB: + * case COLOR_SPACE_2020_RGB_FULLRANGE: + * ocsc_mode = 0; + * break; + * case COLOR_SPACE_SRGB_LIMITED: + * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + * ocsc_mode = 1; + * break; + * case COLOR_SPACE_YCBCR601: + * case COLOR_SPACE_YCBCR601_LIMITED: + * ocsc_mode = 2; + * break; + * case COLOR_SPACE_YCBCR709: + * case COLOR_SPACE_YCBCR709_LIMITED: + * case COLOR_SPACE_2020_YCBCR: + * ocsc_mode = 3; + * break; + * case COLOR_SPACE_UNKNOWN: + * default: + * break; + * } + *} + */ + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + program_color_matrix(oppn10, tbl_entry); +} + static void opp_program_regamma_lut( struct output_pixel_processor *opp, const struct pwl_result_data *rgb, @@ -736,6 +778,8 @@ static void opp_program_regamma_lut( } + + static bool opp_set_regamma_pwl( struct output_pixel_processor *opp, const struct pwl_params *params) { @@ -776,7 +820,7 @@ static void dcn10_opp_destroy(struct output_pixel_processor **opp) static struct opp_funcs dcn10_opp_funcs = { .opp_power_on_regamma_lut = opp_power_on_regamma_lut, - .opp_set_csc_adjustment = NULL, + .opp_set_csc_adjustment = opp_set_output_csc_adjustment, .opp_set_csc_default = opp_set_output_csc_default, .opp_set_dyn_expansion = opp_set_dyn_expansion, .opp_program_regamma_pwl = opp_set_regamma_pwl, @@ -802,3 +846,74 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, oppn10->opp_shift = opp_shift; oppn10->opp_mask = opp_mask; } + + +void program_color_matrix(struct dcn10_opp *oppn10, + const struct out_csc_color_matrix *tbl_entry) +{ + uint32_t mode; + + REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); + + if (tbl_entry == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + + if (mode == 4) { + /*R*/ + REG_SET_2(CM_OCSC_C11_C12, 0, + CM_OCSC_C11, tbl_entry->regval[0], + CM_OCSC_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_OCSC_C13_C14, 0, + CM_OCSC_C13, tbl_entry->regval[2], + CM_OCSC_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_OCSC_C21_C22, 0, + CM_OCSC_C21, tbl_entry->regval[4], + CM_OCSC_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_OCSC_C23_C24, 0, + CM_OCSC_C23, tbl_entry->regval[6], + CM_OCSC_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_OCSC_C31_C32, 0, + CM_OCSC_C31, tbl_entry->regval[8], + CM_OCSC_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_OCSC_C33_C34, 0, + CM_OCSC_C33, tbl_entry->regval[10], + CM_OCSC_C34, tbl_entry->regval[11]); + } else { + /*R*/ + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, tbl_entry->regval[0], + CM_COMB_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, tbl_entry->regval[2], + CM_COMB_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, tbl_entry->regval[4], + CM_COMB_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, tbl_entry->regval[6], + CM_COMB_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, tbl_entry->regval[8], + CM_COMB_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, tbl_entry->regval[10], + CM_COMB_C34, tbl_entry->regval[11]); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index 113e0bc349c3..9cc4c5feaddf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -34,6 +34,18 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define OPP_DCN10_REG_LIST(id) \ + SRI(CM_OCSC_C11_C12, CM, id), \ + SRI(CM_OCSC_C13_C14, CM, id), \ + SRI(CM_OCSC_C21_C22, CM, id), \ + SRI(CM_OCSC_C23_C24, CM, id), \ + SRI(CM_OCSC_C31_C32, CM, id), \ + SRI(CM_OCSC_C33_C34, CM, id), \ + SRI(CM_COMB_C11_C12, CM, id), \ + SRI(CM_COMB_C13_C14, CM, id), \ + SRI(CM_COMB_C21_C22, CM, id), \ + SRI(CM_COMB_C23_C24, CM, id), \ + SRI(CM_COMB_C31_C32, CM, id), \ + SRI(CM_COMB_C33_C34, CM, id), \ SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id), \ SRI(OBUF_CONTROL, DSCL, id), \ @@ -109,6 +121,30 @@ SRI(CM_RGAM_LUT_DATA, CM, id) #define OPP_DCN10_MASK_SH_LIST(mask_sh) \ + OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C14, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C21, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C22, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C23, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C24, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ + OPP_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ + OPP_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh), \ + OPP_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh), \ + OPP_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh), \ + OPP_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh), \ + OPP_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh), \ + OPP_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh), \ + OPP_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh), \ + OPP_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh), \ + OPP_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh), \ + OPP_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh), \ + OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh), \ + OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh), \ OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ @@ -314,6 +350,30 @@ OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ + type CM_OCSC_C11; \ + type CM_OCSC_C12; \ + type CM_OCSC_C13; \ + type CM_OCSC_C14; \ + type CM_OCSC_C21; \ + type CM_OCSC_C22; \ + type CM_OCSC_C23; \ + type CM_OCSC_C24; \ + type CM_OCSC_C31; \ + type CM_OCSC_C32; \ + type CM_OCSC_C33; \ + type CM_OCSC_C34; \ + type CM_COMB_C11; \ + type CM_COMB_C12; \ + type CM_COMB_C13; \ + type CM_COMB_C14; \ + type CM_COMB_C21; \ + type CM_COMB_C22; \ + type CM_COMB_C23; \ + type CM_COMB_C24; \ + type CM_COMB_C31; \ + type CM_COMB_C32; \ + type CM_COMB_C33; \ + type CM_COMB_C34; \ type CM_RGAM_LUT_MODE; \ type OBUF_BYPASS; \ type OBUF_H_2X_UPSCALE_EN; \ @@ -527,6 +587,18 @@ struct dcn10_opp_mask { }; struct dcn10_opp_registers { + uint32_t CM_OCSC_C11_C12; + uint32_t CM_OCSC_C13_C14; + uint32_t CM_OCSC_C21_C22; + uint32_t CM_OCSC_C23_C24; + uint32_t CM_OCSC_C31_C32; + uint32_t CM_OCSC_C33_C34; + uint32_t CM_COMB_C11_C12; + uint32_t CM_COMB_C13_C14; + uint32_t CM_COMB_C21_C22; + uint32_t CM_COMB_C23_C24; + uint32_t CM_COMB_C31_C32; + uint32_t CM_COMB_C33_C34; uint32_t CM_RGAM_LUT_WRITE_EN_MASK; uint32_t CM_RGAM_CONTROL; uint32_t OBUF_CONTROL; @@ -619,4 +691,8 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask); +void program_color_matrix( + struct dcn10_opp *oppn10, + const struct out_csc_color_matrix *tbl_entry); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index d9815a991682..92322b75d868 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -1027,9 +1027,8 @@ static struct transform_funcs dcn10_transform_funcs = { .transform_reset = transform_reset, .transform_set_scaler = transform_set_scaler_manual_scale, - .transform_get_optimal_number_of_taps = - transform_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn_transform_set_gamut_remap + .transform_get_optimal_number_of_taps = transform_get_optimal_number_of_taps, + .transform_set_gamut_remap = dcn_transform_set_gamut_remap, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 8325a0a47179..b4862c376b41 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -180,6 +180,7 @@ struct transform_funcs { struct transform *xfm, const struct xfm_grph_csc_adjustment *adjust); + void (*transform_set_pixel_storage_depth)( struct transform *xfm, enum lb_pixel_depth depth, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 642ae5e4ee1c..97dbd259f66c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -70,6 +70,11 @@ struct hw_sequencer_funcs { void (*program_gamut_remap)( struct pipe_ctx *pipe_ctx); + void (*program_csc_matrix)( + struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix); + void (*update_plane_addr)( const struct core_dc *dc, struct pipe_ctx *pipe_ctx); -- GitLab From 1a87fbfee0a0f96e8b482c2ac7eae113c9ca2497 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Wed, 28 Jun 2017 18:14:09 -0400 Subject: [PATCH 0587/2898] drm/amd/display: Re-enable Vsync Interrupts for Gradual Refresh Ramp - Make sure Vsync interrupts are disabled in static screen case and enabled when not to save power - Create no_static_for_external_dp debug option Signed-off-by: Amy Zhang Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/modules/freesync/freesync.c | 38 ++++++++++++++----- .../amd/display/modules/inc/mod_freesync.h | 5 +++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3e2ed3d15379..93aff8269778 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -188,6 +188,7 @@ struct dc_debug { bool disable_dmcu; bool disable_psr; bool force_abm_enable; + bool no_static_for_external_dp; }; struct dc { diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index c7da90f2d8e7..4df79f7147f8 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -440,14 +440,11 @@ static void calc_freesync_range(struct core_freesync *core_freesync, } /* Determine whether BTR can be supported */ - //if (max_frame_duration_in_ns >= - // 2 * min_frame_duration_in_ns) - // core_freesync->map[index].caps->btr_supported = true; - //else - // core_freesync->map[index].caps->btr_supported = false; - - /* Temp, keep btr disabled */ - core_freesync->map[index].caps->btr_supported = false; + if (max_frame_duration_in_ns >= + 2 * min_frame_duration_in_ns) + core_freesync->map[index].caps->btr_supported = true; + else + core_freesync->map[index].caps->btr_supported = false; /* Cache the time variables */ state->time.max_render_time_in_us = @@ -882,8 +879,10 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, * panels. Also change core variables only if there * is a change. */ - if (dc_is_embedded_signal( - streams[stream_index]->sink->sink_signal) && + if ((dc_is_embedded_signal( + streams[stream_index]->sink->sink_signal) || + core_freesync->map[map_index].caps-> + no_static_for_external_dp == false) && state->static_screen != freesync_params->enable) { @@ -1035,6 +1034,25 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, return true; } +bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + bool *is_ramp_active) +{ + unsigned int index = 0; + struct core_freesync *core_freesync = NULL; + + if (mod_freesync == NULL) + return false; + + core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); + index = map_index_from_stream(core_freesync, stream); + + *is_ramp_active = + core_freesync->map[index].state.static_ramp.ramp_is_active; + + return true; +} + bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *streams, unsigned int min_refresh, diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index f7f5a2cd7914..eae1b348b0dd 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -88,6 +88,7 @@ struct mod_freesync_caps { unsigned int max_refresh_in_micro_hz; bool btr_supported; + bool no_static_for_external_dp; }; struct mod_freesync_params { @@ -129,6 +130,10 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, const struct dc_stream *stream, struct mod_freesync_user_enable *user_enable); +bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, + const struct dc_stream *stream, + bool *is_ramp_active); + bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, const struct dc_stream *streams, unsigned int min_refresh, -- GitLab From 46239f739aa64c797938e9a14b03fd2c1b8ce0e6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 29 Jun 2017 20:25:23 -0400 Subject: [PATCH 0588/2898] drm/amd/display: Enabling VSR on 4K display causes black screen Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f404e4e5e4ea..cc67707b56d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1819,7 +1819,7 @@ static void program_all_pipe_in_tree( pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); } - if (pipe_ctx->surface->public.visible) { + if (pipe_ctx->surface != NULL) { dcn10_power_on_fe(dc, pipe_ctx, context); update_dchubp_dpp(dc, pipe_ctx, context); } -- GitLab From cdc5e04888cec337e44049f9b51d8894364ad52a Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Wed, 28 Jun 2017 13:36:25 -0500 Subject: [PATCH 0589/2898] drm/amd/display: Fix for hdmi frame pack stereo Signed-off-by: Vitaly Prosyak Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 10 +++++++++- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 11 ++++++++--- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 00961bc37200..4486121e3986 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -987,7 +987,15 @@ bool dcn_validate_bandwidth( if (pipe->surface) { struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; - if (v->dpp_per_plane[input_idx] == 2) { + if (v->dpp_per_plane[input_idx] == 2 || + ((pipe->stream->public.view_format == + VIEW_3D_FORMAT_SIDE_BY_SIDE || + pipe->stream->public.view_format == + VIEW_3D_FORMAT_TOP_AND_BOTTOM) && + (pipe->stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM || + pipe->stream->public.timing.timing_3d_format == + TIMING_3D_FORMAT_SIDE_BY_SIDE))) { if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { /* update previously split pipe */ hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a9ddd0756b3b..1d2e421e8d0a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -967,7 +967,6 @@ bool dc_commit_streams( DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); - dc_enable_stereo(dc, context, streams, stream_count); } CONN_MSG_MODE(sink->link, "{%ux%u, %ux%u@%u, %ux%u@%uKhz}", @@ -982,7 +981,7 @@ bool dc_commit_streams( context->streams[i]->public.timing.v_total, context->streams[i]->public.timing.pix_clk_khz); } - + dc_enable_stereo(dc, context, streams, stream_count); dc_resource_validate_ctx_destruct(core_dc->current_context); dm_free(core_dc->current_context); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fb033b69e2bf..ddf032214dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -626,7 +626,7 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) if (stream->public.view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) pipe_ctx->scl_data.ratios.horz.value *= 2; - else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM) + else if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.ratios.vert.value *= 2; pipe_ctx->scl_data.ratios.vert.value = div64_s64( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index cc67707b56d0..d38570e6d4d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -891,7 +891,6 @@ static void reset_hw_ctx_wrap( } } - static bool patch_address_for_sbs_tb_stereo( struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { @@ -904,11 +903,17 @@ static bool patch_address_for_sbs_tb_stereo( pipe_ctx->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { *addr = surface->public.address.grph_stereo.left_addr; - surface->public.address.grph_stereo.left_addr =\ + surface->public.address.grph_stereo.left_addr = surface->public.address.grph_stereo.right_addr; return true; + } else { + if (pipe_ctx->stream->public.view_format != VIEW_3D_FORMAT_NONE && + surface->public.address.type != PLN_ADDR_TYPE_GRPH_STEREO) { + surface->public.address.type = PLN_ADDR_TYPE_GRPH_STEREO; + surface->public.address.grph_stereo.right_addr = + surface->public.address.grph_stereo.left_addr; + } } - return false; } -- GitLab From c3aa1d67295c8fc87364dfe8920c9e30775fd124 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 30 Jun 2017 15:19:55 -0400 Subject: [PATCH 0590/2898] drm/amd/display: Set static screen register for stoney/carrizo -Set CRTC_STATIC_SCREEN_EVENT for stoney/carrizo for FBC implementation -Code is currently guarded with "ENABLE_FBC" compile time flag Signed-off-by: Bhawanpreet Lakha Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 72d5f753949d..8778af76f4e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1395,6 +1395,10 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, if (events->cursor_update) value |= 0x2; +#ifdef ENABLE_FBC + value |= 0x84; +#endif + for (i = 0; i < num_pipes; i++) pipe_ctx[i]->tg->funcs-> set_static_screen_control(pipe_ctx[i]->tg, value); -- GitLab From 62a3213aca0bf519457545f22c41154a4848e390 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 14:33:29 -0400 Subject: [PATCH 0591/2898] drm/amd/display: Rename DCN TG specific function prefixes to tg Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dcn10/dcn10_timing_generator.c | 159 ++++++++---------- .../display/dc/dcn10/dcn10_timing_generator.h | 53 +++--- 2 files changed, 94 insertions(+), 118 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 802ace2e5212..5927478b9044 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -44,7 +44,7 @@ * This is a workaround for a bug that has existed since R5xx and has not been * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive. */ -static void tg_apply_front_porch_workaround( +static void tgn10_apply_front_porch_workaround( struct timing_generator *tg, struct dc_crtc_timing *timing) { @@ -57,7 +57,7 @@ static void tg_apply_front_porch_workaround( } } -static void dcn10_program_global_sync( +static void tgn10_program_global_sync( struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -78,7 +78,7 @@ static void dcn10_program_global_sync( VREADY_OFFSET, tg->dlg_otg_param.vready_offset); } -static void dcn10_disable_stereo(struct timing_generator *tg) +static void tgn10_disable_stereo(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -101,9 +101,10 @@ static void dcn10_disable_stereo(struct timing_generator *tg) * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. * Including SYNC. Call BIOS command table to program Timings. */ -static void tg_program_timing_generator( +static void tgn10_program_timing( struct timing_generator *tg, - const struct dc_crtc_timing *dc_crtc_timing) + const struct dc_crtc_timing *dc_crtc_timing, + bool use_vbios) { struct dc_crtc_timing patched_crtc_timing; uint32_t vesa_sync_start; @@ -118,11 +119,10 @@ static void tg_program_timing_generator( uint32_t field_num = 0; uint32_t h_div_2; - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); patched_crtc_timing = *dc_crtc_timing; - tg_apply_front_porch_workaround(tg, &patched_crtc_timing); + tgn10_apply_front_porch_workaround(tg, &patched_crtc_timing); /* Load horizontal timing */ @@ -253,7 +253,7 @@ static void tg_program_timing_generator( OTG_START_POINT_CNTL, start_point, OTG_FIELD_NUMBER_CNTL, field_num); - dcn10_program_global_sync(tg); + tgn10_program_global_sync(tg); /* TODO * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 @@ -273,25 +273,11 @@ static void tg_program_timing_generator( } -/** tg_program_blanking - * Only programmed part of OTG_H, OTG_V register for set_plane_config - * Assume other OTG registers are programmed by video mode set already. - * This function is for underlay. DCN will have new sequence. - * This function will be removed. Need remove it from set_plane_config - */ - -static void tg_program_timing(struct timing_generator *tg, - const struct dc_crtc_timing *timing, - bool use_vbios) -{ - tg_program_timing_generator(tg, timing); -} - /** * unblank_crtc * Call ASIC Control Object to UnBlank CRTC. */ -static void tg_unblank_crtc(struct timing_generator *tg) +static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -305,7 +291,7 @@ static void tg_unblank_crtc(struct timing_generator *tg) * Call ASIC Control Object to Blank CRTC. */ -static void tg_blank_crtc(struct timing_generator *tg) +static void tgn10_blank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -324,16 +310,16 @@ static void tg_blank_crtc(struct timing_generator *tg) OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 0); } -static void tg_set_blank(struct timing_generator *tg, +static void tgn10_set_blank(struct timing_generator *tg, bool enable_blanking) { if (enable_blanking) - tg_blank_crtc(tg); + tgn10_blank_crtc(tg); else - tg_unblank_crtc(tg); + tgn10_unblank_crtc(tg); } -static bool tg_is_blanked(struct timing_generator *tg) +static bool tgn10_is_blanked(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); uint32_t blank_en; @@ -346,7 +332,7 @@ static bool tg_is_blanked(struct timing_generator *tg) return blank_en && blank_state; } -static void enable_optc_clock(struct timing_generator *tg, bool enable) +static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -388,7 +374,7 @@ static void enable_optc_clock(struct timing_generator *tg, bool enable) * Enable CRTC * Enable CRTC - call ASIC Control Object to enable Timing generator. */ -static bool tg_enable_crtc(struct timing_generator *tg) +static bool tgn10_enable_crtc(struct timing_generator *tg) { /* TODO FPGA wait for answer * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE @@ -415,7 +401,7 @@ static bool tg_enable_crtc(struct timing_generator *tg) } /* disable_crtc - call ASIC Control Object to disable Timing generator. */ -static bool tg_disable_crtc(struct timing_generator *tg) +static bool tgn10_disable_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -438,7 +424,7 @@ static bool tg_disable_crtc(struct timing_generator *tg) } -static void tg_program_blank_color( +static void tgn10_program_blank_color( struct timing_generator *tg, const struct tg_color *black_color) { @@ -464,7 +450,7 @@ static void tg_program_blank_color( * We may move init_hw into DC specific so that we can remove * .disable_vga from upper layer stack */ -static void dcn10_timing_generator_disable_vga( +static void tgn10_disable_vga( struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -487,7 +473,7 @@ static void dcn10_timing_generator_disable_vga( } } -static bool tg_validate_timing( +static bool tgn10_validate_timing( struct timing_generator *tg, const struct dc_crtc_timing *timing) { @@ -560,7 +546,7 @@ static bool tg_validate_timing( * @return * Counter of frames, which should equal to number of vblanks. */ -static uint32_t tg_get_vblank_counter(struct timing_generator *tg) +static uint32_t tgn10_get_vblank_counter(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); uint32_t frame_count; @@ -571,7 +557,7 @@ static uint32_t tg_get_vblank_counter(struct timing_generator *tg) return frame_count; } -void dcn10_lock(struct timing_generator *tg) +static void tgn10_lock(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -581,7 +567,7 @@ void dcn10_lock(struct timing_generator *tg) OTG_MASTER_UPDATE_LOCK, 1); } -void dcn10_unlock(struct timing_generator *tg) +static void tgn10_unlock(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -594,7 +580,7 @@ void dcn10_unlock(struct timing_generator *tg) 20000, 200000);*/ } -static void dcn10_get_position(struct timing_generator *tg, +static void tgn10_get_position(struct timing_generator *tg, struct crtc_position *position) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -607,7 +593,7 @@ static void dcn10_get_position(struct timing_generator *tg, OTG_VERT_COUNT_NOM, &position->nominal_vcount); } -bool dcn10_is_counter_moving(struct timing_generator *tg) +static bool tgn10_is_counter_moving(struct timing_generator *tg) { struct crtc_position position1, position2; @@ -621,7 +607,7 @@ bool dcn10_is_counter_moving(struct timing_generator *tg) return true; } -static bool dcn10_did_triggered_reset_occur( +static bool tgn10_did_triggered_reset_occur( struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -633,7 +619,7 @@ static bool dcn10_did_triggered_reset_occur( return occurred != 0; } -static void dcn10_enable_reset_trigger(struct timing_generator *tg, int source_tg_inst) +static void tgn10_enable_reset_trigger(struct timing_generator *tg, int source_tg_inst) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); uint32_t falling_edge; @@ -667,7 +653,7 @@ static void dcn10_enable_reset_trigger(struct timing_generator *tg, int source_t OTG_FORCE_COUNT_NOW_MODE, 2); } -static void dcn10_disable_reset_trigger(struct timing_generator *tg) +static void tgn10_disable_reset_trigger(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -677,7 +663,7 @@ static void dcn10_disable_reset_trigger(struct timing_generator *tg) OTG_FORCE_COUNT_NOW_CLEAR, 1); } -static void dcn10_wait_for_state(struct timing_generator *tg, +static void tgn10_wait_for_state(struct timing_generator *tg, enum crtc_state state) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -700,7 +686,7 @@ static void dcn10_wait_for_state(struct timing_generator *tg, } } -static void set_early_control( +static void tgn10_set_early_control( struct timing_generator *tg, uint32_t early_cntl) { @@ -710,7 +696,7 @@ static void set_early_control( } -static void set_static_screen_control( +static void tgn10_set_static_screen_control( struct timing_generator *tg, uint32_t value) { @@ -739,7 +725,7 @@ static void set_static_screen_control( * ***************************************************************************** */ -void dcn10_timing_generator_set_drr( +static void tgn10_set_drr( struct timing_generator *tg, const struct drr_params *params) { @@ -776,7 +762,7 @@ void dcn10_timing_generator_set_drr( } } -static void dcn10_timing_generator_set_test_pattern( +static void tgn10_set_test_pattern( struct timing_generator *tg, /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' * because this is not DP-specific (which is probably somewhere in DP @@ -1035,7 +1021,7 @@ static void dcn10_timing_generator_set_test_pattern( } } -void dcn10_timing_generator_get_crtc_scanoutpos( +static void tgn10_get_crtc_scanoutpos( struct timing_generator *tg, uint32_t *v_blank_start, uint32_t *v_blank_end, @@ -1049,7 +1035,7 @@ void dcn10_timing_generator_get_crtc_scanoutpos( OTG_V_BLANK_START, v_blank_start, OTG_V_BLANK_END, v_blank_end); - dcn10_get_position(tg, &position); + tgn10_get_position(tg, &position); *h_position = position.horizontal_count; *v_position = position.vertical_count; @@ -1057,7 +1043,7 @@ void dcn10_timing_generator_get_crtc_scanoutpos( -static void dcn10_enable_stereo(struct timing_generator *tg, +static void tgn10_enable_stereo(struct timing_generator *tg, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -1099,17 +1085,17 @@ static void dcn10_enable_stereo(struct timing_generator *tg, OPPBUF_3D_VACT_SPACE1_SIZE, space1_size); } -static void dcn10_program_stereo(struct timing_generator *tg, +static void tgn10_program_stereo(struct timing_generator *tg, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) { if (flags->PROGRAM_STEREO) - dcn10_enable_stereo(tg, timing, flags); + tgn10_enable_stereo(tg, timing, flags); else - dcn10_disable_stereo(tg); + tgn10_disable_stereo(tg); } -static bool dcn10_is_stereo_left_eye(struct timing_generator *tg) +static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) { bool ret = false; uint32_t left_eye = 0; @@ -1126,46 +1112,34 @@ static bool dcn10_is_stereo_left_eye(struct timing_generator *tg) } static struct timing_generator_funcs dcn10_tg_funcs = { - .validate_timing = tg_validate_timing, - .program_timing = tg_program_timing, - .program_global_sync = dcn10_program_global_sync, - .enable_crtc = tg_enable_crtc, - .disable_crtc = tg_disable_crtc, + .validate_timing = tgn10_validate_timing, + .program_timing = tgn10_program_timing, + .program_global_sync = tgn10_program_global_sync, + .enable_crtc = tgn10_enable_crtc, + .disable_crtc = tgn10_disable_crtc, /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = dcn10_is_counter_moving, - /* never be called */ - .get_position = dcn10_get_position, - .get_frame_count = tg_get_vblank_counter, - .get_scanoutpos = dcn10_timing_generator_get_crtc_scanoutpos, - .set_early_control = set_early_control, + .is_counter_moving = tgn10_is_counter_moving, + .get_position = tgn10_get_position, + .get_frame_count = tgn10_get_vblank_counter, + .get_scanoutpos = tgn10_get_crtc_scanoutpos, + .set_early_control = tgn10_set_early_control, /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = dcn10_wait_for_state, - .set_blank = tg_set_blank, - .is_blanked = tg_is_blanked, - /* never be called */ - .set_colors = NULL, - /* this function will be called by .progam_scaler. dcn and dce - * scaler top level functions are different. .program_scaler is - * not need for dcn. within program_scaler, dcn will return - * early before set_overscan_blank_color is reached - */ - .set_overscan_blank_color = NULL, - .set_blank_color = tg_program_blank_color, - /* dcn10_timing_generator_disable_vga */ - .disable_vga = dcn10_timing_generator_disable_vga, - .did_triggered_reset_occur = dcn10_did_triggered_reset_occur, - .enable_reset_trigger = dcn10_enable_reset_trigger, - .disable_reset_trigger = dcn10_disable_reset_trigger, - .lock = dcn10_lock, - .unlock = dcn10_unlock, - /* dcn10_timing_generator_enable_advanced_request*/ - .enable_advanced_request = NULL, - .enable_optc_clock = enable_optc_clock, - .set_drr = dcn10_timing_generator_set_drr, - .set_static_screen_control = set_static_screen_control, - .set_test_pattern = dcn10_timing_generator_set_test_pattern, - .program_stereo = dcn10_program_stereo, - .is_stereo_left_eye = dcn10_is_stereo_left_eye + .wait_for_state = tgn10_wait_for_state, + .set_blank = tgn10_set_blank, + .is_blanked = tgn10_is_blanked, + .set_blank_color = tgn10_program_blank_color, + .disable_vga = tgn10_disable_vga, + .did_triggered_reset_occur = tgn10_did_triggered_reset_occur, + .enable_reset_trigger = tgn10_enable_reset_trigger, + .disable_reset_trigger = tgn10_disable_reset_trigger, + .lock = tgn10_lock, + .unlock = tgn10_unlock, + .enable_optc_clock = tgn10_enable_optc_clock, + .set_drr = tgn10_set_drr, + .set_static_screen_control = tgn10_set_static_screen_control, + .set_test_pattern = tgn10_set_test_pattern, + .program_stereo = tgn10_program_stereo, + .is_stereo_left_eye = tgn10_is_stereo_left_eye }; void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) @@ -1181,4 +1155,3 @@ void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10) tgn10->min_h_sync_width = 8; tgn10->min_v_sync_width = 1; } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 3b2a20a4b957..e287b2babdc4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -31,7 +31,7 @@ #define DCN10TG_FROM_TG(tg)\ container_of(tg, struct dcn10_timing_generator, base) -#define TG_COMMON_REG_LIST_DCN1_0(inst) \ +#define TG_COMMON_REG_LIST_DCN(inst) \ SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ SRI(OTG_VUPDATE_PARAM, OTG, inst),\ SRI(OTG_VREADY_PARAM, OTG, inst),\ @@ -64,9 +64,6 @@ SRI(OTG_STATUS_POSITION, OTG, inst),\ SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ SRI(OTG_BLACK_COLOR, OTG, inst),\ - SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ - SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ - SRI(OTG_TEST_PATTERN_COLOR, OTG, inst),\ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ @@ -76,7 +73,14 @@ SR(D1VGA_CONTROL),\ SR(D2VGA_CONTROL),\ SR(D3VGA_CONTROL),\ - SR(D4VGA_CONTROL),\ + SR(D4VGA_CONTROL) + +#define TG_COMMON_REG_LIST_DCN1_0(inst) \ + TG_COMMON_REG_LIST_DCN(inst),\ + SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ + SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ + SRI(OTG_TEST_PATTERN_COLOR, OTG, inst) + struct dcn_tg_registers { uint32_t OTG_VSTARTUP_PARAM; @@ -127,7 +131,7 @@ struct dcn_tg_registers { uint32_t D4VGA_CONTROL; }; -#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ +#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ @@ -192,17 +196,6 @@ struct dcn_tg_registers { SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_B_CB, mask_sh),\ SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_G_Y, mask_sh),\ SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_R_CR, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ @@ -210,12 +203,26 @@ struct dcn_tg_registers { SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh),\ SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ - SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh) + +#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh) #define TG_REG_FIELD_LIST(type) \ type VSTARTUP_START;\ @@ -300,11 +307,12 @@ struct dcn_tg_registers { type OPTC_INPUT_CLK_ON;\ type OPTC_INPUT_CLK_GATE_DIS;\ type OPTC_SRC_SEL;\ + type OPTC_SEG0_SRC_SEL;\ type OPPBUF_ACTIVE_WIDTH;\ type OPPBUF_3D_VACT_SPACE1_SIZE;\ type VTG0_ENABLE;\ type VTG0_FP2;\ - type VTG0_VCOUNT_INIT;\ + type VTG0_VCOUNT_INIT; struct dcn_tg_shift { TG_REG_FIELD_LIST(uint8_t) @@ -336,9 +344,4 @@ struct dcn10_timing_generator { void dcn10_timing_generator_init(struct dcn10_timing_generator *tg); -void dcn10_timing_generator_set_drr(struct timing_generator *tg, - const struct drr_params *params); - -void dcn10_unlock(struct timing_generator *tg); -void dcn10_lock(struct timing_generator *tg); #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ -- GitLab From db3bc05034a4b025651ec17d67d50ea581f6612e Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 16:31:58 -0400 Subject: [PATCH 0592/2898] drm/amd/display: Rename DCN mem input specific function prefixes to min. Also updated relevant registers. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_mem_input.c | 96 +++++++++---------- .../amd/display/dc/dcn10/dcn10_mem_input.h | 93 +++++++++++------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 6 +- 3 files changed, 104 insertions(+), 91 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index a58993aa400f..b7ecfad4a8f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -38,7 +38,7 @@ #define FN(reg_name, field_name) \ mi->mi_shift->field_name, mi->mi_mask->field_name -static void dcn_mi_set_blank(struct mem_input *mem_input, bool blank) +static void min10_set_blank(struct mem_input *mem_input, bool blank) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; @@ -48,7 +48,7 @@ static void dcn_mi_set_blank(struct mem_input *mem_input, bool blank) HUBP_TTU_DISABLE, blank_en); } -static void vready_workaround(struct mem_input *mem_input, +static void min10_vready_workaround(struct mem_input *mem_input, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { uint32_t value = 0; @@ -71,7 +71,7 @@ static void vready_workaround(struct mem_input *mem_input, REG_WRITE(HUBPREQ_DEBUG_DB, value); } -static void program_tiling( +static void min10_program_tiling( struct dcn10_mem_input *mi, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) @@ -91,7 +91,7 @@ static void program_tiling( PIPE_ALIGNED, info->gfx9.pipe_aligned); } -static void program_size_and_rotation( +static void min10_program_size_and_rotation( struct dcn10_mem_input *mi, enum dc_rotation_angle rotation, enum surface_pixel_format format, @@ -153,7 +153,7 @@ static void program_size_and_rotation( H_MIRROR_EN, mirror); } -static void program_pixel_format( +static void min10_program_pixel_format( struct dcn10_mem_input *mi, enum surface_pixel_format format) { @@ -229,7 +229,7 @@ static void program_pixel_format( /* don't see the need of program the xbar in DCN 1.0 */ } -static bool mem_input_program_surface_flip_and_addr( +static bool min10_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate) @@ -369,7 +369,7 @@ static bool mem_input_program_surface_flip_and_addr( return true; } -static void dcc_control(struct mem_input *mem_input, bool enable, +static void min10_dcc_control(struct mem_input *mem_input, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; @@ -381,13 +381,7 @@ static void dcc_control(struct mem_input *mem_input, bool enable, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); } -static void program_control(struct dcn10_mem_input *mi, - struct dc_plane_dcc_param *dcc) -{ - dcc_control(&mi->base, dcc->enable, dcc->grph.independent_64b_blks); -} - -static void mem_input_program_surface_config( +static void min10_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -398,14 +392,14 @@ static void mem_input_program_surface_config( { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - program_control(mi, dcc); - program_tiling(mi, tiling_info, format); - program_size_and_rotation( + min10_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); + min10_program_tiling(mi, tiling_info, format); + min10_program_size_and_rotation( mi, rotation, format, plane_size, dcc, horizontal_mirror); - program_pixel_format(mi, format); + min10_program_pixel_format(mi, format); } -static void program_requestor( +static void min10_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs) { @@ -440,7 +434,7 @@ static void program_requestor( } -static void program_deadline( +static void min10_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) @@ -552,7 +546,7 @@ static void program_deadline( ttu_attr->refcyc_per_req_delivery_pre_c); } -static void mem_input_setup( +static void min10_setup( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr, @@ -562,9 +556,9 @@ static void mem_input_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - program_requestor(mem_input, rq_regs); - program_deadline(mem_input, dlg_attr, ttu_attr); - vready_workaround(mem_input, pipe_dest); + min10_program_requestor(mem_input, rq_regs); + min10_program_deadline(mem_input, dlg_attr, ttu_attr); + min10_vready_workaround(mem_input, pipe_dest); } static uint32_t convert_and_clamp( @@ -582,7 +576,7 @@ static uint32_t convert_and_clamp( return ret_val; } -static void program_watermarks( +static void min10_program_watermarks( struct mem_input *mem_input, struct dcn_watermark_set *watermarks, unsigned int refclk_mhz) @@ -811,7 +805,7 @@ static void program_watermarks( #endif } -static void mem_input_program_display_marks( +static void min10_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -823,14 +817,14 @@ static void mem_input_program_display_marks( */ } -bool mem_input_is_flip_pending(struct mem_input *mem_input) +static bool min10_is_flip_pending(struct mem_input *mem_input) { - uint32_t update_pending = 0; + uint32_t flip_pending = 0; struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); struct dc_plane_address earliest_inuse_address; REG_GET(DCSURF_FLIP_CONTROL, - SURFACE_UPDATE_PENDING, &update_pending); + SURFACE_FLIP_PENDING, &flip_pending); REG_GET(DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, &earliest_inuse_address.grph.addr.low_part); @@ -838,7 +832,7 @@ bool mem_input_is_flip_pending(struct mem_input *mem_input) REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &earliest_inuse_address.grph.addr.high_part); - if (update_pending) + if (flip_pending) return true; if (earliest_inuse_address.grph.addr.quad_part != mem_input->request_address.grph.addr.quad_part) @@ -848,7 +842,7 @@ bool mem_input_is_flip_pending(struct mem_input *mem_input) return false; } -static void mem_input_update_dchub( +static void min10_update_dchub( struct mem_input *mem_input, struct dchub_init_data *dh_data) { @@ -911,7 +905,7 @@ struct vm_system_aperture_param { PHYSICAL_ADDRESS_LOC sys_high; }; -static void read_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void min10_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, struct vm_system_aperture_param *apt) { PHYSICAL_ADDRESS_LOC physical_page_number; @@ -934,7 +928,7 @@ static void read_vm_system_aperture_settings(struct dcn10_mem_input *mi, apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; } -static void set_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void min10_set_vm_system_aperture_settings(struct dcn10_mem_input *mi, struct vm_system_aperture_param *apt) { PHYSICAL_ADDRESS_LOC mc_vm_apt_default; @@ -970,7 +964,7 @@ struct vm_context0_param { }; /* Temporary read settings, future will get values from kmd directly */ -static void read_vm_context0_settings(struct dcn10_mem_input *mi, +static void min10_read_vm_context0_settings(struct dcn10_mem_input *mi, struct vm_context0_param *vm0) { PHYSICAL_ADDRESS_LOC fb_base; @@ -1013,7 +1007,7 @@ static void read_vm_context0_settings(struct dcn10_mem_input *mi, vm0->pte_base.quad_part -= fb_offset.quad_part; } -static void set_vm_context0_settings(struct dcn10_mem_input *mi, +static void min10_set_vm_context0_settings(struct dcn10_mem_input *mi, const struct vm_context0_param *vm0) { /* pte base */ @@ -1042,7 +1036,7 @@ static void set_vm_context0_settings(struct dcn10_mem_input *mi, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); } -void dcn_mem_input_program_pte_vm(struct mem_input *mem_input, +static void min10_program_pte_vm(struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation) @@ -1052,11 +1046,11 @@ void dcn_mem_input_program_pte_vm(struct mem_input *mem_input, struct vm_context0_param vm0 = { { { 0 } } }; - read_vm_system_aperture_settings(mi, &apt); - read_vm_context0_settings(mi, &vm0); + min10_read_vm_system_aperture_settings(mi, &apt); + min10_read_vm_context0_settings(mi, &vm0); - set_vm_system_aperture_settings(mi, &apt); - set_vm_context0_settings(mi, &vm0); + min10_set_vm_system_aperture_settings(mi, &apt); + min10_set_vm_context0_settings(mi, &vm0); /* control: enable VM PTE*/ REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, @@ -1065,20 +1059,18 @@ void dcn_mem_input_program_pte_vm(struct mem_input *mem_input, } static struct mem_input_funcs dcn10_mem_input_funcs = { - .mem_input_program_display_marks = mem_input_program_display_marks, - .allocate_mem_input = NULL, - .free_mem_input = NULL, + .mem_input_program_display_marks = min10_program_display_marks, .mem_input_program_surface_flip_and_addr = - mem_input_program_surface_flip_and_addr, + min10_program_surface_flip_and_addr, .mem_input_program_surface_config = - mem_input_program_surface_config, - .mem_input_is_flip_pending = mem_input_is_flip_pending, - .mem_input_setup = mem_input_setup, - .program_watermarks = program_watermarks, - .mem_input_update_dchub = mem_input_update_dchub, - .mem_input_program_pte_vm = dcn_mem_input_program_pte_vm, - .set_blank = dcn_mi_set_blank, - .dcc_control = dcc_control, + min10_program_surface_config, + .mem_input_is_flip_pending = min10_is_flip_pending, + .mem_input_setup = min10_setup, + .program_watermarks = min10_program_watermarks, + .mem_input_update_dchub = min10_update_dchub, + .mem_input_program_pte_vm = min10_program_pte_vm, + .set_blank = min10_set_blank, + .dcc_control = min10_dcc_control, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 9e2f1bb69958..c3f18bdc2157 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -31,7 +31,7 @@ container_of(mi, struct dcn10_mem_input, base) -#define MI_DCN10_REG_LIST(id)\ +#define MI_REG_LIST_DCN(id)\ SRI(DCHUBP_CNTL, HUBP, id),\ SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ SRI(DCSURF_ADDR_CONFIG, HUBP, id),\ @@ -93,27 +93,7 @@ SRI(DCN_SURF0_TTU_CNTL1, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, HUBPREQ, id),\ SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ - SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ - SR(DCHUBBUB_SDPIF_FB_TOP),\ - SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET),\ - SR(DCHUBBUB_SDPIF_AGP_BASE),\ - SR(DCHUBBUB_SDPIF_AGP_BOT),\ - SR(DCHUBBUB_SDPIF_AGP_TOP),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ @@ -152,6 +132,29 @@ MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) +#define MI_REG_LIST_DCN10(id)\ + MI_REG_LIST_DCN(id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ + SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ + SR(DCHUBBUB_SDPIF_FB_TOP),\ + SR(DCHUBBUB_SDPIF_FB_BASE),\ + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SR(DCHUBBUB_SDPIF_AGP_BASE),\ + SR(DCHUBBUB_SDPIF_AGP_BOT),\ + SR(DCHUBBUB_SDPIF_AGP_TOP) + struct dcn_mi_registers { uint32_t DCHUBP_CNTL; uint32_t HUBPREQ_DEBUG_DB; @@ -229,12 +232,20 @@ struct dcn_mi_registers { uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB; uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB; uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; + uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; + uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; uint32_t DCHUBBUB_SDPIF_FB_TOP; uint32_t DCHUBBUB_SDPIF_FB_BASE; uint32_t DCHUBBUB_SDPIF_FB_OFFSET; uint32_t DCHUBBUB_SDPIF_AGP_BASE; uint32_t DCHUBBUB_SDPIF_AGP_BOT; uint32_t DCHUBBUB_SDPIF_AGP_TOP; + uint32_t DCN_VM_FB_LOCATION_TOP; + uint32_t DCN_VM_FB_LOCATION_BASE; + uint32_t DCN_VM_FB_OFFSET; + uint32_t DCN_VM_AGP_BASE; + uint32_t DCN_VM_AGP_BOT; + uint32_t DCN_VM_AGP_TOP; uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; @@ -278,7 +289,7 @@ struct dcn_mi_registers { #define MI_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix -#define MI_DCN10_MASK_SH_LIST(mask_sh)\ +#define MI_MASK_SH_LIST_DCN(mask_sh)\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ @@ -299,7 +310,7 @@ struct dcn_mi_registers { MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ MI_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ - MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_PENDING, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ @@ -382,6 +393,17 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ + MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh),\ + MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ + MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh) + +#define MI_MASK_SH_LIST_DCN10(mask_sh)\ + MI_MASK_SH_LIST_DCN(mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ @@ -390,11 +412,6 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ @@ -405,12 +422,9 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh),\ MI_SF(DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh),\ MI_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh),\ - MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ - MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ /* todo: get these from GVM instead of reading registers ourselves */\ MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, PAGE_DIRECTORY_ENTRY_HI32, mask_sh),\ MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, PAGE_DIRECTORY_ENTRY_LO32, mask_sh),\ @@ -444,7 +458,7 @@ struct dcn_mi_registers { type SURFACE_PIXEL_FORMAT;\ type SURFACE_FLIP_TYPE;\ type SURFACE_UPDATE_LOCK;\ - type SURFACE_UPDATE_PENDING;\ + type SURFACE_FLIP_PENDING;\ type PRIMARY_SURFACE_ADDRESS_HIGH;\ type PRIMARY_SURFACE_ADDRESS;\ type SECONDARY_SURFACE_ADDRESS_HIGH;\ @@ -543,12 +557,20 @@ struct dcn_mi_registers { type MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB;\ type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB;\ type MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB;\ + type MC_VM_SYSTEM_APERTURE_LOW_ADDR;\ + type MC_VM_SYSTEM_APERTURE_HIGH_ADDR;\ type SDPIF_FB_TOP;\ type SDPIF_FB_BASE;\ type SDPIF_FB_OFFSET;\ type SDPIF_AGP_BASE;\ type SDPIF_AGP_BOT;\ type SDPIF_AGP_TOP;\ + type FB_TOP;\ + type FB_BASE;\ + type FB_OFFSET;\ + type AGP_BASE;\ + type AGP_BOT;\ + type AGP_TOP;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ @@ -589,5 +611,4 @@ bool dcn10_mem_input_construct( const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index a0dd75dc1c6d..b0888a86b2ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -374,7 +374,7 @@ static const struct bios_registers bios_regs = { #define mi_regs(id)\ [id] = {\ - MI_DCN10_REG_LIST(id)\ + MI_REG_LIST_DCN10(id)\ } @@ -386,11 +386,11 @@ static const struct dcn_mi_registers mi_regs[] = { }; static const struct dcn_mi_shift mi_shift = { - MI_DCN10_MASK_SH_LIST(__SHIFT) + MI_MASK_SH_LIST_DCN10(__SHIFT) }; static const struct dcn_mi_mask mi_mask = { - MI_DCN10_MASK_SH_LIST(_MASK) + MI_MASK_SH_LIST_DCN10(_MASK) }; #define clk_src_regs(index, pllid)\ -- GitLab From 13066f9f648084b5016cebfa7930ce4c056ab9d6 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 18:41:22 -0400 Subject: [PATCH 0593/2898] drm/amd/display: Rename DCN opp specific function prefixes to oppn10 Also update relevant registers. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 189 +++++++++--------- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 79 ++++---- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 6 +- 3 files changed, 138 insertions(+), 136 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index a07401004f44..e6f2220415e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -37,7 +37,7 @@ #define CTX \ oppn10->base.ctx -static void opp_set_regamma_mode( +static void oppn10_set_regamma_mode( struct output_pixel_processor *opp, enum opp_regamma mode) { @@ -167,7 +167,7 @@ static void set_spatial_dither( FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); } -static void opp_program_bit_depth_reduction( +static void oppn10_program_bit_depth_reduction( struct output_pixel_processor *opp, const struct bit_depth_reduction_params *params) { @@ -255,7 +255,7 @@ static void opp_set_clamping( } -static void opp_set_dyn_expansion( +static void oppn10_set_dyn_expansion( struct output_pixel_processor *opp, enum dc_color_space color_sp, enum dc_color_depth color_dpth, @@ -304,7 +304,7 @@ static void opp_program_clamping_and_pixel_encoding( set_pixel_encoding(oppn10, params); } -static void opp_program_fmt( +static void oppn10_program_fmt( struct output_pixel_processor *opp, struct bit_depth_reduction_params *fmt_bit_depth, struct clamping_and_pixel_encoding_params *clamping) @@ -316,7 +316,7 @@ static void opp_program_fmt( /* dithering is affected by , hence should be * programmed afterwards */ - opp_program_bit_depth_reduction( + oppn10_program_bit_depth_reduction( opp, fmt_bit_depth); @@ -327,7 +327,7 @@ static void opp_program_fmt( return; } -static void opp_set_output_csc_default( +static void oppn10_set_output_csc_default( struct output_pixel_processor *opp, const struct default_adjustment *default_adjust) { @@ -703,7 +703,7 @@ static void opp_configure_regamma_lut( REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); } -static void opp_power_on_regamma_lut( +static void oppn10_power_on_regamma_lut( struct output_pixel_processor *opp, bool power_on) { @@ -713,7 +713,78 @@ static void opp_power_on_regamma_lut( } -void opp_set_output_csc_adjustment( + +static void oppn10_program_color_matrix(struct dcn10_opp *oppn10, + const struct out_csc_color_matrix *tbl_entry) +{ + uint32_t mode; + + REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); + + if (tbl_entry == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + + if (mode == 4) { + /*R*/ + REG_SET_2(CM_OCSC_C11_C12, 0, + CM_OCSC_C11, tbl_entry->regval[0], + CM_OCSC_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_OCSC_C13_C14, 0, + CM_OCSC_C13, tbl_entry->regval[2], + CM_OCSC_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_OCSC_C21_C22, 0, + CM_OCSC_C21, tbl_entry->regval[4], + CM_OCSC_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_OCSC_C23_C24, 0, + CM_OCSC_C23, tbl_entry->regval[6], + CM_OCSC_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_OCSC_C31_C32, 0, + CM_OCSC_C31, tbl_entry->regval[8], + CM_OCSC_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_OCSC_C33_C34, 0, + CM_OCSC_C33, tbl_entry->regval[10], + CM_OCSC_C34, tbl_entry->regval[11]); + } else { + /*R*/ + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, tbl_entry->regval[0], + CM_COMB_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, tbl_entry->regval[2], + CM_COMB_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, tbl_entry->regval[4], + CM_COMB_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, tbl_entry->regval[6], + CM_COMB_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, tbl_entry->regval[8], + CM_COMB_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, tbl_entry->regval[10], + CM_COMB_C34, tbl_entry->regval[11]); + } +} + +void oppn10_set_output_csc_adjustment( struct output_pixel_processor *opp, const struct out_csc_color_matrix *tbl_entry) { @@ -752,7 +823,7 @@ void opp_set_output_csc_adjustment( */ REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - program_color_matrix(oppn10, tbl_entry); + oppn10_program_color_matrix(oppn10, tbl_entry); } static void opp_program_regamma_lut( @@ -778,20 +849,18 @@ static void opp_program_regamma_lut( } - - -static bool opp_set_regamma_pwl( +static bool oppn10_set_regamma_pwl( struct output_pixel_processor *opp, const struct pwl_params *params) { struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - opp_power_on_regamma_lut(opp, true); + oppn10_power_on_regamma_lut(opp, true); opp_configure_regamma_lut(opp, oppn10->is_write_to_ram_a_safe); if (oppn10->is_write_to_ram_a_safe) - opp_program_regamma_luta_settings(opp, params); + opp_program_regamma_luta_settings(opp, params); else - opp_program_regamma_lutb_settings(opp, params); + opp_program_regamma_lutb_settings(opp, params); opp_program_regamma_lut( opp, params->rgb_resulted, params->hw_points_num); @@ -799,7 +868,7 @@ static bool opp_set_regamma_pwl( return true; } -static void opp_set_stereo_polarity( +static void oppn10_set_stereo_polarity( struct output_pixel_processor *opp, bool enable, bool rightEyePolarity) { @@ -819,15 +888,15 @@ static void dcn10_opp_destroy(struct output_pixel_processor **opp) } static struct opp_funcs dcn10_opp_funcs = { - .opp_power_on_regamma_lut = opp_power_on_regamma_lut, - .opp_set_csc_adjustment = opp_set_output_csc_adjustment, - .opp_set_csc_default = opp_set_output_csc_default, - .opp_set_dyn_expansion = opp_set_dyn_expansion, - .opp_program_regamma_pwl = opp_set_regamma_pwl, - .opp_set_regamma_mode = opp_set_regamma_mode, - .opp_program_fmt = opp_program_fmt, - .opp_program_bit_depth_reduction = opp_program_bit_depth_reduction, - .opp_set_stereo_polarity = opp_set_stereo_polarity, + .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, + .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, + .opp_set_csc_default = oppn10_set_output_csc_default, + .opp_set_dyn_expansion = oppn10_set_dyn_expansion, + .opp_program_regamma_pwl = oppn10_set_regamma_pwl, + .opp_set_regamma_mode = oppn10_set_regamma_mode, + .opp_program_fmt = oppn10_program_fmt, + .opp_program_bit_depth_reduction = oppn10_program_bit_depth_reduction, + .opp_set_stereo_polarity = oppn10_set_stereo_polarity, .opp_destroy = dcn10_opp_destroy }; @@ -847,73 +916,3 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, oppn10->opp_mask = opp_mask; } - -void program_color_matrix(struct dcn10_opp *oppn10, - const struct out_csc_color_matrix *tbl_entry) -{ - uint32_t mode; - - REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); - - if (tbl_entry == NULL) { - BREAK_TO_DEBUGGER(); - return; - } - - - if (mode == 4) { - /*R*/ - REG_SET_2(CM_OCSC_C11_C12, 0, - CM_OCSC_C11, tbl_entry->regval[0], - CM_OCSC_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_OCSC_C13_C14, 0, - CM_OCSC_C13, tbl_entry->regval[2], - CM_OCSC_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_OCSC_C21_C22, 0, - CM_OCSC_C21, tbl_entry->regval[4], - CM_OCSC_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_OCSC_C23_C24, 0, - CM_OCSC_C23, tbl_entry->regval[6], - CM_OCSC_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_OCSC_C31_C32, 0, - CM_OCSC_C31, tbl_entry->regval[8], - CM_OCSC_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_OCSC_C33_C34, 0, - CM_OCSC_C33, tbl_entry->regval[10], - CM_OCSC_C34, tbl_entry->regval[11]); - } else { - /*R*/ - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, tbl_entry->regval[0], - CM_COMB_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, tbl_entry->regval[2], - CM_COMB_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, tbl_entry->regval[4], - CM_COMB_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, tbl_entry->regval[6], - CM_COMB_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, tbl_entry->regval[8], - CM_COMB_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, tbl_entry->regval[10], - CM_COMB_C34, tbl_entry->regval[11]); - } -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index 9cc4c5feaddf..eb99c311104f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -33,7 +33,19 @@ #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix -#define OPP_DCN10_REG_LIST(id) \ +#define OPP_REG_LIST_DCN(id) \ + SRI(OBUF_CONTROL, DSCL, id), \ + SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ + SRI(FMT_CONTROL, FMT, id), \ + SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI(FMT_CLAMP_CNTL, FMT, id), \ + SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id) + +#define OPP_REG_LIST_DCN10(id) \ + OPP_REG_LIST_DCN(id), \ SRI(CM_OCSC_C11_C12, CM, id), \ SRI(CM_OCSC_C13_C14, CM, id), \ SRI(CM_OCSC_C21_C22, CM, id), \ @@ -48,15 +60,6 @@ SRI(CM_COMB_C33_C34, CM, id), \ SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id), \ - SRI(OBUF_CONTROL, DSCL, id), \ - SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ - SRI(FMT_CONTROL, FMT, id), \ - SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ - SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ - SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ - SRI(FMT_CLAMP_CNTL, FMT, id), \ - SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ - SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ SRI(CM_OCSC_CONTROL, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ @@ -120,7 +123,34 @@ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_RGAM_LUT_DATA, CM, id) -#define OPP_DCN10_MASK_SH_LIST(mask_sh) \ + +#define OPP_MASK_SH_LIST_DCN(mask_sh) \ + OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh), \ + OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ + OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh) + +#define OPP_MASK_SH_LIST_DCN10(mask_sh) \ + OPP_MASK_SH_LIST_DCN(mask_sh), \ + OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ @@ -146,29 +176,6 @@ OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh), \ OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh), \ OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ - OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh), \ - OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ - OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ - OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ - OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ - OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh), \ - OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ - OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ - OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh), \ - OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh), \ OPP_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ @@ -691,8 +698,4 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask); -void program_color_matrix( - struct dcn10_opp *oppn10, - const struct out_csc_color_matrix *tbl_entry); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index b0888a86b2ec..898b618798d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -286,7 +286,7 @@ static const struct dcn10_ipp_mask ipp_mask = { #define opp_regs(id)\ [id] = {\ - OPP_DCN10_REG_LIST(id),\ + OPP_REG_LIST_DCN10(id),\ } static const struct dcn10_opp_registers opp_regs[] = { @@ -297,11 +297,11 @@ static const struct dcn10_opp_registers opp_regs[] = { }; static const struct dcn10_opp_shift opp_shift = { - OPP_DCN10_MASK_SH_LIST(__SHIFT) + OPP_MASK_SH_LIST_DCN10(__SHIFT) }; static const struct dcn10_opp_mask opp_mask = { - OPP_DCN10_MASK_SH_LIST(_MASK), + OPP_MASK_SH_LIST_DCN10(_MASK), }; #define tf_regs(id)\ -- GitLab From 35ce37d6a4d140ba7e2870d7c0bc4a6b866f1d8d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 28 Jun 2017 18:58:27 -0400 Subject: [PATCH 0594/2898] drm/amd/display: Enable ipp compilation Update relevant registers Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 19 +--- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 91 ++++++++++--------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 6 +- 3 files changed, 54 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 1e7a55d9e9ec..a09226c0d903 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -421,7 +421,10 @@ static void dcn10_ipp_enable_cm_block( struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1); - REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); + if (ippn10->ipp_mask->CM_BYPASS_EN) + REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); + else + REG_UPDATE(CM_CONTROL, CM_BYPASS, 0); } @@ -484,7 +487,7 @@ static bool dcn10_cursor_program_control( REG_UPDATE_2(CURSOR0_CONTROL, CUR0_MODE, color_format, - CUR0_INVERT_MODE, 0); + CUR0_EXPANSION_MODE, 0); if (color_format == CURSOR_MODE_MONO) { /* todo: clarify what to program these to */ @@ -501,18 +504,6 @@ static bool dcn10_cursor_program_control( ALPHA_EN, 1, FORMAT_EXPANSION_MODE, 0); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_EXPANSION_MODE, 0); - - if (0 /*attributes->attribute_flags.bits.MIN_MAX_INVERT*/) { - REG_UPDATE(CURSOR0_CONTROL, - CUR0_MAX, - 0 /* TODO */); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_MIN, - 0 /* TODO */); - } - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index 511993519740..d608abf0e822 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -31,7 +31,7 @@ #define TO_DCN10_IPP(ipp)\ container_of(ipp, struct dcn10_ipp, base) -#define IPP_DCN10_REG_LIST(id) \ +#define IPP_REG_LIST_DCN(id) \ SRI(CM_ICSC_CONTROL, CM, id), \ SRI(CM_ICSC_C11_C12, CM, id), \ SRI(CM_ICSC_C13_C14, CM, id), \ @@ -39,12 +39,6 @@ SRI(CM_ICSC_C23_C24, CM, id), \ SRI(CM_ICSC_C31_C32, CM, id), \ SRI(CM_ICSC_C33_C34, CM, id), \ - SRI(CM_COMA_C11_C12, CM, id), \ - SRI(CM_COMA_C13_C14, CM, id), \ - SRI(CM_COMA_C21_C22, CM, id), \ - SRI(CM_COMA_C23_C24, CM, id), \ - SRI(CM_COMA_C31_C32, CM, id), \ - SRI(CM_COMA_C33_C34, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_R, CM, id), \ @@ -86,22 +80,31 @@ SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ - SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ - SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ - SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_DGAM_LUT_INDEX, CM, id), \ SRI(CM_DGAM_LUT_DATA, CM, id), \ SRI(CM_CONTROL, CM, id), \ SRI(CM_DGAM_CONTROL, CM, id), \ - SRI(CM_IGAM_CONTROL, CM, id), \ + SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(DPP_CONTROL, DPP_TOP, id), \ SRI(CURSOR_SETTINS, HUBPREQ, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ - SRI(CURSOR0_COLOR1, CNVC_CUR, id), \ - SRI(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI(CURSOR0_COLOR1, CNVC_CUR, id) + +#define IPP_REG_LIST_DCN10(id) \ + IPP_REG_LIST_DCN(id), \ + SRI(CM_IGAM_CONTROL, CM, id), \ + SRI(CM_COMA_C11_C12, CM, id), \ + SRI(CM_COMA_C13_C14, CM, id), \ + SRI(CM_COMA_C21_C22, CM, id), \ + SRI(CM_COMA_C23_C24, CM, id), \ + SRI(CM_COMA_C31_C32, CM, id), \ + SRI(CM_COMA_C33_C34, CM, id), \ + SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ + SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ + SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ SRI(CURSOR_SIZE, CURSOR, id), \ @@ -113,7 +116,7 @@ #define IPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix -#define IPP_DCN10_MASK_SH_LIST(mask_sh) \ +#define IPP_MASK_SH_LIST_DCN(mask_sh) \ IPP_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ @@ -127,18 +130,6 @@ IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ - IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ - IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ - IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ - IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh), \ - IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh), \ - IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh), \ - IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh), \ - IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh), \ - IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh), \ - IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh), \ - IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh), \ - IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_G, mask_sh), \ @@ -240,37 +231,46 @@ IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ IPP_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ - IPP_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ IPP_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ - IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_INVERT_MODE, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ - IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MAX, mask_sh), \ - IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MIN, mask_sh), \ + IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh) + +#define IPP_MASK_SH_LIST_DCN10(mask_sh) \ + IPP_MASK_SH_LIST_DCN(mask_sh),\ + IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ + IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ + IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ + IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh), \ + IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh), \ + IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh), \ + IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh), \ + IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh), \ + IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh), \ + IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh), \ + IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh), \ + IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ + IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ + IPP_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ @@ -279,12 +279,15 @@ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ - IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ IPP_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ IPP_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ IPP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ + IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh) @@ -431,6 +434,7 @@ type CM_DGAM_LUT_DATA; \ type DPP_CLOCK_ENABLE; \ type CM_BYPASS_EN; \ + type CM_BYPASS; \ type CNVC_SURFACE_PIXEL_FORMAT; \ type CNVC_BYPASS; \ type ALPHA_EN; \ @@ -440,12 +444,9 @@ type CURSOR0_DST_Y_OFFSET; \ type CURSOR0_CHUNK_HDL_ADJUST; \ type CUR0_MODE; \ - type CUR0_INVERT_MODE; \ type CUR0_COLOR0; \ type CUR0_COLOR1; \ type CUR0_EXPANSION_MODE; \ - type CUR0_MAX; \ - type CUR0_MIN; \ type CURSOR_SURFACE_ADDRESS_HIGH; \ type CURSOR_SURFACE_ADDRESS; \ type CURSOR_WIDTH; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 898b618798d5..fcea49e9f665 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -266,7 +266,7 @@ static const struct dce110_link_enc_registers link_enc_regs[] = { #define ipp_regs(id)\ [id] = {\ - IPP_DCN10_REG_LIST(id),\ + IPP_REG_LIST_DCN10(id),\ } static const struct dcn10_ipp_registers ipp_regs[] = { @@ -277,11 +277,11 @@ static const struct dcn10_ipp_registers ipp_regs[] = { }; static const struct dcn10_ipp_shift ipp_shift = { - IPP_DCN10_MASK_SH_LIST(__SHIFT) + IPP_MASK_SH_LIST_DCN10(__SHIFT) }; static const struct dcn10_ipp_mask ipp_mask = { - IPP_DCN10_MASK_SH_LIST(_MASK), + IPP_MASK_SH_LIST_DCN10(_MASK), }; #define opp_regs(id)\ -- GitLab From 7a8368e6f521871976f3d173f837dd921d06130d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 29 Jun 2017 18:01:35 -0400 Subject: [PATCH 0595/2898] drm/amd/display: Remove SMU_INTERRUPT_CONTROL Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 8b04996d5b89..fd6ba7efc0f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -50,7 +50,6 @@ SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_DATA), \ SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ - SR(SMU_INTERRUPT_CONTROL), \ SRI(DIG_BE_CNTL, DIG, id), \ SRI(DIG_BE_EN_CNTL, DIG, id), \ SRI(DP_CONFIG, DP, id), \ @@ -137,7 +136,6 @@ struct dce110_link_enc_registers { uint32_t DMCU_IRAM_RD_CTRL; uint32_t DMCU_IRAM_RD_DATA; uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK; - uint32_t SMU_INTERRUPT_CONTROL; /* Common DP registers */ uint32_t DIG_BE_CNTL; -- GitLab From 97416d4cbb9efab2eea7740fa4ce86b317da06c5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 26 Jun 2017 16:25:10 -0400 Subject: [PATCH 0596/2898] drm/amd/display: set drr during program timing. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../dc/dce110/dce110_timing_generator.c | 21 +++++++++++++++++++ .../dc/dce120/dce120_timing_generator.c | 19 ++++++++++++++--- .../display/dc/dcn10/dcn10_timing_generator.c | 8 +++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index ec599276ed2e..7f93d6d83cfd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -629,6 +629,27 @@ void dce110_timing_generator_program_blanking( CRTC_V_TOTAL); dm_write_reg(ctx, addr, value); + /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and + * V_TOTAL_MIN are equal to V_TOTAL. + */ + addr = CRTC_REG(mmCRTC_V_TOTAL_MAX); + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->v_total - 1, + CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX); + dm_write_reg(ctx, addr, value); + + addr = CRTC_REG(mmCRTC_V_TOTAL_MIN); + value = dm_read_reg(ctx, addr); + set_reg_field_value( + value, + timing->v_total - 1, + CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN); + dm_write_reg(ctx, addr, value); + addr = CRTC_REG(mmCRTC_H_BLANK_START_END); value = dm_read_reg(ctx, addr); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 03b21e9a1156..58a070debd58 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -441,15 +441,28 @@ void dce120_timing_generator_program_blanking( struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); CRTC_REG_UPDATE( - CRTC0_CRTC_H_TOTAL, - CRTC_H_TOTAL, - timing->h_total - 1); + CRTC0_CRTC_H_TOTAL, + CRTC_H_TOTAL, + timing->h_total - 1); CRTC_REG_UPDATE( CRTC0_CRTC_V_TOTAL, CRTC_V_TOTAL, timing->v_total - 1); + /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and + * V_TOTAL_MIN are equal to V_TOTAL. + */ + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MAX, + CRTC_V_TOTAL_MAX, + timing->v_total - 1); + + CRTC_REG_UPDATE( + CRTC0_CRTC_V_TOTAL_MIN, + CRTC_V_TOTAL_MIN, + timing->v_total - 1); + tmp1 = timing->h_total - (h_sync_start + timing->h_border_left); tmp2 = tmp1 + timing->h_addressable + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 5927478b9044..e1899f5fb083 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -177,6 +177,14 @@ static void tgn10_program_timing( REG_SET(OTG_V_TOTAL, 0, OTG_V_TOTAL, v_total); + /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and + * OTG_V_TOTAL_MIN are equal to V_TOTAL. + */ + REG_SET(OTG_V_TOTAL_MAX, 0, + OTG_V_TOTAL_MAX, v_total); + REG_SET(OTG_V_TOTAL_MIN, 0, + OTG_V_TOTAL_MIN, v_total); + /* v_sync_start = 0, v_sync_end = v_sync_width */ v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor; -- GitLab From ca3268c45b85d61365ba74939650ae519ecff572 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 27 Jun 2017 11:55:43 -0400 Subject: [PATCH 0597/2898] drm/amd/display: Create dm_atomic_state We really want to use the new private_atomic_state but can't right now as we have to maintain some backward compatibility to older kernels. For now let's follow Intel's approach and extend the drm_atomic_state. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 37 ++++++++++++++++++- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 8 ++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 353165c6da1e..a95c9ba64235 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -634,11 +634,46 @@ const struct amdgpu_ip_block_version dm_ip_block = .funcs = &amdgpu_dm_funcs, }; + +struct drm_atomic_state * +dm_atomic_state_alloc(struct drm_device *dev) +{ + struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); + + if (!state || drm_atomic_state_init(dev, &state->base) < 0) { + kfree(state); + return NULL; + } + + return &state->base; +} + +void dm_atomic_state_clear(struct drm_atomic_state *s) +{ + struct dm_atomic_state *state = to_dm_atomic_state(s); + drm_atomic_state_default_clear(&state->base); +} + + +static void dm_atomic_state_free(struct drm_atomic_state *state) +{ + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + + drm_atomic_state_default_release(state); + + kfree(dm_state); +} + + + static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, - .atomic_commit = drm_atomic_helper_commit + .atomic_commit = drm_atomic_helper_commit, + .atomic_state_alloc = dm_atomic_state_alloc, + .atomic_state_clear = dm_atomic_state_clear, + .atomic_state_free = dm_atomic_state_free, }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index bf20d57a99e0..9ba7fdd20519 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -27,6 +27,7 @@ #define __AMDGPU_DM_TYPES_H__ #include +#include struct amdgpu_framebuffer; struct amdgpu_display_manager; @@ -48,6 +49,13 @@ struct dm_crtc_state { #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) +struct dm_atomic_state { + struct drm_atomic_state base; +}; + +#define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) + + /*TODO Jodan Hersen use the one in amdgpu_dm*/ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, -- GitLab From a6818a32317114387dbadf769275275dd56cc624 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 27 Jun 2017 14:35:17 -0400 Subject: [PATCH 0598/2898] drm/amd/display: Hook dm private state into atomic_check Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 64 +++++++++---------- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 5 ++ 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index a6f27ceaf4af..751dd13b54e3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2962,15 +2962,14 @@ static int do_aquire_global_lock( int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { + struct dm_atomic_state *dm_state; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; struct drm_plane *plane; struct drm_plane_state *plane_state; int i, j; int ret; - int set_count; int new_stream_count; - struct dc_validation_set set[MAX_STREAMS] = {{ 0 }}; struct dc_stream *new_streams[MAX_STREAMS] = { 0 }; struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct amdgpu_device *adev = dev->dev_private; @@ -2995,17 +2994,19 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = -EINVAL; + dm_state = to_dm_atomic_state(state); + /* copy existing configuration */ new_stream_count = 0; - set_count = 0; + dm_state->set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); if (acrtc->stream) { - set[set_count].stream = acrtc->stream; - crtc_set[set_count] = crtc; - ++set_count; + dm_state->set[dm_state->set_count].stream = acrtc->stream; + crtc_set[dm_state->set_count] = crtc; + ++dm_state->set_count; } } @@ -3034,16 +3035,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc_stream *new_stream = NULL; struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; if (aconnector) { conn_state = drm_atomic_get_connector_state(state, &aconnector->base); if (IS_ERR(conn_state)) return ret; - dm_state = to_dm_connector_state(conn_state); + dm_conn_state = to_dm_connector_state(conn_state); } - new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_state); + new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); /* * we can have no stream on ACTION_SET if a display @@ -3058,10 +3059,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } new_streams[new_stream_count] = new_stream; - set_count = update_in_val_sets_stream( - set, + dm_state->set_count = update_in_val_sets_stream( + dm_state->set, crtc_set, - set_count, + dm_state->set_count, acrtc->stream, new_stream, crtc); @@ -3074,9 +3075,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, /* i.e. reset mode */ if (acrtc->stream) { - set_count = remove_from_val_sets( - set, - set_count, + dm_state->set_count = remove_from_val_sets( + dm_state->set, + dm_state->set_count, acrtc->stream); aquire_global_lock = true; } @@ -3127,10 +3128,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } new_streams[new_stream_count] = new_stream; - set_count = update_in_val_sets_stream( - set, + dm_state->set_count = update_in_val_sets_stream( + dm_state->set, crtc_set, - set_count, + dm_state->set_count, acrtc->stream, new_stream, &acrtc->base); @@ -3140,12 +3141,12 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, aquire_global_lock = true; } - for (i = 0; i < set_count; i++) { + for (i = 0; i < dm_state->set_count; i++) { for_each_plane_in_state(state, plane, plane_state, j) { struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; struct drm_connector *connector; - struct dm_connector_state *dm_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; struct drm_crtc_state *crtc_state; bool pflip_needed; @@ -3166,7 +3167,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->state->crtc == crtc) { - dm_state = to_dm_connector_state( + dm_conn_state = to_dm_connector_state( connector->state); break; } @@ -3186,7 +3187,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * Also it should be needed when used with actual * drm_atomic_commit ioctl in future */ - if (!dm_state) + if (!dm_conn_state) continue; surface = dc_create_surface(dc); @@ -3196,11 +3197,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, plane_state, false); - add_val_sets_surface( - set, - set_count, - set[i].stream, - surface); + add_val_sets_surface(dm_state->set, + dm_state->set_count, + dm_state->set[i].stream, + surface); need_to_validate = true; aquire_global_lock = true; @@ -3208,9 +3208,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } - context = dc_get_validate_context(dc, set, set_count); + context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count); - if (need_to_validate == false || set_count == 0 || context) { + if (need_to_validate == false || dm_state->set_count == 0 || context) { ret = 0; /* @@ -3232,9 +3232,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dm_free(context); } - for (i = 0; i < set_count; i++) - for (j = 0; j < set[i].surface_count; j++) - dc_surface_release(set[i].surfaces[j]); + for (i = 0; i < dm_state->set_count; i++) + for (j = 0; j < dm_state->set[i].surface_count; j++) + dc_surface_release(dm_state->set[i].surfaces[j]); for (i = 0; i < new_stream_count; i++) dc_stream_release(new_streams[i]); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 9ba7fdd20519..a7adf8dbd067 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -28,6 +28,7 @@ #include #include +#include "dc.h" struct amdgpu_framebuffer; struct amdgpu_display_manager; @@ -51,6 +52,10 @@ struct dm_crtc_state { struct dm_atomic_state { struct drm_atomic_state base; + + struct dc_validation_set set[MAX_STREAMS]; + int set_count; + }; #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) -- GitLab From b29fc8661d5c732a5689afa751983ee27141ad37 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 3 Mar 2017 14:50:00 -0500 Subject: [PATCH 0599/2898] drm/amd/display: Add correct retain/release Needed by objs in dm_atomic_state Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a95c9ba64235..ba20a8cce7df 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -658,9 +658,19 @@ void dm_atomic_state_clear(struct drm_atomic_state *s) static void dm_atomic_state_free(struct drm_atomic_state *state) { struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + int i, j; drm_atomic_state_default_release(state); + for (i = 0; i < dm_state->set_count; i++) { + for (j = 0; j < dm_state->set[i].surface_count; j++) { + dc_surface_release(dm_state->set[i].surfaces[j]); + } + } + + for (i = 0; i < dm_state->set_count; i++) + dc_stream_release(dm_state->set[i].stream); + kfree(dm_state); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 751dd13b54e3..54d31f474d76 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2874,11 +2874,15 @@ static uint32_t update_in_val_sets_stream( } val_sets[i].stream = new_stream; + dc_stream_retain(new_stream); crtcs[i] = crtc; if (i == set_count) { /* nothing found. add new one to the end */ return set_count + 1; + } else { + /* update. relase old stream */ + dc_stream_release(old_stream); } return set_count; @@ -2900,6 +2904,7 @@ static uint32_t remove_from_val_sets( return set_count; } + dc_stream_release(stream); set_count--; for (; i < set_count; i++) { @@ -3004,6 +3009,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); if (acrtc->stream) { + dc_stream_retain(acrtc->stream); dm_state->set[dm_state->set_count].stream = acrtc->stream; crtc_set[dm_state->set_count] = crtc; ++dm_state->set_count; -- GitLab From 7cf2c840c6b5ee98195d249e3748bb90c9bcb831 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 6 Mar 2017 09:43:30 -0500 Subject: [PATCH 0600/2898] drm/amd/display: Commit validation set from state Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 32 ++--- drivers/gpu/drm/amd/display/dc/core/dc.c | 118 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 16 +++ 3 files changed, 151 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 54d31f474d76..c77f35bcacac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2517,12 +2517,11 @@ void amdgpu_dm_atomic_commit_tail( struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; + struct dm_atomic_state *dm_state; uint32_t i, j; - uint32_t commit_streams_count = 0; uint32_t new_crtcs_count = 0; struct drm_crtc *crtc, *pcrtc; struct drm_crtc_state *old_crtc_state; - const struct dc_stream *commit_streams[MAX_STREAMS]; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; const struct dc_stream *new_stream; unsigned long flags; @@ -2531,6 +2530,9 @@ void amdgpu_dm_atomic_commit_tail( struct drm_connector_state *old_conn_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); + + dm_state = to_dm_atomic_state(state); + /* update changed items */ for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc; @@ -2561,16 +2563,16 @@ void amdgpu_dm_atomic_commit_tail( */ if (modeset_required(new_state)) { - struct dm_connector_state *dm_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; new_stream = NULL; if (aconnector) - dm_state = to_dm_connector_state(aconnector->base.state); + dm_conn_state = to_dm_connector_state(aconnector->base.state); new_stream = create_stream_for_sink( aconnector, &crtc->state->mode, - dm_state); + dm_conn_state); DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); @@ -2598,6 +2600,13 @@ void amdgpu_dm_atomic_commit_tail( if (acrtc->stream) remove_stream(adev, acrtc); + /* TODO clean this stupid hack */ + for (j = 0; j < dm_state->set_count; j++) + if (dm_state->set[j].stream->priv == acrtc) { + ASSERT(acrtc->stream == NULL); + new_stream = dm_state->set[j].stream; + break; + } /* * this loop saves set mode crtcs * we needed to enable vblanks once all @@ -2656,15 +2665,6 @@ void amdgpu_dm_atomic_commit_tail( dm_error("%s: Failed to update stream scaling!\n", __func__); } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->stream) { - commit_streams[commit_streams_count] = acrtc->stream; - ++commit_streams_count; - } - } /* * Add streams after required streams from new and replaced streams @@ -2693,7 +2693,8 @@ void amdgpu_dm_atomic_commit_tail( } /* DC is optimized not to do anything if 'streams' didn't change. */ - WARN_ON(!dc_commit_streams(dm->dc, commit_streams, commit_streams_count)); + WARN_ON(!dc_commit_validation_set(dm->dc, dm_state->set, + dm_state->set_count)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -3051,6 +3052,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); + new_stream->priv = acrtc; /* * we can have no stream on ACTION_SET if a display diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1d2e421e8d0a..b50fc0dae28c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -841,6 +841,24 @@ static void program_timing_sync( } } +static bool set_changed( + struct core_dc *dc, + const struct dc_validation_set set[], + uint8_t set_count) +{ + uint8_t i; + + if (set_count != dc->current_context->stream_count) + return true; + + for (i = 0; i < dc->current_context->stream_count; i++) { + if (&dc->current_context->streams[i]->public != set[i].stream) + return true; + } + + return false; +} + static bool streams_changed( struct core_dc *dc, const struct dc_stream *streams[], @@ -896,6 +914,106 @@ bool dc_enable_stereo( return ret; } +/* TODO operate on validation set (or something like it) */ +bool dc_commit_validation_set( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc_bios *dcb = core_dc->ctx->dc_bios; + enum dc_status result = DC_ERROR_UNEXPECTED; + struct validate_context *context; + struct pipe_ctx *pipe; + int i, j, k, l; + + /* TODO check validation set changed */ + if (false == set_changed(core_dc, set, set_count)) + return DC_OK; + + dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", + __func__, set_count); + + for (i = 0; i < set_count; i++) + dc_stream_log(set[i].stream, + core_dc->ctx->logger, + LOG_DC); + + context = dm_alloc(sizeof(struct validate_context)); + if (context == NULL) + goto context_alloc_fail; + + /* TODO no need for validation. just rebuild context */ + /* TODO check context is created deterministically */ + result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, + set_count, + context, + core_dc->current_context); + if (result != DC_OK) { + dm_logger_write(core_dc->ctx->logger, LOG_ERROR, + "%s: Context validation failed! dc_status:%d\n", + __func__, + result); + BREAK_TO_DEBUGGER(); + dc_resource_validate_ctx_destruct(context); + goto fail; + } + + if (!dcb->funcs->is_accelerated_mode(dcb)) + core_dc->hwss.enable_accelerated_mode(core_dc); + + if (result == DC_OK) + result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); + + program_timing_sync(core_dc, context); + + for (i = 0; i < context->stream_count; i++) { + const struct core_sink *sink = context->streams[i]->sink; + + for (j = 0; j < context->stream_status[i].surface_count; j++) { + struct core_surface *surface = + DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); + + core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + + /* + * enable stereo + * TODO rework dc_enable_stereo call to work with validation sets? + */ + for (k = 0; k < MAX_PIPES; k++) { + pipe = &context->res_ctx.pipe_ctx[k]; + + for (l = 0 ; pipe && l < context->stream_count; l++) { + if (context->streams[l] && + context->streams[l] == pipe->stream && + core_dc->hwss.setup_stereo) + core_dc->hwss.setup_stereo(pipe, core_dc); + } + } + } + + CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", + context->streams[i]->public.timing.h_addressable, + context->streams[i]->public.timing.v_addressable, + context->streams[i]->public.timing.h_total, + context->streams[i]->public.timing.v_total, + context->streams[i]->public.timing.pix_clk_khz); + } + + dc_resource_validate_ctx_destruct(core_dc->current_context); + dm_free(core_dc->current_context); + + core_dc->current_context = context; + + return (result == DC_OK); + +fail: + dm_free(context); + +context_alloc_fail: + return (result == DC_OK); +} + bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 93aff8269778..5487fb100a9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -481,6 +481,8 @@ struct dc_stream { /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ /* TODO: CEA VIC */ + + void *priv; }; struct dc_stream_update { @@ -579,6 +581,20 @@ void dc_resource_validate_ctx_copy_construct( void dc_resource_validate_ctx_destruct(struct validate_context *context); +/* + * TODO update to make it about validation sets + * Set up streams and links associated to drive sinks + * The streams parameter is an absolute set of all active streams. + * + * After this call: + * Phy, Encoder, Timing Generator are programmed and enabled. + * New streams are enabled with blank stream; no memory read. + */ +bool dc_commit_validation_set( + const struct dc *dc, + const struct dc_validation_set set[], + uint8_t set_count); + /* * Set up streams and links associated to drive sinks * The streams parameter is an absolute set of all active streams. -- GitLab From bf8aef2ec439673cd43ef6d0edace96aa36c5e7c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 29 Mar 2017 11:25:24 -0400 Subject: [PATCH 0601/2898] drm/amd/display: Add validate_context to atomic_state Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 18 ++---------------- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c77f35bcacac..f2a87cd3507b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2981,7 +2981,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; bool need_to_validate = false; - struct validate_context *context; struct drm_connector *connector; struct drm_connector_state *conn_state; /* @@ -3216,10 +3215,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } - context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count); - - if (need_to_validate == false || dm_state->set_count == 0 || context) { + dm_state->context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count); + if (need_to_validate == false || dm_state->set_count == 0 || dm_state->context) { ret = 0; /* * For full updates case when @@ -3235,18 +3233,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } - if (context) { - dc_resource_validate_ctx_destruct(context); - dm_free(context); - } - - for (i = 0; i < dm_state->set_count; i++) - for (j = 0; j < dm_state->set[i].surface_count; j++) - dc_surface_release(dm_state->set[i].surfaces[j]); - - for (i = 0; i < new_stream_count; i++) - dc_stream_release(new_streams[i]); - if (ret != 0) { if (ret == -EDEADLK) DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index a7adf8dbd067..1e444cb5123d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -55,7 +55,7 @@ struct dm_atomic_state { struct dc_validation_set set[MAX_STREAMS]; int set_count; - + struct validate_context *context; }; #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) -- GitLab From e2c7bb1228bec5b1224b235e90ffa1def8e3900e Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 28 Jun 2017 13:23:04 -0400 Subject: [PATCH 0602/2898] drm/amd/display: Use validate_context from atomic_check in commit Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 18 +++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 71 ++++++------------- .../gpu/drm/amd/display/dc/core/dc_stream.c | 6 +- drivers/gpu/drm/amd/display/dc/dc.h | 5 +- 4 files changed, 40 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index f2a87cd3507b..ab07a9f0934d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2607,6 +2607,7 @@ void amdgpu_dm_atomic_commit_tail( new_stream = dm_state->set[j].stream; break; } + /* * this loop saves set mode crtcs * we needed to enable vblanks once all @@ -2665,7 +2666,6 @@ void amdgpu_dm_atomic_commit_tail( dm_error("%s: Failed to update stream scaling!\n", __func__); } - /* * Add streams after required streams from new and replaced streams * are removed from freesync module @@ -2693,15 +2693,19 @@ void amdgpu_dm_atomic_commit_tail( } /* DC is optimized not to do anything if 'streams' didn't change. */ - WARN_ON(!dc_commit_validation_set(dm->dc, dm_state->set, - dm_state->set_count)); + WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (acrtc->stream != NULL) - acrtc->otg_inst = - dc_stream_get_status(acrtc->stream)->primary_otg_inst; + if (acrtc->stream != NULL) { + const struct dc_stream_status *status = dc_stream_get_status(acrtc->stream); + + if (!status) + DC_ERR("got no status for stream %p on acrtc%p\n", acrtc->stream, acrtc); + else + acrtc->otg_inst = status->primary_otg_inst; + } } for (i = 0; i < new_crtcs_count; i++) { @@ -2884,6 +2888,7 @@ static uint32_t update_in_val_sets_stream( } else { /* update. relase old stream */ dc_stream_release(old_stream); + } return set_count; @@ -3064,6 +3069,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, __func__, acrtc->base.base.id); break; } + new_stream->priv = acrtc; new_streams[new_stream_count] = new_stream; dm_state->set_count = update_in_val_sets_stream( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b50fc0dae28c..90a31509edd6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -841,18 +841,17 @@ static void program_timing_sync( } } -static bool set_changed( +static bool context_changed( struct core_dc *dc, - const struct dc_validation_set set[], - uint8_t set_count) + struct validate_context *context) { uint8_t i; - if (set_count != dc->current_context->stream_count) + if (context->stream_count != dc->current_context->stream_count) return true; for (i = 0; i < dc->current_context->stream_count; i++) { - if (&dc->current_context->streams[i]->public != set[i].stream) + if (&dc->current_context->streams[i]->public != &context->streams[i]->public) return true; } @@ -915,55 +914,37 @@ bool dc_enable_stereo( } /* TODO operate on validation set (or something like it) */ -bool dc_commit_validation_set( - const struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count) +bool dc_commit_context(struct dc *dc, struct validate_context *context) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; - struct validate_context *context; struct pipe_ctx *pipe; int i, j, k, l; - /* TODO check validation set changed */ - if (false == set_changed(core_dc, set, set_count)) + if (!context) + dm_logger_write(core_dc->ctx->logger, LOG_ERROR, + "%s: dc_commit_context with no context!\n", + __func__); + + if (false == context_changed(core_dc, context)) return DC_OK; dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", - __func__, set_count); - - for (i = 0; i < set_count; i++) - dc_stream_log(set[i].stream, - core_dc->ctx->logger, - LOG_DC); + __func__, context->stream_count); - context = dm_alloc(sizeof(struct validate_context)); - if (context == NULL) - goto context_alloc_fail; + for (i = 0; i < context->stream_count; i++) { + const struct dc_stream *stream = &context->streams[i]->public; - /* TODO no need for validation. just rebuild context */ - /* TODO check context is created deterministically */ - result = core_dc->res_pool->funcs->validate_with_context(core_dc, set, - set_count, - context, - core_dc->current_context); - if (result != DC_OK) { - dm_logger_write(core_dc->ctx->logger, LOG_ERROR, - "%s: Context validation failed! dc_status:%d\n", - __func__, - result); - BREAK_TO_DEBUGGER(); - dc_resource_validate_ctx_destruct(context); - goto fail; + dc_stream_log(stream, + core_dc->ctx->logger, + LOG_DC); } if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); - if (result == DC_OK) - result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); + result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); program_timing_sync(core_dc, context); @@ -1000,17 +981,8 @@ bool dc_commit_validation_set( context->streams[i]->public.timing.pix_clk_khz); } - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); - - core_dc->current_context = context; - - return (result == DC_OK); - -fail: - dm_free(context); + dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); -context_alloc_fail: return (result == DC_OK); } @@ -1631,7 +1603,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - if (srf_updates[i].in_transfer_func) + /* TODO find out why check is false */ + /* TODO with this still not programming some color stuff... panel is dark-ish */ + /*if (is_new_pipe_surface || + srf_updates[i].in_transfer_func)*/ core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 4ba446de4d00..ead7b63caab7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -164,9 +164,11 @@ const struct dc_stream_status *dc_stream_get_status( struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); - for (i = 0; i < dc->current_context->stream_count; i++) - if (stream == dc->current_context->streams[i]) + for (i = 0; i < dc->current_context->stream_count; i++) { + if (stream == dc->current_context->streams[i]) { return &dc->current_context->stream_status[i]; + } + } return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5487fb100a9f..5d65416304b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -590,10 +590,7 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context); * Phy, Encoder, Timing Generator are programmed and enabled. * New streams are enabled with blank stream; no memory read. */ -bool dc_commit_validation_set( - const struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count); +bool dc_commit_context(struct dc *dc, struct validate_context *context); /* * Set up streams and links associated to drive sinks -- GitLab From 89a1fc5924cc7c315117be79878f2a6d2d69b576 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 29 Jun 2017 10:41:17 -0400 Subject: [PATCH 0603/2898] drm/amd/display: Update atomic state hooks. Reimplement atomic_state_alloc and atomic_state_clear to release validate_ctx. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 ++++++++----------- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 2 +- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ba20a8cce7df..2cfc1846f4c4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -648,33 +648,29 @@ dm_atomic_state_alloc(struct drm_device *dev) return &state->base; } -void dm_atomic_state_clear(struct drm_atomic_state *s) -{ - struct dm_atomic_state *state = to_dm_atomic_state(s); - drm_atomic_state_default_clear(&state->base); -} - -static void dm_atomic_state_free(struct drm_atomic_state *state) +void dm_atomic_state_clear(struct drm_atomic_state *state) { struct dm_atomic_state *dm_state = to_dm_atomic_state(state); int i, j; - drm_atomic_state_default_release(state); - for (i = 0; i < dm_state->set_count; i++) { for (j = 0; j < dm_state->set[i].surface_count; j++) { dc_surface_release(dm_state->set[i].surfaces[j]); + dm_state->set[i].surfaces[j] = NULL; } - } - for (i = 0; i < dm_state->set_count; i++) dc_stream_release(dm_state->set[i].stream); + dm_state->set[i].stream = NULL; + } + dm_state->set_count = 0; - kfree(dm_state); -} - + dc_resource_validate_ctx_destruct(dm_state->context); + dm_free(dm_state->context); + dm_state->context = NULL; + drm_atomic_state_default_clear(state); +} static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, @@ -683,7 +679,6 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .atomic_commit = drm_atomic_helper_commit, .atomic_state_alloc = dm_atomic_state_alloc, .atomic_state_clear = dm_atomic_state_clear, - .atomic_state_free = dm_atomic_state_free, }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index ab07a9f0934d..10e4823968c8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2695,6 +2695,7 @@ void amdgpu_dm_atomic_commit_tail( /* DC is optimized not to do anything if 'streams' didn't change. */ WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -3069,7 +3070,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, __func__, acrtc->base.base.id); break; } - new_stream->priv = acrtc; new_streams[new_stream_count] = new_stream; dm_state->set_count = update_in_val_sets_stream( -- GitLab From da5c47f682abe61eb81291cb663b77828fda0688 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 29 Jun 2017 12:03:59 -0400 Subject: [PATCH 0604/2898] drm/amd/display: Remove acrtc->stream Remove acrtc->stream and move it into dm_crtc_state. This allows to get rid of dm_atomic_state->dm_set. Also reuse streams created in atomic_check during commit. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 33 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 403 +++++++++--------- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 9 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 - 4 files changed, 226 insertions(+), 221 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2cfc1846f4c4..4b844e5c5dcd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -100,13 +100,16 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) return 0; else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state( + acrtc->base.state); - if (NULL == acrtc->stream) { + + if (acrtc_state->stream == NULL) { DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); return 0; } - return dc_stream_get_vblank_counter(acrtc->stream); + return dc_stream_get_vblank_counter(acrtc_state->stream); } } @@ -119,8 +122,10 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, return -EINVAL; else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state( + acrtc->base.state); - if (NULL == acrtc->stream) { + if (acrtc_state->stream == NULL) { DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); return 0; } @@ -129,7 +134,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, * TODO rework base driver to use values directly. * for now parse it back into reg-format */ - dc_stream_get_scanoutpos(acrtc->stream, + dc_stream_get_scanoutpos(acrtc_state->stream, &v_blank_start, &v_blank_end, &h_position, @@ -652,22 +657,12 @@ dm_atomic_state_alloc(struct drm_device *dev) void dm_atomic_state_clear(struct drm_atomic_state *state) { struct dm_atomic_state *dm_state = to_dm_atomic_state(state); - int i, j; - - for (i = 0; i < dm_state->set_count; i++) { - for (j = 0; j < dm_state->set[i].surface_count; j++) { - dc_surface_release(dm_state->set[i].surfaces[j]); - dm_state->set[i].surfaces[j] = NULL; - } - dc_stream_release(dm_state->set[i].stream); - dm_state->set[i].stream = NULL; + if (dm_state->context) { + dc_resource_validate_ctx_destruct(dm_state->context); + dm_free(dm_state->context); + dm_state->context = NULL; } - dm_state->set_count = 0; - - dc_resource_validate_ctx_destruct(dm_state->context); - dm_free(dm_state->context); - dm_state->context = NULL; drm_atomic_state_default_clear(state); } @@ -676,7 +671,7 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, - .atomic_commit = drm_atomic_helper_commit, + .atomic_commit = amdgpu_dm_atomic_commit, .atomic_state_alloc = dm_atomic_state_alloc, .atomic_state_clear = dm_atomic_state_clear, }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 10e4823968c8..c222cdb59ac1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -86,6 +86,7 @@ static void dm_set_cursor( struct drm_crtc *crtc = &amdgpu_crtc->base; int x, y; int xorigin = 0, yorigin = 0; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); amdgpu_crtc->cursor_width = width; amdgpu_crtc->cursor_height = height; @@ -124,13 +125,13 @@ static void dm_set_cursor( position.y_hotspot = yorigin; if (!dc_stream_set_cursor_attributes( - amdgpu_crtc->stream, + acrtc_state->stream, &attributes)) { DRM_ERROR("DC failed to set cursor attributes\n"); } if (!dc_stream_set_cursor_position( - amdgpu_crtc->stream, + acrtc_state->stream, &position)) { DRM_ERROR("DC failed to set cursor position\n"); } @@ -143,6 +144,7 @@ static int dm_crtc_cursor_set( uint32_t height) { struct dc_cursor_position position; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); int ret; @@ -162,10 +164,10 @@ static int dm_crtc_cursor_set( position.x = 0; position.y = 0; - if (amdgpu_crtc->stream) { + if (acrtc_state->stream) { /*set cursor visible false*/ dc_stream_set_cursor_position( - amdgpu_crtc->stream, + acrtc_state->stream, &position); } goto release; @@ -196,6 +198,7 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); int xorigin = 0, yorigin = 0; struct dc_cursor_position position; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); amdgpu_crtc->cursor_x = x; amdgpu_crtc->cursor_y = y; @@ -233,9 +236,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, position.x_hotspot = xorigin; position.y_hotspot = yorigin; - if (amdgpu_crtc->stream) { + if (acrtc_state->stream) { if (!dc_stream_set_cursor_position( - amdgpu_crtc->stream, + acrtc_state->stream, &position)) { DRM_ERROR("DC failed to set cursor position\n"); return -EINVAL; @@ -611,7 +614,8 @@ static void add_surface(struct dc *dc, { struct dc_surface *dc_surface; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - const struct dc_stream *dc_stream = acrtc->stream; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + const struct dc_stream *dc_stream = acrtc_state->stream; unsigned long flags; spin_lock_irqsave(&crtc->dev->event_lock, flags); @@ -965,11 +969,10 @@ static void dm_crtc_destroy_state(struct drm_crtc *crtc, { struct dm_crtc_state *cur = to_dm_crtc_state(state); - if (cur->dc_stream) { - /* TODO Destroy dc_stream objects are stream object is flattened */ - dm_free(cur->dc_stream); - } else - WARN_ON(1); + /* TODO Destroy dc_stream objects are stream object is flattened */ + if (cur->stream) + dc_stream_release(cur->stream); + __drm_atomic_helper_crtc_destroy_state(state); @@ -988,40 +991,29 @@ static void dm_crtc_reset_state(struct drm_crtc *crtc) if (WARN_ON(!state)) return; - crtc->state = &state->base; crtc->state->crtc = crtc; - state->dc_stream = dm_alloc(sizeof(*state->dc_stream)); - WARN_ON(!state->dc_stream); } static struct drm_crtc_state * dm_crtc_duplicate_state(struct drm_crtc *crtc) { struct dm_crtc_state *state, *cur; - struct dc_stream *dc_stream; - - if (WARN_ON(!crtc->state)) - return NULL; cur = to_dm_crtc_state(crtc->state); - if (WARN_ON(!cur->dc_stream)) - return NULL; - dc_stream = dm_alloc(sizeof(*dc_stream)); - if (WARN_ON(!dc_stream)) + if (WARN_ON(!crtc->state)) return NULL; state = dm_alloc(sizeof(*state)); - if (WARN_ON(!state)) { - dm_free(dc_stream); - return NULL; - } __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); - state->dc_stream = dc_stream; + if (cur->stream) { + state->stream = cur->stream; + dc_stream_retain(state->stream); + } /* TODO Duplicate dc_stream after objects are stream object is flattened */ @@ -2238,21 +2230,15 @@ static bool is_scaling_state_different( return false; } -static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) +static void remove_stream( + struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + const struct dc_stream *stream) { - /* - * we evade vblanks and pflips on crtc that - * should be changed - */ - manage_dm_interrupts(adev, acrtc, false); - /* this is the update mode case */ if (adev->dm.freesync_module) - mod_freesync_remove_stream(adev->dm.freesync_module, - acrtc->stream); + mod_freesync_remove_stream(adev->dm.freesync_module, stream); - dc_stream_release(acrtc->stream); - acrtc->stream = NULL; acrtc->otg_inst = -1; acrtc->enabled = false; } @@ -2324,6 +2310,8 @@ static void amdgpu_dm_do_flip( bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; struct dc_flip_addrs addr = { {0} }; struct dc_surface_update surface_updates[1] = { {0} }; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + /* Prepare wait for target vblank early - before the fence-waits */ target_vblank = target - drm_crtc_vblank_count(crtc) + @@ -2366,7 +2354,7 @@ static void amdgpu_dm_do_flip( crtc->primary->fb = fb; WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); - WARN_ON(!acrtc->stream); + WARN_ON(!acrtc_state->stream); addr.address.grph.addr.low_part = lower_32_bits(afb->address); addr.address.grph.addr.high_part = upper_32_bits(afb->address); @@ -2376,11 +2364,11 @@ static void amdgpu_dm_do_flip( if (acrtc->base.state->event) prepare_flip_isr(acrtc); - surface_updates->surface = dc_stream_get_status(acrtc->stream)->surfaces[0]; + surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0]; surface_updates->flip_addr = &addr; - dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc->stream, NULL); + dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, @@ -2403,6 +2391,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, const struct dc_stream *dc_stream_attach; const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; /* update planes when needed */ @@ -2457,7 +2446,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, dm_error("%s: Failed to add surface!\n", __func__); continue; } - dc_stream_attach = acrtc_attach->stream; + dc_stream_attach = acrtc_state->stream; planes_count++; } else if (crtc->state->planes_changed) { @@ -2511,6 +2500,37 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, } } + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_state; + struct amdgpu_device *adev = dev->dev_private; + int i; + + /* + * We evade vblanks and pflips on crtc that + * should be changed. We do it here to flush & disable + * interrupts before drm_swap_state is called in drm_atomic_helper_commit + * it will update crtc->dm_crtc_state->stream pointer which is used in + * the ISRs. + */ + for_each_crtc_in_state(state, crtc, new_state, i) { + struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) + manage_dm_interrupts(adev, acrtc, false); + } + + return drm_atomic_helper_commit(dev, state, nonblock); + + /*TODO Handle EINTR, reenable IRQ*/ +} + void amdgpu_dm_atomic_commit_tail( struct drm_atomic_state *state) { @@ -2528,6 +2548,7 @@ void amdgpu_dm_atomic_commit_tail( bool wait_for_vblank = true; struct drm_connector *connector; struct drm_connector_state *old_conn_state; + struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -2535,16 +2556,10 @@ void amdgpu_dm_atomic_commit_tail( /* update changed items */ for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc; - struct amdgpu_connector *aconnector = NULL; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_crtc_state *new_state = crtc->state; - - acrtc = to_amdgpu_crtc(crtc); - aconnector = - amdgpu_dm_find_first_crct_matching_connector( - state, - crtc, - false); + new_acrtc_state = to_dm_crtc_state(new_state); + old_acrtc_state = to_dm_crtc_state(old_crtc_state); DRM_DEBUG_KMS( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " @@ -2563,109 +2578,60 @@ void amdgpu_dm_atomic_commit_tail( */ if (modeset_required(new_state)) { - struct dm_connector_state *dm_conn_state = NULL; - new_stream = NULL; - - if (aconnector) - dm_conn_state = to_dm_connector_state(aconnector->base.state); - - new_stream = create_stream_for_sink( - aconnector, - &crtc->state->mode, - dm_conn_state); DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); - if (!new_stream) { + if (!new_acrtc_state->stream) { /* - * this could happen because of issues with - * userspace notifications delivery. - * In this case userspace tries to set mode on - * display which is disconnect in fact. - * dc_sink in NULL in this case on aconnector. - * We expect reset mode will come soon. - * - * This can also happen when unplug is done - * during resume sequence ended - * - * In this case, we want to pretend we still - * have a sink to keep the pipe running so that - * hw state is consistent with the sw state - */ + * this could happen because of issues with + * userspace notifications delivery. + * In this case userspace tries to set mode on + * display which is disconnect in fact. + * dc_sink in NULL in this case on aconnector. + * We expect reset mode will come soon. + * + * This can also happen when unplug is done + * during resume sequence ended + * + * In this case, we want to pretend we still + * have a sink to keep the pipe running so that + * hw state is consistent with the sw state + */ DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); - break; + continue; } - if (acrtc->stream) - remove_stream(adev, acrtc); - /* TODO clean this stupid hack */ - for (j = 0; j < dm_state->set_count; j++) - if (dm_state->set[j].stream->priv == acrtc) { - ASSERT(acrtc->stream == NULL); - new_stream = dm_state->set[j].stream; - break; - } + if (old_acrtc_state->stream) + remove_stream(adev, acrtc, old_acrtc_state->stream); + /* * this loop saves set mode crtcs * we needed to enable vblanks once all * resources acquired in dc after dc_commit_streams */ + + /*TODO move all this into dm_crtc_state, get rid of + * new_crtcs array and use old and new atomic states + * instead + */ new_crtcs[new_crtcs_count] = acrtc; new_crtcs_count++; - acrtc->stream = new_stream; acrtc->enabled = true; acrtc->hw_mode = crtc->state->mode; crtc->hwmode = crtc->state->mode; } else if (modereset_required(new_state)) { - DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); + /* i.e. reset mode */ - if (acrtc->stream) - remove_stream(adev, acrtc); + if (old_acrtc_state->stream) + remove_stream(adev, acrtc, old_acrtc_state->stream); } } /* for_each_crtc_in_state() */ - /* Handle scaling and undersacn changes*/ - for_each_connector_in_state(state, connector, old_conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct dm_connector_state *con_new_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_old_state = - to_dm_connector_state(old_conn_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - const struct dc_stream_status *status = NULL; - - /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) - continue; - - /* Skip any thing not scale or underscan chnages */ - if (!is_scaling_state_different(con_new_state, con_old_state)) - continue; - - update_stream_scaling_settings(&con_new_state->base.crtc->mode, - con_new_state, (struct dc_stream *)acrtc->stream); - - status = dc_stream_get_status(acrtc->stream); - WARN_ON(!status); - WARN_ON(!status->surface_count); - - if (!acrtc->stream) - continue; - - /*TODO How it works with MPO ?*/ - if (!dc_commit_surfaces_to_stream( - dm->dc, - (const struct dc_surface **)status->surfaces, - status->surface_count, - acrtc->stream)) - dm_error("%s: Failed to update stream scaling!\n", __func__); - } - /* * Add streams after required streams from new and replaced streams * are removed from freesync module @@ -2673,7 +2639,9 @@ void amdgpu_dm_atomic_commit_tail( if (adev->dm.freesync_module) { for (i = 0; i < new_crtcs_count; i++) { struct amdgpu_connector *aconnector = NULL; - new_stream = new_crtcs[i]->stream; + new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); + + new_stream = new_acrtc_state->stream; aconnector = amdgpu_dm_find_first_crct_matching_connector( state, @@ -2698,35 +2666,77 @@ void amdgpu_dm_atomic_commit_tail( list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + new_acrtc_state = to_dm_crtc_state(crtc->state); - if (acrtc->stream != NULL) { - const struct dc_stream_status *status = dc_stream_get_status(acrtc->stream); + if (new_acrtc_state->stream != NULL) { + const struct dc_stream_status *status = + dc_stream_get_status(new_acrtc_state->stream); if (!status) - DC_ERR("got no status for stream %p on acrtc%p\n", acrtc->stream, acrtc); + DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc); else acrtc->otg_inst = status->primary_otg_inst; } } + /* Handle scaling and undersacn changes*/ + for_each_connector_in_state(state, connector, old_conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_new_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_old_state = + to_dm_connector_state(old_conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + const struct dc_stream_status *status = NULL; + + /* Skip any modesets/resets */ + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + continue; + + /* Skip any thing not scale or underscan changes */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + + update_stream_scaling_settings(&con_new_state->base.crtc->mode, + con_new_state, (struct dc_stream *)new_acrtc_state->stream); + + status = dc_stream_get_status(new_acrtc_state->stream); + WARN_ON(!status); + WARN_ON(!status->surface_count); + + if (!new_acrtc_state->stream) + continue; + + /*TODO How it works with MPO ?*/ + if (!dc_commit_surfaces_to_stream( + dm->dc, + (const struct dc_surface **)status->surfaces, + status->surface_count, + new_acrtc_state->stream)) + dm_error("%s: Failed to update stream scaling!\n", __func__); + } + for (i = 0; i < new_crtcs_count; i++) { /* * loop to enable interrupts on newly arrived crtc */ struct amdgpu_crtc *acrtc = new_crtcs[i]; + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); if (adev->dm.freesync_module) mod_freesync_notify_mode_change( - adev->dm.freesync_module, &acrtc->stream, 1); + adev->dm.freesync_module, &new_acrtc_state->stream, 1); manage_dm_interrupts(adev, acrtc, true); } /* update planes when needed per crtc*/ for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc); + new_acrtc_state = to_dm_crtc_state(pcrtc->state); - if (acrtc->stream) + if (new_acrtc_state->stream) amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); } @@ -2822,13 +2832,15 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector { struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct amdgpu_crtc *disconnected_acrtc; + struct dm_crtc_state *acrtc_state; if (!aconnector->dc_sink || !connector->state || !connector->encoder) return; disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state); - if (!disconnected_acrtc || !disconnected_acrtc->stream) + if (!disconnected_acrtc || !acrtc_state->stream) return; /* @@ -2836,7 +2848,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector * we deduce we are in a state where we can not rely on usermode call * to turn on the display, so we do it here */ - if (disconnected_acrtc->stream->sink != aconnector->dc_sink) + if (acrtc_state->stream->sink != aconnector->dc_sink) dm_force_atomic_commit(&aconnector->base); } @@ -2880,17 +2892,11 @@ static uint32_t update_in_val_sets_stream( } val_sets[i].stream = new_stream; - dc_stream_retain(new_stream); crtcs[i] = crtc; - if (i == set_count) { + if (i == set_count) /* nothing found. add new one to the end */ return set_count + 1; - } else { - /* update. relase old stream */ - dc_stream_release(old_stream); - - } return set_count; } @@ -2911,7 +2917,6 @@ static uint32_t remove_from_val_sets( return set_count; } - dc_stream_release(stream); set_count--; for (; i < set_count; i++) { @@ -2981,14 +2986,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_plane_state *plane_state; int i, j; int ret; - int new_stream_count; - struct dc_stream *new_streams[MAX_STREAMS] = { 0 }; struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; bool need_to_validate = false; struct drm_connector *connector; struct drm_connector_state *conn_state; + int set_count; + struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; + struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + /* * This bool will be set for true for any modeset/reset * or surface update which implies non fast surfae update. @@ -3008,17 +3015,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dm_state = to_dm_atomic_state(state); /* copy existing configuration */ - new_stream_count = 0; - dm_state->set_count = 0; + set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + old_acrtc_state = to_dm_crtc_state(crtc->state); - if (acrtc->stream) { - dc_stream_retain(acrtc->stream); - dm_state->set[dm_state->set_count].stream = acrtc->stream; - crtc_set[dm_state->set_count] = crtc; - ++dm_state->set_count; + if (old_acrtc_state->stream) { + dc_stream_retain(old_acrtc_state->stream); + set[set_count].stream = old_acrtc_state->stream; + crtc_set[set_count] = crtc; + ++set_count; } } @@ -3026,7 +3032,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; - + old_acrtc_state = to_dm_crtc_state(crtc->state); + new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); @@ -3057,7 +3064,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); - new_stream->priv = acrtc; /* * we can have no stream on ACTION_SET if a display @@ -3071,27 +3077,33 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, break; } - new_streams[new_stream_count] = new_stream; - dm_state->set_count = update_in_val_sets_stream( - dm_state->set, + if (new_acrtc_state->stream) + dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = new_stream; + + set_count = update_in_val_sets_stream( + set, crtc_set, - dm_state->set_count, - acrtc->stream, - new_stream, + set_count, + old_acrtc_state->stream, + new_acrtc_state->stream, crtc); - new_stream_count++; need_to_validate = true; aquire_global_lock = true; } else if (modereset_required(crtc_state)) { /* i.e. reset mode */ - if (acrtc->stream) { - dm_state->set_count = remove_from_val_sets( - dm_state->set, - dm_state->set_count, - acrtc->stream); + if (new_acrtc_state->stream) { + set_count = remove_from_val_sets( + set, + set_count, + new_acrtc_state->stream); + + dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = NULL; + aquire_global_lock = true; } } @@ -3112,6 +3124,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } /* Check scaling and undersacn changes*/ + /*TODO Removed scaling changes validation due to inability to commit + * new stream into context w\o causing full reset. Need to + * decide how to handle. + */ for_each_connector_in_state(state, connector, conn_state, i) { struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct dm_connector_state *con_old_state = @@ -3119,7 +3135,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_connector_state *con_new_state = to_dm_connector_state(conn_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - struct dc_stream *new_stream; /* Skip any modesets/resets */ if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) @@ -3129,32 +3144,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(con_new_state, con_old_state)) continue; - new_stream = create_stream_for_sink( - aconnector, - &acrtc->base.state->mode, - con_new_state); - - if (!new_stream) { - DRM_ERROR("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - continue; - } - - new_streams[new_stream_count] = new_stream; - dm_state->set_count = update_in_val_sets_stream( - dm_state->set, - crtc_set, - dm_state->set_count, - acrtc->stream, - new_stream, - &acrtc->base); - - new_stream_count++; need_to_validate = true; aquire_global_lock = true; } - for (i = 0; i < dm_state->set_count; i++) { + for (i = 0; i < set_count; i++) { for_each_plane_in_state(state, plane, plane_state, j) { struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; @@ -3210,9 +3204,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, plane_state, false); - add_val_sets_surface(dm_state->set, - dm_state->set_count, - dm_state->set[i].stream, + add_val_sets_surface(set, + set_count, + set[i].stream, surface); need_to_validate = true; @@ -3221,9 +3215,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } - dm_state->context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count); + dm_state->context = dc_get_validate_context(dc, set, set_count); - if (need_to_validate == false || dm_state->set_count == 0 || dm_state->context) { + if (need_to_validate == false || set_count == 0 || dm_state->context) { ret = 0; /* * For full updates case when @@ -3239,6 +3233,21 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } + /* TODO until surfaces are moved into dm_plane_state release them + * here + */ + for (i = 0; i < set_count; i++) + for (j = 0; j < set[i].surface_count; j++) + dc_surface_release(set[i].surfaces[j]); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + old_acrtc_state = to_dm_crtc_state(crtc->state); + + if (old_acrtc_state->stream) + dc_stream_release(old_acrtc_state->stream); + } + + if (ret != 0) { if (ret == -EDEADLK) DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 1e444cb5123d..36cb1c840810 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -45,7 +45,7 @@ struct dm_plane_state { struct dm_crtc_state { struct drm_crtc_state base; - struct dc_stream *dc_stream; + const struct dc_stream *stream; }; #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) @@ -53,8 +53,6 @@ struct dm_crtc_state { struct dm_atomic_state { struct drm_atomic_state base; - struct dc_validation_set set[MAX_STREAMS]; - int set_count; struct validate_context *context; }; @@ -83,6 +81,11 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); int amdgpu_dm_connector_get_modes(struct drm_connector *connector); +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); + void amdgpu_dm_atomic_commit_tail( struct drm_atomic_state *state); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5d65416304b0..42c1aa8d68af 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -481,8 +481,6 @@ struct dc_stream { /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ /* TODO: CEA VIC */ - - void *priv; }; struct dc_stream_update { -- GitLab From f9ea47cec22ff332c2206249a18851c7eb68d832 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 5 Jul 2017 13:28:24 -0400 Subject: [PATCH 0605/2898] drm/amd/display: Undo dc_update_surfaces_and_stream change. Restoring conditional call to in_transfer_func since no reason to call it unconditionally. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 90a31509edd6..2f93f0e9ba84 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1603,10 +1603,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - /* TODO find out why check is false */ - /* TODO with this still not programming some color stuff... panel is dark-ish */ - /*if (is_new_pipe_surface || - srf_updates[i].in_transfer_func)*/ + if (srf_updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->surface); -- GitLab From d5d4e09f5de96c986a47dc1ced334d6dc47a9959 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 4 Jun 2017 12:50:20 -0400 Subject: [PATCH 0606/2898] drm/amd/display: update DPM bounding box value based on STA target aligned to FCLK for SS corners with 10% margin also - group all latency together - group all voltage state related together Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 4486121e3986..58a4b2e90c15 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -36,40 +36,65 @@ /* Defaults from spreadsheet rev#247 */ const struct dcn_soc_bounding_box dcn10_soc_defaults = { - .sr_exit_time = 17, /*us*/ /*update based on HW Request for 118773*/ + /* latencies */ + .sr_exit_time = 17, /*us*/ .sr_enter_plus_exit_time = 19, /*us*/ .urgent_latency = 4, /*us*/ + .dram_clock_change_latency = 17, /*us*/ .write_back_latency = 12, /*us*/ .percent_of_ideal_drambw_received_after_urg_latency = 80, /*%*/ - .max_request_size = 256, /*bytes*/ - .dcfclkv_max0p9 = 600, /*MHz*/ - .dcfclkv_nom0p8 = 600, /*MHz*/ - .dcfclkv_mid0p72 = 300, /*MHz*/ - .dcfclkv_min0p65 = 300, /*MHz*/ - .max_dispclk_vmax0p9 = 1086, /*MHz*/ - .max_dispclk_vnom0p8 = 661, /*MHz*/ - .max_dispclk_vmid0p72 = 608, /*MHz*/ - .max_dispclk_vmin0p65 = 608, /*MHz*/ - .max_dppclk_vmax0p9 = 661, /*MHz*/ - .max_dppclk_vnom0p8 = 661, /*MHz*/ - .max_dppclk_vmid0p72 = 435, /*MHz*/ - .max_dppclk_vmin0p65 = 435, /*MHz*/ - .socclk = 208, /*MHz*/ + + /* below default clocks derived from STA target base on + * slow-slow corner + 10% margin with voltages aligned to FCLK. + * + * Use these value if fused value doesn't make sense as earlier + * part don't have correct value fused */ + /* default DCF CLK DPM on RV*/ + .dcfclkv_max0p9 = 655, /* MHz, = 3600/5.5 */ + .dcfclkv_nom0p8 = 626, /* MHz, = 3600/5.75 */ + .dcfclkv_mid0p72 = 600, /* MHz, = 3600/6, bypass */ + .dcfclkv_min0p65 = 300, /* MHz, = 3600/12, bypass */ + + /* default DISP CLK voltage state on RV */ + .max_dispclk_vmax0p9 = 1108, /* MHz, = 3600/3.25 */ + .max_dispclk_vnom0p8 = 1029, /* MHz, = 3600/3.5 */ + .max_dispclk_vmid0p72 = 960, /* MHz, = 3600/3.75 */ + .max_dispclk_vmin0p65 = 626, /* MHz, = 3600/5.75 */ + + /* default DPP CLK voltage state on RV */ + .max_dppclk_vmax0p9 = 720, /* MHz, = 3600/5 */ + .max_dppclk_vnom0p8 = 686, /* MHz, = 3600/5.25 */ + .max_dppclk_vmid0p72 = 626, /* MHz, = 3600/5.75 */ + .max_dppclk_vmin0p65 = 400, /* MHz, = 3600/9 */ + + /* default PHY CLK voltage state on RV */ + .phyclkv_max0p9 = 900, /*MHz*/ + .phyclkv_nom0p8 = 847, /*MHz*/ + .phyclkv_mid0p72 = 800, /*MHz*/ + .phyclkv_min0p65 = 600, /*MHz*/ + + /* BW depend on FCLK, MCLK, # of channels */ + /* dual channel BW */ .fabric_and_dram_bandwidth_vmax0p9 = 38.4f, /*GB/s*/ - .fabric_and_dram_bandwidth_vnom0p8 = 34.1f, /*GB/s*/ - .fabric_and_dram_bandwidth_vmid0p72 = 29.8f, /*GB/s*/ + .fabric_and_dram_bandwidth_vnom0p8 = 34.133f, /*GB/s*/ + .fabric_and_dram_bandwidth_vmid0p72 = 29.866f, /*GB/s*/ .fabric_and_dram_bandwidth_vmin0p65 = 12.8f, /*GB/s*/ - .phyclkv_max0p9 = 810, /*MHz*/ - .phyclkv_nom0p8 = 810, /*MHz*/ - .phyclkv_mid0p72 = 540, /*MHz*/ - .phyclkv_min0p65 = 540, /*MHz*/ + /* single channel BW + .fabric_and_dram_bandwidth_vmax0p9 = 19.2f, + .fabric_and_dram_bandwidth_vnom0p8 = 17.066f, + .fabric_and_dram_bandwidth_vmid0p72 = 14.933f, + .fabric_and_dram_bandwidth_vmin0p65 = 12.8f, + */ + + .number_of_channels = 2, + + .socclk = 208, /*MHz*/ .downspreading = 0.5f, /*%*/ .round_trip_ping_latency_cycles = 128, /*DCFCLK Cycles*/ .urgent_out_of_order_return_per_channel = 256, /*bytes*/ - .number_of_channels = 2, .vmm_page_size = 4096, /*bytes*/ - .dram_clock_change_latency = 17, /*us*/ .return_bus_width = 64, /*bytes*/ + .max_request_size = 256, /*bytes*/ }; const struct dcn_ip_params dcn10_ip_defaults = { -- GitLab From f42485bb6d1171272d5ecb5b6213505b14294472 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 4 Jul 2017 14:13:25 -0400 Subject: [PATCH 0607/2898] drm/amd/display: move number of memory channel calc out of pplib call Move number of memory channel calculation out of dcn_bw_update_from_pplib Fill in fabric_and_dram_bandwidth for single channel case. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 ---- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 58a4b2e90c15..93384a3f3525 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1215,10 +1215,6 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) struct dm_pp_clock_levels_with_voltage clks2 = {0}; kernel_fpu_begin(); - dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; - ASSERT(dc->dcn_soc.number_of_channels && dc->dcn_soc.number_of_channels < 3); - if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ - dc->dcn_soc.number_of_channels = 2; if (dm_pp_get_clock_levels_by_type_with_voltage( ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks2) && diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index fcea49e9f665..66b5d3027336 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1358,6 +1358,19 @@ static bool construct( dml_init_instance(&dc->dml, DML_PROJECT_RAVEN1); dc->dcn_ip = dcn10_ip_defaults; dc->dcn_soc = dcn10_soc_defaults; + + dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc.number_of_channels < 3); + if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc.number_of_channels = 2; + + if (dc->dcn_soc.number_of_channels == 1) { + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 19.2f; + dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = 17.066f; + dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = 14.933f; + dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + } + if (!dc->public.debug.disable_pplib_clock_request) dcn_bw_update_from_pplib(dc); dcn_bw_sync_calcs_and_dml(dc); -- GitLab From 966443b592753f6498f896b4afc7c2df1352af72 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 27 Jun 2017 12:09:01 -0400 Subject: [PATCH 0608/2898] drm/amd/display: block modes that require read bw greater than 30% Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 18 +++++++++++++++++- drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 93384a3f3525..24f8c4496a61 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -95,6 +95,9 @@ const struct dcn_soc_bounding_box dcn10_soc_defaults = { .vmm_page_size = 4096, /*bytes*/ .return_bus_width = 64, /*bytes*/ .max_request_size = 256, /*bytes*/ + + /* Depends on user class (client vs embedded, workstation, etc) */ + .percent_disp_bw_limit = 0.3f /*%*/ }; const struct dcn_ip_params dcn10_ip_defaults = { @@ -695,6 +698,8 @@ bool dcn_validate_bandwidth( struct dcn_bw_internal_vars *v = &context->dcn_bw_vars; int i, input_idx; int vesa_sync_start, asic_blank_end, asic_blank_start; + bool bw_limit_pass; + float bw_limit; if (dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public))) dcn_bw_sync_calcs_and_dml(DC_TO_CORE(&dc->public)); @@ -1072,8 +1077,19 @@ bool dcn_validate_bandwidth( dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc.sr_exit_time; } + /* + * BW limit is set to prevent display from impacting other system functions + */ + + bw_limit = dc->dcn_soc.percent_disp_bw_limit * v->fabric_and_dram_bandwidth_vmax0p9; + bw_limit_pass = (v->total_data_read_bandwidth / 1000.0) < bw_limit; + kernel_fpu_end(); - return v->voltage_level != 5; + + if (bw_limit_pass && v->voltage_level != 5) + return true; + else + return false; } unsigned int dcn_find_normalized_clock_vdd_Level( diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 499bc1127696..b6cc07450f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -572,6 +572,7 @@ struct dcn_soc_bounding_box { int vmm_page_size; /*bytes*/ float dram_clock_change_latency; /*us*/ int return_bus_width; /*bytes*/ + float percent_disp_bw_limit; /*%*/ }; extern const struct dcn_soc_bounding_box dcn10_soc_defaults; -- GitLab From 133e8e1b35c7772f4903d367035e33e02becbb2d Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 5 Jul 2017 15:30:18 -0400 Subject: [PATCH 0609/2898] drm/amd/display: Change how we disable pipe split Before this change, pipe split was disabled by bumping up dpp clock bounding box for DPM level 0 and 1, this allows validation to pass without splitting at a lower DPM level. This change reverts this and instead lowers display clock at DPM level 0, this forces configurations that need pipe split at DPM level 0 to go to DPM level 1, where they can be driven without split. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 24f8c4496a61..3118c248409f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -822,8 +822,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[0] = v->phyclkv_min0p65; if (dc->public.debug.disable_pipe_split) { - v->max_dppclk[1] = v->max_dppclk_vnom0p8; - v->max_dppclk[0] = v->max_dppclk_vnom0p8; + v->max_dispclk[0] = v->max_dppclk_vmin0p65; } if (v->voltage_override == dcn_bw_v_max0p9) { -- GitLab From b884a2ec5863c863a625ef4ee0efee59f969142d Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 6 Jul 2017 14:20:25 -0400 Subject: [PATCH 0610/2898] drm/amd/display: call pplib to update clocks Allow pplib to update fclk and dcfclk for different voltage levels. PPlib's values for dispclk and phyclk is not correct, so we are not getting it from them. fclk is currently not used correctly, although does not effect the actual fclk we request. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 46 ++----------------- 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 3118c248409f..a1eabc47558e 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1226,28 +1226,13 @@ unsigned int dcn_find_dcfclk_suits_all( void dcn_bw_update_from_pplib(struct core_dc *dc) { struct dc_context *ctx = dc->ctx; - struct dm_pp_clock_levels_with_latency clks = {0}; - struct dm_pp_clock_levels_with_voltage clks2 = {0}; + struct dm_pp_clock_levels_with_voltage clks = {0}; kernel_fpu_begin(); + /* TODO: This is not the proper way to obtain fabric_and_dram_bandwidth, should be min(fclk, memclk) */ + if (dm_pp_get_clock_levels_by_type_with_voltage( - ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks2) && - clks2.num_levels >= 3) { - dc->dcn_soc.max_dispclk_vmin0p65 = clks2.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dispclk_vmid0p72 = clks2.data[clks2.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dispclk_vnom0p8 = clks2.data[clks2.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dispclk_vmax0p9 = clks2.data[clks2.num_levels - 1].clocks_in_khz / 1000.0; - } else - BREAK_TO_DEBUGGER(); -/* - if (dm_pp_get_clock_levels_by_type_with_latency( - ctx, DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks) && - clks.num_levels != 0) { - //this is to get DRAM data_rate - //FabricAndDRAMBandwidth = min(64*FCLK , Data rate * single_Channel_Width * number of channels); - }*/ - if (dm_pp_get_clock_levels_by_type_with_latency( ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && clks.num_levels != 0) { ASSERT(clks.num_levels >= 3); @@ -1265,7 +1250,7 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) (clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; } else BREAK_TO_DEBUGGER(); - if (dm_pp_get_clock_levels_by_type_with_latency( + if (dm_pp_get_clock_levels_by_type_with_voltage( ctx, DM_PP_CLOCK_TYPE_DCFCLK, &clks) && clks.num_levels >= 3) { dc->dcn_soc.dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; @@ -1274,30 +1259,7 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) dc->dcn_soc.dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; } else BREAK_TO_DEBUGGER(); - if (dm_pp_get_clock_levels_by_type_with_voltage( - ctx, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, &clks2) && - clks2.num_levels >= 3) { - dc->dcn_soc.phyclkv_min0p65 = clks2.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc.phyclkv_mid0p72 = clks2.data[clks2.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc.phyclkv_nom0p8 = clks2.data[clks2.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc.phyclkv_max0p9 = clks2.data[clks2.num_levels - 1].clocks_in_khz / 1000.0; - } else - BREAK_TO_DEBUGGER(); - if (dm_pp_get_clock_levels_by_type_with_latency( - ctx, DM_PP_CLOCK_TYPE_DPPCLK, &clks) && - clks.num_levels >= 3) { - dc->dcn_soc.max_dppclk_vmin0p65 = clks.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dppclk_vmid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dppclk_vnom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc.max_dppclk_vmax0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; - } - if (dm_pp_get_clock_levels_by_type_with_latency( - ctx, DM_PP_CLOCK_TYPE_SOCCLK, &clks) && - clks.num_levels >= 3) { - dc->dcn_soc.socclk = clks.data[0].clocks_in_khz / 1000.0; - } else - BREAK_TO_DEBUGGER(); kernel_fpu_end(); } -- GitLab From fa6ecfc67a4a0f96b5e4b6d5437602f2d5b191ac Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 6 Jul 2017 13:53:15 -0400 Subject: [PATCH 0611/2898] drm/amd/display: Refactor dc_commit_streams Change it to sue dc_commit_context. dc_commit_context is used directly from Linux DM. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 99 ++++++++++-------------- 1 file changed, 41 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2f93f0e9ba84..52077d39b30a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -913,33 +913,22 @@ bool dc_enable_stereo( return ret; } -/* TODO operate on validation set (or something like it) */ -bool dc_commit_context(struct dc *dc, struct validate_context *context) + +/* + * Applies given context to HW and copy it into current context. + * It's up to the user to release the src context afterwards. + */ +static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; int i, j, k, l; + const struct dc_stream *dc_streams[MAX_STREAMS] = {0}; - if (!context) - dm_logger_write(core_dc->ctx->logger, LOG_ERROR, - "%s: dc_commit_context with no context!\n", - __func__); - - if (false == context_changed(core_dc, context)) - return DC_OK; - - dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", - __func__, context->stream_count); - - for (i = 0; i < context->stream_count; i++) { - const struct dc_stream *stream = &context->streams[i]->public; - - dc_stream_log(stream, - core_dc->ctx->logger, - LOG_DC); - } + for (i = 0; i < context->stream_count; i++) + dc_streams[i] = &context->streams[i]->public; if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); @@ -981,22 +970,49 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) context->streams[i]->public.timing.pix_clk_khz); } + dc_enable_stereo(dc, context, dc_streams, context->stream_count); + dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); return (result == DC_OK); } +bool dc_commit_context(struct dc *dc, struct validate_context *context) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + struct core_dc *core_dc = DC_TO_CORE(dc); + int i; + + if (false == context_changed(core_dc, context)) + return DC_OK; + + dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", + __func__, context->stream_count); + + for (i = 0; i < context->stream_count; i++) { + const struct dc_stream *stream = &context->streams[i]->public; + + dc_stream_log(stream, + core_dc->ctx->logger, + LOG_DC); + } + + result = dc_commit_context_no_check(dc, context); + + return (result == DC_OK); +} + + bool dc_commit_streams( struct dc *dc, const struct dc_stream *streams[], uint8_t stream_count) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; - int i, j; + int i; if (false == streams_changed(core_dc, streams, stream_count)) return DC_OK; @@ -1039,43 +1055,10 @@ bool dc_commit_streams( goto fail; } - if (!dcb->funcs->is_accelerated_mode(dcb)) { - core_dc->hwss.enable_accelerated_mode(core_dc); - } - - if (result == DC_OK) { - result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); - } - - program_timing_sync(core_dc, context); - - for (i = 0; i < context->stream_count; i++) { - const struct core_sink *sink = context->streams[i]->sink; - - for (j = 0; j < context->stream_status[i].surface_count; j++) { - struct core_surface *surface = - DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); - - core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); - } + result = dc_commit_context_no_check(dc, context); - CONN_MSG_MODE(sink->link, "{%ux%u, %ux%u@%u, %ux%u@%uKhz}", - context->streams[i]->public.src.width, - context->streams[i]->public.src.height, - context->streams[i]->public.timing.h_addressable, - context->streams[i]->public.timing.v_addressable, - context->streams[i]->public.timing.pix_clk_khz * 1000 / - context->streams[i]->public.timing.h_total / - context->streams[i]->public.timing.v_total, // Refresh rate - context->streams[i]->public.timing.h_total, - context->streams[i]->public.timing.v_total, - context->streams[i]->public.timing.pix_clk_khz); - } - dc_enable_stereo(dc, context, streams, stream_count); - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); - - core_dc->current_context = context; + dc_resource_validate_ctx_destruct(context); + dm_free(context); return (result == DC_OK); -- GitLab From 184debdbd80bd9d47eb68304417adb6580ff09e4 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 5 Jul 2017 06:57:49 -0400 Subject: [PATCH 0612/2898] drm/amd/display: refactor dcn10 hw_sequencer to new reg access style Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 177 +++++- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 530 ++++-------------- .../gpu/drm/amd/display/dc/inc/reg_helper.h | 66 ++- 3 files changed, 343 insertions(+), 430 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 112f9c85c142..761dba3562b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -122,11 +122,56 @@ HWSEQ_PHYPLL_REG_LIST(CRTC) #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#define HWSEQ_DCN1_REG_LIST()\ +#define HWSEQ_DCN_REG_LIST()\ HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ - HWSEQ_PHYPLL_REG_LIST(OTG) + HWSEQ_PHYPLL_REG_LIST(OTG), \ + SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ + SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 1), \ + SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 2), \ + SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 3), \ + SRII(DCHUBP_CNTL, HUBP, 0), \ + SRII(DCHUBP_CNTL, HUBP, 1), \ + SRII(DCHUBP_CNTL, HUBP, 2), \ + SRII(DCHUBP_CNTL, HUBP, 3), \ + SRII(HUBP_CLK_CNTL, HUBP, 0), \ + SRII(HUBP_CLK_CNTL, HUBP, 1), \ + SRII(HUBP_CLK_CNTL, HUBP, 2), \ + SRII(HUBP_CLK_CNTL, HUBP, 3), \ + SRII(DPP_CONTROL, DPP_TOP, 0), \ + SRII(DPP_CONTROL, DPP_TOP, 1), \ + SRII(DPP_CONTROL, DPP_TOP, 2), \ + SRII(DPP_CONTROL, DPP_TOP, 3), \ + SR(REFCLK_CNTL), \ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN4_PG_CONFIG), \ + SR(DOMAIN5_PG_CONFIG), \ + SR(DOMAIN6_PG_CONFIG), \ + SR(DOMAIN7_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN4_PG_STATUS), \ + SR(DOMAIN5_PG_STATUS), \ + SR(DOMAIN6_PG_STATUS), \ + SR(DOMAIN7_PG_STATUS), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL) +#endif + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN1_REG_LIST()\ + HWSEQ_DCN_REG_LIST() #endif + struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFEV_CLOCK_CONTROL; @@ -134,13 +179,39 @@ struct dce_hwseq_registers { uint32_t BLND_V_UPDATE_LOCK[6]; uint32_t BLND_CONTROL[6]; uint32_t BLNDV_CONTROL; - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - /* DCE + DCN */ -#endif uint32_t CRTC_H_BLANK_START_END[6]; uint32_t PIXEL_RATE_CNTL[6]; uint32_t PHYPLL_PIXEL_RATE_CNTL[6]; + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + uint32_t OTG_GLOBAL_SYNC_STATUS[4]; + uint32_t DCHUBP_CNTL[4]; + uint32_t HUBP_CLK_CNTL[4]; + uint32_t DPP_CONTROL[4]; + uint32_t REFCLK_CNTL; + uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; + uint32_t DC_IP_REQUEST_CNTL; + uint32_t DOMAIN0_PG_CONFIG; + uint32_t DOMAIN1_PG_CONFIG; + uint32_t DOMAIN2_PG_CONFIG; + uint32_t DOMAIN3_PG_CONFIG; + uint32_t DOMAIN4_PG_CONFIG; + uint32_t DOMAIN5_PG_CONFIG; + uint32_t DOMAIN6_PG_CONFIG; + uint32_t DOMAIN7_PG_CONFIG; + uint32_t DOMAIN0_PG_STATUS; + uint32_t DOMAIN1_PG_STATUS; + uint32_t DOMAIN2_PG_STATUS; + uint32_t DOMAIN3_PG_STATUS; + uint32_t DOMAIN4_PG_STATUS; + uint32_t DOMAIN5_PG_STATUS; + uint32_t DOMAIN6_PG_STATUS; + uint32_t DOMAIN7_PG_STATUS; + uint32_t DIO_MEM_PWR_CTRL; + uint32_t DCCG_GATE_DISABLE_CNTL; + uint32_t DCCG_GATE_DISABLE_CNTL2; + uint32_t DCFCLK_CNTL; +#endif }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -202,12 +273,52 @@ struct dce_hwseq_registers { HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ +#define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ - HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, OTG0_) + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, OTG0_),\ + HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR, mask_sh), \ + HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, mask_sh), \ + HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh), \ + HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh), \ + HWS_SF(HUBP0_, HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh), \ + HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) +#endif + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh), \ + HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh) #endif -#define HWSEQ_REG_FIED_LIST(type) \ +#define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ type DCFEV_CLOCK_ENABLE; \ type DC_MEM_GLOBAL_PWR_REQ_DIS; \ @@ -225,12 +336,56 @@ struct dce_hwseq_registers { type PHYPLL_PIXEL_RATE_SOURCE; \ type PIXEL_RATE_PLL_SOURCE; \ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#define HWSEQ_DCN_REG_FIELD_LIST(type) \ + type VUPDATE_NO_LOCK_EVENT_CLEAR; \ + type VUPDATE_NO_LOCK_EVENT_OCCURRED; \ + type HUBP_NO_OUTSTANDING_REQ; \ + type HUBP_VTG_SEL; \ + type HUBP_CLOCK_ENABLE; \ + type DPP_CLOCK_ENABLE; \ + type DPPCLK_RATE_CONTROL; \ + type DCHUBBUB_GLOBAL_TIMER_ENABLE; \ + type IP_REQUEST_EN; \ + type DOMAIN0_POWER_FORCEON; \ + type DOMAIN0_POWER_GATE; \ + type DOMAIN1_POWER_FORCEON; \ + type DOMAIN1_POWER_GATE; \ + type DOMAIN2_POWER_FORCEON; \ + type DOMAIN2_POWER_GATE; \ + type DOMAIN3_POWER_FORCEON; \ + type DOMAIN3_POWER_GATE; \ + type DOMAIN4_POWER_FORCEON; \ + type DOMAIN4_POWER_GATE; \ + type DOMAIN5_POWER_FORCEON; \ + type DOMAIN5_POWER_GATE; \ + type DOMAIN6_POWER_FORCEON; \ + type DOMAIN6_POWER_GATE; \ + type DOMAIN7_POWER_FORCEON; \ + type DOMAIN7_POWER_GATE; \ + type DOMAIN0_PGFSM_PWR_STATUS; \ + type DOMAIN1_PGFSM_PWR_STATUS; \ + type DOMAIN2_PGFSM_PWR_STATUS; \ + type DOMAIN3_PGFSM_PWR_STATUS; \ + type DOMAIN4_PGFSM_PWR_STATUS; \ + type DOMAIN5_PGFSM_PWR_STATUS; \ + type DOMAIN6_PGFSM_PWR_STATUS; \ + type DOMAIN7_PGFSM_PWR_STATUS; \ + type DCFCLK_GATE_DIS; +#endif + struct dce_hwseq_shift { - HWSEQ_REG_FIED_LIST(uint8_t) + HWSEQ_REG_FIELD_LIST(uint8_t) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + HWSEQ_DCN_REG_FIELD_LIST(uint8_t) +#endif }; struct dce_hwseq_mask { - HWSEQ_REG_FIED_LIST(uint32_t) + HWSEQ_REG_FIELD_LIST(uint32_t) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + HWSEQ_DCN_REG_FIELD_LIST(uint32_t) +#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d38570e6d4d2..fb326316b08b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -33,381 +33,120 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" - -#include "dcn10/dcn10_transform.h" -#include "dcn10/dcn10_mpc.h" -#include "dcn10/dcn10_timing_generator.h" - #include "mem_input.h" #include "timing_generator.h" #include "opp.h" #include "ipp.h" - #include "dc_bios_types.h" - #include "raven1/DCN/dcn_1_0_offset.h" #include "raven1/DCN/dcn_1_0_sh_mask.h" #include "vega10/soc15ip.h" - #include "custom_float.h" +#include "reg_helper.h" +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg -struct dcn10_hwseq_reg_offsets { - uint32_t dchubp; - uint32_t dpp; - uint32_t otg; - uint32_t vtg; - uint32_t fmt; -}; - -/* TODO: move to resource */ -static const struct dcn10_hwseq_reg_offsets reg_offsets[] = { - { - .dchubp = (mmHUBP0_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), - .dpp = (mmCM0_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), - .otg = (mmOTG0_OTG_CONTROL - mmOTG0_OTG_CONTROL), - .vtg = (mmVTG0_CONTROL - mmVTG0_CONTROL), - .fmt = (mmFMT0_FMT_BIT_DEPTH_CONTROL - - mmFMT0_FMT_BIT_DEPTH_CONTROL), - }, - { - .dchubp = (mmHUBP1_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), - .dpp = (mmCM1_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), - .otg = (mmOTG1_OTG_CONTROL - mmOTG0_OTG_CONTROL), - .vtg = (mmVTG1_CONTROL - mmVTG0_CONTROL), - .fmt = (mmFMT1_FMT_BIT_DEPTH_CONTROL - - mmFMT0_FMT_BIT_DEPTH_CONTROL), - }, - { - .dchubp = (mmHUBP2_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), - .dpp = (mmCM2_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), - .otg = (mmOTG2_OTG_CONTROL - mmOTG0_OTG_CONTROL), - .vtg = (mmVTG2_CONTROL - mmVTG0_CONTROL), - .fmt = (mmFMT2_FMT_BIT_DEPTH_CONTROL - - mmFMT0_FMT_BIT_DEPTH_CONTROL), - }, - { - .dchubp = (mmHUBP3_DCHUBP_CNTL - mmHUBP0_DCHUBP_CNTL), - .dpp = (mmCM3_CM_DGAM_CONTROL - mmCM0_CM_DGAM_CONTROL), - .otg = (mmOTG3_OTG_CONTROL - mmOTG0_OTG_CONTROL), - .vtg = (mmVTG3_CONTROL - mmVTG0_CONTROL), - .fmt = (mmFMT3_FMT_BIT_DEPTH_CONTROL - - mmFMT0_FMT_BIT_DEPTH_CONTROL), - } -}; - -#define HWSEQ_REG_UPDATE_N(reg_name, n, ...) \ - generic_reg_update_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__) - -#define HWSEQ_REG_SET_N(reg_name, n, ...) \ - generic_reg_set_soc15(ctx, inst_offset, reg_name, n, __VA_ARGS__) - -#define HWSEQ_REG_UPDATE(reg, field, val) \ - HWSEQ_REG_UPDATE_N(reg, 1, FD(reg##__##field), val) - -#define HWSEQ_REG_UPDATE_2(reg, field1, val1, field2, val2) \ - HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2) - -#define HWSEQ_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3) \ - HWSEQ_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3) - - -#define HWSEQ_REG_SET(reg, field, val) \ - HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val) - -/* TODO should be moved to OTG */ - -static bool unlock_master_tg_and_wait( - struct dc_context *ctx, - uint8_t inst) -{ - uint32_t inst_offset = reg_offsets[inst].otg; - - HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_SYNC_STATUS, - VUPDATE_NO_LOCK_EVENT_CLEAR, 1); - HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, 0); - - if (!wait_reg(ctx, inst_offset, OTG0_OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, 1)) { - dm_logger_write(ctx->logger, LOG_ERROR, - "wait for VUPDATE_NO_LOCK_EVENT_OCCURRED failed\n"); - BREAK_TO_DEBUGGER(); - return false; - } - return true; -} - -static void wait_no_outstanding_request( - struct dc_context *ctx, - uint8_t plane_id) -{ - uint32_t inst_offset = reg_offsets[plane_id].dchubp; - - if (!wait_reg(ctx, inst_offset, HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1)) - BREAK_TO_DEBUGGER(); -} +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name static void disable_clocks( - struct dc_context *ctx, + struct dce_hwseq *hws, uint8_t plane_id) { - uint32_t inst_offset = reg_offsets[plane_id].dchubp; - - generic_reg_update_soc15(ctx, inst_offset, HUBP0_HUBP_CLK_CNTL, 1, - FD(HUBP0_HUBP_CLK_CNTL__HUBP_CLOCK_ENABLE), 0); + REG_UPDATE(HUBP_CLK_CNTL[plane_id], HUBP_CLOCK_ENABLE, 0); - inst_offset = reg_offsets[plane_id].dpp; - generic_reg_update_soc15(ctx, inst_offset, DPP_TOP0_DPP_CONTROL, 1, - FD(DPP_TOP0_DPP_CONTROL__DPP_CLOCK_ENABLE), 0); -} - -/* TODO: This is one time program during system boot up, - * this should be done within BIOS or CAIL - */ -static void dchubp_map_fb_to_mc(struct dc_context *ctx) -{ - /* TODO: do not know where to program - * DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB - */ - /* - * TODO: For real ASIC, FB_OFFSET may be need change to the same value - * as FB_BASE. Need re-visit this for real ASIC. - */ - dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_BASE, 0, 0x80); - dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_OFFSET, 0, 0); - dm_write_reg_soc15(ctx, mmDCHUBBUB_SDPIF_FB_TOP, 0, 0xFF); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG0, 7, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_DATA_RESPONSE_STATUS_CLEAR), 0, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_ERROR_CLEAR), 0, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_FLUSH_REQ_CREDIT_EN), 0, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_REQ_CREDIT_EN), 0, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_PORT_CONTROL), 1, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_UNIT_ID_BITMASK), 0xd3, - FD(DCHUBBUB_SDPIF_CFG0__SDPIF_CREDIT_DISCONNECT_DELAY), 0xc); - - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_CFG1, 4, - FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_IO), 0, - FD(DCHUBBUB_SDPIF_CFG1__SDPIF_INSIDE_FB_VC), 6, - FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_IO), 1, - FD(DCHUBBUB_SDPIF_CFG1__SDPIF_OUTSIDE_FB_VC), 6); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_BASE, 1, - FD(DCHUBBUB_SDPIF_FB_BASE__SDPIF_FB_BASE), 0x000080); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_FB_TOP, 1, - FD(DCHUBBUB_SDPIF_FB_TOP__SDPIF_FB_TOP), 0x0000ff); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BOT, 1, - FD(DCHUBBUB_SDPIF_AGP_BOT__SDPIF_AGP_BOT), 0x0000040); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_TOP, 1, - FD(DCHUBBUB_SDPIF_AGP_TOP__SDPIF_AGP_TOP), 0x00001ff); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_AGP_BASE, 1, - FD(DCHUBBUB_SDPIF_AGP_BASE__SDPIF_AGP_BASE), 0x0000080); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_TOP, 1, - FD(DCHUBBUB_SDPIF_APER_TOP__SDPIF_APER_TOP), 0x00007ff); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_APER_DEF_0, 1, - FD(DCHUBBUB_SDPIF_APER_DEF_0__SDPIF_APER_DEF_0), 0xdeadbeef); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_0, 2, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_EN_0), 0, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_0__SDPIF_MARC_RELOC_LO_0), 0x90000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_0, 1, - FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_0__SDPIF_MARC_LENGTH_LO_0), 0x10000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_1, 1, - FD(DCHUBBUB_SDPIF_MARC_BASE_LO_1__SDPIF_MARC_BASE_LO_1), 0x10000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_1, 2, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_EN_1), 0, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_1__SDPIF_MARC_RELOC_LO_1), 0xa0000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_1, 1, - FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_1__SDPIF_MARC_LENGTH_LO_1), 0x10000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_2, 1, - FD(DCHUBBUB_SDPIF_MARC_BASE_LO_2__SDPIF_MARC_BASE_LO_2), 0x20000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_2, 2, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_EN_2), 0, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_2__SDPIF_MARC_RELOC_LO_2), 0xb0000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_2, 1, - FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_2__SDPIF_MARC_LENGTH_LO_2), 0x10000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_BASE_LO_3, 1, - FD(DCHUBBUB_SDPIF_MARC_BASE_LO_3__SDPIF_MARC_BASE_LO_3), 0x30000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_RELOC_LO_3, 2, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_EN_3), 0, - FD(DCHUBBUB_SDPIF_MARC_RELOC_LO_3__SDPIF_MARC_RELOC_LO_3), 0xc0000); - - generic_reg_set_soc15(ctx, 0, DCHUBBUB_SDPIF_MARC_LENGTH_LO_3, 1, - FD(DCHUBBUB_SDPIF_MARC_LENGTH_LO_3__SDPIF_MARC_LENGTH_LO_3), 0x10000); - - /* TODO: Is DCN_VM_SYSTEM_APERTURE address one time programming? - * Are all 4 hubp programmed with the same address? - */ - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); - - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ1_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); - - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ2_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); - - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0, 0x100000); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0, 0); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, 0x80000); - dm_write_reg_soc15(ctx, mmHUBPREQ3_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, 0); -} - -/* TODO: This is one time program during system boot up, - * this should be done within BIOS - */ -static void dchubup_setup_timer(struct dc_context *ctx) -{ - dm_write_reg_soc15(ctx, mmREFCLK_CNTL, 0, 0); - - generic_reg_update_soc15(ctx, 0, DCHUBBUB_GLOBAL_TIMER_CNTL, 1, - FD(DCHUBBUB_GLOBAL_TIMER_CNTL__DCHUBBUB_GLOBAL_TIMER_ENABLE), 1); -} - -/* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG - * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. - * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG - */ -static void select_vtg( - struct dc_context *ctx, - uint8_t plane_id, - uint8_t inst) -{ - uint32_t inst_offset = reg_offsets[plane_id].dchubp; - - HWSEQ_REG_UPDATE(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, inst); -} - -static void enable_dcfclk( - struct dc_context *ctx, - uint8_t plane_id, - uint32_t requested_pix_clk, - bool dppclk_div) -{ - uint32_t inst_offset = reg_offsets[plane_id].dchubp; - - HWSEQ_REG_UPDATE(HUBP0_HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, 1); + REG_UPDATE(DPP_CONTROL[plane_id], DPP_CLOCK_ENABLE, 0); } static void enable_dppclk( - struct dc_context *ctx, + struct dce_hwseq *hws, uint8_t plane_id, uint32_t requested_pix_clk, bool dppclk_div) { - uint32_t inst_offset = reg_offsets[plane_id].dpp; - - dm_logger_write(ctx->logger, LOG_SURFACE, + dm_logger_write(hws->ctx->logger, LOG_SURFACE, "dppclk_rate_control for pipe %d programed to %d\n", plane_id, dppclk_div); - /* TODO: find condition for DPP clock to DISPCLK or 1/2 DISPCLK */ if (dppclk_div) { /* 1/2 DISPCLK*/ - HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL, + REG_UPDATE_2(DPP_CONTROL[plane_id], DPPCLK_RATE_CONTROL, 1, DPP_CLOCK_ENABLE, 1); } else { /* DISPCLK */ - HWSEQ_REG_UPDATE_2(DPP_TOP0_DPP_CONTROL, + REG_UPDATE_2(DPP_CONTROL[plane_id], DPPCLK_RATE_CONTROL, 0, DPP_CLOCK_ENABLE, 1); } } static void enable_power_gating_plane( - struct dc_context *ctx, + struct dce_hwseq *hws, bool enable) { - uint32_t inst_offset = 0; /* each register only has one instance */ bool force_on = 1; /* disable power gating */ if (enable) force_on = 0; /* DCHUBP0/1/2/3 */ - HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on); /* DPP0/1/2/3 */ - HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); - HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); + REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); } static void dpp_pg_control( - struct dc_context *ctx, + struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on) { - uint32_t inst_offset = 0; uint32_t power_gate = power_on ? 0 : 1; uint32_t pwr_status = power_on ? 0 : 2; - if (ctx->dc->debug.disable_dpp_power_gate) + if (hws->ctx->dc->debug.disable_dpp_power_gate) return; switch (dpp_inst) { case 0: /* DPP0 */ - HWSEQ_REG_UPDATE(DOMAIN1_PG_CONFIG, + REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN1_PG_STATUS, - DOMAIN1_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN1_PG_STATUS, + DOMAIN1_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 1: /* DPP1 */ - HWSEQ_REG_UPDATE(DOMAIN3_PG_CONFIG, + REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN3_PG_STATUS, - DOMAIN3_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN3_PG_STATUS, + DOMAIN3_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 2: /* DPP2 */ - HWSEQ_REG_UPDATE(DOMAIN5_PG_CONFIG, + REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN5_PG_STATUS, - DOMAIN5_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN5_PG_STATUS, + DOMAIN5_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 3: /* DPP3 */ - HWSEQ_REG_UPDATE(DOMAIN7_PG_CONFIG, + REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN7_PG_STATUS, - DOMAIN7_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN7_PG_STATUS, + DOMAIN7_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; default: BREAK_TO_DEBUGGER(); @@ -416,45 +155,44 @@ static void dpp_pg_control( } static void hubp_pg_control( - struct dc_context *ctx, + struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) { - uint32_t inst_offset = 0; uint32_t power_gate = power_on ? 0 : 1; uint32_t pwr_status = power_on ? 0 : 2; - if (ctx->dc->debug.disable_hubp_power_gate) + if (hws->ctx->dc->debug.disable_hubp_power_gate) return; switch (hubp_inst) { case 0: /* DCHUBP0 */ - HWSEQ_REG_UPDATE(DOMAIN0_PG_CONFIG, + REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN0_PG_STATUS, - DOMAIN0_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN0_PG_STATUS, + DOMAIN0_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 1: /* DCHUBP1 */ - HWSEQ_REG_UPDATE(DOMAIN2_PG_CONFIG, + REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN2_PG_STATUS, - DOMAIN2_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN2_PG_STATUS, + DOMAIN2_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 2: /* DCHUBP2 */ - HWSEQ_REG_UPDATE(DOMAIN4_PG_CONFIG, + REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN4_PG_STATUS, - DOMAIN4_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN4_PG_STATUS, + DOMAIN4_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; case 3: /* DCHUBP3 */ - HWSEQ_REG_UPDATE(DOMAIN6_PG_CONFIG, + REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, power_gate); - wait_reg(ctx, 0, DOMAIN6_PG_STATUS, - DOMAIN6_PGFSM_PWR_STATUS, pwr_status); + REG_WAIT(DOMAIN6_PG_STATUS, + DOMAIN6_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); break; default: BREAK_TO_DEBUGGER(); @@ -463,18 +201,16 @@ static void hubp_pg_control( } static void power_on_plane( - struct dc_context *ctx, + struct dce_hwseq *hws, int plane_id) { - uint32_t inst_offset = 0; - - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - dpp_pg_control(ctx, plane_id, true); - hubp_pg_control(ctx, plane_id, true); - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + dpp_pg_control(hws, plane_id, true); + hubp_pg_control(hws, plane_id, true); + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - dm_logger_write(ctx->logger, LOG_DC, + dm_logger_write(hws->ctx->logger, LOG_DC, "Un-gated front end for pipe %d\n", plane_id); } @@ -513,47 +249,54 @@ static void bios_golden_init(struct core_dc *dc) } } +/* + * This should be done within BIOS, we are doing it for maximus only + */ +static void dchubup_setup_timer(struct dce_hwseq *hws) +{ + REG_WRITE(REFCLK_CNTL, 0); + + REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); +} + static void init_hw(struct core_dc *dc) { int i; - struct dc_bios *bp; struct transform *xfm; struct abm *abm; + struct dce_hwseq *hws = dc->hwseq; - bp = dc->ctx->dc_bios; - +#if 1 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - /* TODO: this will be moved to Diag or BIOS */ - dchubup_setup_timer(dc->ctx); + dchubup_setup_timer(dc->hwseq); /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface * between dc and kmd */ - dchubp_map_fb_to_mc(dc->ctx); + /*dchubp_map_fb_to_mc(dc->hwseq);*/ + REG_WRITE(DIO_MEM_PWR_CTRL, 0); + + if (!dc->public.debug.disable_clock_gate) { + /* enable all DCN clock gating */ + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - enable_power_gating_plane(dc->ctx, true); + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); + + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + + enable_power_gating_plane(dc->hwseq, true); return; } /* end of FPGA. Below if real ASIC */ +#endif bios_golden_init(dc); for (i = 0; i < dc->res_pool->pipe_count; i++) { xfm = dc->res_pool->transforms[i]; xfm->funcs->transform_reset(xfm); - - /* TODOFPGA: may need later */ -#if 0 - xfm->funcs->transform_power_up(xfm); - dc->hwss.enable_display_pipe_clock_gating( - dc->ctx, - true); -#endif } - /* TODOFPGA: light sleep */ -#if 0 - dc->hwss.clock_gating_power_up(dc->ctx, false); -#endif for (i = 0; i < dc->link_count; i++) { /* Power up AND update implementation according to the @@ -601,67 +344,18 @@ static void init_hw(struct core_dc *dc) } /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - generic_reg_set_soc15(dc->ctx, 0, DIO_MEM_PWR_CTRL, 7, - FD(DIO_MEM_PWR_CTRL__HDMI0_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI1_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI2_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI3_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI4_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE), 0, - FD(DIO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE), 0); + REG_WRITE(DIO_MEM_PWR_CTRL, 0); if (!dc->public.debug.disable_clock_gate) { /* enable all DCN clock gating */ - generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL, 19, - FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__SOCCLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_R_DCCG_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DPPCLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__AOMCLK0_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__AOMCLK1_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__AOMCLK2_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__AUDIO_DTO2_CLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DPREFCLK_GTC_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__UNB_DB_CLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__REFCLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__REFCLK_R_DIG_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__DSICLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__BYTECLK_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL__ESCCLK_GATE_DISABLE), 0); - - generic_reg_set_soc15(dc->ctx, 0, DCCG_GATE_DISABLE_CNTL2, 14, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_FE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKA_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKB_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKC_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKD_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKE_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKF_GATE_DISABLE), 0, - FD(DCCG_GATE_DISABLE_CNTL2__SYMCLKG_GATE_DISABLE), 0); - - generic_reg_update_soc15(dc->ctx, 0, DCFCLK_CNTL, 1, - FD(DCFCLK_CNTL__DCFCLK_GATE_DIS), 0); - } + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - /* This power gating should be one-time program for DAL. - * It can only change by registry key - * TODO: new task will for this. - * if power gating is disable, power_on_plane and power_off_plane - * should be skip. Otherwise, hand will be met in power_off_plane - */ - enable_power_gating_plane(dc->ctx, true); + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + enable_power_gating_plane(dc->hwseq, true); } static enum dc_status dcn10_prog_pixclk_crtc_otg( @@ -759,9 +453,6 @@ static void reset_back_end_for_pipe( struct validate_context *context) { int i; - struct dc_bios *bp; - - bp = dc->ctx->dc_bios; if (pipe_ctx->stream_enc == NULL) { pipe_ctx->stream = NULL; @@ -807,6 +498,7 @@ static void reset_front_end( struct core_dc *dc, int fe_idx) { + struct dce_hwseq *hws = dc->hwseq; struct mpcc_cfg mpcc_cfg; struct mem_input *mi = dc->res_pool->mis[fe_idx]; struct transform *xfm = dc->res_pool->transforms[fe_idx]; @@ -826,11 +518,14 @@ static void reset_front_end( mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; mpcc->funcs->set(mpcc, &mpcc_cfg); - unlock_master_tg_and_wait(dc->ctx, tg->inst); + REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); + tg->funcs->unlock(tg); + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); + mpcc->funcs->wait_for_idle(mpcc); mi->funcs->set_blank(mi, true); - wait_no_outstanding_request(dc->ctx, fe_idx); - disable_clocks(dc->ctx, fe_idx); + REG_WAIT(DCHUBP_CNTL[fe_idx], HUBP_NO_OUTSTANDING_REQ, 1, 20000, 200000); + disable_clocks(dc->hwseq, fe_idx); xfm->funcs->transform_reset(xfm); @@ -841,16 +536,15 @@ static void reset_front_end( static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) { - struct dc_context *ctx = dc->ctx; - uint32_t inst_offset = 0; + struct dce_hwseq *hws = dc->hwseq; reset_front_end(dc, fe_idx); - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - dpp_pg_control(ctx, fe_idx, false); - hubp_pg_control(ctx, fe_idx, false); - HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, + dpp_pg_control(hws, fe_idx, false); + hubp_pg_control(hws, fe_idx, false); + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, "Power gated front end %d\n", fe_idx); @@ -1538,18 +1232,13 @@ static void dcn10_power_on_fe( struct validate_context *context) { struct dc_surface *dc_surface = &pipe_ctx->surface->public; + struct dce_hwseq *hws = dc->hwseq; - power_on_plane(dc->ctx, + power_on_plane(dc->hwseq, pipe_ctx->pipe_idx); /* enable DCFCLK current DCHUB */ - enable_dcfclk(dc->ctx, - pipe_ctx->pipe_idx, - pipe_ctx->pix_clk_params.requested_pix_clk, - context->bw.dcn.calc_clk.dppclk_div); - dc->current_context->bw.dcn.cur_clk.dppclk_div = - context->bw.dcn.calc_clk.dppclk_div; - context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; + REG_UPDATE(HUBP_CLK_CNTL[pipe_ctx->pipe_idx], HUBP_CLOCK_ENABLE, 1); if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1706,6 +1395,7 @@ static void update_dchubp_dpp( struct pipe_ctx *pipe_ctx, struct validate_context *context) { + struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->mi; struct input_pixel_processor *ipp = pipe_ctx->ipp; struct core_surface *surface = pipe_ctx->surface; @@ -1718,7 +1408,7 @@ static void update_dchubp_dpp( /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ enable_dppclk( - dc->ctx, + dc->hwseq, pipe_ctx->pipe_idx, pipe_ctx->pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); @@ -1726,7 +1416,11 @@ static void update_dchubp_dpp( context->bw.dcn.calc_clk.dppclk_div; context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; - select_vtg(dc->ctx, pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG + * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. + * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG + */ + REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->tg->inst); update_plane_addr(dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index 96fba1fb7697..1828d288c6bc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -270,7 +270,7 @@ FN(reg, f8), v8, \ FN(reg, f9), v9) -#define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ +#define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10)\ REG_UPDATE_N(reg, 10, \ FN(reg, f1), v1,\ FN(reg, f2), v2, \ @@ -283,6 +283,70 @@ FN(reg, f9), v9, \ FN(reg, f10), v10) +#define REG_UPDATE_14(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\ + v10, f11, v11, f12, v12, f13, v13, f14, v14)\ + REG_UPDATE_N(reg, 14, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10, \ + FN(reg, f11), v11, \ + FN(reg, f12), v12, \ + FN(reg, f13), v13, \ + FN(reg, f14), v14) + +#define REG_UPDATE_19(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\ + v10, f11, v11, f12, v12, f13, v13, f14, v14, f15, v15, f16, v16, f17, v17, f18, v18, f19, v19)\ + REG_UPDATE_N(reg, 19, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10, \ + FN(reg, f11), v11, \ + FN(reg, f12), v12, \ + FN(reg, f13), v13, \ + FN(reg, f14), v14, \ + FN(reg, f15), v15, \ + FN(reg, f16), v16, \ + FN(reg, f17), v17, \ + FN(reg, f18), v18, \ + FN(reg, f19), v19) + +#define REG_UPDATE_20(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\ + v10, f11, v11, f12, v12, f13, v13, f14, v14, f15, v15, f16, v16, f17, v17, f18, v18, f19, v19, f20, v20)\ + REG_UPDATE_N(reg, 20, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2, \ + FN(reg, f3), v3, \ + FN(reg, f4), v4, \ + FN(reg, f5), v5, \ + FN(reg, f6), v6, \ + FN(reg, f7), v7, \ + FN(reg, f8), v8, \ + FN(reg, f9), v9, \ + FN(reg, f10), v10, \ + FN(reg, f11), v11, \ + FN(reg, f12), v12, \ + FN(reg, f13), v13, \ + FN(reg, f14), v14, \ + FN(reg, f15), v15, \ + FN(reg, f16), v16, \ + FN(reg, f17), v17, \ + FN(reg, f18), v18, \ + FN(reg, f19), v19, \ + FN(reg, f20), v20) /* macro to update a register field to specified values in given sequences. * useful when toggling bits */ -- GitLab From 87449a90c2545eaed5757153770346563378463b Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 6 Jul 2017 14:27:49 -0400 Subject: [PATCH 0613/2898] drm/amd/display: Fix MPO visual confirm 1. Need to blend non-active area to show visual confirm borders 2. Set number of Visual Confirm lines based on pipe instance 3. Set Different colors representing surface format of bottom most plan Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_hw_sequencer.c | 6 --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 16 +++---- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 8 ++-- .../display/dc/dce110/dce110_hw_sequencer.c | 8 +++- .../display/dc/dce110/dce110_transform_v.c | 4 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 45 ++++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 5 ++- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- .../amd/display/dc/dcn10/dcn10_transform.c | 13 +++--- .../amd/display/dc/dcn10/dcn10_transform.h | 1 + 10 files changed, 77 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 6cd1e93b5084..7b1f2493cbc9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -59,12 +59,6 @@ void color_space_to_black_color( enum dc_color_space colorspace, struct tg_color *black_color) { - if (dc->public.debug.surface_visual_confirm) { - *black_color = - black_color_format[BLACK_COLOR_FORMAT_DEBUG]; - return; - } - switch (colorspace) { case COLOR_SPACE_YCBCR601: case COLOR_SPACE_YCBCR709: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ddf032214dc3..5a5ed37474bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -399,11 +399,11 @@ static enum pixel_format convert_pixel_format_to_dalsurface( break; case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - dal_pixel_format = PIXEL_FORMAT_420BPP12; + dal_pixel_format = PIXEL_FORMAT_420BPP8; break; case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - dal_pixel_format = PIXEL_FORMAT_420BPP15; + dal_pixel_format = PIXEL_FORMAT_420BPP10; break; case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: default: @@ -433,8 +433,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; struct rect clip = { 0 }; - int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 - || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 + || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; bool pri_split = pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && @@ -637,8 +637,8 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; - if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12 - || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP15) { + if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP8 + || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP10) { pipe_ctx->scl_data.ratios.horz_c.value /= 2; pipe_ctx->scl_data.ratios.vert_c.value /= 2; } @@ -648,8 +648,8 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r { struct scaler_data *data = &pipe_ctx->scl_data; struct rect src = pipe_ctx->surface->public.src_rect; - int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 - || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 + || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 94fb93066784..05f030ee8cf0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -214,15 +214,15 @@ enum pixel_format { PIXEL_FORMAT_ARGB2101010_XRBIAS, PIXEL_FORMAT_FP16, /*video*/ - PIXEL_FORMAT_420BPP12, - PIXEL_FORMAT_420BPP15, + PIXEL_FORMAT_420BPP8, + PIXEL_FORMAT_420BPP10, /*end of pixel format definition*/ PIXEL_FORMAT_INVALID, PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8, PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16, - PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12, - PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP15, + PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP8, + PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP10, PIXEL_FORMAT_UNKNOWN }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 8778af76f4e0..d3c84dc36b80 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -916,11 +916,15 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, /* set boarder color to blue */ color->color_b_cb = color_value; break; - case PIXEL_FORMAT_420BPP12: - case PIXEL_FORMAT_420BPP15: + case PIXEL_FORMAT_420BPP8: /* set boarder color to green */ color->color_g_y = color_value; break; + case PIXEL_FORMAT_420BPP10: + /* set boarder color to yellow */ + color->color_g_y = color_value; + color->color_r_cr = color_value; + break; case PIXEL_FORMAT_FP16: /* set boarder color to white */ color->color_r_cr = color_value; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index 28963996693c..8548248d4b19 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -59,7 +59,7 @@ static void calculate_viewport( chroma_viewport->height = luma_viewport->height; chroma_viewport->width = luma_viewport->width; - if (scl_data->format == PIXEL_FORMAT_420BPP12) { + if (scl_data->format == PIXEL_FORMAT_420BPP8) { luma_viewport->height += luma_viewport->height % 2; luma_viewport->width += luma_viewport->width % 2; /*for 420 video chroma is 1/4 the area of luma, scaled @@ -184,7 +184,7 @@ static bool setup_scaling_configuration( set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C); set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C); is_scaling_needed = true; - } else if (data->format != PIXEL_FORMAT_420BPP12) { + } else if (data->format != PIXEL_FORMAT_420BPP8) { set_reg_field_value( value, get_reg_field_value(value, SCLV_MODE, SCL_MODE), diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index fb326316b08b..5e275239341d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1390,6 +1390,42 @@ static bool is_rgb_cspace(enum dc_color_space output_color_space) } } +static void dcn10_get_surface_visual_confirm_color( + const struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE; + + switch (pipe_ctx->scl_data.format) { + case PIXEL_FORMAT_ARGB8888: + /* set boarder color to red */ + color->color_r_cr = color_value; + break; + + case PIXEL_FORMAT_ARGB2101010: + /* set boarder color to blue */ + color->color_b_cb = color_value; + break; + case PIXEL_FORMAT_420BPP8: + /* set boarder color to green */ + color->color_g_y = color_value; + break; + case PIXEL_FORMAT_420BPP10: + /* set boarder color to yellow */ + color->color_g_y = color_value; + color->color_r_cr = color_value; + break; + case PIXEL_FORMAT_FP16: + /* set boarder color to white */ + color->color_r_cr = color_value; + color->color_b_cb = color_value; + color->color_g_y = color_value; + break; + default: + break; + } +} + static void update_dchubp_dpp( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -1462,8 +1498,13 @@ static void update_dchubp_dpp( && per_pixel_alpha; pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); - color_space_to_black_color( - dc, pipe_ctx->stream->public.output_color_space, &black_color); + if (dc->public.debug.surface_visual_confirm) { + dcn10_get_surface_visual_confirm_color(pipe_ctx, &black_color); + } else { + color_space_to_black_color( + dc, pipe_ctx->stream->public.output_color_space, + &black_color); + } pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color); pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 7af04bce3599..1c9d5e96ab55 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -25,6 +25,7 @@ #include "reg_helper.h" #include "dcn10_mpc.h" +#include "dc.h" #define REG(reg)\ mpcc10->mpcc_regs->reg @@ -85,6 +86,8 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; int mpcc_mode = cfg->bot_mpcc_id != 0xf ? MODE_BLEND : MODE_TOP_ONLY; + bool blend_active_only = cfg->top_of_tree && + !mpcc->ctx->dc->debug.surface_visual_confirm; REG_SET(MPCC_OPP_ID, 0, MPCC_OPP_ID, cfg->opp_id); @@ -99,7 +102,7 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) MPCC_MODE, mpcc_mode, MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, cfg->top_of_tree); + MPCC_BLND_ACTIVE_OVERLAP_ONLY, blend_active_only); if (cfg->top_of_tree) { if (cfg->opp_id != 0xf) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 66b5d3027336..75ad37e81738 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -465,7 +465,7 @@ static struct transform *dcn10_transform_create( if (!transform) return NULL; - if (dcn10_transform_construct(transform, ctx, + if (dcn10_transform_construct(transform, ctx, inst, &tf_regs[inst], &tf_shift, &tf_mask)) return &transform->base; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index 92322b75d868..398af229f2a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -171,8 +171,8 @@ static enum dscl_mode_sel get_dscl_mode( && data->format <= PIXEL_FORMAT_VIDEO_END) ycbcr = true; - if (data->format == PIXEL_FORMAT_420BPP12 || - data->format == PIXEL_FORMAT_420BPP15) + if (data->format == PIXEL_FORMAT_420BPP8 || + data->format == PIXEL_FORMAT_420BPP10) format420 = true; if (data->ratios.horz.value == one @@ -579,8 +579,8 @@ static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_2; - if (scl_data->format == PIXEL_FORMAT_420BPP12 - || scl_data->format == PIXEL_FORMAT_420BPP15) { + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) { calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); @@ -675,7 +675,8 @@ static void transform_set_recout( RECOUT_WIDTH, recout->width, /* Number of RECOUT vertical lines */ RECOUT_HEIGHT, recout->height - - xfm->base.ctx->dc->debug.surface_visual_confirm * 2); + - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * + (xfm->base.inst + 1)); } static void transform_set_manual_ratio_init( @@ -1038,12 +1039,14 @@ static struct transform_funcs dcn10_transform_funcs = { bool dcn10_transform_construct( struct dcn10_transform *xfm, struct dc_context *ctx, + uint32_t inst, const struct dcn_transform_registers *tf_regs, const struct dcn_transform_shift *tf_shift, const struct dcn_transform_mask *tf_mask) { xfm->base.ctx = ctx; + xfm->base.inst = inst; xfm->base.funcs = &dcn10_transform_funcs; xfm->tf_regs = tf_regs; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h index cd312bd7055b..880a554886b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h @@ -413,6 +413,7 @@ struct dcn10_transform { bool dcn10_transform_construct(struct dcn10_transform *xfm110, struct dc_context *ctx, + uint32_t inst, const struct dcn_transform_registers *tf_regs, const struct dcn_transform_shift *tf_shift, const struct dcn_transform_mask *tf_mask); -- GitLab From 0b6ab57e7ffad05ca266fed9764119cf1807b81b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 5 Jul 2017 12:00:28 -0400 Subject: [PATCH 0614/2898] drm/amd/display: get dal1.1 to run Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 761dba3562b2..6985a4607bd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -275,7 +275,7 @@ struct dce_hwseq_registers { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ - HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, OTG0_),\ + HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \ HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR, mask_sh), \ HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, mask_sh), \ HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh), \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index e6f2220415e8..669ac4b67ea9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -784,7 +784,7 @@ static void oppn10_program_color_matrix(struct dcn10_opp *oppn10, } } -void oppn10_set_output_csc_adjustment( +static void oppn10_set_output_csc_adjustment( struct output_pixel_processor *opp, const struct out_csc_color_matrix *tbl_entry) { -- GitLab From 4fac6da2cb93cd6cabfaeb6de2eb0401bbcc805b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 6 Jul 2017 15:42:04 -0400 Subject: [PATCH 0615/2898] drm/amd/display: minor dcn10_hwseq clean up/refactor Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 49 +++++-------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 5e275239341d..223bb79bc8b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -53,15 +53,6 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name -static void disable_clocks( - struct dce_hwseq *hws, - uint8_t plane_id) -{ - REG_UPDATE(HUBP_CLK_CNTL[plane_id], HUBP_CLOCK_ENABLE, 0); - - REG_UPDATE(DPP_CONTROL[plane_id], DPP_CLOCK_ENABLE, 0); -} - static void enable_dppclk( struct dce_hwseq *hws, uint8_t plane_id, @@ -214,25 +205,6 @@ static void power_on_plane( "Un-gated front end for pipe %d\n", plane_id); } -/* fully check bios enabledisplaypowergating table. dal only need dce init - * other power, clock gate register will be handle by dal itself. - * further may be put within init_hw - */ -static bool dcn10_enable_display_power_gating( - struct core_dc *dc, - uint8_t controller_id, - struct dc_bios *dcb, - enum pipe_gating_control power_gating) -{ - /* TODOFPGA */ -#if 0 - if (power_gating != PIPE_GATING_CONTROL_ENABLE) - dce110_init_pte(ctx); -#endif - - return true; -} - static void bios_golden_init(struct core_dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; @@ -525,7 +497,8 @@ static void reset_front_end( mpcc->funcs->wait_for_idle(mpcc); mi->funcs->set_blank(mi, true); REG_WAIT(DCHUBP_CNTL[fe_idx], HUBP_NO_OUTSTANDING_REQ, 1, 20000, 200000); - disable_clocks(dc->hwseq, fe_idx); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); + REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); xfm->funcs->transform_reset(xfm); @@ -1803,8 +1776,8 @@ static void set_plane_config( program_gamut_remap(pipe_ctx); } -static void dcn10_config_stereo_parameters(struct core_stream *stream,\ - struct crtc_stereo_flags *flags) +static void dcn10_config_stereo_parameters( + struct core_stream *stream, struct crtc_stereo_flags *flags) { enum view_3d_format view_format = stream->public.view_format; enum dc_timing_3d_format timing_3d_format =\ @@ -1840,8 +1813,7 @@ static void dcn10_config_stereo_parameters(struct core_stream *stream,\ return; } -static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, - struct core_dc *dc) +static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) { struct crtc_stereo_flags flags = { 0 }; struct core_stream *stream = pipe_ctx->stream; @@ -1858,11 +1830,15 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, &stream->public.timing, &flags); - - return; } +static bool dcn10_dummy_display_power_gating( + struct core_dc *dc, + uint8_t controller_id, + struct dc_bios *dcb, + enum pipe_gating_control power_gating) {return true; } + static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .program_csc_matrix = program_csc_matrix, @@ -1881,8 +1857,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .enable_stream = dce110_enable_stream, .disable_stream = dce110_disable_stream, .unblank_stream = dce110_unblank_stream, - .enable_display_pipe_clock_gating = NULL, /* TODOFPGA */ - .enable_display_power_gating = dcn10_enable_display_power_gating, + .enable_display_power_gating = dcn10_dummy_display_power_gating, .power_down_front_end = dcn10_power_down_fe, .power_on_front_end = dcn10_power_on_fe, .pipe_control_lock = dcn10_pipe_control_lock, -- GitLab From ea658f7552583b27fd5f4351caf8a139cb554b50 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 6 Jul 2017 15:58:25 -0400 Subject: [PATCH 0616/2898] drm/amd/display: dal1.1 opp prog update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index eb99c311104f..de0b631736bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -138,10 +138,11 @@ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh), \ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh), \ OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh), \ OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh), \ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh), \ @@ -353,8 +354,7 @@ OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_SEL, mask_sh), \ OPP_SF(CM0_CM_RGAM_LUT_INDEX, CM_RGAM_LUT_INDEX, mask_sh), \ OPP_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh), \ - OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) + OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ type CM_OCSC_C11; \ -- GitLab From a3ac9dad7494c946d323fd461df03bed9507157e Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 6 Jul 2017 17:35:17 -0400 Subject: [PATCH 0617/2898] drm/amd/display: dal1.1 ipp prog update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 99 +++++++++---------- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 1 + 2 files changed, 48 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index a09226c0d903..4910d4c59b31 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -69,7 +69,7 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; -static void dcn10_program_input_csc( +static void ippn10_program_input_csc( struct input_pixel_processor *ipp, enum dc_color_space color_space, enum dcn10_input_csc_select select) @@ -159,7 +159,7 @@ static void dcn10_program_input_csc( } /*program de gamma RAM B*/ -static void dcn10_ipp_program_degamma_lutb_settings( +static void ippn10_program_degamma_lutb_settings( struct input_pixel_processor *ipp, const struct pwl_params *params) { @@ -266,7 +266,7 @@ static void dcn10_ipp_program_degamma_lutb_settings( } /*program de gamma RAM A*/ -static void dcn10_ipp_program_degamma_luta_settings( +static void ippn10_program_degamma_luta_settings( struct input_pixel_processor *ipp, const struct pwl_params *params) { @@ -372,7 +372,7 @@ static void dcn10_ipp_program_degamma_luta_settings( CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); } -static void ipp_power_on_degamma_lut( +static void ippn10_power_on_degamma_lut( struct input_pixel_processor *ipp, bool power_on) { @@ -383,7 +383,7 @@ static void ipp_power_on_degamma_lut( } -static void ipp_program_degamma_lut( +static void ippn10_program_degamma_lut( struct input_pixel_processor *ipp, const struct pwl_result_data *rgb, uint32_t num, @@ -410,25 +410,19 @@ static void ipp_program_degamma_lut( CM_DGAM_LUT_DATA, rgb[i].delta_green_reg); REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg); - } - } -static void dcn10_ipp_enable_cm_block( +static void ippn10_enable_cm_block( struct input_pixel_processor *ipp) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1); - if (ippn10->ipp_mask->CM_BYPASS_EN) - REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); - else - REG_UPDATE(CM_CONTROL, CM_BYPASS, 0); + REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } - -static void dcn10_ipp_full_bypass(struct input_pixel_processor *ipp) +static void ippn10_full_bypass(struct input_pixel_processor *ipp) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); @@ -450,12 +444,12 @@ static void dcn10_ipp_full_bypass(struct input_pixel_processor *ipp) REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); } -static void dcn10_ipp_set_degamma( +static void ippn10_set_degamma( struct input_pixel_processor *ipp, enum ipp_degamma_mode mode) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - dcn10_ipp_enable_cm_block(ipp); + ippn10_enable_cm_block(ipp); switch (mode) { case IPP_DEGAMMA_MODE_BYPASS: @@ -474,7 +468,7 @@ static void dcn10_ipp_set_degamma( } } -static bool dcn10_cursor_program_control( +static bool ippn10_cursor_program_control( struct dcn10_ipp *ippn10, bool pixel_data_invert, enum dc_cursor_color_format color_format) @@ -520,7 +514,7 @@ enum cursor_lines_per_chunk { CURSOR_LINE_PER_CHUNK_16 }; -static enum cursor_pitch dcn10_get_cursor_pitch( +static enum cursor_pitch ippn10_get_cursor_pitch( unsigned int pitch) { enum cursor_pitch hw_pitch; @@ -544,7 +538,7 @@ static enum cursor_pitch dcn10_get_cursor_pitch( return hw_pitch; } -static enum cursor_lines_per_chunk dcn10_get_lines_per_chunk( +static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( unsigned int cur_width, enum dc_cursor_color_format format) { @@ -565,13 +559,13 @@ static enum cursor_lines_per_chunk dcn10_get_lines_per_chunk( return line_per_chunk; } -static void dcn10_cursor_set_attributes( +static void ippn10_cursor_set_attributes( struct input_pixel_processor *ipp, const struct dc_cursor_attributes *attr) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - enum cursor_pitch hw_pitch = dcn10_get_cursor_pitch(attr->pitch); - enum cursor_lines_per_chunk lpc = dcn10_get_lines_per_chunk( + enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( attr->width, attr->color_format); ippn10->curs_attr = *attr; @@ -590,12 +584,12 @@ static void dcn10_cursor_set_attributes( CURSOR_PITCH, hw_pitch, CURSOR_LINES_PER_CHUNK, lpc); - dcn10_cursor_program_control(ippn10, + ippn10_cursor_program_control(ippn10, attr->attribute_flags.bits.INVERT_PIXEL_DATA, attr->color_format); } -static void dcn10_cursor_set_position( +static void ippn10_cursor_set_position( struct input_pixel_processor *ipp, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param) @@ -632,7 +626,7 @@ static void dcn10_cursor_set_position( cur_en = 0; /* not visible beyond left edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - dcn10_cursor_set_attributes(ipp, &ippn10->curs_attr); + ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr); REG_UPDATE(CURSOR_CONTROL, CURSOR_ENABLE, cur_en); REG_UPDATE(CURSOR0_CONTROL, @@ -658,7 +652,7 @@ enum pixel_format_description { }; -static void dcn10_setup_format_flags(enum surface_pixel_format input_format,\ +static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ enum pixel_format_description *fmt) { @@ -671,7 +665,7 @@ static void dcn10_setup_format_flags(enum surface_pixel_format input_format,\ *fmt = PIXEL_FORMAT_FIXED; } -static void dcn10_ipp_set_degamma_format_float(struct input_pixel_processor *ipp, +static void ippn10_set_degamma_format_float(struct input_pixel_processor *ipp, bool is_float) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); @@ -686,7 +680,7 @@ static void dcn10_ipp_set_degamma_format_float(struct input_pixel_processor *ipp } -static void dcn10_ipp_cnv_setup ( +static void ippn10_cnv_setup ( struct input_pixel_processor *ipp, enum surface_pixel_format input_format, enum expansion_mode mode, @@ -701,7 +695,7 @@ static void dcn10_ipp_cnv_setup ( struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); bool force_disable_cursor = false; - dcn10_setup_format_flags(input_format, &fmt); + ippn10_setup_format_flags(input_format, &fmt); alpha_en = 1; pixel_format = 0; color_space = COLOR_SPACE_SRGB; @@ -729,7 +723,7 @@ static void dcn10_ipp_cnv_setup ( break; } - dcn10_ipp_set_degamma_format_float(ipp, is_float); + ippn10_set_degamma_format_float(ipp, is_float); switch (input_format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: @@ -787,7 +781,7 @@ static void dcn10_ipp_cnv_setup ( CNVC_SURFACE_PIXEL_FORMAT, pixel_format); REG_UPDATE(FORMAT_CONTROL, ALPHA_EN, alpha_en); - dcn10_program_input_csc(ipp, color_space, select); + ippn10_program_input_csc(ipp, color_space, select); if (force_disable_cursor) { REG_UPDATE(CURSOR_CONTROL, @@ -798,7 +792,7 @@ static void dcn10_ipp_cnv_setup ( } -static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, +static bool ippn10_degamma_ram_inuse(struct input_pixel_processor *ipp, bool *ram_a_inuse) { bool ret = false; @@ -818,7 +812,7 @@ static bool dcn10_degamma_ram_inuse(struct input_pixel_processor *ipp, return ret; } -static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, +static bool ippn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, bool *ram_a_inuse) { bool in_use = false; @@ -840,7 +834,7 @@ static bool dcn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, return in_use; } -static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, +static void ippn10_degamma_ram_select(struct input_pixel_processor *ipp, bool use_ram_a) { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); @@ -852,22 +846,22 @@ static void dcn10_degamma_ram_select(struct input_pixel_processor *ipp, } -static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, +static void ippn10_set_degamma_pwl(struct input_pixel_processor *ipp, const struct pwl_params *params) { bool is_ram_a = true; - ipp_power_on_degamma_lut(ipp, true); - dcn10_ipp_enable_cm_block(ipp); - dcn10_degamma_ram_inuse(ipp, &is_ram_a); + ippn10_power_on_degamma_lut(ipp, true); + ippn10_enable_cm_block(ipp); + ippn10_degamma_ram_inuse(ipp, &is_ram_a); if (is_ram_a == true) - dcn10_ipp_program_degamma_lutb_settings(ipp, params); + ippn10_program_degamma_lutb_settings(ipp, params); else - dcn10_ipp_program_degamma_luta_settings(ipp, params); + ippn10_program_degamma_luta_settings(ipp, params); - ipp_program_degamma_lut(ipp, params->rgb_resulted, + ippn10_program_degamma_lut(ipp, params->rgb_resulted, params->hw_points_num, !is_ram_a); - dcn10_degamma_ram_select(ipp, !is_ram_a); + ippn10_degamma_ram_select(ipp, !is_ram_a); } /* @@ -879,7 +873,7 @@ static void dcn10_ipp_set_degamma_pwl(struct input_pixel_processor *ipp, * In the future, this function should support additional input gamma methods, * such as piecewise linear mapping, and input gamma bypass. */ -void dcn10_ipp_program_input_lut( +static void ippn10_program_input_lut( struct input_pixel_processor *ipp, const struct dc_gamma *gamma) { @@ -889,9 +883,9 @@ void dcn10_ipp_program_input_lut( uint32_t ram_num; // Power on LUT memory. REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); - dcn10_ipp_enable_cm_block(ipp); + ippn10_enable_cm_block(ipp); // Determine whether to use RAM A or RAM B - dcn10_ingamma_ram_inuse(ipp, &rama_occupied); + ippn10_ingamma_ram_inuse(ipp, &rama_occupied); if (!rama_occupied) REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); else @@ -936,13 +930,13 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) } static const struct ipp_funcs dcn10_ipp_funcs = { - .ipp_cursor_set_attributes = dcn10_cursor_set_attributes, - .ipp_cursor_set_position = dcn10_cursor_set_position, - .ipp_set_degamma = dcn10_ipp_set_degamma, - .ipp_program_input_lut = dcn10_ipp_program_input_lut, - .ipp_full_bypass = dcn10_ipp_full_bypass, - .ipp_setup = dcn10_ipp_cnv_setup, - .ipp_program_degamma_pwl = dcn10_ipp_set_degamma_pwl, + .ipp_cursor_set_attributes = ippn10_cursor_set_attributes, + .ipp_cursor_set_position = ippn10_cursor_set_position, + .ipp_set_degamma = ippn10_set_degamma, + .ipp_program_input_lut = ippn10_program_input_lut, + .ipp_full_bypass = ippn10_full_bypass, + .ipp_setup = ippn10_cnv_setup, + .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, .ipp_destroy = dcn10_ipp_destroy }; @@ -962,3 +956,4 @@ void dcn10_ipp_construct( ippn10->ipp_shift = ipp_shift; ippn10->ipp_mask = ipp_mask; } + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index d608abf0e822..1703589623b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -292,6 +292,7 @@ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh) #define IPP_DCN10_REG_FIELD_LIST(type) \ + type CM_DGAM_CONFIG_STATUS; \ type CM_ICSC_MODE; \ type CM_ICSC_C11; \ type CM_ICSC_C12; \ -- GitLab From 7dbeaae2a554c479120836bb02a97d602e5ad4a3 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 7 Jul 2017 10:37:46 -0400 Subject: [PATCH 0618/2898] drm/amd/display: dal1.1 xfm prog update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_transform.c | 10 ++--- .../amd/display/dc/dcn10/dcn10_transform.h | 43 ++++++++++--------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c index 398af229f2a7..59ba2d250d6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c @@ -212,7 +212,7 @@ static int get_pixel_depth_val(enum lb_pixel_depth depth) } } -static void transform_set_lb( +static void xfmn10_set_lb( struct dcn10_transform *xfm, const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) @@ -622,7 +622,7 @@ void transform_set_scaler_auto_scale( return; lb_config = find_lb_memory_config(scl_data); - transform_set_lb(xfm, &scl_data->lb_params, lb_config); + xfmn10_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -738,7 +738,7 @@ static void transform_set_manual_ratio_init( } /* Main function to program scaler and line buffer in manual scaling mode */ -static void transform_set_scaler_manual_scale( +static void xfmn10_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data) { @@ -769,7 +769,7 @@ static void transform_set_scaler_manual_scale( return; /* LB */ lb_config = find_lb_memory_config(scl_data); - transform_set_lb(xfm, &scl_data->lb_params, lb_config); + xfmn10_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -1027,7 +1027,7 @@ static void dcn_transform_set_gamut_remap( static struct transform_funcs dcn10_transform_funcs = { .transform_reset = transform_reset, - .transform_set_scaler = transform_set_scaler_manual_scale, + .transform_set_scaler = xfmn10_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = transform_get_optimal_number_of_taps, .transform_set_gamut_remap = dcn_transform_set_gamut_remap, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h index 880a554886b8..8df74cc153f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h @@ -38,6 +38,13 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define TF_REG_LIST_DCN(id) \ + SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ + SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ + SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ + SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ + SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ + SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ + SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ SRI(OTG_H_BLANK, DSCL, id), \ @@ -74,13 +81,6 @@ #define TF_REG_LIST_DCN10(id) \ TF_REG_LIST_DCN(id), \ - SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ - SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ - SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ - SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ - SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ - SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ - SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ SRI(CM_COMA_C11_C12, CM, id),\ SRI(CM_COMA_C13_C14, CM, id),\ SRI(CM_COMA_C21_C22, CM, id),\ @@ -95,6 +95,19 @@ SRI(CM_COMB_C33_C34, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ + TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ @@ -176,19 +189,6 @@ TF_SF(DSCL0_LB_DATA_FORMAT, PIXEL_REDUCE_MODE, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, DYNAMIC_PIXEL_DEPTH, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh),\ TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh),\ TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh),\ @@ -411,10 +411,11 @@ struct dcn10_transform { int lb_bits_per_entry; }; -bool dcn10_transform_construct(struct dcn10_transform *xfm110, +bool dcn10_transform_construct(struct dcn10_transform *xfmn10, struct dc_context *ctx, uint32_t inst, const struct dcn_transform_registers *tf_regs, const struct dcn_transform_shift *tf_shift, const struct dcn_transform_mask *tf_mask); + #endif -- GitLab From 4e5095ca06a00fda50e2fcc721b1f923478778a8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 7 Jul 2017 11:24:13 -0400 Subject: [PATCH 0619/2898] drm/amd/display: dal1.1 hwseq prog update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 223bb79bc8b8..4c39bf052d08 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -64,17 +64,13 @@ static void enable_dppclk( plane_id, dppclk_div); - if (dppclk_div) { - /* 1/2 DISPCLK*/ + if (hws->shifts->DPPCLK_RATE_CONTROL) REG_UPDATE_2(DPP_CONTROL[plane_id], - DPPCLK_RATE_CONTROL, 1, + DPPCLK_RATE_CONTROL, dppclk_div, DPP_CLOCK_ENABLE, 1); - } else { - /* DISPCLK */ - REG_UPDATE_2(DPP_CONTROL[plane_id], - DPPCLK_RATE_CONTROL, 0, + else + REG_UPDATE(DPP_CONTROL[plane_id], DPP_CLOCK_ENABLE, 1); - } } static void enable_power_gating_plane( -- GitLab From a85c205ae3d183c196d0af7df336b1315e95faf7 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Mon, 10 Jul 2017 15:52:10 -0400 Subject: [PATCH 0620/2898] drm/amd/display: Fix context copy memory leak This change corrects an error introduced in 355f123f. Instead of using the copy constructor to assign the new context, we swap the pointer. Signed-off-by: Corbin McElhanney Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 52077d39b30a..4f9302901a62 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -972,7 +972,9 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - dc_resource_validate_ctx_copy_construct(context, core_dc->current_context); + dc_resource_validate_ctx_destruct(core_dc->current_context); + dm_free(core_dc->current_context); + core_dc->current_context = context; return (result == DC_OK); } @@ -1057,9 +1059,6 @@ bool dc_commit_streams( result = dc_commit_context_no_check(dc, context); - dc_resource_validate_ctx_destruct(context); - dm_free(context); - return (result == DC_OK); fail: -- GitLab From adef2ce36e6ad76888159ea6225da54019d0ff0e Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 10 Jul 2017 16:24:42 -0400 Subject: [PATCH 0621/2898] drm/amd/display: Leave all validate_ctx life cycle management to DC. Follow DC fix. Signed-off-by: Andrey Grodzovsky Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4b844e5c5dcd..63d23c6e7574 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -653,27 +653,12 @@ dm_atomic_state_alloc(struct drm_device *dev) return &state->base; } - -void dm_atomic_state_clear(struct drm_atomic_state *state) -{ - struct dm_atomic_state *dm_state = to_dm_atomic_state(state); - - if (dm_state->context) { - dc_resource_validate_ctx_destruct(dm_state->context); - dm_free(dm_state->context); - dm_state->context = NULL; - } - - drm_atomic_state_default_clear(state); -} - static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = amdgpu_dm_atomic_commit, .atomic_state_alloc = dm_atomic_state_alloc, - .atomic_state_clear = dm_atomic_state_clear, }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { -- GitLab From 3d21a662500fdcc2760ec7d936692bb9efa06c67 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 25 Jul 2017 18:11:18 -0400 Subject: [PATCH 0622/2898] drm/amd/display: Clean dm_plane_state hooks. New surface is created in check only, in duplicate we just reference exsisting surface and in destroy we release it. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 43 +++---------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index c222cdb59ac1..0439f75fb24d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1417,7 +1417,6 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { static void dm_drm_plane_reset(struct drm_plane *plane) { struct dm_plane_state *amdgpu_state = NULL; - struct amdgpu_device *adev = plane->dev->dev_private; if (plane->state) plane->funcs->atomic_destroy_state(plane, plane->state); @@ -1428,9 +1427,6 @@ static void dm_drm_plane_reset(struct drm_plane *plane) plane->state = &amdgpu_state->base; plane->state->plane = plane; plane->state->rotation = DRM_MODE_ROTATE_0; - - amdgpu_state->dc_surface = dc_create_surface(adev->dm.dc); - WARN_ON(!amdgpu_state->dc_surface); } else WARN_ON(1); @@ -1440,35 +1436,17 @@ static struct drm_plane_state * dm_drm_plane_duplicate_state(struct drm_plane *plane) { struct dm_plane_state *dm_plane_state, *old_dm_plane_state; - struct amdgpu_device *adev = plane->dev->dev_private; old_dm_plane_state = to_dm_plane_state(plane->state); dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); if (!dm_plane_state) return NULL; - if (old_dm_plane_state->dc_surface) { - struct dc_surface *dc_surface = dc_create_surface(adev->dm.dc); - if (WARN_ON(!dc_surface)) - return NULL; - - __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - - memcpy(dc_surface, old_dm_plane_state->dc_surface, sizeof(*dc_surface)); + __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - if (old_dm_plane_state->dc_surface->gamma_correction) - dc_gamma_retain(dc_surface->gamma_correction); - - if (old_dm_plane_state->dc_surface->in_transfer_func) - dc_transfer_func_retain(dc_surface->in_transfer_func); - - dm_plane_state->dc_surface = dc_surface; - - /*TODO Check for inferred values to be reset */ - } - else { - WARN_ON(1); - return NULL; + if (old_dm_plane_state->dc_surface) { + dm_plane_state->dc_surface = old_dm_plane_state->dc_surface; + dc_surface_retain(dm_plane_state->dc_surface); } return &dm_plane_state->base; @@ -1479,17 +1457,8 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - if (dm_plane_state->dc_surface) { - struct dc_surface *dc_surface = dm_plane_state->dc_surface; - - if (dc_surface->gamma_correction) - dc_gamma_release(&dc_surface->gamma_correction); - - if (dc_surface->in_transfer_func) - dc_transfer_func_release(dc_surface->in_transfer_func); - - dc_surface_release(dc_surface); - } + if (dm_plane_state->dc_surface) + dc_surface_release(dm_plane_state->dc_surface); __drm_atomic_helper_plane_destroy_state(state); kfree(dm_plane_state); -- GitLab From d7e3316cf492d950f086e7fe5d3eb643c9e84be4 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 7 Jul 2017 16:14:12 -0400 Subject: [PATCH 0623/2898] drm/amd/display: Attach surface to dm_plane_state. Attach surface to state. Remove Create surface from commit. Propogate any surface creation and initialization error back to atomic_check caller. clean outdated code in check and commit. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 348 ++++++++---------- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- 2 files changed, 147 insertions(+), 203 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0439f75fb24d..b56150a29502 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -299,16 +299,16 @@ static bool fill_rects_from_plane_state( return true; } -static bool get_fb_info( +static int get_fb_info( const struct amdgpu_framebuffer *amdgpu_fb, uint64_t *tiling_flags, uint64_t *fb_location) { struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); int r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r != 0)){ + if (unlikely(r)) { DRM_ERROR("Unable to reserve buffer\n"); - return false; + return r; } if (fb_location) @@ -319,9 +319,10 @@ static bool get_fb_info( amdgpu_bo_unreserve(rbo); - return true; + return r; } -static void fill_plane_attributes_from_fb( + +static int fill_plane_attributes_from_fb( struct amdgpu_device *adev, struct dc_surface *surface, const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) @@ -330,13 +331,16 @@ static void fill_plane_attributes_from_fb( uint64_t fb_location = 0; unsigned int awidth; const struct drm_framebuffer *fb = &amdgpu_fb->base; + int ret = 0; struct drm_format_name_buf format_name; - get_fb_info( + ret = get_fb_info( amdgpu_fb, &tiling_flags, addReq == true ? &fb_location:NULL); + if (ret) + return ret; switch (fb->format->format) { case DRM_FORMAT_C8: @@ -366,7 +370,7 @@ static void fill_plane_attributes_from_fb( default: DRM_ERROR("Unsupported screen format %s\n", drm_get_format_name(fb->format->format, &format_name)); - return; + return -EINVAL; } if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { @@ -467,23 +471,26 @@ static void fill_plane_attributes_from_fb( surface->scaling_quality.v_taps = 0; surface->stereo_format = PLANE_STEREO_FORMAT_NONE; + return ret; + } #define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 -static void fill_gamma_from_crtc( - const struct drm_crtc *crtc, +static void fill_gamma_from_crtc_state( + const struct drm_crtc_state *crtc_state, struct dc_surface *dc_surface) { int i; struct dc_gamma *gamma; - struct drm_crtc_state *state = crtc->state; - struct drm_color_lut *lut = (struct drm_color_lut *) state->gamma_lut->data; + struct drm_color_lut *lut = (struct drm_color_lut *) crtc_state->gamma_lut->data; gamma = dc_create_gamma(); - if (gamma == NULL) + if (gamma == NULL) { + WARN_ON(1); return; + } for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { gamma->red[i] = lut[i].red; @@ -494,27 +501,35 @@ static void fill_gamma_from_crtc( dc_surface->gamma_correction = gamma; } -static void fill_plane_attributes( +static int fill_plane_attributes( struct amdgpu_device *adev, struct dc_surface *surface, - struct drm_plane_state *state, bool addrReq) + struct drm_plane_state *plane_state, + struct drm_crtc_state *crtc_state, + bool addrReq) { const struct amdgpu_framebuffer *amdgpu_fb = - to_amdgpu_framebuffer(state->fb); - const struct drm_crtc *crtc = state->crtc; + to_amdgpu_framebuffer(plane_state->fb); + const struct drm_crtc *crtc = plane_state->crtc; struct dc_transfer_func *input_tf; + int ret = 0; + + if (!fill_rects_from_plane_state(plane_state, surface)) + return -EINVAL; - fill_rects_from_plane_state(state, surface); - fill_plane_attributes_from_fb( + ret = fill_plane_attributes_from_fb( crtc->dev->dev_private, surface, amdgpu_fb, addrReq); + if (ret) + return ret; + input_tf = dc_create_transfer_func(); if (input_tf == NULL) - return; + return -ENOMEM; input_tf->type = TF_TYPE_PREDEFINED; input_tf->tf = TRANSFER_FUNCTION_SRGB; @@ -522,9 +537,10 @@ static void fill_plane_attributes( surface->in_transfer_func = input_tf; /* In case of gamma set, update gamma value */ - if (state->crtc->state->gamma_lut) { - fill_gamma_from_crtc(crtc, surface); - } + if (crtc_state->gamma_lut) + fill_gamma_from_crtc_state(crtc_state, surface); + + return ret; } /*****************************************************************************/ @@ -607,57 +623,6 @@ static void update_stream_scaling_settings( } -static void add_surface(struct dc *dc, - struct drm_crtc *crtc, - struct drm_plane *plane, - const struct dc_surface **dc_surfaces) -{ - struct dc_surface *dc_surface; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - const struct dc_stream *dc_stream = acrtc_state->stream; - unsigned long flags; - - spin_lock_irqsave(&crtc->dev->event_lock, flags); - if (acrtc->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("add_surface: acrtc %d, already busy\n", - acrtc->crtc_id); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - /* In comit tail framework this cannot happen */ - BUG_ON(0); - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - if (!dc_stream) { - dm_error( - "%s: Failed to obtain stream on crtc (%d)!\n", - __func__, - acrtc->crtc_id); - goto fail; - } - - dc_surface = dc_create_surface(dc); - - if (!dc_surface) { - dm_error( - "%s: Failed to create a surface!\n", - __func__); - goto fail; - } - - /* Surface programming */ - fill_plane_attributes( - crtc->dev->dev_private, - dc_surface, - plane->state, - true); - - *dc_surfaces = dc_surface; - -fail: - return; -} - static enum dc_color_depth convert_color_depth_from_display_info( const struct drm_connector *connector) { @@ -1444,9 +1409,9 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - if (old_dm_plane_state->dc_surface) { - dm_plane_state->dc_surface = old_dm_plane_state->dc_surface; - dc_surface_retain(dm_plane_state->dc_surface); + if (old_dm_plane_state->surface) { + dm_plane_state->surface = old_dm_plane_state->surface; + dc_surface_retain(dm_plane_state->surface); } return &dm_plane_state->base; @@ -1457,8 +1422,8 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - if (dm_plane_state->dc_surface) - dc_surface_release(dm_plane_state->dc_surface); + if (dm_plane_state->surface) + dc_surface_release(dm_plane_state->surface); __drm_atomic_helper_plane_destroy_state(state); kfree(dm_plane_state); @@ -1481,6 +1446,11 @@ static int dm_plane_helper_prepare_fb( struct drm_gem_object *obj; struct amdgpu_bo *rbo; int r; + struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; + unsigned int awidth; + + dm_plane_state_old = to_dm_plane_state(plane->state); + dm_plane_state_new = to_dm_plane_state(new_state); if (!new_state->fb) { DRM_DEBUG_KMS("No FB bound\n"); @@ -1497,6 +1467,7 @@ static int dm_plane_helper_prepare_fb( r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &afb->address); + amdgpu_bo_unreserve(rbo); if (unlikely(r != 0)) { @@ -1506,6 +1477,23 @@ static int dm_plane_helper_prepare_fb( amdgpu_bo_ref(rbo); + if (dm_plane_state_new->surface && + dm_plane_state_old->surface != dm_plane_state_new->surface) { + struct dc_surface *surface = dm_plane_state_new->surface; + + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + surface->address.grph.addr.low_part = lower_32_bits(afb->address); + surface->address.grph.addr.high_part = upper_32_bits(afb->address); + } else { + awidth = ALIGN(new_state->fb->width, 64); + surface->address.video_progressive.luma_addr.low_part + = lower_32_bits(afb->address); + surface->address.video_progressive.chroma_addr.low_part + = lower_32_bits(afb->address) + + (awidth * new_state->fb->height); + } + } + /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer * prepare and cleanup in drm_atomic_helper_prepare_planes * and drm_atomic_helper_cleanup_planes because fb doens't in s3. @@ -2362,59 +2350,43 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; + unsigned long flags; /* update planes when needed */ for_each_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; - struct drm_connector *connector; - struct dm_connector_state *con_state = NULL; bool pflip_needed; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); if (plane->type == DRM_PLANE_TYPE_CURSOR) { handle_cursor_update(plane, old_plane_state); continue; } - if (!fb || !crtc || pcrtc != crtc || !crtc->state->active) + if (!fb || !crtc || pcrtc != crtc || !crtc->state->active || + (!crtc->state->planes_changed && + !pcrtc->state->color_mgmt_changed)) continue; pflip_needed = !state->allow_modeset; + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) { + DRM_ERROR("add_surface: acrtc %d, already busy\n", + acrtc_attach->crtc_id); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + /* In comit tail framework this cannot happen */ + WARN_ON(1); + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + if (!pflip_needed) { - list_for_each_entry(connector, - &dev->mode_config.connector_list, - head) { - if (connector->state->crtc == crtc) { - con_state = to_dm_connector_state( - connector->state); - break; - } - } + WARN_ON(!dm_plane_state->surface); - /* - * This situation happens in the following case: - * we are about to get set mode for connector who's only - * possible crtc (in encoder crtc mask) is used by - * another connector, that is why it will try to - * re-assing crtcs in order to make configuration - * supported. For our implementation we need to make all - * encoders support all crtcs, then this issue will - * never arise again. But to guard code from this issue - * check is left. - * - * Also it should be needed when used with actual - * drm_atomic_commit ioctl in future - */ - if (!con_state) - continue; + dc_surfaces_constructed[planes_count] = dm_plane_state->surface; - add_surface(dm->dc, crtc, plane, - &dc_surfaces_constructed[planes_count]); - if (dc_surfaces_constructed[planes_count] == NULL) { - dm_error("%s: Failed to add surface!\n", __func__); - continue; - } dc_stream_attach = acrtc_state->stream; planes_count++; @@ -2461,9 +2433,6 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, planes_count, dc_stream_attach)) dm_error("%s: Failed to attach surface!\n", __func__); - - for (i = 0; i < planes_count; i++) - dc_surface_release(dc_surfaces_constructed[i]); } else { /*TODO BUG Here should go disable planes on CRTC. */ } @@ -2846,7 +2815,6 @@ static uint32_t add_val_sets_surface( static uint32_t update_in_val_sets_stream( struct dc_validation_set *val_sets, - struct drm_crtc **crtcs, uint32_t set_count, const struct dc_stream *old_stream, const struct dc_stream *new_stream, @@ -2861,7 +2829,6 @@ static uint32_t update_in_val_sets_stream( } val_sets[i].stream = new_stream; - crtcs[i] = crtc; if (i == set_count) /* nothing found. add new one to the end */ @@ -2955,10 +2922,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_plane_state *plane_state; int i, j; int ret; - struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct amdgpu_device *adev = dev->dev_private; struct dc *dc = adev->dm.dc; - bool need_to_validate = false; struct drm_connector *connector; struct drm_connector_state *conn_state; int set_count; @@ -2974,13 +2939,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_atomic_helper_check(dev, state); if (ret) { - DRM_ERROR("Atomic state validation failed with error :%d !\n", - ret); + DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); return ret; } - ret = -EINVAL; - dm_state = to_dm_atomic_state(state); /* copy existing configuration */ @@ -2992,7 +2954,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (old_acrtc_state->stream) { dc_stream_retain(old_acrtc_state->stream); set[set_count].stream = old_acrtc_state->stream; - crtc_set[set_count] = crtc; ++set_count; } } @@ -3027,8 +2988,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (aconnector) { conn_state = drm_atomic_get_connector_state(state, &aconnector->base); - if (IS_ERR(conn_state)) - return ret; + if (IS_ERR(conn_state)) { + ret = PTR_ERR_OR_ZERO(conn_state); + goto fail_crtcs; + } + dm_conn_state = to_dm_connector_state(conn_state); } @@ -3048,17 +3012,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (new_acrtc_state->stream) dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = new_stream; set_count = update_in_val_sets_stream( set, - crtc_set, set_count, old_acrtc_state->stream, new_acrtc_state->stream, crtc); - need_to_validate = true; aquire_global_lock = true; } else if (modereset_required(crtc_state)) { @@ -3086,9 +3049,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_atomic_add_affected_planes(state, crtc); if (ret) - return ret; - - ret = -EINVAL; + goto fail_crtcs; } } @@ -3113,118 +3074,101 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(con_new_state, con_old_state)) continue; - need_to_validate = true; aquire_global_lock = true; } - for (i = 0; i < set_count; i++) { + for_each_crtc_in_state(state, crtc, crtc_state, i) { + new_acrtc_state = to_dm_crtc_state(crtc_state); + for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_crtc *crtc = plane_state->crtc; + struct drm_crtc *plane_crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; - struct drm_connector *connector; - struct dm_connector_state *dm_conn_state = NULL; - struct drm_crtc_state *crtc_state; bool pflip_needed; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); /*TODO Implement atomic check for cursor plane */ if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - if (!fb || !crtc || crtc_set[i] != crtc || - !crtc->state->planes_changed || !crtc->state->active) + if (!fb || !plane_crtc || crtc != plane_crtc || + (!crtc_state->planes_changed && + !crtc_state->color_mgmt_changed) || + !crtc_state->active) continue; + WARN_ON(!new_acrtc_state->stream); - crtc_state = drm_atomic_get_crtc_state(state, crtc); pflip_needed = !state->allow_modeset; if (!pflip_needed) { struct dc_surface *surface; - list_for_each_entry(connector, - &dev->mode_config.connector_list, head) { - if (connector->state->crtc == crtc) { - dm_conn_state = to_dm_connector_state( - connector->state); - break; - } - } - - /* - * This situation happens in the following case: - * we are about to get set mode for connector who's only - * possible crtc (in encoder crtc mask) is used by - * another connector, that is why it will try to - * re-assing crtcs in order to make configuration - * supported. For our implementation we need to make all - * encoders support all crtcs, then this issue will - * never arise again. But to guard code from this issue - * check is left. - * - * Also it should be needed when used with actual - * drm_atomic_commit ioctl in future - */ - if (!dm_conn_state) - continue; - surface = dc_create_surface(dc); - fill_plane_attributes( - crtc->dev->dev_private, + + ret = fill_plane_attributes( + plane_crtc->dev->dev_private, surface, plane_state, + crtc_state, false); + if (ret) + goto fail_planes; + + + if (dm_plane_state->surface) + dc_surface_release(dm_plane_state->surface); + + dm_plane_state->surface = surface; add_val_sets_surface(set, set_count, - set[i].stream, + new_acrtc_state->stream, surface); - need_to_validate = true; aquire_global_lock = true; } } } dm_state->context = dc_get_validate_context(dc, set, set_count); - - if (need_to_validate == false || set_count == 0 || dm_state->context) { - ret = 0; - /* - * For full updates case when - * removing/adding/updateding streams on once CRTC while flipping - * on another CRTC, - * acquiring global lock will guarantee that any such full - * update commit - * will wait for completion of any outstanding flip using DRMs - * synchronization events. - */ - if (aquire_global_lock) - ret = do_aquire_global_lock(dev, state); - + if (!dm_state->context) { + ret = -EINVAL; + goto fail_planes; } - /* TODO until surfaces are moved into dm_plane_state release them - * here + /* + * For full updates case when + * removing/adding/updating streams on once CRTC while flipping + * on another CRTC, + * acquiring global lock will guarantee that any such full + * update commit + * will wait for completion of any outstanding flip using DRMs + * synchronization events. */ + if (aquire_global_lock) { + ret = do_aquire_global_lock(dev, state); + if (ret) + goto fail_planes; + } + + /* Must be success */ + WARN_ON(ret); + return ret; + +fail_planes: for (i = 0; i < set_count; i++) for (j = 0; j < set[i].surface_count; j++) dc_surface_release(set[i].surfaces[j]); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - old_acrtc_state = to_dm_crtc_state(crtc->state); - - if (old_acrtc_state->stream) - dc_stream_release(old_acrtc_state->stream); - } - +fail_crtcs: + for (i = 0; i < set_count; i++) + dc_stream_release(set[i].stream); - if (ret != 0) { - if (ret == -EDEADLK) - DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); - else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); - else - DRM_ERROR("Atomic check failed.\n"); - } + if (ret == -EDEADLK) + DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); + else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) + DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); + else + DRM_ERROR("Atomic check failed with err: %d .\n", ret); return ret; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 36cb1c840810..115d9081d964 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -40,7 +40,7 @@ struct dc_stream; struct dm_plane_state { struct drm_plane_state base; - struct dc_surface *dc_surface; + struct dc_surface *surface; }; struct dm_crtc_state { -- GitLab From 7b0c470fcb44b7dbe63db5b5fb52b6123ebe335f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Mon, 10 Jul 2017 14:04:21 -0400 Subject: [PATCH 0624/2898] drm/amd/display: Flattening to dc_transfer_func Flattening dc transfer functions in the following manner: transfer_func > core_transfer_func > dc_transfer_func References to deleted structs are updated as needed. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_surface.c | 19 ++++--------------- drivers/gpu/drm/amd/display/dc/dc.h | 10 ++++++---- .../display/dc/dce110/dce110_hw_sequencer.c | 10 +++++----- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +++++----- .../gpu/drm/amd/display/dc/inc/core_types.h | 8 -------- 5 files changed, 20 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index aa6ac9596235..d44ddfb85748 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -45,18 +45,11 @@ struct gamma { int ref_count; }; -struct transfer_func { - struct core_transfer_func protected; - int ref_count; -}; - #define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) #define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) #define DC_GAMMA_TO_GAMMA(dc_gamma) \ container_of(dc_gamma, struct gamma, protected.public) -#define DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf) \ - container_of(dc_tf, struct transfer_func, protected.public) #define CORE_GAMMA_TO_GAMMA(core_gamma) \ container_of(core_gamma, struct gamma, protected) @@ -208,18 +201,14 @@ struct dc_gamma *dc_create_gamma() return NULL; } -void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf) +void dc_transfer_func_retain(struct dc_transfer_func *tf) { - struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); - ASSERT(tf->ref_count > 0); ++tf->ref_count; } -void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) +void dc_transfer_func_release(struct dc_transfer_func *tf) { - struct transfer_func *tf = DC_TRANSFER_FUNC_TO_TRANSFER_FUNC(dc_tf); - ASSERT(tf->ref_count > 0); --tf->ref_count; @@ -229,14 +218,14 @@ void dc_transfer_func_release(const struct dc_transfer_func *dc_tf) struct dc_transfer_func *dc_create_transfer_func() { - struct transfer_func *tf = dm_alloc(sizeof(*tf)); + struct dc_transfer_func *tf = dm_alloc(sizeof(*tf)); if (tf == NULL) goto alloc_fail; ++tf->ref_count; - return &tf->protected.public; + return tf; alloc_fail: return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 42c1aa8d68af..1fad03cdeb9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -293,6 +293,8 @@ struct dc_transfer_func { struct dc_transfer_func_distributed_points tf_pts; enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; + struct dc_context *ctx; + int ref_count; }; struct dc_surface { @@ -310,7 +312,7 @@ struct dc_surface { struct dc_hdr_static_metadata hdr_static_ctx; const struct dc_gamma *gamma_correction; - const struct dc_transfer_func *in_transfer_func; + struct dc_transfer_func *in_transfer_func; enum dc_color_space color_space; enum surface_pixel_format format; @@ -384,8 +386,8 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma); void dc_gamma_release(const struct dc_gamma **dc_gamma); struct dc_gamma *dc_create_gamma(void); -void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf); -void dc_transfer_func_release(const struct dc_transfer_func *dc_tf); +void dc_transfer_func_retain(struct dc_transfer_func *dc_tf); +void dc_transfer_func_release(struct dc_transfer_func *dc_tf); struct dc_transfer_func *dc_create_transfer_func(void); /* @@ -465,7 +467,7 @@ struct dc_stream { struct freesync_context freesync_ctx; - const struct dc_transfer_func *out_transfer_func; + struct dc_transfer_func *out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct csc_transform csc_color_matrix; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d3c84dc36b80..5d64611eb6a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -242,7 +242,7 @@ static bool dce110_set_input_transfer_func( const struct core_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; - const struct core_transfer_func *tf = NULL; + const struct dc_transfer_func *tf = NULL; struct ipp_prescale_params prescale_params = { 0 }; bool result = true; @@ -250,7 +250,7 @@ static bool dce110_set_input_transfer_func( return false; if (surface->public.in_transfer_func) - tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + tf = surface->public.in_transfer_func; build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); @@ -262,8 +262,8 @@ static bool dce110_set_input_transfer_func( /* Default case if no input transfer function specified */ ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); - } else if (tf->public.type == TF_TYPE_PREDEFINED) { - switch (tf->public.tf) { + } else if (tf->type == TF_TYPE_PREDEFINED) { + switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); @@ -283,7 +283,7 @@ static bool dce110_set_input_transfer_func( result = false; break; } - } else if (tf->public.type == TF_TYPE_BYPASS) { + } else if (tf->type == TF_TYPE_BYPASS) { ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4c39bf052d08..ac0d62c10da2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -602,14 +602,14 @@ static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; - const struct core_transfer_func *tf = NULL; + const struct dc_transfer_func *tf = NULL; bool result = true; if (ipp == NULL) return false; if (surface->public.in_transfer_func) - tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func); + tf = surface->public.in_transfer_func; if (surface->public.gamma_correction && dce_use_lut(surface)) ipp->funcs->ipp_program_input_lut(ipp, @@ -617,8 +617,8 @@ static bool dcn10_set_input_transfer_func( if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); - else if (tf->public.type == TF_TYPE_PREDEFINED) { - switch (tf->public.tf) { + else if (tf->type == TF_TYPE_PREDEFINED) { + switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB); @@ -638,7 +638,7 @@ static bool dcn10_set_input_transfer_func( result = false; break; } - } else if (tf->public.type == TF_TYPE_BYPASS) { + } else if (tf->type == TF_TYPE_BYPASS) { ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 030841889803..3e9a0ccca3b4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -49,9 +49,6 @@ struct core_stream; #define DC_GAMMA_TO_CORE(dc_gamma) \ container_of(dc_gamma, struct core_gamma, public) -#define DC_TRANSFER_FUNC_TO_CORE(dc_transfer_func) \ - container_of(dc_transfer_func, struct core_transfer_func, public) - struct core_surface { struct dc_surface public; struct dc_surface_status status; @@ -63,11 +60,6 @@ struct core_gamma { struct dc_context *ctx; }; -struct core_transfer_func { - struct dc_transfer_func public; - struct dc_context *ctx; -}; - void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id); -- GitLab From 2ebad8eb19f68638c5f5dee385e05aa466e810e5 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 11 Jul 2017 13:40:52 -0400 Subject: [PATCH 0625/2898] drm/amd/display: change non_dpm0 state's default SR latency Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index a1eabc47558e..0ea0dab49e0f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -37,8 +37,8 @@ /* Defaults from spreadsheet rev#247 */ const struct dcn_soc_bounding_box dcn10_soc_defaults = { /* latencies */ - .sr_exit_time = 17, /*us*/ - .sr_enter_plus_exit_time = 19, /*us*/ + .sr_exit_time = 13, /*us*/ + .sr_enter_plus_exit_time = 15, /*us*/ .urgent_latency = 4, /*us*/ .dram_clock_change_latency = 17, /*us*/ .write_back_latency = 12, /*us*/ -- GitLab From 8a76708ec4be2e9d63131e3769f17a04d8a82c87 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 11 Jul 2017 14:41:51 -0400 Subject: [PATCH 0626/2898] drm/amd/display: Introduce refcount for dc_validate_context Linux requires to be able to release allocated context in case it was never commited. Signed-off-by: Andrey Grodzovsky Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 64 ++++++++++++++----- drivers/gpu/drm/amd/display/dc/dc.h | 4 ++ .../gpu/drm/amd/display/dc/inc/core_types.h | 2 + 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4f9302901a62..e81c9d57b3d1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -423,7 +423,7 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) static void destruct(struct core_dc *dc) { - dc_resource_validate_ctx_destruct(dc->current_context); + dc_release_validate_context(dc->current_context); destroy_links(dc); @@ -467,6 +467,8 @@ static bool construct(struct core_dc *dc, goto val_ctx_fail; } + dc->current_context->ref_count++; + dc_ctx->cgs_device = init_params->cgs_device; dc_ctx->driver_context = init_params->driver; dc_ctx->dc = &dc->public; @@ -683,6 +685,8 @@ struct validate_context *dc_get_validate_context( if (context == NULL) goto context_alloc_fail; + ++context->ref_count; + if (!is_validation_required(core_dc, set, set_count)) { dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); return context; @@ -698,8 +702,7 @@ struct validate_context *dc_get_validate_context( __func__, result); - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); context = NULL; } @@ -720,6 +723,8 @@ bool dc_validate_resources( if (context == NULL) goto context_alloc_fail; + ++context->ref_count; + result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, set_count, context, NULL); @@ -731,8 +736,7 @@ bool dc_validate_resources( result); } - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); context = NULL; return result == DC_OK; @@ -750,11 +754,12 @@ bool dc_validate_guaranteed( if (context == NULL) goto context_alloc_fail; + ++context->ref_count; + result = core_dc->res_pool->funcs->validate_guaranteed( core_dc, stream, context); - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); context_alloc_fail: if (result != DC_OK) { @@ -972,8 +977,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); + dc_release_validate_context(core_dc->current_context); + + dc_retain_validate_context(context); + core_dc->current_context = context; return (result == DC_OK); @@ -1045,6 +1052,8 @@ bool dc_commit_streams( if (context == NULL) goto context_alloc_fail; + ++context->ref_count; + result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, stream_count, context, core_dc->current_context); if (result != DC_OK){ @@ -1053,7 +1062,6 @@ bool dc_commit_streams( __func__, result); BREAK_TO_DEBUGGER(); - dc_resource_validate_ctx_destruct(context); goto fail; } @@ -1062,7 +1070,7 @@ bool dc_commit_streams( return (result == DC_OK); fail: - dm_free(context); + dc_release_validate_context(context); context_alloc_fail: return (result == DC_OK); @@ -1155,6 +1163,23 @@ bool dc_commit_surfaces_to_stream( return true; } +void dc_retain_validate_context(struct validate_context *context) +{ + ASSERT(context->ref_count > 0); + ++context->ref_count; +} + +void dc_release_validate_context(struct validate_context *context) +{ + ASSERT(context->ref_count > 0); + --context->ref_count; + + if (context->ref_count == 0) { + dc_resource_validate_ctx_destruct(context); + dm_free(context); + } +} + static bool is_surface_in_context( const struct validate_context *context, const struct dc_surface *surface) @@ -1341,6 +1366,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, enum surface_update_type update_type; const struct dc_stream_status *stream_status; struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); + struct dc_context *dc_ctx = core_dc->ctx; stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); @@ -1403,6 +1429,11 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* initialize scratch memory for building context */ context = dm_alloc(sizeof(*context)); + if (context == NULL) + goto context_alloc_fail; + + ++context->ref_count; + dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); @@ -1624,16 +1655,17 @@ void dc_update_surfaces_and_stream(struct dc *dc, } if (core_dc->current_context != context) { - dc_resource_validate_ctx_destruct(core_dc->current_context); - dm_free(core_dc->current_context); - + dc_release_validate_context(core_dc->current_context); + dc_retain_validate_context(context); core_dc->current_context = context; } return; fail: - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); + +context_alloc_fail: + DC_ERROR("Failed to allocate new validate context!\n"); } uint8_t dc_get_current_stream_count(const struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1fad03cdeb9d..cd8981469fe9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -643,6 +643,10 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status); + +void dc_retain_validate_context(struct validate_context *context); +void dc_release_validate_context(struct validate_context *context); + /******************************************************************************* * Link Interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 3e9a0ccca3b4..d216522a9989 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -361,6 +361,8 @@ struct validate_context { #ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct dcn_bw_internal_vars dcn_bw_vars; #endif + + int ref_count; }; #endif /* _CORE_TYPES_H_ */ -- GitLab From 3b42a1c09568ac6b65bfa40931600c5fe49d31e2 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 11 Jul 2017 13:45:57 -0400 Subject: [PATCH 0627/2898] drm/amd/display: Skip DC validation for flips and cursor. Nothing to validate in DC in this case. Skip it. Signed-off-by: Andrey Grodzovsky Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b56150a29502..248b397a6a7d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1311,8 +1311,7 @@ int amdgpu_dm_connector_mode_valid( if (context) { result = MODE_OK; - dc_resource_validate_ctx_destruct(context); - dm_free(context); + dc_release_validate_context(context); } dc_stream_release(stream); @@ -2598,8 +2597,8 @@ void amdgpu_dm_atomic_commit_tail( } } - /* DC is optimized not to do anything if 'streams' didn't change. */ - WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); + if (dm_state->context) + WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -2932,9 +2931,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, /* * This bool will be set for true for any modeset/reset - * or surface update which implies non fast surfae update. + * or surface update which implies non fast surface update. */ - bool aquire_global_lock = false; + bool lock_and_validation_needed = false; ret = drm_atomic_helper_check(dev, state); @@ -3022,7 +3021,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_acrtc_state->stream, crtc); - aquire_global_lock = true; + lock_and_validation_needed = true; } else if (modereset_required(crtc_state)) { @@ -3036,7 +3035,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dc_stream_release(new_acrtc_state->stream); new_acrtc_state->stream = NULL; - aquire_global_lock = true; + lock_and_validation_needed = true; } } @@ -3074,7 +3073,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(con_new_state, con_old_state)) continue; - aquire_global_lock = true; + lock_and_validation_needed = true; } for_each_crtc_in_state(state, crtc, crtc_state, i) { @@ -3124,17 +3123,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_acrtc_state->stream, surface); - aquire_global_lock = true; + lock_and_validation_needed = true; } } } - dm_state->context = dc_get_validate_context(dc, set, set_count); - if (!dm_state->context) { - ret = -EINVAL; - goto fail_planes; - } - /* * For full updates case when * removing/adding/updating streams on once CRTC while flipping @@ -3144,10 +3137,18 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * will wait for completion of any outstanding flip using DRMs * synchronization events. */ - if (aquire_global_lock) { + + if (lock_and_validation_needed) { + ret = do_aquire_global_lock(dev, state); if (ret) goto fail_planes; + + dm_state->context = dc_get_validate_context(dc, set, set_count); + if (!dm_state->context) { + ret = -EINVAL; + goto fail_planes; + } } /* Must be success */ -- GitLab From 0a323b84fab27fe51d35a4c55c73484c45c50f14 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 11 Jul 2017 14:42:57 -0400 Subject: [PATCH 0628/2898] drm/amd/display: Release dm_state->context when state is cleared. Handling a use case of TEST_ONLY request from DRM where commit is not goiing to be called. We need to release the allocated dc_validate_context in this case. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +++++++++++++++++++ .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 63d23c6e7574..e16e87173db3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -653,12 +653,35 @@ dm_atomic_state_alloc(struct drm_device *dev) return &state->base; } +static void +dm_atomic_state_clear(struct drm_atomic_state *state) +{ + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + + if (dm_state->context) { + dc_release_validate_context(dm_state->context); + dm_state->context = NULL; + } + + drm_atomic_state_default_clear(state); +} + +static void +dm_atomic_state_alloc_free(struct drm_atomic_state *state) +{ + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + drm_atomic_state_default_release(state); + kfree(dm_state); +} + static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_user_framebuffer_create, .output_poll_changed = amdgpu_output_poll_changed, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = amdgpu_dm_atomic_commit, .atomic_state_alloc = dm_atomic_state_alloc, + .atomic_state_clear = dm_atomic_state_clear, + .atomic_state_free = dm_atomic_state_alloc_free }; static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 248b397a6a7d..af4de578dadb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -3144,6 +3144,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail_planes; + WARN_ON(dm_state->context); dm_state->context = dc_get_validate_context(dc, set, set_count); if (!dm_state->context) { ret = -EINVAL; -- GitLab From ef347b3b80c2f973140553db41224f886ef3b9da Mon Sep 17 00:00:00 2001 From: John Wu Date: Wed, 12 Jul 2017 14:25:52 +0800 Subject: [PATCH 0629/2898] drm/amd/display: Fix eDP power isn't off when lid close Signed-off-by: John Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 4f46ff14fb69..0092e70b9efd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -112,8 +112,10 @@ void dp_disable_link_phy(struct core_link *link, enum signal_type signal) if (!link->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(link, false); - if (signal == SIGNAL_TYPE_EDP) + if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); + link->link_enc->funcs->power_control(link->link_enc, false); + } link->link_enc->funcs->disable_output(link->link_enc, signal); -- GitLab From 189f73e32e9a7fc5ac62f244b66f8b41a78803c7 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 09:02:54 -0400 Subject: [PATCH 0630/2898] drm/amd/display: change order of HUBP and MPC disable according to HW guide blank hubp first before disconnect MPC Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +++++++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ac0d62c10da2..0e90e6cc4930 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -477,9 +477,14 @@ static void reset_front_end( if (mpcc->opp_id == 0xf) return; - mi->funcs->dcc_control(mi, false, false); tg->funcs->lock(tg); + mi->funcs->dcc_control(mi, false, false); + mi->funcs->set_blank(mi, true); + REG_WAIT(DCHUBP_CNTL[fe_idx], + HUBP_NO_OUTSTANDING_REQ, 1, + 1, 200); + mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; @@ -491,8 +496,7 @@ static void reset_front_end( REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); mpcc->funcs->wait_for_idle(mpcc); - mi->funcs->set_blank(mi, true); - REG_WAIT(DCHUBP_CNTL[fe_idx], HUBP_NO_OUTSTANDING_REQ, 1, 20000, 200000); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 1c9d5e96ab55..9875d812e185 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -117,7 +117,9 @@ static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) { struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); - REG_WAIT(MPCC_STATUS, MPCC_BUSY, 0, 1000, 1000); + REG_WAIT(MPCC_STATUS, + MPCC_BUSY, 0, + 1000, 1000); } -- GitLab From 9a3afbb3ea37b9a6bc16b9d6e4a51b183724158d Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 11 Jul 2017 18:36:42 -0400 Subject: [PATCH 0631/2898] drm/amd/display: dc_validate_ctx refocunt fixes. In dc_resource_validate_ctx_copy_construct don't override dst context refcount. Remove extra retain to new ctx in dc_update_surfaces_and_stream Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +---- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e81c9d57b3d1..8e580ac91b2a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -424,6 +424,7 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc) static void destruct(struct core_dc *dc) { dc_release_validate_context(dc->current_context); + dc->current_context = NULL; destroy_links(dc); @@ -441,9 +442,6 @@ static void destruct(struct core_dc *dc) if (dc->ctx->logger) dal_logger_destroy(&dc->ctx->logger); - dm_free(dc->current_context); - dc->current_context = NULL; - dm_free(dc->ctx); dc->ctx = NULL; } @@ -1656,7 +1654,6 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (core_dc->current_context != context) { dc_release_validate_context(core_dc->current_context); - dc_retain_validate_context(context); core_dc->current_context = context; } return; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 5a5ed37474bf..78ba5c6d9ac2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2166,6 +2166,7 @@ void dc_resource_validate_ctx_copy_construct( struct validate_context *dst_ctx) { int i, j; + int ref_count = dst_ctx->ref_count; *dst_ctx = *src_ctx; @@ -2186,6 +2187,10 @@ void dc_resource_validate_ctx_copy_construct( dc_surface_retain( dst_ctx->stream_status[i].surfaces[j]); } + + /* context refcount should not be overridden */ + dst_ctx->ref_count = ref_count; + } struct clock_source *dc_resource_find_first_free_pll( -- GitLab From d21becbe0225de0e2582d17d4fbc73fbd103b1f7 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 11:54:10 -0400 Subject: [PATCH 0632/2898] drm/amd/display: avoid disabling opp clk before hubp is blanked. Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 7 +++++++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 18 ++++++++++++++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 -- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 8 ++------ 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 6985a4607bd3..4da9142351fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -141,6 +141,10 @@ SRII(DPP_CONTROL, DPP_TOP, 1), \ SRII(DPP_CONTROL, DPP_TOP, 2), \ SRII(DPP_CONTROL, DPP_TOP, 3), \ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, 0), \ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, 1), \ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, 2), \ + SRII(OPP_PIPE_CONTROL, OPP_PIPE, 3), \ SR(REFCLK_CNTL), \ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ SR(DC_IP_REQUEST_CNTL), \ @@ -188,6 +192,7 @@ struct dce_hwseq_registers { uint32_t DCHUBP_CNTL[4]; uint32_t HUBP_CLK_CNTL[4]; uint32_t DPP_CONTROL[4]; + uint32_t OPP_PIPE_CONTROL[4]; uint32_t REFCLK_CNTL; uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; uint32_t DC_IP_REQUEST_CNTL; @@ -282,6 +287,7 @@ struct dce_hwseq_registers { HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh), \ HWS_SF(HUBP0_, HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ + HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ @@ -346,6 +352,7 @@ struct dce_hwseq_registers { type DPP_CLOCK_ENABLE; \ type DPPCLK_RATE_CONTROL; \ type DCHUBBUB_GLOBAL_TIMER_ENABLE; \ + type OPP_PIPE_CLOCK_EN;\ type IP_REQUEST_EN; \ type DOMAIN0_POWER_FORCEON; \ type DOMAIN0_POWER_GATE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 0e90e6cc4930..18686be20004 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -472,9 +472,10 @@ static void reset_front_end( struct transform *xfm = dc->res_pool->transforms[fe_idx]; struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; + unsigned int opp_id = mpcc->opp_id; /*Already reset*/ - if (mpcc->opp_id == 0xf) + if (opp_id == 0xf) return; tg->funcs->lock(tg); @@ -497,8 +498,12 @@ static void reset_front_end( mpcc->funcs->wait_for_idle(mpcc); - REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); - REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], + HUBP_CLOCK_ENABLE, 0); + REG_UPDATE(DPP_CONTROL[fe_idx], + DPP_CLOCK_ENABLE, 0); + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + OPP_PIPE_CLOCK_EN, 0); xfm->funcs->transform_reset(xfm); @@ -1211,7 +1216,12 @@ static void dcn10_power_on_fe( pipe_ctx->pipe_idx); /* enable DCFCLK current DCHUB */ - REG_UPDATE(HUBP_CLK_CNTL[pipe_ctx->pipe_idx], HUBP_CLOCK_ENABLE, 1); + REG_UPDATE(HUBP_CLK_CNTL[pipe_ctx->pipe_idx], + HUBP_CLOCK_ENABLE, 1); + + /* make sure OPP_PIPE_CLOCK_EN = 1 */ + REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->tg->inst], + OPP_PIPE_CLOCK_EN, 1); if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 9875d812e185..de3341d572be 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -68,14 +68,12 @@ static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) { ASSERT(mpcc10->base.opp_id == 0xf || opp_id == mpcc10->base.opp_id); mpcc10->base.opp_id = opp_id; - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); } static void reset_output_mux(struct dcn10_mpcc *mpcc10) { REG_SET(MUX[mpcc10->base.opp_id], 0, MPC_OUT_MUX, 0xf); - REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->base.opp_id], OPP_PIPE_CLOCK_EN, 0); mpcc10->base.opp_id = 0xf; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 6a90a8bc09f8..2985c5d5a0e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -33,8 +33,7 @@ #define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MUX, MPC_OUT, inst),\ - SRII(OPP_PIPE_CONTROL, OPP_PIPE, inst) + SRII(MUX, MPC_OUT, inst) #define MPCC_COMMON_REG_LIST_DCN1_0(inst) \ SRI(MPCC_TOP_SEL, MPCC, inst),\ @@ -56,7 +55,6 @@ struct dcn_mpcc_registers { uint32_t MPCC_BG_G_Y; uint32_t MPCC_BG_R_CR; uint32_t MPCC_BG_B_CB; - uint32_t OPP_PIPE_CONTROL[MAX_OPP]; uint32_t MUX[MAX_OPP]; }; @@ -73,8 +71,7 @@ struct dcn_mpcc_registers { SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ - SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\ - SF(OPP_PIPE0_OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh) + SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh) #define MPCC_REG_FIELD_LIST(type) \ type MPCC_TOP_SEL;\ @@ -90,7 +87,6 @@ struct dcn_mpcc_registers { type MPCC_BG_R_CR;\ type MPCC_BG_B_CB;\ type MPC_OUT_MUX;\ - type OPP_PIPE_CLOCK_EN;\ struct dcn_mpcc_shift { MPCC_REG_FIELD_LIST(uint8_t) -- GitLab From 9294c7763fdc3da62dbf74a279921120c8f76721 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 12 Jul 2017 15:49:46 -0400 Subject: [PATCH 0633/2898] drm/amd/display: fix 4k@30 with 10bit deep color and avi for BT2020 Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 78ba5c6d9ac2..9d0128e95767 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1661,7 +1661,8 @@ static void set_avi_info_frame( /* C0, C1 : Colorimetry */ if (color_space == COLOR_SPACE_YCBCR709 || - color_space == COLOR_SPACE_YCBCR709_LIMITED) + color_space == COLOR_SPACE_YCBCR709_LIMITED || + color_space == COLOR_SPACE_2020_YCBCR) hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709; else if (color_space == COLOR_SPACE_YCBCR601 || color_space == COLOR_SPACE_YCBCR601_LIMITED) -- GitLab From 38917a1eb2748021fc0fd2ed4fd9b7f583713916 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 09:00:14 -0400 Subject: [PATCH 0634/2898] drm/amd/display: ensure OTG is locked before proceeding also remove tg lock at init_hw as not all OTG is running Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 18686be20004..82a96de2843f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -283,13 +283,11 @@ static void init_hw(struct core_dc *dc) dc->res_pool->mpcc[i]; struct mpcc_cfg mpcc_cfg; - tg->funcs->lock(tg); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = true; mpcc->funcs->set(mpcc, &mpcc_cfg); - tg->funcs->unlock(tg); tg->funcs->disable_vga(tg); /* Blank controller using driver code instead of diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index e1899f5fb083..12d7f3570cfa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -573,6 +573,10 @@ static void tgn10_lock(struct timing_generator *tg) OTG_MASTER_UPDATE_LOCK_SEL, tg->inst); REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 1); + + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 100); } static void tgn10_unlock(struct timing_generator *tg) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index e287b2babdc4..747e8211e507 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -140,6 +140,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ @@ -233,6 +234,7 @@ struct dcn_tg_registers { type OTG_BLANK_DE_MODE;\ type OTG_CURRENT_BLANK_STATE;\ type OTG_MASTER_UPDATE_LOCK;\ + type UPDATE_LOCK_STATUS;\ type OTG_UPDATE_PENDING;\ type OTG_MASTER_UPDATE_LOCK_SEL;\ type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ -- GitLab From 71a2f23e9101887de251ef1dcd35219d4e4f5e93 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 12 Jul 2017 18:38:04 -0400 Subject: [PATCH 0635/2898] drm/amd/display: fix mpo exit hang Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 82a96de2843f..dbf9cea2e418 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -500,8 +500,10 @@ static void reset_front_end( HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], - OPP_PIPE_CLOCK_EN, 0); + + if (mpcc_cfg.top_of_tree) + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + OPP_PIPE_CLOCK_EN, 0); xfm->funcs->transform_reset(xfm); @@ -1584,7 +1586,7 @@ static void dcn10_apply_ctx_for_surface( int i; /* reset unused mpcc */ - /*for (i = 0; i < dc->res_pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; @@ -1593,7 +1595,12 @@ static void dcn10_apply_ctx_for_surface( || (!pipe_ctx->stream && old_pipe_ctx->stream)) { struct mpcc_cfg mpcc_cfg; - mpcc_cfg.opp_id = 0xf; + if (!old_pipe_ctx->top_pipe) { + ASSERT(0); + continue; + } + + mpcc_cfg.opp_id = old_pipe_ctx->mpcc->opp_id; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; @@ -1607,7 +1614,7 @@ static void dcn10_apply_ctx_for_surface( "Reset mpcc for pipe %d\n", old_pipe_ctx->pipe_idx); } - }*/ + } if (!surface) return; -- GitLab From 587cdfe9463e6b66186c3c70fe7e63790cf4d148 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Wed, 5 Jul 2017 17:03:04 -0500 Subject: [PATCH 0636/2898] drm/amd/display: Rename trasnform to dpp for dcn's Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../dcn10/{dcn10_transform.c => dcn10_dpp.c} | 113 +++++++++--------- .../dcn10/{dcn10_transform.h => dcn10_dpp.h} | 32 +++-- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 + .../drm/amd/display/dc/dcn10/dcn10_resource.c | 38 +++--- 5 files changed, 93 insertions(+), 94 deletions(-) rename drivers/gpu/drm/amd/display/dc/dcn10/{dcn10_transform.c => dcn10_dpp.c} (91%) rename drivers/gpu/drm/amd/display/dc/dcn10/{dcn10_transform.h => dcn10_dpp.h} (96%) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 2c43ad7a6f3f..9ba1bfc30146 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -2,7 +2,7 @@ # Makefile for DCN. DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ - dcn10_transform.o dcn10_opp.o dcn10_timing_generator.o \ + dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_mem_input.o dcn10_mpc.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c similarity index 91% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c rename to drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 59ba2d250d6d..85d3ca31daf5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -32,7 +32,7 @@ #include "include/logger_interface.h" #include "reg_helper.h" -#include "dcn10_transform.h" +#include "dcn10_dpp.h" #include "basics/conversion.h" #define NUM_PHASES 64 @@ -112,8 +112,8 @@ enum gamut_remap_select { GAMUT_REMAP_COMB_COEFF }; -static void transform_set_overscan( - struct dcn10_transform *xfm, +static void dpp_set_overscan( + struct dcn10_dpp *xfm, const struct scaler_data *data) { uint32_t left = data->recout.x; @@ -140,8 +140,8 @@ static void transform_set_overscan( EXT_OVERSCAN_TOP, top); } -static void transform_set_otg_blank( - struct dcn10_transform *xfm, const struct scaler_data *data) +static void dpp_set_otg_blank( + struct dcn10_dpp *xfm, const struct scaler_data *data) { uint32_t h_blank_start = data->h_active; uint32_t h_blank_end = 0; @@ -212,8 +212,8 @@ static int get_pixel_depth_val(enum lb_pixel_depth depth) } } -static void xfmn10_set_lb( - struct dcn10_transform *xfm, +static void dpp_set_lb( + struct dcn10_dpp *xfm, const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) { @@ -233,8 +233,8 @@ static void xfmn10_set_lb( LB_MAX_PARTITIONS, 63); } -static void transform_set_scaler_filter( - struct dcn10_transform *xfm, +static void dpp_set_scaler_filter( + struct dcn10_dpp *xfm, uint32_t taps, enum dcn10_coef_filter_type_sel filter_type, const uint16_t *filter) @@ -272,12 +272,12 @@ static void transform_set_scaler_filter( } #if 0 -bool transform_set_pixel_storage_depth( - struct transform *xfm, +bool dpp_set_pixel_storage_depth( + struct dpp *xfm, enum lb_pixel_depth depth, const struct bit_depth_reduction_params *bit_depth_params) { - struct dcn10_transform *xfm110 = TO_DCN10_TRANSFORM(xfm); + struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm); bool ret = true; uint32_t value; enum dc_color_depth color_depth; @@ -355,8 +355,8 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) } } -static void transform_set_scl_filter( - struct dcn10_transform *xfm, +static void dpp_set_scl_filter( + struct dcn10_dpp *xfm, const struct scaler_data *scl_data, bool chroma_coef_mode) { @@ -414,25 +414,25 @@ static void transform_set_scl_filter( uint32_t scl_mode = REG_READ(SCL_MODE); if (!h_2tap_hardcode_coef_en && filter_h) { - transform_set_scaler_filter( + dpp_set_scaler_filter( xfm, scl_data->taps.h_taps, SCL_COEF_LUMA_HORZ_FILTER, filter_h); } xfm->filter_h = filter_h; if (!v_2tap_hardcode_coef_en && filter_v) { - transform_set_scaler_filter( + dpp_set_scaler_filter( xfm, scl_data->taps.v_taps, SCL_COEF_LUMA_VERT_FILTER, filter_v); } xfm->filter_v = filter_v; if (chroma_coef_mode) { if (!h_2tap_hardcode_coef_en && filter_h_c) { - transform_set_scaler_filter( + dpp_set_scaler_filter( xfm, scl_data->taps.h_taps_c, SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); } if (!v_2tap_hardcode_coef_en && filter_v_c) { - transform_set_scaler_filter( + dpp_set_scaler_filter( xfm, scl_data->taps.v_taps_c, SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); } @@ -452,8 +452,8 @@ static void transform_set_scl_filter( } } -static void transform_set_viewport( - struct dcn10_transform *xfm, +static void dpp_set_viewport( + struct dcn10_dpp *xfm, const struct rect *viewport, const struct rect *viewport_c) { @@ -599,30 +599,30 @@ static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl return LB_MEMORY_CONFIG_0; } -void transform_set_scaler_auto_scale( +void dpp_set_scaler_auto_scale( struct transform *xfm_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; - struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - transform_set_overscan(xfm, scl_data); + dpp_set_overscan(xfm, scl_data); - transform_set_otg_blank(xfm, scl_data); + dpp_set_otg_blank(xfm, scl_data); REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); + dpp_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; lb_config = find_lb_memory_config(scl_data); - xfmn10_set_lb(xfm, &scl_data->lb_params, lb_config); + dpp_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -650,19 +650,19 @@ void transform_set_scaler_auto_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - transform_set_scl_filter(xfm, scl_data, ycbcr); + dpp_set_scl_filter(xfm, scl_data, ycbcr); } /* Program gamut remap in bypass mode */ -void transform_set_gamut_remap_bypass(struct dcn10_transform *xfm) +void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) { REG_SET(CM_GAMUT_REMAP_CONTROL, 0, CM_GAMUT_REMAP_MODE, 0); /* Gamut remap in bypass */ } -static void transform_set_recout( - struct dcn10_transform *xfm, const struct rect *recout) +static void dpp_set_recout( + struct dcn10_dpp *xfm, const struct rect *recout) { REG_SET_2(RECOUT_START, 0, /* First pixel of RECOUT */ @@ -679,8 +679,8 @@ static void transform_set_recout( (xfm->base.inst + 1)); } -static void transform_set_manual_ratio_init( - struct dcn10_transform *xfm, const struct scaler_data *data) +static void dpp_set_manual_ratio_init( + struct dcn10_dpp *xfm, const struct scaler_data *data) { uint32_t init_frac = 0; uint32_t init_int = 0; @@ -738,19 +738,19 @@ static void transform_set_manual_ratio_init( } /* Main function to program scaler and line buffer in manual scaling mode */ -static void xfmn10_set_scaler_manual_scale( +static void dpp_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; - struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; /* Recout */ - transform_set_recout(xfm, &scl_data->recout); + dpp_set_recout(xfm, &scl_data->recout); /* MPC Size */ REG_SET_2(MPC_SIZE, 0, @@ -763,13 +763,13 @@ static void xfmn10_set_scaler_manual_scale( REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); /* Viewport */ - transform_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); + dpp_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; /* LB */ lb_config = find_lb_memory_config(scl_data); - xfmn10_set_lb(xfm, &scl_data->lb_params, lb_config); + dpp_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -792,7 +792,7 @@ static void xfmn10_set_scaler_manual_scale( SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); /* Manually calculate scale ratio and init values */ - transform_set_manual_ratio_init(xfm, scl_data); + dpp_set_manual_ratio_init(xfm, scl_data); /* HTaps/VTaps */ REG_SET_4(SCL_TAP_CONTROL, 0, @@ -801,13 +801,13 @@ static void xfmn10_set_scaler_manual_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - transform_set_scl_filter(xfm, scl_data, ycbcr); + dpp_set_scl_filter(xfm, scl_data, ycbcr); } #define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) -static bool transform_get_optimal_number_of_taps( +static bool dpp_get_optimal_number_of_taps( struct transform *xfm, struct scaler_data *scl_data, const struct scaling_taps *in_taps) @@ -866,9 +866,9 @@ static bool transform_get_optimal_number_of_taps( return true; } -static void transform_reset(struct transform *xfm_base) +static void dpp_reset(struct transform *xfm_base) { - struct dcn10_transform *xfm = TO_DCN10_TRANSFORM(xfm_base); + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); xfm->filter_h_c = NULL; xfm->filter_v_c = NULL; @@ -880,7 +880,7 @@ static void transform_reset(struct transform *xfm_base) } static void program_gamut_remap( - struct dcn10_transform *xfm, + struct dcn10_dpp *xfm, const uint16_t *regval, enum gamut_remap_select select) { @@ -989,11 +989,11 @@ static void program_gamut_remap( } -static void dcn_transform_set_gamut_remap( +static void dcn_dpp_set_gamut_remap( struct transform *xfm, const struct xfm_grph_csc_adjustment *adjust) { - struct dcn10_transform *dcn_xfm = TO_DCN10_TRANSFORM(xfm); + struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) /* Bypass if type is bypass or hw */ @@ -1024,30 +1024,29 @@ static void dcn_transform_set_gamut_remap( } } -static struct transform_funcs dcn10_transform_funcs = { - - .transform_reset = transform_reset, - .transform_set_scaler = xfmn10_set_scaler_manual_scale, - .transform_get_optimal_number_of_taps = transform_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn_transform_set_gamut_remap, +static struct transform_funcs dcn10_dpp_funcs = { + .transform_reset = dpp_reset, + .transform_set_scaler = dpp_set_scaler_manual_scale, + .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, + .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, }; /*****************************************/ /* Constructor, Destructor */ /*****************************************/ -bool dcn10_transform_construct( - struct dcn10_transform *xfm, +bool dcn10_dpp_construct( + struct dcn10_dpp *xfm, struct dc_context *ctx, uint32_t inst, - const struct dcn_transform_registers *tf_regs, - const struct dcn_transform_shift *tf_shift, - const struct dcn_transform_mask *tf_mask) + const struct dcn_dpp_registers *tf_regs, + const struct dcn_dpp_shift *tf_shift, + const struct dcn_dpp_mask *tf_mask) { xfm->base.ctx = ctx; xfm->base.inst = inst; - xfm->base.funcs = &dcn10_transform_funcs; + xfm->base.funcs = &dcn10_dpp_funcs; xfm->tf_regs = tf_regs; xfm->tf_shift = tf_shift; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h similarity index 96% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h rename to drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 8df74cc153f5..993643552aff 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -22,13 +22,13 @@ * */ -#ifndef __DAL_TRANSFORM_DCN10_H__ -#define __DAL_TRANSFORM_DCN10_H__ +#ifndef __DAL_DPP_DCN10_H__ +#define __DAL_DPP_DCN10_H__ #include "transform.h" -#define TO_DCN10_TRANSFORM(transform)\ - container_of(transform, struct dcn10_transform, base) +#define TO_DCN10_DPP(transform)\ + container_of(transform, struct dcn10_dpp, base) /* TODO: Use correct number of taps. Using polaris values for now */ #define LB_TOTAL_NUMBER_OF_ENTRIES 5124 @@ -332,15 +332,15 @@ type CM_COMB_C33; \ type CM_COMB_C34 -struct dcn_transform_shift { +struct dcn_dpp_shift { TF_REG_FIELD_LIST(uint8_t); }; -struct dcn_transform_mask { +struct dcn_dpp_mask { TF_REG_FIELD_LIST(uint32_t); }; -struct dcn_transform_registers { +struct dcn_dpp_registers { uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; uint32_t OTG_H_BLANK; @@ -395,12 +395,12 @@ struct dcn_transform_registers { uint32_t CM_COMB_C33_C34; }; -struct dcn10_transform { +struct dcn10_dpp { struct transform base; - const struct dcn_transform_registers *tf_regs; - const struct dcn_transform_shift *tf_shift; - const struct dcn_transform_mask *tf_mask; + const struct dcn_dpp_registers *tf_regs; + const struct dcn_dpp_shift *tf_shift; + const struct dcn_dpp_mask *tf_mask; const uint16_t *filter_v; const uint16_t *filter_h; @@ -410,12 +410,10 @@ struct dcn10_transform { int lb_memory_size; int lb_bits_per_entry; }; - -bool dcn10_transform_construct(struct dcn10_transform *xfmn10, +bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, uint32_t inst, - const struct dcn_transform_registers *tf_regs, - const struct dcn_transform_shift *tf_shift, - const struct dcn_transform_mask *tf_mask); - + const struct dcn_dpp_registers *tf_regs, + const struct dcn_dpp_shift *tf_shift, + const struct dcn_dpp_mask *tf_mask); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index dbf9cea2e418..fc46c84aea67 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -33,6 +33,8 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" +#include "dcn10/dcn10_dpp.h" +#include "dcn10/dcn10_mpc.h" #include "mem_input.h" #include "timing_generator.h" #include "opp.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 75ad37e81738..4a996f9ae468 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -33,7 +33,7 @@ #include "dcn10/dcn10_ipp.h" #include "dcn10/dcn10_mpc.h" #include "irq/dcn10/irq_service_dcn10.h" -#include "dcn10/dcn10_transform.h" +#include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_timing_generator.h" #include "dcn10/dcn10_hw_sequencer.h" #include "dce110/dce110_hw_sequencer.h" @@ -309,18 +309,18 @@ static const struct dcn10_opp_mask opp_mask = { TF_REG_LIST_DCN10(id),\ } -static const struct dcn_transform_registers tf_regs[] = { +static const struct dcn_dpp_registers tf_regs[] = { tf_regs(0), tf_regs(1), tf_regs(2), tf_regs(3), }; -static const struct dcn_transform_shift tf_shift = { +static const struct dcn_dpp_shift tf_shift = { TF_REG_LIST_SH_MASK_DCN10(__SHIFT) }; -static const struct dcn_transform_mask tf_mask = { +static const struct dcn_dpp_mask tf_mask = { TF_REG_LIST_SH_MASK_DCN10(_MASK), }; @@ -449,28 +449,28 @@ static const struct dc_debug debug_defaults_diags = { #endif }; -static void dcn10_transform_destroy(struct transform **xfm) +static void dcn10_dpp_destroy(struct transform **xfm) { - dm_free(TO_DCN10_TRANSFORM(*xfm)); + dm_free(TO_DCN10_DPP(*xfm)); *xfm = NULL; } -static struct transform *dcn10_transform_create( +static struct transform *dcn10_dpp_create( struct dc_context *ctx, uint32_t inst) { - struct dcn10_transform *transform = - dm_alloc(sizeof(struct dcn10_transform)); + struct dcn10_dpp *dpp = + dm_alloc(sizeof(struct dcn10_dpp)); - if (!transform) + if (!dpp) return NULL; - if (dcn10_transform_construct(transform, ctx, inst, + if (dcn10_dpp_construct(dpp, ctx, inst, &tf_regs[inst], &tf_shift, &tf_mask)) - return &transform->base; + return &dpp->base; BREAK_TO_DEBUGGER(); - dm_free(transform); + dm_free(dpp); return NULL; } @@ -710,7 +710,7 @@ static void destruct(struct dcn10_resource_pool *pool) pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); if (pool->base.transforms[i] != NULL) - dcn10_transform_destroy(&pool->base.transforms[i]); + dcn10_dpp_destroy(&pool->base.transforms[i]); if (pool->base.ipps[i] != NULL) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); @@ -1387,7 +1387,7 @@ static bool construct( #endif } - /* mem input -> ipp -> transform -> opp -> TG */ + /* mem input -> ipp -> dpp -> opp -> TG */ for (i = 0; i < pool->base.pipe_count; i++) { pool->base.mis[i] = dcn10_mem_input_create(ctx, i); if (pool->base.mis[i] == NULL) { @@ -1405,12 +1405,12 @@ static bool construct( goto ipp_create_fail; } - pool->base.transforms[i] = dcn10_transform_create(ctx, i); + pool->base.transforms[i] = dcn10_dpp_create(ctx, i); if (pool->base.transforms[i] == NULL) { BREAK_TO_DEBUGGER(); dm_error( - "DC: failed to create transform!\n"); - goto transform_create_fail; + "DC: failed to create dpp!\n"); + goto dpp_create_fail; } pool->base.opps[i] = dcn10_opp_create(ctx, i); @@ -1452,7 +1452,7 @@ static bool construct( mpcc_create_fail: otg_create_fail: opp_create_fail: -transform_create_fail: +dpp_create_fail: ipp_create_fail: mi_create_fail: irqs_create_fail: -- GitLab From 60bf1860d29f4f459e8b195dc73fcb2d980500d0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 13 Jul 2017 10:52:47 -0400 Subject: [PATCH 0637/2898] drm/amd/display: Preserve refcount for S3 case. Curent_context is zerroed out for suspend, keep the refcount. Minor code move in dc_commit_context_no_check Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8e580ac91b2a..20f41991f94d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -977,10 +977,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_release_validate_context(core_dc->current_context); - dc_retain_validate_context(context); - core_dc->current_context = context; + dc_retain_validate_context(core_dc->current_context); + return (result == DC_OK); } @@ -1065,8 +1065,6 @@ bool dc_commit_streams( result = dc_commit_context_no_check(dc, context); - return (result == DC_OK); - fail: dc_release_validate_context(context); @@ -1736,6 +1734,7 @@ void dc_set_power_state( enum dc_acpi_cm_power_state power_state) { struct core_dc *core_dc = DC_TO_CORE(dc); + int ref_count; switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: @@ -1749,8 +1748,13 @@ void dc_set_power_state( * clean state, and dc hw programming optimizations will not * cause any trouble. */ + + /* Preserve refcount */ + ref_count = core_dc->current_context->ref_count; + dc_resource_validate_ctx_destruct(core_dc->current_context); memset(core_dc->current_context, 0, sizeof(*core_dc->current_context)); + core_dc->current_context->ref_count = ref_count; break; } -- GitLab From 0a214e2fb6b0a56519b6d5efab4b21475c233ee0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 13 Jul 2017 10:56:48 -0400 Subject: [PATCH 0638/2898] drm/amd/display: Release cached atomic state in S3. Fixes memory leak. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e16e87173db3..a41d271f21a3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -508,6 +508,7 @@ static int dm_suspend(void *handle) amdgpu_dm_irq_suspend(adev); + WARN_ON(adev->dm.cached_state); adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); dc_set_power_state( @@ -607,6 +608,9 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); + drm_atomic_state_put(adev->dm.cached_state); + adev->dm.cached_state = NULL; + amdgpu_dm_irq_resume_late(adev); return ret; -- GitLab From daf6b57dd736ec93b2e1769b90514b015feed3c1 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 11 Jul 2017 13:48:17 -0400 Subject: [PATCH 0639/2898] drm/amd/display: add line number to reg_wait timeout print Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dm_services.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/reg_helper.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 8ed1440d2b01..87b7f6f8870e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -129,7 +129,7 @@ uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value, unsigned int delay_between_poll_us, unsigned int time_out_num_tries, - const char *func_name) + const char *func_name, int line) { uint32_t field_value; uint32_t reg_val; @@ -158,8 +158,8 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, return reg_val; } - dm_error("REG_WAIT timeout %dus * %d tries - %s\n", - delay_between_poll_us, time_out_num_tries, func_name); + dm_error("REG_WAIT timeout %dus * %d tries - %s line:%d\n", + delay_between_poll_us, time_out_num_tries, func_name, line); if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index fb61e333aefd..ea494a71a80b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -194,7 +194,7 @@ uint32_t generic_reg_update_ex(const struct dc_context *ctx, unsigned int generic_reg_wait(const struct dc_context *ctx, uint32_t addr, uint32_t mask, uint32_t shift, uint32_t condition_value, unsigned int delay_between_poll_us, unsigned int time_out_num_tries, - const char *func_name); + const char *func_name, int line); /* These macros need to be used with soc15 registers in order to retrieve diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index 1828d288c6bc..77eb72874e90 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -188,7 +188,7 @@ #define REG_WAIT(reg_name, field, val, delay_between_poll_us, max_try) \ generic_reg_wait(CTX, \ REG(reg_name), FN(reg_name, field), val,\ - delay_between_poll_us, max_try, __func__) + delay_between_poll_us, max_try, __func__, __LINE__) /* macro to update (read, modify, write) register fields */ -- GitLab From b02c3b055fe27cb37969c68cd81db767a16af43b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 7 Jul 2017 17:21:45 -0400 Subject: [PATCH 0640/2898] drm/amd/display: hwseq init sequence update Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 8 ++- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 51 +++++-------------- .../amd/display/dc/dcn10/dcn10_hw_sequencer.h | 2 +- .../amd/display/dc/dcn10/dcn10_mem_input.c | 1 - 4 files changed, 20 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 4da9142351fa..7e1d46fdcc76 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -216,6 +216,11 @@ struct dce_hwseq_registers { uint32_t DCCG_GATE_DISABLE_CNTL; uint32_t DCCG_GATE_DISABLE_CNTL2; uint32_t DCFCLK_CNTL; + uint32_t MICROSECOND_TIME_BASE_DIV; + uint32_t MILLISECOND_TIME_BASE_DIV; + uint32_t DISPCLK_FREQ_CHANGE_CNTL; + uint32_t RBBMIF_TIMEOUT_DIS; + uint32_t RBBMIF_TIMEOUT_DIS_2; #endif }; /* set field name */ @@ -378,7 +383,8 @@ struct dce_hwseq_registers { type DOMAIN5_PGFSM_PWR_STATUS; \ type DOMAIN6_PGFSM_PWR_STATUS; \ type DOMAIN7_PGFSM_PWR_STATUS; \ - type DCFCLK_GATE_DIS; + type DCFCLK_GATE_DIS; \ + type DCHUBBUB_GLOBAL_TIMER_REFDIV; #endif struct dce_hwseq_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index fc46c84aea67..eca0d53eedff 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -24,11 +24,9 @@ */ #include "dm_services.h" -#include "dc.h" -#include "core_dc.h" #include "core_types.h" -#include "core_status.h" #include "resource.h" +#include "custom_float.h" #include "dcn10_hw_sequencer.h" #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" @@ -39,11 +37,10 @@ #include "timing_generator.h" #include "opp.h" #include "ipp.h" -#include "dc_bios_types.h" +#include "mpc.h" #include "raven1/DCN/dcn_1_0_offset.h" #include "raven1/DCN/dcn_1_0_sh_mask.h" #include "vega10/soc15ip.h" -#include "custom_float.h" #include "reg_helper.h" #define CTX \ @@ -219,31 +216,15 @@ static void bios_golden_init(struct core_dc *dc) } } -/* - * This should be done within BIOS, we are doing it for maximus only - */ -static void dchubup_setup_timer(struct dce_hwseq *hws) -{ - REG_WRITE(REFCLK_CNTL, 0); - - REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); -} - -static void init_hw(struct core_dc *dc) +static void dcn10_init_hw(struct core_dc *dc) { int i; - struct transform *xfm; - struct abm *abm; + struct abm *abm = dc->res_pool->abm; struct dce_hwseq *hws = dc->hwseq; -#if 1 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - dchubup_setup_timer(dc->hwseq); - - /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface - * between dc and kmd - */ - /*dchubp_map_fb_to_mc(dc->hwseq);*/ + REG_WRITE(REFCLK_CNTL, 0); + REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); REG_WRITE(DIO_MEM_PWR_CTRL, 0); if (!dc->public.debug.disable_clock_gate) { @@ -259,15 +240,9 @@ static void init_hw(struct core_dc *dc) return; } /* end of FPGA. Below if real ASIC */ -#endif bios_golden_init(dc); - for (i = 0; i < dc->res_pool->pipe_count; i++) { - xfm = dc->res_pool->transforms[i]; - xfm->funcs->transform_reset(xfm); - } - for (i = 0; i < dc->link_count; i++) { /* Power up AND update implementation according to the * required signal (which may be different from the @@ -279,12 +254,12 @@ static void init_hw(struct core_dc *dc) } for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct timing_generator *tg = - dc->res_pool->timing_generators[i]; - struct mpcc *mpcc = - dc->res_pool->mpcc[i]; + struct transform *xfm = dc->res_pool->transforms[i]; + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + struct mpcc *mpcc = dc->res_pool->mpcc[i]; struct mpcc_cfg mpcc_cfg; + xfm->funcs->transform_reset(xfm); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; @@ -305,7 +280,6 @@ static void init_hw(struct core_dc *dc) audio->funcs->hw_init(audio); } - abm = dc->res_pool->abm; if (abm != NULL) { abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); @@ -1859,7 +1833,7 @@ static bool dcn10_dummy_display_power_gating( static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .program_csc_matrix = program_csc_matrix, - .init_hw = init_hw, + .init_hw = dcn10_init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .set_plane_config = set_plane_config, @@ -1888,9 +1862,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { }; -bool dcn10_hw_sequencer_construct(struct core_dc *dc) +void dcn10_hw_sequencer_construct(struct core_dc *dc) { dc->hwss = dcn10_funcs; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index c3aff2eb8d68..28218dc43522 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -30,7 +30,7 @@ struct core_dc; -bool dcn10_hw_sequencer_construct(struct core_dc *dc); +void dcn10_hw_sequencer_construct(struct core_dc *dc); extern void fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index b7ecfad4a8f2..4e723a017b97 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -403,7 +403,6 @@ static void min10_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); REG_UPDATE(HUBPRET_CONTROL, -- GitLab From 4bd3ae5fb5156eb47b4d7f4f12d8467d9c4a8623 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Thu, 13 Jul 2017 15:42:58 -0500 Subject: [PATCH 0641/2898] drm/amd/display: Move view port registers and programming to memory input. Signed-off-by: Vitaly Prosyak Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 36 ------------------ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 36 ------------------ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 + .../amd/display/dc/dcn10/dcn10_mem_input.c | 37 ++++++++++++++++++- .../amd/display/dc/dcn10/dcn10_mem_input.h | 36 ++++++++++++++++++ .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 ++ 6 files changed, 78 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 85d3ca31daf5..fff81a14b21c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -452,37 +452,6 @@ static void dpp_set_scl_filter( } } -static void dpp_set_viewport( - struct dcn10_dpp *xfm, - const struct rect *viewport, - const struct rect *viewport_c) -{ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, - PRI_VIEWPORT_WIDTH, viewport->width, - PRI_VIEWPORT_HEIGHT, viewport->height); - - REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, - PRI_VIEWPORT_X_START, viewport->x, - PRI_VIEWPORT_Y_START, viewport->y); - - /*for stereo*/ - REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, - SEC_VIEWPORT_WIDTH, viewport->width, - SEC_VIEWPORT_HEIGHT, viewport->height); - - REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, - SEC_VIEWPORT_X_START, viewport->x, - SEC_VIEWPORT_Y_START, viewport->y); - - /* DC supports NV12 only at the moment */ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, - PRI_VIEWPORT_WIDTH_C, viewport_c->width, - PRI_VIEWPORT_HEIGHT_C, viewport_c->height); - - REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, - PRI_VIEWPORT_X_START_C, viewport_c->x, - PRI_VIEWPORT_Y_START_C, viewport_c->y); -} static int get_lb_depth_bpc(enum lb_pixel_depth depth) { @@ -616,8 +585,6 @@ void dpp_set_scaler_auto_scale( REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - dpp_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; @@ -762,9 +729,6 @@ static void dpp_set_scaler_manual_scale( /* SCL mode */ REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - /* Viewport */ - dpp_set_viewport(xfm, &scl_data->viewport, &scl_data->viewport_c); - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; /* LB */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 993643552aff..c1124e962d0e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -59,12 +59,6 @@ SRI(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ SRI(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ SRI(DSCL_2TAP_CONTROL, DSCL, id), \ - SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ - SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ - SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ - SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ SRI(MPC_SIZE, DSCL, id), \ SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ @@ -144,18 +138,6 @@ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ - TF_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ @@ -257,18 +239,6 @@ type SCL_V_2TAP_SHARP_EN; \ type SCL_V_2TAP_SHARP_FACTOR; \ type SCL_COEF_RAM_SELECT; \ - type PRI_VIEWPORT_WIDTH; \ - type PRI_VIEWPORT_HEIGHT; \ - type PRI_VIEWPORT_X_START; \ - type PRI_VIEWPORT_Y_START; \ - type SEC_VIEWPORT_WIDTH; \ - type SEC_VIEWPORT_HEIGHT; \ - type SEC_VIEWPORT_X_START; \ - type SEC_VIEWPORT_Y_START; \ - type PRI_VIEWPORT_WIDTH_C; \ - type PRI_VIEWPORT_HEIGHT_C; \ - type PRI_VIEWPORT_X_START_C; \ - type PRI_VIEWPORT_Y_START_C; \ type DSCL_MODE; \ type RECOUT_START_X; \ type RECOUT_START_Y; \ @@ -355,12 +325,6 @@ struct dcn_dpp_registers { uint32_t SCL_COEF_RAM_TAP_SELECT; uint32_t SCL_COEF_RAM_TAP_DATA; uint32_t DSCL_2TAP_CONTROL; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; - uint32_t DCSURF_PRI_VIEWPORT_START; - uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; - uint32_t DCSURF_SEC_VIEWPORT_START; - uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; - uint32_t DCSURF_PRI_VIEWPORT_START_C; uint32_t MPC_SIZE; uint32_t SCL_HORZ_FILTER_SCALE_RATIO; uint32_t SCL_VERT_FILTER_SCALE_RATIO; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index eca0d53eedff..d714422ef979 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1470,6 +1470,8 @@ static void update_dchubp_dpp( /* scaler configuration */ pipe_ctx->xfm->funcs->transform_set_scaler( pipe_ctx->xfm, &pipe_ctx->scl_data); + mi->funcs->mem_program_viewport(mi, + &pipe_ctx->scl_data.viewport, &pipe_ctx->scl_data.viewport_c); /*gamut remap*/ program_gamut_remap(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 4e723a017b97..efa02d160d1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -1057,6 +1057,41 @@ static void min10_program_pte_vm(struct mem_input *mem_input, SYSTEM_ACCESS_MODE, 3); } +static void min_set_viewport( + struct mem_input *mem_input, + const struct rect *viewport, + const struct rect *viewport_c) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, + PRI_VIEWPORT_WIDTH, viewport->width, + PRI_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, + PRI_VIEWPORT_X_START, viewport->x, + PRI_VIEWPORT_Y_START, viewport->y); + + /*for stereo*/ + REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, + SEC_VIEWPORT_WIDTH, viewport->width, + SEC_VIEWPORT_HEIGHT, viewport->height); + + REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, + SEC_VIEWPORT_X_START, viewport->x, + SEC_VIEWPORT_Y_START, viewport->y); + + /* DC supports NV12 only at the moment */ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, + PRI_VIEWPORT_WIDTH_C, viewport_c->width, + PRI_VIEWPORT_HEIGHT_C, viewport_c->height); + + REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, + PRI_VIEWPORT_X_START_C, viewport_c->x, + PRI_VIEWPORT_Y_START_C, viewport_c->y); +} + + static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_display_marks = min10_program_display_marks, .mem_input_program_surface_flip_and_addr = @@ -1070,9 +1105,9 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_pte_vm = min10_program_pte_vm, .set_blank = min10_set_blank, .dcc_control = min10_dcc_control, + .mem_program_viewport = min_set_viewport, }; - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index c3f18bdc2157..7efa857b8710 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -40,6 +40,12 @@ SRI(DCSURF_SURFACE_PITCH_C, HUBPREQ, id),\ SRI(DCSURF_SURFACE_CONFIG, HUBP, id),\ SRI(DCSURF_FLIP_CONTROL, HUBPREQ, id),\ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ + SRI(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ SRI(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ SRI(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id),\ SRI(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id),\ @@ -164,6 +170,12 @@ struct dcn_mi_registers { uint32_t DCSURF_SURFACE_PITCH_C; uint32_t DCSURF_SURFACE_CONFIG; uint32_t DCSURF_FLIP_CONTROL; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION; + uint32_t DCSURF_PRI_VIEWPORT_START; + uint32_t DCSURF_SEC_VIEWPORT_DIMENSION; + uint32_t DCSURF_SEC_VIEWPORT_START; + uint32_t DCSURF_PRI_VIEWPORT_DIMENSION_C; + uint32_t DCSURF_PRI_VIEWPORT_START_C; uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH; uint32_t DCSURF_PRIMARY_SURFACE_ADDRESS; uint32_t DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH; @@ -312,6 +324,18 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ + MI_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ @@ -459,6 +483,18 @@ struct dcn_mi_registers { type SURFACE_FLIP_TYPE;\ type SURFACE_UPDATE_LOCK;\ type SURFACE_FLIP_PENDING;\ + type PRI_VIEWPORT_WIDTH; \ + type PRI_VIEWPORT_HEIGHT; \ + type PRI_VIEWPORT_X_START; \ + type PRI_VIEWPORT_Y_START; \ + type SEC_VIEWPORT_WIDTH; \ + type SEC_VIEWPORT_HEIGHT; \ + type SEC_VIEWPORT_X_START; \ + type SEC_VIEWPORT_Y_START; \ + type PRI_VIEWPORT_WIDTH_C; \ + type PRI_VIEWPORT_HEIGHT_C; \ + type PRI_VIEWPORT_X_START_C; \ + type PRI_VIEWPORT_Y_START_C; \ type PRIMARY_SURFACE_ADDRESS_HIGH;\ type PRIMARY_SURFACE_ADDRESS;\ type SECONDARY_SURFACE_ADDRESS_HIGH;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 64b810d48d07..1b7d151a66f8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -89,6 +89,10 @@ struct mem_input_funcs { void (*dcc_control)(struct mem_input *mem_input, bool enable, bool independent_64b_blks); + void (*mem_program_viewport)( + struct mem_input *mem_input, + const struct rect *viewport, + const struct rect *viewport_c); #endif void (*mem_input_program_display_marks)( -- GitLab From 90114434772321881c8d11133b634e710e4e1f06 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 13 Jul 2017 16:27:08 -0400 Subject: [PATCH 0642/2898] drm/amd/display: Fix S3 gamma corruption. On S3 resume gamma is corrupted since no gamma programming took place. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 20f41991f94d..eda36c7a5c57 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1120,11 +1120,13 @@ bool dc_commit_surfaces_to_stream( stream_update->src = dc_stream->src; stream_update->dst = dc_stream->dst; + stream_update->out_transfer_func = dc_stream->out_transfer_func; for (i = 0; i < new_surface_count; i++) { updates[i].surface = new_surfaces[i]; updates[i].gamma = (struct dc_gamma *)new_surfaces[i]->gamma_correction; + updates[i].in_transfer_func = new_surfaces[i]->in_transfer_func; flip_addr[i].address = new_surfaces[i]->address; flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; plane_info[i].color_space = new_surfaces[i]->color_space; -- GitLab From 820e3935489c85d7dc3024eec709b016ba75b376 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Thu, 13 Jul 2017 12:09:57 -0400 Subject: [PATCH 0643/2898] drm/amd/display: link training fallback actions Signed-off-by: Ding Wang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 239 +++++++++++++++--- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 8 + .../amd/display/include/link_service_types.h | 9 + 4 files changed, 215 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 98048fe6239e..dd3f57fce834 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -731,7 +731,7 @@ static enum hw_dp_training_pattern get_supported_tp(struct core_link *link) return HW_DP_TRAINING_PATTERN_2; } -static bool perform_channel_equalization_sequence( +static enum link_training_result perform_channel_equalization_sequence( struct core_link *link, struct link_training_settings *lt_settings) { @@ -777,19 +777,19 @@ static bool perform_channel_equalization_sequence( /* 5. check CR done*/ if (!is_cr_done(lane_count, dpcd_lane_status)) - return false; + return LINK_TRAINING_EQ_FAIL_CR; /* 6. check CHEQ done*/ if (is_ch_eq_done(lane_count, dpcd_lane_status, &dpcd_lane_status_updated)) - return true; + return LINK_TRAINING_SUCCESS; /* 7. update VS/PE/PC2 in lt_settings*/ update_drive_settings(lt_settings, req_settings); } - return false; + return LINK_TRAINING_EQ_FAIL_EQ; } @@ -943,18 +943,17 @@ static inline bool perform_link_training_int( return status; } -bool dc_link_dp_perform_link_training( +enum link_training_result dc_link_dp_perform_link_training( struct dc_link *link, const struct dc_link_settings *link_setting, bool skip_video_pattern) { + enum link_training_result status = LINK_TRAINING_SUCCESS; struct core_link *core_link = DC_LINK_TO_CORE(link); - bool status; char *link_rate = "Unknown"; struct link_training_settings lt_settings; - status = false; memset(<_settings, '\0', sizeof(lt_settings)); lt_settings.link_settings.link_rate = link_setting->link_rate; @@ -976,16 +975,23 @@ bool dc_link_dp_perform_link_training( /* 2. perform link training (set link training done * to false is done as well)*/ - if (perform_clock_recovery_sequence(core_link, <_settings)) { - - if (perform_channel_equalization_sequence(core_link, - <_settings)) - status = true; + if (!perform_clock_recovery_sequence(core_link, <_settings)) { + status = LINK_TRAINING_CR_FAIL; + } else { + status = perform_channel_equalization_sequence(core_link, + <_settings); } - if (status || !skip_video_pattern) - status = perform_link_training_int(core_link, - <_settings, status); + if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) { + if (!perform_link_training_int(core_link, + <_settings, + status == LINK_TRAINING_SUCCESS)) { + /* the next link training setting in this case + * would be the same as CR failure case. + */ + status = LINK_TRAINING_CR_FAIL; + } + } /* 6. print status message*/ switch (lt_settings.link_settings.link_rate) { @@ -1013,7 +1019,9 @@ bool dc_link_dp_perform_link_training( CONN_MSG_LT(core_link, "%sx%d %s VS=%d, PE=%d", link_rate, lt_settings.link_settings.lane_count, - status ? "pass" : "fail", + (status == LINK_TRAINING_SUCCESS) ? "pass" : + ((status == LINK_TRAINING_CR_FAIL) ? "CR failed" : + "EQ failed"), lt_settings.lane_settings[0].VOLTAGE_SWING, lt_settings.lane_settings[0].PRE_EMPHASIS); @@ -1035,7 +1043,7 @@ bool perform_link_training_with_retries( if (dc_link_dp_perform_link_training( &link->public, link_setting, - skip_video_pattern)) + skip_video_pattern) == LINK_TRAINING_SUCCESS) return true; msleep(delay_between_attempts); @@ -1068,15 +1076,6 @@ static const struct dc_link_settings *get_link_training_fallback_table( return &link_training_fallback_table[i]; } -static bool exceeded_limit_link_setting( - const struct dc_link_settings *link_setting, - const struct dc_link_settings *limit_link_setting) -{ - return (link_setting->lane_count * link_setting->link_rate - > limit_link_setting->lane_count * limit_link_setting->link_rate ? - true : false); -} - static struct dc_link_settings get_max_link_cap(struct core_link *link) { /* Set Default link settings */ @@ -1109,13 +1108,15 @@ bool dp_hbr_verify_link_cap( struct dc_link_settings *known_limit_link_setting) { struct dc_link_settings max_link_cap = {0}; + struct dc_link_settings cur_link_setting = {0}; + struct dc_link_settings *cur = &cur_link_setting; + struct dc_link_settings initial_link_settings = {0}; bool success; bool skip_link_training; - const struct dc_link_settings *cur; bool skip_video_pattern; - uint32_t i; struct clock_source *dp_cs; enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL; + enum link_training_result status; success = false; skip_link_training = false; @@ -1142,19 +1143,16 @@ bool dp_hbr_verify_link_cap( ASSERT(dp_cs); } - for (i = 0; i < get_link_training_fallback_table_len(link) && - !success; i++) { - cur = get_link_training_fallback_table(link, i); - - if (known_limit_link_setting->lane_count != LANE_COUNT_UNKNOWN && - exceeded_limit_link_setting(cur, - known_limit_link_setting)) - continue; - - if (!is_link_setting_supported(cur, &max_link_cap)) - continue; - + /* link training starts with the maximum common settings + * supported by both sink and ASIC. + */ + initial_link_settings = get_common_supported_link_settings( + *known_limit_link_setting, + max_link_cap); + cur_link_setting = initial_link_settings; + do { skip_video_pattern = true; + if (cur->link_rate == LINK_RATE_LOW) skip_video_pattern = false; @@ -1167,10 +1165,12 @@ bool dp_hbr_verify_link_cap( if (skip_link_training) success = true; else { - success = dc_link_dp_perform_link_training( + status = dc_link_dp_perform_link_training( &link->public, cur, skip_video_pattern); + if (status == LINK_TRAINING_SUCCESS) + success = true; } if (success) @@ -1181,7 +1181,8 @@ bool dp_hbr_verify_link_cap( * based on the actual mode we're driving */ dp_disable_link_phy(link, link->public.connector_signal); - } + } while (!success && decide_fallback_link_setting( + initial_link_settings, cur, status)); /* Link Training failed for all Link Settings * (Lane Count is still unknown) @@ -1202,6 +1203,160 @@ bool dp_hbr_verify_link_cap( return success; } +struct dc_link_settings get_common_supported_link_settings ( + struct dc_link_settings link_setting_a, + struct dc_link_settings link_setting_b) +{ + struct dc_link_settings link_settings = {0}; + + link_settings.lane_count = + (link_setting_a.lane_count <= + link_setting_b.lane_count) ? + link_setting_a.lane_count : + link_setting_b.lane_count; + link_settings.link_rate = + (link_setting_a.link_rate <= + link_setting_b.link_rate) ? + link_setting_a.link_rate : + link_setting_b.link_rate; + link_settings.link_spread = LINK_SPREAD_DISABLED; + + /* in DP compliance test, DPR-120 may have + * a random value in its MAX_LINK_BW dpcd field. + * We map it to the maximum supported link rate that + * is smaller than MAX_LINK_BW in this case. + */ + if (link_settings.link_rate > LINK_RATE_HIGH3) { + link_settings.link_rate = LINK_RATE_HIGH3; + } else if (link_settings.link_rate < LINK_RATE_HIGH3 + && link_settings.link_rate > LINK_RATE_HIGH2) { + link_settings.link_rate = LINK_RATE_HIGH2; + } else if (link_settings.link_rate < LINK_RATE_HIGH2 + && link_settings.link_rate > LINK_RATE_HIGH) { + link_settings.link_rate = LINK_RATE_HIGH; + } else if (link_settings.link_rate < LINK_RATE_HIGH + && link_settings.link_rate > LINK_RATE_LOW) { + link_settings.link_rate = LINK_RATE_LOW; + } else if (link_settings.link_rate < LINK_RATE_LOW) { + link_settings.link_rate = LINK_RATE_UNKNOWN; + } + + return link_settings; +} + +bool reached_minimum_lane_count(enum dc_lane_count lane_count) +{ + return lane_count <= LANE_COUNT_ONE; +} + +bool reached_minimum_link_rate(enum dc_link_rate link_rate) +{ + return link_rate <= LINK_RATE_LOW; +} + +enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) +{ + switch (lane_count) { + case LANE_COUNT_FOUR: + return LANE_COUNT_TWO; + case LANE_COUNT_TWO: + return LANE_COUNT_ONE; + case LANE_COUNT_ONE: + return LANE_COUNT_UNKNOWN; + default: + return LANE_COUNT_UNKNOWN; + } +} + +enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) +{ + switch (link_rate) { + case LINK_RATE_HIGH3: + return LINK_RATE_HIGH2; + case LINK_RATE_HIGH2: + return LINK_RATE_HIGH; + case LINK_RATE_HIGH: + return LINK_RATE_LOW; + case LINK_RATE_LOW: + return LINK_RATE_UNKNOWN; + default: + return LINK_RATE_UNKNOWN; + } +} + +/* + * function: set link rate and lane count fallback based + * on current link setting and last link training result + * return value: + * true - link setting could be set + * false - has reached minimum setting + * and no further fallback could be done + */ +bool decide_fallback_link_setting( + struct dc_link_settings initial_link_settings, + struct dc_link_settings *current_link_setting, + enum link_training_result training_result) +{ + if (!current_link_setting) + return false; + + switch (training_result) { + case LINK_TRAINING_CR_FAIL: + { + if (!reached_minimum_link_rate + (current_link_setting->link_rate)) { + current_link_setting->link_rate = + reduce_link_rate( + current_link_setting->link_rate); + } else if (!reached_minimum_lane_count + (current_link_setting->lane_count)) { + current_link_setting->link_rate = + initial_link_settings.link_rate; + current_link_setting->lane_count = + reduce_lane_count( + current_link_setting->lane_count); + } else { + return false; + } + break; + } + case LINK_TRAINING_EQ_FAIL_EQ: + { + if (!reached_minimum_lane_count + (current_link_setting->lane_count)) { + current_link_setting->lane_count = + reduce_lane_count( + current_link_setting->lane_count); + } else if (!reached_minimum_link_rate + (current_link_setting->link_rate)) { + current_link_setting->lane_count = + initial_link_settings.lane_count; + current_link_setting->link_rate = + reduce_link_rate( + current_link_setting->link_rate); + } else { + return false; + } + break; + } + case LINK_TRAINING_EQ_FAIL_CR: + { + if (!reached_minimum_link_rate + (current_link_setting->link_rate)) { + current_link_setting->link_rate = + reduce_link_rate( + current_link_setting->link_rate); + } else { + return false; + } + break; + } + default: + return false; + } + return true; +} + static uint32_t bandwidth_in_kbps_from_timing( const struct dc_crtc_timing *timing) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cd8981469fe9..6a22c91cbcef 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -777,7 +777,7 @@ void dc_link_dp_set_drive_settings( const struct dc_link *link, struct link_training_settings *lt_settings); -bool dc_link_dp_perform_link_training( +enum link_training_result dc_link_dp_perform_link_training( struct dc_link *link, const struct dc_link_settings *link_setting, bool skip_video_pattern); diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 92c56e6f7588..b6ef1bfd267c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -37,6 +37,14 @@ bool dp_hbr_verify_link_cap( struct core_link *link, struct dc_link_settings *known_limit_link_setting); +bool decide_fallback_link_setting(struct dc_link_settings link_setting_init, + struct dc_link_settings *link_setting_current, + enum link_training_result training_result); + +struct dc_link_settings get_common_supported_link_settings ( + struct dc_link_settings link_setting_a, + struct dc_link_settings link_setting_b); + bool dp_validate_mode_timing( struct core_link *link, const struct dc_crtc_timing *timing); diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index fe8b5144e03f..adea1a59f620 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -56,6 +56,15 @@ enum { LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/ }; +enum link_training_result { + LINK_TRAINING_SUCCESS, + LINK_TRAINING_CR_FAIL, + /* CR DONE bit is cleared during EQ step */ + LINK_TRAINING_EQ_FAIL_CR, + /* other failure during EQ step */ + LINK_TRAINING_EQ_FAIL_EQ, +}; + struct link_training_settings { struct dc_link_settings link_settings; struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]; -- GitLab From 83572340097012c91de3f96e52797491c79cfe43 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 17 Jul 2017 17:46:49 -0400 Subject: [PATCH 0644/2898] drm/amd/display: fix DVI connected to HDMI connector max tmds clock Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 812c29982a2e..5663d3dbd7d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -830,6 +830,12 @@ bool dce110_link_encoder_validate_dvi_output( if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB) return false; + /*connect DVI via adpater's HDMI connector*/ + if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK || + connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) && + signal != SIGNAL_TYPE_HDMI_TYPE_A && + crtc_timing->pix_clk_khz > TMDS_MAX_PIXEL_CLOCK) + return false; if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK) return false; -- GitLab From 1674d35bf57b0546577b87af266e45de3ccf45c0 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 17 Jul 2017 10:22:05 -0400 Subject: [PATCH 0645/2898] drm/amd/display: properly turn off unused mpc before front end programming MPCC_OPP_ID must be programmed to 0xf to properly turn off the mpcc. However the software state of the mpcc must keep track of the opp that the mpcc is attached to for reset to properly happen. This is kinda hacky right now, but a good solution may involve a lot of work. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d714422ef979..cadc940e7c0e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1572,17 +1572,24 @@ static void dcn10_apply_ctx_for_surface( if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { struct mpcc_cfg mpcc_cfg; + int opp_id_cached = old_pipe_ctx->mpcc->opp_id; if (!old_pipe_ctx->top_pipe) { ASSERT(0); continue; } - mpcc_cfg.opp_id = old_pipe_ctx->mpcc->opp_id; + mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + /* + * the mpcc is the only thing that keeps track of the mpcc + * mapping for reset front end right now. Might need some + * rework. + */ + old_pipe_ctx->mpcc->opp_id = opp_id_cached; old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; -- GitLab From 15e173352eeae76286e0d018f9eec6b55726caa4 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 17 Jul 2017 16:04:02 -0400 Subject: [PATCH 0646/2898] drm/amd/display: fix aviInfoFrame bar Info and add set_avMute Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 +++++ .../gpu/drm/amd/display/dc/core/dc_resource.c | 37 ++++++++++++++++--- .../amd/display/dc/dce/dce_stream_encoder.c | 13 ++++++- .../display/dc/dce110/dce110_hw_sequencer.c | 13 ++++++- .../display/dc/dce110/dce110_hw_sequencer.h | 1 + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + .../amd/display/dc/inc/hw/stream_encoder.h | 3 ++ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 + .../dc/virtual/virtual_stream_encoder.c | 4 ++ 10 files changed, 77 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index fed38fbab452..036d22f878b8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1911,3 +1911,13 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); } +void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + + if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) + return; + + core_dc->hwss.set_avmute(pipe_ctx, enable); +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9d0128e95767..63056e8c6d78 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1607,6 +1607,8 @@ static void set_avi_info_frame( uint8_t *check_sum = NULL; uint8_t byte_index = 0; union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; + unsigned int vic = pipe_ctx->stream->public.timing.vic; + enum dc_timing_3d_format format; color_space = pipe_ctx->stream->public.output_color_space; if (color_space == COLOR_SPACE_UNKNOWN) @@ -1661,8 +1663,7 @@ static void set_avi_info_frame( /* C0, C1 : Colorimetry */ if (color_space == COLOR_SPACE_YCBCR709 || - color_space == COLOR_SPACE_YCBCR709_LIMITED || - color_space == COLOR_SPACE_2020_YCBCR) + color_space == COLOR_SPACE_YCBCR709_LIMITED) hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709; else if (color_space == COLOR_SPACE_YCBCR601 || color_space == COLOR_SPACE_YCBCR601_LIMITED) @@ -1722,9 +1723,29 @@ static void set_avi_info_frame( hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; } - - hdmi_info->bits.VIC0_VIC7 = - stream->public.timing.vic; + ///VIC + format = stream->public.timing.timing_3d_format; + /*todo, add 3DStereo support*/ + if (format != TIMING_3D_FORMAT_NONE) { + // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled + switch (pipe_ctx->stream->public.timing.hdmi_vic) { + case 1: + vic = 95; + break; + case 2: + vic = 94; + break; + case 3: + vic = 93; + break; + case 4: + vic = 98; + break; + default: + break; + } + } + hdmi_info->bits.VIC0_VIC7 = vic; /* pixel repetition * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel @@ -1737,7 +1758,7 @@ static void set_avi_info_frame( * barLeft: Pixel Number of End of Left Bar. * barRight: Pixel Number of Start of Right Bar. */ hdmi_info->bits.bar_top = stream->public.timing.v_border_top; - hdmi_info->bits.bar_bottom = (stream->public.timing.v_border_top + hdmi_info->bits.bar_bottom = (stream->public.timing.v_total - stream->public.timing.v_border_bottom + 1); hdmi_info->bits.bar_left = stream->public.timing.h_border_left; hdmi_info->bits.bar_right = (stream->public.timing.h_total @@ -1776,6 +1797,10 @@ static void set_vendor_info_packet( uint8_t checksum = 0; uint32_t i = 0; enum dc_timing_3d_format format; + // Can be different depending on packet content /*todo*/ + // unsigned int length = pPathMode->dolbyVision ? 24 : 5; + + info_packet->valid = false; format = stream->public.timing.timing_3d_format; if (stream->public.view_format == VIEW_3D_FORMAT_NONE) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index daab81bd1773..532c6e638943 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1003,6 +1003,16 @@ static void dce110_stream_encoder_dp_unblank( REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); } +static void dce110_stream_encoder_set_avmute( + struct stream_encoder *enc, + bool enable) +{ + struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); + unsigned int value = enable ? 1 : 0; + + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, value); +} + #define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 #define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 @@ -1582,7 +1592,6 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { dce110_stream_encoder_dp_blank, .dp_unblank = dce110_stream_encoder_dp_unblank, - .audio_mute_control = dce110_se_audio_mute_control, .dp_audio_setup = dce110_se_dp_audio_setup, @@ -1592,6 +1601,8 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { .hdmi_audio_setup = dce110_se_hdmi_audio_setup, .hdmi_audio_disable = dce110_se_hdmi_audio_disable, .setup_stereo_sync = setup_stereo_sync, + .set_avmute = dce110_stream_encoder_set_avmute, + }; bool dce110_stream_encoder_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5d64611eb6a6..b691ef956d45 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -801,6 +801,13 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); } + +void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) +{ + if (pipe_ctx != NULL && pipe_ctx->stream_enc != NULL) + pipe_ctx->stream_enc->funcs->set_avmute(pipe_ctx->stream_enc, enable); +} + static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) { switch (crtc_id) { @@ -1095,10 +1102,11 @@ static enum dc_status apply_single_controller_ctx_to_hw( (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? true : false); + resource_build_info_frame(pipe_ctx); + if (!pipe_ctx_old->stream) { core_link_enable_stream(pipe_ctx); - resource_build_info_frame(pipe_ctx); dce110_update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) dce110_unblank_stream(pipe_ctx, @@ -2600,7 +2608,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_static_screen_control = set_static_screen_control, .reset_hw_ctx_wrap = reset_hw_ctx_wrap, .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, - .setup_stereo = NULL + .setup_stereo = NULL, + .set_avmute = dce110_set_avmute, }; bool dce110_hw_sequencer_construct(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 52462c17b2e9..89782ca1917f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -54,6 +54,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); +void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); void dce110_enable_accelerated_mode(struct core_dc *dc); void dce110_power_down(struct core_dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index cadc940e7c0e..8284837898d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1867,7 +1867,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_drr = set_drr, .get_position = get_position, .set_static_screen_control = set_static_screen_control, - .setup_stereo = dcn10_setup_stereo + .setup_stereo = dcn10_setup_stereo, + .set_avmute = dce110_set_avmute, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d216522a9989..d75368030917 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -179,6 +179,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx); void core_link_disable_stream(struct pipe_ctx *pipe_ctx); +void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); /********** DAL Core*********************/ #include "display_clock.h" #include "transform.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 9fb27bd360ac..6ff90a0fef24 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -123,6 +123,9 @@ struct stream_encoder_funcs { struct stream_encoder *enc, int tg_inst, bool enable); + + void (*set_avmute)( + struct stream_encoder *enc, bool enable); }; #endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 97dbd259f66c..d94e8e446ce5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -152,6 +152,8 @@ struct hw_sequencer_funcs { void (*setup_stereo)( struct pipe_ctx *pipe_ctx, struct core_dc *dc); + + void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); }; void color_space_to_black_color( diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index 8de21d9a8079..7fe6085e6e37 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -53,6 +53,9 @@ static void virtual_stream_encoder_update_hdmi_info_packets( static void virtual_stream_encoder_stop_hdmi_info_packets( struct stream_encoder *enc) {} +static void virtual_stream_encoder_set_avmute( + struct stream_encoder *enc, + bool enable) {} static void virtual_stream_encoder_update_dp_info_packets( struct stream_encoder *enc, const struct encoder_info_frame *info_frame) {} @@ -94,6 +97,7 @@ static const struct stream_encoder_funcs virtual_str_enc_funcs = { virtual_stream_encoder_dp_unblank, .audio_mute_control = virtual_audio_mute_control, + .set_avmute = virtual_stream_encoder_set_avmute, }; bool virtual_stream_encoder_construct( -- GitLab From d65359d571aa33dee9ddae659e92d1cb09ffbb2a Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 14 Jul 2017 13:42:23 -0400 Subject: [PATCH 0647/2898] drm/amd/display: revert order change of HUBP and MPC disable - root cause was we disable opp clk in MPC disconnect - hubp_blank is not double buffered, so we can't blank until MPC disconnect or we have risk of underflow Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 - .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 41 +++++++++++-------- .../amd/display/dc/dcn10/dcn10_mem_input.c | 5 +++ .../amd/display/dc/dcn10/dcn10_mem_input.h | 2 + 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 7e1d46fdcc76..94d12b5fb7c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -288,7 +288,6 @@ struct dce_hwseq_registers { HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \ HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR, mask_sh), \ HWS_SF(OTG0_, OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_OCCURRED, mask_sh), \ - HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh), \ HWS_SF(HUBP0_, DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh), \ HWS_SF(HUBP0_, HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ @@ -351,7 +350,6 @@ struct dce_hwseq_registers { #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ type VUPDATE_NO_LOCK_EVENT_OCCURRED; \ - type HUBP_NO_OUTSTANDING_REQ; \ type HUBP_VTG_SEL; \ type HUBP_CLOCK_ENABLE; \ type DPP_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 8284837898d2..adf3d2990687 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -436,29 +436,17 @@ static void reset_back_end_for_pipe( pipe_ctx->pipe_idx, pipe_ctx->tg->inst); } -static void reset_front_end( +static void plane_atomic_stop( struct core_dc *dc, int fe_idx) { - struct dce_hwseq *hws = dc->hwseq; struct mpcc_cfg mpcc_cfg; struct mem_input *mi = dc->res_pool->mis[fe_idx]; struct transform *xfm = dc->res_pool->transforms[fe_idx]; struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - unsigned int opp_id = mpcc->opp_id; - - /*Already reset*/ - if (opp_id == 0xf) - return; - - tg->funcs->lock(tg); mi->funcs->dcc_control(mi, false, false); - mi->funcs->set_blank(mi, true); - REG_WAIT(DCHUBP_CNTL[fe_idx], - HUBP_NO_OUTSTANDING_REQ, 1, - 1, 200); mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; @@ -466,23 +454,44 @@ static void reset_front_end( mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; mpcc->funcs->set(mpcc, &mpcc_cfg); + xfm->funcs->transform_reset(xfm); +} + +static void reset_front_end( + struct core_dc *dc, + int fe_idx) +{ + struct dce_hwseq *hws = dc->hwseq; + struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; + struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; + unsigned int opp_id = mpcc->opp_id; + + /*Already reset*/ + if (opp_id == 0xf) + return; + + tg->funcs->lock(tg); + + plane_atomic_stop(dc, fe_idx); + REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); tg->funcs->unlock(tg); REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); mpcc->funcs->wait_for_idle(mpcc); + mi->funcs->set_blank(mi, true); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - if (mpcc_cfg.top_of_tree) + if (tg->inst == mpcc->inst) REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); - xfm->funcs->transform_reset(xfm); - dm_logger_write(dc->ctx->logger, LOG_DC, "Reset front end %d\n", fe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index efa02d160d1a..8054794dd96d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -46,6 +46,11 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) REG_UPDATE_2(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en, HUBP_TTU_DISABLE, blank_en); + + if (blank) + REG_WAIT(DCHUBP_CNTL, + HUBP_NO_OUTSTANDING_REQ, 1, + 1, 200); } static void min10_vready_workaround(struct mem_input *mem_input, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 7efa857b8710..a0a1cef38d18 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -304,6 +304,7 @@ struct dcn_mi_registers { #define MI_MASK_SH_LIST_DCN(mask_sh)\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ @@ -463,6 +464,7 @@ struct dcn_mi_registers { #define DCN_MI_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ type HUBP_TTU_DISABLE;\ + type HUBP_NO_OUTSTANDING_REQ;\ type NUM_PIPES;\ type NUM_BANKS;\ type PIPE_INTERLEAVE;\ -- GitLab From 2233ec72b350fb8480f67b83f6a71ea422af60a3 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 18 Jul 2017 10:21:43 -0400 Subject: [PATCH 0648/2898] drm/amd/display: Add regkey for DRR control for internal panel Also need to change default to off Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - .../amd/display/modules/freesync/freesync.c | 74 ++++++++++--------- .../amd/display/modules/inc/mod_freesync.h | 1 - 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6a22c91cbcef..07f064f53d85 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -188,7 +188,6 @@ struct dc_debug { bool disable_dmcu; bool disable_psr; bool force_abm_enable; - bool no_static_for_external_dp; }; struct dc { diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 4df79f7147f8..a989d5de9f3c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -43,6 +43,10 @@ #define FREESYNC_REGISTRY_NAME "freesync_v1" +#define FREESYNC_NO_STATIC_FOR_EXTERNAL_DP_REGKEY "DalFreeSyncNoStaticForExternalDp" + +#define FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY "DalFreeSyncNoStaticForInternal" + struct gradual_static_ramp { bool ramp_is_active; bool ramp_direction_is_up; @@ -114,7 +118,8 @@ struct freesync_entity { }; struct freesync_registry_options { - unsigned int min_refresh_from_edid; + bool drr_external_supported; + bool drr_internal_supported; }; struct core_freesync { @@ -176,9 +181,19 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) NULL, NULL, 0, &flag); flag.save_per_edid = false; flag.save_per_link = false; + if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, - "DalDrrSupport", &data, sizeof(data), &flag)) { - core_freesync->opts.min_refresh_from_edid = data; + FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY, + &data, sizeof(data), &flag)) { + core_freesync->opts.drr_internal_supported = + (data & 1) ? false : true; + } + + if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, + FREESYNC_NO_STATIC_FOR_EXTERNAL_DP_REGKEY, + &data, sizeof(data), &flag)) { + core_freesync->opts.drr_external_supported = + (data & 1) ? false : true; } return &core_freesync->public; @@ -236,7 +251,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; struct persistent_data_flag flag; - unsigned int nom_refresh_rate_micro_hz; + unsigned int nom_refresh_rate_uhz; unsigned long long temp; if (mod_freesync == NULL) @@ -258,20 +273,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, temp = div_u64(temp, stream->timing.h_total); temp = div_u64(temp, stream->timing.v_total); - nom_refresh_rate_micro_hz = (unsigned int) temp; - - if (core_freesync->opts.min_refresh_from_edid != 0 && - dc_is_embedded_signal(stream->sink->sink_signal) - && (nom_refresh_rate_micro_hz - - core_freesync->opts.min_refresh_from_edid * - 1000000) >= 10000000) { - caps->supported = true; - caps->min_refresh_in_micro_hz = - core_freesync->opts.min_refresh_from_edid * - 1000000; - caps->max_refresh_in_micro_hz = - nom_refresh_rate_micro_hz; - } + nom_refresh_rate_uhz = (unsigned int) temp; core_freesync->map[core_freesync->num_entities].stream = stream; core_freesync->map[core_freesync->num_entities].caps = caps; @@ -311,8 +313,8 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, } if (caps->supported && - nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz && - nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz) + nom_refresh_rate_uhz >= caps->min_refresh_in_micro_hz && + nom_refresh_rate_uhz <= caps->max_refresh_in_micro_hz) core_stream->public.ignore_msa_timing_param = 1; core_freesync->num_entities++; @@ -865,6 +867,11 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, unsigned int map_index = map_index_from_stream(core_freesync, streams[stream_index]); + bool is_embedded = dc_is_embedded_signal( + streams[stream_index]->sink->sink_signal); + + struct freesync_registry_options *opts = &core_freesync->opts; + state = &core_freesync->map[map_index].state; switch (freesync_params->state){ @@ -875,25 +882,24 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, freesync_params->windowed_fullscreen; break; case FREESYNC_STATE_STATIC_SCREEN: - /* Static screen ramp is only enabled for embedded - * panels. Also change core variables only if there - * is a change. + /* Static screen ramp is disabled by default, but can + * be enabled through regkey. */ - if ((dc_is_embedded_signal( - streams[stream_index]->sink->sink_signal) || - core_freesync->map[map_index].caps-> - no_static_for_external_dp == false) && - state->static_screen != - freesync_params->enable) { + if ((is_embedded && opts->drr_internal_supported) || + (!is_embedded && opts->drr_external_supported)) - /* Change the state flag */ - state->static_screen = freesync_params->enable; + if (state->static_screen != + freesync_params->enable) { - /* Change static screen ramp variables */ - set_static_ramp_variables(core_freesync, + /* Change the state flag */ + state->static_screen = + freesync_params->enable; + + /* Update static screen ramp */ + set_static_ramp_variables(core_freesync, map_index, freesync_params->enable); - } + } /* We program the ramp starting next VUpdate */ break; case FREESYNC_STATE_VIDEO: diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index eae1b348b0dd..53c428b97902 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -88,7 +88,6 @@ struct mod_freesync_caps { unsigned int max_refresh_in_micro_hz; bool btr_supported; - bool no_static_for_external_dp; }; struct mod_freesync_params { -- GitLab From 4bdbab3efda297b2432ae4e722385deaa0089315 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 18 Jul 2017 15:50:47 -0400 Subject: [PATCH 0649/2898] drm/amd/display: powergate fe of reused pipes to reset ttu When we exit MPO, disconnected pipes cannot be immediately powergated because registers are double buffered, and actual disconnection does not happen until VUPDATE. So it is differred for many flips. However in the case of exiting full screen, the transition from MPO to grph only back to MPO is very fast and also involves increasing of watermarks. Since the underlay pipe is never powergated in this scenario, it keeps its old TTU counter, which causes allowPstateSwitch signal to be de-asserted when compared to the new increased watermark. Since the new pipe is not enabled yet, the signal will be continously de-asserted and hangs SMU, who's waiting for the signal to do pstate switching. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index adf3d2990687..6543027469af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1577,6 +1577,14 @@ static void dcn10_apply_ctx_for_surface( struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + /* + * Powergate reused pipes that are not powergated + * fairly hacky right now, using opp_id as indicator + */ + if (pipe_ctx->surface && !old_pipe_ctx->surface) { + if (pipe_ctx->mpcc->opp_id != 0xf) + dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); + } if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { @@ -1588,6 +1596,7 @@ static void dcn10_apply_ctx_for_surface( continue; } + /* reset mpc */ mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; -- GitLab From eb78d83e06371873b87a19721e7fe1503ba1d308 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 18 Jul 2017 18:33:23 -0400 Subject: [PATCH 0650/2898] drm/amd/display: Do not release state objects on atomic check fail In any drm ioctl call, drm_atomic_state_clear() is called at the end to destroy the states; even if atomic check fails. Therefore, releasing states on atomic check failure is incorrect. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index af4de578dadb..44d85b77e252 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2989,7 +2989,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, conn_state = drm_atomic_get_connector_state(state, &aconnector->base); if (IS_ERR(conn_state)) { ret = PTR_ERR_OR_ZERO(conn_state); - goto fail_crtcs; + goto fail; } dm_conn_state = to_dm_connector_state(conn_state); @@ -3048,7 +3048,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_atomic_add_affected_planes(state, crtc); if (ret) - goto fail_crtcs; + goto fail; } } @@ -3110,7 +3110,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, crtc_state, false); if (ret) - goto fail_planes; + goto fail; if (dm_plane_state->surface) @@ -3142,13 +3142,12 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = do_aquire_global_lock(dev, state); if (ret) - goto fail_planes; - + goto fail; WARN_ON(dm_state->context); dm_state->context = dc_get_validate_context(dc, set, set_count); if (!dm_state->context) { ret = -EINVAL; - goto fail_planes; + goto fail; } } @@ -3156,15 +3155,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, WARN_ON(ret); return ret; -fail_planes: - for (i = 0; i < set_count; i++) - for (j = 0; j < set[i].surface_count; j++) - dc_surface_release(set[i].surfaces[j]); - -fail_crtcs: - for (i = 0; i < set_count; i++) - dc_stream_release(set[i].stream); - +fail: if (ret == -EDEADLK) DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) -- GitLab From d8bad05a62a72975cab549f875e0fe2d159169c4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 17:23:45 -0400 Subject: [PATCH 0651/2898] drm/amd/include: Add DC_PINSTRAPS.AUDIO defines Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h | 2 ++ .../gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h index b39fb6821faa..3580218702ce 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h @@ -10361,6 +10361,8 @@ #define mmUNIPHYG_CHANNEL_XBAR_CNTL_BASE_IDX 2 #define mmDCIO_WRCMD_DELAY 0x287e #define mmDCIO_WRCMD_DELAY_BASE_IDX 2 +#define mmDC_PINSTRAPS 0x2880 +#define mmDC_PINSTRAPS_BASE_IDX 2 #define mmDC_DVODATA_CONFIG 0x2882 #define mmDC_DVODATA_CONFIG_BASE_IDX 2 #define mmLVTMA_PWRSEQ_CNTL 0x2883 diff --git a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h index 1e98ce86ed19..ecbe5bfa989b 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h @@ -39956,6 +39956,9 @@ #define DCIO_WRCMD_DELAY__DPHY_DELAY_MASK 0x00000F00L #define DCIO_WRCMD_DELAY__DCRXPHY_DELAY_MASK 0x0000F000L #define DCIO_WRCMD_DELAY__ZCAL_DELAY_MASK 0x000F0000L +//DC_PINSTRAPS +#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO__SHIFT 0xe +#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO_MASK 0x0000C000L //DC_DVODATA_CONFIG #define DC_DVODATA_CONFIG__VIP_MUX_EN__SHIFT 0x13 #define DC_DVODATA_CONFIG__VIP_ALTER_MAPPING_EN__SHIFT 0x14 -- GitLab From ee87a45e95a859a9df5a623d532dd472535cd6ea Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 25 Jul 2017 10:56:49 -0400 Subject: [PATCH 0652/2898] drm/amd/include: Add DCHUBBUB_TEST_DEBUG register defines Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h index 3580218702ce..4ccf9681c45d 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_offset.h @@ -2283,6 +2283,10 @@ #define mmDCHUBBUB_VLINE_SNAPSHOT_BASE_IDX 2 #define mmDCHUBBUB_SPARE 0x0534 #define mmDCHUBBUB_SPARE_BASE_IDX 2 +#define mmDCHUBBUB_TEST_DEBUG_INDEX 0x053a +#define mmDCHUBBUB_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmDCHUBBUB_TEST_DEBUG_DATA 0x053b +#define mmDCHUBBUB_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dchubbub_dchubbub_dcperfmon_dc_perfmon_dispdec -- GitLab From 20e9b0718babaaea9912ad5481a5089292c451a6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 4 Aug 2017 16:20:10 -0400 Subject: [PATCH 0653/2898] drm/amd: Add missing SURFACE_TMZ register shift/mask Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h index ecbe5bfa989b..b28d4b64c05d 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/raven1/DCN/dcn_1_0_sh_mask.h @@ -9361,12 +9361,14 @@ #define HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C__SECONDARY_META_SURFACE_ADDRESS_HIGH_C__SHIFT 0x0 #define HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C__SECONDARY_META_SURFACE_ADDRESS_HIGH_C_MASK 0x0000FFFFL //HUBPREQ0_DCSURF_SURFACE_CONTROL +#define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_TMZ__SHIFT 0x0 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_EN__SHIFT 0x1 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_IND_64B_BLK__SHIFT 0x2 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_IND_64B_BLK_C__SHIFT 0x5 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__SECONDARY_SURFACE_DCC_EN__SHIFT 0x9 #define HUBPREQ0_DCSURF_SURFACE_CONTROL__SECONDARY_SURFACE_DCC_IND_64B_BLK__SHIFT 0xa #define HUBPREQ0_DCSURF_SURFACE_CONTROL__SECONDARY_SURFACE_DCC_IND_64B_BLK_C__SHIFT 0xd +#define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_TMZ_MASK 0x00000001L #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_EN_MASK 0x00000002L #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_IND_64B_BLK_MASK 0x00000004L #define HUBPREQ0_DCSURF_SURFACE_CONTROL__PRIMARY_SURFACE_DCC_IND_64B_BLK_C_MASK 0x00000020L -- GitLab From 6631e5a91139f317caa6c75b38553afda0fa8626 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 19 Jul 2017 14:32:21 -0400 Subject: [PATCH 0654/2898] drm/amd/display: fix dcn10_resource read_dce_straps Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4a996f9ae468..b5f0f547ee83 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -610,12 +610,8 @@ static void read_dce_straps( struct dc_context *ctx, struct resource_straps *straps) { - /* TODO: Registers are missing */ - /*REG_GET_2(CC_DC_HDMI_STRAPS, - HDMI_DISABLE, &straps->hdmi_disable, - AUDIO_STREAM_NUMBER, &straps->audio_stream_number); - - REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); } static struct audio *create_audio( -- GitLab From 3d696cbfd48f20d482f2aab2c65ce3a540debd89 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Wed, 19 Jul 2017 16:46:42 -0400 Subject: [PATCH 0655/2898] drm/amd/display: Set i2c speed to 100khz for DCE11.2 and later. Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 983645b1be78..45e766ea79e3 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -337,6 +337,9 @@ enum { DEFAULT_I2C_SW_SPEED = 50, DEFAULT_I2C_HW_SPEED = 50, + DEFAULT_I2C_SW_SPEED_100KHZ = 100, + DEFAULT_I2C_HW_SPEED_100KHZ = 100, + /* This is the timeout as defined in DP 1.2a, * 2.3.4 "Detailed uPacket TX AUX CH State Description". */ AUX_TIMEOUT_PERIOD = 400, @@ -436,8 +439,13 @@ bool dal_i2caux_construct( i2caux->aux_timeout_period = SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD; - i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; - i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; + if (ctx->dce_version >= DCE_VERSION_11_2) { + i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED_100KHZ; + i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED_100KHZ; + } else { + i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; + i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; + } return true; } -- GitLab From 8ee65d7c93cb082d6c1ca584b7565c1cc08e7861 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 19 Jul 2017 13:18:26 -0400 Subject: [PATCH 0656/2898] drm/amd/display: Return hpd_irq_dpcd from hpd_rx handler Signed-off-by: Wenjing Liu Reviewed-by: Wenjing Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a41d271f21a3..26fbadba97dd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -914,7 +914,7 @@ static void handle_hpd_rx_irq(void *param) if (aconnector->dc_link->type != dc_connection_mst_branch) mutex_lock(&aconnector->hpd_lock); - if (dc_link_handle_hpd_rx_irq(aconnector->dc_link) && + if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && !is_mst_root_connector) { /* Downstream Port status changed. */ if (dc_link_detect(aconnector->dc_link, false)) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index dd3f57fce834..445cd226d36d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1924,7 +1924,7 @@ static void handle_automated_test(struct core_link *link) sizeof(test_response)); } -bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) +bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data *out_hpd_irq_dpcd_data) { struct core_link *link = DC_LINK_TO_LINK(dc_link); union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; @@ -1939,12 +1939,15 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link) "%s: Got short pulse HPD on link %d\n", __func__, link->public.link_index); + /* All the "handle_hpd_irq_xxx()" methods * should be called only after * dal_dpsst_ls_read_hpd_irq_data * Order of calls is important too */ result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data); + if (out_hpd_irq_dpcd_data) + *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data; if (result != DC_OK) { dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 07f064f53d85..7ecbff792e66 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -755,7 +755,8 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot); * detection. * false - no change in Downstream port status. No further action required * from DM. */ -bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link); +bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, + union hpd_irq_data *hpd_irq_dpcd_data); struct dc_sink_init_data; -- GitLab From 72f0281d34b464121f9f6b75a2d7a2502055ec79 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 19 Jul 2017 16:59:14 -0400 Subject: [PATCH 0657/2898] drm/amd/display: fix index and union overwrite in compressor Fixing 2 bugs in compressor: - array out of bounds due to incorrect index - compressor options always 0 due to union overwrite Signed-off-by: Roman Li Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 1e59f4e31a6a..9759d8e790a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -198,7 +198,7 @@ void dce110_compressor_enable_fbc( /* Keep track of enum controller_id FBC is attached to */ compressor->is_enabled = true; compressor->attached_inst = params->inst; - cp110->offsets = reg_offsets[params->inst - 1]; + cp110->offsets = reg_offsets[params->inst]; /*Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); @@ -469,6 +469,7 @@ bool dce110_compressor_construct(struct dce110_compressor *compressor, struct dc_context *ctx) { + compressor->base.options.raw = 0; compressor->base.options.bits.FBC_SUPPORT = true; /* for dce 11 always use one dram channel for lpt */ @@ -490,7 +491,6 @@ bool dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.allocated_size = 0; compressor->base.preferred_requested_size = 0; compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; - compressor->base.options.raw = 0; compressor->base.banks_num = 0; compressor->base.raw_size = 0; compressor->base.channel_interleave_size = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c index 22a5aba073ca..75af2125344b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -404,7 +404,7 @@ void dce112_compressor_enable_fbc( /* Keep track of enum controller_id FBC is attached to */ compressor->is_enabled = true; compressor->attached_inst = params->inst; - cp110->offsets = reg_offsets[params->inst - 1]; + cp110->offsets = reg_offsets[params->inst]; /*Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); @@ -797,6 +797,7 @@ bool dce112_compressor_construct(struct dce112_compressor *compressor, struct dc_bios *bp = ctx->dc_bios; struct embedded_panel_info panel_info; + compressor->base.options.raw = 0; compressor->base.options.bits.FBC_SUPPORT = true; compressor->base.options.bits.LPT_SUPPORT = true; /* For DCE 11 always use one DRAM channel for LPT */ @@ -817,7 +818,6 @@ bool dce112_compressor_construct(struct dce112_compressor *compressor, compressor->base.allocated_size = 0; compressor->base.preferred_requested_size = 0; compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; - compressor->base.options.raw = 0; compressor->base.banks_num = 0; compressor->base.raw_size = 0; compressor->base.channel_interleave_size = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c index eeedb7c4fe53..77626d7624c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c @@ -407,7 +407,7 @@ void dce80_compressor_enable_fbc( /* Keep track of enum controller_id FBC is attached to */ compressor->is_enabled = true; compressor->attached_inst = params->inst; - cp80->offsets = reg_offsets[params->inst - 1]; + cp80->offsets = reg_offsets[params->inst]; /*Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); @@ -777,6 +777,7 @@ bool dce80_compressor_construct(struct dce80_compressor *compressor, struct dc_bios *bp = ctx->dc_bios; struct embedded_panel_info panel_info; + compressor->base.options.raw = 0; compressor->base.options.bits.FBC_SUPPORT = true; compressor->base.options.bits.LPT_SUPPORT = true; /* For DCE 11 always use one DRAM channel for LPT */ @@ -797,7 +798,6 @@ bool dce80_compressor_construct(struct dce80_compressor *compressor, compressor->base.allocated_size = 0; compressor->base.preferred_requested_size = 0; compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID; - compressor->base.options.raw = 0; compressor->base.banks_num = 0; compressor->base.raw_size = 0; compressor->base.channel_interleave_size = 0; -- GitLab From fc0956909f24d2cd6f69777881bcccd771a06f35 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 22:00:34 -0400 Subject: [PATCH 0658/2898] drm/amd/display: register programming consolidation remove redundant DPP_CLOCK_ENABLE in ipp. clock programmed by HWSS Signed-off-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 1 - drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 4910d4c59b31..53dd9a9593f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -418,7 +418,6 @@ static void ippn10_enable_cm_block( { struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 1); REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index 1703589623b0..f14e208dbf1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -235,7 +235,6 @@ IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ IPP_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ - IPP_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ IPP_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ @@ -433,7 +432,6 @@ type CM_DGAM_LUT_WRITE_SEL; \ type CM_DGAM_LUT_INDEX; \ type CM_DGAM_LUT_DATA; \ - type DPP_CLOCK_ENABLE; \ type CM_BYPASS_EN; \ type CM_BYPASS; \ type CNVC_SURFACE_PIXEL_FORMAT; \ -- GitLab From 6d244be884d20b1e9c912291a242dccedd6d9040 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 20 Jul 2017 00:12:20 -0400 Subject: [PATCH 0659/2898] drm/amd/display: plumbing to allow easy print of HW state for DTN Signed-off-by: Tony Cheng Reviewed-by: Wesley Chalmers Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 ++ .../gpu/drm/amd/display/include/logger_interface.h | 4 ++++ 5 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index eda36c7a5c57..ad1b90563eb6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2035,3 +2035,10 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) } +void dc_log_hw_state(struct dc *dc) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + if (core_dc->hwss.log_hw_state) + core_dc->hwss.log_hw_state(core_dc); +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7ecbff792e66..7b8e11c28c62 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -236,6 +236,8 @@ void dc_destroy(struct dc **dc); bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); +void dc_log_hw_state(struct dc *dc); + /******************************************************************************* * Surface Interfaces ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6543027469af..c0aa32b71ad1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1851,6 +1851,17 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) return; } +static void dcn10_log_hw_state(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + + DTN_INFO("%s: Hello World", __func__); + + /* todo: add meaningful register reads and print out HW state + * + */ +} + static bool dcn10_dummy_display_power_gating( struct core_dc *dc, uint8_t controller_id, @@ -1887,6 +1898,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_static_screen_control = set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, + .log_hw_state = dcn10_log_hw_state, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index d94e8e446ce5..4c027a98cfd3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -154,6 +154,8 @@ struct hw_sequencer_funcs { struct core_dc *dc); void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); + + void (*log_hw_state)(struct core_dc *dc); }; void color_space_to_black_color( diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index ce5fef243b09..c861e726cd8f 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -123,6 +123,10 @@ void context_clock_trace( dm_logger_write(dc_ctx->logger, LOG_ERROR, \ __VA_ARGS__); +#define DTN_INFO(...) \ + dm_logger_write(dc_ctx->logger, LOG_DTN, \ + __VA_ARGS__) + #define DC_SYNC_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_SYNC, \ __VA_ARGS__); -- GitLab From 2b13d7d380d50811fd4fc022d135c3c5bb70a418 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 14 Jul 2017 14:07:16 -0400 Subject: [PATCH 0660/2898] drm/amd/display: mpo debug sanity checks Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 6 + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 152 +++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 21 +++ .../drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + 5 files changed, 179 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7b8e11c28c62..617270829936 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -160,6 +160,7 @@ struct dc_config { struct dc_debug { bool surface_visual_confirm; + bool sanity_checks; bool max_disp_clk; bool surface_trace; bool timing_trace; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 94d12b5fb7c6..0479554bc231 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -147,6 +147,9 @@ SRII(OPP_PIPE_CONTROL, OPP_PIPE, 3), \ SR(REFCLK_CNTL), \ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL), \ + SR(DCHUBBUB_TEST_DEBUG_INDEX), \ + SR(DCHUBBUB_TEST_DEBUG_DATA), \ SR(DC_IP_REQUEST_CNTL), \ SR(DOMAIN0_PG_CONFIG), \ SR(DOMAIN1_PG_CONFIG), \ @@ -195,6 +198,9 @@ struct dce_hwseq_registers { uint32_t OPP_PIPE_CONTROL[4]; uint32_t REFCLK_CNTL; uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; + uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; + uint32_t DCHUBBUB_TEST_DEBUG_INDEX; + uint32_t DCHUBBUB_TEST_DEBUG_DATA; uint32_t DC_IP_REQUEST_CNTL; uint32_t DOMAIN0_PG_CONFIG; uint32_t DOMAIN1_PG_CONFIG; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c0aa32b71ad1..b5a925362c8c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -52,6 +52,75 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name + +static void verify_allow_pstate_change_high( + struct dce_hwseq *hws) +{ + /* pstate latency is ~20us so if we wait over 40us and pstate allow + * still not asserted, we are probably stuck and going to hang + */ + static unsigned int pstate_wait_timeout_us = 40; + static unsigned int max_sampled_pstate_wait_us; /* data collection */ + static bool forced_pstate_allow; /* help with revert wa */ + + unsigned int debug_index = 0x7; + unsigned int debug_data; + unsigned int force_allow_pstate = 0x30; + unsigned int i; + + if (forced_pstate_allow) { + /* we hacked to force pstate allow to prevent hang last time + * we verify_allow_pstate_change_high. so disable force + * here so we can check status + */ + REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, 0); + forced_pstate_allow = false; + } + + /* description "3-0: Pipe0 cursor0 QOS + * 7-4: Pipe1 cursor0 QOS + * 11-8: Pipe2 cursor0 QOS + * 15-12: Pipe3 cursor0 QOS + * 16: Pipe0 Plane0 Allow Pstate Change + * 17: Pipe1 Plane0 Allow Pstate Change + * 18: Pipe2 Plane0 Allow Pstate Change + * 19: Pipe3 Plane0 Allow Pstate Change + * 20: Pipe0 Plane1 Allow Pstate Change + * 21: Pipe1 Plane1 Allow Pstate Change + * 22: Pipe2 Plane1 Allow Pstate Change + * 23: Pipe3 Plane1 Allow Pstate Change + * 24: Pipe0 cursor0 Allow Pstate Change + * 25: Pipe1 cursor0 Allow Pstate Change + * 26: Pipe2 cursor0 Allow Pstate Change + * 27: Pipe3 cursor0 Allow Pstate Change + * 28: WB0 Allow Pstate Change + * 29: WB1 Allow Pstate Change + * 30: Arbiter's allow_pstate_change + * 31: SOC pstate change request + */ + + REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, debug_index); + + for (i = 0; i < pstate_wait_timeout_us; i++) { + debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); + + if (debug_data & (1 << 30)) + return; + + if (max_sampled_pstate_wait_us < i) + max_sampled_pstate_wait_us = i; + + udelay(1); + } + + /* force pstate allow to prevent system hang + * and break to debugger to investigate + */ + REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); + forced_pstate_allow = true; + BREAK_TO_DEBUGGER(); +} + static void enable_dppclk( struct dce_hwseq *hws, uint8_t plane_id, @@ -477,12 +546,19 @@ static void reset_front_end( REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); tg->funcs->unlock(tg); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); mpcc->funcs->wait_for_idle(mpcc); mi->funcs->set_blank(mi, true); + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0); REG_UPDATE(DPP_CONTROL[fe_idx], @@ -495,6 +571,9 @@ static void reset_front_end( dm_logger_write(dc->ctx->logger, LOG_DC, "Reset front end %d\n", fe_idx); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) @@ -511,6 +590,9 @@ static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, "Power gated front end %d\n", fe_idx); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } static void reset_hw_ctx_wrap( @@ -995,10 +1077,16 @@ static void dcn10_pipe_control_lock( if (pipe->top_pipe) return; + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + if (lock) pipe->tg->funcs->lock(pipe->tg); else pipe->tg->funcs->unlock(pipe->tg); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } static bool wait_for_reset_trigger_to_occur( @@ -1516,6 +1604,12 @@ static void program_all_pipe_in_tree( /* watermark is for all pipes */ pipe_ctx->mi->funcs->program_watermarks( pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); + + if (dc->public.debug.sanity_checks) { + /* pstate stuck check after watermark update */ + verify_allow_pstate_change_high(dc->hwseq); + } + pipe_ctx->tg->funcs->lock(pipe_ctx->tg); pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; @@ -1534,6 +1628,11 @@ static void program_all_pipe_in_tree( update_dchubp_dpp(dc, pipe_ctx, context); } + if (dc->public.debug.sanity_checks) { + /* pstate stuck check after each pipe is programmed */ + verify_allow_pstate_change_high(dc->hwseq); + } + if (pipe_ctx->bottom_pipe != NULL) program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); } @@ -1572,6 +1671,9 @@ static void dcn10_apply_ctx_for_surface( { int i; + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + /* reset unused mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1602,6 +1704,10 @@ static void dcn10_apply_ctx_for_surface( mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + /* * the mpcc is the only thing that keeps track of the mpcc * mapping for reset front end right now. Might need some @@ -1679,6 +1785,9 @@ static void dcn10_apply_ctx_for_surface( context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns, context->bw.dcn.watermarks.d.pte_meta_urgent_ns ); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } static void dcn10_set_bandwidth( @@ -1738,6 +1847,8 @@ static void dcn10_set_bandwidth( context->bw.dcn.calc_clk.min_active_dram_ccm_us; } dcn10_pplib_apply_display_requirements(dc, context); + + /* need to fix this function. not doing the right thing here */ } static void set_drr(struct pipe_ctx **pipe_ctx, @@ -1866,7 +1977,44 @@ static bool dcn10_dummy_display_power_gating( struct core_dc *dc, uint8_t controller_id, struct dc_bios *dcb, - enum pipe_gating_control power_gating) {return true; } + enum pipe_gating_control power_gating) +{ + return true; +} + +void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) +{ + struct core_surface *surface = pipe_ctx->surface; + struct timing_generator *tg = pipe_ctx->tg; + + if (surface->ctx->dc->debug.sanity_checks) { + struct core_dc *dc = DC_TO_CORE(surface->ctx->dc); + + verify_allow_pstate_change_high(dc->hwseq); + } + + if (surface == NULL) + return; + + surface->status.is_flip_pending = + pipe_ctx->mi->funcs->mem_input_is_flip_pending( + pipe_ctx->mi); + + /* DCN we read INUSE address in MI, do we still need this wa? */ + if (surface->status.is_flip_pending && + !surface->public.visible) { + pipe_ctx->mi->current_address = + pipe_ctx->mi->request_address; + BREAK_TO_DEBUGGER(); + } + + surface->status.current_address = pipe_ctx->mi->current_address; + if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + tg->funcs->is_stereo_left_eye) { + surface->status.is_right_eye = + !tg->funcs->is_stereo_left_eye(pipe_ctx->tg); + } +} static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, @@ -1876,7 +2024,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, - .update_pending_status = dce110_update_pending_status, + .update_pending_status = dcn10_update_pending_status, .set_input_transfer_func = dcn10_set_input_transfer_func, .set_output_transfer_func = dcn10_set_output_transfer_func, .power_down = dce110_power_down, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index de3341d572be..9af288167e2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -77,6 +77,24 @@ static void reset_output_mux(struct dcn10_mpcc *mpcc10) mpcc10->base.opp_id = 0xf; } +static void assert_mpcc_idle_before_connect(struct dcn10_mpcc *mpcc10) +{ + unsigned int top_sel; + unsigned int mpcc_busy, mpcc_idle, mpcc_status; + + REG_GET(MPCC_TOP_SEL, + MPCC_TOP_SEL, &top_sel); + + if (top_sel == 0xf) { + mpcc_status = REG_GET_2(MPCC_STATUS, + MPCC_BUSY, &mpcc_busy, + MPCC_IDLE, &mpcc_idle); + + ASSERT(mpcc_busy == 0); + ASSERT(mpcc_idle == 1); + } +} + static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) { struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); @@ -87,6 +105,9 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) bool blend_active_only = cfg->top_of_tree && !mpcc->ctx->dc->debug.surface_visual_confirm; + if (mpcc->ctx->dc->debug.sanity_checks) + assert_mpcc_idle_before_connect(mpcc10); + REG_SET(MPCC_OPP_ID, 0, MPCC_OPP_ID, cfg->opp_id); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index b5f0f547ee83..eec0d5b22a9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -424,6 +424,7 @@ static const struct resource_caps res_cap = { static const struct dc_debug debug_defaults_drv = { .disable_dcc = false, + .sanity_checks = true, .disable_dmcu = true, .force_abm_enable = false, .timing_trace = false, -- GitLab From 9b1c9b4c2eec7cb2a4d3762da7aa78aea8e34630 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 20 Jul 2017 14:51:16 -0400 Subject: [PATCH 0661/2898] drm/amd/display: update dcn register headers Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 7 ++++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 12 +++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index f14e208dbf1c..69db441e78c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -87,7 +87,6 @@ SRI(CM_DGAM_CONTROL, CM, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(DPP_CONTROL, DPP_TOP, id), \ - SRI(CURSOR_SETTINS, HUBPREQ, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ @@ -95,6 +94,7 @@ #define IPP_REG_LIST_DCN10(id) \ IPP_REG_LIST_DCN(id), \ + SRI(CURSOR_SETTINS, HUBPREQ, id), \ SRI(CM_IGAM_CONTROL, CM, id), \ SRI(CM_COMA_C11_C12, CM, id), \ SRI(CM_COMA_C13_C14, CM, id), \ @@ -240,8 +240,6 @@ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ - IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ - IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ @@ -250,6 +248,8 @@ #define IPP_MASK_SH_LIST_DCN10(mask_sh) \ IPP_MASK_SH_LIST_DCN(mask_sh),\ + IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ @@ -537,6 +537,7 @@ struct dcn10_ipp_registers { uint32_t CM_IGAM_CONTROL; uint32_t DPP_CONTROL; uint32_t CURSOR_SETTINS; + uint32_t CURSOR_SETTINGS; uint32_t CNVC_SURFACE_PIXEL_FORMAT; uint32_t CURSOR0_CONTROL; uint32_t CURSOR0_COLOR0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index a0a1cef38d18..0f4d247c4237 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -75,7 +75,6 @@ SRI(BLANK_OFFSET_1, HUBPREQ, id),\ SRI(DST_DIMENSIONS, HUBPREQ, id),\ SRI(DST_AFTER_SCALER, HUBPREQ, id),\ - SRI(PREFETCH_SETTINS, HUBPREQ, id),\ SRI(VBLANK_PARAMETERS_0, HUBPREQ, id),\ SRI(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id),\ SRI(VBLANK_PARAMETERS_1, HUBPREQ, id),\ @@ -86,7 +85,6 @@ SRI(NOM_PARAMETERS_5, HUBPREQ, id),\ SRI(PER_LINE_DELIVERY_PRE, HUBPREQ, id),\ SRI(PER_LINE_DELIVERY, HUBPREQ, id),\ - SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ SRI(VBLANK_PARAMETERS_2, HUBPREQ, id),\ SRI(VBLANK_PARAMETERS_4, HUBPREQ, id),\ SRI(NOM_PARAMETERS_2, HUBPREQ, id),\ @@ -140,6 +138,8 @@ #define MI_REG_LIST_DCN10(id)\ MI_REG_LIST_DCN(id),\ + SRI(PREFETCH_SETTINS, HUBPREQ, id),\ + SRI(PREFETCH_SETTINS_C, HUBPREQ, id),\ SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, HUBPREQ, id),\ SRI(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, HUBPREQ, id),\ SRI(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, HUBPREQ, id),\ @@ -206,6 +206,7 @@ struct dcn_mi_registers { uint32_t DST_DIMENSIONS; uint32_t DST_AFTER_SCALER; uint32_t PREFETCH_SETTINS; + uint32_t PREFETCH_SETTINGS; uint32_t VBLANK_PARAMETERS_0; uint32_t REF_FREQ_TO_PIX_FREQ; uint32_t VBLANK_PARAMETERS_1; @@ -217,6 +218,7 @@ struct dcn_mi_registers { uint32_t PER_LINE_DELIVERY_PRE; uint32_t PER_LINE_DELIVERY; uint32_t PREFETCH_SETTINS_C; + uint32_t PREFETCH_SETTINGS_C; uint32_t VBLANK_PARAMETERS_2; uint32_t VBLANK_PARAMETERS_4; uint32_t NOM_PARAMETERS_2; @@ -388,8 +390,6 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ MI_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ MI_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ MI_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ MI_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ @@ -403,7 +403,6 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ MI_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ - MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ MI_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ MI_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ MI_SF(HUBPREQ0_NOM_PARAMETERS_2, DST_Y_PER_PTE_ROW_NOM_C, mask_sh),\ @@ -429,6 +428,9 @@ struct dcn_mi_registers { #define MI_MASK_SH_LIST_DCN10(mask_sh)\ MI_MASK_SH_LIST_DCN(mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, DST_Y_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS, VRATIO_PREFETCH, mask_sh),\ + MI_SF(HUBPREQ0_PREFETCH_SETTINS_C, VRATIO_PREFETCH_C, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, mask_sh),\ -- GitLab From 7f10f3c2a761ddf3dc18be45d4ccf60db5fe10cf Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 19 Jul 2017 20:22:22 -0400 Subject: [PATCH 0662/2898] drm/amd/display: mpcc disconnect and pipe pg in multi-display still quite hacky. but this address not properly shutdown pipe video underlay + enable another display case, as well as mode changes with video overlay. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b5a925362c8c..d607ca94bd13 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1669,30 +1669,46 @@ static void dcn10_apply_ctx_for_surface( struct core_surface *surface, struct validate_context *context) { - int i; + int i, be_idx; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); + if (!surface) + return; + + for (be_idx = 0; be_idx < dc->res_pool->pipe_count; be_idx++) + if (surface == context->res_ctx.pipe_ctx[be_idx].surface) + break; + /* reset unused mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->surface && !old_pipe_ctx->surface) + continue; + /* * Powergate reused pipes that are not powergated * fairly hacky right now, using opp_id as indicator */ + if (pipe_ctx->surface && !old_pipe_ctx->surface) { - if (pipe_ctx->mpcc->opp_id != 0xf) + if (pipe_ctx->mpcc->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); } + if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { struct mpcc_cfg mpcc_cfg; int opp_id_cached = old_pipe_ctx->mpcc->opp_id; + if (old_pipe_ctx->tg->inst != be_idx) + continue; + if (!old_pipe_ctx->top_pipe) { ASSERT(0); continue; @@ -1725,9 +1741,6 @@ static void dcn10_apply_ctx_for_surface( } } - if (!surface) - return; - for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; -- GitLab From aa9850705fc05b7e7f44558e30705ac54579e724 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 20 Jul 2017 16:17:17 -0400 Subject: [PATCH 0663/2898] drm/amd/display: fix locking in apply_ctx_for_surface Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d607ca94bd13..6db78d9f8e3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1696,8 +1696,14 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->surface && !old_pipe_ctx->surface) { - if (pipe_ctx->mpcc->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) + if (pipe_ctx->mpcc->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); + /* + * power down fe will unlock when calling reset, need + * to lock it back here. Messy, need rework. + */ + pipe_ctx->tg->funcs->lock(pipe_ctx->tg); + } } -- GitLab From 98e4a22f02da4a66f7652a3301dcb689b739e521 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 18 Jul 2017 20:13:05 -0400 Subject: [PATCH 0664/2898] drm/amd/display: revert dcn10 soc defaults to 17 19 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 0ea0dab49e0f..a1eabc47558e 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -37,8 +37,8 @@ /* Defaults from spreadsheet rev#247 */ const struct dcn_soc_bounding_box dcn10_soc_defaults = { /* latencies */ - .sr_exit_time = 13, /*us*/ - .sr_enter_plus_exit_time = 15, /*us*/ + .sr_exit_time = 17, /*us*/ + .sr_enter_plus_exit_time = 19, /*us*/ .urgent_latency = 4, /*us*/ .dram_clock_change_latency = 17, /*us*/ .write_back_latency = 12, /*us*/ -- GitLab From 50e27654d778114382093eecc1d6e5b7e9343d23 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Thu, 20 Jul 2017 19:04:56 -0400 Subject: [PATCH 0665/2898] drm/amd/display: Implement logic for hdmi info packet bits. Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 68 ++++++++++++++++--- drivers/gpu/drm/amd/display/dc/dc_types.h | 25 +++++++ 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 63056e8c6d78..5acc5cdcda16 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1603,10 +1603,13 @@ static void set_avi_info_frame( enum scanning_type scan_type = SCANNING_TYPE_NODATA; enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; bool itc = false; + uint8_t itc_value = 0; uint8_t cn0_cn1 = 0; + unsigned int cn0_cn1_value = 0; uint8_t *check_sum = NULL; uint8_t byte_index = 0; union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; + union display_content_support support = {0}; unsigned int vic = pipe_ctx->stream->public.timing.vic; enum dc_timing_3d_format format; @@ -1703,26 +1706,71 @@ static void set_avi_info_frame( hdmi_info->bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; /* TODO: un-hardcode cn0_cn1 and itc */ + cn0_cn1 = 0; - itc = false; + cn0_cn1_value = 0; + + itc = true; + itc_value = 1; + + support = stream->public.sink->edid_caps.content_support; if (itc) { - hdmi_info->bits.ITC = 1; - hdmi_info->bits.CN0_CN1 = cn0_cn1; + if (!support.bits.valid_content_type) { + cn0_cn1_value = 0; + } else { + if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { + if (support.bits.graphics_content == 1) { + cn0_cn1_value = 0; + } + } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { + if (support.bits.photo_content == 1) { + cn0_cn1_value = 1; + } else { + cn0_cn1_value = 0; + itc_value = 0; + } + } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { + if (support.bits.cinema_content == 1) { + cn0_cn1_value = 2; + } else { + cn0_cn1_value = 0; + itc_value = 0; + } + } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { + if (support.bits.game_content == 1) { + cn0_cn1_value = 3; + } else { + cn0_cn1_value = 0; + itc_value = 0; + } + } + } + hdmi_info->bits.CN0_CN1 = cn0_cn1_value; + hdmi_info->bits.ITC = itc_value; } /* TODO : We should handle YCC quantization */ /* but we do not have matrix calculation */ - if (color_space == COLOR_SPACE_SRGB) { - hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; - hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; - } else if (color_space == COLOR_SPACE_SRGB_LIMITED) { - hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; - hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; + if (stream->public.sink->edid_caps.qs_bit == 1 && + stream->public.sink->edid_caps.qy_bit == 1) { + if (color_space == COLOR_SPACE_SRGB || + color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE; + } else if (color_space == COLOR_SPACE_SRGB_LIMITED || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; + } else { + hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; + } } else { hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; - hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; + hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; } + ///VIC format = stream->public.timing.timing_3d_format; /*todo, add 3DStereo support*/ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 9662f2c68f83..c7539fe36b66 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -177,6 +177,18 @@ struct dc_edid { #define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20 +union display_content_support { + unsigned int raw; + struct { + unsigned int valid_content_type :1; + unsigned int game_content :1; + unsigned int cinema_content :1; + unsigned int photo_content :1; + unsigned int graphics_content :1; + unsigned int reserved :27; + } bits; +}; + struct dc_edid_caps { /* sink identification */ uint16_t manufacturer_id; @@ -193,6 +205,11 @@ struct dc_edid_caps { uint32_t audio_latency; uint32_t video_latency; + union display_content_support content_support; + + uint8_t qs_bit; + uint8_t qy_bit; + /*HDMI 2.0 caps*/ bool lte_340mcsc_scramble; @@ -384,6 +401,14 @@ enum scaling_transformation { SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE }; +enum display_content_type { + DISPLAY_CONTENT_TYPE_NO_DATA = 0, + DISPLAY_CONTENT_TYPE_GRAPHICS = 1, + DISPLAY_CONTENT_TYPE_PHOTO = 2, + DISPLAY_CONTENT_TYPE_CINEMA = 4, + DISPLAY_CONTENT_TYPE_GAME = 8 +}; + /* audio*/ union audio_sample_rates { -- GitLab From f811fd5a66a3e69cdc184accfe189de5a1f6dba4 Mon Sep 17 00:00:00 2001 From: Wesley Chalmers Date: Thu, 20 Jul 2017 17:13:12 -0400 Subject: [PATCH 0666/2898] drm/amd/display: Change DTN_INFO macro Signed-off-by: Wesley Chalmers Reviewed-by: Wesley Chalmers Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/include/logger_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index c861e726cd8f..6e6fd4e8fc00 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -124,7 +124,7 @@ void context_clock_trace( __VA_ARGS__); #define DTN_INFO(...) \ - dm_logger_write(dc_ctx->logger, LOG_DTN, \ + dc_raw_log(dc_ctx, LOG_DTN, \ __VA_ARGS__) #define DC_SYNC_INFO(...) \ -- GitLab From 516666318fe1f427ab81e2ebe45d116a9667c3b5 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 21 Jul 2017 17:35:16 -0400 Subject: [PATCH 0667/2898] drm/amd/display: support for updated register headers on DCN Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 12 ++++++- .../display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++++-- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 17 ++++++--- .../amd/display/dc/dcn10/dcn10_mem_input.c | 19 +++++++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 15 +++++++- .../display/dc/dcn10/dcn10_timing_generator.c | 36 ++++++++++--------- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 4 +++ 8 files changed, 88 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 0479554bc231..80ee1ac32fee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -227,6 +227,15 @@ struct dce_hwseq_registers { uint32_t DISPCLK_FREQ_CHANGE_CNTL; uint32_t RBBMIF_TIMEOUT_DIS; uint32_t RBBMIF_TIMEOUT_DIS_2; + uint32_t DENTIST_DISPCLK_CNTL; + uint32_t DCHUBBUB_CRC_CTRL; + uint32_t DPP_TOP0_DPP_CRC_CTRL; + uint32_t DPP_TOP0_DPP_CRC_VAL_R_G; + uint32_t DPP_TOP0_DPP_CRC_VAL_B_A; + uint32_t MPC_CRC_CTRL; + uint32_t MPC_CRC_RESULT_GB; + uint32_t MPC_CRC_RESULT_C; + uint32_t MPC_CRC_RESULT_AR; #endif }; /* set field name */ @@ -388,7 +397,8 @@ struct dce_hwseq_registers { type DOMAIN6_PGFSM_PWR_STATUS; \ type DOMAIN7_PGFSM_PWR_STATUS; \ type DCFCLK_GATE_DIS; \ - type DCHUBBUB_GLOBAL_TIMER_REFDIV; + type DCHUBBUB_GLOBAL_TIMER_REFDIV; \ + type DENTIST_DPPCLK_WDIVIDER; #endif struct dce_hwseq_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b691ef956d45..baafe6609d24 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -256,7 +256,7 @@ static bool dce110_set_input_transfer_func( ipp->funcs->ipp_program_prescale(ipp, &prescale_params); if (surface->public.gamma_correction && dce_use_lut(surface)) - ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); + ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); if (tf == NULL) { /* Default case if no input transfer function specified */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6db78d9f8e3b..ce7da8864507 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -550,7 +550,9 @@ static void reset_front_end( if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], + VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); mpcc->funcs->wait_for_idle(mpcc); @@ -1295,6 +1297,7 @@ static void dcn10_power_on_fe( /* make sure OPP_PIPE_CLOCK_EN = 1 */ REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->tg->inst], OPP_PIPE_CLOCK_EN, 1); + /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ if (dc_surface) { dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1984,9 +1987,16 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) static void dcn10_log_hw_state(struct core_dc *dc) { struct dc_context *dc_ctx = dc->ctx; + struct dce_hwseq *hws = dc->hwseq; DTN_INFO("%s: Hello World", __func__); + if (REG(MPC_CRC_RESULT_GB)) + DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", + REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); + if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) + DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", + REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); /* todo: add meaningful register reads and print out HW state * */ @@ -2065,7 +2075,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_static_screen_control = set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, - .log_hw_state = dcn10_log_hw_state, + .log_hw_state = dcn10_log_hw_state }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 53dd9a9593f0..ee12f671d8ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -472,11 +472,18 @@ static bool ippn10_cursor_program_control( bool pixel_data_invert, enum dc_cursor_color_format color_format) { - REG_SET_2(CURSOR_SETTINS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); + if (REG(CURSOR_SETTINS)) + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + else + REG_SET_2(CURSOR_SETTINGS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); REG_UPDATE_2(CURSOR0_CONTROL, CUR0_MODE, color_format, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 8054794dd96d..1f86295d6db6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -460,9 +460,14 @@ static void min10_program_deadline( REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); - REG_SET_2(PREFETCH_SETTINS, 0, - DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, - VRATIO_PREFETCH, dlg_attr->vratio_prefetch); + if (REG(PREFETCH_SETTINS)) + REG_SET_2(PREFETCH_SETTINS, 0, + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); + else + REG_SET_2(PREFETCH_SETTINGS, 0, + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); REG_SET_2(VBLANK_PARAMETERS_0, 0, DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, @@ -498,8 +503,12 @@ static void min10_program_deadline( REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); - REG_SET(PREFETCH_SETTINS_C, 0, - VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); + if (REG(PREFETCH_SETTINS_C)) + REG_SET(PREFETCH_SETTINS_C, 0, + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); + else + REG_SET(PREFETCH_SETTINGS_C, 0, + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); REG_SET(VBLANK_PARAMETERS_2, 0, REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index de0b631736bb..d9d66a4afb19 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -123,7 +123,6 @@ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_RGAM_LUT_DATA, CM, id) - #define OPP_MASK_SH_LIST_DCN(mask_sh) \ OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ @@ -357,6 +356,16 @@ OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ + type DPG_EN; \ + type DPG_MODE; \ + type DPG_VRES; \ + type DPG_HRES; \ + type DPG_COLOUR0_R_CR; \ + type DPG_COLOUR1_R_CR; \ + type DPG_COLOUR0_B_CB; \ + type DPG_COLOUR1_B_CB; \ + type DPG_COLOUR0_G_Y; \ + type DPG_COLOUR1_G_Y; \ type CM_OCSC_C11; \ type CM_OCSC_C12; \ type CM_OCSC_C13; \ @@ -594,6 +603,10 @@ struct dcn10_opp_mask { }; struct dcn10_opp_registers { + uint32_t DPG_CONTROL; + uint32_t DPG_COLOUR_B_CB; + uint32_t DPG_COLOUR_G_Y; + uint32_t DPG_COLOUR_R_CR; uint32_t CM_OCSC_C11_C12; uint32_t CM_OCSC_C13_C14; uint32_t CM_OCSC_C21_C22; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 12d7f3570cfa..b2e796d87dac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -345,17 +345,18 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); if (enable) { - REG_UPDATE(OPTC_INPUT_CLOCK_CONTROL, - OPTC_INPUT_CLK_EN, 1); + REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_EN, 1, + OPTC_INPUT_CLK_GATE_DIS, 1); REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 1, 2000, 500); /* Enable clock */ - REG_UPDATE(OTG_CLOCK_CONTROL, - OTG_CLOCK_EN, 1); - + REG_UPDATE_2(OTG_CLOCK_CONTROL, + OTG_CLOCK_EN, 1, + OTG_CLOCK_GATE_DIS, 1); REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 1, 2000, 500); @@ -364,17 +365,19 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) OTG_CLOCK_GATE_DIS, 0, OTG_CLOCK_EN, 0); - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_CLOCK_ON, 0, - 2000, 500); + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_CLOCK_ON, 0, + 2000, 500); REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, 0, OPTC_INPUT_CLK_EN, 0); - REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, - OPTC_INPUT_CLK_ON, 0, - 2000, 500); + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_ON, 0, + 2000, 500); } } @@ -574,9 +577,10 @@ static void tgn10_lock(struct timing_generator *tg) REG_SET(OTG_MASTER_UPDATE_LOCK, 0, OTG_MASTER_UPDATE_LOCK, 1); - REG_WAIT(OTG_MASTER_UPDATE_LOCK, - UPDATE_LOCK_STATUS, 1, - 1, 100); + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 100); } static void tgn10_unlock(struct timing_generator *tg) @@ -587,9 +591,9 @@ static void tgn10_unlock(struct timing_generator *tg) OTG_MASTER_UPDATE_LOCK, 0); /* why are we waiting here? */ - /*REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, + REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, 0, - 20000, 200000);*/ + 20000, 200000); } static void tgn10_get_position(struct timing_generator *tg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a101f4b5e0c7..4b0c28eef352 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -324,6 +324,10 @@ struct opp_funcs { struct output_pixel_processor *opp, bool enable, bool rightEyePolarity); + + void (*opp_set_test_pattern)( + struct output_pixel_processor *opp, + bool enable); }; #endif -- GitLab From 03618e910797c9bb7ec8eb1e45df64ad8080a37a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 20 Jul 2017 10:26:23 -0400 Subject: [PATCH 0668/2898] drm/amd/display: Roll surface struct into core_surface Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_surface.c | 37 +++++++------------ .../gpu/drm/amd/display/dc/inc/core_types.h | 4 ++ 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d44ddfb85748..3784358d35ef 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -34,20 +34,11 @@ /******************************************************************************* * Private structures ******************************************************************************/ -struct surface { - struct core_surface protected; - enum dc_irq_source irq_source; - int ref_count; -}; - struct gamma { struct core_gamma protected; int ref_count; }; -#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) -#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) - #define DC_GAMMA_TO_GAMMA(dc_gamma) \ container_of(dc_gamma, struct gamma, protected.public) #define CORE_GAMMA_TO_GAMMA(core_gamma) \ @@ -56,23 +47,23 @@ struct gamma { /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct surface *surface) +static bool construct(struct dc_context *ctx, struct core_surface *surface) { - surface->protected.ctx = ctx; - memset(&surface->protected.public.hdr_static_ctx, + surface->ctx = ctx; + memset(&surface->public.hdr_static_ctx, 0, sizeof(struct dc_hdr_static_metadata)); return true; } -static void destruct(struct surface *surface) +static void destruct(struct core_surface *surface) { - if (surface->protected.public.gamma_correction != NULL) { - dc_gamma_release(&surface->protected.public.gamma_correction); + if (surface->public.gamma_correction != NULL) { + dc_gamma_release(&surface->public.gamma_correction); } - if (surface->protected.public.in_transfer_func != NULL) { + if (surface->public.in_transfer_func != NULL) { dc_transfer_func_release( - surface->protected.public.in_transfer_func); - surface->protected.public.in_transfer_func = NULL; + surface->public.in_transfer_func); + surface->public.in_transfer_func = NULL; } } @@ -82,7 +73,7 @@ static void destruct(struct surface *surface) void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id) { - struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; /*register_flip_interrupt(surface);*/ } @@ -91,7 +82,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct surface *surface = dm_alloc(sizeof(*surface)); + struct core_surface *surface = dm_alloc(sizeof(*surface)); if (NULL == surface) goto alloc_fail; @@ -101,7 +92,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) ++surface->ref_count; - return &surface->protected.public; + return &surface->public; construct_fail: dm_free(surface); @@ -146,7 +137,7 @@ const struct dc_surface_status *dc_surface_get_status( void dc_surface_retain(const struct dc_surface *dc_surface) { - struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); ASSERT(surface->ref_count > 0); ++surface->ref_count; @@ -154,7 +145,7 @@ void dc_surface_retain(const struct dc_surface *dc_surface) void dc_surface_release(const struct dc_surface *dc_surface) { - struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface); + struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); ASSERT(surface->ref_count > 0); --surface->ref_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d75368030917..30177f839b8a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -53,6 +53,10 @@ struct core_surface { struct dc_surface public; struct dc_surface_status status; struct dc_context *ctx; + + /* private to dc_surface.c */ + enum dc_irq_source irq_source; + int ref_count; }; struct core_gamma { -- GitLab From 8c4abe0b07a12c402f009abed8217e6c2e33a300 Mon Sep 17 00:00:00 2001 From: Ding Wang Date: Tue, 18 Jul 2017 17:18:11 -0400 Subject: [PATCH 0669/2898] drm/amd/display: fix decide_link_settings Signed-off-by: Ding Wang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 140 ++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 63 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ad1b90563eb6..de05ad09599f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -308,10 +308,8 @@ static void set_preferred_link_settings(struct dc *dc, { struct core_link *core_link = DC_LINK_TO_CORE(link); - core_link->public.verified_link_cap.lane_count = - link_setting->lane_count; - core_link->public.verified_link_cap.link_rate = - link_setting->link_rate; + core_link->public.preferred_link_setting = + *link_setting; dp_retrain_link_dp_test(core_link, link_setting, false); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 445cd226d36d..e90b3ebc8347 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -33,32 +33,6 @@ enum { LINK_TRAINING_MAX_CR_RETRY = 100 }; -static const struct dc_link_settings link_training_fallback_table[] = { -/* 4320 Mbytes/sec*/ -{ LANE_COUNT_FOUR, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, -/* 2160 Mbytes/sec*/ -{ LANE_COUNT_FOUR, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -/* 1080 Mbytes/sec*/ -{ LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -/* 648 Mbytes/sec*/ -{ LANE_COUNT_FOUR, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, -/* 2160 Mbytes/sec*/ -{ LANE_COUNT_TWO, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, -/* 1080 Mbytes/sec*/ -{ LANE_COUNT_TWO, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -/* 540 Mbytes/sec*/ -{ LANE_COUNT_TWO, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -/* 324 Mbytes/sec*/ -{ LANE_COUNT_TWO, LINK_RATE_LOW, LINK_SPREAD_DISABLED }, -/* 1080 Mbytes/sec*/ -{ LANE_COUNT_ONE, LINK_RATE_HIGH3, LINK_SPREAD_DISABLED }, -/* 540 Mbytes/sec*/ -{ LANE_COUNT_ONE, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED }, -/* 270 Mbytes/sec*/ -{ LANE_COUNT_ONE, LINK_RATE_HIGH, LINK_SPREAD_DISABLED }, -/* 162 Mbytes/sec*/ -{ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED } }; - static void wait_for_training_aux_rd_interval( struct core_link* link, uint32_t default_wait_in_micro_secs) @@ -1053,29 +1027,6 @@ bool perform_link_training_with_retries( return false; } -/*TODO add more check to see if link support request link configuration */ -static bool is_link_setting_supported( - const struct dc_link_settings *link_setting, - const struct dc_link_settings *max_link_setting) -{ - if (link_setting->lane_count > max_link_setting->lane_count || - link_setting->link_rate > max_link_setting->link_rate) - return false; - return true; -} - -static const uint32_t get_link_training_fallback_table_len( - struct core_link *link) -{ - return ARRAY_SIZE(link_training_fallback_table); -} - -static const struct dc_link_settings *get_link_training_fallback_table( - struct core_link *link, uint32_t i) -{ - return &link_training_fallback_table[i]; -} - static struct dc_link_settings get_max_link_cap(struct core_link *link) { /* Set Default link settings */ @@ -1284,6 +1235,32 @@ enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) } } +enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) +{ + switch (lane_count) { + case LANE_COUNT_ONE: + return LANE_COUNT_TWO; + case LANE_COUNT_TWO: + return LANE_COUNT_FOUR; + default: + return LANE_COUNT_UNKNOWN; + } +} + +enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) +{ + switch (link_rate) { + case LINK_RATE_LOW: + return LINK_RATE_HIGH; + case LINK_RATE_HIGH: + return LINK_RATE_HIGH2; + case LINK_RATE_HIGH2: + return LINK_RATE_HIGH3; + default: + return LINK_RATE_UNKNOWN; + } +} + /* * function: set link rate and lane count fallback based * on current link setting and last link training result @@ -1463,57 +1440,60 @@ void decide_link_settings(struct core_stream *stream, struct dc_link_settings *link_setting) { - const struct dc_link_settings *cur_ls; + struct dc_link_settings initial_link_setting = { + LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED}; + struct dc_link_settings current_link_setting = + initial_link_setting; struct core_link* link; uint32_t req_bw; uint32_t link_bw; - uint32_t i; req_bw = bandwidth_in_kbps_from_timing( &stream->public.timing); + link = stream->sink->link; + /* if preferred is specified through AMDDP, use it, if it's enough * to drive the mode */ - link = stream->sink->link; - - if ((link->public.reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) && - (link->public.reported_link_cap.link_rate <= - link->public.verified_link_cap.link_rate)) { + if (link->public.preferred_link_setting.lane_count != + LANE_COUNT_UNKNOWN && + link->public.preferred_link_setting.link_rate != + LINK_RATE_UNKNOWN) { + *link_setting = link->public.preferred_link_setting; + return; + } + /* search for the minimum link setting that: + * 1. is supported according to the link training result + * 2. could support the b/w requested by the timing + */ + while (current_link_setting.link_rate <= + link->public.max_link_setting.link_rate) { link_bw = bandwidth_in_kbps_from_link_settings( - &link->public.reported_link_cap); - - if (req_bw < link_bw) { - *link_setting = link->public.reported_link_cap; + ¤t_link_setting); + if (req_bw <= link_bw) { + *link_setting = current_link_setting; return; } - } - /* search for first suitable setting for the requested - * bandwidth - */ - for (i = 0; i < get_link_training_fallback_table_len(link); i++) { - - cur_ls = get_link_training_fallback_table(link, i); - - link_bw = - bandwidth_in_kbps_from_link_settings( - cur_ls); - - if (req_bw < link_bw) { - if (is_link_setting_supported( - cur_ls, - &link->public.max_link_setting)) { - *link_setting = *cur_ls; - return; - } + if (current_link_setting.lane_count < + link->public.max_link_setting.lane_count) { + current_link_setting.lane_count = + increase_lane_count( + current_link_setting.lane_count); + } else { + current_link_setting.link_rate = + increase_link_rate( + current_link_setting.link_rate); + current_link_setting.lane_count = + initial_link_setting.lane_count; } } BREAK_TO_DEBUGGER(); ASSERT(link->public.verified_link_cap.lane_count != - LANE_COUNT_UNKNOWN); + LANE_COUNT_UNKNOWN); *link_setting = link->public.verified_link_cap; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 617270829936..ee04c3562081 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -674,6 +674,7 @@ struct dc_link { struct dc_link_settings max_link_setting; struct dc_link_settings cur_link_settings; struct dc_lane_settings cur_lane_setting; + struct dc_link_settings preferred_link_setting; uint8_t ddc_hw_inst; -- GitLab From 0a87425a37b4c1f06d75949ea39e60455a2b0a4f Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 12 Jul 2017 22:35:52 -0400 Subject: [PATCH 0670/2898] drm/amd/display: move VGA to HWSS from TG Signed-off-by: Tony Cheng Reviewed-by: Zeyu Fan Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 11 +++++- .../display/dc/dce110/dce110_hw_sequencer.c | 3 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 +++++- .../display/dc/dcn10/dcn10_timing_generator.c | 38 ------------------- 4 files changed, 23 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 80ee1ac32fee..7feb1ca9b8c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -170,7 +170,12 @@ SR(DIO_MEM_PWR_CTRL), \ SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCFCLK_CNTL) + SR(DCFCLK_CNTL),\ + SR(DCFCLK_CNTL), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL) #endif #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -236,6 +241,10 @@ struct dce_hwseq_registers { uint32_t MPC_CRC_RESULT_GB; uint32_t MPC_CRC_RESULT_C; uint32_t MPC_CRC_RESULT_AR; + uint32_t D1VGA_CONTROL; + uint32_t D2VGA_CONTROL; + uint32_t D3VGA_CONTROL; + uint32_t D4VGA_CONTROL; #endif }; /* set field name */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index baafe6609d24..72e099953a05 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1198,7 +1198,8 @@ static void disable_vga_and_power_gate_all_controllers( for (i = 0; i < dc->res_pool->pipe_count; i++) { tg = dc->res_pool->timing_generators[i]; - tg->funcs->disable_vga(tg); + if (tg->funcs->disable_vga) + tg->funcs->disable_vga(tg); /* Enable CLOCK gating for each pipe BEFORE controller * powergating. */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ce7da8864507..64f2fd0d539e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -163,6 +163,15 @@ static void enable_power_gating_plane( REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); } +static void disable_vga( + struct dce_hwseq *hws) +{ + REG_WRITE(D1VGA_CONTROL, 0); + REG_WRITE(D2VGA_CONTROL, 0); + REG_WRITE(D3VGA_CONTROL, 0); + REG_WRITE(D4VGA_CONTROL, 0); +} + static void dpp_pg_control( struct dce_hwseq *hws, unsigned int dpp_inst, @@ -312,6 +321,8 @@ static void dcn10_init_hw(struct core_dc *dc) bios_golden_init(dc); + disable_vga(dc->hwseq); + for (i = 0; i < dc->link_count; i++) { /* Power up AND update implementation according to the * required signal (which may be different from the @@ -335,7 +346,6 @@ static void dcn10_init_hw(struct core_dc *dc) mpcc_cfg.top_of_tree = true; mpcc->funcs->set(mpcc, &mpcc_cfg); - tg->funcs->disable_vga(tg); /* Blank controller using driver code instead of * command table. */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index b2e796d87dac..0ef5d8f0625c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -447,43 +447,6 @@ static void tgn10_program_blank_color( OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); } -/** - * dcn10_dcn10_timing_generator_disable_vga - * Turn OFF VGA Mode and Timing - DxVGA_CONTROL - * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors; - */ -/* TODO FPGA FPGA setup is done by Diag which does not enable VGA mode. - * VGA is disable by ASIC default. This function is not needed for - * FPGA story. - * usage: - * init_hw within dc.c - * disable_vga_and_power_gate_all_controllers within dce110_hw_sequencer.c - * We may move init_hw into DC specific so that we can remove - * .disable_vga from upper layer stack - */ -static void tgn10_disable_vga( - struct timing_generator *tg) -{ - struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - - switch (tgn10->base.inst) { - case 0: - REG_WRITE(D1VGA_CONTROL, 0); - break; - case 1: - REG_WRITE(D2VGA_CONTROL, 0); - break; - case 2: - REG_WRITE(D2VGA_CONTROL, 0); - break; - case 3: - REG_WRITE(D4VGA_CONTROL, 0); - break; - default: - break; - } -} - static bool tgn10_validate_timing( struct timing_generator *tg, const struct dc_crtc_timing *timing) @@ -1144,7 +1107,6 @@ static struct timing_generator_funcs dcn10_tg_funcs = { .set_blank = tgn10_set_blank, .is_blanked = tgn10_is_blanked, .set_blank_color = tgn10_program_blank_color, - .disable_vga = tgn10_disable_vga, .did_triggered_reset_occur = tgn10_did_triggered_reset_occur, .enable_reset_trigger = tgn10_enable_reset_trigger, .disable_reset_trigger = tgn10_disable_reset_trigger, -- GitLab From 755d3bcfd44c16d344c7c6305ac6e7da19c27f5e Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Sun, 23 Jul 2017 14:17:09 -0400 Subject: [PATCH 0671/2898] drm/amd/display: Fix generic_reg_wait 1000ms case Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 87b7f6f8870e..f219bd2068e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -143,11 +143,10 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, for (i = 0; i <= time_out_num_tries; i++) { if (i) { - if (0 < delay_between_poll_us && delay_between_poll_us < 1000) - udelay(delay_between_poll_us); - - if (delay_between_poll_us > 1000) + if (delay_between_poll_us >= 1000) msleep(delay_between_poll_us/1000); + else if (delay_between_poll_us > 0) + udelay(delay_between_poll_us); } reg_val = dm_read_reg(ctx, addr); -- GitLab From 8748068764e7a50ac787c1c17f402f3fbbe97ccc Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Sun, 23 Jul 2017 15:18:57 -0400 Subject: [PATCH 0672/2898] drm/amd/display: add idle wait for passive surface update and modeset Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 +++++++++++++++++++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 18 +++++++++++++++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 4 ++++ .../gpu/drm/amd/display/dc/inc/core_types.h | 2 -- .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 3 +++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 1 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 ++ 7 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index de05ad09599f..9ef671735125 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -934,6 +934,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); + for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe); + } result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); program_timing_sync(core_dc, context); @@ -1537,6 +1541,21 @@ void dc_update_surfaces_and_stream(struct dc *dc, } } + if (update_type > UPDATE_TYPE_FAST) { + for (i = 0; i < surface_count; i++) { + struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->surface != surface) + continue; + + core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe_ctx); + } + } + } + if (surface_count == 0) core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 64f2fd0d539e..633d858caf6f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1739,6 +1739,7 @@ static void dcn10_apply_ctx_for_surface( mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); + old_pipe_ctx->top_pipe->opp->mpcc_disconnect_pending[old_pipe_ctx->mpcc->inst] = true; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -2012,6 +2013,20 @@ static void dcn10_log_hw_state(struct core_dc *dc) */ } +static void dcn10_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +{ + int i; + for (i = 0; i < MAX_PIPES; i++) { + if (!pipe_ctx->opp || !pipe_ctx->mpcc) + continue; + + if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { + pipe_ctx->mpcc->funcs->wait_for_idle(res_pool->mpcc[i]); + pipe_ctx->opp->mpcc_disconnect_pending[i] = false; + } + } +} + static bool dcn10_dummy_display_power_gating( struct core_dc *dc, uint8_t controller_id, @@ -2085,7 +2100,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_static_screen_control = set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, - .log_hw_state = dcn10_log_hw_state + .log_hw_state = dcn10_log_hw_state, + .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 669ac4b67ea9..c2aa69deecc2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -907,10 +907,14 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, const struct dcn10_opp_shift *opp_shift, const struct dcn10_opp_mask *opp_mask) { + int i; oppn10->base.ctx = ctx; oppn10->base.inst = inst; oppn10->base.funcs = &dcn10_opp_funcs; + for (i = 0; i < MAX_PIPES; i++) + oppn10->base.mpcc_disconnect_pending[i] = false; + oppn10->regs = regs; oppn10->opp_shift = opp_shift; oppn10->opp_mask = opp_mask; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 30177f839b8a..cc65cfdea66f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -38,10 +38,8 @@ struct core_stream; -#define MAX_PIPES 6 #define MAX_CLOCK_SOURCES 7 - /********* core_surface **********/ #define DC_SURFACE_TO_CORE(dc_surface) \ container_of(dc_surface, struct core_surface, public) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 907e0a9a8474..0212618a36be 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -32,6 +32,9 @@ /****************************************************************************** * Data types shared between different Virtual HW blocks ******************************************************************************/ + +#define MAX_PIPES 6 + struct gamma_curve { uint32_t offset; uint32_t segments_num; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 4b0c28eef352..57bdd6c8f955 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -207,6 +207,7 @@ struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; struct pwl_params regamma_params; + bool mpcc_disconnect_pending[MAX_PIPES]; const struct opp_funcs *funcs; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 4c027a98cfd3..22aca5a375ae 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -156,6 +156,8 @@ struct hw_sequencer_funcs { void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); void (*log_hw_state)(struct core_dc *dc); + + void (*wait_for_mpcc_disconnect)(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); }; void color_space_to_black_color( -- GitLab From 7db90a6b58761577596499ddd90f3c5ace2b716d Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 22 Jul 2017 21:58:08 -0400 Subject: [PATCH 0673/2898] drm/amd/display: move ocsc programming from opp to dpp Signed-off-by: Tony Cheng Reviewed-by: Yuehin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 148 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 46 +++++- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 147 ----------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 40 ----- .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 37 +++++ drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 21 --- .../gpu/drm/amd/display/dc/inc/hw/transform.h | 26 +-- 8 files changed, 242 insertions(+), 225 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index fff81a14b21c..0f3f1a31f10b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -988,11 +988,159 @@ static void dcn_dpp_set_gamut_remap( } } +static void oppn10_set_output_csc_default( + struct transform *xfm_base, + const struct default_adjustment *default_adjust) +{ + + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + uint32_t ocsc_mode = 0; + + if (default_adjust != NULL) { + switch (default_adjust->out_color_space) { + case COLOR_SPACE_SRGB: + case COLOR_SPACE_2020_RGB_FULLRANGE: + ocsc_mode = 0; + break; + case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + ocsc_mode = 1; + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + ocsc_mode = 2; + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_YCBCR: + ocsc_mode = 3; + break; + case COLOR_SPACE_UNKNOWN: + default: + break; + } + } + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + +} + +static void oppn10_program_color_matrix( + struct dcn10_dpp *xfm, + const struct out_csc_color_matrix *tbl_entry) +{ + uint32_t mode; + + REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); + + if (tbl_entry == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + if (mode == 4) { + /*R*/ + REG_SET_2(CM_OCSC_C11_C12, 0, + CM_OCSC_C11, tbl_entry->regval[0], + CM_OCSC_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_OCSC_C13_C14, 0, + CM_OCSC_C13, tbl_entry->regval[2], + CM_OCSC_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_OCSC_C21_C22, 0, + CM_OCSC_C21, tbl_entry->regval[4], + CM_OCSC_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_OCSC_C23_C24, 0, + CM_OCSC_C23, tbl_entry->regval[6], + CM_OCSC_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_OCSC_C31_C32, 0, + CM_OCSC_C31, tbl_entry->regval[8], + CM_OCSC_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_OCSC_C33_C34, 0, + CM_OCSC_C33, tbl_entry->regval[10], + CM_OCSC_C34, tbl_entry->regval[11]); + } else { + /*R*/ + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, tbl_entry->regval[0], + CM_COMB_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, tbl_entry->regval[2], + CM_COMB_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, tbl_entry->regval[4], + CM_COMB_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, tbl_entry->regval[6], + CM_COMB_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, tbl_entry->regval[8], + CM_COMB_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, tbl_entry->regval[10], + CM_COMB_C34, tbl_entry->regval[11]); + } +} + +static void oppn10_set_output_csc_adjustment( + struct transform *xfm_base, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + uint32_t ocsc_mode = 4; + + /** + *if (tbl_entry != NULL) { + * switch (tbl_entry->color_space) { + * case COLOR_SPACE_SRGB: + * case COLOR_SPACE_2020_RGB_FULLRANGE: + * ocsc_mode = 0; + * break; + * case COLOR_SPACE_SRGB_LIMITED: + * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + * ocsc_mode = 1; + * break; + * case COLOR_SPACE_YCBCR601: + * case COLOR_SPACE_YCBCR601_LIMITED: + * ocsc_mode = 2; + * break; + * case COLOR_SPACE_YCBCR709: + * case COLOR_SPACE_YCBCR709_LIMITED: + * case COLOR_SPACE_2020_YCBCR: + * ocsc_mode = 3; + * break; + * case COLOR_SPACE_UNKNOWN: + * default: + * break; + * } + *} + */ + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + oppn10_program_color_matrix(xfm, tbl_entry); +} + static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dpp_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, + .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, + .opp_set_csc_default = oppn10_set_output_csc_default, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index c1124e962d0e..693060e79d21 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -86,7 +86,14 @@ SRI(CM_COMB_C21_C22, CM, id),\ SRI(CM_COMB_C23_C24, CM, id),\ SRI(CM_COMB_C31_C32, CM, id),\ - SRI(CM_COMB_C33_C34, CM, id) + SRI(CM_COMB_C33_C34, CM, id),\ + SRI(CM_OCSC_CONTROL, CM, id), \ + SRI(CM_OCSC_C11_C12, CM, id), \ + SRI(CM_OCSC_C13_C14, CM, id), \ + SRI(CM_OCSC_C21_C22, CM, id), \ + SRI(CM_OCSC_C23_C24, CM, id), \ + SRI(CM_OCSC_C31_C32, CM, id), \ + SRI(CM_OCSC_C33_C34, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ @@ -194,7 +201,20 @@ TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh),\ TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh),\ TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh),\ - TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh) + TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh),\ + TF_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ + TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ + TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ + TF_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ + TF_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C14, mask_sh), \ + TF_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C21, mask_sh), \ + TF_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C22, mask_sh), \ + TF_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C23, mask_sh), \ + TF_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C24, mask_sh), \ + TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ + TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ + TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ + TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh) #define TF_REG_FIELD_LIST(type) \ @@ -300,7 +320,20 @@ type CM_COMB_C31; \ type CM_COMB_C32; \ type CM_COMB_C33; \ - type CM_COMB_C34 + type CM_COMB_C34; \ + type CM_OCSC_MODE; \ + type CM_OCSC_C11; \ + type CM_OCSC_C12; \ + type CM_OCSC_C13; \ + type CM_OCSC_C14; \ + type CM_OCSC_C21; \ + type CM_OCSC_C22; \ + type CM_OCSC_C23; \ + type CM_OCSC_C24; \ + type CM_OCSC_C31; \ + type CM_OCSC_C32; \ + type CM_OCSC_C33; \ + type CM_OCSC_C34 struct dcn_dpp_shift { TF_REG_FIELD_LIST(uint8_t); @@ -357,6 +390,13 @@ struct dcn_dpp_registers { uint32_t CM_COMB_C23_C24; uint32_t CM_COMB_C31_C32; uint32_t CM_COMB_C33_C34; + uint32_t CM_OCSC_CONTROL; + uint32_t CM_OCSC_C11_C12; + uint32_t CM_OCSC_C13_C14; + uint32_t CM_OCSC_C21_C22; + uint32_t CM_OCSC_C23_C24; + uint32_t CM_OCSC_C31_C32; + uint32_t CM_OCSC_C33_C34; }; struct dcn10_dpp { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 633d858caf6f..4cbca15e1cc5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1588,7 +1588,7 @@ static void update_dchubp_dpp( /*TODO add adjustments parameters*/ ocsc.out_color_space = pipe_ctx->stream->public.output_color_space; - pipe_ctx->opp->funcs->opp_set_csc_default(pipe_ctx->opp, &ocsc); + pipe_ctx->xfm->funcs->opp_set_csc_default(pipe_ctx->xfm, &ocsc); mi->funcs->mem_input_program_surface_config( mi, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index c2aa69deecc2..5cf985e4ffa9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -327,42 +327,7 @@ static void oppn10_program_fmt( return; } -static void oppn10_set_output_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - uint32_t ocsc_mode = 0; - - if (default_adjust != NULL) { - switch (default_adjust->out_color_space) { - case COLOR_SPACE_SRGB: - case COLOR_SPACE_2020_RGB_FULLRANGE: - ocsc_mode = 0; - break; - case COLOR_SPACE_SRGB_LIMITED: - case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - ocsc_mode = 1; - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - ocsc_mode = 2; - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_2020_YCBCR: - ocsc_mode = 3; - break; - case COLOR_SPACE_UNKNOWN: - default: - break; - } - } - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - -} /*program re gamma RAM B*/ static void opp_program_regamma_lutb_settings( struct output_pixel_processor *opp, @@ -714,117 +679,7 @@ static void oppn10_power_on_regamma_lut( } -static void oppn10_program_color_matrix(struct dcn10_opp *oppn10, - const struct out_csc_color_matrix *tbl_entry) -{ - uint32_t mode; - - REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); - - if (tbl_entry == NULL) { - BREAK_TO_DEBUGGER(); - return; - } - - - if (mode == 4) { - /*R*/ - REG_SET_2(CM_OCSC_C11_C12, 0, - CM_OCSC_C11, tbl_entry->regval[0], - CM_OCSC_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_OCSC_C13_C14, 0, - CM_OCSC_C13, tbl_entry->regval[2], - CM_OCSC_C14, tbl_entry->regval[3]); - /*G*/ - REG_SET_2(CM_OCSC_C21_C22, 0, - CM_OCSC_C21, tbl_entry->regval[4], - CM_OCSC_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_OCSC_C23_C24, 0, - CM_OCSC_C23, tbl_entry->regval[6], - CM_OCSC_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_OCSC_C31_C32, 0, - CM_OCSC_C31, tbl_entry->regval[8], - CM_OCSC_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_OCSC_C33_C34, 0, - CM_OCSC_C33, tbl_entry->regval[10], - CM_OCSC_C34, tbl_entry->regval[11]); - } else { - /*R*/ - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, tbl_entry->regval[0], - CM_COMB_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, tbl_entry->regval[2], - CM_COMB_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, tbl_entry->regval[4], - CM_COMB_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, tbl_entry->regval[6], - CM_COMB_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, tbl_entry->regval[8], - CM_COMB_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, tbl_entry->regval[10], - CM_COMB_C34, tbl_entry->regval[11]); - } -} - -static void oppn10_set_output_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry) -{ - - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - - - uint32_t ocsc_mode = 4; - - /** - *if (tbl_entry != NULL) { - * switch (tbl_entry->color_space) { - * case COLOR_SPACE_SRGB: - * case COLOR_SPACE_2020_RGB_FULLRANGE: - * ocsc_mode = 0; - * break; - * case COLOR_SPACE_SRGB_LIMITED: - * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - * ocsc_mode = 1; - * break; - * case COLOR_SPACE_YCBCR601: - * case COLOR_SPACE_YCBCR601_LIMITED: - * ocsc_mode = 2; - * break; - * case COLOR_SPACE_YCBCR709: - * case COLOR_SPACE_YCBCR709_LIMITED: - * case COLOR_SPACE_2020_YCBCR: - * ocsc_mode = 3; - * break; - * case COLOR_SPACE_UNKNOWN: - * default: - * break; - * } - *} - */ - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - oppn10_program_color_matrix(oppn10, tbl_entry); -} static void opp_program_regamma_lut( struct output_pixel_processor *opp, @@ -889,8 +744,6 @@ static void dcn10_opp_destroy(struct output_pixel_processor **opp) static struct opp_funcs dcn10_opp_funcs = { .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, - .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, - .opp_set_csc_default = oppn10_set_output_csc_default, .opp_set_dyn_expansion = oppn10_set_dyn_expansion, .opp_program_regamma_pwl = oppn10_set_regamma_pwl, .opp_set_regamma_mode = oppn10_set_regamma_mode, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index d9d66a4afb19..900298d6e5b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -46,21 +46,8 @@ #define OPP_REG_LIST_DCN10(id) \ OPP_REG_LIST_DCN(id), \ - SRI(CM_OCSC_C11_C12, CM, id), \ - SRI(CM_OCSC_C13_C14, CM, id), \ - SRI(CM_OCSC_C21_C22, CM, id), \ - SRI(CM_OCSC_C23_C24, CM, id), \ - SRI(CM_OCSC_C31_C32, CM, id), \ - SRI(CM_OCSC_C33_C34, CM, id), \ - SRI(CM_COMB_C11_C12, CM, id), \ - SRI(CM_COMB_C13_C14, CM, id), \ - SRI(CM_COMB_C21_C22, CM, id), \ - SRI(CM_COMB_C23_C24, CM, id), \ - SRI(CM_COMB_C31_C32, CM, id), \ - SRI(CM_COMB_C33_C34, CM, id), \ SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id), \ - SRI(CM_OCSC_CONTROL, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ SRI(CM_RGAM_RAMB_START_CNTL_R, CM, id), \ @@ -151,32 +138,7 @@ #define OPP_MASK_SH_LIST_DCN10(mask_sh) \ OPP_MASK_SH_LIST_DCN(mask_sh), \ OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C14, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C21, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C22, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C23, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C24, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ - OPP_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ - OPP_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh), \ - OPP_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh), \ - OPP_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh), \ - OPP_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh), \ - OPP_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh), \ - OPP_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh), \ - OPP_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh), \ - OPP_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh), \ - OPP_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh), \ - OPP_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh), \ - OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh), \ - OPP_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh), \ OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - OPP_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_G, mask_sh), \ @@ -414,7 +376,6 @@ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_MAP420MEM_PWR_FORCE; \ - type CM_OCSC_MODE; \ type CM_RGAM_RAMB_EXP_REGION_START_B; \ type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ type CM_RGAM_RAMB_EXP_REGION_START_G; \ @@ -630,7 +591,6 @@ struct dcn10_opp_registers { uint32_t FMT_CLAMP_CNTL; uint32_t FMT_DYNAMIC_EXP_CNTL; uint32_t FMT_MAP420_MEMORY_CONTROL; - uint32_t CM_OCSC_CONTROL; uint32_t CM_RGAM_RAMB_START_CNTL_B; uint32_t CM_RGAM_RAMB_START_CNTL_G; uint32_t CM_RGAM_RAMB_START_CNTL_R; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 0212618a36be..137b4c8dc9d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -28,6 +28,7 @@ #include "os_types.h" #include "fixed31_32.h" +#include "dc_hw_types.h" /****************************************************************************** * Data types shared between different Virtual HW blocks @@ -76,4 +77,40 @@ struct pwl_params { struct pwl_result_data rgb_resulted[256 + 3]; uint32_t hw_points_num; }; + +/* move to dpp + * while we are moving functionality out of opp to dpp to align + * HW programming to HW IP, we define these struct in hw_shared + * so we can still compile while refactoring + */ + +enum lb_pixel_depth { + /* do not change the values because it is used as bit vector */ + LB_PIXEL_DEPTH_18BPP = 1, + LB_PIXEL_DEPTH_24BPP = 2, + LB_PIXEL_DEPTH_30BPP = 4, + LB_PIXEL_DEPTH_36BPP = 8 +}; + +enum graphics_csc_adjust_type { + GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0, + GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */ + GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ +}; + +struct default_adjustment { + enum lb_pixel_depth lb_color_depth; + enum dc_color_space out_color_space; + enum dc_color_space in_color_space; + enum dc_color_depth color_depth; + enum pixel_format surface_pixel_format; + enum graphics_csc_adjust_type csc_adjust_type; + bool force_hw_default; +}; + +struct out_csc_color_matrix { + enum dc_color_space color_space; + uint16_t regval[12]; +}; + #endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 57bdd6c8f955..ef36ffdf2a68 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -217,22 +217,6 @@ enum fmt_stereo_action { FMT_STEREO_ACTION_UPDATE_POLARITY }; -enum graphics_csc_adjust_type { - GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0, - GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */ - GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ -}; - -struct default_adjustment { - enum lb_pixel_depth lb_color_depth; - enum dc_color_space out_color_space; - enum dc_color_space in_color_space; - enum dc_color_depth color_depth; - enum pixel_format surface_pixel_format; - enum graphics_csc_adjust_type csc_adjust_type; - bool force_hw_default; -}; - enum grph_color_adjust_option { GRPH_COLOR_MATRIX_HW_DEFAULT = 1, GRPH_COLOR_MATRIX_SW @@ -250,11 +234,6 @@ struct opp_grph_csc_adjustment { int32_t grph_hue; }; -struct out_csc_color_matrix { - enum dc_color_space color_space; - uint16_t regval[12]; -}; - /* Underlay related types */ struct hw_adjustment_range { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index b4862c376b41..132c5db07456 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -26,6 +26,7 @@ #ifndef __DAL_TRANSFORM_H__ #define __DAL_TRANSFORM_H__ +#include "hw_shared.h" #include "dc_hw_types.h" #include "fixed31_32.h" @@ -112,14 +113,6 @@ struct xfm_grph_csc_adjustment { enum graphics_gamut_adjust_type gamut_adjust_type; }; -enum lb_pixel_depth { - /* do not change the values because it is used as bit vector */ - LB_PIXEL_DEPTH_18BPP = 1, - LB_PIXEL_DEPTH_24BPP = 2, - LB_PIXEL_DEPTH_30BPP = 4, - LB_PIXEL_DEPTH_36BPP = 8 -}; - struct overscan_info { int left; int right; @@ -176,11 +169,6 @@ struct transform_funcs { void (*transform_set_scaler)(struct transform *xfm, const struct scaler_data *scl_data); - void (*transform_set_gamut_remap)( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust); - - void (*transform_set_pixel_storage_depth)( struct transform *xfm, enum lb_pixel_depth depth, @@ -190,6 +178,18 @@ struct transform_funcs { struct transform *xfm, struct scaler_data *scl_data, const struct scaling_taps *in_taps); + + void (*transform_set_gamut_remap)( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust); + + void (*opp_set_csc_default)( + struct transform *xfm, + const struct default_adjustment *default_adjust); + + void (*opp_set_csc_adjustment)( + struct transform *xfm, + const struct out_csc_color_matrix *tbl_entry); }; extern const uint16_t filter_2tap_16p[18]; -- GitLab From b6762f0c16a43c3d2867fb652f8efa429f70c83d Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 24 Jul 2017 11:18:29 -0400 Subject: [PATCH 0674/2898] drm/amd/display: add missing func for dce11o to avoid crash Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 72e099953a05..6ab9712ed808 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2582,6 +2582,11 @@ static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) dc->res_pool->transforms[fe_idx]); } +static void dce110_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +{ + /* do nothing*/ +} + static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, .init_hw = init_hw, @@ -2611,6 +2616,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, .setup_stereo = NULL, .set_avmute = dce110_set_avmute, + .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect }; bool dce110_hw_sequencer_construct(struct core_dc *dc) -- GitLab From e63825be738ea0bb975aee43b603ac5f0190d7a8 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Sun, 23 Jul 2017 16:45:45 -0400 Subject: [PATCH 0675/2898] drm/amd/display: fix YCbCr420 deep color mode not supported Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index a1eabc47558e..17b28280236f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -858,6 +858,8 @@ bool dcn_validate_bandwidth( - pipe->stream->public.timing.v_front_porch; v->vactive[input_idx] = pipe->stream->public.timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->public.timing.pix_clk_khz / 1000.0f; + if (pipe->stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + v->pixel_clock[input_idx] /= 2; if (!pipe->surface){ -- GitLab From c8d7bd8bd0c08aa9115589d264e274ed7fdf4c2e Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Sun, 23 Jul 2017 12:13:37 -0400 Subject: [PATCH 0676/2898] drm/amd/display: move RGAM programming from opp to dpp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 432 +++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 499 +++++++++++++++++- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 16 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 428 --------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.h | 492 +---------------- .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 7 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 7 - .../gpu/drm/amd/display/dc/inc/hw/transform.h | 29 + 8 files changed, 972 insertions(+), 938 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 0f3f1a31f10b..b6aaa95d442b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -1134,6 +1134,431 @@ static void oppn10_set_output_csc_adjustment( oppn10_program_color_matrix(xfm, tbl_entry); } +static void oppn10_power_on_regamma_lut( + struct transform *xfm_base, + bool power_on) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + REG_SET(CM_MEM_PWR_CTRL, 0, + RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); + +} + +static void opp_program_regamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + for (i = 0 ; i < num; i++) { + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); + + } + +} + +static void opp_configure_regamma_lut( + struct transform *xfm_base, + bool is_ram_a) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); +} + +/*program re gamma RAM A*/ +static void opp_program_regamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, + CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, + CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, + CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, + CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, + CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, + CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, + CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, + CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, + CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, + CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, + CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, + CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, + CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, + CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, + CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, + CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, + CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program re gamma RAM B*/ +static void opp_program_regamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, + CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, + CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, + CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, + CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, + CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, + CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, + CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, + CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, + CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, + CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, + CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, + CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, + CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, + CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, + CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, + CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, + CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + +} + +static bool oppn10_set_regamma_pwl( + struct transform *xfm_base, const struct pwl_params *params) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + oppn10_power_on_regamma_lut(xfm_base, true); + opp_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); + + if (xfm->is_write_to_ram_a_safe) + opp_program_regamma_luta_settings(xfm_base, params); + else + opp_program_regamma_lutb_settings(xfm_base, params); + + opp_program_regamma_lut( + xfm_base, params->rgb_resulted, params->hw_points_num); + + return true; +} + +static void oppn10_set_regamma_mode( + struct transform *xfm_base, + enum opp_regamma mode) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + uint32_t re_mode = 0; + uint32_t obuf_bypass = 0; /* need for pipe split */ + uint32_t obuf_hupscale = 0; + + switch (mode) { + case OPP_REGAMMA_BYPASS: + re_mode = 0; + break; + case OPP_REGAMMA_SRGB: + re_mode = 1; + break; + case OPP_REGAMMA_3_6: + re_mode = 2; + break; + case OPP_REGAMMA_USER: + re_mode = xfm->is_write_to_ram_a_safe ? 3 : 4; + xfm->is_write_to_ram_a_safe = !xfm->is_write_to_ram_a_safe; + break; + default: + break; + } + + REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode); + REG_UPDATE_2(OBUF_CONTROL, + OBUF_BYPASS, obuf_bypass, + OBUF_H_2X_UPSCALE_EN, obuf_hupscale); +} + static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dpp_set_scaler_manual_scale, @@ -1141,6 +1566,13 @@ static struct transform_funcs dcn10_dpp_funcs = { .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, .opp_set_csc_default = oppn10_set_output_csc_default, + .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, + .opp_program_regamma_lut = opp_program_regamma_lut, + .opp_configure_regamma_lut = opp_configure_regamma_lut, + .opp_program_regamma_lutb_settings = opp_program_regamma_lutb_settings, + .opp_program_regamma_luta_settings = opp_program_regamma_luta_settings, + .opp_program_regamma_pwl = oppn10_set_regamma_pwl, + .opp_set_regamma_mode = oppn10_set_regamma_mode }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 693060e79d21..34085c0818e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -71,7 +71,8 @@ SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ SRI(RECOUT_START, DSCL, id), \ - SRI(RECOUT_SIZE, DSCL, id) + SRI(RECOUT_SIZE, DSCL, id), \ + SRI(OBUF_CONTROL, DSCL, id) #define TF_REG_LIST_DCN10(id) \ TF_REG_LIST_DCN(id), \ @@ -93,7 +94,70 @@ SRI(CM_OCSC_C21_C22, CM, id), \ SRI(CM_OCSC_C23_C24, CM, id), \ SRI(CM_OCSC_C31_C32, CM, id), \ - SRI(CM_OCSC_C33_C34, CM, id) + SRI(CM_OCSC_C33_C34, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_RGAM_LUT_DATA, CM, id), \ + SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id),\ + SRI(CM_RGAM_LUT_INDEX, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMB_START_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMB_SLOPE_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_B, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_B, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_G, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_G, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL1_R, CM, id), \ + SRI(CM_RGAM_RAMB_END_CNTL2_R, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_0_1, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_2_3, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_4_5, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_6_7, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_8_9, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_10_11, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_12_13, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_14_15, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_16_17, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_18_19, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_20_21, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_22_23, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_24_25, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_26_27, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_28_29, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_30_31, CM, id), \ + SRI(CM_RGAM_RAMB_REGION_32_33, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMA_START_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_B, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_G, CM, id), \ + SRI(CM_RGAM_RAMA_SLOPE_CNTL_R, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_B, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_B, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_G, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_G, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL1_R, CM, id), \ + SRI(CM_RGAM_RAMA_END_CNTL2_R, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_0_1, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_2_3, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_4_5, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_6_7, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_8_9, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_10_11, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_12_13, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_14_15, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_16_17, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_18_19, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_20_21, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_22_23, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_24_25, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_26_27, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ + SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ + SRI(CM_RGAM_CONTROL, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ @@ -169,7 +233,8 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ - TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh) + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ + TF_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh) #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ TF_REG_LIST_SH_MASK_DCN(mask_sh),\ @@ -214,7 +279,186 @@ TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ - TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh) + TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ + TF_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ + TF_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh), \ + TF_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, mask_sh), \ + TF_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_SEL, mask_sh), \ + TF_SF(CM0_CM_RGAM_LUT_INDEX, CM_RGAM_LUT_INDEX, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_B, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_G, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_R, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL1_B, CM_RGAM_RAMB_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL1_G, CM_RGAM_RAMB_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL1_R, CM_RGAM_RAMB_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_B, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_G, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_R, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL1_B, CM_RGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL1_G, CM_RGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL1_R, CM_RGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ + TF_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh) #define TF_REG_FIELD_LIST(type) \ @@ -333,7 +577,187 @@ type CM_OCSC_C31; \ type CM_OCSC_C32; \ type CM_OCSC_C33; \ - type CM_OCSC_C34 + type CM_OCSC_C34; \ + type RGAM_MEM_PWR_FORCE; \ + type CM_RGAM_LUT_DATA; \ + type CM_RGAM_LUT_WRITE_EN_MASK; \ + type CM_RGAM_LUT_WRITE_SEL; \ + type CM_RGAM_LUT_INDEX; \ + type CM_RGAM_RAMB_EXP_REGION_START_B; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_RGAM_RAMB_EXP_REGION_START_G; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_RGAM_RAMB_EXP_REGION_START_R; \ + type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_RGAM_RAMB_EXP_REGION_END_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_RGAM_RAMB_EXP_REGION_END_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_RGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ + type CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION_START_B; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_RGAM_RAMA_EXP_REGION_START_G; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_RGAM_RAMA_EXP_REGION_START_R; \ + type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_RGAM_RAMA_EXP_REGION_END_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_RGAM_RAMA_EXP_REGION_END_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_RGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ + type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ + type CM_RGAM_LUT_MODE; \ + type OBUF_BYPASS; \ + type OBUF_H_2X_UPSCALE_EN struct dcn_dpp_shift { TF_REG_FIELD_LIST(uint8_t); @@ -397,6 +821,70 @@ struct dcn_dpp_registers { uint32_t CM_OCSC_C23_C24; uint32_t CM_OCSC_C31_C32; uint32_t CM_OCSC_C33_C34; + uint32_t CM_MEM_PWR_CTRL; + uint32_t CM_RGAM_LUT_DATA; + uint32_t CM_RGAM_LUT_WRITE_EN_MASK; + uint32_t CM_RGAM_LUT_INDEX; + uint32_t CM_RGAM_RAMB_START_CNTL_B; + uint32_t CM_RGAM_RAMB_START_CNTL_G; + uint32_t CM_RGAM_RAMB_START_CNTL_R; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_RGAM_RAMB_END_CNTL1_B; + uint32_t CM_RGAM_RAMB_END_CNTL2_B; + uint32_t CM_RGAM_RAMB_END_CNTL1_G; + uint32_t CM_RGAM_RAMB_END_CNTL2_G; + uint32_t CM_RGAM_RAMB_END_CNTL1_R; + uint32_t CM_RGAM_RAMB_END_CNTL2_R; + uint32_t CM_RGAM_RAMB_REGION_0_1; + uint32_t CM_RGAM_RAMB_REGION_2_3; + uint32_t CM_RGAM_RAMB_REGION_4_5; + uint32_t CM_RGAM_RAMB_REGION_6_7; + uint32_t CM_RGAM_RAMB_REGION_8_9; + uint32_t CM_RGAM_RAMB_REGION_10_11; + uint32_t CM_RGAM_RAMB_REGION_12_13; + uint32_t CM_RGAM_RAMB_REGION_14_15; + uint32_t CM_RGAM_RAMB_REGION_16_17; + uint32_t CM_RGAM_RAMB_REGION_18_19; + uint32_t CM_RGAM_RAMB_REGION_20_21; + uint32_t CM_RGAM_RAMB_REGION_22_23; + uint32_t CM_RGAM_RAMB_REGION_24_25; + uint32_t CM_RGAM_RAMB_REGION_26_27; + uint32_t CM_RGAM_RAMB_REGION_28_29; + uint32_t CM_RGAM_RAMB_REGION_30_31; + uint32_t CM_RGAM_RAMB_REGION_32_33; + uint32_t CM_RGAM_RAMA_START_CNTL_B; + uint32_t CM_RGAM_RAMA_START_CNTL_G; + uint32_t CM_RGAM_RAMA_START_CNTL_R; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_RGAM_RAMA_END_CNTL1_B; + uint32_t CM_RGAM_RAMA_END_CNTL2_B; + uint32_t CM_RGAM_RAMA_END_CNTL1_G; + uint32_t CM_RGAM_RAMA_END_CNTL2_G; + uint32_t CM_RGAM_RAMA_END_CNTL1_R; + uint32_t CM_RGAM_RAMA_END_CNTL2_R; + uint32_t CM_RGAM_RAMA_REGION_0_1; + uint32_t CM_RGAM_RAMA_REGION_2_3; + uint32_t CM_RGAM_RAMA_REGION_4_5; + uint32_t CM_RGAM_RAMA_REGION_6_7; + uint32_t CM_RGAM_RAMA_REGION_8_9; + uint32_t CM_RGAM_RAMA_REGION_10_11; + uint32_t CM_RGAM_RAMA_REGION_12_13; + uint32_t CM_RGAM_RAMA_REGION_14_15; + uint32_t CM_RGAM_RAMA_REGION_16_17; + uint32_t CM_RGAM_RAMA_REGION_18_19; + uint32_t CM_RGAM_RAMA_REGION_20_21; + uint32_t CM_RGAM_RAMA_REGION_22_23; + uint32_t CM_RGAM_RAMA_REGION_24_25; + uint32_t CM_RGAM_RAMA_REGION_26_27; + uint32_t CM_RGAM_RAMA_REGION_28_29; + uint32_t CM_RGAM_RAMA_REGION_30_31; + uint32_t CM_RGAM_RAMA_REGION_32_33; + uint32_t CM_RGAM_CONTROL; + uint32_t OBUF_CONTROL; }; struct dcn10_dpp { @@ -413,6 +901,7 @@ struct dcn10_dpp { int lb_pixel_depth_supported; int lb_memory_size; int lb_bits_per_entry; + bool is_write_to_ram_a_safe; }; bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4cbca15e1cc5..d61b63df16b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1054,25 +1054,25 @@ static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct core_stream *stream) { - struct output_pixel_processor *opp = pipe_ctx->opp; + struct transform *xfm = pipe_ctx->xfm; - if (opp == NULL) + if (xfm == NULL) return false; - opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->public.out_transfer_func && stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); } else if (dcn10_translate_regamma_to_hw_format( - stream->public.out_transfer_func, &opp->regamma_params)) { - opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + stream->public.out_transfer_func, &xfm->regamma_params)) { + xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); } else { - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 5cf985e4ffa9..f8e4724a629d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -37,38 +37,7 @@ #define CTX \ oppn10->base.ctx -static void oppn10_set_regamma_mode( - struct output_pixel_processor *opp, - enum opp_regamma mode) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - uint32_t re_mode = 0; - uint32_t obuf_bypass = 0; /* need for pipe split */ - uint32_t obuf_hupscale = 0; - - switch (mode) { - case OPP_REGAMMA_BYPASS: - re_mode = 0; - break; - case OPP_REGAMMA_SRGB: - re_mode = 1; - break; - case OPP_REGAMMA_3_6: - re_mode = 2; - break; - case OPP_REGAMMA_USER: - re_mode = oppn10->is_write_to_ram_a_safe ? 3 : 4; - oppn10->is_write_to_ram_a_safe = !oppn10->is_write_to_ram_a_safe; - break; - default: - break; - } - REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode); - REG_UPDATE_2(OBUF_CONTROL, - OBUF_BYPASS, obuf_bypass, - OBUF_H_2X_UPSCALE_EN, obuf_hupscale); -} /************* FORMATTER ************/ @@ -328,400 +297,6 @@ static void oppn10_program_fmt( } -/*program re gamma RAM B*/ -static void opp_program_regamma_lutb_settings( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - - REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, - CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, - CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, - CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, - CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, - CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, - CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, - CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, - CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, - CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, - CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, - CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, - CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, - CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, - CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, - CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, - CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, - CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); - -} - -/*program re gamma RAM A*/ -static void opp_program_regamma_luta_settings( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - - REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, - CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, - CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, - CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, - CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, - CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, - CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, - CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, - CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, - CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, - CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, - CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, - CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, - CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, - CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, - CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, - CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, - CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, - CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, - CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, - CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, - CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, - CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, - CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); -} - -static void opp_configure_regamma_lut( - struct output_pixel_processor *opp, - bool is_ram_a) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - - REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, - CM_RGAM_LUT_WRITE_EN_MASK, 7); - REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, - CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); - REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); -} - -static void oppn10_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - REG_SET(CM_MEM_PWR_CTRL, 0, - RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); - -} - - - - -static void opp_program_regamma_lut( - struct output_pixel_processor *opp, - const struct pwl_result_data *rgb, - uint32_t num) -{ - uint32_t i; - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - for (i = 0 ; i < num; i++) { - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); - - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); - - } - -} - -static bool oppn10_set_regamma_pwl( - struct output_pixel_processor *opp, const struct pwl_params *params) -{ - struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp); - - oppn10_power_on_regamma_lut(opp, true); - opp_configure_regamma_lut(opp, oppn10->is_write_to_ram_a_safe); - - if (oppn10->is_write_to_ram_a_safe) - opp_program_regamma_luta_settings(opp, params); - else - opp_program_regamma_lutb_settings(opp, params); - - opp_program_regamma_lut( - opp, params->rgb_resulted, params->hw_points_num); - - return true; -} static void oppn10_set_stereo_polarity( struct output_pixel_processor *opp, @@ -743,10 +318,7 @@ static void dcn10_opp_destroy(struct output_pixel_processor **opp) } static struct opp_funcs dcn10_opp_funcs = { - .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, .opp_set_dyn_expansion = oppn10_set_dyn_expansion, - .opp_program_regamma_pwl = oppn10_set_regamma_pwl, - .opp_set_regamma_mode = oppn10_set_regamma_mode, .opp_program_fmt = oppn10_program_fmt, .opp_program_bit_depth_reduction = oppn10_program_bit_depth_reduction, .opp_set_stereo_polarity = oppn10_set_stereo_polarity, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index 900298d6e5b5..790ce6014832 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -34,7 +34,6 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define OPP_REG_LIST_DCN(id) \ - SRI(OBUF_CONTROL, DSCL, id), \ SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ SRI(FMT_CONTROL, FMT, id), \ SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ @@ -45,73 +44,9 @@ SRI(FMT_MAP420_MEMORY_CONTROL, FMT, id) #define OPP_REG_LIST_DCN10(id) \ - OPP_REG_LIST_DCN(id), \ - SRI(CM_RGAM_LUT_WRITE_EN_MASK, CM, id), \ - SRI(CM_RGAM_CONTROL, CM, id), \ - SRI(CM_RGAM_RAMB_START_CNTL_B, CM, id), \ - SRI(CM_RGAM_RAMB_START_CNTL_G, CM, id), \ - SRI(CM_RGAM_RAMB_START_CNTL_R, CM, id), \ - SRI(CM_RGAM_RAMB_SLOPE_CNTL_B, CM, id), \ - SRI(CM_RGAM_RAMB_SLOPE_CNTL_G, CM, id), \ - SRI(CM_RGAM_RAMB_SLOPE_CNTL_R, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL1_B, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL2_B, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL1_G, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL2_G, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL1_R, CM, id), \ - SRI(CM_RGAM_RAMB_END_CNTL2_R, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_0_1, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_2_3, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_4_5, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_6_7, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_8_9, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_10_11, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_12_13, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_14_15, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_16_17, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_18_19, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_20_21, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_22_23, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_24_25, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_26_27, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_28_29, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_30_31, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_32_33, CM, id), \ - SRI(CM_RGAM_RAMA_START_CNTL_B, CM, id), \ - SRI(CM_RGAM_RAMA_START_CNTL_G, CM, id), \ - SRI(CM_RGAM_RAMA_START_CNTL_R, CM, id), \ - SRI(CM_RGAM_RAMA_SLOPE_CNTL_B, CM, id), \ - SRI(CM_RGAM_RAMA_SLOPE_CNTL_G, CM, id), \ - SRI(CM_RGAM_RAMA_SLOPE_CNTL_R, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL1_B, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL2_B, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL1_G, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL2_G, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL1_R, CM, id), \ - SRI(CM_RGAM_RAMA_END_CNTL2_R, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_0_1, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_2_3, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_4_5, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_6_7, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_8_9, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_10_11, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_12_13, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_14_15, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_16_17, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_18_19, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_20_21, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_22_23, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_24_25, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_26_27, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ - SRI(CM_RGAM_LUT_INDEX, CM, id), \ - SRI(CM_MEM_PWR_CTRL, CM, id), \ - SRI(CM_RGAM_LUT_DATA, CM, id) + OPP_REG_LIST_DCN(id) #define OPP_MASK_SH_LIST_DCN(mask_sh) \ - OPP_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh), \ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh), \ @@ -136,186 +71,7 @@ OPP_SF(FMT0_FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, mask_sh) #define OPP_MASK_SH_LIST_DCN10(mask_sh) \ - OPP_MASK_SH_LIST_DCN(mask_sh), \ - OPP_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ - OPP_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_B, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_G, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_START_CNTL_R, CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_B, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_G, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_SLOPE_CNTL_R, CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_B, CM_RGAM_RAMB_EXP_REGION_END_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_B, CM_RGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_G, CM_RGAM_RAMB_EXP_REGION_END_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_G, CM_RGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL1_R, CM_RGAM_RAMB_EXP_REGION_END_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_END_CNTL2_R, CM_RGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_B, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_G, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_START_CNTL_R, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_B, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_G, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_SLOPE_CNTL_R, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_B, CM_RGAM_RAMA_EXP_REGION_END_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_B, CM_RGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_G, CM_RGAM_RAMA_EXP_REGION_END_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_G, CM_RGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL1_R, CM_RGAM_RAMA_EXP_REGION_END_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_END_CNTL2_R, CM_RGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ - OPP_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_SEL, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_INDEX, CM_RGAM_LUT_INDEX, mask_sh), \ - OPP_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ - OPP_SF(CM0_CM_RGAM_LUT_DATA, CM_RGAM_LUT_DATA, mask_sh) + OPP_MASK_SH_LIST_DCN(mask_sh) #define OPP_DCN10_REG_FIELD_LIST(type) \ type DPG_EN; \ @@ -352,9 +108,6 @@ type CM_COMB_C32; \ type CM_COMB_C33; \ type CM_COMB_C34; \ - type CM_RGAM_LUT_MODE; \ - type OBUF_BYPASS; \ - type OBUF_H_2X_UPSCALE_EN; \ type FMT_TRUNCATE_EN; \ type FMT_TRUNCATE_DEPTH; \ type FMT_TRUNCATE_MODE; \ @@ -376,183 +129,6 @@ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_MAP420MEM_PWR_FORCE; \ - type CM_RGAM_RAMB_EXP_REGION_START_B; \ - type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ - type CM_RGAM_RAMB_EXP_REGION_START_G; \ - type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ - type CM_RGAM_RAMB_EXP_REGION_START_R; \ - type CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ - type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ - type CM_RGAM_RAMB_EXP_REGION_END_B; \ - type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; \ - type CM_RGAM_RAMB_EXP_REGION_END_BASE_B; \ - type CM_RGAM_RAMB_EXP_REGION_END_G; \ - type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G; \ - type CM_RGAM_RAMB_EXP_REGION_END_BASE_G; \ - type CM_RGAM_RAMB_EXP_REGION_END_R; \ - type CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R; \ - type CM_RGAM_RAMB_EXP_REGION_END_BASE_R; \ - type CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION_START_B; \ - type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ - type CM_RGAM_RAMA_EXP_REGION_START_G; \ - type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ - type CM_RGAM_RAMA_EXP_REGION_START_R; \ - type CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ - type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ - type CM_RGAM_RAMA_EXP_REGION_END_B; \ - type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B; \ - type CM_RGAM_RAMA_EXP_REGION_END_BASE_B; \ - type CM_RGAM_RAMA_EXP_REGION_END_G; \ - type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G; \ - type CM_RGAM_RAMA_EXP_REGION_END_BASE_G; \ - type CM_RGAM_RAMA_EXP_REGION_END_R; \ - type CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R; \ - type CM_RGAM_RAMA_EXP_REGION_END_BASE_R; \ - type CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ - type CM_RGAM_LUT_WRITE_EN_MASK; \ - type CM_RGAM_LUT_WRITE_SEL; \ - type CM_RGAM_LUT_INDEX; \ - type RGAM_MEM_PWR_FORCE; \ - type CM_RGAM_LUT_DATA; \ type FMT_STEREOSYNC_OVERRIDE struct dcn10_opp_shift { @@ -580,9 +156,6 @@ struct dcn10_opp_registers { uint32_t CM_COMB_C23_C24; uint32_t CM_COMB_C31_C32; uint32_t CM_COMB_C33_C34; - uint32_t CM_RGAM_LUT_WRITE_EN_MASK; - uint32_t CM_RGAM_CONTROL; - uint32_t OBUF_CONTROL; uint32_t FMT_BIT_DEPTH_CONTROL; uint32_t FMT_CONTROL; uint32_t FMT_DITHER_RAND_R_SEED; @@ -591,67 +164,6 @@ struct dcn10_opp_registers { uint32_t FMT_CLAMP_CNTL; uint32_t FMT_DYNAMIC_EXP_CNTL; uint32_t FMT_MAP420_MEMORY_CONTROL; - uint32_t CM_RGAM_RAMB_START_CNTL_B; - uint32_t CM_RGAM_RAMB_START_CNTL_G; - uint32_t CM_RGAM_RAMB_START_CNTL_R; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_RGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_RGAM_RAMB_END_CNTL1_B; - uint32_t CM_RGAM_RAMB_END_CNTL2_B; - uint32_t CM_RGAM_RAMB_END_CNTL1_G; - uint32_t CM_RGAM_RAMB_END_CNTL2_G; - uint32_t CM_RGAM_RAMB_END_CNTL1_R; - uint32_t CM_RGAM_RAMB_END_CNTL2_R; - uint32_t CM_RGAM_RAMB_REGION_0_1; - uint32_t CM_RGAM_RAMB_REGION_2_3; - uint32_t CM_RGAM_RAMB_REGION_4_5; - uint32_t CM_RGAM_RAMB_REGION_6_7; - uint32_t CM_RGAM_RAMB_REGION_8_9; - uint32_t CM_RGAM_RAMB_REGION_10_11; - uint32_t CM_RGAM_RAMB_REGION_12_13; - uint32_t CM_RGAM_RAMB_REGION_14_15; - uint32_t CM_RGAM_RAMB_REGION_16_17; - uint32_t CM_RGAM_RAMB_REGION_18_19; - uint32_t CM_RGAM_RAMB_REGION_20_21; - uint32_t CM_RGAM_RAMB_REGION_22_23; - uint32_t CM_RGAM_RAMB_REGION_24_25; - uint32_t CM_RGAM_RAMB_REGION_26_27; - uint32_t CM_RGAM_RAMB_REGION_28_29; - uint32_t CM_RGAM_RAMB_REGION_30_31; - uint32_t CM_RGAM_RAMB_REGION_32_33; - uint32_t CM_RGAM_RAMA_START_CNTL_B; - uint32_t CM_RGAM_RAMA_START_CNTL_G; - uint32_t CM_RGAM_RAMA_START_CNTL_R; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_RGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_RGAM_RAMA_END_CNTL1_B; - uint32_t CM_RGAM_RAMA_END_CNTL2_B; - uint32_t CM_RGAM_RAMA_END_CNTL1_G; - uint32_t CM_RGAM_RAMA_END_CNTL2_G; - uint32_t CM_RGAM_RAMA_END_CNTL1_R; - uint32_t CM_RGAM_RAMA_END_CNTL2_R; - uint32_t CM_RGAM_RAMA_REGION_0_1; - uint32_t CM_RGAM_RAMA_REGION_2_3; - uint32_t CM_RGAM_RAMA_REGION_4_5; - uint32_t CM_RGAM_RAMA_REGION_6_7; - uint32_t CM_RGAM_RAMA_REGION_8_9; - uint32_t CM_RGAM_RAMA_REGION_10_11; - uint32_t CM_RGAM_RAMA_REGION_12_13; - uint32_t CM_RGAM_RAMA_REGION_14_15; - uint32_t CM_RGAM_RAMA_REGION_16_17; - uint32_t CM_RGAM_RAMA_REGION_18_19; - uint32_t CM_RGAM_RAMA_REGION_20_21; - uint32_t CM_RGAM_RAMA_REGION_22_23; - uint32_t CM_RGAM_RAMA_REGION_24_25; - uint32_t CM_RGAM_RAMA_REGION_26_27; - uint32_t CM_RGAM_RAMA_REGION_28_29; - uint32_t CM_RGAM_RAMA_REGION_30_31; - uint32_t CM_RGAM_RAMA_REGION_32_33; - uint32_t CM_RGAM_LUT_INDEX; - uint32_t CM_MEM_PWR_CTRL; - uint32_t CM_RGAM_LUT_DATA; }; struct dcn10_opp { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 137b4c8dc9d5..589bddad7e66 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -113,4 +113,11 @@ struct out_csc_color_matrix { uint16_t regval[12]; }; +enum opp_regamma { + OPP_REGAMMA_BYPASS = 0, + OPP_REGAMMA_SRGB, + OPP_REGAMMA_3_6, + OPP_REGAMMA_USER +}; + #endif /* __DAL_HW_SHARED_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index ef36ffdf2a68..a43a09b3f414 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -196,13 +196,6 @@ struct pwl_float_data { struct fixed31_32 b; }; -enum opp_regamma { - OPP_REGAMMA_BYPASS = 0, - OPP_REGAMMA_SRGB, - OPP_REGAMMA_3_6, - OPP_REGAMMA_USER, -}; - struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 132c5db07456..f3d66752ed90 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -38,6 +38,7 @@ struct transform { const struct transform_funcs *funcs; struct dc_context *ctx; int inst; + struct pwl_params regamma_params; }; /* Colorimetry */ @@ -190,6 +191,34 @@ struct transform_funcs { void (*opp_set_csc_adjustment)( struct transform *xfm, const struct out_csc_color_matrix *tbl_entry); + + void (*opp_power_on_regamma_lut)( + struct transform *xfm, + bool power_on); + + void (*opp_program_regamma_lut)( + struct transform *xfm, + const struct pwl_result_data *rgb, + uint32_t num); + + void (*opp_configure_regamma_lut)( + struct transform *xfm, + bool is_ram_a); + + void (*opp_program_regamma_lutb_settings)( + struct transform *xfm, + const struct pwl_params *params); + + void (*opp_program_regamma_luta_settings)( + struct transform *xfm, + const struct pwl_params *params); + + bool (*opp_program_regamma_pwl)( + struct transform *xfm, const struct pwl_params *params); + + void (*opp_set_regamma_mode)( + struct transform *xfm_base, + enum opp_regamma mode); }; extern const uint16_t filter_2tap_16p[18]; -- GitLab From 08b1688620426ad3e09fc7a98aabc28dda30cde6 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Sun, 23 Jul 2017 18:30:15 -0400 Subject: [PATCH 0677/2898] drm/amd/display: Move DCHUBBUB block from MemInput to HW sequencer. Signed-off-by: Zeyu Fan Reviewed-by: Zeyu Fan Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 122 ++++++- .../drm/amd/display/dc/dce/dce_mem_input.c | 54 +--- .../display/dc/dce110/dce110_hw_sequencer.c | 1 + .../display/dc/dce120/dce120_hw_sequencer.c | 64 ++++ .../amd/display/dc/dce120/dce120_resource.c | 2 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 304 +++++++++++++++++- .../amd/display/dc/dcn10/dcn10_mem_input.c | 303 ----------------- .../amd/display/dc/dcn10/dcn10_mem_input.h | 76 +---- .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 7 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + 11 files changed, 492 insertions(+), 451 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9ef671735125..e89a2e5c8902 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2042,10 +2042,10 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) return false; } - if (mi->funcs->mem_input_update_dchub) - mi->funcs->mem_input_update_dchub(mi, dh_data); + if (core_dc->hwss.update_dchub) + core_dc->hwss.update_dchub(core_dc->hwseq, dh_data); else - ASSERT(mi->funcs->mem_input_update_dchub); + ASSERT(core_dc->hwss.update_dchub); return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 7feb1ca9b8c0..d62fc526783f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -116,6 +116,15 @@ .BLND_V_UPDATE_LOCK[3] = mmBLNDV_V_UPDATE_LOCK, \ .BLND_CONTROL[3] = mmBLNDV_CONTROL +#define HWSEQ_DCE120_REG_LIST() \ + HWSEQ_DCE10_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ + HWSEQ_PHYPLL_REG_LIST(CRTC), \ + SR(DCHUB_FB_LOCATION),\ + SR(DCHUB_AGP_BASE),\ + SR(DCHUB_AGP_BOT),\ + SR(DCHUB_AGP_TOP) + #define HWSEQ_DCE112_REG_LIST() \ HWSEQ_DCE10_REG_LIST(), \ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ @@ -146,8 +155,31 @@ SRII(OPP_PIPE_CONTROL, OPP_PIPE, 2), \ SRII(OPP_PIPE_CONTROL, OPP_PIPE, 3), \ SR(REFCLK_CNTL), \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ + SR(DCHUBBUB_ARB_SAT_LEVEL),\ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DCHUBBUB_ARB_DRAM_STATE_CNTL), \ SR(DCHUBBUB_TEST_DEBUG_INDEX), \ SR(DCHUBBUB_TEST_DEBUG_DATA), \ SR(DC_IP_REQUEST_CNTL), \ @@ -180,7 +212,13 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN1_REG_LIST()\ - HWSEQ_DCN_REG_LIST() + HWSEQ_DCN_REG_LIST(), \ + SR(DCHUBBUB_SDPIF_FB_TOP),\ + SR(DCHUBBUB_SDPIF_FB_BASE),\ + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SR(DCHUBBUB_SDPIF_AGP_BASE),\ + SR(DCHUBBUB_SDPIF_AGP_BOT),\ + SR(DCHUBBUB_SDPIF_AGP_TOP) #endif @@ -194,6 +232,11 @@ struct dce_hwseq_registers { uint32_t CRTC_H_BLANK_START_END[6]; uint32_t PIXEL_RATE_CNTL[6]; uint32_t PHYPLL_PIXEL_RATE_CNTL[6]; + /*DCHUB*/ + uint32_t DCHUB_FB_LOCATION; + uint32_t DCHUB_AGP_BASE; + uint32_t DCHUB_AGP_BOT; + uint32_t DCHUB_AGP_TOP; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) uint32_t OTG_GLOBAL_SYNC_STATUS[4]; @@ -202,10 +245,39 @@ struct dce_hwseq_registers { uint32_t DPP_CONTROL[4]; uint32_t OPP_PIPE_CONTROL[4]; uint32_t REFCLK_CNTL; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C; + uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; + uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; + uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; + uint32_t DCHUBBUB_ARB_SAT_LEVEL; + uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; uint32_t DCHUBBUB_GLOBAL_TIMER_CNTL; uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; uint32_t DCHUBBUB_TEST_DEBUG_INDEX; uint32_t DCHUBBUB_TEST_DEBUG_DATA; + uint32_t DCHUBBUB_SDPIF_FB_TOP; + uint32_t DCHUBBUB_SDPIF_FB_BASE; + uint32_t DCHUBBUB_SDPIF_FB_OFFSET; + uint32_t DCHUBBUB_SDPIF_AGP_BASE; + uint32_t DCHUBBUB_SDPIF_AGP_BOT; + uint32_t DCHUBBUB_SDPIF_AGP_TOP; uint32_t DC_IP_REQUEST_CNTL; uint32_t DOMAIN0_PG_CONFIG; uint32_t DOMAIN1_PG_CONFIG; @@ -300,11 +372,19 @@ struct dce_hwseq_registers { HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) +#define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ + SF(DCHUB_FB_LOCATION, FB_TOP, mask_sh),\ + SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\ + SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ + SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ + SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh) + #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ - HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) + HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ + HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh) #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ @@ -342,6 +422,12 @@ struct dce_hwseq_registers { HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) #endif @@ -349,6 +435,12 @@ struct dce_hwseq_registers { #define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_FB_TOP, SDPIF_FB_TOP, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh), \ + HWS_SF(, DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh) #endif @@ -370,7 +462,6 @@ struct dce_hwseq_registers { type PHYPLL_PIXEL_RATE_SOURCE; \ type PIXEL_RATE_PLL_SOURCE; \ -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ type VUPDATE_NO_LOCK_EVENT_OCCURRED; \ @@ -378,7 +469,25 @@ struct dce_hwseq_registers { type HUBP_CLOCK_ENABLE; \ type DPP_CLOCK_ENABLE; \ type DPPCLK_RATE_CONTROL; \ + type SDPIF_FB_TOP;\ + type SDPIF_FB_BASE;\ + type SDPIF_FB_OFFSET;\ + type SDPIF_AGP_BASE;\ + type SDPIF_AGP_BOT;\ + type SDPIF_AGP_TOP;\ + type FB_TOP;\ + type FB_BASE;\ + type FB_OFFSET;\ + type AGP_BASE;\ + type AGP_BOT;\ + type AGP_TOP;\ type DCHUBBUB_GLOBAL_TIMER_ENABLE; \ + type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ + type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ + type DCHUBBUB_ARB_SAT_LEVEL;\ + type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ type OPP_PIPE_CLOCK_EN;\ type IP_REQUEST_EN; \ type DOMAIN0_POWER_FORCEON; \ @@ -408,20 +517,15 @@ struct dce_hwseq_registers { type DCFCLK_GATE_DIS; \ type DCHUBBUB_GLOBAL_TIMER_REFDIV; \ type DENTIST_DPPCLK_WDIVIDER; -#endif struct dce_hwseq_shift { HWSEQ_REG_FIELD_LIST(uint8_t) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) HWSEQ_DCN_REG_FIELD_LIST(uint8_t) -#endif }; struct dce_hwseq_mask { HWSEQ_REG_FIELD_LIST(uint32_t) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) HWSEQ_DCN_REG_FIELD_LIST(uint32_t) -#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 157f4e1680e3..627669749740 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -656,57 +656,6 @@ static bool dce_mi_program_surface_flip_and_addr( return true; } -static void dce_mi_update_dchub(struct mem_input *mi, - struct dchub_init_data *dh_data) -{ - struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); - /* TODO: port code from dal2 */ - switch (dh_data->fb_mode) { - case FRAME_BUFFER_MODE_ZFB_ONLY: - /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ - REG_UPDATE_2(DCHUB_FB_LOCATION, - FB_TOP, 0, - FB_BASE, 0x0FFFF); - - REG_UPDATE(DCHUB_AGP_BASE, - AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUB_AGP_BOT, - AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUB_AGP_TOP, - AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - REG_UPDATE(DCHUB_AGP_BASE, - AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUB_AGP_BOT, - AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUB_AGP_TOP, - AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_LOCAL_ONLY: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - REG_UPDATE(DCHUB_AGP_BASE, - AGP_BASE, 0); - - REG_UPDATE(DCHUB_AGP_BOT, - AGP_BOT, 0x03FFFF); - - REG_UPDATE(DCHUB_AGP_TOP, - AGP_TOP, 0); - break; - default: - break; - } - - dh_data->dchub_initialzied = true; - dh_data->dchub_info_valid = false; -} - static struct mem_input_funcs dce_mi_funcs = { .mem_input_program_display_marks = dce_mi_program_display_marks, .allocate_mem_input = dce_mi_allocate_dmif, @@ -716,8 +665,7 @@ static struct mem_input_funcs dce_mi_funcs = { .mem_input_program_pte_vm = dce_mi_program_pte_vm, .mem_input_program_surface_config = dce_mi_program_surface_config, - .mem_input_is_flip_pending = dce_mi_is_flip_pending, - .mem_input_update_dchub = dce_mi_update_dchub + .mem_input_is_flip_pending = dce_mi_is_flip_pending }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6ab9712ed808..efba8d7964eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -49,6 +49,7 @@ #include "abm.h" #include "audio.h" #include "dce/dce_hwseq.h" +#include "reg_helper.h" /* include DCE11 register header files */ #include "dce/dce_11_0_d.h" diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index f5ffd8f6ed3b..91301b412aa0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -28,6 +28,7 @@ #include "core_dc.h" #include "core_types.h" #include "dce120_hw_sequencer.h" +#include "dce/dce_hwseq.h" #include "dce110/dce110_hw_sequencer.h" @@ -37,6 +38,15 @@ #include "vega10/soc15ip.h" #include "reg_helper.h" +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + struct dce120_hw_seq_reg_offsets { uint32_t crtc; }; @@ -184,6 +194,59 @@ static bool dce120_enable_display_power_gating( return false; } +static void dce120_update_dchub( + struct dce_hwseq *hws, + struct dchub_init_data *dh_data) +{ + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE_2(DCHUB_FB_LOCATION, + FB_TOP, 0, + FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, (dh_data->zfb_mc_base_addr + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUB_AGP_BASE, + AGP_BASE, 0); + + REG_UPDATE(DCHUB_AGP_BOT, + AGP_BOT, 0x03FFFF); + + REG_UPDATE(DCHUB_AGP_TOP, + AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + + + bool dce120_hw_sequencer_construct(struct core_dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and @@ -191,6 +254,7 @@ bool dce120_hw_sequencer_construct(struct core_dc *dc) */ dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating; + dc->hwss.update_dchub = dce120_update_dchub; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 82481247a812..f829b6e58bcb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -598,7 +598,7 @@ static struct stream_encoder *dce120_stream_encoder_create( mm ## block ## id ## _ ## reg_name static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCE112_REG_LIST() + HWSEQ_DCE120_REG_LIST() }; static const struct dce_hwseq_shift hwseq_shift = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d61b63df16b8..b7940876c761 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -218,6 +218,306 @@ static void dpp_pg_control( } } +static uint32_t convert_and_clamp( + uint32_t wm_ns, + uint32_t refclk_mhz, + uint32_t clamp_value) +{ + uint32_t ret_val = 0; + ret_val = wm_ns * refclk_mhz; + ret_val /= 1000; + + if (ret_val > clamp_value) + ret_val = clamp_value; + + return ret_val; +} + +static void program_watermarks( + struct dce_hwseq *hws, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz) +{ + uint32_t force_en = hws->ctx->dc->debug.disable_stutter ? 1 : 0; + /* + * Need to clamp to max of the register values (i.e. no wrap) + * for dcn1, all wm registers are 21-bit wide + */ + uint32_t prog_wm_value; + + /* Repeat for water mark set A, B, C and D. */ + /* clock state A */ + prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); + + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); + + + /* clock state B */ + prog_wm_value = convert_and_clamp( + watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state C */ + prog_wm_value = convert_and_clamp( + watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); + + /* clock state D */ + prog_wm_value = convert_and_clamp( + watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.urgent_ns, prog_wm_value); + + prog_wm_value = convert_and_clamp( + watermarks->d.pte_meta_urgent_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.pte_meta_urgent_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_ENTER_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "SR_EXIT_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.pstate_change_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n\n", + watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, + DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); + REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, + DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); + + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); + +#if 0 + REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); +#endif +} + + +static void dcn10_update_dchub( + struct dce_hwseq *hws, + struct dchub_init_data *dh_data) +{ + /* TODO: port code from dal2 */ + switch (dh_data->fb_mode) { + case FRAME_BUFFER_MODE_ZFB_ONLY: + /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ + REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, + SDPIF_FB_TOP, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, + SDPIF_FB_BASE, 0x0FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + + dh_data->zfb_size_in_byte - 1) >> 22); + break; + case FRAME_BUFFER_MODE_LOCAL_ONLY: + /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, + SDPIF_AGP_BASE, 0); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, + SDPIF_AGP_BOT, 0X03FFFF); + + REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, + SDPIF_AGP_TOP, 0); + break; + default: + break; + } + + dh_data->dchub_initialzied = true; + dh_data->dchub_info_valid = false; +} + static void hubp_pg_control( struct dce_hwseq *hws, unsigned int hubp_inst, @@ -1615,8 +1915,7 @@ static void program_all_pipe_in_tree( * this OTG. this is done only one time. */ /* watermark is for all pipes */ - pipe_ctx->mi->funcs->program_watermarks( - pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); + program_watermarks(dc->hwseq, &context->bw.dcn.watermarks, ref_clk_mhz); if (dc->public.debug.sanity_checks) { /* pstate stuck check after watermark update */ @@ -2078,6 +2377,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .set_plane_config = set_plane_config, .update_plane_addr = update_plane_addr, + .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, .set_input_transfer_func = dcn10_set_input_transfer_func, .set_output_transfer_func = dcn10_set_output_transfer_func, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 1f86295d6db6..c56a69b5a4d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -574,250 +574,6 @@ static void min10_setup( min10_vready_workaround(mem_input, pipe_dest); } -static uint32_t convert_and_clamp( - uint32_t wm_ns, - uint32_t refclk_mhz, - uint32_t clamp_value) -{ - uint32_t ret_val = 0; - ret_val = wm_ns * refclk_mhz; - ret_val /= 1000; - - if (ret_val > clamp_value) - ret_val = clamp_value; - - return ret_val; -} - -static void min10_program_watermarks( - struct mem_input *mem_input, - struct dcn_watermark_set *watermarks, - unsigned int refclk_mhz) -{ - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - uint32_t force_en = mem_input->ctx->dc->debug.disable_stutter ? 1 : 0; - /* - * Need to clamp to max of the register values (i.e. no wrap) - * for dcn1, all wm registers are 21-bit wide - */ - uint32_t prog_wm_value; - - /* Repeat for water mark set A, B, C and D. */ - /* clock state A */ - prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); - - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "URGENCY_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.urgent_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.pte_meta_urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n\n", - watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); - - - /* clock state B */ - prog_wm_value = convert_and_clamp( - watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "URGENCY_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->b.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.pte_meta_urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); - - /* clock state C */ - prog_wm_value = convert_and_clamp( - watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "URGENCY_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.pte_meta_urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); - - /* clock state D */ - prog_wm_value = convert_and_clamp( - watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "URGENCY_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.urgent_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp( - watermarks->d.pte_meta_urgent_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.pte_meta_urgent_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_ENTER_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "SR_EXIT_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); - dm_logger_write(mem_input->ctx->logger, LOG_HW_MARKS, - "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n\n", - watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); - - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); - REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, - DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); - REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, - DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); - - REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, - DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, - DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); - -#if 0 - REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, 1, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); -#endif -} - static void min10_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, @@ -855,63 +611,6 @@ static bool min10_is_flip_pending(struct mem_input *mem_input) return false; } -static void min10_update_dchub( - struct mem_input *mem_input, - struct dchub_init_data *dh_data) -{ - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - /* TODO: port code from dal2 */ - switch (dh_data->fb_mode) { - case FRAME_BUFFER_MODE_ZFB_ONLY: - /*For ZFB case need to put DCHUB FB BASE and TOP upside down to indicate ZFB mode*/ - REG_UPDATE(DCHUBBUB_SDPIF_FB_TOP, - SDPIF_FB_TOP, 0); - - REG_UPDATE(DCHUBBUB_SDPIF_FB_BASE, - SDPIF_FB_BASE, 0x0FFFF); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + - dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, dh_data->zfb_phys_addr_base >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, dh_data->zfb_mc_base_addr >> 22); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, (dh_data->zfb_mc_base_addr + - dh_data->zfb_size_in_byte - 1) >> 22); - break; - case FRAME_BUFFER_MODE_LOCAL_ONLY: - /*Should not touch FB LOCATION (done by VBIOS on AsicInit table)*/ - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BASE, - SDPIF_AGP_BASE, 0); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_BOT, - SDPIF_AGP_BOT, 0X03FFFF); - - REG_UPDATE(DCHUBBUB_SDPIF_AGP_TOP, - SDPIF_AGP_TOP, 0); - break; - default: - break; - } - - dh_data->dchub_initialzied = true; - dh_data->dchub_info_valid = false; -} - struct vm_system_aperture_param { PHYSICAL_ADDRESS_LOC sys_default; PHYSICAL_ADDRESS_LOC sys_low; @@ -1114,8 +813,6 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { min10_program_surface_config, .mem_input_is_flip_pending = min10_is_flip_pending, .mem_input_setup = min10_setup, - .program_watermarks = min10_program_watermarks, - .mem_input_update_dchub = min10_update_dchub, .mem_input_program_pte_vm = min10_program_pte_vm, .set_blank = min10_set_blank, .dcc_control = min10_dcc_control, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 0f4d247c4237..9130f5e0ab03 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -98,30 +98,6 @@ SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id),\ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ - SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ - SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ - SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ - SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ - SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ - SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ - SR(DCHUBBUB_ARB_SAT_LEVEL),\ - SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ /* todo: get these from GVM instead of reading registers ourselves */\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ @@ -154,12 +130,8 @@ SRI(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ - SR(DCHUBBUB_SDPIF_FB_TOP),\ SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET),\ - SR(DCHUBBUB_SDPIF_AGP_BASE),\ - SR(DCHUBBUB_SDPIF_AGP_BOT),\ - SR(DCHUBBUB_SDPIF_AGP_TOP) + SR(DCHUBBUB_SDPIF_FB_OFFSET) struct dcn_mi_registers { uint32_t DCHUBP_CNTL; @@ -248,42 +220,14 @@ struct dcn_mi_registers { uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB; uint32_t DCN_VM_SYSTEM_APERTURE_LOW_ADDR; uint32_t DCN_VM_SYSTEM_APERTURE_HIGH_ADDR; - uint32_t DCHUBBUB_SDPIF_FB_TOP; uint32_t DCHUBBUB_SDPIF_FB_BASE; uint32_t DCHUBBUB_SDPIF_FB_OFFSET; - uint32_t DCHUBBUB_SDPIF_AGP_BASE; - uint32_t DCHUBBUB_SDPIF_AGP_BOT; - uint32_t DCHUBBUB_SDPIF_AGP_TOP; uint32_t DCN_VM_FB_LOCATION_TOP; uint32_t DCN_VM_FB_LOCATION_BASE; uint32_t DCN_VM_FB_OFFSET; uint32_t DCN_VM_AGP_BASE; uint32_t DCN_VM_AGP_BOT; uint32_t DCN_VM_AGP_TOP; - uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A; - uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A; - uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A; - uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A; - uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A; - uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B; - uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B; - uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B; - uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B; - uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B; - uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C; - uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C; - uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C; - uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C; - uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C; - uint32_t DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D; - uint32_t DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D; - uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D; - uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D; - uint32_t DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D; - uint32_t DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL; - uint32_t DCHUBBUB_ARB_DRAM_STATE_CNTL; - uint32_t DCHUBBUB_ARB_SAT_LEVEL; - uint32_t DCHUBBUB_ARB_DF_REQ_OUTSTAND; /* GC registers. read only. temporary hack */ uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; @@ -418,13 +362,7 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ MI_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh),\ - MI_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh),\ - MI_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh),\ - MI_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh) + MI_SF(HUBPREQ0_DCN_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, mask_sh) #define MI_MASK_SH_LIST_DCN10(mask_sh)\ MI_MASK_SH_LIST_DCN(mask_sh),\ @@ -443,12 +381,8 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_FB_TOP, SDPIF_FB_TOP, mask_sh),\ MI_SF(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, mask_sh),\ MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh),\ - MI_SF(DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ @@ -611,12 +545,6 @@ struct dcn_mi_registers { type AGP_BASE;\ type AGP_BOT;\ type AGP_TOP;\ - type DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST;\ - type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ - type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ - type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ - type DCHUBBUB_ARB_SAT_LEVEL;\ - type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ /* todo: get these from GVM instead of reading registers ourselves */\ type PAGE_DIRECTORY_ENTRY_HI32;\ type PAGE_DIRECTORY_ENTRY_LO32;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 1b7d151a66f8..fd3ce742af2c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -75,11 +75,6 @@ struct mem_input { struct mem_input_funcs { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - void (*program_watermarks)( - struct mem_input *mem_input, - struct dcn_watermark_set *watermarks, - unsigned int refclk_period_ns); - void (*mem_input_setup)( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_regs, @@ -143,7 +138,7 @@ struct mem_input_funcs { bool (*mem_input_is_flip_pending)(struct mem_input *mem_input); void (*mem_input_update_dchub)(struct mem_input *mem_input, - struct dchub_init_data *dh_data); + struct dchub_init_data *dh_data); void (*set_blank)(struct mem_input *mi, bool blank); }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 22aca5a375ae..d865df802c88 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -79,6 +79,10 @@ struct hw_sequencer_funcs { const struct core_dc *dc, struct pipe_ctx *pipe_ctx); + void (*update_dchub)( + struct dce_hwseq *hws, + struct dchub_init_data *dh_data); + void (*update_pending_status)( struct pipe_ctx *pipe_ctx); -- GitLab From e12cfcb1d447cc937d1abc6f4aab8bbe5f88542e Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 20 Jul 2017 11:43:32 -0400 Subject: [PATCH 0678/2898] drm/amd/display: Roll core_surface into dc_surface Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 8 +- .../gpu/drm/amd/display/dc/calcs/dce_calcs.c | 16 +-- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 26 ++--- drivers/gpu/drm/amd/display/dc/core/dc.c | 73 ++++++------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 42 ++++---- .../gpu/drm/amd/display/dc/core/dc_stream.c | 4 +- .../gpu/drm/amd/display/dc/core/dc_surface.c | 44 ++++---- drivers/gpu/drm/amd/display/dc/dc.h | 45 ++++---- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 4 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 102 +++++++++--------- .../amd/display/dc/dce110/dce110_resource.c | 2 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 76 ++++++------- .../gpu/drm/amd/display/dc/inc/core_types.h | 16 +-- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- 16 files changed, 226 insertions(+), 240 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 44d85b77e252..b247904206ba 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2345,7 +2345,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *old_plane_state; const struct dc_stream *dc_stream_attach; - const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; @@ -2624,7 +2624,7 @@ void amdgpu_dm_atomic_commit_tail( struct dm_connector_state *con_old_state = to_dm_connector_state(old_conn_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - const struct dc_stream_status *status = NULL; + struct dc_stream_status *status = NULL; /* Skip any modesets/resets */ if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) @@ -2649,7 +2649,7 @@ void amdgpu_dm_atomic_commit_tail( /*TODO How it works with MPO ?*/ if (!dc_commit_surfaces_to_stream( dm->dc, - (const struct dc_surface **)status->surfaces, + status->surfaces, status->surface_count, new_acrtc_state->stream)) dm_error("%s: Failed to update stream scaling!\n", __func__); @@ -2793,7 +2793,7 @@ static uint32_t add_val_sets_surface( struct dc_validation_set *val_sets, uint32_t set_count, const struct dc_stream *stream, - const struct dc_surface *surface) + struct dc_surface *surface) { uint32_t i = 0, j = 0; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 87666987429e..5ef44ff4bcf8 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2597,12 +2597,12 @@ static void populate_initial_data( ASSERT(pipe[i].surface); if (num_displays == 0) { - if (!pipe[i].surface->public.visible) + if (!pipe[i].surface->visible) data->d0_underlay_mode = bw_def_underlay_only; else data->d0_underlay_mode = bw_def_blend; } else { - if (!pipe[i].surface->public.visible) + if (!pipe[i].surface->visible) data->d1_underlay_mode = bw_def_underlay_only; else data->d1_underlay_mode = bw_def_blend; @@ -2620,7 +2620,7 @@ static void populate_initial_data( data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->public.rotation) { + switch (pipe[i].surface->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); break; @@ -2636,7 +2636,7 @@ static void populate_initial_data( default: break; } - switch (pipe[i].surface->public.format) { + switch (pipe[i].surface->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_RGB565: @@ -2670,14 +2670,14 @@ static void populate_initial_data( data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( - pipe[i].bottom_pipe->surface->public.plane_size.grph.surface_pitch); + pipe[i].bottom_pipe->surface->plane_size.grph.surface_pitch); data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( pipe[i].bottom_pipe->scl_data.ratios.horz.value); data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( pipe[i].bottom_pipe->scl_data.ratios.vert.value); - switch (pipe[i].bottom_pipe->surface->public.rotation) { + switch (pipe[i].bottom_pipe->surface->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); break; @@ -2718,7 +2718,7 @@ static void populate_initial_data( data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->public.rotation) { + switch (pipe[i].surface->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); break; @@ -2734,7 +2734,7 @@ static void populate_initial_data( default: break; } - switch (pipe[i].surface->public.format) { + switch (pipe[i].surface->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 17b28280236f..1651b7548d40 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -238,11 +238,11 @@ static void pipe_ctx_to_e2e_pipe_params ( else if (pipe->bottom_pipe != NULL && pipe->bottom_pipe->surface == pipe->surface) input->src.is_hsplit = true; - input->src.dcc = pipe->surface->public.dcc.enable; + input->src.dcc = pipe->surface->dcc.enable; input->src.dcc_rate = 1; - input->src.meta_pitch = pipe->surface->public.dcc.grph.meta_pitch; + input->src.meta_pitch = pipe->surface->dcc.grph.meta_pitch; input->src.source_scan = dm_horz; - input->src.sw_mode = pipe->surface->public.tiling_info.gfx9.swizzle; + input->src.sw_mode = pipe->surface->tiling_info.gfx9.swizzle; input->src.viewport_width = pipe->scl_data.viewport.width; input->src.viewport_height = pipe->scl_data.viewport.height; @@ -251,7 +251,7 @@ static void pipe_ctx_to_e2e_pipe_params ( input->src.cur0_src_width = 128; /* TODO: Cursor calcs, not curently stored */ input->src.cur0_bpp = 32; - switch (pipe->surface->public.tiling_info.gfx9.swizzle) { + switch (pipe->surface->tiling_info.gfx9.swizzle) { /* for 4/8/16 high tiles */ case DC_SW_LINEAR: input->src.is_display_sw = 1; @@ -299,7 +299,7 @@ static void pipe_ctx_to_e2e_pipe_params ( break; } - switch (pipe->surface->public.rotation) { + switch (pipe->surface->rotation) { case ROTATION_ANGLE_0: case ROTATION_ANGLE_180: input->src.source_scan = dm_horz; @@ -314,7 +314,7 @@ static void pipe_ctx_to_e2e_pipe_params ( } /* TODO: Fix pixel format mappings */ - switch (pipe->surface->public.format) { + switch (pipe->surface->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: input->src.source_format = dm_420_8; @@ -455,7 +455,7 @@ static void dcn_bw_calc_rq_dlg_ttu( true, true, v->pte_enable == dcn_bw_yes, - pipe->surface->public.flip_immediate); + pipe->surface->flip_immediate); } static void dcn_dml_wm_override( @@ -527,7 +527,7 @@ static void dcn_dml_wm_override( true, true, v->pte_enable == dcn_bw_yes, - pipe->surface->public.flip_immediate); + pipe->surface->flip_immediate); in_idx++; } dm_free(input); @@ -883,7 +883,7 @@ bool dcn_validate_bandwidth( v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width; v->scaler_recout_height[input_idx] = pipe->scl_data.recout.height; if (pipe->bottom_pipe && pipe->bottom_pipe->surface == pipe->surface) { - if (pipe->surface->public.rotation % 2 == 0) { + if (pipe->surface->rotation % 2 == 0) { int viewport_end = pipe->scl_data.viewport.width + pipe->scl_data.viewport.x; int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.width @@ -912,17 +912,17 @@ bool dcn_validate_bandwidth( + pipe->bottom_pipe->scl_data.recout.width; } - v->dcc_enable[input_idx] = pipe->surface->public.dcc.enable ? dcn_bw_yes : dcn_bw_no; + v->dcc_enable[input_idx] = pipe->surface->dcc.enable ? dcn_bw_yes : dcn_bw_no; v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs( - pipe->surface->public.format); + pipe->surface->format); v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs( - pipe->surface->public.tiling_info.gfx9.swizzle); + pipe->surface->tiling_info.gfx9.swizzle); v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->scl_data.lb_params.depth); v->override_hta_ps[input_idx] = pipe->scl_data.taps.h_taps; v->override_vta_ps[input_idx] = pipe->scl_data.taps.v_taps; v->override_hta_pschroma[input_idx] = pipe->scl_data.taps.h_taps_c; v->override_vta_pschroma[input_idx] = pipe->scl_data.taps.v_taps_c; - v->source_scan[input_idx] = (pipe->surface->public.rotation % 2) ? dcn_bw_vert : dcn_bw_hor; + v->source_scan[input_idx] = (pipe->surface->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; } if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e89a2e5c8902..569310ab116d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -946,8 +946,8 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c const struct core_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].surface_count; j++) { - struct core_surface *surface = - DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]); + const struct dc_surface *surface = + context->stream_status[i].surfaces[j]; core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); @@ -1098,7 +1098,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) bool dc_commit_surfaces_to_stream( struct dc *dc, - const struct dc_surface **new_surfaces, + struct dc_surface **new_surfaces, uint8_t new_surface_count, const struct dc_stream *dc_stream) { @@ -1189,7 +1189,7 @@ static bool is_surface_in_context( for (j = 0; j < MAX_PIPES; j++) { const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (surface == &pipe_ctx->surface->public) { + if (surface == pipe_ctx->surface) { return true; } } @@ -1422,7 +1422,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { - const struct dc_surface *new_surfaces[MAX_SURFACES] = {0}; + struct dc_surface *new_surfaces[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) new_surfaces[i] = srf_updates[i].surface; @@ -1448,46 +1448,45 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* save update parameters into surface */ for (i = 0; i < surface_count; i++) { - struct core_surface *surface = - DC_SURFACE_TO_CORE(srf_updates[i].surface); + struct dc_surface *surface = srf_updates[i].surface; if (srf_updates[i].flip_addr) { - surface->public.address = srf_updates[i].flip_addr->address; - surface->public.flip_immediate = + surface->address = srf_updates[i].flip_addr->address; + surface->flip_immediate = srf_updates[i].flip_addr->flip_immediate; } if (srf_updates[i].scaling_info) { - surface->public.scaling_quality = + surface->scaling_quality = srf_updates[i].scaling_info->scaling_quality; - surface->public.dst_rect = + surface->dst_rect = srf_updates[i].scaling_info->dst_rect; - surface->public.src_rect = + surface->src_rect = srf_updates[i].scaling_info->src_rect; - surface->public.clip_rect = + surface->clip_rect = srf_updates[i].scaling_info->clip_rect; } if (srf_updates[i].plane_info) { - surface->public.color_space = + surface->color_space = srf_updates[i].plane_info->color_space; - surface->public.format = + surface->format = srf_updates[i].plane_info->format; - surface->public.plane_size = + surface->plane_size = srf_updates[i].plane_info->plane_size; - surface->public.rotation = + surface->rotation = srf_updates[i].plane_info->rotation; - surface->public.horizontal_mirror = + surface->horizontal_mirror = srf_updates[i].plane_info->horizontal_mirror; - surface->public.stereo_format = + surface->stereo_format = srf_updates[i].plane_info->stereo_format; - surface->public.tiling_info = + surface->tiling_info = srf_updates[i].plane_info->tiling_info; - surface->public.visible = + surface->visible = srf_updates[i].plane_info->visible; - surface->public.per_pixel_alpha = + surface->per_pixel_alpha = srf_updates[i].plane_info->per_pixel_alpha; - surface->public.dcc = + surface->dcc = srf_updates[i].plane_info->dcc; } @@ -1503,31 +1502,31 @@ void dc_update_surfaces_and_stream(struct dc *dc, } if (srf_updates[i].gamma && - srf_updates[i].gamma != surface->public.gamma_correction) { - if (surface->public.gamma_correction != NULL) - dc_gamma_release(&surface->public. + srf_updates[i].gamma != surface->gamma_correction) { + if (surface->gamma_correction != NULL) + dc_gamma_release(&surface-> gamma_correction); dc_gamma_retain(srf_updates[i].gamma); - surface->public.gamma_correction = + surface->gamma_correction = srf_updates[i].gamma; } if (srf_updates[i].in_transfer_func && - srf_updates[i].in_transfer_func != surface->public.in_transfer_func) { - if (surface->public.in_transfer_func != NULL) + srf_updates[i].in_transfer_func != surface->in_transfer_func) { + if (surface->in_transfer_func != NULL) dc_transfer_func_release( - surface->public. + surface-> in_transfer_func); dc_transfer_func_retain( srf_updates[i].in_transfer_func); - surface->public.in_transfer_func = + surface->in_transfer_func = srf_updates[i].in_transfer_func; } if (srf_updates[i].hdr_static_metadata) - surface->public.hdr_static_ctx = + surface->hdr_static_ctx = *(srf_updates[i].hdr_static_metadata); } @@ -1543,12 +1542,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (update_type > UPDATE_TYPE_FAST) { for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->surface != srf_updates[i].surface) continue; core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe_ctx); @@ -1561,7 +1558,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + struct dc_surface *surface = srf_updates[i].surface; for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1613,7 +1610,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface); + struct dc_surface *surface = srf_updates[i].surface; if (update_type == UPDATE_TYPE_MED) core_dc->hwss.apply_ctx_for_surface( @@ -1654,7 +1651,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (j = 0; j < surface_count; j++) { if (update_type != UPDATE_TYPE_FULL && - srf_updates[j].surface != &pipe_ctx->surface->public) + srf_updates[j].surface != pipe_ctx->surface) continue; if (!pipe_ctx->surface || pipe_ctx->top_pipe) continue; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 5acc5cdcda16..303c95432d5b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -428,7 +428,7 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_surface *surface = pipe_ctx->surface; const struct dc_stream *stream = &pipe_ctx->stream->public; struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; @@ -446,8 +446,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) sec_split = false; } - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); /* The actual clip is an intersection between stream @@ -527,14 +527,14 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_surface *surface = pipe_ctx->surface; struct core_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; struct rect surf_clip = surface->clip_rect; int recout_full_x, recout_full_y; - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); pipe_ctx->scl_data.recout.x = stream->public.dst.x; @@ -605,7 +605,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_surface *surface = pipe_ctx->surface; struct core_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; const int in_w = stream->public.src.width; @@ -613,8 +613,8 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) const int out_w = stream->public.dst.width; const int out_h = stream->public.dst.height; - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( @@ -647,13 +647,13 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { struct scaler_data *data = &pipe_ctx->scl_data; - struct rect src = pipe_ctx->surface->public.src_rect; + struct rect src = pipe_ctx->surface->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&src); rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); @@ -803,8 +803,8 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); - if (pipe_ctx->surface->public.rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->public.rotation == ROTATION_ANGLE_270) { + if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || + pipe_ctx->surface->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); } @@ -812,7 +812,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = &pipe_ctx->surface->public; + const struct dc_surface *surface = pipe_ctx->surface; struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; struct view recout_skip = { 0 }; bool res = false; @@ -822,7 +822,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) * Inits require viewport, taps, ratios and recout of split pipe */ pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( - pipe_ctx->surface->public.format); + pipe_ctx->surface->format); calculate_scaling_ratios(pipe_ctx); @@ -1029,7 +1029,7 @@ static int acquire_first_split_pipe( #endif bool resource_attach_surfaces_to_context( - const struct dc_surface * const *surfaces, + struct dc_surface * const *surfaces, int surface_count, const struct dc_stream *dc_stream, struct validate_context *context, @@ -1077,7 +1077,7 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { - struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]); + struct dc_surface *surface = surfaces[i]; struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( context, pool, dc_stream); @@ -1358,7 +1358,7 @@ bool resource_is_stream_unchanged( static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { - struct core_surface *surface = to_pipe_ctx->surface; + struct dc_surface *surface = to_pipe_ctx->surface; struct core_stream *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; @@ -2072,7 +2072,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, - struct core_surface *surface, + struct dc_surface *surface, struct core_stream *stream) { uint16_t i = 0; @@ -2083,7 +2083,7 @@ static void set_hdr_static_info_packet( if (!surface) return; - hdr_metadata = surface->public.hdr_static_ctx; + hdr_metadata = surface->hdr_static_ctx; if (!hdr_metadata.hdr_supported) return; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index ead7b63caab7..73712fd6f64a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -157,7 +157,7 @@ struct dc_stream *dc_create_stream_for_sink( return NULL; } -const struct dc_stream_status *dc_stream_get_status( +struct dc_stream_status *dc_stream_get_status( const struct dc_stream *dc_stream) { uint8_t i; @@ -252,7 +252,7 @@ bool dc_stream_set_cursor_position( !pipe_ctx->ipp || !pipe_ctx->surface) continue; - if (pipe_ctx->surface->public.address.type + if (pipe_ctx->surface->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) pos_cpy.enable = false; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 3784358d35ef..9a21ea71f4b3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -47,33 +47,32 @@ struct gamma { /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct core_surface *surface) +static bool construct(struct dc_context *ctx, struct dc_surface *surface) { surface->ctx = ctx; - memset(&surface->public.hdr_static_ctx, + memset(&surface->hdr_static_ctx, 0, sizeof(struct dc_hdr_static_metadata)); return true; } -static void destruct(struct core_surface *surface) +static void destruct(struct dc_surface *surface) { - if (surface->public.gamma_correction != NULL) { - dc_gamma_release(&surface->public.gamma_correction); + if (surface->gamma_correction != NULL) { + dc_gamma_release(&surface->gamma_correction); } - if (surface->public.in_transfer_func != NULL) { + if (surface->in_transfer_func != NULL) { dc_transfer_func_release( - surface->public.in_transfer_func); - surface->public.in_transfer_func = NULL; + surface->in_transfer_func); + surface->in_transfer_func = NULL; } } /******************************************************************************* * Public functions ******************************************************************************/ -void enable_surface_flip_reporting(struct dc_surface *dc_surface, +void enable_surface_flip_reporting(struct dc_surface *surface, uint32_t controller_id) { - struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; /*register_flip_interrupt(surface);*/ } @@ -82,7 +81,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_surface *surface = dm_alloc(sizeof(*surface)); + struct dc_surface *surface = dm_alloc(sizeof(*surface)); if (NULL == surface) goto alloc_fail; @@ -92,7 +91,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) ++surface->ref_count; - return &surface->public; + return surface; construct_fail: dm_free(surface); @@ -104,20 +103,19 @@ struct dc_surface *dc_create_surface(const struct dc *dc) const struct dc_surface_status *dc_surface_get_status( const struct dc_surface *dc_surface) { - struct dc_surface_status *surface_status; - struct core_surface *core_surface = DC_SURFACE_TO_CORE(dc_surface); + const struct dc_surface_status *surface_status; struct core_dc *core_dc; int i; if (!dc_surface || - !core_surface->ctx || - !core_surface->ctx->dc) { + !dc_surface->ctx || + !dc_surface->ctx->dc) { ASSERT(0); return NULL; /* remove this if above assert never hit */ } - surface_status = &core_surface->status; - core_dc = DC_TO_CORE(core_surface->ctx->dc); + surface_status = &dc_surface->status; + core_dc = DC_TO_CORE(dc_surface->ctx->dc); if (core_dc->current_context == NULL) return NULL; @@ -126,7 +124,7 @@ const struct dc_surface_status *dc_surface_get_status( struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != core_surface) + if (pipe_ctx->surface != dc_surface) continue; core_dc->hwss.update_pending_status(pipe_ctx); @@ -135,18 +133,14 @@ const struct dc_surface_status *dc_surface_get_status( return surface_status; } -void dc_surface_retain(const struct dc_surface *dc_surface) +void dc_surface_retain(struct dc_surface *surface) { - struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); - ASSERT(surface->ref_count > 0); ++surface->ref_count; } -void dc_surface_release(const struct dc_surface *dc_surface) +void dc_surface_release(struct dc_surface *surface) { - struct core_surface *surface = DC_SURFACE_TO_CORE(dc_surface); - ASSERT(surface->ref_count > 0); --surface->ref_count; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ee04c3562081..b14bad10db97 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -299,6 +299,18 @@ struct dc_transfer_func { int ref_count; }; +/* + * This structure is filled in by dc_surface_get_status and contains + * the last requested address and the currently active address so the called + * can determine if there are any outstanding flips + */ +struct dc_surface_status { + struct dc_plane_address requested_address; + struct dc_plane_address current_address; + bool is_flip_pending; + bool is_right_eye; +}; + struct dc_surface { struct dc_plane_address address; @@ -325,6 +337,14 @@ struct dc_surface { bool visible; bool flip_immediate; bool horizontal_mirror; + + /* private to DC core */ + struct dc_surface_status status; + struct dc_context *ctx; + + /* private to dc_surface.c */ + enum dc_irq_source irq_source; + int ref_count; }; struct dc_plane_info { @@ -348,7 +368,7 @@ struct dc_scaling_info { }; struct dc_surface_update { - const struct dc_surface *surface; + struct dc_surface *surface; /* isr safe update parameters. null means no updates */ struct dc_flip_addrs *flip_addr; @@ -362,17 +382,6 @@ struct dc_surface_update { struct dc_transfer_func *in_transfer_func; struct dc_hdr_static_metadata *hdr_static_metadata; }; -/* - * This structure is filled in by dc_surface_get_status and contains - * the last requested address and the currently active address so the called - * can determine if there are any outstanding flips - */ -struct dc_surface_status { - struct dc_plane_address requested_address; - struct dc_plane_address current_address; - bool is_flip_pending; - bool is_right_eye; -}; /* * Create a new surface with default parameters; @@ -381,8 +390,8 @@ struct dc_surface *dc_create_surface(const struct dc *dc); const struct dc_surface_status *dc_surface_get_status( const struct dc_surface *dc_surface); -void dc_surface_retain(const struct dc_surface *dc_surface); -void dc_surface_release(const struct dc_surface *dc_surface); +void dc_surface_retain(struct dc_surface *dc_surface); +void dc_surface_release(struct dc_surface *dc_surface); void dc_gamma_retain(const struct dc_gamma *dc_gamma); void dc_gamma_release(const struct dc_gamma **dc_gamma); @@ -416,7 +425,7 @@ struct dc_flip_addrs { bool dc_commit_surfaces_to_stream( struct dc *dc, - const struct dc_surface **dc_surfaces, + struct dc_surface **dc_surfaces, uint8_t surface_count, const struct dc_stream *stream); @@ -545,7 +554,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, */ struct dc_validation_set { const struct dc_stream *stream; - const struct dc_surface *surfaces[MAX_SURFACES]; + struct dc_surface *surfaces[MAX_SURFACES]; uint8_t surface_count; }; @@ -627,7 +636,7 @@ void dc_stream_release(const struct dc_stream *dc_stream); struct dc_stream_status { int primary_otg_inst; int surface_count; - const struct dc_surface *surfaces[MAX_SURFACE_NUM]; + struct dc_surface *surfaces[MAX_SURFACE_NUM]; /* * link this stream passes through @@ -635,7 +644,7 @@ struct dc_stream_status { const struct dc_link *link; }; -const struct dc_stream_status *dc_stream_get_status( +struct dc_stream_status *dc_stream_get_status( const struct dc_stream *dc_stream); enum surface_update_type dc_check_update_surfaces_for_stream( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index cc3178acfc54..a8c254f66c98 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -193,9 +193,9 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, } /* Only use LUT for 8 bit formats */ -bool dce_use_lut(const struct core_surface *surface) +bool dce_use_lut(const struct dc_surface *surface) { - switch (surface->public.format) { + switch (surface->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index d62fc526783f..ade7507e99c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -552,5 +552,5 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst); -bool dce_use_lut(const struct core_surface *surface); +bool dce_use_lut(const struct dc_surface *surface); #endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index efba8d7964eb..cf6bf2098b7c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -215,11 +215,11 @@ static bool dce110_enable_display_power_gating( } static void build_prescale_params(struct ipp_prescale_params *prescale_params, - const struct core_surface *surface) + const struct dc_surface *surface) { prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; - switch (surface->public.format) { + switch (surface->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: prescale_params->scale = 0x2020; @@ -240,7 +240,7 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface) + const struct dc_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -250,14 +250,14 @@ static bool dce110_set_input_transfer_func( if (ipp == NULL) return false; - if (surface->public.in_transfer_func) - tf = surface->public.in_transfer_func; + if (surface->in_transfer_func) + tf = surface->in_transfer_func; build_prescale_params(&prescale_params, surface); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (surface->public.gamma_correction && dce_use_lut(surface)) - ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction); + if (surface->gamma_correction && dce_use_lut(surface)) + ipp->funcs->ipp_program_input_lut(ipp, surface->gamma_correction); if (tf == NULL) { /* Default case if no input transfer function specified */ @@ -1857,7 +1857,7 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) default_adjust.in_color_space = COLOR_SPACE_SRGB; else default_adjust.in_color_space = - pipe_ctx->surface->public.color_space; + pipe_ctx->surface->color_space; if (pipe_ctx->stream == NULL) default_adjust.out_color_space = COLOR_SPACE_SRGB; else @@ -1908,16 +1908,16 @@ static void program_surface_visibility(const struct core_dc *dc, /* For now we are supporting only two pipes */ ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); - if (pipe_ctx->bottom_pipe->surface->public.visible) { - if (pipe_ctx->surface->public.visible) + if (pipe_ctx->bottom_pipe->surface->visible) { + if (pipe_ctx->surface->visible) blender_mode = BLND_MODE_BLENDING; else blender_mode = BLND_MODE_OTHER_PIPE; - } else if (!pipe_ctx->surface->public.visible) + } else if (!pipe_ctx->surface->visible) blank_target = true; - } else if (!pipe_ctx->surface->public.visible) + } else if (!pipe_ctx->surface->visible) blank_target = true; dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); @@ -1975,7 +1975,7 @@ static void set_plane_config( struct resource_context *res_ctx) { struct mem_input *mi = pipe_ctx->mi; - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2040,42 +2040,42 @@ static void set_plane_config( mi->funcs->mem_input_program_surface_config( mi, - surface->public.format, - &surface->public.tiling_info, - &surface->public.plane_size, - surface->public.rotation, + surface->format, + &surface->tiling_info, + &surface->plane_size, + surface->rotation, NULL, false); if (mi->funcs->set_blank) - mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible); + mi->funcs->set_blank(mi, pipe_ctx->surface->visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->public.format, - &surface->public.tiling_info, - surface->public.rotation); + surface->format, + &surface->tiling_info, + surface->rotation); } static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; if (surface == NULL) return; pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( pipe_ctx->mi, - &surface->public.address, - surface->public.flip_immediate); + &surface->address, + surface->flip_immediate); - surface->status.requested_address = surface->public.address; + surface->status.requested_address = surface->address; } void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; if (surface == NULL) return; @@ -2084,7 +2084,7 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) pipe_ctx->mi->funcs->mem_input_is_flip_pending( pipe_ctx->mi); - if (surface->status.is_flip_pending && !surface->public.visible) + if (surface->status.is_flip_pending && !surface->visible) pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; surface->status.current_address = pipe_ctx->mi->current_address; @@ -2425,7 +2425,7 @@ static void dce110_program_front_end_for_pipe( { struct mem_input *mi = pipe_ctx->mi; struct pipe_ctx *old_pipe = NULL; - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2493,21 +2493,21 @@ static void dce110_program_front_end_for_pipe( mi->funcs->mem_input_program_surface_config( mi, - surface->public.format, - &surface->public.tiling_info, - &surface->public.plane_size, - surface->public.rotation, + surface->format, + &surface->tiling_info, + &surface->plane_size, + surface->rotation, NULL, false); if (mi->funcs->set_blank) - mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible); + mi->funcs->set_blank(mi, pipe_ctx->surface->visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->public.format, - &surface->public.tiling_info, - surface->public.rotation); + surface->format, + &surface->tiling_info, + surface->rotation); dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe:%d 0x%x: addr hi:0x%x, " @@ -2517,20 +2517,20 @@ static void dce110_program_front_end_for_pipe( "clip: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, pipe_ctx->surface, - pipe_ctx->surface->public.address.grph.addr.high_part, - pipe_ctx->surface->public.address.grph.addr.low_part, - pipe_ctx->surface->public.src_rect.x, - pipe_ctx->surface->public.src_rect.y, - pipe_ctx->surface->public.src_rect.width, - pipe_ctx->surface->public.src_rect.height, - pipe_ctx->surface->public.dst_rect.x, - pipe_ctx->surface->public.dst_rect.y, - pipe_ctx->surface->public.dst_rect.width, - pipe_ctx->surface->public.dst_rect.height, - pipe_ctx->surface->public.clip_rect.x, - pipe_ctx->surface->public.clip_rect.y, - pipe_ctx->surface->public.clip_rect.width, - pipe_ctx->surface->public.clip_rect.height); + pipe_ctx->surface->address.grph.addr.high_part, + pipe_ctx->surface->address.grph.addr.low_part, + pipe_ctx->surface->src_rect.x, + pipe_ctx->surface->src_rect.y, + pipe_ctx->surface->src_rect.width, + pipe_ctx->surface->src_rect.height, + pipe_ctx->surface->dst_rect.x, + pipe_ctx->surface->dst_rect.y, + pipe_ctx->surface->dst_rect.width, + pipe_ctx->surface->dst_rect.height, + pipe_ctx->surface->clip_rect.x, + pipe_ctx->surface->clip_rect.y, + pipe_ctx->surface->clip_rect.width, + pipe_ctx->surface->clip_rect.height); dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe %d: width, height, x, y\n" @@ -2549,7 +2549,7 @@ static void dce110_program_front_end_for_pipe( static void dce110_apply_ctx_for_surface( struct core_dc *dc, - struct core_surface *surface, + const struct dc_surface *surface, struct validate_context *context) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8b7bc1cc2b7b..0fcb1cf4b4ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -766,7 +766,7 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne return true; if (!pipe_ctx->surface) return false; - if (pipe_ctx->surface->public.format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + if (pipe_ctx->surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b7940876c761..4390023ca6dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -945,24 +945,24 @@ static void reset_hw_ctx_wrap( static bool patch_address_for_sbs_tb_stereo( struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; - if (sec_split && surface->public.address.type == PLN_ADDR_TYPE_GRPH_STEREO && + if (sec_split && surface->address.type == PLN_ADDR_TYPE_GRPH_STEREO && (pipe_ctx->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || pipe_ctx->stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { - *addr = surface->public.address.grph_stereo.left_addr; - surface->public.address.grph_stereo.left_addr = - surface->public.address.grph_stereo.right_addr; + *addr = surface->address.grph_stereo.left_addr; + surface->address.grph_stereo.left_addr = + surface->address.grph_stereo.right_addr; return true; } else { if (pipe_ctx->stream->public.view_format != VIEW_3D_FORMAT_NONE && - surface->public.address.type != PLN_ADDR_TYPE_GRPH_STEREO) { - surface->public.address.type = PLN_ADDR_TYPE_GRPH_STEREO; - surface->public.address.grph_stereo.right_addr = - surface->public.address.grph_stereo.left_addr; + surface->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { + surface->address.type = PLN_ADDR_TYPE_GRPH_STEREO; + surface->address.grph_stereo.right_addr = + surface->address.grph_stereo.left_addr; } } return false; @@ -972,22 +972,22 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; if (surface == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( pipe_ctx->mi, - &surface->public.address, - surface->public.flip_immediate); - surface->status.requested_address = surface->public.address; + &surface->address, + surface->flip_immediate); + surface->status.requested_address = surface->address; if (addr_patched) - pipe_ctx->surface->public.address.grph_stereo.left_addr = addr; + pipe_ctx->surface->address.grph_stereo.left_addr = addr; } static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, const struct core_surface *surface) + struct pipe_ctx *pipe_ctx, const struct dc_surface *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -996,12 +996,12 @@ static bool dcn10_set_input_transfer_func( if (ipp == NULL) return false; - if (surface->public.in_transfer_func) - tf = surface->public.in_transfer_func; + if (surface->in_transfer_func) + tf = surface->in_transfer_func; - if (surface->public.gamma_correction && dce_use_lut(surface)) + if (surface->gamma_correction && dce_use_lut(surface)) ipp->funcs->ipp_program_input_lut(ipp, - surface->public.gamma_correction); + surface->gamma_correction); if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); @@ -1594,7 +1594,7 @@ static void dcn10_power_on_fe( struct pipe_ctx *pipe_ctx, struct validate_context *context) { - struct dc_surface *dc_surface = &pipe_ctx->surface->public; + struct dc_surface *dc_surface = pipe_ctx->surface; struct dce_hwseq *hws = dc->hwseq; power_on_plane(dc->hwseq, @@ -1710,7 +1710,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->public.visible) + if (pipe_ctx->surface->visible) return true; if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) return true; @@ -1719,7 +1719,7 @@ static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->public.visible) + if (pipe_ctx->surface->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1728,7 +1728,7 @@ static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->public.visible) + if (pipe_ctx->surface->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1803,12 +1803,12 @@ static void update_dchubp_dpp( struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->mi; struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct core_surface *surface = pipe_ctx->surface; - union plane_size size = surface->public.plane_size; + struct dc_surface *surface = pipe_ctx->surface; + union plane_size size = surface->plane_size; struct default_adjustment ocsc = {0}; struct tg_color black_color = {0}; struct mpcc_cfg mpcc_cfg; - bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; + bool per_pixel_alpha = surface->per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ @@ -1841,12 +1841,12 @@ static void update_dchubp_dpp( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->public.format, - &surface->public.tiling_info, - surface->public.rotation); + surface->format, + &surface->tiling_info, + surface->rotation); ipp->funcs->ipp_setup(ipp, - surface->public.format, + surface->format, 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); @@ -1892,12 +1892,12 @@ static void update_dchubp_dpp( mi->funcs->mem_input_program_surface_config( mi, - surface->public.format, - &surface->public.tiling_info, + surface->format, + &surface->tiling_info, &size, - surface->public.rotation, - &surface->public.dcc, - surface->public.horizontal_mirror); + surface->rotation, + &surface->dcc, + surface->horizontal_mirror); mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); } @@ -1978,7 +1978,7 @@ static void dcn10_pplib_apply_display_requirements( static void dcn10_apply_ctx_for_surface( struct core_dc *dc, - struct core_surface *surface, + const struct dc_surface *surface, struct validate_context *context) { int i, be_idx; @@ -2337,7 +2337,7 @@ static bool dcn10_dummy_display_power_gating( void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct core_surface *surface = pipe_ctx->surface; + struct dc_surface *surface = pipe_ctx->surface; struct timing_generator *tg = pipe_ctx->tg; if (surface->ctx->dc->debug.sanity_checks) { @@ -2355,7 +2355,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) /* DCN we read INUSE address in MI, do we still need this wa? */ if (surface->status.is_flip_pending && - !surface->public.visible) { + !surface->visible) { pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index cc65cfdea66f..07a1aec5a28b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -40,23 +40,9 @@ struct core_stream; #define MAX_CLOCK_SOURCES 7 -/********* core_surface **********/ -#define DC_SURFACE_TO_CORE(dc_surface) \ - container_of(dc_surface, struct core_surface, public) - #define DC_GAMMA_TO_CORE(dc_gamma) \ container_of(dc_gamma, struct core_gamma, public) -struct core_surface { - struct dc_surface public; - struct dc_surface_status status; - struct dc_context *ctx; - - /* private to dc_surface.c */ - enum dc_irq_source irq_source; - int ref_count; -}; - struct core_gamma { struct dc_gamma public; struct dc_context *ctx; @@ -263,7 +249,7 @@ struct resource_pool { }; struct pipe_ctx { - struct core_surface *surface; + struct dc_surface *surface; struct core_stream *stream; struct mem_input *mi; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index d865df802c88..2343beb4ef87 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -59,7 +59,7 @@ struct hw_sequencer_funcs { void (*apply_ctx_for_surface)( struct core_dc *dc, - struct core_surface *surface, + const struct dc_surface *surface, struct validate_context *context); void (*set_plane_config)( @@ -88,7 +88,7 @@ struct hw_sequencer_funcs { bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct core_surface *surface); + const struct dc_surface *surface); bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 04e5fd1d8c89..ed94df16a2d3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -119,7 +119,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( const struct core_stream *stream); bool resource_attach_surfaces_to_context( - const struct dc_surface *const *surfaces, + struct dc_surface *const *surfaces, int surface_count, const struct dc_stream *dc_stream, struct validate_context *context, -- GitLab From d0778ebfd58f5650de17531296ee5ecdde39ba68 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sat, 22 Jul 2017 20:05:20 -0400 Subject: [PATCH 0679/2898] drm/amd/display: Roll core_link into dc_link Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 100 +++---- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 229 ++++++++------- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 264 +++++++++--------- .../drm/amd/display/dc/core/dc_link_hwss.c | 40 +-- .../gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 9 +- .../gpu/drm/amd/display/dc/core/dc_stream.c | 4 +- drivers/gpu/drm/amd/display/dc/dc.h | 112 +++++--- drivers/gpu/drm/amd/display/dc/dc_ddc_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 4 +- .../drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 16 +- .../amd/display/dc/dce110/dce110_resource.c | 2 +- .../amd/display/dc/dce112/dce112_resource.c | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 2 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 +- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 58 +--- .../gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 2 +- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 16 +- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 2 +- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 22 +- .../amd/display/include/logger_interface.h | 8 +- 29 files changed, 444 insertions(+), 484 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 2bb2fc2a6566..c558f700df35 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -563,7 +563,7 @@ struct amdgpu_connector { /* The 'old' sink - before an HPD. * The 'current' sink is in dc_link->sink. */ const struct dc_sink *dc_sink; - const struct dc_link *dc_link; + struct dc_link *dc_link; const struct dc_sink *dc_em_sink; const struct dc_stream *stream; void *con_priv; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index b247904206ba..4885403f5cec 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1874,7 +1874,7 @@ void amdgpu_dm_connector_init_helper( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector, int connector_type, - const struct dc_link *link, + struct dc_link *link, int link_index) { struct amdgpu_device *adev = dm->ddev->dev_private; @@ -1997,7 +1997,7 @@ int amdgpu_dm_connector_init( int res = 0; int connector_type; struct dc *dc = dm->dc; - const struct dc_link *link = dc_get_link_at_index(dc, link_index); + struct dc_link *link = dc_get_link_at_index(dc, link_index); struct amdgpu_i2c_adapter *i2c; ((struct dc_link *)link)->priv = aconnector; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index 115d9081d964..c565787cd782 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -114,7 +114,7 @@ void amdgpu_dm_connector_init_helper( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector, int connector_type, - const struct dc_link *link, + struct dc_link *link, int link_index); int amdgpu_dm_connector_mode_valid( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 569310ab116d..73740e2a5819 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -94,7 +94,7 @@ static bool create_links( for (i = 0; i < connectors_num; i++) { struct link_init_data link_init_params = {0}; - struct core_link *link; + struct dc_link *link; link_init_params.ctx = dc->ctx; /* next BIOS object table connector */ @@ -111,7 +111,7 @@ static bool create_links( } for (i = 0; i < num_virtual_links; i++) { - struct core_link *link = dm_alloc(sizeof(*link)); + struct dc_link *link = dm_alloc(sizeof(*link)); struct encoder_init_data enc_init = {0}; if (link == NULL) { @@ -121,7 +121,7 @@ static bool create_links( link->ctx = dc->ctx; link->dc = dc; - link->public.connector_signal = SIGNAL_TYPE_VIRTUAL; + link->connector_signal = SIGNAL_TYPE_VIRTUAL; link->link_id.type = OBJECT_TYPE_CONNECTOR; link->link_id.id = CONNECTOR_ID_VIRTUAL; link->link_id.enum_id = ENUM_ID_1; @@ -137,7 +137,7 @@ static bool create_links( enc_init.encoder.enum_id = ENUM_ID_1; virtual_link_encoder_construct(link->link_enc, &enc_init); - link->public.link_index = dc->link_count; + link->link_index = dc->link_count; dc->links[dc->link_count] = link; dc->link_count++; } @@ -278,14 +278,14 @@ static void set_drive_settings(struct dc *dc, int i; for (i = 0; i < core_dc->link_count; i++) { - if (&core_dc->links[i]->public == link) + if (core_dc->links[i] == link) break; } if (i >= core_dc->link_count) ASSERT_CRITICAL(false); - dc_link_dp_set_drive_settings(&core_dc->links[i]->public, lt_settings); + dc_link_dp_set_drive_settings(core_dc->links[i], lt_settings); } static void perform_link_training(struct dc *dc, @@ -297,20 +297,17 @@ static void perform_link_training(struct dc *dc, for (i = 0; i < core_dc->link_count; i++) dc_link_dp_perform_link_training( - &core_dc->links[i]->public, + core_dc->links[i], link_setting, skip_video_pattern); } static void set_preferred_link_settings(struct dc *dc, struct dc_link_settings *link_setting, - const struct dc_link *link) + struct dc_link *link) { - struct core_link *core_link = DC_LINK_TO_CORE(link); - - core_link->public.preferred_link_setting = - *link_setting; - dp_retrain_link_dp_test(core_link, link_setting, false); + link->preferred_link_setting = *link_setting; + dp_retrain_link_dp_test(link, link_setting, false); } static void enable_hpd(const struct dc_link *link) @@ -325,7 +322,7 @@ static void disable_hpd(const struct dc_link *link) static void set_test_pattern( - const struct dc_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, const struct link_training_settings *p_link_settings, const unsigned char *p_custom_pattern, @@ -345,9 +342,8 @@ void set_dither_option(const struct dc_stream *dc_stream, { struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct bit_depth_reduction_params params; - struct core_link *core_link = DC_LINK_TO_CORE(stream->status.link); - struct pipe_ctx *pipes = - core_link->dc->current_context->res_ctx.pipe_ctx; + struct dc_link *link = stream->status.link; + struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; memset(¶ms, 0, sizeof(params)); if (!stream) @@ -1693,10 +1689,10 @@ struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i) return NULL; } -const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) +struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) { struct core_dc *core_dc = DC_TO_CORE(dc); - return &core_dc->links[link_index]->public; + return core_dc->links[link_index]; } const struct graphics_object_id dc_get_link_id_at_index( @@ -1710,7 +1706,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index) { struct core_dc *core_dc = DC_TO_CORE(dc); - return core_dc->links[link_index]->public.irq_source_hpd; + return core_dc->links[link_index]->irq_source_hpd; } const struct audio **dc_get_audios(struct dc *dc) @@ -1796,9 +1792,9 @@ bool dc_read_aux_dpcd( { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->public.ddc, + link->ddc, false, I2C_MOT_UNDEF, address, @@ -1815,10 +1811,10 @@ bool dc_write_aux_dpcd( uint32_t size) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->public.ddc, + link->ddc, false, I2C_MOT_UNDEF, address, @@ -1837,9 +1833,9 @@ bool dc_read_aux_i2c( { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->public.ddc, + link->ddc, true, mot, address, @@ -1857,10 +1853,10 @@ bool dc_write_aux_i2c( uint32_t size) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->public.ddc, + link->ddc, true, mot, address, @@ -1880,10 +1876,10 @@ bool dc_query_ddc_data( struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; + struct dc_link *link = core_dc->links[link_index]; bool result = dal_ddc_service_query_ddc_data( - link->public.ddc, + link->ddc, address, write_buf, write_size, @@ -1900,8 +1896,8 @@ bool dc_submit_i2c( { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_link *link = core_dc->links[link_index]; - struct ddc_service *ddc = link->public.ddc; + struct dc_link *link = core_dc->links[link_index]; + struct ddc_service *ddc = link->ddc; return dal_i2caux_submit_i2c_command( ddc->ctx->i2caux, @@ -1909,10 +1905,8 @@ bool dc_submit_i2c( cmd); } -static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_sink *sink) +static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink) { - struct dc_link *dc_link = &core_link->public; - if (dc_link->sink_count >= MAX_SINKS_PER_LINK) { BREAK_TO_DEBUGGER(); return false; @@ -1927,14 +1921,13 @@ static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_s } struct dc_sink *dc_link_add_remote_sink( - const struct dc_link *link, + struct dc_link *link, const uint8_t *edid, int len, struct dc_sink_init_data *init_data) { struct dc_sink *dc_sink; enum dc_edid_status edid_status; - struct core_link *core_link = DC_LINK_TO_LINK(link); if (len > MAX_EDID_BUFFER_SIZE) { dm_error("Max EDID buffer size breached!\n"); @@ -1960,12 +1953,12 @@ struct dc_sink *dc_link_add_remote_sink( dc_sink->dc_edid.length = len; if (!link_add_remote_sink_helper( - core_link, + link, dc_sink)) goto fail_add_sink; edid_status = dm_helpers_parse_edid_caps( - core_link->ctx, + link->ctx, &dc_sink->dc_edid, &dc_sink->edid_caps); @@ -1980,43 +1973,38 @@ struct dc_sink *dc_link_add_remote_sink( return NULL; } -void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink) +void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink) { - struct core_link *core_link = DC_LINK_TO_LINK(link); - struct dc_link *dc_link = &core_link->public; - - dc_link->local_sink = sink; + link->local_sink = sink; if (sink == NULL) { - dc_link->type = dc_connection_none; + link->type = dc_connection_none; } else { - dc_link->type = dc_connection_single; + link->type = dc_connection_single; } } -void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink) +void dc_link_remove_remote_sink(struct dc_link *link, const struct dc_sink *sink) { int i; - struct core_link *core_link = DC_LINK_TO_LINK(link); - struct dc_link *dc_link = &core_link->public; if (!link->sink_count) { BREAK_TO_DEBUGGER(); return; } - for (i = 0; i < dc_link->sink_count; i++) { - if (dc_link->remote_sinks[i] == sink) { + for (i = 0; i < link->sink_count; i++) { + if (link->remote_sinks[i] == sink) { dc_sink_release(sink); - dc_link->remote_sinks[i] = NULL; + link->remote_sinks[i] = NULL; /* shrink array to remove empty place */ - while (i < dc_link->sink_count - 1) { - dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1]; + while (i < link->sink_count - 1) { + link->remote_sinks[i] = link->remote_sinks[i+1]; i++; } - dc_link->remote_sinks[i] = NULL; - dc_link->sink_count--; + link->remote_sinks[i] = NULL; + link->sink_count--; return; } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 036d22f878b8..428dbff8505b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -62,24 +62,24 @@ enum { /******************************************************************************* * Private functions ******************************************************************************/ -static void destruct(struct core_link *link) +static void destruct(struct dc_link *link) { int i; - if (link->public.ddc) - dal_ddc_service_destroy(&link->public.ddc); + if (link->ddc) + dal_ddc_service_destroy(&link->ddc); if(link->link_enc) link->link_enc->funcs->destroy(&link->link_enc); - if (link->public.local_sink) - dc_sink_release(link->public.local_sink); + if (link->local_sink) + dc_sink_release(link->local_sink); - for (i = 0; i < link->public.sink_count; ++i) - dc_sink_release(link->public.remote_sinks[i]); + for (i = 0; i < link->sink_count; ++i) + dc_sink_release(link->remote_sinks[i]); } -static struct gpio *get_hpd_gpio(const struct core_link *link) +static struct gpio *get_hpd_gpio(const struct dc_link *link) { enum bp_result bp_result; struct dc_bios *dcb = link->ctx->dc_bios; @@ -116,7 +116,7 @@ static struct gpio *get_hpd_gpio(const struct core_link *link) * true on success, false otherwise */ static bool program_hpd_filter( - const struct core_link *link) + const struct dc_link *link) { bool result = false; @@ -126,7 +126,7 @@ static bool program_hpd_filter( int delay_on_disconnect_in_ms = 0; /* Verify feature is supported */ - switch (link->public.connector_signal) { + switch (link->connector_signal) { case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: case SIGNAL_TYPE_HDMI_TYPE_A: @@ -181,7 +181,7 @@ static bool program_hpd_filter( return result; } -static bool detect_sink(struct core_link *link, enum dc_connection_type *type) +static bool detect_sink(struct dc_link *link, enum dc_connection_type *type) { uint32_t is_hpd_high = 0; struct gpio *hpd_pin; @@ -306,7 +306,7 @@ static enum signal_type get_basic_signal_type( * @brief * Check whether there is a dongle on DP connector */ -static bool is_dp_sink_present(struct core_link *link) +static bool is_dp_sink_present(struct dc_link *link) { enum gpio_result gpio_result; uint32_t clock_pin = 0; @@ -320,7 +320,7 @@ static bool is_dp_sink_present(struct core_link *link) ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || (connector_id == CONNECTOR_ID_EDP)); - ddc = dal_ddc_service_get_ddc_pin(link->public.ddc); + ddc = dal_ddc_service_get_ddc_pin(link->ddc); if (!ddc) { BREAK_TO_DEBUGGER(); @@ -356,7 +356,7 @@ static bool is_dp_sink_present(struct core_link *link) * @brief * Detect output sink type */ -static enum signal_type link_detect_sink(struct core_link *link) +static enum signal_type link_detect_sink(struct dc_link *link) { enum signal_type result = get_basic_signal_type( link->link_enc->id, link->link_id); @@ -446,18 +446,18 @@ static enum signal_type dp_passive_dongle_detection( audio_support); } -static void link_disconnect_sink(struct core_link *link) +static void link_disconnect_sink(struct dc_link *link) { - if (link->public.local_sink) { - dc_sink_release(link->public.local_sink); - link->public.local_sink = NULL; + if (link->local_sink) { + dc_sink_release(link->local_sink); + link->local_sink = NULL; } link->dpcd_sink_count = 0; } static void detect_dp( - struct core_link *link, + struct dc_link *link, struct display_sink_capability *sink_caps, bool *converter_disable_audio, struct audio_support *audio_support, @@ -473,7 +473,7 @@ static void detect_dp( /* DP active dongles */ if (is_dp_active_dongle(link)) { - link->public.type = dc_connection_active_dongle; + link->type = dc_connection_active_dongle; if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) { /* * active dongle unplug processing for short irq @@ -517,8 +517,8 @@ static void detect_dp( if (dm_helpers_dp_mst_start_top_mgr( link->ctx, - &link->public, boot)) { - link->public.type = dc_connection_mst_branch; + link, boot)) { + link->type = dc_connection_mst_branch; } else { /* MST not supported */ sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; @@ -526,15 +526,14 @@ static void detect_dp( } } else { /* DP passive dongles */ - sink_caps->signal = dp_passive_dongle_detection(link->public.ddc, + sink_caps->signal = dp_passive_dongle_detection(link->ddc, sink_caps, audio_support); } } -bool dc_link_detect(const struct dc_link *dc_link, bool boot) +bool dc_link_detect(struct dc_link *link, bool boot) { - struct core_link *link = DC_LINK_TO_LINK(dc_link); struct dc_sink_init_data sink_init_data = { 0 }; struct display_sink_capability sink_caps = { 0 }; uint8_t i; @@ -546,7 +545,7 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) struct core_sink *sink = NULL; enum dc_connection_type new_connection_type = dc_connection_none; - if (link->public.connector_signal == SIGNAL_TYPE_VIRTUAL) + if (link->connector_signal == SIGNAL_TYPE_VIRTUAL) return false; if (false == detect_sink(link, &new_connection_type)) { @@ -554,17 +553,17 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) return false; } - if (link->public.connector_signal == SIGNAL_TYPE_EDP && - link->public.local_sink) + if (link->connector_signal == SIGNAL_TYPE_EDP && + link->local_sink) return true; link_disconnect_sink(link); if (new_connection_type != dc_connection_none) { - link->public.type = new_connection_type; + link->type = new_connection_type; /* From Disconnected-to-Connected. */ - switch (link->public.connector_signal) { + switch (link->connector_signal) { case SIGNAL_TYPE_HDMI_TYPE_A: { sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C; if (aud_support->hdmi_audio_native) @@ -602,14 +601,14 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) aud_support, boot); /* Active dongle downstream unplug */ - if (link->public.type == dc_connection_active_dongle + if (link->type == dc_connection_active_dongle && link->dpcd_caps.sink_count. bits.SINK_COUNT == 0) return true; - if (link->public.type == dc_connection_mst_branch) { + if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Connected\n", - link->public.link_index); + link->link_index); return false; } @@ -618,7 +617,7 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) default: DC_ERROR("Invalid connector type! signal:%d\n", - link->public.connector_signal); + link->connector_signal); return false; } /* switch() */ @@ -629,13 +628,13 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) link->dpcd_sink_count = 1; dal_ddc_service_set_transaction_type( - link->public.ddc, + link->ddc, sink_caps.transaction_type); - link->public.aux_mode = dal_ddc_service_is_in_aux_transaction_mode( - link->public.ddc); + link->aux_mode = dal_ddc_service_is_in_aux_transaction_mode( + link->ddc); - sink_init_data.link = &link->public; + sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; dc_sink = dc_sink_create(&sink_init_data); @@ -648,11 +647,11 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) dc_sink->converter_disable_audio = converter_disable_audio; sink = DC_SINK_TO_CORE(dc_sink); - link->public.local_sink = &sink->public; + link->local_sink = &sink->public; edid_status = dm_helpers_read_local_edid( link->ctx, - &link->public, + link, &sink->public); switch (edid_status) { @@ -719,21 +718,21 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) } else { /* From Connected-to-Disconnected. */ - if (link->public.type == dc_connection_mst_branch) { + if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Disconnected\n", - link->public.link_index); - dm_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public); + link->link_index); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); link->mst_stream_alloc_table.stream_count = 0; memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); } - link->public.type = dc_connection_none; + link->type = dc_connection_none; sink_caps.signal = SIGNAL_TYPE_NONE; } LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", - link->public.link_index, &sink->public, + link->link_index, &sink->public, (sink_caps.signal == SIGNAL_TYPE_NONE ? "Disconnected":"Connected")); @@ -741,7 +740,7 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot) } static enum hpd_source_id get_hpd_line( - struct core_link *link) + struct dc_link *link) { struct gpio *hpd; enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN; @@ -779,12 +778,12 @@ static enum hpd_source_id get_hpd_line( return hpd_id; } -static enum channel_id get_ddc_line(struct core_link *link) +static enum channel_id get_ddc_line(struct dc_link *link) { struct ddc *ddc; enum channel_id channel = CHANNEL_ID_UNKNOWN; - ddc = dal_ddc_service_get_ddc_pin(link->public.ddc); + ddc = dal_ddc_service_get_ddc_pin(link->ddc); if (ddc) { switch (dal_ddc_get_line(ddc)) { @@ -887,7 +886,7 @@ static enum transmitter translate_encoder_to_transmitter( } static bool construct( - struct core_link *link, + struct dc_link *link, const struct link_init_data *init_params) { uint8_t i; @@ -899,14 +898,14 @@ static bool construct( struct dc_bios *bios = init_params->dc->ctx->dc_bios; const struct dc_vbios_funcs *bp_funcs = bios->funcs; - link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID; - link->public.irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; + link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; + link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; link->link_status.dpcd_caps = &link->dpcd_caps; link->dc = init_params->dc; link->ctx = dc_ctx; - link->public.link_index = init_params->link_index; + link->link_index = init_params->link_index; link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); @@ -919,35 +918,35 @@ static bool construct( hpd_gpio = get_hpd_gpio(link); if (hpd_gpio != NULL) - link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio); + link->irq_source_hpd = dal_irq_get_source(hpd_gpio); switch (link->link_id.id) { case CONNECTOR_ID_HDMI_TYPE_A: - link->public.connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; + link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; break; case CONNECTOR_ID_SINGLE_LINK_DVID: case CONNECTOR_ID_SINGLE_LINK_DVII: - link->public.connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; break; case CONNECTOR_ID_DUAL_LINK_DVID: case CONNECTOR_ID_DUAL_LINK_DVII: - link->public.connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; + link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; break; case CONNECTOR_ID_DISPLAY_PORT: - link->public.connector_signal = SIGNAL_TYPE_DISPLAY_PORT; + link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; if (hpd_gpio != NULL) - link->public.irq_source_hpd_rx = + link->irq_source_hpd_rx = dal_irq_get_rx_source(hpd_gpio); break; case CONNECTOR_ID_EDP: - link->public.connector_signal = SIGNAL_TYPE_EDP; + link->connector_signal = SIGNAL_TYPE_EDP; if (hpd_gpio != NULL) { - link->public.irq_source_hpd = DC_IRQ_SOURCE_INVALID; - link->public.irq_source_hpd_rx = + link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; + link->irq_source_hpd_rx = dal_irq_get_rx_source(hpd_gpio); } break; @@ -966,21 +965,21 @@ static bool construct( LINK_INFO("Connector[%d] description:" "signal %d\n", init_params->connector_index, - link->public.connector_signal); + link->connector_signal); ddc_service_init_data.ctx = link->ctx; ddc_service_init_data.id = link->link_id; ddc_service_init_data.link = link; - link->public.ddc = dal_ddc_service_create(&ddc_service_init_data); + link->ddc = dal_ddc_service_create(&ddc_service_init_data); - if (link->public.ddc == NULL) { + if (link->ddc == NULL) { DC_ERROR("Failed to create ddc_service!\n"); goto ddc_create_fail; } - link->public.ddc_hw_inst = + link->ddc_hw_inst = dal_ddc_get_line( - dal_ddc_service_get_ddc_pin(link->public.ddc)); + dal_ddc_service_get_ddc_pin(link->ddc)); enc_init_data.ctx = dc_ctx; bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, &enc_init_data.encoder); @@ -988,7 +987,7 @@ static bool construct( enc_init_data.channel = get_ddc_line(link); enc_init_data.hpd_source = get_hpd_line(link); - link->public.hpd_src = enc_init_data.hpd_source; + link->hpd_src = enc_init_data.hpd_source; enc_init_data.transmitter = translate_encoder_to_transmitter(enc_init_data.encoder); @@ -1000,7 +999,7 @@ static bool construct( goto link_enc_create_fail; } - link->public.link_enc_hw_inst = link->link_enc->transmitter; + link->link_enc_hw_inst = link->link_enc->transmitter; for (i = 0; i < 4; i++) { if (BP_RESULT_OK != @@ -1015,10 +1014,10 @@ static bool construct( if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, link->device_tag.dev_id)) continue; if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT - && link->public.connector_signal != SIGNAL_TYPE_RGB) + && link->connector_signal != SIGNAL_TYPE_RGB) continue; if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD - && link->public.connector_signal == SIGNAL_TYPE_RGB) + && link->connector_signal == SIGNAL_TYPE_RGB) continue; break; } @@ -1052,7 +1051,7 @@ static bool construct( device_tag_fail: link->link_enc->funcs->destroy(&link->link_enc); link_enc_create_fail: - dal_ddc_service_destroy(&link->public.ddc); + dal_ddc_service_destroy(&link->ddc); ddc_create_fail: create_fail: @@ -1066,9 +1065,9 @@ static bool construct( /******************************************************************************* * Public functions ******************************************************************************/ -struct core_link *link_create(const struct link_init_data *init_params) +struct dc_link *link_create(const struct link_init_data *init_params) { - struct core_link *link = + struct dc_link *link = dm_alloc(sizeof(*link)); if (NULL == link) @@ -1086,7 +1085,7 @@ struct core_link *link_create(const struct link_init_data *init_params) return NULL; } -void link_destroy(struct core_link **link) +void link_destroy(struct dc_link **link) { destruct(*link); dm_free(*link); @@ -1094,7 +1093,7 @@ void link_destroy(struct core_link **link) } static void dpcd_configure_panel_mode( - struct core_link *link, + struct dc_link *link, enum dp_panel_mode panel_mode) { union dpcd_edp_config edp_config_set; @@ -1139,7 +1138,7 @@ static void dpcd_configure_panel_mode( dm_logger_write(link->ctx->logger, LOG_DETECTION_DP_CAPS, "Link: %d eDP panel mode supported: %d " "eDP panel mode enabled: %d \n", - link->public.link_index, + link->link_index, link->dpcd_caps.panel_mode_edp, panel_mode_edp); } @@ -1147,7 +1146,7 @@ static void dpcd_configure_panel_mode( static void enable_stream_features(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; union down_spread_ctrl downspread; core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL, @@ -1165,7 +1164,7 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) struct core_stream *stream = pipe_ctx->stream; enum dc_status status; bool skip_video_pattern; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; struct dc_link_settings link_settings = {0}; enum dp_panel_mode panel_mode; enum dc_link_rate max_link_rate = LINK_RATE_HIGH2; @@ -1224,7 +1223,7 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) &link_settings, skip_video_pattern, LINK_TRAINING_ATTEMPTS)) { - link->public.cur_link_settings = link_settings; + link->cur_link_settings = link_settings; status = DC_OK; } else @@ -1237,12 +1236,12 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) { - struct core_link *link = pipe_ctx->stream->sink->link; + struct dc_link *link = pipe_ctx->stream->sink->link; /* sink signal type after MST branch is MST. Multiple MST sinks * share one link. Link DP PHY is enable or training only once. */ - if (link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) + if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) return DC_OK; /* set the sink to MST mode before enabling the link */ @@ -1254,16 +1253,16 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; enum dc_color_depth display_color_depth; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( - stream->sink->link->public.ddc, + stream->sink->link->ddc, stream->phy_pix_clk, stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); - memset(&stream->sink->link->public.cur_link_settings, 0, + memset(&stream->sink->link->cur_link_settings, 0, sizeof(struct dc_link_settings)); display_color_depth = stream->public.timing.display_color_depth; @@ -1279,7 +1278,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) stream->phy_pix_clk); if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) - dal_ddc_service_read_scdc_data(link->public.ddc); + dal_ddc_service_read_scdc_data(link->ddc); } /****************************enable_link***********************************/ @@ -1321,7 +1320,7 @@ static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) return status; } -static void disable_link(struct core_link *link, enum signal_type signal) +static void disable_link(struct dc_link *link, enum signal_type signal) { /* * TODO: implement call for dp_set_hw_test_pattern @@ -1345,7 +1344,7 @@ static void disable_link(struct core_link *link, enum signal_type signal) enum dc_status dc_link_validate_mode_timing( const struct core_stream *stream, - struct core_link *link, + struct dc_link *link, const struct dc_crtc_timing *timing) { uint32_t max_pix_clk = stream->sink->public.dongle_max_pix_clk; @@ -1353,7 +1352,7 @@ enum dc_status dc_link_validate_mode_timing( /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle */ - if (link->public.remote_sinks[0]) + if (link->remote_sinks[0]) return DC_OK; if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk) @@ -1376,10 +1375,9 @@ enum dc_status dc_link_validate_mode_timing( } -bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, +bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct core_stream *core_stream = NULL; struct abm *abm = core_dc->res_pool->abm; @@ -1392,7 +1390,7 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, dm_logger_write(link->ctx->logger, LOG_BACKLIGHT, "New Backlight level: %d (0x%X)\n", level, level); - if (dc_is_embedded_signal(dc_link->connector_signal)) { + if (dc_is_embedded_signal(link->connector_signal)) { if (stream != NULL) { core_stream = DC_STREAM_TO_CORE(stream); for (i = 0; i < MAX_PIPES; i++) { @@ -1419,9 +1417,8 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, } -bool dc_link_set_abm_disable(const struct dc_link *dc_link) +bool dc_link_set_abm_disable(const struct dc_link *link) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct abm *abm = core_dc->res_pool->abm; @@ -1434,11 +1431,9 @@ bool dc_link_set_abm_disable(const struct dc_link *dc_link) } -bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) +bool dc_link_set_psr_enable(const struct dc_link *link, bool enable) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) @@ -1447,11 +1442,9 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable) return true; } -bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state) +bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) @@ -1460,20 +1453,18 @@ bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state) return true; } -bool dc_link_setup_psr(const struct dc_link *dc_link, +bool dc_link_setup_psr(struct dc_link *link, const struct dc_stream *stream, struct psr_config *psr_config, struct psr_context *psr_context) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); - struct dc_context *ctx = link->ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i; psr_context->controllerId = CONTROLLER_ID_UNDEFINED; - if (dc_link != NULL && + if (link != NULL && dmcu != NULL) { /* updateSinkPsrDpcdConfig*/ union dpcd_psr_configuration psr_configuration; @@ -1501,12 +1492,12 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, dm_helpers_dp_write_dpcd( link->ctx, - dc_link, + link, 368, &psr_configuration.raw, sizeof(psr_configuration.raw)); - psr_context->channel = link->public.ddc->ddc_pin->hw_info.ddc_channel; + psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel; psr_context->transmitterId = link->link_enc->transmitter; psr_context->engineId = link->link_enc->preferred_engine; @@ -1584,23 +1575,21 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, } -const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link) +const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { - struct core_link *link = DC_LINK_TO_CORE(dc_link); - return &link->link_status; } -void core_link_resume(struct core_link *link) +void core_link_resume(struct dc_link *link) { - if (link->public.connector_signal != SIGNAL_TYPE_VIRTUAL) + if (link->connector_signal != SIGNAL_TYPE_VIRTUAL) program_hpd_filter(link); } static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream) { struct dc_link_settings *link_settings = - &stream->sink->link->public.cur_link_settings; + &stream->sink->link->cur_link_settings; uint32_t link_rate_in_mbps = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ; struct fixed31_32 mbps = dal_fixed31_32_from_int( @@ -1653,7 +1642,7 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) } static void update_mst_stream_alloc_table( - struct core_link *link, + struct dc_link *link, struct stream_encoder *stream_enc, const struct dp_mst_stream_allocation_table *proposed_table) { @@ -1668,7 +1657,7 @@ static void update_mst_stream_alloc_table( ASSERT(proposed_table->stream_count - link->mst_stream_alloc_table.stream_count < 2); - /* copy proposed_table to core_link, add stream encoder */ + /* copy proposed_table to link, add stream encoder */ for (i = 0; i < proposed_table->stream_count; i++) { for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) { @@ -1707,7 +1696,7 @@ static void update_mst_stream_alloc_table( static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; @@ -1789,13 +1778,13 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0); uint8_t i; - bool mst_mode = (link->public.type == dc_connection_mst_branch); + bool mst_mode = (link->type == dc_connection_mst_branch); /* deallocate_mst_payload is called before disable link. When mode or * disable/enable monitor, new stream is created which is not in link @@ -1875,7 +1864,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) if (status != DC_OK) { dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_WARNING, "enabling link %u failed: %d\n", - pipe_ctx->stream->sink->link->public.link_index, + pipe_ctx->stream->sink->link->link_index, status); /* Abort stream enable *unless* the failure was due to diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 2f5a89c5b063..d09e539397ea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -354,7 +354,7 @@ static uint32_t defer_delay_converter_wa( struct ddc_service *ddc, uint32_t defer_delay) { - struct core_link *link = ddc->link; + struct dc_link *link = ddc->link; if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_4 && !memcmp(link->dpcd_caps.branch_dev_name, @@ -423,7 +423,7 @@ static bool i2c_read( return dm_helpers_submit_i2c( ddc->ctx, - &ddc->link->public, + ddc->link, &command); } @@ -624,7 +624,7 @@ bool dal_ddc_service_query_ddc_data( ret = dm_helpers_submit_i2c( ddc->ctx, - &ddc->link->public, + ddc->link, &command); dal_ddc_i2c_payloads_destroy(&payloads); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e90b3ebc8347..c7b400786121 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -34,7 +34,7 @@ enum { }; static void wait_for_training_aux_rd_interval( - struct core_link* link, + struct dc_link *link, uint32_t default_wait_in_micro_secs) { union training_aux_rd_interval training_rd_interval; @@ -63,7 +63,7 @@ static void wait_for_training_aux_rd_interval( } static void dpcd_set_training_pattern( - struct core_link* link, + struct dc_link *link, union dpcd_training_pattern dpcd_pattern) { core_link_write_dpcd( @@ -80,7 +80,7 @@ static void dpcd_set_training_pattern( } static void dpcd_set_link_settings( - struct core_link* link, + struct dc_link *link, const struct link_training_settings *lt_settings) { uint8_t rate = (uint8_t) @@ -123,7 +123,7 @@ static void dpcd_set_link_settings( static enum dpcd_training_patterns hw_training_pattern_to_dpcd_training_pattern( - struct core_link* link, + struct dc_link *link, enum hw_dp_training_pattern pattern) { enum dpcd_training_patterns dpcd_tr_pattern = @@ -155,7 +155,7 @@ static enum dpcd_training_patterns } static void dpcd_set_lt_pattern_and_lane_settings( - struct core_link* link, + struct dc_link *link, const struct link_training_settings *lt_settings, enum hw_dp_training_pattern pattern) { @@ -246,7 +246,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( dpcd_lt_buffer, size_in_bytes + sizeof(dpcd_pattern.raw) ); - link->public.cur_lane_setting = lt_settings->lane_settings[0]; + link->cur_lane_setting = lt_settings->lane_settings[0]; } static bool is_cr_done(enum dc_lane_count ln_count, @@ -419,7 +419,7 @@ static void find_max_drive_settings( } static void get_lane_status_and_drive_settings( - struct core_link* link, + struct dc_link *link, const struct link_training_settings *link_training_setting, union lane_status *ln_status, union lane_align_status_updated *ln_status_updated, @@ -500,7 +500,7 @@ static void get_lane_status_and_drive_settings( } static void dpcd_set_lane_settings( - struct core_link* link, + struct dc_link *link, const struct link_training_settings *link_training_setting) { union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}}; @@ -560,7 +560,7 @@ static void dpcd_set_lane_settings( dpcd_lane[0].bits.MAX_SWING_REACHED, dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); - link->public.cur_lane_setting = link_training_setting->lane_settings[0]; + link->cur_lane_setting = link_training_setting->lane_settings[0]; } @@ -580,19 +580,18 @@ static bool is_max_vs_reached( } void dc_link_dp_set_drive_settings( - const struct dc_link *link, + struct dc_link *link, struct link_training_settings *lt_settings) { - struct core_link *core_link = DC_LINK_TO_CORE(link); /* program ASIC PHY settings*/ - dp_set_hw_lane_settings(core_link, lt_settings); + dp_set_hw_lane_settings(link, lt_settings); /* Notify DP sink the PHY settings from source */ - dpcd_set_lane_settings(core_link, lt_settings); + dpcd_set_lane_settings(link, lt_settings); } static bool perform_post_lt_adj_req_sequence( - struct core_link *link, + struct dc_link *link, struct link_training_settings *lt_settings) { enum dc_lane_count lane_count = @@ -656,7 +655,7 @@ static bool perform_post_lt_adj_req_sequence( update_drive_settings( lt_settings,req_settings); - dc_link_dp_set_drive_settings(&link->public, + dc_link_dp_set_drive_settings(link, lt_settings); break; } @@ -682,7 +681,7 @@ static bool perform_post_lt_adj_req_sequence( } -static enum hw_dp_training_pattern get_supported_tp(struct core_link *link) +static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link) { enum hw_dp_training_pattern highest_tp = HW_DP_TRAINING_PATTERN_2; struct encoder_feature_support *features = &link->link_enc->features; @@ -706,7 +705,7 @@ static enum hw_dp_training_pattern get_supported_tp(struct core_link *link) } static enum link_training_result perform_channel_equalization_sequence( - struct core_link *link, + struct dc_link *link, struct link_training_settings *lt_settings) { struct link_training_settings req_settings; @@ -768,7 +767,7 @@ static enum link_training_result perform_channel_equalization_sequence( } static bool perform_clock_recovery_sequence( - struct core_link *link, + struct dc_link *link, struct link_training_settings *lt_settings) { uint32_t retries_cr; @@ -877,7 +876,7 @@ static bool perform_clock_recovery_sequence( } static inline bool perform_link_training_int( - struct core_link *link, + struct dc_link *link, struct link_training_settings *lt_settings, bool status) { @@ -923,7 +922,6 @@ enum link_training_result dc_link_dp_perform_link_training( bool skip_video_pattern) { enum link_training_result status = LINK_TRAINING_SUCCESS; - struct core_link *core_link = DC_LINK_TO_CORE(link); char *link_rate = "Unknown"; struct link_training_settings lt_settings; @@ -945,19 +943,19 @@ enum link_training_result dc_link_dp_perform_link_training( lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ; /* 1. set link rate, lane count and spread*/ - dpcd_set_link_settings(core_link, <_settings); + dpcd_set_link_settings(link, <_settings); /* 2. perform link training (set link training done * to false is done as well)*/ - if (!perform_clock_recovery_sequence(core_link, <_settings)) { + if (!perform_clock_recovery_sequence(link, <_settings)) { status = LINK_TRAINING_CR_FAIL; } else { - status = perform_channel_equalization_sequence(core_link, + status = perform_channel_equalization_sequence(link, <_settings); } if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) { - if (!perform_link_training_int(core_link, + if (!perform_link_training_int(link, <_settings, status == LINK_TRAINING_SUCCESS)) { /* the next link training setting in this case @@ -990,7 +988,7 @@ enum link_training_result dc_link_dp_perform_link_training( } /* Connectivity log: link training */ - CONN_MSG_LT(core_link, "%sx%d %s VS=%d, PE=%d", + CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d", link_rate, lt_settings.link_settings.lane_count, (status == LINK_TRAINING_SUCCESS) ? "pass" : @@ -1004,7 +1002,7 @@ enum link_training_result dc_link_dp_perform_link_training( bool perform_link_training_with_retries( - struct core_link *link, + struct dc_link *link, const struct dc_link_settings *link_setting, bool skip_video_pattern, int attempts) @@ -1015,7 +1013,7 @@ bool perform_link_training_with_retries( for (j = 0; j < attempts; ++j) { if (dc_link_dp_perform_link_training( - &link->public, + link, link_setting, skip_video_pattern) == LINK_TRAINING_SUCCESS) return true; @@ -1027,7 +1025,7 @@ bool perform_link_training_with_retries( return false; } -static struct dc_link_settings get_max_link_cap(struct core_link *link) +static struct dc_link_settings get_max_link_cap(struct dc_link *link) { /* Set Default link settings */ struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH, @@ -1041,21 +1039,21 @@ static struct dc_link_settings get_max_link_cap(struct core_link *link) max_link_cap.link_rate = LINK_RATE_HIGH3; /* Lower link settings based on sink's link cap */ - if (link->public.reported_link_cap.lane_count < max_link_cap.lane_count) + if (link->reported_link_cap.lane_count < max_link_cap.lane_count) max_link_cap.lane_count = - link->public.reported_link_cap.lane_count; - if (link->public.reported_link_cap.link_rate < max_link_cap.link_rate) + link->reported_link_cap.lane_count; + if (link->reported_link_cap.link_rate < max_link_cap.link_rate) max_link_cap.link_rate = - link->public.reported_link_cap.link_rate; - if (link->public.reported_link_cap.link_spread < + link->reported_link_cap.link_rate; + if (link->reported_link_cap.link_spread < max_link_cap.link_spread) max_link_cap.link_spread = - link->public.reported_link_cap.link_spread; + link->reported_link_cap.link_spread; return max_link_cap; } bool dp_hbr_verify_link_cap( - struct core_link *link, + struct dc_link *link, struct dc_link_settings *known_limit_link_setting) { struct dc_link_settings max_link_cap = {0}; @@ -1080,7 +1078,7 @@ bool dp_hbr_verify_link_cap( * find the physical link capability */ /* disable PHY done possible by BIOS, will be done by driver itself */ - dp_disable_link_phy(link, link->public.connector_signal); + dp_disable_link_phy(link, link->connector_signal); dp_cs = link->dc->res_pool->dp_clock_source; @@ -1109,7 +1107,7 @@ bool dp_hbr_verify_link_cap( dp_enable_link_phy( link, - link->public.connector_signal, + link->connector_signal, dp_cs_id, cur); @@ -1117,7 +1115,7 @@ bool dp_hbr_verify_link_cap( success = true; else { status = dc_link_dp_perform_link_training( - &link->public, + link, cur, skip_video_pattern); if (status == LINK_TRAINING_SUCCESS) @@ -1125,13 +1123,13 @@ bool dp_hbr_verify_link_cap( } if (success) - link->public.verified_link_cap = *cur; + link->verified_link_cap = *cur; /* always disable the link before trying another * setting or before returning we'll enable it later * based on the actual mode we're driving */ - dp_disable_link_phy(link, link->public.connector_signal); + dp_disable_link_phy(link, link->connector_signal); } while (!success && decide_fallback_link_setting( initial_link_settings, cur, status)); @@ -1142,14 +1140,14 @@ bool dp_hbr_verify_link_cap( /* If all LT fails for all settings, * set verified = failed safe (1 lane low) */ - link->public.verified_link_cap.lane_count = LANE_COUNT_ONE; - link->public.verified_link_cap.link_rate = LINK_RATE_LOW; + link->verified_link_cap.lane_count = LANE_COUNT_ONE; + link->verified_link_cap.link_rate = LINK_RATE_LOW; - link->public.verified_link_cap.link_spread = + link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED; } - link->public.max_link_setting = link->public.verified_link_cap; + link->max_link_setting = link->verified_link_cap; return success; } @@ -1391,7 +1389,7 @@ static uint32_t bandwidth_in_kbps_from_link_settings( } bool dp_validate_mode_timing( - struct core_link *link, + struct dc_link *link, const struct dc_crtc_timing *timing) { uint32_t req_bw; @@ -1406,12 +1404,12 @@ bool dp_validate_mode_timing( return true; /* We always use verified link settings */ - link_setting = &link->public.verified_link_cap; + link_setting = &link->verified_link_cap; /* TODO: DYNAMIC_VALIDATION needs to be implemented */ /*if (flags.DYNAMIC_VALIDATION == 1 && - link->public.verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) - link_setting = &link->public.verified_link_cap; + link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN) + link_setting = &link->verified_link_cap; */ req_bw = bandwidth_in_kbps_from_timing(timing); @@ -1444,7 +1442,7 @@ void decide_link_settings(struct core_stream *stream, LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED}; struct dc_link_settings current_link_setting = initial_link_setting; - struct core_link* link; + struct dc_link *link; uint32_t req_bw; uint32_t link_bw; @@ -1456,11 +1454,11 @@ void decide_link_settings(struct core_stream *stream, /* if preferred is specified through AMDDP, use it, if it's enough * to drive the mode */ - if (link->public.preferred_link_setting.lane_count != + if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN && - link->public.preferred_link_setting.link_rate != + link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) { - *link_setting = link->public.preferred_link_setting; + *link_setting = link->preferred_link_setting; return; } @@ -1469,7 +1467,7 @@ void decide_link_settings(struct core_stream *stream, * 2. could support the b/w requested by the timing */ while (current_link_setting.link_rate <= - link->public.max_link_setting.link_rate) { + link->max_link_setting.link_rate) { link_bw = bandwidth_in_kbps_from_link_settings( ¤t_link_setting); if (req_bw <= link_bw) { @@ -1478,7 +1476,7 @@ void decide_link_settings(struct core_stream *stream, } if (current_link_setting.lane_count < - link->public.max_link_setting.lane_count) { + link->max_link_setting.lane_count) { current_link_setting.lane_count = increase_lane_count( current_link_setting.lane_count); @@ -1492,16 +1490,15 @@ void decide_link_settings(struct core_stream *stream, } BREAK_TO_DEBUGGER(); - ASSERT(link->public.verified_link_cap.lane_count != - LANE_COUNT_UNKNOWN); + ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN); - *link_setting = link->public.verified_link_cap; + *link_setting = link->verified_link_cap; } /*************************Short Pulse IRQ***************************/ static bool hpd_rx_irq_check_link_loss_status( - struct core_link *link, + struct dc_link *link, union hpd_irq_data *hpd_irq_dpcd_data) { uint8_t irq_reg_rx_power_state; @@ -1514,7 +1511,7 @@ static bool hpd_rx_irq_check_link_loss_status( sink_status_changed = false; return_code = false; - if (link->public.cur_link_settings.lane_count == 0) + if (link->cur_link_settings.lane_count == 0) return return_code; /*1. Check that we can handle interrupt: Not in FS DOS, * Not in "Display Timeout" state, Link is trained. @@ -1538,7 +1535,7 @@ static bool hpd_rx_irq_check_link_loss_status( /*parse lane status*/ for (lane = 0; - lane < link->public.cur_link_settings.lane_count; + lane < link->cur_link_settings.lane_count; lane++) { /* check status of lanes 0,1 @@ -1577,7 +1574,7 @@ static bool hpd_rx_irq_check_link_loss_status( } static enum dc_status read_hpd_rx_irq_data( - struct core_link *link, + struct dc_link *link, union hpd_irq_data *irq_data) { /* The HW reads 16 bytes from 200h on HPD, @@ -1593,7 +1590,7 @@ static enum dc_status read_hpd_rx_irq_data( sizeof(union hpd_irq_data)); } -static bool allow_hpd_rx_irq(const struct core_link *link) +static bool allow_hpd_rx_irq(const struct dc_link *link) { /* * Don't handle RX IRQ unless one of following is met: @@ -1602,15 +1599,15 @@ static bool allow_hpd_rx_irq(const struct core_link *link) * 3) We know we're dealing with an active dongle */ - if ((link->public.cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - (link->public.type == dc_connection_mst_branch) || + if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || + (link->type == dc_connection_mst_branch) || is_dp_active_dongle(link)) return true; return false; } -static bool handle_hpd_irq_psr_sink(const struct core_link *link) +static bool handle_hpd_irq_psr_sink(const struct dc_link *link) { union dpcd_psr_configuration psr_configuration; @@ -1619,7 +1616,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) dm_helpers_dp_read_dpcd( link->ctx, - &link->public, + link, 368,/*DpcdAddress_PSR_Enable_Cfg*/ &psr_configuration.raw, sizeof(psr_configuration.raw)); @@ -1632,7 +1629,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) dm_helpers_dp_read_dpcd( link->ctx, - &link->public, + link, 0x2006, /*DpcdAddress_PSR_Error_Status*/ (unsigned char *) dpcdbuf, sizeof(dpcdbuf)); @@ -1647,14 +1644,14 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) /* Acknowledge and clear error bits */ dm_helpers_dp_write_dpcd( link->ctx, - &link->public, + link, 8198,/*DpcdAddress_PSR_Error_Status*/ &psr_error_status.raw, sizeof(psr_error_status.raw)); /* PSR error, disable and re-enable PSR */ - dc_link_set_psr_enable(&link->public, false); - dc_link_set_psr_enable(&link->public, true); + dc_link_set_psr_enable(link, false); + dc_link_set_psr_enable(link, true); return true; } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == @@ -1670,7 +1667,7 @@ static bool handle_hpd_irq_psr_sink(const struct core_link *link) return false; } -static void dp_test_send_link_training(struct core_link *link) +static void dp_test_send_link_training(struct dc_link *link) { struct dc_link_settings link_settings = {0}; @@ -1686,13 +1683,13 @@ static void dp_test_send_link_training(struct core_link *link) 1); /* Set preferred link settings */ - link->public.verified_link_cap.lane_count = link_settings.lane_count; - link->public.verified_link_cap.link_rate = link_settings.link_rate; + link->verified_link_cap.lane_count = link_settings.lane_count; + link->verified_link_cap.link_rate = link_settings.link_rate; dp_retrain_link_dp_test(link, &link_settings, false); } -static void dp_test_send_phy_test_pattern(struct core_link *link) +static void dp_test_send_phy_test_pattern(struct dc_link *link) { union phy_test_pattern dpcd_test_pattern; union lane_adjust dpcd_lane_adjustment[2]; @@ -1771,10 +1768,10 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) sizeof(test_80_bit_pattern)); /* prepare link training settings */ - link_settings.link = link->public.cur_link_settings; + link_settings.link = link->cur_link_settings; for (lane = 0; lane < - (unsigned int)(link->public.cur_link_settings.lane_count); + (unsigned int)(link->cur_link_settings.lane_count); lane++) { dpcd_lane_adjust.raw = get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); @@ -1802,7 +1799,7 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) * forward request to DS */ dc_link_dp_set_test_pattern( - &link->public, + link, test_pattern, &link_training_settings, test_80_bit_pattern, @@ -1810,7 +1807,7 @@ static void dp_test_send_phy_test_pattern(struct core_link *link) DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); } -static void dp_test_send_link_test_pattern(struct core_link *link) +static void dp_test_send_link_test_pattern(struct dc_link *link) { union link_test_pattern dpcd_test_pattern; union test_misc dpcd_test_params; @@ -1850,14 +1847,14 @@ static void dp_test_send_link_test_pattern(struct core_link *link) } dc_link_dp_set_test_pattern( - &link->public, + link, test_pattern, NULL, NULL, 0); } -static void handle_automated_test(struct core_link *link) +static void handle_automated_test(struct dc_link *link) { union test_request test_request; union test_response test_response; @@ -1904,9 +1901,8 @@ static void handle_automated_test(struct core_link *link) sizeof(test_response)); } -bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data *out_hpd_irq_dpcd_data) +bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data) { - struct core_link *link = DC_LINK_TO_LINK(dc_link); union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}}; union device_service_irq device_service_clear = { { 0 } }; enum dc_status result = DDC_RESULT_UNKNOWN; @@ -1917,7 +1913,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, "%s: Got short pulse HPD on link %d\n", - __func__, link->public.link_index); + __func__, link->link_index); /* All the "handle_hpd_irq_xxx()" methods @@ -1951,7 +1947,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data if (!allow_hpd_rx_irq(link)) { dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ, "%s: skipping HPD handling on %d\n", - __func__, link->public.link_index); + __func__, link->link_index); return false; } @@ -1984,13 +1980,13 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data "Status: "); perform_link_training_with_retries(link, - &link->public.cur_link_settings, + &link->cur_link_settings, true, LINK_TRAINING_ATTEMPTS); status = false; } - if (link->public.type == dc_connection_active_dongle && + if (link->type == dc_connection_active_dongle && hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT != link->dpcd_sink_count) status = true; @@ -2010,7 +2006,7 @@ bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, union hpd_irq_data } /*query dpcd for version and mst cap addresses*/ -bool is_mst_supported(struct core_link *link) +bool is_mst_supported(struct dc_link *link) { bool mst = false; enum dc_status st = DC_OK; @@ -2034,7 +2030,7 @@ bool is_mst_supported(struct core_link *link) } -bool is_dp_active_dongle(const struct core_link *link) +bool is_dp_active_dongle(const struct dc_link *link) { enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type; @@ -2044,14 +2040,14 @@ bool is_dp_active_dongle(const struct core_link *link) } static void get_active_converter_info( - uint8_t data, struct core_link *link) + uint8_t data, struct dc_link *link) { union dp_downstream_port_present ds_port = { .byte = data }; /* decode converter info*/ if (!ds_port.fields.PORT_PRESENT) { link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; - ddc_service_set_dongle_type(link->public.ddc, + ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); return; } @@ -2121,7 +2117,7 @@ static void get_active_converter_info( } } - ddc_service_set_dongle_type(link->public.ddc, link->dpcd_caps.dongle_type); + ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); { struct dp_device_vendor_id dp_id; @@ -2158,7 +2154,7 @@ static void get_active_converter_info( } } -static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, +static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data, int length) { int retry = 0; @@ -2199,7 +2195,7 @@ static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data, link->wa_flags.dp_keep_receiver_powered = false; } -static void retrieve_link_cap(struct core_link *link) +static void retrieve_link_cap(struct dc_link *link) { uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1]; @@ -2253,11 +2249,11 @@ static void retrieve_link_cap(struct core_link *link) link->dpcd_caps.max_down_spread.raw = dpcd_data[ DP_MAX_DOWNSPREAD - DP_DPCD_REV]; - link->public.reported_link_cap.lane_count = + link->reported_link_cap.lane_count = link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; - link->public.reported_link_cap.link_rate = dpcd_data[ + link->reported_link_cap.link_rate = dpcd_data[ DP_MAX_LINK_RATE - DP_DPCD_REV]; - link->public.reported_link_cap.link_spread = + link->reported_link_cap.link_spread = link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; @@ -2266,8 +2262,8 @@ static void retrieve_link_cap(struct core_link *link) link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; - link->public.test_pattern_enabled = false; - link->public.compliance_test_state.raw = 0; + link->test_pattern_enabled = false; + link->compliance_test_state.raw = 0; /* read sink count */ core_link_read_dpcd(link, @@ -2279,7 +2275,7 @@ static void retrieve_link_cap(struct core_link *link) CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); } -void detect_dp_sink_caps(struct core_link *link) +void detect_dp_sink_caps(struct dc_link *link) { retrieve_link_cap(link); @@ -2291,18 +2287,17 @@ void detect_dp_sink_caps(struct core_link *link) */ if (is_mst_supported(link)) { - link->public.verified_link_cap = link->public.reported_link_cap; + link->verified_link_cap = link->reported_link_cap; } else { dp_hbr_verify_link_cap(link, - &link->public.reported_link_cap); + &link->reported_link_cap); } /* TODO save sink caps in link->sink */ } void dc_link_dp_enable_hpd(const struct dc_link *link) { - struct core_link *core_link = DC_LINK_TO_CORE(link); - struct link_encoder *encoder = core_link->link_enc; + struct link_encoder *encoder = link->link_enc; if (encoder != NULL && encoder->funcs->enable_hpd != NULL) encoder->funcs->enable_hpd(encoder); @@ -2310,8 +2305,7 @@ void dc_link_dp_enable_hpd(const struct dc_link *link) void dc_link_dp_disable_hpd(const struct dc_link *link) { - struct core_link *core_link = DC_LINK_TO_CORE(link); - struct link_encoder *encoder = core_link->link_enc; + struct link_encoder *encoder = link->link_enc; if (encoder != NULL && encoder->funcs->enable_hpd != NULL) encoder->funcs->disable_hpd(encoder); @@ -2327,7 +2321,7 @@ static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern) return false; } -static void set_crtc_test_pattern(struct core_link *link, +static void set_crtc_test_pattern(struct dc_link *link, struct pipe_ctx *pipe_ctx, enum dp_test_pattern test_pattern) { @@ -2402,15 +2396,13 @@ static void set_crtc_test_pattern(struct core_link *link, } bool dc_link_dp_set_test_pattern( - const struct dc_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, const struct link_training_settings *p_link_settings, const unsigned char *p_custom_pattern, unsigned int cust_pattern_size) { - struct core_link *core_link = DC_LINK_TO_CORE(link); - struct pipe_ctx *pipes = - core_link->dc->current_context->res_ctx.pipe_ctx; + struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; struct pipe_ctx pipe_ctx = pipes[0]; unsigned int lane; unsigned int i; @@ -2421,7 +2413,7 @@ bool dc_link_dp_set_test_pattern( memset(&training_pattern, 0, sizeof(training_pattern)); for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream->sink->link == core_link) { + if (pipes[i].stream->sink->link == link) { pipe_ctx = pipes[i]; break; } @@ -2431,24 +2423,24 @@ bool dc_link_dp_set_test_pattern( * is VideoMode Reset DP Phy Test Pattern if it is currently running * and request is VideoMode */ - if (core_link->public.test_pattern_enabled && test_pattern == + if (link->test_pattern_enabled && test_pattern == DP_TEST_PATTERN_VIDEO_MODE) { /* Set CRTC Test Pattern */ - set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); - dp_set_hw_test_pattern(core_link, test_pattern, + set_crtc_test_pattern(link, &pipe_ctx, test_pattern); + dp_set_hw_test_pattern(link, test_pattern, (uint8_t *)p_custom_pattern, (uint32_t)cust_pattern_size); /* Unblank Stream */ - core_link->dc->hwss.unblank_stream( + link->dc->hwss.unblank_stream( &pipe_ctx, - &core_link->public.verified_link_cap); + &link->verified_link_cap); /* TODO:m_pHwss->MuteAudioEndpoint * (pPathMode->pDisplayPath, false); */ /* Reset Test Pattern state */ - core_link->public.test_pattern_enabled = false; + link->test_pattern_enabled = false; return true; } @@ -2457,8 +2449,8 @@ bool dc_link_dp_set_test_pattern( if (is_dp_phy_pattern(test_pattern)) { /* Set DPCD Lane Settings before running test pattern */ if (p_link_settings != NULL) { - dp_set_hw_lane_settings(core_link, p_link_settings); - dpcd_set_lane_settings(core_link, p_link_settings); + dp_set_hw_lane_settings(link, p_link_settings); + dpcd_set_lane_settings(link, p_link_settings); } /* Blank stream if running test pattern */ @@ -2471,15 +2463,15 @@ bool dc_link_dp_set_test_pattern( pipes->stream_enc->funcs->dp_blank(pipe_ctx.stream_enc); } - dp_set_hw_test_pattern(core_link, test_pattern, + dp_set_hw_test_pattern(link, test_pattern, (uint8_t *)p_custom_pattern, (uint32_t)cust_pattern_size); if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) { /* Set Test Pattern state */ - core_link->public.test_pattern_enabled = true; + link->test_pattern_enabled = true; if (p_link_settings != NULL) - dpcd_set_link_settings(core_link, + dpcd_set_link_settings(link, p_link_settings); } @@ -2516,7 +2508,7 @@ bool dc_link_dp_set_test_pattern( /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/) return false; - if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { /* tell receiver that we are sending qualification * pattern DP 1.2 or later - DP receiver's link quality * pattern is set using DPCD LINK_QUAL_LANEx_SET @@ -2526,12 +2518,12 @@ bool dc_link_dp_set_test_pattern( link_qual_pattern[lane] = (unsigned char)(pattern); - core_link_write_dpcd(core_link, + core_link_write_dpcd(link, DP_LINK_QUAL_LANE0_SET, link_qual_pattern, sizeof(link_qual_pattern)); - } else if (core_link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || - core_link->dpcd_caps.dpcd_rev.raw == 0) { + } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 || + link->dpcd_caps.dpcd_rev.raw == 0) { /* tell receiver that we are sending qualification * pattern DP 1.1a or earlier - DP receiver's link * quality pattern is set using @@ -2539,27 +2531,25 @@ bool dc_link_dp_set_test_pattern( * register (0x102). We will use v_1.3 when we are * setting test pattern for DP 1.1. */ - core_link_read_dpcd(core_link, - DP_TRAINING_PATTERN_SET, - &training_pattern.raw, - sizeof(training_pattern)); + core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern; - core_link_write_dpcd(core_link, - DP_TRAINING_PATTERN_SET, - &training_pattern.raw, - sizeof(training_pattern)); + core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET, + &training_pattern.raw, + sizeof(training_pattern)); } } else { /* CRTC Patterns */ - set_crtc_test_pattern(core_link, &pipe_ctx, test_pattern); + set_crtc_test_pattern(link, &pipe_ctx, test_pattern); /* Set Test Pattern state */ - core_link->public.test_pattern_enabled = true; + link->test_pattern_enabled = true; } return true; } -void dp_enable_mst_on_sink(struct core_link *link, bool enable) +void dp_enable_mst_on_sink(struct dc_link *link, bool enable) { unsigned char mstmCntl; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 0092e70b9efd..aac2420caefa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -16,13 +16,13 @@ #include "dpcd_defs.h" enum dc_status core_link_read_dpcd( - struct core_link* link, + struct dc_link *link, uint32_t address, uint8_t *data, uint32_t size) { if (!dm_helpers_dp_read_dpcd(link->ctx, - &link->public, + link, address, data, size)) return DC_ERROR_UNEXPECTED; @@ -30,20 +30,20 @@ enum dc_status core_link_read_dpcd( } enum dc_status core_link_write_dpcd( - struct core_link* link, + struct dc_link *link, uint32_t address, const uint8_t *data, uint32_t size) { if (!dm_helpers_dp_write_dpcd(link->ctx, - &link->public, + link, address, data, size)) return DC_ERROR_UNEXPECTED; return DC_OK; } -void dp_receiver_power_ctrl(struct core_link *link, bool on) +void dp_receiver_power_ctrl(struct dc_link *link, bool on) { uint8_t state; @@ -54,7 +54,7 @@ void dp_receiver_power_ctrl(struct core_link *link, bool on) } void dp_enable_link_phy( - struct core_link *link, + struct dc_link *link, enum signal_type signal, enum clock_source_id clock_source, const struct dc_link_settings *link_settings) @@ -107,7 +107,7 @@ void dp_enable_link_phy( dp_receiver_power_ctrl(link, true); } -void dp_disable_link_phy(struct core_link *link, enum signal_type signal) +void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) { if (!link->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(link, false); @@ -120,11 +120,11 @@ void dp_disable_link_phy(struct core_link *link, enum signal_type signal) link->link_enc->funcs->disable_output(link->link_enc, signal); /* Clear current link setting.*/ - memset(&link->public.cur_link_settings, 0, - sizeof(link->public.cur_link_settings)); + memset(&link->cur_link_settings, 0, + sizeof(link->cur_link_settings)); } -void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal) +void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal) { /* MST disable link only when no stream use the link */ if (link->mst_stream_alloc_table.stream_count > 0) @@ -137,7 +137,7 @@ void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal) } bool dp_set_hw_training_pattern( - struct core_link *link, + struct dc_link *link, enum hw_dp_training_pattern pattern) { enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; @@ -165,7 +165,7 @@ bool dp_set_hw_training_pattern( } void dp_set_hw_lane_settings( - struct core_link *link, + struct dc_link *link, const struct link_training_settings *link_settings) { struct link_encoder *encoder = link->link_enc; @@ -174,13 +174,13 @@ void dp_set_hw_lane_settings( encoder->funcs->dp_set_lane_settings(encoder, link_settings); } -enum dp_panel_mode dp_get_panel_mode(struct core_link *link) +enum dp_panel_mode dp_get_panel_mode(struct dc_link *link) { /* We need to explicitly check that connector * is not DP. Some Travis_VGA get reported * by video bios as DP. */ - if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { + if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) { switch (link->dpcd_caps.branch_dev_id) { case DP_BRANCH_DEVICE_ID_2: @@ -215,7 +215,7 @@ enum dp_panel_mode dp_get_panel_mode(struct core_link *link) } void dp_set_hw_test_pattern( - struct core_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, uint8_t *custom_pattern, uint32_t custom_pattern_size) @@ -231,7 +231,7 @@ void dp_set_hw_test_pattern( encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); } -void dp_retrain_link_dp_test(struct core_link *link, +void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern) { @@ -263,8 +263,8 @@ void dp_retrain_link_dp_test(struct core_link *link, SIGNAL_TYPE_DISPLAY_PORT); /* Clear current link setting. */ - memset(&link->public.cur_link_settings, 0, - sizeof(link->public.cur_link_settings)); + memset(&link->cur_link_settings, 0, + sizeof(link->cur_link_settings)); link->link_enc->funcs->enable_dp_output( link->link_enc, @@ -274,11 +274,11 @@ void dp_retrain_link_dp_test(struct core_link *link, dp_receiver_power_ctrl(link, true); dc_link_dp_perform_link_training( - &link->public, + link, link_setting, skip_video_pattern); - link->public.cur_link_settings = *link_setting; + link->cur_link_settings = *link_setting; link->dc->hwss.enable_stream(&pipes[i]); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 303c95432d5b..7a3d090f8465 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1269,7 +1269,7 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link( { int i; int j = -1; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; for (i = 0; i < pool->stream_enc_count; i++) { if (!res_ctx->is_stream_enc_acquired[i] && @@ -1322,9 +1322,7 @@ static void update_stream_signal(struct core_stream *stream) const struct dc_sink *dc_sink = stream->public.sink; if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = - stream->sink->link-> - public.connector_signal; + stream->signal = stream->sink->link->connector_signal; else stream->signal = dc_sink->sink_signal; } else { @@ -1380,7 +1378,7 @@ static struct core_stream *find_pll_sharable_stream( if (resource_are_streams_timing_synchronizable( stream_needs_pll, stream_has_pll) && !dc_is_dp_signal(stream_has_pll->signal) - && stream_has_pll->sink->link->public.connector_signal + && stream_has_pll->sink->link->connector_signal != SIGNAL_TYPE_VIRTUAL) return stream_has_pll; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index da9955675fbf..7f0ba7267682 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -54,15 +54,14 @@ static void destruct(struct sink *sink) static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params) { - struct core_link *core_link = DC_LINK_TO_LINK(init_params->link); + struct dc_link *link = init_params->link; - if (!core_link) { + if (!link) return false; - } sink->protected.public.sink_signal = init_params->sink_signal; - sink->protected.link = core_link; - sink->protected.ctx = core_link->ctx; + sink->protected.link = link; + sink->protected.ctx = link->ctx; sink->protected.public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; sink->protected.public.converter_disable_audio = init_params->converter_disable_audio; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 73712fd6f64a..a329709de360 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -91,7 +91,7 @@ static bool construct(struct core_stream *stream, /* EDID CAP translation for HDMI 2.0 */ stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; - stream->status.link = &stream->sink->link->public; + stream->status.link = stream->sink->link; return true; } @@ -355,5 +355,5 @@ void dc_stream_log( dm_logger_write(dm_logger, log_type, "\tlink: %d\n", - core_stream->sink->link->public.link_index); + core_stream->sink->link->link_index); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b14bad10db97..e15e8fb1eefe 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -31,6 +31,7 @@ #include "logger_types.h" #include "gpio_types.h" #include "link_service_types.h" +#include "grph_object_ctrl_defs.h" #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -141,11 +142,11 @@ struct dc_link_funcs { bool skip_video_pattern); void (*set_preferred_link_settings)(struct dc *dc, struct dc_link_settings *link_setting, - const struct dc_link *link); + struct dc_link *link); void (*enable_hpd)(const struct dc_link *link); void (*disable_hpd)(const struct dc_link *link); void (*set_test_pattern)( - const struct dc_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, const struct link_training_settings *p_link_settings, const unsigned char *p_custom_pattern, @@ -641,7 +642,7 @@ struct dc_stream_status { /* * link this stream passes through */ - const struct dc_link *link; + struct dc_link *link; }; struct dc_stream_status *dc_stream_get_status( @@ -662,6 +663,50 @@ void dc_release_validate_context(struct validate_context *context); * Link Interfaces ******************************************************************************/ +struct dpcd_caps { + union dpcd_rev dpcd_rev; + union max_lane_count max_ln_count; + union max_down_spread max_down_spread; + + /* dongle type (DP converter, CV smart dongle) */ + enum display_dongle_type dongle_type; + /* Dongle's downstream count. */ + union sink_count sink_count; + /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, + indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ + struct dc_dongle_caps dongle_caps; + + uint32_t sink_dev_id; + uint32_t branch_dev_id; + int8_t branch_dev_name[6]; + int8_t branch_hw_revision; + + bool allow_invalid_MSA_timing_param; + bool panel_mode_edp; +}; + +struct dc_link_status { + struct dpcd_caps *dpcd_caps; +}; + +/* DP MST stream allocation (payload bandwidth number) */ +struct link_mst_stream_allocation { + /* DIG front */ + const struct stream_encoder *stream_enc; + /* associate DRM payload table with DC stream encoder */ + uint8_t vcp_id; + /* number of slots required for the DP stream in transport packet */ + uint8_t slot_count; +}; + +/* DP MST stream allocation table */ +struct link_mst_stream_allocation_table { + /* number of DP video streams */ + int stream_count; + /* array of stream allocations */ + struct link_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; +}; + /* * A link contains one or more sinks and their connected status. * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. @@ -699,32 +744,31 @@ struct dc_link { struct ddc_service *ddc; bool aux_mode; -}; -struct dpcd_caps { - union dpcd_rev dpcd_rev; - union max_lane_count max_ln_count; - union max_down_spread max_down_spread; + /* Private to DC core */ - /* dongle type (DP converter, CV smart dongle) */ - enum display_dongle_type dongle_type; - /* Dongle's downstream count. */ - union sink_count sink_count; - /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, - indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ - struct dc_dongle_caps dongle_caps; + const struct core_dc *dc; - uint32_t sink_dev_id; - uint32_t branch_dev_id; - int8_t branch_dev_name[6]; - int8_t branch_hw_revision; + struct dc_context *ctx; - bool allow_invalid_MSA_timing_param; - bool panel_mode_edp; -}; + struct link_encoder *link_enc; + struct graphics_object_id link_id; + union ddi_channel_mapping ddi_channel_mapping; + struct connector_device_tag_info device_tag; + struct dpcd_caps dpcd_caps; + unsigned int dpcd_sink_count; + + enum edp_revision edp_revision; + bool psr_enabled; + + /* MST record stream using this link */ + struct link_flags { + bool dp_keep_receiver_powered; + } wa_flags; + struct link_mst_stream_allocation_table mst_stream_alloc_table; + + struct dc_link_status link_status; -struct dc_link_status { - struct dpcd_caps *dpcd_caps; }; const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); @@ -734,7 +778,7 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); * boot time. They cannot be created or destroyed. * Use dc_get_caps() to get number of links. */ -const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); +struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); /* Return id of physical connector represented by a dc_link at link_index.*/ const struct graphics_object_id dc_get_link_id_at_index( @@ -750,7 +794,7 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); -bool dc_link_setup_psr(const struct dc_link *dc_link, +bool dc_link_setup_psr(struct dc_link *dc_link, const struct dc_stream *stream, struct psr_config *psr_config, struct psr_context *psr_context); @@ -760,7 +804,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link, * true otherwise. True meaning further action is required (status update * and OS notification). */ -bool dc_link_detect(const struct dc_link *dc_link, bool boot); +bool dc_link_detect(struct dc_link *dc_link, bool boot); /* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). * Return: @@ -768,26 +812,26 @@ bool dc_link_detect(const struct dc_link *dc_link, bool boot); * detection. * false - no change in Downstream port status. No further action required * from DM. */ -bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link, +bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link, union hpd_irq_data *hpd_irq_dpcd_data); struct dc_sink_init_data; struct dc_sink *dc_link_add_remote_sink( - const struct dc_link *dc_link, + struct dc_link *dc_link, const uint8_t *edid, int len, struct dc_sink_init_data *init_data); void dc_link_remove_remote_sink( - const struct dc_link *link, + struct dc_link *link, const struct dc_sink *sink); /* Used by diagnostics for virtual link at the moment */ -void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink); +void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink); void dc_link_dp_set_drive_settings( - const struct dc_link *link, + struct dc_link *link, struct link_training_settings *lt_settings); enum link_training_result dc_link_dp_perform_link_training( @@ -800,7 +844,7 @@ void dc_link_dp_enable_hpd(const struct dc_link *link); void dc_link_dp_disable_hpd(const struct dc_link *link); bool dc_link_dp_set_test_pattern( - const struct dc_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, const struct link_training_settings *p_link_settings, const unsigned char *p_custom_pattern, @@ -844,7 +888,7 @@ const struct audio **dc_get_audios(struct dc *dc); struct dc_sink_init_data { enum signal_type sink_signal; - const struct dc_link *link; + struct dc_link *link; uint32_t dongle_max_pix_clk; bool converter_disable_audio; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h index b143fe88f49f..e1affeb5cc51 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_ddc_types.h @@ -105,7 +105,7 @@ struct ddc_service { enum ddc_transaction_type transaction_type; enum display_dongle_type dongle_type; struct dc_context *ctx; - struct core_link *link; + struct dc_link *link; uint32_t address; uint32_t edid_buf_len; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 0fe3ee8e29d3..aaff946a6d0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -142,7 +142,7 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) } static void dce_dmcu_setup_psr(struct dmcu *dmcu, - struct core_link *link, + struct dc_link *link, struct psr_context *psr_context) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); @@ -382,7 +382,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) } static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, - struct core_link *link, + struct dc_link *link, struct psr_context *psr_context) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 5663d3dbd7d5..318673da189b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1020,7 +1020,7 @@ bool dce110_link_encoder_validate_output_with_stream( case SIGNAL_TYPE_DVI_DUAL_LINK: is_valid = dce110_link_encoder_validate_dvi_output( enc110, - stream->sink->link->public.connector_signal, + stream->sink->link->connector_signal, pipe_ctx->stream->signal, &stream->public.timing); break; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 716f664f40ce..6938158bed7f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -661,7 +661,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index cf6bf2098b7c..fe8084e290a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -700,10 +700,10 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) void dce110_enable_stream(struct pipe_ctx *pipe_ctx) { enum dc_lane_count lane_count = - pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count; + pipe_ctx->stream->sink->link->cur_link_settings.lane_count; struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; - struct core_link *link = pipe_ctx->stream->sink->link; + struct dc_link *link = pipe_ctx->stream->sink->link; /* 1. update AVI info frame (HDMI, DP) * we always need to update info frame @@ -746,7 +746,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { struct core_stream *stream = pipe_ctx->stream; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (pipe_ctx->audio) { pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio); @@ -1111,7 +1111,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( dce110_update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) dce110_unblank_stream(pipe_ctx, - &stream->sink->link->public.cur_link_settings); + &stream->sink->link->cur_link_settings); } pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; @@ -2220,7 +2220,7 @@ static void init_hw(struct core_dc *dc) /* Power up AND update implementation according to the * required signal (which may be different from the * default signal on connector). */ - struct core_link *link = dc->links[i]; + struct dc_link *link = dc->links[i]; link->link_enc->funcs->hw_init(link->link_enc); } @@ -2283,11 +2283,11 @@ void dce110_fill_display_configs( cfg->transmitter = stream->sink->link->link_enc->transmitter; cfg->link_settings.lane_count = - stream->sink->link->public.cur_link_settings.lane_count; + stream->sink->link->cur_link_settings.lane_count; cfg->link_settings.link_rate = - stream->sink->link->public.cur_link_settings.link_rate; + stream->sink->link->cur_link_settings.link_rate; cfg->link_settings.link_spread = - stream->sink->link->public.cur_link_settings.link_spread; + stream->sink->link->cur_link_settings.link_spread; cfg->sym_clock = stream->phy_pix_clk; /* Round v_refresh*/ cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 0fcb1cf4b4ce..015306a6ef88 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -781,7 +781,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 80f067343a91..ca1e13e2a3db 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -730,7 +730,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 5861b3fdf7d2..b2319dbf3be3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -677,7 +677,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4390023ca6dc..c25a39214111 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -628,7 +628,7 @@ static void dcn10_init_hw(struct core_dc *dc) * required signal (which may be different from the * default signal on connector). */ - struct core_link *link = dc->links[i]; + struct dc_link *link = dc->links[i]; link->link_enc->funcs->hw_init(link->link_enc); } @@ -2259,7 +2259,7 @@ static void dcn10_config_stereo_parameters( timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) { enum display_dongle_type dongle = \ - stream->sink->link->public.ddc->dongle_type; + stream->sink->link->ddc->dongle_type; if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER || dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER || dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index eec0d5b22a9f..0110a431e289 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -845,7 +845,7 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct core_link *link = stream->sink->link; + struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 785236a44aee..1ecb54603e17 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -20,7 +20,7 @@ struct core_dc { struct dc_context *ctx; uint8_t link_count; - struct core_link *links[MAX_PIPES * 2]; + struct dc_link *links[MAX_PIPES * 2]; struct validate_context *current_context; struct resource_pool *res_pool; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 07a1aec5a28b..6cdfeeba0faf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -92,13 +92,11 @@ struct core_sink { /** The 'protected' area - read/write access, for use only inside DC **/ /* not used for now */ - struct core_link *link; + struct dc_link *link; struct dc_context *ctx; }; /************ link *****************/ -#define DC_LINK_TO_CORE(dc_link) container_of(dc_link, struct core_link, public) - struct link_init_data { const struct core_dc *dc; struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ @@ -107,61 +105,15 @@ struct link_init_data { TODO: remove it when DC is complete. */ }; -/* DP MST stream allocation (payload bandwidth number) */ -struct link_mst_stream_allocation { - /* DIG front */ - const struct stream_encoder *stream_enc; - /* associate DRM payload table with DC stream encoder */ - uint8_t vcp_id; - /* number of slots required for the DP stream in transport packet */ - uint8_t slot_count; -}; - -/* DP MST stream allocation table */ -struct link_mst_stream_allocation_table { - /* number of DP video streams */ - int stream_count; - /* array of stream allocations */ - struct link_mst_stream_allocation - stream_allocations[MAX_CONTROLLER_NUM]; -}; - -struct core_link { - struct dc_link public; - const struct core_dc *dc; - - struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/ - - struct link_encoder *link_enc; - struct graphics_object_id link_id; - union ddi_channel_mapping ddi_channel_mapping; - struct connector_device_tag_info device_tag; - struct dpcd_caps dpcd_caps; - unsigned int dpcd_sink_count; - - enum edp_revision edp_revision; - bool psr_enabled; - - /* MST record stream using this link */ - struct link_flags { - bool dp_keep_receiver_powered; - } wa_flags; - struct link_mst_stream_allocation_table mst_stream_alloc_table; - - struct dc_link_status link_status; -}; - -#define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public) - -struct core_link *link_create(const struct link_init_data *init_params); -void link_destroy(struct core_link **link); +struct dc_link *link_create(const struct link_init_data *init_params); +void link_destroy(struct dc_link **link); enum dc_status dc_link_validate_mode_timing( const struct core_stream *stream, - struct core_link *link, + struct dc_link *link, const struct dc_crtc_timing *timing); -void core_link_resume(struct core_link *link); +void core_link_resume(struct dc_link *link); void core_link_enable_stream(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h index 9c2f670c3dc3..af7ea5eaf185 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -84,7 +84,7 @@ void dal_ddc_aux_payloads_add( struct ddc_service_init_data { struct graphics_object_id id; struct dc_context *ctx; - struct core_link *link; + struct dc_link *link; }; struct ddc_service *dal_ddc_service_create( diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index b6ef1bfd267c..d9af028a39df 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -29,12 +29,12 @@ #define LINK_TRAINING_ATTEMPTS 4 #define LINK_TRAINING_RETRY_DELAY 50 /* ms */ -struct core_link; +struct dc_link; struct core_stream; struct dc_link_settings; bool dp_hbr_verify_link_cap( - struct core_link *link, + struct dc_link *link, struct dc_link_settings *known_limit_link_setting); bool decide_fallback_link_setting(struct dc_link_settings link_setting_init, @@ -46,7 +46,7 @@ struct dc_link_settings get_common_supported_link_settings ( struct dc_link_settings link_setting_b); bool dp_validate_mode_timing( - struct core_link *link, + struct dc_link *link, const struct dc_crtc_timing *timing); void decide_link_settings( @@ -54,17 +54,17 @@ void decide_link_settings( struct dc_link_settings *link_setting); bool perform_link_training_with_retries( - struct core_link *link, + struct dc_link *link, const struct dc_link_settings *link_setting, bool skip_video_pattern, int attempts); -bool is_mst_supported(struct core_link *link); +bool is_mst_supported(struct dc_link *link); -void detect_dp_sink_caps(struct core_link *link); +void detect_dp_sink_caps(struct dc_link *link); -bool is_dp_active_dongle(const struct core_link *link); +bool is_dp_active_dongle(const struct dc_link *link); -void dp_enable_mst_on_sink(struct core_link *link, bool enable); +void dp_enable_mst_on_sink(struct dc_link *link, bool enable); #endif /* __DC_LINK_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index 6067f464d805..e34b25939a98 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -39,7 +39,7 @@ struct dmcu_funcs { unsigned int bytes); void (*set_psr_enable)(struct dmcu *dmcu, bool enable); void (*setup_psr)(struct dmcu *dmcu, - struct core_link *link, + struct dc_link *link, struct psr_context *psr_context); void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); void (*set_psr_wait_loop)(struct dmcu *dmcu, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 75d10e93b002..f7994cfc850d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -29,46 +29,46 @@ #include "inc/core_status.h" enum dc_status core_link_read_dpcd( - struct core_link* link, + struct dc_link *link, uint32_t address, uint8_t *data, uint32_t size); enum dc_status core_link_write_dpcd( - struct core_link* link, + struct dc_link *link, uint32_t address, const uint8_t *data, uint32_t size); void dp_enable_link_phy( - struct core_link *link, + struct dc_link *link, enum signal_type signal, enum clock_source_id clock_source, const struct dc_link_settings *link_settings); -void dp_receiver_power_ctrl(struct core_link *link, bool on); +void dp_receiver_power_ctrl(struct dc_link *link, bool on); -void dp_disable_link_phy(struct core_link *link, enum signal_type signal); +void dp_disable_link_phy(struct dc_link *link, enum signal_type signal); -void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal); +void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal); bool dp_set_hw_training_pattern( - struct core_link *link, + struct dc_link *link, enum hw_dp_training_pattern pattern); void dp_set_hw_lane_settings( - struct core_link *link, + struct dc_link *link, const struct link_training_settings *link_settings); void dp_set_hw_test_pattern( - struct core_link *link, + struct dc_link *link, enum dp_test_pattern test_pattern, uint8_t *custom_pattern, uint32_t custom_pattern_size); -enum dp_panel_mode dp_get_panel_mode(struct core_link *link); +enum dp_panel_mode dp_get_panel_mode(struct dc_link *link); -void dp_retrain_link_dp_test(struct core_link *link, +void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern); diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 6e6fd4e8fc00..3adf3cfc7aba 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -140,19 +140,19 @@ void context_clock_trace( */ #define CONN_DATA_DETECT(link, hex_data, hex_len, ...) \ - dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \ + dc_conn_log(link->ctx, link, hex_data, hex_len, \ LOG_EVENT_DETECTION, ##__VA_ARGS__) #define CONN_DATA_LINK_LOSS(link, hex_data, hex_len, ...) \ - dc_conn_log(link->ctx, &link->public, hex_data, hex_len, \ + dc_conn_log(link->ctx, link, hex_data, hex_len, \ LOG_EVENT_LINK_LOSS, ##__VA_ARGS__) #define CONN_MSG_LT(link, ...) \ - dc_conn_log(link->ctx, &link->public, NULL, 0, \ + dc_conn_log(link->ctx, link, NULL, 0, \ LOG_EVENT_LINK_TRAINING, ##__VA_ARGS__) #define CONN_MSG_MODE(link, ...) \ - dc_conn_log(link->ctx, &link->public, NULL, 0, \ + dc_conn_log(link->ctx, link, NULL, 0, \ LOG_EVENT_MODE_SET, ##__VA_ARGS__) #endif /* __DAL_LOGGER_INTERFACE_H__ */ -- GitLab From 89899039356a645c1cebe5a454d3577aa1f42bf2 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 13:55:26 -0400 Subject: [PATCH 0680/2898] drm/amd/display: Roll sink struct into core_sink Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 43 +++++++------------ .../gpu/drm/amd/display/dc/inc/core_types.h | 3 ++ 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 7f0ba7267682..1f7985ad5dba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -27,31 +27,19 @@ #include "dm_helpers.h" #include "core_types.h" -/******************************************************************************* - * Private definitions - ******************************************************************************/ - -struct sink { - struct core_sink protected; - int ref_count; -}; - -#define DC_SINK_TO_SINK(dc_sink) \ - container_of(dc_sink, struct sink, protected.public) - /******************************************************************************* * Private functions ******************************************************************************/ -static void destruct(struct sink *sink) +static void destruct(struct core_sink *sink) { - if (sink->protected.public.dc_container_id) { - dm_free(sink->protected.public.dc_container_id); - sink->protected.public.dc_container_id = NULL; + if (sink->public.dc_container_id) { + dm_free(sink->public.dc_container_id); + sink->public.dc_container_id = NULL; } } -static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params) +static bool construct(struct core_sink *sink, const struct dc_sink_init_data *init_params) { struct dc_link *link = init_params->link; @@ -59,13 +47,12 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa if (!link) return false; - sink->protected.public.sink_signal = init_params->sink_signal; - sink->protected.link = link; - sink->protected.ctx = link->ctx; - sink->protected.public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; - sink->protected.public.converter_disable_audio = - init_params->converter_disable_audio; - sink->protected.public.dc_container_id = NULL; + sink->public.sink_signal = init_params->sink_signal; + sink->link = link; + sink->ctx = link->ctx; + sink->public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; + sink->public.converter_disable_audio = init_params->converter_disable_audio; + sink->public.dc_container_id = NULL; return true; } @@ -76,7 +63,7 @@ static bool construct(struct sink *sink, const struct dc_sink_init_data *init_pa void dc_sink_retain(const struct dc_sink *dc_sink) { - struct sink *sink = DC_SINK_TO_SINK(dc_sink); + struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); ASSERT(sink->ref_count > 0); ++sink->ref_count; @@ -84,7 +71,7 @@ void dc_sink_retain(const struct dc_sink *dc_sink) void dc_sink_release(const struct dc_sink *dc_sink) { - struct sink *sink = DC_SINK_TO_SINK(dc_sink); + struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); ASSERT(sink->ref_count > 0); --sink->ref_count; @@ -97,7 +84,7 @@ void dc_sink_release(const struct dc_sink *dc_sink) struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) { - struct sink *sink = dm_alloc(sizeof(*sink)); + struct core_sink *sink = dm_alloc(sizeof(*sink)); if (NULL == sink) goto alloc_fail; @@ -107,7 +94,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) ++sink->ref_count; - return &sink->protected.public; + return &sink->public; construct_fail: dm_free(sink); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 6cdfeeba0faf..eed31a827a90 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -94,6 +94,9 @@ struct core_sink { /* not used for now */ struct dc_link *link; struct dc_context *ctx; + + /* private to dc_sink.c */ + int ref_count; }; /************ link *****************/ -- GitLab From b73a22d3257f9ec237c46be12d74b58d5a925d8c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 14:04:27 -0400 Subject: [PATCH 0681/2898] drm/amd/display: Roll core_sink into dc_sink Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 4 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 60 +++++++++---------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 30 ++++------ .../gpu/drm/amd/display/dc/core/dc_stream.c | 15 +++-- drivers/gpu/drm/amd/display/dc/dc.h | 19 ++++-- .../display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 21 +------ 11 files changed, 72 insertions(+), 91 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index c558f700df35..8d939e3b3f15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -562,9 +562,9 @@ struct amdgpu_connector { int num_modes; /* The 'old' sink - before an HPD. * The 'current' sink is in dc_link->sink. */ - const struct dc_sink *dc_sink; + struct dc_sink *dc_sink; struct dc_link *dc_link; - const struct dc_sink *dc_em_sink; + struct dc_sink *dc_em_sink; const struct dc_stream *stream; void *con_priv; bool dac_load_detect; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 26fbadba97dd..696a4112c8d9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -697,7 +697,7 @@ void amdgpu_dm_update_connector_after_detect( { struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; - const struct dc_sink *sink; + struct dc_sink *sink; /* MST handled by drm_mst framework */ if (aconnector->mst_mgr.mst_state == true) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 4885403f5cec..13708bcb83cd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -1266,7 +1266,7 @@ int amdgpu_dm_connector_mode_valid( struct drm_display_mode *mode) { int result = MODE_ERROR; - const struct dc_sink *dc_sink; + struct dc_sink *dc_sink; struct amdgpu_device *adev = connector->dev->dev_private; struct dc_validation_set val_set = { 0 }; /* TODO: Unhardcode stream count */ @@ -1535,7 +1535,7 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, struct drm_display_mode *mode, struct dc_validation_set *val_set) { int result = MODE_ERROR; - const struct dc_sink *dc_sink = + struct dc_sink *dc_sink = to_amdgpu_connector(connector)->dc_sink; /* TODO: Unhardcode stream count */ struct dc_stream *stream; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 73740e2a5819..30374ffaae0b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -939,7 +939,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c program_timing_sync(core_dc, context); for (i = 0; i < context->stream_count; i++) { - const struct core_sink *sink = context->streams[i]->sink; + const struct dc_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].surface_count; j++) { const struct dc_surface *surface = @@ -1984,7 +1984,7 @@ void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink) } } -void dc_link_remove_remote_sink(struct dc_link *link, const struct dc_sink *sink) +void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 428dbff8505b..e7062069d9a1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -541,8 +541,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) struct audio_support *aud_support = &link->dc->res_pool->audio_support; enum dc_edid_status edid_status; struct dc_context *dc_ctx = link->ctx; - struct dc_sink *dc_sink; - struct core_sink *sink = NULL; + struct dc_sink *sink; enum dc_connection_type new_connection_type = dc_connection_none; if (link->connector_signal == SIGNAL_TYPE_VIRTUAL) @@ -637,22 +636,21 @@ bool dc_link_detect(struct dc_link *link, bool boot) sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; - dc_sink = dc_sink_create(&sink_init_data); - if (!dc_sink) { + sink = dc_sink_create(&sink_init_data); + if (!sink) { DC_ERROR("Failed to create sink!\n"); return false; } - dc_sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; - dc_sink->converter_disable_audio = converter_disable_audio; + sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->converter_disable_audio = converter_disable_audio; - sink = DC_SINK_TO_CORE(dc_sink); - link->local_sink = &sink->public; + link->local_sink = sink; edid_status = dm_helpers_read_local_edid( link->ctx, link, - &sink->public); + sink); switch (edid_status) { case EDID_BAD_CHECKSUM: @@ -669,16 +667,16 @@ bool dc_link_detect(struct dc_link *link, bool boot) } /* HDMI-DVI Dongle */ - if (dc_sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && - !dc_sink->edid_caps.edid_hdmi) - dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && + !sink->edid_caps.edid_hdmi) + sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; /* Connectivity log: detection */ - for (i = 0; i < sink->public.dc_edid.length / EDID_BLOCK_SIZE; i++) { + for (i = 0; i < sink->dc_edid.length / EDID_BLOCK_SIZE; i++) { CONN_DATA_DETECT(link, - &sink->public.dc_edid.raw_edid[i * EDID_BLOCK_SIZE], + &sink->dc_edid.raw_edid[i * EDID_BLOCK_SIZE], EDID_BLOCK_SIZE, - "%s: [Block %d] ", sink->public.edid_caps.display_name, i); + "%s: [Block %d] ", sink->edid_caps.display_name, i); } dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER, @@ -692,16 +690,16 @@ bool dc_link_detect(struct dc_link *link, bool boot) "speaker_flag = %d, " "audio_mode_count = %d\n", __func__, - sink->public.edid_caps.manufacturer_id, - sink->public.edid_caps.product_id, - sink->public.edid_caps.serial_number, - sink->public.edid_caps.manufacture_week, - sink->public.edid_caps.manufacture_year, - sink->public.edid_caps.display_name, - sink->public.edid_caps.speaker_flags, - sink->public.edid_caps.audio_mode_count); - - for (i = 0; i < sink->public.edid_caps.audio_mode_count; i++) { + sink->edid_caps.manufacturer_id, + sink->edid_caps.product_id, + sink->edid_caps.serial_number, + sink->edid_caps.manufacture_week, + sink->edid_caps.manufacture_year, + sink->edid_caps.display_name, + sink->edid_caps.speaker_flags, + sink->edid_caps.audio_mode_count); + + for (i = 0; i < sink->edid_caps.audio_mode_count; i++) { dm_logger_write(link->ctx->logger, LOG_DETECTION_EDID_PARSER, "%s: mode number = %d, " "format_code = %d, " @@ -710,10 +708,10 @@ bool dc_link_detect(struct dc_link *link, bool boot) "sample_size = %d\n", __func__, i, - sink->public.edid_caps.audio_modes[i].format_code, - sink->public.edid_caps.audio_modes[i].channel_count, - sink->public.edid_caps.audio_modes[i].sample_rate, - sink->public.edid_caps.audio_modes[i].sample_size); + sink->edid_caps.audio_modes[i].format_code, + sink->edid_caps.audio_modes[i].channel_count, + sink->edid_caps.audio_modes[i].sample_rate, + sink->edid_caps.audio_modes[i].sample_size); } } else { @@ -732,7 +730,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) } LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", - link->link_index, &sink->public, + link->link_index, sink, (sink_caps.signal == SIGNAL_TYPE_NONE ? "Disconnected":"Connected")); @@ -1347,7 +1345,7 @@ enum dc_status dc_link_validate_mode_timing( struct dc_link *link, const struct dc_crtc_timing *timing) { - uint32_t max_pix_clk = stream->sink->public.dongle_max_pix_clk; + uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk; /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7a3d090f8465..7cb572ff3cba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1528,7 +1528,7 @@ enum dc_status resource_map_pool_resources( pipe_ctx->stream_enc); /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->public.converter_disable_audio && + if (!stream->sink->converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->public.audio_info.mode_count) { pipe_ctx->audio = find_first_free_audio( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 1f7985ad5dba..a83f1243a9d1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -31,15 +31,15 @@ * Private functions ******************************************************************************/ -static void destruct(struct core_sink *sink) +static void destruct(struct dc_sink *sink) { - if (sink->public.dc_container_id) { - dm_free(sink->public.dc_container_id); - sink->public.dc_container_id = NULL; + if (sink->dc_container_id) { + dm_free(sink->dc_container_id); + sink->dc_container_id = NULL; } } -static bool construct(struct core_sink *sink, const struct dc_sink_init_data *init_params) +static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init_params) { struct dc_link *link = init_params->link; @@ -47,12 +47,12 @@ static bool construct(struct core_sink *sink, const struct dc_sink_init_data *in if (!link) return false; - sink->public.sink_signal = init_params->sink_signal; + sink->sink_signal = init_params->sink_signal; sink->link = link; sink->ctx = link->ctx; - sink->public.dongle_max_pix_clk = init_params->dongle_max_pix_clk; - sink->public.converter_disable_audio = init_params->converter_disable_audio; - sink->public.dc_container_id = NULL; + sink->dongle_max_pix_clk = init_params->dongle_max_pix_clk; + sink->converter_disable_audio = init_params->converter_disable_audio; + sink->dc_container_id = NULL; return true; } @@ -61,18 +61,14 @@ static bool construct(struct core_sink *sink, const struct dc_sink_init_data *in * Public functions ******************************************************************************/ -void dc_sink_retain(const struct dc_sink *dc_sink) +void dc_sink_retain(struct dc_sink *sink) { - struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); - ASSERT(sink->ref_count > 0); ++sink->ref_count; } -void dc_sink_release(const struct dc_sink *dc_sink) +void dc_sink_release(struct dc_sink *sink) { - struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); - ASSERT(sink->ref_count > 0); --sink->ref_count; @@ -84,7 +80,7 @@ void dc_sink_release(const struct dc_sink *dc_sink) struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) { - struct core_sink *sink = dm_alloc(sizeof(*sink)); + struct dc_sink *sink = dm_alloc(sizeof(*sink)); if (NULL == sink) goto alloc_fail; @@ -94,7 +90,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) ++sink->ref_count; - return &sink->public; + return sink; construct_fail: dm_free(sink); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index a329709de360..5b356ddf5614 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -46,11 +46,11 @@ struct stream { ******************************************************************************/ static bool construct(struct core_stream *stream, - const struct dc_sink *dc_sink_data) + struct dc_sink *dc_sink_data) { uint32_t i = 0; - stream->sink = DC_SINK_TO_CORE(dc_sink_data); + stream->sink = dc_sink_data; stream->ctx = stream->sink->ctx; stream->public.sink = dc_sink_data; @@ -97,7 +97,7 @@ static bool construct(struct core_stream *stream, static void destruct(struct core_stream *stream) { - dc_sink_release(&stream->sink->public); + dc_sink_release(stream->sink); if (stream->public.out_transfer_func != NULL) { dc_transfer_func_release( stream->public.out_transfer_func); @@ -130,9 +130,8 @@ void dc_stream_release(const struct dc_stream *public) } struct dc_stream *dc_create_stream_for_sink( - const struct dc_sink *dc_sink) + struct dc_sink *sink) { - struct core_sink *sink = DC_SINK_TO_CORE(dc_sink); struct stream *stream; if (sink == NULL) @@ -143,7 +142,7 @@ struct dc_stream *dc_create_stream_for_sink( if (NULL == stream) goto alloc_fail; - if (false == construct(&stream->protected, dc_sink)) + if (false == construct(&stream->protected, sink)) goto construct_fail; stream->ref_count++; @@ -350,8 +349,8 @@ void dc_stream_log( dm_logger_write(dm_logger, log_type, "\tsink name: %s, serial: %d\n", - core_stream->sink->public.edid_caps.display_name, - core_stream->sink->public.edid_caps.serial_number); + core_stream->sink->edid_caps.display_name, + core_stream->sink->edid_caps.serial_number); dm_logger_write(dm_logger, log_type, "\tlink: %d\n", diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e15e8fb1eefe..77bd54659a8b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -629,7 +629,7 @@ bool dc_enable_stereo( /** * Create a new default stream for the requested sink */ -struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink); +struct dc_stream *dc_create_stream_for_sink(struct dc_sink *dc_sink); void dc_stream_retain(const struct dc_stream *dc_stream); void dc_stream_release(const struct dc_stream *dc_stream); @@ -712,9 +712,9 @@ struct link_mst_stream_allocation_table { * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. */ struct dc_link { - const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; + struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; unsigned int sink_count; - const struct dc_sink *local_sink; + struct dc_sink *local_sink; unsigned int link_index; enum dc_connection_type type; enum signal_type connector_signal; @@ -825,7 +825,7 @@ struct dc_sink *dc_link_add_remote_sink( void dc_link_remove_remote_sink( struct dc_link *link, - const struct dc_sink *sink); + struct dc_sink *sink); /* Used by diagnostics for virtual link at the moment */ void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink); @@ -879,10 +879,17 @@ struct dc_sink { void *priv; struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX]; bool converter_disable_audio; + + /* private to DC core */ + struct dc_link *link; + struct dc_context *ctx; + + /* private to dc_sink.c */ + int ref_count; }; -void dc_sink_retain(const struct dc_sink *sink); -void dc_sink_release(const struct dc_sink *sink); +void dc_sink_retain(struct dc_sink *sink); +void dc_sink_release(struct dc_sink *sink); const struct audio **dc_get_audios(struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index fe8084e290a3..58701fdb7c94 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -657,7 +657,7 @@ static enum dc_status bios_parser_crtc_source_select( * encoder block * note: video bios clears all FMT setting here. */ struct bp_crtc_source_select crtc_source_select = {0}; - const struct core_sink *sink = pipe_ctx->stream->sink; + const struct dc_sink *sink = pipe_ctx->stream->sink; crtc_source_select.engine_id = pipe_ctx->stream_enc->id; crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index eed31a827a90..1d733c837854 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -68,7 +68,7 @@ struct core_stream { /* field internal to DC */ struct dc_context *ctx; - const struct core_sink *sink; + struct dc_sink *sink; /* used by DCP and FMT */ struct bit_depth_reduction_params bit_depth_params; @@ -80,25 +80,6 @@ struct core_stream { struct dc_stream_status status; }; -/************ core_sink *****************/ - -#define DC_SINK_TO_CORE(dc_sink) \ - container_of(dc_sink, struct core_sink, public) - -struct core_sink { - /** The public, read-only (for DM) area of sink. **/ - struct dc_sink public; - /** End-of-public area. **/ - - /** The 'protected' area - read/write access, for use only inside DC **/ - /* not used for now */ - struct dc_link *link; - struct dc_context *ctx; - - /* private to dc_sink.c */ - int ref_count; -}; - /************ link *****************/ struct link_init_data { const struct core_dc *dc; -- GitLab From 0b0aab86d51ee63d521f0d96ff4dfe1d6252f9b2 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 15:20:50 -0400 Subject: [PATCH 0682/2898] drm/amd/display: Roll gamma struct into core_gamma Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_surface.c | 21 ++++--------------- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 +++ 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 9a21ea71f4b3..a8b9515fd367 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -31,19 +31,6 @@ #include "core_dc.h" #include "transform.h" -/******************************************************************************* - * Private structures - ******************************************************************************/ -struct gamma { - struct core_gamma protected; - int ref_count; -}; - -#define DC_GAMMA_TO_GAMMA(dc_gamma) \ - container_of(dc_gamma, struct gamma, protected.public) -#define CORE_GAMMA_TO_GAMMA(core_gamma) \ - container_of(core_gamma, struct gamma, protected) - /******************************************************************************* * Private functions ******************************************************************************/ @@ -152,7 +139,7 @@ void dc_surface_release(struct dc_surface *surface) void dc_gamma_retain(const struct dc_gamma *dc_gamma) { - struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); + struct core_gamma *gamma = DC_GAMMA_TO_CORE(dc_gamma); ASSERT(gamma->ref_count > 0); ++gamma->ref_count; @@ -160,7 +147,7 @@ void dc_gamma_retain(const struct dc_gamma *dc_gamma) void dc_gamma_release(const struct dc_gamma **dc_gamma) { - struct gamma *gamma = DC_GAMMA_TO_GAMMA(*dc_gamma); + struct core_gamma *gamma = DC_GAMMA_TO_CORE(*dc_gamma); ASSERT(gamma->ref_count > 0); --gamma->ref_count; @@ -173,14 +160,14 @@ void dc_gamma_release(const struct dc_gamma **dc_gamma) struct dc_gamma *dc_create_gamma() { - struct gamma *gamma = dm_alloc(sizeof(*gamma)); + struct core_gamma *gamma = dm_alloc(sizeof(*gamma)); if (gamma == NULL) goto alloc_fail; ++gamma->ref_count; - return &gamma->protected.public; + return &gamma->public; alloc_fail: return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 1d733c837854..43e9ada278d3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -46,6 +46,9 @@ struct core_stream; struct core_gamma { struct dc_gamma public; struct dc_context *ctx; + + /* private to dc_surface.c */ + int ref_count; }; void enable_surface_flip_reporting(struct dc_surface *dc_surface, -- GitLab From 7a6c4af6bf41516cc9e12d83cc8fcebfdd8be01c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 15:30:17 -0400 Subject: [PATCH 0683/2898] drm/amd/display: Roll core_gamma into dc_gamma Signed-off-by: Harry Wentland Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++--- .../gpu/drm/amd/display/dc/core/dc_surface.c | 22 ++++++++----------- drivers/gpu/drm/amd/display/dc/dc.h | 6 ++--- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 7 ++++++ .../gpu/drm/amd/display/dc/inc/core_types.h | 11 ---------- 5 files changed, 21 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 30374ffaae0b..d3873ac45cf3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1500,12 +1500,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (srf_updates[i].gamma && srf_updates[i].gamma != surface->gamma_correction) { if (surface->gamma_correction != NULL) - dc_gamma_release(&surface-> - gamma_correction); + dc_gamma_release(&surface->gamma_correction); dc_gamma_retain(srf_updates[i].gamma); - surface->gamma_correction = - srf_updates[i].gamma; + surface->gamma_correction = srf_updates[i].gamma; } if (srf_updates[i].in_transfer_func && diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index a8b9515fd367..eded6b7da97d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -137,37 +137,33 @@ void dc_surface_release(struct dc_surface *surface) } } -void dc_gamma_retain(const struct dc_gamma *dc_gamma) +void dc_gamma_retain(struct dc_gamma *gamma) { - struct core_gamma *gamma = DC_GAMMA_TO_CORE(dc_gamma); - ASSERT(gamma->ref_count > 0); ++gamma->ref_count; } -void dc_gamma_release(const struct dc_gamma **dc_gamma) +void dc_gamma_release(struct dc_gamma **gamma) { - struct core_gamma *gamma = DC_GAMMA_TO_CORE(*dc_gamma); - - ASSERT(gamma->ref_count > 0); - --gamma->ref_count; + ASSERT((*gamma)->ref_count > 0); + --(*gamma)->ref_count; - if (gamma->ref_count == 0) - dm_free(gamma); + if ((*gamma)->ref_count == 0) + dm_free((*gamma)); - *dc_gamma = NULL; + *gamma = NULL; } struct dc_gamma *dc_create_gamma() { - struct core_gamma *gamma = dm_alloc(sizeof(*gamma)); + struct dc_gamma *gamma = dm_alloc(sizeof(*gamma)); if (gamma == NULL) goto alloc_fail; ++gamma->ref_count; - return &gamma->public; + return gamma; alloc_fail: return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 77bd54659a8b..5523bb68f4e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -326,7 +326,7 @@ struct dc_surface { struct dc_plane_dcc_param dcc; struct dc_hdr_static_metadata hdr_static_ctx; - const struct dc_gamma *gamma_correction; + struct dc_gamma *gamma_correction; struct dc_transfer_func *in_transfer_func; enum dc_color_space color_space; @@ -394,8 +394,8 @@ const struct dc_surface_status *dc_surface_get_status( void dc_surface_retain(struct dc_surface *dc_surface); void dc_surface_release(struct dc_surface *dc_surface); -void dc_gamma_retain(const struct dc_gamma *dc_gamma); -void dc_gamma_release(const struct dc_gamma **dc_gamma); +void dc_gamma_retain(struct dc_gamma *dc_gamma); +void dc_gamma_release(struct dc_gamma **dc_gamma); struct dc_gamma *dc_create_gamma(void); void dc_transfer_func_retain(struct dc_transfer_func *dc_tf); diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 05f030ee8cf0..4c5e797da5b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -415,6 +415,13 @@ struct dc_gamma { uint16_t red[INPUT_LUT_ENTRIES]; uint16_t green[INPUT_LUT_ENTRIES]; uint16_t blue[INPUT_LUT_ENTRIES]; + + /* private to DC core */ + struct dc_context *ctx; + + /* private to dc_surface.c */ + int ref_count; + }; /* Used by both ipp amd opp functions*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 43e9ada278d3..5a47d4c94df6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -40,17 +40,6 @@ struct core_stream; #define MAX_CLOCK_SOURCES 7 -#define DC_GAMMA_TO_CORE(dc_gamma) \ - container_of(dc_gamma, struct core_gamma, public) - -struct core_gamma { - struct dc_gamma public; - struct dc_context *ctx; - - /* private to dc_surface.c */ - int ref_count; -}; - void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id); -- GitLab From ee356d8f4fff35510b83aa71299ddc0ccb798d58 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 24 Jul 2017 21:41:28 -0400 Subject: [PATCH 0684/2898] drm/amd/display: single PSR display not allow CSTATE sw w/a Description: HW issue when all the pipes are off, DCE_allow_cstate is 0. New sequence : blank OTG only instead of previous OTG_master_en=0) Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/dc_types.h | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index e7062069d9a1..fd2ae181cff2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1548,6 +1548,12 @@ bool dc_link_setup_psr(struct dc_link *link, psr_context->psr_level.u32all = 0; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + /*skip power down the single pipe since it blocks the cstate*/ + if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) + psr_context->psr_level.bits.SKIP_SINGLE_OTG_DISABLE = true; +#endif + /* SMU will perform additional powerdown sequence. * For unsupported ASICs, set psr_level flag to skip PSR * static screen notification to SMU. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index c7539fe36b66..99b893fbcb42 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -539,7 +539,8 @@ union dmcu_psr_level { unsigned int SKIP_SMU_NOTIFICATION:1; unsigned int SKIP_AUTO_STATE_ADVANCE:1; unsigned int DISABLE_PSR_ENTRY_ABORT:1; - unsigned int RESERVED:23; + unsigned int SKIP_SINGLE_OTG_DISABLE:1; + unsigned int RESERVED:22; } bits; unsigned int u32all; }; -- GitLab From a74b27341e46aad3eb48a8c5eadc38b71f79cbce Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 23 Jul 2017 15:22:47 -0400 Subject: [PATCH 0685/2898] drm/amd/display: separate plane disable sequence - disconnect: trigger hw to disconnect plane on next vsync - disable: disables HW block and disable clocks - power_down: kill power Signed-off-by: Tony Cheng Reviewed-by: Eric Yang Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 83 ++++++++++++++----- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c25a39214111..3a0fcaad84c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -815,8 +815,8 @@ static void reset_back_end_for_pipe( pipe_ctx->pipe_idx, pipe_ctx->tg->inst); } -static void plane_atomic_stop( - struct core_dc *dc, +/* trigger HW to start disconnect plane from stream on the next vsync */ +static void plane_atomic_disconnect(struct core_dc *dc, int fe_idx) { struct mpcc_cfg mpcc_cfg; @@ -824,6 +824,12 @@ static void plane_atomic_stop( struct transform *xfm = dc->res_pool->transforms[fe_idx]; struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; + unsigned int opp_id = mpcc->opp_id; + int opp_id_cached = mpcc->opp_id; + + /*Already reset*/ + if (opp_id == 0xf) + return; mi->funcs->dcc_control(mi, false, false); @@ -833,11 +839,19 @@ static void plane_atomic_stop( mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; mpcc->funcs->set(mpcc, &mpcc_cfg); + /* Hack to preserve old opp_id for plane_atomic_disable + * to find the correct otg */ + mpcc->opp_id = opp_id_cached; + + /* todo:call remove pipe from tree */ + /* flag mpcc idle pending */ + xfm->funcs->transform_reset(xfm); } -static void reset_front_end( - struct core_dc *dc, +/* disable HW used by plane. + * note: cannot disable until disconnect is complete */ +static void plane_atomic_disable(struct core_dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; @@ -846,24 +860,9 @@ static void reset_front_end( struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; unsigned int opp_id = mpcc->opp_id; - /*Already reset*/ if (opp_id == 0xf) return; - tg->funcs->lock(tg); - - plane_atomic_stop(dc, fe_idx); - - REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); - tg->funcs->unlock(tg); - - if (dc->public.debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); - - if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) - REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], - VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); - mpcc->funcs->wait_for_idle(mpcc); mi->funcs->set_blank(mi, true); @@ -880,14 +879,54 @@ static void reset_front_end( REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DC, - "Reset front end %d\n", - fe_idx); + mpcc->opp_id = 0xf; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } +/* kill power to plane hw + * note: cannot power down until plane is disable +static void plane_atomic_power_down() +{ + +} +*/ + +static void reset_front_end( + struct core_dc *dc, + int fe_idx) +{ + struct dce_hwseq *hws = dc->hwseq; + struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; + struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; + unsigned int opp_id = mpcc->opp_id; + + /*Already reset*/ + if (opp_id == 0xf) + return; + + tg->funcs->lock(tg); + + plane_atomic_disconnect(dc, fe_idx); + + REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); + tg->funcs->unlock(tg); + + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + + if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], + VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); + + plane_atomic_disable(dc, fe_idx); + + dm_logger_write(dc->ctx->logger, LOG_DC, + "Reset front end %d\n", + fe_idx); +} + static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; -- GitLab From 6be425f3dc16bac797f300136b976bce46229784 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 24 Jul 2017 10:47:02 -0400 Subject: [PATCH 0686/2898] drm/amd/display: break up plane disable and disconnect in set mode Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 23 ++-- .../display/dc/dce110/dce110_hw_sequencer.c | 5 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 102 +++++++++++++++--- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- 4 files changed, 111 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d3873ac45cf3..79218805754e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -932,7 +932,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c for (i = 0; i < core_dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; - core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe); + core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe); } result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); @@ -1364,6 +1364,16 @@ void dc_update_surfaces_and_stream(struct dc *dc, struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct dc_context *dc_ctx = core_dc->ctx; + /* Currently this function do not result in any HW programming + * when called with 0 surface. But proceeding will cause + * SW state to be updated in validate_context. So we might as + * well make it not do anything at all until the hw programming + * is implemented properly to handle 0 surface case. + * TODO: fix hw programming then remove this early return + */ + if (surface_count == 0) + return; + stream_status = dc_stream_get_status(dc_stream); ASSERT(stream_status); if (!stream_status) @@ -1535,15 +1545,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, } if (update_type > UPDATE_TYPE_FAST) { - for (i = 0; i < surface_count; i++) { - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - if (pipe_ctx->surface != srf_updates[i].surface) - continue; + for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - core_dc->hwss.wait_for_mpcc_disconnect(core_dc->res_pool, pipe_ctx); - } + core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe_ctx); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 58701fdb7c94..aa4777a8ec36 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2583,7 +2583,10 @@ static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) dc->res_pool->transforms[fe_idx]); } -static void dce110_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +static void dce110_wait_for_mpcc_disconnect( + struct core_dc *dc, + struct resource_pool *res_pool, + struct pipe_ctx *pipe_ctx) { /* do nothing*/ } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 3a0fcaad84c2..bbe3e8705405 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -831,21 +831,32 @@ static void plane_atomic_disconnect(struct core_dc *dc, if (opp_id == 0xf) return; + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + mi->funcs->dcc_control(mi, false, false); + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + mpcc_cfg.opp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; mpcc->funcs->set(mpcc, &mpcc_cfg); - /* Hack to preserve old opp_id for plane_atomic_disable - * to find the correct otg */ + /* + * Hack to preserve old opp_id for plane_atomic_disable + * to find the correct otg + */ mpcc->opp_id = opp_id_cached; /* todo:call remove pipe from tree */ /* flag mpcc idle pending */ + /*dm_logger_write(dc->ctx->logger, LOG_ERROR, + "[debug_mpo: plane_atomic_disconnect pending on mpcc %d]\n", + fe_idx);*/ xfm->funcs->transform_reset(xfm); } @@ -864,6 +875,10 @@ static void plane_atomic_disable(struct core_dc *dc, return; mpcc->funcs->wait_for_idle(mpcc); + dc->res_pool->opps[opp_id]->mpcc_disconnect_pending[mpcc->inst] = false; + /*dm_logger_write(dc->ctx->logger, LOG_ERROR, + "[debug_mpo: atomic disable finished on mpcc %d]\n", + fe_idx);*/ mi->funcs->set_blank(mi, true); @@ -885,13 +900,27 @@ static void plane_atomic_disable(struct core_dc *dc, verify_allow_pstate_change_high(dc->hwseq); } -/* kill power to plane hw +/* + * kill power to plane hw * note: cannot power down until plane is disable -static void plane_atomic_power_down() + */ +static void plane_atomic_power_down(struct core_dc *dc, int fe_idx) { + struct dce_hwseq *hws = dc->hwseq; + + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, fe_idx, false); + hubp_pg_control(hws, fe_idx, false); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(dc->ctx->logger, LOG_DC, + "Power gated front end %d\n", fe_idx); + if (dc->public.debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); } -*/ + static void reset_front_end( struct core_dc *dc, @@ -953,6 +982,37 @@ static void reset_hw_ctx_wrap( int i; /* Reset Front End*/ + /* Lock*/ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + struct timing_generator *tg = cur_pipe_ctx->tg; + + if (cur_pipe_ctx->stream) + tg->funcs->lock(tg); + } + /* Disconnect*/ + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { + struct pipe_ctx *pipe_ctx_old = + &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (!pipe_ctx->stream || + !pipe_ctx->surface || + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + + plane_atomic_disconnect(dc, i); + } + } + /* Unlock*/ + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + struct timing_generator *tg = cur_pipe_ctx->tg; + + if (cur_pipe_ctx->stream) + tg->funcs->unlock(tg); + } + + /* Disable and Powerdown*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.pipe_ctx[i]; @@ -961,11 +1021,16 @@ static void reset_hw_ctx_wrap( /*if (!pipe_ctx_old->stream) continue;*/ + if (pipe_ctx->stream && pipe_ctx->surface + && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + continue; + + plane_atomic_disable(dc, i); + if (!pipe_ctx->stream || !pipe_ctx->surface) - dcn10_power_down_fe(dc, i); - else if (pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - reset_front_end(dc, i); + plane_atomic_power_down(dc, i); } + /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = @@ -2079,6 +2144,10 @@ static void dcn10_apply_ctx_for_surface( old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); old_pipe_ctx->top_pipe->opp->mpcc_disconnect_pending[old_pipe_ctx->mpcc->inst] = true; + /*dm_logger_write(dc->ctx->logger, LOG_ERROR, + "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", + old_pipe_ctx->mpcc->inst);*/ + if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -2351,18 +2420,27 @@ static void dcn10_log_hw_state(struct core_dc *dc) */ } -static void dcn10_wait_for_mpcc_disconnect(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) +static void dcn10_wait_for_mpcc_disconnect( + struct core_dc *dc, + struct resource_pool *res_pool, + struct pipe_ctx *pipe_ctx) { int i; - for (i = 0; i < MAX_PIPES; i++) { - if (!pipe_ctx->opp || !pipe_ctx->mpcc) - continue; + if (!pipe_ctx->opp || !pipe_ctx->mpcc) + return; + + for (i = 0; i < MAX_PIPES; i++) { if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { pipe_ctx->mpcc->funcs->wait_for_idle(res_pool->mpcc[i]); pipe_ctx->opp->mpcc_disconnect_pending[i] = false; + res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); + /*dm_logger_write(dc->ctx->logger, LOG_ERROR, + "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", + i);*/ } } + } static bool dcn10_dummy_display_power_gating( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 2343beb4ef87..a3eec078dead 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -161,7 +161,9 @@ struct hw_sequencer_funcs { void (*log_hw_state)(struct core_dc *dc); - void (*wait_for_mpcc_disconnect)(struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); + void (*wait_for_mpcc_disconnect)(struct core_dc *dc, + struct resource_pool *res_pool, + struct pipe_ctx *pipe_ctx); }; void color_space_to_black_color( -- GitLab From 9345d9874c324b2f8cce79d4de11f27ae1ef80e9 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 21 Jul 2017 16:34:36 -0400 Subject: [PATCH 0687/2898] drm/amd/display: Move stream validations into seperate function. Stateless streams validations (not require resource population) moved into hook to be called directly from DM. Call dc_validate_stream be before validate_with_context for non Linux APIs Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 24 ++++++++ .../gpu/drm/amd/display/dc/core/dc_resource.c | 61 +++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 2 + .../drm/amd/display/dc/dce/dce_link_encoder.c | 7 +-- .../drm/amd/display/dc/dce/dce_link_encoder.h | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 24 +------- .../amd/display/dc/dce110/dce110_resource.c | 23 +------ .../amd/display/dc/dce112/dce112_resource.c | 25 +------- .../drm/amd/display/dc/dce80/dce80_resource.c | 25 +------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 25 +------- .../drm/amd/display/dc/inc/hw/link_encoder.h | 2 +- .../display/dc/virtual/virtual_link_encoder.c | 2 +- 12 files changed, 90 insertions(+), 132 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 79218805754e..9c2faf8e4b14 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -664,6 +664,20 @@ static bool is_validation_required( return false; } +static bool validate_streams ( + const struct dc *dc, + const struct dc_validation_set set[], + int set_count) +{ + int i; + + for (i = 0; i < set_count; i++) + if (!dc_validate_stream(dc, set[i].stream)) + return false; + + return true; +} + struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], @@ -673,6 +687,7 @@ struct validate_context *dc_get_validate_context( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; @@ -711,6 +726,9 @@ bool dc_validate_resources( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; + if (!validate_streams(dc, set, set_count)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; @@ -742,6 +760,9 @@ bool dc_validate_guaranteed( enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; + if (!dc_validate_stream(dc, stream)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; @@ -1044,6 +1065,9 @@ bool dc_commit_streams( } + if (!validate_streams(dc, set, stream_count)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7cb572ff3cba..4403d8244407 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1416,23 +1416,17 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) return normalized_pix_clk; } -static void calculate_phy_pix_clks(struct validate_context *context) +static void calculate_phy_pix_clks(struct core_stream *stream) { - int i; - - for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; - - update_stream_signal(stream); - - /* update actual pixel clock on all streams */ - if (dc_is_hdmi_signal(stream->signal)) - stream->phy_pix_clk = get_norm_pix_clk( - &stream->public.timing); - else - stream->phy_pix_clk = - stream->public.timing.pix_clk_khz; - } + update_stream_signal(stream); + + /* update actual pixel clock on all streams */ + if (dc_is_hdmi_signal(stream->signal)) + stream->phy_pix_clk = get_norm_pix_clk( + &stream->public.timing); + else + stream->phy_pix_clk = + stream->public.timing.pix_clk_khz; } enum dc_status resource_map_pool_resources( @@ -1443,8 +1437,6 @@ enum dc_status resource_map_pool_resources( const struct resource_pool *pool = dc->res_pool; int i, j; - calculate_phy_pix_clks(context); - for (i = 0; old_context && i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; @@ -2516,3 +2508,36 @@ void resource_build_bit_depth_reduction_params(const struct core_stream *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } + +bool dc_validate_stream(const struct dc *dc, const struct dc_stream *stream) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc_context *dc_ctx = core_dc->ctx; + struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); + struct dc_link *link = core_stream->sink->link; + struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; + enum dc_status res = DC_OK; + + calculate_phy_pix_clks(core_stream); + + if (!tg->funcs->validate_timing(tg, &core_stream->public.timing)) + res = DC_FAIL_CONTROLLER_VALIDATE; + + if (res == DC_OK) + if (!link->link_enc->funcs->validate_output_with_stream( + link->link_enc, core_stream)) + res = DC_FAIL_ENC_VALIDATE; + + /* TODO: validate audio ASIC caps, encoder */ + + if (res == DC_OK) + res = dc_link_validate_mode_timing(core_stream, + link, + &core_stream->public.timing); + + if (res != DC_OK) + DC_ERROR("Failed validation for stream %p, err:%d, !\n", + stream, res); + + return res == DC_OK; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5523bb68f4e8..f250e87d39dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -559,6 +559,8 @@ struct dc_validation_set { uint8_t surface_count; }; +bool dc_validate_stream(const struct dc *dc, const struct dc_stream *stream); + /* * This function takes a set of resources and checks that they are cofunctional. * diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 318673da189b..aff0a440d4d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1009,19 +1009,18 @@ bool dce110_link_encoder_construct( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - struct pipe_ctx *pipe_ctx) + const struct core_stream *stream) { - struct core_stream *stream = pipe_ctx->stream; struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); bool is_valid; - switch (pipe_ctx->stream->signal) { + switch (stream->signal) { case SIGNAL_TYPE_DVI_SINGLE_LINK: case SIGNAL_TYPE_DVI_DUAL_LINK: is_valid = dce110_link_encoder_validate_dvi_output( enc110, stream->sink->link->connector_signal, - pipe_ctx->stream->signal, + stream->signal, &stream->public.timing); break; case SIGNAL_TYPE_HDMI_TYPE_A: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index fd6ba7efc0f9..ded6c61304e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -199,7 +199,7 @@ bool dce110_link_encoder_validate_wireless_output( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - struct pipe_ctx *pipe_ctx); + const struct core_stream *stream); /****************** HW programming ************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 6938158bed7f..3d25a90e49b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -651,7 +651,7 @@ static void destruct(struct dce110_resource_pool *pool) dal_irq_service_destroy(&pool->base.irqs); } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -661,7 +661,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -673,25 +672,8 @@ static enum dc_status validate_mapped_resource( if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; - - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - - /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); - if (status != DC_OK) return status; @@ -769,7 +751,7 @@ enum dc_status dce100_validate_with_context( } if (result == DC_OK) - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -798,7 +780,7 @@ enum dc_status dce100_validate_guaranteed( result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 015306a6ef88..c773351e93af 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -771,7 +771,7 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne return true; } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -781,7 +781,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -797,29 +796,13 @@ static enum dc_status validate_mapped_resource( dc->res_pool->underlay_pipe_index)) return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); if (status != DC_OK) return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - /* TODO: validate audio ASIC caps, encoder */ - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); - - if (status != DC_OK) - return status; - resource_build_info_frame(pipe_ctx); /* do not need to validate non root pipes */ @@ -976,7 +959,7 @@ enum dc_status dce110_validate_with_context( } if (result == DC_OK) - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -1005,7 +988,7 @@ enum dc_status dce110_validate_guaranteed( result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index ca1e13e2a3db..19cd99923b24 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -720,7 +720,7 @@ static struct clock_source *find_matching_pll( return 0; } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -730,7 +730,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -742,26 +741,8 @@ static enum dc_status validate_mapped_resource( if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; - - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - - /* TODO: validate audio ASIC caps, encoder */ - - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); - if (status != DC_OK) return status; @@ -952,7 +933,7 @@ enum dc_status dce112_validate_with_context( } if (result == DC_OK) - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -981,7 +962,7 @@ enum dc_status dce112_validate_guaranteed( result = resource_map_phy_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index b2319dbf3be3..0123006e5360 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -667,7 +667,7 @@ static void destruct(struct dce110_resource_pool *pool) } } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -677,7 +677,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -689,26 +688,8 @@ static enum dc_status validate_mapped_resource( if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; - - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, - pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - - /* TODO: validate audio ASIC caps, encoder */ - - status = dc_link_validate_mode_timing(stream, - link, - &stream->public.timing); - if (status != DC_OK) return status; @@ -786,7 +767,7 @@ enum dc_status dce80_validate_with_context( } if (result == DC_OK) - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) result = resource_build_scaling_params_for_context(dc, context); @@ -814,7 +795,7 @@ enum dc_status dce80_validate_guaranteed( result = resource_map_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 0110a431e289..b901ef9689a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -835,7 +835,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) return DC_OK; } -static enum dc_status validate_mapped_resource( +static enum dc_status build_mapped_resource( const struct core_dc *dc, struct validate_context *context, struct validate_context *old_context) @@ -845,7 +845,6 @@ static enum dc_status validate_mapped_resource( for (i = 0; i < context->stream_count; i++) { struct core_stream *stream = context->streams[i]; - struct dc_link *link = stream->sink->link; if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -870,29 +869,11 @@ static enum dc_status validate_mapped_resource( if (context->res_ctx.pipe_ctx[j].stream != stream) continue; - - if (!pipe_ctx->tg->funcs->validate_timing( - pipe_ctx->tg, &stream->public.timing)) - return DC_FAIL_CONTROLLER_VALIDATE; - status = build_pipe_hw_param(pipe_ctx); if (status != DC_OK) return status; - if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, pipe_ctx)) - return DC_FAIL_ENC_VALIDATE; - - /* TODO: validate audio ASIC caps, encoder */ - - status = dc_link_validate_mode_timing( - stream, link, &stream->public.timing); - - if (status != DC_OK) - return status; - - /* do not need to validate non root pipes */ break; } @@ -928,7 +909,7 @@ enum dc_status dcn10_validate_with_context( if (result != DC_OK) return result; - result = validate_mapped_resource(dc, context, old_context); + result = build_mapped_resource(dc, context, old_context); if (result != DC_OK) return result; @@ -963,7 +944,7 @@ enum dc_status dcn10_validate_guaranteed( result = resource_map_phy_clock_resources(dc, context, NULL); if (result == DC_OK) - result = validate_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, NULL); if (result == DC_OK) { validate_guaranteed_copy_streams( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index d330d38aff16..0ee738774f9f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -94,7 +94,7 @@ struct link_encoder { struct link_encoder_funcs { bool (*validate_output_with_stream)( - struct link_encoder *enc, struct pipe_ctx *pipe_ctx); + struct link_encoder *enc, const struct core_stream *stream); void (*hw_init)(struct link_encoder *enc); void (*setup)(struct link_encoder *enc, enum signal_type signal); diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 12df49927f09..d312874d95b5 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -30,7 +30,7 @@ static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, - struct pipe_ctx *pipe_ctx) { return true; } + const struct core_stream *stream) { return true; } static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} -- GitLab From 4017fcdf5824ea30736e2ecebd02dfa37a249eb5 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 24 Jul 2017 15:35:24 -0400 Subject: [PATCH 0688/2898] drm/amd/display: Use stream validation hook. Use dc_validate_stream from crtc atomic_check for single stream validation. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 86 +++++++++++-------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 13708bcb83cd..0fcd9b373172 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -64,6 +64,24 @@ struct dm_connector_state { #define to_dm_connector_state(x)\ container_of((x), struct dm_connector_state, base) +static bool modeset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; + + if (!crtc_state->enable) + return false; + + return crtc_state->active; +} + +static bool modereset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; + + return !crtc_state->enable || !crtc_state->active; +} void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) { @@ -1268,11 +1286,9 @@ int amdgpu_dm_connector_mode_valid( int result = MODE_ERROR; struct dc_sink *dc_sink; struct amdgpu_device *adev = connector->dev->dev_private; - struct dc_validation_set val_set = { 0 }; /* TODO: Unhardcode stream count */ struct dc_stream *stream; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct validate_context *context; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -1289,35 +1305,28 @@ int amdgpu_dm_connector_mode_valid( if (NULL == dc_sink) { DRM_ERROR("dc_sink is NULL!\n"); - goto null_sink; + goto fail; } stream = dc_create_stream_for_sink(dc_sink); if (NULL == stream) { DRM_ERROR("Failed to create stream for sink!\n"); - goto stream_create_fail; + goto fail; } drm_mode_set_crtcinfo(mode, 0); fill_stream_properties_from_drm_display_mode(stream, mode, connector); - val_set.stream = stream; - val_set.surface_count = 0; stream->src.width = mode->hdisplay; stream->src.height = mode->vdisplay; stream->dst = stream->src; - context = dc_get_validate_context(adev->dm.dc, &val_set, 1); - - if (context) { + if (dc_validate_stream(adev->dm.dc, stream)) result = MODE_OK; - dc_release_validate_context(context); - } dc_stream_release(stream); -stream_create_fail: -null_sink: +fail: /* TODO: error handling*/ return result; } @@ -1343,7 +1352,24 @@ static int dm_crtc_helper_atomic_check( struct drm_crtc *crtc, struct drm_crtc_state *state) { - return 0; + struct amdgpu_device *adev = crtc->dev->dev_private; + struct dc *dc = adev->dm.dc; + struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); + int ret = -EINVAL; + + if (unlikely(!dm_crtc_state->stream && modeset_required(state))) { + WARN_ON(1); + return ret; + } + + /* In some use cases, like reset, no stream is attached */ + if (!dm_crtc_state->stream) + return 0; + + if (dc_validate_stream(dc, dm_crtc_state->stream)) + return 0; + + return ret; } static bool dm_crtc_helper_mode_fixup( @@ -2119,25 +2145,6 @@ int amdgpu_dm_encoder_init( return res; } -static bool modeset_required(struct drm_crtc_state *crtc_state) -{ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - if (!crtc_state->enable) - return false; - - return crtc_state->active; -} - -static bool modereset_required(struct drm_crtc_state *crtc_state) -{ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - return !crtc_state->enable || !crtc_state->active; -} - static void manage_dm_interrupts( struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, @@ -2935,7 +2942,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, */ bool lock_and_validation_needed = false; - ret = drm_atomic_helper_check(dev, state); + ret = drm_atomic_helper_check_modeset(dev, state); if (ret) { DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); @@ -2957,6 +2964,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ /* update changed items */ for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; @@ -3089,10 +3097,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - if (!fb || !plane_crtc || crtc != plane_crtc || - (!crtc_state->planes_changed && - !crtc_state->color_mgmt_changed) || - !crtc_state->active) + if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active) continue; WARN_ON(!new_acrtc_state->stream); @@ -3128,6 +3133,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /* Run this here since we want to validate the streams we created */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + goto fail; + /* * For full updates case when * removing/adding/updating streams on once CRTC while flipping -- GitLab From 48841a20fc794cee0dcbcabee64e068bd6db2df7 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Tue, 25 Jul 2017 14:50:44 -0400 Subject: [PATCH 0689/2898] drm/amd/display: Fix eDP panel light-up Power-down panel on disale only if sink exists otherwise it fails edid read during init sequence Signed-off-by: Roman Li Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index aac2420caefa..5bdcd5067116 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -114,7 +114,9 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); - link->link_enc->funcs->power_control(link->link_enc, false); + if (link->dpcd_sink_count) + link->link_enc->funcs->power_control(link->link_enc, + false); } link->link_enc->funcs->disable_output(link->link_enc, signal); -- GitLab From f4d5abf56b03e55f83d300324e5bf5f32431171c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 25 Jul 2017 16:02:33 -0400 Subject: [PATCH 0690/2898] drm/amd/display: move ocsc programming from opp to dpp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bbe3e8705405..7c24e8f43bb1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1809,7 +1809,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->opp->funcs->opp_set_csc_adjustment(pipe_ctx->opp, &tbl_entry); + pipe_ctx->xfm->funcs->opp_set_csc_adjustment(pipe_ctx->xfm, &tbl_entry); } } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) -- GitLab From 3639fa68122154b453eeaac840daadf3c7c56db4 Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Tue, 25 Jul 2017 15:14:24 -0400 Subject: [PATCH 0691/2898] drm/amd/display: Clean up some DCN1 guards Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 2 ++ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 6 +++--- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 1 + drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 1 + drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 5 +++-- 9 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 84b1f515aa47..9084a32aab79 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -58,6 +58,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; #endif + case DCE_VERSION_12_0: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9c2faf8e4b14..bab07f8d4880 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1109,7 +1109,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version != DCN_VERSION_1_0); + core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version < DCN_VERSION_1_0); #else core_dc->hwss.set_bandwidth(core_dc, context, true); #endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4403d8244407..dea2943392e4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -120,6 +120,8 @@ struct resource_pool *dc_create_resource_pool( num_virtual_links, dc); break; #endif + + default: break; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 142b3a01c204..2205491c83e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -589,6 +589,7 @@ static uint32_t dce110_get_pix_clk_dividers( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: #endif + dce112_get_pix_clk_dividers_helper(clk_src, pll_settings, pix_clk_params); break; @@ -901,6 +902,7 @@ static bool dce110_program_pix_clk( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: #endif + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = pll_settings->use_external_clk; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index f30cd4dff554..37d074f595fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -614,7 +614,7 @@ static bool dce_apply_clock_voltage_request( } if (send_request) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (clk->ctx->dce_version == DCN_VERSION_1_0) { + if (clk->ctx->dce_version >= DCN_VERSION_1_0) { struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); /*use dcfclk request voltage*/ clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index aa4777a8ec36..119365960cd0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1104,11 +1104,11 @@ static enum dc_status apply_single_controller_ctx_to_hw( true : false); resource_build_info_frame(pipe_ctx); - + dce110_update_info_frame(pipe_ctx); if (!pipe_ctx_old->stream) { core_link_enable_stream(pipe_ctx); - dce110_update_info_frame(pipe_ctx); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) dce110_unblank_stream(pipe_ctx, &stream->sink->link->cur_link_settings); @@ -1664,7 +1664,7 @@ enum dc_status dce110_apply_ctx_to_hw( apply_min_clocks(dc, context, &clocks_state, true); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (dc->ctx->dce_version == DCN_VERSION_1_0) { + if (dc->ctx->dce_version >= DCN_VERSION_1_0) { if (context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.cur_clk.fclk_khz) { struct dm_pp_clock_for_voltage_req clock; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 8a8b619a60a8..425f1c4fa891 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -84,6 +84,7 @@ bool dal_hw_factory_init( dal_hw_factory_dcn10_init(factory); return true; #endif + default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 36c082bda4ae..3b55d45b6775 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -80,6 +80,7 @@ bool dal_hw_translate_init( dal_hw_translate_dcn10_init(translate); return true; #endif + default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 45e766ea79e3..10061cc4ba31 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -88,10 +88,11 @@ struct i2caux *dal_i2caux_create( return dal_i2caux_dce100_create(ctx); case DCE_VERSION_12_0: return dal_i2caux_dce120_create(ctx); - #if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: return dal_i2caux_dcn10_create(ctx); - #endif +#endif + default: BREAK_TO_DEBUGGER(); return NULL; -- GitLab From b3d6c3f0f676a06820aa23c9f8590e080d6f6765 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 24 Jul 2017 14:04:27 -0400 Subject: [PATCH 0692/2898] drm/amd/display: Minor fix for dc_sink refactor Signed-off-by: Harry Wentland Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index dea2943392e4..eeefc9c33633 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1321,7 +1321,7 @@ static struct audio *find_first_free_audio( static void update_stream_signal(struct core_stream *stream) { if (stream->public.output_signal == SIGNAL_TYPE_NONE) { - const struct dc_sink *dc_sink = stream->public.sink; + struct dc_sink *dc_sink = stream->public.sink; if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) stream->signal = stream->sink->link->connector_signal; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f250e87d39dd..f87f6c12494c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -469,7 +469,7 @@ enum surface_update_type { * Stream Interfaces ******************************************************************************/ struct dc_stream { - const struct dc_sink *sink; + struct dc_sink *sink; struct dc_crtc_timing timing; struct rect src; /* composition area */ -- GitLab From 8d6a615a16d6fd75c455561914e71b903df73aa4 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 25 Jul 2017 17:11:26 -0400 Subject: [PATCH 0693/2898] drm/amd/display: Disable timestamp and entry heading Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/logger.c | 3 ++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 0b17374b1535..dfd23783cc47 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -428,7 +428,8 @@ void dm_logger_open( logger->open_count++; - log_heading(entry); + if (log_type != LOG_DTN) + log_heading(entry); } void dm_logger_close(struct log_entry *entry) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7c24e8f43bb1..03f404808a1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2407,7 +2407,7 @@ static void dcn10_log_hw_state(struct core_dc *dc) struct dc_context *dc_ctx = dc->ctx; struct dce_hwseq *hws = dc->hwseq; - DTN_INFO("%s: Hello World", __func__); + DTN_INFO("Hello World"); if (REG(MPC_CRC_RESULT_GB)) DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", -- GitLab From d1f69890658909fad1b3881e618a841fc3bd3d96 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Tue, 25 Jul 2017 09:01:13 -0500 Subject: [PATCH 0694/2898] drm/amd/display: Add interfaces for new CM blocks Signed-off-by: Vitaly Prosyak Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 485 +++++++++++++++++- 2 files changed, 485 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index b6aaa95d442b..e52e1f43f67b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -1572,7 +1572,7 @@ static struct transform_funcs dcn10_dpp_funcs = { .opp_program_regamma_lutb_settings = opp_program_regamma_lutb_settings, .opp_program_regamma_luta_settings = opp_program_regamma_luta_settings, .opp_program_regamma_pwl = oppn10_set_regamma_pwl, - .opp_set_regamma_mode = oppn10_set_regamma_mode + .opp_set_regamma_mode = oppn10_set_regamma_mode, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 34085c0818e5..1c9d3320064a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -159,6 +159,7 @@ SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id) + #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ @@ -757,7 +758,373 @@ type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_RGAM_LUT_MODE; \ type OBUF_BYPASS; \ - type OBUF_H_2X_UPSCALE_EN + type OBUF_H_2X_UPSCALE_EN; \ + type CM_BLNDGAM_LUT_MODE; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_BLNDGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ + type CM_BLNDGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type CM_BLNDGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ + type CM_BLNDGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ + type CM_BLNDGAM_LUT_WRITE_EN_MASK; \ + type CM_BLNDGAM_LUT_WRITE_SEL; \ + type CM_BLNDGAM_LUT_INDEX; \ + type CM_BLNDGAM_LUT_DATA; \ + type CM_3DLUT_MODE; \ + type CM_3DLUT_SIZE; \ + type CM_3DLUT_INDEX; \ + type CM_3DLUT_DATA0; \ + type CM_3DLUT_DATA1; \ + type CM_3DLUT_DATA_30BIT; \ + type CM_3DLUT_WRITE_EN_MASK; \ + type CM_3DLUT_RAM_SEL; \ + type CM_3DLUT_30BIT_EN; \ + type CM_3DLUT_CONFIG_STATUS; \ + type CM_3DLUT_READ_SEL; \ + type CM_SHAPER_LUT_MODE; \ + type CM_SHAPER_RAMB_EXP_REGION_START_B; \ + type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_SHAPER_RAMB_EXP_REGION_START_G; \ + type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_SHAPER_RAMB_EXP_REGION_START_R; \ + type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_SHAPER_RAMB_EXP_REGION_END_B; \ + type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_SHAPER_RAMB_EXP_REGION_END_BASE_B; \ + type CM_SHAPER_RAMB_EXP_REGION_END_G; \ + type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_SHAPER_RAMB_EXP_REGION_END_BASE_G; \ + type CM_SHAPER_RAMB_EXP_REGION_END_R; \ + type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_SHAPER_RAMB_EXP_REGION_END_BASE_R; \ + type CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS; \ + type CM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET; \ + type CM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION_START_B; \ + type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_SHAPER_RAMA_EXP_REGION_START_G; \ + type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_SHAPER_RAMA_EXP_REGION_START_R; \ + type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_SHAPER_RAMA_EXP_REGION_END_B; \ + type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_SHAPER_RAMA_EXP_REGION_END_BASE_B; \ + type CM_SHAPER_RAMA_EXP_REGION_END_G; \ + type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_SHAPER_RAMA_EXP_REGION_END_BASE_G; \ + type CM_SHAPER_RAMA_EXP_REGION_END_R; \ + type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_SHAPER_RAMA_EXP_REGION_END_BASE_R; \ + type CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS; \ + type CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET; \ + type CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS; \ + type CM_SHAPER_LUT_WRITE_EN_MASK; \ + type CM_SHAPER_LUT_WRITE_SEL; \ + type CM_SHAPER_LUT_INDEX; \ + type CM_SHAPER_LUT_DATA + struct dcn_dpp_shift { TF_REG_FIELD_LIST(uint8_t); @@ -767,6 +1134,9 @@ struct dcn_dpp_mask { TF_REG_FIELD_LIST(uint32_t); }; + + + struct dcn_dpp_registers { uint32_t DSCL_EXT_OVERSCAN_LEFT_RIGHT; uint32_t DSCL_EXT_OVERSCAN_TOP_BOTTOM; @@ -885,6 +1255,119 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMA_REGION_32_33; uint32_t CM_RGAM_CONTROL; uint32_t OBUF_CONTROL; + uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; + uint32_t CM_BLNDGAM_CONTROL; + uint32_t CM_BLNDGAM_RAMB_START_CNTL_B; + uint32_t CM_BLNDGAM_RAMB_START_CNTL_G; + uint32_t CM_BLNDGAM_RAMB_START_CNTL_R; + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_BLNDGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_B; + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_B; + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_G; + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_G; + uint32_t CM_BLNDGAM_RAMB_END_CNTL1_R; + uint32_t CM_BLNDGAM_RAMB_END_CNTL2_R; + uint32_t CM_BLNDGAM_RAMB_REGION_0_1; + uint32_t CM_BLNDGAM_RAMB_REGION_2_3; + uint32_t CM_BLNDGAM_RAMB_REGION_4_5; + uint32_t CM_BLNDGAM_RAMB_REGION_6_7; + uint32_t CM_BLNDGAM_RAMB_REGION_8_9; + uint32_t CM_BLNDGAM_RAMB_REGION_10_11; + uint32_t CM_BLNDGAM_RAMB_REGION_12_13; + uint32_t CM_BLNDGAM_RAMB_REGION_14_15; + uint32_t CM_BLNDGAM_RAMB_REGION_16_17; + uint32_t CM_BLNDGAM_RAMB_REGION_18_19; + uint32_t CM_BLNDGAM_RAMB_REGION_20_21; + uint32_t CM_BLNDGAM_RAMB_REGION_22_23; + uint32_t CM_BLNDGAM_RAMB_REGION_24_25; + uint32_t CM_BLNDGAM_RAMB_REGION_26_27; + uint32_t CM_BLNDGAM_RAMB_REGION_28_29; + uint32_t CM_BLNDGAM_RAMB_REGION_30_31; + uint32_t CM_BLNDGAM_RAMB_REGION_32_33; + uint32_t CM_BLNDGAM_RAMA_START_CNTL_B; + uint32_t CM_BLNDGAM_RAMA_START_CNTL_G; + uint32_t CM_BLNDGAM_RAMA_START_CNTL_R; + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_BLNDGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_B; + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_B; + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_G; + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_G; + uint32_t CM_BLNDGAM_RAMA_END_CNTL1_R; + uint32_t CM_BLNDGAM_RAMA_END_CNTL2_R; + uint32_t CM_BLNDGAM_RAMA_REGION_0_1; + uint32_t CM_BLNDGAM_RAMA_REGION_2_3; + uint32_t CM_BLNDGAM_RAMA_REGION_4_5; + uint32_t CM_BLNDGAM_RAMA_REGION_6_7; + uint32_t CM_BLNDGAM_RAMA_REGION_8_9; + uint32_t CM_BLNDGAM_RAMA_REGION_10_11; + uint32_t CM_BLNDGAM_RAMA_REGION_12_13; + uint32_t CM_BLNDGAM_RAMA_REGION_14_15; + uint32_t CM_BLNDGAM_RAMA_REGION_16_17; + uint32_t CM_BLNDGAM_RAMA_REGION_18_19; + uint32_t CM_BLNDGAM_RAMA_REGION_20_21; + uint32_t CM_BLNDGAM_RAMA_REGION_22_23; + uint32_t CM_BLNDGAM_RAMA_REGION_24_25; + uint32_t CM_BLNDGAM_RAMA_REGION_26_27; + uint32_t CM_BLNDGAM_RAMA_REGION_28_29; + uint32_t CM_BLNDGAM_RAMA_REGION_30_31; + uint32_t CM_BLNDGAM_RAMA_REGION_32_33; + uint32_t CM_BLNDGAM_LUT_INDEX; + uint32_t CM_BLNDGAM_LUT_DATA; + uint32_t CM_3DLUT_MODE; + uint32_t CM_3DLUT_INDEX; + uint32_t CM_3DLUT_DATA; + uint32_t CM_3DLUT_DATA_30BIT; + uint32_t CM_3DLUT_READ_WRITE_CONTROL; + uint32_t CM_SHAPER_LUT_WRITE_EN_MASK; + uint32_t CM_SHAPER_CONTROL; + uint32_t CM_SHAPER_RAMB_START_CNTL_B; + uint32_t CM_SHAPER_RAMB_START_CNTL_G; + uint32_t CM_SHAPER_RAMB_START_CNTL_R; + uint32_t CM_SHAPER_RAMB_REGION_0_1; + uint32_t CM_SHAPER_RAMB_REGION_2_3; + uint32_t CM_SHAPER_RAMB_REGION_4_5; + uint32_t CM_SHAPER_RAMB_REGION_6_7; + uint32_t CM_SHAPER_RAMB_REGION_8_9; + uint32_t CM_SHAPER_RAMB_REGION_10_11; + uint32_t CM_SHAPER_RAMB_REGION_12_13; + uint32_t CM_SHAPER_RAMB_REGION_14_15; + uint32_t CM_SHAPER_RAMB_REGION_16_17; + uint32_t CM_SHAPER_RAMB_REGION_18_19; + uint32_t CM_SHAPER_RAMB_REGION_20_21; + uint32_t CM_SHAPER_RAMB_REGION_22_23; + uint32_t CM_SHAPER_RAMB_REGION_24_25; + uint32_t CM_SHAPER_RAMB_REGION_26_27; + uint32_t CM_SHAPER_RAMB_REGION_28_29; + uint32_t CM_SHAPER_RAMB_REGION_30_31; + uint32_t CM_SHAPER_RAMB_REGION_32_33; + uint32_t CM_SHAPER_RAMA_START_CNTL_B; + uint32_t CM_SHAPER_RAMA_START_CNTL_G; + uint32_t CM_SHAPER_RAMA_START_CNTL_R; + uint32_t CM_SHAPER_RAMA_REGION_0_1; + uint32_t CM_SHAPER_RAMA_REGION_2_3; + uint32_t CM_SHAPER_RAMA_REGION_4_5; + uint32_t CM_SHAPER_RAMA_REGION_6_7; + uint32_t CM_SHAPER_RAMA_REGION_8_9; + uint32_t CM_SHAPER_RAMA_REGION_10_11; + uint32_t CM_SHAPER_RAMA_REGION_12_13; + uint32_t CM_SHAPER_RAMA_REGION_14_15; + uint32_t CM_SHAPER_RAMA_REGION_16_17; + uint32_t CM_SHAPER_RAMA_REGION_18_19; + uint32_t CM_SHAPER_RAMA_REGION_20_21; + uint32_t CM_SHAPER_RAMA_REGION_22_23; + uint32_t CM_SHAPER_RAMA_REGION_24_25; + uint32_t CM_SHAPER_RAMA_REGION_26_27; + uint32_t CM_SHAPER_RAMA_REGION_28_29; + uint32_t CM_SHAPER_RAMA_REGION_30_31; + uint32_t CM_SHAPER_RAMA_REGION_32_33; + uint32_t CM_SHAPER_LUT_INDEX; + uint32_t CM_SHAPER_LUT_DATA; + + }; struct dcn10_dpp { -- GitLab From 2248eb6b4f1fdd7aded987d178a95b021d3a1d91 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 25 Jul 2017 22:52:45 -0400 Subject: [PATCH 0695/2898] drm/amd/display: log HUBP using DTN logging also simplify DTN INFO. all we need is a way to have DC log register states some where we can compare with golden. going through connectivity is overkill. Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 9 ++++ .../drm/amd/display/dc/basics/log_helpers.c | 28 ---------- .../gpu/drm/amd/display/dc/basics/logger.c | 3 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 53 ++++++++++++++++--- .../amd/display/dc/dcn10/dcn10_mem_input.c | 34 ++++++++++++ .../amd/display/dc/dcn10/dcn10_mem_input.h | 18 +++++++ drivers/gpu/drm/amd/display/dc/dm_helpers.h | 6 --- drivers/gpu/drm/amd/display/dc/dm_services.h | 12 +++++ .../amd/display/include/logger_interface.h | 24 +++++---- 9 files changed, 133 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index df4d221e46c1..6c19a07709df 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -327,6 +327,15 @@ bool dm_helpers_dc_conn_log(struct dc_context *ctx, struct log_entry *entry, enu return true; } +void dm_dtn_log_begin(struct dc_context *ctx) +{} + +void dm_dtn_log_append_v(struct dc_context *ctx, + const char *pMsg, ...) +{} + +void dm_dtn_log_end(struct dc_context *ctx) +{} bool dm_helpers_dp_mst_start_top_mgr( struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c index 070ae6f680e1..785b943b60ed 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/basics/log_helpers.c @@ -100,31 +100,3 @@ void dc_conn_log(struct dc_context *ctx, va_end(args); } - -void dc_raw_log(struct dc_context *ctx, - enum dc_log_type event, - const char *msg, - ...) -{ - va_list args; - struct log_entry entry = { 0 }; - - dm_logger_open(ctx->logger, &entry, event); - - va_start(args, msg); - entry.buf_offset += dm_log_to_buffer( - &entry.buf[entry.buf_offset], - LOG_MAX_LINE_SIZE - entry.buf_offset, - msg, args); - - if (entry.buf[strlen(entry.buf) - 1] == '\n') { - entry.buf[strlen(entry.buf) - 1] = '\0'; - entry.buf_offset--; - } - - dm_logger_append(&entry, "^\n"); - dm_helpers_dc_conn_log(ctx, &entry, event); - dm_logger_close(&entry); - - va_end(args); -} diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index dfd23783cc47..0b17374b1535 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -428,8 +428,7 @@ void dm_logger_open( logger->open_count++; - if (log_type != LOG_DTN) - log_heading(entry); + log_heading(entry); } void dm_logger_close(struct log_entry *entry) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 03f404808a1c..e738387d8ba3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -31,9 +31,9 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" +#include "dcn10/dcn10_mem_input.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" -#include "mem_input.h" #include "timing_generator.h" #include "opp.h" #include "ipp.h" @@ -2402,22 +2402,61 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) return; } -static void dcn10_log_hw_state(struct core_dc *dc) + +static void log_mpc_crc(struct core_dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct dce_hwseq *hws = dc->hwseq; - DTN_INFO("Hello World"); - if (REG(MPC_CRC_RESULT_GB)) DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); - /* todo: add meaningful register reads and print out HW state - * - */ +} + +static void dcn10_log_hw_state(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct resource_pool *pool = dc->res_pool; + int i; + + DTN_INFO_BEGIN(); + + DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t rotation \t" + "mirror \t sw_mode \t dcc_en \t blank_en \t ttu_dis \t" + "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); + + for (i = 0; i < pool->pipe_count; i++) { + struct mem_input *mi = pool->mis[i]; + struct dcn_hubp_state s; + + dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); + + DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t %xh \t %xh \t " + "%d \t %d \t %d \t %d \t" + "%d \t %d \t %d \n", + i, + s.pixel_format, + s.inuse_addr_hi, + s.viewport_width, + s.viewport_height, + s.rotation_angle, + s.h_mirror_en, + s.sw_mode, + s.dcc_en, + s.blank_en, + s.ttu_disable, + s.min_ttu_vblank, + s.qos_level_low_wm, + s.qos_level_high_wm); + } + DTN_INFO("\n"); + + log_mpc_crc(dc); + + DTN_INFO_END(); } static void dcn10_wait_for_mpcc_disconnect( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index c56a69b5a4d7..6f01db6a51dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -804,6 +804,40 @@ static void min_set_viewport( PRI_VIEWPORT_Y_START_C, viewport_c->y); } +void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, + struct dcn_hubp_state *s) +{ + REG_GET(DCSURF_SURFACE_CONFIG, + SURFACE_PIXEL_FORMAT, &s->pixel_format); + + REG_GET(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, + SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, &s->inuse_addr_hi); + + REG_GET_2(DCSURF_PRI_VIEWPORT_DIMENSION, + PRI_VIEWPORT_WIDTH, &s->viewport_width, + PRI_VIEWPORT_HEIGHT, &s->viewport_height); + + REG_GET_2(DCSURF_SURFACE_CONFIG, + ROTATION_ANGLE, &s->rotation_angle, + H_MIRROR_EN, &s->h_mirror_en); + + REG_GET(DCSURF_TILING_CONFIG, + SW_MODE, &s->sw_mode); + + REG_GET(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_DCC_EN, &s->dcc_en); + + REG_GET_2(DCHUBP_CNTL, + HUBP_BLANK_EN, &s->blank_en, + HUBP_TTU_DISABLE, &s->ttu_disable); + + REG_GET(DCN_GLOBAL_TTU_CNTL, + MIN_TTU_VBLANK, &s->min_ttu_vblank); + + REG_GET_2(DCN_TTU_QOS_WM, + QoS_LEVEL_LOW_WM, &s->qos_level_low_wm, + QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); +} static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_display_marks = min10_program_display_marks, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 9130f5e0ab03..4f4e2c0708d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -579,4 +579,22 @@ bool dcn10_mem_input_construct( const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask); +struct dcn_hubp_state { + uint32_t pixel_format; + uint32_t inuse_addr_hi; + uint32_t viewport_width; + uint32_t viewport_height; + uint32_t rotation_angle; + uint32_t h_mirror_en; + uint32_t sw_mode; + uint32_t dcc_en; + uint32_t blank_en; + uint32_t ttu_disable; + uint32_t min_ttu_vblank; + uint32_t qos_level_low_wm; + uint32_t qos_level_high_wm; +}; +void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, + struct dcn_hubp_state *s); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index a831421c7ea0..e8bd501feb48 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -68,15 +68,9 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot); -bool dm_helpers_dc_conn_log( - struct dc_context*ctx, - struct log_entry *entry, - enum dc_log_type event); - void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, const struct dc_link *link); - /** * OS specific aux read callback. */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index ea494a71a80b..e9bf4c417cc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -463,4 +463,16 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); #define dm_log_to_buffer(buffer, size, fmt, args)\ vsnprintf(buffer, size, fmt, args) +/* + * Debug and verification hooks + */ +bool dm_helpers_dc_conn_log( + struct dc_context *ctx, + struct log_entry *entry, + enum dc_log_type event); + +void dm_dtn_log_begin(struct dc_context *ctx); +void dm_dtn_log_append_v(struct dc_context *ctx, const char *msg, ...); +void dm_dtn_log_end(struct dc_context *ctx); + #endif /* __DM_SERVICES_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 3adf3cfc7aba..0a872472ecba 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -70,11 +70,6 @@ void dc_conn_log(struct dc_context *ctx, const char *msg, ...); -void dc_raw_log(struct dc_context *ctx, - enum dc_log_type event, - const char *msg, - ...); - void logger_write(struct dal_logger *logger, enum dc_log_type log_type, const char *msg, @@ -121,16 +116,11 @@ void context_clock_trace( #define DC_ERROR(...) \ dm_logger_write(dc_ctx->logger, LOG_ERROR, \ - __VA_ARGS__); - -#define DTN_INFO(...) \ - dc_raw_log(dc_ctx, LOG_DTN, \ __VA_ARGS__) #define DC_SYNC_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_SYNC, \ - __VA_ARGS__); - + __VA_ARGS__) /* Connectivity log format: * [time stamp] [drm] [Major_minor] [connector name] message..... @@ -155,4 +145,16 @@ void context_clock_trace( dc_conn_log(link->ctx, link, NULL, 0, \ LOG_EVENT_MODE_SET, ##__VA_ARGS__) +/* + * Display Test Next logging + */ +#define DTN_INFO_BEGIN() \ + dm_dtn_log_begin(dc_ctx) + +#define DTN_INFO(msg, ...) \ + dm_dtn_log_append_v(dc_ctx, msg, ##__VA_ARGS__) + +#define DTN_INFO_END() \ + dm_dtn_log_end(dc_ctx) + #endif /* __DAL_LOGGER_INTERFACE_H__ */ -- GitLab From 4fa086b9b6640818c053c79d4d7104790ba76cb7 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 25 Jul 2017 20:51:26 -0400 Subject: [PATCH 0696/2898] drm/amd/display: Roll core_stream into dc_stream Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 10 +- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 2 +- .../gpu/drm/amd/display/dc/calcs/dce_calcs.c | 16 +- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 92 +++---- drivers/gpu/drm/amd/display/dc/core/dc.c | 107 ++++---- .../gpu/drm/amd/display/dc/core/dc_debug.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 41 ++- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 7 +- .../drm/amd/display/dc/core/dc_link_hwss.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 259 +++++++++--------- .../gpu/drm/amd/display/dc/core/dc_stream.c | 118 ++++---- drivers/gpu/drm/amd/display/dc/dc.h | 71 +++-- .../drm/amd/display/dc/dce/dce_link_encoder.c | 10 +- .../drm/amd/display/dc/dce/dce_link_encoder.h | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 12 +- .../display/dc/dce110/dce110_hw_sequencer.c | 176 ++++++------ .../amd/display/dc/dce110/dce110_resource.c | 46 ++-- .../amd/display/dc/dce112/dce112_resource.c | 16 +- .../amd/display/dc/dce112/dce112_resource.h | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 12 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 72 ++--- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 36 +-- .../gpu/drm/amd/display/dc/inc/core_types.h | 33 +-- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 4 +- .../drm/amd/display/dc/inc/hw/link_encoder.h | 3 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 14 +- .../display/dc/virtual/virtual_link_encoder.c | 2 +- .../amd/display/modules/freesync/freesync.c | 60 ++-- .../amd/display/modules/inc/mod_freesync.h | 28 +- 31 files changed, 612 insertions(+), 649 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 696a4112c8d9..c802437f4858 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1401,7 +1401,7 @@ static int amdgpu_notify_freesync(struct drm_device *dev, void *data, num_streams = dc_get_current_stream_count(adev->dm.dc); for (i = 0; i < num_streams; i++) { - const struct dc_stream *stream; + struct dc_stream *stream; stream = dc_get_stream_at_index(adev->dm.dc, i); mod_freesync_update_state(adev->dm.freesync_module, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 0fcd9b373172..80d4e2670cc2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -2196,7 +2196,7 @@ static bool is_scaling_state_different( static void remove_stream( struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, - const struct dc_stream *stream) + struct dc_stream *stream) { /* this is the update mode case */ if (adev->dm.freesync_module) @@ -2351,7 +2351,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, uint32_t i; struct drm_plane *plane; struct drm_plane_state *old_plane_state; - const struct dc_stream *dc_stream_attach; + struct dc_stream *dc_stream_attach; struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); @@ -2487,7 +2487,7 @@ void amdgpu_dm_atomic_commit_tail( struct drm_crtc *crtc, *pcrtc; struct drm_crtc_state *old_crtc_state; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; - const struct dc_stream *new_stream; + struct dc_stream *new_stream = NULL; unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; @@ -2822,8 +2822,8 @@ static uint32_t add_val_sets_surface( static uint32_t update_in_val_sets_stream( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_stream *old_stream, - const struct dc_stream *new_stream, + struct dc_stream *old_stream, + struct dc_stream *new_stream, struct drm_crtc *crtc) { uint32_t i = 0; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h index c565787cd782..94de6a3736fc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h @@ -45,7 +45,7 @@ struct dm_plane_state { struct dm_crtc_state { struct drm_crtc_state base; - const struct dc_stream *stream; + struct dc_stream *stream; }; #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 5ef44ff4bcf8..9a850227eeeb 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2610,9 +2610,9 @@ static void populate_initial_data( data->fbc_en[num_displays + 4] = false; data->lpt_en[num_displays + 4] = false; - data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); - data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); - data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); @@ -2707,9 +2707,9 @@ static void populate_initial_data( data->fbc_en[num_displays + 4] = false; data->lpt_en[num_displays + 4] = false; - data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_total); - data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_total); - data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->public.timing.pix_clk_khz, 1000); + data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); + data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); + data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); if (pipe[i].surface) { data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; @@ -2759,9 +2759,9 @@ static void populate_initial_data( break; } } else { - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.h_addressable); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_addressable); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->public.timing.v_addressable); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_addressable); data->h_taps[num_displays + 4] = bw_int_to_fixed(1); data->v_taps[num_displays + 4] = bw_int_to_fixed(1); data->h_scale_ratio[num_displays + 4] = bw_int_to_fixed(1); diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1651b7548d40..ef10a8b49379 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -365,7 +365,7 @@ static void pipe_ctx_to_e2e_pipe_params ( } - input->dest.vactive = pipe->stream->public.timing.v_addressable; + input->dest.vactive = pipe->stream->timing.v_addressable; input->dest.recout_width = pipe->scl_data.recout.width; input->dest.recout_height = pipe->scl_data.recout.height; @@ -373,24 +373,24 @@ static void pipe_ctx_to_e2e_pipe_params ( input->dest.full_recout_width = pipe->scl_data.recout.width; input->dest.full_recout_height = pipe->scl_data.recout.height; - input->dest.htotal = pipe->stream->public.timing.h_total; - input->dest.hblank_start = input->dest.htotal - pipe->stream->public.timing.h_front_porch; + input->dest.htotal = pipe->stream->timing.h_total; + input->dest.hblank_start = input->dest.htotal - pipe->stream->timing.h_front_porch; input->dest.hblank_end = input->dest.hblank_start - - pipe->stream->public.timing.h_addressable - - pipe->stream->public.timing.h_border_left - - pipe->stream->public.timing.h_border_right; + - pipe->stream->timing.h_addressable + - pipe->stream->timing.h_border_left + - pipe->stream->timing.h_border_right; - input->dest.vtotal = pipe->stream->public.timing.v_total; - input->dest.vblank_start = input->dest.vtotal - pipe->stream->public.timing.v_front_porch; + input->dest.vtotal = pipe->stream->timing.v_total; + input->dest.vblank_start = input->dest.vtotal - pipe->stream->timing.v_front_porch; input->dest.vblank_end = input->dest.vblank_start - - pipe->stream->public.timing.v_addressable - - pipe->stream->public.timing.v_border_bottom - - pipe->stream->public.timing.v_border_top; - - input->dest.vsync_plus_back_porch = pipe->stream->public.timing.v_total - - pipe->stream->public.timing.v_addressable - - pipe->stream->public.timing.v_front_porch; - input->dest.pixel_rate_mhz = pipe->stream->public.timing.pix_clk_khz/1000.0; + - pipe->stream->timing.v_addressable + - pipe->stream->timing.v_border_bottom + - pipe->stream->timing.v_border_top; + + input->dest.vsync_plus_back_porch = pipe->stream->timing.v_total + - pipe->stream->timing.v_addressable + - pipe->stream->timing.v_front_porch; + input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0; input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; @@ -851,14 +851,14 @@ bool dcn_validate_bandwidth( v->underscan_output[input_idx] = false; /* taken care of in recout already*/ v->interlace_output[input_idx] = false; - v->htotal[input_idx] = pipe->stream->public.timing.h_total; - v->vtotal[input_idx] = pipe->stream->public.timing.v_total; - v->v_sync_plus_back_porch[input_idx] = pipe->stream->public.timing.v_total - - pipe->stream->public.timing.v_addressable - - pipe->stream->public.timing.v_front_porch; - v->vactive[input_idx] = pipe->stream->public.timing.v_addressable; - v->pixel_clock[input_idx] = pipe->stream->public.timing.pix_clk_khz / 1000.0f; - if (pipe->stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + v->htotal[input_idx] = pipe->stream->timing.h_total; + v->vtotal[input_idx] = pipe->stream->timing.v_total; + v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total + - pipe->stream->timing.v_addressable + - pipe->stream->timing.v_front_porch; + v->vactive[input_idx] = pipe->stream->timing.v_addressable; + v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; + if (pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) v->pixel_clock[input_idx] /= 2; @@ -867,10 +867,10 @@ bool dcn_validate_bandwidth( v->source_pixel_format[input_idx] = dcn_bw_rgb_sub_32; v->source_surface_mode[input_idx] = dcn_bw_sw_4_kb_s; v->lb_bit_per_pixel[input_idx] = 30; - v->viewport_width[input_idx] = pipe->stream->public.timing.h_addressable; - v->viewport_height[input_idx] = pipe->stream->public.timing.v_addressable; - v->scaler_rec_out_width[input_idx] = pipe->stream->public.timing.h_addressable; - v->scaler_recout_height[input_idx] = pipe->stream->public.timing.v_addressable; + v->viewport_width[input_idx] = pipe->stream->timing.h_addressable; + v->viewport_height[input_idx] = pipe->stream->timing.v_addressable; + v->scaler_rec_out_width[input_idx] = pipe->stream->timing.h_addressable; + v->scaler_recout_height[input_idx] = pipe->stream->timing.v_addressable; v->override_hta_ps[input_idx] = 1; v->override_vta_ps[input_idx] = 1; v->override_hta_pschroma[input_idx] = 1; @@ -995,22 +995,22 @@ bool dcn_validate_bandwidth( pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; - pipe->pipe_dlg_param.htotal = pipe->stream->public.timing.h_total; - pipe->pipe_dlg_param.vtotal = pipe->stream->public.timing.v_total; - vesa_sync_start = pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_border_bottom + - pipe->stream->public.timing.v_front_porch; + pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total; + pipe->pipe_dlg_param.vtotal = pipe->stream->timing.v_total; + vesa_sync_start = pipe->stream->timing.v_addressable + + pipe->stream->timing.v_border_bottom + + pipe->stream->timing.v_front_porch; - asic_blank_end = (pipe->stream->public.timing.v_total - + asic_blank_end = (pipe->stream->timing.v_total - vesa_sync_start - - pipe->stream->public.timing.v_border_top) - * (pipe->stream->public.timing.flags.INTERLACE ? 1 : 0); + pipe->stream->timing.v_border_top) + * (pipe->stream->timing.flags.INTERLACE ? 1 : 0); asic_blank_start = asic_blank_end + - (pipe->stream->public.timing.v_border_top + - pipe->stream->public.timing.v_addressable + - pipe->stream->public.timing.v_border_bottom) - * (pipe->stream->public.timing.flags.INTERLACE ? 1 : 0); + (pipe->stream->timing.v_border_top + + pipe->stream->timing.v_addressable + + pipe->stream->timing.v_border_bottom) + * (pipe->stream->timing.flags.INTERLACE ? 1 : 0); pipe->pipe_dlg_param.vblank_start = asic_blank_start; pipe->pipe_dlg_param.vblank_end = asic_blank_end; @@ -1019,13 +1019,13 @@ bool dcn_validate_bandwidth( struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; if (v->dpp_per_plane[input_idx] == 2 || - ((pipe->stream->public.view_format == + ((pipe->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || - pipe->stream->public.view_format == + pipe->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) && - (pipe->stream->public.timing.timing_3d_format == + (pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM || - pipe->stream->public.timing.timing_3d_format == + pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE))) { if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { /* update previously split pipe */ @@ -1034,8 +1034,8 @@ bool dcn_validate_bandwidth( hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset[input_idx]; hsplit_pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx]; - hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->public.timing.h_total; - hsplit_pipe->pipe_dlg_param.vtotal = pipe->stream->public.timing.v_total; + hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total; + hsplit_pipe->pipe_dlg_param.vtotal = pipe->stream->timing.v_total; hsplit_pipe->pipe_dlg_param.vblank_start = pipe->pipe_dlg_param.vblank_start; hsplit_pipe->pipe_dlg_param.vblank_end = pipe->pipe_dlg_param.vblank_end; } else { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index bab07f8d4880..df8c5ca6b22a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -149,19 +149,19 @@ static bool create_links( } static bool stream_adjust_vmin_vmax(struct dc *dc, - const struct dc_stream **stream, int num_streams, + struct dc_stream **streams, int num_streams, int vmin, int vmax) { /* TODO: Support multiple streams */ struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + struct dc_stream *stream = streams[0]; int i = 0; bool ret = false; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe->stream == core_stream && pipe->stream_enc) { + if (pipe->stream == stream && pipe->stream_enc) { core_dc->hwss.set_drr(&pipe, 1, vmin, vmax); /* build and update the info frame */ @@ -175,12 +175,12 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, } static bool stream_get_crtc_position(struct dc *dc, - const struct dc_stream **stream, int num_streams, + struct dc_stream **streams, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]); + struct dc_stream *stream = streams[0]; int i = 0; bool ret = false; struct crtc_position position; @@ -189,7 +189,7 @@ static bool stream_get_crtc_position(struct dc *dc, struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe->stream == core_stream && pipe->stream_enc) { + if (pipe->stream == stream && pipe->stream_enc) { core_dc->hwss.get_position(&pipe, 1, &position); *v_pos = position.vertical_count; @@ -203,15 +203,12 @@ static bool stream_get_crtc_position(struct dc *dc, static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i = 0; bool ret = false; struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) { - + if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; core_dc->hwss.program_gamut_remap(pipes); ret = true; @@ -221,22 +218,21 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) return ret; } -static bool program_csc_matrix(struct dc *dc, const struct dc_stream *stream) +static bool program_csc_matrix(struct dc *dc, struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i = 0; bool ret = false; struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) { + == stream) { pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; core_dc->hwss.program_csc_matrix(pipes, - core_stream->public.output_color_space, - core_stream->public.csc_color_matrix.matrix); + stream->output_color_space, + stream->csc_color_matrix.matrix); ret = true; } } @@ -245,7 +241,7 @@ static bool program_csc_matrix(struct dc *dc, const struct dc_stream *stream) } static void set_static_screen_events(struct dc *dc, - const struct dc_stream **stream, + struct dc_stream **streams, int num_streams, const struct dc_static_screen_events *events) { @@ -256,11 +252,11 @@ static void set_static_screen_events(struct dc *dc, int num_pipes_affected = 0; for (i = 0; i < num_streams; i++) { - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[i]); + struct dc_stream *stream = streams[i]; for (j = 0; j < MAX_PIPES; j++) { if (core_dc->current_context->res_ctx.pipe_ctx[j].stream - == core_stream) { + == stream) { pipes_affected[num_pipes_affected++] = &core_dc->current_context->res_ctx.pipe_ctx[j]; } @@ -337,10 +333,9 @@ static void set_test_pattern( cust_pattern_size); } -void set_dither_option(const struct dc_stream *dc_stream, +void set_dither_option(struct dc_stream *stream, enum dc_dither_option option) { - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; @@ -351,21 +346,21 @@ void set_dither_option(const struct dc_stream *dc_stream, if (option > DITHER_OPTION_MAX) return; if (option == DITHER_OPTION_DEFAULT) { - switch (stream->public.timing.display_color_depth) { + switch (stream->timing.display_color_depth) { case COLOR_DEPTH_666: - stream->public.dither_option = DITHER_OPTION_SPATIAL6; + stream->dither_option = DITHER_OPTION_SPATIAL6; break; case COLOR_DEPTH_888: - stream->public.dither_option = DITHER_OPTION_SPATIAL8; + stream->dither_option = DITHER_OPTION_SPATIAL8; break; case COLOR_DEPTH_101010: - stream->public.dither_option = DITHER_OPTION_SPATIAL10; + stream->dither_option = DITHER_OPTION_SPATIAL10; break; default: option = DITHER_OPTION_DISABLE; } } else { - stream->public.dither_option = option; + stream->dither_option = option; } resource_build_bit_depth_reduction_params(stream, ¶ms); @@ -644,7 +639,7 @@ static bool is_validation_required( if (set[i].surface_count != context->stream_status[i].surface_count) return true; - if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i])) + if (!is_stream_unchanged(set[i].stream, context->streams[i])) return true; for (j = 0; j < set[i].surface_count; j++) { @@ -754,7 +749,7 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - const struct dc_stream *stream) + struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); enum dc_status result = DC_ERROR_UNEXPECTED; @@ -869,7 +864,7 @@ static bool context_changed( return true; for (i = 0; i < dc->current_context->stream_count; i++) { - if (&dc->current_context->streams[i]->public != &context->streams[i]->public) + if (dc->current_context->streams[i] != context->streams[i]) return true; } @@ -878,7 +873,7 @@ static bool context_changed( static bool streams_changed( struct core_dc *dc, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count) { uint8_t i; @@ -887,7 +882,7 @@ static bool streams_changed( return true; for (i = 0; i < dc->current_context->stream_count; i++) { - if (&dc->current_context->streams[i]->public != streams[i]) + if (dc->current_context->streams[i] != streams[i]) return true; } @@ -897,7 +892,7 @@ static bool streams_changed( bool dc_enable_stereo( struct dc *dc, struct validate_context *context, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count) { bool ret = true; @@ -915,7 +910,7 @@ bool dc_enable_stereo( else pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; for (j = 0 ; pipe && j < stream_count; j++) { - if (streams[j] && streams[j] == &pipe->stream->public && + if (streams[j] && streams[j] == pipe->stream && core_dc->hwss.setup_stereo) core_dc->hwss.setup_stereo(pipe, core_dc); } @@ -943,10 +938,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; int i, j, k, l; - const struct dc_stream *dc_streams[MAX_STREAMS] = {0}; + struct dc_stream *dc_streams[MAX_STREAMS] = {0}; for (i = 0; i < context->stream_count; i++) - dc_streams[i] = &context->streams[i]->public; + dc_streams[i] = context->streams[i]; if (!dcb->funcs->is_accelerated_mode(dcb)) core_dc->hwss.enable_accelerated_mode(core_dc); @@ -985,11 +980,11 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", - context->streams[i]->public.timing.h_addressable, - context->streams[i]->public.timing.v_addressable, - context->streams[i]->public.timing.h_total, - context->streams[i]->public.timing.v_total, - context->streams[i]->public.timing.pix_clk_khz); + context->streams[i]->timing.h_addressable, + context->streams[i]->timing.v_addressable, + context->streams[i]->timing.h_total, + context->streams[i]->timing.v_total, + context->streams[i]->timing.pix_clk_khz); } dc_enable_stereo(dc, context, dc_streams, context->stream_count); @@ -1016,7 +1011,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) __func__, context->stream_count); for (i = 0; i < context->stream_count; i++) { - const struct dc_stream *stream = &context->streams[i]->public; + struct dc_stream *stream = context->streams[i]; dc_stream_log(stream, core_dc->ctx->logger, @@ -1031,7 +1026,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) bool dc_commit_streams( struct dc *dc, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1047,8 +1042,8 @@ bool dc_commit_streams( __func__, stream_count); for (i = 0; i < stream_count; i++) { - const struct dc_stream *stream = streams[i]; - const struct dc_stream_status *status = dc_stream_get_status(stream); + struct dc_stream *stream = streams[i]; + struct dc_stream_status *status = dc_stream_get_status(stream); int j; dc_stream_log(stream, @@ -1120,7 +1115,7 @@ bool dc_commit_surfaces_to_stream( struct dc *dc, struct dc_surface **new_surfaces, uint8_t new_surface_count, - const struct dc_stream *dc_stream) + struct dc_stream *dc_stream) { struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs flip_addr[MAX_SURFACES]; @@ -1377,7 +1372,7 @@ enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_surfaces_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, - const struct dc_stream *dc_stream, + struct dc_stream *stream, struct dc_stream_update *stream_update) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1385,7 +1380,6 @@ void dc_update_surfaces_and_stream(struct dc *dc, int i, j; enum surface_update_type update_type; const struct dc_stream_status *stream_status; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct dc_context *dc_ctx = core_dc->ctx; /* Currently this function do not result in any HW programming @@ -1398,7 +1392,8 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (surface_count == 0) return; - stream_status = dc_stream_get_status(dc_stream); + stream_status = dc_stream_get_status(stream); + ASSERT(stream_status); if (!stream_status) return; /* Cannot commit surface to stream that is not committed */ @@ -1415,19 +1410,19 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (stream_update) { if ((stream_update->src.height != 0) && (stream_update->src.width != 0)) - stream->public.src = stream_update->src; + stream->src = stream_update->src; if ((stream_update->dst.height != 0) && (stream_update->dst.width != 0)) - stream->public.dst = stream_update->dst; + stream->dst = stream_update->dst; if (stream_update->out_transfer_func && stream_update->out_transfer_func != - dc_stream->out_transfer_func) { - if (dc_stream->out_transfer_func != NULL) - dc_transfer_func_release(dc_stream->out_transfer_func); + stream->out_transfer_func) { + if (stream->out_transfer_func != NULL) + dc_transfer_func_release(stream->out_transfer_func); dc_transfer_func_retain(stream_update->out_transfer_func); - stream->public.out_transfer_func = + stream->out_transfer_func = stream_update->out_transfer_func; } } @@ -1469,7 +1464,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* add surface to context */ if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, dc_stream, + new_surfaces, surface_count, stream, context, core_dc->res_pool)) { BREAK_TO_DEBUGGER(); goto fail; @@ -1617,7 +1612,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, core_dc, pipe_ctx->surface, context); /* TODO: this is a hack w/a for switching from mpo to pipe split */ - dc_stream_set_cursor_position(&pipe_ctx->stream->public, &position); + dc_stream_set_cursor_position(pipe_ctx->stream, &position); if (is_new_pipe_surface) { core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); @@ -1712,7 +1707,7 @@ struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i) { struct core_dc *core_dc = DC_TO_CORE(dc); if (i < core_dc->current_context->stream_count) - return &(core_dc->current_context->streams[i]->public); + return core_dc->current_context->streams[i]; return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 9a5df3a848b5..bf127a88e533 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -321,8 +321,8 @@ void context_timing_trace( TIMING_TRACE("OTG_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", pipe_ctx->tg->inst, - pipe_ctx->stream->public.timing.h_total, - pipe_ctx->stream->public.timing.v_total, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, h_pos[i], v_pos[i]); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index fd2ae181cff2..2487046457c8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1143,7 +1143,7 @@ static void dpcd_configure_panel_mode( static void enable_stream_features(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; union down_spread_ctrl downspread; @@ -1151,7 +1151,7 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) &downspread.raw, sizeof(downspread)); downspread.bits.IGNORE_MSA_TIMING_PARAM = - (stream->public.ignore_msa_timing_param) ? 1 : 0; + (stream->ignore_msa_timing_param) ? 1 : 0; core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, &downspread.raw, sizeof(downspread)); @@ -1159,7 +1159,7 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; enum dc_status status; bool skip_video_pattern; struct dc_link *link = stream->sink->link; @@ -1250,7 +1250,7 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; enum dc_color_depth display_color_depth; @@ -1258,13 +1258,13 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) dal_ddc_service_write_scdc_data( stream->sink->link->ddc, stream->phy_pix_clk, - stream->public.timing.flags.LTE_340MCSC_SCRAMBLE); + stream->timing.flags.LTE_340MCSC_SCRAMBLE); memset(&stream->sink->link->cur_link_settings, 0, sizeof(struct dc_link_settings)); - display_color_depth = stream->public.timing.display_color_depth; - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + display_color_depth = stream->timing.display_color_depth; + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) display_color_depth = COLOR_DEPTH_888; link->link_enc->funcs->enable_tmds_output( @@ -1341,7 +1341,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) } enum dc_status dc_link_validate_mode_timing( - const struct core_stream *stream, + const struct dc_stream *stream, struct dc_link *link, const struct dc_crtc_timing *timing) { @@ -1377,7 +1377,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, uint32_t frame_ramp, const struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); - struct core_stream *core_stream = NULL; struct abm *abm = core_dc->res_pool->abm; unsigned int controller_id = 0; int i; @@ -1390,11 +1389,10 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, if (dc_is_embedded_signal(link->connector_signal)) { if (stream != NULL) { - core_stream = DC_STREAM_TO_CORE(stream); for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_context->res_ctx. pipe_ctx[i].stream - == core_stream) + == stream) /* DMCU -1 for all controller id values, * therefore +1 here */ @@ -1457,7 +1455,6 @@ bool dc_link_setup_psr(struct dc_link *link, { struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); int i; psr_context->controllerId = CONTROLLER_ID_UNDEFINED; @@ -1501,7 +1498,7 @@ bool dc_link_setup_psr(struct dc_link *link, for (i = 0; i < MAX_PIPES; i++) { if (core_dc->current_context->res_ctx.pipe_ctx[i].stream - == core_stream) { + == stream) { /* dmcu -1 for all controller id values, * therefore +1 here */ @@ -1590,7 +1587,7 @@ void core_link_resume(struct dc_link *link) program_hpd_filter(link); } -static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream) +static struct fixed31_32 get_pbn_per_slot(struct dc_stream *stream) { struct dc_link_settings *link_settings = &stream->sink->link->cur_link_settings; @@ -1699,7 +1696,7 @@ static void update_mst_stream_alloc_table( */ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; @@ -1717,7 +1714,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) /* get calculate VC payload for stream: stream_alloc */ if (dm_helpers_dp_mst_write_payload_allocation_table( stream->ctx, - &stream->public, + stream, &proposed_table, true)) { update_mst_stream_alloc_table( @@ -1759,11 +1756,11 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) /* send down message */ dm_helpers_dp_mst_poll_for_allocation_change_trigger( stream->ctx, - &stream->public); + stream); dm_helpers_dp_mst_send_payload_allocation( stream->ctx, - &stream->public, + stream, true); /* slot X.Y for only current stream */ @@ -1781,7 +1778,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; @@ -1806,7 +1803,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) if (mst_mode) { if (dm_helpers_dp_mst_write_payload_allocation_table( stream->ctx, - &stream->public, + stream, &proposed_table, false)) { @@ -1848,11 +1845,11 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) if (mst_mode) { dm_helpers_dp_mst_poll_for_allocation_change_trigger( stream->ctx, - &stream->public); + stream); dm_helpers_dp_mst_send_payload_allocation( stream->ctx, - &stream->public, + stream, false); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index c7b400786121..d9754b5f2543 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1434,7 +1434,7 @@ bool dp_validate_mode_timing( return false; } -void decide_link_settings(struct core_stream *stream, +void decide_link_settings(struct dc_stream *stream, struct dc_link_settings *link_setting) { @@ -1446,8 +1446,7 @@ void decide_link_settings(struct core_stream *stream, uint32_t req_bw; uint32_t link_bw; - req_bw = bandwidth_in_kbps_from_timing( - &stream->public.timing); + req_bw = bandwidth_in_kbps_from_timing(&stream->timing); link = stream->sink->link; @@ -2327,7 +2326,7 @@ static void set_crtc_test_pattern(struct dc_link *link, { enum controller_dp_test_pattern controller_test_pattern; enum dc_color_depth color_depth = pipe_ctx-> - stream->public.timing.display_color_depth; + stream->timing.display_color_depth; struct bit_depth_reduction_params params; memset(¶ms, 0, sizeof(params)); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 5bdcd5067116..76dc16916821 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -78,7 +78,7 @@ void dp_enable_link_phy( pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { pipes[i].clock_source = dp_cs; pipes[i].pix_clk_params.requested_pix_clk = - pipes[i].stream->public.timing.pix_clk_khz; + pipes[i].stream->timing.pix_clk_khz; pipes[i].clock_source->funcs->program_pix_clk( pipes[i].clock_source, &pipes[i].pix_clk_params, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index eeefc9c33633..ddbd3de63a8d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -294,25 +294,25 @@ void resource_reference_clock_source( } bool resource_are_streams_timing_synchronizable( - const struct core_stream *stream1, - const struct core_stream *stream2) + struct dc_stream *stream1, + struct dc_stream *stream2) { - if (stream1->public.timing.h_total != stream2->public.timing.h_total) + if (stream1->timing.h_total != stream2->timing.h_total) return false; - if (stream1->public.timing.v_total != stream2->public.timing.v_total) + if (stream1->timing.v_total != stream2->timing.v_total) return false; - if (stream1->public.timing.h_addressable - != stream2->public.timing.h_addressable) + if (stream1->timing.h_addressable + != stream2->timing.h_addressable) return false; - if (stream1->public.timing.v_addressable - != stream2->public.timing.v_addressable) + if (stream1->timing.v_addressable + != stream2->timing.v_addressable) return false; - if (stream1->public.timing.pix_clk_khz - != stream2->public.timing.pix_clk_khz) + if (stream1->timing.pix_clk_khz + != stream2->timing.pix_clk_khz) return false; if (stream1->phy_pix_clk != stream2->phy_pix_clk @@ -431,7 +431,7 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = pipe_ctx->surface; - const struct dc_stream *stream = &pipe_ctx->stream->public; + const struct dc_stream *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; struct rect clip = { 0 }; @@ -530,7 +530,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { const struct dc_surface *surface = pipe_ctx->surface; - struct core_stream *stream = pipe_ctx->stream; + const struct dc_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; struct rect surf_clip = surface->clip_rect; int recout_full_x, recout_full_y; @@ -539,38 +539,38 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->surface->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); - pipe_ctx->scl_data.recout.x = stream->public.dst.x; - if (stream->public.src.x < surf_clip.x) + pipe_ctx->scl_data.recout.x = stream->dst.x; + if (stream->src.x < surf_clip.x) pipe_ctx->scl_data.recout.x += (surf_clip.x - - stream->public.src.x) * stream->public.dst.width - / stream->public.src.width; + - stream->src.x) * stream->dst.width + / stream->src.width; pipe_ctx->scl_data.recout.width = surf_clip.width * - stream->public.dst.width / stream->public.src.width; + stream->dst.width / stream->src.width; if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > - stream->public.dst.x + stream->public.dst.width) + stream->dst.x + stream->dst.width) pipe_ctx->scl_data.recout.width = - stream->public.dst.x + stream->public.dst.width + stream->dst.x + stream->dst.width - pipe_ctx->scl_data.recout.x; - pipe_ctx->scl_data.recout.y = stream->public.dst.y; - if (stream->public.src.y < surf_clip.y) + pipe_ctx->scl_data.recout.y = stream->dst.y; + if (stream->src.y < surf_clip.y) pipe_ctx->scl_data.recout.y += (surf_clip.y - - stream->public.src.y) * stream->public.dst.height - / stream->public.src.height; + - stream->src.y) * stream->dst.height + / stream->src.height; pipe_ctx->scl_data.recout.height = surf_clip.height * - stream->public.dst.height / stream->public.src.height; + stream->dst.height / stream->src.height; if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > - stream->public.dst.y + stream->public.dst.height) + stream->dst.y + stream->dst.height) pipe_ctx->scl_data.recout.height = - stream->public.dst.y + stream->public.dst.height + stream->dst.y + stream->dst.height - pipe_ctx->scl_data.recout.y; /* Handle h & vsplit */ if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { - if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { + if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { pipe_ctx->scl_data.recout.height /= 2; pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; /* Floor primary pipe, ceil 2ndary pipe */ @@ -582,7 +582,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip } } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { - if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) + if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.recout.height /= 2; else pipe_ctx->scl_data.recout.width /= 2; @@ -592,14 +592,14 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ - recout_full_x = stream->public.dst.x + (surface->dst_rect.x - stream->public.src.x) - * stream->public.dst.width / stream->public.src.width - + recout_full_x = stream->dst.x + (surface->dst_rect.x - stream->src.x) + * stream->dst.width / stream->src.width - surf_src.x * surface->dst_rect.width / surf_src.width - * stream->public.dst.width / stream->public.src.width; - recout_full_y = stream->public.dst.y + (surface->dst_rect.y - stream->public.src.y) - * stream->public.dst.height / stream->public.src.height - + * stream->dst.width / stream->src.width; + recout_full_y = stream->dst.y + (surface->dst_rect.y - stream->src.y) + * stream->dst.height / stream->src.height - surf_src.y * surface->dst_rect.height / surf_src.height - * stream->public.dst.height / stream->public.src.height; + * stream->dst.height / stream->src.height; recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; recout_skip->height = pipe_ctx->scl_data.recout.y - recout_full_y; @@ -608,12 +608,12 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = pipe_ctx->surface; - struct core_stream *stream = pipe_ctx->stream; + const struct dc_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; - const int in_w = stream->public.src.width; - const int in_h = stream->public.src.height; - const int out_w = stream->public.dst.width; - const int out_h = stream->public.dst.height; + const int in_w = stream->src.width; + const int in_h = stream->src.height; + const int out_w = stream->dst.width; + const int out_h = stream->dst.height; if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || pipe_ctx->surface->rotation == ROTATION_ANGLE_270) @@ -626,9 +626,9 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) surf_src.height, surface->dst_rect.height); - if (stream->public.view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) + if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) pipe_ctx->scl_data.ratios.horz.value *= 2; - else if (stream->public.view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) + else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.ratios.vert.value *= 2; pipe_ctx->scl_data.ratios.vert.value = div64_s64( @@ -815,7 +815,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { const struct dc_surface *surface = pipe_ctx->surface; - struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct view recout_skip = { 0 }; bool res = false; @@ -920,7 +920,7 @@ struct pipe_ctx *find_idle_secondary_pipe( struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, - const struct core_stream *stream) + struct dc_stream *stream) { int i; for (i = 0; i < MAX_PIPES; i++) { @@ -940,11 +940,10 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( static struct pipe_ctx *acquire_free_pipe_for_stream( struct validate_context *context, const struct resource_pool *pool, - const struct dc_stream *dc_stream) + struct dc_stream *stream) { int i; struct resource_context *res_ctx = &context->res_ctx; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct pipe_ctx *head_pipe = NULL; @@ -980,10 +979,9 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( static void release_free_pipes_for_stream( struct resource_context *res_ctx, - const struct dc_stream *dc_stream) + struct dc_stream *stream) { int i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); for (i = MAX_PIPES - 1; i >= 0; i--) { /* never release the topmost pipe*/ @@ -999,7 +997,7 @@ static void release_free_pipes_for_stream( static int acquire_first_split_pipe( struct resource_context *res_ctx, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { int i; @@ -1033,14 +1031,13 @@ static int acquire_first_split_pipe( bool resource_attach_surfaces_to_context( struct dc_surface * const *surfaces, int surface_count, - const struct dc_stream *dc_stream, + struct dc_stream *stream, struct validate_context *context, const struct resource_pool *pool) { int i; struct pipe_ctx *tail_pipe; struct dc_stream_status *stream_status = NULL; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); if (surface_count > MAX_SURFACE_NUM) { @@ -1050,7 +1047,7 @@ bool resource_attach_surfaces_to_context( } for (i = 0; i < context->stream_count; i++) - if (&context->streams[i]->public == dc_stream) { + if (context->streams[i] == stream) { stream_status = &context->stream_status[i]; break; } @@ -1081,7 +1078,7 @@ bool resource_attach_surfaces_to_context( for (i = 0; i < surface_count; i++) { struct dc_surface *surface = surfaces[i]; struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( - context, pool, dc_stream); + context, pool, stream); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (!free_pipe) { @@ -1109,7 +1106,7 @@ bool resource_attach_surfaces_to_context( tail_pipe = free_pipe; } - release_free_pipes_for_stream(&context->res_ctx, dc_stream); + release_free_pipes_for_stream(&context->res_ctx, stream); /* assign new surfaces*/ for (i = 0; i < surface_count; i++) @@ -1121,8 +1118,8 @@ bool resource_attach_surfaces_to_context( } -static bool is_timing_changed(const struct core_stream *cur_stream, - const struct core_stream *new_stream) +static bool is_timing_changed(struct dc_stream *cur_stream, + struct dc_stream *new_stream) { if (cur_stream == NULL) return true; @@ -1134,18 +1131,17 @@ static bool is_timing_changed(const struct core_stream *cur_stream, return true; /* If output color space is changed, need to reprogram info frames */ - if (cur_stream->public.output_color_space != - new_stream->public.output_color_space) + if (cur_stream->output_color_space != new_stream->output_color_space) return true; return memcmp( - &cur_stream->public.timing, - &new_stream->public.timing, + &cur_stream->timing, + &new_stream->timing, sizeof(struct dc_crtc_timing)) != 0; } static bool are_stream_backends_same( - const struct core_stream *stream_a, const struct core_stream *stream_b) + struct dc_stream *stream_a, struct dc_stream *stream_b) { if (stream_a == stream_b) return true; @@ -1160,7 +1156,7 @@ static bool are_stream_backends_same( } bool is_stream_unchanged( - const struct core_stream *old_stream, const struct core_stream *stream) + struct dc_stream *old_stream, struct dc_stream *stream) { if (!are_stream_backends_same(old_stream, stream)) @@ -1186,7 +1182,7 @@ bool resource_validate_attach_surfaces( if (!resource_attach_surfaces_to_context( old_context->stream_status[j].surfaces, old_context->stream_status[j].surface_count, - &context->streams[i]->public, + context->streams[i], context, pool)) return false; context->stream_status[i] = old_context->stream_status[j]; @@ -1195,7 +1191,7 @@ bool resource_validate_attach_surfaces( if (!resource_attach_surfaces_to_context( set[i].surfaces, set[i].surface_count, - &context->streams[i]->public, + context->streams[i], context, pool)) return false; @@ -1237,7 +1233,7 @@ static void set_audio_in_use( static int acquire_first_free_pipe( struct resource_context *res_ctx, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { int i; @@ -1267,7 +1263,7 @@ static int acquire_first_free_pipe( static struct stream_encoder *find_first_free_match_stream_enc_for_link( struct resource_context *res_ctx, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { int i; int j = -1; @@ -1318,22 +1314,22 @@ static struct audio *find_first_free_audio( return 0; } -static void update_stream_signal(struct core_stream *stream) +static void update_stream_signal(struct dc_stream *stream) { - if (stream->public.output_signal == SIGNAL_TYPE_NONE) { - struct dc_sink *dc_sink = stream->public.sink; + if (stream->output_signal == SIGNAL_TYPE_NONE) { + struct dc_sink *dc_sink = stream->sink; if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) stream->signal = stream->sink->link->connector_signal; else stream->signal = dc_sink->sink_signal; } else { - stream->signal = stream->public.output_signal; + stream->signal = stream->output_signal; } if (dc_is_dvi_signal(stream->signal)) { - if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && - stream->public.sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && + stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; else stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; @@ -1341,12 +1337,12 @@ static void update_stream_signal(struct core_stream *stream) } bool resource_is_stream_unchanged( - const struct validate_context *old_context, const struct core_stream *stream) + struct validate_context *old_context, struct dc_stream *stream) { int i; for (i = 0; i < old_context->stream_count; i++) { - const struct core_stream *old_stream = old_context->streams[i]; + struct dc_stream *old_stream = old_context->streams[i]; if (are_stream_backends_same(old_stream, stream)) return true; @@ -1359,7 +1355,7 @@ static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { struct dc_surface *surface = to_pipe_ctx->surface; - struct core_stream *stream = to_pipe_ctx->stream; + struct dc_stream *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; to_pipe_ctx->stream = stream; @@ -1367,14 +1363,14 @@ static void copy_pipe_ctx( to_pipe_ctx->surface = surface; } -static struct core_stream *find_pll_sharable_stream( - const struct core_stream *stream_needs_pll, +static struct dc_stream *find_pll_sharable_stream( + struct dc_stream *stream_needs_pll, struct validate_context *context) { int i; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream_has_pll = context->streams[i]; + struct dc_stream *stream_has_pll = context->streams[i]; /* We are looking for non dp, non virtual stream */ if (resource_are_streams_timing_synchronizable( @@ -1418,17 +1414,17 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) return normalized_pix_clk; } -static void calculate_phy_pix_clks(struct core_stream *stream) +static void calculate_phy_pix_clks(struct dc_stream *stream) { update_stream_signal(stream); /* update actual pixel clock on all streams */ if (dc_is_hdmi_signal(stream->signal)) stream->phy_pix_clk = get_norm_pix_clk( - &stream->public.timing); + &stream->timing); else stream->phy_pix_clk = - stream->public.timing.pix_clk_khz; + stream->timing.pix_clk_khz; } enum dc_status resource_map_pool_resources( @@ -1440,7 +1436,7 @@ enum dc_status resource_map_pool_resources( int i, j; for (i = 0; old_context && i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (!resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -1493,7 +1489,7 @@ enum dc_status resource_map_pool_resources( } for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; struct pipe_ctx *pipe_ctx = NULL; int pipe_idx = -1; @@ -1524,7 +1520,7 @@ enum dc_status resource_map_pool_resources( /* TODO: Add check if ASIC support and EDID audio */ if (!stream->sink->converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && - stream->public.audio_info.mode_count) { + stream->audio_info.mode_count) { pipe_ctx->audio = find_first_free_audio( &context->res_ctx, pool); @@ -1560,7 +1556,7 @@ void validate_guaranteed_copy_streams( context->res_ctx.pipe_ctx[i].stream = context->res_ctx.pipe_ctx[0].stream; - dc_stream_retain(&context->streams[i]->public); + dc_stream_retain(context->streams[i]); context->stream_count++; } } @@ -1588,7 +1584,7 @@ static void set_avi_info_frame( struct encoder_info_packet *info_packet, struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; struct info_frame info_frame = { {0} }; uint32_t pixel_encoding = 0; @@ -1602,12 +1598,12 @@ static void set_avi_info_frame( uint8_t byte_index = 0; union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi; union display_content_support support = {0}; - unsigned int vic = pipe_ctx->stream->public.timing.vic; + unsigned int vic = pipe_ctx->stream->timing.vic; enum dc_timing_3d_format format; - color_space = pipe_ctx->stream->public.output_color_space; + color_space = pipe_ctx->stream->output_color_space; if (color_space == COLOR_SPACE_UNKNOWN) - color_space = (stream->public.timing.pixel_encoding == PIXEL_ENCODING_RGB)? + color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; /* Initialize header */ @@ -1622,7 +1618,7 @@ static void set_avi_info_frame( * according to HDMI 2.0 spec (Section 10.1) */ - switch (stream->public.timing.pixel_encoding) { + switch (stream->timing.pixel_encoding) { case PIXEL_ENCODING_YCBCR422: pixel_encoding = 1; break; @@ -1664,7 +1660,7 @@ static void set_avi_info_frame( color_space == COLOR_SPACE_YCBCR601_LIMITED) hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601; else { - if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB) + if (stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) BREAK_TO_DEBUGGER(); hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA; } @@ -1679,7 +1675,7 @@ static void set_avi_info_frame( } /* TODO: un-hardcode aspect ratio */ - aspect = stream->public.timing.aspect_ratio; + aspect = stream->timing.aspect_ratio; switch (aspect) { case ASPECT_RATIO_4_3: @@ -1705,7 +1701,7 @@ static void set_avi_info_frame( itc = true; itc_value = 1; - support = stream->public.sink->edid_caps.content_support; + support = stream->sink->edid_caps.content_support; if (itc) { if (!support.bits.valid_content_type) { @@ -1744,8 +1740,8 @@ static void set_avi_info_frame( /* TODO : We should handle YCC quantization */ /* but we do not have matrix calculation */ - if (stream->public.sink->edid_caps.qs_bit == 1 && - stream->public.sink->edid_caps.qy_bit == 1) { + if (stream->sink->edid_caps.qs_bit == 1 && + stream->sink->edid_caps.qy_bit == 1) { if (color_space == COLOR_SPACE_SRGB || color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; @@ -1764,11 +1760,11 @@ static void set_avi_info_frame( } ///VIC - format = stream->public.timing.timing_3d_format; + format = stream->timing.timing_3d_format; /*todo, add 3DStereo support*/ if (format != TIMING_3D_FORMAT_NONE) { // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled - switch (pipe_ctx->stream->public.timing.hdmi_vic) { + switch (pipe_ctx->stream->timing.hdmi_vic) { case 1: vic = 95; break; @@ -1797,12 +1793,12 @@ static void set_avi_info_frame( * barBottom: Line Number of Start of Bottom Bar. * barLeft: Pixel Number of End of Left Bar. * barRight: Pixel Number of Start of Right Bar. */ - hdmi_info->bits.bar_top = stream->public.timing.v_border_top; - hdmi_info->bits.bar_bottom = (stream->public.timing.v_total - - stream->public.timing.v_border_bottom + 1); - hdmi_info->bits.bar_left = stream->public.timing.h_border_left; - hdmi_info->bits.bar_right = (stream->public.timing.h_total - - stream->public.timing.h_border_right + 1); + hdmi_info->bits.bar_top = stream->timing.v_border_top; + hdmi_info->bits.bar_bottom = (stream->timing.v_total + - stream->timing.v_border_bottom + 1); + hdmi_info->bits.bar_left = stream->timing.h_border_left; + hdmi_info->bits.bar_right = (stream->timing.h_total + - stream->timing.h_border_right + 1); /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ check_sum = &info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; @@ -1830,7 +1826,7 @@ static void set_avi_info_frame( static void set_vendor_info_packet( struct encoder_info_packet *info_packet, - struct core_stream *stream) + struct dc_stream *stream) { uint32_t length = 0; bool hdmi_vic_mode = false; @@ -1842,16 +1838,16 @@ static void set_vendor_info_packet( info_packet->valid = false; - format = stream->public.timing.timing_3d_format; - if (stream->public.view_format == VIEW_3D_FORMAT_NONE) + format = stream->timing.timing_3d_format; + if (stream->view_format == VIEW_3D_FORMAT_NONE) format = TIMING_3D_FORMAT_NONE; /* Can be different depending on packet content */ length = 5; - if (stream->public.timing.hdmi_vic != 0 - && stream->public.timing.h_total >= 3840 - && stream->public.timing.v_total >= 2160) + if (stream->timing.hdmi_vic != 0 + && stream->timing.h_total >= 3840 + && stream->timing.v_total >= 2160) hdmi_vic_mode = true; /* According to HDMI 1.4a CTS, VSIF should be sent @@ -1918,7 +1914,7 @@ static void set_vendor_info_packet( /*PB5: If PB4 is set to 0x1 (extended resolution format) * fill PB5 with the correct HDMI VIC code */ if (hdmi_vic_mode) - info_packet->sb[5] = stream->public.timing.hdmi_vic; + info_packet->sb[5] = stream->timing.hdmi_vic; /* Header */ info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */ @@ -1943,7 +1939,7 @@ static void set_vendor_info_packet( static void set_spd_info_packet( struct encoder_info_packet *info_packet, - struct core_stream *stream) + struct dc_stream *stream) { /* SPD info packet for FreeSync */ @@ -1953,7 +1949,7 @@ static void set_spd_info_packet( /* Check if Freesync is supported. Return if false. If true, * set the corresponding bit in the info packet */ - if (stream->public.freesync_ctx.supported == false) + if (stream->freesync_ctx.supported == false) return; if (dc_is_hdmi_signal(stream->signal)) { @@ -2018,20 +2014,20 @@ static void set_spd_info_packet( /* PB6 = [Bits 7:3 = Reserved] */ info_packet->sb[6] = 0x00; - if (stream->public.freesync_ctx.supported == true) + if (stream->freesync_ctx.supported == true) /* PB6 = [Bit 0 = FreeSync Supported] */ info_packet->sb[6] |= 0x01; - if (stream->public.freesync_ctx.enabled == true) + if (stream->freesync_ctx.enabled == true) /* PB6 = [Bit 1 = FreeSync Enabled] */ info_packet->sb[6] |= 0x02; - if (stream->public.freesync_ctx.active == true) + if (stream->freesync_ctx.active == true) /* PB6 = [Bit 2 = FreeSync Active] */ info_packet->sb[6] |= 0x04; /* PB7 = FreeSync Minimum refresh rate (Hz) */ - info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx. + info_packet->sb[7] = (unsigned char) (stream->freesync_ctx. min_refresh_in_micro_hz / 1000000); /* PB8 = FreeSync Maximum refresh rate (Hz) @@ -2040,7 +2036,7 @@ static void set_spd_info_packet( * of the panel, because we should never go above the field * rate of the mode timing set. */ - info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx. + info_packet->sb[8] = (unsigned char) (stream->freesync_ctx. nominal_refresh_in_micro_hz / 1000000); /* PB9 - PB27 = Reserved */ @@ -2065,7 +2061,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, struct dc_surface *surface, - struct core_stream *stream) + struct dc_stream *stream) { uint16_t i = 0; enum signal_type signal = stream->signal; @@ -2168,7 +2164,7 @@ static void set_hdr_static_info_packet( static void set_vsc_info_packet( struct encoder_info_packet *info_packet, - struct core_stream *stream) + struct dc_stream *stream) { unsigned int vscPacketRevision = 0; unsigned int i; @@ -2218,7 +2214,7 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context) context->stream_status[i].surfaces[j]); context->stream_status[i].surface_count = 0; - dc_stream_release(&context->streams[i]->public); + dc_stream_release(context->streams[i]); context->streams[i] = NULL; } } @@ -2248,7 +2244,7 @@ void dc_resource_validate_ctx_copy_construct( } for (i = 0; i < dst_ctx->stream_count; i++) { - dc_stream_retain(&dst_ctx->streams[i]->public); + dc_stream_retain(dst_ctx->streams[i]); for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++) dc_surface_retain( dst_ctx->stream_status[i].surfaces[j]); @@ -2321,7 +2317,7 @@ enum dc_status resource_map_clock_resources( /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { - const struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -2401,12 +2397,12 @@ bool pipe_need_reprogram( return false; } -void resource_build_bit_depth_reduction_params(const struct core_stream *stream, +void resource_build_bit_depth_reduction_params(struct dc_stream *stream, struct bit_depth_reduction_params *fmt_bit_depth) { - enum dc_dither_option option = stream->public.dither_option; + enum dc_dither_option option = stream->dither_option; enum dc_pixel_encoding pixel_encoding = - stream->public.timing.pixel_encoding; + stream->timing.pixel_encoding; memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); @@ -2511,31 +2507,30 @@ void resource_build_bit_depth_reduction_params(const struct core_stream *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(const struct dc *dc, const struct dc_stream *stream) +bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_context *dc_ctx = core_dc->ctx; - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - struct dc_link *link = core_stream->sink->link; + struct dc_link *link = stream->sink->link; struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; enum dc_status res = DC_OK; - calculate_phy_pix_clks(core_stream); + calculate_phy_pix_clks(stream); - if (!tg->funcs->validate_timing(tg, &core_stream->public.timing)) + if (!tg->funcs->validate_timing(tg, &stream->timing)) res = DC_FAIL_CONTROLLER_VALIDATE; if (res == DC_OK) if (!link->link_enc->funcs->validate_output_with_stream( - link->link_enc, core_stream)) + link->link_enc, stream)) res = DC_FAIL_ENC_VALIDATE; /* TODO: validate audio ASIC caps, encoder */ if (res == DC_OK) - res = dc_link_validate_mode_timing(core_stream, + res = dc_link_validate_mode_timing(stream, link, - &core_stream->public.timing); + &stream->timing); if (res != DC_OK) DC_ERROR("Failed validation for stream %p, err:%d, !\n", diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 5b356ddf5614..46ad1bc12f63 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -35,24 +35,24 @@ ******************************************************************************/ struct stream { - struct core_stream protected; + struct dc_stream protected; int ref_count; }; -#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public) +#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected) /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct core_stream *stream, +static bool construct(struct dc_stream *stream, struct dc_sink *dc_sink_data) { uint32_t i = 0; stream->sink = dc_sink_data; stream->ctx = stream->sink->ctx; - stream->public.sink = dc_sink_data; + stream->sink = dc_sink_data; dc_sink_retain(dc_sink_data); @@ -60,52 +60,52 @@ static bool construct(struct core_stream *stream, /* TODO - Remove this translation */ for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++) { - stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count; - stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code; - stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate; - stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size; + stream->audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count; + stream->audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code; + stream->audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate; + stream->audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size; } - stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count; - stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency; - stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency; + stream->audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count; + stream->audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency; + stream->audio_info.video_latency = dc_sink_data->edid_caps.video_latency; memmove( - stream->public.audio_info.display_name, + stream->audio_info.display_name, dc_sink_data->edid_caps.display_name, AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS); - stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id; - stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id; - stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; + stream->audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id; + stream->audio_info.product_id = dc_sink_data->edid_caps.product_id; + stream->audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags; if (dc_sink_data->dc_container_id != NULL) { struct dc_container_id *dc_container_id = dc_sink_data->dc_container_id; - stream->public.audio_info.port_id[0] = dc_container_id->portId[0]; - stream->public.audio_info.port_id[1] = dc_container_id->portId[1]; + stream->audio_info.port_id[0] = dc_container_id->portId[0]; + stream->audio_info.port_id[1] = dc_container_id->portId[1]; } else { /* TODO - WindowDM has implemented, other DMs need Unhardcode port_id */ - stream->public.audio_info.port_id[0] = 0x5558859e; - stream->public.audio_info.port_id[1] = 0xd989449; + stream->audio_info.port_id[0] = 0x5558859e; + stream->audio_info.port_id[1] = 0xd989449; } /* EDID CAP translation for HDMI 2.0 */ - stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; + stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; stream->status.link = stream->sink->link; return true; } -static void destruct(struct core_stream *stream) +static void destruct(struct dc_stream *stream) { dc_sink_release(stream->sink); - if (stream->public.out_transfer_func != NULL) { + if (stream->out_transfer_func != NULL) { dc_transfer_func_release( - stream->public.out_transfer_func); - stream->public.out_transfer_func = NULL; + stream->out_transfer_func); + stream->out_transfer_func = NULL; } } -void dc_stream_retain(const struct dc_stream *dc_stream) +void dc_stream_retain(struct dc_stream *dc_stream) { struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); @@ -113,17 +113,16 @@ void dc_stream_retain(const struct dc_stream *dc_stream) stream->ref_count++; } -void dc_stream_release(const struct dc_stream *public) +void dc_stream_release(struct dc_stream *public) { struct stream *stream = DC_STREAM_TO_STREAM(public); - struct core_stream *protected = DC_STREAM_TO_CORE(public); if (public != NULL) { ASSERT(stream->ref_count > 0); stream->ref_count--; if (stream->ref_count == 0) { - destruct(protected); + destruct(public); dm_free(stream); } } @@ -147,7 +146,7 @@ struct dc_stream *dc_create_stream_for_sink( stream->ref_count++; - return &stream->protected.public; + return &stream->protected; construct_fail: dm_free(stream); @@ -157,10 +156,9 @@ struct dc_stream *dc_create_stream_for_sink( } struct dc_stream_status *dc_stream_get_status( - const struct dc_stream *dc_stream) + struct dc_stream *stream) { uint8_t i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); for (i = 0; i < dc->current_context->stream_count; i++) { @@ -176,15 +174,14 @@ struct dc_stream_status *dc_stream_get_status( * Update the cursor attributes and set cursor surface address */ bool dc_stream_set_cursor_attributes( - const struct dc_stream *dc_stream, + const struct dc_stream *stream, const struct dc_cursor_attributes *attributes) { int i; - struct core_stream *stream; struct core_dc *core_dc; struct resource_context *res_ctx; - if (NULL == dc_stream) { + if (NULL == stream) { dm_error("DC: dc_stream is NULL!\n"); return false; } @@ -193,7 +190,6 @@ bool dc_stream_set_cursor_attributes( return false; } - stream = DC_STREAM_TO_CORE(dc_stream); core_dc = DC_TO_CORE(stream->ctx->dc); res_ctx = &core_dc->current_context->res_ctx; @@ -213,15 +209,14 @@ bool dc_stream_set_cursor_attributes( } bool dc_stream_set_cursor_position( - const struct dc_stream *dc_stream, + struct dc_stream *stream, const struct dc_cursor_position *position) { int i; - struct core_stream *stream; struct core_dc *core_dc; struct resource_context *res_ctx; - if (NULL == dc_stream) { + if (NULL == stream) { dm_error("DC: dc_stream is NULL!\n"); return false; } @@ -231,7 +226,6 @@ bool dc_stream_set_cursor_position( return false; } - stream = DC_STREAM_TO_CORE(dc_stream); core_dc = DC_TO_CORE(stream->ctx->dc); res_ctx = &core_dc->current_context->res_ctx; @@ -240,7 +234,7 @@ bool dc_stream_set_cursor_position( struct input_pixel_processor *ipp = pipe_ctx->ipp; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { - .pixel_clk_khz = dc_stream->timing.pix_clk_khz, + .pixel_clk_khz = stream->timing.pix_clk_khz, .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz, .viewport_x_start = pipe_ctx->scl_data.viewport.x, .viewport_width = pipe_ctx->scl_data.viewport.width, @@ -264,10 +258,9 @@ bool dc_stream_set_cursor_position( return true; } -uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) +uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream) { uint8_t i; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &core_dc->current_context->res_ctx; @@ -284,7 +277,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream) return 0; } -bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream, +bool dc_stream_get_scanoutpos(const struct dc_stream *stream, uint32_t *v_blank_start, uint32_t *v_blank_end, uint32_t *h_position, @@ -292,7 +285,6 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream, { uint8_t i; bool ret = false; - struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &core_dc->current_context->res_ctx; @@ -322,37 +314,35 @@ void dc_stream_log( struct dal_logger *dm_logger, enum dc_log_type log_type) { - const struct core_stream *core_stream = - DC_STREAM_TO_CORE(stream); dm_logger_write(dm_logger, log_type, "core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d, colorSpace:%d\n", - core_stream, - core_stream->public.src.x, - core_stream->public.src.y, - core_stream->public.src.width, - core_stream->public.src.height, - core_stream->public.dst.x, - core_stream->public.dst.y, - core_stream->public.dst.width, - core_stream->public.dst.height, - core_stream->public.output_color_space); + stream, + stream->src.x, + stream->src.y, + stream->src.width, + stream->src.height, + stream->dst.x, + stream->dst.y, + stream->dst.width, + stream->dst.height, + stream->output_color_space); dm_logger_write(dm_logger, log_type, "\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n", - core_stream->public.timing.pix_clk_khz, - core_stream->public.timing.h_total, - core_stream->public.timing.v_total, - core_stream->public.timing.pixel_encoding, - core_stream->public.timing.display_color_depth); + stream->timing.pix_clk_khz, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pixel_encoding, + stream->timing.display_color_depth); dm_logger_write(dm_logger, log_type, "\tsink name: %s, serial: %d\n", - core_stream->sink->edid_caps.display_name, - core_stream->sink->edid_caps.serial_number); + stream->sink->edid_caps.display_name, + stream->sink->edid_caps.serial_number); dm_logger_write(dm_logger, log_type, "\tlink: %d\n", - core_stream->sink->link->link_index); + stream->sink->link->link_index); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f87f6c12494c..b20f7bfcdc1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -32,6 +32,7 @@ #include "gpio_types.h" #include "link_service_types.h" #include "grph_object_ctrl_defs.h" +#include #define MAX_SURFACES 3 #define MAX_STREAMS 6 @@ -106,12 +107,12 @@ struct dc_cap_funcs { struct dc_stream_funcs { bool (*adjust_vmin_vmax)(struct dc *dc, - const struct dc_stream **stream, + struct dc_stream **stream, int num_streams, int vmin, int vmax); bool (*get_crtc_position)(struct dc *dc, - const struct dc_stream **stream, + struct dc_stream **stream, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos); @@ -120,14 +121,14 @@ struct dc_stream_funcs { const struct dc_stream *stream); bool (*program_csc_matrix)(struct dc *dc, - const struct dc_stream *stream); + struct dc_stream *stream); void (*set_static_screen_events)(struct dc *dc, - const struct dc_stream **stream, + struct dc_stream **stream, int num_streams, const struct dc_static_screen_events *events); - void (*set_dither_option)(const struct dc_stream *stream, + void (*set_dither_option)(struct dc_stream *stream, enum dc_dither_option option); }; @@ -428,7 +429,7 @@ bool dc_commit_surfaces_to_stream( struct dc *dc, struct dc_surface **dc_surfaces, uint8_t surface_count, - const struct dc_stream *stream); + struct dc_stream *stream); bool dc_post_update_surfaces_to_stream( struct dc *dc); @@ -468,6 +469,18 @@ enum surface_update_type { /******************************************************************************* * Stream Interfaces ******************************************************************************/ + +struct dc_stream_status { + int primary_otg_inst; + int surface_count; + struct dc_surface *surfaces[MAX_SURFACE_NUM]; + + /* + * link this stream passes through + */ + struct dc_link *link; +}; + struct dc_stream { struct dc_sink *sink; struct dc_crtc_timing timing; @@ -495,6 +508,21 @@ struct dc_stream { /* TODO: ABM info (DMCU) */ /* TODO: PSR info */ /* TODO: CEA VIC */ + + /* from core_stream struct */ + struct dc_context *ctx; + + /* used by DCP and FMT */ + struct bit_depth_reduction_params bit_depth_params; + struct clamping_and_pixel_encoding_params clamping; + + int phy_pix_clk; + enum signal_type signal; + + struct dc_stream_status status; + + /* from stream struct */ + int ref_count; }; struct dc_stream_update { @@ -521,7 +549,7 @@ struct dc_stream_update { void dc_update_surfaces_and_stream(struct dc *dc, struct dc_surface_update *surface_updates, int surface_count, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct dc_stream_update *stream_update); /* @@ -554,12 +582,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, * Structure to store surface/stream associations for validation */ struct dc_validation_set { - const struct dc_stream *stream; + struct dc_stream *stream; struct dc_surface *surfaces[MAX_SURFACES]; uint8_t surface_count; }; -bool dc_validate_stream(const struct dc *dc, const struct dc_stream *stream); +bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream); /* * This function takes a set of resources and checks that they are cofunctional. @@ -587,7 +615,7 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - const struct dc_stream *stream); + struct dc_stream *stream); void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, @@ -616,7 +644,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context); */ bool dc_commit_streams( struct dc *dc, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count); /* * Enable stereo when commit_streams is not required, @@ -625,7 +653,7 @@ bool dc_commit_streams( bool dc_enable_stereo( struct dc *dc, struct validate_context *context, - const struct dc_stream *streams[], + struct dc_stream *streams[], uint8_t stream_count); /** @@ -633,22 +661,11 @@ bool dc_enable_stereo( */ struct dc_stream *dc_create_stream_for_sink(struct dc_sink *dc_sink); -void dc_stream_retain(const struct dc_stream *dc_stream); -void dc_stream_release(const struct dc_stream *dc_stream); - -struct dc_stream_status { - int primary_otg_inst; - int surface_count; - struct dc_surface *surfaces[MAX_SURFACE_NUM]; - - /* - * link this stream passes through - */ - struct dc_link *link; -}; +void dc_stream_retain(struct dc_stream *dc_stream); +void dc_stream_release(struct dc_stream *dc_stream); struct dc_stream_status *dc_stream_get_status( - const struct dc_stream *dc_stream); + struct dc_stream *dc_stream); enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, @@ -915,7 +932,7 @@ bool dc_stream_set_cursor_attributes( const struct dc_cursor_attributes *attributes); bool dc_stream_set_cursor_position( - const struct dc_stream *stream, + struct dc_stream *stream, const struct dc_cursor_position *position); /* Newer interfaces */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index aff0a440d4d3..24d0c48258ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1009,7 +1009,7 @@ bool dce110_link_encoder_construct( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct core_stream *stream) + const struct dc_stream *stream) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); bool is_valid; @@ -1021,22 +1021,22 @@ bool dce110_link_encoder_validate_output_with_stream( enc110, stream->sink->link->connector_signal, stream->signal, - &stream->public.timing); + &stream->timing); break; case SIGNAL_TYPE_HDMI_TYPE_A: is_valid = dce110_link_encoder_validate_hdmi_output( enc110, - &stream->public.timing, + &stream->timing, stream->phy_pix_clk); break; case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: is_valid = dce110_link_encoder_validate_dp_output( - enc110, &stream->public.timing); + enc110, &stream->timing); break; case SIGNAL_TYPE_EDP: is_valid = - (stream->public.timing. + (stream->timing. pixel_encoding == PIXEL_ENCODING_RGB) ? true : false; break; case SIGNAL_TYPE_VIRTUAL: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index ded6c61304e6..a47b075f4869 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -199,7 +199,7 @@ bool dce110_link_encoder_validate_wireless_output( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct core_stream *stream); + const struct dc_stream *stream); /****************** HW programming ************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 3d25a90e49b4..cf98f2471023 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -660,7 +660,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -734,8 +734,8 @@ enum dc_status dce100_validate_with_context( return DC_FAIL_SURFACE_VALIDATE; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -765,13 +765,13 @@ enum dc_status dce100_validate_with_context( enum dc_status dce100_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = dc_stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 119365960cd0..15f6eeef343d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -623,21 +623,21 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_stream *stream) + const struct dc_stream *stream) { struct output_pixel_processor *opp = pipe_ctx->opp; opp->funcs->opp_power_on_regamma_lut(opp, true); opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; - if (stream->public.out_transfer_func && - stream->public.out_transfer_func->type == + if (stream->out_transfer_func && + stream->out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->public.out_transfer_func->tf == + stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); } else if (dce110_translate_regamma_to_hw_format( - stream->public.out_transfer_func, &opp->regamma_params)) { + stream->out_transfer_func, &opp->regamma_params)) { opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); } else { @@ -702,7 +702,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) enum dc_lane_count lane_count = pipe_ctx->stream->sink->link->cur_link_settings.lane_count; - struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; + struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct dc_link *link = pipe_ctx->stream->sink->link; /* 1. update AVI info frame (HDMI, DP) @@ -745,7 +745,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; if (pipe_ctx->audio) { @@ -797,7 +797,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, /* only 3 items below are used by unblank */ params.pixel_clk_khz = - pipe_ctx->stream->public.timing.pix_clk_khz; + pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); } @@ -833,7 +833,7 @@ static void build_audio_output( const struct pipe_ctx *pipe_ctx, struct audio_output *audio_output) { - const struct core_stream *stream = pipe_ctx->stream; + const struct dc_stream *stream = pipe_ctx->stream; audio_output->engine_id = pipe_ctx->stream_enc->id; audio_output->signal = pipe_ctx->stream->signal; @@ -841,33 +841,33 @@ static void build_audio_output( /* audio_crtc_info */ audio_output->crtc_info.h_total = - stream->public.timing.h_total; + stream->timing.h_total; /* * Audio packets are sent during actual CRTC blank physical signal, we * need to specify actual active signal portion */ audio_output->crtc_info.h_active = - stream->public.timing.h_addressable - + stream->public.timing.h_border_left - + stream->public.timing.h_border_right; + stream->timing.h_addressable + + stream->timing.h_border_left + + stream->timing.h_border_right; audio_output->crtc_info.v_active = - stream->public.timing.v_addressable - + stream->public.timing.v_border_top - + stream->public.timing.v_border_bottom; + stream->timing.v_addressable + + stream->timing.v_border_top + + stream->timing.v_border_bottom; audio_output->crtc_info.pixel_repetition = 1; audio_output->crtc_info.interlaced = - stream->public.timing.flags.INTERLACE; + stream->timing.flags.INTERLACE; audio_output->crtc_info.refresh_rate = - (stream->public.timing.pix_clk_khz*1000)/ - (stream->public.timing.h_total*stream->public.timing.v_total); + (stream->timing.pix_clk_khz*1000)/ + (stream->timing.h_total*stream->timing.v_total); audio_output->crtc_info.color_depth = - stream->public.timing.display_color_depth; + stream->timing.display_color_depth; audio_output->crtc_info.requested_pixel_clock = pipe_ctx->pix_clk_params.requested_pix_clk; @@ -878,7 +878,7 @@ static void build_audio_output( /*for HDMI, audio ACR is with deep color ratio factor*/ if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && audio_output->crtc_info.requested_pixel_clock == - stream->public.timing.pix_clk_khz) { + stream->timing.pix_clk_khz) { if (pipe_ctx->pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { audio_output->crtc_info.requested_pixel_clock = audio_output->crtc_info.requested_pixel_clock/2; @@ -959,7 +959,7 @@ static void program_scaler(const struct core_dc *dc, get_surface_visual_confirm_color(pipe_ctx, &color); else color_space_to_black_color(dc, - pipe_ctx->stream->public.output_color_space, + pipe_ctx->stream->output_color_space, &color); pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth( @@ -981,7 +981,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( struct validate_context *context, struct core_dc *dc) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; struct tg_color black_color = {0}; @@ -990,7 +990,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( /* program blank color */ color_space_to_black_color(dc, - stream->public.output_color_space, &black_color); + stream->output_color_space, &black_color); pipe_ctx->tg->funcs->set_blank_color( pipe_ctx->tg, &black_color); @@ -1011,7 +1011,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( pipe_ctx->tg->funcs->program_timing( pipe_ctx->tg, - &stream->public.timing, + &stream->timing, true); pipe_ctx->tg->funcs->set_static_screen_control( @@ -1037,7 +1037,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( struct validate_context *context, struct core_dc *dc) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; @@ -1047,7 +1047,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->opp->funcs->opp_set_dyn_expansion( pipe_ctx->opp, COLOR_SPACE_YCBCR601, - stream->public.timing.display_color_depth, + stream->timing.display_color_depth, pipe_ctx->stream->signal); /* FPGA does not program backend */ @@ -1074,7 +1074,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_enc->funcs->setup_stereo_sync( pipe_ctx->stream_enc, pipe_ctx->tg->inst, - stream->public.timing.timing_3d_format != TIMING_3D_FORMAT_NONE); + stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); /*vbios crtc_source_selection and encoder_setup will override fmt_C*/ @@ -1086,20 +1086,20 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_enc, - &stream->public.timing, - stream->public.output_color_space); + &stream->timing, + stream->output_color_space); if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute( pipe_ctx->stream_enc, - &stream->public.timing, + &stream->timing, stream->phy_pix_clk, pipe_ctx->audio != NULL); if (dc_is_dvi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute( pipe_ctx->stream_enc, - &stream->public.timing, + &stream->timing, (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? true : false); @@ -1129,9 +1129,9 @@ static enum dc_status apply_single_controller_ctx_to_hw( #endif pipe_ctx->mi->funcs->allocate_mem_input( pipe_ctx->mi, - stream->public.timing.h_total, - stream->public.timing.v_total, - stream->public.timing.pix_clk_khz, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pix_clk_khz, context->stream_count); pipe_ctx->stream->sink->link->psr_enabled = false; @@ -1228,7 +1228,7 @@ void dce110_enable_accelerated_mode(struct core_dc *dc) static uint32_t compute_pstate_blackout_duration( struct bw_fixed blackout_duration, - const struct core_stream *stream) + const struct dc_stream *stream) { uint32_t total_dest_line_time_ns; uint32_t pstate_blackout_duration_ns; @@ -1236,8 +1236,8 @@ static uint32_t compute_pstate_blackout_duration( pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24; total_dest_line_time_ns = 1000000UL * - stream->public.timing.h_total / - stream->public.timing.pix_clk_khz + + stream->timing.h_total / + stream->timing.pix_clk_khz + pstate_blackout_duration_ns; return total_dest_line_time_ns; @@ -1805,19 +1805,19 @@ enum dc_status dce110_apply_ctx_to_hw( pipe_ctx->stream_enc->funcs->dp_audio_setup( pipe_ctx->stream_enc, pipe_ctx->audio->inst, - &pipe_ctx->stream->public.audio_info); + &pipe_ctx->stream->audio_info); else pipe_ctx->stream_enc->funcs->hdmi_audio_setup( pipe_ctx->stream_enc, pipe_ctx->audio->inst, - &pipe_ctx->stream->public.audio_info, + &pipe_ctx->stream->audio_info, &audio_output.crtc_info); pipe_ctx->audio->funcs->az_configure( pipe_ctx->audio, pipe_ctx->stream->signal, &audio_output.crtc_info, - &pipe_ctx->stream->public.audio_info); + &pipe_ctx->stream->audio_info); } status = apply_single_controller_ctx_to_hw( @@ -1862,13 +1862,13 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) default_adjust.out_color_space = COLOR_SPACE_SRGB; else default_adjust.out_color_space = - pipe_ctx->stream->public.output_color_space; + pipe_ctx->stream->output_color_space; default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; default_adjust.surface_pixel_format = pipe_ctx->scl_data.format; /* display color depth */ default_adjust.color_depth = - pipe_ctx->stream->public.timing.display_color_depth; + pipe_ctx->stream->timing.display_color_depth; /* Lb color depth */ default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth; @@ -1932,35 +1932,35 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; - if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; adjust.temperature_matrix[0] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[0]; + gamut_remap_matrix.matrix[0]; adjust.temperature_matrix[1] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[1]; + gamut_remap_matrix.matrix[1]; adjust.temperature_matrix[2] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[2]; + gamut_remap_matrix.matrix[2]; adjust.temperature_matrix[3] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[4]; + gamut_remap_matrix.matrix[4]; adjust.temperature_matrix[4] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[5]; + gamut_remap_matrix.matrix[5]; adjust.temperature_matrix[5] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[6]; + gamut_remap_matrix.matrix[6]; adjust.temperature_matrix[6] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[8]; + gamut_remap_matrix.matrix[8]; adjust.temperature_matrix[7] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[9]; + gamut_remap_matrix.matrix[9]; adjust.temperature_matrix[8] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[10]; + gamut_remap_matrix.matrix[10]; } pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); @@ -1987,48 +1987,48 @@ static void set_plane_config( dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); set_default_colors(pipe_ctx); - if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { tbl_entry.color_space = - pipe_ctx->stream->public.output_color_space; + pipe_ctx->stream->output_color_space; for (i = 0; i < 12; i++) tbl_entry.regval[i] = - pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + pipe_ctx->stream->csc_color_matrix.matrix[i]; pipe_ctx->opp->funcs->opp_set_csc_adjustment (pipe_ctx->opp, &tbl_entry); } - if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; adjust.temperature_matrix[0] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[0]; + gamut_remap_matrix.matrix[0]; adjust.temperature_matrix[1] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[1]; + gamut_remap_matrix.matrix[1]; adjust.temperature_matrix[2] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[2]; + gamut_remap_matrix.matrix[2]; adjust.temperature_matrix[3] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[4]; + gamut_remap_matrix.matrix[4]; adjust.temperature_matrix[4] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[5]; + gamut_remap_matrix.matrix[5]; adjust.temperature_matrix[5] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[6]; + gamut_remap_matrix.matrix[6]; adjust.temperature_matrix[6] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[8]; + gamut_remap_matrix.matrix[8]; adjust.temperature_matrix[7] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[9]; + gamut_remap_matrix.matrix[9]; adjust.temperature_matrix[8] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[10]; + gamut_remap_matrix.matrix[10]; } pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); @@ -2260,7 +2260,7 @@ void dce110_fill_display_configs( for (j = 0; j < context->stream_count; j++) { int k; - const struct core_stream *stream = context->streams[j]; + const struct dc_stream *stream = context->streams[j]; struct dm_pp_single_disp_config *cfg = &pp_display_cfg->disp_configs[num_cfgs]; const struct pipe_ctx *pipe_ctx = NULL; @@ -2276,8 +2276,8 @@ void dce110_fill_display_configs( num_cfgs++; cfg->signal = pipe_ctx->stream->signal; cfg->pipe_idx = pipe_ctx->pipe_idx; - cfg->src_height = stream->public.src.height; - cfg->src_width = stream->public.src.width; + cfg->src_height = stream->src.height; + cfg->src_width = stream->src.width; cfg->ddi_channel_mapping = stream->sink->link->ddi_channel_mapping.raw; cfg->transmitter = @@ -2290,10 +2290,10 @@ void dce110_fill_display_configs( stream->sink->link->cur_link_settings.link_spread; cfg->sym_clock = stream->phy_pix_clk; /* Round v_refresh*/ - cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000; - cfg->v_refresh /= stream->public.timing.h_total; - cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2) - / stream->public.timing.v_total; + cfg->v_refresh = stream->timing.pix_clk_khz * 1000; + cfg->v_refresh /= stream->timing.h_total; + cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) + / stream->timing.v_total; } pp_display_cfg->display_count = num_cfgs; @@ -2305,7 +2305,7 @@ uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) uint32_t min_vertical_blank_time = -1; for (j = 0; j < context->stream_count; j++) { - const struct dc_stream *stream = &context->streams[j]->public; + struct dc_stream *stream = context->streams[j]; uint32_t vertical_blank_in_pixels = 0; uint32_t vertical_blank_time = 0; @@ -2388,7 +2388,7 @@ static void pplib_apply_display_requirements( /* TODO: is this still applicable?*/ if (pp_display_cfg->display_count == 1) { const struct dc_crtc_timing *timing = - &context->streams[0]->public.timing; + &context->streams[0]->timing; pp_display_cfg->crtc_index = pp_display_cfg->disp_configs[0].pipe_idx; @@ -2441,48 +2441,48 @@ static void dce110_program_front_end_for_pipe( dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true); set_default_colors(pipe_ctx); - if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { tbl_entry.color_space = - pipe_ctx->stream->public.output_color_space; + pipe_ctx->stream->output_color_space; for (i = 0; i < 12; i++) tbl_entry.regval[i] = - pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + pipe_ctx->stream->csc_color_matrix.matrix[i]; pipe_ctx->opp->funcs->opp_set_csc_adjustment (pipe_ctx->opp, &tbl_entry); } - if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; adjust.temperature_matrix[0] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[0]; + gamut_remap_matrix.matrix[0]; adjust.temperature_matrix[1] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[1]; + gamut_remap_matrix.matrix[1]; adjust.temperature_matrix[2] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[2]; + gamut_remap_matrix.matrix[2]; adjust.temperature_matrix[3] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[4]; + gamut_remap_matrix.matrix[4]; adjust.temperature_matrix[4] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[5]; + gamut_remap_matrix.matrix[5]; adjust.temperature_matrix[5] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[6]; + gamut_remap_matrix.matrix[6]; adjust.temperature_matrix[6] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[8]; + gamut_remap_matrix.matrix[8]; adjust.temperature_matrix[7] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[9]; + gamut_remap_matrix.matrix[9]; adjust.temperature_matrix[8] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[10]; + gamut_remap_matrix.matrix[10]; } pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index c773351e93af..cc25c4b6c06f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -718,13 +718,13 @@ static void get_pixel_clock_parameters( const struct pipe_ctx *pipe_ctx, struct pixel_clk_params *pixel_clk_params) { - const struct core_stream *stream = pipe_ctx->stream; + const struct dc_stream *stream = pipe_ctx->stream; /*TODO: is this halved for YCbCr 420? in that case we might want to move * the pixel clock normalization for hdmi up to here instead of doing it * in pll_adjust_pix_clk */ - pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz; pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; @@ -733,15 +733,15 @@ static void get_pixel_clock_parameters( LINK_RATE_REF_FREQ_IN_KHZ; pixel_clk_params->flags.ENABLE_SS = 0; pixel_clk_params->color_depth = - stream->public.timing.display_color_depth; + stream->timing.display_color_depth; pixel_clk_params->flags.DISPLAY_BLANKED = 1; - pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->public.timing.pixel_encoding == + pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420); - pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { + pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { pixel_clk_params->color_depth = COLOR_DEPTH_888; } - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { pixel_clk_params->requested_pix_clk = pixel_clk_params->requested_pix_clk / 2; } } @@ -755,7 +755,7 @@ enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) &pipe_ctx->pll_settings); resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); - pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; return DC_OK; } @@ -780,7 +780,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -837,9 +837,9 @@ bool dce110_validate_bandwidth( dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION, "%s: %dx%d@%d Bandwidth validation failed!\n", __func__, - context->streams[0]->public.timing.h_addressable, - context->streams[0]->public.timing.v_addressable, - context->streams[0]->public.timing.pix_clk_khz); + context->streams[0]->timing.h_addressable, + context->streams[0]->timing.v_addressable, + context->streams[0]->timing.pix_clk_khz); if (memcmp(&dc->current_context->bw.dce, &context->bw.dce, sizeof(context->bw.dce))) { @@ -942,8 +942,8 @@ enum dc_status dce110_validate_with_context( return DC_FAIL_SURFACE_VALIDATE; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -973,13 +973,13 @@ enum dc_status dce110_validate_with_context( enum dc_status dce110_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = dc_stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); @@ -1006,7 +1006,7 @@ enum dc_status dce110_validate_guaranteed( static struct pipe_ctx *dce110_acquire_underlay( struct validate_context *context, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &context->res_ctx; @@ -1041,18 +1041,18 @@ static struct pipe_ctx *dce110_acquire_underlay( */ pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, - &stream->public.timing, + &stream->timing, false); pipe_ctx->tg->funcs->enable_advanced_request( pipe_ctx->tg, true, - &stream->public.timing); + &stream->timing); pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, - stream->public.timing.h_total, - stream->public.timing.v_total, - stream->public.timing.pix_clk_khz, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pix_clk_khz, context->stream_count); color_space_to_black_color(dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 19cd99923b24..9589208ea0c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -698,7 +698,7 @@ static void destruct(struct dce110_resource_pool *pool) static struct clock_source *find_matching_pll( struct resource_context *res_ctx, const struct resource_pool *pool, - const struct core_stream *const stream) + const struct dc_stream *const stream) { switch (stream->sink->link->link_enc->transmitter) { case TRANSMITTER_UNIPHY_A: @@ -729,7 +729,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -843,7 +843,7 @@ enum dc_status resource_map_phy_clock_resources( /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -916,8 +916,8 @@ enum dc_status dce112_validate_with_context( return DC_FAIL_SURFACE_VALIDATE; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -947,13 +947,13 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index c6c0bbac5335..cb2c69fb05a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -44,7 +44,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context); bool dce112_validate_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 0123006e5360..2fde43c91ad0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -676,7 +676,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -750,8 +750,8 @@ enum dc_status dce80_validate_with_context( return DC_FAIL_SURFACE_VALIDATE; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -780,13 +780,13 @@ enum dc_status dce80_validate_with_context( enum dc_status dce80_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = dc_stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e738387d8ba3..1531b52e61c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -684,12 +684,12 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( struct validate_context *context, struct core_dc *dc) { - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; enum dc_color_space color_space; struct tg_color black_color = {0}; - bool enableStereo = stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? + bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? false:true; - bool rightEyePolarity = stream->public.timing.flags.RIGHT_EYE_3D_POLARITY; + bool rightEyePolarity = stream->timing.flags.RIGHT_EYE_3D_POLARITY; /* by upper caller loop, pipe0 is parent pipe and be called first. @@ -722,7 +722,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( pipe_ctx->tg->funcs->program_timing( pipe_ctx->tg, - &stream->public.timing, + &stream->timing, true); pipe_ctx->opp->funcs->opp_set_stereo_polarity( @@ -742,7 +742,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( &stream->clamping); #endif /* program otg blank color */ - color_space = stream->public.output_color_space; + color_space = stream->output_color_space; color_space_to_black_color(dc, color_space, &black_color); pipe_ctx->tg->funcs->set_blank_color( pipe_ctx->tg, @@ -1053,16 +1053,16 @@ static bool patch_address_for_sbs_tb_stereo( bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; if (sec_split && surface->address.type == PLN_ADDR_TYPE_GRPH_STEREO && - (pipe_ctx->stream->public.timing.timing_3d_format == + (pipe_ctx->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || - pipe_ctx->stream->public.timing.timing_3d_format == + pipe_ctx->stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { *addr = surface->address.grph_stereo.left_addr; surface->address.grph_stereo.left_addr = surface->address.grph_stereo.right_addr; return true; } else { - if (pipe_ctx->stream->public.view_format != VIEW_3D_FORMAT_NONE && + if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE && surface->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { surface->address.type = PLN_ADDR_TYPE_GRPH_STEREO; surface->address.grph_stereo.right_addr = @@ -1456,7 +1456,7 @@ static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct core_stream *stream) + const struct dc_stream *stream) { struct transform *xfm = pipe_ctx->xfm; @@ -1465,14 +1465,14 @@ static bool dcn10_set_output_transfer_func( xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; - if (stream->public.out_transfer_func && - stream->public.out_transfer_func->type == + if (stream->out_transfer_func && + stream->out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->public.out_transfer_func->tf == + stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); } else if (dcn10_translate_regamma_to_hw_format( - stream->public.out_transfer_func, &xfm->regamma_params)) { + stream->out_transfer_func, &xfm->regamma_params)) { xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); } else { @@ -1756,35 +1756,35 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; - if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) { + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; adjust.temperature_matrix[0] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[0]; + gamut_remap_matrix.matrix[0]; adjust.temperature_matrix[1] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[1]; + gamut_remap_matrix.matrix[1]; adjust.temperature_matrix[2] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[2]; + gamut_remap_matrix.matrix[2]; adjust.temperature_matrix[3] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[4]; + gamut_remap_matrix.matrix[4]; adjust.temperature_matrix[4] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[5]; + gamut_remap_matrix.matrix[5]; adjust.temperature_matrix[5] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[6]; + gamut_remap_matrix.matrix[6]; adjust.temperature_matrix[6] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[8]; + gamut_remap_matrix.matrix[8]; adjust.temperature_matrix[7] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[9]; + gamut_remap_matrix.matrix[9]; adjust.temperature_matrix[8] = pipe_ctx->stream-> - public.gamut_remap_matrix.matrix[10]; + gamut_remap_matrix.matrix[10]; } pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); @@ -1798,14 +1798,14 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, int i; struct out_csc_color_matrix tbl_entry; - if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { enum dc_color_space color_space = - pipe_ctx->stream->public.output_color_space; + pipe_ctx->stream->output_color_space; //uint16_t matrix[12]; for (i = 0; i < 12; i++) - tbl_entry.regval[i] = pipe_ctx->stream->public.csc_color_matrix.matrix[i]; + tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; @@ -1967,7 +1967,7 @@ static void update_dchubp_dpp( * pre-multiplied alpha. */ mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( - pipe_ctx->stream->public.output_color_space) + pipe_ctx->stream->output_color_space) && per_pixel_alpha; pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); @@ -1975,7 +1975,7 @@ static void update_dchubp_dpp( dcn10_get_surface_visual_confirm_color(pipe_ctx, &black_color); } else { color_space_to_black_color( - dc, pipe_ctx->stream->public.output_color_space, + dc, pipe_ctx->stream->output_color_space, &black_color); } pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color); @@ -1991,7 +1991,7 @@ static void update_dchubp_dpp( program_gamut_remap(pipe_ctx); /*TODO add adjustments parameters*/ - ocsc.out_color_space = pipe_ctx->stream->public.output_color_space; + ocsc.out_color_space = pipe_ctx->stream->output_color_space; pipe_ctx->xfm->funcs->opp_set_csc_default(pipe_ctx->xfm, &ocsc); mi->funcs->mem_input_program_surface_config( @@ -2346,11 +2346,11 @@ static void set_plane_config( } static void dcn10_config_stereo_parameters( - struct core_stream *stream, struct crtc_stereo_flags *flags) + struct dc_stream *stream, struct crtc_stereo_flags *flags) { - enum view_3d_format view_format = stream->public.view_format; + enum view_3d_format view_format = stream->view_format; enum dc_timing_3d_format timing_3d_format =\ - stream->public.timing.timing_3d_format; + stream->timing.timing_3d_format; bool non_stereo_timing = false; if (timing_3d_format == TIMING_3D_FORMAT_NONE || @@ -2374,7 +2374,7 @@ static void dcn10_config_stereo_parameters( flags->DISABLE_STEREO_DP_SYNC = 1; } flags->RIGHT_EYE_POLARITY =\ - stream->public.timing.flags.RIGHT_EYE_3D_POLARITY; + stream->timing.flags.RIGHT_EYE_3D_POLARITY; if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) flags->FRAME_PACKED = 1; } @@ -2385,18 +2385,18 @@ static void dcn10_config_stereo_parameters( static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) { struct crtc_stereo_flags flags = { 0 }; - struct core_stream *stream = pipe_ctx->stream; + struct dc_stream *stream = pipe_ctx->stream; dcn10_config_stereo_parameters(stream, &flags); pipe_ctx->opp->funcs->opp_set_stereo_polarity( pipe_ctx->opp, flags.PROGRAM_STEREO == 1 ? true:false, - stream->public.timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); + stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); pipe_ctx->tg->funcs->program_stereo( pipe_ctx->tg, - &stream->public.timing, + &stream->timing, &flags); return; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index b901ef9689a6..33beb0bc3ddf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -787,8 +787,8 @@ static void get_pixel_clock_parameters( const struct pipe_ctx *pipe_ctx, struct pixel_clk_params *pixel_clk_params) { - const struct core_stream *stream = pipe_ctx->stream; - pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz; + const struct dc_stream *stream = pipe_ctx->stream; + pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz; pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->controller_id = pipe_ctx->pipe_idx + 1; @@ -797,23 +797,23 @@ static void get_pixel_clock_parameters( LINK_RATE_REF_FREQ_IN_KHZ; pixel_clk_params->flags.ENABLE_SS = 0; pixel_clk_params->color_depth = - stream->public.timing.display_color_depth; + stream->timing.display_color_depth; pixel_clk_params->flags.DISPLAY_BLANKED = 1; - pixel_clk_params->pixel_encoding = stream->public.timing.pixel_encoding; + pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) pixel_clk_params->color_depth = COLOR_DEPTH_888; - if (stream->public.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) pixel_clk_params->requested_pix_clk /= 2; } -static void build_clamping_params(struct core_stream *stream) +static void build_clamping_params(struct dc_stream *stream) { stream->clamping.clamping_level = CLAMPING_FULL_RANGE; - stream->clamping.c_depth = stream->public.timing.display_color_depth; - stream->clamping.pixel_encoding = stream->public.timing.pixel_encoding; + stream->clamping.c_depth = stream->timing.display_color_depth; + stream->clamping.pixel_encoding = stream->timing.pixel_encoding; } static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) @@ -826,7 +826,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) &pipe_ctx->pix_clk_params, &pipe_ctx->pll_settings); - pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->public.timing.pixel_encoding; + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); @@ -844,7 +844,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct core_stream *stream = context->streams[i]; + struct dc_stream *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -852,7 +852,7 @@ static enum dc_status build_mapped_resource( resource_build_bit_depth_reduction_params(stream, &stream->bit_depth_params); stream->clamping.pixel_encoding = - stream->public.timing.pixel_encoding; + stream->timing.pixel_encoding; resource_build_bit_depth_reduction_params(stream, &stream->bit_depth_params); @@ -896,8 +896,8 @@ enum dc_status dcn10_validate_with_context( return result; for (i = 0; i < set_count; i++) { - context->streams[i] = DC_STREAM_TO_CORE(set[i].stream); - dc_stream_retain(&context->streams[i]->public); + context->streams[i] = set[i].stream; + dc_stream_retain(context->streams[i]); context->stream_count++; } @@ -929,13 +929,13 @@ enum dc_status dcn10_validate_with_context( enum dc_status dcn10_validate_guaranteed( const struct core_dc *dc, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - context->streams[0] = DC_STREAM_TO_CORE(dc_stream); - dc_stream_retain(&context->streams[0]->public); + context->streams[0] = dc_stream; + dc_stream_retain(context->streams[0]); context->stream_count++; result = resource_map_pool_resources(dc, context, NULL); @@ -960,7 +960,7 @@ enum dc_status dcn10_validate_guaranteed( static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( struct validate_context *context, const struct resource_pool *pool, - struct core_stream *stream) + struct dc_stream *stream) { struct resource_context *res_ctx = &context->res_ctx; struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 5a47d4c94df6..2ae5a607fb5a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -36,41 +36,18 @@ #include "mpc.h" #endif -struct core_stream; - #define MAX_CLOCK_SOURCES 7 void enable_surface_flip_reporting(struct dc_surface *dc_surface, uint32_t controller_id); -/********* core_stream ************/ #include "grph_object_id.h" #include "link_encoder.h" #include "stream_encoder.h" #include "clock_source.h" #include "audio.h" #include "hw_sequencer_types.h" -#include "opp.h" - -#define DC_STREAM_TO_CORE(dc_stream) container_of( \ - dc_stream, struct core_stream, public) - -struct core_stream { - struct dc_stream public; - - /* field internal to DC */ - struct dc_context *ctx; - struct dc_sink *sink; - /* used by DCP and FMT */ - struct bit_depth_reduction_params bit_depth_params; - struct clamping_and_pixel_encoding_params clamping; - - int phy_pix_clk; - enum signal_type signal; - - struct dc_stream_status status; -}; /************ link *****************/ struct link_init_data { @@ -85,7 +62,7 @@ struct dc_link *link_create(const struct link_init_data *init_params); void link_destroy(struct dc_link **link); enum dc_status dc_link_validate_mode_timing( - const struct core_stream *stream, + const struct dc_stream *stream, struct dc_link *link, const struct dc_crtc_timing *timing); @@ -117,7 +94,7 @@ struct resource_funcs { enum dc_status (*validate_guaranteed)( const struct core_dc *dc, - const struct dc_stream *stream, + struct dc_stream *stream, struct validate_context *context); bool (*validate_bandwidth)( @@ -127,7 +104,7 @@ struct resource_funcs { struct pipe_ctx *(*acquire_idle_pipe_for_layer)( struct validate_context *context, const struct resource_pool *pool, - struct core_stream *stream); + struct dc_stream *stream); }; struct audio_support{ @@ -178,7 +155,7 @@ struct resource_pool { struct pipe_ctx { struct dc_surface *surface; - struct core_stream *stream; + struct dc_stream *stream; struct mem_input *mi; struct input_pixel_processor *ipp; @@ -264,7 +241,7 @@ union bw_context { }; struct validate_context { - struct core_stream *streams[MAX_PIPES]; + struct dc_stream *streams[MAX_PIPES]; struct dc_stream_status stream_status[MAX_PIPES]; uint8_t stream_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index d9af028a39df..5b4185053e9c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -30,7 +30,7 @@ #define LINK_TRAINING_RETRY_DELAY 50 /* ms */ struct dc_link; -struct core_stream; +struct dc_stream; struct dc_link_settings; bool dp_hbr_verify_link_cap( @@ -50,7 +50,7 @@ bool dp_validate_mode_timing( const struct dc_crtc_timing *timing); void decide_link_settings( - struct core_stream *stream, + struct dc_stream *stream, struct dc_link_settings *link_setting); bool perform_link_training_with_retries( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 0ee738774f9f..28fb02fb677e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -17,7 +17,6 @@ struct encoder_set_dp_phy_pattern_param; struct link_mst_stream_allocation_table; struct dc_link_settings; struct link_training_settings; -struct core_stream; struct pipe_ctx; struct encoder_init_data { @@ -94,7 +93,7 @@ struct link_encoder { struct link_encoder_funcs { bool (*validate_output_with_stream)( - struct link_encoder *enc, const struct core_stream *stream); + struct link_encoder *enc, const struct dc_stream *stream); void (*hw_init)(struct link_encoder *enc); void (*setup)(struct link_encoder *enc, enum signal_type signal); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index a3eec078dead..b2f7ba2115c9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -92,7 +92,7 @@ struct hw_sequencer_funcs { bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct core_stream *stream); + const struct dc_stream *stream); void (*power_down)(struct core_dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index ed94df16a2d3..571bfae62a3c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -103,8 +103,8 @@ void resource_reference_clock_source( struct clock_source *clock_source); bool resource_are_streams_timing_synchronizable( - const struct core_stream *stream1, - const struct core_stream *stream2); + struct dc_stream *stream1, + struct dc_stream *stream2); struct clock_source *resource_find_used_clk_src_for_sharing( struct resource_context *res_ctx, @@ -116,12 +116,12 @@ struct clock_source *dc_resource_find_first_free_pll( struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, - const struct core_stream *stream); + struct dc_stream *stream); bool resource_attach_surfaces_to_context( struct dc_surface *const *surfaces, int surface_count, - const struct dc_stream *dc_stream, + struct dc_stream *dc_stream, struct validate_context *context, const struct resource_pool *pool); @@ -130,10 +130,10 @@ struct pipe_ctx *find_idle_secondary_pipe( const struct resource_pool *pool); bool resource_is_stream_unchanged( - const struct validate_context *old_context, const struct core_stream *stream); + struct validate_context *old_context, struct dc_stream *stream); bool is_stream_unchanged( - const struct core_stream *old_stream, const struct core_stream *stream); + struct dc_stream *old_stream, struct dc_stream *stream); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], @@ -164,7 +164,7 @@ bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx); -void resource_build_bit_depth_reduction_params(const struct core_stream *stream, +void resource_build_bit_depth_reduction_params(struct dc_stream *stream, struct bit_depth_reduction_params *fmt_bit_depth); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index d312874d95b5..dd024c99fb7e 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -30,7 +30,7 @@ static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct core_stream *stream) { return true; } + const struct dc_stream *stream) { return true; } static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index a989d5de9f3c..358f8a855a59 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -111,7 +111,7 @@ struct freesync_state { }; struct freesync_entity { - const struct dc_stream *stream; + struct dc_stream *stream; struct mod_freesync_caps *caps; struct freesync_state state; struct mod_freesync_user_enable user_enable; @@ -229,7 +229,7 @@ void mod_freesync_destroy(struct mod_freesync *mod_freesync) * on the core_freesync->map and returns the corresponding index */ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, - const struct dc_stream *stream) + struct dc_stream *stream) { unsigned int index = 0; @@ -244,9 +244,8 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, } bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, struct mod_freesync_caps *caps) + struct dc_stream *stream, struct mod_freesync_caps *caps) { - struct core_stream *core_stream = NULL; struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; @@ -258,7 +257,6 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_stream = DC_STREAM_TO_CORE(stream); core_dc = DC_TO_CORE(core_freesync->dc); flag.save_per_edid = true; @@ -315,7 +313,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, if (caps->supported && nom_refresh_rate_uhz >= caps->min_refresh_in_micro_hz && nom_refresh_rate_uhz <= caps->max_refresh_in_micro_hz) - core_stream->public.ignore_msa_timing_param = 1; + stream->ignore_msa_timing_param = 1; core_freesync->num_entities++; return true; @@ -324,7 +322,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, } bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, - const struct dc_stream *stream) + struct dc_stream *stream) { int i = 0; struct core_freesync *core_freesync = NULL; @@ -346,14 +344,12 @@ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, } static void update_stream_freesync_context(struct core_freesync *core_freesync, - const struct dc_stream *stream) + struct dc_stream *stream) { unsigned int index; struct freesync_context *ctx; - struct core_stream *core_stream; - core_stream = DC_STREAM_TO_CORE(stream); - ctx = &core_stream->public.freesync_ctx; + ctx = &stream->freesync_ctx; index = map_index_from_stream(core_freesync, stream); @@ -372,19 +368,17 @@ static void update_stream_freesync_context(struct core_freesync *core_freesync, } static void update_stream(struct core_freesync *core_freesync, - const struct dc_stream *stream) + struct dc_stream *stream) { - struct core_stream *core_stream = DC_STREAM_TO_CORE(stream); - unsigned int index = map_index_from_stream(core_freesync, stream); if (core_freesync->map[index].caps->supported) { - core_stream->public.ignore_msa_timing_param = 1; + stream->ignore_msa_timing_param = 1; update_stream_freesync_context(core_freesync, stream); } } static void calc_freesync_range(struct core_freesync *core_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct freesync_state *state, unsigned int min_refresh_in_uhz, unsigned int max_refresh_in_uhz) @@ -458,7 +452,7 @@ static void calc_freesync_range(struct core_freesync *core_freesync, min_frame_duration_in_ns) / 2000; } -static void calc_v_total_from_duration(const struct dc_stream *stream, +static void calc_v_total_from_duration(struct dc_stream *stream, unsigned int duration_in_ns, int *v_total_nominal) { *v_total_nominal = div64_u64(div64_u64(((unsigned long long)( @@ -467,7 +461,7 @@ static void calc_v_total_from_duration(const struct dc_stream *stream, } static void calc_v_total_for_static_ramp(struct core_freesync *core_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int index, int *v_total) { unsigned int frame_duration = 0; @@ -563,7 +557,7 @@ static void reset_freesync_state_variables(struct freesync_state* state) * Sets freesync mode on a stream depending on current freesync state. */ static bool set_freesync_on_streams(struct core_freesync *core_freesync, - const struct dc_stream **streams, int num_streams) + struct dc_stream **streams, int num_streams) { int v_total_nominal = 0, v_total_min = 0, v_total_max = 0; unsigned int stream_idx, map_index = 0; @@ -735,7 +729,7 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, } void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams) + struct dc_stream **streams, int num_streams) { unsigned int index, v_total, inserted_frame_v_total = 0; unsigned int min_frame_duration_in_ns, vmax, vmin = 0; @@ -845,7 +839,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, } void mod_freesync_update_state(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, struct mod_freesync_params *freesync_params) { bool freesync_program_required = false; @@ -935,7 +929,7 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, bool mod_freesync_get_state(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct mod_freesync_params *freesync_params) { unsigned int index = 0; @@ -971,7 +965,7 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, } bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, struct mod_freesync_user_enable *user_enable) { unsigned int stream_index, map_index; @@ -1023,7 +1017,7 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, } bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct mod_freesync_user_enable *user_enable) { unsigned int index = 0; @@ -1041,7 +1035,7 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, } bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, bool *is_ramp_active) { unsigned int index = 0; @@ -1060,7 +1054,7 @@ bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, } bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, - const struct dc_stream *streams, + struct dc_stream *streams, unsigned int min_refresh, unsigned int max_refresh, struct mod_freesync_caps *caps) @@ -1113,7 +1107,7 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, } bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *min_refresh, unsigned int *max_refresh) { @@ -1135,7 +1129,7 @@ bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, } bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *vmin, unsigned int *vmax) { @@ -1157,7 +1151,7 @@ bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, } bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *nom_v_pos, unsigned int *v_pos) { @@ -1185,7 +1179,7 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, } void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams) + struct dc_stream **streams, int num_streams) { unsigned int stream_index, map_index; struct freesync_state *state; @@ -1310,7 +1304,7 @@ static void update_timestamps(struct core_freesync *core_freesync, } static void apply_below_the_range(struct core_freesync *core_freesync, - const struct dc_stream *stream, unsigned int map_index, + struct dc_stream *stream, unsigned int map_index, unsigned int last_render_time_in_us) { unsigned int inserted_frame_duration_in_us = 0; @@ -1409,7 +1403,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync, } static void apply_fixed_refresh(struct core_freesync *core_freesync, - const struct dc_stream *stream, unsigned int map_index) + struct dc_stream *stream, unsigned int map_index) { unsigned int vmin = 0, vmax = 0; struct freesync_state *state = &core_freesync->map[map_index].state; @@ -1440,7 +1434,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, } void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, unsigned int curr_time_stamp_in_us) { unsigned int stream_index, map_index, last_render_time_in_us = 0; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 53c428b97902..2b9d45100bdd 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -101,67 +101,67 @@ struct mod_freesync_params { * Add stream to be tracked by module */ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, struct mod_freesync_caps *caps); + struct dc_stream *stream, struct mod_freesync_caps *caps); /* * Remove stream to be tracked by module */ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, - const struct dc_stream *stream); + struct dc_stream *stream); /* * Update the freesync state flags for each display and program * freesync accordingly */ void mod_freesync_update_state(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, struct mod_freesync_params *freesync_params); bool mod_freesync_get_state(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct mod_freesync_params *freesync_params); bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, struct mod_freesync_user_enable *user_enable); bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, struct mod_freesync_user_enable *user_enable); bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, bool *is_ramp_active); bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, - const struct dc_stream *streams, + struct dc_stream *streams, unsigned int min_refresh, unsigned int max_refresh, struct mod_freesync_caps *caps); bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *min_refresh, unsigned int *max_refresh); bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *vmin, unsigned int *vmax); bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, - const struct dc_stream *stream, + struct dc_stream *stream, unsigned int *nom_v_pos, unsigned int *v_pos); void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams); + struct dc_stream **streams, int num_streams); void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams); + struct dc_stream **streams, int num_streams); void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, - const struct dc_stream **streams, int num_streams, + struct dc_stream **streams, int num_streams, unsigned int curr_time_stamp); #endif -- GitLab From a989ab08a7e3ee4675ea56b5dcfd0f2966aa91db Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Wed, 26 Jul 2017 16:13:48 -0400 Subject: [PATCH 0697/2898] drm/amd/display: Roll stream into dc_stream Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_stream.c | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 46ad1bc12f63..a77e1e80d7c2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -30,17 +30,6 @@ #include "ipp.h" #include "timing_generator.h" -/******************************************************************************* - * Private definitions - ******************************************************************************/ - -struct stream { - struct dc_stream protected; - int ref_count; -}; - -#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected) - /******************************************************************************* * Private functions ******************************************************************************/ @@ -105,24 +94,22 @@ static void destruct(struct dc_stream *stream) } } -void dc_stream_retain(struct dc_stream *dc_stream) +void dc_stream_retain(struct dc_stream *stream) { - struct stream *stream = DC_STREAM_TO_STREAM(dc_stream); ASSERT(stream->ref_count > 0); stream->ref_count++; } -void dc_stream_release(struct dc_stream *public) +void dc_stream_release(struct dc_stream *stream) { - struct stream *stream = DC_STREAM_TO_STREAM(public); - if (public != NULL) { + if (stream != NULL) { ASSERT(stream->ref_count > 0); stream->ref_count--; if (stream->ref_count == 0) { - destruct(public); + destruct(stream); dm_free(stream); } } @@ -131,22 +118,22 @@ void dc_stream_release(struct dc_stream *public) struct dc_stream *dc_create_stream_for_sink( struct dc_sink *sink) { - struct stream *stream; + struct dc_stream *stream; if (sink == NULL) goto alloc_fail; - stream = dm_alloc(sizeof(struct stream)); + stream = dm_alloc(sizeof(struct dc_stream)); if (NULL == stream) goto alloc_fail; - if (false == construct(&stream->protected, sink)) + if (false == construct(stream, sink)) goto construct_fail; stream->ref_count++; - return &stream->protected; + return stream; construct_fail: dm_free(stream); -- GitLab From 4d6356b0cc264686597aac2d04886cbfd8607f09 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 26 Jul 2017 16:15:26 -0400 Subject: [PATCH 0698/2898] drm/amd/display: reduce 40s time out to 1s in disable crtc Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 0ef5d8f0625c..f4dce2806ae1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -429,7 +429,7 @@ static bool tgn10_disable_crtc(struct timing_generator *tg) /* CRTC disabled, so disable clock. */ REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, - 2000, 20000); + 2000, 500); return true; } -- GitLab From 2f3bfb2794e1aed018e344469f9c371f36f12867 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 26 Jul 2017 14:42:38 -0400 Subject: [PATCH 0699/2898] drm/amd/display: safeguard compressor api Only call compressor api if it's available. Signed-off-by: Roman Li Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 15f6eeef343d..d45773087644 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1185,7 +1185,8 @@ static void power_down_all_hw_blocks(struct core_dc *dc) power_down_clock_sources(dc); #ifdef ENABLE_FBC - dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif } @@ -1658,7 +1659,8 @@ enum dc_status dce110_apply_ctx_to_hw( set_safe_displaymarks(&context->res_ctx, dc->res_pool); #ifdef ENABLE_FBC - dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif /*TODO: when pplib works*/ apply_min_clocks(dc, context, &clocks_state, true); @@ -2246,7 +2248,8 @@ static void init_hw(struct core_dc *dc) abm->funcs->abm_init(abm); } #ifdef ENABLE_FBC - dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); #endif } -- GitLab From 54e8695ef14acc04e9aa99957249f520cf52e826 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 26 Jul 2017 16:54:39 -0400 Subject: [PATCH 0700/2898] drm/amd/display: collapse dce11 reset_hw_ctx_wrap into 1 function Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 47 ++++++++----------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d45773087644..6afe572cfb06 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1345,28 +1345,6 @@ static void switch_dp_clock_sources( * Public functions ******************************************************************************/ -static void reset_single_pipe_hw_ctx( - const struct core_dc *dc, - struct pipe_ctx *pipe_ctx, - struct validate_context *context) -{ - core_link_disable_stream(pipe_ctx); - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); - if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) { - dm_error("DC: failed to blank crtc!\n"); - BREAK_TO_DEBUGGER(); - } - pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); - pipe_ctx->mi->funcs->free_mem_input( - pipe_ctx->mi, context->stream_count); - resource_unreference_clock_source(&context->res_ctx, dc->res_pool, - &pipe_ctx->clock_source); - - dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx->pipe_idx); - - pipe_ctx->stream = NULL; -} - static void set_drr(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax) { @@ -1580,7 +1558,7 @@ static enum dc_status apply_ctx_to_hw_fpga( return DC_OK; } -static void reset_hw_ctx_wrap( +static void dce110_reset_hw_ctx_wrap( struct core_dc *dc, struct validate_context *context) { @@ -1603,9 +1581,24 @@ static void reset_hw_ctx_wrap( continue; if (!pipe_ctx->stream || - pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - reset_single_pipe_hw_ctx( - dc, pipe_ctx_old, dc->current_context); + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + core_link_disable_stream(pipe_ctx_old); + pipe_ctx_old->tg->funcs->set_blank(pipe_ctx_old->tg, true); + if (!hwss_wait_for_blank_complete(pipe_ctx_old->tg)) { + dm_error("DC: failed to blank crtc!\n"); + BREAK_TO_DEBUGGER(); + } + pipe_ctx_old->tg->funcs->disable_crtc(pipe_ctx_old->tg); + pipe_ctx_old->mi->funcs->free_mem_input( + pipe_ctx_old->mi, dc->current_context->stream_count); + resource_unreference_clock_source( + &dc->current_context->res_ctx, dc->res_pool, + &pipe_ctx_old->clock_source); + + dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); + + pipe_ctx_old->stream = NULL; + } } } @@ -2619,7 +2612,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_drr = set_drr, .get_position = get_position, .set_static_screen_control = set_static_screen_control, - .reset_hw_ctx_wrap = reset_hw_ctx_wrap, + .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap, .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, .setup_stereo = NULL, .set_avmute = dce110_set_avmute, -- GitLab From cc408d726c20f32e4fdd688f870dd2b17960d4a2 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 21 Jul 2017 17:46:50 -0400 Subject: [PATCH 0701/2898] drm/amd/display: mpc block redesign Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 - .../gpu/drm/amd/display/dc/core/dc_resource.c | 5 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 146 +++++------ .../amd/display/dc/dcn10/dcn10_mem_input.c | 8 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 246 ++++++++++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 82 +++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 3 + .../drm/amd/display/dc/dcn10/dcn10_resource.c | 74 +++--- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 +- .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 26 +- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 7 + 12 files changed, 339 insertions(+), 267 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index ef10a8b49379..49b75765d900 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -547,11 +547,9 @@ static void split_stream_across_pipes( *secondary_pipe = *primary_pipe; secondary_pipe->pipe_idx = pipe_idx; - secondary_pipe->mpcc = pool->mpcc[secondary_pipe->pipe_idx]; secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->xfm = pool->transforms[secondary_pipe->pipe_idx]; - secondary_pipe->opp = pool->opps[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ddbd3de63a8d..4068d53137f5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1017,7 +1017,6 @@ static int acquire_first_split_pipe( pipe_ctx->xfm = pool->transforms[i]; pipe_ctx->opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; - pipe_ctx->mpcc = pool->mpcc[i]; pipe_ctx->pipe_idx = i; pipe_ctx->stream = stream; @@ -1096,6 +1095,7 @@ bool resource_attach_surfaces_to_context( if (tail_pipe) { free_pipe->tg = tail_pipe->tg; + free_pipe->opp = tail_pipe->opp; free_pipe->stream_enc = tail_pipe->stream_enc; free_pipe->audio = tail_pipe->audio; free_pipe->clock_source = tail_pipe->clock_source; @@ -1241,9 +1241,6 @@ static int acquire_first_free_pipe( if (!res_ctx->pipe_ctx[i].stream) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - pipe_ctx->mpcc = pool->mpcc[i]; -#endif pipe_ctx->tg = pool->timing_generators[i]; pipe_ctx->mi = pool->mis[i]; pipe_ctx->ipp = pool->ipps[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 1531b52e61c2..2299bdaca376 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -636,15 +636,10 @@ static void dcn10_init_hw(struct core_dc *dc) for (i = 0; i < dc->res_pool->pipe_count; i++) { struct transform *xfm = dc->res_pool->transforms[i]; struct timing_generator *tg = dc->res_pool->timing_generators[i]; - struct mpcc *mpcc = dc->res_pool->mpcc[i]; - struct mpcc_cfg mpcc_cfg; xfm->funcs->transform_reset(xfm); - mpcc_cfg.opp_id = 0xf; - mpcc_cfg.top_dpp_id = 0xf; - mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = true; - mpcc->funcs->set(mpcc, &mpcc_cfg); + dc->res_pool->mpc->funcs->remove( + dc->res_pool->mpc, dc->res_pool->opps[i], i); /* Blank controller using driver code instead of * command table. @@ -819,45 +814,35 @@ static void reset_back_end_for_pipe( static void plane_atomic_disconnect(struct core_dc *dc, int fe_idx) { - struct mpcc_cfg mpcc_cfg; struct mem_input *mi = dc->res_pool->mis[fe_idx]; - struct transform *xfm = dc->res_pool->transforms[fe_idx]; - struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; - struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - unsigned int opp_id = mpcc->opp_id; - int opp_id_cached = mpcc->opp_id; + struct mpc *mpc = dc->res_pool->mpc; + int opp_id, z_idx; + int mpcc_id = -1; + + /* look at tree rather than mi here to know if we already reset */ + for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) { + struct output_pixel_processor *opp = dc->res_pool->opps[opp_id]; + for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) { + if (opp->mpc_tree.dpp[z_idx] == fe_idx) { + mpcc_id = opp->mpc_tree.mpcc[z_idx]; + break; + } + } + if (mpcc_id != -1) + break; + } /*Already reset*/ - if (opp_id == 0xf) + if (opp_id == dc->res_pool->pipe_count) return; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mi->funcs->dcc_control(mi, false, false); - if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mpcc_cfg.opp_id = 0xf; - mpcc_cfg.top_dpp_id = 0xf; - mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = tg->inst == mpcc->inst; - mpcc->funcs->set(mpcc, &mpcc_cfg); - - /* - * Hack to preserve old opp_id for plane_atomic_disable - * to find the correct otg - */ - mpcc->opp_id = opp_id_cached; - - /* todo:call remove pipe from tree */ - /* flag mpcc idle pending */ - - /*dm_logger_write(dc->ctx->logger, LOG_ERROR, - "[debug_mpo: plane_atomic_disconnect pending on mpcc %d]\n", - fe_idx);*/ - xfm->funcs->transform_reset(xfm); + mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx); } /* disable HW used by plane. @@ -867,20 +852,21 @@ static void plane_atomic_disable(struct core_dc *dc, { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = dc->res_pool->mis[fe_idx]; - struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; - struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - unsigned int opp_id = mpcc->opp_id; + struct mpc *mpc = dc->res_pool->mpc; - if (opp_id == 0xf) + if (mi->opp_id == 0xf) return; - mpcc->funcs->wait_for_idle(mpcc); - dc->res_pool->opps[opp_id]->mpcc_disconnect_pending[mpcc->inst] = false; + mpc->funcs->wait_for_idle(mpc, mi->mpcc_id); + dc->res_pool->opps[mi->opp_id]->mpcc_disconnect_pending[mi->mpcc_id] = false; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: atomic disable finished on mpcc %d]\n", fe_idx);*/ mi->funcs->set_blank(mi, true); + /*todo: unhack this*/ + mi->opp_id = 0xf; + mi->mpcc_id = 0xf; if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -890,12 +876,10 @@ static void plane_atomic_disable(struct core_dc *dc, REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - if (tg->inst == mpcc->inst) - REG_UPDATE(OPP_PIPE_CONTROL[opp_id], + if (dc->res_pool->opps[mi->opp_id]->mpc_tree.num_pipes == 0) + REG_UPDATE(OPP_PIPE_CONTROL[mi->opp_id], OPP_PIPE_CLOCK_EN, 0); - mpcc->opp_id = 0xf; - if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } @@ -907,11 +891,13 @@ static void plane_atomic_disable(struct core_dc *dc, static void plane_atomic_power_down(struct core_dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; + struct transform *xfm = dc->res_pool->transforms[fe_idx]; REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); + xfm->funcs->transform_reset(xfm); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, @@ -927,14 +913,14 @@ static void reset_front_end( int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx]; - struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id]; - unsigned int opp_id = mpcc->opp_id; + struct timing_generator *tg; + int opp_id = dc->res_pool->mis[fe_idx]->opp_id; /*Already reset*/ if (opp_id == 0xf) return; + tg = dc->res_pool->timing_generators[opp_id]; tg->funcs->lock(tg); plane_atomic_disconnect(dc, fe_idx); @@ -943,7 +929,7 @@ static void reset_front_end( tg->funcs->unlock(tg); if (dc->public.debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + verify_allow_pstate_change_high(hws); if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], @@ -959,6 +945,7 @@ static void reset_front_end( static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; + struct transform *xfm = dc->res_pool->transforms[fe_idx]; reset_front_end(dc, fe_idx); @@ -966,6 +953,7 @@ static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); + xfm->funcs->transform_reset(xfm); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DC, @@ -1910,8 +1898,8 @@ static void update_dchubp_dpp( struct dc_surface *surface = pipe_ctx->surface; union plane_size size = surface->plane_size; struct default_adjustment ocsc = {0}; - struct tg_color black_color = {0}; - struct mpcc_cfg mpcc_cfg; + struct mpcc_cfg mpcc_cfg = {0}; + struct pipe_ctx *top_pipe; bool per_pixel_alpha = surface->per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ @@ -1954,14 +1942,17 @@ static void update_dchubp_dpp( 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); - pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; - mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx; - if (pipe_ctx->bottom_pipe) - mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst; + mpcc_cfg.mi = mi; + mpcc_cfg.opp = pipe_ctx->opp; + for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) + mpcc_cfg.z_index++; + if (dc->public.debug.surface_visual_confirm) + dcn10_get_surface_visual_confirm_color( + pipe_ctx, &mpcc_cfg.black_color); else - mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.opp_id = pipe_ctx->tg->inst; - mpcc_cfg.top_of_tree = pipe_ctx->pipe_idx == pipe_ctx->tg->inst; + color_space_to_black_color( + dc, pipe_ctx->stream->output_color_space, + &mpcc_cfg.black_color); mpcc_cfg.per_pixel_alpha = per_pixel_alpha; /* DCN1.0 has output CM before MPC which seems to screw with * pre-multiplied alpha. @@ -1969,17 +1960,9 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->output_color_space) && per_pixel_alpha; - pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); - - if (dc->public.debug.surface_visual_confirm) { - dcn10_get_surface_visual_confirm_color(pipe_ctx, &black_color); - } else { - color_space_to_black_color( - dc, pipe_ctx->stream->output_color_space, - &black_color); - } - pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color); + dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ pipe_ctx->xfm->funcs->transform_set_scaler( @@ -2112,7 +2095,7 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->surface && !old_pipe_ctx->surface) { - if (pipe_ctx->mpcc->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { + if (pipe_ctx->mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need @@ -2125,9 +2108,6 @@ static void dcn10_apply_ctx_for_surface( if ((!pipe_ctx->surface && old_pipe_ctx->surface) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { - struct mpcc_cfg mpcc_cfg; - int opp_id_cached = old_pipe_ctx->mpcc->opp_id; - if (old_pipe_ctx->tg->inst != be_idx) continue; @@ -2137,12 +2117,11 @@ static void dcn10_apply_ctx_for_surface( } /* reset mpc */ - mpcc_cfg.opp_id = 0xf; - mpcc_cfg.top_dpp_id = 0xf; - mpcc_cfg.bot_mpcc_id = 0xf; - mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe; - old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg); - old_pipe_ctx->top_pipe->opp->mpcc_disconnect_pending[old_pipe_ctx->mpcc->inst] = true; + dc->res_pool->mpc->funcs->remove( + dc->res_pool->mpc, + old_pipe_ctx->opp, + old_pipe_ctx->pipe_idx); + old_pipe_ctx->opp->mpcc_disconnect_pending[old_pipe_ctx->mi->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2151,13 +2130,6 @@ static void dcn10_apply_ctx_for_surface( if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - /* - * the mpcc is the only thing that keeps track of the mpcc - * mapping for reset front end right now. Might need some - * rework. - */ - old_pipe_ctx->mpcc->opp_id = opp_id_cached; - old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; old_pipe_ctx->surface = NULL; @@ -2466,12 +2438,12 @@ static void dcn10_wait_for_mpcc_disconnect( { int i; - if (!pipe_ctx->opp || !pipe_ctx->mpcc) + if (!pipe_ctx->opp) return; for (i = 0; i < MAX_PIPES; i++) { if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { - pipe_ctx->mpcc->funcs->wait_for_idle(res_pool->mpcc[i]); + res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, i); pipe_ctx->opp->mpcc_disconnect_pending[i] = false; res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); /*dm_logger_write(dc->ctx->logger, LOG_ERROR, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 6f01db6a51dd..76879f5d7907 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -47,10 +47,14 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) HUBP_BLANK_EN, blank_en, HUBP_TTU_DISABLE, blank_en); - if (blank) + if (blank) { REG_WAIT(DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1, 1, 200); + /*todo: unhack this + mem_input->mpcc_id = 0xf; + mem_input->opp_id = 0xf;*/ + } } static void min10_vready_workaround(struct mem_input *mem_input, @@ -871,6 +875,8 @@ bool dcn10_mem_input_construct( mi->mi_shift = mi_shift; mi->mi_mask = mi_mask; mi->base.inst = inst; + mi->base.opp_id = 0xf; + mi->base.mpcc_id = 0xf; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 9af288167e2e..246b60a16521 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -26,16 +26,17 @@ #include "reg_helper.h" #include "dcn10_mpc.h" #include "dc.h" +#include "mem_input.h" #define REG(reg)\ - mpcc10->mpcc_regs->reg + mpc10->mpc_regs->reg #define CTX \ - mpcc10->base.ctx + mpc10->base.ctx #undef FN #define FN(reg_name, field_name) \ - mpcc10->mpcc_shift->field_name, mpcc10->mpcc_mask->field_name + mpc10->mpc_shift->field_name, mpc10->mpc_mask->field_name #define MODE_TOP_ONLY 1 #define MODE_BLEND 3 @@ -43,11 +44,11 @@ #define BLND_GLOBAL_ALPHA 2 -void dcn10_mpcc_set_bg_color( - struct mpcc *mpcc, - struct tg_color *bg_color) +static void mpc10_set_bg_color( + struct dcn10_mpc *mpc10, + struct tg_color *bg_color, + int id) { - struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); /* mpc color is 12 bit. tg_color is 10 bit */ /* todo: might want to use 16 bit to represent color and have each * hw block translate to correct color depth. @@ -56,113 +57,210 @@ void dcn10_mpcc_set_bg_color( uint32_t bg_g_y = bg_color->color_g_y << 2; uint32_t bg_b_cb = bg_color->color_b_cb << 2; - REG_SET(MPCC_BG_R_CR, 0, + REG_SET(MPCC_BG_R_CR[id], 0, MPCC_BG_R_CR, bg_r_cr); - REG_SET(MPCC_BG_G_Y, 0, + REG_SET(MPCC_BG_G_Y[id], 0, MPCC_BG_G_Y, bg_g_y); - REG_SET(MPCC_BG_B_CB, 0, + REG_SET(MPCC_BG_B_CB[id], 0, MPCC_BG_B_CB, bg_b_cb); } -static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) +static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) { - ASSERT(mpcc10->base.opp_id == 0xf || opp_id == mpcc10->base.opp_id); - mpcc10->base.opp_id = opp_id; - REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << id)); + REG_WAIT(MPCC_STATUS[id], + MPCC_BUSY, 0, + 1000, 1000); } -static void reset_output_mux(struct dcn10_mpcc *mpcc10) +static int mpc10_get_idle_mpcc_id(struct dcn10_mpc *mpc10) { - REG_SET(MUX[mpcc10->base.opp_id], 0, MPC_OUT_MUX, 0xf); - mpcc10->base.opp_id = 0xf; + int i; + int last_free_mpcc_id = -1; + + for (i = 0; i < mpc10->num_mpcc; i++) { + uint32_t is_idle = 0; + + if (mpc10->mpcc_in_use_mask & 1 << i) + continue; + + last_free_mpcc_id = i; + REG_GET(MPCC_STATUS[i], MPCC_IDLE, &is_idle); + if (is_idle) + return i; + } + + /* This assert should never trigger, we have mpcc leak if it does */ + ASSERT(last_free_mpcc_id != -1); + + mpc10_assert_idle_mpcc(&mpc10->base, last_free_mpcc_id); + return last_free_mpcc_id; } -static void assert_mpcc_idle_before_connect(struct dcn10_mpcc *mpcc10) +static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int id) { - unsigned int top_sel; - unsigned int mpcc_busy, mpcc_idle, mpcc_status; + unsigned int top_sel, mpc_busy, mpc_idle; - REG_GET(MPCC_TOP_SEL, + REG_GET(MPCC_TOP_SEL[id], MPCC_TOP_SEL, &top_sel); if (top_sel == 0xf) { - mpcc_status = REG_GET_2(MPCC_STATUS, - MPCC_BUSY, &mpcc_busy, - MPCC_IDLE, &mpcc_idle); + REG_GET_2(MPCC_STATUS[id], + MPCC_BUSY, &mpc_busy, + MPCC_IDLE, &mpc_idle); + + ASSERT(mpc_busy == 0); + ASSERT(mpc_idle == 1); + } +} + +static void mpc10_mpcc_remove( + struct mpc *mpc, + struct output_pixel_processor *opp, + int dpp_id) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + + for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) + if (opp->mpc_tree.dpp[z_idx] == dpp_id) + break; + if (z_idx == opp->mpc_tree.num_pipes) { + ASSERT(0); + return; + } + mpcc_id = opp->mpc_tree.mpcc[z_idx]; + + REG_SET(MPCC_OPP_ID[mpcc_id], 0, + MPCC_OPP_ID, 0xf); + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, + MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, 0xf); - ASSERT(mpcc_busy == 0); - ASSERT(mpcc_idle == 1); + if (z_idx > 0) { + int top_mpcc_id = opp->mpc_tree.mpcc[z_idx - 1]; + + if (z_idx + 1 < opp->mpc_tree.num_pipes) + REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + MPCC_BOT_SEL, opp->mpc_tree.mpcc[z_idx + 1]); + else { + REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + MPCC_BOT_SEL, 0xf); + REG_UPDATE(MPCC_CONTROL[top_mpcc_id], + MPCC_MODE, MODE_TOP_ONLY); + } + } else if (opp->mpc_tree.num_pipes > 1) + REG_SET(MUX[opp->inst], 0, + MPC_OUT_MUX, opp->mpc_tree.mpcc[z_idx + 1]); + else + REG_SET(MUX[opp->inst], 0, MPC_OUT_MUX, 0xf); + + mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); + opp->mpc_tree.num_pipes--; + for (; z_idx < opp->mpc_tree.num_pipes; z_idx++) { + opp->mpc_tree.dpp[z_idx] = opp->mpc_tree.dpp[z_idx + 1]; + opp->mpc_tree.mpcc[z_idx] = opp->mpc_tree.mpcc[z_idx + 1]; } + opp->mpc_tree.dpp[opp->mpc_tree.num_pipes] = 0xdeadbeef; + opp->mpc_tree.mpcc[opp->mpc_tree.num_pipes] = 0xdeadbeef; } -static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) +static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) { - struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); int alpha_blnd_mode = cfg->per_pixel_alpha ? BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; - int mpcc_mode = cfg->bot_mpcc_id != 0xf ? - MODE_BLEND : MODE_TOP_ONLY; - bool blend_active_only = cfg->top_of_tree && - !mpcc->ctx->dc->debug.surface_visual_confirm; + int mpcc_mode = MODE_TOP_ONLY; + int mpcc_id, z_idx; + + ASSERT(cfg->z_index < mpc10->num_mpcc); - if (mpcc->ctx->dc->debug.sanity_checks) - assert_mpcc_idle_before_connect(mpcc10); + for (z_idx = 0; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) + if (cfg->opp->mpc_tree.dpp[z_idx] == cfg->mi->inst) + break; + if (z_idx == cfg->opp->mpc_tree.num_pipes) { + ASSERT(cfg->z_index <= cfg->opp->mpc_tree.num_pipes); + mpcc_id = mpc10_get_idle_mpcc_id(mpc10); + /*todo: remove hack*/ + mpcc_id = cfg->mi->inst; + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); + + if (mpc->ctx->dc->debug.sanity_checks) + mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); + } else { + ASSERT(cfg->z_index < cfg->opp->mpc_tree.num_pipes); + mpcc_id = cfg->opp->mpc_tree.mpcc[z_idx]; + mpc10_mpcc_remove(mpc, cfg->opp, cfg->mi->inst); + } - REG_SET(MPCC_OPP_ID, 0, - MPCC_OPP_ID, cfg->opp_id); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, + MPCC_OPP_ID, cfg->opp->inst); - REG_SET(MPCC_TOP_SEL, 0, - MPCC_TOP_SEL, cfg->top_dpp_id); + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, + MPCC_TOP_SEL, cfg->mi->inst); - REG_SET(MPCC_BOT_SEL, 0, - MPCC_BOT_SEL, cfg->bot_mpcc_id); + if (cfg->z_index > 0) { + int top_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index - 1]; + + REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + MPCC_BOT_SEL, mpcc_id); + REG_UPDATE(MPCC_CONTROL[top_mpcc_id], + MPCC_MODE, MODE_BLEND); + } else + REG_SET(MUX[cfg->opp->inst], 0, MPC_OUT_MUX, mpcc_id); + + if (cfg->z_index < cfg->opp->mpc_tree.num_pipes) { + int bot_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index]; + + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, bot_mpcc_id); + mpcc_mode = MODE_BLEND; + } - REG_SET_4(MPCC_CONTROL, 0xffffffff, + REG_SET_4(MPCC_CONTROL[mpcc_id], 0xffffffff, MPCC_MODE, mpcc_mode, MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, - MPCC_BLND_ACTIVE_OVERLAP_ONLY, blend_active_only); + MPCC_BLND_ACTIVE_OVERLAP_ONLY, false); - if (cfg->top_of_tree) { - if (cfg->opp_id != 0xf) - set_output_mux(mpcc10, cfg->opp_id, mpcc->inst); - else if (mpcc->opp_id != 0xf) - reset_output_mux(mpcc10); - } - mpcc10->base.opp_id = cfg->opp_id; -} - -static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) -{ - struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); + mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); - REG_WAIT(MPCC_STATUS, - MPCC_BUSY, 0, - 1000, 1000); + mpc10->mpcc_in_use_mask |= 1 << mpcc_id; + for (z_idx = cfg->z_index; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) { + cfg->opp->mpc_tree.dpp[z_idx + 1] = cfg->opp->mpc_tree.dpp[z_idx]; + cfg->opp->mpc_tree.mpcc[z_idx + 1] = cfg->opp->mpc_tree.mpcc[z_idx]; + } + cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst; + cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id; + cfg->opp->mpc_tree.num_pipes++; + cfg->mi->opp_id = cfg->opp->inst; + cfg->mi->mpcc_id = mpcc_id; } - -const struct mpcc_funcs dcn10_mpcc_funcs = { - .set = dcn10_mpcc_set, - .wait_for_idle = dcn10_mpcc_wait_idle, - .set_bg_color = dcn10_mpcc_set_bg_color, +const struct mpc_funcs dcn10_mpc_funcs = { + .add = mpc10_mpcc_add, + .remove = mpc10_mpcc_remove, + .wait_for_idle = mpc10_assert_idle_mpcc }; -void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, +void dcn10_mpc_construct(struct dcn10_mpc *mpc10, struct dc_context *ctx, - const struct dcn_mpcc_registers *mpcc_regs, - const struct dcn_mpcc_shift *mpcc_shift, - const struct dcn_mpcc_mask *mpcc_mask, - int inst) + const struct dcn_mpc_registers *mpc_regs, + const struct dcn_mpc_shift *mpc_shift, + const struct dcn_mpc_mask *mpc_mask, + int num_mpcc) { - mpcc10->base.ctx = ctx; + mpc10->base.ctx = ctx; - mpcc10->base.inst = inst; - mpcc10->base.funcs = &dcn10_mpcc_funcs; + mpc10->base.funcs = &dcn10_mpc_funcs; - mpcc10->mpcc_regs = mpcc_regs; - mpcc10->mpcc_shift = mpcc_shift; - mpcc10->mpcc_mask = mpcc_mask; + mpc10->mpc_regs = mpc_regs; + mpc10->mpc_shift = mpc_shift; + mpc10->mpc_mask = mpc_mask; - mpcc10->base.opp_id = inst; + mpc10->mpcc_in_use_mask = 0; + mpc10->num_mpcc = num_mpcc; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 2985c5d5a0e3..94f890a0ad40 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -27,38 +27,37 @@ #include "mpc.h" -#define TO_DCN10_MPCC(mpcc_base) \ - container_of(mpcc_base, struct dcn10_mpcc, base) +#define TO_DCN10_MPC(mpc_base) \ + container_of(mpc_base, struct dcn10_mpc, base) +#define MAX_MPCC 6 #define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MUX, MPC_OUT, inst) + SRII(MUX, MPC_OUT, inst),\ + SRII(MPCC_TOP_SEL, MPCC, inst),\ + SRII(MPCC_BOT_SEL, MPCC, inst),\ + SRII(MPCC_CONTROL, MPCC, inst),\ + SRII(MPCC_STATUS, MPCC, inst),\ + SRII(MPCC_OPP_ID, MPCC, inst),\ + SRII(MPCC_BG_G_Y, MPCC, inst),\ + SRII(MPCC_BG_R_CR, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst),\ + SRII(MPCC_BG_B_CB, MPCC, inst) -#define MPCC_COMMON_REG_LIST_DCN1_0(inst) \ - SRI(MPCC_TOP_SEL, MPCC, inst),\ - SRI(MPCC_BOT_SEL, MPCC, inst),\ - SRI(MPCC_CONTROL, MPCC, inst),\ - SRI(MPCC_STATUS, MPCC, inst),\ - SRI(MPCC_OPP_ID, MPCC, inst),\ - SRI(MPCC_BG_G_Y, MPCC, inst),\ - SRI(MPCC_BG_R_CR, MPCC, inst),\ - SRI(MPCC_BG_B_CB, MPCC, inst),\ - SRI(MPCC_BG_B_CB, MPCC, inst) - -struct dcn_mpcc_registers { - uint32_t MPCC_TOP_SEL; - uint32_t MPCC_BOT_SEL; - uint32_t MPCC_CONTROL; - uint32_t MPCC_STATUS; - uint32_t MPCC_OPP_ID; - uint32_t MPCC_BG_G_Y; - uint32_t MPCC_BG_R_CR; - uint32_t MPCC_BG_B_CB; +struct dcn_mpc_registers { + uint32_t MPCC_TOP_SEL[MAX_MPCC]; + uint32_t MPCC_BOT_SEL[MAX_MPCC]; + uint32_t MPCC_CONTROL[MAX_MPCC]; + uint32_t MPCC_STATUS[MAX_MPCC]; + uint32_t MPCC_OPP_ID[MAX_MPCC]; + uint32_t MPCC_BG_G_Y[MAX_MPCC]; + uint32_t MPCC_BG_R_CR[MAX_MPCC]; + uint32_t MPCC_BG_B_CB[MAX_MPCC]; uint32_t MUX[MAX_OPP]; }; -#define MPCC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ +#define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\ @@ -73,7 +72,7 @@ struct dcn_mpcc_registers { SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\ SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh) -#define MPCC_REG_FIELD_LIST(type) \ +#define MPC_REG_FIELD_LIST(type) \ type MPCC_TOP_SEL;\ type MPCC_BOT_SEL;\ type MPCC_MODE;\ @@ -86,28 +85,31 @@ struct dcn_mpcc_registers { type MPCC_BG_G_Y;\ type MPCC_BG_R_CR;\ type MPCC_BG_B_CB;\ - type MPC_OUT_MUX;\ + type MPC_OUT_MUX; -struct dcn_mpcc_shift { - MPCC_REG_FIELD_LIST(uint8_t) +struct dcn_mpc_shift { + MPC_REG_FIELD_LIST(uint8_t) }; -struct dcn_mpcc_mask { - MPCC_REG_FIELD_LIST(uint32_t) +struct dcn_mpc_mask { + MPC_REG_FIELD_LIST(uint32_t) }; -struct dcn10_mpcc { - struct mpcc base; - const struct dcn_mpcc_registers *mpcc_regs; - const struct dcn_mpcc_shift *mpcc_shift; - const struct dcn_mpcc_mask *mpcc_mask; +struct dcn10_mpc { + struct mpc base; + + int mpcc_in_use_mask; + int num_mpcc; + const struct dcn_mpc_registers *mpc_regs; + const struct dcn_mpc_shift *mpc_shift; + const struct dcn_mpc_mask *mpc_mask; }; -void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, +void dcn10_mpc_construct(struct dcn10_mpc *mpcc10, struct dc_context *ctx, - const struct dcn_mpcc_registers *mpcc_regs, - const struct dcn_mpcc_shift *mpcc_shift, - const struct dcn_mpcc_mask *mpcc_mask, - int inst); + const struct dcn_mpc_registers *mpc_regs, + const struct dcn_mpc_shift *mpc_shift, + const struct dcn_mpc_mask *mpc_mask, + int num_mpcc); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index f8e4724a629d..38d15f7c2a88 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -337,6 +337,9 @@ void dcn10_opp_construct(struct dcn10_opp *oppn10, oppn10->base.inst = inst; oppn10->base.funcs = &dcn10_opp_funcs; + oppn10->base.mpc_tree.dpp[0] = inst; + oppn10->base.mpc_tree.mpcc[0] = inst; + oppn10->base.mpc_tree.num_pipes = 1; for (i = 0; i < MAX_PIPES; i++) oppn10->base.mpcc_disconnect_pending[i] = false; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 33beb0bc3ddf..9d44f42cbf96 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -324,29 +324,19 @@ static const struct dcn_dpp_mask tf_mask = { TF_REG_LIST_SH_MASK_DCN10(_MASK), }; - -#define mpcc_regs(id)\ -[id] = {\ - MPCC_COMMON_REG_LIST_DCN1_0(id),\ - MPC_COMMON_REG_LIST_DCN1_0(0),\ - MPC_COMMON_REG_LIST_DCN1_0(1),\ - MPC_COMMON_REG_LIST_DCN1_0(2),\ - MPC_COMMON_REG_LIST_DCN1_0(3),\ -} - -static const struct dcn_mpcc_registers mpcc_regs[] = { - mpcc_regs(0), - mpcc_regs(1), - mpcc_regs(2), - mpcc_regs(3), +static const struct dcn_mpc_registers mpc_regs = { + MPC_COMMON_REG_LIST_DCN1_0(0), + MPC_COMMON_REG_LIST_DCN1_0(1), + MPC_COMMON_REG_LIST_DCN1_0(2), + MPC_COMMON_REG_LIST_DCN1_0(3) }; -static const struct dcn_mpcc_shift mpcc_shift = { - MPCC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +static const struct dcn_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) }; -static const struct dcn_mpcc_mask mpcc_mask = { - MPCC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), +static const struct dcn_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK), }; #define tg_regs(id)\ @@ -508,22 +498,20 @@ static struct output_pixel_processor *dcn10_opp_create( return &opp->base; } -static struct mpcc *dcn10_mpcc_create( - struct dc_context *ctx, - int inst) +static struct mpc *dcn10_mpc_create(struct dc_context *ctx) { - struct dcn10_mpcc *mpcc10 = dm_alloc(sizeof(struct dcn10_mpcc)); + struct dcn10_mpc *mpc10 = dm_alloc(sizeof(struct dcn10_mpc)); - if (!mpcc10) + if (!mpc10) return NULL; - dcn10_mpcc_construct(mpcc10, ctx, - &mpcc_regs[inst], - &mpcc_shift, - &mpcc_mask, - inst); + dcn10_mpc_construct(mpc10, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + 4); - return &mpcc10->base; + return &mpc10->base; } static struct timing_generator *dcn10_timing_generator_create( @@ -702,6 +690,10 @@ static void destruct(struct dcn10_resource_pool *pool) } } + if (pool->base.mpc != NULL) { + dm_free(TO_DCN10_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } for (i = 0; i < pool->base.pipe_count; i++) { if (pool->base.opps[i] != NULL) pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); @@ -725,11 +717,6 @@ static void destruct(struct dcn10_resource_pool *pool) dm_free(DCN10TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } - - if (pool->base.mpcc[i] != NULL) { - dm_free(TO_DCN10_MPCC(pool->base.mpcc[i])); - pool->base.mpcc[i] = NULL; - } } for (i = 0; i < pool->base.stream_enc_count; i++) { @@ -974,12 +961,11 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream = head_pipe->stream; idle_pipe->tg = head_pipe->tg; + idle_pipe->opp = head_pipe->opp; - idle_pipe->mpcc = pool->mpcc[idle_pipe->pipe_idx]; idle_pipe->mi = pool->mis[idle_pipe->pipe_idx]; idle_pipe->ipp = pool->ipps[idle_pipe->pipe_idx]; idle_pipe->xfm = pool->transforms[idle_pipe->pipe_idx]; - idle_pipe->opp = pool->opps[idle_pipe->pipe_idx]; return idle_pipe; } @@ -1406,12 +1392,12 @@ static bool construct( dm_error("DC: failed to create tg!\n"); goto otg_create_fail; } - pool->base.mpcc[i] = dcn10_mpcc_create(ctx, i); - if (pool->base.mpcc[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpcc!\n"); - goto mpcc_create_fail; - } + } + pool->base.mpc = dcn10_mpc_create(ctx); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto mpc_create_fail; } if (!resource_construct(num_virtual_links, dc, &pool->base, @@ -1427,7 +1413,7 @@ static bool construct( return true; disp_clk_create_fail: -mpcc_create_fail: +mpc_create_fail: otg_create_fail: opp_create_fail: dpp_create_fail: diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 2ae5a607fb5a..b312bb3b3350 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -123,7 +123,7 @@ struct resource_pool { struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct mpcc *mpcc[MAX_PIPES]; + struct mpc *mpc; #endif unsigned int pipe_count; @@ -183,7 +183,6 @@ struct pipe_ctx { struct pipe_ctx *bottom_pipe; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct mpcc *mpcc; struct _vcs_dpi_display_dlg_regs_st dlg_regs; struct _vcs_dpi_display_ttu_regs_st ttu_regs; struct _vcs_dpi_display_rq_regs_st rq_regs; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index fd3ce742af2c..a7c89c36f90f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -69,7 +69,9 @@ struct mem_input { struct dc_context *ctx; struct dc_plane_address request_address; struct dc_plane_address current_address; - uint32_t inst; + int inst; + int opp_id; + int mpcc_id; struct stutter_modes stutter_mode; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 55c9c305a259..4bbcff48acc8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -26,27 +26,29 @@ #define __DC_MPCC_H__ #include "dc_hw_types.h" +#include "opp.h" struct mpcc_cfg { - int top_dpp_id; - int bot_mpcc_id; - int opp_id; + struct mem_input *mi; + struct output_pixel_processor *opp; + unsigned int z_index; + + struct tg_color black_color; bool per_pixel_alpha; bool pre_multiplied_alpha; - bool top_of_tree; }; -struct mpcc { - const struct mpcc_funcs *funcs; +struct mpc { + const struct mpc_funcs *funcs; struct dc_context *ctx; - int inst; - int opp_id; }; -struct mpcc_funcs { - void (*set)(struct mpcc *mpcc, struct mpcc_cfg *cfg); - void (*wait_for_idle)(struct mpcc *mpcc); - void (*set_bg_color)( struct mpcc *mpcc, struct tg_color *bg_color); +struct mpc_funcs { + void (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + void (*remove)(struct mpc *mpc, + struct output_pixel_processor *opp, + int mpcc_inst); + void (*wait_for_idle)(struct mpc *mpc, int id); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a43a09b3f414..01d6957c07fb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -196,10 +196,17 @@ struct pwl_float_data { struct fixed31_32 b; }; +struct mpc_tree_cfg { + int num_pipes; + int dpp[MAX_PIPES]; + int mpcc[MAX_PIPES]; +}; + struct output_pixel_processor { struct dc_context *ctx; uint32_t inst; struct pwl_params regamma_params; + struct mpc_tree_cfg mpc_tree; bool mpcc_disconnect_pending[MAX_PIPES]; const struct opp_funcs *funcs; }; -- GitLab From cd273548e4f96508c97e5325ce0f5301aa2e3ad5 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 26 Jul 2017 17:01:06 -0400 Subject: [PATCH 0702/2898] drm/amd/display: fix mpcc idle wait Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 246b60a16521..036f161ab1c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -71,7 +71,7 @@ static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) ASSERT(!(mpc10->mpcc_in_use_mask & 1 << id)); REG_WAIT(MPCC_STATUS[id], - MPCC_BUSY, 0, + MPCC_IDLE, 1, 1000, 1000); } -- GitLab From 4654a2f7fce0c2fd3dafe2c366ddf8e9e080fa44 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 26 Jul 2017 16:27:37 -0400 Subject: [PATCH 0703/2898] drm/amd/display: add detect caps for edp 1. The caps detect sequence for edp is different from dp. Added separate function for edp. 2. Removed max_link_setting and replaced it with verified to avoid confusion. 3. Reverted sink count guard for edp powerdown as unnecessary with the changes above. Signed-off-by: Roman Li Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 11 ++++++++--- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 +--- drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 2 ++ 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2487046457c8..a983a5ee3172 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -585,7 +585,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) } case SIGNAL_TYPE_EDP: { - detect_dp_sink_caps(link); + detect_edp_sink_caps(link); sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX; sink_caps.signal = SIGNAL_TYPE_EDP; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index d9754b5f2543..17506345f97a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1147,7 +1147,6 @@ bool dp_hbr_verify_link_cap( LINK_SPREAD_DISABLED; } - link->max_link_setting = link->verified_link_cap; return success; } @@ -1466,7 +1465,7 @@ void decide_link_settings(struct dc_stream *stream, * 2. could support the b/w requested by the timing */ while (current_link_setting.link_rate <= - link->max_link_setting.link_rate) { + link->verified_link_cap.link_rate) { link_bw = bandwidth_in_kbps_from_link_settings( ¤t_link_setting); if (req_bw <= link_bw) { @@ -1475,7 +1474,7 @@ void decide_link_settings(struct dc_stream *stream, } if (current_link_setting.lane_count < - link->max_link_setting.lane_count) { + link->verified_link_cap.lane_count) { current_link_setting.lane_count = increase_lane_count( current_link_setting.lane_count); @@ -2294,6 +2293,12 @@ void detect_dp_sink_caps(struct dc_link *link) /* TODO save sink caps in link->sink */ } +void detect_edp_sink_caps(struct dc_link *link) +{ + retrieve_link_cap(link); + link->verified_link_cap = link->reported_link_cap; +} + void dc_link_dp_enable_hpd(const struct dc_link *link) { struct link_encoder *encoder = link->link_enc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 76dc16916821..f2f57a75f864 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -114,9 +114,7 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); - if (link->dpcd_sink_count) - link->link_enc->funcs->power_control(link->link_enc, - false); + link->link_enc->funcs->power_control(link->link_enc, false); } link->link_enc->funcs->disable_output(link->link_enc, signal); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b20f7bfcdc1f..58bfb867b71c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -744,7 +744,6 @@ struct dc_link { */ struct dc_link_settings reported_link_cap; struct dc_link_settings verified_link_cap; - struct dc_link_settings max_link_setting; struct dc_link_settings cur_link_settings; struct dc_lane_settings cur_lane_setting; struct dc_link_settings preferred_link_setting; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 5b4185053e9c..1a4a605cb449 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -63,6 +63,8 @@ bool is_mst_supported(struct dc_link *link); void detect_dp_sink_caps(struct dc_link *link); +void detect_edp_sink_caps(struct dc_link *link); + bool is_dp_active_dongle(const struct dc_link *link); void dp_enable_mst_on_sink(struct dc_link *link, bool enable); -- GitLab From 1c3fb02d2567ae348a3495c93bea991e9d028780 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 26 Jul 2017 18:31:25 -0400 Subject: [PATCH 0704/2898] drm/amd/display: update clocks we report to PPlib Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 49b75765d900..875b98dae6e1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1267,13 +1267,14 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) { struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0}; int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, - nom_dcfclk_khz, min_dcfclk_khz, socclk_khz; + nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz; const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); kernel_fpu_begin(); max_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; nom_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; + mid_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 * 1000000 / factor; min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; max_dcfclk_khz = dc->dcn_soc.dcfclkv_max0p9 * 1000; nom_dcfclk_khz = dc->dcn_soc.dcfclkv_nom0p8 * 1000; @@ -1293,48 +1294,48 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) clk_ranges.num_wm_mcif_sets = 4; clk_ranges.wm_dmif_clocks_ranges[0].wm_set_id = WM_SET_A; clk_ranges.wm_dmif_clocks_ranges[0].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = nom_dcfclk_khz - 1; + clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; clk_ranges.wm_dmif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = nom_fclk_khz - 1; + clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz; clk_ranges.wm_mcif_clocks_ranges[0].wm_set_id = WM_SET_A; clk_ranges.wm_mcif_clocks_ranges[0].wm_min_socclk_clk_in_khz = socclk_khz; clk_ranges.wm_mcif_clocks_ranges[0].wm_max_socclk_clk_in_khz = overdrive; clk_ranges.wm_mcif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = nom_fclk_khz - 1; + clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz; clk_ranges.wm_dmif_clocks_ranges[1].wm_set_id = WM_SET_B; - clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = nom_dcfclk_khz - 1; - clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz; clk_ranges.wm_mcif_clocks_ranges[1].wm_set_id = WM_SET_B; clk_ranges.wm_mcif_clocks_ranges[1].wm_min_socclk_clk_in_khz = socclk_khz; clk_ranges.wm_mcif_clocks_ranges[1].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz; clk_ranges.wm_dmif_clocks_ranges[2].wm_set_id = WM_SET_C; - clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = nom_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = min_fclk_khz; clk_ranges.wm_dmif_clocks_ranges[2].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; clk_ranges.wm_dmif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz; clk_ranges.wm_mcif_clocks_ranges[2].wm_set_id = WM_SET_C; clk_ranges.wm_mcif_clocks_ranges[2].wm_min_socclk_clk_in_khz = socclk_khz; clk_ranges.wm_mcif_clocks_ranges[2].wm_max_socclk_clk_in_khz = overdrive; clk_ranges.wm_mcif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz; clk_ranges.wm_dmif_clocks_ranges[3].wm_set_id = WM_SET_D; - clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = max_dcfclk_khz + 1; - clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = overdrive; - clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz + 1; - clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = overdrive; + clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = min_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; + clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz; + clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz; clk_ranges.wm_mcif_clocks_ranges[3].wm_set_id = WM_SET_D; clk_ranges.wm_mcif_clocks_ranges[3].wm_min_socclk_clk_in_khz = socclk_khz; clk_ranges.wm_mcif_clocks_ranges[3].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz + 1; - clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = overdrive; + clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz; + clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz; /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges); -- GitLab From 1515a47b44c8667987d070fdc494691f91b44b46 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 26 Jul 2017 19:31:53 -0400 Subject: [PATCH 0705/2898] drm/amd/display: Rename firmware_info to dc_firmware_info This is to avoid conflicts with amdgpu's firmware_info once we merge amdgpu_dm_types with amdgpu_dm. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 14 +++++++------- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 2 +- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 2 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 2 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 2 +- .../amd/display/include/grph_object_ctrl_defs.h | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 47a467688073..2c683d468bb8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -622,17 +622,17 @@ static enum bp_result bios_parser_get_device_tag( static enum bp_result get_firmware_info_v1_4( struct bios_parser *bp, - struct firmware_info *info); + struct dc_firmware_info *info); static enum bp_result get_firmware_info_v2_1( struct bios_parser *bp, - struct firmware_info *info); + struct dc_firmware_info *info); static enum bp_result get_firmware_info_v2_2( struct bios_parser *bp, - struct firmware_info *info); + struct dc_firmware_info *info); static enum bp_result bios_parser_get_firmware_info( struct dc_bios *dcb, - struct firmware_info *info) + struct dc_firmware_info *info) { struct bios_parser *bp = BP_FROM_DCB(dcb); enum bp_result result = BP_RESULT_BADBIOSTABLE; @@ -676,7 +676,7 @@ static enum bp_result bios_parser_get_firmware_info( static enum bp_result get_firmware_info_v1_4( struct bios_parser *bp, - struct firmware_info *info) + struct dc_firmware_info *info) { ATOM_FIRMWARE_INFO_V1_4 *firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4, @@ -726,7 +726,7 @@ static enum bp_result get_ss_info_v3_1( static enum bp_result get_firmware_info_v2_1( struct bios_parser *bp, - struct firmware_info *info) + struct dc_firmware_info *info) { ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo)); @@ -810,7 +810,7 @@ static enum bp_result get_firmware_info_v2_1( static enum bp_result get_firmware_info_v2_2( struct bios_parser *bp, - struct firmware_info *info) + struct dc_firmware_info *info) { ATOM_FIRMWARE_INFO_V2_2 *firmware_info; struct spread_spectrum_info internal_ss; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 3a69f9c5d20a..86fce5ae5856 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -81,7 +81,7 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, static enum bp_result bios_parser_get_firmware_info( struct dc_bios *dcb, - struct firmware_info *info); + struct dc_firmware_info *info); static enum bp_result bios_parser_get_encoder_cap_info( struct dc_bios *dcb, @@ -90,7 +90,7 @@ static enum bp_result bios_parser_get_encoder_cap_info( static enum bp_result get_firmware_info_v3_1( struct bios_parser *bp, - struct firmware_info *info); + struct dc_firmware_info *info); static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp, struct atom_display_object_path_v2 *object); @@ -1583,7 +1583,7 @@ static void bios_parser_set_scratch_critical_state( static enum bp_result bios_parser_get_firmware_info( struct dc_bios *dcb, - struct firmware_info *info) + struct dc_firmware_info *info) { struct bios_parser *bp = BP_FROM_DCB(dcb); enum bp_result result = BP_RESULT_BADBIOSTABLE; @@ -1615,7 +1615,7 @@ static enum bp_result bios_parser_get_firmware_info( static enum bp_result get_firmware_info_v3_1( struct bios_parser *bp, - struct firmware_info *info) + struct dc_firmware_info *info) { struct atom_firmware_info_v3_1 *firmware_info; struct atom_display_controller_info_v4_1 *dce_info = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4068d53137f5..d381e380e974 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -126,7 +126,7 @@ struct resource_pool *dc_create_resource_pool( break; } if (res_pool != NULL) { - struct firmware_info fw_info = { { 0 } }; + struct dc_firmware_info fw_info = { { 0 } }; if (dc->ctx->dc_bios->funcs->get_firmware_info( dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 6e1291d5f51d..273d80a4ebce 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -84,7 +84,7 @@ struct dc_vbios_funcs { struct connector_device_tag_info *info); enum bp_result (*get_firmware_info)( struct dc_bios *bios, - struct firmware_info *info); + struct dc_firmware_info *info); enum bp_result (*get_spread_spectrum_info)( struct dc_bios *bios, enum as_signal_type signal, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 2205491c83e9..dd7e1dd62636 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1103,7 +1103,7 @@ static bool calc_pll_max_vco_construct( struct calc_pll_clock_source_init_data *init_data) { uint32_t i; - struct firmware_info fw_info = { { 0 } }; + struct dc_firmware_info fw_info = { { 0 } }; if (calc_pll_cs == NULL || init_data == NULL || init_data->bp == NULL) @@ -1185,7 +1185,7 @@ bool dce110_clk_src_construct( const struct dce110_clk_src_shift *cs_shift, const struct dce110_clk_src_mask *cs_mask) { - struct firmware_info fw_info = { { 0 } }; + struct dc_firmware_info fw_info = { { 0 } }; struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi; struct calc_pll_clock_source_init_data calc_pll_cs_init_data; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 37d074f595fb..a73228b97da5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -424,7 +424,7 @@ static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) struct dc_debug *debug = &clk_dce->base.ctx->dc->debug; struct dc_bios *bp = clk_dce->base.ctx->dc_bios; struct integrated_info info = { { { 0 } } }; - struct firmware_info fw_info = { { 0 } }; + struct dc_firmware_info fw_info = { { 0 } }; int i; if (bp->integrated_info) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index cf98f2471023..9ac246f05110 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -819,7 +819,7 @@ static bool construct( { unsigned int i; struct dc_context *ctx = dc->ctx; - struct firmware_info info; + struct dc_firmware_info info; struct dc_bios *bp; struct dm_pp_static_clock_info static_clk_info = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index cc25c4b6c06f..5c1790b61290 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1190,7 +1190,7 @@ static bool construct( { unsigned int i; struct dc_context *ctx = dc->ctx; - struct firmware_info info; + struct dc_firmware_info info; struct dc_bios *bp; struct dm_pp_static_clock_info static_clk_info = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 2fde43c91ad0..92f01ed97621 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -833,7 +833,7 @@ static bool construct( { unsigned int i; struct dc_context *ctx = dc->ctx; - struct firmware_info info; + struct dc_firmware_info info; struct dc_bios *bp; struct dm_pp_static_clock_info static_clk_info = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 10061cc4ba31..da08cc1c6dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -320,7 +320,7 @@ void dal_i2caux_destroy( uint32_t dal_i2caux_get_reference_clock( struct dc_bios *bios) { - struct firmware_info info = { { 0 } }; + struct dc_firmware_info info = { { 0 } }; if (bios->funcs->get_firmware_info(bios, &info) != BP_RESULT_OK) return 0; diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index 9c0bf6521dd9..6cdbf84f34e6 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -154,7 +154,7 @@ struct embedded_panel_info { bool realtek_eDPToLVDS; }; -struct firmware_info { +struct dc_firmware_info { struct pll_info { uint32_t crystal_frequency; /* in KHz */ uint32_t min_input_pxl_clk_pll_frequency; /* in KHz */ -- GitLab From e7b07ceef2a650e5ed8ca37997689e086c680daf Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 10 Aug 2017 13:29:07 -0400 Subject: [PATCH 0706/2898] drm/amd/display: Merge amdgpu_dm_types and amdgpu_dm This separation stopped making sense a long time ago. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/Makefile | 2 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3245 +++++++++++++++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 108 +- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 1 - .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- .../display/amdgpu_dm/amdgpu_dm_services.c | 1 - .../amd/display/amdgpu_dm/amdgpu_dm_types.c | 3286 ----------------- .../amd/display/amdgpu_dm/amdgpu_dm_types.h | 135 - 8 files changed, 3350 insertions(+), 3430 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c delete mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile index 698b1d4f83f5..4699e47aa76b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile @@ -4,7 +4,7 @@ -AMDGPUDM = amdgpu_dm_types.o amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o +AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o ifneq ($(CONFIG_DRM_AMD_DC),) AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c802437f4858..646a946a2571 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -31,21 +31,27 @@ #include "amdgpu_display.h" #include "atom.h" #include "amdgpu_dm.h" -#include "amdgpu_dm_types.h" +#include "amdgpu_pm.h" #include "amd_shared.h" #include "amdgpu_dm_irq.h" #include "dm_helpers.h" +#include "dm_services_types.h" +#include "amdgpu_dm_mst_types.h" #include "ivsrcid/ivsrcid_vislands30.h" #include #include #include +#include +#include #include #include #include +#include +#include #include "modules/inc/mod_freesync.h" @@ -59,6 +65,11 @@ #include "soc15_common.h" #endif +#include "modules/inc/mod_freesync.h" + +#include "i2caux_interface.h" + + static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, @@ -1552,8 +1563,3238 @@ bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) { - /* TODO */ + /* TODO */ return true; +} + + +struct dm_connector_state { + struct drm_connector_state base; + + enum amdgpu_rmx_type scaling; + uint8_t underscan_vborder; + uint8_t underscan_hborder; + bool underscan_enable; +}; + +#define to_dm_connector_state(x)\ + container_of((x), struct dm_connector_state, base) + +static bool modeset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; + + if (!crtc_state->enable) + return false; + + return crtc_state->active; +} + +static bool modereset_required(struct drm_crtc_state *crtc_state) +{ + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + return false; + + return !crtc_state->enable || !crtc_state->active; +} + +void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); + kfree(encoder); +} + +static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { + .destroy = amdgpu_dm_encoder_destroy, +}; + +static void dm_set_cursor( + struct amdgpu_crtc *amdgpu_crtc, + uint64_t gpu_addr, + uint32_t width, + uint32_t height) +{ + struct dc_cursor_attributes attributes; + struct dc_cursor_position position; + struct drm_crtc *crtc = &amdgpu_crtc->base; + int x, y; + int xorigin = 0, yorigin = 0; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + + amdgpu_crtc->cursor_width = width; + amdgpu_crtc->cursor_height = height; + + attributes.address.high_part = upper_32_bits(gpu_addr); + attributes.address.low_part = lower_32_bits(gpu_addr); + attributes.width = width; + attributes.height = height; + attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; + attributes.rotation_angle = 0; + attributes.attribute_flags.value = 0; + + attributes.pitch = attributes.width; + + x = amdgpu_crtc->cursor_x; + y = amdgpu_crtc->cursor_y; + + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + position.enable = true; + position.x = x; + position.y = y; + + position.x_hotspot = xorigin; + position.y_hotspot = yorigin; + + if (!dc_stream_set_cursor_attributes( + acrtc_state->stream, + &attributes)) { + DRM_ERROR("DC failed to set cursor attributes\n"); + } + + if (!dc_stream_set_cursor_position( + acrtc_state->stream, + &position)) { + DRM_ERROR("DC failed to set cursor position\n"); + } +} + +static int dm_crtc_cursor_set( + struct drm_crtc *crtc, + uint64_t address, + uint32_t width, + uint32_t height) +{ + struct dc_cursor_position position; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + + int ret; + + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + ret = EINVAL; + + DRM_DEBUG_KMS( + "%s: crtc_id=%d with size %d to %d \n", + __func__, + amdgpu_crtc->crtc_id, + width, + height); + + if (!address) { + /* turn off cursor */ + position.enable = false; + position.x = 0; + position.y = 0; + + if (acrtc_state->stream) { + /*set cursor visible false*/ + dc_stream_set_cursor_position( + acrtc_state->stream, + &position); + } + goto release; + + } + + if ((width > amdgpu_crtc->max_cursor_width) || + (height > amdgpu_crtc->max_cursor_height)) { + DRM_ERROR( + "%s: bad cursor width or height %d x %d\n", + __func__, + width, + height); + goto release; + } + + /*program new cursor bo to hardware*/ + dm_set_cursor(amdgpu_crtc, address, width, height); + +release: + return ret; + +} + +static int dm_crtc_cursor_move(struct drm_crtc *crtc, + int x, int y) +{ + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + int xorigin = 0, yorigin = 0; + struct dc_cursor_position position; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + + amdgpu_crtc->cursor_x = x; + amdgpu_crtc->cursor_y = y; + + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + + /* + * TODO: for cursor debugging unguard the following + */ +#if 0 + DRM_DEBUG_KMS( + "%s: x %d y %d c->x %d c->y %d\n", + __func__, + x, + y, + crtc->x, + crtc->y); +#endif + + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + + position.enable = true; + position.x = x; + position.y = y; + + position.x_hotspot = xorigin; + position.y_hotspot = yorigin; + + if (acrtc_state->stream) { + if (!dc_stream_set_cursor_position( + acrtc_state->stream, + &position)) { + DRM_ERROR("DC failed to set cursor position\n"); + return -EINVAL; + } + } + + return 0; +} + +static bool fill_rects_from_plane_state( + const struct drm_plane_state *state, + struct dc_surface *surface) +{ + surface->src_rect.x = state->src_x >> 16; + surface->src_rect.y = state->src_y >> 16; + /*we ignore for now mantissa and do not to deal with floating pixels :(*/ + surface->src_rect.width = state->src_w >> 16; + + if (surface->src_rect.width == 0) + return false; + + surface->src_rect.height = state->src_h >> 16; + if (surface->src_rect.height == 0) + return false; + + surface->dst_rect.x = state->crtc_x; + surface->dst_rect.y = state->crtc_y; + + if (state->crtc_w == 0) + return false; + + surface->dst_rect.width = state->crtc_w; + + if (state->crtc_h == 0) + return false; + + surface->dst_rect.height = state->crtc_h; + + surface->clip_rect = surface->dst_rect; + + switch (state->rotation & DRM_MODE_ROTATE_MASK) { + case DRM_MODE_ROTATE_0: + surface->rotation = ROTATION_ANGLE_0; + break; + case DRM_MODE_ROTATE_90: + surface->rotation = ROTATION_ANGLE_90; + break; + case DRM_MODE_ROTATE_180: + surface->rotation = ROTATION_ANGLE_180; + break; + case DRM_MODE_ROTATE_270: + surface->rotation = ROTATION_ANGLE_270; + break; + default: + surface->rotation = ROTATION_ANGLE_0; + break; + } + return true; } +static int get_fb_info( + const struct amdgpu_framebuffer *amdgpu_fb, + uint64_t *tiling_flags, + uint64_t *fb_location) +{ + struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); + int r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) { + DRM_ERROR("Unable to reserve buffer\n"); + return r; + } + + if (fb_location) + *fb_location = amdgpu_bo_gpu_offset(rbo); + + if (tiling_flags) + amdgpu_bo_get_tiling_flags(rbo, tiling_flags); + + amdgpu_bo_unreserve(rbo); + + return r; +} + +static int fill_plane_attributes_from_fb( + struct amdgpu_device *adev, + struct dc_surface *surface, + const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) +{ + uint64_t tiling_flags; + uint64_t fb_location = 0; + unsigned int awidth; + const struct drm_framebuffer *fb = &amdgpu_fb->base; + int ret = 0; + struct drm_format_name_buf format_name; + + ret = get_fb_info( + amdgpu_fb, + &tiling_flags, + addReq == true ? &fb_location:NULL); + + if (ret) + return ret; + + switch (fb->format->format) { + case DRM_FORMAT_C8: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; + break; + case DRM_FORMAT_RGB565: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; + break; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; + break; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; + break; + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: + surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; + break; + case DRM_FORMAT_NV21: + surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; + break; + case DRM_FORMAT_NV12: + surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; + break; + default: + DRM_ERROR("Unsupported screen format %s\n", + drm_get_format_name(fb->format->format, &format_name)); + return -EINVAL; + } + + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + surface->address.type = PLN_ADDR_TYPE_GRAPHICS; + surface->address.grph.addr.low_part = lower_32_bits(fb_location); + surface->address.grph.addr.high_part = upper_32_bits(fb_location); + surface->plane_size.grph.surface_size.x = 0; + surface->plane_size.grph.surface_size.y = 0; + surface->plane_size.grph.surface_size.width = fb->width; + surface->plane_size.grph.surface_size.height = fb->height; + surface->plane_size.grph.surface_pitch = + fb->pitches[0] / fb->format->cpp[0]; + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_SRGB; + + } else { + awidth = ALIGN(fb->width, 64); + surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; + surface->address.video_progressive.luma_addr.low_part + = lower_32_bits(fb_location); + surface->address.video_progressive.chroma_addr.low_part + = lower_32_bits(fb_location) + + (awidth * fb->height); + surface->plane_size.video.luma_size.x = 0; + surface->plane_size.video.luma_size.y = 0; + surface->plane_size.video.luma_size.width = awidth; + surface->plane_size.video.luma_size.height = fb->height; + /* TODO: unhardcode */ + surface->plane_size.video.luma_pitch = awidth; + + surface->plane_size.video.chroma_size.x = 0; + surface->plane_size.video.chroma_size.y = 0; + surface->plane_size.video.chroma_size.width = awidth; + surface->plane_size.video.chroma_size.height = fb->height; + surface->plane_size.video.chroma_pitch = awidth / 2; + + /* TODO: unhardcode */ + surface->color_space = COLOR_SPACE_YCBCR709; + } + + memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); + + /* Fill GFX params */ + if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) + { + unsigned bankw, bankh, mtaspect, tile_split, num_banks; + + bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); + bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); + mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); + tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); + num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); + + /* XXX fix me for VI */ + surface->tiling_info.gfx8.num_banks = num_banks; + surface->tiling_info.gfx8.array_mode = + DC_ARRAY_2D_TILED_THIN1; + surface->tiling_info.gfx8.tile_split = tile_split; + surface->tiling_info.gfx8.bank_width = bankw; + surface->tiling_info.gfx8.bank_height = bankh; + surface->tiling_info.gfx8.tile_aspect = mtaspect; + surface->tiling_info.gfx8.tile_mode = + DC_ADDR_SURF_MICRO_TILING_DISPLAY; + } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) + == DC_ARRAY_1D_TILED_THIN1) { + surface->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; + } + + surface->tiling_info.gfx8.pipe_config = + AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); + + if (adev->asic_type == CHIP_VEGA10 || + adev->asic_type == CHIP_RAVEN) { + /* Fill GFX9 params */ + surface->tiling_info.gfx9.num_pipes = + adev->gfx.config.gb_addr_config_fields.num_pipes; + surface->tiling_info.gfx9.num_banks = + adev->gfx.config.gb_addr_config_fields.num_banks; + surface->tiling_info.gfx9.pipe_interleave = + adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; + surface->tiling_info.gfx9.num_shader_engines = + adev->gfx.config.gb_addr_config_fields.num_se; + surface->tiling_info.gfx9.max_compressed_frags = + adev->gfx.config.gb_addr_config_fields.max_compress_frags; + surface->tiling_info.gfx9.num_rb_per_se = + adev->gfx.config.gb_addr_config_fields.num_rb_per_se; + surface->tiling_info.gfx9.swizzle = + AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); + surface->tiling_info.gfx9.shaderEnable = 1; + } + + surface->visible = true; + surface->scaling_quality.h_taps_c = 0; + surface->scaling_quality.v_taps_c = 0; + + /* is this needed? is surface zeroed at allocation? */ + surface->scaling_quality.h_taps = 0; + surface->scaling_quality.v_taps = 0; + surface->stereo_format = PLANE_STEREO_FORMAT_NONE; + + return ret; + +} + +#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 + +static void fill_gamma_from_crtc_state( + const struct drm_crtc_state *crtc_state, + struct dc_surface *dc_surface) +{ + int i; + struct dc_gamma *gamma; + struct drm_color_lut *lut = (struct drm_color_lut *) crtc_state->gamma_lut->data; + + gamma = dc_create_gamma(); + + if (gamma == NULL) { + WARN_ON(1); + return; + } + + for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { + gamma->red[i] = lut[i].red; + gamma->green[i] = lut[i].green; + gamma->blue[i] = lut[i].blue; + } + + dc_surface->gamma_correction = gamma; +} + +static int fill_plane_attributes( + struct amdgpu_device *adev, + struct dc_surface *surface, + struct drm_plane_state *plane_state, + struct drm_crtc_state *crtc_state, + bool addrReq) +{ + const struct amdgpu_framebuffer *amdgpu_fb = + to_amdgpu_framebuffer(plane_state->fb); + const struct drm_crtc *crtc = plane_state->crtc; + struct dc_transfer_func *input_tf; + int ret = 0; + + if (!fill_rects_from_plane_state(plane_state, surface)) + return -EINVAL; + + ret = fill_plane_attributes_from_fb( + crtc->dev->dev_private, + surface, + amdgpu_fb, + addrReq); + + if (ret) + return ret; + + input_tf = dc_create_transfer_func(); + + if (input_tf == NULL) + return -ENOMEM; + + input_tf->type = TF_TYPE_PREDEFINED; + input_tf->tf = TRANSFER_FUNCTION_SRGB; + + surface->in_transfer_func = input_tf; + + /* In case of gamma set, update gamma value */ + if (crtc_state->gamma_lut) + fill_gamma_from_crtc_state(crtc_state, surface); + + return ret; +} + +/*****************************************************************************/ + +struct amdgpu_connector *aconnector_from_drm_crtc_id( + const struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_connector *connector; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_connector *aconnector; + + list_for_each_entry(connector, + &dev->mode_config.connector_list, head) { + + aconnector = to_amdgpu_connector(connector); + + if (aconnector->base.state->crtc != &acrtc->base) + continue; + + /* Found the connector */ + return aconnector; + } + + /* If we get here, not found. */ + return NULL; +} + +static void update_stream_scaling_settings( + const struct drm_display_mode *mode, + const struct dm_connector_state *dm_state, + struct dc_stream *stream) +{ + enum amdgpu_rmx_type rmx_type; + + struct rect src = { 0 }; /* viewport in composition space*/ + struct rect dst = { 0 }; /* stream addressable area */ + + /* no mode. nothing to be done */ + if (!mode) + return; + + /* Full screen scaling by default */ + src.width = mode->hdisplay; + src.height = mode->vdisplay; + dst.width = stream->timing.h_addressable; + dst.height = stream->timing.v_addressable; + + rmx_type = dm_state->scaling; + if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { + if (src.width * dst.height < + src.height * dst.width) { + /* height needs less upscaling/more downscaling */ + dst.width = src.width * + dst.height / src.height; + } else { + /* width needs less upscaling/more downscaling */ + dst.height = src.height * + dst.width / src.width; + } + } else if (rmx_type == RMX_CENTER) { + dst = src; + } + + dst.x = (stream->timing.h_addressable - dst.width) / 2; + dst.y = (stream->timing.v_addressable - dst.height) / 2; + + if (dm_state->underscan_enable) { + dst.x += dm_state->underscan_hborder / 2; + dst.y += dm_state->underscan_vborder / 2; + dst.width -= dm_state->underscan_hborder; + dst.height -= dm_state->underscan_vborder; + } + + stream->src = src; + stream->dst = dst; + + DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", + dst.x, dst.y, dst.width, dst.height); + +} + +static enum dc_color_depth convert_color_depth_from_display_info( + const struct drm_connector *connector) +{ + uint32_t bpc = connector->display_info.bpc; + + /* Limited color depth to 8bit + * TODO: Still need to handle deep color*/ + if (bpc > 8) + bpc = 8; + + switch (bpc) { + case 0: + /* Temporary Work around, DRM don't parse color depth for + * EDID revision before 1.4 + * TODO: Fix edid parsing + */ + return COLOR_DEPTH_888; + case 6: + return COLOR_DEPTH_666; + case 8: + return COLOR_DEPTH_888; + case 10: + return COLOR_DEPTH_101010; + case 12: + return COLOR_DEPTH_121212; + case 14: + return COLOR_DEPTH_141414; + case 16: + return COLOR_DEPTH_161616; + default: + return COLOR_DEPTH_UNDEFINED; + } +} + +static enum dc_aspect_ratio get_aspect_ratio( + const struct drm_display_mode *mode_in) +{ + int32_t width = mode_in->crtc_hdisplay * 9; + int32_t height = mode_in->crtc_vdisplay * 16; + if ((width - height) < 10 && (width - height) > -10) + return ASPECT_RATIO_16_9; + else + return ASPECT_RATIO_4_3; +} + +static enum dc_color_space get_output_color_space( + const struct dc_crtc_timing *dc_crtc_timing) +{ + enum dc_color_space color_space = COLOR_SPACE_SRGB; + + switch (dc_crtc_timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + case PIXEL_ENCODING_YCBCR444: + case PIXEL_ENCODING_YCBCR420: + { + /* + * 27030khz is the separation point between HDTV and SDTV + * according to HDMI spec, we use YCbCr709 and YCbCr601 + * respectively + */ + if (dc_crtc_timing->pix_clk_khz > 27030) { + if (dc_crtc_timing->flags.Y_ONLY) + color_space = + COLOR_SPACE_YCBCR709_LIMITED; + else + color_space = COLOR_SPACE_YCBCR709; + } else { + if (dc_crtc_timing->flags.Y_ONLY) + color_space = + COLOR_SPACE_YCBCR601_LIMITED; + else + color_space = COLOR_SPACE_YCBCR601; + } + + } + break; + case PIXEL_ENCODING_RGB: + color_space = COLOR_SPACE_SRGB; + break; + + default: + WARN_ON(1); + break; + } + + return color_space; +} + +/*****************************************************************************/ + +static void fill_stream_properties_from_drm_display_mode( + struct dc_stream *stream, + const struct drm_display_mode *mode_in, + const struct drm_connector *connector) +{ + struct dc_crtc_timing *timing_out = &stream->timing; + memset(timing_out, 0, sizeof(struct dc_crtc_timing)); + + timing_out->h_border_left = 0; + timing_out->h_border_right = 0; + timing_out->v_border_top = 0; + timing_out->v_border_bottom = 0; + /* TODO: un-hardcode */ + + if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) + && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) + timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; + else + timing_out->pixel_encoding = PIXEL_ENCODING_RGB; + + timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE; + timing_out->display_color_depth = convert_color_depth_from_display_info( + connector); + timing_out->scan_type = SCANNING_TYPE_NODATA; + timing_out->hdmi_vic = 0; + timing_out->vic = drm_match_cea_mode(mode_in); + + timing_out->h_addressable = mode_in->crtc_hdisplay; + timing_out->h_total = mode_in->crtc_htotal; + timing_out->h_sync_width = + mode_in->crtc_hsync_end - mode_in->crtc_hsync_start; + timing_out->h_front_porch = + mode_in->crtc_hsync_start - mode_in->crtc_hdisplay; + timing_out->v_total = mode_in->crtc_vtotal; + timing_out->v_addressable = mode_in->crtc_vdisplay; + timing_out->v_front_porch = + mode_in->crtc_vsync_start - mode_in->crtc_vdisplay; + timing_out->v_sync_width = + mode_in->crtc_vsync_end - mode_in->crtc_vsync_start; + timing_out->pix_clk_khz = mode_in->crtc_clock; + timing_out->aspect_ratio = get_aspect_ratio(mode_in); + if (mode_in->flags & DRM_MODE_FLAG_PHSYNC) + timing_out->flags.HSYNC_POSITIVE_POLARITY = 1; + if (mode_in->flags & DRM_MODE_FLAG_PVSYNC) + timing_out->flags.VSYNC_POSITIVE_POLARITY = 1; + + stream->output_color_space = get_output_color_space(timing_out); + + { + struct dc_transfer_func *tf = dc_create_transfer_func(); + tf->type = TF_TYPE_PREDEFINED; + tf->tf = TRANSFER_FUNCTION_SRGB; + stream->out_transfer_func = tf; + } +} + +static void fill_audio_info( + struct audio_info *audio_info, + const struct drm_connector *drm_connector, + const struct dc_sink *dc_sink) +{ + int i = 0; + int cea_revision = 0; + const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps; + + audio_info->manufacture_id = edid_caps->manufacturer_id; + audio_info->product_id = edid_caps->product_id; + + cea_revision = drm_connector->display_info.cea_rev; + + while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && + edid_caps->display_name[i]) { + audio_info->display_name[i] = edid_caps->display_name[i]; + i++; + } + + if(cea_revision >= 3) { + audio_info->mode_count = edid_caps->audio_mode_count; + + for (i = 0; i < audio_info->mode_count; ++i) { + audio_info->modes[i].format_code = + (enum audio_format_code) + (edid_caps->audio_modes[i].format_code); + audio_info->modes[i].channel_count = + edid_caps->audio_modes[i].channel_count; + audio_info->modes[i].sample_rates.all = + edid_caps->audio_modes[i].sample_rate; + audio_info->modes[i].sample_size = + edid_caps->audio_modes[i].sample_size; + } + } + + audio_info->flags.all = edid_caps->speaker_flags; + + /* TODO: We only check for the progressive mode, check for interlace mode too */ + if(drm_connector->latency_present[0]) { + audio_info->video_latency = drm_connector->video_latency[0]; + audio_info->audio_latency = drm_connector->audio_latency[0]; + } + + /* TODO: For DP, video and audio latency should be calculated from DPCD caps */ + +} + +static void copy_crtc_timing_for_drm_display_mode( + const struct drm_display_mode *src_mode, + struct drm_display_mode *dst_mode) +{ + dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay; + dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay; + dst_mode->crtc_clock = src_mode->crtc_clock; + dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start; + dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end; + dst_mode->crtc_hsync_start= src_mode->crtc_hsync_start; + dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; + dst_mode->crtc_htotal = src_mode->crtc_htotal; + dst_mode->crtc_hskew = src_mode->crtc_hskew; + dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start; + dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end; + dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start; + dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end; + dst_mode->crtc_vtotal = src_mode->crtc_vtotal; +} + +static void decide_crtc_timing_for_drm_display_mode( + struct drm_display_mode *drm_mode, + const struct drm_display_mode *native_mode, + bool scale_enabled) +{ + if (scale_enabled) { + copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); + } else if (native_mode->clock == drm_mode->clock && + native_mode->htotal == drm_mode->htotal && + native_mode->vtotal == drm_mode->vtotal) { + copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); + } else { + /* no scaling nor amdgpu inserted, no need to patch */ + } +} + +static struct dc_stream *create_stream_for_sink( + struct amdgpu_connector *aconnector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state) +{ + struct drm_display_mode *preferred_mode = NULL; + const struct drm_connector *drm_connector; + struct dc_stream *stream = NULL; + struct drm_display_mode mode = *drm_mode; + bool native_mode_found = false; + + if (NULL == aconnector) { + DRM_ERROR("aconnector is NULL!\n"); + goto drm_connector_null; + } + + if (NULL == dm_state) { + DRM_ERROR("dm_state is NULL!\n"); + goto dm_state_null; + } + drm_connector = &aconnector->base; + stream = dc_create_stream_for_sink(aconnector->dc_sink); + if (NULL == stream) { + DRM_ERROR("Failed to create stream for sink!\n"); + goto stream_create_fail; + } + + list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { + /* Search for preferred mode */ + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { + native_mode_found = true; + break; + } + } + if (!native_mode_found) + preferred_mode = list_first_entry_or_null( + &aconnector->base.modes, + struct drm_display_mode, + head); + + if (NULL == preferred_mode) { + /* This may not be an error, the use case is when we we have no + * usermode calls to reset and set mode upon hotplug. In this + * case, we call set mode ourselves to restore the previous mode + * and the modelist may not be filled in in time. + */ + DRM_INFO("No preferred mode found\n"); + } else { + decide_crtc_timing_for_drm_display_mode( + &mode, preferred_mode, + dm_state->scaling != RMX_OFF); + } + + fill_stream_properties_from_drm_display_mode(stream, + &mode, &aconnector->base); + update_stream_scaling_settings(&mode, dm_state, stream); + + fill_audio_info( + &stream->audio_info, + drm_connector, + aconnector->dc_sink); + +stream_create_fail: +dm_state_null: +drm_connector_null: + return stream; +} + +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) +{ + drm_crtc_cleanup(crtc); + kfree(crtc); +} + +static void dm_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct dm_crtc_state *cur = to_dm_crtc_state(state); + + /* TODO Destroy dc_stream objects are stream object is flattened */ + if (cur->stream) + dc_stream_release(cur->stream); + + + __drm_atomic_helper_crtc_destroy_state(state); + + + kfree(state); +} + +static void dm_crtc_reset_state(struct drm_crtc *crtc) +{ + struct dm_crtc_state *state; + + if (crtc->state) + dm_crtc_destroy_state(crtc, crtc->state); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (WARN_ON(!state)) + return; + + crtc->state = &state->base; + crtc->state->crtc = crtc; + +} + +static struct drm_crtc_state * +dm_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct dm_crtc_state *state, *cur; + + cur = to_dm_crtc_state(crtc->state); + + if (WARN_ON(!crtc->state)) + return NULL; + + state = dm_alloc(sizeof(*state)); + + __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); + + if (cur->stream) { + state->stream = cur->stream; + dc_stream_retain(state->stream); + } + + /* TODO Duplicate dc_stream after objects are stream object is flattened */ + + return &state->base; +} + +/* Implemented only the options currently availible for the driver */ +static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { + .reset = dm_crtc_reset_state, + .destroy = amdgpu_dm_crtc_destroy, + .gamma_set = drm_atomic_helper_legacy_gamma_set, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = dm_crtc_duplicate_state, + .atomic_destroy_state = dm_crtc_destroy_state, +}; + +static enum drm_connector_status +amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) +{ + bool connected; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + /* Notes: + * 1. This interface is NOT called in context of HPD irq. + * 2. This interface *is called* in context of user-mode ioctl. Which + * makes it a bad place for *any* MST-related activit. */ + + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + connected = (aconnector->dc_sink != NULL); + else + connected = (aconnector->base.force == DRM_FORCE_ON); + + return (connected ? connector_status_connected : + connector_status_disconnected); +} + +int amdgpu_dm_connector_atomic_set_property( + struct drm_connector *connector, + struct drm_connector_state *connector_state, + struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct dm_connector_state *dm_old_state = + to_dm_connector_state(connector->state); + struct dm_connector_state *dm_new_state = + to_dm_connector_state(connector_state); + + int ret = -EINVAL; + + if (property == dev->mode_config.scaling_mode_property) { + enum amdgpu_rmx_type rmx_type; + + switch (val) { + case DRM_MODE_SCALE_CENTER: + rmx_type = RMX_CENTER; + break; + case DRM_MODE_SCALE_ASPECT: + rmx_type = RMX_ASPECT; + break; + case DRM_MODE_SCALE_FULLSCREEN: + rmx_type = RMX_FULL; + break; + case DRM_MODE_SCALE_NONE: + default: + rmx_type = RMX_OFF; + break; + } + + if (dm_old_state->scaling == rmx_type) + return 0; + + dm_new_state->scaling = rmx_type; + ret = 0; + } else if (property == adev->mode_info.underscan_hborder_property) { + dm_new_state->underscan_hborder = val; + ret = 0; + } else if (property == adev->mode_info.underscan_vborder_property) { + dm_new_state->underscan_vborder = val; + ret = 0; + } else if (property == adev->mode_info.underscan_property) { + dm_new_state->underscan_enable = val; + ret = 0; + } + + return ret; +} + +int amdgpu_dm_connector_atomic_get_property( + struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct dm_connector_state *dm_state = + to_dm_connector_state(state); + int ret = -EINVAL; + + if (property == dev->mode_config.scaling_mode_property) { + switch (dm_state->scaling) { + case RMX_CENTER: + *val = DRM_MODE_SCALE_CENTER; + break; + case RMX_ASPECT: + *val = DRM_MODE_SCALE_ASPECT; + break; + case RMX_FULL: + *val = DRM_MODE_SCALE_FULLSCREEN; + break; + case RMX_OFF: + default: + *val = DRM_MODE_SCALE_NONE; + break; + } + ret = 0; + } else if (property == adev->mode_info.underscan_hborder_property) { + *val = dm_state->underscan_hborder; + ret = 0; + } else if (property == adev->mode_info.underscan_vborder_property) { + *val = dm_state->underscan_vborder; + ret = 0; + } else if (property == adev->mode_info.underscan_property) { + *val = dm_state->underscan_enable; + ret = 0; + } + return ret; +} + +void amdgpu_dm_connector_destroy(struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + const struct dc_link *link = aconnector->dc_link; + struct amdgpu_device *adev = connector->dev->dev_private; + struct amdgpu_display_manager *dm = &adev->dm; +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) { + backlight_device_unregister(dm->backlight_dev); + dm->backlight_dev = NULL; + } + + } +#endif + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) +{ + struct dm_connector_state *state = + to_dm_connector_state(connector->state); + + kfree(state); + + state = kzalloc(sizeof(*state), GFP_KERNEL); + + if (state) { + state->scaling = RMX_OFF; + state->underscan_enable = false; + state->underscan_hborder = 0; + state->underscan_vborder = 0; + + connector->state = &state->base; + connector->state->connector = connector; + } +} + +struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( + struct drm_connector *connector) +{ + struct dm_connector_state *state = + to_dm_connector_state(connector->state); + + struct dm_connector_state *new_state = + kmemdup(state, sizeof(*state), GFP_KERNEL); + + if (new_state) { + __drm_atomic_helper_connector_duplicate_state(connector, + &new_state->base); + return &new_state->base; + } + + return NULL; +} + +static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { + .reset = amdgpu_dm_connector_funcs_reset, + .detect = amdgpu_dm_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = amdgpu_dm_connector_destroy, + .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_set_property = amdgpu_dm_connector_atomic_set_property, + .atomic_get_property = amdgpu_dm_connector_atomic_get_property +}; + +static struct drm_encoder *best_encoder(struct drm_connector *connector) +{ + int enc_id = connector->encoder_ids[0]; + struct drm_mode_object *obj; + struct drm_encoder *encoder; + + DRM_DEBUG_KMS("Finding the best encoder\n"); + + /* pick the encoder ids */ + if (enc_id) { + obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); + if (!obj) { + DRM_ERROR("Couldn't find a matching encoder for our connector\n"); + return NULL; + } + encoder = obj_to_encoder(obj); + return encoder; + } + DRM_ERROR("No encoder id\n"); + return NULL; +} + +static int get_modes(struct drm_connector *connector) +{ + return amdgpu_dm_connector_get_modes(connector); +} + +static void create_eml_sink(struct amdgpu_connector *aconnector) +{ + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_VIRTUAL + }; + struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data; + + if (!aconnector->base.edid_blob_ptr || + !aconnector->base.edid_blob_ptr->data) { + DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", + aconnector->base.name); + + aconnector->base.force = DRM_FORCE_OFF; + aconnector->base.override_edid = false; + return; + } + + aconnector->edid = edid; + + aconnector->dc_em_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + + if (aconnector->base.force + == DRM_FORCE_ON) + aconnector->dc_sink = aconnector->dc_link->local_sink ? + aconnector->dc_link->local_sink : + aconnector->dc_em_sink; +} + +static void handle_edid_mgmt(struct amdgpu_connector *aconnector) +{ + struct dc_link *link = (struct dc_link *)aconnector->dc_link; + + /* In case of headless boot with force on for DP managed connector + * Those settings have to be != 0 to get initial modeset + */ + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) { + link->verified_link_cap.lane_count = LANE_COUNT_FOUR; + link->verified_link_cap.link_rate = LINK_RATE_HIGH2; + } + + + aconnector->base.override_edid = true; + create_eml_sink(aconnector); +} + +int amdgpu_dm_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode) +{ + int result = MODE_ERROR; + struct dc_sink *dc_sink; + struct amdgpu_device *adev = connector->dev->dev_private; + /* TODO: Unhardcode stream count */ + struct dc_stream *stream; + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || + (mode->flags & DRM_MODE_FLAG_DBLSCAN)) + return result; + + /* Only run this the first time mode_valid is called to initilialize + * EDID mgmt + */ + if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && + !aconnector->dc_em_sink) + handle_edid_mgmt(aconnector); + + dc_sink = to_amdgpu_connector(connector)->dc_sink; + + if (NULL == dc_sink) { + DRM_ERROR("dc_sink is NULL!\n"); + goto fail; + } + + stream = dc_create_stream_for_sink(dc_sink); + if (NULL == stream) { + DRM_ERROR("Failed to create stream for sink!\n"); + goto fail; + } + + drm_mode_set_crtcinfo(mode, 0); + fill_stream_properties_from_drm_display_mode(stream, mode, connector); + + stream->src.width = mode->hdisplay; + stream->src.height = mode->vdisplay; + stream->dst = stream->src; + + if (dc_validate_stream(adev->dm.dc, stream)) + result = MODE_OK; + + dc_stream_release(stream); + +fail: + /* TODO: error handling*/ + return result; +} + +static const struct drm_connector_helper_funcs +amdgpu_dm_connector_helper_funcs = { + /* + * If hotplug a second bigger display in FB Con mode, bigger resolution + * modes will be filtered by drm_mode_validate_size(), and those modes + * is missing after user start lightdm. So we need to renew modes list. + * in get_modes call back, not just return the modes count + */ + .get_modes = get_modes, + .mode_valid = amdgpu_dm_connector_mode_valid, + .best_encoder = best_encoder +}; + +static void dm_crtc_helper_disable(struct drm_crtc *crtc) +{ +} + +static int dm_crtc_helper_atomic_check( + struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct amdgpu_device *adev = crtc->dev->dev_private; + struct dc *dc = adev->dm.dc; + struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); + int ret = -EINVAL; + + if (unlikely(!dm_crtc_state->stream && modeset_required(state))) { + WARN_ON(1); + return ret; + } + + /* In some use cases, like reset, no stream is attached */ + if (!dm_crtc_state->stream) + return 0; + + if (dc_validate_stream(dc, dm_crtc_state->stream)) + return 0; + + return ret; +} + +static bool dm_crtc_helper_mode_fixup( + struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = { + .disable = dm_crtc_helper_disable, + .atomic_check = dm_crtc_helper_atomic_check, + .mode_fixup = dm_crtc_helper_mode_fixup +}; + +static void dm_encoder_helper_disable(struct drm_encoder *encoder) +{ + +} + +static int dm_encoder_helper_atomic_check( + struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + return 0; +} + +const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { + .disable = dm_encoder_helper_disable, + .atomic_check = dm_encoder_helper_atomic_check +}; + +static void dm_drm_plane_reset(struct drm_plane *plane) +{ + struct dm_plane_state *amdgpu_state = NULL; + + if (plane->state) + plane->funcs->atomic_destroy_state(plane, plane->state); + + amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); + + if (amdgpu_state) { + plane->state = &amdgpu_state->base; + plane->state->plane = plane; + plane->state->rotation = DRM_MODE_ROTATE_0; + } else + WARN_ON(1); +} + +static struct drm_plane_state * +dm_drm_plane_duplicate_state(struct drm_plane *plane) +{ + struct dm_plane_state *dm_plane_state, *old_dm_plane_state; + + old_dm_plane_state = to_dm_plane_state(plane->state); + dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); + if (!dm_plane_state) + return NULL; + + __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); + + if (old_dm_plane_state->surface) { + dm_plane_state->surface = old_dm_plane_state->surface; + dc_surface_retain(dm_plane_state->surface); + } + + return &dm_plane_state->base; +} + +void dm_drm_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); + + if (dm_plane_state->surface) + dc_surface_release(dm_plane_state->surface); + + __drm_atomic_helper_plane_destroy_state(state); + kfree(dm_plane_state); +} + +static const struct drm_plane_funcs dm_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = dm_drm_plane_reset, + .atomic_duplicate_state = dm_drm_plane_duplicate_state, + .atomic_destroy_state = dm_drm_plane_destroy_state, +}; + +static int dm_plane_helper_prepare_fb( + struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct amdgpu_framebuffer *afb; + struct drm_gem_object *obj; + struct amdgpu_bo *rbo; + int r; + struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; + unsigned int awidth; + + dm_plane_state_old = to_dm_plane_state(plane->state); + dm_plane_state_new = to_dm_plane_state(new_state); + + if (!new_state->fb) { + DRM_DEBUG_KMS("No FB bound\n"); + return 0; + } + + afb = to_amdgpu_framebuffer(new_state->fb); + + obj = afb->obj; + rbo = gem_to_amdgpu_bo(obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; + + r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &afb->address); + + + amdgpu_bo_unreserve(rbo); + + if (unlikely(r != 0)) { + DRM_ERROR("Failed to pin framebuffer\n"); + return r; + } + + amdgpu_bo_ref(rbo); + + if (dm_plane_state_new->surface && + dm_plane_state_old->surface != dm_plane_state_new->surface) { + struct dc_surface *surface = dm_plane_state_new->surface; + + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + surface->address.grph.addr.low_part = lower_32_bits(afb->address); + surface->address.grph.addr.high_part = upper_32_bits(afb->address); + } else { + awidth = ALIGN(new_state->fb->width, 64); + surface->address.video_progressive.luma_addr.low_part + = lower_32_bits(afb->address); + surface->address.video_progressive.chroma_addr.low_part + = lower_32_bits(afb->address) + + (awidth * new_state->fb->height); + } + } + + /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer + * prepare and cleanup in drm_atomic_helper_prepare_planes + * and drm_atomic_helper_cleanup_planes because fb doens't in s3. + * IN 4.10 kernel this code should be removed and amdgpu_device_suspend + * code touching fram buffers should be avoided for DC. + */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_state->crtc); + + acrtc->cursor_bo = obj; + } + return 0; +} + +static void dm_plane_helper_cleanup_fb( + struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct amdgpu_bo *rbo; + struct amdgpu_framebuffer *afb; + int r; + + if (!old_state->fb) + return; + + afb = to_amdgpu_framebuffer(old_state->fb); + rbo = gem_to_amdgpu_bo(afb->obj); + r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) { + DRM_ERROR("failed to reserve rbo before unpin\n"); + return; + } else { + amdgpu_bo_unpin(rbo); + amdgpu_bo_unreserve(rbo); + amdgpu_bo_unref(&rbo); + }; +} + +int dm_create_validation_set_for_connector(struct drm_connector *connector, + struct drm_display_mode *mode, struct dc_validation_set *val_set) +{ + int result = MODE_ERROR; + struct dc_sink *dc_sink = + to_amdgpu_connector(connector)->dc_sink; + /* TODO: Unhardcode stream count */ + struct dc_stream *stream; + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || + (mode->flags & DRM_MODE_FLAG_DBLSCAN)) + return result; + + if (NULL == dc_sink) { + DRM_ERROR("dc_sink is NULL!\n"); + return result; + } + + stream = dc_create_stream_for_sink(dc_sink); + + if (NULL == stream) { + DRM_ERROR("Failed to create stream for sink!\n"); + return result; + } + + drm_mode_set_crtcinfo(mode, 0); + + fill_stream_properties_from_drm_display_mode(stream, mode, connector); + + val_set->stream = stream; + + stream->src.width = mode->hdisplay; + stream->src.height = mode->vdisplay; + stream->dst = stream->src; + + return MODE_OK; +} + +static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { + .prepare_fb = dm_plane_helper_prepare_fb, + .cleanup_fb = dm_plane_helper_cleanup_fb, +}; + +/* + * TODO: these are currently initialized to rgb formats only. + * For future use cases we should either initialize them dynamically based on + * plane capabilities, or initialize this array to all formats, so internal drm + * check will succeed, and let DC to implement proper check + */ +static uint32_t rgb_formats[] = { + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, +}; + +static uint32_t yuv_formats[] = { + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, +}; + +static const u32 cursor_formats[] = { + DRM_FORMAT_ARGB8888 +}; + +int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs) +{ + int res = -EPERM; + + switch (aplane->base.type) { + case DRM_PLANE_TYPE_PRIMARY: + aplane->base.format_default = true; + + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + rgb_formats, + ARRAY_SIZE(rgb_formats), + NULL, aplane->base.type, NULL); + break; + case DRM_PLANE_TYPE_OVERLAY: + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + yuv_formats, + ARRAY_SIZE(yuv_formats), + NULL, aplane->base.type, NULL); + break; + case DRM_PLANE_TYPE_CURSOR: + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + cursor_formats, + ARRAY_SIZE(cursor_formats), + NULL, aplane->base.type, NULL); + break; + } + + drm_plane_helper_add(&aplane->base, &dm_plane_helper_funcs); + + return res; +} + +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t crtc_index) +{ + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_plane *cursor_plane; + + int res = -ENOMEM; + + cursor_plane = kzalloc(sizeof(*cursor_plane), GFP_KERNEL); + if (!cursor_plane) + goto fail; + + cursor_plane->base.type = DRM_PLANE_TYPE_CURSOR; + res = amdgpu_dm_plane_init(dm, cursor_plane, 0); + + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); + if (!acrtc) + goto fail; + + res = drm_crtc_init_with_planes( + dm->ddev, + &acrtc->base, + plane, + &cursor_plane->base, + &amdgpu_dm_crtc_funcs, NULL); + + if (res) + goto fail; + + drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); + + acrtc->max_cursor_width = dm->adev->dm.dc->caps.max_cursor_size; + acrtc->max_cursor_height = dm->adev->dm.dc->caps.max_cursor_size; + + acrtc->crtc_id = crtc_index; + acrtc->base.enabled = false; + + dm->adev->mode_info.crtcs[crtc_index] = acrtc; + drm_mode_crtc_set_gamma_size(&acrtc->base, 256); + + return 0; + +fail: + if (acrtc) + kfree(acrtc); + if (cursor_plane) + kfree(cursor_plane); + acrtc->crtc_id = -1; + return res; +} + + +static int to_drm_connector_type(enum signal_type st) +{ + switch (st) { + case SIGNAL_TYPE_HDMI_TYPE_A: + return DRM_MODE_CONNECTOR_HDMIA; + case SIGNAL_TYPE_EDP: + return DRM_MODE_CONNECTOR_eDP; + case SIGNAL_TYPE_RGB: + return DRM_MODE_CONNECTOR_VGA; + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + return DRM_MODE_CONNECTOR_DisplayPort; + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_DVI_SINGLE_LINK: + return DRM_MODE_CONNECTOR_DVID; + case SIGNAL_TYPE_VIRTUAL: + return DRM_MODE_CONNECTOR_VIRTUAL; + + default: + return DRM_MODE_CONNECTOR_Unknown; + } +} + +static void amdgpu_dm_get_native_mode(struct drm_connector *connector) +{ + const struct drm_connector_helper_funcs *helper = + connector->helper_private; + struct drm_encoder *encoder; + struct amdgpu_encoder *amdgpu_encoder; + + encoder = helper->best_encoder(connector); + + if (encoder == NULL) + return; + + amdgpu_encoder = to_amdgpu_encoder(encoder); + + amdgpu_encoder->native_mode.clock = 0; + + if (!list_empty(&connector->probed_modes)) { + struct drm_display_mode *preferred_mode = NULL; + list_for_each_entry(preferred_mode, + &connector->probed_modes, + head) { + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { + amdgpu_encoder->native_mode = *preferred_mode; + } + break; + } + + } +} + +static struct drm_display_mode *amdgpu_dm_create_common_mode( + struct drm_encoder *encoder, char *name, + int hdisplay, int vdisplay) +{ + struct drm_device *dev = encoder->dev; + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; + + mode = drm_mode_duplicate(dev, native_mode); + + if(mode == NULL) + return NULL; + + mode->hdisplay = hdisplay; + mode->vdisplay = vdisplay; + mode->type &= ~DRM_MODE_TYPE_PREFERRED; + strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN); + + return mode; + +} + +static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); + struct drm_display_mode *mode = NULL; + struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + int i; + int n; + struct mode_size { + char name[DRM_DISPLAY_MODE_LEN]; + int w; + int h; + }common_modes[] = { + { "640x480", 640, 480}, + { "800x600", 800, 600}, + { "1024x768", 1024, 768}, + { "1280x720", 1280, 720}, + { "1280x800", 1280, 800}, + {"1280x1024", 1280, 1024}, + { "1440x900", 1440, 900}, + {"1680x1050", 1680, 1050}, + {"1600x1200", 1600, 1200}, + {"1920x1080", 1920, 1080}, + {"1920x1200", 1920, 1200} + }; + + n = sizeof(common_modes) / sizeof(common_modes[0]); + + for (i = 0; i < n; i++) { + struct drm_display_mode *curmode = NULL; + bool mode_existed = false; + + if (common_modes[i].w > native_mode->hdisplay || + common_modes[i].h > native_mode->vdisplay || + (common_modes[i].w == native_mode->hdisplay && + common_modes[i].h == native_mode->vdisplay)) + continue; + + list_for_each_entry(curmode, &connector->probed_modes, head) { + if (common_modes[i].w == curmode->hdisplay && + common_modes[i].h == curmode->vdisplay) { + mode_existed = true; + break; + } + } + + if (mode_existed) + continue; + + mode = amdgpu_dm_create_common_mode(encoder, + common_modes[i].name, common_modes[i].w, + common_modes[i].h); + drm_mode_probed_add(connector, mode); + amdgpu_connector->num_modes++; + } +} + +static void amdgpu_dm_connector_ddc_get_modes( + struct drm_connector *connector, + struct edid *edid) +{ + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + if (edid) { + /* empty probed_modes */ + INIT_LIST_HEAD(&connector->probed_modes); + amdgpu_connector->num_modes = + drm_add_edid_modes(connector, edid); + + drm_edid_to_eld(connector, edid); + + amdgpu_dm_get_native_mode(connector); + } else + amdgpu_connector->num_modes = 0; +} + +int amdgpu_dm_connector_get_modes(struct drm_connector *connector) +{ + const struct drm_connector_helper_funcs *helper = + connector->helper_private; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + struct drm_encoder *encoder; + struct edid *edid = amdgpu_connector->edid; + + encoder = helper->best_encoder(connector); + + amdgpu_dm_connector_ddc_get_modes(connector, edid); + amdgpu_dm_connector_add_common_modes(encoder, connector); + return amdgpu_connector->num_modes; +} + +void amdgpu_dm_connector_init_helper( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + int connector_type, + struct dc_link *link, + int link_index) +{ + struct amdgpu_device *adev = dm->ddev->dev_private; + + aconnector->connector_id = link_index; + aconnector->dc_link = link; + aconnector->base.interlace_allowed = false; + aconnector->base.doublescan_allowed = false; + aconnector->base.stereo_allowed = false; + aconnector->base.dpms = DRM_MODE_DPMS_OFF; + aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ + + mutex_init(&aconnector->hpd_lock); + + /*configure suport HPD hot plug connector_>polled default value is 0 + * which means HPD hot plug not supported*/ + switch (connector_type) { + case DRM_MODE_CONNECTOR_HDMIA: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + case DRM_MODE_CONNECTOR_DisplayPort: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + case DRM_MODE_CONNECTOR_DVID: + aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; + break; + default: + break; + } + + drm_object_attach_property(&aconnector->base.base, + dm->ddev->mode_config.scaling_mode_property, + DRM_MODE_SCALE_NONE); + + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_property, + UNDERSCAN_OFF); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_hborder_property, + 0); + drm_object_attach_property(&aconnector->base.base, + adev->mode_info.underscan_vborder_property, + 0); + +} + +int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); + struct ddc_service *ddc_service = i2c->ddc_service; + struct i2c_command cmd; + int i; + int result = -EIO; + + cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL); + + if (!cmd.payloads) + return result; + + cmd.number_of_payloads = num; + cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; + cmd.speed = 100; + + for (i = 0; i < num; i++) { + cmd.payloads[i].write = !(msgs[i].flags & I2C_M_RD); + cmd.payloads[i].address = msgs[i].addr; + cmd.payloads[i].length = msgs[i].len; + cmd.payloads[i].data = msgs[i].buf; + } + + if (dal_i2caux_submit_i2c_command( + ddc_service->ctx->i2caux, + ddc_service->ddc_pin, + &cmd)) + result = num; + + kfree(cmd.payloads); + return result; +} + +u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm amdgpu_dm_i2c_algo = { + .master_xfer = amdgpu_dm_i2c_xfer, + .functionality = amdgpu_dm_i2c_func, +}; + +static struct amdgpu_i2c_adapter *create_i2c( + struct ddc_service *ddc_service, + int link_index, + int *res) +{ + struct amdgpu_device *adev = ddc_service->ctx->driver_context; + struct amdgpu_i2c_adapter *i2c; + + i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); + i2c->base.owner = THIS_MODULE; + i2c->base.class = I2C_CLASS_DDC; + i2c->base.dev.parent = &adev->pdev->dev; + i2c->base.algo = &amdgpu_dm_i2c_algo; + snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); + i2c_set_adapdata(&i2c->base, i2c); + i2c->ddc_service = ddc_service; + + return i2c; +} + +/* Note: this function assumes that dc_link_detect() was called for the + * dc_link which will be represented by this aconnector. */ +int amdgpu_dm_connector_init( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + uint32_t link_index, + struct amdgpu_encoder *aencoder) +{ + int res = 0; + int connector_type; + struct dc *dc = dm->dc; + struct dc_link *link = dc_get_link_at_index(dc, link_index); + struct amdgpu_i2c_adapter *i2c; + ((struct dc_link *)link)->priv = aconnector; + + DRM_DEBUG_KMS("%s()\n", __func__); + + i2c = create_i2c(link->ddc, link->link_index, &res); + aconnector->i2c = i2c; + res = i2c_add_adapter(&i2c->base); + + if (res) { + DRM_ERROR("Failed to register hw i2c %d\n", link->link_index); + goto out_free; + } + + connector_type = to_drm_connector_type(link->connector_signal); + + res = drm_connector_init( + dm->ddev, + &aconnector->base, + &amdgpu_dm_connector_funcs, + connector_type); + + if (res) { + DRM_ERROR("connector_init failed\n"); + aconnector->connector_id = -1; + goto out_free; + } + + drm_connector_helper_add( + &aconnector->base, + &amdgpu_dm_connector_helper_funcs); + + amdgpu_dm_connector_init_helper( + dm, + aconnector, + connector_type, + link, + link_index); + + drm_mode_connector_attach_encoder( + &aconnector->base, &aencoder->base); + + drm_connector_register(&aconnector->base); + + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort + || connector_type == DRM_MODE_CONNECTOR_eDP) + amdgpu_dm_initialize_dp_connector(dm, aconnector); + +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + /* NOTE: this currently will create backlight device even if a panel + * is not connected to the eDP/LVDS connector. + * + * This is less than ideal but we don't have sink information at this + * stage since detection happens after. We can't do detection earlier + * since MST detection needs connectors to be created first. + */ + if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + /* Event if registration failed, we should continue with + * DM initialization because not having a backlight control + * is better then a black screen. */ + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) + dm->backlight_link = link; + } +#endif + +out_free: + if (res) { + kfree(i2c); + aconnector->i2c = NULL; + } + return res; +} + +int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) +{ + switch (adev->mode_info.num_crtc) { + case 1: + return 0x1; + case 2: + return 0x3; + case 3: + return 0x7; + case 4: + return 0xf; + case 5: + return 0x1f; + case 6: + default: + return 0x3f; + } +} + +int amdgpu_dm_encoder_init( + struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index) +{ + struct amdgpu_device *adev = dev->dev_private; + + int res = drm_encoder_init(dev, + &aencoder->base, + &amdgpu_dm_encoder_funcs, + DRM_MODE_ENCODER_TMDS, + NULL); + + aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); + + if (!res) + aencoder->encoder_id = link_index; + else + aencoder->encoder_id = -1; + + drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs); + + return res; +} + +static void manage_dm_interrupts( + struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + bool enable) +{ + /* + * this is not correct translation but will work as soon as VBLANK + * constant is the same as PFLIP + */ + int irq_type = + amdgpu_crtc_idx_to_irq_type( + adev, + acrtc->crtc_id); + + if (enable) { + drm_crtc_vblank_on(&acrtc->base); + amdgpu_irq_get( + adev, + &adev->pageflip_irq, + irq_type); + } else { + + amdgpu_irq_put( + adev, + &adev->pageflip_irq, + irq_type); + drm_crtc_vblank_off(&acrtc->base); + } +} + +static bool is_scaling_state_different( + const struct dm_connector_state *dm_state, + const struct dm_connector_state *old_dm_state) +{ + if (dm_state->scaling != old_dm_state->scaling) + return true; + if (!dm_state->underscan_enable && old_dm_state->underscan_enable) { + if (old_dm_state->underscan_hborder != 0 && old_dm_state->underscan_vborder != 0) + return true; + } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) { + if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0) + return true; + } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder + || dm_state->underscan_vborder != old_dm_state->underscan_vborder) + return true; + return false; +} + +static void remove_stream( + struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + struct dc_stream *stream) +{ + /* this is the update mode case */ + if (adev->dm.freesync_module) + mod_freesync_remove_stream(adev->dm.freesync_module, stream); + + acrtc->otg_inst = -1; + acrtc->enabled = false; +} + +static void handle_cursor_update( + struct drm_plane *plane, + struct drm_plane_state *old_plane_state) +{ + if (!plane->state->fb && !old_plane_state->fb) + return; + + /* Check if it's a cursor on/off update or just cursor move*/ + if (plane->state->fb == old_plane_state->fb) + dm_crtc_cursor_move( + plane->state->crtc, + plane->state->crtc_x, + plane->state->crtc_y); + else { + struct amdgpu_framebuffer *afb = + to_amdgpu_framebuffer(plane->state->fb); + dm_crtc_cursor_set( + (!!plane->state->fb) ? + plane->state->crtc : + old_plane_state->crtc, + (!!plane->state->fb) ? + afb->address : + 0, + plane->state->crtc_w, + plane->state->crtc_h); + } +} + + +static void prepare_flip_isr(struct amdgpu_crtc *acrtc) +{ + + assert_spin_locked(&acrtc->base.dev->event_lock); + WARN_ON(acrtc->event); + + acrtc->event = acrtc->base.state->event; + + /* Set the flip status */ + acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; + + /* Mark this event as consumed */ + acrtc->base.state->event = NULL; + + DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", + acrtc->crtc_id); +} + +/* + * Executes flip + * + * Waits on all BO's fences and for proper vblank count + */ +static void amdgpu_dm_do_flip( + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + uint32_t target) +{ + unsigned long flags; + uint32_t target_vblank; + int r, vpos, hpos; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); + struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); + struct amdgpu_device *adev = crtc->dev->dev_private; + bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + struct dc_flip_addrs addr = { {0} }; + struct dc_surface_update surface_updates[1] = { {0} }; + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); + + + /* Prepare wait for target vblank early - before the fence-waits */ + target_vblank = target - drm_crtc_vblank_count(crtc) + + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); + + /*TODO This might fail and hence better not used, wait + * explicitly on fences instead + * and in general should be called for + * blocking commit to as per framework helpers + * */ + r = amdgpu_bo_reserve(abo, true); + if (unlikely(r != 0)) { + DRM_ERROR("failed to reserve buffer before flip\n"); + WARN_ON(1); + } + + /* Wait for all fences on this FB */ + WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false, + MAX_SCHEDULE_TIMEOUT) < 0); + + amdgpu_bo_unreserve(abo); + + /* Wait until we're out of the vertical blank period before the one + * targeted by the flip + */ + while ((acrtc->enabled && + (amdgpu_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id, 0, + &vpos, &hpos, NULL, NULL, + &crtc->hwmode) + & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == + (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && + (int)(target_vblank - + amdgpu_get_vblank_counter_kms(adev->ddev, acrtc->crtc_id)) > 0)) { + usleep_range(1000, 1100); + } + + /* Flip */ + spin_lock_irqsave(&crtc->dev->event_lock, flags); + /* update crtc fb */ + crtc->primary->fb = fb; + + WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); + WARN_ON(!acrtc_state->stream); + + addr.address.grph.addr.low_part = lower_32_bits(afb->address); + addr.address.grph.addr.high_part = upper_32_bits(afb->address); + addr.flip_immediate = async_flip; + + + if (acrtc->base.state->event) + prepare_flip_isr(acrtc); + + surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0]; + surface_updates->flip_addr = &addr; + + + dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); + + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", + __func__, + addr.address.grph.addr.high_part, + addr.address.grph.addr.low_part); + + + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); +} + +static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, + struct drm_device *dev, + struct amdgpu_display_manager *dm, + struct drm_crtc *pcrtc, + bool *wait_for_vblank) +{ + uint32_t i; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state; + struct dc_stream *dc_stream_attach; + struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); + int planes_count = 0; + unsigned long flags; + + /* update planes when needed */ + for_each_plane_in_state(state, plane, old_plane_state, i) { + struct drm_plane_state *plane_state = plane->state; + struct drm_crtc *crtc = plane_state->crtc; + struct drm_framebuffer *fb = plane_state->fb; + bool pflip_needed; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + handle_cursor_update(plane, old_plane_state); + continue; + } + + if (!fb || !crtc || pcrtc != crtc || !crtc->state->active || + (!crtc->state->planes_changed && + !pcrtc->state->color_mgmt_changed)) + continue; + + pflip_needed = !state->allow_modeset; + + spin_lock_irqsave(&crtc->dev->event_lock, flags); + if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) { + DRM_ERROR("add_surface: acrtc %d, already busy\n", + acrtc_attach->crtc_id); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + /* In comit tail framework this cannot happen */ + WARN_ON(1); + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + if (!pflip_needed) { + WARN_ON(!dm_plane_state->surface); + + dc_surfaces_constructed[planes_count] = dm_plane_state->surface; + + dc_stream_attach = acrtc_state->stream; + planes_count++; + + } else if (crtc->state->planes_changed) { + /* Assume even ONE crtc with immediate flip means + * entire can't wait for VBLANK + * TODO Check if it's correct + */ + *wait_for_vblank = + acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + false : true; + + /* TODO: Needs rework for multiplane flip */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + drm_crtc_vblank_get(crtc); + + amdgpu_dm_do_flip( + crtc, + fb, + drm_crtc_vblank_count(crtc) + *wait_for_vblank); + + /*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */ + + /*clean up the flags for next usage*/ + acrtc_attach->flip_flags = 0; + } + + } + + if (planes_count) { + unsigned long flags; + + if (pcrtc->state->event) { + + drm_crtc_vblank_get(pcrtc); + + spin_lock_irqsave(&pcrtc->dev->event_lock, flags); + prepare_flip_isr(acrtc_attach); + spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); + } + + if (false == dc_commit_surfaces_to_stream(dm->dc, + dc_surfaces_constructed, + planes_count, + dc_stream_attach)) + dm_error("%s: Failed to attach surface!\n", __func__); + } else { + /*TODO BUG Here should go disable planes on CRTC. */ + } +} + + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_state; + struct amdgpu_device *adev = dev->dev_private; + int i; + + /* + * We evade vblanks and pflips on crtc that + * should be changed. We do it here to flush & disable + * interrupts before drm_swap_state is called in drm_atomic_helper_commit + * it will update crtc->dm_crtc_state->stream pointer which is used in + * the ISRs. + */ + for_each_crtc_in_state(state, crtc, new_state, i) { + struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) + manage_dm_interrupts(adev, acrtc, false); + } + + return drm_atomic_helper_commit(dev, state, nonblock); + + /*TODO Handle EINTR, reenable IRQ*/ +} + +void amdgpu_dm_atomic_commit_tail( + struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_display_manager *dm = &adev->dm; + struct dm_atomic_state *dm_state; + uint32_t i, j; + uint32_t new_crtcs_count = 0; + struct drm_crtc *crtc, *pcrtc; + struct drm_crtc_state *old_crtc_state; + struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; + struct dc_stream *new_stream = NULL; + unsigned long flags; + bool wait_for_vblank = true; + struct drm_connector *connector; + struct drm_connector_state *old_conn_state; + struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + + drm_atomic_helper_update_legacy_modeset_state(dev, state); + + dm_state = to_dm_atomic_state(state); + + /* update changed items */ + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct drm_crtc_state *new_state = crtc->state; + new_acrtc_state = to_dm_crtc_state(new_state); + old_acrtc_state = to_dm_crtc_state(old_crtc_state); + + DRM_DEBUG_KMS( + "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " + "planes_changed:%d, mode_changed:%d,active_changed:%d," + "connectors_changed:%d\n", + acrtc->crtc_id, + new_state->enable, + new_state->active, + new_state->planes_changed, + new_state->mode_changed, + new_state->active_changed, + new_state->connectors_changed); + + /* handles headless hotplug case, updating new_state and + * aconnector as needed + */ + + if (modeset_required(new_state)) { + + DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); + + if (!new_acrtc_state->stream) { + /* + * this could happen because of issues with + * userspace notifications delivery. + * In this case userspace tries to set mode on + * display which is disconnect in fact. + * dc_sink in NULL in this case on aconnector. + * We expect reset mode will come soon. + * + * This can also happen when unplug is done + * during resume sequence ended + * + * In this case, we want to pretend we still + * have a sink to keep the pipe running so that + * hw state is consistent with the sw state + */ + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + continue; + } + + + if (old_acrtc_state->stream) + remove_stream(adev, acrtc, old_acrtc_state->stream); + + + /* + * this loop saves set mode crtcs + * we needed to enable vblanks once all + * resources acquired in dc after dc_commit_streams + */ + + /*TODO move all this into dm_crtc_state, get rid of + * new_crtcs array and use old and new atomic states + * instead + */ + new_crtcs[new_crtcs_count] = acrtc; + new_crtcs_count++; + + acrtc->enabled = true; + acrtc->hw_mode = crtc->state->mode; + crtc->hwmode = crtc->state->mode; + } else if (modereset_required(new_state)) { + DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); + + /* i.e. reset mode */ + if (old_acrtc_state->stream) + remove_stream(adev, acrtc, old_acrtc_state->stream); + } + } /* for_each_crtc_in_state() */ + + /* + * Add streams after required streams from new and replaced streams + * are removed from freesync module + */ + if (adev->dm.freesync_module) { + for (i = 0; i < new_crtcs_count; i++) { + struct amdgpu_connector *aconnector = NULL; + new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); + + new_stream = new_acrtc_state->stream; + aconnector = + amdgpu_dm_find_first_crct_matching_connector( + state, + &new_crtcs[i]->base, + false); + if (!aconnector) { + DRM_INFO( + "Atomic commit: Failed to find connector for acrtc id:%d " + "skipping freesync init\n", + new_crtcs[i]->crtc_id); + continue; + } + + mod_freesync_add_stream(adev->dm.freesync_module, + new_stream, &aconnector->caps); + } + } + + if (dm_state->context) + WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); + + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + new_acrtc_state = to_dm_crtc_state(crtc->state); + + if (new_acrtc_state->stream != NULL) { + const struct dc_stream_status *status = + dc_stream_get_status(new_acrtc_state->stream); + + if (!status) + DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc); + else + acrtc->otg_inst = status->primary_otg_inst; + } + } + + /* Handle scaling and undersacn changes*/ + for_each_connector_in_state(state, connector, old_conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_new_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_old_state = + to_dm_connector_state(old_conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + struct dc_stream_status *status = NULL; + + /* Skip any modesets/resets */ + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + continue; + + /* Skip any thing not scale or underscan changes */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + + update_stream_scaling_settings(&con_new_state->base.crtc->mode, + con_new_state, (struct dc_stream *)new_acrtc_state->stream); + + status = dc_stream_get_status(new_acrtc_state->stream); + WARN_ON(!status); + WARN_ON(!status->surface_count); + + if (!new_acrtc_state->stream) + continue; + + /*TODO How it works with MPO ?*/ + if (!dc_commit_surfaces_to_stream( + dm->dc, + status->surfaces, + status->surface_count, + new_acrtc_state->stream)) + dm_error("%s: Failed to update stream scaling!\n", __func__); + } + + for (i = 0; i < new_crtcs_count; i++) { + /* + * loop to enable interrupts on newly arrived crtc + */ + struct amdgpu_crtc *acrtc = new_crtcs[i]; + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + + if (adev->dm.freesync_module) + mod_freesync_notify_mode_change( + adev->dm.freesync_module, &new_acrtc_state->stream, 1); + + manage_dm_interrupts(adev, acrtc, true); + } + + /* update planes when needed per crtc*/ + for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { + new_acrtc_state = to_dm_crtc_state(pcrtc->state); + + if (new_acrtc_state->stream) + amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + } + + + /* + * send vblank event on all events not handled in flip and + * mark consumed event for drm_atomic_helper_commit_hw_done + */ + spin_lock_irqsave(&adev->ddev->event_lock, flags); + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (acrtc->base.state->event) + drm_send_event_locked(dev, &crtc->state->event->base); + + acrtc->base.state->event = NULL; + } + spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + + /* Signal HW programming completion */ + drm_atomic_helper_commit_hw_done(state); + + if (wait_for_vblank) + drm_atomic_helper_wait_for_vblanks(dev, state); + + drm_atomic_helper_cleanup_planes(dev, state); +} + + +static int dm_force_atomic_commit(struct drm_connector *connector) +{ + int ret = 0; + struct drm_device *ddev = connector->dev; + struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); + struct amdgpu_crtc *disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + struct drm_plane *plane = disconnected_acrtc->base.primary; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + struct drm_plane_state *plane_state; + + if (!state) + return -ENOMEM; + + state->acquire_ctx = ddev->mode_config.acquire_ctx; + + /* Construct an atomic state to restore previous display setting */ + + /* + * Attach connectors to drm_atomic_state + */ + conn_state = drm_atomic_get_connector_state(state, connector); + + ret = PTR_ERR_OR_ZERO(conn_state); + if (ret) + goto err; + + /* Attach crtc to drm_atomic_state*/ + crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base); + + ret = PTR_ERR_OR_ZERO(crtc_state); + if (ret) + goto err; + + /* force a restore */ + crtc_state->mode_changed = true; + + /* Attach plane to drm_atomic_state */ + plane_state = drm_atomic_get_plane_state(state, plane); + + ret = PTR_ERR_OR_ZERO(plane_state); + if (ret) + goto err; + + + /* Call commit internally with the state we just constructed */ + ret = drm_atomic_commit(state); + if (!ret) + return 0; + +err: + DRM_ERROR("Restoring old state failed with %i\n", ret); + drm_atomic_state_put(state); + + return ret; +} + +/* + * This functions handle all cases when set mode does not come upon hotplug. + * This include when the same display is unplugged then plugged back into the + * same port and when we are running without usermode desktop manager supprot + */ +void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) +{ + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_crtc *disconnected_acrtc; + struct dm_crtc_state *acrtc_state; + + if (!aconnector->dc_sink || !connector->state || !connector->encoder) + return; + + disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); + acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state); + + if (!disconnected_acrtc || !acrtc_state->stream) + return; + + /* + * If the previous sink is not released and different from the current, + * we deduce we are in a state where we can not rely on usermode call + * to turn on the display, so we do it here + */ + if (acrtc_state->stream->sink != aconnector->dc_sink) + dm_force_atomic_commit(&aconnector->base); +} + +static uint32_t add_val_sets_surface( + struct dc_validation_set *val_sets, + uint32_t set_count, + const struct dc_stream *stream, + struct dc_surface *surface) +{ + uint32_t i = 0, j = 0; + + while (i < set_count) { + if (val_sets[i].stream == stream) { + while (val_sets[i].surfaces[j]) + j++; + break; + } + ++i; + } + + val_sets[i].surfaces[j] = surface; + val_sets[i].surface_count++; + + return val_sets[i].surface_count; +} + +static uint32_t update_in_val_sets_stream( + struct dc_validation_set *val_sets, + uint32_t set_count, + struct dc_stream *old_stream, + struct dc_stream *new_stream, + struct drm_crtc *crtc) +{ + uint32_t i = 0; + + while (i < set_count) { + if (val_sets[i].stream == old_stream) + break; + ++i; + } + + val_sets[i].stream = new_stream; + + if (i == set_count) + /* nothing found. add new one to the end */ + return set_count + 1; + + return set_count; +} + +static uint32_t remove_from_val_sets( + struct dc_validation_set *val_sets, + uint32_t set_count, + const struct dc_stream *stream) +{ + int i; + + for (i = 0; i < set_count; i++) + if (val_sets[i].stream == stream) + break; + + if (i == set_count) { + /* nothing found */ + return set_count; + } + + set_count--; + + for (; i < set_count; i++) { + val_sets[i] = val_sets[i + 1]; + } + + return set_count; +} + +/*` + * Grabs all modesetting locks to serialize against any blocking commits, + * Waits for completion of all non blocking commits. + */ +static int do_aquire_global_lock( + struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_commit *commit; + long ret; + + /* Adding all modeset locks to aquire_ctx will + * ensure that when the framework release it the + * extra locks we are locking here will get released to + */ + ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx); + if (ret) + return ret; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + spin_lock(&crtc->commit_lock); + commit = list_first_entry_or_null(&crtc->commit_list, + struct drm_crtc_commit, commit_entry); + if (commit) + drm_crtc_commit_get(commit); + spin_unlock(&crtc->commit_lock); + + if (!commit) + continue; + + /* Make sure all pending HW programming completed and + * page flips done + */ + ret = wait_for_completion_interruptible_timeout(&commit->hw_done, 10*HZ); + + if (ret > 0) + ret = wait_for_completion_interruptible_timeout( + &commit->flip_done, 10*HZ); + + if (ret == 0) + DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done " + "timed out\n", crtc->base.id, crtc->name); + + drm_crtc_commit_put(commit); + } + + return ret < 0 ? ret : 0; +} + +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + struct dm_atomic_state *dm_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + int i, j; + int ret; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + int set_count; + struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; + struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + + /* + * This bool will be set for true for any modeset/reset + * or surface update which implies non fast surface update. + */ + bool lock_and_validation_needed = false; + + ret = drm_atomic_helper_check_modeset(dev, state); + + if (ret) { + DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); + return ret; + } + + dm_state = to_dm_atomic_state(state); + + /* copy existing configuration */ + set_count = 0; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + + old_acrtc_state = to_dm_crtc_state(crtc->state); + + if (old_acrtc_state->stream) { + dc_stream_retain(old_acrtc_state->stream); + set[set_count].stream = old_acrtc_state->stream; + ++set_count; + } + } + + /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ + /* update changed items */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_connector *aconnector = NULL; + old_acrtc_state = to_dm_crtc_state(crtc->state); + new_acrtc_state = to_dm_crtc_state(crtc_state); + acrtc = to_amdgpu_crtc(crtc); + + aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); + + DRM_DEBUG_KMS( + "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " + "planes_changed:%d, mode_changed:%d,active_changed:%d," + "connectors_changed:%d\n", + acrtc->crtc_id, + crtc_state->enable, + crtc_state->active, + crtc_state->planes_changed, + crtc_state->mode_changed, + crtc_state->active_changed, + crtc_state->connectors_changed); + + if (modeset_required(crtc_state)) { + + struct dc_stream *new_stream = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; + + if (aconnector) { + conn_state = drm_atomic_get_connector_state(state, &aconnector->base); + if (IS_ERR(conn_state)) { + ret = PTR_ERR_OR_ZERO(conn_state); + goto fail; + } + + dm_conn_state = to_dm_connector_state(conn_state); + } + + new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); + + /* + * we can have no stream on ACTION_SET if a display + * was disconnected during S3, in this case it not and + * error, the OS will be updated after detection, and + * do the right thing on next atomic commit + */ + if (!new_stream) { + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + if (new_acrtc_state->stream) + dc_stream_release(new_acrtc_state->stream); + + new_acrtc_state->stream = new_stream; + + set_count = update_in_val_sets_stream( + set, + set_count, + old_acrtc_state->stream, + new_acrtc_state->stream, + crtc); + + lock_and_validation_needed = true; + + } else if (modereset_required(crtc_state)) { + + /* i.e. reset mode */ + if (new_acrtc_state->stream) { + set_count = remove_from_val_sets( + set, + set_count, + new_acrtc_state->stream); + + dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = NULL; + + lock_and_validation_needed = true; + } + } + + + /* + * Hack: Commit needs planes right now, specifically for gamma + * TODO rework commit to check CRTC for gamma change + */ + if (crtc_state->color_mgmt_changed) { + + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + goto fail; + } + } + + /* Check scaling and undersacn changes*/ + /*TODO Removed scaling changes validation due to inability to commit + * new stream into context w\o causing full reset. Need to + * decide how to handle. + */ + for_each_connector_in_state(state, connector, conn_state, i) { + struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct dm_connector_state *con_old_state = + to_dm_connector_state(aconnector->base.state); + struct dm_connector_state *con_new_state = + to_dm_connector_state(conn_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + + /* Skip any modesets/resets */ + if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + continue; + + /* Skip any thing not scale or underscan chnages */ + if (!is_scaling_state_different(con_new_state, con_old_state)) + continue; + + lock_and_validation_needed = true; + } + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + new_acrtc_state = to_dm_crtc_state(crtc_state); + + for_each_plane_in_state(state, plane, plane_state, j) { + struct drm_crtc *plane_crtc = plane_state->crtc; + struct drm_framebuffer *fb = plane_state->fb; + bool pflip_needed; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + + /*TODO Implement atomic check for cursor plane */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + + if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active) + continue; + + WARN_ON(!new_acrtc_state->stream); + + pflip_needed = !state->allow_modeset; + if (!pflip_needed) { + struct dc_surface *surface; + + surface = dc_create_surface(dc); + + ret = fill_plane_attributes( + plane_crtc->dev->dev_private, + surface, + plane_state, + crtc_state, + false); + if (ret) + goto fail; + + + if (dm_plane_state->surface) + dc_surface_release(dm_plane_state->surface); + + dm_plane_state->surface = surface; + + add_val_sets_surface(set, + set_count, + new_acrtc_state->stream, + surface); + + lock_and_validation_needed = true; + } + } + } + + /* Run this here since we want to validate the streams we created */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + goto fail; + + /* + * For full updates case when + * removing/adding/updating streams on once CRTC while flipping + * on another CRTC, + * acquiring global lock will guarantee that any such full + * update commit + * will wait for completion of any outstanding flip using DRMs + * synchronization events. + */ + + if (lock_and_validation_needed) { + + ret = do_aquire_global_lock(dev, state); + if (ret) + goto fail; + WARN_ON(dm_state->context); + dm_state->context = dc_get_validate_context(dc, set, set_count); + if (!dm_state->context) { + ret = -EINVAL; + goto fail; + } + } + + /* Must be success */ + WARN_ON(ret); + return ret; + +fail: + if (ret == -EDEADLK) + DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); + else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) + DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); + else + DRM_ERROR("Atomic check failed with err: %d .\n", ret); + + return ret; +} + +static bool is_dp_capable_without_timing_msa( + struct dc *dc, + struct amdgpu_connector *amdgpu_connector) +{ + uint8_t dpcd_data; + bool capable = false; + + if (amdgpu_connector->dc_link && + dm_helpers_dp_read_dpcd( + NULL, + amdgpu_connector->dc_link, + DP_DOWN_STREAM_PORT_COUNT, + &dpcd_data, + sizeof(dpcd_data))) { + capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; + } + + return capable; +} +void amdgpu_dm_add_sink_to_freesync_module( + struct drm_connector *connector, + struct edid *edid) +{ + int i; + uint64_t val_capable; + bool edid_check_required; + struct detailed_timing *timing; + struct detailed_non_pixel *data; + struct detailed_data_monitor_range *range; + struct amdgpu_connector *amdgpu_connector = + to_amdgpu_connector(connector); + + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + edid_check_required = false; + if (!amdgpu_connector->dc_sink) { + DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); + return; + } + if (!adev->dm.freesync_module) + return; + /* + * if edid non zero restrict freesync only for dp and edp + */ + if (edid) { + if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT + || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { + edid_check_required = is_dp_capable_without_timing_msa( + adev->dm.dc, + amdgpu_connector); + } + } + val_capable = 0; + if (edid_check_required == true && (edid->version > 1 || + (edid->version == 1 && edid->revision > 1))) { + for (i = 0; i < 4; i++) { + + timing = &edid->detailed_timings[i]; + data = &timing->data.other_data; + range = &data->data.range; + /* + * Check if monitor has continuous frequency mode + */ + if (data->type != EDID_DETAIL_MONITOR_RANGE) + continue; + /* + * Check for flag range limits only. If flag == 1 then + * no additional timing information provided. + * Default GTF, GTF Secondary curve and CVT are not + * supported + */ + if (range->flags != 1) + continue; + + amdgpu_connector->min_vfreq = range->min_vfreq; + amdgpu_connector->max_vfreq = range->max_vfreq; + amdgpu_connector->pixel_clock_mhz = + range->pixel_clock_mhz * 10; + break; + } + + if (amdgpu_connector->max_vfreq - + amdgpu_connector->min_vfreq > 10) { + amdgpu_connector->caps.supported = true; + amdgpu_connector->caps.min_refresh_in_micro_hz = + amdgpu_connector->min_vfreq * 1000000; + amdgpu_connector->caps.max_refresh_in_micro_hz = + amdgpu_connector->max_vfreq * 1000000; + val_capable = 1; + } + } + + /* + * TODO figure out how to notify user-mode or DRM of freesync caps + * once we figure out how to deal with freesync in an upstreamable + * fashion + */ + +} + +void amdgpu_dm_remove_sink_from_freesync_module( + struct drm_connector *connector) +{ + /* + * TODO fill in once we figure out how to deal with freesync in + * an upstreamable fashion + */ +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index ee69179636a1..16b2e0849a65 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -26,9 +26,9 @@ #ifndef __AMDGPU_DM_H__ #define __AMDGPU_DM_H__ -/* -#include "linux/switch.h" -*/ +#include +#include +#include "dc.h" /* * This file contains the definition for amdgpu_display_manager @@ -173,4 +173,106 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_crtc *crtc, bool from_state_var); + +struct amdgpu_framebuffer; +struct amdgpu_display_manager; +struct dc_validation_set; +struct dc_surface; +/* TODO rename to dc_stream_state */ +struct dc_stream; + + +struct dm_plane_state { + struct drm_plane_state base; + struct dc_surface *surface; +}; + +struct dm_crtc_state { + struct drm_crtc_state base; + struct dc_stream *stream; +}; + +#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) + +struct dm_atomic_state { + struct drm_atomic_state base; + + struct validate_context *context; +}; + +#define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) + + +/*TODO Jodan Hersen use the one in amdgpu_dm*/ +int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs); +int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t link_index); +int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_connector *amdgpu_connector, + uint32_t link_index, + struct amdgpu_encoder *amdgpu_encoder); +int amdgpu_dm_encoder_init( + struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index); + +void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); +void amdgpu_dm_connector_destroy(struct drm_connector *connector); +void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); + +int amdgpu_dm_connector_get_modes(struct drm_connector *connector); + +int amdgpu_dm_atomic_commit( + struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); + +void amdgpu_dm_atomic_commit_tail( + struct drm_atomic_state *state); + +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state); + +void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); +struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( + struct drm_connector *connector); +int amdgpu_dm_connector_atomic_set_property( + struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val); + +int amdgpu_dm_connector_atomic_get_property( + struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val); + +int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); + +void amdgpu_dm_connector_init_helper( + struct amdgpu_display_manager *dm, + struct amdgpu_connector *aconnector, + int connector_type, + struct dc_link *link, + int link_index); + +int amdgpu_dm_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode); + +void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); + +void amdgpu_dm_add_sink_to_freesync_module( + struct drm_connector *connector, + struct edid *edid); + +void amdgpu_dm_remove_sink_from_freesync_module( + struct drm_connector *connector); + +extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; + #endif /* __AMDGPU_DM_H__ */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 6c19a07709df..0a615583de63 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -38,7 +38,6 @@ #include "dc.h" #include "amdgpu_dm.h" #include "amdgpu_dm_irq.h" -#include "amdgpu_dm_types.h" #include "dm_helpers.h" diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index ec91a52c002f..82e4d49fb184 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -27,7 +27,7 @@ #include #include "dm_services.h" #include "amdgpu.h" -#include "amdgpu_dm_types.h" +#include "amdgpu_dm.h" #include "amdgpu_dm_mst_types.h" #include "dc.h" diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index a8a53b85905a..3348e90a0a37 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -33,7 +33,6 @@ #include "amdgpu.h" #include "amdgpu_dm.h" #include "amdgpu_dm_irq.h" -#include "amdgpu_dm_types.h" #include "amdgpu_pm.h" /****************************************************************************** diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c deleted file mode 100644 index 80d4e2670cc2..000000000000 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ /dev/null @@ -1,3286 +0,0 @@ -/* - * Copyright 2012-13 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include -#include - -#include -#include -#include -#include -#include - - -#include "amdgpu.h" -#include "amdgpu_pm.h" -#include "dm_helpers.h" -#include "dm_services_types.h" - -// We need to #undef FRAME_SIZE and DEPRECATED because they conflict -// with ptrace-abi.h's #define's of them. -#undef FRAME_SIZE -#undef DEPRECATED - -#include "dc.h" - -#include "amdgpu_dm_types.h" -#include "amdgpu_dm_mst_types.h" - -#include "modules/inc/mod_freesync.h" - -#include "i2caux_interface.h" - -struct dm_connector_state { - struct drm_connector_state base; - - enum amdgpu_rmx_type scaling; - uint8_t underscan_vborder; - uint8_t underscan_hborder; - bool underscan_enable; -}; - -#define to_dm_connector_state(x)\ - container_of((x), struct dm_connector_state, base) - -static bool modeset_required(struct drm_crtc_state *crtc_state) -{ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - if (!crtc_state->enable) - return false; - - return crtc_state->active; -} - -static bool modereset_required(struct drm_crtc_state *crtc_state) -{ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - return !crtc_state->enable || !crtc_state->active; -} - -void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); - kfree(encoder); -} - -static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { - .destroy = amdgpu_dm_encoder_destroy, -}; - -static void dm_set_cursor( - struct amdgpu_crtc *amdgpu_crtc, - uint64_t gpu_addr, - uint32_t width, - uint32_t height) -{ - struct dc_cursor_attributes attributes; - struct dc_cursor_position position; - struct drm_crtc *crtc = &amdgpu_crtc->base; - int x, y; - int xorigin = 0, yorigin = 0; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - amdgpu_crtc->cursor_width = width; - amdgpu_crtc->cursor_height = height; - - attributes.address.high_part = upper_32_bits(gpu_addr); - attributes.address.low_part = lower_32_bits(gpu_addr); - attributes.width = width; - attributes.height = height; - attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; - attributes.rotation_angle = 0; - attributes.attribute_flags.value = 0; - - attributes.pitch = attributes.width; - - x = amdgpu_crtc->cursor_x; - y = amdgpu_crtc->cursor_y; - - /* avivo cursor are offset into the total surface */ - x += crtc->primary->state->src_x >> 16; - y += crtc->primary->state->src_y >> 16; - - if (x < 0) { - xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); - x = 0; - } - if (y < 0) { - yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); - y = 0; - } - - position.enable = true; - position.x = x; - position.y = y; - - position.x_hotspot = xorigin; - position.y_hotspot = yorigin; - - if (!dc_stream_set_cursor_attributes( - acrtc_state->stream, - &attributes)) { - DRM_ERROR("DC failed to set cursor attributes\n"); - } - - if (!dc_stream_set_cursor_position( - acrtc_state->stream, - &position)) { - DRM_ERROR("DC failed to set cursor position\n"); - } -} - -static int dm_crtc_cursor_set( - struct drm_crtc *crtc, - uint64_t address, - uint32_t width, - uint32_t height) -{ - struct dc_cursor_position position; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - int ret; - - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; - - DRM_DEBUG_KMS( - "%s: crtc_id=%d with size %d to %d \n", - __func__, - amdgpu_crtc->crtc_id, - width, - height); - - if (!address) { - /* turn off cursor */ - position.enable = false; - position.x = 0; - position.y = 0; - - if (acrtc_state->stream) { - /*set cursor visible false*/ - dc_stream_set_cursor_position( - acrtc_state->stream, - &position); - } - goto release; - - } - - if ((width > amdgpu_crtc->max_cursor_width) || - (height > amdgpu_crtc->max_cursor_height)) { - DRM_ERROR( - "%s: bad cursor width or height %d x %d\n", - __func__, - width, - height); - goto release; - } - - /*program new cursor bo to hardware*/ - dm_set_cursor(amdgpu_crtc, address, width, height); - -release: - return ret; - -} - -static int dm_crtc_cursor_move(struct drm_crtc *crtc, - int x, int y) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - int xorigin = 0, yorigin = 0; - struct dc_cursor_position position; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - amdgpu_crtc->cursor_x = x; - amdgpu_crtc->cursor_y = y; - - /* avivo cursor are offset into the total surface */ - x += crtc->primary->state->src_x >> 16; - y += crtc->primary->state->src_y >> 16; - - /* - * TODO: for cursor debugging unguard the following - */ -#if 0 - DRM_DEBUG_KMS( - "%s: x %d y %d c->x %d c->y %d\n", - __func__, - x, - y, - crtc->x, - crtc->y); -#endif - - if (x < 0) { - xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); - x = 0; - } - if (y < 0) { - yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); - y = 0; - } - - position.enable = true; - position.x = x; - position.y = y; - - position.x_hotspot = xorigin; - position.y_hotspot = yorigin; - - if (acrtc_state->stream) { - if (!dc_stream_set_cursor_position( - acrtc_state->stream, - &position)) { - DRM_ERROR("DC failed to set cursor position\n"); - return -EINVAL; - } - } - - return 0; -} - -static bool fill_rects_from_plane_state( - const struct drm_plane_state *state, - struct dc_surface *surface) -{ - surface->src_rect.x = state->src_x >> 16; - surface->src_rect.y = state->src_y >> 16; - /*we ignore for now mantissa and do not to deal with floating pixels :(*/ - surface->src_rect.width = state->src_w >> 16; - - if (surface->src_rect.width == 0) - return false; - - surface->src_rect.height = state->src_h >> 16; - if (surface->src_rect.height == 0) - return false; - - surface->dst_rect.x = state->crtc_x; - surface->dst_rect.y = state->crtc_y; - - if (state->crtc_w == 0) - return false; - - surface->dst_rect.width = state->crtc_w; - - if (state->crtc_h == 0) - return false; - - surface->dst_rect.height = state->crtc_h; - - surface->clip_rect = surface->dst_rect; - - switch (state->rotation & DRM_MODE_ROTATE_MASK) { - case DRM_MODE_ROTATE_0: - surface->rotation = ROTATION_ANGLE_0; - break; - case DRM_MODE_ROTATE_90: - surface->rotation = ROTATION_ANGLE_90; - break; - case DRM_MODE_ROTATE_180: - surface->rotation = ROTATION_ANGLE_180; - break; - case DRM_MODE_ROTATE_270: - surface->rotation = ROTATION_ANGLE_270; - break; - default: - surface->rotation = ROTATION_ANGLE_0; - break; - } - - return true; -} -static int get_fb_info( - const struct amdgpu_framebuffer *amdgpu_fb, - uint64_t *tiling_flags, - uint64_t *fb_location) -{ - struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); - int r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r)) { - DRM_ERROR("Unable to reserve buffer\n"); - return r; - } - - if (fb_location) - *fb_location = amdgpu_bo_gpu_offset(rbo); - - if (tiling_flags) - amdgpu_bo_get_tiling_flags(rbo, tiling_flags); - - amdgpu_bo_unreserve(rbo); - - return r; -} - -static int fill_plane_attributes_from_fb( - struct amdgpu_device *adev, - struct dc_surface *surface, - const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) -{ - uint64_t tiling_flags; - uint64_t fb_location = 0; - unsigned int awidth; - const struct drm_framebuffer *fb = &amdgpu_fb->base; - int ret = 0; - struct drm_format_name_buf format_name; - - ret = get_fb_info( - amdgpu_fb, - &tiling_flags, - addReq == true ? &fb_location:NULL); - - if (ret) - return ret; - - switch (fb->format->format) { - case DRM_FORMAT_C8: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; - break; - case DRM_FORMAT_RGB565: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; - break; - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; - break; - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_ARGB2101010: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; - break; - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_ABGR2101010: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; - break; - case DRM_FORMAT_NV21: - surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; - break; - case DRM_FORMAT_NV12: - surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; - break; - default: - DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(fb->format->format, &format_name)); - return -EINVAL; - } - - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - surface->address.type = PLN_ADDR_TYPE_GRAPHICS; - surface->address.grph.addr.low_part = lower_32_bits(fb_location); - surface->address.grph.addr.high_part = upper_32_bits(fb_location); - surface->plane_size.grph.surface_size.x = 0; - surface->plane_size.grph.surface_size.y = 0; - surface->plane_size.grph.surface_size.width = fb->width; - surface->plane_size.grph.surface_size.height = fb->height; - surface->plane_size.grph.surface_pitch = - fb->pitches[0] / fb->format->cpp[0]; - /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_SRGB; - - } else { - awidth = ALIGN(fb->width, 64); - surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; - surface->address.video_progressive.luma_addr.low_part - = lower_32_bits(fb_location); - surface->address.video_progressive.chroma_addr.low_part - = lower_32_bits(fb_location) + - (awidth * fb->height); - surface->plane_size.video.luma_size.x = 0; - surface->plane_size.video.luma_size.y = 0; - surface->plane_size.video.luma_size.width = awidth; - surface->plane_size.video.luma_size.height = fb->height; - /* TODO: unhardcode */ - surface->plane_size.video.luma_pitch = awidth; - - surface->plane_size.video.chroma_size.x = 0; - surface->plane_size.video.chroma_size.y = 0; - surface->plane_size.video.chroma_size.width = awidth; - surface->plane_size.video.chroma_size.height = fb->height; - surface->plane_size.video.chroma_pitch = awidth / 2; - - /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_YCBCR709; - } - - memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); - - /* Fill GFX params */ - if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) - { - unsigned bankw, bankh, mtaspect, tile_split, num_banks; - - bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); - bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); - mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT); - tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT); - num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); - - /* XXX fix me for VI */ - surface->tiling_info.gfx8.num_banks = num_banks; - surface->tiling_info.gfx8.array_mode = - DC_ARRAY_2D_TILED_THIN1; - surface->tiling_info.gfx8.tile_split = tile_split; - surface->tiling_info.gfx8.bank_width = bankw; - surface->tiling_info.gfx8.bank_height = bankh; - surface->tiling_info.gfx8.tile_aspect = mtaspect; - surface->tiling_info.gfx8.tile_mode = - DC_ADDR_SURF_MICRO_TILING_DISPLAY; - } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) - == DC_ARRAY_1D_TILED_THIN1) { - surface->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; - } - - surface->tiling_info.gfx8.pipe_config = - AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); - - if (adev->asic_type == CHIP_VEGA10 || - adev->asic_type == CHIP_RAVEN) { - /* Fill GFX9 params */ - surface->tiling_info.gfx9.num_pipes = - adev->gfx.config.gb_addr_config_fields.num_pipes; - surface->tiling_info.gfx9.num_banks = - adev->gfx.config.gb_addr_config_fields.num_banks; - surface->tiling_info.gfx9.pipe_interleave = - adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; - surface->tiling_info.gfx9.num_shader_engines = - adev->gfx.config.gb_addr_config_fields.num_se; - surface->tiling_info.gfx9.max_compressed_frags = - adev->gfx.config.gb_addr_config_fields.max_compress_frags; - surface->tiling_info.gfx9.num_rb_per_se = - adev->gfx.config.gb_addr_config_fields.num_rb_per_se; - surface->tiling_info.gfx9.swizzle = - AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); - surface->tiling_info.gfx9.shaderEnable = 1; - } - - surface->visible = true; - surface->scaling_quality.h_taps_c = 0; - surface->scaling_quality.v_taps_c = 0; - - /* is this needed? is surface zeroed at allocation? */ - surface->scaling_quality.h_taps = 0; - surface->scaling_quality.v_taps = 0; - surface->stereo_format = PLANE_STEREO_FORMAT_NONE; - - return ret; - -} - -#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 - -static void fill_gamma_from_crtc_state( - const struct drm_crtc_state *crtc_state, - struct dc_surface *dc_surface) -{ - int i; - struct dc_gamma *gamma; - struct drm_color_lut *lut = (struct drm_color_lut *) crtc_state->gamma_lut->data; - - gamma = dc_create_gamma(); - - if (gamma == NULL) { - WARN_ON(1); - return; - } - - for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { - gamma->red[i] = lut[i].red; - gamma->green[i] = lut[i].green; - gamma->blue[i] = lut[i].blue; - } - - dc_surface->gamma_correction = gamma; -} - -static int fill_plane_attributes( - struct amdgpu_device *adev, - struct dc_surface *surface, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state, - bool addrReq) -{ - const struct amdgpu_framebuffer *amdgpu_fb = - to_amdgpu_framebuffer(plane_state->fb); - const struct drm_crtc *crtc = plane_state->crtc; - struct dc_transfer_func *input_tf; - int ret = 0; - - if (!fill_rects_from_plane_state(plane_state, surface)) - return -EINVAL; - - ret = fill_plane_attributes_from_fb( - crtc->dev->dev_private, - surface, - amdgpu_fb, - addrReq); - - if (ret) - return ret; - - input_tf = dc_create_transfer_func(); - - if (input_tf == NULL) - return -ENOMEM; - - input_tf->type = TF_TYPE_PREDEFINED; - input_tf->tf = TRANSFER_FUNCTION_SRGB; - - surface->in_transfer_func = input_tf; - - /* In case of gamma set, update gamma value */ - if (crtc_state->gamma_lut) - fill_gamma_from_crtc_state(crtc_state, surface); - - return ret; -} - -/*****************************************************************************/ - -struct amdgpu_connector *aconnector_from_drm_crtc_id( - const struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_connector *connector; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_connector *aconnector; - - list_for_each_entry(connector, - &dev->mode_config.connector_list, head) { - - aconnector = to_amdgpu_connector(connector); - - if (aconnector->base.state->crtc != &acrtc->base) - continue; - - /* Found the connector */ - return aconnector; - } - - /* If we get here, not found. */ - return NULL; -} - -static void update_stream_scaling_settings( - const struct drm_display_mode *mode, - const struct dm_connector_state *dm_state, - struct dc_stream *stream) -{ - enum amdgpu_rmx_type rmx_type; - - struct rect src = { 0 }; /* viewport in composition space*/ - struct rect dst = { 0 }; /* stream addressable area */ - - /* no mode. nothing to be done */ - if (!mode) - return; - - /* Full screen scaling by default */ - src.width = mode->hdisplay; - src.height = mode->vdisplay; - dst.width = stream->timing.h_addressable; - dst.height = stream->timing.v_addressable; - - rmx_type = dm_state->scaling; - if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { - if (src.width * dst.height < - src.height * dst.width) { - /* height needs less upscaling/more downscaling */ - dst.width = src.width * - dst.height / src.height; - } else { - /* width needs less upscaling/more downscaling */ - dst.height = src.height * - dst.width / src.width; - } - } else if (rmx_type == RMX_CENTER) { - dst = src; - } - - dst.x = (stream->timing.h_addressable - dst.width) / 2; - dst.y = (stream->timing.v_addressable - dst.height) / 2; - - if (dm_state->underscan_enable) { - dst.x += dm_state->underscan_hborder / 2; - dst.y += dm_state->underscan_vborder / 2; - dst.width -= dm_state->underscan_hborder; - dst.height -= dm_state->underscan_vborder; - } - - stream->src = src; - stream->dst = dst; - - DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", - dst.x, dst.y, dst.width, dst.height); - -} - -static enum dc_color_depth convert_color_depth_from_display_info( - const struct drm_connector *connector) -{ - uint32_t bpc = connector->display_info.bpc; - - /* Limited color depth to 8bit - * TODO: Still need to handle deep color*/ - if (bpc > 8) - bpc = 8; - - switch (bpc) { - case 0: - /* Temporary Work around, DRM don't parse color depth for - * EDID revision before 1.4 - * TODO: Fix edid parsing - */ - return COLOR_DEPTH_888; - case 6: - return COLOR_DEPTH_666; - case 8: - return COLOR_DEPTH_888; - case 10: - return COLOR_DEPTH_101010; - case 12: - return COLOR_DEPTH_121212; - case 14: - return COLOR_DEPTH_141414; - case 16: - return COLOR_DEPTH_161616; - default: - return COLOR_DEPTH_UNDEFINED; - } -} - -static enum dc_aspect_ratio get_aspect_ratio( - const struct drm_display_mode *mode_in) -{ - int32_t width = mode_in->crtc_hdisplay * 9; - int32_t height = mode_in->crtc_vdisplay * 16; - if ((width - height) < 10 && (width - height) > -10) - return ASPECT_RATIO_16_9; - else - return ASPECT_RATIO_4_3; -} - -static enum dc_color_space get_output_color_space( - const struct dc_crtc_timing *dc_crtc_timing) -{ - enum dc_color_space color_space = COLOR_SPACE_SRGB; - - switch (dc_crtc_timing->pixel_encoding) { - case PIXEL_ENCODING_YCBCR422: - case PIXEL_ENCODING_YCBCR444: - case PIXEL_ENCODING_YCBCR420: - { - /* - * 27030khz is the separation point between HDTV and SDTV - * according to HDMI spec, we use YCbCr709 and YCbCr601 - * respectively - */ - if (dc_crtc_timing->pix_clk_khz > 27030) { - if (dc_crtc_timing->flags.Y_ONLY) - color_space = - COLOR_SPACE_YCBCR709_LIMITED; - else - color_space = COLOR_SPACE_YCBCR709; - } else { - if (dc_crtc_timing->flags.Y_ONLY) - color_space = - COLOR_SPACE_YCBCR601_LIMITED; - else - color_space = COLOR_SPACE_YCBCR601; - } - - } - break; - case PIXEL_ENCODING_RGB: - color_space = COLOR_SPACE_SRGB; - break; - - default: - WARN_ON(1); - break; - } - - return color_space; -} - -/*****************************************************************************/ - -static void fill_stream_properties_from_drm_display_mode( - struct dc_stream *stream, - const struct drm_display_mode *mode_in, - const struct drm_connector *connector) -{ - struct dc_crtc_timing *timing_out = &stream->timing; - memset(timing_out, 0, sizeof(struct dc_crtc_timing)); - - timing_out->h_border_left = 0; - timing_out->h_border_right = 0; - timing_out->v_border_top = 0; - timing_out->v_border_bottom = 0; - /* TODO: un-hardcode */ - - if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444) - && stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) - timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444; - else - timing_out->pixel_encoding = PIXEL_ENCODING_RGB; - - timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE; - timing_out->display_color_depth = convert_color_depth_from_display_info( - connector); - timing_out->scan_type = SCANNING_TYPE_NODATA; - timing_out->hdmi_vic = 0; - timing_out->vic = drm_match_cea_mode(mode_in); - - timing_out->h_addressable = mode_in->crtc_hdisplay; - timing_out->h_total = mode_in->crtc_htotal; - timing_out->h_sync_width = - mode_in->crtc_hsync_end - mode_in->crtc_hsync_start; - timing_out->h_front_porch = - mode_in->crtc_hsync_start - mode_in->crtc_hdisplay; - timing_out->v_total = mode_in->crtc_vtotal; - timing_out->v_addressable = mode_in->crtc_vdisplay; - timing_out->v_front_porch = - mode_in->crtc_vsync_start - mode_in->crtc_vdisplay; - timing_out->v_sync_width = - mode_in->crtc_vsync_end - mode_in->crtc_vsync_start; - timing_out->pix_clk_khz = mode_in->crtc_clock; - timing_out->aspect_ratio = get_aspect_ratio(mode_in); - if (mode_in->flags & DRM_MODE_FLAG_PHSYNC) - timing_out->flags.HSYNC_POSITIVE_POLARITY = 1; - if (mode_in->flags & DRM_MODE_FLAG_PVSYNC) - timing_out->flags.VSYNC_POSITIVE_POLARITY = 1; - - stream->output_color_space = get_output_color_space(timing_out); - - { - struct dc_transfer_func *tf = dc_create_transfer_func(); - tf->type = TF_TYPE_PREDEFINED; - tf->tf = TRANSFER_FUNCTION_SRGB; - stream->out_transfer_func = tf; - } -} - -static void fill_audio_info( - struct audio_info *audio_info, - const struct drm_connector *drm_connector, - const struct dc_sink *dc_sink) -{ - int i = 0; - int cea_revision = 0; - const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps; - - audio_info->manufacture_id = edid_caps->manufacturer_id; - audio_info->product_id = edid_caps->product_id; - - cea_revision = drm_connector->display_info.cea_rev; - - while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && - edid_caps->display_name[i]) { - audio_info->display_name[i] = edid_caps->display_name[i]; - i++; - } - - if(cea_revision >= 3) { - audio_info->mode_count = edid_caps->audio_mode_count; - - for (i = 0; i < audio_info->mode_count; ++i) { - audio_info->modes[i].format_code = - (enum audio_format_code) - (edid_caps->audio_modes[i].format_code); - audio_info->modes[i].channel_count = - edid_caps->audio_modes[i].channel_count; - audio_info->modes[i].sample_rates.all = - edid_caps->audio_modes[i].sample_rate; - audio_info->modes[i].sample_size = - edid_caps->audio_modes[i].sample_size; - } - } - - audio_info->flags.all = edid_caps->speaker_flags; - - /* TODO: We only check for the progressive mode, check for interlace mode too */ - if(drm_connector->latency_present[0]) { - audio_info->video_latency = drm_connector->video_latency[0]; - audio_info->audio_latency = drm_connector->audio_latency[0]; - } - - /* TODO: For DP, video and audio latency should be calculated from DPCD caps */ - -} - -static void copy_crtc_timing_for_drm_display_mode( - const struct drm_display_mode *src_mode, - struct drm_display_mode *dst_mode) -{ - dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay; - dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay; - dst_mode->crtc_clock = src_mode->crtc_clock; - dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start; - dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end; - dst_mode->crtc_hsync_start= src_mode->crtc_hsync_start; - dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; - dst_mode->crtc_htotal = src_mode->crtc_htotal; - dst_mode->crtc_hskew = src_mode->crtc_hskew; - dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start; - dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end; - dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start; - dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end; - dst_mode->crtc_vtotal = src_mode->crtc_vtotal; -} - -static void decide_crtc_timing_for_drm_display_mode( - struct drm_display_mode *drm_mode, - const struct drm_display_mode *native_mode, - bool scale_enabled) -{ - if (scale_enabled) { - copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); - } else if (native_mode->clock == drm_mode->clock && - native_mode->htotal == drm_mode->htotal && - native_mode->vtotal == drm_mode->vtotal) { - copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); - } else { - /* no scaling nor amdgpu inserted, no need to patch */ - } -} - -static struct dc_stream *create_stream_for_sink( - struct amdgpu_connector *aconnector, - const struct drm_display_mode *drm_mode, - const struct dm_connector_state *dm_state) -{ - struct drm_display_mode *preferred_mode = NULL; - const struct drm_connector *drm_connector; - struct dc_stream *stream = NULL; - struct drm_display_mode mode = *drm_mode; - bool native_mode_found = false; - - if (NULL == aconnector) { - DRM_ERROR("aconnector is NULL!\n"); - goto drm_connector_null; - } - - if (NULL == dm_state) { - DRM_ERROR("dm_state is NULL!\n"); - goto dm_state_null; - } - - drm_connector = &aconnector->base; - stream = dc_create_stream_for_sink(aconnector->dc_sink); - - if (NULL == stream) { - DRM_ERROR("Failed to create stream for sink!\n"); - goto stream_create_fail; - } - - list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { - /* Search for preferred mode */ - if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { - native_mode_found = true; - break; - } - } - if (!native_mode_found) - preferred_mode = list_first_entry_or_null( - &aconnector->base.modes, - struct drm_display_mode, - head); - - if (NULL == preferred_mode) { - /* This may not be an error, the use case is when we we have no - * usermode calls to reset and set mode upon hotplug. In this - * case, we call set mode ourselves to restore the previous mode - * and the modelist may not be filled in in time. - */ - DRM_INFO("No preferred mode found\n"); - } else { - decide_crtc_timing_for_drm_display_mode( - &mode, preferred_mode, - dm_state->scaling != RMX_OFF); - } - - fill_stream_properties_from_drm_display_mode(stream, - &mode, &aconnector->base); - update_stream_scaling_settings(&mode, dm_state, stream); - - fill_audio_info( - &stream->audio_info, - drm_connector, - aconnector->dc_sink); - -stream_create_fail: -dm_state_null: -drm_connector_null: - return stream; -} - -void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) -{ - drm_crtc_cleanup(crtc); - kfree(crtc); -} - -static void dm_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - struct dm_crtc_state *cur = to_dm_crtc_state(state); - - /* TODO Destroy dc_stream objects are stream object is flattened */ - if (cur->stream) - dc_stream_release(cur->stream); - - - __drm_atomic_helper_crtc_destroy_state(state); - - - kfree(state); -} - -static void dm_crtc_reset_state(struct drm_crtc *crtc) -{ - struct dm_crtc_state *state; - - if (crtc->state) - dm_crtc_destroy_state(crtc, crtc->state); - - state = kzalloc(sizeof(*state), GFP_KERNEL); - if (WARN_ON(!state)) - return; - - crtc->state = &state->base; - crtc->state->crtc = crtc; - -} - -static struct drm_crtc_state * -dm_crtc_duplicate_state(struct drm_crtc *crtc) -{ - struct dm_crtc_state *state, *cur; - - cur = to_dm_crtc_state(crtc->state); - - if (WARN_ON(!crtc->state)) - return NULL; - - state = dm_alloc(sizeof(*state)); - - __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); - - if (cur->stream) { - state->stream = cur->stream; - dc_stream_retain(state->stream); - } - - /* TODO Duplicate dc_stream after objects are stream object is flattened */ - - return &state->base; -} - -/* Implemented only the options currently availible for the driver */ -static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { - .reset = dm_crtc_reset_state, - .destroy = amdgpu_dm_crtc_destroy, - .gamma_set = drm_atomic_helper_legacy_gamma_set, - .set_config = drm_atomic_helper_set_config, - .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = dm_crtc_duplicate_state, - .atomic_destroy_state = dm_crtc_destroy_state, -}; - -static enum drm_connector_status -amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) -{ - bool connected; - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - - /* Notes: - * 1. This interface is NOT called in context of HPD irq. - * 2. This interface *is called* in context of user-mode ioctl. Which - * makes it a bad place for *any* MST-related activit. */ - - if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) - connected = (aconnector->dc_sink != NULL); - else - connected = (aconnector->base.force == DRM_FORCE_ON); - - return (connected ? connector_status_connected : - connector_status_disconnected); -} - -int amdgpu_dm_connector_atomic_set_property( - struct drm_connector *connector, - struct drm_connector_state *connector_state, - struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; - struct dm_connector_state *dm_old_state = - to_dm_connector_state(connector->state); - struct dm_connector_state *dm_new_state = - to_dm_connector_state(connector_state); - - int ret = -EINVAL; - - if (property == dev->mode_config.scaling_mode_property) { - enum amdgpu_rmx_type rmx_type; - - switch (val) { - case DRM_MODE_SCALE_CENTER: - rmx_type = RMX_CENTER; - break; - case DRM_MODE_SCALE_ASPECT: - rmx_type = RMX_ASPECT; - break; - case DRM_MODE_SCALE_FULLSCREEN: - rmx_type = RMX_FULL; - break; - case DRM_MODE_SCALE_NONE: - default: - rmx_type = RMX_OFF; - break; - } - - if (dm_old_state->scaling == rmx_type) - return 0; - - dm_new_state->scaling = rmx_type; - ret = 0; - } else if (property == adev->mode_info.underscan_hborder_property) { - dm_new_state->underscan_hborder = val; - ret = 0; - } else if (property == adev->mode_info.underscan_vborder_property) { - dm_new_state->underscan_vborder = val; - ret = 0; - } else if (property == adev->mode_info.underscan_property) { - dm_new_state->underscan_enable = val; - ret = 0; - } - - return ret; -} - -int amdgpu_dm_connector_atomic_get_property( - struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) -{ - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; - struct dm_connector_state *dm_state = - to_dm_connector_state(state); - int ret = -EINVAL; - - if (property == dev->mode_config.scaling_mode_property) { - switch (dm_state->scaling) { - case RMX_CENTER: - *val = DRM_MODE_SCALE_CENTER; - break; - case RMX_ASPECT: - *val = DRM_MODE_SCALE_ASPECT; - break; - case RMX_FULL: - *val = DRM_MODE_SCALE_FULLSCREEN; - break; - case RMX_OFF: - default: - *val = DRM_MODE_SCALE_NONE; - break; - } - ret = 0; - } else if (property == adev->mode_info.underscan_hborder_property) { - *val = dm_state->underscan_hborder; - ret = 0; - } else if (property == adev->mode_info.underscan_vborder_property) { - *val = dm_state->underscan_vborder; - ret = 0; - } else if (property == adev->mode_info.underscan_property) { - *val = dm_state->underscan_enable; - ret = 0; - } - return ret; -} - -void amdgpu_dm_connector_destroy(struct drm_connector *connector) -{ - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - const struct dc_link *link = aconnector->dc_link; - struct amdgpu_device *adev = connector->dev->dev_private; - struct amdgpu_display_manager *dm = &adev->dm; -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ - defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - - if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { - amdgpu_dm_register_backlight_device(dm); - - if (dm->backlight_dev) { - backlight_device_unregister(dm->backlight_dev); - dm->backlight_dev = NULL; - } - - } -#endif - drm_connector_unregister(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - -void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) -{ - struct dm_connector_state *state = - to_dm_connector_state(connector->state); - - kfree(state); - - state = kzalloc(sizeof(*state), GFP_KERNEL); - - if (state) { - state->scaling = RMX_OFF; - state->underscan_enable = false; - state->underscan_hborder = 0; - state->underscan_vborder = 0; - - connector->state = &state->base; - connector->state->connector = connector; - } -} - -struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( - struct drm_connector *connector) -{ - struct dm_connector_state *state = - to_dm_connector_state(connector->state); - - struct dm_connector_state *new_state = - kmemdup(state, sizeof(*state), GFP_KERNEL); - - if (new_state) { - __drm_atomic_helper_connector_duplicate_state(connector, - &new_state->base); - return &new_state->base; - } - - return NULL; -} - -static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { - .reset = amdgpu_dm_connector_funcs_reset, - .detect = amdgpu_dm_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = amdgpu_dm_connector_destroy, - .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - .atomic_set_property = amdgpu_dm_connector_atomic_set_property, - .atomic_get_property = amdgpu_dm_connector_atomic_get_property -}; - -static struct drm_encoder *best_encoder(struct drm_connector *connector) -{ - int enc_id = connector->encoder_ids[0]; - struct drm_mode_object *obj; - struct drm_encoder *encoder; - - DRM_DEBUG_KMS("Finding the best encoder\n"); - - /* pick the encoder ids */ - if (enc_id) { - obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); - if (!obj) { - DRM_ERROR("Couldn't find a matching encoder for our connector\n"); - return NULL; - } - encoder = obj_to_encoder(obj); - return encoder; - } - DRM_ERROR("No encoder id\n"); - return NULL; -} - -static int get_modes(struct drm_connector *connector) -{ - return amdgpu_dm_connector_get_modes(connector); -} - -static void create_eml_sink(struct amdgpu_connector *aconnector) -{ - struct dc_sink_init_data init_params = { - .link = aconnector->dc_link, - .sink_signal = SIGNAL_TYPE_VIRTUAL - }; - struct edid *edid = (struct edid *) aconnector->base.edid_blob_ptr->data; - - if (!aconnector->base.edid_blob_ptr || - !aconnector->base.edid_blob_ptr->data) { - DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", - aconnector->base.name); - - aconnector->base.force = DRM_FORCE_OFF; - aconnector->base.override_edid = false; - return; - } - - aconnector->edid = edid; - - aconnector->dc_em_sink = dc_link_add_remote_sink( - aconnector->dc_link, - (uint8_t *)edid, - (edid->extensions + 1) * EDID_LENGTH, - &init_params); - - if (aconnector->base.force - == DRM_FORCE_ON) - aconnector->dc_sink = aconnector->dc_link->local_sink ? - aconnector->dc_link->local_sink : - aconnector->dc_em_sink; -} - -static void handle_edid_mgmt(struct amdgpu_connector *aconnector) -{ - struct dc_link *link = (struct dc_link *)aconnector->dc_link; - - /* In case of headless boot with force on for DP managed connector - * Those settings have to be != 0 to get initial modeset - */ - if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) { - link->verified_link_cap.lane_count = LANE_COUNT_FOUR; - link->verified_link_cap.link_rate = LINK_RATE_HIGH2; - } - - - aconnector->base.override_edid = true; - create_eml_sink(aconnector); -} - -int amdgpu_dm_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode) -{ - int result = MODE_ERROR; - struct dc_sink *dc_sink; - struct amdgpu_device *adev = connector->dev->dev_private; - /* TODO: Unhardcode stream count */ - struct dc_stream *stream; - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || - (mode->flags & DRM_MODE_FLAG_DBLSCAN)) - return result; - - /* Only run this the first time mode_valid is called to initilialize - * EDID mgmt - */ - if (aconnector->base.force != DRM_FORCE_UNSPECIFIED && - !aconnector->dc_em_sink) - handle_edid_mgmt(aconnector); - - dc_sink = to_amdgpu_connector(connector)->dc_sink; - - if (NULL == dc_sink) { - DRM_ERROR("dc_sink is NULL!\n"); - goto fail; - } - - stream = dc_create_stream_for_sink(dc_sink); - if (NULL == stream) { - DRM_ERROR("Failed to create stream for sink!\n"); - goto fail; - } - - drm_mode_set_crtcinfo(mode, 0); - fill_stream_properties_from_drm_display_mode(stream, mode, connector); - - stream->src.width = mode->hdisplay; - stream->src.height = mode->vdisplay; - stream->dst = stream->src; - - if (dc_validate_stream(adev->dm.dc, stream)) - result = MODE_OK; - - dc_stream_release(stream); - -fail: - /* TODO: error handling*/ - return result; -} - -static const struct drm_connector_helper_funcs -amdgpu_dm_connector_helper_funcs = { - /* - * If hotplug a second bigger display in FB Con mode, bigger resolution - * modes will be filtered by drm_mode_validate_size(), and those modes - * is missing after user start lightdm. So we need to renew modes list. - * in get_modes call back, not just return the modes count - */ - .get_modes = get_modes, - .mode_valid = amdgpu_dm_connector_mode_valid, - .best_encoder = best_encoder -}; - -static void dm_crtc_helper_disable(struct drm_crtc *crtc) -{ -} - -static int dm_crtc_helper_atomic_check( - struct drm_crtc *crtc, - struct drm_crtc_state *state) -{ - struct amdgpu_device *adev = crtc->dev->dev_private; - struct dc *dc = adev->dm.dc; - struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); - int ret = -EINVAL; - - if (unlikely(!dm_crtc_state->stream && modeset_required(state))) { - WARN_ON(1); - return ret; - } - - /* In some use cases, like reset, no stream is attached */ - if (!dm_crtc_state->stream) - return 0; - - if (dc_validate_stream(dc, dm_crtc_state->stream)) - return 0; - - return ret; -} - -static bool dm_crtc_helper_mode_fixup( - struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = { - .disable = dm_crtc_helper_disable, - .atomic_check = dm_crtc_helper_atomic_check, - .mode_fixup = dm_crtc_helper_mode_fixup -}; - -static void dm_encoder_helper_disable(struct drm_encoder *encoder) -{ - -} - -static int dm_encoder_helper_atomic_check( - struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - return 0; -} - -const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { - .disable = dm_encoder_helper_disable, - .atomic_check = dm_encoder_helper_atomic_check -}; - -static void dm_drm_plane_reset(struct drm_plane *plane) -{ - struct dm_plane_state *amdgpu_state = NULL; - - if (plane->state) - plane->funcs->atomic_destroy_state(plane, plane->state); - - amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); - - if (amdgpu_state) { - plane->state = &amdgpu_state->base; - plane->state->plane = plane; - plane->state->rotation = DRM_MODE_ROTATE_0; - } - else - WARN_ON(1); -} - -static struct drm_plane_state * -dm_drm_plane_duplicate_state(struct drm_plane *plane) -{ - struct dm_plane_state *dm_plane_state, *old_dm_plane_state; - - old_dm_plane_state = to_dm_plane_state(plane->state); - dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL); - if (!dm_plane_state) - return NULL; - - __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - - if (old_dm_plane_state->surface) { - dm_plane_state->surface = old_dm_plane_state->surface; - dc_surface_retain(dm_plane_state->surface); - } - - return &dm_plane_state->base; -} - -void dm_drm_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *state) -{ - struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - - if (dm_plane_state->surface) - dc_surface_release(dm_plane_state->surface); - - __drm_atomic_helper_plane_destroy_state(state); - kfree(dm_plane_state); -} - -static const struct drm_plane_funcs dm_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_plane_cleanup, - .reset = dm_drm_plane_reset, - .atomic_duplicate_state = dm_drm_plane_duplicate_state, - .atomic_destroy_state = dm_drm_plane_destroy_state, -}; - -static int dm_plane_helper_prepare_fb( - struct drm_plane *plane, - struct drm_plane_state *new_state) -{ - struct amdgpu_framebuffer *afb; - struct drm_gem_object *obj; - struct amdgpu_bo *rbo; - int r; - struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; - unsigned int awidth; - - dm_plane_state_old = to_dm_plane_state(plane->state); - dm_plane_state_new = to_dm_plane_state(new_state); - - if (!new_state->fb) { - DRM_DEBUG_KMS("No FB bound\n"); - return 0; - } - - afb = to_amdgpu_framebuffer(new_state->fb); - - obj = afb->obj; - rbo = gem_to_amdgpu_bo(obj); - r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r != 0)) - return r; - - r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, &afb->address); - - - amdgpu_bo_unreserve(rbo); - - if (unlikely(r != 0)) { - DRM_ERROR("Failed to pin framebuffer\n"); - return r; - } - - amdgpu_bo_ref(rbo); - - if (dm_plane_state_new->surface && - dm_plane_state_old->surface != dm_plane_state_new->surface) { - struct dc_surface *surface = dm_plane_state_new->surface; - - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - surface->address.grph.addr.low_part = lower_32_bits(afb->address); - surface->address.grph.addr.high_part = upper_32_bits(afb->address); - } else { - awidth = ALIGN(new_state->fb->width, 64); - surface->address.video_progressive.luma_addr.low_part - = lower_32_bits(afb->address); - surface->address.video_progressive.chroma_addr.low_part - = lower_32_bits(afb->address) + - (awidth * new_state->fb->height); - } - } - - /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer - * prepare and cleanup in drm_atomic_helper_prepare_planes - * and drm_atomic_helper_cleanup_planes because fb doens't in s3. - * IN 4.10 kernel this code should be removed and amdgpu_device_suspend - * code touching fram buffers should be avoided for DC. - */ - if (plane->type == DRM_PLANE_TYPE_CURSOR) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_state->crtc); - - acrtc->cursor_bo = obj; - } - return 0; -} - -static void dm_plane_helper_cleanup_fb( - struct drm_plane *plane, - struct drm_plane_state *old_state) -{ - struct amdgpu_bo *rbo; - struct amdgpu_framebuffer *afb; - int r; - - if (!old_state->fb) - return; - - afb = to_amdgpu_framebuffer(old_state->fb); - rbo = gem_to_amdgpu_bo(afb->obj); - r = amdgpu_bo_reserve(rbo, false); - if (unlikely(r)) { - DRM_ERROR("failed to reserve rbo before unpin\n"); - return; - } else { - amdgpu_bo_unpin(rbo); - amdgpu_bo_unreserve(rbo); - amdgpu_bo_unref(&rbo); - }; -} - -int dm_create_validation_set_for_connector(struct drm_connector *connector, - struct drm_display_mode *mode, struct dc_validation_set *val_set) -{ - int result = MODE_ERROR; - struct dc_sink *dc_sink = - to_amdgpu_connector(connector)->dc_sink; - /* TODO: Unhardcode stream count */ - struct dc_stream *stream; - - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || - (mode->flags & DRM_MODE_FLAG_DBLSCAN)) - return result; - - if (NULL == dc_sink) { - DRM_ERROR("dc_sink is NULL!\n"); - return result; - } - - stream = dc_create_stream_for_sink(dc_sink); - - if (NULL == stream) { - DRM_ERROR("Failed to create stream for sink!\n"); - return result; - } - - drm_mode_set_crtcinfo(mode, 0); - - fill_stream_properties_from_drm_display_mode(stream, mode, connector); - - val_set->stream = stream; - - stream->src.width = mode->hdisplay; - stream->src.height = mode->vdisplay; - stream->dst = stream->src; - - return MODE_OK; -} - -static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { - .prepare_fb = dm_plane_helper_prepare_fb, - .cleanup_fb = dm_plane_helper_cleanup_fb, -}; - -/* - * TODO: these are currently initialized to rgb formats only. - * For future use cases we should either initialize them dynamically based on - * plane capabilities, or initialize this array to all formats, so internal drm - * check will succeed, and let DC to implement proper check - */ -static uint32_t rgb_formats[] = { - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGBA8888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_XBGR2101010, - DRM_FORMAT_ARGB2101010, - DRM_FORMAT_ABGR2101010, -}; - -static uint32_t yuv_formats[] = { - DRM_FORMAT_NV12, - DRM_FORMAT_NV21, -}; - -static const u32 cursor_formats[] = { - DRM_FORMAT_ARGB8888 -}; - -int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs) -{ - int res = -EPERM; - - switch (aplane->base.type) { - case DRM_PLANE_TYPE_PRIMARY: - aplane->base.format_default = true; - - res = drm_universal_plane_init( - dm->adev->ddev, - &aplane->base, - possible_crtcs, - &dm_plane_funcs, - rgb_formats, - ARRAY_SIZE(rgb_formats), - NULL, aplane->base.type, NULL); - break; - case DRM_PLANE_TYPE_OVERLAY: - res = drm_universal_plane_init( - dm->adev->ddev, - &aplane->base, - possible_crtcs, - &dm_plane_funcs, - yuv_formats, - ARRAY_SIZE(yuv_formats), - NULL, aplane->base.type, NULL); - break; - case DRM_PLANE_TYPE_CURSOR: - res = drm_universal_plane_init( - dm->adev->ddev, - &aplane->base, - possible_crtcs, - &dm_plane_funcs, - cursor_formats, - ARRAY_SIZE(cursor_formats), - NULL, aplane->base.type, NULL); - break; - } - - drm_plane_helper_add(&aplane->base, &dm_plane_helper_funcs); - - return res; -} - -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct drm_plane *plane, - uint32_t crtc_index) -{ - struct amdgpu_crtc *acrtc = NULL; - struct amdgpu_plane *cursor_plane; - - int res = -ENOMEM; - - cursor_plane = kzalloc(sizeof(*cursor_plane), GFP_KERNEL); - if (!cursor_plane) - goto fail; - - cursor_plane->base.type = DRM_PLANE_TYPE_CURSOR; - res = amdgpu_dm_plane_init(dm, cursor_plane, 0); - - acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); - if (!acrtc) - goto fail; - - res = drm_crtc_init_with_planes( - dm->ddev, - &acrtc->base, - plane, - &cursor_plane->base, - &amdgpu_dm_crtc_funcs, NULL); - - if (res) - goto fail; - - drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); - - acrtc->max_cursor_width = dm->adev->dm.dc->caps.max_cursor_size; - acrtc->max_cursor_height = dm->adev->dm.dc->caps.max_cursor_size; - - acrtc->crtc_id = crtc_index; - acrtc->base.enabled = false; - - dm->adev->mode_info.crtcs[crtc_index] = acrtc; - drm_mode_crtc_set_gamma_size(&acrtc->base, 256); - - return 0; - -fail: - if (acrtc) - kfree(acrtc); - if (cursor_plane) - kfree(cursor_plane); - acrtc->crtc_id = -1; - return res; -} - - -static int to_drm_connector_type(enum signal_type st) -{ - switch (st) { - case SIGNAL_TYPE_HDMI_TYPE_A: - return DRM_MODE_CONNECTOR_HDMIA; - case SIGNAL_TYPE_EDP: - return DRM_MODE_CONNECTOR_eDP; - case SIGNAL_TYPE_RGB: - return DRM_MODE_CONNECTOR_VGA; - case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_DISPLAY_PORT_MST: - return DRM_MODE_CONNECTOR_DisplayPort; - case SIGNAL_TYPE_DVI_DUAL_LINK: - case SIGNAL_TYPE_DVI_SINGLE_LINK: - return DRM_MODE_CONNECTOR_DVID; - case SIGNAL_TYPE_VIRTUAL: - return DRM_MODE_CONNECTOR_VIRTUAL; - - default: - return DRM_MODE_CONNECTOR_Unknown; - } -} - -static void amdgpu_dm_get_native_mode(struct drm_connector *connector) -{ - const struct drm_connector_helper_funcs *helper = - connector->helper_private; - struct drm_encoder *encoder; - struct amdgpu_encoder *amdgpu_encoder; - - encoder = helper->best_encoder(connector); - - if (encoder == NULL) - return; - - amdgpu_encoder = to_amdgpu_encoder(encoder); - - amdgpu_encoder->native_mode.clock = 0; - - if (!list_empty(&connector->probed_modes)) { - struct drm_display_mode *preferred_mode = NULL; - list_for_each_entry(preferred_mode, - &connector->probed_modes, - head) { - if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { - amdgpu_encoder->native_mode = *preferred_mode; - } - break; - } - - } -} - -static struct drm_display_mode *amdgpu_dm_create_common_mode( - struct drm_encoder *encoder, char *name, - int hdisplay, int vdisplay) -{ - struct drm_device *dev = encoder->dev; - struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); - struct drm_display_mode *mode = NULL; - struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; - - mode = drm_mode_duplicate(dev, native_mode); - - if(mode == NULL) - return NULL; - - mode->hdisplay = hdisplay; - mode->vdisplay = vdisplay; - mode->type &= ~DRM_MODE_TYPE_PREFERRED; - strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN); - - return mode; - -} - -static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); - struct drm_display_mode *mode = NULL; - struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - int i; - int n; - struct mode_size { - char name[DRM_DISPLAY_MODE_LEN]; - int w; - int h; - }common_modes[] = { - { "640x480", 640, 480}, - { "800x600", 800, 600}, - { "1024x768", 1024, 768}, - { "1280x720", 1280, 720}, - { "1280x800", 1280, 800}, - {"1280x1024", 1280, 1024}, - { "1440x900", 1440, 900}, - {"1680x1050", 1680, 1050}, - {"1600x1200", 1600, 1200}, - {"1920x1080", 1920, 1080}, - {"1920x1200", 1920, 1200} - }; - - n = sizeof(common_modes) / sizeof(common_modes[0]); - - for (i = 0; i < n; i++) { - struct drm_display_mode *curmode = NULL; - bool mode_existed = false; - - if (common_modes[i].w > native_mode->hdisplay || - common_modes[i].h > native_mode->vdisplay || - (common_modes[i].w == native_mode->hdisplay && - common_modes[i].h == native_mode->vdisplay)) - continue; - - list_for_each_entry(curmode, &connector->probed_modes, head) { - if (common_modes[i].w == curmode->hdisplay && - common_modes[i].h == curmode->vdisplay) { - mode_existed = true; - break; - } - } - - if (mode_existed) - continue; - - mode = amdgpu_dm_create_common_mode(encoder, - common_modes[i].name, common_modes[i].w, - common_modes[i].h); - drm_mode_probed_add(connector, mode); - amdgpu_connector->num_modes++; - } -} - -static void amdgpu_dm_connector_ddc_get_modes( - struct drm_connector *connector, - struct edid *edid) -{ - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - - if (edid) { - /* empty probed_modes */ - INIT_LIST_HEAD(&connector->probed_modes); - amdgpu_connector->num_modes = - drm_add_edid_modes(connector, edid); - - drm_edid_to_eld(connector, edid); - - amdgpu_dm_get_native_mode(connector); - } else - amdgpu_connector->num_modes = 0; -} - -int amdgpu_dm_connector_get_modes(struct drm_connector *connector) -{ - const struct drm_connector_helper_funcs *helper = - connector->helper_private; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - struct drm_encoder *encoder; - struct edid *edid = amdgpu_connector->edid; - - encoder = helper->best_encoder(connector); - - amdgpu_dm_connector_ddc_get_modes(connector, edid); - amdgpu_dm_connector_add_common_modes(encoder, connector); - return amdgpu_connector->num_modes; -} - -void amdgpu_dm_connector_init_helper( - struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, - int connector_type, - struct dc_link *link, - int link_index) -{ - struct amdgpu_device *adev = dm->ddev->dev_private; - - aconnector->connector_id = link_index; - aconnector->dc_link = link; - aconnector->base.interlace_allowed = false; - aconnector->base.doublescan_allowed = false; - aconnector->base.stereo_allowed = false; - aconnector->base.dpms = DRM_MODE_DPMS_OFF; - aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */ - - mutex_init(&aconnector->hpd_lock); - - /*configure suport HPD hot plug connector_>polled default value is 0 - * which means HPD hot plug not supported*/ - switch (connector_type) { - case DRM_MODE_CONNECTOR_HDMIA: - aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; - break; - case DRM_MODE_CONNECTOR_DisplayPort: - aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; - break; - case DRM_MODE_CONNECTOR_DVID: - aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; - break; - default: - break; - } - - drm_object_attach_property(&aconnector->base.base, - dm->ddev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_NONE); - - drm_object_attach_property(&aconnector->base.base, - adev->mode_info.underscan_property, - UNDERSCAN_OFF); - drm_object_attach_property(&aconnector->base.base, - adev->mode_info.underscan_hborder_property, - 0); - drm_object_attach_property(&aconnector->base.base, - adev->mode_info.underscan_vborder_property, - 0); - -} - -int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); - struct ddc_service *ddc_service = i2c->ddc_service; - struct i2c_command cmd; - int i; - int result = -EIO; - - cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL); - - if (!cmd.payloads) - return result; - - cmd.number_of_payloads = num; - cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; - cmd.speed = 100; - - for (i = 0; i < num; i++) { - cmd.payloads[i].write = !(msgs[i].flags & I2C_M_RD); - cmd.payloads[i].address = msgs[i].addr; - cmd.payloads[i].length = msgs[i].len; - cmd.payloads[i].data = msgs[i].buf; - } - - if (dal_i2caux_submit_i2c_command( - ddc_service->ctx->i2caux, - ddc_service->ddc_pin, - &cmd)) - result = num; - - kfree(cmd.payloads); - return result; -} - -u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm amdgpu_dm_i2c_algo = { - .master_xfer = amdgpu_dm_i2c_xfer, - .functionality = amdgpu_dm_i2c_func, -}; - -static struct amdgpu_i2c_adapter *create_i2c( - struct ddc_service *ddc_service, - int link_index, - int *res) -{ - struct amdgpu_device *adev = ddc_service->ctx->driver_context; - struct amdgpu_i2c_adapter *i2c; - - i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); - i2c->base.owner = THIS_MODULE; - i2c->base.class = I2C_CLASS_DDC; - i2c->base.dev.parent = &adev->pdev->dev; - i2c->base.algo = &amdgpu_dm_i2c_algo; - snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); - i2c_set_adapdata(&i2c->base, i2c); - i2c->ddc_service = ddc_service; - - return i2c; -} - -/* Note: this function assumes that dc_link_detect() was called for the - * dc_link which will be represented by this aconnector. */ -int amdgpu_dm_connector_init( - struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, - uint32_t link_index, - struct amdgpu_encoder *aencoder) -{ - int res = 0; - int connector_type; - struct dc *dc = dm->dc; - struct dc_link *link = dc_get_link_at_index(dc, link_index); - struct amdgpu_i2c_adapter *i2c; - ((struct dc_link *)link)->priv = aconnector; - - DRM_DEBUG_KMS("%s()\n", __func__); - - i2c = create_i2c(link->ddc, link->link_index, &res); - aconnector->i2c = i2c; - res = i2c_add_adapter(&i2c->base); - - if (res) { - DRM_ERROR("Failed to register hw i2c %d\n", link->link_index); - goto out_free; - } - - connector_type = to_drm_connector_type(link->connector_signal); - - res = drm_connector_init( - dm->ddev, - &aconnector->base, - &amdgpu_dm_connector_funcs, - connector_type); - - if (res) { - DRM_ERROR("connector_init failed\n"); - aconnector->connector_id = -1; - goto out_free; - } - - drm_connector_helper_add( - &aconnector->base, - &amdgpu_dm_connector_helper_funcs); - - amdgpu_dm_connector_init_helper( - dm, - aconnector, - connector_type, - link, - link_index); - - drm_mode_connector_attach_encoder( - &aconnector->base, &aencoder->base); - - drm_connector_register(&aconnector->base); - - if (connector_type == DRM_MODE_CONNECTOR_DisplayPort - || connector_type == DRM_MODE_CONNECTOR_eDP) - amdgpu_dm_initialize_dp_connector(dm, aconnector); - -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ - defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - - /* NOTE: this currently will create backlight device even if a panel - * is not connected to the eDP/LVDS connector. - * - * This is less than ideal but we don't have sink information at this - * stage since detection happens after. We can't do detection earlier - * since MST detection needs connectors to be created first. - */ - if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { - /* Event if registration failed, we should continue with - * DM initialization because not having a backlight control - * is better then a black screen. */ - amdgpu_dm_register_backlight_device(dm); - - if (dm->backlight_dev) - dm->backlight_link = link; - } -#endif - -out_free: - if (res) { - kfree(i2c); - aconnector->i2c = NULL; - } - return res; -} - -int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) -{ - switch (adev->mode_info.num_crtc) { - case 1: - return 0x1; - case 2: - return 0x3; - case 3: - return 0x7; - case 4: - return 0xf; - case 5: - return 0x1f; - case 6: - default: - return 0x3f; - } -} - -int amdgpu_dm_encoder_init( - struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index) -{ - struct amdgpu_device *adev = dev->dev_private; - - int res = drm_encoder_init(dev, - &aencoder->base, - &amdgpu_dm_encoder_funcs, - DRM_MODE_ENCODER_TMDS, - NULL); - - aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); - - if (!res) - aencoder->encoder_id = link_index; - else - aencoder->encoder_id = -1; - - drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs); - - return res; -} - -static void manage_dm_interrupts( - struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - bool enable) -{ - /* - * this is not correct translation but will work as soon as VBLANK - * constant is the same as PFLIP - */ - int irq_type = - amdgpu_crtc_idx_to_irq_type( - adev, - acrtc->crtc_id); - - if (enable) { - drm_crtc_vblank_on(&acrtc->base); - amdgpu_irq_get( - adev, - &adev->pageflip_irq, - irq_type); - } else { - - amdgpu_irq_put( - adev, - &adev->pageflip_irq, - irq_type); - drm_crtc_vblank_off(&acrtc->base); - } -} - -static bool is_scaling_state_different( - const struct dm_connector_state *dm_state, - const struct dm_connector_state *old_dm_state) -{ - if (dm_state->scaling != old_dm_state->scaling) - return true; - if (!dm_state->underscan_enable && old_dm_state->underscan_enable) { - if (old_dm_state->underscan_hborder != 0 && old_dm_state->underscan_vborder != 0) - return true; - } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) { - if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0) - return true; - } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder - || dm_state->underscan_vborder != old_dm_state->underscan_vborder) - return true; - return false; -} - -static void remove_stream( - struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - struct dc_stream *stream) -{ - /* this is the update mode case */ - if (adev->dm.freesync_module) - mod_freesync_remove_stream(adev->dm.freesync_module, stream); - - acrtc->otg_inst = -1; - acrtc->enabled = false; -} - -static void handle_cursor_update( - struct drm_plane *plane, - struct drm_plane_state *old_plane_state) -{ - if (!plane->state->fb && !old_plane_state->fb) - return; - - /* Check if it's a cursor on/off update or just cursor move*/ - if (plane->state->fb == old_plane_state->fb) - dm_crtc_cursor_move( - plane->state->crtc, - plane->state->crtc_x, - plane->state->crtc_y); - else { - struct amdgpu_framebuffer *afb = - to_amdgpu_framebuffer(plane->state->fb); - dm_crtc_cursor_set( - (!!plane->state->fb) ? - plane->state->crtc : - old_plane_state->crtc, - (!!plane->state->fb) ? - afb->address : - 0, - plane->state->crtc_w, - plane->state->crtc_h); - } -} - - -static void prepare_flip_isr(struct amdgpu_crtc *acrtc) -{ - - assert_spin_locked(&acrtc->base.dev->event_lock); - WARN_ON(acrtc->event); - - acrtc->event = acrtc->base.state->event; - - /* Set the flip status */ - acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED; - - /* Mark this event as consumed */ - acrtc->base.state->event = NULL; - - DRM_DEBUG_DRIVER("crtc:%d, pflip_stat:AMDGPU_FLIP_SUBMITTED\n", - acrtc->crtc_id); -} - -/* - * Executes flip - * - * Waits on all BO's fences and for proper vblank count - */ -static void amdgpu_dm_do_flip( - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - uint32_t target) -{ - unsigned long flags; - uint32_t target_vblank; - int r, vpos, hpos; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); - struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); - struct amdgpu_device *adev = crtc->dev->dev_private; - bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; - struct dc_flip_addrs addr = { {0} }; - struct dc_surface_update surface_updates[1] = { {0} }; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - - /* Prepare wait for target vblank early - before the fence-waits */ - target_vblank = target - drm_crtc_vblank_count(crtc) + - amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); - - /*TODO This might fail and hence better not used, wait - * explicitly on fences instead - * and in general should be called for - * blocking commit to as per framework helpers - * */ - r = amdgpu_bo_reserve(abo, true); - if (unlikely(r != 0)) { - DRM_ERROR("failed to reserve buffer before flip\n"); - WARN_ON(1); - } - - /* Wait for all fences on this FB */ - WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false, - MAX_SCHEDULE_TIMEOUT) < 0); - - amdgpu_bo_unreserve(abo); - - /* Wait until we're out of the vertical blank period before the one - * targeted by the flip - */ - while ((acrtc->enabled && - (amdgpu_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id, 0, - &vpos, &hpos, NULL, NULL, - &crtc->hwmode) - & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == - (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && - (int)(target_vblank - - amdgpu_get_vblank_counter_kms(adev->ddev, acrtc->crtc_id)) > 0)) { - usleep_range(1000, 1100); - } - - /* Flip */ - spin_lock_irqsave(&crtc->dev->event_lock, flags); - /* update crtc fb */ - crtc->primary->fb = fb; - - WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); - WARN_ON(!acrtc_state->stream); - - addr.address.grph.addr.low_part = lower_32_bits(afb->address); - addr.address.grph.addr.high_part = upper_32_bits(afb->address); - addr.flip_immediate = async_flip; - - - if (acrtc->base.state->event) - prepare_flip_isr(acrtc); - - surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0]; - surface_updates->flip_addr = &addr; - - - dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); - - DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", - __func__, - addr.address.grph.addr.high_part, - addr.address.grph.addr.low_part); - - - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); -} - -static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, - struct drm_device *dev, - struct amdgpu_display_manager *dm, - struct drm_crtc *pcrtc, - bool *wait_for_vblank) -{ - uint32_t i; - struct drm_plane *plane; - struct drm_plane_state *old_plane_state; - struct dc_stream *dc_stream_attach; - struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; - struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); - int planes_count = 0; - unsigned long flags; - - /* update planes when needed */ - for_each_plane_in_state(state, plane, old_plane_state, i) { - struct drm_plane_state *plane_state = plane->state; - struct drm_crtc *crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; - bool pflip_needed; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); - - if (plane->type == DRM_PLANE_TYPE_CURSOR) { - handle_cursor_update(plane, old_plane_state); - continue; - } - - if (!fb || !crtc || pcrtc != crtc || !crtc->state->active || - (!crtc->state->planes_changed && - !pcrtc->state->color_mgmt_changed)) - continue; - - pflip_needed = !state->allow_modeset; - - spin_lock_irqsave(&crtc->dev->event_lock, flags); - if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("add_surface: acrtc %d, already busy\n", - acrtc_attach->crtc_id); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - /* In comit tail framework this cannot happen */ - WARN_ON(1); - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - if (!pflip_needed) { - WARN_ON(!dm_plane_state->surface); - - dc_surfaces_constructed[planes_count] = dm_plane_state->surface; - - dc_stream_attach = acrtc_state->stream; - planes_count++; - - } else if (crtc->state->planes_changed) { - /* Assume even ONE crtc with immediate flip means - * entire can't wait for VBLANK - * TODO Check if it's correct - */ - *wait_for_vblank = - acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? - false : true; - - /* TODO: Needs rework for multiplane flip */ - if (plane->type == DRM_PLANE_TYPE_PRIMARY) - drm_crtc_vblank_get(crtc); - - amdgpu_dm_do_flip( - crtc, - fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank); - - /*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */ - - /*clean up the flags for next usage*/ - acrtc_attach->flip_flags = 0; - } - - } - - if (planes_count) { - unsigned long flags; - - if (pcrtc->state->event) { - - drm_crtc_vblank_get(pcrtc); - - spin_lock_irqsave(&pcrtc->dev->event_lock, flags); - prepare_flip_isr(acrtc_attach); - spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); - } - - if (false == dc_commit_surfaces_to_stream(dm->dc, - dc_surfaces_constructed, - planes_count, - dc_stream_attach)) - dm_error("%s: Failed to attach surface!\n", __func__); - } else { - /*TODO BUG Here should go disable planes on CRTC. */ - } -} - - -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) -{ - struct drm_crtc *crtc; - struct drm_crtc_state *new_state; - struct amdgpu_device *adev = dev->dev_private; - int i; - - /* - * We evade vblanks and pflips on crtc that - * should be changed. We do it here to flush & disable - * interrupts before drm_swap_state is called in drm_atomic_helper_commit - * it will update crtc->dm_crtc_state->stream pointer which is used in - * the ISRs. - */ - for_each_crtc_in_state(state, crtc, new_state, i) { - struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) - manage_dm_interrupts(adev, acrtc, false); - } - - return drm_atomic_helper_commit(dev, state, nonblock); - - /*TODO Handle EINTR, reenable IRQ*/ -} - -void amdgpu_dm_atomic_commit_tail( - struct drm_atomic_state *state) -{ - struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_display_manager *dm = &adev->dm; - struct dm_atomic_state *dm_state; - uint32_t i, j; - uint32_t new_crtcs_count = 0; - struct drm_crtc *crtc, *pcrtc; - struct drm_crtc_state *old_crtc_state; - struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; - struct dc_stream *new_stream = NULL; - unsigned long flags; - bool wait_for_vblank = true; - struct drm_connector *connector; - struct drm_connector_state *old_conn_state; - struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; - - drm_atomic_helper_update_legacy_modeset_state(dev, state); - - dm_state = to_dm_atomic_state(state); - - /* update changed items */ - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_crtc_state *new_state = crtc->state; - new_acrtc_state = to_dm_crtc_state(new_state); - old_acrtc_state = to_dm_crtc_state(old_crtc_state); - - DRM_DEBUG_KMS( - "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " - "planes_changed:%d, mode_changed:%d,active_changed:%d," - "connectors_changed:%d\n", - acrtc->crtc_id, - new_state->enable, - new_state->active, - new_state->planes_changed, - new_state->mode_changed, - new_state->active_changed, - new_state->connectors_changed); - - /* handles headless hotplug case, updating new_state and - * aconnector as needed - */ - - if (modeset_required(new_state)) { - - DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); - - if (!new_acrtc_state->stream) { - /* - * this could happen because of issues with - * userspace notifications delivery. - * In this case userspace tries to set mode on - * display which is disconnect in fact. - * dc_sink in NULL in this case on aconnector. - * We expect reset mode will come soon. - * - * This can also happen when unplug is done - * during resume sequence ended - * - * In this case, we want to pretend we still - * have a sink to keep the pipe running so that - * hw state is consistent with the sw state - */ - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - continue; - } - - - if (old_acrtc_state->stream) - remove_stream(adev, acrtc, old_acrtc_state->stream); - - - /* - * this loop saves set mode crtcs - * we needed to enable vblanks once all - * resources acquired in dc after dc_commit_streams - */ - - /*TODO move all this into dm_crtc_state, get rid of - * new_crtcs array and use old and new atomic states - * instead - */ - new_crtcs[new_crtcs_count] = acrtc; - new_crtcs_count++; - - acrtc->enabled = true; - acrtc->hw_mode = crtc->state->mode; - crtc->hwmode = crtc->state->mode; - } else if (modereset_required(new_state)) { - DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); - - /* i.e. reset mode */ - if (old_acrtc_state->stream) - remove_stream(adev, acrtc, old_acrtc_state->stream); - } - } /* for_each_crtc_in_state() */ - - /* - * Add streams after required streams from new and replaced streams - * are removed from freesync module - */ - if (adev->dm.freesync_module) { - for (i = 0; i < new_crtcs_count; i++) { - struct amdgpu_connector *aconnector = NULL; - new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); - - new_stream = new_acrtc_state->stream; - aconnector = - amdgpu_dm_find_first_crct_matching_connector( - state, - &new_crtcs[i]->base, - false); - if (!aconnector) { - DRM_INFO( - "Atomic commit: Failed to find connector for acrtc id:%d " - "skipping freesync init\n", - new_crtcs[i]->crtc_id); - continue; - } - - mod_freesync_add_stream(adev->dm.freesync_module, - new_stream, &aconnector->caps); - } - } - - if (dm_state->context) - WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); - - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - new_acrtc_state = to_dm_crtc_state(crtc->state); - - if (new_acrtc_state->stream != NULL) { - const struct dc_stream_status *status = - dc_stream_get_status(new_acrtc_state->stream); - - if (!status) - DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc); - else - acrtc->otg_inst = status->primary_otg_inst; - } - } - - /* Handle scaling and undersacn changes*/ - for_each_connector_in_state(state, connector, old_conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct dm_connector_state *con_new_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_old_state = - to_dm_connector_state(old_conn_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - struct dc_stream_status *status = NULL; - - /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) - continue; - - /* Skip any thing not scale or underscan changes */ - if (!is_scaling_state_different(con_new_state, con_old_state)) - continue; - - new_acrtc_state = to_dm_crtc_state(acrtc->base.state); - - update_stream_scaling_settings(&con_new_state->base.crtc->mode, - con_new_state, (struct dc_stream *)new_acrtc_state->stream); - - status = dc_stream_get_status(new_acrtc_state->stream); - WARN_ON(!status); - WARN_ON(!status->surface_count); - - if (!new_acrtc_state->stream) - continue; - - /*TODO How it works with MPO ?*/ - if (!dc_commit_surfaces_to_stream( - dm->dc, - status->surfaces, - status->surface_count, - new_acrtc_state->stream)) - dm_error("%s: Failed to update stream scaling!\n", __func__); - } - - for (i = 0; i < new_crtcs_count; i++) { - /* - * loop to enable interrupts on newly arrived crtc - */ - struct amdgpu_crtc *acrtc = new_crtcs[i]; - new_acrtc_state = to_dm_crtc_state(acrtc->base.state); - - if (adev->dm.freesync_module) - mod_freesync_notify_mode_change( - adev->dm.freesync_module, &new_acrtc_state->stream, 1); - - manage_dm_interrupts(adev, acrtc, true); - } - - /* update planes when needed per crtc*/ - for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { - new_acrtc_state = to_dm_crtc_state(pcrtc->state); - - if (new_acrtc_state->stream) - amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); - } - - - /* - * send vblank event on all events not handled in flip and - * mark consumed event for drm_atomic_helper_commit_hw_done - */ - spin_lock_irqsave(&adev->ddev->event_lock, flags); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - if (acrtc->base.state->event) - drm_send_event_locked(dev, &crtc->state->event->base); - - acrtc->base.state->event = NULL; - } - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - - /* Signal HW programming completion */ - drm_atomic_helper_commit_hw_done(state); - - if (wait_for_vblank) - drm_atomic_helper_wait_for_vblanks(dev, state); - - drm_atomic_helper_cleanup_planes(dev, state); -} - - -static int dm_force_atomic_commit(struct drm_connector *connector) -{ - int ret = 0; - struct drm_device *ddev = connector->dev; - struct drm_atomic_state *state = drm_atomic_state_alloc(ddev); - struct amdgpu_crtc *disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); - struct drm_plane *plane = disconnected_acrtc->base.primary; - struct drm_connector_state *conn_state; - struct drm_crtc_state *crtc_state; - struct drm_plane_state *plane_state; - - if (!state) - return -ENOMEM; - - state->acquire_ctx = ddev->mode_config.acquire_ctx; - - /* Construct an atomic state to restore previous display setting */ - - /* - * Attach connectors to drm_atomic_state - */ - conn_state = drm_atomic_get_connector_state(state, connector); - - ret = PTR_ERR_OR_ZERO(conn_state); - if (ret) - goto err; - - /* Attach crtc to drm_atomic_state*/ - crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base); - - ret = PTR_ERR_OR_ZERO(crtc_state); - if (ret) - goto err; - - /* force a restore */ - crtc_state->mode_changed = true; - - /* Attach plane to drm_atomic_state */ - plane_state = drm_atomic_get_plane_state(state, plane); - - ret = PTR_ERR_OR_ZERO(plane_state); - if (ret) - goto err; - - - /* Call commit internally with the state we just constructed */ - ret = drm_atomic_commit(state); - if (!ret) - return 0; - -err: - DRM_ERROR("Restoring old state failed with %i\n", ret); - drm_atomic_state_put(state); - - return ret; -} - -/* - * This functions handle all cases when set mode does not come upon hotplug. - * This include when the same display is unplugged then plugged back into the - * same port and when we are running without usermode desktop manager supprot - */ -void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) -{ - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct amdgpu_crtc *disconnected_acrtc; - struct dm_crtc_state *acrtc_state; - - if (!aconnector->dc_sink || !connector->state || !connector->encoder) - return; - - disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); - acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state); - - if (!disconnected_acrtc || !acrtc_state->stream) - return; - - /* - * If the previous sink is not released and different from the current, - * we deduce we are in a state where we can not rely on usermode call - * to turn on the display, so we do it here - */ - if (acrtc_state->stream->sink != aconnector->dc_sink) - dm_force_atomic_commit(&aconnector->base); -} - -static uint32_t add_val_sets_surface( - struct dc_validation_set *val_sets, - uint32_t set_count, - const struct dc_stream *stream, - struct dc_surface *surface) -{ - uint32_t i = 0, j = 0; - - while (i < set_count) { - if (val_sets[i].stream == stream) { - while (val_sets[i].surfaces[j]) - j++; - break; - } - ++i; - } - - val_sets[i].surfaces[j] = surface; - val_sets[i].surface_count++; - - return val_sets[i].surface_count; -} - -static uint32_t update_in_val_sets_stream( - struct dc_validation_set *val_sets, - uint32_t set_count, - struct dc_stream *old_stream, - struct dc_stream *new_stream, - struct drm_crtc *crtc) -{ - uint32_t i = 0; - - while (i < set_count) { - if (val_sets[i].stream == old_stream) - break; - ++i; - } - - val_sets[i].stream = new_stream; - - if (i == set_count) - /* nothing found. add new one to the end */ - return set_count + 1; - - return set_count; -} - -static uint32_t remove_from_val_sets( - struct dc_validation_set *val_sets, - uint32_t set_count, - const struct dc_stream *stream) -{ - int i; - - for (i = 0; i < set_count; i++) - if (val_sets[i].stream == stream) - break; - - if (i == set_count) { - /* nothing found */ - return set_count; - } - - set_count--; - - for (; i < set_count; i++) { - val_sets[i] = val_sets[i + 1]; - } - - return set_count; -} - -/*` - * Grabs all modesetting locks to serialize against any blocking commits, - * Waits for completion of all non blocking commits. - */ -static int do_aquire_global_lock( - struct drm_device *dev, - struct drm_atomic_state *state) -{ - struct drm_crtc *crtc; - struct drm_crtc_commit *commit; - long ret; - - /* Adding all modeset locks to aquire_ctx will - * ensure that when the framework release it the - * extra locks we are locking here will get released to - */ - ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx); - if (ret) - return ret; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - spin_lock(&crtc->commit_lock); - commit = list_first_entry_or_null(&crtc->commit_list, - struct drm_crtc_commit, commit_entry); - if (commit) - drm_crtc_commit_get(commit); - spin_unlock(&crtc->commit_lock); - - if (!commit) - continue; - - /* Make sure all pending HW programming completed and - * page flips done - */ - ret = wait_for_completion_interruptible_timeout(&commit->hw_done, 10*HZ); - - if (ret > 0) - ret = wait_for_completion_interruptible_timeout( - &commit->flip_done, 10*HZ); - - if (ret == 0) - DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done " - "timed out\n", crtc->base.id, crtc->name); - - drm_crtc_commit_put(commit); - } - - return ret < 0 ? ret : 0; -} - -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) -{ - struct dm_atomic_state *dm_state; - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; - struct drm_plane *plane; - struct drm_plane_state *plane_state; - int i, j; - int ret; - struct amdgpu_device *adev = dev->dev_private; - struct dc *dc = adev->dm.dc; - struct drm_connector *connector; - struct drm_connector_state *conn_state; - int set_count; - struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; - struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; - - /* - * This bool will be set for true for any modeset/reset - * or surface update which implies non fast surface update. - */ - bool lock_and_validation_needed = false; - - ret = drm_atomic_helper_check_modeset(dev, state); - - if (ret) { - DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); - return ret; - } - - dm_state = to_dm_atomic_state(state); - - /* copy existing configuration */ - set_count = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - - old_acrtc_state = to_dm_crtc_state(crtc->state); - - if (old_acrtc_state->stream) { - dc_stream_retain(old_acrtc_state->stream); - set[set_count].stream = old_acrtc_state->stream; - ++set_count; - } - } - - /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ - /* update changed items */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - struct amdgpu_crtc *acrtc = NULL; - struct amdgpu_connector *aconnector = NULL; - old_acrtc_state = to_dm_crtc_state(crtc->state); - new_acrtc_state = to_dm_crtc_state(crtc_state); - acrtc = to_amdgpu_crtc(crtc); - - aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); - - DRM_DEBUG_KMS( - "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " - "planes_changed:%d, mode_changed:%d,active_changed:%d," - "connectors_changed:%d\n", - acrtc->crtc_id, - crtc_state->enable, - crtc_state->active, - crtc_state->planes_changed, - crtc_state->mode_changed, - crtc_state->active_changed, - crtc_state->connectors_changed); - - if (modeset_required(crtc_state)) { - - struct dc_stream *new_stream = NULL; - struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_conn_state = NULL; - - if (aconnector) { - conn_state = drm_atomic_get_connector_state(state, &aconnector->base); - if (IS_ERR(conn_state)) { - ret = PTR_ERR_OR_ZERO(conn_state); - goto fail; - } - - dm_conn_state = to_dm_connector_state(conn_state); - } - - new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); - - /* - * we can have no stream on ACTION_SET if a display - * was disconnected during S3, in this case it not and - * error, the OS will be updated after detection, and - * do the right thing on next atomic commit - */ - if (!new_stream) { - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - break; - } - - if (new_acrtc_state->stream) - dc_stream_release(new_acrtc_state->stream); - - new_acrtc_state->stream = new_stream; - - set_count = update_in_val_sets_stream( - set, - set_count, - old_acrtc_state->stream, - new_acrtc_state->stream, - crtc); - - lock_and_validation_needed = true; - - } else if (modereset_required(crtc_state)) { - - /* i.e. reset mode */ - if (new_acrtc_state->stream) { - set_count = remove_from_val_sets( - set, - set_count, - new_acrtc_state->stream); - - dc_stream_release(new_acrtc_state->stream); - new_acrtc_state->stream = NULL; - - lock_and_validation_needed = true; - } - } - - - /* - * Hack: Commit needs planes right now, specifically for gamma - * TODO rework commit to check CRTC for gamma change - */ - if (crtc_state->color_mgmt_changed) { - - ret = drm_atomic_add_affected_planes(state, crtc); - if (ret) - goto fail; - } - } - - /* Check scaling and undersacn changes*/ - /*TODO Removed scaling changes validation due to inability to commit - * new stream into context w\o causing full reset. Need to - * decide how to handle. - */ - for_each_connector_in_state(state, connector, conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct dm_connector_state *con_old_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_new_state = - to_dm_connector_state(conn_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); - - /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) - continue; - - /* Skip any thing not scale or underscan chnages */ - if (!is_scaling_state_different(con_new_state, con_old_state)) - continue; - - lock_and_validation_needed = true; - } - - for_each_crtc_in_state(state, crtc, crtc_state, i) { - new_acrtc_state = to_dm_crtc_state(crtc_state); - - for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_crtc *plane_crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; - bool pflip_needed; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); - - /*TODO Implement atomic check for cursor plane */ - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; - - if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active) - continue; - - WARN_ON(!new_acrtc_state->stream); - - pflip_needed = !state->allow_modeset; - if (!pflip_needed) { - struct dc_surface *surface; - - surface = dc_create_surface(dc); - - ret = fill_plane_attributes( - plane_crtc->dev->dev_private, - surface, - plane_state, - crtc_state, - false); - if (ret) - goto fail; - - - if (dm_plane_state->surface) - dc_surface_release(dm_plane_state->surface); - - dm_plane_state->surface = surface; - - add_val_sets_surface(set, - set_count, - new_acrtc_state->stream, - surface); - - lock_and_validation_needed = true; - } - } - } - - /* Run this here since we want to validate the streams we created */ - ret = drm_atomic_helper_check_planes(dev, state); - if (ret) - goto fail; - - /* - * For full updates case when - * removing/adding/updating streams on once CRTC while flipping - * on another CRTC, - * acquiring global lock will guarantee that any such full - * update commit - * will wait for completion of any outstanding flip using DRMs - * synchronization events. - */ - - if (lock_and_validation_needed) { - - ret = do_aquire_global_lock(dev, state); - if (ret) - goto fail; - WARN_ON(dm_state->context); - dm_state->context = dc_get_validate_context(dc, set, set_count); - if (!dm_state->context) { - ret = -EINVAL; - goto fail; - } - } - - /* Must be success */ - WARN_ON(ret); - return ret; - -fail: - if (ret == -EDEADLK) - DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); - else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); - else - DRM_ERROR("Atomic check failed with err: %d .\n", ret); - - return ret; -} - -static bool is_dp_capable_without_timing_msa( - struct dc *dc, - struct amdgpu_connector *amdgpu_connector) -{ - uint8_t dpcd_data; - bool capable = false; - - if (amdgpu_connector->dc_link && - dm_helpers_dp_read_dpcd( - NULL, - amdgpu_connector->dc_link, - DP_DOWN_STREAM_PORT_COUNT, - &dpcd_data, - sizeof(dpcd_data))) { - capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false; - } - - return capable; -} -void amdgpu_dm_add_sink_to_freesync_module( - struct drm_connector *connector, - struct edid *edid) -{ - int i; - uint64_t val_capable; - bool edid_check_required; - struct detailed_timing *timing; - struct detailed_non_pixel *data; - struct detailed_data_monitor_range *range; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; - edid_check_required = false; - if (!amdgpu_connector->dc_sink) { - DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); - return; - } - if (!adev->dm.freesync_module) - return; - /* - * if edid non zero restrict freesync only for dp and edp - */ - if (edid) { - if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT - || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { - edid_check_required = is_dp_capable_without_timing_msa( - adev->dm.dc, - amdgpu_connector); - } - } - val_capable = 0; - if (edid_check_required == true && (edid->version > 1 || - (edid->version == 1 && edid->revision > 1))) { - for (i = 0; i < 4; i++) { - - timing = &edid->detailed_timings[i]; - data = &timing->data.other_data; - range = &data->data.range; - /* - * Check if monitor has continuous frequency mode - */ - if (data->type != EDID_DETAIL_MONITOR_RANGE) - continue; - /* - * Check for flag range limits only. If flag == 1 then - * no additional timing information provided. - * Default GTF, GTF Secondary curve and CVT are not - * supported - */ - if (range->flags != 1) - continue; - - amdgpu_connector->min_vfreq = range->min_vfreq; - amdgpu_connector->max_vfreq = range->max_vfreq; - amdgpu_connector->pixel_clock_mhz = - range->pixel_clock_mhz * 10; - break; - } - - if (amdgpu_connector->max_vfreq - - amdgpu_connector->min_vfreq > 10) { - amdgpu_connector->caps.supported = true; - amdgpu_connector->caps.min_refresh_in_micro_hz = - amdgpu_connector->min_vfreq * 1000000; - amdgpu_connector->caps.max_refresh_in_micro_hz = - amdgpu_connector->max_vfreq * 1000000; - val_capable = 1; - } - } - - /* - * TODO figure out how to notify user-mode or DRM of freesync caps - * once we figure out how to deal with freesync in an upstreamable - * fashion - */ - -} - -void amdgpu_dm_remove_sink_from_freesync_module( - struct drm_connector *connector) -{ - /* - * TODO fill in once we figure out how to deal with freesync in - * an upstreamable fashion - */ -} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h deleted file mode 100644 index 94de6a3736fc..000000000000 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2012-13 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __AMDGPU_DM_TYPES_H__ -#define __AMDGPU_DM_TYPES_H__ - -#include -#include -#include "dc.h" - -struct amdgpu_framebuffer; -struct amdgpu_display_manager; -struct dc_validation_set; -struct dc_surface; -/* TODO rename to dc_stream_state */ -struct dc_stream; - - -struct dm_plane_state { - struct drm_plane_state base; - struct dc_surface *surface; -}; - -struct dm_crtc_state { - struct drm_crtc_state base; - struct dc_stream *stream; -}; - -#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) - -struct dm_atomic_state { - struct drm_atomic_state base; - - struct validate_context *context; -}; - -#define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) - - -/*TODO Jodan Hersen use the one in amdgpu_dm*/ -int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs); -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct drm_plane *plane, - uint32_t link_index); -int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_connector *amdgpu_connector, - uint32_t link_index, - struct amdgpu_encoder *amdgpu_encoder); -int amdgpu_dm_encoder_init( - struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index); - -void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); -void amdgpu_dm_connector_destroy(struct drm_connector *connector); -void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); - -int amdgpu_dm_connector_get_modes(struct drm_connector *connector); - -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock); - -void amdgpu_dm_atomic_commit_tail( - struct drm_atomic_state *state); - -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state); - -void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); -struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( - struct drm_connector *connector); - -int amdgpu_dm_connector_atomic_set_property( - struct drm_connector *connector, - struct drm_connector_state *state, - struct drm_property *property, - uint64_t val); - -int amdgpu_dm_connector_atomic_get_property( - struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val); - -int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); - -void amdgpu_dm_connector_init_helper( - struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, - int connector_type, - struct dc_link *link, - int link_index); - -int amdgpu_dm_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode); - -void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); - -void amdgpu_dm_add_sink_to_freesync_module( - struct drm_connector *connector, - struct edid *edid); - -void amdgpu_dm_remove_sink_from_freesync_module( - struct drm_connector *connector); - -extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; - -#endif /* __AMDGPU_DM_TYPES_H__ */ -- GitLab From b830ebc910f641286ea0b816614db43d1135fc1a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 26 Jul 2017 21:03:22 -0400 Subject: [PATCH 0707/2898] drm/amd/display: Fix ckeckpatch problems in amdgpu_dm Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 179 +++++++++--------- 1 file changed, 94 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 646a946a2571..02ca9d6225eb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1682,14 +1682,13 @@ static int dm_crtc_cursor_set( int ret; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; + ret = EINVAL; - DRM_DEBUG_KMS( - "%s: crtc_id=%d with size %d to %d \n", - __func__, - amdgpu_crtc->crtc_id, - width, - height); + DRM_DEBUG_KMS("%s: crtc_id=%d with size %d to %d \n", + __func__, + amdgpu_crtc->crtc_id, + width, + height); if (!address) { /* turn off cursor */ @@ -1839,6 +1838,7 @@ static int get_fb_info( { struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); int r = amdgpu_bo_reserve(rbo, false); + if (unlikely(r)) { DRM_ERROR("Unable to reserve buffer\n"); return r; @@ -1946,10 +1946,9 @@ static int fill_plane_attributes_from_fb( memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); - /* Fill GFX params */ - if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) - { - unsigned bankw, bankh, mtaspect, tile_split, num_banks; + /* Fill GFX8 params */ + if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { + unsigned int bankw, bankh, mtaspect, tile_split, num_banks; bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH); bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT); @@ -2162,7 +2161,8 @@ static enum dc_color_depth convert_color_depth_from_display_info( uint32_t bpc = connector->display_info.bpc; /* Limited color depth to 8bit - * TODO: Still need to handle deep color*/ + * TODO: Still need to handle deep color + */ if (bpc > 8) bpc = 8; @@ -2195,6 +2195,7 @@ static enum dc_aspect_ratio get_aspect_ratio( { int32_t width = mode_in->crtc_hdisplay * 9; int32_t height = mode_in->crtc_vdisplay * 16; + if ((width - height) < 10 && (width - height) > -10) return ASPECT_RATIO_16_9; else @@ -2252,6 +2253,7 @@ static void fill_stream_properties_from_drm_display_mode( const struct drm_connector *connector) { struct dc_crtc_timing *timing_out = &stream->timing; + memset(timing_out, 0, sizeof(struct dc_crtc_timing)); timing_out->h_border_left = 0; @@ -2296,6 +2298,7 @@ static void fill_stream_properties_from_drm_display_mode( { struct dc_transfer_func *tf = dc_create_transfer_func(); + tf->type = TF_TYPE_PREDEFINED; tf->tf = TRANSFER_FUNCTION_SRGB; stream->out_transfer_func = tf; @@ -2322,7 +2325,7 @@ static void fill_audio_info( i++; } - if(cea_revision >= 3) { + if (cea_revision >= 3) { audio_info->mode_count = edid_caps->audio_mode_count; for (i = 0; i < audio_info->mode_count; ++i) { @@ -2341,7 +2344,7 @@ static void fill_audio_info( audio_info->flags.all = edid_caps->speaker_flags; /* TODO: We only check for the progressive mode, check for interlace mode too */ - if(drm_connector->latency_present[0]) { + if (drm_connector->latency_present[0]) { audio_info->video_latency = drm_connector->video_latency[0]; audio_info->audio_latency = drm_connector->audio_latency[0]; } @@ -2359,7 +2362,7 @@ static void copy_crtc_timing_for_drm_display_mode( dst_mode->crtc_clock = src_mode->crtc_clock; dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start; dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end; - dst_mode->crtc_hsync_start= src_mode->crtc_hsync_start; + dst_mode->crtc_hsync_start = src_mode->crtc_hsync_start; dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end; dst_mode->crtc_htotal = src_mode->crtc_htotal; dst_mode->crtc_hskew = src_mode->crtc_hskew; @@ -2397,12 +2400,12 @@ static struct dc_stream *create_stream_for_sink( struct drm_display_mode mode = *drm_mode; bool native_mode_found = false; - if (NULL == aconnector) { + if (aconnector == NULL) { DRM_ERROR("aconnector is NULL!\n"); goto drm_connector_null; } - if (NULL == dm_state) { + if (dm_state == NULL) { DRM_ERROR("dm_state is NULL!\n"); goto dm_state_null; } @@ -2410,7 +2413,7 @@ static struct dc_stream *create_stream_for_sink( drm_connector = &aconnector->base; stream = dc_create_stream_for_sink(aconnector->dc_sink); - if (NULL == stream) { + if (stream == NULL) { DRM_ERROR("Failed to create stream for sink!\n"); goto stream_create_fail; } @@ -2428,7 +2431,7 @@ static struct dc_stream *create_stream_for_sink( struct drm_display_mode, head); - if (NULL == preferred_mode) { + if (preferred_mode == NULL) { /* This may not be an error, the use case is when we we have no * usermode calls to reset and set mode upon hotplug. In this * case, we call set mode ourselves to restore the previous mode @@ -2818,13 +2821,13 @@ int amdgpu_dm_connector_mode_valid( dc_sink = to_amdgpu_connector(connector)->dc_sink; - if (NULL == dc_sink) { + if (dc_sink == NULL) { DRM_ERROR("dc_sink is NULL!\n"); goto fail; } stream = dc_create_stream_for_sink(dc_sink); - if (NULL == stream) { + if (stream == NULL) { DRM_ERROR("Failed to create stream for sink!\n"); goto fail; } @@ -2849,11 +2852,11 @@ int amdgpu_dm_connector_mode_valid( static const struct drm_connector_helper_funcs amdgpu_dm_connector_helper_funcs = { /* - * If hotplug a second bigger display in FB Con mode, bigger resolution - * modes will be filtered by drm_mode_validate_size(), and those modes - * is missing after user start lightdm. So we need to renew modes list. - * in get_modes call back, not just return the modes count - */ + * If hotplug a second bigger display in FB Con mode, bigger resolution + * modes will be filtered by drm_mode_validate_size(), and those modes + * is missing after user start lightdm. So we need to renew modes list. + * in get_modes call back, not just return the modes count + */ .get_modes = get_modes, .mode_valid = amdgpu_dm_connector_mode_valid, .best_encoder = best_encoder @@ -3064,11 +3067,11 @@ static void dm_plane_helper_cleanup_fb( if (unlikely(r)) { DRM_ERROR("failed to reserve rbo before unpin\n"); return; - } else { - amdgpu_bo_unpin(rbo); - amdgpu_bo_unreserve(rbo); - amdgpu_bo_unref(&rbo); - }; + } + + amdgpu_bo_unpin(rbo); + amdgpu_bo_unreserve(rbo); + amdgpu_bo_unref(&rbo); } int dm_create_validation_set_for_connector(struct drm_connector *connector, @@ -3084,14 +3087,14 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, (mode->flags & DRM_MODE_FLAG_DBLSCAN)) return result; - if (NULL == dc_sink) { + if (dc_sink == NULL) { DRM_ERROR("dc_sink is NULL!\n"); return result; } stream = dc_create_stream_for_sink(dc_sink); - if (NULL == stream) { + if (stream == NULL) { DRM_ERROR("Failed to create stream for sink!\n"); return result; } @@ -3230,10 +3233,8 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, return 0; fail: - if (acrtc) - kfree(acrtc); - if (cursor_plane) - kfree(cursor_plane); + kfree(acrtc); + kfree(cursor_plane); acrtc->crtc_id = -1; return res; } @@ -3280,12 +3281,13 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector) if (!list_empty(&connector->probed_modes)) { struct drm_display_mode *preferred_mode = NULL; + list_for_each_entry(preferred_mode, - &connector->probed_modes, - head) { - if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) { - amdgpu_encoder->native_mode = *preferred_mode; - } + &connector->probed_modes, + head) { + if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) + amdgpu_encoder->native_mode = *preferred_mode; + break; } @@ -3303,7 +3305,7 @@ static struct drm_display_mode *amdgpu_dm_create_common_mode( mode = drm_mode_duplicate(dev, native_mode); - if(mode == NULL) + if (mode == NULL) return NULL; mode->hdisplay = hdisplay; @@ -3329,7 +3331,7 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, char name[DRM_DISPLAY_MODE_LEN]; int w; int h; - }common_modes[] = { + } common_modes[] = { { "640x480", 640, 480}, { "800x600", 800, 600}, { "1024x768", 1024, 768}, @@ -3343,21 +3345,21 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, {"1920x1200", 1920, 1200} }; - n = sizeof(common_modes) / sizeof(common_modes[0]); + n = ARRAY_SIZE(common_modes); for (i = 0; i < n; i++) { struct drm_display_mode *curmode = NULL; bool mode_existed = false; if (common_modes[i].w > native_mode->hdisplay || - common_modes[i].h > native_mode->vdisplay || - (common_modes[i].w == native_mode->hdisplay && - common_modes[i].h == native_mode->vdisplay)) - continue; + common_modes[i].h > native_mode->vdisplay || + (common_modes[i].w == native_mode->hdisplay && + common_modes[i].h == native_mode->vdisplay)) + continue; list_for_each_entry(curmode, &connector->probed_modes, head) { if (common_modes[i].w == curmode->hdisplay && - common_modes[i].h == curmode->vdisplay) { + common_modes[i].h == curmode->vdisplay) { mode_existed = true; break; } @@ -3429,8 +3431,9 @@ void amdgpu_dm_connector_init_helper( mutex_init(&aconnector->hpd_lock); - /*configure suport HPD hot plug connector_>polled default value is 0 - * which means HPD hot plug not supported*/ + /* configure support HPD hot plug connector_>polled default value is 0 + * which means HPD hot plug not supported + */ switch (connector_type) { case DRM_MODE_CONNECTOR_HDMIA: aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; @@ -3470,7 +3473,7 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, int i; int result = -EIO; - cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL); + cmd.payloads = kcalloc(num, sizeof(struct i2c_payload), GFP_KERNEL); if (!cmd.payloads) return result; @@ -3514,12 +3517,12 @@ static struct amdgpu_i2c_adapter *create_i2c( struct amdgpu_device *adev = ddc_service->ctx->driver_context; struct amdgpu_i2c_adapter *i2c; - i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL); + i2c = kzalloc(sizeof(struct amdgpu_i2c_adapter), GFP_KERNEL); i2c->base.owner = THIS_MODULE; i2c->base.class = I2C_CLASS_DDC; i2c->base.dev.parent = &adev->pdev->dev; i2c->base.algo = &amdgpu_dm_i2c_algo; - snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); + snprintf(i2c->base.name, sizeof(i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); i2c_set_adapdata(&i2c->base, i2c); i2c->ddc_service = ddc_service; @@ -3527,7 +3530,8 @@ static struct amdgpu_i2c_adapter *create_i2c( } /* Note: this function assumes that dc_link_detect() was called for the - * dc_link which will be represented by this aconnector. */ + * dc_link which will be represented by this aconnector. + */ int amdgpu_dm_connector_init( struct amdgpu_display_manager *dm, struct amdgpu_connector *aconnector, @@ -3599,7 +3603,8 @@ int amdgpu_dm_connector_init( if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { /* Event if registration failed, we should continue with * DM initialization because not having a backlight control - * is better then a black screen. */ + * is better then a black screen. + */ amdgpu_dm_register_backlight_device(dm); if (dm->backlight_dev) @@ -3701,9 +3706,9 @@ static bool is_scaling_state_different( } else if (dm_state->underscan_enable && !old_dm_state->underscan_enable) { if (dm_state->underscan_hborder != 0 && dm_state->underscan_vborder != 0) return true; - } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder - || dm_state->underscan_vborder != old_dm_state->underscan_vborder) - return true; + } else if (dm_state->underscan_hborder != old_dm_state->underscan_hborder || + dm_state->underscan_vborder != old_dm_state->underscan_vborder) + return true; return false; } @@ -3794,11 +3799,11 @@ static void amdgpu_dm_do_flip( target_vblank = target - drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); - /*TODO This might fail and hence better not used, wait + /* TODO This might fail and hence better not used, wait * explicitly on fences instead * and in general should be called for * blocking commit to as per framework helpers - * */ + */ r = amdgpu_bo_reserve(abo, true); if (unlikely(r != 0)) { DRM_ERROR("failed to reserve buffer before flip\n"); @@ -3897,7 +3902,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, DRM_ERROR("add_surface: acrtc %d, already busy\n", acrtc_attach->crtc_id); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - /* In comit tail framework this cannot happen */ + /* In commit tail framework this cannot happen */ WARN_ON(1); } spin_unlock_irqrestore(&crtc->dev->event_lock, flags); @@ -4016,6 +4021,7 @@ void amdgpu_dm_atomic_commit_tail( for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_crtc_state *new_state = crtc->state; + new_acrtc_state = to_dm_crtc_state(new_state); old_acrtc_state = to_dm_crtc_state(old_crtc_state); @@ -4041,20 +4047,20 @@ void amdgpu_dm_atomic_commit_tail( if (!new_acrtc_state->stream) { /* - * this could happen because of issues with - * userspace notifications delivery. - * In this case userspace tries to set mode on - * display which is disconnect in fact. - * dc_sink in NULL in this case on aconnector. - * We expect reset mode will come soon. - * - * This can also happen when unplug is done - * during resume sequence ended - * - * In this case, we want to pretend we still - * have a sink to keep the pipe running so that - * hw state is consistent with the sw state - */ + * this could happen because of issues with + * userspace notifications delivery. + * In this case userspace tries to set mode on + * display which is disconnect in fact. + * dc_sink in NULL in this case on aconnector. + * We expect reset mode will come soon. + * + * This can also happen when unplug is done + * during resume sequence ended + * + * In this case, we want to pretend we still + * have a sink to keep the pipe running so that + * hw state is consistent with the sw state + */ DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); continue; @@ -4097,6 +4103,7 @@ void amdgpu_dm_atomic_commit_tail( if (adev->dm.freesync_module) { for (i = 0; i < new_crtcs_count; i++) { struct amdgpu_connector *aconnector = NULL; + new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); new_stream = new_acrtc_state->stream; @@ -4106,10 +4113,9 @@ void amdgpu_dm_atomic_commit_tail( &new_crtcs[i]->base, false); if (!aconnector) { - DRM_INFO( - "Atomic commit: Failed to find connector for acrtc id:%d " - "skipping freesync init\n", - new_crtcs[i]->crtc_id); + DRM_INFO("Atomic commit: Failed to find connector for acrtc id:%d " + "skipping freesync init\n", + new_crtcs[i]->crtc_id); continue; } @@ -4124,6 +4130,7 @@ void amdgpu_dm_atomic_commit_tail( list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + new_acrtc_state = to_dm_crtc_state(crtc->state); if (new_acrtc_state->stream != NULL) { @@ -4181,6 +4188,7 @@ void amdgpu_dm_atomic_commit_tail( * loop to enable interrupts on newly arrived crtc */ struct amdgpu_crtc *acrtc = new_crtcs[i]; + new_acrtc_state = to_dm_crtc_state(acrtc->base.state); if (adev->dm.freesync_module) @@ -4375,9 +4383,8 @@ static uint32_t remove_from_val_sets( set_count--; - for (; i < set_count; i++) { + for (; i < set_count; i++) val_sets[i] = val_sets[i + 1]; - } return set_count; } @@ -4424,7 +4431,7 @@ static int do_aquire_global_lock( if (ret == 0) DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done " - "timed out\n", crtc->base.id, crtc->name); + "timed out\n", crtc->base.id, crtc->name); drm_crtc_commit_put(commit); } @@ -4483,6 +4490,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; + old_acrtc_state = to_dm_crtc_state(crtc->state); new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); @@ -4591,7 +4599,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) continue; - /* Skip any thing not scale or underscan chnages */ + /* Skip any thing not scale or underscan changes */ if (!is_scaling_state_different(con_new_state, con_old_state)) continue; @@ -4724,6 +4732,7 @@ void amdgpu_dm_add_sink_to_freesync_module( struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; + edid_check_required = false; if (!amdgpu_connector->dc_sink) { DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); -- GitLab From bdf9a1a0e16c9e60be796341d79da87503a1cf70 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 25 Jul 2017 16:45:18 -0400 Subject: [PATCH 0708/2898] drm/amd/display: move ocsc programming from opp to dpp for dce Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 201 +---------------- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 31 --- .../drm/amd/display/dc/dce/dce_transform.c | 210 ++++++++++++++++++ .../drm/amd/display/dc/dce/dce_transform.h | 30 +++ .../display/dc/dce110/dce110_hw_sequencer.c | 35 ++- .../amd/display/dc/dce110/dce110_opp_csc_v.c | 45 ++-- .../drm/amd/display/dc/dce110/dce110_opp_v.c | 2 - .../drm/amd/display/dc/dce110/dce110_opp_v.h | 6 - .../display/dc/dce110/dce110_transform_v.c | 2 + .../display/dc/dce110/dce110_transform_v.h | 7 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 7 +- 11 files changed, 306 insertions(+), 270 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index f716a9e8784e..7abf252369fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -55,31 +55,9 @@ enum { OUTPUT_CSC_MATRIX_SIZE = 12 }; -static const struct out_csc_color_matrix global_color_matrix[] = { -{ COLOR_SPACE_SRGB, - { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, -{ COLOR_SPACE_SRGB_LIMITED, - { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, -{ COLOR_SPACE_YCBCR601, - { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, - 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, - 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, -/* TODO: correct values below */ -{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, - 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, -{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, - 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } -}; -enum csc_color_mode { - /* 00 - BITS2:0 Bypass */ - CSC_COLOR_MODE_GRAPHICS_BYPASS, - /* 01 - hard coded coefficient TV RGB */ - CSC_COLOR_MODE_GRAPHICS_PREDEFINED, - /* 04 - programmable OUTPUT CSC coefficient */ - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, -}; + + @@ -781,181 +759,8 @@ void dce110_opp_program_fmt( return; } -static void program_color_matrix( - struct dce110_opp *opp110, - const struct out_csc_color_matrix *tbl_entry, - enum grph_color_adjust_option options) -{ - { - REG_SET_2(OUTPUT_CSC_C11_C12, 0, - OUTPUT_CSC_C11, tbl_entry->regval[0], - OUTPUT_CSC_C12, tbl_entry->regval[1]); - } - { - REG_SET_2(OUTPUT_CSC_C13_C14, 0, - OUTPUT_CSC_C11, tbl_entry->regval[2], - OUTPUT_CSC_C12, tbl_entry->regval[3]); - } - { - REG_SET_2(OUTPUT_CSC_C21_C22, 0, - OUTPUT_CSC_C11, tbl_entry->regval[4], - OUTPUT_CSC_C12, tbl_entry->regval[5]); - } - { - REG_SET_2(OUTPUT_CSC_C23_C24, 0, - OUTPUT_CSC_C11, tbl_entry->regval[6], - OUTPUT_CSC_C12, tbl_entry->regval[7]); - } - { - REG_SET_2(OUTPUT_CSC_C31_C32, 0, - OUTPUT_CSC_C11, tbl_entry->regval[8], - OUTPUT_CSC_C12, tbl_entry->regval[9]); - } - { - REG_SET_2(OUTPUT_CSC_C33_C34, 0, - OUTPUT_CSC_C11, tbl_entry->regval[10], - OUTPUT_CSC_C12, tbl_entry->regval[11]); - } -} -static bool configure_graphics_mode( - struct dce110_opp *opp110, - enum csc_color_mode config, - enum graphics_csc_adjust_type csc_adjust_type, - enum dc_color_space color_space) -{ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 0); - if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { - if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 4); - } else { - - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 0); - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 1); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 2); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 3); - break; - default: - return false; - } - } - } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { - switch (color_space) { - case COLOR_SPACE_SRGB: - /* by pass */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 0); - break; - break; - case COLOR_SPACE_SRGB_LIMITED: - /* TV RGB */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 1); - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - /* YCbCr601 */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 2); - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - /* YCbCr709 */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 3); - break; - default: - return false; - } - - } else - /* by pass */ - REG_SET(OUTPUT_CSC_CONTROL, 0, - OUTPUT_CSC_GRPH_MODE, 0); - - return true; -} - -void dce110_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - - program_color_matrix( - opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); - - /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ - configure_graphics_mode(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, - tbl_entry->color_space); -} - -void dce110_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - enum csc_color_mode config = - CSC_COLOR_MODE_GRAPHICS_PREDEFINED; - - if (default_adjust->force_hw_default == false) { - const struct out_csc_color_matrix *elm; - /* currently parameter not in use */ - enum grph_color_adjust_option option = - GRPH_COLOR_MATRIX_HW_DEFAULT; - uint32_t i; - /* - * HW default false we program locally defined matrix - * HW default true we use predefined hw matrix and we - * do not need to program matrix - * OEM wants the HW default via runtime parameter. - */ - option = GRPH_COLOR_MATRIX_SW; - - for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { - elm = &global_color_matrix[i]; - if (elm->color_space != default_adjust->out_color_space) - continue; - /* program the matrix with default values from this - * file */ - program_color_matrix(opp110, elm, option); - config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - break; - } - } - - /* configure the what we programmed : - * 1. Default values from this file - * 2. Use hardware default from ROM_A and we do not need to program - * matrix */ - - configure_graphics_mode(opp110, config, - default_adjust->csc_adjust_type, - default_adjust->out_color_space); -} /*****************************************/ @@ -964,8 +769,6 @@ void dce110_opp_set_csc_default( static const struct opp_funcs funcs = { .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, - .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, - .opp_set_csc_default = dce110_opp_set_csc_default, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, .opp_set_regamma_mode = dce110_opp_set_regamma_mode, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index e5045d21a05c..ca09f52f49e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -57,13 +57,6 @@ enum dce110_opp_reg_type { SRI(REGAMMA_LUT_INDEX, DCP, id), \ SRI(REGAMMA_LUT_DATA, DCP, id), \ SRI(REGAMMA_CONTROL, DCP, id), \ - SRI(OUTPUT_CSC_C11_C12, DCP, id), \ - SRI(OUTPUT_CSC_C13_C14, DCP, id), \ - SRI(OUTPUT_CSC_C21_C22, DCP, id), \ - SRI(OUTPUT_CSC_C23_C24, DCP, id), \ - SRI(OUTPUT_CSC_C31_C32, DCP, id), \ - SRI(OUTPUT_CSC_C33_C34, DCP, id), \ - SRI(OUTPUT_CSC_CONTROL, DCP, id), \ SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ SRI(FMT_CONTROL, FMT, id), \ @@ -129,9 +122,6 @@ enum dce110_opp_reg_type { OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ OPP_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ OPP_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ - OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ - OPP_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ - OPP_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ @@ -222,9 +212,6 @@ enum dce110_opp_reg_type { OPP_SF(DCFE0_DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(DCP0_REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ OPP_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ - OPP_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ - OPP_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ - OPP_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ @@ -288,9 +275,6 @@ enum dce110_opp_reg_type { type REGAMMA_LUT_MEM_PWR_STATE; \ type REGAMMA_LUT_WRITE_EN_MASK; \ type GRPH_REGAMMA_MODE; \ - type OUTPUT_CSC_C11; \ - type OUTPUT_CSC_C12; \ - type OUTPUT_CSC_GRPH_MODE; \ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_TRUNCATE_EN; \ @@ -362,13 +346,6 @@ struct dce_opp_registers { uint32_t DCFE_MEM_PWR_STATUS; uint32_t REGAMMA_LUT_DATA; uint32_t REGAMMA_CONTROL; - uint32_t OUTPUT_CSC_C11_C12; - uint32_t OUTPUT_CSC_C13_C14; - uint32_t OUTPUT_CSC_C21_C22; - uint32_t OUTPUT_CSC_C23_C24; - uint32_t OUTPUT_CSC_C31_C32; - uint32_t OUTPUT_CSC_C33_C34; - uint32_t OUTPUT_CSC_CONTROL; uint32_t FMT_DYNAMIC_EXP_CNTL; uint32_t FMT_BIT_DEPTH_CONTROL; uint32_t FMT_CONTROL; @@ -417,14 +394,6 @@ bool dce110_opp_program_regamma_pwl( void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, enum opp_regamma mode); -void dce110_opp_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); - -void dce110_opp_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); - /* FORMATTER RELATED */ void dce110_opp_program_bit_depth_reduction( struct output_pixel_processor *opp, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index c861fd7b5767..fb64dca427c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -80,6 +80,37 @@ enum dcp_spatial_dither_depth { DCP_SPATIAL_DITHER_DEPTH_24BPP }; +enum csc_color_mode { + /* 00 - BITS2:0 Bypass */ + CSC_COLOR_MODE_GRAPHICS_BYPASS, + /* 01 - hard coded coefficient TV RGB */ + CSC_COLOR_MODE_GRAPHICS_PREDEFINED, + /* 04 - programmable OUTPUT CSC coefficient */ + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, +}; + +enum grph_color_adjust_option { + GRPH_COLOR_MATRIX_HW_DEFAULT = 1, + GRPH_COLOR_MATRIX_SW +}; + +static const struct out_csc_color_matrix global_color_matrix[] = { +{ COLOR_SPACE_SRGB, + { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, +{ COLOR_SPACE_SRGB_LIMITED, + { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, +{ COLOR_SPACE_YCBCR601, + { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, + 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, + 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, +/* TODO: correct values below */ +{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, + 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, +{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, + 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } +}; + static bool setup_scaling_configuration( struct dce_transform *xfm_dce, const struct scaler_data *data) @@ -970,6 +1001,183 @@ static void dce_transform_reset(struct transform *xfm) xfm_dce->filter_v = NULL; } +static void program_color_matrix( + struct dce_transform *xfm_dce, + const struct out_csc_color_matrix *tbl_entry, + enum grph_color_adjust_option options) +{ + { + REG_SET_2(OUTPUT_CSC_C11_C12, 0, + OUTPUT_CSC_C11, tbl_entry->regval[0], + OUTPUT_CSC_C12, tbl_entry->regval[1]); + } + { + REG_SET_2(OUTPUT_CSC_C13_C14, 0, + OUTPUT_CSC_C11, tbl_entry->regval[2], + OUTPUT_CSC_C12, tbl_entry->regval[3]); + } + { + REG_SET_2(OUTPUT_CSC_C21_C22, 0, + OUTPUT_CSC_C11, tbl_entry->regval[4], + OUTPUT_CSC_C12, tbl_entry->regval[5]); + } + { + REG_SET_2(OUTPUT_CSC_C23_C24, 0, + OUTPUT_CSC_C11, tbl_entry->regval[6], + OUTPUT_CSC_C12, tbl_entry->regval[7]); + } + { + REG_SET_2(OUTPUT_CSC_C31_C32, 0, + OUTPUT_CSC_C11, tbl_entry->regval[8], + OUTPUT_CSC_C12, tbl_entry->regval[9]); + } + { + REG_SET_2(OUTPUT_CSC_C33_C34, 0, + OUTPUT_CSC_C11, tbl_entry->regval[10], + OUTPUT_CSC_C12, tbl_entry->regval[11]); + } +} + +static bool configure_graphics_mode( + struct dce_transform *xfm_dce, + enum csc_color_mode config, + enum graphics_csc_adjust_type csc_adjust_type, + enum dc_color_space color_space) +{ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + + if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { + if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 4); + } else { + + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 1); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 2); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 3); + break; + default: + return false; + } + } + } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { + switch (color_space) { + case COLOR_SPACE_SRGB: + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + break; + break; + case COLOR_SPACE_SRGB_LIMITED: + /* TV RGB */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 1); + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + /* YCbCr601 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 2); + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + /* YCbCr709 */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 3); + break; + default: + return false; + } + + } else + /* by pass */ + REG_SET(OUTPUT_CSC_CONTROL, 0, + OUTPUT_CSC_GRPH_MODE, 0); + + return true; +} + +void dce110_opp_set_csc_adjustment( + struct transform *xfm, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + + program_color_matrix( + xfm_dce, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + + /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ + configure_graphics_mode(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + tbl_entry->color_space); +} + +void dce110_opp_set_csc_default( + struct transform *xfm, + const struct default_adjustment *default_adjust) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + enum csc_color_mode config = + CSC_COLOR_MODE_GRAPHICS_PREDEFINED; + + if (default_adjust->force_hw_default == false) { + const struct out_csc_color_matrix *elm; + /* currently parameter not in use */ + enum grph_color_adjust_option option = + GRPH_COLOR_MATRIX_HW_DEFAULT; + uint32_t i; + /* + * HW default false we program locally defined matrix + * HW default true we use predefined hw matrix and we + * do not need to program matrix + * OEM wants the HW default via runtime parameter. + */ + option = GRPH_COLOR_MATRIX_SW; + + for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { + elm = &global_color_matrix[i]; + if (elm->color_space != default_adjust->out_color_space) + continue; + /* program the matrix with default values from this + * file */ + program_color_matrix(xfm_dce, elm, option); + config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + break; + } + } + + /* configure the what we programmed : + * 1. Default values from this file + * 2. Use hardware default from ROM_A and we do not need to program + * matrix */ + + configure_graphics_mode(xfm_dce, config, + default_adjust->csc_adjust_type, + default_adjust->out_color_space); +} + + static const struct transform_funcs dce_transform_funcs = { .transform_reset = dce_transform_reset, @@ -977,6 +1185,8 @@ static const struct transform_funcs dce_transform_funcs = { dce_transform_set_scaler, .transform_set_gamut_remap = dce_transform_set_gamut_remap, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, .transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth, .transform_get_optimal_number_of_taps = diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index ca6c621151b2..8632d8f4dac0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -44,6 +44,13 @@ SRI(GAMUT_REMAP_C23_C24, DCP, id), \ SRI(GAMUT_REMAP_C31_C32, DCP, id), \ SRI(GAMUT_REMAP_C33_C34, DCP, id), \ + SRI(OUTPUT_CSC_C11_C12, DCP, id), \ + SRI(OUTPUT_CSC_C13_C14, DCP, id), \ + SRI(OUTPUT_CSC_C21_C22, DCP, id), \ + SRI(OUTPUT_CSC_C23_C24, DCP, id), \ + SRI(OUTPUT_CSC_C31_C32, DCP, id), \ + SRI(OUTPUT_CSC_C33_C34, DCP, id), \ + SRI(OUTPUT_CSC_CONTROL, DCP, id), \ SRI(DENORM_CONTROL, DCP, id), \ SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \ SRI(OUT_ROUND_CONTROL, DCP, id), \ @@ -114,6 +121,9 @@ XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + XFM_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -183,6 +193,9 @@ XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ XFM_SF(DCP0_GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + XFM_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -249,6 +262,9 @@ type GAMUT_REMAP_C33; \ type GAMUT_REMAP_C34; \ type GRPH_GAMUT_REMAP_MODE; \ + type OUTPUT_CSC_C11; \ + type OUTPUT_CSC_C12; \ + type OUTPUT_CSC_GRPH_MODE; \ type SCL_MODE; \ type SCL_BYPASS_MODE; \ type SCL_PSCL_EN; \ @@ -302,6 +318,13 @@ struct dce_transform_registers { uint32_t GAMUT_REMAP_C23_C24; uint32_t GAMUT_REMAP_C31_C32; uint32_t GAMUT_REMAP_C33_C34; + uint32_t OUTPUT_CSC_C11_C12; + uint32_t OUTPUT_CSC_C13_C14; + uint32_t OUTPUT_CSC_C21_C22; + uint32_t OUTPUT_CSC_C23_C24; + uint32_t OUTPUT_CSC_C31_C32; + uint32_t OUTPUT_CSC_C33_C34; + uint32_t OUTPUT_CSC_CONTROL; uint32_t DENORM_CONTROL; uint32_t DCP_SPATIAL_DITHER_CNTL; uint32_t OUT_ROUND_CONTROL; @@ -381,5 +404,12 @@ bool dce_transform_get_optimal_number_of_taps( struct scaler_data *scl_data, const struct scaling_taps *in_taps); +void dce110_opp_set_csc_adjustment( + struct transform *xfm, + const struct out_csc_color_matrix *tbl_entry); + +void dce110_opp_set_csc_default( + struct transform *xfm, + const struct default_adjustment *default_adjust); #endif /* _DCE_DCE_TRANSFORM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6afe572cfb06..ad831e586021 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1868,8 +1868,8 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) /* Lb color depth */ default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth; - pipe_ctx->opp->funcs->opp_set_csc_default( - pipe_ctx->opp, &default_adjust); + pipe_ctx->xfm->funcs->opp_set_csc_default( + pipe_ctx->xfm, &default_adjust); } @@ -1991,8 +1991,8 @@ static void set_plane_config( tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - pipe_ctx->opp->funcs->opp_set_csc_adjustment - (pipe_ctx->opp, &tbl_entry); + pipe_ctx->xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->xfm, &tbl_entry); } if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { @@ -2446,8 +2446,8 @@ static void dce110_program_front_end_for_pipe( tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - pipe_ctx->opp->funcs->opp_set_csc_adjustment - (pipe_ctx->opp, &tbl_entry); + pipe_ctx->xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->xfm, &tbl_entry); } if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { @@ -2587,8 +2587,31 @@ static void dce110_wait_for_mpcc_disconnect( /* do nothing*/ } +static void program_csc_matrix(struct pipe_ctx *pipe_ctx, + enum dc_color_space colorspace, + uint16_t *matrix) +{ + int i; + struct out_csc_color_matrix tbl_entry; + + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment + == true) { + enum dc_color_space color_space = + pipe_ctx->stream->output_color_space; + + //uint16_t matrix[12]; + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; + + tbl_entry.color_space = color_space; + //tbl_entry.regval = matrix; + pipe_ctx->xfm->funcs->opp_set_csc_adjustment(pipe_ctx->xfm, &tbl_entry); + } +} + static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, + .program_csc_matrix = program_csc_matrix, .init_hw = init_hw, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dce110_apply_ctx_for_surface, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c index 019effe4c99c..feb397b5c1a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c @@ -24,7 +24,7 @@ */ #include "dm_services.h" -#include "dce/dce_opp.h" +#include "dce110_transform_v.h" #include "basics/conversion.h" /* include DCE11 register header files */ @@ -100,12 +100,17 @@ enum csc_color_mode { CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, }; +enum grph_color_adjust_option { + GRPH_COLOR_MATRIX_HW_DEFAULT = 1, + GRPH_COLOR_MATRIX_SW +}; + static void program_color_matrix_v( - struct dce110_opp *opp110, + struct dce_transform *xfm_dce, const struct out_csc_color_matrix *tbl_entry, enum grph_color_adjust_option options) { - struct dc_context *ctx = opp110->base.ctx; + struct dc_context *ctx = xfm_dce->base.ctx; uint32_t cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL); bool use_set_a = (get_reg_field_value(cntl_value, COL_MAN_OUTPUT_CSC_CONTROL, @@ -351,12 +356,12 @@ static void program_color_matrix_v( } static bool configure_graphics_mode_v( - struct dce110_opp *opp110, + struct dce_transform *xfm_dce, enum csc_color_mode config, enum graphics_csc_adjust_type csc_adjust_type, enum dc_color_space color_space) { - struct dc_context *ctx = opp110->base.ctx; + struct dc_context *ctx = xfm_dce->base.ctx; uint32_t addr = mmCOL_MAN_OUTPUT_CSC_CONTROL; uint32_t value = dm_read_reg(ctx, addr); @@ -454,10 +459,10 @@ static bool configure_graphics_mode_v( } /*TODO: color depth is not correct when this is called*/ -static void set_Denormalization(struct output_pixel_processor *opp, +static void set_Denormalization(struct transform *xfm, enum dc_color_depth color_depth) { - uint32_t value = dm_read_reg(opp->ctx, mmDENORM_CLAMP_CONTROL); + uint32_t value = dm_read_reg(xfm->ctx, mmDENORM_CLAMP_CONTROL); switch (color_depth) { case COLOR_DEPTH_888: @@ -495,7 +500,7 @@ static void set_Denormalization(struct output_pixel_processor *opp, DENORM_CLAMP_CONTROL, DENORM_10BIT_OUT); - dm_write_reg(opp->ctx, mmDENORM_CLAMP_CONTROL, value); + dm_write_reg(xfm->ctx, mmDENORM_CLAMP_CONTROL, value); } struct input_csc_matrix { @@ -524,10 +529,10 @@ static const struct input_csc_matrix input_csc_matrix[] = { }; static void program_input_csc( - struct output_pixel_processor *opp, enum dc_color_space color_space) + struct transform *xfm, enum dc_color_space color_space) { int arr_size = sizeof(input_csc_matrix)/sizeof(struct input_csc_matrix); - struct dc_context *ctx = opp->ctx; + struct dc_context *ctx = xfm->ctx; const uint32_t *regval = NULL; bool use_set_a; uint32_t value; @@ -664,10 +669,10 @@ static void program_input_csc( } void dce110_opp_v_set_csc_default( - struct output_pixel_processor *opp, + struct transform *xfm, const struct default_adjustment *default_adjust) { - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_PREDEFINED; @@ -692,13 +697,13 @@ void dce110_opp_v_set_csc_default( /* program the matrix with default values from this * file */ - program_color_matrix_v(opp110, elm, option); + program_color_matrix_v(xfm_dce, elm, option); config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; break; } } - program_input_csc(opp, default_adjust->in_color_space); + program_input_csc(xfm, default_adjust->in_color_space); /* configure the what we programmed : * 1. Default values from this file @@ -706,26 +711,26 @@ void dce110_opp_v_set_csc_default( * matrix */ - configure_graphics_mode_v(opp110, config, + configure_graphics_mode_v(xfm_dce, config, default_adjust->csc_adjust_type, default_adjust->out_color_space); - set_Denormalization(opp, default_adjust->color_depth); + set_Denormalization(xfm, default_adjust->color_depth); } void dce110_opp_v_set_csc_adjustment( - struct output_pixel_processor *opp, + struct transform *xfm, const struct out_csc_color_matrix *tbl_entry) { - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; program_color_matrix_v( - opp110, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); + xfm_dce, tbl_entry, GRAPHICS_CSC_ADJUST_TYPE_SW); /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ - configure_graphics_mode_v(opp110, config, GRAPHICS_CSC_ADJUST_TYPE_SW, + configure_graphics_mode_v(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW, tbl_entry->color_space); /*TODO: Check if denormalization is needed*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 6f8b414cabbc..24d9032faade 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -39,8 +39,6 @@ static const struct opp_funcs funcs = { .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, - .opp_set_csc_default = dce110_opp_v_set_csc_default, - .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, .opp_destroy = dce110_opp_destroy, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index cb26c515d30f..7deaa4f5c659 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -33,13 +33,7 @@ bool dce110_opp_v_construct(struct dce110_opp *opp110, struct dc_context *ctx); /* underlay callbacks */ -void dce110_opp_v_set_csc_default( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); -void dce110_opp_v_set_csc_adjustment( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); bool dce110_opp_program_regamma_pwl_v( struct output_pixel_processor *opp, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index 8548248d4b19..f655145b3c47 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -681,6 +681,8 @@ static const struct transform_funcs dce110_xfmv_funcs = { .transform_set_scaler = dce110_xfmv_set_scaler, .transform_set_gamut_remap = dce110_xfmv_set_gamut_remap, + .opp_set_csc_default = dce110_opp_v_set_csc_default, + .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, .transform_set_pixel_storage_depth = dce110_xfmv_set_pixel_storage_depth, .transform_get_optimal_number_of_taps = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h index 267af34db3e5..b7f8fdb392a5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h @@ -34,4 +34,11 @@ bool dce110_transform_v_construct( struct dce_transform *xfm110, struct dc_context *ctx); +void dce110_opp_v_set_csc_default( + struct transform *xfm, + const struct default_adjustment *default_adjust); + +void dce110_opp_v_set_csc_adjustment( + struct transform *xfm, + const struct out_csc_color_matrix *tbl_entry); #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index 01d6957c07fb..a4f8556d6797 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -217,13 +217,8 @@ enum fmt_stereo_action { FMT_STEREO_ACTION_UPDATE_POLARITY }; -enum grph_color_adjust_option { - GRPH_COLOR_MATRIX_HW_DEFAULT = 1, - GRPH_COLOR_MATRIX_SW -}; - struct opp_grph_csc_adjustment { - enum grph_color_adjust_option color_adjust_option; + //enum grph_color_adjust_option color_adjust_option; enum dc_color_space c_space; enum dc_color_depth color_depth; /* clean up to uint32_t */ enum graphics_csc_adjust_type csc_adjust_type; -- GitLab From 49baf95740b4f233ea286ebbe7c1066c03f5dd3b Mon Sep 17 00:00:00 2001 From: Vikrant Mhaske Date: Thu, 27 Jul 2017 17:30:52 +0800 Subject: [PATCH 0709/2898] drm/amd/display: Fix DCN compile errors Fix for DCN compiler errors caused due to various submits Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2299bdaca376..e1298d7029e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1475,6 +1475,8 @@ static void dcn10_pipe_control_lock( struct pipe_ctx *pipe, bool lock) { + struct mem_input *mi = NULL; + mi = dc->res_pool->mis[pipe->pipe_idx]; /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ -- GitLab From 792671d7e1e28995c6a63104fac1208e19a0ab08 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 26 Jul 2017 15:51:31 -0400 Subject: [PATCH 0710/2898] drm/amd/display: Add per surface validation hook. For now just validate pixel format in the hook. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 +++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/dce100/dce100_resource.c | 12 +++++++++++- .../gpu/drm/amd/display/dc/dce100/dce100_resource.h | 2 ++ .../gpu/drm/amd/display/dc/dce112/dce112_resource.c | 3 +++ .../gpu/drm/amd/display/dc/dce120/dce120_resource.c | 5 ++++- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 4 +++- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 ++ 8 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d381e380e974..1f4237fc3e53 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2535,3 +2535,14 @@ bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream) return res == DC_OK; } + +bool dc_validate_surface(const struct dc *dc, const struct dc_surface *surface) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + + /* TODO For now validates pixel format only */ + if (core_dc->res_pool->funcs->validate_surface) + return core_dc->res_pool->funcs->validate_surface(surface) == DC_OK; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 58bfb867b71c..e9c9b91d1286 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -589,6 +589,7 @@ struct dc_validation_set { bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream); +bool dc_validate_surface(const struct dc *dc, const struct dc_surface *surface); /* * This function takes a set of resources and checks that they are cofunctional. * diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9ac246f05110..59f4caf057f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -804,12 +804,22 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } +enum dc_status dce100_validate_surface(const struct dc_surface *surface) +{ + + if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return DC_OK; + + return DC_FAIL_SURFACE_VALIDATE; +} + static const struct resource_funcs dce100_res_pool_funcs = { .destroy = dce100_destroy_resource_pool, .link_enc_create = dce100_link_encoder_create, .validate_with_context = dce100_validate_with_context, .validate_guaranteed = dce100_validate_guaranteed, - .validate_bandwidth = dce100_validate_bandwidth + .validate_bandwidth = dce100_validate_bandwidth, + .validate_surface = dce100_validate_surface, }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index bfd7518c94c9..13fc637eb731 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -16,4 +16,6 @@ struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, struct core_dc *dc); +enum dc_status dce100_validate_surface(const struct dc_surface *surface); + #endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 9589208ea0c8..495f38750ae4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -55,6 +55,8 @@ #include "dce/dce_11_2_d.h" #include "dce/dce_11_2_sh_mask.h" +#include "dce100/dce100_resource.h" + #ifndef mmDP_DPHY_INTERNAL_CTRL #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 @@ -992,6 +994,7 @@ static const struct resource_funcs dce112_res_pool_funcs = { .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, + .validate_surface = dce100_validate_surface }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index f829b6e58bcb..b31307b9d3e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -60,6 +60,8 @@ #include "vega10/NBIO/nbio_6_1_offset.h" #include "reg_helper.h" +#include "dce100/dce100_resource.h" + #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 @@ -698,7 +700,8 @@ static const struct resource_funcs dce120_res_pool_funcs = { .link_enc_create = dce120_link_encoder_create, .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, - .validate_bandwidth = dce112_validate_bandwidth + .validate_bandwidth = dce112_validate_bandwidth, + .validate_surface = dce100_validate_surface }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 92f01ed97621..6eeb5e9f656f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -49,6 +49,7 @@ #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" #include "dce80/dce80_hw_sequencer.h" +#include "dce100/dce100_resource.h" #include "reg_helper.h" @@ -823,7 +824,8 @@ static const struct resource_funcs dce80_res_pool_funcs = { .link_enc_create = dce80_link_encoder_create, .validate_with_context = dce80_validate_with_context, .validate_guaranteed = dce80_validate_guaranteed, - .validate_bandwidth = dce80_validate_bandwidth + .validate_bandwidth = dce80_validate_bandwidth, + .validate_surface = dce100_validate_surface }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b312bb3b3350..ab389abf4e79 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -105,6 +105,8 @@ struct resource_funcs { struct validate_context *context, const struct resource_pool *pool, struct dc_stream *stream); + + enum dc_status (*validate_surface)(const struct dc_surface *surface); }; struct audio_support{ -- GitLab From cdc95cbb4cc29679e6116548d6e39d02a2b91649 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 26 Jul 2017 15:51:31 -0400 Subject: [PATCH 0711/2898] drm/amd/display: add preferred mode from Video Format Preference Data Block Signed-off-by: Charlene Liu Reviewed-by: Vitaly Prosyak Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 875b98dae6e1..be6e3ca9fb0d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -856,8 +856,6 @@ bool dcn_validate_bandwidth( - pipe->stream->timing.v_front_porch; v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; - if (pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) - v->pixel_clock[input_idx] /= 2; if (!pipe->surface){ -- GitLab From a32e24b486e80417e62d34f60d625783affff431 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 27 Jul 2017 19:53:55 -0400 Subject: [PATCH 0712/2898] drm/amd/display: Initial prototype of FBC implementation - Protected by ENABLE_FBC compile flag - DC part will follow Signed-off-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 +++++++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 12 ++++++++ 2 files changed, 41 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 02ca9d6225eb..dfb04c5776ad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -297,6 +297,30 @@ static void hotplug_notify_work_func(struct work_struct *work) drm_kms_helper_hotplug_event(dev); } +#ifdef ENABLE_FBC +#include "dal_asic_id.h" +/* Allocate memory for FBC compressed data */ +/* TODO: Dynamic allocation */ +#define AMDGPU_FBC_SIZE (3840 * 2160 * 4) + +void amdgpu_dm_initialize_fbc(struct amdgpu_device *adev) +{ + int r; + struct dm_comressor_info *compressor = &adev->dm.compressor; + + if (!compressor->bo_ptr) { + r = amdgpu_bo_create_kernel(adev, AMDGPU_FBC_SIZE, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, &compressor->bo_ptr, + &compressor->gpu_addr, &compressor->cpu_addr); + + if (r) + DRM_ERROR("DM: Failed to initialize fbc\n"); + } + +} +#endif + + /* Init display KMS * * Returns 0 on success @@ -347,6 +371,11 @@ int amdgpu_dm_init(struct amdgpu_device *adev) init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; +#ifdef ENABLE_FBC + if (adev->family == FAMILY_CZ) + amdgpu_dm_initialize_fbc(adev); + init_data.fbc_gpu_addr = adev->dm.compressor.gpu_addr; +#endif /* Display Core create. */ adev->dm.dc = dc_create(&init_data); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 16b2e0849a65..ce0223af7d5f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -72,6 +72,15 @@ struct irq_list_head { struct work_struct work; }; +#ifdef ENABLE_FBC +struct dm_comressor_info { + void *cpu_addr; + struct amdgpu_bo *bo_ptr; + uint64_t gpu_addr; +}; +#endif + + struct amdgpu_display_manager { struct dal *dal; struct dc *dc; @@ -133,6 +142,9 @@ struct amdgpu_display_manager { * Caches device atomic state for suspend/resume */ struct drm_atomic_state *cached_state; +#ifdef ENABLE_FBC + struct dm_comressor_info compressor; +#endif }; /* basic init/fini API */ -- GitLab From 690b5e3960810c733f812f8849c3a05415c2f53d Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 27 Jul 2017 20:00:06 -0400 Subject: [PATCH 0713/2898] drm/amd/display: Initial prototype of FBC implementation - Protected by ENABLE_FBC compile flag Signed-off-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +- drivers/gpu/drm/amd/display/dc/dc.h | 3 + drivers/gpu/drm/amd/display/dc/dc_types.h | 3 + .../display/dc/dce110/dce110_hw_sequencer.c | 69 +++++++++++++++++++ .../gpu/drm/amd/display/dc/inc/compressor.h | 1 + 5 files changed, 81 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index df8c5ca6b22a..1c0d21840cba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -475,7 +475,9 @@ static bool construct(struct core_dc *dc, dc_version = resource_parse_asic_id(init_params->asic_id); dc->ctx->dce_version = dc_version; - +#ifdef ENABLE_FBC + dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; +#endif /* Resource should construct all asic specific resources. * This should be the only place where we need to parse the asic id */ @@ -919,7 +921,7 @@ bool dc_enable_stereo( #ifdef ENABLE_FBC if (fbc_compressor != NULL && fbc_compressor->funcs->is_fbc_enabled_in_hw(core_dc->fbc_compressor, - &pipe->tg->inst)) + NULL)) fbc_compressor->funcs->disable_fbc(fbc_compressor); #endif @@ -2066,3 +2068,4 @@ void dc_log_hw_state(struct dc *dc) if (core_dc->hwss.log_hw_state) core_dc->hwss.log_hw_state(core_dc); } + diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e9c9b91d1286..63fd5b3de738 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -231,6 +231,9 @@ struct dc_init_data { enum dce_environment dce_environment; struct dc_config flags; +#ifdef ENABLE_FBC + uint64_t fbc_gpu_addr; +#endif }; struct dc *dc_create(const struct dc_init_data *init_params); diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 99b893fbcb42..ee9e6bc88c32 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -92,6 +92,9 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; +#ifdef ENABLE_FBC + uint64_t fbc_gpu_addr; +#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ad831e586021..b62a7614fd28 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1528,6 +1528,69 @@ static void apply_min_clocks( } } +#ifdef ENABLE_FBC + +/* + * Check if FBC can be enabled + */ +static enum dc_status validate_fbc(struct core_dc *dc, + struct validate_context *context) +{ + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[0]; + + ASSERT(dc->fbc_compressor); + + /* FBC memory should be allocated */ + if (!dc->ctx->fbc_gpu_addr) + return DC_ERROR_UNEXPECTED; + + /* Only supports single display */ + if (context->stream_count != 1) + return DC_ERROR_UNEXPECTED; + + /* Only supports eDP */ + if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) + return DC_ERROR_UNEXPECTED; + + /* PSR should not be enabled */ + if (pipe_ctx->stream->sink->link->psr_enabled) + return DC_ERROR_UNEXPECTED; + + return DC_OK; +} + +/* + * Enable FBC + */ +static enum dc_status enable_fbc(struct core_dc *dc, + struct validate_context *context) +{ + enum dc_status status = validate_fbc(dc, context); + + if (status == DC_OK) { + /* Program GRPH COMPRESSED ADDRESS and PITCH */ + struct compr_addr_and_pitch_params params = {0, 0, 0}; + struct compressor *compr = dc->fbc_compressor; + struct pipe_ctx *pipe_ctx = + &context->res_ctx.pipe_ctx[0]; + + params.source_view_width = + pipe_ctx->stream->timing.h_addressable; + params.source_view_height = + pipe_ctx->stream->timing.v_addressable; + + compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; + + compr->funcs->surface_address_and_pitch(compr, ¶ms); + compr->funcs->set_fbc_invalidation_triggers(compr, 1); + + compr->funcs->enable_fbc(compr, ¶ms); + } + return status; +} +#endif + static enum dc_status apply_ctx_to_hw_fpga( struct core_dc *dc, struct validate_context *context) @@ -1836,6 +1899,11 @@ enum dc_status dce110_apply_ctx_to_hw( switch_dp_clock_sources(dc, &context->res_ctx); +#ifdef ENABLE_FBC + if (dc->fbc_compressor) + enable_fbc(dc, context); + +#endif return DC_OK; } @@ -2244,6 +2312,7 @@ static void init_hw(struct core_dc *dc) if (dc->fbc_compressor) dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); #endif + } void dce110_fill_display_configs( diff --git a/drivers/gpu/drm/amd/display/dc/inc/compressor.h b/drivers/gpu/drm/amd/display/dc/inc/compressor.h index 24cca18f3c8f..bcb18f5e1e60 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/compressor.h +++ b/drivers/gpu/drm/amd/display/dc/inc/compressor.h @@ -42,6 +42,7 @@ union fbc_physical_address { uint32_t low_part; int32_t high_part; } addr; + uint64_t quad_part; }; struct compr_addr_and_pitch_params { -- GitLab From cbd194881e05844cc54573480aac8df3fd97222d Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 26 Jul 2017 15:52:28 -0400 Subject: [PATCH 0714/2898] drm/amd/display: Implement plane atomic_check. Use per surface validation hook. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index dfb04c5776ad..baa788ba6f55 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3141,9 +3141,26 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, return MODE_OK; } +int dm_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct amdgpu_device *adev = plane->dev->dev_private; + struct dc *dc = adev->dm.dc; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); + + if (!dm_plane_state->surface) + return true; + + if (dc_validate_surface(dc, dm_plane_state->surface)) + return 0; + + return -EINVAL; +} + static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { .prepare_fb = dm_plane_helper_prepare_fb, .cleanup_fb = dm_plane_helper_cleanup_fb, + .atomic_check = dm_plane_atomic_check, }; /* -- GitLab From f669089aa12ab9b509ed8ff3755e73794b7941ea Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 27 Jul 2017 16:47:14 -0400 Subject: [PATCH 0715/2898] drm/amd/display: Add stateless surface validation to validate_resources Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1c0d21840cba..83b8b196cc1e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -675,6 +675,21 @@ static bool validate_streams ( return true; } +static bool validate_surfaces( + const struct dc *dc, + const struct dc_validation_set set[], + int set_count) +{ + int i, j; + + for (i = 0; i < set_count; i++) + for (j = 0; j < set[i].surface_count; j++) + if (!dc_validate_surface(dc, set[i].surfaces[j])) + return false; + + return true; +} + struct validate_context *dc_get_validate_context( const struct dc *dc, const struct dc_validation_set set[], @@ -726,6 +741,9 @@ bool dc_validate_resources( if (!validate_streams(dc, set, set_count)) return false; + if (!validate_surfaces(dc, set, set_count)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; @@ -1065,6 +1083,9 @@ bool dc_commit_streams( if (!validate_streams(dc, set, stream_count)) return false; + if (!validate_surfaces(dc, set, stream_count)) + return false; + context = dm_alloc(sizeof(struct validate_context)); if (context == NULL) goto context_alloc_fail; -- GitLab From e75504b1292f3a9a173789a06a674fb3ba04450f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 28 Jul 2017 14:16:13 -0400 Subject: [PATCH 0716/2898] drm/amd/display: fix dcn fe reset memory access error Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e1298d7029e6..fa19c6b92f29 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -853,8 +853,9 @@ static void plane_atomic_disable(struct core_dc *dc, struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = dc->res_pool->mis[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; + int opp_id = mi->opp_id; - if (mi->opp_id == 0xf) + if (opp_id == 0xf) return; mpc->funcs->wait_for_idle(mpc, mi->mpcc_id); @@ -876,8 +877,8 @@ static void plane_atomic_disable(struct core_dc *dc, REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0); - if (dc->res_pool->opps[mi->opp_id]->mpc_tree.num_pipes == 0) - REG_UPDATE(OPP_PIPE_CONTROL[mi->opp_id], + if (dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0) + REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); if (dc->public.debug.sanity_checks) -- GitLab From d70ccd4a65373599fe9aa999dff07c05ea2893e6 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 28 Jul 2017 15:33:38 -0400 Subject: [PATCH 0717/2898] drm/amd/display: Keep blank until set visibility to true after mode switch Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 ++++++++----------- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 4 ++++ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 83b8b196cc1e..ba8093317aa9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1609,12 +1609,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!pipe_ctx->surface || pipe_ctx->top_pipe) continue; - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc, - pipe_ctx, - true); - } + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + true); } if (update_type == UPDATE_TYPE_FULL) break; @@ -1697,12 +1695,11 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (!pipe_ctx->surface || pipe_ctx->top_pipe) continue; - if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) { - core_dc->hwss.pipe_control_lock( - core_dc, - pipe_ctx, - false); - } + core_dc->hwss.pipe_control_lock( + core_dc, + pipe_ctx, + false); + break; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index a8c254f66c98..c46b3e82cdcc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -52,6 +52,10 @@ void dce_pipe_control_lock(struct core_dc *dc, uint32_t dcp_grph, scl, blnd, update_lock_mode, val; struct dce_hwseq *hws = dc->hwseq; + /* Not lock pipe when blank */ + if (lock && pipe->tg->funcs->is_blanked(pipe->tg)) + return; + val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx], BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph, BLND_SCL_V_UPDATE_LOCK, &scl, -- GitLab From e51bf71e8c827e1d71235f6b1fe12a952c3a0514 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 28 Jul 2017 18:21:22 -0400 Subject: [PATCH 0718/2898] drm/amd/display: fix bw_calc for hdmi and 420 outputs Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index be6e3ca9fb0d..c809ad3738e9 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -923,8 +923,10 @@ bool dcn_validate_bandwidth( if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp; v->dcc_rate[input_idx] = 1; /*TODO: Worst case? does this change?*/ - v->output_format[input_idx] = dcn_bw_444; - v->output[input_idx] = dcn_bw_dp; + v->output_format[input_idx] = pipe->stream->timing.pixel_encoding == + PIXEL_ENCODING_YCBCR420 ? dcn_bw_420 : dcn_bw_444; + v->output[input_idx] = pipe->stream->sink->sink_signal == + SIGNAL_TYPE_HDMI_TYPE_A ? dcn_bw_hdmi : dcn_bw_dp; input_idx++; } -- GitLab From b701542d29d61c3514f51496168831c8476a8e2a Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 28 Jul 2017 18:21:22 -0400 Subject: [PATCH 0719/2898] drm/amd/display: fix >340 Mhz with deep color pipe split no display the input to HW formula needs to take care the deep color. Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 13 ++++++++++++- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 -- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index c809ad3738e9..7f7cb8ff124d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -856,7 +856,18 @@ bool dcn_validate_bandwidth( - pipe->stream->timing.v_front_porch; v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; - + if (pipe->stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (pipe->stream->timing.display_color_depth) { + case COLOR_DEPTH_101010: + v->pixel_clock[input_idx] = (v->pixel_clock[input_idx] * 30) / 24; + break; + case COLOR_DEPTH_121212: + v->pixel_clock[input_idx] = (v->pixel_clock[input_idx] * 36) / 24; + break; + default: + break; + } + } if (!pipe->surface){ v->dcc_enable[input_idx] = dcn_bw_yes; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1f4237fc3e53..566a1bed9828 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1657,8 +1657,6 @@ static void set_avi_info_frame( color_space == COLOR_SPACE_YCBCR601_LIMITED) hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601; else { - if (stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) - BREAK_TO_DEBUGGER(); hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA; } if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || -- GitLab From d54d29db47cdbe1f26776f2d03320ca56c5271fa Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 28 Jul 2017 12:07:38 -0400 Subject: [PATCH 0720/2898] drm/amd/display: Move and Rename "is_stream_changed()" -Move "is_stream_changed()" to DC interface -Rename "is_stream_changed()" to "dc_is_stream_changed()" Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 -- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ba8093317aa9..5acf4c697ae8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -641,7 +641,7 @@ static bool is_validation_required( if (set[i].surface_count != context->stream_status[i].surface_count) return true; - if (!is_stream_unchanged(set[i].stream, context->streams[i])) + if (!dc_is_stream_unchanged(set[i].stream, context->streams[i])) return true; for (j = 0; j < set[i].surface_count; j++) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 566a1bed9828..005eac5fae80 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1155,7 +1155,7 @@ static bool are_stream_backends_same( return true; } -bool is_stream_unchanged( +bool dc_is_stream_unchanged( struct dc_stream *old_stream, struct dc_stream *stream) { @@ -1176,7 +1176,7 @@ bool resource_validate_attach_surfaces( for (i = 0; i < set_count; i++) { for (j = 0; old_context && j < old_context->stream_count; j++) - if (is_stream_unchanged( + if (dc_is_stream_unchanged( old_context->streams[j], context->streams[i])) { if (!resource_attach_surfaces_to_context( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 63fd5b3de738..0918569eefa8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -534,6 +534,8 @@ struct dc_stream_update { struct dc_transfer_func *out_transfer_func; }; +bool dc_is_stream_unchanged( + struct dc_stream *old_stream, struct dc_stream *stream); /* * Setup stream attributes if no stream updates are provided diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 571bfae62a3c..ca3f49379bea 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -132,8 +132,6 @@ struct pipe_ctx *find_idle_secondary_pipe( bool resource_is_stream_unchanged( struct validate_context *old_context, struct dc_stream *stream); -bool is_stream_unchanged( - struct dc_stream *old_stream, struct dc_stream *stream); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], -- GitLab From 9b690ef3c70422cdcd0cf912db33f2c92ef4a53f Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 28 Jul 2017 13:11:00 -0400 Subject: [PATCH 0721/2898] drm/amd/display: Avoid full modeset when not required Fix IGT test case (kms_atomic_transition) -DRM sets the mode_changed flag, while we don't need to do a full modeset. -We want to override the mode_changed flag in this case If we don't do this, we will still bypass the modeset in DC. This will fail to update the new stream_status, causing nullptr at a later stage when trying to access stream_status" We now avoid this by discarding the new_stream instead of partially filling it. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 97 ++++++++++++------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index baa788ba6f55..7b597a0a2ab9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1608,8 +1608,16 @@ struct dm_connector_state { #define to_dm_connector_state(x)\ container_of((x), struct dm_connector_state, base) -static bool modeset_required(struct drm_crtc_state *crtc_state) +static bool modeset_required(struct drm_crtc_state *crtc_state, + struct dc_stream *new_stream, + struct dc_stream *old_stream) { + if (dc_is_stream_unchanged(new_stream, old_stream)) { + crtc_state->mode_changed = false; + DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d", + crtc_state->mode_changed); + } + if (!drm_atomic_crtc_needs_modeset(crtc_state)) return false; @@ -2904,7 +2912,8 @@ static int dm_crtc_helper_atomic_check( struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); int ret = -EINVAL; - if (unlikely(!dm_crtc_state->stream && modeset_required(state))) { + if (unlikely(!dm_crtc_state->stream && + modeset_required(state, NULL, dm_crtc_state->stream))) { WARN_ON(1); return ret; } @@ -4087,7 +4096,7 @@ void amdgpu_dm_atomic_commit_tail( * aconnector as needed */ - if (modeset_required(new_state)) { + if (modeset_required(new_state, new_acrtc_state->stream, old_acrtc_state->stream)) { DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); @@ -4536,6 +4545,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; + struct dc_stream *new_stream = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; old_acrtc_state = to_dm_crtc_state(crtc->state); new_acrtc_state = to_dm_crtc_state(crtc_state); @@ -4555,23 +4567,50 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, crtc_state->active_changed, crtc_state->connectors_changed); - if (modeset_required(crtc_state)) { + if (modereset_required(crtc_state)) { - struct dc_stream *new_stream = NULL; - struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_conn_state = NULL; + /* i.e. reset mode */ + if (new_acrtc_state->stream) { + set_count = remove_from_val_sets( + set, + set_count, + new_acrtc_state->stream); + + dc_stream_release(new_acrtc_state->stream); + new_acrtc_state->stream = NULL; + + lock_and_validation_needed = true; + } + + } else { if (aconnector) { - conn_state = drm_atomic_get_connector_state(state, &aconnector->base); + conn_state = drm_atomic_get_connector_state(state, + &aconnector->base); + if (IS_ERR(conn_state)) { ret = PTR_ERR_OR_ZERO(conn_state); goto fail; } dm_conn_state = to_dm_connector_state(conn_state); + + new_stream = create_stream_for_sink(aconnector, + &crtc_state->mode, + dm_conn_state); + + if (!new_stream) { + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + break; + } + + } - new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state); + if (modeset_required(crtc_state, new_stream, + old_acrtc_state->stream)) { + /* * we can have no stream on ACTION_SET if a display @@ -4579,39 +4618,27 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * error, the OS will be updated after detection, and * do the right thing on next atomic commit */ - if (!new_stream) { - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - break; - } - - if (new_acrtc_state->stream) - dc_stream_release(new_acrtc_state->stream); - - new_acrtc_state->stream = new_stream; - - set_count = update_in_val_sets_stream( - set, - set_count, - old_acrtc_state->stream, - new_acrtc_state->stream, - crtc); - lock_and_validation_needed = true; + if (new_acrtc_state->stream) + dc_stream_release(new_acrtc_state->stream); - } else if (modereset_required(crtc_state)) { + new_acrtc_state->stream = new_stream; - /* i.e. reset mode */ - if (new_acrtc_state->stream) { - set_count = remove_from_val_sets( + set_count = update_in_val_sets_stream( set, set_count, - new_acrtc_state->stream); - - dc_stream_release(new_acrtc_state->stream); - new_acrtc_state->stream = NULL; + old_acrtc_state->stream, + new_acrtc_state->stream, + crtc); lock_and_validation_needed = true; + } else { + /* + * The new stream is unused, so we release it + */ + if (new_stream) + dc_stream_release(new_stream); + } } -- GitLab From 7a09f5be98df25a7253e4647e801120b37b90feb Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Fri, 28 Jul 2017 13:08:03 -0400 Subject: [PATCH 0722/2898] drm/amd/display: move regamma from opp to dpp for dce Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 237 ----------------- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 113 +-------- .../drm/amd/display/dc/dce/dce_transform.c | 240 ++++++++++++++++++ .../drm/amd/display/dc/dce/dce_transform.h | 88 +++++++ .../display/dc/dce110/dce110_hw_sequencer.c | 18 +- .../display/dc/dce110/dce110_opp_regamma_v.c | 88 +++---- .../drm/amd/display/dc/dce110/dce110_opp_v.c | 3 - .../drm/amd/display/dc/dce110/dce110_opp_v.h | 11 - .../display/dc/dce110/dce110_transform_v.c | 3 + .../display/dc/dce110/dce110_transform_v.h | 14 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 17 -- 11 files changed, 399 insertions(+), 433 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 7abf252369fb..348e4b7047f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -92,242 +92,8 @@ enum { * ***************************************************************************** */ -static void regamma_config_regions_and_segments( - struct dce110_opp *opp110, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - - { - REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, - REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, - REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); - } - { - REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, - REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); - - } - { - REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, - REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); - } - { - REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, - REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, - REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[2].custom_float_slope); - } - - curve = params->arr_curve_points; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - { - REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - } - - curve += 2; - - { - REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, - REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - } -} - -static void program_pwl( - struct dce110_opp *opp110, - const struct pwl_params *params) -{ - uint32_t value; - int retval; - - { - uint8_t max_tries = 10; - uint8_t counter = 0; - - /* Power on LUT memory */ - if (REG(DCFE_MEM_PWR_CTRL)) - REG_UPDATE(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, 1); - else - REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); - - while (counter < max_tries) { - if (REG(DCFE_MEM_PWR_STATUS)) { - value = REG_READ(DCFE_MEM_PWR_STATUS); - REG_GET(DCFE_MEM_PWR_STATUS, - DCP_REGAMMA_MEM_PWR_STATE, - &retval); - - if (retval == 0) - break; - ++counter; - } else { - value = REG_READ(DCFE_MEM_LIGHT_SLEEP_CNTL); - REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_MEM_PWR_STATE, - &retval); - - if (retval == 0) - break; - ++counter; - } - } - - if (counter == max_tries) { - dm_logger_write(opp110->base.ctx->logger, LOG_WARNING, - "%s: regamma lut was not powered on " - "in a timely manner," - " programming still proceeds\n", - __func__); - } - } - - REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK, - REGAMMA_LUT_WRITE_EN_MASK, 7); - - REG_WRITE(REGAMMA_LUT_INDEX, 0); - - /* Program REGAMMA_LUT_DATA */ - { - uint32_t i = 0; - const struct pwl_result_data *rgb = params->rgb_resulted; - - while (i != params->hw_points_num) { - - REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); - REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); - - ++rgb; - ++i; - } - } - - /* we are done with DCP LUT memory; re-enable low power mode */ - if (REG(DCFE_MEM_PWR_CTRL)) - REG_UPDATE(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, 0); - else - REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); -} - -bool dce110_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - /* Setup regions */ - regamma_config_regions_and_segments(opp110, params); - - /* Program PWL */ - program_pwl(opp110, params); - - return true; -} - -void dce110_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - if (REG(DCFE_MEM_PWR_CTRL)) - REG_UPDATE_2(DCFE_MEM_PWR_CTRL, - DCP_REGAMMA_MEM_PWR_DIS, power_on, - DCP_LUT_MEM_PWR_DIS, power_on); - else - REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL, - REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, - DCP_LUT_LIGHT_SLEEP_DIS, power_on); - -} - -void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode) -{ - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); - - REG_SET(REGAMMA_CONTROL, 0, - GRPH_REGAMMA_MODE, mode); -} /** * set_truncation @@ -768,10 +534,7 @@ void dce110_opp_program_fmt( /*****************************************/ static const struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode, .opp_destroy = dce110_opp_destroy, .opp_program_fmt = dce110_opp_program_fmt, .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index ca09f52f49e5..0874c22b8b02 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -41,22 +41,6 @@ enum dce110_opp_reg_type { }; #define OPP_COMMON_REG_LIST_BASE(id) \ - SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \ - SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \ - SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \ - SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \ - SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \ - SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \ - SRI(REGAMMA_LUT_INDEX, DCP, id), \ - SRI(REGAMMA_LUT_DATA, DCP, id), \ - SRI(REGAMMA_CONTROL, DCP, id), \ SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ SRI(FMT_CONTROL, FMT, id), \ @@ -70,31 +54,24 @@ enum dce110_opp_reg_type { #define OPP_DCE_80_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id), \ SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) #define OPP_DCE_100_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \ - SRI(DCFE_MEM_PWR_STATUS, CRTC, id), \ SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) #define OPP_DCE_110_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ - SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id) #define OPP_DCE_112_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ - SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \ SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \ @@ -102,26 +79,12 @@ enum dce110_opp_reg_type { #define OPP_DCE_120_REG_LIST(id) \ OPP_COMMON_REG_LIST_BASE(id), \ - SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ - SRI(DCFE_MEM_PWR_STATUS, DCFE, id), \ SRI(CONTROL, FMT_MEMORY, id) #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix #define OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\ - OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ - OPP_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ - OPP_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ - OPP_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ @@ -160,27 +123,18 @@ enum dce110_opp_reg_type { #define OPP_COMMON_MASK_SH_LIST_DCE_110(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_100(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\ OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\ OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\ OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\ @@ -191,27 +145,9 @@ enum dce110_opp_reg_type { OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_80(mask_sh)\ - OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\ - OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ - OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) + OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) #define OPP_COMMON_MASK_SH_LIST_DCE_120(mask_sh)\ - OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ - OPP_SF(DCFE0_DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ - OPP_SF(DCP0_REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ - OPP_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ @@ -257,24 +193,6 @@ enum dce110_opp_reg_type { OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh) #define OPP_REG_FIELD_LIST(type) \ - type DCP_REGAMMA_MEM_PWR_DIS; \ - type DCP_LUT_MEM_PWR_DIS; \ - type REGAMMA_LUT_LIGHT_SLEEP_DIS; \ - type DCP_LUT_LIGHT_SLEEP_DIS; \ - type REGAMMA_CNTLA_EXP_REGION_START; \ - type REGAMMA_CNTLA_EXP_REGION_START_SEGMENT; \ - type REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE; \ - type REGAMMA_CNTLA_EXP_REGION_END; \ - type REGAMMA_CNTLA_EXP_REGION_END_BASE; \ - type REGAMMA_CNTLA_EXP_REGION_END_SLOPE; \ - type REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET; \ - type REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS; \ - type REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET; \ - type REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS; \ - type DCP_REGAMMA_MEM_PWR_STATE; \ - type REGAMMA_LUT_MEM_PWR_STATE; \ - type REGAMMA_LUT_WRITE_EN_MASK; \ - type GRPH_REGAMMA_MODE; \ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ type FMT_TRUNCATE_EN; \ @@ -327,25 +245,6 @@ struct dce_opp_mask { }; struct dce_opp_registers { - uint32_t DCFE_MEM_PWR_CTRL; - uint32_t DCFE_MEM_LIGHT_SLEEP_CNTL; - uint32_t REGAMMA_CNTLA_START_CNTL; - uint32_t REGAMMA_CNTLA_SLOPE_CNTL; - uint32_t REGAMMA_CNTLA_END_CNTL1; - uint32_t REGAMMA_CNTLA_END_CNTL2; - uint32_t REGAMMA_CNTLA_REGION_0_1; - uint32_t REGAMMA_CNTLA_REGION_2_3; - uint32_t REGAMMA_CNTLA_REGION_4_5; - uint32_t REGAMMA_CNTLA_REGION_6_7; - uint32_t REGAMMA_CNTLA_REGION_8_9; - uint32_t REGAMMA_CNTLA_REGION_10_11; - uint32_t REGAMMA_CNTLA_REGION_12_13; - uint32_t REGAMMA_CNTLA_REGION_14_15; - uint32_t REGAMMA_LUT_WRITE_EN_MASK; - uint32_t REGAMMA_LUT_INDEX; - uint32_t DCFE_MEM_PWR_STATUS; - uint32_t REGAMMA_LUT_DATA; - uint32_t REGAMMA_CONTROL; uint32_t FMT_DYNAMIC_EXP_CNTL; uint32_t FMT_BIT_DEPTH_CONTROL; uint32_t FMT_CONTROL; @@ -382,17 +281,7 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp); -/* REGAMMA RELATED */ -void dce110_opp_power_on_regamma_lut( - struct output_pixel_processor *opp, - bool power_on); - -bool dce110_opp_program_regamma_pwl( - struct output_pixel_processor *opp, - const struct pwl_params *params); -void dce110_opp_set_regamma_mode(struct output_pixel_processor *opp, - enum opp_regamma mode); /* FORMATTER RELATED */ void dce110_opp_program_bit_depth_reduction( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index fb64dca427c1..0e366021cf16 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -1177,7 +1177,244 @@ void dce110_opp_set_csc_default( default_adjust->out_color_space); } +static void program_pwl( + struct dce_transform *xfm_dce, + const struct pwl_params *params) +{ + uint32_t value; + int retval; + + { + uint8_t max_tries = 10; + uint8_t counter = 0; + + /* Power on LUT memory */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 1); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); + + while (counter < max_tries) { + if (REG(DCFE_MEM_PWR_STATUS)) { + value = REG_READ(DCFE_MEM_PWR_STATUS); + REG_GET(DCFE_MEM_PWR_STATUS, + DCP_REGAMMA_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } else { + value = REG_READ(DCFE_MEM_LIGHT_SLEEP_CNTL); + REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_MEM_PWR_STATE, + &retval); + + if (retval == 0) + break; + ++counter; + } + } + + if (counter == max_tries) { + dm_logger_write(xfm_dce->base.ctx->logger, LOG_WARNING, + "%s: regamma lut was not powered on " + "in a timely manner," + " programming still proceeds\n", + __func__); + } + } + + REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK, + REGAMMA_LUT_WRITE_EN_MASK, 7); + + REG_WRITE(REGAMMA_LUT_INDEX, 0); + + /* Program REGAMMA_LUT_DATA */ + { + uint32_t i = 0; + const struct pwl_result_data *rgb = params->rgb_resulted; + + while (i != params->hw_points_num) { + + REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); + REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); + + ++rgb; + ++i; + } + } + + /* we are done with DCP LUT memory; re-enable low power mode */ + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, 0); + else + REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); +} + +static void regamma_config_regions_and_segments( + struct dce_transform *xfm_dce, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + + { + REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); + } + { + REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); + + } + { + REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, + REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); + } + { + REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, + REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[2].custom_float_slope); + } + + curve = params->arr_curve_points; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + } + + curve += 2; + + { + REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, + REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + } +} + + + +bool dce110_opp_program_regamma_pwl( + struct transform *xfm, + const struct pwl_params *params) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + /* Setup regions */ + regamma_config_regions_and_segments(xfm_dce, params); + + /* Program PWL */ + program_pwl(xfm_dce, params); + + return true; +} + +void dce110_opp_power_on_regamma_lut( + struct transform *xfm, + bool power_on) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + if (REG(DCFE_MEM_PWR_CTRL)) + REG_UPDATE_2(DCFE_MEM_PWR_CTRL, + DCP_REGAMMA_MEM_PWR_DIS, power_on, + DCP_LUT_MEM_PWR_DIS, power_on); + else + REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL, + REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, + DCP_LUT_LIGHT_SLEEP_DIS, power_on); + +} + +void dce110_opp_set_regamma_mode(struct transform *xfm, + enum opp_regamma mode) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + + REG_SET(REGAMMA_CONTROL, 0, + GRPH_REGAMMA_MODE, mode); +} static const struct transform_funcs dce_transform_funcs = { .transform_reset = dce_transform_reset, @@ -1187,6 +1424,9 @@ static const struct transform_funcs dce_transform_funcs = { dce_transform_set_gamut_remap, .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, .transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth, .transform_get_optimal_number_of_taps = diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index 8632d8f4dac0..f9622ff54560 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -51,6 +51,22 @@ SRI(OUTPUT_CSC_C31_C32, DCP, id), \ SRI(OUTPUT_CSC_C33_C34, DCP, id), \ SRI(OUTPUT_CSC_CONTROL, DCP, id), \ + SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \ + SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \ + SRI(REGAMMA_LUT_INDEX, DCP, id), \ + SRI(REGAMMA_LUT_DATA, DCP, id), \ + SRI(REGAMMA_CONTROL, DCP, id), \ SRI(DENORM_CONTROL, DCP, id), \ SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \ SRI(OUT_ROUND_CONTROL, DCP, id), \ @@ -124,6 +140,18 @@ XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ XFM_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + XFM_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ + XFM_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -161,6 +189,9 @@ XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ + XFM_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + XFM_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ + XFM_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) #define XFM_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ @@ -196,6 +227,16 @@ XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ XFM_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -265,6 +306,24 @@ type OUTPUT_CSC_C11; \ type OUTPUT_CSC_C12; \ type OUTPUT_CSC_GRPH_MODE; \ + type DCP_REGAMMA_MEM_PWR_DIS; \ + type DCP_LUT_MEM_PWR_DIS; \ + type REGAMMA_LUT_LIGHT_SLEEP_DIS; \ + type DCP_LUT_LIGHT_SLEEP_DIS; \ + type REGAMMA_CNTLA_EXP_REGION_START; \ + type REGAMMA_CNTLA_EXP_REGION_START_SEGMENT; \ + type REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE; \ + type REGAMMA_CNTLA_EXP_REGION_END; \ + type REGAMMA_CNTLA_EXP_REGION_END_BASE; \ + type REGAMMA_CNTLA_EXP_REGION_END_SLOPE; \ + type REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET; \ + type REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS; \ + type REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET; \ + type REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS; \ + type DCP_REGAMMA_MEM_PWR_STATE; \ + type REGAMMA_LUT_MEM_PWR_STATE; \ + type REGAMMA_LUT_WRITE_EN_MASK; \ + type GRPH_REGAMMA_MODE; \ type SCL_MODE; \ type SCL_BYPASS_MODE; \ type SCL_PSCL_EN; \ @@ -325,6 +384,23 @@ struct dce_transform_registers { uint32_t OUTPUT_CSC_C31_C32; uint32_t OUTPUT_CSC_C33_C34; uint32_t OUTPUT_CSC_CONTROL; + uint32_t DCFE_MEM_LIGHT_SLEEP_CNTL; + uint32_t REGAMMA_CNTLA_START_CNTL; + uint32_t REGAMMA_CNTLA_SLOPE_CNTL; + uint32_t REGAMMA_CNTLA_END_CNTL1; + uint32_t REGAMMA_CNTLA_END_CNTL2; + uint32_t REGAMMA_CNTLA_REGION_0_1; + uint32_t REGAMMA_CNTLA_REGION_2_3; + uint32_t REGAMMA_CNTLA_REGION_4_5; + uint32_t REGAMMA_CNTLA_REGION_6_7; + uint32_t REGAMMA_CNTLA_REGION_8_9; + uint32_t REGAMMA_CNTLA_REGION_10_11; + uint32_t REGAMMA_CNTLA_REGION_12_13; + uint32_t REGAMMA_CNTLA_REGION_14_15; + uint32_t REGAMMA_LUT_WRITE_EN_MASK; + uint32_t REGAMMA_LUT_INDEX; + uint32_t REGAMMA_LUT_DATA; + uint32_t REGAMMA_CONTROL; uint32_t DENORM_CONTROL; uint32_t DCP_SPATIAL_DITHER_CNTL; uint32_t OUT_ROUND_CONTROL; @@ -412,4 +488,16 @@ void dce110_opp_set_csc_default( struct transform *xfm, const struct default_adjustment *default_adjust); +/* REGAMMA RELATED */ +void dce110_opp_power_on_regamma_lut( + struct transform *xfm, + bool power_on); + +bool dce110_opp_program_regamma_pwl( + struct transform *xfm, + const struct pwl_params *params); + +void dce110_opp_set_regamma_mode(struct transform *xfm, + enum opp_regamma mode); + #endif /* _DCE_DCE_TRANSFORM_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b62a7614fd28..1f18fcf52661 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -625,26 +625,26 @@ static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream *stream) { - struct output_pixel_processor *opp = pipe_ctx->opp; + struct transform *xfm = pipe_ctx->xfm; - opp->funcs->opp_power_on_regamma_lut(opp, true); - opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + xfm->funcs->opp_power_on_regamma_lut(xfm, true); + xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->out_transfer_func && stream->out_transfer_func->type == TF_TYPE_PREDEFINED && stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); } else if (dce110_translate_regamma_to_hw_format( - stream->out_transfer_func, &opp->regamma_params)) { - opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params); - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); + stream->out_transfer_func, &xfm->regamma_params)) { + xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); } else { - opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS); + xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); } - opp->funcs->opp_power_on_regamma_lut(opp, false); + xfm->funcs->opp_power_on_regamma_lut(xfm, false); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index 876445f14c85..c86105b8cfaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -29,12 +29,12 @@ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" -#include "dce/dce_opp.h" +#include "dce110_transform_v.h" -static void power_on_lut(struct output_pixel_processor *opp, +static void power_on_lut(struct transform *xfm, bool power_on, bool inputgamma, bool regamma) { - uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); int i; if (power_on) { @@ -65,10 +65,10 @@ static void power_on_lut(struct output_pixel_processor *opp, COL_MAN_GAMMA_CORR_MEM_PWR_DIS); } - dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); + dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); for (i = 0; i < 3; i++) { - value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); if (get_reg_field_value(value, DCFEV_MEM_PWR_CTRL, COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) && @@ -81,11 +81,11 @@ static void power_on_lut(struct output_pixel_processor *opp, } } -static void set_bypass_input_gamma(struct dce110_opp *opp110) +static void set_bypass_input_gamma(struct dce_transform *xfm_dce) { uint32_t value; - value = dm_read_reg(opp110->base.ctx, + value = dm_read_reg(xfm_dce->base.ctx, mmCOL_MAN_INPUT_GAMMA_CONTROL1); set_reg_field_value( @@ -94,11 +94,11 @@ static void set_bypass_input_gamma(struct dce110_opp *opp110) COL_MAN_INPUT_GAMMA_CONTROL1, INPUT_GAMMA_MODE); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmCOL_MAN_INPUT_GAMMA_CONTROL1, value); } -static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) +static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode) { uint32_t value = 0; @@ -108,7 +108,7 @@ static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) GAMMA_CORR_CONTROL, GAMMA_CORR_MODE); - dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CONTROL, 0); + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0); } /* @@ -128,7 +128,7 @@ static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) ***************************************************************************** */ static void regamma_config_regions_and_segments( - struct dce110_opp *opp110, const struct pwl_params *params) + struct dce_transform *xfm_dce, const struct pwl_params *params) { const struct gamma_curve *curve; uint32_t value = 0; @@ -146,7 +146,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_START_CNTL, GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT); - dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, value); } { @@ -157,7 +157,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_SLOPE_CNTL, GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value); } { @@ -168,7 +168,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_END_CNTL1, GAMMA_CORR_CNTLA_EXP_REGION_END); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_END_CNTL1, value); } { @@ -185,7 +185,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_END_CNTL2, GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_END_CNTL2, value); } @@ -218,7 +218,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS); dm_write_reg( - opp110->base.ctx, + xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_0_1, value); } @@ -250,7 +250,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_2_3, GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_2_3, value); } @@ -282,7 +282,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_4_5, GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_4_5, value); } @@ -314,7 +314,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_6_7, GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_6_7, value); } @@ -346,7 +346,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_8_9, GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_8_9, value); } @@ -378,7 +378,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_10_11, GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_10_11, value); } @@ -410,7 +410,7 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_12_13, GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_12_13, value); } @@ -442,13 +442,13 @@ static void regamma_config_regions_and_segments( GAMMA_CORR_CNTLA_REGION_14_15, GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_REGION_14_15, value); } } -static void program_pwl(struct dce110_opp *opp110, +static void program_pwl(struct dce_transform *xfm_dce, const struct pwl_params *params) { uint32_t value = 0; @@ -459,10 +459,10 @@ static void program_pwl(struct dce110_opp *opp110, GAMMA_CORR_LUT_WRITE_EN_MASK, GAMMA_CORR_LUT_WRITE_EN_MASK); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_LUT_WRITE_EN_MASK, value); - dm_write_reg(opp110->base.ctx, + dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_LUT_INDEX, 0); /* Program REGAMMA_LUT_DATA */ @@ -473,15 +473,15 @@ static void program_pwl(struct dce110_opp *opp110, params->rgb_resulted; while (i != params->hw_points_num) { - dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); - dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); - dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); + dm_write_reg(xfm_dce->base.ctx, addr, rgb->red_reg); + dm_write_reg(xfm_dce->base.ctx, addr, rgb->green_reg); + dm_write_reg(xfm_dce->base.ctx, addr, rgb->blue_reg); - dm_write_reg(opp110->base.ctx, addr, + dm_write_reg(xfm_dce->base.ctx, addr, rgb->delta_red_reg); - dm_write_reg(opp110->base.ctx, addr, + dm_write_reg(xfm_dce->base.ctx, addr, rgb->delta_green_reg); - dm_write_reg(opp110->base.ctx, addr, + dm_write_reg(xfm_dce->base.ctx, addr, rgb->delta_blue_reg); ++rgb; @@ -491,36 +491,36 @@ static void program_pwl(struct dce110_opp *opp110, } bool dce110_opp_program_regamma_pwl_v( - struct output_pixel_processor *opp, + struct transform *xfm, const struct pwl_params *params) { - struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); /* Setup regions */ - regamma_config_regions_and_segments(opp110, params); + regamma_config_regions_and_segments(xfm_dce, params); - set_bypass_input_gamma(opp110); + set_bypass_input_gamma(xfm_dce); /* Power on gamma LUT memory */ - power_on_lut(opp, true, false, true); + power_on_lut(xfm, true, false, true); /* Program PWL */ - program_pwl(opp110, params); + program_pwl(xfm_dce, params); /* program regamma config */ - configure_regamma_mode(opp110, 1); + configure_regamma_mode(xfm_dce, 1); /* Power return to auto back */ - power_on_lut(opp, false, false, true); + power_on_lut(xfm, false, false, true); return true; } void dce110_opp_power_on_regamma_lut_v( - struct output_pixel_processor *opp, + struct transform *xfm, bool power_on) { - uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); + uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); set_reg_field_value( value, @@ -546,11 +546,11 @@ void dce110_opp_power_on_regamma_lut_v( DCFEV_MEM_PWR_CTRL, COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); - dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); + dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); } void dce110_opp_set_regamma_mode_v( - struct output_pixel_processor *opp, + struct transform *xfm, enum opp_regamma mode) { // TODO: need to implement the function diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 24d9032faade..69d6a110dbc3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -37,10 +37,7 @@ /*****************************************/ static const struct opp_funcs funcs = { - .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, - .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, - .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, .opp_destroy = dce110_opp_destroy, .opp_program_fmt = dce110_opp_program_fmt, .opp_program_bit_depth_reduction = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index 7deaa4f5c659..269c1a88d5bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -35,16 +35,5 @@ bool dce110_opp_v_construct(struct dce110_opp *opp110, /* underlay callbacks */ -bool dce110_opp_program_regamma_pwl_v( - struct output_pixel_processor *opp, - const struct pwl_params *params); - -void dce110_opp_power_on_regamma_lut_v( - struct output_pixel_processor *opp, - bool power_on); - -void dce110_opp_set_regamma_mode_v( - struct output_pixel_processor *opp, - enum opp_regamma mode); #endif /* __DC_OPP_DCE110_V_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index f655145b3c47..c84823a40f61 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -683,6 +683,9 @@ static const struct transform_funcs dce110_xfmv_funcs = { dce110_xfmv_set_gamut_remap, .opp_set_csc_default = dce110_opp_v_set_csc_default, .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, .transform_set_pixel_storage_depth = dce110_xfmv_set_pixel_storage_depth, .transform_get_optimal_number_of_taps = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h index b7f8fdb392a5..eeed3b9f90f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h @@ -41,4 +41,18 @@ void dce110_opp_v_set_csc_default( void dce110_opp_v_set_csc_adjustment( struct transform *xfm, const struct out_csc_color_matrix *tbl_entry); + + +bool dce110_opp_program_regamma_pwl_v( + struct transform *xfm, + const struct pwl_params *params); + +void dce110_opp_power_on_regamma_lut_v( + struct transform *xfm, + bool power_on); + +void dce110_opp_set_regamma_mode_v( + struct transform *xfm, + enum opp_regamma mode); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index a4f8556d6797..dadd2ad2e5b8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -251,24 +251,7 @@ enum ovl_csc_adjust_item { }; struct opp_funcs { - void (*opp_power_on_regamma_lut)( - struct output_pixel_processor *opp, - bool power_on); - - bool (*opp_program_regamma_pwl)( - struct output_pixel_processor *opp, - const struct pwl_params *params); - - void (*opp_set_regamma_mode)(struct output_pixel_processor *opp, - enum opp_regamma mode); - void (*opp_set_csc_adjustment)( - struct output_pixel_processor *opp, - const struct out_csc_color_matrix *tbl_entry); - - void (*opp_set_csc_default)( - struct output_pixel_processor *opp, - const struct default_adjustment *default_adjust); /* FORMATTER RELATED */ -- GitLab From 43193c7991de7a2112fe2ddcfd930733bc357862 Mon Sep 17 00:00:00 2001 From: "AMD\\ktsao" Date: Sun, 30 Jul 2017 14:18:36 -0400 Subject: [PATCH 0723/2898] drm/amd/display: remove DCN1 guard as DCN1 is already open sourced. Signed-off-by: Kenny Tsao Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 6 -- drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 91 +++++++++---------- .../drm/amd/display/dc/dce/dce_clock_source.h | 2 - drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 20 ++-- .../drm/amd/display/dc/dce/dce_link_encoder.h | 15 ++- .../amd/display/dc/dce/dce_stream_encoder.h | 6 -- drivers/gpu/drm/amd/display/dc/dm_services.h | 2 - .../gpu/drm/amd/display/dc/inc/core_types.h | 2 - .../drm/amd/display/dc/inc/hw/display_clock.h | 2 - drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 2 - .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 - drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 2 - .../amd/display/dc/inc/hw/timing_generator.h | 7 +- .../gpu/drm/amd/display/include/dal_asic_id.h | 4 - .../gpu/drm/amd/display/include/dal_types.h | 3 +- 15 files changed, 58 insertions(+), 110 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0918569eefa8..d03218d6210a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -96,13 +96,9 @@ struct dc_surface; struct validate_context; struct dc_cap_funcs { -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) bool (*get_dcc_compression_cap)(const struct dc *dc, const struct dc_dcc_surface_param *input, struct dc_surface_dcc_cap *output); -#else - int i; -#endif }; struct dc_stream_funcs { @@ -171,7 +167,6 @@ struct dc_debug { bool disable_stutter; bool disable_dcc; bool disable_dfs_bypass; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) bool disable_dpp_power_gate; bool disable_hubp_power_gate; bool disable_pplib_wm_range; @@ -185,7 +180,6 @@ struct dc_debug { int percent_of_ideal_drambw; int dram_clock_change_latency_ns; int always_scale; -#endif bool disable_pplib_clock_request; bool disable_clock_gate; bool disable_dmcu; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index e0abd2d49370..59e909ec88f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -54,21 +54,19 @@ SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ SR(BIOS_SCRATCH_2) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define ABM_DCN10_REG_LIST(id)\ - ABM_COMMON_REG_LIST_DCE_BASE(), \ - SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ - SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ - SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ - SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \ - SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ - SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ - SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ - SRI(BL1_PWM_USER_LEVEL, ABM, id), \ - SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ - SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ - NBIO_SR(BIOS_SCRATCH_2) -#endif +#define ABM_DCN10_REG_LIST(id)\ + ABM_COMMON_REG_LIST_DCE_BASE(), \ + SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ + SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \ + SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ + SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_USER_LEVEL, ABM, id), \ + SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ + SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + NBIO_SR(BIOS_SCRATCH_2) #define ABM_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -120,39 +118,36 @@ ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define ABM_MASK_SH_LIST_DCN10(mask_sh) \ - ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ - ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ - ABM1_HG_VMAX_SEL, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ - ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ - ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ - ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ - ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ - ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \ - BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ - ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \ - BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ - ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \ - BL1_PWM_USER_LEVEL, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ - ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ - ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ - ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ - ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ - ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ - ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) -#endif +#define ABM_MASK_SH_LIST_DCN10(mask_sh) \ + ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_VMAX_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \ + ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_R, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_G, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \ + ABM1_IPCSC_COEFF_SEL_B, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \ + BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \ + BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \ + ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \ + BL1_PWM_USER_LEVEL, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \ + ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \ + ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \ + ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh) #define ABM_REG_FIELD_LIST(type) \ type ABM1_HG_NUM_OF_BINS_SEL; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index e8bc98b3b622..fc923886e3d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -55,7 +55,6 @@ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \ SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\ SRII(PHASE, DP_DTO, 0),\ @@ -74,7 +73,6 @@ #define CS_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) -#endif #define CS_REG_FIELD_LIST(type) \ type PLL_REF_DIV_SRC; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index c421a0250016..b85f53c2f6f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -48,11 +48,9 @@ DMCU_COMMON_REG_LIST_DCE_BASE(), \ SR(DCI_MEM_PWR_STATUS) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define DMCU_DCN10_REG_LIST()\ - DMCU_COMMON_REG_LIST_DCE_BASE(), \ - SR(DMU_MEM_PWR_CNTL) -#endif +#define DMCU_DCN10_REG_LIST()\ + DMCU_COMMON_REG_LIST_DCE_BASE(), \ + SR(DMU_MEM_PWR_CNTL) #define DMCU_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -82,12 +80,10 @@ DMCU_SF(DCI_MEM_PWR_STATUS, \ DMCU_IRAM_MEM_PWR_STATE, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define DMCU_MASK_SH_LIST_DCN10(mask_sh) \ - DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ - DMCU_SF(DMU_MEM_PWR_CNTL, \ - DMCU_IRAM_MEM_PWR_STATE, mask_sh) -#endif +#define DMCU_MASK_SH_LIST_DCN10(mask_sh) \ + DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + DMCU_SF(DMU_MEM_PWR_CNTL, \ + DMCU_IRAM_MEM_PWR_STATE, mask_sh) #define DMCU_REG_FIELD_LIST(type) \ type DMCU_IRAM_MEM_PWR_STATE; \ @@ -211,13 +207,11 @@ struct dmcu *dce_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct dmcu *dcn10_dmcu_create( struct dc_context *ctx, const struct dce_dmcu_registers *regs, const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask); -#endif void dce_dmcu_destroy(struct dmcu **dmcu); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index a47b075f4869..5f05ca65281e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -100,15 +100,12 @@ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SR(DCI_MEM_PWR_STATUS) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - #define LE_DCN10_REG_LIST(id)\ - LE_COMMON_REG_LIST_BASE(id), \ - SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DMU_MEM_PWR_CNTL) -#endif - +#define LE_DCN10_REG_LIST(id)\ + LE_COMMON_REG_LIST_BASE(id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ + SR(DMU_MEM_PWR_CNTL) struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index 0b548cb3af14..ff8ca1246650 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -97,7 +97,6 @@ SE_COMMON_REG_LIST_DCE_BASE(id), \ SRI(AFMT_CNTL, DIG, id) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define SE_DCN_REG_LIST(id)\ SE_COMMON_REG_LIST_BASE(id),\ SRI(AFMT_CNTL, DIG, id),\ @@ -112,7 +111,6 @@ SRI(DP_MSA_TIMING_PARAM3, DP, id), \ SRI(DP_MSA_TIMING_PARAM4, DP, id), \ SRI(HDMI_DB_CONTROL, DIG, id) -#endif #define SE_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -328,7 +326,6 @@ SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\ SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\ SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\ @@ -368,7 +365,6 @@ SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh) -#endif struct dce_stream_encoder_shift { uint8_t AFMT_GENERIC_INDEX; @@ -684,7 +680,6 @@ struct dce110_stream_enc_registers { uint32_t HDMI_ACR_48_0; uint32_t HDMI_ACR_48_1; uint32_t TMDS_CNTL; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) uint32_t DP_DB_CNTL; uint32_t DP_MSA_MISC; uint32_t DP_MSA_COLORIMETRY; @@ -693,7 +688,6 @@ struct dce110_stream_enc_registers { uint32_t DP_MSA_TIMING_PARAM3; uint32_t DP_MSA_TIMING_PARAM4; uint32_t HDMI_DB_CONTROL; -#endif }; struct dce110_stream_encoder { diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index e9bf4c417cc7..a7d661d1ff1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -75,9 +75,7 @@ BREAK_TO_DEBUGGER(); \ } while (0) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include -#endif #define dm_alloc(size) kzalloc(size, GFP_KERNEL) #define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index ab389abf4e79..da52971d3f06 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,9 +32,7 @@ #include "ddc_service_types.h" #include "dc_bios_types.h" #include "mem_input.h" -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" -#endif #define MAX_CLOCK_SOURCES 7 diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 240ab11d1d30..879c3db7cba6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -37,13 +37,11 @@ struct clocks_value { bool dispclk_notify_pplib_done; bool pixelclk_notify_pplib_done; bool phyclk_notigy_pplib_done; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) int dcfclock_in_khz; int dppclk_in_khz; int mclk_in_khz; int phyclk_in_khz; int common_vdd_level; -#endif }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 1298d306db69..0f952e5b3ae8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -122,9 +122,7 @@ struct ipp_funcs { struct input_pixel_processor *ipp, const struct pwl_params *params); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) void (*ipp_destroy)(struct input_pixel_processor **ipp); -#endif }; #endif /* __DAL_IPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index a7c89c36f90f..a02f18ae527d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -28,7 +28,6 @@ #include "dc.h" #include "include/grph_object_id.h" -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dml/display_mode_structs.h" struct cstate_pstate_watermarks_st { @@ -49,7 +48,6 @@ struct dcn_watermark_set { struct dcn_watermarks c; struct dcn_watermarks d; }; -#endif struct dce_watermarks { int a_mark; @@ -76,7 +74,6 @@ struct mem_input { }; struct mem_input_funcs { -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) void (*mem_input_setup)( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_regs, @@ -90,7 +87,6 @@ struct mem_input_funcs { struct mem_input *mem_input, const struct rect *viewport, const struct rect *viewport_c); -#endif void (*mem_input_program_display_marks)( struct mem_input *mem_input, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index dadd2ad2e5b8..75adb8fec551 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -27,9 +27,7 @@ #define __DAL_OPP_H__ #include "hw_shared.h" -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dc_hw_types.h" -#endif #include "transform.h" struct fixed31_32; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 2b72d1d8012f..c6ab38c5b2be 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -91,7 +91,7 @@ enum crtc_state { CRTC_STATE_VBLANK = 0, CRTC_STATE_VACTIVE }; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + struct _dlg_otg_param { int vstartup_start; int vupdate_offset; @@ -99,7 +99,6 @@ struct _dlg_otg_param { int vready_offset; enum signal_type signal; }; -#endif struct crtc_stereo_flags { uint8_t PROGRAM_STEREO : 1; @@ -113,9 +112,7 @@ struct timing_generator { const struct timing_generator_funcs *funcs; struct dc_bios *bp; struct dc_context *ctx; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct _dlg_otg_param dlg_otg_param; -#endif int inst; }; @@ -176,10 +173,8 @@ struct timing_generator_funcs { bool (*arm_vert_intr)(struct timing_generator *tg, uint8_t width); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) void (*program_global_sync)(struct timing_generator *tg); void (*enable_optc_clock)(struct timing_generator *tg, bool enable); -#endif void (*program_stereo)(struct timing_generator *tg, const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags); bool (*is_stereo_left_eye)(struct timing_generator *tg); diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 3d2ed5c83734..af9fa66b32b8 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -109,18 +109,14 @@ #define ASIC_REV_IS_STONEY(rev) \ ((rev >= STONEY_A0) && (rev < CZ_UNKNOWN)) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) /* DCN1_0 */ #define INTERNAL_REV_RAVEN_A0 0x00 /* First spin of Raven */ #define RAVEN_A0 0x01 #define RAVEN_UNKNOWN 0xFF #define ASIC_REV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) -#endif -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define FAMILY_RV 142 /* DCN 1*/ -#endif /* * ASIC chip ID diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index 50a2a3ebf36d..1bfc191574aa 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -39,9 +39,8 @@ enum dce_version { DCE_VERSION_11_0, DCE_VERSION_11_2, DCE_VERSION_12_0, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + DCE_VERSION_MAX, DCN_VERSION_1_0, -#endif DCN_VERSION_MAX }; -- GitLab From c9614aeb12f80fa7a787e608d75b707175997edd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 27 Jul 2017 09:24:04 -0400 Subject: [PATCH 0724/2898] drm/amd/display: Rename dc_surface to dc_plane_state find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_surface/struct dc_plane_state/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_plane_state_update/struct dc_surface_update/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_plane_state_status/struct dc_surface_status/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_plane_state_dcc_cap/struct dc_surface_dcc_cap/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +++++++-------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 18 +++++++-------- .../gpu/drm/amd/display/dc/core/dc_debug.c | 4 ++-- .../gpu/drm/amd/display/dc/core/dc_resource.c | 22 +++++++++---------- .../gpu/drm/amd/display/dc/core/dc_surface.c | 16 +++++++------- drivers/gpu/drm/amd/display/dc/dc.h | 22 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 2 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 6 ++--- .../amd/display/dc/dce100/dce100_resource.h | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 14 ++++++------ .../amd/display/dc/dce112/dce112_resource.c | 2 +- .../amd/display/dc/dce120/dce120_resource.c | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 2 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++++------ .../gpu/drm/amd/display/dc/inc/core_types.h | 6 ++--- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- .../amd/display/include/logger_interface.h | 2 +- 22 files changed, 84 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7b597a0a2ab9..af6bed907d10 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1819,7 +1819,7 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, static bool fill_rects_from_plane_state( const struct drm_plane_state *state, - struct dc_surface *surface) + struct dc_plane_state *surface) { surface->src_rect.x = state->src_x >> 16; surface->src_rect.y = state->src_y >> 16; @@ -1894,7 +1894,7 @@ static int get_fb_info( static int fill_plane_attributes_from_fb( struct amdgpu_device *adev, - struct dc_surface *surface, + struct dc_plane_state *surface, const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) { uint64_t tiling_flags; @@ -2048,7 +2048,7 @@ static int fill_plane_attributes_from_fb( static void fill_gamma_from_crtc_state( const struct drm_crtc_state *crtc_state, - struct dc_surface *dc_surface) + struct dc_plane_state *dc_surface) { int i; struct dc_gamma *gamma; @@ -2072,7 +2072,7 @@ static void fill_gamma_from_crtc_state( static int fill_plane_attributes( struct amdgpu_device *adev, - struct dc_surface *surface, + struct dc_plane_state *surface, struct drm_plane_state *plane_state, struct drm_crtc_state *crtc_state, bool addrReq) @@ -3059,7 +3059,7 @@ static int dm_plane_helper_prepare_fb( if (dm_plane_state_new->surface && dm_plane_state_old->surface != dm_plane_state_new->surface) { - struct dc_surface *surface = dm_plane_state_new->surface; + struct dc_plane_state *surface = dm_plane_state_new->surface; if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { surface->address.grph.addr.low_part = lower_32_bits(afb->address); @@ -3160,7 +3160,7 @@ int dm_plane_atomic_check(struct drm_plane *plane, if (!dm_plane_state->surface) return true; - if (dc_validate_surface(dc, dm_plane_state->surface)) + if (dc_validate_plane(dc, dm_plane_state->surface)) return 0; return -EINVAL; @@ -3926,7 +3926,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *old_plane_state; struct dc_stream *dc_stream_attach; - struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; + struct dc_plane_state *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; @@ -4377,7 +4377,7 @@ static uint32_t add_val_sets_surface( struct dc_validation_set *val_sets, uint32_t set_count, const struct dc_stream *stream, - struct dc_surface *surface) + struct dc_plane_state *surface) { uint32_t i = 0, j = 0; @@ -4699,7 +4699,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, pflip_needed = !state->allow_modeset; if (!pflip_needed) { - struct dc_surface *surface; + struct dc_plane_state *surface; surface = dc_create_surface(dc); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index ce0223af7d5f..dcf1f77390a8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -189,14 +189,14 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; -struct dc_surface; +struct dc_plane_state; /* TODO rename to dc_stream_state */ struct dc_stream; struct dm_plane_state { struct drm_plane_state base; - struct dc_surface *surface; + struct dc_plane_state *surface; }; struct dm_crtc_state { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5acf4c697ae8..500788c35d70 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -645,7 +645,7 @@ static bool is_validation_required( return true; for (j = 0; j < set[i].surface_count; j++) { - struct dc_surface temp_surf; + struct dc_plane_state temp_surf; memset(&temp_surf, 0, sizeof(temp_surf)); temp_surf = *context->stream_status[i].surfaces[j]; @@ -684,7 +684,7 @@ static bool validate_surfaces( for (i = 0; i < set_count; i++) for (j = 0; j < set[i].surface_count; j++) - if (!dc_validate_surface(dc, set[i].surfaces[j])) + if (!dc_validate_plane(dc, set[i].surfaces[j])) return false; return true; @@ -978,7 +978,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c const struct dc_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].surface_count; j++) { - const struct dc_surface *surface = + const struct dc_plane_state *surface = context->stream_status[i].surfaces[j]; core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); @@ -1136,7 +1136,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) bool dc_commit_surfaces_to_stream( struct dc *dc, - struct dc_surface **new_surfaces, + struct dc_plane_state **new_surfaces, uint8_t new_surface_count, struct dc_stream *dc_stream) { @@ -1220,7 +1220,7 @@ void dc_release_validate_context(struct validate_context *context) static bool is_surface_in_context( const struct validate_context *context, - const struct dc_surface *surface) + const struct dc_plane_state *surface) { int j; @@ -1470,7 +1470,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { - struct dc_surface *new_surfaces[MAX_SURFACES] = {0}; + struct dc_plane_state *new_surfaces[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) new_surfaces[i] = srf_updates[i].surface; @@ -1496,7 +1496,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* save update parameters into surface */ for (i = 0; i < surface_count; i++) { - struct dc_surface *surface = srf_updates[i].surface; + struct dc_plane_state *surface = srf_updates[i].surface; if (srf_updates[i].flip_addr) { surface->address = srf_updates[i].flip_addr->address; @@ -1599,7 +1599,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { - struct dc_surface *surface = srf_updates[i].surface; + struct dc_plane_state *surface = srf_updates[i].surface; for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -1649,7 +1649,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { - struct dc_surface *surface = srf_updates[i].surface; + struct dc_plane_state *surface = srf_updates[i].surface; if (update_type == UPDATE_TYPE_MED) core_dc->hwss.apply_ctx_for_surface( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index bf127a88e533..e8d4b8c3ac2b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -38,7 +38,7 @@ void pre_surface_trace( const struct dc *dc, - const struct dc_surface *const *surfaces, + const struct dc_plane_state *const *surfaces, int surface_count) { int i; @@ -46,7 +46,7 @@ void pre_surface_trace( struct dal_logger *logger = core_dc->ctx->logger; for (i = 0; i < surface_count; i++) { - const struct dc_surface *surface = surfaces[i]; + const struct dc_plane_state *surface = surfaces[i]; SURFACE_TRACE("Surface %d:\n", i); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 005eac5fae80..fd1d6be79fee 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -430,7 +430,7 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = pipe_ctx->surface; + const struct dc_plane_state *surface = pipe_ctx->surface; const struct dc_stream *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; @@ -529,7 +529,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - const struct dc_surface *surface = pipe_ctx->surface; + const struct dc_plane_state *surface = pipe_ctx->surface; const struct dc_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; struct rect surf_clip = surface->clip_rect; @@ -607,7 +607,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = pipe_ctx->surface; + const struct dc_plane_state *surface = pipe_ctx->surface; const struct dc_stream *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; const int in_w = stream->src.width; @@ -814,7 +814,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { - const struct dc_surface *surface = pipe_ctx->surface; + const struct dc_plane_state *surface = pipe_ctx->surface; struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct view recout_skip = { 0 }; bool res = false; @@ -1028,7 +1028,7 @@ static int acquire_first_split_pipe( #endif bool resource_attach_surfaces_to_context( - struct dc_surface * const *surfaces, + struct dc_plane_state * const *surfaces, int surface_count, struct dc_stream *stream, struct validate_context *context, @@ -1075,7 +1075,7 @@ bool resource_attach_surfaces_to_context( tail_pipe = NULL; for (i = 0; i < surface_count; i++) { - struct dc_surface *surface = surfaces[i]; + struct dc_plane_state *surface = surfaces[i]; struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( context, pool, stream); @@ -1351,7 +1351,7 @@ bool resource_is_stream_unchanged( static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { - struct dc_surface *surface = to_pipe_ctx->surface; + struct dc_plane_state *surface = to_pipe_ctx->surface; struct dc_stream *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; @@ -2055,7 +2055,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, - struct dc_surface *surface, + struct dc_plane_state *surface, struct dc_stream *stream) { uint16_t i = 0; @@ -2534,13 +2534,13 @@ bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream) return res == DC_OK; } -bool dc_validate_surface(const struct dc *dc, const struct dc_surface *surface) +bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state) { struct core_dc *core_dc = DC_TO_CORE(dc); /* TODO For now validates pixel format only */ - if (core_dc->res_pool->funcs->validate_surface) - return core_dc->res_pool->funcs->validate_surface(surface) == DC_OK; + if (core_dc->res_pool->funcs->validate_plane) + return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index eded6b7da97d..941b3671375d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -34,7 +34,7 @@ /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct dc_surface *surface) +static bool construct(struct dc_context *ctx, struct dc_plane_state *surface) { surface->ctx = ctx; memset(&surface->hdr_static_ctx, @@ -42,7 +42,7 @@ static bool construct(struct dc_context *ctx, struct dc_surface *surface) return true; } -static void destruct(struct dc_surface *surface) +static void destruct(struct dc_plane_state *surface) { if (surface->gamma_correction != NULL) { dc_gamma_release(&surface->gamma_correction); @@ -57,18 +57,18 @@ static void destruct(struct dc_surface *surface) /******************************************************************************* * Public functions ******************************************************************************/ -void enable_surface_flip_reporting(struct dc_surface *surface, +void enable_surface_flip_reporting(struct dc_plane_state *surface, uint32_t controller_id) { surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; /*register_flip_interrupt(surface);*/ } -struct dc_surface *dc_create_surface(const struct dc *dc) +struct dc_plane_state *dc_create_surface(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_surface *surface = dm_alloc(sizeof(*surface)); + struct dc_plane_state *surface = dm_alloc(sizeof(*surface)); if (NULL == surface) goto alloc_fail; @@ -88,7 +88,7 @@ struct dc_surface *dc_create_surface(const struct dc *dc) } const struct dc_surface_status *dc_surface_get_status( - const struct dc_surface *dc_surface) + const struct dc_plane_state *dc_surface) { const struct dc_surface_status *surface_status; struct core_dc *core_dc; @@ -120,13 +120,13 @@ const struct dc_surface_status *dc_surface_get_status( return surface_status; } -void dc_surface_retain(struct dc_surface *surface) +void dc_surface_retain(struct dc_plane_state *surface) { ASSERT(surface->ref_count > 0); ++surface->ref_count; } -void dc_surface_release(struct dc_surface *surface) +void dc_surface_release(struct dc_plane_state *surface) { ASSERT(surface->ref_count > 0); --surface->ref_count; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d03218d6210a..d1943b9644d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -92,7 +92,7 @@ struct dc_static_screen_events { /* Forward declaration*/ struct dc; -struct dc_surface; +struct dc_plane_state; struct validate_context; struct dc_cap_funcs { @@ -310,7 +310,7 @@ struct dc_surface_status { bool is_right_eye; }; -struct dc_surface { +struct dc_plane_state { struct dc_plane_address address; struct scaling_taps scaling_quality; @@ -367,7 +367,7 @@ struct dc_scaling_info { }; struct dc_surface_update { - struct dc_surface *surface; + struct dc_plane_state *surface; /* isr safe update parameters. null means no updates */ struct dc_flip_addrs *flip_addr; @@ -385,12 +385,12 @@ struct dc_surface_update { /* * Create a new surface with default parameters; */ -struct dc_surface *dc_create_surface(const struct dc *dc); +struct dc_plane_state *dc_create_surface(const struct dc *dc); const struct dc_surface_status *dc_surface_get_status( - const struct dc_surface *dc_surface); + const struct dc_plane_state *dc_surface); -void dc_surface_retain(struct dc_surface *dc_surface); -void dc_surface_release(struct dc_surface *dc_surface); +void dc_surface_retain(struct dc_plane_state *dc_surface); +void dc_surface_release(struct dc_plane_state *dc_surface); void dc_gamma_retain(struct dc_gamma *dc_gamma); void dc_gamma_release(struct dc_gamma **dc_gamma); @@ -424,7 +424,7 @@ struct dc_flip_addrs { bool dc_commit_surfaces_to_stream( struct dc *dc, - struct dc_surface **dc_surfaces, + struct dc_plane_state **dc_surfaces, uint8_t surface_count, struct dc_stream *stream); @@ -470,7 +470,7 @@ enum surface_update_type { struct dc_stream_status { int primary_otg_inst; int surface_count; - struct dc_surface *surfaces[MAX_SURFACE_NUM]; + struct dc_plane_state *surfaces[MAX_SURFACE_NUM]; /* * link this stream passes through @@ -582,13 +582,13 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, */ struct dc_validation_set { struct dc_stream *stream; - struct dc_surface *surfaces[MAX_SURFACES]; + struct dc_plane_state *surfaces[MAX_SURFACES]; uint8_t surface_count; }; bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream); -bool dc_validate_surface(const struct dc *dc, const struct dc_surface *surface); +bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state); /* * This function takes a set of resources and checks that they are cofunctional. * diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 4c5e797da5b1..3c0b47373dfb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -528,7 +528,7 @@ enum dc_quantization_range { /* XFM */ -/* used in struct dc_surface */ +/* used in struct dc_plane_state */ struct scaling_taps { uint32_t v_taps; uint32_t h_taps; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index ee9e6bc88c32..4fb9584452a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -34,7 +34,7 @@ #include "grph_object_defs.h" /* forward declarations */ -struct dc_surface; +struct dc_plane_state; struct dc_stream; struct dc_link; struct dc_sink; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index c46b3e82cdcc..af59ab93796a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -197,7 +197,7 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, } /* Only use LUT for 8 bit formats */ -bool dce_use_lut(const struct dc_surface *surface) +bool dce_use_lut(const struct dc_plane_state *surface) { switch (surface->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index ade7507e99c7..d5cb98a92c53 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -552,5 +552,5 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst); -bool dce_use_lut(const struct dc_surface *surface); +bool dce_use_lut(const struct dc_plane_state *surface); #endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 59f4caf057f7..2cf2fefc3d79 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -804,10 +804,10 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -enum dc_status dce100_validate_surface(const struct dc_surface *surface) +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state) { - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return DC_OK; return DC_FAIL_SURFACE_VALIDATE; @@ -819,7 +819,7 @@ static const struct resource_funcs dce100_res_pool_funcs = { .validate_with_context = dce100_validate_with_context, .validate_guaranteed = dce100_validate_guaranteed, .validate_bandwidth = dce100_validate_bandwidth, - .validate_surface = dce100_validate_surface, + .validate_plane = dce100_validate_plane, }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index 13fc637eb731..edc50caf04d1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -16,6 +16,6 @@ struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, struct core_dc *dc); -enum dc_status dce100_validate_surface(const struct dc_surface *surface); +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); #endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1f18fcf52661..84dc8916de96 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -215,7 +215,7 @@ static bool dce110_enable_display_power_gating( } static void build_prescale_params(struct ipp_prescale_params *prescale_params, - const struct dc_surface *surface) + const struct dc_plane_state *surface) { prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; @@ -240,7 +240,7 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, - const struct dc_surface *surface) + const struct dc_plane_state *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -2038,7 +2038,7 @@ static void set_plane_config( struct resource_context *res_ctx) { struct mem_input *mi = pipe_ctx->mi; - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2123,7 +2123,7 @@ static void set_plane_config( static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; if (surface == NULL) return; @@ -2138,7 +2138,7 @@ static void update_plane_addr(const struct core_dc *dc, void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; if (surface == NULL) return; @@ -2490,7 +2490,7 @@ static void dce110_program_front_end_for_pipe( { struct mem_input *mi = pipe_ctx->mi; struct pipe_ctx *old_pipe = NULL; - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2614,7 +2614,7 @@ static void dce110_program_front_end_for_pipe( static void dce110_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_surface *surface, + const struct dc_plane_state *surface, struct validate_context *context) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 495f38750ae4..c68372fa1292 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -994,7 +994,7 @@ static const struct resource_funcs dce112_res_pool_funcs = { .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, - .validate_surface = dce100_validate_surface + .validate_plane = dce100_validate_plane }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index b31307b9d3e3..45f5fd63ce14 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -701,7 +701,7 @@ static const struct resource_funcs dce120_res_pool_funcs = { .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, - .validate_surface = dce100_validate_surface + .validate_plane = dce100_validate_plane }; static void bw_calcs_data_update_from_pplib(struct core_dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 6eeb5e9f656f..bcb66447b558 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -825,7 +825,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_with_context = dce80_validate_with_context, .validate_guaranteed = dce80_validate_guaranteed, .validate_bandwidth = dce80_validate_bandwidth, - .validate_surface = dce100_validate_surface + .validate_plane = dce100_validate_plane }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index fa19c6b92f29..3979cb03cf8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1038,7 +1038,7 @@ static void reset_hw_ctx_wrap( static bool patch_address_for_sbs_tb_stereo( struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; bool sec_split = pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface; if (sec_split && surface->address.type == PLN_ADDR_TYPE_GRPH_STEREO && @@ -1065,7 +1065,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; if (surface == NULL) return; @@ -1080,7 +1080,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct } static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, const struct dc_surface *surface) + struct pipe_ctx *pipe_ctx, const struct dc_plane_state *surface) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -1689,7 +1689,7 @@ static void dcn10_power_on_fe( struct pipe_ctx *pipe_ctx, struct validate_context *context) { - struct dc_surface *dc_surface = pipe_ctx->surface; + struct dc_plane_state *dc_surface = pipe_ctx->surface; struct dce_hwseq *hws = dc->hwseq; power_on_plane(dc->hwseq, @@ -1898,7 +1898,7 @@ static void update_dchubp_dpp( struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->mi; struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; union plane_size size = surface->plane_size; struct default_adjustment ocsc = {0}; struct mpcc_cfg mpcc_cfg = {0}; @@ -2068,7 +2068,7 @@ static void dcn10_pplib_apply_display_requirements( static void dcn10_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_surface *surface, + const struct dc_plane_state *surface, struct validate_context *context) { int i, be_idx; @@ -2468,7 +2468,7 @@ static bool dcn10_dummy_display_power_gating( void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct dc_surface *surface = pipe_ctx->surface; + struct dc_plane_state *surface = pipe_ctx->surface; struct timing_generator *tg = pipe_ctx->tg; if (surface->ctx->dc->debug.sanity_checks) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index da52971d3f06..44a87c9427f7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -36,7 +36,7 @@ #define MAX_CLOCK_SOURCES 7 -void enable_surface_flip_reporting(struct dc_surface *dc_surface, +void enable_surface_flip_reporting(struct dc_plane_state *dc_surface, uint32_t controller_id); #include "grph_object_id.h" @@ -104,7 +104,7 @@ struct resource_funcs { const struct resource_pool *pool, struct dc_stream *stream); - enum dc_status (*validate_surface)(const struct dc_surface *surface); + enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); }; struct audio_support{ @@ -154,7 +154,7 @@ struct resource_pool { }; struct pipe_ctx { - struct dc_surface *surface; + struct dc_plane_state *surface; struct dc_stream *stream; struct mem_input *mi; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index b2f7ba2115c9..c529ddd2e0d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -59,7 +59,7 @@ struct hw_sequencer_funcs { void (*apply_ctx_for_surface)( struct core_dc *dc, - const struct dc_surface *surface, + const struct dc_plane_state *surface, struct validate_context *context); void (*set_plane_config)( @@ -88,7 +88,7 @@ struct hw_sequencer_funcs { bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct dc_surface *surface); + const struct dc_plane_state *surface); bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index ca3f49379bea..bfd7cfc86df0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -119,7 +119,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( struct dc_stream *stream); bool resource_attach_surfaces_to_context( - struct dc_surface *const *surfaces, + struct dc_plane_state *const *surfaces, int surface_count, struct dc_stream *dc_stream, struct validate_context *context, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 0a872472ecba..0e978d921fdf 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -77,7 +77,7 @@ void logger_write(struct dal_logger *logger, void pre_surface_trace( const struct dc *dc, - const struct dc_surface *const *surfaces, + const struct dc_plane_state *const *surfaces, int surface_count); void update_surface_trace( -- GitLab From 0971c40e180696c3512b9a63ca7ca5161cbfce32 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 27 Jul 2017 09:33:33 -0400 Subject: [PATCH 0725/2898] drm/amd/display: Rename dc_stream to dc_stream_state find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_stream/struct dc_stream_state/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_stream_state_update/struct dc_stream_update/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/struct dc_stream_state_status/struct dc_stream_status/g' Plus some manual changes Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 ++++++------ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 38 +++++------ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 18 ++--- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 68 +++++++++---------- .../gpu/drm/amd/display/dc/core/dc_stream.c | 26 +++---- drivers/gpu/drm/amd/display/dc/dc.h | 58 ++++++++-------- drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- .../drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- .../drm/amd/display/dc/dce/dce_link_encoder.h | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 4 +- .../display/dc/dce110/dce110_hw_sequencer.c | 16 ++--- .../amd/display/dc/dce110/dce110_resource.c | 8 +-- .../amd/display/dc/dce112/dce112_resource.c | 8 +-- .../amd/display/dc/dce112/dce112_resource.h | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 4 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 +-- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 10 +-- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 6 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 11 ++- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 4 +- .../drm/amd/display/dc/inc/hw/link_encoder.h | 2 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 13 ++-- .../display/dc/virtual/virtual_link_encoder.c | 2 +- .../amd/display/modules/freesync/freesync.c | 50 +++++++------- .../amd/display/modules/inc/mod_freesync.h | 28 ++++---- 29 files changed, 222 insertions(+), 222 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index af6bed907d10..497104a29d89 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -116,7 +116,8 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) if (acrtc_state->stream == NULL) { - DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); + DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n", + crtc); return 0; } @@ -137,7 +138,8 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, acrtc->base.state); if (acrtc_state->stream == NULL) { - DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc); + DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n", + crtc); return 0; } @@ -1441,7 +1443,7 @@ static int amdgpu_notify_freesync(struct drm_device *dev, void *data, num_streams = dc_get_current_stream_count(adev->dm.dc); for (i = 0; i < num_streams; i++) { - struct dc_stream *stream; + struct dc_stream_state *stream; stream = dc_get_stream_at_index(adev->dm.dc, i); mod_freesync_update_state(adev->dm.freesync_module, @@ -1609,8 +1611,8 @@ struct dm_connector_state { container_of((x), struct dm_connector_state, base) static bool modeset_required(struct drm_crtc_state *crtc_state, - struct dc_stream *new_stream, - struct dc_stream *old_stream) + struct dc_stream_state *new_stream, + struct dc_stream_state *old_stream) { if (dc_is_stream_unchanged(new_stream, old_stream)) { crtc_state->mode_changed = false; @@ -2141,7 +2143,7 @@ struct amdgpu_connector *aconnector_from_drm_crtc_id( static void update_stream_scaling_settings( const struct drm_display_mode *mode, const struct dm_connector_state *dm_state, - struct dc_stream *stream) + struct dc_stream_state *stream) { enum amdgpu_rmx_type rmx_type; @@ -2285,7 +2287,7 @@ static enum dc_color_space get_output_color_space( /*****************************************************************************/ static void fill_stream_properties_from_drm_display_mode( - struct dc_stream *stream, + struct dc_stream_state *stream, const struct drm_display_mode *mode_in, const struct drm_connector *connector) { @@ -2426,14 +2428,14 @@ static void decide_crtc_timing_for_drm_display_mode( } } -static struct dc_stream *create_stream_for_sink( +static struct dc_stream_state *create_stream_for_sink( struct amdgpu_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { struct drm_display_mode *preferred_mode = NULL; const struct drm_connector *drm_connector; - struct dc_stream *stream = NULL; + struct dc_stream_state *stream = NULL; struct drm_display_mode mode = *drm_mode; bool native_mode_found = false; @@ -2842,7 +2844,7 @@ int amdgpu_dm_connector_mode_valid( struct dc_sink *dc_sink; struct amdgpu_device *adev = connector->dev->dev_private; /* TODO: Unhardcode stream count */ - struct dc_stream *stream; + struct dc_stream_state *stream; struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || @@ -3119,7 +3121,7 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, struct dc_sink *dc_sink = to_amdgpu_connector(connector)->dc_sink; /* TODO: Unhardcode stream count */ - struct dc_stream *stream; + struct dc_stream_state *stream; if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -3770,7 +3772,7 @@ static bool is_scaling_state_different( static void remove_stream( struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, - struct dc_stream *stream) + struct dc_stream_state *stream) { /* this is the update mode case */ if (adev->dm.freesync_module) @@ -3925,7 +3927,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, uint32_t i; struct drm_plane *plane; struct drm_plane_state *old_plane_state; - struct dc_stream *dc_stream_attach; + struct dc_stream_state *dc_stream_attach; struct dc_plane_state *dc_surfaces_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); @@ -4061,7 +4063,7 @@ void amdgpu_dm_atomic_commit_tail( struct drm_crtc *crtc, *pcrtc; struct drm_crtc_state *old_crtc_state; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; - struct dc_stream *new_stream = NULL; + struct dc_stream_state *new_stream = NULL; unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; @@ -4220,7 +4222,7 @@ void amdgpu_dm_atomic_commit_tail( new_acrtc_state = to_dm_crtc_state(acrtc->base.state); update_stream_scaling_settings(&con_new_state->base.crtc->mode, - con_new_state, (struct dc_stream *)new_acrtc_state->stream); + con_new_state, (struct dc_stream_state *)new_acrtc_state->stream); status = dc_stream_get_status(new_acrtc_state->stream); WARN_ON(!status); @@ -4376,7 +4378,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector static uint32_t add_val_sets_surface( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dc_plane_state *surface) { uint32_t i = 0, j = 0; @@ -4399,8 +4401,8 @@ static uint32_t add_val_sets_surface( static uint32_t update_in_val_sets_stream( struct dc_validation_set *val_sets, uint32_t set_count, - struct dc_stream *old_stream, - struct dc_stream *new_stream, + struct dc_stream_state *old_stream, + struct dc_stream_state *new_stream, struct drm_crtc *crtc) { uint32_t i = 0; @@ -4423,7 +4425,7 @@ static uint32_t update_in_val_sets_stream( static uint32_t remove_from_val_sets( struct dc_validation_set *val_sets, uint32_t set_count, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { int i; @@ -4545,7 +4547,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; - struct dc_stream *new_stream = NULL; + struct dc_stream_state *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_conn_state = NULL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index dcf1f77390a8..cca65a37b213 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -201,7 +201,7 @@ struct dm_plane_state { struct dm_crtc_state { struct drm_crtc_state base; - struct dc_stream *stream; + struct dc_stream_state *stream; }; #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 0a615583de63..4a124537dc9a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -174,7 +174,7 @@ static void get_payload_table( */ bool dm_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dp_mst_stream_allocation_table *proposed_table, bool enable) { @@ -264,7 +264,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( */ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( struct dc_context *ctx, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { struct amdgpu_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; @@ -290,7 +290,7 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( bool dm_helpers_dp_mst_send_payload_allocation( struct dc_context *ctx, - const struct dc_stream *stream, + const struct dc_stream_state *stream, bool enable) { struct amdgpu_connector *aconnector; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 500788c35d70..8b6b7631d776 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -149,12 +149,12 @@ static bool create_links( } static bool stream_adjust_vmin_vmax(struct dc *dc, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, int vmin, int vmax) { /* TODO: Support multiple streams */ struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_stream *stream = streams[0]; + struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -175,12 +175,12 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, } static bool stream_get_crtc_position(struct dc *dc, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_stream *stream = streams[0]; + struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; struct crtc_position position; @@ -200,7 +200,7 @@ static bool stream_get_crtc_position(struct dc *dc, return ret; } -static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) +static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); int i = 0; @@ -218,7 +218,7 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream) return ret; } -static bool program_csc_matrix(struct dc *dc, struct dc_stream *stream) +static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); int i = 0; @@ -241,7 +241,7 @@ static bool program_csc_matrix(struct dc *dc, struct dc_stream *stream) } static void set_static_screen_events(struct dc *dc, - struct dc_stream **streams, + struct dc_stream_state **streams, int num_streams, const struct dc_static_screen_events *events) { @@ -252,7 +252,7 @@ static void set_static_screen_events(struct dc *dc, int num_pipes_affected = 0; for (i = 0; i < num_streams; i++) { - struct dc_stream *stream = streams[i]; + struct dc_stream_state *stream = streams[i]; for (j = 0; j < MAX_PIPES; j++) { if (core_dc->current_context->res_ctx.pipe_ctx[j].stream @@ -333,7 +333,7 @@ static void set_test_pattern( cust_pattern_size); } -void set_dither_option(struct dc_stream *stream, +void set_dither_option(struct dc_stream_state *stream, enum dc_dither_option option) { struct bit_depth_reduction_params params; @@ -769,7 +769,7 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - struct dc_stream *stream) + struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); enum dc_status result = DC_ERROR_UNEXPECTED; @@ -893,7 +893,7 @@ static bool context_changed( static bool streams_changed( struct core_dc *dc, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count) { uint8_t i; @@ -912,7 +912,7 @@ static bool streams_changed( bool dc_enable_stereo( struct dc *dc, struct validate_context *context, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count) { bool ret = true; @@ -958,7 +958,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; int i, j, k, l; - struct dc_stream *dc_streams[MAX_STREAMS] = {0}; + struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; for (i = 0; i < context->stream_count; i++) dc_streams[i] = context->streams[i]; @@ -1031,7 +1031,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) __func__, context->stream_count); for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; dc_stream_log(stream, core_dc->ctx->logger, @@ -1046,7 +1046,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) bool dc_commit_streams( struct dc *dc, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1062,7 +1062,7 @@ bool dc_commit_streams( __func__, stream_count); for (i = 0; i < stream_count; i++) { - struct dc_stream *stream = streams[i]; + struct dc_stream_state *stream = streams[i]; struct dc_stream_status *status = dc_stream_get_status(stream); int j; @@ -1138,7 +1138,7 @@ bool dc_commit_surfaces_to_stream( struct dc *dc, struct dc_plane_state **new_surfaces, uint8_t new_surface_count, - struct dc_stream *dc_stream) + struct dc_stream_state *dc_stream) { struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs flip_addr[MAX_SURFACES]; @@ -1395,7 +1395,7 @@ enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_surfaces_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, - struct dc_stream *stream, + struct dc_stream_state *stream, struct dc_stream_update *stream_update) { struct core_dc *core_dc = DC_TO_CORE(dc); @@ -1723,7 +1723,7 @@ uint8_t dc_get_current_stream_count(const struct dc *dc) return core_dc->current_context->stream_count; } -struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i) +struct dc_stream_state *dc_get_stream_at_index(const struct dc *dc, uint8_t i) { struct core_dc *core_dc = DC_TO_CORE(dc); if (i < core_dc->current_context->stream_count) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a983a5ee3172..7a2fe2f3e65c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1143,7 +1143,7 @@ static void dpcd_configure_panel_mode( static void enable_stream_features(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; union down_spread_ctrl downspread; @@ -1159,7 +1159,7 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; enum dc_status status; bool skip_video_pattern; struct dc_link *link = stream->sink->link; @@ -1250,7 +1250,7 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; enum dc_color_depth display_color_depth; @@ -1341,7 +1341,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) } enum dc_status dc_link_validate_mode_timing( - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dc_link *link, const struct dc_crtc_timing *timing) { @@ -1374,7 +1374,7 @@ enum dc_status dc_link_validate_mode_timing( bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, - uint32_t frame_ramp, const struct dc_stream *stream) + uint32_t frame_ramp, const struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); struct abm *abm = core_dc->res_pool->abm; @@ -1450,7 +1450,7 @@ bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) } bool dc_link_setup_psr(struct dc_link *link, - const struct dc_stream *stream, struct psr_config *psr_config, + const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context) { struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); @@ -1587,7 +1587,7 @@ void core_link_resume(struct dc_link *link) program_hpd_filter(link); } -static struct fixed31_32 get_pbn_per_slot(struct dc_stream *stream) +static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream) { struct dc_link_settings *link_settings = &stream->sink->link->cur_link_settings; @@ -1696,7 +1696,7 @@ static void update_mst_stream_alloc_table( */ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; @@ -1778,7 +1778,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 17506345f97a..50724f9a8e2c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1433,7 +1433,7 @@ bool dp_validate_mode_timing( return false; } -void decide_link_settings(struct dc_stream *stream, +void decide_link_settings(struct dc_stream_state *stream, struct dc_link_settings *link_setting) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fd1d6be79fee..ce0415f26600 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -294,8 +294,8 @@ void resource_reference_clock_source( } bool resource_are_streams_timing_synchronizable( - struct dc_stream *stream1, - struct dc_stream *stream2) + struct dc_stream_state *stream1, + struct dc_stream_state *stream2) { if (stream1->timing.h_total != stream2->timing.h_total) return false; @@ -431,7 +431,7 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *surface = pipe_ctx->surface; - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->scl_data; struct rect surf_src = surface->src_rect; struct rect clip = { 0 }; @@ -530,7 +530,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { const struct dc_plane_state *surface = pipe_ctx->surface; - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; struct rect surf_clip = surface->clip_rect; int recout_full_x, recout_full_y; @@ -608,7 +608,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *surface = pipe_ctx->surface; - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; struct rect surf_src = surface->src_rect; const int in_w = stream->src.width; const int in_h = stream->src.height; @@ -920,7 +920,7 @@ struct pipe_ctx *find_idle_secondary_pipe( struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; for (i = 0; i < MAX_PIPES; i++) { @@ -940,7 +940,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( static struct pipe_ctx *acquire_free_pipe_for_stream( struct validate_context *context, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; struct resource_context *res_ctx = &context->res_ctx; @@ -979,7 +979,7 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( static void release_free_pipes_for_stream( struct resource_context *res_ctx, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; @@ -997,7 +997,7 @@ static void release_free_pipes_for_stream( static int acquire_first_split_pipe( struct resource_context *res_ctx, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; @@ -1030,7 +1030,7 @@ static int acquire_first_split_pipe( bool resource_attach_surfaces_to_context( struct dc_plane_state * const *surfaces, int surface_count, - struct dc_stream *stream, + struct dc_stream_state *stream, struct validate_context *context, const struct resource_pool *pool) { @@ -1118,8 +1118,8 @@ bool resource_attach_surfaces_to_context( } -static bool is_timing_changed(struct dc_stream *cur_stream, - struct dc_stream *new_stream) +static bool is_timing_changed(struct dc_stream_state *cur_stream, + struct dc_stream_state *new_stream) { if (cur_stream == NULL) return true; @@ -1141,7 +1141,7 @@ static bool is_timing_changed(struct dc_stream *cur_stream, } static bool are_stream_backends_same( - struct dc_stream *stream_a, struct dc_stream *stream_b) + struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) { if (stream_a == stream_b) return true; @@ -1156,7 +1156,7 @@ static bool are_stream_backends_same( } bool dc_is_stream_unchanged( - struct dc_stream *old_stream, struct dc_stream *stream) + struct dc_stream_state *old_stream, struct dc_stream_state *stream) { if (!are_stream_backends_same(old_stream, stream)) @@ -1233,7 +1233,7 @@ static void set_audio_in_use( static int acquire_first_free_pipe( struct resource_context *res_ctx, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; @@ -1260,7 +1260,7 @@ static int acquire_first_free_pipe( static struct stream_encoder *find_first_free_match_stream_enc_for_link( struct resource_context *res_ctx, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i; int j = -1; @@ -1311,7 +1311,7 @@ static struct audio *find_first_free_audio( return 0; } -static void update_stream_signal(struct dc_stream *stream) +static void update_stream_signal(struct dc_stream_state *stream) { if (stream->output_signal == SIGNAL_TYPE_NONE) { struct dc_sink *dc_sink = stream->sink; @@ -1334,12 +1334,12 @@ static void update_stream_signal(struct dc_stream *stream) } bool resource_is_stream_unchanged( - struct validate_context *old_context, struct dc_stream *stream) + struct validate_context *old_context, struct dc_stream_state *stream) { int i; for (i = 0; i < old_context->stream_count; i++) { - struct dc_stream *old_stream = old_context->streams[i]; + struct dc_stream_state *old_stream = old_context->streams[i]; if (are_stream_backends_same(old_stream, stream)) return true; @@ -1352,7 +1352,7 @@ static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { struct dc_plane_state *surface = to_pipe_ctx->surface; - struct dc_stream *stream = to_pipe_ctx->stream; + struct dc_stream_state *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; to_pipe_ctx->stream = stream; @@ -1360,14 +1360,14 @@ static void copy_pipe_ctx( to_pipe_ctx->surface = surface; } -static struct dc_stream *find_pll_sharable_stream( - struct dc_stream *stream_needs_pll, +static struct dc_stream_state *find_pll_sharable_stream( + struct dc_stream_state *stream_needs_pll, struct validate_context *context) { int i; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream_has_pll = context->streams[i]; + struct dc_stream_state *stream_has_pll = context->streams[i]; /* We are looking for non dp, non virtual stream */ if (resource_are_streams_timing_synchronizable( @@ -1411,7 +1411,7 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) return normalized_pix_clk; } -static void calculate_phy_pix_clks(struct dc_stream *stream) +static void calculate_phy_pix_clks(struct dc_stream_state *stream) { update_stream_signal(stream); @@ -1433,7 +1433,7 @@ enum dc_status resource_map_pool_resources( int i, j; for (i = 0; old_context && i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (!resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -1486,7 +1486,7 @@ enum dc_status resource_map_pool_resources( } for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; struct pipe_ctx *pipe_ctx = NULL; int pipe_idx = -1; @@ -1581,7 +1581,7 @@ static void set_avi_info_frame( struct encoder_info_packet *info_packet, struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; struct info_frame info_frame = { {0} }; uint32_t pixel_encoding = 0; @@ -1821,7 +1821,7 @@ static void set_avi_info_frame( static void set_vendor_info_packet( struct encoder_info_packet *info_packet, - struct dc_stream *stream) + struct dc_stream_state *stream) { uint32_t length = 0; bool hdmi_vic_mode = false; @@ -1934,7 +1934,7 @@ static void set_vendor_info_packet( static void set_spd_info_packet( struct encoder_info_packet *info_packet, - struct dc_stream *stream) + struct dc_stream_state *stream) { /* SPD info packet for FreeSync */ @@ -2056,7 +2056,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, struct dc_plane_state *surface, - struct dc_stream *stream) + struct dc_stream_state *stream) { uint16_t i = 0; enum signal_type signal = stream->signal; @@ -2159,7 +2159,7 @@ static void set_hdr_static_info_packet( static void set_vsc_info_packet( struct encoder_info_packet *info_packet, - struct dc_stream *stream) + struct dc_stream_state *stream) { unsigned int vscPacketRevision = 0; unsigned int i; @@ -2312,7 +2312,7 @@ enum dc_status resource_map_clock_resources( /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -2392,7 +2392,7 @@ bool pipe_need_reprogram( return false; } -void resource_build_bit_depth_reduction_params(struct dc_stream *stream, +void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, struct bit_depth_reduction_params *fmt_bit_depth) { enum dc_dither_option option = stream->dither_option; @@ -2502,7 +2502,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream) +bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream) { struct core_dc *core_dc = DC_TO_CORE(dc); struct dc_context *dc_ctx = core_dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index a77e1e80d7c2..7a87f38f2324 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -34,7 +34,7 @@ * Private functions ******************************************************************************/ -static bool construct(struct dc_stream *stream, +static bool construct(struct dc_stream_state *stream, struct dc_sink *dc_sink_data) { uint32_t i = 0; @@ -84,7 +84,7 @@ static bool construct(struct dc_stream *stream, return true; } -static void destruct(struct dc_stream *stream) +static void destruct(struct dc_stream_state *stream) { dc_sink_release(stream->sink); if (stream->out_transfer_func != NULL) { @@ -94,14 +94,14 @@ static void destruct(struct dc_stream *stream) } } -void dc_stream_retain(struct dc_stream *stream) +void dc_stream_retain(struct dc_stream_state *stream) { ASSERT(stream->ref_count > 0); stream->ref_count++; } -void dc_stream_release(struct dc_stream *stream) +void dc_stream_release(struct dc_stream_state *stream) { if (stream != NULL) { @@ -115,15 +115,15 @@ void dc_stream_release(struct dc_stream *stream) } } -struct dc_stream *dc_create_stream_for_sink( +struct dc_stream_state *dc_create_stream_for_sink( struct dc_sink *sink) { - struct dc_stream *stream; + struct dc_stream_state *stream; if (sink == NULL) goto alloc_fail; - stream = dm_alloc(sizeof(struct dc_stream)); + stream = dm_alloc(sizeof(struct dc_stream_state)); if (NULL == stream) goto alloc_fail; @@ -143,7 +143,7 @@ struct dc_stream *dc_create_stream_for_sink( } struct dc_stream_status *dc_stream_get_status( - struct dc_stream *stream) + struct dc_stream_state *stream) { uint8_t i; struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); @@ -161,7 +161,7 @@ struct dc_stream_status *dc_stream_get_status( * Update the cursor attributes and set cursor surface address */ bool dc_stream_set_cursor_attributes( - const struct dc_stream *stream, + const struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes) { int i; @@ -196,7 +196,7 @@ bool dc_stream_set_cursor_attributes( } bool dc_stream_set_cursor_position( - struct dc_stream *stream, + struct dc_stream_state *stream, const struct dc_cursor_position *position) { int i; @@ -245,7 +245,7 @@ bool dc_stream_set_cursor_position( return true; } -uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream) +uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) { uint8_t i; struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); @@ -264,7 +264,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream) return 0; } -bool dc_stream_get_scanoutpos(const struct dc_stream *stream, +bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *v_blank_start, uint32_t *v_blank_end, uint32_t *h_position, @@ -297,7 +297,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, void dc_stream_log( - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dal_logger *dm_logger, enum dc_log_type log_type) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d1943b9644d4..ab805965e321 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -101,30 +101,30 @@ struct dc_cap_funcs { struct dc_surface_dcc_cap *output); }; -struct dc_stream_funcs { +struct dc_stream_state_funcs { bool (*adjust_vmin_vmax)(struct dc *dc, - struct dc_stream **stream, + struct dc_stream_state **stream, int num_streams, int vmin, int vmax); bool (*get_crtc_position)(struct dc *dc, - struct dc_stream **stream, + struct dc_stream_state **stream, int num_streams, unsigned int *v_pos, unsigned int *nom_v_pos); bool (*set_gamut_remap)(struct dc *dc, - const struct dc_stream *stream); + const struct dc_stream_state *stream); bool (*program_csc_matrix)(struct dc *dc, - struct dc_stream *stream); + struct dc_stream_state *stream); void (*set_static_screen_events)(struct dc *dc, - struct dc_stream **stream, + struct dc_stream_state **stream, int num_streams, const struct dc_static_screen_events *events); - void (*set_dither_option)(struct dc_stream *stream, + void (*set_dither_option)(struct dc_stream_state *stream, enum dc_dither_option option); }; @@ -190,7 +190,7 @@ struct dc_debug { struct dc { struct dc_caps caps; struct dc_cap_funcs cap_funcs; - struct dc_stream_funcs stream_funcs; + struct dc_stream_state_funcs stream_funcs; struct dc_link_funcs link_funcs; struct dc_config config; struct dc_debug debug; @@ -426,7 +426,7 @@ bool dc_commit_surfaces_to_stream( struct dc *dc, struct dc_plane_state **dc_surfaces, uint8_t surface_count, - struct dc_stream *stream); + struct dc_stream_state *stream); bool dc_post_update_surfaces_to_stream( struct dc *dc); @@ -478,7 +478,7 @@ struct dc_stream_status { struct dc_link *link; }; -struct dc_stream { +struct dc_stream_state { struct dc_sink *sink; struct dc_crtc_timing timing; @@ -529,7 +529,7 @@ struct dc_stream_update { }; bool dc_is_stream_unchanged( - struct dc_stream *old_stream, struct dc_stream *stream); + struct dc_stream_state *old_stream, struct dc_stream_state *stream); /* * Setup stream attributes if no stream updates are provided @@ -548,30 +548,30 @@ bool dc_is_stream_unchanged( void dc_update_surfaces_and_stream(struct dc *dc, struct dc_surface_update *surface_updates, int surface_count, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct dc_stream_update *stream_update); /* * Log the current stream state. */ void dc_stream_log( - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dal_logger *dc_logger, enum dc_log_type log_type); uint8_t dc_get_current_stream_count(const struct dc *dc); -struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i); +struct dc_stream_state *dc_get_stream_at_index(const struct dc *dc, uint8_t i); /* * Return the current frame counter. */ -uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream); +uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream); /* TODO: Return parsed values rather than direct register read * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) * being refactored properly to be dce-specific */ -bool dc_stream_get_scanoutpos(const struct dc_stream *stream, +bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *v_blank_start, uint32_t *v_blank_end, uint32_t *h_position, @@ -581,12 +581,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream *stream, * Structure to store surface/stream associations for validation */ struct dc_validation_set { - struct dc_stream *stream; + struct dc_stream_state *stream; struct dc_plane_state *surfaces[MAX_SURFACES]; uint8_t surface_count; }; -bool dc_validate_stream(const struct dc *dc, struct dc_stream *stream); +bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream); bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state); /* @@ -615,7 +615,7 @@ bool dc_validate_resources( bool dc_validate_guaranteed( const struct dc *dc, - struct dc_stream *stream); + struct dc_stream_state *stream); void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, @@ -644,7 +644,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context); */ bool dc_commit_streams( struct dc *dc, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count); /* * Enable stereo when commit_streams is not required, @@ -653,19 +653,19 @@ bool dc_commit_streams( bool dc_enable_stereo( struct dc *dc, struct validate_context *context, - struct dc_stream *streams[], + struct dc_stream_state *streams[], uint8_t stream_count); /** * Create a new default stream for the requested sink */ -struct dc_stream *dc_create_stream_for_sink(struct dc_sink *dc_sink); +struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink); -void dc_stream_retain(struct dc_stream *dc_stream); -void dc_stream_release(struct dc_stream *dc_stream); +void dc_stream_retain(struct dc_stream_state *dc_stream); +void dc_stream_release(struct dc_stream_state *dc_stream); struct dc_stream_status *dc_stream_get_status( - struct dc_stream *dc_stream); + struct dc_stream_state *dc_stream); enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, @@ -804,7 +804,7 @@ const struct graphics_object_id dc_get_link_id_at_index( /* Set backlight level of an embedded panel (eDP, LVDS). */ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, - uint32_t frame_ramp, const struct dc_stream *stream); + uint32_t frame_ramp, const struct dc_stream_state *stream); bool dc_link_set_abm_disable(const struct dc_link *dc_link); @@ -813,7 +813,7 @@ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); bool dc_link_setup_psr(struct dc_link *dc_link, - const struct dc_stream *stream, struct psr_config *psr_config, + const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context); /* Request DC to detect if there is a Panel connected. @@ -927,11 +927,11 @@ bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container ******************************************************************************/ /* TODO: Deprecated once we switch to dc_set_cursor_position */ bool dc_stream_set_cursor_attributes( - const struct dc_stream *stream, + const struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes); bool dc_stream_set_cursor_position( - struct dc_stream *stream, + struct dc_stream_state *stream, const struct dc_cursor_position *position); /* Newer interfaces */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 4fb9584452a4..a47f7472ea92 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -35,7 +35,7 @@ /* forward declarations */ struct dc_plane_state; -struct dc_stream; +struct dc_stream_state; struct dc_link; struct dc_sink; struct dal; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 24d0c48258ee..5bb2ac71f297 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1009,7 +1009,7 @@ bool dce110_link_encoder_construct( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); bool is_valid; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 5f05ca65281e..5960fb933f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -196,7 +196,7 @@ bool dce110_link_encoder_validate_wireless_output( bool dce110_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct dc_stream *stream); + const struct dc_stream_state *stream); /****************** HW programming ************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 2cf2fefc3d79..98fb7f02a6fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -660,7 +660,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -765,7 +765,7 @@ enum dc_status dce100_validate_with_context( enum dc_status dce100_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 84dc8916de96..e4310a376116 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -623,7 +623,7 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { struct transform *xfm = pipe_ctx->xfm; @@ -745,7 +745,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; if (pipe_ctx->audio) { @@ -833,7 +833,7 @@ static void build_audio_output( const struct pipe_ctx *pipe_ctx, struct audio_output *audio_output) { - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; audio_output->engine_id = pipe_ctx->stream_enc->id; audio_output->signal = pipe_ctx->stream->signal; @@ -981,7 +981,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( struct validate_context *context, struct core_dc *dc) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; struct tg_color black_color = {0}; @@ -1037,7 +1037,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( struct validate_context *context, struct core_dc *dc) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; @@ -1229,7 +1229,7 @@ void dce110_enable_accelerated_mode(struct core_dc *dc) static uint32_t compute_pstate_blackout_duration( struct bw_fixed blackout_duration, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { uint32_t total_dest_line_time_ns; uint32_t pstate_blackout_duration_ns; @@ -2325,7 +2325,7 @@ void dce110_fill_display_configs( for (j = 0; j < context->stream_count; j++) { int k; - const struct dc_stream *stream = context->streams[j]; + const struct dc_stream_state *stream = context->streams[j]; struct dm_pp_single_disp_config *cfg = &pp_display_cfg->disp_configs[num_cfgs]; const struct pipe_ctx *pipe_ctx = NULL; @@ -2370,7 +2370,7 @@ uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) uint32_t min_vertical_blank_time = -1; for (j = 0; j < context->stream_count; j++) { - struct dc_stream *stream = context->streams[j]; + struct dc_stream_state *stream = context->streams[j]; uint32_t vertical_blank_in_pixels = 0; uint32_t vertical_blank_time = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 5c1790b61290..89b21bd57a35 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -718,7 +718,7 @@ static void get_pixel_clock_parameters( const struct pipe_ctx *pipe_ctx, struct pixel_clk_params *pixel_clk_params) { - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; /*TODO: is this halved for YCbCr 420? in that case we might want to move * the pixel clock normalization for hdmi up to here instead of doing it @@ -780,7 +780,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -973,7 +973,7 @@ enum dc_status dce110_validate_with_context( enum dc_status dce110_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -1006,7 +1006,7 @@ enum dc_status dce110_validate_guaranteed( static struct pipe_ctx *dce110_acquire_underlay( struct validate_context *context, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); struct resource_context *res_ctx = &context->res_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index c68372fa1292..68554d6edd94 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -700,7 +700,7 @@ static void destruct(struct dce110_resource_pool *pool) static struct clock_source *find_matching_pll( struct resource_context *res_ctx, const struct resource_pool *pool, - const struct dc_stream *const stream) + const struct dc_stream_state *const stream) { switch (stream->sink->link->link_enc->transmitter) { case TRANSMITTER_UNIPHY_A: @@ -731,7 +731,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -845,7 +845,7 @@ enum dc_status resource_map_phy_clock_resources( /* acquire new resources */ for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -949,7 +949,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *stream, + struct dc_stream_state *stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index cb2c69fb05a6..feef559f1ecd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -44,7 +44,7 @@ enum dc_status dce112_validate_with_context( enum dc_status dce112_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context); bool dce112_validate_bandwidth( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index bcb66447b558..734b35eddeed 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -677,7 +677,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) continue; @@ -781,7 +781,7 @@ enum dc_status dce80_validate_with_context( enum dc_status dce80_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 3979cb03cf8d..866f63d1259d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -679,7 +679,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( struct validate_context *context, struct core_dc *dc) { - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space; struct tg_color black_color = {0}; bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ? @@ -1445,7 +1445,7 @@ static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, - const struct dc_stream *stream) + const struct dc_stream_state *stream) { struct transform *xfm = pipe_ctx->xfm; @@ -2321,7 +2321,7 @@ static void set_plane_config( } static void dcn10_config_stereo_parameters( - struct dc_stream *stream, struct crtc_stereo_flags *flags) + struct dc_stream_state *stream, struct crtc_stereo_flags *flags) { enum view_3d_format view_format = stream->view_format; enum dc_timing_3d_format timing_3d_format =\ @@ -2360,7 +2360,7 @@ static void dcn10_config_stereo_parameters( static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) { struct crtc_stereo_flags flags = { 0 }; - struct dc_stream *stream = pipe_ctx->stream; + struct dc_stream_state *stream = pipe_ctx->stream; dcn10_config_stereo_parameters(stream, &flags); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 9d44f42cbf96..5a9fcbc22d04 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -774,7 +774,7 @@ static void get_pixel_clock_parameters( const struct pipe_ctx *pipe_ctx, struct pixel_clk_params *pixel_clk_params) { - const struct dc_stream *stream = pipe_ctx->stream; + const struct dc_stream_state *stream = pipe_ctx->stream; pixel_clk_params->requested_pix_clk = stream->timing.pix_clk_khz; pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; @@ -796,7 +796,7 @@ static void get_pixel_clock_parameters( } -static void build_clamping_params(struct dc_stream *stream) +static void build_clamping_params(struct dc_stream_state *stream) { stream->clamping.clamping_level = CLAMPING_FULL_RANGE; stream->clamping.c_depth = stream->timing.display_color_depth; @@ -831,7 +831,7 @@ static enum dc_status build_mapped_resource( uint8_t i, j; for (i = 0; i < context->stream_count; i++) { - struct dc_stream *stream = context->streams[i]; + struct dc_stream_state *stream = context->streams[i]; if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { @@ -916,7 +916,7 @@ enum dc_status dcn10_validate_with_context( enum dc_status dcn10_validate_guaranteed( const struct core_dc *dc, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -947,7 +947,7 @@ enum dc_status dcn10_validate_guaranteed( static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( struct validate_context *context, const struct resource_pool *pool, - struct dc_stream *stream) + struct dc_stream_state *stream) { struct resource_context *res_ctx = &context->res_ctx; struct pipe_ctx *head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index e8bd501feb48..39010325cef9 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -45,7 +45,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( */ bool dm_helpers_dp_mst_write_payload_allocation_table( struct dc_context *ctx, - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dp_mst_stream_allocation_table *proposed_table, bool enable); @@ -54,13 +54,13 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( */ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( struct dc_context *ctx, - const struct dc_stream *stream); + const struct dc_stream_state *stream); /* * Sends ALLOCATE_PAYLOAD message. */ bool dm_helpers_dp_mst_send_payload_allocation( struct dc_context *ctx, - const struct dc_stream *stream, + const struct dc_stream_state *stream, bool enable); bool dm_helpers_dp_mst_start_top_mgr( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 44a87c9427f7..d5c0f9e34ce9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -60,7 +60,7 @@ struct dc_link *link_create(const struct link_init_data *init_params); void link_destroy(struct dc_link **link); enum dc_status dc_link_validate_mode_timing( - const struct dc_stream *stream, + const struct dc_stream_state *stream, struct dc_link *link, const struct dc_crtc_timing *timing); @@ -92,7 +92,7 @@ struct resource_funcs { enum dc_status (*validate_guaranteed)( const struct core_dc *dc, - struct dc_stream *stream, + struct dc_stream_state *stream, struct validate_context *context); bool (*validate_bandwidth)( @@ -102,8 +102,7 @@ struct resource_funcs { struct pipe_ctx *(*acquire_idle_pipe_for_layer)( struct validate_context *context, const struct resource_pool *pool, - struct dc_stream *stream); - + struct dc_stream_state *stream); enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); }; @@ -155,7 +154,7 @@ struct resource_pool { struct pipe_ctx { struct dc_plane_state *surface; - struct dc_stream *stream; + struct dc_stream_state *stream; struct mem_input *mi; struct input_pixel_processor *ipp; @@ -240,7 +239,7 @@ union bw_context { }; struct validate_context { - struct dc_stream *streams[MAX_PIPES]; + struct dc_stream_state *streams[MAX_PIPES]; struct dc_stream_status stream_status[MAX_PIPES]; uint8_t stream_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 1a4a605cb449..7168dcc70ae7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -30,7 +30,7 @@ #define LINK_TRAINING_RETRY_DELAY 50 /* ms */ struct dc_link; -struct dc_stream; +struct dc_stream_state; struct dc_link_settings; bool dp_hbr_verify_link_cap( @@ -50,7 +50,7 @@ bool dp_validate_mode_timing( const struct dc_crtc_timing *timing); void decide_link_settings( - struct dc_stream *stream, + struct dc_stream_state *stream, struct dc_link_settings *link_setting); bool perform_link_training_with_retries( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 28fb02fb677e..38e4070806cb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -93,7 +93,7 @@ struct link_encoder { struct link_encoder_funcs { bool (*validate_output_with_stream)( - struct link_encoder *enc, const struct dc_stream *stream); + struct link_encoder *enc, const struct dc_stream_state *stream); void (*hw_init)(struct link_encoder *enc); void (*setup)(struct link_encoder *enc, enum signal_type signal); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index c529ddd2e0d5..7e03f8d45b2b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -92,7 +92,7 @@ struct hw_sequencer_funcs { bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct dc_stream *stream); + const struct dc_stream_state *stream); void (*power_down)(struct core_dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index bfd7cfc86df0..aef1197cf749 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -103,8 +103,8 @@ void resource_reference_clock_source( struct clock_source *clock_source); bool resource_are_streams_timing_synchronizable( - struct dc_stream *stream1, - struct dc_stream *stream2); + struct dc_stream_state *stream1, + struct dc_stream_state *stream2); struct clock_source *resource_find_used_clk_src_for_sharing( struct resource_context *res_ctx, @@ -116,12 +116,12 @@ struct clock_source *dc_resource_find_first_free_pll( struct pipe_ctx *resource_get_head_pipe_for_stream( struct resource_context *res_ctx, - struct dc_stream *stream); + struct dc_stream_state *stream); bool resource_attach_surfaces_to_context( struct dc_plane_state *const *surfaces, int surface_count, - struct dc_stream *dc_stream, + struct dc_stream_state *dc_stream, struct validate_context *context, const struct resource_pool *pool); @@ -130,8 +130,7 @@ struct pipe_ctx *find_idle_secondary_pipe( const struct resource_pool *pool); bool resource_is_stream_unchanged( - struct validate_context *old_context, struct dc_stream *stream); - + struct validate_context *old_context, struct dc_stream_state *stream); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], @@ -162,7 +161,7 @@ bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx); -void resource_build_bit_depth_reduction_params(struct dc_stream *stream, +void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, struct bit_depth_reduction_params *fmt_bit_depth); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index dd024c99fb7e..57b5a3babdf8 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -30,7 +30,7 @@ static bool virtual_link_encoder_validate_output_with_stream( struct link_encoder *enc, - const struct dc_stream *stream) { return true; } + const struct dc_stream_state *stream) { return true; } static void virtual_link_encoder_hw_init(struct link_encoder *enc) {} diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 358f8a855a59..f0a3e4332a09 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -111,7 +111,7 @@ struct freesync_state { }; struct freesync_entity { - struct dc_stream *stream; + struct dc_stream_state *stream; struct mod_freesync_caps *caps; struct freesync_state state; struct mod_freesync_user_enable user_enable; @@ -229,7 +229,7 @@ void mod_freesync_destroy(struct mod_freesync *mod_freesync) * on the core_freesync->map and returns the corresponding index */ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, - struct dc_stream *stream) + struct dc_stream_state *stream) { unsigned int index = 0; @@ -244,7 +244,7 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, } bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream, struct mod_freesync_caps *caps) + struct dc_stream_state *stream, struct mod_freesync_caps *caps) { struct core_dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; @@ -322,7 +322,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, } bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream) + struct dc_stream_state *stream) { int i = 0; struct core_freesync *core_freesync = NULL; @@ -344,7 +344,7 @@ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, } static void update_stream_freesync_context(struct core_freesync *core_freesync, - struct dc_stream *stream) + struct dc_stream_state *stream) { unsigned int index; struct freesync_context *ctx; @@ -368,7 +368,7 @@ static void update_stream_freesync_context(struct core_freesync *core_freesync, } static void update_stream(struct core_freesync *core_freesync, - struct dc_stream *stream) + struct dc_stream_state *stream) { unsigned int index = map_index_from_stream(core_freesync, stream); if (core_freesync->map[index].caps->supported) { @@ -378,7 +378,7 @@ static void update_stream(struct core_freesync *core_freesync, } static void calc_freesync_range(struct core_freesync *core_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct freesync_state *state, unsigned int min_refresh_in_uhz, unsigned int max_refresh_in_uhz) @@ -452,7 +452,7 @@ static void calc_freesync_range(struct core_freesync *core_freesync, min_frame_duration_in_ns) / 2000; } -static void calc_v_total_from_duration(struct dc_stream *stream, +static void calc_v_total_from_duration(struct dc_stream_state *stream, unsigned int duration_in_ns, int *v_total_nominal) { *v_total_nominal = div64_u64(div64_u64(((unsigned long long)( @@ -461,7 +461,7 @@ static void calc_v_total_from_duration(struct dc_stream *stream, } static void calc_v_total_for_static_ramp(struct core_freesync *core_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int index, int *v_total) { unsigned int frame_duration = 0; @@ -557,7 +557,7 @@ static void reset_freesync_state_variables(struct freesync_state* state) * Sets freesync mode on a stream depending on current freesync state. */ static bool set_freesync_on_streams(struct core_freesync *core_freesync, - struct dc_stream **streams, int num_streams) + struct dc_stream_state **streams, int num_streams) { int v_total_nominal = 0, v_total_min = 0, v_total_max = 0; unsigned int stream_idx, map_index = 0; @@ -729,7 +729,7 @@ static void set_static_ramp_variables(struct core_freesync *core_freesync, } void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams) + struct dc_stream_state **streams, int num_streams) { unsigned int index, v_total, inserted_frame_v_total = 0; unsigned int min_frame_duration_in_ns, vmax, vmin = 0; @@ -839,7 +839,7 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, } void mod_freesync_update_state(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, struct mod_freesync_params *freesync_params) { bool freesync_program_required = false; @@ -929,7 +929,7 @@ void mod_freesync_update_state(struct mod_freesync *mod_freesync, bool mod_freesync_get_state(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct mod_freesync_params *freesync_params) { unsigned int index = 0; @@ -965,7 +965,7 @@ bool mod_freesync_get_state(struct mod_freesync *mod_freesync, } bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, struct mod_freesync_user_enable *user_enable) { unsigned int stream_index, map_index; @@ -1017,7 +1017,7 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, } bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct mod_freesync_user_enable *user_enable) { unsigned int index = 0; @@ -1035,7 +1035,7 @@ bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, } bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, bool *is_ramp_active) { unsigned int index = 0; @@ -1054,7 +1054,7 @@ bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, } bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, - struct dc_stream *streams, + struct dc_stream_state *streams, unsigned int min_refresh, unsigned int max_refresh, struct mod_freesync_caps *caps) @@ -1107,7 +1107,7 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, } bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *min_refresh, unsigned int *max_refresh) { @@ -1129,7 +1129,7 @@ bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, } bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *vmin, unsigned int *vmax) { @@ -1151,7 +1151,7 @@ bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, } bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *nom_v_pos, unsigned int *v_pos) { @@ -1179,7 +1179,7 @@ bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, } void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams) + struct dc_stream_state **streams, int num_streams) { unsigned int stream_index, map_index; struct freesync_state *state; @@ -1239,7 +1239,7 @@ void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, * is required, depending on the times calculated */ static void update_timestamps(struct core_freesync *core_freesync, - const struct dc_stream *stream, unsigned int map_index, + const struct dc_stream_state *stream, unsigned int map_index, unsigned int last_render_time_in_us) { struct freesync_state *state = &core_freesync->map[map_index].state; @@ -1304,7 +1304,7 @@ static void update_timestamps(struct core_freesync *core_freesync, } static void apply_below_the_range(struct core_freesync *core_freesync, - struct dc_stream *stream, unsigned int map_index, + struct dc_stream_state *stream, unsigned int map_index, unsigned int last_render_time_in_us) { unsigned int inserted_frame_duration_in_us = 0; @@ -1403,7 +1403,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync, } static void apply_fixed_refresh(struct core_freesync *core_freesync, - struct dc_stream *stream, unsigned int map_index) + struct dc_stream_state *stream, unsigned int map_index) { unsigned int vmin = 0, vmax = 0; struct freesync_state *state = &core_freesync->map[map_index].state; @@ -1434,7 +1434,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync, } void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, unsigned int curr_time_stamp_in_us) { unsigned int stream_index, map_index, last_render_time_in_us = 0; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h index 2b9d45100bdd..84b53425f2c8 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h @@ -101,67 +101,67 @@ struct mod_freesync_params { * Add stream to be tracked by module */ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream, struct mod_freesync_caps *caps); + struct dc_stream_state *stream, struct mod_freesync_caps *caps); /* * Remove stream to be tracked by module */ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync, - struct dc_stream *stream); + struct dc_stream_state *stream); /* * Update the freesync state flags for each display and program * freesync accordingly */ void mod_freesync_update_state(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, struct mod_freesync_params *freesync_params); bool mod_freesync_get_state(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct mod_freesync_params *freesync_params); bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, struct mod_freesync_user_enable *user_enable); bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, struct mod_freesync_user_enable *user_enable); bool mod_freesync_get_static_ramp_active(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, bool *is_ramp_active); bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync, - struct dc_stream *streams, + struct dc_stream_state *streams, unsigned int min_refresh, unsigned int max_refresh, struct mod_freesync_caps *caps); bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *min_refresh, unsigned int *max_refresh); bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *vmin, unsigned int *vmax); bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync, - struct dc_stream *stream, + struct dc_stream_state *stream, unsigned int *nom_v_pos, unsigned int *v_pos); void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams); + struct dc_stream_state **streams, int num_streams); void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams); + struct dc_stream_state **streams, int num_streams); void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync, - struct dc_stream **streams, int num_streams, + struct dc_stream_state **streams, int num_streams, unsigned int curr_time_stamp); #endif -- GitLab From 3be5262e353b8ab97c528bfc7d0dd3c820e4ba27 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 27 Jul 2017 09:55:38 -0400 Subject: [PATCH 0726/2898] drm/amd/display: Rename more dc_surface stuff to plane_state Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 288 +++++++++--------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- .../gpu/drm/amd/display/dc/calcs/dce_calcs.c | 20 +- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 52 ++-- drivers/gpu/drm/amd/display/dc/core/dc.c | 130 ++++---- .../gpu/drm/amd/display/dc/core/dc_debug.c | 188 ++++++------ .../gpu/drm/amd/display/dc/core/dc_resource.c | 190 ++++++------ .../gpu/drm/amd/display/dc/core/dc_stream.c | 8 +- .../gpu/drm/amd/display/dc/core/dc_surface.c | 74 ++--- drivers/gpu/drm/amd/display/dc/dc.h | 32 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 4 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 8 +- .../display/dc/dce110/dce110_hw_sequencer.c | 125 ++++---- .../amd/display/dc/dce110/dce110_resource.c | 20 +- .../amd/display/dc/dce112/dce112_resource.c | 8 +- .../amd/display/dc/dce120/dce120_resource.c | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 8 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 140 ++++----- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 4 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- .../amd/display/include/logger_interface.h | 2 +- 24 files changed, 658 insertions(+), 657 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 497104a29d89..08567b3631cf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -70,7 +70,7 @@ #include "i2caux_interface.h" -static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { +static enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, @@ -79,14 +79,14 @@ static enum drm_plane_type dm_surfaces_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, }; -static enum drm_plane_type dm_surfaces_type_carizzo[AMDGPU_MAX_PLANES] = { +static enum drm_plane_type dm_plane_type_carizzo[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_OVERLAY,/* YUV Capable Underlay */ }; -static enum drm_plane_type dm_surfaces_type_stoney[AMDGPU_MAX_PLANES] = { +static enum drm_plane_type dm_plane_type_stoney[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_OVERLAY, /* YUV Capable Underlay */ @@ -1285,11 +1285,11 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) return -1; } - for (i = 0; i < dm->dc->caps.max_surfaces; i++) { + for (i = 0; i < dm->dc->caps.max_planes; i++) { mode_info->planes[i] = kzalloc(sizeof(struct amdgpu_plane), GFP_KERNEL); if (!mode_info->planes[i]) { - DRM_ERROR("KMS: Failed to allocate surface\n"); + DRM_ERROR("KMS: Failed to allocate plane\n"); goto fail_free_planes; } mode_info->planes[i]->base.type = mode_info->plane_type[i]; @@ -1389,7 +1389,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) fail_free_connector: kfree(aconnector); fail_free_planes: - for (i = 0; i < dm->dc->caps.max_surfaces; i++) + for (i = 0; i < dm->dc->caps.max_planes; i++) kfree(mode_info->planes[i]); return -1; } @@ -1518,52 +1518,52 @@ static int dm_early_init(void *handle) adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; case CHIP_FIJI: case CHIP_TONGA: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 7; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; case CHIP_CARRIZO: adev->mode_info.num_crtc = 3; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; - adev->mode_info.plane_type = dm_surfaces_type_carizzo; + adev->mode_info.plane_type = dm_plane_type_carizzo; break; case CHIP_STONEY: adev->mode_info.num_crtc = 2; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 9; - adev->mode_info.plane_type = dm_surfaces_type_stoney; + adev->mode_info.plane_type = dm_plane_type_stoney; break; case CHIP_POLARIS11: case CHIP_POLARIS12: adev->mode_info.num_crtc = 5; adev->mode_info.num_hpd = 5; adev->mode_info.num_dig = 5; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; case CHIP_POLARIS10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; case CHIP_VEGA10: adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case CHIP_RAVEN: adev->mode_info.num_crtc = 4; adev->mode_info.num_hpd = 4; adev->mode_info.num_dig = 4; - adev->mode_info.plane_type = dm_surfaces_type_default; + adev->mode_info.plane_type = dm_plane_type_default; break; #endif default: @@ -1821,50 +1821,50 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, static bool fill_rects_from_plane_state( const struct drm_plane_state *state, - struct dc_plane_state *surface) + struct dc_plane_state *plane_state) { - surface->src_rect.x = state->src_x >> 16; - surface->src_rect.y = state->src_y >> 16; + plane_state->src_rect.x = state->src_x >> 16; + plane_state->src_rect.y = state->src_y >> 16; /*we ignore for now mantissa and do not to deal with floating pixels :(*/ - surface->src_rect.width = state->src_w >> 16; + plane_state->src_rect.width = state->src_w >> 16; - if (surface->src_rect.width == 0) + if (plane_state->src_rect.width == 0) return false; - surface->src_rect.height = state->src_h >> 16; - if (surface->src_rect.height == 0) + plane_state->src_rect.height = state->src_h >> 16; + if (plane_state->src_rect.height == 0) return false; - surface->dst_rect.x = state->crtc_x; - surface->dst_rect.y = state->crtc_y; + plane_state->dst_rect.x = state->crtc_x; + plane_state->dst_rect.y = state->crtc_y; if (state->crtc_w == 0) return false; - surface->dst_rect.width = state->crtc_w; + plane_state->dst_rect.width = state->crtc_w; if (state->crtc_h == 0) return false; - surface->dst_rect.height = state->crtc_h; + plane_state->dst_rect.height = state->crtc_h; - surface->clip_rect = surface->dst_rect; + plane_state->clip_rect = plane_state->dst_rect; switch (state->rotation & DRM_MODE_ROTATE_MASK) { case DRM_MODE_ROTATE_0: - surface->rotation = ROTATION_ANGLE_0; + plane_state->rotation = ROTATION_ANGLE_0; break; case DRM_MODE_ROTATE_90: - surface->rotation = ROTATION_ANGLE_90; + plane_state->rotation = ROTATION_ANGLE_90; break; case DRM_MODE_ROTATE_180: - surface->rotation = ROTATION_ANGLE_180; + plane_state->rotation = ROTATION_ANGLE_180; break; case DRM_MODE_ROTATE_270: - surface->rotation = ROTATION_ANGLE_270; + plane_state->rotation = ROTATION_ANGLE_270; break; default: - surface->rotation = ROTATION_ANGLE_0; + plane_state->rotation = ROTATION_ANGLE_0; break; } @@ -1896,7 +1896,7 @@ static int get_fb_info( static int fill_plane_attributes_from_fb( struct amdgpu_device *adev, - struct dc_plane_state *surface, + struct dc_plane_state *plane_state, const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) { uint64_t tiling_flags; @@ -1916,28 +1916,28 @@ static int fill_plane_attributes_from_fb( switch (fb->format->format) { case DRM_FORMAT_C8: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS; break; case DRM_FORMAT_RGB565: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565; break; case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888; break; case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_ARGB2101010: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010; break; case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: - surface->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; + plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010; break; case DRM_FORMAT_NV21: - surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; + plane_state->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr; break; case DRM_FORMAT_NV12: - surface->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; + plane_state->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb; break; default: DRM_ERROR("Unsupported screen format %s\n", @@ -1945,45 +1945,45 @@ static int fill_plane_attributes_from_fb( return -EINVAL; } - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - surface->address.type = PLN_ADDR_TYPE_GRAPHICS; - surface->address.grph.addr.low_part = lower_32_bits(fb_location); - surface->address.grph.addr.high_part = upper_32_bits(fb_location); - surface->plane_size.grph.surface_size.x = 0; - surface->plane_size.grph.surface_size.y = 0; - surface->plane_size.grph.surface_size.width = fb->width; - surface->plane_size.grph.surface_size.height = fb->height; - surface->plane_size.grph.surface_pitch = + if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + plane_state->address.type = PLN_ADDR_TYPE_GRAPHICS; + plane_state->address.grph.addr.low_part = lower_32_bits(fb_location); + plane_state->address.grph.addr.high_part = upper_32_bits(fb_location); + plane_state->plane_size.grph.surface_size.x = 0; + plane_state->plane_size.grph.surface_size.y = 0; + plane_state->plane_size.grph.surface_size.width = fb->width; + plane_state->plane_size.grph.surface_size.height = fb->height; + plane_state->plane_size.grph.surface_pitch = fb->pitches[0] / fb->format->cpp[0]; /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_SRGB; + plane_state->color_space = COLOR_SPACE_SRGB; } else { awidth = ALIGN(fb->width, 64); - surface->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; - surface->address.video_progressive.luma_addr.low_part + plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; + plane_state->address.video_progressive.luma_addr.low_part = lower_32_bits(fb_location); - surface->address.video_progressive.chroma_addr.low_part + plane_state->address.video_progressive.chroma_addr.low_part = lower_32_bits(fb_location) + (awidth * fb->height); - surface->plane_size.video.luma_size.x = 0; - surface->plane_size.video.luma_size.y = 0; - surface->plane_size.video.luma_size.width = awidth; - surface->plane_size.video.luma_size.height = fb->height; + plane_state->plane_size.video.luma_size.x = 0; + plane_state->plane_size.video.luma_size.y = 0; + plane_state->plane_size.video.luma_size.width = awidth; + plane_state->plane_size.video.luma_size.height = fb->height; /* TODO: unhardcode */ - surface->plane_size.video.luma_pitch = awidth; + plane_state->plane_size.video.luma_pitch = awidth; - surface->plane_size.video.chroma_size.x = 0; - surface->plane_size.video.chroma_size.y = 0; - surface->plane_size.video.chroma_size.width = awidth; - surface->plane_size.video.chroma_size.height = fb->height; - surface->plane_size.video.chroma_pitch = awidth / 2; + plane_state->plane_size.video.chroma_size.x = 0; + plane_state->plane_size.video.chroma_size.y = 0; + plane_state->plane_size.video.chroma_size.width = awidth; + plane_state->plane_size.video.chroma_size.height = fb->height; + plane_state->plane_size.video.chroma_pitch = awidth / 2; /* TODO: unhardcode */ - surface->color_space = COLOR_SPACE_YCBCR709; + plane_state->color_space = COLOR_SPACE_YCBCR709; } - memset(&surface->tiling_info, 0, sizeof(surface->tiling_info)); + memset(&plane_state->tiling_info, 0, sizeof(plane_state->tiling_info)); /* Fill GFX8 params */ if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) { @@ -1996,51 +1996,51 @@ static int fill_plane_attributes_from_fb( num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS); /* XXX fix me for VI */ - surface->tiling_info.gfx8.num_banks = num_banks; - surface->tiling_info.gfx8.array_mode = + plane_state->tiling_info.gfx8.num_banks = num_banks; + plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_2D_TILED_THIN1; - surface->tiling_info.gfx8.tile_split = tile_split; - surface->tiling_info.gfx8.bank_width = bankw; - surface->tiling_info.gfx8.bank_height = bankh; - surface->tiling_info.gfx8.tile_aspect = mtaspect; - surface->tiling_info.gfx8.tile_mode = + plane_state->tiling_info.gfx8.tile_split = tile_split; + plane_state->tiling_info.gfx8.bank_width = bankw; + plane_state->tiling_info.gfx8.bank_height = bankh; + plane_state->tiling_info.gfx8.tile_aspect = mtaspect; + plane_state->tiling_info.gfx8.tile_mode = DC_ADDR_SURF_MICRO_TILING_DISPLAY; } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_1D_TILED_THIN1) { - surface->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; + plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1; } - surface->tiling_info.gfx8.pipe_config = + plane_state->tiling_info.gfx8.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); if (adev->asic_type == CHIP_VEGA10 || adev->asic_type == CHIP_RAVEN) { /* Fill GFX9 params */ - surface->tiling_info.gfx9.num_pipes = + plane_state->tiling_info.gfx9.num_pipes = adev->gfx.config.gb_addr_config_fields.num_pipes; - surface->tiling_info.gfx9.num_banks = + plane_state->tiling_info.gfx9.num_banks = adev->gfx.config.gb_addr_config_fields.num_banks; - surface->tiling_info.gfx9.pipe_interleave = + plane_state->tiling_info.gfx9.pipe_interleave = adev->gfx.config.gb_addr_config_fields.pipe_interleave_size; - surface->tiling_info.gfx9.num_shader_engines = + plane_state->tiling_info.gfx9.num_shader_engines = adev->gfx.config.gb_addr_config_fields.num_se; - surface->tiling_info.gfx9.max_compressed_frags = + plane_state->tiling_info.gfx9.max_compressed_frags = adev->gfx.config.gb_addr_config_fields.max_compress_frags; - surface->tiling_info.gfx9.num_rb_per_se = + plane_state->tiling_info.gfx9.num_rb_per_se = adev->gfx.config.gb_addr_config_fields.num_rb_per_se; - surface->tiling_info.gfx9.swizzle = + plane_state->tiling_info.gfx9.swizzle = AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); - surface->tiling_info.gfx9.shaderEnable = 1; + plane_state->tiling_info.gfx9.shaderEnable = 1; } - surface->visible = true; - surface->scaling_quality.h_taps_c = 0; - surface->scaling_quality.v_taps_c = 0; + plane_state->visible = true; + plane_state->scaling_quality.h_taps_c = 0; + plane_state->scaling_quality.v_taps_c = 0; - /* is this needed? is surface zeroed at allocation? */ - surface->scaling_quality.h_taps = 0; - surface->scaling_quality.v_taps = 0; - surface->stereo_format = PLANE_STEREO_FORMAT_NONE; + /* is this needed? is plane_state zeroed at allocation? */ + plane_state->scaling_quality.h_taps = 0; + plane_state->scaling_quality.v_taps = 0; + plane_state->stereo_format = PLANE_STEREO_FORMAT_NONE; return ret; @@ -2050,7 +2050,7 @@ static int fill_plane_attributes_from_fb( static void fill_gamma_from_crtc_state( const struct drm_crtc_state *crtc_state, - struct dc_plane_state *dc_surface) + struct dc_plane_state *plane_state) { int i; struct dc_gamma *gamma; @@ -2069,12 +2069,12 @@ static void fill_gamma_from_crtc_state( gamma->blue[i] = lut[i].blue; } - dc_surface->gamma_correction = gamma; + plane_state->gamma_correction = gamma; } static int fill_plane_attributes( struct amdgpu_device *adev, - struct dc_plane_state *surface, + struct dc_plane_state *dc_plane_state, struct drm_plane_state *plane_state, struct drm_crtc_state *crtc_state, bool addrReq) @@ -2085,12 +2085,12 @@ static int fill_plane_attributes( struct dc_transfer_func *input_tf; int ret = 0; - if (!fill_rects_from_plane_state(plane_state, surface)) + if (!fill_rects_from_plane_state(plane_state, dc_plane_state)) return -EINVAL; ret = fill_plane_attributes_from_fb( crtc->dev->dev_private, - surface, + dc_plane_state, amdgpu_fb, addrReq); @@ -2105,11 +2105,11 @@ static int fill_plane_attributes( input_tf->type = TF_TYPE_PREDEFINED; input_tf->tf = TRANSFER_FUNCTION_SRGB; - surface->in_transfer_func = input_tf; + dc_plane_state->in_transfer_func = input_tf; /* In case of gamma set, update gamma value */ if (crtc_state->gamma_lut) - fill_gamma_from_crtc_state(crtc_state, surface); + fill_gamma_from_crtc_state(crtc_state, dc_plane_state); return ret; } @@ -2991,9 +2991,9 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base); - if (old_dm_plane_state->surface) { - dm_plane_state->surface = old_dm_plane_state->surface; - dc_surface_retain(dm_plane_state->surface); + if (old_dm_plane_state->dc_state) { + dm_plane_state->dc_state = old_dm_plane_state->dc_state; + dc_plane_state_retain(dm_plane_state->dc_state); } return &dm_plane_state->base; @@ -3004,8 +3004,8 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - if (dm_plane_state->surface) - dc_surface_release(dm_plane_state->surface); + if (dm_plane_state->dc_state) + dc_plane_state_release(dm_plane_state->dc_state); __drm_atomic_helper_plane_destroy_state(state); kfree(dm_plane_state); @@ -3059,18 +3059,18 @@ static int dm_plane_helper_prepare_fb( amdgpu_bo_ref(rbo); - if (dm_plane_state_new->surface && - dm_plane_state_old->surface != dm_plane_state_new->surface) { - struct dc_plane_state *surface = dm_plane_state_new->surface; + if (dm_plane_state_new->dc_state && + dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) { + struct dc_plane_state *plane_state = dm_plane_state_new->dc_state; - if (surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - surface->address.grph.addr.low_part = lower_32_bits(afb->address); - surface->address.grph.addr.high_part = upper_32_bits(afb->address); + if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + plane_state->address.grph.addr.low_part = lower_32_bits(afb->address); + plane_state->address.grph.addr.high_part = upper_32_bits(afb->address); } else { awidth = ALIGN(new_state->fb->width, 64); - surface->address.video_progressive.luma_addr.low_part + plane_state->address.video_progressive.luma_addr.low_part = lower_32_bits(afb->address); - surface->address.video_progressive.chroma_addr.low_part + plane_state->address.video_progressive.chroma_addr.low_part = lower_32_bits(afb->address) + (awidth * new_state->fb->height); } @@ -3159,10 +3159,10 @@ int dm_plane_atomic_check(struct drm_plane *plane, struct dc *dc = adev->dm.dc; struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); - if (!dm_plane_state->surface) + if (!dm_plane_state->dc_state) return true; - if (dc_validate_plane(dc, dm_plane_state->surface)) + if (dc_validate_plane(dc, dm_plane_state->dc_state)) return 0; return -EINVAL; @@ -3848,6 +3848,7 @@ static void amdgpu_dm_do_flip( struct amdgpu_device *adev = crtc->dev->dev_private; bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; struct dc_flip_addrs addr = { {0} }; + /* TODO eliminate or rename surface_update */ struct dc_surface_update surface_updates[1] = { {0} }; struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); @@ -3903,11 +3904,11 @@ static void amdgpu_dm_do_flip( if (acrtc->base.state->event) prepare_flip_isr(acrtc); - surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0]; + surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->plane_states[0]; surface_updates->flip_addr = &addr; - dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); + dc_update_planes_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, @@ -3918,7 +3919,7 @@ static void amdgpu_dm_do_flip( spin_unlock_irqrestore(&crtc->dev->event_lock, flags); } -static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, +static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, struct drm_device *dev, struct amdgpu_display_manager *dm, struct drm_crtc *pcrtc, @@ -3928,7 +3929,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *old_plane_state; struct dc_stream_state *dc_stream_attach; - struct dc_plane_state *dc_surfaces_constructed[MAX_SURFACES]; + struct dc_plane_state *plane_states_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); int planes_count = 0; @@ -3956,8 +3957,9 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, spin_lock_irqsave(&crtc->dev->event_lock, flags); if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) { - DRM_ERROR("add_surface: acrtc %d, already busy\n", - acrtc_attach->crtc_id); + DRM_ERROR("%s: acrtc %d, already busy\n", + __func__, + acrtc_attach->crtc_id); spin_unlock_irqrestore(&crtc->dev->event_lock, flags); /* In commit tail framework this cannot happen */ WARN_ON(1); @@ -3965,9 +3967,9 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); if (!pflip_needed) { - WARN_ON(!dm_plane_state->surface); + WARN_ON(!dm_plane_state->dc_state); - dc_surfaces_constructed[planes_count] = dm_plane_state->surface; + plane_states_constructed[planes_count] = dm_plane_state->dc_state; dc_stream_attach = acrtc_state->stream; planes_count++; @@ -4010,11 +4012,11 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); } - if (false == dc_commit_surfaces_to_stream(dm->dc, - dc_surfaces_constructed, - planes_count, - dc_stream_attach)) - dm_error("%s: Failed to attach surface!\n", __func__); + if (false == dc_commit_planes_to_stream(dm->dc, + plane_states_constructed, + planes_count, + dc_stream_attach)) + dm_error("%s: Failed to attach plane!\n", __func__); } else { /*TODO BUG Here should go disable planes on CRTC. */ } @@ -4226,16 +4228,16 @@ void amdgpu_dm_atomic_commit_tail( status = dc_stream_get_status(new_acrtc_state->stream); WARN_ON(!status); - WARN_ON(!status->surface_count); + WARN_ON(!status->plane_count); if (!new_acrtc_state->stream) continue; /*TODO How it works with MPO ?*/ - if (!dc_commit_surfaces_to_stream( + if (!dc_commit_planes_to_stream( dm->dc, - status->surfaces, - status->surface_count, + status->plane_states, + status->plane_count, new_acrtc_state->stream)) dm_error("%s: Failed to update stream scaling!\n", __func__); } @@ -4260,7 +4262,7 @@ void amdgpu_dm_atomic_commit_tail( new_acrtc_state = to_dm_crtc_state(pcrtc->state); if (new_acrtc_state->stream) - amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank); + amdgpu_dm_commit_planes(state, dev, dm, pcrtc, &wait_for_vblank); } @@ -4375,27 +4377,27 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector dm_force_atomic_commit(&aconnector->base); } -static uint32_t add_val_sets_surface( +static uint32_t add_val_sets_plane( struct dc_validation_set *val_sets, uint32_t set_count, const struct dc_stream_state *stream, - struct dc_plane_state *surface) + struct dc_plane_state *plane_state) { uint32_t i = 0, j = 0; while (i < set_count) { if (val_sets[i].stream == stream) { - while (val_sets[i].surfaces[j]) + while (val_sets[i].plane_states[j]) j++; break; } ++i; } - val_sets[i].surfaces[j] = surface; - val_sets[i].surface_count++; + val_sets[i].plane_states[j] = plane_state; + val_sets[i].plane_count++; - return val_sets[i].surface_count; + return val_sets[i].plane_count; } static uint32_t update_in_val_sets_stream( @@ -4516,7 +4518,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, /* * This bool will be set for true for any modeset/reset - * or surface update which implies non fast surface update. + * or plane update which implies non fast surface update. */ bool lock_and_validation_needed = false; @@ -4701,13 +4703,13 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, pflip_needed = !state->allow_modeset; if (!pflip_needed) { - struct dc_plane_state *surface; + struct dc_plane_state *dc_plane_state; - surface = dc_create_surface(dc); + dc_plane_state = dc_create_plane_state(dc); ret = fill_plane_attributes( plane_crtc->dev->dev_private, - surface, + dc_plane_state, plane_state, crtc_state, false); @@ -4715,15 +4717,15 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; - if (dm_plane_state->surface) - dc_surface_release(dm_plane_state->surface); + if (dm_plane_state->dc_state) + dc_plane_state_release(dm_plane_state->dc_state); - dm_plane_state->surface = surface; + dm_plane_state->dc_state = dc_plane_state; - add_val_sets_surface(set, + add_val_sets_plane(set, set_count, new_acrtc_state->stream, - surface); + dc_plane_state); lock_and_validation_needed = true; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index cca65a37b213..e0a5632f00a3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -196,7 +196,7 @@ struct dc_stream; struct dm_plane_state { struct drm_plane_state base; - struct dc_plane_state *surface; + struct dc_plane_state *dc_state; }; struct dm_crtc_state { diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 9a850227eeeb..28dbd18b2d86 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2594,15 +2594,15 @@ static void populate_initial_data( if (!pipe[i].stream || !pipe[i].bottom_pipe) continue; - ASSERT(pipe[i].surface); + ASSERT(pipe[i].plane_state); if (num_displays == 0) { - if (!pipe[i].surface->visible) + if (!pipe[i].plane_state->visible) data->d0_underlay_mode = bw_def_underlay_only; else data->d0_underlay_mode = bw_def_blend; } else { - if (!pipe[i].surface->visible) + if (!pipe[i].plane_state->visible) data->d1_underlay_mode = bw_def_underlay_only; else data->d1_underlay_mode = bw_def_blend; @@ -2620,7 +2620,7 @@ static void populate_initial_data( data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->rotation) { + switch (pipe[i].plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); break; @@ -2636,7 +2636,7 @@ static void populate_initial_data( default: break; } - switch (pipe[i].surface->format) { + switch (pipe[i].plane_state->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_RGB565: @@ -2670,14 +2670,14 @@ static void populate_initial_data( data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( - pipe[i].bottom_pipe->surface->plane_size.grph.surface_pitch); + pipe[i].bottom_pipe->plane_state->plane_size.grph.surface_pitch); data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( pipe[i].bottom_pipe->scl_data.ratios.horz.value); data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( pipe[i].bottom_pipe->scl_data.ratios.vert.value); - switch (pipe[i].bottom_pipe->surface->rotation) { + switch (pipe[i].bottom_pipe->plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); break; @@ -2710,7 +2710,7 @@ static void populate_initial_data( data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); - if (pipe[i].surface) { + if (pipe[i].plane_state) { data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); @@ -2718,7 +2718,7 @@ static void populate_initial_data( data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); - switch (pipe[i].surface->rotation) { + switch (pipe[i].plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); break; @@ -2734,7 +2734,7 @@ static void populate_initial_data( default: break; } - switch (pipe[i].surface->format) { + switch (pipe[i].plane_state->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 7f7cb8ff124d..404b39e7b44b 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -233,16 +233,16 @@ static void pipe_ctx_to_e2e_pipe_params ( struct _vcs_dpi_display_pipe_params_st *input) { input->src.is_hsplit = false; - if (pipe->top_pipe != NULL && pipe->top_pipe->surface == pipe->surface) + if (pipe->top_pipe != NULL && pipe->top_pipe->plane_state == pipe->plane_state) input->src.is_hsplit = true; - else if (pipe->bottom_pipe != NULL && pipe->bottom_pipe->surface == pipe->surface) + else if (pipe->bottom_pipe != NULL && pipe->bottom_pipe->plane_state == pipe->plane_state) input->src.is_hsplit = true; - input->src.dcc = pipe->surface->dcc.enable; + input->src.dcc = pipe->plane_state->dcc.enable; input->src.dcc_rate = 1; - input->src.meta_pitch = pipe->surface->dcc.grph.meta_pitch; + input->src.meta_pitch = pipe->plane_state->dcc.grph.meta_pitch; input->src.source_scan = dm_horz; - input->src.sw_mode = pipe->surface->tiling_info.gfx9.swizzle; + input->src.sw_mode = pipe->plane_state->tiling_info.gfx9.swizzle; input->src.viewport_width = pipe->scl_data.viewport.width; input->src.viewport_height = pipe->scl_data.viewport.height; @@ -251,7 +251,7 @@ static void pipe_ctx_to_e2e_pipe_params ( input->src.cur0_src_width = 128; /* TODO: Cursor calcs, not curently stored */ input->src.cur0_bpp = 32; - switch (pipe->surface->tiling_info.gfx9.swizzle) { + switch (pipe->plane_state->tiling_info.gfx9.swizzle) { /* for 4/8/16 high tiles */ case DC_SW_LINEAR: input->src.is_display_sw = 1; @@ -299,7 +299,7 @@ static void pipe_ctx_to_e2e_pipe_params ( break; } - switch (pipe->surface->rotation) { + switch (pipe->plane_state->rotation) { case ROTATION_ANGLE_0: case ROTATION_ANGLE_180: input->src.source_scan = dm_horz; @@ -314,7 +314,7 @@ static void pipe_ctx_to_e2e_pipe_params ( } /* TODO: Fix pixel format mappings */ - switch (pipe->surface->format) { + switch (pipe->plane_state->format) { case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: input->src.source_format = dm_420_8; @@ -455,7 +455,7 @@ static void dcn_bw_calc_rq_dlg_ttu( true, true, v->pte_enable == dcn_bw_yes, - pipe->surface->flip_immediate); + pipe->plane_state->flip_immediate); } static void dcn_dml_wm_override( @@ -478,7 +478,7 @@ static void dcn_dml_wm_override( for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - if (!pipe->stream || !pipe->surface) + if (!pipe->stream || !pipe->plane_state) continue; input[in_idx].clks_cfg.dcfclk_mhz = v->dcfclk; @@ -516,7 +516,7 @@ static void dcn_dml_wm_override( for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - if (!pipe->stream || !pipe->surface) + if (!pipe->stream || !pipe->plane_state) continue; dml_rq_dlg_get_dlg_reg(dml, @@ -527,7 +527,7 @@ static void dcn_dml_wm_override( true, true, v->pte_enable == dcn_bw_yes, - pipe->surface->flip_immediate); + pipe->plane_state->flip_immediate); in_idx++; } dm_free(input); @@ -541,7 +541,7 @@ static void split_stream_across_pipes( { int pipe_idx = secondary_pipe->pipe_idx; - if (!primary_pipe->surface) + if (!primary_pipe->plane_state) return; *secondary_pipe = *primary_pipe; @@ -843,7 +843,7 @@ bool dcn_validate_bandwidth( if (!pipe->stream) continue; /* skip all but first of split pipes */ - if (pipe->top_pipe && pipe->top_pipe->surface == pipe->surface) + if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) continue; v->underscan_output[input_idx] = false; /* taken care of in recout already*/ @@ -869,7 +869,7 @@ bool dcn_validate_bandwidth( } } - if (!pipe->surface){ + if (!pipe->plane_state) { v->dcc_enable[input_idx] = dcn_bw_yes; v->source_pixel_format[input_idx] = dcn_bw_rgb_sub_32; v->source_surface_mode[input_idx] = dcn_bw_sw_4_kb_s; @@ -889,8 +889,8 @@ bool dcn_validate_bandwidth( v->viewport_width[input_idx] = pipe->scl_data.viewport.width; v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width; v->scaler_recout_height[input_idx] = pipe->scl_data.recout.height; - if (pipe->bottom_pipe && pipe->bottom_pipe->surface == pipe->surface) { - if (pipe->surface->rotation % 2 == 0) { + if (pipe->bottom_pipe && pipe->bottom_pipe->plane_state == pipe->plane_state) { + if (pipe->plane_state->rotation % 2 == 0) { int viewport_end = pipe->scl_data.viewport.width + pipe->scl_data.viewport.x; int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.width @@ -919,17 +919,17 @@ bool dcn_validate_bandwidth( + pipe->bottom_pipe->scl_data.recout.width; } - v->dcc_enable[input_idx] = pipe->surface->dcc.enable ? dcn_bw_yes : dcn_bw_no; + v->dcc_enable[input_idx] = pipe->plane_state->dcc.enable ? dcn_bw_yes : dcn_bw_no; v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs( - pipe->surface->format); + pipe->plane_state->format); v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs( - pipe->surface->tiling_info.gfx9.swizzle); + pipe->plane_state->tiling_info.gfx9.swizzle); v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->scl_data.lb_params.depth); v->override_hta_ps[input_idx] = pipe->scl_data.taps.h_taps; v->override_vta_ps[input_idx] = pipe->scl_data.taps.v_taps; v->override_hta_pschroma[input_idx] = pipe->scl_data.taps.h_taps_c; v->override_vta_pschroma[input_idx] = pipe->scl_data.taps.v_taps_c; - v->source_scan[input_idx] = (pipe->surface->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; + v->source_scan[input_idx] = (pipe->plane_state->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; } if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp; @@ -996,7 +996,7 @@ bool dcn_validate_bandwidth( if (!pipe->stream) continue; /* skip all but first of split pipes */ - if (pipe->top_pipe && pipe->top_pipe->surface == pipe->surface) + if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) continue; pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; @@ -1024,7 +1024,7 @@ bool dcn_validate_bandwidth( pipe->pipe_dlg_param.vblank_start = asic_blank_start; pipe->pipe_dlg_param.vblank_end = asic_blank_end; - if (pipe->surface) { + if (pipe->plane_state) { struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; if (v->dpp_per_plane[input_idx] == 2 || @@ -1036,7 +1036,7 @@ bool dcn_validate_bandwidth( TIMING_3D_FORMAT_TOP_AND_BOTTOM || pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE))) { - if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { + if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { /* update previously split pipe */ hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width[input_idx]; hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset[input_idx]; @@ -1057,12 +1057,12 @@ bool dcn_validate_bandwidth( } dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); - } else if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { + } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { /* merge previously split pipe */ pipe->bottom_pipe = hsplit_pipe->bottom_pipe; if (hsplit_pipe->bottom_pipe) hsplit_pipe->bottom_pipe->top_pipe = pipe; - hsplit_pipe->surface = NULL; + hsplit_pipe->plane_state = NULL; hsplit_pipe->stream = NULL; hsplit_pipe->top_pipe = NULL; hsplit_pipe->bottom_pipe = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8b6b7631d776..ffc9c05e2fb5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -639,21 +639,21 @@ static bool is_validation_required( for (i = 0; i < set_count; i++) { - if (set[i].surface_count != context->stream_status[i].surface_count) + if (set[i].plane_count != context->stream_status[i].plane_count) return true; if (!dc_is_stream_unchanged(set[i].stream, context->streams[i])) return true; - for (j = 0; j < set[i].surface_count; j++) { - struct dc_plane_state temp_surf; - memset(&temp_surf, 0, sizeof(temp_surf)); + for (j = 0; j < set[i].plane_count; j++) { + struct dc_plane_state temp_plane; + memset(&temp_plane, 0, sizeof(temp_plane)); - temp_surf = *context->stream_status[i].surfaces[j]; - temp_surf.clip_rect = set[i].surfaces[j]->clip_rect; - temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x; - temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y; + temp_plane = *context->stream_status[i].plane_states[j]; + temp_plane.clip_rect = set[i].plane_states[j]->clip_rect; + temp_plane.dst_rect.x = set[i].plane_states[j]->dst_rect.x; + temp_plane.dst_rect.y = set[i].plane_states[j]->dst_rect.y; - if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0) + if (memcmp(&temp_plane, set[i].plane_states[j], sizeof(temp_plane)) != 0) return true; } } @@ -683,8 +683,8 @@ static bool validate_surfaces( int i, j; for (i = 0; i < set_count; i++) - for (j = 0; j < set[i].surface_count; j++) - if (!dc_validate_plane(dc, set[i].surfaces[j])) + for (j = 0; j < set[i].plane_count; j++) + if (!dc_validate_plane(dc, set[i].plane_states[j])) return false; return true; @@ -977,11 +977,11 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; - for (j = 0; j < context->stream_status[i].surface_count; j++) { - const struct dc_plane_state *surface = - context->stream_status[i].surfaces[j]; + for (j = 0; j < context->stream_status[i].plane_count; j++) { + const struct dc_plane_state *plane_state = + context->stream_status[i].plane_states[j]; - core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); + core_dc->hwss.apply_ctx_for_surface(core_dc, plane_state, context); /* * enable stereo @@ -1073,9 +1073,9 @@ bool dc_commit_streams( set[i].stream = stream; if (status) { - set[i].surface_count = status->surface_count; - for (j = 0; j < status->surface_count; j++) - set[i].surfaces[j] = status->surfaces[j]; + set[i].plane_count = status->plane_count; + for (j = 0; j < status->plane_count; j++) + set[i].plane_states[j] = status->plane_states[j]; } } @@ -1122,7 +1122,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) for (i = 0; i < core_dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL - || context->res_ctx.pipe_ctx[i].surface == NULL) + || context->res_ctx.pipe_ctx[i].plane_state == NULL) core_dc->hwss.power_down_front_end(core_dc, i); /* 3rd param should be true, temp w/a for RV*/ @@ -1134,10 +1134,10 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) return true; } -bool dc_commit_surfaces_to_stream( +bool dc_commit_planes_to_stream( struct dc *dc, - struct dc_plane_state **new_surfaces, - uint8_t new_surface_count, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, struct dc_stream_state *dc_stream) { struct dc_surface_update updates[MAX_SURFACES]; @@ -1162,37 +1162,37 @@ bool dc_commit_surfaces_to_stream( stream_update->dst = dc_stream->dst; stream_update->out_transfer_func = dc_stream->out_transfer_func; - for (i = 0; i < new_surface_count; i++) { - updates[i].surface = new_surfaces[i]; + for (i = 0; i < new_plane_count; i++) { + updates[i].surface = plane_states[i]; updates[i].gamma = - (struct dc_gamma *)new_surfaces[i]->gamma_correction; - updates[i].in_transfer_func = new_surfaces[i]->in_transfer_func; - flip_addr[i].address = new_surfaces[i]->address; - flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate; - plane_info[i].color_space = new_surfaces[i]->color_space; - plane_info[i].format = new_surfaces[i]->format; - plane_info[i].plane_size = new_surfaces[i]->plane_size; - plane_info[i].rotation = new_surfaces[i]->rotation; - plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror; - plane_info[i].stereo_format = new_surfaces[i]->stereo_format; - plane_info[i].tiling_info = new_surfaces[i]->tiling_info; - plane_info[i].visible = new_surfaces[i]->visible; - plane_info[i].per_pixel_alpha = new_surfaces[i]->per_pixel_alpha; - plane_info[i].dcc = new_surfaces[i]->dcc; - scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality; - scaling_info[i].src_rect = new_surfaces[i]->src_rect; - scaling_info[i].dst_rect = new_surfaces[i]->dst_rect; - scaling_info[i].clip_rect = new_surfaces[i]->clip_rect; + (struct dc_gamma *)plane_states[i]->gamma_correction; + updates[i].in_transfer_func = plane_states[i]->in_transfer_func; + flip_addr[i].address = plane_states[i]->address; + flip_addr[i].flip_immediate = plane_states[i]->flip_immediate; + plane_info[i].color_space = plane_states[i]->color_space; + plane_info[i].format = plane_states[i]->format; + plane_info[i].plane_size = plane_states[i]->plane_size; + plane_info[i].rotation = plane_states[i]->rotation; + plane_info[i].horizontal_mirror = plane_states[i]->horizontal_mirror; + plane_info[i].stereo_format = plane_states[i]->stereo_format; + plane_info[i].tiling_info = plane_states[i]->tiling_info; + plane_info[i].visible = plane_states[i]->visible; + plane_info[i].per_pixel_alpha = plane_states[i]->per_pixel_alpha; + plane_info[i].dcc = plane_states[i]->dcc; + scaling_info[i].scaling_quality = plane_states[i]->scaling_quality; + scaling_info[i].src_rect = plane_states[i]->src_rect; + scaling_info[i].dst_rect = plane_states[i]->dst_rect; + scaling_info[i].clip_rect = plane_states[i]->clip_rect; updates[i].flip_addr = &flip_addr[i]; updates[i].plane_info = &plane_info[i]; updates[i].scaling_info = &scaling_info[i]; } - dc_update_surfaces_and_stream( + dc_update_planes_and_stream( dc, updates, - new_surface_count, + new_plane_count, dc_stream, stream_update); dc_post_update_surfaces_to_stream(dc); @@ -1220,14 +1220,14 @@ void dc_release_validate_context(struct validate_context *context) static bool is_surface_in_context( const struct validate_context *context, - const struct dc_plane_state *surface) + const struct dc_plane_state *plane_state) { int j; for (j = 0; j < MAX_PIPES; j++) { const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (surface == pipe_ctx->surface) { + if (plane_state == pipe_ctx->plane_state) { return true; } } @@ -1371,7 +1371,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; - if (stream_status == NULL || stream_status->surface_count != surface_count) + if (stream_status == NULL || stream_status->plane_count != surface_count) return UPDATE_TYPE_FULL; if (stream_update) @@ -1393,7 +1393,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; -void dc_update_surfaces_and_stream(struct dc *dc, +void dc_update_planes_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, struct dc_stream_update *stream_update) @@ -1470,10 +1470,10 @@ void dc_update_surfaces_and_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); if (update_type >= UPDATE_TYPE_FULL) { - struct dc_plane_state *new_surfaces[MAX_SURFACES] = {0}; + struct dc_plane_state *new_planes[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) - new_surfaces[i] = srf_updates[i].surface; + new_planes[i] = srf_updates[i].surface; /* initialize scratch memory for building context */ context = dm_alloc(sizeof(*context)); @@ -1487,7 +1487,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* add surface to context */ if (!resource_attach_surfaces_to_context( - new_surfaces, surface_count, stream, + new_planes, surface_count, stream, context, core_dc->res_pool)) { BREAK_TO_DEBUGGER(); goto fail; @@ -1542,7 +1542,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->plane_state != surface) continue; resource_build_scaling_params(pipe_ctx); @@ -1599,14 +1599,14 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = srf_updates[i].surface; + struct dc_plane_state *plane_state = srf_updates[i].surface; for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (update_type != UPDATE_TYPE_FULL && pipe_ctx->surface != surface) + if (update_type != UPDATE_TYPE_FULL && pipe_ctx->plane_state != plane_state) continue; - if (!pipe_ctx->surface || pipe_ctx->top_pipe) + if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) continue; core_dc->hwss.pipe_control_lock( @@ -1622,15 +1622,15 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct pipe_ctx *cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; - bool is_new_pipe_surface = cur_pipe_ctx->surface != pipe_ctx->surface; + bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; struct dc_cursor_position position = { 0 }; - if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->surface) + if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) continue; if (!pipe_ctx->top_pipe) core_dc->hwss.apply_ctx_for_surface( - core_dc, pipe_ctx->surface, context); + core_dc, pipe_ctx->plane_state, context); /* TODO: this is a hack w/a for switching from mpo to pipe split */ dc_stream_set_cursor_position(pipe_ctx->stream, &position); @@ -1638,7 +1638,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (is_new_pipe_surface) { core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); core_dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->surface); + pipe_ctx, pipe_ctx->plane_state); core_dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->stream); } @@ -1649,16 +1649,16 @@ void dc_update_surfaces_and_stream(struct dc *dc, /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = srf_updates[i].surface; + struct dc_plane_state *plane_state = srf_updates[i].surface; if (update_type == UPDATE_TYPE_MED) core_dc->hwss.apply_ctx_for_surface( - core_dc, surface, context); + core_dc, plane_state, context); for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->plane_state != plane_state) continue; if (srf_updates[i].flip_addr) @@ -1669,7 +1669,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, if (srf_updates[i].in_transfer_func) core_dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->surface); + pipe_ctx, pipe_ctx->plane_state); if (stream_update != NULL && stream_update->out_transfer_func != NULL) { @@ -1690,9 +1690,9 @@ void dc_update_surfaces_and_stream(struct dc *dc, for (j = 0; j < surface_count; j++) { if (update_type != UPDATE_TYPE_FULL && - srf_updates[j].surface != pipe_ctx->surface) + srf_updates[j].surface != pipe_ctx->plane_state) continue; - if (!pipe_ctx->surface || pipe_ctx->top_pipe) + if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) continue; core_dc->hwss.pipe_control_lock( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index e8d4b8c3ac2b..ca4f1db4a58a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -38,7 +38,7 @@ void pre_surface_trace( const struct dc *dc, - const struct dc_plane_state *const *surfaces, + const struct dc_plane_state *const *plane_states, int surface_count) { int i; @@ -46,111 +46,111 @@ void pre_surface_trace( struct dal_logger *logger = core_dc->ctx->logger; for (i = 0; i < surface_count; i++) { - const struct dc_plane_state *surface = surfaces[i]; + const struct dc_plane_state *plane_state = plane_states[i]; - SURFACE_TRACE("Surface %d:\n", i); + SURFACE_TRACE("Planes %d:\n", i); SURFACE_TRACE( - "surface->visible = %d;\n" - "surface->flip_immediate = %d;\n" - "surface->address.type = %d;\n" - "surface->address.grph.addr.quad_part = 0x%X;\n" - "surface->address.grph.meta_addr.quad_part = 0x%X;\n" - "surface->scaling_quality.h_taps = %d;\n" - "surface->scaling_quality.v_taps = %d;\n" - "surface->scaling_quality.h_taps_c = %d;\n" - "surface->scaling_quality.v_taps_c = %d;\n", - surface->visible, - surface->flip_immediate, - surface->address.type, - surface->address.grph.addr.quad_part, - surface->address.grph.meta_addr.quad_part, - surface->scaling_quality.h_taps, - surface->scaling_quality.v_taps, - surface->scaling_quality.h_taps_c, - surface->scaling_quality.v_taps_c); + "plane_state->visible = %d;\n" + "plane_state->flip_immediate = %d;\n" + "plane_state->address.type = %d;\n" + "plane_state->address.grph.addr.quad_part = 0x%X;\n" + "plane_state->address.grph.meta_addr.quad_part = 0x%X;\n" + "plane_state->scaling_quality.h_taps = %d;\n" + "plane_state->scaling_quality.v_taps = %d;\n" + "plane_state->scaling_quality.h_taps_c = %d;\n" + "plane_state->scaling_quality.v_taps_c = %d;\n", + plane_state->visible, + plane_state->flip_immediate, + plane_state->address.type, + plane_state->address.grph.addr.quad_part, + plane_state->address.grph.meta_addr.quad_part, + plane_state->scaling_quality.h_taps, + plane_state->scaling_quality.v_taps, + plane_state->scaling_quality.h_taps_c, + plane_state->scaling_quality.v_taps_c); SURFACE_TRACE( - "surface->src_rect.x = %d;\n" - "surface->src_rect.y = %d;\n" - "surface->src_rect.width = %d;\n" - "surface->src_rect.height = %d;\n" - "surface->dst_rect.x = %d;\n" - "surface->dst_rect.y = %d;\n" - "surface->dst_rect.width = %d;\n" - "surface->dst_rect.height = %d;\n" - "surface->clip_rect.x = %d;\n" - "surface->clip_rect.y = %d;\n" - "surface->clip_rect.width = %d;\n" - "surface->clip_rect.height = %d;\n", - surface->src_rect.x, - surface->src_rect.y, - surface->src_rect.width, - surface->src_rect.height, - surface->dst_rect.x, - surface->dst_rect.y, - surface->dst_rect.width, - surface->dst_rect.height, - surface->clip_rect.x, - surface->clip_rect.y, - surface->clip_rect.width, - surface->clip_rect.height); + "plane_state->src_rect.x = %d;\n" + "plane_state->src_rect.y = %d;\n" + "plane_state->src_rect.width = %d;\n" + "plane_state->src_rect.height = %d;\n" + "plane_state->dst_rect.x = %d;\n" + "plane_state->dst_rect.y = %d;\n" + "plane_state->dst_rect.width = %d;\n" + "plane_state->dst_rect.height = %d;\n" + "plane_state->clip_rect.x = %d;\n" + "plane_state->clip_rect.y = %d;\n" + "plane_state->clip_rect.width = %d;\n" + "plane_state->clip_rect.height = %d;\n", + plane_state->src_rect.x, + plane_state->src_rect.y, + plane_state->src_rect.width, + plane_state->src_rect.height, + plane_state->dst_rect.x, + plane_state->dst_rect.y, + plane_state->dst_rect.width, + plane_state->dst_rect.height, + plane_state->clip_rect.x, + plane_state->clip_rect.y, + plane_state->clip_rect.width, + plane_state->clip_rect.height); SURFACE_TRACE( - "surface->plane_size.grph.surface_size.x = %d;\n" - "surface->plane_size.grph.surface_size.y = %d;\n" - "surface->plane_size.grph.surface_size.width = %d;\n" - "surface->plane_size.grph.surface_size.height = %d;\n" - "surface->plane_size.grph.surface_pitch = %d;\n", - surface->plane_size.grph.surface_size.x, - surface->plane_size.grph.surface_size.y, - surface->plane_size.grph.surface_size.width, - surface->plane_size.grph.surface_size.height, - surface->plane_size.grph.surface_pitch); + "plane_state->plane_size.grph.surface_size.x = %d;\n" + "plane_state->plane_size.grph.surface_size.y = %d;\n" + "plane_state->plane_size.grph.surface_size.width = %d;\n" + "plane_state->plane_size.grph.surface_size.height = %d;\n" + "plane_state->plane_size.grph.surface_pitch = %d;\n", + plane_state->plane_size.grph.surface_size.x, + plane_state->plane_size.grph.surface_size.y, + plane_state->plane_size.grph.surface_size.width, + plane_state->plane_size.grph.surface_size.height, + plane_state->plane_size.grph.surface_pitch); SURFACE_TRACE( - "surface->tiling_info.gfx8.num_banks = %d;\n" - "surface->tiling_info.gfx8.bank_width = %d;\n" - "surface->tiling_info.gfx8.bank_width_c = %d;\n" - "surface->tiling_info.gfx8.bank_height = %d;\n" - "surface->tiling_info.gfx8.bank_height_c = %d;\n" - "surface->tiling_info.gfx8.tile_aspect = %d;\n" - "surface->tiling_info.gfx8.tile_aspect_c = %d;\n" - "surface->tiling_info.gfx8.tile_split = %d;\n" - "surface->tiling_info.gfx8.tile_split_c = %d;\n" - "surface->tiling_info.gfx8.tile_mode = %d;\n" - "surface->tiling_info.gfx8.tile_mode_c = %d;\n", - surface->tiling_info.gfx8.num_banks, - surface->tiling_info.gfx8.bank_width, - surface->tiling_info.gfx8.bank_width_c, - surface->tiling_info.gfx8.bank_height, - surface->tiling_info.gfx8.bank_height_c, - surface->tiling_info.gfx8.tile_aspect, - surface->tiling_info.gfx8.tile_aspect_c, - surface->tiling_info.gfx8.tile_split, - surface->tiling_info.gfx8.tile_split_c, - surface->tiling_info.gfx8.tile_mode, - surface->tiling_info.gfx8.tile_mode_c); + "plane_state->tiling_info.gfx8.num_banks = %d;\n" + "plane_state->tiling_info.gfx8.bank_width = %d;\n" + "plane_state->tiling_info.gfx8.bank_width_c = %d;\n" + "plane_state->tiling_info.gfx8.bank_height = %d;\n" + "plane_state->tiling_info.gfx8.bank_height_c = %d;\n" + "plane_state->tiling_info.gfx8.tile_aspect = %d;\n" + "plane_state->tiling_info.gfx8.tile_aspect_c = %d;\n" + "plane_state->tiling_info.gfx8.tile_split = %d;\n" + "plane_state->tiling_info.gfx8.tile_split_c = %d;\n" + "plane_state->tiling_info.gfx8.tile_mode = %d;\n" + "plane_state->tiling_info.gfx8.tile_mode_c = %d;\n", + plane_state->tiling_info.gfx8.num_banks, + plane_state->tiling_info.gfx8.bank_width, + plane_state->tiling_info.gfx8.bank_width_c, + plane_state->tiling_info.gfx8.bank_height, + plane_state->tiling_info.gfx8.bank_height_c, + plane_state->tiling_info.gfx8.tile_aspect, + plane_state->tiling_info.gfx8.tile_aspect_c, + plane_state->tiling_info.gfx8.tile_split, + plane_state->tiling_info.gfx8.tile_split_c, + plane_state->tiling_info.gfx8.tile_mode, + plane_state->tiling_info.gfx8.tile_mode_c); SURFACE_TRACE( - "surface->tiling_info.gfx8.pipe_config = %d;\n" - "surface->tiling_info.gfx8.array_mode = %d;\n" - "surface->color_space = %d;\n" - "surface->dcc.enable = %d;\n" - "surface->format = %d;\n" - "surface->rotation = %d;\n" - "surface->stereo_format = %d;\n", - surface->tiling_info.gfx8.pipe_config, - surface->tiling_info.gfx8.array_mode, - surface->color_space, - surface->dcc.enable, - surface->format, - surface->rotation, - surface->stereo_format); - - SURFACE_TRACE("surface->tiling_info.gfx9.swizzle = %d;\n", - surface->tiling_info.gfx9.swizzle); + "plane_state->tiling_info.gfx8.pipe_config = %d;\n" + "plane_state->tiling_info.gfx8.array_mode = %d;\n" + "plane_state->color_space = %d;\n" + "plane_state->dcc.enable = %d;\n" + "plane_state->format = %d;\n" + "plane_state->rotation = %d;\n" + "plane_state->stereo_format = %d;\n", + plane_state->tiling_info.gfx8.pipe_config, + plane_state->tiling_info.gfx8.array_mode, + plane_state->color_space, + plane_state->dcc.enable, + plane_state->format, + plane_state->rotation, + plane_state->stereo_format); + + SURFACE_TRACE("plane_state->tiling_info.gfx9.swizzle = %d;\n", + plane_state->tiling_info.gfx9.swizzle); SURFACE_TRACE("\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ce0415f26600..4eef400cb551 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -430,17 +430,17 @@ static void rect_swap_helper(struct rect *rect) static void calculate_viewport(struct pipe_ctx *pipe_ctx) { - const struct dc_plane_state *surface = pipe_ctx->surface; + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->scl_data; - struct rect surf_src = surface->src_rect; + struct rect surf_src = plane_state->src_rect; struct rect clip = { 0 }; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; bool pri_split = pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->surface == pipe_ctx->surface; + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; bool sec_split = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->surface == pipe_ctx->surface; + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { @@ -448,41 +448,41 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) sec_split = false; } - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); /* The actual clip is an intersection between stream * source and surface clip */ - clip.x = stream->src.x > surface->clip_rect.x ? - stream->src.x : surface->clip_rect.x; + clip.x = stream->src.x > plane_state->clip_rect.x ? + stream->src.x : plane_state->clip_rect.x; clip.width = stream->src.x + stream->src.width < - surface->clip_rect.x + surface->clip_rect.width ? + plane_state->clip_rect.x + plane_state->clip_rect.width ? stream->src.x + stream->src.width - clip.x : - surface->clip_rect.x + surface->clip_rect.width - clip.x ; + plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; - clip.y = stream->src.y > surface->clip_rect.y ? - stream->src.y : surface->clip_rect.y; + clip.y = stream->src.y > plane_state->clip_rect.y ? + stream->src.y : plane_state->clip_rect.y; clip.height = stream->src.y + stream->src.height < - surface->clip_rect.y + surface->clip_rect.height ? + plane_state->clip_rect.y + plane_state->clip_rect.height ? stream->src.y + stream->src.height - clip.y : - surface->clip_rect.y + surface->clip_rect.height - clip.y ; + plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio * num_pixels = clip.num_pix * scl_ratio */ - data->viewport.x = surf_src.x + (clip.x - surface->dst_rect.x) * - surf_src.width / surface->dst_rect.width; + data->viewport.x = surf_src.x + (clip.x - plane_state->dst_rect.x) * + surf_src.width / plane_state->dst_rect.width; data->viewport.width = clip.width * - surf_src.width / surface->dst_rect.width; + surf_src.width / plane_state->dst_rect.width; - data->viewport.y = surf_src.y + (clip.y - surface->dst_rect.y) * - surf_src.height / surface->dst_rect.height; + data->viewport.y = surf_src.y + (clip.y - plane_state->dst_rect.y) * + surf_src.height / plane_state->dst_rect.height; data->viewport.height = clip.height * - surf_src.height / surface->dst_rect.height; + surf_src.height / plane_state->dst_rect.height; /* Round down, compensate in init */ data->viewport_c.x = data->viewport.x / vpc_div; @@ -498,13 +498,13 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) /* Handle hsplit */ if (pri_split || sec_split) { /* HMirror XOR Secondary_pipe XOR Rotation_180 */ - bool right_view = (sec_split != surface->horizontal_mirror) != - (surface->rotation == ROTATION_ANGLE_180); + bool right_view = (sec_split != plane_state->horizontal_mirror) != + (plane_state->rotation == ROTATION_ANGLE_180); - if (surface->rotation == ROTATION_ANGLE_90 - || surface->rotation == ROTATION_ANGLE_270) + if (plane_state->rotation == ROTATION_ANGLE_90 + || plane_state->rotation == ROTATION_ANGLE_270) /* Secondary_pipe XOR Rotation_270 */ - right_view = (surface->rotation == ROTATION_ANGLE_270) != sec_split; + right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; if (right_view) { data->viewport.width /= 2; @@ -520,8 +520,8 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) } } - if (surface->rotation == ROTATION_ANGLE_90 || - surface->rotation == ROTATION_ANGLE_270) { + if (plane_state->rotation == ROTATION_ANGLE_90 || + plane_state->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); } @@ -529,14 +529,14 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - const struct dc_plane_state *surface = pipe_ctx->surface; + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; - struct rect surf_src = surface->src_rect; - struct rect surf_clip = surface->clip_rect; + struct rect surf_src = plane_state->src_rect; + struct rect surf_clip = plane_state->clip_rect; int recout_full_x, recout_full_y; - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); pipe_ctx->scl_data.recout.x = stream->dst.x; @@ -568,8 +568,8 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip - pipe_ctx->scl_data.recout.y; /* Handle h & vsplit */ - if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == - pipe_ctx->surface) { + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == + pipe_ctx->plane_state) { if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { pipe_ctx->scl_data.recout.height /= 2; pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; @@ -581,7 +581,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; } } else if (pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) { if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) pipe_ctx->scl_data.recout.height /= 2; else @@ -592,13 +592,13 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl * ratio) */ - recout_full_x = stream->dst.x + (surface->dst_rect.x - stream->src.x) + recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) * stream->dst.width / stream->src.width - - surf_src.x * surface->dst_rect.width / surf_src.width + surf_src.x * plane_state->dst_rect.width / surf_src.width * stream->dst.width / stream->src.width; - recout_full_y = stream->dst.y + (surface->dst_rect.y - stream->src.y) + recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) * stream->dst.height / stream->src.height - - surf_src.y * surface->dst_rect.height / surf_src.height + surf_src.y * plane_state->dst_rect.height / surf_src.height * stream->dst.height / stream->src.height; recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; @@ -607,24 +607,24 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) { - const struct dc_plane_state *surface = pipe_ctx->surface; + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; - struct rect surf_src = surface->src_rect; + struct rect surf_src = plane_state->src_rect; const int in_w = stream->src.width; const int in_h = stream->src.height; const int out_w = stream->dst.width; const int out_h = stream->dst.height; - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( surf_src.width, - surface->dst_rect.width); + plane_state->dst_rect.width); pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( surf_src.height, - surface->dst_rect.height); + plane_state->dst_rect.height); if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) pipe_ctx->scl_data.ratios.horz.value *= 2; @@ -649,13 +649,13 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { struct scaler_data *data = &pipe_ctx->scl_data; - struct rect src = pipe_ctx->surface->src_rect; + struct rect src = pipe_ctx->plane_state->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) { + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&src); rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); @@ -805,8 +805,8 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); - if (pipe_ctx->surface->rotation == ROTATION_ANGLE_90 || - pipe_ctx->surface->rotation == ROTATION_ANGLE_270) { + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { rect_swap_helper(&data->viewport_c); rect_swap_helper(&data->viewport); } @@ -814,7 +814,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { - const struct dc_plane_state *surface = pipe_ctx->surface; + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct view recout_skip = { 0 }; bool res = false; @@ -824,7 +824,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) * Inits require viewport, taps, ratios and recout of split pipe */ pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( - pipe_ctx->surface->format); + pipe_ctx->plane_state->format); calculate_scaling_ratios(pipe_ctx); @@ -846,14 +846,14 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) /* Taps calculations */ res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + pipe_ctx->xfm, &pipe_ctx->scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + pipe_ctx->xfm, &pipe_ctx->scl_data, &plane_state->scaling_quality); } if (res) @@ -869,10 +869,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->scl_data.viewport.width, pipe_ctx->scl_data.viewport.x, pipe_ctx->scl_data.viewport.y, - surface->dst_rect.height, - surface->dst_rect.width, - surface->dst_rect.x, - surface->dst_rect.y); + plane_state->dst_rect.height, + plane_state->dst_rect.width, + plane_state->dst_rect.x, + plane_state->dst_rect.y); return res; } @@ -885,7 +885,7 @@ enum dc_status resource_build_scaling_params_for_context( int i; for (i = 0; i < MAX_PIPES; i++) { - if (context->res_ctx.pipe_ctx[i].surface != NULL && + if (context->res_ctx.pipe_ctx[i].plane_state != NULL && context->res_ctx.pipe_ctx[i].stream != NULL) if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) return DC_FAIL_SCALING; @@ -954,13 +954,13 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( if (!head_pipe) ASSERT(0); - if (!head_pipe->surface) + if (!head_pipe->plane_state) return head_pipe; /* Re-use pipe already acquired for this stream if available*/ for (i = pool->pipe_count - 1; i >= 0; i--) { if (res_ctx->pipe_ctx[i].stream == stream && - !res_ctx->pipe_ctx[i].surface) { + !res_ctx->pipe_ctx[i].plane_state) { return &res_ctx->pipe_ctx[i]; } } @@ -987,7 +987,7 @@ static void release_free_pipes_for_stream( /* never release the topmost pipe*/ if (res_ctx->pipe_ctx[i].stream == stream && res_ctx->pipe_ctx[i].top_pipe && - !res_ctx->pipe_ctx[i].surface) { + !res_ctx->pipe_ctx[i].plane_state) { memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx)); } } @@ -1005,7 +1005,7 @@ static int acquire_first_split_pipe( struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; if (pipe_ctx->top_pipe && - pipe_ctx->top_pipe->surface == pipe_ctx->surface) { + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) { pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; if (pipe_ctx->bottom_pipe) pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; @@ -1028,7 +1028,7 @@ static int acquire_first_split_pipe( #endif bool resource_attach_surfaces_to_context( - struct dc_plane_state * const *surfaces, + struct dc_plane_state * const *plane_states, int surface_count, struct dc_stream_state *stream, struct validate_context *context, @@ -1057,25 +1057,25 @@ bool resource_attach_surfaces_to_context( /* retain new surfaces */ for (i = 0; i < surface_count; i++) - dc_surface_retain(surfaces[i]); + dc_plane_state_retain(plane_states[i]); /* detach surfaces from pipes */ for (i = 0; i < pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == stream) { - context->res_ctx.pipe_ctx[i].surface = NULL; + context->res_ctx.pipe_ctx[i].plane_state = NULL; context->res_ctx.pipe_ctx[i].bottom_pipe = NULL; } /* release existing surfaces*/ - for (i = 0; i < stream_status->surface_count; i++) - dc_surface_release(stream_status->surfaces[i]); + for (i = 0; i < stream_status->plane_count; i++) + dc_plane_state_release(stream_status->plane_states[i]); - for (i = surface_count; i < stream_status->surface_count; i++) - stream_status->surfaces[i] = NULL; + for (i = surface_count; i < stream_status->plane_count; i++) + stream_status->plane_states[i] = NULL; tail_pipe = NULL; for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = surfaces[i]; + struct dc_plane_state *plane_state = plane_states[i]; struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( context, pool, stream); @@ -1087,11 +1087,11 @@ bool resource_attach_surfaces_to_context( } #endif if (!free_pipe) { - stream_status->surfaces[i] = NULL; + stream_status->plane_states[i] = NULL; return false; } - free_pipe->surface = surface; + free_pipe->plane_state = plane_state; if (tail_pipe) { free_pipe->tg = tail_pipe->tg; @@ -1110,9 +1110,9 @@ bool resource_attach_surfaces_to_context( /* assign new surfaces*/ for (i = 0; i < surface_count; i++) - stream_status->surfaces[i] = surfaces[i]; + stream_status->plane_states[i] = plane_states[i]; - stream_status->surface_count = surface_count; + stream_status->plane_count = surface_count; return true; } @@ -1180,17 +1180,17 @@ bool resource_validate_attach_surfaces( old_context->streams[j], context->streams[i])) { if (!resource_attach_surfaces_to_context( - old_context->stream_status[j].surfaces, - old_context->stream_status[j].surface_count, + old_context->stream_status[j].plane_states, + old_context->stream_status[j].plane_count, context->streams[i], context, pool)) return false; context->stream_status[i] = old_context->stream_status[j]; } - if (set[i].surface_count != 0) + if (set[i].plane_count != 0) if (!resource_attach_surfaces_to_context( - set[i].surfaces, - set[i].surface_count, + set[i].plane_states, + set[i].plane_count, context->streams[i], context, pool)) return false; @@ -1351,13 +1351,13 @@ bool resource_is_stream_unchanged( static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { - struct dc_plane_state *surface = to_pipe_ctx->surface; + struct dc_plane_state *plane_state = to_pipe_ctx->plane_state; struct dc_stream_state *stream = to_pipe_ctx->stream; *to_pipe_ctx = *from_pipe_ctx; to_pipe_ctx->stream = stream; - if (surface != NULL) - to_pipe_ctx->surface = surface; + if (plane_state != NULL) + to_pipe_ctx->plane_state = plane_state; } static struct dc_stream_state *find_pll_sharable_stream( @@ -2055,7 +2055,7 @@ static void set_spd_info_packet( static void set_hdr_static_info_packet( struct encoder_info_packet *info_packet, - struct dc_plane_state *surface, + struct dc_plane_state *plane_state, struct dc_stream_state *stream) { uint16_t i = 0; @@ -2063,10 +2063,10 @@ static void set_hdr_static_info_packet( struct dc_hdr_static_metadata hdr_metadata; uint32_t data; - if (!surface) + if (!plane_state) return; - hdr_metadata = surface->hdr_static_ctx; + hdr_metadata = plane_state->hdr_static_ctx; if (!hdr_metadata.hdr_supported) return; @@ -2204,11 +2204,11 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context) int i, j; for (i = 0; i < context->stream_count; i++) { - for (j = 0; j < context->stream_status[i].surface_count; j++) - dc_surface_release( - context->stream_status[i].surfaces[j]); + for (j = 0; j < context->stream_status[i].plane_count; j++) + dc_plane_state_release( + context->stream_status[i].plane_states[j]); - context->stream_status[i].surface_count = 0; + context->stream_status[i].plane_count = 0; dc_stream_release(context->streams[i]); context->streams[i] = NULL; } @@ -2240,9 +2240,9 @@ void dc_resource_validate_ctx_copy_construct( for (i = 0; i < dst_ctx->stream_count; i++) { dc_stream_retain(dst_ctx->streams[i]); - for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++) - dc_surface_retain( - dst_ctx->stream_status[i].surfaces[j]); + for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) + dc_plane_state_retain( + dst_ctx->stream_status[i].plane_states[j]); } /* context refcount should not be overridden */ @@ -2288,7 +2288,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_spd_info_packet(&info->spd, pipe_ctx->stream); set_hdr_static_info_packet(&info->hdrsmd, - pipe_ctx->surface, pipe_ctx->stream); + pipe_ctx->plane_state, pipe_ctx->stream); } else if (dc_is_dp_signal(signal)) { set_vsc_info_packet(&info->vsc, pipe_ctx->stream); @@ -2296,7 +2296,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) set_spd_info_packet(&info->spd, pipe_ctx->stream); set_hdr_static_info_packet(&info->hdrsmd, - pipe_ctx->surface, pipe_ctx->stream); + pipe_ctx->plane_state, pipe_ctx->stream); } patch_gamut_packet_checksum(&info->gamut); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 7a87f38f2324..2b6506822cca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -185,7 +185,7 @@ bool dc_stream_set_cursor_attributes( if (pipe_ctx->stream != stream || !pipe_ctx->ipp) continue; - if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; pipe_ctx->ipp->funcs->ipp_cursor_set_attributes( @@ -229,14 +229,14 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->ipp || !pipe_ctx->surface) + !pipe_ctx->ipp || !pipe_ctx->plane_state) continue; - if (pipe_ctx->surface->address.type + if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) pos_cpy.enable = false; - if (pipe_ctx->top_pipe && pipe_ctx->surface != pipe_ctx->top_pipe->surface) + if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) pos_cpy.enable = false; ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 941b3671375d..3bcca2d1872b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -34,75 +34,75 @@ /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct dc_plane_state *surface) +static bool construct(struct dc_context *ctx, struct dc_plane_state *plane_state) { - surface->ctx = ctx; - memset(&surface->hdr_static_ctx, + plane_state->ctx = ctx; + memset(&plane_state->hdr_static_ctx, 0, sizeof(struct dc_hdr_static_metadata)); return true; } -static void destruct(struct dc_plane_state *surface) +static void destruct(struct dc_plane_state *plane_state) { - if (surface->gamma_correction != NULL) { - dc_gamma_release(&surface->gamma_correction); + if (plane_state->gamma_correction != NULL) { + dc_gamma_release(&plane_state->gamma_correction); } - if (surface->in_transfer_func != NULL) { + if (plane_state->in_transfer_func != NULL) { dc_transfer_func_release( - surface->in_transfer_func); - surface->in_transfer_func = NULL; + plane_state->in_transfer_func); + plane_state->in_transfer_func = NULL; } } /******************************************************************************* * Public functions ******************************************************************************/ -void enable_surface_flip_reporting(struct dc_plane_state *surface, +void enable_surface_flip_reporting(struct dc_plane_state *plane_state, uint32_t controller_id) { - surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; + plane_state->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1; /*register_flip_interrupt(surface);*/ } -struct dc_plane_state *dc_create_surface(const struct dc *dc) +struct dc_plane_state *dc_create_plane_state(const struct dc *dc) { struct core_dc *core_dc = DC_TO_CORE(dc); - struct dc_plane_state *surface = dm_alloc(sizeof(*surface)); + struct dc_plane_state *plane_state = dm_alloc(sizeof(*plane_state)); - if (NULL == surface) + if (NULL == plane_state) goto alloc_fail; - if (false == construct(core_dc->ctx, surface)) + if (false == construct(core_dc->ctx, plane_state)) goto construct_fail; - ++surface->ref_count; + ++plane_state->ref_count; - return surface; + return plane_state; construct_fail: - dm_free(surface); + dm_free(plane_state); alloc_fail: return NULL; } -const struct dc_surface_status *dc_surface_get_status( - const struct dc_plane_state *dc_surface) +const struct dc_plane_status *dc_plane_get_status( + const struct dc_plane_state *plane_state) { - const struct dc_surface_status *surface_status; + const struct dc_plane_status *plane_status; struct core_dc *core_dc; int i; - if (!dc_surface || - !dc_surface->ctx || - !dc_surface->ctx->dc) { + if (!plane_state || + !plane_state->ctx || + !plane_state->ctx->dc) { ASSERT(0); return NULL; /* remove this if above assert never hit */ } - surface_status = &dc_surface->status; - core_dc = DC_TO_CORE(dc_surface->ctx->dc); + plane_status = &plane_state->status; + core_dc = DC_TO_CORE(plane_state->ctx->dc); if (core_dc->current_context == NULL) return NULL; @@ -111,29 +111,29 @@ const struct dc_surface_status *dc_surface_get_status( struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != dc_surface) + if (pipe_ctx->plane_state != plane_state) continue; core_dc->hwss.update_pending_status(pipe_ctx); } - return surface_status; + return plane_status; } -void dc_surface_retain(struct dc_plane_state *surface) +void dc_plane_state_retain(struct dc_plane_state *plane_state) { - ASSERT(surface->ref_count > 0); - ++surface->ref_count; + ASSERT(plane_state->ref_count > 0); + ++plane_state->ref_count; } -void dc_surface_release(struct dc_plane_state *surface) +void dc_plane_state_release(struct dc_plane_state *plane_state) { - ASSERT(surface->ref_count > 0); - --surface->ref_count; + ASSERT(plane_state->ref_count > 0); + --plane_state->ref_count; - if (surface->ref_count == 0) { - destruct(surface); - dm_free(surface); + if (plane_state->ref_count == 0) { + destruct(plane_state); + dm_free(plane_state); } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ab805965e321..d1a6398043a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct dc_caps { uint32_t max_links; uint32_t max_audios; uint32_t max_slave_planes; - uint32_t max_surfaces; + uint32_t max_planes; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; @@ -303,7 +303,7 @@ struct dc_transfer_func { * the last requested address and the currently active address so the called * can determine if there are any outstanding flips */ -struct dc_surface_status { +struct dc_plane_status { struct dc_plane_address requested_address; struct dc_plane_address current_address; bool is_flip_pending; @@ -338,7 +338,7 @@ struct dc_plane_state { bool horizontal_mirror; /* private to DC core */ - struct dc_surface_status status; + struct dc_plane_status status; struct dc_context *ctx; /* private to dc_surface.c */ @@ -385,12 +385,12 @@ struct dc_surface_update { /* * Create a new surface with default parameters; */ -struct dc_plane_state *dc_create_surface(const struct dc *dc); -const struct dc_surface_status *dc_surface_get_status( - const struct dc_plane_state *dc_surface); +struct dc_plane_state *dc_create_plane_state(const struct dc *dc); +const struct dc_plane_status *dc_plane_get_status( + const struct dc_plane_state *plane_state); -void dc_surface_retain(struct dc_plane_state *dc_surface); -void dc_surface_release(struct dc_plane_state *dc_surface); +void dc_plane_state_retain(struct dc_plane_state *plane_state); +void dc_plane_state_release(struct dc_plane_state *plane_state); void dc_gamma_retain(struct dc_gamma *dc_gamma); void dc_gamma_release(struct dc_gamma **dc_gamma); @@ -422,10 +422,10 @@ struct dc_flip_addrs { * This does not trigger a flip. No surface address is programmed. */ -bool dc_commit_surfaces_to_stream( +bool dc_commit_planes_to_stream( struct dc *dc, - struct dc_plane_state **dc_surfaces, - uint8_t surface_count, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, struct dc_stream_state *stream); bool dc_post_update_surfaces_to_stream( @@ -469,8 +469,8 @@ enum surface_update_type { struct dc_stream_status { int primary_otg_inst; - int surface_count; - struct dc_plane_state *surfaces[MAX_SURFACE_NUM]; + int plane_count; + struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; /* * link this stream passes through @@ -546,7 +546,7 @@ bool dc_is_stream_unchanged( * */ -void dc_update_surfaces_and_stream(struct dc *dc, +void dc_update_planes_and_stream(struct dc *dc, struct dc_surface_update *surface_updates, int surface_count, struct dc_stream_state *dc_stream, struct dc_stream_update *stream_update); @@ -582,8 +582,8 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, */ struct dc_validation_set { struct dc_stream_state *stream; - struct dc_plane_state *surfaces[MAX_SURFACES]; - uint8_t surface_count; + struct dc_plane_state *plane_states[MAX_SURFACES]; + uint8_t plane_count; }; bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index af59ab93796a..8140ff31c3bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -197,9 +197,9 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, } /* Only use LUT for 8 bit formats */ -bool dce_use_lut(const struct dc_plane_state *surface) +bool dce_use_lut(const struct dc_plane_state *plane_state) { - switch (surface->format) { + switch (plane_state->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index d5cb98a92c53..a0531b3aa6a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -552,5 +552,5 @@ void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws, struct clock_source *clk_src, unsigned int tg_inst); -bool dce_use_lut(const struct dc_plane_state *surface); +bool dce_use_lut(const struct dc_plane_state *plane_state); #endif /*__DCE_HWSEQ_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 98fb7f02a6fe..46f0c71fbac4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -705,13 +705,13 @@ static bool dce100_validate_surface_sets( int i; for (i = 0; i < set_count; i++) { - if (set[i].surface_count == 0) + if (set[i].plane_count == 0) continue; - if (set[i].surface_count > 1) + if (set[i].plane_count > 1) return false; - if (set[i].surfaces[0]->format + if (set[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -958,7 +958,7 @@ static bool construct( } } - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e4310a376116..ea9ce87d348a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -215,11 +215,11 @@ static bool dce110_enable_display_power_gating( } static void build_prescale_params(struct ipp_prescale_params *prescale_params, - const struct dc_plane_state *surface) + const struct dc_plane_state *plane_state) { prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; - switch (surface->format) { + switch (plane_state->format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: prescale_params->scale = 0x2020; @@ -240,7 +240,7 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params, static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *surface) + const struct dc_plane_state *plane_state) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -250,14 +250,14 @@ static bool dce110_set_input_transfer_func( if (ipp == NULL) return false; - if (surface->in_transfer_func) - tf = surface->in_transfer_func; + if (plane_state->in_transfer_func) + tf = plane_state->in_transfer_func; - build_prescale_params(&prescale_params, surface); + build_prescale_params(&prescale_params, plane_state); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (surface->gamma_correction && dce_use_lut(surface)) - ipp->funcs->ipp_program_input_lut(ipp, surface->gamma_correction); + if (plane_state->gamma_correction && dce_use_lut(plane_state)) + ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction); if (tf == NULL) { /* Default case if no input transfer function specified */ @@ -1119,7 +1119,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( if ((!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data, &pipe_ctx->scl_data, sizeof(struct scaler_data)) != 0) && - pipe_ctx->surface) { + pipe_ctx->plane_state) { program_scaler(dc, pipe_ctx); } @@ -1916,11 +1916,11 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) struct default_adjustment default_adjust = { 0 }; default_adjust.force_hw_default = false; - if (pipe_ctx->surface == NULL) + if (pipe_ctx->plane_state == NULL) default_adjust.in_color_space = COLOR_SPACE_SRGB; else default_adjust.in_color_space = - pipe_ctx->surface->color_space; + pipe_ctx->plane_state->color_space; if (pipe_ctx->stream == NULL) default_adjust.out_color_space = COLOR_SPACE_SRGB; else @@ -1971,16 +1971,16 @@ static void program_surface_visibility(const struct core_dc *dc, /* For now we are supporting only two pipes */ ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL); - if (pipe_ctx->bottom_pipe->surface->visible) { - if (pipe_ctx->surface->visible) + if (pipe_ctx->bottom_pipe->plane_state->visible) { + if (pipe_ctx->plane_state->visible) blender_mode = BLND_MODE_BLENDING; else blender_mode = BLND_MODE_OTHER_PIPE; - } else if (!pipe_ctx->surface->visible) + } else if (!pipe_ctx->plane_state->visible) blank_target = true; - } else if (!pipe_ctx->surface->visible) + } else if (!pipe_ctx->plane_state->visible) blank_target = true; dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); @@ -2038,7 +2038,7 @@ static void set_plane_config( struct resource_context *res_ctx) { struct mem_input *mi = pipe_ctx->mi; - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2103,57 +2103,57 @@ static void set_plane_config( mi->funcs->mem_input_program_surface_config( mi, - surface->format, - &surface->tiling_info, - &surface->plane_size, - surface->rotation, + plane_state->format, + &plane_state->tiling_info, + &plane_state->plane_size, + plane_state->rotation, NULL, false); if (mi->funcs->set_blank) - mi->funcs->set_blank(mi, pipe_ctx->surface->visible); + mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->format, - &surface->tiling_info, - surface->rotation); + plane_state->format, + &plane_state->tiling_info, + plane_state->rotation); } static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; - if (surface == NULL) + if (plane_state == NULL) return; pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( pipe_ctx->mi, - &surface->address, - surface->flip_immediate); + &plane_state->address, + plane_state->flip_immediate); - surface->status.requested_address = surface->address; + plane_state->status.requested_address = plane_state->address; } void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; - if (surface == NULL) + if (plane_state == NULL) return; - surface->status.is_flip_pending = + plane_state->status.is_flip_pending = pipe_ctx->mi->funcs->mem_input_is_flip_pending( pipe_ctx->mi); - if (surface->status.is_flip_pending && !surface->visible) + if (plane_state->status.is_flip_pending && !plane_state->visible) pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; - surface->status.current_address = pipe_ctx->mi->current_address; + plane_state->status.current_address = pipe_ctx->mi->current_address; if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && pipe_ctx->tg->funcs->is_stereo_left_eye) { - surface->status.is_right_eye =\ + plane_state->status.is_right_eye =\ !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg); } } @@ -2490,7 +2490,7 @@ static void dce110_program_front_end_for_pipe( { struct mem_input *mi = pipe_ctx->mi; struct pipe_ctx *old_pipe = NULL; - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; unsigned int i; @@ -2558,21 +2558,21 @@ static void dce110_program_front_end_for_pipe( mi->funcs->mem_input_program_surface_config( mi, - surface->format, - &surface->tiling_info, - &surface->plane_size, - surface->rotation, + plane_state->format, + &plane_state->tiling_info, + &plane_state->plane_size, + plane_state->rotation, NULL, false); if (mi->funcs->set_blank) - mi->funcs->set_blank(mi, pipe_ctx->surface->visible); + mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->format, - &surface->tiling_info, - surface->rotation); + plane_state->format, + &plane_state->tiling_info, + plane_state->rotation); dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe:%d 0x%x: addr hi:0x%x, " @@ -2581,21 +2581,21 @@ static void dce110_program_front_end_for_pipe( " %d; dst: %d, %d, %d, %d;" "clip: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, - pipe_ctx->surface, - pipe_ctx->surface->address.grph.addr.high_part, - pipe_ctx->surface->address.grph.addr.low_part, - pipe_ctx->surface->src_rect.x, - pipe_ctx->surface->src_rect.y, - pipe_ctx->surface->src_rect.width, - pipe_ctx->surface->src_rect.height, - pipe_ctx->surface->dst_rect.x, - pipe_ctx->surface->dst_rect.y, - pipe_ctx->surface->dst_rect.width, - pipe_ctx->surface->dst_rect.height, - pipe_ctx->surface->clip_rect.x, - pipe_ctx->surface->clip_rect.y, - pipe_ctx->surface->clip_rect.width, - pipe_ctx->surface->clip_rect.height); + pipe_ctx->plane_state, + pipe_ctx->plane_state->address.grph.addr.high_part, + pipe_ctx->plane_state->address.grph.addr.low_part, + pipe_ctx->plane_state->src_rect.x, + pipe_ctx->plane_state->src_rect.y, + pipe_ctx->plane_state->src_rect.width, + pipe_ctx->plane_state->src_rect.height, + pipe_ctx->plane_state->dst_rect.x, + pipe_ctx->plane_state->dst_rect.y, + pipe_ctx->plane_state->dst_rect.width, + pipe_ctx->plane_state->dst_rect.height, + pipe_ctx->plane_state->clip_rect.x, + pipe_ctx->plane_state->clip_rect.y, + pipe_ctx->plane_state->clip_rect.width, + pipe_ctx->plane_state->clip_rect.height); dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe %d: width, height, x, y\n" @@ -2614,19 +2614,18 @@ static void dce110_program_front_end_for_pipe( static void dce110_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_plane_state *surface, + const struct dc_plane_state *plane_state, struct validate_context *context) { int i; - /* TODO remove when removing the surface reset workaroud*/ - if (!surface) + if (!plane_state) return; for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->plane_state != plane_state) continue; dce110_program_front_end_for_pipe(dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 89b21bd57a35..f580da1b3249 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -764,9 +764,9 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne { if (pipe_ctx->pipe_idx != underlay_idx) return true; - if (!pipe_ctx->surface) + if (!pipe_ctx->plane_state) return false; - if (pipe_ctx->surface->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + if (pipe_ctx->plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; return true; } @@ -901,22 +901,22 @@ static bool dce110_validate_surface_sets( int i; for (i = 0; i < set_count; i++) { - if (set[i].surface_count == 0) + if (set[i].plane_count == 0) continue; - if (set[i].surface_count > 2) + if (set[i].plane_count > 2) return false; - if (set[i].surfaces[0]->format + if (set[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; - if (set[i].surface_count == 2) { - if (set[i].surfaces[1]->format + if (set[i].plane_count == 2) { + if (set[i].plane_states[1]->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; - if (set[i].surfaces[1]->src_rect.width > 1920 - || set[i].surfaces[1]->src_rect.height > 1080) + if (set[i].plane_states[1]->src_rect.width > 1920 + || set[i].plane_states[1]->src_rect.height > 1080) return false; if (set[i].stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) @@ -1351,7 +1351,7 @@ static bool construct( if (!dce110_hw_sequencer_construct(dc)) goto res_create_fail; - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 68554d6edd94..420434d7283e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -889,13 +889,13 @@ static bool dce112_validate_surface_sets( int i; for (i = 0; i < set_count; i++) { - if (set[i].surface_count == 0) + if (set[i].plane_count == 0) continue; - if (set[i].surface_count > 1) + if (set[i].plane_count > 1) return false; - if (set[i].surfaces[0]->format + if (set[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -1319,7 +1319,7 @@ static bool construct( &res_create_funcs)) goto res_create_fail; - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; /* Create hardware sequencer */ if (!dce112_hw_sequencer_construct(dc)) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 45f5fd63ce14..6448d15c02f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -982,7 +982,7 @@ static bool construct( if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 734b35eddeed..7473f58584c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -722,13 +722,13 @@ static bool dce80_validate_surface_sets( int i; for (i = 0; i < set_count; i++) { - if (set[i].surface_count == 0) + if (set[i].plane_count == 0) continue; - if (set[i].surface_count > 1) + if (set[i].plane_count > 1) return false; - if (set[i].surfaces[0]->format + if (set[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -959,7 +959,7 @@ static bool construct( } } - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 866f63d1259d..5922cf8272f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -986,7 +986,7 @@ static void reset_hw_ctx_wrap( struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (!pipe_ctx->stream || - !pipe_ctx->surface || + !pipe_ctx->plane_state || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { plane_atomic_disconnect(dc, i); @@ -1010,13 +1010,13 @@ static void reset_hw_ctx_wrap( /*if (!pipe_ctx_old->stream) continue;*/ - if (pipe_ctx->stream && pipe_ctx->surface + if (pipe_ctx->stream && pipe_ctx->plane_state && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) continue; plane_atomic_disable(dc, i); - if (!pipe_ctx->stream || !pipe_ctx->surface) + if (!pipe_ctx->stream || !pipe_ctx->plane_state) plane_atomic_power_down(dc, i); } @@ -1038,24 +1038,24 @@ static void reset_hw_ctx_wrap( static bool patch_address_for_sbs_tb_stereo( struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) { - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; bool sec_split = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->surface == pipe_ctx->surface; - if (sec_split && surface->address.type == PLN_ADDR_TYPE_GRPH_STEREO && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; + if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO && (pipe_ctx->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || pipe_ctx->stream->timing.timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { - *addr = surface->address.grph_stereo.left_addr; - surface->address.grph_stereo.left_addr = - surface->address.grph_stereo.right_addr; + *addr = plane_state->address.grph_stereo.left_addr; + plane_state->address.grph_stereo.left_addr = + plane_state->address.grph_stereo.right_addr; return true; } else { if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE && - surface->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { - surface->address.type = PLN_ADDR_TYPE_GRPH_STEREO; - surface->address.grph_stereo.right_addr = - surface->address.grph_stereo.left_addr; + plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { + plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO; + plane_state->address.grph_stereo.right_addr = + plane_state->address.grph_stereo.left_addr; } } return false; @@ -1065,22 +1065,22 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; - if (surface == NULL) + if (plane_state == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( pipe_ctx->mi, - &surface->address, - surface->flip_immediate); - surface->status.requested_address = surface->address; + &plane_state->address, + plane_state->flip_immediate); + plane_state->status.requested_address = plane_state->address; if (addr_patched) - pipe_ctx->surface->address.grph_stereo.left_addr = addr; + pipe_ctx->plane_state->address.grph_stereo.left_addr = addr; } static bool dcn10_set_input_transfer_func( - struct pipe_ctx *pipe_ctx, const struct dc_plane_state *surface) + struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { struct input_pixel_processor *ipp = pipe_ctx->ipp; const struct dc_transfer_func *tf = NULL; @@ -1089,12 +1089,12 @@ static bool dcn10_set_input_transfer_func( if (ipp == NULL) return false; - if (surface->in_transfer_func) - tf = surface->in_transfer_func; + if (plane_state->in_transfer_func) + tf = plane_state->in_transfer_func; - if (surface->gamma_correction && dce_use_lut(surface)) + if (plane_state->gamma_correction && dce_use_lut(plane_state)) ipp->funcs->ipp_program_input_lut(ipp, - surface->gamma_correction); + plane_state->gamma_correction); if (tf == NULL) ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); @@ -1689,7 +1689,7 @@ static void dcn10_power_on_fe( struct pipe_ctx *pipe_ctx, struct validate_context *context) { - struct dc_plane_state *dc_surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; power_on_plane(dc->hwseq, @@ -1704,24 +1704,24 @@ static void dcn10_power_on_fe( OPP_PIPE_CLOCK_EN, 1); /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ - if (dc_surface) { + if (plane_state) { dm_logger_write(dc->ctx->logger, LOG_DC, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " "src: %d, %d, %d," " %d; dst: %d, %d, %d, %d;\n", pipe_ctx->pipe_idx, - dc_surface, - dc_surface->address.grph.addr.high_part, - dc_surface->address.grph.addr.low_part, - dc_surface->src_rect.x, - dc_surface->src_rect.y, - dc_surface->src_rect.width, - dc_surface->src_rect.height, - dc_surface->dst_rect.x, - dc_surface->dst_rect.y, - dc_surface->dst_rect.width, - dc_surface->dst_rect.height); + plane_state, + plane_state->address.grph.addr.high_part, + plane_state->address.grph.addr.low_part, + plane_state->src_rect.x, + plane_state->src_rect.y, + plane_state->src_rect.width, + plane_state->src_rect.height, + plane_state->dst_rect.x, + plane_state->dst_rect.y, + plane_state->dst_rect.width, + plane_state->dst_rect.height); dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, "Pipe %d: width, height, x, y\n" @@ -1805,7 +1805,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->visible) + if (pipe_ctx->plane_state->visible) return true; if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) return true; @@ -1814,7 +1814,7 @@ static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->visible) + if (pipe_ctx->plane_state->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1823,7 +1823,7 @@ static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) { - if (pipe_ctx->surface->visible) + if (pipe_ctx->plane_state->visible) return true; if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) return true; @@ -1898,12 +1898,12 @@ static void update_dchubp_dpp( struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->mi; struct input_pixel_processor *ipp = pipe_ctx->ipp; - struct dc_plane_state *surface = pipe_ctx->surface; - union plane_size size = surface->plane_size; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + union plane_size size = plane_state->plane_size; struct default_adjustment ocsc = {0}; struct mpcc_cfg mpcc_cfg = {0}; struct pipe_ctx *top_pipe; - bool per_pixel_alpha = surface->per_pixel_alpha && pipe_ctx->bottom_pipe; + bool per_pixel_alpha = plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; /* TODO: proper fix once fpga works */ /* depends on DML calculation, DPP clock value may change dynamically */ @@ -1936,12 +1936,12 @@ static void update_dchubp_dpp( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->mi, - surface->format, - &surface->tiling_info, - surface->rotation); + plane_state->format, + &plane_state->tiling_info, + plane_state->rotation); ipp->funcs->ipp_setup(ipp, - surface->format, + plane_state->format, 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); @@ -1982,12 +1982,12 @@ static void update_dchubp_dpp( mi->funcs->mem_input_program_surface_config( mi, - surface->format, - &surface->tiling_info, + plane_state->format, + &plane_state->tiling_info, &size, - surface->rotation, - &surface->dcc, - surface->horizontal_mirror); + plane_state->rotation, + &plane_state->dcc, + plane_state->horizontal_mirror); mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); } @@ -2025,7 +2025,7 @@ static void program_all_pipe_in_tree( pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); } - if (pipe_ctx->surface != NULL) { + if (pipe_ctx->plane_state != NULL) { dcn10_power_on_fe(dc, pipe_ctx, context); update_dchubp_dpp(dc, pipe_ctx, context); } @@ -2068,7 +2068,7 @@ static void dcn10_pplib_apply_display_requirements( static void dcn10_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_plane_state *surface, + const struct dc_plane_state *plane_state, struct validate_context *context) { int i, be_idx; @@ -2076,11 +2076,11 @@ static void dcn10_apply_ctx_for_surface( if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - if (!surface) + if (!plane_state) return; for (be_idx = 0; be_idx < dc->res_pool->pipe_count; be_idx++) - if (surface == context->res_ctx.pipe_ctx[be_idx].surface) + if (plane_state == context->res_ctx.pipe_ctx[be_idx].plane_state) break; /* reset unused mpcc */ @@ -2089,7 +2089,7 @@ static void dcn10_apply_ctx_for_surface( struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->surface && !old_pipe_ctx->surface) + if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) continue; /* @@ -2097,7 +2097,7 @@ static void dcn10_apply_ctx_for_surface( * fairly hacky right now, using opp_id as indicator */ - if (pipe_ctx->surface && !old_pipe_ctx->surface) { + if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { if (pipe_ctx->mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* @@ -2109,7 +2109,7 @@ static void dcn10_apply_ctx_for_surface( } - if ((!pipe_ctx->surface && old_pipe_ctx->surface) + if ((!pipe_ctx->plane_state && old_pipe_ctx->plane_state) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { if (old_pipe_ctx->tg->inst != be_idx) continue; @@ -2135,7 +2135,7 @@ static void dcn10_apply_ctx_for_surface( old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; - old_pipe_ctx->surface = NULL; + old_pipe_ctx->plane_state = NULL; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset mpcc for pipe %d\n", @@ -2146,7 +2146,7 @@ static void dcn10_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->surface != surface) + if (pipe_ctx->plane_state != plane_state) continue; /* looking for top pipe to program */ @@ -2468,34 +2468,34 @@ static bool dcn10_dummy_display_power_gating( void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) { - struct dc_plane_state *surface = pipe_ctx->surface; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct timing_generator *tg = pipe_ctx->tg; - if (surface->ctx->dc->debug.sanity_checks) { - struct core_dc *dc = DC_TO_CORE(surface->ctx->dc); + if (plane_state->ctx->dc->debug.sanity_checks) { + struct core_dc *dc = DC_TO_CORE(plane_state->ctx->dc); verify_allow_pstate_change_high(dc->hwseq); } - if (surface == NULL) + if (plane_state == NULL) return; - surface->status.is_flip_pending = + plane_state->status.is_flip_pending = pipe_ctx->mi->funcs->mem_input_is_flip_pending( pipe_ctx->mi); /* DCN we read INUSE address in MI, do we still need this wa? */ - if (surface->status.is_flip_pending && - !surface->visible) { + if (plane_state->status.is_flip_pending && + !plane_state->visible) { pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; BREAK_TO_DEBUGGER(); } - surface->status.current_address = pipe_ctx->mi->current_address; + plane_state->status.current_address = pipe_ctx->mi->current_address; if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { - surface->status.is_right_eye = + plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->tg); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 5a9fcbc22d04..3fe6df92f91f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1406,7 +1406,7 @@ static bool construct( goto res_create_fail; dcn10_hw_sequencer_construct(dc); - dc->public.caps.max_surfaces = pool->base.pipe_count; + dc->public.caps.max_planes = pool->base.pipe_count; dc->public.cap_funcs = cap_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index d5c0f9e34ce9..3b3330c563e0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -36,7 +36,7 @@ #define MAX_CLOCK_SOURCES 7 -void enable_surface_flip_reporting(struct dc_plane_state *dc_surface, +void enable_surface_flip_reporting(struct dc_plane_state *plane_state, uint32_t controller_id); #include "grph_object_id.h" @@ -153,7 +153,7 @@ struct resource_pool { }; struct pipe_ctx { - struct dc_plane_state *surface; + struct dc_plane_state *plane_state; struct dc_stream_state *stream; struct mem_input *mi; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 7e03f8d45b2b..5d075f93b4b9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -59,7 +59,7 @@ struct hw_sequencer_funcs { void (*apply_ctx_for_surface)( struct core_dc *dc, - const struct dc_plane_state *surface, + const struct dc_plane_state *plane_state, struct validate_context *context); void (*set_plane_config)( @@ -88,7 +88,7 @@ struct hw_sequencer_funcs { bool (*set_input_transfer_func)( struct pipe_ctx *pipe_ctx, - const struct dc_plane_state *surface); + const struct dc_plane_state *plane_state); bool (*set_output_transfer_func)( struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index aef1197cf749..7f30d9937d10 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -119,7 +119,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( struct dc_stream_state *stream); bool resource_attach_surfaces_to_context( - struct dc_plane_state *const *surfaces, + struct dc_plane_state *const *plane_state, int surface_count, struct dc_stream_state *dc_stream, struct validate_context *context, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 0e978d921fdf..beb790937769 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -77,7 +77,7 @@ void logger_write(struct dal_logger *logger, void pre_surface_trace( const struct dc *dc, - const struct dc_plane_state *const *surfaces, + const struct dc_plane_state *const *plane_states, int surface_count); void update_surface_trace( -- GitLab From 0a8f43ff64156525f98220efe0992925995153b6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 13:19:56 -0400 Subject: [PATCH 0727/2898] drm/amd/display: Remove struct from stack in dp_set_test_pattern Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 50724f9a8e2c..231cade5e1fd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2407,7 +2407,7 @@ bool dc_link_dp_set_test_pattern( unsigned int cust_pattern_size) { struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; - struct pipe_ctx pipe_ctx = pipes[0]; + struct pipe_ctx *pipe_ctx = &pipes[0]; unsigned int lane; unsigned int i; unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0}; @@ -2418,7 +2418,7 @@ bool dc_link_dp_set_test_pattern( for (i = 0; i < MAX_PIPES; i++) { if (pipes[i].stream->sink->link == link) { - pipe_ctx = pipes[i]; + pipe_ctx = &pipes[i]; break; } } @@ -2430,14 +2430,14 @@ bool dc_link_dp_set_test_pattern( if (link->test_pattern_enabled && test_pattern == DP_TEST_PATTERN_VIDEO_MODE) { /* Set CRTC Test Pattern */ - set_crtc_test_pattern(link, &pipe_ctx, test_pattern); + set_crtc_test_pattern(link, pipe_ctx, test_pattern); dp_set_hw_test_pattern(link, test_pattern, (uint8_t *)p_custom_pattern, (uint32_t)cust_pattern_size); /* Unblank Stream */ link->dc->hwss.unblank_stream( - &pipe_ctx, + pipe_ctx, &link->verified_link_cap); /* TODO:m_pHwss->MuteAudioEndpoint * (pPathMode->pDisplayPath, false); @@ -2464,7 +2464,7 @@ bool dc_link_dp_set_test_pattern( * MuteAudioEndpoint(pPathMode->pDisplayPath, true); */ /* Blank stream */ - pipes->stream_enc->funcs->dp_blank(pipe_ctx.stream_enc); + pipes->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc); } dp_set_hw_test_pattern(link, test_pattern, @@ -2545,7 +2545,7 @@ bool dc_link_dp_set_test_pattern( } } else { /* CRTC Patterns */ - set_crtc_test_pattern(link, &pipe_ctx, test_pattern); + set_crtc_test_pattern(link, pipe_ctx, test_pattern); /* Set Test Pattern state */ link->test_pattern_enabled = true; } -- GitLab From 79b06f0ce58cc6eb7cd8ad83c308fa59ccb355e0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 11:43:06 -0400 Subject: [PATCH 0728/2898] drm/amd/display: Stub new resource objects We want to split pipe_ctx into plane and stream resource objects. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 3b3330c563e0..6c937411af23 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -152,10 +152,21 @@ struct resource_pool { const struct resource_caps *res_cap; }; +struct stream_resource { + int stub; +}; + +struct plane_resource { + int stub; +}; + struct pipe_ctx { struct dc_plane_state *plane_state; struct dc_stream_state *stream; + struct plane_resource plane_res; + struct stream_resource stream_res; + struct mem_input *mi; struct input_pixel_processor *ipp; struct transform *xfm; -- GitLab From 6702a9ac53f88a373a9969b4dee292f4c5f023f5 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 11:51:21 -0400 Subject: [PATCH 0729/2898] drm/amd/display: Move scl_data to plane_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.scl_data/\.plane_res.scl_data/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->scl_data/->plane_res.scl_data/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dce_calcs.c | 36 +++---- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 84 +++++++-------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 100 +++++++++--------- .../gpu/drm/amd/display/dc/core/dc_stream.c | 6 +- .../display/dc/dce110/dce110_hw_sequencer.c | 34 +++--- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 28 ++--- .../gpu/drm/amd/display/dc/inc/core_types.h | 4 +- 7 files changed, 145 insertions(+), 147 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 28dbd18b2d86..dba25853f7f9 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2613,13 +2613,13 @@ static void populate_initial_data( data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total); data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); - data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); - data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); - data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); - data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].plane_res.scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].plane_res.scl_data.ratios.vert.value); switch (pipe[i].plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); @@ -2667,16 +2667,16 @@ static void populate_initial_data( data->fbc_en[num_displays * 2 + j] = false; data->lpt_en[num_displays * 2 + j] = false; - data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.height); - data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.viewport.width); + data->src_height[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->plane_res.scl_data.viewport.height); + data->src_width[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->plane_res.scl_data.viewport.width); data->pitch_in_pixels[num_displays * 2 + j] = bw_int_to_fixed( pipe[i].bottom_pipe->plane_state->plane_size.grph.surface_pitch); - data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.h_taps); - data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->scl_data.taps.v_taps); + data->h_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->plane_res.scl_data.taps.h_taps); + data->v_taps[num_displays * 2 + j] = bw_int_to_fixed(pipe[i].bottom_pipe->plane_res.scl_data.taps.v_taps); data->h_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( - pipe[i].bottom_pipe->scl_data.ratios.horz.value); + pipe[i].bottom_pipe->plane_res.scl_data.ratios.horz.value); data->v_scale_ratio[num_displays * 2 + j] = fixed31_32_to_bw_fixed( - pipe[i].bottom_pipe->scl_data.ratios.vert.value); + pipe[i].bottom_pipe->plane_res.scl_data.ratios.vert.value); switch (pipe[i].bottom_pipe->plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays * 2 + j] = bw_int_to_fixed(0); @@ -2711,13 +2711,13 @@ static void populate_initial_data( data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total); data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000); if (pipe[i].plane_state) { - data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.width); + data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width); data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4]; - data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.viewport.height); - data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.h_taps); - data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].scl_data.taps.v_taps); - data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.horz.value); - data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].scl_data.ratios.vert.value); + data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.height); + data->h_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.taps.h_taps); + data->v_taps[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.taps.v_taps); + data->h_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].plane_res.scl_data.ratios.horz.value); + data->v_scale_ratio[num_displays + 4] = fixed31_32_to_bw_fixed(pipe[i].plane_res.scl_data.ratios.vert.value); switch (pipe[i].plane_state->rotation) { case ROTATION_ANGLE_0: data->rotation_angle[num_displays + 4] = bw_int_to_fixed(0); diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 404b39e7b44b..cb762006e1c3 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -244,10 +244,10 @@ static void pipe_ctx_to_e2e_pipe_params ( input->src.source_scan = dm_horz; input->src.sw_mode = pipe->plane_state->tiling_info.gfx9.swizzle; - input->src.viewport_width = pipe->scl_data.viewport.width; - input->src.viewport_height = pipe->scl_data.viewport.height; - input->src.data_pitch = pipe->scl_data.viewport.width; - input->src.data_pitch_c = pipe->scl_data.viewport.width; + input->src.viewport_width = pipe->plane_res.scl_data.viewport.width; + input->src.viewport_height = pipe->plane_res.scl_data.viewport.height; + input->src.data_pitch = pipe->plane_res.scl_data.viewport.width; + input->src.data_pitch_c = pipe->plane_res.scl_data.viewport.width; input->src.cur0_src_width = 128; /* TODO: Cursor calcs, not curently stored */ input->src.cur0_bpp = 32; @@ -341,21 +341,21 @@ static void pipe_ctx_to_e2e_pipe_params ( break; } - input->scale_taps.htaps = pipe->scl_data.taps.h_taps; - input->scale_ratio_depth.hscl_ratio = pipe->scl_data.ratios.horz.value/4294967296.0; - input->scale_ratio_depth.vscl_ratio = pipe->scl_data.ratios.vert.value/4294967296.0; - input->scale_ratio_depth.vinit = pipe->scl_data.inits.v.value/4294967296.0; + input->scale_taps.htaps = pipe->plane_res.scl_data.taps.h_taps; + input->scale_ratio_depth.hscl_ratio = pipe->plane_res.scl_data.ratios.horz.value/4294967296.0; + input->scale_ratio_depth.vscl_ratio = pipe->plane_res.scl_data.ratios.vert.value/4294967296.0; + input->scale_ratio_depth.vinit = pipe->plane_res.scl_data.inits.v.value/4294967296.0; if (input->scale_ratio_depth.vinit < 1.0) input->scale_ratio_depth.vinit = 1; - input->scale_taps.vtaps = pipe->scl_data.taps.v_taps; - input->scale_taps.vtaps_c = pipe->scl_data.taps.v_taps_c; - input->scale_taps.htaps_c = pipe->scl_data.taps.h_taps_c; - input->scale_ratio_depth.hscl_ratio_c = pipe->scl_data.ratios.horz_c.value/4294967296.0; - input->scale_ratio_depth.vscl_ratio_c = pipe->scl_data.ratios.vert_c.value/4294967296.0; - input->scale_ratio_depth.vinit_c = pipe->scl_data.inits.v_c.value/4294967296.0; + input->scale_taps.vtaps = pipe->plane_res.scl_data.taps.v_taps; + input->scale_taps.vtaps_c = pipe->plane_res.scl_data.taps.v_taps_c; + input->scale_taps.htaps_c = pipe->plane_res.scl_data.taps.h_taps_c; + input->scale_ratio_depth.hscl_ratio_c = pipe->plane_res.scl_data.ratios.horz_c.value/4294967296.0; + input->scale_ratio_depth.vscl_ratio_c = pipe->plane_res.scl_data.ratios.vert_c.value/4294967296.0; + input->scale_ratio_depth.vinit_c = pipe->plane_res.scl_data.inits.v_c.value/4294967296.0; if (input->scale_ratio_depth.vinit_c < 1.0) input->scale_ratio_depth.vinit_c = 1; - switch (pipe->scl_data.lb_params.depth) { + switch (pipe->plane_res.scl_data.lb_params.depth) { case LB_PIXEL_DEPTH_30BPP: input->scale_ratio_depth.lb_depth = 30; break; case LB_PIXEL_DEPTH_36BPP: @@ -367,11 +367,11 @@ static void pipe_ctx_to_e2e_pipe_params ( input->dest.vactive = pipe->stream->timing.v_addressable; - input->dest.recout_width = pipe->scl_data.recout.width; - input->dest.recout_height = pipe->scl_data.recout.height; + input->dest.recout_width = pipe->plane_res.scl_data.recout.width; + input->dest.recout_height = pipe->plane_res.scl_data.recout.height; - input->dest.full_recout_width = pipe->scl_data.recout.width; - input->dest.full_recout_height = pipe->scl_data.recout.height; + input->dest.full_recout_width = pipe->plane_res.scl_data.recout.width; + input->dest.full_recout_height = pipe->plane_res.scl_data.recout.height; input->dest.htotal = pipe->stream->timing.h_total; input->dest.hblank_start = input->dest.htotal - pipe->stream->timing.h_front_porch; @@ -885,38 +885,38 @@ bool dcn_validate_bandwidth( v->source_scan[input_idx] = dcn_bw_hor; } else { - v->viewport_height[input_idx] = pipe->scl_data.viewport.height; - v->viewport_width[input_idx] = pipe->scl_data.viewport.width; - v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width; - v->scaler_recout_height[input_idx] = pipe->scl_data.recout.height; + v->viewport_height[input_idx] = pipe->plane_res.scl_data.viewport.height; + v->viewport_width[input_idx] = pipe->plane_res.scl_data.viewport.width; + v->scaler_rec_out_width[input_idx] = pipe->plane_res.scl_data.recout.width; + v->scaler_recout_height[input_idx] = pipe->plane_res.scl_data.recout.height; if (pipe->bottom_pipe && pipe->bottom_pipe->plane_state == pipe->plane_state) { if (pipe->plane_state->rotation % 2 == 0) { - int viewport_end = pipe->scl_data.viewport.width - + pipe->scl_data.viewport.x; - int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.width - + pipe->bottom_pipe->scl_data.viewport.x; + int viewport_end = pipe->plane_res.scl_data.viewport.width + + pipe->plane_res.scl_data.viewport.x; + int viewport_b_end = pipe->bottom_pipe->plane_res.scl_data.viewport.width + + pipe->bottom_pipe->plane_res.scl_data.viewport.x; if (viewport_end > viewport_b_end) v->viewport_width[input_idx] = viewport_end - - pipe->bottom_pipe->scl_data.viewport.x; + - pipe->bottom_pipe->plane_res.scl_data.viewport.x; else v->viewport_width[input_idx] = viewport_b_end - - pipe->scl_data.viewport.x; + - pipe->plane_res.scl_data.viewport.x; } else { - int viewport_end = pipe->scl_data.viewport.height - + pipe->scl_data.viewport.y; - int viewport_b_end = pipe->bottom_pipe->scl_data.viewport.height - + pipe->bottom_pipe->scl_data.viewport.y; + int viewport_end = pipe->plane_res.scl_data.viewport.height + + pipe->plane_res.scl_data.viewport.y; + int viewport_b_end = pipe->bottom_pipe->plane_res.scl_data.viewport.height + + pipe->bottom_pipe->plane_res.scl_data.viewport.y; if (viewport_end > viewport_b_end) v->viewport_height[input_idx] = viewport_end - - pipe->bottom_pipe->scl_data.viewport.y; + - pipe->bottom_pipe->plane_res.scl_data.viewport.y; else v->viewport_height[input_idx] = viewport_b_end - - pipe->scl_data.viewport.y; + - pipe->plane_res.scl_data.viewport.y; } - v->scaler_rec_out_width[input_idx] = pipe->scl_data.recout.width - + pipe->bottom_pipe->scl_data.recout.width; + v->scaler_rec_out_width[input_idx] = pipe->plane_res.scl_data.recout.width + + pipe->bottom_pipe->plane_res.scl_data.recout.width; } v->dcc_enable[input_idx] = pipe->plane_state->dcc.enable ? dcn_bw_yes : dcn_bw_no; @@ -924,11 +924,11 @@ bool dcn_validate_bandwidth( pipe->plane_state->format); v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs( pipe->plane_state->tiling_info.gfx9.swizzle); - v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->scl_data.lb_params.depth); - v->override_hta_ps[input_idx] = pipe->scl_data.taps.h_taps; - v->override_vta_ps[input_idx] = pipe->scl_data.taps.v_taps; - v->override_hta_pschroma[input_idx] = pipe->scl_data.taps.h_taps_c; - v->override_vta_pschroma[input_idx] = pipe->scl_data.taps.v_taps_c; + v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->plane_res.scl_data.lb_params.depth); + v->override_hta_ps[input_idx] = pipe->plane_res.scl_data.taps.h_taps; + v->override_vta_ps[input_idx] = pipe->plane_res.scl_data.taps.v_taps; + v->override_hta_pschroma[input_idx] = pipe->plane_res.scl_data.taps.h_taps_c; + v->override_vta_pschroma[input_idx] = pipe->plane_res.scl_data.taps.v_taps_c; v->source_scan[input_idx] = (pipe->plane_state->rotation % 2) ? dcn_bw_vert : dcn_bw_hor; } if (v->is_line_buffer_bpp_fixed == dcn_bw_yes) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4eef400cb551..84a15a999117 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -432,7 +432,7 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; - struct scaler_data *data = &pipe_ctx->scl_data; + struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect surf_src = plane_state->src_rect; struct rect clip = { 0 }; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 @@ -539,53 +539,53 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); - pipe_ctx->scl_data.recout.x = stream->dst.x; + pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; if (stream->src.x < surf_clip.x) - pipe_ctx->scl_data.recout.x += (surf_clip.x + pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x - stream->src.x) * stream->dst.width / stream->src.width; - pipe_ctx->scl_data.recout.width = surf_clip.width * + pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * stream->dst.width / stream->src.width; - if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x > + if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > stream->dst.x + stream->dst.width) - pipe_ctx->scl_data.recout.width = + pipe_ctx->plane_res.scl_data.recout.width = stream->dst.x + stream->dst.width - - pipe_ctx->scl_data.recout.x; + - pipe_ctx->plane_res.scl_data.recout.x; - pipe_ctx->scl_data.recout.y = stream->dst.y; + pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; if (stream->src.y < surf_clip.y) - pipe_ctx->scl_data.recout.y += (surf_clip.y + pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y - stream->src.y) * stream->dst.height / stream->src.height; - pipe_ctx->scl_data.recout.height = surf_clip.height * + pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * stream->dst.height / stream->src.height; - if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y > + if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > stream->dst.y + stream->dst.height) - pipe_ctx->scl_data.recout.height = + pipe_ctx->plane_res.scl_data.recout.height = stream->dst.y + stream->dst.height - - pipe_ctx->scl_data.recout.y; + - pipe_ctx->plane_res.scl_data.recout.y; /* Handle h & vsplit */ if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) { if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { - pipe_ctx->scl_data.recout.height /= 2; - pipe_ctx->scl_data.recout.y += pipe_ctx->scl_data.recout.height; + pipe_ctx->plane_res.scl_data.recout.height /= 2; + pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height; /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->scl_data.recout.height += pipe_ctx->scl_data.recout.height % 2; + pipe_ctx->plane_res.scl_data.recout.height += pipe_ctx->plane_res.scl_data.recout.height % 2; } else { - pipe_ctx->scl_data.recout.width /= 2; - pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; - pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; + pipe_ctx->plane_res.scl_data.recout.width /= 2; + pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width; + pipe_ctx->plane_res.scl_data.recout.width += pipe_ctx->plane_res.scl_data.recout.width % 2; } } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) { if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) - pipe_ctx->scl_data.recout.height /= 2; + pipe_ctx->plane_res.scl_data.recout.height /= 2; else - pipe_ctx->scl_data.recout.width /= 2; + pipe_ctx->plane_res.scl_data.recout.width /= 2; } /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) @@ -601,8 +601,8 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip surf_src.y * plane_state->dst_rect.height / surf_src.height * stream->dst.height / stream->src.height; - recout_skip->width = pipe_ctx->scl_data.recout.x - recout_full_x; - recout_skip->height = pipe_ctx->scl_data.recout.y - recout_full_y; + recout_skip->width = pipe_ctx->plane_res.scl_data.recout.x - recout_full_x; + recout_skip->height = pipe_ctx->plane_res.scl_data.recout.y - recout_full_y; } static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) @@ -619,36 +619,36 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) rect_swap_helper(&surf_src); - pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction( + pipe_ctx->plane_res.scl_data.ratios.horz = dal_fixed31_32_from_fraction( surf_src.width, plane_state->dst_rect.width); - pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction( + pipe_ctx->plane_res.scl_data.ratios.vert = dal_fixed31_32_from_fraction( surf_src.height, plane_state->dst_rect.height); if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) - pipe_ctx->scl_data.ratios.horz.value *= 2; + pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) - pipe_ctx->scl_data.ratios.vert.value *= 2; + pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; - pipe_ctx->scl_data.ratios.vert.value = div64_s64( - pipe_ctx->scl_data.ratios.vert.value * in_h, out_h); - pipe_ctx->scl_data.ratios.horz.value = div64_s64( - pipe_ctx->scl_data.ratios.horz.value * in_w, out_w); + pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( + pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); + pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( + pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); - pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; - pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; + pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; + pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; - if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP8 - || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP10) { - pipe_ctx->scl_data.ratios.horz_c.value /= 2; - pipe_ctx->scl_data.ratios.vert_c.value /= 2; + if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 + || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { + pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; + pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; } } static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) { - struct scaler_data *data = &pipe_ctx->scl_data; + struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect src = pipe_ctx->plane_state->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; @@ -823,14 +823,14 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) * lb depth calculation requires recout and taps require scaling ratios. * Inits require viewport, taps, ratios and recout of split pipe */ - pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( + pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( pipe_ctx->plane_state->format); calculate_scaling_ratios(pipe_ctx); calculate_viewport(pipe_ctx); - if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16) + if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16) return false; calculate_recout(pipe_ctx, &recout_skip); @@ -839,21 +839,21 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) * Setting line buffer pixel depth to 24bpp yields banding * on certain displays, such as the Sharp 4k */ - pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; - pipe_ctx->scl_data.h_active = timing->h_addressable; - pipe_ctx->scl_data.v_active = timing->v_addressable; + pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; + pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; /* Taps calculations */ res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->scl_data, &plane_state->scaling_quality); + pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ - pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->scl_data, &plane_state->scaling_quality); + pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); } if (res) @@ -865,10 +865,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) "y:%d\n dst_rect:\nheight:%d width:%d x:%d " "y:%d\n", __func__, - pipe_ctx->scl_data.viewport.height, - pipe_ctx->scl_data.viewport.width, - pipe_ctx->scl_data.viewport.x, - pipe_ctx->scl_data.viewport.y, + pipe_ctx->plane_res.scl_data.viewport.height, + pipe_ctx->plane_res.scl_data.viewport.width, + pipe_ctx->plane_res.scl_data.viewport.x, + pipe_ctx->plane_res.scl_data.viewport.y, plane_state->dst_rect.height, plane_state->dst_rect.width, plane_state->dst_rect.x, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 2b6506822cca..ef3a7b83cebe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -223,9 +223,9 @@ bool dc_stream_set_cursor_position( struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz, - .viewport_x_start = pipe_ctx->scl_data.viewport.x, - .viewport_width = pipe_ctx->scl_data.viewport.width, - .h_scale_ratio = pipe_ctx->scl_data.ratios.horz + .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x, + .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width, + .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz }; if (pipe_ctx->stream != stream || diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ea9ce87d348a..dee18c92fd52 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -914,7 +914,7 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, { uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4; - switch (pipe_ctx->scl_data.format) { + switch (pipe_ctx->plane_res.scl_data.format) { case PIXEL_FORMAT_ARGB8888: /* set boarder color to red */ color->color_r_cr = color_value; @@ -964,7 +964,7 @@ static void program_scaler(const struct core_dc *dc, pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth( pipe_ctx->xfm, - pipe_ctx->scl_data.lb_params.depth, + pipe_ctx->plane_res.scl_data.lb_params.depth, &pipe_ctx->stream->bit_depth_params); if (pipe_ctx->tg->funcs->set_overscan_blank_color) @@ -973,7 +973,7 @@ static void program_scaler(const struct core_dc *dc, &color); pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, - &pipe_ctx->scl_data); + &pipe_ctx->plane_res.scl_data); } static enum dc_status dce110_prog_pixclk_crtc_otg( @@ -1114,10 +1114,10 @@ static enum dc_status apply_single_controller_ctx_to_hw( &stream->sink->link->cur_link_settings); } - pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; /* program_scaler and allocate_mem_input are not new asic */ if ((!pipe_ctx_old || - memcmp(&pipe_ctx_old->scl_data, &pipe_ctx->scl_data, + memcmp(&pipe_ctx_old->plane_res.scl_data, &pipe_ctx->plane_res.scl_data, sizeof(struct scaler_data)) != 0) && pipe_ctx->plane_state) { program_scaler(dc, pipe_ctx); @@ -1927,14 +1927,14 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) default_adjust.out_color_space = pipe_ctx->stream->output_color_space; default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; - default_adjust.surface_pixel_format = pipe_ctx->scl_data.format; + default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; /* display color depth */ default_adjust.color_depth = pipe_ctx->stream->timing.display_color_depth; /* Lb color depth */ - default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth; + default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; pipe_ctx->xfm->funcs->opp_set_csc_default( pipe_ctx->xfm, &default_adjust); @@ -2096,7 +2096,7 @@ static void set_plane_config( pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); - pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; program_scaler(dc, pipe_ctx); program_surface_visibility(dc, pipe_ctx); @@ -2552,7 +2552,7 @@ static void dce110_program_front_end_for_pipe( pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); - pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; program_scaler(dc, pipe_ctx); @@ -2602,14 +2602,14 @@ static void dce110_program_front_end_for_pipe( "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, - pipe_ctx->scl_data.viewport.width, - pipe_ctx->scl_data.viewport.height, - pipe_ctx->scl_data.viewport.x, - pipe_ctx->scl_data.viewport.y, - pipe_ctx->scl_data.recout.width, - pipe_ctx->scl_data.recout.height, - pipe_ctx->scl_data.recout.x, - pipe_ctx->scl_data.recout.y); + pipe_ctx->plane_res.scl_data.viewport.width, + pipe_ctx->plane_res.scl_data.viewport.height, + pipe_ctx->plane_res.scl_data.viewport.x, + pipe_ctx->plane_res.scl_data.viewport.y, + pipe_ctx->plane_res.scl_data.recout.width, + pipe_ctx->plane_res.scl_data.recout.height, + pipe_ctx->plane_res.scl_data.recout.x, + pipe_ctx->plane_res.scl_data.recout.y); } static void dce110_apply_ctx_for_surface( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 5922cf8272f5..314d7645a898 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1728,14 +1728,14 @@ static void dcn10_power_on_fe( "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, - pipe_ctx->scl_data.viewport.width, - pipe_ctx->scl_data.viewport.height, - pipe_ctx->scl_data.viewport.x, - pipe_ctx->scl_data.viewport.y, - pipe_ctx->scl_data.recout.width, - pipe_ctx->scl_data.recout.height, - pipe_ctx->scl_data.recout.x, - pipe_ctx->scl_data.recout.y); + pipe_ctx->plane_res.scl_data.viewport.width, + pipe_ctx->plane_res.scl_data.viewport.height, + pipe_ctx->plane_res.scl_data.viewport.x, + pipe_ctx->plane_res.scl_data.viewport.y, + pipe_ctx->plane_res.scl_data.recout.width, + pipe_ctx->plane_res.scl_data.recout.height, + pipe_ctx->plane_res.scl_data.recout.x, + pipe_ctx->plane_res.scl_data.recout.y); print_rq_dlg_ttu(dc, pipe_ctx); } } @@ -1860,7 +1860,7 @@ static void dcn10_get_surface_visual_confirm_color( { uint32_t color_value = MAX_TG_COLOR_VALUE; - switch (pipe_ctx->scl_data.format) { + switch (pipe_ctx->plane_res.scl_data.format) { case PIXEL_FORMAT_ARGB8888: /* set boarder color to red */ color->color_r_cr = color_value; @@ -1931,7 +1931,7 @@ static void update_dchubp_dpp( &pipe_ctx->rq_regs, &pipe_ctx->pipe_dlg_param); - size.grph.surface_size = pipe_ctx->scl_data.viewport; + size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( @@ -1965,13 +1965,13 @@ static void update_dchubp_dpp( && per_pixel_alpha; dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); - pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; - pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ pipe_ctx->xfm->funcs->transform_set_scaler( - pipe_ctx->xfm, &pipe_ctx->scl_data); + pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data); mi->funcs->mem_program_viewport(mi, - &pipe_ctx->scl_data.viewport, &pipe_ctx->scl_data.viewport_c); + &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); /*gamut remap*/ program_gamut_remap(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 6c937411af23..dbca1de89494 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -157,7 +157,7 @@ struct stream_resource { }; struct plane_resource { - int stub; + struct scaler_data scl_data; }; struct pipe_ctx { @@ -173,8 +173,6 @@ struct pipe_ctx { struct output_pixel_processor *opp; struct timing_generator *tg; - struct scaler_data scl_data; - struct stream_encoder *stream_enc; struct display_clock *dis_clk; struct clock_source *clock_source; -- GitLab From 86a66c4eb7365c96230bca218634439f7b057306 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 11:55:55 -0400 Subject: [PATCH 0730/2898] drm/amd/display: Move mi, ipp, xfm to plane_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.mi/\.plane_res.mi/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->mi/->plane_res.mi/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.ipp/\.plane_res.ipp/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->ipp/->plane_res.ipp/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.xfm/\.plane_res.xfm/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->xfm/->plane_res.xfm/g' To clean up bad renames: find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.min/\.min/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.min/->min/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mic/->mic/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.mis/\.mis/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mid/->mid/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.mid/\.mid/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mis/->mis/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.min/\.min/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.min/->min/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mic/->mic/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.mis/\.mis/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mid/->mid/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.mid/\.mid/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/->plane_res\.mis/->mis/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/\.plane_res\.ipps/\.ipps/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/mpcc_cfg\.plane_res\.mi/mpcc_cfg\.mi/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/mi->plane_res\./mi->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/cfg->plane_res\./cfg->/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 20 ++--- .../gpu/drm/amd/display/dc/core/dc_stream.c | 10 +-- .../display/dc/dce110/dce110_hw_sequencer.c | 80 +++++++++---------- .../amd/display/dc/dce110/dce110_resource.c | 8 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 40 +++++----- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 6 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 7 +- 8 files changed, 89 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index cb762006e1c3..1922c13d6f22 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -547,9 +547,9 @@ static void split_stream_across_pipes( *secondary_pipe = *primary_pipe; secondary_pipe->pipe_idx = pipe_idx; - secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; - secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; - secondary_pipe->xfm = pool->transforms[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 84a15a999117..7270f0de9598 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -845,15 +845,15 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; /* Taps calculations */ - res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; - res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); } if (res) @@ -1012,9 +1012,9 @@ static int acquire_first_split_pipe( memset(pipe_ctx, 0, sizeof(*pipe_ctx)); pipe_ctx->tg = pool->timing_generators[i]; - pipe_ctx->mi = pool->mis[i]; - pipe_ctx->ipp = pool->ipps[i]; - pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.ipp = pool->ipps[i]; + pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; @@ -1242,9 +1242,9 @@ static int acquire_first_free_pipe( struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; pipe_ctx->tg = pool->timing_generators[i]; - pipe_ctx->mi = pool->mis[i]; - pipe_ctx->ipp = pool->ipps[i]; - pipe_ctx->xfm = pool->transforms[i]; + pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.ipp = pool->ipps[i]; + pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index ef3a7b83cebe..10587896cc86 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -183,13 +183,13 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->ipp) + if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.ipp) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; - pipe_ctx->ipp->funcs->ipp_cursor_set_attributes( - pipe_ctx->ipp, attributes); + pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( + pipe_ctx->plane_res.ipp, attributes); } return true; @@ -218,7 +218,7 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, @@ -229,7 +229,7 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->ipp || !pipe_ctx->plane_state) + !pipe_ctx->plane_res.ipp || !pipe_ctx->plane_state) continue; if (pipe_ctx->plane_state->address.type diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index dee18c92fd52..1586dc95f5e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -242,7 +242,7 @@ static bool dce110_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; const struct dc_transfer_func *tf = NULL; struct ipp_prescale_params prescale_params = { 0 }; bool result = true; @@ -625,7 +625,7 @@ static bool dce110_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { - struct transform *xfm = pipe_ctx->xfm; + struct transform *xfm = pipe_ctx->plane_res.xfm; xfm->funcs->opp_power_on_regamma_lut(xfm, true); xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; @@ -951,7 +951,7 @@ static void program_scaler(const struct core_dc *dc, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) /* TOFPGA */ - if (pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth == NULL) + if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL) return; #endif @@ -962,8 +962,8 @@ static void program_scaler(const struct core_dc *dc, pipe_ctx->stream->output_color_space, &color); - pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth( - pipe_ctx->xfm, + pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( + pipe_ctx->plane_res.xfm, pipe_ctx->plane_res.scl_data.lb_params.depth, &pipe_ctx->stream->bit_depth_params); @@ -972,7 +972,7 @@ static void program_scaler(const struct core_dc *dc, pipe_ctx->tg, &color); - pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm, + pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); } @@ -1125,10 +1125,10 @@ static enum dc_status apply_single_controller_ctx_to_hw( /* mst support - use total stream count */ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (pipe_ctx->mi->funcs->allocate_mem_input != NULL) + if (pipe_ctx->plane_res.mi->funcs->allocate_mem_input != NULL) #endif - pipe_ctx->mi->funcs->allocate_mem_input( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, stream->timing.h_total, stream->timing.v_total, stream->timing.pix_clk_khz, @@ -1260,16 +1260,16 @@ void dce110_set_displaymarks( total_dest_line_time_ns = compute_pstate_blackout_duration( dc->bw_vbios.blackout_duration, pipe_ctx->stream); - pipe_ctx->mi->funcs->mem_input_program_display_marks( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( + pipe_ctx->plane_res.mi, context->bw.dce.nbp_state_change_wm_ns[num_pipes], context->bw.dce.stutter_exit_wm_ns[num_pipes], context->bw.dce.urgent_wm_ns[num_pipes], total_dest_line_time_ns); if (i == underlay_idx) { num_pipes++; - pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks( + pipe_ctx->plane_res.mi, context->bw.dce.nbp_state_change_wm_ns[num_pipes], context->bw.dce.stutter_exit_wm_ns[num_pipes], context->bw.dce.urgent_wm_ns[num_pipes], @@ -1294,15 +1294,15 @@ static void set_safe_displaymarks( if (res_ctx->pipe_ctx[i].stream == NULL) continue; - res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks( - res_ctx->pipe_ctx[i].mi, + res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( + res_ctx->pipe_ctx[i].plane_res.mi, nbp_marks, max_marks, max_marks, MAX_WATERMARK); if (i == underlay_idx) - res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_chroma_display_marks( - res_ctx->pipe_ctx[i].mi, + res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( + res_ctx->pipe_ctx[i].plane_res.mi, nbp_marks, max_marks, max_marks, @@ -1652,8 +1652,8 @@ static void dce110_reset_hw_ctx_wrap( BREAK_TO_DEBUGGER(); } pipe_ctx_old->tg->funcs->disable_crtc(pipe_ctx_old->tg); - pipe_ctx_old->mi->funcs->free_mem_input( - pipe_ctx_old->mi, dc->current_context->stream_count); + pipe_ctx_old->plane_res.mi->funcs->free_mem_input( + pipe_ctx_old->plane_res.mi, dc->current_context->stream_count); resource_unreference_clock_source( &dc->current_context->res_ctx, dc->res_pool, &pipe_ctx_old->clock_source); @@ -1936,8 +1936,8 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) /* Lb color depth */ default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; - pipe_ctx->xfm->funcs->opp_set_csc_default( - pipe_ctx->xfm, &default_adjust); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( + pipe_ctx->plane_res.xfm, &default_adjust); } @@ -2026,7 +2026,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) gamut_remap_matrix.matrix[10]; } - pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); } /** @@ -2037,7 +2037,7 @@ static void set_plane_config( struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx) { - struct mem_input *mi = pipe_ctx->mi; + struct mem_input *mi = pipe_ctx->plane_res.mi; struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; @@ -2059,8 +2059,8 @@ static void set_plane_config( tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - pipe_ctx->xfm->funcs->opp_set_csc_adjustment - (pipe_ctx->xfm, &tbl_entry); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->plane_res.xfm, &tbl_entry); } if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { @@ -2094,7 +2094,7 @@ static void set_plane_config( gamut_remap_matrix.matrix[10]; } - pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; program_scaler(dc, pipe_ctx); @@ -2114,7 +2114,7 @@ static void set_plane_config( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( - pipe_ctx->mi, + pipe_ctx->plane_res.mi, plane_state->format, &plane_state->tiling_info, plane_state->rotation); @@ -2128,8 +2128,8 @@ static void update_plane_addr(const struct core_dc *dc, if (plane_state == NULL) return; - pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( + pipe_ctx->plane_res.mi, &plane_state->address, plane_state->flip_immediate); @@ -2144,14 +2144,14 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) return; plane_state->status.is_flip_pending = - pipe_ctx->mi->funcs->mem_input_is_flip_pending( - pipe_ctx->mi); + pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( + pipe_ctx->plane_res.mi); if (plane_state->status.is_flip_pending && !plane_state->visible) - pipe_ctx->mi->current_address = pipe_ctx->mi->request_address; + pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address; - plane_state->status.current_address = pipe_ctx->mi->current_address; - if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; + if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && pipe_ctx->tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye =\ !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg); @@ -2488,7 +2488,7 @@ static void dce110_set_bandwidth( static void dce110_program_front_end_for_pipe( struct core_dc *dc, struct pipe_ctx *pipe_ctx) { - struct mem_input *mi = pipe_ctx->mi; + struct mem_input *mi = pipe_ctx->plane_res.mi; struct pipe_ctx *old_pipe = NULL; struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; @@ -2515,8 +2515,8 @@ static void dce110_program_front_end_for_pipe( tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i]; - pipe_ctx->xfm->funcs->opp_set_csc_adjustment - (pipe_ctx->xfm, &tbl_entry); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->plane_res.xfm, &tbl_entry); } if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { @@ -2550,7 +2550,7 @@ static void dce110_program_front_end_for_pipe( gamut_remap_matrix.matrix[10]; } - pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; @@ -2569,7 +2569,7 @@ static void dce110_program_front_end_for_pipe( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( - pipe_ctx->mi, + pipe_ctx->plane_res.mi, plane_state->format, &plane_state->tiling_info, plane_state->rotation); @@ -2673,7 +2673,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->xfm->funcs->opp_set_csc_adjustment(pipe_ctx->xfm, &tbl_entry); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index f580da1b3249..04a508234251 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1017,9 +1017,9 @@ static struct pipe_ctx *dce110_acquire_underlay( return NULL; pipe_ctx->tg = pool->timing_generators[underlay_idx]; - pipe_ctx->mi = pool->mis[underlay_idx]; - /*pipe_ctx->ipp = res_ctx->pool->ipps[underlay_idx];*/ - pipe_ctx->xfm = pool->transforms[underlay_idx]; + pipe_ctx->plane_res.mi = pool->mis[underlay_idx]; + /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ + pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; pipe_ctx->opp = pool->opps[underlay_idx]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = underlay_idx; @@ -1049,7 +1049,7 @@ static struct pipe_ctx *dce110_acquire_underlay( true, &stream->timing); - pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->allocate_mem_input(pipe_ctx->plane_res.mi, stream->timing.h_total, stream->timing.v_total, stream->timing.pix_clk_khz, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 314d7645a898..1cf672d4a1ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1070,8 +1070,8 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct if (plane_state == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); - pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr( - pipe_ctx->mi, + pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( + pipe_ctx->plane_res.mi, &plane_state->address, plane_state->flip_immediate); plane_state->status.requested_address = plane_state->address; @@ -1082,7 +1082,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; const struct dc_transfer_func *tf = NULL; bool result = true; @@ -1447,7 +1447,7 @@ static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { - struct transform *xfm = pipe_ctx->xfm; + struct transform *xfm = pipe_ctx->plane_res.xfm; if (xfm == NULL) return false; @@ -1778,7 +1778,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) gamut_remap_matrix.matrix[10]; } - pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust); + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); } @@ -1800,7 +1800,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->xfm->funcs->opp_set_csc_adjustment(pipe_ctx->xfm, &tbl_entry); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); } } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) @@ -1896,8 +1896,8 @@ static void update_dchubp_dpp( struct validate_context *context) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = pipe_ctx->mi; - struct input_pixel_processor *ipp = pipe_ctx->ipp; + struct mem_input *mi = pipe_ctx->plane_res.mi; + struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; struct default_adjustment ocsc = {0}; @@ -1935,7 +1935,7 @@ static void update_dchubp_dpp( if (dc->public.config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( - pipe_ctx->mi, + pipe_ctx->plane_res.mi, plane_state->format, &plane_state->tiling_info, plane_state->rotation); @@ -1968,8 +1968,8 @@ static void update_dchubp_dpp( pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ - pipe_ctx->xfm->funcs->transform_set_scaler( - pipe_ctx->xfm, &pipe_ctx->plane_res.scl_data); + pipe_ctx->plane_res.xfm->funcs->transform_set_scaler( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); mi->funcs->mem_program_viewport(mi, &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); @@ -1978,7 +1978,7 @@ static void update_dchubp_dpp( /*TODO add adjustments parameters*/ ocsc.out_color_space = pipe_ctx->stream->output_color_space; - pipe_ctx->xfm->funcs->opp_set_csc_default(pipe_ctx->xfm, &ocsc); + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(pipe_ctx->plane_res.xfm, &ocsc); mi->funcs->mem_input_program_surface_config( mi, @@ -2098,7 +2098,7 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { + if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need @@ -2124,7 +2124,7 @@ static void dcn10_apply_ctx_for_surface( dc->res_pool->mpc, old_pipe_ctx->opp, old_pipe_ctx->pipe_idx); - old_pipe_ctx->opp->mpcc_disconnect_pending[old_pipe_ctx->mi->mpcc_id] = true; + old_pipe_ctx->opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2481,19 +2481,19 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) return; plane_state->status.is_flip_pending = - pipe_ctx->mi->funcs->mem_input_is_flip_pending( - pipe_ctx->mi); + pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( + pipe_ctx->plane_res.mi); /* DCN we read INUSE address in MI, do we still need this wa? */ if (plane_state->status.is_flip_pending && !plane_state->visible) { - pipe_ctx->mi->current_address = - pipe_ctx->mi->request_address; + pipe_ctx->plane_res.mi->current_address = + pipe_ctx->plane_res.mi->request_address; BREAK_TO_DEBUGGER(); } - plane_state->status.current_address = pipe_ctx->mi->current_address; - if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; + if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->tg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 3fe6df92f91f..710e514ee950 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -963,9 +963,9 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->tg = head_pipe->tg; idle_pipe->opp = head_pipe->opp; - idle_pipe->mi = pool->mis[idle_pipe->pipe_idx]; - idle_pipe->ipp = pool->ipps[idle_pipe->pipe_idx]; - idle_pipe->xfm = pool->transforms[idle_pipe->pipe_idx]; + idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; + idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.xfm = pool->transforms[idle_pipe->pipe_idx]; return idle_pipe; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index dbca1de89494..4640c43d17a4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -158,6 +158,10 @@ struct stream_resource { struct plane_resource { struct scaler_data scl_data; + + struct mem_input *mi; + struct input_pixel_processor *ipp; + struct transform *xfm; }; struct pipe_ctx { @@ -167,9 +171,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct mem_input *mi; - struct input_pixel_processor *ipp; - struct transform *xfm; struct output_pixel_processor *opp; struct timing_generator *tg; -- GitLab From a6a6cb349e39ef23a341a17752eebf69a5c0d7ff Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 13:55:28 -0400 Subject: [PATCH 0731/2898] drm/amd/display: Move OPP to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->opp/pipes->stream_res\.opp/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->opp->/ctx->stream_res\.opp->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->opp/pipe->stream_res\.opp/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->opp/pipe_ctx->stream_res\.opp/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++-- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 +++---- .../gpu/drm/amd/display/dc/core/dc_resource.c | 6 ++--- .../display/dc/dce110/dce110_hw_sequencer.c | 12 +++++----- .../amd/display/dc/dce110/dce110_resource.c | 2 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 24 +++++++++---------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 +-- 8 files changed, 30 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ffc9c05e2fb5..507732e4b67b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -365,8 +365,8 @@ void set_dither_option(struct dc_stream_state *stream, resource_build_bit_depth_reduction_params(stream, ¶ms); stream->bit_depth_params = params; - pipes->opp->funcs-> - opp_program_bit_depth_reduction(pipes->opp, ¶ms); + pipes->stream_res.opp->funcs-> + opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } static void allocate_dc_stream_funcs(struct core_dc *core_dc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 231cade5e1fd..0c90060c0f62 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2372,8 +2372,8 @@ static void set_crtc_test_pattern(struct dc_link *link, { /* disable bit depth reduction */ pipe_ctx->stream->bit_depth_params = params; - pipe_ctx->opp->funcs-> - opp_program_bit_depth_reduction(pipe_ctx->opp, ¶ms); + pipe_ctx->stream_res.opp->funcs-> + opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, ¶ms); pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, controller_test_pattern, color_depth); @@ -2385,8 +2385,8 @@ static void set_crtc_test_pattern(struct dc_link *link, resource_build_bit_depth_reduction_params(pipe_ctx->stream, ¶ms); pipe_ctx->stream->bit_depth_params = params; - pipe_ctx->opp->funcs-> - opp_program_bit_depth_reduction(pipe_ctx->opp, ¶ms); + pipe_ctx->stream_res.opp->funcs-> + opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, ¶ms); pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7270f0de9598..ba529f8b24e8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1015,7 +1015,7 @@ static int acquire_first_split_pipe( pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; - pipe_ctx->opp = pool->opps[i]; + pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; @@ -1095,7 +1095,7 @@ bool resource_attach_surfaces_to_context( if (tail_pipe) { free_pipe->tg = tail_pipe->tg; - free_pipe->opp = tail_pipe->opp; + free_pipe->stream_res.opp = tail_pipe->stream_res.opp; free_pipe->stream_enc = tail_pipe->stream_enc; free_pipe->audio = tail_pipe->audio; free_pipe->clock_source = tail_pipe->clock_source; @@ -1245,7 +1245,7 @@ static int acquire_first_free_pipe( pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; - pipe_ctx->opp = pool->opps[i]; + pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1586dc95f5e4..0601105a5e3f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1044,16 +1044,16 @@ static enum dc_status apply_single_controller_ctx_to_hw( /* */ dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc); - pipe_ctx->opp->funcs->opp_set_dyn_expansion( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( + pipe_ctx->stream_res.opp, COLOR_SPACE_YCBCR601, stream->timing.display_color_depth, pipe_ctx->stream->signal); /* FPGA does not program backend */ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - pipe_ctx->opp->funcs->opp_program_fmt( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); return DC_OK; @@ -1078,8 +1078,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( /*vbios crtc_source_selection and encoder_setup will override fmt_C*/ - pipe_ctx->opp->funcs->opp_program_fmt( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 04a508234251..4b7bce2427a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1020,7 +1020,7 @@ static struct pipe_ctx *dce110_acquire_underlay( pipe_ctx->plane_res.mi = pool->mis[underlay_idx]; /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; - pipe_ctx->opp = pool->opps[underlay_idx]; + pipe_ctx->stream_res.opp = pool->opps[underlay_idx]; pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = underlay_idx; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 1cf672d4a1ee..2db6b46baa6c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -720,8 +720,8 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( &stream->timing, true); - pipe_ctx->opp->funcs->opp_set_stereo_polarity( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity( + pipe_ctx->stream_res.opp, enableStereo, rightEyePolarity); @@ -731,8 +731,8 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( inst_offset = reg_offsets[pipe_ctx->tg->inst].fmt; - pipe_ctx->opp->funcs->opp_program_fmt( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); #endif @@ -1946,7 +1946,7 @@ static void update_dchubp_dpp( IPP_OUTPUT_FORMAT_12_BIT_FIX); mpcc_cfg.mi = mi; - mpcc_cfg.opp = pipe_ctx->opp; + mpcc_cfg.opp = pipe_ctx->stream_res.opp; for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) mpcc_cfg.z_index++; if (dc->public.debug.surface_visual_confirm) @@ -2122,9 +2122,9 @@ static void dcn10_apply_ctx_for_surface( /* reset mpc */ dc->res_pool->mpc->funcs->remove( dc->res_pool->mpc, - old_pipe_ctx->opp, + old_pipe_ctx->stream_res.opp, old_pipe_ctx->pipe_idx); - old_pipe_ctx->opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; + old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2364,8 +2364,8 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) dcn10_config_stereo_parameters(stream, &flags); - pipe_ctx->opp->funcs->opp_set_stereo_polarity( - pipe_ctx->opp, + pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity( + pipe_ctx->stream_res.opp, flags.PROGRAM_STEREO == 1 ? true:false, stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); @@ -2441,13 +2441,13 @@ static void dcn10_wait_for_mpcc_disconnect( { int i; - if (!pipe_ctx->opp) + if (!pipe_ctx->stream_res.opp) return; for (i = 0; i < MAX_PIPES; i++) { - if (pipe_ctx->opp->mpcc_disconnect_pending[i]) { + if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i]) { res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, i); - pipe_ctx->opp->mpcc_disconnect_pending[i] = false; + pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i] = false; res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 710e514ee950..e15eec315228 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -961,7 +961,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream = head_pipe->stream; idle_pipe->tg = head_pipe->tg; - idle_pipe->opp = head_pipe->opp; + idle_pipe->stream_res.opp = head_pipe->stream_res.opp; idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 4640c43d17a4..24a525495bfc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -153,7 +153,7 @@ struct resource_pool { }; struct stream_resource { - int stub; + struct output_pixel_processor *opp; }; struct plane_resource { @@ -171,7 +171,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct output_pixel_processor *opp; struct timing_generator *tg; struct stream_encoder *stream_enc; -- GitLab From 6b670fa965b620bf0131a0a339a388a0581bc466 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 13:59:26 -0400 Subject: [PATCH 0732/2898] drm/amd/display: Move TG to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->tg/pipes->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->tg->/ctx->stream_res\.tg->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->tg/pipe->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->tg/pipe_ctx->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.tg/pipe_ctx\[pipe_offset\]\.stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/grouped_pipes\[i\]->tg/grouped_pipes\[i\]->stream_^Cs\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/grouped_pipes\[0\]->tg/grouped_pipes\[0\]->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/grouped_pipes\[1\]->tg/grouped_pipes\[1\]->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx\[i\]->tg/pipe_ctx\[i\]->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx_old->tg/pipe_ctx_old->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_set\[j\]->tg/pipe_set\[j\]->stream_res\.tg/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx\[i\]\.tg/pipe_ctx\[i\]\.stream_res\.tg/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- .../gpu/drm/amd/display/dc/core/dc_debug.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- .../gpu/drm/amd/display/dc/core/dc_stream.c | 4 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 64 ++++++------- .../amd/display/dc/dce110/dce110_resource.c | 12 +-- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 96 +++++++++---------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 +- .../dc/irq/dce110/irq_service_dce110.c | 2 +- 13 files changed, 105 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 507732e4b67b..61c2a210c123 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -846,7 +846,7 @@ static void program_timing_sync( for (j = 0; j < group_size; j++) { struct pipe_ctx *temp; - if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) { + if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { if (j == 0) break; @@ -859,7 +859,7 @@ static void program_timing_sync( /* remove any other unblanked pipes as they have already been synced */ for (j = j + 1; j < group_size; j++) { - if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) { + if (!pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { group_size--; pipe_set[j] = pipe_set[group_size]; j--; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index ca4f1db4a58a..21af3bc057c7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -309,7 +309,7 @@ void context_timing_trace( || pipe_ctx->pipe_idx == underlay_idx) continue; - pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &position); + pipe_ctx->stream_res.tg->funcs->get_position(pipe_ctx->stream_res.tg, &position); h_pos[i] = position.horizontal_count; v_pos[i] = position.vertical_count; } @@ -320,7 +320,7 @@ void context_timing_trace( continue; TIMING_TRACE("OTG_%d H_tot:%d V_tot:%d H_pos:%d V_pos:%d\n", - pipe_ctx->tg->inst, + pipe_ctx->stream_res.tg->inst, pipe_ctx->stream->timing.h_total, pipe_ctx->stream->timing.v_total, h_pos[i], v_pos[i]); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 7a2fe2f3e65c..2c43edf2c7c4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1398,7 +1398,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, */ controller_id = core_dc->current_context-> - res_ctx.pipe_ctx[i].tg->inst + + res_ctx.pipe_ctx[i].stream_res.tg->inst + 1; } } @@ -1504,7 +1504,7 @@ bool dc_link_setup_psr(struct dc_link *link, */ psr_context->controllerId = core_dc->current_context->res_ctx. - pipe_ctx[i].tg->inst + 1; + pipe_ctx[i].stream_res.tg->inst + 1; break; } } @@ -1879,7 +1879,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) } /* turn off otg test pattern if enable */ - pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, COLOR_DEPTH_UNDEFINED); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 0c90060c0f62..eda25942aea0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2375,7 +2375,7 @@ static void set_crtc_test_pattern(struct dc_link *link, pipe_ctx->stream_res.opp->funcs-> opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, ¶ms); - pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, controller_test_pattern, color_depth); } break; @@ -2388,7 +2388,7 @@ static void set_crtc_test_pattern(struct dc_link *link, pipe_ctx->stream_res.opp->funcs-> opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, ¶ms); - pipe_ctx->tg->funcs->set_test_pattern(pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, color_depth); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ba529f8b24e8..5326713bf3fb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1011,7 +1011,7 @@ static int acquire_first_split_pipe( pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; memset(pipe_ctx, 0, sizeof(*pipe_ctx)); - pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; @@ -1094,7 +1094,7 @@ bool resource_attach_surfaces_to_context( free_pipe->plane_state = plane_state; if (tail_pipe) { - free_pipe->tg = tail_pipe->tg; + free_pipe->stream_res.tg = tail_pipe->stream_res.tg; free_pipe->stream_res.opp = tail_pipe->stream_res.opp; free_pipe->stream_enc = tail_pipe->stream_enc; free_pipe->audio = tail_pipe->audio; @@ -1241,7 +1241,7 @@ static int acquire_first_free_pipe( if (!res_ctx->pipe_ctx[i].stream) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - pipe_ctx->tg = pool->timing_generators[i]; + pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; @@ -1532,7 +1532,7 @@ enum dc_status resource_map_pool_resources( pipe_ctx->audio); } - context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst; + context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; } return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 10587896cc86..2de37fed12a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -253,7 +253,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) &core_dc->current_context->res_ctx; for (i = 0; i < MAX_PIPES; i++) { - struct timing_generator *tg = res_ctx->pipe_ctx[i].tg; + struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; if (res_ctx->pipe_ctx[i].stream != stream) continue; @@ -277,7 +277,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, &core_dc->current_context->res_ctx; for (i = 0; i < MAX_PIPES; i++) { - struct timing_generator *tg = res_ctx->pipe_ctx[i].tg; + struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; if (res_ctx->pipe_ctx[i].stream != stream) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 8140ff31c3bd..4894e1755d84 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -53,7 +53,7 @@ void dce_pipe_control_lock(struct core_dc *dc, struct dce_hwseq *hws = dc->hwseq; /* Not lock pipe when blank */ - if (lock && pipe->tg->funcs->is_blanked(pipe->tg)) + if (lock && pipe->stream_res.tg->funcs->is_blanked(pipe->stream_res.tg)) return; val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->pipe_idx], diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0601105a5e3f..1d7c7fb668be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -710,7 +710,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) */ uint32_t active_total_with_borders; uint32_t early_control = 0; - struct timing_generator *tg = pipe_ctx->tg; + struct timing_generator *tg = pipe_ctx->stream_res.tg; /* TODOFPGA may change to hwss.update_info_frame */ dce110_update_info_frame(pipe_ctx); @@ -967,9 +967,9 @@ static void program_scaler(const struct core_dc *dc, pipe_ctx->plane_res.scl_data.lb_params.depth, &pipe_ctx->stream->bit_depth_params); - if (pipe_ctx->tg->funcs->set_overscan_blank_color) - pipe_ctx->tg->funcs->set_overscan_blank_color( - pipe_ctx->tg, + if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) + pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( + pipe_ctx->stream_res.tg, &color); pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, @@ -991,15 +991,15 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( /* program blank color */ color_space_to_black_color(dc, stream->output_color_space, &black_color); - pipe_ctx->tg->funcs->set_blank_color( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, &black_color); /* * Must blank CRTC after disabling power gating and before any * programming, otherwise CRTC will be hung in bad state */ - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, @@ -1009,19 +1009,19 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( return DC_ERROR_UNEXPECTED; } - pipe_ctx->tg->funcs->program_timing( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->program_timing( + pipe_ctx->stream_res.tg, &stream->timing, true); - pipe_ctx->tg->funcs->set_static_screen_control( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_static_screen_control( + pipe_ctx->stream_res.tg, 0x182); } if (!pipe_ctx_old->stream) { - if (false == pipe_ctx->tg->funcs->enable_crtc( - pipe_ctx->tg)) { + if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc( + pipe_ctx->stream_res.tg)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } @@ -1073,7 +1073,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) pipe_ctx->stream_enc->funcs->setup_stereo_sync( pipe_ctx->stream_enc, - pipe_ctx->tg->inst, + pipe_ctx->stream_res.tg->inst, stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); @@ -1359,7 +1359,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, */ for (i = 0; i < num_pipes; i++) { - pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, ¶ms); + pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms); } } @@ -1372,7 +1372,7 @@ static void get_position(struct pipe_ctx **pipe_ctx, /* TODO: handle pipes > 1 */ for (i = 0; i < num_pipes; i++) - pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position); + pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); } static void set_static_screen_control(struct pipe_ctx **pipe_ctx, @@ -1393,8 +1393,8 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, #endif for (i = 0; i < num_pipes; i++) - pipe_ctx[i]->tg->funcs-> - set_static_screen_control(pipe_ctx[i]->tg, value); + pipe_ctx[i]->stream_res.tg->funcs-> + set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); } /* unit: in_khz before mode set, get pixel clock from context. ASIC register @@ -1646,12 +1646,12 @@ static void dce110_reset_hw_ctx_wrap( if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { core_link_disable_stream(pipe_ctx_old); - pipe_ctx_old->tg->funcs->set_blank(pipe_ctx_old->tg, true); - if (!hwss_wait_for_blank_complete(pipe_ctx_old->tg)) { + pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); + if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { dm_error("DC: failed to blank crtc!\n"); BREAK_TO_DEBUGGER(); } - pipe_ctx_old->tg->funcs->disable_crtc(pipe_ctx_old->tg); + pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_context->stream_count); resource_unreference_clock_source( @@ -1984,7 +1984,7 @@ static void program_surface_visibility(const struct core_dc *dc, blank_target = true; dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode); - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, blank_target); + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); } @@ -2152,9 +2152,9 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && - pipe_ctx->tg->funcs->is_stereo_left_eye) { + pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye =\ - !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg); + !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); } } @@ -2218,28 +2218,28 @@ static void dce110_enable_timing_synchronization( * Since HW doesn't care which one, we always assign * the 1st one in the group. */ gsl_params.gsl_group = 0; - gsl_params.gsl_master = grouped_pipes[0]->tg->inst; + gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst; for (i = 0; i < group_size; i++) - grouped_pipes[i]->tg->funcs->setup_global_swap_lock( - grouped_pipes[i]->tg, &gsl_params); + grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock( + grouped_pipes[i]->stream_res.tg, &gsl_params); /* Reset slave controllers on master VSync */ DC_SYNC_INFO("GSL: enabling trigger-reset\n"); for (i = 1 /* skip the master */; i < group_size; i++) - grouped_pipes[i]->tg->funcs->enable_reset_trigger( - grouped_pipes[i]->tg, gsl_params.gsl_group); + grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( + grouped_pipes[i]->stream_res.tg, gsl_params.gsl_group); for (i = 1 /* skip the master */; i < group_size; i++) { DC_SYNC_INFO("GSL: waiting for reset to occur.\n"); - wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->tg); + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); /* Regardless of success of the wait above, remove the reset or * the driver will start timing out on Display requests. */ DC_SYNC_INFO("GSL: disabling trigger-reset.\n"); - grouped_pipes[i]->tg->funcs->disable_reset_trigger(grouped_pipes[i]->tg); + grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(grouped_pipes[i]->stream_res.tg); } @@ -2247,7 +2247,7 @@ static void dce110_enable_timing_synchronization( * is that the sync'ed displays will not drift out of sync over time*/ DC_SYNC_INFO("GSL: Restoring register states.\n"); for (i = 0; i < group_size; i++) - grouped_pipes[i]->tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->tg); + grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg); DC_SYNC_INFO("GSL: Set-up complete.\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 4b7bce2427a8..94058ee16029 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1016,7 +1016,7 @@ static struct pipe_ctx *dce110_acquire_underlay( if (res_ctx->pipe_ctx[underlay_idx].stream) return NULL; - pipe_ctx->tg = pool->timing_generators[underlay_idx]; + pipe_ctx->stream_res.tg = pool->timing_generators[underlay_idx]; pipe_ctx->plane_res.mi = pool->mis[underlay_idx]; /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; @@ -1040,12 +1040,12 @@ static struct pipe_ctx *dce110_acquire_underlay( * need to be enabled */ - pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->program_timing(pipe_ctx->stream_res.tg, &stream->timing, false); - pipe_ctx->tg->funcs->enable_advanced_request( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->enable_advanced_request( + pipe_ctx->stream_res.tg, true, &stream->timing); @@ -1057,8 +1057,8 @@ static struct pipe_ctx *dce110_acquire_underlay( color_space_to_black_color(dc, COLOR_SPACE_YCBCR601, &black_color); - pipe_ctx->tg->funcs->set_blank_color( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, &black_color); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2db6b46baa6c..99ef0f25492c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -699,7 +699,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( /* HW program guide assume display already disable * by unplug sequence. OTG assume stop. */ - pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, true); + pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true); if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, @@ -708,15 +708,15 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } - pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; - pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; - pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; - pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; + pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; + pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; + pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; + pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; - pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal; - pipe_ctx->tg->funcs->program_timing( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->program_timing( + pipe_ctx->stream_res.tg, &stream->timing, true); @@ -729,7 +729,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( /* TODO: OPP FMT, ABM. etc. should be done here. */ /* or FPGA now. instance 0 only. TODO: move to opp.c */ - inst_offset = reg_offsets[pipe_ctx->tg->inst].fmt; + inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt; pipe_ctx->stream_res.opp->funcs->opp_program_fmt( pipe_ctx->stream_res.opp, @@ -739,15 +739,15 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( /* program otg blank color */ color_space = stream->output_color_space; color_space_to_black_color(dc, color_space, &black_color); - pipe_ctx->tg->funcs->set_blank_color( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, &black_color); - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true); - hwss_wait_for_blank_complete(pipe_ctx->tg); + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); + hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg); /* VTG is within DCHUB command block. DCFCLK is always on */ - if (false == pipe_ctx->tg->funcs->enable_crtc(pipe_ctx->tg)) { + if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } @@ -787,9 +787,9 @@ static void reset_back_end_for_pipe( * parent pipe. */ if (pipe_ctx->top_pipe == NULL) { - pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg); + pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); - pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, false); + pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) @@ -807,7 +807,7 @@ static void reset_back_end_for_pipe( pipe_ctx->stream = NULL; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset back end for pipe %d, tg:%d\n", - pipe_ctx->pipe_idx, pipe_ctx->tg->inst); + pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); } /* trigger HW to start disconnect plane from stream on the next vsync */ @@ -974,7 +974,7 @@ static void reset_hw_ctx_wrap( /* Lock*/ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; - struct timing_generator *tg = cur_pipe_ctx->tg; + struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; if (cur_pipe_ctx->stream) tg->funcs->lock(tg); @@ -995,7 +995,7 @@ static void reset_hw_ctx_wrap( /* Unlock*/ for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; - struct timing_generator *tg = cur_pipe_ctx->tg; + struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; if (cur_pipe_ctx->stream) tg->funcs->unlock(tg); @@ -1488,9 +1488,9 @@ static void dcn10_pipe_control_lock( verify_allow_pstate_change_high(dc->hwseq); if (lock) - pipe->tg->funcs->lock(pipe->tg); + pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg); else - pipe->tg->funcs->unlock(pipe->tg); + pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -1545,8 +1545,8 @@ static void dcn10_enable_timing_synchronization( DC_SYNC_INFO("Setting up OTG reset trigger\n"); for (i = 1; i < group_size; i++) - grouped_pipes[i]->tg->funcs->enable_reset_trigger( - grouped_pipes[i]->tg, grouped_pipes[0]->tg->inst); + grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( + grouped_pipes[i]->stream_res.tg, grouped_pipes[0]->stream_res.tg->inst); DC_SYNC_INFO("Waiting for trigger\n"); @@ -1554,10 +1554,10 @@ static void dcn10_enable_timing_synchronization( /* Need to get only check 1 pipe for having reset as all the others are * synchronized. Look at last pipe programmed to reset. */ - wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->tg); + wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg); for (i = 1; i < group_size; i++) - grouped_pipes[i]->tg->funcs->disable_reset_trigger( - grouped_pipes[i]->tg); + grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( + grouped_pipes[i]->stream_res.tg); DC_SYNC_INFO("Sync complete\n"); } @@ -1700,7 +1700,7 @@ static void dcn10_power_on_fe( HUBP_CLOCK_ENABLE, 1); /* make sure OPP_PIPE_CLOCK_EN = 1 */ - REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->tg->inst], + REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->stream_res.tg->inst], OPP_PIPE_CLOCK_EN, 1); /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ @@ -1920,7 +1920,7 @@ static void update_dchubp_dpp( * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG */ - REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->tg->inst); + REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); update_plane_addr(dc, pipe_ctx); @@ -2012,17 +2012,17 @@ static void program_all_pipe_in_tree( verify_allow_pstate_change_high(dc->hwseq); } - pipe_ctx->tg->funcs->lock(pipe_ctx->tg); + pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); - pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; - pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; - pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; - pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; - pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal; + pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; + pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; + pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; + pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; + pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal; - pipe_ctx->tg->funcs->program_global_sync( - pipe_ctx->tg); - pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg); + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, !is_pipe_tree_visible(pipe_ctx)); } if (pipe_ctx->plane_state != NULL) { @@ -2098,20 +2098,20 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->tg->inst == be_idx) { + if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need * to lock it back here. Messy, need rework. */ - pipe_ctx->tg->funcs->lock(pipe_ctx->tg); + pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); } } if ((!pipe_ctx->plane_state && old_pipe_ctx->plane_state) || (!pipe_ctx->stream && old_pipe_ctx->stream)) { - if (old_pipe_ctx->tg->inst != be_idx) + if (old_pipe_ctx->stream_res.tg->inst != be_idx) continue; if (!old_pipe_ctx->top_pipe) { @@ -2279,7 +2279,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, * some GSL stuff */ for (i = 0; i < num_pipes; i++) { - pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, ¶ms); + pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms); } } @@ -2292,7 +2292,7 @@ static void get_position(struct pipe_ctx **pipe_ctx, /* TODO: handle pipes > 1 */ for (i = 0; i < num_pipes; i++) - pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position); + pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); } static void set_static_screen_control(struct pipe_ctx **pipe_ctx, @@ -2307,8 +2307,8 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, value |= 0x2; for (i = 0; i < num_pipes; i++) - pipe_ctx[i]->tg->funcs-> - set_static_screen_control(pipe_ctx[i]->tg, value); + pipe_ctx[i]->stream_res.tg->funcs-> + set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); } static void set_plane_config( @@ -2369,8 +2369,8 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) flags.PROGRAM_STEREO == 1 ? true:false, stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false); - pipe_ctx->tg->funcs->program_stereo( - pipe_ctx->tg, + pipe_ctx->stream_res.tg->funcs->program_stereo( + pipe_ctx->stream_res.tg, &stream->timing, &flags); @@ -2469,7 +2469,7 @@ static bool dcn10_dummy_display_power_gating( void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) { struct dc_plane_state *plane_state = pipe_ctx->plane_state; - struct timing_generator *tg = pipe_ctx->tg; + struct timing_generator *tg = pipe_ctx->stream_res.tg; if (plane_state->ctx->dc->debug.sanity_checks) { struct core_dc *dc = DC_TO_CORE(plane_state->ctx->dc); @@ -2496,7 +2496,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye = - !tg->funcs->is_stereo_left_eye(pipe_ctx->tg); + !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index e15eec315228..bb9a42d0a147 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -960,7 +960,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( return false; idle_pipe->stream = head_pipe->stream; - idle_pipe->tg = head_pipe->tg; + idle_pipe->stream_res.tg = head_pipe->stream_res.tg; idle_pipe->stream_res.opp = head_pipe->stream_res.opp; idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 24a525495bfc..488ade37e353 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -154,6 +154,7 @@ struct resource_pool { struct stream_resource { struct output_pixel_processor *opp; + struct timing_generator *tg; }; struct plane_resource { @@ -171,8 +172,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct timing_generator *tg; - struct stream_encoder *stream_enc; struct display_clock *dis_clk; struct clock_source *clock_source; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 52361d1472fa..24e47eb8cf3f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -214,7 +214,7 @@ bool dce110_vblank_set( uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; struct timing_generator *tg = - core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].tg; + core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; if (enable) { if (!tg->funcs->arm_vert_intr(tg, 2)) { -- GitLab From 8e9c4c8cf35ff23aafc69f9ef4c9cc471dac4094 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 14:36:12 -0400 Subject: [PATCH 0733/2898] drm/amd/display: Move stream_enc to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->stream_enc/pipes->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->stream_enc->/ctx->stream_res\.stream_enc->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->stream_enc/pipe->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->stream_enc/pipe_ctx->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.stream_enc/pipe_ctx\[pipe_offset\]\.stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[i\]->stream_enc/grouped_pipes\[i\]->stream_^Cs\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[0\]->stream_enc/grouped_pipes\[0\]->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[1\]->stream_enc/grouped_pipes\[1\]->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]->stream_enc/pipe_ctx\[i\]->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx_old->stream_enc/pipe_ctx_old->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_set\[j\]->stream_enc/pipe_set\[j\]->stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]\.stream_enc/pipe_ctx\[i\]\.stream_res\.stream_enc/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipes\[i\]\.stream_enc/pipes\[i\]\.stream_res\.stream_enc/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 12 ++-- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- .../drm/amd/display/dc/core/dc_link_hwss.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 16 ++--- .../display/dc/dce110/dce110_hw_sequencer.c | 72 +++++++++---------- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 61c2a210c123..748e709c611f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -161,7 +161,7 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe->stream == stream && pipe->stream_enc) { + if (pipe->stream == stream && pipe->stream_res.stream_enc) { core_dc->hwss.set_drr(&pipe, 1, vmin, vmax); /* build and update the info frame */ @@ -189,7 +189,7 @@ static bool stream_get_crtc_position(struct dc *dc, struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; - if (pipe->stream == stream && pipe->stream_enc) { + if (pipe->stream == stream && pipe->stream_res.stream_enc) { core_dc->hwss.get_position(&pipe, 1, &position); *v_pos = position.vertical_count; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2c43edf2c7c4..6a3d2ad97d5d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1311,8 +1311,8 @@ static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) /* un-mute audio */ /* TODO: audio should be per stream rather than per link */ - pipe_ctx->stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_enc, false); + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, false); } return status; @@ -1699,7 +1699,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; - struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; + struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; @@ -1718,7 +1718,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) &proposed_table, true)) { update_mst_stream_alloc_table( - link, pipe_ctx->stream_enc, &proposed_table); + link, pipe_ctx->stream_res.stream_enc, &proposed_table); } else dm_logger_write(link->ctx->logger, LOG_WARNING, @@ -1781,7 +1781,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct link_encoder *link_encoder = link->link_enc; - struct stream_encoder *stream_encoder = pipe_ctx->stream_enc; + struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0); uint8_t i; @@ -1808,7 +1808,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) false)) { update_mst_stream_alloc_table( - link, pipe_ctx->stream_enc, &proposed_table); + link, pipe_ctx->stream_res.stream_enc, &proposed_table); } else { dm_logger_write(link->ctx->logger, LOG_WARNING, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index eda25942aea0..3d296b1d118f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2464,7 +2464,7 @@ bool dc_link_dp_set_test_pattern( * MuteAudioEndpoint(pPathMode->pDisplayPath, true); */ /* Blank stream */ - pipes->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc); + pipes->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); } dp_set_hw_test_pattern(link, test_pattern, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index f2f57a75f864..7d52c6c7cf89 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -243,12 +243,12 @@ void dp_retrain_link_dp_test(struct dc_link *link, if (pipes[i].stream != NULL && pipes[i].stream->sink != NULL && pipes[i].stream->sink->link != NULL && - pipes[i].stream_enc != NULL && + pipes[i].stream_res.stream_enc != NULL && pipes[i].stream->sink->link == link) { dm_delay_in_microseconds(link->ctx, 100); - pipes[i].stream_enc->funcs->dp_blank( - pipes[i].stream_enc); + pipes[i].stream_res.stream_enc->funcs->dp_blank( + pipes[i].stream_res.stream_enc); /* disable any test pattern that might be active */ dp_set_hw_test_pattern(link, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 5326713bf3fb..13feff1003d8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -925,7 +925,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( int i; for (i = 0; i < MAX_PIPES; i++) { if (res_ctx->pipe_ctx[i].stream == stream && - res_ctx->pipe_ctx[i].stream_enc) { + res_ctx->pipe_ctx[i].stream_res.stream_enc) { return &res_ctx->pipe_ctx[i]; break; } @@ -1096,7 +1096,7 @@ bool resource_attach_surfaces_to_context( if (tail_pipe) { free_pipe->stream_res.tg = tail_pipe->stream_res.tg; free_pipe->stream_res.opp = tail_pipe->stream_res.opp; - free_pipe->stream_enc = tail_pipe->stream_enc; + free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; free_pipe->audio = tail_pipe->audio; free_pipe->clock_source = tail_pipe->clock_source; free_pipe->top_pipe = tail_pipe; @@ -1461,12 +1461,12 @@ enum dc_status resource_map_pool_resources( copy_pipe_ctx(old_pipe_ctx, pipe_ctx); /* Split pipe resource, do not acquire back end */ - if (!pipe_ctx->stream_enc) + if (!pipe_ctx->stream_res.stream_enc) continue; set_stream_engine_in_use( &context->res_ctx, pool, - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc); /* Switch to dp clock source only if there is * no non dp stream that shares the same timing @@ -1503,16 +1503,16 @@ enum dc_status resource_map_pool_resources( pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; - pipe_ctx->stream_enc = + pipe_ctx->stream_res.stream_enc = find_first_free_match_stream_enc_for_link( &context->res_ctx, pool, stream); - if (!pipe_ctx->stream_enc) + if (!pipe_ctx->stream_res.stream_enc) return DC_NO_STREAM_ENG_RESOURCE; set_stream_engine_in_use( &context->res_ctx, pool, - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc); /* TODO: Add check if ASIC support and EDID audio */ if (!stream->sink->converter_disable_audio && @@ -2382,7 +2382,7 @@ bool pipe_need_reprogram( && pipe_ctx_old->stream != pipe_ctx->stream) return true; - if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc) + if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) return true; if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1d7c7fb668be..48d151039fe8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -659,7 +659,7 @@ static enum dc_status bios_parser_crtc_source_select( struct bp_crtc_source_select crtc_source_select = {0}; const struct dc_sink *sink = pipe_ctx->stream->sink; - crtc_source_select.engine_id = pipe_ctx->stream_enc->id; + crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id; crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1; /*TODO: Need to un-hardcode color depth, dp_audio and account for * the case where signal and sink signal is different (translator @@ -684,16 +684,16 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) { ASSERT(pipe_ctx->stream); - if (pipe_ctx->stream_enc == NULL) + if (pipe_ctx->stream_res.stream_enc == NULL) return; /* this is not root pipe */ if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->update_hdmi_info_packets( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( + pipe_ctx->stream_res.stream_enc, &pipe_ctx->encoder_info_frame); else if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->update_dp_info_packets( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( + pipe_ctx->stream_res.stream_enc, &pipe_ctx->encoder_info_frame); } @@ -731,7 +731,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) /* enable audio only within mode set */ if (pipe_ctx->audio != NULL) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); } /* For MST, there are multiply stream go to only one link. @@ -739,7 +739,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) * disconnect them during disable_stream * BY this, it is logic clean to separate stream and link */ link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, - pipe_ctx->stream_enc->id, true); + pipe_ctx->stream_res.stream_enc->id, true); } @@ -752,11 +752,11 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_audio_disable( - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( + pipe_ctx->stream_res.stream_enc); else - pipe_ctx->stream_enc->funcs->hdmi_audio_disable( - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( + pipe_ctx->stream_res.stream_enc); pipe_ctx->audio = NULL; @@ -768,24 +768,24 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) } if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets( - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( + pipe_ctx->stream_res.stream_enc); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->stop_dp_info_packets( - pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( + pipe_ctx->stream_res.stream_enc); - pipe_ctx->stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_enc, true); + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, true); /* blank at encoder level */ if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, - pipe_ctx->stream_enc->id, + pipe_ctx->stream_res.stream_enc->id, false); } @@ -799,14 +799,14 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, params.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; - pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, ¶ms); + pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); } void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) { - if (pipe_ctx != NULL && pipe_ctx->stream_enc != NULL) - pipe_ctx->stream_enc->funcs->set_avmute(pipe_ctx->stream_enc, enable); + if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL) + pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable); } static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) @@ -834,7 +834,7 @@ static void build_audio_output( struct audio_output *audio_output) { const struct dc_stream_state *stream = pipe_ctx->stream; - audio_output->engine_id = pipe_ctx->stream_enc->id; + audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id; audio_output->signal = pipe_ctx->stream->signal; @@ -1071,8 +1071,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream->signal); if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) - pipe_ctx->stream_enc->funcs->setup_stereo_sync( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync( + pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst, stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); @@ -1084,21 +1084,21 @@ static enum dc_status apply_single_controller_ctx_to_hw( &stream->clamping); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_set_stream_attribute( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, &stream->timing, stream->output_color_space); if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, &stream->timing, stream->phy_pix_clk, pipe_ctx->audio != NULL); if (dc_is_dvi_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, &stream->timing, (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? true : false); @@ -1860,13 +1860,13 @@ enum dc_status dce110_apply_ctx_to_hw( build_audio_output(pipe_ctx, &audio_output); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_enc->funcs->dp_audio_setup( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_res.stream_enc, pipe_ctx->audio->inst, &pipe_ctx->stream->audio_info); else - pipe_ctx->stream_enc->funcs->hdmi_audio_setup( - pipe_ctx->stream_enc, + pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( + pipe_ctx->stream_res.stream_enc, pipe_ctx->audio->inst, &pipe_ctx->stream->audio_info, &audio_output.crtc_info); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 99ef0f25492c..16ac96358620 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -770,7 +770,7 @@ static void reset_back_end_for_pipe( { int i; - if (pipe_ctx->stream_enc == NULL) { + if (pipe_ctx->stream_res.stream_enc == NULL) { pipe_ctx->stream = NULL; return; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 488ade37e353..4d35c6d120a7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -155,6 +155,7 @@ struct resource_pool { struct stream_resource { struct output_pixel_processor *opp; struct timing_generator *tg; + struct stream_encoder *stream_enc; }; struct plane_resource { @@ -172,7 +173,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct stream_encoder *stream_enc; struct display_clock *dis_clk; struct clock_source *clock_source; -- GitLab From 0b73b84cf59334e48d56e5ef5e121f4ecd02be44 Mon Sep 17 00:00:00 2001 From: Kenny Tsao Date: Sun, 30 Jul 2017 16:17:49 -0400 Subject: [PATCH 0734/2898] drm/amd/display: remove remaining DCN1 guard Signed-off-by: Kenny Tsao Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index a0531b3aa6a1..9a97d8ee7971 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -130,7 +130,6 @@ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ HWSEQ_PHYPLL_REG_LIST(CRTC) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_REG_LIST()\ HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ HWSEQ_PHYPLL_REG_LIST(OTG), \ @@ -208,9 +207,7 @@ SR(D2VGA_CONTROL), \ SR(D3VGA_CONTROL), \ SR(D4VGA_CONTROL) -#endif -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ SR(DCHUBBUB_SDPIF_FB_TOP),\ @@ -219,7 +216,6 @@ SR(DCHUBBUB_SDPIF_AGP_BASE),\ SR(DCHUBBUB_SDPIF_AGP_BOT),\ SR(DCHUBBUB_SDPIF_AGP_TOP) -#endif struct dce_hwseq_registers { @@ -238,7 +234,6 @@ struct dce_hwseq_registers { uint32_t DCHUB_AGP_BOT; uint32_t DCHUB_AGP_TOP; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) uint32_t OTG_GLOBAL_SYNC_STATUS[4]; uint32_t DCHUBP_CNTL[4]; uint32_t HUBP_CLK_CNTL[4]; @@ -317,7 +312,6 @@ struct dce_hwseq_registers { uint32_t D2VGA_CONTROL; uint32_t D3VGA_CONTROL; uint32_t D4VGA_CONTROL; -#endif }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -386,7 +380,6 @@ struct dce_hwseq_registers { HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh) -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh), \ @@ -429,9 +422,7 @@ struct dce_hwseq_registers { HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) -#endif -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #define HWSEQ_DCN1_MASK_SH_LIST(mask_sh)\ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ HWS_SF1(OTG0_, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh), \ @@ -442,7 +433,6 @@ struct dce_hwseq_registers { HWS_SF(, DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh), \ HWS_SF(, DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh) -#endif #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ -- GitLab From afaacef482759215681ad0a8c6a8b60cc7d29592 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 14:59:17 -0400 Subject: [PATCH 0735/2898] drm/amd/display: Move audio to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->audio/pipes->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_with_clk_src->audio/pipe_with_clk_src->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->audio->/ctx->stream_res\.audio->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->audio/pipe->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->audio/pipe_ctx->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.audio/pipe_ctx\[pipe_offset\]\.stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[i\]->audio/grouped_pipes\[i\]->stream_^Cs\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[0\]->audio/grouped_pipes\[0\]->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[1\]->audio/grouped_pipes\[1\]->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]->audio/pipe_ctx\[i\]->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx_old->audio/pipe_ctx_old->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_set\[j\]->audio/pipe_set\[j\]->stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]\.audio/pipe_ctx\[i\]\.stream_res\.audio/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipes\[i\]\.audio/pipes\[i\]\.stream_res\.audio/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +-- .../gpu/drm/amd/display/dc/core/dc_resource.c | 12 +++---- .../display/dc/dce110/dce110_hw_sequencer.c | 32 +++++++++---------- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 +- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 6a3d2ad97d5d..9665fc127fe2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1305,9 +1305,9 @@ static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) break; } - if (pipe_ctx->audio && status == DC_OK) { + if (pipe_ctx->stream_res.audio && status == DC_OK) { /* notify audio driver for audio modes of monitor */ - pipe_ctx->audio->funcs->az_enable(pipe_ctx->audio); + pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); /* un-mute audio */ /* TODO: audio should be per stream rather than per link */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 13feff1003d8..5c1d3c568090 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1097,7 +1097,7 @@ bool resource_attach_surfaces_to_context( free_pipe->stream_res.tg = tail_pipe->stream_res.tg; free_pipe->stream_res.opp = tail_pipe->stream_res.opp; free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; - free_pipe->audio = tail_pipe->audio; + free_pipe->stream_res.audio = tail_pipe->stream_res.audio; free_pipe->clock_source = tail_pipe->clock_source; free_pipe->top_pipe = tail_pipe; tail_pipe->bottom_pipe = free_pipe; @@ -1481,7 +1481,7 @@ enum dc_status resource_map_pool_resources( pipe_ctx->clock_source); set_audio_in_use(&context->res_ctx, pool, - pipe_ctx->audio); + pipe_ctx->stream_res.audio); } } @@ -1518,7 +1518,7 @@ enum dc_status resource_map_pool_resources( if (!stream->sink->converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && stream->audio_info.mode_count) { - pipe_ctx->audio = find_first_free_audio( + pipe_ctx->stream_res.audio = find_first_free_audio( &context->res_ctx, pool); /* @@ -1526,10 +1526,10 @@ enum dc_status resource_map_pool_resources( * There are asics which has number of audio * resources less then number of pipes */ - if (pipe_ctx->audio) + if (pipe_ctx->stream_res.audio) set_audio_in_use( &context->res_ctx, pool, - pipe_ctx->audio); + pipe_ctx->stream_res.audio); } context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; @@ -2375,7 +2375,7 @@ bool pipe_need_reprogram( if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) return true; - if (pipe_ctx_old->audio != pipe_ctx->audio) + if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) return true; if (pipe_ctx_old->clock_source != pipe_ctx->clock_source diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 48d151039fe8..ef5d496656e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -729,7 +729,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) tg->funcs->set_early_control(tg, early_control); /* enable audio only within mode set */ - if (pipe_ctx->audio != NULL) { + if (pipe_ctx->stream_res.audio != NULL) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); } @@ -748,8 +748,8 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; - if (pipe_ctx->audio) { - pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio); + if (pipe_ctx->stream_res.audio) { + pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( @@ -758,7 +758,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); - pipe_ctx->audio = NULL; + pipe_ctx->stream_res.audio = NULL; /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ @@ -1094,7 +1094,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.stream_enc, &stream->timing, stream->phy_pix_clk, - pipe_ctx->audio != NULL); + pipe_ctx->stream_res.audio != NULL); if (dc_is_dvi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute( @@ -1792,13 +1792,13 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) continue; - if (pipe_ctx->audio != NULL) { + if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; build_audio_output(pipe_ctx, &audio_output); - pipe_ctx->audio->funcs->wall_dto_setup( - pipe_ctx->audio, + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio, pipe_ctx->stream->signal, &audio_output.crtc_info, &audio_output.pll_info); @@ -1820,13 +1820,13 @@ enum dc_status dce110_apply_ctx_to_hw( if (!dc_is_dp_signal(pipe_ctx->stream->signal)) continue; - if (pipe_ctx->audio != NULL) { + if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; build_audio_output(pipe_ctx, &audio_output); - pipe_ctx->audio->funcs->wall_dto_setup( - pipe_ctx->audio, + pipe_ctx->stream_res.audio->funcs->wall_dto_setup( + pipe_ctx->stream_res.audio, pipe_ctx->stream->signal, &audio_output.crtc_info, &audio_output.pll_info); @@ -1853,7 +1853,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->top_pipe) continue; - if (context->res_ctx.pipe_ctx[i].audio != NULL) { + if (context->res_ctx.pipe_ctx[i].stream_res.audio != NULL) { struct audio_output audio_output; @@ -1862,17 +1862,17 @@ enum dc_status dce110_apply_ctx_to_hw( if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( pipe_ctx->stream_res.stream_enc, - pipe_ctx->audio->inst, + pipe_ctx->stream_res.audio->inst, &pipe_ctx->stream->audio_info); else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( pipe_ctx->stream_res.stream_enc, - pipe_ctx->audio->inst, + pipe_ctx->stream_res.audio->inst, &pipe_ctx->stream->audio_info, &audio_output.crtc_info); - pipe_ctx->audio->funcs->az_configure( - pipe_ctx->audio, + pipe_ctx->stream_res.audio->funcs->az_configure( + pipe_ctx->stream_res.audio, pipe_ctx->stream->signal, &audio_output.crtc_info, &pipe_ctx->stream->audio_info); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 4d35c6d120a7..6f09653ac2cb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -156,6 +156,7 @@ struct stream_resource { struct output_pixel_processor *opp; struct timing_generator *tg; struct stream_encoder *stream_enc; + struct audio *audio; }; struct plane_resource { @@ -176,8 +177,6 @@ struct pipe_ctx { struct display_clock *dis_clk; struct clock_source *clock_source; - struct audio *audio; - struct pixel_clk_params pix_clk_params; struct pll_settings pll_settings; -- GitLab From 10688217e3af3ec73892139bed3d23a6e1170a14 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 15:17:43 -0400 Subject: [PATCH 0736/2898] drm/amd/display: Move pix_clk_params into stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->pix_clk_params/pipes->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_with_clk_src->pix_clk_params/pipe_with_clk_src->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->pix_clk_params->/ctx->stream_res\.pix_clk_params->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->pix_clk_params/pipe->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->pix_clk_params/pipe_ctx->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.pix_clk_params/pipe_ctx\[pipe_offset\]\.stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[i\]->pix_clk_params/grouped_pipes\[i\]->stream_^Cs\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[0\]->pix_clk_params/grouped_pipes\[0\]->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[1\]->pix_clk_params/grouped_pipes\[1\]->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]->pix_clk_params/pipe_ctx\[i\]->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx_old->pix_clk_params/pipe_ctx_old->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_set\[j\]->pix_clk_params/pipe_set\[j\]->stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]\.pix_clk_params/pipe_ctx\[i\]\.stream_res\.pix_clk_params/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipes\[i\]\.pix_clk_params/pipes\[i\]\.stream_res\.pix_clk_params/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 ++-- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 14 +++++++------- .../drm/amd/display/dc/dce110/dce110_resource.c | 4 ++-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++-- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 ++- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 9665fc127fe2..1279eb1dfc2e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1620,8 +1620,8 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) uint32_t numerator; uint32_t denominator; - bpc = get_color_depth(pipe_ctx->pix_clk_params.color_depth); - kbps = pipe_ctx->pix_clk_params.requested_pix_clk * bpc * 3; + bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth); + kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk * bpc * 3; /* * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 7d52c6c7cf89..822568767f2d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -77,11 +77,11 @@ void dp_enable_link_phy( if (pipes[i].clock_source != NULL && pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { pipes[i].clock_source = dp_cs; - pipes[i].pix_clk_params.requested_pix_clk = + pipes[i].stream_res.pix_clk_params.requested_pix_clk = pipes[i].stream->timing.pix_clk_khz; pipes[i].clock_source->funcs->program_pix_clk( pipes[i].clock_source, - &pipes[i].pix_clk_params, + &pipes[i].stream_res.pix_clk_params, &pipes[i].pll_settings); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ef5d496656e5..93161a92a427 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -870,20 +870,20 @@ static void build_audio_output( stream->timing.display_color_depth; audio_output->crtc_info.requested_pixel_clock = - pipe_ctx->pix_clk_params.requested_pix_clk; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; audio_output->crtc_info.calculated_pixel_clock = - pipe_ctx->pix_clk_params.requested_pix_clk; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; /*for HDMI, audio ACR is with deep color ratio factor*/ if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && audio_output->crtc_info.requested_pixel_clock == stream->timing.pix_clk_khz) { - if (pipe_ctx->pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) { audio_output->crtc_info.requested_pixel_clock = audio_output->crtc_info.requested_pixel_clock/2; audio_output->crtc_info.calculated_pixel_clock = - pipe_ctx->pix_clk_params.requested_pix_clk/2; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2; } } @@ -1003,7 +1003,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, - &pipe_ctx->pix_clk_params, + &pipe_ctx->stream_res.pix_clk_params, &pipe_ctx->pll_settings)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; @@ -1425,9 +1425,9 @@ static uint32_t get_max_pixel_clock_for_all_paths( if (pipe_ctx->top_pipe) continue; - if (pipe_ctx->pix_clk_params.requested_pix_clk > max_pix_clk) + if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk) max_pix_clk = - pipe_ctx->pix_clk_params.requested_pix_clk; + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk; } if (max_pix_clk == 0) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 94058ee16029..c677f98c3516 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -748,10 +748,10 @@ static void get_pixel_clock_parameters( enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); pipe_ctx->clock_source->funcs->get_pix_clk_dividers( pipe_ctx->clock_source, - &pipe_ctx->pix_clk_params, + &pipe_ctx->stream_res.pix_clk_params, &pipe_ctx->pll_settings); resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 16ac96358620..e69839802889 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -703,7 +703,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, - &pipe_ctx->pix_clk_params, + &pipe_ctx->stream_res.pix_clk_params, &pipe_ctx->pll_settings)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; @@ -1910,7 +1910,7 @@ static void update_dchubp_dpp( enable_dppclk( dc->hwseq, pipe_ctx->pipe_idx, - pipe_ctx->pix_clk_params.requested_pix_clk, + pipe_ctx->stream_res.pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); dc->current_context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index bb9a42d0a147..ff2dcb7a491d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -806,11 +806,11 @@ static void build_clamping_params(struct dc_stream_state *stream) static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->pix_clk_params); + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); pipe_ctx->clock_source->funcs->get_pix_clk_dividers( pipe_ctx->clock_source, - &pipe_ctx->pix_clk_params, + &pipe_ctx->stream_res.pix_clk_params, &pipe_ctx->pll_settings); pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 6f09653ac2cb..968835191da8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -157,6 +157,8 @@ struct stream_resource { struct timing_generator *tg; struct stream_encoder *stream_enc; struct audio *audio; + + struct pixel_clk_params pix_clk_params; }; struct plane_resource { @@ -177,7 +179,6 @@ struct pipe_ctx { struct display_clock *dis_clk; struct clock_source *clock_source; - struct pixel_clk_params pix_clk_params; struct pll_settings pll_settings; /*fmt*/ -- GitLab From 96c50c0d0cead772001fd4ab1861594c059e7e0f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 30 Jul 2017 15:58:26 -0400 Subject: [PATCH 0737/2898] drm/amd/display: Move encoder_info_frame to stream_res find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipes->encoder_info_frame/pipes->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_with_clk_src->encoder_info_frame/pipe_with_clk_src->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/ctx->encoder_info_frame->/ctx->stream_res\.encoder_info_frame->/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe->encoder_info_frame/pipe->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i 's/pipe_ctx->encoder_info_frame/pipe_ctx->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[pipe_offset\]\.encoder_info_frame/pipe_ctx\[pipe_offset\]\.stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[i\]->encoder_info_frame/grouped_pipes\[i\]->stream_^Cs\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[0\]->encoder_info_frame/grouped_pipes\[0\]->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/grouped_pipes\[1\]->encoder_info_frame/grouped_pipes\[1\]->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]->encoder_info_frame/pipe_ctx\[i\]->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx_old->encoder_info_frame/pipe_ctx_old->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_set\[j\]->encoder_info_frame/pipe_set\[j\]->stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipe_ctx\[i\]\.encoder_info_frame/pipe_ctx\[i\]\.stream_res\.encoder_info_frame/g' find -name Makefile -o -name Kconfig -o -name "*.c" -o -name "*.h" \ -o -name "*.cpp" -o -name "*.hpp" | \ xargs sed -i \ 's/pipes\[i\]\.encoder_info_frame/pipes\[i\]\.stream_res\.encoder_info_frame/g' Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 5c1d3c568090..30237f049c99 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2267,7 +2267,7 @@ struct clock_source *dc_resource_find_first_free_pll( void resource_build_info_frame(struct pipe_ctx *pipe_ctx) { enum signal_type signal = SIGNAL_TYPE_NONE; - struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame; + struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; /* default all packets to invalid */ info->avi.valid = false; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 93161a92a427..d3368a8bd1d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -690,11 +690,11 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_res.stream_enc, - &pipe_ctx->encoder_info_frame); + &pipe_ctx->stream_res.encoder_info_frame); else if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( pipe_ctx->stream_res.stream_enc, - &pipe_ctx->encoder_info_frame); + &pipe_ctx->stream_res.encoder_info_frame); } void dce110_enable_stream(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 968835191da8..b3005629ab21 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -159,6 +159,7 @@ struct stream_resource { struct audio *audio; struct pixel_clk_params pix_clk_params; + struct encoder_info_frame encoder_info_frame; }; struct plane_resource { @@ -181,9 +182,6 @@ struct pipe_ctx { struct pll_settings pll_settings; - /*fmt*/ - struct encoder_info_frame encoder_info_frame; - uint8_t pipe_idx; struct pipe_ctx *top_pipe; -- GitLab From 6dd28867b1f964226c1c0b1600ecbfa4f8f98bba Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 31 Jul 2017 15:35:01 -0400 Subject: [PATCH 0738/2898] drm/amd/display: fix PHYCLK in formula. Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/dcn_calc_auto.c | 11 ++++++++ .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 28 +++++++++++-------- .../gpu/drm/amd/display/dc/inc/dcn_calcs.h | 5 ++++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index fb5d8db33a82..e8086c09eb6f 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -266,6 +266,17 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) v->required_output_bw = v->pixel_clock[k] * 3.0; } if (v->output[k] == dcn_bw_hdmi) { + v->required_phyclk[k] = v->required_output_bw; + switch (v->output_deep_color[k]) { + case dcn_bw_encoder_10bpc: + v->required_phyclk[k] = v->required_phyclk[k] * 5.0 / 4; + break; + case dcn_bw_encoder_12bpc: + v->required_phyclk[k] = v->required_phyclk[k] * 3.0 / 2; + break; + default: + break; + } v->required_phyclk[k] = v->required_output_bw / 3.0; } else if (v->output[k] == dcn_bw_dp) { diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1922c13d6f22..13b7d8872f97 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -856,18 +856,6 @@ bool dcn_validate_bandwidth( - pipe->stream->timing.v_front_porch; v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; - if (pipe->stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) { - switch (pipe->stream->timing.display_color_depth) { - case COLOR_DEPTH_101010: - v->pixel_clock[input_idx] = (v->pixel_clock[input_idx] * 30) / 24; - break; - case COLOR_DEPTH_121212: - v->pixel_clock[input_idx] = (v->pixel_clock[input_idx] * 36) / 24; - break; - default: - break; - } - } if (!pipe->plane_state) { v->dcc_enable[input_idx] = dcn_bw_yes; @@ -938,6 +926,22 @@ bool dcn_validate_bandwidth( PIXEL_ENCODING_YCBCR420 ? dcn_bw_420 : dcn_bw_444; v->output[input_idx] = pipe->stream->sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ? dcn_bw_hdmi : dcn_bw_dp; + v->output_deep_color[input_idx] = dcn_bw_encoder_8bpc; + if (v->output[input_idx] == dcn_bw_hdmi) { + switch (pipe->stream->timing.display_color_depth) { + case COLOR_DEPTH_101010: + v->output_deep_color[input_idx] = dcn_bw_encoder_10bpc; + break; + case COLOR_DEPTH_121212: + v->output_deep_color[input_idx] = dcn_bw_encoder_12bpc; + break; + case COLOR_DEPTH_161616: + v->output_deep_color[input_idx] = dcn_bw_encoder_16bpc; + break; + default: + break; + } + } input_idx++; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index b6cc07450f1f..7e8abcd60d12 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -89,6 +89,10 @@ enum dcn_bw_defs { dcn_bw_supported_in_v_blank, dcn_bw_not_supported, dcn_bw_na, + dcn_bw_encoder_8bpc, + dcn_bw_encoder_10bpc, + dcn_bw_encoder_12bpc, + dcn_bw_encoder_16bpc, }; /*bounding box parameters*/ @@ -182,6 +186,7 @@ struct dcn_bw_internal_vars { enum dcn_bw_defs source_pixel_format[number_of_planes_minus_one + 1]; enum dcn_bw_defs source_surface_mode[number_of_planes_minus_one + 1]; enum dcn_bw_defs output_format[number_of_planes_minus_one + 1]; + enum dcn_bw_defs output_deep_color[number_of_planes_minus_one + 1]; enum dcn_bw_defs output[number_of_planes_minus_one + 1]; float scaler_rec_out_width[number_of_planes_minus_one + 1]; float scaler_recout_height[number_of_planes_minus_one + 1]; -- GitLab From 4d128c2f8a0d90f6e693c62423a678af4fc34bf5 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 27 Jul 2017 15:50:26 -0400 Subject: [PATCH 0739/2898] drm/amd/display: Add surface to dm_plane_state if fb reserve fails Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 08567b3631cf..41731943b4e7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4707,6 +4707,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dc_plane_state = dc_create_plane_state(dc); + if (dm_plane_state->dc_state) + dc_plane_state_release(dm_plane_state->dc_state); + + dm_plane_state->dc_state = dc_plane_state; + ret = fill_plane_attributes( plane_crtc->dev->dev_private, dc_plane_state, @@ -4716,12 +4721,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - - if (dm_plane_state->dc_state) - dc_plane_state_release(dm_plane_state->dc_state); - - dm_plane_state->dc_state = dc_plane_state; - add_val_sets_plane(set, set_count, new_acrtc_state->stream, -- GitLab From 9a3329b172d26806477d07da7142925c8643ec9b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 31 Jul 2017 13:15:04 -0400 Subject: [PATCH 0740/2898] drm/amd/display: Fix plane_atomic_check when no dc_state Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 41731943b4e7..0436261243ab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3160,7 +3160,7 @@ int dm_plane_atomic_check(struct drm_plane *plane, struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); if (!dm_plane_state->dc_state) - return true; + return 0; if (dc_validate_plane(dc, dm_plane_state->dc_state)) return 0; -- GitLab From f0f8b2db570bf3cdb6948cadb83e6dad0faf4c37 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 31 Jul 2017 17:27:52 -0400 Subject: [PATCH 0741/2898] drm/amd/display: fix PHYCLK in formula. Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index e8086c09eb6f..626f9cf8aad2 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c @@ -277,7 +277,7 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v) default: break; } - v->required_phyclk[k] = v->required_output_bw / 3.0; + v->required_phyclk[k] = v->required_phyclk[k] / 3.0; } else if (v->output[k] == dcn_bw_dp) { v->required_phyclk[k] = v->required_output_bw / 4.0; -- GitLab From 497de04ffe666c2f006ab318aa99cde25cc1176a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 30 Jun 2017 11:52:14 -0400 Subject: [PATCH 0742/2898] drm/amd/display: do not report min_memory_clock_khz to pplib for dce8 & 10 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index 843f50a08e21..c638f47acefc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -114,8 +114,8 @@ static void dce100_pplib_apply_display_requirements( pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); - pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz - / MEMORY_TYPE_MULTIPLIER; + /*pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz + / MEMORY_TYPE_MULTIPLIER;*/ dce110_fill_display_configs(context, pp_display_cfg); -- GitLab From a7b06724eeb4ecca0c64e8f734e8ef27001670ca Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 31 Jul 2017 12:09:02 -0400 Subject: [PATCH 0743/2898] drm/amd/display: Fix comment placement for when new_stream is null Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0436261243ab..c89d6089f3c3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4603,6 +4603,13 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, &crtc_state->mode, dm_conn_state); + /* + * we can have no stream on ACTION_SET if a display + * was disconnected during S3, in this case it not and + * error, the OS will be updated after detection, and + * do the right thing on next atomic commit + */ + if (!new_stream) { DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); @@ -4615,14 +4622,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (modeset_required(crtc_state, new_stream, old_acrtc_state->stream)) { - - /* - * we can have no stream on ACTION_SET if a display - * was disconnected during S3, in this case it not and - * error, the OS will be updated after detection, and - * do the right thing on next atomic commit - */ - if (new_acrtc_state->stream) dc_stream_release(new_acrtc_state->stream); -- GitLab From 746e082fdd1c7650322ba4c08652245fcdf83adb Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 1 Aug 2017 13:23:56 -0400 Subject: [PATCH 0744/2898] drm/amd/display: update predefined latency for Rv1_F0 Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 10 ++++++++++ drivers/gpu/drm/amd/display/include/dal_asic_id.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index ff2dcb7a491d..6006fb4799c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1323,6 +1323,13 @@ static bool construct( dc->dcn_ip = dcn10_ip_defaults; dc->dcn_soc = dcn10_soc_defaults; + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc.urgent_latency = 3; + dc->public.debug.disable_dmcu = true; + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 41.60f; + } + + dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; ASSERT(dc->dcn_soc.number_of_channels < 3); if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ @@ -1333,6 +1340,9 @@ static bool construct( dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = 17.066f; dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = 14.933f; dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 20.80f; + } } if (!dc->public.debug.disable_pplib_clock_request) diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index af9fa66b32b8..14e3146a0cb2 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -115,6 +115,9 @@ #define RAVEN_UNKNOWN 0xFF #define ASIC_REV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) +#define RAVEN1_F0 0xF0 +#define ASICREV_IS_RV1_F0(eChipRev) ((eChipRev >= RAVEN1_F0) && (eChipRev < RAVEN_UNKNOWN)) + #define FAMILY_RV 142 /* DCN 1*/ -- GitLab From 0d18d7bb80132467a3b88a2fe7277dc1fee65353 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 1 Aug 2017 21:13:24 -0400 Subject: [PATCH 0745/2898] drm/amd/display: fix dlg ttu calculation input Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 13b7d8872f97..67da973c898b 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -401,7 +401,8 @@ static void pipe_ctx_to_e2e_pipe_params ( static void dcn_bw_calc_rq_dlg_ttu( const struct core_dc *dc, const struct dcn_bw_internal_vars *v, - struct pipe_ctx *pipe) + struct pipe_ctx *pipe, + int in_idx) { struct display_mode_lib *dml = (struct display_mode_lib *)(&dc->dml); struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &pipe->dlg_regs; @@ -439,6 +440,21 @@ static void dcn_bw_calc_rq_dlg_ttu( input.clks_cfg.socclk_mhz = v->socclk; input.clks_cfg.voltage = v->voltage_level; // dc->dml.logger = pool->base.logger; + input.dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; + input.dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; + //input[in_idx].dout.output_standard; + switch (v->output_deep_color[in_idx]) { + case dcn_bw_encoder_12bpc: + input.dout.output_bpc = dm_out_12; + break; + case dcn_bw_encoder_10bpc: + input.dout.output_bpc = dm_out_10; + break; + case dcn_bw_encoder_8bpc: + default: + input.dout.output_bpc = dm_out_8; + break; + } /*todo: soc->sr_enter_plus_exit_time??*/ dlg_sys_param.t_srx_delay_us = dc->dcn_ip.dcfclk_cstate_latency / v->dcf_clk_deep_sleep; @@ -487,6 +503,21 @@ static void dcn_dml_wm_override( input[in_idx].clks_cfg.refclk_mhz = pool->ref_clock_inKhz / 1000; input[in_idx].clks_cfg.socclk_mhz = v->socclk; input[in_idx].clks_cfg.voltage = v->voltage_level; + input[in_idx].dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; + input[in_idx].dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; + //input[in_idx].dout.output_standard; + switch (v->output_deep_color[in_idx]) { + case dcn_bw_encoder_12bpc: + input[in_idx].dout.output_bpc = dm_out_12; + break; + case dcn_bw_encoder_10bpc: + input[in_idx].dout.output_bpc = dm_out_10; + break; + case dcn_bw_encoder_8bpc: + default: + input[in_idx].dout.output_bpc = dm_out_8; + break; + } pipe_ctx_to_e2e_pipe_params(pipe, &input[in_idx].pipe); dml_rq_dlg_get_rq_reg( dml, @@ -1060,7 +1091,7 @@ bool dcn_validate_bandwidth( pipe, hsplit_pipe); } - dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); + dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe, input_idx); } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { /* merge previously split pipe */ pipe->bottom_pipe = hsplit_pipe->bottom_pipe; @@ -1073,7 +1104,7 @@ bool dcn_validate_bandwidth( resource_build_scaling_params(pipe); } /* for now important to do this after pipe split for building e2e params */ - dcn_bw_calc_rq_dlg_ttu(dc, v, pipe); + dcn_bw_calc_rq_dlg_ttu(dc, v, pipe, input_idx); } input_idx++; -- GitLab From 9ee20ee6117b84fb6240f0ba5c4deafc23d9a458 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 1 Aug 2017 16:54:48 -0400 Subject: [PATCH 0746/2898] drm/amd/display: Implement tmz surface. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 2 ++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 3c0b47373dfb..778bd5555c7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -66,6 +66,7 @@ enum dc_plane_addr_type { struct dc_plane_address { enum dc_plane_addr_type type; + bool tmz_surface; union { struct{ PHYSICAL_ADDRESS_LOC addr; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 76879f5d7907..0d40fa753036 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -266,6 +266,9 @@ static bool min10_program_surface_flip_and_addr( if (address->grph.addr.quad_part == 0) break; + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + if (address->grph.meta_addr.quad_part != 0) { REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH, @@ -289,6 +292,9 @@ static bool min10_program_surface_flip_and_addr( || address->video_progressive.chroma_addr.quad_part == 0) break; + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + if (address->video_progressive.luma_meta_addr.quad_part != 0) { REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, @@ -328,6 +334,10 @@ static bool min10_program_surface_flip_and_addr( break; if (address->grph_stereo.right_addr.quad_part == 0) break; + + REG_UPDATE(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface); + if (address->grph_stereo.right_meta_addr.quad_part != 0) { REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 4f4e2c0708d5..e2eba25f44ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -303,6 +303,7 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ + MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_TMZ, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ MI_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\ MI_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ @@ -453,6 +454,7 @@ struct dcn_mi_registers { type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH;\ type SURFACE_EARLIEST_INUSE_ADDRESS_C;\ type SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C;\ + type PRIMARY_SURFACE_TMZ;\ type PRIMARY_SURFACE_DCC_EN;\ type PRIMARY_SURFACE_DCC_IND_64B_BLK;\ type DET_BUF_PLANE1_BASE_ADDRESS;\ -- GitLab From 2a8f6ccb665c6ac53afdcf76b2aaa7fc5e513bfc Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 31 Jul 2017 16:32:18 -0400 Subject: [PATCH 0747/2898] drm/amd/display: Clean up cursor code This will also fix disappearing cursor after resume. With this change we'll set cursor attributes, as well as cursor position on every update. The impact is minor. These are sample logs that show timestamps at beginning and end of atomic_check, commit_tail, handle_cursor_update, and before and after cursor_attribute and cursor_position calls: [ 66.800353] hwhw: begin of check [ 66.800377] hwhw: end of check [ 66.800428] hwhw: begin of commit_tail [ 66.800441] hwhw: begin of cursor [ 66.800449] hwhw: begin of cursor_attr [ 66.800468] hwhw: end of cursor_attr [ 66.800484] hwhw: end of cursor_positionr [ 66.800501] hwhw: end of commit_tail [ 66.807139] hwhw: begin of check [ 66.807160] hwhw: end of check [ 66.807206] hwhw: begin of commit_tail [ 66.807217] hwhw: begin of cursor [ 66.807225] hwhw: begin of cursor_attr [ 66.807357] hwhw: end of cursor_attr [ 66.807374] hwhw: end of cursor_positionr [ 66.807392] hwhw: end of commit_tail Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 283 ++++++------------ 1 file changed, 92 insertions(+), 191 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c89d6089f3c3..4535942e8a63 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1647,178 +1647,6 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { .destroy = amdgpu_dm_encoder_destroy, }; -static void dm_set_cursor( - struct amdgpu_crtc *amdgpu_crtc, - uint64_t gpu_addr, - uint32_t width, - uint32_t height) -{ - struct dc_cursor_attributes attributes; - struct dc_cursor_position position; - struct drm_crtc *crtc = &amdgpu_crtc->base; - int x, y; - int xorigin = 0, yorigin = 0; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - amdgpu_crtc->cursor_width = width; - amdgpu_crtc->cursor_height = height; - - attributes.address.high_part = upper_32_bits(gpu_addr); - attributes.address.low_part = lower_32_bits(gpu_addr); - attributes.width = width; - attributes.height = height; - attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; - attributes.rotation_angle = 0; - attributes.attribute_flags.value = 0; - - attributes.pitch = attributes.width; - - x = amdgpu_crtc->cursor_x; - y = amdgpu_crtc->cursor_y; - - /* avivo cursor are offset into the total surface */ - x += crtc->primary->state->src_x >> 16; - y += crtc->primary->state->src_y >> 16; - - if (x < 0) { - xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); - x = 0; - } - if (y < 0) { - yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); - y = 0; - } - - position.enable = true; - position.x = x; - position.y = y; - - position.x_hotspot = xorigin; - position.y_hotspot = yorigin; - - if (!dc_stream_set_cursor_attributes( - acrtc_state->stream, - &attributes)) { - DRM_ERROR("DC failed to set cursor attributes\n"); - } - - if (!dc_stream_set_cursor_position( - acrtc_state->stream, - &position)) { - DRM_ERROR("DC failed to set cursor position\n"); - } -} - -static int dm_crtc_cursor_set( - struct drm_crtc *crtc, - uint64_t address, - uint32_t width, - uint32_t height) -{ - struct dc_cursor_position position; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - int ret; - - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; - - DRM_DEBUG_KMS("%s: crtc_id=%d with size %d to %d \n", - __func__, - amdgpu_crtc->crtc_id, - width, - height); - - if (!address) { - /* turn off cursor */ - position.enable = false; - position.x = 0; - position.y = 0; - - if (acrtc_state->stream) { - /*set cursor visible false*/ - dc_stream_set_cursor_position( - acrtc_state->stream, - &position); - } - goto release; - - } - - if ((width > amdgpu_crtc->max_cursor_width) || - (height > amdgpu_crtc->max_cursor_height)) { - DRM_ERROR( - "%s: bad cursor width or height %d x %d\n", - __func__, - width, - height); - goto release; - } - - /*program new cursor bo to hardware*/ - dm_set_cursor(amdgpu_crtc, address, width, height); - -release: - return ret; - -} - -static int dm_crtc_cursor_move(struct drm_crtc *crtc, - int x, int y) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - int xorigin = 0, yorigin = 0; - struct dc_cursor_position position; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); - - amdgpu_crtc->cursor_x = x; - amdgpu_crtc->cursor_y = y; - - /* avivo cursor are offset into the total surface */ - x += crtc->primary->state->src_x >> 16; - y += crtc->primary->state->src_y >> 16; - - /* - * TODO: for cursor debugging unguard the following - */ -#if 0 - DRM_DEBUG_KMS( - "%s: x %d y %d c->x %d c->y %d\n", - __func__, - x, - y, - crtc->x, - crtc->y); -#endif - - if (x < 0) { - xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); - x = 0; - } - if (y < 0) { - yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); - y = 0; - } - - position.enable = true; - position.x = x; - position.y = y; - - position.x_hotspot = xorigin; - position.y_hotspot = yorigin; - - if (acrtc_state->stream) { - if (!dc_stream_set_cursor_position( - acrtc_state->stream, - &position)) { - DRM_ERROR("DC failed to set cursor position\n"); - return -EINVAL; - } - } - - return 0; -} - static bool fill_rects_from_plane_state( const struct drm_plane_state *state, struct dc_plane_state *plane_state) @@ -3782,34 +3610,107 @@ static void remove_stream( acrtc->enabled = false; } +int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, + struct dc_cursor_position *position) +{ + struct amdgpu_crtc *amdgpu_crtc = amdgpu_crtc = to_amdgpu_crtc(crtc); + int x, y; + int xorigin = 0, yorigin = 0; + + if (!crtc || !plane->state->fb) { + position->enable = false; + position->x = 0; + position->y = 0; + return 0; + } + + if ((plane->state->crtc_w > amdgpu_crtc->max_cursor_width) || + (plane->state->crtc_h > amdgpu_crtc->max_cursor_height)) { + DRM_ERROR("%s: bad cursor width or height %d x %d\n", + __func__, + plane->state->crtc_w, + plane->state->crtc_h); + return -EINVAL; + } + + x = plane->state->crtc_x; + y = plane->state->crtc_y; + /* avivo cursor are offset into the total surface */ + x += crtc->primary->state->src_x >> 16; + y += crtc->primary->state->src_y >> 16; + if (x < 0) { + xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1); + x = 0; + } + if (y < 0) { + yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1); + y = 0; + } + position->enable = true; + position->x = x; + position->y = y; + position->x_hotspot = xorigin; + position->y_hotspot = yorigin; + + return 0; +} + static void handle_cursor_update( struct drm_plane *plane, struct drm_plane_state *old_plane_state) { + struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); + struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; + struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; + struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + uint64_t address = afb ? afb->address : 0; + struct dc_cursor_position position; + struct dc_cursor_attributes attributes; + int ret; + if (!plane->state->fb && !old_plane_state->fb) return; - /* Check if it's a cursor on/off update or just cursor move*/ - if (plane->state->fb == old_plane_state->fb) - dm_crtc_cursor_move( - plane->state->crtc, - plane->state->crtc_x, - plane->state->crtc_y); - else { - struct amdgpu_framebuffer *afb = - to_amdgpu_framebuffer(plane->state->fb); - dm_crtc_cursor_set( - (!!plane->state->fb) ? - plane->state->crtc : - old_plane_state->crtc, - (!!plane->state->fb) ? - afb->address : - 0, - plane->state->crtc_w, - plane->state->crtc_h); + DRM_DEBUG_KMS("%s: crtc_id=%d with size %d to %d\n", + __func__, + amdgpu_crtc->crtc_id, + plane->state->crtc_w, + plane->state->crtc_h); + + ret = get_cursor_position(plane, crtc, &position); + if (ret) + return; + + if (!position.enable) { + /* turn off cursor */ + if (crtc_state && crtc_state->stream) + dc_stream_set_cursor_position(crtc_state->stream, + &position); + return; } -} + amdgpu_crtc->cursor_width = plane->state->crtc_w; + amdgpu_crtc->cursor_height = plane->state->crtc_h; + + attributes.address.high_part = upper_32_bits(address); + attributes.address.low_part = lower_32_bits(address); + attributes.width = plane->state->crtc_w; + attributes.height = plane->state->crtc_h; + attributes.color_format = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA; + attributes.rotation_angle = 0; + attributes.attribute_flags.value = 0; + + attributes.pitch = attributes.width; + + if (!dc_stream_set_cursor_attributes(crtc_state->stream, + &attributes)) + DRM_ERROR("DC failed to set cursor attributes\n"); + + if (crtc_state->stream) + if (!dc_stream_set_cursor_position(crtc_state->stream, + &position)) + DRM_ERROR("DC failed to set cursor position\n"); +} static void prepare_flip_isr(struct amdgpu_crtc *acrtc) { -- GitLab From c10efbd3714bfb6fff8c3b8e2d817028bc25355b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 3 Aug 2017 13:04:44 -0400 Subject: [PATCH 0748/2898] drm/amd/display: fix eDP power down sequence Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_hwss.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 822568767f2d..d19c663c257f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -90,10 +90,13 @@ void dp_enable_link_phy( if (dc_is_dp_sst_signal(signal)) { if (signal == SIGNAL_TYPE_EDP) { link_enc->funcs->power_control(link_enc, true); + link_enc->funcs->enable_dp_output( + link_enc, + link_settings, + clock_source); link_enc->funcs->backlight_control(link_enc, true); - } - - link_enc->funcs->enable_dp_output( + } else + link_enc->funcs->enable_dp_output( link_enc, link_settings, clock_source); @@ -114,10 +117,10 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); + link->link_enc->funcs->disable_output(link->link_enc, signal); link->link_enc->funcs->power_control(link->link_enc, false); - } - - link->link_enc->funcs->disable_output(link->link_enc, signal); + } else + link->link_enc->funcs->disable_output(link->link_enc, signal); /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, -- GitLab From 713950115bc5f964e65f79a7684468c41ed41654 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 08:59:12 -0400 Subject: [PATCH 0749/2898] drm/amd/display: log HW state when we about to encounter DF DPM hang Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 115 +++++++++--------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e69839802889..30ddf920b270 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -52,6 +52,61 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name +static void log_mpc_crc(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dce_hwseq *hws = dc->hwseq; + + if (REG(MPC_CRC_RESULT_GB)) + DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", + REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); + if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) + DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", + REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); +} + +static void dcn10_log_hw_state(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct resource_pool *pool = dc->res_pool; + int i; + + DTN_INFO_BEGIN(); + + DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t rotation \t" + "mirror \t sw_mode \t dcc_en \t blank_en \t ttu_dis \t" + "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); + + for (i = 0; i < pool->pipe_count; i++) { + struct mem_input *mi = pool->mis[i]; + struct dcn_hubp_state s; + + dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); + + DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t %xh \t %xh \t " + "%d \t %d \t %d \t %d \t" + "%d \t %d \t %d \n", + i, + s.pixel_format, + s.inuse_addr_hi, + s.viewport_width, + s.viewport_height, + s.rotation_angle, + s.h_mirror_en, + s.sw_mode, + s.dcc_en, + s.blank_en, + s.ttu_disable, + s.min_ttu_vblank, + s.qos_level_low_wm, + s.qos_level_high_wm); + } + DTN_INFO("\n"); + + log_mpc_crc(dc); + + DTN_INFO_END(); +} static void verify_allow_pstate_change_high( struct dce_hwseq *hws) @@ -118,6 +173,9 @@ static void verify_allow_pstate_change_high( */ REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); forced_pstate_allow = true; + + dcn10_log_hw_state(DC_TO_CORE(hws->ctx->dc)); + BREAK_TO_DEBUGGER(); } @@ -2377,63 +2435,6 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) return; } - -static void log_mpc_crc(struct core_dc *dc) -{ - struct dc_context *dc_ctx = dc->ctx; - struct dce_hwseq *hws = dc->hwseq; - - if (REG(MPC_CRC_RESULT_GB)) - DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", - REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); - if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) - DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", - REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); -} - -static void dcn10_log_hw_state(struct core_dc *dc) -{ - struct dc_context *dc_ctx = dc->ctx; - struct resource_pool *pool = dc->res_pool; - int i; - - DTN_INFO_BEGIN(); - - DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t rotation \t" - "mirror \t sw_mode \t dcc_en \t blank_en \t ttu_dis \t" - "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); - - for (i = 0; i < pool->pipe_count; i++) { - struct mem_input *mi = pool->mis[i]; - struct dcn_hubp_state s; - - dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); - - DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t %xh \t %xh \t " - "%d \t %d \t %d \t %d \t" - "%d \t %d \t %d \n", - i, - s.pixel_format, - s.inuse_addr_hi, - s.viewport_width, - s.viewport_height, - s.rotation_angle, - s.h_mirror_en, - s.sw_mode, - s.dcc_en, - s.blank_en, - s.ttu_disable, - s.min_ttu_vblank, - s.qos_level_low_wm, - s.qos_level_high_wm); - } - DTN_INFO("\n"); - - log_mpc_crc(dc); - - DTN_INFO_END(); -} - static void dcn10_wait_for_mpcc_disconnect( struct core_dc *dc, struct resource_pool *res_pool, -- GitLab From eb4e33b7c98a4d69d84d783fd0a7918e5ad011da Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 09:22:14 -0400 Subject: [PATCH 0750/2898] drm/amd/display: log underflow as well as convert output in ref_cycle to nano sec Signed-off-by: Tony Cheng Reviewed-by: Logatharshan Thothiralingam Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 33 ++++++++++++++----- .../amd/display/dc/dcn10/dcn10_mem_input.c | 5 +-- .../amd/display/dc/dcn10/dcn10_mem_input.h | 3 ++ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 30ddf920b270..a4c0c338285d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -65,6 +65,20 @@ static void log_mpc_crc(struct core_dc *dc) REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); } +void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle) +{ + static const uint32_t ref_clk_mhz = 48; + static const unsigned int frac = 10; + uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz; + + DTN_INFO("%d.%d \t ", + us_x10 / frac, + us_x10 % frac); +} + +#define DTN_INFO_MICRO_SEC(ref_cycle) \ + print_microsec(dc_ctx, ref_cycle) + static void dcn10_log_hw_state(struct core_dc *dc) { struct dc_context *dc_ctx = dc->ctx; @@ -73,8 +87,9 @@ static void dcn10_log_hw_state(struct core_dc *dc) DTN_INFO_BEGIN(); - DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t rotation \t" - "mirror \t sw_mode \t dcc_en \t blank_en \t ttu_dis \t" + DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t " + "rotation \t mirror \t sw_mode \t " + "dcc_en \t blank_en \t ttu_dis \t underflow \t " "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); for (i = 0; i < pool->pipe_count; i++) { @@ -83,9 +98,9 @@ static void dcn10_log_hw_state(struct core_dc *dc) dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); - DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t %xh \t %xh \t " - "%d \t %d \t %d \t %d \t" - "%d \t %d \t %d \n", + DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t " + "%xh \t %xh \t %xh \t " + "%d \t %d \t %d \t %xh \t", i, s.pixel_format, s.inuse_addr_hi, @@ -97,9 +112,11 @@ static void dcn10_log_hw_state(struct core_dc *dc) s.dcc_en, s.blank_en, s.ttu_disable, - s.min_ttu_vblank, - s.qos_level_low_wm, - s.qos_level_high_wm); + s.underflow_status); + DTN_INFO_MICRO_SEC(s.min_ttu_vblank); + DTN_INFO_MICRO_SEC(s.qos_level_low_wm); + DTN_INFO_MICRO_SEC(s.qos_level_high_wm); + DTN_INFO("\n"); } DTN_INFO("\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 0d40fa753036..f36585de15df 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -841,9 +841,10 @@ void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, REG_GET(DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, &s->dcc_en); - REG_GET_2(DCHUBP_CNTL, + REG_GET_3(DCHUBP_CNTL, HUBP_BLANK_EN, &s->blank_en, - HUBP_TTU_DISABLE, &s->ttu_disable); + HUBP_TTU_DISABLE, &s->ttu_disable, + HUBP_UNDERFLOW_STATUS, &s->underflow_status); REG_GET(DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, &s->min_ttu_vblank); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index e2eba25f44ec..b3ec16c17826 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -250,6 +250,7 @@ struct dcn_mi_registers { #define MI_MASK_SH_LIST_DCN(mask_sh)\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + MI_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ MI_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ MI_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ @@ -402,6 +403,7 @@ struct dcn_mi_registers { type HUBP_BLANK_EN;\ type HUBP_TTU_DISABLE;\ type HUBP_NO_OUTSTANDING_REQ;\ + type HUBP_UNDERFLOW_STATUS;\ type NUM_PIPES;\ type NUM_BANKS;\ type PIPE_INTERLEAVE;\ @@ -591,6 +593,7 @@ struct dcn_hubp_state { uint32_t sw_mode; uint32_t dcc_en; uint32_t blank_en; + uint32_t underflow_status; uint32_t ttu_disable; uint32_t min_ttu_vblank; uint32_t qos_level_low_wm; -- GitLab From 665da60f23d8c6bda5431529a73be49b3b9d97cb Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 3 Aug 2017 14:20:14 -0400 Subject: [PATCH 0751/2898] drm/amd/display: Add more pstate sanity checks Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a4c0c338285d..114dd279fe47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1767,6 +1767,10 @@ static void dcn10_power_on_fe( struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + power_on_plane(dc->hwseq, pipe_ctx->pipe_idx); @@ -1813,6 +1817,10 @@ static void dcn10_power_on_fe( pipe_ctx->plane_res.scl_data.recout.y); print_rq_dlg_ttu(dc, pipe_ctx); } + + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } } static void program_gamut_remap(struct pipe_ctx *pipe_ctx) @@ -2287,6 +2295,10 @@ static void dcn10_set_bandwidth( { struct dm_pp_clock_for_voltage_req clock; + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) return; @@ -2338,6 +2350,10 @@ static void dcn10_set_bandwidth( } dcn10_pplib_apply_display_requirements(dc, context); + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + /* need to fix this function. not doing the right thing here */ } @@ -2459,6 +2475,10 @@ static void dcn10_wait_for_mpcc_disconnect( { int i; + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + if (!pipe_ctx->stream_res.opp) return; @@ -2473,6 +2493,10 @@ static void dcn10_wait_for_mpcc_disconnect( } } + if (dc->public.debug.sanity_checks) { + verify_allow_pstate_change_high(dc->hwseq); + } + } static bool dcn10_dummy_display_power_gating( -- GitLab From d66cf5f5013a4268057bcb92d301d010268ea27f Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Thu, 3 Aug 2017 09:59:23 -0400 Subject: [PATCH 0752/2898] drm/amd/display: implement DXGI Gamma Ramps Support for gamma correction ramp in Floating Point format Signed-off-by: Anthony Koo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 ++++++------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 21 ++++++++++++++----- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 14 +++++++++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 11 ++++++---- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4535942e8a63..b0fcfebc04b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1874,15 +1874,14 @@ static int fill_plane_attributes_from_fb( } -#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256 - static void fill_gamma_from_crtc_state( const struct drm_crtc_state *crtc_state, struct dc_plane_state *plane_state) { int i; struct dc_gamma *gamma; - struct drm_color_lut *lut = (struct drm_color_lut *) crtc_state->gamma_lut->data; + struct drm_color_lut *lut = + (struct drm_color_lut *) crtc_state->gamma_lut->data; gamma = dc_create_gamma(); @@ -1891,10 +1890,11 @@ static void fill_gamma_from_crtc_state( return; } - for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { - gamma->red[i] = lut[i].red; - gamma->green[i] = lut[i].green; - gamma->blue[i] = lut[i].blue; + gamma->type = GAMMA_RGB_256_ENTRIES; + for (i = 0; i < GAMMA_RGB_256_ENTRIES; i++) { + gamma->entries.red[i] = dal_fixed31_32_from_int(lut[i].red); + gamma->entries.green[i] = dal_fixed31_32_from_int(lut[i].green); + gamma->entries.blue[i] = dal_fixed31_32_from_int(lut[i].blue); } plane_state->gamma_correction = gamma; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 778bd5555c7a..8d1504668ec7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -409,20 +409,31 @@ struct dc_cursor_mi_param { /* IPP related types */ enum { - INPUT_LUT_ENTRIES = 256 + GAMMA_RGB_256_ENTRIES = 256, + GAMMA_RGB_FLOAT_1024_ENTRIES = 1024, + GAMMA_MAX_ENTRIES = 1024 +}; + +enum dc_gamma_type { + GAMMA_RGB_256 = 1, + GAMMA_RGB_FLOAT_1024 = 2 }; struct dc_gamma { - uint16_t red[INPUT_LUT_ENTRIES]; - uint16_t green[INPUT_LUT_ENTRIES]; - uint16_t blue[INPUT_LUT_ENTRIES]; + enum dc_gamma_type type; + unsigned int num_entries; + + struct dc_gamma_entries { + struct fixed31_32 red[GAMMA_MAX_ENTRIES]; + struct fixed31_32 green[GAMMA_MAX_ENTRIES]; + struct fixed31_32 blue[GAMMA_MAX_ENTRIES]; + } entries; /* private to DC core */ struct dc_context *ctx; /* private to dc_surface.c */ int ref_count; - }; /* Used by both ipp amd opp functions*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index 9e8f0a3593a2..e010cf10d605 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -193,10 +193,16 @@ static void dce_ipp_program_input_lut( REG_SET(DC_LUT_RW_INDEX, 0, DC_LUT_RW_INDEX, 0); - for (i = 0; i < INPUT_LUT_ENTRIES; i++) { - REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->red[i]); - REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->green[i]); - REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, gamma->blue[i]); + for (i = 0; i < gamma->num_entries; i++) { + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.red[i])); + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.green[i])); + REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.blue[i])); } /* power off LUT memory */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index ee12f671d8ea..8ee830522148 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -910,13 +910,16 @@ static void ippn10_program_input_lut( CM_IGAM_LUT_FORMAT_B, 3); // Start at index 0 of IGAM LUT REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); - for (i = 0; i < INPUT_LUT_ENTRIES; i++) { + for (i = 0; i < gamma->num_entries; i++) { REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - gamma->red[i]); + dal_fixed31_32_round( + gamma->entries.red[i])); REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - gamma->green[i]); + dal_fixed31_32_round( + gamma->entries.green[i])); REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - gamma->blue[i]); + dal_fixed31_32_round( + gamma->entries.blue[i])); } // Power off LUT memory REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); -- GitLab From f334073ae31eaee742811e6ca282622aad5844ad Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 3 Aug 2017 13:57:05 -0400 Subject: [PATCH 0753/2898] drm/amd/display: Move verify link cap after read edid DP link layer test 400.1.1 fails intermittently. The test device will pull hpd low immediately after verify link cap. Driver reads edid when hpd low that causes the test to fail. Move read edid before verify link cap, so driver will read edid before starting link training Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 7 ------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 1279eb1dfc2e..72eb6af62f45 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -666,6 +666,22 @@ bool dc_link_detect(struct dc_link *link, bool boot) break; } + if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && + sink_caps.transaction_type == + DDC_TRANSACTION_TYPE_I2C_OVER_AUX) { + /* + * TODO debug why Dell 2413 doesn't like + * two link trainings + */ + if (is_mst_supported(link)) { + link->verified_link_cap = + link->reported_link_cap; + } else { + dp_hbr_verify_link_cap(link, + &link->reported_link_cap); + } + } + /* HDMI-DVI Dongle */ if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A && !sink->edid_caps.edid_hdmi) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 3d296b1d118f..9d5fe658d14c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2283,13 +2283,6 @@ void detect_dp_sink_caps(struct dc_link *link) * DP, hw_init may need check signal or power up * encoder here. */ - - if (is_mst_supported(link)) { - link->verified_link_cap = link->reported_link_cap; - } else { - dp_hbr_verify_link_cap(link, - &link->reported_link_cap); - } /* TODO save sink caps in link->sink */ } -- GitLab From 3e9ad6164b98f82ff4b191980c502f09fee4deef Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 3 Aug 2017 00:22:25 -0400 Subject: [PATCH 0754/2898] drm/amd/display: add programming for 0 plane case Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 45 +++++++++++-------- .../display/dc/dce110/dce110_hw_sequencer.c | 17 +++++-- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 29 +++++++++--- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 +- 4 files changed, 64 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 748e709c611f..f305780c36ce 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -978,10 +978,10 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c const struct dc_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].plane_count; j++) { - const struct dc_plane_state *plane_state = - context->stream_status[i].plane_states[j]; - - core_dc->hwss.apply_ctx_for_surface(core_dc, plane_state, context); + core_dc->hwss.apply_ctx_for_surface( + core_dc, context->streams[i], + context->stream_status[i].plane_count, + context); /* * enable stereo @@ -1391,6 +1391,21 @@ enum surface_update_type dc_check_update_surfaces_for_stream( return overall_type; } +static struct dc_stream_status *stream_get_status( + struct validate_context *ctx, + struct dc_stream_state *stream) +{ + uint8_t i; + + for (i = 0; i < ctx->stream_count; i++) { + if (stream == ctx->streams[i]) { + return &ctx->stream_status[i]; + } + } + + return NULL; +} + enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_planes_and_stream(struct dc *dc, @@ -1405,16 +1420,6 @@ void dc_update_planes_and_stream(struct dc *dc, const struct dc_stream_status *stream_status; struct dc_context *dc_ctx = core_dc->ctx; - /* Currently this function do not result in any HW programming - * when called with 0 surface. But proceeding will cause - * SW state to be updated in validate_context. So we might as - * well make it not do anything at all until the hw programming - * is implemented properly to handle 0 surface case. - * TODO: fix hw programming then remove this early return - */ - if (surface_count == 0) - return; - stream_status = dc_stream_get_status(stream); ASSERT(stream_status); @@ -1595,7 +1600,7 @@ void dc_update_planes_and_stream(struct dc *dc, } if (surface_count == 0) - core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); + core_dc->hwss.apply_ctx_for_surface(core_dc, stream, surface_count, context); /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { @@ -1625,12 +1630,16 @@ void dc_update_planes_and_stream(struct dc *dc, bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; struct dc_cursor_position position = { 0 }; + if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) continue; - if (!pipe_ctx->top_pipe) + if (!pipe_ctx->top_pipe && pipe_ctx->stream) { + struct dc_stream_status *stream_status = stream_get_status(context, pipe_ctx->stream); + core_dc->hwss.apply_ctx_for_surface( - core_dc, pipe_ctx->plane_state, context); + core_dc, pipe_ctx->stream, stream_status->plane_count, context); + } /* TODO: this is a hack w/a for switching from mpo to pipe split */ dc_stream_set_cursor_position(pipe_ctx->stream, &position); @@ -1653,7 +1662,7 @@ void dc_update_planes_and_stream(struct dc *dc, if (update_type == UPDATE_TYPE_MED) core_dc->hwss.apply_ctx_for_surface( - core_dc, plane_state, context); + core_dc, stream, surface_count, context); for (j = 0; j < core_dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d3368a8bd1d5..59925723271e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2614,18 +2614,27 @@ static void dce110_program_front_end_for_pipe( static void dce110_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_plane_state *plane_state, + const struct dc_stream_state *stream, + int num_planes, struct validate_context *context) { - int i; + int i, be_idx; - if (!plane_state) + if (num_planes == 0) return; + be_idx = -1; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (stream == context->res_ctx.pipe_ctx[i].stream) { + be_idx = context->res_ctx.pipe_ctx[i].stream_res.tg->inst; + break; + } + } + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->plane_state != plane_state) + if (pipe_ctx->stream == stream) continue; dce110_program_front_end_for_pipe(dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 114dd279fe47..948aaeb73122 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2151,7 +2151,8 @@ static void dcn10_pplib_apply_display_requirements( static void dcn10_apply_ctx_for_surface( struct core_dc *dc, - const struct dc_plane_state *plane_state, + const struct dc_stream_state *stream, + int num_planes, struct validate_context *context) { int i, be_idx; @@ -2159,12 +2160,26 @@ static void dcn10_apply_ctx_for_surface( if (dc->public.debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - if (!plane_state) - return; - - for (be_idx = 0; be_idx < dc->res_pool->pipe_count; be_idx++) - if (plane_state == context->res_ctx.pipe_ctx[be_idx].plane_state) + be_idx = -1; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (stream == context->res_ctx.pipe_ctx[i].stream) { + be_idx = context->res_ctx.pipe_ctx[i].stream_res.tg->inst; break; + } + } + + ASSERT(be_idx != -1); + + if (num_planes == 0) { + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { + struct pipe_ctx *old_pipe_ctx = + &dc->current_context->res_ctx.pipe_ctx[i]; + + if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) + dcn10_power_down_fe(dc, old_pipe_ctx->pipe_idx); + } + return; + } /* reset unused mpcc */ for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -2229,7 +2244,7 @@ static void dcn10_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->plane_state != plane_state) + if (pipe_ctx->stream != stream) continue; /* looking for top pipe to program */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 5d075f93b4b9..7689e372b9da 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -59,7 +59,8 @@ struct hw_sequencer_funcs { void (*apply_ctx_for_surface)( struct core_dc *dc, - const struct dc_plane_state *plane_state, + const struct dc_stream_state *stream, + int num_planes, struct validate_context *context); void (*set_plane_config)( -- GitLab From cbb4d72e290df8fedc764c7abb823cae938a45aa Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 3 Aug 2017 15:46:10 -0400 Subject: [PATCH 0755/2898] drm/amd/display: Clear water mark change request bit before programing. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 948aaeb73122..9165dc80cd22 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -320,6 +320,9 @@ static void program_watermarks( */ uint32_t prog_wm_value; + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + /* Repeat for water mark set A, B, C and D. */ /* clock state A */ prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, @@ -518,8 +521,7 @@ static void program_watermarks( REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 1); - REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, - DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, 0); + REG_UPDATE(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, -- GitLab From 5aa72db72ccc08c2d3d3e4b0a285bab932db5132 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 3 Aug 2017 18:29:42 -0400 Subject: [PATCH 0756/2898] drm/amd/display: Fix accessing freed memory Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f305780c36ce..b69a726717d9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1714,8 +1714,11 @@ void dc_update_planes_and_stream(struct dc *dc, } if (core_dc->current_context != context) { - dc_release_validate_context(core_dc->current_context); + struct validate_context *old = core_dc->current_context; + core_dc->current_context = context; + dc_release_validate_context(old); + } return; -- GitLab From 8a5d82451e297fc3864bb9ab0247b53c7ab8a022 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 21:23:04 -0400 Subject: [PATCH 0757/2898] drm/amd/display: use some sensible time out 40s time out is not sensible. also make all udelay poll happen more frequently since CPU is busy anyways Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 6 ++++- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 11 ++++---- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 4 +-- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 27 ++++++++++++------- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 +- .../display/dc/dcn10/dcn10_timing_generator.c | 18 ++++++------- 6 files changed, 41 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index f219bd2068e5..0d84b2a1ccfd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -135,6 +135,9 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, uint32_t reg_val; int i; + /* something is terribly wrong if time out is > 200ms. (5Hz) */ + ASSERT(delay_between_poll_us * time_out_num_tries <= 200000); + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { /* 35 seconds */ delay_between_poll_us = 35000; @@ -158,7 +161,8 @@ uint32_t generic_reg_wait(const struct dc_context *ctx, } dm_error("REG_WAIT timeout %dus * %d tries - %s line:%d\n", - delay_between_poll_us, time_out_num_tries, func_name, line); + delay_between_poll_us, time_out_num_tries, + func_name, line); if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index b4fa78292ad2..0e9d914e1a8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -195,8 +195,9 @@ static void driver_set_backlight_level(struct dce_abm *abm_dce, uint32_t level) BL_PWM_GRP1_REG_LOCK, 0); /* 5.4.4 Wait for pending bit to be cleared */ - REG_WAIT(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, - 0, 10, 1000); + REG_WAIT(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_UPDATE_PENDING, 0, + 1, 10000); } static void dmcu_set_backlight_level( @@ -224,7 +225,7 @@ static void dmcu_set_backlight_level( /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, - 0, 100, 800); + 0, 1, 80000); /* setDMCUParam_BL */ REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17_bit); @@ -304,7 +305,7 @@ static bool dce_abm_set_level(struct abm *abm, uint32_t level) struct dce_abm *abm_dce = TO_DCE_ABM(abm); REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, - 100, 800); + 1, 80000); /* setDMCUParam_ABMLevel */ REG_UPDATE_2(MASTER_COMM_CMD_REG, @@ -322,7 +323,7 @@ static bool dce_abm_immediate_disable(struct abm *abm) struct dce_abm *abm_dce = TO_DCE_ABM(abm); REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, - 100, 800); + 1, 80000); /* setDMCUParam_ABMLevel */ REG_UPDATE_2(MASTER_COMM_CMD_REG, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index aaff946a6d0a..92902f011418 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -262,7 +262,7 @@ static void dce_psr_wait_loop( union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; /* waitDMCUReadyForCmd */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); masterCmdData1.u32 = 0; masterCmdData1.bits.wait_loop = wait_loop_number; @@ -502,7 +502,7 @@ static void dcn10_psr_wait_loop( union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; /* waitDMCUReadyForCmd */ - REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 100); + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); masterCmdData1.u32 = 0; masterCmdData1.bits.wait_loop = wait_loop_number; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 9165dc80cd22..292dfef91c9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -264,28 +264,32 @@ static void dpp_pg_control( DOMAIN1_POWER_GATE, power_gate); REG_WAIT(DOMAIN1_PG_STATUS, - DOMAIN1_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN1_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 1: /* DPP1 */ REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, power_gate); REG_WAIT(DOMAIN3_PG_STATUS, - DOMAIN3_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN3_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 2: /* DPP2 */ REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, power_gate); REG_WAIT(DOMAIN5_PG_STATUS, - DOMAIN5_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN5_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 3: /* DPP3 */ REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, power_gate); REG_WAIT(DOMAIN7_PG_STATUS, - DOMAIN7_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN7_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; default: BREAK_TO_DEBUGGER(); @@ -612,28 +616,32 @@ static void hubp_pg_control( DOMAIN0_POWER_GATE, power_gate); REG_WAIT(DOMAIN0_PG_STATUS, - DOMAIN0_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN0_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 1: /* DCHUBP1 */ REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, power_gate); REG_WAIT(DOMAIN2_PG_STATUS, - DOMAIN2_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN2_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 2: /* DCHUBP2 */ REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, power_gate); REG_WAIT(DOMAIN4_PG_STATUS, - DOMAIN4_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN4_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; case 3: /* DCHUBP3 */ REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, power_gate); REG_WAIT(DOMAIN6_PG_STATUS, - DOMAIN6_PGFSM_PWR_STATUS, pwr_status, 20000, 200000); + DOMAIN6_PGFSM_PWR_STATUS, pwr_status, + 1, 1000); break; default: BREAK_TO_DEBUGGER(); @@ -1011,7 +1019,8 @@ static void reset_front_end( if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], - VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000); + VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, + 1, 100000); plane_atomic_disable(dc, fe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 036f161ab1c1..52f2f2dd9a43 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -72,7 +72,7 @@ static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) ASSERT(!(mpc10->mpcc_in_use_mask & 1 << id)); REG_WAIT(MPCC_STATUS[id], MPCC_IDLE, 1, - 1000, 1000); + 1, 100000); } static int mpc10_get_idle_mpcc_id(struct dcn10_mpc *mpc10) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index f4dce2806ae1..941e0125ff06 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -312,7 +312,7 @@ static void tgn10_blank_crtc(struct timing_generator *tg) */ REG_WAIT(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 1, - 20000, 200000); + 1, 100000); REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 0); @@ -351,7 +351,7 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 1, - 2000, 500); + 1, 1000); /* Enable clock */ REG_UPDATE_2(OTG_CLOCK_CONTROL, @@ -359,7 +359,7 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) OTG_CLOCK_GATE_DIS, 1); REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 1, - 2000, 500); + 1, 1000); } else { REG_UPDATE_2(OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, 0, @@ -368,7 +368,7 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OTG_CLOCK_CONTROL, OTG_CLOCK_ON, 0, - 2000, 500); + 1, 1000); REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, 0, @@ -377,7 +377,7 @@ static void tgn10_enable_optc_clock(struct timing_generator *tg, bool enable) if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, 0, - 2000, 500); + 1, 1000); } } @@ -429,7 +429,7 @@ static bool tgn10_disable_crtc(struct timing_generator *tg) /* CRTC disabled, so disable clock. */ REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, - 2000, 500); + 1, 100000); return true; } @@ -556,7 +556,7 @@ static void tgn10_unlock(struct timing_generator *tg) /* why are we waiting here? */ REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, 0, - 20000, 200000); + 1, 100000); } static void tgn10_get_position(struct timing_generator *tg, @@ -651,13 +651,13 @@ static void tgn10_wait_for_state(struct timing_generator *tg, case CRTC_STATE_VBLANK: REG_WAIT(OTG_STATUS, OTG_V_BLANK, 1, - 100, 100000); /* 1 vupdate at 10hz */ + 1, 100000); /* 1 vupdate at 10hz */ break; case CRTC_STATE_VACTIVE: REG_WAIT(OTG_STATUS, OTG_V_ACTIVE_DISP, 1, - 100, 100000); /* 1 vupdate at 10hz */ + 1, 100000); /* 1 vupdate at 10hz */ break; default: -- GitLab From 0627bbd30f87e06987cb38aee557b06414ae3735 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sat, 5 Aug 2017 10:30:11 -0400 Subject: [PATCH 0758/2898] drm/amd/display: Use public plane destroy helper Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b0fcfebc04b8..3aab3d233a52 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2835,8 +2835,7 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane, if (dm_plane_state->dc_state) dc_plane_state_release(dm_plane_state->dc_state); - __drm_atomic_helper_plane_destroy_state(state); - kfree(dm_plane_state); + drm_atomic_helper_plane_destroy_state(plane, state); } static const struct drm_plane_funcs dm_plane_funcs = { -- GitLab From e1403629d86402ccc25a5c18feb80fc97f671c12 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sat, 5 Aug 2017 12:43:45 -0400 Subject: [PATCH 0759/2898] drm/amd/display: Couple newline fixes Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 3aab3d233a52..0caf8135084b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1472,7 +1472,6 @@ static const struct amdgpu_display_funcs dm_display_funcs = { }; - #if defined(CONFIG_DEBUG_KERNEL_DC) static ssize_t s3_debug_store( @@ -1594,7 +1593,8 @@ bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) { - /* TODO */ return true; + /* TODO */ + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d1a6398043a3..cac92bf91e4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -312,7 +312,6 @@ struct dc_plane_status { struct dc_plane_state { struct dc_plane_address address; - struct scaling_taps scaling_quality; struct rect src_rect; struct rect dst_rect; -- GitLab From 08b8ccfbcb511aa64efd8fa211f785597890af9e Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Fri, 4 Aug 2017 15:30:45 -0400 Subject: [PATCH 0760/2898] drm/amd/display: Fix hw state logging regression Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 292dfef91c9d..2fd9c33dbf1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -134,6 +134,7 @@ static void verify_allow_pstate_change_high( static unsigned int pstate_wait_timeout_us = 40; static unsigned int max_sampled_pstate_wait_us; /* data collection */ static bool forced_pstate_allow; /* help with revert wa */ + static bool should_log_hw_state; /* prevent hw state log by default */ unsigned int debug_index = 0x7; unsigned int debug_data; @@ -191,7 +192,9 @@ static void verify_allow_pstate_change_high( REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); forced_pstate_allow = true; - dcn10_log_hw_state(DC_TO_CORE(hws->ctx->dc)); + if (should_log_hw_state) { + dcn10_log_hw_state(DC_TO_CORE(hws->ctx->dc)); + } BREAK_TO_DEBUGGER(); } -- GitLab From 9d6f264b5653e1fe5e9646c7075cfc81445b25cd Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 4 Aug 2017 15:42:36 -0400 Subject: [PATCH 0761/2898] drm/amd/display: Workaround for underflow. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2fd9c33dbf1c..b07ca5693cb6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1150,6 +1150,22 @@ static bool patch_address_for_sbs_tb_stereo( return false; } +static void toggle_watermark_change_req(struct dce_hwseq *hws) +{ + uint32_t watermark_change_req; + + REG_GET(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, &watermark_change_req); + + if (watermark_change_req) + watermark_change_req = 0; + else + watermark_change_req = 1; + + REG_UPDATE(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); +} + static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { bool addr_patched = false; @@ -2089,6 +2105,7 @@ static void update_dchubp_dpp( mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); } + static void program_all_pipe_in_tree( struct core_dc *dc, struct pipe_ctx *pipe_ctx, @@ -2124,6 +2141,18 @@ static void program_all_pipe_in_tree( if (pipe_ctx->plane_state != NULL) { dcn10_power_on_fe(dc, pipe_ctx, context); + + /* temporary dcn1 wa: + * watermark update requires toggle after a/b/c/d sets are programmed + * if hubp is pg then wm value doesn't get properaged to hubp + * need to toggle after ungate to ensure wm gets to hubp. + * + * final solution: we need to get SMU to do the toggle as + * DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST is owned by SMU we should have + * both driver and fw accessing same register + */ + toggle_watermark_change_req(dc->hwseq); + update_dchubp_dpp(dc, pipe_ctx, context); } -- GitLab From 233dcd2092f9f9786ff019174b1d38f288231f2c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 23:21:46 -0400 Subject: [PATCH 0762/2898] drm/amd/display: log watermarks Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b07ca5693cb6..7b943e1837ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -79,6 +79,84 @@ void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle) #define DTN_INFO_MICRO_SEC(ref_cycle) \ print_microsec(dc_ctx, ref_cycle) +struct dcn_hubbub_wm_set { + uint32_t wm_set; + uint32_t data_urgent; + uint32_t pte_meta_urgent; + uint32_t sr_enter; + uint32_t sr_exit; + uint32_t dram_clk_chanage; +}; + +struct dcn_hubbub_wm { + struct dcn_hubbub_wm_set sets[4]; +}; + +static void dcn10_hubbub_wm_read_state(struct dce_hwseq *hws, + struct dcn_hubbub_wm *wm) +{ + struct dcn_hubbub_wm_set *s; + + s = &wm->sets[0]; + s->wm_set = 0; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A); + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A); + + s = &wm->sets[1]; + s->wm_set = 1; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B); + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B); + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B); + + s = &wm->sets[2]; + s->wm_set = 2; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C); + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C); + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C); + + s = &wm->sets[3]; + s->wm_set = 3; + s->data_urgent = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D); + s->pte_meta_urgent = REG_READ(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D); + s->sr_enter = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D); + s->sr_exit = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D); + s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); +} + +static void dcn10_log_hubbub_state(struct core_dc *dc) +{ + struct dc_context *dc_ctx = dc->ctx; + struct dcn_hubbub_wm wm; + int i; + + dcn10_hubbub_wm_read_state(dc->hwseq, &wm); + + DTN_INFO("HUBBUB WM: \t data_urgent \t pte_meta_urgent \t " + "sr_enter \t sr_exit \t dram_clk_change \n"); + + for (i = 0; i < 4; i++) { + struct dcn_hubbub_wm_set *s; + + s = &wm.sets[i]; + DTN_INFO("WM_Set[%d]:\t ", s->wm_set); + DTN_INFO_MICRO_SEC(s->data_urgent); + DTN_INFO_MICRO_SEC(s->pte_meta_urgent); + DTN_INFO_MICRO_SEC(s->sr_enter); + DTN_INFO_MICRO_SEC(s->sr_exit); + DTN_INFO_MICRO_SEC(s->dram_clk_chanage); + DTN_INFO("\n"); + } + + DTN_INFO("\n"); +} + static void dcn10_log_hw_state(struct core_dc *dc) { struct dc_context *dc_ctx = dc->ctx; @@ -87,6 +165,8 @@ static void dcn10_log_hw_state(struct core_dc *dc) DTN_INFO_BEGIN(); + dcn10_log_hubbub_state(dc); + DTN_INFO("HUBP:\t format \t addr_hi \t width \t height \t " "rotation \t mirror \t sw_mode \t " "dcc_en \t blank_en \t ttu_dis \t underflow \t " -- GitLab From f0c4d9977ae215859ff13304ef0fc02a8b779478 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Thu, 3 Aug 2017 14:20:14 -0400 Subject: [PATCH 0763/2898] drm/amd/display: fix HDMI 12bits last two bits are zero issue (FF-158) -[FF N-1] HDMI Deep Color Mode incorrect bit depth: FMT_DYNAMIC_EXP_EN is being reset to 0 Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 17 +++++++++++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 59925723271e..c29e51409286 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1044,14 +1044,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( /* */ dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc); - pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( - pipe_ctx->stream_res.opp, - COLOR_SPACE_YCBCR601, - stream->timing.display_color_depth, - pipe_ctx->stream->signal); - /* FPGA does not program backend */ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( + pipe_ctx->stream_res.opp, + COLOR_SPACE_YCBCR601, + stream->timing.display_color_depth, + pipe_ctx->stream->signal); + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( pipe_ctx->stream_res.opp, &stream->bit_depth_params, @@ -1064,6 +1064,11 @@ static enum dc_status apply_single_controller_ctx_to_hw( BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; } + pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( + pipe_ctx->stream_res.opp, + COLOR_SPACE_YCBCR601, + stream->timing.display_color_depth, + pipe_ctx->stream->signal); if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) stream->sink->link->link_enc->funcs->setup( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 38d15f7c2a88..8048782ac599 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -240,7 +240,8 @@ static void oppn10_set_dyn_expansion( /*01 - 8-bit -> 12-bit dynamic expansion*/ if (signal == SIGNAL_TYPE_HDMI_TYPE_A || signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + signal == SIGNAL_TYPE_VIRTUAL) { switch (color_dpth) { case COLOR_DEPTH_888: REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, -- GitLab From a2607aef3d0210859d4e9cae6bba7e134ec720d8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 8 Aug 2017 11:35:10 -0400 Subject: [PATCH 0764/2898] drm/amd/display: Fix regression in dce110_apply_ctx_for_surfaces Caused by "add programming for 0 plane case" which was tested on DCN but not on DCE. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c29e51409286..5b46e776b9b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2639,7 +2639,7 @@ static void dce110_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream == stream) + if (pipe_ctx->stream != stream) continue; dce110_program_front_end_for_pipe(dc, pipe_ctx); -- GitLab From 7483bed45de728dacc7cfffe641e67abb3513f61 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 8 Aug 2017 12:23:15 -0400 Subject: [PATCH 0765/2898] drm/amd/display: Pass correct number for gamma entries This was broken by "implement DXGI Gamma Ramps" Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0caf8135084b..7a50aeae8ad7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1890,7 +1890,8 @@ static void fill_gamma_from_crtc_state( return; } - gamma->type = GAMMA_RGB_256_ENTRIES; + gamma->type = GAMMA_RGB_256; + gamma->num_entries = GAMMA_RGB_256_ENTRIES; for (i = 0; i < GAMMA_RGB_256_ENTRIES; i++) { gamma->entries.red[i] = dal_fixed31_32_from_int(lut[i].red); gamma->entries.green[i] = dal_fixed31_32_from_int(lut[i].green); -- GitLab From 533ed6c708334b697254ff831972b657f5c98a40 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 8 Aug 2017 21:01:20 -0400 Subject: [PATCH 0766/2898] drm/amd/display: Fix warnings about uninitialized use Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 72eb6af62f45..b858fec72bd7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -541,7 +541,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) struct audio_support *aud_support = &link->dc->res_pool->audio_support; enum dc_edid_status edid_status; struct dc_context *dc_ctx = link->ctx; - struct dc_sink *sink; + struct dc_sink *sink = NULL; enum dc_connection_type new_connection_type = dc_connection_none; if (link->connector_signal == SIGNAL_TYPE_VIRTUAL) diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index da08cc1c6dc3..4035caf47d31 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -265,6 +265,8 @@ static bool get_hw_supported_ddc_line( { enum gpio_ddc_line line_found; + *line = GPIO_DDC_LINE_UNKNOWN; + if (!ddc) { BREAK_TO_DEBUGGER(); return false; -- GitLab From 5394eb82133b6e9897b9d6e5aed13c08dd71d8c2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:22:21 -0400 Subject: [PATCH 0767/2898] drm/amd/display/dc: Make dce110_validate_bandwidth static (v2) Not used outside of the dce110_resource.c. v2: make a bunch of other functions static as well. Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index c677f98c3516..a7f30dcc906c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -565,7 +565,7 @@ static const struct encoder_feature_support link_enc_feature = { .flags.bits.IS_YCBCR_CAPABLE = true }; -struct link_encoder *dce110_link_encoder_create( +static struct link_encoder *dce110_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = @@ -813,7 +813,7 @@ static enum dc_status build_mapped_resource( return DC_OK; } -bool dce110_validate_bandwidth( +static bool dce110_validate_bandwidth( const struct core_dc *dc, struct validate_context *context) { @@ -927,7 +927,7 @@ static bool dce110_validate_surface_sets( return true; } -enum dc_status dce110_validate_with_context( +static enum dc_status dce110_validate_with_context( const struct core_dc *dc, const struct dc_validation_set set[], int set_count, @@ -971,7 +971,7 @@ enum dc_status dce110_validate_with_context( return result; } -enum dc_status dce110_validate_guaranteed( +static enum dc_status dce110_validate_guaranteed( const struct core_dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) -- GitLab From 2cf5a5e6adba1021a608f58fcedce7201d671086 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:22:22 -0400 Subject: [PATCH 0768/2898] drm/amd/display/dc: make dce120_link_encoder_create static Only used in dce120_resource.c. Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 6448d15c02f5..d4e962756fbb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -535,7 +535,7 @@ static const struct encoder_feature_support link_enc_feature = { .flags.bits.IS_YCBCR_CAPABLE = true }; -struct link_encoder *dce120_link_encoder_create( +static struct link_encoder *dce120_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = -- GitLab From cd4b356f3a8abcd8a96e19b515cf7dc00f41dcbe Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:47 -0400 Subject: [PATCH 0769/2898] drm/amd/display/dm: add KV, KB, ML (v2) Add DCE8 APUs to display manager. v2: rebase changes Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7a50aeae8ad7..d28de04efa42 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1355,6 +1355,9 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_BONAIRE: case CHIP_HAWAII: + case CHIP_KAVERI: + case CHIP_KABINI: + case CHIP_MULLINS: case CHIP_TONGA: case CHIP_FIJI: case CHIP_CARRIZO: @@ -1519,6 +1522,19 @@ static int dm_early_init(void *handle) adev->mode_info.num_dig = 6; adev->mode_info.plane_type = dm_plane_type_default; break; + case CHIP_KAVERI: + adev->mode_info.num_crtc = 4; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 7; + adev->mode_info.plane_type = dm_plane_type_default; + break; + case CHIP_KABINI: + case CHIP_MULLINS: + adev->mode_info.num_crtc = 2; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; + adev->mode_info.plane_type = dm_plane_type_default; + break; case CHIP_FIJI: case CHIP_TONGA: adev->mode_info.num_crtc = 6; -- GitLab From 0d6fbccb22f8af70b729367431a489093aad2ddd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:48 -0400 Subject: [PATCH 0770/2898] drm/amdgpu: add DCE8 APUs to dc_supported check Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2368792b7d67..99f91e52db10 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1980,6 +1980,9 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) #if defined(CONFIG_DRM_AMD_DC) case CHIP_BONAIRE: case CHIP_HAWAII: + case CHIP_KAVERI: + case CHIP_KABINI: + case CHIP_MULLINS: case CHIP_CARRIZO: case CHIP_STONEY: case CHIP_POLARIS11: -- GitLab From ea062558fd796ecff167ca64282bd2c3e3e2663f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:49 -0400 Subject: [PATCH 0771/2898] drm/amd/display/dc: add DIGG for KV KV has 7 possible DIG blocks. Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 5bb2ac71f297..7e9afab8fca0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -80,6 +80,7 @@ #define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08 #define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10 #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 +#define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 /* all values are in milliseconds */ /* For eDP, after power-up/power/down, @@ -471,6 +472,8 @@ static uint8_t get_frontend_source( return DCE110_DIG_FE_SOURCE_SELECT_DIGE; case ENGINE_ID_DIGF: return DCE110_DIG_FE_SOURCE_SELECT_DIGF; + case ENGINE_ID_DIGG: + return DCE110_DIG_FE_SOURCE_SELECT_DIGG; default: ASSERT_CRITICAL(false); return DCE110_DIG_FE_SOURCE_SELECT_INVALID; @@ -984,6 +987,9 @@ bool dce110_link_encoder_construct( case TRANSMITTER_UNIPHY_F: enc110->base.preferred_engine = ENGINE_ID_DIGF; break; + case TRANSMITTER_UNIPHY_G: + enc110->base.preferred_engine = ENGINE_ID_DIGG; + break; default: ASSERT_CRITICAL(false); enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 7473f58584c3..40a9591833aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -262,7 +262,8 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = { stream_enc_regs(2), stream_enc_regs(3), stream_enc_regs(4), - stream_enc_regs(5) + stream_enc_regs(5), + stream_enc_regs(6) }; static const struct dce_stream_encoder_shift se_shift = { -- GitLab From ebfdf0d0770bd20e9baff3750b5103d6b7fa21c3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:50 -0400 Subject: [PATCH 0772/2898] drm/amd/display/dc: add DCE_VERSION for DCE8 APUs DCE 8.1 = Kaveri DCE 8.3 = Kabini/Mullins Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/bios/command_table_helper.c | 2 ++ .../drm/amd/display/dc/bios/command_table_helper2.c | 2 ++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 ++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 2 ++ drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 2 ++ drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c | 2 ++ drivers/gpu/drm/amd/display/include/dal_types.h | 2 ++ 8 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c index 40d9a9921c45..2979358c6a55 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c @@ -37,6 +37,8 @@ bool dal_bios_parser_init_cmd_tbl_helper( { switch (dce) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: *h = dal_cmd_tbl_helper_dce80_get_table(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 9084a32aab79..35c3f3a8e493 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -39,6 +39,8 @@ bool dal_bios_parser_init_cmd_tbl_helper2( { switch (dce) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: *h = dal_cmd_tbl_helper_dce80_get_table(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 30237f049c99..ee7a393b2b00 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -50,9 +50,16 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) switch (asic_id.chip_family) { case FAMILY_CI: - case FAMILY_KV: dc_version = DCE_VERSION_8_0; break; + case FAMILY_KV: + if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || + ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || + ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) + dc_version = DCE_VERSION_8_3; + else + dc_version = DCE_VERSION_8_1; + break; case FAMILY_CZ: dc_version = DCE_VERSION_11_0; break; @@ -94,6 +101,8 @@ struct resource_pool *dc_create_resource_pool( switch (dc_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: res_pool = dce80_create_resource_pool( num_virtual_links, dc); break; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index dd7e1dd62636..88e266ac6dd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -578,6 +578,8 @@ static uint32_t dce110_get_pix_clk_dividers( switch (cs->ctx->dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: case DCE_VERSION_10_0: case DCE_VERSION_11_0: pll_calc_error = @@ -862,6 +864,8 @@ static bool dce110_program_pix_clk( switch (clock_source->ctx->dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: case DCE_VERSION_10_0: case DCE_VERSION_11_0: bp_pc_params.reference_divider = pll_settings->reference_divider; @@ -1209,6 +1213,8 @@ bool dce110_clk_src_construct( switch (clk_src->base.ctx->dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: case DCE_VERSION_10_0: case DCE_VERSION_11_0: diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 425f1c4fa891..25f6f9103c44 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -66,6 +66,8 @@ bool dal_hw_factory_init( switch (dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: dal_hw_factory_dce80_init(factory); return true; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 3b55d45b6775..0ae8ace25739 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -65,6 +65,8 @@ bool dal_hw_translate_init( switch (dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: dal_hw_translate_dce80_init(translate); return true; case DCE_VERSION_10_0: diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 4035caf47d31..9b115e1e2f1a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -79,6 +79,8 @@ struct i2caux *dal_i2caux_create( switch (ctx->dce_version) { case DCE_VERSION_8_0: + case DCE_VERSION_8_1: + case DCE_VERSION_8_3: return dal_i2caux_dce80_create(ctx); case DCE_VERSION_11_2: return dal_i2caux_dce112_create(ctx); diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index 1bfc191574aa..fa543965feb5 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -35,6 +35,8 @@ struct dc_bios; enum dce_version { DCE_VERSION_UNKNOWN = (-1), DCE_VERSION_8_0, + DCE_VERSION_8_1, + DCE_VERSION_8_3, DCE_VERSION_10_0, DCE_VERSION_11_0, DCE_VERSION_11_2, -- GitLab From 7992a6290a79afc1568c873d434f39234f7d3e26 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:51 -0400 Subject: [PATCH 0773/2898] drm/amd/disply/dc: add resource support for DCE8 APUs (v2) Add the appropriate resources for APUs: KV: 4 pipes, 7 dig, 3 PPLLs KB/ML: 2 pipes, 6 dig, 2 PPLLs v2: rebase changes Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 8 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 343 +++++++++++++++++- .../drm/amd/display/dc/dce80/dce80_resource.h | 8 + 3 files changed, 356 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ee7a393b2b00..56a85c80131d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -101,9 +101,15 @@ struct resource_pool *dc_create_resource_pool( switch (dc_version) { case DCE_VERSION_8_0: + res_pool = dce80_create_resource_pool( + num_virtual_links, dc); + break; case DCE_VERSION_8_1: + res_pool = dce81_create_resource_pool( + num_virtual_links, dc); + break; case DCE_VERSION_8_3: - res_pool = dce80_create_resource_pool( + res_pool = dce83_create_resource_pool( num_virtual_links, dc); break; case DCE_VERSION_10_0: diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 40a9591833aa..132117e8bb77 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -350,6 +350,20 @@ static const struct resource_caps res_cap = { .num_pll = 3, }; +static const struct resource_caps res_cap_81 = { + .num_timing_generator = 4, + .num_audio = 7, + .num_stream_encoder = 7, + .num_pll = 3, +}; + +static const struct resource_caps res_cap_83 = { + .num_timing_generator = 2, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 2, +}; + #define CTX ctx #define REG(reg) mm ## reg @@ -829,7 +843,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_plane = dce100_validate_plane }; -static bool construct( +static bool dce80_construct( uint8_t num_virtual_links, struct core_dc *dc, struct dce110_resource_pool *pool) @@ -987,10 +1001,335 @@ struct resource_pool *dce80_create_resource_pool( if (!pool) return NULL; - if (construct(num_virtual_links, dc, pool)) + if (dce80_construct(num_virtual_links, dc, pool)) return &pool->base; BREAK_TO_DEBUGGER(); return NULL; } +static bool dce81_construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_81; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap_81.num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 40; + dc->public.caps.max_cursor_size = 128; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dce_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = + static_clk_info.max_clocks_state; + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + dc->public.caps.max_planes = pool->base.pipe_count; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce80_hw_sequencer_construct(dc)) + goto res_create_fail; + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce81_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (dce81_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool dce83_construct( + uint8_t num_virtual_links, + struct core_dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_firmware_info info; + struct dc_bios *bp; + struct dm_pp_static_clock_info static_clk_info = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_83; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap_83.num_timing_generator; + dc->public.caps.max_downscale_ratio = 200; + dc->public.caps.i2c_speed_in_khz = 40; + dc->public.caps.max_cursor_size = 128; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if ((bp->funcs->get_firmware_info(bp, &info) == BP_RESULT_OK) && + info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + pool->base.clk_src_count = 2; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + pool->base.clk_src_count = 1; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.display_clock = dce_disp_clk_create(ctx, + &disp_clk_regs, + &disp_clk_shift, + &disp_clk_mask); + if (pool->base.display_clock == NULL) { + dm_error("DC: failed to create display clock!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + if (dm_pp_get_static_clocks(ctx, &static_clk_info)) + pool->base.display_clock->max_clks_state = + static_clk_info.max_clocks_state; + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + dc->public.caps.max_planes = pool->base.pipe_count; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce80_hw_sequencer_construct(dc)) + goto res_create_fail; + + return true; + +res_create_fail: + destruct(pool); + return false; +} + +struct resource_pool *dce83_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc) +{ + struct dce110_resource_pool *pool = + dm_alloc(sizeof(struct dce110_resource_pool)); + + if (!pool) + return NULL; + + if (dce83_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h index 2a0cdccddeaf..04f0cfe24ef2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h @@ -35,5 +35,13 @@ struct resource_pool *dce80_create_resource_pool( uint8_t num_virtual_links, struct core_dc *dc); +struct resource_pool *dce81_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + +struct resource_pool *dce83_create_resource_pool( + uint8_t num_virtual_links, + struct core_dc *dc); + #endif /* __DC_RESOURCE_DCE80_H__ */ -- GitLab From 9355c0e8519f3b0d61278b5ab9dee68321494351 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Aug 2017 14:39:52 -0400 Subject: [PATCH 0774/2898] drm/amdgpu/cik: add IP modules for DC for APUs Enable DC for DCE8 APUs. Signed-off-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index af3b66f6f47c..793b1470284d 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1937,6 +1937,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v8_1_ip_block); amdgpu_ip_block_add(adev, &gfx_v7_1_ip_block); @@ -1952,6 +1956,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block); if (adev->enable_virtual_display) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_ip_block_add(adev, &dce_v8_3_ip_block); amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block); -- GitLab From 153ae53232d7d885b532d1aa7fa7ad156834a366 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 10 Aug 2017 15:20:00 -0400 Subject: [PATCH 0775/2898] drm/amd/display: Add a TODO list Signed-off-by: Harry Wentland Reviewed-by: Jordan Lazare Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/TODO | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/TODO diff --git a/drivers/gpu/drm/amd/display/TODO b/drivers/gpu/drm/amd/display/TODO new file mode 100644 index 000000000000..2737873db12d --- /dev/null +++ b/drivers/gpu/drm/amd/display/TODO @@ -0,0 +1,81 @@ +=============================================================================== +TODOs +=============================================================================== + +1. Base this on drm-next - WIP + + +2. Cleanup commit history + + +3. WIP - Drop page flip helper and use DRM's version + + +4. DONE - Flatten all DC objects + * dc_stream/core_stream/stream should just be dc_stream + * Same for other DC objects + + "Is there any major reason to keep all those abstractions? + + Could you collapse everything into struct dc_stream? + + I haven't looked recently but I didn't get the impression there was a + lot of design around what was public/protected, more whatever needed + to be used by someone else was in public." + ~ Dave Airlie + + +5. DONE - Rename DC objects to align more with DRM + * dc_surface -> dc_plane_state + * dc_stream -> dc_stream_state + + +6. DONE - Per-plane and per-stream validation + + +7. WIP - Per-plane and per-stream commit + + +8. WIP - Split pipe_ctx into plane and stream resource structs + + +9. Attach plane and stream reources to state object instead of validate_context + + +10. Remove dc_edid_caps and drm_helpers_parse_edid_caps + * Use drm_display_info instead + * Remove DC's edid quirks and rely on DRM's quirks (add quirks if needed) + + "Making sure you use the sink-specific helper libraries and kernel + subsystems, since there's really no good reason to have 2nd + implementation of those in the kernel. Looks likes that's done for mst + and edid parsing. There's still a bit a midlayer feeling to the edid + parsing side (e.g. dc_edid_caps and dm_helpers_parse_edid_caps, I + think it'd be much better if you convert that over to reading stuff + from drm_display_info and if needed, push stuff into the core). Also, + I can't come up with a good reason why DC needs all this (except to + reimplement half of our edid quirk table, which really isn't a good + idea). Might be good if you put this onto the list of things to fix + long-term, but imo not a blocker. Definitely make sure new stuff + doesn't slip in (i.e. if you start adding edid quirks to DC instead of + the drm core, refactoring to use the core edid stuff was pointless)." + ~ Daniel Vetter + + +11. Remove existing i2c implementation from DC + + "Similar story for i2c, it uses the kernel's i2c code now, but there's + still a full i2c implementation hidden beneath that in + display/dc/i2caux. Kinda not cool, but imo ok if you fix that + post-merging (perhaps by not including any of this in the linux DC + code in the upstream kernel, but as an aux module in your internal + codebase since there you probably need that, same applies to the edid + parsing DC still does. For both cases I assume that the minimal shim + you need on linux (bit banging and edid parsing isn't rocket since) is + a lot less than the glue code to interface with the dc-provided + abstraction." + ~ Daniel Vetter + + +12. drm_modeset_lock in MST should no longer be needed in recent kernels + * Adopt appropriate locking scheme -- GitLab From 17b7cf8c556601eea56b38582fd74945a712cd93 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 23 Aug 2017 09:42:22 -0400 Subject: [PATCH 0776/2898] drm/amdgpu: disable DC on KB/ML for now Until I've had time to test it better. bug: https://bugs.freedesktop.org/show_bug.cgi?id=102372 Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 99f91e52db10..add0032977f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1981,8 +1981,6 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_BONAIRE: case CHIP_HAWAII: case CHIP_KAVERI: - case CHIP_KABINI: - case CHIP_MULLINS: case CHIP_CARRIZO: case CHIP_STONEY: case CHIP_POLARIS11: @@ -1993,9 +1991,10 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_VEGA10: #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) return amdgpu_dc != 0; -#else - return amdgpu_dc > 0; #endif + case CHIP_KABINI: + case CHIP_MULLINS: + return amdgpu_dc > 0; #endif #if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_DCN1_0) case CHIP_RAVEN: -- GitLab From f81483c4ccca0d2ceca14ee15564a14f2c34eb2c Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 10 Aug 2017 16:11:10 -0400 Subject: [PATCH 0777/2898] drm/amd/display: fix gamma distortion on Vega Added missing reg shift/masks to soc base Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index f9622ff54560..d87225d15cd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -237,6 +237,7 @@ XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + XFM_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ @@ -270,6 +271,8 @@ XFM_SF(SCL0_SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \ XFM_SF(LB0_LB_DATA_FORMAT, ALPHA_EN, mask_sh), \ XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ + XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\ + XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\ XFM_SF(DCFE0_DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \ XFM_SF(SCL0_SCL_MODE, SCL_PSCL_EN, mask_sh) -- GitLab From e8cd26434df0cd8d97f31aeb4399afcdc37fcfda Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Mon, 31 Jul 2017 17:10:44 -0400 Subject: [PATCH 0778/2898] drm/amd/display: Use atomic types for ref_count Current ref_count inc/dec is not guarded by locks which leads to a raced condition where two threads try to access the variable at the same time. In this case, both might act on the same cached value and inc/dec from the same value, rather than inc/dec by 2. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 24 ++++++------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 12 +++---- .../gpu/drm/amd/display/dc/core/dc_stream.c | 14 ++++---- .../gpu/drm/amd/display/dc/core/dc_surface.c | 36 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 8 ++--- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 8 files changed, 49 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index b69a726717d9..8efdd05841e1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -454,7 +454,7 @@ static bool construct(struct core_dc *dc, goto val_ctx_fail; } - dc->current_context->ref_count++; + atomic_inc(&dc->current_context->ref_count); dc_ctx->cgs_device = init_params->cgs_device; dc_ctx->driver_context = init_params->driver; @@ -704,7 +704,7 @@ struct validate_context *dc_get_validate_context( if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); if (!is_validation_required(core_dc, set, set_count)) { dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); @@ -748,7 +748,7 @@ bool dc_validate_resources( if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, set_count, context, NULL); @@ -782,7 +782,7 @@ bool dc_validate_guaranteed( if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); result = core_dc->res_pool->funcs->validate_guaranteed( core_dc, stream, context); @@ -1090,7 +1090,7 @@ bool dc_commit_streams( if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); result = core_dc->res_pool->funcs->validate_with_context( core_dc, set, stream_count, context, core_dc->current_context); @@ -1203,16 +1203,16 @@ bool dc_commit_planes_to_stream( void dc_retain_validate_context(struct validate_context *context) { - ASSERT(context->ref_count > 0); - ++context->ref_count; + ASSERT(atomic_read(&context->ref_count) > 0); + atomic_inc(&context->ref_count); } void dc_release_validate_context(struct validate_context *context) { - ASSERT(context->ref_count > 0); - --context->ref_count; + ASSERT(atomic_read(&context->ref_count) > 0); + atomic_dec(&context->ref_count); - if (context->ref_count == 0) { + if (atomic_read(&context->ref_count) == 0) { dc_resource_validate_ctx_destruct(context); dm_free(context); } @@ -1485,7 +1485,7 @@ void dc_update_planes_and_stream(struct dc *dc, if (context == NULL) goto context_alloc_fail; - ++context->ref_count; + atomic_inc(&context->ref_count); dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); @@ -1800,7 +1800,7 @@ void dc_set_power_state( enum dc_acpi_cm_power_state power_state) { struct core_dc *core_dc = DC_TO_CORE(dc); - int ref_count; + atomic_t ref_count; switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 56a85c80131d..1d69bd25e07b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2238,7 +2238,7 @@ void dc_resource_validate_ctx_copy_construct( struct validate_context *dst_ctx) { int i, j; - int ref_count = dst_ctx->ref_count; + atomic_t ref_count = dst_ctx->ref_count; *dst_ctx = *src_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index a83f1243a9d1..7717350297a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -63,16 +63,16 @@ static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init void dc_sink_retain(struct dc_sink *sink) { - ASSERT(sink->ref_count > 0); - ++sink->ref_count; + ASSERT(atomic_read(&sink->ref_count) > 0); + atomic_inc(&sink->ref_count); } void dc_sink_release(struct dc_sink *sink) { - ASSERT(sink->ref_count > 0); - --sink->ref_count; + ASSERT(atomic_read(&sink->ref_count) > 0); + atomic_dec(&sink->ref_count); - if (sink->ref_count == 0) { + if (atomic_read(&sink->ref_count) == 0) { destruct(sink); dm_free(sink); } @@ -88,7 +88,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) if (false == construct(sink, init_params)) goto construct_fail; - ++sink->ref_count; + atomic_inc(&sink->ref_count); return sink; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 2de37fed12a5..47e407dab4a3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -96,19 +96,17 @@ static void destruct(struct dc_stream_state *stream) void dc_stream_retain(struct dc_stream_state *stream) { - - ASSERT(stream->ref_count > 0); - stream->ref_count++; + ASSERT(atomic_read(&stream->ref_count) > 0); + atomic_inc(&stream->ref_count); } void dc_stream_release(struct dc_stream_state *stream) { - if (stream != NULL) { - ASSERT(stream->ref_count > 0); - stream->ref_count--; + ASSERT(atomic_read(&stream->ref_count) > 0); + atomic_dec(&stream->ref_count); - if (stream->ref_count == 0) { + if (atomic_read(&stream->ref_count) == 0) { destruct(stream); dm_free(stream); } @@ -131,7 +129,7 @@ struct dc_stream_state *dc_create_stream_for_sink( if (false == construct(stream, sink)) goto construct_fail; - stream->ref_count++; + atomic_inc(&stream->ref_count); return stream; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 3bcca2d1872b..da19c7fa5151 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -76,7 +76,7 @@ struct dc_plane_state *dc_create_plane_state(const struct dc *dc) if (false == construct(core_dc->ctx, plane_state)) goto construct_fail; - ++plane_state->ref_count; + atomic_inc(&plane_state->ref_count); return plane_state; @@ -122,16 +122,16 @@ const struct dc_plane_status *dc_plane_get_status( void dc_plane_state_retain(struct dc_plane_state *plane_state) { - ASSERT(plane_state->ref_count > 0); - ++plane_state->ref_count; + ASSERT(atomic_read(&plane_state->ref_count) > 0); + atomic_inc(&plane_state->ref_count); } void dc_plane_state_release(struct dc_plane_state *plane_state) { - ASSERT(plane_state->ref_count > 0); - --plane_state->ref_count; + ASSERT(atomic_read(&plane_state->ref_count) > 0); + atomic_dec(&plane_state->ref_count); - if (plane_state->ref_count == 0) { + if (atomic_read(&plane_state->ref_count) == 0) { destruct(plane_state); dm_free(plane_state); } @@ -139,16 +139,16 @@ void dc_plane_state_release(struct dc_plane_state *plane_state) void dc_gamma_retain(struct dc_gamma *gamma) { - ASSERT(gamma->ref_count > 0); - ++gamma->ref_count; + ASSERT(atomic_read(&gamma->ref_count) > 0); + atomic_inc(&gamma->ref_count); } void dc_gamma_release(struct dc_gamma **gamma) { - ASSERT((*gamma)->ref_count > 0); - --(*gamma)->ref_count; + ASSERT(atomic_read(&(*gamma)->ref_count) > 0); + atomic_dec(&(*gamma)->ref_count); - if ((*gamma)->ref_count == 0) + if (atomic_read(&(*gamma)->ref_count) == 0) dm_free((*gamma)); *gamma = NULL; @@ -161,7 +161,7 @@ struct dc_gamma *dc_create_gamma() if (gamma == NULL) goto alloc_fail; - ++gamma->ref_count; + atomic_inc(&gamma->ref_count); return gamma; @@ -171,16 +171,16 @@ struct dc_gamma *dc_create_gamma() void dc_transfer_func_retain(struct dc_transfer_func *tf) { - ASSERT(tf->ref_count > 0); - ++tf->ref_count; + ASSERT(atomic_read(&tf->ref_count) > 0); + atomic_inc(&tf->ref_count); } void dc_transfer_func_release(struct dc_transfer_func *tf) { - ASSERT(tf->ref_count > 0); - --tf->ref_count; + ASSERT(atomic_read(&tf->ref_count) > 0); + atomic_dec(&tf->ref_count); - if (tf->ref_count == 0) + if (atomic_read(&tf->ref_count) == 0) dm_free(tf); } @@ -191,7 +191,7 @@ struct dc_transfer_func *dc_create_transfer_func() if (tf == NULL) goto alloc_fail; - ++tf->ref_count; + atomic_inc(&tf->ref_count); return tf; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cac92bf91e4a..4e60adb981e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -295,7 +295,7 @@ struct dc_transfer_func { enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; struct dc_context *ctx; - int ref_count; + atomic_t ref_count; }; /* @@ -342,7 +342,7 @@ struct dc_plane_state { /* private to dc_surface.c */ enum dc_irq_source irq_source; - int ref_count; + atomic_t ref_count; }; struct dc_plane_info { @@ -518,7 +518,7 @@ struct dc_stream_state { struct dc_stream_status status; /* from stream struct */ - int ref_count; + atomic_t ref_count; }; struct dc_stream_update { @@ -902,7 +902,7 @@ struct dc_sink { struct dc_context *ctx; /* private to dc_sink.c */ - int ref_count; + atomic_t ref_count; }; void dc_sink_retain(struct dc_sink *sink); diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 8d1504668ec7..94f83cd9ab32 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -433,7 +433,7 @@ struct dc_gamma { struct dc_context *ctx; /* private to dc_surface.c */ - int ref_count; + atomic_t ref_count; }; /* Used by both ipp amd opp functions*/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b3005629ab21..5190901ea379 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -260,7 +260,7 @@ struct validate_context { struct dcn_bw_internal_vars dcn_bw_vars; #endif - int ref_count; + atomic_t ref_count; }; #endif /* _CORE_TYPES_H_ */ -- GitLab From 391e20d84104a6b7b9d4a66fec6a7eb0a93f6ef4 Mon Sep 17 00:00:00 2001 From: Duke Du Date: Thu, 3 Aug 2017 10:20:52 -0400 Subject: [PATCH 0779/2898] drm/amd/display: add display write back(DWB) Signed-off-by: Duke Du Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 + drivers/gpu/drm/amd/display/dc/dc.h | 2 + .../drm/amd/display/dc/dce/dce_clock_source.c | 87 ++- .../drm/amd/display/dc/dce/dce_clock_source.h | 8 + drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c | 652 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h | 32 + .../drm/amd/display/dc/dcn10/dcn10_resource.c | 9 + .../gpu/drm/amd/display/dc/inc/clock_source.h | 4 + .../gpu/drm/amd/display/dc/inc/core_types.h | 6 + drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h | 193 ++++++ 11 files changed, 1003 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8efdd05841e1..aeed95a5d097 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1749,6 +1749,16 @@ struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) return core_dc->links[link_index]; } +struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe) +{ + struct core_dc *core_dc = DC_TO_CORE(dc); + if ((pipe >= dwb_pipe0) && (pipe < dwb_pipe_max_num)) { + return core_dc->res_pool->dwbc[(int)pipe]; + } else { + return NULL; + } +} + const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4e60adb981e1..e62d15d90fdb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -797,6 +797,8 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); */ struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); +struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe); + /* Return id of physical connector represented by a dc_link at link_index.*/ const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 88e266ac6dd3..cc707bd615dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -34,6 +34,7 @@ #include "dce_clock_source.h" +#include "core_dc.h" #include "reg_helper.h" #define REG(reg)\ @@ -602,6 +603,89 @@ static uint32_t dce110_get_pix_clk_dividers( return pll_calc_error; } +static uint32_t dce110_get_pll_pixel_rate_in_hz( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + struct core_dc *dc_core = DC_TO_CORE(cs->ctx->dc); + struct validate_context *context = dc_core->current_context; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; + + /* This function need separate to different DCE version, before separate, just use pixel clock */ + return pipe_ctx->stream->phy_pix_clk; +} + +static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + struct core_dc *dc_core = DC_TO_CORE(cs->ctx->dc); + struct validate_context *context = dc_core->current_context; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; + + /* This function need separate to different DCE version, before separate, just use pixel clock */ + return pipe_ctx->stream->phy_pix_clk; +} + +static uint32_t dce110_get_d_to_pixel_rate_in_hz( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; + struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs); + int dto_enabled = 0; + struct fixed31_32 pix_rate; + + REG_GET(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, &dto_enabled); + + if (dto_enabled) { + uint32_t phase = 0; + uint32_t modulo = 0; + REG_GET(PHASE[inst], DP_DTO0_PHASE, &phase); + REG_GET(MODULO[inst], DP_DTO0_MODULO, &modulo); + + if (modulo == 0) { + return 0; + } + + pix_rate = dal_fixed31_32_from_int(clk_src->ref_freq_khz); + pix_rate = dal_fixed31_32_mul_int(pix_rate, 1000); + pix_rate = dal_fixed31_32_mul_int(pix_rate, phase); + pix_rate = dal_fixed31_32_div_int(pix_rate, modulo); + + return dal_fixed31_32_round(pix_rate); + } else { + return dce110_get_dp_pixel_rate_from_combo_phy_pll(cs, pix_clk_params, pll_settings); + } +} + +static uint32_t dce110_get_pix_rate_in_hz( + struct clock_source *cs, + struct pixel_clk_params *pix_clk_params, + struct pll_settings *pll_settings) +{ + uint32_t pix_rate = 0; + switch (pix_clk_params->signal_type) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + case SIGNAL_TYPE_VIRTUAL: + pix_rate = dce110_get_d_to_pixel_rate_in_hz(cs, pix_clk_params, pll_settings); + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + default: + pix_rate = dce110_get_pll_pixel_rate_in_hz(cs, pix_clk_params, pll_settings); + break; + } + + return pix_rate; +} + static bool disable_spread_spectrum(struct dce110_clk_src *clk_src) { enum bp_result result; @@ -962,7 +1046,8 @@ static bool dce110_clock_source_power_down( static const struct clock_source_funcs dce110_clk_src_funcs = { .cs_power_down = dce110_clock_source_power_down, .program_pix_clk = dce110_program_pix_clk, - .get_pix_clk_dividers = dce110_get_pix_clk_dividers + .get_pix_clk_dividers = dce110_get_pix_clk_dividers, + .get_pix_rate_in_hz = dce110_get_pix_rate_in_hz }; static void get_ss_info_from_atombios( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index fc923886e3d4..238c03f14959 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -55,6 +55,8 @@ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + #define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \ SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\ SRII(PHASE, DP_DTO, 0),\ @@ -71,9 +73,13 @@ SRII(PIXEL_RATE_CNTL, OTG, 3) #define CS_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + CS_SF(DP_DTO0_PHASE, DP_DTO0_PHASE, mask_sh),\ + CS_SF(DP_DTO0_MODULO, DP_DTO0_MODULO, mask_sh),\ CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\ CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh) +#endif + #define CS_REG_FIELD_LIST(type) \ type PLL_REF_DIV_SRC; \ type DCCG_DEEP_COLOR_CNTL1; \ @@ -81,6 +87,8 @@ type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \ type PLL_POST_DIV_PIXCLK; \ type PLL_REF_DIV; \ + type DP_DTO0_PHASE; \ + type DP_DTO0_MODULO; \ type DP_DTO0_ENABLE; struct dce110_clk_src_shift { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 9ba1bfc30146..8af201a51a2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,7 +3,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o + dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c new file mode 100644 index 000000000000..11386121f8ed --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c @@ -0,0 +1,652 @@ +/* + * Copyright 2012-17 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + +#include "reg_helper.h" +#include "core_dc.h" +#include "resource.h" +#include "dwb.h" +#include "dcn10_dwb.h" +#include "vega10/soc15ip.h" +#include "raven1/DCN/dcn_1_0_offset.h" +#include "raven1/DCN/dcn_1_0_sh_mask.h" + +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define REG(reg)\ + dwbc10->dwbc_regs->reg + +#define CTX \ + dwbc10->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + dwbc10->dwbc_shift->field_name, dwbc10->dwbc_mask->field_name + +#define TO_DCN10_DWBC(dwbc_base) \ + container_of(dwbc_base, struct dcn10_dwbc, base) + +#define DWBC_COMMON_REG_LIST_DCN1_0(inst) \ + SRI(WB_ENABLE, CNV, inst),\ + SRI(WB_EC_CONFIG, CNV, inst),\ + SRI(CNV_MODE, CNV, inst),\ + SRI(WB_SOFT_RESET, CNV, inst),\ + SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ + SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MCIF_WB, inst),\ + SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_WATERMARK, MCIF_WB, inst),\ + SRI(MCIF_WB_WARM_UP_CNTL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ + .DWB_SOURCE_SELECT = mmDWB_SOURCE_SELECT\ + +#define DWBC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh) \ + SF(CNV0_WB_ENABLE, WB_ENABLE, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_TYPE, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_EYE_SELECTION, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_NEW_CONTENT, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\ + SF(CNV0_WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_DUALSIZE_REQ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) + +#define DWBC_REG_FIELD_LIST(type) \ + type WB_ENABLE;\ + type DISPCLK_R_WB_GATE_DIS;\ + type DISPCLK_G_WB_GATE_DIS;\ + type DISPCLK_G_WBSCL_GATE_DIS;\ + type WB_LB_LS_DIS;\ + type WB_LB_SD_DIS;\ + type WB_LUT_LS_DIS;\ + type CNV_WINDOW_CROP_EN;\ + type CNV_STEREO_TYPE;\ + type CNV_INTERLACED_MODE;\ + type CNV_EYE_SELECTION;\ + type CNV_STEREO_POLARITY;\ + type CNV_INTERLACED_FIELD_ORDER;\ + type CNV_STEREO_SPLIT;\ + type CNV_NEW_CONTENT;\ + type CNV_FRAME_CAPTURE_EN;\ + type WB_SOFT_RESET;\ + type MCIF_WB_BUFMGR_ENABLE;\ + type MCIF_WB_BUF_DUALSIZE_REQ;\ + type MCIF_WB_BUFMGR_SW_INT_EN;\ + type MCIF_WB_BUFMGR_SW_INT_ACK;\ + type MCIF_WB_BUFMGR_SW_SLICE_INT_EN;\ + type MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN;\ + type MCIF_WB_BUFMGR_SW_LOCK;\ + type MCIF_WB_P_VMID;\ + type MCIF_WB_BUF_ADDR_FENCE_EN;\ + type MCIF_WB_BUF_LUMA_PITCH;\ + type MCIF_WB_BUF_CHROMA_PITCH;\ + type MCIF_WB_CLIENT_ARBITRATION_SLICE;\ + type MCIF_WB_TIME_PER_PIXEL;\ + type WM_CHANGE_ACK_FORCE_ON;\ + type MCIF_WB_CLI_WATERMARK_MASK;\ + type MCIF_WB_BUF_1_ADDR_Y;\ + type MCIF_WB_BUF_1_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_1_ADDR_C;\ + type MCIF_WB_BUF_1_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_2_ADDR_Y;\ + type MCIF_WB_BUF_2_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_2_ADDR_C;\ + type MCIF_WB_BUF_2_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_3_ADDR_Y;\ + type MCIF_WB_BUF_3_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_3_ADDR_C;\ + type MCIF_WB_BUF_3_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_4_ADDR_Y;\ + type MCIF_WB_BUF_4_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_4_ADDR_C;\ + type MCIF_WB_BUF_4_ADDR_C_OFFSET;\ + type MCIF_WB_BUFMGR_VCE_LOCK_IGNORE;\ + type MCIF_WB_BUFMGR_VCE_INT_EN;\ + type MCIF_WB_BUFMGR_VCE_INT_ACK;\ + type MCIF_WB_BUFMGR_VCE_SLICE_INT_EN;\ + type MCIF_WB_BUFMGR_VCE_LOCK;\ + type MCIF_WB_BUFMGR_SLICE_SIZE;\ + type NB_PSTATE_CHANGE_REFRESH_WATERMARK;\ + type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST;\ + type NB_PSTATE_CHANGE_FORCE_ON;\ + type NB_PSTATE_ALLOW_FOR_URGENT;\ + type NB_PSTATE_CHANGE_WATERMARK_MASK;\ + type MCIF_WB_CLI_WATERMARK;\ + type MCIF_WB_CLI_CLOCK_GATER_OVERRIDE;\ + type MCIF_WB_PITCH_SIZE_WARMUP;\ + type MCIF_WB_BUF_LUMA_SIZE;\ + type MCIF_WB_BUF_CHROMA_SIZE;\ + type OPTC_DWB0_SOURCE_SELECT;\ + type OPTC_DWB1_SOURCE_SELECT;\ + +struct dcn10_dwbc_registers { + uint32_t WB_ENABLE; + uint32_t WB_EC_CONFIG; + uint32_t CNV_MODE; + uint32_t WB_SOFT_RESET; + uint32_t MCIF_WB_BUFMGR_SW_CONTROL; + uint32_t MCIF_WB_BUF_PITCH; + uint32_t MCIF_WB_ARBITRATION_CONTROL; + uint32_t MCIF_WB_SCLK_CHANGE; + uint32_t MCIF_WB_BUF_1_ADDR_Y; + uint32_t MCIF_WB_BUF_1_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_1_ADDR_C; + uint32_t MCIF_WB_BUF_1_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_2_ADDR_Y; + uint32_t MCIF_WB_BUF_2_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_2_ADDR_C; + uint32_t MCIF_WB_BUF_2_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_3_ADDR_Y; + uint32_t MCIF_WB_BUF_3_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_3_ADDR_C; + uint32_t MCIF_WB_BUF_3_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_4_ADDR_Y; + uint32_t MCIF_WB_BUF_4_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_4_ADDR_C; + uint32_t MCIF_WB_BUF_4_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUFMGR_VCE_CONTROL; + uint32_t MCIF_WB_NB_PSTATE_LATENCY_WATERMARK; + uint32_t MCIF_WB_NB_PSTATE_CONTROL; + uint32_t MCIF_WB_WATERMARK; + uint32_t MCIF_WB_WARM_UP_CNTL; + uint32_t MCIF_WB_BUF_LUMA_SIZE; + uint32_t MCIF_WB_BUF_CHROMA_SIZE; + uint32_t DWB_SOURCE_SELECT; +}; +struct dcn10_dwbc_mask { + DWBC_REG_FIELD_LIST(uint32_t) +}; +struct dcn10_dwbc_shift { + DWBC_REG_FIELD_LIST(uint8_t) +}; +struct dcn10_dwbc { + struct dwbc base; + const struct dcn10_dwbc_registers *dwbc_regs; + const struct dcn10_dwbc_shift *dwbc_shift; + const struct dcn10_dwbc_mask *dwbc_mask; +}; + +#define dwbc_regs(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN1_0(id),\ +} + +static const struct dcn10_dwbc_registers dwbc10_regs[] = { + dwbc_regs(0), + dwbc_regs(1), +}; + +static const struct dcn10_dwbc_shift dwbc10_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn10_dwbc_mask dwbc10_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + + +static bool get_caps(struct dwbc *dwbc, struct dwb_caps *caps) +{ + if (caps) { + caps->adapter_id = 0; /* we only support 1 adapter currently */ + caps->hw_version = DCN_VERSION_1_0; + caps->num_pipes = 2; + memset(&caps->reserved, 0, sizeof(caps->reserved)); + memset(&caps->reserved2, 0, sizeof(caps->reserved2)); + caps->sw_version = dwb_ver_1_0; + caps->caps.support_dwb = true; + caps->caps.support_ogam = false; + caps->caps.support_wbscl = true; + caps->caps.support_ocsc = false; + return true; + } else { + return false; + } +} + +static bool enable(struct dwbc *dwbc) +{ + struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); + + /* disable first. */ + dwbc->funcs->disable(dwbc); + + /* disable power gating */ + REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 1, + DISPCLK_G_WB_GATE_DIS, 1, DISPCLK_G_WBSCL_GATE_DIS, 1, + WB_LB_LS_DIS, 1, WB_LUT_LS_DIS, 1); + + REG_UPDATE(WB_ENABLE, WB_ENABLE, 1); + + /* lock buffer0~buffer3 */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0xf); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, (dwbc->config.basic_settings.luma_address[0] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[0] >> 32)); */ + /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, 0); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, (dwbc->config.basic_settings.chroma_address[0] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[0] >> 32)); */ + /* right eye offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, 0); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, (dwbc->config.basic_settings.luma_address[1] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[1] >> 32)); */ + /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, 0); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, (dwbc->config.basic_settings.chroma_address[1] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[1] >> 32)); */ + /* right eye offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, 0); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, (dwbc->config.basic_settings.luma_address[2] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[2] >> 32)); */ + /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, 0); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, (dwbc->config.basic_settings.chroma_address[2] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[2] >> 32)); */ + /* right eye offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, 0); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, (dwbc->config.basic_settings.luma_address[3] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[3] >> 32)); */ + /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, 0); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, (dwbc->config.basic_settings.chroma_address[3] & 0xffffffff)); +/* REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[3] >> 32)); */ + /* right eye offset for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, 0); + + /* setup luma & chroma size */ + REG_UPDATE(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, dwbc->config.basic_settings.luma_pitch * dwbc->config.basic_settings.dest_height); /* should be enough to contain a whole frame Luma data, same for stereo mode */ + REG_UPDATE(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, dwbc->config.basic_settings.chroma_pitch * dwbc->config.basic_settings.dest_height); /* should be enough to contain a whole frame Luma data, same for stereo mode */ + + /* enable address fence */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, 1); + + /* setup pitch */ + REG_UPDATE_2(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, dwbc->config.basic_settings.luma_pitch, + MCIF_WB_BUF_CHROMA_PITCH, dwbc->config.basic_settings.chroma_pitch); + + /* Set pitch for MC cache warm up mode */ + /* Pitch is 256 bytes aligned. The default pitch is 4K */ + REG_UPDATE(MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, 0x10); /* default is 0x10 */ + + /* Programmed by the video driver based on the CRTC timing (for DWB) */ + REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, 0); + + /* Programming dwb watermark */ + /* Watermark to generate urgent in MCIF_WB_CLI, value is determined by MCIF_WB_CLI_WATERMARK_MASK. */ + /* Program in ns. A formula will be provided in the pseudo code to calculate the value. */ + REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x0); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkA */ + REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x1); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkB */ + REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x2); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkC */ + REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x3); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkD */ + + /* Programming nb pstate watermark */ + REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x0); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkA */ + REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x1); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkB */ + REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x2); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkC */ + REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x3); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkD */ + + /* buf_lh_capability = (buffer_size / byte_per_pixel)*time_per_pixel; //client buffer latency hiding capability */ + /* if (MCIF_WB_CLI_WATERMARK * 2 < buf_lh_capability) //factor '2' can be adjusted if better value is identified during bringup/debug */ + /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = MCIF_WB_CLI_WATERMARK * 2; */ + /* else */ + /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = buf_lh_capability; //ensure QoS can be fully mapped to [0:15] region in any scenario */ + + REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, 31); + + /* Set arbitration unit for Luma/Chroma */ + /* arb_unit=2 should be chosen for more efficiency */ + REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, 2); /* Arbitration size, 0: 512 bytes 1: 1024 bytes 2: 2048 Bytes */ + + /* Program VMID, don't support virtual mode, won't set VMID */ + /* REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, pVmid); */ + + if (dwbc->config.basic_settings.input_pipe_select == dwb_pipe0) { + REG_UPDATE(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, dwbc->config.basic_settings.input_src_select - dwb_src_otg0); + } else if (dwbc->config.basic_settings.input_pipe_select == dwb_pipe1) { + REG_UPDATE(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, dwbc->config.basic_settings.input_src_select - dwb_src_otg0); + } + + /* Set interrupt mask */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, 0); /* Disable interrupt to SW. (the default value is 0.) */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, 0); /* Disable slice complete interrupt to SW.(the default value is 0.) */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, 0); /* Disable frame buffer overrun interrupt to SW. (the default value is 0.) */ + + REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, 1); /* Enable interrupt to VCE */ + REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, 0); /* Disable slice complete interrupt to VCE. */ + + /* ////////////////// */ + /* Enable Mcifwb */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, 1); /* Start working */ + + /* unlock sw lock. */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0); + + dwbc->status.enabled = true; + + return true; +} + +static bool disable(struct dwbc *dwbc) +{ + struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); + + /* disable CNV */ + REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_EN, 0); + + /* disable WB */ + REG_UPDATE(WB_ENABLE, WB_ENABLE, 0); + + /* soft reset */ + REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 1); + REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 0); + + /* enable power gating */ + REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 0, + DISPCLK_G_WB_GATE_DIS, 0, DISPCLK_G_WBSCL_GATE_DIS, 0, + WB_LB_LS_DIS, 0, WB_LUT_LS_DIS, 0); + + /* disable buffer manager */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, 0); + + dwbc->status.enabled = false; + + return true; +} + +static bool get_status(struct dwbc *dwbc, struct dwb_status *status) +{ + if (status) { + memcpy(status, &dwbc->status, sizeof(struct dwb_status)); + return true; + } else { + return false; + } +} + +static bool dump_frame(struct dwbc *dwbc, struct dwb_frame_info *frame_info, + unsigned char *luma_buffer, unsigned char *chroma_buffer, + unsigned char *dest_luma_buffer, unsigned char *dest_chroma_buffer) +{ + struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); + + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0xf); + + memcpy(dest_luma_buffer, luma_buffer, dwbc->config.basic_settings.luma_pitch * dwbc->config.basic_settings.dest_height); + memcpy(dest_chroma_buffer, chroma_buffer, dwbc->config.basic_settings.chroma_pitch * dwbc->config.basic_settings.dest_height / 2); + + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0x0); + + frame_info->format = dwbc->config.advanced_settings.out_format; + frame_info->width = dwbc->config.basic_settings.dest_width; + frame_info->height = dwbc->config.basic_settings.dest_height; + frame_info->luma_pitch = dwbc->config.basic_settings.luma_pitch; + frame_info->chroma_pitch = dwbc->config.basic_settings.chroma_pitch; + frame_info->size = dwbc->config.basic_settings.dest_height * (dwbc->config.basic_settings.luma_pitch + dwbc->config.basic_settings.chroma_pitch); + + return true; +} + +static bool set_basic_settings(struct dwbc *dwbc, + const struct dwb_basic_settings *basic_settings) +{ + if (basic_settings) { + memcpy(&dwbc->config.basic_settings, basic_settings, sizeof(struct dwb_basic_settings)); + return true; + } else { + return false; + } +} + +static bool get_basic_settings(struct dwbc *dwbc, + struct dwb_basic_settings *basic_settings) +{ + if (basic_settings) { + memcpy(basic_settings, &dwbc->config.basic_settings, sizeof(struct dwb_basic_settings)); + return true; + } else { + return false; + } +} + +static bool set_advanced_settings(struct dwbc *dwbc, + const struct dwb_advanced_settings *advanced_settings) +{ + if (advanced_settings) { + if (advanced_settings->uFlag & sf_output_format) { + dwbc->config.advanced_settings.uFlag |= sf_output_format; + dwbc->config.advanced_settings.out_format = advanced_settings->out_format; + } + + if (advanced_settings->uFlag & sf_capture_rate) { + dwbc->config.advanced_settings.uFlag |= sf_capture_rate; + dwbc->config.advanced_settings.capture_rate = advanced_settings->capture_rate; + } + + return true; + } else { + return false; + } +} + +static bool get_advanced_settings(struct dwbc *dwbc, + struct dwb_advanced_settings *advanced_settings) +{ + if (advanced_settings) { + memcpy(advanced_settings, &dwbc->config.advanced_settings, sizeof(struct dwb_advanced_settings)); + return true; + } else { + return false; + } +} + +static bool reset_advanced_settings(struct dwbc *dwbc) +{ + dwbc->config.advanced_settings.uFlag = 0; + dwbc->config.advanced_settings.out_format = dwb_scaler_mode_bypass444; + dwbc->config.advanced_settings.capture_rate = dwb_capture_rate_0; + + return true; +} + +const struct dwbc_funcs dcn10_dwbc_funcs = { + .get_caps = get_caps, + .enable = enable, + .disable = disable, + .get_status = get_status, + .dump_frame = dump_frame, + .set_basic_settings = set_basic_settings, + .get_basic_settings = get_basic_settings, + .set_advanced_settings = set_advanced_settings, + .get_advanced_settings = get_advanced_settings, + .reset_advanced_settings = reset_advanced_settings, +}; + +static void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, + struct dc_context *ctx, + const struct dcn10_dwbc_registers *dwbc_regs, + const struct dcn10_dwbc_shift *dwbc_shift, + const struct dcn10_dwbc_mask *dwbc_mask, + int inst) +{ + dwbc10->base.ctx = ctx; + + dwbc10->base.inst = inst; + dwbc10->base.funcs = &dcn10_dwbc_funcs; + + dwbc10->dwbc_regs = dwbc_regs; + dwbc10->dwbc_shift = dwbc_shift; + dwbc10->dwbc_mask = dwbc_mask; +} + +bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + ASSERT(pipe_count > 0); + + for (i = 0; i < pipe_count; i++) { + struct dcn10_dwbc *dwbc10 = dm_alloc(sizeof(struct dcn10_dwbc)); + + if (!dwbc10) + return false; + + dcn10_dwbc_construct(dwbc10, ctx, + &dwbc10_regs[i], + &dwbc10_shift, + &dwbc10_mask, + i); + + pool->dwbc[i] = &dwbc10->base; + if (pool->dwbc[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc10!\n"); + return false; + } + } + return true; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h new file mode 100644 index 000000000000..cf530aed4e1c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h @@ -0,0 +1,32 @@ +/* Copyright 2012-17 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DC_DWBC_DCN10_H__ +#define __DC_DWBC_DCN10_H__ + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + +bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool); +#endif + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 6006fb4799c3..fa990a51ac83 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -32,6 +32,7 @@ #include "dcn10/dcn10_ipp.h" #include "dcn10/dcn10_mpc.h" +#include "dcn10/dcn10_dwb.h" #include "irq/dcn10/irq_service_dcn10.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_timing_generator.h" @@ -410,6 +411,7 @@ static const struct resource_caps res_cap = { .num_audio = 4, .num_stream_encoder = 4, .num_pll = 4, + .num_dwb = 2, }; static const struct dc_debug debug_defaults_drv = { @@ -1410,6 +1412,12 @@ static bool construct( goto mpc_create_fail; } +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (!dcn10_dwbc_create(ctx, &pool->base)) { + goto dwbc_create_fail; + } +#endif + if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) @@ -1432,6 +1440,7 @@ static bool construct( irqs_create_fail: res_create_fail: clock_source_create_fail: +dwbc_create_fail: destruct(pool); diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h index 47ef90495376..ebcf67b5fc57 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h @@ -166,6 +166,10 @@ struct clock_source_funcs { struct clock_source *, struct pixel_clk_params *, struct pll_settings *); + uint32_t (*get_pix_rate_in_hz)( + struct clock_source *, + struct pixel_clk_params *, + struct pll_settings *); }; struct clock_source { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 5190901ea379..28454028434c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,7 +32,10 @@ #include "ddc_service_types.h" #include "dc_bios_types.h" #include "mem_input.h" +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" +#endif +#include "dwb.h" #define MAX_CLOCK_SOURCES 7 @@ -125,6 +128,8 @@ struct resource_pool { struct mpc *mpc; #endif + struct dwbc *dwbc[MAX_DWB_PIPES]; + unsigned int pipe_count; unsigned int underlay_pipe_index; unsigned int stream_enc_count; @@ -193,6 +198,7 @@ struct pipe_ctx { struct _vcs_dpi_display_rq_regs_st rq_regs; struct _vcs_dpi_display_pipe_dest_params_st pipe_dlg_param; #endif + struct dwbc *dwbc; }; struct resource_context { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h new file mode 100644 index 000000000000..82347ba480fe --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h @@ -0,0 +1,193 @@ +/* Copyright 2012-17 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_DWBC_H__ +#define __DC_DWBC_H__ + +#include "dc_hw_types.h" + +#define MAX_DWB_PIPES 3 + +enum dce_version; + +enum dwb_sw_version { + dwb_ver_1_0 = 1, +}; + +enum dwb_source { + dwb_src_scl = 0, /* for DCE7x/9x, DCN won't support. */ + dwb_src_blnd, /* for DCE7x/9x */ + dwb_src_fmt, /* for DCE7x/9x */ +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + dwb_src_otg0 = 0x100, /* for DCN1.x, register: mmDWB_SOURCE_SELECT */ + dwb_src_otg1, /* for DCN1.x */ + dwb_src_otg2, /* for DCN1.x */ + dwb_src_otg3, /* for DCN1.x */ +#endif +}; + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +/* DCN1.x supports 2 pipes */ +#endif +enum dwb_pipe { + dwb_pipe0 = 0, +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + dwb_pipe1, +#endif + dwb_pipe_max_num, +}; + +enum setting_flags { + sf_pipe = 0x00000001, + sf_output_format = 0x00000002, + sf_capture_rate = 0x00000004, + sf_all = 0xffffffff, +}; + +enum dwb_capture_rate { + + dwb_capture_rate_0 = 0, /* Every frame is captured. */ + dwb_capture_rate_1 = 1, /* Every other frame is captured. */ + dwb_capture_rate_2 = 2, /* Every 3rd frame is captured. */ + dwb_capture_rate_3 = 3, /* Every 4th frame is captured. */ +}; + +enum dwb_scaler_mode { + dwb_scaler_mode_bypass444 = 0, + dwb_scaler_mode_rgb444 = 1, + dwb_scaler_mode_yuv444 = 2, + dwb_scaler_mode_yuv420 = 3 +}; + +struct dwb_caps { + enum dce_version hw_version; /* DCN engine version. */ + enum dwb_sw_version sw_version; /* DWB sw implementation version. */ + unsigned int reserved[6]; /* Reserved for future use, MUST BE 0. */ + unsigned int adapter_id; + unsigned int num_pipes; /* number of DWB pipes */ + struct { + unsigned int support_dwb :1; + unsigned int support_ogam :1; + unsigned int support_wbscl :1; + unsigned int support_ocsc :1; + } caps; + unsigned int reserved2[10]; /* Reserved for future use, MUST BE 0. */ +}; + +struct dwb_status { + bool enabled; + /* Reserved ========================================================================= */ + unsigned int reserved[8]; /* Reserved fields */ +}; + +struct dwb_basic_settings { + /* General DWB related input parameters ============================================= */ + enum dwb_source input_src_select; /* Select input source: (DCE) 0: SCL; 1: BLND; 2: FMT; (DCN) OTG* or MPC* */ + enum dwb_pipe input_pipe_select; /* Select input pipe: 0: PIPE0; 1: PIPE1; 2: PIPE2 */ + + /* CNV: WND Related parameters ====================================================== */ + unsigned int capture_rate; /* Captures once every (capture_rate+1) frames */ + + /* CNV: CSC Related parameters ====================================================== */ + unsigned int start_x; /* Horizontal window start position */ + unsigned int start_y; /* Vertical window start position */ + unsigned int src_width; /* Width of window captured within source window */ + unsigned int src_height; /* Height of window captured within source window */ + + /* SISCL Related parameters ========================================================= */ + unsigned int dest_width; /* Destination width */ + unsigned int dest_height; /* Destination height */ + + /* MCIF bufer parameters ========================================================= */ + unsigned long long luma_address[4]; + unsigned long long chroma_address[4]; + unsigned int luma_pitch; + unsigned int chroma_pitch; + unsigned int slice_lines; + + /* Reserved ========================================================================= */ + unsigned int reserved[8]; /* Reserved fields */ + +}; + +struct dwb_advanced_settings { + enum setting_flags uFlag; + enum dwb_pipe pipe; /* default = DWB_PIPE_ALL */ + enum dwb_scaler_mode out_format; /* default = DWBScalerMode_YUV420 */ + enum dwb_capture_rate capture_rate; /* default = Every frame is captured */ + unsigned int reserved[64]; /* reserved for future use, must be 0 */ +}; + +/* / - dwb_frame_info is the info of the dumping data */ +struct dwb_frame_info { + unsigned int size; + unsigned int width; + unsigned int height; + unsigned int luma_pitch; + unsigned int chroma_pitch; + enum dwb_scaler_mode format; +}; + +struct dwbc_cfg { + struct dwb_basic_settings basic_settings; + struct dwb_advanced_settings advanced_settings; +}; + +struct dwbc { + const struct dwbc_funcs *funcs; + struct dc_context *ctx; + struct dwbc_cfg config; + struct dwb_status status; + int inst; +}; + +struct dwbc_funcs { + bool (*get_caps)(struct dwbc *dwbc, struct dwb_caps *caps); + + bool (*enable)(struct dwbc *dwbc); + + bool (*disable)(struct dwbc *dwbc); + + bool (*get_status)(struct dwbc *dwbc, struct dwb_status *status); + + bool (*dump_frame)(struct dwbc *dwbc, struct dwb_frame_info *frame_info, + unsigned char *luma_buffer, unsigned char *chroma_buffer, + unsigned char *dest_luma_buffer, unsigned char *dest_chroma_buffer); + + bool (*set_basic_settings)(struct dwbc *dwbc, + const struct dwb_basic_settings *basic_settings); + + bool (*get_basic_settings)(struct dwbc *dwbc, + struct dwb_basic_settings *basic_settings); + + bool (*set_advanced_settings)(struct dwbc *dwbc, + const struct dwb_advanced_settings *advanced_settings); + + bool (*get_advanced_settings)(struct dwbc *dwbc, + struct dwb_advanced_settings *advanced_settings); + + bool (*reset_advanced_settings)(struct dwbc *dwbc); +}; + +#endif -- GitLab From 77a4ea53fd89ccf823e77cc31cea808a3589f732 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Wed, 2 Aug 2017 16:56:03 -0400 Subject: [PATCH 0780/2898] drm/amd/display: change bw_dceip and bw_vbios into pointers -Change bw_calcs_dceip into pointer -Change bw_calcs_vbios into pointer This is needed for flattening of core_dc into dc, as without this the diags build fails Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 ++++++++++ .../display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../amd/display/dc/dce110/dce110_resource.c | 34 ++++++------- .../amd/display/dc/dce112/dce112_resource.c | 50 +++++++++---------- .../amd/display/dc/dce120/dce120_resource.c | 24 ++++----- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 4 +- 6 files changed, 83 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index aeed95a5d097..477024c467e6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -433,6 +433,13 @@ static void destruct(struct core_dc *dc) dm_free(dc->ctx); dc->ctx = NULL; + + dm_free(dc->bw_vbios); + dc->bw_vbios = NULL; + + dm_free(dc->bw_dceip); + dc->bw_dceip = NULL; + } static bool construct(struct core_dc *dc, @@ -440,8 +447,25 @@ static bool construct(struct core_dc *dc, { struct dal_logger *logger; struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx)); + struct bw_calcs_dceip *dc_dceip = dm_alloc(sizeof(*dc_dceip)); + struct bw_calcs_vbios *dc_vbios = dm_alloc(sizeof(*dc_vbios)); + enum dce_version dc_version = DCE_VERSION_UNKNOWN; + if (!dc_dceip) { + dm_error("%s: failed to create dceip\n", __func__); + goto dceip_fail; + } + + dc->bw_dceip = dc_dceip; + + if (!dc_vbios) { + dm_error("%s: failed to create vbios\n", __func__); + goto vbios_fail; + } + + dc->bw_vbios = dc_vbios; + if (!dc_ctx) { dm_error("%s: failed to create ctx\n", __func__); goto ctx_fail; @@ -544,6 +568,8 @@ static bool construct(struct core_dc *dc, logger_fail: val_ctx_fail: ctx_fail: +dceip_fail: +vbios_fail: destruct(dc); return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5b46e776b9b7..ccde7c80d658 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1264,7 +1264,7 @@ void dce110_set_displaymarks( continue; total_dest_line_time_ns = compute_pstate_blackout_duration( - dc->bw_vbios.blackout_duration, pipe_ctx->stream); + dc->bw_vbios->blackout_duration, pipe_ctx->stream); pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks( pipe_ctx->plane_res.mi, context->bw.dce.nbp_state_change_wm_ns[num_pipes], diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index a7f30dcc906c..56be84ce5a0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -826,8 +826,8 @@ static bool dce110_validate_bandwidth( if (bw_calcs( dc->ctx, - &dc->bw_dceip, - &dc->bw_vbios, + dc->bw_dceip, + dc->bw_vbios, context->res_ctx.pipe_ctx, dc->res_pool->pipe_count, &context->bw.dce)) @@ -1127,21 +1127,21 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) DM_PP_CLOCK_TYPE_ENGINE_CLK, &clks); /* convert all the clock fro kHz to fix point mHz */ - dc->bw_vbios.high_sclk = bw_frc_to_fixed( + dc->bw_vbios->high_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels/8], 1000); - dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*2/8], 1000); - dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*3/8], 1000); - dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*4/8], 1000); - dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*5/8], 1000); - dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*6/8], 1000); - dc->bw_vbios.low_sclk = bw_frc_to_fixed( + dc->bw_vbios->low_sclk = bw_frc_to_fixed( clks.clocks_in_khz[0], 1000); dc->sclk_lvls = clks; @@ -1150,11 +1150,11 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) dc->ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clks); - dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed( + dc->bw_vbios->high_voltage_max_dispclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios.mid_voltage_max_dispclk = bw_frc_to_fixed( + dc->bw_vbios->mid_voltage_max_dispclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels>>1], 1000); - dc->bw_vbios.low_voltage_max_dispclk = bw_frc_to_fixed( + dc->bw_vbios->low_voltage_max_dispclk = bw_frc_to_fixed( clks.clocks_in_khz[0], 1000); /*do memory clock*/ @@ -1163,12 +1163,12 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks); - dc->bw_vbios.low_yclk = bw_frc_to_fixed( + dc->bw_vbios->low_yclk = bw_frc_to_fixed( clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.high_yclk = bw_frc_to_fixed( + dc->bw_vbios->high_yclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, 1000); } @@ -1353,7 +1353,7 @@ static bool construct( dc->public.caps.max_planes = pool->base.pipe_count; - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 420434d7283e..d6e58a25f3d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -771,8 +771,8 @@ bool dce112_validate_bandwidth( if (bw_calcs( dc->ctx, - &dc->bw_dceip, - &dc->bw_vbios, + dc->bw_dceip, + dc->bw_vbios, context->res_ctx.pipe_ctx, dc->res_pool->pipe_count, &context->bw.dce)) @@ -1018,21 +1018,21 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) DM_PP_CLOCK_TYPE_ENGINE_CLK, &clks); /* convert all the clock fro kHz to fix point mHz */ - dc->bw_vbios.high_sclk = bw_frc_to_fixed( + dc->bw_vbios->high_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels/8], 1000); - dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*2/8], 1000); - dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*3/8], 1000); - dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*4/8], 1000); - dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*5/8], 1000); - dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels*6/8], 1000); - dc->bw_vbios.low_sclk = bw_frc_to_fixed( + dc->bw_vbios->low_sclk = bw_frc_to_fixed( clks.clocks_in_khz[0], 1000); /*do memory clock*/ @@ -1041,12 +1041,12 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) DM_PP_CLOCK_TYPE_MEMORY_CLK, &clks); - dc->bw_vbios.low_yclk = bw_frc_to_fixed( + dc->bw_vbios->low_yclk = bw_frc_to_fixed( clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.high_yclk = bw_frc_to_fixed( + dc->bw_vbios->high_yclk = bw_frc_to_fixed( clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER, 1000); @@ -1054,21 +1054,21 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) } /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ - dc->bw_vbios.high_sclk = bw_frc_to_fixed( + dc->bw_vbios->high_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); - dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); - dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); - dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); - dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); - dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); - dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); - dc->bw_vbios.low_sclk = bw_frc_to_fixed( + dc->bw_vbios->low_sclk = bw_frc_to_fixed( eng_clks.data[0].clocks_in_khz, 1000); /*do memory clock*/ @@ -1082,12 +1082,12 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): * YCLK = UMACLK*m_memoryTypeMultiplier */ - dc->bw_vbios.low_yclk = bw_frc_to_fixed( + dc->bw_vbios->low_yclk = bw_frc_to_fixed( mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.high_yclk = bw_frc_to_fixed( + dc->bw_vbios->high_yclk = bw_frc_to_fixed( mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); @@ -1325,7 +1325,7 @@ static bool construct( if (!dce112_hw_sequencer_construct(dc)) goto res_create_fail; - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index d4e962756fbb..562ae2205a90 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -729,21 +729,21 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) } /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ - dc->bw_vbios.high_sclk = bw_frc_to_fixed( + dc->bw_vbios->high_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); - dc->bw_vbios.mid1_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); - dc->bw_vbios.mid2_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); - dc->bw_vbios.mid3_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); - dc->bw_vbios.mid4_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); - dc->bw_vbios.mid5_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); - dc->bw_vbios.mid6_sclk = bw_frc_to_fixed( + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); - dc->bw_vbios.low_sclk = bw_frc_to_fixed( + dc->bw_vbios->low_sclk = bw_frc_to_fixed( eng_clks.data[0].clocks_in_khz, 1000); /*do memory clock*/ @@ -770,12 +770,12 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): * YCLK = UMACLK*m_memoryTypeMultiplier */ - dc->bw_vbios.low_yclk = bw_frc_to_fixed( + dc->bw_vbios->low_yclk = bw_frc_to_fixed( mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.mid_yclk = bw_frc_to_fixed( + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); - dc->bw_vbios.high_yclk = bw_frc_to_fixed( + dc->bw_vbios->high_yclk = bw_frc_to_fixed( mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000); @@ -984,7 +984,7 @@ static bool construct( dc->public.caps.max_planes = pool->base.pipe_count; - bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id); + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); bw_calcs_data_update_from_pplib(dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 1ecb54603e17..982f7170f5d2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -29,8 +29,8 @@ struct core_dc { struct dm_pp_clock_levels sclk_lvls; /* Inputs into BW and WM calculations. */ - struct bw_calcs_dceip bw_dceip; - struct bw_calcs_vbios bw_vbios; + struct bw_calcs_dceip *bw_dceip; + struct bw_calcs_vbios *bw_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct dcn_soc_bounding_box dcn_soc; struct dcn_ip_params dcn_ip; -- GitLab From e771aae02baa59386972faec491cd221c169ed53 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Wed, 9 Aug 2017 10:30:28 -0400 Subject: [PATCH 0781/2898] drm/amd/display: Add comment explaining context free This comment explains a previous change that adds some complexity to the context free in dc: commit 9ad58779a895 ("drm/amd/display: Fix accessing freed memory") Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 477024c467e6..33c3d88b1c86 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1740,6 +1740,15 @@ void dc_update_planes_and_stream(struct dc *dc, } if (core_dc->current_context != context) { + + /* Since memory free requires elevated IRQL, an interrupt + * request is generated by mem free. If this happens + * between freeing and reassigning the context, our vsync + * interrupt will call into dc and cause a memory + * corruption BSOD. Hence, we first reassign the context, + * then free the old context. + */ + struct validate_context *old = core_dc->current_context; core_dc->current_context = context; -- GitLab From 65111f25f1fea751f3b4321a59c993c2898b7dbf Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 3 Aug 2017 13:02:29 -0400 Subject: [PATCH 0782/2898] drm/amd/display: change dcn_ip and dcn_soc into pointers -Change dcn_ip into pointer -Change dcn_soc into pointer This is needed for flattening of core_dc into dc, as without this the diags build fails Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 553 +++++++++--------- drivers/gpu/drm/amd/display/dc/core/dc.c | 59 +- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 28 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 4 +- 4 files changed, 331 insertions(+), 313 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 67da973c898b..6fb1b9a91993 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -457,7 +457,7 @@ static void dcn_bw_calc_rq_dlg_ttu( } /*todo: soc->sr_enter_plus_exit_time??*/ - dlg_sys_param.t_srx_delay_us = dc->dcn_ip.dcfclk_cstate_latency / v->dcf_clk_deep_sleep; + dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; dml_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); extract_rq_regs(dml, rq_regs, rq_param); @@ -679,39 +679,39 @@ static bool dcn_bw_apply_registry_override(struct core_dc *dc) bool updated = false; kernel_fpu_begin(); - if ((int)(dc->dcn_soc.sr_exit_time * 1000) != dc->public.debug.sr_exit_time_ns + if ((int)(dc->dcn_soc->sr_exit_time * 1000) != dc->public.debug.sr_exit_time_ns && dc->public.debug.sr_exit_time_ns) { updated = true; - dc->dcn_soc.sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; + dc->dcn_soc->sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; } - if ((int)(dc->dcn_soc.sr_enter_plus_exit_time * 1000) + if ((int)(dc->dcn_soc->sr_enter_plus_exit_time * 1000) != dc->public.debug.sr_enter_plus_exit_time_ns && dc->public.debug.sr_enter_plus_exit_time_ns) { updated = true; - dc->dcn_soc.sr_enter_plus_exit_time = + dc->dcn_soc->sr_enter_plus_exit_time = dc->public.debug.sr_enter_plus_exit_time_ns / 1000.0; } - if ((int)(dc->dcn_soc.urgent_latency * 1000) != dc->public.debug.urgent_latency_ns + if ((int)(dc->dcn_soc->urgent_latency * 1000) != dc->public.debug.urgent_latency_ns && dc->public.debug.urgent_latency_ns) { updated = true; - dc->dcn_soc.urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; + dc->dcn_soc->urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; } - if ((int)(dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency * 1000) + if ((int)(dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency * 1000) != dc->public.debug.percent_of_ideal_drambw && dc->public.debug.percent_of_ideal_drambw) { updated = true; - dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency = + dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency = dc->public.debug.percent_of_ideal_drambw; } - if ((int)(dc->dcn_soc.dram_clock_change_latency * 1000) + if ((int)(dc->dcn_soc->dram_clock_change_latency * 1000) != dc->public.debug.dram_clock_change_latency_ns && dc->public.debug.dram_clock_change_latency_ns) { updated = true; - dc->dcn_soc.dram_clock_change_latency = + dc->dcn_soc->dram_clock_change_latency = dc->public.debug.dram_clock_change_latency_ns / 1000.0; } kernel_fpu_end(); @@ -735,83 +735,83 @@ bool dcn_validate_bandwidth( memset(v, 0, sizeof(*v)); kernel_fpu_begin(); - v->sr_exit_time = dc->dcn_soc.sr_exit_time; - v->sr_enter_plus_exit_time = dc->dcn_soc.sr_enter_plus_exit_time; - v->urgent_latency = dc->dcn_soc.urgent_latency; - v->write_back_latency = dc->dcn_soc.write_back_latency; + v->sr_exit_time = dc->dcn_soc->sr_exit_time; + v->sr_enter_plus_exit_time = dc->dcn_soc->sr_enter_plus_exit_time; + v->urgent_latency = dc->dcn_soc->urgent_latency; + v->write_back_latency = dc->dcn_soc->write_back_latency; v->percent_of_ideal_drambw_received_after_urg_latency = - dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency; - - v->dcfclkv_min0p65 = dc->dcn_soc.dcfclkv_min0p65; - v->dcfclkv_mid0p72 = dc->dcn_soc.dcfclkv_mid0p72; - v->dcfclkv_nom0p8 = dc->dcn_soc.dcfclkv_nom0p8; - v->dcfclkv_max0p9 = dc->dcn_soc.dcfclkv_max0p9; - - v->max_dispclk_vmin0p65 = dc->dcn_soc.max_dispclk_vmin0p65; - v->max_dispclk_vmid0p72 = dc->dcn_soc.max_dispclk_vmid0p72; - v->max_dispclk_vnom0p8 = dc->dcn_soc.max_dispclk_vnom0p8; - v->max_dispclk_vmax0p9 = dc->dcn_soc.max_dispclk_vmax0p9; - - v->max_dppclk_vmin0p65 = dc->dcn_soc.max_dppclk_vmin0p65; - v->max_dppclk_vmid0p72 = dc->dcn_soc.max_dppclk_vmid0p72; - v->max_dppclk_vnom0p8 = dc->dcn_soc.max_dppclk_vnom0p8; - v->max_dppclk_vmax0p9 = dc->dcn_soc.max_dppclk_vmax0p9; - - v->socclk = dc->dcn_soc.socclk; - - v->fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65; - v->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72; - v->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8; - v->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9; - - v->phyclkv_min0p65 = dc->dcn_soc.phyclkv_min0p65; - v->phyclkv_mid0p72 = dc->dcn_soc.phyclkv_mid0p72; - v->phyclkv_nom0p8 = dc->dcn_soc.phyclkv_nom0p8; - v->phyclkv_max0p9 = dc->dcn_soc.phyclkv_max0p9; - - v->downspreading = dc->dcn_soc.downspreading; - v->round_trip_ping_latency_cycles = dc->dcn_soc.round_trip_ping_latency_cycles; - v->urgent_out_of_order_return_per_channel = dc->dcn_soc.urgent_out_of_order_return_per_channel; - v->number_of_channels = dc->dcn_soc.number_of_channels; - v->vmm_page_size = dc->dcn_soc.vmm_page_size; - v->dram_clock_change_latency = dc->dcn_soc.dram_clock_change_latency; - v->return_bus_width = dc->dcn_soc.return_bus_width; - - v->rob_buffer_size_in_kbyte = dc->dcn_ip.rob_buffer_size_in_kbyte; - v->det_buffer_size_in_kbyte = dc->dcn_ip.det_buffer_size_in_kbyte; - v->dpp_output_buffer_pixels = dc->dcn_ip.dpp_output_buffer_pixels; - v->opp_output_buffer_lines = dc->dcn_ip.opp_output_buffer_lines; - v->pixel_chunk_size_in_kbyte = dc->dcn_ip.pixel_chunk_size_in_kbyte; - v->pte_enable = dc->dcn_ip.pte_enable; - v->pte_chunk_size = dc->dcn_ip.pte_chunk_size; - v->meta_chunk_size = dc->dcn_ip.meta_chunk_size; - v->writeback_chunk_size = dc->dcn_ip.writeback_chunk_size; - v->odm_capability = dc->dcn_ip.odm_capability; - v->dsc_capability = dc->dcn_ip.dsc_capability; - v->line_buffer_size = dc->dcn_ip.line_buffer_size; - v->is_line_buffer_bpp_fixed = dc->dcn_ip.is_line_buffer_bpp_fixed; - v->line_buffer_fixed_bpp = dc->dcn_ip.line_buffer_fixed_bpp; - v->max_line_buffer_lines = dc->dcn_ip.max_line_buffer_lines; - v->writeback_luma_buffer_size = dc->dcn_ip.writeback_luma_buffer_size; - v->writeback_chroma_buffer_size = dc->dcn_ip.writeback_chroma_buffer_size; - v->max_num_dpp = dc->dcn_ip.max_num_dpp; - v->max_num_writeback = dc->dcn_ip.max_num_writeback; - v->max_dchub_topscl_throughput = dc->dcn_ip.max_dchub_topscl_throughput; - v->max_pscl_tolb_throughput = dc->dcn_ip.max_pscl_tolb_throughput; - v->max_lb_tovscl_throughput = dc->dcn_ip.max_lb_tovscl_throughput; - v->max_vscl_tohscl_throughput = dc->dcn_ip.max_vscl_tohscl_throughput; - v->max_hscl_ratio = dc->dcn_ip.max_hscl_ratio; - v->max_vscl_ratio = dc->dcn_ip.max_vscl_ratio; - v->max_hscl_taps = dc->dcn_ip.max_hscl_taps; - v->max_vscl_taps = dc->dcn_ip.max_vscl_taps; - v->under_scan_factor = dc->dcn_ip.under_scan_factor; - v->pte_buffer_size_in_requests = dc->dcn_ip.pte_buffer_size_in_requests; - v->dispclk_ramping_margin = dc->dcn_ip.dispclk_ramping_margin; - v->max_inter_dcn_tile_repeaters = dc->dcn_ip.max_inter_dcn_tile_repeaters; + dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency; + + v->dcfclkv_min0p65 = dc->dcn_soc->dcfclkv_min0p65; + v->dcfclkv_mid0p72 = dc->dcn_soc->dcfclkv_mid0p72; + v->dcfclkv_nom0p8 = dc->dcn_soc->dcfclkv_nom0p8; + v->dcfclkv_max0p9 = dc->dcn_soc->dcfclkv_max0p9; + + v->max_dispclk_vmin0p65 = dc->dcn_soc->max_dispclk_vmin0p65; + v->max_dispclk_vmid0p72 = dc->dcn_soc->max_dispclk_vmid0p72; + v->max_dispclk_vnom0p8 = dc->dcn_soc->max_dispclk_vnom0p8; + v->max_dispclk_vmax0p9 = dc->dcn_soc->max_dispclk_vmax0p9; + + v->max_dppclk_vmin0p65 = dc->dcn_soc->max_dppclk_vmin0p65; + v->max_dppclk_vmid0p72 = dc->dcn_soc->max_dppclk_vmid0p72; + v->max_dppclk_vnom0p8 = dc->dcn_soc->max_dppclk_vnom0p8; + v->max_dppclk_vmax0p9 = dc->dcn_soc->max_dppclk_vmax0p9; + + v->socclk = dc->dcn_soc->socclk; + + v->fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65; + v->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72; + v->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8; + v->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9; + + v->phyclkv_min0p65 = dc->dcn_soc->phyclkv_min0p65; + v->phyclkv_mid0p72 = dc->dcn_soc->phyclkv_mid0p72; + v->phyclkv_nom0p8 = dc->dcn_soc->phyclkv_nom0p8; + v->phyclkv_max0p9 = dc->dcn_soc->phyclkv_max0p9; + + v->downspreading = dc->dcn_soc->downspreading; + v->round_trip_ping_latency_cycles = dc->dcn_soc->round_trip_ping_latency_cycles; + v->urgent_out_of_order_return_per_channel = dc->dcn_soc->urgent_out_of_order_return_per_channel; + v->number_of_channels = dc->dcn_soc->number_of_channels; + v->vmm_page_size = dc->dcn_soc->vmm_page_size; + v->dram_clock_change_latency = dc->dcn_soc->dram_clock_change_latency; + v->return_bus_width = dc->dcn_soc->return_bus_width; + + v->rob_buffer_size_in_kbyte = dc->dcn_ip->rob_buffer_size_in_kbyte; + v->det_buffer_size_in_kbyte = dc->dcn_ip->det_buffer_size_in_kbyte; + v->dpp_output_buffer_pixels = dc->dcn_ip->dpp_output_buffer_pixels; + v->opp_output_buffer_lines = dc->dcn_ip->opp_output_buffer_lines; + v->pixel_chunk_size_in_kbyte = dc->dcn_ip->pixel_chunk_size_in_kbyte; + v->pte_enable = dc->dcn_ip->pte_enable; + v->pte_chunk_size = dc->dcn_ip->pte_chunk_size; + v->meta_chunk_size = dc->dcn_ip->meta_chunk_size; + v->writeback_chunk_size = dc->dcn_ip->writeback_chunk_size; + v->odm_capability = dc->dcn_ip->odm_capability; + v->dsc_capability = dc->dcn_ip->dsc_capability; + v->line_buffer_size = dc->dcn_ip->line_buffer_size; + v->is_line_buffer_bpp_fixed = dc->dcn_ip->is_line_buffer_bpp_fixed; + v->line_buffer_fixed_bpp = dc->dcn_ip->line_buffer_fixed_bpp; + v->max_line_buffer_lines = dc->dcn_ip->max_line_buffer_lines; + v->writeback_luma_buffer_size = dc->dcn_ip->writeback_luma_buffer_size; + v->writeback_chroma_buffer_size = dc->dcn_ip->writeback_chroma_buffer_size; + v->max_num_dpp = dc->dcn_ip->max_num_dpp; + v->max_num_writeback = dc->dcn_ip->max_num_writeback; + v->max_dchub_topscl_throughput = dc->dcn_ip->max_dchub_topscl_throughput; + v->max_pscl_tolb_throughput = dc->dcn_ip->max_pscl_tolb_throughput; + v->max_lb_tovscl_throughput = dc->dcn_ip->max_lb_tovscl_throughput; + v->max_vscl_tohscl_throughput = dc->dcn_ip->max_vscl_tohscl_throughput; + v->max_hscl_ratio = dc->dcn_ip->max_hscl_ratio; + v->max_vscl_ratio = dc->dcn_ip->max_vscl_ratio; + v->max_hscl_taps = dc->dcn_ip->max_hscl_taps; + v->max_vscl_taps = dc->dcn_ip->max_vscl_taps; + v->under_scan_factor = dc->dcn_ip->under_scan_factor; + v->pte_buffer_size_in_requests = dc->dcn_ip->pte_buffer_size_in_requests; + v->dispclk_ramping_margin = dc->dcn_ip->dispclk_ramping_margin; + v->max_inter_dcn_tile_repeaters = dc->dcn_ip->max_inter_dcn_tile_repeaters; v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = - dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; v->bug_forcing_luma_and_chroma_request_to_same_size_fixed = - dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed; + dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed; v->voltage[5] = dcn_bw_no_support; v->voltage[4] = dcn_bw_v_max0p9; @@ -1021,7 +1021,7 @@ bool dcn_validate_bandwidth( context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); if (dc->public.debug.max_disp_clk == true) - context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc.max_dispclk_vmax0p9 * 1000); + context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000); context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { @@ -1118,15 +1118,15 @@ bool dcn_validate_bandwidth( struct core_dc *dc_core = DC_TO_CORE(&dc->public); dc_core->dml.soc.sr_enter_plus_exit_time_us = - dc_core->dcn_soc.sr_enter_plus_exit_time; - dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc.sr_exit_time; + dc_core->dcn_soc->sr_enter_plus_exit_time; + dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc->sr_exit_time; } /* * BW limit is set to prevent display from impacting other system functions */ - bw_limit = dc->dcn_soc.percent_disp_bw_limit * v->fabric_and_dram_bandwidth_vmax0p9; + bw_limit = dc->dcn_soc->percent_disp_bw_limit * v->fabric_and_dram_bandwidth_vmax0p9; bw_limit_pass = (v->total_data_read_bandwidth / 1000.0) < bw_limit; kernel_fpu_end(); @@ -1149,41 +1149,41 @@ unsigned int dcn_find_normalized_clock_vdd_Level( switch (clocks_type) { case DM_PP_CLOCK_TYPE_DISPLAY_CLK: - if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmax0p9*1000) { + if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmax0p9*1000) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vnom0p8*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dispclk_vnom0p8*1000) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmid0p72*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmid0p72*1000) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.max_dispclk_vmin0p65*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dispclk_vmin0p65*1000) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; break; case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK: - if (clocks_in_khz > dc->dcn_soc.phyclkv_max0p9*1000) { + if (clocks_in_khz > dc->dcn_soc->phyclkv_max0p9*1000) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.phyclkv_nom0p8*1000) { + } else if (clocks_in_khz > dc->dcn_soc->phyclkv_nom0p8*1000) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.phyclkv_mid0p72*1000) { + } else if (clocks_in_khz > dc->dcn_soc->phyclkv_mid0p72*1000) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.phyclkv_min0p65*1000) { + } else if (clocks_in_khz > dc->dcn_soc->phyclkv_min0p65*1000) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; break; case DM_PP_CLOCK_TYPE_DPPCLK: - if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmax0p9*1000) { + if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmax0p9*1000) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vnom0p8*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dppclk_vnom0p8*1000) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmid0p72*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmid0p72*1000) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.max_dppclk_vmin0p65*1000) { + } else if (clocks_in_khz > dc->dcn_soc->max_dppclk_vmin0p65*1000) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; @@ -1191,15 +1191,16 @@ unsigned int dcn_find_normalized_clock_vdd_Level( case DM_PP_CLOCK_TYPE_MEMORY_CLK: { - unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); - if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9*1000000/factor) { + unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); + + if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9*1000000/factor) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8*1000000/factor) { + } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8*1000000/factor) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72*1000000/factor) { + } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72*1000000/factor) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65*1000000/factor) { + } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65*1000000/factor) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; @@ -1207,14 +1208,14 @@ unsigned int dcn_find_normalized_clock_vdd_Level( break; case DM_PP_CLOCK_TYPE_DCFCLK: - if (clocks_in_khz > dc->dcn_soc.dcfclkv_max0p9*1000) { + if (clocks_in_khz > dc->dcn_soc->dcfclkv_max0p9*1000) { vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); - } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_nom0p8*1000) { + } else if (clocks_in_khz > dc->dcn_soc->dcfclkv_nom0p8*1000) { vdd_level = dcn_bw_v_max0p9; - } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_mid0p72*1000) { + } else if (clocks_in_khz > dc->dcn_soc->dcfclkv_mid0p72*1000) { vdd_level = dcn_bw_v_nom0p8; - } else if (clocks_in_khz > dc->dcn_soc.dcfclkv_min0p65*1000) { + } else if (clocks_in_khz > dc->dcn_soc->dcfclkv_min0p65*1000) { vdd_level = dcn_bw_v_mid0p72; } else vdd_level = dcn_bw_v_min0p65; @@ -1254,15 +1255,15 @@ unsigned int dcn_find_dcfclk_suits_all( vdd_level = dcn_bw_max(vdd_level, vdd_level_temp); if (vdd_level == dcn_bw_v_max0p91) { BREAK_TO_DEBUGGER(); - dcf_clk = dc->dcn_soc.dcfclkv_max0p9*1000; + dcf_clk = dc->dcn_soc->dcfclkv_max0p9*1000; } else if (vdd_level == dcn_bw_v_max0p9) - dcf_clk = dc->dcn_soc.dcfclkv_max0p9*1000; + dcf_clk = dc->dcn_soc->dcfclkv_max0p9*1000; else if (vdd_level == dcn_bw_v_nom0p8) - dcf_clk = dc->dcn_soc.dcfclkv_nom0p8*1000; + dcf_clk = dc->dcn_soc->dcfclkv_nom0p8*1000; else if (vdd_level == dcn_bw_v_mid0p72) - dcf_clk = dc->dcn_soc.dcfclkv_mid0p72*1000; + dcf_clk = dc->dcn_soc->dcfclkv_mid0p72*1000; else - dcf_clk = dc->dcn_soc.dcfclkv_min0p65*1000; + dcf_clk = dc->dcn_soc->dcfclkv_min0p65*1000; dm_logger_write(dc->ctx->logger, LOG_HW_MARKS, "\tdcf_clk for voltage = %d\n", dcf_clk); @@ -1282,27 +1283,27 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) ctx, DM_PP_CLOCK_TYPE_FCLK, &clks) && clks.num_levels != 0) { ASSERT(clks.num_levels >= 3); - dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 32 * (clks.data[0].clocks_in_khz / 1000.0) / 1000.0; + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 32 * (clks.data[0].clocks_in_khz / 1000.0) / 1000.0; if (clks.num_levels > 2) { - dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels * (clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; } else { - dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc.number_of_channels * + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels * (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; } - dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc.number_of_channels * + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc->number_of_channels * (clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc.number_of_channels * + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc->number_of_channels * (clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 1000.0; } else BREAK_TO_DEBUGGER(); if (dm_pp_get_clock_levels_by_type_with_voltage( ctx, DM_PP_CLOCK_TYPE_DCFCLK, &clks) && clks.num_levels >= 3) { - dc->dcn_soc.dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; - dc->dcn_soc.dcfclkv_mid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; - dc->dcn_soc.dcfclkv_nom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; - dc->dcn_soc.dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_min0p65 = clks.data[0].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_mid0p72 = clks.data[clks.num_levels - 3].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_nom0p8 = clks.data[clks.num_levels - 2].clocks_in_khz / 1000.0; + dc->dcn_soc->dcfclkv_max0p9 = clks.data[clks.num_levels - 1].clocks_in_khz / 1000.0; } else BREAK_TO_DEBUGGER(); @@ -1315,17 +1316,17 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz; const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ - unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc.number_of_channels); + unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); kernel_fpu_begin(); - max_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; - nom_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; - mid_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 * 1000000 / factor; - min_fclk_khz = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; - max_dcfclk_khz = dc->dcn_soc.dcfclkv_max0p9 * 1000; - nom_dcfclk_khz = dc->dcn_soc.dcfclkv_nom0p8 * 1000; - min_dcfclk_khz = dc->dcn_soc.dcfclkv_min0p65 * 1000; - socclk_khz = dc->dcn_soc.socclk * 1000; + max_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; + nom_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; + mid_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 * 1000000 / factor; + min_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; + max_dcfclk_khz = dc->dcn_soc->dcfclkv_max0p9 * 1000; + nom_dcfclk_khz = dc->dcn_soc->dcfclkv_nom0p8 * 1000; + min_dcfclk_khz = dc->dcn_soc->dcfclkv_min0p65 * 1000; + socclk_khz = dc->dcn_soc->socclk * 1000; kernel_fpu_end(); /* Now notify PPLib/SMU about which Watermarks sets they should select @@ -1425,40 +1426,40 @@ void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) "vmm_page_size: %d Bytes\n" "dram_clock_change_latency: %d ns\n" "return_bus_width: %d Bytes\n", - dc->dcn_soc.sr_exit_time * 1000, - dc->dcn_soc.sr_enter_plus_exit_time * 1000, - dc->dcn_soc.urgent_latency * 1000, - dc->dcn_soc.write_back_latency * 1000, - dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency, - dc->dcn_soc.max_request_size, - dc->dcn_soc.dcfclkv_max0p9 * 1000, - dc->dcn_soc.dcfclkv_nom0p8 * 1000, - dc->dcn_soc.dcfclkv_mid0p72 * 1000, - dc->dcn_soc.dcfclkv_min0p65 * 1000, - dc->dcn_soc.max_dispclk_vmax0p9 * 1000, - dc->dcn_soc.max_dispclk_vnom0p8 * 1000, - dc->dcn_soc.max_dispclk_vmid0p72 * 1000, - dc->dcn_soc.max_dispclk_vmin0p65 * 1000, - dc->dcn_soc.max_dppclk_vmax0p9 * 1000, - dc->dcn_soc.max_dppclk_vnom0p8 * 1000, - dc->dcn_soc.max_dppclk_vmid0p72 * 1000, - dc->dcn_soc.max_dppclk_vmin0p65 * 1000, - dc->dcn_soc.socclk * 1000, - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 * 1000, - dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 * 1000, - dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 * 1000, - dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 * 1000, - dc->dcn_soc.phyclkv_max0p9 * 1000, - dc->dcn_soc.phyclkv_nom0p8 * 1000, - dc->dcn_soc.phyclkv_mid0p72 * 1000, - dc->dcn_soc.phyclkv_min0p65 * 1000, - dc->dcn_soc.downspreading * 100, - dc->dcn_soc.round_trip_ping_latency_cycles, - dc->dcn_soc.urgent_out_of_order_return_per_channel, - dc->dcn_soc.number_of_channels, - dc->dcn_soc.vmm_page_size, - dc->dcn_soc.dram_clock_change_latency * 1000, - dc->dcn_soc.return_bus_width); + dc->dcn_soc->sr_exit_time * 1000, + dc->dcn_soc->sr_enter_plus_exit_time * 1000, + dc->dcn_soc->urgent_latency * 1000, + dc->dcn_soc->write_back_latency * 1000, + dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency, + dc->dcn_soc->max_request_size, + dc->dcn_soc->dcfclkv_max0p9 * 1000, + dc->dcn_soc->dcfclkv_nom0p8 * 1000, + dc->dcn_soc->dcfclkv_mid0p72 * 1000, + dc->dcn_soc->dcfclkv_min0p65 * 1000, + dc->dcn_soc->max_dispclk_vmax0p9 * 1000, + dc->dcn_soc->max_dispclk_vnom0p8 * 1000, + dc->dcn_soc->max_dispclk_vmid0p72 * 1000, + dc->dcn_soc->max_dispclk_vmin0p65 * 1000, + dc->dcn_soc->max_dppclk_vmax0p9 * 1000, + dc->dcn_soc->max_dppclk_vnom0p8 * 1000, + dc->dcn_soc->max_dppclk_vmid0p72 * 1000, + dc->dcn_soc->max_dppclk_vmin0p65 * 1000, + dc->dcn_soc->socclk * 1000, + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 * 1000, + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 * 1000, + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 * 1000, + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 * 1000, + dc->dcn_soc->phyclkv_max0p9 * 1000, + dc->dcn_soc->phyclkv_nom0p8 * 1000, + dc->dcn_soc->phyclkv_mid0p72 * 1000, + dc->dcn_soc->phyclkv_min0p65 * 1000, + dc->dcn_soc->downspreading * 100, + dc->dcn_soc->round_trip_ping_latency_cycles, + dc->dcn_soc->urgent_out_of_order_return_per_channel, + dc->dcn_soc->number_of_channels, + dc->dcn_soc->vmm_page_size, + dc->dcn_soc->dram_clock_change_latency * 1000, + dc->dcn_soc->return_bus_width); dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, "rob_buffer_size_in_kbyte: %d\n" "det_buffer_size_in_kbyte: %d\n" @@ -1494,120 +1495,120 @@ void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) "can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one: %d\n" "bug_forcing_luma_and_chroma_request_to_same_size_fixed: %d\n" "dcfclk_cstate_latency: %d\n", - dc->dcn_ip.rob_buffer_size_in_kbyte, - dc->dcn_ip.det_buffer_size_in_kbyte, - dc->dcn_ip.dpp_output_buffer_pixels, - dc->dcn_ip.opp_output_buffer_lines, - dc->dcn_ip.pixel_chunk_size_in_kbyte, - dc->dcn_ip.pte_enable, - dc->dcn_ip.pte_chunk_size, - dc->dcn_ip.meta_chunk_size, - dc->dcn_ip.writeback_chunk_size, - dc->dcn_ip.odm_capability, - dc->dcn_ip.dsc_capability, - dc->dcn_ip.line_buffer_size, - dc->dcn_ip.max_line_buffer_lines, - dc->dcn_ip.is_line_buffer_bpp_fixed, - dc->dcn_ip.line_buffer_fixed_bpp, - dc->dcn_ip.writeback_luma_buffer_size, - dc->dcn_ip.writeback_chroma_buffer_size, - dc->dcn_ip.max_num_dpp, - dc->dcn_ip.max_num_writeback, - dc->dcn_ip.max_dchub_topscl_throughput, - dc->dcn_ip.max_pscl_tolb_throughput, - dc->dcn_ip.max_lb_tovscl_throughput, - dc->dcn_ip.max_vscl_tohscl_throughput, - dc->dcn_ip.max_hscl_ratio, - dc->dcn_ip.max_vscl_ratio, - dc->dcn_ip.max_hscl_taps, - dc->dcn_ip.max_vscl_taps, - dc->dcn_ip.pte_buffer_size_in_requests, - dc->dcn_ip.dispclk_ramping_margin, - dc->dcn_ip.under_scan_factor * 100, - dc->dcn_ip.max_inter_dcn_tile_repeaters, - dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one, - dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed, - dc->dcn_ip.dcfclk_cstate_latency); - dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc.socclk; - dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc.socclk; - dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc.socclk; - dc->dml.soc.vmax.socclk_mhz = dc->dcn_soc.socclk; - - dc->dml.soc.vmin.dcfclk_mhz = dc->dcn_soc.dcfclkv_min0p65; - dc->dml.soc.vmid.dcfclk_mhz = dc->dcn_soc.dcfclkv_mid0p72; - dc->dml.soc.vnom.dcfclk_mhz = dc->dcn_soc.dcfclkv_nom0p8; - dc->dml.soc.vmax.dcfclk_mhz = dc->dcn_soc.dcfclkv_max0p9; - - dc->dml.soc.vmin.dispclk_mhz = dc->dcn_soc.max_dispclk_vmin0p65; - dc->dml.soc.vmid.dispclk_mhz = dc->dcn_soc.max_dispclk_vmid0p72; - dc->dml.soc.vnom.dispclk_mhz = dc->dcn_soc.max_dispclk_vnom0p8; - dc->dml.soc.vmax.dispclk_mhz = dc->dcn_soc.max_dispclk_vmax0p9; - - dc->dml.soc.vmin.dppclk_mhz = dc->dcn_soc.max_dppclk_vmin0p65; - dc->dml.soc.vmid.dppclk_mhz = dc->dcn_soc.max_dppclk_vmid0p72; - dc->dml.soc.vnom.dppclk_mhz = dc->dcn_soc.max_dppclk_vnom0p8; - dc->dml.soc.vmax.dppclk_mhz = dc->dcn_soc.max_dppclk_vmax0p9; - - dc->dml.soc.vmin.phyclk_mhz = dc->dcn_soc.phyclkv_min0p65; - dc->dml.soc.vmid.phyclk_mhz = dc->dcn_soc.phyclkv_mid0p72; - dc->dml.soc.vnom.phyclk_mhz = dc->dcn_soc.phyclkv_nom0p8; - dc->dml.soc.vmax.phyclk_mhz = dc->dcn_soc.phyclkv_max0p9; - - dc->dml.soc.vmin.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65; - dc->dml.soc.vmid.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72; - dc->dml.soc.vnom.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8; - dc->dml.soc.vmax.dram_bw_per_chan_gbps = dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9; - - dc->dml.soc.sr_exit_time_us = dc->dcn_soc.sr_exit_time; - dc->dml.soc.sr_enter_plus_exit_time_us = dc->dcn_soc.sr_enter_plus_exit_time; - dc->dml.soc.urgent_latency_us = dc->dcn_soc.urgent_latency; - dc->dml.soc.writeback_latency_us = dc->dcn_soc.write_back_latency; + dc->dcn_ip->rob_buffer_size_in_kbyte, + dc->dcn_ip->det_buffer_size_in_kbyte, + dc->dcn_ip->dpp_output_buffer_pixels, + dc->dcn_ip->opp_output_buffer_lines, + dc->dcn_ip->pixel_chunk_size_in_kbyte, + dc->dcn_ip->pte_enable, + dc->dcn_ip->pte_chunk_size, + dc->dcn_ip->meta_chunk_size, + dc->dcn_ip->writeback_chunk_size, + dc->dcn_ip->odm_capability, + dc->dcn_ip->dsc_capability, + dc->dcn_ip->line_buffer_size, + dc->dcn_ip->max_line_buffer_lines, + dc->dcn_ip->is_line_buffer_bpp_fixed, + dc->dcn_ip->line_buffer_fixed_bpp, + dc->dcn_ip->writeback_luma_buffer_size, + dc->dcn_ip->writeback_chroma_buffer_size, + dc->dcn_ip->max_num_dpp, + dc->dcn_ip->max_num_writeback, + dc->dcn_ip->max_dchub_topscl_throughput, + dc->dcn_ip->max_pscl_tolb_throughput, + dc->dcn_ip->max_lb_tovscl_throughput, + dc->dcn_ip->max_vscl_tohscl_throughput, + dc->dcn_ip->max_hscl_ratio, + dc->dcn_ip->max_vscl_ratio, + dc->dcn_ip->max_hscl_taps, + dc->dcn_ip->max_vscl_taps, + dc->dcn_ip->pte_buffer_size_in_requests, + dc->dcn_ip->dispclk_ramping_margin, + dc->dcn_ip->under_scan_factor * 100, + dc->dcn_ip->max_inter_dcn_tile_repeaters, + dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one, + dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed, + dc->dcn_ip->dcfclk_cstate_latency); + dc->dml.soc.vmin.socclk_mhz = dc->dcn_soc->socclk; + dc->dml.soc.vmid.socclk_mhz = dc->dcn_soc->socclk; + dc->dml.soc.vnom.socclk_mhz = dc->dcn_soc->socclk; + dc->dml.soc.vmax.socclk_mhz = dc->dcn_soc->socclk; + + dc->dml.soc.vmin.dcfclk_mhz = dc->dcn_soc->dcfclkv_min0p65; + dc->dml.soc.vmid.dcfclk_mhz = dc->dcn_soc->dcfclkv_mid0p72; + dc->dml.soc.vnom.dcfclk_mhz = dc->dcn_soc->dcfclkv_nom0p8; + dc->dml.soc.vmax.dcfclk_mhz = dc->dcn_soc->dcfclkv_max0p9; + + dc->dml.soc.vmin.dispclk_mhz = dc->dcn_soc->max_dispclk_vmin0p65; + dc->dml.soc.vmid.dispclk_mhz = dc->dcn_soc->max_dispclk_vmid0p72; + dc->dml.soc.vnom.dispclk_mhz = dc->dcn_soc->max_dispclk_vnom0p8; + dc->dml.soc.vmax.dispclk_mhz = dc->dcn_soc->max_dispclk_vmax0p9; + + dc->dml.soc.vmin.dppclk_mhz = dc->dcn_soc->max_dppclk_vmin0p65; + dc->dml.soc.vmid.dppclk_mhz = dc->dcn_soc->max_dppclk_vmid0p72; + dc->dml.soc.vnom.dppclk_mhz = dc->dcn_soc->max_dppclk_vnom0p8; + dc->dml.soc.vmax.dppclk_mhz = dc->dcn_soc->max_dppclk_vmax0p9; + + dc->dml.soc.vmin.phyclk_mhz = dc->dcn_soc->phyclkv_min0p65; + dc->dml.soc.vmid.phyclk_mhz = dc->dcn_soc->phyclkv_mid0p72; + dc->dml.soc.vnom.phyclk_mhz = dc->dcn_soc->phyclkv_nom0p8; + dc->dml.soc.vmax.phyclk_mhz = dc->dcn_soc->phyclkv_max0p9; + + dc->dml.soc.vmin.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65; + dc->dml.soc.vmid.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72; + dc->dml.soc.vnom.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8; + dc->dml.soc.vmax.dram_bw_per_chan_gbps = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9; + + dc->dml.soc.sr_exit_time_us = dc->dcn_soc->sr_exit_time; + dc->dml.soc.sr_enter_plus_exit_time_us = dc->dcn_soc->sr_enter_plus_exit_time; + dc->dml.soc.urgent_latency_us = dc->dcn_soc->urgent_latency; + dc->dml.soc.writeback_latency_us = dc->dcn_soc->write_back_latency; dc->dml.soc.ideal_dram_bw_after_urgent_percent = - dc->dcn_soc.percent_of_ideal_drambw_received_after_urg_latency; - dc->dml.soc.max_request_size_bytes = dc->dcn_soc.max_request_size; - dc->dml.soc.downspread_percent = dc->dcn_soc.downspreading; + dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency; + dc->dml.soc.max_request_size_bytes = dc->dcn_soc->max_request_size; + dc->dml.soc.downspread_percent = dc->dcn_soc->downspreading; dc->dml.soc.round_trip_ping_latency_dcfclk_cycles = - dc->dcn_soc.round_trip_ping_latency_cycles; + dc->dcn_soc->round_trip_ping_latency_cycles; dc->dml.soc.urgent_out_of_order_return_per_channel_bytes = - dc->dcn_soc.urgent_out_of_order_return_per_channel; - dc->dml.soc.num_chans = dc->dcn_soc.number_of_channels; - dc->dml.soc.vmm_page_size_bytes = dc->dcn_soc.vmm_page_size; - dc->dml.soc.dram_clock_change_latency_us = dc->dcn_soc.dram_clock_change_latency; - dc->dml.soc.return_bus_width_bytes = dc->dcn_soc.return_bus_width; - - dc->dml.ip.rob_buffer_size_kbytes = dc->dcn_ip.rob_buffer_size_in_kbyte; - dc->dml.ip.det_buffer_size_kbytes = dc->dcn_ip.det_buffer_size_in_kbyte; - dc->dml.ip.dpp_output_buffer_pixels = dc->dcn_ip.dpp_output_buffer_pixels; - dc->dml.ip.opp_output_buffer_lines = dc->dcn_ip.opp_output_buffer_lines; - dc->dml.ip.pixel_chunk_size_kbytes = dc->dcn_ip.pixel_chunk_size_in_kbyte; - dc->dml.ip.pte_enable = dc->dcn_ip.pte_enable == dcn_bw_yes; - dc->dml.ip.pte_chunk_size_kbytes = dc->dcn_ip.pte_chunk_size; - dc->dml.ip.meta_chunk_size_kbytes = dc->dcn_ip.meta_chunk_size; - dc->dml.ip.writeback_chunk_size_kbytes = dc->dcn_ip.writeback_chunk_size; - dc->dml.ip.line_buffer_size_bits = dc->dcn_ip.line_buffer_size; - dc->dml.ip.max_line_buffer_lines = dc->dcn_ip.max_line_buffer_lines; - dc->dml.ip.IsLineBufferBppFixed = dc->dcn_ip.is_line_buffer_bpp_fixed == dcn_bw_yes; - dc->dml.ip.LineBufferFixedBpp = dc->dcn_ip.line_buffer_fixed_bpp; - dc->dml.ip.writeback_luma_buffer_size_kbytes = dc->dcn_ip.writeback_luma_buffer_size; - dc->dml.ip.writeback_chroma_buffer_size_kbytes = dc->dcn_ip.writeback_chroma_buffer_size; - dc->dml.ip.max_num_dpp = dc->dcn_ip.max_num_dpp; - dc->dml.ip.max_num_wb = dc->dcn_ip.max_num_writeback; - dc->dml.ip.max_dchub_pscl_bw_pix_per_clk = dc->dcn_ip.max_dchub_topscl_throughput; - dc->dml.ip.max_pscl_lb_bw_pix_per_clk = dc->dcn_ip.max_pscl_tolb_throughput; - dc->dml.ip.max_lb_vscl_bw_pix_per_clk = dc->dcn_ip.max_lb_tovscl_throughput; - dc->dml.ip.max_vscl_hscl_bw_pix_per_clk = dc->dcn_ip.max_vscl_tohscl_throughput; - dc->dml.ip.max_hscl_ratio = dc->dcn_ip.max_hscl_ratio; - dc->dml.ip.max_vscl_ratio = dc->dcn_ip.max_vscl_ratio; - dc->dml.ip.max_hscl_taps = dc->dcn_ip.max_hscl_taps; - dc->dml.ip.max_vscl_taps = dc->dcn_ip.max_vscl_taps; + dc->dcn_soc->urgent_out_of_order_return_per_channel; + dc->dml.soc.num_chans = dc->dcn_soc->number_of_channels; + dc->dml.soc.vmm_page_size_bytes = dc->dcn_soc->vmm_page_size; + dc->dml.soc.dram_clock_change_latency_us = dc->dcn_soc->dram_clock_change_latency; + dc->dml.soc.return_bus_width_bytes = dc->dcn_soc->return_bus_width; + + dc->dml.ip.rob_buffer_size_kbytes = dc->dcn_ip->rob_buffer_size_in_kbyte; + dc->dml.ip.det_buffer_size_kbytes = dc->dcn_ip->det_buffer_size_in_kbyte; + dc->dml.ip.dpp_output_buffer_pixels = dc->dcn_ip->dpp_output_buffer_pixels; + dc->dml.ip.opp_output_buffer_lines = dc->dcn_ip->opp_output_buffer_lines; + dc->dml.ip.pixel_chunk_size_kbytes = dc->dcn_ip->pixel_chunk_size_in_kbyte; + dc->dml.ip.pte_enable = dc->dcn_ip->pte_enable == dcn_bw_yes; + dc->dml.ip.pte_chunk_size_kbytes = dc->dcn_ip->pte_chunk_size; + dc->dml.ip.meta_chunk_size_kbytes = dc->dcn_ip->meta_chunk_size; + dc->dml.ip.writeback_chunk_size_kbytes = dc->dcn_ip->writeback_chunk_size; + dc->dml.ip.line_buffer_size_bits = dc->dcn_ip->line_buffer_size; + dc->dml.ip.max_line_buffer_lines = dc->dcn_ip->max_line_buffer_lines; + dc->dml.ip.IsLineBufferBppFixed = dc->dcn_ip->is_line_buffer_bpp_fixed == dcn_bw_yes; + dc->dml.ip.LineBufferFixedBpp = dc->dcn_ip->line_buffer_fixed_bpp; + dc->dml.ip.writeback_luma_buffer_size_kbytes = dc->dcn_ip->writeback_luma_buffer_size; + dc->dml.ip.writeback_chroma_buffer_size_kbytes = dc->dcn_ip->writeback_chroma_buffer_size; + dc->dml.ip.max_num_dpp = dc->dcn_ip->max_num_dpp; + dc->dml.ip.max_num_wb = dc->dcn_ip->max_num_writeback; + dc->dml.ip.max_dchub_pscl_bw_pix_per_clk = dc->dcn_ip->max_dchub_topscl_throughput; + dc->dml.ip.max_pscl_lb_bw_pix_per_clk = dc->dcn_ip->max_pscl_tolb_throughput; + dc->dml.ip.max_lb_vscl_bw_pix_per_clk = dc->dcn_ip->max_lb_tovscl_throughput; + dc->dml.ip.max_vscl_hscl_bw_pix_per_clk = dc->dcn_ip->max_vscl_tohscl_throughput; + dc->dml.ip.max_hscl_ratio = dc->dcn_ip->max_hscl_ratio; + dc->dml.ip.max_vscl_ratio = dc->dcn_ip->max_vscl_ratio; + dc->dml.ip.max_hscl_taps = dc->dcn_ip->max_hscl_taps; + dc->dml.ip.max_vscl_taps = dc->dcn_ip->max_vscl_taps; /*pte_buffer_size_in_requests missing in dml*/ - dc->dml.ip.dispclk_ramp_margin_percent = dc->dcn_ip.dispclk_ramping_margin; - dc->dml.ip.underscan_factor = dc->dcn_ip.under_scan_factor; - dc->dml.ip.max_inter_dcn_tile_repeaters = dc->dcn_ip.max_inter_dcn_tile_repeaters; + dc->dml.ip.dispclk_ramp_margin_percent = dc->dcn_ip->dispclk_ramping_margin; + dc->dml.ip.underscan_factor = dc->dcn_ip->under_scan_factor; + dc->dml.ip.max_inter_dcn_tile_repeaters = dc->dcn_ip->max_inter_dcn_tile_repeaters; dc->dml.ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = - dc->dcn_ip.can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes; + dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one == dcn_bw_yes; dc->dml.ip.bug_forcing_LC_req_same_size_fixed = - dc->dcn_ip.bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes; - dc->dml.ip.dcfclk_cstate_latency = dc->dcn_ip.dcfclk_cstate_latency; + dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed == dcn_bw_yes; + dc->dml.ip.dcfclk_cstate_latency = dc->dcn_ip->dcfclk_cstate_latency; kernel_fpu_end(); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 33c3d88b1c86..40d65b758994 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -440,6 +440,13 @@ static void destruct(struct core_dc *dc) dm_free(dc->bw_dceip); dc->bw_dceip = NULL; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + dm_free(dc->dcn_soc); + dc->dcn_soc = NULL; + + dm_free(dc->dcn_ip); + dc->dcn_ip = NULL; +#endif } static bool construct(struct core_dc *dc, @@ -449,33 +456,52 @@ static bool construct(struct core_dc *dc, struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx)); struct bw_calcs_dceip *dc_dceip = dm_alloc(sizeof(*dc_dceip)); struct bw_calcs_vbios *dc_vbios = dm_alloc(sizeof(*dc_vbios)); +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct dcn_soc_bounding_box *dcn_soc = dm_alloc(sizeof(*dcn_soc)); + struct dcn_ip_params *dcn_ip = dm_alloc(sizeof(*dcn_ip)); +#endif enum dce_version dc_version = DCE_VERSION_UNKNOWN; if (!dc_dceip) { dm_error("%s: failed to create dceip\n", __func__); - goto dceip_fail; + goto fail; } dc->bw_dceip = dc_dceip; if (!dc_vbios) { dm_error("%s: failed to create vbios\n", __func__); - goto vbios_fail; + goto fail; } dc->bw_vbios = dc_vbios; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + if (!dcn_soc) { + dm_error("%s: failed to create dcn_soc\n", __func__); + goto fail; + } + + dc->dcn_soc = dcn_soc; + + if (!dcn_ip) { + dm_error("%s: failed to create dcn_ip\n", __func__); + goto fail; + } + + dc->dcn_ip = dcn_ip; +#endif if (!dc_ctx) { dm_error("%s: failed to create ctx\n", __func__); - goto ctx_fail; + goto fail; } dc->current_context = dm_alloc(sizeof(*dc->current_context)); if (!dc->current_context) { dm_error("%s: failed to create validate ctx\n", __func__); - goto val_ctx_fail; + goto fail; } atomic_inc(&dc->current_context->ref_count); @@ -491,7 +517,7 @@ static bool construct(struct core_dc *dc, if (!logger) { /* can *not* call logger. call base driver 'print error' */ dm_error("%s: failed to create Logger!\n", __func__); - goto logger_fail; + goto fail; } dc_ctx->logger = logger; dc->ctx = dc_ctx; @@ -519,7 +545,7 @@ static bool construct(struct core_dc *dc, if (!dc_ctx->dc_bios) { ASSERT_CRITICAL(false); - goto bios_fail; + goto fail; } dc_ctx->created_bios = true; @@ -530,7 +556,7 @@ static bool construct(struct core_dc *dc, if (!dc_ctx->i2caux) { ASSERT_CRITICAL(false); - goto failed_to_create_i2caux; + goto fail; } /* Create GPIO service */ @@ -541,7 +567,7 @@ static bool construct(struct core_dc *dc, if (!dc_ctx->gpio_service) { ASSERT_CRITICAL(false); - goto gpio_fail; + goto fail; } dc->res_pool = dc_create_resource_pool( @@ -550,26 +576,17 @@ static bool construct(struct core_dc *dc, dc_version, init_params->asic_id); if (!dc->res_pool) - goto create_resource_fail; + goto fail; if (!create_links(dc, init_params->num_virtual_links)) - goto create_links_fail; + goto fail; allocate_dc_stream_funcs(dc); return true; - /**** error handling here ****/ -create_links_fail: -create_resource_fail: -gpio_fail: -failed_to_create_i2caux: -bios_fail: -logger_fail: -val_ctx_fail: -ctx_fail: -dceip_fail: -vbios_fail: +fail: + destruct(dc); return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index fa990a51ac83..c36843d497ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1322,28 +1322,28 @@ static bool construct( } dml_init_instance(&dc->dml, DML_PROJECT_RAVEN1); - dc->dcn_ip = dcn10_ip_defaults; - dc->dcn_soc = dcn10_soc_defaults; + memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults)); + memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults)); if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc.urgent_latency = 3; + dc->dcn_soc->urgent_latency = 3; dc->public.debug.disable_dmcu = true; - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 41.60f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; } - dc->dcn_soc.number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; - ASSERT(dc->dcn_soc.number_of_channels < 3); - if (dc->dcn_soc.number_of_channels == 0)/*old sbios bug*/ - dc->dcn_soc.number_of_channels = 2; + dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc->number_of_channels < 3); + if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc->number_of_channels = 2; - if (dc->dcn_soc.number_of_channels == 1) { - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 19.2f; - dc->dcn_soc.fabric_and_dram_bandwidth_vnom0p8 = 17.066f; - dc->dcn_soc.fabric_and_dram_bandwidth_vmid0p72 = 14.933f; - dc->dcn_soc.fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + if (dc->dcn_soc->number_of_channels == 1) { + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f; + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f; if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc.fabric_and_dram_bandwidth_vmax0p9 = 20.80f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f; } } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h index 982f7170f5d2..ebe1fd78a92a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h @@ -32,8 +32,8 @@ struct core_dc { struct bw_calcs_dceip *bw_dceip; struct bw_calcs_vbios *bw_vbios; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box dcn_soc; - struct dcn_ip_params dcn_ip; + struct dcn_soc_bounding_box *dcn_soc; + struct dcn_ip_params *dcn_ip; struct display_mode_lib dml; #endif -- GitLab From b8e9eb7259f744fdc2e34f008e4af211ce0df19a Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 9 Aug 2017 14:03:34 -0400 Subject: [PATCH 0783/2898] drm/amd/display: fix eDP bootup/S4 backlight on also pass-in correct dispclk tor DMCU Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 12 +++++----- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 22 ++++++++++++------- .../drm/amd/display/dc/dce/dce_link_encoder.c | 2 ++ .../drm/amd/display/dc/inc/hw/display_clock.h | 2 +- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1d69bd25e07b..0d33e179d9f7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -169,16 +169,14 @@ static void update_num_audio( unsigned int *num_audio, struct audio_support *aud_support) { + aud_support->dp_audio = true; + aud_support->hdmi_audio_native = false; + aud_support->hdmi_audio_on_dongle = false; + if (straps->hdmi_disable == 0) { - aud_support->hdmi_audio_native = true; - aud_support->hdmi_audio_on_dongle = true; - aud_support->dp_audio = true; - } else { if (straps->dc_pinstraps_audio & 0x2) { aud_support->hdmi_audio_on_dongle = true; - aud_support->dp_audio = true; - } else { - aud_support->dp_audio = true; + aud_support->hdmi_audio_native = true; } } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index a73228b97da5..7bb2eaf07da5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -327,13 +327,14 @@ static bool dce_clock_set_min_clocks_state( return true; } -static void dce_set_clock( +static int dce_set_clock( struct display_clock *clk, int requested_clk_khz) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_pixel_clock_parameters pxl_clk_params = { 0 }; struct dc_bios *bp = clk->ctx->dc_bios; + int actual_clock = requested_clk_khz; /* Make sure requested clock isn't lower than minimum threshold*/ if (requested_clk_khz > 0) @@ -351,15 +352,17 @@ static void dce_set_clock( /* Cache the fixed display clock*/ clk_dce->dfs_bypass_disp_clk = pxl_clk_params.dfs_bypass_display_clock; + actual_clock = pxl_clk_params.dfs_bypass_display_clock; } /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ if (requested_clk_khz == 0) clk->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; + return actual_clock; } -static void dce_psr_set_clock( +static int dce_psr_set_clock( struct display_clock *clk, int requested_clk_khz) { @@ -367,13 +370,15 @@ static void dce_psr_set_clock( struct dc_context *ctx = clk_dce->base.ctx; struct core_dc *core_dc = DC_TO_CORE(ctx->dc); struct dmcu *dmcu = core_dc->res_pool->dmcu; + int actual_clk_khz = requested_clk_khz; - dce_set_clock(clk, requested_clk_khz); + actual_clk_khz = dce_set_clock(clk, requested_clk_khz); - dmcu->funcs->set_psr_wait_loop(dmcu, requested_clk_khz / 1000 / 7); + dmcu->funcs->set_psr_wait_loop(dmcu, actual_clk_khz / 1000 / 7); + return actual_clk_khz; } -static void dce112_set_clock( +static int dce112_set_clock( struct display_clock *clk, int requested_clk_khz) { @@ -383,7 +388,7 @@ static void dce112_set_clock( struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); struct abm *abm = core_dc->res_pool->abm; struct dmcu *dmcu = core_dc->res_pool->dmcu; - + int actual_clock = requested_clk_khz; /* Prepare to program display clock*/ memset(&dce_clk_params, 0, sizeof(dce_clk_params)); @@ -397,6 +402,7 @@ static void dce112_set_clock( dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK; bp->funcs->set_dce_clock(bp, &dce_clk_params); + actual_clock = dce_clk_params.target_clock_frequency; /* from power down, we need mark the clock state as ClocksStateNominal * from HWReset, so when resume we will call pplib voltage regulator.*/ @@ -415,8 +421,8 @@ static void dce112_set_clock( if (abm->funcs->is_dmcu_initialized(abm)) dmcu->funcs->set_psr_wait_loop(dmcu, - requested_clk_khz / 1000 / 7); - + actual_clock / 1000 / 7); + return actual_clock; } static void dce_clock_read_integrated_info(struct dce_disp_clk *clk_dce) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 7e9afab8fca0..0dab5bacde3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1288,6 +1288,8 @@ void dce110_link_encoder_disable_output( /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ return; } + if (enc110->base.connector.id == CONNECTOR_ID_EDP) + dce110_link_encoder_edp_backlight_control(enc, false); /* Power-down RX and disable GPU PHY should be paired. * Disabling PHY without powering down RX may cause * symbol lock loss, on which we will get DP Sink interrupt. */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h index 879c3db7cba6..f5f69cd81f6f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h @@ -62,7 +62,7 @@ struct display_clock { }; struct display_clock_funcs { - void (*set_clock)(struct display_clock *disp_clk, + int (*set_clock)(struct display_clock *disp_clk, int requested_clock_khz); enum dm_pp_clocks_state (*get_required_clocks_state)( -- GitLab From 503a7c6f2518be909fa61276ee002846524b588b Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 3 Aug 2017 10:19:58 -0400 Subject: [PATCH 0784/2898] drm/amd/display: Use function pointer for update_plane_addr Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 0d33e179d9f7..d2b8f27416d6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -132,7 +132,7 @@ struct resource_pool *dc_create_resource_pool( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case DCN_VERSION_1_0: res_pool = dcn10_create_resource_pool( - num_virtual_links, dc); + num_virtual_links, dc); break; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index cc707bd615dc..922af2d1b91a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -615,6 +615,7 @@ static uint32_t dce110_get_pll_pixel_rate_in_hz( /* This function need separate to different DCE version, before separate, just use pixel clock */ return pipe_ctx->stream->phy_pix_clk; + } static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7b943e1837ce..184627c8685e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1246,7 +1246,7 @@ static void toggle_watermark_change_req(struct dce_hwseq *hws) DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); } -static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) +static void dcn10_update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; @@ -2115,7 +2115,7 @@ static void update_dchubp_dpp( */ REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); - update_plane_addr(dc, pipe_ctx); + dc->hwss.update_plane_addr(dc, pipe_ctx); mi->funcs->mem_input_setup( mi, @@ -2687,7 +2687,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .set_plane_config = set_plane_config, - .update_plane_addr = update_plane_addr, + .update_plane_addr = dcn10_update_plane_addr, .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, .set_input_transfer_func = dcn10_set_input_transfer_func, -- GitLab From fb3466a450cc4684654367ae2f47fc3fc7846574 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 1 Aug 2017 15:00:25 -0400 Subject: [PATCH 0785/2898] drm/amd/display: Flattening core_dc to dc -Flattening core_dc to dc Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 73 ++++---- drivers/gpu/drm/amd/display/dc/core/dc.c | 162 +++++++++--------- .../gpu/drm/amd/display/dc/core/dc_debug.c | 20 +-- .../drm/amd/display/dc/core/dc_hw_sequencer.c | 3 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 19 +- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 1 - .../drm/amd/display/dc/core/dc_link_hwss.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 22 +-- .../gpu/drm/amd/display/dc/core/dc_stream.c | 14 +- .../gpu/drm/amd/display/dc/core/dc_surface.c | 10 +- drivers/gpu/drm/amd/display/dc/dc.h | 71 ++++++-- .../drm/amd/display/dc/dce/dce_clock_source.c | 5 +- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 10 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.c | 4 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 2 +- .../display/dc/dce100/dce100_hw_sequencer.c | 9 +- .../display/dc/dce100/dce100_hw_sequencer.h | 6 +- .../amd/display/dc/dce100/dce100_resource.c | 22 +-- .../amd/display/dc/dce100/dce100_resource.h | 4 +- .../display/dc/dce110/dce110_hw_sequencer.c | 72 ++++---- .../display/dc/dce110/dce110_hw_sequencer.h | 12 +- .../amd/display/dc/dce110/dce110_resource.c | 26 +-- .../amd/display/dc/dce110/dce110_resource.h | 4 +- .../display/dc/dce112/dce112_hw_sequencer.c | 5 +- .../display/dc/dce112/dce112_hw_sequencer.h | 4 +- .../amd/display/dc/dce112/dce112_resource.c | 26 +-- .../amd/display/dc/dce112/dce112_resource.h | 10 +- .../display/dc/dce120/dce120_hw_sequencer.c | 5 +- .../display/dc/dce120/dce120_hw_sequencer.h | 4 +- .../amd/display/dc/dce120/dce120_resource.c | 18 +- .../amd/display/dc/dce120/dce120_resource.h | 4 +- .../amd/display/dc/dce80/dce80_hw_sequencer.c | 5 +- .../amd/display/dc/dce80/dce80_hw_sequencer.h | 4 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 46 ++--- .../drm/amd/display/dc/dce80/dce80_resource.h | 8 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c | 1 - .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 108 ++++++------ .../amd/display/dc/dcn10/dcn10_hw_sequencer.h | 4 +- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 34 ++-- .../drm/amd/display/dc/dcn10/dcn10_resource.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/core_dc.h | 55 ------ .../gpu/drm/amd/display/dc/inc/core_types.h | 8 +- .../gpu/drm/amd/display/dc/inc/dce_calcs.h | 2 +- .../gpu/drm/amd/display/dc/inc/dcn_calcs.h | 12 +- .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 1 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 50 +++--- drivers/gpu/drm/amd/display/dc/inc/resource.h | 15 +- .../dc/irq/dce110/irq_service_dce110.c | 6 +- .../display/dc/irq/dce80/irq_service_dce80.c | 1 - .../amd/display/include/logger_interface.h | 10 +- .../amd/display/modules/freesync/freesync.c | 11 +- 51 files changed, 507 insertions(+), 527 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/core_dc.h diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6fb1b9a91993..f0dfd3c3c12c 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -27,7 +27,6 @@ #include "dcn_calcs.h" #include "dcn_calc_auto.h" #include "dc.h" -#include "core_dc.h" #include "dal_asic_id.h" #include "resource.h" @@ -399,7 +398,7 @@ static void pipe_ctx_to_e2e_pipe_params ( } static void dcn_bw_calc_rq_dlg_ttu( - const struct core_dc *dc, + const struct dc *dc, const struct dcn_bw_internal_vars *v, struct pipe_ctx *pipe, int in_idx) @@ -674,45 +673,45 @@ static void calc_wm_sets_and_perf_params( context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; } -static bool dcn_bw_apply_registry_override(struct core_dc *dc) +static bool dcn_bw_apply_registry_override(struct dc *dc) { bool updated = false; kernel_fpu_begin(); - if ((int)(dc->dcn_soc->sr_exit_time * 1000) != dc->public.debug.sr_exit_time_ns - && dc->public.debug.sr_exit_time_ns) { + if ((int)(dc->dcn_soc->sr_exit_time * 1000) != dc->debug.sr_exit_time_ns + && dc->debug.sr_exit_time_ns) { updated = true; - dc->dcn_soc->sr_exit_time = dc->public.debug.sr_exit_time_ns / 1000.0; + dc->dcn_soc->sr_exit_time = dc->debug.sr_exit_time_ns / 1000.0; } if ((int)(dc->dcn_soc->sr_enter_plus_exit_time * 1000) - != dc->public.debug.sr_enter_plus_exit_time_ns - && dc->public.debug.sr_enter_plus_exit_time_ns) { + != dc->debug.sr_enter_plus_exit_time_ns + && dc->debug.sr_enter_plus_exit_time_ns) { updated = true; dc->dcn_soc->sr_enter_plus_exit_time = - dc->public.debug.sr_enter_plus_exit_time_ns / 1000.0; + dc->debug.sr_enter_plus_exit_time_ns / 1000.0; } - if ((int)(dc->dcn_soc->urgent_latency * 1000) != dc->public.debug.urgent_latency_ns - && dc->public.debug.urgent_latency_ns) { + if ((int)(dc->dcn_soc->urgent_latency * 1000) != dc->debug.urgent_latency_ns + && dc->debug.urgent_latency_ns) { updated = true; - dc->dcn_soc->urgent_latency = dc->public.debug.urgent_latency_ns / 1000.0; + dc->dcn_soc->urgent_latency = dc->debug.urgent_latency_ns / 1000.0; } if ((int)(dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency * 1000) - != dc->public.debug.percent_of_ideal_drambw - && dc->public.debug.percent_of_ideal_drambw) { + != dc->debug.percent_of_ideal_drambw + && dc->debug.percent_of_ideal_drambw) { updated = true; dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency = - dc->public.debug.percent_of_ideal_drambw; + dc->debug.percent_of_ideal_drambw; } if ((int)(dc->dcn_soc->dram_clock_change_latency * 1000) - != dc->public.debug.dram_clock_change_latency_ns - && dc->public.debug.dram_clock_change_latency_ns) { + != dc->debug.dram_clock_change_latency_ns + && dc->debug.dram_clock_change_latency_ns) { updated = true; dc->dcn_soc->dram_clock_change_latency = - dc->public.debug.dram_clock_change_latency_ns / 1000.0; + dc->debug.dram_clock_change_latency_ns / 1000.0; } kernel_fpu_end(); @@ -720,7 +719,7 @@ static bool dcn_bw_apply_registry_override(struct core_dc *dc) } bool dcn_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { const struct resource_pool *pool = dc->res_pool; @@ -730,8 +729,8 @@ bool dcn_validate_bandwidth( bool bw_limit_pass; float bw_limit; - if (dcn_bw_apply_registry_override(DC_TO_CORE(&dc->public))) - dcn_bw_sync_calcs_and_dml(DC_TO_CORE(&dc->public)); + if (dcn_bw_apply_registry_override(dc)) + dcn_bw_sync_calcs_and_dml(dc); memset(v, 0, sizeof(*v)); kernel_fpu_begin(); @@ -850,7 +849,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[1] = v->phyclkv_mid0p72; v->phyclk_per_state[0] = v->phyclkv_min0p65; - if (dc->public.debug.disable_pipe_split) { + if (dc->debug.disable_pipe_split) { v->max_dispclk[0] = v->max_dppclk_vmin0p65; } @@ -982,15 +981,15 @@ bool dcn_validate_bandwidth( mode_support_and_system_configuration(v); if (v->voltage_level == 0 && - (dc->public.debug.sr_exit_time_dpm0_ns - || dc->public.debug.sr_enter_plus_exit_time_dpm0_ns)) { - struct core_dc *dc_core = DC_TO_CORE(&dc->public); + (dc->debug.sr_exit_time_dpm0_ns + || dc->debug.sr_enter_plus_exit_time_dpm0_ns)) { + struct dc *dc_core = dc; - if (dc->public.debug.sr_enter_plus_exit_time_dpm0_ns) + if (dc->debug.sr_enter_plus_exit_time_dpm0_ns) v->sr_enter_plus_exit_time = - dc->public.debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f; - if (dc->public.debug.sr_exit_time_dpm0_ns) - v->sr_exit_time = dc->public.debug.sr_exit_time_dpm0_ns / 1000.0f; + dc->debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f; + if (dc->debug.sr_exit_time_dpm0_ns) + v->sr_exit_time = dc->debug.sr_exit_time_dpm0_ns / 1000.0f; dc_core->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; dc_core->dml.soc.sr_exit_time_us = v->sr_exit_time; mode_support_and_system_configuration(v); @@ -1020,7 +1019,7 @@ bool dcn_validate_bandwidth( context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); - if (dc->public.debug.max_disp_clk == true) + if (dc->debug.max_disp_clk == true) context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000); context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; @@ -1109,13 +1108,13 @@ bool dcn_validate_bandwidth( input_idx++; } - if (dc->public.debug.use_dml_wm) + if (dc->debug.use_dml_wm) dcn_dml_wm_override(v, (struct display_mode_lib *) &dc->dml, context, pool); } if (v->voltage_level == 0) { - struct core_dc *dc_core = DC_TO_CORE(&dc->public); + struct dc *dc_core = dc; dc_core->dml.soc.sr_enter_plus_exit_time_us = dc_core->dcn_soc->sr_enter_plus_exit_time; @@ -1138,7 +1137,7 @@ bool dcn_validate_bandwidth( } unsigned int dcn_find_normalized_clock_vdd_Level( - const struct core_dc *dc, + const struct dc *dc, enum dm_pp_clock_type clocks_type, int clocks_in_khz) { @@ -1228,7 +1227,7 @@ unsigned int dcn_find_normalized_clock_vdd_Level( } unsigned int dcn_find_dcfclk_suits_all( - const struct core_dc *dc, + const struct dc *dc, struct clocks_value *clocks) { unsigned vdd_level, vdd_level_temp; @@ -1270,7 +1269,7 @@ unsigned int dcn_find_dcfclk_suits_all( return dcf_clk; } -void dcn_bw_update_from_pplib(struct core_dc *dc) +void dcn_bw_update_from_pplib(struct dc *dc) { struct dc_context *ctx = dc->ctx; struct dm_pp_clock_levels_with_voltage clks = {0}; @@ -1310,7 +1309,7 @@ void dcn_bw_update_from_pplib(struct core_dc *dc) kernel_fpu_end(); } -void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) +void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) { struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0}; int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, @@ -1388,7 +1387,7 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc) dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges); } -void dcn_bw_sync_calcs_and_dml(struct core_dc *dc) +void dcn_bw_sync_calcs_and_dml(struct dc *dc) { kernel_fpu_begin(); dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 40d65b758994..44c7b52e4a00 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -35,7 +35,6 @@ #include "clock_source.h" #include "dc_bios_types.h" -#include "dce_calcs.h" #include "bios_parser_interface.h" #include "include/irq_service_interface.h" #include "transform.h" @@ -52,7 +51,7 @@ /******************************************************************************* * Private functions ******************************************************************************/ -static void destroy_links(struct core_dc *dc) +static void destroy_links(struct dc *dc) { uint32_t i; @@ -63,7 +62,7 @@ static void destroy_links(struct core_dc *dc) } static bool create_links( - struct core_dc *dc, + struct dc *dc, uint32_t num_virtual_links) { int i; @@ -153,7 +152,7 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, int vmin, int vmax) { /* TODO: Support multiple streams */ - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -179,7 +178,7 @@ static bool stream_get_crtc_position(struct dc *dc, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -202,7 +201,7 @@ static bool stream_get_crtc_position(struct dc *dc, static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i = 0; bool ret = false; struct pipe_ctx *pipes; @@ -220,7 +219,7 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i = 0; bool ret = false; struct pipe_ctx *pipes; @@ -245,7 +244,7 @@ static void set_static_screen_events(struct dc *dc, int num_streams, const struct dc_static_screen_events *events) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i = 0; int j = 0; struct pipe_ctx *pipes_affected[MAX_PIPES]; @@ -270,7 +269,7 @@ static void set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i; for (i = 0; i < core_dc->link_count; i++) { @@ -288,7 +287,7 @@ static void perform_link_training(struct dc *dc, struct dc_link_settings *link_setting, bool skip_video_pattern) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i; for (i = 0; i < core_dc->link_count; i++) @@ -369,48 +368,48 @@ void set_dither_option(struct dc_stream_state *stream, opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } -static void allocate_dc_stream_funcs(struct core_dc *core_dc) +static void allocate_dc_stream_funcs(struct dc *core_dc) { if (core_dc->hwss.set_drr != NULL) { - core_dc->public.stream_funcs.adjust_vmin_vmax = + core_dc->stream_funcs.adjust_vmin_vmax = stream_adjust_vmin_vmax; } - core_dc->public.stream_funcs.set_static_screen_events = + core_dc->stream_funcs.set_static_screen_events = set_static_screen_events; - core_dc->public.stream_funcs.get_crtc_position = + core_dc->stream_funcs.get_crtc_position = stream_get_crtc_position; - core_dc->public.stream_funcs.set_gamut_remap = + core_dc->stream_funcs.set_gamut_remap = set_gamut_remap; - core_dc->public.stream_funcs.program_csc_matrix = + core_dc->stream_funcs.program_csc_matrix = program_csc_matrix; - core_dc->public.stream_funcs.set_dither_option = + core_dc->stream_funcs.set_dither_option = set_dither_option; - core_dc->public.link_funcs.set_drive_settings = + core_dc->link_funcs.set_drive_settings = set_drive_settings; - core_dc->public.link_funcs.perform_link_training = + core_dc->link_funcs.perform_link_training = perform_link_training; - core_dc->public.link_funcs.set_preferred_link_settings = + core_dc->link_funcs.set_preferred_link_settings = set_preferred_link_settings; - core_dc->public.link_funcs.enable_hpd = + core_dc->link_funcs.enable_hpd = enable_hpd; - core_dc->public.link_funcs.disable_hpd = + core_dc->link_funcs.disable_hpd = disable_hpd; - core_dc->public.link_funcs.set_test_pattern = + core_dc->link_funcs.set_test_pattern = set_test_pattern; } -static void destruct(struct core_dc *dc) +static void destruct(struct dc *dc) { dc_release_validate_context(dc->current_context); dc->current_context = NULL; @@ -446,10 +445,11 @@ static void destruct(struct core_dc *dc) dm_free(dc->dcn_ip); dc->dcn_ip = NULL; + #endif } -static bool construct(struct core_dc *dc, +static bool construct(struct dc *dc, const struct dc_init_data *init_params) { struct dal_logger *logger; @@ -508,7 +508,7 @@ static bool construct(struct core_dc *dc, dc_ctx->cgs_device = init_params->cgs_device; dc_ctx->driver_context = init_params->driver; - dc_ctx->dc = &dc->public; + dc_ctx->dc = dc; dc_ctx->asic_id = init_params->asic_id; /* Create logger */ @@ -621,7 +621,7 @@ void ProgramPixelDurationV(unsigned int pixelClockInKHz ) struct dc *dc_create(const struct dc_init_data *init_params) { - struct core_dc *core_dc = dm_alloc(sizeof(*core_dc)); + struct dc *core_dc = dm_alloc(sizeof(*core_dc)); unsigned int full_pipe_count; if (NULL == core_dc) @@ -636,23 +636,23 @@ struct dc *dc_create(const struct dc_init_data *init_params) full_pipe_count = core_dc->res_pool->pipe_count; if (core_dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) full_pipe_count--; - core_dc->public.caps.max_streams = min( + core_dc->caps.max_streams = min( full_pipe_count, core_dc->res_pool->stream_enc_count); - core_dc->public.caps.max_links = core_dc->link_count; - core_dc->public.caps.max_audios = core_dc->res_pool->audio_count; + core_dc->caps.max_links = core_dc->link_count; + core_dc->caps.max_audios = core_dc->res_pool->audio_count; - core_dc->public.config = init_params->flags; + core_dc->config = init_params->flags; dm_logger_write(core_dc->ctx->logger, LOG_DC, "Display Core initialized\n"); /* TODO: missing feature to be enabled */ - core_dc->public.debug.disable_dfs_bypass = true; + core_dc->debug.disable_dfs_bypass = true; - return &core_dc->public; + return core_dc; construct_fail: dm_free(core_dc); @@ -663,14 +663,14 @@ struct dc *dc_create(const struct dc_init_data *init_params) void dc_destroy(struct dc **dc) { - struct core_dc *core_dc = DC_TO_CORE(*dc); + struct dc *core_dc = *dc; destruct(core_dc); dm_free(core_dc); *dc = NULL; } static bool is_validation_required( - const struct core_dc *dc, + const struct dc *dc, const struct dc_validation_set set[], int set_count) { @@ -705,7 +705,7 @@ static bool is_validation_required( } static bool validate_streams ( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count) { @@ -719,7 +719,7 @@ static bool validate_streams ( } static bool validate_surfaces( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count) { @@ -734,11 +734,11 @@ static bool validate_surfaces( } struct validate_context *dc_get_validate_context( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], uint8_t set_count) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; @@ -773,11 +773,11 @@ struct validate_context *dc_get_validate_context( } bool dc_validate_resources( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], uint8_t set_count) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; @@ -811,10 +811,10 @@ bool dc_validate_resources( } bool dc_validate_guaranteed( - const struct dc *dc, + struct dc *dc, struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; @@ -844,7 +844,7 @@ bool dc_validate_guaranteed( } static void program_timing_sync( - struct core_dc *core_dc, + struct dc *core_dc, struct validate_context *ctx) { int i, j; @@ -918,7 +918,7 @@ static void program_timing_sync( } static bool context_changed( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { uint8_t i; @@ -935,7 +935,7 @@ static bool context_changed( } static bool streams_changed( - struct core_dc *dc, + struct dc *dc, struct dc_stream_state *streams[], uint8_t stream_count) { @@ -961,7 +961,7 @@ bool dc_enable_stereo( bool ret = true; int i, j; struct pipe_ctx *pipe; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; #ifdef ENABLE_FBC struct compressor *fbc_compressor = core_dc->fbc_compressor; @@ -996,7 +996,7 @@ bool dc_enable_stereo( */ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_bios *dcb = core_dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; @@ -1064,7 +1064,7 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c bool dc_commit_context(struct dc *dc, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i; if (false == context_changed(core_dc, context)) @@ -1092,7 +1092,7 @@ bool dc_commit_streams( struct dc_stream_state *streams[], uint8_t stream_count) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; @@ -1158,7 +1158,7 @@ bool dc_commit_streams( bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct validate_context *context = core_dc->current_context; post_surface_trace(dc); @@ -1375,7 +1375,7 @@ static enum surface_update_type get_scaling_info_update_type( } static enum surface_update_type det_surface_update( - const struct core_dc *dc, + const struct dc *dc, const struct dc_surface_update *u, int surface_index) { @@ -1410,7 +1410,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; @@ -1456,7 +1456,7 @@ void dc_update_planes_and_stream(struct dc *dc, struct dc_stream_state *stream, struct dc_stream_update *stream_update) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct validate_context *context; int i, j; enum surface_update_type update_type; @@ -1781,29 +1781,29 @@ void dc_update_planes_and_stream(struct dc *dc, DC_ERROR("Failed to allocate new validate context!\n"); } -uint8_t dc_get_current_stream_count(const struct dc *dc) +uint8_t dc_get_current_stream_count(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return core_dc->current_context->stream_count; } -struct dc_stream_state *dc_get_stream_at_index(const struct dc *dc, uint8_t i) +struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; if (i < core_dc->current_context->stream_count) return core_dc->current_context->streams[i]; return NULL; } -struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index) +struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return core_dc->links[link_index]; } -struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe) +struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; if ((pipe >= dwb_pipe0) && (pipe < dwb_pipe_max_num)) { return core_dc->res_pool->dwbc[(int)pipe]; } else { @@ -1814,20 +1814,20 @@ struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe) const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return core_dc->links[link_index]->link_id; } enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return core_dc->links[link_index]->irq_source_hpd; } const struct audio **dc_get_audios(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return (const struct audio **)core_dc->res_pool->audios; } @@ -1836,24 +1836,24 @@ enum dc_irq_source dc_interrupt_to_irq_source( uint32_t src_id, uint32_t ext_id) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id); } -void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable) +void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) { - struct core_dc *core_dc; + struct dc *core_dc; if (dc == NULL) return; - core_dc = DC_TO_CORE(dc); + core_dc = dc; dal_irq_service_set(core_dc->res_pool->irqs, src, enable); } void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; dal_irq_service_ack(core_dc->res_pool->irqs, src); } @@ -1861,7 +1861,7 @@ void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; atomic_t ref_count; switch (power_state) { @@ -1889,9 +1889,9 @@ void dc_set_power_state( } -void dc_resume(const struct dc *dc) +void dc_resume(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; uint32_t i; @@ -1906,7 +1906,7 @@ bool dc_read_aux_dpcd( uint8_t *data, uint32_t size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( @@ -1926,7 +1926,7 @@ bool dc_write_aux_dpcd( const uint8_t *data, uint32_t size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( @@ -1947,7 +1947,7 @@ bool dc_read_aux_i2c( uint8_t *data, uint32_t size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( @@ -1968,7 +1968,7 @@ bool dc_write_aux_i2c( const uint8_t *data, uint32_t size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( @@ -1990,7 +1990,7 @@ bool dc_query_ddc_data( uint8_t *read_buf, uint32_t read_size) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; @@ -2010,7 +2010,7 @@ bool dc_submit_i2c( uint32_t link_index, struct i2c_command *cmd) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_link *link = core_dc->links[link_index]; struct ddc_service *ddc = link->ddc; @@ -2129,7 +2129,7 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct mem_input *mi = NULL; for (i = 0; i < core_dc->res_pool->pipe_count; i++) { @@ -2155,7 +2155,7 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) void dc_log_hw_state(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; if (core_dc->hwss.log_hw_state) core_dc->hwss.log_hw_state(core_dc); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 21af3bc057c7..d74eed8f9b96 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -37,12 +37,12 @@ } while (0) void pre_surface_trace( - const struct dc *dc, + struct dc *dc, const struct dc_plane_state *const *plane_states, int surface_count) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; for (i = 0; i < surface_count; i++) { @@ -158,12 +158,12 @@ void pre_surface_trace( } void update_surface_trace( - const struct dc *dc, + struct dc *dc, const struct dc_surface_update *updates, int surface_count) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; for (i = 0; i < surface_count; i++) { @@ -279,9 +279,9 @@ void update_surface_trace( SURFACE_TRACE("\n"); } -void post_surface_trace(const struct dc *dc) +void post_surface_trace(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; SURFACE_TRACE("post surface process.\n"); @@ -289,11 +289,11 @@ void post_surface_trace(const struct dc *dc) } void context_timing_trace( - const struct dc *dc, + struct dc *dc, struct resource_context *res_ctx) { int i; - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; int h_pos[MAX_PIPES], v_pos[MAX_PIPES]; struct crtc_position position; @@ -328,11 +328,11 @@ void context_timing_trace( } void context_clock_trace( - const struct dc *dc, + struct dc *dc, struct validate_context *context) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dal_logger *logger = core_dc->ctx->logger; CLOCK_TRACE("Current: dispclk_khz:%d dppclk_div:%d dcfclk_khz:%d\n" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 7b1f2493cbc9..71993d5983bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -25,7 +25,6 @@ #include "dm_services.h" #include "core_types.h" -#include "core_dc.h" #include "timing_generator.h" #include "hw_sequencer.h" @@ -55,7 +54,7 @@ static const struct tg_color black_color_format[] = { }; void color_space_to_black_color( - const struct core_dc *dc, + const struct dc *dc, enum dc_color_space colorspace, struct tg_color *black_color) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b858fec72bd7..1888bf4d2c3f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -26,14 +26,13 @@ #include "dm_services.h" #include "dm_helpers.h" #include "dc.h" -#include "core_dc.h" #include "grph_object_id.h" #include "gpio_service_interface.h" #include "core_status.h" #include "dc_link_dp.h" #include "dc_link_ddc.h" #include "link_hwss.h" -#include "stream_encoder.h" + #include "link_encoder.h" #include "hw_sequencer.h" #include "resource.h" @@ -1392,7 +1391,7 @@ enum dc_status dc_link_validate_mode_timing( bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, uint32_t frame_ramp, const struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; unsigned int controller_id = 0; int i; @@ -1431,7 +1430,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, bool dc_link_set_abm_disable(const struct dc_link *link) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct abm *abm = core_dc->res_pool->abm; if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) @@ -1445,7 +1444,7 @@ bool dc_link_set_abm_disable(const struct dc_link *link) bool dc_link_set_psr_enable(const struct dc_link *link, bool enable) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) @@ -1456,7 +1455,7 @@ bool dc_link_set_psr_enable(const struct dc_link *link, bool enable) bool dc_link_get_psr_state(const struct dc_link *link, uint32_t *psr_state) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) @@ -1469,7 +1468,7 @@ bool dc_link_setup_psr(struct dc_link *link, const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context) { - struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc); + struct dc *core_dc = link->ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; int i; @@ -1874,7 +1873,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) void core_link_enable_stream(struct pipe_ctx *pipe_ctx) { - struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + struct dc *core_dc = pipe_ctx->stream->ctx->dc; enum dc_status status = enable_link(pipe_ctx); @@ -1907,7 +1906,7 @@ void core_link_enable_stream(struct pipe_ctx *pipe_ctx) void core_link_disable_stream(struct pipe_ctx *pipe_ctx) { - struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + struct dc *core_dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); @@ -1919,7 +1918,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) { - struct core_dc *core_dc = DC_TO_CORE(pipe_ctx->stream->ctx->dc); + struct dc *core_dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) return; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 9d5fe658d14c..0144c98fd0d5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -10,7 +10,6 @@ #include "core_status.h" #include "dpcd_defs.h" -#include "core_dc.h" #include "resource.h" /* maximum pre emphasis level allowed for each voltage swing level*/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index d19c663c257f..da880bd02ad7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -3,7 +3,7 @@ #include "dm_services.h" #include "dc.h" -#include "inc/core_dc.h" +#include "inc/core_types.h" #include "include/ddc_service_types.h" #include "include/i2caux_interface.h" #include "link_hwss.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d2b8f27416d6..2b357318f945 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -92,7 +92,7 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) } struct resource_pool *dc_create_resource_pool( - struct core_dc *dc, + struct dc *dc, int num_virtual_links, enum dce_version dc_version, struct hw_asic_id asic_id) @@ -153,7 +153,7 @@ struct resource_pool *dc_create_resource_pool( return res_pool; } -void dc_destroy_resource_pool(struct core_dc *dc) +void dc_destroy_resource_pool(struct dc *dc) { if (dc) { if (dc->res_pool) @@ -193,7 +193,7 @@ static void update_num_audio( bool resource_construct( unsigned int num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct resource_pool *pool, const struct resource_create_funcs *create_funcs) { @@ -892,7 +892,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) enum dc_status resource_build_scaling_params_for_context( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context) { int i; @@ -1438,7 +1438,7 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) } enum dc_status resource_map_pool_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -2316,7 +2316,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) } enum dc_status resource_map_clock_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -2343,7 +2343,7 @@ enum dc_status resource_map_clock_resources( else { pipe_ctx->clock_source = NULL; - if (!dc->public.config.disable_disp_pll_sharing) + if (!dc->config.disable_disp_pll_sharing) resource_find_used_clk_src_for_sharing( &context->res_ctx, pipe_ctx); @@ -2515,9 +2515,9 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream) +bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_context *dc_ctx = core_dc->ctx; struct dc_link *link = stream->sink->link; struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; @@ -2547,9 +2547,9 @@ bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream) return res == DC_OK; } -bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state) +bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; /* TODO For now validates pixel format only */ if (core_dc->res_pool->funcs->validate_plane) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 47e407dab4a3..5e4f7f08e3db 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -144,7 +144,7 @@ struct dc_stream_status *dc_stream_get_status( struct dc_stream_state *stream) { uint8_t i; - struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); + struct dc *dc = stream->ctx->dc; for (i = 0; i < dc->current_context->stream_count; i++) { if (stream == dc->current_context->streams[i]) { @@ -163,7 +163,7 @@ bool dc_stream_set_cursor_attributes( const struct dc_cursor_attributes *attributes) { int i; - struct core_dc *core_dc; + struct dc *core_dc; struct resource_context *res_ctx; if (NULL == stream) { @@ -175,7 +175,7 @@ bool dc_stream_set_cursor_attributes( return false; } - core_dc = DC_TO_CORE(stream->ctx->dc); + core_dc = stream->ctx->dc; res_ctx = &core_dc->current_context->res_ctx; for (i = 0; i < MAX_PIPES; i++) { @@ -198,7 +198,7 @@ bool dc_stream_set_cursor_position( const struct dc_cursor_position *position) { int i; - struct core_dc *core_dc; + struct dc *core_dc; struct resource_context *res_ctx; if (NULL == stream) { @@ -211,7 +211,7 @@ bool dc_stream_set_cursor_position( return false; } - core_dc = DC_TO_CORE(stream->ctx->dc); + core_dc = stream->ctx->dc; res_ctx = &core_dc->current_context->res_ctx; for (i = 0; i < MAX_PIPES; i++) { @@ -246,7 +246,7 @@ bool dc_stream_set_cursor_position( uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) { uint8_t i; - struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); + struct dc *core_dc = stream->ctx->dc; struct resource_context *res_ctx = &core_dc->current_context->res_ctx; @@ -270,7 +270,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, { uint8_t i; bool ret = false; - struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); + struct dc *core_dc = stream->ctx->dc; struct resource_context *res_ctx = &core_dc->current_context->res_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index da19c7fa5151..0b6410fb2f3e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -28,7 +28,7 @@ #include "dc.h" /* DC core (private) */ -#include "core_dc.h" +#include "core_types.h" #include "transform.h" /******************************************************************************* @@ -64,9 +64,9 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, /*register_flip_interrupt(surface);*/ } -struct dc_plane_state *dc_create_plane_state(const struct dc *dc) +struct dc_plane_state *dc_create_plane_state(struct dc *dc) { - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct dc_plane_state *plane_state = dm_alloc(sizeof(*plane_state)); @@ -91,7 +91,7 @@ const struct dc_plane_status *dc_plane_get_status( const struct dc_plane_state *plane_state) { const struct dc_plane_status *plane_status; - struct core_dc *core_dc; + struct dc *core_dc; int i; if (!plane_state || @@ -102,7 +102,7 @@ const struct dc_plane_status *dc_plane_get_status( } plane_status = &plane_state->status; - core_dc = DC_TO_CORE(plane_state->ctx->dc); + core_dc = plane_state->ctx->dc; if (core_dc->current_context == NULL) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e62d15d90fdb..68056d888def 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -34,14 +34,19 @@ #include "grph_object_ctrl_defs.h" #include +#include "inc/hw_sequencer.h" +#include "dml/display_mode_lib.h" + + + #define MAX_SURFACES 3 #define MAX_STREAMS 6 #define MAX_SINKS_PER_LINK 4 + /******************************************************************************* * Display Core Interfaces ******************************************************************************/ - struct dc_caps { uint32_t max_streams; uint32_t max_links; @@ -186,7 +191,9 @@ struct dc_debug { bool disable_psr; bool force_abm_enable; }; - +struct validate_context; +struct resource_pool; +struct dce_hwseq; struct dc { struct dc_caps caps; struct dc_cap_funcs cap_funcs; @@ -194,6 +201,40 @@ struct dc { struct dc_link_funcs link_funcs; struct dc_config config; struct dc_debug debug; + + struct dc_context *ctx; + + uint8_t link_count; + struct dc_link *links[MAX_PIPES * 2]; + + struct validate_context *current_context; + struct resource_pool *res_pool; + + /* Display Engine Clock levels */ + struct dm_pp_clock_levels sclk_lvls; + + /* Inputs into BW and WM calculations. */ + struct bw_calcs_dceip *bw_dceip; + struct bw_calcs_vbios *bw_vbios; +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct dcn_soc_bounding_box *dcn_soc; + struct dcn_ip_params *dcn_ip; + struct display_mode_lib dml; +#endif + + /* HW functions */ + struct hw_sequencer_funcs hwss; + struct dce_hwseq *hwseq; + + /* temp store of dm_pp_display_configuration + * to compare to see if display config changed + */ + struct dm_pp_display_configuration prev_display_config; + + /* FBC compressor */ +#ifdef ENABLE_FBC + struct compressor *fbc_compressor; +#endif }; enum frame_buffer_mode { @@ -384,7 +425,7 @@ struct dc_surface_update { /* * Create a new surface with default parameters; */ -struct dc_plane_state *dc_create_plane_state(const struct dc *dc); +struct dc_plane_state *dc_create_plane_state(struct dc *dc); const struct dc_plane_status *dc_plane_get_status( const struct dc_plane_state *plane_state); @@ -558,8 +599,8 @@ void dc_stream_log( struct dal_logger *dc_logger, enum dc_log_type log_type); -uint8_t dc_get_current_stream_count(const struct dc *dc); -struct dc_stream_state *dc_get_stream_at_index(const struct dc *dc, uint8_t i); +uint8_t dc_get_current_stream_count(struct dc *dc); +struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i); /* * Return the current frame counter. @@ -585,9 +626,9 @@ struct dc_validation_set { uint8_t plane_count; }; -bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream); +bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); -bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state); +bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); /* * This function takes a set of resources and checks that they are cofunctional. * @@ -595,12 +636,12 @@ bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_s * No hardware is programmed for call. Only validation is done. */ struct validate_context *dc_get_validate_context( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], uint8_t set_count); bool dc_validate_resources( - const struct dc *dc, + struct dc *dc, const struct dc_validation_set set[], uint8_t set_count); @@ -613,7 +654,7 @@ bool dc_validate_resources( */ bool dc_validate_guaranteed( - const struct dc *dc, + struct dc *dc, struct dc_stream_state *stream); void dc_resource_validate_ctx_copy_construct( @@ -764,7 +805,7 @@ struct dc_link { /* Private to DC core */ - const struct core_dc *dc; + const struct dc *dc; struct dc_context *ctx; @@ -795,9 +836,9 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); * boot time. They cannot be created or destroyed. * Use dc_get_caps() to get number of links. */ -struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index); +struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); -struct dwbc *dc_get_dwb_at_pipe(const struct dc *dc, uint32_t pipe); +struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe); /* Return id of physical connector represented by a dc_link at link_index.*/ const struct graphics_object_id dc_get_link_id_at_index( @@ -948,7 +989,7 @@ enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, uint32_t ext_id); -void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable); +void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable); void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src); enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index); @@ -960,7 +1001,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index( void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state); -void dc_resume(const struct dc *dc); +void dc_resume(struct dc *dc); /* * DPCD access interfaces diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 922af2d1b91a..0654fe34627c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -34,7 +34,6 @@ #include "dce_clock_source.h" -#include "core_dc.h" #include "reg_helper.h" #define REG(reg)\ @@ -609,7 +608,7 @@ static uint32_t dce110_get_pll_pixel_rate_in_hz( struct pll_settings *pll_settings) { uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; - struct core_dc *dc_core = DC_TO_CORE(cs->ctx->dc); + struct dc *dc_core = cs->ctx->dc; struct validate_context *context = dc_core->current_context; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; @@ -624,7 +623,7 @@ static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll( struct pll_settings *pll_settings) { uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; - struct core_dc *dc_core = DC_TO_CORE(cs->ctx->dc); + struct dc *dc_core = cs->ctx->dc; struct validate_context *context = dc_core->current_context; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 7bb2eaf07da5..9d67340a6b8b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -29,14 +29,12 @@ #include "fixed32_32.h" #include "bios_parser_interface.h" #include "dc.h" -#include "core_dc.h" #include "dce_abm.h" #include "dmcu.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "dcn_calcs.h" -#include "core_dc.h" #endif - +#include "core_types.h" #define TO_DCE_CLOCKS(clocks)\ @@ -368,7 +366,7 @@ static int dce_psr_set_clock( { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct dc_context *ctx = clk_dce->base.ctx; - struct core_dc *core_dc = DC_TO_CORE(ctx->dc); + struct dc *core_dc = ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; int actual_clk_khz = requested_clk_khz; @@ -385,7 +383,7 @@ static int dce112_set_clock( struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); struct bp_set_dce_clock_parameters dce_clk_params; struct dc_bios *bp = clk->ctx->dc_bios; - struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + struct dc *core_dc = clk->ctx->dc; struct abm *abm = core_dc->res_pool->abm; struct dmcu *dmcu = core_dc->res_pool->dmcu; int actual_clock = requested_clk_khz; @@ -621,7 +619,7 @@ static bool dce_apply_clock_voltage_request( if (send_request) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (clk->ctx->dce_version >= DCN_VERSION_1_0) { - struct core_dc *core_dc = DC_TO_CORE(clk->ctx->dc); + struct dc *core_dc = clk->ctx->dc; /*use dcfclk request voltage*/ clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; clock_voltage_req.clocks_in_khz = diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index 4894e1755d84..d2e66b1bc0ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -26,7 +26,7 @@ #include "dce_hwseq.h" #include "reg_helper.h" #include "hw_sequencer.h" -#include "core_dc.h" +#include "core_types.h" #define CTX \ hws->ctx @@ -44,7 +44,7 @@ void dce_enable_fe_clock(struct dce_hwseq *hws, DCFE_CLOCK_ENABLE, enable); } -void dce_pipe_control_lock(struct core_dc *dc, +void dce_pipe_control_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 9a97d8ee7971..3a1eb6a79d66 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -528,7 +528,7 @@ enum blnd_mode { void dce_enable_fe_clock(struct dce_hwseq *hwss, unsigned int inst, bool enable); -void dce_pipe_control_lock(struct core_dc *dc, +void dce_pipe_control_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index c638f47acefc..b7e51c5ed1b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -24,7 +24,6 @@ */ #include "dm_services.h" #include "dc.h" -#include "core_dc.h" #include "core_types.h" #include "hw_sequencer.h" #include "dce100_hw_sequencer.h" @@ -71,7 +70,7 @@ static const struct dce100_hw_seq_reg_offsets reg_offsets[] = { /***************************PIPE_CONTROL***********************************/ static bool dce100_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -107,7 +106,7 @@ static bool dce100_enable_display_power_gating( } static void dce100_pplib_apply_display_requirements( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -127,7 +126,7 @@ static void dce100_pplib_apply_display_requirements( } void dce100_set_bandwidth( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed) { @@ -143,7 +142,7 @@ void dce100_set_bandwidth( /**************************************************************************/ -bool dce100_hw_sequencer_construct(struct core_dc *dc) +bool dce100_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index 24433f0e770b..c04aa15cd656 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -28,13 +28,13 @@ #include "core_types.h" -struct core_dc; +struct dc; struct validate_context; -bool dce100_hw_sequencer_construct(struct core_dc *dc); +bool dce100_hw_sequencer_construct(struct dc *dc); void dce100_set_bandwidth( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 46f0c71fbac4..b2b03633eb4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -652,7 +652,7 @@ static void destruct(struct dce110_resource_pool *pool) } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -688,7 +688,7 @@ static enum dc_status build_mapped_resource( } bool dce100_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ @@ -720,7 +720,7 @@ static bool dce100_validate_surface_sets( } enum dc_status dce100_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -764,7 +764,7 @@ enum dc_status dce100_validate_with_context( } enum dc_status dce100_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) { @@ -784,7 +784,7 @@ enum dc_status dce100_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } @@ -824,7 +824,7 @@ static const struct resource_funcs dce100_res_pool_funcs = { static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -909,9 +909,9 @@ static bool construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 40; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; for (i = 0; i < pool->base.pipe_count; i++) { pool->base.timing_generators[i] = @@ -958,7 +958,7 @@ static bool construct( } } - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) @@ -978,7 +978,7 @@ static bool construct( struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index edc50caf04d1..ca7b2b7c1a48 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -8,13 +8,13 @@ #ifndef DCE100_RESOURCE_H_ #define DCE100_RESOURCE_H_ -struct core_dc; +struct dc; struct resource_pool; struct dc_validation_set; struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index ccde7c80d658..e6c6f1108078 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -164,7 +164,7 @@ static void enable_display_pipe_clock_gating( } static bool dce110_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -944,7 +944,7 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, } } -static void program_scaler(const struct core_dc *dc, +static void program_scaler(const struct dc *dc, const struct pipe_ctx *pipe_ctx) { struct tg_color color = {0}; @@ -955,7 +955,7 @@ static void program_scaler(const struct core_dc *dc, return; #endif - if (dc->public.debug.surface_visual_confirm) + if (dc->debug.surface_visual_confirm) get_surface_visual_confirm_color(pipe_ctx, &color); else color_space_to_black_color(dc, @@ -979,7 +979,7 @@ static void program_scaler(const struct core_dc *dc, static enum dc_status dce110_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, struct validate_context *context, - struct core_dc *dc) + struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. @@ -1035,7 +1035,7 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( static enum dc_status apply_single_controller_ctx_to_hw( struct pipe_ctx *pipe_ctx, struct validate_context *context, - struct core_dc *dc) + struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. @@ -1146,7 +1146,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( /******************************************************************************/ -static void power_down_encoders(struct core_dc *dc) +static void power_down_encoders(struct dc *dc) { int i; @@ -1156,7 +1156,7 @@ static void power_down_encoders(struct core_dc *dc) } } -static void power_down_controllers(struct core_dc *dc) +static void power_down_controllers(struct dc *dc) { int i; @@ -1166,7 +1166,7 @@ static void power_down_controllers(struct core_dc *dc) } } -static void power_down_clock_sources(struct core_dc *dc) +static void power_down_clock_sources(struct dc *dc) { int i; @@ -1181,7 +1181,7 @@ static void power_down_clock_sources(struct core_dc *dc) } } -static void power_down_all_hw_blocks(struct core_dc *dc) +static void power_down_all_hw_blocks(struct dc *dc) { power_down_encoders(dc); @@ -1196,7 +1196,7 @@ static void power_down_all_hw_blocks(struct core_dc *dc) } static void disable_vga_and_power_gate_all_controllers( - struct core_dc *dc) + struct dc *dc) { int i; struct timing_generator *tg; @@ -1224,7 +1224,7 @@ static void disable_vga_and_power_gate_all_controllers( * 3. Enable power gating for controller * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS) */ -void dce110_enable_accelerated_mode(struct core_dc *dc) +void dce110_enable_accelerated_mode(struct dc *dc) { power_down_all_hw_blocks(dc); @@ -1250,7 +1250,7 @@ static uint32_t compute_pstate_blackout_duration( } void dce110_set_displaymarks( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context) { uint8_t i, num_pipes; @@ -1316,7 +1316,7 @@ static void set_safe_displaymarks( } static void switch_dp_clock_sources( - const struct core_dc *dc, + const struct dc *dc, struct resource_context *res_ctx) { uint8_t i; @@ -1408,7 +1408,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, * may read PLL register to get pixel clock */ static uint32_t get_max_pixel_clock_for_all_paths( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool pre_mode_set) { @@ -1449,7 +1449,7 @@ static uint32_t get_max_pixel_clock_for_all_paths( * etc support for dcn1.0 */ static void apply_min_clocks( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, enum dm_pp_clocks_state *clocks_state, bool pre_mode_set) @@ -1538,7 +1538,7 @@ static void apply_min_clocks( /* * Check if FBC can be enabled */ -static enum dc_status validate_fbc(struct core_dc *dc, +static enum dc_status validate_fbc(struct dc *dc, struct validate_context *context) { struct pipe_ctx *pipe_ctx = @@ -1568,7 +1568,7 @@ static enum dc_status validate_fbc(struct core_dc *dc, /* * Enable FBC */ -static enum dc_status enable_fbc(struct core_dc *dc, +static enum dc_status enable_fbc(struct dc *dc, struct validate_context *context) { enum dc_status status = validate_fbc(dc, context); @@ -1597,7 +1597,7 @@ static enum dc_status enable_fbc(struct core_dc *dc, #endif static enum dc_status apply_ctx_to_hw_fpga( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { enum dc_status status = DC_ERROR_UNEXPECTED; @@ -1627,7 +1627,7 @@ static enum dc_status apply_ctx_to_hw_fpga( } static void dce110_reset_hw_ctx_wrap( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { int i; @@ -1672,7 +1672,7 @@ static void dce110_reset_hw_ctx_wrap( enum dc_status dce110_apply_ctx_to_hw( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { struct dc_bios *dcb = dc->ctx->dc_bios; @@ -1965,7 +1965,7 @@ static void set_default_colors(struct pipe_ctx *pipe_ctx) * -------------------------------------------------| * ******************************************************************************/ -static void program_surface_visibility(const struct core_dc *dc, +static void program_surface_visibility(const struct dc *dc, struct pipe_ctx *pipe_ctx) { enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE; @@ -2038,7 +2038,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) * TODO REMOVE, USE UPDATE INSTEAD */ static void set_plane_config( - const struct core_dc *dc, + const struct dc *dc, struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx) { @@ -2117,7 +2117,7 @@ static void set_plane_config( if (mi->funcs->set_blank) mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); - if (dc->public.config.gpu_vm_support) + if (dc->config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->plane_res.mi, plane_state->format, @@ -2125,7 +2125,7 @@ static void set_plane_config( plane_state->rotation); } -static void update_plane_addr(const struct core_dc *dc, +static void update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) { struct dc_plane_state *plane_state = pipe_ctx->plane_state; @@ -2163,7 +2163,7 @@ void dce110_update_pending_status(struct pipe_ctx *pipe_ctx) } } -void dce110_power_down(struct core_dc *dc) +void dce110_power_down(struct dc *dc) { power_down_all_hw_blocks(dc); disable_vga_and_power_gate_all_controllers(dc); @@ -2208,7 +2208,7 @@ static bool wait_for_reset_trigger_to_occur( /* Enable timing synchronization for a group of Timing Generators. */ static void dce110_enable_timing_synchronization( - struct core_dc *dc, + struct dc *dc, int group_index, int group_size, struct pipe_ctx *grouped_pipes[]) @@ -2257,7 +2257,7 @@ static void dce110_enable_timing_synchronization( DC_SYNC_INFO("GSL: Set-up complete.\n"); } -static void init_hw(struct core_dc *dc) +static void init_hw(struct dc *dc) { int i; struct dc_bios *bp; @@ -2394,7 +2394,7 @@ uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) } static int determine_sclk_from_bounding_box( - const struct core_dc *dc, + const struct dc *dc, int required_sclk) { int i; @@ -2420,7 +2420,7 @@ static int determine_sclk_from_bounding_box( } static void pplib_apply_display_requirements( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -2474,7 +2474,7 @@ static void pplib_apply_display_requirements( } static void dce110_set_bandwidth( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed) { @@ -2491,7 +2491,7 @@ static void dce110_set_bandwidth( } static void dce110_program_front_end_for_pipe( - struct core_dc *dc, struct pipe_ctx *pipe_ctx) + struct dc *dc, struct pipe_ctx *pipe_ctx) { struct mem_input *mi = pipe_ctx->plane_res.mi; struct pipe_ctx *old_pipe = NULL; @@ -2572,7 +2572,7 @@ static void dce110_program_front_end_for_pipe( if (mi->funcs->set_blank) mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); - if (dc->public.config.gpu_vm_support) + if (dc->config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->plane_res.mi, plane_state->format, @@ -2618,7 +2618,7 @@ static void dce110_program_front_end_for_pipe( } static void dce110_apply_ctx_for_surface( - struct core_dc *dc, + struct dc *dc, const struct dc_stream_state *stream, int num_planes, struct validate_context *context) @@ -2648,7 +2648,7 @@ static void dce110_apply_ctx_for_surface( } } -static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) +static void dce110_power_down_fe(struct dc *dc, int fe_idx) { /* Do not power down fe when stream is active on dce*/ if (dc->current_context->res_ctx.pipe_ctx[fe_idx].stream) @@ -2662,7 +2662,7 @@ static void dce110_power_down_fe(struct core_dc *dc, int fe_idx) } static void dce110_wait_for_mpcc_disconnect( - struct core_dc *dc, + struct dc *dc, struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) { @@ -2724,7 +2724,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect }; -bool dce110_hw_sequencer_construct(struct core_dc *dc) +bool dce110_hw_sequencer_construct(struct dc *dc) { dc->hwss = dce110_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 89782ca1917f..d710f6e6dc07 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -29,20 +29,20 @@ #include "core_types.h" #define GAMMA_HW_POINTS_NUM 256 -struct core_dc; +struct dc; struct validate_context; struct dm_pp_display_configuration; -bool dce110_hw_sequencer_construct(struct core_dc *dc); +bool dce110_hw_sequencer_construct(struct dc *dc); enum dc_status dce110_apply_ctx_to_hw( - struct core_dc *dc, + struct dc *dc, struct validate_context *context); void dce110_set_display_clock(struct validate_context *context); void dce110_set_displaymarks( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context); void dce110_enable_stream(struct pipe_ctx *pipe_ctx); @@ -55,9 +55,9 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); -void dce110_enable_accelerated_mode(struct core_dc *dc); +void dce110_enable_accelerated_mode(struct dc *dc); -void dce110_power_down(struct core_dc *dc); +void dce110_power_down(struct dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 56be84ce5a0d..2154c2e567f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -772,7 +772,7 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -814,7 +814,7 @@ static enum dc_status build_mapped_resource( } static bool dce110_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { bool result = false; @@ -928,7 +928,7 @@ static bool dce110_validate_surface_sets( } static enum dc_status dce110_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -972,7 +972,7 @@ static enum dc_status dce110_validate_with_context( } static enum dc_status dce110_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) { @@ -992,7 +992,7 @@ static enum dc_status dce110_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } @@ -1008,7 +1008,7 @@ static struct pipe_ctx *dce110_acquire_underlay( const struct resource_pool *pool, struct dc_stream_state *stream) { - struct core_dc *dc = DC_TO_CORE(stream->ctx->dc); + struct dc *dc = stream->ctx->dc; struct resource_context *res_ctx = &context->res_ctx; unsigned int underlay_idx = pool->underlay_pipe_index; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; @@ -1117,7 +1117,7 @@ static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) return true; } -static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +static void bw_calcs_data_update_from_pplib(struct dc *dc) { struct dm_pp_clock_levels clks = {0}; @@ -1184,7 +1184,7 @@ const struct resource_caps *dce110_resource_cap( static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool, struct hw_asic_id asic_id) { @@ -1206,9 +1206,9 @@ static bool construct( pool->base.pipe_count = pool->base.res_cap->num_timing_generator; pool->base.underlay_pipe_index = pool->base.pipe_count; - dc->public.caps.max_downscale_ratio = 150; - dc->public.caps.i2c_speed_in_khz = 100; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 150; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -1351,7 +1351,7 @@ static bool construct( if (!dce110_hw_sequencer_construct(dc)) goto res_create_fail; - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); @@ -1366,7 +1366,7 @@ static bool construct( struct resource_pool *dce110_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct hw_asic_id asic_id) { struct dce110_resource_pool *pool = diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h index 8e2e85dd30b9..5bb692d037d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -28,7 +28,7 @@ #include "core_types.h" -struct core_dc; +struct dc; struct resource_pool; #define TO_DCE110_RES_POOL(pool)\ @@ -42,7 +42,7 @@ enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); struct resource_pool *dce110_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct hw_asic_id asic_id); #endif /* __DC_RESOURCE_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c index 204f613467b7..8816e09110e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c @@ -25,7 +25,6 @@ #include "dm_services.h" #include "dc.h" -#include "core_dc.h" #include "core_types.h" #include "dce112_hw_sequencer.h" @@ -112,7 +111,7 @@ static void dce112_init_pte(struct dc_context *ctx) } static bool dce112_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -153,7 +152,7 @@ static bool dce112_enable_display_power_gating( return false; } -bool dce112_hw_sequencer_construct(struct core_dc *dc) +bool dce112_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h index d96c582da45c..37bd60cc93f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h @@ -28,9 +28,9 @@ #include "core_types.h" -struct core_dc; +struct dc; -bool dce112_hw_sequencer_construct(struct core_dc *dc); +bool dce112_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index d6e58a25f3d0..89a8dfa68c01 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -723,7 +723,7 @@ static struct clock_source *find_matching_pll( } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -759,7 +759,7 @@ static enum dc_status build_mapped_resource( } bool dce112_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { bool result = false; @@ -837,7 +837,7 @@ bool dce112_validate_bandwidth( } enum dc_status resource_map_phy_clock_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -904,7 +904,7 @@ static bool dce112_validate_surface_sets( } enum dc_status dce112_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -948,7 +948,7 @@ enum dc_status dce112_validate_with_context( } enum dc_status dce112_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *stream, struct validate_context *context) { @@ -968,7 +968,7 @@ enum dc_status dce112_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } @@ -997,7 +997,7 @@ static const struct resource_funcs dce112_res_pool_funcs = { .validate_plane = dce100_validate_plane }; -static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +static void bw_calcs_data_update_from_pplib(struct dc *dc) { struct dm_pp_clock_levels_with_latency eng_clks = {0}; struct dm_pp_clock_levels_with_latency mem_clks = {0}; @@ -1153,7 +1153,7 @@ const struct resource_caps *dce112_resource_cap( static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -1170,9 +1170,9 @@ static bool construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 100; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -1319,7 +1319,7 @@ static bool construct( &res_create_funcs)) goto res_create_fail; - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; /* Create hardware sequencer */ if (!dce112_hw_sequencer_construct(dc)) @@ -1338,7 +1338,7 @@ static bool construct( struct resource_pool *dce112_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index feef559f1ecd..69f8f689196d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -28,27 +28,27 @@ #include "core_types.h" -struct core_dc; +struct dc; struct resource_pool; struct resource_pool *dce112_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); enum dc_status dce112_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, struct validate_context *old_context); enum dc_status dce112_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context); bool dce112_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index 91301b412aa0..d6225f332431 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -25,7 +25,6 @@ #include "dm_services.h" #include "dc.h" -#include "core_dc.h" #include "core_types.h" #include "dce120_hw_sequencer.h" #include "dce/dce_hwseq.h" @@ -149,7 +148,7 @@ static void dce120_init_pte(struct dc_context *ctx, uint8_t controller_id) #endif static bool dce120_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -247,7 +246,7 @@ static void dce120_update_dchub( -bool dce120_hw_sequencer_construct(struct core_dc *dc) +bool dce120_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h index 3402413c7156..6448a17c2fde 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h @@ -28,9 +28,9 @@ #include "core_types.h" -struct core_dc; +struct dc; -bool dce120_hw_sequencer_construct(struct core_dc *dc); +bool dce120_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 562ae2205a90..b8fcdff40db3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -410,7 +410,7 @@ void dce120_clock_source_destroy(struct clock_source **clk_src) } -bool dce120_hw_sequencer_create(struct core_dc *dc) +bool dce120_hw_sequencer_create(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure @@ -704,7 +704,7 @@ static const struct resource_funcs dce120_res_pool_funcs = { .validate_plane = dce100_validate_plane }; -static void bw_calcs_data_update_from_pplib(struct core_dc *dc) +static void bw_calcs_data_update_from_pplib(struct dc *dc) { struct dm_pp_clock_levels_with_latency eng_clks = {0}; struct dm_pp_clock_levels_with_latency mem_clks = {0}; @@ -831,7 +831,7 @@ static void bw_calcs_data_update_from_pplib(struct core_dc *dc) static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -847,10 +847,10 @@ static bool construct( pool->base.pipe_count = res_cap.num_timing_generator; pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 100; - dc->public.caps.max_cursor_size = 128; - dc->public.debug = debug_defaults; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.max_cursor_size = 128; + dc->debug = debug_defaults; /************************************************* * Create resources * @@ -982,7 +982,7 @@ static bool construct( if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); @@ -1003,7 +1003,7 @@ static bool construct( struct resource_pool *dce120_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h index 038c78dcc247..3d1f3cf012f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h @@ -28,12 +28,12 @@ #include "core_types.h" -struct core_dc; +struct dc; struct resource_pool; struct resource_pool *dce120_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); #endif /* __DC_RESOURCE_DCE120_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index 4cba80ff6ca4..28fe3824441f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -25,7 +25,6 @@ #include "dm_services.h" #include "dc.h" -#include "core_dc.h" #include "core_types.h" #include "dce80_hw_sequencer.h" @@ -72,7 +71,7 @@ static const struct dce80_hw_seq_reg_offsets reg_offsets[] = { /***************************PIPE_CONTROL***********************************/ static bool dce80_enable_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -107,7 +106,7 @@ static bool dce80_enable_display_power_gating( return false; } -bool dce80_hw_sequencer_construct(struct core_dc *dc) +bool dce80_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h index 7cc203f433d3..9d6dd05bd596 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h @@ -28,9 +28,9 @@ #include "core_types.h" -struct core_dc; +struct dc; -bool dce80_hw_sequencer_construct(struct core_dc *dc); +bool dce80_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 132117e8bb77..838bfdaee009 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -684,7 +684,7 @@ static void destruct(struct dce110_resource_pool *pool) } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -720,7 +720,7 @@ static enum dc_status build_mapped_resource( } bool dce80_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context) { /* TODO implement when needed but for now hardcode max value*/ @@ -752,7 +752,7 @@ static bool dce80_validate_surface_sets( } enum dc_status dce80_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -795,7 +795,7 @@ enum dc_status dce80_validate_with_context( } enum dc_status dce80_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) { @@ -815,7 +815,7 @@ enum dc_status dce80_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } @@ -845,7 +845,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { static bool dce80_construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -865,9 +865,9 @@ static bool dce80_construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap.num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 40; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -974,7 +974,7 @@ static bool dce80_construct( } } - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) @@ -993,7 +993,7 @@ static bool dce80_construct( struct resource_pool *dce80_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); @@ -1010,7 +1010,7 @@ struct resource_pool *dce80_create_resource_pool( static bool dce81_construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -1030,9 +1030,9 @@ static bool dce81_construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap_81.num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 40; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -1139,7 +1139,7 @@ static bool dce81_construct( } } - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) @@ -1158,7 +1158,7 @@ static bool dce81_construct( struct resource_pool *dce81_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); @@ -1175,7 +1175,7 @@ struct resource_pool *dce81_create_resource_pool( static bool dce83_construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dce110_resource_pool *pool) { unsigned int i; @@ -1195,9 +1195,9 @@ static bool dce83_construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; pool->base.pipe_count = res_cap_83.num_timing_generator; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 40; - dc->public.caps.max_cursor_size = 128; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; /************************************************* * Create resources * @@ -1300,7 +1300,7 @@ static bool dce83_construct( } } - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; if (!resource_construct(num_virtual_links, dc, &pool->base, &res_create_funcs)) @@ -1319,7 +1319,7 @@ static bool dce83_construct( struct resource_pool *dce83_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dce110_resource_pool *pool = dm_alloc(sizeof(struct dce110_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h index 04f0cfe24ef2..eff31ab83a39 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h @@ -28,20 +28,20 @@ #include "core_types.h" -struct core_dc; +struct dc; struct resource_pool; struct resource_pool *dce80_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); struct resource_pool *dce81_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); struct resource_pool *dce83_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); #endif /* __DC_RESOURCE_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c index 11386121f8ed..684241cb40d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c @@ -26,7 +26,6 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "reg_helper.h" -#include "core_dc.h" #include "resource.h" #include "dwb.h" #include "dcn10_dwb.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 184627c8685e..d5d2398d92b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -52,7 +52,7 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name -static void log_mpc_crc(struct core_dc *dc) +static void log_mpc_crc(struct dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct dce_hwseq *hws = dc->hwseq; @@ -130,7 +130,7 @@ static void dcn10_hubbub_wm_read_state(struct dce_hwseq *hws, s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); } -static void dcn10_log_hubbub_state(struct core_dc *dc) +static void dcn10_log_hubbub_state(struct dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct dcn_hubbub_wm wm; @@ -157,7 +157,7 @@ static void dcn10_log_hubbub_state(struct core_dc *dc) DTN_INFO("\n"); } -static void dcn10_log_hw_state(struct core_dc *dc) +static void dcn10_log_hw_state(struct dc *dc) { struct dc_context *dc_ctx = dc->ctx; struct resource_pool *pool = dc->res_pool; @@ -273,7 +273,7 @@ static void verify_allow_pstate_change_high( forced_pstate_allow = true; if (should_log_hw_state) { - dcn10_log_hw_state(DC_TO_CORE(hws->ctx->dc)); + dcn10_log_hw_state(hws->ctx->dc); } BREAK_TO_DEBUGGER(); @@ -746,7 +746,7 @@ static void power_on_plane( "Un-gated front end for pipe %d\n", plane_id); } -static void bios_golden_init(struct core_dc *dc) +static void bios_golden_init(struct dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; int i; @@ -762,7 +762,7 @@ static void bios_golden_init(struct core_dc *dc) } } -static void dcn10_init_hw(struct core_dc *dc) +static void dcn10_init_hw(struct dc *dc) { int i; struct abm *abm = dc->res_pool->abm; @@ -773,7 +773,7 @@ static void dcn10_init_hw(struct core_dc *dc) REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); REG_WRITE(DIO_MEM_PWR_CTRL, 0); - if (!dc->public.debug.disable_clock_gate) { + if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); @@ -830,7 +830,7 @@ static void dcn10_init_hw(struct core_dc *dc) /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ REG_WRITE(DIO_MEM_PWR_CTRL, 0); - if (!dc->public.debug.disable_clock_gate) { + if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); @@ -845,7 +845,7 @@ static void dcn10_init_hw(struct core_dc *dc) static enum dc_status dcn10_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, struct validate_context *context, - struct core_dc *dc) + struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; enum dc_color_space color_space; @@ -932,7 +932,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( } static void reset_back_end_for_pipe( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { @@ -979,7 +979,7 @@ static void reset_back_end_for_pipe( } /* trigger HW to start disconnect plane from stream on the next vsync */ -static void plane_atomic_disconnect(struct core_dc *dc, +static void plane_atomic_disconnect(struct dc *dc, int fe_idx) { struct mem_input *mi = dc->res_pool->mis[fe_idx]; @@ -1004,10 +1004,10 @@ static void plane_atomic_disconnect(struct core_dc *dc, if (opp_id == dc->res_pool->pipe_count) return; - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); mi->funcs->dcc_control(mi, false, false); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx); @@ -1015,7 +1015,7 @@ static void plane_atomic_disconnect(struct core_dc *dc, /* disable HW used by plane. * note: cannot disable until disconnect is complete */ -static void plane_atomic_disable(struct core_dc *dc, +static void plane_atomic_disable(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; @@ -1037,7 +1037,7 @@ static void plane_atomic_disable(struct core_dc *dc, mi->opp_id = 0xf; mi->mpcc_id = 0xf; - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); REG_UPDATE(HUBP_CLK_CNTL[fe_idx], @@ -1049,7 +1049,7 @@ static void plane_atomic_disable(struct core_dc *dc, REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 0); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } @@ -1057,7 +1057,7 @@ static void plane_atomic_disable(struct core_dc *dc, * kill power to plane hw * note: cannot power down until plane is disable */ -static void plane_atomic_power_down(struct core_dc *dc, int fe_idx) +static void plane_atomic_power_down(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; struct transform *xfm = dc->res_pool->transforms[fe_idx]; @@ -1072,13 +1072,13 @@ static void plane_atomic_power_down(struct core_dc *dc, int fe_idx) dm_logger_write(dc->ctx->logger, LOG_DC, "Power gated front end %d\n", fe_idx); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } static void reset_front_end( - struct core_dc *dc, + struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; @@ -1097,7 +1097,7 @@ static void reset_front_end( REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1); tg->funcs->unlock(tg); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(hws); if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) @@ -1112,7 +1112,7 @@ static void reset_front_end( fe_idx); } -static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) +static void dcn10_power_down_fe(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; struct transform *xfm = dc->res_pool->transforms[fe_idx]; @@ -1129,12 +1129,12 @@ static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx) dm_logger_write(dc->ctx->logger, LOG_DC, "Power gated front end %d\n", fe_idx); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } static void reset_hw_ctx_wrap( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { int i; @@ -1246,7 +1246,7 @@ static void toggle_watermark_change_req(struct dce_hwseq *hws) DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); } -static void dcn10_update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx) +static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) { bool addr_patched = false; PHYSICAL_ADDRESS_LOC addr; @@ -1657,7 +1657,7 @@ static bool dcn10_set_output_transfer_func( } static void dcn10_pipe_control_lock( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe, bool lock) { @@ -1669,7 +1669,7 @@ static void dcn10_pipe_control_lock( if (pipe->top_pipe) return; - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); if (lock) @@ -1677,7 +1677,7 @@ static void dcn10_pipe_control_lock( else pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } @@ -1719,7 +1719,7 @@ static bool wait_for_reset_trigger_to_occur( } static void dcn10_enable_timing_synchronization( - struct core_dc *dc, + struct dc *dc, int group_index, int group_size, struct pipe_ctx *grouped_pipes[]) @@ -1748,7 +1748,7 @@ static void dcn10_enable_timing_synchronization( } static void print_rq_dlg_ttu( - struct core_dc *core_dc, + struct dc *core_dc, struct pipe_ctx *pipe_ctx) { dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS, @@ -1870,14 +1870,14 @@ static void print_rq_dlg_ttu( } static void dcn10_power_on_fe( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } @@ -1928,7 +1928,7 @@ static void dcn10_power_on_fe( print_rq_dlg_ttu(dc, pipe_ctx); } - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } } @@ -2084,7 +2084,7 @@ static void dcn10_get_surface_visual_confirm_color( } static void update_dchubp_dpp( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { @@ -2126,7 +2126,7 @@ static void update_dchubp_dpp( size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; - if (dc->public.config.gpu_vm_support) + if (dc->config.gpu_vm_support) mi->funcs->mem_input_program_pte_vm( pipe_ctx->plane_res.mi, plane_state->format, @@ -2142,7 +2142,7 @@ static void update_dchubp_dpp( mpcc_cfg.opp = pipe_ctx->stream_res.opp; for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) mpcc_cfg.z_index++; - if (dc->public.debug.surface_visual_confirm) + if (dc->debug.surface_visual_confirm) dcn10_get_surface_visual_confirm_color( pipe_ctx, &mpcc_cfg.black_color); else @@ -2187,7 +2187,7 @@ static void update_dchubp_dpp( static void program_all_pipe_in_tree( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe_ctx, struct validate_context *context) { @@ -2201,7 +2201,7 @@ static void program_all_pipe_in_tree( /* watermark is for all pipes */ program_watermarks(dc->hwseq, &context->bw.dcn.watermarks, ref_clk_mhz); - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { /* pstate stuck check after watermark update */ verify_allow_pstate_change_high(dc->hwseq); } @@ -2236,7 +2236,7 @@ static void program_all_pipe_in_tree( update_dchubp_dpp(dc, pipe_ctx, context); } - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { /* pstate stuck check after each pipe is programmed */ verify_allow_pstate_change_high(dc->hwseq); } @@ -2246,7 +2246,7 @@ static void program_all_pipe_in_tree( } static void dcn10_pplib_apply_display_requirements( - struct core_dc *dc, + struct dc *dc, struct validate_context *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -2273,14 +2273,14 @@ static void dcn10_pplib_apply_display_requirements( } static void dcn10_apply_ctx_for_surface( - struct core_dc *dc, + struct dc *dc, const struct dc_stream_state *stream, int num_planes, struct validate_context *context) { int i, be_idx; - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); be_idx = -1; @@ -2351,7 +2351,7 @@ static void dcn10_apply_ctx_for_surface( "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", old_pipe_ctx->mpcc->inst);*/ - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); old_pipe_ctx->top_pipe = NULL; @@ -2422,18 +2422,18 @@ static void dcn10_apply_ctx_for_surface( context->bw.dcn.watermarks.d.pte_meta_urgent_ns ); - if (dc->public.debug.sanity_checks) + if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); } static void dcn10_set_bandwidth( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed) { struct dm_pp_clock_for_voltage_req clock; - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } @@ -2488,7 +2488,7 @@ static void dcn10_set_bandwidth( } dcn10_pplib_apply_display_requirements(dc, context); - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } @@ -2541,7 +2541,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, } static void set_plane_config( - const struct core_dc *dc, + const struct dc *dc, struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx) { @@ -2586,7 +2586,7 @@ static void dcn10_config_stereo_parameters( return; } -static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) +static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) { struct crtc_stereo_flags flags = { 0 }; struct dc_stream_state *stream = pipe_ctx->stream; @@ -2607,13 +2607,13 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc) } static void dcn10_wait_for_mpcc_disconnect( - struct core_dc *dc, + struct dc *dc, struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx) { int i; - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } @@ -2631,14 +2631,14 @@ static void dcn10_wait_for_mpcc_disconnect( } } - if (dc->public.debug.sanity_checks) { + if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); } } static bool dcn10_dummy_display_power_gating( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating) @@ -2652,7 +2652,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) struct timing_generator *tg = pipe_ctx->stream_res.tg; if (plane_state->ctx->dc->debug.sanity_checks) { - struct core_dc *dc = DC_TO_CORE(plane_state->ctx->dc); + struct dc *dc = plane_state->ctx->dc; verify_allow_pstate_change_high(dc->hwseq); } @@ -2716,7 +2716,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { }; -void dcn10_hw_sequencer_construct(struct core_dc *dc) +void dcn10_hw_sequencer_construct(struct dc *dc) { dc->hwss = dcn10_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 28218dc43522..8bb09de8dcd7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -28,9 +28,9 @@ #include "core_types.h" -struct core_dc; +struct dc; -void dcn10_hw_sequencer_construct(struct core_dc *dc); +void dcn10_hw_sequencer_construct(struct dc *dc); extern void fill_display_configs( const struct validate_context *context, struct dm_pp_display_configuration *pp_display_cfg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index c36843d497ac..2d9e88f08abb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -825,7 +825,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) } static enum dc_status build_mapped_resource( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context) { @@ -872,7 +872,7 @@ static enum dc_status build_mapped_resource( } enum dc_status dcn10_validate_with_context( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, @@ -917,7 +917,7 @@ enum dc_status dcn10_validate_with_context( } enum dc_status dcn10_validate_guaranteed( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *dc_stream, struct validate_context *context) { @@ -937,7 +937,7 @@ enum dc_status dcn10_validate_guaranteed( if (result == DC_OK) { validate_guaranteed_copy_streams( - context, dc->public.caps.max_streams); + context, dc->caps.max_streams); result = resource_build_scaling_params_for_context(dc, context); } if (result == DC_OK && !dcn_validate_bandwidth(dc, context)) @@ -1221,7 +1221,7 @@ static struct resource_funcs dcn10_res_pool_funcs = { static bool construct( uint8_t num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct dcn10_resource_pool *pool) { int i; @@ -1244,16 +1244,16 @@ static bool construct( /* TODO: Hardcode to correct number of functional controllers */ pool->base.pipe_count = 4; - dc->public.caps.max_downscale_ratio = 200; - dc->public.caps.i2c_speed_in_khz = 100; - dc->public.caps.max_cursor_size = 256; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.max_cursor_size = 256; - dc->public.caps.max_slave_planes = 1; + dc->caps.max_slave_planes = 1; if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->public.debug = debug_defaults_drv; + dc->debug = debug_defaults_drv; else - dc->public.debug = debug_defaults_diags; + dc->debug = debug_defaults_diags; /************************************************* * Create resources * @@ -1327,7 +1327,7 @@ static bool construct( if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { dc->dcn_soc->urgent_latency = 3; - dc->public.debug.disable_dmcu = true; + dc->debug.disable_dmcu = true; dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; } @@ -1347,10 +1347,10 @@ static bool construct( } } - if (!dc->public.debug.disable_pplib_clock_request) + if (!dc->debug.disable_pplib_clock_request) dcn_bw_update_from_pplib(dc); dcn_bw_sync_calcs_and_dml(dc); - if (!dc->public.debug.disable_pplib_wm_range) + if (!dc->debug.disable_pplib_wm_range) dcn_bw_notify_pplib_of_wm_ranges(dc); { @@ -1424,9 +1424,9 @@ static bool construct( goto res_create_fail; dcn10_hw_sequencer_construct(dc); - dc->public.caps.max_planes = pool->base.pipe_count; + dc->caps.max_planes = pool->base.pipe_count; - dc->public.cap_funcs = cap_funcs; + dc->cap_funcs = cap_funcs; return true; @@ -1449,7 +1449,7 @@ static bool construct( struct resource_pool *dcn10_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc) + struct dc *dc) { struct dcn10_resource_pool *pool = dm_alloc(sizeof(struct dcn10_resource_pool)); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h index 5f84dbd0bdea..8f71225bc61b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h @@ -31,7 +31,7 @@ #define TO_DCN10_RES_POOL(pool)\ container_of(pool, struct dcn10_resource_pool, base) -struct core_dc; +struct dc; struct resource_pool; struct _vcs_dpi_display_pipe_params_st; @@ -40,7 +40,7 @@ struct dcn10_resource_pool { }; struct resource_pool *dcn10_create_resource_pool( uint8_t num_virtual_links, - struct core_dc *dc); + struct dc *dc); #endif /* __DC_RESOURCE_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h b/drivers/gpu/drm/amd/display/dc/inc/core_dc.h deleted file mode 100644 index ebe1fd78a92a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/core_dc.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * core_dc.h - * - * Created on: Nov 13, 2015 - * Author: yonsun - */ - -#ifndef __CORE_DC_H__ -#define __CORE_DC_H__ - -#include "core_types.h" -#include "hw_sequencer.h" -#include "compressor.h" - -#define DC_TO_CORE(dc)\ - container_of(dc, struct core_dc, public) - -struct core_dc { - struct dc public; - struct dc_context *ctx; - - uint8_t link_count; - struct dc_link *links[MAX_PIPES * 2]; - - struct validate_context *current_context; - struct resource_pool *res_pool; - - /* Display Engine Clock levels */ - struct dm_pp_clock_levels sclk_lvls; - - /* Inputs into BW and WM calculations. */ - struct bw_calcs_dceip *bw_dceip; - struct bw_calcs_vbios *bw_vbios; -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box *dcn_soc; - struct dcn_ip_params *dcn_ip; - struct display_mode_lib dml; -#endif - - /* HW functions */ - struct hw_sequencer_funcs hwss; - struct dce_hwseq *hwseq; - - /* temp store of dm_pp_display_configuration - * to compare to see if display config changed - */ - struct dm_pp_display_configuration prev_display_config; - - /* FBC compressor */ -#ifdef ENABLE_FBC - struct compressor *fbc_compressor; -#endif -}; - -#endif /* __CORE_DC_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 28454028434c..f8ade552c595 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -52,7 +52,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, /************ link *****************/ struct link_init_data { - const struct core_dc *dc; + const struct dc *dc; struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ uint32_t connector_index; /* this will be mapped to the HPD pins */ uint32_t link_index; /* this is mapped to DAL display_index @@ -87,19 +87,19 @@ struct resource_funcs { struct link_encoder *(*link_enc_create)( const struct encoder_init_data *init); enum dc_status (*validate_with_context)( - const struct core_dc *dc, + struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *context, struct validate_context *old_context); enum dc_status (*validate_guaranteed)( - const struct core_dc *dc, + struct dc *dc, struct dc_stream_state *stream, struct validate_context *context); bool (*validate_bandwidth)( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context); struct pipe_ctx *(*acquire_idle_pipe_for_layer)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h index 36c48f7d3f56..6a205b010084 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h @@ -33,7 +33,7 @@ #include "bw_fixed.h" struct pipe_ctx; -struct core_dc; +struct dc; struct validate_context; struct dce_bw_output; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 7e8abcd60d12..58744fe87ed8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -34,7 +34,7 @@ #include "display_clock.h" #include "../dml/display_mode_lib.h" -struct core_dc; +struct dc; struct validate_context; /******************************************************************************* @@ -620,16 +620,16 @@ struct dcn_ip_params { extern const struct dcn_ip_params dcn10_ip_defaults; bool dcn_validate_bandwidth( - const struct core_dc *dc, + struct dc *dc, struct validate_context *context); unsigned int dcn_find_dcfclk_suits_all( - const struct core_dc *dc, + const struct dc *dc, struct clocks_value *clocks); -void dcn_bw_update_from_pplib(struct core_dc *dc); -void dcn_bw_notify_pplib_of_wm_ranges(struct core_dc *dc); -void dcn_bw_sync_calcs_and_dml(struct core_dc *dc); +void dcn_bw_update_from_pplib(struct dc *dc); +void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc); +void dcn_bw_sync_calcs_and_dml(struct dc *dc); #endif /* __DCN_CALCS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index a02f18ae527d..f876a11c903f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -30,6 +30,7 @@ #include "dml/display_mode_structs.h" +struct dchub_init_data; struct cstate_pstate_watermarks_st { uint32_t cstate_exit_ns; uint32_t cstate_enter_plus_exit_ns; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 7689e372b9da..c73dca9f6d46 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -25,8 +25,10 @@ #ifndef __DC_HW_SEQUENCER_H__ #define __DC_HW_SEQUENCER_H__ -#include "core_types.h" -#include "timing_generator.h" +#include "dc_types.h" +#include "clock_source.h" +#include "inc/hw/timing_generator.h" +#include "core_status.h" enum pipe_gating_control { PIPE_GATING_CONTROL_DISABLE = 0, @@ -46,25 +48,31 @@ struct dce_hwseq { struct dce_hwseq_wa wa; }; +struct pipe_ctx; +struct validate_context; +struct dchub_init_data; +struct dc_static_screen_events; +struct resource_pool; +struct resource_context; struct hw_sequencer_funcs { - void (*init_hw)(struct core_dc *dc); + void (*init_hw)(struct dc *dc); enum dc_status (*apply_ctx_to_hw)( - struct core_dc *dc, struct validate_context *context); + struct dc *dc, struct validate_context *context); void (*reset_hw_ctx_wrap)( - struct core_dc *dc, struct validate_context *context); + struct dc *dc, struct validate_context *context); void (*apply_ctx_for_surface)( - struct core_dc *dc, + struct dc *dc, const struct dc_stream_state *stream, int num_planes, struct validate_context *context); void (*set_plane_config)( - const struct core_dc *dc, + const struct dc *dc, struct pipe_ctx *pipe_ctx, struct resource_context *res_ctx); @@ -77,7 +85,7 @@ struct hw_sequencer_funcs { uint16_t *matrix); void (*update_plane_addr)( - const struct core_dc *dc, + const struct dc *dc, struct pipe_ctx *pipe_ctx); void (*update_dchub)( @@ -95,12 +103,12 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream); - void (*power_down)(struct core_dc *dc); + void (*power_down)(struct dc *dc); - void (*enable_accelerated_mode)(struct core_dc *dc); + void (*enable_accelerated_mode)(struct dc *dc); void (*enable_timing_synchronization)( - struct core_dc *dc, + struct dc *dc, int group_index, int group_size, struct pipe_ctx *grouped_pipes[]); @@ -110,14 +118,14 @@ struct hw_sequencer_funcs { bool clock_gating); bool (*enable_display_power_gating)( - struct core_dc *dc, + struct dc *dc, uint8_t controller_id, struct dc_bios *dcb, enum pipe_gating_control power_gating); - void (*power_down_front_end)(struct core_dc *dc, int fe_idx); + void (*power_down_front_end)(struct dc *dc, int fe_idx); - void (*power_on_front_end)(struct core_dc *dc, + void (*power_on_front_end)(struct dc *dc, struct pipe_ctx *pipe, struct validate_context *context); @@ -131,12 +139,12 @@ struct hw_sequencer_funcs { struct dc_link_settings *link_settings); void (*pipe_control_lock)( - struct core_dc *dc, + struct dc *dc, struct pipe_ctx *pipe, bool lock); void (*set_bandwidth)( - struct core_dc *dc, + struct dc *dc, struct validate_context *context, bool decrease_allowed); @@ -152,23 +160,23 @@ struct hw_sequencer_funcs { enum dc_status (*prog_pixclk_crtc_otg)( struct pipe_ctx *pipe_ctx, struct validate_context *context, - struct core_dc *dc); + struct dc *dc); void (*setup_stereo)( struct pipe_ctx *pipe_ctx, - struct core_dc *dc); + struct dc *dc); void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable); - void (*log_hw_state)(struct core_dc *dc); + void (*log_hw_state)(struct dc *dc); - void (*wait_for_mpcc_disconnect)(struct core_dc *dc, + void (*wait_for_mpcc_disconnect)(struct dc *dc, struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); }; void color_space_to_black_color( - const struct core_dc *dc, + const struct dc *dc, enum dc_color_space colorspace, struct tg_color *black_color); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 7f30d9937d10..13218a52e2fa 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -27,7 +27,6 @@ #include "core_types.h" #include "core_status.h" -#include "core_dc.h" #include "dal_asic_id.h" /* TODO unhardcode, 4 for CZ*/ @@ -67,27 +66,27 @@ struct resource_create_funcs { bool resource_construct( unsigned int num_virtual_links, - struct core_dc *dc, + struct dc *dc, struct resource_pool *pool, const struct resource_create_funcs *create_funcs); struct resource_pool *dc_create_resource_pool( - struct core_dc *dc, + struct dc *dc, int num_virtual_links, enum dce_version dc_version, struct hw_asic_id asic_id); -void dc_destroy_resource_pool(struct core_dc *dc); +void dc_destroy_resource_pool(struct dc *dc); enum dc_status resource_map_pool_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); enum dc_status resource_build_scaling_params_for_context( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context); void resource_build_info_frame(struct pipe_ctx *pipe_ctx); @@ -148,12 +147,12 @@ void resource_validate_ctx_update_pointer_after_copy( struct validate_context *dst_ctx); enum dc_status resource_map_clock_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context); enum dc_status resource_map_phy_clock_resources( - const struct core_dc *dc, + const struct dc *dc, struct validate_context *context, struct validate_context *old_context); diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 24e47eb8cf3f..e3a12f3e0642 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -34,8 +34,8 @@ #include "ivsrcid/ivsrcid_vislands30.h" -#include "core_dc.h" - +#include "dc.h" +#include "core_types.h" static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) @@ -206,7 +206,7 @@ bool dce110_vblank_set( bool enable) { struct dc_context *dc_ctx = irq_service->ctx; - struct core_dc *core_dc = DC_TO_CORE(irq_service->ctx->dc); + struct dc *core_dc = irq_service->ctx->dc; enum dc_irq_source dal_irq_src = dc_interrupt_to_irq_source( irq_service->ctx->dc, info->src_id, diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index 7e8cb22f280f..f458ef8e4c57 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -36,7 +36,6 @@ #include "ivsrcid/ivsrcid_vislands30.h" #include "dc_types.h" -#include "inc/core_dc.h" static bool hpd_ack( struct irq_service *irq_service, diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index beb790937769..93c8556358f0 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -76,23 +76,23 @@ void logger_write(struct dal_logger *logger, void *paralist); void pre_surface_trace( - const struct dc *dc, + struct dc *dc, const struct dc_plane_state *const *plane_states, int surface_count); void update_surface_trace( - const struct dc *dc, + struct dc *dc, const struct dc_surface_update *updates, int surface_count); -void post_surface_trace(const struct dc *dc); +void post_surface_trace(struct dc *dc); void context_timing_trace( - const struct dc *dc, + struct dc *dc, struct resource_context *res_ctx); void context_clock_trace( - const struct dc *dc, + struct dc *dc, struct validate_context *context); /* Any function which is empty or have incomplete implementation should be diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index f0a3e4332a09..f49203b3eb94 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -27,7 +27,6 @@ #include "dc.h" #include "mod_freesync.h" #include "core_types.h" -#include "core_dc.h" #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32 @@ -146,7 +145,7 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) struct core_freesync *core_freesync = dm_alloc(sizeof(struct core_freesync)); - struct core_dc *core_dc = DC_TO_CORE(dc); + struct dc *core_dc = dc; struct persistent_data_flag flag; @@ -246,7 +245,7 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct dc_stream_state *stream, struct mod_freesync_caps *caps) { - struct core_dc *core_dc = NULL; + struct dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; struct persistent_data_flag flag; @@ -257,7 +256,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_dc = DC_TO_CORE(core_freesync->dc); + core_dc = core_freesync->dc; flag.save_per_edid = true; flag.save_per_link = false; @@ -971,14 +970,14 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, unsigned int stream_index, map_index; int persistent_data = 0; struct persistent_data_flag flag; - struct core_dc *core_dc = NULL; + struct dc *core_dc = NULL; struct core_freesync *core_freesync = NULL; if (mod_freesync == NULL) return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_dc = DC_TO_CORE(core_freesync->dc); + core_dc = core_freesync->dc; flag.save_per_edid = true; flag.save_per_link = false; -- GitLab From 641106d3fab8790af12c71e750d9b6287ffc75ce Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 3 Aug 2017 16:41:48 -0400 Subject: [PATCH 0786/2898] drm/amd/display: Use MAX_PIPES for DTO reg arrays Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 238c03f14959..c45e2f76189e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -107,9 +107,9 @@ struct dce110_clk_src_regs { /* below are for DTO. * todo: should probably use different struct to not waste space */ - uint32_t PHASE[4]; - uint32_t MODULO[4]; - uint32_t PIXEL_RATE_CNTL[4]; + uint32_t PHASE[MAX_PIPES]; + uint32_t MODULO[MAX_PIPES]; + uint32_t PIXEL_RATE_CNTL[MAX_PIPES]; }; struct dce110_clk_src { -- GitLab From 4e772ae5f99a1595a2e064a70d2eab4946e5c08d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 11 Aug 2017 11:23:30 -0400 Subject: [PATCH 0787/2898] drm/amd/display: blank otg before power gate front end. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d5d2398d92b8..ce48d81c4442 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2298,8 +2298,10 @@ static void dcn10_apply_ctx_for_surface( struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; - if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) + if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) { + old_pipe_ctx->stream_res.tg->funcs->set_blank(old_pipe_ctx->stream_res.tg, true); dcn10_power_down_fe(dc, old_pipe_ctx->pipe_idx); + } } return; } -- GitLab From 71afd9d14f49a0a16050ada488ac1be182f5602f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 11 Aug 2017 13:22:02 -0400 Subject: [PATCH 0788/2898] drm/amd/display: eDP power sequence T9 fail Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_link_hwss.c | 23 +++++++++++++++++++ .../drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index da880bd02ad7..e12f1f9fb590 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -110,6 +110,28 @@ void dp_enable_link_phy( dp_receiver_power_ctrl(link, true); } +bool edp_receiver_ready_T9(struct dc_link *link) +{ + unsigned int tries = 0; + unsigned char sinkstatus = 0; + unsigned char edpRev = 0; + enum dc_status result = DC_OK; + result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); + if (edpRev < DP_EDP_12) + return true; + /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ + do { + sinkstatus = 1; + result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); + if (sinkstatus == 0) + break; + if (result != DC_OK) + break; + dm_delay_in_microseconds(link->ctx, 100); //MAx T9 + } while (++tries < 50); + return result; +} + void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) { if (!link->wa_flags.dp_keep_receiver_powered) @@ -117,6 +139,7 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { link->link_enc->funcs->backlight_control(link->link_enc, false); + edp_receiver_ready_T9(link); link->link_enc->funcs->disable_output(link->link_enc, signal); link->link_enc->funcs->power_control(link->link_enc, false); } else diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 0dab5bacde3c..559a9f81c9c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -744,7 +744,7 @@ void dce110_link_encoder_edp_backlight_control( return; } - if (!enable && !is_panel_powered_on(enc110)) { + if (!enable && !is_panel_backlight_on(enc110)) { dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, "%s: panel already powered down. Do nothing.\n", __func__); -- GitLab From b4c8e6da39091b2931074e001febc598e2acdbb1 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 10 Aug 2017 16:16:20 -0400 Subject: [PATCH 0789/2898] drm/amd/display: Leave DCN config guard around fpu header See https://lists.freedesktop.org/archives/dri-devel/2017-August/149938.html Signed-off-by: Harry Wentland Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index a7d661d1ff1d..e9bf4c417cc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -75,7 +75,9 @@ BREAK_TO_DEBUGGER(); \ } while (0) +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include +#endif #define dm_alloc(size) kzalloc(size, GFP_KERNEL) #define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) -- GitLab From be7c97f6a7d10cd60f09001c61047055b49d5d8d Mon Sep 17 00:00:00 2001 From: Roman Li Date: Mon, 14 Aug 2017 17:35:08 -0400 Subject: [PATCH 0790/2898] drm/amd/display: Fix FBC compilation - Fixing compilation with ENABLE_FBC flag which was broken after flattening core_dc to dc Signed-off-by: Roman Li Reviewed-by: Jerry Zuo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 68056d888def..1210fdd48c56 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -35,6 +35,7 @@ #include #include "inc/hw_sequencer.h" +#include "inc/compressor.h" #include "dml/display_mode_lib.h" -- GitLab From 992fe94c1b6afdf6f09ada61d4a1ecc5df52fe5f Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 3 Aug 2017 08:49:41 -0400 Subject: [PATCH 0791/2898] drm/amd/display: remove fake address reporting when blank Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ce48d81c4442..23aa6e1242c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2666,14 +2666,6 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( pipe_ctx->plane_res.mi); - /* DCN we read INUSE address in MI, do we still need this wa? */ - if (plane_state->status.is_flip_pending && - !plane_state->visible) { - pipe_ctx->plane_res.mi->current_address = - pipe_ctx->plane_res.mi->request_address; - BREAK_TO_DEBUGGER(); - } - plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { -- GitLab From 0cb8a88122ecfaa183ede19748269cb4fb5c739c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Mon, 14 Aug 2017 18:17:01 -0400 Subject: [PATCH 0792/2898] drm/amd/display: move vm registers to hwsequencer Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 52 ++++++++- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 95 +++++++++++++++- .../amd/display/dc/dcn10/dcn10_mem_input.c | 106 +----------------- .../amd/display/dc/dcn10/dcn10_mem_input.h | 41 +------ .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 21 ++++ 5 files changed, 172 insertions(+), 143 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 3a1eb6a79d66..2d3a41f744af 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -206,7 +206,20 @@ SR(D1VGA_CONTROL), \ SR(D2VGA_CONTROL), \ SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL) + SR(D4VGA_CONTROL), \ + /* todo: get these from GVM instead of reading registers ourselves */\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ + MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ + MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ + MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ + MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ @@ -312,6 +325,19 @@ struct dce_hwseq_registers { uint32_t D2VGA_CONTROL; uint32_t D3VGA_CONTROL; uint32_t D4VGA_CONTROL; + /* MMHUB registers. read only. temporary hack */ + uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; + uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32; + uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32; + uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32; + uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32; + uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32; + uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; + uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; + uint32_t MC_VM_SYSTEM_APERTURE_LOW_ADDR; + uint32_t MC_VM_SYSTEM_APERTURE_HIGH_ADDR; }; /* set field name */ #define HWS_SF(blk_name, reg_name, field_name, post_fix)\ @@ -432,7 +458,17 @@ struct dce_hwseq_registers { HWS_SF(, DCHUBBUB_SDPIF_AGP_BASE, SDPIF_AGP_BASE, mask_sh), \ HWS_SF(, DCHUBBUB_SDPIF_AGP_BOT, SDPIF_AGP_BOT, mask_sh), \ HWS_SF(, DCHUBBUB_SDPIF_AGP_TOP, SDPIF_AGP_TOP, mask_sh), \ - HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh) + HWS_SF(DPP_TOP0_, DPP_CONTROL, DPPCLK_RATE_CONTROL, mask_sh), \ + /* todo: get these from GVM instead of reading registers ourselves */\ + HWS_SF(, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, PAGE_DIRECTORY_ENTRY_HI32, mask_sh),\ + HWS_SF(, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, PAGE_DIRECTORY_ENTRY_LO32, mask_sh),\ + HWS_SF(, VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, LOGICAL_PAGE_NUMBER_HI4, mask_sh),\ + HWS_SF(, VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, LOGICAL_PAGE_NUMBER_LO32, mask_sh),\ + HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, PHYSICAL_PAGE_ADDR_HI4, mask_sh),\ + HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ + HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ + HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ + HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ @@ -451,6 +487,18 @@ struct dce_hwseq_registers { type PIXEL_RATE_SOURCE; \ type PHYPLL_PIXEL_RATE_SOURCE; \ type PIXEL_RATE_PLL_SOURCE; \ + /* todo: get these from GVM instead of reading registers ourselves */\ + type PAGE_DIRECTORY_ENTRY_HI32;\ + type PAGE_DIRECTORY_ENTRY_LO32;\ + type LOGICAL_PAGE_NUMBER_HI4;\ + type LOGICAL_PAGE_NUMBER_LO32;\ + type PHYSICAL_PAGE_ADDR_HI4;\ + type PHYSICAL_PAGE_ADDR_LO32;\ + type PHYSICAL_PAGE_NUMBER_MSB;\ + type PHYSICAL_PAGE_NUMBER_LSB;\ + type LOGICAL_ADDR; \ + type ENABLE_L1_TLB;\ + type SYSTEM_ACCESS_MODE; #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 23aa6e1242c5..f0e49d16019c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2083,6 +2083,93 @@ static void dcn10_get_surface_visual_confirm_color( } } +static void mmhub_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, + struct vm_system_aperture_param *apt, + struct dce_hwseq *hws) +{ + PHYSICAL_ADDRESS_LOC physical_page_number; + uint32_t logical_addr_low; + uint32_t logical_addr_high; + + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, + PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); + REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, + PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); + + REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, + LOGICAL_ADDR, &logical_addr_low); + + REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, + LOGICAL_ADDR, &logical_addr_high); + + apt->sys_default.quad_part = physical_page_number.quad_part << 12; + apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; + apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; +} + +/* Temporary read settings, future will get values from kmd directly */ +static void mmhub_read_vm_context0_settings(struct dcn10_mem_input *mi, + struct vm_context0_param *vm0, + struct dce_hwseq *hws) +{ + PHYSICAL_ADDRESS_LOC fb_base; + PHYSICAL_ADDRESS_LOC fb_offset; + uint32_t fb_base_value; + uint32_t fb_offset_value; + + REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); + REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, + PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, + PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); + + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, + LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); + REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, + LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); + + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, + PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); + REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, + PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); + + /* + * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. + * Therefore we need to do + * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE + */ + fb_base.quad_part = (uint64_t)fb_base_value << 24; + fb_offset.quad_part = (uint64_t)fb_offset_value << 24; + vm0->pte_base.quad_part += fb_base.quad_part; + vm0->pte_base.quad_part -= fb_offset.quad_part; +} + +static void dcn10_program_pte_vm(struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation, + struct dce_hwseq *hws) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct vm_system_aperture_param apt = { {{ 0 } } }; + struct vm_context0_param vm0 = { { { 0 } } }; + + + mmhub_read_vm_system_aperture_settings(mi, &apt, hws); + mmhub_read_vm_context0_settings(mi, &vm0, hws); + + mem_input->funcs->mem_input_set_vm_system_aperture_settings(mem_input, &apt); + mem_input->funcs->mem_input_set_vm_context0_settings(mem_input, &vm0); +} + static void update_dchubp_dpp( struct dc *dc, struct pipe_ctx *pipe_ctx, @@ -2127,11 +2214,13 @@ static void update_dchubp_dpp( size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; if (dc->config.gpu_vm_support) - mi->funcs->mem_input_program_pte_vm( + dcn10_program_pte_vm( pipe_ctx->plane_res.mi, plane_state->format, &plane_state->tiling_info, - plane_state->rotation); + plane_state->rotation, + hws + ); ipp->funcs->ipp_setup(ipp, plane_state->format, @@ -2674,6 +2763,8 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) } } + + static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = program_gamut_remap, .program_csc_matrix = program_csc_matrix, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index f36585de15df..11daf6b5c7d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -625,38 +625,10 @@ static bool min10_is_flip_pending(struct mem_input *mem_input) return false; } -struct vm_system_aperture_param { - PHYSICAL_ADDRESS_LOC sys_default; - PHYSICAL_ADDRESS_LOC sys_low; - PHYSICAL_ADDRESS_LOC sys_high; -}; - -static void min10_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, - struct vm_system_aperture_param *apt) -{ - PHYSICAL_ADDRESS_LOC physical_page_number; - uint32_t logical_addr_low; - uint32_t logical_addr_high; - - REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, - PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); - REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, - PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); - - REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, - LOGICAL_ADDR, &logical_addr_low); - - REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, - LOGICAL_ADDR, &logical_addr_high); - - apt->sys_default.quad_part = physical_page_number.quad_part << 12; - apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; - apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; -} - -static void min10_set_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, struct vm_system_aperture_param *apt) { + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); PHYSICAL_ADDRESS_LOC mc_vm_apt_default; PHYSICAL_ADDRESS_LOC mc_vm_apt_low; PHYSICAL_ADDRESS_LOC mc_vm_apt_high; @@ -682,60 +654,10 @@ static void min10_set_vm_system_aperture_settings(struct dcn10_mem_input *mi, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); } -struct vm_context0_param { - PHYSICAL_ADDRESS_LOC pte_base; - PHYSICAL_ADDRESS_LOC pte_start; - PHYSICAL_ADDRESS_LOC pte_end; - PHYSICAL_ADDRESS_LOC fault_default; -}; - -/* Temporary read settings, future will get values from kmd directly */ -static void min10_read_vm_context0_settings(struct dcn10_mem_input *mi, - struct vm_context0_param *vm0) -{ - PHYSICAL_ADDRESS_LOC fb_base; - PHYSICAL_ADDRESS_LOC fb_offset; - uint32_t fb_base_value; - uint32_t fb_offset_value; - - REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); - REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); - - REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, - PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, - PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); - - REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, - LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, - LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); - - REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, - LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); - REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, - LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); - - REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, - PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); - REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, - PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); - - /* - * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. - * Therefore we need to do - * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR - * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE - */ - fb_base.quad_part = (uint64_t)fb_base_value << 24; - fb_offset.quad_part = (uint64_t)fb_offset_value << 24; - vm0->pte_base.quad_part += fb_base.quad_part; - vm0->pte_base.quad_part -= fb_offset.quad_part; -} - -static void min10_set_vm_context0_settings(struct dcn10_mem_input *mi, +static void min10_set_vm_context0_settings(struct mem_input *mem_input, const struct vm_context0_param *vm0) { + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); /* pte base */ REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); @@ -760,23 +682,6 @@ static void min10_set_vm_context0_settings(struct dcn10_mem_input *mi, /* VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, 0 */ REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); -} - -static void min10_program_pte_vm(struct mem_input *mem_input, - enum surface_pixel_format format, - union dc_tiling_info *tiling_info, - enum dc_rotation_angle rotation) -{ - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - struct vm_system_aperture_param apt = { {{ 0 } } }; - struct vm_context0_param vm0 = { { { 0 } } }; - - - min10_read_vm_system_aperture_settings(mi, &apt); - min10_read_vm_context0_settings(mi, &vm0); - - min10_set_vm_system_aperture_settings(mi, &apt); - min10_set_vm_context0_settings(mi, &vm0); /* control: enable VM PTE*/ REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, @@ -862,7 +767,8 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { min10_program_surface_config, .mem_input_is_flip_pending = min10_is_flip_pending, .mem_input_setup = min10_setup, - .mem_input_program_pte_vm = min10_program_pte_vm, + .mem_input_set_vm_system_aperture_settings = min10_set_vm_system_aperture_settings, + .mem_input_set_vm_context0_settings = min10_set_vm_context0_settings, .set_blank = min10_set_blank, .dcc_control = min10_dcc_control, .mem_program_viewport = min_set_viewport, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index b3ec16c17826..acee05155b5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -97,20 +97,7 @@ SRI(DCN_SURF0_TTU_CNTL1, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL0, HUBPREQ, id),\ SRI(DCN_SURF1_TTU_CNTL1, HUBPREQ, id),\ - SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id),\ - /* todo: get these from GVM instead of reading registers ourselves */\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32),\ - MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32),\ - MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32),\ - MMHUB_SR(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32),\ - MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB),\ - MMHUB_SR(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB),\ - MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ - MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) + SRI(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) #define MI_REG_LIST_DCN10(id)\ MI_REG_LIST_DCN(id),\ @@ -228,20 +215,6 @@ struct dcn_mi_registers { uint32_t DCN_VM_AGP_BASE; uint32_t DCN_VM_AGP_BOT; uint32_t DCN_VM_AGP_TOP; - - /* GC registers. read only. temporary hack */ - uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; - uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; - uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32; - uint32_t VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32; - uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32; - uint32_t VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32; - uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32; - uint32_t VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32; - uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB; - uint32_t MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB; - uint32_t MC_VM_SYSTEM_APERTURE_LOW_ADDR; - uint32_t MC_VM_SYSTEM_APERTURE_HIGH_ADDR; }; #define MI_SF(reg_name, field_name, post_fix)\ @@ -387,17 +360,7 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ - /* todo: get these from GVM instead of reading registers ourselves */\ - MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, PAGE_DIRECTORY_ENTRY_HI32, mask_sh),\ - MI_SF(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, PAGE_DIRECTORY_ENTRY_LO32, mask_sh),\ - MI_SF(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, LOGICAL_PAGE_NUMBER_HI4, mask_sh),\ - MI_SF(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, LOGICAL_PAGE_NUMBER_LO32, mask_sh),\ - MI_SF(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, PHYSICAL_PAGE_ADDR_HI4, mask_sh),\ - MI_SF(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ - MI_SF(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ - MI_SF(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ - MI_SF(MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh) #define DCN_MI_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index f876a11c903f..6f4f04da9e28 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -74,6 +74,19 @@ struct mem_input { struct stutter_modes stutter_mode; }; +struct vm_system_aperture_param { + PHYSICAL_ADDRESS_LOC sys_default; + PHYSICAL_ADDRESS_LOC sys_low; + PHYSICAL_ADDRESS_LOC sys_high; +}; + +struct vm_context0_param { + PHYSICAL_ADDRESS_LOC pte_base; + PHYSICAL_ADDRESS_LOC pte_start; + PHYSICAL_ADDRESS_LOC pte_end; + PHYSICAL_ADDRESS_LOC fault_default; +}; + struct mem_input_funcs { void (*mem_input_setup)( struct mem_input *mem_input, @@ -125,6 +138,14 @@ struct mem_input_funcs { union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation); + void (*mem_input_set_vm_system_aperture_settings)( + struct mem_input *mem_input, + struct vm_system_aperture_param *apt); + + void (*mem_input_set_vm_context0_settings)( + struct mem_input *mem_input, + const struct vm_context0_param *vm0); + void (*mem_input_program_surface_config)( struct mem_input *mem_input, enum surface_pixel_format format, -- GitLab From 1e8635ea0ea370bf4f0f2b2f1b3eb61474dd962a Mon Sep 17 00:00:00 2001 From: Zeyu Fan Date: Mon, 14 Aug 2017 18:43:11 -0400 Subject: [PATCH 0793/2898] drm/amd/display: Implement HDMI retimer settings for RV AM4 support. Signed-off-by: Zeyu Fan Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/bios/bios_parser2.c | 69 +++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 420 +++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 5 - .../display/include/grph_object_ctrl_defs.h | 38 ++ 5 files changed, 524 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 86fce5ae5856..f8d4f08bf985 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -993,6 +993,8 @@ static struct device_id device_type_from_device_id(uint16_t device_id) struct device_id result_device_id; + result_device_id.raw_device_tag = device_id; + switch (device_id) { case ATOM_DISPLAY_LCD1_SUPPORT: result_device_id.device_type = DEVICE_TYPE_LCD; @@ -1812,10 +1814,77 @@ static enum bp_result get_integrated_info_v11( info_v11->extdispconninfo.path[i].hpdlut_index; info->ext_disp_conn_info.path[i].channel_mapping.raw = info_v11->extdispconninfo.path[i].channelmapping; + info->ext_disp_conn_info.path[i].caps = + le16_to_cpu(info_v11->extdispconninfo.path[i].caps); } info->ext_disp_conn_info.checksum = info_v11->extdispconninfo.checksum; + info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr; + info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum; + for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) { + info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index = + info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; + info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val = + info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal; + } + info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum; + for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) { + info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index = + info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; + info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val = + info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; + } + + info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr; + info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum; + for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) { + info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index = + info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; + info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val = + info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal; + } + info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum; + for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) { + info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index = + info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; + info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val = + info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; + } + + info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr; + info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum; + for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) { + info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index = + info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; + info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val = + info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal; + } + info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum; + for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) { + info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index = + info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; + info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val = + info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; + } + + info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr; + info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum; + for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) { + info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index = + info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; + info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val = + info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal; + } + info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum; + for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) { + info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index = + info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; + info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val = + info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal; + } + + /** TODO - review **/ #if 0 info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 1888bf4d2c3f..d77f0de0f2bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1044,10 +1044,17 @@ static bool construct( &info.ext_disp_conn_info.path[i]; if (path->device_connector_id.enum_id == link->link_id.enum_id && path->device_connector_id.id == link->link_id.id - && path->device_connector_id.type == link->link_id.type - && path->device_acpi_enum - == link->device_tag.acpi_device) { - link->ddi_channel_mapping = path->channel_mapping; + && path->device_connector_id.type == link->link_id.type) { + + if (link->device_tag.acpi_device != 0 + && path->device_acpi_enum == link->device_tag.acpi_device) { + link->ddi_channel_mapping = path->channel_mapping; + link->chip_caps = path->caps; + } else if (path->device_tag == + link->device_tag.dev_id.raw_device_tag) { + link->ddi_channel_mapping = path->channel_mapping; + link->chip_caps = path->caps; + } break; } } @@ -1263,11 +1270,416 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) return enable_link_dp(pipe_ctx); } +static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, + enum engine_id eng_id, + struct ext_hdmi_settings *settings) +{ + bool result = false; + int i = 0; + struct integrated_info *integrated_info = + pipe_ctx->stream->ctx->dc_bios->integrated_info; + + if (integrated_info == NULL) + return false; + + /* + * Get retimer settings from sbios for passing SI eye test for DCE11 + * The setting values are varied based on board revision and port id + * Therefore the setting values of each ports is passed by sbios. + */ + + // Check if current bios contains ext Hdmi settings + if (integrated_info->gpu_cap_info & 0x20) { + switch (eng_id) { + case ENGINE_ID_DIGA: + settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp0_ext_hdmi_reg_settings, + sizeof(integrated_info->dp0_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp0_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings)); + result = true; + break; + case ENGINE_ID_DIGB: + settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp1_ext_hdmi_reg_settings, + sizeof(integrated_info->dp1_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp1_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings)); + result = true; + break; + case ENGINE_ID_DIGC: + settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp2_ext_hdmi_reg_settings, + sizeof(integrated_info->dp2_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp2_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); + result = true; + break; + + default: + break; + } + + if (result == true) { + // Validate settings from bios integrated info table + if (settings->slv_addr == 0) + return false; + if (settings->reg_num > 9) + return false; + if (settings->reg_num_6g > 3) + return false; + + for (i = 0; i < settings->reg_num; i++) { + if (settings->reg_settings[i].i2c_reg_index > 0x20) + return false; + } + + for (i = 0; i < settings->reg_num_6g; i++) { + if (settings->reg_settings_6g[i].i2c_reg_index > 0x20) + return false; + } + } + } + + return result; +} + +static bool i2c_write(struct pipe_ctx *pipe_ctx, + uint8_t address, uint8_t *buffer, uint32_t length) +{ + struct i2c_command cmd = {0}; + struct i2c_payload payload = {0}; + + memset(&payload, 0, sizeof(payload)); + memset(&cmd, 0, sizeof(cmd)); + + cmd.number_of_payloads = 1; + cmd.engine = I2C_COMMAND_ENGINE_DEFAULT; + cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz; + + payload.address = address; + payload.data = buffer; + payload.length = length; + payload.write = true; + cmd.payloads = &payload; + + if (dc_submit_i2c(pipe_ctx->stream->ctx->dc, + pipe_ctx->stream->sink->link->link_index, &cmd)) + return true; + + return false; +} + +static void write_i2c_retimer_setting( + struct pipe_ctx *pipe_ctx, + bool is_vga_mode, + bool is_over_340mhz, + struct ext_hdmi_settings *settings) +{ + uint8_t slave_address = (settings->slv_addr >> 1); + uint8_t buffer[2]; + const uint8_t apply_rx_tx_change = 0x4; + uint8_t offset = 0xA; + uint8_t value = 0; + int i = 0; + bool i2c_success = false; + + memset(&buffer, 0, sizeof(buffer)); + + /* Start Ext-Hdmi programming*/ + + for (i = 0; i < settings->reg_num; i++) { + /* Apply 3G settings */ + if (settings->reg_settings[i].i2c_reg_index <= 0x20) { + + buffer[0] = settings->reg_settings[i].i2c_reg_index; + buffer[1] = settings->reg_settings[i].i2c_reg_val; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A + * needs to be set to 1 on every 0xA-0xC write. + */ + if (settings->reg_settings[i].i2c_reg_index == 0xA || + settings->reg_settings[i].i2c_reg_index == 0xB || + settings->reg_settings[i].i2c_reg_index == 0xC) { + + /* Query current value from offset 0xA */ + if (settings->reg_settings[i].i2c_reg_index == 0xA) + value = settings->reg_settings[i].i2c_reg_val; + else { + i2c_success = + dal_ddc_service_query_ddc_data( + pipe_ctx->stream->sink->link->ddc, + slave_address, &offset, 1, &value, 1); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } + + buffer[0] = offset; + /* Set APPLY_RX_TX_CHANGE bit to 1 */ + buffer[1] = value | apply_rx_tx_change; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } + } + } + + /* Apply 3G settings */ + if (is_over_340mhz) { + for (i = 0; i < settings->reg_num_6g; i++) { + /* Apply 3G settings */ + if (settings->reg_settings[i].i2c_reg_index <= 0x20) { + + buffer[0] = settings->reg_settings_6g[i].i2c_reg_index; + buffer[1] = settings->reg_settings_6g[i].i2c_reg_val; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A + * needs to be set to 1 on every 0xA-0xC write. + */ + if (settings->reg_settings_6g[i].i2c_reg_index == 0xA || + settings->reg_settings_6g[i].i2c_reg_index == 0xB || + settings->reg_settings_6g[i].i2c_reg_index == 0xC) { + + /* Query current value from offset 0xA */ + if (settings->reg_settings_6g[i].i2c_reg_index == 0xA) + value = settings->reg_settings_6g[i].i2c_reg_val; + else { + i2c_success = + dal_ddc_service_query_ddc_data( + pipe_ctx->stream->sink->link->ddc, + slave_address, &offset, 1, &value, 1); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } + + buffer[0] = offset; + /* Set APPLY_RX_TX_CHANGE bit to 1 */ + buffer[1] = value | apply_rx_tx_change; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } + } + } + } + + if (is_vga_mode) { + /* Program additional settings if using 640x480 resolution */ + + /* Write offset 0xFF to 0x01 */ + buffer[0] = 0xff; + buffer[1] = 0x01; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x00 to 0x23 */ + buffer[0] = 0x00; + buffer[1] = 0x23; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0xff to 0x00 */ + buffer[0] = 0xff; + buffer[1] = 0x00; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + } +} + +static void write_i2c_default_retimer_setting( + struct pipe_ctx *pipe_ctx, + bool is_vga_mode, + bool is_over_340mhz) +{ + uint8_t slave_address = (0xBA >> 1); + uint8_t buffer[2]; + bool i2c_success = false; + + memset(&buffer, 0, sizeof(buffer)); + + /* Program Slave Address for tuning single integrity */ + /* Write offset 0x0A to 0x13 */ + buffer[0] = 0x0A; + buffer[1] = 0x13; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0A to 0x17 */ + buffer[0] = 0x0A; + buffer[1] = 0x17; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0B to 0xDA or 0xD8 */ + buffer[0] = 0x0B; + buffer[1] = is_over_340mhz ? 0xDA : 0xD8; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0A to 0x17 */ + buffer[0] = 0x0A; + buffer[1] = 0x17; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0C to 0x1D or 0x91 */ + buffer[0] = 0x0C; + buffer[1] = is_over_340mhz ? 0x1D : 0x91; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x0A to 0x17 */ + buffer[0] = 0x0A; + buffer[1] = 0x17; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + + if (is_vga_mode) { + /* Program additional settings if using 640x480 resolution */ + + /* Write offset 0xFF to 0x01 */ + buffer[0] = 0xff; + buffer[1] = 0x01; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0x00 to 0x23 */ + buffer[0] = 0x00; + buffer[1] = 0x23; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + + /* Write offset 0xff to 0x00 */ + buffer[0] = 0xff; + buffer[1] = 0x00; + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); + } +} + +static void write_i2c_redriver_setting( + struct pipe_ctx *pipe_ctx, + bool is_over_340mhz) +{ + uint8_t slave_address = (0xF0 >> 1); + uint8_t buffer[16]; + bool i2c_success = false; + + memset(&buffer, 0, sizeof(buffer)); + + // Program Slave Address for tuning single integrity + buffer[3] = 0x4E; + buffer[4] = 0x4E; + buffer[5] = 0x4E; + buffer[6] = is_over_340mhz ? 0x4E : 0x4A; + + i2c_success = i2c_write(pipe_ctx, slave_address, + buffer, sizeof(buffer)); + + if (!i2c_success) + /* Write failure */ + ASSERT(i2c_success); +} + static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; enum dc_color_depth display_color_depth; + enum engine_id eng_id; + struct ext_hdmi_settings settings = {0}; + bool is_over_340mhz = false; + bool is_vga_mode = (stream->timing.h_addressable == 640) + && (stream->timing.v_addressable == 480); + + if (stream->phy_pix_clk > 340000) + is_over_340mhz = true; + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { + if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x2) { + /* DP159, Retimer settings */ + eng_id = pipe_ctx->stream_res.stream_enc->id; + + if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) { + write_i2c_retimer_setting(pipe_ctx, + is_vga_mode, is_over_340mhz, &settings); + } else { + write_i2c_default_retimer_setting(pipe_ctx, + is_vga_mode, is_over_340mhz); + } + } else if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x1) { + /* PI3EQX1204, Redriver settings */ + write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); + } + } if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) dal_ddc_service_write_scdc_data( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1210fdd48c56..629aa3c323ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -815,6 +815,7 @@ struct dc_link { union ddi_channel_mapping ddi_channel_mapping; struct connector_device_tag_info device_tag; struct dpcd_caps dpcd_caps; + unsigned short chip_caps; unsigned int dpcd_sink_count; enum edp_revision edp_revision; diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 39010325cef9..ab88f07772a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -96,11 +96,6 @@ bool dm_helpers_submit_i2c( const struct dc_link *link, struct i2c_command *cmd); - - - - - enum dc_edid_status dm_helpers_read_local_edid( struct dc_context *ctx, struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index 6cdbf84f34e6..92fe00fab87c 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -65,6 +65,7 @@ enum dal_device_type { struct device_id { enum dal_device_type device_type:16; uint32_t enum_id:16; /* 1 based enum */ + uint16_t raw_device_tag; }; struct graphics_object_i2c_info { @@ -264,6 +265,20 @@ struct transmitter_configuration { #define NUMBER_OF_DISP_CLK_VOLTAGE 4 #define NUMBER_OF_AVAILABLE_SCLK 5 +struct i2c_reg_info { + unsigned char i2c_reg_index; + unsigned char i2c_reg_val; +}; + +struct ext_hdmi_settings { + unsigned char slv_addr; + unsigned char reg_num; + struct i2c_reg_info reg_settings[9]; + unsigned char reg_num_6g; + struct i2c_reg_info reg_settings_6g[3]; +}; + + /* V6 */ struct integrated_info { struct clock_voltage_caps { @@ -291,6 +306,8 @@ struct integrated_info { struct graphics_object_id ext_encoder_obj_id; /* XBAR mapping of the PHY channels */ union ddi_channel_mapping channel_mapping; + + unsigned short caps; } path[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID]; @@ -357,6 +374,27 @@ struct integrated_info { uint32_t lvds_pwr_off_seq_blon_to_vary_bl_in_4ms; uint32_t lvds_reserved1; uint32_t lvds_bit_depth_control_val; + //Start from V9 + unsigned char dp0_ext_hdmi_slv_addr; + unsigned char dp0_ext_hdmi_reg_num; + struct i2c_reg_info dp0_ext_hdmi_reg_settings[9]; + unsigned char dp0_ext_hdmi_6g_reg_num; + struct i2c_reg_info dp0_ext_hdmi_6g_reg_settings[3]; + unsigned char dp1_ext_hdmi_slv_addr; + unsigned char dp1_ext_hdmi_reg_num; + struct i2c_reg_info dp1_ext_hdmi_reg_settings[9]; + unsigned char dp1_ext_hdmi_6g_reg_num; + struct i2c_reg_info dp1_ext_hdmi_6g_reg_settings[3]; + unsigned char dp2_ext_hdmi_slv_addr; + unsigned char dp2_ext_hdmi_reg_num; + struct i2c_reg_info dp2_ext_hdmi_reg_settings[9]; + unsigned char dp2_ext_hdmi_6g_reg_num; + struct i2c_reg_info dp2_ext_hdmi_6g_reg_settings[3]; + unsigned char dp3_ext_hdmi_slv_addr; + unsigned char dp3_ext_hdmi_reg_num; + struct i2c_reg_info dp3_ext_hdmi_reg_settings[9]; + unsigned char dp3_ext_hdmi_6g_reg_num; + struct i2c_reg_info dp3_ext_hdmi_6g_reg_settings[3]; }; /** -- GitLab From a185048ca88ce143f980f2b819f034cfc09a5377 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 13 Aug 2017 13:50:52 -0400 Subject: [PATCH 0794/2898] drm/amd/display: refactor pplib/smu communication new per SoC interface instead legacy interface with lots of un-used field that only cause confusion model pp_smu like one of our HW objects with func_ptr interface to call into it. struct pp_smu as handle to call pp/smu Signed-off-by: Tony Cheng Reviewed-by: Jun Lei Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/amdgpu_dm/amdgpu_dm_services.c | 13 +- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 100 ++++++------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 19 ++- drivers/gpu/drm/amd/display/dc/dm_pp_smu.h | 131 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dm_services.h | 5 +- .../drm/amd/display/dc/dm_services_types.h | 2 + .../gpu/drm/amd/display/dc/inc/core_types.h | 2 + drivers/gpu/drm/amd/display/dc/inc/resource.h | 1 + 8 files changed, 213 insertions(+), 60 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dm_pp_smu.h diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 3348e90a0a37..aefd9ebc7bce 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -401,14 +401,6 @@ bool dm_pp_notify_wm_clock_changes( return false; } -bool dm_pp_notify_wm_clock_changes_soc15( - const struct dc_context *ctx, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges) -{ - /* TODO: to be implemented */ - return false; -} - bool dm_pp_apply_power_level_change_request( const struct dc_context *ctx, struct dm_pp_power_level_change_request *level_change_req) @@ -433,4 +425,9 @@ bool dm_pp_get_static_clocks( return false; } +void dm_pp_get_funcs_rv( + struct dc_context *ctx, + struct pp_smu_funcs_rv *funcs) +{} + /**** end of power component interfaces ****/ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index f0dfd3c3c12c..afd403ceb2a7 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1311,12 +1311,16 @@ void dcn_bw_update_from_pplib(struct dc *dc) void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) { - struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0}; + struct pp_smu_funcs_rv *pp = dc->res_pool->pp_smu; + struct pp_smu_wm_range_sets ranges = {0}; int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz; const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); + if (!pp->set_wm_ranges) + return; + kernel_fpu_begin(); max_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor; nom_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor; @@ -1336,55 +1340,55 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) /* SOCCLK does not affect anytihng but writeback for DCN so for now we dont * care what the value is, hence min to overdrive level */ - clk_ranges.num_wm_dmif_sets = 4; - clk_ranges.num_wm_mcif_sets = 4; - clk_ranges.wm_dmif_clocks_ranges[0].wm_set_id = WM_SET_A; - clk_ranges.wm_dmif_clocks_ranges[0].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[0].wm_set_id = WM_SET_A; - clk_ranges.wm_mcif_clocks_ranges[0].wm_min_socclk_clk_in_khz = socclk_khz; - clk_ranges.wm_mcif_clocks_ranges[0].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz; - - clk_ranges.wm_dmif_clocks_ranges[1].wm_set_id = WM_SET_B; - clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[1].wm_set_id = WM_SET_B; - clk_ranges.wm_mcif_clocks_ranges[1].wm_min_socclk_clk_in_khz = socclk_khz; - clk_ranges.wm_mcif_clocks_ranges[1].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz; - - - clk_ranges.wm_dmif_clocks_ranges[2].wm_set_id = WM_SET_C; - clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[2].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[2].wm_set_id = WM_SET_C; - clk_ranges.wm_mcif_clocks_ranges[2].wm_min_socclk_clk_in_khz = socclk_khz; - clk_ranges.wm_mcif_clocks_ranges[2].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz; - - clk_ranges.wm_dmif_clocks_ranges[3].wm_set_id = WM_SET_D; - clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = min_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz; - clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz; - clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[3].wm_set_id = WM_SET_D; - clk_ranges.wm_mcif_clocks_ranges[3].wm_min_socclk_clk_in_khz = socclk_khz; - clk_ranges.wm_mcif_clocks_ranges[3].wm_max_socclk_clk_in_khz = overdrive; - clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz; - clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz; + ranges.num_reader_wm_sets = WM_COUNT; + ranges.num_writer_wm_sets = WM_COUNT; + ranges.reader_wm_sets[0].wm_inst = WM_A; + ranges.reader_wm_sets[0].min_drain_clk_khz = min_dcfclk_khz; + ranges.reader_wm_sets[0].max_drain_clk_khz = max_dcfclk_khz; + ranges.reader_wm_sets[0].min_fill_clk_khz = min_fclk_khz; + ranges.reader_wm_sets[0].max_fill_clk_khz = min_fclk_khz; + ranges.writer_wm_sets[0].wm_inst = WM_A; + ranges.writer_wm_sets[0].min_fill_clk_khz = socclk_khz; + ranges.writer_wm_sets[0].max_fill_clk_khz = overdrive; + ranges.writer_wm_sets[0].min_drain_clk_khz = min_fclk_khz; + ranges.writer_wm_sets[0].max_drain_clk_khz = min_fclk_khz; + + ranges.reader_wm_sets[1].wm_inst = WM_B; + ranges.reader_wm_sets[1].min_drain_clk_khz = min_fclk_khz; + ranges.reader_wm_sets[1].max_drain_clk_khz = max_dcfclk_khz; + ranges.reader_wm_sets[1].min_fill_clk_khz = mid_fclk_khz; + ranges.reader_wm_sets[1].max_fill_clk_khz = mid_fclk_khz; + ranges.writer_wm_sets[1].wm_inst = WM_B; + ranges.writer_wm_sets[1].min_fill_clk_khz = socclk_khz; + ranges.writer_wm_sets[1].max_fill_clk_khz = overdrive; + ranges.writer_wm_sets[1].min_drain_clk_khz = mid_fclk_khz; + ranges.writer_wm_sets[1].max_drain_clk_khz = mid_fclk_khz; + + + ranges.reader_wm_sets[2].wm_inst = WM_C; + ranges.reader_wm_sets[2].min_drain_clk_khz = min_fclk_khz; + ranges.reader_wm_sets[2].max_drain_clk_khz = max_dcfclk_khz; + ranges.reader_wm_sets[2].min_fill_clk_khz = nom_fclk_khz; + ranges.reader_wm_sets[2].max_fill_clk_khz = nom_fclk_khz; + ranges.writer_wm_sets[2].wm_inst = WM_C; + ranges.writer_wm_sets[2].min_fill_clk_khz = socclk_khz; + ranges.writer_wm_sets[2].max_fill_clk_khz = overdrive; + ranges.writer_wm_sets[2].min_drain_clk_khz = nom_fclk_khz; + ranges.writer_wm_sets[2].max_drain_clk_khz = nom_fclk_khz; + + ranges.reader_wm_sets[3].wm_inst = WM_D; + ranges.reader_wm_sets[3].min_drain_clk_khz = min_fclk_khz; + ranges.reader_wm_sets[3].max_drain_clk_khz = max_dcfclk_khz; + ranges.reader_wm_sets[3].min_fill_clk_khz = max_fclk_khz; + ranges.reader_wm_sets[3].max_fill_clk_khz = max_fclk_khz; + ranges.writer_wm_sets[3].wm_inst = WM_D; + ranges.writer_wm_sets[3].min_fill_clk_khz = socclk_khz; + ranges.writer_wm_sets[3].max_fill_clk_khz = overdrive; + ranges.writer_wm_sets[3].min_drain_clk_khz = max_fclk_khz; + ranges.writer_wm_sets[3].max_drain_clk_khz = max_fclk_khz; /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ - dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges); + pp->set_wm_ranges(&pp->pp_smu, &ranges); } void dcn_bw_sync_calcs_and_dml(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 2d9e88f08abb..954c234090db 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -678,6 +678,17 @@ void dcn10_clock_source_destroy(struct clock_source **clk_src) *clk_src = NULL; } +static struct pp_smu_funcs_rv *dcn10_pp_smu_create(struct dc_context *ctx) +{ + struct pp_smu_funcs_rv *pp_smu = dm_alloc(sizeof(*pp_smu)); + + if (!pp_smu) + return pp_smu; + + dm_pp_get_funcs_rv(ctx, pp_smu); + return pp_smu; +} + static void destruct(struct dcn10_resource_pool *pool) { unsigned int i; @@ -751,6 +762,8 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.display_clock != NULL) dce_disp_clk_destroy(&pool->base.display_clock); + + dm_free(pool->base.pp_smu); } static struct mem_input *dcn10_mem_input_create( @@ -1347,11 +1360,15 @@ static bool construct( } } + pool->base.pp_smu = dcn10_pp_smu_create(ctx); + if (!dc->debug.disable_pplib_clock_request) dcn_bw_update_from_pplib(dc); dcn_bw_sync_calcs_and_dml(dc); - if (!dc->debug.disable_pplib_wm_range) + if (!dc->debug.disable_pplib_wm_range) { + dc->res_pool = &pool->base; dcn_bw_notify_pplib_of_wm_ranges(dc); + } { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) diff --git a/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h new file mode 100644 index 000000000000..bbfa83252fc1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h @@ -0,0 +1,131 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DM_PP_SMU_IF__H +#define DM_PP_SMU_IF__H + +/* + * interface to PPLIB/SMU to setup clocks and pstate requirements on SoC + */ + + +struct pp_smu { + struct dc_context *ctx; +}; + +enum wm_set_id { + WM_A, + WM_B, + WM_C, + WM_D, + WM_COUNT, +}; + +struct pp_smu_wm_set_range { + enum wm_set_id wm_inst; + uint32_t min_fill_clk_khz; + uint32_t max_fill_clk_khz; + uint32_t min_drain_clk_khz; + uint32_t max_drain_clk_khz; +}; + +struct pp_smu_wm_range_sets { + uint32_t num_reader_wm_sets; + struct pp_smu_wm_set_range reader_wm_sets[WM_COUNT]; + + uint32_t num_writer_wm_sets; + struct pp_smu_wm_set_range writer_wm_sets[WM_COUNT]; +}; + +struct pp_smu_display_requirement_rv { + /* PPSMC_MSG_SetDisplayCount: count + * 0 triggers S0i2 optimization + */ + unsigned int display_count; + + /* PPSMC_MSG_SetHardMinFclkByFreq: khz + * FCLK will vary with DPM, but never below requested hard min + */ + unsigned int hard_min_fclk_khz; + + /* PPSMC_MSG_SetHardMinDcefclkByFreq: khz + * fixed clock at requested freq, either from FCH bypass or DFS + */ + unsigned int hard_min_dcefclk_khz; + + /* PPSMC_MSG_SetMinDeepSleepDcefclk: mhz + * when DF is in cstate, dcf clock is further divided down + * to just above given frequency + */ + unsigned int min_deep_sleep_dcefclk_mhz; +}; + +struct pp_smu_funcs_rv { + struct pp_smu pp_smu; + + void (*set_display_requirement)(struct pp_smu *pp, + struct pp_smu_display_requirement_rv *req); + + /* which SMU message? are reader and writer WM separate SMU msg? */ + void (*set_wm_ranges)(struct pp_smu *pp, + struct pp_smu_wm_range_sets *ranges); + +}; + +#if 0 +struct pp_smu_funcs_rv { + + /* PPSMC_MSG_SetDisplayCount + * 0 triggers S0i2 optimization + */ + void (*set_display_count)(struct pp_smu *pp, int count); + + /* PPSMC_MSG_SetHardMinFclkByFreq + * FCLK will vary with DPM, but never below requested hard min + */ + void (*set_hard_min_fclk_by_freq)(struct pp_smu *pp, int khz); + + /* PPSMC_MSG_SetHardMinDcefclkByFreq + * fixed clock at requested freq, either from FCH bypass or DFS + */ + void (*set_hard_min_dcefclk_by_freq)(struct pp_smu *pp, int khz); + + /* PPSMC_MSG_SetMinDeepSleepDcefclk + * when DF is in cstate, dcf clock is further divided down + * to just above given frequency + */ + void (*set_min_deep_sleep_dcefclk)(struct pp_smu *pp, int mhz); + + /* todo: aesthetic + * watermark range table + */ + + /* todo: functional/feature + * PPSMC_MSG_SetHardMinSocclkByFreq: required to support DWB + */ +}; +#endif + +#endif /* DM_PP_SMU_IF__H */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index e9bf4c417cc7..8ab0af6f4c6b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -339,9 +339,8 @@ bool dm_pp_notify_wm_clock_changes( const struct dc_context *ctx, struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges); -bool dm_pp_notify_wm_clock_changes_soc15( - const struct dc_context *ctx, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); +void dm_pp_get_funcs_rv(struct dc_context *ctx, + struct pp_smu_funcs_rv *funcs); /* DAL calls this function to notify PP about completion of Mode Set. * For PP it means that current DCE clocks are those which were returned diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h index 4c04ec587308..fa26cf488b3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h @@ -29,6 +29,8 @@ #include "os_types.h" #include "dc_types.h" +#include "dm_pp_smu.h" + struct dm_pp_clock_range { int min_khz; int max_khz; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index f8ade552c595..a3f0039088ab 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -48,6 +48,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, #include "clock_source.h" #include "audio.h" #include "hw_sequencer_types.h" +#include "dm_pp_smu.h" /************ link *****************/ @@ -126,6 +127,7 @@ struct resource_pool { struct stream_encoder *stream_enc[MAX_PIPES * 2]; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct mpc *mpc; + struct pp_smu_funcs_rv *pp_smu; #endif struct dwbc *dwbc[MAX_DWB_PIPES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 13218a52e2fa..9085ec7ceac7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -28,6 +28,7 @@ #include "core_types.h" #include "core_status.h" #include "dal_asic_id.h" +#include "dm_pp_smu.h" /* TODO unhardcode, 4 for CZ*/ #define MEMORY_TYPE_MULTIPLIER 4 -- GitLab From 1dc904974eb7deef924650adc5af542878ce2040 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 31 Jul 2017 11:29:25 -0400 Subject: [PATCH 0795/2898] drm/amd/display: Per stream validate_context build v2. Until now new context would start as empty, then populated with exsisting pipes + new. Now we start with duplication of existing context and then add/delete from the context pipes as needed. This allows to do a per stream resource population, start discarding dc_validation_set and by this brings DC closer to to DRM. v2: Add some fixes and rebase. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 68 ++- drivers/gpu/drm/amd/display/dc/core/dc.c | 108 +--- .../gpu/drm/amd/display/dc/core/dc_resource.c | 468 ++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 32 +- .../amd/display/dc/dce100/dce100_resource.c | 78 +-- .../amd/display/dc/dce110/dce110_resource.c | 86 +--- .../amd/display/dc/dce112/dce112_resource.c | 143 ++---- .../amd/display/dc/dce112/dce112_resource.h | 5 + .../amd/display/dc/dce120/dce120_resource.c | 4 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 79 +-- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 85 +--- .../gpu/drm/amd/display/dc/inc/core_types.h | 19 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 6 +- 13 files changed, 577 insertions(+), 604 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d28de04efa42..17e9bf7a2ebb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -25,6 +25,7 @@ #include "dm_services_types.h" #include "dc.h" +#include "dc/inc/core_types.h" #include "vid.h" #include "amdgpu.h" @@ -690,13 +691,33 @@ struct drm_atomic_state * dm_atomic_state_alloc(struct drm_device *dev) { struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); + struct validate_context *new_ctx; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; - if (!state || drm_atomic_state_init(dev, &state->base) < 0) { - kfree(state); + if (!state) return NULL; - } + + if (drm_atomic_state_init(dev, &state->base) < 0) + goto fail; + + /* copy existing configuration */ + new_ctx = dm_alloc(sizeof(*new_ctx)); + + if (!new_ctx) + goto fail; + + atomic_inc(&new_ctx->ref_count); + + dc_resource_validate_ctx_copy_construct_current(dc, new_ctx); + + state->context = new_ctx; return &state->base; + +fail: + kfree(state); + return NULL; } static void @@ -4418,7 +4439,6 @@ static int do_aquire_global_lock( int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { - struct dm_atomic_state *dm_state; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; struct drm_plane *plane; @@ -4432,6 +4452,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, int set_count; struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); /* * This bool will be set for true for any modeset/reset @@ -4446,8 +4467,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, return ret; } - dm_state = to_dm_atomic_state(state); - /* copy existing configuration */ set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -4490,8 +4509,17 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (modereset_required(crtc_state)) { - /* i.e. reset mode */ + /* i.e. reset mode */ if (new_acrtc_state->stream) { + + if (!dc_remove_stream_from_ctx( + dc, + dm_state->context, + new_acrtc_state->stream)) { + ret = -EINVAL; + goto fail; + } + set_count = remove_from_val_sets( set, set_count, @@ -4539,8 +4567,19 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (modeset_required(crtc_state, new_stream, old_acrtc_state->stream)) { - if (new_acrtc_state->stream) + if (new_acrtc_state->stream) { + + if (!dc_remove_stream_from_ctx( + dc, + dm_state->context, + new_acrtc_state->stream)) { + ret = -EINVAL; + goto fail; + } + + dc_stream_release(new_acrtc_state->stream); + } new_acrtc_state->stream = new_stream; @@ -4551,6 +4590,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_acrtc_state->stream, crtc); + if (!dc_add_stream_to_ctx( + dc, + dm_state->context, + new_acrtc_state->stream)) { + ret = -EINVAL; + goto fail; + } + lock_and_validation_needed = true; } else { /* @@ -4667,9 +4714,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ret = do_aquire_global_lock(dev, state); if (ret) goto fail; - WARN_ON(dm_state->context); - dm_state->context = dc_get_validate_context(dc, set, set_count); - if (!dm_state->context) { + + if (!dc_validate_global_state(dc, set, set_count, dm_state->context)) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 44c7b52e4a00..10126d9a7233 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -669,41 +669,6 @@ void dc_destroy(struct dc **dc) *dc = NULL; } -static bool is_validation_required( - const struct dc *dc, - const struct dc_validation_set set[], - int set_count) -{ - const struct validate_context *context = dc->current_context; - int i, j; - - if (context->stream_count != set_count) - return true; - - for (i = 0; i < set_count; i++) { - - if (set[i].plane_count != context->stream_status[i].plane_count) - return true; - if (!dc_is_stream_unchanged(set[i].stream, context->streams[i])) - return true; - - for (j = 0; j < set[i].plane_count; j++) { - struct dc_plane_state temp_plane; - memset(&temp_plane, 0, sizeof(temp_plane)); - - temp_plane = *context->stream_status[i].plane_states[j]; - temp_plane.clip_rect = set[i].plane_states[j]->clip_rect; - temp_plane.dst_rect.x = set[i].plane_states[j]->dst_rect.x; - temp_plane.dst_rect.y = set[i].plane_states[j]->dst_rect.y; - - if (memcmp(&temp_plane, set[i].plane_states[j], sizeof(temp_plane)) != 0) - return true; - } - } - - return false; -} - static bool validate_streams ( struct dc *dc, const struct dc_validation_set set[], @@ -733,52 +698,12 @@ static bool validate_surfaces( return true; } -struct validate_context *dc_get_validate_context( - struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count) -{ - struct dc *core_dc = dc; - enum dc_status result = DC_ERROR_UNEXPECTED; - struct validate_context *context; - - - context = dm_alloc(sizeof(struct validate_context)); - if (context == NULL) - goto context_alloc_fail; - - atomic_inc(&context->ref_count); - - if (!is_validation_required(core_dc, set, set_count)) { - dc_resource_validate_ctx_copy_construct(core_dc->current_context, context); - return context; - } - - result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, set_count, context, core_dc->current_context); - -context_alloc_fail: - if (result != DC_OK) { - dm_logger_write(core_dc->ctx->logger, LOG_WARNING, - "%s:resource validation failed, dc_status:%d\n", - __func__, - result); - - dc_release_validate_context(context); - context = NULL; - } - - return context; - -} - bool dc_validate_resources( struct dc *dc, const struct dc_validation_set set[], uint8_t set_count) { - struct dc *core_dc = dc; - enum dc_status result = DC_ERROR_UNEXPECTED; + bool result = false; struct validate_context *context; if (!validate_streams(dc, set, set_count)) @@ -793,21 +718,16 @@ bool dc_validate_resources( atomic_inc(&context->ref_count); - result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, set_count, context, NULL); + dc_resource_validate_ctx_copy_construct_current(dc, context); -context_alloc_fail: - if (result != DC_OK) { - dm_logger_write(core_dc->ctx->logger, LOG_WARNING, - "%s:resource validation failed, dc_status:%d\n", - __func__, - result); - } + result = dc_validate_with_context( + dc, set, set_count, context); +context_alloc_fail: dc_release_validate_context(context); context = NULL; - return result == DC_OK; + return result; } bool dc_validate_guaranteed( @@ -1093,7 +1013,7 @@ bool dc_commit_streams( uint8_t stream_count) { struct dc *core_dc = dc; - enum dc_status result = DC_ERROR_UNEXPECTED; + bool result = false; struct validate_context *context; struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; int i; @@ -1135,13 +1055,11 @@ bool dc_commit_streams( atomic_inc(&context->ref_count); - result = core_dc->res_pool->funcs->validate_with_context( - core_dc, set, stream_count, context, core_dc->current_context); - if (result != DC_OK){ - dm_logger_write(core_dc->ctx->logger, LOG_ERROR, - "%s: Context validation failed! dc_status:%d\n", - __func__, - result); + dc_resource_validate_ctx_copy_construct_current(dc, context); + + result = dc_validate_with_context( + dc, set, stream_count, context); + if (!result) { BREAK_TO_DEBUGGER(); goto fail; } @@ -1152,7 +1070,7 @@ bool dc_commit_streams( dc_release_validate_context(context); context_alloc_fail: - return (result == DC_OK); + return result; } bool dc_post_update_surfaces_to_stream(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2b357318f945..f640986c6fd2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -938,7 +938,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( int i; for (i = 0; i < MAX_PIPES; i++) { if (res_ctx->pipe_ctx[i].stream == stream && - res_ctx->pipe_ctx[i].stream_res.stream_enc) { + !res_ctx->pipe_ctx[i].top_pipe) { return &res_ctx->pipe_ctx[i]; break; } @@ -1217,29 +1217,31 @@ bool resource_validate_attach_surfaces( #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 -static void set_stream_engine_in_use( +static void update_stream_engine_usage( struct resource_context *res_ctx, const struct resource_pool *pool, - struct stream_encoder *stream_enc) + struct stream_encoder *stream_enc, + bool acquired) { int i; for (i = 0; i < pool->stream_enc_count; i++) { if (pool->stream_enc[i] == stream_enc) - res_ctx->is_stream_enc_acquired[i] = true; + res_ctx->is_stream_enc_acquired[i] = acquired; } } /* TODO: release audio object */ -static void set_audio_in_use( +static void update_audio_usage( struct resource_context *res_ctx, const struct resource_pool *pool, - struct audio *audio) + struct audio *audio, + bool acquired) { int i; for (i = 0; i < pool->audio_count; i++) { if (pool->audios[i] == audio) - res_ctx->is_audio_acquired[i] = true; + res_ctx->is_audio_acquired[i] = acquired; } } @@ -1361,6 +1363,100 @@ bool resource_is_stream_unchanged( return false; } +bool dc_add_stream_to_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream) +{ + struct dc_context *dc_ctx = dc->ctx; + enum dc_status res; + + if (new_ctx->stream_count >= dc->res_pool->pipe_count) { + DC_ERROR("Max streams reached, can add stream %p !\n", stream); + return DC_ERROR_UNEXPECTED; + } + + new_ctx->streams[new_ctx->stream_count] = stream; + dc_stream_retain(stream); + new_ctx->stream_count++; + + res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); + if (res != DC_OK) + DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res); + + return res == DC_OK; +} + +bool dc_remove_stream_from_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream) +{ + int i, j; + struct dc_context *dc_ctx = dc->ctx; + struct pipe_ctx *del_pipe = NULL; + + /*TODO MPO to remove extra pipe or in surface remove ?*/ + + /* Release primary and secondary pipe (if exsist) */ + for (i = 0; i < MAX_PIPES; i++) { + if (new_ctx->res_ctx.pipe_ctx[i].stream == stream) { + del_pipe = &new_ctx->res_ctx.pipe_ctx[i]; + + if (del_pipe->stream_res.stream_enc) + update_stream_engine_usage( + &new_ctx->res_ctx, + dc->res_pool, + del_pipe->stream_res.stream_enc, + false); + + if (del_pipe->stream_res.audio) + update_audio_usage( + &new_ctx->res_ctx, + dc->res_pool, + del_pipe->stream_res.audio, + false); + + memset(del_pipe, 0, sizeof(*del_pipe)); + } + } + + if (!del_pipe) { + DC_ERROR("Pipe not found for stream %p !\n", stream); + return DC_ERROR_UNEXPECTED; + } + + for (i = 0; i < new_ctx->stream_count; i++) + if (new_ctx->streams[i] == stream) + break; + + if (new_ctx->streams[i] != stream) { + DC_ERROR("Context doesn't have stream %p !\n", stream); + return DC_ERROR_UNEXPECTED; + } + + dc_stream_release(new_ctx->streams[i]); + new_ctx->stream_count--; + + /*TODO move into dc_remove_surface_from_ctx ?*/ + for (j = 0; j < new_ctx->stream_status[i].plane_count; j++) + dc_plane_state_release(new_ctx->stream_status[i].plane_states[j]); + + /* Trim back arrays */ + for (; i < new_ctx->stream_count; i++) { + new_ctx->streams[i] = new_ctx->streams[i + 1]; + new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; + } + + new_ctx->streams[new_ctx->stream_count] = NULL; + memset( + &new_ctx->stream_status[new_ctx->stream_count], + 0, + sizeof(new_ctx->stream_status[0])); + + return DC_OK; +} + static void copy_pipe_ctx( const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx) { @@ -1440,15 +1536,16 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) enum dc_status resource_map_pool_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { const struct resource_pool *pool = dc->res_pool; - int i, j; - - for (i = 0; old_context && i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + int i; + struct dc_context *dc_ctx = dc->ctx; + struct pipe_ctx *pipe_ctx = NULL; + int pipe_idx = -1; - if (!resource_is_stream_unchanged(old_context, stream)) { + /* TODO Check if this is needed */ + /*if (!resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { stream->bit_depth_params = old_context->streams[i]->bit_depth_params; @@ -1456,119 +1553,228 @@ enum dc_status resource_map_pool_resources( continue; } } + */ - /* mark resources used for stream that is already active */ - for (j = 0; j < pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - const struct pipe_ctx *old_pipe_ctx = - &old_context->res_ctx.pipe_ctx[j]; - - if (!are_stream_backends_same(old_pipe_ctx->stream, stream)) - continue; + /* acquire new resources */ + pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); - if (old_pipe_ctx->top_pipe) - continue; +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (pipe_idx < 0) + acquire_first_split_pipe(&context->res_ctx, pool, stream); +#endif + if (pipe_idx < 0) + return DC_NO_CONTROLLER_RESOURCE; + + pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + pipe_ctx->stream_res.stream_enc = + find_first_free_match_stream_enc_for_link( + &context->res_ctx, pool, stream); + + if (!pipe_ctx->stream_res.stream_enc) + return DC_NO_STREAM_ENG_RESOURCE; + + update_stream_engine_usage( + &context->res_ctx, pool, + pipe_ctx->stream_res.stream_enc, + true); + + /* TODO: Add check if ASIC support and EDID audio */ + if (!stream->sink->converter_disable_audio && + dc_is_audio_capable_signal(pipe_ctx->stream->signal) && + stream->audio_info.mode_count) { + pipe_ctx->stream_res.audio = find_first_free_audio( + &context->res_ctx, pool); + + /* + * Audio assigned in order first come first get. + * There are asics which has number of audio + * resources less then number of pipes + */ + if (pipe_ctx->stream_res.audio) + update_audio_usage(&context->res_ctx, pool, + pipe_ctx->stream_res.audio, true); + } - pipe_ctx->stream = stream; - copy_pipe_ctx(old_pipe_ctx, pipe_ctx); + for (i = 0; i < context->stream_count; i++) + if (context->streams[i] == stream) { + context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; + return DC_OK; + } - /* Split pipe resource, do not acquire back end */ - if (!pipe_ctx->stream_res.stream_enc) - continue; + DC_ERROR("Stream %p not found in new ctx!\n", stream); + return DC_ERROR_UNEXPECTED; +} - set_stream_engine_in_use( - &context->res_ctx, pool, - pipe_ctx->stream_res.stream_enc); +/* first stream in the context is used to populate the rest */ +void validate_guaranteed_copy_streams( + struct validate_context *context, + int max_streams) +{ + int i; - /* Switch to dp clock source only if there is - * no non dp stream that shares the same timing - * with the dp stream. - */ - if (dc_is_dp_signal(pipe_ctx->stream->signal) && - !find_pll_sharable_stream(stream, context)) - pipe_ctx->clock_source = pool->dp_clock_source; + for (i = 1; i < max_streams; i++) { + context->streams[i] = context->streams[0]; - resource_reference_clock_source( - &context->res_ctx, pool, - pipe_ctx->clock_source); + copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], + &context->res_ctx.pipe_ctx[i]); + context->res_ctx.pipe_ctx[i].stream = + context->res_ctx.pipe_ctx[0].stream; - set_audio_in_use(&context->res_ctx, pool, - pipe_ctx->stream_res.audio); - } + dc_stream_retain(context->streams[i]); + context->stream_count++; } +} - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - struct pipe_ctx *pipe_ctx = NULL; - int pipe_idx = -1; +void dc_resource_validate_ctx_copy_construct_current( + const struct dc *dc, + struct validate_context *dst_ctx) +{ + dc_resource_validate_ctx_copy_construct(dc->current_context, dst_ctx); +} - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - /* acquire new resources */ - pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (pipe_idx < 0) - acquire_first_split_pipe(&context->res_ctx, pool, stream); -#endif - if (pipe_idx < 0) - return DC_NO_CONTROLLER_RESOURCE; +bool dc_validate_with_context( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + int i, j; + enum dc_status res = DC_ERROR_UNEXPECTED; + bool found = false; + int old_stream_count = context->stream_count; + struct dc_stream_state *del_streams[MAX_PIPES] = { 0 }; + struct dc_stream_state *add_streams[MAX_PIPES] = { 0 }; + int del_streams_count = 0; + int add_streams_count = 0; - pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; - pipe_ctx->stream_res.stream_enc = - find_first_free_match_stream_enc_for_link( - &context->res_ctx, pool, stream); + /* First remove from context all deleted streams */ + for (i = 0; i < old_stream_count; i++) { + struct dc_stream_state *stream = context->streams[i]; + + for (j = 0; j < set_count; j++) { + if (stream == set[j].stream) { + found = true; + break; + } + } - if (!pipe_ctx->stream_res.stream_enc) - return DC_NO_STREAM_ENG_RESOURCE; + if (!found) + del_streams[del_streams_count++] = stream; - set_stream_engine_in_use( - &context->res_ctx, pool, - pipe_ctx->stream_res.stream_enc); + found = false; + } - /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->converter_disable_audio && - dc_is_audio_capable_signal(pipe_ctx->stream->signal) && - stream->audio_info.mode_count) { - pipe_ctx->stream_res.audio = find_first_free_audio( - &context->res_ctx, pool); + /* Now add new ones */ + for (i = 0; i < set_count; i++) { + struct dc_stream_state *stream = set[i].stream; - /* - * Audio assigned in order first come first get. - * There are asics which has number of audio - * resources less then number of pipes - */ - if (pipe_ctx->stream_res.audio) - set_audio_in_use( - &context->res_ctx, pool, - pipe_ctx->stream_res.audio); + for (j = 0; j < old_stream_count; j++) { + if (stream == context->streams[j]) { + found = true; + break; + } } - context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; + if (!found) + add_streams[add_streams_count++] = stream; + + found = false; } - return DC_OK; + for (i = 0; i < del_streams_count; i++) + if (!dc_remove_stream_from_ctx(dc, context, del_streams[i])) + goto fail; + + for (i = 0; i < add_streams_count; i++) + if (!dc_add_stream_to_ctx(dc, context, add_streams[i])) + goto fail; + + if (!dc_validate_global_state(dc, set, set_count, context)) + goto fail; + + res = DC_OK; + +fail: + if (res != DC_OK) { + dm_logger_write(dc->ctx->logger, LOG_WARNING, + "%s:resource validation failed, dc_status:%d\n", + __func__, + res); +} + return res == DC_OK; } -/* first stream in the context is used to populate the rest */ -void validate_guaranteed_copy_streams( - struct validate_context *context, - int max_streams) +bool dc_validate_global_state( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *new_ctx) { - int i; + enum dc_status result = DC_ERROR_UNEXPECTED; + struct dc_context *dc_ctx = dc->ctx; + struct validate_context *old_context = dc->current_context; + int i, j; - for (i = 1; i < max_streams; i++) { - context->streams[i] = context->streams[0]; + if (dc->res_pool->funcs->validate_global && + dc->res_pool->funcs->validate_global(dc, set, set_count, + old_context, new_ctx) != DC_OK) + return false; - copy_pipe_ctx(&context->res_ctx.pipe_ctx[0], - &context->res_ctx.pipe_ctx[i]); - context->res_ctx.pipe_ctx[i].stream = - context->res_ctx.pipe_ctx[0].stream; + /* TODO without this SWDEV-114774 brakes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; - dc_stream_retain(context->streams[i]); - context->stream_count++; + if (pipe_ctx->top_pipe) + memset(pipe_ctx, 0, sizeof(*pipe_ctx)); + } + + for (i = 0; new_ctx && i < new_ctx->stream_count; i++) { + struct dc_stream_state *stream = new_ctx->streams[i]; + + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->stream != stream) + continue; + + /* Switch to dp clock source only if there is + * no non dp stream that shares the same timing + * with the dp stream. + */ + if (dc_is_dp_signal(pipe_ctx->stream->signal) && + !find_pll_sharable_stream(stream, new_ctx)) { + + resource_unreference_clock_source( + &new_ctx->res_ctx, + dc->res_pool, + &pipe_ctx->clock_source); + pipe_ctx->clock_source = dc->res_pool->dp_clock_source; + resource_reference_clock_source( + &new_ctx->res_ctx, + dc->res_pool, + pipe_ctx->clock_source); + } + } + } + + /*TODO This should be ok */ + /* Split pipe resource, do not acquire back end */ + + if (!resource_validate_attach_surfaces( + set, set_count, old_context, new_ctx, dc->res_pool)) { + DC_ERROR("Failed to attach surface to stream!\n"); + return DC_FAIL_ATTACH_SURFACES; } + + result = resource_build_scaling_params_for_context(dc, new_ctx); + + if (result == DC_OK) + if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx)) + result = DC_FAIL_BANDWIDTH_VALIDATE; + + return result; } static void patch_gamut_packet_checksum( @@ -2318,54 +2524,40 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) enum dc_status resource_map_clock_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { - int i, j; - const struct resource_pool *pool = dc->res_pool; - /* acquire new resources */ - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; + const struct resource_pool *pool = dc->res_pool; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( + &context->res_ctx, stream); - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = pool->dp_clock_source; + else { + pipe_ctx->clock_source = NULL; - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) - pipe_ctx->clock_source = pool->dp_clock_source; - else { - pipe_ctx->clock_source = NULL; - - if (!dc->config.disable_disp_pll_sharing) - resource_find_used_clk_src_for_sharing( - &context->res_ctx, - pipe_ctx); - - if (pipe_ctx->clock_source == NULL) - pipe_ctx->clock_source = - dc_resource_find_first_free_pll( - &context->res_ctx, - pool); - } + if (!dc->config.disable_disp_pll_sharing) + resource_find_used_clk_src_for_sharing( + &context->res_ctx, + pipe_ctx); - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; + if (pipe_ctx->clock_source == NULL) + pipe_ctx->clock_source = + dc_resource_find_first_free_pll( + &context->res_ctx, + pool); + } - resource_reference_clock_source( - &context->res_ctx, pool, - pipe_ctx->clock_source); + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; - /* only one cs per stream regardless of mpo */ - break; - } - } + resource_reference_clock_source( + &context->res_ctx, pool, + pipe_ctx->clock_source); return DC_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 629aa3c323ca..2b4fc6616243 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -618,6 +618,16 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *h_position, uint32_t *v_position); +bool dc_remove_stream_from_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream); + +bool dc_add_stream_to_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream); + /* * Structure to store surface/stream associations for validation */ @@ -630,16 +640,18 @@ struct dc_validation_set { bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); -/* - * This function takes a set of resources and checks that they are cofunctional. - * - * After this call: - * No hardware is programmed for call. Only validation is done. - */ -struct validate_context *dc_get_validate_context( + +bool dc_validate_with_context( struct dc *dc, const struct dc_validation_set set[], - uint8_t set_count); + int set_count, + struct validate_context *context); + +bool dc_validate_global_state( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *new_ctx); bool dc_validate_resources( struct dc *dc, @@ -662,6 +674,10 @@ void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, struct validate_context *dst_ctx); +void dc_resource_validate_ctx_copy_construct_current( + const struct dc *dc, + struct validate_context *dst_ctx); + void dc_resource_validate_ctx_destruct(struct validate_context *context); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index b2b03633eb4f..c9dad4e2a7c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -654,35 +654,20 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; - - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); - - /* do not need to validate non root pipes */ - break; - } - } + resource_build_info_frame(pipe_ctx); return DC_OK; } @@ -719,48 +704,17 @@ static bool dce100_validate_surface_sets( return true; } -enum dc_status dce100_validate_with_context( +enum dc_status dce100_validate_global( struct dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *old_context, + struct validate_context *context) { - struct dc_context *dc_ctx = dc->ctx; - enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - if (!dce100_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); - - if (result == DC_OK) - result = resource_map_clock_resources(dc, context, old_context); - - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } - - if (result == DC_OK) - result = build_mapped_resource(dc, context, old_context); - - if (result == DC_OK) - result = resource_build_scaling_params_for_context(dc, context); - - if (result == DC_OK) - if (!dce100_validate_bandwidth(dc, context)) - result = DC_FAIL_BANDWIDTH_VALIDATE; - - return result; + return DC_OK; } enum dc_status dce100_validate_guaranteed( @@ -774,13 +728,13 @@ enum dc_status dce100_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, dc_stream); if (result == DC_OK) - result = resource_map_clock_resources(dc, context, NULL); + result = resource_map_clock_resources(dc, context, dc_stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, dc_stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -816,10 +770,10 @@ enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state) static const struct resource_funcs dce100_res_pool_funcs = { .destroy = dce100_destroy_resource_pool, .link_enc_create = dce100_link_encoder_create, - .validate_with_context = dce100_validate_with_context, .validate_guaranteed = dce100_validate_guaranteed, .validate_bandwidth = dce100_validate_bandwidth, .validate_plane = dce100_validate_plane, + .validate_global = dce100_validate_global }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 2154c2e567f2..d682180f2eaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -774,41 +774,26 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; - - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + if (!is_surface_pixel_format_supported(pipe_ctx, + dc->res_pool->underlay_pipe_index)) + return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - if (!is_surface_pixel_format_supported(pipe_ctx, - dc->res_pool->underlay_pipe_index)) - return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + if (status != DC_OK) + return status; - if (status != DC_OK) - return status; + /* TODO: validate audio ASIC caps, encoder */ - /* TODO: validate audio ASIC caps, encoder */ - - resource_build_info_frame(pipe_ctx); - - /* do not need to validate non root pipes */ - break; - } - } + resource_build_info_frame(pipe_ctx); return DC_OK; } @@ -927,48 +912,17 @@ static bool dce110_validate_surface_sets( return true; } -static enum dc_status dce110_validate_with_context( +enum dc_status dce110_validate_global( struct dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *old_context, + struct validate_context *context) { - struct dc_context *dc_ctx = dc->ctx; - enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - if (!dce110_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); - - if (result == DC_OK) - result = resource_map_clock_resources(dc, context, old_context); - - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } - - if (result == DC_OK) - result = build_mapped_resource(dc, context, old_context); - - if (result == DC_OK) - result = resource_build_scaling_params_for_context(dc, context); - - if (result == DC_OK) - if (!dce110_validate_bandwidth(dc, context)) - result = DC_FAIL_BANDWIDTH_VALIDATE; - - return result; + return DC_OK; } static enum dc_status dce110_validate_guaranteed( @@ -982,13 +936,13 @@ static enum dc_status dce110_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, dc_stream); if (result == DC_OK) - result = resource_map_clock_resources(dc, context, NULL); + result = resource_map_clock_resources(dc, context, dc_stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, dc_stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -1078,10 +1032,10 @@ static void dce110_destroy_resource_pool(struct resource_pool **pool) static const struct resource_funcs dce110_res_pool_funcs = { .destroy = dce110_destroy_resource_pool, .link_enc_create = dce110_link_encoder_create, - .validate_with_context = dce110_validate_with_context, .validate_guaranteed = dce110_validate_guaranteed, .validate_bandwidth = dce110_validate_bandwidth, .acquire_idle_pipe_for_layer = dce110_acquire_underlay, + .validate_global = dce110_validate_global }; static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 89a8dfa68c01..85a396ef5aa5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -725,35 +725,20 @@ static struct clock_source *find_matching_pll( static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + if (status != DC_OK) + return status; - if (status != DC_OK) - return status; - - resource_build_info_frame(pipe_ctx); - - /* do not need to validate non root pipes */ - break; - } - } + resource_build_info_frame(pipe_ctx); return DC_OK; } @@ -839,45 +824,32 @@ bool dce112_validate_bandwidth( enum dc_status resource_map_phy_clock_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { - uint8_t i, j; /* acquire new resources */ - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( + &context->res_ctx, stream); - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) - pipe_ctx->clock_source = - dc->res_pool->dp_clock_source; - else - pipe_ctx->clock_source = find_matching_pll( - &context->res_ctx, dc->res_pool, - stream); + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) + pipe_ctx->clock_source = + dc->res_pool->dp_clock_source; + else + pipe_ctx->clock_source = find_matching_pll( + &context->res_ctx, dc->res_pool, + stream); - resource_reference_clock_source( - &context->res_ctx, - dc->res_pool, - pipe_ctx->clock_source); + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; - /* only one cs per stream regardless of mpo */ - break; - } - } + resource_reference_clock_source( + &context->res_ctx, + dc->res_pool, + pipe_ctx->clock_source); return DC_OK; } @@ -903,46 +875,21 @@ static bool dce112_validate_surface_sets( return true; } -enum dc_status dce112_validate_with_context( +enum dc_status dce112_add_stream_to_ctx( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *new_ctx, + struct dc_stream_state *dc_stream) { - struct dc_context *dc_ctx = dc->ctx; enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - if (!dce112_validate_surface_sets(set, set_count)) - return DC_FAIL_SURFACE_VALIDATE; - - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); + result = resource_map_pool_resources(dc, new_ctx, dc_stream); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context, old_context); - - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } + result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); - if (result == DC_OK) - result = build_mapped_resource(dc, context, old_context); if (result == DC_OK) - result = resource_build_scaling_params_for_context(dc, context); - - if (result == DC_OK) - if (!dce112_validate_bandwidth(dc, context)) - result = DC_FAIL_BANDWIDTH_VALIDATE; + result = build_mapped_resource(dc, new_ctx, dc_stream); return result; } @@ -958,13 +905,13 @@ enum dc_status dce112_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, stream); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context, NULL); + result = resource_map_phy_clock_resources(dc, context, stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -979,6 +926,19 @@ enum dc_status dce112_validate_guaranteed( return result; } +enum dc_status dce112_validate_global( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *old_context, + struct validate_context *context) +{ + if (!dce112_validate_surface_sets(set, set_count)) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + static void dce112_destroy_resource_pool(struct resource_pool **pool) { struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); @@ -991,10 +951,11 @@ static void dce112_destroy_resource_pool(struct resource_pool **pool) static const struct resource_funcs dce112_res_pool_funcs = { .destroy = dce112_destroy_resource_pool, .link_enc_create = dce112_link_encoder_create, - .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, - .validate_plane = dce100_validate_plane + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce112_add_stream_to_ctx, + .validate_global = dce112_validate_global }; static void bw_calcs_data_update_from_pplib(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index 69f8f689196d..f1834bfe3d1e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -51,6 +51,11 @@ bool dce112_validate_bandwidth( struct dc *dc, struct validate_context *context); +enum dc_status dce112_add_stream_to_ctx( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *dc_stream); + #endif /* __DC_RESOURCE_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index b8fcdff40db3..e5d2d98982f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -698,10 +698,10 @@ static void dce120_destroy_resource_pool(struct resource_pool **pool) static const struct resource_funcs dce120_res_pool_funcs = { .destroy = dce120_destroy_resource_pool, .link_enc_create = dce120_link_encoder_create, - .validate_with_context = dce112_validate_with_context, .validate_guaranteed = dce112_validate_guaranteed, .validate_bandwidth = dce112_validate_bandwidth, - .validate_plane = dce100_validate_plane + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce112_add_stream_to_ctx }; static void bw_calcs_data_update_from_pplib(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 838bfdaee009..ac3f42a44030 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -686,35 +686,20 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (old_context && resource_is_stream_unchanged(old_context, stream)) - continue; - - for (j = 0; j < MAX_PIPES; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; - - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; - - status = dce110_resource_build_pipe_hw_param(pipe_ctx); + status = dce110_resource_build_pipe_hw_param(pipe_ctx); - if (status != DC_OK) - return status; + if (status != DC_OK) + return status; - resource_build_info_frame(pipe_ctx); - - /* do not need to validate non root pipes */ - break; - } - } + resource_build_info_frame(pipe_ctx); return DC_OK; } @@ -751,47 +736,17 @@ static bool dce80_validate_surface_sets( return true; } -enum dc_status dce80_validate_with_context( +enum dc_status dce80_validate_global( struct dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *old_context, + struct validate_context *context) { - struct dc_context *dc_ctx = dc->ctx; - enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - if (!dce80_validate_surface_sets(set, set_count)) return DC_FAIL_SURFACE_VALIDATE; - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); - - if (result == DC_OK) - result = resource_map_clock_resources(dc, context, old_context); - - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } - - if (result == DC_OK) - result = build_mapped_resource(dc, context, old_context); - - if (result == DC_OK) - result = resource_build_scaling_params_for_context(dc, context); - - if (result == DC_OK) - result = dce80_validate_bandwidth(dc, context); - - return result; + return DC_OK; } enum dc_status dce80_validate_guaranteed( @@ -805,13 +760,13 @@ enum dc_status dce80_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, dc_stream); if (result == DC_OK) - result = resource_map_clock_resources(dc, context, NULL); + result = resource_map_clock_resources(dc, context, dc_stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, dc_stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -837,10 +792,10 @@ static void dce80_destroy_resource_pool(struct resource_pool **pool) static const struct resource_funcs dce80_res_pool_funcs = { .destroy = dce80_destroy_resource_pool, .link_enc_create = dce80_link_encoder_create, - .validate_with_context = dce80_validate_with_context, .validate_guaranteed = dce80_validate_guaranteed, .validate_bandwidth = dce80_validate_bandwidth, - .validate_plane = dce100_validate_plane + .validate_plane = dce100_validate_plane, + .validate_global = dce80_validate_global }; static bool dce80_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 954c234090db..ee43cbc70c8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -48,6 +48,7 @@ #include "dce/dce_hwseq.h" #include "../virtual/virtual_stream_encoder.h" #include "dce110/dce110_resource.h" +#include "dce112/dce112_resource.h" #include "vega10/soc15ip.h" @@ -840,17 +841,15 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) static enum dc_status build_mapped_resource( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context) + struct dc_stream_state *stream) { enum dc_status status = DC_OK; - uint8_t i, j; - - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; + struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - if (old_context && resource_is_stream_unchanged(old_context, stream)) { + /*TODO Seems unneeded anymore */ + /* if (old_context && resource_is_stream_unchanged(old_context, stream)) { if (stream != NULL && old_context->streams[i] != NULL) { - /* todo: shouldn't have to copy missing parameter here */ + todo: shouldn't have to copy missing parameter here resource_build_bit_depth_reduction_params(stream, &stream->bit_depth_params); stream->clamping.pixel_encoding = @@ -863,68 +862,34 @@ static enum dc_status build_mapped_resource( continue; } } + */ - for (j = 0; j < dc->res_pool->pipe_count ; j++) { - struct pipe_ctx *pipe_ctx = - &context->res_ctx.pipe_ctx[j]; + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; - if (context->res_ctx.pipe_ctx[j].stream != stream) - continue; + status = build_pipe_hw_param(pipe_ctx); - status = build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; - - /* do not need to validate non root pipes */ - break; - } - } + if (status != DC_OK) + return status; return DC_OK; } -enum dc_status dcn10_validate_with_context( +enum dc_status dcn10_add_stream_to_ctx( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context, - struct validate_context *old_context) + struct validate_context *new_ctx, + struct dc_stream_state *dc_stream) { - enum dc_status result = DC_OK; - int i; - - if (set_count == 0) - return result; - - for (i = 0; i < set_count; i++) { - context->streams[i] = set[i].stream; - dc_stream_retain(context->streams[i]); - context->stream_count++; - } - - result = resource_map_pool_resources(dc, context, old_context); - if (result != DC_OK) - return result; - - result = resource_map_phy_clock_resources(dc, context, old_context); - if (result != DC_OK) - return result; + enum dc_status result = DC_ERROR_UNEXPECTED; - result = build_mapped_resource(dc, context, old_context); - if (result != DC_OK) - return result; + result = resource_map_pool_resources(dc, new_ctx, dc_stream); - if (!resource_validate_attach_surfaces(set, set_count, - old_context, context, dc->res_pool)) - return DC_FAIL_ATTACH_SURFACES; + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); - result = resource_build_scaling_params_for_context(dc, context); - if (result != DC_OK) - return result; - if (!dcn_validate_bandwidth(dc, context)) - return DC_FAIL_BANDWIDTH_VALIDATE; + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); return result; } @@ -940,13 +905,13 @@ enum dc_status dcn10_validate_guaranteed( dc_stream_retain(context->streams[0]); context->stream_count++; - result = resource_map_pool_resources(dc, context, NULL); + result = resource_map_pool_resources(dc, context, dc_stream); if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, context, NULL); + result = resource_map_phy_clock_resources(dc, context, dc_stream); if (result == DC_OK) - result = build_mapped_resource(dc, context, NULL); + result = build_mapped_resource(dc, context, dc_stream); if (result == DC_OK) { validate_guaranteed_copy_streams( @@ -1226,10 +1191,10 @@ static struct dc_cap_funcs cap_funcs = { static struct resource_funcs dcn10_res_pool_funcs = { .destroy = dcn10_destroy_resource_pool, .link_enc_create = dcn10_link_encoder_create, - .validate_with_context = dcn10_validate_with_context, .validate_guaranteed = dcn10_validate_guaranteed, .validate_bandwidth = dcn_validate_bandwidth, .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, + .add_stream_to_ctx = dcn10_add_stream_to_ctx }; static bool construct( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index a3f0039088ab..9a3239028377 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -87,12 +87,6 @@ struct resource_funcs { void (*destroy)(struct resource_pool **pool); struct link_encoder *(*link_enc_create)( const struct encoder_init_data *init); - enum dc_status (*validate_with_context)( - struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context, - struct validate_context *old_context); enum dc_status (*validate_guaranteed)( struct dc *dc, @@ -103,11 +97,24 @@ struct resource_funcs { struct dc *dc, struct validate_context *context); + enum dc_status (*validate_global)( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct validate_context *old_context, + struct validate_context *context); + struct pipe_ctx *(*acquire_idle_pipe_for_layer)( struct validate_context *context, const struct resource_pool *pool, struct dc_stream_state *stream); + enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); + + enum dc_status (*add_stream_to_ctx)( + struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *dc_stream); }; struct audio_support{ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 9085ec7ceac7..ebc0f5b02365 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -82,7 +82,7 @@ void dc_destroy_resource_pool(struct dc *dc); enum dc_status resource_map_pool_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context); + struct dc_stream_state *stream); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); @@ -150,12 +150,12 @@ void resource_validate_ctx_update_pointer_after_copy( enum dc_status resource_map_clock_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context); + struct dc_stream_state *stream); enum dc_status resource_map_phy_clock_resources( const struct dc *dc, struct validate_context *context, - struct validate_context *old_context); + struct dc_stream_state *stream); bool pipe_need_reprogram( struct pipe_ctx *pipe_ctx_old, -- GitLab From 81c90ec0348002b6f6b0c108e3e60e666cb4b673 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 7 Sep 2017 16:46:34 -0400 Subject: [PATCH 0796/2898] drm/amd/display: Refactor dc_state creation into a function. For less repetition and easy debugging. Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +--- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 +++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 17e9bf7a2ebb..776bd4a1fecc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -702,13 +702,11 @@ dm_atomic_state_alloc(struct drm_device *dev) goto fail; /* copy existing configuration */ - new_ctx = dm_alloc(sizeof(*new_ctx)); + new_ctx = dc_create_state(); if (!new_ctx) goto fail; - atomic_inc(&new_ctx->ref_count); - dc_resource_validate_ctx_copy_construct_current(dc, new_ctx); state->context = new_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 10126d9a7233..8a6bd2917799 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -497,15 +497,13 @@ static bool construct(struct dc *dc, goto fail; } - dc->current_context = dm_alloc(sizeof(*dc->current_context)); + dc->current_context = dc_create_state(); if (!dc->current_context) { dm_error("%s: failed to create validate ctx\n", __func__); goto fail; } - atomic_inc(&dc->current_context->ref_count); - dc_ctx->cgs_device = init_params->cgs_device; dc_ctx->driver_context = init_params->driver; dc_ctx->dc = dc; @@ -1162,6 +1160,17 @@ bool dc_commit_planes_to_stream( return true; } +struct validate_context *dc_create_state(void) +{ + struct validate_context *context = dm_alloc(sizeof(struct validate_context)); + + if (!context) + return NULL; + + atomic_inc(&context->ref_count); + return context; +} + void dc_retain_validate_context(struct validate_context *context) { ASSERT(atomic_read(&context->ref_count) > 0); @@ -1442,12 +1451,10 @@ void dc_update_planes_and_stream(struct dc *dc, new_planes[i] = srf_updates[i].surface; /* initialize scratch memory for building context */ - context = dm_alloc(sizeof(*context)); + context = dc_create_state(); if (context == NULL) goto context_alloc_fail; - atomic_inc(&context->ref_count); - dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2b4fc6616243..928d2a0501eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -732,6 +732,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( const struct dc_stream_status *stream_status); +struct validate_context *dc_create_state(void); void dc_retain_validate_context(struct validate_context *context); void dc_release_validate_context(struct validate_context *context); -- GitLab From d4d4a64574ab546811d29a21366afe6bb6cdb264 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 21 Sep 2017 16:13:00 -0400 Subject: [PATCH 0797/2898] drm/amd/display: Move copy_construct from state_alloc to atomic_check. Previously atomic_check assumed that dc_state is allocated and filled in. This is not the case when we hit EDEADLK and have to backup and retry. We could change atomic_state_clear but that revealed some other problems. For now let's create and construct dc_state in atomic_check. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 776bd4a1fecc..4bb78f76acce 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -691,9 +691,6 @@ struct drm_atomic_state * dm_atomic_state_alloc(struct drm_device *dev) { struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); - struct validate_context *new_ctx; - struct amdgpu_device *adev = dev->dev_private; - struct dc *dc = adev->dm.dc; if (!state) return NULL; @@ -701,16 +698,6 @@ dm_atomic_state_alloc(struct drm_device *dev) if (drm_atomic_state_init(dev, &state->base) < 0) goto fail; - /* copy existing configuration */ - new_ctx = dc_create_state(); - - if (!new_ctx) - goto fail; - - dc_resource_validate_ctx_copy_construct_current(dc, new_ctx); - - state->context = new_ctx; - return &state->base; fail: @@ -4465,6 +4452,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, return ret; } + dm_state->context = dc_create_state(); + ASSERT(dm_state->context); + dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); + /* copy existing configuration */ set_count = 0; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -- GitLab From 42f8ffa1081a7bf430107587757a1e1b02dfcdf8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 15 Sep 2017 14:07:30 -0400 Subject: [PATCH 0798/2898] drm/amd/display: Enable Vega by default. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index add0032977f3..3c0885ed5db7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1988,16 +1988,16 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) case CHIP_POLARIS12: case CHIP_TONGA: case CHIP_FIJI: - case CHIP_VEGA10: #if defined(CONFIG_DRM_AMD_DC_PRE_VEGA) return amdgpu_dc != 0; #endif case CHIP_KABINI: case CHIP_MULLINS: return amdgpu_dc > 0; -#endif -#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_DCN1_0) + case CHIP_VEGA10: +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) case CHIP_RAVEN: +#endif return amdgpu_dc != 0; #endif default: -- GitLab From 1bd4653a29a49f6fd732cd294e0f87b15feec5a8 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 16 Aug 2017 19:06:49 -0400 Subject: [PATCH 0799/2898] drm/amd/display: increase polling interval for fbc status update 1.Fixing error message: "wait counter exceeded, changes to HW not applied" 2. Added "FBC status changed to 0/1" logs Signed-off-by: Roman Li Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 9759d8e790a3..2e97e5757fb9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -115,7 +115,7 @@ static void wait_for_fbc_state_changed( FBC_STATUS, FBC_ENABLE_STATUS) == enabled) break; - udelay(10); + msleep(10); counter++; } @@ -124,7 +124,13 @@ static void wait_for_fbc_state_changed( cp110->base.ctx->logger, LOG_WARNING, "%s: wait counter exceeded, changes to HW not applied", __func__); + } else { + dm_logger_write( + cp110->base.ctx->logger, LOG_SYNC, + "FBC status changed to %d", enabled); } + + } void dce110_compressor_power_up_fbc(struct compressor *compressor) -- GitLab From b05dee52efdcb6286a28be4dddeb450b58591c6d Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 16 Aug 2017 20:25:42 -0400 Subject: [PATCH 0800/2898] drm/amd/display: fix not enter/exit PSR with latest driver/SBIOS Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 3 ++- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d77f0de0f2bf..cab54afa1131 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1975,7 +1975,7 @@ bool dc_link_setup_psr(struct dc_link *link, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) /*skip power down the single pipe since it blocks the cstate*/ if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) - psr_context->psr_level.bits.SKIP_SINGLE_OTG_DISABLE = true; + psr_context->psr_level.bits.SKIP_SINGLE_OTG_DISABLE = false; #endif /* SMU will perform additional powerdown sequence. diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 9d67340a6b8b..06d9a3e7c8a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -417,9 +417,10 @@ static int dce112_set_clock( bp->funcs->set_dce_clock(bp, &dce_clk_params); - if (abm->funcs->is_dmcu_initialized(abm)) + if (abm->funcs->is_dmcu_initialized(abm) && clk_dce->dfs_bypass_disp_clk != actual_clock) dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7); + clk_dce->dfs_bypass_disp_clk = actual_clock; return actual_clock; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 92902f011418..efcdb2bf4d0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -260,6 +260,8 @@ static void dce_psr_wait_loop( { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; + if (cached_wait_loop_number == wait_loop_number) + return; /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); @@ -500,7 +502,7 @@ static void dcn10_psr_wait_loop( { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); union dce_dmcu_psr_config_data_wait_loop_reg1 masterCmdData1; - + if (wait_loop_number != 0) { /* waitDMCUReadyForCmd */ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); @@ -514,6 +516,7 @@ static void dcn10_psr_wait_loop( /* notifyDMCUMsg */ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + } } static void dcn10_get_psr_wait_loop(unsigned int *psr_wait_loop_number) -- GitLab From 214435ff1369a9d48c194c7a75d918130c53bab2 Mon Sep 17 00:00:00 2001 From: Corbin McElhanney Date: Wed, 16 Aug 2017 11:49:07 -0400 Subject: [PATCH 0801/2898] drm/amd/display: Log OTG registers with dcn10 hw state Signed-off-by: Corbin McElhanney Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 33 +++++++++++++++ .../display/dc/dcn10/dcn10_timing_generator.c | 42 +++++++++++++++++++ .../display/dc/dcn10/dcn10_timing_generator.h | 25 +++++++++++ 3 files changed, 100 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index f0e49d16019c..ddfa6a8d087b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -32,6 +32,7 @@ #include "dce/dce_hwseq.h" #include "abm.h" #include "dcn10/dcn10_mem_input.h" +#include "dcn10/dcn10_timing_generator.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" #include "timing_generator.h" @@ -200,6 +201,38 @@ static void dcn10_log_hw_state(struct dc *dc) } DTN_INFO("\n"); + DTN_INFO("OTG:\t v_bs \t v_be \t v_ss \t v_se \t vpol \t vmax \t vmin \t " + "h_bs \t h_be \t h_ss \t h_se \t hpol \t htot \t vtot \t underflow\n"); + + for (i = 0; i < pool->pipe_count; i++) { + struct timing_generator *tg = pool->timing_generators[i]; + struct dcn_otg_state s; + + tgn10_read_otg_state(DCN10TG_FROM_TG(tg), &s); + + DTN_INFO("[%d]:\t %d \t %d \t %d \t %d \t " + "%d \t %d \t %d \t %d \t %d \t %d \t " + "%d \t %d \t %d \t %d \t %d \t ", + i, + s.v_blank_start, + s.v_blank_end, + s.v_sync_a_start, + s.v_sync_a_end, + s.v_sync_a_pol, + s.v_total_max, + s.v_total_min, + s.h_blank_start, + s.h_blank_end, + s.h_sync_a_start, + s.h_sync_a_end, + s.h_sync_a_pol, + s.h_total, + s.v_total, + s.underflow_occurred_status); + DTN_INFO("\n"); + } + DTN_INFO("\n"); + log_mpc_crc(dc); DTN_INFO_END(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 941e0125ff06..6a5f2683c2e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -1090,6 +1090,48 @@ static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) return ret; } +void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, + struct dcn_otg_state *s) +{ + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &s->v_blank_start, + OTG_V_BLANK_END, &s->v_blank_end); + + REG_GET(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, &s->v_sync_a_pol); + + REG_GET(OTG_V_TOTAL, + OTG_V_TOTAL, &s->v_total); + + REG_GET(OTG_V_TOTAL_MAX, + OTG_V_TOTAL_MAX, &s->v_total_max); + + REG_GET(OTG_V_TOTAL_MIN, + OTG_V_TOTAL_MIN, &s->v_total_min); + + REG_GET_2(OTG_V_SYNC_A, + OTG_V_SYNC_A_START, &s->v_sync_a_start, + OTG_V_SYNC_A_END, &s->v_sync_a_end); + + REG_GET_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, &s->h_blank_start, + OTG_H_BLANK_END, &s->h_blank_end); + + REG_GET_2(OTG_H_SYNC_A, + OTG_H_SYNC_A_START, &s->h_sync_a_start, + OTG_H_SYNC_A_END, &s->h_sync_a_end); + + REG_GET(OTG_H_SYNC_A_CNTL, + OTG_H_SYNC_A_POL, &s->h_sync_a_pol); + + REG_GET(OTG_H_TOTAL, + OTG_H_TOTAL, &s->h_total); + + REG_GET(OPTC_INPUT_GLOBAL_CONTROL, + OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); +} + + static struct timing_generator_funcs dcn10_tg_funcs = { .validate_timing = tgn10_validate_timing, .program_timing = tgn10_program_timing, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 747e8211e507..654889318fc1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -67,6 +67,7 @@ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ SRI(OPPBUF_CONTROL, OPPBUF, inst),\ SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ SRI(CONTROL, VTG, inst),\ @@ -121,6 +122,7 @@ struct dcn_tg_registers { uint32_t OTG_CLOCK_CONTROL; uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; + uint32_t OPTC_INPUT_GLOBAL_CONTROL; uint32_t OPPBUF_CONTROL; uint32_t OPPBUF_3D_PARAMETERS_0; uint32_t CONTROL; @@ -204,6 +206,7 @@ struct dcn_tg_registers { SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ SF(OPPBUF0_OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, mask_sh),\ SF(OPPBUF0_OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, mask_sh),\ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ @@ -310,6 +313,7 @@ struct dcn_tg_registers { type OPTC_INPUT_CLK_GATE_DIS;\ type OPTC_SRC_SEL;\ type OPTC_SEG0_SRC_SEL;\ + type OPTC_UNDERFLOW_OCCURRED_STATUS;\ type OPPBUF_ACTIVE_WIDTH;\ type OPPBUF_3D_VACT_SPACE1_SIZE;\ type VTG0_ENABLE;\ @@ -346,4 +350,25 @@ struct dcn10_timing_generator { void dcn10_timing_generator_init(struct dcn10_timing_generator *tg); +struct dcn_otg_state { + uint32_t v_blank_start; + uint32_t v_blank_end; + uint32_t v_sync_a_pol; + uint32_t v_total; + uint32_t v_total_max; + uint32_t v_total_min; + uint32_t v_sync_a_start; + uint32_t v_sync_a_end; + uint32_t h_blank_start; + uint32_t h_blank_end; + uint32_t h_sync_a_start; + uint32_t h_sync_a_end; + uint32_t h_sync_a_pol; + uint32_t h_total; + uint32_t underflow_occurred_status; +}; + +void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, + struct dcn_otg_state *s); + #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ -- GitLab From 57d972d4927581d027007c92b57b843c186128d4 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 17 Aug 2017 16:14:45 -0400 Subject: [PATCH 0802/2898] drm/amd/display: Fix FBC disable for stereo Removed FBC disable from dc_enable_stereo(). It should be implemented in stereo_setup callback, which is not implemented yet. Otherwise it always disable FBC regardless if stereo supported or not. Signed-off-by: Roman Li Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8a6bd2917799..035c44e0e7d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -881,10 +881,6 @@ bool dc_enable_stereo( struct pipe_ctx *pipe; struct dc *core_dc = dc; -#ifdef ENABLE_FBC - struct compressor *fbc_compressor = core_dc->fbc_compressor; -#endif - for (i = 0; i < MAX_PIPES; i++) { if (context != NULL) pipe = &context->res_ctx.pipe_ctx[i]; @@ -897,13 +893,6 @@ bool dc_enable_stereo( } } -#ifdef ENABLE_FBC - if (fbc_compressor != NULL && - fbc_compressor->funcs->is_fbc_enabled_in_hw(core_dc->fbc_compressor, - NULL)) - fbc_compressor->funcs->disable_fbc(fbc_compressor); - -#endif return ret; } -- GitLab From 5e9a81b2c465557adbaeef7231834e3ab40e4102 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 15 Aug 2017 17:44:19 -0400 Subject: [PATCH 0803/2898] drm/amd/display: separate scl functions out from dcn10_dpp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 3 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 650 +-------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 5 + .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 762 ++++++++++++++++++ 4 files changed, 770 insertions(+), 650 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 8af201a51a2a..83619e6b8a05 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,7 +3,8 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o + dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \ + dcn10_dpp_dscl.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index e52e1f43f67b..a841ed36c217 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -112,514 +112,6 @@ enum gamut_remap_select { GAMUT_REMAP_COMB_COEFF }; -static void dpp_set_overscan( - struct dcn10_dpp *xfm, - const struct scaler_data *data) -{ - uint32_t left = data->recout.x; - uint32_t top = data->recout.y; - - int right = data->h_active - data->recout.x - data->recout.width; - int bottom = data->v_active - data->recout.y - data->recout.height; - - if (right < 0) { - BREAK_TO_DEBUGGER(); - right = 0; - } - if (bottom < 0) { - BREAK_TO_DEBUGGER(); - bottom = 0; - } - - REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0, - EXT_OVERSCAN_LEFT, left, - EXT_OVERSCAN_RIGHT, right); - - REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0, - EXT_OVERSCAN_BOTTOM, bottom, - EXT_OVERSCAN_TOP, top); -} - -static void dpp_set_otg_blank( - struct dcn10_dpp *xfm, const struct scaler_data *data) -{ - uint32_t h_blank_start = data->h_active; - uint32_t h_blank_end = 0; - uint32_t v_blank_start = data->v_active; - uint32_t v_blank_end = 0; - - REG_SET_2(OTG_H_BLANK, 0, - OTG_H_BLANK_START, h_blank_start, - OTG_H_BLANK_END, h_blank_end); - - REG_SET_2(OTG_V_BLANK, 0, - OTG_V_BLANK_START, v_blank_start, - OTG_V_BLANK_END, v_blank_end); -} - -static enum dscl_mode_sel get_dscl_mode( - const struct scaler_data *data, bool dbg_always_scale) -{ - const long long one = dal_fixed31_32_one.value; - bool ycbcr = false; - bool format420 = false; - - if (data->format == PIXEL_FORMAT_FP16) - return DSCL_MODE_DSCL_BYPASS; - - if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && data->format <= PIXEL_FORMAT_VIDEO_END) - ycbcr = true; - - if (data->format == PIXEL_FORMAT_420BPP8 || - data->format == PIXEL_FORMAT_420BPP10) - format420 = true; - - if (data->ratios.horz.value == one - && data->ratios.vert.value == one - && data->ratios.horz_c.value == one - && data->ratios.vert_c.value == one - && !dbg_always_scale) - return DSCL_MODE_SCALING_444_BYPASS; - - if (!format420) { - if (ycbcr) - return DSCL_MODE_SCALING_444_YCBCR_ENABLE; - else - return DSCL_MODE_SCALING_444_RGB_ENABLE; - } - if (data->ratios.horz.value == one && data->ratios.vert.value == one) - return DSCL_MODE_SCALING_420_LUMA_BYPASS; - if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one) - return DSCL_MODE_SCALING_420_CHROMA_BYPASS; - - return DSCL_MODE_SCALING_420_YCBCR_ENABLE; -} - -static int get_pixel_depth_val(enum lb_pixel_depth depth) -{ - if (depth == LB_PIXEL_DEPTH_30BPP) - return 0; /* 10 bpc */ - else if (depth == LB_PIXEL_DEPTH_24BPP) - return 1; /* 8 bpc */ - else if (depth == LB_PIXEL_DEPTH_18BPP) - return 2; /* 6 bpc */ - else if (depth == LB_PIXEL_DEPTH_36BPP) - return 3; /* 12 bpc */ - else { - ASSERT(0); - return -1; /* Unsupported */ - } -} - -static void dpp_set_lb( - struct dcn10_dpp *xfm, - const struct line_buffer_params *lb_params, - enum lb_memory_config mem_size_config) -{ - uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); - uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; - REG_SET_7(LB_DATA_FORMAT, 0, - PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ - PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ - PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ - DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ - DITHER_EN, 0, /* Dithering enable: Disabled */ - INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ - ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ - - REG_SET_2(LB_MEMORY_CTRL, 0, - MEMORY_CONFIG, mem_size_config, - LB_MAX_PARTITIONS, 63); -} - -static void dpp_set_scaler_filter( - struct dcn10_dpp *xfm, - uint32_t taps, - enum dcn10_coef_filter_type_sel filter_type, - const uint16_t *filter) -{ - const int tap_pairs = (taps + 1) / 2; - int phase; - int pair; - uint16_t odd_coef, even_coef; - - REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0, - SCL_COEF_RAM_TAP_PAIR_IDX, 0, - SCL_COEF_RAM_PHASE, 0, - SCL_COEF_RAM_FILTER_TYPE, filter_type); - - for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) { - for (pair = 0; pair < tap_pairs; pair++) { - even_coef = filter[phase * taps + 2 * pair]; - if ((pair * 2 + 1) < taps) - odd_coef = filter[phase * taps + 2 * pair + 1]; - else - odd_coef = 0; - - REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, - /* Even tap coefficient (bits 1:0 fixed to 0) */ - SCL_COEF_RAM_EVEN_TAP_COEF, even_coef, - /* Write/read control for even coefficient */ - SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1, - /* Odd tap coefficient (bits 1:0 fixed to 0) */ - SCL_COEF_RAM_ODD_TAP_COEF, odd_coef, - /* Write/read control for odd coefficient */ - SCL_COEF_RAM_ODD_TAP_COEF_EN, 1); - } - } - -} - -#if 0 -bool dpp_set_pixel_storage_depth( - struct dpp *xfm, - enum lb_pixel_depth depth, - const struct bit_depth_reduction_params *bit_depth_params) -{ - struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm); - bool ret = true; - uint32_t value; - enum dc_color_depth color_depth; - - value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); - switch (depth) { - case LB_PIXEL_DEPTH_18BPP: - color_depth = COLOR_DEPTH_666; - set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_24BPP: - color_depth = COLOR_DEPTH_888; - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_30BPP: - color_depth = COLOR_DEPTH_101010; - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_36BPP: - color_depth = COLOR_DEPTH_121212; - set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - default: - ret = false; - break; - } - - if (ret == true) { - set_denormalization(xfm110, color_depth); - ret = program_bit_depth_reduction(xfm110, color_depth, - bit_depth_params); - - set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); - dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); - if (!(xfm110->lb_pixel_depth_supported & depth)) { - /* We should use unsupported capabilities - * unless it is required by w/a - */ - dm_logger_write(xfm->ctx->logger, LOG_WARNING, - "%s: Capability not supported", - __func__); - } - } - - return ret; -} -#endif - -static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) -{ - if (taps == 8) - return get_filter_8tap_64p(ratio); - else if (taps == 7) - return get_filter_7tap_64p(ratio); - else if (taps == 6) - return get_filter_6tap_64p(ratio); - else if (taps == 5) - return get_filter_5tap_64p(ratio); - else if (taps == 4) - return get_filter_4tap_64p(ratio); - else if (taps == 3) - return get_filter_3tap_64p(ratio); - else if (taps == 2) - return filter_2tap_64p; - else if (taps == 1) - return NULL; - else { - /* should never happen, bug */ - BREAK_TO_DEBUGGER(); - return NULL; - } -} - -static void dpp_set_scl_filter( - struct dcn10_dpp *xfm, - const struct scaler_data *scl_data, - bool chroma_coef_mode) -{ - bool h_2tap_hardcode_coef_en = false; - bool v_2tap_hardcode_coef_en = false; - bool h_2tap_sharp_en = false; - bool v_2tap_sharp_en = false; - uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz; - uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert; - bool coef_ram_current; - const uint16_t *filter_h = NULL; - const uint16_t *filter_v = NULL; - const uint16_t *filter_h_c = NULL; - const uint16_t *filter_v_c = NULL; - - h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 - && scl_data->taps.h_taps_c < 3 - && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); - v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 - && scl_data->taps.v_taps_c < 3 - && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); - - h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; - v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; - - REG_UPDATE_6(DSCL_2TAP_CONTROL, - SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en, - SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en, - SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor, - SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en, - SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en, - SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor); - - if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { - bool filter_updated = false; - - filter_h = get_filter_coeffs_64p( - scl_data->taps.h_taps, scl_data->ratios.horz); - filter_v = get_filter_coeffs_64p( - scl_data->taps.v_taps, scl_data->ratios.vert); - - filter_updated = (filter_h && (filter_h != xfm->filter_h)) - || (filter_v && (filter_v != xfm->filter_v)); - - if (chroma_coef_mode) { - filter_h_c = get_filter_coeffs_64p( - scl_data->taps.h_taps_c, scl_data->ratios.horz_c); - filter_v_c = get_filter_coeffs_64p( - scl_data->taps.v_taps_c, scl_data->ratios.vert_c); - filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) - || (filter_v_c && (filter_v_c != xfm->filter_v_c)); - } - - if (filter_updated) { - uint32_t scl_mode = REG_READ(SCL_MODE); - - if (!h_2tap_hardcode_coef_en && filter_h) { - dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps, - SCL_COEF_LUMA_HORZ_FILTER, filter_h); - } - xfm->filter_h = filter_h; - if (!v_2tap_hardcode_coef_en && filter_v) { - dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps, - SCL_COEF_LUMA_VERT_FILTER, filter_v); - } - xfm->filter_v = filter_v; - if (chroma_coef_mode) { - if (!h_2tap_hardcode_coef_en && filter_h_c) { - dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps_c, - SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); - } - if (!v_2tap_hardcode_coef_en && filter_v_c) { - dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps_c, - SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); - } - } - xfm->filter_h_c = filter_h_c; - xfm->filter_v_c = filter_v_c; - - coef_ram_current = get_reg_field_value_ex( - scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, - xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); - - /* Swap coefficient RAM and set chroma coefficient mode */ - REG_SET_2(SCL_MODE, scl_mode, - SCL_COEF_RAM_SELECT, !coef_ram_current, - SCL_CHROMA_COEF_MODE, chroma_coef_mode); - } - } -} - - -static int get_lb_depth_bpc(enum lb_pixel_depth depth) -{ - if (depth == LB_PIXEL_DEPTH_30BPP) - return 10; - else if (depth == LB_PIXEL_DEPTH_24BPP) - return 8; - else if (depth == LB_PIXEL_DEPTH_18BPP) - return 6; - else if (depth == LB_PIXEL_DEPTH_36BPP) - return 12; - else { - BREAK_TO_DEBUGGER(); - return -1; /* Unsupported */ - } -} - -static void calc_lb_num_partitions( - const struct scaler_data *scl_data, - enum lb_memory_config lb_config, - int *num_part_y, - int *num_part_c) -{ - int line_size = scl_data->viewport.width < scl_data->recout.width ? - scl_data->viewport.width : scl_data->recout.width; - int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? - scl_data->viewport_c.width : scl_data->recout.width; - int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); - int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ - int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ - int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ - int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; - - if (lb_config == LB_MEMORY_CONFIG_1) { - lb_memory_size = 816; - lb_memory_size_c = 816; - lb_memory_size_a = 984; - } else if (lb_config == LB_MEMORY_CONFIG_2) { - lb_memory_size = 1088; - lb_memory_size_c = 1088; - lb_memory_size_a = 1312; - } else if (lb_config == LB_MEMORY_CONFIG_3) { - lb_memory_size = 816 + 1088 + 848 + 848 + 848; - lb_memory_size_c = 816 + 1088; - lb_memory_size_a = 984 + 1312 + 456; - } else { - lb_memory_size = 816 + 1088 + 848; - lb_memory_size_c = 816 + 1088 + 848; - lb_memory_size_a = 984 + 1312 + 456; - } - *num_part_y = lb_memory_size / memory_line_size_y; - *num_part_c = lb_memory_size_c / memory_line_size_c; - num_partitions_a = lb_memory_size_a / memory_line_size_a; - - if (scl_data->lb_params.alpha_en - && (num_partitions_a < *num_part_y)) - *num_part_y = num_partitions_a; - - if (*num_part_y > 64) - *num_part_y = 64; - if (*num_part_c > 64) - *num_part_c = 64; - -} - -static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) -{ - if (ceil_vratio > 2) - return vtaps <= (num_partitions - ceil_vratio + 2); - else - return vtaps <= num_partitions; -} - -/*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) -{ - int num_part_y, num_part_c; - int vtaps = scl_data->taps.v_taps; - int vtaps_c = scl_data->taps.v_taps_c; - int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); - int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_1; - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_2; - - if (scl_data->format == PIXEL_FORMAT_420BPP8 - || scl_data->format == PIXEL_FORMAT_420BPP10) { - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); - - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) - return LB_MEMORY_CONFIG_3; - } - - calc_lb_num_partitions( - scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); - - /*Ensure we can support the requested number of vtaps*/ - ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); - - return LB_MEMORY_CONFIG_0; -} - -void dpp_set_scaler_auto_scale( - struct transform *xfm_base, - const struct scaler_data *scl_data) -{ - enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); - bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - - dpp_set_overscan(xfm, scl_data); - - dpp_set_otg_blank(xfm, scl_data); - - REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) - return; - - lb_config = find_lb_memory_config(scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); - - if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) - return; - - /* TODO: v_min */ - REG_SET_3(DSCL_AUTOCAL, 0, - AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE, - AUTOCAL_NUM_PIPE, 0, - AUTOCAL_PIPE_ID, 0); - - /* Black offsets */ - if (ycbcr) - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); - else - - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); - - REG_SET_4(SCL_TAP_CONTROL, 0, - SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, - SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, - SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, - SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - - dpp_set_scl_filter(xfm, scl_data, ycbcr); -} - /* Program gamut remap in bypass mode */ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) { @@ -628,146 +120,6 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) /* Gamut remap in bypass */ } -static void dpp_set_recout( - struct dcn10_dpp *xfm, const struct rect *recout) -{ - REG_SET_2(RECOUT_START, 0, - /* First pixel of RECOUT */ - RECOUT_START_X, recout->x, - /* First line of RECOUT */ - RECOUT_START_Y, recout->y); - - REG_SET_2(RECOUT_SIZE, 0, - /* Number of RECOUT horizontal pixels */ - RECOUT_WIDTH, recout->width, - /* Number of RECOUT vertical lines */ - RECOUT_HEIGHT, recout->height - - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * - (xfm->base.inst + 1)); -} - -static void dpp_set_manual_ratio_init( - struct dcn10_dpp *xfm, const struct scaler_data *data) -{ - uint32_t init_frac = 0; - uint32_t init_int = 0; - - REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, - SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5); - - REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, - SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5); - - REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0, - SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5); - - REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0, - SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5); - - /* - * 0.24 format for fraction, first five bits zeroed - */ - init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5; - init_int = dal_fixed31_32_floor(data->inits.h); - REG_SET_2(SCL_HORZ_FILTER_INIT, 0, - SCL_H_INIT_FRAC, init_frac, - SCL_H_INIT_INT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5; - init_int = dal_fixed31_32_floor(data->inits.h_c); - REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0, - SCL_H_INIT_FRAC_C, init_frac, - SCL_H_INIT_INT_C, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5; - init_int = dal_fixed31_32_floor(data->inits.v); - REG_SET_2(SCL_VERT_FILTER_INIT, 0, - SCL_V_INIT_FRAC, init_frac, - SCL_V_INIT_INT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, - SCL_V_INIT_FRAC_BOT, init_frac, - SCL_V_INIT_INT_BOT, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_c); - REG_SET_2(SCL_VERT_FILTER_INIT_C, 0, - SCL_V_INIT_FRAC_C, init_frac, - SCL_V_INIT_INT_C, init_int); - - init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5; - init_int = dal_fixed31_32_floor(data->inits.v_c_bot); - REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, - SCL_V_INIT_FRAC_BOT_C, init_frac, - SCL_V_INIT_INT_BOT_C, init_int); -} - -/* Main function to program scaler and line buffer in manual scaling mode */ -static void dpp_set_scaler_manual_scale( - struct transform *xfm_base, - const struct scaler_data *scl_data) -{ - enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); - bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - - /* Recout */ - dpp_set_recout(xfm, &scl_data->recout); - - /* MPC Size */ - REG_SET_2(MPC_SIZE, 0, - /* Number of horizontal pixels of MPC */ - MPC_WIDTH, scl_data->h_active, - /* Number of vertical lines of MPC */ - MPC_HEIGHT, scl_data->v_active); - - /* SCL mode */ - REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); - - if (dscl_mode == DSCL_MODE_DSCL_BYPASS) - return; - /* LB */ - lb_config = find_lb_memory_config(scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); - - if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) - return; - - /* Autocal off */ - REG_SET_3(DSCL_AUTOCAL, 0, - AUTOCAL_MODE, AUTOCAL_MODE_OFF, - AUTOCAL_NUM_PIPE, 0, - AUTOCAL_PIPE_ID, 0); - - /* Black offsets */ - if (ycbcr) - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); - else - - REG_SET_2(SCL_BLACK_OFFSET, 0, - SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, - SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); - - /* Manually calculate scale ratio and init values */ - dpp_set_manual_ratio_init(xfm, scl_data); - - /* HTaps/VTaps */ - REG_SET_4(SCL_TAP_CONTROL, 0, - SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, - SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, - SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, - SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - - dpp_set_scl_filter(xfm, scl_data, ycbcr); -} - #define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) @@ -1561,7 +913,7 @@ static void oppn10_set_regamma_mode( static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, - .transform_set_scaler = dpp_set_scaler_manual_scale, + .transform_set_scaler = dcn10_dpp_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 1c9d3320064a..496df1fad8c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1386,6 +1386,11 @@ struct dcn10_dpp { int lb_bits_per_entry; bool is_write_to_ram_a_safe; }; + +void dcn10_dpp_set_scaler_manual_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data); + bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, uint32_t inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c new file mode 100644 index 000000000000..95f014b5e7ed --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -0,0 +1,762 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "core_types.h" + +#include "reg_helper.h" +#include "dcn10_dpp.h" +#include "basics/conversion.h" + +#define NUM_PHASES 64 +#define HORZ_MAX_TAPS 8 +#define VERT_MAX_TAPS 8 + +#define BLACK_OFFSET_RGB_Y 0x0 +#define BLACK_OFFSET_CBCR 0x8000 + +#define REG(reg)\ + xfm->tf_regs->reg + +#define CTX \ + xfm->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + xfm->tf_shift->field_name, xfm->tf_mask->field_name + +enum dcn10_coef_filter_type_sel { + SCL_COEF_LUMA_VERT_FILTER = 0, + SCL_COEF_LUMA_HORZ_FILTER = 1, + SCL_COEF_CHROMA_VERT_FILTER = 2, + SCL_COEF_CHROMA_HORZ_FILTER = 3, + SCL_COEF_ALPHA_VERT_FILTER = 4, + SCL_COEF_ALPHA_HORZ_FILTER = 5 +}; + +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + +enum dscl_autocal_mode { + AUTOCAL_MODE_OFF = 0, + + /* Autocal calculate the scaling ratio and initial phase and the + * DSCL_MODE_SEL must be set to 1 + */ + AUTOCAL_MODE_AUTOSCALE = 1, + /* Autocal perform auto centering without replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOCENTER = 2, + /* Autocal perform auto centering and auto replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOREPLICATE = 3 +}; + +enum dscl_mode_sel { + DSCL_MODE_SCALING_444_BYPASS = 0, + DSCL_MODE_SCALING_444_RGB_ENABLE = 1, + DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2, + DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3, + DSCL_MODE_SCALING_420_LUMA_BYPASS = 4, + DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5, + DSCL_MODE_DSCL_BYPASS = 6 +}; + +enum gamut_remap_select { + GAMUT_REMAP_BYPASS = 0, + GAMUT_REMAP_COEFF, + GAMUT_REMAP_COMA_COEFF, + GAMUT_REMAP_COMB_COEFF +}; + + +static void dpp_set_overscan( + struct dcn10_dpp *xfm, + const struct scaler_data *data) +{ + uint32_t left = data->recout.x; + uint32_t top = data->recout.y; + + int right = data->h_active - data->recout.x - data->recout.width; + int bottom = data->v_active - data->recout.y - data->recout.height; + + if (right < 0) { + BREAK_TO_DEBUGGER(); + right = 0; + } + if (bottom < 0) { + BREAK_TO_DEBUGGER(); + bottom = 0; + } + + REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0, + EXT_OVERSCAN_LEFT, left, + EXT_OVERSCAN_RIGHT, right); + + REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0, + EXT_OVERSCAN_BOTTOM, bottom, + EXT_OVERSCAN_TOP, top); +} + +static void dpp_set_otg_blank( + struct dcn10_dpp *xfm, const struct scaler_data *data) +{ + uint32_t h_blank_start = data->h_active; + uint32_t h_blank_end = 0; + uint32_t v_blank_start = data->v_active; + uint32_t v_blank_end = 0; + + REG_SET_2(OTG_H_BLANK, 0, + OTG_H_BLANK_START, h_blank_start, + OTG_H_BLANK_END, h_blank_end); + + REG_SET_2(OTG_V_BLANK, 0, + OTG_V_BLANK_START, v_blank_start, + OTG_V_BLANK_END, v_blank_end); +} + +static int get_pixel_depth_val(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 0; /* 10 bpc */ + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 1; /* 8 bpc */ + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 2; /* 6 bpc */ + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 3; /* 12 bpc */ + else { + ASSERT(0); + return -1; /* Unsupported */ + } +} + +static enum dscl_mode_sel get_dscl_mode( + const struct scaler_data *data, bool dbg_always_scale) +{ + const long long one = dal_fixed31_32_one.value; + bool ycbcr = false; + bool format420 = false; + + if (data->format == PIXEL_FORMAT_FP16) + return DSCL_MODE_DSCL_BYPASS; + + if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && data->format <= PIXEL_FORMAT_VIDEO_END) + ycbcr = true; + + if (data->format == PIXEL_FORMAT_420BPP8 || + data->format == PIXEL_FORMAT_420BPP10) + format420 = true; + + if (data->ratios.horz.value == one + && data->ratios.vert.value == one + && data->ratios.horz_c.value == one + && data->ratios.vert_c.value == one + && !dbg_always_scale) + return DSCL_MODE_SCALING_444_BYPASS; + + if (!format420) { + if (ycbcr) + return DSCL_MODE_SCALING_444_YCBCR_ENABLE; + else + return DSCL_MODE_SCALING_444_RGB_ENABLE; + } + if (data->ratios.horz.value == one && data->ratios.vert.value == one) + return DSCL_MODE_SCALING_420_LUMA_BYPASS; + if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one) + return DSCL_MODE_SCALING_420_CHROMA_BYPASS; + + return DSCL_MODE_SCALING_420_YCBCR_ENABLE; +} + +static void dpp_set_lb( + struct dcn10_dpp *xfm, + const struct line_buffer_params *lb_params, + enum lb_memory_config mem_size_config) +{ + uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; + REG_SET_7(LB_DATA_FORMAT, 0, + PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ + PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ + PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ + DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ + DITHER_EN, 0, /* Dithering enable: Disabled */ + INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ + ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + + REG_SET_2(LB_MEMORY_CTRL, 0, + MEMORY_CONFIG, mem_size_config, + LB_MAX_PARTITIONS, 63); +} + +static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +{ + if (taps == 8) + return get_filter_8tap_64p(ratio); + else if (taps == 7) + return get_filter_7tap_64p(ratio); + else if (taps == 6) + return get_filter_6tap_64p(ratio); + else if (taps == 5) + return get_filter_5tap_64p(ratio); + else if (taps == 4) + return get_filter_4tap_64p(ratio); + else if (taps == 3) + return get_filter_3tap_64p(ratio); + else if (taps == 2) + return filter_2tap_64p; + else if (taps == 1) + return NULL; + else { + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return NULL; + } +} + +static void dpp_set_scaler_filter( + struct dcn10_dpp *xfm, + uint32_t taps, + enum dcn10_coef_filter_type_sel filter_type, + const uint16_t *filter) +{ + const int tap_pairs = (taps + 1) / 2; + int phase; + int pair; + uint16_t odd_coef, even_coef; + + REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0, + SCL_COEF_RAM_TAP_PAIR_IDX, 0, + SCL_COEF_RAM_PHASE, 0, + SCL_COEF_RAM_FILTER_TYPE, filter_type); + + for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) { + for (pair = 0; pair < tap_pairs; pair++) { + even_coef = filter[phase * taps + 2 * pair]; + if ((pair * 2 + 1) < taps) + odd_coef = filter[phase * taps + 2 * pair + 1]; + else + odd_coef = 0; + + REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, + /* Even tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_EVEN_TAP_COEF, even_coef, + /* Write/read control for even coefficient */ + SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1, + /* Odd tap coefficient (bits 1:0 fixed to 0) */ + SCL_COEF_RAM_ODD_TAP_COEF, odd_coef, + /* Write/read control for odd coefficient */ + SCL_COEF_RAM_ODD_TAP_COEF_EN, 1); + } + } + +} + +static void dpp_set_scl_filter( + struct dcn10_dpp *xfm, + const struct scaler_data *scl_data, + bool chroma_coef_mode) +{ + bool h_2tap_hardcode_coef_en = false; + bool v_2tap_hardcode_coef_en = false; + bool h_2tap_sharp_en = false; + bool v_2tap_sharp_en = false; + uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz; + uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert; + bool coef_ram_current; + const uint16_t *filter_h = NULL; + const uint16_t *filter_v = NULL; + const uint16_t *filter_h_c = NULL; + const uint16_t *filter_v_c = NULL; + + h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 + && scl_data->taps.h_taps_c < 3 + && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); + v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 + && scl_data->taps.v_taps_c < 3 + && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); + + h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; + v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; + + REG_UPDATE_6(DSCL_2TAP_CONTROL, + SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en, + SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en, + SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor, + SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en, + SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en, + SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor); + + if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { + bool filter_updated = false; + + filter_h = get_filter_coeffs_64p( + scl_data->taps.h_taps, scl_data->ratios.horz); + filter_v = get_filter_coeffs_64p( + scl_data->taps.v_taps, scl_data->ratios.vert); + + filter_updated = (filter_h && (filter_h != xfm->filter_h)) + || (filter_v && (filter_v != xfm->filter_v)); + + if (chroma_coef_mode) { + filter_h_c = get_filter_coeffs_64p( + scl_data->taps.h_taps_c, scl_data->ratios.horz_c); + filter_v_c = get_filter_coeffs_64p( + scl_data->taps.v_taps_c, scl_data->ratios.vert_c); + filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) + || (filter_v_c && (filter_v_c != xfm->filter_v_c)); + } + + if (filter_updated) { + uint32_t scl_mode = REG_READ(SCL_MODE); + + if (!h_2tap_hardcode_coef_en && filter_h) { + dpp_set_scaler_filter( + xfm, scl_data->taps.h_taps, + SCL_COEF_LUMA_HORZ_FILTER, filter_h); + } + xfm->filter_h = filter_h; + if (!v_2tap_hardcode_coef_en && filter_v) { + dpp_set_scaler_filter( + xfm, scl_data->taps.v_taps, + SCL_COEF_LUMA_VERT_FILTER, filter_v); + } + xfm->filter_v = filter_v; + if (chroma_coef_mode) { + if (!h_2tap_hardcode_coef_en && filter_h_c) { + dpp_set_scaler_filter( + xfm, scl_data->taps.h_taps_c, + SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); + } + if (!v_2tap_hardcode_coef_en && filter_v_c) { + dpp_set_scaler_filter( + xfm, scl_data->taps.v_taps_c, + SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); + } + } + xfm->filter_h_c = filter_h_c; + xfm->filter_v_c = filter_v_c; + + coef_ram_current = get_reg_field_value_ex( + scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, + xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); + + /* Swap coefficient RAM and set chroma coefficient mode */ + REG_SET_2(SCL_MODE, scl_mode, + SCL_COEF_RAM_SELECT, !coef_ram_current, + SCL_CHROMA_COEF_MODE, chroma_coef_mode); + } + } +} + +static int get_lb_depth_bpc(enum lb_pixel_depth depth) +{ + if (depth == LB_PIXEL_DEPTH_30BPP) + return 10; + else if (depth == LB_PIXEL_DEPTH_24BPP) + return 8; + else if (depth == LB_PIXEL_DEPTH_18BPP) + return 6; + else if (depth == LB_PIXEL_DEPTH_36BPP) + return 12; + else { + BREAK_TO_DEBUGGER(); + return -1; /* Unsupported */ + } +} + +static void calc_lb_num_partitions( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c) +{ + int line_size = scl_data->viewport.width < scl_data->recout.width ? + scl_data->viewport.width : scl_data->recout.width; + int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? + scl_data->viewport_c.width : scl_data->recout.width; + int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); + int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ + int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ + int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; + + if (lb_config == LB_MEMORY_CONFIG_1) { + lb_memory_size = 816; + lb_memory_size_c = 816; + lb_memory_size_a = 984; + } else if (lb_config == LB_MEMORY_CONFIG_2) { + lb_memory_size = 1088; + lb_memory_size_c = 1088; + lb_memory_size_a = 1312; + } else if (lb_config == LB_MEMORY_CONFIG_3) { + lb_memory_size = 816 + 1088 + 848 + 848 + 848; + lb_memory_size_c = 816 + 1088; + lb_memory_size_a = 984 + 1312 + 456; + } else { + lb_memory_size = 816 + 1088 + 848; + lb_memory_size_c = 816 + 1088 + 848; + lb_memory_size_a = 984 + 1312 + 456; + } + *num_part_y = lb_memory_size / memory_line_size_y; + *num_part_c = lb_memory_size_c / memory_line_size_c; + num_partitions_a = lb_memory_size_a / memory_line_size_a; + + if (scl_data->lb_params.alpha_en + && (num_partitions_a < *num_part_y)) + *num_part_y = num_partitions_a; + + if (*num_part_y > 64) + *num_part_y = 64; + if (*num_part_c > 64) + *num_part_c = 64; + +} + +static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +{ + if (ceil_vratio > 2) + return vtaps <= (num_partitions - ceil_vratio + 2); + else + return vtaps <= num_partitions; +} + +/*find first match configuration which meets the min required lb size*/ +static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) +{ + int num_part_y, num_part_c; + int vtaps = scl_data->taps.v_taps; + int vtaps_c = scl_data->taps.v_taps_c; + int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); + int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_1; + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_2; + + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) { + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); + + if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + return LB_MEMORY_CONFIG_3; + } + + calc_lb_num_partitions( + scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); + + /*Ensure we can support the requested number of vtaps*/ + ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); + + return LB_MEMORY_CONFIG_0; +} + +void dpp_set_scaler_auto_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + dpp_set_overscan(xfm, scl_data); + + dpp_set_otg_blank(xfm, scl_data); + + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + + lb_config = find_lb_memory_config(scl_data); + dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* TODO: v_min */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + dpp_set_scl_filter(xfm, scl_data, ycbcr); +} + + +static void dpp_set_manual_ratio_init( + struct dcn10_dpp *xfm, const struct scaler_data *data) +{ + uint32_t init_frac = 0; + uint32_t init_int = 0; + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, + SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, + SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5); + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0, + SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0, + SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5); + + /* + * 0.24 format for fraction, first five bits zeroed + */ + init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5; + init_int = dal_fixed31_32_floor(data->inits.h); + REG_SET_2(SCL_HORZ_FILTER_INIT, 0, + SCL_H_INIT_FRAC, init_frac, + SCL_H_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.h_c); + REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0, + SCL_H_INIT_FRAC_C, init_frac, + SCL_H_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5; + init_int = dal_fixed31_32_floor(data->inits.v); + REG_SET_2(SCL_VERT_FILTER_INIT, 0, + SCL_V_INIT_FRAC, init_frac, + SCL_V_INIT_INT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, + SCL_V_INIT_FRAC_BOT, init_frac, + SCL_V_INIT_INT_BOT, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c); + REG_SET_2(SCL_VERT_FILTER_INIT_C, 0, + SCL_V_INIT_FRAC_C, init_frac, + SCL_V_INIT_INT_C, init_int); + + init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5; + init_int = dal_fixed31_32_floor(data->inits.v_c_bot); + REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, + SCL_V_INIT_FRAC_BOT_C, init_frac, + SCL_V_INIT_INT_BOT_C, init_int); +} + + + +static void dpp_set_recout( + struct dcn10_dpp *xfm, const struct rect *recout) +{ + REG_SET_2(RECOUT_START, 0, + /* First pixel of RECOUT */ + RECOUT_START_X, recout->x, + /* First line of RECOUT */ + RECOUT_START_Y, recout->y); + + REG_SET_2(RECOUT_SIZE, 0, + /* Number of RECOUT horizontal pixels */ + RECOUT_WIDTH, recout->width, + /* Number of RECOUT vertical lines */ + RECOUT_HEIGHT, recout->height + - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * + (xfm->base.inst + 1)); +} + +/* Main function to program scaler and line buffer in manual scaling mode */ +void dcn10_dpp_set_scaler_manual_scale( + struct transform *xfm_base, + const struct scaler_data *scl_data) +{ + enum lb_memory_config lb_config; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + enum dscl_mode_sel dscl_mode = get_dscl_mode( + scl_data, xfm_base->ctx->dc->debug.always_scale); + bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN + && scl_data->format <= PIXEL_FORMAT_VIDEO_END; + + /* Recout */ + dpp_set_recout(xfm, &scl_data->recout); + + /* MPC Size */ + REG_SET_2(MPC_SIZE, 0, + /* Number of horizontal pixels of MPC */ + MPC_WIDTH, scl_data->h_active, + /* Number of vertical lines of MPC */ + MPC_HEIGHT, scl_data->v_active); + + /* SCL mode */ + REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); + + if (dscl_mode == DSCL_MODE_DSCL_BYPASS) + return; + /* LB */ + lb_config = find_lb_memory_config(scl_data); + dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + return; + + /* Autocal off */ + REG_SET_3(DSCL_AUTOCAL, 0, + AUTOCAL_MODE, AUTOCAL_MODE_OFF, + AUTOCAL_NUM_PIPE, 0, + AUTOCAL_PIPE_ID, 0); + + /* Black offsets */ + if (ycbcr) + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR); + else + + REG_SET_2(SCL_BLACK_OFFSET, 0, + SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y, + SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); + + /* Manually calculate scale ratio and init values */ + dpp_set_manual_ratio_init(xfm, scl_data); + + /* HTaps/VTaps */ + REG_SET_4(SCL_TAP_CONTROL, 0, + SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1, + SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1, + SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, + SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); + + dpp_set_scl_filter(xfm, scl_data, ycbcr); +} + + +#if 0 +bool dpp_set_pixel_storage_depth( + struct dpp *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm); + bool ret = true; + uint32_t value; + enum dc_color_depth color_depth; + + value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + color_depth = COLOR_DEPTH_666; + set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_24BPP: + color_depth = COLOR_DEPTH_888; + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_30BPP: + color_depth = COLOR_DEPTH_101010; + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + case LB_PIXEL_DEPTH_36BPP: + color_depth = COLOR_DEPTH_121212; + set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); + set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); + break; + default: + ret = false; + break; + } + + if (ret == true) { + set_denormalization(xfm110, color_depth); + ret = program_bit_depth_reduction(xfm110, color_depth, + bit_depth_params); + + set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); + dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); + if (!(xfm110->lb_pixel_depth_supported & depth)) { + /* We should use unsupported capabilities + * unless it is required by w/a + */ + dm_logger_write(xfm->ctx->logger, LOG_WARNING, + "%s: Capability not supported", + __func__); + } + } + + return ret; +} +#endif + + -- GitLab From 9799624ac236eb238b5a5c885c759b1cbcac6349 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Tue, 15 Aug 2017 19:10:14 -0400 Subject: [PATCH 0804/2898] drm/amd/display: Cache edp config in dc link Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 ++ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 0144c98fd0d5..d621237e923e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2258,6 +2258,8 @@ static void retrieve_link_cap(struct dc_link *link) DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV]; link->dpcd_caps.panel_mode_edp = edp_config_cap.bits.ALT_SCRAMBLER_RESET; + link->dpcd_caps.dpcd_display_control_capable = + edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE; link->test_pattern_enabled = false; link->compliance_test_state.raw = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 928d2a0501eb..bd8b1ba22df8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -760,6 +760,7 @@ struct dpcd_caps { bool allow_invalid_MSA_timing_param; bool panel_mode_edp; + bool dpcd_display_control_capable; }; struct dc_link_status { @@ -834,7 +835,6 @@ struct dc_link { struct dpcd_caps dpcd_caps; unsigned short chip_caps; unsigned int dpcd_sink_count; - enum edp_revision edp_revision; bool psr_enabled; -- GitLab From 3005e437e70fd4d1da64d91b4ef027f62d3b9a41 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 17 Aug 2017 16:24:11 -0400 Subject: [PATCH 0805/2898] drm/amd/display: re-enable audio after LT test [Description] Audio should be attached to the same pipe once it is attached. We will not remove audio endpoint in disable stream. We will reeanble the audio after automated link training test Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 14 ++++++++++++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 2 -- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index e12f1f9fb590..3a5abd92036a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -310,6 +310,20 @@ void dp_retrain_link_dp_test(struct dc_link *link, link->dc->hwss.unblank_stream(&pipes[i], link_setting); + + if (pipes[i].stream_res.audio) { + /* notify audio driver for + * audio modes of monitor */ + pipes[i].stream_res.audio->funcs->az_enable( + pipes[i].stream_res.audio); + + /* un-mute audio */ + /* TODO: audio should be per stream rather than + * per link */ + pipes[i].stream_res.stream_enc->funcs-> + audio_mute_control( + pipes[i].stream_res.stream_enc, false); + } } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e6c6f1108078..7516c198d13a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -758,8 +758,6 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); - pipe_ctx->stream_res.audio = NULL; - /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ /* dal_audio_disable_azalia_audio_jack_presence(stream->audio, -- GitLab From dff2721bd1d777eba3917f04d4b8adede89badff Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 17 Aug 2017 17:17:37 -0400 Subject: [PATCH 0806/2898] drm/amd/display: separate cm functions out from dcn10_dpp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 662 --------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 34 + .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 776 ++++++++++++++++++ 4 files changed, 811 insertions(+), 663 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 83619e6b8a05..52b56d19ca40 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -4,7 +4,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \ - dcn10_dpp_dscl.o + dcn10_dpp_dscl.o dcn10_dpp_cm.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index a841ed36c217..f0e74afc4518 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -195,669 +195,7 @@ static void dpp_reset(struct transform *xfm_base) REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); } -static void program_gamut_remap( - struct dcn10_dpp *xfm, - const uint16_t *regval, - enum gamut_remap_select select) -{ - uint16_t selection = 0; - - if (regval == NULL || select == GAMUT_REMAP_BYPASS) { - REG_SET(CM_GAMUT_REMAP_CONTROL, 0, - CM_GAMUT_REMAP_MODE, 0); - return; - } - switch (select) { - case GAMUT_REMAP_COEFF: - selection = 1; - break; - case GAMUT_REMAP_COMA_COEFF: - selection = 2; - break; - case GAMUT_REMAP_COMB_COEFF: - selection = 3; - break; - default: - break; - } - - - if (select == GAMUT_REMAP_COEFF) { - - REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, - CM_GAMUT_REMAP_C11, regval[0], - CM_GAMUT_REMAP_C12, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, - CM_GAMUT_REMAP_C13, regval[0], - CM_GAMUT_REMAP_C14, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, - CM_GAMUT_REMAP_C21, regval[0], - CM_GAMUT_REMAP_C22, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, - CM_GAMUT_REMAP_C23, regval[0], - CM_GAMUT_REMAP_C24, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, - CM_GAMUT_REMAP_C31, regval[0], - CM_GAMUT_REMAP_C32, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, - CM_GAMUT_REMAP_C33, regval[0], - CM_GAMUT_REMAP_C34, regval[1]); - - } else if (select == GAMUT_REMAP_COMA_COEFF) { - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); - - } else { - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, regval[0], - CM_COMB_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, regval[0], - CM_COMB_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, regval[0], - CM_COMB_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, regval[0], - CM_COMB_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, regval[0], - CM_COMB_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, regval[0], - CM_COMB_C34, regval[1]); - } - - REG_SET( - CM_GAMUT_REMAP_CONTROL, 0, - CM_GAMUT_REMAP_MODE, selection); - -} - -static void dcn_dpp_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust) -{ - struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); - - if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) - /* Bypass if type is bypass or hw */ - program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); - else { - struct fixed31_32 arr_matrix[12]; - uint16_t arr_reg_val[12]; - - arr_matrix[0] = adjust->temperature_matrix[0]; - arr_matrix[1] = adjust->temperature_matrix[1]; - arr_matrix[2] = adjust->temperature_matrix[2]; - arr_matrix[3] = dal_fixed31_32_zero; - - arr_matrix[4] = adjust->temperature_matrix[3]; - arr_matrix[5] = adjust->temperature_matrix[4]; - arr_matrix[6] = adjust->temperature_matrix[5]; - arr_matrix[7] = dal_fixed31_32_zero; - - arr_matrix[8] = adjust->temperature_matrix[6]; - arr_matrix[9] = adjust->temperature_matrix[7]; - arr_matrix[10] = adjust->temperature_matrix[8]; - arr_matrix[11] = dal_fixed31_32_zero; - - convert_float_matrix( - arr_reg_val, arr_matrix, 12); - - program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); - } -} -static void oppn10_set_output_csc_default( - struct transform *xfm_base, - const struct default_adjustment *default_adjust) -{ - - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - uint32_t ocsc_mode = 0; - - if (default_adjust != NULL) { - switch (default_adjust->out_color_space) { - case COLOR_SPACE_SRGB: - case COLOR_SPACE_2020_RGB_FULLRANGE: - ocsc_mode = 0; - break; - case COLOR_SPACE_SRGB_LIMITED: - case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - ocsc_mode = 1; - break; - case COLOR_SPACE_YCBCR601: - case COLOR_SPACE_YCBCR601_LIMITED: - ocsc_mode = 2; - break; - case COLOR_SPACE_YCBCR709: - case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_2020_YCBCR: - ocsc_mode = 3; - break; - case COLOR_SPACE_UNKNOWN: - default: - break; - } - } - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - -} - -static void oppn10_program_color_matrix( - struct dcn10_dpp *xfm, - const struct out_csc_color_matrix *tbl_entry) -{ - uint32_t mode; - - REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); - - if (tbl_entry == NULL) { - BREAK_TO_DEBUGGER(); - return; - } - - if (mode == 4) { - /*R*/ - REG_SET_2(CM_OCSC_C11_C12, 0, - CM_OCSC_C11, tbl_entry->regval[0], - CM_OCSC_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_OCSC_C13_C14, 0, - CM_OCSC_C13, tbl_entry->regval[2], - CM_OCSC_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_OCSC_C21_C22, 0, - CM_OCSC_C21, tbl_entry->regval[4], - CM_OCSC_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_OCSC_C23_C24, 0, - CM_OCSC_C23, tbl_entry->regval[6], - CM_OCSC_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_OCSC_C31_C32, 0, - CM_OCSC_C31, tbl_entry->regval[8], - CM_OCSC_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_OCSC_C33_C34, 0, - CM_OCSC_C33, tbl_entry->regval[10], - CM_OCSC_C34, tbl_entry->regval[11]); - } else { - /*R*/ - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, tbl_entry->regval[0], - CM_COMB_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, tbl_entry->regval[2], - CM_COMB_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, tbl_entry->regval[4], - CM_COMB_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, tbl_entry->regval[6], - CM_COMB_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, tbl_entry->regval[8], - CM_COMB_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, tbl_entry->regval[10], - CM_COMB_C34, tbl_entry->regval[11]); - } -} - -static void oppn10_set_output_csc_adjustment( - struct transform *xfm_base, - const struct out_csc_color_matrix *tbl_entry) -{ - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; - uint32_t ocsc_mode = 4; - - /** - *if (tbl_entry != NULL) { - * switch (tbl_entry->color_space) { - * case COLOR_SPACE_SRGB: - * case COLOR_SPACE_2020_RGB_FULLRANGE: - * ocsc_mode = 0; - * break; - * case COLOR_SPACE_SRGB_LIMITED: - * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - * ocsc_mode = 1; - * break; - * case COLOR_SPACE_YCBCR601: - * case COLOR_SPACE_YCBCR601_LIMITED: - * ocsc_mode = 2; - * break; - * case COLOR_SPACE_YCBCR709: - * case COLOR_SPACE_YCBCR709_LIMITED: - * case COLOR_SPACE_2020_YCBCR: - * ocsc_mode = 3; - * break; - * case COLOR_SPACE_UNKNOWN: - * default: - * break; - * } - *} - */ - - REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - oppn10_program_color_matrix(xfm, tbl_entry); -} - -static void oppn10_power_on_regamma_lut( - struct transform *xfm_base, - bool power_on) -{ - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - REG_SET(CM_MEM_PWR_CTRL, 0, - RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); - -} - -static void opp_program_regamma_lut( - struct transform *xfm_base, - const struct pwl_result_data *rgb, - uint32_t num) -{ - uint32_t i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - for (i = 0 ; i < num; i++) { - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); - - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); - REG_SET(CM_RGAM_LUT_DATA, 0, - CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); - - } - -} - -static void opp_configure_regamma_lut( - struct transform *xfm_base, - bool is_ram_a) -{ - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, - CM_RGAM_LUT_WRITE_EN_MASK, 7); - REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, - CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); - REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); -} - -/*program re gamma RAM A*/ -static void opp_program_regamma_luta_settings( - struct transform *xfm_base, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, - CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, - CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, - CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, - CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, - CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, - CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, - CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, - CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, - CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, - CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, - CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, - CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, - CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, - CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, - CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, - CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, - CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, - CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, - CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, - CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, - CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, - CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, - CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); -} - -/*program re gamma RAM B*/ -static void opp_program_regamma_lutb_settings( - struct transform *xfm_base, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, - CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, - CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, - CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, - CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, - CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, - CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, - CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, - CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, - CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, - CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, - CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, - CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, - CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, - CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, - CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, - CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, - CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); - -} static bool oppn10_set_regamma_pwl( struct transform *xfm_base, const struct pwl_params *params) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 496df1fad8c4..a4dfdb9b4d69 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1387,6 +1387,40 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; +void opp_program_regamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num); + +void oppn10_power_on_regamma_lut( + struct transform *xfm_base, + bool power_on); + +void opp_configure_regamma_lut( + struct transform *xfm_base, + bool is_ram_a); + +/*program re gamma RAM A*/ +void opp_program_regamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params); + +/*program re gamma RAM B*/ +void opp_program_regamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params); +void oppn10_set_output_csc_adjustment( + struct transform *xfm_base, + const struct out_csc_color_matrix *tbl_entry); + +void oppn10_set_output_csc_default( + struct transform *xfm_base, + const struct default_adjustment *default_adjust); + +void dcn_dpp_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust); + void dcn10_dpp_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c new file mode 100644 index 000000000000..7eb4334c30fc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -0,0 +1,776 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "core_types.h" + +#include "include/grph_object_id.h" +#include "include/fixed31_32.h" +#include "include/logger_interface.h" + +#include "reg_helper.h" +#include "dcn10_dpp.h" +#include "basics/conversion.h" + +#define NUM_PHASES 64 +#define HORZ_MAX_TAPS 8 +#define VERT_MAX_TAPS 8 + +#define BLACK_OFFSET_RGB_Y 0x0 +#define BLACK_OFFSET_CBCR 0x8000 + +#define REG(reg)\ + xfm->tf_regs->reg + +#define CTX \ + xfm->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + xfm->tf_shift->field_name, xfm->tf_mask->field_name + +enum dcn10_coef_filter_type_sel { + SCL_COEF_LUMA_VERT_FILTER = 0, + SCL_COEF_LUMA_HORZ_FILTER = 1, + SCL_COEF_CHROMA_VERT_FILTER = 2, + SCL_COEF_CHROMA_HORZ_FILTER = 3, + SCL_COEF_ALPHA_VERT_FILTER = 4, + SCL_COEF_ALPHA_HORZ_FILTER = 5 +}; + +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + +enum dscl_autocal_mode { + AUTOCAL_MODE_OFF = 0, + + /* Autocal calculate the scaling ratio and initial phase and the + * DSCL_MODE_SEL must be set to 1 + */ + AUTOCAL_MODE_AUTOSCALE = 1, + /* Autocal perform auto centering without replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOCENTER = 2, + /* Autocal perform auto centering and auto replication and the + * DSCL_MODE_SEL must be set to 0 + */ + AUTOCAL_MODE_AUTOREPLICATE = 3 +}; + +enum dscl_mode_sel { + DSCL_MODE_SCALING_444_BYPASS = 0, + DSCL_MODE_SCALING_444_RGB_ENABLE = 1, + DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2, + DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3, + DSCL_MODE_SCALING_420_LUMA_BYPASS = 4, + DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5, + DSCL_MODE_DSCL_BYPASS = 6 +}; + +enum gamut_remap_select { + GAMUT_REMAP_BYPASS = 0, + GAMUT_REMAP_COEFF, + GAMUT_REMAP_COMA_COEFF, + GAMUT_REMAP_COMB_COEFF +}; + +static void program_gamut_remap( + struct dcn10_dpp *xfm, + const uint16_t *regval, + enum gamut_remap_select select) +{ + uint16_t selection = 0; + + if (regval == NULL || select == GAMUT_REMAP_BYPASS) { + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + return; + } + switch (select) { + case GAMUT_REMAP_COEFF: + selection = 1; + break; + case GAMUT_REMAP_COMA_COEFF: + selection = 2; + break; + case GAMUT_REMAP_COMB_COEFF: + selection = 3; + break; + default: + break; + } + + + if (select == GAMUT_REMAP_COEFF) { + + REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, + CM_GAMUT_REMAP_C11, regval[0], + CM_GAMUT_REMAP_C12, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, + CM_GAMUT_REMAP_C13, regval[0], + CM_GAMUT_REMAP_C14, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, + CM_GAMUT_REMAP_C21, regval[0], + CM_GAMUT_REMAP_C22, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, + CM_GAMUT_REMAP_C23, regval[0], + CM_GAMUT_REMAP_C24, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, + CM_GAMUT_REMAP_C31, regval[0], + CM_GAMUT_REMAP_C32, regval[1]); + regval += 2; + REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, + CM_GAMUT_REMAP_C33, regval[0], + CM_GAMUT_REMAP_C34, regval[1]); + + } else if (select == GAMUT_REMAP_COMA_COEFF) { + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + + } else { + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, regval[0], + CM_COMB_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, regval[0], + CM_COMB_C14, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, regval[0], + CM_COMB_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, regval[0], + CM_COMB_C24, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, regval[0], + CM_COMB_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, regval[0], + CM_COMB_C34, regval[1]); + } + + REG_SET( + CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, selection); + +} + +void dcn_dpp_set_gamut_remap( + struct transform *xfm, + const struct xfm_grph_csc_adjustment *adjust) +{ + struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + /* Bypass if type is bypass or hw */ + program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); + else { + struct fixed31_32 arr_matrix[12]; + uint16_t arr_reg_val[12]; + + arr_matrix[0] = adjust->temperature_matrix[0]; + arr_matrix[1] = adjust->temperature_matrix[1]; + arr_matrix[2] = adjust->temperature_matrix[2]; + arr_matrix[3] = dal_fixed31_32_zero; + + arr_matrix[4] = adjust->temperature_matrix[3]; + arr_matrix[5] = adjust->temperature_matrix[4]; + arr_matrix[6] = adjust->temperature_matrix[5]; + arr_matrix[7] = dal_fixed31_32_zero; + + arr_matrix[8] = adjust->temperature_matrix[6]; + arr_matrix[9] = adjust->temperature_matrix[7]; + arr_matrix[10] = adjust->temperature_matrix[8]; + arr_matrix[11] = dal_fixed31_32_zero; + + convert_float_matrix( + arr_reg_val, arr_matrix, 12); + + program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); + } +} + +void oppn10_set_output_csc_default( + struct transform *xfm_base, + const struct default_adjustment *default_adjust) +{ + + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + uint32_t ocsc_mode = 0; + + if (default_adjust != NULL) { + switch (default_adjust->out_color_space) { + case COLOR_SPACE_SRGB: + case COLOR_SPACE_2020_RGB_FULLRANGE: + ocsc_mode = 0; + break; + case COLOR_SPACE_SRGB_LIMITED: + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + ocsc_mode = 1; + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + ocsc_mode = 2; + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + case COLOR_SPACE_2020_YCBCR: + ocsc_mode = 3; + break; + case COLOR_SPACE_UNKNOWN: + default: + break; + } + } + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + +} + +static void oppn10_program_color_matrix( + struct dcn10_dpp *xfm, + const struct out_csc_color_matrix *tbl_entry) +{ + uint32_t mode; + + REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); + + if (tbl_entry == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + if (mode == 4) { + /*R*/ + REG_SET_2(CM_OCSC_C11_C12, 0, + CM_OCSC_C11, tbl_entry->regval[0], + CM_OCSC_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_OCSC_C13_C14, 0, + CM_OCSC_C13, tbl_entry->regval[2], + CM_OCSC_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_OCSC_C21_C22, 0, + CM_OCSC_C21, tbl_entry->regval[4], + CM_OCSC_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_OCSC_C23_C24, 0, + CM_OCSC_C23, tbl_entry->regval[6], + CM_OCSC_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_OCSC_C31_C32, 0, + CM_OCSC_C31, tbl_entry->regval[8], + CM_OCSC_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_OCSC_C33_C34, 0, + CM_OCSC_C33, tbl_entry->regval[10], + CM_OCSC_C34, tbl_entry->regval[11]); + } else { + /*R*/ + REG_SET_2(CM_COMB_C11_C12, 0, + CM_COMB_C11, tbl_entry->regval[0], + CM_COMB_C12, tbl_entry->regval[1]); + + REG_SET_2(CM_COMB_C13_C14, 0, + CM_COMB_C13, tbl_entry->regval[2], + CM_COMB_C14, tbl_entry->regval[3]); + + /*G*/ + REG_SET_2(CM_COMB_C21_C22, 0, + CM_COMB_C21, tbl_entry->regval[4], + CM_COMB_C22, tbl_entry->regval[5]); + + REG_SET_2(CM_COMB_C23_C24, 0, + CM_COMB_C23, tbl_entry->regval[6], + CM_COMB_C24, tbl_entry->regval[7]); + + /*B*/ + REG_SET_2(CM_COMB_C31_C32, 0, + CM_COMB_C31, tbl_entry->regval[8], + CM_COMB_C32, tbl_entry->regval[9]); + + REG_SET_2(CM_COMB_C33_C34, 0, + CM_COMB_C33, tbl_entry->regval[10], + CM_COMB_C34, tbl_entry->regval[11]); + } +} + +void oppn10_set_output_csc_adjustment( + struct transform *xfm_base, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; + uint32_t ocsc_mode = 4; + + /** + *if (tbl_entry != NULL) { + * switch (tbl_entry->color_space) { + * case COLOR_SPACE_SRGB: + * case COLOR_SPACE_2020_RGB_FULLRANGE: + * ocsc_mode = 0; + * break; + * case COLOR_SPACE_SRGB_LIMITED: + * case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + * ocsc_mode = 1; + * break; + * case COLOR_SPACE_YCBCR601: + * case COLOR_SPACE_YCBCR601_LIMITED: + * ocsc_mode = 2; + * break; + * case COLOR_SPACE_YCBCR709: + * case COLOR_SPACE_YCBCR709_LIMITED: + * case COLOR_SPACE_2020_YCBCR: + * ocsc_mode = 3; + * break; + * case COLOR_SPACE_UNKNOWN: + * default: + * break; + * } + *} + */ + + REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); + oppn10_program_color_matrix(xfm, tbl_entry); +} + +void oppn10_power_on_regamma_lut( + struct transform *xfm_base, + bool power_on) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + REG_SET(CM_MEM_PWR_CTRL, 0, + RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); + +} + +void opp_program_regamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + for (i = 0 ; i < num; i++) { + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_RGAM_LUT_DATA, 0, + CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg); + + } + +} + +void opp_configure_regamma_lut( + struct transform *xfm_base, + bool is_ram_a) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, + CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); +} + +/*program re gamma RAM A*/ +void opp_program_regamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, + CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, + CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, + CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, + CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, + CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, + CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, + CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, + CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, + CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, + CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, + CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, + CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, + CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, + CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, + CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, + CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, + CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, + CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, + CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program re gamma RAM B*/ +void opp_program_regamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, + CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); + + REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, + CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, + CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, + CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, + CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, + CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, + CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, + CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, + CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, + CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, + CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, + CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, + CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, + CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, + CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, + CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, + CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, + CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, + CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, + CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + +} -- GitLab From 3f1f74f436798a54b6ebcacfc026ddc4347eab46 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 17 Aug 2017 16:05:37 -0400 Subject: [PATCH 0807/2898] drm/amd/display: Fix two MST not light up regressions 1. Change 100104: Move verify link cap after read edid causes MST link_cap struct not being set. It leads to zero denominator pbn_per_slot value, leading to the crash at dal_fixed31_32_div(). Skip MST link training for now and will need to add MST specific link traning routine later. 2. Change 98822: Adding edp supports changes link setting condition from max_link to verified_link. It leads to MST is getting wrong link settings. e.g. LINK_SPREAD_05_DOWNSPREAD_30KHZ not set in MST case Signed-off-by: Jerry Zuo Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 16 +++++++++------- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index cab54afa1131..ee9b98472029 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -607,6 +607,12 @@ bool dc_link_detect(struct dc_link *link, bool boot) if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Connected\n", link->link_index); + /* Need to setup mst link_cap struct here + * otherwise dc_link_detect() will leave mst link_cap + * empty which leads to allocate_mst_payload() has "0" + * pbn_per_slot value leading to exception on dal_fixed31_32_div() + */ + link->verified_link_cap = link->reported_link_cap; return false; } @@ -672,13 +678,9 @@ bool dc_link_detect(struct dc_link *link, bool boot) * TODO debug why Dell 2413 doesn't like * two link trainings */ - if (is_mst_supported(link)) { - link->verified_link_cap = - link->reported_link_cap; - } else { - dp_hbr_verify_link_cap(link, - &link->reported_link_cap); - } + + /* deal with non-mst cases */ + dp_hbr_verify_link_cap(link, &link->reported_link_cap); } /* HDMI-DVI Dongle */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index d621237e923e..e35bdce6a0f3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1459,6 +1459,14 @@ void decide_link_settings(struct dc_stream_state *stream, return; } + /* MST doesn't perform link training for now + * TODO: add MST specific link training routine + */ + if (is_mst_supported(link)) { + *link_setting = link->verified_link_cap; + return; + } + /* search for the minimum link setting that: * 1. is supported according to the link training result * 2. could support the b/w requested by the timing -- GitLab From 79c24086570953e10f2c5c08946619a9a0f71ee9 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 17 Aug 2017 17:00:47 -0400 Subject: [PATCH 0808/2898] drm/amd/display: Disable stutter for Raven Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4bb78f76acce..e037ed85a5cc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1383,6 +1383,10 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) DRM_ERROR("DM: Failed to initialize IRQ\n"); goto fail_free_encoder; } + /* + * Temporary disable until pplib/smu interaction is implemented + */ + dm->dc->debug.disable_stutter = true; break; #endif default: -- GitLab From f670af8a954ae09b1f4949421e5d300be66d1156 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 17 Aug 2017 14:57:27 -0400 Subject: [PATCH 0809/2898] drm/amd/display: Remove unnecessary assignemnt Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 5e4f7f08e3db..aaa6d2326190 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -41,7 +41,6 @@ static bool construct(struct dc_stream_state *stream, stream->sink = dc_sink_data; stream->ctx = stream->sink->ctx; - stream->sink = dc_sink_data; dc_sink_retain(dc_sink_data); -- GitLab From 8eb5def95762dc1cd9e516510925a95060452c5a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 28 Jul 2017 08:16:27 -0400 Subject: [PATCH 0810/2898] drm/amd/display: fix hubp mpcc and opp tracking This should be handled by mi and mpc only Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 2 ++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 627669749740..83d9caa4f438 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -686,6 +686,8 @@ void dce_mem_input_construct( dce_mi->shifts = mi_shift; dce_mi->masks = mi_mask; + dce_mi->base.mpcc_id = 0xf; + dce_mi->base.opp_id = 0xf; } void dce112_mem_input_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ddfa6a8d087b..69f67f6e27b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1066,9 +1066,6 @@ static void plane_atomic_disable(struct dc *dc, fe_idx);*/ mi->funcs->set_blank(mi, true); - /*todo: unhack this*/ - mi->opp_id = 0xf; - mi->mpcc_id = 0xf; if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -2304,7 +2301,8 @@ static void update_dchubp_dpp( &plane_state->dcc, plane_state->horizontal_mirror); - mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx)); + if (is_pipe_tree_visible(pipe_ctx)) + mi->funcs->set_blank(mi, false); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 11daf6b5c7d8..0a47e6ad4286 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -51,9 +51,8 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) REG_WAIT(DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1, 1, 200); - /*todo: unhack this mem_input->mpcc_id = 0xf; - mem_input->opp_id = 0xf;*/ + mem_input->opp_id = 0xf; } } -- GitLab From b823defeb73aa8737006abe73844fd697ecf6983 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 28 Jul 2017 08:16:27 -0400 Subject: [PATCH 0811/2898] drm/amd/display: Fixed mpc add, enable always scaler for video surface. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 52f2f2dd9a43..ce408ccb428e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -229,9 +229,9 @@ static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); mpc10->mpcc_in_use_mask |= 1 << mpcc_id; - for (z_idx = cfg->z_index; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) { - cfg->opp->mpc_tree.dpp[z_idx + 1] = cfg->opp->mpc_tree.dpp[z_idx]; - cfg->opp->mpc_tree.mpcc[z_idx + 1] = cfg->opp->mpc_tree.mpcc[z_idx]; + for (z_idx = cfg->opp->mpc_tree.num_pipes; z_idx > cfg->z_index; z_idx--) { + cfg->opp->mpc_tree.dpp[z_idx] = cfg->opp->mpc_tree.dpp[z_idx - 1]; + cfg->opp->mpc_tree.mpcc[z_idx] = cfg->opp->mpc_tree.mpcc[z_idx - 1]; } cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst; cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index ee43cbc70c8a..9c7ec047f083 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -422,6 +422,10 @@ static const struct dc_debug debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .clock_trace = true, + /* spread sheet doesn't handle taps_c is one properly, + * need to enable scaler for video surface to pass + * bandwidth validation.*/ + .always_scale = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- GitLab From 58314e5812d5027edb01e0d20cf72068c95a7c10 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Sat, 19 Aug 2017 12:10:28 -0400 Subject: [PATCH 0812/2898] drm/amd/display: cleanup naming of DCN DPP functions Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 41 ++++++++++--------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 25 +++++++---- .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 20 ++++----- .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 2 +- 4 files changed, 48 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index f0e74afc4518..30722495de0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -123,7 +123,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) #define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19)) -static bool dpp_get_optimal_number_of_taps( +bool dpp_get_optimal_number_of_taps( struct transform *xfm, struct scaler_data *scl_data, const struct scaling_taps *in_taps) @@ -182,7 +182,7 @@ static bool dpp_get_optimal_number_of_taps( return true; } -static void dpp_reset(struct transform *xfm_base) +void dpp_reset(struct transform *xfm_base) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); @@ -197,26 +197,26 @@ static void dpp_reset(struct transform *xfm_base) -static bool oppn10_set_regamma_pwl( +static bool dcn10_dpp_cm_set_regamma_pwl( struct transform *xfm_base, const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - oppn10_power_on_regamma_lut(xfm_base, true); - opp_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); + dcn10_dpp_cm_power_on_regamma_lut(xfm_base, true); + dcn10_dpp_cm_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); if (xfm->is_write_to_ram_a_safe) - opp_program_regamma_luta_settings(xfm_base, params); + dcn10_dpp_cm_program_regamma_luta_settings(xfm_base, params); else - opp_program_regamma_lutb_settings(xfm_base, params); + dcn10_dpp_cm_program_regamma_lutb_settings(xfm_base, params); - opp_program_regamma_lut( + dcn10_dpp_cm_program_regamma_lut( xfm_base, params->rgb_resulted, params->hw_points_num); return true; } -static void oppn10_set_regamma_mode( +static void dcn10_dpp_cm_set_regamma_mode( struct transform *xfm_base, enum opp_regamma mode) { @@ -251,20 +251,21 @@ static void oppn10_set_regamma_mode( static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, - .transform_set_scaler = dcn10_dpp_set_scaler_manual_scale, + .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn_dpp_set_gamut_remap, - .opp_set_csc_adjustment = oppn10_set_output_csc_adjustment, - .opp_set_csc_default = oppn10_set_output_csc_default, - .opp_power_on_regamma_lut = oppn10_power_on_regamma_lut, - .opp_program_regamma_lut = opp_program_regamma_lut, - .opp_configure_regamma_lut = opp_configure_regamma_lut, - .opp_program_regamma_lutb_settings = opp_program_regamma_lutb_settings, - .opp_program_regamma_luta_settings = opp_program_regamma_luta_settings, - .opp_program_regamma_pwl = oppn10_set_regamma_pwl, - .opp_set_regamma_mode = oppn10_set_regamma_mode, + .transform_set_gamut_remap = dcn10_dpp_cm_set_gamut_remap, + .opp_set_csc_adjustment = dcn10_dpp_cm_set_output_csc_adjustment, + .opp_set_csc_default = dcn10_dpp_cm_set_output_csc_default, + .opp_power_on_regamma_lut = dcn10_dpp_cm_power_on_regamma_lut, + .opp_program_regamma_lut = dcn10_dpp_cm_program_regamma_lut, + .opp_configure_regamma_lut = dcn10_dpp_cm_configure_regamma_lut, + .opp_program_regamma_lutb_settings = dcn10_dpp_cm_program_regamma_lutb_settings, + .opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings, + .opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl, + .opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode, }; + /*****************************************/ /* Constructor, Destructor */ /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index a4dfdb9b4d69..18ee338f6b28 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1387,41 +1387,48 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; -void opp_program_regamma_lut( +bool dpp_get_optimal_number_of_taps( + struct transform *xfm, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); + +void dpp_reset(struct transform *xfm_base); + +void dcn10_dpp_cm_program_regamma_lut( struct transform *xfm_base, const struct pwl_result_data *rgb, uint32_t num); -void oppn10_power_on_regamma_lut( +void dcn10_dpp_cm_power_on_regamma_lut( struct transform *xfm_base, bool power_on); -void opp_configure_regamma_lut( +void dcn10_dpp_cm_configure_regamma_lut( struct transform *xfm_base, bool is_ram_a); /*program re gamma RAM A*/ -void opp_program_regamma_luta_settings( +void dcn10_dpp_cm_program_regamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params); /*program re gamma RAM B*/ -void opp_program_regamma_lutb_settings( +void dcn10_dpp_cm_program_regamma_lutb_settings( struct transform *xfm_base, const struct pwl_params *params); -void oppn10_set_output_csc_adjustment( +void dcn10_dpp_cm_set_output_csc_adjustment( struct transform *xfm_base, const struct out_csc_color_matrix *tbl_entry); -void oppn10_set_output_csc_default( +void dcn10_dpp_cm_set_output_csc_default( struct transform *xfm_base, const struct default_adjustment *default_adjust); -void dcn_dpp_set_gamut_remap( +void dcn10_dpp_cm_set_gamut_remap( struct transform *xfm, const struct xfm_grph_csc_adjustment *adjust); -void dcn10_dpp_set_scaler_manual_scale( +void dcn10_dpp_dscl_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 7eb4334c30fc..9ff283bff007 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -221,7 +221,7 @@ static void program_gamut_remap( } -void dcn_dpp_set_gamut_remap( +void dcn10_dpp_cm_set_gamut_remap( struct transform *xfm, const struct xfm_grph_csc_adjustment *adjust) { @@ -256,7 +256,7 @@ void dcn_dpp_set_gamut_remap( } } -void oppn10_set_output_csc_default( +void dcn10_dpp_cm_set_output_csc_default( struct transform *xfm_base, const struct default_adjustment *default_adjust) { @@ -293,7 +293,7 @@ void oppn10_set_output_csc_default( } -static void oppn10_program_color_matrix( +static void dcn10_dpp_cm_program_color_matrix( struct dcn10_dpp *xfm, const struct out_csc_color_matrix *tbl_entry) { @@ -363,7 +363,7 @@ static void oppn10_program_color_matrix( } } -void oppn10_set_output_csc_adjustment( +void dcn10_dpp_cm_set_output_csc_adjustment( struct transform *xfm_base, const struct out_csc_color_matrix *tbl_entry) { @@ -399,10 +399,10 @@ void oppn10_set_output_csc_adjustment( */ REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - oppn10_program_color_matrix(xfm, tbl_entry); + dcn10_dpp_cm_program_color_matrix(xfm, tbl_entry); } -void oppn10_power_on_regamma_lut( +void dcn10_dpp_cm_power_on_regamma_lut( struct transform *xfm_base, bool power_on) { @@ -412,7 +412,7 @@ void oppn10_power_on_regamma_lut( } -void opp_program_regamma_lut( +void dcn10_dpp_cm_program_regamma_lut( struct transform *xfm_base, const struct pwl_result_data *rgb, uint32_t num) @@ -435,7 +435,7 @@ void opp_program_regamma_lut( } -void opp_configure_regamma_lut( +void dcn10_dpp_cm_configure_regamma_lut( struct transform *xfm_base, bool is_ram_a) { @@ -449,7 +449,7 @@ void opp_configure_regamma_lut( } /*program re gamma RAM A*/ -void opp_program_regamma_luta_settings( +void dcn10_dpp_cm_program_regamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params) { @@ -612,7 +612,7 @@ void opp_program_regamma_luta_settings( } /*program re gamma RAM B*/ -void opp_program_regamma_lutb_settings( +void dcn10_dpp_cm_program_regamma_lutb_settings( struct transform *xfm_base, const struct pwl_params *params) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 95f014b5e7ed..76d5f5d4d82f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -636,7 +636,7 @@ static void dpp_set_recout( } /* Main function to program scaler and line buffer in manual scaling mode */ -void dcn10_dpp_set_scaler_manual_scale( +void dcn10_dpp_dscl_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data) { -- GitLab From 9ea29a1f8b9da52d8eca8b0996f1d84eac548d3b Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 19 Aug 2017 16:36:13 -0400 Subject: [PATCH 0813/2898] drm/amd/display: memory leak dwb Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 9c7ec047f083..4af40f5138fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -747,6 +747,11 @@ static void destruct(struct dcn10_resource_pool *pool) dce_aud_destroy(&pool->base.audios[i]); } + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + dm_free(pool->base.dwbc[i]); + pool->base.dwbc[i] = NULL; + } + for (i = 0; i < pool->base.clk_src_count; i++) { if (pool->base.clock_sources[i] != NULL) { dcn10_clock_source_destroy(&pool->base.clock_sources[i]); -- GitLab From 0045b749bdedc60ca46a7801cb9b5ae967bea669 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 22 Aug 2017 10:29:23 -0400 Subject: [PATCH 0814/2898] drm/amd/display: dc: Remove unneeded includes in DCN Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 69f67f6e27b1..54e37b10ffbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -39,9 +39,6 @@ #include "opp.h" #include "ipp.h" #include "mpc.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -#include "vega10/soc15ip.h" #include "reg_helper.h" #define CTX \ -- GitLab From 4d1501eb65d606c05f28da12539cf0defd111f75 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 21 Aug 2017 11:00:25 -0400 Subject: [PATCH 0815/2898] drm/amd/display: Enable double buffer when unblank crtc. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 6a5f2683c2e5..cc58f43400d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -289,6 +289,9 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); + REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, OTG_BLANK_DE_MODE, 0); -- GitLab From 7fb77c51f3b8e91499b6fd1973804c9230d2d8d3 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sat, 19 Aug 2017 08:55:58 -0400 Subject: [PATCH 0816/2898] drm/amd/display: version 3.1.01 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 035c44e0e7d2..e6cea839d283 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -48,6 +48,9 @@ #include "dm_helpers.h" #include "mem_input.h" + +char dc_ver[] = DC_VER; + /******************************************************************************* * Private functions ******************************************************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bd8b1ba22df8..caf585dbabb3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" - +#define DC_VER "3.1.01" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- GitLab From a0c38ebaa1fe99ea8d112d808d84a2e75194fcf6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 21 Aug 2017 12:59:41 -0400 Subject: [PATCH 0817/2898] drm/amd/display: write dpcd 0x600 to 2 for DP/eDP when powerdown Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 10 +++++++++- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ee9b98472029..0bdd41ca8799 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1977,7 +1977,7 @@ bool dc_link_setup_psr(struct dc_link *link, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) /*skip power down the single pipe since it blocks the cstate*/ if (ASIC_REV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) - psr_context->psr_level.bits.SKIP_SINGLE_OTG_DISABLE = false; + psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; #endif /* SMU will perform additional powerdown sequence. diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 7516c198d13a..8ba61b9b8792 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1147,8 +1147,16 @@ static enum dc_status apply_single_controller_ctx_to_hw( static void power_down_encoders(struct dc *dc) { int i; - + enum connector_id connector_id; for (i = 0; i < dc->link_count; i++) { + connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); + if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || + (connector_id == CONNECTOR_ID_EDP)) { + + if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) + dp_receiver_power_ctrl(dc->links[i], false); + } + dc->links[i]->link_enc->funcs->disable_output( dc->links[i]->link_enc, SIGNAL_TYPE_NONE); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index d710f6e6dc07..ac418fd83894 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -67,5 +67,6 @@ void dce110_fill_display_configs( uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context); +void dp_receiver_power_ctrl(struct dc_link *link, bool on); #endif /* __DC_HWSS_DCE110_H__ */ -- GitLab From 5f06b3cf90d252160352442a789cad410eb6696e Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Sun, 20 Aug 2017 14:25:19 -0400 Subject: [PATCH 0818/2898] drm/amd/display: retire dm_pp_apply_clock_for_voltage_request set dcfclk and fclk req with pp_smu_display_requirement_rv Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 26 +++++++++++-------- .../gpu/drm/amd/display/dc/inc/core_types.h | 8 ++---- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 54e37b10ffbf..20c4164a59d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2550,7 +2550,10 @@ static void dcn10_set_bandwidth( struct validate_context *context, bool decrease_allowed) { - struct dm_pp_clock_for_voltage_req clock; + struct pp_smu_display_requirement_rv *smu_req_cur = + &dc->res_pool->pp_smu_req; + struct pp_smu_display_requirement_rv smu_req = *smu_req_cur; + struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; if (dc->debug.sanity_checks) { verify_allow_pstate_change_high(dc->hwseq); @@ -2569,19 +2572,12 @@ static void dcn10_set_bandwidth( } if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { - clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; - clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; - dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; - context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + smu_req.hard_min_dcefclk_khz = + context->bw.dcn.calc_clk.dcfclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz > dc->current_context->bw.dcn.cur_clk.fclk_khz) { - clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; - clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; - dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz; - context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + smu_req.hard_min_fclk_khz = context->bw.dcn.calc_clk.fclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz > dc->current_context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) { @@ -2590,6 +2586,14 @@ static void dcn10_set_bandwidth( context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; } + + smu_req.display_count = context->stream_count; + + if (pp_smu->set_display_requirement) + pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); + + *smu_req_cur = smu_req; + /* Decrease in freq is increase in period so opposite comparison for dram_ccm */ if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us < dc->current_context->bw.dcn.cur_clk.dram_ccm_us) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 9a3239028377..62bd11d250c5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -132,10 +132,10 @@ struct resource_pool { struct output_pixel_processor *opps[MAX_PIPES]; struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 + struct mpc *mpc; struct pp_smu_funcs_rv *pp_smu; -#endif + struct pp_smu_display_requirement_rv pp_smu_req; struct dwbc *dwbc[MAX_DWB_PIPES]; @@ -234,7 +234,6 @@ struct dce_bw_output { int blackout_recovery_time_us; }; -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct dcn_bw_clocks { int dispclk_khz; bool dppclk_div; @@ -250,12 +249,9 @@ struct dcn_bw_output { struct dcn_bw_clocks calc_clk; struct dcn_watermark_set watermarks; }; -#endif union bw_context { -#ifdef CONFIG_DRM_AMD_DC_DCN1_0 struct dcn_bw_output dcn; -#endif struct dce_bw_output dce; }; -- GitLab From 39902db0343e0e4f335324d22d6707303be24448 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 21 Aug 2017 11:46:17 -0400 Subject: [PATCH 0819/2898] drm/amd/display: Change log level for DCN powergatting Change log level from LOG_DC to LOG_DEBUG LOG_DC spams dmesg on linux when hotpluging Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 20c4164a59d0..bd023299e2af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -772,7 +772,7 @@ static void power_on_plane( hubp_pg_control(hws, plane_id, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - dm_logger_write(hws->ctx->logger, LOG_DC, + dm_logger_write(hws->ctx->logger, LOG_DEBUG, "Un-gated front end for pipe %d\n", plane_id); } @@ -1003,7 +1003,7 @@ static void reset_back_end_for_pipe( return; pipe_ctx->stream = NULL; - dm_logger_write(dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Reset back end for pipe %d, tg:%d\n", pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); } @@ -1096,7 +1096,7 @@ static void plane_atomic_power_down(struct dc *dc, int fe_idx) xfm->funcs->transform_reset(xfm); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Power gated front end %d\n", fe_idx); if (dc->debug.sanity_checks) @@ -1153,7 +1153,7 @@ static void dcn10_power_down_fe(struct dc *dc, int fe_idx) xfm->funcs->transform_reset(xfm); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Power gated front end %d\n", fe_idx); if (dc->debug.sanity_checks) @@ -1921,7 +1921,7 @@ static void dcn10_power_on_fe( /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ if (plane_state) { - dm_logger_write(dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " "src: %d, %d, %d," @@ -1939,7 +1939,7 @@ static void dcn10_power_on_fe( plane_state->dst_rect.width, plane_state->dst_rect.height); - dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE, + dm_logger_write(dc->ctx->logger, LOG_DEBUG, "Pipe %d: width, height, x, y\n" "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", -- GitLab From c25e2d1f8ff403fdb7a82a025ae492d167bbdb99 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 21 Aug 2017 16:43:08 -0400 Subject: [PATCH 0820/2898] drm/amd/display: retry LT on failing LT in automated request [Description] Link training is not retried in automated link training request. In case link training is occasionally failing, there is not way to retry so the requested lane settings will not set. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 3a5abd92036a..23d8b614e0fd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -299,10 +299,11 @@ void dp_retrain_link_dp_test(struct dc_link *link, dp_receiver_power_ctrl(link, true); - dc_link_dp_perform_link_training( + perform_link_training_with_retries( link, link_setting, - skip_video_pattern); + skip_video_pattern, + LINK_TRAINING_ATTEMPTS); link->cur_link_settings = *link_setting; -- GitLab From 83a3d42d121301d26601ef7599052e1d78fde9fb Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 21 Aug 2017 16:28:39 -0400 Subject: [PATCH 0821/2898] drm/amd/display: Remove unneeded code Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 145 ------------------ .../gpu/drm/amd/display/dc/core/dc_resource.c | 73 --------- drivers/gpu/drm/amd/display/dc/dc.h | 71 --------- 3 files changed, 289 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e6cea839d283..ab2b8f23b20a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -670,67 +670,6 @@ void dc_destroy(struct dc **dc) *dc = NULL; } -static bool validate_streams ( - struct dc *dc, - const struct dc_validation_set set[], - int set_count) -{ - int i; - - for (i = 0; i < set_count; i++) - if (!dc_validate_stream(dc, set[i].stream)) - return false; - - return true; -} - -static bool validate_surfaces( - struct dc *dc, - const struct dc_validation_set set[], - int set_count) -{ - int i, j; - - for (i = 0; i < set_count; i++) - for (j = 0; j < set[i].plane_count; j++) - if (!dc_validate_plane(dc, set[i].plane_states[j])) - return false; - - return true; -} - -bool dc_validate_resources( - struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count) -{ - bool result = false; - struct validate_context *context; - - if (!validate_streams(dc, set, set_count)) - return false; - - if (!validate_surfaces(dc, set, set_count)) - return false; - - context = dm_alloc(sizeof(struct validate_context)); - if (context == NULL) - goto context_alloc_fail; - - atomic_inc(&context->ref_count); - - dc_resource_validate_ctx_copy_construct_current(dc, context); - - result = dc_validate_with_context( - dc, set, set_count, context); - -context_alloc_fail: - dc_release_validate_context(context); - context = NULL; - - return result; -} - bool dc_validate_guaranteed( struct dc *dc, struct dc_stream_state *stream) @@ -855,24 +794,6 @@ static bool context_changed( return false; } -static bool streams_changed( - struct dc *dc, - struct dc_stream_state *streams[], - uint8_t stream_count) -{ - uint8_t i; - - if (stream_count != dc->current_context->stream_count) - return true; - - for (i = 0; i < dc->current_context->stream_count; i++) { - if (dc->current_context->streams[i] != streams[i]) - return true; - } - - return false; -} - bool dc_enable_stereo( struct dc *dc, struct validate_context *context, @@ -997,72 +918,6 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) } -bool dc_commit_streams( - struct dc *dc, - struct dc_stream_state *streams[], - uint8_t stream_count) -{ - struct dc *core_dc = dc; - bool result = false; - struct validate_context *context; - struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } }; - int i; - - if (false == streams_changed(core_dc, streams, stream_count)) - return DC_OK; - - dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", - __func__, stream_count); - - for (i = 0; i < stream_count; i++) { - struct dc_stream_state *stream = streams[i]; - struct dc_stream_status *status = dc_stream_get_status(stream); - int j; - - dc_stream_log(stream, - core_dc->ctx->logger, - LOG_DC); - - set[i].stream = stream; - - if (status) { - set[i].plane_count = status->plane_count; - for (j = 0; j < status->plane_count; j++) - set[i].plane_states[j] = status->plane_states[j]; - } - - } - - if (!validate_streams(dc, set, stream_count)) - return false; - - if (!validate_surfaces(dc, set, stream_count)) - return false; - - context = dm_alloc(sizeof(struct validate_context)); - if (context == NULL) - goto context_alloc_fail; - - atomic_inc(&context->ref_count); - - dc_resource_validate_ctx_copy_construct_current(dc, context); - - result = dc_validate_with_context( - dc, set, stream_count, context); - if (!result) { - BREAK_TO_DEBUGGER(); - goto fail; - } - - result = dc_commit_context_no_check(dc, context); - -fail: - dc_release_validate_context(context); - -context_alloc_fail: - return result; -} - bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f640986c6fd2..428863bccab6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1633,79 +1633,6 @@ void dc_resource_validate_ctx_copy_construct_current( dc_resource_validate_ctx_copy_construct(dc->current_context, dst_ctx); } -bool dc_validate_with_context( - struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context) -{ - int i, j; - enum dc_status res = DC_ERROR_UNEXPECTED; - bool found = false; - int old_stream_count = context->stream_count; - struct dc_stream_state *del_streams[MAX_PIPES] = { 0 }; - struct dc_stream_state *add_streams[MAX_PIPES] = { 0 }; - int del_streams_count = 0; - int add_streams_count = 0; - - - /* First remove from context all deleted streams */ - for (i = 0; i < old_stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - for (j = 0; j < set_count; j++) { - if (stream == set[j].stream) { - found = true; - break; - } - } - - if (!found) - del_streams[del_streams_count++] = stream; - - found = false; - } - - /* Now add new ones */ - for (i = 0; i < set_count; i++) { - struct dc_stream_state *stream = set[i].stream; - - for (j = 0; j < old_stream_count; j++) { - if (stream == context->streams[j]) { - found = true; - break; - } - } - - if (!found) - add_streams[add_streams_count++] = stream; - - found = false; - } - - for (i = 0; i < del_streams_count; i++) - if (!dc_remove_stream_from_ctx(dc, context, del_streams[i])) - goto fail; - - for (i = 0; i < add_streams_count; i++) - if (!dc_add_stream_to_ctx(dc, context, add_streams[i])) - goto fail; - - if (!dc_validate_global_state(dc, set, set_count, context)) - goto fail; - - res = DC_OK; - -fail: - if (res != DC_OK) { - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "%s:resource validation failed, dc_status:%d\n", - __func__, - res); -} - return res == DC_OK; -} - bool dc_validate_global_state( struct dc *dc, const struct dc_validation_set set[], diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index caf585dbabb3..0f2a16a0cf82 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -641,23 +641,12 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); -bool dc_validate_with_context( - struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *context); - bool dc_validate_global_state( struct dc *dc, const struct dc_validation_set set[], int set_count, struct validate_context *new_ctx); -bool dc_validate_resources( - struct dc *dc, - const struct dc_validation_set set[], - uint8_t set_count); - /* * This function takes a stream and checks if it is guaranteed to be supported. * Guaranteed means that MAX_COFUNC similar streams are supported. @@ -666,10 +655,6 @@ bool dc_validate_resources( * No hardware is programmed for call. Only validation is done. */ -bool dc_validate_guaranteed( - struct dc *dc, - struct dc_stream_state *stream); - void dc_resource_validate_ctx_copy_construct( const struct validate_context *src_ctx, struct validate_context *dst_ctx); @@ -699,10 +684,6 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context); * Phy, Encoder, Timing Generator are programmed and enabled. * New streams are enabled with blank stream; no memory read. */ -bool dc_commit_streams( - struct dc *dc, - struct dc_stream_state *streams[], - uint8_t stream_count); /* * Enable stereo when commit_streams is not required, * for example, frame alternate. @@ -857,18 +838,10 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); */ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); -struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe); - -/* Return id of physical connector represented by a dc_link at link_index.*/ -const struct graphics_object_id dc_get_link_id_at_index( - struct dc *dc, uint32_t link_index); - /* Set backlight level of an embedded panel (eDP, LVDS). */ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream_state *stream); -bool dc_link_set_abm_disable(const struct dc_link *dc_link); - bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); @@ -907,7 +880,6 @@ void dc_link_remove_remote_sink( struct dc_sink *sink); /* Used by diagnostics for virtual link at the moment */ -void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink); void dc_link_dp_set_drive_settings( struct dc_link *link, @@ -970,8 +942,6 @@ struct dc_sink { void dc_sink_retain(struct dc_sink *sink); void dc_sink_release(struct dc_sink *sink); -const struct audio **dc_get_audios(struct dc *dc); - struct dc_sink_init_data { enum signal_type sink_signal; struct dc_link *link; @@ -980,8 +950,6 @@ struct dc_sink_init_data { }; struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); -bool dc_sink_get_container_id(struct dc_sink *dc_sink, struct dc_container_id *container_id); -bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container_id *container_id); /******************************************************************************* * Cursor interfaces - To manages the cursor within a stream @@ -1026,45 +994,6 @@ void dc_resume(struct dc *dc); * DPCD access interfaces */ -bool dc_read_aux_dpcd( - struct dc *dc, - uint32_t link_index, - uint32_t address, - uint8_t *data, - uint32_t size); - -bool dc_write_aux_dpcd( - struct dc *dc, - uint32_t link_index, - uint32_t address, - const uint8_t *data, - uint32_t size); - -bool dc_read_aux_i2c( - struct dc *dc, - uint32_t link_index, - enum i2c_mot_mode mot, - uint32_t address, - uint8_t *data, - uint32_t size); - -bool dc_write_aux_i2c( - struct dc *dc, - uint32_t link_index, - enum i2c_mot_mode mot, - uint32_t address, - const uint8_t *data, - uint32_t size); - -bool dc_query_ddc_data( - struct dc *dc, - uint32_t link_index, - uint32_t address, - uint8_t *write_buf, - uint32_t write_size, - uint8_t *read_buf, - uint32_t read_size); - bool dc_submit_i2c( struct dc *dc, uint32_t link_index, -- GitLab From ae5baf7a1047eece4ff87469ae85a45b5ddf6aa3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 22 Aug 2017 10:29:40 -0400 Subject: [PATCH 0822/2898] drm/amd/display: Remove old, misleading comment Signed-off-by: Harry Wentland Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index d6225f332431..56e3b124f19c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -31,7 +31,6 @@ #include "dce110/dce110_hw_sequencer.h" -/* include DCE12.0 register header files */ #include "vega10/DC/dce_12_0_offset.h" #include "vega10/DC/dce_12_0_sh_mask.h" #include "vega10/soc15ip.h" -- GitLab From 67a72b6944446f68b9a930c13c8cdadba72beed8 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 22 Aug 2017 09:35:41 -0400 Subject: [PATCH 0823/2898] drm/amd/display: Stop including atomfimrwareid.h directly It's already included in atomfirmware.h Signed-off-by: Harry Wentland Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 1 - drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 1 - drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index f8d4f08bf985..95fe50f62c57 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -29,7 +29,6 @@ #include "ObjectID.h" #include "atomfirmware.h" -#include "atomfirmwareid.h" #include "dc_bios_types.h" #include "include/grph_object_ctrl_defs.h" diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index e33e6bfccb6d..64eab356d336 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -27,7 +27,6 @@ #include "ObjectID.h" #include "atomfirmware.h" -#include "atomfirmwareid.h" #include "include/bios_parser_interface.h" diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 35c3f3a8e493..9a4d30dd4969 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -27,7 +27,6 @@ #include "ObjectID.h" #include "atomfirmware.h" -#include "atomfirmwareid.h" #include "include/bios_parser_types.h" -- GitLab From aaa15026f273c184454ea8672274a682bc161da1 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Tue, 22 Aug 2017 15:49:57 -0400 Subject: [PATCH 0824/2898] drm/amd/display: Fix return value from rx irq handler on up request Signed-off-by: Wenjing Liu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e35bdce6a0f3..e19447d526ea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1964,11 +1964,11 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd * so do not handle as a normal sink status change interrupt. */ + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) + return true; + /* check if we have MST msg and return since we poll for it */ - if (hpd_irq_dpcd_data.bytes.device_service_irq. - bits.DOWN_REP_MSG_RDY || - hpd_irq_dpcd_data.bytes.device_service_irq. - bits.UP_REQ_MSG_RDY) + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) return false; /* For now we only handle 'Downstream port status' case. -- GitLab From 0f0bdca5cae04ec2f842955bcef16a3daed6149f Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Tue, 22 Aug 2017 18:42:51 -0400 Subject: [PATCH 0825/2898] drm/amd/display: Safe stream encoder id in stream_status Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 428863bccab6..fbfe15f783c0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1599,6 +1599,7 @@ enum dc_status resource_map_pool_resources( for (i = 0; i < context->stream_count; i++) if (context->streams[i] == stream) { context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; + context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->id; return DC_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0f2a16a0cf82..9cc1c28caa4e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -510,6 +510,7 @@ enum surface_update_type { struct dc_stream_status { int primary_otg_inst; + int stream_enc_inst; int plane_count; struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; -- GitLab From 577b5c2b51014b3c276ab1d456aaad965dbb4930 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Tue, 22 Aug 2017 20:15:28 -0400 Subject: [PATCH 0826/2898] drm/amd/display: Block 6Ghz timing if SBIOS set HDMI_6G_en to 0 Signed-off-by: Charlene Liu Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 1 + 3 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 2c683d468bb8..2c411441771b 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -1853,6 +1853,7 @@ static enum bp_result bios_parser_get_encoder_cap_info( info->DP_HBR2_EN = record->usHBR2En; info->DP_HBR3_EN = record->usHBR3En; + info->HDMI_6GB_EN = record->usHDMI6GEn; return BP_RESULT_OK; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 559a9f81c9c9..0ce94ede80bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -887,6 +887,9 @@ static bool dce110_link_encoder_validate_hdmi_output( crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) return false; + if (!enc110->base.features.flags.bits.HDMI_6GB_EN && + adjusted_pix_clk_khz >= 300000) + return false; return true; } @@ -1008,6 +1011,7 @@ bool dce110_link_encoder_construct( bp_cap_info.DP_HBR2_EN; enc110->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; + enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; } return true; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 38e4070806cb..961bbcc9202c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -37,6 +37,7 @@ struct encoder_feature_support { uint32_t IS_TPS3_CAPABLE:1; uint32_t IS_TPS4_CAPABLE:1; uint32_t IS_YCBCR_CAPABLE:1; + uint32_t HDMI_6GB_EN:1; } bits; uint32_t raw; } flags; -- GitLab From 19f89e2392e692208a0a00465d30b2b2bf43e9a9 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 11 Aug 2017 10:43:45 -0400 Subject: [PATCH 0827/2898] drm/amd/display: Per plane validation context build. Introduce add/remove plane to/from context. Make DC wrapper to use them in WIndows/Diags. Use them in dc_update_surface_to_stream. Call add/remove plane from Linux DM. Remove dc_validation_set from dc_validate_global_state interface and by this remove clean Linux DM from using it. Signed-off-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 165 +++----- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 362 +++++++++++------- drivers/gpu/drm/amd/display/dc/dc.h | 37 +- .../amd/display/dc/dce100/dce100_resource.c | 16 +- .../amd/display/dc/dce110/dce110_resource.c | 26 +- .../amd/display/dc/dce112/dce112_resource.c | 16 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 16 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 - 9 files changed, 353 insertions(+), 300 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e037ed85a5cc..e8835e751702 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4304,77 +4304,6 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector dm_force_atomic_commit(&aconnector->base); } -static uint32_t add_val_sets_plane( - struct dc_validation_set *val_sets, - uint32_t set_count, - const struct dc_stream_state *stream, - struct dc_plane_state *plane_state) -{ - uint32_t i = 0, j = 0; - - while (i < set_count) { - if (val_sets[i].stream == stream) { - while (val_sets[i].plane_states[j]) - j++; - break; - } - ++i; - } - - val_sets[i].plane_states[j] = plane_state; - val_sets[i].plane_count++; - - return val_sets[i].plane_count; -} - -static uint32_t update_in_val_sets_stream( - struct dc_validation_set *val_sets, - uint32_t set_count, - struct dc_stream_state *old_stream, - struct dc_stream_state *new_stream, - struct drm_crtc *crtc) -{ - uint32_t i = 0; - - while (i < set_count) { - if (val_sets[i].stream == old_stream) - break; - ++i; - } - - val_sets[i].stream = new_stream; - - if (i == set_count) - /* nothing found. add new one to the end */ - return set_count + 1; - - return set_count; -} - -static uint32_t remove_from_val_sets( - struct dc_validation_set *val_sets, - uint32_t set_count, - const struct dc_stream_state *stream) -{ - int i; - - for (i = 0; i < set_count; i++) - if (val_sets[i].stream == stream) - break; - - if (i == set_count) { - /* nothing found */ - return set_count; - } - - set_count--; - - for (; i < set_count; i++) - val_sets[i] = val_sets[i + 1]; - - return set_count; -} - /*` * Grabs all modesetting locks to serialize against any blocking commits, * Waits for completion of all non blocking commits. @@ -4438,10 +4367,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; struct drm_connector *connector; struct drm_connector_state *conn_state; - int set_count; - struct dc_validation_set set[MAX_STREAMS] = { { 0 } }; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + bool pflip_needed = !state->allow_modeset; /* * This bool will be set for true for any modeset/reset @@ -4460,16 +4388,44 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ASSERT(dm_state->context); dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); - /* copy existing configuration */ - set_count = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + /* Remove exiting planes if they are disabled or their CRTC is updated */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + new_acrtc_state = to_dm_crtc_state(crtc_state); - old_acrtc_state = to_dm_crtc_state(crtc->state); + if (pflip_needed) + continue; - if (old_acrtc_state->stream) { - dc_stream_retain(old_acrtc_state->stream); - set[set_count].stream = old_acrtc_state->stream; - ++set_count; + for_each_plane_in_state(state, plane, plane_state, j) { + struct drm_crtc *plane_crtc = plane_state->crtc; + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + + if (crtc != plane_crtc || !dm_plane_state->dc_state) + continue; + + WARN_ON(!new_acrtc_state->stream); + + if (drm_atomic_plane_disabling(plane->state, plane_state) || + drm_atomic_crtc_needs_modeset(crtc_state)) { + if (!dc_remove_plane_from_context( + dc, + new_acrtc_state->stream, + dm_plane_state->dc_state, + dm_state->context)) { + + ret = EINVAL; + goto fail; + } + + } + + dc_plane_state_release(dm_plane_state->dc_state); + dm_plane_state->dc_state = NULL; + + DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n", + plane->base.id, crtc->base.id); } } @@ -4513,11 +4469,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; } - set_count = remove_from_val_sets( - set, - set_count, - new_acrtc_state->stream); - dc_stream_release(new_acrtc_state->stream); new_acrtc_state->stream = NULL; @@ -4576,13 +4527,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, new_acrtc_state->stream = new_stream; - set_count = update_in_val_sets_stream( - set, - set_count, - old_acrtc_state->stream, - new_acrtc_state->stream, - crtc); - if (!dc_add_stream_to_ctx( dc, dm_state->context, @@ -4639,32 +4583,32 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, lock_and_validation_needed = true; } + /* Add new planes */ for_each_crtc_in_state(state, crtc, crtc_state, i) { new_acrtc_state = to_dm_crtc_state(crtc_state); + if (pflip_needed) + continue; + for_each_plane_in_state(state, plane, plane_state, j) { struct drm_crtc *plane_crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; - bool pflip_needed; struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); /*TODO Implement atomic check for cursor plane */ if (plane->type == DRM_PLANE_TYPE_CURSOR) continue; - if (!fb || !plane_crtc || crtc != plane_crtc || !crtc_state->active) + if (crtc != plane_crtc) continue; - WARN_ON(!new_acrtc_state->stream); - - pflip_needed = !state->allow_modeset; - if (!pflip_needed) { + if (!drm_atomic_plane_disabling(plane->state, plane_state)) { struct dc_plane_state *dc_plane_state; + WARN_ON(!new_acrtc_state->stream); + dc_plane_state = dc_create_plane_state(dc); - if (dm_plane_state->dc_state) - dc_plane_state_release(dm_plane_state->dc_state); + WARN_ON(dm_plane_state->dc_state); dm_plane_state->dc_state = dc_plane_state; @@ -4677,10 +4621,17 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - add_val_sets_plane(set, - set_count, - new_acrtc_state->stream, - dc_plane_state); + + if (!dc_add_plane_to_context( + dc, + new_acrtc_state->stream, + dc_plane_state, + dm_state->context)) { + + ret = EINVAL; + goto fail; + } + lock_and_validation_needed = true; } @@ -4708,7 +4659,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - if (!dc_validate_global_state(dc, set, set_count, dm_state->context)) { + if (!dc_validate_global_state(dc, dm_state->context)) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ab2b8f23b20a..79980cb0900c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1305,10 +1305,16 @@ void dc_update_planes_and_stream(struct dc *dc, dc_resource_validate_ctx_copy_construct( core_dc->current_context, context); + /*remove old surfaces from context */ + if (!dc_rem_all_planes_for_stream(dc, stream, context)) { + + BREAK_TO_DEBUGGER(); + goto fail; + } + /* add surface to context */ - if (!resource_attach_surfaces_to_context( - new_planes, surface_count, stream, - context, core_dc->res_pool)) { + if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { + BREAK_TO_DEBUGGER(); goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fbfe15f783c0..6eee1b1a563e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -946,6 +946,26 @@ struct pipe_ctx *resource_get_head_pipe_for_stream( return NULL; } +static struct pipe_ctx *resource_get_tail_pipe_for_stream( + struct resource_context *res_ctx, + struct dc_stream_state *stream) +{ + struct pipe_ctx *head_pipe, *tail_pipe; + head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream); + + if (!head_pipe) + return NULL; + + tail_pipe = head_pipe->bottom_pipe; + + while (tail_pipe) { + head_pipe = tail_pipe; + tail_pipe = tail_pipe->bottom_pipe; + } + + return head_pipe; +} + /* * A free_pipe for a stream is defined here as a pipe * that has no surface attached yet @@ -990,22 +1010,6 @@ static struct pipe_ctx *acquire_free_pipe_for_stream( } -static void release_free_pipes_for_stream( - struct resource_context *res_ctx, - struct dc_stream_state *stream) -{ - int i; - - for (i = MAX_PIPES - 1; i >= 0; i--) { - /* never release the topmost pipe*/ - if (res_ctx->pipe_ctx[i].stream == stream && - res_ctx->pipe_ctx[i].top_pipe && - !res_ctx->pipe_ctx[i].plane_state) { - memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx)); - } - } -} - #if defined(CONFIG_DRM_AMD_DC_DCN1_0) static int acquire_first_split_pipe( struct resource_context *res_ctx, @@ -1040,96 +1044,235 @@ static int acquire_first_split_pipe( } #endif -bool resource_attach_surfaces_to_context( - struct dc_plane_state * const *plane_states, - int surface_count, +bool dc_add_plane_to_context( + const struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context, - const struct resource_pool *pool) + struct dc_plane_state *plane_state, + struct validate_context *context) { int i; - struct pipe_ctx *tail_pipe; + struct resource_pool *pool = dc->res_pool; + struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; struct dc_stream_status *stream_status = NULL; + for (i = 0; i < context->stream_count; i++) + if (context->streams[i] == stream) { + stream_status = &context->stream_status[i]; + break; + } + if (stream_status == NULL) { + dm_error("Existing stream not found; failed to attach surface!\n"); + return false; + } + + + if (stream_status->plane_count == MAX_SURFACE_NUM) { + dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", + plane_state, MAX_SURFACE_NUM); + return false; + } + + head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); + + if (!head_pipe) { + dm_error("Head pipe not found for stream_state %p !\n", stream); + return false; + } + + /* retain new surfaces */ + dc_plane_state_retain(plane_state); + + free_pipe = acquire_free_pipe_for_stream(context, pool, stream); - if (surface_count > MAX_SURFACE_NUM) { - dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n", - surface_count, MAX_SURFACE_NUM); +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) + if (!free_pipe) { + int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); + if (pipe_idx >= 0) + free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; + } +#endif + if (!free_pipe) { + stream_status->plane_states[i] = NULL; return false; } + free_pipe->plane_state = plane_state; + + if (head_pipe != free_pipe) { + + tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream); + ASSERT(tail_pipe); + + free_pipe->stream_res.tg = tail_pipe->stream_res.tg; + free_pipe->stream_res.opp = tail_pipe->stream_res.opp; + free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; + free_pipe->stream_res.audio = tail_pipe->stream_res.audio; + free_pipe->clock_source = tail_pipe->clock_source; + free_pipe->top_pipe = tail_pipe; + tail_pipe->bottom_pipe = free_pipe; + } + + /* assign new surfaces*/ + stream_status->plane_states[stream_status->plane_count] = plane_state; + + stream_status->plane_count++; + + return true; +} + +bool dc_remove_plane_from_context( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state *plane_state, + struct validate_context *context) +{ + int i; + struct dc_stream_status *stream_status = NULL; + struct resource_pool *pool = dc->res_pool; + for (i = 0; i < context->stream_count; i++) if (context->streams[i] == stream) { stream_status = &context->stream_status[i]; break; } + if (stream_status == NULL) { - dm_error("Existing stream not found; failed to attach surfaces\n"); + dm_error("Existing stream not found; failed to remove plane.\n"); return false; } - /* retain new surfaces */ - for (i = 0; i < surface_count; i++) - dc_plane_state_retain(plane_states[i]); - - /* detach surfaces from pipes */ - for (i = 0; i < pool->pipe_count; i++) - if (context->res_ctx.pipe_ctx[i].stream == stream) { - context->res_ctx.pipe_ctx[i].plane_state = NULL; - context->res_ctx.pipe_ctx[i].bottom_pipe = NULL; - } + /* release pipe for plane*/ + for (i = pool->pipe_count - 1; i >= 0; i--) { + struct pipe_ctx *pipe_ctx; - /* release existing surfaces*/ - for (i = 0; i < stream_status->plane_count; i++) - dc_plane_state_release(stream_status->plane_states[i]); + if (context->res_ctx.pipe_ctx[i].plane_state == plane_state) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; - for (i = surface_count; i < stream_status->plane_count; i++) - stream_status->plane_states[i] = NULL; + if (pipe_ctx->top_pipe) + pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; - tail_pipe = NULL; - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *plane_state = plane_states[i]; - struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream( - context, pool, stream); + /* Second condition is to avoid setting NULL to top pipe + * of tail pipe making it look like head pipe in subsequent + * deletes + */ + if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) + pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (!free_pipe) { - int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); - if (pipe_idx >= 0) - free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; - } -#endif - if (!free_pipe) { - stream_status->plane_states[i] = NULL; - return false; + /* + * For head pipe detach surfaces from pipe for tail + * pipe just zero it out + */ + if (!pipe_ctx->top_pipe) { + pipe_ctx->plane_state = NULL; + pipe_ctx->bottom_pipe = NULL; + } else { + memset(pipe_ctx, 0, sizeof(*pipe_ctx)); + } } + } + - free_pipe->plane_state = plane_state; + for (i = 0; i < stream_status->plane_count; i++) { + if (stream_status->plane_states[i] == plane_state) { - if (tail_pipe) { - free_pipe->stream_res.tg = tail_pipe->stream_res.tg; - free_pipe->stream_res.opp = tail_pipe->stream_res.opp; - free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; - free_pipe->stream_res.audio = tail_pipe->stream_res.audio; - free_pipe->clock_source = tail_pipe->clock_source; - free_pipe->top_pipe = tail_pipe; - tail_pipe->bottom_pipe = free_pipe; + dc_plane_state_release(stream_status->plane_states[i]); + break; } + } - tail_pipe = free_pipe; + if (i == stream_status->plane_count) { + dm_error("Existing plane_state not found; failed to detach it!\n"); + return false; } - release_free_pipes_for_stream(&context->res_ctx, stream); + stream_status->plane_count--; - /* assign new surfaces*/ - for (i = 0; i < surface_count; i++) - stream_status->plane_states[i] = plane_states[i]; + /* Trim back arrays */ + for (i = 0; i < stream_status->plane_count; i++) + stream_status->plane_states[i] = stream_status->plane_states[i + 1]; + + stream_status->plane_states[stream_status->plane_count] = NULL; + + return true; +} + +bool dc_rem_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct validate_context *context) +{ + int i, old_plane_count; + struct dc_stream_status *stream_status = NULL; + struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; + + for (i = 0; i < context->stream_count; i++) + if (context->streams[i] == stream) { + stream_status = &context->stream_status[i]; + break; + } + + if (stream_status == NULL) { + dm_error("Existing stream %p not found!\n", stream); + return false; + } + + old_plane_count = stream_status->plane_count; - stream_status->plane_count = surface_count; + for (i = 0; i < old_plane_count; i++) + del_planes[i] = stream_status->plane_states[i]; + + for (i = 0; i < old_plane_count; i++) + if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) + return false; return true; } +static bool add_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + const struct dc_validation_set set[], + int set_count, + struct validate_context *context) +{ + int i, j; + + for (i = 0; i < set_count; i++) + if (set[i].stream == stream) + break; + + if (i == set_count) { + dm_error("Stream %p not found in set!\n", stream); + return false; + } + + for (j = 0; j < set[i].plane_count; j++) + if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) + return false; + + return true; +} + +bool dc_add_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state * const *plane_states, + int plane_count, + struct validate_context *context) +{ + struct dc_validation_set set; + int i; + + set.stream = stream; + set.plane_count = plane_count; + + for (i = 0; i < plane_count; i++) + set.plane_states[i] = plane_states[i]; + + return add_all_planes_for_stream(dc, stream, &set, 1, context); +} + + static bool is_timing_changed(struct dc_stream_state *cur_stream, struct dc_stream_state *new_stream) @@ -1178,41 +1321,6 @@ bool dc_is_stream_unchanged( return true; } -bool resource_validate_attach_surfaces( - const struct dc_validation_set set[], - int set_count, - const struct validate_context *old_context, - struct validate_context *context, - const struct resource_pool *pool) -{ - int i, j; - - for (i = 0; i < set_count; i++) { - for (j = 0; old_context && j < old_context->stream_count; j++) - if (dc_is_stream_unchanged( - old_context->streams[j], - context->streams[i])) { - if (!resource_attach_surfaces_to_context( - old_context->stream_status[j].plane_states, - old_context->stream_status[j].plane_count, - context->streams[i], - context, pool)) - return false; - context->stream_status[i] = old_context->stream_status[j]; - } - if (set[i].plane_count != 0) - if (!resource_attach_surfaces_to_context( - set[i].plane_states, - set[i].plane_count, - context->streams[i], - context, pool)) - return false; - - } - - return true; -} - /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 @@ -1392,23 +1500,22 @@ bool dc_remove_stream_from_ctx( struct validate_context *new_ctx, struct dc_stream_state *stream) { - int i, j; + int i; struct dc_context *dc_ctx = dc->ctx; struct pipe_ctx *del_pipe = NULL; - /*TODO MPO to remove extra pipe or in surface remove ?*/ - - /* Release primary and secondary pipe (if exsist) */ + /* Release primary pipe */ for (i = 0; i < MAX_PIPES; i++) { - if (new_ctx->res_ctx.pipe_ctx[i].stream == stream) { + if (new_ctx->res_ctx.pipe_ctx[i].stream == stream && + !new_ctx->res_ctx.pipe_ctx[i].top_pipe) { del_pipe = &new_ctx->res_ctx.pipe_ctx[i]; - if (del_pipe->stream_res.stream_enc) - update_stream_engine_usage( - &new_ctx->res_ctx, + ASSERT(del_pipe->stream_res.stream_enc); + update_stream_engine_usage( + &new_ctx->res_ctx, dc->res_pool, - del_pipe->stream_res.stream_enc, - false); + del_pipe->stream_res.stream_enc, + false); if (del_pipe->stream_res.audio) update_audio_usage( @@ -1418,6 +1525,8 @@ bool dc_remove_stream_from_ctx( false); memset(del_pipe, 0, sizeof(*del_pipe)); + + break; } } @@ -1438,10 +1547,6 @@ bool dc_remove_stream_from_ctx( dc_stream_release(new_ctx->streams[i]); new_ctx->stream_count--; - /*TODO move into dc_remove_surface_from_ctx ?*/ - for (j = 0; j < new_ctx->stream_status[i].plane_count; j++) - dc_plane_state_release(new_ctx->stream_status[i].plane_states[j]); - /* Trim back arrays */ for (; i < new_ctx->stream_count; i++) { new_ctx->streams[i] = new_ctx->streams[i + 1]; @@ -1636,18 +1741,14 @@ void dc_resource_validate_ctx_copy_construct_current( bool dc_validate_global_state( struct dc *dc, - const struct dc_validation_set set[], - int set_count, struct validate_context *new_ctx) { enum dc_status result = DC_ERROR_UNEXPECTED; - struct dc_context *dc_ctx = dc->ctx; - struct validate_context *old_context = dc->current_context; int i, j; if (dc->res_pool->funcs->validate_global && - dc->res_pool->funcs->validate_global(dc, set, set_count, - old_context, new_ctx) != DC_OK) + dc->res_pool->funcs->validate_global( + dc, new_ctx) != DC_OK) return false; /* TODO without this SWDEV-114774 brakes */ @@ -1687,15 +1788,6 @@ bool dc_validate_global_state( } } - /*TODO This should be ok */ - /* Split pipe resource, do not acquire back end */ - - if (!resource_validate_attach_surfaces( - set, set_count, old_context, new_ctx, dc->res_pool)) { - DC_ERROR("Failed to attach surface to stream!\n"); - return DC_FAIL_ATTACH_SURFACES; - } - result = resource_build_scaling_params_for_context(dc, new_ctx); if (result == DC_OK) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9cc1c28caa4e..55fc58102515 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -619,15 +619,40 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *h_position, uint32_t *v_position); -bool dc_remove_stream_from_ctx( +bool dc_add_stream_to_ctx( struct dc *dc, + struct validate_context *new_ctx, + struct dc_stream_state *stream); + +bool dc_remove_stream_from_ctx( + struct dc *dc, struct validate_context *new_ctx, struct dc_stream_state *stream); -bool dc_add_stream_to_ctx( - struct dc *dc, - struct validate_context *new_ctx, - struct dc_stream_state *stream); + +bool dc_add_plane_to_context( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state *plane_state, + struct validate_context *context); + +bool dc_remove_plane_from_context( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state *plane_state, + struct validate_context *context); + +bool dc_rem_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct validate_context *context); + +bool dc_add_all_planes_for_stream( + const struct dc *dc, + struct dc_stream_state *stream, + struct dc_plane_state * const *plane_states, + int plane_count, + struct validate_context *context); /* * Structure to store surface/stream associations for validation @@ -644,8 +669,6 @@ bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); bool dc_validate_global_state( struct dc *dc, - const struct dc_validation_set set[], - int set_count, struct validate_context *new_ctx); /* diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c9dad4e2a7c8..c991610315b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -684,19 +684,18 @@ bool dce100_validate_bandwidth( } static bool dce100_validate_surface_sets( - const struct dc_validation_set set[], - int set_count) + struct validate_context *context) { int i; - for (i = 0; i < set_count; i++) { - if (set[i].plane_count == 0) + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) continue; - if (set[i].plane_count > 1) + if (context->stream_status[i].plane_count > 1) return false; - if (set[i].plane_states[0]->format + if (context->stream_status[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -706,12 +705,9 @@ static bool dce100_validate_surface_sets( enum dc_status dce100_validate_global( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context) { - if (!dce100_validate_surface_sets(set, set_count)) + if (!dce100_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index d682180f2eaf..18c67f89e9b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -880,31 +880,30 @@ static bool dce110_validate_bandwidth( } static bool dce110_validate_surface_sets( - const struct dc_validation_set set[], - int set_count) + struct validate_context *context) { int i; - for (i = 0; i < set_count; i++) { - if (set[i].plane_count == 0) + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) continue; - if (set[i].plane_count > 2) + if (context->stream_status[i].plane_count > 2) return false; - if (set[i].plane_states[0]->format + if (context->stream_status[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; - if (set[i].plane_count == 2) { - if (set[i].plane_states[1]->format + if (context->stream_status[i].plane_count == 2) { + if (context->stream_status[i].plane_states[1]->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; - if (set[i].plane_states[1]->src_rect.width > 1920 - || set[i].plane_states[1]->src_rect.height > 1080) + if (context->stream_status[i].plane_states[1]->src_rect.width > 1920 + || context->stream_status[i].plane_states[1]->src_rect.height > 1080) return false; - if (set[i].stream->timing.pixel_encoding != PIXEL_ENCODING_RGB) + if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) return false; } } @@ -914,12 +913,9 @@ static bool dce110_validate_surface_sets( enum dc_status dce110_validate_global( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context) { - if (!dce110_validate_surface_sets(set, set_count)) + if (!dce110_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 85a396ef5aa5..d5a8ee69171d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -855,19 +855,18 @@ enum dc_status resource_map_phy_clock_resources( } static bool dce112_validate_surface_sets( - const struct dc_validation_set set[], - int set_count) + struct validate_context *context) { int i; - for (i = 0; i < set_count; i++) { - if (set[i].plane_count == 0) + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) continue; - if (set[i].plane_count > 1) + if (context->stream_status[i].plane_count > 1) return false; - if (set[i].plane_states[0]->format + if (context->stream_status[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -928,12 +927,9 @@ enum dc_status dce112_validate_guaranteed( enum dc_status dce112_validate_global( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context) { - if (!dce112_validate_surface_sets(set, set_count)) + if (!dce112_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index ac3f42a44030..945ff7ee6cd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -716,19 +716,18 @@ bool dce80_validate_bandwidth( } static bool dce80_validate_surface_sets( - const struct dc_validation_set set[], - int set_count) + struct validate_context *context) { int i; - for (i = 0; i < set_count; i++) { - if (set[i].plane_count == 0) + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) continue; - if (set[i].plane_count > 1) + if (context->stream_status[i].plane_count > 1) return false; - if (set[i].plane_states[0]->format + if (context->stream_status[i].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) return false; } @@ -738,12 +737,9 @@ static bool dce80_validate_surface_sets( enum dc_status dce80_validate_global( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context) { - if (!dce80_validate_surface_sets(set, set_count)) + if (!dce80_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 62bd11d250c5..bd1a6367872f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -99,9 +99,6 @@ struct resource_funcs { enum dc_status (*validate_global)( struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct validate_context *old_context, struct validate_context *context); struct pipe_ctx *(*acquire_idle_pipe_for_layer)( -- GitLab From 62f555377f972c206c69c6acc93d91f2baec9a26 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 18 Aug 2017 10:52:20 -0400 Subject: [PATCH 0828/2898] drm/amd/display: Refactor atomic check. Split into update crtcs and update plane functions. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 462 ++++++++++-------- 1 file changed, 261 insertions(+), 201 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e8835e751702..193a634f46e6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1640,12 +1640,6 @@ static bool modeset_required(struct drm_crtc_state *crtc_state, struct dc_stream_state *new_stream, struct dc_stream_state *old_stream) { - if (dc_is_stream_unchanged(new_stream, old_stream)) { - crtc_state->mode_changed = false; - DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d", - crtc_state->mode_changed); - } - if (!drm_atomic_crtc_needs_modeset(crtc_state)) return false; @@ -3875,9 +3869,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, continue; } - if (!fb || !crtc || pcrtc != crtc || !crtc->state->active || - (!crtc->state->planes_changed && - !pcrtc->state->color_mgmt_changed)) + if (!fb || !crtc || pcrtc != crtc || !crtc->state->active) continue; pflip_needed = !state->allow_modeset; @@ -4354,95 +4346,76 @@ static int do_aquire_global_lock( return ret < 0 ? ret : 0; } -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) +static int dm_update_crtcs_state( + struct dc *dc, + struct drm_atomic_state *state, + bool enable, + bool *lock_and_validation_needed) { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; - struct drm_plane *plane; - struct drm_plane_state *plane_state; - int i, j; - int ret; - struct amdgpu_device *adev = dev->dev_private; - struct dc *dc = adev->dm.dc; - struct drm_connector *connector; - struct drm_connector_state *conn_state; + int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); - bool pflip_needed = !state->allow_modeset; - - /* - * This bool will be set for true for any modeset/reset - * or plane update which implies non fast surface update. - */ - bool lock_and_validation_needed = false; - - ret = drm_atomic_helper_check_modeset(dev, state); - - if (ret) { - DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); - return ret; - } - - dm_state->context = dc_create_state(); - ASSERT(dm_state->context); - dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); + int ret = 0; - /* Remove exiting planes if they are disabled or their CRTC is updated */ + /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ + /* update changed items */ for_each_crtc_in_state(state, crtc, crtc_state, i) { - new_acrtc_state = to_dm_crtc_state(crtc_state); + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_connector *aconnector = NULL; + struct dc_stream_state *new_stream = NULL; + struct drm_connector_state *conn_state = NULL; + struct dm_connector_state *dm_conn_state = NULL; - if (pflip_needed) - continue; + old_acrtc_state = to_dm_crtc_state(crtc->state); + new_acrtc_state = to_dm_crtc_state(crtc_state); + acrtc = to_amdgpu_crtc(crtc); - for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_crtc *plane_crtc = plane_state->crtc; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; + /* TODO This hack should go away */ + if (aconnector && aconnector->dc_sink) { + conn_state = drm_atomic_get_connector_state(state, + &aconnector->base); - if (crtc != plane_crtc || !dm_plane_state->dc_state) - continue; + if (IS_ERR(conn_state)) { + ret = PTR_ERR_OR_ZERO(conn_state); + break; + } - WARN_ON(!new_acrtc_state->stream); + dm_conn_state = to_dm_connector_state(conn_state); - if (drm_atomic_plane_disabling(plane->state, plane_state) || - drm_atomic_crtc_needs_modeset(crtc_state)) { - if (!dc_remove_plane_from_context( - dc, - new_acrtc_state->stream, - dm_plane_state->dc_state, - dm_state->context)) { + new_stream = create_stream_for_sink(aconnector, + &crtc_state->mode, + dm_conn_state); - ret = EINVAL; - goto fail; - } + /* + * we can have no stream on ACTION_SET if a display + * was disconnected during S3, in this case it not and + * error, the OS will be updated after detection, and + * do the right thing on next atomic commit + */ + if (!new_stream) { + DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + __func__, acrtc->base.base.id); + break; } + } - dc_plane_state_release(dm_plane_state->dc_state); - dm_plane_state->dc_state = NULL; + if (dc_is_stream_unchanged(new_stream, + old_acrtc_state->stream)) { - DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n", - plane->base.id, crtc->base.id); - } - } + crtc_state->mode_changed = false; - /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ - /* update changed items */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - struct amdgpu_crtc *acrtc = NULL; - struct amdgpu_connector *aconnector = NULL; - struct dc_stream_state *new_stream = NULL; - struct drm_connector_state *conn_state = NULL; - struct dm_connector_state *dm_conn_state = NULL; + DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d", + crtc_state->mode_changed); + } - old_acrtc_state = to_dm_crtc_state(crtc->state); - new_acrtc_state = to_dm_crtc_state(crtc_state); - acrtc = to_amdgpu_crtc(crtc); - aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); + if (!drm_atomic_crtc_needs_modeset(crtc_state)) + continue; DRM_DEBUG_KMS( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " @@ -4456,109 +4429,256 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, crtc_state->active_changed, crtc_state->connectors_changed); - if (modereset_required(crtc_state)) { + /* Remove stream for any changed/disabled CRTC */ + if (!enable) { + + if (!old_acrtc_state->stream) + continue; + + DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", + crtc->base.id); /* i.e. reset mode */ - if (new_acrtc_state->stream) { + if (!dc_remove_stream_from_ctx( + dc, + dm_state->context, + old_acrtc_state->stream)) { + ret = -EINVAL; + break; + } + + dc_stream_release(old_acrtc_state->stream); + new_acrtc_state->stream = NULL; + + *lock_and_validation_needed = true; + + } else {/* Add stream for any updated/enabled CRTC */ + + if (modereset_required(crtc_state)) + continue; + + if (modeset_required(crtc_state, new_stream, + old_acrtc_state->stream)) { + + WARN_ON(new_acrtc_state->stream); + + new_acrtc_state->stream = new_stream; + dc_stream_retain(new_stream); + + DRM_DEBUG_KMS("Enabling DRM crtc: %d\n", + crtc->base.id); - if (!dc_remove_stream_from_ctx( + if (!dc_add_stream_to_ctx( dc, dm_state->context, new_acrtc_state->stream)) { ret = -EINVAL; - goto fail; + break; } - dc_stream_release(new_acrtc_state->stream); - new_acrtc_state->stream = NULL; - - lock_and_validation_needed = true; + *lock_and_validation_needed = true; } + } - } else { + /* Release extra reference */ + if (new_stream) + dc_stream_release(new_stream); + } - if (aconnector) { - conn_state = drm_atomic_get_connector_state(state, - &aconnector->base); + return ret; +} - if (IS_ERR(conn_state)) { - ret = PTR_ERR_OR_ZERO(conn_state); - goto fail; - } +static int dm_update_planes_state( + struct dc *dc, + struct drm_atomic_state *state, + bool enable, + bool *lock_and_validation_needed) +{ + struct drm_crtc *new_plane_crtc, *old_plane_crtc; + struct drm_crtc_state *new_crtc_state; + struct drm_plane *plane; + struct drm_plane_state *old_plane_state, *new_plane_state; + struct dm_crtc_state *new_acrtc_state, *old_acrtc_state; + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state; + int i ; + /* TODO return page_flip_needed() function */ + bool pflip_needed = !state->allow_modeset; + int ret = 0; - dm_conn_state = to_dm_connector_state(conn_state); + if (pflip_needed) + return ret; - new_stream = create_stream_for_sink(aconnector, - &crtc_state->mode, - dm_conn_state); + /* Add new planes */ + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { + new_plane_crtc = new_plane_state->crtc; + old_plane_crtc = old_plane_state->crtc; + new_dm_plane_state = to_dm_plane_state(new_plane_state); + old_dm_plane_state = to_dm_plane_state(old_plane_state); + + /*TODO Implement atomic check for cursor plane */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; - /* - * we can have no stream on ACTION_SET if a display - * was disconnected during S3, in this case it not and - * error, the OS will be updated after detection, and - * do the right thing on next atomic commit - */ + /* Remove any changed/removed planes */ + if (!enable) { - if (!new_stream) { - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", - __func__, acrtc->base.base.id); - break; - } + if (!old_plane_crtc) + continue; + + old_acrtc_state = to_dm_crtc_state( + drm_atomic_get_old_crtc_state( + state, + old_plane_crtc)); + if (!old_acrtc_state->stream) + continue; + + DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n", + plane->base.id, old_plane_crtc->base.id); + if (!dc_remove_plane_from_context( + dc, + old_acrtc_state->stream, + old_dm_plane_state->dc_state, + dm_state->context)) { + + ret = EINVAL; + return ret; } - if (modeset_required(crtc_state, new_stream, - old_acrtc_state->stream)) { - if (new_acrtc_state->stream) { + dc_plane_state_release(old_dm_plane_state->dc_state); + new_dm_plane_state->dc_state = NULL; - if (!dc_remove_stream_from_ctx( - dc, - dm_state->context, - new_acrtc_state->stream)) { - ret = -EINVAL; - goto fail; - } + *lock_and_validation_needed = true; + } else { /* Add new planes */ - dc_stream_release(new_acrtc_state->stream); - } + if (drm_atomic_plane_disabling(plane->state, new_plane_state)) + continue; - new_acrtc_state->stream = new_stream; + if (!new_plane_crtc) + continue; - if (!dc_add_stream_to_ctx( - dc, - dm_state->context, - new_acrtc_state->stream)) { - ret = -EINVAL; - goto fail; - } + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); - lock_and_validation_needed = true; - } else { - /* - * The new stream is unused, so we release it - */ - if (new_stream) - dc_stream_release(new_stream); + if (!new_acrtc_state->stream) + continue; + + + WARN_ON(new_dm_plane_state->dc_state); + new_dm_plane_state->dc_state = dc_create_plane_state(dc); + + DRM_DEBUG_KMS("Enabling DRM plane: %d on DRM crtc %d\n", + plane->base.id, new_plane_crtc->base.id); + + if (!new_dm_plane_state->dc_state) { + ret = -EINVAL; + return ret; + } + + ret = fill_plane_attributes( + new_plane_crtc->dev->dev_private, + new_dm_plane_state->dc_state, + new_plane_state, + new_crtc_state, + false); + if (ret) + return ret; + + + if (!dc_add_plane_to_context( + dc, + new_acrtc_state->stream, + new_dm_plane_state->dc_state, + dm_state->context)) { + + ret = -EINVAL; + return ret; } + + *lock_and_validation_needed = true; } + } - /* - * Hack: Commit needs planes right now, specifically for gamma - * TODO rework commit to check CRTC for gamma change - */ - if (crtc_state->color_mgmt_changed) { + return ret; +} + +int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + int i; + int ret; + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + /* + * This bool will be set for true for any modeset/reset + * or plane update which implies non fast surface update. + */ + bool lock_and_validation_needed = false; + + ret = drm_atomic_helper_check_modeset(dev, state); + + if (ret) { + DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); + return ret; + } + + /* + * Hack: Commit needs planes right now, specifically for gamma + * TODO rework commit to check CRTC for gamma change + */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + if (crtc_state->color_mgmt_changed) { ret = drm_atomic_add_affected_planes(state, crtc); if (ret) goto fail; } } + dm_state->context = dc_create_state(); + ASSERT(dm_state->context); + dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); + + /* Remove exiting planes if they are modified */ + ret = dm_update_planes_state(dc, state, false, &lock_and_validation_needed); + if (ret) { + goto fail; + } + + /* Disable all crtcs which require disable */ + ret = dm_update_crtcs_state(dc, state, false, &lock_and_validation_needed); + if (ret) { + goto fail; + } + + /* Enable all crtcs which require enable */ + ret = dm_update_crtcs_state(dc, state, true, &lock_and_validation_needed); + if (ret) { + goto fail; + } + + /* Add new/modified planes */ + ret = dm_update_planes_state(dc, state, true, &lock_and_validation_needed); + if (ret) { + goto fail; + } + + /* Run this here since we want to validate the streams we created */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + goto fail; + /* Check scaling and undersacn changes*/ /*TODO Removed scaling changes validation due to inability to commit * new stream into context w\o causing full reset. Need to @@ -4583,66 +4703,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, lock_and_validation_needed = true; } - /* Add new planes */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { - new_acrtc_state = to_dm_crtc_state(crtc_state); - - if (pflip_needed) - continue; - - for_each_plane_in_state(state, plane, plane_state, j) { - struct drm_crtc *plane_crtc = plane_state->crtc; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); - - /*TODO Implement atomic check for cursor plane */ - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; - - if (crtc != plane_crtc) - continue; - - if (!drm_atomic_plane_disabling(plane->state, plane_state)) { - struct dc_plane_state *dc_plane_state; - - WARN_ON(!new_acrtc_state->stream); - - dc_plane_state = dc_create_plane_state(dc); - - WARN_ON(dm_plane_state->dc_state); - - dm_plane_state->dc_state = dc_plane_state; - - ret = fill_plane_attributes( - plane_crtc->dev->dev_private, - dc_plane_state, - plane_state, - crtc_state, - false); - if (ret) - goto fail; - - - if (!dc_add_plane_to_context( - dc, - new_acrtc_state->stream, - dc_plane_state, - dm_state->context)) { - - ret = EINVAL; - goto fail; - } - - - lock_and_validation_needed = true; - } - } - } - - /* Run this here since we want to validate the streams we created */ - ret = drm_atomic_helper_check_planes(dev, state); - if (ret) - goto fail; - /* * For full updates case when * removing/adding/updating streams on once CRTC while flipping @@ -4675,7 +4735,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); else - DRM_ERROR("Atomic check failed with err: %d .\n", ret); + DRM_ERROR("Atomic check failed with err: %d \n", ret); return ret; } -- GitLab From 9635b75436e5f536831c810c715f3ae24a5bbbae Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 12 Sep 2017 17:10:25 +0100 Subject: [PATCH 0829/2898] drm/amd/display: Don't leak dc_stream_state. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noticed while playing “Valley”, which was causing some 8MB of leakage per second. kmemleak listed many entries looking like this: unreferenced object 0xffff8802c2951800 (size 1024): comm "Xorg", pid 2982, jiffies 4297410155 (age 392.787s) hex dump (first 32 bytes): 00 50 f9 0c 04 88 ff ff 98 08 00 00 00 00 00 00 .P.............. 80 07 00 00 00 00 00 00 58 00 00 00 2c 00 00 00 ........X...,... backtrace: [] create_object+0x13c/0x261 [] kmemleak_alloc+0x20/0x3c [] slab_post_alloc_hook+0x42/0x52 [] kmem_cache_alloc+0x67/0x76 [] dc_create_stream_for_sink+0x24/0x1cf [] create_stream_for_sink+0x6f/0x295 [] dm_update_crtcs_state+0xa6/0x268 [] amdgpu_dm_atomic_check+0x9a/0x314 [] drm_atomic_check_only+0x17a/0x42d [] drm_atomic_commit+0x13/0x4b [] drm_atomic_connector_commit_dpms+0xcb/0xe8 [] drm_mode_obj_set_property_ioctl+0xe6/0x1e3 [] drm_mode_connector_property_set_ioctl+0x2b/0x2d [] drm_ioctl_kernel+0x64/0x9d [] drm_ioctl+0x230/0x316 [] amdgpu_drm_ioctl+0x4b/0x7d v2: also handle break statements. Signed-off-by: Darren Salt Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 193a634f46e6..4f1e31cd4cbe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4357,6 +4357,7 @@ static int dm_update_crtcs_state( int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); + struct dc_stream_state *new_stream; int ret = 0; /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ @@ -4364,10 +4365,11 @@ static int dm_update_crtcs_state( for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_connector *aconnector = NULL; - struct dc_stream_state *new_stream = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_conn_state = NULL; + new_stream = NULL; + old_acrtc_state = to_dm_crtc_state(crtc->state); new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); @@ -4415,7 +4417,7 @@ static int dm_update_crtcs_state( if (!drm_atomic_crtc_needs_modeset(crtc_state)) - continue; + goto next_crtc; DRM_DEBUG_KMS( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " @@ -4433,7 +4435,7 @@ static int dm_update_crtcs_state( if (!enable) { if (!old_acrtc_state->stream) - continue; + goto next_crtc; DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", crtc->base.id); @@ -4444,7 +4446,7 @@ static int dm_update_crtcs_state( dm_state->context, old_acrtc_state->stream)) { ret = -EINVAL; - break; + goto fail; } dc_stream_release(old_acrtc_state->stream); @@ -4455,7 +4457,7 @@ static int dm_update_crtcs_state( } else {/* Add stream for any updated/enabled CRTC */ if (modereset_required(crtc_state)) - continue; + goto next_crtc; if (modeset_required(crtc_state, new_stream, old_acrtc_state->stream)) { @@ -4473,19 +4475,25 @@ static int dm_update_crtcs_state( dm_state->context, new_acrtc_state->stream)) { ret = -EINVAL; - break; + goto fail; } *lock_and_validation_needed = true; } } +next_crtc: /* Release extra reference */ if (new_stream) dc_stream_release(new_stream); } return ret; + +fail: + if (new_stream) + dc_stream_release(new_stream); + return ret; } static int dm_update_planes_state( -- GitLab From 156590454259a19d1709fab2ff7d59870574e822 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Wed, 23 Aug 2017 15:44:42 -0400 Subject: [PATCH 0830/2898] drm/amd/display: Clean up flattening core_dc to dc Clean up some code related to flattening core_dc commit (Remove redundent dc = dc, which was the result of removing DC_TO_CORE() macro) Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 12 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 335 ++++++++---------- .../amd/display/modules/freesync/freesync.c | 19 +- 3 files changed, 164 insertions(+), 202 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index afd403ceb2a7..5e5766a63a47 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -983,15 +983,14 @@ bool dcn_validate_bandwidth( if (v->voltage_level == 0 && (dc->debug.sr_exit_time_dpm0_ns || dc->debug.sr_enter_plus_exit_time_dpm0_ns)) { - struct dc *dc_core = dc; if (dc->debug.sr_enter_plus_exit_time_dpm0_ns) v->sr_enter_plus_exit_time = dc->debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f; if (dc->debug.sr_exit_time_dpm0_ns) v->sr_exit_time = dc->debug.sr_exit_time_dpm0_ns / 1000.0f; - dc_core->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; - dc_core->dml.soc.sr_exit_time_us = v->sr_exit_time; + dc->dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time; + dc->dml.soc.sr_exit_time_us = v->sr_exit_time; mode_support_and_system_configuration(v); } @@ -1114,11 +1113,10 @@ bool dcn_validate_bandwidth( } if (v->voltage_level == 0) { - struct dc *dc_core = dc; - dc_core->dml.soc.sr_enter_plus_exit_time_us = - dc_core->dcn_soc->sr_enter_plus_exit_time; - dc_core->dml.soc.sr_exit_time_us = dc_core->dcn_soc->sr_exit_time; + dc->dml.soc.sr_enter_plus_exit_time_us = + dc->dcn_soc->sr_enter_plus_exit_time; + dc->dml.soc.sr_exit_time_us = dc->dcn_soc->sr_exit_time; } /* diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 79980cb0900c..dc1b7d061be2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -155,20 +155,19 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, int vmin, int vmax) { /* TODO: Support multiple streams */ - struct dc *core_dc = dc; struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &dc->current_context->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { - core_dc->hwss.set_drr(&pipe, 1, vmin, vmax); + dc->hwss.set_drr(&pipe, 1, vmin, vmax); /* build and update the info frame */ resource_build_info_frame(pipe); - core_dc->hwss.update_info_frame(pipe); + dc->hwss.update_info_frame(pipe); ret = true; } @@ -181,7 +180,6 @@ static bool stream_get_crtc_position(struct dc *dc, unsigned int *v_pos, unsigned int *nom_v_pos) { /* TODO: Support multiple streams */ - struct dc *core_dc = dc; struct dc_stream_state *stream = streams[0]; int i = 0; bool ret = false; @@ -189,10 +187,10 @@ static bool stream_get_crtc_position(struct dc *dc, for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = - &core_dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_context->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { - core_dc->hwss.get_position(&pipe, 1, &position); + dc->hwss.get_position(&pipe, 1, &position); *v_pos = position.vertical_count; *nom_v_pos = position.nominal_vcount; @@ -204,15 +202,14 @@ static bool stream_get_crtc_position(struct dc *dc, static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) { - struct dc *core_dc = dc; int i = 0; bool ret = false; struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.program_gamut_remap(pipes); + if (dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { + pipes = &dc->current_context->res_ctx.pipe_ctx[i]; + dc->hwss.program_gamut_remap(pipes); ret = true; } } @@ -222,17 +219,16 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) { - struct dc *core_dc = dc; int i = 0; bool ret = false; struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + if (dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &core_dc->current_context->res_ctx.pipe_ctx[i]; - core_dc->hwss.program_csc_matrix(pipes, + pipes = &dc->current_context->res_ctx.pipe_ctx[i]; + dc->hwss.program_csc_matrix(pipes, stream->output_color_space, stream->csc_color_matrix.matrix); ret = true; @@ -247,7 +243,6 @@ static void set_static_screen_events(struct dc *dc, int num_streams, const struct dc_static_screen_events *events) { - struct dc *core_dc = dc; int i = 0; int j = 0; struct pipe_ctx *pipes_affected[MAX_PIPES]; @@ -257,45 +252,44 @@ static void set_static_screen_events(struct dc *dc, struct dc_stream_state *stream = streams[i]; for (j = 0; j < MAX_PIPES; j++) { - if (core_dc->current_context->res_ctx.pipe_ctx[j].stream + if (dc->current_context->res_ctx.pipe_ctx[j].stream == stream) { pipes_affected[num_pipes_affected++] = - &core_dc->current_context->res_ctx.pipe_ctx[j]; + &dc->current_context->res_ctx.pipe_ctx[j]; } } } - core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); + dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events); } static void set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link) { - struct dc *core_dc = dc; + int i; - for (i = 0; i < core_dc->link_count; i++) { - if (core_dc->links[i] == link) + for (i = 0; i < dc->link_count; i++) { + if (dc->links[i] == link) break; } - if (i >= core_dc->link_count) + if (i >= dc->link_count) ASSERT_CRITICAL(false); - dc_link_dp_set_drive_settings(core_dc->links[i], lt_settings); + dc_link_dp_set_drive_settings(dc->links[i], lt_settings); } static void perform_link_training(struct dc *dc, struct dc_link_settings *link_setting, bool skip_video_pattern) { - struct dc *core_dc = dc; int i; - for (i = 0; i < core_dc->link_count; i++) + for (i = 0; i < dc->link_count; i++) dc_link_dp_perform_link_training( - core_dc->links[i], + dc->links[i], link_setting, skip_video_pattern); } @@ -371,44 +365,44 @@ void set_dither_option(struct dc_stream_state *stream, opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } -static void allocate_dc_stream_funcs(struct dc *core_dc) +static void allocate_dc_stream_funcs(struct dc *dc) { - if (core_dc->hwss.set_drr != NULL) { - core_dc->stream_funcs.adjust_vmin_vmax = + if (dc->hwss.set_drr != NULL) { + dc->stream_funcs.adjust_vmin_vmax = stream_adjust_vmin_vmax; } - core_dc->stream_funcs.set_static_screen_events = + dc->stream_funcs.set_static_screen_events = set_static_screen_events; - core_dc->stream_funcs.get_crtc_position = + dc->stream_funcs.get_crtc_position = stream_get_crtc_position; - core_dc->stream_funcs.set_gamut_remap = + dc->stream_funcs.set_gamut_remap = set_gamut_remap; - core_dc->stream_funcs.program_csc_matrix = + dc->stream_funcs.program_csc_matrix = program_csc_matrix; - core_dc->stream_funcs.set_dither_option = + dc->stream_funcs.set_dither_option = set_dither_option; - core_dc->link_funcs.set_drive_settings = + dc->link_funcs.set_drive_settings = set_drive_settings; - core_dc->link_funcs.perform_link_training = + dc->link_funcs.perform_link_training = perform_link_training; - core_dc->link_funcs.set_preferred_link_settings = + dc->link_funcs.set_preferred_link_settings = set_preferred_link_settings; - core_dc->link_funcs.enable_hpd = + dc->link_funcs.enable_hpd = enable_hpd; - core_dc->link_funcs.disable_hpd = + dc->link_funcs.disable_hpd = disable_hpd; - core_dc->link_funcs.set_test_pattern = + dc->link_funcs.set_test_pattern = set_test_pattern; } @@ -622,41 +616,41 @@ void ProgramPixelDurationV(unsigned int pixelClockInKHz ) struct dc *dc_create(const struct dc_init_data *init_params) { - struct dc *core_dc = dm_alloc(sizeof(*core_dc)); + struct dc *dc = dm_alloc(sizeof(*dc)); unsigned int full_pipe_count; - if (NULL == core_dc) + if (NULL == dc) goto alloc_fail; - if (false == construct(core_dc, init_params)) + if (false == construct(dc, init_params)) goto construct_fail; /*TODO: separate HW and SW initialization*/ - core_dc->hwss.init_hw(core_dc); + dc->hwss.init_hw(dc); - full_pipe_count = core_dc->res_pool->pipe_count; - if (core_dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) + full_pipe_count = dc->res_pool->pipe_count; + if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE) full_pipe_count--; - core_dc->caps.max_streams = min( + dc->caps.max_streams = min( full_pipe_count, - core_dc->res_pool->stream_enc_count); + dc->res_pool->stream_enc_count); - core_dc->caps.max_links = core_dc->link_count; - core_dc->caps.max_audios = core_dc->res_pool->audio_count; + dc->caps.max_links = dc->link_count; + dc->caps.max_audios = dc->res_pool->audio_count; - core_dc->config = init_params->flags; + dc->config = init_params->flags; - dm_logger_write(core_dc->ctx->logger, LOG_DC, + dm_logger_write(dc->ctx->logger, LOG_DC, "Display Core initialized\n"); /* TODO: missing feature to be enabled */ - core_dc->debug.disable_dfs_bypass = true; + dc->debug.disable_dfs_bypass = true; - return core_dc; + return dc; construct_fail: - dm_free(core_dc); + dm_free(dc); alloc_fail: return NULL; @@ -664,9 +658,8 @@ struct dc *dc_create(const struct dc_init_data *init_params) void dc_destroy(struct dc **dc) { - struct dc *core_dc = *dc; - destruct(core_dc); - dm_free(core_dc); + destruct(*dc); + dm_free(*dc); *dc = NULL; } @@ -674,7 +667,6 @@ bool dc_validate_guaranteed( struct dc *dc, struct dc_stream_state *stream) { - struct dc *core_dc = dc; enum dc_status result = DC_ERROR_UNEXPECTED; struct validate_context *context; @@ -687,14 +679,14 @@ bool dc_validate_guaranteed( atomic_inc(&context->ref_count); - result = core_dc->res_pool->funcs->validate_guaranteed( - core_dc, stream, context); + result = dc->res_pool->funcs->validate_guaranteed( + dc, stream, context); dc_release_validate_context(context); context_alloc_fail: if (result != DC_OK) { - dm_logger_write(core_dc->ctx->logger, LOG_WARNING, + dm_logger_write(dc->ctx->logger, LOG_WARNING, "%s:guaranteed validation failed, dc_status:%d\n", __func__, result); @@ -704,12 +696,12 @@ bool dc_validate_guaranteed( } static void program_timing_sync( - struct dc *core_dc, + struct dc *dc, struct validate_context *ctx) { int i, j; int group_index = 0; - int pipe_count = core_dc->res_pool->pipe_count; + int pipe_count = dc->res_pool->pipe_count; struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; for (i = 0; i < pipe_count; i++) { @@ -770,8 +762,8 @@ static void program_timing_sync( } if (group_size > 1) { - core_dc->hwss.enable_timing_synchronization( - core_dc, group_index, group_size, pipe_set); + dc->hwss.enable_timing_synchronization( + dc, group_index, group_size, pipe_set); group_index++; } } @@ -803,17 +795,16 @@ bool dc_enable_stereo( bool ret = true; int i, j; struct pipe_ctx *pipe; - struct dc *core_dc = dc; for (i = 0; i < MAX_PIPES; i++) { if (context != NULL) pipe = &context->res_ctx.pipe_ctx[i]; else - pipe = &core_dc->current_context->res_ctx.pipe_ctx[i]; + pipe = &dc->current_context->res_ctx.pipe_ctx[i]; for (j = 0 ; pipe && j < stream_count; j++) { if (streams[j] && streams[j] == pipe->stream && - core_dc->hwss.setup_stereo) - core_dc->hwss.setup_stereo(pipe, core_dc); + dc->hwss.setup_stereo) + dc->hwss.setup_stereo(pipe, dc); } } @@ -827,8 +818,7 @@ bool dc_enable_stereo( */ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context) { - struct dc *core_dc = dc; - struct dc_bios *dcb = core_dc->ctx->dc_bios; + struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; struct pipe_ctx *pipe; int i, j, k, l; @@ -838,22 +828,22 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_streams[i] = context->streams[i]; if (!dcb->funcs->is_accelerated_mode(dcb)) - core_dc->hwss.enable_accelerated_mode(core_dc); + dc->hwss.enable_accelerated_mode(dc); - for (i = 0; i < core_dc->res_pool->pipe_count; i++) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; - core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe); + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); } - result = core_dc->hwss.apply_ctx_to_hw(core_dc, context); + result = dc->hwss.apply_ctx_to_hw(dc, context); - program_timing_sync(core_dc, context); + program_timing_sync(dc, context); for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; for (j = 0; j < context->stream_status[i].plane_count; j++) { - core_dc->hwss.apply_ctx_for_surface( - core_dc, context->streams[i], + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], context->stream_status[i].plane_count, context); @@ -867,8 +857,8 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c for (l = 0 ; pipe && l < context->stream_count; l++) { if (context->streams[l] && context->streams[l] == pipe->stream && - core_dc->hwss.setup_stereo) - core_dc->hwss.setup_stereo(pipe, core_dc); + dc->hwss.setup_stereo) + dc->hwss.setup_stereo(pipe, dc); } } } @@ -883,11 +873,11 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - dc_release_validate_context(core_dc->current_context); + dc_release_validate_context(dc->current_context); - core_dc->current_context = context; + dc->current_context = context; - dc_retain_validate_context(core_dc->current_context); + dc_retain_validate_context(dc->current_context); return (result == DC_OK); } @@ -895,20 +885,19 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c bool dc_commit_context(struct dc *dc, struct validate_context *context) { enum dc_status result = DC_ERROR_UNEXPECTED; - struct dc *core_dc = dc; int i; - if (false == context_changed(core_dc, context)) + if (false == context_changed(dc, context)) return DC_OK; - dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n", + dm_logger_write(dc->ctx->logger, LOG_DC, "%s: %d streams\n", __func__, context->stream_count); for (i = 0; i < context->stream_count; i++) { struct dc_stream_state *stream = context->streams[i]; dc_stream_log(stream, - core_dc->ctx->logger, + dc->ctx->logger, LOG_DC); } @@ -921,21 +910,20 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; - struct dc *core_dc = dc; - struct validate_context *context = core_dc->current_context; + struct validate_context *context = dc->current_context; post_surface_trace(dc); - for (i = 0; i < core_dc->res_pool->pipe_count; i++) + for (i = 0; i < dc->res_pool->pipe_count; i++) if (context->res_ctx.pipe_ctx[i].stream == NULL || context->res_ctx.pipe_ctx[i].plane_state == NULL) - core_dc->hwss.power_down_front_end(core_dc, i); + dc->hwss.power_down_front_end(dc, i); /* 3rd param should be true, temp w/a for RV*/ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) - core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version < DCN_VERSION_1_0); + dc->hwss.set_bandwidth(dc, context, dc->ctx->dce_version < DCN_VERSION_1_0); #else - core_dc->hwss.set_bandwidth(core_dc, context, true); + dc->hwss.set_bandwidth(dc, context, true); #endif return true; } @@ -1184,7 +1172,6 @@ enum surface_update_type dc_check_update_surfaces_for_stream( struct dc_stream_update *stream_update, const struct dc_stream_status *stream_status) { - struct dc *core_dc = dc; int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; @@ -1196,7 +1183,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( for (i = 0 ; i < surface_count; i++) { enum surface_update_type type = - det_surface_update(core_dc, &updates[i], i); + det_surface_update(dc, &updates[i], i); if (type == UPDATE_TYPE_FULL) return type; @@ -1230,12 +1217,11 @@ void dc_update_planes_and_stream(struct dc *dc, struct dc_stream_state *stream, struct dc_stream_update *stream_update) { - struct dc *core_dc = dc; struct validate_context *context; int i, j; enum surface_update_type update_type; const struct dc_stream_status *stream_status; - struct dc_context *dc_ctx = core_dc->ctx; + struct dc_context *dc_ctx = dc->ctx; stream_status = dc_stream_get_status(stream); @@ -1249,7 +1235,7 @@ void dc_update_planes_and_stream(struct dc *dc, ASSERT(0); } #endif - context = core_dc->current_context; + context = dc->current_context; /* update current stream with the new updates */ if (stream_update) { @@ -1303,7 +1289,7 @@ void dc_update_planes_and_stream(struct dc *dc, goto context_alloc_fail; dc_resource_validate_ctx_copy_construct( - core_dc->current_context, context); + dc->current_context, context); /*remove old surfaces from context */ if (!dc_rem_all_planes_for_stream(dc, stream, context)) { @@ -1365,7 +1351,7 @@ void dc_update_planes_and_stream(struct dc *dc, } if (update_type >= UPDATE_TYPE_MED) { - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (pipe_ctx->plane_state != surface) @@ -1403,31 +1389,31 @@ void dc_update_planes_and_stream(struct dc *dc, } if (update_type == UPDATE_TYPE_FULL) { - if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { + if (!dc->res_pool->funcs->validate_bandwidth(dc, context)) { BREAK_TO_DEBUGGER(); goto fail; } else { - core_dc->hwss.set_bandwidth(core_dc, context, false); + dc->hwss.set_bandwidth(dc, context, false); context_clock_trace(dc, context); } } if (update_type > UPDATE_TYPE_FAST) { - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - core_dc->hwss.wait_for_mpcc_disconnect(core_dc, core_dc->res_pool, pipe_ctx); + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); } } if (surface_count == 0) - core_dc->hwss.apply_ctx_for_surface(core_dc, stream, surface_count, context); + dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context); /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { struct dc_plane_state *plane_state = srf_updates[i].surface; - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (update_type != UPDATE_TYPE_FULL && pipe_ctx->plane_state != plane_state) @@ -1435,8 +1421,8 @@ void dc_update_planes_and_stream(struct dc *dc, if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) continue; - core_dc->hwss.pipe_control_lock( - core_dc, + dc->hwss.pipe_control_lock( + dc, pipe_ctx, true); } @@ -1445,9 +1431,9 @@ void dc_update_planes_and_stream(struct dc *dc, } /* Full fe update*/ - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[j]; bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; struct dc_cursor_position position = { 0 }; @@ -1458,18 +1444,18 @@ void dc_update_planes_and_stream(struct dc *dc, if (!pipe_ctx->top_pipe && pipe_ctx->stream) { struct dc_stream_status *stream_status = stream_get_status(context, pipe_ctx->stream); - core_dc->hwss.apply_ctx_for_surface( - core_dc, pipe_ctx->stream, stream_status->plane_count, context); + dc->hwss.apply_ctx_for_surface( + dc, pipe_ctx->stream, stream_status->plane_count, context); } /* TODO: this is a hack w/a for switching from mpo to pipe split */ dc_stream_set_cursor_position(pipe_ctx->stream, &position); if (is_new_pipe_surface) { - core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); - core_dc->hwss.set_input_transfer_func( + dc->hwss.update_plane_addr(dc, pipe_ctx); + dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->plane_state); - core_dc->hwss.set_output_transfer_func( + dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->stream); } } @@ -1482,40 +1468,40 @@ void dc_update_planes_and_stream(struct dc *dc, struct dc_plane_state *plane_state = srf_updates[i].surface; if (update_type == UPDATE_TYPE_MED) - core_dc->hwss.apply_ctx_for_surface( - core_dc, stream, surface_count, context); + dc->hwss.apply_ctx_for_surface( + dc, stream, surface_count, context); - for (j = 0; j < core_dc->res_pool->pipe_count; j++) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; if (pipe_ctx->plane_state != plane_state) continue; if (srf_updates[i].flip_addr) - core_dc->hwss.update_plane_addr(core_dc, pipe_ctx); + dc->hwss.update_plane_addr(dc, pipe_ctx); if (update_type == UPDATE_TYPE_FAST) continue; if (srf_updates[i].in_transfer_func) - core_dc->hwss.set_input_transfer_func( + dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->plane_state); if (stream_update != NULL && stream_update->out_transfer_func != NULL) { - core_dc->hwss.set_output_transfer_func( + dc->hwss.set_output_transfer_func( pipe_ctx, pipe_ctx->stream); } if (srf_updates[i].hdr_static_metadata) { resource_build_info_frame(pipe_ctx); - core_dc->hwss.update_info_frame(pipe_ctx); + dc->hwss.update_info_frame(pipe_ctx); } } } /* Unlock pipes */ - for (i = core_dc->res_pool->pipe_count - 1; i >= 0; i--) { + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; for (j = 0; j < surface_count; j++) { @@ -1525,8 +1511,8 @@ void dc_update_planes_and_stream(struct dc *dc, if (!pipe_ctx->plane_state || pipe_ctx->top_pipe) continue; - core_dc->hwss.pipe_control_lock( - core_dc, + dc->hwss.pipe_control_lock( + dc, pipe_ctx, false); @@ -1534,7 +1520,7 @@ void dc_update_planes_and_stream(struct dc *dc, } } - if (core_dc->current_context != context) { + if (dc->current_context != context) { /* Since memory free requires elevated IRQL, an interrupt * request is generated by mem free. If this happens @@ -1544,9 +1530,9 @@ void dc_update_planes_and_stream(struct dc *dc, * then free the old context. */ - struct validate_context *old = core_dc->current_context; + struct validate_context *old = dc->current_context; - core_dc->current_context = context; + dc->current_context = context; dc_release_validate_context(old); } @@ -1561,29 +1547,25 @@ void dc_update_planes_and_stream(struct dc *dc, uint8_t dc_get_current_stream_count(struct dc *dc) { - struct dc *core_dc = dc; - return core_dc->current_context->stream_count; + return dc->current_context->stream_count; } struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) { - struct dc *core_dc = dc; - if (i < core_dc->current_context->stream_count) - return core_dc->current_context->streams[i]; + if (i < dc->current_context->stream_count) + return dc->current_context->streams[i]; return NULL; } struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) { - struct dc *core_dc = dc; - return core_dc->links[link_index]; + return dc->links[link_index]; } struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe) { - struct dc *core_dc = dc; if ((pipe >= dwb_pipe0) && (pipe < dwb_pipe_max_num)) { - return core_dc->res_pool->dwbc[(int)pipe]; + return dc->res_pool->dwbc[(int)pipe]; } else { return NULL; } @@ -1592,21 +1574,18 @@ struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe) const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index) { - struct dc *core_dc = dc; - return core_dc->links[link_index]->link_id; + return dc->links[link_index]->link_id; } enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index) { - struct dc *core_dc = dc; - return core_dc->links[link_index]->irq_source_hpd; + return dc->links[link_index]->irq_source_hpd; } const struct audio **dc_get_audios(struct dc *dc) { - struct dc *core_dc = dc; - return (const struct audio **)core_dc->res_pool->audios; + return (const struct audio **)dc->res_pool->audios; } enum dc_irq_source dc_interrupt_to_irq_source( @@ -1614,41 +1593,36 @@ enum dc_irq_source dc_interrupt_to_irq_source( uint32_t src_id, uint32_t ext_id) { - struct dc *core_dc = dc; - return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id); + return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); } void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) { - struct dc *core_dc; if (dc == NULL) return; - core_dc = dc; - dal_irq_service_set(core_dc->res_pool->irqs, src, enable); + dal_irq_service_set(dc->res_pool->irqs, src, enable); } void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) { - struct dc *core_dc = dc; - dal_irq_service_ack(core_dc->res_pool->irqs, src); + dal_irq_service_ack(dc->res_pool->irqs, src); } void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state) { - struct dc *core_dc = dc; atomic_t ref_count; switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: - core_dc->hwss.init_hw(core_dc); + dc->hwss.init_hw(dc); break; default: - core_dc->hwss.power_down(core_dc); + dc->hwss.power_down(dc); /* Zero out the current context so that on resume we start with * clean state, and dc hw programming optimizations will not @@ -1656,11 +1630,11 @@ void dc_set_power_state( */ /* Preserve refcount */ - ref_count = core_dc->current_context->ref_count; - dc_resource_validate_ctx_destruct(core_dc->current_context); - memset(core_dc->current_context, 0, - sizeof(*core_dc->current_context)); - core_dc->current_context->ref_count = ref_count; + ref_count = dc->current_context->ref_count; + dc_resource_validate_ctx_destruct(dc->current_context); + memset(dc->current_context, 0, + sizeof(*dc->current_context)); + dc->current_context->ref_count = ref_count; break; } @@ -1669,12 +1643,11 @@ void dc_set_power_state( void dc_resume(struct dc *dc) { - struct dc *core_dc = dc; uint32_t i; - for (i = 0; i < core_dc->link_count; i++) - core_link_resume(core_dc->links[i]); + for (i = 0; i < dc->link_count; i++) + core_link_resume(dc->links[i]); } bool dc_read_aux_dpcd( @@ -1684,9 +1657,8 @@ bool dc_read_aux_dpcd( uint8_t *data, uint32_t size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( link->ddc, false, @@ -1704,8 +1676,7 @@ bool dc_write_aux_dpcd( const uint8_t *data, uint32_t size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( link->ddc, @@ -1725,9 +1696,8 @@ bool dc_read_aux_i2c( uint8_t *data, uint32_t size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; enum ddc_result r = dal_ddc_service_read_dpcd_data( link->ddc, true, @@ -1746,8 +1716,7 @@ bool dc_write_aux_i2c( const uint8_t *data, uint32_t size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; enum ddc_result r = dal_ddc_service_write_dpcd_data( link->ddc, @@ -1768,9 +1737,8 @@ bool dc_query_ddc_data( uint8_t *read_buf, uint32_t read_size) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; bool result = dal_ddc_service_query_ddc_data( link->ddc, @@ -1788,9 +1756,8 @@ bool dc_submit_i2c( uint32_t link_index, struct i2c_command *cmd) { - struct dc *core_dc = dc; - struct dc_link *link = core_dc->links[link_index]; + struct dc_link *link = dc->links[link_index]; struct ddc_service *ddc = link->ddc; return dal_i2caux_submit_i2c_command( @@ -1907,12 +1874,11 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) { int i; - struct dc *core_dc = dc; struct mem_input *mi = NULL; - for (i = 0; i < core_dc->res_pool->pipe_count; i++) { - if (core_dc->res_pool->mis[i] != NULL) { - mi = core_dc->res_pool->mis[i]; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (dc->res_pool->mis[i] != NULL) { + mi = dc->res_pool->mis[i]; break; } } @@ -1921,10 +1887,10 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) return false; } - if (core_dc->hwss.update_dchub) - core_dc->hwss.update_dchub(core_dc->hwseq, dh_data); + if (dc->hwss.update_dchub) + dc->hwss.update_dchub(dc->hwseq, dh_data); else - ASSERT(core_dc->hwss.update_dchub); + ASSERT(dc->hwss.update_dchub); return true; @@ -1933,9 +1899,8 @@ bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) void dc_log_hw_state(struct dc *dc) { - struct dc *core_dc = dc; - if (core_dc->hwss.log_hw_state) - core_dc->hwss.log_hw_state(core_dc); + if (dc->hwss.log_hw_state) + dc->hwss.log_hw_state(dc); } diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index f49203b3eb94..52350d0e68d0 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -145,7 +145,6 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) struct core_freesync *core_freesync = dm_alloc(sizeof(struct core_freesync)); - struct dc *core_dc = dc; struct persistent_data_flag flag; @@ -176,19 +175,19 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) /* Create initial module folder in registry for freesync enable data */ flag.save_per_edid = true; flag.save_per_link = false; - dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, + dm_write_persistent_data(dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL, 0, &flag); flag.save_per_edid = false; flag.save_per_link = false; - if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, + if (dm_read_persistent_data(dc->ctx, NULL, NULL, FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY, &data, sizeof(data), &flag)) { core_freesync->opts.drr_internal_supported = (data & 1) ? false : true; } - if (dm_read_persistent_data(core_dc->ctx, NULL, NULL, + if (dm_read_persistent_data(dc->ctx, NULL, NULL, FREESYNC_NO_STATIC_FOR_EXTERNAL_DP_REGKEY, &data, sizeof(data), &flag)) { core_freesync->opts.drr_external_supported = @@ -245,7 +244,7 @@ static unsigned int map_index_from_stream(struct core_freesync *core_freesync, bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, struct dc_stream_state *stream, struct mod_freesync_caps *caps) { - struct dc *core_dc = NULL; + struct dc *dc = NULL; struct core_freesync *core_freesync = NULL; int persistent_freesync_enable = 0; struct persistent_data_flag flag; @@ -256,7 +255,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_dc = core_freesync->dc; + dc = core_freesync->dc; flag.save_per_edid = true; flag.save_per_link = false; @@ -287,7 +286,7 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync, static_ramp.ramp_is_active = false; /* get persistent data from registry */ - if (dm_read_persistent_data(core_dc->ctx, stream->sink, + if (dm_read_persistent_data(dc->ctx, stream->sink, FREESYNC_REGISTRY_NAME, "userenable", &persistent_freesync_enable, sizeof(int), &flag)) { @@ -970,14 +969,14 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, unsigned int stream_index, map_index; int persistent_data = 0; struct persistent_data_flag flag; - struct dc *core_dc = NULL; + struct dc *dc = NULL; struct core_freesync *core_freesync = NULL; if (mod_freesync == NULL) return false; core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync); - core_dc = core_freesync->dc; + dc = core_freesync->dc; flag.save_per_edid = true; flag.save_per_link = false; @@ -1001,7 +1000,7 @@ bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync, enable_for_video) persistent_data = persistent_data | 4; - dm_write_persistent_data(core_dc->ctx, + dm_write_persistent_data(dc->ctx, streams[stream_index]->sink, FREESYNC_REGISTRY_NAME, "userenable", -- GitLab From 1cf49dea28dfc76f0816a4bc73c2ab975c72f55d Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 23 Aug 2017 17:02:34 -0400 Subject: [PATCH 0831/2898] drm/amd/display: do not reset lane count in EQ fallback [Description] According to DP1.4 specs we should not reset lane count back when falling back in failing EQ training. This causes PHY test pattern compliance to fail as infinite LT when LT fails EQ to 4 RBR and fails CR in a loop. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e19447d526ea..446e2933474c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1302,8 +1302,6 @@ bool decide_fallback_link_setting( current_link_setting->lane_count); } else if (!reached_minimum_link_rate (current_link_setting->link_rate)) { - current_link_setting->lane_count = - initial_link_settings.lane_count; current_link_setting->link_rate = reduce_link_rate( current_link_setting->link_rate); -- GitLab From e1b522bff39d4834f4cfedc557857bb4d50f3946 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 24 Aug 2017 17:29:24 -0400 Subject: [PATCH 0832/2898] drm/amd/display: work around for 8k sleep crash Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 5e5766a63a47..6c85a54e47d6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -581,6 +581,7 @@ static void split_stream_across_pipes( secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { + ASSERT(primary_pipe->bottom_pipe != secondary_pipe); secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bd023299e2af..498680a9b996 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2358,7 +2358,7 @@ static void program_all_pipe_in_tree( verify_allow_pstate_change_high(dc->hwseq); } - if (pipe_ctx->bottom_pipe != NULL) + if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); } -- GitLab From aac6a07e40dea7996851c81f9a5f0e433b806086 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 23 Aug 2017 16:54:03 -0400 Subject: [PATCH 0833/2898] drm/amd/display: Use DRM provided page flip flag. Starting with 4.12 kernel DRM provides page flip flags so we don't need to have our own copy. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4f1e31cd4cbe..9c44b82036fa 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3767,7 +3767,7 @@ static void amdgpu_dm_do_flip( struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); struct amdgpu_bo *abo = gem_to_amdgpu_bo(afb->obj); struct amdgpu_device *adev = crtc->dev->dev_private; - bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; + bool async_flip = (crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; struct dc_flip_addrs addr = { {0} }; /* TODO eliminate or rename surface_update */ struct dc_surface_update surface_updates[1] = { {0} }; @@ -3899,7 +3899,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * TODO Check if it's correct */ *wait_for_vblank = - acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + pcrtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? false : true; /* TODO: Needs rework for multiplane flip */ @@ -3910,11 +3910,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, crtc, fb, drm_crtc_vblank_count(crtc) + *wait_for_vblank); - - /*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */ - - /*clean up the flags for next usage*/ - acrtc_attach->flip_flags = 0; } } -- GitLab From 96313f1b7a4b14c8e120564698aa3be709445324 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 24 Aug 2017 16:03:02 -0400 Subject: [PATCH 0834/2898] drm/amd/display: Fix MST downstream display not light up regression The fix is for the scenario: MST+SST chain together, and hook up to the card. Regression: Per stream validate_context build v2 Before dc_add_stream_to_ctx(), need to update/reset stream signal type to SIGNAL_TYPE_DISPLAY_PORT_MST. Otherwise, downstream device cannot be added to ctx due to the lack of signal type info (SIGNAL_TYPE_NONE). update_stream_signal() needs to be done after stream is created. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 25 ------------------- .../gpu/drm/amd/display/dc/core/dc_stream.c | 24 ++++++++++++++++++ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6eee1b1a563e..9eb8d48bc889 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1323,7 +1323,6 @@ bool dc_is_stream_unchanged( /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 -#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 static void update_stream_engine_usage( struct resource_context *res_ctx, @@ -1434,28 +1433,6 @@ static struct audio *find_first_free_audio( return 0; } -static void update_stream_signal(struct dc_stream_state *stream) -{ - if (stream->output_signal == SIGNAL_TYPE_NONE) { - struct dc_sink *dc_sink = stream->sink; - - if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) - stream->signal = stream->sink->link->connector_signal; - else - stream->signal = dc_sink->sink_signal; - } else { - stream->signal = stream->output_signal; - } - - if (dc_is_dvi_signal(stream->signal)) { - if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && - stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) - stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; - else - stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; - } -} - bool resource_is_stream_unchanged( struct validate_context *old_context, struct dc_stream_state *stream) { @@ -1627,8 +1604,6 @@ static int get_norm_pix_clk(const struct dc_crtc_timing *timing) static void calculate_phy_pix_clks(struct dc_stream_state *stream) { - update_stream_signal(stream); - /* update actual pixel clock on all streams */ if (dc_is_hdmi_signal(stream->signal)) stream->phy_pix_clk = get_norm_pix_clk( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index aaa6d2326190..0e7cc293184e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -33,6 +33,28 @@ /******************************************************************************* * Private functions ******************************************************************************/ +#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 +static void update_stream_signal(struct dc_stream_state *stream) +{ + if (stream->output_signal == SIGNAL_TYPE_NONE) { + struct dc_sink *dc_sink = stream->sink; + + if (dc_sink->sink_signal == SIGNAL_TYPE_NONE) + stream->signal = stream->sink->link->connector_signal; + else + stream->signal = dc_sink->sink_signal; + } else { + stream->signal = stream->output_signal; + } + + if (dc_is_dvi_signal(stream->signal)) { + if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && + stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) + stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; + else + stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; + } +} static bool construct(struct dc_stream_state *stream, struct dc_sink *dc_sink_data) @@ -80,6 +102,8 @@ static bool construct(struct dc_stream_state *stream, stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; stream->status.link = stream->sink->link; + + update_stream_signal(stream); return true; } -- GitLab From b656c34e24b5af59a5e8e1f0fbc740c3fc2d5ad8 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Thu, 24 Aug 2017 16:16:50 -0400 Subject: [PATCH 0835/2898] drm/amd/display: Update DSCL Signed-off-by: Eric Bernstein Signed-off-by: Tony Cheng Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 101 +++++------------- 1 file changed, 29 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 76d5f5d4d82f..33830639e210 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -215,14 +215,18 @@ static void dpp_set_lb( { uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; - REG_SET_7(LB_DATA_FORMAT, 0, - PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ - PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ - PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ - DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ - DITHER_EN, 0, /* Dithering enable: Disabled */ - INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ - ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + + /* LB */ + if (xfm->tf_mask->PIXEL_DEPTH) { + REG_SET_7(LB_DATA_FORMAT, 0, + PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ + PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ + PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */ + DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ + DITHER_EN, 0, /* Dithering enable: Disabled */ + INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ + ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + } REG_SET_2(LB_MEMORY_CTRL, 0, MEMORY_CONFIG, mem_size_config, @@ -462,7 +466,8 @@ static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data) +static enum lb_memory_config dpp10_find_lb_memory_config( + const struct scaler_data *scl_data) { int num_part_y, num_part_c; int vtaps = scl_data->taps.v_taps; @@ -504,6 +509,18 @@ static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl return LB_MEMORY_CONFIG_0; } +/*find first match configuration which meets the min required lb size*/ +static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, + const struct scaler_data *scl_data) +{ + enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; + + if (xfm->tf_mask->PIXEL_DEPTH) { + mem_cfg = dpp10_find_lb_memory_config(scl_data); + } + return mem_cfg; +} + void dpp_set_scaler_auto_scale( struct transform *xfm_base, const struct scaler_data *scl_data) @@ -524,7 +541,7 @@ void dpp_set_scaler_auto_scale( if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; - lb_config = find_lb_memory_config(scl_data); + lb_config = find_lb_memory_config(xfm, scl_data); dpp_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) @@ -662,8 +679,9 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; + /* LB */ - lb_config = find_lb_memory_config(scl_data); + lb_config = find_lb_memory_config(xfm, scl_data); dpp_set_lb(xfm, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) @@ -699,64 +717,3 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( dpp_set_scl_filter(xfm, scl_data, ycbcr); } - -#if 0 -bool dpp_set_pixel_storage_depth( - struct dpp *xfm, - enum lb_pixel_depth depth, - const struct bit_depth_reduction_params *bit_depth_params) -{ - struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm); - bool ret = true; - uint32_t value; - enum dc_color_depth color_depth; - - value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT)); - switch (depth) { - case LB_PIXEL_DEPTH_18BPP: - color_depth = COLOR_DEPTH_666; - set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_24BPP: - color_depth = COLOR_DEPTH_888; - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_30BPP: - color_depth = COLOR_DEPTH_101010; - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - case LB_PIXEL_DEPTH_36BPP: - color_depth = COLOR_DEPTH_121212; - set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH); - set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE); - break; - default: - ret = false; - break; - } - - if (ret == true) { - set_denormalization(xfm110, color_depth); - ret = program_bit_depth_reduction(xfm110, color_depth, - bit_depth_params); - - set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN); - dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value); - if (!(xfm110->lb_pixel_depth_supported & depth)) { - /* We should use unsupported capabilities - * unless it is required by w/a - */ - dm_logger_write(xfm->ctx->logger, LOG_WARNING, - "%s: Capability not supported", - __func__); - } - } - - return ret; -} -#endif - - -- GitLab From b3c340fad4643b7351a4777fae37e58925db04c9 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Sat, 19 Aug 2017 16:34:36 -0400 Subject: [PATCH 0836/2898] drm/amd/display: move cm registers from ipp to dpp_cm Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 150 ++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 489 ++++++++++++- .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 555 ++++++++++++++ .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 3 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 20 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 676 +----------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 416 ----------- .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 18 + drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 17 +- .../gpu/drm/amd/display/dc/inc/hw/transform.h | 20 + 10 files changed, 1239 insertions(+), 1125 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 30722495de0a..20163668e2a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -52,6 +52,12 @@ #define FN(reg_name, field_name) \ xfm->tf_shift->field_name, xfm->tf_mask->field_name +enum pixel_format_description { + PIXEL_FORMAT_FIXED = 0, + PIXEL_FORMAT_FIXED16, + PIXEL_FORMAT_FLOAT + +}; enum dcn10_coef_filter_type_sel { SCL_COEF_LUMA_VERT_FILTER = 0, @@ -249,6 +255,145 @@ static void dcn10_dpp_cm_set_regamma_mode( OBUF_H_2X_UPSCALE_EN, obuf_hupscale); } +static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ + enum pixel_format_description *fmt) +{ + + if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || + input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) + *fmt = PIXEL_FORMAT_FLOAT; + else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) + *fmt = PIXEL_FORMAT_FIXED16; + else + *fmt = PIXEL_FORMAT_FIXED; +} + +static void ippn10_set_degamma_format_float( + struct transform *xfm_base, + bool is_float) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + if (is_float) { + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1); + } else { + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2); + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0); + } +} + +void ippn10_cnv_setup ( + struct transform *xfm_base, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format cnv_out_format) +{ + uint32_t pixel_format; + uint32_t alpha_en; + enum pixel_format_description fmt ; + enum dc_color_space color_space; + enum dcn10_input_csc_select select; + bool is_float; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + bool force_disable_cursor = false; + + ippn10_setup_format_flags(input_format, &fmt); + alpha_en = 1; + pixel_format = 0; + color_space = COLOR_SPACE_SRGB; + select = INPUT_CSC_SELECT_BYPASS; + is_float = false; + + switch (fmt) { + case PIXEL_FORMAT_FIXED: + case PIXEL_FORMAT_FIXED16: + /*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/ + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode, + OUTPUT_FP, 0); + break; + case PIXEL_FORMAT_FLOAT: + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode, + OUTPUT_FP, 1); + is_float = true; + break; + default: + + break; + } + + ippn10_set_degamma_format_float(xfm_base, is_float); + + switch (input_format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + pixel_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + pixel_format = 3; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + pixel_format = 8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + pixel_format = 10; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + force_disable_cursor = false; + pixel_format = 65; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + force_disable_cursor = true; + pixel_format = 64; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + force_disable_cursor = true; + pixel_format = 67; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + force_disable_cursor = true; + pixel_format = 66; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + pixel_format = 22; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + pixel_format = 24; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + pixel_format = 25; + break; + default: + break; + } + REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, pixel_format); + REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); + + ippn10_program_input_csc(xfm_base, color_space, select); + + if (force_disable_cursor) { + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, 0); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, 0); + } +} + static struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, @@ -263,6 +408,11 @@ static struct transform_funcs dcn10_dpp_funcs = { .opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings, .opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl, .opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode, + .ipp_set_degamma = ippn10_set_degamma, + .ipp_program_input_lut = ippn10_program_input_lut, + .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, + .ipp_setup = ippn10_cnv_setup, + .ipp_full_bypass = ippn10_full_bypass, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 18ee338f6b28..9a678dcaa908 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -37,6 +37,10 @@ #define TF_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix +//Used to resolve corner case +#define TF2_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## _ ## field_name ## post_fix + #define TF_REG_LIST_DCN(id) \ SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ @@ -72,7 +76,65 @@ SRI(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id), \ SRI(RECOUT_START, DSCL, id), \ SRI(RECOUT_SIZE, DSCL, id), \ - SRI(OBUF_CONTROL, DSCL, id) + SRI(OBUF_CONTROL, DSCL, id), \ + SRI(CM_ICSC_CONTROL, CM, id), \ + SRI(CM_ICSC_C11_C12, CM, id), \ + SRI(CM_ICSC_C13_C14, CM, id), \ + SRI(CM_ICSC_C21_C22, CM, id), \ + SRI(CM_ICSC_C23_C24, CM, id), \ + SRI(CM_ICSC_C31_C32, CM, id), \ + SRI(CM_ICSC_C33_C34, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMB_START_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMB_SLOPE_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_B, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_B, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_G, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_G, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL1_R, CM, id), \ + SRI(CM_DGAM_RAMB_END_CNTL2_R, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_0_1, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_2_3, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_4_5, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_6_7, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_8_9, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_10_11, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_12_13, CM, id), \ + SRI(CM_DGAM_RAMB_REGION_14_15, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMA_START_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_B, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_G, CM, id), \ + SRI(CM_DGAM_RAMA_SLOPE_CNTL_R, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_B, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_B, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_G, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_G, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL1_R, CM, id), \ + SRI(CM_DGAM_RAMA_END_CNTL2_R, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_0_1, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_2_3, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_4_5, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_6_7, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_8_9, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_10_11, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ + SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ + SRI(CM_DGAM_LUT_INDEX, CM, id), \ + SRI(CM_DGAM_LUT_DATA, CM, id), \ + SRI(CM_CONTROL, CM, id), \ + SRI(CM_DGAM_CONTROL, CM, id), \ + SRI(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI(CURSOR0_CONTROL, CNVC_CUR, id) + + #define TF_REG_LIST_DCN10(id) \ TF_REG_LIST_DCN(id), \ @@ -157,7 +219,12 @@ SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ - SRI(CM_RGAM_CONTROL, CM, id) + SRI(CM_RGAM_CONTROL, CM, id), \ + SRI(CM_IGAM_CONTROL, CM, id), \ + SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ + SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ + SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ + SRI(CURSOR_CONTROL, CURSOR, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ @@ -183,7 +250,7 @@ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ - TF_SF(DSCL0_LB_DATA_FORMAT, ALPHA_EN, mask_sh),\ + TF2_SF(DSCL0, LB_DATA_FORMAT__ALPHA_EN, mask_sh),\ TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ @@ -235,7 +302,133 @@ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ - TF_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh) + TF_SF(DSCL0_OBUF_CONTROL, OBUF_BYPASS, mask_sh), \ + TF_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ + TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ + TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ + TF_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C13, mask_sh), \ + TF_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C14, mask_sh), \ + TF_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C21, mask_sh), \ + TF_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C22, mask_sh), \ + TF_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C23, mask_sh), \ + TF_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C24, mask_sh), \ + TF_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C31, mask_sh), \ + TF_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ + TF_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ + TF_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_B, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_G, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_R, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL1_B, CM_DGAM_RAMB_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL1_G, CM_DGAM_RAMB_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL1_R, CM_DGAM_RAMB_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_B, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_G, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_R, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL1_B, CM_DGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL1_G, CM_DGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL1_R, CM_DGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ + TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ + TF_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ + TF_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ + TF_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ + TF_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ + TF_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ + TF_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ + TF2_SF(CNVC_CFG0, FORMAT_CONTROL__ALPHA_EN, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh) #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ TF_REG_LIST_SH_MASK_DCN(mask_sh),\ @@ -459,8 +652,25 @@ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_CONTROL, CM_RGAM_LUT_MODE, mask_sh), \ - TF_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh) - + TF_SF(DSCL0_OBUF_CONTROL, OBUF_H_2X_UPSCALE_EN, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ + TF_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ + TF_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ + TF_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh), \ + TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh) #define TF_REG_FIELD_LIST(type) \ type EXT_OVERSCAN_LEFT; \ @@ -477,7 +687,7 @@ type DYNAMIC_PIXEL_DEPTH; \ type DITHER_EN; \ type INTERLEAVE_EN; \ - type ALPHA_EN; \ + type LB_DATA_FORMAT__ALPHA_EN; \ type MEMORY_CONFIG; \ type LB_MAX_PARTITIONS; \ type AUTOCAL_MODE; \ @@ -1123,7 +1333,154 @@ type CM_SHAPER_LUT_WRITE_EN_MASK; \ type CM_SHAPER_LUT_WRITE_SEL; \ type CM_SHAPER_LUT_INDEX; \ - type CM_SHAPER_LUT_DATA + type CM_SHAPER_LUT_DATA; \ + type CM_DGAM_CONFIG_STATUS; \ + type CM_ICSC_MODE; \ + type CM_ICSC_C11; \ + type CM_ICSC_C12; \ + type CM_ICSC_C13; \ + type CM_ICSC_C14; \ + type CM_ICSC_C21; \ + type CM_ICSC_C22; \ + type CM_ICSC_C23; \ + type CM_ICSC_C24; \ + type CM_ICSC_C31; \ + type CM_ICSC_C32; \ + type CM_ICSC_C33; \ + type CM_ICSC_C34; \ + type CM_DGAM_RAMB_EXP_REGION_START_B; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ + type CM_DGAM_RAMB_EXP_REGION_START_G; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ + type CM_DGAM_RAMB_EXP_REGION_START_R; \ + type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_B; \ + type CM_DGAM_RAMB_EXP_REGION_END_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_G; \ + type CM_DGAM_RAMB_EXP_REGION_END_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R; \ + type CM_DGAM_RAMB_EXP_REGION_END_BASE_R; \ + type CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ + type CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ + type CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION_START_B; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_DGAM_RAMA_EXP_REGION_START_G; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ + type CM_DGAM_RAMA_EXP_REGION_START_R; \ + type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ + type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_B; \ + type CM_DGAM_RAMA_EXP_REGION_END_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_G; \ + type CM_DGAM_RAMA_EXP_REGION_END_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R; \ + type CM_DGAM_RAMA_EXP_REGION_END_BASE_R; \ + type CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ + type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ + type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ + type SHARED_MEM_PWR_DIS; \ + type CM_IGAM_LUT_FORMAT_R; \ + type CM_IGAM_LUT_FORMAT_G; \ + type CM_IGAM_LUT_FORMAT_B; \ + type CM_IGAM_LUT_HOST_EN; \ + type CM_IGAM_LUT_RW_MODE; \ + type CM_IGAM_LUT_WRITE_EN_MASK; \ + type CM_IGAM_LUT_SEL; \ + type CM_IGAM_LUT_SEQ_COLOR; \ + type CM_IGAM_DGAM_CONFIG_STATUS; \ + type CM_DGAM_LUT_WRITE_EN_MASK; \ + type CM_DGAM_LUT_WRITE_SEL; \ + type CM_DGAM_LUT_INDEX; \ + type CM_DGAM_LUT_DATA; \ + type CM_DGAM_LUT_MODE; \ + type CM_IGAM_LUT_MODE; \ + type CM_IGAM_INPUT_FORMAT; \ + type CM_IGAM_LUT_RW_INDEX; \ + type CM_BYPASS_EN; \ + type FORMAT_EXPANSION_MODE; \ + type CNVC_BYPASS; \ + type OUTPUT_FP; \ + type CNVC_SURFACE_PIXEL_FORMAT; \ + type CURSOR_MODE; \ + type CURSOR_PITCH; \ + type CURSOR_LINES_PER_CHUNK; \ + type CURSOR_ENABLE; \ + type CUR0_MODE; \ + type CUR0_EXPANSION_MODE; \ + type CUR0_ENABLE; \ + type CM_BYPASS; \ + type FORMAT_CONTROL__ALPHA_EN + struct dcn_dpp_shift { @@ -1366,8 +1723,66 @@ struct dcn_dpp_registers { uint32_t CM_SHAPER_RAMA_REGION_32_33; uint32_t CM_SHAPER_LUT_INDEX; uint32_t CM_SHAPER_LUT_DATA; - - + uint32_t CM_ICSC_CONTROL; + uint32_t CM_ICSC_C11_C12; + uint32_t CM_ICSC_C13_C14; + uint32_t CM_ICSC_C21_C22; + uint32_t CM_ICSC_C23_C24; + uint32_t CM_ICSC_C31_C32; + uint32_t CM_ICSC_C33_C34; + uint32_t CM_DGAM_RAMB_START_CNTL_B; + uint32_t CM_DGAM_RAMB_START_CNTL_G; + uint32_t CM_DGAM_RAMB_START_CNTL_R; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; + uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; + uint32_t CM_DGAM_RAMB_END_CNTL1_B; + uint32_t CM_DGAM_RAMB_END_CNTL2_B; + uint32_t CM_DGAM_RAMB_END_CNTL1_G; + uint32_t CM_DGAM_RAMB_END_CNTL2_G; + uint32_t CM_DGAM_RAMB_END_CNTL1_R; + uint32_t CM_DGAM_RAMB_END_CNTL2_R; + uint32_t CM_DGAM_RAMB_REGION_0_1; + uint32_t CM_DGAM_RAMB_REGION_2_3; + uint32_t CM_DGAM_RAMB_REGION_4_5; + uint32_t CM_DGAM_RAMB_REGION_6_7; + uint32_t CM_DGAM_RAMB_REGION_8_9; + uint32_t CM_DGAM_RAMB_REGION_10_11; + uint32_t CM_DGAM_RAMB_REGION_12_13; + uint32_t CM_DGAM_RAMB_REGION_14_15; + uint32_t CM_DGAM_RAMA_START_CNTL_B; + uint32_t CM_DGAM_RAMA_START_CNTL_G; + uint32_t CM_DGAM_RAMA_START_CNTL_R; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; + uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; + uint32_t CM_DGAM_RAMA_END_CNTL1_B; + uint32_t CM_DGAM_RAMA_END_CNTL2_B; + uint32_t CM_DGAM_RAMA_END_CNTL1_G; + uint32_t CM_DGAM_RAMA_END_CNTL2_G; + uint32_t CM_DGAM_RAMA_END_CNTL1_R; + uint32_t CM_DGAM_RAMA_END_CNTL2_R; + uint32_t CM_DGAM_RAMA_REGION_0_1; + uint32_t CM_DGAM_RAMA_REGION_2_3; + uint32_t CM_DGAM_RAMA_REGION_4_5; + uint32_t CM_DGAM_RAMA_REGION_6_7; + uint32_t CM_DGAM_RAMA_REGION_8_9; + uint32_t CM_DGAM_RAMA_REGION_10_11; + uint32_t CM_DGAM_RAMA_REGION_12_13; + uint32_t CM_DGAM_RAMA_REGION_14_15; + uint32_t CM_DGAM_LUT_WRITE_EN_MASK; + uint32_t CM_DGAM_LUT_INDEX; + uint32_t CM_DGAM_LUT_DATA; + uint32_t CM_CONTROL; + uint32_t CM_DGAM_CONTROL; + uint32_t CM_IGAM_CONTROL; + uint32_t CM_IGAM_LUT_RW_CONTROL; + uint32_t CM_IGAM_LUT_RW_INDEX; + uint32_t CM_IGAM_LUT_SEQ_COLOR; + uint32_t FORMAT_CONTROL; + uint32_t CNVC_SURFACE_PIXEL_FORMAT; + uint32_t CURSOR_CONTROL; + uint32_t CURSOR0_CONTROL; }; struct dcn10_dpp { @@ -1387,6 +1802,52 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; +enum dcn10_input_csc_select { + INPUT_CSC_SELECT_BYPASS = 0, + INPUT_CSC_SELECT_ICSC, + INPUT_CSC_SELECT_COMA +}; + +void ippn10_degamma_ram_select( + struct transform *xfm_base, + bool use_ram_a); + +void ippn10_program_degamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params); + +void ippn10_program_degamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params); + +void ippn10_program_degamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num, + bool is_ram_a); + +void ippn10_power_on_degamma_lut( + struct transform *xfm_base, + bool power_on); + +void ippn10_program_input_csc( + struct transform *xfm_base, + enum dc_color_space color_space, + enum dcn10_input_csc_select select); + +void ippn10_program_input_lut( + struct transform *xfm_base, + const struct dc_gamma *gamma); + +void ippn10_full_bypass(struct transform *xfm_base); + +void ippn10_set_degamma( + struct transform *xfm_base, + enum ipp_degamma_mode mode); + +void ippn10_set_degamma_pwl(struct transform *xfm_base, + const struct pwl_params *params); + bool dpp_get_optimal_number_of_taps( struct transform *xfm, struct scaler_data *scl_data, @@ -1432,6 +1893,14 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( struct transform *xfm_base, const struct scaler_data *scl_data); +void ippn10_cnv_setup ( + struct transform *xfm_base, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format cnv_out_format); + +void ippn10_full_bypass(struct transform *xfm_base); + bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, uint32_t inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 9ff283bff007..409462f29f54 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -52,6 +52,11 @@ #define FN(reg_name, field_name) \ xfm->tf_shift->field_name, xfm->tf_mask->field_name +struct dcn10_input_csc_matrix { + enum dc_color_space color_space; + uint32_t regval[12]; +}; + enum dcn10_coef_filter_type_sel { SCL_COEF_LUMA_VERT_FILTER = 0, SCL_COEF_LUMA_HORZ_FILTER = 1, @@ -111,6 +116,26 @@ enum gamut_remap_select { GAMUT_REMAP_COMB_COEFF }; +static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { + {COLOR_SPACE_SRGB, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_SRGB_LIMITED, + {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, + {COLOR_SPACE_YCBCR601, + {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, + 0, 0x2000, 0x38b4, 0xe3a6} }, + {COLOR_SPACE_YCBCR601_LIMITED, + {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, + 0, 0x2568, 0x40de, 0xdd3a} }, + {COLOR_SPACE_YCBCR709, + {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, + 0x2000, 0x3b61, 0xe24f} }, + + {COLOR_SPACE_YCBCR709_LIMITED, + {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, + 0x2568, 0x43ee, 0xdbb2} } +}; + static void program_gamut_remap( struct dcn10_dpp *xfm, const uint16_t *regval, @@ -774,3 +799,533 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); } + +void ippn10_program_input_csc( + struct transform *xfm_base, + enum dc_color_space color_space, + enum dcn10_input_csc_select select) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + int i; + int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); + const uint32_t *regval = NULL; + uint32_t selection = 1; + + if (select == INPUT_CSC_SELECT_BYPASS) { + REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0); + return; + } + + for (i = 0; i < arr_size; i++) + if (dcn10_input_csc_matrix[i].color_space == color_space) { + regval = dcn10_input_csc_matrix[i].regval; + break; + } + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + if (select == INPUT_CSC_SELECT_COMA) + selection = 2; + REG_SET(CM_ICSC_CONTROL, 0, + CM_ICSC_MODE, selection); + + if (select == INPUT_CSC_SELECT_ICSC) { + /*R*/ + REG_SET_2(CM_ICSC_C11_C12, 0, + CM_ICSC_C11, regval[0], + CM_ICSC_C12, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C13_C14, 0, + CM_ICSC_C13, regval[0], + CM_ICSC_C14, regval[1]); + /*G*/ + regval += 2; + REG_SET_2(CM_ICSC_C21_C22, 0, + CM_ICSC_C21, regval[0], + CM_ICSC_C22, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C23_C24, 0, + CM_ICSC_C23, regval[0], + CM_ICSC_C24, regval[1]); + /*B*/ + regval += 2; + REG_SET_2(CM_ICSC_C31_C32, 0, + CM_ICSC_C31, regval[0], + CM_ICSC_C32, regval[1]); + regval += 2; + REG_SET_2(CM_ICSC_C33_C34, 0, + CM_ICSC_C33, regval[0], + CM_ICSC_C34, regval[1]); + } else { + /*R*/ + REG_SET_2(CM_COMA_C11_C12, 0, + CM_COMA_C11, regval[0], + CM_COMA_C12, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C13_C14, 0, + CM_COMA_C13, regval[0], + CM_COMA_C14, regval[1]); + /*G*/ + regval += 2; + REG_SET_2(CM_COMA_C21_C22, 0, + CM_COMA_C21, regval[0], + CM_COMA_C22, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C23_C24, 0, + CM_COMA_C23, regval[0], + CM_COMA_C24, regval[1]); + /*B*/ + regval += 2; + REG_SET_2(CM_COMA_C31_C32, 0, + CM_COMA_C31, regval[0], + CM_COMA_C32, regval[1]); + regval += 2; + REG_SET_2(CM_COMA_C33_C34, 0, + CM_COMA_C33, regval[0], + CM_COMA_C34, regval[1]); + } +} + +/*program de gamma RAM B*/ +void ippn10_program_degamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0, + CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0, + CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); + + REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0, + CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0, + CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0, + CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0, + CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0, + CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0, + CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, + CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); + + curve = params->arr_curve_points; + REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0, + CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0, + CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0, + CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0, + CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0, + CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0, + CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0, + CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0, + CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program de gamma RAM A*/ +void ippn10_program_degamma_luta_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0, + CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0, + CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); + + REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0, + CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, + CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0, + CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0, + CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0, + CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); + + REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0, + CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); + + REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0, + CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, + CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); + + curve = params->arr_curve_points; + REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0, + CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0, + CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0, + CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0, + CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0, + CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0, + CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0, + CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0, + CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); +} + +void ippn10_power_on_degamma_lut( + struct transform *xfm_base, + bool power_on) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_SET(CM_MEM_PWR_CTRL, 0, + SHARED_MEM_PWR_DIS, power_on == true ? 0:1); + +} + +static void ippn10_enable_cm_block( + struct transform *xfm_base) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); +} + +void ippn10_set_degamma( + struct transform *xfm_base, + enum ipp_degamma_mode mode) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + ippn10_enable_cm_block(xfm_base); + + switch (mode) { + case IPP_DEGAMMA_MODE_BYPASS: + /* Setting de gamma bypass for now */ + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0); + break; + case IPP_DEGAMMA_MODE_HW_sRGB: + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1); + break; + case IPP_DEGAMMA_MODE_HW_xvYCC: + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } +} + +void ippn10_degamma_ram_select( + struct transform *xfm_base, + bool use_ram_a) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + if (use_ram_a) + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); + else + REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4); + +} + +static bool ippn10_degamma_ram_inuse( + struct transform *xfm_base, + bool *ram_a_inuse) +{ + bool ret = false; + uint32_t status_reg = 0; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + + if (status_reg == 9) { + *ram_a_inuse = true; + ret = true; + } else if (status_reg == 10) { + *ram_a_inuse = false; + ret = true; + } + return ret; +} + +void ippn10_program_degamma_lut( + struct transform *xfm_base, + const struct pwl_result_data *rgb, + uint32_t num, + bool is_ram_a) +{ + uint32_t i; + + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); + REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, + CM_DGAM_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, + is_ram_a == true ? 0:1); + + REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0); + for (i = 0 ; i < num; i++) { + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_red_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_green_reg); + REG_SET(CM_DGAM_LUT_DATA, 0, + CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg); + } +} + +void ippn10_set_degamma_pwl(struct transform *xfm_base, + const struct pwl_params *params) +{ + bool is_ram_a = true; + + ippn10_power_on_degamma_lut(xfm_base, true); + ippn10_enable_cm_block(xfm_base); + ippn10_degamma_ram_inuse(xfm_base, &is_ram_a); + if (is_ram_a == true) + ippn10_program_degamma_lutb_settings(xfm_base, params); + else + ippn10_program_degamma_luta_settings(xfm_base, params); + + ippn10_program_degamma_lut(xfm_base, params->rgb_resulted, + params->hw_points_num, !is_ram_a); + ippn10_degamma_ram_select(xfm_base, !is_ram_a); +} + +void ippn10_full_bypass(struct transform *xfm_base) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + /* Input pixel format: ARGB8888 */ + REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, 0x8); + + /* Zero expansion */ + REG_SET_3(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_CONTROL__ALPHA_EN, 0, + FORMAT_EXPANSION_MODE, 0); + + /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ + REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); + + /* Setting degamma bypass for now */ + REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); + REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); +} + +static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, + bool *ram_a_inuse) +{ + bool in_use = false; + uint32_t status_reg = 0; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + + REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, + &status_reg); + + // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB + if (status_reg == 1 || status_reg == 3 || status_reg == 4) { + *ram_a_inuse = true; + in_use = true; + // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB + } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) { + *ram_a_inuse = false; + in_use = true; + } + return in_use; +} + +/* + * Input gamma LUT currently supports 256 values only. This means input color + * can have a maximum of 8 bits per channel (= 256 possible values) in order to + * have a one-to-one mapping with the LUT. Truncation will occur with color + * values greater than 8 bits. + * + * In the future, this function should support additional input gamma methods, + * such as piecewise linear mapping, and input gamma bypass. + */ +void ippn10_program_input_lut( + struct transform *xfm_base, + const struct dc_gamma *gamma) +{ + int i; + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + bool rama_occupied = false; + uint32_t ram_num; + // Power on LUT memory. + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); + ippn10_enable_cm_block(xfm_base); + // Determine whether to use RAM A or RAM B + ippn10_ingamma_ram_inuse(xfm_base, &rama_occupied); + if (!rama_occupied) + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); + else + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1); + // RW mode is 256-entry LUT + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0); + // IGAM Input format should be 8 bits per channel. + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0); + // Do not mask any R,G,B values + REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7); + // LUT-256, unsigned, integer, new u0.12 format + REG_UPDATE_3( + CM_IGAM_CONTROL, + CM_IGAM_LUT_FORMAT_R, 3, + CM_IGAM_LUT_FORMAT_G, 3, + CM_IGAM_LUT_FORMAT_B, 3); + // Start at index 0 of IGAM LUT + REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); + for (i = 0; i < gamma->num_entries; i++) { + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.red[i])); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.green[i])); + REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, + dal_fixed31_32_round( + gamma->entries.blue[i])); + } + // Power off LUT memory + REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); + // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB + REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2); + REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 33830639e210..14c3b330b27b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -225,7 +225,7 @@ static void dpp_set_lb( DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */ DITHER_EN, 0, /* Dithering enable: Disabled */ INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */ - ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ + LB_DATA_FORMAT__ALPHA_EN, lb_params->alpha_en); /* Alpha enable */ } REG_SET_2(LB_MEMORY_CTRL, 0, @@ -716,4 +716,3 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( dpp_set_scl_filter(xfm, scl_data, ycbcr); } - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 498680a9b996..4a24893486e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1294,34 +1294,34 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct transform *xfm_base = pipe_ctx->plane_res.xfm; const struct dc_transfer_func *tf = NULL; bool result = true; - if (ipp == NULL) + if (xfm_base == NULL) return false; if (plane_state->in_transfer_func) tf = plane_state->in_transfer_func; if (plane_state->gamma_correction && dce_use_lut(plane_state)) - ipp->funcs->ipp_program_input_lut(ipp, + xfm_base->funcs->ipp_program_input_lut(xfm_base, plane_state->gamma_correction); if (tf == NULL) - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); else if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: - ipp->funcs->ipp_set_degamma(ipp, + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709: - ipp->funcs->ipp_set_degamma(ipp, + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR: - ipp->funcs->ipp_set_degamma(ipp, + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ: @@ -1332,7 +1332,7 @@ static bool dcn10_set_input_transfer_func( break; } } else if (tf->type == TF_TYPE_BYPASS) { - ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS); + xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS*/ result = false; @@ -2204,7 +2204,7 @@ static void update_dchubp_dpp( { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->plane_res.mi; - struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; struct default_adjustment ocsc = {0}; @@ -2249,7 +2249,7 @@ static void update_dchubp_dpp( hws ); - ipp->funcs->ipp_setup(ipp, + xfm->funcs->ipp_setup(xfm, plane_state->format, 1, IPP_OUTPUT_FORMAT_12_BIT_FIX); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 8ee830522148..bc9827967535 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -69,403 +69,7 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; -static void ippn10_program_input_csc( - struct input_pixel_processor *ipp, - enum dc_color_space color_space, - enum dcn10_input_csc_select select) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - int i; - int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); - const uint32_t *regval = NULL; - uint32_t selection = 1; - - if (select == INPUT_CSC_SELECT_BYPASS) { - REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0); - return; - } - - for (i = 0; i < arr_size; i++) - if (dcn10_input_csc_matrix[i].color_space == color_space) { - regval = dcn10_input_csc_matrix[i].regval; - break; - } - - if (regval == NULL) { - BREAK_TO_DEBUGGER(); - return; - } - - if (select == INPUT_CSC_SELECT_COMA) - selection = 2; - REG_SET(CM_ICSC_CONTROL, 0, - CM_ICSC_MODE, selection); - - if (select == INPUT_CSC_SELECT_ICSC) { - /*R*/ - REG_SET_2(CM_ICSC_C11_C12, 0, - CM_ICSC_C11, regval[0], - CM_ICSC_C12, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C13_C14, 0, - CM_ICSC_C13, regval[0], - CM_ICSC_C14, regval[1]); - /*G*/ - regval += 2; - REG_SET_2(CM_ICSC_C21_C22, 0, - CM_ICSC_C21, regval[0], - CM_ICSC_C22, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C23_C24, 0, - CM_ICSC_C23, regval[0], - CM_ICSC_C24, regval[1]); - /*B*/ - regval += 2; - REG_SET_2(CM_ICSC_C31_C32, 0, - CM_ICSC_C31, regval[0], - CM_ICSC_C32, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C33_C34, 0, - CM_ICSC_C33, regval[0], - CM_ICSC_C34, regval[1]); - } else { - /*R*/ - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - /*G*/ - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - /*B*/ - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); - } -} - -/*program de gamma RAM B*/ -static void ippn10_program_degamma_lutb_settings( - struct input_pixel_processor *ipp, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0, - CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0, - CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0, - CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0, - CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0, - CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0, - CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); - - curve = params->arr_curve_points; - REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0, - CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0, - CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0, - CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0, - CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0, - CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0, - CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0, - CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0, - CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); -} - -/*program de gamma RAM A*/ -static void ippn10_program_degamma_luta_settings( - struct input_pixel_processor *ipp, - const struct pwl_params *params) -{ - const struct gamma_curve *curve; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0, - CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0, - CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0, - CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0, - CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0, - CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0, - CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); - - curve = params->arr_curve_points; - REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0, - CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0, - CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0, - CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0, - CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0, - CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0, - CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0, - CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0, - CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); -} - -static void ippn10_power_on_degamma_lut( - struct input_pixel_processor *ipp, - bool power_on) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_SET(CM_MEM_PWR_CTRL, 0, - SHARED_MEM_PWR_DIS, power_on == true ? 0:1); -} - -static void ippn10_program_degamma_lut( - struct input_pixel_processor *ipp, - const struct pwl_result_data *rgb, - uint32_t num, - bool is_ram_a) -{ - uint32_t i; - - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); - REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, - CM_DGAM_LUT_WRITE_EN_MASK, 7); - REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, - is_ram_a == true ? 0:1); - - REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0); - for (i = 0 ; i < num; i++) { - REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg); - REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg); - REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg); - - REG_SET(CM_DGAM_LUT_DATA, 0, - CM_DGAM_LUT_DATA, rgb[i].delta_red_reg); - REG_SET(CM_DGAM_LUT_DATA, 0, - CM_DGAM_LUT_DATA, rgb[i].delta_green_reg); - REG_SET(CM_DGAM_LUT_DATA, 0, - CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg); - } -} - -static void ippn10_enable_cm_block( - struct input_pixel_processor *ipp) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); -} - -static void ippn10_full_bypass(struct input_pixel_processor *ipp) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - /* Input pixel format: ARGB8888 */ - REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, - CNVC_SURFACE_PIXEL_FORMAT, 0x8); - - /* Zero expansion */ - REG_SET_3(FORMAT_CONTROL, 0, - CNVC_BYPASS, 0, - ALPHA_EN, 0, - FORMAT_EXPANSION_MODE, 0); - - /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ - REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); - - /* Setting degamma bypass for now */ - REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); - REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); -} - -static void ippn10_set_degamma( - struct input_pixel_processor *ipp, - enum ipp_degamma_mode mode) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - ippn10_enable_cm_block(ipp); - - switch (mode) { - case IPP_DEGAMMA_MODE_BYPASS: - /* Setting de gamma bypass for now */ - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0); - break; - case IPP_DEGAMMA_MODE_HW_sRGB: - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1); - break; - case IPP_DEGAMMA_MODE_HW_xvYCC: - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2); - break; - default: - BREAK_TO_DEBUGGER(); - break; - } -} static bool ippn10_cursor_program_control( struct dcn10_ipp *ippn10, @@ -658,276 +262,6 @@ enum pixel_format_description { }; -static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ - enum pixel_format_description *fmt) -{ - - if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F || - input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) - *fmt = PIXEL_FORMAT_FLOAT; - else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616) - *fmt = PIXEL_FORMAT_FIXED16; - else - *fmt = PIXEL_FORMAT_FIXED; -} - -static void ippn10_set_degamma_format_float(struct input_pixel_processor *ipp, - bool is_float) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - if (is_float) { - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1); - } else { - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2); - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0); - } -} - - -static void ippn10_cnv_setup ( - struct input_pixel_processor *ipp, - enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format cnv_out_format) -{ - uint32_t pixel_format; - uint32_t alpha_en; - enum pixel_format_description fmt ; - enum dc_color_space color_space; - enum dcn10_input_csc_select select; - bool is_float; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - bool force_disable_cursor = false; - - ippn10_setup_format_flags(input_format, &fmt); - alpha_en = 1; - pixel_format = 0; - color_space = COLOR_SPACE_SRGB; - select = INPUT_CSC_SELECT_BYPASS; - is_float = false; - - switch (fmt) { - case PIXEL_FORMAT_FIXED: - case PIXEL_FORMAT_FIXED16: - /*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/ - REG_SET_3(FORMAT_CONTROL, 0, - CNVC_BYPASS, 0, - FORMAT_EXPANSION_MODE, mode, - OUTPUT_FP, 0); - break; - case PIXEL_FORMAT_FLOAT: - REG_SET_3(FORMAT_CONTROL, 0, - CNVC_BYPASS, 0, - FORMAT_EXPANSION_MODE, mode, - OUTPUT_FP, 1); - is_float = true; - break; - default: - - break; - } - - ippn10_set_degamma_format_float(ipp, is_float); - - switch (input_format) { - case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: - pixel_format = 1; - break; - case SURFACE_PIXEL_FORMAT_GRPH_RGB565: - pixel_format = 3; - alpha_en = 0; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: - pixel_format = 8; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: - pixel_format = 10; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: - force_disable_cursor = false; - pixel_format = 65; - color_space = COLOR_SPACE_YCBCR709; - select = INPUT_CSC_SELECT_ICSC; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: - force_disable_cursor = true; - pixel_format = 64; - color_space = COLOR_SPACE_YCBCR709; - select = INPUT_CSC_SELECT_ICSC; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: - force_disable_cursor = true; - pixel_format = 67; - color_space = COLOR_SPACE_YCBCR709; - select = INPUT_CSC_SELECT_ICSC; - break; - case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: - force_disable_cursor = true; - pixel_format = 66; - color_space = COLOR_SPACE_YCBCR709; - select = INPUT_CSC_SELECT_ICSC; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: - pixel_format = 22; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: - pixel_format = 24; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - pixel_format = 25; - break; - default: - break; - } - REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, - CNVC_SURFACE_PIXEL_FORMAT, pixel_format); - REG_UPDATE(FORMAT_CONTROL, ALPHA_EN, alpha_en); - - ippn10_program_input_csc(ipp, color_space, select); - - if (force_disable_cursor) { - REG_UPDATE(CURSOR_CONTROL, - CURSOR_ENABLE, 0); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_ENABLE, 0); - } -} - - -static bool ippn10_degamma_ram_inuse(struct input_pixel_processor *ipp, - bool *ram_a_inuse) -{ - bool ret = false; - uint32_t status_reg = 0; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, - &status_reg); - - if (status_reg == 9) { - *ram_a_inuse = true; - ret = true; - } else if (status_reg == 10) { - *ram_a_inuse = false; - ret = true; - } - return ret; -} - -static bool ippn10_ingamma_ram_inuse(struct input_pixel_processor *ipp, - bool *ram_a_inuse) -{ - bool in_use = false; - uint32_t status_reg = 0; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, - &status_reg); - - // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB - if (status_reg == 1 || status_reg == 3 || status_reg == 4) { - *ram_a_inuse = true; - in_use = true; - // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB - } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) { - *ram_a_inuse = false; - in_use = true; - } - return in_use; -} - -static void ippn10_degamma_ram_select(struct input_pixel_processor *ipp, - bool use_ram_a) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - - if (use_ram_a) - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); - else - REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4); - -} - -static void ippn10_set_degamma_pwl(struct input_pixel_processor *ipp, - const struct pwl_params *params) -{ - bool is_ram_a = true; - - ippn10_power_on_degamma_lut(ipp, true); - ippn10_enable_cm_block(ipp); - ippn10_degamma_ram_inuse(ipp, &is_ram_a); - if (is_ram_a == true) - ippn10_program_degamma_lutb_settings(ipp, params); - else - ippn10_program_degamma_luta_settings(ipp, params); - - ippn10_program_degamma_lut(ipp, params->rgb_resulted, - params->hw_points_num, !is_ram_a); - ippn10_degamma_ram_select(ipp, !is_ram_a); -} - -/* - * Input gamma LUT currently supports 256 values only. This means input color - * can have a maximum of 8 bits per channel (= 256 possible values) in order to - * have a one-to-one mapping with the LUT. Truncation will occur with color - * values greater than 8 bits. - * - * In the future, this function should support additional input gamma methods, - * such as piecewise linear mapping, and input gamma bypass. - */ -static void ippn10_program_input_lut( - struct input_pixel_processor *ipp, - const struct dc_gamma *gamma) -{ - int i; - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - bool rama_occupied = false; - uint32_t ram_num; - // Power on LUT memory. - REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); - ippn10_enable_cm_block(ipp); - // Determine whether to use RAM A or RAM B - ippn10_ingamma_ram_inuse(ipp, &rama_occupied); - if (!rama_occupied) - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); - else - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1); - // RW mode is 256-entry LUT - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0); - // IGAM Input format should be 8 bits per channel. - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0); - // Do not mask any R,G,B values - REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7); - // LUT-256, unsigned, integer, new u0.12 format - REG_UPDATE_3( - CM_IGAM_CONTROL, - CM_IGAM_LUT_FORMAT_R, 3, - CM_IGAM_LUT_FORMAT_G, 3, - CM_IGAM_LUT_FORMAT_B, 3); - // Start at index 0 of IGAM LUT - REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0); - for (i = 0; i < gamma->num_entries; i++) { - REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - dal_fixed31_32_round( - gamma->entries.red[i])); - REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - dal_fixed31_32_round( - gamma->entries.green[i])); - REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR, - dal_fixed31_32_round( - gamma->entries.blue[i])); - } - // Power off LUT memory - REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0); - // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB - REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2); - REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num); -} - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -941,11 +275,11 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) static const struct ipp_funcs dcn10_ipp_funcs = { .ipp_cursor_set_attributes = ippn10_cursor_set_attributes, .ipp_cursor_set_position = ippn10_cursor_set_position, - .ipp_set_degamma = ippn10_set_degamma, - .ipp_program_input_lut = ippn10_program_input_lut, - .ipp_full_bypass = ippn10_full_bypass, - .ipp_setup = ippn10_cnv_setup, - .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, + .ipp_set_degamma = NULL, + .ipp_program_input_lut = NULL, + .ipp_full_bypass = NULL, + .ipp_setup = NULL, + .ipp_program_degamma_pwl = NULL, .ipp_destroy = dcn10_ipp_destroy }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index 69db441e78c4..e4f292822975 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -32,59 +32,6 @@ container_of(ipp, struct dcn10_ipp, base) #define IPP_REG_LIST_DCN(id) \ - SRI(CM_ICSC_CONTROL, CM, id), \ - SRI(CM_ICSC_C11_C12, CM, id), \ - SRI(CM_ICSC_C13_C14, CM, id), \ - SRI(CM_ICSC_C21_C22, CM, id), \ - SRI(CM_ICSC_C23_C24, CM, id), \ - SRI(CM_ICSC_C31_C32, CM, id), \ - SRI(CM_ICSC_C33_C34, CM, id), \ - SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ - SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ - SRI(CM_DGAM_RAMB_START_CNTL_R, CM, id), \ - SRI(CM_DGAM_RAMB_SLOPE_CNTL_B, CM, id), \ - SRI(CM_DGAM_RAMB_SLOPE_CNTL_G, CM, id), \ - SRI(CM_DGAM_RAMB_SLOPE_CNTL_R, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL1_B, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL2_B, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL1_G, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL2_G, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL1_R, CM, id), \ - SRI(CM_DGAM_RAMB_END_CNTL2_R, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_0_1, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_2_3, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_4_5, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_6_7, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_8_9, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_10_11, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_12_13, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_14_15, CM, id), \ - SRI(CM_DGAM_RAMA_START_CNTL_B, CM, id), \ - SRI(CM_DGAM_RAMA_START_CNTL_G, CM, id), \ - SRI(CM_DGAM_RAMA_START_CNTL_R, CM, id), \ - SRI(CM_DGAM_RAMA_SLOPE_CNTL_B, CM, id), \ - SRI(CM_DGAM_RAMA_SLOPE_CNTL_G, CM, id), \ - SRI(CM_DGAM_RAMA_SLOPE_CNTL_R, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL1_B, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL2_B, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL1_G, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL2_G, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL1_R, CM, id), \ - SRI(CM_DGAM_RAMA_END_CNTL2_R, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_0_1, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_2_3, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_4_5, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_6_7, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_8_9, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_10_11, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ - SRI(CM_MEM_PWR_CTRL, CM, id), \ - SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ - SRI(CM_DGAM_LUT_INDEX, CM, id), \ - SRI(CM_DGAM_LUT_DATA, CM, id), \ - SRI(CM_CONTROL, CM, id), \ - SRI(CM_DGAM_CONTROL, CM, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(DPP_CONTROL, DPP_TOP, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ @@ -95,16 +42,6 @@ #define IPP_REG_LIST_DCN10(id) \ IPP_REG_LIST_DCN(id), \ SRI(CURSOR_SETTINS, HUBPREQ, id), \ - SRI(CM_IGAM_CONTROL, CM, id), \ - SRI(CM_COMA_C11_C12, CM, id), \ - SRI(CM_COMA_C13_C14, CM, id), \ - SRI(CM_COMA_C21_C22, CM, id), \ - SRI(CM_COMA_C23_C24, CM, id), \ - SRI(CM_COMA_C31_C32, CM, id), \ - SRI(CM_COMA_C33_C34, CM, id), \ - SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ - SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ - SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ SRI(CURSOR_SIZE, CURSOR, id), \ @@ -117,129 +54,10 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define IPP_MASK_SH_LIST_DCN(mask_sh) \ - IPP_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C13, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C14, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C21, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C22, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C23, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C24, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C31, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ - IPP_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_G, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_START_CNTL_R, CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_B, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_G, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_SLOPE_CNTL_R, CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_B, CM_DGAM_RAMB_EXP_REGION_END_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_B, CM_DGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_G, CM_DGAM_RAMB_EXP_REGION_END_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_G, CM_DGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL1_R, CM_DGAM_RAMB_EXP_REGION_END_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_END_CNTL2_R, CM_DGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_B, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_G, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_START_CNTL_R, CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_B, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_G, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_SLOPE_CNTL_R, CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_B, CM_DGAM_RAMA_EXP_REGION_END_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_B, CM_DGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_G, CM_DGAM_RAMA_EXP_REGION_END_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_G, CM_DGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL1_R, CM_DGAM_RAMA_EXP_REGION_END_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_END_CNTL2_R, CM_DGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - IPP_SF(CM0_CM_MEM_PWR_CTRL, SHARED_MEM_PWR_DIS, mask_sh), \ - IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, mask_sh), \ - IPP_SF(CM0_CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL, mask_sh), \ - IPP_SF(CM0_CM_DGAM_LUT_INDEX, CM_DGAM_LUT_INDEX, mask_sh), \ - IPP_SF(CM0_CM_DGAM_LUT_DATA, CM_DGAM_LUT_DATA, mask_sh), \ IPP_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, ALPHA_EN, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ - IPP_SF(CM0_CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ IPP_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ @@ -250,26 +68,6 @@ IPP_MASK_SH_LIST_DCN(mask_sh),\ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ IPP_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ - IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh), \ - IPP_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh), \ - IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh), \ - IPP_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh), \ - IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh), \ - IPP_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh), \ - IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh), \ - IPP_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh), \ - IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh), \ - IPP_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh), \ - IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh), \ - IPP_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, mask_sh), \ - IPP_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ - IPP_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ @@ -283,163 +81,13 @@ IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ IPP_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ IPP_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_R, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_G, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_LUT_FORMAT_B, mask_sh), \ - IPP_SF(CM0_CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, mask_sh), \ IPP_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh) #define IPP_DCN10_REG_FIELD_LIST(type) \ - type CM_DGAM_CONFIG_STATUS; \ - type CM_ICSC_MODE; \ - type CM_ICSC_C11; \ - type CM_ICSC_C12; \ - type CM_ICSC_C13; \ - type CM_ICSC_C14; \ - type CM_ICSC_C21; \ - type CM_ICSC_C22; \ - type CM_ICSC_C23; \ - type CM_ICSC_C24; \ - type CM_ICSC_C31; \ - type CM_ICSC_C32; \ - type CM_ICSC_C33; \ - type CM_ICSC_C34; \ - type CM_COMA_C11; \ - type CM_COMA_C12; \ - type CM_COMA_C13; \ - type CM_COMA_C14; \ - type CM_COMA_C21; \ - type CM_COMA_C22; \ - type CM_COMA_C23; \ - type CM_COMA_C24; \ - type CM_COMA_C31; \ - type CM_COMA_C32; \ - type CM_COMA_C33; \ - type CM_COMA_C34; \ - type CM_DGAM_RAMB_EXP_REGION_START_B; \ - type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; \ - type CM_DGAM_RAMB_EXP_REGION_START_G; \ - type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G; \ - type CM_DGAM_RAMB_EXP_REGION_START_R; \ - type CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R; \ - type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ - type CM_DGAM_RAMB_EXP_REGION_END_B; \ - type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B; \ - type CM_DGAM_RAMB_EXP_REGION_END_BASE_B; \ - type CM_DGAM_RAMB_EXP_REGION_END_G; \ - type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G; \ - type CM_DGAM_RAMB_EXP_REGION_END_BASE_G; \ - type CM_DGAM_RAMB_EXP_REGION_END_R; \ - type CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R; \ - type CM_DGAM_RAMB_EXP_REGION_END_BASE_R; \ - type CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION_START_B; \ - type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B; \ - type CM_DGAM_RAMA_EXP_REGION_START_G; \ - type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G; \ - type CM_DGAM_RAMA_EXP_REGION_START_R; \ - type CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R; \ - type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ - type CM_DGAM_RAMA_EXP_REGION_END_B; \ - type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B; \ - type CM_DGAM_RAMA_EXP_REGION_END_BASE_B; \ - type CM_DGAM_RAMA_EXP_REGION_END_G; \ - type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G; \ - type CM_DGAM_RAMA_EXP_REGION_END_BASE_G; \ - type CM_DGAM_RAMA_EXP_REGION_END_R; \ - type CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R; \ - type CM_DGAM_RAMA_EXP_REGION_END_BASE_R; \ - type CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ - type SHARED_MEM_PWR_DIS; \ - type CM_IGAM_LUT_FORMAT_R; \ - type CM_IGAM_LUT_FORMAT_G; \ - type CM_IGAM_LUT_FORMAT_B; \ - type CM_IGAM_LUT_HOST_EN; \ - type CM_IGAM_LUT_RW_INDEX; \ - type CM_IGAM_LUT_RW_MODE; \ - type CM_IGAM_LUT_WRITE_EN_MASK; \ - type CM_IGAM_LUT_SEL; \ - type CM_IGAM_LUT_SEQ_COLOR; \ - type CM_IGAM_DGAM_CONFIG_STATUS; \ - type CM_DGAM_LUT_WRITE_EN_MASK; \ - type CM_DGAM_LUT_WRITE_SEL; \ - type CM_DGAM_LUT_INDEX; \ - type CM_DGAM_LUT_DATA; \ - type CM_BYPASS_EN; \ - type CM_BYPASS; \ type CNVC_SURFACE_PIXEL_FORMAT; \ type CNVC_BYPASS; \ type ALPHA_EN; \ type FORMAT_EXPANSION_MODE; \ - type CM_DGAM_LUT_MODE; \ - type CM_IGAM_LUT_MODE; \ type CURSOR0_DST_Y_OFFSET; \ type CURSOR0_CHUNK_HDL_ADJUST; \ type CUR0_MODE; \ @@ -460,7 +108,6 @@ type CURSOR_HOT_SPOT_X; \ type CURSOR_HOT_SPOT_Y; \ type CURSOR_DST_X_OFFSET; \ - type CM_IGAM_INPUT_FORMAT; \ type OUTPUT_FP struct dcn10_ipp_shift { @@ -472,69 +119,6 @@ struct dcn10_ipp_mask { }; struct dcn10_ipp_registers { - uint32_t CM_ICSC_CONTROL; - uint32_t CM_ICSC_C11_C12; - uint32_t CM_ICSC_C13_C14; - uint32_t CM_ICSC_C21_C22; - uint32_t CM_ICSC_C23_C24; - uint32_t CM_ICSC_C31_C32; - uint32_t CM_ICSC_C33_C34; - uint32_t CM_COMA_C11_C12; - uint32_t CM_COMA_C13_C14; - uint32_t CM_COMA_C21_C22; - uint32_t CM_COMA_C23_C24; - uint32_t CM_COMA_C31_C32; - uint32_t CM_COMA_C33_C34; - uint32_t CM_DGAM_RAMB_START_CNTL_B; - uint32_t CM_DGAM_RAMB_START_CNTL_G; - uint32_t CM_DGAM_RAMB_START_CNTL_R; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_B; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_G; - uint32_t CM_DGAM_RAMB_SLOPE_CNTL_R; - uint32_t CM_DGAM_RAMB_END_CNTL1_B; - uint32_t CM_DGAM_RAMB_END_CNTL2_B; - uint32_t CM_DGAM_RAMB_END_CNTL1_G; - uint32_t CM_DGAM_RAMB_END_CNTL2_G; - uint32_t CM_DGAM_RAMB_END_CNTL1_R; - uint32_t CM_DGAM_RAMB_END_CNTL2_R; - uint32_t CM_DGAM_RAMB_REGION_0_1; - uint32_t CM_DGAM_RAMB_REGION_2_3; - uint32_t CM_DGAM_RAMB_REGION_4_5; - uint32_t CM_DGAM_RAMB_REGION_6_7; - uint32_t CM_DGAM_RAMB_REGION_8_9; - uint32_t CM_DGAM_RAMB_REGION_10_11; - uint32_t CM_DGAM_RAMB_REGION_12_13; - uint32_t CM_DGAM_RAMB_REGION_14_15; - uint32_t CM_DGAM_RAMA_START_CNTL_B; - uint32_t CM_DGAM_RAMA_START_CNTL_G; - uint32_t CM_DGAM_RAMA_START_CNTL_R; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_B; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_G; - uint32_t CM_DGAM_RAMA_SLOPE_CNTL_R; - uint32_t CM_DGAM_RAMA_END_CNTL1_B; - uint32_t CM_DGAM_RAMA_END_CNTL2_B; - uint32_t CM_DGAM_RAMA_END_CNTL1_G; - uint32_t CM_DGAM_RAMA_END_CNTL2_G; - uint32_t CM_DGAM_RAMA_END_CNTL1_R; - uint32_t CM_DGAM_RAMA_END_CNTL2_R; - uint32_t CM_DGAM_RAMA_REGION_0_1; - uint32_t CM_DGAM_RAMA_REGION_2_3; - uint32_t CM_DGAM_RAMA_REGION_4_5; - uint32_t CM_DGAM_RAMA_REGION_6_7; - uint32_t CM_DGAM_RAMA_REGION_8_9; - uint32_t CM_DGAM_RAMA_REGION_10_11; - uint32_t CM_DGAM_RAMA_REGION_12_13; - uint32_t CM_DGAM_RAMA_REGION_14_15; - uint32_t CM_MEM_PWR_CTRL; - uint32_t CM_IGAM_LUT_RW_CONTROL; - uint32_t CM_IGAM_LUT_RW_INDEX; - uint32_t CM_IGAM_LUT_SEQ_COLOR; - uint32_t CM_DGAM_LUT_WRITE_EN_MASK; - uint32_t CM_DGAM_LUT_INDEX; - uint32_t CM_DGAM_LUT_DATA; - uint32_t CM_CONTROL; - uint32_t CM_DGAM_CONTROL; - uint32_t CM_IGAM_CONTROL; uint32_t DPP_CONTROL; uint32_t CURSOR_SETTINS; uint32_t CURSOR_SETTINGS; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 589bddad7e66..9602f261b614 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -98,6 +98,24 @@ enum graphics_csc_adjust_type { GRAPHICS_CSC_ADJUST_TYPE_SW /*use adjustments */ }; +enum ipp_degamma_mode { + IPP_DEGAMMA_MODE_BYPASS, + IPP_DEGAMMA_MODE_HW_sRGB, + IPP_DEGAMMA_MODE_HW_xvYCC, + IPP_DEGAMMA_MODE_USER_PWL +}; + +enum ipp_output_format { + IPP_OUTPUT_FORMAT_12_BIT_FIX, + IPP_OUTPUT_FORMAT_16_BIT_BYPASS, + IPP_OUTPUT_FORMAT_FLOAT +}; + +enum expansion_mode { + EXPANSION_MODE_DYNAMIC, + EXPANSION_MODE_ZERO +}; + struct default_adjustment { enum lb_pixel_depth lb_color_depth; enum dc_color_space out_color_space; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 0f952e5b3ae8..7ebfdc1c19c1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -54,12 +54,7 @@ struct ipp_prescale_params { uint16_t scale; }; -enum ipp_degamma_mode { - IPP_DEGAMMA_MODE_BYPASS, - IPP_DEGAMMA_MODE_HW_sRGB, - IPP_DEGAMMA_MODE_HW_xvYCC, - IPP_DEGAMMA_MODE_USER_PWL -}; + enum ovl_color_space { OVL_COLOR_SPACE_UNKNOWN = 0, @@ -68,16 +63,6 @@ enum ovl_color_space { OVL_COLOR_SPACE_YUV709 }; -enum expansion_mode { - EXPANSION_MODE_DYNAMIC, - EXPANSION_MODE_ZERO -}; - -enum ipp_output_format { - IPP_OUTPUT_FORMAT_12_BIT_FIX, - IPP_OUTPUT_FORMAT_16_BIT_BYPASS, - IPP_OUTPUT_FORMAT_FLOAT -}; struct ipp_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index f3d66752ed90..623042d2c272 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -219,6 +219,26 @@ struct transform_funcs { void (*opp_set_regamma_mode)( struct transform *xfm_base, enum opp_regamma mode); + + void (*ipp_set_degamma)( + struct transform *xfm_base, + enum ipp_degamma_mode mode); + + void (*ipp_program_input_lut)( + struct transform *xfm_base, + const struct dc_gamma *gamma); + + void (*ipp_program_degamma_pwl)(struct transform *xfm_base, + const struct pwl_params *params); + + void (*ipp_setup)( + struct transform *xfm_base, + enum surface_pixel_format input_format, + enum expansion_mode mode, + enum ipp_output_format cnv_out_format); + + void (*ipp_full_bypass)(struct transform *xfm_base); + }; extern const uint16_t filter_2tap_16p[18]; -- GitLab From 41f97c0773aed681ad65fa27ee88b503fbdcd298 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 24 Aug 2017 17:40:00 -0400 Subject: [PATCH 0837/2898] drm/amd/display: DF C-state entry blocked when DPMS Signed-off-by: Hersen Wu Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++ .../display/dc/dce110/dce110_hw_sequencer.c | 9 +++- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 48 ++++++++++++++++++- .../amd/display/dc/dcn10/dcn10_mem_input.c | 9 ++++ .../drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 2 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++ 7 files changed, 74 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index dc1b7d061be2..a20dc24db0d5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -830,6 +830,8 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); + dc->hwss.ready_shared_resources(dc); + for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); @@ -879,6 +881,8 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_retain_validate_context(dc->current_context); + dc->hwss.optimize_shared_resources(dc); + return (result == DC_OK); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 8ba61b9b8792..3502faa1458f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2697,6 +2697,10 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } } +static void ready_shared_resources(struct dc *dc) {} + +static void optimize_shared_resources(struct dc *dc) {} + static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, .program_csc_matrix = program_csc_matrix, @@ -2727,7 +2731,10 @@ static const struct hw_sequencer_funcs dce110_funcs = { .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg, .setup_stereo = NULL, .set_avmute = dce110_set_avmute, - .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect + .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, + .ready_shared_resources = ready_shared_resources, + .optimize_shared_resources = optimize_shared_resources, + }; bool dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4a24893486e8..9c54cae28997 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -776,6 +776,50 @@ static void power_on_plane( "Un-gated front end for pipe %d\n", plane_id); } +static void undo_DEGVIDCN10_253_wa(struct dc *dc) +{ + struct dce_hwseq *hws = dc->hwseq; + struct mem_input *mi = dc->res_pool->mis[0]; + + mi->funcs->set_blank(mi, true); + + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + + hubp_pg_control(hws, 0, false); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); +} + +static void ready_shared_resources(struct dc *dc) +{ + if (dc->current_context->stream_count == 0 && + !dc->debug.disable_stutter) + undo_DEGVIDCN10_253_wa(dc); +} + +static void apply_DEGVIDCN10_253_wa(struct dc *dc) +{ + struct dce_hwseq *hws = dc->hwseq; + struct mem_input *mi = dc->res_pool->mis[0]; + + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + + hubp_pg_control(hws, 0, true); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + + mi->funcs->set_hubp_blank_en(mi, false); +} + +static void optimize_shared_resources(struct dc *dc) +{ + if (dc->current_context->stream_count == 0 && + !dc->debug.disable_stutter) + apply_DEGVIDCN10_253_wa(dc); +} + static void bios_golden_init(struct dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; @@ -2829,7 +2873,9 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, .log_hw_state = dcn10_log_hw_state, - .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect + .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, + .ready_shared_resources = ready_shared_resources, + .optimize_shared_resources = optimize_shared_resources, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 0a47e6ad4286..9008cd03b139 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -56,6 +56,14 @@ static void min10_set_blank(struct mem_input *mem_input, bool blank) } } +static void min10_set_hubp_blank_en(struct mem_input *mem_input, bool blank) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + uint32_t blank_en = blank ? 1 : 0; + + REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); +} + static void min10_vready_workaround(struct mem_input *mem_input, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { @@ -771,6 +779,7 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .set_blank = min10_set_blank, .dcc_control = min10_dcc_control, .mem_program_viewport = min_set_viewport, + .set_hubp_blank_en = min10_set_hubp_blank_en, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4af40f5138fc..d09ed13fb8ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -439,6 +439,7 @@ static const struct dc_debug debug_defaults_diags = { .force_abm_enable = false, .timing_trace = true, .clock_trace = true, + .disable_stutter = true, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 6f4f04da9e28..6cef9ad0af91 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -161,6 +161,8 @@ struct mem_input_funcs { struct dchub_init_data *dh_data); void (*set_blank)(struct mem_input *mi, bool blank); + void (*set_hubp_blank_en)(struct mem_input *mi, bool blank); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index c73dca9f6d46..01e426194163 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -173,6 +173,9 @@ struct hw_sequencer_funcs { void (*wait_for_mpcc_disconnect)(struct dc *dc, struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); + + void (*ready_shared_resources)(struct dc *dc); + void (*optimize_shared_resources)(struct dc *dc); }; void color_space_to_black_color( -- GitLab From d1423e6faf161e69070dbb1d6764dd5da59563a8 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 22 Aug 2017 15:03:06 -0400 Subject: [PATCH 0838/2898] drm/amd/display: Remove mpc from bios left over, keep double buffer disabled. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 10 +++++++++- .../drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 --- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index ce408ccb428e..082b39a65e6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -127,10 +127,18 @@ static void mpc10_mpcc_remove( for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) if (opp->mpc_tree.dpp[z_idx] == dpp_id) break; + if (z_idx == opp->mpc_tree.num_pipes) { - ASSERT(0); + /* In case of resume from S3/S4, remove mpcc from bios left over */ + REG_SET(MPCC_OPP_ID[dpp_id], 0, + MPCC_OPP_ID, 0xf); + REG_SET(MPCC_TOP_SEL[dpp_id], 0, + MPCC_TOP_SEL, 0xf); + REG_SET(MPCC_BOT_SEL[dpp_id], 0, + MPCC_BOT_SEL, 0xf); return; } + mpcc_id = opp->mpc_tree.mpcc[z_idx]; REG_SET(MPCC_OPP_ID[mpcc_id], 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index cc58f43400d7..6a5f2683c2e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -289,9 +289,6 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); - REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, OTG_BLANK_DE_MODE, 0); -- GitLab From 9cffc573196bb3eea2d3dfd24893b6b9970cdfce Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Fri, 25 Aug 2017 16:13:55 -0400 Subject: [PATCH 0839/2898] drm/amd/display: clean up header file includes Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 20 --------- .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 20 --------- .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 8 ---- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 41 ------------------- 4 files changed, 89 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 20163668e2a8..99caafb27b37 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -27,10 +27,6 @@ #include "core_types.h" -#include "include/grph_object_id.h" -#include "include/fixed31_32.h" -#include "include/logger_interface.h" - #include "reg_helper.h" #include "dcn10_dpp.h" #include "basics/conversion.h" @@ -68,22 +64,6 @@ enum dcn10_coef_filter_type_sel { SCL_COEF_ALPHA_HORZ_FILTER = 5 }; -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dscl_autocal_mode { AUTOCAL_MODE_OFF = 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 409462f29f54..81620241a978 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -27,10 +27,6 @@ #include "core_types.h" -#include "include/grph_object_id.h" -#include "include/fixed31_32.h" -#include "include/logger_interface.h" - #include "reg_helper.h" #include "dcn10_dpp.h" #include "basics/conversion.h" @@ -66,22 +62,6 @@ enum dcn10_coef_filter_type_sel { SCL_COEF_ALPHA_HORZ_FILTER = 5 }; -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dscl_autocal_mode { AUTOCAL_MODE_OFF = 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 14c3b330b27b..b62cb38f523c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -100,14 +100,6 @@ enum dscl_mode_sel { DSCL_MODE_DSCL_BYPASS = 6 }; -enum gamut_remap_select { - GAMUT_REMAP_BYPASS = 0, - GAMUT_REMAP_COEFF, - GAMUT_REMAP_COMA_COEFF, - GAMUT_REMAP_COMB_COEFF -}; - - static void dpp_set_overscan( struct dcn10_dpp *xfm, const struct scaler_data *data) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index bc9827967535..5edc4b7073e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -37,40 +37,6 @@ #define CTX \ ippn10->base.ctx - -struct dcn10_input_csc_matrix { - enum dc_color_space color_space; - uint32_t regval[12]; -}; - -static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { - {COLOR_SPACE_SRGB, - {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, - {COLOR_SPACE_SRGB_LIMITED, - {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, - {COLOR_SPACE_YCBCR601, - {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef, - 0, 0x2000, 0x38b4, 0xe3a6} }, - {COLOR_SPACE_YCBCR601_LIMITED, - {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108, - 0, 0x2568, 0x40de, 0xdd3a} }, - {COLOR_SPACE_YCBCR709, - {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0, - 0x2000, 0x3b61, 0xe24f} }, - - {COLOR_SPACE_YCBCR709_LIMITED, - {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, - 0x2568, 0x43ee, 0xdbb2} } -}; - -enum dcn10_input_csc_select { - INPUT_CSC_SELECT_BYPASS = 0, - INPUT_CSC_SELECT_ICSC, - INPUT_CSC_SELECT_COMA -}; - - - static bool ippn10_cursor_program_control( struct dcn10_ipp *ippn10, bool pixel_data_invert, @@ -255,13 +221,6 @@ static void ippn10_cursor_set_position( /* TODO Handle surface pixel formats other than 4:4:4 */ } -enum pixel_format_description { - PIXEL_FORMAT_FIXED = 0, - PIXEL_FORMAT_FIXED16, - PIXEL_FORMAT_FLOAT - -}; - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ -- GitLab From 608ac7bb3924178d7bfa8b88d79d3d9d72b8f485 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Fri, 25 Aug 2017 16:16:10 -0400 Subject: [PATCH 0840/2898] drm/amd/display: Rename dc validate_context and current_context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename all the dc validate_context to dc_state and dc current_context to current_state. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 108 +++++++++--------- .../gpu/drm/amd/display/dc/core/dc_debug.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 +- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- .../drm/amd/display/dc/core/dc_link_hwss.c | 4 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 40 +++---- .../gpu/drm/amd/display/dc/core/dc_stream.c | 15 ++- .../gpu/drm/amd/display/dc/core/dc_surface.c | 4 +- drivers/gpu/drm/amd/display/dc/dc.h | 38 +++--- .../drm/amd/display/dc/dce/dce_clock_source.c | 4 +- .../display/dc/dce100/dce100_hw_sequencer.c | 8 +- .../display/dc/dce100/dce100_hw_sequencer.h | 4 +- .../amd/display/dc/dce100/dce100_resource.c | 10 +- .../display/dc/dce110/dce110_hw_sequencer.c | 70 ++++++------ .../display/dc/dce110/dce110_hw_sequencer.h | 12 +- .../amd/display/dc/dce110/dce110_resource.c | 16 +-- .../amd/display/dc/dce112/dce112_resource.c | 16 +-- .../amd/display/dc/dce112/dce112_resource.h | 10 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 10 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 62 +++++----- .../amd/display/dc/dcn10/dcn10_hw_sequencer.h | 2 +- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 8 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 14 +-- .../gpu/drm/amd/display/dc/inc/dce_calcs.h | 2 +- .../gpu/drm/amd/display/dc/inc/dcn_calcs.h | 4 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 14 +-- drivers/gpu/drm/amd/display/dc/inc/resource.h | 22 ++-- .../dc/irq/dce110/irq_service_dce110.c | 2 +- .../amd/display/include/logger_interface.h | 4 +- 32 files changed, 263 insertions(+), 264 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9c44b82036fa..9b018115d97e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -711,7 +711,7 @@ dm_atomic_state_clear(struct drm_atomic_state *state) struct dm_atomic_state *dm_state = to_dm_atomic_state(state); if (dm_state->context) { - dc_release_validate_context(dm_state->context); + dc_release_state(dm_state->context); dm_state->context = NULL; } @@ -4098,7 +4098,7 @@ void amdgpu_dm_atomic_commit_tail( } if (dm_state->context) - WARN_ON(!dc_commit_context(dm->dc, dm_state->context)); + WARN_ON(!dc_commit_state(dm->dc, dm_state->context)); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index e0a5632f00a3..71cbee199016 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -209,7 +209,7 @@ struct dm_crtc_state { struct dm_atomic_state { struct drm_atomic_state base; - struct validate_context *context; + struct dc_state *context; }; #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6c85a54e47d6..ee1b76c074e6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -476,7 +476,7 @@ static void dcn_bw_calc_rq_dlg_ttu( static void dcn_dml_wm_override( const struct dcn_bw_internal_vars *v, struct display_mode_lib *dml, - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool) { int i, in_idx, active_count; @@ -593,7 +593,7 @@ static void split_stream_across_pipes( } static void calc_wm_sets_and_perf_params( - struct validate_context *context, + struct dc_state *context, struct dcn_bw_internal_vars *v) { /* Calculate set A last to keep internal var state consistent for required config */ @@ -721,7 +721,7 @@ static bool dcn_bw_apply_registry_override(struct dc *dc) bool dcn_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { const struct resource_pool *pool = dc->res_pool; struct dcn_bw_internal_vars *v = &context->dcn_bw_vars; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a20dc24db0d5..53f814dcc24d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -160,7 +160,7 @@ static bool stream_adjust_vmin_vmax(struct dc *dc, bool ret = false; for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx *pipe = &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { dc->hwss.set_drr(&pipe, 1, vmin, vmax); @@ -187,7 +187,7 @@ static bool stream_get_crtc_position(struct dc *dc, for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->stream == stream && pipe->stream_res.stream_enc) { dc->hwss.get_position(&pipe, 1, &position); @@ -207,8 +207,8 @@ static bool set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream) struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_context->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &dc->current_context->res_ctx.pipe_ctx[i]; + if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { + pipes = &dc->current_state->res_ctx.pipe_ctx[i]; dc->hwss.program_gamut_remap(pipes); ret = true; } @@ -224,10 +224,10 @@ static bool program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) struct pipe_ctx *pipes; for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_context->res_ctx.pipe_ctx[i].stream + if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { - pipes = &dc->current_context->res_ctx.pipe_ctx[i]; + pipes = &dc->current_state->res_ctx.pipe_ctx[i]; dc->hwss.program_csc_matrix(pipes, stream->output_color_space, stream->csc_color_matrix.matrix); @@ -252,10 +252,10 @@ static void set_static_screen_events(struct dc *dc, struct dc_stream_state *stream = streams[i]; for (j = 0; j < MAX_PIPES; j++) { - if (dc->current_context->res_ctx.pipe_ctx[j].stream + if (dc->current_state->res_ctx.pipe_ctx[j].stream == stream) { pipes_affected[num_pipes_affected++] = - &dc->current_context->res_ctx.pipe_ctx[j]; + &dc->current_state->res_ctx.pipe_ctx[j]; } } } @@ -334,7 +334,7 @@ void set_dither_option(struct dc_stream_state *stream, { struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; + struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; memset(¶ms, 0, sizeof(params)); if (!stream) @@ -408,8 +408,8 @@ static void allocate_dc_stream_funcs(struct dc *dc) static void destruct(struct dc *dc) { - dc_release_validate_context(dc->current_context); - dc->current_context = NULL; + dc_release_state(dc->current_state); + dc->current_state = NULL; destroy_links(dc); @@ -494,9 +494,9 @@ static bool construct(struct dc *dc, goto fail; } - dc->current_context = dc_create_state(); + dc->current_state = dc_create_state(); - if (!dc->current_context) { + if (!dc->current_state) { dm_error("%s: failed to create validate ctx\n", __func__); goto fail; } @@ -668,12 +668,12 @@ bool dc_validate_guaranteed( struct dc_stream_state *stream) { enum dc_status result = DC_ERROR_UNEXPECTED; - struct validate_context *context; + struct dc_state *context; if (!dc_validate_stream(dc, stream)) return false; - context = dm_alloc(sizeof(struct validate_context)); + context = dm_alloc(sizeof(struct dc_state)); if (context == NULL) goto context_alloc_fail; @@ -682,7 +682,7 @@ bool dc_validate_guaranteed( result = dc->res_pool->funcs->validate_guaranteed( dc, stream, context); - dc_release_validate_context(context); + dc_release_state(context); context_alloc_fail: if (result != DC_OK) { @@ -697,7 +697,7 @@ bool dc_validate_guaranteed( static void program_timing_sync( struct dc *dc, - struct validate_context *ctx) + struct dc_state *ctx) { int i, j; int group_index = 0; @@ -771,15 +771,15 @@ static void program_timing_sync( static bool context_changed( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { uint8_t i; - if (context->stream_count != dc->current_context->stream_count) + if (context->stream_count != dc->current_state->stream_count) return true; - for (i = 0; i < dc->current_context->stream_count; i++) { - if (dc->current_context->streams[i] != context->streams[i]) + for (i = 0; i < dc->current_state->stream_count; i++) { + if (dc->current_state->streams[i] != context->streams[i]) return true; } @@ -788,7 +788,7 @@ static bool context_changed( bool dc_enable_stereo( struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *streams[], uint8_t stream_count) { @@ -800,7 +800,7 @@ bool dc_enable_stereo( if (context != NULL) pipe = &context->res_ctx.pipe_ctx[i]; else - pipe = &dc->current_context->res_ctx.pipe_ctx[i]; + pipe = &dc->current_state->res_ctx.pipe_ctx[i]; for (j = 0 ; pipe && j < stream_count; j++) { if (streams[j] && streams[j] == pipe->stream && dc->hwss.setup_stereo) @@ -816,7 +816,7 @@ bool dc_enable_stereo( * Applies given context to HW and copy it into current context. * It's up to the user to release the src context afterwards. */ -static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *context) +static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) { struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -875,18 +875,18 @@ static bool dc_commit_context_no_check(struct dc *dc, struct validate_context *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - dc_release_validate_context(dc->current_context); + dc_release_state(dc->current_state); - dc->current_context = context; + dc->current_state = context; - dc_retain_validate_context(dc->current_context); + dc_retain_state(dc->current_state); dc->hwss.optimize_shared_resources(dc); return (result == DC_OK); } -bool dc_commit_context(struct dc *dc, struct validate_context *context) +bool dc_commit_state(struct dc *dc, struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; int i; @@ -905,7 +905,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) LOG_DC); } - result = dc_commit_context_no_check(dc, context); + result = dc_commit_state_no_check(dc, context); return (result == DC_OK); } @@ -914,7 +914,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context) bool dc_post_update_surfaces_to_stream(struct dc *dc) { int i; - struct validate_context *context = dc->current_context; + struct dc_state *context = dc->current_state; post_surface_trace(dc); @@ -999,9 +999,9 @@ bool dc_commit_planes_to_stream( return true; } -struct validate_context *dc_create_state(void) +struct dc_state *dc_create_state(void) { - struct validate_context *context = dm_alloc(sizeof(struct validate_context)); + struct dc_state *context = dm_alloc(sizeof(struct dc_state)); if (!context) return NULL; @@ -1010,13 +1010,13 @@ struct validate_context *dc_create_state(void) return context; } -void dc_retain_validate_context(struct validate_context *context) +void dc_retain_state(struct dc_state *context) { ASSERT(atomic_read(&context->ref_count) > 0); atomic_inc(&context->ref_count); } -void dc_release_validate_context(struct validate_context *context) +void dc_release_state(struct dc_state *context) { ASSERT(atomic_read(&context->ref_count) > 0); atomic_dec(&context->ref_count); @@ -1028,7 +1028,7 @@ void dc_release_validate_context(struct validate_context *context) } static bool is_surface_in_context( - const struct validate_context *context, + const struct dc_state *context, const struct dc_plane_state *plane_state) { int j; @@ -1145,7 +1145,7 @@ static enum surface_update_type det_surface_update( const struct dc_surface_update *u, int surface_index) { - const struct validate_context *context = dc->current_context; + const struct dc_state *context = dc->current_state; enum surface_update_type type = UPDATE_TYPE_FAST; enum surface_update_type overall_type = UPDATE_TYPE_FAST; @@ -1200,7 +1200,7 @@ enum surface_update_type dc_check_update_surfaces_for_stream( } static struct dc_stream_status *stream_get_status( - struct validate_context *ctx, + struct dc_state *ctx, struct dc_stream_state *stream) { uint8_t i; @@ -1221,7 +1221,7 @@ void dc_update_planes_and_stream(struct dc *dc, struct dc_stream_state *stream, struct dc_stream_update *stream_update) { - struct validate_context *context; + struct dc_state *context; int i, j; enum surface_update_type update_type; const struct dc_stream_status *stream_status; @@ -1239,7 +1239,7 @@ void dc_update_planes_and_stream(struct dc *dc, ASSERT(0); } #endif - context = dc->current_context; + context = dc->current_state; /* update current stream with the new updates */ if (stream_update) { @@ -1293,7 +1293,7 @@ void dc_update_planes_and_stream(struct dc *dc, goto context_alloc_fail; dc_resource_validate_ctx_copy_construct( - dc->current_context, context); + dc->current_state, context); /*remove old surfaces from context */ if (!dc_rem_all_planes_for_stream(dc, stream, context)) { @@ -1437,7 +1437,7 @@ void dc_update_planes_and_stream(struct dc *dc, /* Full fe update*/ for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[j]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j]; bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; struct dc_cursor_position position = { 0 }; @@ -1524,7 +1524,7 @@ void dc_update_planes_and_stream(struct dc *dc, } } - if (dc->current_context != context) { + if (dc->current_state != context) { /* Since memory free requires elevated IRQL, an interrupt * request is generated by mem free. If this happens @@ -1534,16 +1534,16 @@ void dc_update_planes_and_stream(struct dc *dc, * then free the old context. */ - struct validate_context *old = dc->current_context; + struct dc_state *old = dc->current_state; - dc->current_context = context; - dc_release_validate_context(old); + dc->current_state = context; + dc_release_state(old); } return; fail: - dc_release_validate_context(context); + dc_release_state(context); context_alloc_fail: DC_ERROR("Failed to allocate new validate context!\n"); @@ -1551,13 +1551,13 @@ void dc_update_planes_and_stream(struct dc *dc, uint8_t dc_get_current_stream_count(struct dc *dc) { - return dc->current_context->stream_count; + return dc->current_state->stream_count; } struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) { - if (i < dc->current_context->stream_count) - return dc->current_context->streams[i]; + if (i < dc->current_state->stream_count) + return dc->current_state->streams[i]; return NULL; } @@ -1634,11 +1634,11 @@ void dc_set_power_state( */ /* Preserve refcount */ - ref_count = dc->current_context->ref_count; - dc_resource_validate_ctx_destruct(dc->current_context); - memset(dc->current_context, 0, - sizeof(*dc->current_context)); - dc->current_context->ref_count = ref_count; + ref_count = dc->current_state->ref_count; + dc_resource_validate_ctx_destruct(dc->current_state); + memset(dc->current_state, 0, + sizeof(*dc->current_state)); + dc->current_state->ref_count = ref_count; break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index d74eed8f9b96..6acee5426e4b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -329,7 +329,7 @@ void context_timing_trace( void context_clock_trace( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { #if defined(CONFIG_DRM_AMD_DC_DCN1_0) struct dc *core_dc = dc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 0bdd41ca8799..65e12614d96c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1819,14 +1819,14 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, if (dc_is_embedded_signal(link->connector_signal)) { if (stream != NULL) { for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx. + if (core_dc->current_state->res_ctx. pipe_ctx[i].stream == stream) /* DMCU -1 for all controller id values, * therefore +1 here */ controller_id = - core_dc->current_context-> + core_dc->current_state-> res_ctx.pipe_ctx[i].stream_res.tg->inst + 1; } @@ -1926,13 +1926,13 @@ bool dc_link_setup_psr(struct dc_link *link, psr_context->engineId = link->link_enc->preferred_engine; for (i = 0; i < MAX_PIPES; i++) { - if (core_dc->current_context->res_ctx.pipe_ctx[i].stream + if (core_dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { /* dmcu -1 for all controller id values, * therefore +1 here */ psr_context->controllerId = - core_dc->current_context->res_ctx. + core_dc->current_state->res_ctx. pipe_ctx[i].stream_res.tg->inst + 1; break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 446e2933474c..5f2b52e41427 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2406,7 +2406,7 @@ bool dc_link_dp_set_test_pattern( const unsigned char *p_custom_pattern, unsigned int cust_pattern_size) { - struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx; + struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; struct pipe_ctx *pipe_ctx = &pipes[0]; unsigned int lane; unsigned int i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 23d8b614e0fd..3427fb5b7e30 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -62,7 +62,7 @@ void dp_enable_link_phy( struct link_encoder *link_enc = link->link_enc; struct pipe_ctx *pipes = - link->dc->current_context->res_ctx.pipe_ctx; + link->dc->current_state->res_ctx.pipe_ctx; struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source; unsigned int i; @@ -262,7 +262,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, bool skip_video_pattern) { struct pipe_ctx *pipes = - &link->dc->current_context->res_ctx.pipe_ctx[0]; + &link->dc->current_state->res_ctx.pipe_ctx[0]; unsigned int i; for (i = 0; i < MAX_PIPES; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9eb8d48bc889..727afeaa3830 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -893,7 +893,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) enum dc_status resource_build_scaling_params_for_context( const struct dc *dc, - struct validate_context *context) + struct dc_state *context) { int i; @@ -971,7 +971,7 @@ static struct pipe_ctx *resource_get_tail_pipe_for_stream( * that has no surface attached yet */ static struct pipe_ctx *acquire_free_pipe_for_stream( - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool, struct dc_stream_state *stream) { @@ -1048,7 +1048,7 @@ bool dc_add_plane_to_context( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, - struct validate_context *context) + struct dc_state *context) { int i; struct resource_pool *pool = dc->res_pool; @@ -1124,7 +1124,7 @@ bool dc_remove_plane_from_context( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, - struct validate_context *context) + struct dc_state *context) { int i; struct dc_stream_status *stream_status = NULL; @@ -1199,7 +1199,7 @@ bool dc_remove_plane_from_context( bool dc_rem_all_planes_for_stream( const struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context) + struct dc_state *context) { int i, old_plane_count; struct dc_stream_status *stream_status = NULL; @@ -1233,7 +1233,7 @@ static bool add_all_planes_for_stream( struct dc_stream_state *stream, const struct dc_validation_set set[], int set_count, - struct validate_context *context) + struct dc_state *context) { int i, j; @@ -1258,7 +1258,7 @@ bool dc_add_all_planes_for_stream( struct dc_stream_state *stream, struct dc_plane_state * const *plane_states, int plane_count, - struct validate_context *context) + struct dc_state *context) { struct dc_validation_set set; int i; @@ -1434,7 +1434,7 @@ static struct audio *find_first_free_audio( } bool resource_is_stream_unchanged( - struct validate_context *old_context, struct dc_stream_state *stream) + struct dc_state *old_context, struct dc_stream_state *stream) { int i; @@ -1450,7 +1450,7 @@ bool resource_is_stream_unchanged( bool dc_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *stream) { struct dc_context *dc_ctx = dc->ctx; @@ -1474,7 +1474,7 @@ bool dc_add_stream_to_ctx( bool dc_remove_stream_from_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *stream) { int i; @@ -1553,7 +1553,7 @@ static void copy_pipe_ctx( static struct dc_stream_state *find_pll_sharable_stream( struct dc_stream_state *stream_needs_pll, - struct validate_context *context) + struct dc_state *context) { int i; @@ -1615,7 +1615,7 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) enum dc_status resource_map_pool_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { const struct resource_pool *pool = dc->res_pool; @@ -1689,7 +1689,7 @@ enum dc_status resource_map_pool_resources( /* first stream in the context is used to populate the rest */ void validate_guaranteed_copy_streams( - struct validate_context *context, + struct dc_state *context, int max_streams) { int i; @@ -1709,14 +1709,14 @@ void validate_guaranteed_copy_streams( void dc_resource_validate_ctx_copy_construct_current( const struct dc *dc, - struct validate_context *dst_ctx) + struct dc_state *dst_ctx) { - dc_resource_validate_ctx_copy_construct(dc->current_context, dst_ctx); + dc_resource_validate_ctx_copy_construct(dc->current_state, dst_ctx); } bool dc_validate_global_state( struct dc *dc, - struct validate_context *new_ctx) + struct dc_state *new_ctx) { enum dc_status result = DC_ERROR_UNEXPECTED; int i, j; @@ -2413,7 +2413,7 @@ static void set_vsc_info_packet( /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ } -void dc_resource_validate_ctx_destruct(struct validate_context *context) +void dc_resource_validate_ctx_destruct(struct dc_state *context) { int i, j; @@ -2433,8 +2433,8 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context) * by the src_ctx */ void dc_resource_validate_ctx_copy_construct( - const struct validate_context *src_ctx, - struct validate_context *dst_ctx) + const struct dc_state *src_ctx, + struct dc_state *dst_ctx) { int i, j; atomic_t ref_count = dst_ctx->ref_count; @@ -2518,7 +2518,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) enum dc_status resource_map_clock_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { /* acquire new resources */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 0e7cc293184e..a421779093d9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -169,10 +169,9 @@ struct dc_stream_status *dc_stream_get_status( uint8_t i; struct dc *dc = stream->ctx->dc; - for (i = 0; i < dc->current_context->stream_count; i++) { - if (stream == dc->current_context->streams[i]) { - return &dc->current_context->stream_status[i]; - } + for (i = 0; i < dc->current_state->stream_count; i++) { + if (stream == dc->current_state->streams[i]) + return &dc->current_state->stream_status[i]; } return NULL; @@ -199,7 +198,7 @@ bool dc_stream_set_cursor_attributes( } core_dc = stream->ctx->dc; - res_ctx = &core_dc->current_context->res_ctx; + res_ctx = &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; @@ -235,7 +234,7 @@ bool dc_stream_set_cursor_position( } core_dc = stream->ctx->dc; - res_ctx = &core_dc->current_context->res_ctx; + res_ctx = &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; @@ -271,7 +270,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) uint8_t i; struct dc *core_dc = stream->ctx->dc; struct resource_context *res_ctx = - &core_dc->current_context->res_ctx; + &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; @@ -295,7 +294,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, bool ret = false; struct dc *core_dc = stream->ctx->dc; struct resource_context *res_ctx = - &core_dc->current_context->res_ctx; + &core_dc->current_state->res_ctx; for (i = 0; i < MAX_PIPES; i++) { struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 0b6410fb2f3e..e96f63eed070 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -104,12 +104,12 @@ const struct dc_plane_status *dc_plane_get_status( plane_status = &plane_state->status; core_dc = plane_state->ctx->dc; - if (core_dc->current_context == NULL) + if (core_dc->current_state == NULL) return NULL; for (i = 0; i < core_dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = - &core_dc->current_context->res_ctx.pipe_ctx[i]; + &core_dc->current_state->res_ctx.pipe_ctx[i]; if (pipe_ctx->plane_state != plane_state) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 55fc58102515..d1d5737398df 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -99,7 +99,7 @@ struct dc_static_screen_events { /* Forward declaration*/ struct dc; struct dc_plane_state; -struct validate_context; +struct dc_state; struct dc_cap_funcs { bool (*get_dcc_compression_cap)(const struct dc *dc, @@ -192,7 +192,7 @@ struct dc_debug { bool disable_psr; bool force_abm_enable; }; -struct validate_context; +struct dc_state; struct resource_pool; struct dce_hwseq; struct dc { @@ -208,7 +208,7 @@ struct dc { uint8_t link_count; struct dc_link *links[MAX_PIPES * 2]; - struct validate_context *current_context; + struct dc_state *current_state; struct resource_pool *res_pool; /* Display Engine Clock levels */ @@ -621,12 +621,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, bool dc_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *stream); bool dc_remove_stream_from_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *stream); @@ -634,25 +634,25 @@ bool dc_add_plane_to_context( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, - struct validate_context *context); + struct dc_state *context); bool dc_remove_plane_from_context( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, - struct validate_context *context); + struct dc_state *context); bool dc_rem_all_planes_for_stream( const struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context); + struct dc_state *context); bool dc_add_all_planes_for_stream( const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state * const *plane_states, int plane_count, - struct validate_context *context); + struct dc_state *context); /* * Structure to store surface/stream associations for validation @@ -669,7 +669,7 @@ bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); bool dc_validate_global_state( struct dc *dc, - struct validate_context *new_ctx); + struct dc_state *new_ctx); /* * This function takes a stream and checks if it is guaranteed to be supported. @@ -680,14 +680,14 @@ bool dc_validate_global_state( */ void dc_resource_validate_ctx_copy_construct( - const struct validate_context *src_ctx, - struct validate_context *dst_ctx); + const struct dc_state *src_ctx, + struct dc_state *dst_ctx); void dc_resource_validate_ctx_copy_construct_current( const struct dc *dc, - struct validate_context *dst_ctx); + struct dc_state *dst_ctx); -void dc_resource_validate_ctx_destruct(struct validate_context *context); +void dc_resource_validate_ctx_destruct(struct dc_state *context); /* * TODO update to make it about validation sets @@ -698,7 +698,7 @@ void dc_resource_validate_ctx_destruct(struct validate_context *context); * Phy, Encoder, Timing Generator are programmed and enabled. * New streams are enabled with blank stream; no memory read. */ -bool dc_commit_context(struct dc *dc, struct validate_context *context); +bool dc_commit_state(struct dc *dc, struct dc_state *context); /* * Set up streams and links associated to drive sinks @@ -714,7 +714,7 @@ bool dc_commit_context(struct dc *dc, struct validate_context *context); */ bool dc_enable_stereo( struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *streams[], uint8_t stream_count); @@ -737,9 +737,9 @@ enum surface_update_type dc_check_update_surfaces_for_stream( const struct dc_stream_status *stream_status); -struct validate_context *dc_create_state(void); -void dc_retain_validate_context(struct validate_context *context); -void dc_release_validate_context(struct validate_context *context); +struct dc_state *dc_create_state(void); +void dc_retain_state(struct dc_state *context); +void dc_release_state(struct dc_state *context); /******************************************************************************* * Link Interfaces diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 0654fe34627c..d3b61b92ebec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -609,7 +609,7 @@ static uint32_t dce110_get_pll_pixel_rate_in_hz( { uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; struct dc *dc_core = cs->ctx->dc; - struct validate_context *context = dc_core->current_context; + struct dc_state *context = dc_core->current_state; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; /* This function need separate to different DCE version, before separate, just use pixel clock */ @@ -624,7 +624,7 @@ static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll( { uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0; struct dc *dc_core = cs->ctx->dc; - struct validate_context *context = dc_core->current_context; + struct dc_state *context = dc_core->current_state; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst]; /* This function need separate to different DCE version, before separate, just use pixel clock */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index b7e51c5ed1b1..492ea6069eb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -107,7 +107,7 @@ static bool dce100_enable_display_power_gating( static void dce100_pplib_apply_display_requirements( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -127,14 +127,14 @@ static void dce100_pplib_apply_display_requirements( void dce100_set_bandwidth( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed) { - if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { + if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dce.dispclk_khz * 115 / 100); - dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; + dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; } dce100_pplib_apply_display_requirements(dc, context); } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index c04aa15cd656..770b5bb1ff40 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -29,13 +29,13 @@ #include "core_types.h" struct dc; -struct validate_context; +struct dc_state; bool dce100_hw_sequencer_construct(struct dc *dc); void dce100_set_bandwidth( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed); #endif /* __DC_HWSS_DCE100_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c991610315b2..36d79175354c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -653,7 +653,7 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -674,7 +674,7 @@ static enum dc_status build_mapped_resource( bool dce100_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { /* TODO implement when needed but for now hardcode max value*/ context->bw.dce.dispclk_khz = 681000; @@ -684,7 +684,7 @@ bool dce100_validate_bandwidth( } static bool dce100_validate_surface_sets( - struct validate_context *context) + struct dc_state *context) { int i; @@ -705,7 +705,7 @@ static bool dce100_validate_surface_sets( enum dc_status dce100_validate_global( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { if (!dce100_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -716,7 +716,7 @@ enum dc_status dce100_validate_global( enum dc_status dce100_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 3502faa1458f..1c6e2006f2a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -976,11 +976,11 @@ static void program_scaler(const struct dc *dc, static enum dc_status dce110_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, - struct validate_context *context, + struct dc_state *context, struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. + struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; struct tg_color black_color = {0}; @@ -1032,11 +1032,11 @@ static enum dc_status dce110_prog_pixclk_crtc_otg( static enum dc_status apply_single_controller_ctx_to_hw( struct pipe_ctx *pipe_ctx, - struct validate_context *context, + struct dc_state *context, struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx. + struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. pipe_ctx[pipe_ctx->pipe_idx]; /* */ @@ -1257,7 +1257,7 @@ static uint32_t compute_pstate_blackout_duration( void dce110_set_displaymarks( const struct dc *dc, - struct validate_context *context) + struct dc_state *context) { uint8_t i, num_pipes; unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; @@ -1415,7 +1415,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, */ static uint32_t get_max_pixel_clock_for_all_paths( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool pre_mode_set) { uint32_t max_pix_clk = 0; @@ -1456,7 +1456,7 @@ static uint32_t get_max_pixel_clock_for_all_paths( */ static void apply_min_clocks( struct dc *dc, - struct validate_context *context, + struct dc_state *context, enum dm_pp_clocks_state *clocks_state, bool pre_mode_set) { @@ -1545,7 +1545,7 @@ static void apply_min_clocks( * Check if FBC can be enabled */ static enum dc_status validate_fbc(struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; @@ -1575,7 +1575,7 @@ static enum dc_status validate_fbc(struct dc *dc, * Enable FBC */ static enum dc_status enable_fbc(struct dc *dc, - struct validate_context *context) + struct dc_state *context) { enum dc_status status = validate_fbc(dc, context); @@ -1604,14 +1604,14 @@ static enum dc_status enable_fbc(struct dc *dc, static enum dc_status apply_ctx_to_hw_fpga( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { enum dc_status status = DC_ERROR_UNEXPECTED; int i; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL) @@ -1634,7 +1634,7 @@ static enum dc_status apply_ctx_to_hw_fpga( static void dce110_reset_hw_ctx_wrap( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { int i; @@ -1642,7 +1642,7 @@ static void dce110_reset_hw_ctx_wrap( /* look up the targets that have been removed since last commit */ for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; /* Note: We need to disable output if clock sources change, @@ -1664,9 +1664,9 @@ static void dce110_reset_hw_ctx_wrap( } pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); pipe_ctx_old->plane_res.mi->funcs->free_mem_input( - pipe_ctx_old->plane_res.mi, dc->current_context->stream_count); + pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); resource_unreference_clock_source( - &dc->current_context->res_ctx, dc->res_pool, + &dc->current_state->res_ctx, dc->res_pool, &pipe_ctx_old->clock_source); dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); @@ -1679,7 +1679,7 @@ static void dce110_reset_hw_ctx_wrap( enum dc_status dce110_apply_ctx_to_hw( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status status; @@ -1705,7 +1705,7 @@ enum dc_status dce110_apply_ctx_to_hw( /* below is for real asic only */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) @@ -1735,31 +1735,31 @@ enum dc_status dce110_apply_ctx_to_hw( #if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (dc->ctx->dce_version >= DCN_VERSION_1_0) { if (context->bw.dcn.calc_clk.fclk_khz - > dc->current_context->bw.dcn.cur_clk.fclk_khz) { + > dc->current_state->bw.dcn.cur_clk.fclk_khz) { struct dm_pp_clock_for_voltage_req clock; clock.clk_type = DM_PP_CLOCK_TYPE_FCLK; clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; + dc->current_state->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz; } if (context->bw.dcn.calc_clk.dcfclk_khz - > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { + > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) { struct dm_pp_clock_for_voltage_req clock; clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz; dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock); - dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; + dc->current_state->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz; } if (context->bw.dcn.calc_clk.dispclk_khz - > dc->current_context->bw.dcn.cur_clk.dispclk_khz) { + > dc->current_state->bw.dcn.cur_clk.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dcn.calc_clk.dispclk_khz); - dc->current_context->bw.dcn.cur_clk.dispclk_khz = + dc->current_state->bw.dcn.cur_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; context->bw.dcn.cur_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; @@ -1767,7 +1767,7 @@ enum dc_status dce110_apply_ctx_to_hw( } else #endif if (context->bw.dce.dispclk_khz - > dc->current_context->bw.dce.dispclk_khz) { + > dc->current_state->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dce.dispclk_khz * 115 / 100); @@ -1848,7 +1848,7 @@ enum dc_status dce110_apply_ctx_to_hw( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == NULL) @@ -2327,7 +2327,7 @@ static void init_hw(struct dc *dc) } void dce110_fill_display_configs( - const struct validate_context *context, + const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg) { int j; @@ -2375,7 +2375,7 @@ void dce110_fill_display_configs( pp_display_cfg->display_count = num_cfgs; } -uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context) +uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) { uint8_t j; uint32_t min_vertical_blank_time = -1; @@ -2427,7 +2427,7 @@ static int determine_sclk_from_bounding_box( static void pplib_apply_display_requirements( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -2481,16 +2481,16 @@ static void pplib_apply_display_requirements( static void dce110_set_bandwidth( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed) { dce110_set_displaymarks(dc, context); - if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) { + if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dce.dispclk_khz * 115 / 100); - dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; + dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz; } pplib_apply_display_requirements(dc, context); @@ -2508,8 +2508,8 @@ static void dce110_program_front_end_for_pipe( memset(&tbl_entry, 0, sizeof(tbl_entry)); - if (dc->current_context) - old_pipe = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + if (dc->current_state) + old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; memset(&adjust, 0, sizeof(adjust)); adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; @@ -2627,7 +2627,7 @@ static void dce110_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, int num_planes, - struct validate_context *context) + struct dc_state *context) { int i, be_idx; @@ -2657,7 +2657,7 @@ static void dce110_apply_ctx_for_surface( static void dce110_power_down_fe(struct dc *dc, int fe_idx) { /* Do not power down fe when stream is active on dce*/ - if (dc->current_context->res_ctx.pipe_ctx[fe_idx].stream) + if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream) return; dc->hwss.enable_display_power_gating( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index ac418fd83894..baa20c1f17ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -30,20 +30,20 @@ #define GAMMA_HW_POINTS_NUM 256 struct dc; -struct validate_context; +struct dc_state; struct dm_pp_display_configuration; bool dce110_hw_sequencer_construct(struct dc *dc); enum dc_status dce110_apply_ctx_to_hw( struct dc *dc, - struct validate_context *context); + struct dc_state *context); -void dce110_set_display_clock(struct validate_context *context); +void dce110_set_display_clock(struct dc_state *context); void dce110_set_displaymarks( const struct dc *dc, - struct validate_context *context); + struct dc_state *context); void dce110_enable_stream(struct pipe_ctx *pipe_ctx); @@ -62,10 +62,10 @@ void dce110_power_down(struct dc *dc); void dce110_update_pending_status(struct pipe_ctx *pipe_ctx); void dce110_fill_display_configs( - const struct validate_context *context, + const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg); -uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context); +uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 18c67f89e9b5..94b6eb83e01e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -773,7 +773,7 @@ static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigne static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -800,7 +800,7 @@ static enum dc_status build_mapped_resource( static bool dce110_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { bool result = false; @@ -826,7 +826,7 @@ static bool dce110_validate_bandwidth( context->streams[0]->timing.v_addressable, context->streams[0]->timing.pix_clk_khz); - if (memcmp(&dc->current_context->bw.dce, + if (memcmp(&dc->current_state->bw.dce, &context->bw.dce, sizeof(context->bw.dce))) { struct log_entry log_entry; dm_logger_open( @@ -880,7 +880,7 @@ static bool dce110_validate_bandwidth( } static bool dce110_validate_surface_sets( - struct validate_context *context) + struct dc_state *context) { int i; @@ -913,7 +913,7 @@ static bool dce110_validate_surface_sets( enum dc_status dce110_validate_global( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { if (!dce110_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -924,7 +924,7 @@ enum dc_status dce110_validate_global( static enum dc_status dce110_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -954,7 +954,7 @@ static enum dc_status dce110_validate_guaranteed( } static struct pipe_ctx *dce110_acquire_underlay( - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool, struct dc_stream_state *stream) { @@ -976,7 +976,7 @@ static struct pipe_ctx *dce110_acquire_underlay( pipe_ctx->stream = stream; - if (!dc->current_context->res_ctx.pipe_ctx[underlay_idx].stream) { + if (!dc->current_state->res_ctx.pipe_ctx[underlay_idx].stream) { struct tg_color black_color = {0}; struct dc_bios *dcb = dc->ctx->dc_bios; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index d5a8ee69171d..de6f71d8a89b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -724,7 +724,7 @@ static struct clock_source *find_matching_pll( static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -745,7 +745,7 @@ static enum dc_status build_mapped_resource( bool dce112_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { bool result = false; @@ -768,7 +768,7 @@ bool dce112_validate_bandwidth( "%s: Bandwidth validation failed!", __func__); - if (memcmp(&dc->current_context->bw.dce, + if (memcmp(&dc->current_state->bw.dce, &context->bw.dce, sizeof(context->bw.dce))) { struct log_entry log_entry; dm_logger_open( @@ -823,7 +823,7 @@ bool dce112_validate_bandwidth( enum dc_status resource_map_phy_clock_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { @@ -855,7 +855,7 @@ enum dc_status resource_map_phy_clock_resources( } static bool dce112_validate_surface_sets( - struct validate_context *context) + struct dc_state *context) { int i; @@ -876,7 +876,7 @@ static bool dce112_validate_surface_sets( enum dc_status dce112_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *dc_stream) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -896,7 +896,7 @@ enum dc_status dce112_add_stream_to_ctx( enum dc_status dce112_validate_guaranteed( struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -927,7 +927,7 @@ enum dc_status dce112_validate_guaranteed( enum dc_status dce112_validate_global( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { if (!dce112_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h index f1834bfe3d1e..d5c19d34eb0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h @@ -39,21 +39,21 @@ enum dc_status dce112_validate_with_context( struct dc *dc, const struct dc_validation_set set[], int set_count, - struct validate_context *context, - struct validate_context *old_context); + struct dc_state *context, + struct dc_state *old_context); enum dc_status dce112_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context); + struct dc_state *context); bool dce112_validate_bandwidth( struct dc *dc, - struct validate_context *context); + struct dc_state *context); enum dc_status dce112_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *dc_stream); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 945ff7ee6cd9..316080767a21 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -685,7 +685,7 @@ static void destruct(struct dce110_resource_pool *pool) static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -706,7 +706,7 @@ static enum dc_status build_mapped_resource( bool dce80_validate_bandwidth( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { /* TODO implement when needed but for now hardcode max value*/ context->bw.dce.dispclk_khz = 681000; @@ -716,7 +716,7 @@ bool dce80_validate_bandwidth( } static bool dce80_validate_surface_sets( - struct validate_context *context) + struct dc_state *context) { int i; @@ -737,7 +737,7 @@ static bool dce80_validate_surface_sets( enum dc_status dce80_validate_global( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { if (!dce80_validate_surface_sets(context)) return DC_FAIL_SURFACE_VALIDATE; @@ -748,7 +748,7 @@ enum dc_status dce80_validate_global( enum dc_status dce80_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 9c54cae28997..71ff1cedbdf4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -793,7 +793,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) static void ready_shared_resources(struct dc *dc) { - if (dc->current_context->stream_count == 0 && + if (dc->current_state->stream_count == 0 && !dc->debug.disable_stutter) undo_DEGVIDCN10_253_wa(dc); } @@ -815,7 +815,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) static void optimize_shared_resources(struct dc *dc) { - if (dc->current_context->stream_count == 0 && + if (dc->current_state->stream_count == 0 && !dc->debug.disable_stutter) apply_DEGVIDCN10_253_wa(dc); } @@ -918,7 +918,7 @@ static void dcn10_init_hw(struct dc *dc) static enum dc_status dcn10_prog_pixclk_crtc_otg( struct pipe_ctx *pipe_ctx, - struct validate_context *context, + struct dc_state *context, struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; @@ -1008,7 +1008,7 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg( static void reset_back_end_for_pipe( struct dc *dc, struct pipe_ctx *pipe_ctx, - struct validate_context *context) + struct dc_state *context) { int i; @@ -1040,7 +1040,7 @@ static void reset_back_end_for_pipe( &pipe_ctx->clock_source); for (i = 0; i < dc->res_pool->pipe_count; i++) - if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe_ctx) + if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx) break; if (i == dc->res_pool->pipe_count) @@ -1206,14 +1206,14 @@ static void dcn10_power_down_fe(struct dc *dc, int fe_idx) static void reset_hw_ctx_wrap( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { int i; /* Reset Front End*/ /* Lock*/ for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; if (cur_pipe_ctx->stream) @@ -1222,7 +1222,7 @@ static void reset_hw_ctx_wrap( /* Disconnect*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (!pipe_ctx->stream || @@ -1234,7 +1234,7 @@ static void reset_hw_ctx_wrap( } /* Unlock*/ for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; struct timing_generator *tg = cur_pipe_ctx->stream_res.tg; if (cur_pipe_ctx->stream) @@ -1244,7 +1244,7 @@ static void reset_hw_ctx_wrap( /* Disable and Powerdown*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; /*if (!pipe_ctx_old->stream) @@ -1263,7 +1263,7 @@ static void reset_hw_ctx_wrap( /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; if (!pipe_ctx_old->stream) @@ -1271,7 +1271,7 @@ static void reset_hw_ctx_wrap( if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) - reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_context); + reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state); } } @@ -1943,7 +1943,7 @@ static void print_rq_dlg_ttu( static void dcn10_power_on_fe( struct dc *dc, struct pipe_ctx *pipe_ctx, - struct validate_context *context) + struct dc_state *context) { struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dce_hwseq *hws = dc->hwseq; @@ -2244,7 +2244,7 @@ static void dcn10_program_pte_vm(struct mem_input *mem_input, static void update_dchubp_dpp( struct dc *dc, struct pipe_ctx *pipe_ctx, - struct validate_context *context) + struct dc_state *context) { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = pipe_ctx->plane_res.mi; @@ -2263,7 +2263,7 @@ static void update_dchubp_dpp( pipe_ctx->pipe_idx, pipe_ctx->stream_res.pix_clk_params.requested_pix_clk, context->bw.dcn.calc_clk.dppclk_div); - dc->current_context->bw.dcn.cur_clk.dppclk_div = + dc->current_state->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div; @@ -2350,7 +2350,7 @@ static void update_dchubp_dpp( static void program_all_pipe_in_tree( struct dc *dc, struct pipe_ctx *pipe_ctx, - struct validate_context *context) + struct dc_state *context) { unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; @@ -2408,7 +2408,7 @@ static void program_all_pipe_in_tree( static void dcn10_pplib_apply_display_requirements( struct dc *dc, - struct validate_context *context) + struct dc_state *context) { struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; @@ -2437,7 +2437,7 @@ static void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, int num_planes, - struct validate_context *context) + struct dc_state *context) { int i, be_idx; @@ -2457,7 +2457,7 @@ static void dcn10_apply_ctx_for_surface( if (num_planes == 0) { for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; if (old_pipe_ctx->stream_res.tg && old_pipe_ctx->stream_res.tg->inst == be_idx) { old_pipe_ctx->stream_res.tg->funcs->set_blank(old_pipe_ctx->stream_res.tg, true); @@ -2471,7 +2471,7 @@ static void dcn10_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *old_pipe_ctx = - &dc->current_context->res_ctx.pipe_ctx[i]; + &dc->current_state->res_ctx.pipe_ctx[i]; if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) continue; @@ -2591,7 +2591,7 @@ static void dcn10_apply_ctx_for_surface( static void dcn10_set_bandwidth( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed) { struct pp_smu_display_requirement_rv *smu_req_cur = @@ -2607,25 +2607,25 @@ static void dcn10_set_bandwidth( return; if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz - > dc->current_context->bw.dcn.cur_clk.dispclk_khz) { + > dc->current_state->bw.dcn.cur_clk.dispclk_khz) { dc->res_pool->display_clock->funcs->set_clock( dc->res_pool->display_clock, context->bw.dcn.calc_clk.dispclk_khz); - dc->current_context->bw.dcn.cur_clk.dispclk_khz = + dc->current_state->bw.dcn.cur_clk.dispclk_khz = context->bw.dcn.calc_clk.dispclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz - > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) { + > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) { smu_req.hard_min_dcefclk_khz = context->bw.dcn.calc_clk.dcfclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz - > dc->current_context->bw.dcn.cur_clk.fclk_khz) { + > dc->current_state->bw.dcn.cur_clk.fclk_khz) { smu_req.hard_min_fclk_khz = context->bw.dcn.calc_clk.fclk_khz; } if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz - > dc->current_context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) { - dc->current_context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = + > dc->current_state->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) { + dc->current_state->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz = context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz; @@ -2640,15 +2640,15 @@ static void dcn10_set_bandwidth( /* Decrease in freq is increase in period so opposite comparison for dram_ccm */ if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us - < dc->current_context->bw.dcn.cur_clk.dram_ccm_us) { - dc->current_context->bw.dcn.calc_clk.dram_ccm_us = + < dc->current_state->bw.dcn.cur_clk.dram_ccm_us) { + dc->current_state->bw.dcn.calc_clk.dram_ccm_us = context->bw.dcn.calc_clk.dram_ccm_us; context->bw.dcn.cur_clk.dram_ccm_us = context->bw.dcn.calc_clk.dram_ccm_us; } if (decrease_allowed || context->bw.dcn.calc_clk.min_active_dram_ccm_us - < dc->current_context->bw.dcn.cur_clk.min_active_dram_ccm_us) { - dc->current_context->bw.dcn.calc_clk.min_active_dram_ccm_us = + < dc->current_state->bw.dcn.cur_clk.min_active_dram_ccm_us) { + dc->current_state->bw.dcn.calc_clk.min_active_dram_ccm_us = context->bw.dcn.calc_clk.min_active_dram_ccm_us; context->bw.dcn.cur_clk.min_active_dram_ccm_us = context->bw.dcn.calc_clk.min_active_dram_ccm_us; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 8bb09de8dcd7..ca53dc1cc19b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -32,7 +32,7 @@ struct dc; void dcn10_hw_sequencer_construct(struct dc *dc); extern void fill_display_configs( - const struct validate_context *context, + const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg); #endif /* __DC_HWSS_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index d09ed13fb8ea..fff86ad0c411 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -850,7 +850,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) static enum dc_status build_mapped_resource( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream) { enum dc_status status = DC_OK; @@ -887,7 +887,7 @@ static enum dc_status build_mapped_resource( enum dc_status dcn10_add_stream_to_ctx( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *dc_stream) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -907,7 +907,7 @@ enum dc_status dcn10_add_stream_to_ctx( enum dc_status dcn10_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, - struct validate_context *context) + struct dc_state *context) { enum dc_status result = DC_ERROR_UNEXPECTED; @@ -935,7 +935,7 @@ enum dc_status dcn10_validate_guaranteed( } static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool, struct dc_stream_state *stream) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index bd1a6367872f..71eb9859faf2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -80,7 +80,7 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); #include "transform.h" struct resource_pool; -struct validate_context; +struct dc_state; struct resource_context; struct resource_funcs { @@ -91,18 +91,18 @@ struct resource_funcs { enum dc_status (*validate_guaranteed)( struct dc *dc, struct dc_stream_state *stream, - struct validate_context *context); + struct dc_state *context); bool (*validate_bandwidth)( struct dc *dc, - struct validate_context *context); + struct dc_state *context); enum dc_status (*validate_global)( struct dc *dc, - struct validate_context *context); + struct dc_state *context); struct pipe_ctx *(*acquire_idle_pipe_for_layer)( - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool, struct dc_stream_state *stream); @@ -110,7 +110,7 @@ struct resource_funcs { enum dc_status (*add_stream_to_ctx)( struct dc *dc, - struct validate_context *new_ctx, + struct dc_state *new_ctx, struct dc_stream_state *dc_stream); }; @@ -252,7 +252,7 @@ union bw_context { struct dce_bw_output dce; }; -struct validate_context { +struct dc_state { struct dc_stream_state *streams[MAX_PIPES]; struct dc_stream_status stream_status[MAX_PIPES]; uint8_t stream_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h index 6a205b010084..ae2399f16d1c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dce_calcs.h @@ -34,7 +34,7 @@ struct pipe_ctx; struct dc; -struct validate_context; +struct dc_state; struct dce_bw_output; enum bw_calcs_version { diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 58744fe87ed8..1e231f6de732 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -35,7 +35,7 @@ #include "../dml/display_mode_lib.h" struct dc; -struct validate_context; +struct dc_state; /******************************************************************************* * DCN data structures. @@ -621,7 +621,7 @@ extern const struct dcn_ip_params dcn10_ip_defaults; bool dcn_validate_bandwidth( struct dc *dc, - struct validate_context *context); + struct dc_state *context); unsigned int dcn_find_dcfclk_suits_all( const struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 01e426194163..aae7629b1c08 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -49,7 +49,7 @@ struct dce_hwseq { }; struct pipe_ctx; -struct validate_context; +struct dc_state; struct dchub_init_data; struct dc_static_screen_events; struct resource_pool; @@ -60,16 +60,16 @@ struct hw_sequencer_funcs { void (*init_hw)(struct dc *dc); enum dc_status (*apply_ctx_to_hw)( - struct dc *dc, struct validate_context *context); + struct dc *dc, struct dc_state *context); void (*reset_hw_ctx_wrap)( - struct dc *dc, struct validate_context *context); + struct dc *dc, struct dc_state *context); void (*apply_ctx_for_surface)( struct dc *dc, const struct dc_stream_state *stream, int num_planes, - struct validate_context *context); + struct dc_state *context); void (*set_plane_config)( const struct dc *dc, @@ -127,7 +127,7 @@ struct hw_sequencer_funcs { void (*power_on_front_end)(struct dc *dc, struct pipe_ctx *pipe, - struct validate_context *context); + struct dc_state *context); void (*update_info_frame)(struct pipe_ctx *pipe_ctx); @@ -145,7 +145,7 @@ struct hw_sequencer_funcs { void (*set_bandwidth)( struct dc *dc, - struct validate_context *context, + struct dc_state *context, bool decrease_allowed); void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, @@ -159,7 +159,7 @@ struct hw_sequencer_funcs { enum dc_status (*prog_pixclk_crtc_otg)( struct pipe_ctx *pipe_ctx, - struct validate_context *context, + struct dc_state *context, struct dc *dc); void (*setup_stereo)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index ebc0f5b02365..41437da5fb9b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -81,14 +81,14 @@ void dc_destroy_resource_pool(struct dc *dc); enum dc_status resource_map_pool_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); enum dc_status resource_build_scaling_params_for_context( const struct dc *dc, - struct validate_context *context); + struct dc_state *context); void resource_build_info_frame(struct pipe_ctx *pipe_ctx); @@ -122,7 +122,7 @@ bool resource_attach_surfaces_to_context( struct dc_plane_state *const *plane_state, int surface_count, struct dc_stream_state *dc_stream, - struct validate_context *context, + struct dc_state *context, const struct resource_pool *pool); struct pipe_ctx *find_idle_secondary_pipe( @@ -130,31 +130,31 @@ struct pipe_ctx *find_idle_secondary_pipe( const struct resource_pool *pool); bool resource_is_stream_unchanged( - struct validate_context *old_context, struct dc_stream_state *stream); + struct dc_state *old_context, struct dc_stream_state *stream); bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, - const struct validate_context *old_context, - struct validate_context *context, + const struct dc_state *old_context, + struct dc_state *context, const struct resource_pool *pool); void validate_guaranteed_copy_streams( - struct validate_context *context, + struct dc_state *context, int max_streams); void resource_validate_ctx_update_pointer_after_copy( - const struct validate_context *src_ctx, - struct validate_context *dst_ctx); + const struct dc_state *src_ctx, + struct dc_state *dst_ctx); enum dc_status resource_map_clock_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream); enum dc_status resource_map_phy_clock_resources( const struct dc *dc, - struct validate_context *context, + struct dc_state *context, struct dc_stream_state *stream); bool pipe_need_reprogram( diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index e3a12f3e0642..7cce28489dba 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -214,7 +214,7 @@ bool dce110_vblank_set( uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; struct timing_generator *tg = - core_dc->current_context->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; + core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; if (enable) { if (!tg->funcs->arm_vert_intr(tg, 2)) { diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 93c8556358f0..6641e8001e97 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -32,7 +32,7 @@ struct dc_context; struct dc_link; struct dc_surface_update; struct resource_context; -struct validate_context; +struct dc_state; /* * @@ -93,7 +93,7 @@ void context_timing_trace( void context_clock_trace( struct dc *dc, - struct validate_context *context); + struct dc_state *context); /* Any function which is empty or have incomplete implementation should be * marked by this macro. -- GitLab From f36cc577c3254738e370b553f9f8cedf2df84070 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 28 Aug 2017 12:04:23 -0400 Subject: [PATCH 0841/2898] drm/amd/display: Rename dc resource_validate_ctx methods Rename dc_resource methods from validate_ctx to state Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++--- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/dc.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9b018115d97e..4c7515d9c811 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4651,7 +4651,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, dm_state->context = dc_create_state(); ASSERT(dm_state->context); - dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context); + dc_resource_state_copy_construct_current(dc, dm_state->context); /* Remove exiting planes if they are modified */ ret = dm_update_planes_state(dc, state, false, &lock_and_validation_needed); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 53f814dcc24d..6bf8af7a592d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1022,7 +1022,7 @@ void dc_release_state(struct dc_state *context) atomic_dec(&context->ref_count); if (atomic_read(&context->ref_count) == 0) { - dc_resource_validate_ctx_destruct(context); + dc_resource_state_destruct(context); dm_free(context); } } @@ -1292,7 +1292,7 @@ void dc_update_planes_and_stream(struct dc *dc, if (context == NULL) goto context_alloc_fail; - dc_resource_validate_ctx_copy_construct( + dc_resource_state_copy_construct( dc->current_state, context); /*remove old surfaces from context */ @@ -1635,7 +1635,7 @@ void dc_set_power_state( /* Preserve refcount */ ref_count = dc->current_state->ref_count; - dc_resource_validate_ctx_destruct(dc->current_state); + dc_resource_state_destruct(dc->current_state); memset(dc->current_state, 0, sizeof(*dc->current_state)); dc->current_state->ref_count = ref_count; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 727afeaa3830..d284d9d40e2b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1707,11 +1707,11 @@ void validate_guaranteed_copy_streams( } } -void dc_resource_validate_ctx_copy_construct_current( +void dc_resource_state_copy_construct_current( const struct dc *dc, struct dc_state *dst_ctx) { - dc_resource_validate_ctx_copy_construct(dc->current_state, dst_ctx); + dc_resource_state_copy_construct(dc->current_state, dst_ctx); } bool dc_validate_global_state( @@ -2413,7 +2413,7 @@ static void set_vsc_info_packet( /*TODO: stereo 3D support and extend pixel encoding colorimetry*/ } -void dc_resource_validate_ctx_destruct(struct dc_state *context) +void dc_resource_state_destruct(struct dc_state *context) { int i, j; @@ -2432,7 +2432,7 @@ void dc_resource_validate_ctx_destruct(struct dc_state *context) * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced * by the src_ctx */ -void dc_resource_validate_ctx_copy_construct( +void dc_resource_state_copy_construct( const struct dc_state *src_ctx, struct dc_state *dst_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d1d5737398df..f3ccc2043405 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -679,15 +679,15 @@ bool dc_validate_global_state( * No hardware is programmed for call. Only validation is done. */ -void dc_resource_validate_ctx_copy_construct( +void dc_resource_state_copy_construct( const struct dc_state *src_ctx, struct dc_state *dst_ctx); -void dc_resource_validate_ctx_copy_construct_current( +void dc_resource_state_copy_construct_current( const struct dc *dc, struct dc_state *dst_ctx); -void dc_resource_validate_ctx_destruct(struct dc_state *context); +void dc_resource_state_destruct(struct dc_state *context); /* * TODO update to make it about validation sets -- GitLab From 4ed4e51b19496c4d160f3ca368d9ff5dd3e4a5b9 Mon Sep 17 00:00:00 2001 From: Mikita Lipski Date: Wed, 23 Aug 2017 15:29:18 -0400 Subject: [PATCH 0842/2898] drm/amd/display: Add a clock source to a sharing pipe Fix to allow DVI displays to share the same clock source Signed-off-by: Mikita Lipski Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d284d9d40e2b..a4e92219a594 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2536,7 +2536,7 @@ enum dc_status resource_map_clock_resources( pipe_ctx->clock_source = NULL; if (!dc->config.disable_disp_pll_sharing) - resource_find_used_clk_src_for_sharing( + pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( &context->res_ctx, pipe_ctx); -- GitLab From ceda4e980058316531a1a6b72797d9068ddacd02 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 24 Aug 2017 17:12:48 -0400 Subject: [PATCH 0843/2898] drm/amd/display: add aux arbitration logic Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/i2caux/aux_engine.c | 6 ++++ .../drm/amd/display/dc/i2caux/aux_engine.h | 2 ++ .../dc/i2caux/dce110/aux_engine_dce110.c | 30 +++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c index 667660f3fa26..3c9608ce94b8 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c @@ -69,6 +69,12 @@ bool dal_aux_engine_acquire( struct aux_engine *aux_engine = FROM_ENGINE(engine); enum gpio_result result; + if (aux_engine->funcs->is_engine_available) { + /*check whether SW could use the engine*/ + if (!aux_engine->funcs->is_engine_available(aux_engine)) { + return false; + } + } result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, GPIO_DDC_CONFIG_TYPE_MODE_AUX); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h index b5d6c79eb029..40b202893772 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h @@ -86,6 +86,8 @@ struct aux_engine_funcs { enum aux_channel_operation_result (*get_channel_status)( struct aux_engine *engine, uint8_t *returned_bytes); + bool (*is_engine_available) ( + struct aux_engine *engine); }; struct aux_engine { diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index f49fd1ad3807..98ce0fe5ac37 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -93,15 +93,36 @@ static void destroy( } #define SW_CAN_ACCESS_AUX 1 +#define DMCU_CAN_ACCESS_AUX 2 +static bool is_engine_available( + struct aux_engine *engine) +{ + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + + uint32_t value = REG_READ(AUX_ARB_CONTROL); + uint32_t field = get_reg_field_value( + value, + AUX_ARB_CONTROL, + AUX_REG_RW_CNTL_STATUS); + + return (field != DMCU_CAN_ACCESS_AUX); +} static bool acquire_engine( struct aux_engine *engine) { struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); + uint32_t value = REG_READ(AUX_ARB_CONTROL); + uint32_t field = get_reg_field_value( + value, + AUX_ARB_CONTROL, + AUX_REG_RW_CNTL_STATUS); + if (field == DMCU_CAN_ACCESS_AUX) + return false; /* enable AUX before request SW to access AUX */ - uint32_t value = REG_READ(AUX_CONTROL); - uint32_t field = get_reg_field_value(value, + value = REG_READ(AUX_CONTROL); + field = get_reg_field_value(value, AUX_CONTROL, AUX_EN); @@ -395,6 +416,7 @@ static const struct aux_engine_funcs aux_engine_funcs = { .submit_channel_request = submit_channel_request, .process_channel_reply = process_channel_reply, .get_channel_status = get_channel_status, + .is_engine_available = is_engine_available, }; static const struct engine_funcs engine_funcs = { @@ -425,6 +447,10 @@ static bool construct( static void destruct( struct aux_engine_dce110 *engine) { + struct aux_engine_dce110 *aux110 = engine; +/*temp w/a, to do*/ + REG_UPDATE(AUX_ARB_CONTROL, AUX_DMCU_DONE_USING_AUX_REG, 1); + REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); dal_aux_engine_destruct(&engine->base); } -- GitLab From ab8db3e1653c50ae19d1c31d82f94beb5115aeef Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 28 Aug 2017 14:25:01 -0400 Subject: [PATCH 0844/2898] drm/amd/display: Move dis_clk into dc_state. dis_clk is single instance across pipes. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 38 ++++++----- .../gpu/drm/amd/display/dc/core/dc_resource.c | 10 ++- drivers/gpu/drm/amd/display/dc/dc.h | 5 ++ .../display/dc/dce110/dce110_hw_sequencer.c | 67 +++++++++---------- .../amd/display/dc/dce110/dce110_resource.c | 1 - .../gpu/drm/amd/display/dc/inc/core_types.h | 7 +- 7 files changed, 78 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 6bf8af7a592d..ab6ad946231e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -573,6 +573,8 @@ static bool construct(struct dc *dc, if (!dc->res_pool) goto fail; + dc_resource_state_construct(dc, dc->current_state); + if (!create_links(dc, init_params->num_virtual_links)) goto fail; @@ -677,6 +679,8 @@ bool dc_validate_guaranteed( if (context == NULL) goto context_alloc_fail; + dc_resource_state_construct(dc, dc->current_state); + atomic_inc(&context->ref_count); result = dc->res_pool->funcs->validate_guaranteed( @@ -1622,6 +1626,8 @@ void dc_set_power_state( switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: + dc_resource_state_construct(dc, dc->current_state); + dc->hwss.init_hw(dc); break; default: @@ -1638,6 +1644,7 @@ void dc_set_power_state( dc_resource_state_destruct(dc->current_state); memset(dc->current_state, 0, sizeof(*dc->current_state)); + dc->current_state->ref_count = ref_count; break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 65e12614d96c..b95b58d3648a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1181,7 +1181,9 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) &downspread.raw, sizeof(downspread)); } -static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) +static enum dc_status enable_link_dp( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; enum dc_status status; @@ -1201,14 +1203,14 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) max_link_rate = LINK_RATE_HIGH3; if (link_settings.link_rate == max_link_rate) { - if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { - if (pipe_ctx->dis_clk->cur_min_clks_state < DM_PP_CLOCKS_STATE_NOMINAL) - pipe_ctx->dis_clk->funcs->set_min_clocks_state( - pipe_ctx->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); + if (state->dis_clk->funcs->set_min_clocks_state) { + if (state->dis_clk->cur_min_clks_state < DM_PP_CLOCKS_STATE_NOMINAL) + state->dis_clk->funcs->set_min_clocks_state( + state->dis_clk, DM_PP_CLOCKS_STATE_NOMINAL); } else { uint32_t dp_phyclk_in_khz; const struct clocks_value clocks_value = - pipe_ctx->dis_clk->cur_clocks_value; + state->dis_clk->cur_clocks_value; /* 27mhz = 27000000hz= 27000khz */ dp_phyclk_in_khz = link_settings.link_rate * 27000; @@ -1216,8 +1218,8 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) if (((clocks_value.max_non_dp_phyclk_in_khz != 0) && (dp_phyclk_in_khz > clocks_value.max_non_dp_phyclk_in_khz)) || (dp_phyclk_in_khz > clocks_value.max_dp_phyclk_in_khz)) { - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + state->dis_clk->funcs->apply_clock_voltage_request( + state->dis_clk, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, dp_phyclk_in_khz, false, @@ -1256,7 +1258,9 @@ static enum dc_status enable_link_dp(struct pipe_ctx *pipe_ctx) return status; } -static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) +static enum dc_status enable_link_dp_mst( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) { struct dc_link *link = pipe_ctx->stream->sink->link; @@ -1269,7 +1273,7 @@ static enum dc_status enable_link_dp_mst(struct pipe_ctx *pipe_ctx) /* set the sink to MST mode before enabling the link */ dp_enable_mst_on_sink(link, true); - return enable_link_dp(pipe_ctx); + return enable_link_dp(state, pipe_ctx); } static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, @@ -1709,16 +1713,18 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) } /****************************enable_link***********************************/ -static enum dc_status enable_link(struct pipe_ctx *pipe_ctx) +static enum dc_status enable_link( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) { enum dc_status status = DC_ERROR_UNEXPECTED; switch (pipe_ctx->stream->signal) { case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_EDP: - status = enable_link_dp(pipe_ctx); + status = enable_link_dp(state, pipe_ctx); break; case SIGNAL_TYPE_DISPLAY_PORT_MST: - status = enable_link_dp_mst(pipe_ctx); + status = enable_link_dp_mst(state, pipe_ctx); msleep(200); break; case SIGNAL_TYPE_DVI_SINGLE_LINK: @@ -2285,11 +2291,13 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) return DC_OK; } -void core_link_enable_stream(struct pipe_ctx *pipe_ctx) +void core_link_enable_stream( + struct dc_state *state, + struct pipe_ctx *pipe_ctx) { struct dc *core_dc = pipe_ctx->stream->ctx->dc; - enum dc_status status = enable_link(pipe_ctx); + enum dc_status status = enable_link(state, pipe_ctx); if (status != DC_OK) { dm_logger_write(pipe_ctx->stream->ctx->logger, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a4e92219a594..c7bb966e8b29 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1033,7 +1033,6 @@ static int acquire_first_split_pipe( pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->stream_res.opp = pool->opps[i]; - pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; pipe_ctx->stream = stream; @@ -1368,7 +1367,6 @@ static int acquire_first_free_pipe( pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->stream_res.opp = pool->opps[i]; - pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = i; @@ -1714,6 +1712,14 @@ void dc_resource_state_copy_construct_current( dc_resource_state_copy_construct(dc->current_state, dst_ctx); } + +void dc_resource_state_construct( + const struct dc *dc, + struct dc_state *dst_ctx) +{ + dst_ctx->dis_clk = dc->res_pool->display_clock; +} + bool dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f3ccc2043405..e2159306a9c2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -679,6 +679,11 @@ bool dc_validate_global_state( * No hardware is programmed for call. Only validation is done. */ + +void dc_resource_state_construct( + const struct dc *dc, + struct dc_state *dst_ctx); + void dc_resource_state_copy_construct( const struct dc_state *src_ctx, struct dc_state *dst_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1c6e2006f2a1..42caad423430 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -828,6 +828,7 @@ static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) } static void build_audio_output( + struct dc_state *state, const struct pipe_ctx *pipe_ctx, struct audio_output *audio_output) { @@ -889,8 +890,8 @@ static void build_audio_output( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { audio_output->pll_info.dp_dto_source_clock_in_khz = - pipe_ctx->dis_clk->funcs->get_dp_ref_clk_frequency( - pipe_ctx->dis_clk); + state->dis_clk->funcs->get_dp_ref_clk_frequency( + state->dis_clk); } audio_output->pll_info.feed_back_divider = @@ -1109,7 +1110,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( resource_build_info_frame(pipe_ctx); dce110_update_info_frame(pipe_ctx); if (!pipe_ctx_old->stream) { - core_link_enable_stream(pipe_ctx); + core_link_enable_stream(context, pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) @@ -1461,42 +1462,34 @@ static void apply_min_clocks( bool pre_mode_set) { struct state_dependent_clocks req_clocks = {0}; - struct pipe_ctx *pipe_ctx; - int i; - - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (pipe_ctx->dis_clk != NULL) - break; - } if (!pre_mode_set) { /* set clock_state without verification */ - if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) { - pipe_ctx->dis_clk->funcs->set_min_clocks_state( - pipe_ctx->dis_clk, *clocks_state); + if (context->dis_clk->funcs->set_min_clocks_state) { + context->dis_clk->funcs->set_min_clocks_state( + context->dis_clk, *clocks_state); return; } /* TODO: This is incorrect. Figure out how to fix. */ - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_DISPLAY_CLK, - pipe_ctx->dis_clk->cur_clocks_value.dispclk_in_khz, + context->dis_clk->cur_clocks_value.dispclk_in_khz, pre_mode_set, false); - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_PIXELCLK, - pipe_ctx->dis_clk->cur_clocks_value.max_pixelclk_in_khz, + context->dis_clk->cur_clocks_value.max_pixelclk_in_khz, pre_mode_set, false); - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, - pipe_ctx->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz, + context->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz, pre_mode_set, false); return; @@ -1510,28 +1503,28 @@ static void apply_min_clocks( req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths( dc, context, true); - if (pipe_ctx->dis_clk->funcs->get_required_clocks_state) { - *clocks_state = pipe_ctx->dis_clk->funcs->get_required_clocks_state( - pipe_ctx->dis_clk, &req_clocks); - pipe_ctx->dis_clk->funcs->set_min_clocks_state( - pipe_ctx->dis_clk, *clocks_state); + if (context->dis_clk->funcs->get_required_clocks_state) { + *clocks_state = context->dis_clk->funcs->get_required_clocks_state( + context->dis_clk, &req_clocks); + context->dis_clk->funcs->set_min_clocks_state( + context->dis_clk, *clocks_state); } else { - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_DISPLAY_CLK, req_clocks.display_clk_khz, pre_mode_set, false); - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_PIXELCLK, req_clocks.pixel_clk_khz, pre_mode_set, false); - pipe_ctx->dis_clk->funcs->apply_clock_voltage_request( - pipe_ctx->dis_clk, + context->dis_clk->funcs->apply_clock_voltage_request( + context->dis_clk, DM_PP_CLOCK_TYPE_DISPLAYPHYCLK, req_clocks.pixel_clk_khz, pre_mode_set, @@ -1806,7 +1799,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; - build_audio_output(pipe_ctx, &audio_output); + build_audio_output(context, pipe_ctx, &audio_output); pipe_ctx->stream_res.audio->funcs->wall_dto_setup( pipe_ctx->stream_res.audio, @@ -1834,7 +1827,7 @@ enum dc_status dce110_apply_ctx_to_hw( if (pipe_ctx->stream_res.audio != NULL) { struct audio_output audio_output; - build_audio_output(pipe_ctx, &audio_output); + build_audio_output(context, pipe_ctx, &audio_output); pipe_ctx->stream_res.audio->funcs->wall_dto_setup( pipe_ctx->stream_res.audio, @@ -1868,7 +1861,7 @@ enum dc_status dce110_apply_ctx_to_hw( struct audio_output audio_output; - build_audio_output(pipe_ctx, &audio_output); + build_audio_output(context, pipe_ctx, &audio_output); if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 94b6eb83e01e..4942460d42ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -971,7 +971,6 @@ static struct pipe_ctx *dce110_acquire_underlay( /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; pipe_ctx->stream_res.opp = pool->opps[underlay_idx]; - pipe_ctx->dis_clk = pool->display_clock; pipe_ctx->pipe_idx = underlay_idx; pipe_ctx->stream = stream; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 71eb9859faf2..915d5c10361b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -70,7 +70,9 @@ enum dc_status dc_link_validate_mode_timing( void core_link_resume(struct dc_link *link); -void core_link_enable_stream(struct pipe_ctx *pipe_ctx); +void core_link_enable_stream( + struct dc_state *state, + struct pipe_ctx *pipe_ctx); void core_link_disable_stream(struct pipe_ctx *pipe_ctx); @@ -188,7 +190,6 @@ struct pipe_ctx { struct plane_resource plane_res; struct stream_resource stream_res; - struct display_clock *dis_clk; struct clock_source *clock_source; struct pll_settings pll_settings; @@ -268,6 +269,8 @@ struct dc_state { struct dcn_bw_internal_vars dcn_bw_vars; #endif + struct display_clock *dis_clk; + atomic_t ref_count; }; -- GitLab From c9bb686b597d30935d6e05aaade51fc765d1ca5b Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Mon, 28 Aug 2017 16:50:17 -0400 Subject: [PATCH 0845/2898] drm/amd/display: Fix time out on boot On boot, hubp 0 is powergated during enable accel mode, so we time out when we try to blank in undo wa. Fix: Check power gate status before set blank Signed-off-by: Eric Yang Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 71ff1cedbdf4..7ea274475598 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -780,6 +780,12 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = dc->res_pool->mis[0]; + int pwr_status = 0; + + REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status); + /* Don't need to blank if hubp is power gated*/ + if (pwr_status == 2) + return; mi->funcs->set_blank(mi, true); -- GitLab From c7299705e6e76fe499ddc9af7beb0500e945fec9 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 28 Aug 2017 16:28:34 -0400 Subject: [PATCH 0846/2898] drm/amd/display: only polling VSync Phase within VSync peroroid Signed-off-by: Charlene Liu Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +-- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 +-- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 27 ++++++++++--------- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 2 +- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b95b58d3648a..cea8dafd2edc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1862,13 +1862,13 @@ bool dc_link_set_abm_disable(const struct dc_link *link) } -bool dc_link_set_psr_enable(const struct dc_link *link, bool enable) +bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait) { struct dc *core_dc = link->ctx->dc; struct dmcu *dmcu = core_dc->res_pool->dmcu; if (dmcu != NULL && link->psr_enabled) - dmcu->funcs->set_psr_enable(dmcu, enable); + dmcu->funcs->set_psr_enable(dmcu, enable, wait); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 5f2b52e41427..527cc0400fd3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1653,8 +1653,8 @@ static bool handle_hpd_irq_psr_sink(const struct dc_link *link) sizeof(psr_error_status.raw)); /* PSR error, disable and re-enable PSR */ - dc_link_set_psr_enable(link, false); - dc_link_set_psr_enable(link, true); + dc_link_set_psr_enable(link, false, true); + dc_link_set_psr_enable(link, true, true); return true; } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS == diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e2159306a9c2..2316a6060b2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -871,7 +871,7 @@ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream_state *stream); -bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable); +bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable, bool wait); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index efcdb2bf4d0d..313f61bf06e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -103,7 +103,7 @@ static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); } -static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) +static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); unsigned int dmcu_max_retry_on_wait_reg_ready = 801; @@ -127,17 +127,18 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) /* notifyDMCUMsg */ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); - - for (retryCount = 0; retryCount <= 100; retryCount++) { - dce_get_dmcu_psr_state(dmcu, &psr_state); - if (enable) { - if (psr_state != 0) - break; - } else { - if (psr_state == 0) - break; + if (wait == true) { + for (retryCount = 0; retryCount <= 100; retryCount++) { + dce_get_dmcu_psr_state(dmcu, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + dm_delay_in_microseconds(dmcu->ctx, 10); } - dm_delay_in_microseconds(dmcu->ctx, 10); } } @@ -338,7 +339,7 @@ static void dcn10_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state) REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0); } -static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) +static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); unsigned int dmcu_max_retry_on_wait_reg_ready = 801; @@ -367,6 +368,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) * Exit PSR may need to wait 1-2 frames to power up. Timeout after at * least a few frames. Should never hit the max retry assert below. */ + if (wait == true) { for (retryCount = 0; retryCount <= 1000; retryCount++) { dcn10_get_dmcu_psr_state(dmcu, &psr_state); if (enable) { @@ -381,6 +383,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable) /* assert if max retry hit */ ASSERT(retryCount <= 1000); + } } static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index e34b25939a98..0574c29cc4a8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -37,7 +37,7 @@ struct dmcu_funcs { unsigned int start_offset, const char *src, unsigned int bytes); - void (*set_psr_enable)(struct dmcu *dmcu, bool enable); + void (*set_psr_enable)(struct dmcu *dmcu, bool enable, bool wait); void (*setup_psr)(struct dmcu *dmcu, struct dc_link *link, struct psr_context *psr_context); -- GitLab From b97a88cd569c5f1dac82654bee2efee07633921c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Mon, 28 Aug 2017 14:05:17 -0400 Subject: [PATCH 0847/2898] drm/amd/display: clean up functions in dcn10_dpp_cm Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 420 ------------ .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 628 ++++-------------- 2 files changed, 140 insertions(+), 908 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 9a678dcaa908..717930584111 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -97,12 +97,6 @@ SRI(CM_DGAM_RAMB_END_CNTL1_R, CM, id), \ SRI(CM_DGAM_RAMB_END_CNTL2_R, CM, id), \ SRI(CM_DGAM_RAMB_REGION_0_1, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_2_3, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_4_5, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_6_7, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_8_9, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_10_11, CM, id), \ - SRI(CM_DGAM_RAMB_REGION_12_13, CM, id), \ SRI(CM_DGAM_RAMB_REGION_14_15, CM, id), \ SRI(CM_DGAM_RAMA_START_CNTL_B, CM, id), \ SRI(CM_DGAM_RAMA_START_CNTL_G, CM, id), \ @@ -117,12 +111,6 @@ SRI(CM_DGAM_RAMA_END_CNTL1_R, CM, id), \ SRI(CM_DGAM_RAMA_END_CNTL2_R, CM, id), \ SRI(CM_DGAM_RAMA_REGION_0_1, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_2_3, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_4_5, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_6_7, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_8_9, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_10_11, CM, id), \ - SRI(CM_DGAM_RAMA_REGION_12_13, CM, id), \ SRI(CM_DGAM_RAMA_REGION_14_15, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_DGAM_LUT_WRITE_EN_MASK, CM, id), \ @@ -174,21 +162,6 @@ SRI(CM_RGAM_RAMB_END_CNTL1_R, CM, id), \ SRI(CM_RGAM_RAMB_END_CNTL2_R, CM, id), \ SRI(CM_RGAM_RAMB_REGION_0_1, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_2_3, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_4_5, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_6_7, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_8_9, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_10_11, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_12_13, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_14_15, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_16_17, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_18_19, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_20_21, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_22_23, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_24_25, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_26_27, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_28_29, CM, id), \ - SRI(CM_RGAM_RAMB_REGION_30_31, CM, id), \ SRI(CM_RGAM_RAMB_REGION_32_33, CM, id), \ SRI(CM_RGAM_RAMA_START_CNTL_B, CM, id), \ SRI(CM_RGAM_RAMA_START_CNTL_G, CM, id), \ @@ -203,21 +176,6 @@ SRI(CM_RGAM_RAMA_END_CNTL1_R, CM, id), \ SRI(CM_RGAM_RAMA_END_CNTL2_R, CM, id), \ SRI(CM_RGAM_RAMA_REGION_0_1, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_2_3, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_4_5, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_6_7, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_8_9, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_10_11, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_12_13, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_14_15, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_16_17, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_18_19, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_20_21, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_22_23, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_24_25, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_26_27, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_28_29, CM, id), \ - SRI(CM_RGAM_RAMA_REGION_30_31, CM, id), \ SRI(CM_RGAM_RAMA_REGION_32_33, CM, id), \ SRI(CM_RGAM_CONTROL, CM, id), \ SRI(CM_IGAM_CONTROL, CM, id), \ @@ -338,30 +296,6 @@ TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_0_1, CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_2_3, CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_4_5, CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_6_7, CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_8_9, CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_10_11, CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMB_REGION_12_13, CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_REGION_14_15, CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ @@ -388,30 +322,6 @@ TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_0_1, CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_2_3, CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_4_5, CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_6_7, CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_8_9, CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_10_11, CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_DGAM_RAMA_REGION_12_13, CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMA_REGION_14_15, CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ @@ -501,66 +411,6 @@ TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_0_1, CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_2_3, CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_4_5, CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_6_7, CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_8_9, CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_10_11, CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_12_13, CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_14_15, CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_16_17, CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_18_19, CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_20_21, CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_22_23, CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_24_25, CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_26_27, CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_28_29, CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMB_REGION_30_31, CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMB_REGION_32_33, CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh), \ @@ -587,66 +437,6 @@ TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_0_1, CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_2_3, CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_4_5, CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_6_7, CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_8_9, CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_10_11, CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_12_13, CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_14_15, CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_16_17, CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_18_19, CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_20_21, CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_22_23, CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_24_25, CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_26_27, CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_28_29, CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh), \ - TF_SF(CM0_CM_RGAM_RAMA_REGION_30_31, CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh), \ TF_SF(CM0_CM_RGAM_RAMA_REGION_32_33, CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh), \ @@ -816,66 +606,6 @@ type CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ type CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ type CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS; \ - type CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET; \ - type CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS; \ type CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET; \ type CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS; \ type CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET; \ @@ -902,66 +632,6 @@ type CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ type CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ type CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS; \ - type CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET; \ - type CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS; \ type CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET; \ type CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS; \ type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ @@ -1370,30 +1040,6 @@ type CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS; \ type CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET; \ type CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS; \ - type CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET; \ - type CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS; \ type CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET; \ type CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS; \ type CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET; \ @@ -1420,30 +1066,6 @@ type CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; \ type CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; \ type CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS; \ - type CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET; \ - type CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS; \ type CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET; \ type CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS; \ type CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET; \ @@ -1565,21 +1187,6 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMB_END_CNTL1_R; uint32_t CM_RGAM_RAMB_END_CNTL2_R; uint32_t CM_RGAM_RAMB_REGION_0_1; - uint32_t CM_RGAM_RAMB_REGION_2_3; - uint32_t CM_RGAM_RAMB_REGION_4_5; - uint32_t CM_RGAM_RAMB_REGION_6_7; - uint32_t CM_RGAM_RAMB_REGION_8_9; - uint32_t CM_RGAM_RAMB_REGION_10_11; - uint32_t CM_RGAM_RAMB_REGION_12_13; - uint32_t CM_RGAM_RAMB_REGION_14_15; - uint32_t CM_RGAM_RAMB_REGION_16_17; - uint32_t CM_RGAM_RAMB_REGION_18_19; - uint32_t CM_RGAM_RAMB_REGION_20_21; - uint32_t CM_RGAM_RAMB_REGION_22_23; - uint32_t CM_RGAM_RAMB_REGION_24_25; - uint32_t CM_RGAM_RAMB_REGION_26_27; - uint32_t CM_RGAM_RAMB_REGION_28_29; - uint32_t CM_RGAM_RAMB_REGION_30_31; uint32_t CM_RGAM_RAMB_REGION_32_33; uint32_t CM_RGAM_RAMA_START_CNTL_B; uint32_t CM_RGAM_RAMA_START_CNTL_G; @@ -1594,21 +1201,6 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMA_END_CNTL1_R; uint32_t CM_RGAM_RAMA_END_CNTL2_R; uint32_t CM_RGAM_RAMA_REGION_0_1; - uint32_t CM_RGAM_RAMA_REGION_2_3; - uint32_t CM_RGAM_RAMA_REGION_4_5; - uint32_t CM_RGAM_RAMA_REGION_6_7; - uint32_t CM_RGAM_RAMA_REGION_8_9; - uint32_t CM_RGAM_RAMA_REGION_10_11; - uint32_t CM_RGAM_RAMA_REGION_12_13; - uint32_t CM_RGAM_RAMA_REGION_14_15; - uint32_t CM_RGAM_RAMA_REGION_16_17; - uint32_t CM_RGAM_RAMA_REGION_18_19; - uint32_t CM_RGAM_RAMA_REGION_20_21; - uint32_t CM_RGAM_RAMA_REGION_22_23; - uint32_t CM_RGAM_RAMA_REGION_24_25; - uint32_t CM_RGAM_RAMA_REGION_26_27; - uint32_t CM_RGAM_RAMA_REGION_28_29; - uint32_t CM_RGAM_RAMA_REGION_30_31; uint32_t CM_RGAM_RAMA_REGION_32_33; uint32_t CM_RGAM_CONTROL; uint32_t OBUF_CONTROL; @@ -1743,12 +1335,6 @@ struct dcn_dpp_registers { uint32_t CM_DGAM_RAMB_END_CNTL1_R; uint32_t CM_DGAM_RAMB_END_CNTL2_R; uint32_t CM_DGAM_RAMB_REGION_0_1; - uint32_t CM_DGAM_RAMB_REGION_2_3; - uint32_t CM_DGAM_RAMB_REGION_4_5; - uint32_t CM_DGAM_RAMB_REGION_6_7; - uint32_t CM_DGAM_RAMB_REGION_8_9; - uint32_t CM_DGAM_RAMB_REGION_10_11; - uint32_t CM_DGAM_RAMB_REGION_12_13; uint32_t CM_DGAM_RAMB_REGION_14_15; uint32_t CM_DGAM_RAMA_START_CNTL_B; uint32_t CM_DGAM_RAMA_START_CNTL_G; @@ -1763,12 +1349,6 @@ struct dcn_dpp_registers { uint32_t CM_DGAM_RAMA_END_CNTL1_R; uint32_t CM_DGAM_RAMA_END_CNTL2_R; uint32_t CM_DGAM_RAMA_REGION_0_1; - uint32_t CM_DGAM_RAMA_REGION_2_3; - uint32_t CM_DGAM_RAMA_REGION_4_5; - uint32_t CM_DGAM_RAMA_REGION_6_7; - uint32_t CM_DGAM_RAMA_REGION_8_9; - uint32_t CM_DGAM_RAMA_REGION_10_11; - uint32_t CM_DGAM_RAMA_REGION_12_13; uint32_t CM_DGAM_RAMA_REGION_14_15; uint32_t CM_DGAM_LUT_WRITE_EN_MASK; uint32_t CM_DGAM_LUT_INDEX; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 81620241a978..01b1c0ee0110 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -453,331 +453,145 @@ void dcn10_dpp_cm_configure_regamma_lut( REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); } -/*program re gamma RAM A*/ -void dcn10_dpp_cm_program_regamma_luta_settings( +struct cm_gam_ram_reg { + uint32_t start_cntl_b; + uint32_t start_cntl_g; + uint32_t start_cntl_r; + uint32_t start_slope_cntl_b; + uint32_t start_slope_cntl_g; + uint32_t start_slope_cntl_r; + uint32_t start_end_cntl1_b; + uint32_t start_end_cntl2_b; + uint32_t start_end_cntl1_g; + uint32_t start_end_cntl2_g; + uint32_t start_end_cntl1_r; + uint32_t start_end_cntl2_r; + uint32_t region_start; + uint32_t region_end; +}; + +static void dpp_cm_program_region_lut( struct transform *xfm_base, - const struct pwl_params *params) + const struct pwl_params *params, + const struct cm_gam_ram_reg *reg) { - const struct gamma_curve *curve; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + uint32_t reg_region_cur; + unsigned int i = 0; + +#undef REG +#define REG(reg) reg - REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0, + REG_SET_2(reg->start_cntl_b, 0, CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0, + REG_SET_2(reg->start_cntl_g, 0, CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0, + REG_SET_2(reg->start_cntl_r, 0, CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0, + REG_SET(reg->start_slope_cntl_b, 0, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0, + REG_SET(reg->start_slope_cntl_g, 0, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0, + REG_SET(reg->start_slope_cntl_r, 0, CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0, + REG_SET(reg->start_end_cntl1_b, 0, CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0, + REG_SET_2(reg->start_end_cntl2_b, 0, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0, + REG_SET(reg->start_end_cntl1_g, 0, CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0, + REG_SET_2(reg->start_end_cntl2_g, 0, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0, + REG_SET(reg->start_end_cntl1_r, 0, CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0, + REG_SET_2(reg->start_end_cntl2_r, 0, CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0, - CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0, - CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0, - CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0, - CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0, - CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0, - CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0, - CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0, - CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0, - CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0, - CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0, - CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0, - CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0, - CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0, - CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0, - CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0, - CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0, - CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + for (reg_region_cur = reg->region_start; + reg_region_cur <= reg->region_end; + reg_region_cur++) { + + const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); + const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); + + REG_SET_4(reg_region_cur, 0, + CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve0->offset, + CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve0->segments_num, + CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve1->offset, + CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve1->segments_num); + + i++; + } + +#undef REG +#define REG(reg)\ + xfm->tf_regs->reg + } -/*program re gamma RAM B*/ -void dcn10_dpp_cm_program_regamma_lutb_settings( + + +/*program re gamma RAM A*/ +void dcn10_dpp_cm_program_regamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params) { - const struct gamma_curve *curve; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct cm_gam_ram_reg gam_regs; + + gam_regs.start_cntl_b = REG(CM_RGAM_RAMA_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_RGAM_RAMA_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_RGAM_RAMA_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_RGAM_RAMA_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_RGAM_RAMA_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_RGAM_RAMA_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_RGAM_RAMA_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_RGAM_RAMA_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_RGAM_RAMA_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_RGAM_RAMA_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_RGAM_RAMA_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_RGAM_RAMA_END_CNTL2_R); + gam_regs.region_start = REG(CM_RGAM_RAMA_REGION_0_1); + gam_regs.region_end = REG(CM_RGAM_RAMA_REGION_32_33); + + dpp_cm_program_region_lut(xfm_base, params, &gam_regs); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0, - CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0, - CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - curve = params->arr_curve_points; - REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0, - CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0, - CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0, - CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0, - CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0, - CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0, - CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0, - CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0, - CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0, - CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0, - CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0, - CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0, - CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0, - CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0, - CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0, - CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0, - CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0, - CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, - CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, - CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, - CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} +/*program re gamma RAM B*/ +void dcn10_dpp_cm_program_regamma_lutb_settings( + struct transform *xfm_base, + const struct pwl_params *params) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct cm_gam_ram_reg gam_regs; + + gam_regs.start_cntl_b = REG(CM_RGAM_RAMB_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_RGAM_RAMB_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_RGAM_RAMB_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_RGAM_RAMB_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_RGAM_RAMB_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_RGAM_RAMB_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_RGAM_RAMB_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_RGAM_RAMB_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_RGAM_RAMB_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_RGAM_RAMB_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_RGAM_RAMB_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_RGAM_RAMB_END_CNTL2_R); + gam_regs.region_start = REG(CM_RGAM_RAMB_REGION_0_1); + gam_regs.region_end = REG(CM_RGAM_RAMB_REGION_32_33); + + dpp_cm_program_region_lut(xfm_base, params, &gam_regs); } void ippn10_program_input_csc( @@ -874,106 +688,25 @@ void ippn10_program_degamma_lutb_settings( struct transform *xfm_base, const struct pwl_params *params) { - const struct gamma_curve *curve; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_B, 0, - CM_DGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_G, 0, - CM_DGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0); - - REG_SET_2(CM_DGAM_RAMB_START_CNTL_R, 0, - CM_DGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_B, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_G, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_SLOPE_CNTL_R, 0, - CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_B, 0, - CM_DGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_B, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_G, 0, - CM_DGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_G, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMB_END_CNTL1_R, 0, - CM_DGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMB_END_CNTL2_R, 0, - CM_DGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, - CM_DGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); - - curve = params->arr_curve_points; - REG_SET_4(CM_DGAM_RAMB_REGION_0_1, 0, - CM_DGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_2_3, 0, - CM_DGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_4_5, 0, - CM_DGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_6_7, 0, - CM_DGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_8_9, 0, - CM_DGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_10_11, 0, - CM_DGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_12_13, 0, - CM_DGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMB_REGION_14_15, 0, - CM_DGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + struct cm_gam_ram_reg gam_regs; + + gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_DGAM_RAMB_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_DGAM_RAMB_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_DGAM_RAMB_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_DGAM_RAMB_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_DGAM_RAMB_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_DGAM_RAMB_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_DGAM_RAMB_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_DGAM_RAMB_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_DGAM_RAMB_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_DGAM_RAMB_END_CNTL2_R); + gam_regs.region_start = REG(CM_DGAM_RAMB_REGION_0_1); + gam_regs.region_end = REG(CM_DGAM_RAMB_REGION_14_15); + + dpp_cm_program_region_lut(xfm_base, params, &gam_regs); } /*program de gamma RAM A*/ @@ -981,106 +714,25 @@ void ippn10_program_degamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params) { - const struct gamma_curve *curve; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_B, 0, - CM_DGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_G, 0, - CM_DGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - - REG_SET_2(CM_DGAM_RAMA_START_CNTL_R, 0, - CM_DGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_DGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_B, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_G, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_SLOPE_CNTL_R, 0, - CM_DGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_B, 0, - CM_DGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_B, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_G, 0, - CM_DGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_G, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[2].custom_float_slope); - - REG_SET(CM_DGAM_RAMA_END_CNTL1_R, 0, - CM_DGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - - REG_SET_2(CM_DGAM_RAMA_END_CNTL2_R, 0, - CM_DGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_y, - CM_DGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[2].custom_float_slope); - - curve = params->arr_curve_points; - REG_SET_4(CM_DGAM_RAMA_REGION_0_1, 0, - CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_2_3, 0, - CM_DGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_4_5, 0, - CM_DGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_6_7, 0, - CM_DGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_8_9, 0, - CM_DGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_10_11, 0, - CM_DGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_12_13, 0, - CM_DGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); - - curve += 2; - REG_SET_4(CM_DGAM_RAMA_REGION_14_15, 0, - CM_DGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, - CM_DGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, - CM_DGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, - CM_DGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + struct cm_gam_ram_reg gam_regs; + + gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_DGAM_RAMA_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_DGAM_RAMA_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_DGAM_RAMA_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_DGAM_RAMA_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_DGAM_RAMA_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_DGAM_RAMA_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_DGAM_RAMA_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_DGAM_RAMA_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_DGAM_RAMA_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_DGAM_RAMA_END_CNTL2_R); + gam_regs.region_start = REG(CM_DGAM_RAMA_REGION_0_1); + gam_regs.region_end = REG(CM_DGAM_RAMA_REGION_14_15); + + dpp_cm_program_region_lut(xfm_base, params, &gam_regs); } void ippn10_power_on_degamma_lut( -- GitLab From 1f0997f1555571a9c16205a851ffbce92097196d Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 28 Aug 2017 19:33:23 -0400 Subject: [PATCH 0848/2898] drm/amd/display: not override the FMT setting set by VBIOS for eDP Signed-off-by: Charlene Liu Reviewed-by: Krunoslav Kovac Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 42caad423430..3b4ca1a9217f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1082,11 +1082,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( /*vbios crtc_source_selection and encoder_setup will override fmt_C*/ - pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + if (pipe_ctx->stream->signal != SIGNAL_TYPE_EDP && + pipe_ctx->stream->signal != SIGNAL_TYPE_LVDS) { + /*for embedded panel, don't override VBIOS's setting*/ + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); - + } if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_res.stream_enc, -- GitLab From 1e4cee77bbd50d6c868439bfaf8ad61b6c6fcfc3 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 28 Aug 2017 19:35:25 -0400 Subject: [PATCH 0849/2898] drm/amd/display: add backlight control in blankstream. Signed-off-by: Charlene Liu Reviewed-by: Krunoslav Kovac Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 3b4ca1a9217f..9fb0ba7e7b7d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -778,9 +778,11 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) /* blank at encoder level */ - if (dc_is_dp_signal(pipe_ctx->stream->signal)) + if (dc_is_dp_signal(pipe_ctx->stream->signal)) { + if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) + link->link_enc->funcs->backlight_control(link->link_enc, false); pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); - + } link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, pipe_ctx->stream_res.stream_enc->id, @@ -792,12 +794,15 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings) { struct encoder_unblank_param params = { { 0 } }; + struct dc_link *link = pipe_ctx->stream->sink->link; /* only 3 items below are used by unblank */ params.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz; params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); + if (link->connector_signal == SIGNAL_TYPE_EDP) + link->link_enc->funcs->backlight_control(link->link_enc, true); } -- GitLab From 07fde11f27fb4de3b63ef117593291b094a23e15 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 25 Aug 2017 16:44:20 -0400 Subject: [PATCH 0850/2898] drm/amd/display: program fbc for scatter/gather Fixing screen flickering when FBC enabled on Stoney Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_compressor.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 2e97e5757fb9..f82c26995609 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -189,7 +189,7 @@ void dce110_compressor_enable_fbc( (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL))) { uint32_t addr; - uint32_t value; + uint32_t value, misc_value; addr = mmFBC_CNTL; @@ -206,9 +206,23 @@ void dce110_compressor_enable_fbc( compressor->attached_inst = params->inst; cp110->offsets = reg_offsets[params->inst]; - /*Toggle it as there is bug in HW */ + /* Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); dm_write_reg(compressor->ctx, addr, value); + + /* FBC usage with scatter & gather for dce110 */ + misc_value = dm_read_reg(compressor->ctx, mmFBC_MISC); + + set_reg_field_value(misc_value, 1, + FBC_MISC, FBC_INVALIDATE_ON_ERROR); + set_reg_field_value(misc_value, 1, + FBC_MISC, FBC_DECOMPRESS_ERROR_CLEAR); + set_reg_field_value(misc_value, 0x14, + FBC_MISC, FBC_SLOW_REQ_INTERVAL); + + dm_write_reg(compressor->ctx, mmFBC_MISC, misc_value); + + /* Enable FBC */ set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); dm_write_reg(compressor->ctx, addr, value); -- GitLab From 4486201caf9c890f132d9a7631b4e5ebbaf524c3 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 29 Aug 2017 12:50:21 -0400 Subject: [PATCH 0851/2898] drm/amd/display: Program reg for vertical interrupt. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 10 ++++++++++ .../drm/amd/display/dc/dcn10/dcn10_timing_generator.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 6a5f2683c2e5..94ea3a9f6bb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -118,6 +118,7 @@ static void tgn10_program_timing( uint32_t start_point = 0; uint32_t field_num = 0; uint32_t h_div_2; + uint32_t vertial_line_start; struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -212,6 +213,12 @@ static void tgn10_program_timing( OTG_V_BLANK_START, asic_blank_start, OTG_V_BLANK_END, asic_blank_end); + /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, + * program the reg for interrupt postition. + */ + vertial_line_start = asic_blank_end - tg->dlg_otg_param.vstartup_start + 1; + REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, + OTG_VERTICAL_INTERRUPT2_LINE_START, vertial_line_start); /* v_sync polarity */ v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? @@ -289,6 +296,9 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); + REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, OTG_BLANK_DE_MODE, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 654889318fc1..38d3dcf89d60 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -65,6 +65,7 @@ SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ SRI(OTG_BLACK_COLOR, OTG, inst),\ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ @@ -120,6 +121,7 @@ struct dcn_tg_registers { uint32_t OTG_TEST_PATTERN_CONTROL; uint32_t OTG_TEST_PATTERN_COLOR; uint32_t OTG_CLOCK_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; uint32_t OPTC_INPUT_GLOBAL_CONTROL; @@ -203,6 +205,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ @@ -308,6 +311,7 @@ struct dcn_tg_registers { type OTG_CLOCK_EN;\ type OTG_CLOCK_ON;\ type OTG_CLOCK_GATE_DIS;\ + type OTG_VERTICAL_INTERRUPT2_LINE_START;\ type OPTC_INPUT_CLK_EN;\ type OPTC_INPUT_CLK_ON;\ type OPTC_INPUT_CLK_GATE_DIS;\ -- GitLab From 0bfac360edcd843e90a0444475616a486f643eeb Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 29 Aug 2017 15:27:20 -0400 Subject: [PATCH 0852/2898] drm/amd/display: Disable OTG double buffer. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 94ea3a9f6bb4..15f1f44e102a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -296,9 +296,6 @@ static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); - REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, OTG_BLANK_DE_MODE, 0); -- GitLab From 1d9521a74029c3afcf996e207ecd61a74414dd68 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 25 Aug 2017 16:33:40 -0400 Subject: [PATCH 0853/2898] drm/amd/display: Set add_stream_ctx for CZ, Hawaii and others Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce100/dce100_resource.c | 19 ++++++++++++++++++ .../amd/display/dc/dce100/dce100_resource.h | 5 +++++ .../amd/display/dc/dce110/dce110_resource.c | 20 +++++++++++++++++++ .../drm/amd/display/dc/dce80/dce80_resource.c | 1 + 4 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 36d79175354c..ca6c7c2a1b4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -713,6 +713,24 @@ enum dc_status dce100_validate_global( return DC_OK; } +enum dc_status dce100_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + enum dc_status dce100_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, @@ -769,6 +787,7 @@ static const struct resource_funcs dce100_res_pool_funcs = { .validate_guaranteed = dce100_validate_guaranteed, .validate_bandwidth = dce100_validate_bandwidth, .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce100_add_stream_to_ctx, .validate_global = dce100_validate_global }; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index ca7b2b7c1a48..f52cae24ee23 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -18,4 +18,9 @@ struct resource_pool *dce100_create_resource_pool( enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); +enum dc_status dce100_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream); + #endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 4942460d42ca..41bfddf9574e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -921,6 +921,25 @@ enum dc_status dce110_validate_global( return DC_OK; } +static enum dc_status dce110_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, new_ctx, dc_stream); + + + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + static enum dc_status dce110_validate_guaranteed( struct dc *dc, struct dc_stream_state *dc_stream, @@ -1030,6 +1049,7 @@ static const struct resource_funcs dce110_res_pool_funcs = { .validate_guaranteed = dce110_validate_guaranteed, .validate_bandwidth = dce110_validate_bandwidth, .acquire_idle_pipe_for_layer = dce110_acquire_underlay, + .add_stream_to_ctx = dce110_add_stream_to_ctx, .validate_global = dce110_validate_global }; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 316080767a21..9234086aac27 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -791,6 +791,7 @@ static const struct resource_funcs dce80_res_pool_funcs = { .validate_guaranteed = dce80_validate_guaranteed, .validate_bandwidth = dce80_validate_bandwidth, .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce100_add_stream_to_ctx, .validate_global = dce80_validate_global }; -- GitLab From 513b5693391af332feda8f273af8446ccd4a220b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 25 Aug 2017 22:34:51 -0400 Subject: [PATCH 0854/2898] drm/amd/display: Restore missing DCE8 xfm regs Signed-off-by: Harry Wentland Reviewed-by: Roman Li Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index d87225d15cd9..805bb9c4e188 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -94,6 +94,10 @@ SRI(SCL_UPDATE, SCL, id), \ SRI(SCL_F_SHARP_CONTROL, SCL, id) +#define XFM_COMMON_REG_LIST_DCE80(id) \ + XFM_COMMON_REG_LIST_DCE_BASE(id), \ + SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id) + #define XFM_COMMON_REG_LIST_DCE100(id) \ XFM_COMMON_REG_LIST_DCE_BASE(id), \ SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \ @@ -185,6 +189,12 @@ XFM_SF(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \ XFM_SF(LB_DATA_FORMAT, ALPHA_EN, mask_sh) +#define XFM_COMMON_MASK_SH_LIST_DCE80(mask_sh) \ + XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) + #define XFM_COMMON_MASK_SH_LIST_DCE110(mask_sh) \ XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \ XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 9234086aac27..5453f02ea8ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -187,7 +187,7 @@ static const struct dce_ipp_mask ipp_mask = { #define transform_regs(id)\ [id] = {\ - XFM_COMMON_REG_LIST_DCE_BASE(id)\ + XFM_COMMON_REG_LIST_DCE80(id)\ } static const struct dce_transform_registers xfm_regs[] = { @@ -200,11 +200,11 @@ static const struct dce_transform_registers xfm_regs[] = { }; static const struct dce_transform_shift xfm_shift = { - XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) + XFM_COMMON_MASK_SH_LIST_DCE80(__SHIFT) }; static const struct dce_transform_mask xfm_mask = { - XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) + XFM_COMMON_MASK_SH_LIST_DCE80(_MASK) }; #define aux_regs(id)\ -- GitLab From 7c228a1a910784801360db5aedd153db9f465b56 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 28 Aug 2017 10:59:39 -0400 Subject: [PATCH 0855/2898] drm/amd/display: Don't spam log with failed validation In a lot of case we fail validation of timings for legitimate reasons. No need to print an error. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c7bb966e8b29..fbf7747424a9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2711,7 +2711,6 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) { struct dc *core_dc = dc; - struct dc_context *dc_ctx = core_dc->ctx; struct dc_link *link = stream->sink->link; struct timing_generator *tg = core_dc->res_pool->timing_generators[0]; enum dc_status res = DC_OK; @@ -2733,10 +2732,6 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) link, &stream->timing); - if (res != DC_OK) - DC_ERROR("Failed validation for stream %p, err:%d, !\n", - stream, res); - return res == DC_OK; } -- GitLab From fd96c1775a75c14bf15465af7040cc00855b1ec0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 28 Aug 2017 09:51:03 -0400 Subject: [PATCH 0856/2898] drm/amd/display: delete dead code Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index ee1b76c074e6..1b0f64756be6 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1312,8 +1312,9 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) { struct pp_smu_funcs_rv *pp = dc->res_pool->pp_smu; struct pp_smu_wm_range_sets ranges = {0}; - int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz, - nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz; + int max_fclk_khz, nom_fclk_khz, mid_fclk_khz, min_fclk_khz; + int max_dcfclk_khz, min_dcfclk_khz; + int socclk_khz; const int overdrive = 5000000; /* 5 GHz to cover Overdrive */ unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); @@ -1326,7 +1327,6 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) mid_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 * 1000000 / factor; min_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32; max_dcfclk_khz = dc->dcn_soc->dcfclkv_max0p9 * 1000; - nom_dcfclk_khz = dc->dcn_soc->dcfclkv_nom0p8 * 1000; min_dcfclk_khz = dc->dcn_soc->dcfclkv_min0p65 * 1000; socclk_khz = dc->dcn_soc->socclk * 1000; kernel_fpu_end(); -- GitLab From 7ad124cc23172a7a70d642adf8f5c99f6c974539 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 29 Aug 2017 15:01:06 -0400 Subject: [PATCH 0857/2898] drm/amd/display: clean up cm register programming functions Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 120 --------- .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 251 ++++++------------ 2 files changed, 76 insertions(+), 295 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 717930584111..4bbd3b4f7ae6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -44,10 +44,6 @@ #define TF_REG_LIST_DCN(id) \ SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ - SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ - SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ - SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ - SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ @@ -79,10 +75,6 @@ SRI(OBUF_CONTROL, DSCL, id), \ SRI(CM_ICSC_CONTROL, CM, id), \ SRI(CM_ICSC_C11_C12, CM, id), \ - SRI(CM_ICSC_C13_C14, CM, id), \ - SRI(CM_ICSC_C21_C22, CM, id), \ - SRI(CM_ICSC_C23_C24, CM, id), \ - SRI(CM_ICSC_C31_C32, CM, id), \ SRI(CM_ICSC_C33_C34, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_B, CM, id), \ SRI(CM_DGAM_RAMB_START_CNTL_G, CM, id), \ @@ -127,23 +119,11 @@ #define TF_REG_LIST_DCN10(id) \ TF_REG_LIST_DCN(id), \ SRI(CM_COMA_C11_C12, CM, id),\ - SRI(CM_COMA_C13_C14, CM, id),\ - SRI(CM_COMA_C21_C22, CM, id),\ - SRI(CM_COMA_C23_C24, CM, id),\ - SRI(CM_COMA_C31_C32, CM, id),\ SRI(CM_COMA_C33_C34, CM, id),\ SRI(CM_COMB_C11_C12, CM, id),\ - SRI(CM_COMB_C13_C14, CM, id),\ - SRI(CM_COMB_C21_C22, CM, id),\ - SRI(CM_COMB_C23_C24, CM, id),\ - SRI(CM_COMB_C31_C32, CM, id),\ SRI(CM_COMB_C33_C34, CM, id),\ SRI(CM_OCSC_CONTROL, CM, id), \ SRI(CM_OCSC_C11_C12, CM, id), \ - SRI(CM_OCSC_C13_C14, CM, id), \ - SRI(CM_OCSC_C21_C22, CM, id), \ - SRI(CM_OCSC_C23_C24, CM, id), \ - SRI(CM_OCSC_C31_C32, CM, id), \ SRI(CM_OCSC_C33_C34, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_RGAM_LUT_DATA, CM, id), \ @@ -189,14 +169,6 @@ TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ - TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ @@ -264,14 +236,6 @@ TF_SF(CM0_CM_ICSC_CONTROL, CM_ICSC_MODE, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C11, mask_sh), \ TF_SF(CM0_CM_ICSC_C11_C12, CM_ICSC_C12, mask_sh), \ - TF_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C13, mask_sh), \ - TF_SF(CM0_CM_ICSC_C13_C14, CM_ICSC_C14, mask_sh), \ - TF_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C21, mask_sh), \ - TF_SF(CM0_CM_ICSC_C21_C22, CM_ICSC_C22, mask_sh), \ - TF_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C23, mask_sh), \ - TF_SF(CM0_CM_ICSC_C23_C24, CM_ICSC_C24, mask_sh), \ - TF_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C31, mask_sh), \ - TF_SF(CM0_CM_ICSC_C31_C32, CM_ICSC_C32, mask_sh), \ TF_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C33, mask_sh), \ TF_SF(CM0_CM_ICSC_C33_C34, CM_ICSC_C34, mask_sh), \ TF_SF(CM0_CM_DGAM_RAMB_START_CNTL_B, CM_DGAM_RAMB_EXP_REGION_START_B, mask_sh), \ @@ -349,39 +313,15 @@ TF_SF(DSCL0_LB_DATA_FORMAT, DITHER_EN, mask_sh),\ TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C11, mask_sh),\ TF_SF(CM0_CM_COMA_C11_C12, CM_COMA_C12, mask_sh),\ - TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C13, mask_sh),\ - TF_SF(CM0_CM_COMA_C13_C14, CM_COMA_C14, mask_sh),\ - TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C21, mask_sh),\ - TF_SF(CM0_CM_COMA_C21_C22, CM_COMA_C22, mask_sh),\ - TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C23, mask_sh),\ - TF_SF(CM0_CM_COMA_C23_C24, CM_COMA_C24, mask_sh),\ - TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C31, mask_sh),\ - TF_SF(CM0_CM_COMA_C31_C32, CM_COMA_C32, mask_sh),\ TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C33, mask_sh),\ TF_SF(CM0_CM_COMA_C33_C34, CM_COMA_C34, mask_sh),\ TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C11, mask_sh),\ TF_SF(CM0_CM_COMB_C11_C12, CM_COMB_C12, mask_sh),\ - TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C13, mask_sh),\ - TF_SF(CM0_CM_COMB_C13_C14, CM_COMB_C14, mask_sh),\ - TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C21, mask_sh),\ - TF_SF(CM0_CM_COMB_C21_C22, CM_COMB_C22, mask_sh),\ - TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C23, mask_sh),\ - TF_SF(CM0_CM_COMB_C23_C24, CM_COMB_C24, mask_sh),\ - TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C31, mask_sh),\ TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C33, mask_sh),\ - TF_SF(CM0_CM_COMB_C31_C32, CM_COMB_C32, mask_sh),\ TF_SF(CM0_CM_COMB_C33_C34, CM_COMB_C34, mask_sh),\ TF_SF(CM0_CM_OCSC_CONTROL, CM_OCSC_MODE, mask_sh), \ TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C11, mask_sh), \ TF_SF(CM0_CM_OCSC_C11_C12, CM_OCSC_C12, mask_sh), \ - TF_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C13, mask_sh), \ - TF_SF(CM0_CM_OCSC_C13_C14, CM_OCSC_C14, mask_sh), \ - TF_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C21, mask_sh), \ - TF_SF(CM0_CM_OCSC_C21_C22, CM_OCSC_C22, mask_sh), \ - TF_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C23, mask_sh), \ - TF_SF(CM0_CM_OCSC_C23_C24, CM_OCSC_C24, mask_sh), \ - TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C31, mask_sh), \ - TF_SF(CM0_CM_OCSC_C31_C32, CM_OCSC_C32, mask_sh), \ TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C33, mask_sh), \ TF_SF(CM0_CM_OCSC_C33_C34, CM_OCSC_C34, mask_sh), \ TF_SF(CM0_CM_MEM_PWR_CTRL, RGAM_MEM_PWR_FORCE, mask_sh), \ @@ -532,51 +472,19 @@ type CM_GAMUT_REMAP_MODE; \ type CM_GAMUT_REMAP_C11; \ type CM_GAMUT_REMAP_C12; \ - type CM_GAMUT_REMAP_C13; \ - type CM_GAMUT_REMAP_C14; \ - type CM_GAMUT_REMAP_C21; \ - type CM_GAMUT_REMAP_C22; \ - type CM_GAMUT_REMAP_C23; \ - type CM_GAMUT_REMAP_C24; \ - type CM_GAMUT_REMAP_C31; \ - type CM_GAMUT_REMAP_C32; \ type CM_GAMUT_REMAP_C33; \ type CM_GAMUT_REMAP_C34; \ type CM_COMA_C11; \ type CM_COMA_C12; \ - type CM_COMA_C13; \ - type CM_COMA_C14; \ - type CM_COMA_C21; \ - type CM_COMA_C22; \ - type CM_COMA_C23; \ - type CM_COMA_C24; \ - type CM_COMA_C31; \ - type CM_COMA_C32; \ type CM_COMA_C33; \ type CM_COMA_C34; \ type CM_COMB_C11; \ type CM_COMB_C12; \ - type CM_COMB_C13; \ - type CM_COMB_C14; \ - type CM_COMB_C21; \ - type CM_COMB_C22; \ - type CM_COMB_C23; \ - type CM_COMB_C24; \ - type CM_COMB_C31; \ - type CM_COMB_C32; \ type CM_COMB_C33; \ type CM_COMB_C34; \ type CM_OCSC_MODE; \ type CM_OCSC_C11; \ type CM_OCSC_C12; \ - type CM_OCSC_C13; \ - type CM_OCSC_C14; \ - type CM_OCSC_C21; \ - type CM_OCSC_C22; \ - type CM_OCSC_C23; \ - type CM_OCSC_C24; \ - type CM_OCSC_C31; \ - type CM_OCSC_C32; \ type CM_OCSC_C33; \ type CM_OCSC_C34; \ type RGAM_MEM_PWR_FORCE; \ @@ -1008,14 +916,6 @@ type CM_ICSC_MODE; \ type CM_ICSC_C11; \ type CM_ICSC_C12; \ - type CM_ICSC_C13; \ - type CM_ICSC_C14; \ - type CM_ICSC_C21; \ - type CM_ICSC_C22; \ - type CM_ICSC_C23; \ - type CM_ICSC_C24; \ - type CM_ICSC_C31; \ - type CM_ICSC_C32; \ type CM_ICSC_C33; \ type CM_ICSC_C34; \ type CM_DGAM_RAMB_EXP_REGION_START_B; \ @@ -1146,29 +1046,13 @@ struct dcn_dpp_registers { uint32_t RECOUT_SIZE; uint32_t CM_GAMUT_REMAP_CONTROL; uint32_t CM_GAMUT_REMAP_C11_C12; - uint32_t CM_GAMUT_REMAP_C13_C14; - uint32_t CM_GAMUT_REMAP_C21_C22; - uint32_t CM_GAMUT_REMAP_C23_C24; - uint32_t CM_GAMUT_REMAP_C31_C32; uint32_t CM_GAMUT_REMAP_C33_C34; uint32_t CM_COMA_C11_C12; - uint32_t CM_COMA_C13_C14; - uint32_t CM_COMA_C21_C22; - uint32_t CM_COMA_C23_C24; - uint32_t CM_COMA_C31_C32; uint32_t CM_COMA_C33_C34; uint32_t CM_COMB_C11_C12; - uint32_t CM_COMB_C13_C14; - uint32_t CM_COMB_C21_C22; - uint32_t CM_COMB_C23_C24; - uint32_t CM_COMB_C31_C32; uint32_t CM_COMB_C33_C34; uint32_t CM_OCSC_CONTROL; uint32_t CM_OCSC_C11_C12; - uint32_t CM_OCSC_C13_C14; - uint32_t CM_OCSC_C21_C22; - uint32_t CM_OCSC_C23_C24; - uint32_t CM_OCSC_C31_C32; uint32_t CM_OCSC_C33_C34; uint32_t CM_MEM_PWR_CTRL; uint32_t CM_RGAM_LUT_DATA; @@ -1317,10 +1201,6 @@ struct dcn_dpp_registers { uint32_t CM_SHAPER_LUT_DATA; uint32_t CM_ICSC_CONTROL; uint32_t CM_ICSC_C11_C12; - uint32_t CM_ICSC_C13_C14; - uint32_t CM_ICSC_C21_C22; - uint32_t CM_ICSC_C23_C24; - uint32_t CM_ICSC_C31_C32; uint32_t CM_ICSC_C33_C34; uint32_t CM_DGAM_RAMB_START_CNTL_B; uint32_t CM_DGAM_RAMB_START_CNTL_G; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 01b1c0ee0110..d698fccdef68 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -50,7 +50,7 @@ struct dcn10_input_csc_matrix { enum dc_color_space color_space; - uint32_t regval[12]; + uint16_t regval[12]; }; enum dcn10_coef_filter_type_sel { @@ -116,6 +116,38 @@ static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { 0x2568, 0x43ee, 0xdbb2} } }; +static void dpp_cm_program_color_registers( + struct dcn10_dpp *xfm, + const uint16_t *regval, + uint32_t cm_reg_start, + uint32_t cm_reg_end) +{ + uint32_t reg_region_cur; + unsigned int i = 0; + +#undef REG +#define REG(reg) reg + + for (reg_region_cur = cm_reg_start; + reg_region_cur <= cm_reg_end; + reg_region_cur++) { + + const uint16_t *regval0 = &(regval[2 * i]); + const uint16_t *regval1 = &(regval[(2 * i) + 1]); + + REG_SET_2(reg_region_cur, 0, + CM_GAMUT_REMAP_C11, *regval0, + CM_GAMUT_REMAP_C12, *regval1); + + i++; + } + +#undef REG +#define REG(reg)\ + xfm->tf_regs->reg + +} + static void program_gamut_remap( struct dcn10_dpp *xfm, const uint16_t *regval, @@ -145,79 +177,27 @@ static void program_gamut_remap( if (select == GAMUT_REMAP_COEFF) { - REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0, - CM_GAMUT_REMAP_C11, regval[0], - CM_GAMUT_REMAP_C12, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0, - CM_GAMUT_REMAP_C13, regval[0], - CM_GAMUT_REMAP_C14, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0, - CM_GAMUT_REMAP_C21, regval[0], - CM_GAMUT_REMAP_C22, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0, - CM_GAMUT_REMAP_C23, regval[0], - CM_GAMUT_REMAP_C24, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0, - CM_GAMUT_REMAP_C31, regval[0], - CM_GAMUT_REMAP_C32, regval[1]); - regval += 2; - REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0, - CM_GAMUT_REMAP_C33, regval[0], - CM_GAMUT_REMAP_C34, regval[1]); + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_GAMUT_REMAP_C11_C12), + REG(CM_GAMUT_REMAP_C33_C34)); } else if (select == GAMUT_REMAP_COMA_COEFF) { - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); + + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_COMA_C11_C12), + REG(CM_COMA_C33_C34)); } else { - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, regval[0], - CM_COMB_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, regval[0], - CM_COMB_C14, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, regval[0], - CM_COMB_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, regval[0], - CM_COMB_C24, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, regval[0], - CM_COMB_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, regval[0], - CM_COMB_C34, regval[1]); + + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_COMB_C11_C12), + REG(CM_COMB_C33_C34)); } REG_SET( @@ -312,59 +292,20 @@ static void dcn10_dpp_cm_program_color_matrix( } if (mode == 4) { - /*R*/ - REG_SET_2(CM_OCSC_C11_C12, 0, - CM_OCSC_C11, tbl_entry->regval[0], - CM_OCSC_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_OCSC_C13_C14, 0, - CM_OCSC_C13, tbl_entry->regval[2], - CM_OCSC_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_OCSC_C21_C22, 0, - CM_OCSC_C21, tbl_entry->regval[4], - CM_OCSC_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_OCSC_C23_C24, 0, - CM_OCSC_C23, tbl_entry->regval[6], - CM_OCSC_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_OCSC_C31_C32, 0, - CM_OCSC_C31, tbl_entry->regval[8], - CM_OCSC_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_OCSC_C33_C34, 0, - CM_OCSC_C33, tbl_entry->regval[10], - CM_OCSC_C34, tbl_entry->regval[11]); + + dpp_cm_program_color_registers( + xfm, + tbl_entry->regval, + REG(CM_OCSC_C11_C12), + REG(CM_OCSC_C33_C34)); + } else { - /*R*/ - REG_SET_2(CM_COMB_C11_C12, 0, - CM_COMB_C11, tbl_entry->regval[0], - CM_COMB_C12, tbl_entry->regval[1]); - - REG_SET_2(CM_COMB_C13_C14, 0, - CM_COMB_C13, tbl_entry->regval[2], - CM_COMB_C14, tbl_entry->regval[3]); - - /*G*/ - REG_SET_2(CM_COMB_C21_C22, 0, - CM_COMB_C21, tbl_entry->regval[4], - CM_COMB_C22, tbl_entry->regval[5]); - - REG_SET_2(CM_COMB_C23_C24, 0, - CM_COMB_C23, tbl_entry->regval[6], - CM_COMB_C24, tbl_entry->regval[7]); - - /*B*/ - REG_SET_2(CM_COMB_C31_C32, 0, - CM_COMB_C31, tbl_entry->regval[8], - CM_COMB_C32, tbl_entry->regval[9]); - - REG_SET_2(CM_COMB_C33_C34, 0, - CM_COMB_C33, tbl_entry->regval[10], - CM_COMB_C34, tbl_entry->regval[11]); + + dpp_cm_program_color_registers( + xfm, + tbl_entry->regval, + REG(CM_COMB_C11_C12), + REG(CM_COMB_C33_C34)); } } @@ -602,7 +543,7 @@ void ippn10_program_input_csc( struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); int i; int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); - const uint32_t *regval = NULL; + const uint16_t *regval = NULL; uint32_t selection = 1; if (select == INPUT_CSC_SELECT_BYPASS) { @@ -627,59 +568,19 @@ void ippn10_program_input_csc( CM_ICSC_MODE, selection); if (select == INPUT_CSC_SELECT_ICSC) { - /*R*/ - REG_SET_2(CM_ICSC_C11_C12, 0, - CM_ICSC_C11, regval[0], - CM_ICSC_C12, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C13_C14, 0, - CM_ICSC_C13, regval[0], - CM_ICSC_C14, regval[1]); - /*G*/ - regval += 2; - REG_SET_2(CM_ICSC_C21_C22, 0, - CM_ICSC_C21, regval[0], - CM_ICSC_C22, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C23_C24, 0, - CM_ICSC_C23, regval[0], - CM_ICSC_C24, regval[1]); - /*B*/ - regval += 2; - REG_SET_2(CM_ICSC_C31_C32, 0, - CM_ICSC_C31, regval[0], - CM_ICSC_C32, regval[1]); - regval += 2; - REG_SET_2(CM_ICSC_C33_C34, 0, - CM_ICSC_C33, regval[0], - CM_ICSC_C34, regval[1]); + + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_ICSC_C11_C12), + REG(CM_ICSC_C33_C34)); } else { - /*R*/ - REG_SET_2(CM_COMA_C11_C12, 0, - CM_COMA_C11, regval[0], - CM_COMA_C12, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C13_C14, 0, - CM_COMA_C13, regval[0], - CM_COMA_C14, regval[1]); - /*G*/ - regval += 2; - REG_SET_2(CM_COMA_C21_C22, 0, - CM_COMA_C21, regval[0], - CM_COMA_C22, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C23_C24, 0, - CM_COMA_C23, regval[0], - CM_COMA_C24, regval[1]); - /*B*/ - regval += 2; - REG_SET_2(CM_COMA_C31_C32, 0, - CM_COMA_C31, regval[0], - CM_COMA_C32, regval[1]); - regval += 2; - REG_SET_2(CM_COMA_C33_C34, 0, - CM_COMA_C33, regval[0], - CM_COMA_C34, regval[1]); + + dpp_cm_program_color_registers( + xfm, + regval, + REG(CM_COMA_C11_C12), + REG(CM_COMA_C33_C34)); } } -- GitLab From b46c085c238fdfea9b1cc49326dae92a47b34832 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 31 Aug 2017 21:17:05 -0400 Subject: [PATCH 0858/2898] drm/amdgpu: Remove unused flip_flags from amdgpu_crtc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No more need since Andrey's change to use drm_crtc's version Signed-off-by: Harry Wentland Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 8d939e3b3f15..b541ade8a03f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -436,7 +436,6 @@ struct amdgpu_crtc { enum amdgpu_interrupt_state vsync_timer_enabled; int otg_inst; - uint32_t flip_flags; /* After Set Mode stream will be non-NULL */ const struct dc_stream *stream; struct drm_pending_vblank_event *event; -- GitLab From 6f54d0b1d82194116fcb8a3683827c9d8eb8cb9b Mon Sep 17 00:00:00 2001 From: Logatharshan Thothiralingam Date: Fri, 18 Aug 2017 19:09:57 -0400 Subject: [PATCH 0859/2898] drm/amd/display: Get OTG info if OTG master enabled Signed-off-by: Logatharshan Thothiralingam Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 +++++- .../gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 +++ .../gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7ea274475598..4fa856e9a872 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -203,10 +203,14 @@ static void dcn10_log_hw_state(struct dc *dc) for (i = 0; i < pool->pipe_count; i++) { struct timing_generator *tg = pool->timing_generators[i]; - struct dcn_otg_state s; + struct dcn_otg_state s = {0}; tgn10_read_otg_state(DCN10TG_FROM_TG(tg), &s); + //only print if OTG master is enabled + if ((s.otg_enabled & 1) == 0) + continue; + DTN_INFO("[%d]:\t %d \t %d \t %d \t %d \t " "%d \t %d \t %d \t %d \t %d \t %d \t " "%d \t %d \t %d \t %d \t %d \t ", diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 15f1f44e102a..405f595f219a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -1100,6 +1100,9 @@ static bool tgn10_is_stereo_left_eye(struct timing_generator *tg) void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, struct dcn_otg_state *s) { + REG_GET(OTG_CONTROL, + OTG_MASTER_EN, &s->otg_enabled); + REG_GET_2(OTG_V_BLANK_START_END, OTG_V_BLANK_START, &s->v_blank_start, OTG_V_BLANK_END, &s->v_blank_end); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 38d3dcf89d60..69da293e9b4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -370,6 +370,7 @@ struct dcn_otg_state { uint32_t h_sync_a_pol; uint32_t h_total; uint32_t underflow_occurred_status; + uint32_t otg_enabled; }; void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, -- GitLab From 649e0c7679a5189dec1045329e36cfcf41919dc9 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 30 Aug 2017 11:55:40 -0400 Subject: [PATCH 0860/2898] drm/amd/display: Added negative check for vertical line start. In case of vstartup happens before vsync, set vertical line start to 0. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 405f595f219a..2d3dd9a3a196 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -118,7 +118,7 @@ static void tgn10_program_timing( uint32_t start_point = 0; uint32_t field_num = 0; uint32_t h_div_2; - uint32_t vertial_line_start; + int32_t vertical_line_start; struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); @@ -216,9 +216,13 @@ static void tgn10_program_timing( /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, * program the reg for interrupt postition. */ - vertial_line_start = asic_blank_end - tg->dlg_otg_param.vstartup_start + 1; + vertical_line_start = asic_blank_end - tg->dlg_otg_param.vstartup_start + 1; + if (vertical_line_start < 0) { + ASSERT(0); + vertical_line_start = 0; + } REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, - OTG_VERTICAL_INTERRUPT2_LINE_START, vertial_line_start); + OTG_VERTICAL_INTERRUPT2_LINE_START, vertical_line_start); /* v_sync polarity */ v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? -- GitLab From 890db270a5763ccacda8df7cbfac674ade78744a Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 30 Aug 2017 14:29:40 -0400 Subject: [PATCH 0861/2898] drm/amd/display: Remove sanity check. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4fa856e9a872..a6015c2c20c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2828,12 +2828,6 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct timing_generator *tg = pipe_ctx->stream_res.tg; - if (plane_state->ctx->dc->debug.sanity_checks) { - struct dc *dc = plane_state->ctx->dc; - - verify_allow_pstate_change_high(dc->hwseq); - } - if (plane_state == NULL) return; -- GitLab From 78e685f9a385eb984f69720e463878e5c3ae80b7 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 30 Aug 2017 17:49:39 -0400 Subject: [PATCH 0862/2898] drm/amd/display: Use TPS4 instead of CP2520_3 for phy pattern 7 [Description] We originally use TPS4 phy test pattern for test pattern 7. On RV we switched to a new method to use CP2520. CP2520 should produce the same result. However in reality, it fails DP PHY automation test. We use the original method instead. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 527cc0400fd3..1aec586b0367 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1756,7 +1756,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern = DP_TEST_PATTERN_CP2520_2; break; case PHY_TEST_PATTERN_CP2520_3: - test_pattern = DP_TEST_PATTERN_CP2520_3; + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; break; default: test_pattern = DP_TEST_PATTERN_VIDEO_MODE; -- GitLab From 1bb47154408ffa0501bb544580304ce0fdbc4ab6 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Mon, 28 Aug 2017 17:15:34 -0400 Subject: [PATCH 0863/2898] drm/amd/display: Request to have DCN RV pipe Harvesting TODO: Current change only work for sucessive last fused pipe, like p3, or p3,p2. It does not work for fused p1,p2. Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 55 +++++++++++++++---- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index fff86ad0c411..ac6d01ec0505 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1207,13 +1207,23 @@ static struct resource_funcs dcn10_res_pool_funcs = { .add_stream_to_ctx = dcn10_add_stream_to_ctx }; +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0); + /* RV1 support max 4 pipes */ + value = value & 0xf; + return value; +} + static bool construct( uint8_t num_virtual_links, struct dc *dc, struct dcn10_resource_pool *pool) { int i; + int j; struct dc_context *ctx = dc->ctx; + uint32_t pipe_fuses = read_pipe_fuses(ctx); ctx->dc_bios->regs = &bios_regs; @@ -1230,8 +1240,9 @@ static bool construct( *************************************************/ pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - /* TODO: Hardcode to correct number of functional controllers */ - pool->base.pipe_count = 4; + /* max pipe num for ASIC before check pipe fuses */ + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 256; @@ -1355,48 +1366,68 @@ static bool construct( #endif } + /* index to valid pipe resource */ + j = 0; /* mem input -> ipp -> dpp -> opp -> TG */ for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.mis[i] = dcn10_mem_input_create(ctx, i); - if (pool->base.mis[i] == NULL) { + /* if pipe is disabled, skip instance of HW pipe, + * i.e, skip ASIC register instance + */ + if ((pipe_fuses & (1 << i)) != 0) + continue; + + pool->base.mis[j] = dcn10_mem_input_create(ctx, i); + if (pool->base.mis[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); goto mi_create_fail; } - pool->base.ipps[i] = dcn10_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { + pool->base.ipps[j] = dcn10_ipp_create(ctx, i); + if (pool->base.ipps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create input pixel processor!\n"); goto ipp_create_fail; } - pool->base.transforms[i] = dcn10_dpp_create(ctx, i); - if (pool->base.transforms[i] == NULL) { + pool->base.transforms[j] = dcn10_dpp_create(ctx, i); + if (pool->base.transforms[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create dpp!\n"); goto dpp_create_fail; } - pool->base.opps[i] = dcn10_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { + pool->base.opps[j] = dcn10_opp_create(ctx, i); + if (pool->base.opps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create output pixel processor!\n"); goto opp_create_fail; } - pool->base.timing_generators[i] = dcn10_timing_generator_create( + pool->base.timing_generators[j] = dcn10_timing_generator_create( ctx, i); - if (pool->base.timing_generators[i] == NULL) { + if (pool->base.timing_generators[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error("DC: failed to create tg!\n"); goto otg_create_fail; } + /* check next valid pipe */ + j++; } + + /* valid pipe num */ + pool->base.pipe_count = j; + + /* within dml lib, it is hard code to 4. If ASIC pipe is fused, + * the value may be changed + */ + dc->dml.ip.max_num_dpp = pool->base.pipe_count; + dc->dcn_ip->max_num_dpp = pool->base.pipe_count; + pool->base.mpc = dcn10_mpc_create(ctx); if (pool->base.mpc == NULL) { BREAK_TO_DEBUGGER(); -- GitLab From 4451a2551dcac9ea8c90829e0fcc798b834deb6b Mon Sep 17 00:00:00 2001 From: Shirish S Date: Mon, 21 Aug 2017 14:02:17 +0530 Subject: [PATCH 0864/2898] drm/amd/display: dce110: fix plane validation For MPO to work with per surface rendering and flipping, the previous logic of restricting plane[1] only as underlay needs to be removed. validate_surface_sets() now checks only the width and height bounds in case of underlay rather than checking format. Without this patch one cannot set underlay only. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_resource.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 41bfddf9574e..25eda52c32ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -891,21 +891,14 @@ static bool dce110_validate_surface_sets( if (context->stream_status[i].plane_count > 2) return false; - if (context->stream_status[i].plane_states[0]->format - >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + if ((context->stream_status[i].plane_states[i]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) && + (context->stream_status[i].plane_states[i]->src_rect.width > 1920 || + context->stream_status[i].plane_states[i]->src_rect.height > 1080)) return false; - if (context->stream_status[i].plane_count == 2) { - if (context->stream_status[i].plane_states[1]->format - < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return false; - if (context->stream_status[i].plane_states[1]->src_rect.width > 1920 - || context->stream_status[i].plane_states[1]->src_rect.height > 1080) - return false; - - if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) - return false; - } + /* irrespective of plane format, stream should be RGB encoded */ + if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) + return false; } return true; -- GitLab From 8f38b66c82618854d019f9df8ff4cd8dd796da10 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Mon, 11 Sep 2017 16:42:14 -0400 Subject: [PATCH 0865/2898] drm/amd/display: USB-C to HDMI dongle not light RV1 support only USB-C active DP-2-HDMI dongle. HPD short pulse is generated only for DP signal. When processing HPD short pulse, it must be DP active dongle. No need for I2C-Over-AUX detection. v2: Add description Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++--- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 32 ++++++++++++------- drivers/gpu/drm/amd/display/dc/dc.h | 8 ++++- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4c7515d9c811..febfff2225d9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -639,7 +639,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) continue; mutex_lock(&aconnector->hpd_lock); - dc_link_detect(aconnector->dc_link, false); + dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); aconnector->dc_sink = NULL; amdgpu_dm_update_connector_after_detect(aconnector); mutex_unlock(&aconnector->hpd_lock); @@ -855,7 +855,7 @@ static void handle_hpd_irq(void *param) * since (for MST case) MST does this in it's own context. */ mutex_lock(&aconnector->hpd_lock); - if (dc_link_detect(aconnector->dc_link, false)) { + if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -965,7 +965,7 @@ static void handle_hpd_rx_irq(void *param) if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && !is_mst_root_connector) { /* Downstream Port status changed. */ - if (dc_link_detect(aconnector->dc_link, false)) { + if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPDRX)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -1353,7 +1353,8 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_encoder; } - if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true)) + if (dc_link_detect(dc_get_link_at_index(dm->dc, i), + DETECT_REASON_BOOT)) amdgpu_dm_update_connector_after_detect(aconnector); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index cea8dafd2edc..845ec421d861 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -355,7 +355,9 @@ static bool is_dp_sink_present(struct dc_link *link) * @brief * Detect output sink type */ -static enum signal_type link_detect_sink(struct dc_link *link) +static enum signal_type link_detect_sink( + struct dc_link *link, + enum dc_detect_reason reason) { enum signal_type result = get_basic_signal_type( link->link_enc->id, link->link_id); @@ -388,12 +390,17 @@ static enum signal_type link_detect_sink(struct dc_link *link) } break; case CONNECTOR_ID_DISPLAY_PORT: { - - /* Check whether DP signal detected: if not - - * we assume signal is DVI; it could be corrected - * to HDMI after dongle detection */ - if (!is_dp_sink_present(link)) - result = SIGNAL_TYPE_DVI_SINGLE_LINK; + /* DP HPD short pulse. Passive DP dongle will not + * have short pulse + */ + if (reason != DETECT_REASON_HPDRX) { + /* Check whether DP signal detected: if not - + * we assume signal is DVI; it could be corrected + * to HDMI after dongle detection + */ + if (!is_dp_sink_present(link)) + result = SIGNAL_TYPE_DVI_SINGLE_LINK; + } } break; default: @@ -460,9 +467,10 @@ static void detect_dp( struct display_sink_capability *sink_caps, bool *converter_disable_audio, struct audio_support *audio_support, - bool boot) + enum dc_detect_reason reason) { - sink_caps->signal = link_detect_sink(link); + bool boot = false; + sink_caps->signal = link_detect_sink(link, reason); sink_caps->transaction_type = get_ddc_transaction_type(sink_caps->signal); @@ -513,6 +521,8 @@ static void detect_dp( * Need check ->sink usages in case ->sink = NULL * TODO: s3 resume check */ + if (reason == DETECT_REASON_BOOT) + boot = true; if (dm_helpers_dp_mst_start_top_mgr( link->ctx, @@ -531,7 +541,7 @@ static void detect_dp( } } -bool dc_link_detect(struct dc_link *link, bool boot) +bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) { struct dc_sink_init_data sink_init_data = { 0 }; struct display_sink_capability sink_caps = { 0 }; @@ -596,7 +606,7 @@ bool dc_link_detect(struct dc_link *link, bool boot) link, &sink_caps, &converter_disable_audio, - aud_support, boot); + aud_support, reason); /* Active dongle downstream unplug */ if (link->type == dc_connection_active_dongle diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2316a6060b2c..1f0521ff4614 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -885,7 +885,13 @@ bool dc_link_setup_psr(struct dc_link *dc_link, * true otherwise. True meaning further action is required (status update * and OS notification). */ -bool dc_link_detect(struct dc_link *dc_link, bool boot); +enum dc_detect_reason { + DETECT_REASON_BOOT, + DETECT_REASON_HPD, + DETECT_REASON_HPDRX, +}; + +bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason); /* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). * Return: -- GitLab From acea7183b5d72d0713d2129956e7357ebde28054 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 31 Aug 2017 16:49:56 -0400 Subject: [PATCH 0866/2898] drm/amd/display: set CP2520 Test pattern to use DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 1aec586b0367..38ccc011004d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1750,7 +1750,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; break; case PHY_TEST_PATTERN_CP2520_1: - test_pattern = DP_TEST_PATTERN_CP2520_1; + test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; break; case PHY_TEST_PATTERN_CP2520_2: test_pattern = DP_TEST_PATTERN_CP2520_2; -- GitLab From 1b7441b00a986cbed017a13ccf316efb54ab7a4b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 1 Sep 2017 12:51:47 -0400 Subject: [PATCH 0867/2898] drm/amd/display: fix crc_source_select use hardcoded color depth Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9fb0ba7e7b7d..47e8b582445e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -667,7 +667,25 @@ static enum dc_status bios_parser_crtc_source_select( crtc_source_select.signal = pipe_ctx->stream->signal; crtc_source_select.enable_dp_audio = false; crtc_source_select.sink_signal = pipe_ctx->stream->signal; - crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; + + switch (pipe_ctx->stream->timing.display_color_depth) { + case COLOR_DEPTH_666: + crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR; + break; + case COLOR_DEPTH_888: + crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; + break; + case COLOR_DEPTH_101010: + crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR; + break; + case COLOR_DEPTH_121212: + crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR; + break; + default: + BREAK_TO_DEBUGGER(); + crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR; + break; + } dcb = sink->ctx->dc_bios; -- GitLab From 61a44fc6265dd3bb86c35bcdfb62a225891ada59 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 31 Aug 2017 16:08:51 -0400 Subject: [PATCH 0868/2898] drm/amd/display: Enable dcn10_power_on_fe log by default This should only happen on full update. If this ever happens on regular pageflips it needs to be debugged. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a6015c2c20c6..6b76fc417456 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1975,7 +1975,7 @@ static void dcn10_power_on_fe( /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/ if (plane_state) { - dm_logger_write(dc->ctx->logger, LOG_DEBUG, + dm_logger_write(dc->ctx->logger, LOG_DC, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " "src: %d, %d, %d," @@ -1993,7 +1993,7 @@ static void dcn10_power_on_fe( plane_state->dst_rect.width, plane_state->dst_rect.height); - dm_logger_write(dc->ctx->logger, LOG_DEBUG, + dm_logger_write(dc->ctx->logger, LOG_DC, "Pipe %d: width, height, x, y\n" "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", -- GitLab From 603767f903bf5bf301728b197dcde63cf880fe2e Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Fri, 1 Sep 2017 16:14:01 -0400 Subject: [PATCH 0869/2898] drm/amd/display: fix default dithering bug: default is mapped to no dithering. default to spatial dithering based on color depth Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 20 +++---------------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 16 +++++++++++++++ .../display/dc/dce110/dce110_hw_sequencer.c | 14 +++++-------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ab6ad946231e..d5320f7162b4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -341,23 +341,9 @@ void set_dither_option(struct dc_stream_state *stream, return; if (option > DITHER_OPTION_MAX) return; - if (option == DITHER_OPTION_DEFAULT) { - switch (stream->timing.display_color_depth) { - case COLOR_DEPTH_666: - stream->dither_option = DITHER_OPTION_SPATIAL6; - break; - case COLOR_DEPTH_888: - stream->dither_option = DITHER_OPTION_SPATIAL8; - break; - case COLOR_DEPTH_101010: - stream->dither_option = DITHER_OPTION_SPATIAL10; - break; - default: - option = DITHER_OPTION_DISABLE; - } - } else { - stream->dither_option = option; - } + + stream->dither_option = option; + resource_build_bit_depth_reduction_params(stream, ¶ms); stream->bit_depth_params = params; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fbf7747424a9..ce721b77c1bc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2607,6 +2607,22 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); + if (option == DITHER_OPTION_DEFAULT) { + switch (stream->timing.display_color_depth) { + case COLOR_DEPTH_666: + option = DITHER_OPTION_SPATIAL6; + break; + case COLOR_DEPTH_888: + option = DITHER_OPTION_SPATIAL8; + break; + case COLOR_DEPTH_101010: + option = DITHER_OPTION_SPATIAL10; + break; + default: + option = DITHER_OPTION_DISABLE; + } + } + if (option == DITHER_OPTION_DISABLE) return; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 47e8b582445e..b36220bc619d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1104,15 +1104,11 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); -/*vbios crtc_source_selection and encoder_setup will override fmt_C*/ - if (pipe_ctx->stream->signal != SIGNAL_TYPE_EDP && - pipe_ctx->stream->signal != SIGNAL_TYPE_LVDS) { - /*for embedded panel, don't override VBIOS's setting*/ - pipe_ctx->stream_res.opp->funcs->opp_program_fmt( - pipe_ctx->stream_res.opp, - &stream->bit_depth_params, - &stream->clamping); - } + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp, + &stream->bit_depth_params, + &stream->clamping); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_res.stream_enc, -- GitLab From aeff7ab11e2516bfa41c77b9ea57bc2c07bb3b62 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Fri, 1 Sep 2017 16:03:16 -0400 Subject: [PATCH 0870/2898] drm/amd/display: Fix context alloc failed logging Since there was no return statement in the fail block immediately preceding the context_alloc_fail block, any failure within the function caused a context alloc failed error message to be printed. Since the context_alloc_fail block is only used once, move it to where the goto is directly and accompany it with a return statement. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d5320f7162b4..5579d2167a9a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1279,8 +1279,10 @@ void dc_update_planes_and_stream(struct dc *dc, /* initialize scratch memory for building context */ context = dc_create_state(); - if (context == NULL) - goto context_alloc_fail; + if (context == NULL) { + DC_ERROR("Failed to allocate new validate context!\n"); + return; + } dc_resource_state_copy_construct( dc->current_state, context); @@ -1534,9 +1536,6 @@ void dc_update_planes_and_stream(struct dc *dc, fail: dc_release_state(context); - -context_alloc_fail: - DC_ERROR("Failed to allocate new validate context!\n"); } uint8_t dc_get_current_stream_count(struct dc *dc) -- GitLab From 83524646611381c4b0e31ffc5286cb05f8818aba Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 29 Aug 2017 16:54:39 -0400 Subject: [PATCH 0871/2898] drm/amd/display: seperate dpp_cm_helper functions into new file Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 2 + .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 259 +++++++----------- .../display/dc/dcn10/dcn10_dpp_cm_helper.c | 123 +++++++++ .../display/dc/dcn10/dcn10_dpp_cm_helper.h | 99 +++++++ 5 files changed, 330 insertions(+), 155 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 52b56d19ca40..e92ac2997a1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -4,7 +4,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \ - dcn10_dpp_dscl.o dcn10_dpp_cm.o + dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 4bbd3b4f7ae6..70d6ba09501b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1262,6 +1262,8 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; + + enum dcn10_input_csc_select { INPUT_CSC_SELECT_BYPASS = 0, INPUT_CSC_SELECT_ICSC, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index d698fccdef68..840dd0346782 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -29,6 +29,7 @@ #include "reg_helper.h" #include "dcn10_dpp.h" +#include "dcn10_dpp_cm_helper.h" #include "basics/conversion.h" #define NUM_PHASES 64 @@ -116,37 +117,7 @@ static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { 0x2568, 0x43ee, 0xdbb2} } }; -static void dpp_cm_program_color_registers( - struct dcn10_dpp *xfm, - const uint16_t *regval, - uint32_t cm_reg_start, - uint32_t cm_reg_end) -{ - uint32_t reg_region_cur; - unsigned int i = 0; - -#undef REG -#define REG(reg) reg - - for (reg_region_cur = cm_reg_start; - reg_region_cur <= cm_reg_end; - reg_region_cur++) { - - const uint16_t *regval0 = &(regval[2 * i]); - const uint16_t *regval1 = &(regval[(2 * i) + 1]); - REG_SET_2(reg_region_cur, 0, - CM_GAMUT_REMAP_C11, *regval0, - CM_GAMUT_REMAP_C12, *regval1); - - i++; - } - -#undef REG -#define REG(reg)\ - xfm->tf_regs->reg - -} static void program_gamut_remap( struct dcn10_dpp *xfm, @@ -154,6 +125,7 @@ static void program_gamut_remap( enum gamut_remap_select select) { uint16_t selection = 0; + struct color_matrices_reg gam_regs; if (regval == NULL || select == GAMUT_REMAP_BYPASS) { REG_SET(CM_GAMUT_REMAP_CONTROL, 0, @@ -174,30 +146,40 @@ static void program_gamut_remap( break; } + gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_GAMUT_REMAP_C11; + gam_regs.masks.csc_c11 = xfm->tf_mask->CM_GAMUT_REMAP_C11; + gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_GAMUT_REMAP_C12; + gam_regs.masks.csc_c12 = xfm->tf_mask->CM_GAMUT_REMAP_C12; + if (select == GAMUT_REMAP_COEFF) { + gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34); - dpp_cm_program_color_registers( - xfm, + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_GAMUT_REMAP_C11_C12), - REG(CM_GAMUT_REMAP_C33_C34)); + &gam_regs); } else if (select == GAMUT_REMAP_COMA_COEFF) { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_COMA_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_COMA_C11_C12), - REG(CM_COMA_C33_C34)); + &gam_regs); } else { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_COMB_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_COMB_C11_C12), - REG(CM_COMB_C33_C34)); + &gam_regs); } REG_SET( @@ -278,11 +260,39 @@ void dcn10_dpp_cm_set_output_csc_default( } +static void dcn10_dpp_cm_get_reg_field( + struct dcn10_dpp *xfm, + struct xfer_func_reg *reg) +{ + reg->shifts.exp_region0_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->masks.field_region_end = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->masks.field_region_linear_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->shifts.exp_region_start = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->masks.exp_region_start = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; +} + static void dcn10_dpp_cm_program_color_matrix( struct dcn10_dpp *xfm, const struct out_csc_color_matrix *tbl_entry) { uint32_t mode; + struct color_matrices_reg gam_regs; REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode); @@ -291,21 +301,30 @@ static void dcn10_dpp_cm_program_color_matrix( return; } + gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_OCSC_C11; + gam_regs.masks.csc_c11 = xfm->tf_mask->CM_OCSC_C11; + gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_OCSC_C12; + gam_regs.masks.csc_c12 = xfm->tf_mask->CM_OCSC_C12; + if (mode == 4) { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_OCSC_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_OCSC_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, tbl_entry->regval, - REG(CM_OCSC_C11_C12), - REG(CM_OCSC_C33_C34)); + &gam_regs); } else { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_COMB_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, tbl_entry->regval, - REG(CM_COMB_C11_C12), - REG(CM_COMB_C33_C34)); + &gam_regs); } } @@ -394,101 +413,15 @@ void dcn10_dpp_cm_configure_regamma_lut( REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0); } -struct cm_gam_ram_reg { - uint32_t start_cntl_b; - uint32_t start_cntl_g; - uint32_t start_cntl_r; - uint32_t start_slope_cntl_b; - uint32_t start_slope_cntl_g; - uint32_t start_slope_cntl_r; - uint32_t start_end_cntl1_b; - uint32_t start_end_cntl2_b; - uint32_t start_end_cntl1_g; - uint32_t start_end_cntl2_g; - uint32_t start_end_cntl1_r; - uint32_t start_end_cntl2_r; - uint32_t region_start; - uint32_t region_end; -}; - -static void dpp_cm_program_region_lut( - struct transform *xfm_base, - const struct pwl_params *params, - const struct cm_gam_ram_reg *reg) -{ - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - uint32_t reg_region_cur; - unsigned int i = 0; - -#undef REG -#define REG(reg) reg - - REG_SET_2(reg->start_cntl_b, 0, - CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0); - REG_SET_2(reg->start_cntl_g, 0, - CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0); - REG_SET_2(reg->start_cntl_r, 0, - CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x, - CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0); - - REG_SET(reg->start_slope_cntl_b, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope); - REG_SET(reg->start_slope_cntl_g, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope); - REG_SET(reg->start_slope_cntl_r, 0, - CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope); - - REG_SET(reg->start_end_cntl1_b, 0, - CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_b, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y); - - REG_SET(reg->start_end_cntl1_g, 0, - CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_g, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y); - - REG_SET(reg->start_end_cntl1_r, 0, - CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x); - REG_SET_2(reg->start_end_cntl2_r, 0, - CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope, - CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y); - - for (reg_region_cur = reg->region_start; - reg_region_cur <= reg->region_end; - reg_region_cur++) { - - const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); - const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); - - REG_SET_4(reg_region_cur, 0, - CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve0->offset, - CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve0->segments_num, - CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve1->offset, - CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve1->segments_num); - - i++; - } - -#undef REG -#define REG(reg)\ - xfm->tf_regs->reg - -} - - - /*program re gamma RAM A*/ void dcn10_dpp_cm_program_regamma_luta_settings( struct transform *xfm_base, const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - struct cm_gam_ram_reg gam_regs; + struct xfer_func_reg gam_regs; + + dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMA_START_CNTL_G); @@ -505,7 +438,7 @@ void dcn10_dpp_cm_program_regamma_luta_settings( gam_regs.region_start = REG(CM_RGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMA_REGION_32_33); - dpp_cm_program_region_lut(xfm_base, params, &gam_regs); + cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); } @@ -515,7 +448,9 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - struct cm_gam_ram_reg gam_regs; + struct xfer_func_reg gam_regs; + + dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMB_START_CNTL_G); @@ -532,7 +467,7 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( gam_regs.region_start = REG(CM_RGAM_RAMB_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMB_REGION_32_33); - dpp_cm_program_region_lut(xfm_base, params, &gam_regs); + cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); } void ippn10_program_input_csc( @@ -545,6 +480,7 @@ void ippn10_program_input_csc( int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); const uint16_t *regval = NULL; uint32_t selection = 1; + struct color_matrices_reg gam_regs; if (select == INPUT_CSC_SELECT_BYPASS) { REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0); @@ -567,20 +503,30 @@ void ippn10_program_input_csc( REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, selection); + gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_ICSC_C11; + gam_regs.masks.csc_c11 = xfm->tf_mask->CM_ICSC_C11; + gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_ICSC_C12; + gam_regs.masks.csc_c12 = xfm->tf_mask->CM_ICSC_C12; + + if (select == INPUT_CSC_SELECT_ICSC) { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_ICSC_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_ICSC_C11_C12), - REG(CM_ICSC_C33_C34)); + &gam_regs); } else { - dpp_cm_program_color_registers( - xfm, + gam_regs.csc_c11_c12 = REG(CM_COMA_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); + + cm_helper_program_color_matrices( + xfm->base.ctx, regval, - REG(CM_COMA_C11_C12), - REG(CM_COMA_C33_C34)); + &gam_regs); } } @@ -590,7 +536,9 @@ void ippn10_program_degamma_lutb_settings( const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - struct cm_gam_ram_reg gam_regs; + struct xfer_func_reg gam_regs; + + dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G); @@ -607,7 +555,8 @@ void ippn10_program_degamma_lutb_settings( gam_regs.region_start = REG(CM_DGAM_RAMB_REGION_0_1); gam_regs.region_end = REG(CM_DGAM_RAMB_REGION_14_15); - dpp_cm_program_region_lut(xfm_base, params, &gam_regs); + + cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); } /*program de gamma RAM A*/ @@ -616,7 +565,9 @@ void ippn10_program_degamma_luta_settings( const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - struct cm_gam_ram_reg gam_regs; + struct xfer_func_reg gam_regs; + + dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G); @@ -633,7 +584,7 @@ void ippn10_program_degamma_luta_settings( gam_regs.region_start = REG(CM_DGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_DGAM_RAMA_REGION_14_15); - dpp_cm_program_region_lut(xfm_base, params, &gam_regs); + cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); } void ippn10_power_on_degamma_lut( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c new file mode 100644 index 000000000000..f616e08759de --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c @@ -0,0 +1,123 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "reg_helper.h" +#include "dcn10_dpp.h" + +#include "dcn10_dpp_cm_helper.h" + +#define REG(reg) reg + +#define CTX \ + ctx + +#undef FN +#define FN(reg_name, field_name) \ + reg->shifts.field_name, reg->masks.field_name + +void cm_helper_program_color_matrices( + struct dc_context *ctx, + const uint16_t *regval, + const struct color_matrices_reg *reg) +{ + uint32_t cur_csc_reg; + unsigned int i = 0; + + for (cur_csc_reg = reg->csc_c11_c12; + cur_csc_reg <= reg->csc_c33_c34; + cur_csc_reg++) { + + const uint16_t *regval0 = &(regval[2 * i]); + const uint16_t *regval1 = &(regval[(2 * i) + 1]); + + REG_SET_2(cur_csc_reg, 0, + csc_c11, *regval0, + csc_c12, *regval1); + + i++; + } + +} + +void cm_helper_program_xfer_func( + struct dc_context *ctx, + const struct pwl_params *params, + const struct xfer_func_reg *reg) +{ + uint32_t reg_region_cur; + unsigned int i = 0; + + REG_SET_2(reg->start_cntl_b, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + REG_SET_2(reg->start_cntl_g, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + REG_SET_2(reg->start_cntl_r, 0, + exp_region_start, params->arr_points[0].custom_float_x, + exp_resion_start_segment, 0); + + REG_SET(reg->start_slope_cntl_b, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + REG_SET(reg->start_slope_cntl_g, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + REG_SET(reg->start_slope_cntl_r, 0, + field_region_linear_slope, params->arr_points[0].custom_float_slope); + + REG_SET(reg->start_end_cntl1_b, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_b, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + REG_SET(reg->start_end_cntl1_g, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_g, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + REG_SET(reg->start_end_cntl1_r, 0, + field_region_end, params->arr_points[1].custom_float_x); + REG_SET_2(reg->start_end_cntl2_r, 0, + field_region_end_slope, params->arr_points[1].custom_float_slope, + field_region_end_base, params->arr_points[1].custom_float_y); + + for (reg_region_cur = reg->region_start; + reg_region_cur <= reg->region_end; + reg_region_cur++) { + + const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); + const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); + + REG_SET_4(reg_region_cur, 0, + exp_region0_lut_offset, curve0->offset, + exp_region0_num_segments, curve0->segments_num, + exp_region1_lut_offset, curve1->offset, + exp_region1_num_segments, curve1->segments_num); + + i++; + } + +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h new file mode 100644 index 000000000000..1155ee522898 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h @@ -0,0 +1,99 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_DPP_DCN10_CM_HELPER_H__ +#define __DAL_DPP_DCN10_CM_HELPER_H__ + +#define TF_HELPER_REG_FIELD_LIST(type) \ + type exp_region0_lut_offset; \ + type exp_region0_num_segments; \ + type exp_region1_lut_offset; \ + type exp_region1_num_segments;\ + type field_region_end;\ + type field_region_end_slope;\ + type field_region_end_base;\ + type exp_region_start;\ + type exp_resion_start_segment;\ + type field_region_linear_slope + +#define TF_CM_REG_FIELD_LIST(type) \ + type csc_c11; \ + type csc_c12 + +struct xfer_func_shift { + TF_HELPER_REG_FIELD_LIST(uint8_t); +}; + +struct xfer_func_mask { + TF_HELPER_REG_FIELD_LIST(uint32_t); +}; + +struct xfer_func_reg { + struct xfer_func_shift shifts; + struct xfer_func_mask masks; + + uint32_t start_cntl_b; + uint32_t start_cntl_g; + uint32_t start_cntl_r; + uint32_t start_slope_cntl_b; + uint32_t start_slope_cntl_g; + uint32_t start_slope_cntl_r; + uint32_t start_end_cntl1_b; + uint32_t start_end_cntl2_b; + uint32_t start_end_cntl1_g; + uint32_t start_end_cntl2_g; + uint32_t start_end_cntl1_r; + uint32_t start_end_cntl2_r; + uint32_t region_start; + uint32_t region_end; +}; + +struct cm_color_matrix_shift { + TF_CM_REG_FIELD_LIST(uint8_t); +}; + +struct cm_color_matrix_mask { + TF_CM_REG_FIELD_LIST(uint32_t); +}; + +struct color_matrices_reg{ + struct cm_color_matrix_shift shifts; + struct cm_color_matrix_mask masks; + + uint32_t csc_c11_c12; + uint32_t csc_c33_c34; +}; + +void cm_helper_program_color_matrices( + struct dc_context *ctx, + const uint16_t *regval, + const struct color_matrices_reg *reg); + +void cm_helper_program_xfer_func( + struct dc_context *ctx, + const struct pwl_params *params, + const struct xfer_func_reg *reg); + +#endif -- GitLab From 4a6295361c737a80e9f079952ac863a3b0c26acf Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 28 Aug 2017 18:43:45 -0400 Subject: [PATCH 0872/2898] drm/amd/display: Don't reset clock source at unref Powering down the clock source during unref is unsafe as we might want to unref during atomic_check Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 25 ++++++++++++------- .../display/dc/dce110/dce110_hw_sequencer.c | 16 ++++++++---- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 9 ++++--- drivers/gpu/drm/amd/display/dc/inc/resource.h | 4 +-- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ce721b77c1bc..57c3dcd3fadd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -261,31 +261,34 @@ bool resource_construct( } -void resource_unreference_clock_source( +bool resource_unreference_clock_source( struct resource_context *res_ctx, const struct resource_pool *pool, - struct clock_source **clock_source) + struct clock_source *clock_source) { int i; + bool need_reset = false; + for (i = 0; i < pool->clk_src_count; i++) { - if (pool->clock_sources[i] != *clock_source) + if (pool->clock_sources[i] != clock_source) continue; res_ctx->clock_source_ref_count[i]--; if (res_ctx->clock_source_ref_count[i] == 0) - (*clock_source)->funcs->cs_power_down(*clock_source); + need_reset = true; break; } - if (pool->dp_clock_source == *clock_source) { + if (pool->dp_clock_source == clock_source) { res_ctx->dp_clock_source_ref_count--; if (res_ctx->dp_clock_source_ref_count == 0) - (*clock_source)->funcs->cs_power_down(*clock_source); + need_reset = true; } - *clock_source = NULL; + + return need_reset; } void resource_reference_clock_source( @@ -1756,10 +1759,14 @@ bool dc_validate_global_state( if (dc_is_dp_signal(pipe_ctx->stream->signal) && !find_pll_sharable_stream(stream, new_ctx)) { - resource_unreference_clock_source( + if (resource_unreference_clock_source( &new_ctx->res_ctx, dc->res_pool, - &pipe_ctx->clock_source); + pipe_ctx->clock_source)) { + pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); + pipe_ctx->clock_source = NULL; + } + pipe_ctx->clock_source = dc->res_pool->dp_clock_source; resource_reference_clock_source( &new_ctx->res_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b36220bc619d..75c636cba545 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1362,9 +1362,12 @@ static void switch_dp_clock_sources( if (clk_src && clk_src != pipe_ctx->clock_source) { - resource_unreference_clock_source( - res_ctx, dc->res_pool, - &pipe_ctx->clock_source); + if (resource_unreference_clock_source(res_ctx, + dc->res_pool, pipe_ctx->clock_source)) { + pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); + pipe_ctx->clock_source = NULL; + } + pipe_ctx->clock_source = clk_src; resource_reference_clock_source( res_ctx, dc->res_pool, clk_src); @@ -1680,9 +1683,12 @@ static void dce110_reset_hw_ctx_wrap( pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); - resource_unreference_clock_source( + if (resource_unreference_clock_source( &dc->current_state->res_ctx, dc->res_pool, - &pipe_ctx_old->clock_source); + pipe_ctx_old->clock_source)) { + pipe_ctx_old->clock_source->funcs->cs_power_down(pipe_ctx_old->clock_source); + pipe_ctx_old->clock_source = NULL; + } dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6b76fc417456..7460560fbefc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1045,9 +1045,12 @@ static void reset_back_end_for_pipe( } if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - resource_unreference_clock_source( - &context->res_ctx, dc->res_pool, - &pipe_ctx->clock_source); + if (resource_unreference_clock_source(&context->res_ctx, + dc->res_pool, pipe_ctx->clock_source)) { + pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); + pipe_ctx->clock_source = NULL; + } + for (i = 0; i < dc->res_pool->pipe_count; i++) if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 41437da5fb9b..cf1797c191e9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -92,10 +92,10 @@ enum dc_status resource_build_scaling_params_for_context( void resource_build_info_frame(struct pipe_ctx *pipe_ctx); -void resource_unreference_clock_source( +bool resource_unreference_clock_source( struct resource_context *res_ctx, const struct resource_pool *pool, - struct clock_source **clock_source); + struct clock_source *clock_source); void resource_reference_clock_source( struct resource_context *res_ctx, -- GitLab From 9d0dcecd93e4997c65b18404f1ab2fce2ab79010 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 28 Aug 2017 19:05:17 -0400 Subject: [PATCH 0873/2898] drm/amd/display: Power down clock source at commit Still one more in dc_validate_global Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 19 +++++++++------ .../display/dc/dce110/dce110_hw_sequencer.c | 22 ++++++++++++----- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 24 ++++++++++++------- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 ++ 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 57c3dcd3fadd..9aa0da743174 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -275,8 +275,10 @@ bool resource_unreference_clock_source( res_ctx->clock_source_ref_count[i]--; - if (res_ctx->clock_source_ref_count[i] == 0) + if (res_ctx->clock_source_ref_count[i] == 0) { + res_ctx->clock_source_changed[i] = true; need_reset = true; + } break; } @@ -284,8 +286,10 @@ bool resource_unreference_clock_source( if (pool->dp_clock_source == clock_source) { res_ctx->dp_clock_source_ref_count--; - if (res_ctx->dp_clock_source_ref_count == 0) + if (res_ctx->dp_clock_source_ref_count == 0) { + res_ctx->dp_clock_source_changed = true; need_reset = true; + } } return need_reset; @@ -1502,6 +1506,10 @@ bool dc_remove_stream_from_ctx( del_pipe->stream_res.audio, false); + resource_unreference_clock_source(&new_ctx->res_ctx, + dc->res_pool, + del_pipe->clock_source); + memset(del_pipe, 0, sizeof(*del_pipe)); break; @@ -1759,13 +1767,10 @@ bool dc_validate_global_state( if (dc_is_dp_signal(pipe_ctx->stream->signal) && !find_pll_sharable_stream(stream, new_ctx)) { - if (resource_unreference_clock_source( + resource_unreference_clock_source( &new_ctx->res_ctx, dc->res_pool, - pipe_ctx->clock_source)) { - pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); - pipe_ctx->clock_source = NULL; - } + pipe_ctx->clock_source); pipe_ctx->clock_source = dc->res_pool->dp_clock_source; resource_reference_clock_source( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 75c636cba545..96db166b7fba 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1683,18 +1683,28 @@ static void dce110_reset_hw_ctx_wrap( pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg); pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); - if (resource_unreference_clock_source( - &dc->current_state->res_ctx, dc->res_pool, - pipe_ctx_old->clock_source)) { - pipe_ctx_old->clock_source->funcs->cs_power_down(pipe_ctx_old->clock_source); - pipe_ctx_old->clock_source = NULL; - } dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); pipe_ctx_old->stream = NULL; } } + + /* power down changed clock sources */ + for (i = 0; i < dc->res_pool->clk_src_count; i++) + if (context->res_ctx.clock_source_changed[i]) { + struct clock_source *clk = dc->res_pool->clock_sources[i]; + + clk->funcs->cs_power_down(clk); + context->res_ctx.clock_source_changed[i] = false; + } + + if (context->res_ctx.dp_clock_source_changed) { + struct clock_source *clk = dc->res_pool->dp_clock_source; + + clk->funcs->cs_power_down(clk); + context->res_ctx.clock_source_changed[i] = false; + } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 7460560fbefc..a1f4a00e5e04 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1044,14 +1044,6 @@ static void reset_back_end_for_pipe( pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); } - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - if (resource_unreference_clock_source(&context->res_ctx, - dc->res_pool, pipe_ctx->clock_source)) { - pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); - pipe_ctx->clock_source = NULL; - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx) break; @@ -1273,6 +1265,22 @@ static void reset_hw_ctx_wrap( plane_atomic_power_down(dc, i); } + /* power down changed clock sources */ + for (i = 0; i < dc->res_pool->clk_src_count; i++) + if (context->res_ctx.clock_source_changed[i]) { + struct clock_source *clk = dc->res_pool->clock_sources[i]; + + clk->funcs->cs_power_down(clk); + context->res_ctx.clock_source_changed[i] = false; + } + + if (context->res_ctx.dp_clock_source_changed) { + struct clock_source *clk = dc->res_pool->dp_clock_source; + + clk->funcs->cs_power_down(clk); + context->res_ctx.dp_clock_source_changed = false; + } + /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 915d5c10361b..b6a513d6feda 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -213,7 +213,9 @@ struct resource_context { bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; + bool clock_source_changed[MAX_CLOCK_SOURCES]; uint8_t dp_clock_source_ref_count; + bool dp_clock_source_changed; }; struct dce_bw_output { -- GitLab From b8ea60cea245e8cd68b6ac45b9680a590f76391a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 28 Aug 2017 19:44:38 -0400 Subject: [PATCH 0874/2898] drm/amd/display: Remove switching of clk sources at end of commit This should be taken care of in validate now. All of timing sync is quite broken at the moment anyways. Will submit another patch set to address that. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 96db166b7fba..c57dc45d6677 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1344,40 +1344,6 @@ static void set_safe_displaymarks( } } -static void switch_dp_clock_sources( - const struct dc *dc, - struct resource_context *res_ctx) -{ - uint8_t i; - for (i = 0; i < MAX_PIPES; i++) { - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - - if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe) - continue; - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) { - struct clock_source *clk_src = - resource_find_used_clk_src_for_sharing( - res_ctx, pipe_ctx); - - if (clk_src && - clk_src != pipe_ctx->clock_source) { - if (resource_unreference_clock_source(res_ctx, - dc->res_pool, pipe_ctx->clock_source)) { - pipe_ctx->clock_source->funcs->cs_power_down(pipe_ctx->clock_source); - pipe_ctx->clock_source = NULL; - } - - pipe_ctx->clock_source = clk_src; - resource_reference_clock_source( - res_ctx, dc->res_pool, clk_src); - - dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i); - } - } - } -} - /******************************************************************************* * Public functions ******************************************************************************/ @@ -1939,8 +1905,6 @@ enum dc_status dce110_apply_ctx_to_hw( dcb->funcs->set_scratch_critical_state(dcb, false); - switch_dp_clock_sources(dc, &context->res_ctx); - #ifdef ENABLE_FBC if (dc->fbc_compressor) enable_fbc(dc, context); -- GitLab From 264efa31835dd87af4e77e3a27090e60d4fe1511 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Thu, 31 Aug 2017 16:04:24 -0400 Subject: [PATCH 0875/2898] drm/amd/display: remove output_format from ipp_setup Signed-off-by: Eric Bernstein Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 3 +-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 3 +-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 +-- drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h | 3 +-- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 3 +-- 6 files changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 99caafb27b37..487694125ea4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -266,8 +266,7 @@ static void ippn10_set_degamma_format_float( void ippn10_cnv_setup ( struct transform *xfm_base, enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format cnv_out_format) + enum expansion_mode mode) { uint32_t pixel_format; uint32_t alpha_en; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 70d6ba09501b..34e501979b55 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1358,8 +1358,7 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( void ippn10_cnv_setup ( struct transform *xfm_base, enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format cnv_out_format); + enum expansion_mode mode); void ippn10_full_bypass(struct transform *xfm_base); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 840dd0346782..d0e72acfc1d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -727,11 +727,11 @@ void ippn10_full_bypass(struct transform *xfm_base) FORMAT_EXPANSION_MODE, 0); /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ - REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); + if (xfm->tf_mask->CM_BYPASS_EN) + REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); /* Setting degamma bypass for now */ REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); - REG_SET(CM_IGAM_CONTROL, 0, CM_IGAM_LUT_MODE, 0); } static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a1f4a00e5e04..6fee6957c1a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2316,8 +2316,7 @@ static void update_dchubp_dpp( xfm->funcs->ipp_setup(xfm, plane_state->format, - 1, - IPP_OUTPUT_FORMAT_12_BIT_FIX); + EXPANSION_MODE_ZERO); mpcc_cfg.mi = mi; mpcc_cfg.opp = pipe_ctx->stream_res.opp; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h index 7ebfdc1c19c1..f11aa484f46e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h @@ -86,8 +86,7 @@ struct ipp_funcs { void (*ipp_setup)( struct input_pixel_processor *ipp, enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format output_format); + enum expansion_mode mode); /* DCE function to setup IPP. TODO: see if we can consolidate to setup */ void (*ipp_program_prescale)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 623042d2c272..32947450e702 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -234,8 +234,7 @@ struct transform_funcs { void (*ipp_setup)( struct transform *xfm_base, enum surface_pixel_format input_format, - enum expansion_mode mode, - enum ipp_output_format cnv_out_format); + enum expansion_mode mode); void (*ipp_full_bypass)(struct transform *xfm_base); -- GitLab From e74c6972f85d48de4d2fe797ddd0fbc8bd899f0e Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 5 Sep 2017 11:50:34 -0400 Subject: [PATCH 0876/2898] drm/amd/display: move dwb registers to header file Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c | 288 +----------------- .../gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h | 247 ++++++++++++++- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 42 +++ 3 files changed, 289 insertions(+), 288 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c index 684241cb40d7..4ec5554f0f5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c @@ -29,32 +29,7 @@ #include "resource.h" #include "dwb.h" #include "dcn10_dwb.h" -#include "vega10/soc15ip.h" -#include "raven1/DCN/dcn_1_0_offset.h" -#include "raven1/DCN/dcn_1_0_sh_mask.h" -/* DCN */ -#define BASE_INNER(seg) \ - DCE_BASE__INST0_SEG ## seg - -#define BASE(seg) \ - BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix #define REG(reg)\ dwbc10->dwbc_regs->reg @@ -69,240 +44,6 @@ #define TO_DCN10_DWBC(dwbc_base) \ container_of(dwbc_base, struct dcn10_dwbc, base) -#define DWBC_COMMON_REG_LIST_DCN1_0(inst) \ - SRI(WB_ENABLE, CNV, inst),\ - SRI(WB_EC_CONFIG, CNV, inst),\ - SRI(CNV_MODE, CNV, inst),\ - SRI(WB_SOFT_RESET, CNV, inst),\ - SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ - SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MCIF_WB, inst),\ - SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_WATERMARK, MCIF_WB, inst),\ - SRI(MCIF_WB_WARM_UP_CNTL, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ - .DWB_SOURCE_SELECT = mmDWB_SOURCE_SELECT\ - -#define DWBC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh) \ - SF(CNV0_WB_ENABLE, WB_ENABLE, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_TYPE, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_EYE_SELECTION, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_NEW_CONTENT, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\ - SF(CNV0_WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_DUALSIZE_REQ, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) - -#define DWBC_REG_FIELD_LIST(type) \ - type WB_ENABLE;\ - type DISPCLK_R_WB_GATE_DIS;\ - type DISPCLK_G_WB_GATE_DIS;\ - type DISPCLK_G_WBSCL_GATE_DIS;\ - type WB_LB_LS_DIS;\ - type WB_LB_SD_DIS;\ - type WB_LUT_LS_DIS;\ - type CNV_WINDOW_CROP_EN;\ - type CNV_STEREO_TYPE;\ - type CNV_INTERLACED_MODE;\ - type CNV_EYE_SELECTION;\ - type CNV_STEREO_POLARITY;\ - type CNV_INTERLACED_FIELD_ORDER;\ - type CNV_STEREO_SPLIT;\ - type CNV_NEW_CONTENT;\ - type CNV_FRAME_CAPTURE_EN;\ - type WB_SOFT_RESET;\ - type MCIF_WB_BUFMGR_ENABLE;\ - type MCIF_WB_BUF_DUALSIZE_REQ;\ - type MCIF_WB_BUFMGR_SW_INT_EN;\ - type MCIF_WB_BUFMGR_SW_INT_ACK;\ - type MCIF_WB_BUFMGR_SW_SLICE_INT_EN;\ - type MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN;\ - type MCIF_WB_BUFMGR_SW_LOCK;\ - type MCIF_WB_P_VMID;\ - type MCIF_WB_BUF_ADDR_FENCE_EN;\ - type MCIF_WB_BUF_LUMA_PITCH;\ - type MCIF_WB_BUF_CHROMA_PITCH;\ - type MCIF_WB_CLIENT_ARBITRATION_SLICE;\ - type MCIF_WB_TIME_PER_PIXEL;\ - type WM_CHANGE_ACK_FORCE_ON;\ - type MCIF_WB_CLI_WATERMARK_MASK;\ - type MCIF_WB_BUF_1_ADDR_Y;\ - type MCIF_WB_BUF_1_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_1_ADDR_C;\ - type MCIF_WB_BUF_1_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_2_ADDR_Y;\ - type MCIF_WB_BUF_2_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_2_ADDR_C;\ - type MCIF_WB_BUF_2_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_3_ADDR_Y;\ - type MCIF_WB_BUF_3_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_3_ADDR_C;\ - type MCIF_WB_BUF_3_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_4_ADDR_Y;\ - type MCIF_WB_BUF_4_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_4_ADDR_C;\ - type MCIF_WB_BUF_4_ADDR_C_OFFSET;\ - type MCIF_WB_BUFMGR_VCE_LOCK_IGNORE;\ - type MCIF_WB_BUFMGR_VCE_INT_EN;\ - type MCIF_WB_BUFMGR_VCE_INT_ACK;\ - type MCIF_WB_BUFMGR_VCE_SLICE_INT_EN;\ - type MCIF_WB_BUFMGR_VCE_LOCK;\ - type MCIF_WB_BUFMGR_SLICE_SIZE;\ - type NB_PSTATE_CHANGE_REFRESH_WATERMARK;\ - type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST;\ - type NB_PSTATE_CHANGE_FORCE_ON;\ - type NB_PSTATE_ALLOW_FOR_URGENT;\ - type NB_PSTATE_CHANGE_WATERMARK_MASK;\ - type MCIF_WB_CLI_WATERMARK;\ - type MCIF_WB_CLI_CLOCK_GATER_OVERRIDE;\ - type MCIF_WB_PITCH_SIZE_WARMUP;\ - type MCIF_WB_BUF_LUMA_SIZE;\ - type MCIF_WB_BUF_CHROMA_SIZE;\ - type OPTC_DWB0_SOURCE_SELECT;\ - type OPTC_DWB1_SOURCE_SELECT;\ - -struct dcn10_dwbc_registers { - uint32_t WB_ENABLE; - uint32_t WB_EC_CONFIG; - uint32_t CNV_MODE; - uint32_t WB_SOFT_RESET; - uint32_t MCIF_WB_BUFMGR_SW_CONTROL; - uint32_t MCIF_WB_BUF_PITCH; - uint32_t MCIF_WB_ARBITRATION_CONTROL; - uint32_t MCIF_WB_SCLK_CHANGE; - uint32_t MCIF_WB_BUF_1_ADDR_Y; - uint32_t MCIF_WB_BUF_1_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_1_ADDR_C; - uint32_t MCIF_WB_BUF_1_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_2_ADDR_Y; - uint32_t MCIF_WB_BUF_2_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_2_ADDR_C; - uint32_t MCIF_WB_BUF_2_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_3_ADDR_Y; - uint32_t MCIF_WB_BUF_3_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_3_ADDR_C; - uint32_t MCIF_WB_BUF_3_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_4_ADDR_Y; - uint32_t MCIF_WB_BUF_4_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_4_ADDR_C; - uint32_t MCIF_WB_BUF_4_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUFMGR_VCE_CONTROL; - uint32_t MCIF_WB_NB_PSTATE_LATENCY_WATERMARK; - uint32_t MCIF_WB_NB_PSTATE_CONTROL; - uint32_t MCIF_WB_WATERMARK; - uint32_t MCIF_WB_WARM_UP_CNTL; - uint32_t MCIF_WB_BUF_LUMA_SIZE; - uint32_t MCIF_WB_BUF_CHROMA_SIZE; - uint32_t DWB_SOURCE_SELECT; -}; -struct dcn10_dwbc_mask { - DWBC_REG_FIELD_LIST(uint32_t) -}; -struct dcn10_dwbc_shift { - DWBC_REG_FIELD_LIST(uint8_t) -}; -struct dcn10_dwbc { - struct dwbc base; - const struct dcn10_dwbc_registers *dwbc_regs; - const struct dcn10_dwbc_shift *dwbc_shift; - const struct dcn10_dwbc_mask *dwbc_mask; -}; - -#define dwbc_regs(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN1_0(id),\ -} - -static const struct dcn10_dwbc_registers dwbc10_regs[] = { - dwbc_regs(0), - dwbc_regs(1), -}; - -static const struct dcn10_dwbc_shift dwbc10_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) -}; - -static const struct dcn10_dwbc_mask dwbc10_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN1_0(_MASK) -}; - - static bool get_caps(struct dwbc *dwbc, struct dwb_caps *caps) { if (caps) { @@ -603,7 +344,7 @@ const struct dwbc_funcs dcn10_dwbc_funcs = { .reset_advanced_settings = reset_advanced_settings, }; -static void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, +void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, struct dc_context *ctx, const struct dcn10_dwbc_registers *dwbc_regs, const struct dcn10_dwbc_shift *dwbc_shift, @@ -620,32 +361,5 @@ static void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, dwbc10->dwbc_mask = dwbc_mask; } -bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - ASSERT(pipe_count > 0); - for (i = 0; i < pipe_count; i++) { - struct dcn10_dwbc *dwbc10 = dm_alloc(sizeof(struct dcn10_dwbc)); - - if (!dwbc10) - return false; - - dcn10_dwbc_construct(dwbc10, ctx, - &dwbc10_regs[i], - &dwbc10_shift, - &dwbc10_mask, - i); - - pool->dwbc[i] = &dwbc10->base; - if (pool->dwbc[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc10!\n"); - return false; - } - } - return true; -} #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h index cf530aed4e1c..1fdc2be42fa9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h @@ -26,7 +26,252 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool); +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + + +#define DWBC_COMMON_REG_LIST_DCN1_0(inst) \ + SRI(WB_ENABLE, CNV, inst),\ + SRI(WB_EC_CONFIG, CNV, inst),\ + SRI(CNV_MODE, CNV, inst),\ + SRI(WB_SOFT_RESET, CNV, inst),\ + SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ + SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB, inst),\ + SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MCIF_WB, inst),\ + SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_WATERMARK, MCIF_WB, inst),\ + SRI(MCIF_WB_WARM_UP_CNTL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ + .DWB_SOURCE_SELECT = mmDWB_SOURCE_SELECT\ + +#define DWBC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh) \ + SF(CNV0_WB_ENABLE, WB_ENABLE, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\ + SF(CNV0_WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_TYPE, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_EYE_SELECTION, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_NEW_CONTENT, mask_sh),\ + SF(CNV0_CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\ + SF(CNV0_WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_DUALSIZE_REQ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) + +#define DWBC_REG_FIELD_LIST(type) \ + type WB_ENABLE;\ + type DISPCLK_R_WB_GATE_DIS;\ + type DISPCLK_G_WB_GATE_DIS;\ + type DISPCLK_G_WBSCL_GATE_DIS;\ + type WB_LB_LS_DIS;\ + type WB_LB_SD_DIS;\ + type WB_LUT_LS_DIS;\ + type CNV_WINDOW_CROP_EN;\ + type CNV_STEREO_TYPE;\ + type CNV_INTERLACED_MODE;\ + type CNV_EYE_SELECTION;\ + type CNV_STEREO_POLARITY;\ + type CNV_INTERLACED_FIELD_ORDER;\ + type CNV_STEREO_SPLIT;\ + type CNV_NEW_CONTENT;\ + type CNV_FRAME_CAPTURE_EN;\ + type WB_SOFT_RESET;\ + type MCIF_WB_BUFMGR_ENABLE;\ + type MCIF_WB_BUF_DUALSIZE_REQ;\ + type MCIF_WB_BUFMGR_SW_INT_EN;\ + type MCIF_WB_BUFMGR_SW_INT_ACK;\ + type MCIF_WB_BUFMGR_SW_SLICE_INT_EN;\ + type MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN;\ + type MCIF_WB_BUFMGR_SW_LOCK;\ + type MCIF_WB_P_VMID;\ + type MCIF_WB_BUF_ADDR_FENCE_EN;\ + type MCIF_WB_BUF_LUMA_PITCH;\ + type MCIF_WB_BUF_CHROMA_PITCH;\ + type MCIF_WB_CLIENT_ARBITRATION_SLICE;\ + type MCIF_WB_TIME_PER_PIXEL;\ + type WM_CHANGE_ACK_FORCE_ON;\ + type MCIF_WB_CLI_WATERMARK_MASK;\ + type MCIF_WB_BUF_1_ADDR_Y;\ + type MCIF_WB_BUF_1_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_1_ADDR_C;\ + type MCIF_WB_BUF_1_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_2_ADDR_Y;\ + type MCIF_WB_BUF_2_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_2_ADDR_C;\ + type MCIF_WB_BUF_2_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_3_ADDR_Y;\ + type MCIF_WB_BUF_3_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_3_ADDR_C;\ + type MCIF_WB_BUF_3_ADDR_C_OFFSET;\ + type MCIF_WB_BUF_4_ADDR_Y;\ + type MCIF_WB_BUF_4_ADDR_Y_OFFSET;\ + type MCIF_WB_BUF_4_ADDR_C;\ + type MCIF_WB_BUF_4_ADDR_C_OFFSET;\ + type MCIF_WB_BUFMGR_VCE_LOCK_IGNORE;\ + type MCIF_WB_BUFMGR_VCE_INT_EN;\ + type MCIF_WB_BUFMGR_VCE_INT_ACK;\ + type MCIF_WB_BUFMGR_VCE_SLICE_INT_EN;\ + type MCIF_WB_BUFMGR_VCE_LOCK;\ + type MCIF_WB_BUFMGR_SLICE_SIZE;\ + type NB_PSTATE_CHANGE_REFRESH_WATERMARK;\ + type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST;\ + type NB_PSTATE_CHANGE_FORCE_ON;\ + type NB_PSTATE_ALLOW_FOR_URGENT;\ + type NB_PSTATE_CHANGE_WATERMARK_MASK;\ + type MCIF_WB_CLI_WATERMARK;\ + type MCIF_WB_CLI_CLOCK_GATER_OVERRIDE;\ + type MCIF_WB_PITCH_SIZE_WARMUP;\ + type MCIF_WB_BUF_LUMA_SIZE;\ + type MCIF_WB_BUF_CHROMA_SIZE;\ + type OPTC_DWB0_SOURCE_SELECT;\ + type OPTC_DWB1_SOURCE_SELECT;\ + +struct dcn10_dwbc_registers { + uint32_t WB_ENABLE; + uint32_t WB_EC_CONFIG; + uint32_t CNV_MODE; + uint32_t WB_SOFT_RESET; + uint32_t MCIF_WB_BUFMGR_SW_CONTROL; + uint32_t MCIF_WB_BUF_PITCH; + uint32_t MCIF_WB_ARBITRATION_CONTROL; + uint32_t MCIF_WB_SCLK_CHANGE; + uint32_t MCIF_WB_BUF_1_ADDR_Y; + uint32_t MCIF_WB_BUF_1_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_1_ADDR_C; + uint32_t MCIF_WB_BUF_1_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_2_ADDR_Y; + uint32_t MCIF_WB_BUF_2_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_2_ADDR_C; + uint32_t MCIF_WB_BUF_2_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_3_ADDR_Y; + uint32_t MCIF_WB_BUF_3_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_3_ADDR_C; + uint32_t MCIF_WB_BUF_3_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUF_4_ADDR_Y; + uint32_t MCIF_WB_BUF_4_ADDR_Y_OFFSET; + uint32_t MCIF_WB_BUF_4_ADDR_C; + uint32_t MCIF_WB_BUF_4_ADDR_C_OFFSET; + uint32_t MCIF_WB_BUFMGR_VCE_CONTROL; + uint32_t MCIF_WB_NB_PSTATE_LATENCY_WATERMARK; + uint32_t MCIF_WB_NB_PSTATE_CONTROL; + uint32_t MCIF_WB_WATERMARK; + uint32_t MCIF_WB_WARM_UP_CNTL; + uint32_t MCIF_WB_BUF_LUMA_SIZE; + uint32_t MCIF_WB_BUF_CHROMA_SIZE; + uint32_t DWB_SOURCE_SELECT; +}; +struct dcn10_dwbc_mask { + DWBC_REG_FIELD_LIST(uint32_t) +}; +struct dcn10_dwbc_shift { + DWBC_REG_FIELD_LIST(uint8_t) +}; +struct dcn10_dwbc { + struct dwbc base; + const struct dcn10_dwbc_registers *dwbc_regs; + const struct dcn10_dwbc_shift *dwbc_shift; + const struct dcn10_dwbc_mask *dwbc_mask; +}; + +void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, + struct dc_context *ctx, + const struct dcn10_dwbc_registers *dwbc_regs, + const struct dcn10_dwbc_shift *dwbc_shift, + const struct dcn10_dwbc_mask *dwbc_mask, + int inst); + #endif #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index ac6d01ec0505..298eb44ad9bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -326,6 +326,24 @@ static const struct dcn_dpp_mask tf_mask = { TF_REG_LIST_SH_MASK_DCN10(_MASK), }; +#define dwbc_regs(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN1_0(id),\ +} + +static const struct dcn10_dwbc_registers dwbc10_regs[] = { + dwbc_regs(0), + dwbc_regs(1), +}; + +static const struct dcn10_dwbc_shift dwbc10_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn10_dwbc_mask dwbc10_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + static const struct dcn_mpc_registers mpc_regs = { MPC_COMMON_REG_LIST_DCN1_0(0), MPC_COMMON_REG_LIST_DCN1_0(1), @@ -1215,6 +1233,30 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) return value; } +static bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t dwb_count = pool->res_cap->num_dwb; + + for (i = 0; i < dwb_count; i++) { + struct dcn10_dwbc *dwbc10 = dm_alloc(sizeof(struct dcn10_dwbc)); + + if (!dwbc10) { + dm_error("DC: failed to create dwbc10!\n"); + return false; + } + + dcn10_dwbc_construct(dwbc10, ctx, + &dwbc10_regs[i], + &dwbc10_shift, + &dwbc10_mask, + i); + + pool->dwbc[i] = &dwbc10->base; + } + return true; +} + static bool construct( uint8_t num_virtual_links, struct dc *dc, -- GitLab From 21e67d4d52ca8688feb8c4f6e6d29b2d16d578ad Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 5 Sep 2017 15:50:48 -0400 Subject: [PATCH 0877/2898] drm/amd/display: No need to keep track of unreffed clk sources This simplifies clock source reprogramming a bit. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 18 ++----------- .../display/dc/dce110/dce110_hw_sequencer.c | 21 ++++------------ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 25 ++++++------------- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 -- drivers/gpu/drm/amd/display/dc/inc/resource.h | 2 +- 5 files changed, 16 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9aa0da743174..15b627548cd2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -261,13 +261,12 @@ bool resource_construct( } -bool resource_unreference_clock_source( +void resource_unreference_clock_source( struct resource_context *res_ctx, const struct resource_pool *pool, struct clock_source *clock_source) { int i; - bool need_reset = false; for (i = 0; i < pool->clk_src_count; i++) { if (pool->clock_sources[i] != clock_source) @@ -275,24 +274,11 @@ bool resource_unreference_clock_source( res_ctx->clock_source_ref_count[i]--; - if (res_ctx->clock_source_ref_count[i] == 0) { - res_ctx->clock_source_changed[i] = true; - need_reset = true; - } - break; } - if (pool->dp_clock_source == clock_source) { + if (pool->dp_clock_source == clock_source) res_ctx->dp_clock_source_ref_count--; - - if (res_ctx->dp_clock_source_ref_count == 0) { - res_ctx->dp_clock_source_changed = true; - need_reset = true; - } - } - - return need_reset; } void resource_reference_clock_source( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c57dc45d6677..31592e53f504 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1640,6 +1640,8 @@ static void dce110_reset_hw_ctx_wrap( if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + struct clock_source *old_clk = pipe_ctx_old->clock_source; + core_link_disable_stream(pipe_ctx_old); pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { @@ -1650,27 +1652,14 @@ static void dce110_reset_hw_ctx_wrap( pipe_ctx_old->plane_res.mi->funcs->free_mem_input( pipe_ctx_old->plane_res.mi, dc->current_state->stream_count); + if (old_clk) + old_clk->funcs->cs_power_down(old_clk); + dc->hwss.power_down_front_end(dc, pipe_ctx_old->pipe_idx); pipe_ctx_old->stream = NULL; } } - - /* power down changed clock sources */ - for (i = 0; i < dc->res_pool->clk_src_count; i++) - if (context->res_ctx.clock_source_changed[i]) { - struct clock_source *clk = dc->res_pool->clock_sources[i]; - - clk->funcs->cs_power_down(clk); - context->res_ctx.clock_source_changed[i] = false; - } - - if (context->res_ctx.dp_clock_source_changed) { - struct clock_source *clk = dc->res_pool->dp_clock_source; - - clk->funcs->cs_power_down(clk); - context->res_ctx.clock_source_changed[i] = false; - } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6fee6957c1a6..c8c4b951ee1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1265,22 +1265,6 @@ static void reset_hw_ctx_wrap( plane_atomic_power_down(dc, i); } - /* power down changed clock sources */ - for (i = 0; i < dc->res_pool->clk_src_count; i++) - if (context->res_ctx.clock_source_changed[i]) { - struct clock_source *clk = dc->res_pool->clock_sources[i]; - - clk->funcs->cs_power_down(clk); - context->res_ctx.clock_source_changed[i] = false; - } - - if (context->res_ctx.dp_clock_source_changed) { - struct clock_source *clk = dc->res_pool->dp_clock_source; - - clk->funcs->cs_power_down(clk); - context->res_ctx.dp_clock_source_changed = false; - } - /* Reset Back End*/ for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { struct pipe_ctx *pipe_ctx_old = @@ -1291,9 +1275,16 @@ static void reset_hw_ctx_wrap( continue; if (!pipe_ctx->stream || - pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) + pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { + struct clock_source *old_clk = pipe_ctx_old->clock_source; + reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state); + + if (old_clk) + old_clk->funcs->cs_power_down(old_clk); + } } + } static bool patch_address_for_sbs_tb_stereo( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b6a513d6feda..915d5c10361b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -213,9 +213,7 @@ struct resource_context { bool is_stream_enc_acquired[MAX_PIPES * 2]; bool is_audio_acquired[MAX_PIPES]; uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; - bool clock_source_changed[MAX_CLOCK_SOURCES]; uint8_t dp_clock_source_ref_count; - bool dp_clock_source_changed; }; struct dce_bw_output { diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index cf1797c191e9..614bb691ab59 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -92,7 +92,7 @@ enum dc_status resource_build_scaling_params_for_context( void resource_build_info_frame(struct pipe_ctx *pipe_ctx); -bool resource_unreference_clock_source( +void resource_unreference_clock_source( struct resource_context *res_ctx, const struct resource_pool *pool, struct clock_source *clock_source); -- GitLab From e9475143fb42b62689163c95aabdb6c173fcdbb0 Mon Sep 17 00:00:00 2001 From: pana Date: Fri, 1 Sep 2017 15:43:22 +0800 Subject: [PATCH 0878/2898] drm/amd/display: Add 2X Cursor Magnification Code Signed-off-by: Pandey, Arun Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 5edc4b7073e1..5e0e2464eab3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -154,12 +154,10 @@ static void ippn10_cursor_set_attributes( REG_UPDATE_2(CURSOR_SIZE, CURSOR_WIDTH, attr->width, CURSOR_HEIGHT, attr->height); - REG_UPDATE_3(CURSOR_CONTROL, CURSOR_MODE, attr->color_format, CURSOR_PITCH, hw_pitch, CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(ippn10, attr->attribute_flags.bits.INVERT_PIXEL_DATA, attr->color_format); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h index e4f292822975..d7b5bd20352a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.h @@ -50,6 +50,15 @@ SRI(CURSOR_HOT_SPOT, CURSOR, id), \ SRI(CURSOR_DST_OFFSET, CURSOR, id) +#define CURSOR0_CURSOR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x4 +#define CURSOR0_CURSOR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00000010L +#define CURSOR1_CURSOR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x4 +#define CURSOR1_CURSOR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00000010L +#define CURSOR2_CURSOR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x4 +#define CURSOR2_CURSOR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00000010L +#define CURSOR3_CURSOR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x4 +#define CURSOR3_CURSOR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00000010L + #define IPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -73,6 +82,7 @@ IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ IPP_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ @@ -99,6 +109,7 @@ type CURSOR_WIDTH; \ type CURSOR_HEIGHT; \ type CURSOR_MODE; \ + type CURSOR_2X_MAGNIFY; \ type CURSOR_PITCH; \ type CURSOR_LINES_PER_CHUNK; \ type CURSOR_ENABLE; \ -- GitLab From c84dec2fe8837facf4ccaffd2afae9b157719327 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 5 Sep 2017 14:16:09 -0400 Subject: [PATCH 0879/2898] drm/amd/display: Break out amdgpu_dm_connector Stop using amdgpu_connector and roll our own. There is no overlap with amdgpu. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 126 +++++++++--------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 53 +++++++- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 20 +-- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 12 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 34 ++--- .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 4 +- 6 files changed, 146 insertions(+), 103 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index febfff2225d9..c42660520871 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -465,14 +465,14 @@ static int dm_sw_fini(void *handle) static int detect_mst_link_for_all_connectors(struct drm_device *dev) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; int ret = 0; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type == dc_connection_mst_branch) { DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); @@ -500,13 +500,13 @@ static int dm_late_init(void *handle) static void s3_handle_mst(struct drm_device *dev, bool suspend) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type == dc_connection_mst_branch && !aconnector->mst_port) { @@ -562,7 +562,7 @@ static int dm_suspend(void *handle) return ret; } -struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( +struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_atomic_state *state, struct drm_crtc *crtc, bool from_state_var) @@ -583,7 +583,7 @@ struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( connector->state->crtc; if (crtc_from_state == crtc) - return to_amdgpu_connector(connector); + return to_amdgpu_dm_connector(connector); } return NULL; @@ -607,7 +607,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) { struct drm_device *ddev = adev->ddev; struct amdgpu_display_manager *dm = &adev->dm; - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; @@ -629,7 +629,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev ) /* Do detection*/ list_for_each_entry(connector, &ddev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); /* * this is the case when traversing through already created @@ -741,7 +741,7 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { }; void amdgpu_dm_update_connector_after_detect( - struct amdgpu_connector *aconnector) + struct amdgpu_dm_connector *aconnector) { struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; @@ -847,7 +847,7 @@ void amdgpu_dm_update_connector_after_detect( static void handle_hpd_irq(void *param) { - struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param; + struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; @@ -870,7 +870,7 @@ static void handle_hpd_irq(void *param) } -static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector) +static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) { uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 }; uint8_t dret; @@ -949,7 +949,7 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_connector *aconnector) static void handle_hpd_rx_irq(void *param) { - struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param; + struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; const struct dc_link *dc_link = aconnector->dc_link; @@ -988,7 +988,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev) { struct drm_device *dev = adev->ddev; struct drm_connector *connector; - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; const struct dc_link *dc_link; struct dc_interrupt_params int_params = {0}; @@ -998,7 +998,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); dc_link = aconnector->dc_link; if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) { @@ -1279,7 +1279,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) { struct amdgpu_display_manager *dm = &adev->dm; uint32_t i; - struct amdgpu_connector *aconnector = NULL; + struct amdgpu_dm_connector *aconnector = NULL; struct amdgpu_encoder *aencoder = NULL; struct amdgpu_mode_info *mode_info = &adev->mode_info; uint32_t link_cnt; @@ -1966,18 +1966,18 @@ static int fill_plane_attributes( /*****************************************************************************/ -struct amdgpu_connector *aconnector_from_drm_crtc_id( +struct amdgpu_dm_connector *aconnector_from_drm_crtc_id( const struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_connector *connector; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->base.state->crtc != &acrtc->base) continue; @@ -2279,7 +2279,7 @@ static void decide_crtc_timing_for_drm_display_mode( } static struct dc_stream_state *create_stream_for_sink( - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state) { @@ -2425,7 +2425,7 @@ static enum drm_connector_status amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) { bool connected; - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); /* Notes: * 1. This interface is NOT called in context of HPD irq. @@ -2538,7 +2538,7 @@ int amdgpu_dm_connector_atomic_get_property( void amdgpu_dm_connector_destroy(struct drm_connector *connector) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); const struct dc_link *link = aconnector->dc_link; struct amdgpu_device *adev = connector->dev->dev_private; struct amdgpu_display_manager *dm = &adev->dm; @@ -2636,7 +2636,7 @@ static int get_modes(struct drm_connector *connector) return amdgpu_dm_connector_get_modes(connector); } -static void create_eml_sink(struct amdgpu_connector *aconnector) +static void create_eml_sink(struct amdgpu_dm_connector *aconnector) { struct dc_sink_init_data init_params = { .link = aconnector->dc_link, @@ -2669,7 +2669,7 @@ static void create_eml_sink(struct amdgpu_connector *aconnector) aconnector->dc_em_sink; } -static void handle_edid_mgmt(struct amdgpu_connector *aconnector) +static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector) { struct dc_link *link = (struct dc_link *)aconnector->dc_link; @@ -2695,7 +2695,7 @@ int amdgpu_dm_connector_mode_valid( struct amdgpu_device *adev = connector->dev->dev_private; /* TODO: Unhardcode stream count */ struct dc_stream_state *stream; - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) @@ -2708,7 +2708,7 @@ int amdgpu_dm_connector_mode_valid( !aconnector->dc_em_sink) handle_edid_mgmt(aconnector); - dc_sink = to_amdgpu_connector(connector)->dc_sink; + dc_sink = to_amdgpu_dm_connector(connector)->dc_sink; if (dc_sink == NULL) { DRM_ERROR("dc_sink is NULL!\n"); @@ -2968,7 +2968,7 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, { int result = MODE_ERROR; struct dc_sink *dc_sink = - to_amdgpu_connector(connector)->dc_sink; + to_amdgpu_dm_connector(connector)->dc_sink; /* TODO: Unhardcode stream count */ struct dc_stream_state *stream; @@ -3229,8 +3229,8 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_display_mode *mode = NULL; struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); int i; int n; struct mode_size { @@ -3278,7 +3278,7 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, common_modes[i].name, common_modes[i].w, common_modes[i].h); drm_mode_probed_add(connector, mode); - amdgpu_connector->num_modes++; + amdgpu_dm_connector->num_modes++; } } @@ -3286,41 +3286,41 @@ static void amdgpu_dm_connector_ddc_get_modes( struct drm_connector *connector, struct edid *edid) { - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); if (edid) { /* empty probed_modes */ INIT_LIST_HEAD(&connector->probed_modes); - amdgpu_connector->num_modes = + amdgpu_dm_connector->num_modes = drm_add_edid_modes(connector, edid); drm_edid_to_eld(connector, edid); amdgpu_dm_get_native_mode(connector); } else - amdgpu_connector->num_modes = 0; + amdgpu_dm_connector->num_modes = 0; } int amdgpu_dm_connector_get_modes(struct drm_connector *connector) { const struct drm_connector_helper_funcs *helper = connector->helper_private; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); struct drm_encoder *encoder; - struct edid *edid = amdgpu_connector->edid; + struct edid *edid = amdgpu_dm_connector->edid; encoder = helper->best_encoder(connector); amdgpu_dm_connector_ddc_get_modes(connector, edid); amdgpu_dm_connector_add_common_modes(encoder, connector); - return amdgpu_connector->num_modes; + return amdgpu_dm_connector->num_modes; } void amdgpu_dm_connector_init_helper( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, int connector_type, struct dc_link *link, int link_index) @@ -3440,7 +3440,7 @@ static struct amdgpu_i2c_adapter *create_i2c( */ int amdgpu_dm_connector_init( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, uint32_t link_index, struct amdgpu_encoder *aencoder) { @@ -4076,7 +4076,7 @@ void amdgpu_dm_atomic_commit_tail( */ if (adev->dm.freesync_module) { for (i = 0; i < new_crtcs_count; i++) { - struct amdgpu_connector *aconnector = NULL; + struct amdgpu_dm_connector *aconnector = NULL; new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); @@ -4120,7 +4120,7 @@ void amdgpu_dm_atomic_commit_tail( /* Handle scaling and undersacn changes*/ for_each_connector_in_state(state, connector, old_conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *con_new_state = to_dm_connector_state(aconnector->base.state); struct dm_connector_state *con_old_state = @@ -4270,7 +4270,7 @@ static int dm_force_atomic_commit(struct drm_connector *connector) */ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_crtc *disconnected_acrtc; struct dm_crtc_state *acrtc_state; @@ -4360,7 +4360,7 @@ static int dm_update_crtcs_state( /* update changed items */ for_each_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; - struct amdgpu_connector *aconnector = NULL; + struct amdgpu_dm_connector *aconnector = NULL; struct drm_connector_state *conn_state = NULL; struct dm_connector_state *dm_conn_state = NULL; @@ -4689,7 +4689,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * decide how to handle. */ for_each_connector_in_state(state, connector, conn_state, i) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *con_old_state = to_dm_connector_state(aconnector->base.state); struct dm_connector_state *con_new_state = @@ -4746,15 +4746,15 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, static bool is_dp_capable_without_timing_msa( struct dc *dc, - struct amdgpu_connector *amdgpu_connector) + struct amdgpu_dm_connector *amdgpu_dm_connector) { uint8_t dpcd_data; bool capable = false; - if (amdgpu_connector->dc_link && + if (amdgpu_dm_connector->dc_link && dm_helpers_dp_read_dpcd( NULL, - amdgpu_connector->dc_link, + amdgpu_dm_connector->dc_link, DP_DOWN_STREAM_PORT_COUNT, &dpcd_data, sizeof(dpcd_data))) { @@ -4773,14 +4773,14 @@ void amdgpu_dm_add_sink_to_freesync_module( struct detailed_timing *timing; struct detailed_non_pixel *data; struct detailed_data_monitor_range *range; - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; edid_check_required = false; - if (!amdgpu_connector->dc_sink) { + if (!amdgpu_dm_connector->dc_sink) { DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); return; } @@ -4790,11 +4790,11 @@ void amdgpu_dm_add_sink_to_freesync_module( * if edid non zero restrict freesync only for dp and edp */ if (edid) { - if (amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT - || amdgpu_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { + if (amdgpu_dm_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT + || amdgpu_dm_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { edid_check_required = is_dp_capable_without_timing_msa( adev->dm.dc, - amdgpu_connector); + amdgpu_dm_connector); } } val_capable = 0; @@ -4819,20 +4819,20 @@ void amdgpu_dm_add_sink_to_freesync_module( if (range->flags != 1) continue; - amdgpu_connector->min_vfreq = range->min_vfreq; - amdgpu_connector->max_vfreq = range->max_vfreq; - amdgpu_connector->pixel_clock_mhz = + amdgpu_dm_connector->min_vfreq = range->min_vfreq; + amdgpu_dm_connector->max_vfreq = range->max_vfreq; + amdgpu_dm_connector->pixel_clock_mhz = range->pixel_clock_mhz * 10; break; } - if (amdgpu_connector->max_vfreq - - amdgpu_connector->min_vfreq > 10) { - amdgpu_connector->caps.supported = true; - amdgpu_connector->caps.min_refresh_in_micro_hz = - amdgpu_connector->min_vfreq * 1000000; - amdgpu_connector->caps.max_refresh_in_micro_hz = - amdgpu_connector->max_vfreq * 1000000; + if (amdgpu_dm_connector->max_vfreq - + amdgpu_dm_connector->min_vfreq > 10) { + amdgpu_dm_connector->caps.supported = true; + amdgpu_dm_connector->caps.min_refresh_in_micro_hz = + amdgpu_dm_connector->min_vfreq * 1000000; + amdgpu_dm_connector->caps.max_refresh_in_micro_hz = + amdgpu_dm_connector->max_vfreq * 1000000; val_capable = 1; } } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 71cbee199016..8894613e956c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -147,6 +147,50 @@ struct amdgpu_display_manager { #endif }; +struct amdgpu_dm_connector { + + struct drm_connector base; + uint32_t connector_id; + + /* we need to mind the EDID between detect + and get modes due to analog/digital/tvencoder */ + struct edid *edid; + + /* shared with amdgpu */ + struct amdgpu_hpd hpd; + + /* number of modes generated from EDID at 'dc_sink' */ + int num_modes; + + /* The 'old' sink - before an HPD. + * The 'current' sink is in dc_link->sink. */ + struct dc_sink *dc_sink; + struct dc_link *dc_link; + struct dc_sink *dc_em_sink; + + /* DM only */ + struct drm_dp_mst_topology_mgr mst_mgr; + struct amdgpu_dm_dp_aux dm_dp_aux; + struct drm_dp_mst_port *port; + struct amdgpu_dm_connector *mst_port; + struct amdgpu_encoder *mst_encoder; + + /* TODO see if we can merge with ddc_bus or make a dm_connector */ + struct amdgpu_i2c_adapter *i2c; + + /* Monitor range limits */ + int min_vfreq ; + int max_vfreq ; + int pixel_clock_mhz; + + /*freesync caps*/ + struct mod_freesync_caps caps; + + struct mutex hpd_lock; +}; + +#define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) + /* basic init/fini API */ int amdgpu_dm_init(struct amdgpu_device *adev); @@ -178,9 +222,9 @@ void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm); extern const struct amdgpu_ip_block_version dm_ip_block; void amdgpu_dm_update_connector_after_detect( - struct amdgpu_connector *aconnector); + struct amdgpu_dm_connector *aconnector); -struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector( +struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_atomic_state *state, struct drm_crtc *crtc, bool from_state_var); @@ -193,7 +237,6 @@ struct dc_plane_state; /* TODO rename to dc_stream_state */ struct dc_stream; - struct dm_plane_state { struct drm_plane_state base; struct dc_plane_state *dc_state; @@ -223,7 +266,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, uint32_t link_index); int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_connector *amdgpu_connector, + struct amdgpu_dm_connector *amdgpu_dm_connector, uint32_t link_index, struct amdgpu_encoder *amdgpu_encoder); int amdgpu_dm_encoder_init( @@ -267,7 +310,7 @@ int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); void amdgpu_dm_connector_init_helper( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, int connector_type, struct dc_link *link, int link_index); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 4a124537dc9a..9bd142f65f9b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -133,7 +133,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( } static void get_payload_table( - struct amdgpu_connector *aconnector, + struct amdgpu_dm_connector *aconnector, struct dp_mst_stream_allocation_table *proposed_table) { int i; @@ -178,7 +178,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( struct dp_mst_stream_allocation_table *proposed_table, bool enable) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; int slots = 0; @@ -266,7 +266,7 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger( struct dc_context *ctx, const struct dc_stream_state *stream) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; int ret; @@ -293,7 +293,7 @@ bool dm_helpers_dp_mst_send_payload_allocation( const struct dc_stream_state *stream, bool enable) { - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_mgr *mst_mgr; struct drm_dp_mst_port *mst_port; int ret; @@ -341,7 +341,7 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -364,7 +364,7 @@ void dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, const struct dc_link *link) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -386,7 +386,7 @@ bool dm_helpers_dp_read_dpcd( uint32_t size) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -404,7 +404,7 @@ bool dm_helpers_dp_write_dpcd( const uint8_t *data, uint32_t size) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; if (!aconnector) { DRM_ERROR("Failed to found connector for link!"); @@ -420,7 +420,7 @@ bool dm_helpers_submit_i2c( const struct dc_link *link, struct i2c_command *cmd) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; struct i2c_msg *msgs; int i = 0; int num = cmd->number_of_payloads; @@ -455,7 +455,7 @@ enum dc_edid_status dm_helpers_read_local_edid( struct dc_link *link, struct dc_sink *sink) { - struct amdgpu_connector *aconnector = link->priv; + struct amdgpu_dm_connector *aconnector = link->priv; struct i2c_adapter *ddc; int retry = 3; enum dc_edid_status edid_status; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 4aee146a848f..276adf96d5f2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -787,10 +787,10 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) struct drm_connector *connector; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); - const struct dc_link *dc_link = amdgpu_connector->dc_link; + const struct dc_link *dc_link = amdgpu_dm_connector->dc_link; if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) { dc_interrupt_set(adev->dm.dc, @@ -820,9 +820,9 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) struct drm_connector *connector; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct amdgpu_connector *amdgpu_connector = - to_amdgpu_connector(connector); - const struct dc_link *dc_link = amdgpu_connector->dc_link; + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); + const struct dc_link *dc_link = amdgpu_dm_connector->dc_link; dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 82e4d49fb184..343645e4070b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -137,8 +137,8 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg static enum drm_connector_status dm_dp_mst_detect(struct drm_connector *connector, bool force) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); - struct amdgpu_connector *master = aconnector->mst_port; + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + struct amdgpu_dm_connector *master = aconnector->mst_port; enum drm_connector_status status = drm_dp_mst_detect_port( @@ -152,13 +152,13 @@ dm_dp_mst_detect(struct drm_connector *connector, bool force) static void dm_dp_mst_connector_destroy(struct drm_connector *connector) { - struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); - struct amdgpu_encoder *amdgpu_encoder = amdgpu_connector->mst_encoder; + struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); + struct amdgpu_encoder *amdgpu_encoder = amdgpu_dm_connector->mst_encoder; drm_encoder_cleanup(&amdgpu_encoder->base); kfree(amdgpu_encoder); drm_connector_cleanup(connector); - kfree(amdgpu_connector); + kfree(amdgpu_dm_connector); } static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { @@ -174,7 +174,7 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { static int dm_dp_mst_get_modes(struct drm_connector *connector) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); int ret = 0; ret = drm_add_edid_modes(&aconnector->base, aconnector->edid); @@ -186,9 +186,9 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector) { - struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); - return &amdgpu_connector->mst_encoder->base; + return &amdgpu_dm_connector->mst_encoder->base; } static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = { @@ -198,7 +198,7 @@ static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs }; static struct amdgpu_encoder * -dm_dp_create_fake_mst_encoder(struct amdgpu_connector *connector) +dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) { struct drm_device *dev = connector->base.dev; struct amdgpu_device *adev = dev->dev_private; @@ -233,15 +233,15 @@ static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_ struct drm_dp_mst_port *port, const char *pathprop) { - struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr); + struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->mst_port == master && !aconnector->port) { DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n", @@ -315,7 +315,7 @@ static void dm_dp_destroy_mst_connector( struct drm_dp_mst_topology_mgr *mgr, struct drm_connector *connector) { - struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n", aconnector, connector->base.id, aconnector->mst_port); @@ -339,17 +339,17 @@ static void dm_dp_destroy_mst_connector( static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) { - struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr); + struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; struct amdgpu_device *adev = dev->dev_private; struct drm_connector *connector; - struct amdgpu_connector *aconnector; + struct amdgpu_dm_connector *aconnector; struct edid *edid; struct dc_sink *dc_sink; drm_modeset_lock_all(dev); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->port && aconnector->port->pdt != DP_PEER_DEVICE_NONE && aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING && @@ -440,7 +440,7 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { void amdgpu_dm_initialize_dp_connector( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector) + struct amdgpu_dm_connector *aconnector) { aconnector->dm_dp_aux.aux.name = "dmdc"; aconnector->dm_dp_aux.aux.dev = dm->adev->dev; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 418061f3b46b..ba64a408d79c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -27,10 +27,10 @@ #define __DAL_AMDGPU_DM_MST_TYPES_H__ struct amdgpu_display_manager; -struct amdgpu_connector; +struct amdgpu_dm_connector; void amdgpu_dm_initialize_dp_connector( struct amdgpu_display_manager *dm, - struct amdgpu_connector *aconnector); + struct amdgpu_dm_connector *aconnector); #endif -- GitLab From 2e0ac3d68838d20a5eace958bdf853a295a7175f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 17 Aug 2017 14:58:07 -0400 Subject: [PATCH 0880/2898] drm/amd/display: Create fake sink if needed when commit stream The problem we're trying to fix is this (and similar): 1) X Desktop with single display 2) VT switch 3) Unplug display 4) VT switch back to X 5) re-plug same display Before this we'd fail at step 4 when trying to create a dc_stream_state because of a missing sink. This change will fake a sink in this case. The same scenario applies to S3 resume. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 ++++++++++++++++++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 ++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c42660520871..d2ece343b5fa 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -855,6 +855,10 @@ static void handle_hpd_irq(void *param) * since (for MST case) MST does this in it's own context. */ mutex_lock(&aconnector->hpd_lock); + + if (aconnector->fake_enable) + aconnector->fake_enable = false; + if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -2278,6 +2282,25 @@ static void decide_crtc_timing_for_drm_display_mode( } } +static void create_fake_sink(struct amdgpu_dm_connector *aconnector) +{ + struct dc_sink *sink = NULL; + struct dc_sink_init_data sink_init_data = { 0 }; + + sink_init_data.link = aconnector->dc_link; + sink_init_data.sink_signal = aconnector->dc_link->connector_signal; + + sink = dc_sink_create(&sink_init_data); + if (!sink) + DRM_ERROR("Failed to create sink!\n"); + + sink->sink_signal = SIGNAL_TYPE_VIRTUAL; + aconnector->fake_enable = true; + + aconnector->dc_sink = sink; + aconnector->dc_link->local_sink = sink; +} + static struct dc_stream_state *create_stream_for_sink( struct amdgpu_dm_connector *aconnector, const struct drm_display_mode *drm_mode, @@ -2300,6 +2323,10 @@ static struct dc_stream_state *create_stream_for_sink( } drm_connector = &aconnector->base; + + if (!aconnector->dc_sink) + create_fake_sink(aconnector); + stream = dc_create_stream_for_sink(aconnector->dc_sink); if (stream == NULL) { @@ -4373,7 +4400,7 @@ static int dm_update_crtcs_state( aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); /* TODO This hack should go away */ - if (aconnector && aconnector->dc_sink) { + if (aconnector) { conn_state = drm_atomic_get_connector_state(state, &aconnector->base); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 8894613e956c..630e6cdf84f6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -187,6 +187,8 @@ struct amdgpu_dm_connector { struct mod_freesync_caps caps; struct mutex hpd_lock; + + bool fake_enable; }; #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) -- GitLab From e338aab03f0d8d0ae37b83bdf3ff5633c6eaf52f Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Tue, 5 Sep 2017 15:58:37 -0500 Subject: [PATCH 0881/2898] drm/amd/display: Update DPP registers Signed-off-by: Vitaly Prosyak Reviewed-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 34e501979b55..afe9d8f629d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -742,17 +742,11 @@ type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G; \ type CM_SHAPER_RAMB_EXP_REGION_START_R; \ type CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R; \ - type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_SHAPER_RAMB_EXP_REGION_LINEAR_SLOPE_R; \ type CM_SHAPER_RAMB_EXP_REGION_END_B; \ - type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_B; \ type CM_SHAPER_RAMB_EXP_REGION_END_BASE_B; \ type CM_SHAPER_RAMB_EXP_REGION_END_G; \ - type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_G; \ type CM_SHAPER_RAMB_EXP_REGION_END_BASE_G; \ type CM_SHAPER_RAMB_EXP_REGION_END_R; \ - type CM_SHAPER_RAMB_EXP_REGION_END_SLOPE_R; \ type CM_SHAPER_RAMB_EXP_REGION_END_BASE_R; \ type CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET; \ type CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS; \ @@ -828,17 +822,11 @@ type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G; \ type CM_SHAPER_RAMA_EXP_REGION_START_R; \ type CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R; \ - type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_B; \ - type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_G; \ - type CM_SHAPER_RAMA_EXP_REGION_LINEAR_SLOPE_R; \ type CM_SHAPER_RAMA_EXP_REGION_END_B; \ - type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_B; \ type CM_SHAPER_RAMA_EXP_REGION_END_BASE_B; \ type CM_SHAPER_RAMA_EXP_REGION_END_G; \ - type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_G; \ type CM_SHAPER_RAMA_EXP_REGION_END_BASE_G; \ type CM_SHAPER_RAMA_EXP_REGION_END_R; \ - type CM_SHAPER_RAMA_EXP_REGION_END_SLOPE_R; \ type CM_SHAPER_RAMA_EXP_REGION_END_BASE_R; \ type CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET; \ type CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS; \ @@ -1160,6 +1148,9 @@ struct dcn_dpp_registers { uint32_t CM_SHAPER_RAMB_START_CNTL_B; uint32_t CM_SHAPER_RAMB_START_CNTL_G; uint32_t CM_SHAPER_RAMB_START_CNTL_R; + uint32_t CM_SHAPER_RAMB_END_CNTL_B; + uint32_t CM_SHAPER_RAMB_END_CNTL_G; + uint32_t CM_SHAPER_RAMB_END_CNTL_R; uint32_t CM_SHAPER_RAMB_REGION_0_1; uint32_t CM_SHAPER_RAMB_REGION_2_3; uint32_t CM_SHAPER_RAMB_REGION_4_5; @@ -1180,6 +1171,9 @@ struct dcn_dpp_registers { uint32_t CM_SHAPER_RAMA_START_CNTL_B; uint32_t CM_SHAPER_RAMA_START_CNTL_G; uint32_t CM_SHAPER_RAMA_START_CNTL_R; + uint32_t CM_SHAPER_RAMA_END_CNTL_B; + uint32_t CM_SHAPER_RAMA_END_CNTL_G; + uint32_t CM_SHAPER_RAMA_END_CNTL_R; uint32_t CM_SHAPER_RAMA_REGION_0_1; uint32_t CM_SHAPER_RAMA_REGION_2_3; uint32_t CM_SHAPER_RAMA_REGION_4_5; -- GitLab From 05230fa90d96523755ddad30972a25b6651de739 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Tue, 5 Sep 2017 18:23:46 -0400 Subject: [PATCH 0882/2898] drm/amd/display: Disable FBC for linear tiling - Fixing text console on FBC-enabled builds Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 31592e53f504..37497e88a930 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1552,6 +1552,10 @@ static enum dc_status validate_fbc(struct dc *dc, if (pipe_ctx->stream->sink->link->psr_enabled) return DC_ERROR_UNEXPECTED; + /* Only for non-linear tiling */ + if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) + return DC_ERROR_UNEXPECTED; + return DC_OK; } -- GitLab From 1ecfc3da95428983725d643e80e9a320497d2059 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 8 Sep 2017 10:23:42 -0400 Subject: [PATCH 0883/2898] drm/amd/display: Format changes to bring in line with internal tree Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 ++-- drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d2ece343b5fa..bb4f415746d5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -603,7 +603,7 @@ static int dm_resume(void *handle) return 0; } -int amdgpu_dm_display_resume(struct amdgpu_device *adev ) +int amdgpu_dm_display_resume(struct amdgpu_device *adev) { struct drm_device *ddev = adev->ddev; struct amdgpu_display_manager *dm = &adev->dm; @@ -1794,7 +1794,7 @@ static int fill_plane_attributes_from_fb( break; default: DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(fb->format->format, &format_name)); + drm_get_format_name(fb->format->format, &format_name)); return -EINVAL; } @@ -2618,7 +2618,7 @@ struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( if (new_state) { __drm_atomic_helper_connector_duplicate_state(connector, - &new_state->base); + &new_state->base); return &new_state->base; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 276adf96d5f2..22d41d35249e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -705,8 +705,8 @@ static inline int dm_irq_state( if (!acrtc) { DRM_ERROR( "%s: crtc is NULL at id :%d\n", - func, - crtc_id); + func, + crtc_id); return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 25f6f9103c44..f7d049c0e62a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -41,7 +41,6 @@ */ #include "dce80/hw_factory_dce80.h" - #include "dce110/hw_factory_dce110.h" #include "dce120/hw_factory_dce120.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- GitLab From f6baff4d1a0e3235b4a8ffd755e257b998705419 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 8 Sep 2017 10:24:21 -0400 Subject: [PATCH 0884/2898] drm/amd/display: Change comments to bring in line with internal tree Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 8 +++----- .../drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 37497e88a930..5bbfc34d6f01 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1439,13 +1439,11 @@ static uint32_t get_max_pixel_clock_for_all_paths( return max_pix_clk; } -/* Find clock state based on clock requested. if clock value is 0, simply +/* + * Find clock state based on clock requested. if clock value is 0, simply * set clock state as requested without finding clock state by clock value - *TODO: when dce120_hw_sequencer.c is created, override apply_min_clock. - * - * TODOFPGA remove TODO after implement dal_display_clock_get_cur_clocks_value - * etc support for dcn1.0 */ + static void apply_min_clocks( struct dc *dc, struct dc_state *context, diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index 98ce0fe5ac37..d3eaf8977a60 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -372,7 +372,7 @@ static enum aux_channel_operation_result get_channel_status( 10, aux110->timeout_period/10); /* Note that the following bits are set in 'status.bits' - * during CTS 4.2.1.2: + * during CTS 4.2.1.2 (FW 3.3.1): * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. * -- GitLab From a6def44598eb6b82992ffd696cfd7f027940e2cd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 8 Sep 2017 10:25:25 -0400 Subject: [PATCH 0885/2898] drm/amd/display: Update include to bring in line with internal tree Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1 + drivers/gpu/drm/amd/display/include/dal_asic_id.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c8c4b951ee1d..c4875c3a0d93 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -40,6 +40,7 @@ #include "ipp.h" #include "mpc.h" #include "reg_helper.h" +#include "custom_float.h" #define CTX \ hws->ctx diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 14e3146a0cb2..7abe663ecc6e 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -112,6 +112,7 @@ /* DCN1_0 */ #define INTERNAL_REV_RAVEN_A0 0x00 /* First spin of Raven */ #define RAVEN_A0 0x01 +#define RAVEN_B0 0x21 #define RAVEN_UNKNOWN 0xFF #define ASIC_REV_IS_RAVEN(eChipRev) ((eChipRev >= RAVEN_A0) && eChipRev < RAVEN_UNKNOWN) -- GitLab From dd3d18bf5e4994c5f8dd008db6123d0525eb62e5 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 11 Sep 2017 18:48:27 -0400 Subject: [PATCH 0886/2898] drm/amd/display: Clean Kconfig formatting Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 89fc8e738668..6d1086d0a277 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -18,11 +18,11 @@ config DRM_AMD_DC_PRE_VEGA and Hawaii. config DRM_AMD_DC_DCN1_0 - bool "DCN 1.0 Raven family" - depends on DRM_AMD_DC && X86 - help - Choose this option if you want to have - RV family for display engine + bool "DCN 1.0 Raven family" + depends on DRM_AMD_DC && X86 + help + Choose this option if you want to have + RV family for display engine config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" -- GitLab From 02e749dcbe5da2b1b2b1c3825be094287257046f Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 20:02:11 -0400 Subject: [PATCH 0887/2898] drm/amdgpu: Add dc_log module parameter We want to make DC less chatty but still allow bug reporters to provide more detailed logs. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2c88dd07e1bc..cd1562fefd73 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -103,6 +103,7 @@ extern int amdgpu_vm_fault_stop; extern int amdgpu_vm_debug; extern int amdgpu_vm_update_mode; extern int amdgpu_dc; +extern int amdgpu_dc_log; extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern int amdgpu_no_evict; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 13cd35b70c51..7e753969506b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -104,6 +104,7 @@ int amdgpu_vram_page_split = 512; int amdgpu_vm_update_mode = -1; int amdgpu_exp_hw_support = 0; int amdgpu_dc = -1; +int amdgpu_dc_log = 0; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_no_evict = 0; @@ -211,6 +212,9 @@ module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444); MODULE_PARM_DESC(dc, "Display Core driver (1 = enable, 0 = disable, -1 = auto (default))"); module_param_named(dc, amdgpu_dc, int, 0444); +MODULE_PARM_DESC(dc, "Display Core Log Level (0 = minimal (default), 1 = chatty"); +module_param_named(dc_log, amdgpu_dc_log, int, 0444); + MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 32)"); module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444); -- GitLab From 01a526f3dee9abe1e2db9e37e4ceb4149f8ae77b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 19:33:40 -0400 Subject: [PATCH 0888/2898] drm/amd/display: Pass log_mask from DM Linux and Windows often desire different log levels. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 + .../gpu/drm/amd/display/dc/basics/logger.c | 41 +++---------------- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/include/logger_interface.h | 2 +- .../drm/amd/display/include/logger_types.h | 32 +++++++++++++++ 6 files changed, 42 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index bb4f415746d5..5f4e7dc92797 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -374,6 +374,8 @@ int amdgpu_dm_init(struct amdgpu_device *adev) init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; + init_data.log_mask = DC_DEFAULT_LOG_MASK; + #ifdef ENABLE_FBC if (adev->family == FAMILY_CZ) amdgpu_dm_initialize_fbc(adev); diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 0b17374b1535..5895dd3903a3 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -64,40 +64,9 @@ static const struct dc_log_type_info log_type_info_tbl[] = { }; -#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \ - (1 << LOG_WARNING) | \ - (1 << LOG_EVENT_MODE_SET) | \ - (1 << LOG_EVENT_DETECTION) | \ - (1 << LOG_EVENT_LINK_TRAINING) | \ - (1 << LOG_EVENT_LINK_LOSS) | \ - (1 << LOG_EVENT_UNDERFLOW) | \ - (1 << LOG_RESOURCE) | \ - (1 << LOG_FEATURE_OVERRIDE) | \ - (1 << LOG_DETECTION_EDID_PARSER) | \ - (1 << LOG_DC) | \ - (1 << LOG_HW_HOTPLUG) | \ - (1 << LOG_HW_SET_MODE) | \ - (1 << LOG_HW_RESUME_S3) | \ - (1 << LOG_HW_HPD_IRQ) | \ - (1 << LOG_SYNC) | \ - (1 << LOG_BANDWIDTH_VALIDATION) | \ - (1 << LOG_MST) | \ - (1 << LOG_DETECTION_DP_CAPS) | \ - (1 << LOG_BACKLIGHT)) | \ - (1 << LOG_I2C_AUX) | \ - (1 << LOG_IF_TRACE) | \ - (1 << LOG_DTN) /* | \ - (1 << LOG_DEBUG) | \ - (1 << LOG_BIOS) | \ - (1 << LOG_SURFACE) | \ - (1 << LOG_SCALER) | \ - (1 << LOG_DML) | \ - (1 << LOG_HW_LINK_TRAINING) | \ - (1 << LOG_HW_AUDIO)| \ - (1 << LOG_BANDWIDTH_CALCS)*/ - /* ----------- Object init and destruction ----------- */ -static bool construct(struct dc_context *ctx, struct dal_logger *logger) +static bool construct(struct dc_context *ctx, struct dal_logger *logger, + uint32_t log_mask) { /* malloc buffer and init offsets */ logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; @@ -120,7 +89,7 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger) logger->ctx = ctx; - logger->mask = DC_DEFAULT_LOG_MASK; + logger->mask = log_mask; return true; } @@ -133,14 +102,14 @@ static void destruct(struct dal_logger *logger) } } -struct dal_logger *dal_logger_create(struct dc_context *ctx) +struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask) { /* malloc struct */ struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger)); if (!logger) return NULL; - if (!construct(ctx, logger)) { + if (!construct(ctx, logger, log_mask)) { dm_free(logger); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5579d2167a9a..75a5fa2296d7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -493,7 +493,7 @@ static bool construct(struct dc *dc, dc_ctx->asic_id = init_params->asic_id; /* Create logger */ - logger = dal_logger_create(dc_ctx); + logger = dal_logger_create(dc_ctx, init_params->log_mask); if (!logger) { /* can *not* call logger. call base driver 'print error' */ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1f0521ff4614..9c0e00050753 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -267,6 +267,7 @@ struct dc_init_data { enum dce_environment dce_environment; struct dc_config flags; + uint32_t log_mask; #ifdef ENABLE_FBC uint64_t fbc_gpu_addr; #endif diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 6641e8001e97..5aaf2dacfe38 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -40,7 +40,7 @@ struct dc_state; * */ -struct dal_logger *dal_logger_create(struct dc_context *ctx); +struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask); uint32_t dal_logger_destroy(struct dal_logger **logger); diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 42ffb93e3172..044805ccac25 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -70,6 +70,38 @@ enum dc_log_type { LOG_SECTION_TOTAL_COUNT }; +#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \ + (1 << LOG_WARNING) | \ + (1 << LOG_EVENT_MODE_SET) | \ + (1 << LOG_EVENT_DETECTION) | \ + (1 << LOG_EVENT_LINK_TRAINING) | \ + (1 << LOG_EVENT_LINK_LOSS) | \ + (1 << LOG_EVENT_UNDERFLOW) | \ + (1 << LOG_RESOURCE) | \ + (1 << LOG_FEATURE_OVERRIDE) | \ + (1 << LOG_DETECTION_EDID_PARSER) | \ + (1 << LOG_DC) | \ + (1 << LOG_HW_HOTPLUG) | \ + (1 << LOG_HW_SET_MODE) | \ + (1 << LOG_HW_RESUME_S3) | \ + (1 << LOG_HW_HPD_IRQ) | \ + (1 << LOG_SYNC) | \ + (1 << LOG_BANDWIDTH_VALIDATION) | \ + (1 << LOG_MST) | \ + (1 << LOG_DETECTION_DP_CAPS) | \ + (1 << LOG_BACKLIGHT)) | \ + (1 << LOG_I2C_AUX) | \ + (1 << LOG_IF_TRACE) | \ + (1 << LOG_DTN) /* | \ + (1 << LOG_DEBUG) | \ + (1 << LOG_BIOS) | \ + (1 << LOG_SURFACE) | \ + (1 << LOG_SCALER) | \ + (1 << LOG_DML) | \ + (1 << LOG_HW_LINK_TRAINING) | \ + (1 << LOG_HW_AUDIO)| \ + (1 << LOG_BANDWIDTH_CALCS)*/ + union logger_flags { struct { uint32_t ENABLE_CONSOLE:1; /* Print to console */ -- GitLab From f1ad2f5efd29dc838222f37281675a2623714538 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 20:04:48 -0400 Subject: [PATCH 0889/2898] drm/amd/display: Reduce DC chattiness Log DC init but default log level to 0 (default for amdgpu_dc_log) otherwise. Bug reporters can still make DC more chatty by using the dc_log module param. amdgpu.dc_log = 1 v2: Only provide runtime option, no compile time config Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 74 ++++++++++--------- .../drm/amd/display/include/logger_types.h | 3 + 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5f4e7dc92797..36635486b937 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -334,7 +334,6 @@ int amdgpu_dm_init(struct amdgpu_device *adev) adev->dm.ddev = adev->ddev; adev->dm.adev = adev; - DRM_INFO("DAL is enabled\n"); /* Zero all the fields */ memset(&init_data, 0, sizeof(init_data)); @@ -374,7 +373,10 @@ int amdgpu_dm_init(struct amdgpu_device *adev) init_data.dce_environment = DCE_ENV_PRODUCTION_DRV; - init_data.log_mask = DC_DEFAULT_LOG_MASK; + if (amdgpu_dc_log) + init_data.log_mask = DC_DEFAULT_LOG_MASK; + else + init_data.log_mask = DC_MIN_LOG_MASK; #ifdef ENABLE_FBC if (adev->family == FAMILY_CZ) @@ -384,7 +386,9 @@ int amdgpu_dm_init(struct amdgpu_device *adev) /* Display Core create. */ adev->dm.dc = dc_create(&init_data); - if (!adev->dm.dc) + if (adev->dm.dc) + DRM_INFO("Display Core initialized!\n"); + else DRM_INFO("Display Core failed to initialize!\n"); INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func); @@ -394,7 +398,7 @@ int amdgpu_dm_init(struct amdgpu_device *adev) DRM_ERROR( "amdgpu: failed to initialize freesync_module.\n"); } else - DRM_INFO("amdgpu: freesync_module init done %p.\n", + DRM_DEBUG_DRIVER("amdgpu: freesync_module init done %p.\n", adev->dm.freesync_module); if (amdgpu_dm_initialize_drm_device(adev)) { @@ -418,7 +422,7 @@ int amdgpu_dm_init(struct amdgpu_device *adev) goto error; } - DRM_INFO("KMS initialized.\n"); + DRM_DEBUG_DRIVER("KMS initialized.\n"); return 0; error: @@ -476,7 +480,7 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type == dc_connection_mst_branch) { - DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n", + DRM_DEBUG_DRIVER("DM_MST: starting TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); ret = drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true); @@ -805,12 +809,12 @@ void amdgpu_dm_update_connector_after_detect( if (aconnector->dc_sink == sink) { /* We got a DP short pulse (Link Loss, DP CTS, etc...). * Do nothing!! */ - DRM_INFO("DCHPD: connector_id=%d: dc_sink didn't change.\n", + DRM_DEBUG_DRIVER("DCHPD: connector_id=%d: dc_sink didn't change.\n", aconnector->connector_id); return; } - DRM_INFO("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n", + DRM_DEBUG_DRIVER("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n", aconnector->connector_id, aconnector->dc_sink, sink); mutex_lock(&dev->mode_config.mutex); @@ -912,7 +916,7 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) process_count++; - DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]); + DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]); /* handle HPD short pulse irq */ if (aconnector->mst_mgr.mst_state) drm_dp_mst_hpd_irq( @@ -950,7 +954,7 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) } if (process_count == max_process_count) - DRM_DEBUG_KMS("Loop exceeded max iterations\n"); + DRM_DEBUG_DRIVER("Loop exceeded max iterations\n"); } static void handle_hpd_rx_irq(void *param) @@ -1269,7 +1273,7 @@ void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) if (NULL == dm->backlight_dev) DRM_ERROR("DM: Backlight registration failed!\n"); else - DRM_INFO("DM: Registered Backlight device: %s\n", bl_name); + DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); } #endif @@ -2045,7 +2049,7 @@ static void update_stream_scaling_settings( stream->src = src; stream->dst = dst; - DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", + DRM_DEBUG_DRIVER("Destination Rectangle x:%d y:%d width:%d height:%d\n", dst.x, dst.y, dst.width, dst.height); } @@ -2355,7 +2359,7 @@ static struct dc_stream_state *create_stream_for_sink( * case, we call set mode ourselves to restore the previous mode * and the modelist may not be filled in in time. */ - DRM_INFO("No preferred mode found\n"); + DRM_DEBUG_DRIVER("No preferred mode found\n"); } else { decide_crtc_timing_for_drm_display_mode( &mode, preferred_mode, @@ -2644,7 +2648,7 @@ static struct drm_encoder *best_encoder(struct drm_connector *connector) struct drm_mode_object *obj; struct drm_encoder *encoder; - DRM_DEBUG_KMS("Finding the best encoder\n"); + DRM_DEBUG_DRIVER("Finding the best encoder\n"); /* pick the encoder ids */ if (enc_id) { @@ -2913,7 +2917,7 @@ static int dm_plane_helper_prepare_fb( dm_plane_state_new = to_dm_plane_state(new_state); if (!new_state->fb) { - DRM_DEBUG_KMS("No FB bound\n"); + DRM_DEBUG_DRIVER("No FB bound\n"); return 0; } @@ -3480,7 +3484,7 @@ int amdgpu_dm_connector_init( struct amdgpu_i2c_adapter *i2c; ((struct dc_link *)link)->priv = aconnector; - DRM_DEBUG_KMS("%s()\n", __func__); + DRM_DEBUG_DRIVER("%s()\n", __func__); i2c = create_i2c(link->ddc, link->link_index, &res); aconnector->i2c = i2c; @@ -3721,11 +3725,11 @@ static void handle_cursor_update( if (!plane->state->fb && !old_plane_state->fb) return; - DRM_DEBUG_KMS("%s: crtc_id=%d with size %d to %d\n", - __func__, - amdgpu_crtc->crtc_id, - plane->state->crtc_w, - plane->state->crtc_h); + DRM_DEBUG_DRIVER("%s: crtc_id=%d with size %d to %d\n", + __func__, + amdgpu_crtc->crtc_id, + plane->state->crtc_w, + plane->state->crtc_h); ret = get_cursor_position(plane, crtc, &position); if (ret) @@ -4028,7 +4032,7 @@ void amdgpu_dm_atomic_commit_tail( new_acrtc_state = to_dm_crtc_state(new_state); old_acrtc_state = to_dm_crtc_state(old_crtc_state); - DRM_DEBUG_KMS( + DRM_DEBUG_DRIVER( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", @@ -4046,7 +4050,7 @@ void amdgpu_dm_atomic_commit_tail( if (modeset_required(new_state, new_acrtc_state->stream, old_acrtc_state->stream)) { - DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); + DRM_DEBUG_DRIVER("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); if (!new_acrtc_state->stream) { /* @@ -4064,7 +4068,7 @@ void amdgpu_dm_atomic_commit_tail( * have a sink to keep the pipe running so that * hw state is consistent with the sw state */ - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + DRM_DEBUG_DRIVER("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); continue; } @@ -4091,7 +4095,7 @@ void amdgpu_dm_atomic_commit_tail( acrtc->hw_mode = crtc->state->mode; crtc->hwmode = crtc->state->mode; } else if (modereset_required(new_state)) { - DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); + DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ if (old_acrtc_state->stream) @@ -4116,7 +4120,7 @@ void amdgpu_dm_atomic_commit_tail( &new_crtcs[i]->base, false); if (!aconnector) { - DRM_INFO("Atomic commit: Failed to find connector for acrtc id:%d " + DRM_DEBUG_DRIVER("Atomic commit: Failed to find connector for acrtc id:%d " "skipping freesync init\n", new_crtcs[i]->crtc_id); continue; @@ -4425,7 +4429,7 @@ static int dm_update_crtcs_state( */ if (!new_stream) { - DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", + DRM_DEBUG_DRIVER("%s: Failed to create new stream for crtc %d\n", __func__, acrtc->base.base.id); break; } @@ -4436,7 +4440,7 @@ static int dm_update_crtcs_state( crtc_state->mode_changed = false; - DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d", + DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", crtc_state->mode_changed); } @@ -4444,7 +4448,7 @@ static int dm_update_crtcs_state( if (!drm_atomic_crtc_needs_modeset(crtc_state)) goto next_crtc; - DRM_DEBUG_KMS( + DRM_DEBUG_DRIVER( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", @@ -4462,7 +4466,7 @@ static int dm_update_crtcs_state( if (!old_acrtc_state->stream) goto next_crtc; - DRM_DEBUG_KMS("Disabling DRM crtc: %d\n", + DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n", crtc->base.id); /* i.e. reset mode */ @@ -4492,7 +4496,7 @@ static int dm_update_crtcs_state( new_acrtc_state->stream = new_stream; dc_stream_retain(new_stream); - DRM_DEBUG_KMS("Enabling DRM crtc: %d\n", + DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", crtc->base.id); if (!dc_add_stream_to_ctx( @@ -4567,7 +4571,7 @@ static int dm_update_planes_state( if (!old_acrtc_state->stream) continue; - DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n", + DRM_DEBUG_DRIVER("Disabling DRM plane: %d on DRM crtc %d\n", plane->base.id, old_plane_crtc->base.id); if (!dc_remove_plane_from_context( @@ -4605,7 +4609,7 @@ static int dm_update_planes_state( new_dm_plane_state->dc_state = dc_create_plane_state(dc); - DRM_DEBUG_KMS("Enabling DRM plane: %d on DRM crtc %d\n", + DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", plane->base.id, new_plane_crtc->base.id); if (!new_dm_plane_state->dc_state) { @@ -4764,9 +4768,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, fail: if (ret == -EDEADLK) - DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); + DRM_DEBUG_DRIVER("Atomic check stopped due to to deadlock.\n"); else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS) - DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n"); + DRM_DEBUG_DRIVER("Atomic check stopped due to to signal.\n"); else DRM_ERROR("Atomic check failed with err: %d \n", ret); diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 044805ccac25..1f22e84cedb9 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -70,6 +70,9 @@ enum dc_log_type { LOG_SECTION_TOTAL_COUNT }; +#define DC_MIN_LOG_MASK ((1 << LOG_ERROR) | \ + (1 << LOG_DETECTION_EDID_PARSER)) + #define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \ (1 << LOG_WARNING) | \ (1 << LOG_EVENT_MODE_SET) | \ -- GitLab From 4a6cee2ca142615970fa3334191e992e7fb51159 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Sun, 24 Sep 2017 14:31:51 -0400 Subject: [PATCH 0890/2898] drm/amd/display: Remove unused dc_validate_guaranteed function It got refactored away and was never cleaned. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 34 ------------------------ 1 file changed, 34 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 75a5fa2296d7..58c5083bef2a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -651,40 +651,6 @@ void dc_destroy(struct dc **dc) *dc = NULL; } -bool dc_validate_guaranteed( - struct dc *dc, - struct dc_stream_state *stream) -{ - enum dc_status result = DC_ERROR_UNEXPECTED; - struct dc_state *context; - - if (!dc_validate_stream(dc, stream)) - return false; - - context = dm_alloc(sizeof(struct dc_state)); - if (context == NULL) - goto context_alloc_fail; - - dc_resource_state_construct(dc, dc->current_state); - - atomic_inc(&context->ref_count); - - result = dc->res_pool->funcs->validate_guaranteed( - dc, stream, context); - - dc_release_state(context); - -context_alloc_fail: - if (result != DC_OK) { - dm_logger_write(dc->ctx->logger, LOG_WARNING, - "%s:guaranteed validation failed, dc_status:%d\n", - __func__, - result); - } - - return (result == DC_OK); -} - static void program_timing_sync( struct dc *dc, struct dc_state *ctx) -- GitLab From 2c8f195adf21430e4e8bbd13942826ccf8fa225c Mon Sep 17 00:00:00 2001 From: Shirish S Date: Tue, 26 Sep 2017 12:26:41 +0530 Subject: [PATCH 0891/2898] drm/amd/display: don't clean-up bottom pipe plane_state In the scenario of setting underlay, dc_validate_global_state() is called after constructing the context with all relevant bottom_pipe related configurations in dm_update_planes_state(). Currently, in dc_validate_global_state(), without checking for bottom_pipe's existence, the pipe_ctx structure is initialised to 0, hence nullyfying the plane_state of bottom_pipe which shall be accessed in populate_initial_data() called from bw_calcs(). Due to this null pointer access kernel panics and leads to reboot when underlay is tried to set. This patch fixes the issue by no longer clearing the top_pipe. This workaround is no longer required. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 15b627548cd2..dcfdfebd5c62 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1729,14 +1729,6 @@ bool dc_validate_global_state( dc, new_ctx) != DC_OK) return false; - /* TODO without this SWDEV-114774 brakes */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->top_pipe) - memset(pipe_ctx, 0, sizeof(*pipe_ctx)); - } - for (i = 0; new_ctx && i < new_ctx->stream_count; i++) { struct dc_stream_state *stream = new_ctx->streams[i]; -- GitLab From fff0925832368d55d2d50ccfedc3fb0887721627 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 18 Sep 2017 15:19:31 -0400 Subject: [PATCH 0892/2898] drm/amd/display: fix pflip irq registor for raven The pflip registor index was incorrect, this was overriding the macro and caused a dummy irq call. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c index 7577e2903787..be59f0a654e2 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -272,8 +272,8 @@ irq_source_info_dcn10[DAL_IRQ_SOURCES_NUMBER] = { pflip_int_entry(1), pflip_int_entry(2), pflip_int_entry(3), - [DC_IRQ_SOURCE_PFLIP4] = dummy_irq_entry(), [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(), + [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(), [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), gpio_pad_int_entry(0), gpio_pad_int_entry(1), -- GitLab From dfbf0c14dd75d3b15f65478f10f373aa83042a50 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 2 Jun 2017 14:38:03 -0400 Subject: [PATCH 0893/2898] drm/amdgpu: drop experimental flag for vega10 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 7e753969506b..96774ce00124 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -519,15 +519,15 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x6997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, {0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, /* Vega 10 */ - {0x1002, 0x6860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6861, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6862, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6863, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6864, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6867, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x6868, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, + {0x1002, 0x6860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6861, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6862, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6863, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6864, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6867, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x6868, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, + {0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10}, /* Raven */ {0x1002, 0x15dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU|AMD_EXP_HW_SUPPORT}, -- GitLab From 4c05984459ec55056857bee32ecb01653c6b8f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20Belleng=C3=A9?= Date: Sat, 23 Sep 2017 18:23:37 +0200 Subject: [PATCH 0894/2898] platform/x86: asus-wmi: Add lightbar led support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some Asus laptops (ROG series for example) are provided with a lightbar behind the monitor. This patch make possible to switch it on and off. This lightbar works exactly like any other led. Signed-off-by: Maxime Bellengé [dvhart: fix commit message format and variable declaration order] Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/asus-wmi.c | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 48e1541dc8d4..a32c5c00e0e7 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -119,6 +119,7 @@ MODULE_LICENSE("GPL"); #define ASUS_WMI_DEVID_BRIGHTNESS 0x00050012 #define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 #define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */ +#define ASUS_WMI_DEVID_LIGHTBAR 0x00050025 /* Misc */ #define ASUS_WMI_DEVID_CAMERA 0x00060013 @@ -148,6 +149,7 @@ MODULE_LICENSE("GPL"); #define ASUS_WMI_DSTS_BIOS_BIT 0x00040000 #define ASUS_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF #define ASUS_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00 +#define ASUS_WMI_DSTS_LIGHTBAR_MASK 0x0000000F #define ASUS_FAN_DESC "cpu_fan" #define ASUS_FAN_MFUN 0x13 @@ -222,10 +224,13 @@ struct asus_wmi { int tpd_led_wk; struct led_classdev kbd_led; int kbd_led_wk; + struct led_classdev lightbar_led; + int lightbar_led_wk; struct workqueue_struct *led_workqueue; struct work_struct tpd_led_work; struct work_struct kbd_led_work; struct work_struct wlan_led_work; + struct work_struct lightbar_led_work; struct asus_rfkill wlan; struct asus_rfkill bluetooth; @@ -567,6 +572,48 @@ static enum led_brightness wlan_led_get(struct led_classdev *led_cdev) return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK; } +static void lightbar_led_update(struct work_struct *work) +{ + struct asus_wmi *asus; + int ctrl_param; + + asus = container_of(work, struct asus_wmi, lightbar_led_work); + + ctrl_param = asus->lightbar_led_wk; + asus_wmi_set_devstate(ASUS_WMI_DEVID_LIGHTBAR, ctrl_param, NULL); +} + +static void lightbar_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct asus_wmi *asus; + + asus = container_of(led_cdev, struct asus_wmi, lightbar_led); + + asus->lightbar_led_wk = !!value; + queue_work(asus->led_workqueue, &asus->lightbar_led_work); +} + +static enum led_brightness lightbar_led_get(struct led_classdev *led_cdev) +{ + struct asus_wmi *asus; + u32 result; + + asus = container_of(led_cdev, struct asus_wmi, lightbar_led); + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_LIGHTBAR, &result); + + return result & ASUS_WMI_DSTS_LIGHTBAR_MASK; +} + +static int lightbar_led_presence(struct asus_wmi *asus) +{ + u32 result; + + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_LIGHTBAR, &result); + + return result & ASUS_WMI_DSTS_PRESENCE_BIT; +} + static void asus_wmi_led_exit(struct asus_wmi *asus) { if (!IS_ERR_OR_NULL(asus->kbd_led.dev)) @@ -575,6 +622,8 @@ static void asus_wmi_led_exit(struct asus_wmi *asus) led_classdev_unregister(&asus->tpd_led); if (!IS_ERR_OR_NULL(asus->wlan_led.dev)) led_classdev_unregister(&asus->wlan_led); + if (!IS_ERR_OR_NULL(asus->lightbar_led.dev)) + led_classdev_unregister(&asus->lightbar_led); if (asus->led_workqueue) destroy_workqueue(asus->led_workqueue); } @@ -630,6 +679,20 @@ static int asus_wmi_led_init(struct asus_wmi *asus) rv = led_classdev_register(&asus->platform_device->dev, &asus->wlan_led); + if (rv) + goto error; + } + + if (lightbar_led_presence(asus)) { + INIT_WORK(&asus->lightbar_led_work, lightbar_led_update); + + asus->lightbar_led.name = "asus::lightbar"; + asus->lightbar_led.brightness_set = lightbar_led_set; + asus->lightbar_led.brightness_get = lightbar_led_get; + asus->lightbar_led.max_brightness = 1; + + rv = led_classdev_register(&asus->platform_device->dev, + &asus->lightbar_led); } error: -- GitLab From 8834b0950156de37acccd422263d4da3c94495e6 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 15:46:53 +0200 Subject: [PATCH 0895/2898] clk: samsung: Delete a memory allocation error message in clk-cpu.c Omit an extra message for a memory allocation failure in exynos_register_cpu_clock() function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-cpu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c index 6686e8ba61f9..d2c99d8916b8 100644 --- a/drivers/clk/samsung/clk-cpu.c +++ b/drivers/clk/samsung/clk-cpu.c @@ -457,8 +457,6 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, cpuclk->cfg = kmemdup(cfg, sizeof(*cfg) * num_cfgs, GFP_KERNEL); if (!cpuclk->cfg) { - pr_err("%s: could not allocate memory for cpuclk data\n", - __func__); ret = -ENOMEM; goto unregister_clk_nb; } -- GitLab From 72e83204b7ec3d698189117d980dc7c15d07af8a Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 26 Sep 2017 13:49:59 -0500 Subject: [PATCH 0896/2898] platform/x86: dell-wmi: Label driver as handling notifications This driver serves the purpose of responding to WMI based notifications from the DELL_EVENT_GUID (9DBB5994-A997-11DA-B012-B622A1EF5492). Other GUIDs will be handled by separate drivers. Update the language used by this driver to avoid future confusion. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- MAINTAINERS | 2 +- drivers/platform/x86/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a6a5746ced9d..08b96f77f618 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3996,7 +3996,7 @@ S: Maintained F: Documentation/dcdbas.txt F: drivers/firmware/dcdbas.* -DELL WMI EXTRAS DRIVER +DELL WMI NOTIFICATIONS DRIVER M: Matthew Garrett M: Pali Rohár S: Maintained diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f401ae463e9b..1f7959ff055c 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -116,7 +116,7 @@ config DELL_LAPTOP laptops (except for some models covered by the Compal driver). config DELL_WMI - tristate "Dell WMI extras" + tristate "Dell WMI notifications" depends on ACPI_WMI depends on DMI depends on INPUT -- GitLab From 9808f3628ce43fafbb6f8eb8d347f38ba9b275ba Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 26 Sep 2017 13:50:01 -0500 Subject: [PATCH 0897/2898] platform/x86: dell-wmi: Do not match on descriptor GUID modalias The descriptor GUID is not used to indicate that WMI notifications in the dell-wmi driver work properly. As such a modalias should not be present that causes this driver to load on systems with this GUID. Signed-off-by: Mario Limonciello Reviewed-by: Pali Pohar Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-wmi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 28d9f8696081..1fbef560ca67 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -51,7 +51,6 @@ MODULE_LICENSE("GPL"); static bool wmi_requires_smbios_request; MODULE_ALIAS("wmi:"DELL_EVENT_GUID); -MODULE_ALIAS("wmi:"DELL_DESCRIPTOR_GUID); struct dell_wmi_priv { struct input_dev *input_dev; -- GitLab From 7b4dd21630afa835a907cd030fd4e2af6849c6a9 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 26 Sep 2017 13:50:02 -0500 Subject: [PATCH 0898/2898] platform/x86: dell-smbios: Add pr_fmt definition to driver pr_fmt provides formatting to be used by the driver when displaying errors and messages. Signed-off-by: Mario Limonciello Reviewed-by: Pali Pohar Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-smbios.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index 0a5723468bff..e9b1ca07c872 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -12,6 +12,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include -- GitLab From b60ee4e0918db95a1e458ae160488368c45a0687 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 26 Sep 2017 13:50:03 -0500 Subject: [PATCH 0899/2898] platform/x86: wmi: Sort include list The include list is randomly assembled right now. Sort in alphabetical order. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 0765b1797d4c..e19b074df01d 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -33,17 +33,17 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include +#include #include +#include +#include #include -#include -#include #include #include -#include +#include +#include #include +#include ACPI_MODULE_NAME("wmi"); MODULE_AUTHOR("Carlos Corbacho"); -- GitLab From 303d1fcc0bf07129bc05a61632fad9f7064b671f Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 26 Sep 2017 13:50:04 -0500 Subject: [PATCH 0900/2898] platform/x86: wmi: Cleanup exit routine in reverse order of init The initialize routine is: * class -> bus -> platform The exit routine is: * platform -> class -> bus Fix the exit routine to be: * platform -> bus -> class Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index e19b074df01d..acbc2b02db3d 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -1264,8 +1264,8 @@ static int __init acpi_wmi_init(void) static void __exit acpi_wmi_exit(void) { platform_driver_unregister(&acpi_wmi_driver); - class_unregister(&wmi_bus_class); bus_unregister(&wmi_bus_type); + class_unregister(&wmi_bus_class); } subsys_initcall(acpi_wmi_init); -- GitLab From 7b11e8989618581bc0226ad313264cdc05d48d86 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 26 Sep 2017 13:50:05 -0500 Subject: [PATCH 0901/2898] platform/x86: wmi: Destroy on cleanup rather than unregister device_create documentation says to cleanup using device_destroy Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index acbc2b02db3d..7a05843aff19 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -1145,7 +1145,7 @@ static int acpi_wmi_remove(struct platform_device *device) acpi_remove_address_space_handler(acpi_device->handle, ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); wmi_free_devices(acpi_device); - device_unregister((struct device *)dev_get_drvdata(&device->dev)); + device_destroy(&wmi_bus_class, MKDEV(0, 0)); return 0; } @@ -1199,7 +1199,7 @@ static int acpi_wmi_probe(struct platform_device *device) return 0; err_remove_busdev: - device_unregister(wmi_bus_dev); + device_destroy(&wmi_bus_class, MKDEV(0, 0)); err_remove_notify_handler: acpi_remove_notify_handler(acpi_device->handle, ACPI_DEVICE_NOTIFY, -- GitLab From 01c3f0a42a2a0ff0c3fed80a1a25f2641ae72554 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 10 Sep 2017 13:44:47 -0700 Subject: [PATCH 0902/2898] sparc64: mmu_context: Add missing include files Fix the following build errors. In file included from arch/sparc/include/asm/mmu_context.h:4:0, from include/linux/mmu_context.h:4, from drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h:29, from drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c:23: arch/sparc/include/asm/mmu_context_64.h:22:37: error: unknown type name 'per_cpu_secondary_mm' arch/sparc/include/asm/mmu_context_64.h: In function 'switch_mm': arch/sparc/include/asm/mmu_context_64.h:79:2: error: implicit declaration of function 'smp_processor_id' Fixes: 70539bd79500 ("drm/amd: Update MEC HQD loading code for KFD") Signed-off-by: Guenter Roeck Acked-by: Oded Gabbay Signed-off-by: David S. Miller --- arch/sparc/include/asm/mmu_context_64.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h index 87841d687f8d..a34315e1f0ed 100644 --- a/arch/sparc/include/asm/mmu_context_64.h +++ b/arch/sparc/include/asm/mmu_context_64.h @@ -7,9 +7,11 @@ #include #include +#include #include #include +#include static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { -- GitLab From 92c807067e9ade7d41f453befe560a362e95be7f Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Mon, 18 Sep 2017 19:58:21 +0200 Subject: [PATCH 0903/2898] sparc: time: Remove unneeded linux/miscdevice.h include arch/sparc/kernel/time_64.c does not contain any miscdevice so the inclusion of linux/miscdevice.h is unnecessary. Signed-off-by: Corentin Labbe Signed-off-by: David S. Miller --- arch/sparc/kernel/time_64.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 564f0e46ffd4..5c8524ff09d9 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include -- GitLab From da61e7308df868c20a41861c0a11f6eefd822993 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Mon, 18 Sep 2017 20:10:36 +0200 Subject: [PATCH 0904/2898] sbus: char: Move D7S_MINOR to include/linux/miscdevice.h This patch move the define for D7S_MINOR to include/linux/miscdevice.h. It's better that all minor number are in the same place. Signed-off-by: Corentin Labbe Signed-off-by: David S. Miller --- drivers/sbus/char/display7seg.c | 1 - include/linux/miscdevice.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index f32765d3cbd8..5c8ed7350a04 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -22,7 +22,6 @@ #include -#define D7S_MINOR 193 #define DRIVER_NAME "d7s" #define PFX DRIVER_NAME ": " diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 58751eae5f77..05c3892b3e92 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -35,6 +35,7 @@ #define HWRNG_MINOR 183 #define MICROCODE_MINOR 184 #define IRNET_MINOR 187 +#define D7S_MINOR 193 #define VFIO_MINOR 196 #define TUN_MINOR 200 #define CUSE_MINOR 203 -- GitLab From 23198ddffb6cddb5d5824230af4dd4b46e4046a4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Sep 2017 22:38:19 -0700 Subject: [PATCH 0905/2898] sparc32: Add cmpxchg64(). This fixes the build with i40e driver enabled. Reported-by: Guenter Roeck Signed-off-by: David S. Miller --- arch/sparc/include/asm/cmpxchg_32.h | 3 +++ arch/sparc/lib/atomic32.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h index 83ffb83c5397..a0101a58fd3f 100644 --- a/arch/sparc/include/asm/cmpxchg_32.h +++ b/arch/sparc/include/asm/cmpxchg_32.h @@ -62,6 +62,9 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size) (unsigned long)_n_, sizeof(*(ptr))); \ }) +u64 __cmpxchg_u64(u64 *ptr, u64 old, u64 new); +#define cmpxchg64(ptr, old, new) __cmpxchg_u64(ptr, old, new) + #include /* diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c index 2c373329d5cb..ddacb5aeb424 100644 --- a/arch/sparc/lib/atomic32.c +++ b/arch/sparc/lib/atomic32.c @@ -172,6 +172,20 @@ unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new) } EXPORT_SYMBOL(__cmpxchg_u32); +u64 __cmpxchg_u64(u64 *ptr, u64 old, u64 new) +{ + unsigned long flags; + u64 prev; + + spin_lock_irqsave(ATOMIC_HASH(ptr), flags); + if ((prev = *ptr) == old) + *ptr = new; + spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); + + return prev; +} +EXPORT_SYMBOL(__cmpxchg_u64); + unsigned long __xchg_u32(volatile u32 *ptr, u32 new) { unsigned long flags; -- GitLab From 74717b28cb32e1ad3c1042cafd76b264c8c0f68d Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 28 Sep 2017 13:53:27 +0200 Subject: [PATCH 0906/2898] rtc: set the alarm to the next expiring timer If there is any non expired timer in the queue, the RTC alarm is never set. This is an issue when adding a timer that expires before the next non expired timer. Ensure the RTC alarm is set in that case. Fixes: 2b2f5ff00f63 ("rtc: interface: ignore expired timers when enqueuing new timers") Signed-off-by: Alexandre Belloni --- drivers/rtc/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8cec9a02c0b8..9eb32ead63db 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -779,7 +779,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) } timerqueue_add(&rtc->timerqueue, &timer->node); - if (!next) { + if (!next || ktime_before(timer->node.expires, next->expires)) { struct rtc_wkalrm alarm; int err; alarm.time = rtc_ktime_to_tm(timer->node.expires); -- GitLab From 9edb39d750c0a9a6f7dafb8d9d15e63f6d44b68c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 27 Sep 2017 11:38:17 +0200 Subject: [PATCH 0907/2898] clk: rockchip: Remove superfluous error message in rockchip_clk_register_cpuclk() Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-cpu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 0e09684d43a5..32c19c0f1e14 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -322,8 +322,6 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, sizeof(*rates) * nrates, GFP_KERNEL); if (!cpuclk->rate_table) { - pr_err("%s: could not allocate memory for cpuclk rates\n", - __func__); ret = -ENOMEM; goto unregister_notifier; } -- GitLab From 168bcbcb1c72a4753fc64ef384b46e330bfccd08 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 25 Sep 2017 10:10:51 +0200 Subject: [PATCH 0908/2898] clk: renesas: mstp: Delete error messages for failed memory allocations The script "checkpatch.pl" pointed information out like the following. WARNING: Possible unnecessary 'out of memory' message Thus fix affected source code places. Signed-off-by: Markus Elfring Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/clk-mstp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index 500a9e4e03c4..c944cc421e30 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c @@ -156,10 +156,8 @@ static struct clk * __init cpg_mstp_clock_register(const char *name, struct clk *clk; clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) { - pr_err("%s: failed to allocate MSTP clock.\n", __func__); + if (!clock) return ERR_PTR(-ENOMEM); - } init.name = name; init.ops = &cpg_mstp_clock_ops; @@ -196,7 +194,6 @@ static void __init cpg_mstp_clocks_init(struct device_node *np) if (group == NULL || clks == NULL) { kfree(group); kfree(clks); - pr_err("%s: failed to allocate group\n", __func__); return; } -- GitLab From b4021bbe10017d994e5a96ebfd2677bbaf2b37e0 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 25 Sep 2017 10:10:51 +0200 Subject: [PATCH 0909/2898] clk: renesas: rcar-gen2: Delete error message for failed memory allocation The script "checkpatch.pl" pointed information out like the following. WARNING: Possible unnecessary 'out of memory' message Thus fix affected source code places. Signed-off-by: Markus Elfring Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/clk-rcar-gen2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c index 0b2e56d0d94b..d14cbe1ca29a 100644 --- a/drivers/clk/renesas/clk-rcar-gen2.c +++ b/drivers/clk/renesas/clk-rcar-gen2.c @@ -423,7 +423,6 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) /* We're leaking memory on purpose, there's no point in cleaning * up as the system won't boot anyway. */ - pr_err("%s: failed to allocate cpg\n", __func__); return; } -- GitLab From d34cb808402898e53b9a9bcbbedd01667a78723b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 25 Sep 2017 11:01:31 -0700 Subject: [PATCH 0910/2898] libnvdimm, dimm: clear 'locked' status on successful DIMM enable If we successfully enable a DIMM then it must not be locked and we can clear the label-read failure condition. Otherwise, we need to reload the entire bus provider driver to achieve the same effect, and that can disrupt unrelated DIMMs and namespaces. Fixes: 9d62ed965118 ("libnvdimm: handle locked label storage areas") Cc: Signed-off-by: Dan Williams --- drivers/nvdimm/dimm.c | 1 + drivers/nvdimm/dimm_devs.c | 7 +++++++ drivers/nvdimm/nd.h | 1 + 3 files changed, 9 insertions(+) diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c index e0f0e3ce1a32..98466d762c8f 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c @@ -68,6 +68,7 @@ static int nvdimm_probe(struct device *dev) rc = nd_label_reserve_dpa(ndd); if (ndd->ns_current >= 0) nvdimm_set_aliasing(dev); + nvdimm_clear_locked(dev); nvdimm_bus_unlock(dev); if (rc) diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index f0d1b7e5de01..5f1385b96b13 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -200,6 +200,13 @@ void nvdimm_set_locked(struct device *dev) set_bit(NDD_LOCKED, &nvdimm->flags); } +void nvdimm_clear_locked(struct device *dev) +{ + struct nvdimm *nvdimm = to_nvdimm(dev); + + clear_bit(NDD_LOCKED, &nvdimm->flags); +} + static void nvdimm_release(struct device *dev) { struct nvdimm *nvdimm = to_nvdimm(dev); diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 9c758a91372b..156be00e1f76 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -254,6 +254,7 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, unsigned int len); void nvdimm_set_aliasing(struct device *dev); void nvdimm_set_locked(struct device *dev); +void nvdimm_clear_locked(struct device *dev); struct nd_btt *to_nd_btt(struct device *dev); struct nd_gen_sb { -- GitLab From d083e6dae083ba3576ee454d5cab4491d9c21ec5 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 25 Sep 2017 16:11:13 +0530 Subject: [PATCH 0911/2898] dax: pr_err() strings should end with newlines pr_err() messages should terminated with a new-line to avoid other messages being concatenated onto the end. Signed-off-by: Arvind Yadav Signed-off-by: Dan Williams --- drivers/dax/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 557b93703532..30d8a5aedd23 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -118,7 +118,7 @@ int __bdev_dax_supported(struct super_block *sb, int blocksize) put_dax(dax_dev); if (len < 1) { - pr_err("VFS (%s): error: dax access failed (%ld)", + pr_err("VFS (%s): error: dax access failed (%ld)\n", sb->s_id, len); return len < 0 ? len : -EIO; } -- GitLab From b8ff981f88df03c72a4de2f6eaa9ce447a10ac03 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 26 Sep 2017 11:17:52 -0700 Subject: [PATCH 0912/2898] libnvdimm, region : make 'resource' attribute only readable by root For the same reason that /proc/iomem returns 0's for non-root readers and acpi tables are root-only, make the 'resource' attribute for region devices only readable by root. Otherwise we disclose physical address information. Fixes: 802f4be6feee ("libnvdimm: Add 'resource' sysfs attribute to regions") Cc: Cc: Dave Jiang Cc: Johannes Thumshirn Reported-by: Dave Hansen Signed-off-by: Dan Williams --- drivers/nvdimm/region_devs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 829d760f651c..abaf38c61220 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -562,8 +562,12 @@ static umode_t region_visible(struct kobject *kobj, struct attribute *a, int n) if (!is_nd_pmem(dev) && a == &dev_attr_badblocks.attr) return 0; - if (!is_nd_pmem(dev) && a == &dev_attr_resource.attr) - return 0; + if (a == &dev_attr_resource.attr) { + if (is_nd_pmem(dev)) + return 0400; + else + return 0; + } if (a == &dev_attr_deep_flush.attr) { int has_flush = nvdimm_has_flush(nd_region); -- GitLab From c1fb3542074fd0c4d901d778bd52455111e4eb6f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 26 Sep 2017 11:21:24 -0700 Subject: [PATCH 0913/2898] libnvdimm, namespace: make 'resource' attribute only readable by root For the same reason that /proc/iomem returns 0's for non-root readers and acpi tables are root-only, make the 'resource' attribute for namespace devices only readable by root. Otherwise we disclose physical address information. Fixes: bf9bccc14c05 ("libnvdimm: pmem label sets and namespace instantiation") Cc: Reported-by: Dave Hansen Signed-off-by: Dan Williams --- drivers/nvdimm/namespace_devs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index 3e4d1e7998da..0af988739a06 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -1620,7 +1620,7 @@ static umode_t namespace_visible(struct kobject *kobj, if (a == &dev_attr_resource.attr) { if (is_namespace_blk(dev)) return 0; - return a->mode; + return 0400; } if (is_namespace_pmem(dev) || is_namespace_blk(dev)) { -- GitLab From 26417ae4fc6108f8db436f24108b08f68bdc520e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 26 Sep 2017 13:07:06 -0700 Subject: [PATCH 0914/2898] libnvdimm, pfn: make 'resource' attribute only readable by root For the same reason that /proc/iomem returns 0's for non-root readers and acpi tables are root-only, make the 'resource' attribute for pfn devices only readable by root. Otherwise we disclose physical address information. Fixes: f6ed58c70d14 ("libnvdimm, pfn: 'resource'-address and 'size'...") Cc: Reported-by: Dave Hansen Signed-off-by: Dan Williams --- drivers/nvdimm/pfn_devs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 9576c444f0ab..65cc171c721d 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -282,8 +282,16 @@ static struct attribute *nd_pfn_attributes[] = { NULL, }; +static umode_t pfn_visible(struct kobject *kobj, struct attribute *a, int n) +{ + if (a == &dev_attr_resource.attr) + return 0400; + return a->mode; +} + struct attribute_group nd_pfn_attribute_group = { .attrs = nd_pfn_attributes, + .is_visible = pfn_visible, }; static const struct attribute_group *nd_pfn_attribute_groups[] = { -- GitLab From b18d4b8a25af6fe83d7692191d6ff962ea611c4f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 26 Sep 2017 11:41:28 -0700 Subject: [PATCH 0915/2898] libnvdimm, namespace: fix label initialization to use valid seq numbers The set of valid sequence numbers is {1,2,3}. The specification indicates that an implementation should consider 0 a sign of a critical error: UEFI 2.7: 13.19 NVDIMM Label Protocol Software never writes the sequence number 00, so a correctly check-summed Index Block with this sequence number probably indicates a critical error. When software discovers this case it treats it as an invalid Index Block indication. While the expectation is that the invalid block is just thrown away, the Robustness Principle says we should fix this to make both sequence numbers valid. Fixes: f524bf271a5c ("libnvdimm: write pmem label set") Cc: Reported-by: Juston Li Signed-off-by: Dan Williams --- drivers/nvdimm/label.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c index 9c5f108910e3..de66c02f6140 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c @@ -1050,7 +1050,7 @@ static int init_labels(struct nd_mapping *nd_mapping, int num_labels) nsindex = to_namespace_index(ndd, 0); memset(nsindex, 0, ndd->nsarea.config_size); for (i = 0; i < 2; i++) { - int rc = nd_label_write_index(ndd, i, i*2, ND_NSINDEX_INIT); + int rc = nd_label_write_index(ndd, i, 3 - i, ND_NSINDEX_INIT); if (rc) return rc; -- GitLab From a586cb4937fa328a857c8d7fbefb986d347bd4a7 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 22 Sep 2017 16:46:26 +0900 Subject: [PATCH 0916/2898] nfit_test Make private definitions to command emulation Move private definitions to command emulation. These definitions were originally defined at include/uapi/linux/ndctl.h, but they are used at only nfit_test emulation now. Signed-off-by: Yasunori Goto Reviewed-by: Vishal Verma Signed-off-by: Dan Williams --- tools/testing/nvdimm/test/nfit_test.h | 47 +++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h index d3d63dd5ed38..52c83be9dcfa 100644 --- a/tools/testing/nvdimm/test/nfit_test.h +++ b/tools/testing/nvdimm/test/nfit_test.h @@ -32,6 +32,53 @@ struct nfit_test_resource { void *buf; }; +#define ND_TRANSLATE_SPA_STATUS_INVALID_SPA 2 + +/* nfit commands */ +enum nfit_cmd_num { + NFIT_CMD_TRANSLATE_SPA = 5, + NFIT_CMD_ARS_INJECT_SET = 7, + NFIT_CMD_ARS_INJECT_CLEAR = 8, + NFIT_CMD_ARS_INJECT_GET = 9, +}; + +struct nd_cmd_translate_spa { + __u64 spa; + __u32 status; + __u8 flags; + __u8 _reserved[3]; + __u64 translate_length; + __u32 num_nvdimms; + struct nd_nvdimm_device { + __u32 nfit_device_handle; + __u32 _reserved; + __u64 dpa; + } __packed devices[0]; + +} __packed; + +struct nd_cmd_ars_err_inj { + __u64 err_inj_spa_range_base; + __u64 err_inj_spa_range_length; + __u8 err_inj_options; + __u32 status; +} __packed; + +struct nd_cmd_ars_err_inj_clr { + __u64 err_inj_clr_spa_range_base; + __u64 err_inj_clr_spa_range_length; + __u32 status; +} __packed; + +struct nd_cmd_ars_err_inj_stat { + __u32 status; + __u32 inj_err_rec_count; + struct nd_error_stat_query_record { + __u64 err_inj_stat_spa_range_base; + __u64 err_inj_stat_spa_range_length; + } __packed record[0]; +} __packed; + union acpi_object; typedef void *acpi_handle; -- GitLab From 82b400a62f2fd42b87f91a298c5641d0ead99251 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Sep 2017 12:15:50 +0200 Subject: [PATCH 0917/2898] drm/amd: DC pull request review Ok, here's one more attempt at scrolling through 130k diff. Overall verdict from me is that DC is big project, and like any big project it's never done. So at least for me the goal isn't to make things perfect, becaue if that's the hoop to jump through we wouldn't have any gpu drivers at all. More important is whether merging a new driver base will benefit the overall subsystem, and here this primarily means whether the DC team understands how upstream works and is designed, and whether the code is largely aligned with upstream (especially the atomic modeset) architecture. Looking back over the last two years I think that's the case now, so Acked-by: Daniel Vetter for merging this pull. While scrolling through the pull I spotted a bunch more things that should be refactored, but most of these will be a real pain with DC is out of tree, and much easier in tree since in many of these areas the in-tree helpers aren't up to snuff yet for what DC needs. That kind of work is best done when there's one tree with everything integrated. That's also why I think we should merge DC into drm-next directly, so we can get started on the integration polish right away. That has a bit higher risk of Linus having a spazz, so here's my recommendation for merging: - There's a few additions to drm_dp_helper.h sprinkled all over the pull. I think those should be put into a patch of it's own, and merged first. No need to rebase DC, git merge will dtrt and not end up with duplicates. - dm_alloc/realloc/free is something Dave Airlie noticed, and I agree it's an easy red flag that might upset Linus. cocci can fix this easy, so no real problem I think to patch up in one big patch (I thought we've had a "remove malloc wrappers" todo item in the very first review, apparently there was more than one such wrapper). - The history is huge, but AMD folks want to keep it if possible, and I see the value in that. Would be good to get an ack from Linus for that (but shouldn't be an issue, not the first time we've merged the full history of out-of-tree work). Short&longer term TODO items are still tracked, might be a good idea to integrate those the overall drm todo in our gpu documentation, for more visibility. So in a way this is kinda like staging, except not with the horribly broken process of having an entirely separate tree for staging drivers which just makes refactoring needlessly painful (which defeats the point of staging really). So staging-within-the-subsystem. We've had that before, with early nouveau. And yes some of the files are utterly horrible to read and not anything close to kernel coding style standards. But that's the point, they're essentially gospel from hw engineers that happens to be parseable by gcc. Signed-off-by: Daniel Vetter Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/TODO | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpu/drm/amd/display/TODO b/drivers/gpu/drm/amd/display/TODO index 2737873db12d..eea645b102a1 100644 --- a/drivers/gpu/drm/amd/display/TODO +++ b/drivers/gpu/drm/amd/display/TODO @@ -79,3 +79,34 @@ TODOs 12. drm_modeset_lock in MST should no longer be needed in recent kernels * Adopt appropriate locking scheme + +13. get_modes and best_encoder callbacks look a bit funny. Can probably rip out +a few indirections, and consider removing entirely and using the +drm_atomic_helper_best_encoder default behaviour. + +14. core/dc_debug.c, consider switching to the atomic state debug helpers and +moving all your driver state printing into the various atomic_print_state +callbacks. There's also plans to expose this stuff in a standard way across all +drivers, to make debugging userspace compositors easier across different hw. + +15. Move DP/HDMI dual mode adaptors to drm_dp_dual_mode_helper.c. + +16. Move to core SCDC helpers (I think those are new since initial DC review). + +17. There's still a pretty massive layer cake around dp aux and DPCD handling, +with like 3 levels of abstraction and using your own structures instead of the +stuff in drm_dp_helper.h. drm_dp_helper.h isn't really great and already has 2 +incompatible styles, just means more reasons not to add a third (or well third +one gets to do the cleanup refactor). + +18. There's a pile of sink handling code, both for DP and HDMI where I didn't +immediately recognize the standard. I think long term it'd be best for the drm +subsystem if we try to move as much of that into helpers/core as possible, and +share it with drivers. But that's a very long term goal, and by far not just an +issue with DC - other drivers, especially around DP sink handling, are equally +guilty. + +19. The DC logger is still a rather sore thing, but I know that the DRM_DEBUG +stuff just isn't up to the challenges either. We need to figure out something +that integrates better with DRM and linux debug printing, while not being +useless with filtering output. dynamic debug printing might be an option. -- GitLab From 2004f45ef83f07f43f5da6ede780b08068c7583d Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 27 Sep 2017 10:53:50 -0400 Subject: [PATCH 0918/2898] drm/amd/display: Use kernel alloc/free Abstractions are frowned upon. cocci script: virtual context virtual patch virtual org virtual report @@ expression ptr; @@ - dm_alloc(ptr) + kzalloc(ptr, GFP_KERNEL) @@ expression ptr, size; @@ - dm_realloc(ptr, size) + krealloc(ptr, size, GFP_KERNEL) @@ expression ptr; @@ - dm_free(ptr) + kfree(ptr) v2: use GFP_KERNEL, not GFP_ATOMIC. add cocci script Reviewed-by: Alex Deucher Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../gpu/drm/amd/display/dc/basics/logger.c | 18 +++--- .../gpu/drm/amd/display/dc/basics/vector.c | 19 +++--- .../gpu/drm/amd/display/dc/bios/bios_parser.c | 17 +++--- .../drm/amd/display/dc/bios/bios_parser2.c | 14 ++--- .../gpu/drm/amd/display/dc/calcs/dce_calcs.c | 5 +- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 6 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 42 +++++++------ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 18 +++--- .../gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 11 ++-- .../gpu/drm/amd/display/dc/core/dc_stream.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_surface.c | 15 ++--- drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | 4 +- .../gpu/drm/amd/display/dc/dce/dce_audio.c | 4 +- .../drm/amd/display/dc/dce/dce_clock_source.c | 12 ++-- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 10 +-- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 6 +- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 2 +- .../drm/amd/display/dc/dce/dce_link_encoder.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 43 ++++++------- .../amd/display/dc/dce110/dce110_compressor.c | 6 +- .../amd/display/dc/dce110/dce110_resource.c | 61 ++++++++++--------- .../amd/display/dc/dce112/dce112_compressor.c | 6 +- .../amd/display/dc/dce112/dce112_resource.c | 43 ++++++------- .../amd/display/dc/dce120/dce120_resource.c | 43 ++++++------- .../amd/display/dc/dce80/dce80_compressor.c | 6 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 47 +++++++------- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 56 +++++++++-------- .../gpu/drm/amd/display/dc/gpio/gpio_base.c | 4 +- .../drm/amd/display/dc/gpio/gpio_service.c | 21 ++++--- drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 6 +- .../gpu/drm/amd/display/dc/gpio/hw_factory.c | 2 +- drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c | 6 +- .../display/dc/i2caux/dce100/i2caux_dce100.c | 4 +- .../dc/i2caux/dce110/aux_engine_dce110.c | 6 +- .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 7 ++- .../dc/i2caux/dce110/i2c_sw_engine_dce110.c | 7 ++- .../display/dc/i2caux/dce110/i2caux_dce110.c | 6 +- .../display/dc/i2caux/dce112/i2caux_dce112.c | 4 +- .../display/dc/i2caux/dce120/i2caux_dce120.c | 4 +- .../dc/i2caux/dce80/i2c_hw_engine_dce80.c | 6 +- .../dc/i2caux/dce80/i2c_sw_engine_dce80.c | 6 +- .../display/dc/i2caux/dce80/i2caux_dce80.c | 6 +- .../display/dc/i2caux/dcn10/i2caux_dcn10.c | 4 +- .../dc/i2caux/diagnostics/i2caux_diag.c | 7 ++- .../drm/amd/display/dc/i2caux/i2c_sw_engine.c | 6 +- .../dc/irq/dce110/irq_service_dce110.c | 5 +- .../dc/irq/dce120/irq_service_dce120.c | 5 +- .../display/dc/irq/dce80/irq_service_dce80.c | 5 +- .../display/dc/irq/dcn10/irq_service_dcn10.c | 5 +- .../gpu/drm/amd/display/dc/irq/irq_service.c | 2 +- .../display/dc/virtual/virtual_link_encoder.c | 2 +- .../dc/virtual/virtual_stream_encoder.c | 4 +- .../amd/display/modules/freesync/freesync.c | 14 ++--- 59 files changed, 362 insertions(+), 330 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 36635486b937..dba54c0a7b5f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2429,7 +2429,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) if (WARN_ON(!crtc->state)) return NULL; - state = dm_alloc(sizeof(*state)); + state = kzalloc(sizeof(*state), GFP_KERNEL); __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index 5895dd3903a3..afb6d2d80e0c 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -70,8 +70,8 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, { /* malloc buffer and init offsets */ logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE; - logger->log_buffer = (char *)dm_alloc(logger->log_buffer_size * - sizeof(char)); + logger->log_buffer = (char *)kzalloc(logger->log_buffer_size * sizeof(char), + GFP_KERNEL); if (!logger->log_buffer) return false; @@ -97,7 +97,7 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, static void destruct(struct dal_logger *logger) { if (logger->log_buffer) { - dm_free(logger->log_buffer); + kfree(logger->log_buffer); logger->log_buffer = NULL; } } @@ -105,12 +105,13 @@ static void destruct(struct dal_logger *logger) struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask) { /* malloc struct */ - struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger)); + struct dal_logger *logger = kzalloc(sizeof(struct dal_logger), + GFP_KERNEL); if (!logger) return NULL; if (!construct(ctx, logger, log_mask)) { - dm_free(logger); + kfree(logger); return NULL; } @@ -122,7 +123,7 @@ uint32_t dal_logger_destroy(struct dal_logger **logger) if (logger == NULL || *logger == NULL) return 1; destruct(*logger); - dm_free(*logger); + kfree(*logger); *logger = NULL; return 0; @@ -390,7 +391,8 @@ void dm_logger_open( entry->type = log_type; entry->logger = logger; - entry->buf = dm_alloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char)); + entry->buf = kzalloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char), + GFP_KERNEL); entry->buf_offset = 0; entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char); @@ -421,7 +423,7 @@ void dm_logger_close(struct log_entry *entry) cleanup: if (entry->buf) { - dm_free(entry->buf); + kfree(entry->buf); entry->buf = NULL; entry->buf_offset = 0; entry->max_buf_bytes = 0; diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c index bb72a1857160..e00fc4db3ac4 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/vector.c +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -40,7 +40,7 @@ bool dal_vector_construct( return false; } - vector->container = dm_alloc(struct_size * capacity); + vector->container = kzalloc(struct_size * capacity, GFP_KERNEL); if (vector->container == NULL) return false; vector->capacity = capacity; @@ -67,7 +67,7 @@ bool dal_vector_presized_costruct( return false; } - vector->container = dm_alloc(struct_size * count); + vector->container = kzalloc(struct_size * count, GFP_KERNEL); if (vector->container == NULL) return false; @@ -95,7 +95,7 @@ struct vector *dal_vector_presized_create( void *initial_value, uint32_t struct_size) { - struct vector *vector = dm_alloc(sizeof(struct vector)); + struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); if (vector == NULL) return NULL; @@ -105,7 +105,7 @@ struct vector *dal_vector_presized_create( return vector; BREAK_TO_DEBUGGER(); - dm_free(vector); + kfree(vector); return NULL; } @@ -114,7 +114,7 @@ struct vector *dal_vector_create( uint32_t capacity, uint32_t struct_size) { - struct vector *vector = dm_alloc(sizeof(struct vector)); + struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL); if (vector == NULL) return NULL; @@ -123,7 +123,7 @@ struct vector *dal_vector_create( return vector; BREAK_TO_DEBUGGER(); - dm_free(vector); + kfree(vector); return NULL; } @@ -131,7 +131,7 @@ void dal_vector_destruct( struct vector *vector) { if (vector->container != NULL) - dm_free(vector->container); + kfree(vector->container); vector->count = 0; vector->capacity = 0; } @@ -142,7 +142,7 @@ void dal_vector_destroy( if (vector == NULL || *vector == NULL) return; dal_vector_destruct(*vector); - dm_free(*vector); + kfree(*vector); *vector = NULL; } @@ -290,7 +290,8 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity) if (capacity <= vector->capacity) return true; - new_container = dm_realloc(vector->container, capacity * vector->struct_size); + new_container = krealloc(vector->container, + capacity * vector->struct_size, GFP_KERNEL); if (new_container) { vector->container = new_container; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 2c411441771b..47d673a1f688 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -116,14 +116,14 @@ struct dc_bios *bios_parser_create( { struct bios_parser *bp = NULL; - bp = dm_alloc(sizeof(struct bios_parser)); + bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL); if (!bp) return NULL; if (bios_parser_construct(bp, init, dce_version)) return &bp->base; - dm_free(bp); + kfree(bp); BREAK_TO_DEBUGGER(); return NULL; } @@ -131,10 +131,10 @@ struct dc_bios *bios_parser_create( static void destruct(struct bios_parser *bp) { if (bp->base.bios_local_image) - dm_free(bp->base.bios_local_image); + kfree(bp->base.bios_local_image); if (bp->base.integrated_info) - dm_free(bp->base.integrated_info); + kfree(bp->base.integrated_info); } static void bios_parser_destroy(struct dc_bios **dcb) @@ -148,7 +148,7 @@ static void bios_parser_destroy(struct dc_bios **dcb) destruct(bp); - dm_free(bp); + kfree(bp); *dcb = NULL; } @@ -3531,7 +3531,8 @@ static void process_ext_display_connection_info(struct bios_parser *bp) uint8_t *original_bios; /* Step 1: Replace bios image with the new copy which will be * patched */ - bp->base.bios_local_image = dm_alloc(bp->base.bios_size); + bp->base.bios_local_image = kzalloc(bp->base.bios_size, + GFP_KERNEL); if (bp->base.bios_local_image == NULL) { BREAK_TO_DEBUGGER(); /* Failed to alloc bp->base.bios_local_image */ @@ -3965,7 +3966,7 @@ static struct integrated_info *bios_parser_create_integrated_info( struct bios_parser *bp = BP_FROM_DCB(dcb); struct integrated_info *info = NULL; - info = dm_alloc(sizeof(struct integrated_info)); + info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL); if (info == NULL) { ASSERT_CRITICAL(0); @@ -3975,7 +3976,7 @@ static struct integrated_info *bios_parser_create_integrated_info( if (construct_integrated_info(bp, info) == BP_RESULT_OK) return info; - dm_free(info); + kfree(info); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 95fe50f62c57..3f8e605efde9 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -107,10 +107,10 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( static void destruct(struct bios_parser *bp) { if (bp->base.bios_local_image) - dm_free(bp->base.bios_local_image); + kfree(bp->base.bios_local_image); if (bp->base.integrated_info) - dm_free(bp->base.integrated_info); + kfree(bp->base.integrated_info); } static void firmware_parser_destroy(struct dc_bios **dcb) @@ -124,7 +124,7 @@ static void firmware_parser_destroy(struct dc_bios **dcb) destruct(bp); - dm_free(bp); + kfree(bp); *dcb = NULL; } @@ -2030,7 +2030,7 @@ static struct integrated_info *bios_parser_create_integrated_info( struct bios_parser *bp = BP_FROM_DCB(dcb); struct integrated_info *info = NULL; - info = dm_alloc(sizeof(struct integrated_info)); + info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL); if (info == NULL) { ASSERT_CRITICAL(0); @@ -2040,7 +2040,7 @@ static struct integrated_info *bios_parser_create_integrated_info( if (construct_integrated_info(bp, info) == BP_RESULT_OK) return info; - dm_free(info); + kfree(info); return NULL; } @@ -2205,14 +2205,14 @@ struct dc_bios *firmware_parser_create( { struct bios_parser *bp = NULL; - bp = dm_alloc(sizeof(struct bios_parser)); + bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL); if (!bp) return NULL; if (bios_parser_construct(bp, init, dce_version)) return &bp->base; - dm_free(bp); + kfree(bp); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index dba25853f7f9..15cbfc400633 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2792,7 +2792,8 @@ bool bw_calcs(struct dc_context *ctx, int pipe_count, struct dce_bw_output *calcs_output) { - struct bw_calcs_data *data = dm_alloc(sizeof(struct bw_calcs_data)); + struct bw_calcs_data *data = kzalloc(sizeof(struct bw_calcs_data), + GFP_KERNEL); populate_initial_data(pipe, pipe_count, data); @@ -3248,7 +3249,7 @@ bool bw_calcs(struct dc_context *ctx, calcs_output->sclk_khz = 0; } - dm_free(data); + kfree(data); return is_display_configuration_supported(vbios, calcs_output); } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 1b0f64756be6..91f43a1b88ee 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -481,8 +481,8 @@ static void dcn_dml_wm_override( { int i, in_idx, active_count; - struct _vcs_dpi_display_e2e_pipe_params_st *input = dm_alloc(pool->pipe_count * - sizeof(struct _vcs_dpi_display_e2e_pipe_params_st)); + struct _vcs_dpi_display_e2e_pipe_params_st *input = kzalloc(pool->pipe_count * sizeof(struct _vcs_dpi_display_e2e_pipe_params_st), + GFP_KERNEL); struct wm { double urgent; struct _vcs_dpi_cstate_pstate_watermarks_st cpstate; @@ -560,7 +560,7 @@ static void dcn_dml_wm_override( pipe->plane_state->flip_immediate); in_idx++; } - dm_free(input); + kfree(input); } static void split_stream_across_pipes( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 58c5083bef2a..d86d9796e4cc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -113,7 +113,7 @@ static bool create_links( } for (i = 0; i < num_virtual_links; i++) { - struct dc_link *link = dm_alloc(sizeof(*link)); + struct dc_link *link = kzalloc(sizeof(*link), GFP_KERNEL); struct encoder_init_data enc_init = {0}; if (link == NULL) { @@ -127,7 +127,7 @@ static bool create_links( link->link_id.type = OBJECT_TYPE_CONNECTOR; link->link_id.id = CONNECTOR_ID_VIRTUAL; link->link_id.enum_id = ENUM_ID_1; - link->link_enc = dm_alloc(sizeof(*link->link_enc)); + link->link_enc = kzalloc(sizeof(*link->link_enc), GFP_KERNEL); enc_init.ctx = dc->ctx; enc_init.channel = CHANNEL_ID_UNKNOWN; @@ -413,20 +413,20 @@ static void destruct(struct dc *dc) if (dc->ctx->logger) dal_logger_destroy(&dc->ctx->logger); - dm_free(dc->ctx); + kfree(dc->ctx); dc->ctx = NULL; - dm_free(dc->bw_vbios); + kfree(dc->bw_vbios); dc->bw_vbios = NULL; - dm_free(dc->bw_dceip); + kfree(dc->bw_dceip); dc->bw_dceip = NULL; #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - dm_free(dc->dcn_soc); + kfree(dc->dcn_soc); dc->dcn_soc = NULL; - dm_free(dc->dcn_ip); + kfree(dc->dcn_ip); dc->dcn_ip = NULL; #endif @@ -436,12 +436,15 @@ static bool construct(struct dc *dc, const struct dc_init_data *init_params) { struct dal_logger *logger; - struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx)); - struct bw_calcs_dceip *dc_dceip = dm_alloc(sizeof(*dc_dceip)); - struct bw_calcs_vbios *dc_vbios = dm_alloc(sizeof(*dc_vbios)); + struct dc_context *dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL); + struct bw_calcs_dceip *dc_dceip = kzalloc(sizeof(*dc_dceip), + GFP_KERNEL); + struct bw_calcs_vbios *dc_vbios = kzalloc(sizeof(*dc_vbios), + GFP_KERNEL); #ifdef CONFIG_DRM_AMD_DC_DCN1_0 - struct dcn_soc_bounding_box *dcn_soc = dm_alloc(sizeof(*dcn_soc)); - struct dcn_ip_params *dcn_ip = dm_alloc(sizeof(*dcn_ip)); + struct dcn_soc_bounding_box *dcn_soc = kzalloc(sizeof(*dcn_soc), + GFP_KERNEL); + struct dcn_ip_params *dcn_ip = kzalloc(sizeof(*dcn_ip), GFP_KERNEL); #endif enum dce_version dc_version = DCE_VERSION_UNKNOWN; @@ -604,7 +607,7 @@ void ProgramPixelDurationV(unsigned int pixelClockInKHz ) struct dc *dc_create(const struct dc_init_data *init_params) { - struct dc *dc = dm_alloc(sizeof(*dc)); + struct dc *dc = kzalloc(sizeof(*dc), GFP_KERNEL); unsigned int full_pipe_count; if (NULL == dc) @@ -638,7 +641,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) return dc; construct_fail: - dm_free(dc); + kfree(dc); alloc_fail: return NULL; @@ -647,7 +650,7 @@ struct dc *dc_create(const struct dc_init_data *init_params) void dc_destroy(struct dc **dc) { destruct(*dc); - dm_free(*dc); + kfree(*dc); *dc = NULL; } @@ -900,7 +903,7 @@ bool dc_commit_planes_to_stream( struct dc_scaling_info scaling_info[MAX_SURFACES]; int i; struct dc_stream_update *stream_update = - dm_alloc(sizeof(struct dc_stream_update)); + kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL); if (!stream_update) { BREAK_TO_DEBUGGER(); @@ -951,13 +954,14 @@ bool dc_commit_planes_to_stream( dc_post_update_surfaces_to_stream(dc); - dm_free(stream_update); + kfree(stream_update); return true; } struct dc_state *dc_create_state(void) { - struct dc_state *context = dm_alloc(sizeof(struct dc_state)); + struct dc_state *context = kzalloc(sizeof(struct dc_state), + GFP_KERNEL); if (!context) return NULL; @@ -979,7 +983,7 @@ void dc_release_state(struct dc_state *context) if (atomic_read(&context->ref_count) == 0) { dc_resource_state_destruct(context); - dm_free(context); + kfree(context); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 845ec421d861..43ebd8941b77 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1100,7 +1100,7 @@ static bool construct( struct dc_link *link_create(const struct link_init_data *init_params) { struct dc_link *link = - dm_alloc(sizeof(*link)); + kzalloc(sizeof(*link), GFP_KERNEL); if (NULL == link) goto alloc_fail; @@ -1111,7 +1111,7 @@ struct dc_link *link_create(const struct link_init_data *init_params) return link; construct_fail: - dm_free(link); + kfree(link); alloc_fail: return NULL; @@ -1120,7 +1120,7 @@ struct dc_link *link_create(const struct link_init_data *init_params) void link_destroy(struct dc_link **link) { destruct(*link); - dm_free(*link); + kfree(*link); *link = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index d09e539397ea..226512c11ab7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -130,7 +130,7 @@ struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_ { struct i2c_payloads *payloads; - payloads = dm_alloc(sizeof(struct i2c_payloads)); + payloads = kzalloc(sizeof(struct i2c_payloads), GFP_KERNEL); if (!payloads) return NULL; @@ -139,7 +139,7 @@ struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_ &payloads->payloads, ctx, count, sizeof(struct i2c_payload))) return payloads; - dm_free(payloads); + kfree(payloads); return NULL; } @@ -159,7 +159,7 @@ void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) if (!p || !*p) return; dal_vector_destruct(&(*p)->payloads); - dm_free(*p); + kfree(*p); *p = NULL; } @@ -168,7 +168,7 @@ struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_ { struct aux_payloads *payloads; - payloads = dm_alloc(sizeof(struct aux_payloads)); + payloads = kzalloc(sizeof(struct aux_payloads), GFP_KERNEL); if (!payloads) return NULL; @@ -177,7 +177,7 @@ struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_ &payloads->payloads, ctx, count, sizeof(struct aux_payload))) return payloads; - dm_free(payloads); + kfree(payloads); return NULL; } @@ -197,7 +197,7 @@ void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) return; dal_vector_destruct(&(*p)->payloads); - dm_free(*p); + kfree(*p); *p = NULL; } @@ -290,7 +290,7 @@ struct ddc_service *dal_ddc_service_create( { struct ddc_service *ddc_service; - ddc_service = dm_alloc(sizeof(struct ddc_service)); + ddc_service = kzalloc(sizeof(struct ddc_service), GFP_KERNEL); if (!ddc_service) return NULL; @@ -298,7 +298,7 @@ struct ddc_service *dal_ddc_service_create( if (construct(ddc_service, init_data)) return ddc_service; - dm_free(ddc_service); + kfree(ddc_service); return NULL; } @@ -315,7 +315,7 @@ void dal_ddc_service_destroy(struct ddc_service **ddc) return; } destruct(*ddc); - dm_free(*ddc); + kfree(*ddc); *ddc = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index dcfdfebd5c62..1832f252edab 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -160,7 +160,7 @@ void dc_destroy_resource_pool(struct dc *dc) dc->res_pool->funcs->destroy(&dc->res_pool); if (dc->hwseq) - dm_free(dc->hwseq); + kfree(dc->hwseq); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 7717350297a5..b3bbafc8fd6a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -34,7 +34,7 @@ static void destruct(struct dc_sink *sink) { if (sink->dc_container_id) { - dm_free(sink->dc_container_id); + kfree(sink->dc_container_id); sink->dc_container_id = NULL; } } @@ -74,13 +74,13 @@ void dc_sink_release(struct dc_sink *sink) if (atomic_read(&sink->ref_count) == 0) { destruct(sink); - dm_free(sink); + kfree(sink); } } struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) { - struct dc_sink *sink = dm_alloc(sizeof(*sink)); + struct dc_sink *sink = kzalloc(sizeof(*sink), GFP_KERNEL); if (NULL == sink) goto alloc_fail; @@ -93,7 +93,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) return sink; construct_fail: - dm_free(sink); + kfree(sink); alloc_fail: return NULL; @@ -117,7 +117,8 @@ bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container { if (dc_sink && container_id) { if (!dc_sink->dc_container_id) - dc_sink->dc_container_id = dm_alloc(sizeof(*dc_sink->dc_container_id)); + dc_sink->dc_container_id = kzalloc(sizeof(*dc_sink->dc_container_id), + GFP_KERNEL); if (dc_sink->dc_container_id) { memmove(&dc_sink->dc_container_id->guid, &container_id->guid, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index a421779093d9..d5da847ffad6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -131,7 +131,7 @@ void dc_stream_release(struct dc_stream_state *stream) if (atomic_read(&stream->ref_count) == 0) { destruct(stream); - dm_free(stream); + kfree(stream); } } } @@ -144,7 +144,7 @@ struct dc_stream_state *dc_create_stream_for_sink( if (sink == NULL) goto alloc_fail; - stream = dm_alloc(sizeof(struct dc_stream_state)); + stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL); if (NULL == stream) goto alloc_fail; @@ -157,7 +157,7 @@ struct dc_stream_state *dc_create_stream_for_sink( return stream; construct_fail: - dm_free(stream); + kfree(stream); alloc_fail: return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index e96f63eed070..511ada94530e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -68,7 +68,8 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) { struct dc *core_dc = dc; - struct dc_plane_state *plane_state = dm_alloc(sizeof(*plane_state)); + struct dc_plane_state *plane_state = kzalloc(sizeof(*plane_state), + GFP_KERNEL); if (NULL == plane_state) goto alloc_fail; @@ -81,7 +82,7 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) return plane_state; construct_fail: - dm_free(plane_state); + kfree(plane_state); alloc_fail: return NULL; @@ -133,7 +134,7 @@ void dc_plane_state_release(struct dc_plane_state *plane_state) if (atomic_read(&plane_state->ref_count) == 0) { destruct(plane_state); - dm_free(plane_state); + kfree(plane_state); } } @@ -149,14 +150,14 @@ void dc_gamma_release(struct dc_gamma **gamma) atomic_dec(&(*gamma)->ref_count); if (atomic_read(&(*gamma)->ref_count) == 0) - dm_free((*gamma)); + kfree((*gamma)); *gamma = NULL; } struct dc_gamma *dc_create_gamma() { - struct dc_gamma *gamma = dm_alloc(sizeof(*gamma)); + struct dc_gamma *gamma = kzalloc(sizeof(*gamma), GFP_KERNEL); if (gamma == NULL) goto alloc_fail; @@ -181,12 +182,12 @@ void dc_transfer_func_release(struct dc_transfer_func *tf) atomic_dec(&tf->ref_count); if (atomic_read(&tf->ref_count) == 0) - dm_free(tf); + kfree(tf); } struct dc_transfer_func *dc_create_transfer_func() { - struct dc_transfer_func *tf = dm_alloc(sizeof(*tf)); + struct dc_transfer_func *tf = kzalloc(sizeof(*tf), GFP_KERNEL); if (tf == NULL) goto alloc_fail; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 0e9d914e1a8f..0e0336c5af4e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -462,7 +462,7 @@ struct abm *dce_abm_create( const struct dce_abm_shift *abm_shift, const struct dce_abm_mask *abm_mask) { - struct dce_abm *abm_dce = dm_alloc(sizeof(*abm_dce)); + struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); if (abm_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -480,6 +480,6 @@ void dce_abm_destroy(struct abm **abm) { struct dce_abm *abm_dce = TO_DCE_ABM(*abm); - dm_free(abm_dce); + kfree(abm_dce); *abm = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index b94c1e5d85cb..198f4532e100 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -897,7 +897,7 @@ void dce_aud_destroy(struct audio **audio) { struct dce_audio *aud = DCE_AUD(*audio); - dm_free(aud); + kfree(aud); *audio = NULL; } @@ -909,7 +909,7 @@ struct audio *dce_audio_create( const struct dce_aduio_mask *masks ) { - struct dce_audio *audio = dm_alloc(sizeof(*audio)); + struct dce_audio *audio = kzalloc(sizeof(*audio), GFP_KERNEL); if (audio == NULL) { ASSERT_CRITICAL(audio); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index d3b61b92ebec..31280d252753 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1084,12 +1084,14 @@ static void get_ss_info_from_atombios( if (*ss_entries_num == 0) return; - ss_info = dm_alloc(sizeof(struct spread_spectrum_info) * (*ss_entries_num)); + ss_info = kzalloc(sizeof(struct spread_spectrum_info) * (*ss_entries_num), + GFP_KERNEL); ss_info_cur = ss_info; if (ss_info == NULL) return; - ss_data = dm_alloc(sizeof(struct spread_spectrum_data) * (*ss_entries_num)); + ss_data = kzalloc(sizeof(struct spread_spectrum_data) * (*ss_entries_num), + GFP_KERNEL); if (ss_data == NULL) goto out_free_info; @@ -1157,14 +1159,14 @@ static void get_ss_info_from_atombios( } *spread_spectrum_data = ss_data; - dm_free(ss_info); + kfree(ss_info); return; out_free_data: - dm_free(ss_data); + kfree(ss_data); *ss_entries_num = 0; out_free_info: - dm_free(ss_info); + kfree(ss_info); } static void ss_info_from_atombios_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 06d9a3e7c8a2..3e9ff2f5472d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -719,7 +719,7 @@ struct display_clock *dce_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask) { - struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); if (clk_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -742,7 +742,7 @@ struct display_clock *dce110_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask) { - struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); if (clk_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -767,7 +767,7 @@ struct display_clock *dce112_disp_clk_create( const struct dce_disp_clk_shift *clk_shift, const struct dce_disp_clk_mask *clk_mask) { - struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); if (clk_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -788,7 +788,7 @@ struct display_clock *dce112_disp_clk_create( struct display_clock *dce120_disp_clk_create(struct dc_context *ctx) { - struct dce_disp_clk *clk_dce = dm_alloc(sizeof(*clk_dce)); + struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); struct dm_pp_clock_levels_with_voltage clk_level_info = {0}; if (clk_dce == NULL) { @@ -822,6 +822,6 @@ void dce_disp_clk_destroy(struct display_clock **disp_clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(*disp_clk); - dm_free(clk_dce); + kfree(clk_dce); *disp_clk = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 313f61bf06e1..f9873cad40e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -573,7 +573,7 @@ struct dmcu *dce_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask) { - struct dce_dmcu *dmcu_dce = dm_alloc(sizeof(*dmcu_dce)); + struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL); if (dmcu_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -595,7 +595,7 @@ struct dmcu *dcn10_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask) { - struct dce_dmcu *dmcu_dce = dm_alloc(sizeof(*dmcu_dce)); + struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL); if (dmcu_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -615,6 +615,6 @@ void dce_dmcu_destroy(struct dmcu **dmcu) { struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(*dmcu); - dm_free(dmcu_dce); + kfree(dmcu_dce); *dmcu = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index e010cf10d605..fa481d481132 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -261,6 +261,6 @@ void dce_ipp_construct( void dce_ipp_destroy(struct input_pixel_processor **ipp) { - dm_free(TO_DCE_IPP(*ipp)); + kfree(TO_DCE_IPP(*ipp)); *ipp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 0ce94ede80bf..2ce730de0dc3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1108,7 +1108,7 @@ void dce110_link_encoder_hw_init( void dce110_link_encoder_destroy(struct link_encoder **enc) { - dm_free(TO_DCE110_LINK_ENC(*enc)); + kfree(TO_DCE110_LINK_ENC(*enc)); *enc = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 348e4b7047f1..c0736aeabd85 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -563,7 +563,7 @@ bool dce110_opp_construct(struct dce110_opp *opp110, void dce110_opp_destroy(struct output_pixel_processor **opp) { if (*opp) - dm_free(FROM_DCE11_OPP(*opp)); + kfree(FROM_DCE11_OPP(*opp)); *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index ca6c7c2a1b4c..9a75bde32611 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -370,7 +370,7 @@ static struct timing_generator *dce100_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -380,7 +380,7 @@ static struct timing_generator *dce100_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } @@ -389,7 +389,7 @@ static struct stream_encoder *dce100_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -400,7 +400,7 @@ static struct stream_encoder *dce100_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -422,7 +422,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce100_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -467,7 +467,8 @@ static struct mem_input *dce100_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -481,7 +482,7 @@ static struct mem_input *dce100_mem_input_create( static void dce100_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -490,7 +491,7 @@ static struct transform *dce100_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -501,14 +502,14 @@ static struct transform *dce100_transform_create( } BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } static struct input_pixel_processor *dce100_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -532,7 +533,7 @@ struct link_encoder *dce100_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -549,7 +550,7 @@ struct link_encoder *dce100_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -558,7 +559,7 @@ struct output_pixel_processor *dce100_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -568,7 +569,7 @@ struct output_pixel_processor *dce100_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -580,7 +581,7 @@ struct clock_source *dce100_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -597,7 +598,7 @@ struct clock_source *dce100_clock_source_create( void dce100_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } @@ -616,19 +617,19 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -768,7 +769,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -950,7 +951,7 @@ struct resource_pool *dce100_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index f82c26995609..90770cb2ffcd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -388,7 +388,7 @@ void dce110_compressor_set_fbc_invalidation_triggers( struct compressor *dce110_compressor_create(struct dc_context *ctx) { struct dce110_compressor *cp110 = - dm_alloc(sizeof(struct dce110_compressor)); + kzalloc(sizeof(struct dce110_compressor), GFP_KERNEL); if (!cp110) return NULL; @@ -397,13 +397,13 @@ struct compressor *dce110_compressor_create(struct dc_context *ctx) return &cp110->base; BREAK_TO_DEBUGGER(); - dm_free(cp110); + kfree(cp110); return NULL; } void dce110_compressor_destroy(struct compressor **compressor) { - dm_free(TO_DCE110_COMPRESSOR(*compressor)); + kfree(TO_DCE110_COMPRESSOR(*compressor)); *compressor = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 25eda52c32ef..787e20e15221 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -405,7 +405,7 @@ static struct timing_generator *dce110_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -414,7 +414,7 @@ static struct timing_generator *dce110_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } @@ -423,7 +423,7 @@ static struct stream_encoder *dce110_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -434,7 +434,7 @@ static struct stream_encoder *dce110_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -460,7 +460,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce110_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -505,7 +505,8 @@ static struct mem_input *dce110_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -519,7 +520,7 @@ static struct mem_input *dce110_mem_input_create( static void dce110_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -528,7 +529,7 @@ static struct transform *dce110_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -538,14 +539,14 @@ static struct transform *dce110_transform_create( return &transform->base; BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } static struct input_pixel_processor *dce110_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -569,7 +570,7 @@ static struct link_encoder *dce110_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -586,7 +587,7 @@ static struct link_encoder *dce110_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -595,7 +596,7 @@ static struct output_pixel_processor *dce110_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -605,7 +606,7 @@ static struct output_pixel_processor *dce110_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -617,7 +618,7 @@ struct clock_source *dce110_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -642,15 +643,15 @@ void dce110_clock_source_destroy(struct clock_source **clk_src) dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); if (dce110_clk_src->dp_ss_params) - dm_free(dce110_clk_src->dp_ss_params); + kfree(dce110_clk_src->dp_ss_params); if (dce110_clk_src->hdmi_ss_params) - dm_free(dce110_clk_src->hdmi_ss_params); + kfree(dce110_clk_src->hdmi_ss_params); if (dce110_clk_src->dvi_ss_params) - dm_free(dce110_clk_src->dvi_ss_params); + kfree(dce110_clk_src->dvi_ss_params); - dm_free(dce110_clk_src); + kfree(dce110_clk_src); *clk_src = NULL; } @@ -669,19 +670,19 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -1031,7 +1032,7 @@ static void dce110_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -1048,10 +1049,14 @@ static const struct resource_funcs dce110_res_pool_funcs = { static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) { - struct dce110_timing_generator *dce110_tgv = dm_alloc(sizeof (*dce110_tgv)); - struct dce_transform *dce110_xfmv = dm_alloc(sizeof (*dce110_xfmv)); - struct dce_mem_input *dce110_miv = dm_alloc(sizeof (*dce110_miv)); - struct dce110_opp *dce110_oppv = dm_alloc(sizeof (*dce110_oppv)); + struct dce110_timing_generator *dce110_tgv = kzalloc(sizeof(*dce110_tgv), + GFP_KERNEL); + struct dce_transform *dce110_xfmv = kzalloc(sizeof(*dce110_xfmv), + GFP_KERNEL); + struct dce_mem_input *dce110_miv = kzalloc(sizeof(*dce110_miv), + GFP_KERNEL); + struct dce110_opp *dce110_oppv = kzalloc(sizeof(*dce110_oppv), + GFP_KERNEL); if ((dce110_tgv == NULL) || (dce110_xfmv == NULL) || @@ -1332,7 +1337,7 @@ struct resource_pool *dce110_create_resource_pool( struct hw_asic_id asic_id) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c index 75af2125344b..e75895baa132 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -839,7 +839,7 @@ bool dce112_compressor_construct(struct dce112_compressor *compressor, struct compressor *dce112_compressor_create(struct dc_context *ctx) { struct dce112_compressor *cp110 = - dm_alloc(sizeof(struct dce112_compressor)); + kzalloc(sizeof(struct dce112_compressor), GFP_KERNEL); if (!cp110) return NULL; @@ -848,12 +848,12 @@ struct compressor *dce112_compressor_create(struct dc_context *ctx) return &cp110->base; BREAK_TO_DEBUGGER(); - dm_free(cp110); + kfree(cp110); return NULL; } void dce112_compressor_destroy(struct compressor **compressor) { - dm_free(TO_DCE112_COMPRESSOR(*compressor)); + kfree(TO_DCE112_COMPRESSOR(*compressor)); *compressor = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index de6f71d8a89b..4e2ed3429a90 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -410,7 +410,7 @@ static struct timing_generator *dce112_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -419,7 +419,7 @@ static struct timing_generator *dce112_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } @@ -428,7 +428,7 @@ static struct stream_encoder *dce112_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -439,7 +439,7 @@ static struct stream_encoder *dce112_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -461,7 +461,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce112_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -501,7 +501,8 @@ static struct mem_input *dce112_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -514,7 +515,7 @@ static struct mem_input *dce112_mem_input_create( static void dce112_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -523,7 +524,7 @@ static struct transform *dce112_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -535,7 +536,7 @@ static struct transform *dce112_transform_create( } BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } @@ -554,7 +555,7 @@ struct link_encoder *dce112_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -571,14 +572,14 @@ struct link_encoder *dce112_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } static struct input_pixel_processor *dce112_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -595,7 +596,7 @@ struct output_pixel_processor *dce112_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -605,7 +606,7 @@ struct output_pixel_processor *dce112_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -617,7 +618,7 @@ struct clock_source *dce112_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -634,7 +635,7 @@ struct clock_source *dce112_clock_source_create( void dce112_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } @@ -653,19 +654,19 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -940,7 +941,7 @@ static void dce112_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -1298,7 +1299,7 @@ struct resource_pool *dce112_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index e5d2d98982f7..6b5d5948ddb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -351,7 +351,7 @@ struct output_pixel_processor *dce120_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -361,7 +361,7 @@ struct output_pixel_processor *dce120_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -388,7 +388,7 @@ struct clock_source *dce120_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(*clk_src)); + kzalloc(sizeof(*clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -405,7 +405,7 @@ struct clock_source *dce120_clock_source_create( void dce120_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } @@ -428,7 +428,7 @@ static struct timing_generator *dce120_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -437,13 +437,13 @@ static struct timing_generator *dce120_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } static void dce120_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -462,7 +462,7 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -471,7 +471,7 @@ static void destruct(struct dce110_resource_pool *pool) } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } @@ -483,7 +483,7 @@ static void destruct(struct dce110_resource_pool *pool) for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -539,7 +539,7 @@ static struct link_encoder *dce120_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -556,14 +556,14 @@ static struct link_encoder *dce120_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } static struct input_pixel_processor *dce120_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -580,7 +580,7 @@ static struct stream_encoder *dce120_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -591,7 +591,7 @@ static struct stream_encoder *dce120_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -614,7 +614,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce120_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -654,7 +654,8 @@ static struct mem_input *dce120_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -670,7 +671,7 @@ static struct transform *dce120_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -682,7 +683,7 @@ static struct transform *dce120_transform_create( } BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } @@ -691,7 +692,7 @@ static void dce120_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -1006,7 +1007,7 @@ struct resource_pool *dce120_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c index 77626d7624c6..cc1c0d390945 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c @@ -819,7 +819,7 @@ bool dce80_compressor_construct(struct dce80_compressor *compressor, struct compressor *dce80_compressor_create(struct dc_context *ctx) { struct dce80_compressor *cp80 = - dm_alloc(sizeof(struct dce80_compressor)); + kzalloc(sizeof(struct dce80_compressor), GFP_KERNEL); if (!cp80) return NULL; @@ -828,12 +828,12 @@ struct compressor *dce80_compressor_create(struct dc_context *ctx) return &cp80->base; BREAK_TO_DEBUGGER(); - dm_free(cp80); + kfree(cp80); return NULL; } void dce80_compressor_destroy(struct compressor **compressor) { - dm_free(TO_DCE80_COMPRESSOR(*compressor)); + kfree(TO_DCE80_COMPRESSOR(*compressor)); *compressor = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 5453f02ea8ca..170509a4a221 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -399,7 +399,7 @@ static struct timing_generator *dce80_timing_generator_create( const struct dce110_timing_generator_offsets *offsets) { struct dce110_timing_generator *tg110 = - dm_alloc(sizeof(struct dce110_timing_generator)); + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); if (!tg110) return NULL; @@ -408,7 +408,7 @@ static struct timing_generator *dce80_timing_generator_create( return &tg110->base; BREAK_TO_DEBUGGER(); - dm_free(tg110); + kfree(tg110); return NULL; } @@ -417,7 +417,7 @@ static struct output_pixel_processor *dce80_opp_create( uint32_t inst) { struct dce110_opp *opp = - dm_alloc(sizeof(struct dce110_opp)); + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); if (!opp) return NULL; @@ -427,7 +427,7 @@ static struct output_pixel_processor *dce80_opp_create( return &opp->base; BREAK_TO_DEBUGGER(); - dm_free(opp); + kfree(opp); return NULL; } @@ -436,7 +436,7 @@ static struct stream_encoder *dce80_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -447,7 +447,7 @@ static struct stream_encoder *dce80_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -469,7 +469,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dce80_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -514,7 +514,8 @@ static struct mem_input *dce80_mem_input_create( struct dc_context *ctx, uint32_t inst) { - struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input)); + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); if (!dce_mi) { BREAK_TO_DEBUGGER(); @@ -528,7 +529,7 @@ static struct mem_input *dce80_mem_input_create( static void dce80_transform_destroy(struct transform **xfm) { - dm_free(TO_DCE_TRANSFORM(*xfm)); + kfree(TO_DCE_TRANSFORM(*xfm)); *xfm = NULL; } @@ -537,7 +538,7 @@ static struct transform *dce80_transform_create( uint32_t inst) { struct dce_transform *transform = - dm_alloc(sizeof(struct dce_transform)); + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); if (!transform) return NULL; @@ -549,7 +550,7 @@ static struct transform *dce80_transform_create( } BREAK_TO_DEBUGGER(); - dm_free(transform); + kfree(transform); return NULL; } @@ -565,7 +566,7 @@ struct link_encoder *dce80_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -582,7 +583,7 @@ struct link_encoder *dce80_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -594,7 +595,7 @@ struct clock_source *dce80_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -611,14 +612,14 @@ struct clock_source *dce80_clock_source_create( void dce80_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } static struct input_pixel_processor *dce80_ipp_create( struct dc_context *ctx, uint32_t inst) { - struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp)); + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -645,19 +646,19 @@ static void destruct(struct dce110_resource_pool *pool) dce_ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.clk_src_count; i++) { @@ -781,7 +782,7 @@ static void dce80_destroy_resource_pool(struct resource_pool **pool) struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); destruct(dce110_pool); - dm_free(dce110_pool); + kfree(dce110_pool); *pool = NULL; } @@ -948,7 +949,7 @@ struct resource_pool *dce80_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; @@ -1113,7 +1114,7 @@ struct resource_pool *dce81_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; @@ -1274,7 +1275,7 @@ struct resource_pool *dce83_create_resource_pool( struct dc *dc) { struct dce110_resource_pool *pool = - dm_alloc(sizeof(struct dce110_resource_pool)); + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 5e0e2464eab3..67bd6a738fe9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -225,7 +225,7 @@ static void ippn10_cursor_set_position( static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) { - dm_free(TO_DCN10_IPP(*ipp)); + kfree(TO_DCN10_IPP(*ipp)); *ipp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 8048782ac599..a136f70b7a3c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -314,7 +314,7 @@ static void oppn10_set_stereo_polarity( static void dcn10_opp_destroy(struct output_pixel_processor **opp) { - dm_free(TO_DCN10_OPP(*opp)); + kfree(TO_DCN10_OPP(*opp)); *opp = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 298eb44ad9bf..71adda0e5b59 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -468,7 +468,7 @@ static const struct dc_debug debug_defaults_diags = { static void dcn10_dpp_destroy(struct transform **xfm) { - dm_free(TO_DCN10_DPP(*xfm)); + kfree(TO_DCN10_DPP(*xfm)); *xfm = NULL; } @@ -477,7 +477,7 @@ static struct transform *dcn10_dpp_create( uint32_t inst) { struct dcn10_dpp *dpp = - dm_alloc(sizeof(struct dcn10_dpp)); + kzalloc(sizeof(struct dcn10_dpp), GFP_KERNEL); if (!dpp) return NULL; @@ -487,7 +487,7 @@ static struct transform *dcn10_dpp_create( return &dpp->base; BREAK_TO_DEBUGGER(); - dm_free(dpp); + kfree(dpp); return NULL; } @@ -495,7 +495,7 @@ static struct input_pixel_processor *dcn10_ipp_create( struct dc_context *ctx, uint32_t inst) { struct dcn10_ipp *ipp = - dm_alloc(sizeof(struct dcn10_ipp)); + kzalloc(sizeof(struct dcn10_ipp), GFP_KERNEL); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -512,7 +512,7 @@ static struct output_pixel_processor *dcn10_opp_create( struct dc_context *ctx, uint32_t inst) { struct dcn10_opp *opp = - dm_alloc(sizeof(struct dcn10_opp)); + kzalloc(sizeof(struct dcn10_opp), GFP_KERNEL); if (!opp) { BREAK_TO_DEBUGGER(); @@ -526,7 +526,8 @@ static struct output_pixel_processor *dcn10_opp_create( static struct mpc *dcn10_mpc_create(struct dc_context *ctx) { - struct dcn10_mpc *mpc10 = dm_alloc(sizeof(struct dcn10_mpc)); + struct dcn10_mpc *mpc10 = kzalloc(sizeof(struct dcn10_mpc), + GFP_KERNEL); if (!mpc10) return NULL; @@ -545,7 +546,7 @@ static struct timing_generator *dcn10_timing_generator_create( uint32_t instance) { struct dcn10_timing_generator *tgn10 = - dm_alloc(sizeof(struct dcn10_timing_generator)); + kzalloc(sizeof(struct dcn10_timing_generator), GFP_KERNEL); if (!tgn10) return NULL; @@ -577,7 +578,7 @@ struct link_encoder *dcn10_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = - dm_alloc(sizeof(struct dce110_link_encoder)); + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -594,7 +595,7 @@ struct link_encoder *dcn10_link_encoder_create( } BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -606,7 +607,7 @@ struct clock_source *dcn10_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - dm_alloc(sizeof(struct dce110_clk_src)); + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); if (!clk_src) return NULL; @@ -641,7 +642,7 @@ static struct stream_encoder *dcn10_stream_encoder_create( struct dc_context *ctx) { struct dce110_stream_encoder *enc110 = - dm_alloc(sizeof(struct dce110_stream_encoder)); + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); if (!enc110) return NULL; @@ -652,7 +653,7 @@ static struct stream_encoder *dcn10_stream_encoder_create( return &enc110->base; BREAK_TO_DEBUGGER(); - dm_free(enc110); + kfree(enc110); return NULL; } @@ -671,7 +672,7 @@ static const struct dce_hwseq_mask hwseq_mask = { static struct dce_hwseq *dcn10_hwseq_create( struct dc_context *ctx) { - struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq)); + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); if (hws) { hws->ctx = ctx; @@ -698,13 +699,13 @@ static const struct resource_create_funcs res_create_maximus_funcs = { void dcn10_clock_source_destroy(struct clock_source **clk_src) { - dm_free(TO_DCE110_CLK_SRC(*clk_src)); + kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; } static struct pp_smu_funcs_rv *dcn10_pp_smu_create(struct dc_context *ctx) { - struct pp_smu_funcs_rv *pp_smu = dm_alloc(sizeof(*pp_smu)); + struct pp_smu_funcs_rv *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); if (!pp_smu) return pp_smu; @@ -722,13 +723,13 @@ static void destruct(struct dcn10_resource_pool *pool) /* TODO: free dcn version of stream encoder once implemented * rather than using virtual stream encoder */ - dm_free(pool->base.stream_enc[i]); + kfree(pool->base.stream_enc[i]); pool->base.stream_enc[i] = NULL; } } if (pool->base.mpc != NULL) { - dm_free(TO_DCN10_MPC(pool->base.mpc)); + kfree(TO_DCN10_MPC(pool->base.mpc)); pool->base.mpc = NULL; } for (i = 0; i < pool->base.pipe_count; i++) { @@ -742,7 +743,7 @@ static void destruct(struct dcn10_resource_pool *pool) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); if (pool->base.mis[i] != NULL) { - dm_free(TO_DCN10_MEM_INPUT(pool->base.mis[i])); + kfree(TO_DCN10_MEM_INPUT(pool->base.mis[i])); pool->base.mis[i] = NULL; } @@ -751,14 +752,14 @@ static void destruct(struct dcn10_resource_pool *pool) } if (pool->base.timing_generators[i] != NULL) { - dm_free(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); pool->base.timing_generators[i] = NULL; } } for (i = 0; i < pool->base.stream_enc_count; i++) { if (pool->base.stream_enc[i] != NULL) - dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); } for (i = 0; i < pool->base.audio_count; i++) { @@ -767,7 +768,7 @@ static void destruct(struct dcn10_resource_pool *pool) } for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - dm_free(pool->base.dwbc[i]); + kfree(pool->base.dwbc[i]); pool->base.dwbc[i] = NULL; } @@ -792,7 +793,7 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.display_clock != NULL) dce_disp_clk_destroy(&pool->base.display_clock); - dm_free(pool->base.pp_smu); + kfree(pool->base.pp_smu); } static struct mem_input *dcn10_mem_input_create( @@ -800,7 +801,7 @@ static struct mem_input *dcn10_mem_input_create( uint32_t inst) { struct dcn10_mem_input *mem_inputn10 = - dm_alloc(sizeof(struct dcn10_mem_input)); + kzalloc(sizeof(struct dcn10_mem_input), GFP_KERNEL); if (!mem_inputn10) return NULL; @@ -810,7 +811,7 @@ static struct mem_input *dcn10_mem_input_create( return &mem_inputn10->base; BREAK_TO_DEBUGGER(); - dm_free(mem_inputn10); + kfree(mem_inputn10); return NULL; } @@ -1207,7 +1208,7 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool) struct dcn10_resource_pool *dcn10_pool = TO_DCN10_RES_POOL(*pool); destruct(dcn10_pool); - dm_free(dcn10_pool); + kfree(dcn10_pool); *pool = NULL; } @@ -1239,7 +1240,8 @@ static bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool uint32_t dwb_count = pool->res_cap->num_dwb; for (i = 0; i < dwb_count; i++) { - struct dcn10_dwbc *dwbc10 = dm_alloc(sizeof(struct dcn10_dwbc)); + struct dcn10_dwbc *dwbc10 = kzalloc(sizeof(struct dcn10_dwbc), + GFP_KERNEL); if (!dwbc10) { dm_error("DC: failed to create dwbc10!\n"); @@ -1517,7 +1519,7 @@ struct resource_pool *dcn10_create_resource_pool( struct dc *dc) { struct dcn10_resource_pool *pool = - dm_alloc(sizeof(struct dcn10_resource_pool)); + kzalloc(sizeof(struct dcn10_resource_pool), GFP_KERNEL); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c index d42eb3de2ea4..1d1efd72b291 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c @@ -239,7 +239,7 @@ struct gpio *dal_gpio_create( uint32_t en, enum gpio_pin_output_state output_state) { - struct gpio *gpio = dm_alloc(sizeof(struct gpio)); + struct gpio *gpio = kzalloc(sizeof(struct gpio), GFP_KERNEL); if (!gpio) { ASSERT_CRITICAL(false); @@ -266,7 +266,7 @@ void dal_gpio_destroy( dal_gpio_close(*gpio); - dm_free(*gpio); + kfree(*gpio); *gpio = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index eeb1cd0f75a6..d4e5ef64e489 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -59,7 +59,7 @@ struct gpio_service *dal_gpio_service_create( uint32_t index_of_id; - service = dm_alloc(sizeof(struct gpio_service)); + service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL); if (!service) { BREAK_TO_DEBUGGER(); @@ -98,7 +98,8 @@ struct gpio_service *dal_gpio_service_create( if (number_of_bits) { uint32_t index_of_uint = 0; - slot = dm_alloc(number_of_uints * sizeof(uint32_t)); + slot = kzalloc(number_of_uints * sizeof(uint32_t), + GFP_KERNEL); if (!slot) { BREAK_TO_DEBUGGER(); @@ -130,11 +131,11 @@ struct gpio_service *dal_gpio_service_create( slot = service->busyness[index_of_id]; if (slot) - dm_free(slot); + kfree(slot); }; failure_1: - dm_free(service); + kfree(service); return NULL; } @@ -171,13 +172,13 @@ void dal_gpio_service_destroy( uint32_t *slot = (*ptr)->busyness[index_of_id]; if (slot) - dm_free(slot); + kfree(slot); ++index_of_id; } while (index_of_id < GPIO_ID_COUNT); } - dm_free(*ptr); + kfree(*ptr); *ptr = NULL; } @@ -399,7 +400,7 @@ void dal_gpio_destroy_irq( dal_gpio_close(*irq); dal_gpio_destroy(irq); - dm_free(*irq); + kfree(*irq); *irq = NULL; } @@ -417,7 +418,7 @@ struct ddc *dal_gpio_create_ddc( if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) return NULL; - ddc = dm_alloc(sizeof(struct ddc)); + ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL); if (!ddc) { BREAK_TO_DEBUGGER(); @@ -450,7 +451,7 @@ struct ddc *dal_gpio_create_ddc( dal_gpio_destroy(&ddc->pin_data); failure_1: - dm_free(ddc); + kfree(ddc); return NULL; } @@ -466,7 +467,7 @@ void dal_gpio_destroy_ddc( dal_ddc_close(*ddc); dal_gpio_destroy(&(*ddc)->pin_data); dal_gpio_destroy(&(*ddc)->pin_clock); - dm_free(*ddc); + kfree(*ddc); *ddc = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c index 47e0f8f24a86..7b6efa4f2efd 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -55,7 +55,7 @@ static void destroy( destruct(pin); - dm_free(pin); + kfree(pin); *ptr = NULL; } @@ -225,7 +225,7 @@ struct hw_gpio_pin *dal_hw_ddc_create( enum gpio_id id, uint32_t en) { - struct hw_ddc *pin = dm_alloc(sizeof(struct hw_ddc)); + struct hw_ddc *pin = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL); if (!pin) { ASSERT_CRITICAL(false); @@ -237,7 +237,7 @@ struct hw_gpio_pin *dal_hw_ddc_create( ASSERT_CRITICAL(false); - dm_free(pin); + kfree(pin); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index f7d049c0e62a..87b580fa4bc9 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -101,7 +101,7 @@ void dal_hw_factory_destroy( return; } - dm_free(*factory); + kfree(*factory); *factory = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c index 9634e8841d90..0c255c02045b 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c @@ -72,7 +72,7 @@ static void destroy( destruct(hpd); - dm_free(hpd); + kfree(hpd); *ptr = NULL; } @@ -157,7 +157,7 @@ struct hw_gpio_pin *dal_hw_hpd_create( enum gpio_id id, uint32_t en) { - struct hw_hpd *hpd = dm_alloc(sizeof(struct hw_hpd)); + struct hw_hpd *hpd = kzalloc(sizeof(struct hw_hpd), GFP_KERNEL); if (!hpd) { ASSERT_CRITICAL(false); @@ -169,7 +169,7 @@ struct hw_gpio_pin *dal_hw_hpd_create( ASSERT_CRITICAL(false); - dm_free(hpd); + kfree(hpd); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c index 0712cafb4c42..c45a2ee8c336 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c @@ -88,7 +88,7 @@ struct i2caux *dal_i2caux_dce100_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -106,7 +106,7 @@ struct i2caux *dal_i2caux_dce100_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index d3eaf8977a60..4b673b48bf42 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -87,7 +87,7 @@ static void destroy( destruct(engine); - dm_free(engine); + kfree(engine); *aux_engine = NULL; } @@ -464,7 +464,7 @@ struct aux_engine *dal_aux_engine_dce110_create( return NULL; } - engine = dm_alloc(sizeof(*engine)); + engine = kzalloc(sizeof(*engine), GFP_KERNEL); if (!engine) { ASSERT_CRITICAL(false); @@ -476,7 +476,7 @@ struct aux_engine *dal_aux_engine_dce110_create( ASSERT_CRITICAL(false); - dm_free(engine); + kfree(engine); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c index 80d06ad78e07..aab77a81008a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c @@ -469,7 +469,7 @@ static void destroy( dal_i2c_hw_engine_destruct(&engine_dce110->base); - dm_free(engine_dce110); + kfree(engine_dce110); *i2c_engine = NULL; } @@ -559,7 +559,8 @@ struct i2c_engine *dal_i2c_hw_engine_dce110_create( return NULL; } - engine_dce10 = dm_alloc(sizeof(struct i2c_hw_engine_dce110)); + engine_dce10 = kzalloc(sizeof(struct i2c_hw_engine_dce110), + GFP_KERNEL); if (!engine_dce10) { ASSERT_CRITICAL(false); @@ -571,7 +572,7 @@ struct i2c_engine *dal_i2c_hw_engine_dce110_create( ASSERT_CRITICAL(false); - dm_free(engine_dce10); + kfree(engine_dce10); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c index 996813d9165f..bf2c4b240b78 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c @@ -88,7 +88,7 @@ static void destroy( destruct(sw_engine); - dm_free(sw_engine); + kfree(sw_engine); *engine = NULL; } @@ -153,7 +153,8 @@ struct i2c_engine *dal_i2c_sw_engine_dce110_create( return NULL; } - engine_dce110 = dm_alloc(sizeof(struct i2c_sw_engine_dce110)); + engine_dce110 = kzalloc(sizeof(struct i2c_sw_engine_dce110), + GFP_KERNEL); if (!engine_dce110) { ASSERT_CRITICAL(false); @@ -165,7 +166,7 @@ struct i2c_engine *dal_i2c_sw_engine_dce110_create( ASSERT_CRITICAL(false); - dm_free(engine_dce110); + kfree(engine_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c index 1c00ed0010d9..ae9adb389319 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c @@ -68,7 +68,7 @@ static void destroy( destruct(i2caux_dce110); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); *i2c_engine = NULL; } @@ -299,7 +299,7 @@ struct i2caux *dal_i2caux_dce110_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -317,7 +317,7 @@ struct i2caux *dal_i2caux_dce110_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c index d74f3f15d600..715ba4390957 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c @@ -122,7 +122,7 @@ struct i2caux *dal_i2caux_dce112_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -134,7 +134,7 @@ struct i2caux *dal_i2caux_dce112_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c index 91198295f1a4..d52827ae3f1a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c @@ -101,7 +101,7 @@ struct i2caux *dal_i2caux_dce120_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -119,7 +119,7 @@ struct i2caux *dal_i2caux_dce120_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c index 423c38ac880c..d41e37c94214 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c @@ -190,7 +190,7 @@ static void destroy( destruct(engine); - dm_free(engine); + kfree(engine); *i2c_engine = NULL; } @@ -867,7 +867,7 @@ struct i2c_engine *dal_i2c_hw_engine_dce80_create( return NULL; } - engine = dm_alloc(sizeof(struct i2c_hw_engine_dce80)); + engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL); if (!engine) { BREAK_TO_DEBUGGER(); @@ -879,7 +879,7 @@ struct i2c_engine *dal_i2c_hw_engine_dce80_create( BREAK_TO_DEBUGGER(); - dm_free(engine); + kfree(engine); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c index 804a3266c578..6be77bc931c6 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c @@ -103,7 +103,7 @@ static void destroy( destruct(sw_engine); - dm_free(sw_engine); + kfree(sw_engine); *engine = NULL; } @@ -165,7 +165,7 @@ struct i2c_engine *dal_i2c_sw_engine_dce80_create( return NULL; } - engine = dm_alloc(sizeof(struct i2c_sw_engine_dce80)); + engine = kzalloc(sizeof(struct i2c_sw_engine_dce80), GFP_KERNEL); if (!engine) { BREAK_TO_DEBUGGER(); @@ -177,7 +177,7 @@ struct i2c_engine *dal_i2c_sw_engine_dce80_create( BREAK_TO_DEBUGGER(); - dm_free(engine); + kfree(engine); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c index 5e71450c44e0..d3c157e5eccd 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c @@ -101,7 +101,7 @@ static void destroy( destruct(i2caux_dce80); - dm_free(i2caux_dce80); + kfree(i2caux_dce80); *i2c_engine = NULL; } @@ -277,7 +277,7 @@ struct i2caux *dal_i2caux_dce80_create( struct dc_context *ctx) { struct i2caux_dce80 *i2caux_dce80 = - dm_alloc(sizeof(struct i2caux_dce80)); + kzalloc(sizeof(struct i2caux_dce80), GFP_KERNEL); if (!i2caux_dce80) { BREAK_TO_DEBUGGER(); @@ -289,7 +289,7 @@ struct i2caux *dal_i2caux_dce80_create( BREAK_TO_DEBUGGER(); - dm_free(i2caux_dce80); + kfree(i2caux_dce80); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c index 9f17d2e4376b..f8659f1c5f9d 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c @@ -101,7 +101,7 @@ struct i2caux *dal_i2caux_dcn10_create( struct dc_context *ctx) { struct i2caux_dce110 *i2caux_dce110 = - dm_alloc(sizeof(struct i2caux_dce110)); + kzalloc(sizeof(struct i2caux_dce110), GFP_KERNEL); if (!i2caux_dce110) { ASSERT_CRITICAL(false); @@ -119,7 +119,7 @@ struct i2caux *dal_i2caux_dcn10_create( ASSERT_CRITICAL(false); - dm_free(i2caux_dce110); + kfree(i2caux_dce110); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c index 029bf735036c..1fdb3252920b 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c @@ -59,7 +59,7 @@ static void destroy( { destruct(*i2c_engine); - dm_free(*i2c_engine); + kfree(*i2c_engine); *i2c_engine = NULL; } @@ -90,7 +90,8 @@ static bool construct( struct i2caux *dal_i2caux_diag_fpga_create( struct dc_context *ctx) { - struct i2caux *i2caux = dm_alloc(sizeof(struct i2caux)); + struct i2caux *i2caux = kzalloc(sizeof(struct i2caux), + GFP_KERNEL); if (!i2caux) { ASSERT_CRITICAL(false); @@ -102,7 +103,7 @@ struct i2caux *dal_i2caux_diag_fpga_create( ASSERT_CRITICAL(false); - dm_free(i2caux); + kfree(i2caux); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c index 95bc4457d44b..9d0077ade12c 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c @@ -541,7 +541,7 @@ static void destroy( { dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr)); - dm_free(*ptr); + kfree(*ptr); *ptr = NULL; } @@ -592,7 +592,7 @@ struct i2c_engine *dal_i2c_sw_engine_create( return NULL; } - engine = dm_alloc(sizeof(struct i2c_sw_engine)); + engine = kzalloc(sizeof(struct i2c_sw_engine), GFP_KERNEL); if (!engine) { BREAK_TO_DEBUGGER(); @@ -604,7 +604,7 @@ struct i2c_engine *dal_i2c_sw_engine_create( BREAK_TO_DEBUGGER(); - dm_free(engine); + kfree(engine); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 7cce28489dba..a6c3a7229def 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -422,7 +422,8 @@ bool construct( struct irq_service *dal_irq_service_dce110_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); if (!irq_service) return NULL; @@ -430,6 +431,6 @@ struct irq_service *dal_irq_service_dce110_create( if (construct(irq_service, init_data)) return irq_service; - dm_free(irq_service); + kfree(irq_service); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c index 3871633ac635..61d7c286802a 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -281,7 +281,8 @@ static bool construct( struct irq_service *dal_irq_service_dce120_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); if (!irq_service) return NULL; @@ -289,6 +290,6 @@ struct irq_service *dal_irq_service_dce120_create( if (construct(irq_service, init_data)) return irq_service; - dm_free(irq_service); + kfree(irq_service); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index f458ef8e4c57..d6e1fb665d90 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -293,7 +293,8 @@ static bool construct( struct irq_service *dal_irq_service_dce80_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); if (!irq_service) return NULL; @@ -301,7 +302,7 @@ struct irq_service *dal_irq_service_dce80_create( if (construct(irq_service, init_data)) return irq_service; - dm_free(irq_service); + kfree(irq_service); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c index be59f0a654e2..f6e861162a6e 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -348,7 +348,8 @@ static bool construct( struct irq_service *dal_irq_service_dcn10_create( struct irq_service_init_data *init_data) { - struct irq_service *irq_service = dm_alloc(sizeof(*irq_service)); + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); if (!irq_service) return NULL; @@ -356,6 +357,6 @@ struct irq_service *dal_irq_service_dcn10_create( if (construct(irq_service, init_data)) return irq_service; - dm_free(irq_service); + kfree(irq_service); return NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index 0a1fae4ef83a..ce20622c7c89 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -66,7 +66,7 @@ void dal_irq_service_destroy(struct irq_service **irq_service) return; } - dm_free(*irq_service); + kfree(*irq_service); *irq_service = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 57b5a3babdf8..db513abd735a 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -87,7 +87,7 @@ static void virtual_link_encoder_connect_dig_be_to_fe( static void virtual_link_encoder_destroy(struct link_encoder **enc) { - dm_free(*enc); + kfree(*enc); *enc = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index 7fe6085e6e37..3dc1733eea20 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -121,7 +121,7 @@ bool virtual_stream_encoder_construct( struct stream_encoder *virtual_stream_encoder_create( struct dc_context *ctx, struct dc_bios *bp) { - struct stream_encoder *enc = dm_alloc(sizeof(*enc)); + struct stream_encoder *enc = kzalloc(sizeof(*enc), GFP_KERNEL); if (!enc) return NULL; @@ -130,7 +130,7 @@ struct stream_encoder *virtual_stream_encoder_create( return enc; BREAK_TO_DEBUGGER(); - dm_free(enc); + kfree(enc); return NULL; } diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 52350d0e68d0..4d7db4aa28e0 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -143,7 +143,7 @@ static bool check_dc_support(const struct dc *dc) struct mod_freesync *mod_freesync_create(struct dc *dc) { struct core_freesync *core_freesync = - dm_alloc(sizeof(struct core_freesync)); + kzalloc(sizeof(struct core_freesync), GFP_KERNEL); struct persistent_data_flag flag; @@ -153,8 +153,8 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) if (core_freesync == NULL) goto fail_alloc_context; - core_freesync->map = dm_alloc(sizeof(struct freesync_entity) * - MOD_FREESYNC_MAX_CONCURRENT_STREAMS); + core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS, + GFP_KERNEL); if (core_freesync->map == NULL) goto fail_alloc_map; @@ -197,10 +197,10 @@ struct mod_freesync *mod_freesync_create(struct dc *dc) return &core_freesync->public; fail_construct: - dm_free(core_freesync->map); + kfree(core_freesync->map); fail_alloc_map: - dm_free(core_freesync); + kfree(core_freesync); fail_alloc_context: return NULL; @@ -217,9 +217,9 @@ void mod_freesync_destroy(struct mod_freesync *mod_freesync) if (core_freesync->map[i].stream) dc_stream_release(core_freesync->map[i].stream); - dm_free(core_freesync->map); + kfree(core_freesync->map); - dm_free(core_freesync); + kfree(core_freesync); } } -- GitLab From 2e12d9b761212053d0260b6309155c5e8a65948c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 27 Sep 2017 15:36:11 -0400 Subject: [PATCH 0919/2898] drm/amd/display: DC I2C review While reviewing I2C in DC identified a few places. Added a couple to the TODO list. 1) Connector info read See get_ext_display_connection_info On some boards the connector information has to be read through a special I2C channel. This line is only used for this purpose and only on driver init. 2) SCDC stuff This should all be reworked to go through DRM's SCDC code. When this is done some unnecessary I2C code can be retired as well. 3) Max TMDS clock read See dal_ddc_service_i2c_query_dp_dual_mode_adaptor This should happen in DRM as well. I haven't checked if there's currently functionality in DRM. If not we can propose something. 4) HDMI retimer programming Some boards have an HDMI retimer that we need to program to pass PHY compliance. 1 & 3 might be a good exercise if someone is looking for things to do. v2: Merge dp_dual_mode_adaptor TODO Acked-by: Alex Deucher Signed-off-by: Harry Wentland Acked-by: Daniel Vetter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/TODO | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/TODO b/drivers/gpu/drm/amd/display/TODO index eea645b102a1..46464678f2b3 100644 --- a/drivers/gpu/drm/amd/display/TODO +++ b/drivers/gpu/drm/amd/display/TODO @@ -62,20 +62,10 @@ TODOs ~ Daniel Vetter -11. Remove existing i2c implementation from DC - - "Similar story for i2c, it uses the kernel's i2c code now, but there's - still a full i2c implementation hidden beneath that in - display/dc/i2caux. Kinda not cool, but imo ok if you fix that - post-merging (perhaps by not including any of this in the linux DC - code in the upstream kernel, but as an aux module in your internal - codebase since there you probably need that, same applies to the edid - parsing DC still does. For both cases I assume that the minimal shim - you need on linux (bit banging and edid parsing isn't rocket since) is - a lot less than the glue code to interface with the dc-provided - abstraction." - ~ Daniel Vetter - +11. Remove dc/i2caux. This folder can be somewhat misleading. It's basically an +overy complicated HW programming function for sendind and receiving i2c/aux +commands. We can greatly simplify that and move it into dc/dceXYZ like other +HW blocks. 12. drm_modeset_lock in MST should no longer be needed in recent kernels * Adopt appropriate locking scheme @@ -89,7 +79,8 @@ moving all your driver state printing into the various atomic_print_state callbacks. There's also plans to expose this stuff in a standard way across all drivers, to make debugging userspace compositors easier across different hw. -15. Move DP/HDMI dual mode adaptors to drm_dp_dual_mode_helper.c. +15. Move DP/HDMI dual mode adaptors to drm_dp_dual_mode_helper.c. See +dal_ddc_service_i2c_query_dp_dual_mode_adaptor. 16. Move to core SCDC helpers (I think those are new since initial DC review). @@ -110,3 +101,7 @@ guilty. stuff just isn't up to the challenges either. We need to figure out something that integrates better with DRM and linux debug printing, while not being useless with filtering output. dynamic debug printing might be an option. + +20. Use kernel i2c device to program HDMI retimer. Some boards have an HDMI +retimer that we need to program to pass PHY compliance. Currently that's +bypassing the i2c device and goes directly to HW. This should be changed. -- GitLab From 0a26a45d1a2338326a369c9544dc5141a6e75106 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 28 Sep 2017 11:53:19 -0400 Subject: [PATCH 0920/2898] drm/doc: Reference AMD DC todos Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- Documentation/gpu/todo.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 22af55d06ab8..4a837cfb6a39 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -390,5 +390,15 @@ those drivers as simple as possible, so lots of room for refactoring: Contact: Noralf Trønnes, Daniel Vetter +AMD DC Display Driver +--------------------- + +AMD DC is the display driver for AMD devices starting with Vega. There has been +a bunch of progress cleaning it up but there's still plenty of work to be done. + +See drivers/gpu/drm/amd/display/TODO for tasks. + +Contact: Harry Wentland, Alex Deucher + Outside DRM =========== -- GitLab From 24a0d8538ed36ae08d8009bd4a46c6eb36d92bd1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 09:21:33 +1000 Subject: [PATCH 0921/2898] amdgpu/dc: add static to construct function There was a global construct symbol in the module symbols, kill it. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index a6c3a7229def..5c558969f39f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -406,7 +406,7 @@ static const struct irq_service_funcs irq_service_funcs_dce110 = { .to_dal_irq_source = to_dal_irq_source_dce110 }; -bool construct( +static bool construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { -- GitLab From 8c0dc2b9891155afc3b1fbf6b04839819ec9099b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:22:48 +1000 Subject: [PATCH 0922/2898] amdgpu/dc: move filter taps to being static const data (v2) This just adds two accessor methods, and moves all the data to static const. v2: fix dcn build. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_scl_filters.c | 78 +++++++++++-------- .../drm/amd/display/dc/dce/dce_transform.c | 2 +- .../display/dc/dce110/dce110_transform_v.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 2 +- .../gpu/drm/amd/display/dc/inc/hw/transform.h | 4 +- 5 files changed, 49 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c index 2cfdb835f1a8..6243450b41b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_scl_filters.c @@ -25,7 +25,7 @@ #include "transform.h" -const uint16_t filter_2tap_16p[18] = { +static const uint16_t filter_2tap_16p[18] = { 4096, 0, 3840, 256, 3584, 512, @@ -37,7 +37,7 @@ const uint16_t filter_2tap_16p[18] = { 2048, 2048 }; -const uint16_t filter_3tap_16p_upscale[27] = { +static const uint16_t filter_3tap_16p_upscale[27] = { 2048, 2048, 0, 1708, 2424, 16348, 1372, 2796, 16308, @@ -49,7 +49,7 @@ const uint16_t filter_3tap_16p_upscale[27] = { 0, 4096, 0 }; -const uint16_t filter_3tap_16p_117[27] = { +static const uint16_t filter_3tap_16p_117[27] = { 2048, 2048, 0, 1824, 2276, 16376, 1600, 2496, 16380, @@ -61,7 +61,7 @@ const uint16_t filter_3tap_16p_117[27] = { 428, 3236, 428 }; -const uint16_t filter_3tap_16p_150[27] = { +static const uint16_t filter_3tap_16p_150[27] = { 2048, 2048, 0, 1872, 2184, 36, 1692, 2308, 88, @@ -73,7 +73,7 @@ const uint16_t filter_3tap_16p_150[27] = { 696, 2696, 696 }; -const uint16_t filter_3tap_16p_183[27] = { +static const uint16_t filter_3tap_16p_183[27] = { 2048, 2048, 0, 1892, 2104, 92, 1744, 2152, 196, @@ -85,7 +85,7 @@ const uint16_t filter_3tap_16p_183[27] = { 900, 2292, 900 }; -const uint16_t filter_4tap_16p_upscale[36] = { +static const uint16_t filter_4tap_16p_upscale[36] = { 0, 4096, 0, 0, 16240, 4056, 180, 16380, 16136, 3952, 404, 16364, @@ -97,7 +97,7 @@ const uint16_t filter_4tap_16p_upscale[36] = { 16128, 2304, 2304, 16128 }; -const uint16_t filter_4tap_16p_117[36] = { +static const uint16_t filter_4tap_16p_117[36] = { 428, 3236, 428, 0, 276, 3232, 604, 16364, 148, 3184, 800, 16340, @@ -109,7 +109,7 @@ const uint16_t filter_4tap_16p_117[36] = { 16212, 2216, 2216, 16212 }; -const uint16_t filter_4tap_16p_150[36] = { +static const uint16_t filter_4tap_16p_150[36] = { 696, 2700, 696, 0, 560, 2700, 848, 16364, 436, 2676, 1008, 16348, @@ -121,7 +121,7 @@ const uint16_t filter_4tap_16p_150[36] = { 16376, 2052, 2052, 16376 }; -const uint16_t filter_4tap_16p_183[36] = { +static const uint16_t filter_4tap_16p_183[36] = { 940, 2208, 940, 0, 832, 2200, 1052, 4, 728, 2180, 1164, 16, @@ -133,7 +133,7 @@ const uint16_t filter_4tap_16p_183[36] = { 232, 1812, 1812, 232 }; -const uint16_t filter_2tap_64p[66] = { +static const uint16_t filter_2tap_64p[66] = { 4096, 0, 4032, 64, 3968, 128, @@ -168,7 +168,7 @@ const uint16_t filter_2tap_64p[66] = { 2112, 1984, 2048, 2048 }; -const uint16_t filter_3tap_64p_upscale[99] = { +static const uint16_t filter_3tap_64p_upscale[99] = { 2048, 2048, 0, 1960, 2140, 16376, 1876, 2236, 16364, @@ -204,7 +204,7 @@ const uint16_t filter_3tap_64p_upscale[99] = { 0, 4096, 0 }; -const uint16_t filter_3tap_64p_117[99] = { +static const uint16_t filter_3tap_64p_117[99] = { 2048, 2048, 0, 1992, 2104, 16380, 1936, 2160, 16380, @@ -240,7 +240,7 @@ const uint16_t filter_3tap_64p_117[99] = { 428, 3236, 428 }; -const uint16_t filter_3tap_64p_150[99] = { +static const uint16_t filter_3tap_64p_150[99] = { 2048, 2048, 0, 2004, 2080, 8, 1960, 2116, 16, @@ -276,7 +276,7 @@ const uint16_t filter_3tap_64p_150[99] = { 696, 2696, 696 }; -const uint16_t filter_3tap_64p_183[99] = { +static const uint16_t filter_3tap_64p_183[99] = { 2048, 2048, 0, 2008, 2060, 20, 1968, 2076, 44, @@ -312,7 +312,7 @@ const uint16_t filter_3tap_64p_183[99] = { 900, 2292, 900 }; -const uint16_t filter_4tap_64p_upscale[132] = { +static const uint16_t filter_4tap_64p_upscale[132] = { 0, 4096, 0, 0, 16344, 4092, 40, 0, 16308, 4084, 84, 16380, @@ -347,7 +347,7 @@ const uint16_t filter_4tap_64p_upscale[132] = { 16116, 2388, 2216, 16140, 16128, 2304, 2304, 16128 }; -const uint16_t filter_4tap_64p_117[132] = { +static const uint16_t filter_4tap_64p_117[132] = { 420, 3248, 420, 0, 380, 3248, 464, 16380, 344, 3248, 508, 16372, @@ -382,7 +382,7 @@ const uint16_t filter_4tap_64p_117[132] = { 16212, 2276, 2160, 16212, 16212, 2220, 2220, 16212 }; -const uint16_t filter_4tap_64p_150[132] = { +static const uint16_t filter_4tap_64p_150[132] = { 696, 2700, 696, 0, 660, 2704, 732, 16380, 628, 2704, 768, 16376, @@ -417,7 +417,7 @@ const uint16_t filter_4tap_64p_150[132] = { 4, 2112, 1996, 16364, 16380, 2072, 2036, 16372 }; -const uint16_t filter_4tap_64p_183[132] = { +static const uint16_t filter_4tap_64p_183[132] = { 944, 2204, 944, 0, 916, 2204, 972, 0, 888, 2200, 996, 0, @@ -452,7 +452,7 @@ const uint16_t filter_4tap_64p_183[132] = { 252, 1832, 1784, 220, 236, 1808, 1808, 236 }; -const uint16_t filter_5tap_64p_upscale[165] = { +static const uint16_t filter_5tap_64p_upscale[165] = { 15936, 2496, 2496, 15936, 0, 15948, 2404, 2580, 15924, 0, 15960, 2312, 2664, 15912, 4, @@ -487,7 +487,7 @@ const uint16_t filter_5tap_64p_upscale[165] = { 16376, 48, 4092, 16336, 4, 0, 0, 4096, 0, 0 }; -const uint16_t filter_5tap_64p_117[165] = { +static const uint16_t filter_5tap_64p_117[165] = { 16056, 2372, 2372, 16056, 0, 16052, 2312, 2432, 16060, 0, 16052, 2252, 2488, 16064, 0, @@ -522,7 +522,7 @@ const uint16_t filter_5tap_64p_117[165] = { 16248, 504, 3428, 408, 16268, 16256, 456, 3428, 456, 16256 }; -const uint16_t filter_5tap_64p_150[165] = { +static const uint16_t filter_5tap_64p_150[165] = { 16368, 2064, 2064, 16368, 0, 16352, 2028, 2100, 16380, 16380, 16340, 1996, 2132, 12, 16376, @@ -557,7 +557,7 @@ const uint16_t filter_5tap_64p_150[165] = { 16248, 860, 2708, 788, 16252, 16248, 824, 2708, 824, 16248 }; -const uint16_t filter_5tap_64p_183[165] = { +static const uint16_t filter_5tap_64p_183[165] = { 228, 1816, 1816, 228, 0, 216, 1792, 1836, 248, 16380, 200, 1772, 1860, 264, 16376, @@ -592,7 +592,7 @@ const uint16_t filter_5tap_64p_183[165] = { 16340, 1000, 2232, 944, 16336, 16340, 972, 2232, 972, 16340 }; -const uint16_t filter_6tap_64p_upscale[198] = { +static const uint16_t filter_6tap_64p_upscale[198] = { 0, 0, 4092, 0, 0, 0, 12, 16332, 4092, 52, 16368, 0, 24, 16280, 4088, 108, 16356, 0, @@ -627,7 +627,7 @@ const uint16_t filter_6tap_64p_upscale[198] = { 104, 15816, 2588, 2416, 15840, 92, 100, 15828, 2504, 2504, 15828, 100 }; -const uint16_t filter_6tap_64p_117[198] = { +static const uint16_t filter_6tap_64p_117[198] = { 16168, 476, 3568, 476, 16168, 0, 16180, 428, 3564, 528, 16156, 0, 16192, 376, 3556, 584, 16144, 4, @@ -662,7 +662,7 @@ const uint16_t filter_6tap_64p_117[198] = { 40, 15956, 2496, 2376, 15944, 44, 40, 15952, 2436, 2436, 15952, 40 }; -const uint16_t filter_6tap_64p_150[198] = { +static const uint16_t filter_6tap_64p_150[198] = { 16148, 920, 2724, 920, 16148, 0, 16152, 880, 2724, 956, 16148, 0, 16152, 844, 2720, 996, 16144, 0, @@ -697,7 +697,7 @@ const uint16_t filter_6tap_64p_150[198] = { 16292, 8, 2172, 2108, 16356, 16304, 16300, 16372, 2140, 2140, 16372, 16300 }; -const uint16_t filter_6tap_64p_183[198] = { +static const uint16_t filter_6tap_64p_183[198] = { 16296, 1032, 2196, 1032, 16296, 0, 16292, 1004, 2200, 1060, 16304, 16380, 16288, 976, 2200, 1088, 16308, 16380, @@ -732,7 +732,7 @@ const uint16_t filter_6tap_64p_183[198] = { 16288, 296, 1880, 1840, 256, 16296, 16292, 276, 1860, 1860, 276, 16292 }; -const uint16_t filter_7tap_64p_upscale[231] = { +static const uint16_t filter_7tap_64p_upscale[231] = { 176, 15760, 2488, 2488, 15760, 176, 0, 172, 15772, 2404, 2572, 15752, 180, 16380, 168, 15784, 2324, 2656, 15740, 184, 16380, @@ -767,7 +767,7 @@ const uint16_t filter_7tap_64p_upscale[231] = { 0, 16364, 56, 4092, 16328, 16, 16380, 0, 0, 0, 4096, 0, 0, 0 }; -const uint16_t filter_7tap_64p_117[231] = { +static const uint16_t filter_7tap_64p_117[231] = { 92, 15868, 2464, 2464, 15868, 92, 0, 96, 15864, 2404, 2528, 15876, 88, 0, 100, 15860, 2344, 2584, 15884, 84, 0, @@ -802,7 +802,7 @@ const uint16_t filter_7tap_64p_117[231] = { 68, 16108, 504, 3572, 396, 16140, 60, 64, 16124, 452, 3576, 452, 16124, 64 }; -const uint16_t filter_7tap_64p_150[231] = { +static const uint16_t filter_7tap_64p_150[231] = { 16224, 16380, 2208, 2208, 16380, 16224, 0, 16232, 16360, 2172, 2236, 16, 16216, 0, 16236, 16340, 2140, 2268, 40, 16212, 0, @@ -837,7 +837,7 @@ const uint16_t filter_7tap_64p_150[231] = { 16380, 16076, 1020, 2740, 944, 16076, 0, 0, 16076, 984, 2740, 984, 16076, 0 }; -const uint16_t filter_7tap_64p_183[231] = { +static const uint16_t filter_7tap_64p_183[231] = { 16216, 324, 1884, 1884, 324, 16216, 0, 16220, 304, 1864, 1904, 344, 16216, 0, 16224, 284, 1844, 1924, 364, 16216, 0, @@ -872,7 +872,7 @@ const uint16_t filter_7tap_64p_183[231] = { 16316, 16284, 1132, 2216, 1076, 16268, 16324, 16320, 16276, 1104, 2216, 1104, 16276, 16320 }; -const uint16_t filter_8tap_64p_upscale[264] = { +static const uint16_t filter_8tap_64p_upscale[264] = { 0, 0, 0, 4096, 0, 0, 0, 0, 16376, 20, 16328, 4092, 56, 16364, 4, 0, 16372, 36, 16272, 4088, 116, 16340, 12, 0, @@ -907,7 +907,7 @@ const uint16_t filter_8tap_64p_upscale[264] = { 16328, 248, 15692, 2616, 2448, 15716, 240, 16332, 16332, 244, 15704, 2532, 2532, 15704, 244, 16332 }; -const uint16_t filter_8tap_64p_117[264] = { +static const uint16_t filter_8tap_64p_117[264] = { 116, 16100, 428, 3564, 428, 16100, 116, 0, 112, 16116, 376, 3564, 484, 16084, 120, 16380, 104, 16136, 324, 3560, 540, 16064, 124, 16380, @@ -942,7 +942,7 @@ const uint16_t filter_8tap_64p_117[264] = { 16372, 136, 15816, 2548, 2428, 15804, 148, 16368, 16372, 140, 15812, 2488, 2488, 15812, 140, 16372 }; -const uint16_t filter_8tap_64p_150[264] = { +static const uint16_t filter_8tap_64p_150[264] = { 16380, 16020, 1032, 2756, 1032, 16020, 16380, 0, 0, 16020, 992, 2756, 1068, 16024, 16376, 0, 4, 16020, 952, 2752, 1108, 16024, 16372, 0, @@ -977,7 +977,7 @@ const uint16_t filter_8tap_64p_150[264] = { 44, 16160, 24, 2244, 2180, 16364, 16176, 40, 44, 16168, 4, 2212, 2212, 4, 16168, 44 }; -const uint16_t filter_8tap_64p_183[264] = { +static const uint16_t filter_8tap_64p_183[264] = { 16264, 16264, 1164, 2244, 1164, 16264, 16264, 0, 16268, 16256, 1136, 2240, 1188, 16272, 16260, 0, 16272, 16248, 1108, 2240, 1216, 16280, 16256, 0, @@ -1107,3 +1107,13 @@ const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio) else return filter_8tap_64p_183; } + +const uint16_t *get_filter_2tap_16p(void) +{ + return filter_2tap_16p; +} + +const uint16_t *get_filter_2tap_64p(void) +{ + return filter_2tap_64p; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index 0e366021cf16..a8f60d7531be 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -306,7 +306,7 @@ static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio) else if (taps == 3) return get_filter_3tap_16p(ratio); else if (taps == 2) - return filter_2tap_16p; + return get_filter_2tap_16p(); else if (taps == 1) return NULL; else { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c index c84823a40f61..47390dc58306 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c @@ -489,7 +489,7 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) if (taps == 4) return get_filter_4tap_64p(ratio); else if (taps == 2) - return filter_2tap_64p; + return get_filter_2tap_64p(); else if (taps == 1) return NULL; else { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index b62cb38f523c..82b8887d4973 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -240,7 +240,7 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) else if (taps == 3) return get_filter_3tap_64p(ratio); else if (taps == 2) - return filter_2tap_64p; + return get_filter_2tap_64p(); else if (taps == 1) return NULL; else { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 32947450e702..9d4a3a0098a9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -240,8 +240,8 @@ struct transform_funcs { }; -extern const uint16_t filter_2tap_16p[18]; -extern const uint16_t filter_2tap_64p[66]; +const uint16_t *get_filter_2tap_16p(void); +const uint16_t *get_filter_2tap_64p(void); const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio); const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio); -- GitLab From b3fbdcec5e6c16c93867289ae0960a64c423eb34 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:10:22 +1000 Subject: [PATCH 0923/2898] amdgpu/dc: drop display_pipe_clocks.c. This code isn't used at all in the kernel tree, perhaps it can wait to be imported when it is. It also does a lot of floating point calcs, so probably good to drop it until it's needed and we can ensure proper fpu accessors. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +- .../drm/amd/display/dc/dml/display_mode_lib.h | 1 - .../amd/display/dc/dml/display_pipe_clocks.c | 367 ------------------ .../amd/display/dc/dml/display_pipe_clocks.h | 41 -- 4 files changed, 1 insertion(+), 410 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 9d7791d00e97..a6bf36466497 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -13,7 +13,7 @@ CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 -DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ +DML = display_mode_lib.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o display_watermark.o \ soc_bounding_box.o dml_common_defs.o display_mode_support.o diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index e2e311138358..eb1c8e6e7f23 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -28,7 +28,6 @@ #include "dml_common_defs.h" #include "soc_bounding_box.h" #include "display_watermark.h" -#include "display_pipe_clocks.h" #include "display_rq_dlg_calc.h" #include "display_mode_support.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c deleted file mode 100644 index 2e4dc57cafa0..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "display_pipe_clocks.h" -#include "display_mode_lib.h" -#include "soc_bounding_box.h" - -static enum voltage_state power_state( - struct display_mode_lib *mode_lib, - double dispclk, - double dppclk) -{ - enum voltage_state state1; - enum voltage_state state2; - - if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) - state1 = dm_vmin; - else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) - state1 = dm_vnom; - else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) - state1 = dm_vmax; - else - state1 = dm_vmax_exceeded; - - if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) - state2 = dm_vmin; - else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) - state2 = dm_vnom; - else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) - state2 = dm_vmax; - else - state2 = dm_vmax_exceeded; - - if (state1 > state2) - return state1; - else - return state2; -} - -static unsigned int dpp_in_grp( - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - unsigned int hsplit_grp) -{ - unsigned int num_dpp = 0; - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - if (e2e[i].pipe.src.is_hsplit) { - if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { - num_dpp++; - } - } - } - - if (0 == num_dpp) - num_dpp = 1; - - return num_dpp; -} - -static void calculate_pipe_clk_requirement( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp, - double *dppclk, - double *dispclk, - bool *dppdiv) -{ - double pscl_throughput = 0.0; - double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; - double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; - double max_htaps = e2e->pipe.scale_taps.htaps; - double max_vtaps = e2e->pipe.scale_taps.vtaps; - double dpp_clock_divider = (double) num_dpp_in_grp; - double dispclk_dppclk_ratio; - double dispclk_ramp_margin_percent; - - if (max_hratio > 1.0) { - double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) - / dml_ceil(max_htaps / 6.0); - pscl_throughput = dml_min( - pscl_to_lb, - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); - } else { - pscl_throughput = dml_min( - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); - } - - DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); - DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); - *dppclk = dml_max( - max_vtaps / 6.0 * dml_min(1.0, max_hratio), - max_hratio * max_vratio / pscl_throughput); - DTRACE("pixel rate multiplier: %f", *dppclk); - *dppclk = dml_max(*dppclk, 1.0); - DTRACE("pixel rate multiplier clamped: %f", *dppclk); - *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; - - *dppclk = *dppclk / dpp_clock_divider; - DTRACE("dppclk after split: %f", *dppclk); - - if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { - dispclk_dppclk_ratio = 2.0; - *dppdiv = true; - } else { - dispclk_dppclk_ratio = 1.0; - *dppdiv = false; - } - - dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; - - /* Comment this out because of Gabes possible bug in spreadsheet, - * just to make other cases evident during debug - * - *if(e2e->clks_cfg.voltage == dm_vmax) - * dispclk_ramp_margin_percent = 0.0; - */ - - /* account for ramping margin and downspread */ - *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) - * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) - * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); - - return; -} - -bool dml_clks_pipe_clock_requirement_fit_power_constraint( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp) -{ - double dppclk = 0; - double dispclk = 0; - bool dppdiv = 0; - - calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); - - if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { - return false; - } - - return true; -} - -static void get_plane_clks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - double *dppclks, - double *dispclks, - bool *dppdiv) -{ - /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated - * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to - * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently - * and we would expect the same result on any split pipes, which would be handled - */ - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - double num_dpp_in_grp; - double dispclk_ramp_margin_percent; - double dispclk_margined; - - if (e2e[i].pipe.src.is_hsplit) - num_dpp_in_grp = (double) dpp_in_grp( - e2e, - num_pipes, - e2e[i].pipe.src.hsplit_grp); - else - num_dpp_in_grp = 1; - - calculate_pipe_clk_requirement( - mode_lib, - &e2e[i], - num_dpp_in_grp, - &dppclks[i], - &dispclks[i], - &dppdiv[i]); - - dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; - - dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz - * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) - * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); - - DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); - - if (power_state(mode_lib, dispclks[i], dppclks[i]) - > power_state(mode_lib, dispclk_margined, dispclk_margined) - && dispclk_margined > dppclks[i]) { - if (power_state(mode_lib, dispclks[i], dppclks[i]) - > e2e[0].clks_cfg.voltage) { - dispclks[i] = dispclk_margined; - dppclks[i] = dispclk_margined; - dppdiv[i] = false; - } - } - - DTRACE("p%d: dispclk: %f", i, dispclks[i]); - } -} - -static void get_dcfclk( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - double *dcfclk_mhz) -{ - double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; - double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; - double swath_width_y[DC__NUM_PIPES__MAX]; - unsigned int i; - double total_read_bandwidth_gbps = 0.0; - - for (i = 0; i < num_pipes; i++) { - if (e2e[i].pipe.src.source_scan == dm_horz) { - swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; - } else { - swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; - } - - switch (e2e[i].pipe.src.source_format) { - case dm_444_64: - bytes_per_pixel_det_y[i] = 8.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_444_32: - bytes_per_pixel_det_y[i] = 4.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_444_16: - bytes_per_pixel_det_y[i] = 2.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_422_8: - bytes_per_pixel_det_y[i] = 2.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_422_10: - bytes_per_pixel_det_y[i] = 4.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_420_8: - bytes_per_pixel_det_y[i] = 1.0; - bytes_per_pixel_det_c[i] = 2.0; - break; - case dm_420_10: - bytes_per_pixel_det_y[i] = 4.0 / 3.0; - bytes_per_pixel_det_c[i] = 8.0 / 3.0; - break; - default: - BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ - } - } - - for (i = 0; i < num_pipes; i++) { - double read_bandwidth_plane_mbps = 0.0; - read_bandwidth_plane_mbps = (double) swath_width_y[i] - * ((double) bytes_per_pixel_det_y[i] - + (double) bytes_per_pixel_det_c[i] / 2.0) - / ((double) e2e[i].pipe.dest.htotal - / (double) e2e[i].pipe.dest.pixel_rate_mhz) - * e2e[i].pipe.scale_ratio_depth.vscl_ratio; - - if (e2e[i].pipe.src.dcc) { - read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); - } - - if (e2e[i].pipe.src.vm) { - read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); - } - - total_read_bandwidth_gbps = total_read_bandwidth_gbps - + read_bandwidth_plane_mbps / 1000.0; - } - - DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); - - (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; - - DTRACE( - "minimum theoretical dcfclk without stutter and full utilization = %f MHz", - (*dcfclk_mhz)); - -} - -struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - struct _vcs_dpi_display_pipe_clock_st clocks; - double max_dispclk = 0.0; - double dcfclk; - double dispclks[DC__NUM_PIPES__MAX]; - double dppclks[DC__NUM_PIPES__MAX]; - bool dppdiv[DC__NUM_PIPES__MAX]; - unsigned int i; - - DTRACE("Calculating pipe clocks..."); - - /* this is the theoretical minimum, have to adjust based on valid values for soc */ - get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); - - /* if(dcfclk > soc.vnom.dcfclk_mhz) - * dcfclk = soc.vmax.dcfclk_mhz; - * else if(dcfclk > soc.vmin.dcfclk_mhz) - * dcfclk = soc.vnom.dcfclk_mhz; - * else - * dcfclk = soc.vmin.dcfclk_mhz; - */ - - dcfclk = dml_socbb_voltage_scaling( - &mode_lib->soc, - (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; - clocks.dcfclk_mhz = dcfclk; - - get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); - - for (i = 0; i < num_pipes; i++) { - max_dispclk = dml_max(max_dispclk, dispclks[i]); - } - - clocks.dispclk_mhz = max_dispclk; - DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); - DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); - - for (i = 0; i < num_pipes; i++) { - if (dppclks[i] * 2 < max_dispclk) - dppdiv[i] = 1; - - if (dppdiv[i]) - clocks.dppclk_div[i] = 1; - else - clocks.dppclk_div[i] = 0; - - clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); - DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); - } - - return clocks; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h deleted file mode 100644 index aed5f33bb04f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DISPLAY_PIPE_CLOCKS_H__ -#define __DISPLAY_PIPE_CLOCKS_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); - -bool dml_clks_pipe_clock_requirement_fit_power_constraint( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp); -#endif -- GitLab From d1209512e028a917e6e70b13297ff185234ba24d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:45:25 +1000 Subject: [PATCH 0924/2898] amdgpu/dc: inline a bunch of float operations. This reduces code size for the bw calcs code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/dcn_calc_math.c | 29 --------------- .../drm/amd/display/dc/calcs/dcn_calc_math.h | 36 +++++++++++++++---- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index a18474437990..05cf5f77ec60 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -25,25 +25,6 @@ #include "dcn_calc_math.h" -float dcn_bw_mod(const float arg1, const float arg2) -{ - return arg1 - arg1 * ((int) (arg1 / arg2)); -} - -float dcn_bw_min2(const float arg1, const float arg2) -{ - return arg1 < arg2 ? arg1 : arg2; -} - -unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} -float dcn_bw_max2(const float arg1, const float arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} - float dcn_bw_floor2(const float arg, const float significance) { if (significance == 0) @@ -59,16 +40,6 @@ float dcn_bw_ceil2(const float arg, const float significance) return flr + 0.00001 >= arg ? arg : flr + significance; } -float dcn_bw_max3(float v1, float v2, float v3) -{ - return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); -} - -float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) -{ - return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); -} - float dcn_bw_pow(float a, float exp) { float temp; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h index f46ab0e24ca1..6f66d9d164d1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h @@ -26,14 +26,38 @@ #ifndef _DCN_CALC_MATH_H_ #define _DCN_CALC_MATH_H_ -float dcn_bw_mod(const float arg1, const float arg2); -float dcn_bw_min2(const float arg1, const float arg2); -unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2); -float dcn_bw_max2(const float arg1, const float arg2); +static inline float dcn_bw_mod(const float arg1, const float arg2) +{ + return arg1 - arg1 * ((int) (arg1 / arg2)); +} + +static inline float dcn_bw_min2(const float arg1, const float arg2) +{ + return arg1 < arg2 ? arg1 : arg2; +} + +static inline unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + +static inline float dcn_bw_max2(const float arg1, const float arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + +static inline float dcn_bw_max3(float v1, float v2, float v3) +{ + return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); +} + +static inline float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) +{ + return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); +} + float dcn_bw_floor2(const float arg, const float significance); float dcn_bw_ceil2(const float arg, const float significance); -float dcn_bw_max3(float v1, float v2, float v3); -float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5); float dcn_bw_pow(float a, float exp); float dcn_bw_log(float a, float b); -- GitLab From 3e8c3108dab197858e74dbb740c5312ae636ea9b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:45:26 +1000 Subject: [PATCH 0925/2898] amdgpu/dc: inline a bunch of the dml wrappers. This reduces code size. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dml/display_mode_support.c | 1 + .../amd/display/dc/dml/display_rq_dlg_calc.c | 2 + .../amd/display/dc/dml/display_watermark.c | 1 + .../drm/amd/display/dc/dml/dml_common_defs.c | 56 +---------------- .../drm/amd/display/dc/dml/dml_common_defs.h | 11 ---- .../drm/amd/display/dc/dml/dml_inline_defs.h | 61 +++++++++++++++++++ .../drm/amd/display/dc/dml/soc_bounding_box.c | 1 + 7 files changed, 67 insertions(+), 66 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c index 3b4ee74527f5..ac573568c10a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -26,6 +26,7 @@ #include "display_mode_support.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" int dml_ms_check( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_e2e_pipe_params_st *e2e, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 9fccbbffe129..7a5fb1cef303 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -25,6 +25,8 @@ #include "display_rq_dlg_calc.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" + static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c index 390f09391433..142a3284ac44 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c @@ -24,6 +24,7 @@ */ #include "display_watermark.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" static void get_bytes_per_pixel( enum source_format_class format, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 21349a022de3..c242b8d41b8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -26,26 +26,7 @@ #include "dml_common_defs.h" #include "../calcs/dcn_calc_math.h" -double dml_min(double a, double b) -{ - return (double) dcn_bw_min2(a, b); -} - -double dml_max(double a, double b) -{ - return (double) dcn_bw_max2(a, b); -} - -double dml_ceil(double a) -{ - return (double) dcn_bw_ceil2(a, 1); -} - -double dml_floor(double a) -{ - return (double) dcn_bw_floor2(a, 1); -} - +#include "dml_inline_defs.h" double dml_round(double a) { double round_pt = 0.5; @@ -58,16 +39,6 @@ double dml_round(double a) return floor; } -int dml_log2(double x) -{ - return dml_round((double)dcn_bw_log(x, 2)); -} - -double dml_pow(double a, int exp) -{ - return (double) dcn_bw_pow(a, exp); -} - unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, @@ -89,16 +60,6 @@ unsigned int dml_round_to_multiple( return (num - remainder); } -double dml_fmod(double f, int val) -{ - return (double) dcn_bw_mod(f, val); -} - -double dml_ceil_2(double f) -{ - return (double) dcn_bw_ceil2(f, 2); -} - bool dml_util_is_420(enum source_format_class sorce_format) { bool val = false; @@ -131,18 +92,3 @@ bool dml_util_is_420(enum source_format_class sorce_format) return val; } - -double dml_ceil_ex(double x, double granularity) -{ - return (double) dcn_bw_ceil2(x, granularity); -} - -double dml_floor_ex(double x, double granularity) -{ - return (double) dcn_bw_floor2(x, granularity); -} - -double dml_log(double x, double base) -{ - return (double) dcn_bw_log(x, base); -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index c5340d41eedb..c621f8321b03 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -32,20 +32,9 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); -double dml_min(double a, double b); -double dml_max(double a, double b); bool dml_util_is_420(enum source_format_class sorce_format); -double dml_ceil_ex(double x, double granularity); -double dml_floor_ex(double x, double granularity); -double dml_log(double x, double base); -double dml_ceil(double a); -double dml_floor(double a); double dml_round(double a); -int dml_log2(double x); -double dml_pow(double a, int exp); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -double dml_fmod(double f, int val); -double dml_ceil_2(double f); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h new file mode 100644 index 000000000000..1c6c631daad4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -0,0 +1,61 @@ +#ifndef __DML_INLINE_DEFS_H__ +#define __DML_INLINE_DEFS_H__ +#include "dml_common_defs.h" +#include "../calcs/dcn_calc_math.h" + +static inline double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +static inline double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +static inline double dml_ceil(double a) +{ + return (double) dcn_bw_ceil2(a, 1); +} + +static inline double dml_floor(double a) +{ + return (double) dcn_bw_floor2(a, 1); +} + +static inline int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +static inline double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + +static inline double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +static inline double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + +static inline double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +static inline double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +static inline double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index cb143d3d40f0..0745366d80bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -25,6 +25,7 @@ #include "soc_bounding_box.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" void dml_socbb_set_latencies( struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box) -- GitLab From e5bcf3d83e40cc7acc9d111519b7bacaf4a01070 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:55:25 +1000 Subject: [PATCH 0926/2898] amdgpu/dc: drop dml_util_is_420 This is unused code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/dml_common_defs.c | 33 ------------------- .../drm/amd/display/dc/dml/dml_common_defs.h | 1 - 2 files changed, 34 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index c242b8d41b8a..7c0eb52b91b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -59,36 +59,3 @@ unsigned int dml_round_to_multiple( else return (num - remainder); } - -bool dml_util_is_420(enum source_format_class sorce_format) -{ - bool val = false; - - switch (sorce_format) { - case dm_444_16: - val = false; - break; - case dm_444_32: - val = false; - break; - case dm_444_64: - val = false; - break; - case dm_420_8: - val = true; - break; - case dm_420_10: - val = true; - break; - case dm_422_8: - val = false; - break; - case dm_422_10: - val = false; - break; - default: - BREAK_TO_DEBUGGER(); - } - - return val; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index c621f8321b03..a2da3da5ef8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -32,7 +32,6 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); -bool dml_util_is_420(enum source_format_class sorce_format); double dml_round(double a); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -- GitLab From e25cb588e6c8a948df147599de5469c3a95d3682 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 11:24:06 +1000 Subject: [PATCH 0927/2898] amdgpu/dc: separate out some common code from bios parsers. This extracts the bios parser object id handling into a common file. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/Makefile | 2 +- .../gpu/drm/amd/display/dc/bios/bios_parser.c | 274 +---------------- .../drm/amd/display/dc/bios/bios_parser2.c | 284 +---------------- .../amd/display/dc/bios/bios_parser_common.c | 288 ++++++++++++++++++ .../amd/display/dc/bios/bios_parser_common.h | 33 ++ 5 files changed, 324 insertions(+), 557 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.h diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index a26cc605462d..6ec815dce9cc 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -2,7 +2,7 @@ # Makefile for the 'bios' sub-component of DAL. # It provides the parsing and executing controls for atom bios image. -BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o +BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o bios_parser_common.o BIOS += command_table2.o command_table_helper2.o bios_parser2.o diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 47d673a1f688..f6828f43eac6 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -41,6 +41,7 @@ #include "bios_parser_types_internal.h" #include "bios_parser_interface.h" +#include "bios_parser_common.h" /* TODO remove - only needed for default i2c speed */ #include "dc.h" @@ -57,18 +58,6 @@ static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = { #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table) -static enum object_type object_type_from_bios_object_id( - uint32_t bios_object_id); -static struct graphics_object_id object_id_from_bios_object_id( - uint32_t bios_object_id); -static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); -static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); -static enum connector_id connector_id_from_bios_object_id( - uint32_t bios_object_id); -static uint32_t id_from_bios_object_id(enum object_type type, - uint32_t bios_object_id); -static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); -static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); static void get_atom_data_table_revision( ATOM_COMMON_TABLE_HEADER *atom_data_tbl, struct atom_data_revision *tbl_revision); @@ -2403,267 +2392,6 @@ static uint32_t get_dst_number_from_object(struct bios_parser *bp, return *number; } - -static struct graphics_object_id object_id_from_bios_object_id( - uint32_t bios_object_id) -{ - enum object_type type; - enum object_enum_id enum_id; - struct graphics_object_id go_id = { 0 }; - - type = object_type_from_bios_object_id(bios_object_id); - - if (OBJECT_TYPE_UNKNOWN == type) - return go_id; - - enum_id = enum_id_from_bios_object_id(bios_object_id); - - if (ENUM_ID_UNKNOWN == enum_id) - return go_id; - - go_id = dal_graphics_object_id_init( - id_from_bios_object_id(type, bios_object_id), enum_id, type); - - return go_id; -} - -static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) - >> OBJECT_TYPE_SHIFT; - enum object_type object_type; - - switch (bios_object_type) { - case GRAPH_OBJECT_TYPE_GPU: - object_type = OBJECT_TYPE_GPU; - break; - case GRAPH_OBJECT_TYPE_ENCODER: - object_type = OBJECT_TYPE_ENCODER; - break; - case GRAPH_OBJECT_TYPE_CONNECTOR: - object_type = OBJECT_TYPE_CONNECTOR; - break; - case GRAPH_OBJECT_TYPE_ROUTER: - object_type = OBJECT_TYPE_ROUTER; - break; - case GRAPH_OBJECT_TYPE_GENERIC: - object_type = OBJECT_TYPE_GENERIC; - break; - default: - object_type = OBJECT_TYPE_UNKNOWN; - break; - } - - return object_type; -} - -static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_enum_id = - (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; - enum object_enum_id id; - - switch (bios_enum_id) { - case GRAPH_OBJECT_ENUM_ID1: - id = ENUM_ID_1; - break; - case GRAPH_OBJECT_ENUM_ID2: - id = ENUM_ID_2; - break; - case GRAPH_OBJECT_ENUM_ID3: - id = ENUM_ID_3; - break; - case GRAPH_OBJECT_ENUM_ID4: - id = ENUM_ID_4; - break; - case GRAPH_OBJECT_ENUM_ID5: - id = ENUM_ID_5; - break; - case GRAPH_OBJECT_ENUM_ID6: - id = ENUM_ID_6; - break; - case GRAPH_OBJECT_ENUM_ID7: - id = ENUM_ID_7; - break; - default: - id = ENUM_ID_UNKNOWN; - break; - } - - return id; -} - -static uint32_t id_from_bios_object_id(enum object_type type, - uint32_t bios_object_id) -{ - switch (type) { - case OBJECT_TYPE_GPU: - return gpu_id_from_bios_object_id(bios_object_id); - case OBJECT_TYPE_ENCODER: - return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); - case OBJECT_TYPE_CONNECTOR: - return (uint32_t)connector_id_from_bios_object_id( - bios_object_id); - case OBJECT_TYPE_GENERIC: - return generic_id_from_bios_object_id(bios_object_id); - default: - return 0; - } -} - -static enum connector_id connector_id_from_bios_object_id( - uint32_t bios_object_id) -{ - uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); - - enum connector_id id; - - switch (bios_connector_id) { - case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: - id = CONNECTOR_ID_SINGLE_LINK_DVII; - break; - case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: - id = CONNECTOR_ID_DUAL_LINK_DVII; - break; - case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: - id = CONNECTOR_ID_SINGLE_LINK_DVID; - break; - case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: - id = CONNECTOR_ID_DUAL_LINK_DVID; - break; - case CONNECTOR_OBJECT_ID_VGA: - id = CONNECTOR_ID_VGA; - break; - case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: - id = CONNECTOR_ID_HDMI_TYPE_A; - break; - case CONNECTOR_OBJECT_ID_LVDS: - id = CONNECTOR_ID_LVDS; - break; - case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: - id = CONNECTOR_ID_PCIE; - break; - case CONNECTOR_OBJECT_ID_HARDCODE_DVI: - id = CONNECTOR_ID_HARDCODE_DVI; - break; - case CONNECTOR_OBJECT_ID_DISPLAYPORT: - id = CONNECTOR_ID_DISPLAY_PORT; - break; - case CONNECTOR_OBJECT_ID_eDP: - id = CONNECTOR_ID_EDP; - break; - case CONNECTOR_OBJECT_ID_MXM: - id = CONNECTOR_ID_MXM; - break; - default: - id = CONNECTOR_ID_UNKNOWN; - break; - } - - return id; -} - -static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); - enum encoder_id id; - - switch (bios_encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_LVDS: - id = ENCODER_ID_INTERNAL_LVDS; - break; - case ENCODER_OBJECT_ID_INTERNAL_TMDS1: - id = ENCODER_ID_INTERNAL_TMDS1; - break; - case ENCODER_OBJECT_ID_INTERNAL_TMDS2: - id = ENCODER_ID_INTERNAL_TMDS2; - break; - case ENCODER_OBJECT_ID_INTERNAL_DAC1: - id = ENCODER_ID_INTERNAL_DAC1; - break; - case ENCODER_OBJECT_ID_INTERNAL_DAC2: - id = ENCODER_ID_INTERNAL_DAC2; - break; - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - id = ENCODER_ID_INTERNAL_LVTM1; - break; - case ENCODER_OBJECT_ID_HDMI_INTERNAL: - id = ENCODER_ID_INTERNAL_HDMI; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: - id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: - id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; - break; - case ENCODER_OBJECT_ID_MVPU_FPGA: - id = ENCODER_ID_EXTERNAL_MVPU_FPGA; - break; - case ENCODER_OBJECT_ID_INTERNAL_DDI: - id = ENCODER_ID_INTERNAL_DDI; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - id = ENCODER_ID_INTERNAL_UNIPHY; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - id = ENCODER_ID_INTERNAL_UNIPHY1; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - id = ENCODER_ID_INTERNAL_UNIPHY2; - break; - case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ - id = ENCODER_ID_EXTERNAL_NUTMEG; - break; - case ENCODER_OBJECT_ID_TRAVIS: - id = ENCODER_ID_EXTERNAL_TRAVIS; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: - id = ENCODER_ID_INTERNAL_UNIPHY3; - break; - default: - id = ENCODER_ID_UNKNOWN; - ASSERT(0); - break; - } - - return id; -} - -uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) -{ - return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; -} - -enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); - - enum generic_id id; - - switch (bios_generic_id) { - case GENERIC_OBJECT_ID_MXM_OPM: - id = GENERIC_ID_MXM_OPM; - break; - case GENERIC_OBJECT_ID_GLSYNC: - id = GENERIC_ID_GLSYNC; - break; - case GENERIC_OBJECT_ID_STEREO_PIN: - id = GENERIC_ID_STEREO; - break; - default: - id = GENERIC_ID_UNKNOWN; - break; - } - - return id; -} - static struct device_id device_type_from_device_id(uint16_t device_id) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 3f8e605efde9..852bb0d2eb8d 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -25,8 +25,6 @@ #include "dm_services.h" -#define _BIOS_PARSER_2_ - #include "ObjectID.h" #include "atomfirmware.h" @@ -44,6 +42,7 @@ #include "bios_parser_types_internal2.h" #include "bios_parser_interface.h" +#include "bios_parser_common.h" #define LAST_RECORD_TYPE 0xff @@ -54,26 +53,6 @@ struct i2c_id_config_access { uint8_t ucAccess; }; -static enum object_type object_type_from_bios_object_id( - uint32_t bios_object_id); - -static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id); - -static struct graphics_object_id object_id_from_bios_object_id( - uint32_t bios_object_id); - -static uint32_t id_from_bios_object_id(enum object_type type, - uint32_t bios_object_id); - -static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id); - -static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id); - -static enum connector_id connector_id_from_bios_object_id( - uint32_t bios_object_id); - -static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id); - static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, struct atom_i2c_record *record, struct graphics_object_i2c_info *info); @@ -148,267 +127,6 @@ static void get_atom_data_table_revision( (uint32_t) atom_data_tbl->content_revision & 0x3f; } -static struct graphics_object_id object_id_from_bios_object_id( - uint32_t bios_object_id) -{ - enum object_type type; - enum object_enum_id enum_id; - struct graphics_object_id go_id = { 0 }; - - type = object_type_from_bios_object_id(bios_object_id); - - if (type == OBJECT_TYPE_UNKNOWN) - return go_id; - - enum_id = enum_id_from_bios_object_id(bios_object_id); - - if (enum_id == ENUM_ID_UNKNOWN) - return go_id; - - go_id = dal_graphics_object_id_init( - id_from_bios_object_id(type, bios_object_id), - enum_id, type); - - return go_id; -} - -static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) - >> OBJECT_TYPE_SHIFT; - enum object_type object_type; - - switch (bios_object_type) { - case GRAPH_OBJECT_TYPE_GPU: - object_type = OBJECT_TYPE_GPU; - break; - case GRAPH_OBJECT_TYPE_ENCODER: - object_type = OBJECT_TYPE_ENCODER; - break; - case GRAPH_OBJECT_TYPE_CONNECTOR: - object_type = OBJECT_TYPE_CONNECTOR; - break; - case GRAPH_OBJECT_TYPE_ROUTER: - object_type = OBJECT_TYPE_ROUTER; - break; - case GRAPH_OBJECT_TYPE_GENERIC: - object_type = OBJECT_TYPE_GENERIC; - break; - default: - object_type = OBJECT_TYPE_UNKNOWN; - break; - } - - return object_type; -} - -static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_enum_id = - (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; - enum object_enum_id id; - - switch (bios_enum_id) { - case GRAPH_OBJECT_ENUM_ID1: - id = ENUM_ID_1; - break; - case GRAPH_OBJECT_ENUM_ID2: - id = ENUM_ID_2; - break; - case GRAPH_OBJECT_ENUM_ID3: - id = ENUM_ID_3; - break; - case GRAPH_OBJECT_ENUM_ID4: - id = ENUM_ID_4; - break; - case GRAPH_OBJECT_ENUM_ID5: - id = ENUM_ID_5; - break; - case GRAPH_OBJECT_ENUM_ID6: - id = ENUM_ID_6; - break; - case GRAPH_OBJECT_ENUM_ID7: - id = ENUM_ID_7; - break; - default: - id = ENUM_ID_UNKNOWN; - break; - } - - return id; -} - -static uint32_t id_from_bios_object_id(enum object_type type, - uint32_t bios_object_id) -{ - switch (type) { - case OBJECT_TYPE_GPU: - return gpu_id_from_bios_object_id(bios_object_id); - case OBJECT_TYPE_ENCODER: - return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); - case OBJECT_TYPE_CONNECTOR: - return (uint32_t)connector_id_from_bios_object_id( - bios_object_id); - case OBJECT_TYPE_GENERIC: - return generic_id_from_bios_object_id(bios_object_id); - default: - return 0; - } -} - -uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) -{ - return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; -} - -static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); - enum encoder_id id; - - switch (bios_encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_LVDS: - id = ENCODER_ID_INTERNAL_LVDS; - break; - case ENCODER_OBJECT_ID_INTERNAL_TMDS1: - id = ENCODER_ID_INTERNAL_TMDS1; - break; - case ENCODER_OBJECT_ID_INTERNAL_TMDS2: - id = ENCODER_ID_INTERNAL_TMDS2; - break; - case ENCODER_OBJECT_ID_INTERNAL_DAC1: - id = ENCODER_ID_INTERNAL_DAC1; - break; - case ENCODER_OBJECT_ID_INTERNAL_DAC2: - id = ENCODER_ID_INTERNAL_DAC2; - break; - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - id = ENCODER_ID_INTERNAL_LVTM1; - break; - case ENCODER_OBJECT_ID_HDMI_INTERNAL: - id = ENCODER_ID_INTERNAL_HDMI; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: - id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: - id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; - break; - case ENCODER_OBJECT_ID_MVPU_FPGA: - id = ENCODER_ID_EXTERNAL_MVPU_FPGA; - break; - case ENCODER_OBJECT_ID_INTERNAL_DDI: - id = ENCODER_ID_INTERNAL_DDI; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - id = ENCODER_ID_INTERNAL_UNIPHY; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - id = ENCODER_ID_INTERNAL_UNIPHY1; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - id = ENCODER_ID_INTERNAL_UNIPHY2; - break; - case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ - id = ENCODER_ID_EXTERNAL_NUTMEG; - break; - case ENCODER_OBJECT_ID_TRAVIS: - id = ENCODER_ID_EXTERNAL_TRAVIS; - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: - id = ENCODER_ID_INTERNAL_UNIPHY3; - break; - default: - id = ENCODER_ID_UNKNOWN; - ASSERT(0); - break; - } - - return id; -} - -static enum connector_id connector_id_from_bios_object_id( - uint32_t bios_object_id) -{ - uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); - - enum connector_id id; - - switch (bios_connector_id) { - case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: - id = CONNECTOR_ID_SINGLE_LINK_DVII; - break; - case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: - id = CONNECTOR_ID_DUAL_LINK_DVII; - break; - case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: - id = CONNECTOR_ID_SINGLE_LINK_DVID; - break; - case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: - id = CONNECTOR_ID_DUAL_LINK_DVID; - break; - case CONNECTOR_OBJECT_ID_VGA: - id = CONNECTOR_ID_VGA; - break; - case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: - id = CONNECTOR_ID_HDMI_TYPE_A; - break; - case CONNECTOR_OBJECT_ID_LVDS: - id = CONNECTOR_ID_LVDS; - break; - case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: - id = CONNECTOR_ID_PCIE; - break; - case CONNECTOR_OBJECT_ID_HARDCODE_DVI: - id = CONNECTOR_ID_HARDCODE_DVI; - break; - case CONNECTOR_OBJECT_ID_DISPLAYPORT: - id = CONNECTOR_ID_DISPLAY_PORT; - break; - case CONNECTOR_OBJECT_ID_eDP: - id = CONNECTOR_ID_EDP; - break; - case CONNECTOR_OBJECT_ID_MXM: - id = CONNECTOR_ID_MXM; - break; - default: - id = CONNECTOR_ID_UNKNOWN; - break; - } - - return id; -} - -enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) -{ - uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); - - enum generic_id id; - - switch (bios_generic_id) { - case GENERIC_OBJECT_ID_MXM_OPM: - id = GENERIC_ID_MXM_OPM; - break; - case GENERIC_OBJECT_ID_GLSYNC: - id = GENERIC_ID_GLSYNC; - break; - case GENERIC_OBJECT_ID_STEREO_PIN: - id = GENERIC_ID_STEREO; - break; - default: - id = GENERIC_ID_UNKNOWN; - break; - } - - return id; -} - /* BIOS oject table displaypath is per connector. * There is extra path not for connector. BIOS fill its encoderid as 0 */ diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.c new file mode 100644 index 000000000000..a8cb039d2572 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.c @@ -0,0 +1,288 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "bios_parser_common.h" +#include "include/grph_object_ctrl_defs.h" + +static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK) + >> OBJECT_TYPE_SHIFT; + enum object_type object_type; + + switch (bios_object_type) { + case GRAPH_OBJECT_TYPE_GPU: + object_type = OBJECT_TYPE_GPU; + break; + case GRAPH_OBJECT_TYPE_ENCODER: + object_type = OBJECT_TYPE_ENCODER; + break; + case GRAPH_OBJECT_TYPE_CONNECTOR: + object_type = OBJECT_TYPE_CONNECTOR; + break; + case GRAPH_OBJECT_TYPE_ROUTER: + object_type = OBJECT_TYPE_ROUTER; + break; + case GRAPH_OBJECT_TYPE_GENERIC: + object_type = OBJECT_TYPE_GENERIC; + break; + default: + object_type = OBJECT_TYPE_UNKNOWN; + break; + } + + return object_type; +} + +static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_enum_id = + (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; + enum object_enum_id id; + + switch (bios_enum_id) { + case GRAPH_OBJECT_ENUM_ID1: + id = ENUM_ID_1; + break; + case GRAPH_OBJECT_ENUM_ID2: + id = ENUM_ID_2; + break; + case GRAPH_OBJECT_ENUM_ID3: + id = ENUM_ID_3; + break; + case GRAPH_OBJECT_ENUM_ID4: + id = ENUM_ID_4; + break; + case GRAPH_OBJECT_ENUM_ID5: + id = ENUM_ID_5; + break; + case GRAPH_OBJECT_ENUM_ID6: + id = ENUM_ID_6; + break; + case GRAPH_OBJECT_ENUM_ID7: + id = ENUM_ID_7; + break; + default: + id = ENUM_ID_UNKNOWN; + break; + } + + return id; +} + +static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id) +{ + return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; +} + +static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id); + enum encoder_id id; + + switch (bios_encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + id = ENCODER_ID_INTERNAL_LVDS; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + id = ENCODER_ID_INTERNAL_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS2: + id = ENCODER_ID_INTERNAL_TMDS2; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + id = ENCODER_ID_INTERNAL_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + id = ENCODER_ID_INTERNAL_DAC2; + break; + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + id = ENCODER_ID_INTERNAL_LVTM1; + break; + case ENCODER_OBJECT_ID_HDMI_INTERNAL: + id = ENCODER_ID_INTERNAL_HDMI; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC1; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + id = ENCODER_ID_INTERNAL_KLDSCP_DAC2; + break; + case ENCODER_OBJECT_ID_MVPU_FPGA: + id = ENCODER_ID_EXTERNAL_MVPU_FPGA; + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + id = ENCODER_ID_INTERNAL_DDI; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + id = ENCODER_ID_INTERNAL_UNIPHY; + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + id = ENCODER_ID_INTERNAL_UNIPHY1; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + id = ENCODER_ID_INTERNAL_UNIPHY2; + break; + case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */ + id = ENCODER_ID_EXTERNAL_NUTMEG; + break; + case ENCODER_OBJECT_ID_TRAVIS: + id = ENCODER_ID_EXTERNAL_TRAVIS; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: + id = ENCODER_ID_INTERNAL_UNIPHY3; + break; + default: + id = ENCODER_ID_UNKNOWN; + ASSERT(0); + break; + } + + return id; +} + +static enum connector_id connector_id_from_bios_object_id( + uint32_t bios_object_id) +{ + uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id); + + enum connector_id id; + + switch (bios_connector_id) { + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I: + id = CONNECTOR_ID_SINGLE_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I: + id = CONNECTOR_ID_DUAL_LINK_DVII; + break; + case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D: + id = CONNECTOR_ID_SINGLE_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D: + id = CONNECTOR_ID_DUAL_LINK_DVID; + break; + case CONNECTOR_OBJECT_ID_VGA: + id = CONNECTOR_ID_VGA; + break; + case CONNECTOR_OBJECT_ID_HDMI_TYPE_A: + id = CONNECTOR_ID_HDMI_TYPE_A; + break; + case CONNECTOR_OBJECT_ID_LVDS: + id = CONNECTOR_ID_LVDS; + break; + case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR: + id = CONNECTOR_ID_PCIE; + break; + case CONNECTOR_OBJECT_ID_HARDCODE_DVI: + id = CONNECTOR_ID_HARDCODE_DVI; + break; + case CONNECTOR_OBJECT_ID_DISPLAYPORT: + id = CONNECTOR_ID_DISPLAY_PORT; + break; + case CONNECTOR_OBJECT_ID_eDP: + id = CONNECTOR_ID_EDP; + break; + case CONNECTOR_OBJECT_ID_MXM: + id = CONNECTOR_ID_MXM; + break; + default: + id = CONNECTOR_ID_UNKNOWN; + break; + } + + return id; +} + +static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id) +{ + uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id); + + enum generic_id id; + + switch (bios_generic_id) { + case GENERIC_OBJECT_ID_MXM_OPM: + id = GENERIC_ID_MXM_OPM; + break; + case GENERIC_OBJECT_ID_GLSYNC: + id = GENERIC_ID_GLSYNC; + break; + case GENERIC_OBJECT_ID_STEREO_PIN: + id = GENERIC_ID_STEREO; + break; + default: + id = GENERIC_ID_UNKNOWN; + break; + } + + return id; +} + +static uint32_t id_from_bios_object_id(enum object_type type, + uint32_t bios_object_id) +{ + switch (type) { + case OBJECT_TYPE_GPU: + return gpu_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_ENCODER: + return (uint32_t)encoder_id_from_bios_object_id(bios_object_id); + case OBJECT_TYPE_CONNECTOR: + return (uint32_t)connector_id_from_bios_object_id( + bios_object_id); + case OBJECT_TYPE_GENERIC: + return generic_id_from_bios_object_id(bios_object_id); + default: + return 0; + } +} + +struct graphics_object_id object_id_from_bios_object_id(uint32_t bios_object_id) +{ + enum object_type type; + enum object_enum_id enum_id; + struct graphics_object_id go_id = { 0 }; + + type = object_type_from_bios_object_id(bios_object_id); + + if (OBJECT_TYPE_UNKNOWN == type) + return go_id; + + enum_id = enum_id_from_bios_object_id(bios_object_id); + + if (ENUM_ID_UNKNOWN == enum_id) + return go_id; + + go_id = dal_graphics_object_id_init( + id_from_bios_object_id(type, bios_object_id), enum_id, type); + + return go_id; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.h new file mode 100644 index 000000000000..a076c61dfae4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_common.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __BIOS_PARSER_COMMON_H__ +#define __BIOS_PARSER_COMMON_H__ + +#include "dm_services.h" +#include "ObjectID.h" + +struct graphics_object_id object_id_from_bios_object_id(uint32_t bios_object_id); +#endif -- GitLab From 5e0adbff084f33202db36be798c583a115990392 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 12:29:53 +1000 Subject: [PATCH 0928/2898] amdgpu/dc: drop dml display_mode_support.c (v2) This code isn't used, and this function is huge, reimport later if going to be used. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 4 +- .../amd/display/dc/dml/display_mode_support.c | 2327 ----------------- .../amd/display/dc/dml/display_mode_support.h | 5 - 3 files changed, 1 insertion(+), 2335 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index a6bf36466497..ec712d727665 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -10,12 +10,10 @@ CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 - DML = display_mode_lib.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o display_watermark.o \ - soc_bounding_box.o dml_common_defs.o display_mode_support.o + soc_bounding_box.o dml_common_defs.o AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c deleted file mode 100644 index ac573568c10a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c +++ /dev/null @@ -1,2327 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "display_mode_support.h" -#include "display_mode_lib.h" - -#include "dml_inline_defs.h" -int dml_ms_check( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - int num_pipes) -{ - struct _vcs_dpi_ip_params_st *ip; - struct _vcs_dpi_soc_bounding_box_st *soc; - struct _vcs_dpi_mode_evaluation_st *me; - struct dml_ms_internal_vars *v; - int num_planes, i, j, ij, k, ijk; - - ip = &(mode_lib->ip); - soc = &(mode_lib->soc); - me = &(mode_lib->me); - v = &(mode_lib->vars); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); - - //instantiating variables to zero - v->MacroTileBlockWidthC = 0; - v->SwathWidthGranularityC = 0; - - v->DCFCLKPerState[5] = 0; - v->DCFCLKPerState[4] = 0; - v->DCFCLKPerState[3] = 0; - v->DCFCLKPerState[2] = 0; - v->DCFCLKPerState[1] = 0; - v->DCFCLKPerState[0] = 0; - - if (soc->vmin.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; - } - - if (soc->vmid.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; - } - - if (soc->vnom.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; - } - - if (soc->vmax.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; - } - - v->FabricAndDRAMBandwidthPerState[5] = 0; - v->FabricAndDRAMBandwidthPerState[4] = 0; - v->FabricAndDRAMBandwidthPerState[3] = 0; - v->FabricAndDRAMBandwidthPerState[2] = 0; - v->FabricAndDRAMBandwidthPerState[1] = 0; - v->FabricAndDRAMBandwidthPerState[0] = 0; - - if (soc->vmin.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; - } - - if (soc->vmid.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; - } - - if (soc->vnom.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; - } - - if (soc->vmax.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; - } - - v->PHYCLKPerState[5] = 0; - v->PHYCLKPerState[4] = 0; - v->PHYCLKPerState[3] = 0; - v->PHYCLKPerState[2] = 0; - v->PHYCLKPerState[1] = 0; - v->PHYCLKPerState[0] = 0; - - if (soc->vmin.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; - } - - if (soc->vmid.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; - } - - if (soc->vnom.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; - } - - if (soc->vmax.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; - } - - v->MaxDispclk[5] = 0; - v->MaxDispclk[4] = 0; - v->MaxDispclk[3] = 0; - v->MaxDispclk[2] = 0; - v->MaxDispclk[1] = 0; - v->MaxDispclk[0] = 0; - - if (soc->vmin.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmin.dispclk_mhz; - v->MaxDispclk[4] = soc->vmin.dispclk_mhz; - v->MaxDispclk[3] = soc->vmin.dispclk_mhz; - v->MaxDispclk[2] = soc->vmin.dispclk_mhz; - v->MaxDispclk[1] = soc->vmin.dispclk_mhz; - v->MaxDispclk[0] = soc->vmin.dispclk_mhz; - } - - if (soc->vmid.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmid.dispclk_mhz; - v->MaxDispclk[4] = soc->vmid.dispclk_mhz; - v->MaxDispclk[3] = soc->vmid.dispclk_mhz; - v->MaxDispclk[2] = soc->vmid.dispclk_mhz; - v->MaxDispclk[1] = soc->vmid.dispclk_mhz; - } - - if (soc->vnom.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vnom.dispclk_mhz; - v->MaxDispclk[4] = soc->vnom.dispclk_mhz; - v->MaxDispclk[3] = soc->vnom.dispclk_mhz; - v->MaxDispclk[2] = soc->vnom.dispclk_mhz; - } - - if (soc->vmax.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmax.dispclk_mhz; - v->MaxDispclk[4] = soc->vmax.dispclk_mhz; - v->MaxDispclk[3] = soc->vmax.dispclk_mhz; - } - - v->MaxDppclk[5] = 0; - v->MaxDppclk[4] = 0; - v->MaxDppclk[3] = 0; - v->MaxDppclk[2] = 0; - v->MaxDppclk[1] = 0; - v->MaxDppclk[0] = 0; - - if (soc->vmin.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmin.dppclk_mhz; - v->MaxDppclk[4] = soc->vmin.dppclk_mhz; - v->MaxDppclk[3] = soc->vmin.dppclk_mhz; - v->MaxDppclk[2] = soc->vmin.dppclk_mhz; - v->MaxDppclk[1] = soc->vmin.dppclk_mhz; - v->MaxDppclk[0] = soc->vmin.dppclk_mhz; - } - - if (soc->vmid.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmid.dppclk_mhz; - v->MaxDppclk[4] = soc->vmid.dppclk_mhz; - v->MaxDppclk[3] = soc->vmid.dppclk_mhz; - v->MaxDppclk[2] = soc->vmid.dppclk_mhz; - v->MaxDppclk[1] = soc->vmid.dppclk_mhz; - } - - if (soc->vnom.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vnom.dppclk_mhz; - v->MaxDppclk[4] = soc->vnom.dppclk_mhz; - v->MaxDppclk[3] = soc->vnom.dppclk_mhz; - v->MaxDppclk[2] = soc->vnom.dppclk_mhz; - } - - if (soc->vmax.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmax.dppclk_mhz; - v->MaxDppclk[4] = soc->vmax.dppclk_mhz; - v->MaxDppclk[3] = soc->vmax.dppclk_mhz; - } - - if (me->voltage_override == dm_vmax) { - v->VoltageOverrideLevel = NumberOfStates - 1; - } else if (me->voltage_override == dm_vnom) { - v->VoltageOverrideLevel = NumberOfStates - 2; - } else if (me->voltage_override == dm_vmid) { - v->VoltageOverrideLevel = NumberOfStates - 3; - } else { - v->VoltageOverrideLevel = 0; - } - - // Scale Ratio Support Check - - v->ScaleRatioSupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio - || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio - || scale_ratio_depth.hscl_ratio > scale_taps.htaps - || scale_ratio_depth.vscl_ratio > scale_taps.vtaps - || (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16 - && ((scale_ratio_depth.hscl_ratio / 2 - > scale_taps.htaps_c) - || (scale_ratio_depth.vscl_ratio / 2 - > scale_taps.vtaps_c)))) - - { - v->ScaleRatioSupport = 0; - } - } - - // Source Format, Pixel Format and Scan Support Check - - v->SourceFormatPixelAndScanSupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) - || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x - || src.sw_mode == dm_sw_var_d - || src.sw_mode == dm_sw_var_d_x) - && (src.source_format != dm_444_64))) { - v->SourceFormatPixelAndScanSupport = 0; - } - } - - // Bandwidth Support Check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.source_scan == dm_horz) { - v->SwathWidthYSingleDPP[k] = src.viewport_width; - } else { - v->SwathWidthYSingleDPP[k] = src.viewport_height; - } - - if (src.source_format == dm_444_64) { - v->BytePerPixelInDETY[k] = 8; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_444_32) { - v->BytePerPixelInDETY[k] = 4; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_444_16) { - v->BytePerPixelInDETY[k] = 2; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_420_8) { - v->BytePerPixelInDETY[k] = 1; - v->BytePerPixelInDETC[k] = 2; - } else { - v->BytePerPixelInDETY[k] = 4.00 / 3.00; - v->BytePerPixelInDETC[k] = 8.00 / 3.00; - } - } - - v->TotalReadBandwidthConsumedGBytePerSecond = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - - v->ReadBandwidth[k] = - v->SwathWidthYSingleDPP[k] - * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - * scale_ratio_depth.vscl_ratio - + (dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) / 2) - * (scale_ratio_depth.vscl_ratio - / 2)) - / (dest.htotal / dest.pixel_rate_mhz); - - if (src.dcc == 1) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); - } - - if (ip->pte_enable == 1 && src.source_scan != dm_horz - && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x)) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); - } else if (ip->pte_enable == 1 && src.source_scan == dm_horz - && (src.source_format == dm_444_64 || src.source_format == dm_444_32) - && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x)) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); - } else if (ip->pte_enable == 1) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); - } - - v->TotalReadBandwidthConsumedGBytePerSecond = - v->TotalReadBandwidthConsumedGBytePerSecond - + v->ReadBandwidth[k] / 1000; - } - - v->TotalWriteBandwidthConsumedGBytePerSecond = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb && dout.output_format == dm_444) { - v->WriteBandwidth[k] = dest.recout_width - / (dest.htotal / dest.pixel_rate_mhz) * 4; - } else if (dout.output_type == dm_wb) { - v->WriteBandwidth[k] = dest.recout_width - / (dest.htotal / dest.pixel_rate_mhz) * 1.5; - } else { - v->WriteBandwidth[k] = 0; - } - - v->TotalWriteBandwidthConsumedGBytePerSecond = - v->TotalWriteBandwidthConsumedGBytePerSecond - + v->WriteBandwidth[k] / 1000; - } - - v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond - + v->TotalWriteBandwidthConsumedGBytePerSecond; - - v->DCCEnabledInAnyPlane = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.dcc == 1) { - v->DCCEnabledInAnyPlane = 1; - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->ReturnBWToDCNPerState = dml_min( - soc->return_bus_width_bytes * v->DCFCLKPerState[i], - v->FabricAndDRAMBandwidthPerState[i] * 1000 - * soc->ideal_dram_bw_after_urgent_percent / 100); - - v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; - - if (v->DCCEnabledInAnyPlane == 1 - && v->ReturnBWToDCNPerState - > (v->DCFCLKPerState[i] - * soc->return_bus_width_bytes / 4)) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - v->ReturnBWToDCNPerState * 4 - * (1 - - soc->urgent_latency_us - / ((ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - / (v->ReturnBWToDCNPerState - - v->DCFCLKPerState[i] - * soc->return_bus_width_bytes - / 4) - + soc->urgent_latency_us))); - } - - v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / (v->ReturnBWToDCNPerState * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024); - - if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - 4 * v->ReturnBWToDCNPerState - * (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - * soc->return_bus_width_bytes - * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / dml_pow( - (v->ReturnBWToDCNPerState - * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024), - 2)); - } - - v->ReturnBWToDCNPerState = dml_min( - soc->return_bus_width_bytes * v->DCFCLKPerState[i], - v->FabricAndDRAMBandwidthPerState[i] * 1000); - - if (v->DCCEnabledInAnyPlane == 1 - && v->ReturnBWToDCNPerState - > (v->DCFCLKPerState[i] - * soc->return_bus_width_bytes / 4)) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - v->ReturnBWToDCNPerState * 4 - * (1 - - soc->urgent_latency_us - / ((ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - / (v->ReturnBWToDCNPerState - - v->DCFCLKPerState[i] - * soc->return_bus_width_bytes - / 4) - + soc->urgent_latency_us))); - } - - v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / (v->ReturnBWToDCNPerState * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024); - - if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - 4 * v->ReturnBWToDCNPerState - * (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - * soc->return_bus_width_bytes - * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / dml_pow( - (v->ReturnBWToDCNPerState - * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024), - 2)); - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) - && (v->TotalBandwidthConsumedGBytePerSecond * 1000 - <= v->FabricAndDRAMBandwidthPerState[i] * 1000 - * soc->ideal_dram_bw_after_urgent_percent - / 100)) { - v->BandwidthSupport[i] = 1; - } else { - v->BandwidthSupport[i] = 0; - } - } - - // Writeback Latency support check - - v->WritebackLatencySupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb && dout.output_format == dm_444 - && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) - > ((ip->writeback_luma_buffer_size_kbytes - + ip->writeback_chroma_buffer_size_kbytes) - * 1024 / soc->writeback_latency_us)) { - v->WritebackLatencySupport = 0; - } else if (dout.output_type == dm_wb - && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) - > (dml_min( - ip->writeback_luma_buffer_size_kbytes, - 2 - * ip->writeback_chroma_buffer_size_kbytes) - * 1024 / soc->writeback_latency_us)) { - v->WritebackLatencySupport = 0; - } - } - - // Re-ordering Buffer Support Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = - (soc->round_trip_ping_latency_dcfclk_cycles + 32) - / v->DCFCLKPerState[i] - + soc->urgent_out_of_order_return_per_channel_bytes - * soc->num_chans - / v->ReturnBWPerState[i]; - - if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 - / v->ReturnBWPerState[i] - > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { - v->ROBSupport[i] = 1; - } else { - v->ROBSupport[i] = 0; - } - } - - // Display IO Support Check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_format == dm_420) { - v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; - } else { - v->RequiredOutputBW = dest.pixel_rate_mhz * 3; - } - - if (dout.output_type == dm_hdmi) { - v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; - } else if (dout.output_type == dm_dp) { - v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; - } else { - v->RequiredPHYCLK[k] = 0; - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->DIOSupport[i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_output_params_st dout = - e2e[v->planes[k].e2e_index].dout; - - if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) - || (dout.output_type == dm_hdmi - && v->RequiredPHYCLK[k] > 600)) { - v->DIOSupport[i] = 0; - } - } - } - - // Total Available Writeback Support Check - - v->TotalNumberOfActiveWriteback = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb) { - v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; - } - } - - if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { - v->TotalAvailableWritebackSupport = 1; - } else { - v->TotalAvailableWritebackSupport = 0; - } - - // Maximum DISPCLK/DPPCLK Support check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - - if (scale_ratio_depth.hscl_ratio > 1) { - v->PSCL_FACTOR[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk - * scale_ratio_depth.hscl_ratio - / dml_ceil_ex(scale_taps.htaps / 6, 1)); - } else { - v->PSCL_FACTOR[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk); - } - - if (v->BytePerPixelInDETC[k] == 0) { - v->PSCL_FACTOR_CHROMA[k] = 0; - v->MinDPPCLKUsingSingleDPP[k] = - dest.pixel_rate_mhz - * dml_max( - scale_taps.vtaps / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio), - dml_max( - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / v->PSCL_FACTOR[k], - 1)); - - } else { - if (scale_ratio_depth.hscl_ratio / 2 > 1) { - v->PSCL_FACTOR_CHROMA[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk - * scale_ratio_depth.hscl_ratio / 2 - / dml_ceil_ex( - scale_taps.htaps_c - / 6, - 1)); - } else { - v->PSCL_FACTOR_CHROMA[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk); - } - v->MinDPPCLKUsingSingleDPP[k] = - dest.pixel_rate_mhz - * dml_max( - dml_max( - scale_taps.vtaps - / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio), - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / v->PSCL_FACTOR[k]), - dml_max( - dml_max( - scale_taps.vtaps_c - / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio - / 2), - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / 4 - / v->PSCL_FACTOR_CHROMA[k]), - 1)); - - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - - if (src.source_format == dm_444_64 || src.source_format == dm_444_32 - || src.source_format == dm_444_16) { - if (src.sw_mode == dm_sw_linear) { - v->Read256BlockHeightY[k] = 1; - } else if (src.source_format == dm_444_64) { - v->Read256BlockHeightY[k] = 4; - } else { - v->Read256BlockHeightY[k] = 8; - } - - v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->Read256BlockHeightY[k]; - v->Read256BlockHeightC[k] = 0; - v->Read256BlockWidthC[k] = 0; - } else { - if (src.sw_mode == dm_sw_linear) { - v->Read256BlockHeightY[k] = 1; - v->Read256BlockHeightC[k] = 1; - } else if (src.source_format == dm_420_8) { - v->Read256BlockHeightY[k] = 16; - v->Read256BlockHeightC[k] = 8; - } else { - v->Read256BlockHeightY[k] = 8; - v->Read256BlockHeightC[k] = 8; - } - - v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->Read256BlockHeightY[k]; - v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) - / v->Read256BlockHeightC[k]; - } - - if (src.source_scan == dm_horz) { - v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; - v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; - } else { - v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; - v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; - } - - if (src.source_format == dm_444_64 || src.source_format == dm_444_32 - || src.source_format == dm_444_16) { - if (src.sw_mode == dm_sw_linear - || (src.source_format == dm_444_64 - && (src.sw_mode == dm_sw_4kb_s - || src.sw_mode - == dm_sw_4kb_s_x - || src.sw_mode - == dm_sw_64kb_s - || src.sw_mode - == dm_sw_64kb_s_t - || src.sw_mode - == dm_sw_64kb_s_x - || src.sw_mode - == dm_sw_var_s - || src.sw_mode - == dm_sw_var_s_x) - && src.source_scan == dm_horz)) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - } - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else { - if (src.sw_mode == dm_sw_linear) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - if (ip->bug_forcing_LC_req_same_size_fixed == 1) { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; - } - } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; - if (ip->bug_forcing_LC_req_same_size_fixed == 1) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - } - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } - } - - if (src.sw_mode == dm_sw_linear) { - v->MaximumSwathWidth = 8192; - } else { - v->MaximumSwathWidth = 5120; - } - - v->NumberOfDPPRequiredForDETSize = - dml_ceil_ex( - v->SwathWidthYSingleDPP[k] - / dml_min( - v->MaximumSwathWidth, - ip->det_buffer_size_kbytes - * 1024 - / 2 - / (v->BytePerPixelInDETY[k] - * v->MinSwathHeightY[k] - + v->BytePerPixelInDETC[k] - / 2 - * v->MinSwathHeightC[k])), - 1); - - if (v->BytePerPixelInDETC[k] == 0) { - v->NumberOfDPPRequiredForLBSize = - dml_ceil_ex( - (scale_taps.vtaps - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1); - } else { - v->NumberOfDPPRequiredForLBSize = - dml_max( - dml_ceil_ex( - (scale_taps.vtaps - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1), - dml_ceil_ex( - (scale_taps.vtaps_c - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio - / 2, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / 2 - / dml_max( - scale_ratio_depth.hscl_ratio - / 2, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1)); - } - - v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( - v->NumberOfDPPRequiredForDETSize, - v->NumberOfDPPRequiredForLBSize); - - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->MinDispclkUsingSingleDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) - * (1 + soc->downspread_percent / 100); - v->MinDispclkUsingDualDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) - * (1 + soc->downspread_percent / 100); - - if (i < NumberOfStates) { - v->MinDispclkUsingSingleDPP = - v->MinDispclkUsingSingleDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - v->MinDispclkUsingDualDPP = - v->MinDispclkUsingDualDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - } - - if (v->MinDispclkUsingSingleDPP - <= dml_min( - v->MaxDispclk[i], - (j + 1) * v->MaxDppclk[i]) - && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { - v->NoOfDPP[ijk] = 1; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingSingleDPP); - } else if (v->MinDispclkUsingDualDPP - <= dml_min( - v->MaxDispclk[i], - (j + 1) * v->MaxDppclk[i])) { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - } else { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = - 0; - } - - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo - + i] + v->NoOfDPP[ijk]; - } - - if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] - > ip->max_num_dpp) { - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo - + j * NumberOfStatesPlusTwo + i; - - v->MinDispclkUsingSingleDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) - * (1 + soc->downspread_percent / 100); - v->MinDispclkUsingDualDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) - * (1 + soc->downspread_percent / 100); - - if (i < NumberOfStates) { - v->MinDispclkUsingSingleDPP = - v->MinDispclkUsingSingleDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - v->MinDispclkUsingDualDPP = - v->MinDispclkUsingDualDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - } - - if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { - v->NoOfDPP[ijk] = 1; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = - dml_max( - v->RequiredDISPCLK[j - * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingSingleDPP); - if (v->MinDispclkUsingSingleDPP - > dml_min( - v->MaxDispclk[i], - (j + 1) - * v->MaxDppclk[i])) { - v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + i] = - 0; - } - } else { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = - dml_max( - v->RequiredDISPCLK[j - * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - if (v->MinDispclkUsingDualDPP - > dml_min( - v->MaxDispclk[i], - (j + 1) - * v->MaxDppclk[i])) { - v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + i] = - 0; - } - } - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = - v->TotalNumberOfActiveDPP[j - * NumberOfStatesPlusTwo + i] - + v->NoOfDPP[ijk]; - } - } - } - } - - // Viewport Size Check - - v->ViewportSizeSupport = 1; - - for (k = 0; k < num_planes; k++) { - if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { - v->ViewportSizeSupport = 0; - } - } - - // Total Available Pipes Support Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] - <= ip->max_num_dpp) { - v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; - } else { - v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; - } - } - } - - // Urgent Latency Support Check - - for (j = 0; j < 2; j++) { - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - ij = j * NumberOfStatesPlusTwo + i; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] - / v->NoOfDPP[ijk]; - - v->SwathWidthGranularityY = 256 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->MaxSwathHeightY[k]; - v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( - v->SwathWidthYPerState[ijk] - 1, - v->SwathWidthGranularityY) - + v->SwathWidthGranularityY) - * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; - if (src.source_format == dm_420_10) { - v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( - v->RoundedUpMaxSwathSizeBytesY, - 256) + 256; - } - if (v->MaxSwathHeightC[k] > 0) { - v->SwathWidthGranularityC = 256 - / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) - / v->MaxSwathHeightC[k]; - } - v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( - v->SwathWidthYPerState[ijk] / 2 - 1, - v->SwathWidthGranularityC) - + v->SwathWidthGranularityC) - * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; - if (src.source_format == dm_420_10) { - v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( - v->RoundedUpMaxSwathSizeBytesC, - 256) + 256; - } - - if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC - <= ip->det_buffer_size_kbytes * 1024 / 2) { - v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; - v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; - } else { - v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; - v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; - } - - if (v->BytePerPixelInDETC[k] == 0) { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 - / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - - v->LinesInDETChroma = 0; - } else if (v->SwathHeightYPerState[ijk] - <= v->SwathHeightCPerState[ijk]) { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 - / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 - / v->BytePerPixelInDETC[k] - / (v->SwathWidthYPerState[ijk] / 2); - } else { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 - / 3 / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 - / v->BytePerPixelInDETY[k] - / (v->SwathWidthYPerState[ijk] / 2); - } - - v->EffectiveLBLatencyHidingSourceLinesLuma = - dml_min( - ip->max_line_buffer_lines, - dml_floor_ex( - ip->line_buffer_size_bits - / scale_ratio_depth.lb_depth - / (v->SwathWidthYPerState[ijk] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1)), - 1)) - - (scale_taps.vtaps - 1); - - v->EffectiveLBLatencyHidingSourceLinesChroma = - dml_min( - ip->max_line_buffer_lines, - dml_floor_ex( - ip->line_buffer_size_bits - / scale_ratio_depth.lb_depth - / (v->SwathWidthYPerState[ijk] - / 2 - / dml_max( - scale_ratio_depth.hscl_ratio - / 2, - 1)), - 1)) - - (scale_taps.vtaps_c - 1); - - v->EffectiveDETLBLinesLuma = - dml_floor_ex( - v->LinesInDETLuma - + dml_min( - v->LinesInDETLuma - * v->RequiredDISPCLK[ij] - * v->BytePerPixelInDETY[k] - * v->PSCL_FACTOR[k] - / v->ReturnBWPerState[i], - v->EffectiveLBLatencyHidingSourceLinesLuma), - v->SwathHeightYPerState[ijk]); - - v->EffectiveDETLBLinesChroma = - dml_floor_ex( - v->LinesInDETChroma - + dml_min( - v->LinesInDETChroma - * v->RequiredDISPCLK[ij] - * v->BytePerPixelInDETC[k] - * v->PSCL_FACTOR_CHROMA[k] - / v->ReturnBWPerState[i], - v->EffectiveLBLatencyHidingSourceLinesChroma), - v->SwathHeightCPerState[ijk]); - - if (v->BytePerPixelInDETC[k] == 0) { - v->UrgentLatencySupportUsPerState[ijk] = - v->EffectiveDETLBLinesLuma - * (dest.htotal - / dest.pixel_rate_mhz) - / scale_ratio_depth.vscl_ratio - - v->EffectiveDETLBLinesLuma - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk]); - } else { - v->UrgentLatencySupportUsPerState[ijk] = - dml_min( - v->EffectiveDETLBLinesLuma - * (dest.htotal - / dest.pixel_rate_mhz) - / scale_ratio_depth.vscl_ratio - - v->EffectiveDETLBLinesLuma - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk]), - v->EffectiveDETLBLinesChroma - * (dest.htotal - / dest.pixel_rate_mhz) - / (scale_ratio_depth.vscl_ratio - / 2) - - v->EffectiveDETLBLinesChroma - * v->SwathWidthYPerState[ijk] - / 2 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk])); - } - - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->UrgentLatencySupport[ij] = 1; - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (v->UrgentLatencySupportUsPerState[ijk] - < soc->urgent_latency_us / 1) { - v->UrgentLatencySupport[ij] = 0; - } - } - } - } - - // Prefetch Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->TotalNumberOfDCCActiveDPP[ij] = 0; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.dcc == 1) { - v->TotalNumberOfDCCActiveDPP[ij] = - v->TotalNumberOfDCCActiveDPP[ij] - + v->NoOfDPP[ijk]; - } - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->ProjectedDCFCLKDeepSleep = 8; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->ProjectedDCFCLKDeepSleep = dml_max( - v->ProjectedDCFCLKDeepSleep, - dest.pixel_rate_mhz / 16); - if (v->BytePerPixelInDETC[k] == 0) { - if (scale_ratio_depth.vscl_ratio <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 64 - * scale_ratio_depth.hscl_ratio - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 64 - * v->PSCL_FACTOR[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - - } else { - if (scale_ratio_depth.vscl_ratio <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 32 - * scale_ratio_depth.hscl_ratio - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 32 - * v->PSCL_FACTOR[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 32 - * scale_ratio_depth.hscl_ratio - / 2 - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 32 - * v->PSCL_FACTOR_CHROMA[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - struct _vcs_dpi_display_output_params_st dout = - e2e[v->planes[k].e2e_index].dout; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.dcc == 1) { - v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; - v->MetaReqWidthY = 64 * 256 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->MetaReqHeightY; - v->MetaSurfaceWidthY = dml_ceil_ex( - src.viewport_width / v->NoOfDPP[ijk] - 1, - v->MetaReqWidthY) + v->MetaReqWidthY; - v->MetaSurfaceHeightY = dml_ceil_ex( - src.viewport_height - 1, - v->MetaReqHeightY) + v->MetaReqHeightY; - if (ip->pte_enable == 1) { - v->MetaPteBytesPerFrameY = - (dml_ceil_ex( - (v->MetaSurfaceWidthY - * v->MetaSurfaceHeightY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256.0 - - 4096) - / 8 - / 4096, - 1) + 1) * 64; - } else { - v->MetaPteBytesPerFrameY = 0; - } - if (src.source_scan == dm_horz) { - v->MetaRowBytesY = - v->MetaSurfaceWidthY - * v->MetaReqHeightY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256; - } else { - v->MetaRowBytesY = - v->MetaSurfaceHeightY - * v->MetaReqWidthY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256; - } - } else { - v->MetaPteBytesPerFrameY = 0; - v->MetaRowBytesY = 0; - } - - if (ip->pte_enable == 1) { - if (src.sw_mode == dm_sw_linear) { - v->MacroTileBlockSizeBytesY = 256; - v->MacroTileBlockHeightY = 1; - } else if (src.sw_mode == dm_sw_4kb_s - || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x) { - v->MacroTileBlockSizeBytesY = 4096; - v->MacroTileBlockHeightY = 4 - * v->Read256BlockHeightY[k]; - } else if (src.sw_mode == dm_sw_64kb_s - || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x) { - v->MacroTileBlockSizeBytesY = 64 * 1024; - v->MacroTileBlockHeightY = 16 - * v->Read256BlockHeightY[k]; - } else { - v->MacroTileBlockSizeBytesY = 256 * 1024; - v->MacroTileBlockHeightY = 32 - * v->Read256BlockHeightY[k]; - } - if (v->MacroTileBlockSizeBytesY <= 65536) { - v->DataPTEReqHeightY = v->MacroTileBlockHeightY; - } else { - v->DataPTEReqHeightY = 16 - * v->Read256BlockHeightY[k]; - } - v->DataPTEReqWidthY = 4096 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->DataPTEReqHeightY * 8; - if (src.sw_mode == dm_sw_linear) { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - * dml_min( - 128, - dml_pow( - 2, - dml_floor_ex( - dml_log( - ip->dpte_buffer_size_in_pte_reqs - * v->DataPTEReqWidthY - / (src.viewport_width - / v->NoOfDPP[ijk]), - 2), - 1))) - - 1) - / v->DataPTEReqWidthY, - 1) - + 1); - } else if (src.source_scan == dm_horz) { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - - 1) - / v->DataPTEReqWidthY, - 1) - + 1); - } else { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_height - - 1) - / v->DataPTEReqHeightY, - 1) - + 1); - } - } else { - v->DPTEBytesPerRowY = 0; - } - - if (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16) { - if (src.dcc == 1) { - v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; - v->MetaReqWidthC = - 64 * 256 - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->MetaReqHeightC; - v->MetaSurfaceWidthC = dml_ceil_ex( - src.viewport_width / v->NoOfDPP[ijk] - / 2 - 1, - v->MetaReqWidthC) - + v->MetaReqWidthC; - v->MetaSurfaceHeightC = dml_ceil_ex( - src.viewport_height / 2 - 1, - v->MetaReqHeightC) - + v->MetaReqHeightC; - if (ip->pte_enable == 1) { - v->MetaPteBytesPerFrameC = - (dml_ceil_ex( - (v->MetaSurfaceWidthC - * v->MetaSurfaceHeightC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256.0 - - 4096) - / 8 - / 4096, - 1) + 1) - * 64; - } else { - v->MetaPteBytesPerFrameC = 0; - } - if (src.source_scan == dm_horz) { - v->MetaRowBytesC = - v->MetaSurfaceWidthC - * v->MetaReqHeightC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256; - } else { - v->MetaRowBytesC = - v->MetaSurfaceHeightC - * v->MetaReqWidthC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256; - } - } else { - v->MetaPteBytesPerFrameC = 0; - v->MetaRowBytesC = 0; - } - - if (ip->pte_enable == 1) { - if (src.sw_mode == dm_sw_linear) { - v->MacroTileBlockSizeBytesC = 256; - v->MacroTileBlockHeightC = 1; - } else if (src.sw_mode == dm_sw_4kb_s - || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x) { - v->MacroTileBlockSizeBytesC = 4096; - v->MacroTileBlockHeightC = 4 - * v->Read256BlockHeightC[k]; - } else if (src.sw_mode == dm_sw_64kb_s - || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x) { - v->MacroTileBlockSizeBytesC = 64 * 1024; - v->MacroTileBlockHeightC = 16 - * v->Read256BlockHeightC[k]; - } else { - v->MacroTileBlockSizeBytesC = 256 * 1024; - v->MacroTileBlockHeightC = 32 - * v->Read256BlockHeightC[k]; - } - v->MacroTileBlockWidthC = - v->MacroTileBlockSizeBytesC - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->MacroTileBlockHeightC; - if (v->MacroTileBlockSizeBytesC <= 65536) { - v->DataPTEReqHeightC = - v->MacroTileBlockHeightC; - } else { - v->DataPTEReqHeightC = 16 - * v->Read256BlockHeightC[k]; - } - v->DataPTEReqWidthC = - 4096 - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->DataPTEReqHeightC - * 8; - if (src.sw_mode == dm_sw_linear) { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - / 2 - * dml_min( - 128, - dml_pow( - 2, - dml_floor_ex( - dml_log( - ip->dpte_buffer_size_in_pte_reqs - * v->DataPTEReqWidthC - / (src.viewport_width - / v->NoOfDPP[ijk] - / 2), - 2), - 1))) - - 1) - / v->DataPTEReqWidthC, - 1) - + 1); - } else if (src.source_scan == dm_horz) { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - / 2 - - 1) - / v->DataPTEReqWidthC, - 1) - + 1); - } else { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_height - / 2 - - 1) - / v->DataPTEReqHeightC, - 1) - + 1); - } - } else { - v->DPTEBytesPerRowC = 0; - } - } else { - v->DPTEBytesPerRowC = 0; - v->MetaPteBytesPerFrameC = 0; - v->MetaRowBytesC = 0; - } - - v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; - v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY - + v->MetaPteBytesPerFrameC; - v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; - - v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 - + dest.interlaced * 0.5 - * scale_ratio_depth.vscl_ratio) - / 2.0; - v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); - v->MaxNumSwY[k] = dml_ceil_ex( - (v->PrefillY[k] - 1.0) - / v->SwathHeightYPerState[ijk], - 1) + 1.0; - - if (v->PrefillY[k] > 1) { - v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) - % ((int) v->SwathHeightYPerState[ijk]); - } else { - v->MaxPartialSwY = ((int) (v->PrefillY[k] - + v->SwathHeightYPerState[ijk] - 2)) - % ((int) v->SwathHeightYPerState[ijk]); - } - v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); - - v->PrefetchLinesY[k] = v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; - - if (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16) { - v->VInitC = - (scale_ratio_depth.vscl_ratio / 2 - + scale_taps.vtaps + 1 - + dest.interlaced * 0.5 - * scale_ratio_depth.vscl_ratio - / 2) / 2.0; - v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); - v->MaxNumSwC[k] = - dml_ceil_ex( - (v->PrefillC[k] - 1.0) - / v->SwathHeightCPerState[ijk], - 1) + 1.0; - if (v->PrefillC[k] > 1) { - v->MaxPartialSwC = - ((int) (v->PrefillC[k] - 2)) - % ((int) v->SwathHeightCPerState[ijk]); - } else { - v->MaxPartialSwC = - ((int) (v->PrefillC[k] - + v->SwathHeightCPerState[ijk] - - 2)) - % ((int) v->SwathHeightCPerState[ijk]); - } - v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); - - v->PrefetchLinesC[k] = v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk] - + v->MaxPartialSwC; - } else { - v->PrefetchLinesC[k] = 0; - } - - v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz - / (v->RequiredDISPCLK[ij] / (j + 1)) - + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; - if (v->NoOfDPP[ijk] > 1) { - v->dst_x_after_scaler = v->dst_x_after_scaler - + dest.recout_width / 2.0; - } - - if (dout.output_format == dm_420) { - v->dst_y_after_scaler = 1; - } else { - v->dst_y_after_scaler = 0; - } - - v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; - - v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); - v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters - * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) - + 3 / v->RequiredDISPCLK[ij]); - v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep - + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) - + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; - v->VReadyOffset = - dml_max( - 150 - / (v->RequiredDISPCLK[ij] - / (j - + 1)), - v->TotalRepeaterDelay - + 20 - / v->ProjectedDCFCLKDeepSleep - + 10 - / (v->RequiredDISPCLK[ij] - / (j - + 1))) - * dest.pixel_rate_mhz; - - v->TimeSetup = - (v->VUpdateOffset + v->VUpdateWidth - + v->VReadyOffset) - / dest.pixel_rate_mhz; - - v->ExtraLatency = - v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] - + (v->TotalNumberOfActiveDPP[ij] - * ip->pixel_chunk_size_kbytes - + v->TotalNumberOfDCCActiveDPP[ij] - * ip->meta_chunk_size_kbytes) - * 1024 - / v->ReturnBWPerState[i]; - - if (ip->pte_enable == 1) { - v->ExtraLatency = v->ExtraLatency - + v->TotalNumberOfActiveDPP[ij] - * ip->pte_chunk_size_kbytes - * 1024 - / v->ReturnBWPerState[i]; - } - - if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one - == 1) { - v->MaximumVStartup = dest.vtotal - dest.vactive - 1; - } else { - v->MaximumVStartup = dest.vsync_plus_back_porch - 1; - } - - v->LineTimesForPrefetch[k] = - v->MaximumVStartup - - soc->urgent_latency_us - / (dest.htotal - / dest.pixel_rate_mhz) - - (v->TimeCalc + v->TimeSetup) - / (dest.htotal - / dest.pixel_rate_mhz) - - (v->dst_y_after_scaler - + v->dst_x_after_scaler - / dest.htotal); - - v->LineTimesForPrefetch[k] = dml_floor_ex( - 4.0 * (v->LineTimesForPrefetch[k] + 0.125), - 1) / 4; - - v->PrefetchBW[k] = - (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] - + 2 * v->DPTEBytesPerRow[k] - + v->PrefetchLinesY[k] - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - * v->SwathWidthYPerState[ijk] - / 2 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2)) - / (v->LineTimesForPrefetch[k] - * dest.htotal - / dest.pixel_rate_mhz); - } - - v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; - - for (k = 0; k < num_planes; k++) { - v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip - - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); - } - - v->TotalImmediateFlipBytes = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.source_format != dm_420_8 - && src.source_format != dm_420_10) { - v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes - + v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]; - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (ip->pte_enable == 1 && src.dcc == 1) { - v->TimeForMetaPTEWithImmediateFlip = - dml_max( - v->MetaPTEBytesPerFrame[k] - / v->PrefetchBW[k], - dml_max( - v->MetaPTEBytesPerFrame[k] - * v->TotalImmediateFlipBytes - / (v->BWAvailableForImmediateFlip - * (v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k])), - dml_max( - v->ExtraLatency, - dml_max( - soc->urgent_latency_us, - dest.htotal - / dest.pixel_rate_mhz - / 4)))); - - v->TimeForMetaPTEWithoutImmediateFlip = - dml_max( - v->MetaPTEBytesPerFrame[k] - / v->PrefetchBW[k], - dml_max( - v->ExtraLatency, - dest.htotal - / dest.pixel_rate_mhz - / 4)); - } else { - v->TimeForMetaPTEWithImmediateFlip = dest.htotal - / dest.pixel_rate_mhz / 4; - v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal - / dest.pixel_rate_mhz / 4; - } - - if (ip->pte_enable == 1 || src.dcc == 1) { - v->TimeForMetaAndDPTERowWithImmediateFlip = - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / v->PrefetchBW[k], - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - * v->TotalImmediateFlipBytes - / (v->BWAvailableForImmediateFlip - * (v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k])), - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithImmediateFlip, - dml_max( - v->ExtraLatency, - 2 - * soc->urgent_latency_us)))); - - v->TimeForMetaAndDPTERowWithoutImmediateFlip = - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / v->PrefetchBW[k], - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithoutImmediateFlip, - v->ExtraLatency)); - } else { - v->TimeForMetaAndDPTERowWithImmediateFlip = - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithImmediateFlip, - v->ExtraLatency - - v->TimeForMetaPTEWithImmediateFlip); - v->TimeForMetaAndDPTERowWithoutImmediateFlip = - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithoutImmediateFlip, - v->ExtraLatency - - v->TimeForMetaPTEWithoutImmediateFlip); - } - - v->LinesForMetaPTEWithImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaPTEWithImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaPTEWithoutImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaPTEWithoutImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaAndDPTERowWithImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaAndDPTERowWithImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaAndDPTERowWithoutImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = - v->LineTimesForPrefetch[k] - - v->LinesForMetaPTEWithImmediateFlip[k] - - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; - - v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = - v->LineTimesForPrefetch[k] - - v->LinesForMetaPTEWithoutImmediateFlip[k] - - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; - - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { - v->VRatioPreYWithImmediateFlip[ijk] = - v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - if (v->SwathHeightYPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillY[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreYWithImmediateFlip[ijk] = - dml_max( - v->VRatioPreYWithImmediateFlip[ijk], - (v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillY[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreYWithImmediateFlip[ijk] = - 999999; - } - } - v->VRatioPreCWithImmediateFlip[ijk] = - v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - if (v->SwathHeightCPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillC[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreCWithImmediateFlip[ijk] = - dml_max( - v->VRatioPreCWithImmediateFlip[ijk], - (v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillC[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreCWithImmediateFlip[ijk] = - 999999; - } - } - - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = - v->NoOfDPP[ijk] - * (v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 2) - * v->SwathWidthYPerState[ijk] - / (dest.htotal - / dest.pixel_rate_mhz); - } else { - v->VRatioPreYWithImmediateFlip[ijk] = 999999; - v->VRatioPreCWithImmediateFlip[ijk] = 999999; - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = - 999999; - } - - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - > 0) { - v->VRatioPreYWithoutImmediateFlip[ijk] = - v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - if (v->SwathHeightYPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillY[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreYWithoutImmediateFlip[ijk] = - dml_max( - v->VRatioPreYWithoutImmediateFlip[ijk], - (v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillY[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreYWithoutImmediateFlip[ijk] = - 999999; - } - } - v->VRatioPreCWithoutImmediateFlip[ijk] = - v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - if (v->SwathHeightCPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillC[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreCWithoutImmediateFlip[ijk] = - dml_max( - v->VRatioPreCWithoutImmediateFlip[ijk], - (v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillC[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreCWithoutImmediateFlip[ijk] = - 999999; - } - } - - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = - v->NoOfDPP[ijk] - * (v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 2) - * v->SwathWidthYPerState[ijk] - / (dest.htotal - / dest.pixel_rate_mhz); - } else { - v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; - v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = - 999999; - } - } - - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.source_format != dm_420_8 - && src.source_format != dm_420_10) { - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) - + dml_max( - v->MetaPTEBytesPerFrame[k] - / (v->LinesForMetaPTEWithImmediateFlip[k] - * dest.htotal - / dest.pixel_rate_mhz), - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] - * dest.htotal - / dest.pixel_rate_mhz)); - } else { - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); - } - } - - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; - - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); - } - - v->PrefetchSupportedWithImmediateFlip[ij] = 1; - if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - > v->ReturnBWPerState[i]) { - v->PrefetchSupportedWithImmediateFlip[ij] = 0; - } - for (k = 0; k < num_planes; k++) { - if (v->LineTimesForPrefetch[k] < 2 - || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 - || v->LinesForMetaAndDPTERowWithImmediateFlip[k] - >= 16) { - v->PrefetchSupportedWithImmediateFlip[ij] = 0; - } - } - - v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; - if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip - > v->ReturnBWPerState[i]) { - v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - for (k = 0; k < num_planes; k++) { - if (v->LineTimesForPrefetch[k] < 2 - || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 - || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] - >= 16) { - v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (((src.source_format != dm_420_8 - && src.source_format != dm_420_10) - && (v->VRatioPreYWithImmediateFlip[ijk] > 4 - || v->VRatioPreCWithImmediateFlip[ijk] - > 4)) - || ((src.source_format == dm_420_8 - || src.source_format == dm_420_10) - && (v->VRatioPreYWithoutImmediateFlip[ijk] - > 4 - || v->VRatioPreCWithoutImmediateFlip[ijk] - > 4))) { - v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; - } - } - v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 - || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { - v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - } - } - } - - // Mode Support, Voltage State and SOC Configuration - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 - && v->ViewportSizeSupport == 1 - && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 - && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 - && v->DISPCLK_DPPCLK_Support[ij] == 1 - && v->TotalAvailablePipesSupport[ij] == 1 - && v->TotalAvailableWritebackSupport == 1 - && v->WritebackLatencySupport == 1) { - if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 - && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] - == 1) { - v->ModeSupportWithImmediateFlip[ij] = 1; - } else { - v->ModeSupportWithImmediateFlip[ij] = 0; - } - if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 - && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] - == 1) { - v->ModeSupportWithoutImmediateFlip[ij] = 1; - } else { - v->ModeSupportWithoutImmediateFlip[ij] = 0; - } - } else { - v->ModeSupportWithImmediateFlip[ij] = 0; - v->ModeSupportWithoutImmediateFlip[ij] = 0; - } - } - } - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - if ((i == (NumberOfStatesPlusTwo - 1) - || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] - == 1 - || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] - == 1) && i >= v->VoltageOverrideLevel) { - v->VoltageLevelWithImmediateFlip = i; - } - } - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - if ((i == (NumberOfStatesPlusTwo - 1) - || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] - == 1 - || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] - == 1) && i >= v->VoltageOverrideLevel) { - v->VoltageLevelWithoutImmediateFlip = i; - } - } - - if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { - v->ImmediateFlipSupported = 0; - v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; - } else { - v->ImmediateFlipSupported = 1; - v->VoltageLevel = v->VoltageLevelWithImmediateFlip; - } - - v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; - v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; - - for (j = 0; j < 2; j++) { - v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + (int) v->VoltageLevel]; - for (k = 0; k < num_planes; k++) { - v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo - + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; - } - v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; - } - - ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); - - return (v->VoltageLevel); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h index ead4942f998c..d4ea0371cde2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h @@ -191,9 +191,4 @@ struct dml_ms_internal_vars { struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; }; -int dml_ms_check( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - int num_pipes); - #endif -- GitLab From e9d7dc62bc09bd95461d5444b54d59195b207fd6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 12:42:01 +1000 Subject: [PATCH 0929/2898] amdgpu/dc: don't check for 0 on register read/writes always. This adds ~50k to the driver text segment, and 10k to data segment. text data bss dec hex filename 2385556 39681 1045 2426282 2505aa drivers/gpu/drm/amd/amdgpu/amdgpu.o text data bss dec hex filename 2336593 28857 1045 2366495 241c1f drivers/gpu/drm/amd/amdgpu/amdgpu.o Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 8ab0af6f4c6b..c976e2aa10e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -96,6 +96,9 @@ irq_handler_idx dm_register_interrupt( * */ +/* enable for debugging new code, this adds 50k to the driver size. */ +/* #define DM_CHECK_ADDR_0 */ + #define dm_read_reg(ctx, address) \ dm_read_reg_func(ctx, address, __func__) @@ -105,12 +108,12 @@ static inline uint32_t dm_read_reg_func( const char *func_name) { uint32_t value; - +#ifdef DM_CHECK_ADDR_0 if (address == 0) { DC_ERR("invalid register read; address = 0\n"); return 0; } - +#endif value = cgs_read_register(ctx->cgs_device, address); return value; @@ -125,10 +128,12 @@ static inline void dm_write_reg_func( uint32_t value, const char *func_name) { +#ifdef DM_CHECK_ADDR_0 if (address == 0) { DC_ERR("invalid register write. address = 0"); return; } +#endif cgs_write_register(ctx->cgs_device, address, value); } -- GitLab From 29656a363c1f3060e9a5b3bafa0bd4b589e20e3c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 13:29:32 +1000 Subject: [PATCH 0930/2898] amdgpu/dc: remove wait_reg/wait_reg_func interfaces. These aren't used in the tree anywhere, and there is a TODO. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 46 -------------------- 1 file changed, 46 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index c976e2aa10e0..8166027d2d83 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -236,52 +236,6 @@ unsigned int generic_reg_wait(const struct dc_context *ctx, block ## reg_num ## _ ## reg_name ## __ ## reg_field ## _MASK,\ block ## reg_num ## _ ## reg_name ## __ ## reg_field ## __SHIFT) -/* TODO get rid of this pos*/ -static inline bool wait_reg_func( - const struct dc_context *ctx, - uint32_t addr, - uint32_t mask, - uint8_t shift, - uint32_t condition_value, - unsigned int interval_us, - unsigned int timeout_us) -{ - uint32_t field_value; - uint32_t reg_val; - unsigned int count = 0; - - if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) - timeout_us *= 655; /* 6553 give about 30 second before time out */ - - do { - /* try once without sleeping */ - if (count > 0) { - if (interval_us >= 1000) - msleep(interval_us/1000); - else - udelay(interval_us); - } - reg_val = dm_read_reg(ctx, addr); - field_value = get_reg_field_value_ex(reg_val, mask, shift); - count += interval_us; - - } while (field_value != condition_value && count <= timeout_us); - - ASSERT(count <= timeout_us); - - return count <= timeout_us; -} - -#define wait_reg(ctx, inst_offset, reg_name, reg_field, condition_value)\ - wait_reg_func(\ - ctx,\ - mm##reg_name + inst_offset + DCE_BASE.instance[0].segment[mm##reg_name##_BASE_IDX],\ - reg_name ## __ ## reg_field ## _MASK,\ - reg_name ## __ ## reg_field ## __SHIFT,\ - condition_value,\ - 20000,\ - 200000) - /************************************** * Power Play (PP) interfaces **************************************/ -- GitLab From a2e74cb626d2e1587a5ec35c3ccfc26104bdfa30 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 28 Sep 2017 15:39:41 -0400 Subject: [PATCH 0931/2898] drm/amd/display: Remove DWB It's not in a good shape and currently completely unused. Signed-off-by: Harry Wentland Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 - drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c | 365 ------------------ .../gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h | 277 ------------- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 57 --- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 - drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h | 193 --------- 7 files changed, 1 insertion(+), 905 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d86d9796e4cc..7fd42fc8bdfa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1525,15 +1525,6 @@ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) return dc->links[link_index]; } -struct dwbc *dc_get_dwb_at_pipe(struct dc *dc, uint32_t pipe) -{ - if ((pipe >= dwb_pipe0) && (pipe < dwb_pipe_max_num)) { - return dc->res_pool->dwbc[(int)pipe]; - } else { - return NULL; - } -} - const struct graphics_object_id dc_get_link_id_at_index( struct dc *dc, uint32_t link_index) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index e92ac2997a1a..2d6d3a371858 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,7 +3,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o dcn10_dwb.o \ + dcn10_mem_input.o dcn10_mpc.o \ dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c deleted file mode 100644 index 4ec5554f0f5b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2012-17 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - -#include "reg_helper.h" -#include "resource.h" -#include "dwb.h" -#include "dcn10_dwb.h" - - -#define REG(reg)\ - dwbc10->dwbc_regs->reg - -#define CTX \ - dwbc10->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - dwbc10->dwbc_shift->field_name, dwbc10->dwbc_mask->field_name - -#define TO_DCN10_DWBC(dwbc_base) \ - container_of(dwbc_base, struct dcn10_dwbc, base) - -static bool get_caps(struct dwbc *dwbc, struct dwb_caps *caps) -{ - if (caps) { - caps->adapter_id = 0; /* we only support 1 adapter currently */ - caps->hw_version = DCN_VERSION_1_0; - caps->num_pipes = 2; - memset(&caps->reserved, 0, sizeof(caps->reserved)); - memset(&caps->reserved2, 0, sizeof(caps->reserved2)); - caps->sw_version = dwb_ver_1_0; - caps->caps.support_dwb = true; - caps->caps.support_ogam = false; - caps->caps.support_wbscl = true; - caps->caps.support_ocsc = false; - return true; - } else { - return false; - } -} - -static bool enable(struct dwbc *dwbc) -{ - struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); - - /* disable first. */ - dwbc->funcs->disable(dwbc); - - /* disable power gating */ - REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 1, - DISPCLK_G_WB_GATE_DIS, 1, DISPCLK_G_WBSCL_GATE_DIS, 1, - WB_LB_LS_DIS, 1, WB_LUT_LS_DIS, 1); - - REG_UPDATE(WB_ENABLE, WB_ENABLE, 1); - - /* lock buffer0~buffer3 */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0xf); - - /* buffer address for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, (dwbc->config.basic_settings.luma_address[0] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[0] >> 32)); */ - /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, 0); - - /* buffer address for Chroma in planar mode (unused in packing mode) */ - REG_UPDATE(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, (dwbc->config.basic_settings.chroma_address[0] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[0] >> 32)); */ - /* right eye offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, 0); - - /* buffer address for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, (dwbc->config.basic_settings.luma_address[1] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[1] >> 32)); */ - /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, 0); - - /* buffer address for Chroma in planar mode (unused in packing mode) */ - REG_UPDATE(MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, (dwbc->config.basic_settings.chroma_address[1] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[1] >> 32)); */ - /* right eye offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, 0); - - /* buffer address for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, (dwbc->config.basic_settings.luma_address[2] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[2] >> 32)); */ - /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, 0); - - /* buffer address for Chroma in planar mode (unused in packing mode) */ - REG_UPDATE(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, (dwbc->config.basic_settings.chroma_address[2] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[2] >> 32)); */ - /* right eye offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, 0); - - /* buffer address for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, (dwbc->config.basic_settings.luma_address[3] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, (dwbc->config.basic_settings.luma_address[3] >> 32)); */ - /* right eye sub-buffer address offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, 0); - - /* buffer address for Chroma in planar mode (unused in packing mode) */ - REG_UPDATE(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, (dwbc->config.basic_settings.chroma_address[3] & 0xffffffff)); -/* REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, (dwbc->config.basic_settings.chroma_address[3] >> 32)); */ - /* right eye offset for packing mode or Luma in planar mode */ - REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, 0); - - /* setup luma & chroma size */ - REG_UPDATE(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, dwbc->config.basic_settings.luma_pitch * dwbc->config.basic_settings.dest_height); /* should be enough to contain a whole frame Luma data, same for stereo mode */ - REG_UPDATE(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, dwbc->config.basic_settings.chroma_pitch * dwbc->config.basic_settings.dest_height); /* should be enough to contain a whole frame Luma data, same for stereo mode */ - - /* enable address fence */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, 1); - - /* setup pitch */ - REG_UPDATE_2(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, dwbc->config.basic_settings.luma_pitch, - MCIF_WB_BUF_CHROMA_PITCH, dwbc->config.basic_settings.chroma_pitch); - - /* Set pitch for MC cache warm up mode */ - /* Pitch is 256 bytes aligned. The default pitch is 4K */ - REG_UPDATE(MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, 0x10); /* default is 0x10 */ - - /* Programmed by the video driver based on the CRTC timing (for DWB) */ - REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, 0); - - /* Programming dwb watermark */ - /* Watermark to generate urgent in MCIF_WB_CLI, value is determined by MCIF_WB_CLI_WATERMARK_MASK. */ - /* Program in ns. A formula will be provided in the pseudo code to calculate the value. */ - REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x0); - REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkA */ - REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x1); - REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkB */ - REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x2); - REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkC */ - REG_UPDATE(MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, 0x3); - REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, 0xffff); /* urgent_watermarkD */ - - /* Programming nb pstate watermark */ - REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x0); - REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkA */ - REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x1); - REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkB */ - REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x2); - REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkC */ - REG_UPDATE(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x3); - REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, 0xffff); /* nbp_state_change_watermarkD */ - - /* buf_lh_capability = (buffer_size / byte_per_pixel)*time_per_pixel; //client buffer latency hiding capability */ - /* if (MCIF_WB_CLI_WATERMARK * 2 < buf_lh_capability) //factor '2' can be adjusted if better value is identified during bringup/debug */ - /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = MCIF_WB_CLI_WATERMARK * 2; */ - /* else */ - /* MULTI_LEVEL_QOS_CTRL.MAX_SCALED_TIME_TO_URGENT = buf_lh_capability; //ensure QoS can be fully mapped to [0:15] region in any scenario */ - - REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, 31); - - /* Set arbitration unit for Luma/Chroma */ - /* arb_unit=2 should be chosen for more efficiency */ - REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, 2); /* Arbitration size, 0: 512 bytes 1: 1024 bytes 2: 2048 Bytes */ - - /* Program VMID, don't support virtual mode, won't set VMID */ - /* REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, pVmid); */ - - if (dwbc->config.basic_settings.input_pipe_select == dwb_pipe0) { - REG_UPDATE(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, dwbc->config.basic_settings.input_src_select - dwb_src_otg0); - } else if (dwbc->config.basic_settings.input_pipe_select == dwb_pipe1) { - REG_UPDATE(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, dwbc->config.basic_settings.input_src_select - dwb_src_otg0); - } - - /* Set interrupt mask */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, 0); /* Disable interrupt to SW. (the default value is 0.) */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, 0); /* Disable slice complete interrupt to SW.(the default value is 0.) */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, 0); /* Disable frame buffer overrun interrupt to SW. (the default value is 0.) */ - - REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, 1); /* Enable interrupt to VCE */ - REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, 0); /* Disable slice complete interrupt to VCE. */ - - /* ////////////////// */ - /* Enable Mcifwb */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, 1); /* Start working */ - - /* unlock sw lock. */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0); - - dwbc->status.enabled = true; - - return true; -} - -static bool disable(struct dwbc *dwbc) -{ - struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); - - /* disable CNV */ - REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_EN, 0); - - /* disable WB */ - REG_UPDATE(WB_ENABLE, WB_ENABLE, 0); - - /* soft reset */ - REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 1); - REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 0); - - /* enable power gating */ - REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 0, - DISPCLK_G_WB_GATE_DIS, 0, DISPCLK_G_WBSCL_GATE_DIS, 0, - WB_LB_LS_DIS, 0, WB_LUT_LS_DIS, 0); - - /* disable buffer manager */ - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, 0); - - dwbc->status.enabled = false; - - return true; -} - -static bool get_status(struct dwbc *dwbc, struct dwb_status *status) -{ - if (status) { - memcpy(status, &dwbc->status, sizeof(struct dwb_status)); - return true; - } else { - return false; - } -} - -static bool dump_frame(struct dwbc *dwbc, struct dwb_frame_info *frame_info, - unsigned char *luma_buffer, unsigned char *chroma_buffer, - unsigned char *dest_luma_buffer, unsigned char *dest_chroma_buffer) -{ - struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc); - - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0xf); - - memcpy(dest_luma_buffer, luma_buffer, dwbc->config.basic_settings.luma_pitch * dwbc->config.basic_settings.dest_height); - memcpy(dest_chroma_buffer, chroma_buffer, dwbc->config.basic_settings.chroma_pitch * dwbc->config.basic_settings.dest_height / 2); - - REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, 0x0); - - frame_info->format = dwbc->config.advanced_settings.out_format; - frame_info->width = dwbc->config.basic_settings.dest_width; - frame_info->height = dwbc->config.basic_settings.dest_height; - frame_info->luma_pitch = dwbc->config.basic_settings.luma_pitch; - frame_info->chroma_pitch = dwbc->config.basic_settings.chroma_pitch; - frame_info->size = dwbc->config.basic_settings.dest_height * (dwbc->config.basic_settings.luma_pitch + dwbc->config.basic_settings.chroma_pitch); - - return true; -} - -static bool set_basic_settings(struct dwbc *dwbc, - const struct dwb_basic_settings *basic_settings) -{ - if (basic_settings) { - memcpy(&dwbc->config.basic_settings, basic_settings, sizeof(struct dwb_basic_settings)); - return true; - } else { - return false; - } -} - -static bool get_basic_settings(struct dwbc *dwbc, - struct dwb_basic_settings *basic_settings) -{ - if (basic_settings) { - memcpy(basic_settings, &dwbc->config.basic_settings, sizeof(struct dwb_basic_settings)); - return true; - } else { - return false; - } -} - -static bool set_advanced_settings(struct dwbc *dwbc, - const struct dwb_advanced_settings *advanced_settings) -{ - if (advanced_settings) { - if (advanced_settings->uFlag & sf_output_format) { - dwbc->config.advanced_settings.uFlag |= sf_output_format; - dwbc->config.advanced_settings.out_format = advanced_settings->out_format; - } - - if (advanced_settings->uFlag & sf_capture_rate) { - dwbc->config.advanced_settings.uFlag |= sf_capture_rate; - dwbc->config.advanced_settings.capture_rate = advanced_settings->capture_rate; - } - - return true; - } else { - return false; - } -} - -static bool get_advanced_settings(struct dwbc *dwbc, - struct dwb_advanced_settings *advanced_settings) -{ - if (advanced_settings) { - memcpy(advanced_settings, &dwbc->config.advanced_settings, sizeof(struct dwb_advanced_settings)); - return true; - } else { - return false; - } -} - -static bool reset_advanced_settings(struct dwbc *dwbc) -{ - dwbc->config.advanced_settings.uFlag = 0; - dwbc->config.advanced_settings.out_format = dwb_scaler_mode_bypass444; - dwbc->config.advanced_settings.capture_rate = dwb_capture_rate_0; - - return true; -} - -const struct dwbc_funcs dcn10_dwbc_funcs = { - .get_caps = get_caps, - .enable = enable, - .disable = disable, - .get_status = get_status, - .dump_frame = dump_frame, - .set_basic_settings = set_basic_settings, - .get_basic_settings = get_basic_settings, - .set_advanced_settings = set_advanced_settings, - .get_advanced_settings = get_advanced_settings, - .reset_advanced_settings = reset_advanced_settings, -}; - -void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, - struct dc_context *ctx, - const struct dcn10_dwbc_registers *dwbc_regs, - const struct dcn10_dwbc_shift *dwbc_shift, - const struct dcn10_dwbc_mask *dwbc_mask, - int inst) -{ - dwbc10->base.ctx = ctx; - - dwbc10->base.inst = inst; - dwbc10->base.funcs = &dcn10_dwbc_funcs; - - dwbc10->dwbc_regs = dwbc_regs; - dwbc10->dwbc_shift = dwbc_shift; - dwbc10->dwbc_mask = dwbc_mask; -} - - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h deleted file mode 100644 index 1fdc2be42fa9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.h +++ /dev/null @@ -1,277 +0,0 @@ -/* Copyright 2012-17 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DC_DWBC_DCN10_H__ -#define __DC_DWBC_DCN10_H__ - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - -/* DCN */ -#define BASE_INNER(seg) \ - DCE_BASE__INST0_SEG ## seg - -#define BASE(seg) \ - BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - - -#define DWBC_COMMON_REG_LIST_DCN1_0(inst) \ - SRI(WB_ENABLE, CNV, inst),\ - SRI(WB_EC_CONFIG, CNV, inst),\ - SRI(CNV_MODE, CNV, inst),\ - SRI(WB_SOFT_RESET, CNV, inst),\ - SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ - SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB, inst),\ - SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MCIF_WB, inst),\ - SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ - SRI(MCIF_WB_WATERMARK, MCIF_WB, inst),\ - SRI(MCIF_WB_WARM_UP_CNTL, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ - SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ - .DWB_SOURCE_SELECT = mmDWB_SOURCE_SELECT\ - -#define DWBC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh) \ - SF(CNV0_WB_ENABLE, WB_ENABLE, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\ - SF(CNV0_WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_TYPE, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_EYE_SELECTION, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_NEW_CONTENT, mask_sh),\ - SF(CNV0_CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\ - SF(CNV0_WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_DUALSIZE_REQ, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_P_VMID, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_OFFSET, MCIF_WB_BUF_1_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_OFFSET, MCIF_WB_BUF_1_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_OFFSET, MCIF_WB_BUF_2_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_OFFSET, MCIF_WB_BUF_2_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_OFFSET, MCIF_WB_BUF_3_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_OFFSET, MCIF_WB_BUF_3_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_OFFSET, MCIF_WB_BUF_4_ADDR_Y_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_OFFSET, MCIF_WB_BUF_4_ADDR_C_OFFSET, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK_IGNORE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_INT_ACK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_LOCK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_WARM_UP_CNTL, MCIF_WB_PITCH_SIZE_WARMUP, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ - SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) - -#define DWBC_REG_FIELD_LIST(type) \ - type WB_ENABLE;\ - type DISPCLK_R_WB_GATE_DIS;\ - type DISPCLK_G_WB_GATE_DIS;\ - type DISPCLK_G_WBSCL_GATE_DIS;\ - type WB_LB_LS_DIS;\ - type WB_LB_SD_DIS;\ - type WB_LUT_LS_DIS;\ - type CNV_WINDOW_CROP_EN;\ - type CNV_STEREO_TYPE;\ - type CNV_INTERLACED_MODE;\ - type CNV_EYE_SELECTION;\ - type CNV_STEREO_POLARITY;\ - type CNV_INTERLACED_FIELD_ORDER;\ - type CNV_STEREO_SPLIT;\ - type CNV_NEW_CONTENT;\ - type CNV_FRAME_CAPTURE_EN;\ - type WB_SOFT_RESET;\ - type MCIF_WB_BUFMGR_ENABLE;\ - type MCIF_WB_BUF_DUALSIZE_REQ;\ - type MCIF_WB_BUFMGR_SW_INT_EN;\ - type MCIF_WB_BUFMGR_SW_INT_ACK;\ - type MCIF_WB_BUFMGR_SW_SLICE_INT_EN;\ - type MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN;\ - type MCIF_WB_BUFMGR_SW_LOCK;\ - type MCIF_WB_P_VMID;\ - type MCIF_WB_BUF_ADDR_FENCE_EN;\ - type MCIF_WB_BUF_LUMA_PITCH;\ - type MCIF_WB_BUF_CHROMA_PITCH;\ - type MCIF_WB_CLIENT_ARBITRATION_SLICE;\ - type MCIF_WB_TIME_PER_PIXEL;\ - type WM_CHANGE_ACK_FORCE_ON;\ - type MCIF_WB_CLI_WATERMARK_MASK;\ - type MCIF_WB_BUF_1_ADDR_Y;\ - type MCIF_WB_BUF_1_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_1_ADDR_C;\ - type MCIF_WB_BUF_1_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_2_ADDR_Y;\ - type MCIF_WB_BUF_2_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_2_ADDR_C;\ - type MCIF_WB_BUF_2_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_3_ADDR_Y;\ - type MCIF_WB_BUF_3_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_3_ADDR_C;\ - type MCIF_WB_BUF_3_ADDR_C_OFFSET;\ - type MCIF_WB_BUF_4_ADDR_Y;\ - type MCIF_WB_BUF_4_ADDR_Y_OFFSET;\ - type MCIF_WB_BUF_4_ADDR_C;\ - type MCIF_WB_BUF_4_ADDR_C_OFFSET;\ - type MCIF_WB_BUFMGR_VCE_LOCK_IGNORE;\ - type MCIF_WB_BUFMGR_VCE_INT_EN;\ - type MCIF_WB_BUFMGR_VCE_INT_ACK;\ - type MCIF_WB_BUFMGR_VCE_SLICE_INT_EN;\ - type MCIF_WB_BUFMGR_VCE_LOCK;\ - type MCIF_WB_BUFMGR_SLICE_SIZE;\ - type NB_PSTATE_CHANGE_REFRESH_WATERMARK;\ - type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST;\ - type NB_PSTATE_CHANGE_FORCE_ON;\ - type NB_PSTATE_ALLOW_FOR_URGENT;\ - type NB_PSTATE_CHANGE_WATERMARK_MASK;\ - type MCIF_WB_CLI_WATERMARK;\ - type MCIF_WB_CLI_CLOCK_GATER_OVERRIDE;\ - type MCIF_WB_PITCH_SIZE_WARMUP;\ - type MCIF_WB_BUF_LUMA_SIZE;\ - type MCIF_WB_BUF_CHROMA_SIZE;\ - type OPTC_DWB0_SOURCE_SELECT;\ - type OPTC_DWB1_SOURCE_SELECT;\ - -struct dcn10_dwbc_registers { - uint32_t WB_ENABLE; - uint32_t WB_EC_CONFIG; - uint32_t CNV_MODE; - uint32_t WB_SOFT_RESET; - uint32_t MCIF_WB_BUFMGR_SW_CONTROL; - uint32_t MCIF_WB_BUF_PITCH; - uint32_t MCIF_WB_ARBITRATION_CONTROL; - uint32_t MCIF_WB_SCLK_CHANGE; - uint32_t MCIF_WB_BUF_1_ADDR_Y; - uint32_t MCIF_WB_BUF_1_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_1_ADDR_C; - uint32_t MCIF_WB_BUF_1_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_2_ADDR_Y; - uint32_t MCIF_WB_BUF_2_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_2_ADDR_C; - uint32_t MCIF_WB_BUF_2_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_3_ADDR_Y; - uint32_t MCIF_WB_BUF_3_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_3_ADDR_C; - uint32_t MCIF_WB_BUF_3_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUF_4_ADDR_Y; - uint32_t MCIF_WB_BUF_4_ADDR_Y_OFFSET; - uint32_t MCIF_WB_BUF_4_ADDR_C; - uint32_t MCIF_WB_BUF_4_ADDR_C_OFFSET; - uint32_t MCIF_WB_BUFMGR_VCE_CONTROL; - uint32_t MCIF_WB_NB_PSTATE_LATENCY_WATERMARK; - uint32_t MCIF_WB_NB_PSTATE_CONTROL; - uint32_t MCIF_WB_WATERMARK; - uint32_t MCIF_WB_WARM_UP_CNTL; - uint32_t MCIF_WB_BUF_LUMA_SIZE; - uint32_t MCIF_WB_BUF_CHROMA_SIZE; - uint32_t DWB_SOURCE_SELECT; -}; -struct dcn10_dwbc_mask { - DWBC_REG_FIELD_LIST(uint32_t) -}; -struct dcn10_dwbc_shift { - DWBC_REG_FIELD_LIST(uint8_t) -}; -struct dcn10_dwbc { - struct dwbc base; - const struct dcn10_dwbc_registers *dwbc_regs; - const struct dcn10_dwbc_shift *dwbc_shift; - const struct dcn10_dwbc_mask *dwbc_mask; -}; - -void dcn10_dwbc_construct(struct dcn10_dwbc *dwbc10, - struct dc_context *ctx, - const struct dcn10_dwbc_registers *dwbc_regs, - const struct dcn10_dwbc_shift *dwbc_shift, - const struct dcn10_dwbc_mask *dwbc_mask, - int inst); - -#endif - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 71adda0e5b59..e21ba8c2f8d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -32,7 +32,6 @@ #include "dcn10/dcn10_ipp.h" #include "dcn10/dcn10_mpc.h" -#include "dcn10/dcn10_dwb.h" #include "irq/dcn10/irq_service_dcn10.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_timing_generator.h" @@ -326,24 +325,6 @@ static const struct dcn_dpp_mask tf_mask = { TF_REG_LIST_SH_MASK_DCN10(_MASK), }; -#define dwbc_regs(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN1_0(id),\ -} - -static const struct dcn10_dwbc_registers dwbc10_regs[] = { - dwbc_regs(0), - dwbc_regs(1), -}; - -static const struct dcn10_dwbc_shift dwbc10_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) -}; - -static const struct dcn10_dwbc_mask dwbc10_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN1_0(_MASK) -}; - static const struct dcn_mpc_registers mpc_regs = { MPC_COMMON_REG_LIST_DCN1_0(0), MPC_COMMON_REG_LIST_DCN1_0(1), @@ -430,7 +411,6 @@ static const struct resource_caps res_cap = { .num_audio = 4, .num_stream_encoder = 4, .num_pll = 4, - .num_dwb = 2, }; static const struct dc_debug debug_defaults_drv = { @@ -767,11 +747,6 @@ static void destruct(struct dcn10_resource_pool *pool) dce_aud_destroy(&pool->base.audios[i]); } - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - kfree(pool->base.dwbc[i]); - pool->base.dwbc[i] = NULL; - } - for (i = 0; i < pool->base.clk_src_count; i++) { if (pool->base.clock_sources[i] != NULL) { dcn10_clock_source_destroy(&pool->base.clock_sources[i]); @@ -1234,31 +1209,6 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) return value; } -static bool dcn10_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t dwb_count = pool->res_cap->num_dwb; - - for (i = 0; i < dwb_count; i++) { - struct dcn10_dwbc *dwbc10 = kzalloc(sizeof(struct dcn10_dwbc), - GFP_KERNEL); - - if (!dwbc10) { - dm_error("DC: failed to create dwbc10!\n"); - return false; - } - - dcn10_dwbc_construct(dwbc10, ctx, - &dwbc10_regs[i], - &dwbc10_shift, - &dwbc10_mask, - i); - - pool->dwbc[i] = &dwbc10->base; - } - return true; -} - static bool construct( uint8_t num_virtual_links, struct dc *dc, @@ -1479,12 +1429,6 @@ static bool construct( goto mpc_create_fail; } -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (!dcn10_dwbc_create(ctx, &pool->base)) { - goto dwbc_create_fail; - } -#endif - if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) @@ -1507,7 +1451,6 @@ static bool construct( irqs_create_fail: res_create_fail: clock_source_create_fail: -dwbc_create_fail: destruct(pool); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 915d5c10361b..1a1d322da8cc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -35,7 +35,6 @@ #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" #endif -#include "dwb.h" #define MAX_CLOCK_SOURCES 7 @@ -136,8 +135,6 @@ struct resource_pool { struct pp_smu_funcs_rv *pp_smu; struct pp_smu_display_requirement_rv pp_smu_req; - struct dwbc *dwbc[MAX_DWB_PIPES]; - unsigned int pipe_count; unsigned int underlay_pipe_index; unsigned int stream_enc_count; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h deleted file mode 100644 index 82347ba480fe..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright 2012-17 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DC_DWBC_H__ -#define __DC_DWBC_H__ - -#include "dc_hw_types.h" - -#define MAX_DWB_PIPES 3 - -enum dce_version; - -enum dwb_sw_version { - dwb_ver_1_0 = 1, -}; - -enum dwb_source { - dwb_src_scl = 0, /* for DCE7x/9x, DCN won't support. */ - dwb_src_blnd, /* for DCE7x/9x */ - dwb_src_fmt, /* for DCE7x/9x */ -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - dwb_src_otg0 = 0x100, /* for DCN1.x, register: mmDWB_SOURCE_SELECT */ - dwb_src_otg1, /* for DCN1.x */ - dwb_src_otg2, /* for DCN1.x */ - dwb_src_otg3, /* for DCN1.x */ -#endif -}; - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -/* DCN1.x supports 2 pipes */ -#endif -enum dwb_pipe { - dwb_pipe0 = 0, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - dwb_pipe1, -#endif - dwb_pipe_max_num, -}; - -enum setting_flags { - sf_pipe = 0x00000001, - sf_output_format = 0x00000002, - sf_capture_rate = 0x00000004, - sf_all = 0xffffffff, -}; - -enum dwb_capture_rate { - - dwb_capture_rate_0 = 0, /* Every frame is captured. */ - dwb_capture_rate_1 = 1, /* Every other frame is captured. */ - dwb_capture_rate_2 = 2, /* Every 3rd frame is captured. */ - dwb_capture_rate_3 = 3, /* Every 4th frame is captured. */ -}; - -enum dwb_scaler_mode { - dwb_scaler_mode_bypass444 = 0, - dwb_scaler_mode_rgb444 = 1, - dwb_scaler_mode_yuv444 = 2, - dwb_scaler_mode_yuv420 = 3 -}; - -struct dwb_caps { - enum dce_version hw_version; /* DCN engine version. */ - enum dwb_sw_version sw_version; /* DWB sw implementation version. */ - unsigned int reserved[6]; /* Reserved for future use, MUST BE 0. */ - unsigned int adapter_id; - unsigned int num_pipes; /* number of DWB pipes */ - struct { - unsigned int support_dwb :1; - unsigned int support_ogam :1; - unsigned int support_wbscl :1; - unsigned int support_ocsc :1; - } caps; - unsigned int reserved2[10]; /* Reserved for future use, MUST BE 0. */ -}; - -struct dwb_status { - bool enabled; - /* Reserved ========================================================================= */ - unsigned int reserved[8]; /* Reserved fields */ -}; - -struct dwb_basic_settings { - /* General DWB related input parameters ============================================= */ - enum dwb_source input_src_select; /* Select input source: (DCE) 0: SCL; 1: BLND; 2: FMT; (DCN) OTG* or MPC* */ - enum dwb_pipe input_pipe_select; /* Select input pipe: 0: PIPE0; 1: PIPE1; 2: PIPE2 */ - - /* CNV: WND Related parameters ====================================================== */ - unsigned int capture_rate; /* Captures once every (capture_rate+1) frames */ - - /* CNV: CSC Related parameters ====================================================== */ - unsigned int start_x; /* Horizontal window start position */ - unsigned int start_y; /* Vertical window start position */ - unsigned int src_width; /* Width of window captured within source window */ - unsigned int src_height; /* Height of window captured within source window */ - - /* SISCL Related parameters ========================================================= */ - unsigned int dest_width; /* Destination width */ - unsigned int dest_height; /* Destination height */ - - /* MCIF bufer parameters ========================================================= */ - unsigned long long luma_address[4]; - unsigned long long chroma_address[4]; - unsigned int luma_pitch; - unsigned int chroma_pitch; - unsigned int slice_lines; - - /* Reserved ========================================================================= */ - unsigned int reserved[8]; /* Reserved fields */ - -}; - -struct dwb_advanced_settings { - enum setting_flags uFlag; - enum dwb_pipe pipe; /* default = DWB_PIPE_ALL */ - enum dwb_scaler_mode out_format; /* default = DWBScalerMode_YUV420 */ - enum dwb_capture_rate capture_rate; /* default = Every frame is captured */ - unsigned int reserved[64]; /* reserved for future use, must be 0 */ -}; - -/* / - dwb_frame_info is the info of the dumping data */ -struct dwb_frame_info { - unsigned int size; - unsigned int width; - unsigned int height; - unsigned int luma_pitch; - unsigned int chroma_pitch; - enum dwb_scaler_mode format; -}; - -struct dwbc_cfg { - struct dwb_basic_settings basic_settings; - struct dwb_advanced_settings advanced_settings; -}; - -struct dwbc { - const struct dwbc_funcs *funcs; - struct dc_context *ctx; - struct dwbc_cfg config; - struct dwb_status status; - int inst; -}; - -struct dwbc_funcs { - bool (*get_caps)(struct dwbc *dwbc, struct dwb_caps *caps); - - bool (*enable)(struct dwbc *dwbc); - - bool (*disable)(struct dwbc *dwbc); - - bool (*get_status)(struct dwbc *dwbc, struct dwb_status *status); - - bool (*dump_frame)(struct dwbc *dwbc, struct dwb_frame_info *frame_info, - unsigned char *luma_buffer, unsigned char *chroma_buffer, - unsigned char *dest_luma_buffer, unsigned char *dest_chroma_buffer); - - bool (*set_basic_settings)(struct dwbc *dwbc, - const struct dwb_basic_settings *basic_settings); - - bool (*get_basic_settings)(struct dwbc *dwbc, - struct dwb_basic_settings *basic_settings); - - bool (*set_advanced_settings)(struct dwbc *dwbc, - const struct dwb_advanced_settings *advanced_settings); - - bool (*get_advanced_settings)(struct dwbc *dwbc, - struct dwb_advanced_settings *advanced_settings); - - bool (*reset_advanced_settings)(struct dwbc *dwbc); -}; - -#endif -- GitLab From c07c1a0f68d0f2f7ca9aff924e2772526027b019 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Fri, 29 Sep 2017 09:32:53 +0200 Subject: [PATCH 0932/2898] clk: samsung: Fix m2m scaler clock on Exynos542x The TOP "aclk400_mscl" clock should be kept enabled all the time to allow proper access to power management control for MSC power domain and devices that are a part of it. This change is required for the scaler to work properly after domain power on/off sequence. Fixes: 318fa46cc60d ("clk/samsung: exynos542x: mark some clocks as critical") Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 25601967d1cd..038701a2af4c 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -998,7 +998,7 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { GATE(0, "aclk400_isp", "mout_user_aclk400_isp", GATE_BUS_TOP, 16, 0, 0), GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl", - GATE_BUS_TOP, 17, 0, 0), + GATE_BUS_TOP, 17, CLK_IS_CRITICAL, 0), GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1", GATE_BUS_TOP, 18, CLK_IS_CRITICAL, 0), GATE(CLK_SCLK_MPHY_IXTAL24, "sclk_mphy_ixtal24", "mphy_refclk_ixtal24", -- GitLab From 80815004a45fc68b6e34653af4fca47be7fb96ed Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 29 Sep 2017 16:22:53 +0800 Subject: [PATCH 0933/2898] clk: sunxi-ng: sun6i: Export video PLLs The 2x outputs of the 2 video PLL clocks are directly used by the HDMI controller block. Export them so they can be referenced in the device tree. Fixes: c6e6c96d8fa6 ("clk: sunxi-ng: Add A31/A31s clocks") Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun6i-a31.h | 8 ++++++-- include/dt-bindings/clock/sun6i-a31-ccu.h | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.h b/drivers/clk/sunxi-ng/ccu-sun6i-a31.h index 4e434011e9e7..27e6ad4133ab 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.h +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.h @@ -27,7 +27,9 @@ #define CLK_PLL_AUDIO_4X 4 #define CLK_PLL_AUDIO_8X 5 #define CLK_PLL_VIDEO0 6 -#define CLK_PLL_VIDEO0_2X 7 + +/* The PLL_VIDEO0_2X clock is exported */ + #define CLK_PLL_VE 8 #define CLK_PLL_DDR 9 @@ -35,7 +37,9 @@ #define CLK_PLL_PERIPH_2X 11 #define CLK_PLL_VIDEO1 12 -#define CLK_PLL_VIDEO1_2X 13 + +/* The PLL_VIDEO1_2X clock is exported */ + #define CLK_PLL_GPU 14 #define CLK_PLL_MIPI 15 #define CLK_PLL9 16 diff --git a/include/dt-bindings/clock/sun6i-a31-ccu.h b/include/dt-bindings/clock/sun6i-a31-ccu.h index 4482530fb6f5..c5d13340184a 100644 --- a/include/dt-bindings/clock/sun6i-a31-ccu.h +++ b/include/dt-bindings/clock/sun6i-a31-ccu.h @@ -43,8 +43,12 @@ #ifndef _DT_BINDINGS_CLK_SUN6I_A31_H_ #define _DT_BINDINGS_CLK_SUN6I_A31_H_ +#define CLK_PLL_VIDEO0_2X 7 + #define CLK_PLL_PERIPH 10 +#define CLK_PLL_VIDEO1_2X 13 + #define CLK_CPU 18 #define CLK_AHB1_MIPIDSI 23 -- GitLab From 7f3ed79188f2f094d0ee366fa858857fb7f511ba Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 29 Sep 2017 16:22:54 +0800 Subject: [PATCH 0934/2898] clk: sunxi-ng: sun6i: Rename HDMI DDC clock to avoid name collision The HDMI DDC clock found in the CCU is the parent of the actual DDC clock within the HDMI controller. That clock is also named "hdmi-ddc". Rename the one in the CCU to "ddc". This makes more sense than renaming the one in the HDMI controller to something else. Fixes: c6e6c96d8fa6 ("clk: sunxi-ng: Add A31/A31s clocks") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 8af434815fba..241fb13f1c06 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -608,7 +608,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", lcd_ch1_parents, 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT); -static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", 0x150, BIT(30), 0); +static SUNXI_CCU_GATE(hdmi_ddc_clk, "ddc", "osc24M", 0x150, BIT(30), 0); static SUNXI_CCU_GATE(ps_clk, "ps", "lcd1-ch1", 0x140, BIT(31), 0); -- GitLab From 1b3bce4d6bf839304a90951b4b25a5863533bf2a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 29 Sep 2017 12:34:13 -0400 Subject: [PATCH 0935/2898] VT_RESIZEX: get rid of field-by-field copyin Signed-off-by: Al Viro --- drivers/tty/vt/vt_ioctl.c | 68 ++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 96d389cb506c..89afc960851e 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -842,58 +842,44 @@ int vt_ioctl(struct tty_struct *tty, case VT_RESIZEX: { - struct vt_consize __user *vtconsize = up; - ushort ll,cc,vlin,clin,vcol,ccol; + struct vt_consize v; if (!perm) return -EPERM; - if (!access_ok(VERIFY_READ, vtconsize, - sizeof(struct vt_consize))) { - ret = -EFAULT; - break; - } + if (copy_from_user(&v, up, sizeof(struct vt_consize))) + return -EFAULT; /* FIXME: Should check the copies properly */ - __get_user(ll, &vtconsize->v_rows); - __get_user(cc, &vtconsize->v_cols); - __get_user(vlin, &vtconsize->v_vlin); - __get_user(clin, &vtconsize->v_clin); - __get_user(vcol, &vtconsize->v_vcol); - __get_user(ccol, &vtconsize->v_ccol); - vlin = vlin ? vlin : vc->vc_scan_lines; - if (clin) { - if (ll) { - if (ll != vlin/clin) { - /* Parameters don't add up */ - ret = -EINVAL; - break; - } - } else - ll = vlin/clin; + if (!v.v_vlin) + v.v_vlin = vc->vc_scan_lines; + if (v.v_clin) { + int rows = v.v_vlin/v.v_clin; + if (v.v_rows != rows) { + if (v.v_rows) /* Parameters don't add up */ + return -EINVAL; + v.v_rows = rows; + } } - if (vcol && ccol) { - if (cc) { - if (cc != vcol/ccol) { - ret = -EINVAL; - break; - } - } else - cc = vcol/ccol; + if (v.v_vcol && v.v_ccol) { + int cols = v.v_vcol/v.v_ccol; + if (v.v_cols != cols) { + if (v.v_cols) + return -EINVAL; + v.v_cols = cols; + } } - if (clin > 32) { - ret = -EINVAL; - break; - } - + if (v.v_clin > 32) + return -EINVAL; + for (i = 0; i < MAX_NR_CONSOLES; i++) { if (!vc_cons[i].d) continue; console_lock(); - if (vlin) - vc_cons[i].d->vc_scan_lines = vlin; - if (clin) - vc_cons[i].d->vc_font.height = clin; + if (v.v_vlin) + vc_cons[i].d->vc_scan_lines = v.v_vlin; + if (v.v_clin) + vc_cons[i].d->vc_font.height = v.v_clin; vc_cons[i].d->vc_resize_user = 1; - vc_resize(vc_cons[i].d, cc, ll); + vc_resize(vc_cons[i].d, v.v_cols, v.v_rows); console_unlock(); } break; -- GitLab From 2a479aa83bd6d55bfc20b07d85e5d19a84f292f7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 29 Sep 2017 12:40:54 -0400 Subject: [PATCH 0936/2898] selection: get rid of field-by-field copyin Signed-off-by: Al Viro --- drivers/tty/vt/selection.c | 50 ++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index accbd1257bc4..5cace702bd9c 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -155,42 +155,34 @@ static int store_utf8(u16 c, char *p) int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) { struct vc_data *vc = vc_cons[fg_console].d; - int sel_mode, new_sel_start, new_sel_end, spc; + int new_sel_start, new_sel_end, spc; + struct tiocl_selection v; char *bp, *obp; int i, ps, pe, multiplier; u16 c; int mode; poke_blanked_console(); + if (copy_from_user(&v, sel, sizeof(*sel))) + return -EFAULT; - { unsigned short xs, ys, xe, ye; + v.xs = limit(v.xs - 1, vc->vc_cols - 1); + v.ys = limit(v.ys - 1, vc->vc_rows - 1); + v.xe = limit(v.xe - 1, vc->vc_cols - 1); + v.ye = limit(v.ye - 1, vc->vc_rows - 1); + ps = v.ys * vc->vc_size_row + (v.xs << 1); + pe = v.ye * vc->vc_size_row + (v.xe << 1); - if (!access_ok(VERIFY_READ, sel, sizeof(*sel))) - return -EFAULT; - __get_user(xs, &sel->xs); - __get_user(ys, &sel->ys); - __get_user(xe, &sel->xe); - __get_user(ye, &sel->ye); - __get_user(sel_mode, &sel->sel_mode); - xs--; ys--; xe--; ye--; - xs = limit(xs, vc->vc_cols - 1); - ys = limit(ys, vc->vc_rows - 1); - xe = limit(xe, vc->vc_cols - 1); - ye = limit(ye, vc->vc_rows - 1); - ps = ys * vc->vc_size_row + (xs << 1); - pe = ye * vc->vc_size_row + (xe << 1); - - if (sel_mode == TIOCL_SELCLEAR) { - /* useful for screendump without selection highlights */ - clear_selection(); - return 0; - } - - if (mouse_reporting() && (sel_mode & TIOCL_SELMOUSEREPORT)) { - mouse_report(tty, sel_mode & TIOCL_SELBUTTONMASK, xs, ys); - return 0; - } - } + if (v.sel_mode == TIOCL_SELCLEAR) { + /* useful for screendump without selection highlights */ + clear_selection(); + return 0; + } + + if (mouse_reporting() && (v.sel_mode & TIOCL_SELMOUSEREPORT)) { + mouse_report(tty, v.sel_mode & TIOCL_SELBUTTONMASK, v.xs, v.ys); + return 0; + } if (ps > pe) /* make sel_start <= sel_end */ { @@ -209,7 +201,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t else use_unicode = 0; - switch (sel_mode) + switch (v.sel_mode) { case TIOCL_SELCHAR: /* character-by-character selection */ new_sel_start = ps; -- GitLab From 2dc3e4a86c8cce49bc73f41d8e0134557c506488 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:20:39 +1000 Subject: [PATCH 0937/2898] amdgpu/dc: drop dc_ver char This isn't referenced anywhere, and if it was it should be const. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7fd42fc8bdfa..008f137dff80 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -49,8 +49,6 @@ #include "mem_input.h" -char dc_ver[] = DC_VER; - /******************************************************************************* * Private functions ******************************************************************************/ -- GitLab From b8a1d69ccb5e0ffc2771b3a7a6ec9d948d10ee9d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:23:15 +1000 Subject: [PATCH 0938/2898] amdgpu/dc: static constify update_surface_trace_level Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 008f137dff80..c8235b041b5b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1172,7 +1172,7 @@ static struct dc_stream_status *stream_get_status( return NULL; } -enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; +static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; void dc_update_planes_and_stream(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, -- GitLab From 99d1abf8f41ed2c256e8cca7e9da71d751894c7f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:27:41 +1000 Subject: [PATCH 0939/2898] amdgpu/dm: constify yuv_formats. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index dba54c0a7b5f..89442cce7373 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3073,7 +3073,7 @@ static uint32_t rgb_formats[] = { DRM_FORMAT_ABGR2101010, }; -static uint32_t yuv_formats[] = { +static const uint32_t yuv_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21, }; -- GitLab From e04a6123a45abf6836f547e679a8f9aca37ceeb6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:32:23 +1000 Subject: [PATCH 0940/2898] amdgpu/dm: constify plane type. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index b541ade8a03f..59e2e5d59562 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -361,7 +361,7 @@ struct amdgpu_mode_info { int num_dig; /* number of dig blocks */ int disp_priority; const struct amdgpu_display_funcs *funcs; - enum drm_plane_type *plane_type; + const enum drm_plane_type *plane_type; }; #define AMDGPU_MAX_BL_LEVEL 0xFF diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 89442cce7373..ef938521fec8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -71,7 +71,7 @@ #include "i2caux_interface.h" -static enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { +static const enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, @@ -80,14 +80,14 @@ static enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, }; -static enum drm_plane_type dm_plane_type_carizzo[AMDGPU_MAX_PLANES] = { +static const enum drm_plane_type dm_plane_type_carizzo[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_OVERLAY,/* YUV Capable Underlay */ }; -static enum drm_plane_type dm_plane_type_stoney[AMDGPU_MAX_PLANES] = { +static const enum drm_plane_type dm_plane_type_stoney[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_OVERLAY, /* YUV Capable Underlay */ -- GitLab From d90371b0f5f3258a808d12a17a942e4d16f8252c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:32:24 +1000 Subject: [PATCH 0941/2898] amdgpu/dm: constify rgb formats. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ef938521fec8..61ccddd19718 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3062,7 +3062,7 @@ static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { * plane capabilities, or initialize this array to all formats, so internal drm * check will succeed, and let DC to implement proper check */ -static uint32_t rgb_formats[] = { +static const uint32_t rgb_formats[] = { DRM_FORMAT_RGB888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, -- GitLab From 395f669eb69b8b37ed2ffe0c5f67e942e9d00dc8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 10:39:29 +1000 Subject: [PATCH 0942/2898] amdgpu/dc: constify a bunch of dc structs. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 2 +- .../drm/amd/display/dc/dce120/dce120_timing_generator.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c index 3e9ff2f5472d..9031d22285ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c @@ -51,7 +51,7 @@ clk_dce->base.ctx /* Max clock values for each state indexed by "enum clocks_state": */ -static struct state_dependent_clocks dce80_max_clks_by_state[] = { +static const struct state_dependent_clocks dce80_max_clks_by_state[] = { /* ClocksStateInvalid - should not be used */ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, /* ClocksStateUltraLow - not expected to be used for DCE 8.0 */ @@ -63,7 +63,7 @@ static struct state_dependent_clocks dce80_max_clks_by_state[] = { /* ClocksStatePerformance */ { .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; -static struct state_dependent_clocks dce110_max_clks_by_state[] = { +static const struct state_dependent_clocks dce110_max_clks_by_state[] = { /*ClocksStateInvalid - should not be used*/ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ @@ -75,7 +75,7 @@ static struct state_dependent_clocks dce110_max_clks_by_state[] = { /*ClocksStatePerformance*/ { .display_clk_khz = 643000, .pixel_clk_khz = 400000 } }; -static struct state_dependent_clocks dce112_max_clks_by_state[] = { +static const struct state_dependent_clocks dce112_max_clks_by_state[] = { /*ClocksStateInvalid - should not be used*/ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ @@ -87,7 +87,7 @@ static struct state_dependent_clocks dce112_max_clks_by_state[] = { /*ClocksStatePerformance*/ { .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } }; -static struct state_dependent_clocks dce120_max_clks_by_state[] = { +static const struct state_dependent_clocks dce120_max_clks_by_state[] = { /*ClocksStateInvalid - should not be used*/ { .display_clk_khz = 0, .pixel_clk_khz = 0 }, /*ClocksStateUltraLow - currently by HW design team not supposed to be used*/ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 6b5d5948ddb7..a6f93a42c2ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -302,7 +302,7 @@ static const struct dce_opp_mask opp_mask = { AUD_COMMON_REG_LIST(id)\ } -static struct dce_audio_registers audio_regs[] = { +static const struct dce_audio_registers audio_regs[] = { audio_regs(0), audio_regs(1), audio_regs(2), diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 58a070debd58..791c9b084941 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -1109,7 +1109,7 @@ static bool dce120_arm_vert_intr( return true; } -static struct timing_generator_funcs dce120_tg_funcs = { +static const struct timing_generator_funcs dce120_tg_funcs = { .validate_timing = dce120_tg_validate_timing, .program_timing = dce120_tg_program_timing, .enable_crtc = dce120_timing_generator_enable_crtc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 487694125ea4..ac03b04f1ea5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -373,7 +373,7 @@ void ippn10_cnv_setup ( } } -static struct transform_funcs dcn10_dpp_funcs = { +static const struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 2d3dd9a3a196..7cd10cbc5497 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -1146,7 +1146,7 @@ void tgn10_read_otg_state(struct dcn10_timing_generator *tgn10, } -static struct timing_generator_funcs dcn10_tg_funcs = { +static const struct timing_generator_funcs dcn10_tg_funcs = { .validate_timing = tgn10_validate_timing, .program_timing = tgn10_program_timing, .program_global_sync = tgn10_program_global_sync, -- GitLab From ca19d1a68b7e0f1d0717bd3f2d9d75cb3c568ddb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:55 +1000 Subject: [PATCH 0943/2898] amdgpu/dc: make timing generator constructor return void. This can't fail as is. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 9 ++------- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 8 ++------ .../drm/amd/display/dc/dce110/dce110_timing_generator.c | 7 +------ .../drm/amd/display/dc/dce110/dce110_timing_generator.h | 2 +- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 8 ++------ 5 files changed, 8 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 9a75bde32611..6765162a0d78 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -375,13 +375,8 @@ static struct timing_generator *dce100_timing_generator_create( if (!tg110) return NULL; - if (dce110_timing_generator_construct(tg110, ctx, instance, - offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static struct stream_encoder *dce100_stream_encoder_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 787e20e15221..3d91f2a49d1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -410,12 +410,8 @@ static struct timing_generator *dce110_timing_generator_create( if (!tg110) return NULL; - if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static struct stream_encoder *dce110_stream_encoder_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index 7f93d6d83cfd..bcd544d85621 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1941,15 +1941,12 @@ static const struct timing_generator_funcs dce110_tg_funcs = { .arm_vert_intr = dce110_arm_vert_intr, }; -bool dce110_timing_generator_construct( +void dce110_timing_generator_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx, uint32_t instance, const struct dce110_timing_generator_offsets *offsets) { - if (!tg110) - return false; - tg110->controller_id = CONTROLLER_ID_D0 + instance; tg110->base.inst = instance; @@ -1966,6 +1963,4 @@ bool dce110_timing_generator_construct( tg110->min_h_blank = 56; tg110->min_h_front_porch = 4; tg110->min_h_back_porch = 4; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index a5d63c626ada..bd8d0ab668b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -118,7 +118,7 @@ struct dce110_timing_generator { #define DCE110TG_FROM_TG(tg)\ container_of(tg, struct dce110_timing_generator, base) -bool dce110_timing_generator_construct( +void dce110_timing_generator_construct( struct dce110_timing_generator *tg, struct dc_context *ctx, uint32_t instance, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 4e2ed3429a90..a06a68521c59 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -415,12 +415,8 @@ static struct timing_generator *dce112_timing_generator_create( if (!tg110) return NULL; - if (dce110_timing_generator_construct(tg110, ctx, instance, offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static struct stream_encoder *dce112_stream_encoder_create( -- GitLab From f29f918f2868ece27c8aff0edc84c7d7fbdc5598 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:56 +1000 Subject: [PATCH 0944/2898] amdgpu/dc: make stream encoder constructor return void. The checks weren't useful here really. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 9 +-------- .../drm/amd/display/dc/dce/dce_stream_encoder.h | 2 +- .../drm/amd/display/dc/dce100/dce100_resource.c | 11 +++-------- .../drm/amd/display/dc/dce110/dce110_resource.c | 12 ++++-------- .../drm/amd/display/dc/dce112/dce112_resource.c | 14 +++++--------- .../drm/amd/display/dc/dce120/dce120_resource.c | 12 ++++-------- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 12 ++++-------- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 12 ++++-------- 8 files changed, 26 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 532c6e638943..b2add58ef889 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1605,7 +1605,7 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { }; -bool dce110_stream_encoder_construct( +void dce110_stream_encoder_construct( struct dce110_stream_encoder *enc110, struct dc_context *ctx, struct dc_bios *bp, @@ -1614,11 +1614,6 @@ bool dce110_stream_encoder_construct( const struct dce_stream_encoder_shift *se_shift, const struct dce_stream_encoder_mask *se_mask) { - if (!enc110) - return false; - if (!bp) - return false; - enc110->base.funcs = &dce110_str_enc_funcs; enc110->base.ctx = ctx; enc110->base.id = eng_id; @@ -1626,6 +1621,4 @@ bool dce110_stream_encoder_construct( enc110->regs = regs; enc110->se_shift = se_shift; enc110->se_mask = se_mask; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h index ff8ca1246650..6c28229c76eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h @@ -697,7 +697,7 @@ struct dce110_stream_encoder { const struct dce_stream_encoder_mask *se_mask; }; -bool dce110_stream_encoder_construct( +void dce110_stream_encoder_construct( struct dce110_stream_encoder *enc110, struct dc_context *ctx, struct dc_bios *bp, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 6765162a0d78..75961338a8e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -389,14 +389,9 @@ static struct stream_encoder *dce100_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 3d91f2a49d1d..9faf2feabdf1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -424,14 +424,10 @@ static struct stream_encoder *dce110_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index a06a68521c59..0011dd704af0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -428,15 +428,11 @@ static struct stream_encoder *dce112_stream_encoder_create( if (!enc110) return NULL; - - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index a6f93a42c2ec..a63193913496 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -585,14 +585,10 @@ static struct stream_encoder *dce120_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 170509a4a221..0b309acab6b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -441,14 +441,10 @@ static struct stream_encoder *dce80_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } #define SRII(reg_name, block, id)\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index e21ba8c2f8d4..5d6dd7f30253 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -627,14 +627,10 @@ static struct stream_encoder *dcn10_stream_encoder_create( if (!enc110) return NULL; - if (dce110_stream_encoder_construct( - enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask)) - return &enc110->base; - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; } static const struct dce_hwseq_registers hwseq_reg = { -- GitLab From c60ae11201caff8b0c5c23e4349bf42388e3828b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:57 +1000 Subject: [PATCH 0945/2898] amdgpu/dc: make link encoder construct void. This only ever returned true. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce/dce_link_encoder.c | 4 +--- .../drm/amd/display/dc/dce/dce_link_encoder.h | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 21 +++++++------------ .../amd/display/dc/dce110/dce110_resource.c | 21 +++++++------------ .../amd/display/dc/dce112/dce112_resource.c | 21 +++++++------------ .../amd/display/dc/dce120/dce120_resource.c | 20 +++++++----------- .../drm/amd/display/dc/dce80/dce80_resource.c | 21 +++++++------------ .../drm/amd/display/dc/dcn10/dcn10_resource.c | 20 +++++++----------- 8 files changed, 44 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 2ce730de0dc3..37aeddfb7431 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -914,7 +914,7 @@ bool dce110_link_encoder_validate_dp_output( return false; } -bool dce110_link_encoder_construct( +void dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, const struct encoder_feature_support *enc_features, @@ -1013,8 +1013,6 @@ bool dce110_link_encoder_construct( bp_cap_info.DP_HBR3_EN; enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; } - - return true; } bool dce110_link_encoder_validate_output_with_stream( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 5960fb933f1f..be0a45bdc5e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -168,7 +168,7 @@ struct dce110_link_encoder { }; -bool dce110_link_encoder_construct( +void dce110_link_encoder_construct( struct dce110_link_encoder *enc110, const struct encoder_init_data *init_data, const struct encoder_feature_support *enc_features, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 75961338a8e4..0084645837ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -528,20 +528,13 @@ struct link_encoder *dce100_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; } struct output_pixel_processor *dce100_opp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 9faf2feabdf1..2c24f2b882fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -567,20 +567,13 @@ static struct link_encoder *dce110_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; } static struct output_pixel_processor *dce110_opp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 0011dd704af0..7aac8fdb3030 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -552,20 +552,13 @@ struct link_encoder *dce112_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; } static struct input_pixel_processor *dce112_ipp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index a63193913496..7de99c454f4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -544,20 +544,14 @@ static struct link_encoder *dce120_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + return &enc110->base; } static struct input_pixel_processor *dce120_ipp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 0b309acab6b1..3603ae93cd72 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -567,20 +567,13 @@ struct link_encoder *dce80_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } - - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; } struct clock_source *dce80_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 5d6dd7f30253..c2df57b5e921 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -563,20 +563,14 @@ struct link_encoder *dcn10_link_encoder_create( if (!enc110) return NULL; - if (dce110_link_encoder_construct( - enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source])) { - - return &enc110->base; - } + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); - BREAK_TO_DEBUGGER(); - kfree(enc110); - return NULL; + return &enc110->base; } struct clock_source *dcn10_clock_source_create( -- GitLab From 9cf29399f615fc13732f3c8ba3f5ff47e2ca256d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:58 +1000 Subject: [PATCH 0946/2898] amdgpu/dc: make opp construct void. This doesn't return anything except true. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 2 +- .../gpu/drm/amd/display/dc/dce100/dce100_resource.c | 10 +++------- .../gpu/drm/amd/display/dc/dce110/dce110_resource.c | 10 +++------- .../gpu/drm/amd/display/dc/dce112/dce112_resource.c | 10 +++------- .../gpu/drm/amd/display/dc/dce120/dce120_resource.c | 10 +++------- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 10 +++------- 7 files changed, 17 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index c0736aeabd85..3931412ab6d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -540,7 +540,7 @@ static const struct opp_funcs funcs = { .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction }; -bool dce110_opp_construct(struct dce110_opp *opp110, +void dce110_opp_construct(struct dce110_opp *opp110, struct dc_context *ctx, uint32_t inst, const struct dce_opp_registers *regs, @@ -556,8 +556,6 @@ bool dce110_opp_construct(struct dce110_opp *opp110, opp110->regs = regs; opp110->opp_shift = opp_shift; opp110->opp_mask = opp_mask; - - return true; } void dce110_opp_destroy(struct output_pixel_processor **opp) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 0874c22b8b02..2ab0147cbd9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -272,7 +272,7 @@ struct dce110_opp { const struct dce_opp_mask *opp_mask; }; -bool dce110_opp_construct(struct dce110_opp *opp110, +void dce110_opp_construct(struct dce110_opp *opp110, struct dc_context *ctx, uint32_t inst, const struct dce_opp_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 0084645837ec..729d82eb6500 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -547,13 +547,9 @@ struct output_pixel_processor *dce100_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } struct clock_source *dce100_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 2c24f2b882fe..8e3f365177b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -586,13 +586,9 @@ static struct output_pixel_processor *dce110_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } struct clock_source *dce110_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 7aac8fdb3030..3cb18cecb800 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -586,13 +586,9 @@ struct output_pixel_processor *dce112_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } struct clock_source *dce112_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 7de99c454f4b..ea234376c0e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -356,13 +356,9 @@ struct output_pixel_processor *dce120_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } static const struct bios_registers bios_regs = { diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 3603ae93cd72..71f265b6b670 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -422,13 +422,9 @@ static struct output_pixel_processor *dce80_opp_create( if (!opp) return NULL; - if (dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask)) - return &opp->base; - - BREAK_TO_DEBUGGER(); - kfree(opp); - return NULL; + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; } static struct stream_encoder *dce80_stream_encoder_create( -- GitLab From 5fb005c4583749f54d5bab6622dbed1d2d56c268 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:15:59 +1000 Subject: [PATCH 0947/2898] amdgpu/dc: make dce transform constructor void This never returns anything but true. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 2 +- .../gpu/drm/amd/display/dc/dce100/dce100_resource.c | 11 +++-------- .../gpu/drm/amd/display/dc/dce110/dce110_resource.c | 10 +++------- .../gpu/drm/amd/display/dc/dce112/dce112_resource.c | 13 ++++--------- .../gpu/drm/amd/display/dc/dce120/dce120_resource.c | 13 ++++--------- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 13 ++++--------- 7 files changed, 20 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index a8f60d7531be..c40d2e9e5f7c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -1437,7 +1437,7 @@ static const struct transform_funcs dce_transform_funcs = { /* Constructor, Destructor */ /*****************************************/ -bool dce_transform_construct( +void dce_transform_construct( struct dce_transform *xfm_dce, struct dc_context *ctx, uint32_t inst, @@ -1462,6 +1462,4 @@ bool dce_transform_construct( xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index 805bb9c4e188..e1f1e5129f86 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -481,7 +481,7 @@ struct dce_transform { bool prescaler_on; }; -bool dce_transform_construct(struct dce_transform *xfm_dce, +void dce_transform_construct(struct dce_transform *xfm_dce, struct dc_context *ctx, uint32_t inst, const struct dce_transform_registers *regs, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 729d82eb6500..1caf2983dda5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -486,14 +486,9 @@ static struct transform *dce100_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) { - return &transform->base; - } - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + return &transform->base; } static struct input_pixel_processor *dce100_ipp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8e3f365177b8..45c5facf79b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -526,13 +526,9 @@ static struct transform *dce110_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) - return &transform->base; - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + return &transform->base; } static struct input_pixel_processor *dce110_ipp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 3cb18cecb800..251e4a29d56f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -521,15 +521,10 @@ static struct transform *dce112_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) { - transform->lb_memory_size = 0x1404; /*5124*/ - return &transform->base; - } - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; } static const struct encoder_feature_support link_enc_feature = { diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index ea234376c0e2..13d75df71396 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -662,15 +662,10 @@ static struct transform *dce120_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) { - transform->lb_memory_size = 0x1404; /*5124*/ - return &transform->base; - } - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; } static void dce120_destroy_resource_pool(struct resource_pool **pool) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 71f265b6b670..db8afb6491cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -535,15 +535,10 @@ static struct transform *dce80_transform_create( if (!transform) return NULL; - if (dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask)) { - transform->prescaler_on = false; - return &transform->base; - } - - BREAK_TO_DEBUGGER(); - kfree(transform); - return NULL; + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->prescaler_on = false; + return &transform->base; } static const struct encoder_feature_support link_enc_feature = { -- GitLab From 99913a171d00b2d4c94127a9e38e5457bc45635d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 13:16:00 +1000 Subject: [PATCH 0948/2898] amdgpu/dc: make dce80 timing generator construct return void. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 8 ++------ .../gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c | 7 +------ .../gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index db8afb6491cd..5e00ca6a1292 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -404,12 +404,8 @@ static struct timing_generator *dce80_timing_generator_create( if (!tg110) return NULL; - if (dce80_timing_generator_construct(tg110, ctx, instance, offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce80_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static struct output_pixel_processor *dce80_opp_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c index 179a6d604838..265894851493 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c @@ -152,15 +152,12 @@ static const struct timing_generator_funcs dce80_tg_funcs = { dce80_timing_generator_enable_advanced_request, }; -bool dce80_timing_generator_construct( +void dce80_timing_generator_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx, uint32_t instance, const struct dce110_timing_generator_offsets *offsets) { - if (!tg110) - return false; - tg110->controller_id = CONTROLLER_ID_D0 + instance; tg110->base.inst = instance; tg110->offsets = *offsets; @@ -177,8 +174,6 @@ bool dce80_timing_generator_construct( tg110->min_h_blank = 56; tg110->min_h_front_porch = 4; tg110->min_h_back_porch = 4; - - return true; } void dce80_timing_generator_enable_advanced_request( diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h index 6e4722a970d7..9cebb24c94c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.h @@ -30,7 +30,7 @@ #include "../include/grph_object_id.h" /* DCE8.0 implementation inherits from DCE11.0 */ -bool dce80_timing_generator_construct( +void dce80_timing_generator_construct( struct dce110_timing_generator *tg, struct dc_context *ctx, uint32_t instance, -- GitLab From 2c9a7908b44eca05d1d08270a9f982b96ee30bda Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:34 +1000 Subject: [PATCH 0949/2898] amdgpu/dc: make get_audio_clock_info return void. This function never returned false under any sane circumstances. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dce/dce_stream_encoder.c | 75 +++++++++---------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index b2add58ef889..a09727fb405f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1238,7 +1238,7 @@ uint32_t calc_max_audio_packets_per_line( return max_packets_per_line; } -bool get_audio_clock_info( +void get_audio_clock_info( enum dc_color_depth color_depth, uint32_t crtc_pixel_clock_in_khz, uint32_t actual_pixel_clock_in_khz, @@ -1249,9 +1249,6 @@ bool get_audio_clock_info( uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10; uint32_t audio_array_size; - if (audio_clock_info == NULL) - return false; /* should not happen */ - switch (color_depth) { case COLOR_DEPTH_161616: clock_info = audio_clock_info_table_48bpc; @@ -1280,7 +1277,7 @@ bool get_audio_clock_info( crtc_pixel_clock_in_10khz) { /* match found */ *audio_clock_info = clock_info[index]; - return true; + return; } } } @@ -1300,8 +1297,6 @@ bool get_audio_clock_info( audio_clock_info->n_32khz = 4096; audio_clock_info->n_44khz = 6272; audio_clock_info->n_48khz = 6144; - - return true; } static void dce110_se_audio_setup( @@ -1362,40 +1357,38 @@ static void dce110_se_setup_hdmi_audio( HDMI_ACR_AUDIO_PRIORITY, 0); /* Program audio clock sample/regeneration parameters */ - if (get_audio_clock_info( - crtc_info->color_depth, - crtc_info->requested_pixel_clock, - crtc_info->calculated_pixel_clock, - &audio_clock_info)) { - dm_logger_write(enc->ctx->logger, LOG_HW_AUDIO, - "\n%s:Input::requested_pixel_clock = %d"\ - "calculated_pixel_clock = %d \n", __func__,\ - crtc_info->requested_pixel_clock,\ - crtc_info->calculated_pixel_clock); - - /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ - REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); - - /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ - REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); - - /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ - REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); - - /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ - REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); - - /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ - REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); - - /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ - REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); - - /* Video driver cannot know in advance which sample rate will - be used by HD Audio driver - HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is - programmed below in interruppt callback */ - } /* if */ + get_audio_clock_info(crtc_info->color_depth, + crtc_info->requested_pixel_clock, + crtc_info->calculated_pixel_clock, + &audio_clock_info); + dm_logger_write(enc->ctx->logger, LOG_HW_AUDIO, + "\n%s:Input::requested_pixel_clock = %d" \ + "calculated_pixel_clock = %d \n", __func__, \ + crtc_info->requested_pixel_clock, \ + crtc_info->calculated_pixel_clock); + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + be used by HD Audio driver + HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + programmed below in interruppt callback */ /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ -- GitLab From 4dec2aa9eb1386e592d76f380360360178c4af02 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:35 +1000 Subject: [PATCH 0950/2898] amdgpu/dc: make program_regamma_pwl return void The return value was unused. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c | 4 +--- drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 4 +--- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 2 +- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index c40d2e9e5f7c..ae32af31eff1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -1375,7 +1375,7 @@ static void regamma_config_regions_and_segments( -bool dce110_opp_program_regamma_pwl( +void dce110_opp_program_regamma_pwl( struct transform *xfm, const struct pwl_params *params) { @@ -1386,8 +1386,6 @@ bool dce110_opp_program_regamma_pwl( /* Program PWL */ program_pwl(xfm_dce, params); - - return true; } void dce110_opp_power_on_regamma_lut( diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index e1f1e5129f86..bfc94b4927b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -506,7 +506,7 @@ void dce110_opp_power_on_regamma_lut( struct transform *xfm, bool power_on); -bool dce110_opp_program_regamma_pwl( +void dce110_opp_program_regamma_pwl( struct transform *xfm, const struct pwl_params *params); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c index c86105b8cfaf..e98ed3058ea2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c @@ -490,7 +490,7 @@ static void program_pwl(struct dce_transform *xfm_dce, } } -bool dce110_opp_program_regamma_pwl_v( +void dce110_opp_program_regamma_pwl_v( struct transform *xfm, const struct pwl_params *params) { @@ -512,8 +512,6 @@ bool dce110_opp_program_regamma_pwl_v( /* Power return to auto back */ power_on_lut(xfm, false, false, true); - - return true; } void dce110_opp_power_on_regamma_lut_v( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h index eeed3b9f90f7..b70780210aad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.h @@ -43,7 +43,7 @@ void dce110_opp_v_set_csc_adjustment( const struct out_csc_color_matrix *tbl_entry); -bool dce110_opp_program_regamma_pwl_v( +void dce110_opp_program_regamma_pwl_v( struct transform *xfm, const struct pwl_params *params); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index ac03b04f1ea5..8607ab2da610 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -183,7 +183,7 @@ void dpp_reset(struct transform *xfm_base) -static bool dcn10_dpp_cm_set_regamma_pwl( +static void dcn10_dpp_cm_set_regamma_pwl( struct transform *xfm_base, const struct pwl_params *params) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); @@ -198,8 +198,6 @@ static bool dcn10_dpp_cm_set_regamma_pwl( dcn10_dpp_cm_program_regamma_lut( xfm_base, params->rgb_resulted, params->hw_points_num); - - return true; } static void dcn10_dpp_cm_set_regamma_mode( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 9d4a3a0098a9..785d39706832 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -213,7 +213,7 @@ struct transform_funcs { struct transform *xfm, const struct pwl_params *params); - bool (*opp_program_regamma_pwl)( + void (*opp_program_regamma_pwl)( struct transform *xfm, const struct pwl_params *params); void (*opp_set_regamma_mode)( -- GitLab From 4179cd81376112d627216580b09b803eb25e1635 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:36 +1000 Subject: [PATCH 0951/2898] amdgpu/dc: make some audio functions return void There is no need to check for these pointers being valid at this level. Check earlier if required. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 198f4532e100..6e940286c98d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -703,14 +703,11 @@ void dce_aud_az_configure( */ /* search pixel clock value for Azalia HDMI Audio */ -static bool get_azalia_clock_info_hdmi( +static void get_azalia_clock_info_hdmi( uint32_t crtc_pixel_clock_in_khz, uint32_t actual_pixel_clock_in_khz, struct azalia_clock_info *azalia_clock_info) { - if (azalia_clock_info == NULL) - return false; - /* audio_dto_phase= 24 * 10,000; * 24MHz in [100Hz] units */ azalia_clock_info->audio_dto_phase = @@ -720,18 +717,13 @@ static bool get_azalia_clock_info_hdmi( * [khz] -> [100Hz] */ azalia_clock_info->audio_dto_module = actual_pixel_clock_in_khz * 10; - - return true; } -static bool get_azalia_clock_info_dp( +static void get_azalia_clock_info_dp( uint32_t requested_pixel_clock_in_khz, const struct audio_pll_info *pll_info, struct azalia_clock_info *azalia_clock_info) { - if (pll_info == NULL || azalia_clock_info == NULL) - return false; - /* Reported dpDtoSourceClockInkhz value for * DCE8 already adjusted for SS, do not need any * adjustment here anymore @@ -745,8 +737,6 @@ static bool get_azalia_clock_info_dp( * [khz] ->[100Hz] */ azalia_clock_info->audio_dto_module = pll_info->dp_dto_source_clock_in_khz * 10; - - return true; } void dce_aud_wall_dto_setup( -- GitLab From b08c3ca4e90d03b3a120f4e60dba4b2b5e087433 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 15:44:54 +1000 Subject: [PATCH 0952/2898] amdgpu/dc: remove pointless returns in the i2caux constructor paths. (v2) There was lots of return true, and error checking that was never used in these paths. Just remove it all. v2: I missed one return true. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/i2caux/aux_engine.c | 6 ++-- .../drm/amd/display/dc/i2caux/aux_engine.h | 2 +- .../display/dc/i2caux/dce100/i2caux_dce100.c | 21 ++++-------- .../dc/i2caux/dce110/aux_engine_dce110.c | 20 +++--------- .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 24 +++++--------- .../dc/i2caux/dce110/i2c_hw_engine_dce110.h | 4 --- .../dc/i2caux/dce110/i2c_sw_engine_dce110.c | 20 +++--------- .../display/dc/i2caux/dce110/i2caux_dce110.c | 30 ++++++----------- .../display/dc/i2caux/dce110/i2caux_dce110.h | 2 +- .../display/dc/i2caux/dce112/i2caux_dce112.c | 30 ++++++----------- .../display/dc/i2caux/dce120/i2caux_dce120.c | 21 ++++-------- .../dc/i2caux/dce80/i2c_hw_engine_dce80.c | 32 +++++++------------ .../dc/i2caux/dce80/i2c_sw_engine_dce80.c | 19 +++-------- .../display/dc/i2caux/dce80/i2caux_dce80.c | 19 +++-------- .../display/dc/i2caux/dcn10/i2caux_dcn10.c | 21 ++++-------- .../dc/i2caux/diagnostics/i2caux_diag.c | 20 +++--------- .../gpu/drm/amd/display/dc/i2caux/engine.h | 2 +- .../drm/amd/display/dc/i2caux/engine_base.c | 3 +- .../drm/amd/display/dc/i2caux/i2c_engine.c | 7 ++-- .../drm/amd/display/dc/i2caux/i2c_engine.h | 2 +- .../display/dc/i2caux/i2c_generic_hw_engine.c | 6 ++-- .../display/dc/i2caux/i2c_generic_hw_engine.h | 2 +- .../drm/amd/display/dc/i2caux/i2c_hw_engine.c | 6 ++-- .../drm/amd/display/dc/i2caux/i2c_hw_engine.h | 2 +- .../drm/amd/display/dc/i2caux/i2c_sw_engine.c | 17 +++------- .../drm/amd/display/dc/i2caux/i2c_sw_engine.h | 2 +- .../gpu/drm/amd/display/dc/i2caux/i2caux.c | 4 +-- .../gpu/drm/amd/display/dc/i2caux/i2caux.h | 2 +- 28 files changed, 100 insertions(+), 246 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c index 3c9608ce94b8..fc7a7d4ebca5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.c @@ -555,15 +555,13 @@ bool dal_aux_engine_submit_request( return result; } -bool dal_aux_engine_construct( +void dal_aux_engine_construct( struct aux_engine *engine, struct dc_context *ctx) { - if (!dal_i2caux_construct_engine(&engine->base, ctx)) - return false; + dal_i2caux_construct_engine(&engine->base, ctx); engine->delay = 0; engine->max_defer_write_retry = 0; - return true; } void dal_aux_engine_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h index 40b202893772..8e71324ccb10 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/aux_engine.h @@ -100,7 +100,7 @@ struct aux_engine { bool acquire_reset; }; -bool dal_aux_engine_construct( +void dal_aux_engine_construct( struct aux_engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c index c45a2ee8c336..e8d3781deaed 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce100/i2caux_dce100.c @@ -95,18 +95,11 @@ struct i2caux *dal_i2caux_dce100_create( return NULL; } - if (dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dce100_aux_regs, - dce100_hw_engine_regs, - &i2c_shift, - &i2c_mask)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dce100_aux_regs, + dce100_hw_engine_regs, + &i2c_shift, + &i2c_mask); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index 4b673b48bf42..0c4bbc10510d 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -426,22 +426,16 @@ static const struct engine_funcs engine_funcs = { .acquire = dal_aux_engine_acquire, }; -static bool construct( +static void construct( struct aux_engine_dce110 *engine, const struct aux_engine_dce110_init_data *aux_init_data) { - if (!dal_aux_engine_construct( - &engine->base, aux_init_data->ctx)) { - ASSERT_CRITICAL(false); - return false; - } + dal_aux_engine_construct(&engine->base, aux_init_data->ctx); engine->base.base.funcs = &engine_funcs; engine->base.funcs = &aux_engine_funcs; engine->timeout_period = aux_init_data->timeout_period; engine->regs = aux_init_data->regs; - - return true; } static void destruct( @@ -471,12 +465,6 @@ struct aux_engine *dal_aux_engine_dce110_create( return NULL; } - if (construct(engine, aux_init_data)) - return &engine->base; - - ASSERT_CRITICAL(false); - - kfree(engine); - - return NULL; + construct(engine, aux_init_data); + return &engine->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c index aab77a81008a..1a5b3f70ddc9 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c @@ -498,17 +498,13 @@ static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { .wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result, }; -bool i2c_hw_engine_dce110_construct( +static void construct( struct i2c_hw_engine_dce110 *hw_engine, const struct i2c_hw_engine_dce110_create_arg *arg) { uint32_t xtal_ref_div = 0; - if (!arg->reference_frequency) - return false; - - if (!dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx)) - return false; + dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx); hw_engine->base.base.base.funcs = &engine_funcs; hw_engine->base.base.funcs = &i2c_engine_funcs; @@ -545,8 +541,6 @@ bool i2c_hw_engine_dce110_construct( */ hw_engine->reference_frequency = (arg->reference_frequency * 2) / xtal_ref_div; - - return true; } struct i2c_engine *dal_i2c_hw_engine_dce110_create( @@ -558,6 +552,10 @@ struct i2c_engine *dal_i2c_hw_engine_dce110_create( ASSERT_CRITICAL(false); return NULL; } + if (!arg->reference_frequency) { + ASSERT_CRITICAL(false); + return NULL; + } engine_dce10 = kzalloc(sizeof(struct i2c_hw_engine_dce110), GFP_KERNEL); @@ -567,12 +565,6 @@ struct i2c_engine *dal_i2c_hw_engine_dce110_create( return NULL; } - if (i2c_hw_engine_dce110_construct(engine_dce10, arg)) - return &engine_dce10->base.base; - - ASSERT_CRITICAL(false); - - kfree(engine_dce10); - - return NULL; + construct(engine_dce10, arg); + return &engine_dce10->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h index c573c6459ec6..5bb04085f670 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.h @@ -207,8 +207,4 @@ struct i2c_hw_engine_dce110_create_arg { struct i2c_engine *dal_i2c_hw_engine_dce110_create( const struct i2c_hw_engine_dce110_create_arg *arg); -bool i2c_hw_engine_dce110_construct( - struct i2c_hw_engine_dce110 *engine_dce110, - const struct i2c_hw_engine_dce110_create_arg *arg); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c index bf2c4b240b78..3aa7f791e523 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_sw_engine_dce110.c @@ -118,7 +118,7 @@ static const struct engine_funcs engine_funcs = { .submit_request = dal_i2c_sw_engine_submit_request, }; -static bool construct( +static void construct( struct i2c_sw_engine_dce110 *engine_dce110, const struct i2c_sw_engine_dce110_create_arg *arg_dce110) { @@ -127,11 +127,7 @@ static bool construct( arg_base.ctx = arg_dce110->ctx; arg_base.default_speed = arg_dce110->default_speed; - if (!dal_i2c_sw_engine_construct( - &engine_dce110->base, &arg_base)) { - ASSERT_CRITICAL(false); - return false; - } + dal_i2c_sw_engine_construct(&engine_dce110->base, &arg_base); /*struct engine struct engine_funcs*/ engine_dce110->base.base.base.funcs = &engine_funcs; @@ -139,8 +135,6 @@ static bool construct( engine_dce110->base.base.funcs = &i2c_engine_funcs; engine_dce110->base.default_speed = arg_dce110->default_speed; engine_dce110->engine_id = arg_dce110->engine_id; - - return true; } struct i2c_engine *dal_i2c_sw_engine_dce110_create( @@ -161,12 +155,6 @@ struct i2c_engine *dal_i2c_sw_engine_dce110_create( return NULL; } - if (construct(engine_dce110, arg)) - return &engine_dce110->base.base; - - ASSERT_CRITICAL(false); - - kfree(engine_dce110); - - return NULL; + construct(engine_dce110, arg); + return &engine_dce110->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c index ae9adb389319..2a047f8ca0e9 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.c @@ -196,7 +196,7 @@ static const struct dce110_i2c_hw_engine_mask i2c_mask = { I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) }; -bool dal_i2caux_dce110_construct( +void dal_i2caux_dce110_construct( struct i2caux_dce110 *i2caux_dce110, struct dc_context *ctx, const struct dce110_aux_registers aux_regs[], @@ -217,10 +217,7 @@ bool dal_i2caux_dce110_construct( base = &i2caux_dce110->base; - if (!dal_i2caux_construct(base, ctx)) { - ASSERT_CRITICAL(false); - return false; - } + dal_i2caux_construct(base, ctx); i2caux_dce110->base.funcs = &i2caux_funcs; i2caux_dce110->i2c_hw_buffer_in_use = false; @@ -278,8 +275,6 @@ bool dal_i2caux_dce110_construct( } while (i < ARRAY_SIZE(hw_aux_lines)); /*TODO Generic I2C SW and HW*/ - - return true; } /* @@ -306,18 +301,11 @@ struct i2caux *dal_i2caux_dce110_create( return NULL; } - if (dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dce110_aux_regs, - i2c_hw_engine_regs, - &i2c_shift, - &i2c_mask)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dce110_aux_regs, + i2c_hw_engine_regs, + &i2c_shift, + &i2c_mask); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h index fd1cc23c3d70..1b1f71c60ac9 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2caux_dce110.h @@ -42,7 +42,7 @@ struct dce110_i2c_hw_engine_mask; struct i2caux *dal_i2caux_dce110_create( struct dc_context *ctx); -bool dal_i2caux_dce110_construct( +void dal_i2caux_dce110_construct( struct i2caux_dce110 *i2caux_dce110, struct dc_context *ctx, const struct dce110_aux_registers *aux_regs, diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c index 715ba4390957..dafc1a727f7f 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce112/i2caux_dce112.c @@ -87,22 +87,16 @@ static const struct dce110_i2c_hw_engine_mask i2c_mask = { I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) }; -static bool construct( +static void construct( struct i2caux_dce110 *i2caux_dce110, struct dc_context *ctx) { - if (!dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dce112_aux_regs, - dce112_hw_engine_regs, - &i2c_shift, - &i2c_mask)) { - ASSERT_CRITICAL(false); - return false; - } - - return true; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dce112_aux_regs, + dce112_hw_engine_regs, + &i2c_shift, + &i2c_mask); } /* @@ -129,12 +123,6 @@ struct i2caux *dal_i2caux_dce112_create( return NULL; } - if (construct(i2caux_dce110, ctx)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + construct(i2caux_dce110, ctx); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c index d52827ae3f1a..668981a4c285 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce120/i2caux_dce120.c @@ -108,18 +108,11 @@ struct i2caux *dal_i2caux_dce120_create( return NULL; } - if (dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dce120_aux_regs, - dce120_hw_engine_regs, - &i2c_shift, - &i2c_mask)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dce120_aux_regs, + dce120_hw_engine_regs, + &i2c_shift, + &i2c_mask); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c index d41e37c94214..fd0832dd2c75 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c @@ -824,20 +824,11 @@ static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = { dal_i2c_hw_engine_wait_on_operation_result, }; -static bool construct( +static void construct( struct i2c_hw_engine_dce80 *engine, const struct i2c_hw_engine_dce80_create_arg *arg) { - if (arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) - return false; - if (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) - return false; - - if (!arg->reference_frequency) - return false; - - if (!dal_i2c_hw_engine_construct(&engine->base, arg->ctx)) - return false; + dal_i2c_hw_engine_construct(&engine->base, arg->ctx); engine->base.base.base.funcs = &engine_funcs; engine->base.base.funcs = &i2c_engine_funcs; @@ -853,8 +844,6 @@ static bool construct( engine->buffer_used_bytes = 0; engine->transaction_count = 0; engine->engine_keep_power_up_count = 1; - - return true; } struct i2c_engine *dal_i2c_hw_engine_dce80_create( @@ -867,6 +856,13 @@ struct i2c_engine *dal_i2c_hw_engine_dce80_create( return NULL; } + if ((arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) || + (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) || + !arg->reference_frequency) { + BREAK_TO_DEBUGGER(); + return NULL; + } + engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL); if (!engine) { @@ -874,12 +870,6 @@ struct i2c_engine *dal_i2c_hw_engine_dce80_create( return NULL; } - if (construct(engine, arg)) - return &engine->base.base; - - BREAK_TO_DEBUGGER(); - - kfree(engine); - - return NULL; + construct(engine, arg); + return &engine->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c index 6be77bc931c6..4853ee26096a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_sw_engine_dce80.c @@ -133,7 +133,7 @@ static const struct engine_funcs engine_funcs = { .submit_request = dal_i2c_sw_engine_submit_request, }; -static bool construct( +static void construct( struct i2c_sw_engine_dce80 *engine, const struct i2c_sw_engine_dce80_create_arg *arg) { @@ -142,17 +142,12 @@ static bool construct( arg_base.ctx = arg->ctx; arg_base.default_speed = arg->default_speed; - if (!dal_i2c_sw_engine_construct(&engine->base, &arg_base)) { - BREAK_TO_DEBUGGER(); - return false; - } + dal_i2c_sw_engine_construct(&engine->base, &arg_base); engine->base.base.base.funcs = &engine_funcs; engine->base.base.funcs = &i2c_engine_funcs; engine->base.default_speed = arg->default_speed; engine->engine_id = arg->engine_id; - - return true; } struct i2c_engine *dal_i2c_sw_engine_dce80_create( @@ -172,13 +167,7 @@ struct i2c_engine *dal_i2c_sw_engine_dce80_create( return NULL; } - if (construct(engine, arg)) - return &engine->base.base; - - BREAK_TO_DEBUGGER(); - - kfree(engine); - - return NULL; + construct(engine, arg); + return &engine->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c index d3c157e5eccd..ed48596dd2a5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2caux_dce80.c @@ -187,7 +187,7 @@ static const struct i2caux_funcs i2caux_funcs = { .acquire_aux_engine = dal_i2caux_acquire_aux_engine, }; -static bool construct( +static void construct( struct i2caux_dce80 *i2caux_dce80, struct dc_context *ctx) { @@ -207,10 +207,7 @@ static bool construct( uint32_t i; - if (!dal_i2caux_construct(base, ctx)) { - BREAK_TO_DEBUGGER(); - return false; - } + dal_i2caux_construct(base, ctx); i2caux_dce80->base.funcs = &i2caux_funcs; i2caux_dce80->i2c_hw_buffer_in_use = false; @@ -269,8 +266,6 @@ static bool construct( } while (i < ARRAY_SIZE(hw_aux_lines)); /* TODO Generic I2C SW and HW */ - - return true; } struct i2caux *dal_i2caux_dce80_create( @@ -284,12 +279,6 @@ struct i2caux *dal_i2caux_dce80_create( return NULL; } - if (construct(i2caux_dce80, ctx)) - return &i2caux_dce80->base; - - BREAK_TO_DEBUGGER(); - - kfree(i2caux_dce80); - - return NULL; + construct(i2caux_dce80, ctx); + return &i2caux_dce80->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c index f8659f1c5f9d..13b807d8aff8 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dcn10/i2caux_dcn10.c @@ -108,18 +108,11 @@ struct i2caux *dal_i2caux_dcn10_create( return NULL; } - if (dal_i2caux_dce110_construct( - i2caux_dce110, - ctx, - dcn10_aux_regs, - dcn10_hw_engine_regs, - &i2c_shift, - &i2c_mask)) - return &i2caux_dce110->base; - - ASSERT_CRITICAL(false); - - kfree(i2caux_dce110); - - return NULL; + dal_i2caux_dce110_construct(i2caux_dce110, + ctx, + dcn10_aux_regs, + dcn10_hw_engine_regs, + &i2c_shift, + &i2c_mask); + return &i2caux_dce110->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c index 1fdb3252920b..e6408f644086 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/diagnostics/i2caux_diag.c @@ -73,18 +73,12 @@ static const struct i2caux_funcs i2caux_funcs = { .acquire_aux_engine = NULL, }; -static bool construct( +static void construct( struct i2caux *i2caux, struct dc_context *ctx) { - if (!dal_i2caux_construct(i2caux, ctx)) { - ASSERT_CRITICAL(false); - return false; - } - + dal_i2caux_construct(i2caux, ctx); i2caux->funcs = &i2caux_funcs; - - return true; } struct i2caux *dal_i2caux_diag_fpga_create( @@ -98,12 +92,6 @@ struct i2caux *dal_i2caux_diag_fpga_create( return NULL; } - if (construct(i2caux, ctx)) - return i2caux; - - ASSERT_CRITICAL(false); - - kfree(i2caux); - - return NULL; + construct(i2caux, ctx); + return i2caux; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h index 76fe2df3c2f8..33de8a8834dc 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine.h @@ -110,7 +110,7 @@ struct engine { struct dc_context *ctx; }; -bool dal_i2caux_construct_engine( +void dal_i2caux_construct_engine( struct engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c index 09da81379491..5d155d36d353 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/engine_base.c @@ -36,13 +36,12 @@ #include "engine.h" -bool dal_i2caux_construct_engine( +void dal_i2caux_construct_engine( struct engine *engine, struct dc_context *ctx) { engine->ddc = NULL; engine->ctx = ctx; - return true; } void dal_i2caux_destruct_engine( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c index 144f51dc4523..70e20bd47ce4 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.c @@ -103,15 +103,12 @@ void dal_i2c_engine_process_channel_reply( } -bool dal_i2c_engine_construct( +void dal_i2c_engine_construct( struct i2c_engine *engine, struct dc_context *ctx) { - if (!dal_i2caux_construct_engine(&engine->base, ctx)) - return false; - + dal_i2caux_construct_engine(&engine->base, ctx); engine->timeout_delay = 0; - return true; } void dal_i2c_engine_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h index ce2c51ddea02..58fc0f25eceb 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_engine.h @@ -88,7 +88,7 @@ struct i2c_engine { uint32_t timeout_delay; }; -bool dal_i2c_engine_construct( +void dal_i2c_engine_construct( struct i2c_engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c index 521c4ec98632..5a4295e0fae5 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.c @@ -270,13 +270,11 @@ uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout( (1 + (length << 3) + 1); } -bool dal_i2c_generic_hw_engine_construct( +void dal_i2c_generic_hw_engine_construct( struct i2c_generic_hw_engine *engine, struct dc_context *ctx) { - if (!dal_i2c_hw_engine_construct(&engine->base, ctx)) - return false; - return true; + dal_i2c_hw_engine_construct(&engine->base, ctx); } void dal_i2c_generic_hw_engine_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h index 083bb0dee9a1..1da0397b04a2 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_generic_hw_engine.h @@ -59,7 +59,7 @@ struct i2c_generic_hw_engine { const struct i2c_generic_hw_engine_funcs *funcs; }; -bool dal_i2c_generic_hw_engine_construct( +void dal_i2c_generic_hw_engine_construct( struct i2c_generic_hw_engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c index 00a8f07a74e9..4b54fcfb28ec 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.c @@ -228,15 +228,13 @@ enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result( return result; } -bool dal_i2c_hw_engine_construct( +void dal_i2c_hw_engine_construct( struct i2c_hw_engine *engine, struct dc_context *ctx) { - if (!dal_i2c_engine_construct(&engine->base, ctx)) - return false; + dal_i2c_engine_construct(&engine->base, ctx); engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED; - return true; } void dal_i2c_hw_engine_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h index f2df1749820e..8936a994804a 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_hw_engine.h @@ -53,7 +53,7 @@ struct i2c_hw_engine { uint32_t default_speed; }; -bool dal_i2c_hw_engine_construct( +void dal_i2c_hw_engine_construct( struct i2c_hw_engine *engine, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c index 9d0077ade12c..8e19bb629394 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.c @@ -569,17 +569,14 @@ static const struct engine_funcs engine_funcs = { .submit_request = dal_i2c_sw_engine_submit_request, }; -bool dal_i2c_sw_engine_construct( +void dal_i2c_sw_engine_construct( struct i2c_sw_engine *engine, const struct i2c_sw_engine_create_arg *arg) { - if (!dal_i2c_engine_construct(&engine->base, arg->ctx)) - return false; - + dal_i2c_engine_construct(&engine->base, arg->ctx); dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed); engine->base.funcs = &i2c_engine_funcs; engine->base.base.funcs = &engine_funcs; - return true; } struct i2c_engine *dal_i2c_sw_engine_create( @@ -599,12 +596,6 @@ struct i2c_engine *dal_i2c_sw_engine_create( return NULL; } - if (dal_i2c_sw_engine_construct(engine, arg)) - return &engine->base; - - BREAK_TO_DEBUGGER(); - - kfree(engine); - - return NULL; + dal_i2c_sw_engine_construct(engine, arg); + return &engine->base; } diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h index e0cb4c3d483d..546f15b0d3f1 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2c_sw_engine.h @@ -48,7 +48,7 @@ struct i2c_sw_engine_create_arg { struct dc_context *ctx; }; -bool dal_i2c_sw_engine_construct( +void dal_i2c_sw_engine_construct( struct i2c_sw_engine *engine, const struct i2c_sw_engine_create_arg *arg); diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c index 9b115e1e2f1a..e1593ffe5a2b 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c @@ -423,7 +423,7 @@ void dal_i2caux_release_engine( engine->ddc = NULL; } -bool dal_i2caux_construct( +void dal_i2caux_construct( struct i2caux *i2caux, struct dc_context *ctx) { @@ -451,8 +451,6 @@ bool dal_i2caux_construct( i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED; i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED; } - - return true; } void dal_i2caux_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h index bc20de3da1c4..64f51bb06915 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h +++ b/drivers/gpu/drm/amd/display/dc/i2caux/i2caux.h @@ -97,7 +97,7 @@ struct i2caux { uint32_t default_i2c_hw_speed; }; -bool dal_i2caux_construct( +void dal_i2caux_construct( struct i2caux *i2caux, struct dc_context *ctx); -- GitLab From 0e1c42fd181e7359be5c97655198551b6660f028 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:38 +1000 Subject: [PATCH 0953/2898] amdgpu/dc: cleanup construct returns in gpio. This is similiar to previous patches, don't return when we don't need to, also do error checking before allocating memory, makes it simpler to cleanup after. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c | 33 +++++-------- drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c | 4 +- drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h | 2 +- drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c | 47 +++++++------------ 4 files changed, 30 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c index 7b6efa4f2efd..310f48965b27 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c @@ -199,25 +199,14 @@ static const struct hw_gpio_pin_funcs funcs = { .close = dal_hw_gpio_close, }; -static bool construct( +static void construct( struct hw_ddc *ddc, enum gpio_id id, uint32_t en, struct dc_context *ctx) { - if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) { - ASSERT_CRITICAL(false); - return false; - } - - if (!dal_hw_gpio_construct(&ddc->base, id, en, ctx)) { - ASSERT_CRITICAL(false); - return false; - } - + dal_hw_gpio_construct(&ddc->base, id, en, ctx); ddc->base.base.funcs = &funcs; - - return true; } struct hw_gpio_pin *dal_hw_ddc_create( @@ -225,19 +214,19 @@ struct hw_gpio_pin *dal_hw_ddc_create( enum gpio_id id, uint32_t en) { - struct hw_ddc *pin = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL); + struct hw_ddc *pin; - if (!pin) { + if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) { ASSERT_CRITICAL(false); return NULL; } - if (construct(pin, id, en, ctx)) - return &pin->base.base; - - ASSERT_CRITICAL(false); - - kfree(pin); + pin = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL); + if (!pin) { + ASSERT_CRITICAL(false); + return NULL; + } - return NULL; + construct(pin, id, en, ctx); + return &pin->base.base; } diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c index 4cdcdfb73e5c..660510842ecf 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c @@ -176,7 +176,7 @@ enum gpio_result dal_hw_gpio_config_mode( } } -bool dal_hw_gpio_construct( +void dal_hw_gpio_construct( struct hw_gpio *pin, enum gpio_id id, uint32_t en, @@ -194,8 +194,6 @@ bool dal_hw_gpio_construct( pin->store.mux = 0; pin->mux_supported = false; - - return true; } void dal_hw_gpio_destruct( diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h index fb41ee2be958..bca0cef18ff9 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.h @@ -109,7 +109,7 @@ struct hw_gpio { #define HW_GPIO_FROM_BASE(hw_gpio_pin) \ container_of((hw_gpio_pin), struct hw_gpio, base) -bool dal_hw_gpio_construct( +void dal_hw_gpio_construct( struct hw_gpio *pin, enum gpio_id id, uint32_t en, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c index 0c255c02045b..784feccc5853 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c @@ -41,15 +41,13 @@ #define REG(reg)\ (hpd->regs->reg) -static bool dal_hw_hpd_construct( +static void dal_hw_hpd_construct( struct hw_hpd *pin, enum gpio_id id, uint32_t en, struct dc_context *ctx) { - if (!dal_hw_gpio_construct(&pin->base, id, en, ctx)) - return false; - return true; + dal_hw_gpio_construct(&pin->base, id, en, ctx); } static void dal_hw_hpd_destruct( @@ -126,30 +124,14 @@ static const struct hw_gpio_pin_funcs funcs = { .close = dal_hw_gpio_close, }; -static bool construct( +static void construct( struct hw_hpd *hpd, enum gpio_id id, uint32_t en, struct dc_context *ctx) { - if (id != GPIO_ID_HPD) { - ASSERT_CRITICAL(false); - return false; - } - - if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) { - ASSERT_CRITICAL(false); - return false; - } - - if (!dal_hw_hpd_construct(hpd, id, en, ctx)) { - ASSERT_CRITICAL(false); - return false; - } - + dal_hw_hpd_construct(hpd, id, en, ctx); hpd->base.base.funcs = &funcs; - - return true; } struct hw_gpio_pin *dal_hw_hpd_create( @@ -157,19 +139,24 @@ struct hw_gpio_pin *dal_hw_hpd_create( enum gpio_id id, uint32_t en) { - struct hw_hpd *hpd = kzalloc(sizeof(struct hw_hpd), GFP_KERNEL); + struct hw_hpd *hpd; - if (!hpd) { + if (id != GPIO_ID_HPD) { ASSERT_CRITICAL(false); return NULL; } - if (construct(hpd, id, en, ctx)) - return &hpd->base.base; - - ASSERT_CRITICAL(false); + if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) { + ASSERT_CRITICAL(false); + return NULL; + } - kfree(hpd); + hpd = kzalloc(sizeof(struct hw_hpd), GFP_KERNEL); + if (!hpd) { + ASSERT_CRITICAL(false); + return NULL; + } - return NULL; + construct(hpd, id, en, ctx); + return &hpd->base.base; } -- GitLab From c13b408b81f8a101501d78ca499afee98e0f0ab9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:39 +1000 Subject: [PATCH 0954/2898] amdgpu/dc: another round of dce/dcn construct cleanups. This removes any remaining pointless return codepaths from the DCE code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce100/dce100_hw_sequencer.c | 4 +--- .../display/dc/dce100/dce100_hw_sequencer.h | 2 +- .../amd/display/dc/dce100/dce100_resource.c | 4 +--- .../amd/display/dc/dce110/dce110_compressor.c | 11 +++------- .../amd/display/dc/dce110/dce110_compressor.h | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 4 +--- .../display/dc/dce110/dce110_hw_sequencer.h | 2 +- .../drm/amd/display/dc/dce110/dce110_opp_v.c | 4 +--- .../drm/amd/display/dc/dce110/dce110_opp_v.h | 2 +- .../amd/display/dc/dce110/dce110_resource.c | 6 ++---- .../dc/dce110/dce110_timing_generator_v.c | 7 +------ .../dc/dce110/dce110_timing_generator_v.h | 2 +- .../amd/display/dc/dce112/dce112_compressor.c | 11 +++------- .../amd/display/dc/dce112/dce112_compressor.h | 2 +- .../display/dc/dce112/dce112_hw_sequencer.c | 4 +--- .../display/dc/dce112/dce112_hw_sequencer.h | 2 +- .../amd/display/dc/dce112/dce112_resource.c | 3 +-- .../display/dc/dce120/dce120_hw_sequencer.c | 4 +--- .../display/dc/dce120/dce120_hw_sequencer.h | 2 +- .../amd/display/dc/dce120/dce120_resource.c | 8 ++------ .../dc/dce120/dce120_timing_generator.c | 7 +------ .../dc/dce120/dce120_timing_generator.h | 2 +- .../amd/display/dc/dce80/dce80_compressor.c | 11 +++------- .../amd/display/dc/dce80/dce80_compressor.h | 2 +- .../amd/display/dc/dce80/dce80_hw_sequencer.c | 4 +--- .../amd/display/dc/dce80/dce80_hw_sequencer.h | 2 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 9 +++------ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 4 +--- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 2 +- .../amd/display/dc/dcn10/dcn10_mem_input.c | 4 +--- .../amd/display/dc/dcn10/dcn10_mem_input.h | 2 +- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 20 ++++++------------- 32 files changed, 47 insertions(+), 108 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c index 492ea6069eb4..e7a694835e3e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c @@ -142,13 +142,11 @@ void dce100_set_bandwidth( /**************************************************************************/ -bool dce100_hw_sequencer_construct(struct dc *dc) +void dce100_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating; dc->hwss.set_bandwidth = dce100_set_bandwidth; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h index 770b5bb1ff40..cb5384ef46c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.h @@ -31,7 +31,7 @@ struct dc; struct dc_state; -bool dce100_hw_sequencer_construct(struct dc *dc); +void dce100_hw_sequencer_construct(struct dc *dc); void dce100_set_bandwidth( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 1caf2983dda5..0db987d504c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -909,9 +909,7 @@ static bool construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce100_hw_sequencer_construct(dc)) - goto res_create_fail; - + dce100_hw_sequencer_construct(dc); return true; res_create_fail: diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 90770cb2ffcd..3872febb4f6b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -393,12 +393,8 @@ struct compressor *dce110_compressor_create(struct dc_context *ctx) if (!cp110) return NULL; - if (dce110_compressor_construct(cp110, ctx)) - return &cp110->base; - - BREAK_TO_DEBUGGER(); - kfree(cp110); - return NULL; + dce110_compressor_construct(cp110, ctx); + return &cp110->base; } void dce110_compressor_destroy(struct compressor **compressor) @@ -485,7 +481,7 @@ static const struct compressor_funcs dce110_compressor_funcs = { }; -bool dce110_compressor_construct(struct dce110_compressor *compressor, +void dce110_compressor_construct(struct dce110_compressor *compressor, struct dc_context *ctx) { @@ -522,6 +518,5 @@ bool dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.funcs = &dce110_compressor_funcs; #endif - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h index 460cb77b8d75..26c7335a1cbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.h @@ -42,7 +42,7 @@ struct dce110_compressor { struct compressor *dce110_compressor_create(struct dc_context *ctx); -bool dce110_compressor_construct(struct dce110_compressor *cp110, +void dce110_compressor_construct(struct dce110_compressor *cp110, struct dc_context *ctx); void dce110_compressor_destroy(struct compressor **cp); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5bbfc34d6f01..de154329b049 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2723,10 +2723,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { }; -bool dce110_hw_sequencer_construct(struct dc *dc) +void dce110_hw_sequencer_construct(struct dc *dc) { dc->hwss = dce110_funcs; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index baa20c1f17ad..db6c19cd15eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -33,7 +33,7 @@ struct dc; struct dc_state; struct dm_pp_display_configuration; -bool dce110_hw_sequencer_construct(struct dc *dc); +void dce110_hw_sequencer_construct(struct dc *dc); enum dc_status dce110_apply_ctx_to_hw( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c index 69d6a110dbc3..3545e43a4b77 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c @@ -44,13 +44,11 @@ static const struct opp_funcs funcs = { dce110_opp_program_bit_depth_reduction }; -bool dce110_opp_v_construct(struct dce110_opp *opp110, +void dce110_opp_v_construct(struct dce110_opp *opp110, struct dc_context *ctx) { opp110->base.funcs = &funcs; opp110->base.ctx = ctx; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h index 269c1a88d5bb..152af4c418cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h @@ -29,7 +29,7 @@ #include "opp.h" #include "core_types.h" -bool dce110_opp_v_construct(struct dce110_opp *opp110, +void dce110_opp_v_construct(struct dce110_opp *opp110, struct dc_context *ctx); /* underlay callbacks */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 45c5facf79b1..017a1fd1f659 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1041,8 +1041,7 @@ static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) (dce110_oppv == NULL)) return false; - if (!dce110_opp_v_construct(dce110_oppv, ctx)) - return false; + dce110_opp_v_construct(dce110_oppv, ctx); dce110_timing_generator_v_construct(dce110_tgv, ctx); dce110_mem_input_v_construct(dce110_miv, ctx); @@ -1292,8 +1291,7 @@ static bool construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce110_hw_sequencer_construct(dc)) - goto res_create_fail; + dce110_hw_sequencer_construct(dc); dc->caps.max_planes = pool->base.pipe_count; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c index 93ca6ae48cb9..07d9303d5477 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c @@ -668,13 +668,10 @@ static const struct timing_generator_funcs dce110_tg_v_funcs = { dce110_timing_generator_v_enable_advanced_request }; -bool dce110_timing_generator_v_construct( +void dce110_timing_generator_v_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx) { - if (!tg110) - return false; - tg110->controller_id = CONTROLLER_ID_UNDERLAY0; tg110->base.funcs = &dce110_tg_v_funcs; @@ -688,6 +685,4 @@ bool dce110_timing_generator_v_construct( tg110->min_h_blank = 56; tg110->min_h_front_porch = 4; tg110->min_h_back_porch = 4; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h index 7e49ca8e26ad..d2623a5994e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.h @@ -26,7 +26,7 @@ #ifndef __DC_TIMING_GENERATOR_V_DCE110_H__ #define __DC_TIMING_GENERATOR_V_DCE110_H__ -bool dce110_timing_generator_v_construct( +void dce110_timing_generator_v_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c index e75895baa132..69649928768c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c @@ -791,7 +791,7 @@ void dce112_compressor_set_fbc_invalidation_triggers( dm_write_reg(compressor->ctx, addr, value); } -bool dce112_compressor_construct(struct dce112_compressor *compressor, +void dce112_compressor_construct(struct dce112_compressor *compressor, struct dc_context *ctx) { struct dc_bios *bp = ctx->dc_bios; @@ -833,7 +833,6 @@ bool dce112_compressor_construct(struct dce112_compressor *compressor, compressor->base.embedded_panel_v_size = panel_info.lcd_timing.vertical_addressable; } - return true; } struct compressor *dce112_compressor_create(struct dc_context *ctx) @@ -844,12 +843,8 @@ struct compressor *dce112_compressor_create(struct dc_context *ctx) if (!cp110) return NULL; - if (dce112_compressor_construct(cp110, ctx)) - return &cp110->base; - - BREAK_TO_DEBUGGER(); - kfree(cp110); - return NULL; + dce112_compressor_construct(cp110, ctx); + return &cp110->base; } void dce112_compressor_destroy(struct compressor **compressor) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h index 106506387270..f1227133f6df 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.h @@ -42,7 +42,7 @@ struct dce112_compressor { struct compressor *dce112_compressor_create(struct dc_context *ctx); -bool dce112_compressor_construct(struct dce112_compressor *cp110, +void dce112_compressor_construct(struct dce112_compressor *cp110, struct dc_context *ctx); void dce112_compressor_destroy(struct compressor **cp); diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c index 8816e09110e1..1e4a7c13f0ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.c @@ -152,14 +152,12 @@ static bool dce112_enable_display_power_gating( return false; } -bool dce112_hw_sequencer_construct(struct dc *dc) +void dce112_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure */ dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce112_enable_display_power_gating; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h index 37bd60cc93f9..e646f4a37fa2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_hw_sequencer.h @@ -30,7 +30,7 @@ struct dc; -bool dce112_hw_sequencer_construct(struct dc *dc); +void dce112_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 251e4a29d56f..11902a2fdaa4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1256,8 +1256,7 @@ static bool construct( dc->caps.max_planes = pool->base.pipe_count; /* Create hardware sequencer */ - if (!dce112_hw_sequencer_construct(dc)) - goto res_create_fail; + dce112_hw_sequencer_construct(dc); bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index 56e3b124f19c..1a0b54d6034e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -245,7 +245,7 @@ static void dce120_update_dchub( -bool dce120_hw_sequencer_construct(struct dc *dc) +void dce120_hw_sequencer_construct(struct dc *dc) { /* All registers used by dce11.2 match those in dce11 in offset and * structure @@ -253,7 +253,5 @@ bool dce120_hw_sequencer_construct(struct dc *dc) dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating; dc->hwss.update_dchub = dce120_update_dchub; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h index 6448a17c2fde..77a6b86d7606 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.h @@ -30,7 +30,7 @@ struct dc; -bool dce120_hw_sequencer_construct(struct dc *dc); +void dce120_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE112_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 13d75df71396..3ed28a870e20 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -429,12 +429,8 @@ static struct timing_generator *dce120_timing_generator_create( if (!tg110) return NULL; - if (dce120_timing_generator_construct(tg110, ctx, instance, offsets)) - return &tg110->base; - - BREAK_TO_DEBUGGER(); - kfree(tg110); - return NULL; + dce120_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; } static void dce120_transform_destroy(struct transform **xfm) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 791c9b084941..95d871be3a0b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -1143,15 +1143,12 @@ static const struct timing_generator_funcs dce120_tg_funcs = { }; -bool dce120_timing_generator_construct( +void dce120_timing_generator_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx, uint32_t instance, const struct dce110_timing_generator_offsets *offsets) { - if (!tg110) - return false; - tg110->controller_id = CONTROLLER_ID_D0 + instance; tg110->base.inst = instance; @@ -1175,6 +1172,4 @@ bool dce120_timing_generator_construct( tg110->min_h_sync_width = 8; tg110->min_v_sync_width = 1; tg110->min_v_blank = 3; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h index 243c0a3493da..d69871ec0dde 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h @@ -32,7 +32,7 @@ #include "dce110/dce110_timing_generator.h" -bool dce120_timing_generator_construct( +void dce120_timing_generator_construct( struct dce110_timing_generator *tg110, struct dc_context *ctx, uint32_t instance, diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c index cc1c0d390945..951f2caba9b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.c @@ -771,7 +771,7 @@ void dce80_compressor_set_fbc_invalidation_triggers( dm_write_reg(compressor->ctx, addr, value); } -bool dce80_compressor_construct(struct dce80_compressor *compressor, +void dce80_compressor_construct(struct dce80_compressor *compressor, struct dc_context *ctx) { struct dc_bios *bp = ctx->dc_bios; @@ -813,7 +813,6 @@ bool dce80_compressor_construct(struct dce80_compressor *compressor, compressor->base.embedded_panel_v_size = panel_info.lcd_timing.vertical_addressable; } - return true; } struct compressor *dce80_compressor_create(struct dc_context *ctx) @@ -824,12 +823,8 @@ struct compressor *dce80_compressor_create(struct dc_context *ctx) if (!cp80) return NULL; - if (dce80_compressor_construct(cp80, ctx)) - return &cp80->base; - - BREAK_TO_DEBUGGER(); - kfree(cp80); - return NULL; + dce80_compressor_construct(cp80, ctx); + return &cp80->base; } void dce80_compressor_destroy(struct compressor **compressor) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h index 01290969ff92..cca58b044402 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_compressor.h @@ -42,7 +42,7 @@ struct dce80_compressor { struct compressor *dce80_compressor_create(struct dc_context *ctx); -bool dce80_compressor_construct(struct dce80_compressor *cp80, +void dce80_compressor_construct(struct dce80_compressor *cp80, struct dc_context *ctx); void dce80_compressor_destroy(struct compressor **cp); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c index 28fe3824441f..ccfcf1c0eeb3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c @@ -106,14 +106,12 @@ static bool dce80_enable_display_power_gating( return false; } -bool dce80_hw_sequencer_construct(struct dc *dc) +void dce80_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating; dc->hwss.pipe_control_lock = dce_pipe_control_lock; dc->hwss.set_bandwidth = dce100_set_bandwidth; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h index 9d6dd05bd596..7a1b31def66f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.h @@ -30,7 +30,7 @@ struct dc; -bool dce80_hw_sequencer_construct(struct dc *dc); +void dce80_hw_sequencer_construct(struct dc *dc); #endif /* __DC_HWSS_DCE80_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 5e00ca6a1292..c6571a908786 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -910,8 +910,7 @@ static bool dce80_construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce80_hw_sequencer_construct(dc)) - goto res_create_fail; + dce80_hw_sequencer_construct(dc); return true; @@ -1075,8 +1074,7 @@ static bool dce81_construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce80_hw_sequencer_construct(dc)) - goto res_create_fail; + dce80_hw_sequencer_construct(dc); return true; @@ -1236,8 +1234,7 @@ static bool dce83_construct( goto res_create_fail; /* Create hardware sequencer */ - if (!dce80_hw_sequencer_construct(dc)) - goto res_create_fail; + dce80_hw_sequencer_construct(dc); return true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 8607ab2da610..9d9604f05095 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -397,7 +397,7 @@ static const struct transform_funcs dcn10_dpp_funcs = { /* Constructor, Destructor */ /*****************************************/ -bool dcn10_dpp_construct( +void dcn10_dpp_construct( struct dcn10_dpp *xfm, struct dc_context *ctx, uint32_t inst, @@ -421,6 +421,4 @@ bool dcn10_dpp_construct( xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index afe9d8f629d6..a1f6b01a2eb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1356,7 +1356,7 @@ void ippn10_cnv_setup ( void ippn10_full_bypass(struct transform *xfm_base); -bool dcn10_dpp_construct(struct dcn10_dpp *xfm110, +void dcn10_dpp_construct(struct dcn10_dpp *xfm110, struct dc_context *ctx, uint32_t inst, const struct dcn_dpp_registers *tf_regs, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 9008cd03b139..c8088489c6a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -786,7 +786,7 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { /* Constructor, Destructor */ /*****************************************/ -bool dcn10_mem_input_construct( +void dcn10_mem_input_construct( struct dcn10_mem_input *mi, struct dc_context *ctx, uint32_t inst, @@ -802,7 +802,5 @@ bool dcn10_mem_input_construct( mi->base.inst = inst; mi->base.opp_id = 0xf; mi->base.mpcc_id = 0xf; - - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index acee05155b5b..aefd3e7bd7eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -538,7 +538,7 @@ struct dcn10_mem_input { const struct dcn_mi_mask *mi_mask; }; -bool dcn10_mem_input_construct( +void dcn10_mem_input_construct( struct dcn10_mem_input *mi, struct dc_context *ctx, uint32_t inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index c2df57b5e921..fb3ef134ea12 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -462,13 +462,9 @@ static struct transform *dcn10_dpp_create( if (!dpp) return NULL; - if (dcn10_dpp_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; + dcn10_dpp_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask); + return &dpp->base; } static struct input_pixel_processor *dcn10_ipp_create( @@ -771,13 +767,9 @@ static struct mem_input *dcn10_mem_input_create( if (!mem_inputn10) return NULL; - if (dcn10_mem_input_construct(mem_inputn10, ctx, inst, - &mi_regs[inst], &mi_shift, &mi_mask)) - return &mem_inputn10->base; - - BREAK_TO_DEBUGGER(); - kfree(mem_inputn10); - return NULL; + dcn10_mem_input_construct(mem_inputn10, ctx, inst, + &mi_regs[inst], &mi_shift, &mi_mask); + return &mem_inputn10->base; } static void get_pixel_clock_parameters( -- GitLab From 94de2bbdfa613165ff20a3e958775c8d01581946 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:40 +1000 Subject: [PATCH 0955/2898] amdgpu/dc: remove pointless return from build_pipe_hw_param This never returned anything else. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce100/dce100_resource.c | 6 +----- .../gpu/drm/amd/display/dc/dce110/dce110_resource.c | 10 ++-------- .../gpu/drm/amd/display/dc/dce110/dce110_resource.h | 2 +- .../gpu/drm/amd/display/dc/dce112/dce112_resource.c | 6 +----- drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 6 +----- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 11 ++--------- 6 files changed, 8 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 0db987d504c0..b1cf591b3408 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -631,16 +631,12 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); if (!pipe_ctx) return DC_ERROR_UNEXPECTED; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; + dce110_resource_build_pipe_hw_param(pipe_ctx); resource_build_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 017a1fd1f659..89036aff9021 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -724,7 +724,7 @@ static void get_pixel_clock_parameters( } } -enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +void dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); pipe_ctx->clock_source->funcs->get_pix_clk_dividers( @@ -734,8 +734,6 @@ enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; - - return DC_OK; } static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx) @@ -754,7 +752,6 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); if (!pipe_ctx) @@ -764,10 +761,7 @@ static enum dc_status build_mapped_resource( dc->res_pool->underlay_pipe_index)) return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; + dce110_resource_build_pipe_hw_param(pipe_ctx); /* TODO: validate audio ASIC caps, encoder */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h index 5bb692d037d9..e5f168c1f8c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h @@ -38,7 +38,7 @@ struct dce110_resource_pool { struct resource_pool base; }; -enum dc_status dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); +void dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); struct resource_pool *dce110_create_resource_pool( uint8_t num_virtual_links, diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 11902a2fdaa4..663e0a047a4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -704,16 +704,12 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); if (!pipe_ctx) return DC_ERROR_UNEXPECTED; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; + dce110_resource_build_pipe_hw_param(pipe_ctx); resource_build_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index c6571a908786..9c18efd3446f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -665,16 +665,12 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); if (!pipe_ctx) return DC_ERROR_UNEXPECTED; - status = dce110_resource_build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; + dce110_resource_build_pipe_hw_param(pipe_ctx); resource_build_info_frame(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index fb3ef134ea12..dc878f77837b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -805,7 +805,7 @@ static void build_clamping_params(struct dc_stream_state *stream) stream->clamping.pixel_encoding = stream->timing.pixel_encoding; } -static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +static void build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); @@ -820,8 +820,6 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) resource_build_bit_depth_reduction_params(pipe_ctx->stream, &pipe_ctx->stream->bit_depth_params); build_clamping_params(pipe_ctx->stream); - - return DC_OK; } static enum dc_status build_mapped_resource( @@ -829,7 +827,6 @@ static enum dc_status build_mapped_resource( struct dc_state *context, struct dc_stream_state *stream) { - enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); /*TODO Seems unneeded anymore */ @@ -853,11 +850,7 @@ static enum dc_status build_mapped_resource( if (!pipe_ctx) return DC_ERROR_UNEXPECTED; - status = build_pipe_hw_param(pipe_ctx); - - if (status != DC_OK) - return status; - + build_pipe_hw_param(pipe_ctx); return DC_OK; } -- GitLab From db6c3bdcfe2d810338f90a13d415d43dd98d342b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:41 +1000 Subject: [PATCH 0956/2898] amdgpu: fixup construct to void paths on some more dc objects. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 10 +++------- .../gpu/drm/amd/display/dc/core/dc_stream.c | 18 +++++------------- .../gpu/drm/amd/display/dc/core/dc_surface.c | 15 +++------------ 3 files changed, 11 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 226512c11ab7..315160d5f0f7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -245,7 +245,7 @@ void dal_ddc_aux_payloads_add( } } -static bool construct( +static void construct( struct ddc_service *ddc_service, struct ddc_service_init_data *init_data) { @@ -282,7 +282,6 @@ static bool construct( connector_id == CONNECTOR_ID_LVDS; ddc_service->wa.raw = 0; - return true; } struct ddc_service *dal_ddc_service_create( @@ -295,11 +294,8 @@ struct ddc_service *dal_ddc_service_create( if (!ddc_service) return NULL; - if (construct(ddc_service, init_data)) - return ddc_service; - - kfree(ddc_service); - return NULL; + construct(ddc_service, init_data); + return ddc_service; } static void destruct(struct ddc_service *ddc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index d5da847ffad6..a99196414255 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -56,7 +56,7 @@ static void update_stream_signal(struct dc_stream_state *stream) } } -static bool construct(struct dc_stream_state *stream, +static void construct(struct dc_stream_state *stream, struct dc_sink *dc_sink_data) { uint32_t i = 0; @@ -104,7 +104,6 @@ static bool construct(struct dc_stream_state *stream, stream->status.link = stream->sink->link; update_stream_signal(stream); - return true; } static void destruct(struct dc_stream_state *stream) @@ -142,25 +141,18 @@ struct dc_stream_state *dc_create_stream_for_sink( struct dc_stream_state *stream; if (sink == NULL) - goto alloc_fail; + return NULL; stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL); + if (stream == NULL) + return NULL; - if (NULL == stream) - goto alloc_fail; - - if (false == construct(stream, sink)) - goto construct_fail; + construct(stream, sink); atomic_inc(&stream->ref_count); return stream; -construct_fail: - kfree(stream); - -alloc_fail: - return NULL; } struct dc_stream_status *dc_stream_get_status( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 511ada94530e..f170ae95529c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -34,12 +34,11 @@ /******************************************************************************* * Private functions ******************************************************************************/ -static bool construct(struct dc_context *ctx, struct dc_plane_state *plane_state) +static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state) { plane_state->ctx = ctx; memset(&plane_state->hdr_static_ctx, 0, sizeof(struct dc_hdr_static_metadata)); - return true; } static void destruct(struct dc_plane_state *plane_state) @@ -72,20 +71,12 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) GFP_KERNEL); if (NULL == plane_state) - goto alloc_fail; - - if (false == construct(core_dc->ctx, plane_state)) - goto construct_fail; + return NULL; + construct(core_dc->ctx, plane_state); atomic_inc(&plane_state->ref_count); return plane_state; - -construct_fail: - kfree(plane_state); - -alloc_fail: - return NULL; } const struct dc_plane_status *dc_plane_get_status( -- GitLab From 6be663b5bdb7cc299b2aafca56be39f6618090ab Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 14:34:42 +1000 Subject: [PATCH 0957/2898] amdgpu/dc: fix construct return values on irq service. This just removes more unused return/errors paths. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/irq/dce110/irq_service_dce110.c | 14 ++++---------- .../amd/display/dc/irq/dce120/irq_service_dce120.c | 14 ++++---------- .../amd/display/dc/irq/dce80/irq_service_dce80.c | 14 ++++---------- .../amd/display/dc/irq/dcn10/irq_service_dcn10.c | 14 ++++---------- drivers/gpu/drm/amd/display/dc/irq/irq_service.c | 9 +++++---- drivers/gpu/drm/amd/display/dc/irq/irq_service.h | 2 +- 6 files changed, 22 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 5c558969f39f..f7e40b292dfb 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -406,17 +406,14 @@ static const struct irq_service_funcs irq_service_funcs_dce110 = { .to_dal_irq_source = to_dal_irq_source_dce110 }; -static bool construct( +static void construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!dal_irq_service_construct(irq_service, init_data)) - return false; + dal_irq_service_construct(irq_service, init_data); irq_service->info = irq_source_info_dce110; irq_service->funcs = &irq_service_funcs_dce110; - - return true; } struct irq_service *dal_irq_service_dce110_create( @@ -428,9 +425,6 @@ struct irq_service *dal_irq_service_dce110_create( if (!irq_service) return NULL; - if (construct(irq_service, init_data)) - return irq_service; - - kfree(irq_service); - return NULL; + construct(irq_service, init_data); + return irq_service; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c index 61d7c286802a..2ad56b1a4099 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c @@ -265,17 +265,14 @@ static const struct irq_service_funcs irq_service_funcs_dce120 = { .to_dal_irq_source = to_dal_irq_source_dce110 }; -static bool construct( +static void construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!dal_irq_service_construct(irq_service, init_data)) - return false; + dal_irq_service_construct(irq_service, init_data); irq_service->info = irq_source_info_dce120; irq_service->funcs = &irq_service_funcs_dce120; - - return true; } struct irq_service *dal_irq_service_dce120_create( @@ -287,9 +284,6 @@ struct irq_service *dal_irq_service_dce120_create( if (!irq_service) return NULL; - if (construct(irq_service, init_data)) - return irq_service; - - kfree(irq_service); - return NULL; + construct(irq_service, init_data); + return irq_service; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c index d6e1fb665d90..8a2066c313fe 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c @@ -277,17 +277,14 @@ static const struct irq_service_funcs irq_service_funcs_dce80 = { .to_dal_irq_source = to_dal_irq_source_dce110 }; -static bool construct( +static void construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!dal_irq_service_construct(irq_service, init_data)) - return false; + dal_irq_service_construct(irq_service, init_data); irq_service->info = irq_source_info_dce80; irq_service->funcs = &irq_service_funcs_dce80; - - return true; } struct irq_service *dal_irq_service_dce80_create( @@ -299,11 +296,8 @@ struct irq_service *dal_irq_service_dce80_create( if (!irq_service) return NULL; - if (construct(irq_service, init_data)) - return irq_service; - - kfree(irq_service); - return NULL; + construct(irq_service, init_data); + return irq_service; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c index f6e861162a6e..74ad24714f6b 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c @@ -332,17 +332,14 @@ static const struct irq_service_funcs irq_service_funcs_dcn10 = { .to_dal_irq_source = to_dal_irq_source_dcn10 }; -static bool construct( +static void construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!dal_irq_service_construct(irq_service, init_data)) - return false; + dal_irq_service_construct(irq_service, init_data); irq_service->info = irq_source_info_dcn10; irq_service->funcs = &irq_service_funcs_dcn10; - - return true; } struct irq_service *dal_irq_service_dcn10_create( @@ -354,9 +351,6 @@ struct irq_service *dal_irq_service_dcn10_create( if (!irq_service) return NULL; - if (construct(irq_service, init_data)) - return irq_service; - - kfree(irq_service); - return NULL; + construct(irq_service, init_data); + return irq_service; } diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index ce20622c7c89..b106513fc2dc 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -48,15 +48,16 @@ #define CTX \ irq_service->ctx -bool dal_irq_service_construct( +void dal_irq_service_construct( struct irq_service *irq_service, struct irq_service_init_data *init_data) { - if (!init_data || !init_data->ctx) - return false; + if (!init_data || !init_data->ctx) { + BREAK_TO_DEBUGGER(); + return; + } irq_service->ctx = init_data->ctx; - return true; } void dal_irq_service_destroy(struct irq_service **irq_service) diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h index a2a2d6965c2f..dbfcb096eedd 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h @@ -69,7 +69,7 @@ struct irq_service { const struct irq_service_funcs *funcs; }; -bool dal_irq_service_construct( +void dal_irq_service_construct( struct irq_service *irq_service, struct irq_service_init_data *init_data); -- GitLab From c4fee8796119ee6403317461b73d6afba85f8113 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 15:45:07 +1000 Subject: [PATCH 0958/2898] amdgpu/dc: inline some of the fixed 32_32 fns This drops ~400 bytes here. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/basics/fixpt32_32.c | 60 --------------- .../gpu/drm/amd/display/include/fixed32_32.h | 76 +++++++++++++++---- 2 files changed, 61 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c index 911e90bb1b5c..4d3aaa82a07b 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt32_32.c @@ -57,14 +57,6 @@ struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d) return fx; } -struct fixed32_32 dal_fixed32_32_from_int(uint32_t value) -{ - struct fixed32_32 fx; - - fx.value = (uint64_t)value<<32; - return fx; -} - struct fixed32_32 dal_fixed32_32_add( struct fixed32_32 lhs, struct fixed32_32 rhs) @@ -155,67 +147,15 @@ struct fixed32_32 dal_fixed32_32_div_int(struct fixed32_32 lhs, uint32_t rhs) return fx; } -struct fixed32_32 dal_fixed32_32_min( - struct fixed32_32 lhs, - struct fixed32_32 rhs) -{ - return (lhs.value < rhs.value) ? lhs : rhs; -} - -struct fixed32_32 dal_fixed32_32_max( - struct fixed32_32 lhs, - struct fixed32_32 rhs) -{ - return (lhs.value > rhs.value) ? lhs : rhs; -} - -bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs) -{ - return lhs.value > rhs.value; -} -bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs) -{ - return lhs.value > ((uint64_t)rhs<<32); -} - -bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs) -{ - return lhs.value < rhs.value; -} - -bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs) -{ - return lhs.value <= rhs.value; -} - -bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs) -{ - return lhs.value < ((uint64_t)rhs<<32); -} - -bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs) -{ - return lhs.value <= ((uint64_t)rhs<<32); -} - uint32_t dal_fixed32_32_ceil(struct fixed32_32 v) { ASSERT((uint32_t)v.value ? (v.value >> 32) + 1 >= 1 : true); return (v.value>>32) + ((uint32_t)v.value ? 1 : 0); } -uint32_t dal_fixed32_32_floor(struct fixed32_32 v) -{ - return v.value>>32; -} - uint32_t dal_fixed32_32_round(struct fixed32_32 v) { ASSERT(v.value + (1ULL<<31) >= (1ULL<<31)); return (v.value + (1ULL<<31))>>32; } -bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs) -{ - return lhs.value == rhs.value; -} diff --git a/drivers/gpu/drm/amd/display/include/fixed32_32.h b/drivers/gpu/drm/amd/display/include/fixed32_32.h index c7ddd0e435eb..9c70341fe026 100644 --- a/drivers/gpu/drm/amd/display/include/fixed32_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed32_32.h @@ -38,7 +38,14 @@ static const struct fixed32_32 dal_fixed32_32_one = { 0x100000000LL }; static const struct fixed32_32 dal_fixed32_32_half = { 0x80000000LL }; struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d); -struct fixed32_32 dal_fixed32_32_from_int(uint32_t value); +static inline struct fixed32_32 dal_fixed32_32_from_int(uint32_t value) +{ + struct fixed32_32 fx; + + fx.value = (uint64_t)value<<32; + return fx; +} + struct fixed32_32 dal_fixed32_32_add( struct fixed32_32 lhs, struct fixed32_32 rhs); @@ -63,21 +70,60 @@ struct fixed32_32 dal_fixed32_32_div( struct fixed32_32 dal_fixed32_32_div_int( struct fixed32_32 lhs, uint32_t rhs); -struct fixed32_32 dal_fixed32_32_min( - struct fixed32_32 lhs, - struct fixed32_32 rhs); -struct fixed32_32 dal_fixed32_32_max( - struct fixed32_32 lhs, - struct fixed32_32 rhs); -bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs); -bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs); -bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs); -bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs); -bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs); -bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs); -bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs); + +static inline struct fixed32_32 dal_fixed32_32_min(struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + return (lhs.value < rhs.value) ? lhs : rhs; +} + +static inline struct fixed32_32 dal_fixed32_32_max(struct fixed32_32 lhs, + struct fixed32_32 rhs) +{ + return (lhs.value > rhs.value) ? lhs : rhs; +} + +static inline bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value > rhs.value; +} + +static inline bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value > ((uint64_t)rhs<<32); +} + +static inline bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value < rhs.value; +} + +static inline bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value < ((uint64_t)rhs<<32); +} + +static inline bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value <= rhs.value; +} + +static inline bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs) +{ + return lhs.value <= ((uint64_t)rhs<<32); +} + +static inline bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs) +{ + return lhs.value == rhs.value; +} + uint32_t dal_fixed32_32_ceil(struct fixed32_32 value); -uint32_t dal_fixed32_32_floor(struct fixed32_32 value); +static inline uint32_t dal_fixed32_32_floor(struct fixed32_32 value) +{ + return value.value>>32; +} + uint32_t dal_fixed32_32_round(struct fixed32_32 value); #endif -- GitLab From 204de25fd0685237a6382626e5862328a16ce15b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 15:45:08 +1000 Subject: [PATCH 0959/2898] amdgpu/dc: inline a bunch of the fixed 31_32 helpers. This decreases code size by a few hundred bytes. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/basics/fixpt31_32.c | 122 ---------------- .../gpu/drm/amd/display/include/fixed31_32.h | 132 ++++++++++++------ 2 files changed, 93 insertions(+), 161 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 546ed67c6f83..578691cf8725 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -132,79 +132,6 @@ struct fixed31_32 dal_fixed31_32_from_int( return res; } -struct fixed31_32 dal_fixed31_32_neg( - struct fixed31_32 arg) -{ - struct fixed31_32 res; - - res.value = -arg.value; - - return res; -} - -struct fixed31_32 dal_fixed31_32_abs( - struct fixed31_32 arg) -{ - if (arg.value < 0) - return dal_fixed31_32_neg(arg); - else - return arg; -} - -bool dal_fixed31_32_lt( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - return arg1.value < arg2.value; -} - -bool dal_fixed31_32_le( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - return arg1.value <= arg2.value; -} - -bool dal_fixed31_32_eq( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - return arg1.value == arg2.value; -} - -struct fixed31_32 dal_fixed31_32_min( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - if (arg1.value <= arg2.value) - return arg1; - else - return arg2; -} - -struct fixed31_32 dal_fixed31_32_max( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - if (arg1.value <= arg2.value) - return arg2; - else - return arg1; -} - -struct fixed31_32 dal_fixed31_32_clamp( - struct fixed31_32 arg, - struct fixed31_32 min_value, - struct fixed31_32 max_value) -{ - if (dal_fixed31_32_le(arg, min_value)) - return min_value; - else if (dal_fixed31_32_le(max_value, arg)) - return max_value; - else - return arg; -} - struct fixed31_32 dal_fixed31_32_shl( struct fixed31_32 arg, uint8_t shift) @@ -219,19 +146,6 @@ struct fixed31_32 dal_fixed31_32_shl( return res; } -struct fixed31_32 dal_fixed31_32_shr( - struct fixed31_32 arg, - uint8_t shift) -{ - struct fixed31_32 res; - - ASSERT(shift < 64); - - res.value = arg.value >> shift; - - return res; -} - struct fixed31_32 dal_fixed31_32_add( struct fixed31_32 arg1, struct fixed31_32 arg2) @@ -246,24 +160,6 @@ struct fixed31_32 dal_fixed31_32_add( return res; } -struct fixed31_32 dal_fixed31_32_add_int( - struct fixed31_32 arg1, - int32_t arg2) -{ - return dal_fixed31_32_add( - arg1, - dal_fixed31_32_from_int(arg2)); -} - -struct fixed31_32 dal_fixed31_32_sub_int( - struct fixed31_32 arg1, - int32_t arg2) -{ - return dal_fixed31_32_sub( - arg1, - dal_fixed31_32_from_int(arg2)); -} - struct fixed31_32 dal_fixed31_32_sub( struct fixed31_32 arg1, struct fixed31_32 arg2) @@ -278,15 +174,6 @@ struct fixed31_32 dal_fixed31_32_sub( return res; } -struct fixed31_32 dal_fixed31_32_mul_int( - struct fixed31_32 arg1, - int32_t arg2) -{ - return dal_fixed31_32_mul( - arg1, - dal_fixed31_32_from_int(arg2)); -} - struct fixed31_32 dal_fixed31_32_mul( struct fixed31_32 arg1, struct fixed31_32 arg2) @@ -390,15 +277,6 @@ struct fixed31_32 dal_fixed31_32_div_int( dal_fixed31_32_from_int(arg2).value); } -struct fixed31_32 dal_fixed31_32_div( - struct fixed31_32 arg1, - struct fixed31_32 arg2) -{ - return dal_fixed31_32_from_fraction( - arg1.value, - arg2.value); -} - struct fixed31_32 dal_fixed31_32_recip( struct fixed31_32 arg) { diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 5a4364dfd2f7..f0bc3c4afe02 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -90,15 +90,26 @@ struct fixed31_32 dal_fixed31_32_from_int( * @brief * result = -arg */ -struct fixed31_32 dal_fixed31_32_neg( - struct fixed31_32 arg); +static inline struct fixed31_32 dal_fixed31_32_neg(struct fixed31_32 arg) +{ + struct fixed31_32 res; + + res.value = -arg.value; + + return res; +} /* * @brief * result = abs(arg) := (arg >= 0) ? arg : -arg */ -struct fixed31_32 dal_fixed31_32_abs( - struct fixed31_32 arg); +static inline struct fixed31_32 dal_fixed31_32_abs(struct fixed31_32 arg) +{ + if (arg.value < 0) + return dal_fixed31_32_neg(arg); + else + return arg; +} /* * @brief @@ -109,41 +120,57 @@ struct fixed31_32 dal_fixed31_32_abs( * @brief * result = arg1 < arg2 */ -bool dal_fixed31_32_lt( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline bool dal_fixed31_32_lt(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value < arg2.value; +} /* * @brief * result = arg1 <= arg2 */ -bool dal_fixed31_32_le( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline bool dal_fixed31_32_le(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value <= arg2.value; +} /* * @brief * result = arg1 == arg2 */ -bool dal_fixed31_32_eq( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline bool dal_fixed31_32_eq(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return arg1.value == arg2.value; +} /* * @brief * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2 */ -struct fixed31_32 dal_fixed31_32_min( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_min(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + if (arg1.value <= arg2.value) + return arg1; + else + return arg2; +} /* * @brief * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1 */ -struct fixed31_32 dal_fixed31_32_max( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_max(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + if (arg1.value <= arg2.value) + return arg2; + else + return arg1; +} /* * @brief @@ -151,10 +178,18 @@ struct fixed31_32 dal_fixed31_32_max( * result = | arg, when min_value < arg < max_value * | max_value, when arg >= max_value */ -struct fixed31_32 dal_fixed31_32_clamp( +static inline struct fixed31_32 dal_fixed31_32_clamp( struct fixed31_32 arg, struct fixed31_32 min_value, - struct fixed31_32 max_value); + struct fixed31_32 max_value) +{ + if (dal_fixed31_32_le(arg, min_value)) + return min_value; + else if (dal_fixed31_32_le(max_value, arg)) + return max_value; + else + return arg; +} /* * @brief @@ -173,9 +208,14 @@ struct fixed31_32 dal_fixed31_32_shl( * @brief * result = arg >> shift */ -struct fixed31_32 dal_fixed31_32_shr( +static inline struct fixed31_32 dal_fixed31_32_shr( struct fixed31_32 arg, - uint8_t shift); + uint8_t shift) +{ + struct fixed31_32 res; + res.value = arg.value >> shift; + return res; +} /* * @brief @@ -194,25 +234,32 @@ struct fixed31_32 dal_fixed31_32_add( * @brief * result = arg1 + arg2 */ -struct fixed31_32 dal_fixed31_32_add_int( - struct fixed31_32 arg1, - int32_t arg2); +static inline struct fixed31_32 dal_fixed31_32_add_int(struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_add(arg1, + dal_fixed31_32_from_int(arg2)); +} /* * @brief * result = arg1 - arg2 */ -struct fixed31_32 dal_fixed31_32_sub_int( +struct fixed31_32 dal_fixed31_32_sub( struct fixed31_32 arg1, - int32_t arg2); + struct fixed31_32 arg2); /* * @brief * result = arg1 - arg2 */ -struct fixed31_32 dal_fixed31_32_sub( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_sub_int(struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_sub(arg1, + dal_fixed31_32_from_int(arg2)); +} + /* * @brief @@ -223,17 +270,21 @@ struct fixed31_32 dal_fixed31_32_sub( * @brief * result = arg1 * arg2 */ -struct fixed31_32 dal_fixed31_32_mul_int( +struct fixed31_32 dal_fixed31_32_mul( struct fixed31_32 arg1, - int32_t arg2); + struct fixed31_32 arg2); + /* * @brief * result = arg1 * arg2 */ -struct fixed31_32 dal_fixed31_32_mul( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_mul_int(struct fixed31_32 arg1, + int32_t arg2) +{ + return dal_fixed31_32_mul(arg1, + dal_fixed31_32_from_int(arg2)); +} /* * @brief @@ -254,9 +305,12 @@ struct fixed31_32 dal_fixed31_32_div_int( * @brief * result = arg1 / arg2 */ -struct fixed31_32 dal_fixed31_32_div( - struct fixed31_32 arg1, - struct fixed31_32 arg2); +static inline struct fixed31_32 dal_fixed31_32_div(struct fixed31_32 arg1, + struct fixed31_32 arg2) +{ + return dal_fixed31_32_from_fraction(arg1.value, + arg2.value); +} /* * @brief -- GitLab From 736b4f153b62247d0f2e2bd1e9b04b7489edb596 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:22 +1000 Subject: [PATCH 0960/2898] amdgpu/dc: hide some unused aux/i2c payload apis. I've no idea if these are used on other platforms, but they aren't used outside this file here, so make them static. Drops 300 bytes. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 16 ++++++++-------- drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h | 10 ---------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 315160d5f0f7..d5294798b0a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -126,7 +126,7 @@ struct aux_payloads { struct vector payloads; }; -struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) +static struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) { struct i2c_payloads *payloads; @@ -144,17 +144,17 @@ struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_ } -struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) +static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) { return (struct i2c_payload *)p->payloads.container; } -uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) +static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) { return p->payloads.count; } -void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) +static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) { if (!p || !*p) return; @@ -164,7 +164,7 @@ void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) } -struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) +static struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) { struct aux_payloads *payloads; @@ -181,17 +181,17 @@ struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_ return NULL; } -struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) +static struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) { return (struct aux_payload *)p->payloads.container; } -uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) +static uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) { return p->payloads.count; } -void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) +static void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) { if (!p || !*p) return; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h index af7ea5eaf185..0bf73b742f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h @@ -57,16 +57,6 @@ struct dp_receiver_id_info; struct i2c_payloads; struct aux_payloads; -struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count); -struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p); -uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p); -void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p); - -struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count); -struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p); -uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p); -void dal_ddc_aux_payloads_destroy(struct aux_payloads **p); - void dal_ddc_i2c_payloads_add( struct i2c_payloads *payloads, uint32_t address, -- GitLab From 450619d328d0824fab649187019cbea3532f879c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:23 +1000 Subject: [PATCH 0961/2898] amdgpu/dc: move some one line dp functions to inlines. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 38ccc011004d..305ca0decfaa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1191,12 +1191,12 @@ struct dc_link_settings get_common_supported_link_settings ( return link_settings; } -bool reached_minimum_lane_count(enum dc_lane_count lane_count) +static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count) { return lane_count <= LANE_COUNT_ONE; } -bool reached_minimum_link_rate(enum dc_link_rate link_rate) +static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate) { return link_rate <= LINK_RATE_LOW; } -- GitLab From 1fcd8c53b0c45c405433b5d78a5e2b2d858bd3af Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:24 +1000 Subject: [PATCH 0962/2898] amdgpu/dc: inline some of the bw_fixed code. This results in a ~4.5k code size reduction. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/bw_fixed.c | 93 --------------- drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h | 111 +++++++++++++++--- 2 files changed, 96 insertions(+), 108 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c index fbf2adcc5ff8..0de6fa1bb07d 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c @@ -56,16 +56,6 @@ static uint64_t abs_i64(int64_t arg) return (uint64_t)(-arg); } -struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) -{ - return bw_min2(bw_min2(v1, v2), v3); -} - -struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3) -{ - return bw_max2(bw_max2(v1, v2), v3); -} - struct bw_fixed bw_int_to_fixed(int64_t value) { struct bw_fixed res; @@ -133,16 +123,6 @@ struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) return res; } -struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return (arg1.value <= arg2.value) ? arg1 : arg2; -} - -struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return (arg2.value <= arg1.value) ? arg1 : arg2; -} - struct bw_fixed bw_floor2( const struct bw_fixed arg, const struct bw_fixed significance) @@ -174,24 +154,6 @@ struct bw_fixed bw_ceil2( return result; } -struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - struct bw_fixed res; - - res.value = arg1.value + arg2.value; - - return res; -} - -struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - struct bw_fixed res; - - res.value = arg1.value - arg2.value; - - return res; -} - struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) { struct bw_fixed res; @@ -242,58 +204,3 @@ struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) return res; } -struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - struct bw_fixed res = bw_frc_to_fixed(arg1.value, arg2.value); - return res; -} - -struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - struct bw_fixed res; - div64_u64_rem(arg1.value, arg2.value, &res.value); - return res; -} -struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw) -{ - struct bw_fixed result = { 0 }; - - if (raw < 0) { - raw = -raw; - result.value = -(raw >> (32 - BITS_PER_FRACTIONAL_PART)); - } else { - result.value = raw >> (32 - BITS_PER_FRACTIONAL_PART); - } - - return result; -} - -bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value == arg2.value; -} - -bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value != arg2.value; -} - -bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value <= arg2.value; -} - -bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value >= arg2.value; -} - -bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value < arg2.value; -} - -bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2) -{ - return arg1.value > arg2.value; -} diff --git a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h index b31d07a57c31..4477e6208998 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h @@ -30,9 +30,31 @@ struct bw_fixed { int64_t value; }; -struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3); +static inline struct bw_fixed bw_min2(const struct bw_fixed arg1, + const struct bw_fixed arg2) +{ + return (arg1.value <= arg2.value) ? arg1 : arg2; +} -struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3); +static inline struct bw_fixed bw_max2(const struct bw_fixed arg1, + const struct bw_fixed arg2) +{ + return (arg2.value <= arg1.value) ? arg1 : arg2; +} + +static inline struct bw_fixed bw_min3(struct bw_fixed v1, + struct bw_fixed v2, + struct bw_fixed v3) +{ + return bw_min2(bw_min2(v1, v2), v3); +} + +static inline struct bw_fixed bw_max3(struct bw_fixed v1, + struct bw_fixed v2, + struct bw_fixed v3) +{ + return bw_max2(bw_max2(v1, v2), v3); +} struct bw_fixed bw_int_to_fixed(int64_t value); @@ -40,24 +62,83 @@ int32_t bw_fixed_to_int(struct bw_fixed value); struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum); -struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw); +static inline struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw) +{ + struct bw_fixed result = { 0 }; + + if (raw < 0) { + raw = -raw; + result.value = -(raw >> (32 - BW_FIXED_BITS_PER_FRACTIONAL_PART)); + } else { + result.value = raw >> (32 - BW_FIXED_BITS_PER_FRACTIONAL_PART); + } + + return result; +} + +static inline struct bw_fixed bw_add(const struct bw_fixed arg1, + const struct bw_fixed arg2) +{ + struct bw_fixed res; + + res.value = arg1.value + arg2.value; + + return res; +} + +static inline struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + + res.value = arg1.value - arg2.value; + + return res; +} -struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2); -struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2); struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2); -struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2); -struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2); +static inline struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return bw_frc_to_fixed(arg1.value, arg2.value); +} + +static inline struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + struct bw_fixed res; + div64_u64_rem(arg1.value, arg2.value, &res.value); + return res; +} -struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2); -struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2); struct bw_fixed bw_floor2(const struct bw_fixed arg, const struct bw_fixed significance); struct bw_fixed bw_ceil2(const struct bw_fixed arg, const struct bw_fixed significance); -bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2); -bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2); +static inline bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value == arg2.value; +} + +static inline bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value != arg2.value; +} + +static inline bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value <= arg2.value; +} + +static inline bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value >= arg2.value; +} + +static inline bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value < arg2.value; +} + +static inline bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2) +{ + return arg1.value > arg2.value; +} #endif //BW_FIXED_H_ -- GitLab From dfd1e5ce673b8b2557d622dc99735e2d7ad5ba5b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:25 +1000 Subject: [PATCH 0963/2898] amdgpu/dc: allow inlining constant int to fixed a lot better. This uses two things that might be Linux specific, __builtin_constant_p (might be gcc) and BUILD_BUG_ON. (maybe other dm's can have something similiar). This saves 4k in the bw calcs code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/bw_fixed.c | 37 ++++++------------- drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h | 26 ++++++++++++- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c index 0de6fa1bb07d..6ca288fb5fb9 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c @@ -25,13 +25,6 @@ #include "dm_services.h" #include "bw_fixed.h" -#define BITS_PER_FRACTIONAL_PART 24 - -#define MIN_I32 \ - (int64_t)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART))) - -#define MAX_I32 \ - (int64_t)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1) #define MIN_I64 \ (int64_t)(-(1LL << 63)) @@ -40,10 +33,7 @@ (int64_t)((1ULL << 63) - 1) #define FRACTIONAL_PART_MASK \ - ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) - -#define GET_INTEGER_PART(x) \ - ((x) >> BITS_PER_FRACTIONAL_PART) + ((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1) #define GET_FRACTIONAL_PART(x) \ (FRACTIONAL_PART_MASK & (x)) @@ -56,19 +46,14 @@ static uint64_t abs_i64(int64_t arg) return (uint64_t)(-arg); } -struct bw_fixed bw_int_to_fixed(int64_t value) +struct bw_fixed bw_int_to_fixed_nonconst(int64_t value) { struct bw_fixed res; - ASSERT(value < MAX_I32 && value > MIN_I32); - res.value = value << BITS_PER_FRACTIONAL_PART; + ASSERT(value < BW_FIXED_MAX_I32 && value > BW_FIXED_MIN_I32); + res.value = value << BW_FIXED_BITS_PER_FRACTIONAL_PART; return res; } -int32_t bw_fixed_to_int(struct bw_fixed value) -{ - return GET_INTEGER_PART(value.value); -} - struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) { struct bw_fixed res; @@ -87,11 +72,11 @@ struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator) arg2_value = abs_i64(denominator); res_value = div64_u64_rem(arg1_value, arg2_value, &remainder); - ASSERT(res_value <= MAX_I32); + ASSERT(res_value <= BW_FIXED_MAX_I32); /* determine fractional part */ { - uint32_t i = BITS_PER_FRACTIONAL_PART; + uint32_t i = BW_FIXED_BITS_PER_FRACTIONAL_PART; do { @@ -164,8 +149,8 @@ struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) uint64_t arg1_value = abs_i64(arg1.value); uint64_t arg2_value = abs_i64(arg2.value); - uint64_t arg1_int = GET_INTEGER_PART(arg1_value); - uint64_t arg2_int = GET_INTEGER_PART(arg2_value); + uint64_t arg1_int = BW_FIXED_GET_INTEGER_PART(arg1_value); + uint64_t arg2_int = BW_FIXED_GET_INTEGER_PART(arg2_value); uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value); uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value); @@ -174,9 +159,9 @@ struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) res.value = arg1_int * arg2_int; - ASSERT(res.value <= MAX_I32); + ASSERT(res.value <= BW_FIXED_MAX_I32); - res.value <<= BITS_PER_FRACTIONAL_PART; + res.value <<= BW_FIXED_BITS_PER_FRACTIONAL_PART; tmp = arg1_int * arg2_fra; @@ -192,7 +177,7 @@ struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2) tmp = arg1_fra * arg2_fra; - tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + tmp = (tmp >> BW_FIXED_BITS_PER_FRACTIONAL_PART) + (tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value)); ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value)); diff --git a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h index 4477e6208998..39ee8eba3c31 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h +++ b/drivers/gpu/drm/amd/display/dc/inc/bw_fixed.h @@ -26,10 +26,19 @@ #ifndef BW_FIXED_H_ #define BW_FIXED_H_ +#define BW_FIXED_BITS_PER_FRACTIONAL_PART 24 + +#define BW_FIXED_GET_INTEGER_PART(x) ((x) >> BW_FIXED_BITS_PER_FRACTIONAL_PART) struct bw_fixed { int64_t value; }; +#define BW_FIXED_MIN_I32 \ + (int64_t)(-(1LL << (63 - BW_FIXED_BITS_PER_FRACTIONAL_PART))) + +#define BW_FIXED_MAX_I32 \ + (int64_t)((1ULL << (63 - BW_FIXED_BITS_PER_FRACTIONAL_PART)) - 1) + static inline struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2) { @@ -56,9 +65,22 @@ static inline struct bw_fixed bw_max3(struct bw_fixed v1, return bw_max2(bw_max2(v1, v2), v3); } -struct bw_fixed bw_int_to_fixed(int64_t value); +struct bw_fixed bw_int_to_fixed_nonconst(int64_t value); +static inline struct bw_fixed bw_int_to_fixed(int64_t value) +{ + if (__builtin_constant_p(value)) { + struct bw_fixed res; + BUILD_BUG_ON(value > BW_FIXED_MAX_I32 || value < BW_FIXED_MIN_I32); + res.value = value << BW_FIXED_BITS_PER_FRACTIONAL_PART; + return res; + } else + return bw_int_to_fixed_nonconst(value); +} -int32_t bw_fixed_to_int(struct bw_fixed value); +static inline int32_t bw_fixed_to_int(struct bw_fixed value) +{ + return BW_FIXED_GET_INTEGER_PART(value.value); +} struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum); -- GitLab From c233e91b0f3f7c9abc80eae491fa6507a24a8a32 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:26 +1000 Subject: [PATCH 0964/2898] amdgpu/dc: use the builtin constant p trick on the 31/32 fixed point. This only gets us 100 bytes, but may as well be consistent. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/basics/fixpt31_32.c | 22 +++++++++---------- .../gpu/drm/amd/display/include/fixed31_32.h | 15 +++++++++++-- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 578691cf8725..1764a33c8350 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -54,14 +54,12 @@ static inline uint64_t complete_integer_division_u64( return result; } -#define BITS_PER_FRACTIONAL_PART \ - 32 #define FRACTIONAL_PART_MASK \ - ((1ULL << BITS_PER_FRACTIONAL_PART) - 1) + ((1ULL << FIXED31_32_BITS_PER_FRACTIONAL_PART) - 1) #define GET_INTEGER_PART(x) \ - ((x) >> BITS_PER_FRACTIONAL_PART) + ((x) >> FIXED31_32_BITS_PER_FRACTIONAL_PART) #define GET_FRACTIONAL_PART(x) \ (FRACTIONAL_PART_MASK & (x)) @@ -89,7 +87,7 @@ struct fixed31_32 dal_fixed31_32_from_fraction( /* determine fractional part */ { - uint32_t i = BITS_PER_FRACTIONAL_PART; + uint32_t i = FIXED31_32_BITS_PER_FRACTIONAL_PART; do { remainder <<= 1; @@ -120,14 +118,14 @@ struct fixed31_32 dal_fixed31_32_from_fraction( return res; } -struct fixed31_32 dal_fixed31_32_from_int( +struct fixed31_32 dal_fixed31_32_from_int_nonconst( int64_t arg) { struct fixed31_32 res; ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX)); - res.value = arg << BITS_PER_FRACTIONAL_PART; + res.value = arg << FIXED31_32_BITS_PER_FRACTIONAL_PART; return res; } @@ -198,7 +196,7 @@ struct fixed31_32 dal_fixed31_32_mul( ASSERT(res.value <= LONG_MAX); - res.value <<= BITS_PER_FRACTIONAL_PART; + res.value <<= FIXED31_32_BITS_PER_FRACTIONAL_PART; tmp = arg1_int * arg2_fra; @@ -214,7 +212,7 @@ struct fixed31_32 dal_fixed31_32_mul( tmp = arg1_fra * arg2_fra; - tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + tmp = (tmp >> FIXED31_32_BITS_PER_FRACTIONAL_PART) + (tmp >= (uint64_t)dal_fixed31_32_half.value); ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); @@ -244,7 +242,7 @@ struct fixed31_32 dal_fixed31_32_sqr( ASSERT(res.value <= LONG_MAX); - res.value <<= BITS_PER_FRACTIONAL_PART; + res.value <<= FIXED31_32_BITS_PER_FRACTIONAL_PART; tmp = arg_int * arg_fra; @@ -258,7 +256,7 @@ struct fixed31_32 dal_fixed31_32_sqr( tmp = arg_fra * arg_fra; - tmp = (tmp >> BITS_PER_FRACTIONAL_PART) + + tmp = (tmp >> FIXED31_32_BITS_PER_FRACTIONAL_PART) + (tmp >= (uint64_t)dal_fixed31_32_half.value); ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value)); @@ -560,7 +558,7 @@ static inline uint32_t ux_dy( /* 4. make space for fractional part to be filled in after integer */ result <<= fractional_bits; /* 5. shrink fixed point fractional part to of fractional_bits width*/ - fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits; + fractional_part >>= FIXED31_32_BITS_PER_FRACTIONAL_PART - fractional_bits; /* 6. merge the result */ return result | fractional_part; } diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index f0bc3c4afe02..2c9e2231ef06 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -28,6 +28,8 @@ #include "os_types.h" +#define FIXED31_32_BITS_PER_FRACTIONAL_PART 32 + /* * @brief * Arithmetic operations on real numbers @@ -78,8 +80,17 @@ struct fixed31_32 dal_fixed31_32_from_fraction( * @brief * result = arg */ -struct fixed31_32 dal_fixed31_32_from_int( - int64_t arg); +struct fixed31_32 dal_fixed31_32_from_int_nonconst(int64_t arg); +static inline struct fixed31_32 dal_fixed31_32_from_int(int64_t arg) +{ + if (__builtin_constant_p(arg)) { + struct fixed31_32 res; + BUILD_BUG_ON((LONG_MIN > arg) || (arg > LONG_MAX)); + res.value = arg << FIXED31_32_BITS_PER_FRACTIONAL_PART; + return res; + } else + return dal_fixed31_32_from_int_nonconst(arg); +} /* * @brief -- GitLab From bd6d15769e6dcd22c57224b67376e1c6fb44b04f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:27 +1000 Subject: [PATCH 0965/2898] amdgpu/dc: inline fixed31_32 div_int Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c | 9 --------- drivers/gpu/drm/amd/display/include/fixed31_32.h | 9 ++++++--- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c index 1764a33c8350..26936892c6f5 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c +++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c @@ -266,15 +266,6 @@ struct fixed31_32 dal_fixed31_32_sqr( return res; } -struct fixed31_32 dal_fixed31_32_div_int( - struct fixed31_32 arg1, - int64_t arg2) -{ - return dal_fixed31_32_from_fraction( - arg1.value, - dal_fixed31_32_from_int(arg2).value); -} - struct fixed31_32 dal_fixed31_32_recip( struct fixed31_32 arg) { diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 2c9e2231ef06..3248f699daf2 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -308,9 +308,12 @@ struct fixed31_32 dal_fixed31_32_sqr( * @brief * result = arg1 / arg2 */ -struct fixed31_32 dal_fixed31_32_div_int( - struct fixed31_32 arg1, - int64_t arg2); +static inline struct fixed31_32 dal_fixed31_32_div_int(struct fixed31_32 arg1, + int64_t arg2) +{ + return dal_fixed31_32_from_fraction(arg1.value, + dal_fixed31_32_from_int(arg2).value); +} /* * @brief -- GitLab From 69e3fdaabe185ecbf7413eb53cd43ca407d6fbba Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:28 +1000 Subject: [PATCH 0966/2898] amdgpu/dc: inline all the signal_types code. This is worth 300 bytes, and one less source file. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/basics/Makefile | 2 +- .../drm/amd/display/dc/basics/signal_types.c | 80 ------------------- .../drm/amd/display/include/signal_types.h | 59 ++++++++++++-- 3 files changed, 52 insertions(+), 89 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/basics/signal_types.c diff --git a/drivers/gpu/drm/amd/display/dc/basics/Makefile b/drivers/gpu/drm/amd/display/dc/basics/Makefile index 065816209da1..43c5ccdeeb72 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/Makefile +++ b/drivers/gpu/drm/amd/display/dc/basics/Makefile @@ -4,7 +4,7 @@ # subcomponents. BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \ - logger.o log_helpers.o signal_types.o vector.o + logger.o log_helpers.o vector.o AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS)) diff --git a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c b/drivers/gpu/drm/amd/display/dc/basics/signal_types.c deleted file mode 100644 index 534c803e7091..000000000000 --- a/drivers/gpu/drm/amd/display/dc/basics/signal_types.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "dm_services.h" -#include "include/signal_types.h" - -bool dc_is_hdmi_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_HDMI_TYPE_A); -} - -bool dc_is_dp_sst_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_EDP); -} - -bool dc_is_dp_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_EDP || - signal == SIGNAL_TYPE_DISPLAY_PORT_MST); -} - -bool dc_is_embedded_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); -} - -bool dc_is_dvi_signal(enum signal_type signal) -{ - switch (signal) { - case SIGNAL_TYPE_DVI_SINGLE_LINK: - case SIGNAL_TYPE_DVI_DUAL_LINK: - return true; - break; - default: - return false; - } -} - -bool dc_is_dvi_single_link_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); -} - -bool dc_is_dual_link_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DVI_DUAL_LINK); -} - -bool dc_is_audio_capable_signal(enum signal_type signal) -{ - return (signal == SIGNAL_TYPE_DISPLAY_PORT || - signal == SIGNAL_TYPE_DISPLAY_PORT_MST || - dc_is_hdmi_signal(signal)); -} - diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index 1a2ca53c68cd..b5ebde642207 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -40,13 +40,56 @@ enum signal_type { }; /* help functions for signal types manipulation */ -bool dc_is_hdmi_signal(enum signal_type signal); -bool dc_is_dp_sst_signal(enum signal_type signal); -bool dc_is_dp_signal(enum signal_type signal); -bool dc_is_embedded_signal(enum signal_type signal); -bool dc_is_dvi_signal(enum signal_type signal); -bool dc_is_dvi_single_link_signal(enum signal_type signal); -bool dc_is_dual_link_signal(enum signal_type signal); -bool dc_is_audio_capable_signal(enum signal_type signal); +static inline bool dc_is_hdmi_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_HDMI_TYPE_A); +} + +static inline bool dc_is_dp_sst_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP); +} + +static inline bool dc_is_dp_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_EDP || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST); +} + +static inline bool dc_is_embedded_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS); +} + +static inline bool dc_is_dvi_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + return true; + break; + default: + return false; + } +} + +static inline bool dc_is_dvi_single_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); +} + +static inline bool dc_is_dual_link_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DVI_DUAL_LINK); +} + +static inline bool dc_is_audio_capable_signal(enum signal_type signal) +{ + return (signal == SIGNAL_TYPE_DISPLAY_PORT || + signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + dc_is_hdmi_signal(signal)); +} #endif -- GitLab From 04e212926f0d1213bc1ff1f8ab4050878699977d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:29 +1000 Subject: [PATCH 0967/2898] amdgpu/dc: set some of the link dp code to static. These aren't currently used outside this file. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 18 +++++++++++++----- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 8 -------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 305ca0decfaa..888d268e9622 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -32,6 +32,14 @@ enum { LINK_TRAINING_MAX_CR_RETRY = 100 }; +static bool decide_fallback_link_setting( + struct dc_link_settings initial_link_settings, + struct dc_link_settings *current_link_setting, + enum link_training_result training_result); +static struct dc_link_settings get_common_supported_link_settings ( + struct dc_link_settings link_setting_a, + struct dc_link_settings link_setting_b); + static void wait_for_training_aux_rd_interval( struct dc_link *link, uint32_t default_wait_in_micro_secs) @@ -1150,7 +1158,7 @@ bool dp_hbr_verify_link_cap( return success; } -struct dc_link_settings get_common_supported_link_settings ( +static struct dc_link_settings get_common_supported_link_settings ( struct dc_link_settings link_setting_a, struct dc_link_settings link_setting_b) { @@ -1215,7 +1223,7 @@ enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) } } -enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) +static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) { switch (link_rate) { case LINK_RATE_HIGH3: @@ -1231,7 +1239,7 @@ enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) } } -enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) +static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) { switch (lane_count) { case LANE_COUNT_ONE: @@ -1243,7 +1251,7 @@ enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) } } -enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) +static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) { switch (link_rate) { case LINK_RATE_LOW: @@ -1265,7 +1273,7 @@ enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) * false - has reached minimum setting * and no further fallback could be done */ -bool decide_fallback_link_setting( +static bool decide_fallback_link_setting( struct dc_link_settings initial_link_settings, struct dc_link_settings *current_link_setting, enum link_training_result training_result) diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 7168dcc70ae7..616c73e2b0bd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -37,14 +37,6 @@ bool dp_hbr_verify_link_cap( struct dc_link *link, struct dc_link_settings *known_limit_link_setting); -bool decide_fallback_link_setting(struct dc_link_settings link_setting_init, - struct dc_link_settings *link_setting_current, - enum link_training_result training_result); - -struct dc_link_settings get_common_supported_link_settings ( - struct dc_link_settings link_setting_a, - struct dc_link_settings link_setting_b); - bool dp_validate_mode_timing( struct dc_link *link, const struct dc_crtc_timing *timing); -- GitLab From 2a206cc20a37b0a7a31179b32d1281ead9c56038 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:30 +1000 Subject: [PATCH 0968/2898] amdgpu/dc: rename bios get_image symbol to something more searchable. This just makes it easier to find. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 6 +++--- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 2 +- drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c | 2 +- drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index f6828f43eac6..2e003b5c8d08 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -412,7 +412,7 @@ static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, if (!DATA_TABLES(VoltageObjectInfo)) return result; - voltage_info_address = get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER)); + voltage_info_address = bios_get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER)); header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address; @@ -2328,7 +2328,7 @@ static uint32_t get_dest_obj_list(struct bios_parser *bp, return 0; offset += sizeof(uint8_t); - *id_list = (uint16_t *)get_image(&bp->base, offset, *number * sizeof(uint16_t)); + *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); if (!*id_list) return 0; @@ -2355,7 +2355,7 @@ static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, return 0; offset += sizeof(uint8_t); - *id_list = (uint16_t *)get_image(&bp->base, offset, *number * sizeof(uint16_t)); + *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); if (!*id_list) return 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 852bb0d2eb8d..0c623b314577 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -535,7 +535,7 @@ static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, if (!DATA_TABLES(voltageobject_info)) return result; - voltage_info_address = get_image(&bp->base, + voltage_info_address = bios_get_image(&bp->base, DATA_TABLES(voltageobject_info), sizeof(struct atom_common_table_header)); diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c index 8e56d2f25dea..5c9e5108c32c 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c @@ -33,7 +33,7 @@ #include "command_table.h" #include "bios_parser_types_internal.h" -uint8_t *get_image(struct dc_bios *bp, +uint8_t *bios_get_image(struct dc_bios *bp, uint32_t offset, uint32_t size) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h index a8fbb82b8c8e..c0047efeb006 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h @@ -28,13 +28,13 @@ struct bios_parser; -uint8_t *get_image(struct dc_bios *bp, uint32_t offset, +uint8_t *bios_get_image(struct dc_bios *bp, uint32_t offset, uint32_t size); bool bios_is_accelerated_mode(struct dc_bios *bios); void bios_set_scratch_acc_mode_change(struct dc_bios *bios); void bios_set_scratch_critical_state(struct dc_bios *bios, bool state); -#define GET_IMAGE(type, offset) ((type *) get_image(&bp->base, offset, sizeof(type))) +#define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type))) #endif -- GitLab From d8c893b44b2199f5935fe8667708253c38353782 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:31 +1000 Subject: [PATCH 0969/2898] amdgpu/dc: inline dml_round_to_multiple turns out to be a win to inline this. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/dml_common_defs.c | 19 ------------------- .../drm/amd/display/dc/dml/dml_common_defs.h | 2 -- .../drm/amd/display/dc/dml/dml_inline_defs.h | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 7c0eb52b91b8..df2d5099b90e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -39,23 +39,4 @@ double dml_round(double a) return floor; } -unsigned int dml_round_to_multiple( - unsigned int num, - unsigned int multiple, - bool up) -{ - unsigned int remainder; - - if (multiple == 0) - return num; - - remainder = num % multiple; - if (remainder == 0) - return num; - - if (up) - return (num + multiple - remainder); - else - return (num - remainder); -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index a2da3da5ef8f..81c53d879a16 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -33,7 +33,5 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); double dml_round(double a); -unsigned int dml_round_to_multiple( - unsigned int num, unsigned int multiple, bool up); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h index 1c6c631daad4..a91b4a6c6154 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -58,4 +58,23 @@ static inline double dml_log(double x, double base) return (double) dcn_bw_log(x, base); } +static inline unsigned int dml_round_to_multiple(unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} #endif -- GitLab From 2ff7cfe9985617d34c2166b529e7e54beac11175 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 29 Sep 2017 13:42:35 -0400 Subject: [PATCH 0970/2898] r128: switch compat ioctls to drm_ioctl_kernel() Signed-off-by: Al Viro --- drivers/gpu/drm/r128/r128_drv.h | 4 ++ drivers/gpu/drm/r128/r128_ioc32.c | 99 +++++++++++++------------------ drivers/gpu/drm/r128/r128_state.c | 6 +- 3 files changed, 48 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h index 09143b840482..2de40d276116 100644 --- a/drivers/gpu/drm/r128/r128_drv.h +++ b/drivers/gpu/drm/r128/r128_drv.h @@ -147,6 +147,10 @@ extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv); + extern void r128_freelist_reset(struct drm_device *dev); extern int r128_wait_ring(drm_r128_private_t *dev_priv, int n); diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c index 663f38c63ba6..6589f9e0310e 100644 --- a/drivers/gpu/drm/r128/r128_ioc32.c +++ b/drivers/gpu/drm/r128/r128_ioc32.c @@ -63,39 +63,36 @@ static int compat_r128_init(struct file *file, unsigned int cmd, unsigned long arg) { drm_r128_init32_t init32; - drm_r128_init_t __user *init; + drm_r128_init_t init; if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) return -EFAULT; - init = compat_alloc_user_space(sizeof(*init)); - if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) - || __put_user(init32.func, &init->func) - || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) - || __put_user(init32.is_pci, &init->is_pci) - || __put_user(init32.cce_mode, &init->cce_mode) - || __put_user(init32.cce_secure, &init->cce_secure) - || __put_user(init32.ring_size, &init->ring_size) - || __put_user(init32.usec_timeout, &init->usec_timeout) - || __put_user(init32.fb_bpp, &init->fb_bpp) - || __put_user(init32.front_offset, &init->front_offset) - || __put_user(init32.front_pitch, &init->front_pitch) - || __put_user(init32.back_offset, &init->back_offset) - || __put_user(init32.back_pitch, &init->back_pitch) - || __put_user(init32.depth_bpp, &init->depth_bpp) - || __put_user(init32.depth_offset, &init->depth_offset) - || __put_user(init32.depth_pitch, &init->depth_pitch) - || __put_user(init32.span_offset, &init->span_offset) - || __put_user(init32.fb_offset, &init->fb_offset) - || __put_user(init32.mmio_offset, &init->mmio_offset) - || __put_user(init32.ring_offset, &init->ring_offset) - || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset) - || __put_user(init32.buffers_offset, &init->buffers_offset) - || __put_user(init32.agp_textures_offset, - &init->agp_textures_offset)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_R128_INIT, (unsigned long)init); + init.func = init32.func; + init.sarea_priv_offset = init32.sarea_priv_offset; + init.is_pci = init32.is_pci; + init.cce_mode = init32.cce_mode; + init.cce_secure = init32.cce_secure; + init.ring_size = init32.ring_size; + init.usec_timeout = init32.usec_timeout; + init.fb_bpp = init32.fb_bpp; + init.front_offset = init32.front_offset; + init.front_pitch = init32.front_pitch; + init.back_offset = init32.back_offset; + init.back_pitch = init32.back_pitch; + init.depth_bpp = init32.depth_bpp; + init.depth_offset = init32.depth_offset; + init.depth_pitch = init32.depth_pitch; + init.span_offset = init32.span_offset; + init.fb_offset = init32.fb_offset; + init.mmio_offset = init32.mmio_offset; + init.ring_offset = init32.ring_offset; + init.ring_rptr_offset = init32.ring_rptr_offset; + init.buffers_offset = init32.buffers_offset; + init.agp_textures_offset = init32.agp_textures_offset; + + return drm_ioctl_kernel(file, r128_cce_init, &init, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } typedef struct drm_r128_depth32 { @@ -111,25 +108,19 @@ static int compat_r128_depth(struct file *file, unsigned int cmd, unsigned long arg) { drm_r128_depth32_t depth32; - drm_r128_depth_t __user *depth; + drm_r128_depth_t depth; if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32))) return -EFAULT; - depth = compat_alloc_user_space(sizeof(*depth)); - if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth)) - || __put_user(depth32.func, &depth->func) - || __put_user(depth32.n, &depth->n) - || __put_user((int __user *)(unsigned long)depth32.x, &depth->x) - || __put_user((int __user *)(unsigned long)depth32.y, &depth->y) - || __put_user((unsigned int __user *)(unsigned long)depth32.buffer, - &depth->buffer) - || __put_user((unsigned char __user *)(unsigned long)depth32.mask, - &depth->mask)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth); + depth.func = depth32.func; + depth.n = depth32.n; + depth.x = compat_ptr(depth32.x); + depth.y = compat_ptr(depth32.y); + depth.buffer = compat_ptr(depth32.buffer); + depth.mask = compat_ptr(depth32.mask); + return drm_ioctl_kernel(file, r128_cce_depth, &depth, DRM_AUTH); } typedef struct drm_r128_stipple32 { @@ -140,18 +131,14 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd, unsigned long arg) { drm_r128_stipple32_t stipple32; - drm_r128_stipple_t __user *stipple; + drm_r128_stipple_t stipple; if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32))) return -EFAULT; - stipple = compat_alloc_user_space(sizeof(*stipple)); - if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple)) - || __put_user((unsigned int __user *)(unsigned long)stipple32.mask, - &stipple->mask)) - return -EFAULT; + stipple.mask = compat_ptr(stipple32.mask); - return drm_ioctl(file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); + return drm_ioctl_kernel(file, r128_cce_stipple, &stipple, DRM_AUTH); } typedef struct drm_r128_getparam32 { @@ -163,19 +150,15 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd, unsigned long arg) { drm_r128_getparam32_t getparam32; - drm_r128_getparam_t __user *getparam; + drm_r128_getparam_t getparam; if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) return -EFAULT; - getparam = compat_alloc_user_space(sizeof(*getparam)); - if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam)) - || __put_user(getparam32.param, &getparam->param) - || __put_user((void __user *)(unsigned long)getparam32.value, - &getparam->value)) - return -EFAULT; + getparam.param = getparam32.param; + getparam.value = compat_ptr(getparam32.value); - return drm_ioctl(file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); + return drm_ioctl_kernel(file, r128_getparam, &getparam, DRM_AUTH); } drm_ioctl_compat_t *r128_compat_ioctls[] = { diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c index 8fd2d9f58f77..8fdc56c1c953 100644 --- a/drivers/gpu/drm/r128/r128_state.c +++ b/drivers/gpu/drm/r128/r128_state.c @@ -1460,7 +1460,7 @@ static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *fi return ret; } -static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_depth_t *depth = data; @@ -1492,7 +1492,7 @@ static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *f return ret; } -static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_stipple_t *stipple = data; @@ -1582,7 +1582,7 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file return 0; } -static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_getparam_t *param = data; -- GitLab From cd6bf7741cf992306748db11e1888c741d16dd0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Sep 2017 23:00:59 +0300 Subject: [PATCH 0971/2898] platform/x86: fujitsu-laptop: Don't oops when FUJ02E3 is not presnt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My Fujitsu-Siemens Lifebook S6120 doesn't have the FUJ02E3 device, but it does have FUJ02B1. That means we do register the backlight device (and it even seems to work), but the code will oops as soon as we try to set the backlight brightness because it's trying to call call_fext_func() with a NULL device. Let's just skip those function calls when the FUJ02E3 device is not present. Cc: Jonathan Woithe Cc: Andy Shevchenko Signed-off-by: Ville Syrjälä Cc: # 4.13.x Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/fujitsu-laptop.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 85de30f93a9c..56a8195096a2 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -254,10 +254,12 @@ static int bl_update_status(struct backlight_device *b) { struct acpi_device *device = bl_get_data(b); - if (b->props.power == FB_BLANK_POWERDOWN) - call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x3); - else - call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x0); + if (fext) { + if (b->props.power == FB_BLANK_POWERDOWN) + call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x3); + else + call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x0); + } return set_lcd_level(device, b->props.brightness); } -- GitLab From c6eb50d2790478d8b5841379b9502812a5e5feb3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 30 Sep 2017 14:45:42 -0400 Subject: [PATCH 0972/2898] mode_t whack-a-mole: task_dump_owner() should be umode_t... Signed-off-by: Al Viro --- fs/proc/base.c | 2 +- fs/proc/internal.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index ad3b0762cc3e..0a17e52a3d18 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1681,7 +1681,7 @@ const struct inode_operations proc_pid_link_inode_operations = { /* building an inode */ -void task_dump_owner(struct task_struct *task, mode_t mode, +void task_dump_owner(struct task_struct *task, umode_t mode, kuid_t *ruid, kgid_t *rgid) { /* Depending on the state of dumpable compute who should own a diff --git a/fs/proc/internal.h b/fs/proc/internal.h index a34195e92b20..5bc75e56a8de 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -100,7 +100,7 @@ static inline struct task_struct *get_proc_task(struct inode *inode) return get_pid_task(proc_pid(inode), PIDTYPE_PID); } -void task_dump_owner(struct task_struct *task, mode_t mode, +void task_dump_owner(struct task_struct *task, umode_t mode, kuid_t *ruid, kgid_t *rgid); static inline unsigned name_to_int(const struct qstr *qstr) -- GitLab From dda3ec0aa631d15b12a42438d23336354037e108 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Fri, 15 Sep 2017 15:20:49 +0200 Subject: [PATCH 0973/2898] platform/x86: thinkpad_acpi: Implement tablet mode using GMMS method Many thinkpad laptops and convertibles provide the GMMS method to resolve how far the laptop has been opened and whether it has been converted into tablet mode. This allows reporting a more precise tablet mode state to userspace. The current implementation only reports a summarized tablet mode state which is triggered as soon as the input devices become unusable as they are folded away from the display. This will work on all models where the CMMD method was used previously and it may also work in other cases. Thanks to Peter Zhang of Lenovo for providing information on how to use the GMMS method to query the tablet mode. Signed-off-by: Benjamin Berg Cc: Peter FP1 Zhang Cc: Lyude Paul Acked-by: Henrique de Moraes Holschuh Reviewed-by: Lyude Paul Signed-off-by: Andy Shevchenko --- drivers/platform/x86/thinkpad_acpi.c | 132 ++++++++++++++++++++++++--- 1 file changed, 119 insertions(+), 13 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 2242d6035d9e..91fab1a13a6d 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -310,8 +310,7 @@ static struct { enum { TP_HOTKEY_TABLET_NONE = 0, TP_HOTKEY_TABLET_USES_MHKG, - /* X1 Yoga 2016, seen on BIOS N1FET44W */ - TP_HOTKEY_TABLET_USES_CMMD, + TP_HOTKEY_TABLET_USES_GMMS, } hotkey_tablet; u32 kbdlight:1; u32 light:1; @@ -2044,8 +2043,28 @@ static void hotkey_poll_setup(const bool may_warn); /* HKEY.MHKG() return bits */ #define TP_HOTKEY_TABLET_MASK (1 << 3) -/* ThinkPad X1 Yoga (2016) */ -#define TP_EC_CMMD_TABLET_MODE 0x6 +enum { + TP_ACPI_MULTI_MODE_INVALID = 0, + TP_ACPI_MULTI_MODE_UNKNOWN = 1 << 0, + TP_ACPI_MULTI_MODE_LAPTOP = 1 << 1, + TP_ACPI_MULTI_MODE_TABLET = 1 << 2, + TP_ACPI_MULTI_MODE_FLAT = 1 << 3, + TP_ACPI_MULTI_MODE_STAND = 1 << 4, + TP_ACPI_MULTI_MODE_TENT = 1 << 5, + TP_ACPI_MULTI_MODE_STAND_TENT = 1 << 6, +}; + +enum { + /* The following modes are considered tablet mode for the purpose of + * reporting the status to userspace. i.e. in all these modes it makes + * sense to disable the laptop input devices such as touchpad and + * keyboard. + */ + TP_ACPI_MULTI_MODE_TABLET_LIKE = TP_ACPI_MULTI_MODE_TABLET | + TP_ACPI_MULTI_MODE_STAND | + TP_ACPI_MULTI_MODE_TENT | + TP_ACPI_MULTI_MODE_STAND_TENT, +}; static int hotkey_get_wlsw(void) { @@ -2066,6 +2085,90 @@ static int hotkey_get_wlsw(void) return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF; } +static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode) +{ + int type = (s >> 16) & 0xffff; + int value = s & 0xffff; + int mode = TP_ACPI_MULTI_MODE_INVALID; + int valid_modes = 0; + + if (has_tablet_mode) + *has_tablet_mode = 0; + + switch (type) { + case 1: + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP | + TP_ACPI_MULTI_MODE_TABLET | + TP_ACPI_MULTI_MODE_STAND_TENT; + break; + case 2: + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP | + TP_ACPI_MULTI_MODE_FLAT | + TP_ACPI_MULTI_MODE_TABLET | + TP_ACPI_MULTI_MODE_STAND | + TP_ACPI_MULTI_MODE_TENT; + break; + case 3: + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP | + TP_ACPI_MULTI_MODE_FLAT; + break; + case 4: + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP | + TP_ACPI_MULTI_MODE_TABLET | + TP_ACPI_MULTI_MODE_STAND | + TP_ACPI_MULTI_MODE_TENT; + break; + case 5: + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP | + TP_ACPI_MULTI_MODE_FLAT | + TP_ACPI_MULTI_MODE_TABLET | + TP_ACPI_MULTI_MODE_STAND | + TP_ACPI_MULTI_MODE_TENT; + break; + default: + pr_err("Unknown multi mode status type %d with value 0x%04X, please report this to %s\n", + type, value, TPACPI_MAIL); + return 0; + } + + if (has_tablet_mode && (valid_modes & TP_ACPI_MULTI_MODE_TABLET_LIKE)) + *has_tablet_mode = 1; + + switch (value) { + case 1: + mode = TP_ACPI_MULTI_MODE_LAPTOP; + break; + case 2: + mode = TP_ACPI_MULTI_MODE_FLAT; + break; + case 3: + mode = TP_ACPI_MULTI_MODE_TABLET; + break; + case 4: + if (type == 1) + mode = TP_ACPI_MULTI_MODE_STAND_TENT; + else + mode = TP_ACPI_MULTI_MODE_STAND; + break; + case 5: + mode = TP_ACPI_MULTI_MODE_TENT; + break; + default: + if (type == 5 && value == 0xffff) { + pr_warn("Multi mode status is undetected, assuming laptop\n"); + return 0; + } + } + + if (!(mode & valid_modes)) { + pr_err("Unknown/reserved multi mode value 0x%04X for type %d, please report this to %s\n", + value, type, TPACPI_MAIL); + return 0; + } + + return !!(mode & TP_ACPI_MULTI_MODE_TABLET_LIKE); +} + static int hotkey_get_tablet_mode(int *status) { int s; @@ -2077,11 +2180,11 @@ static int hotkey_get_tablet_mode(int *status) *status = ((s & TP_HOTKEY_TABLET_MASK) != 0); break; - case TP_HOTKEY_TABLET_USES_CMMD: - if (!acpi_evalf(ec_handle, &s, "CMMD", "d")) + case TP_HOTKEY_TABLET_USES_GMMS: + if (!acpi_evalf(hkey_handle, &s, "GMMS", "dd", 0)) return -EIO; - *status = (s == TP_EC_CMMD_TABLET_MODE); + *status = hotkey_gmms_get_tablet_mode(s, NULL); break; default: break; @@ -3113,16 +3216,19 @@ static int hotkey_init_tablet_mode(void) int in_tablet_mode = 0, res; char *type = NULL; - if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) { + if (acpi_evalf(hkey_handle, &res, "GMMS", "qdd", 0)) { + int has_tablet_mode; + + in_tablet_mode = hotkey_gmms_get_tablet_mode(res, + &has_tablet_mode); + if (has_tablet_mode) + tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GMMS; + type = "GMMS"; + } else if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) { /* For X41t, X60t, X61t Tablets... */ tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_MHKG; in_tablet_mode = !!(res & TP_HOTKEY_TABLET_MASK); type = "MHKG"; - } else if (acpi_evalf(ec_handle, &res, "CMMD", "qd")) { - /* For X1 Yoga (2016) */ - tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_CMMD; - in_tablet_mode = res == TP_EC_CMMD_TABLET_MODE; - type = "CMMD"; } if (!tp_features.hotkey_tablet) -- GitLab From d7ca5ebf2493ddd610d07cc1c6c48de8fabb0496 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Mon, 4 Sep 2017 22:37:21 -0700 Subject: [PATCH 0974/2898] platform/x86: intel_pmc_ipc: Use devm_* calls in driver probe function This patch cleans up unnecessary free/alloc calls in ipc_plat_probe(), ipc_pci_probe() and ipc_plat_get_res() functions by using devm_* calls. This patch also adds proper error handling for failure cases in ipc_pci_probe() function. Signed-off-by: Kuppuswamy Sathyanarayanan [andy: fixed style issues, missed devm_free_irq(), removed unnecessary log message] Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_pmc_ipc.c | 94 +++++++++------------------- 1 file changed, 28 insertions(+), 66 deletions(-) diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index bb792a52248b..751b1212d01c 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -480,52 +480,39 @@ static irqreturn_t ioc(int irq, void *dev_id) static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - resource_size_t pci_resource; + struct intel_pmc_ipc_dev *pmc = &ipcdev; int ret; - int len; - ipcdev.dev = &pci_dev_get(pdev)->dev; - ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; + /* Only one PMC is supported */ + if (pmc->dev) + return -EBUSY; - ret = pci_enable_device(pdev); + pmc->irq_mode = IPC_TRIGGER_MODE_IRQ; + + ret = pcim_enable_device(pdev); if (ret) return ret; - ret = pci_request_regions(pdev, "intel_pmc_ipc"); + ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); if (ret) return ret; - pci_resource = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - if (!pci_resource || !len) { - dev_err(&pdev->dev, "Failed to get resource\n"); - return -ENOMEM; - } + init_completion(&pmc->cmd_complete); - init_completion(&ipcdev.cmd_complete); + pmc->ipc_base = pcim_iomap_table(pdev)[0]; - if (request_irq(pdev->irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) { + ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc", + pmc); + if (ret) { dev_err(&pdev->dev, "Failed to request irq\n"); - return -EBUSY; + return ret; } - ipcdev.ipc_base = ioremap_nocache(pci_resource, len); - if (!ipcdev.ipc_base) { - dev_err(&pdev->dev, "Failed to ioremap ipc base\n"); - free_irq(pdev->irq, &ipcdev); - ret = -ENOMEM; - } + pmc->dev = &pdev->dev; - return ret; -} + pci_set_drvdata(pdev, pmc); -static void ipc_pci_remove(struct pci_dev *pdev) -{ - free_irq(pdev->irq, &ipcdev); - pci_release_regions(pdev); - pci_dev_put(pdev); - iounmap(ipcdev.ipc_base); - ipcdev.dev = NULL; + return 0; } static const struct pci_device_id ipc_pci_ids[] = { @@ -540,7 +527,6 @@ static struct pci_driver ipc_pci_driver = { .name = "intel_pmc_ipc", .id_table = ipc_pci_ids, .probe = ipc_pci_probe, - .remove = ipc_pci_remove, }; static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev, @@ -850,17 +836,12 @@ static int ipc_plat_get_res(struct platform_device *pdev) return -ENXIO; } size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE; + res->end = res->start + size - 1; + + addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(addr)) + return PTR_ERR(addr); - if (!request_mem_region(res->start, size, pdev->name)) { - dev_err(&pdev->dev, "Failed to request ipc resource\n"); - return -EBUSY; - } - addr = ioremap_nocache(res->start, size); - if (!addr) { - dev_err(&pdev->dev, "I/O memory remapping failed\n"); - release_mem_region(res->start, size); - return -ENOMEM; - } ipcdev.ipc_base = addr; ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; @@ -917,7 +898,6 @@ MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids); static int ipc_plat_probe(struct platform_device *pdev) { - struct resource *res; int ret; ipcdev.dev = &pdev->dev; @@ -939,11 +919,11 @@ static int ipc_plat_probe(struct platform_device *pdev) ret = ipc_create_pmc_devices(); if (ret) { dev_err(&pdev->dev, "Failed to create pmc devices\n"); - goto err_device; + return ret; } - if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND, - "intel_pmc_ipc", &ipcdev)) { + if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND, + "intel_pmc_ipc", &ipcdev)) { dev_err(&pdev->dev, "Failed to request irq\n"); ret = -EBUSY; goto err_irq; @@ -960,40 +940,22 @@ static int ipc_plat_probe(struct platform_device *pdev) return 0; err_sys: - free_irq(ipcdev.irq, &ipcdev); + devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); err_irq: platform_device_unregister(ipcdev.tco_dev); platform_device_unregister(ipcdev.punit_dev); platform_device_unregister(ipcdev.telemetry_dev); -err_device: - iounmap(ipcdev.ipc_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_IPC_INDEX); - if (res) { - release_mem_region(res->start, - PLAT_RESOURCE_IPC_SIZE + - PLAT_RESOURCE_GCR_SIZE); - } + return ret; } static int ipc_plat_remove(struct platform_device *pdev) { - struct resource *res; - sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group); - free_irq(ipcdev.irq, &ipcdev); + devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); platform_device_unregister(ipcdev.tco_dev); platform_device_unregister(ipcdev.punit_dev); platform_device_unregister(ipcdev.telemetry_dev); - iounmap(ipcdev.ipc_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_IPC_INDEX); - if (res) { - release_mem_region(res->start, - PLAT_RESOURCE_IPC_SIZE + - PLAT_RESOURCE_GCR_SIZE); - } ipcdev.dev = NULL; return 0; } -- GitLab From a8f2023d5d265fe3ff7e434bd7217e394b809f0b Mon Sep 17 00:00:00 2001 From: Cihangir Akturk Date: Fri, 11 Aug 2017 15:32:58 +0300 Subject: [PATCH 0975/2898] drm/imx: switch to drm_*_get(), drm_*_put() helpers Use drm_*_get() and drm_*_put() helpers instead of drm_*_reference() and drm_*_unreference() helpers. drm_*_reference() and drm_*_unreference() functions are just compatibility alias for drm_*_get() and drm_*_put() and should not be used by new code. So convert all users of compatibility functions to use the new APIs. Generated by: scripts/coccinelle/api/drm-get-put.cocci Signed-off-by: Cihangir Akturk Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/ipuv3-crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 53e0b24beda6..9a9961802f5c 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -115,7 +115,7 @@ static void imx_drm_crtc_reset(struct drm_crtc *crtc) if (crtc->state) { if (crtc->state->mode_blob) - drm_property_unreference_blob(crtc->state->mode_blob); + drm_property_blob_put(crtc->state->mode_blob); state = to_imx_crtc_state(crtc->state); memset(state, 0, sizeof(*state)); -- GitLab From f13c87c22314c3a19197c8e325d2b433148cc8db Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 18 Aug 2017 18:34:22 +0200 Subject: [PATCH 0976/2898] drm/imx: parallel-display: use correct connector enum The imx parrallel display exposes a, well, display parallel interface. Use the correct enum, instead of disguising the thing as a VGA connector. Signed-off-by: Lucas Stach Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 8def97d75030..aedecda9728a 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -183,7 +183,7 @@ static int imx_pd_register(struct drm_device *drm, &imx_pd_connector_helper_funcs); drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs, - DRM_MODE_CONNECTOR_VGA); + DRM_MODE_CONNECTOR_DPI); } if (imxpd->panel) -- GitLab From dbfdd153d4aefec13460c97475737e59af92d8e2 Mon Sep 17 00:00:00 2001 From: Marco Franchi Date: Mon, 2 Oct 2017 10:45:30 -0300 Subject: [PATCH 0977/2898] dt-bindings: fsl-imx-drm: Remove incorrect "@di0" usage Improve the binding example by removing the '@di0' notation, which fixes the following build warning: Warning (unit_address_vs_reg): Node /display@di0 has a unit name, but no reg property Signed-off-by: Marco Franchi Signed-off-by: Philipp Zabel --- Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt index f79854783c2c..5bf77f6dd19d 100644 --- a/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt +++ b/Documentation/devicetree/bindings/display/imx/fsl-imx-drm.txt @@ -129,7 +129,7 @@ Optional properties: example: -display@di0 { +disp0 { compatible = "fsl,imx-parallel-display"; edid = [edid-data]; interface-pix-fmt = "rgb24"; -- GitLab From 61a646e1355cf7215ed9a3fef4ba4c2b42bd495f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Thu, 14 Sep 2017 16:38:17 +0200 Subject: [PATCH 0978/2898] clk: samsung: Properly propagate flags in __PLL macro All users of __PLL macro already provide flags parameter, so don't overwrite it unconditionally with CLK_GET_RATE_NOCACHE. Signed-off-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index b8ca0dd3a38b..d5f0d3f818b6 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -305,7 +305,7 @@ struct samsung_pll_clock { .dev_name = _dname, \ .name = _name, \ .parent_name = _pname, \ - .flags = CLK_GET_RATE_NOCACHE, \ + .flags = _flags, \ .con_offset = _con, \ .lock_offset = _lock, \ .rate_table = _rtable, \ -- GitLab From e64b9189bfd58e215ee44159767b39b8cf6fa302 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 16 Sep 2017 22:03:22 -0300 Subject: [PATCH 0979/2898] gpu: ipu-v3: ipu-dc: Remove unused 'di' variable The 'di' variable is never used inside ipu_dc_enable_channel(), so just remove it. This fixes the following build warning with W=1: drivers/gpu/ipu-v3/ipu-dc.c: In function 'ipu_dc_enable_channel': drivers/gpu/ipu-v3/ipu-dc.c:252:6: warning: variable 'di' set but not used [-Wunused-but-set-variable] Signed-off-by: Fabio Estevam Signed-off-by: Philipp Zabel --- drivers/gpu/ipu-v3/ipu-dc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c index 7a4b8362dda8..49bfe6e7d005 100644 --- a/drivers/gpu/ipu-v3/ipu-dc.c +++ b/drivers/gpu/ipu-v3/ipu-dc.c @@ -249,11 +249,8 @@ EXPORT_SYMBOL_GPL(ipu_dc_enable); void ipu_dc_enable_channel(struct ipu_dc *dc) { - int di; u32 reg; - di = dc->di; - reg = readl(dc->base + DC_WR_CH_CONF); reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL; writel(reg, dc->base + DC_WR_CH_CONF); -- GitLab From ff74972e966bfc586cea116f976866858d1b0fec Mon Sep 17 00:00:00 2001 From: Kai Heng Feng Date: Mon, 2 Oct 2017 11:56:00 +0800 Subject: [PATCH 0980/2898] platform/x86: peaq-wmi: Blacklist Lenovo ideapad 700-15ISK peaq-wmi on Lenovo ideapad 700-15ISK keeps sending KEY_SOUND, which makes user's repeated keys gets interrupted. The system does not have Dolby button, let's blacklist it. BugLink: https://bugs.launchpad.net/bugs/1720219 Signed-off-by: Kai-Heng Feng Signed-off-by: Andy Shevchenko --- drivers/platform/x86/peaq-wmi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/peaq-wmi.c b/drivers/platform/x86/peaq-wmi.c index bc98ef95514a..e09f37cdeb3c 100644 --- a/drivers/platform/x86/peaq-wmi.c +++ b/drivers/platform/x86/peaq-wmi.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -64,9 +65,22 @@ static void peaq_wmi_poll(struct input_polled_dev *dev) } } +static const struct dmi_system_id peaq_blacklist[] __initconst = { + { + /* Lenovo ideapad 700-15ISK does not have Dolby button */ + .ident = "Lenovo ideapad 700-15ISK", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "80RU"), + }, + }, + {} +}; + static int __init peaq_wmi_init(void) { - if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID)) + if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID) || + dmi_check_system(peaq_blacklist)) return -ENODEV; peaq_poll_dev = input_allocate_polled_device(); -- GitLab From d8c4deee6dc6876ae3b7d09a5b58138a57ee45f6 Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Fri, 8 Sep 2017 23:55:17 -0700 Subject: [PATCH 0981/2898] tracing: Remove obsolete sched_switch tracer selftest Since commit 87d80de2800d087ea833cb79bc13f85ff34ed49f ("tracing: Remove obsolete sched_switch tracer"), the sched_switch tracer selftest is no longer used. This patch removes the same. Link: http://lkml.kernel.org/r/20170909065517.22262-1-joelaf@google.com Cc: Ingo Molnar Cc: kernel-team@android.com Signed-off-by: Joel Fernandes Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace.h | 2 -- kernel/trace/trace_selftest.c | 32 -------------------------------- 2 files changed, 34 deletions(-) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 652c682707cd..3c078e2ad777 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -738,8 +738,6 @@ extern int trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr); extern int trace_selftest_startup_nop(struct tracer *trace, struct trace_array *tr); -extern int trace_selftest_startup_sched_switch(struct tracer *trace, - struct trace_array *tr); extern int trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr); /* diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index b17ec642793b..364f78abdf47 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -1150,38 +1150,6 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) } #endif /* CONFIG_SCHED_TRACER */ -#ifdef CONFIG_CONTEXT_SWITCH_TRACER -int -trace_selftest_startup_sched_switch(struct tracer *trace, struct trace_array *tr) -{ - unsigned long count; - int ret; - - /* start the tracing */ - ret = tracer_init(trace, tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - return ret; - } - - /* Sleep for a 1/10 of a second */ - msleep(100); - /* stop the tracing. */ - tracing_stop(); - /* check the trace buffer */ - ret = trace_test_buffer(&tr->trace_buffer, &count); - trace->reset(tr); - tracing_start(); - - if (!ret && !count) { - printk(KERN_CONT ".. no entries found .."); - ret = -1; - } - - return ret; -} -#endif /* CONFIG_CONTEXT_SWITCH_TRACER */ - #ifdef CONFIG_BRANCH_TRACER int trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr) -- GitLab From 6e7a2398114a2597a0995f96f44d908741ae5035 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 23 Aug 2017 12:23:09 +0100 Subject: [PATCH 0982/2898] tracing: Remove redundant unread variable ret Integer ret is being assigned but never used and hence it is redundant. Remove it, fixes clang warning: trace_events_hist.c:1077:3: warning: Value stored to 'ret' is never read Link: http://lkml.kernel.org/r/20170823112309.19383-1-colin.king@canonical.com Signed-off-by: Colin Ian King Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_events_hist.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 1c21d0e2a145..f123b5d0c226 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -1062,7 +1062,7 @@ static void hist_trigger_show(struct seq_file *m, struct event_trigger_data *data, int n) { struct hist_trigger_data *hist_data; - int n_entries, ret = 0; + int n_entries; if (n > 0) seq_puts(m, "\n\n"); @@ -1073,10 +1073,8 @@ static void hist_trigger_show(struct seq_file *m, hist_data = data->private_data; n_entries = print_entries(m, hist_data); - if (n_entries < 0) { - ret = n_entries; + if (n_entries < 0) n_entries = 0; - } seq_printf(m, "\nTotals:\n Hits: %llu\n Entries: %u\n Dropped: %llu\n", (u64)atomic64_read(&hist_data->map->hits), -- GitLab From 12ecef0cb12102d8c034770173d2d1363cb97d52 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Thu, 21 Sep 2017 16:22:49 -0400 Subject: [PATCH 0983/2898] tracing: Reverse the order of trace_types_lock and event_mutex In order to make future changes where we need to call tracing_set_clock() from within an event command, the order of trace_types_lock and event_mutex must be reversed, as the event command will hold event_mutex and the trace_types_lock is taken from within tracing_set_clock(). Link: http://lkml.kernel.org/r/20170921162249.0dde3dca@gandalf.local.home Requested-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace.c | 5 +++++ kernel/trace/trace_events.c | 31 +++++++++++++++---------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 752e5daf0896..5f1ac7d3402c 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -7687,6 +7687,7 @@ static int instance_mkdir(const char *name) struct trace_array *tr; int ret; + mutex_lock(&event_mutex); mutex_lock(&trace_types_lock); ret = -EEXIST; @@ -7742,6 +7743,7 @@ static int instance_mkdir(const char *name) list_add(&tr->list, &ftrace_trace_arrays); mutex_unlock(&trace_types_lock); + mutex_unlock(&event_mutex); return 0; @@ -7753,6 +7755,7 @@ static int instance_mkdir(const char *name) out_unlock: mutex_unlock(&trace_types_lock); + mutex_unlock(&event_mutex); return ret; @@ -7765,6 +7768,7 @@ static int instance_rmdir(const char *name) int ret; int i; + mutex_lock(&event_mutex); mutex_lock(&trace_types_lock); ret = -ENODEV; @@ -7810,6 +7814,7 @@ static int instance_rmdir(const char *name) out_unlock: mutex_unlock(&trace_types_lock); + mutex_unlock(&event_mutex); return ret; } diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 87468398b9ed..ec0f9aa4e151 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1406,8 +1406,8 @@ static int subsystem_open(struct inode *inode, struct file *filp) return -ENODEV; /* Make sure the system still exists */ - mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); + mutex_lock(&trace_types_lock); list_for_each_entry(tr, &ftrace_trace_arrays, list) { list_for_each_entry(dir, &tr->systems, list) { if (dir == inode->i_private) { @@ -1421,8 +1421,8 @@ static int subsystem_open(struct inode *inode, struct file *filp) } } exit_loop: - mutex_unlock(&event_mutex); mutex_unlock(&trace_types_lock); + mutex_unlock(&event_mutex); if (!system) return -ENODEV; @@ -2294,15 +2294,15 @@ static void __add_event_to_tracers(struct trace_event_call *call); int trace_add_event_call(struct trace_event_call *call) { int ret; - mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); + mutex_lock(&trace_types_lock); ret = __register_event(call, NULL); if (ret >= 0) __add_event_to_tracers(call); - mutex_unlock(&event_mutex); mutex_unlock(&trace_types_lock); + mutex_unlock(&event_mutex); return ret; } @@ -2356,13 +2356,13 @@ int trace_remove_event_call(struct trace_event_call *call) { int ret; - mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); + mutex_lock(&trace_types_lock); down_write(&trace_event_sem); ret = probe_remove_event_call(call); up_write(&trace_event_sem); - mutex_unlock(&event_mutex); mutex_unlock(&trace_types_lock); + mutex_unlock(&event_mutex); return ret; } @@ -2424,8 +2424,8 @@ static int trace_module_notify(struct notifier_block *self, { struct module *mod = data; - mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); + mutex_lock(&trace_types_lock); switch (val) { case MODULE_STATE_COMING: trace_module_add_events(mod); @@ -2434,8 +2434,8 @@ static int trace_module_notify(struct notifier_block *self, trace_module_remove_events(mod); break; } - mutex_unlock(&event_mutex); mutex_unlock(&trace_types_lock); + mutex_unlock(&event_mutex); return 0; } @@ -2950,24 +2950,24 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) * creates the event hierachry in the @parent/events directory. * * Returns 0 on success. + * + * Must be called with event_mutex held. */ int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr) { int ret; - mutex_lock(&event_mutex); + lockdep_assert_held(&event_mutex); ret = create_event_toplevel_files(parent, tr); if (ret) - goto out_unlock; + goto out; down_write(&trace_event_sem); __trace_add_event_dirs(tr); up_write(&trace_event_sem); - out_unlock: - mutex_unlock(&event_mutex); - + out: return ret; } @@ -2996,9 +2996,10 @@ early_event_add_tracer(struct dentry *parent, struct trace_array *tr) return ret; } +/* Must be called with event_mutex held */ int event_trace_del_tracer(struct trace_array *tr) { - mutex_lock(&event_mutex); + lockdep_assert_held(&event_mutex); /* Disable any event triggers and associated soft-disabled events */ clear_event_triggers(tr); @@ -3019,8 +3020,6 @@ int event_trace_del_tracer(struct trace_array *tr) tr->event_dir = NULL; - mutex_unlock(&event_mutex); - return 0; } -- GitLab From 1a149d7d3f45d311da1f63473736c05f30ae8a75 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 22 Sep 2017 16:59:02 -0400 Subject: [PATCH 0984/2898] ring-buffer: Rewrite trace_recursive_(un)lock() to be simpler The current method to prevent the ring buffer from entering into a recursize loop is to use a bitmask and set the bit that maps to the current context (normal, softirq, irq or NMI), and if that bit was already set, it is considered a recursive loop. New code is being added that may require the ring buffer to be entered a second time in the current context. The recursive locking prevents that from happening. Instead of mapping a bitmask to the current context, just allow 4 levels of nesting in the ring buffer. This matches the 4 context levels that it can already nest. It is highly unlikely to have more than two levels, thus it should be fine when we add the second entry into the ring buffer. If that proves to be a problem, we can always up the number to 8. An added benefit is that reading preempt_count() to get the current level adds a very slight but noticeable overhead. This removes that need. Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/ring_buffer.c | 64 ++++++++++---------------------------- 1 file changed, 17 insertions(+), 47 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 81279c6602ff..f6ee9b1ef62a 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2538,61 +2538,29 @@ rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer) * The lock and unlock are done within a preempt disable section. * The current_context per_cpu variable can only be modified * by the current task between lock and unlock. But it can - * be modified more than once via an interrupt. To pass this - * information from the lock to the unlock without having to - * access the 'in_interrupt()' functions again (which do show - * a bit of overhead in something as critical as function tracing, - * we use a bitmask trick. + * be modified more than once via an interrupt. There are four + * different contexts that we need to consider. * - * bit 0 = NMI context - * bit 1 = IRQ context - * bit 2 = SoftIRQ context - * bit 3 = normal context. + * Normal context. + * SoftIRQ context + * IRQ context + * NMI context * - * This works because this is the order of contexts that can - * preempt other contexts. A SoftIRQ never preempts an IRQ - * context. - * - * When the context is determined, the corresponding bit is - * checked and set (if it was set, then a recursion of that context - * happened). - * - * On unlock, we need to clear this bit. To do so, just subtract - * 1 from the current_context and AND it to itself. - * - * (binary) - * 101 - 1 = 100 - * 101 & 100 = 100 (clearing bit zero) - * - * 1010 - 1 = 1001 - * 1010 & 1001 = 1000 (clearing bit 1) - * - * The least significant bit can be cleared this way, and it - * just so happens that it is the same bit corresponding to - * the current context. + * If for some reason the ring buffer starts to recurse, we + * only allow that to happen at most 4 times (one for each + * context). If it happens 5 times, then we consider this a + * recusive loop and do not let it go further. */ static __always_inline int trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer) { - unsigned int val = cpu_buffer->current_context; - int bit; - - if (in_interrupt()) { - if (in_nmi()) - bit = RB_CTX_NMI; - else if (in_irq()) - bit = RB_CTX_IRQ; - else - bit = RB_CTX_SOFTIRQ; - } else - bit = RB_CTX_NORMAL; - - if (unlikely(val & (1 << bit))) + if (cpu_buffer->current_context >= 4) return 1; - val |= (1 << bit); - cpu_buffer->current_context = val; + cpu_buffer->current_context++; + /* Interrupts must see this update */ + barrier(); return 0; } @@ -2600,7 +2568,9 @@ trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer) static __always_inline void trace_recursive_unlock(struct ring_buffer_per_cpu *cpu_buffer) { - cpu_buffer->current_context &= cpu_buffer->current_context - 1; + /* Don't let the dec leak out */ + barrier(); + cpu_buffer->current_context--; } /** -- GitLab From a15f7fc20389a8827d5859907568b201234d4b79 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Fri, 22 Sep 2017 14:58:17 -0500 Subject: [PATCH 0985/2898] tracing: Exclude 'generic fields' from histograms There are a small number of 'generic fields' (comm/COMM/cpu/CPU) that are found by trace_find_event_field() but are only meant for filtering. Specifically, they unlike normal fields, they have a size of 0 and thus wreak havoc when used as a histogram key. Exclude these (return -EINVAL) when used as histogram keys. Link: http://lkml.kernel.org/r/956154cbc3e8a4f0633d619b886c97f0f0edf7b4.1506105045.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_events_hist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index f123b5d0c226..121d56850f24 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -450,7 +450,7 @@ static int create_val_field(struct hist_trigger_data *hist_data, } field = trace_find_event_field(file->event_call, field_name); - if (!field) { + if (!field || !field->size) { ret = -EINVAL; goto out; } @@ -548,7 +548,7 @@ static int create_key_field(struct hist_trigger_data *hist_data, } field = trace_find_event_field(file->event_call, field_name); - if (!field) { + if (!field || !field->size) { ret = -EINVAL; goto out; } -- GitLab From 83c07ecc4203728e85fc4a2ce6fdf25d16ea118e Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Fri, 22 Sep 2017 14:58:18 -0500 Subject: [PATCH 0986/2898] tracing: Remove lookups from tracing_map hitcount Lookups inflate the hitcount, making it essentially useless. Only inserts and updates should really affect the hitcount anyway, so explicitly filter lookups out. Link: http://lkml.kernel.org/r/c8d9dc39d269a8abf88bf4102d0dfc65deb0fc7f.1506105045.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/tracing_map.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c index 305039b122fa..07e75344725b 100644 --- a/kernel/trace/tracing_map.c +++ b/kernel/trace/tracing_map.c @@ -428,7 +428,8 @@ __tracing_map_insert(struct tracing_map *map, void *key, bool lookup_only) if (test_key && test_key == key_hash && entry->val && keys_match(key, entry->val->key, map->key_size)) { - atomic64_inc(&map->hits); + if (!lookup_only) + atomic64_inc(&map->hits); return entry->val; } -- GitLab From 4f36c2d85cedea60ad424d44534121ab0458069e Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Fri, 22 Sep 2017 14:58:19 -0500 Subject: [PATCH 0987/2898] tracing: Increase tracing map KEYS_MAX size The current default for the number of subkeys in a compound key is 2, which is too restrictive. Increase it to a more realistic value of 3. Link: http://lkml.kernel.org/r/b6952cca06d1f912eba33804a6fd6069b3847d44.1506105045.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/tracing_map.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/tracing_map.h b/kernel/trace/tracing_map.h index 618838f5f30a..f0975110b967 100644 --- a/kernel/trace/tracing_map.h +++ b/kernel/trace/tracing_map.h @@ -5,7 +5,7 @@ #define TRACING_MAP_BITS_MAX 17 #define TRACING_MAP_BITS_MIN 7 -#define TRACING_MAP_KEYS_MAX 2 +#define TRACING_MAP_KEYS_MAX 3 #define TRACING_MAP_VALS_MAX 3 #define TRACING_MAP_FIELDS_MAX (TRACING_MAP_KEYS_MAX + \ TRACING_MAP_VALS_MAX) -- GitLab From 7e465baa80293ed5f87fdf6405391d6f02110d4e Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Fri, 22 Sep 2017 14:58:20 -0500 Subject: [PATCH 0988/2898] tracing: Make traceprobe parsing code reusable traceprobe_probes_write() and traceprobe_command() actually contain nothing that ties them to kprobes - the code is generically useful for similar types of parsing elsewhere, so separate it out and move it to trace.c/trace.h. Other than moving it, the only change is in naming: traceprobe_probes_write() becomes trace_parse_run_command() and traceprobe_command() becomes trace_run_command(). Link: http://lkml.kernel.org/r/ae5c26ea40c196a8986854d921eb6e713ede7e3f.1506105045.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace.c | 86 +++++++++++++++++++++++++++++++++++++ kernel/trace/trace.h | 7 +++ kernel/trace/trace_kprobe.c | 18 ++++---- kernel/trace/trace_probe.c | 86 ------------------------------------- kernel/trace/trace_probe.h | 7 --- kernel/trace/trace_uprobe.c | 2 +- 6 files changed, 103 insertions(+), 103 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 5f1ac7d3402c..73e67b68c53b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -8281,6 +8281,92 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) } EXPORT_SYMBOL_GPL(ftrace_dump); +int trace_run_command(const char *buf, int (*createfn)(int, char **)) +{ + char **argv; + int argc, ret; + + argc = 0; + ret = 0; + argv = argv_split(GFP_KERNEL, buf, &argc); + if (!argv) + return -ENOMEM; + + if (argc) + ret = createfn(argc, argv); + + argv_free(argv); + + return ret; +} + +#define WRITE_BUFSIZE 4096 + +ssize_t trace_parse_run_command(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos, + int (*createfn)(int, char **)) +{ + char *kbuf, *buf, *tmp; + int ret = 0; + size_t done = 0; + size_t size; + + kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL); + if (!kbuf) + return -ENOMEM; + + while (done < count) { + size = count - done; + + if (size >= WRITE_BUFSIZE) + size = WRITE_BUFSIZE - 1; + + if (copy_from_user(kbuf, buffer + done, size)) { + ret = -EFAULT; + goto out; + } + kbuf[size] = '\0'; + buf = kbuf; + do { + tmp = strchr(buf, '\n'); + if (tmp) { + *tmp = '\0'; + size = tmp - buf + 1; + } else { + size = strlen(buf); + if (done + size < count) { + if (buf != kbuf) + break; + /* This can accept WRITE_BUFSIZE - 2 ('\n' + '\0') */ + pr_warn("Line length is too long: Should be less than %d\n", + WRITE_BUFSIZE - 2); + ret = -EINVAL; + goto out; + } + } + done += size; + + /* Remove comments */ + tmp = strchr(buf, '#'); + + if (tmp) + *tmp = '\0'; + + ret = trace_run_command(buf, createfn); + if (ret) + goto out; + buf += size; + + } while (done < count); + } + ret = done; + +out: + kfree(kbuf); + + return ret; +} + __init static int tracer_alloc_buffers(void) { int ring_buf_size; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 3c078e2ad777..f8343eb3c1f9 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1752,6 +1752,13 @@ void trace_printk_start_comm(void); int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set); int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled); +#define MAX_EVENT_NAME_LEN 64 + +extern int trace_run_command(const char *buf, int (*createfn)(int, char**)); +extern ssize_t trace_parse_run_command(struct file *file, + const char __user *buffer, size_t count, loff_t *ppos, + int (*createfn)(int, char**)); + /* * Normal trace_printk() and friends allocates special buffers * to do the manipulation, as well as saves the print formats diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 8a907e12b6b9..af6134f2e597 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -907,8 +907,8 @@ static int probes_open(struct inode *inode, struct file *file) static ssize_t probes_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - return traceprobe_probes_write(file, buffer, count, ppos, - create_trace_kprobe); + return trace_parse_run_command(file, buffer, count, ppos, + create_trace_kprobe); } static const struct file_operations kprobe_events_ops = { @@ -1433,9 +1433,9 @@ static __init int kprobe_trace_self_tests_init(void) pr_info("Testing kprobe tracing: "); - ret = traceprobe_command("p:testprobe kprobe_trace_selftest_target " - "$stack $stack0 +0($stack)", - create_trace_kprobe); + ret = trace_run_command("p:testprobe kprobe_trace_selftest_target " + "$stack $stack0 +0($stack)", + create_trace_kprobe); if (WARN_ON_ONCE(ret)) { pr_warn("error on probing function entry.\n"); warn++; @@ -1455,8 +1455,8 @@ static __init int kprobe_trace_self_tests_init(void) } } - ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " - "$retval", create_trace_kprobe); + ret = trace_run_command("r:testprobe2 kprobe_trace_selftest_target " + "$retval", create_trace_kprobe); if (WARN_ON_ONCE(ret)) { pr_warn("error on probing function return.\n"); warn++; @@ -1526,13 +1526,13 @@ static __init int kprobe_trace_self_tests_init(void) disable_trace_kprobe(tk, file); } - ret = traceprobe_command("-:testprobe", create_trace_kprobe); + ret = trace_run_command("-:testprobe", create_trace_kprobe); if (WARN_ON_ONCE(ret)) { pr_warn("error on deleting a probe.\n"); warn++; } - ret = traceprobe_command("-:testprobe2", create_trace_kprobe); + ret = trace_run_command("-:testprobe2", create_trace_kprobe); if (WARN_ON_ONCE(ret)) { pr_warn("error on deleting a probe.\n"); warn++; diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 52478f033f88..d59357308677 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -623,92 +623,6 @@ void traceprobe_free_probe_arg(struct probe_arg *arg) kfree(arg->comm); } -int traceprobe_command(const char *buf, int (*createfn)(int, char **)) -{ - char **argv; - int argc, ret; - - argc = 0; - ret = 0; - argv = argv_split(GFP_KERNEL, buf, &argc); - if (!argv) - return -ENOMEM; - - if (argc) - ret = createfn(argc, argv); - - argv_free(argv); - - return ret; -} - -#define WRITE_BUFSIZE 4096 - -ssize_t traceprobe_probes_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos, - int (*createfn)(int, char **)) -{ - char *kbuf, *buf, *tmp; - int ret = 0; - size_t done = 0; - size_t size; - - kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; - - while (done < count) { - size = count - done; - - if (size >= WRITE_BUFSIZE) - size = WRITE_BUFSIZE - 1; - - if (copy_from_user(kbuf, buffer + done, size)) { - ret = -EFAULT; - goto out; - } - kbuf[size] = '\0'; - buf = kbuf; - do { - tmp = strchr(buf, '\n'); - if (tmp) { - *tmp = '\0'; - size = tmp - buf + 1; - } else { - size = strlen(buf); - if (done + size < count) { - if (buf != kbuf) - break; - /* This can accept WRITE_BUFSIZE - 2 ('\n' + '\0') */ - pr_warn("Line length is too long: Should be less than %d\n", - WRITE_BUFSIZE - 2); - ret = -EINVAL; - goto out; - } - } - done += size; - - /* Remove comments */ - tmp = strchr(buf, '#'); - - if (tmp) - *tmp = '\0'; - - ret = traceprobe_command(buf, createfn); - if (ret) - goto out; - buf += size; - - } while (done < count); - } - ret = done; - -out: - kfree(kbuf); - - return ret; -} - static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, bool is_return) { diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index 903273c93e61..fb66e3eaa192 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h @@ -42,7 +42,6 @@ #define MAX_TRACE_ARGS 128 #define MAX_ARGSTR_LEN 63 -#define MAX_EVENT_NAME_LEN 64 #define MAX_STRING_SIZE PATH_MAX /* Reserved field names */ @@ -356,12 +355,6 @@ extern void traceprobe_free_probe_arg(struct probe_arg *arg); extern int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset); -extern ssize_t traceprobe_probes_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos, - int (*createfn)(int, char**)); - -extern int traceprobe_command(const char *buf, int (*createfn)(int, char**)); - /* Sum up total data length for dynamic arraies (strings) */ static nokprobe_inline int __get_data_size(struct trace_probe *tp, struct pt_regs *regs) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 4525e0271a53..b34965e62fb9 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -651,7 +651,7 @@ static int probes_open(struct inode *inode, struct file *file) static ssize_t probes_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - return traceprobe_probes_write(file, buffer, count, ppos, create_trace_uprobe); + return trace_parse_run_command(file, buffer, count, ppos, create_trace_uprobe); } static const struct file_operations uprobe_events_ops = { -- GitLab From 0d7a8325bf3326c92da2d21b4496a9ddde896d4f Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Fri, 22 Sep 2017 14:58:21 -0500 Subject: [PATCH 0989/2898] tracing: Clean up hist_field_flags enum As we add more flags, specifying explicit integers for the flag values becomes more unwieldy and error-prone - switch them over to left-shift values. Link: http://lkml.kernel.org/r/e644e4fb7665aec015f4a2d84a2f990d3dd5b8a1.1506105045.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_events_hist.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 121d56850f24..0c7ec3048624 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -110,16 +110,16 @@ DEFINE_HIST_FIELD_FN(u8); #define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE) enum hist_field_flags { - HIST_FIELD_FL_HITCOUNT = 1, - HIST_FIELD_FL_KEY = 2, - HIST_FIELD_FL_STRING = 4, - HIST_FIELD_FL_HEX = 8, - HIST_FIELD_FL_SYM = 16, - HIST_FIELD_FL_SYM_OFFSET = 32, - HIST_FIELD_FL_EXECNAME = 64, - HIST_FIELD_FL_SYSCALL = 128, - HIST_FIELD_FL_STACKTRACE = 256, - HIST_FIELD_FL_LOG2 = 512, + HIST_FIELD_FL_HITCOUNT = 1 << 0, + HIST_FIELD_FL_KEY = 1 << 1, + HIST_FIELD_FL_STRING = 1 << 2, + HIST_FIELD_FL_HEX = 1 << 3, + HIST_FIELD_FL_SYM = 1 << 4, + HIST_FIELD_FL_SYM_OFFSET = 1 << 5, + HIST_FIELD_FL_EXECNAME = 1 << 6, + HIST_FIELD_FL_SYSCALL = 1 << 7, + HIST_FIELD_FL_STACKTRACE = 1 << 8, + HIST_FIELD_FL_LOG2 = 1 << 9, }; struct hist_trigger_attrs { -- GitLab From 85013256cf01629f72a327674c5d007b4a4b40da Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Fri, 22 Sep 2017 14:58:22 -0500 Subject: [PATCH 0990/2898] tracing: Add hist_field_name() accessor In preparation for hist_fields that won't be strictly based on trace_event_fields, add a new hist_field_name() accessor to allow that flexibility and update associated users. Link: http://lkml.kernel.org/r/5b5a2d36dde067cbbe2434b10f06daac27b7dbd5.1506105045.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_events_hist.c | 67 +++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 0c7ec3048624..34edf5fd85fd 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -146,6 +146,23 @@ struct hist_trigger_data { struct tracing_map *map; }; +static const char *hist_field_name(struct hist_field *field, + unsigned int level) +{ + const char *field_name = ""; + + if (level > 1) + return field_name; + + if (field->field) + field_name = field->field->name; + + if (field_name == NULL) + field_name = ""; + + return field_name; +} + static hist_field_fn_t select_value_fn(int field_size, int field_is_signed) { hist_field_fn_t fn = NULL; @@ -653,7 +670,6 @@ static int is_descending(const char *str) static int create_sort_keys(struct hist_trigger_data *hist_data) { char *fields_str = hist_data->attrs->sort_key_str; - struct ftrace_event_field *field = NULL; struct tracing_map_sort_key *sort_key; int descending, ret = 0; unsigned int i, j; @@ -670,7 +686,9 @@ static int create_sort_keys(struct hist_trigger_data *hist_data) } for (i = 0; i < TRACING_MAP_SORT_KEYS_MAX; i++) { + struct hist_field *hist_field; char *field_str, *field_name; + const char *test_name; sort_key = &hist_data->sort_keys[i]; @@ -703,8 +721,10 @@ static int create_sort_keys(struct hist_trigger_data *hist_data) } for (j = 1; j < hist_data->n_fields; j++) { - field = hist_data->fields[j]->field; - if (field && (strcmp(field_name, field->name) == 0)) { + hist_field = hist_data->fields[j]; + test_name = hist_field_name(hist_field, 0); + + if (strcmp(field_name, test_name) == 0) { sort_key->field_idx = j; descending = is_descending(field_str); if (descending < 0) { @@ -952,6 +972,7 @@ hist_trigger_entry_print(struct seq_file *m, struct hist_field *key_field; char str[KSYM_SYMBOL_LEN]; bool multiline = false; + const char *field_name; unsigned int i; u64 uval; @@ -963,26 +984,27 @@ hist_trigger_entry_print(struct seq_file *m, if (i > hist_data->n_vals) seq_puts(m, ", "); + field_name = hist_field_name(key_field, 0); + if (key_field->flags & HIST_FIELD_FL_HEX) { uval = *(u64 *)(key + key_field->offset); - seq_printf(m, "%s: %llx", - key_field->field->name, uval); + seq_printf(m, "%s: %llx", field_name, uval); } else if (key_field->flags & HIST_FIELD_FL_SYM) { uval = *(u64 *)(key + key_field->offset); sprint_symbol_no_offset(str, uval); - seq_printf(m, "%s: [%llx] %-45s", - key_field->field->name, uval, str); + seq_printf(m, "%s: [%llx] %-45s", field_name, + uval, str); } else if (key_field->flags & HIST_FIELD_FL_SYM_OFFSET) { uval = *(u64 *)(key + key_field->offset); sprint_symbol(str, uval); - seq_printf(m, "%s: [%llx] %-55s", - key_field->field->name, uval, str); + seq_printf(m, "%s: [%llx] %-55s", field_name, + uval, str); } else if (key_field->flags & HIST_FIELD_FL_EXECNAME) { char *comm = elt->private_data; uval = *(u64 *)(key + key_field->offset); - seq_printf(m, "%s: %-16s[%10llu]", - key_field->field->name, comm, uval); + seq_printf(m, "%s: %-16s[%10llu]", field_name, + comm, uval); } else if (key_field->flags & HIST_FIELD_FL_SYSCALL) { const char *syscall_name; @@ -991,8 +1013,8 @@ hist_trigger_entry_print(struct seq_file *m, if (!syscall_name) syscall_name = "unknown_syscall"; - seq_printf(m, "%s: %-30s[%3llu]", - key_field->field->name, syscall_name, uval); + seq_printf(m, "%s: %-30s[%3llu]", field_name, + syscall_name, uval); } else if (key_field->flags & HIST_FIELD_FL_STACKTRACE) { seq_puts(m, "stacktrace:\n"); hist_trigger_stacktrace_print(m, @@ -1000,15 +1022,14 @@ hist_trigger_entry_print(struct seq_file *m, HIST_STACKTRACE_DEPTH); multiline = true; } else if (key_field->flags & HIST_FIELD_FL_LOG2) { - seq_printf(m, "%s: ~ 2^%-2llu", key_field->field->name, + seq_printf(m, "%s: ~ 2^%-2llu", field_name, *(u64 *)(key + key_field->offset)); } else if (key_field->flags & HIST_FIELD_FL_STRING) { - seq_printf(m, "%s: %-50s", key_field->field->name, + seq_printf(m, "%s: %-50s", field_name, (char *)(key + key_field->offset)); } else { uval = *(u64 *)(key + key_field->offset); - seq_printf(m, "%s: %10llu", key_field->field->name, - uval); + seq_printf(m, "%s: %10llu", field_name, uval); } } @@ -1021,13 +1042,13 @@ hist_trigger_entry_print(struct seq_file *m, tracing_map_read_sum(elt, HITCOUNT_IDX)); for (i = 1; i < hist_data->n_vals; i++) { + field_name = hist_field_name(hist_data->fields[i], 0); + if (hist_data->fields[i]->flags & HIST_FIELD_FL_HEX) { - seq_printf(m, " %s: %10llx", - hist_data->fields[i]->field->name, + seq_printf(m, " %s: %10llx", field_name, tracing_map_read_sum(elt, i)); } else { - seq_printf(m, " %s: %10llu", - hist_data->fields[i]->field->name, + seq_printf(m, " %s: %10llu", field_name, tracing_map_read_sum(elt, i)); } } @@ -1140,7 +1161,9 @@ static const char *get_hist_field_flags(struct hist_field *hist_field) static void hist_field_print(struct seq_file *m, struct hist_field *hist_field) { - seq_printf(m, "%s", hist_field->field->name); + const char *field_name = hist_field_name(hist_field, 0); + + seq_printf(m, "%s", field_name); if (hist_field->flags) { const char *flags_str = get_hist_field_flags(hist_field); -- GitLab From 5819eaddf35b24d628ddfa4fbb5f8d4026e44b96 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Fri, 22 Sep 2017 14:58:23 -0500 Subject: [PATCH 0991/2898] tracing: Reimplement log2 log2 as currently implemented applies only to u64 trace_event_field derived fields, and assumes that anything it's applied to is a u64 field. To prepare for synthetic fields like latencies, log2 should be applicable to those as well, so take the opportunity now to fix the current problems as well as expand to more general uses. log2 should be thought of as a chaining function rather than a field type. To enable this as well as possible future function implementations, add a hist_field operand array into the hist_field definition for this purpose, and make use of it to implement the log2 'function'. Link: http://lkml.kernel.org/r/b47f93fc0b87b36eccf716b0c018f3a71e1f1111.1506105045.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_events_hist.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 34edf5fd85fd..1e1558c99d56 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -28,12 +28,16 @@ struct hist_field; typedef u64 (*hist_field_fn_t) (struct hist_field *field, void *event); +#define HIST_FIELD_OPERANDS_MAX 2 + struct hist_field { struct ftrace_event_field *field; unsigned long flags; hist_field_fn_t fn; unsigned int size; unsigned int offset; + unsigned int is_signed; + struct hist_field *operands[HIST_FIELD_OPERANDS_MAX]; }; static u64 hist_field_none(struct hist_field *field, void *event) @@ -71,7 +75,9 @@ static u64 hist_field_pstring(struct hist_field *hist_field, void *event) static u64 hist_field_log2(struct hist_field *hist_field, void *event) { - u64 val = *(u64 *)(event + hist_field->field->offset); + struct hist_field *operand = hist_field->operands[0]; + + u64 val = operand->fn(operand, event); return (u64) ilog2(roundup_pow_of_two(val)); } @@ -156,6 +162,8 @@ static const char *hist_field_name(struct hist_field *field, if (field->field) field_name = field->field->name; + else if (field->flags & HIST_FIELD_FL_LOG2) + field_name = hist_field_name(field->operands[0], ++level); if (field_name == NULL) field_name = ""; @@ -357,8 +365,20 @@ static const struct tracing_map_ops hist_trigger_elt_comm_ops = { .elt_init = hist_trigger_elt_comm_init, }; -static void destroy_hist_field(struct hist_field *hist_field) +static void destroy_hist_field(struct hist_field *hist_field, + unsigned int level) { + unsigned int i; + + if (level > 2) + return; + + if (!hist_field) + return; + + for (i = 0; i < HIST_FIELD_OPERANDS_MAX; i++) + destroy_hist_field(hist_field->operands[i], level + 1); + kfree(hist_field); } @@ -385,7 +405,10 @@ static struct hist_field *create_hist_field(struct ftrace_event_field *field, } if (flags & HIST_FIELD_FL_LOG2) { + unsigned long fl = flags & ~HIST_FIELD_FL_LOG2; hist_field->fn = hist_field_log2; + hist_field->operands[0] = create_hist_field(field, fl); + hist_field->size = hist_field->operands[0]->size; goto out; } @@ -405,7 +428,7 @@ static struct hist_field *create_hist_field(struct ftrace_event_field *field, hist_field->fn = select_value_fn(field->size, field->is_signed); if (!hist_field->fn) { - destroy_hist_field(hist_field); + destroy_hist_field(hist_field, 0); return NULL; } } @@ -422,7 +445,7 @@ static void destroy_hist_fields(struct hist_trigger_data *hist_data) for (i = 0; i < TRACING_MAP_FIELDS_MAX; i++) { if (hist_data->fields[i]) { - destroy_hist_field(hist_data->fields[i]); + destroy_hist_field(hist_data->fields[i], 0); hist_data->fields[i] = NULL; } } -- GitLab From 6cafbe159416822f6d3dfd711bf4c39050c650ba Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Tue, 20 Jun 2017 10:44:58 -0400 Subject: [PATCH 0992/2898] ftrace: Add a ftrace_free_mem() function for modules to use In order to be able to trace module init functions, the module code needs to tell ftrace what is being freed when the init sections are freed. Use the code that the main init calls to tell ftrace to free the main init sections. This requires passing in a start and end address to free. Signed-off-by: Steven Rostedt (VMware) --- include/linux/ftrace.h | 2 ++ kernel/trace/ftrace.c | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 2e028854bac7..47fc404ad233 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -151,8 +151,10 @@ struct ftrace_ops_hash { }; void ftrace_free_init_mem(void); +void ftrace_free_mem(void *start, void *end); #else static inline void ftrace_free_init_mem(void) { } +static inline void ftrace_free_mem(void *start, void *end) { } #endif /* diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6abfafd7f173..84cb5928665a 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5868,10 +5868,10 @@ void ftrace_module_init(struct module *mod) } #endif /* CONFIG_MODULES */ -void __init ftrace_free_init_mem(void) +void ftrace_free_mem(void *start_ptr, void *end_ptr) { - unsigned long start = (unsigned long)(&__init_begin); - unsigned long end = (unsigned long)(&__init_end); + unsigned long start = (unsigned long)(start_ptr); + unsigned long end = (unsigned long)(end_ptr); struct ftrace_page **last_pg = &ftrace_pages_start; struct ftrace_page *pg; struct dyn_ftrace *rec; @@ -5913,6 +5913,14 @@ void __init ftrace_free_init_mem(void) mutex_unlock(&ftrace_lock); } +void __init ftrace_free_init_mem(void) +{ + void *start = (void *)(&__init_begin); + void *end = (void *)(&__init_end); + + ftrace_free_mem(start, end); +} + void __init ftrace_init(void) { extern unsigned long __start_mcount_loc[]; -- GitLab From 9542446048e01871fd323cba9a1d468b46cfceea Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 15 Sep 2017 16:02:52 -0400 Subject: [PATCH 0993/2898] nfsd: remove unnecessary nofilehandle checks These checks should have already be done centrally in nfsd4_proc_compound, the checks in each individual operation are unnecessary. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 3c69db7d4905..7aff6d383d34 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -485,9 +485,6 @@ static __be32 nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { - if (!cstate->current_fh.fh_dentry) - return nfserr_nofilehandle; - u->getfh = &cstate->current_fh; return nfs_ok; } @@ -535,9 +532,6 @@ static __be32 nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { - if (!cstate->current_fh.fh_dentry) - return nfserr_nofilehandle; - fh_dup2(&cstate->save_fh, &cstate->current_fh); if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG)) { memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t)); @@ -703,10 +697,8 @@ nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { struct nfsd4_link *link = &u->link; - __be32 status = nfserr_nofilehandle; + __be32 status; - if (!cstate->save_fh.fh_dentry) - return status; status = nfsd_link(rqstp, &cstate->current_fh, link->li_name, link->li_namelen, &cstate->save_fh); if (!status) @@ -850,10 +842,8 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { struct nfsd4_rename *rename = &u->rename; - __be32 status = nfserr_nofilehandle; + __be32 status; - if (!cstate->save_fh.fh_dentry) - return status; if (opens_in_grace(SVC_NET(rqstp)) && !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK)) return nfserr_grace; -- GitLab From 44d8660d3bb0a1c8363ebcb906af2343ea8e15f6 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 19 Sep 2017 20:51:31 -0400 Subject: [PATCH 0994/2898] nfsd: increase DRC cache limit An NFSv4.1+ client negotiates the size of its duplicate reply cache size in the initial CREATE_SESSION request. The server preallocates the memory for the duplicate reply cache to ensure that we'll never fail to record the response to a nonidempotent operation. To prevent a few CREATE_SESSIONs from consuming all of memory we set an upper limit based on nr_free_buffer_pages(). 1/2^10 has been too limiting in practice; 1/2^7 is still less than one percent. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfssvc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 7e3af3ef0917..6bbc717f40f2 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -446,7 +446,7 @@ void nfsd_reset_versions(void) */ static void set_max_drc(void) { - #define NFSD_DRC_SIZE_SHIFT 10 + #define NFSD_DRC_SIZE_SHIFT 7 nfsd_drc_max_mem = (nr_free_buffer_pages() >> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE; nfsd_drc_mem_used = 0; -- GitLab From de766e570413bd0484af0b580299b495ada625c3 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 19 Sep 2017 19:25:41 -0400 Subject: [PATCH 0995/2898] nfsd: give out fewer session slots as limit approaches Instead of granting client's full requests until we hit our DRC size limit and then failing CREATE_SESSIONs (and hence mounts) completely, start granting clients smaller slot tables as we approach the limit. The factor chosen here is pretty much arbitrary. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 0c04f81aa63b..9db8a19cceaa 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1472,6 +1472,11 @@ static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca) spin_lock(&nfsd_drc_lock); avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, nfsd_drc_max_mem - nfsd_drc_mem_used); + /* + * Never use more than a third of the remaining memory, + * unless it's the only way to give this client a slot: + */ + avail = clamp_t(int, avail, slotsize, avail/3); num = min_t(int, num, avail / slotsize); nfsd_drc_mem_used += num * slotsize; spin_unlock(&nfsd_drc_lock); -- GitLab From a133552a0049aa2ff92f83dbe8d5185485b538c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Lefaure?= Date: Sun, 1 Oct 2017 15:30:47 -0400 Subject: [PATCH 0996/2898] nfsd: use ARRAY_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the ARRAY_SIZE macro improves the readability of the code. Found with Coccinelle with the following semantic patch: @r depends on (org || report)@ type T; T[] E; position p; @@ ( (sizeof(E)@p /sizeof(*E)) | (sizeof(E)@p /sizeof(E[...])) | (sizeof(E)@p /sizeof(T)) ) Signed-off-by: Jérémy Lefaure Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/nfsd/fault_inject.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/fault_inject.c b/fs/nfsd/fault_inject.c index 34c1c449fddf..3ec72c931ac5 100644 --- a/fs/nfsd/fault_inject.c +++ b/fs/nfsd/fault_inject.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "state.h" #include "netns.h" @@ -125,8 +126,6 @@ static struct nfsd_fault_inject_op inject_ops[] = { }, }; -#define NUM_INJECT_OPS (sizeof(inject_ops)/sizeof(struct nfsd_fault_inject_op)) - int nfsd_fault_inject_init(void) { unsigned int i; @@ -137,7 +136,7 @@ int nfsd_fault_inject_init(void) if (!debug_dir) goto fail; - for (i = 0; i < NUM_INJECT_OPS; i++) { + for (i = 0; i < ARRAY_SIZE(inject_ops); i++) { op = &inject_ops[i]; if (!debugfs_create_file(op->file, mode, debug_dir, op, &fops_nfsd)) goto fail; -- GitLab From 3e234289f86b12985ef8909cd34525fcb66c4efb Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 3 Mar 2017 18:00:22 -0500 Subject: [PATCH 0997/2898] ftrace: Allow module init functions to be traced Allow for module init sections to be traced as well as core kernel init sections. Now that filtering modules functions can be stored, for when they are loaded, it makes sense to be able to trace them. Cc: Jessica Yu Cc: Rusty Russell Signed-off-by: Steven Rostedt (VMware) --- include/linux/init.h | 4 +--- kernel/module.c | 2 ++ kernel/trace/ftrace.c | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/linux/init.h b/include/linux/init.h index 94769d687cf0..a779c1816437 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -39,7 +39,7 @@ /* These are for everybody (although not all archs will actually discard it in modules) */ -#define __init __section(.init.text) __cold __inittrace __latent_entropy +#define __init __section(.init.text) __cold __latent_entropy #define __initdata __section(.init.data) #define __initconst __section(.init.rodata) #define __exitdata __section(.exit.data) @@ -68,10 +68,8 @@ #ifdef MODULE #define __exitused -#define __inittrace notrace #else #define __exitused __used -#define __inittrace #endif #define __exit __section(.exit.text) __exitused __cold notrace diff --git a/kernel/module.c b/kernel/module.c index de66ec825992..58bca427ac3f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3473,6 +3473,8 @@ static noinline int do_init_module(struct module *mod) if (!mod->async_probe_requested && (current->flags & PF_USED_ASYNC)) async_synchronize_full(); + ftrace_free_mem(mod->init_layout.base, mod->init_layout.base + + mod->init_layout.size); mutex_lock(&module_mutex); /* Drop initial reference. */ module_put(mod); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 84cb5928665a..d7297e866e4a 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5752,7 +5752,8 @@ void ftrace_release_mod(struct module *mod) last_pg = &ftrace_pages_start; for (pg = ftrace_pages_start; pg; pg = *last_pg) { rec = &pg->records[0]; - if (within_module_core(rec->ip, mod)) { + if (within_module_core(rec->ip, mod) || + within_module_init(rec->ip, mod)) { /* * As core pages are first, the first * page should never be a module page. @@ -5821,7 +5822,8 @@ void ftrace_module_enable(struct module *mod) * not part of this module, then skip this pg, * which the "break" will do. */ - if (!within_module_core(rec->ip, mod)) + if (!within_module_core(rec->ip, mod) && + !within_module_init(rec->ip, mod)) break; cnt = 0; -- GitLab From aba4b5c22cbac296f4081a0476d0c55828f135b4 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 1 Sep 2017 08:35:38 -0400 Subject: [PATCH 0998/2898] ftrace: Save module init functions kallsyms symbols for tracing If function tracing is active when the module init functions are freed, then store them to be referenced by kallsyms. As module init functions can now be traced on module load, they were useless: ># echo ':mod:snd_seq' > set_ftrace_filter ># echo function > current_tracer ># modprobe snd_seq ># cat trace # tracer: function # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | modprobe-2786 [000] .... 3189.037874: 0xffffffffa0860000 <-do_one_initcall modprobe-2786 [000] .... 3189.037876: 0xffffffffa086004d <-0xffffffffa086000f modprobe-2786 [000] .... 3189.037876: 0xffffffffa086010d <-0xffffffffa0860018 modprobe-2786 [000] .... 3189.037877: 0xffffffffa086011a <-0xffffffffa0860021 modprobe-2786 [000] .... 3189.037877: 0xffffffffa0860080 <-0xffffffffa086002a modprobe-2786 [000] .... 3189.039523: 0xffffffffa0860400 <-0xffffffffa0860033 modprobe-2786 [000] .... 3189.039523: 0xffffffffa086038a <-0xffffffffa086041c modprobe-2786 [000] .... 3189.039591: 0xffffffffa086038a <-0xffffffffa0860436 modprobe-2786 [000] .... 3189.039657: 0xffffffffa086038a <-0xffffffffa0860450 modprobe-2786 [000] .... 3189.039719: 0xffffffffa0860127 <-0xffffffffa086003c modprobe-2786 [000] .... 3189.039742: snd_seq_create_kernel_client <-0xffffffffa08601f6 When the output is shown, the kallsyms for the module init functions have already been freed, and the output of the trace can not convert them to their function names. Now this looks like this: # tracer: function # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | modprobe-2463 [002] .... 174.243237: alsa_seq_init <-do_one_initcall modprobe-2463 [002] .... 174.243239: client_init_data <-alsa_seq_init modprobe-2463 [002] .... 174.243240: snd_sequencer_memory_init <-alsa_seq_init modprobe-2463 [002] .... 174.243240: snd_seq_queues_init <-alsa_seq_init modprobe-2463 [002] .... 174.243240: snd_sequencer_device_init <-alsa_seq_init modprobe-2463 [002] .... 174.244860: snd_seq_info_init <-alsa_seq_init modprobe-2463 [002] .... 174.244861: create_info_entry <-snd_seq_info_init modprobe-2463 [002] .... 174.244936: create_info_entry <-snd_seq_info_init modprobe-2463 [002] .... 174.245003: create_info_entry <-snd_seq_info_init modprobe-2463 [002] .... 174.245072: snd_seq_system_client_init <-alsa_seq_init modprobe-2463 [002] .... 174.245094: snd_seq_create_kernel_client <-snd_seq_system_client_init Signed-off-by: Steven Rostedt (VMware) --- include/linux/ftrace.h | 20 +++++- kernel/kallsyms.c | 5 ++ kernel/module.c | 2 +- kernel/trace/ftrace.c | 146 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 168 insertions(+), 5 deletions(-) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 47fc404ad233..202b40784c4e 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -51,6 +51,21 @@ static inline void early_trace_init(void) { } struct module; struct ftrace_hash; +#if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_MODULES) && \ + defined(CONFIG_DYNAMIC_FTRACE) +const char * +ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, + unsigned long *off, char **modname, char *sym); +#else +static inline const char * +ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, + unsigned long *off, char **modname, char *sym) +{ + return NULL; +} +#endif + + #ifdef CONFIG_FUNCTION_TRACER extern int ftrace_enabled; @@ -151,10 +166,10 @@ struct ftrace_ops_hash { }; void ftrace_free_init_mem(void); -void ftrace_free_mem(void *start, void *end); +void ftrace_free_mem(struct module *mod, void *start, void *end); #else static inline void ftrace_free_init_mem(void) { } -static inline void ftrace_free_mem(void *start, void *end) { } +static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { } #endif /* @@ -272,6 +287,7 @@ static inline int ftrace_nr_registered_ops(void) static inline void clear_ftrace_function(void) { } static inline void ftrace_kill(void) { } static inline void ftrace_free_init_mem(void) { } +static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { } #endif /* CONFIG_FUNCTION_TRACER */ #ifdef CONFIG_STACK_TRACER diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 127e7cfafa55..976ecb9275d9 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -337,6 +338,10 @@ const char *kallsyms_lookup(unsigned long addr, if (!ret) ret = bpf_address_lookup(addr, symbolsize, offset, modname, namebuf); + + if (!ret) + ret = ftrace_mod_address_lookup(addr, symbolsize, + offset, modname, namebuf); return ret; } diff --git a/kernel/module.c b/kernel/module.c index 58bca427ac3f..279a469dc375 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3473,7 +3473,7 @@ static noinline int do_init_module(struct module *mod) if (!mod->async_probe_requested && (current->flags & PF_USED_ASYNC)) async_synchronize_full(); - ftrace_free_mem(mod->init_layout.base, mod->init_layout.base + + ftrace_free_mem(mod, mod->init_layout.base, mod->init_layout.base + mod->init_layout.size); mutex_lock(&module_mutex); /* Drop initial reference. */ diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index d7297e866e4a..86dbbfb353db 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5675,6 +5675,21 @@ static int ftrace_process_locs(struct module *mod, return ret; } +struct ftrace_mod_func { + struct list_head list; + char *name; + unsigned long ip; + unsigned int size; +}; + +struct ftrace_mod_map { + struct list_head list; + struct module *mod; + unsigned long start_addr; + unsigned long end_addr; + struct list_head funcs; +}; + #ifdef CONFIG_MODULES #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next) @@ -5868,9 +5883,123 @@ void ftrace_module_init(struct module *mod) ftrace_process_locs(mod, mod->ftrace_callsites, mod->ftrace_callsites + mod->num_ftrace_callsites); } + +static void save_ftrace_mod_rec(struct ftrace_mod_map *mod_map, + struct dyn_ftrace *rec) +{ + struct ftrace_mod_func *mod_func; + unsigned long symsize; + unsigned long offset; + char str[KSYM_SYMBOL_LEN]; + char *modname; + const char *ret; + + ret = kallsyms_lookup(rec->ip, &symsize, &offset, &modname, str); + if (!ret) + return; + + mod_func = kmalloc(sizeof(*mod_func), GFP_KERNEL); + if (!mod_func) + return; + + mod_func->name = kstrdup(str, GFP_KERNEL); + if (!mod_func->name) { + kfree(mod_func); + return; + } + + mod_func->ip = rec->ip - offset; + mod_func->size = symsize; + + list_add_rcu(&mod_func->list, &mod_map->funcs); +} + +static LIST_HEAD(ftrace_mod_maps); + +static struct ftrace_mod_map * +allocate_ftrace_mod_map(struct module *mod, + unsigned long start, unsigned long end) +{ + struct ftrace_mod_map *mod_map; + + mod_map = kmalloc(sizeof(*mod_map), GFP_KERNEL); + if (!mod_map) + return NULL; + + mod_map->mod = mod; + mod_map->start_addr = start; + mod_map->end_addr = end; + + INIT_LIST_HEAD_RCU(&mod_map->funcs); + + list_add_rcu(&mod_map->list, &ftrace_mod_maps); + + return mod_map; +} + +static const char * +ftrace_func_address_lookup(struct ftrace_mod_map *mod_map, + unsigned long addr, unsigned long *size, + unsigned long *off, char *sym) +{ + struct ftrace_mod_func *found_func = NULL; + struct ftrace_mod_func *mod_func; + + list_for_each_entry_rcu(mod_func, &mod_map->funcs, list) { + if (addr >= mod_func->ip && + addr < mod_func->ip + mod_func->size) { + found_func = mod_func; + break; + } + } + + if (found_func) { + if (size) + *size = found_func->size; + if (off) + *off = addr - found_func->ip; + if (sym) + strlcpy(sym, found_func->name, KSYM_NAME_LEN); + + return found_func->name; + } + + return NULL; +} + +const char * +ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, + unsigned long *off, char **modname, char *sym) +{ + struct ftrace_mod_map *mod_map; + const char *ret = NULL; + + preempt_disable(); + list_for_each_entry_rcu(mod_map, &ftrace_mod_maps, list) { + ret = ftrace_func_address_lookup(mod_map, addr, size, off, sym); + if (ret) { + if (modname) + *modname = mod_map->mod->name; + break; + } + } + preempt_enable(); + + return ret; +} + +#else +static void save_ftrace_mod_rec(struct ftrace_mod_map *mod_map, + struct dyn_ftrace *rec) { } +static inline struct ftrace_mod_map * +allocate_ftrace_mod_map(struct module *mod, + unsigned long start, unsigned long end) +{ + return NULL; +} #endif /* CONFIG_MODULES */ -void ftrace_free_mem(void *start_ptr, void *end_ptr) +void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) { unsigned long start = (unsigned long)(start_ptr); unsigned long end = (unsigned long)(end_ptr); @@ -5878,6 +6007,7 @@ void ftrace_free_mem(void *start_ptr, void *end_ptr) struct ftrace_page *pg; struct dyn_ftrace *rec; struct dyn_ftrace key; + struct ftrace_mod_map *mod_map = NULL; int order; key.ip = start; @@ -5885,6 +6015,14 @@ void ftrace_free_mem(void *start_ptr, void *end_ptr) mutex_lock(&ftrace_lock); + /* + * If we are freeing module init memory, then check if + * any tracer is active. If so, we need to save a mapping of + * the module functions being freed with the address. + */ + if (mod && ftrace_ops_list != &ftrace_list_end) + mod_map = allocate_ftrace_mod_map(mod, start, end); + for (pg = ftrace_pages_start; pg; last_pg = &pg->next, pg = *last_pg) { if (end < pg->records[0].ip || start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE)) @@ -5895,6 +6033,10 @@ void ftrace_free_mem(void *start_ptr, void *end_ptr) ftrace_cmp_recs); if (!rec) continue; + + if (mod_map) + save_ftrace_mod_rec(mod_map, rec); + pg->index--; ftrace_update_tot_cnt--; if (!pg->index) { @@ -5920,7 +6062,7 @@ void __init ftrace_free_init_mem(void) void *start = (void *)(&__init_begin); void *end = (void *)(&__init_end); - ftrace_free_mem(start, end); + ftrace_free_mem(NULL, start, end); } void __init ftrace_init(void) -- GitLab From 6aa69784b43eb5f69120339938c50a97a433049f Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Tue, 5 Sep 2017 19:20:16 -0400 Subject: [PATCH 0999/2898] ftrace: Add freeing algorithm to free ftrace_mod_maps The ftrace_mod_map is a descriptor to save module init function names in case they were traced, and the trace output needs to reference the function name from the function address. But after the function is unloaded, it the maps should be freed, as the rest of the function names are as well. Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/ftrace.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 86dbbfb353db..a5824408bed9 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5683,6 +5683,7 @@ struct ftrace_mod_func { }; struct ftrace_mod_map { + struct rcu_head rcu; struct list_head list; struct module *mod; unsigned long start_addr; @@ -5694,6 +5695,8 @@ struct ftrace_mod_map { #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next) +static LIST_HEAD(ftrace_mod_maps); + static int referenced_filters(struct dyn_ftrace *rec) { struct ftrace_ops *ops; @@ -5747,8 +5750,26 @@ static void clear_mod_from_hashes(struct ftrace_page *pg) mutex_unlock(&trace_types_lock); } +static void ftrace_free_mod_map(struct rcu_head *rcu) +{ + struct ftrace_mod_map *mod_map = container_of(rcu, struct ftrace_mod_map, rcu); + struct ftrace_mod_func *mod_func; + struct ftrace_mod_func *n; + + /* All the contents of mod_map are now not visible to readers */ + list_for_each_entry_safe(mod_func, n, &mod_map->funcs, list) { + kfree(mod_func->name); + list_del(&mod_func->list); + kfree(mod_func); + } + + kfree(mod_map); +} + void ftrace_release_mod(struct module *mod) { + struct ftrace_mod_map *mod_map; + struct ftrace_mod_map *n; struct dyn_ftrace *rec; struct ftrace_page **last_pg; struct ftrace_page *tmp_page = NULL; @@ -5760,6 +5781,14 @@ void ftrace_release_mod(struct module *mod) if (ftrace_disabled) goto out_unlock; + list_for_each_entry_safe(mod_map, n, &ftrace_mod_maps, list) { + if (mod_map->mod == mod) { + list_del_rcu(&mod_map->list); + call_rcu_sched(&mod_map->rcu, ftrace_free_mod_map); + break; + } + } + /* * Each module has its own ftrace_pages, remove * them from the list. @@ -5914,8 +5943,6 @@ static void save_ftrace_mod_rec(struct ftrace_mod_map *mod_map, list_add_rcu(&mod_func->list, &mod_map->funcs); } -static LIST_HEAD(ftrace_mod_maps); - static struct ftrace_mod_map * allocate_ftrace_mod_map(struct module *mod, unsigned long start, unsigned long end) @@ -5974,6 +6001,7 @@ ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, struct ftrace_mod_map *mod_map; const char *ret = NULL; + /* mod_map is freed via call_rcu_sched() */ preempt_disable(); list_for_each_entry_rcu(mod_map, &ftrace_mod_maps, list) { ret = ftrace_func_address_lookup(mod_map, addr, size, off, sym); -- GitLab From 6171a0310a06a7a0cb83713fa7068bdd4192de19 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 6 Sep 2017 08:40:41 -0400 Subject: [PATCH 1000/2898] ftrace/kallsyms: Have /proc/kallsyms show saved mod init functions If a module is loaded while tracing is enabled, then there's a possibility that the module init functions were traced. These functions have their name and address stored by ftrace such that it can translate the function address that is written into the buffer into a human readable function name. As userspace tools may be doing the same, they need a way to map function names to their address as well. This is done through reading /proc/kallsyms. Signed-off-by: Steven Rostedt (VMware) --- include/linux/ftrace.h | 9 +++++++++ kernel/kallsyms.c | 38 ++++++++++++++++++++++++++++++++------ kernel/trace/ftrace.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 202b40784c4e..346f8294e40a 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -56,6 +56,9 @@ struct ftrace_hash; const char * ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, unsigned long *off, char **modname, char *sym); +int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value, + char *type, char *name, + char *module_name, int *exported); #else static inline const char * ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, @@ -63,6 +66,12 @@ ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, { return NULL; } +static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value, + char *type, char *name, + char *module_name, int *exported) +{ + return -1; +} #endif diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 976ecb9275d9..1966fe1c2b57 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -479,6 +479,7 @@ EXPORT_SYMBOL(__print_symbol); struct kallsym_iter { loff_t pos; loff_t pos_mod_end; + loff_t pos_ftrace_mod_end; unsigned long value; unsigned int nameoff; /* If iterating in core kernel symbols. */ char type; @@ -501,11 +502,25 @@ static int get_ksymbol_mod(struct kallsym_iter *iter) return 1; } +static int get_ksymbol_ftrace_mod(struct kallsym_iter *iter) +{ + int ret = ftrace_mod_get_kallsym(iter->pos - iter->pos_mod_end, + &iter->value, &iter->type, + iter->name, iter->module_name, + &iter->exported); + if (ret < 0) { + iter->pos_ftrace_mod_end = iter->pos; + return 0; + } + + return 1; +} + static int get_ksymbol_bpf(struct kallsym_iter *iter) { iter->module_name[0] = '\0'; iter->exported = 0; - return bpf_get_kallsym(iter->pos - iter->pos_mod_end, + return bpf_get_kallsym(iter->pos - iter->pos_ftrace_mod_end, &iter->value, &iter->type, iter->name) < 0 ? 0 : 1; } @@ -530,20 +545,31 @@ static void reset_iter(struct kallsym_iter *iter, loff_t new_pos) iter->name[0] = '\0'; iter->nameoff = get_symbol_offset(new_pos); iter->pos = new_pos; - if (new_pos == 0) + if (new_pos == 0) { iter->pos_mod_end = 0; + iter->pos_ftrace_mod_end = 0; + } } static int update_iter_mod(struct kallsym_iter *iter, loff_t pos) { iter->pos = pos; - if (iter->pos_mod_end > 0 && - iter->pos_mod_end < iter->pos) + if (iter->pos_ftrace_mod_end > 0 && + iter->pos_ftrace_mod_end < iter->pos) return get_ksymbol_bpf(iter); - if (!get_ksymbol_mod(iter)) - return get_ksymbol_bpf(iter); + if (iter->pos_mod_end > 0 && + iter->pos_mod_end < iter->pos) { + if (!get_ksymbol_ftrace_mod(iter)) + return get_ksymbol_bpf(iter); + return 1; + } + + if (!get_ksymbol_mod(iter)) { + if (!get_ksymbol_ftrace_mod(iter)) + return get_ksymbol_bpf(iter); + } return 1; } diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index a5824408bed9..9e99bd55732e 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5689,6 +5689,7 @@ struct ftrace_mod_map { unsigned long start_addr; unsigned long end_addr; struct list_head funcs; + unsigned int num_funcs; }; #ifdef CONFIG_MODULES @@ -5940,6 +5941,8 @@ static void save_ftrace_mod_rec(struct ftrace_mod_map *mod_map, mod_func->ip = rec->ip - offset; mod_func->size = symsize; + mod_map->num_funcs++; + list_add_rcu(&mod_func->list, &mod_map->funcs); } @@ -5956,6 +5959,7 @@ allocate_ftrace_mod_map(struct module *mod, mod_map->mod = mod; mod_map->start_addr = start; mod_map->end_addr = end; + mod_map->num_funcs = 0; INIT_LIST_HEAD_RCU(&mod_map->funcs); @@ -6016,6 +6020,42 @@ ftrace_mod_address_lookup(unsigned long addr, unsigned long *size, return ret; } +int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *value, + char *type, char *name, + char *module_name, int *exported) +{ + struct ftrace_mod_map *mod_map; + struct ftrace_mod_func *mod_func; + + preempt_disable(); + list_for_each_entry_rcu(mod_map, &ftrace_mod_maps, list) { + + if (symnum >= mod_map->num_funcs) { + symnum -= mod_map->num_funcs; + continue; + } + + list_for_each_entry_rcu(mod_func, &mod_map->funcs, list) { + if (symnum > 1) { + symnum--; + continue; + } + + *value = mod_func->ip; + *type = 'T'; + strlcpy(name, mod_func->name, KSYM_NAME_LEN); + strlcpy(module_name, mod_map->mod->name, MODULE_NAME_LEN); + *exported = 1; + preempt_enable(); + return 0; + } + WARN_ON(1); + break; + } + preempt_enable(); + return -ERANGE; +} + #else static void save_ftrace_mod_rec(struct ftrace_mod_map *mod_map, struct dyn_ftrace *rec) { } -- GitLab From 48aa3ddfd535a8e80b1b46da8a13920d9de8e5c5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:36:54 +1000 Subject: [PATCH 1001/2898] amdgpu/dc: inline dal grph object id functions. This is worth 400 bytes. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/basics/grph_object_id.c | 61 +--------------- .../drm/amd/display/include/grph_object_id.h | 72 ++++++++++++++----- 2 files changed, 56 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c index 9c80847d03a9..147822545252 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c +++ b/drivers/gpu/drm/amd/display/dc/basics/grph_object_id.c @@ -26,7 +26,7 @@ #include "dm_services.h" #include "include/grph_object_id.h" -bool dal_graphics_object_id_is_valid(struct graphics_object_id id) +static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) { bool rc = true; @@ -72,63 +72,4 @@ bool dal_graphics_object_id_is_equal( return false; } -/* Based on internal data members memory layout */ -uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id) -{ - uint32_t object_id = 0; - - object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc); - return object_id; -} - -/* - * ******* get specific ID - internal safe cast into specific type ******* - */ - -enum controller_id dal_graphics_object_id_get_controller_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_CONTROLLER) - return id.id; - return CONTROLLER_ID_UNDEFINED; -} - -enum clock_source_id dal_graphics_object_id_get_clock_source_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_CLOCK_SOURCE) - return id.id; - return CLOCK_SOURCE_ID_UNDEFINED; -} - -enum encoder_id dal_graphics_object_id_get_encoder_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_ENCODER) - return id.id; - return ENCODER_ID_UNKNOWN; -} - -enum connector_id dal_graphics_object_id_get_connector_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_CONNECTOR) - return id.id; - return CONNECTOR_ID_UNKNOWN; -} - -enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_AUDIO) - return id.id; - return AUDIO_ID_UNKNOWN; -} - -enum engine_id dal_graphics_object_id_get_engine_id( - struct graphics_object_id id) -{ - if (id.type == OBJECT_TYPE_ENGINE) - return id.id; - return ENGINE_ID_UNKNOWN; -} diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h index e4aa4ddf9d2a..5eb2b4dc7b9c 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_id.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h @@ -233,24 +233,62 @@ static inline struct graphics_object_id dal_graphics_object_id_init( return result; } -bool dal_graphics_object_id_is_valid( - struct graphics_object_id id); bool dal_graphics_object_id_is_equal( struct graphics_object_id id1, struct graphics_object_id id2); -uint32_t dal_graphics_object_id_to_uint( - struct graphics_object_id id); - -enum controller_id dal_graphics_object_id_get_controller_id( - struct graphics_object_id id); -enum clock_source_id dal_graphics_object_id_get_clock_source_id( - struct graphics_object_id id); -enum encoder_id dal_graphics_object_id_get_encoder_id( - struct graphics_object_id id); -enum connector_id dal_graphics_object_id_get_connector_id( - struct graphics_object_id id); -enum audio_id dal_graphics_object_id_get_audio_id( - struct graphics_object_id id); -enum engine_id dal_graphics_object_id_get_engine_id( - struct graphics_object_id id); + +/* Based on internal data members memory layout */ +static inline uint32_t dal_graphics_object_id_to_uint( + struct graphics_object_id id) +{ + return id.id + (id.enum_id << 0x8) + (id.type << 0xc); +} + +static inline enum controller_id dal_graphics_object_id_get_controller_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONTROLLER) + return id.id; + return CONTROLLER_ID_UNDEFINED; +} + +static inline enum clock_source_id dal_graphics_object_id_get_clock_source_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CLOCK_SOURCE) + return id.id; + return CLOCK_SOURCE_ID_UNDEFINED; +} + +static inline enum encoder_id dal_graphics_object_id_get_encoder_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENCODER) + return id.id; + return ENCODER_ID_UNKNOWN; +} + +static inline enum connector_id dal_graphics_object_id_get_connector_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_CONNECTOR) + return id.id; + return CONNECTOR_ID_UNKNOWN; +} + +static inline enum audio_id dal_graphics_object_id_get_audio_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_AUDIO) + return id.id; + return AUDIO_ID_UNKNOWN; +} + +static inline enum engine_id dal_graphics_object_id_get_engine_id( + struct graphics_object_id id) +{ + if (id.type == OBJECT_TYPE_ENGINE) + return id.id; + return ENGINE_ID_UNKNOWN; +} #endif -- GitLab From 4ee67c71b89948289eb5c55f1a19281be61178e5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:37:33 +1000 Subject: [PATCH 1002/2898] amdgpu/dc: don't memset after kzalloc. We allocate this struct zeroed, so don't need to memset in the constructor. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index f170ae95529c..ff07105bfd99 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -37,8 +37,6 @@ static void construct(struct dc_context *ctx, struct dc_plane_state *plane_state) { plane_state->ctx = ctx; - memset(&plane_state->hdr_static_ctx, - 0, sizeof(struct dc_hdr_static_metadata)); } static void destruct(struct dc_plane_state *plane_state) -- GitLab From 23d433fabef852e82053186b60710d138f727284 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 13:49:42 +1000 Subject: [PATCH 1003/2898] amdgpu/dc: use kernel ilog2 for log_2. This should produce the same result. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/conversion.c | 10 ---------- drivers/gpu/drm/amd/display/dc/basics/conversion.h | 5 ++++- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.c b/drivers/gpu/drm/amd/display/dc/basics/conversion.c index a2e22ae12adb..23c9a0ec0181 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.c +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.c @@ -102,13 +102,3 @@ void convert_float_matrix( matrix[i] = (uint16_t)reg_value; } } - -unsigned int log_2(unsigned int num) -{ - unsigned int result = 0; - - while ((num >>= 1) != 0) - result++; - - return result; -} diff --git a/drivers/gpu/drm/amd/display/dc/basics/conversion.h b/drivers/gpu/drm/amd/display/dc/basics/conversion.h index 189325f68cfd..ade785c4fdc7 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/conversion.h +++ b/drivers/gpu/drm/amd/display/dc/basics/conversion.h @@ -38,6 +38,9 @@ void convert_float_matrix( struct fixed31_32 *flt, uint32_t buffer_size); -unsigned int log_2(unsigned int num); +static inline unsigned int log_2(unsigned int num) +{ + return ilog2(num); +} #endif -- GitLab From bd42a6f45180b3bd2bfe260959f53344f2636e71 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 13:49:43 +1000 Subject: [PATCH 1004/2898] amdgpu/dc: drop dce110_types.h Doesn't appear to be used. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce110/dce110_types.h | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h deleted file mode 100644 index 55f52382ddfb..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_types.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef _DCE110_TYPES_H_ -#define __DCE110_TYPES_H_ - -#define GAMMA_SEGMENTS_NUM 16 - -#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_DCE110_DCE110_TYPES_H_ */ -- GitLab From 2016b641f421ecb28c21e34063ac8bd43ca6cfdc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 13:49:44 +1000 Subject: [PATCH 1005/2898] amdgpu/dc: drop hw_sequencer_types.h This isn't used or required. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../dc/dce110/dce110_timing_generator.h | 1 - .../dc/dce120/dce120_timing_generator.h | 1 - .../gpu/drm/amd/display/dc/inc/core_types.h | 1 - .../amd/display/dc/inc/hw/stream_encoder.h | 1 - .../amd/display/include/hw_sequencer_types.h | 33 ------------------- 5 files changed, 37 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/include/hw_sequencer_types.h diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h index bd8d0ab668b7..82737dea6984 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h @@ -28,7 +28,6 @@ #include "timing_generator.h" #include "../include/grph_object_id.h" -#include "../include/hw_sequencer_types.h" /* GSL Sync related values */ diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h index d69871ec0dde..549d70b23e82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.h @@ -28,7 +28,6 @@ #include "timing_generator.h" #include "../include/grph_object_id.h" -#include "../include/hw_sequencer_types.h" #include "dce110/dce110_timing_generator.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 1a1d322da8cc..c47ce6b9fc6b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -46,7 +46,6 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, #include "stream_encoder.h" #include "clock_source.h" #include "audio.h" -#include "hw_sequencer_types.h" #include "dm_pp_smu.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 6ff90a0fef24..3050afe8e8a9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -6,7 +6,6 @@ #ifndef STREAM_ENCODER_H_ #define STREAM_ENCODER_H_ -#include "include/hw_sequencer_types.h" #include "audio_types.h" struct dc_bios; diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h deleted file mode 100644 index 8ba9f65276f5..000000000000 --- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_HW_SEQUENCER_TYPES_H__ -#define __DAL_HW_SEQUENCER_TYPES_H__ - -#include "signal_types.h" -#include "grph_object_defs.h" -#include "link_service_types.h" - -#endif -- GitLab From 5667ff5c117f2d8735f27a267bc68a0811c55075 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 14:27:13 +1000 Subject: [PATCH 1006/2898] amdgpu/dc: fix a bunch of misc whitespace. This just aligns a few things with kernel style. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++-- drivers/gpu/drm/amd/display/dc/dc_types.h | 16 +++---- .../dc/dce110/dce110_timing_generator.c | 4 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 16 +++---- .../amd/display/dc/dcn10/dcn10_mem_input.c | 46 +++++++++---------- .../display/include/grph_object_ctrl_defs.h | 20 ++++---- 6 files changed, 55 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 888d268e9622..3c323c1ea366 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1473,10 +1473,10 @@ void decide_link_settings(struct dc_stream_state *stream, return; } - /* search for the minimum link setting that: - * 1. is supported according to the link training result - * 2. could support the b/w requested by the timing - */ + /* search for the minimum link setting that: + * 1. is supported according to the link training result + * 2. could support the b/w requested by the timing + */ while (current_link_setting.link_rate <= link->verified_link_cap.link_rate) { link_bw = bandwidth_in_kbps_from_link_settings( diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index a47f7472ea92..6b891fde400c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -429,14 +429,14 @@ union audio_sample_rates { }; struct audio_speaker_flags { - uint32_t FL_FR:1; - uint32_t LFE:1; - uint32_t FC:1; - uint32_t RL_RR:1; - uint32_t RC:1; - uint32_t FLC_FRC:1; - uint32_t RLC_RRC:1; - uint32_t SUPPORT_AI:1; + uint32_t FL_FR:1; + uint32_t LFE:1; + uint32_t FC:1; + uint32_t RL_RR:1; + uint32_t RC:1; + uint32_t FLC_FRC:1; + uint32_t RLC_RRC:1; + uint32_t SUPPORT_AI:1; }; struct audio_speaker_info { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c index bcd544d85621..67ac737eaa7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c @@ -1238,8 +1238,8 @@ void dce110_timing_generator_setup_global_swap_lock( DCP_GSL_CONTROL, DCP_GSL_HSYNC_FLIP_FORCE_DELAY); - /* Keep signal low (pending high) during 6 lines. - * Also defines minimum interval before re-checking signal. */ + /* Keep signal low (pending high) during 6 lines. + * Also defines minimum interval before re-checking signal. */ set_reg_field_value(value, HFLIP_CHECK_DELAY, DCP_GSL_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c4875c3a0d93..d3fee15aeb79 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2396,14 +2396,14 @@ static void program_all_pipe_in_tree( dcn10_power_on_fe(dc, pipe_ctx, context); /* temporary dcn1 wa: - * watermark update requires toggle after a/b/c/d sets are programmed - * if hubp is pg then wm value doesn't get properaged to hubp - * need to toggle after ungate to ensure wm gets to hubp. - * - * final solution: we need to get SMU to do the toggle as - * DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST is owned by SMU we should have - * both driver and fw accessing same register - */ + * watermark update requires toggle after a/b/c/d sets are programmed + * if hubp is pg then wm value doesn't get properaged to hubp + * need to toggle after ungate to ensure wm gets to hubp. + * + * final solution: we need to get SMU to do the toggle as + * DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST is owned by SMU we should have + * both driver and fw accessing same register + */ toggle_watermark_change_req(dc->hwseq); update_dchubp_dpp(dc, pipe_ctx, context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index c8088489c6a2..a28495d95a15 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -697,37 +697,37 @@ static void min10_set_vm_context0_settings(struct mem_input *mem_input, } static void min_set_viewport( - struct mem_input *mem_input, - const struct rect *viewport, - const struct rect *viewport_c) + struct mem_input *mem_input, + const struct rect *viewport, + const struct rect *viewport_c) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, - PRI_VIEWPORT_WIDTH, viewport->width, - PRI_VIEWPORT_HEIGHT, viewport->height); + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, + PRI_VIEWPORT_WIDTH, viewport->width, + PRI_VIEWPORT_HEIGHT, viewport->height); - REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, - PRI_VIEWPORT_X_START, viewport->x, - PRI_VIEWPORT_Y_START, viewport->y); + REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0, + PRI_VIEWPORT_X_START, viewport->x, + PRI_VIEWPORT_Y_START, viewport->y); - /*for stereo*/ - REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, - SEC_VIEWPORT_WIDTH, viewport->width, - SEC_VIEWPORT_HEIGHT, viewport->height); + /*for stereo*/ + REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0, + SEC_VIEWPORT_WIDTH, viewport->width, + SEC_VIEWPORT_HEIGHT, viewport->height); - REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, - SEC_VIEWPORT_X_START, viewport->x, - SEC_VIEWPORT_Y_START, viewport->y); + REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0, + SEC_VIEWPORT_X_START, viewport->x, + SEC_VIEWPORT_Y_START, viewport->y); - /* DC supports NV12 only at the moment */ - REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, - PRI_VIEWPORT_WIDTH_C, viewport_c->width, - PRI_VIEWPORT_HEIGHT_C, viewport_c->height); + /* DC supports NV12 only at the moment */ + REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0, + PRI_VIEWPORT_WIDTH_C, viewport_c->width, + PRI_VIEWPORT_HEIGHT_C, viewport_c->height); - REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, - PRI_VIEWPORT_X_START_C, viewport_c->x, - PRI_VIEWPORT_Y_START_C, viewport_c->y); + REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0, + PRI_VIEWPORT_X_START_C, viewport_c->x, + PRI_VIEWPORT_Y_START_C, viewport_c->y); } void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index 92fe00fab87c..7a9b43f84a31 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h @@ -183,9 +183,9 @@ struct dc_firmware_info { }; struct step_and_delay_info { - uint32_t step; - uint32_t delay; - uint32_t recommended_ref_div; + uint32_t step; + uint32_t delay; + uint32_t recommended_ref_div; }; struct spread_spectrum_info { @@ -266,16 +266,16 @@ struct transmitter_configuration { #define NUMBER_OF_AVAILABLE_SCLK 5 struct i2c_reg_info { - unsigned char i2c_reg_index; - unsigned char i2c_reg_val; + unsigned char i2c_reg_index; + unsigned char i2c_reg_val; }; struct ext_hdmi_settings { - unsigned char slv_addr; - unsigned char reg_num; - struct i2c_reg_info reg_settings[9]; - unsigned char reg_num_6g; - struct i2c_reg_info reg_settings_6g[3]; + unsigned char slv_addr; + unsigned char reg_num; + struct i2c_reg_info reg_settings[9]; + unsigned char reg_num_6g; + struct i2c_reg_info reg_settings_6g[3]; }; -- GitLab From d029810caafa4e6b146274560154e3f0f0381fb5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 14:27:14 +1000 Subject: [PATCH 1007/2898] amdgpu/dc: kfree already checks for NULL. Don't bother checking for it. Found with the cocci ifnullfree.cocci script. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/basics/vector.c | 3 +-- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 7 ++----- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 7 ++----- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +-- .../gpu/drm/amd/display/dc/dce110/dce110_resource.c | 11 +++-------- 5 files changed, 9 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c index e00fc4db3ac4..217b8f1f7bf6 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/vector.c +++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c @@ -130,8 +130,7 @@ struct vector *dal_vector_create( void dal_vector_destruct( struct vector *vector) { - if (vector->container != NULL) - kfree(vector->container); + kfree(vector->container); vector->count = 0; vector->capacity = 0; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 2e003b5c8d08..6d2f886f7ff4 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -119,11 +119,8 @@ struct dc_bios *bios_parser_create( static void destruct(struct bios_parser *bp) { - if (bp->base.bios_local_image) - kfree(bp->base.bios_local_image); - - if (bp->base.integrated_info) - kfree(bp->base.integrated_info); + kfree(bp->base.bios_local_image); + kfree(bp->base.integrated_info); } static void bios_parser_destroy(struct dc_bios **dcb) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 0c623b314577..3d65e2ab9bf1 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -85,11 +85,8 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( static void destruct(struct bios_parser *bp) { - if (bp->base.bios_local_image) - kfree(bp->base.bios_local_image); - - if (bp->base.integrated_info) - kfree(bp->base.integrated_info); + kfree(bp->base.bios_local_image); + kfree(bp->base.integrated_info); } static void firmware_parser_destroy(struct dc_bios **dcb) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1832f252edab..99a4d19f582d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -159,8 +159,7 @@ void dc_destroy_resource_pool(struct dc *dc) if (dc->res_pool) dc->res_pool->funcs->destroy(&dc->res_pool); - if (dc->hwseq) - kfree(dc->hwseq); + kfree(dc->hwseq); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 89036aff9021..28e768de744c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -619,14 +619,9 @@ void dce110_clock_source_destroy(struct clock_source **clk_src) dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); - if (dce110_clk_src->dp_ss_params) - kfree(dce110_clk_src->dp_ss_params); - - if (dce110_clk_src->hdmi_ss_params) - kfree(dce110_clk_src->hdmi_ss_params); - - if (dce110_clk_src->dvi_ss_params) - kfree(dce110_clk_src->dvi_ss_params); + kfree(dce110_clk_src->dp_ss_params); + kfree(dce110_clk_src->hdmi_ss_params); + kfree(dce110_clk_src->dvi_ss_params); kfree(dce110_clk_src); *clk_src = NULL; -- GitLab From ae3a27d19b59e431aea9f9d5917c1aec710ae4c3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 14:27:15 +1000 Subject: [PATCH 1008/2898] amdgpu/dm: don't use after free. This dereference acrtc after freeing it. Found by the kfree cocci script. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 61ccddd19718..4f8973182f8a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3174,7 +3174,6 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, fail: kfree(acrtc); kfree(cursor_plane); - acrtc->crtc_id = -1; return res; } -- GitLab From c1199962f58528d6530db055b576cfaf5340b427 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 15:10:59 +1000 Subject: [PATCH 1009/2898] amdgpu/dc: fix indentation on a couple of returns. These were misaligned. found by the cocci ifcol script. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 3d65e2ab9bf1..cb94e18cc455 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1472,7 +1472,7 @@ static enum bp_result get_integrated_info_v11( DATA_TABLES(integratedsysteminfo)); if (info_v11 == NULL) - return BP_RESULT_BADBIOSTABLE; + return BP_RESULT_BADBIOSTABLE; info->gpu_cap_info = le32_to_cpu(info_v11->gpucapinfo); @@ -1753,7 +1753,7 @@ static struct integrated_info *bios_parser_create_integrated_info( } if (construct_integrated_info(bp, info) == BP_RESULT_OK) - return info; + return info; kfree(info); -- GitLab From c6fa531809f08af52406347e5351920cc2d55e42 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 15:11:00 +1000 Subject: [PATCH 1010/2898] amdgpu/dc: kill some deadcode in dc core. Moves one function to an inline, but kills a bunch of deadcode. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 91 ------------------------ drivers/gpu/drm/amd/display/dc/dc.h | 9 ++- 2 files changed, 4 insertions(+), 96 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c8235b041b5b..1ec8248546c5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -575,30 +575,6 @@ static bool construct(struct dc *dc, return false; } -/* -void ProgramPixelDurationV(unsigned int pixelClockInKHz ) -{ - fixed31_32 pixel_duration = Fixed31_32(100000000, pixelClockInKHz) * 10; - unsigned int pixDurationInPico = round(pixel_duration); - - DPG_PIPE_ARBITRATION_CONTROL1 arb_control; - - arb_control.u32All = ReadReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1); - arb_control.bits.PIXEL_DURATION = pixDurationInPico; - WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1, arb_control.u32All); - - arb_control.u32All = ReadReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1); - arb_control.bits.PIXEL_DURATION = pixDurationInPico; - WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1, arb_control.u32All); - - WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL2, 0x4000800); - WriteReg (mmDPGV0_REPEATER_PROGRAM, 0x11); - - WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL2, 0x4000800); - WriteReg (mmDPGV1_REPEATER_PROGRAM, 0x11); -} -*/ - /******************************************************************************* * Public functions ******************************************************************************/ @@ -1518,28 +1494,6 @@ struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i) return NULL; } -struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) -{ - return dc->links[link_index]; -} - -const struct graphics_object_id dc_get_link_id_at_index( - struct dc *dc, uint32_t link_index) -{ - return dc->links[link_index]->link_id; -} - -enum dc_irq_source dc_get_hpd_irq_source_at_index( - struct dc *dc, uint32_t link_index) -{ - return dc->links[link_index]->irq_source_hpd; -} - -const struct audio **dc_get_audios(struct dc *dc) -{ - return (const struct audio **)dc->res_pool->audios; -} - enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, @@ -1789,17 +1743,6 @@ struct dc_sink *dc_link_add_remote_sink( return NULL; } -void dc_link_set_sink(struct dc_link *link, struct dc_sink *sink) -{ - link->local_sink = sink; - - if (sink == NULL) { - link->type = dc_connection_none; - } else { - link->type = dc_connection_single; - } -} - void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) { int i; @@ -1825,37 +1768,3 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) } } } - -bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data) -{ - int i; - struct mem_input *mi = NULL; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (dc->res_pool->mis[i] != NULL) { - mi = dc->res_pool->mis[i]; - break; - } - } - if (mi == NULL) { - dm_error("no mem_input!\n"); - return false; - } - - if (dc->hwss.update_dchub) - dc->hwss.update_dchub(dc->hwseq, dh_data); - else - ASSERT(dc->hwss.update_dchub); - - - return true; - -} - -void dc_log_hw_state(struct dc *dc) -{ - - if (dc->hwss.log_hw_state) - dc->hwss.log_hw_state(dc); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9c0e00050753..259ac6918564 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -277,10 +277,6 @@ struct dc *dc_create(const struct dc_init_data *init_params); void dc_destroy(struct dc **dc); -bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data); - -void dc_log_hw_state(struct dc *dc); - /******************************************************************************* * Surface Interfaces ******************************************************************************/ @@ -866,7 +862,10 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); * boot time. They cannot be created or destroyed. * Use dc_get_caps() to get number of links. */ -struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); +static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) +{ + return dc->links[link_index]; +} /* Set backlight level of an embedded panel (eDP, LVDS). */ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, -- GitLab From 44858055bb28b1ba45dc05acecf9087bc4786701 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 15:11:01 +1000 Subject: [PATCH 1011/2898] amdgpu/dc: set a bunch of functions to static. All of these are unused outside the file they are in. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 2 +- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 3 +-- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 6 +++--- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 6d2f886f7ff4..aaaebd06d7ee 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -531,7 +531,7 @@ static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, return BP_RESULT_NORECORD; } -enum bp_result bios_parser_get_device_tag_record( +static enum bp_result bios_parser_get_device_tag_record( struct bios_parser *bp, ATOM_OBJECT *object, ATOM_CONNECTOR_DEVICE_TAG_RECORD **record) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 91f43a1b88ee..8ca6c3e4e65a 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1135,7 +1135,7 @@ bool dcn_validate_bandwidth( return false; } -unsigned int dcn_find_normalized_clock_vdd_Level( +static unsigned int dcn_find_normalized_clock_vdd_Level( const struct dc *dc, enum dm_pp_clock_type clocks_type, int clocks_in_khz) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1ec8248546c5..2dcff41c9b38 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -327,7 +327,7 @@ static void set_test_pattern( cust_pattern_size); } -void set_dither_option(struct dc_stream_state *stream, +static void set_dither_option(struct dc_stream_state *stream, enum dc_dither_option option) { struct bit_depth_reduction_params params; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 43ebd8941b77..d02dd9f2ef09 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -208,7 +208,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type) return false; } -enum ddc_transaction_type get_ddc_transaction_type( +static enum ddc_transaction_type get_ddc_transaction_type( enum signal_type sink_signal) { enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 3c323c1ea366..b735782b8fe0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1209,7 +1209,7 @@ static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate) return link_rate <= LINK_RATE_LOW; } -enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) +static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) { switch (lane_count) { case LANE_COUNT_FOUR: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 3427fb5b7e30..616431e25b79 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -110,7 +110,7 @@ void dp_enable_link_phy( dp_receiver_power_ctrl(link, true); } -bool edp_receiver_ready_T9(struct dc_link *link) +static bool edp_receiver_ready_T9(struct dc_link *link) { unsigned int tries = 0; unsigned char sinkstatus = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 6e940286c98d..526ec5c8eafd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -833,8 +833,7 @@ void dce_aud_wall_dto_setup( } } -bool dce_aud_endpoint_valid( - struct audio *audio) +static bool dce_aud_endpoint_valid(struct audio *audio) { uint32_t value; uint32_t port_connectivity; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index a09727fb405f..4fd49a16c3b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1183,7 +1183,7 @@ static const struct audio_clock_info audio_clock_info_table_48bpc[14] = { }; -union audio_cea_channels speakers_to_channels( +static union audio_cea_channels speakers_to_channels( struct audio_speaker_flags speaker_flags) { union audio_cea_channels cea_channels = {0}; @@ -1217,7 +1217,7 @@ union audio_cea_channels speakers_to_channels( return cea_channels; } -uint32_t calc_max_audio_packets_per_line( +static uint32_t calc_max_audio_packets_per_line( const struct audio_crtc_info *crtc_info) { uint32_t max_packets_per_line; @@ -1238,7 +1238,7 @@ uint32_t calc_max_audio_packets_per_line( return max_packets_per_line; } -void get_audio_clock_info( +static void get_audio_clock_info( enum dc_color_depth color_depth, uint32_t crtc_pixel_clock_in_khz, uint32_t actual_pixel_clock_in_khz, -- GitLab From 5d15ae23f8a42ce6728294808b6bd96c6b251a5f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 15:11:02 +1000 Subject: [PATCH 1012/2898] amdgpu/dc: kill a bunch of dead code. None of this code is used currently. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 101 ------------------ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 15 --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 34 ------ 3 files changed, 150 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2dcff41c9b38..d8820d6f79c6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1559,107 +1559,6 @@ void dc_resume(struct dc *dc) core_link_resume(dc->links[i]); } -bool dc_read_aux_dpcd( - struct dc *dc, - uint32_t link_index, - uint32_t address, - uint8_t *data, - uint32_t size) -{ - - struct dc_link *link = dc->links[link_index]; - enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->ddc, - false, - I2C_MOT_UNDEF, - address, - data, - size); - return r == DDC_RESULT_SUCESSFULL; -} - -bool dc_write_aux_dpcd( - struct dc *dc, - uint32_t link_index, - uint32_t address, - const uint8_t *data, - uint32_t size) -{ - struct dc_link *link = dc->links[link_index]; - - enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->ddc, - false, - I2C_MOT_UNDEF, - address, - data, - size); - return r == DDC_RESULT_SUCESSFULL; -} - -bool dc_read_aux_i2c( - struct dc *dc, - uint32_t link_index, - enum i2c_mot_mode mot, - uint32_t address, - uint8_t *data, - uint32_t size) -{ - - struct dc_link *link = dc->links[link_index]; - enum ddc_result r = dal_ddc_service_read_dpcd_data( - link->ddc, - true, - mot, - address, - data, - size); - return r == DDC_RESULT_SUCESSFULL; -} - -bool dc_write_aux_i2c( - struct dc *dc, - uint32_t link_index, - enum i2c_mot_mode mot, - uint32_t address, - const uint8_t *data, - uint32_t size) -{ - struct dc_link *link = dc->links[link_index]; - - enum ddc_result r = dal_ddc_service_write_dpcd_data( - link->ddc, - true, - mot, - address, - data, - size); - return r == DDC_RESULT_SUCESSFULL; -} - -bool dc_query_ddc_data( - struct dc *dc, - uint32_t link_index, - uint32_t address, - uint8_t *write_buf, - uint32_t write_size, - uint8_t *read_buf, - uint32_t read_size) { - - - struct dc_link *link = dc->links[link_index]; - - bool result = dal_ddc_service_query_ddc_data( - link->ddc, - address, - write_buf, - write_size, - read_buf, - read_size); - - return result; -} - bool dc_submit_i2c( struct dc *dc, uint32_t link_index, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d02dd9f2ef09..4a70948c91b1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1857,21 +1857,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, return true; } - -bool dc_link_set_abm_disable(const struct dc_link *link) -{ - struct dc *core_dc = link->ctx->dc; - struct abm *abm = core_dc->res_pool->abm; - - if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) - return false; - - abm->funcs->set_abm_immediate_disable(abm); - - return true; -} - - bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait) { struct dc *core_dc = link->ctx->dc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index b3bbafc8fd6a..3d620d3d0672 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -99,40 +99,6 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) return NULL; } -bool dc_sink_get_container_id(struct dc_sink *dc_sink, struct dc_container_id *container_id) -{ - if (dc_sink && container_id && dc_sink->dc_container_id) { - memmove(&container_id->guid, &dc_sink->dc_container_id->guid, - sizeof(container_id->guid)); - memmove(&container_id->portId, &dc_sink->dc_container_id->portId, - sizeof(container_id->portId)); - container_id->manufacturerName = dc_sink->dc_container_id->manufacturerName; - container_id->productCode = dc_sink->dc_container_id->productCode; - return true; - } - return false; -} - -bool dc_sink_set_container_id(struct dc_sink *dc_sink, const struct dc_container_id *container_id) -{ - if (dc_sink && container_id) { - if (!dc_sink->dc_container_id) - dc_sink->dc_container_id = kzalloc(sizeof(*dc_sink->dc_container_id), - GFP_KERNEL); - - if (dc_sink->dc_container_id) { - memmove(&dc_sink->dc_container_id->guid, &container_id->guid, - sizeof(container_id->guid)); - memmove(&dc_sink->dc_container_id->portId, &container_id->portId, - sizeof(container_id->portId)); - dc_sink->dc_container_id->manufacturerName = container_id->manufacturerName; - dc_sink->dc_container_id->productCode = container_id->productCode; - return true; - } - } - return false; -} - /******************************************************************************* * Protected functions - visible only inside of DC (not visible in DM) ******************************************************************************/ -- GitLab From 93052132568aedb5eda04deae51d6034738a4800 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:38:57 +1000 Subject: [PATCH 1013/2898] amdgpu/dc: convert dc_transfer to use a kref. Rolling your own atomic ref counts is frowned upon. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_surface.c | 17 +++++++++-------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/os_types.h | 2 ++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index ff07105bfd99..c2168dfacc8d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -161,17 +161,18 @@ struct dc_gamma *dc_create_gamma() void dc_transfer_func_retain(struct dc_transfer_func *tf) { - ASSERT(atomic_read(&tf->ref_count) > 0); - atomic_inc(&tf->ref_count); + kref_get(&tf->refcount); } -void dc_transfer_func_release(struct dc_transfer_func *tf) +static void dc_transfer_func_free(struct kref *kref) { - ASSERT(atomic_read(&tf->ref_count) > 0); - atomic_dec(&tf->ref_count); + struct dc_transfer_func *tf = container_of(kref, struct dc_transfer_func, refcount); + kfree(tf); +} - if (atomic_read(&tf->ref_count) == 0) - kfree(tf); +void dc_transfer_func_release(struct dc_transfer_func *tf) +{ + kref_put(&tf->refcount, dc_transfer_func_free); } struct dc_transfer_func *dc_create_transfer_func() @@ -181,7 +182,7 @@ struct dc_transfer_func *dc_create_transfer_func() if (tf == NULL) goto alloc_fail; - atomic_inc(&tf->ref_count); + kref_init(&tf->refcount); return tf; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 259ac6918564..f16c545a87ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -330,11 +330,11 @@ enum dc_transfer_func_predefined { }; struct dc_transfer_func { + struct kref refcount; struct dc_transfer_func_distributed_points tf_pts; enum dc_transfer_func_type type; enum dc_transfer_func_predefined tf; struct dc_context *ctx; - atomic_t ref_count; }; /* diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index 27ed2a61c3c8..e0cd5278aae8 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -32,6 +32,8 @@ #include #include +#include + #include "cgs_linux.h" #if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU) -- GitLab From 5c58ab0bd61b5c8538721f4200475c0af0e33efe Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:38:58 +1000 Subject: [PATCH 1014/2898] amdgpu/dc: convert dc_gamma to kref reference counting. Rolling your own reference counting is frowned upon. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_surface.c | 19 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 +--- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index c2168dfacc8d..0950075b6c54 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -129,18 +129,18 @@ void dc_plane_state_release(struct dc_plane_state *plane_state) void dc_gamma_retain(struct dc_gamma *gamma) { - ASSERT(atomic_read(&gamma->ref_count) > 0); - atomic_inc(&gamma->ref_count); + kref_get(&gamma->refcount); } -void dc_gamma_release(struct dc_gamma **gamma) +static void dc_gamma_free(struct kref *kref) { - ASSERT(atomic_read(&(*gamma)->ref_count) > 0); - atomic_dec(&(*gamma)->ref_count); - - if (atomic_read(&(*gamma)->ref_count) == 0) - kfree((*gamma)); + struct dc_gamma *gamma = container_of(kref, struct dc_gamma, refcount); + kfree(gamma); +} +void dc_gamma_release(struct dc_gamma **gamma) +{ + kref_put(&(*gamma)->refcount, dc_gamma_free); *gamma = NULL; } @@ -151,8 +151,7 @@ struct dc_gamma *dc_create_gamma() if (gamma == NULL) goto alloc_fail; - atomic_inc(&gamma->ref_count); - + kref_init(&gamma->refcount); return gamma; alloc_fail: diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 94f83cd9ab32..4ab109314e4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -420,6 +420,7 @@ enum dc_gamma_type { }; struct dc_gamma { + struct kref refcount; enum dc_gamma_type type; unsigned int num_entries; @@ -431,9 +432,6 @@ struct dc_gamma { /* private to DC core */ struct dc_context *ctx; - - /* private to dc_surface.c */ - atomic_t ref_count; }; /* Used by both ipp amd opp functions*/ -- GitLab From 4d090f0fae08ddaccf8caaf707f386d52b7f7a08 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:38:59 +1000 Subject: [PATCH 1015/2898] amdgpu/dc: use kref for dc_plane_state. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_surface.c | 20 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 0950075b6c54..d43783a45ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -71,8 +71,8 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc) if (NULL == plane_state) return NULL; + kref_init(&plane_state->refcount); construct(core_dc->ctx, plane_state); - atomic_inc(&plane_state->ref_count); return plane_state; } @@ -112,19 +112,19 @@ const struct dc_plane_status *dc_plane_get_status( void dc_plane_state_retain(struct dc_plane_state *plane_state) { - ASSERT(atomic_read(&plane_state->ref_count) > 0); - atomic_inc(&plane_state->ref_count); + kref_get(&plane_state->refcount); } -void dc_plane_state_release(struct dc_plane_state *plane_state) +static void dc_plane_state_free(struct kref *kref) { - ASSERT(atomic_read(&plane_state->ref_count) > 0); - atomic_dec(&plane_state->ref_count); + struct dc_plane_state *plane_state = container_of(kref, struct dc_plane_state, refcount); + destruct(plane_state); + kfree(plane_state); +} - if (atomic_read(&plane_state->ref_count) == 0) { - destruct(plane_state); - kfree(plane_state); - } +void dc_plane_state_release(struct dc_plane_state *plane_state) +{ + kref_put(&plane_state->refcount, dc_plane_state_free); } void dc_gamma_retain(struct dc_gamma *gamma) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f16c545a87ed..1adfa97bf3fd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -381,7 +381,7 @@ struct dc_plane_state { /* private to dc_surface.c */ enum dc_irq_source irq_source; - atomic_t ref_count; + struct kref refcount; }; struct dc_plane_info { -- GitLab From bfe0feb143151cce76411bb211c3eec0f6cff7ba Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:39:00 +1000 Subject: [PATCH 1016/2898] amdgpu/dc: convert dc_stream_state to kref. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_stream.c | 22 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index a99196414255..23df7bc020d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -118,20 +118,21 @@ static void destruct(struct dc_stream_state *stream) void dc_stream_retain(struct dc_stream_state *stream) { - ASSERT(atomic_read(&stream->ref_count) > 0); - atomic_inc(&stream->ref_count); + kref_get(&stream->refcount); +} + +static void dc_stream_free(struct kref *kref) +{ + struct dc_stream_state *stream = container_of(kref, struct dc_stream_state, refcount); + + destruct(stream); + kfree(stream); } void dc_stream_release(struct dc_stream_state *stream) { if (stream != NULL) { - ASSERT(atomic_read(&stream->ref_count) > 0); - atomic_dec(&stream->ref_count); - - if (atomic_read(&stream->ref_count) == 0) { - destruct(stream); - kfree(stream); - } + kref_put(&stream->refcount, dc_stream_free); } } @@ -149,10 +150,9 @@ struct dc_stream_state *dc_create_stream_for_sink( construct(stream, sink); - atomic_inc(&stream->ref_count); + kref_init(&stream->refcount); return stream; - } struct dc_stream_status *dc_stream_get_status( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1adfa97bf3fd..97f6f34f3d22 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -558,7 +558,7 @@ struct dc_stream_state { struct dc_stream_status status; /* from stream struct */ - atomic_t ref_count; + struct kref refcount; }; struct dc_stream_update { -- GitLab From cb56aceabd36ef42bc7e081c43dc55ef57efba7a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:39:01 +1000 Subject: [PATCH 1017/2898] amdgpu/dc: convert dc_sink to kref. Refcounts use krefs. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_sink.c | 20 +++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c index 3d620d3d0672..25fae38409ab 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_sink.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_sink.c @@ -63,19 +63,19 @@ static bool construct(struct dc_sink *sink, const struct dc_sink_init_data *init void dc_sink_retain(struct dc_sink *sink) { - ASSERT(atomic_read(&sink->ref_count) > 0); - atomic_inc(&sink->ref_count); + kref_get(&sink->refcount); } -void dc_sink_release(struct dc_sink *sink) +static void dc_sink_free(struct kref *kref) { - ASSERT(atomic_read(&sink->ref_count) > 0); - atomic_dec(&sink->ref_count); + struct dc_sink *sink = container_of(kref, struct dc_sink, refcount); + destruct(sink); + kfree(sink); +} - if (atomic_read(&sink->ref_count) == 0) { - destruct(sink); - kfree(sink); - } +void dc_sink_release(struct dc_sink *sink) +{ + kref_put(&sink->refcount, dc_sink_free); } struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) @@ -88,7 +88,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params) if (false == construct(sink, init_params)) goto construct_fail; - atomic_inc(&sink->ref_count); + kref_init(&sink->refcount); return sink; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 97f6f34f3d22..4ff543826476 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -971,7 +971,7 @@ struct dc_sink { struct dc_context *ctx; /* private to dc_sink.c */ - atomic_t ref_count; + struct kref refcount; }; void dc_sink_retain(struct dc_sink *sink); -- GitLab From 8ee5702afdd48b5864c46418ad310d6a23c8e9ab Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 Oct 2017 12:39:02 +1000 Subject: [PATCH 1018/2898] amdgpu/dc: use kref for dc_state. I'm not a huge fan of those copying around refcounts bits, might want to consider alternates, but this should work for now. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 26 +++++++++---------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 4 +-- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d8820d6f79c6..f41f15faf019 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -940,25 +940,25 @@ struct dc_state *dc_create_state(void) if (!context) return NULL; - atomic_inc(&context->ref_count); + kref_init(&context->refcount); return context; } void dc_retain_state(struct dc_state *context) { - ASSERT(atomic_read(&context->ref_count) > 0); - atomic_inc(&context->ref_count); + kref_get(&context->refcount); } -void dc_release_state(struct dc_state *context) +static void dc_state_free(struct kref *kref) { - ASSERT(atomic_read(&context->ref_count) > 0); - atomic_dec(&context->ref_count); + struct dc_state *context = container_of(kref, struct dc_state, refcount); + dc_resource_state_destruct(context); + kfree(context); +} - if (atomic_read(&context->ref_count) == 0) { - dc_resource_state_destruct(context); - kfree(context); - } +void dc_release_state(struct dc_state *context) +{ + kref_put(&context->refcount, dc_state_free); } static bool is_surface_in_context( @@ -1520,7 +1520,7 @@ void dc_set_power_state( struct dc *dc, enum dc_acpi_cm_power_state power_state) { - atomic_t ref_count; + struct kref refcount; switch (power_state) { case DC_ACPI_CM_POWER_STATE_D0: @@ -1538,12 +1538,12 @@ void dc_set_power_state( */ /* Preserve refcount */ - ref_count = dc->current_state->ref_count; + refcount = dc->current_state->refcount; dc_resource_state_destruct(dc->current_state); memset(dc->current_state, 0, sizeof(*dc->current_state)); - dc->current_state->ref_count = ref_count; + dc->current_state->refcount = refcount; break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 99a4d19f582d..77b3474a7c9e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2432,7 +2432,7 @@ void dc_resource_state_copy_construct( struct dc_state *dst_ctx) { int i, j; - atomic_t ref_count = dst_ctx->ref_count; + struct kref refcount = dst_ctx->refcount; *dst_ctx = *src_ctx; @@ -2455,7 +2455,7 @@ void dc_resource_state_copy_construct( } /* context refcount should not be overridden */ - dst_ctx->ref_count = ref_count; + dst_ctx->refcount = refcount; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index c47ce6b9fc6b..ff23f268fe02 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -267,7 +267,7 @@ struct dc_state { struct display_clock *dis_clk; - atomic_t ref_count; + struct kref refcount; }; #endif /* _CORE_TYPES_H_ */ -- GitLab From 878e832ade6fc315e6ea59d95824bbb0430c6e8d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 6 Oct 2017 11:19:24 -0400 Subject: [PATCH 1019/2898] acct.h: get rid of detritus unused forward declarations of structs Signed-off-by: Al Viro --- include/linux/acct.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/acct.h b/include/linux/acct.h index dccc2d4fe7de..3912a45b8c89 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h @@ -19,9 +19,6 @@ #ifdef CONFIG_BSD_PROCESS_ACCT -struct vfsmount; -struct super_block; -struct pacct_struct; struct pid_namespace; extern int acct_parm[]; /* for sysctl */ extern void acct_collect(long exitcode, int group_dead); -- GitLab From aaecaa0b5f31794f1711247da4b5883a6ff98163 Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Thu, 5 Oct 2017 17:54:31 -0700 Subject: [PATCH 1020/2898] tracing: Prepare to add preempt and irq trace events In preparation of adding irqsoff and preemptsoff enable and disable trace events, move required functions and code to make it easier to add these events in a later patch. This patch is just code movement and no functional change. Link: http://lkml.kernel.org/r/20171006005432.14244-2-joelaf@google.com Cc: Peter Zijlstra Cc: kernel-team@android.com Signed-off-by: Joel Fernandes Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_irqsoff.c | 100 ++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 7758bc0617cb..0e3033c00474 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -16,6 +16,7 @@ #include "trace.h" +#if defined(CONFIG_IRQSOFF_TRACER) || defined(CONFIG_PREEMPT_TRACER) static struct trace_array *irqsoff_trace __read_mostly; static int tracer_enabled __read_mostly; @@ -462,64 +463,44 @@ void time_hardirqs_off(unsigned long a0, unsigned long a1) #else /* !CONFIG_PROVE_LOCKING */ -/* - * Stubs: - */ - -void trace_softirqs_on(unsigned long ip) -{ -} - -void trace_softirqs_off(unsigned long ip) -{ -} - -inline void print_irqtrace_events(struct task_struct *curr) -{ -} - /* * We are only interested in hardirq on/off events: */ -void trace_hardirqs_on(void) +static inline void tracer_hardirqs_on(void) { if (!preempt_trace() && irq_trace()) stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1); } -EXPORT_SYMBOL(trace_hardirqs_on); -void trace_hardirqs_off(void) +static inline void tracer_hardirqs_off(void) { if (!preempt_trace() && irq_trace()) start_critical_timing(CALLER_ADDR0, CALLER_ADDR1); } -EXPORT_SYMBOL(trace_hardirqs_off); -__visible void trace_hardirqs_on_caller(unsigned long caller_addr) +static inline void tracer_hardirqs_on_caller(unsigned long caller_addr) { if (!preempt_trace() && irq_trace()) stop_critical_timing(CALLER_ADDR0, caller_addr); } -EXPORT_SYMBOL(trace_hardirqs_on_caller); -__visible void trace_hardirqs_off_caller(unsigned long caller_addr) +static inline void tracer_hardirqs_off_caller(unsigned long caller_addr) { if (!preempt_trace() && irq_trace()) start_critical_timing(CALLER_ADDR0, caller_addr); } -EXPORT_SYMBOL(trace_hardirqs_off_caller); #endif /* CONFIG_PROVE_LOCKING */ #endif /* CONFIG_IRQSOFF_TRACER */ #ifdef CONFIG_PREEMPT_TRACER -void trace_preempt_on(unsigned long a0, unsigned long a1) +static inline void tracer_preempt_on(unsigned long a0, unsigned long a1) { if (preempt_trace() && !irq_trace()) stop_critical_timing(a0, a1); } -void trace_preempt_off(unsigned long a0, unsigned long a1) +static inline void tracer_preempt_off(unsigned long a0, unsigned long a1) { if (preempt_trace() && !irq_trace()) start_critical_timing(a0, a1); @@ -781,3 +762,70 @@ __init static int init_irqsoff_tracer(void) return 0; } core_initcall(init_irqsoff_tracer); +#endif /* IRQSOFF_TRACER || PREEMPTOFF_TRACER */ + +#ifndef CONFIG_IRQSOFF_TRACER +static inline void tracer_hardirqs_on(void) { } +static inline void tracer_hardirqs_off(void) { } +static inline void tracer_hardirqs_on_caller(unsigned long caller_addr) { } +static inline void tracer_hardirqs_off_caller(unsigned long caller_addr) { } +#endif + +#ifndef CONFIG_PREEMPT_TRACER +static inline void tracer_preempt_on(unsigned long a0, unsigned long a1) { } +static inline void tracer_preempt_off(unsigned long a0, unsigned long a1) { } +#endif + +#if defined(CONFIG_TRACE_IRQFLAGS) && !defined(CONFIG_PROVE_LOCKING) +void trace_hardirqs_on(void) +{ + tracer_hardirqs_on(); +} +EXPORT_SYMBOL(trace_hardirqs_on); + +void trace_hardirqs_off(void) +{ + tracer_hardirqs_off(); +} +EXPORT_SYMBOL(trace_hardirqs_off); + +__visible void trace_hardirqs_on_caller(unsigned long caller_addr) +{ + tracer_hardirqs_on_caller(caller_addr); +} +EXPORT_SYMBOL(trace_hardirqs_on_caller); + +__visible void trace_hardirqs_off_caller(unsigned long caller_addr) +{ + tracer_hardirqs_off_caller(caller_addr); +} +EXPORT_SYMBOL(trace_hardirqs_off_caller); + +/* + * Stubs: + */ + +void trace_softirqs_on(unsigned long ip) +{ +} + +void trace_softirqs_off(unsigned long ip) +{ +} + +inline void print_irqtrace_events(struct task_struct *curr) +{ +} +#endif + +#ifdef CONFIG_PREEMPT_TRACER +void trace_preempt_on(unsigned long a0, unsigned long a1) +{ + tracer_preempt_on(a0, a1); +} + +void trace_preempt_off(unsigned long a0, unsigned long a1) +{ + tracer_preempt_off(a0, a1); +} +#endif -- GitLab From f3d0d8d938b4d71be1f7fb003ca2ac9250b3be4d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 24 Sep 2017 19:39:12 +0200 Subject: [PATCH 1021/2898] mtd: nand: gpio: Convert to use GPIO descriptors There is exactly one board in the kernel that defines platform data for the GPIO NAND driver. Use the feature to provide a lookup table for the GPIOs in the board file so we can convert the driver as a whole to just use GPIO descriptors. After this we can cut the use of and use the GPIO descriptor management from alone to grab and use the GPIOs used in the driver. I also created a local struct device *dev in the probe() function because I was getting annoyed with all the &pdev->dev dereferencing. Cc: arm@kernel.org Cc: Mike Rapoport Cc: Frans Klaver Cc: Gerhard Sittig Cc: Jamie Iles Signed-off-by: Linus Walleij Reviewed-by: Marek Vasut Acked-by: Jamie Iles Acked-by: Olof Johansson Acked-by: Robert Jarzmik Signed-off-by: Boris Brezillon --- arch/arm/mach-pxa/cm-x255.c | 19 ++++-- drivers/mtd/nand/gpio.c | 112 +++++++++++++++++----------------- include/linux/mtd/nand-gpio.h | 5 -- 3 files changed, 70 insertions(+), 66 deletions(-) diff --git a/arch/arm/mach-pxa/cm-x255.c b/arch/arm/mach-pxa/cm-x255.c index b592f79a1742..fa8e7dd4d898 100644 --- a/arch/arm/mach-pxa/cm-x255.c +++ b/arch/arm/mach-pxa/cm-x255.c @@ -14,7 +14,7 @@ #include #include #include - +#include #include #include @@ -176,6 +176,17 @@ static inline void cmx255_init_nor(void) {} #endif #if defined(CONFIG_MTD_NAND_GPIO) || defined(CONFIG_MTD_NAND_GPIO_MODULE) + +static struct gpiod_lookup_table cmx255_nand_gpiod_table = { + .dev_id = "gpio-nand", + .table = { + GPIO_LOOKUP("gpio-pxa", GPIO_NAND_CS, "nce", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-pxa", GPIO_NAND_CLE, "cle", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-pxa", GPIO_NAND_ALE, "ale", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-pxa", GPIO_NAND_RB, "rdy", GPIO_ACTIVE_HIGH), + }, +}; + static struct resource cmx255_nand_resource[] = { [0] = { .start = PXA_CS1_PHYS, @@ -198,11 +209,6 @@ static struct mtd_partition cmx255_nand_parts[] = { }; static struct gpio_nand_platdata cmx255_nand_platdata = { - .gpio_nce = GPIO_NAND_CS, - .gpio_cle = GPIO_NAND_CLE, - .gpio_ale = GPIO_NAND_ALE, - .gpio_rdy = GPIO_NAND_RB, - .gpio_nwp = -1, .parts = cmx255_nand_parts, .num_parts = ARRAY_SIZE(cmx255_nand_parts), .chip_delay = 25, @@ -220,6 +226,7 @@ static struct platform_device cmx255_nand = { static void __init cmx255_init_nand(void) { + gpiod_add_lookup_table(&cmx255_nand_gpiod_table); platform_device_register(&cmx255_nand); } #else diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index fd3648952b5a..484f7fbc3f7d 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,12 +31,16 @@ #include #include #include -#include struct gpiomtd { void __iomem *io_sync; struct nand_chip nand_chip; struct gpio_nand_platdata plat; + struct gpio_desc *nce; /* Optional chip enable */ + struct gpio_desc *cle; + struct gpio_desc *ale; + struct gpio_desc *rdy; + struct gpio_desc *nwp; /* Optional write protection */ }; static inline struct gpiomtd *gpio_nand_getpriv(struct mtd_info *mtd) @@ -78,11 +82,10 @@ static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) gpio_nand_dosync(gpiomtd); if (ctrl & NAND_CTRL_CHANGE) { - if (gpio_is_valid(gpiomtd->plat.gpio_nce)) - gpio_set_value(gpiomtd->plat.gpio_nce, - !(ctrl & NAND_NCE)); - gpio_set_value(gpiomtd->plat.gpio_cle, !!(ctrl & NAND_CLE)); - gpio_set_value(gpiomtd->plat.gpio_ale, !!(ctrl & NAND_ALE)); + if (gpiomtd->nce) + gpiod_set_value(gpiomtd->nce, !(ctrl & NAND_NCE)); + gpiod_set_value(gpiomtd->cle, !!(ctrl & NAND_CLE)); + gpiod_set_value(gpiomtd->ale, !!(ctrl & NAND_ALE)); gpio_nand_dosync(gpiomtd); } if (cmd == NAND_CMD_NONE) @@ -96,7 +99,7 @@ static int gpio_nand_devready(struct mtd_info *mtd) { struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd); - return gpio_get_value(gpiomtd->plat.gpio_rdy); + return gpiod_get_value(gpiomtd->rdy); } #ifdef CONFIG_OF @@ -123,12 +126,6 @@ static int gpio_nand_get_config_of(const struct device *dev, } } - plat->gpio_rdy = of_get_gpio(dev->of_node, 0); - plat->gpio_nce = of_get_gpio(dev->of_node, 1); - plat->gpio_ale = of_get_gpio(dev->of_node, 2); - plat->gpio_cle = of_get_gpio(dev->of_node, 3); - plat->gpio_nwp = of_get_gpio(dev->of_node, 4); - if (!of_property_read_u32(dev->of_node, "chip-delay", &val)) plat->chip_delay = val; @@ -201,10 +198,11 @@ static int gpio_nand_remove(struct platform_device *pdev) nand_release(nand_to_mtd(&gpiomtd->nand_chip)); - if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) - gpio_set_value(gpiomtd->plat.gpio_nwp, 0); - if (gpio_is_valid(gpiomtd->plat.gpio_nce)) - gpio_set_value(gpiomtd->plat.gpio_nce, 1); + /* Enable write protection and disable the chip */ + if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) + gpiod_set_value(gpiomtd->nwp, 0); + if (gpiomtd->nce && !IS_ERR(gpiomtd->nce)) + gpiod_set_value(gpiomtd->nce, 0); return 0; } @@ -215,66 +213,66 @@ static int gpio_nand_probe(struct platform_device *pdev) struct nand_chip *chip; struct mtd_info *mtd; struct resource *res; + struct device *dev = &pdev->dev; int ret = 0; - if (!pdev->dev.of_node && !dev_get_platdata(&pdev->dev)) + if (!dev->of_node && !dev_get_platdata(dev)) return -EINVAL; - gpiomtd = devm_kzalloc(&pdev->dev, sizeof(*gpiomtd), GFP_KERNEL); + gpiomtd = devm_kzalloc(dev, sizeof(*gpiomtd), GFP_KERNEL); if (!gpiomtd) return -ENOMEM; chip = &gpiomtd->nand_chip; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); + chip->IO_ADDR_R = devm_ioremap_resource(dev, res); if (IS_ERR(chip->IO_ADDR_R)) return PTR_ERR(chip->IO_ADDR_R); res = gpio_nand_get_io_sync(pdev); if (res) { - gpiomtd->io_sync = devm_ioremap_resource(&pdev->dev, res); + gpiomtd->io_sync = devm_ioremap_resource(dev, res); if (IS_ERR(gpiomtd->io_sync)) return PTR_ERR(gpiomtd->io_sync); } - ret = gpio_nand_get_config(&pdev->dev, &gpiomtd->plat); + ret = gpio_nand_get_config(dev, &gpiomtd->plat); if (ret) return ret; - if (gpio_is_valid(gpiomtd->plat.gpio_nce)) { - ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nce, - "NAND NCE"); - if (ret) - return ret; - gpio_direction_output(gpiomtd->plat.gpio_nce, 1); + /* Just enable the chip */ + gpiomtd->nce = devm_gpiod_get_optional(dev, "nce", GPIOD_OUT_HIGH); + if (IS_ERR(gpiomtd->nce)) + return PTR_ERR(gpiomtd->nce); + + /* We disable write protection once we know probe() will succeed */ + gpiomtd->nwp = devm_gpiod_get_optional(dev, "nwp", GPIOD_OUT_LOW); + if (IS_ERR(gpiomtd->nwp)) { + ret = PTR_ERR(gpiomtd->nwp); + goto out_ce; } - if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) { - ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nwp, - "NAND NWP"); - if (ret) - return ret; + gpiomtd->nwp = devm_gpiod_get(dev, "ale", GPIOD_OUT_LOW); + if (IS_ERR(gpiomtd->nwp)) { + ret = PTR_ERR(gpiomtd->nwp); + goto out_ce; } - ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_ale, "NAND ALE"); - if (ret) - return ret; - gpio_direction_output(gpiomtd->plat.gpio_ale, 0); + gpiomtd->cle = devm_gpiod_get(dev, "cle", GPIOD_OUT_LOW); + if (IS_ERR(gpiomtd->cle)) { + ret = PTR_ERR(gpiomtd->cle); + goto out_ce; + } - ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_cle, "NAND CLE"); - if (ret) - return ret; - gpio_direction_output(gpiomtd->plat.gpio_cle, 0); - - if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) { - ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_rdy, - "NAND RDY"); - if (ret) - return ret; - gpio_direction_input(gpiomtd->plat.gpio_rdy); - chip->dev_ready = gpio_nand_devready; + gpiomtd->rdy = devm_gpiod_get_optional(dev, "rdy", GPIOD_IN); + if (IS_ERR(gpiomtd->rdy)) { + ret = PTR_ERR(gpiomtd->rdy); + goto out_ce; } + /* Using RDY pin */ + if (gpiomtd->rdy) + chip->dev_ready = gpio_nand_devready; nand_set_flash_node(chip, pdev->dev.of_node); chip->IO_ADDR_W = chip->IO_ADDR_R; @@ -285,12 +283,13 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->cmd_ctrl = gpio_nand_cmd_ctrl; mtd = nand_to_mtd(chip); - mtd->dev.parent = &pdev->dev; + mtd->dev.parent = dev; platform_set_drvdata(pdev, gpiomtd); - if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) - gpio_direction_output(gpiomtd->plat.gpio_nwp, 1); + /* Disable write protection, if wired up */ + if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) + gpiod_direction_output(gpiomtd->nwp, 1); ret = nand_scan(mtd, 1); if (ret) @@ -305,8 +304,11 @@ static int gpio_nand_probe(struct platform_device *pdev) return 0; err_wp: - if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) - gpio_set_value(gpiomtd->plat.gpio_nwp, 0); + if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) + gpiod_set_value(gpiomtd->nwp, 0); +out_ce: + if (gpiomtd->nce && !IS_ERR(gpiomtd->nce)) + gpiod_set_value(gpiomtd->nce, 0); return ret; } diff --git a/include/linux/mtd/nand-gpio.h b/include/linux/mtd/nand-gpio.h index be4f45d89be2..98f71908212d 100644 --- a/include/linux/mtd/nand-gpio.h +++ b/include/linux/mtd/nand-gpio.h @@ -4,11 +4,6 @@ #include struct gpio_nand_platdata { - int gpio_nce; - int gpio_nwp; - int gpio_cle; - int gpio_ale; - int gpio_rdy; void (*adjust_parts)(struct gpio_nand_platdata *, size_t); struct mtd_partition *parts; unsigned int num_parts; -- GitLab From 8c4cdce8b1ab044a2ee1d86d5a086f67e32b3c10 Mon Sep 17 00:00:00 2001 From: Abhishek Sahu Date: Mon, 25 Sep 2017 13:21:25 +0530 Subject: [PATCH 1022/2898] mtd: nand: qcom: add command elements in BAM transaction All the QPIC register read/write through BAM DMA requires command descriptor which contains the array of command elements. Reviewed-by: Archit Taneja Signed-off-by: Abhishek Sahu Signed-off-by: Boris Brezillon --- drivers/mtd/nand/qcom_nandc.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c index 3baddfc997d1..3d1d506d3d18 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c @@ -22,6 +22,7 @@ #include #include #include +#include /* NANDc reg offsets */ #define NAND_FLASH_CMD 0x00 @@ -199,6 +200,7 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_##reg, \ */ #define dev_cmd_reg_addr(nandc, reg) ((nandc)->props->dev_cmd_reg_start + (reg)) +#define QPIC_PER_CW_CMD_ELEMENTS 32 #define QPIC_PER_CW_CMD_SGL 32 #define QPIC_PER_CW_DATA_SGL 8 @@ -221,8 +223,13 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_##reg, \ /* * This data type corresponds to the BAM transaction which will be used for all * NAND transfers. + * @bam_ce - the array of BAM command elements * @cmd_sgl - sgl for NAND BAM command pipe * @data_sgl - sgl for NAND BAM consumer/producer pipe + * @bam_ce_pos - the index in bam_ce which is available for next sgl + * @bam_ce_start - the index in bam_ce which marks the start position ce + * for current sgl. It will be used for size calculation + * for current sgl * @cmd_sgl_pos - current index in command sgl. * @cmd_sgl_start - start index in command sgl. * @tx_sgl_pos - current index in data sgl for tx. @@ -231,8 +238,11 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_##reg, \ * @rx_sgl_start - start index in data sgl for rx. */ struct bam_transaction { + struct bam_cmd_element *bam_ce; struct scatterlist *cmd_sgl; struct scatterlist *data_sgl; + u32 bam_ce_pos; + u32 bam_ce_start; u32 cmd_sgl_pos; u32 cmd_sgl_start; u32 tx_sgl_pos; @@ -462,7 +472,8 @@ alloc_bam_transaction(struct qcom_nand_controller *nandc) bam_txn_size = sizeof(*bam_txn) + num_cw * - ((sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) + + ((sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS) + + (sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) + (sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL)); bam_txn_buf = devm_kzalloc(nandc->dev, bam_txn_size, GFP_KERNEL); @@ -472,6 +483,10 @@ alloc_bam_transaction(struct qcom_nand_controller *nandc) bam_txn = bam_txn_buf; bam_txn_buf += sizeof(*bam_txn); + bam_txn->bam_ce = bam_txn_buf; + bam_txn_buf += + sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw; + bam_txn->cmd_sgl = bam_txn_buf; bam_txn_buf += sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw; @@ -489,6 +504,8 @@ static void clear_bam_transaction(struct qcom_nand_controller *nandc) if (!nandc->props->is_bam) return; + bam_txn->bam_ce_pos = 0; + bam_txn->bam_ce_start = 0; bam_txn->cmd_sgl_pos = 0; bam_txn->cmd_sgl_start = 0; bam_txn->tx_sgl_pos = 0; -- GitLab From 8d6b6d7e135e9bbfc923d34a45cb0e72695e63ed Mon Sep 17 00:00:00 2001 From: Abhishek Sahu Date: Mon, 25 Sep 2017 13:21:26 +0530 Subject: [PATCH 1023/2898] mtd: nand: qcom: support for command descriptor formation 1. Add the function for command descriptor preparation which will be used only by BAM DMA and it will form the DMA descriptors containing command elements 2. DMA_PREP_CMD flag should be used for forming command DMA descriptors Reviewed-by: Archit Taneja Signed-off-by: Abhishek Sahu Signed-off-by: Boris Brezillon --- drivers/mtd/nand/qcom_nandc.c | 108 +++++++++++++++++++++++++++++----- 1 file changed, 92 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c index 3d1d506d3d18..2656c1ac5646 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c @@ -200,6 +200,14 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_##reg, \ */ #define dev_cmd_reg_addr(nandc, reg) ((nandc)->props->dev_cmd_reg_start + (reg)) +/* Returns the NAND register physical address */ +#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset)) + +/* Returns the dma address for reg read buffer */ +#define reg_buf_dma_addr(chip, vaddr) \ + ((chip)->reg_read_dma + \ + ((uint8_t *)(vaddr) - (uint8_t *)(chip)->reg_read_buf)) + #define QPIC_PER_CW_CMD_ELEMENTS 32 #define QPIC_PER_CW_CMD_SGL 32 #define QPIC_PER_CW_DATA_SGL 8 @@ -317,7 +325,8 @@ struct nandc_regs { * controller * @dev: parent device * @base: MMIO base - * @base_dma: physical base address of controller registers + * @base_phys: physical base address of controller registers + * @base_dma: dma base address of controller registers * @core_clk: controller clock * @aon_clk: another controller clock * @@ -350,6 +359,7 @@ struct qcom_nand_controller { struct device *dev; void __iomem *base; + phys_addr_t base_phys; dma_addr_t base_dma; struct clk *core_clk; @@ -750,6 +760,66 @@ static int prepare_bam_async_desc(struct qcom_nand_controller *nandc, return 0; } +/* + * Prepares the command descriptor for BAM DMA which will be used for NAND + * register reads and writes. The command descriptor requires the command + * to be formed in command element type so this function uses the command + * element from bam transaction ce array and fills the same with required + * data. A single SGL can contain multiple command elements so + * NAND_BAM_NEXT_SGL will be used for starting the separate SGL + * after the current command element. + */ +static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, + int reg_off, const void *vaddr, + int size, unsigned int flags) +{ + int bam_ce_size; + int i, ret; + struct bam_cmd_element *bam_ce_buffer; + struct bam_transaction *bam_txn = nandc->bam_txn; + + bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos]; + + /* fill the command desc */ + for (i = 0; i < size; i++) { + if (read) + bam_prep_ce(&bam_ce_buffer[i], + nandc_reg_phys(nandc, reg_off + 4 * i), + BAM_READ_COMMAND, + reg_buf_dma_addr(nandc, + (__le32 *)vaddr + i)); + else + bam_prep_ce_le32(&bam_ce_buffer[i], + nandc_reg_phys(nandc, reg_off + 4 * i), + BAM_WRITE_COMMAND, + *((__le32 *)vaddr + i)); + } + + bam_txn->bam_ce_pos += size; + + /* use the separate sgl after this command */ + if (flags & NAND_BAM_NEXT_SGL) { + bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start]; + bam_ce_size = (bam_txn->bam_ce_pos - + bam_txn->bam_ce_start) * + sizeof(struct bam_cmd_element); + sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos], + bam_ce_buffer, bam_ce_size); + bam_txn->cmd_sgl_pos++; + bam_txn->bam_ce_start = bam_txn->bam_ce_pos; + + if (flags & NAND_BAM_NWD) { + ret = prepare_bam_async_desc(nandc, nandc->cmd_chan, + DMA_PREP_FENCE | + DMA_PREP_CMD); + if (ret) + return ret; + } + } + + return 0; +} + /* * Prepares the data descriptor for BAM DMA which will be used for NAND * data reads and writes. @@ -868,19 +938,22 @@ static int read_reg_dma(struct qcom_nand_controller *nandc, int first, { bool flow_control = false; void *vaddr; - int size; - if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) - flow_control = true; + vaddr = nandc->reg_read_buf + nandc->reg_read_pos; + nandc->reg_read_pos += num_regs; if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1) first = dev_cmd_reg_addr(nandc, first); - size = num_regs * sizeof(u32); - vaddr = nandc->reg_read_buf + nandc->reg_read_pos; - nandc->reg_read_pos += num_regs; + if (nandc->props->is_bam) + return prep_bam_dma_desc_cmd(nandc, true, first, vaddr, + num_regs, flags); - return prep_adm_dma_desc(nandc, true, first, vaddr, size, flow_control); + if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) + flow_control = true; + + return prep_adm_dma_desc(nandc, true, first, vaddr, + num_regs * sizeof(u32), flow_control); } /* @@ -897,13 +970,9 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first, bool flow_control = false; struct nandc_regs *regs = nandc->regs; void *vaddr; - int size; vaddr = offset_to_nandc_reg(regs, first); - if (first == NAND_FLASH_CMD) - flow_control = true; - if (first == NAND_ERASED_CW_DETECT_CFG) { if (flags & NAND_ERASED_CW_SET) vaddr = ®s->erased_cw_detect_cfg_set; @@ -920,10 +989,15 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first, if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD) first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD); - size = num_regs * sizeof(u32); + if (nandc->props->is_bam) + return prep_bam_dma_desc_cmd(nandc, false, first, vaddr, + num_regs, flags); + + if (first == NAND_FLASH_CMD) + flow_control = true; - return prep_adm_dma_desc(nandc, false, first, vaddr, size, - flow_control); + return prep_adm_dma_desc(nandc, false, first, vaddr, + num_regs * sizeof(u32), flow_control); } /* @@ -1187,7 +1261,8 @@ static int submit_descs(struct qcom_nand_controller *nandc) } if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) { - r = prepare_bam_async_desc(nandc, nandc->cmd_chan, 0); + r = prepare_bam_async_desc(nandc, nandc->cmd_chan, + DMA_PREP_CMD); if (r) return r; } @@ -2722,6 +2797,7 @@ static int qcom_nandc_probe(struct platform_device *pdev) if (IS_ERR(nandc->base)) return PTR_ERR(nandc->base); + nandc->base_phys = res->start; nandc->base_dma = phys_to_dma(dev, (phys_addr_t)res->start); nandc->core_clk = devm_clk_get(dev, "core"); -- GitLab From 143b0ab97d7a40df399cfbc6e925107bed1c7953 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Thu, 28 Sep 2017 11:46:23 +0200 Subject: [PATCH 1024/2898] mtd: nand: atmel: Avoid ECC errors when leaving backup mode During backup mode, the contents of all registers will be cleared as the SoC will be completely powered down. For a product that boots on NAND Flash memory, the bootloader will obviously use the related controller to read the Flash and correct any detected error in the memory, before handling back control to the kernel's resuming entry point. But it does not clean the NAND controller registers after use and on its side the kernel driver expects the error locator to be powered down and in a clean state. Add a resume hook for the PMECC error locator, and reset its registers. Signed-off-by: Romain Izard Signed-off-by: Boris Brezillon --- drivers/mtd/nand/atmel/nand-controller.c | 3 +++ drivers/mtd/nand/atmel/pmecc.c | 17 +++++++++-------- drivers/mtd/nand/atmel/pmecc.h | 1 + 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c index 7bc8d20ed885..29182160bb5f 100644 --- a/drivers/mtd/nand/atmel/nand-controller.c +++ b/drivers/mtd/nand/atmel/nand-controller.c @@ -2529,6 +2529,9 @@ static __maybe_unused int atmel_nand_controller_resume(struct device *dev) struct atmel_nand_controller *nc = dev_get_drvdata(dev); struct atmel_nand *nand; + if (nc->pmecc) + atmel_pmecc_reset(nc->pmecc); + list_for_each_entry(nand, &nc->chips, node) { int i; diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/atmel/pmecc.c index 146af8218314..0a3f12141c45 100644 --- a/drivers/mtd/nand/atmel/pmecc.c +++ b/drivers/mtd/nand/atmel/pmecc.c @@ -765,6 +765,13 @@ void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user, } EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes); +void atmel_pmecc_reset(struct atmel_pmecc *pmecc) +{ + writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL); + writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL); +} +EXPORT_SYMBOL_GPL(atmel_pmecc_reset); + int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op) { struct atmel_pmecc *pmecc = user->pmecc; @@ -797,10 +804,7 @@ EXPORT_SYMBOL_GPL(atmel_pmecc_enable); void atmel_pmecc_disable(struct atmel_pmecc_user *user) { - struct atmel_pmecc *pmecc = user->pmecc; - - writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL); - writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL); + atmel_pmecc_reset(user->pmecc); mutex_unlock(&user->pmecc->lock); } EXPORT_SYMBOL_GPL(atmel_pmecc_disable); @@ -855,10 +859,7 @@ static struct atmel_pmecc *atmel_pmecc_create(struct platform_device *pdev, /* Disable all interrupts before registering the PMECC handler. */ writel(0xffffffff, pmecc->regs.base + ATMEL_PMECC_IDR); - - /* Reset the ECC engine */ - writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL); - writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL); + atmel_pmecc_reset(pmecc); return pmecc; } diff --git a/drivers/mtd/nand/atmel/pmecc.h b/drivers/mtd/nand/atmel/pmecc.h index a8ddbfca2ea5..817e0dd9fd15 100644 --- a/drivers/mtd/nand/atmel/pmecc.h +++ b/drivers/mtd/nand/atmel/pmecc.h @@ -61,6 +61,7 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc, struct atmel_pmecc_user_req *req); void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user); +void atmel_pmecc_reset(struct atmel_pmecc *pmecc); int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op); void atmel_pmecc_disable(struct atmel_pmecc_user *user); int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user); -- GitLab From 263c68afb521b2ff1ca386d312d155ff3d22b69a Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 29 Sep 2017 15:34:24 +0200 Subject: [PATCH 1025/2898] mtd: nand: pxa3xx_nand: Update Kconfig information More and more SoCs use the pxa3xx_nand driver for their controller but the list of them was not updated. This patch add the last SoCs using the driver. Signed-off-by: Gregory CLEMENT Signed-off-by: Boris Brezillon --- drivers/mtd/nand/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 3f2036f31da4..bb48aafed9a2 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -317,8 +317,11 @@ config MTD_NAND_PXA3xx tristate "NAND support on PXA3xx and Armada 370/XP" depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU help + This enables the driver for the NAND flash device found on - PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2). + PXA3xx processors (NFCv1) and also on 32-bit Armada + platforms (XP, 370, 375, 38x, 39x) and 64-bit Armada + platforms (7K, 8K) (NFCv2). config MTD_NAND_SLC_LPC32XX tristate "NXP LPC32xx SLC Controller" -- GitLab From 7963f58cbf3a722c93f946c80a12f185b86dc45c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 29 Sep 2017 23:12:57 +0900 Subject: [PATCH 1026/2898] mtd: nand: denali: fix setup_data_interface to meet tCCS delay The WE_2_RE register specifies the number of clock cycles inserted between the rising edge of #WE and the falling edge of #RE. The current setup_data_interface implementation takes care of tWHR, but tCCS is missing. Wait for max(tCSS, tWHR) to meet the spec. With setup_data_interface() properly programmed, the Denali NAND controller can observe the timing, so NAND_WAIT_TCCS flag is unneeded. Clarify this in the comment block. Signed-off-by: Masahiro Yamada Signed-off-by: Boris Brezillon --- drivers/mtd/nand/denali.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 0b268ec88435..5124f8ae8c04 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1004,8 +1004,14 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, tmp |= FIELD_PREP(RE_2_RE__VALUE, re_2_re); iowrite32(tmp, denali->reg + RE_2_RE); - /* tWHR -> WE_2_RE */ - we_2_re = DIV_ROUND_UP(timings->tWHR_min, t_clk); + /* + * tCCS, tWHR -> WE_2_RE + * + * With WE_2_RE properly set, the Denali controller automatically takes + * care of the delay; the driver need not set NAND_WAIT_TCCS. + */ + we_2_re = DIV_ROUND_UP(max(timings->tCCS_min, timings->tWHR_min), + t_clk); we_2_re = min_t(int, we_2_re, TWHR2_AND_WE_2_RE__WE_2_RE); tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE); -- GitLab From b8640c5b8bef7e24fe54d2713f4c91b563a65c55 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 4 Oct 2017 14:19:03 +0200 Subject: [PATCH 1027/2898] mtd: nand: sh_flctl: Use of_device_get_match_data() helper Use the of_device_get_match_data() helper instead of open coding. While at it, make config const so the cast can be dropped. Signed-off-by: Geert Uytterhoeven Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sh_flctl.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index e7f3c98487e6..3c5008a4f5f3 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -1094,14 +1094,11 @@ MODULE_DEVICE_TABLE(of, of_flctl_match); static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) { - const struct of_device_id *match; - struct flctl_soc_config *config; + const struct flctl_soc_config *config; struct sh_flctl_platform_data *pdata; - match = of_match_device(of_flctl_match, dev); - if (match) - config = (struct flctl_soc_config *)match->data; - else { + config = of_device_get_match_data(dev); + if (!config) { dev_err(dev, "%s: no OF configuration attached\n", __func__); return NULL; } -- GitLab From b330213d98c357859b686b77ad0db9e98fe73763 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 25 Sep 2017 16:53:50 +0200 Subject: [PATCH 1028/2898] Documentation: devicetree: add pxa3xx compatible and syscon property Document the new pxa3xx_nand driver compatible string for A7k/A8k SoCs that need to access system controller registers in order to enable the NAND controller through the use of a phandle pointed to by the 'marvell,system-controller' property. Signed-off-by: Miquel Raynal Signed-off-by: Boris Brezillon --- Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt index d9b655f11048..d4ee4da58463 100644 --- a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt +++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt @@ -5,9 +5,13 @@ Required properties: - compatible: Should be set to one of the following: marvell,pxa3xx-nand marvell,armada370-nand + marvell,armada-8k-nand - reg: The register base for the controller - interrupts: The interrupt to map - #address-cells: Set to <1> if the node includes partitions + - marvell,system-controller: Set to retrieve the syscon node that handles + NAND controller related registers (only required + with marvell,armada-8k-nand compatible). Optional properties: -- GitLab From fc256f5789cbb58bb5aa308a781be46a270bcd98 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 25 Sep 2017 16:53:51 +0200 Subject: [PATCH 1029/2898] mtd: nand: pxa3xx: enable NAND controller if the SoC needs it Marvell recent SoCs like A7k/A8k do not boot with NAND flash controller activated by default. Enabling the controller is a matter of writing in a system controller register that may also be used for other NAND related choices. This change is needed to stay bootloader independent. Signed-off-by: Miquel Raynal Signed-off-by: Boris Brezillon --- drivers/mtd/nand/pxa3xx_nand.c | 41 ++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 85cff68643e0..90b9a9ccbe60 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #define CHIP_DELAY_TIMEOUT msecs_to_jiffies(200) #define NAND_STOP_DELAY msecs_to_jiffies(40) @@ -45,6 +47,10 @@ */ #define INIT_BUFFER_SIZE 2048 +/* System control register and bit to enable NAND on some SoCs */ +#define GENCONF_SOC_DEVICE_MUX 0x208 +#define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0) + /* registers and bit definitions */ #define NDCR (0x00) /* Control register */ #define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */ @@ -174,6 +180,7 @@ enum { enum pxa3xx_nand_variant { PXA3XX_NAND_VARIANT_PXA, PXA3XX_NAND_VARIANT_ARMADA370, + PXA3XX_NAND_VARIANT_ARMADA_8K, }; struct pxa3xx_nand_host { @@ -425,6 +432,10 @@ static const struct of_device_id pxa3xx_nand_dt_ids[] = { .compatible = "marvell,armada370-nand", .data = (void *)PXA3XX_NAND_VARIANT_ARMADA370, }, + { + .compatible = "marvell,armada-8k-nand", + .data = (void *)PXA3XX_NAND_VARIANT_ARMADA_8K, + }, {} }; MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids); @@ -825,7 +836,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) info->retcode = ERR_UNCORERR; if (status & NDSR_CORERR) { info->retcode = ERR_CORERR; - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 && + if ((info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) && info->ecc_bch) info->ecc_err_cnt = NDSR_ERR_CNT(status); else @@ -888,7 +900,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) nand_writel(info, NDCB0, info->ndcb2); /* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */ - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) nand_writel(info, NDCB0, info->ndcb3); } @@ -1671,7 +1684,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) chip->options |= NAND_BUSWIDTH_16; /* Device detection must be done with ECC disabled */ - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) nand_writel(info, NDECCCTRL, 0x0); if (pdata->flash_bbt) @@ -1709,7 +1723,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) * (aka splitted) command handling, */ if (mtd->writesize > PAGE_CHUNK_SIZE) { - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) { + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) { chip->cmdfunc = nand_cmdfunc_extended; } else { dev_err(&info->pdev->dev, @@ -1928,6 +1943,24 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev) if (!of_id) return 0; + /* + * Some SoCs like A7k/A8k need to enable manually the NAND + * controller to avoid being bootloader dependent. This is done + * through the use of a single bit in the System Functions registers. + */ + if (pxa3xx_nand_get_variant(pdev) == PXA3XX_NAND_VARIANT_ARMADA_8K) { + struct regmap *sysctrl_base = syscon_regmap_lookup_by_phandle( + pdev->dev.of_node, "marvell,system-controller"); + u32 reg; + + if (IS_ERR(sysctrl_base)) + return PTR_ERR(sysctrl_base); + + regmap_read(sysctrl_base, GENCONF_SOC_DEVICE_MUX, ®); + reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN; + regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg); + } + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; -- GitLab From b37b3fd33d034470749db55d1ccd7331bd35bdca Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 22 Sep 2017 16:47:40 +0900 Subject: [PATCH 1030/2898] acpi nfit: Enable to show what feature is supported via ND_CMD_CALL for nfit_test Though nfit_test need to show what feature is supported via ND_CMD_CALL on device/nfit/dsm_mask, currently there is no way to tell it. This patch makes to enable it. Signed-off-by: Yasunori Goto Reviewed-by: Vishal Verma Signed-off-by: Dan Williams --- drivers/acpi/nfit/core.c | 1 + drivers/acpi/nfit/nfit.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 9c2c49b6a240..3369bb8fd9ba 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -1645,6 +1645,7 @@ static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc) int i; nd_desc->cmd_mask = acpi_desc->bus_cmd_force_en; + nd_desc->bus_dsm_mask = acpi_desc->bus_nfit_cmd_force_en; adev = to_acpi_dev(acpi_desc); if (!adev) return; diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index 54292db61262..f2c6380bdbb2 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -167,6 +167,7 @@ struct acpi_nfit_desc { unsigned int init_complete:1; unsigned long dimm_cmd_force_en; unsigned long bus_cmd_force_en; + unsigned long bus_nfit_cmd_force_en; int (*blk_do_io)(struct nd_blk_region *ndbr, resource_size_t dpa, void *iobuf, u64 len, int rw); }; -- GitLab From 10246dc84dfcabb05f2d29d442c9de967fd61270 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Fri, 22 Sep 2017 16:48:38 +0900 Subject: [PATCH 1031/2898] acpi nfit: nfit_test supports translate SPA To test ndctl list which use interface of Translate SPA, nfit_test needs to emulates it. This test module searches region which includes SPA and returns 1 dimm handle which is last one. Signed-off-by: Yasunori Goto Reviewed-by: Vishal Verma Signed-off-by: Dan Williams --- tools/testing/nvdimm/test/nfit.c | 104 ++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index bef419d4266d..3a3bad348d56 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -342,6 +342,84 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err, return 0; } +struct region_search_spa { + u64 addr; + struct nd_region *region; +}; + +static int is_region_device(struct device *dev) +{ + return !strncmp(dev->kobj.name, "region", 6); +} + +static int nfit_test_search_region_spa(struct device *dev, void *data) +{ + struct region_search_spa *ctx = data; + struct nd_region *nd_region; + resource_size_t ndr_end; + + if (!is_region_device(dev)) + return 0; + + nd_region = to_nd_region(dev); + ndr_end = nd_region->ndr_start + nd_region->ndr_size; + + if (ctx->addr >= nd_region->ndr_start && ctx->addr < ndr_end) { + ctx->region = nd_region; + return 1; + } + + return 0; +} + +static int nfit_test_search_spa(struct nvdimm_bus *bus, + struct nd_cmd_translate_spa *spa) +{ + int ret; + struct nd_region *nd_region = NULL; + struct nvdimm *nvdimm = NULL; + struct nd_mapping *nd_mapping = NULL; + struct region_search_spa ctx = { + .addr = spa->spa, + .region = NULL, + }; + u64 dpa; + + ret = device_for_each_child(&bus->dev, &ctx, + nfit_test_search_region_spa); + + if (!ret) + return -ENODEV; + + nd_region = ctx.region; + + dpa = ctx.addr - nd_region->ndr_start; + + /* + * last dimm is selected for test + */ + nd_mapping = &nd_region->mapping[nd_region->ndr_mappings - 1]; + nvdimm = nd_mapping->nvdimm; + + spa->devices[0].nfit_device_handle = handle[nvdimm->id]; + spa->num_nvdimms = 1; + spa->devices[0].dpa = dpa; + + return 0; +} + +static int nfit_test_cmd_translate_spa(struct nvdimm_bus *bus, + struct nd_cmd_translate_spa *spa, unsigned int buf_len) +{ + if (buf_len < spa->translate_length) + return -EINVAL; + + if (nfit_test_search_spa(bus, spa) < 0 || !spa->num_nvdimms) + spa->status = 2; + + return 0; +} + static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len) { static const struct nd_smart_payload smart_data = { @@ -449,6 +527,26 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, } } else { struct ars_state *ars_state = &t->ars_state; + struct nd_cmd_pkg *call_pkg = buf; + + if (!nd_desc) + return -ENOTTY; + + if (cmd == ND_CMD_CALL) { + func = call_pkg->nd_command; + + buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out; + buf = (void *) call_pkg->nd_payload; + + switch (func) { + case NFIT_CMD_TRANSLATE_SPA: + rc = nfit_test_cmd_translate_spa( + acpi_desc->nvdimm_bus, buf, buf_len); + return rc; + default: + return -ENOTTY; + } + } if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask)) return -ENOTTY; @@ -1430,7 +1528,9 @@ static void nfit_test0_setup(struct nfit_test *t) set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); + set_bit(ND_CMD_CALL, &acpi_desc->bus_cmd_force_en); set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en); + set_bit(NFIT_CMD_TRANSLATE_SPA, &acpi_desc->bus_nfit_cmd_force_en); } static void nfit_test1_setup(struct nfit_test *t) @@ -1613,10 +1713,12 @@ static int nfit_ctl_test(struct device *dev) .cmd_mask = 1UL << ND_CMD_ARS_CAP | 1UL << ND_CMD_ARS_START | 1UL << ND_CMD_ARS_STATUS - | 1UL << ND_CMD_CLEAR_ERROR, + | 1UL << ND_CMD_CLEAR_ERROR + | 1UL << ND_CMD_CALL, .module = THIS_MODULE, .provider_name = "ACPI.NFIT", .ndctl = acpi_nfit_ctl, + .bus_dsm_mask = 1UL << NFIT_CMD_TRANSLATE_SPA, }, .dev = &adev->dev, }; -- GitLab From 4b27db7e26cdb9deb4a211e963e2993fde0110cb Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 24 Sep 2017 09:57:34 -0700 Subject: [PATCH 1032/2898] acpi, nfit: add support for the _LSI, _LSR, and _LSW label methods ACPI 6.2 adds support for named methods to access the label storage area of an NVDIMM. We prefer these new methods if available and otherwise fallback to the NVDIMM_FAMILY_INTEL _DSMs. The kernel ioctls, ND_IOCTL_{GET,SET}_CONFIG_{SIZE,DATA}, remain generic and the driver translates the 'package' payloads into the NVDIMM_FAMILY_INTEL 'buffer' format to maintain compatibility with existing userspace and keep the output buffer parsing code in the driver common. The output payloads are mostly compatible save for the 'label area locked' status that moves from the 'config_size' (_LSI) command to the 'config_read' (_LSR) command status. Cc: Jeff Moyer Cc: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/acpi/nfit/core.c | 213 ++++++++++++++++++++++++++++++++++++++- drivers/acpi/nfit/nfit.h | 3 + drivers/nvdimm/dimm.c | 2 + 3 files changed, 214 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 3369bb8fd9ba..ebe0857ac346 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -183,13 +183,33 @@ static int xlat_bus_status(void *buf, unsigned int cmd, u32 status) return 0; } -static int xlat_nvdimm_status(void *buf, unsigned int cmd, u32 status) +#define ACPI_LABELS_LOCKED 3 + +static int xlat_nvdimm_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd, + u32 status) { + struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); + switch (cmd) { case ND_CMD_GET_CONFIG_SIZE: + /* + * In the _LSI, _LSR, _LSW case the locked status is + * communicated via the read/write commands + */ + if (nfit_mem->has_lsi) + break; + if (status >> 16 & ND_CONFIG_LOCKED) return -EACCES; break; + case ND_CMD_GET_CONFIG_DATA: + if (nfit_mem->has_lsr && status == ACPI_LABELS_LOCKED) + return -EACCES; + break; + case ND_CMD_SET_CONFIG_DATA: + if (nfit_mem->has_lsw && status == ACPI_LABELS_LOCKED) + return -EACCES; + break; default: break; } @@ -205,13 +225,156 @@ static int xlat_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd, { if (!nvdimm) return xlat_bus_status(buf, cmd, status); - return xlat_nvdimm_status(buf, cmd, status); + return xlat_nvdimm_status(nvdimm, buf, cmd, status); +} + +/* convert _LS{I,R} packages to the buffer object acpi_nfit_ctl expects */ +static union acpi_object *pkg_to_buf(union acpi_object *pkg) +{ + int i; + void *dst; + size_t size = 0; + union acpi_object *buf = NULL; + + if (pkg->type != ACPI_TYPE_PACKAGE) { + WARN_ONCE(1, "BIOS bug, unexpected element type: %d\n", + pkg->type); + goto err; + } + + for (i = 0; i < pkg->package.count; i++) { + union acpi_object *obj = &pkg->package.elements[i]; + + if (obj->type == ACPI_TYPE_INTEGER) + size += 4; + else if (obj->type == ACPI_TYPE_BUFFER) + size += obj->buffer.length; + else { + WARN_ONCE(1, "BIOS bug, unexpected element type: %d\n", + obj->type); + goto err; + } + } + + buf = ACPI_ALLOCATE(sizeof(*buf) + size); + if (!buf) + goto err; + + dst = buf + 1; + buf->type = ACPI_TYPE_BUFFER; + buf->buffer.length = size; + buf->buffer.pointer = dst; + for (i = 0; i < pkg->package.count; i++) { + union acpi_object *obj = &pkg->package.elements[i]; + + if (obj->type == ACPI_TYPE_INTEGER) { + memcpy(dst, &obj->integer.value, 4); + dst += 4; + } else if (obj->type == ACPI_TYPE_BUFFER) { + memcpy(dst, obj->buffer.pointer, obj->buffer.length); + dst += obj->buffer.length; + } + } +err: + ACPI_FREE(pkg); + return buf; +} + +static union acpi_object *int_to_buf(union acpi_object *integer) +{ + union acpi_object *buf = ACPI_ALLOCATE(sizeof(*buf) + 4); + void *dst = NULL; + + if (!buf) + goto err; + + if (integer->type != ACPI_TYPE_INTEGER) { + WARN_ONCE(1, "BIOS bug, unexpected element type: %d\n", + integer->type); + goto err; + } + + dst = buf + 1; + buf->type = ACPI_TYPE_BUFFER; + buf->buffer.length = 4; + buf->buffer.pointer = dst; + memcpy(dst, &integer->integer.value, 4); +err: + ACPI_FREE(integer); + return buf; +} + +static union acpi_object *acpi_label_write(acpi_handle handle, u32 offset, + u32 len, void *data) +{ + acpi_status rc; + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_object_list input = { + .count = 3, + .pointer = (union acpi_object []) { + [0] = { + .integer.type = ACPI_TYPE_INTEGER, + .integer.value = offset, + }, + [1] = { + .integer.type = ACPI_TYPE_INTEGER, + .integer.value = len, + }, + [2] = { + .buffer.type = ACPI_TYPE_BUFFER, + .buffer.pointer = data, + .buffer.length = len, + }, + }, + }; + + rc = acpi_evaluate_object(handle, "_LSW", &input, &buf); + if (ACPI_FAILURE(rc)) + return NULL; + return int_to_buf(buf.pointer); +} + +static union acpi_object *acpi_label_read(acpi_handle handle, u32 offset, + u32 len) +{ + acpi_status rc; + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_object_list input = { + .count = 2, + .pointer = (union acpi_object []) { + [0] = { + .integer.type = ACPI_TYPE_INTEGER, + .integer.value = offset, + }, + [1] = { + .integer.type = ACPI_TYPE_INTEGER, + .integer.value = len, + }, + }, + }; + + rc = acpi_evaluate_object(handle, "_LSR", &input, &buf); + if (ACPI_FAILURE(rc)) + return NULL; + return pkg_to_buf(buf.pointer); +} + +static union acpi_object *acpi_label_info(acpi_handle handle) +{ + acpi_status rc; + struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; + + rc = acpi_evaluate_object(handle, "_LSI", NULL, &buf); + if (ACPI_FAILURE(rc)) + return NULL; + return pkg_to_buf(buf.pointer); } int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) { struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); + struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); union acpi_object in_obj, in_buf, *out_obj; const struct nd_cmd_desc *desc = NULL; struct device *dev = acpi_desc->dev; @@ -235,7 +398,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, } if (nvdimm) { - struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); struct acpi_device *adev = nfit_mem->adev; if (!adev) @@ -294,7 +456,21 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, in_buf.buffer.pointer, min_t(u32, 256, in_buf.buffer.length), true); - out_obj = acpi_evaluate_dsm(handle, guid, 1, func, &in_obj); + /* call the BIOS, prefer the named methods over _DSM if available */ + if (cmd == ND_CMD_GET_CONFIG_SIZE && nfit_mem->has_lsi) + out_obj = acpi_label_info(handle); + else if (cmd == ND_CMD_GET_CONFIG_DATA && nfit_mem->has_lsr) { + struct nd_cmd_get_config_data_hdr *p = buf; + + out_obj = acpi_label_read(handle, p->in_offset, p->in_length); + } else if (cmd == ND_CMD_SET_CONFIG_DATA && nfit_mem->has_lsw) { + struct nd_cmd_set_config_hdr *p = buf; + + out_obj = acpi_label_write(handle, p->in_offset, p->in_length, + p->in_buf); + } else + out_obj = acpi_evaluate_dsm(handle, guid, 1, func, &in_obj); + if (!out_obj) { dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name, cmd_name); @@ -1431,6 +1607,7 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, { struct acpi_device *adev, *adev_dimm; struct device *dev = acpi_desc->dev; + union acpi_object *obj; unsigned long dsm_mask; const guid_t *guid; int i; @@ -1496,6 +1673,27 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, if (acpi_check_dsm(adev_dimm->handle, guid, 1, 1ULL << i)) set_bit(i, &nfit_mem->dsm_mask); + obj = acpi_label_info(adev_dimm->handle); + if (obj) { + ACPI_FREE(obj); + nfit_mem->has_lsi = 1; + dev_dbg(dev, "%s: has _LSI\n", dev_name(&adev_dimm->dev)); + } + + obj = acpi_label_read(adev_dimm->handle, 0, 0); + if (obj) { + ACPI_FREE(obj); + nfit_mem->has_lsr = 1; + dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev)); + } + + obj = acpi_label_write(adev_dimm->handle, 0, 0, NULL); + if (obj) { + ACPI_FREE(obj); + nfit_mem->has_lsw = 1; + dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev)); + } + return 0; } @@ -1574,6 +1772,13 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc) if (nfit_mem->family == NVDIMM_FAMILY_INTEL) cmd_mask |= nfit_mem->dsm_mask; + if (nfit_mem->has_lsi) + set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask); + if (nfit_mem->has_lsr) + set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask); + if (nfit_mem->has_lsw) + set_bit(ND_CMD_SET_CONFIG_DATA, &cmd_mask); + flush = nfit_mem->nfit_flush ? nfit_mem->nfit_flush->flush : NULL; nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem, diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index f2c6380bdbb2..3976d649f27c 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -140,6 +140,9 @@ struct nfit_mem { struct resource *flush_wpq; unsigned long dsm_mask; int family; + u32 has_lsi:1; + u32 has_lsr:1; + u32 has_lsw:1; }; struct acpi_nfit_desc { diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c index 98466d762c8f..f8913b8124b6 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c @@ -55,6 +55,8 @@ static int nvdimm_probe(struct device *dev) goto err; rc = nvdimm_init_config_data(ndd); + if (rc == -EACCES) + nvdimm_set_locked(dev); if (rc) goto err; -- GitLab From efbf6f50ada168b68f5e3de474bc8dee4a02d046 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 25 Sep 2017 10:24:26 -0700 Subject: [PATCH 1033/2898] libnvdimm: introduce 'flags' attribute for DIMM 'lock' and 'alias' status Given that we now how have two mechanisms for a DIMM to indicate that it is locked: * NVDIMM_FAMILY_INTEL 'get_config_size' _DSM command * ACPI 6.2 Label Storage Read / Write commands ...export the generic libnvdimm DIMM status in a new 'flags' attribute. This attribute can also reflect the 'alias' state which indicates whether the nvdimm core is enforcing labels for aliased-region-capacity that the given dimm is an interleave-set member. Signed-off-by: Dan Williams --- drivers/nvdimm/dimm_devs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index 5f1385b96b13..097794d9f786 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -331,6 +331,17 @@ static ssize_t commands_show(struct device *dev, } static DEVICE_ATTR_RO(commands); +static ssize_t flags_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvdimm *nvdimm = to_nvdimm(dev); + + return sprintf(buf, "%s%s\n", + test_bit(NDD_ALIASING, &nvdimm->flags) ? "alias " : "", + test_bit(NDD_LOCKED, &nvdimm->flags) ? "lock " : ""); +} +static DEVICE_ATTR_RO(flags); + static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -372,6 +383,7 @@ static DEVICE_ATTR_RO(available_slots); static struct attribute *nvdimm_attributes[] = { &dev_attr_state.attr, + &dev_attr_flags.attr, &dev_attr_commands.attr, &dev_attr_available_slots.attr, NULL, -- GitLab From 65853a1da3c181f85d368daa40abb91025c368fc Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 5 Oct 2017 10:55:57 +0100 Subject: [PATCH 1034/2898] libnvdimm, namespace: make a couple of functions static The functions create_namespace_pmem and create_namespace_blk are local to the source and do not need to be in global scope, so make them static. Cleans up sparse warnings: symbol 'create_namespace_pmem' was not declared. Should it be static? symbol 'create_namespace_blk' was not declared. Should it be static? Signed-off-by: Colin Ian King Reviewed-by: Johannes Thumshirn Signed-off-by: Dan Williams --- drivers/nvdimm/namespace_devs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index 0af988739a06..bb3ba8cf24d4 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -1875,7 +1875,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id) * @nspm: target namespace to create * @nd_label: target pmem namespace label to evaluate */ -struct device *create_namespace_pmem(struct nd_region *nd_region, +static struct device *create_namespace_pmem(struct nd_region *nd_region, struct nd_namespace_index *nsindex, struct nd_namespace_label *nd_label) { @@ -2186,7 +2186,7 @@ static int add_namespace_resource(struct nd_region *nd_region, return i; } -struct device *create_namespace_blk(struct nd_region *nd_region, +static struct device *create_namespace_blk(struct nd_region *nd_region, struct nd_namespace_label *nd_label, int count) { -- GitLab From dfea7e18276c6a702860c927298e15d4a4c2569d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 8 Oct 2017 21:04:43 +0300 Subject: [PATCH 1035/2898] platform/x86: peaq-wmi: Revert Blacklist Lenovo ideapad 700-15ISK In favour of new approach this reverts commit ff74972e966bfc586cea116f976866858d1b0fec. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/peaq-wmi.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/platform/x86/peaq-wmi.c b/drivers/platform/x86/peaq-wmi.c index e09f37cdeb3c..bc98ef95514a 100644 --- a/drivers/platform/x86/peaq-wmi.c +++ b/drivers/platform/x86/peaq-wmi.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include @@ -65,22 +64,9 @@ static void peaq_wmi_poll(struct input_polled_dev *dev) } } -static const struct dmi_system_id peaq_blacklist[] __initconst = { - { - /* Lenovo ideapad 700-15ISK does not have Dolby button */ - .ident = "Lenovo ideapad 700-15ISK", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "80RU"), - }, - }, - {} -}; - static int __init peaq_wmi_init(void) { - if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID) || - dmi_check_system(peaq_blacklist)) + if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID)) return -ENODEV; peaq_poll_dev = input_allocate_polled_device(); -- GitLab From 3b95206110a2c13076c3a7fa8ddeae36c2dbcf42 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 5 Oct 2017 20:04:04 +0200 Subject: [PATCH 1036/2898] platform/x86: peaq-wmi: Add DMI check before binding to the WMI interface It seems that the WMI GUID used by the PEAQ 2-in-1 WMI hotkeys is not as unique as a GUID should be and is used on some other devices too. This is causing spurious key-press reports on these other devices. This commits adds a DMI check to the PEAQ 2-in-1 WMI hotkeys driver to ensure that it is actually running on a PEAQ 2-in-1, fixing the spurious key-presses on these other devices. BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1497861 BugLink: https://bugzilla.suse.com/attachment.cgi?id=743182 Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/peaq-wmi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/platform/x86/peaq-wmi.c b/drivers/platform/x86/peaq-wmi.c index bc98ef95514a..67fa3fa32011 100644 --- a/drivers/platform/x86/peaq-wmi.c +++ b/drivers/platform/x86/peaq-wmi.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -64,8 +65,22 @@ static void peaq_wmi_poll(struct input_polled_dev *dev) } } +/* Some other devices (Shuttle XS35) use the same WMI GUID for other purposes */ +static const struct dmi_system_id peaq_dmi_table[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"), + DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"), + }, + }, +}; + static int __init peaq_wmi_init(void) { + /* WMI GUID is not unique, also check for a DMI match */ + if (!dmi_check_system(peaq_dmi_table)) + return -ENODEV; + if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID)) return -ENODEV; @@ -86,6 +101,9 @@ static int __init peaq_wmi_init(void) static void __exit peaq_wmi_exit(void) { + if (!dmi_check_system(peaq_dmi_table)) + return; + if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID)) return; -- GitLab From 687d25a2bae98b32534d2119419ed1eea6e53bbb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 5 Oct 2017 16:31:47 +0200 Subject: [PATCH 1037/2898] MAINTAINERS: Add entry for the PEAQ WMI hotkeys driver Add an entry to make myself the maintainer of the PEAQ WMI hotkeys driver. Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 08b96f77f618..037a8d2a7f4e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10521,6 +10521,12 @@ S: Maintained F: crypto/pcrypt.c F: include/crypto/pcrypt.h +PEAQ WMI HOTKEYS DRIVER +M: Hans de Goede +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/peaq-wmi.c + PER-CPU MEMORY ALLOCATOR M: Tejun Heo M: Christoph Lameter -- GitLab From f5b33d94c1eca23802e3ac76b0788ba59e44a481 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 26 Jan 2017 17:16:26 +0200 Subject: [PATCH 1038/2898] platform/x86: intel_ips: Simplify error handling via devres API Use devm_ and pcim_ functions to make error handling simpler and code smaller and tidier. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 62 ++++++++------------------------ 1 file changed, 15 insertions(+), 47 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 58dcee562d64..063d9a1624b4 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -296,7 +296,7 @@ static struct ips_mcp_limits ips_ulv_limits = { struct ips_driver { struct pci_dev *dev; - void *regmap; + void __iomem *regmap; struct task_struct *monitor; struct task_struct *adjust; struct dentry *debug_root; @@ -1517,62 +1517,45 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) if (dmi_check_system(ips_blacklist)) return -ENODEV; - ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL); + ips = devm_kzalloc(&dev->dev, sizeof(*ips), GFP_KERNEL); if (!ips) return -ENOMEM; - pci_set_drvdata(dev, ips); + spin_lock_init(&ips->turbo_status_lock); ips->dev = dev; ips->limits = ips_detect_cpu(ips); if (!ips->limits) { dev_info(&dev->dev, "IPS not supported on this CPU\n"); - ret = -ENXIO; - goto error_free; + return -ENXIO; } - spin_lock_init(&ips->turbo_status_lock); - - ret = pci_enable_device(dev); + ret = pcim_enable_device(dev); if (ret) { dev_err(&dev->dev, "can't enable PCI device, aborting\n"); - goto error_free; + return ret; } - if (!pci_resource_start(dev, 0)) { - dev_err(&dev->dev, "TBAR not assigned, aborting\n"); - ret = -ENXIO; - goto error_free; - } - - ret = pci_request_regions(dev, "ips thermal sensor"); + ret = pcim_iomap_regions(dev, 1 << 0, pci_name(dev)); if (ret) { - dev_err(&dev->dev, "thermal resource busy, aborting\n"); - goto error_free; - } - - - ips->regmap = ioremap(pci_resource_start(dev, 0), - pci_resource_len(dev, 0)); - if (!ips->regmap) { dev_err(&dev->dev, "failed to map thermal regs, aborting\n"); - ret = -EBUSY; - goto error_release; + return ret; } + ips->regmap = pcim_iomap_table(dev)[0]; + + pci_set_drvdata(dev, ips); tse = thm_readb(THM_TSE); if (tse != TSE_EN) { dev_err(&dev->dev, "thermal device not enabled (0x%02x), aborting\n", tse); - ret = -ENXIO; - goto error_unmap; + return -ENXIO; } trc = thm_readw(THM_TRC); trc_required_mask = TRC_CORE1_EN | TRC_CORE_PWR | TRC_MCH_EN; if ((trc & trc_required_mask) != trc_required_mask) { dev_err(&dev->dev, "thermal reporting for required devices not enabled, aborting\n"); - ret = -ENXIO; - goto error_unmap; + return -ENXIO; } if (trc & TRC_CORE2_EN) @@ -1602,8 +1585,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) rdmsrl(PLATFORM_INFO, platform_info); if (!(platform_info & PLATFORM_TDP)) { dev_err(&dev->dev, "platform indicates TDP override unavailable, aborting\n"); - ret = -ENODEV; - goto error_unmap; + return -ENODEV; } /* @@ -1615,7 +1597,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) ips); if (ret) { dev_err(&dev->dev, "request irq failed, aborting\n"); - goto error_unmap; + return ret; } /* Enable aux, hot & critical interrupts */ @@ -1673,12 +1655,6 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) kthread_stop(ips->adjust); error_free_irq: free_irq(ips->dev->irq, ips); -error_unmap: - iounmap(ips->regmap); -error_release: - pci_release_regions(dev); -error_free: - kfree(ips); return ret; } @@ -1714,22 +1690,14 @@ static void ips_remove(struct pci_dev *dev) kthread_stop(ips->adjust); if (ips->monitor) kthread_stop(ips->monitor); - iounmap(ips->regmap); - pci_release_regions(dev); - kfree(ips); dev_dbg(&dev->dev, "IPS driver removed\n"); } -static void ips_shutdown(struct pci_dev *dev) -{ -} - static struct pci_driver ips_pci_driver = { .name = "intel ips", .id_table = ips_id_table, .probe = ips_probe, .remove = ips_remove, - .shutdown = ips_shutdown, }; module_pci_driver(ips_pci_driver); -- GitLab From 8b8bd6d255c960e1a935837c26fbc598e91eba24 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Oct 2017 11:28:01 +0300 Subject: [PATCH 1039/2898] platform/x86: intel_ips: Switch to new PCI IRQ allocation API This makes code cleaner. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 063d9a1624b4..6f6900065bc2 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -297,6 +297,8 @@ static struct ips_mcp_limits ips_ulv_limits = { struct ips_driver { struct pci_dev *dev; void __iomem *regmap; + int irq; + struct task_struct *monitor; struct task_struct *adjust; struct dentry *debug_root; @@ -1592,9 +1594,13 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) * IRQ handler for ME interaction * Note: don't use MSI here as the PCH has bugs. */ - pci_disable_msi(dev); - ret = request_irq(dev->irq, ips_irq_handler, IRQF_SHARED, "ips", - ips); + ret = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY); + if (ret < 0) + return ret; + + ips->irq = pci_irq_vector(dev, 0); + + ret = request_irq(ips->irq, ips_irq_handler, IRQF_SHARED, "ips", ips); if (ret) { dev_err(&dev->dev, "request irq failed, aborting\n"); return ret; @@ -1654,7 +1660,8 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) error_thread_cleanup: kthread_stop(ips->adjust); error_free_irq: - free_irq(ips->dev->irq, ips); + free_irq(ips->irq, ips); + pci_free_irq_vectors(dev); return ret; } @@ -1685,7 +1692,8 @@ static void ips_remove(struct pci_dev *dev) wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override); wrmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); - free_irq(ips->dev->irq, ips); + free_irq(ips->irq, ips); + pci_free_irq_vectors(dev); if (ips->adjust) kthread_stop(ips->adjust); if (ips->monitor) -- GitLab From 512f4665d839e1b4d5ebc8e446a4b948cbac681d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Oct 2017 10:46:40 +0300 Subject: [PATCH 1040/2898] platform/x86: intel_ips: Use PCI_VDEVICE() macro Intel vendor ID is defined globally, thus we may use PCI_VDEVICE(). Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 6f6900065bc2..489ff6fff9f9 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -1482,8 +1482,7 @@ ips_link_to_i915_driver(void) EXPORT_SYMBOL_GPL(ips_link_to_i915_driver); static const struct pci_device_id ips_id_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), }, { 0, } }; -- GitLab From d2fa170a2543bfd0c3d91ae0a6f808a5becda5c9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Oct 2017 10:55:40 +0300 Subject: [PATCH 1041/2898] platform/x86: intel_ips: Keep pointer to struct device ...instead of keeping pointer to struct pci_dev. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 51 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 489ff6fff9f9..27e70637e40b 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -295,7 +295,7 @@ static struct ips_mcp_limits ips_ulv_limits = { }; struct ips_driver { - struct pci_dev *dev; + struct device *dev; void __iomem *regmap; int irq; @@ -596,7 +596,7 @@ static void ips_disable_gpu_turbo(struct ips_driver *ips) return; if (!ips->gpu_turbo_disable()) - dev_err(&ips->dev->dev, "failed to disable graphics turbo\n"); + dev_err(ips->dev, "failed to disable graphics turbo\n"); else ips->__gpu_turbo_on = false; } @@ -651,8 +651,7 @@ static bool cpu_exceeded(struct ips_driver *ips, int cpu) spin_unlock_irqrestore(&ips->turbo_status_lock, flags); if (ret) - dev_info(&ips->dev->dev, - "CPU power or thermal limit exceeded\n"); + dev_info(ips->dev, "CPU power or thermal limit exceeded\n"); return ret; } @@ -771,7 +770,7 @@ static int ips_adjust(void *data) struct ips_driver *ips = data; unsigned long flags; - dev_dbg(&ips->dev->dev, "starting ips-adjust thread\n"); + dev_dbg(ips->dev, "starting ips-adjust thread\n"); /* * Adjust CPU and GPU clamps every 5s if needed. Doing it more @@ -818,7 +817,7 @@ static int ips_adjust(void *data) schedule_timeout_interruptible(msecs_to_jiffies(IPS_ADJUST_PERIOD)); } while (!kthread_should_stop()); - dev_dbg(&ips->dev->dev, "ips-adjust thread stopped\n"); + dev_dbg(ips->dev, "ips-adjust thread stopped\n"); return 0; } @@ -978,7 +977,7 @@ static int ips_monitor(void *data) mchp_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL); if (!mcp_samples || !ctv1_samples || !ctv2_samples || !mch_samples || !cpu_samples || !mchp_samples) { - dev_err(&ips->dev->dev, + dev_err(ips->dev, "failed to allocate sample array, ips disabled\n"); kfree(mcp_samples); kfree(ctv1_samples); @@ -1099,7 +1098,8 @@ static int ips_monitor(void *data) ITV_ME_SEQNO_SHIFT; if (cur_seqno == last_seqno && time_after(jiffies, seqno_timestamp + HZ)) { - dev_warn(&ips->dev->dev, "ME failed to update for more than 1s, likely hung\n"); + dev_warn(ips->dev, + "ME failed to update for more than 1s, likely hung\n"); } else { seqno_timestamp = get_jiffies_64(); last_seqno = cur_seqno; @@ -1121,7 +1121,7 @@ static int ips_monitor(void *data) del_timer_sync(&timer); destroy_timer_on_stack(&timer); - dev_dbg(&ips->dev->dev, "ips-monitor thread stopped\n"); + dev_dbg(ips->dev, "ips-monitor thread stopped\n"); return 0; } @@ -1130,17 +1130,17 @@ static int ips_monitor(void *data) #define THM_DUMPW(reg) \ { \ u16 val = thm_readw(reg); \ - dev_dbg(&ips->dev->dev, #reg ": 0x%04x\n", val); \ + dev_dbg(ips->dev, #reg ": 0x%04x\n", val); \ } #define THM_DUMPL(reg) \ { \ u32 val = thm_readl(reg); \ - dev_dbg(&ips->dev->dev, #reg ": 0x%08x\n", val); \ + dev_dbg(ips->dev, #reg ": 0x%08x\n", val); \ } #define THM_DUMPQ(reg) \ { \ u64 val = thm_readq(reg); \ - dev_dbg(&ips->dev->dev, #reg ": 0x%016x\n", val); \ + dev_dbg(ips->dev, #reg ": 0x%016x\n", val); \ } static void dump_thermal_info(struct ips_driver *ips) @@ -1148,7 +1148,7 @@ static void dump_thermal_info(struct ips_driver *ips) u16 ptl; ptl = thm_readw(THM_PTL); - dev_dbg(&ips->dev->dev, "Processor temp limit: %d\n", ptl); + dev_dbg(ips->dev, "Processor temp limit: %d\n", ptl); THM_DUMPW(THM_CTA); THM_DUMPW(THM_TRC); @@ -1177,8 +1177,8 @@ static irqreturn_t ips_irq_handler(int irq, void *arg) if (!tses && !tes) return IRQ_NONE; - dev_info(&ips->dev->dev, "TSES: 0x%02x\n", tses); - dev_info(&ips->dev->dev, "TES: 0x%02x\n", tes); + dev_info(ips->dev, "TSES: 0x%02x\n", tses); + dev_info(ips->dev, "TES: 0x%02x\n", tes); /* STS update from EC? */ if (tes & 1) { @@ -1216,8 +1216,8 @@ static irqreturn_t ips_irq_handler(int irq, void *arg) /* Thermal trip */ if (tses) { - dev_warn(&ips->dev->dev, - "thermal trip occurred, tses: 0x%04x\n", tses); + dev_warn(ips->dev, "thermal trip occurred, tses: 0x%04x\n", + tses); thm_writeb(THM_TSES, tses); } @@ -1332,8 +1332,7 @@ static void ips_debugfs_init(struct ips_driver *ips) ips->debug_root = debugfs_create_dir("ips", NULL); if (!ips->debug_root) { - dev_err(&ips->dev->dev, - "failed to create debugfs entries: %ld\n", + dev_err(ips->dev, "failed to create debugfs entries: %ld\n", PTR_ERR(ips->debug_root)); return; } @@ -1347,8 +1346,7 @@ static void ips_debugfs_init(struct ips_driver *ips) ips->debug_root, node, &ips_debugfs_ops); if (!ent) { - dev_err(&ips->dev->dev, - "failed to create debug file: %ld\n", + dev_err(ips->dev, "failed to create debug file: %ld\n", PTR_ERR(ent)); goto err_cleanup; } @@ -1375,7 +1373,7 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) u16 tdp; if (!(boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 37)) { - dev_info(&ips->dev->dev, "Non-IPS CPU detected.\n"); + dev_info(ips->dev, "Non-IPS CPU detected.\n"); goto out; } @@ -1397,7 +1395,7 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) else if (strstr(boot_cpu_data.x86_model_id, "CPU U")) limits = &ips_ulv_limits; else { - dev_info(&ips->dev->dev, "No CPUID match found.\n"); + dev_info(ips->dev, "No CPUID match found.\n"); goto out; } @@ -1406,7 +1404,8 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) /* Sanity check TDP against CPU */ if (limits->core_power_limit != (tdp / 8) * 1000) { - dev_info(&ips->dev->dev, "CPU TDP doesn't match expected value (found %d, expected %d)\n", + dev_info(ips->dev, + "CPU TDP doesn't match expected value (found %d, expected %d)\n", tdp / 8, limits->core_power_limit / 1000); limits->core_power_limit = (tdp / 8) * 1000; } @@ -1461,7 +1460,7 @@ ips_gpu_turbo_enabled(struct ips_driver *ips) { if (!ips->gpu_busy && late_i915_load) { if (ips_get_i915_syms(ips)) { - dev_info(&ips->dev->dev, + dev_info(ips->dev, "i915 driver attached, reenabling gpu turbo\n"); ips->gpu_turbo_enabled = !(thm_readl(THM_HTS) & HTS_GTD_DIS); } @@ -1523,7 +1522,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENOMEM; spin_lock_init(&ips->turbo_status_lock); - ips->dev = dev; + ips->dev = &dev->dev; ips->limits = ips_detect_cpu(ips); if (!ips->limits) { -- GitLab From b8cc799ddcbde8bf970804ce5f5546af2abc81bc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Oct 2017 14:10:03 +0300 Subject: [PATCH 1042/2898] platform/x86: intel_ips: Remove unneeded fields and label There are fields in the struct ips_mcp_limits which are not used anywhere and a label which we may get rid of. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 27e70637e40b..9f5afdd123bb 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -259,8 +259,6 @@ static const int IPS_SAMPLE_WINDOW = 5000; /* 5s moving window of samples */ /* Per-SKU limits */ struct ips_mcp_limits { - int cpu_family; - int cpu_model; /* includes extended model... */ int mcp_power_limit; /* mW units */ int core_power_limit; int mch_power_limit; @@ -1374,7 +1372,7 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) if (!(boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 37)) { dev_info(ips->dev, "Non-IPS CPU detected.\n"); - goto out; + return NULL; } rdmsrl(IA32_MISC_ENABLE, misc_en); @@ -1396,7 +1394,7 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) limits = &ips_ulv_limits; else { dev_info(ips->dev, "No CPUID match found.\n"); - goto out; + return NULL; } rdmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_power); @@ -1410,7 +1408,6 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) limits->core_power_limit = (tdp / 8) * 1000; } -out: return limits; } -- GitLab From 8f21b74e7cf87af187f628ceb29419a1303ef008 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 17 Jul 2017 16:05:41 -0400 Subject: [PATCH 1043/2898] platform/x86: intel_ips: Remove FSF address from GPL notice This patch removes the FSF address from the GPL notice to fix a checkpatch.pl CHECK message. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 4 ---- drivers/platform/x86/intel_ips.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 9f5afdd123bb..680ab4fd7087 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -10,10 +10,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * * The full GNU General Public License is included in this distribution in * the file called "COPYING". * diff --git a/drivers/platform/x86/intel_ips.h b/drivers/platform/x86/intel_ips.h index 73299beff5b3..60f4e3ddbe9f 100644 --- a/drivers/platform/x86/intel_ips.h +++ b/drivers/platform/x86/intel_ips.h @@ -10,10 +10,6 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * * The full GNU General Public License is included in this distribution in * the file called "COPYING". */ -- GitLab From 7c4f63ec94a1a45dd90dd3bf4da8de24a0a5a9c0 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Thu, 5 Oct 2017 04:33:14 +0200 Subject: [PATCH 1044/2898] clk: sunxi-ng: a83t: Fix invalid csi-mclk mux offset Datasheet specified that parent MUX settings are at bits [10:8], but current implementation specifies incorrect offset at [10:12]. Fix this. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-a83t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c index e43acebdfbcd..c7b51f030eb2 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c @@ -506,7 +506,7 @@ static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents, csi_mclk_table, 0x134, 0, 5, /* M */ - 10, 3, /* mux */ + 8, 3, /* mux */ BIT(15), /* gate */ 0); -- GitLab From 6736ce27ce34d791ff2f030df6162527bd383a3c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 30 Sep 2017 10:10:03 +0900 Subject: [PATCH 1045/2898] kbuild: rpm-pkg: remove ppc64 specific image handling This conditional was added by commit 1a0f3d422bb9 ("kbuild: fix make rpm for powerpc"). Its git-log explains the default kernel image is zImage, but obviously the current arch/powerpc/Makefile does not set KBUILD_IMAGE, so the image file is actually vmlinux. Moreover, since commit 09549aa1baa9 ("deb-pkg: Remove the KBUILD_IMAGE workaround"), all architectures are supposed to set the full path to the image in KBUILD_IMAGE. I see no good reason to differentiate ppc64 from others. Rip off the conditional. Signed-off-by: Masahiro Yamada --- scripts/package/mkspec | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scripts/package/mkspec b/scripts/package/mkspec index f47f17aae135..ef007501effe 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -92,13 +92,8 @@ echo "%ifarch ia64" echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE" echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/" echo "%else" -echo "%ifarch ppc64" -echo "cp vmlinux arch/powerpc/boot" -echo "cp arch/powerpc/boot/"'$KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE" -echo "%else" echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE" echo "%endif" -echo "%endif" echo 'make %{?_smp_mflags} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr KBUILD_SRC= headers_install' echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE" -- GitLab From 81771ce2d1a9f9ce8739aac7af64bb03ff4b6a1a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 30 Sep 2017 10:10:04 +0900 Subject: [PATCH 1046/2898] kbuild: rpm-pkg: install vmlinux.bz2 unconditionally This conditional was added by commit fc370ecfdb37 ("kbuild: add vmlinux to kernel rpm"). Its git-log mentioned vmlinux.bz2 was necessary for debugging, but did not explain why ppc64 was an exception. I see no problem to copy vmlinux.bz2 all the time. Signed-off-by: Masahiro Yamada --- scripts/package/mkspec | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/package/mkspec b/scripts/package/mkspec index ef007501effe..a026c089d773 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -99,11 +99,8 @@ echo 'make %{?_smp_mflags} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr KBUILD_SRC= head echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE" echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE" - -echo "%ifnarch ppc64" echo 'bzip2 -9 --keep vmlinux' echo 'mv vmlinux.bz2 $RPM_BUILD_ROOT'"/boot/vmlinux-$KERNELRELEASE.bz2" -echo "%endif" if ! $PREBUILT; then echo 'rm -f $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE/build" -- GitLab From 5289c322ba994c7b07a4780243dca1feb610954f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 30 Sep 2017 10:10:05 +0900 Subject: [PATCH 1047/2898] kbuild: rpm-pkg: clean up mkspec Clean up the mkspec without changing the behavior. - grep CONFIG_DRM=y more simply - move "EXCLUDE" out of the "%install" section because it can be computed when the spec file is generated - remove "BuildRoot:" field, which is now redundant - do not mkdir $RPM_BUILD_ROOT/lib/modules explicitly because it is automatically created by "make modules_install" - exclude "%package devel" from source package spec file because it does not make sense where "%files devel" is already excluded - exclude "%build" from source package spec file - remove unneeded "make clean" because we had already cleaned before making tar file - merge two %ifarch ia64 conditionals - replace KBUILD_IMAGE with direct use of $(make image_name) - remove trailing empty line from the spec file Signed-off-by: Masahiro Yamada --- scripts/package/mkspec | 44 +++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/scripts/package/mkspec b/scripts/package/mkspec index a026c089d773..97feb60e6482 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -10,19 +10,21 @@ # # how we were called determines which rpms we build and how we build them -if [ "$1" = "prebuilt" ]; then +if [ "$1" = prebuilt ]; then PREBUILT=true else PREBUILT=false fi -# starting to output the spec -if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then +if grep -q CONFIG_DRM=y .config; then PROVIDES=kernel-drm fi PROVIDES="$PROVIDES kernel-$KERNELRELEASE" -__KERNELRELEASE=`echo $KERNELRELEASE | sed -e "s/-/_/g"` +__KERNELRELEASE=$(echo $KERNELRELEASE | sed -e "s/-/_/g") +EXCLUDES="$RCS_TAR_IGNORE --exclude=.tmp_versions --exclude=*vmlinux* \ +--exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation \ +--exclude=.config.old --exclude=.missing-syscalls.d" echo "Name: kernel" echo "Summary: The Linux Kernel" @@ -37,7 +39,6 @@ if ! $PREBUILT; then echo "Source: kernel-$__KERNELRELEASE.tar.gz" fi -echo "BuildRoot: %{_tmppath}/%{name}-%{PACKAGE_VERSION}-root" echo "Provides: $PROVIDES" echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :" echo "%define debug_package %{nil}" @@ -57,6 +58,8 @@ echo "header files define structures and constants that are needed for" echo "building most standard programs and are also needed for rebuilding the" echo "glibc package." echo "" + +if ! $PREBUILT; then echo "%package devel" echo "Summary: Development package for building kernel modules to match the $__KERNELRELEASE kernel" echo "Group: System Environment/Kernel" @@ -65,39 +68,26 @@ echo "%description -n kernel-devel" echo "This package provides kernel headers and makefiles sufficient to build modules" echo "against the $__KERNELRELEASE kernel package." echo "" - -if ! $PREBUILT; then echo "%prep" echo "%setup -q" echo "" -fi - echo "%build" - -if ! $PREBUILT; then -echo "make clean && make %{?_smp_mflags} KBUILD_BUILD_VERSION=%{release}" +echo "make %{?_smp_mflags} KBUILD_BUILD_VERSION=%{release}" echo "" fi echo "%install" -echo 'KBUILD_IMAGE=$(make image_name)' +echo 'mkdir -p $RPM_BUILD_ROOT/boot' echo "%ifarch ia64" -echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi $RPM_BUILD_ROOT/lib/modules' -echo "%else" -echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib/modules' -echo "%endif" - -echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} KBUILD_SRC= modules_install' -echo "%ifarch ia64" -echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE" +echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi' +echo 'cp $(make image_name) $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE" echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/" echo "%else" -echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE" +echo 'cp $(make image_name) $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE" echo "%endif" - +echo 'make %{?_smp_mflags} INSTALL_MOD_PATH=$RPM_BUILD_ROOT KBUILD_SRC= modules_install' echo 'make %{?_smp_mflags} INSTALL_HDR_PATH=$RPM_BUILD_ROOT/usr KBUILD_SRC= headers_install' echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE" - echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE" echo 'bzip2 -9 --keep vmlinux' echo 'mv vmlinux.bz2 $RPM_BUILD_ROOT'"/boot/vmlinux-$KERNELRELEASE.bz2" @@ -106,8 +96,7 @@ if ! $PREBUILT; then echo 'rm -f $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE/build" echo 'rm -f $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE/source" echo "mkdir -p "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE" -echo "EXCLUDES=\"$RCS_TAR_IGNORE --exclude .tmp_versions --exclude=*vmlinux* --exclude=*.o --exclude=*.ko --exclude=*.cmd --exclude=Documentation --exclude .config.old --exclude .missing-syscalls.d\"" -echo "tar "'$EXCLUDES'" -cf- . | (cd "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE;tar xvf -)" +echo "tar cf - . $EXCLUDES | tar xf - -C "'$RPM_BUILD_ROOT'"/usr/src/kernels/$KERNELRELEASE" echo 'cd $RPM_BUILD_ROOT'"/lib/modules/$KERNELRELEASE" echo "ln -sf /usr/src/kernels/$KERNELRELEASE build" echo "ln -sf /usr/src/kernels/$KERNELRELEASE source" @@ -146,12 +135,11 @@ echo "" echo "%files headers" echo '%defattr (-, root, root)' echo "/usr/include" -echo "" if ! $PREBUILT; then +echo "" echo "%files devel" echo '%defattr (-, root, root)' echo "/usr/src/kernels/$KERNELRELEASE" echo "/lib/modules/$KERNELRELEASE/build" echo "/lib/modules/$KERNELRELEASE/source" -echo "" fi -- GitLab From d5cd103b06f9d766295d18798de484528eb120ea Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 4 Oct 2017 08:38:26 +0200 Subject: [PATCH 1048/2898] clk: samsung: Remove support for Exynos4212 SoCs in Exynos CLKOUT driver Support for Exynos4212 SoCs has been removed by commit bca9085e0ae9 ("ARM: dts: exynos: remove Exynos4212 support (dead code)"), so there is no need to keep remaining dead code related to this SoC version. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos-clkout.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c index a21aea062bae..f29fb5824005 100644 --- a/drivers/clk/samsung/clk-exynos-clkout.c +++ b/drivers/clk/samsung/clk-exynos-clkout.c @@ -144,8 +144,6 @@ static void __init exynos4_clkout_init(struct device_node *node) } CLK_OF_DECLARE_DRIVER(exynos4210_clkout, "samsung,exynos4210-pmu", exynos4_clkout_init); -CLK_OF_DECLARE_DRIVER(exynos4212_clkout, "samsung,exynos4212-pmu", - exynos4_clkout_init); CLK_OF_DECLARE_DRIVER(exynos4412_clkout, "samsung,exynos4412-pmu", exynos4_clkout_init); CLK_OF_DECLARE_DRIVER(exynos3250_clkout, "samsung,exynos3250-pmu", -- GitLab From c9194fb623b0158029a268376df09fe28a2a2b05 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:08 +0200 Subject: [PATCH 1049/2898] clk: samsung: Remove support for obsolete Exynos4212 CPU clock Support for Exynos 4212 SoC has been removed by commit bca9085e0ae9 ("ARM: dts: exynos: remove Exynos4212 support (dead code)"), so there is no need to keep dead code. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 33 ++++--------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index e40b77583c47..9a51ce9a658f 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1401,24 +1401,6 @@ static const struct exynos_cpuclk_cfg_data e4210_armclk_d[] __initconst = { { 0 }, }; -static const struct exynos_cpuclk_cfg_data e4212_armclk_d[] __initconst = { - { 1500000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), }, - { 1400000, E4210_CPU_DIV0(2, 1, 6, 0, 7, 3), E4210_CPU_DIV1(2, 6), }, - { 1300000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), }, - { 1200000, E4210_CPU_DIV0(2, 1, 5, 0, 7, 3), E4210_CPU_DIV1(2, 5), }, - { 1100000, E4210_CPU_DIV0(2, 1, 4, 0, 6, 3), E4210_CPU_DIV1(2, 4), }, - { 1000000, E4210_CPU_DIV0(1, 1, 4, 0, 5, 2), E4210_CPU_DIV1(2, 4), }, - { 900000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), }, - { 800000, E4210_CPU_DIV0(1, 1, 3, 0, 5, 2), E4210_CPU_DIV1(2, 3), }, - { 700000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 600000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 500000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 400000, E4210_CPU_DIV0(1, 1, 3, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 300000, E4210_CPU_DIV0(1, 1, 2, 0, 4, 2), E4210_CPU_DIV1(2, 3), }, - { 200000, E4210_CPU_DIV0(1, 1, 1, 0, 3, 1), E4210_CPU_DIV1(2, 3), }, - { 0 }, -}; - #define E4412_CPU_DIV1(cores, hpm, copy) \ (((cores) << 8) | ((hpm) << 4) | ((copy) << 0)) @@ -1533,17 +1515,10 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_fixed_factor(ctx, exynos4x12_fixed_factor_clks, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); - if (of_machine_is_compatible("samsung,exynos4412")) { - exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, - e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d), - CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); - } else { - exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, - e4212_armclk_d, ARRAY_SIZE(e4212_armclk_d), - CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); - } + exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", + mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, + e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d), + CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); } samsung_clk_register_alias(ctx, exynos4_aliases, -- GitLab From 58f4a5ff3a6248a89c849415cab8089e41425f5e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:09 +0200 Subject: [PATCH 1050/2898] clk: samsung: Remove clkdev alias support in Exynos4 clk driver All Exynos4 boards have been fully converted to device-tree and use generic dt-based CPUfreq driver, so there is no need to create any clkdev aliases for the clocks. Drop all the code related to aliases handling. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 47 +++++++------------------------ 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 9a51ce9a658f..3fbfd9ed82b7 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -535,9 +535,8 @@ static const struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __ /* list of mux clocks supported in all exynos4 soc's */ static const struct samsung_mux_clock exynos4_mux_clks[] __initconst = { - MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, - CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0, - "mout_apll"), + MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, + CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0), MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1), MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1), MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), @@ -838,11 +837,6 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = { /* list of gate clocks supported in all exynos4 soc's */ static const struct samsung_gate_clock exynos4_gate_clks[] __initconst = { - /* - * After all Exynos4 based platforms are migrated to use device tree, - * the device name and clock alias names specified below for some - * of the clocks can be removed. - */ GATE(CLK_PPMULEFT, "ppmuleft", "aclk200", GATE_IP_LEFTBUS, 1, 0, 0), GATE(CLK_PPMURIGHT, "ppmuright", "aclk200", GATE_IP_RIGHTBUS, 1, 0, 0), GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0), @@ -1190,20 +1184,6 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = { 0), }; -static const struct samsung_clock_alias exynos4_aliases[] __initconst = { - ALIAS(CLK_MOUT_CORE, NULL, "moutcore"), - ALIAS(CLK_ARM_CLK, NULL, "armclk"), - ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"), -}; - -static const struct samsung_clock_alias exynos4210_aliases[] __initconst = { - ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"), -}; - -static const struct samsung_clock_alias exynos4x12_aliases[] __initconst = { - ALIAS(CLK_MOUT_MPLL_USER_C, NULL, "mout_mpll"), -}; - /* * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit * resides in chipid register space, outside of the clock controller memory @@ -1340,14 +1320,14 @@ static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst = }; static struct samsung_pll_clock exynos4210_plls[nr_plls] __initdata = { - [apll] = PLL_A(pll_4508, CLK_FOUT_APLL, "fout_apll", "fin_pll", - APLL_LOCK, APLL_CON0, "fout_apll", NULL), - [mpll] = PLL_A(pll_4508, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", - E4210_MPLL_LOCK, E4210_MPLL_CON0, "fout_mpll", NULL), - [epll] = PLL_A(pll_4600, CLK_FOUT_EPLL, "fout_epll", "fin_pll", - EPLL_LOCK, EPLL_CON0, "fout_epll", NULL), - [vpll] = PLL_A(pll_4650c, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc", - VPLL_LOCK, VPLL_CON0, "fout_vpll", NULL), + [apll] = PLL(pll_4508, CLK_FOUT_APLL, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON0, NULL), + [mpll] = PLL(pll_4508, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", + E4210_MPLL_LOCK, E4210_MPLL_CON0, NULL), + [epll] = PLL(pll_4600, CLK_FOUT_EPLL, "fout_epll", "fin_pll", + EPLL_LOCK, EPLL_CON0, NULL), + [vpll] = PLL(pll_4650c, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc", + VPLL_LOCK, VPLL_CON0, NULL), }; static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { @@ -1494,8 +1474,6 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4210_div_clks)); samsung_clk_register_gate(ctx, exynos4210_gate_clks, ARRAY_SIZE(exynos4210_gate_clks)); - samsung_clk_register_alias(ctx, exynos4210_aliases, - ARRAY_SIZE(exynos4210_aliases)); samsung_clk_register_fixed_factor(ctx, exynos4210_fixed_factor_clks, ARRAY_SIZE(exynos4210_fixed_factor_clks)); @@ -1510,8 +1488,6 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4x12_div_clks)); samsung_clk_register_gate(ctx, exynos4x12_gate_clks, ARRAY_SIZE(exynos4x12_gate_clks)); - samsung_clk_register_alias(ctx, exynos4x12_aliases, - ARRAY_SIZE(exynos4x12_aliases)); samsung_clk_register_fixed_factor(ctx, exynos4x12_fixed_factor_clks, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); @@ -1521,9 +1497,6 @@ static void __init exynos4_clk_init(struct device_node *np, CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); } - samsung_clk_register_alias(ctx, exynos4_aliases, - ARRAY_SIZE(exynos4_aliases)); - if (soc == EXYNOS4X12) exynos4x12_core_down_clock(); exynos4_clk_sleep_init(); -- GitLab From 6de08891c896d313e6541e5a56e373adcf0bbebc Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:10 +0200 Subject: [PATCH 1051/2898] clk: samsung: Remove double assignment of CLK_ARM_CLK in Exynos4 driver CLK_ARM_CLK ("armclk") clock is provided by cpu-clk subdriver, which is instantiated after creating all divider clocks from exynos4_div_clks array. There is no point assigning this id to "div_core2" clock and later overwrite with proper "armcpu" clock by cpu-clk subdriver. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 3fbfd9ed82b7..3bd2d84b2a17 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -721,7 +721,7 @@ static const struct samsung_div_clock exynos4_div_clks[] __initconst = { DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3), DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3), DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3), - DIV(CLK_ARM_CLK, "div_core2", "div_core", DIV_CPU0, 28, 3), + DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3), DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3), DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6), -- GitLab From 29964890f31c2cb98b0aa277d81652e6aecd8bbc Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:11 +0200 Subject: [PATCH 1052/2898] clk: samsung: Remove clkdev alias support in Exynos5250 clk driver All Exynos5250 boards have been fully converted to device-tree and use generic dt-based CPUfreq driver, so there is no need to create any clkdev aliases for the clocks. Drop all the code related to aliases handling. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5250.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 27a227d6620c..9b073c98a891 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -293,14 +293,14 @@ static const struct samsung_mux_clock exynos5250_mux_clks[] __initconst = { /* * CMU_CPU */ - MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, - CLK_SET_RATE_PARENT, 0, "mout_apll"), - MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"), + MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, + CLK_SET_RATE_PARENT, 0), + MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), /* * CMU_CORE */ - MUX_A(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"), + MUX(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1), /* * CMU_TOP @@ -391,7 +391,7 @@ static const struct samsung_div_clock exynos5250_div_clks[] __initconst = { */ DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3), - DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"), + DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3), /* * CMU_TOP @@ -743,10 +743,10 @@ static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = { }; static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = { - [apll] = PLL_A(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", - APLL_LOCK, APLL_CON0, "fout_apll", NULL), - [mpll] = PLL_A(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", - MPLL_LOCK, MPLL_CON0, "fout_mpll", NULL), + [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, + APLL_CON0, NULL), + [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK, + MPLL_CON0, NULL), [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK, BPLL_CON0, NULL), [gpll] = PLL(pll_35xx, CLK_FOUT_GPLL, "fout_gpll", "fin_pll", GPLL_LOCK, -- GitLab From 36ba48240b19395ececd7303bde56f9af4177062 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:12 +0200 Subject: [PATCH 1053/2898] clk: samsung: Drop useless alias in Exynos5420 clk driver Drop clkdev alias for "mout_aclk400_mscl" clock. It was not used at all and it was probably committed by accident. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 038701a2af4c..45d34f601e9e 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -600,8 +600,7 @@ static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = { TOP_SPARE2, 4, 1), MUX(0, "mout_aclk400_isp", mout_group1_p, SRC_TOP0, 0, 2), - MUX_A(0, "mout_aclk400_mscl", mout_group1_p, - SRC_TOP0, 4, 2, "aclk400_mscl"), + MUX(0, "mout_aclk400_mscl", mout_group1_p, SRC_TOP0, 4, 2), MUX(0, "mout_aclk400_wcore", mout_group1_p, SRC_TOP0, 16, 2), MUX(0, "mout_aclk100_noc", mout_group1_p, SRC_TOP0, 20, 2), -- GitLab From efea8d3771843bca26862fabebfa83aa9b497bd2 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:13 +0200 Subject: [PATCH 1054/2898] clk: samsung: Rework clkdev alias handling in Exynos5440 driver Exynos5440 still uses old, non-dt CPUfreq driver, which requires clkdev aliases to get access to proper clocks. Create those aliases using samsung_clk_register_alias() function instead of using *_A clock macros, which will be removed soon. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5440.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index a80f3ef20801..b08bd54c5e76 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -53,8 +53,7 @@ static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __ /* mux clocks */ static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = { MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1), - MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p, - CPU_CLK_STATUS, 0, 1, "armclk"), + MUX(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1), }; /* divider clocks */ @@ -117,6 +116,13 @@ static const struct samsung_pll_clock exynos5440_plls[] __initconst = { PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL), }; +/* + * Clock aliases for legacy clkdev look-up. + */ +static const struct samsung_clock_alias exynos5440_aliases[] __initconst = { + ALIAS(CLK_ARM_CLK, NULL, "armclk"), +}; + /* register exynos5440 clocks */ static void __init exynos5440_clk_init(struct device_node *np) { @@ -147,6 +153,8 @@ static void __init exynos5440_clk_init(struct device_node *np) ARRAY_SIZE(exynos5440_div_clks)); samsung_clk_register_gate(ctx, exynos5440_gate_clks, ARRAY_SIZE(exynos5440_gate_clks)); + samsung_clk_register_alias(ctx, exynos5440_aliases, + ARRAY_SIZE(exynos5440_aliases)); samsung_clk_of_add_provider(np, ctx); -- GitLab From cd05417f728ba914caf5d94fa4a15b2300a268b5 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:14 +0200 Subject: [PATCH 1055/2898] clk: samsung: Rework clkdev alias handling in S3C2443 driver S3C2443 SoC still uses old, non-dt CPUfreq driver, which requires clkdev aliases to get access to proper clocks. Create those aliases using samsung_clk_register_alias() function instead of using *_A clock macros, which will be removed soon. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-s3c2443.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index abb935c42916..45166033f638 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -117,8 +117,8 @@ struct samsung_mux_clock s3c2443_common_muxes[] __initdata = { MUX(0, "epllref", epllref_p, CLKSRC, 7, 2), MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1), MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1), - MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"), - MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"), + MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1), + MUX(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1), MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2), }; @@ -189,6 +189,8 @@ struct samsung_gate_clock s3c2443_common_gates[] __initdata = { }; struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { + ALIAS(MSYSCLK, NULL, "msysclk"), + ALIAS(ARMCLK, NULL, "armclk"), ALIAS(HCLK, NULL, "hclk"), ALIAS(HCLK_SSMC, NULL, "nand"), ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), -- GitLab From 45d882daf88a57ec681254e8a41dd5ba268a097d Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:15 +0200 Subject: [PATCH 1056/2898] clk: samsung: Add explicit MPLL, EPLL clkdev aliases in S3C2443 driver S3C2443 platform still use non-dt based lookup in some of its drivers to get MPLL and EPLL clocks. Till now it worked only because PLL() macro implicitly created aliases for all instantiated clocks. This feature will be removed, so explicitly create aliases for MPLL and EPLL clocks. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-s3c2443.c | 10 ++++++---- include/dt-bindings/clock/s3c2443.h | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index 45166033f638..d94b85a42356 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -191,6 +191,8 @@ struct samsung_gate_clock s3c2443_common_gates[] __initdata = { struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { ALIAS(MSYSCLK, NULL, "msysclk"), ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(MPLL, NULL, "mpll"), + ALIAS(EPLL, NULL, "epll"), ALIAS(HCLK, NULL, "hclk"), ALIAS(HCLK_SSMC, NULL, "nand"), ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), @@ -223,9 +225,9 @@ struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { /* S3C2416 specific clocks */ static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = { - [mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref", + [mpll] = PLL(pll_6552_s3c2416, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL), - [epll] = PLL(pll_6553, 0, "epll", "epllref", + [epll] = PLL(pll_6553, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL), }; @@ -277,9 +279,9 @@ struct samsung_clock_alias s3c2416_aliases[] __initdata = { /* S3C2443 specific clocks */ static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = { - [mpll] = PLL(pll_3000, 0, "mpll", "mpllref", + [mpll] = PLL(pll_3000, MPLL, "mpll", "mpllref", LOCKCON0, MPLLCON, NULL), - [epll] = PLL(pll_2126, 0, "epll", "epllref", + [epll] = PLL(pll_2126, EPLL, "epll", "epllref", LOCKCON1, EPLLCON, NULL), }; diff --git a/include/dt-bindings/clock/s3c2443.h b/include/dt-bindings/clock/s3c2443.h index 37e66b054d64..f3ba68a25ecb 100644 --- a/include/dt-bindings/clock/s3c2443.h +++ b/include/dt-bindings/clock/s3c2443.h @@ -26,6 +26,8 @@ #define ARMCLK 4 #define HCLK 5 #define PCLK 6 +#define MPLL 7 +#define EPLL 8 /* Special clocks */ #define SCLK_HSSPI0 16 -- GitLab From a4f21e9ceb5c81f5b297cabb98dac0b5c03bd4dc Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 3 Oct 2017 12:00:16 +0200 Subject: [PATCH 1057/2898] clk: samsung: Remove obsolete clkdev alias support Remove support for obsolete clkdev alias definition in generic helper macros for MUX, DIV, GATE and PLL clocks. clkdev aliases can be still created using samsung_clk_register_alias() function if given platform still needs them. All current drivers have been converted not to use *_A-style macros and checked if there are any clients for the PLL clocks, which had aliases created unconditionally. Signed-off-by: Marek Szyprowski Acked-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-pll.c | 9 ----- drivers/clk/samsung/clk.c | 33 ++-------------- drivers/clk/samsung/clk.h | 71 ++++++----------------------------- 3 files changed, 15 insertions(+), 98 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 037c61484098..137882657370 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -1397,15 +1397,6 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, } samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id); - - if (!pll_clk->alias) - return; - - ret = clk_hw_register_clkdev(&pll->hw, pll_clk->alias, - pll_clk->dev_name); - if (ret) - pr_err("%s: failed to register lookup for %s : %d", - __func__, pll_clk->name, ret); } void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 7ce0fa86c5ff..484abc84a352 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -181,7 +181,7 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, unsigned int nr_clk) { struct clk_hw *clk_hw; - unsigned int idx, ret; + unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_mux(NULL, list->name, @@ -195,15 +195,6 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, } samsung_clk_add_lookup(ctx, clk_hw, list->id); - - /* register a clock lookup only if a clock alias is specified */ - if (list->alias) { - ret = clk_hw_register_clkdev(clk_hw, list->alias, - list->dev_name); - if (ret) - pr_err("%s: failed to register lookup %s\n", - __func__, list->alias); - } } } @@ -213,7 +204,7 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, unsigned int nr_clk) { struct clk_hw *clk_hw; - unsigned int idx, ret; + unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { if (list->table) @@ -234,15 +225,6 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, } samsung_clk_add_lookup(ctx, clk_hw, list->id); - - /* register a clock lookup only if a clock alias is specified */ - if (list->alias) { - ret = clk_hw_register_clkdev(clk_hw, list->alias, - list->dev_name); - if (ret) - pr_err("%s: failed to register lookup %s\n", - __func__, list->alias); - } } } @@ -252,7 +234,7 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, unsigned int nr_clk) { struct clk_hw *clk_hw; - unsigned int idx, ret; + unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_gate(NULL, list->name, list->parent_name, @@ -264,15 +246,6 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, continue; } - /* register a clock lookup only if a clock alias is specified */ - if (list->alias) { - ret = clk_hw_register_clkdev(clk_hw, list->alias, - list->dev_name); - if (ret) - pr_err("%s: failed to register lookup %s\n", - __func__, list->alias); - } - samsung_clk_add_lookup(ctx, clk_hw, list->id); } } diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index d5f0d3f818b6..1cb03b6e2dfd 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -106,7 +106,6 @@ struct samsung_fixed_factor_clock { /** * struct samsung_mux_clock: information about mux clock * @id: platform specific id of the clock. - * @dev_name: name of the device to which this clock belongs. * @name: name of this mux clock. * @parent_names: array of pointer to parent clock names. * @num_parents: number of parents listed in @parent_names. @@ -115,11 +114,9 @@ struct samsung_fixed_factor_clock { * @shift: starting bit location of the mux control bit-field in @reg. * @width: width of the mux control bit-field in @reg. * @mux_flags: flags for mux-type clock. - * @alias: optional clock alias name to be assigned to this clock. */ struct samsung_mux_clock { unsigned int id; - const char *dev_name; const char *name; const char *const *parent_names; u8 num_parents; @@ -128,13 +125,11 @@ struct samsung_mux_clock { u8 shift; u8 width; u8 mux_flags; - const char *alias; }; -#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a) \ +#define __MUX(_id, cname, pnames, o, s, w, f, mf) \ { \ .id = _id, \ - .dev_name = dname, \ .name = cname, \ .parent_names = pnames, \ .num_parents = ARRAY_SIZE(pnames), \ @@ -143,36 +138,26 @@ struct samsung_mux_clock { .shift = s, \ .width = w, \ .mux_flags = mf, \ - .alias = a, \ } #define MUX(_id, cname, pnames, o, s, w) \ - __MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL) - -#define MUX_A(_id, cname, pnames, o, s, w, a) \ - __MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a) + __MUX(_id, cname, pnames, o, s, w, 0, 0) #define MUX_F(_id, cname, pnames, o, s, w, f, mf) \ - __MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL) - -#define MUX_FA(_id, cname, pnames, o, s, w, f, mf, a) \ - __MUX(_id, NULL, cname, pnames, o, s, w, f, mf, a) + __MUX(_id, cname, pnames, o, s, w, f, mf) /** * @id: platform specific id of the clock. * struct samsung_div_clock: information about div clock - * @dev_name: name of the device to which this clock belongs. * @name: name of this div clock. * @parent_name: name of the parent clock. * @flags: optional flags for basic clock. * @offset: offset of the register for configuring the div. * @shift: starting bit location of the div control bit-field in @reg. * @div_flags: flags for div-type clock. - * @alias: optional clock alias name to be assigned to this clock. */ struct samsung_div_clock { unsigned int id; - const char *dev_name; const char *name; const char *parent_name; unsigned long flags; @@ -180,14 +165,12 @@ struct samsung_div_clock { u8 shift; u8 width; u8 div_flags; - const char *alias; struct clk_div_table *table; }; -#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t) \ +#define __DIV(_id, cname, pname, o, s, w, f, df, t) \ { \ .id = _id, \ - .dev_name = dname, \ .name = cname, \ .parent_name = pname, \ .flags = f, \ @@ -195,70 +178,51 @@ struct samsung_div_clock { .shift = s, \ .width = w, \ .div_flags = df, \ - .alias = a, \ .table = t, \ } #define DIV(_id, cname, pname, o, s, w) \ - __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL) - -#define DIV_A(_id, cname, pname, o, s, w, a) \ - __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL) + __DIV(_id, cname, pname, o, s, w, 0, 0, NULL) #define DIV_F(_id, cname, pname, o, s, w, f, df) \ - __DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL) + __DIV(_id, cname, pname, o, s, w, f, df, NULL) #define DIV_T(_id, cname, pname, o, s, w, t) \ - __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t) + __DIV(_id, cname, pname, o, s, w, 0, 0, t) /** * struct samsung_gate_clock: information about gate clock * @id: platform specific id of the clock. - * @dev_name: name of the device to which this clock belongs. * @name: name of this gate clock. * @parent_name: name of the parent clock. * @flags: optional flags for basic clock. * @offset: offset of the register for configuring the gate. * @bit_idx: bit index of the gate control bit-field in @reg. * @gate_flags: flags for gate-type clock. - * @alias: optional clock alias name to be assigned to this clock. */ struct samsung_gate_clock { unsigned int id; - const char *dev_name; const char *name; const char *parent_name; unsigned long flags; unsigned long offset; u8 bit_idx; u8 gate_flags; - const char *alias; }; -#define __GATE(_id, dname, cname, pname, o, b, f, gf, a) \ +#define __GATE(_id, cname, pname, o, b, f, gf) \ { \ .id = _id, \ - .dev_name = dname, \ .name = cname, \ .parent_name = pname, \ .flags = f, \ .offset = o, \ .bit_idx = b, \ .gate_flags = gf, \ - .alias = a, \ } #define GATE(_id, cname, pname, o, b, f, gf) \ - __GATE(_id, NULL, cname, pname, o, b, f, gf, NULL) - -#define GATE_A(_id, cname, pname, o, b, f, gf, a) \ - __GATE(_id, NULL, cname, pname, o, b, f, gf, a) - -#define GATE_D(_id, dname, cname, pname, o, b, f, gf) \ - __GATE(_id, dname, cname, pname, o, b, f, gf, NULL) - -#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a) \ - __GATE(_id, dname, cname, pname, o, b, f, gf, a) + __GATE(_id, cname, pname, o, b, f, gf) #define PNAME(x) static const char * const x[] __initconst @@ -275,18 +239,15 @@ struct samsung_clk_reg_dump { /** * struct samsung_pll_clock: information about pll clock * @id: platform specific id of the clock. - * @dev_name: name of the device to which this clock belongs. * @name: name of this pll clock. * @parent_name: name of the parent clock. * @flags: optional flags for basic clock. * @con_offset: offset of the register for configuring the PLL. * @lock_offset: offset of the register for locking the PLL. * @type: Type of PLL to be registered. - * @alias: optional clock alias name to be assigned to this clock. */ struct samsung_pll_clock { unsigned int id; - const char *dev_name; const char *name; const char *parent_name; unsigned long flags; @@ -294,31 +255,23 @@ struct samsung_pll_clock { int lock_offset; enum samsung_pll_type type; const struct samsung_pll_rate_table *rate_table; - const char *alias; }; -#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \ - _rtable, _alias) \ +#define __PLL(_typ, _id, _name, _pname, _flags, _lock, _con, _rtable) \ { \ .id = _id, \ .type = _typ, \ - .dev_name = _dname, \ .name = _name, \ .parent_name = _pname, \ .flags = _flags, \ .con_offset = _con, \ .lock_offset = _lock, \ .rate_table = _rtable, \ - .alias = _alias, \ } #define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \ - __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ - _lock, _con, _rtable, _name) - -#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \ - __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ - _lock, _con, _rtable, _alias) + __PLL(_typ, _id, _name, _pname, CLK_GET_RATE_NOCACHE, _lock, \ + _con, _rtable) struct samsung_clock_reg_cache { struct list_head node; -- GitLab From f231e43333124d92a82acd19431f8104b8e48a75 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 21 Sep 2017 00:17:50 +0900 Subject: [PATCH 1058/2898] hexagon: get rid of #include is created (or updated) when Kbuild descends into the init/ directory. In parallel building from a pristine source tree, there is no guarantee exists when arch/hexagon/kernel/ptrace.c is compiled. For hexagon architecture, we know UTS_MACHINE is a fixed string "hexagon", so let's hard-code it, like many architectures do. Signed-off-by: Masahiro Yamada Acked-by: Richard Kuo --- arch/hexagon/kernel/ptrace.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c index ecd75e2e8eb3..fa76493c1745 100644 --- a/arch/hexagon/kernel/ptrace.c +++ b/arch/hexagon/kernel/ptrace.c @@ -18,8 +18,6 @@ * 02110-1301, USA. */ -#include - #include #include #include @@ -180,7 +178,7 @@ static const struct user_regset hexagon_regsets[] = { }; static const struct user_regset_view hexagon_user_view = { - .name = UTS_MACHINE, + .name = "hexagon", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, .regsets = hexagon_regsets, -- GitLab From 278ae6040397f37fa6a96a6b86ed02d4762080a7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 14:31:13 +0900 Subject: [PATCH 1059/2898] kbuild: link-vmlinux.sh: simplify .version increment Since commit 1f2bfbd00e46 ("kbuild: link of vmlinux moved to a script"), it is easy to increment .version without using a temporary file .old_version. I do not see anybody who creates the .tmp_version. Probably it is a left-over of commit 4e25d8bb9550fb ("[PATCH] kbuild: adjust .version updating"). Just remove it. Signed-off-by: Masahiro Yamada --- Makefile | 2 +- scripts/link-vmlinux.sh | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index cf007a31d575..9aa47218100e 100644 --- a/Makefile +++ b/Makefile @@ -1278,7 +1278,7 @@ CLEAN_DIRS += $(MODVERDIR) # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config usr/include include/generated \ arch/*/include/generated .tmp_objdiff -MRPROPER_FILES += .config .config.old .version .old_version \ +MRPROPER_FILES += .config .config.old .version \ Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ signing_key.pem signing_key.priv signing_key.x509 \ x509.genkey extra_certificates signing_key.x509.keyid \ diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index e7b7eee31538..0cdb25b66e6f 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -187,10 +187,8 @@ sortextable() # Delete output files in case of error cleanup() { - rm -f .old_version rm -f .tmp_System.map rm -f .tmp_kallsyms* - rm -f .tmp_version rm -f .tmp_vmlinux* rm -f built-in.o rm -f System.map @@ -238,12 +236,12 @@ esac # Update version info GEN .version -if [ ! -r .version ]; then - rm -f .version; - echo 1 >.version; +if [ -r .version ]; then + VERSION=$(expr 0$(cat .version) + 1) + echo $VERSION > .version else - mv .version .old_version; - expr 0$(cat .old_version) + 1 >.version; + rm -f .version + echo 1 > .version fi; # final build of init/ @@ -331,6 +329,3 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then exit 1 fi fi - -# We made a new kernel - delete old version file -rm -f .old_version -- GitLab From 37131ec4f9cb60750be6f75fca20ff6bbf1b8efd Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 22 Sep 2017 14:31:14 +0900 Subject: [PATCH 1060/2898] kbuild: mkcompile_h: do not create .version This script does not need to create .version; it will be created by scripts/link-vmlinux.sh later. Clean-up the code slightly. Signed-off-by: Masahiro Yamada --- scripts/mkcompile_h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h index fd8fdb91581d..f1ee4ebd6518 100755 --- a/scripts/mkcompile_h +++ b/scripts/mkcompile_h @@ -27,12 +27,7 @@ LC_ALL=C export LC_ALL if [ -z "$KBUILD_BUILD_VERSION" ]; then - if [ -r .version ]; then - VERSION=`cat .version` - else - VERSION=0 - echo 0 > .version - fi + VERSION=$(cat .version 2>/dev/null || echo 1) else VERSION=$KBUILD_BUILD_VERSION fi -- GitLab From 9d022c540606a5a8ae5d1cc02fc12de362ba4585 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 4 Oct 2017 12:56:04 +0900 Subject: [PATCH 1061/2898] kbuild: replace $(hdr-arch) with $(SRCARCH) Since commit 5e53879008b9 ("sparc,sparc64: unify Makefile"), hdr-arch and SRCARCH always match. Signed-off-by: Masahiro Yamada Reviewed-by: Douglas Anderson --- Makefile | 21 +++++++++------------ scripts/Makefile.headersinst | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 9aa47218100e..27fcdc1d4ec9 100644 --- a/Makefile +++ b/Makefile @@ -283,9 +283,6 @@ ifeq ($(ARCH),tilegx) SRCARCH := tile endif -# Where to locate arch specific headers -hdr-arch := $(SRCARCH) - KCONFIG_CONFIG ?= .config export KCONFIG_CONFIG @@ -378,8 +375,8 @@ CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,) # Use USERINCLUDE when you must reference the UAPI directories only. USERINCLUDE := \ - -I$(srctree)/arch/$(hdr-arch)/include/uapi \ - -I$(objtree)/arch/$(hdr-arch)/include/generated/uapi \ + -I$(srctree)/arch/$(SRCARCH)/include/uapi \ + -I$(objtree)/arch/$(SRCARCH)/include/generated/uapi \ -I$(srctree)/include/uapi \ -I$(objtree)/include/generated/uapi \ -include $(srctree)/include/linux/kconfig.h @@ -387,8 +384,8 @@ USERINCLUDE := \ # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option LINUXINCLUDE := \ - -I$(srctree)/arch/$(hdr-arch)/include \ - -I$(objtree)/arch/$(hdr-arch)/include/generated \ + -I$(srctree)/arch/$(SRCARCH)/include \ + -I$(objtree)/arch/$(SRCARCH)/include/generated \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ -I$(objtree)/include \ $(USERINCLUDE) @@ -1134,8 +1131,8 @@ headerdep: #Default location for installed headers export INSTALL_HDR_PATH = $(objtree)/usr -# If we do an all arch process set dst to include/arch-$(hdr-arch) -hdr-dst = $(if $(KBUILD_HEADERS), dst=include/arch-$(hdr-arch), dst=include) +# If we do an all arch process set dst to include/arch-$(SRCARCH) +hdr-dst = $(if $(KBUILD_HEADERS), dst=include/arch-$(SRCARCH), dst=include) PHONY += archheaders archheaders: @@ -1153,10 +1150,10 @@ headers_install_all: PHONY += headers_install headers_install: __headers - $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/uapi/asm/Kbuild),, \ + $(if $(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/Kbuild),, \ $(error Headers not exportable for the $(SRCARCH) architecture)) $(Q)$(MAKE) $(hdr-inst)=include/uapi dst=include - $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst) + $(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi $(hdr-dst) PHONY += headers_check_all headers_check_all: headers_install_all @@ -1165,7 +1162,7 @@ headers_check_all: headers_install_all PHONY += headers_check headers_check: headers_install $(Q)$(MAKE) $(hdr-inst)=include/uapi dst=include HDRCHECK=1 - $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst) HDRCHECK=1 + $(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi $(hdr-dst) HDRCHECK=1 # --------------------------------------------------------------------------- # Kernel selftest diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index 343d586e566e..5692d7a66163 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -30,7 +30,7 @@ __headers: $(subdirs) $(subdirs): $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(dst)/$@ -# Skip header install/check for include/uapi and arch/$(hdr-arch)/include/uapi. +# Skip header install/check for include/uapi and arch/$(SRCARCH)/include/uapi. # We have only sub-directories there. skip-inst := $(if $(filter %/uapi,$(obj)),1) -- GitLab From ba634eceb535d95e87ef09caae7814b3687c6036 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 4 Oct 2017 12:56:05 +0900 Subject: [PATCH 1062/2898] kbuild: move "_all" target out of $(KBUILD_SRC) conditional The first "_all" occurrence around line 120 is only visible when KBUILD_SRC is unset. If O=... is specified, the working directory is relocated, then the only second occurrence around line 193 is visible, that is not set to PHONY. Move the first one to an always visible place. This clarifies "_all" is our default target and it is always set to PHONY. Signed-off-by: Masahiro Yamada Reviewed-by: Douglas Anderson --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 27fcdc1d4ec9..a793ed153f7a 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,10 @@ NAME = Fearless Coyote # Comments in this file are targeted only to the developer, do not # expect to learn how to build the kernel reading this file. +# That's our default target when none is given on the command line +PHONY := _all +_all: + # o Do not use make's built-in rules and variables # (this increases performance and avoids hard-to-debug behaviour); # o Look for make include files relative to root of kernel src @@ -116,10 +120,6 @@ ifeq ("$(origin O)", "command line") KBUILD_OUTPUT := $(O) endif -# That's our default target when none is given on the command line -PHONY := _all -_all: - # Cancel implicit rules on top Makefile $(CURDIR)/Makefile Makefile: ; -- GitLab From 2c1f4f125159f10521944cea23e33a00fcf85ede Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 4 Oct 2017 12:56:06 +0900 Subject: [PATCH 1063/2898] kbuild: re-order the code to not parse unnecessary variables The top Makefile is divided into some sections such as mixed targets, config targets, build targets, etc. When we build mixed targets, Kbuild just invokes submake to process them one by one. In this case, compiler-related variables like CC, KBUILD_CFLAGS, etc. are unneeded. Check what kind of targets we are building first, and parse variables for building only when necessary. Signed-off-by: Masahiro Yamada --- Makefile | 233 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 118 insertions(+), 115 deletions(-) diff --git a/Makefile b/Makefile index a793ed153f7a..1ec97b902e52 100644 --- a/Makefile +++ b/Makefile @@ -186,15 +186,6 @@ ifeq ("$(origin M)", "command line") KBUILD_EXTMOD := $(M) endif -# If building an external module we do not care about the all: rule -# but instead _all depend on modules -PHONY += all -ifeq ($(KBUILD_EXTMOD),) -_all: all -else -_all: modules -endif - ifeq ($(KBUILD_SRC),) # building in the source tree srctree := . @@ -206,6 +197,9 @@ else srctree := $(KBUILD_SRC) endif endif + +export KBUILD_CHECKSRC KBUILD_EXTMOD KBUILD_SRC + objtree := . src := $(srctree) obj := $(objtree) @@ -214,6 +208,74 @@ VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD)) export srctree objtree VPATH +# To make sure we do not include .config for any of the *config targets +# catch them early, and hand them over to scripts/kconfig/Makefile +# It is allowed to specify more targets when calling make, including +# mixing *config targets and build targets. +# For example 'make oldconfig all'. +# Detect when mixed targets is specified, and make a second invocation +# of make so .config is not included in this case either (for *config). + +version_h := include/generated/uapi/linux/version.h +old_version_h := include/linux/version.h + +no-dot-config-targets := clean mrproper distclean \ + cscope gtags TAGS tags help% %docs check% coccicheck \ + $(version_h) headers_% archheaders archscripts \ + kernelversion %src-pkg + +config-targets := 0 +mixed-targets := 0 +dot-config := 1 + +ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) + ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) + dot-config := 0 + endif +endif + +ifeq ($(KBUILD_EXTMOD),) + ifneq ($(filter config %config,$(MAKECMDGOALS)),) + config-targets := 1 + ifneq ($(words $(MAKECMDGOALS)),1) + mixed-targets := 1 + endif + endif +endif +# install and modules_install need also be processed one by one +ifneq ($(filter install,$(MAKECMDGOALS)),) + ifneq ($(filter modules_install,$(MAKECMDGOALS)),) + mixed-targets := 1 + endif +endif + +ifeq ($(mixed-targets),1) +# =========================================================================== +# We're called with mixed targets (*config and build targets). +# Handle them one by one. + +PHONY += $(MAKECMDGOALS) __build_one_by_one + +$(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one + @: + +__build_one_by_one: + $(Q)set -e; \ + for i in $(MAKECMDGOALS); do \ + $(MAKE) -f $(srctree)/Makefile $$i; \ + done + +else + +# We need some generic definitions (do not try to remake the file). +scripts/Kbuild.include: ; +include scripts/Kbuild.include + +# Read KERNELRELEASE from include/config/kernel.release (if it exists) +KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) +KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) +export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION + # SUBARCH tells the usermode build what the underlying arch is. That is set # first, and if a usermode build is happening, the "ARCH=um" on the command # line overrides the setting of ARCH below. If a native build is happening, @@ -308,40 +370,6 @@ HOSTCFLAGS += -Wno-unused-value -Wno-unused-parameter \ -Wno-missing-field-initializers -fno-delete-null-pointer-checks endif -# Decide whether to build built-in, modular, or both. -# Normally, just do built-in. - -KBUILD_MODULES := -KBUILD_BUILTIN := 1 - -# If we have only "make modules", don't compile built-in objects. -# When we're building modules with modversions, we need to consider -# the built-in objects during the descend as well, in order to -# make sure the checksums are up to date before we record them. - -ifeq ($(MAKECMDGOALS),modules) - KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1) -endif - -# If we have "make modules", compile modules -# in addition to whatever we do anyway. -# Just "make" or "make all" shall build modules as well - -ifneq ($(filter all _all modules,$(MAKECMDGOALS)),) - KBUILD_MODULES := 1 -endif - -ifeq ($(MAKECMDGOALS),) - KBUILD_MODULES := 1 -endif - -export KBUILD_MODULES KBUILD_BUILTIN -export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD - -# We need some generic definitions (do not try to remake the file). -scripts/Kbuild.include: ; -include scripts/Kbuild.include - # Make variables (CC, etc...) AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld @@ -406,11 +434,6 @@ KBUILD_AFLAGS_MODULE := -DMODULE KBUILD_CFLAGS_MODULE := -DMODULE KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds -# Read KERNELRELEASE from include/config/kernel.release (if it exists) -KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) -KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) - -export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC export CPP AR NM STRIP OBJCOPY OBJDUMP HOSTLDFLAGS HOST_LOADLIBES export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE @@ -459,73 +482,6 @@ ifneq ($(KBUILD_SRC),) $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) endif -# Support for using generic headers in asm-generic -PHONY += asm-generic uapi-asm-generic -asm-generic: uapi-asm-generic - $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ - src=asm obj=arch/$(SRCARCH)/include/generated/asm -uapi-asm-generic: - $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ - src=uapi/asm obj=arch/$(SRCARCH)/include/generated/uapi/asm - -# To make sure we do not include .config for any of the *config targets -# catch them early, and hand them over to scripts/kconfig/Makefile -# It is allowed to specify more targets when calling make, including -# mixing *config targets and build targets. -# For example 'make oldconfig all'. -# Detect when mixed targets is specified, and make a second invocation -# of make so .config is not included in this case either (for *config). - -version_h := include/generated/uapi/linux/version.h -old_version_h := include/linux/version.h - -no-dot-config-targets := clean mrproper distclean \ - cscope gtags TAGS tags help% %docs check% coccicheck \ - $(version_h) headers_% archheaders archscripts \ - kernelversion %src-pkg - -config-targets := 0 -mixed-targets := 0 -dot-config := 1 - -ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) - ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) - dot-config := 0 - endif -endif - -ifeq ($(KBUILD_EXTMOD),) - ifneq ($(filter config %config,$(MAKECMDGOALS)),) - config-targets := 1 - ifneq ($(words $(MAKECMDGOALS)),1) - mixed-targets := 1 - endif - endif -endif -# install and modules_install need also be processed one by one -ifneq ($(filter install,$(MAKECMDGOALS)),) - ifneq ($(filter modules_install,$(MAKECMDGOALS)),) - mixed-targets := 1 - endif -endif - -ifeq ($(mixed-targets),1) -# =========================================================================== -# We're called with mixed targets (*config and build targets). -# Handle them one by one. - -PHONY += $(MAKECMDGOALS) __build_one_by_one - -$(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one - @: - -__build_one_by_one: - $(Q)set -e; \ - for i in $(MAKECMDGOALS); do \ - $(MAKE) -f $(srctree)/Makefile $$i; \ - done - -else ifeq ($(config-targets),1) # =========================================================================== # *config targets only - make sure prerequisites are updated, and descend @@ -548,6 +504,44 @@ else # Build targets only - this includes vmlinux, arch specific targets, clean # targets and others. In general all targets except *config targets. +# If building an external module we do not care about the all: rule +# but instead _all depend on modules +PHONY += all +ifeq ($(KBUILD_EXTMOD),) +_all: all +else +_all: modules +endif + +# Decide whether to build built-in, modular, or both. +# Normally, just do built-in. + +KBUILD_MODULES := +KBUILD_BUILTIN := 1 + +# If we have only "make modules", don't compile built-in objects. +# When we're building modules with modversions, we need to consider +# the built-in objects during the descend as well, in order to +# make sure the checksums are up to date before we record them. + +ifeq ($(MAKECMDGOALS),modules) + KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1) +endif + +# If we have "make modules", compile modules +# in addition to whatever we do anyway. +# Just "make" or "make all" shall build modules as well + +ifneq ($(filter all _all modules,$(MAKECMDGOALS)),) + KBUILD_MODULES := 1 +endif + +ifeq ($(MAKECMDGOALS),) + KBUILD_MODULES := 1 +endif + +export KBUILD_MODULES KBUILD_BUILTIN + ifeq ($(KBUILD_EXTMOD),) # Additional helpers built in scripts/ # Carefully list dependencies so we do not try to build scripts twice @@ -1063,6 +1057,15 @@ prepare0: archprepare gcc-plugins # All the preparing.. prepare: prepare0 prepare-objtool +# Support for using generic headers in asm-generic +PHONY += asm-generic uapi-asm-generic +asm-generic: uapi-asm-generic + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ + src=asm obj=arch/$(SRCARCH)/include/generated/asm +uapi-asm-generic: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ + src=uapi/asm obj=arch/$(SRCARCH)/include/generated/uapi/asm + PHONY += prepare-objtool prepare-objtool: $(objtool_target) -- GitLab From 90d4fa4540f16df552b4bac480a032552e594fc3 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 17 Sep 2017 16:13:52 +0200 Subject: [PATCH 1064/2898] mtd: spi-nor: Kill check with no effect header.minor is of type u8 and cannot be negative. Detected by CoverityScan CID#1417858 ("Integer handling issues") Fixes: f384b352cbf0 ("mtd: spi-nor: parse Serial Flash Discoverable Parameters (SFDP) tables") Signed-off-by: Richard Weinberger Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 19c000722cbc..33f6fc1b0eab 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2288,8 +2288,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, /* Check the SFDP header version. */ if (le32_to_cpu(header.signature) != SFDP_SIGNATURE || - header.major != SFDP_JESD216_MAJOR || - header.minor < SFDP_JESD216_MINOR) + header.major != SFDP_JESD216_MAJOR) return -EINVAL; /* -- GitLab From 46dde01f6bab35d99af111fcc02ca3ee1146050f Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Tue, 22 Aug 2017 16:45:21 -0400 Subject: [PATCH 1065/2898] mtd: spi-nor: add spi_nor_init() function This patch extracts some chunks from spi_nor_init_params and spi_nor_scan() and moves them into a new spi_nor_init() function. Indeed, spi_nor_init() regroups all the required SPI flash commands to be sent to the SPI flash memory before performing any runtime operations (Fast Read, Page Program, Sector Erase, ...). Hence spi_nor_init(): 1) removes the flash protection if applicable for certain vendors. 2) sets the Quad Enable bit, if needed, before using Quad SPI protocols. 3) makes the memory enter its (stateful) 4-byte address mode, if needed, for SPI flash memory > 128Mbits not supporting the 4-byte address instruction set. spi_nor_scan() now ends by calling spi_nor_init() once the probe phase has completed. Further patches could also use spi_nor_init() to implement the mtd->_resume() handler for the spi-nor framework. Signed-off-by: Kamal Dasu Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 56 ++++++++++++++++++++++++----------- include/linux/mtd/spi-nor.h | 10 +++++++ 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 33f6fc1b0eab..04751a73c3fe 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2629,14 +2629,44 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, /* Enable Quad I/O if needed. */ enable_quad_io = (spi_nor_get_protocol_width(nor->read_proto) == 4 || spi_nor_get_protocol_width(nor->write_proto) == 4); - if (enable_quad_io && params->quad_enable) { - err = params->quad_enable(nor); + if (enable_quad_io && params->quad_enable) + nor->quad_enable = params->quad_enable; + else + nor->quad_enable = NULL; + + return 0; +} + +static int spi_nor_init(struct spi_nor *nor) +{ + int err; + + /* + * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up + * with the software protection bits set + */ + if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL || + JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || + JEDEC_MFR(nor->info) == SNOR_MFR_SST || + nor->info->flags & SPI_NOR_HAS_LOCK) { + write_enable(nor); + write_sr(nor, 0); + spi_nor_wait_till_ready(nor); + } + + if (nor->quad_enable) { + err = nor->quad_enable(nor); if (err) { dev_err(nor->dev, "quad mode not supported\n"); return err; } } + if ((nor->addr_width == 4) && + (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) && + !(nor->info->flags & SPI_NOR_4B_OPCODES)) + set_4byte(nor, nor->info, 1); + return 0; } @@ -2707,20 +2737,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, if (ret) return ret; - /* - * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up - * with the software protection bits set - */ - - if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || - JEDEC_MFR(info) == SNOR_MFR_INTEL || - JEDEC_MFR(info) == SNOR_MFR_SST || - info->flags & SPI_NOR_HAS_LOCK) { - write_enable(nor); - write_sr(nor, 0); - spi_nor_wait_till_ready(nor); - } - if (!mtd->name) mtd->name = dev_name(dev); mtd->priv = nor; @@ -2803,8 +2819,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || info->flags & SPI_NOR_4B_OPCODES) spi_nor_set_4byte_opcodes(nor, info); - else - set_4byte(nor, info, 1); } else { nor->addr_width = 3; } @@ -2821,6 +2835,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, return ret; } + /* Send all the required SPI flash commands to initialize device */ + nor->info = info; + ret = spi_nor_init(nor); + if (ret) + return ret; + dev_info(dev, "%s (%lld Kbytes)\n", info->name, (long long)mtd->size >> 10); diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 1f0a7fc7772f..d0c66a0975cf 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -231,11 +231,18 @@ enum spi_nor_option_flags { SNOR_F_USE_CLSR = BIT(5), }; +/** + * struct flash_info - Forward declaration of a structure used internally by + * spi_nor_scan() + */ +struct flash_info; + /** * struct spi_nor - Structure for defining a the SPI NOR layer * @mtd: point to a mtd_info structure * @lock: the lock for the read/write/erase/lock/unlock operations * @dev: point to a spi device, or a spi nor controller device. + * @info: spi-nor part JDEC MFR id and other info * @page_size: the page size of the SPI NOR * @addr_width: number of address bytes * @erase_opcode: the opcode for erasing a sector @@ -262,6 +269,7 @@ enum spi_nor_option_flags { * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is + * @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode * completely locked * @priv: the private data */ @@ -269,6 +277,7 @@ struct spi_nor { struct mtd_info mtd; struct mutex lock; struct device *dev; + const struct flash_info *info; u32 page_size; u8 addr_width; u8 erase_opcode; @@ -296,6 +305,7 @@ struct spi_nor { int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*quad_enable)(struct spi_nor *nor); void *priv; }; -- GitLab From d6084fc83c8249779a6b7a1d48830f1f3fc120fe Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Tue, 22 Aug 2017 16:45:22 -0400 Subject: [PATCH 1066/2898] mtd: spi-nor: Add spi-nor mtd resume handler Implemented and populated spi-nor mtd PM handlers for resume ops. spi-nor resume op re-initializes spi-nor flash to its probed state by calling the newly implemented spi_nor_init() function. Signed-off-by: Kamal Dasu Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 04751a73c3fe..61fdd3c1a2bc 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2670,6 +2670,19 @@ static int spi_nor_init(struct spi_nor *nor) return 0; } +/* mtd resume handler */ +static void spi_nor_resume(struct mtd_info *mtd) +{ + struct spi_nor *nor = mtd_to_spi_nor(mtd); + struct device *dev = nor->dev; + int ret; + + /* re-initialize the nor chip */ + ret = spi_nor_init(nor); + if (ret) + dev_err(dev, "resume() failed\n"); +} + int spi_nor_scan(struct spi_nor *nor, const char *name, const struct spi_nor_hwcaps *hwcaps) { @@ -2746,6 +2759,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, mtd->size = params.size; mtd->_erase = spi_nor_erase; mtd->_read = spi_nor_read; + mtd->_resume = spi_nor_resume; /* NOR protection support for STmicro/Micron chips and similar */ if (JEDEC_MFR(info) == SNOR_MFR_MICRON || -- GitLab From 70597eec673bad7c43b56ea23b666a951522aad1 Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Fri, 29 Sep 2017 11:07:49 -0500 Subject: [PATCH 1067/2898] mtd: spi-nor: Allow Cadence QSPI support for ARM64 Allow ARM64 support for the Cadence QSPI interface by adding ARM64 as a dependency. Signed-off-by: Thor Thayer Reviewed-by: Marek Vasut Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 69c638dd0484..f26aaa6d1430 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -50,7 +50,7 @@ config SPI_ATMEL_QUADSPI config SPI_CADENCE_QUADSPI tristate "Cadence Quad SPI controller" - depends on OF && (ARM || COMPILE_TEST) + depends on OF && (ARM || ARM64 || COMPILE_TEST) help Enable support for the Cadence Quad SPI Flash controller. -- GitLab From e27072851bf7d706c592fc528549b52023b17a09 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Mon, 28 Aug 2017 09:58:29 +0800 Subject: [PATCH 1068/2898] mtd: spi-nor: add a quad_enable callback in struct flash_info Some manufacturers may use different bit to set QE on different memories. The GD25Q256 from GigaDevice is an example, which uses S6(bit 6 of the Status Register-1) to set QE, which is different with other supported memories from GigaDevice that use S9(bit 1 of the Status Register-2). This makes it is impossible to select the quad enable method by distinguishing the MFR. This patch introduce a quad_enable function which can be set per memory in the flash_info list table. Signed-off-by: Andy Yan Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 61fdd3c1a2bc..a50ea46298e6 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -89,6 +89,8 @@ struct flash_info { #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ #define USE_CLSR BIT(14) /* use CLSR command */ + + int (*quad_enable)(struct spi_nor *nor); }; #define JEDEC_MFR(info) ((info)->id[0]) @@ -2426,6 +2428,15 @@ static int spi_nor_init_params(struct spi_nor *nor, params->quad_enable = spansion_quad_enable; break; } + + /* + * Some manufacturer like GigaDevice may use different + * bit to set QE on different memories, so the MFR can't + * indicate the quad_enable method for this case, we need + * set it in flash info list. + */ + if (info->quad_enable) + params->quad_enable = info->quad_enable; } /* Override the parameters with data read from SFDP tables. */ -- GitLab From 65153846b18c486ce3c90477c467d53915114e3f Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Mon, 28 Aug 2017 10:00:46 +0800 Subject: [PATCH 1069/2898] mtd: spi-nor: add support for GD25Q256 Add support for GD25Q256, a 32MiB SPI Nor flash from GigaDevice. Signed-off-by: Andy Yan Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index a50ea46298e6..85ac588e995d 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -872,6 +872,8 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) return ret; } +static int macronix_quad_enable(struct spi_nor *nor); + /* Used when the "_ext_id" is two bytes at most */ #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ .id = { \ @@ -999,6 +1001,12 @@ static const struct flash_info spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, + { + "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + .quad_enable = macronix_quad_enable, + }, /* Intel/Numonyx -- xxxs33b */ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, -- GitLab From 5a0682835ca270c6a4f8a1bdaa59e710f6968f62 Mon Sep 17 00:00:00 2001 From: Klaus Goger Date: Wed, 13 Sep 2017 10:25:35 +0200 Subject: [PATCH 1070/2898] mtd: spi-nor: add support for Gigadevice GD25LQ32 Tested against GD25LQ32D but the GD25LQ32C datasheet seems to be identically feature-wise. Therefore dropping the suffix as it's probably only indicating the die revision. Signed-off-by: Klaus Goger Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 85ac588e995d..3128d8c4fa6f 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -986,6 +986,11 @@ static const struct flash_info spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, + { + "gd25lq32", INFO(0xc86016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | -- GitLab From d92b0f18a2039ff736b4296ad3cf3d505512051e Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 21 Sep 2017 16:19:45 +0300 Subject: [PATCH 1071/2898] mtd: spi-nor: intel-spi: Add support for Intel Lewisburg SPI serial flash Intel Lewisburg chipset exposes the SPI serial flash controller as a PCI device in the same way than Intel Denverton. Add Intel Lewisburg SPI serial flash PCI ID to the driver list of supported devices. Signed-off-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi-nor/intel-spi-pci.c b/drivers/mtd/spi-nor/intel-spi-pci.c index e82652335ede..7fa5b81b0d88 100644 --- a/drivers/mtd/spi-nor/intel-spi-pci.c +++ b/drivers/mtd/spi-nor/intel-spi-pci.c @@ -64,6 +64,7 @@ static void intel_spi_pci_remove(struct pci_dev *pdev) static const struct pci_device_id intel_spi_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, + { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info }, { }, }; MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids); -- GitLab From 824af37ef2d054d1f89bd2b9125755a4acc37332 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 21 Sep 2017 16:19:46 +0300 Subject: [PATCH 1072/2898] mtd: spi-nor: intel-spi: Add support for Intel Cedar Fork SPI serial flash Intel Cedar Fork has the same SPI serial flash controller than Intel Denverton. Add the Intel Cedar Fork PCI ID to the driver list of supported devices. Signed-off-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi-nor/intel-spi-pci.c b/drivers/mtd/spi-nor/intel-spi-pci.c index 7fa5b81b0d88..a5a5c5897aad 100644 --- a/drivers/mtd/spi-nor/intel-spi-pci.c +++ b/drivers/mtd/spi-nor/intel-spi-pci.c @@ -63,6 +63,7 @@ static void intel_spi_pci_remove(struct pci_dev *pdev) } static const struct pci_device_id intel_spi_pci_ids[] = { + { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info }, { }, -- GitLab From d59158162e032917a428704160a2063a02405ec6 Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Tue, 10 Oct 2017 15:51:37 -0700 Subject: [PATCH 1073/2898] tracing: Add support for preempt and irq enable/disable events Preempt and irq trace events can be used for tracing the start and end of an atomic section which can be used by a trace viewer like systrace to graphically view the start and end of an atomic section and correlate them with latencies and scheduling issues. This also serves as a prelude to using synthetic events or probes to rewrite the preempt and irqsoff tracers, along with numerous benefits of using trace events features for these events. Link: http://lkml.kernel.org/r/20171006005432.14244-3-joelaf@google.com Link: http://lkml.kernel.org/r/20171010225137.17370-1-joelaf@google.com Cc: Peter Zilstra Cc: kernel-team@android.com Signed-off-by: Joel Fernandes Signed-off-by: Steven Rostedt (VMware) --- include/linux/ftrace.h | 3 +- include/trace/events/preemptirq.h | 70 +++++++++++++++++++++++++++++++ kernel/trace/Kconfig | 11 +++++ kernel/trace/Makefile | 1 + kernel/trace/trace_irqsoff.c | 35 +++++++++++++++- 5 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 include/trace/events/preemptirq.h diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 346f8294e40a..1f8545caa691 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -769,7 +769,8 @@ static inline unsigned long get_lock_parent_ip(void) static inline void time_hardirqs_off(unsigned long a0, unsigned long a1) { } #endif -#ifdef CONFIG_PREEMPT_TRACER +#if defined(CONFIG_PREEMPT_TRACER) || \ + (defined(CONFIG_DEBUG_PREEMPT) && defined(CONFIG_PREEMPTIRQ_EVENTS)) extern void trace_preempt_on(unsigned long a0, unsigned long a1); extern void trace_preempt_off(unsigned long a0, unsigned long a1); #else diff --git a/include/trace/events/preemptirq.h b/include/trace/events/preemptirq.h new file mode 100644 index 000000000000..f5024c560d8f --- /dev/null +++ b/include/trace/events/preemptirq.h @@ -0,0 +1,70 @@ +#ifdef CONFIG_PREEMPTIRQ_EVENTS + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM preemptirq + +#if !defined(_TRACE_PREEMPTIRQ_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_PREEMPTIRQ_H + +#include +#include +#include +#include + +DECLARE_EVENT_CLASS(preemptirq_template, + + TP_PROTO(unsigned long ip, unsigned long parent_ip), + + TP_ARGS(ip, parent_ip), + + TP_STRUCT__entry( + __field(u32, caller_offs) + __field(u32, parent_offs) + ), + + TP_fast_assign( + __entry->caller_offs = (u32)(ip - (unsigned long)_stext); + __entry->parent_offs = (u32)(parent_ip - (unsigned long)_stext); + ), + + TP_printk("caller=%pF parent=%pF", + (void *)((unsigned long)(_stext) + __entry->caller_offs), + (void *)((unsigned long)(_stext) + __entry->parent_offs)) +); + +#ifndef CONFIG_PROVE_LOCKING +DEFINE_EVENT(preemptirq_template, irq_disable, + TP_PROTO(unsigned long ip, unsigned long parent_ip), + TP_ARGS(ip, parent_ip)); + +DEFINE_EVENT(preemptirq_template, irq_enable, + TP_PROTO(unsigned long ip, unsigned long parent_ip), + TP_ARGS(ip, parent_ip)); +#endif + +#ifdef CONFIG_DEBUG_PREEMPT +DEFINE_EVENT(preemptirq_template, preempt_disable, + TP_PROTO(unsigned long ip, unsigned long parent_ip), + TP_ARGS(ip, parent_ip)); + +DEFINE_EVENT(preemptirq_template, preempt_enable, + TP_PROTO(unsigned long ip, unsigned long parent_ip), + TP_ARGS(ip, parent_ip)); +#endif + +#endif /* _TRACE_PREEMPTIRQ_H */ + +#include + +#else /* !CONFIG_PREEMPTIRQ_EVENTS */ + +#define trace_irq_enable(...) +#define trace_irq_disable(...) +#define trace_preempt_enable(...) +#define trace_preempt_disable(...) +#define trace_irq_enable_rcuidle(...) +#define trace_irq_disable_rcuidle(...) +#define trace_preempt_enable_rcuidle(...) +#define trace_preempt_disable_rcuidle(...) + +#endif diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 434c840e2d82..b8395a020821 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -160,6 +160,17 @@ config FUNCTION_GRAPH_TRACER address on the current task structure into a stack of calls. +config PREEMPTIRQ_EVENTS + bool "Enable trace events for preempt and irq disable/enable" + select TRACE_IRQFLAGS + depends on DEBUG_PREEMPT || !PROVE_LOCKING + default n + help + Enable tracing of disable and enable events for preemption and irqs. + For tracing preempt disable/enable events, DEBUG_PREEMPT must be + enabled. For tracing irq disable/enable events, PROVE_LOCKING must + be disabled. + config IRQSOFF_TRACER bool "Interrupts-off Latency Tracer" default n diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 90f2701d92a7..9f62eee61f14 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_TRACING) += trace_printk.o obj-$(CONFIG_TRACING_MAP) += tracing_map.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o +obj-$(CONFIG_PREEMPTIRQ_EVENTS) += trace_irqsoff.o obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o obj-$(CONFIG_SCHED_TRACER) += trace_sched_wakeup.o diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 0e3033c00474..03ecb4465ee4 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -16,6 +16,9 @@ #include "trace.h" +#define CREATE_TRACE_POINTS +#include + #if defined(CONFIG_IRQSOFF_TRACER) || defined(CONFIG_PREEMPT_TRACER) static struct trace_array *irqsoff_trace __read_mostly; static int tracer_enabled __read_mostly; @@ -777,26 +780,53 @@ static inline void tracer_preempt_off(unsigned long a0, unsigned long a1) { } #endif #if defined(CONFIG_TRACE_IRQFLAGS) && !defined(CONFIG_PROVE_LOCKING) +/* Per-cpu variable to prevent redundant calls when IRQs already off */ +static DEFINE_PER_CPU(int, tracing_irq_cpu); + void trace_hardirqs_on(void) { + if (!this_cpu_read(tracing_irq_cpu)) + return; + + trace_irq_enable_rcuidle(CALLER_ADDR0, CALLER_ADDR1); tracer_hardirqs_on(); + + this_cpu_write(tracing_irq_cpu, 0); } EXPORT_SYMBOL(trace_hardirqs_on); void trace_hardirqs_off(void) { + if (this_cpu_read(tracing_irq_cpu)) + return; + + this_cpu_write(tracing_irq_cpu, 1); + + trace_irq_disable_rcuidle(CALLER_ADDR0, CALLER_ADDR1); tracer_hardirqs_off(); } EXPORT_SYMBOL(trace_hardirqs_off); __visible void trace_hardirqs_on_caller(unsigned long caller_addr) { + if (!this_cpu_read(tracing_irq_cpu)) + return; + + trace_irq_enable_rcuidle(CALLER_ADDR0, caller_addr); tracer_hardirqs_on_caller(caller_addr); + + this_cpu_write(tracing_irq_cpu, 0); } EXPORT_SYMBOL(trace_hardirqs_on_caller); __visible void trace_hardirqs_off_caller(unsigned long caller_addr) { + if (this_cpu_read(tracing_irq_cpu)) + return; + + this_cpu_write(tracing_irq_cpu, 1); + + trace_irq_disable_rcuidle(CALLER_ADDR0, caller_addr); tracer_hardirqs_off_caller(caller_addr); } EXPORT_SYMBOL(trace_hardirqs_off_caller); @@ -818,14 +848,17 @@ inline void print_irqtrace_events(struct task_struct *curr) } #endif -#ifdef CONFIG_PREEMPT_TRACER +#if defined(CONFIG_PREEMPT_TRACER) || \ + (defined(CONFIG_DEBUG_PREEMPT) && defined(CONFIG_PREEMPTIRQ_EVENTS)) void trace_preempt_on(unsigned long a0, unsigned long a1) { + trace_preempt_enable_rcuidle(a0, a1); tracer_preempt_on(a0, a1); } void trace_preempt_off(unsigned long a0, unsigned long a1) { + trace_preempt_disable_rcuidle(a0, a1); tracer_preempt_off(a0, a1); } #endif -- GitLab From 8715b108cd75523c9b2e833cdcd7aeb363767f95 Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Mon, 9 Oct 2017 12:29:31 -0700 Subject: [PATCH 1074/2898] ftrace: Clear hashes of stale ips of init memory Filters should be cleared of init functions during freeing of init memory when the ftrace dyn records are released. However in current code, the filters are left as is. This patch clears the hashes of the saved init functions when the init memory is freed. This fixes the following issue reproducible with the following sequence of commands for a test module: ================================================ void bar(void) { printk(KERN_INFO "bar!\n"); } void foo(void) { printk(KERN_INFO "foo!\n"); bar(); } static int __init hello_init(void) { printk(KERN_INFO "Hello world!\n"); foo(); return 0; } static void __exit hello_cleanup(void) { printk(KERN_INFO "Cleaning up module.\n"); } module_init(hello_init); module_exit(hello_cleanup); ================================================ Commands: echo '*:mod:test' > /d/tracing/set_ftrace_filter echo function > /d/tracing/current_tracer modprobe test rmmod test sleep 1 modprobe test cat /d/tracing/set_ftrace_filter Behavior without patch: Init function is still in the filter Expected behavior: Shouldn't have any of the filters set Link: http://lkml.kernel.org/r/20171009192931.56401-1-joelaf@google.com Signed-off-by: Joel Fernandes Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/ftrace.c | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 9e99bd55732e..e0a98225666b 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -6067,6 +6067,63 @@ allocate_ftrace_mod_map(struct module *mod, } #endif /* CONFIG_MODULES */ +struct ftrace_init_func { + struct list_head list; + unsigned long ip; +}; + +/* Clear any init ips from hashes */ +static void +clear_func_from_hash(struct ftrace_init_func *func, struct ftrace_hash *hash) +{ + struct ftrace_func_entry *entry; + + if (ftrace_hash_empty(hash)) + return; + + entry = __ftrace_lookup_ip(hash, func->ip); + + /* + * Do not allow this rec to match again. + * Yeah, it may waste some memory, but will be removed + * if/when the hash is modified again. + */ + if (entry) + entry->ip = 0; +} + +static void +clear_func_from_hashes(struct ftrace_init_func *func) +{ + struct trace_array *tr; + + mutex_lock(&trace_types_lock); + list_for_each_entry(tr, &ftrace_trace_arrays, list) { + if (!tr->ops || !tr->ops->func_hash) + continue; + mutex_lock(&tr->ops->func_hash->regex_lock); + clear_func_from_hash(func, tr->ops->func_hash->filter_hash); + clear_func_from_hash(func, tr->ops->func_hash->notrace_hash); + mutex_unlock(&tr->ops->func_hash->regex_lock); + } + mutex_unlock(&trace_types_lock); +} + +static void add_to_clear_hash_list(struct list_head *clear_list, + struct dyn_ftrace *rec) +{ + struct ftrace_init_func *func; + + func = kmalloc(sizeof(*func), GFP_KERNEL); + if (!func) { + WARN_ONCE(1, "alloc failure, ftrace filter could be stale\n"); + return; + } + + func->ip = rec->ip; + list_add(&func->list, clear_list); +} + void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) { unsigned long start = (unsigned long)(start_ptr); @@ -6076,8 +6133,12 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) struct dyn_ftrace *rec; struct dyn_ftrace key; struct ftrace_mod_map *mod_map = NULL; + struct ftrace_init_func *func, *func_next; + struct list_head clear_hash; int order; + INIT_LIST_HEAD(&clear_hash); + key.ip = start; key.flags = end; /* overload flags, as it is unsigned long */ @@ -6102,6 +6163,9 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) if (!rec) continue; + /* rec will be cleared from hashes after ftrace_lock unlock */ + add_to_clear_hash_list(&clear_hash, rec); + if (mod_map) save_ftrace_mod_rec(mod_map, rec); @@ -6123,6 +6187,11 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) goto again; } mutex_unlock(&ftrace_lock); + + list_for_each_entry_safe(func, func_next, &clear_hash, list) { + clear_func_from_hashes(func); + kfree(func); + } } void __init ftrace_free_init_mem(void) -- GitLab From 9cbb035cc111f5c6655f1026d4e7918282f6e137 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:51 -0700 Subject: [PATCH 1075/2898] spi-nor: intel-spi: Fix number of protected range registers for BYT/LPT The number of protected range registers is not the same on BYT/LPT/ BXT. GPR0 only exists on Apollo Lake and its offset is reserved on other platforms. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index 8a596bfeddff..e5b52e8b08ef 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -67,8 +67,6 @@ #define PR_LIMIT_MASK (0x3fff << PR_LIMIT_SHIFT) #define PR_RPE BIT(15) #define PR_BASE_MASK 0x3fff -/* Last PR is GPR0 */ -#define PR_NUM (5 + 1) /* Offsets are from @ispi->sregs */ #define SSFSTS_CTL 0x00 @@ -96,14 +94,17 @@ #define BYT_BCR 0xfc #define BYT_BCR_WPD BIT(0) #define BYT_FREG_NUM 5 +#define BYT_PR_NUM 5 #define LPT_PR 0x74 #define LPT_SSFSTS_CTL 0x90 #define LPT_FREG_NUM 5 +#define LPT_PR_NUM 5 #define BXT_PR 0x84 #define BXT_SSFSTS_CTL 0xa0 #define BXT_FREG_NUM 12 +#define BXT_PR_NUM 6 #define INTEL_SPI_TIMEOUT 5000 /* ms */ #define INTEL_SPI_FIFO_SZ 64 @@ -117,6 +118,7 @@ * @pregs: Start of protection registers * @sregs: Start of software sequencer registers * @nregions: Maximum number of regions + * @pr_num: Maximum number of protected range registers * @writeable: Is the chip writeable * @swseq: Use SW sequencer in register reads/writes * @erase_64k: 64k erase supported @@ -132,6 +134,7 @@ struct intel_spi { void __iomem *pregs; void __iomem *sregs; size_t nregions; + size_t pr_num; bool writeable; bool swseq; bool erase_64k; @@ -167,7 +170,7 @@ static void intel_spi_dump_regs(struct intel_spi *ispi) for (i = 0; i < ispi->nregions; i++) dev_dbg(ispi->dev, "FREG(%d)=0x%08x\n", i, readl(ispi->base + FREG(i))); - for (i = 0; i < PR_NUM; i++) + for (i = 0; i < ispi->pr_num; i++) dev_dbg(ispi->dev, "PR(%d)=0x%08x\n", i, readl(ispi->pregs + PR(i))); @@ -182,7 +185,7 @@ static void intel_spi_dump_regs(struct intel_spi *ispi) dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR)); dev_dbg(ispi->dev, "Protected regions:\n"); - for (i = 0; i < PR_NUM; i++) { + for (i = 0; i < ispi->pr_num; i++) { u32 base, limit; value = readl(ispi->pregs + PR(i)); @@ -286,6 +289,7 @@ static int intel_spi_init(struct intel_spi *ispi) ispi->sregs = ispi->base + BYT_SSFSTS_CTL; ispi->pregs = ispi->base + BYT_PR; ispi->nregions = BYT_FREG_NUM; + ispi->pr_num = BYT_PR_NUM; if (writeable) { /* Disable write protection */ @@ -305,12 +309,14 @@ static int intel_spi_init(struct intel_spi *ispi) ispi->sregs = ispi->base + LPT_SSFSTS_CTL; ispi->pregs = ispi->base + LPT_PR; ispi->nregions = LPT_FREG_NUM; + ispi->pr_num = LPT_PR_NUM; break; case INTEL_SPI_BXT: ispi->sregs = ispi->base + BXT_SSFSTS_CTL; ispi->pregs = ispi->base + BXT_PR; ispi->nregions = BXT_FREG_NUM; + ispi->pr_num = BXT_PR_NUM; ispi->erase_64k = true; break; @@ -652,7 +658,7 @@ static bool intel_spi_is_protected(const struct intel_spi *ispi, { int i; - for (i = 0; i < PR_NUM; i++) { + for (i = 0; i < ispi->pr_num; i++) { u32 pr_base, pr_limit, pr_value; pr_value = readl(ispi->pregs + PR(i)); -- GitLab From e58348b0e41b56660a349d63448826df11bb6163 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:52 -0700 Subject: [PATCH 1076/2898] spi-nor: intel-spi: Remove useless 'buf' parameter in the HW/SW cycle intel_spi_hw_cycle() and intel_spi_sw_cycle() don't use the parameter 'buf' at all. Remove it. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index e5b52e8b08ef..07626caa7b32 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -377,8 +377,7 @@ static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode) return -EINVAL; } -static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, u8 *buf, - int len) +static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, int len) { u32 val, status; int ret; @@ -418,8 +417,7 @@ static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, u8 *buf, return 0; } -static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, u8 *buf, - int len) +static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len) { u32 val, status; int ret; @@ -456,9 +454,9 @@ static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) writel(0, ispi->base + FADDR); if (ispi->swseq) - ret = intel_spi_sw_cycle(ispi, opcode, buf, len); + ret = intel_spi_sw_cycle(ispi, opcode, len); else - ret = intel_spi_hw_cycle(ispi, opcode, buf, len); + ret = intel_spi_hw_cycle(ispi, opcode, len); if (ret) return ret; @@ -486,8 +484,8 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) return ret; if (ispi->swseq) - return intel_spi_sw_cycle(ispi, opcode, buf, len); - return intel_spi_hw_cycle(ispi, opcode, buf, len); + return intel_spi_sw_cycle(ispi, opcode, len); + return intel_spi_hw_cycle(ispi, opcode, len); } static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, -- GitLab From 9d63f17661e25fd28714dac94bdebc4ff5b75f09 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:53 -0700 Subject: [PATCH 1077/2898] spi-nor: intel-spi: Fix broken software sequencing codes There are two bugs in current intel_spi_sw_cycle(): - The 'data byte count' field should be the number of bytes transferred minus 1 - SSFSTS_CTL is the offset from ispi->sregs, not ispi->base Signed-off-by: Bin Meng Cc: # v4.11+ Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index 07626caa7b32..263c6ab5849a 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -426,7 +426,7 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len) if (ret < 0) return ret; - val = (len << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS; + val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS; val |= ret << SSFSTS_CTL_COP_SHIFT; val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE; val |= SSFSTS_CTL_SCGO; @@ -436,7 +436,7 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len) if (ret) return ret; - status = readl(ispi->base + SSFSTS_CTL); + status = readl(ispi->sregs + SSFSTS_CTL); if (status & SSFSTS_CTL_FCERR) return -EIO; else if (status & SSFSTS_CTL_AEL) -- GitLab From db2ce7f3c7b01a6a3611fb8e0bfa453dec168a47 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:54 -0700 Subject: [PATCH 1078/2898] spi-nor: intel-spi: Check transfer length in the HW/SW cycle Intel SPI controller only has a 64 bytes FIFO. This adds a sanity check before triggering any HW/SW sequencer work. Additionally for the SW sequencer, if given data length is zero, we should not mark the 'Data Cycle' bit. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index 263c6ab5849a..c4a9de6b8045 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -399,6 +399,9 @@ static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, int len) return -EINVAL; } + if (len > INTEL_SPI_FIFO_SZ) + return -EINVAL; + val |= (len - 1) << HSFSTS_CTL_FDBC_SHIFT; val |= HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE; val |= HSFSTS_CTL_FGO; @@ -419,14 +422,19 @@ static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, int len) static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len) { - u32 val, status; + u32 val = 0, status; int ret; ret = intel_spi_opcode_index(ispi, opcode); if (ret < 0) return ret; - val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS; + if (len > INTEL_SPI_FIFO_SZ) + return -EINVAL; + + /* Only mark 'Data Cycle' bit when there is data to be transferred */ + if (len > 0) + val = ((len - 1) << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS; val |= ret << SSFSTS_CTL_COP_SHIFT; val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE; val |= SSFSTS_CTL_SCGO; -- GitLab From fc2b34726101016b2736d5025dde5a112e313577 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:55 -0700 Subject: [PATCH 1079/2898] spi-nor: intel-spi: Use SW sequencer for BYT/LPT Baytrail/Lynx Point SPI controller's HW sequencer only supports basic operations. This is determined by the chipset design, however current codes try to use register values in OPMENU0/OPMENU1 to see whether SW sequencer should be used, which is wrong. In fact OPMENU0/OPMENU1 can remain unprogrammed by some bootloaders. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index c4a9de6b8045..d0237fe5779c 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -290,6 +290,7 @@ static int intel_spi_init(struct intel_spi *ispi) ispi->pregs = ispi->base + BYT_PR; ispi->nregions = BYT_FREG_NUM; ispi->pr_num = BYT_PR_NUM; + ispi->swseq = true; if (writeable) { /* Disable write protection */ @@ -310,6 +311,7 @@ static int intel_spi_init(struct intel_spi *ispi) ispi->pregs = ispi->base + LPT_PR; ispi->nregions = LPT_FREG_NUM; ispi->pr_num = LPT_PR_NUM; + ispi->swseq = true; break; case INTEL_SPI_BXT: @@ -324,11 +326,23 @@ static int intel_spi_init(struct intel_spi *ispi) return -EINVAL; } - /* Disable #SMI generation */ + /* Disable #SMI generation from HW sequencer */ val = readl(ispi->base + HSFSTS_CTL); val &= ~HSFSTS_CTL_FSMIE; writel(val, ispi->base + HSFSTS_CTL); + /* + * Some controllers can only do basic operations using hardware + * sequencer. All other operations are supposed to be carried out + * using software sequencer. + */ + if (ispi->swseq) { + /* Disable #SMI generation from SW sequencer */ + val = readl(ispi->sregs + SSFSTS_CTL); + val &= ~SSFSTS_CTL_FSMIE; + writel(val, ispi->sregs + SSFSTS_CTL); + } + /* * BIOS programs allowed opcodes and then locks down the register. * So read back what opcodes it decided to support. That's the set @@ -337,13 +351,6 @@ static int intel_spi_init(struct intel_spi *ispi) opmenu0 = readl(ispi->sregs + OPMENU0); opmenu1 = readl(ispi->sregs + OPMENU1); - /* - * Some controllers can only do basic operations using hardware - * sequencer. All other operations are supposed to be carried out - * using software sequencer. If we find that BIOS has programmed - * opcodes for the software sequencer we use that over the hardware - * sequencer. - */ if (opmenu0 && opmenu1) { for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) { ispi->opcodes[i] = opmenu0 >> i * 8; @@ -353,13 +360,6 @@ static int intel_spi_init(struct intel_spi *ispi) val = readl(ispi->sregs + PREOP_OPTYPE); ispi->preopcodes[0] = val; ispi->preopcodes[1] = val >> 8; - - /* Disable #SMI generation from SW sequencer */ - val = readl(ispi->sregs + SSFSTS_CTL); - val &= ~SSFSTS_CTL_FSMIE; - writel(val, ispi->sregs + SSFSTS_CTL); - - ispi->swseq = true; } intel_spi_dump_regs(ispi); -- GitLab From aecf59e90a494f5d439415ce8d50064f6c644615 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:56 -0700 Subject: [PATCH 1080/2898] spi-nor: intel-spi: Remove 'Atomic Cycle Sequence' in intel_spi_write() So far intel_spi_write() uses the HW sequencer to do the write. But the HW sequencer register HSFSTS_CTL does not have such a field for 'Atomic Cycle Sequence', remove it. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index d0237fe5779c..757b9f14fd73 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -572,11 +572,6 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE; val |= (block_size - 1) << HSFSTS_CTL_FDBC_SHIFT; val |= HSFSTS_CTL_FCYCLE_WRITE; - - /* Write enable */ - if (ispi->preopcodes[1] == SPINOR_OP_WREN) - val |= SSFSTS_CTL_SPOP; - val |= SSFSTS_CTL_ACS; writel(val, ispi->base + HSFSTS_CTL); ret = intel_spi_write_block(ispi, write_buf, block_size); -- GitLab From 8c473dd61bb55f4d1576b50947b54d101553517b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:57 -0700 Subject: [PATCH 1081/2898] spi-nor: intel-spi: Don't assume OPMENU0/1 to be programmed by BIOS At present the driver relies on valid OPMENU0/OPMENU1 register values that are programmed by BIOS to function correctly. However in a real world it's absolutely legitimate for a bootloader to leave these two registers untouched. Intel FSP for Baytrail exactly does like this. When we are booting from any Intel FSP based bootloaders like U-Boot, the driver refuses to work. We can of course program various flash opcodes in the OPMENU0/OPMENU1 registers, and such workaround can be added in either the bootloader codes, or the kernel driver itself. But a graceful solution would be to update the kernel driver to remove such limitation of OPMENU0/1 register dependency. The SPI controller settings are not locked under such configuration. So we can first check the controller locking status, and if it is not locked that means the driver job can be fulfilled by using a chosen OPMENU index to set up the flash opcode every time. While we are here, the missing 'Atomic Cycle Sequence' handling in the SW sequencer codes is also added. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 91 +++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index 757b9f14fd73..07146ab19cac 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -88,6 +88,11 @@ #define OPMENU0 0x08 #define OPMENU1 0x0c +#define OPTYPE_READ_NO_ADDR 0 +#define OPTYPE_WRITE_NO_ADDR 1 +#define OPTYPE_READ_WITH_ADDR 2 +#define OPTYPE_WRITE_WITH_ADDR 3 + /* CPU specifics */ #define BYT_PR 0x74 #define BYT_SSFSTS_CTL 0x90 @@ -120,6 +125,7 @@ * @nregions: Maximum number of regions * @pr_num: Maximum number of protected range registers * @writeable: Is the chip writeable + * @locked: Is SPI setting locked * @swseq: Use SW sequencer in register reads/writes * @erase_64k: 64k erase supported * @opcodes: Opcodes which are supported. This are programmed by BIOS @@ -136,6 +142,7 @@ struct intel_spi { size_t nregions; size_t pr_num; bool writeable; + bool locked; bool swseq; bool erase_64k; u8 opcodes[8]; @@ -343,23 +350,29 @@ static int intel_spi_init(struct intel_spi *ispi) writel(val, ispi->sregs + SSFSTS_CTL); } - /* - * BIOS programs allowed opcodes and then locks down the register. - * So read back what opcodes it decided to support. That's the set - * we are going to support as well. - */ - opmenu0 = readl(ispi->sregs + OPMENU0); - opmenu1 = readl(ispi->sregs + OPMENU1); + /* Check controller's lock status */ + val = readl(ispi->base + HSFSTS_CTL); + ispi->locked = !!(val & HSFSTS_CTL_FLOCKDN); - if (opmenu0 && opmenu1) { - for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) { - ispi->opcodes[i] = opmenu0 >> i * 8; - ispi->opcodes[i + 4] = opmenu1 >> i * 8; - } + if (ispi->locked) { + /* + * BIOS programs allowed opcodes and then locks down the + * register. So read back what opcodes it decided to support. + * That's the set we are going to support as well. + */ + opmenu0 = readl(ispi->sregs + OPMENU0); + opmenu1 = readl(ispi->sregs + OPMENU1); - val = readl(ispi->sregs + PREOP_OPTYPE); - ispi->preopcodes[0] = val; - ispi->preopcodes[1] = val >> 8; + if (opmenu0 && opmenu1) { + for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) { + ispi->opcodes[i] = opmenu0 >> i * 8; + ispi->opcodes[i + 4] = opmenu1 >> i * 8; + } + + val = readl(ispi->sregs + PREOP_OPTYPE); + ispi->preopcodes[0] = val; + ispi->preopcodes[1] = val >> 8; + } } intel_spi_dump_regs(ispi); @@ -367,14 +380,25 @@ static int intel_spi_init(struct intel_spi *ispi) return 0; } -static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode) +static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode, int optype) { int i; + int preop; - for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) - if (ispi->opcodes[i] == opcode) - return i; - return -EINVAL; + if (ispi->locked) { + for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) + if (ispi->opcodes[i] == opcode) + return i; + + return -EINVAL; + } + + /* The lock is off, so just use index 0 */ + writel(opcode, ispi->sregs + OPMENU0); + preop = readw(ispi->sregs + PREOP_OPTYPE); + writel(optype << 16 | preop, ispi->sregs + PREOP_OPTYPE); + + return 0; } static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, int len) @@ -420,12 +444,14 @@ static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, int len) return 0; } -static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len) +static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len, + int optype) { u32 val = 0, status; + u16 preop; int ret; - ret = intel_spi_opcode_index(ispi, opcode); + ret = intel_spi_opcode_index(ispi, opcode, optype); if (ret < 0) return ret; @@ -438,6 +464,12 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, int len) val |= ret << SSFSTS_CTL_COP_SHIFT; val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE; val |= SSFSTS_CTL_SCGO; + preop = readw(ispi->sregs + PREOP_OPTYPE); + if (preop) { + val |= SSFSTS_CTL_ACS; + if (preop >> 8) + val |= SSFSTS_CTL_SPOP; + } writel(val, ispi->sregs + SSFSTS_CTL); ret = intel_spi_wait_sw_busy(ispi); @@ -462,7 +494,8 @@ static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) writel(0, ispi->base + FADDR); if (ispi->swseq) - ret = intel_spi_sw_cycle(ispi, opcode, len); + ret = intel_spi_sw_cycle(ispi, opcode, len, + OPTYPE_READ_NO_ADDR); else ret = intel_spi_hw_cycle(ispi, opcode, len); @@ -479,10 +512,15 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) /* * This is handled with atomic operation and preop code in Intel - * controller so skip it here now. + * controller so skip it here now. If the controller is not locked, + * program the opcode to the PREOP register for later use. */ - if (opcode == SPINOR_OP_WREN) + if (opcode == SPINOR_OP_WREN) { + if (!ispi->locked) + writel(opcode, ispi->sregs + PREOP_OPTYPE); + return 0; + } writel(0, ispi->base + FADDR); @@ -492,7 +530,8 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) return ret; if (ispi->swseq) - return intel_spi_sw_cycle(ispi, opcode, len); + return intel_spi_sw_cycle(ispi, opcode, len, + OPTYPE_WRITE_NO_ADDR); return intel_spi_hw_cycle(ispi, opcode, len); } -- GitLab From 6e995b84ce449758017d1eab5a91865158e3ceee Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:58 -0700 Subject: [PATCH 1082/2898] spi-nor: intel-spi: Remove the unnecessary HSFSTS register RW There is no code that alters the HSFSTS register content in between in intel_spi_write(). Remove the unnecessary RW to save some cycles. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index 07146ab19cac..91ceef7c9185 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -611,7 +611,6 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE; val |= (block_size - 1) << HSFSTS_CTL_FDBC_SHIFT; val |= HSFSTS_CTL_FCYCLE_WRITE; - writel(val, ispi->base + HSFSTS_CTL); ret = intel_spi_write_block(ispi, write_buf, block_size); if (ret) { @@ -620,8 +619,8 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, } /* Start the write now */ - val = readl(ispi->base + HSFSTS_CTL); - writel(val | HSFSTS_CTL_FGO, ispi->base + HSFSTS_CTL); + val |= HSFSTS_CTL_FGO; + writel(val, ispi->base + HSFSTS_CTL); ret = intel_spi_wait_hw_busy(ispi); if (ret) { -- GitLab From 2421f1ccbd4e7c8fc10c5f6a6e9cc403ace4e449 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:41:59 -0700 Subject: [PATCH 1083/2898] spi-nor: intel-spi: Rename swseq to swseq_reg in 'struct intel_spi' The ispi->swseq is used for register access. Let's rename it to swseq_reg to better describe its usage. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index 91ceef7c9185..5e7a38994e87 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -126,7 +126,7 @@ * @pr_num: Maximum number of protected range registers * @writeable: Is the chip writeable * @locked: Is SPI setting locked - * @swseq: Use SW sequencer in register reads/writes + * @swseq_reg: Use SW sequencer in register reads/writes * @erase_64k: 64k erase supported * @opcodes: Opcodes which are supported. This are programmed by BIOS * before it locks down the controller. @@ -143,7 +143,7 @@ struct intel_spi { size_t pr_num; bool writeable; bool locked; - bool swseq; + bool swseq_reg; bool erase_64k; u8 opcodes[8]; u8 preopcodes[2]; @@ -224,7 +224,7 @@ static void intel_spi_dump_regs(struct intel_spi *ispi) } dev_dbg(ispi->dev, "Using %cW sequencer for register access\n", - ispi->swseq ? 'S' : 'H'); + ispi->swseq_reg ? 'S' : 'H'); } /* Reads max INTEL_SPI_FIFO_SZ bytes from the device fifo */ @@ -297,7 +297,7 @@ static int intel_spi_init(struct intel_spi *ispi) ispi->pregs = ispi->base + BYT_PR; ispi->nregions = BYT_FREG_NUM; ispi->pr_num = BYT_PR_NUM; - ispi->swseq = true; + ispi->swseq_reg = true; if (writeable) { /* Disable write protection */ @@ -318,7 +318,7 @@ static int intel_spi_init(struct intel_spi *ispi) ispi->pregs = ispi->base + LPT_PR; ispi->nregions = LPT_FREG_NUM; ispi->pr_num = LPT_PR_NUM; - ispi->swseq = true; + ispi->swseq_reg = true; break; case INTEL_SPI_BXT: @@ -343,7 +343,7 @@ static int intel_spi_init(struct intel_spi *ispi) * sequencer. All other operations are supposed to be carried out * using software sequencer. */ - if (ispi->swseq) { + if (ispi->swseq_reg) { /* Disable #SMI generation from SW sequencer */ val = readl(ispi->sregs + SSFSTS_CTL); val &= ~SSFSTS_CTL_FSMIE; @@ -493,7 +493,7 @@ static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) /* Address of the first chip */ writel(0, ispi->base + FADDR); - if (ispi->swseq) + if (ispi->swseq_reg) ret = intel_spi_sw_cycle(ispi, opcode, len, OPTYPE_READ_NO_ADDR); else @@ -529,7 +529,7 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) if (ret) return ret; - if (ispi->swseq) + if (ispi->swseq_reg) return intel_spi_sw_cycle(ispi, opcode, len, OPTYPE_WRITE_NO_ADDR); return intel_spi_hw_cycle(ispi, opcode, len); -- GitLab From 3163d125b7b1f9c6844fc3448f8080ad268a8f63 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 11 Sep 2017 02:42:00 -0700 Subject: [PATCH 1084/2898] spi-nor: intel-spi: Fall back to use SW sequencer to erase According to the datasheet, the HW sequencer has a predefined list of opcodes, with only the erase opcode being programmable in LVSCC and UVSCC registers. If these registers don't contain a valid erase opcode (eg: BIOS does not program it), erase cannot be done using the HW sequencer, even though the erase operation does not report any error, the flash remains not erased. If such register setting is detected, let's fall back to use the SW sequencer to erase instead. Signed-off-by: Bin Meng Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi.c | 50 ++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c index 5e7a38994e87..ef034d898a23 100644 --- a/drivers/mtd/spi-nor/intel-spi.c +++ b/drivers/mtd/spi-nor/intel-spi.c @@ -111,6 +111,13 @@ #define BXT_FREG_NUM 12 #define BXT_PR_NUM 6 +#define LVSCC 0xc4 +#define UVSCC 0xc8 +#define ERASE_OPCODE_SHIFT 8 +#define ERASE_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT) +#define ERASE_64K_OPCODE_SHIFT 16 +#define ERASE_64K_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT) + #define INTEL_SPI_TIMEOUT 5000 /* ms */ #define INTEL_SPI_FIFO_SZ 64 @@ -127,6 +134,7 @@ * @writeable: Is the chip writeable * @locked: Is SPI setting locked * @swseq_reg: Use SW sequencer in register reads/writes + * @swseq_erase: Use SW sequencer in erase operation * @erase_64k: 64k erase supported * @opcodes: Opcodes which are supported. This are programmed by BIOS * before it locks down the controller. @@ -144,6 +152,7 @@ struct intel_spi { bool writeable; bool locked; bool swseq_reg; + bool swseq_erase; bool erase_64k; u8 opcodes[8]; u8 preopcodes[2]; @@ -191,6 +200,9 @@ static void intel_spi_dump_regs(struct intel_spi *ispi) if (ispi->info->type == INTEL_SPI_BYT) dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR)); + dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC)); + dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC)); + dev_dbg(ispi->dev, "Protected regions:\n"); for (i = 0; i < ispi->pr_num; i++) { u32 base, limit; @@ -225,6 +237,8 @@ static void intel_spi_dump_regs(struct intel_spi *ispi) dev_dbg(ispi->dev, "Using %cW sequencer for register access\n", ispi->swseq_reg ? 'S' : 'H'); + dev_dbg(ispi->dev, "Using %cW sequencer for erase operation\n", + ispi->swseq_erase ? 'S' : 'H'); } /* Reads max INTEL_SPI_FIFO_SZ bytes from the device fifo */ @@ -288,7 +302,7 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi) static int intel_spi_init(struct intel_spi *ispi) { - u32 opmenu0, opmenu1, val; + u32 opmenu0, opmenu1, lvscc, uvscc, val; int i; switch (ispi->info->type) { @@ -338,6 +352,24 @@ static int intel_spi_init(struct intel_spi *ispi) val &= ~HSFSTS_CTL_FSMIE; writel(val, ispi->base + HSFSTS_CTL); + /* + * Determine whether erase operation should use HW or SW sequencer. + * + * The HW sequencer has a predefined list of opcodes, with only the + * erase opcode being programmable in LVSCC and UVSCC registers. + * If these registers don't contain a valid erase opcode, erase + * cannot be done using HW sequencer. + */ + lvscc = readl(ispi->base + LVSCC); + uvscc = readl(ispi->base + UVSCC); + if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK)) + ispi->swseq_erase = true; + /* SPI controller on Intel BXT supports 64K erase opcode */ + if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase) + if (!(lvscc & ERASE_64K_OPCODE_MASK) || + !(uvscc & ERASE_64K_OPCODE_MASK)) + ispi->erase_64k = false; + /* * Some controllers can only do basic operations using hardware * sequencer. All other operations are supposed to be carried out @@ -665,6 +697,22 @@ static int intel_spi_erase(struct spi_nor *nor, loff_t offs) erase_size = SZ_4K; } + if (ispi->swseq_erase) { + while (len > 0) { + writel(offs, ispi->base + FADDR); + + ret = intel_spi_sw_cycle(ispi, nor->erase_opcode, + 0, OPTYPE_WRITE_WITH_ADDR); + if (ret) + return ret; + + offs += erase_size; + len -= erase_size; + } + + return 0; + } + while (len > 0) { writel(offs, ispi->base + FADDR); -- GitLab From 4e8975cbb516c5e4d1a5d026ffab1638409447d5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Oct 2017 11:15:12 +0200 Subject: [PATCH 1085/2898] clk: samsung: exynos5433: mark PM functions as __maybe_unused The suspend/resume functions are referenced conditionally, causing a harmless warning when CONFIG_PM is disabled: drivers/clk/samsung/clk-exynos5433.c:5476:12: error: 'exynos5433_cmu_resume' defined but not used [-Werror=unused-function] drivers/clk/samsung/clk-exynos5433.c:5453:12: error: 'exynos5433_cmu_suspend' defined but not used [-Werror=unused-function] This marks both as __maybe_unused to shut up the warning. Fixes: 523d3de41f02 ("clk: samsung: exynos5433: Add support for runtime PM") Signed-off-by: Arnd Bergmann Acked-by: Marek Szyprowski Acked-by: Chanwoo Choi Acked-by: Ulf Hansson Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index cd9337613dd8..db270908037a 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -5450,7 +5450,7 @@ struct exynos5433_cmu_data { struct samsung_clk_provider ctx; }; -static int exynos5433_cmu_suspend(struct device *dev) +static int __maybe_unused exynos5433_cmu_suspend(struct device *dev) { struct exynos5433_cmu_data *data = dev_get_drvdata(dev); int i; @@ -5473,7 +5473,7 @@ static int exynos5433_cmu_suspend(struct device *dev) return 0; } -static int exynos5433_cmu_resume(struct device *dev) +static int __maybe_unused exynos5433_cmu_resume(struct device *dev) { struct exynos5433_cmu_data *data = dev_get_drvdata(dev); int i; -- GitLab From 6aa211e8ce6916d8a0df88b4fbc790e9c78f5d9d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 25 Sep 2017 18:37:28 -0700 Subject: [PATCH 1086/2898] fix address space warnings in ipc/ Signed-off-by: Linus Torvalds Signed-off-by: Al Viro --- ipc/msg.c | 4 ++-- ipc/sem.c | 4 ++-- ipc/shm.c | 4 ++-- ipc/syscall.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ipc/msg.c b/ipc/msg.c index 06be5a9adfa4..ebb7ea24ee28 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -590,13 +590,13 @@ static int copy_compat_msqid_from_user(struct msqid64_ds *out, void __user *buf, { memset(out, 0, sizeof(*out)); if (version == IPC_64) { - struct compat_msqid64_ds *p = buf; + struct compat_msqid64_ds __user *p = buf; if (get_compat_ipc64_perm(&out->msg_perm, &p->msg_perm)) return -EFAULT; if (get_user(out->msg_qbytes, &p->msg_qbytes)) return -EFAULT; } else { - struct compat_msqid_ds *p = buf; + struct compat_msqid_ds __user *p = buf; if (get_compat_ipc_perm(&out->msg_perm, &p->msg_perm)) return -EFAULT; if (get_user(out->msg_qbytes, &p->msg_qbytes)) diff --git a/ipc/sem.c b/ipc/sem.c index f7385bce5fd3..6220e9616207 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1636,10 +1636,10 @@ static int copy_compat_semid_from_user(struct semid64_ds *out, void __user *buf, { memset(out, 0, sizeof(*out)); if (version == IPC_64) { - struct compat_semid64_ds *p = buf; + struct compat_semid64_ds __user *p = buf; return get_compat_ipc64_perm(&out->sem_perm, &p->sem_perm); } else { - struct compat_semid_ds *p = buf; + struct compat_semid_ds __user *p = buf; return get_compat_ipc_perm(&out->sem_perm, &p->sem_perm); } } diff --git a/ipc/shm.c b/ipc/shm.c index 1b3adfe3c60e..41706416a3c4 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -1193,10 +1193,10 @@ static int copy_compat_shmid_from_user(struct shmid64_ds *out, void __user *buf, { memset(out, 0, sizeof(*out)); if (version == IPC_64) { - struct compat_shmid64_ds *p = buf; + struct compat_shmid64_ds __user *p = buf; return get_compat_ipc64_perm(&out->shm_perm, &p->shm_perm); } else { - struct compat_shmid_ds *p = buf; + struct compat_shmid_ds __user *p = buf; return get_compat_ipc_perm(&out->shm_perm, &p->shm_perm); } } diff --git a/ipc/syscall.c b/ipc/syscall.c index 667022746ca5..977bffd5a7f8 100644 --- a/ipc/syscall.c +++ b/ipc/syscall.c @@ -171,7 +171,7 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second, COMPAT_SHMLBA); if (err < 0) return err; - return put_user(raddr, (compat_ulong_t *)compat_ptr(third)); + return put_user(raddr, (compat_ulong_t __user *)compat_ptr(third)); } case SHMDT: return sys_shmdt(compat_ptr(ptr)); -- GitLab From 0200894d11551a8abcff7872c2260d0801951f67 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 11 Oct 2017 13:48:55 -0400 Subject: [PATCH 1087/2898] new helper: destroy_unused_super() Used for disposal of super_block instances that had never been reachable via any shared data structures. No need for RCU delay in there, everything can be called directly. Signed-off-by: Al Viro --- fs/super.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/fs/super.c b/fs/super.c index 166c4ee0d0ed..01b7e3fd09e8 100644 --- a/fs/super.c +++ b/fs/super.c @@ -171,6 +171,21 @@ static void destroy_super(struct super_block *s) call_rcu(&s->rcu, destroy_super_rcu); } +/* Free a superblock that has never been seen by anyone */ +static void destroy_unused_super(struct super_block *s) +{ + if (!s) + return; + up_write(&s->s_umount); + list_lru_destroy(&s->s_dentry_lru); + list_lru_destroy(&s->s_inode_lru); + security_sb_free(s); + put_user_ns(s->s_user_ns); + kfree(s->s_subtype); + /* no delays needed */ + destroy_super_work(&s->destroy_work); +} + /** * alloc_super - create new superblock * @type: filesystem type superblock should belong to @@ -256,7 +271,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, return s; fail: - destroy_super(s); + destroy_unused_super(s); return NULL; } @@ -484,19 +499,12 @@ struct super_block *sget_userns(struct file_system_type *type, continue; if (user_ns != old->s_user_ns) { spin_unlock(&sb_lock); - if (s) { - up_write(&s->s_umount); - destroy_super(s); - } + destroy_unused_super(s); return ERR_PTR(-EBUSY); } if (!grab_super(old)) goto retry; - if (s) { - up_write(&s->s_umount); - destroy_super(s); - s = NULL; - } + destroy_unused_super(s); return old; } } @@ -511,8 +519,7 @@ struct super_block *sget_userns(struct file_system_type *type, err = set(s, data); if (err) { spin_unlock(&sb_lock); - up_write(&s->s_umount); - destroy_super(s); + destroy_unused_super(s); return ERR_PTR(err); } s->s_type = type; -- GitLab From c645b9309839be3f1543255db2abfe120f9d4f26 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 11 Oct 2017 13:48:55 -0400 Subject: [PATCH 1088/2898] fold destroy_super() into __put_super() There's only one caller of destroy_super() left now. Fold it there, and replace those list_lru_destroy() calls with checks that they had already been done (as they should have, when we were dropping the last active reference). Signed-off-by: Al Viro --- fs/super.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/fs/super.c b/fs/super.c index 01b7e3fd09e8..8ca15415351a 100644 --- a/fs/super.c +++ b/fs/super.c @@ -154,23 +154,6 @@ static void destroy_super_rcu(struct rcu_head *head) schedule_work(&s->destroy_work); } -/** - * destroy_super - frees a superblock - * @s: superblock to free - * - * Frees a superblock. - */ -static void destroy_super(struct super_block *s) -{ - list_lru_destroy(&s->s_dentry_lru); - list_lru_destroy(&s->s_inode_lru); - security_sb_free(s); - WARN_ON(!list_empty(&s->s_mounts)); - put_user_ns(s->s_user_ns); - kfree(s->s_subtype); - call_rcu(&s->rcu, destroy_super_rcu); -} - /* Free a superblock that has never been seen by anyone */ static void destroy_unused_super(struct super_block *s) { @@ -280,11 +263,17 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, /* * Drop a superblock's refcount. The caller must hold sb_lock. */ -static void __put_super(struct super_block *sb) +static void __put_super(struct super_block *s) { - if (!--sb->s_count) { - list_del_init(&sb->s_list); - destroy_super(sb); + if (!--s->s_count) { + list_del_init(&s->s_list); + WARN_ON(s->s_dentry_lru.node); + WARN_ON(s->s_inode_lru.node); + WARN_ON(!list_empty(&s->s_mounts)); + security_sb_free(s); + put_user_ns(s->s_user_ns); + kfree(s->s_subtype); + call_rcu(&s->rcu, destroy_super_rcu); } } -- GitLab From e9d4bf219c83d09579bc62512fea2ca10f025d93 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 10 Oct 2017 17:31:42 -0400 Subject: [PATCH 1089/2898] SUNRPC: Fix tracepoint storage issues with svc_recv and svc_rqst_status There is no guarantee that either the request or the svc_xprt exist by the time we get round to printing the trace message. Signed-off-by: Trond Myklebust Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- include/trace/events/sunrpc.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 8a707f8a41c3..8a13e3903839 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h @@ -455,20 +455,22 @@ TRACE_EVENT(svc_recv, TP_ARGS(rqst, status), TP_STRUCT__entry( - __field(struct sockaddr *, addr) __field(__be32, xid) __field(int, status) __field(unsigned long, flags) + __dynamic_array(unsigned char, addr, rqst->rq_addrlen) ), TP_fast_assign( - __entry->addr = (struct sockaddr *)&rqst->rq_addr; __entry->xid = status > 0 ? rqst->rq_xid : 0; __entry->status = status; __entry->flags = rqst->rq_flags; + memcpy(__get_dynamic_array(addr), + &rqst->rq_addr, rqst->rq_addrlen); ), - TP_printk("addr=%pIScp xid=0x%x status=%d flags=%s", __entry->addr, + TP_printk("addr=%pIScp xid=0x%x status=%d flags=%s", + (struct sockaddr *)__get_dynamic_array(addr), be32_to_cpu(__entry->xid), __entry->status, show_rqstp_flags(__entry->flags)) ); @@ -513,22 +515,23 @@ DECLARE_EVENT_CLASS(svc_rqst_status, TP_ARGS(rqst, status), TP_STRUCT__entry( - __field(struct sockaddr *, addr) __field(__be32, xid) - __field(int, dropme) __field(int, status) __field(unsigned long, flags) + __dynamic_array(unsigned char, addr, rqst->rq_addrlen) ), TP_fast_assign( - __entry->addr = (struct sockaddr *)&rqst->rq_addr; __entry->xid = rqst->rq_xid; __entry->status = status; __entry->flags = rqst->rq_flags; + memcpy(__get_dynamic_array(addr), + &rqst->rq_addr, rqst->rq_addrlen); ), TP_printk("addr=%pIScp rq_xid=0x%x status=%d flags=%s", - __entry->addr, be32_to_cpu(__entry->xid), + (struct sockaddr *)__get_dynamic_array(addr), + be32_to_cpu(__entry->xid), __entry->status, show_rqstp_flags(__entry->flags)) ); -- GitLab From 076098e51bd502402a7c166b5c2bb59a196e84e1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 23 Sep 2017 16:08:57 -0400 Subject: [PATCH 1090/2898] bio_map_user_iov(): switch to iov_iter_get_pages()/iov_iter_advance() ... and to hell with iov_for_each() nonsense Signed-off-by: Al Viro --- block/bio.c | 57 ++++++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/block/bio.c b/block/bio.c index 101c2a9b5481..5de54dedab66 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1328,7 +1328,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, struct page **pages; struct bio *bio; int cur_page = 0; - int ret, offset; + int ret; struct iov_iter i; struct iovec iov; struct bio_vec *bvec; @@ -1365,43 +1365,32 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (!pages) goto out; - iov_for_each(iov, i, *iter) { - unsigned long uaddr = (unsigned long) iov.iov_base; - unsigned long len = iov.iov_len; - unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; - unsigned long start = uaddr >> PAGE_SHIFT; - const int local_nr_pages = end - start; - const int page_limit = cur_page + local_nr_pages; - - ret = get_user_pages_fast(uaddr, local_nr_pages, - (iter->type & WRITE) != WRITE, - &pages[cur_page]); - if (unlikely(ret < local_nr_pages)) { - for (j = cur_page; j < page_limit; j++) { - if (!pages[j]) - break; - put_page(pages[j]); - } - ret = -EFAULT; + i = *iter; + while (iov_iter_count(&i)) { + ssize_t bytes; + size_t offs, added = 0; + int npages; + + bytes = iov_iter_get_pages(&i, pages + cur_page, LONG_MAX, + nr_pages - cur_page, &offs); + if (unlikely(bytes <= 0)) { + ret = bytes ? bytes : -EFAULT; goto out_unmap; } - offset = offset_in_page(uaddr); - for (j = cur_page; j < page_limit; j++) { - unsigned int bytes = PAGE_SIZE - offset; + npages = DIV_ROUND_UP(offs + bytes, PAGE_SIZE); + + for (j = cur_page; j < cur_page + npages; j++) { + unsigned int n = PAGE_SIZE - offs; unsigned short prev_bi_vcnt = bio->bi_vcnt; - if (len <= 0) - break; - - if (bytes > len) - bytes = len; + if (n > bytes) + n = bytes; /* * sorry... */ - if (bio_add_pc_page(q, bio, pages[j], bytes, offset) < - bytes) + if (bio_add_pc_page(q, bio, pages[j], n, offs) < n) break; /* @@ -1411,16 +1400,18 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (bio->bi_vcnt == prev_bi_vcnt) put_page(pages[j]); - len -= bytes; - offset = 0; + added += n; + bytes -= n; + offs = 0; } + iov_iter_advance(&i, added); - cur_page = j; /* * release the pages we didn't map into the bio, if any */ - while (j < page_limit) + while (j < cur_page + npages) put_page(pages[j++]); + cur_page = j; } kfree(pages); -- GitLab From 629e42bcc3d0bc04b4e0e40ef3f831507a4693bd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 23 Sep 2017 16:13:10 -0400 Subject: [PATCH 1091/2898] ... and with iov_iter_get_pages_alloc() it becomes even simpler Signed-off-by: Al Viro --- block/bio.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/block/bio.c b/block/bio.c index 5de54dedab66..5dbc5e90d716 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1325,9 +1325,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, { int j; int nr_pages = 0; - struct page **pages; struct bio *bio; - int cur_page = 0; int ret; struct iov_iter i; struct iovec iov; @@ -1360,19 +1358,14 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (!bio) return ERR_PTR(-ENOMEM); - ret = -ENOMEM; - pages = kcalloc(nr_pages, sizeof(struct page *), gfp_mask); - if (!pages) - goto out; - i = *iter; while (iov_iter_count(&i)) { + struct page **pages; ssize_t bytes; size_t offs, added = 0; int npages; - bytes = iov_iter_get_pages(&i, pages + cur_page, LONG_MAX, - nr_pages - cur_page, &offs); + bytes = iov_iter_get_pages_alloc(&i, &pages, LONG_MAX, &offs); if (unlikely(bytes <= 0)) { ret = bytes ? bytes : -EFAULT; goto out_unmap; @@ -1380,7 +1373,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, npages = DIV_ROUND_UP(offs + bytes, PAGE_SIZE); - for (j = cur_page; j < cur_page + npages; j++) { + for (j = 0; j < npages; j++) { unsigned int n = PAGE_SIZE - offs; unsigned short prev_bi_vcnt = bio->bi_vcnt; @@ -1409,13 +1402,11 @@ struct bio *bio_map_user_iov(struct request_queue *q, /* * release the pages we didn't map into the bio, if any */ - while (j < cur_page + npages) + while (j < npages) put_page(pages[j++]); - cur_page = j; + kvfree(pages); } - kfree(pages); - bio_set_flag(bio, BIO_USER_MAPPED); /* @@ -1431,8 +1422,6 @@ struct bio *bio_map_user_iov(struct request_queue *q, bio_for_each_segment_all(bvec, bio, j) { put_page(bvec->bv_page); } - out: - kfree(pages); bio_put(bio); return ERR_PTR(ret); } -- GitLab From e2e115d18b76467274d8f818f8828ba168f9c80b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 23 Sep 2017 16:16:06 -0400 Subject: [PATCH 1092/2898] don't rely upon subsequent bio_add_pc_page() calls failing ... they might actually succeed in some cases (when we are at the queue-imposed segments limit, the next page is not mergable with the last one we'd got in, but the first page covered by the next iovec *is* mergable). Make sure that once it's failed, we are done with that bio. Signed-off-by: Al Viro --- block/bio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/block/bio.c b/block/bio.c index 5dbc5e90d716..fe40948d62af 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1380,10 +1380,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (n > bytes) n = bytes; - /* - * sorry... - */ - if (bio_add_pc_page(q, bio, pages[j], n, offs) < n) + if (!bio_add_pc_page(q, bio, pages[j], n, offs)) break; /* @@ -1405,6 +1402,9 @@ struct bio *bio_map_user_iov(struct request_queue *q, while (j < npages) put_page(pages[j++]); kvfree(pages); + /* couldn't stuff something into bio? */ + if (bytes) + break; } bio_set_flag(bio, BIO_USER_MAPPED); -- GitLab From 98f0bc99055da5797fae0c35d3d18261d59df9ac Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 23 Sep 2017 16:23:18 -0400 Subject: [PATCH 1093/2898] bio_map_user_iov(): move alignment check into the main loop Signed-off-by: Al Viro --- block/bio.c | 54 ++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/block/bio.c b/block/bio.c index fe40948d62af..d851f68727f1 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1344,11 +1344,6 @@ struct bio *bio_map_user_iov(struct request_queue *q, return ERR_PTR(-EINVAL); nr_pages += end - start; - /* - * buffer must be aligned to at least logical block size for now - */ - if (uaddr & queue_dma_alignment(q)) - return ERR_PTR(-EINVAL); } if (!nr_pages) @@ -1373,29 +1368,34 @@ struct bio *bio_map_user_iov(struct request_queue *q, npages = DIV_ROUND_UP(offs + bytes, PAGE_SIZE); - for (j = 0; j < npages; j++) { - unsigned int n = PAGE_SIZE - offs; - unsigned short prev_bi_vcnt = bio->bi_vcnt; - - if (n > bytes) - n = bytes; - - if (!bio_add_pc_page(q, bio, pages[j], n, offs)) - break; - - /* - * check if vector was merged with previous - * drop page reference if needed - */ - if (bio->bi_vcnt == prev_bi_vcnt) - put_page(pages[j]); - - added += n; - bytes -= n; - offs = 0; + if (unlikely(offs & queue_dma_alignment(q))) { + ret = -EINVAL; + j = 0; + } else { + for (j = 0; j < npages; j++) { + struct page *page = pages[j]; + unsigned int n = PAGE_SIZE - offs; + unsigned short prev_bi_vcnt = bio->bi_vcnt; + + if (n > bytes) + n = bytes; + + if (!bio_add_pc_page(q, bio, page, n, offs)) + break; + + /* + * check if vector was merged with previous + * drop page reference if needed + */ + if (bio->bi_vcnt == prev_bi_vcnt) + put_page(page); + + added += n; + bytes -= n; + offs = 0; + } + iov_iter_advance(&i, added); } - iov_iter_advance(&i, added); - /* * release the pages we didn't map into the bio, if any */ -- GitLab From b282cc766958af161249b7b04d50e3eae12a2a1c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 23 Sep 2017 16:24:59 -0400 Subject: [PATCH 1094/2898] bio_map_user_iov(): get rid of the iov_for_each() Use iov_iter_npages() Signed-off-by: Al Viro --- block/bio.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/block/bio.c b/block/bio.c index d851f68727f1..d1ca7eecc8aa 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1324,32 +1324,15 @@ struct bio *bio_map_user_iov(struct request_queue *q, gfp_t gfp_mask) { int j; - int nr_pages = 0; struct bio *bio; int ret; struct iov_iter i; - struct iovec iov; struct bio_vec *bvec; - iov_for_each(iov, i, *iter) { - unsigned long uaddr = (unsigned long) iov.iov_base; - unsigned long len = iov.iov_len; - unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; - unsigned long start = uaddr >> PAGE_SHIFT; - - /* - * Overflow, abort - */ - if (end < start) - return ERR_PTR(-EINVAL); - - nr_pages += end - start; - } - - if (!nr_pages) + if (!iov_iter_count(iter)) return ERR_PTR(-EINVAL); - bio = bio_kmalloc(gfp_mask, nr_pages); + bio = bio_kmalloc(gfp_mask, iov_iter_npages(iter, BIO_MAX_PAGES)); if (!bio) return ERR_PTR(-ENOMEM); -- GitLab From e81cef5d3001501350b4e596b4bd6dfd26187afa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 09:25:39 -0400 Subject: [PATCH 1095/2898] blk_rq_map_user_iov(): move iov_iter_advance() down ... into bio_{map,copy}_user_iov() Signed-off-by: Al Viro --- block/bio.c | 6 ++++-- block/blk-map.c | 1 - include/linux/bio.h | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/block/bio.c b/block/bio.c index d1ca7eecc8aa..cd1282db03cb 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1195,7 +1195,7 @@ int bio_uncopy_user(struct bio *bio) */ struct bio *bio_copy_user_iov(struct request_queue *q, struct rq_map_data *map_data, - const struct iov_iter *iter, + struct iov_iter *iter, gfp_t gfp_mask) { struct bio_map_data *bmd; @@ -1298,6 +1298,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, if (ret) goto cleanup; } + iov_iter_advance(iter, bio->bi_iter.bi_size); bio->bi_private = bmd; return bio; @@ -1320,7 +1321,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, * device. Returns an error pointer in case of error. */ struct bio *bio_map_user_iov(struct request_queue *q, - const struct iov_iter *iter, + struct iov_iter *iter, gfp_t gfp_mask) { int j; @@ -1399,6 +1400,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, * reference to it */ bio_get(bio); + iov_iter_advance(iter, bio->bi_iter.bi_size); return bio; out_unmap: diff --git a/block/blk-map.c b/block/blk-map.c index 2547016aa7aa..891eea11f68e 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -69,7 +69,6 @@ static int __blk_rq_map_user_iov(struct request *rq, if (map_data && map_data->null_mapped) bio_set_flag(bio, BIO_NULL_MAPPED); - iov_iter_advance(iter, bio->bi_iter.bi_size); if (map_data) map_data->offset += bio->bi_iter.bi_size; diff --git a/include/linux/bio.h b/include/linux/bio.h index 275c91c99516..6050c0caa4e1 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -462,7 +462,7 @@ extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter); struct rq_map_data; extern struct bio *bio_map_user_iov(struct request_queue *, - const struct iov_iter *, gfp_t); + struct iov_iter *, gfp_t); extern void bio_unmap_user(struct bio *); extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int, gfp_t); @@ -494,7 +494,7 @@ extern void bio_free_pages(struct bio *bio); extern struct bio *bio_copy_user_iov(struct request_queue *, struct rq_map_data *, - const struct iov_iter *, + struct iov_iter *, gfp_t); extern int bio_uncopy_user(struct bio *); void zero_fill_bio(struct bio *bio); -- GitLab From 2884d0be878eb5cbbc6d983c6054feef3b9aa86d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 12:09:21 -0400 Subject: [PATCH 1096/2898] move more stuff down into bio_copy_user_iov() Signed-off-by: Al Viro --- block/bio.c | 5 +++++ block/blk-map.c | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/block/bio.c b/block/bio.c index cd1282db03cb..02457c2d4379 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1289,6 +1289,9 @@ struct bio *bio_copy_user_iov(struct request_queue *q, if (ret) goto cleanup; + if (map_data) + map_data->offset += bio->bi_iter.bi_size; + /* * success */ @@ -1301,6 +1304,8 @@ struct bio *bio_copy_user_iov(struct request_queue *q, iov_iter_advance(iter, bio->bi_iter.bi_size); bio->bi_private = bmd; + if (map_data && map_data->null_mapped) + bio_set_flag(bio, BIO_NULL_MAPPED); return bio; cleanup: if (!map_data) diff --git a/block/blk-map.c b/block/blk-map.c index 891eea11f68e..c872d62b62fb 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -66,12 +66,6 @@ static int __blk_rq_map_user_iov(struct request *rq, bio->bi_opf &= ~REQ_OP_MASK; bio->bi_opf |= req_op(rq); - if (map_data && map_data->null_mapped) - bio_set_flag(bio, BIO_NULL_MAPPED); - - if (map_data) - map_data->offset += bio->bi_iter.bi_size; - orig_bio = bio; /* -- GitLab From 98a09d6106660ec6e69ff2a6fa14039bd504412b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 12:14:36 -0400 Subject: [PATCH 1097/2898] bio_copy_from_iter(): get rid of copying iov_iter we want the one passed to it advanced, anyway Signed-off-by: Al Viro --- block/bio.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/block/bio.c b/block/bio.c index 02457c2d4379..f5002b44c963 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1088,7 +1088,7 @@ static struct bio_map_data *bio_alloc_map_data(unsigned int iov_count, * Copy all pages from iov_iter to bio. * Returns 0 on success, or error on failure. */ -static int bio_copy_from_iter(struct bio *bio, struct iov_iter iter) +static int bio_copy_from_iter(struct bio *bio, struct iov_iter *iter) { int i; struct bio_vec *bvec; @@ -1099,9 +1099,9 @@ static int bio_copy_from_iter(struct bio *bio, struct iov_iter iter) ret = copy_page_from_iter(bvec->bv_page, bvec->bv_offset, bvec->bv_len, - &iter); + iter); - if (!iov_iter_count(&iter)) + if (!iov_iter_count(iter)) break; if (ret < bvec->bv_len) @@ -1297,11 +1297,12 @@ struct bio *bio_copy_user_iov(struct request_queue *q, */ if (((iter->type & WRITE) && (!map_data || !map_data->null_mapped)) || (map_data && map_data->from_user)) { - ret = bio_copy_from_iter(bio, *iter); + ret = bio_copy_from_iter(bio, iter); if (ret) goto cleanup; + } else { + iov_iter_advance(iter, bio->bi_iter.bi_size); } - iov_iter_advance(iter, bio->bi_iter.bi_size); bio->bi_private = bmd; if (map_data && map_data->null_mapped) -- GitLab From 0a0f151364f5bf836ad1d4de6113adb103a6628c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 12:30:17 -0400 Subject: [PATCH 1098/2898] bio_map_user_iov(): get rid of copying iov_iter we do want *iter advanced Signed-off-by: Al Viro --- block/bio.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/block/bio.c b/block/bio.c index f5002b44c963..28f66e2edc53 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1333,7 +1333,6 @@ struct bio *bio_map_user_iov(struct request_queue *q, int j; struct bio *bio; int ret; - struct iov_iter i; struct bio_vec *bvec; if (!iov_iter_count(iter)) @@ -1343,14 +1342,13 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (!bio) return ERR_PTR(-ENOMEM); - i = *iter; - while (iov_iter_count(&i)) { + while (iov_iter_count(iter)) { struct page **pages; ssize_t bytes; size_t offs, added = 0; int npages; - bytes = iov_iter_get_pages_alloc(&i, &pages, LONG_MAX, &offs); + bytes = iov_iter_get_pages_alloc(iter, &pages, LONG_MAX, &offs); if (unlikely(bytes <= 0)) { ret = bytes ? bytes : -EFAULT; goto out_unmap; @@ -1384,7 +1382,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, bytes -= n; offs = 0; } - iov_iter_advance(&i, added); + iov_iter_advance(iter, added); } /* * release the pages we didn't map into the bio, if any @@ -1406,7 +1404,6 @@ struct bio *bio_map_user_iov(struct request_queue *q, * reference to it */ bio_get(bio); - iov_iter_advance(iter, bio->bi_iter.bi_size); return bio; out_unmap: -- GitLab From d16d44ebb016792285ec1b9566dbd9d022ce70f9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 13:09:18 -0400 Subject: [PATCH 1099/2898] bio_copy_user_iov(): saner bio size calculation it's a bounce buffer; we don't *care* how badly is the real source/destination fragmented, all that matters is the total size. Signed-off-by: Al Viro --- block/bio.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/block/bio.c b/block/bio.c index 28f66e2edc53..e87f70cd528e 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1201,33 +1201,11 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct bio_map_data *bmd; struct page *page; struct bio *bio; - int i, ret; - int nr_pages = 0; + int i = 0, ret; + int nr_pages; unsigned int len = iter->count; unsigned int offset = map_data ? offset_in_page(map_data->offset) : 0; - for (i = 0; i < iter->nr_segs; i++) { - unsigned long uaddr; - unsigned long end; - unsigned long start; - - uaddr = (unsigned long) iter->iov[i].iov_base; - end = (uaddr + iter->iov[i].iov_len + PAGE_SIZE - 1) - >> PAGE_SHIFT; - start = uaddr >> PAGE_SHIFT; - - /* - * Overflow, abort - */ - if (end < start) - return ERR_PTR(-EINVAL); - - nr_pages += end - start; - } - - if (offset) - nr_pages++; - bmd = bio_alloc_map_data(iter->nr_segs, gfp_mask); if (!bmd) return ERR_PTR(-ENOMEM); @@ -1242,6 +1220,10 @@ struct bio *bio_copy_user_iov(struct request_queue *q, bmd->iter = *iter; bmd->iter.iov = bmd->iov; + nr_pages = DIV_ROUND_UP(offset + len, PAGE_SIZE); + if (nr_pages > BIO_MAX_PAGES) + nr_pages = BIO_MAX_PAGES; + ret = -ENOMEM; bio = bio_kmalloc(gfp_mask, nr_pages); if (!bio) -- GitLab From 0e5b935d43f385ab23d2e38e7134b1abb0e7907e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 13:14:35 -0400 Subject: [PATCH 1100/2898] bio_alloc_map_data(): do bmd->iter setup right there just need to copy it iter instead of iter->nr_segs Signed-off-by: Al Viro --- block/bio.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/block/bio.c b/block/bio.c index e87f70cd528e..ad34cdb99ad2 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1070,14 +1070,21 @@ struct bio_map_data { struct iovec iov[]; }; -static struct bio_map_data *bio_alloc_map_data(unsigned int iov_count, +static struct bio_map_data *bio_alloc_map_data(struct iov_iter *data, gfp_t gfp_mask) { - if (iov_count > UIO_MAXIOV) + struct bio_map_data *bmd; + if (data->nr_segs > UIO_MAXIOV) return NULL; - return kmalloc(sizeof(struct bio_map_data) + - sizeof(struct iovec) * iov_count, gfp_mask); + bmd = kmalloc(sizeof(struct bio_map_data) + + sizeof(struct iovec) * data->nr_segs, gfp_mask); + if (!bmd) + return NULL; + memcpy(bmd->iov, data->iov, sizeof(struct iovec) * data->nr_segs); + bmd->iter = *data; + bmd->iter.iov = bmd->iov; + return bmd; } /** @@ -1206,7 +1213,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, unsigned int len = iter->count; unsigned int offset = map_data ? offset_in_page(map_data->offset) : 0; - bmd = bio_alloc_map_data(iter->nr_segs, gfp_mask); + bmd = bio_alloc_map_data(iter, gfp_mask); if (!bmd) return ERR_PTR(-ENOMEM); @@ -1216,9 +1223,6 @@ struct bio *bio_copy_user_iov(struct request_queue *q, * shortlived one. */ bmd->is_our_pages = map_data ? 0 : 1; - memcpy(bmd->iov, iter->iov, sizeof(struct iovec) * iter->nr_segs); - bmd->iter = *iter; - bmd->iter.iov = bmd->iov; nr_pages = DIV_ROUND_UP(offset + len, PAGE_SIZE); if (nr_pages > BIO_MAX_PAGES) -- GitLab From faea13297ea739f94913d56d7b865134b4fc8726 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 14:03:29 -0400 Subject: [PATCH 1101/2898] kill iov_shorten() Signed-off-by: Al Viro --- fs/read_write.c | 21 --------------------- include/linux/uio.h | 2 -- 2 files changed, 23 deletions(-) diff --git a/fs/read_write.c b/fs/read_write.c index f0d4b16873e8..b8bf2cb3298a 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -634,27 +634,6 @@ SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf, return ret; } -/* - * Reduce an iovec's length in-place. Return the resulting number of segments - */ -unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) -{ - unsigned long seg = 0; - size_t len = 0; - - while (seg < nr_segs) { - seg++; - if (len + iov->iov_len >= to) { - iov->iov_len = to - len; - break; - } - len += iov->iov_len; - iov++; - } - return seg; -} -EXPORT_SYMBOL(iov_shorten); - static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, loff_t *ppos, int type, rwf_t flags) { diff --git a/include/linux/uio.h b/include/linux/uio.h index 8a642cda641c..5885daeae721 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -80,8 +80,6 @@ static inline struct iovec iov_iter_iovec(const struct iov_iter *iter) ((iov = iov_iter_iovec(&(iter))), 1); \ iov_iter_advance(&(iter), (iov).iov_len)) -unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to); - size_t iov_iter_copy_from_user_atomic(struct page *page, struct iov_iter *i, unsigned long offset, size_t bytes); void iov_iter_advance(struct iov_iter *i, size_t bytes); -- GitLab From 6570f0dd6004b5b925b19666e9c60da432d197fd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 17:43:00 -0400 Subject: [PATCH 1102/2898] orangefs: remove detritus from struct orangefs_kiocb_s Signed-off-by: Al Viro --- fs/orangefs/orangefs-kernel.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index ea0ce507a6ab..937a5dd2cb14 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -274,12 +274,6 @@ struct orangefs_kiocb_s { /* orangefs kernel operation type */ struct orangefs_kernel_op_s *op; - /* The user space buffers from/to which I/O is being staged */ - struct iovec *iov; - - /* number of elements in the iovector */ - unsigned long nr_segs; - /* set to indicate the type of the operation */ int rw; -- GitLab From 83683dc6e017dabfd8c2c0e9301b94b8a2d01233 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 17:46:21 -0400 Subject: [PATCH 1103/2898] xen: don't open-code iov_iter_kvec() Signed-off-by: Al Viro --- drivers/xen/pvcalls-back.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c index b209cd44bb8d..ddc671170a5f 100644 --- a/drivers/xen/pvcalls-back.c +++ b/drivers/xen/pvcalls-back.c @@ -134,20 +134,16 @@ static void pvcalls_conn_back_read(void *opaque) masked_cons = pvcalls_mask(cons, array_size); memset(&msg, 0, sizeof(msg)); - msg.msg_iter.type = ITER_KVEC|WRITE; - msg.msg_iter.count = wanted; if (masked_prod < masked_cons) { vec[0].iov_base = data->in + masked_prod; vec[0].iov_len = wanted; - msg.msg_iter.kvec = vec; - msg.msg_iter.nr_segs = 1; + iov_iter_kvec(&msg.msg_iter, ITER_KVEC|WRITE, vec, 1, wanted); } else { vec[0].iov_base = data->in + masked_prod; vec[0].iov_len = array_size - masked_prod; vec[1].iov_base = data->in; vec[1].iov_len = wanted - vec[0].iov_len; - msg.msg_iter.kvec = vec; - msg.msg_iter.nr_segs = 2; + iov_iter_kvec(&msg.msg_iter, ITER_KVEC|WRITE, vec, 2, wanted); } atomic_set(&map->read, 0); @@ -196,20 +192,16 @@ static void pvcalls_conn_back_write(struct sock_mapping *map) memset(&msg, 0, sizeof(msg)); msg.msg_flags |= MSG_DONTWAIT; - msg.msg_iter.type = ITER_KVEC|READ; - msg.msg_iter.count = size; if (pvcalls_mask(prod, array_size) > pvcalls_mask(cons, array_size)) { vec[0].iov_base = data->out + pvcalls_mask(cons, array_size); vec[0].iov_len = size; - msg.msg_iter.kvec = vec; - msg.msg_iter.nr_segs = 1; + iov_iter_kvec(&msg.msg_iter, ITER_KVEC|READ, vec, 1, size); } else { vec[0].iov_base = data->out + pvcalls_mask(cons, array_size); vec[0].iov_len = array_size - pvcalls_mask(cons, array_size); vec[1].iov_base = data->out; vec[1].iov_len = size - vec[0].iov_len; - msg.msg_iter.kvec = vec; - msg.msg_iter.nr_segs = 2; + iov_iter_kvec(&msg.msg_iter, ITER_KVEC|READ, vec, 2, size); } atomic_set(&map->write, 0); -- GitLab From 6d1ff4d6f37dc3c14d9fc08dbbbb920a12c21f84 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Feb 2017 00:37:49 -0500 Subject: [PATCH 1104/2898] lnet_return_rx_credits_locked: don't abuse list_entry Signed-off-by: Al Viro --- drivers/staging/lustre/lnet/lnet/lib-move.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index bc0779c02d97..2b96c02bed50 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -889,7 +889,7 @@ lnet_return_rx_credits_locked(struct lnet_msg *msg) */ LASSERT(msg->msg_kiov); - rb = list_entry(msg->msg_kiov, struct lnet_rtrbuf, rb_kiov[0]); + rb = container_of(msg->msg_kiov, struct lnet_rtrbuf, rb_kiov[0]); rbp = rb->rb_pool; msg->msg_kiov = NULL; -- GitLab From 09cf698a594276139b7dfafb232af3fe4fbc4438 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Feb 2017 01:44:03 -0500 Subject: [PATCH 1105/2898] new primitive: iov_iter_for_each_range() For kvec and bvec: feeds segments to given callback as long as it returns 0. For iovec and pipe: fails. Signed-off-by: Al Viro --- include/linux/uio.h | 4 ++++ lib/iov_iter.c | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/linux/uio.h b/include/linux/uio.h index 5885daeae721..e67e12adb136 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -244,4 +244,8 @@ int compat_import_iovec(int type, const struct compat_iovec __user * uvector, int import_single_range(int type, void __user *buf, size_t len, struct iovec *iov, struct iov_iter *i); +int iov_iter_for_each_range(struct iov_iter *i, size_t bytes, + int (*f)(struct kvec *vec, void *context), + void *context); + #endif diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 1c1c06ddc20a..970212670b6a 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1446,3 +1446,25 @@ int import_single_range(int rw, void __user *buf, size_t len, return 0; } EXPORT_SYMBOL(import_single_range); + +int iov_iter_for_each_range(struct iov_iter *i, size_t bytes, + int (*f)(struct kvec *vec, void *context), + void *context) +{ + struct kvec w; + int err = -EINVAL; + if (!bytes) + return 0; + + iterate_all_kinds(i, bytes, v, -EINVAL, ({ + w.iov_base = kmap(v.bv_page) + v.bv_offset; + w.iov_len = v.bv_len; + err = f(&w, context); + kunmap(v.bv_page); + err;}), ({ + w = v; + err = f(&w, context);}) + ) + return err; +} +EXPORT_SYMBOL(iov_iter_for_each_range); -- GitLab From 11d49e9d089ccec81be87c2386dfdd010d7f7f6e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 18:36:44 -0400 Subject: [PATCH 1106/2898] fix a page leak in vhost_scsi_iov_to_sgl() error recovery we are advancing sg as we go, so the pages we need to drop in case of error are *before* the current sg. Cc: stable@vger.kernel.org Signed-off-by: Al Viro --- drivers/vhost/scsi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 046f6d280af5..e47c5bc3ddca 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -688,6 +688,7 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write, struct scatterlist *sg, int sg_count) { size_t off = iter->iov_offset; + struct scatterlist *p = sg; int i, ret; for (i = 0; i < iter->nr_segs; i++) { @@ -696,8 +697,8 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write, ret = vhost_scsi_map_to_sgl(cmd, base, len, sg, write); if (ret < 0) { - for (i = 0; i < sg_count; i++) { - struct page *page = sg_page(&sg[i]); + while (p < sg) { + struct page *page = sg_page(p++); if (page) put_page(page); } -- GitLab From 2f240c4ae8869907d4c8161ee015bedb366512e2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 22:07:59 -0400 Subject: [PATCH 1107/2898] vhost/scsi: switch to iov_iter_get_pages() Signed-off-by: Al Viro --- drivers/vhost/scsi.c | 68 +++++++++++++------------------------------- 1 file changed, 20 insertions(+), 48 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index e47c5bc3ddca..e5b18320f1a3 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -210,12 +210,6 @@ static struct workqueue_struct *vhost_scsi_workqueue; static DEFINE_MUTEX(vhost_scsi_mutex); static LIST_HEAD(vhost_scsi_list); -static int iov_num_pages(void __user *iov_base, size_t iov_len) -{ - return (PAGE_ALIGN((unsigned long)iov_base + iov_len) - - ((unsigned long)iov_base & PAGE_MASK)) >> PAGE_SHIFT; -} - static void vhost_scsi_done_inflight(struct kref *kref) { struct vhost_scsi_inflight *inflight; @@ -618,48 +612,31 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, */ static int vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd, - void __user *ptr, - size_t len, + struct iov_iter *iter, struct scatterlist *sgl, bool write) { - unsigned int npages = 0, offset, nbytes; - unsigned int pages_nr = iov_num_pages(ptr, len); - struct scatterlist *sg = sgl; struct page **pages = cmd->tvc_upages; - int ret, i; - - if (pages_nr > VHOST_SCSI_PREALLOC_UPAGES) { - pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than" - " preallocated VHOST_SCSI_PREALLOC_UPAGES: %u\n", - pages_nr, VHOST_SCSI_PREALLOC_UPAGES); - return -ENOBUFS; - } + struct scatterlist *sg = sgl; + ssize_t bytes; + size_t offset; + unsigned int npages = 0; - ret = get_user_pages_fast((unsigned long)ptr, pages_nr, write, pages); + bytes = iov_iter_get_pages(iter, pages, LONG_MAX, + VHOST_SCSI_PREALLOC_UPAGES, &offset); /* No pages were pinned */ - if (ret < 0) - goto out; - /* Less pages pinned than wanted */ - if (ret != pages_nr) { - for (i = 0; i < ret; i++) - put_page(pages[i]); - ret = -EFAULT; - goto out; - } + if (bytes <= 0) + return bytes < 0 ? bytes : -EFAULT; - while (len > 0) { - offset = (uintptr_t)ptr & ~PAGE_MASK; - nbytes = min_t(unsigned int, PAGE_SIZE - offset, len); - sg_set_page(sg, pages[npages], nbytes, offset); - ptr += nbytes; - len -= nbytes; - sg++; - npages++; - } + iov_iter_advance(iter, bytes); -out: - return ret; + while (bytes) { + unsigned n = min_t(unsigned, PAGE_SIZE - offset, bytes); + sg_set_page(sg++, pages[npages++], n, offset); + bytes -= n; + offset = 0; + } + return npages; } static int @@ -687,15 +664,11 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write, struct iov_iter *iter, struct scatterlist *sg, int sg_count) { - size_t off = iter->iov_offset; struct scatterlist *p = sg; - int i, ret; - - for (i = 0; i < iter->nr_segs; i++) { - void __user *base = iter->iov[i].iov_base + off; - size_t len = iter->iov[i].iov_len - off; + int ret; - ret = vhost_scsi_map_to_sgl(cmd, base, len, sg, write); + while (iov_iter_count(iter)) { + ret = vhost_scsi_map_to_sgl(cmd, iter, sg, write); if (ret < 0) { while (p < sg) { struct page *page = sg_page(p++); @@ -705,7 +678,6 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write, return ret; } sg += ret; - off = 0; } return 0; } -- GitLab From 33ec9c5cae2526ee2ef4f8224ddd2d7779b64e89 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 24 Sep 2017 22:54:53 -0400 Subject: [PATCH 1108/2898] lustre: switch struct ksock_conn to iov_iter Merge ksnc_rx_{no_wanted,iov,kiov,niov,nkiov} into a single iov_iter (ksnc_rx_to). Signed-off-by: Al Viro --- .../lustre/lnet/klnds/socklnd/socklnd.c | 4 +- .../lustre/lnet/klnds/socklnd/socklnd.h | 6 +- .../lustre/lnet/klnds/socklnd/socklnd_cb.c | 123 +++++------------- .../lustre/lnet/klnds/socklnd/socklnd_lib.c | 40 +++--- 4 files changed, 52 insertions(+), 121 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index fbbd8a5489e9..b390813d74be 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -1688,10 +1688,10 @@ ksocknal_destroy_conn(struct ksock_conn *conn) case SOCKNAL_RX_LNET_PAYLOAD: last_rcv = conn->ksnc_rx_deadline - cfs_time_seconds(*ksocknal_tunables.ksnd_timeout); - CERROR("Completing partial receive from %s[%d], ip %pI4h:%d, with error, wanted: %d, left: %d, last alive is %ld secs ago\n", + CERROR("Completing partial receive from %s[%d], ip %pI4h:%d, with error, wanted: %zd, left: %d, last alive is %ld secs ago\n", libcfs_id2str(conn->ksnc_peer->ksnp_id), conn->ksnc_type, &conn->ksnc_ipaddr, conn->ksnc_port, - conn->ksnc_rx_nob_wanted, conn->ksnc_rx_nob_left, + iov_iter_count(&conn->ksnc_rx_to), conn->ksnc_rx_nob_left, cfs_duration_sec(cfs_time_sub(cfs_time_current(), last_rcv))); lnet_finalize(conn->ksnc_peer->ksnp_ni, diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index e6428c4b7aec..694d45b45976 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -357,11 +357,7 @@ struct ksock_conn { __u8 ksnc_rx_scheduled; /* being progressed */ __u8 ksnc_rx_state; /* what is being read */ int ksnc_rx_nob_left; /* # bytes to next hdr/body */ - int ksnc_rx_nob_wanted;/* bytes actually wanted */ - int ksnc_rx_niov; /* # iovec frags */ - struct kvec *ksnc_rx_iov; /* the iovec frags */ - int ksnc_rx_nkiov; /* # page frags */ - struct bio_vec *ksnc_rx_kiov; /* the page frags */ + struct iov_iter ksnc_rx_to; /* copy destination */ union ksock_rxiovspace ksnc_rx_iov_space; /* space for frag descriptors */ __u32 ksnc_rx_csum; /* partial checksum for incoming * data diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 6b38d5a8fe92..c79aeb463a5c 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -251,14 +251,11 @@ ksocknal_transmit(struct ksock_conn *conn, struct ksock_tx *tx) static int ksocknal_recv_iov(struct ksock_conn *conn) { - struct kvec *iov = conn->ksnc_rx_iov; int nob; int rc; - LASSERT(conn->ksnc_rx_niov > 0); - /* - * Never touch conn->ksnc_rx_iov or change connection + * Never touch conn->ksnc_rx_to or change connection * status inside ksocknal_lib_recv_iov */ rc = ksocknal_lib_recv_iov(conn); @@ -275,22 +272,11 @@ ksocknal_recv_iov(struct ksock_conn *conn) mb(); /* order with setting rx_started */ conn->ksnc_rx_started = 1; - conn->ksnc_rx_nob_wanted -= nob; conn->ksnc_rx_nob_left -= nob; - do { - LASSERT(conn->ksnc_rx_niov > 0); - - if (nob < (int)iov->iov_len) { - iov->iov_len -= nob; - iov->iov_base += nob; - return -EAGAIN; - } - - nob -= iov->iov_len; - conn->ksnc_rx_iov = ++iov; - conn->ksnc_rx_niov--; - } while (nob); + iov_iter_advance(&conn->ksnc_rx_to, nob); + if (iov_iter_count(&conn->ksnc_rx_to)) + return -EAGAIN; return rc; } @@ -298,14 +284,11 @@ ksocknal_recv_iov(struct ksock_conn *conn) static int ksocknal_recv_kiov(struct ksock_conn *conn) { - struct bio_vec *kiov = conn->ksnc_rx_kiov; int nob; int rc; - LASSERT(conn->ksnc_rx_nkiov > 0); - /* - * Never touch conn->ksnc_rx_kiov or change connection + * Never touch conn->ksnc_rx_to or change connection * status inside ksocknal_lib_recv_iov */ rc = ksocknal_lib_recv_kiov(conn); @@ -322,22 +305,10 @@ ksocknal_recv_kiov(struct ksock_conn *conn) mb(); /* order with setting rx_started */ conn->ksnc_rx_started = 1; - conn->ksnc_rx_nob_wanted -= nob; conn->ksnc_rx_nob_left -= nob; - - do { - LASSERT(conn->ksnc_rx_nkiov > 0); - - if (nob < (int)kiov->bv_len) { - kiov->bv_offset += nob; - kiov->bv_len -= nob; - return -EAGAIN; - } - - nob -= kiov->bv_len; - conn->ksnc_rx_kiov = ++kiov; - conn->ksnc_rx_nkiov--; - } while (nob); + iov_iter_advance(&conn->ksnc_rx_to, nob); + if (iov_iter_count(&conn->ksnc_rx_to)) + return -EAGAIN; return 1; } @@ -347,7 +318,7 @@ ksocknal_receive(struct ksock_conn *conn) { /* * Return 1 on success, 0 on EOF, < 0 on error. - * Caller checks ksnc_rx_nob_wanted to determine + * Caller checks ksnc_rx_to to determine * progress/completion. */ int rc; @@ -364,7 +335,7 @@ ksocknal_receive(struct ksock_conn *conn) } for (;;) { - if (conn->ksnc_rx_niov) + if (conn->ksnc_rx_to.type & ITER_KVEC) rc = ksocknal_recv_iov(conn); else rc = ksocknal_recv_kiov(conn); @@ -382,7 +353,7 @@ ksocknal_receive(struct ksock_conn *conn) /* Completed a fragment */ - if (!conn->ksnc_rx_nob_wanted) { + if (!iov_iter_count(&conn->ksnc_rx_to)) { rc = 1; break; } @@ -1050,6 +1021,7 @@ int ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip) { static char ksocknal_slop_buffer[4096]; + struct kvec *kvec = (struct kvec *)&conn->ksnc_rx_iov_space; int nob; unsigned int niov; @@ -1070,32 +1042,26 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip) case KSOCK_PROTO_V2: case KSOCK_PROTO_V3: conn->ksnc_rx_state = SOCKNAL_RX_KSM_HEADER; - conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg; - - conn->ksnc_rx_nob_wanted = offsetof(struct ksock_msg, ksm_u); + kvec->iov_base = &conn->ksnc_msg; + kvec->iov_len = offsetof(struct ksock_msg, ksm_u); conn->ksnc_rx_nob_left = offsetof(struct ksock_msg, ksm_u); - conn->ksnc_rx_iov[0].iov_len = offsetof(struct ksock_msg, ksm_u); + iov_iter_kvec(&conn->ksnc_rx_to, READ|ITER_KVEC, kvec, + 1, offsetof(struct ksock_msg, ksm_u)); break; case KSOCK_PROTO_V1: /* Receiving bare struct lnet_hdr */ conn->ksnc_rx_state = SOCKNAL_RX_LNET_HEADER; - conn->ksnc_rx_nob_wanted = sizeof(struct lnet_hdr); + kvec->iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; + kvec->iov_len = sizeof(struct lnet_hdr); conn->ksnc_rx_nob_left = sizeof(struct lnet_hdr); - - conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; - conn->ksnc_rx_iov[0].iov_len = sizeof(struct lnet_hdr); + iov_iter_kvec(&conn->ksnc_rx_to, READ|ITER_KVEC, kvec, + 1, sizeof(struct lnet_hdr)); break; default: LBUG(); } - conn->ksnc_rx_niov = 1; - - conn->ksnc_rx_kiov = NULL; - conn->ksnc_rx_nkiov = 0; conn->ksnc_rx_csum = ~0; return 1; } @@ -1106,15 +1072,14 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip) */ conn->ksnc_rx_state = SOCKNAL_RX_SLOP; conn->ksnc_rx_nob_left = nob_to_skip; - conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; skipped = 0; niov = 0; do { nob = min_t(int, nob_to_skip, sizeof(ksocknal_slop_buffer)); - conn->ksnc_rx_iov[niov].iov_base = ksocknal_slop_buffer; - conn->ksnc_rx_iov[niov].iov_len = nob; + kvec[niov].iov_base = ksocknal_slop_buffer; + kvec[niov].iov_len = nob; niov++; skipped += nob; nob_to_skip -= nob; @@ -1122,16 +1087,14 @@ ksocknal_new_packet(struct ksock_conn *conn, int nob_to_skip) } while (nob_to_skip && /* mustn't overflow conn's rx iov */ niov < sizeof(conn->ksnc_rx_iov_space) / sizeof(struct iovec)); - conn->ksnc_rx_niov = niov; - conn->ksnc_rx_kiov = NULL; - conn->ksnc_rx_nkiov = 0; - conn->ksnc_rx_nob_wanted = skipped; + iov_iter_kvec(&conn->ksnc_rx_to, READ|ITER_KVEC, kvec, niov, skipped); return 0; } static int ksocknal_process_receive(struct ksock_conn *conn) { + struct kvec *kvec = (struct kvec *)&conn->ksnc_rx_iov_space; struct lnet_hdr *lhdr; struct lnet_process_id *id; int rc; @@ -1145,7 +1108,7 @@ ksocknal_process_receive(struct ksock_conn *conn) conn->ksnc_rx_state == SOCKNAL_RX_LNET_HEADER || conn->ksnc_rx_state == SOCKNAL_RX_SLOP); again: - if (conn->ksnc_rx_nob_wanted) { + if (iov_iter_count(&conn->ksnc_rx_to)) { rc = ksocknal_receive(conn); if (rc <= 0) { @@ -1170,7 +1133,7 @@ ksocknal_process_receive(struct ksock_conn *conn) return (!rc ? -ESHUTDOWN : rc); } - if (conn->ksnc_rx_nob_wanted) { + if (iov_iter_count(&conn->ksnc_rx_to)) { /* short read */ return -EAGAIN; } @@ -1233,16 +1196,13 @@ ksocknal_process_receive(struct ksock_conn *conn) } conn->ksnc_rx_state = SOCKNAL_RX_LNET_HEADER; - conn->ksnc_rx_nob_wanted = sizeof(struct ksock_lnet_msg); conn->ksnc_rx_nob_left = sizeof(struct ksock_lnet_msg); - conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; - conn->ksnc_rx_iov[0].iov_len = sizeof(struct ksock_lnet_msg); + kvec->iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; + kvec->iov_len = sizeof(struct ksock_lnet_msg); - conn->ksnc_rx_niov = 1; - conn->ksnc_rx_kiov = NULL; - conn->ksnc_rx_nkiov = 0; + iov_iter_kvec(&conn->ksnc_rx_to, READ|ITER_KVEC, kvec, + 1, sizeof(struct ksock_lnet_msg)); goto again; /* read lnet header now */ @@ -1344,26 +1304,9 @@ ksocknal_recv(struct lnet_ni *ni, void *private, struct lnet_msg *msg, LASSERT(to->nr_segs <= LNET_MAX_IOV); conn->ksnc_cookie = msg; - conn->ksnc_rx_nob_wanted = iov_iter_count(to); conn->ksnc_rx_nob_left = rlen; - if (to->type & ITER_KVEC) { - conn->ksnc_rx_nkiov = 0; - conn->ksnc_rx_kiov = NULL; - conn->ksnc_rx_iov = conn->ksnc_rx_iov_space.iov; - conn->ksnc_rx_niov = - lnet_extract_iov(LNET_MAX_IOV, conn->ksnc_rx_iov, - to->nr_segs, to->kvec, - to->iov_offset, iov_iter_count(to)); - } else { - conn->ksnc_rx_niov = 0; - conn->ksnc_rx_iov = NULL; - conn->ksnc_rx_kiov = conn->ksnc_rx_iov_space.kiov; - conn->ksnc_rx_nkiov = - lnet_extract_kiov(LNET_MAX_IOV, conn->ksnc_rx_kiov, - to->nr_segs, to->bvec, - to->iov_offset, iov_iter_count(to)); - } + conn->ksnc_rx_to = *to; LASSERT(conn->ksnc_rx_scheduled); @@ -2328,12 +2271,12 @@ ksocknal_find_timed_out_conn(struct ksock_peer *peer) conn->ksnc_rx_deadline)) { /* Timed out incomplete incoming message */ ksocknal_conn_addref(conn); - CNETERR("Timeout receiving from %s (%pI4h:%d), state %d wanted %d left %d\n", + CNETERR("Timeout receiving from %s (%pI4h:%d), state %d wanted %zd left %d\n", libcfs_id2str(peer->ksnp_id), &conn->ksnc_ipaddr, conn->ksnc_port, conn->ksnc_rx_state, - conn->ksnc_rx_nob_wanted, + iov_iter_count(&conn->ksnc_rx_to), conn->ksnc_rx_nob_left); return conn; } diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 9c328dc6537b..0ec032373497 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -164,26 +164,19 @@ ksocknal_lib_eager_ack(struct ksock_conn *conn) int ksocknal_lib_recv_iov(struct ksock_conn *conn) { - unsigned int niov = conn->ksnc_rx_niov; - struct kvec *iov = conn->ksnc_rx_iov; + unsigned int niov = conn->ksnc_rx_to.nr_segs; + const struct iovec *iov = conn->ksnc_rx_to.iov; struct msghdr msg = { .msg_flags = 0 }; - int nob; int i; int rc; int fragnob; int sum; __u32 saved_csum; + int off = conn->ksnc_rx_to.iov_offset; - LASSERT(niov > 0); - - for (nob = i = 0; i < niov; i++) - nob += iov[i].iov_len; - - LASSERT(nob <= conn->ksnc_rx_nob_wanted); - - iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, iov, niov, nob); + msg.msg_iter = conn->ksnc_rx_to; rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); saved_csum = 0; @@ -197,13 +190,14 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { LASSERT(i < niov); - fragnob = iov[i].iov_len; + fragnob = iov[i].iov_len - off; if (fragnob > sum) fragnob = sum; conn->ksnc_rx_csum = crc32_le(conn->ksnc_rx_csum, - iov[i].iov_base, + iov[i].iov_base + off, fragnob); + off = 0; } conn->ksnc_msg.ksm_csum = saved_csum; } @@ -214,32 +208,29 @@ ksocknal_lib_recv_iov(struct ksock_conn *conn) int ksocknal_lib_recv_kiov(struct ksock_conn *conn) { - unsigned int niov = conn->ksnc_rx_nkiov; - struct bio_vec *kiov = conn->ksnc_rx_kiov; + unsigned int niov = conn->ksnc_rx_to.nr_segs; + const struct bio_vec *kiov = conn->ksnc_rx_to.bvec; + int off = conn->ksnc_rx_to.iov_offset; struct msghdr msg = { .msg_flags = 0 }; - int nob; int i; int rc; void *base; int sum; int fragnob; - for (nob = i = 0; i < niov; i++) - nob += kiov[i].bv_len; - - LASSERT(nob <= conn->ksnc_rx_nob_wanted); - - iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, kiov, niov, nob); + msg.msg_iter = conn->ksnc_rx_to; rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); + if (rc <= 0) + return rc; if (conn->ksnc_msg.ksm_csum) { for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { LASSERT(i < niov); - base = kmap(kiov[i].bv_page) + kiov[i].bv_offset; - fragnob = kiov[i].bv_len; + base = kmap(kiov[i].bv_page) + kiov[i].bv_offset + off; + fragnob = kiov[i].bv_len - off; if (fragnob > sum) fragnob = sum; @@ -247,6 +238,7 @@ ksocknal_lib_recv_kiov(struct ksock_conn *conn) base, fragnob); kunmap(kiov[i].bv_page); + off = 0; } } return rc; -- GitLab From 8ececffa12f5555171075ce52e1226f570836b26 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Sep 2017 13:58:39 -0400 Subject: [PATCH 1109/2898] switch ksocknal_lib_recv_...() to use of iov_iter_for_each_range() ... and fold kvec and bio_vec variants in one Signed-off-by: Al Viro --- .../lustre/lnet/klnds/socklnd/socklnd.h | 3 +- .../lustre/lnet/klnds/socklnd/socklnd_cb.c | 44 +--------- .../lustre/lnet/klnds/socklnd/socklnd_lib.c | 87 +++++-------------- 3 files changed, 25 insertions(+), 109 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index 694d45b45976..a18a57c4de81 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -696,8 +696,7 @@ int ksocknal_lib_setup_sock(struct socket *so); int ksocknal_lib_send_iov(struct ksock_conn *conn, struct ksock_tx *tx); int ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx); void ksocknal_lib_eager_ack(struct ksock_conn *conn); -int ksocknal_lib_recv_iov(struct ksock_conn *conn); -int ksocknal_lib_recv_kiov(struct ksock_conn *conn); +int ksocknal_lib_recv(struct ksock_conn *conn); int ksocknal_lib_get_conn_tunables(struct ksock_conn *conn, int *txmem, int *rxmem, int *nagle); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index c79aeb463a5c..b12c3b0f39e1 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -249,16 +249,16 @@ ksocknal_transmit(struct ksock_conn *conn, struct ksock_tx *tx) } static int -ksocknal_recv_iov(struct ksock_conn *conn) +ksocknal_recv_iter(struct ksock_conn *conn) { int nob; int rc; /* * Never touch conn->ksnc_rx_to or change connection - * status inside ksocknal_lib_recv_iov + * status inside ksocknal_lib_recv */ - rc = ksocknal_lib_recv_iov(conn); + rc = ksocknal_lib_recv(conn); if (rc <= 0) return rc; @@ -274,38 +274,6 @@ ksocknal_recv_iov(struct ksock_conn *conn) conn->ksnc_rx_nob_left -= nob; - iov_iter_advance(&conn->ksnc_rx_to, nob); - if (iov_iter_count(&conn->ksnc_rx_to)) - return -EAGAIN; - - return rc; -} - -static int -ksocknal_recv_kiov(struct ksock_conn *conn) -{ - int nob; - int rc; - - /* - * Never touch conn->ksnc_rx_to or change connection - * status inside ksocknal_lib_recv_iov - */ - rc = ksocknal_lib_recv_kiov(conn); - - if (rc <= 0) - return rc; - - /* received something... */ - nob = rc; - - conn->ksnc_peer->ksnp_last_alive = cfs_time_current(); - conn->ksnc_rx_deadline = - cfs_time_shift(*ksocknal_tunables.ksnd_timeout); - mb(); /* order with setting rx_started */ - conn->ksnc_rx_started = 1; - - conn->ksnc_rx_nob_left -= nob; iov_iter_advance(&conn->ksnc_rx_to, nob); if (iov_iter_count(&conn->ksnc_rx_to)) return -EAGAIN; @@ -335,11 +303,7 @@ ksocknal_receive(struct ksock_conn *conn) } for (;;) { - if (conn->ksnc_rx_to.type & ITER_KVEC) - rc = ksocknal_recv_iov(conn); - else - rc = ksocknal_recv_kiov(conn); - + rc = ksocknal_recv_iter(conn); if (rc <= 0) { /* error/EOF or partial receive */ if (rc == -EAGAIN) { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 0ec032373497..2e3e2dd70baa 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -161,86 +161,39 @@ ksocknal_lib_eager_ack(struct ksock_conn *conn) sizeof(opt)); } -int -ksocknal_lib_recv_iov(struct ksock_conn *conn) +static int lustre_csum(struct kvec *v, void *context) { - unsigned int niov = conn->ksnc_rx_to.nr_segs; - const struct iovec *iov = conn->ksnc_rx_to.iov; - struct msghdr msg = { - .msg_flags = 0 - }; - int i; - int rc; - int fragnob; - int sum; - __u32 saved_csum; - int off = conn->ksnc_rx_to.iov_offset; - - msg.msg_iter = conn->ksnc_rx_to; - rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); - - saved_csum = 0; - if (conn->ksnc_proto == &ksocknal_protocol_v2x) { - saved_csum = conn->ksnc_msg.ksm_csum; - conn->ksnc_msg.ksm_csum = 0; - } - - if (saved_csum) { - /* accumulate checksum */ - for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { - LASSERT(i < niov); - - fragnob = iov[i].iov_len - off; - if (fragnob > sum) - fragnob = sum; - - conn->ksnc_rx_csum = crc32_le(conn->ksnc_rx_csum, - iov[i].iov_base + off, - fragnob); - off = 0; - } - conn->ksnc_msg.ksm_csum = saved_csum; - } - - return rc; + struct ksock_conn *conn = context; + conn->ksnc_rx_csum = crc32_le(conn->ksnc_rx_csum, + v->iov_base, v->iov_len); + return 0; } int -ksocknal_lib_recv_kiov(struct ksock_conn *conn) +ksocknal_lib_recv(struct ksock_conn *conn) { - unsigned int niov = conn->ksnc_rx_to.nr_segs; - const struct bio_vec *kiov = conn->ksnc_rx_to.bvec; - int off = conn->ksnc_rx_to.iov_offset; - struct msghdr msg = { - .msg_flags = 0 - }; - int i; + struct msghdr msg = { .msg_iter = conn->ksnc_rx_to }; + __u32 saved_csum; int rc; - void *base; - int sum; - int fragnob; - msg.msg_iter = conn->ksnc_rx_to; rc = sock_recvmsg(conn->ksnc_sock, &msg, MSG_DONTWAIT); if (rc <= 0) return rc; - if (conn->ksnc_msg.ksm_csum) { - for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { - LASSERT(i < niov); - - base = kmap(kiov[i].bv_page) + kiov[i].bv_offset + off; - fragnob = kiov[i].bv_len - off; - if (fragnob > sum) - fragnob = sum; + saved_csum = conn->ksnc_msg.ksm_csum; + if (!saved_csum) + return rc; - conn->ksnc_rx_csum = crc32_le(conn->ksnc_rx_csum, - base, fragnob); + /* header is included only in V2 - V3 checksums only the bulk data */ + if (!(conn->ksnc_rx_to.type & ITER_BVEC) && + conn->ksnc_proto != &ksocknal_protocol_v2x) + return rc; + + /* accumulate checksum */ + conn->ksnc_msg.ksm_csum = 0; + iov_iter_for_each_range(&conn->ksnc_rx_to, rc, lustre_csum, conn); + conn->ksnc_msg.ksm_csum = saved_csum; - kunmap(kiov[i].bv_page); - off = 0; - } - } return rc; } -- GitLab From cfe057f7db1ff026c8db75469a3f9ba9736e1975 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 11 Sep 2017 21:17:09 +0100 Subject: [PATCH 1110/2898] iomap_dio_actor(): fix iov_iter bugs 1) Ignoring return value from iov_iter_zero() is wrong for iovec-backed case as well as for pipes - it can fail. 2) Failure to fault destination pages in 25Mb into a 50Mb iovec should not act as if nothing in the area had been read, nevermind that the first 25Mb might have *already* been read by that point. Signed-off-by: Al Viro --- fs/iomap.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/fs/iomap.c b/fs/iomap.c index be61cf742b5e..9c41008833ac 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -848,6 +848,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, struct bio *bio; bool need_zeroout = false; int nr_pages, ret; + size_t copied = 0; if ((pos | length | align) & ((1 << blkbits) - 1)) return -EINVAL; @@ -859,7 +860,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, /*FALLTHRU*/ case IOMAP_UNWRITTEN: if (!(dio->flags & IOMAP_DIO_WRITE)) { - iov_iter_zero(length, dio->submit.iter); + length = iov_iter_zero(length, dio->submit.iter); dio->size += length; return length; } @@ -896,8 +897,11 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, } do { - if (dio->error) + size_t n; + if (dio->error) { + iov_iter_revert(dio->submit.iter, copied); return 0; + } bio = bio_alloc(GFP_KERNEL, nr_pages); bio_set_dev(bio, iomap->bdev); @@ -910,20 +914,24 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, ret = bio_iov_iter_get_pages(bio, &iter); if (unlikely(ret)) { bio_put(bio); - return ret; + return copied ? copied : ret; } + n = bio->bi_iter.bi_size; if (dio->flags & IOMAP_DIO_WRITE) { bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_SYNC | REQ_IDLE); - task_io_account_write(bio->bi_iter.bi_size); + task_io_account_write(n); } else { bio_set_op_attrs(bio, REQ_OP_READ, 0); if (dio->flags & IOMAP_DIO_DIRTY) bio_set_pages_dirty(bio); } - dio->size += bio->bi_iter.bi_size; - pos += bio->bi_iter.bi_size; + iov_iter_advance(dio->submit.iter, n); + + dio->size += n; + pos += n; + copied += n; nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES); @@ -939,9 +947,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, if (pad) iomap_dio_zero(dio, iomap, pos, fs_block_size - pad); } - - iov_iter_advance(dio->submit.iter, length); - return length; + return copied; } ssize_t -- GitLab From 584ce30c72954e5ec67aaf317d7cbffe6c2c97fa Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 29 Aug 2017 21:52:56 +0200 Subject: [PATCH 1111/2898] rtc: ds1307: improve weekday handling The current code for checking and fixing the weekday in ds1307_probe faces some issues: - This check is applied to all chips even if its applicable (AFAIK) to mcp794xx only - The check uses MCP794XX constants for registers and bits even though it's executed also on other chips (ok, this could be fixed easily) - It relies on tm_wday being properly populated when core calls set_time and set_alarm. This is not guaranteed at all. First two issue we could solve by moving the check to the mcp794xx-specific initialization (where also VBATEN flag is set). The proposed alternative is in the set_alarm path for mcp794xx only and calculates the alarm weekday based on the current weekday in the RTC timekeeping regs and the difference between alarm date and current date. So we are fine with any weekday even if it doesn't match the date. Still there are cases where this could fail, e.g.: - rtc date/time + weekday have power-on-reset default values - alarm is set to actual date/time + x - set_time is called (may change diff between rtc weekday and actual weekday) But similar issues we have with the current code too: - rtc date/time + weekday have power-on-reset default values - alarm is set to rtc date/time + x - set_time is called before the alarm triggers Using random rtc date/time with relative alarms simply can interfere with set_time. I'm not totally convinced of either option yet. Signed-off-by: Heiner Kallweit Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index e7d9215c9201..1cca20fdd025 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -787,8 +787,6 @@ static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) * Alarm support for mcp794xx devices. */ -#define MCP794XX_REG_WEEKDAY 0x3 -#define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7 #define MCP794XX_REG_CONTROL 0x07 # define MCP794XX_BIT_ALM0_EN 0x10 # define MCP794XX_BIT_ALM1_EN 0x20 @@ -877,15 +875,38 @@ static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t) return 0; } +/* + * We may have a random RTC weekday, therefore calculate alarm weekday based + * on current weekday we read from the RTC timekeeping regs + */ +static int mcp794xx_alm_weekday(struct device *dev, struct rtc_time *tm_alarm) +{ + struct rtc_time tm_now; + int days_now, days_alarm, ret; + + ret = ds1307_get_time(dev, &tm_now); + if (ret) + return ret; + + days_now = div_s64(rtc_tm_to_time64(&tm_now), 24 * 60 * 60); + days_alarm = div_s64(rtc_tm_to_time64(tm_alarm), 24 * 60 * 60); + + return (tm_now.tm_wday + days_alarm - days_now) % 7 + 1; +} + static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) { struct ds1307 *ds1307 = dev_get_drvdata(dev); unsigned char regs[10]; - int ret; + int wday, ret; if (!test_bit(HAS_ALARM, &ds1307->flags)) return -EINVAL; + wday = mcp794xx_alm_weekday(dev, &t->time); + if (wday < 0) + return wday; + dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " "enabled=%d pending=%d\n", __func__, t->time.tm_sec, t->time.tm_min, t->time.tm_hour, @@ -902,7 +923,7 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) regs[3] = bin2bcd(t->time.tm_sec); regs[4] = bin2bcd(t->time.tm_min); regs[5] = bin2bcd(t->time.tm_hour); - regs[6] = bin2bcd(t->time.tm_wday + 1); + regs[6] = wday; regs[7] = bin2bcd(t->time.tm_mday); regs[8] = bin2bcd(t->time.tm_mon + 1); @@ -1354,14 +1375,12 @@ static int ds1307_probe(struct i2c_client *client, { struct ds1307 *ds1307; int err = -ENODEV; - int tmp, wday; + int tmp; const struct chip_desc *chip; bool want_irq; bool ds1307_can_wakeup_device = false; unsigned char regs[8]; struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); - struct rtc_time tm; - unsigned long timestamp; u8 trickle_charger_setup = 0; ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL); @@ -1641,25 +1660,6 @@ static int ds1307_probe(struct i2c_client *client, bin2bcd(tmp)); } - /* - * Some IPs have weekday reset value = 0x1 which might not correct - * hence compute the wday using the current date/month/year values - */ - ds1307_get_time(ds1307->dev, &tm); - wday = tm.tm_wday; - timestamp = rtc_tm_to_time64(&tm); - rtc_time64_to_tm(timestamp, &tm); - - /* - * Check if reset wday is different from the computed wday - * If different then set the wday which we computed using - * timestamp - */ - if (wday != tm.tm_wday) - regmap_update_bits(ds1307->regmap, MCP794XX_REG_WEEKDAY, - MCP794XX_REG_WEEKDAY_WDAY_MASK, - tm.tm_wday + 1); - if (want_irq || ds1307_can_wakeup_device) { device_set_wakeup_capable(ds1307->dev, true); set_bit(HAS_ALARM, &ds1307->flags); -- GitLab From 49de9828810cb4ccf85ac213d4fd15f1a30fb4f6 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Sun, 10 Sep 2017 21:39:57 +0200 Subject: [PATCH 1112/2898] rtc: jz4740: remove duplicate 'write' in message Trivial fix in error message with duplicate 'write' Signed-off-by: Mathieu Malaterre Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-jz4740.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index 64989afffa3d..c9536fb0ba4a 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -368,7 +368,7 @@ static int jz4740_rtc_probe(struct platform_device *pdev) ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); if (ret) { - dev_err(&pdev->dev, "Could not write write to RTC registers\n"); + dev_err(&pdev->dev, "Could not write to RTC registers\n"); return ret; } } -- GitLab From 695e38d8818dd858d7516c77bab96be266f56694 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Mon, 18 Sep 2017 21:10:13 +0200 Subject: [PATCH 1113/2898] rtc: jz4740: fix loading of rtc driver The current timeout for waiting for WRDY is not always sufficient. Always increase it to 10000 even on JZ4740. This is technically only required on JZ4780, where the current symptoms seen after a hard reboot are: jz4740-rtc 10003000.rtc: rtc core: registered 10003000.rtc as rtc0 jz4740-rtc 10003000.rtc: Could not write to RTC registers jz4740-rtc: probe of 10003000.rtc failed with error -5 Suggested-by: Alex Smith Cc: Zubair Lutfullah Kakakhel Signed-off-by: Mathieu Malaterre Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-jz4740.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index c9536fb0ba4a..ff65a7d2b9c9 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -82,7 +82,7 @@ static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) { uint32_t ctrl; - int timeout = 1000; + int timeout = 10000; do { ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); @@ -94,7 +94,7 @@ static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) static inline int jz4780_rtc_enable_write(struct jz4740_rtc *rtc) { uint32_t ctrl; - int ret, timeout = 1000; + int ret, timeout = 10000; ret = jz4740_rtc_wait_write_ready(rtc); if (ret != 0) -- GitLab From 97f5b0379c382d9c2b944baa02852338dee7d8aa Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 21 Sep 2017 00:45:30 +0300 Subject: [PATCH 1114/2898] rtc: rv3029: Clean up error handling in rv3029_eeprom_write() We don't need both "ret" and "err" when they do the same thing. All the functions called here return zero on success or negative error codes. It's more clear to return a literal zero at the end instead of "return ret;" Signed-off-by: Dan Carpenter Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv3029c2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index cfe3aece51d1..3d6174eb32f6 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -282,13 +282,13 @@ static int rv3029_eeprom_read(struct device *dev, u8 reg, static int rv3029_eeprom_write(struct device *dev, u8 reg, u8 const buf[], size_t len) { - int ret, err; + int ret; size_t i; u8 tmp; - err = rv3029_eeprom_enter(dev); - if (err < 0) - return err; + ret = rv3029_eeprom_enter(dev); + if (ret < 0) + return ret; for (i = 0; i < len; i++, reg++) { ret = rv3029_read_regs(dev, reg, &tmp, 1); @@ -304,11 +304,11 @@ static int rv3029_eeprom_write(struct device *dev, u8 reg, break; } - err = rv3029_eeprom_exit(dev); - if (err < 0) - return err; + ret = rv3029_eeprom_exit(dev); + if (ret < 0) + return ret; - return ret; + return 0; } static int rv3029_eeprom_update_bits(struct device *dev, -- GitLab From eb508b36d549d96a7ddcf1fe0656cdd86b038fe5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 29 Sep 2017 11:22:00 +0100 Subject: [PATCH 1115/2898] rtc: pl031: constify amba_ids The AMBA device IDs should be marked const. Make that so. Reviewed-by: Linus Walleij Signed-off-by: Russell King Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pl031.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index e1687e19c59f..0d87b90b1903 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -446,7 +446,7 @@ static struct pl031_vendor_data stv2_pl031 = { .irqflags = IRQF_SHARED | IRQF_COND_SUSPEND, }; -static struct amba_id pl031_ids[] = { +static const struct amba_id pl031_ids[] = { { .id = 0x00041031, .mask = 0x000fffff, -- GitLab From 273c868e85a56481ccb34822be2033dbe63248fb Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 29 Sep 2017 11:22:05 +0100 Subject: [PATCH 1116/2898] rtc: pl031: use devm_* for allocating memory and mapping resource Use the devm_* APIs for allocating memory and mapping the memory in the probe function to relieve the driver from having to deal with this in the cleanup paths. Signed-off-by: Russell King Reviewed-by: Linus Walleij Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pl031.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 0d87b90b1903..777da06d53ee 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -310,8 +310,6 @@ static int pl031_remove(struct amba_device *adev) device_init_wakeup(&adev->dev, false); free_irq(adev->irq[0], ldata); rtc_device_unregister(ldata->rtc); - iounmap(ldata->base); - kfree(ldata); amba_release_regions(adev); return 0; @@ -329,18 +327,19 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) if (ret) goto err_req; - ldata = kzalloc(sizeof(struct pl031_local), GFP_KERNEL); + ldata = devm_kzalloc(&adev->dev, sizeof(struct pl031_local), + GFP_KERNEL); if (!ldata) { ret = -ENOMEM; goto out; } ldata->vendor = vendor; - ldata->base = ioremap(adev->res.start, resource_size(&adev->res)); - + ldata->base = devm_ioremap(&adev->dev, adev->res.start, + resource_size(&adev->res)); if (!ldata->base) { ret = -ENOMEM; - goto out_no_remap; + goto out; } amba_set_drvdata(adev, ldata); @@ -378,7 +377,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) THIS_MODULE); if (IS_ERR(ldata->rtc)) { ret = PTR_ERR(ldata->rtc); - goto out_no_rtc; + goto out; } if (request_irq(adev->irq[0], pl031_interrupt, @@ -391,10 +390,6 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) out_no_irq: rtc_device_unregister(ldata->rtc); -out_no_rtc: - iounmap(ldata->base); -out_no_remap: - kfree(ldata); out: amba_release_regions(adev); err_req: -- GitLab From b86f581f8cdbec3655d400ad952c2203a74edde1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 29 Sep 2017 11:22:10 +0100 Subject: [PATCH 1117/2898] rtc: pl031: avoid exposing alarm if no interrupt If the RTC has no interrupt, there is little point in exposing the RTC alarm capabilities, as it can't be used as a wakeup source nor can it deliver an event to userspace. Signed-off-by: Russell King Reviewed-by: Linus Walleij Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pl031.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 777da06d53ee..64c77ec1b4ea 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -320,7 +320,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) int ret; struct pl031_local *ldata; struct pl031_vendor_data *vendor = id->data; - struct rtc_class_ops *ops = &vendor->ops; + struct rtc_class_ops *ops; unsigned long time, data; ret = amba_request_regions(adev, NULL); @@ -329,12 +329,14 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) ldata = devm_kzalloc(&adev->dev, sizeof(struct pl031_local), GFP_KERNEL); - if (!ldata) { + ops = devm_kmemdup(&adev->dev, &vendor->ops, sizeof(vendor->ops), + GFP_KERNEL); + if (!ldata || !ops) { ret = -ENOMEM; goto out; } - ldata->vendor = vendor; + ldata->vendor = vendor; ldata->base = devm_ioremap(&adev->dev, adev->res.start, resource_size(&adev->res)); if (!ldata->base) { @@ -372,6 +374,13 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) } } + if (!adev->irq[0]) { + /* When there's no interrupt, no point in exposing the alarm */ + ops->read_alarm = NULL; + ops->set_alarm = NULL; + ops->alarm_irq_enable = NULL; + } + device_init_wakeup(&adev->dev, true); ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, THIS_MODULE); -- GitLab From 5b64a2965dfdfca8039e93303c64e2b15c19ff0c Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 29 Sep 2017 11:22:15 +0100 Subject: [PATCH 1118/2898] rtc: pl031: make interrupt optional On some platforms, the interrupt for the PL031 is optional. Avoid trying to claim the interrupt if it's not specified. Reviewed-by: Linus Walleij Signed-off-by: Russell King Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pl031.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 64c77ec1b4ea..82eb7da2c478 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -308,7 +308,8 @@ static int pl031_remove(struct amba_device *adev) dev_pm_clear_wake_irq(&adev->dev); device_init_wakeup(&adev->dev, false); - free_irq(adev->irq[0], ldata); + if (adev->irq[0]) + free_irq(adev->irq[0], ldata); rtc_device_unregister(ldata->rtc); amba_release_regions(adev); @@ -389,12 +390,13 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) goto out; } - if (request_irq(adev->irq[0], pl031_interrupt, - vendor->irqflags, "rtc-pl031", ldata)) { - ret = -EIO; - goto out_no_irq; + if (adev->irq[0]) { + ret = request_irq(adev->irq[0], pl031_interrupt, + vendor->irqflags, "rtc-pl031", ldata); + if (ret) + goto out_no_irq; + dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); } - dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); return 0; out_no_irq: -- GitLab From 11e3e8d6d9274bf630859b4c47bc4e4d76f289db Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 12 Oct 2017 17:31:46 +0200 Subject: [PATCH 1119/2898] elf_fdpic: fix unused variable warning The elf_fdpic code shows a harmless warning when built with MMU disabled, I ran into this now that fdpic is available on ARM randconfig builds since commit 50b2b2e691cd ("ARM: add ELF_FDPIC support"). fs/binfmt_elf_fdpic.c: In function 'elf_fdpic_dump_segments': fs/binfmt_elf_fdpic.c:1501:17: error: unused variable 'addr' [-Werror=unused-variable] This adds another #ifdef around the variable declaration to shut up the warning. Fixes: e6c1baa9b562 ("convert the rest of binfmt_elf_fdpic to dump_emit()") Acked-by: Nicolas Pitre Signed-off-by: Arnd Bergmann Signed-off-by: Al Viro --- fs/binfmt_elf_fdpic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index e70c039ac190..c4565061da84 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1489,7 +1489,9 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm) struct vm_area_struct *vma; for (vma = current->mm->mmap; vma; vma = vma->vm_next) { +#ifdef CONFIG_MMU unsigned long addr; +#endif if (!maydump(vma, cprm->mm_flags)) continue; -- GitLab From 0619d9e8f101320ee0ee95e8071031c9217d50a3 Mon Sep 17 00:00:00 2001 From: Allen Pais Date: Thu, 12 Oct 2017 18:18:23 +0200 Subject: [PATCH 1120/2898] video: fbdev: matroxfb: return -ENOMEM on allocation failure Signed-off-by: Allen Pais Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/matrox/matroxfb_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c index b9b284d79631..838869c6490c 100644 --- a/drivers/video/fbdev/matrox/matroxfb_base.c +++ b/drivers/video/fbdev/matrox/matroxfb_base.c @@ -2056,7 +2056,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm minfo = kzalloc(sizeof(*minfo), GFP_KERNEL); if (!minfo) - return -1; + return -ENOMEM; minfo->pcidev = pdev; minfo->dead = 0; -- GitLab From 160d9a6b27b71499557d368fb514f8a9fcbde12e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 12 Oct 2017 18:18:23 +0200 Subject: [PATCH 1121/2898] video: fbdev: aty: make const arrays static, reduces object code size Don't populate the const arrays ragepro_tbl and ragexl_tbl on the stack, instead make them static. Makes the object code smaller by over 380 bytes: Before: text data bss dec hex filename 41089 10592 768 52449 cce1 atyfb_base.o After: text data bss dec hex filename 40544 10752 768 52064 cb60 atyfb_base.o (gcc version 7.2.0, x86_64) Signed-off-by: Colin Ian King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/aty/atyfb_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index 3ec72f19114b..a9a8272f7a6e 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -2272,10 +2272,10 @@ static void aty_bl_exit(struct backlight_device *bd) static void aty_calc_mem_refresh(struct atyfb_par *par, int xclk) { - const int ragepro_tbl[] = { + static const int ragepro_tbl[] = { 44, 50, 55, 66, 75, 80, 100 }; - const int ragexl_tbl[] = { + static const int ragexl_tbl[] = { 50, 66, 75, 83, 90, 95, 100, 105, 110, 115, 120, 125, 133, 143, 166 }; -- GitLab From b90b3eca16b7ba6f42df35c029b674f1a00b0c69 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 12 Oct 2017 18:18:23 +0200 Subject: [PATCH 1122/2898] video: fbdev: sis: make const array specialtv static, reduces object code size Don't populate the const array specialtv on the stack, instead make it static. Makes the object code smaller by over 1100 bytes: Before: text data bss dec hex filename 179899 7504 0 187403 2dc0b drivers/video/fbdev/sis/init301.o After: text data bss dec hex filename 178720 7568 0 186288 2d7b0 drivers/video/fbdev/sis/init301.o (gcc version 7.2.0, x86_64) Signed-off-by: Colin Ian King Cc: Thomas Winischhofer Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sis/init301.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/sis/init301.c b/drivers/video/fbdev/sis/init301.c index 1ec9c3e0e1d8..02ee752d5000 100644 --- a/drivers/video/fbdev/sis/init301.c +++ b/drivers/video/fbdev/sis/init301.c @@ -6486,7 +6486,7 @@ SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo) if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) { if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) { - const unsigned char specialtv[] = { + static const unsigned char specialtv[] = { 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53, 0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a, 0x58,0xe4,0x73,0xda,0x13 -- GitLab From 3961e9ac3a4546a1022988cc93aec0dc29b513de Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 12 Oct 2017 18:18:23 +0200 Subject: [PATCH 1123/2898] video: fbdev: dnfb: make fb_var_screeninfo static and const Make this structure static as it is not referenced in any other file. Make it const as it is used only during a copy operation. Signed-off-by: Bhumika Goyal Cc: Julia Lawall [b.zolnierkie: split from combined patch] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/dnfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/dnfb.c b/drivers/video/fbdev/dnfb.c index 7b1492d34e98..09415009d797 100644 --- a/drivers/video/fbdev/dnfb.c +++ b/drivers/video/fbdev/dnfb.c @@ -115,7 +115,7 @@ static struct fb_ops dn_fb_ops = { .fb_imageblit = cfb_imageblit, }; -struct fb_var_screeninfo dnfb_var = { +static const struct fb_var_screeninfo dnfb_var = { .xres = 1280, .yres = 1024, .xres_virtual = 2048, -- GitLab From 0c09dd051b0cb9cb949cf8582ff7c9b10bfdfb0f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 12 Oct 2017 18:28:26 +0200 Subject: [PATCH 1124/2898] video: fbdev: radeon: make const array post_divs static, reduces object code size Don't populate the read-only const array post_divs on the stack, instead make it static. Makes the object code smaller by 90 bytes: Before: text data bss dec hex filename 40231 8584 896 49711 c22f radeon_base.o After: text data bss dec hex filename 39914 8744 960 49618 c1d2 radeon_base.o (gcc version 7.2.0, x86_64) Signed-off-by: Colin Ian King Cc: Benjamin Herrenschmidt Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/aty/radeon_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index 1e2ec360f8c1..8ad1643e7d1c 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -1534,7 +1534,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs, unsigned long freq) { - const struct { + static const struct { int divider; int bitvalue; } *post_div, -- GitLab From 6a4e89161e4ae4aa57eb8d4a419e7fb2cc340a13 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:03:22 +0200 Subject: [PATCH 1125/2898] rtc: ds1305: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1305.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 72b22935eb62..c3232c818e65 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -708,10 +708,15 @@ static int ds1305_probe(struct spi_device *spi) dev_dbg(&spi->dev, "AM/PM\n"); /* register RTC ... from here on, ds1305->ctrl needs locking */ - ds1305->rtc = devm_rtc_device_register(&spi->dev, "ds1305", - &ds1305_ops, THIS_MODULE); + ds1305->rtc = devm_rtc_allocate_device(&spi->dev); if (IS_ERR(ds1305->rtc)) { - status = PTR_ERR(ds1305->rtc); + return PTR_ERR(ds1305->rtc); + } + + ds1305->rtc->ops = &ds1305_ops; + + status = rtc_register_device(ds1305->rtc); + if (status) { dev_dbg(&spi->dev, "register rtc --> %d\n", status); return status; } -- GitLab From 41e607f21b16ce648d629daa0349bfe4bf4cadaa Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:03:23 +0200 Subject: [PATCH 1126/2898] rtc: ds1305: use generic nvmem Instead of adding a binary sysfs attribute from the driver (which suffers from a race condition as the attribute appears after the device), use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1305.c | 59 ++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index c3232c818e65..d8df2e9e14ad 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -514,56 +514,43 @@ static void msg_init(struct spi_message *m, struct spi_transfer *x, spi_message_add_tail(x, m); } -static ssize_t -ds1305_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int ds1305_nvram_read(void *priv, unsigned int off, void *buf, + size_t count) { - struct spi_device *spi; + struct ds1305 *ds1305 = priv; + struct spi_device *spi = ds1305->spi; u8 addr; struct spi_message m; struct spi_transfer x[2]; - int status; - - spi = to_spi_device(kobj_to_dev(kobj)); addr = DS1305_NVRAM + off; msg_init(&m, x, &addr, count, NULL, buf); - status = spi_sync(spi, &m); - if (status < 0) - dev_err(&spi->dev, "nvram %s error %d\n", "read", status); - return (status < 0) ? status : count; + return spi_sync(spi, &m); } -static ssize_t -ds1305_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int ds1305_nvram_write(void *priv, unsigned int off, void *buf, + size_t count) { - struct spi_device *spi; + struct ds1305 *ds1305 = priv; + struct spi_device *spi = ds1305->spi; u8 addr; struct spi_message m; struct spi_transfer x[2]; - int status; - - spi = to_spi_device(kobj_to_dev(kobj)); addr = (DS1305_WRITE | DS1305_NVRAM) + off; msg_init(&m, x, &addr, count, buf, NULL); - status = spi_sync(spi, &m); - if (status < 0) - dev_err(&spi->dev, "nvram %s error %d\n", "write", status); - return (status < 0) ? status : count; + return spi_sync(spi, &m); } -static struct bin_attribute nvram = { - .attr.name = "nvram", - .attr.mode = S_IRUGO | S_IWUSR, - .read = ds1305_nvram_read, - .write = ds1305_nvram_write, - .size = DS1305_NVRAM_LEN, +static struct nvmem_config ds1305_nvmem_cfg = { + .name = "ds1305_nvram", + .word_size = 1, + .stride = 1, + .size = DS1305_NVRAM_LEN, + .reg_read = ds1305_nvram_read, + .reg_write = ds1305_nvram_write, }; /*----------------------------------------------------------------------*/ @@ -715,6 +702,10 @@ static int ds1305_probe(struct spi_device *spi) ds1305->rtc->ops = &ds1305_ops; + ds1305_nvmem_cfg.priv = ds1305; + ds1305->rtc->nvmem_config = &ds1305_nvmem_cfg; + ds1305->rtc->nvram_old_abi = true; + status = rtc_register_device(ds1305->rtc); if (status) { dev_dbg(&spi->dev, "register rtc --> %d\n", status); @@ -739,12 +730,6 @@ static int ds1305_probe(struct spi_device *spi) } } - /* export NVRAM */ - status = sysfs_create_bin_file(&spi->dev.kobj, &nvram); - if (status < 0) { - dev_err(&spi->dev, "register nvram --> %d\n", status); - } - return 0; } @@ -752,8 +737,6 @@ static int ds1305_remove(struct spi_device *spi) { struct ds1305 *ds1305 = spi_get_drvdata(spi); - sysfs_remove_bin_file(&spi->dev.kobj, &nvram); - /* carefully shut down irq and workqueue, if present */ if (spi->irq) { set_bit(FLAG_EXITING, &ds1305->flags); -- GitLab From 5508c72528d22805e301ecdfd3abcd85af24b0ec Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:04:20 +0200 Subject: [PATCH 1127/2898] rtc: m48t86: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m48t86.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 02af045305dd..22656a90cfc5 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -228,6 +228,7 @@ static int m48t86_rtc_probe(struct platform_device *pdev) struct m48t86_rtc_info *info; struct resource *res; unsigned char reg; + int err; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) @@ -254,11 +255,16 @@ static int m48t86_rtc_probe(struct platform_device *pdev) return -ENODEV; } - info->rtc = devm_rtc_device_register(&pdev->dev, "m48t86", - &m48t86_rtc_ops, THIS_MODULE); + info->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(info->rtc)) return PTR_ERR(info->rtc); + info->rtc->ops = &m48t86_rtc_ops; + + err = rtc_register_device(info->rtc); + if (err) + return err; + /* read battery status */ reg = m48t86_readb(&pdev->dev, M48T86_D); dev_info(&pdev->dev, "battery %s\n", -- GitLab From f8033aabb23bd8b2b51e2c32ee759f860ecdd1ee Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:04:21 +0200 Subject: [PATCH 1128/2898] rtc: m48t86: use generic nvmem Instead of adding a binary sysfs attribute from the driver (which suffers from a race condition as the attribute appears after the device), use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m48t86.c | 48 +++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index 22656a90cfc5..d9aea9b6d9cd 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -163,35 +163,30 @@ static const struct rtc_class_ops m48t86_rtc_ops = { .proc = m48t86_rtc_proc, }; -static ssize_t m48t86_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int m48t86_nvram_read(void *priv, unsigned int off, void *buf, + size_t count) { - struct device *dev = kobj_to_dev(kobj); + struct device *dev = priv; unsigned int i; for (i = 0; i < count; i++) - buf[i] = m48t86_readb(dev, M48T86_NVRAM(off + i)); + ((u8 *)buf)[i] = m48t86_readb(dev, M48T86_NVRAM(off + i)); - return count; + return 0; } -static ssize_t m48t86_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static int m48t86_nvram_write(void *priv, unsigned int off, void *buf, + size_t count) { - struct device *dev = kobj_to_dev(kobj); + struct device *dev = priv; unsigned int i; for (i = 0; i < count; i++) - m48t86_writeb(dev, buf[i], M48T86_NVRAM(off + i)); + m48t86_writeb(dev, ((u8 *)buf)[i], M48T86_NVRAM(off + i)); - return count; + return 0; } -static BIN_ATTR(nvram, 0644, m48t86_nvram_read, m48t86_nvram_write, - M48T86_NVRAM_LEN); - /* * The RTC is an optional feature at purchase time on some Technologic Systems * boards. Verify that it actually exists by checking if the last two bytes @@ -223,6 +218,15 @@ static bool m48t86_verify_chip(struct platform_device *pdev) return false; } +static struct nvmem_config m48t86_nvmem_cfg = { + .name = "m48t86_nvram", + .word_size = 1, + .stride = 1, + .size = M48T86_NVRAM_LEN, + .reg_read = m48t86_nvram_read, + .reg_write = m48t86_nvram_write, +}; + static int m48t86_rtc_probe(struct platform_device *pdev) { struct m48t86_rtc_info *info; @@ -261,6 +265,10 @@ static int m48t86_rtc_probe(struct platform_device *pdev) info->rtc->ops = &m48t86_rtc_ops; + m48t86_nvmem_cfg.priv = &pdev->dev; + info->rtc->nvmem_config = &m48t86_nvmem_cfg; + info->rtc->nvram_old_abi = true; + err = rtc_register_device(info->rtc); if (err) return err; @@ -270,15 +278,6 @@ static int m48t86_rtc_probe(struct platform_device *pdev) dev_info(&pdev->dev, "battery %s\n", (reg & M48T86_D_VRT) ? "ok" : "exhausted"); - if (device_create_bin_file(&pdev->dev, &bin_attr_nvram)) - dev_err(&pdev->dev, "failed to create nvram sysfs entry\n"); - - return 0; -} - -static int m48t86_rtc_remove(struct platform_device *pdev) -{ - device_remove_bin_file(&pdev->dev, &bin_attr_nvram); return 0; } @@ -287,7 +286,6 @@ static struct platform_driver m48t86_rtc_platform_driver = { .name = "rtc-m48t86", }, .probe = m48t86_rtc_probe, - .remove = m48t86_rtc_remove, }; module_platform_driver(m48t86_rtc_platform_driver); -- GitLab From 9360a6a81862d3acfeb44745d9db4f9861ba4159 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:04:46 +0200 Subject: [PATCH 1129/2898] rtc: abx80x: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-abx80x.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index fea9a60b06cf..442e62a3c9a9 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -614,12 +614,16 @@ static int abx80x_probe(struct i2c_client *client, if (err) return err; - rtc = devm_rtc_device_register(&client->dev, "abx8xx", - &abx80x_rtc_ops, THIS_MODULE); - + rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(rtc)) return PTR_ERR(rtc); + rtc->ops = &abx80x_rtc_ops; + + err = rtc_register_device(rtc); + if (err) + return err; + i2c_set_clientdata(client, rtc); if (client->irq > 0) { -- GitLab From 9da32ba64d59d577297bf766a3f12753ebef5712 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:04:47 +0200 Subject: [PATCH 1130/2898] rtc: abx80x: solve race condition There is a race condition that can happen if abx80x_probe() fails after the rtc registration succeeded. Solve that by moving the registration at the end of the probe function. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-abx80x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index 442e62a3c9a9..b033bc556f5d 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -620,10 +620,6 @@ static int abx80x_probe(struct i2c_client *client, rtc->ops = &abx80x_rtc_ops; - err = rtc_register_device(rtc); - if (err) - return err; - i2c_set_clientdata(client, rtc); if (client->irq > 0) { @@ -650,10 +646,14 @@ static int abx80x_probe(struct i2c_client *client, err = devm_add_action_or_reset(&client->dev, rtc_calib_remove_sysfs_group, &client->dev); - if (err) + if (err) { dev_err(&client->dev, "Failed to add sysfs cleanup action: %d\n", err); + return err; + } + + err = rtc_register_device(rtc); return err; } -- GitLab From 3032269b21fdbfc021b14d14a50bec39f9891b08 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:05:27 +0200 Subject: [PATCH 1131/2898] rtc: ds1511: switch to rtc_register_device This allows for future improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1511.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 1b2dcb58c0ab..d44635178771 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -477,11 +477,16 @@ static int ds1511_rtc_probe(struct platform_device *pdev) spin_lock_init(&pdata->lock); platform_set_drvdata(pdev, pdata); - pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &ds1511_rtc_ops, THIS_MODULE); + pdata->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(pdata->rtc)) return PTR_ERR(pdata->rtc); + pdata->rtc->ops = &ds1511_rtc_ops; + + ret = rtc_register_device(pdata->rtc); + if (ret) + return ret; + /* * if the platform has an interrupt in mind for this device, * then by all means, set it -- GitLab From a283d27625ffe3dadf5daece25674eab89722b6a Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:05:28 +0200 Subject: [PATCH 1132/2898] rtc: ds1511: allow waking platform Disabling interrupts when removing the driver is bad practice as this will prevent some platform from waking up when using that RTC. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1511.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index d44635178771..eda45358d63a 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -511,16 +511,8 @@ static int ds1511_rtc_probe(struct platform_device *pdev) static int ds1511_rtc_remove(struct platform_device *pdev) { - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); - if (pdata->irq > 0) { - /* - * disable the alarm interrupt - */ - rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); - rtc_read(RTC_CMD1); - } + return 0; } -- GitLab From 9d7ed21ff4af20628bad39689ff946d4649472d6 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:05:29 +0200 Subject: [PATCH 1133/2898] rtc: ds1511: use generic nvmem Instead of adding a binary sysfs attribute from the driver (which suffers from a race condition as the attribute appears after the device), use the core to register an nvmem device. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1511.c | 58 +++++++++++++++------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index eda45358d63a..1e95312a6f2e 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -398,42 +398,37 @@ static const struct rtc_class_ops ds1511_rtc_ops = { .alarm_irq_enable = ds1511_rtc_alarm_irq_enable, }; -static ssize_t -ds1511_nvram_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *ba, - char *buf, loff_t pos, size_t size) +static int ds1511_nvram_read(void *priv, unsigned int pos, void *buf, + size_t size) { - ssize_t count; + int i; rtc_write(pos, DS1511_RAMADDR_LSB); - for (count = 0; count < size; count++) - *buf++ = rtc_read(DS1511_RAMDATA); + for (i = 0; i < size; i++) + *(char *)buf++ = rtc_read(DS1511_RAMDATA); - return count; + return 0; } -static ssize_t -ds1511_nvram_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +static int ds1511_nvram_write(void *priv, unsigned int pos, void *buf, + size_t size) { - ssize_t count; + int i; rtc_write(pos, DS1511_RAMADDR_LSB); - for (count = 0; count < size; count++) - rtc_write(*buf++, DS1511_RAMDATA); + for (i = 0; i < size; i++) + rtc_write(*(char *)buf++, DS1511_RAMDATA); - return count; + return 0; } -static struct bin_attribute ds1511_nvram_attr = { - .attr = { - .name = "nvram", - .mode = S_IRUGO | S_IWUSR, - }, +static struct nvmem_config ds1511_nvmem_cfg = { + .name = "ds1511_nvram", + .word_size = 1, + .stride = 1, .size = DS1511_RAM_MAX, - .read = ds1511_nvram_read, - .write = ds1511_nvram_write, + .reg_read = ds1511_nvram_read, + .reg_write = ds1511_nvram_write, }; static int ds1511_rtc_probe(struct platform_device *pdev) @@ -483,6 +478,10 @@ static int ds1511_rtc_probe(struct platform_device *pdev) pdata->rtc->ops = &ds1511_rtc_ops; + ds1511_nvmem_cfg.priv = &pdev->dev; + pdata->rtc->nvmem_config = &ds1511_nvmem_cfg; + pdata->rtc->nvram_old_abi = true; + ret = rtc_register_device(pdata->rtc); if (ret) return ret; @@ -501,18 +500,6 @@ static int ds1511_rtc_probe(struct platform_device *pdev) } } - ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); - if (ret) - dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n", - ds1511_nvram_attr.attr.name); - - return 0; -} - -static int ds1511_rtc_remove(struct platform_device *pdev) -{ - sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); - return 0; } @@ -521,7 +508,6 @@ MODULE_ALIAS("platform:ds1511"); static struct platform_driver ds1511_rtc_driver = { .probe = ds1511_rtc_probe, - .remove = ds1511_rtc_remove, .driver = { .name = "ds1511", }, -- GitLab From d51fe3ba9773c8b6fc79f82bbe75d64baf604292 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:36:57 +0800 Subject: [PATCH 1134/2898] clk: sunxi-ng: sun5i: Fix bit offset of audio PLL post-divider The post-divider for the audio PLL is in bits [29:26], as specified in the user manual, not [19:16] as currently programmed in the code. The post-divider has a default register value of 2, i.e. a divider of 3. This means the clock rate fed to the audio codec would be off. This was discovered when porting sigma-delta modulation for the PLL to sun5i, which needs the post-divider to be 1. Fix the bit offset, so we do actually force the post-divider to a certain value. Fixes: 5e73761786d6 ("clk: sunxi-ng: Add sun5i CCU driver") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun5i.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c index ab9e850b3707..2f385a57cd91 100644 --- a/drivers/clk/sunxi-ng/ccu-sun5i.c +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c @@ -982,8 +982,8 @@ static void __init sun5i_ccu_init(struct device_node *node, /* Force the PLL-Audio-1x divider to 4 */ val = readl(reg + SUN5I_PLL_AUDIO_REG); - val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN5I_PLL_AUDIO_REG); + val &= ~GENMASK(29, 26); + writel(val | (3 << 26), reg + SUN5I_PLL_AUDIO_REG); /* * Use the peripheral PLL as the AHB parent, instead of CPU / -- GitLab From 4cdbc40d64d4b8303a97e29a52862e4d99502beb Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:36:58 +0800 Subject: [PATCH 1135/2898] clk: sunxi-ng: nm: Check if requested rate is supported by fractional clock The round_rate callback for N-M-factor style clocks does not check if the requested clock rate is supported by the fractional clock mode. While this doesn't affect usage in practice, since the clock rates are also supported through N-M factors, it does not match the set_rate code. Add a check to the round_rate callback so it matches the set_rate callback. Fixes: 6174a1e24b0d ("clk: sunxi-ng: Add N-M-factor clock support") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu_nm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index a32158e8f2e3..84a5e7f17f6f 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -99,6 +99,9 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, struct ccu_nm *nm = hw_to_ccu_nm(hw); struct _ccu_nm _nm; + if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) + return rate; + _nm.min_n = nm->n.min ?: 1; _nm.max_n = nm->n.max ?: 1 << nm->n.width; _nm.min_m = 1; -- GitLab From 05d2eaac96d4284b0967cc522ad22f6f23fdf82a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:36:59 +0800 Subject: [PATCH 1136/2898] clk: sunxi-ng: Add sigma-delta modulation support Sigma-delta modulation is supported for some PLLs. This allows fractional-N multipliers to be used. In reality we don't know how to configure the individual settings for it. However we can copy existing settings from the vendor kernel to support clock rates that cannot be generated from integer factors, but are really desired. The vendor kernel only uses this for the audio PLL clock, and only on the latest chips. This patch adds a new class of clocks, along with helper functions. It is intended to be merged into N-M-factor style clocks as a feature, much like fractional clocks. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_common.h | 1 + drivers/clk/sunxi-ng/ccu_sdm.c | 158 ++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_sdm.h | 80 +++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_sdm.c create mode 100644 drivers/clk/sunxi-ng/ccu_sdm.h diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 85a0633c1eac..8504d9c6f03a 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -10,6 +10,7 @@ lib-$(CONFIG_SUNXI_CCU) += ccu_gate.o lib-$(CONFIG_SUNXI_CCU) += ccu_mux.o lib-$(CONFIG_SUNXI_CCU) += ccu_mult.o lib-$(CONFIG_SUNXI_CCU) += ccu_phase.o +lib-$(CONFIG_SUNXI_CCU) += ccu_sdm.o # Multi-factor clocks lib-$(CONFIG_SUNXI_CCU) += ccu_nk.o diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h index cadd1a9f93b6..5d684ce77c54 100644 --- a/drivers/clk/sunxi-ng/ccu_common.h +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -24,6 +24,7 @@ #define CCU_FEATURE_ALL_PREDIV BIT(4) #define CCU_FEATURE_LOCK_REG BIT(5) #define CCU_FEATURE_MMC_TIMING_SWITCH BIT(6) +#define CCU_FEATURE_SIGMA_DELTA_MOD BIT(7) /* MMC timing mode switch bit */ #define CCU_MMC_NEW_TIMING_MODE BIT(30) diff --git a/drivers/clk/sunxi-ng/ccu_sdm.c b/drivers/clk/sunxi-ng/ccu_sdm.c new file mode 100644 index 000000000000..3b3dc9bdf2b0 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_sdm.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2017 Chen-Yu Tsai + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + */ + +#include +#include + +#include "ccu_sdm.h" + +bool ccu_sdm_helper_is_enabled(struct ccu_common *common, + struct ccu_sdm_internal *sdm) +{ + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return false; + + if (sdm->enable && !(readl(common->base + common->reg) & sdm->enable)) + return false; + + return !!(readl(common->base + sdm->tuning_reg) & sdm->tuning_enable); +} + +void ccu_sdm_helper_enable(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate) +{ + unsigned long flags; + unsigned int i; + u32 reg; + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return; + + /* Set the pattern */ + for (i = 0; i < sdm->table_size; i++) + if (sdm->table[i].rate == rate) + writel(sdm->table[i].pattern, + common->base + sdm->tuning_reg); + + /* Make sure SDM is enabled */ + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + sdm->tuning_reg); + writel(reg | sdm->tuning_enable, common->base + sdm->tuning_reg); + spin_unlock_irqrestore(common->lock, flags); + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + common->reg); + writel(reg | sdm->enable, common->base + common->reg); + spin_unlock_irqrestore(common->lock, flags); +} + +void ccu_sdm_helper_disable(struct ccu_common *common, + struct ccu_sdm_internal *sdm) +{ + unsigned long flags; + u32 reg; + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return; + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + common->reg); + writel(reg & ~sdm->enable, common->base + common->reg); + spin_unlock_irqrestore(common->lock, flags); + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + sdm->tuning_reg); + writel(reg & ~sdm->tuning_enable, common->base + sdm->tuning_reg); + spin_unlock_irqrestore(common->lock, flags); +} + +/* + * Sigma delta modulation provides a way to do fractional-N frequency + * synthesis, in essence allowing the PLL to output any frequency + * within its operational range. On earlier SoCs such as the A10/A20, + * some PLLs support this. On later SoCs, all PLLs support this. + * + * The datasheets do not explain what the "wave top" and "wave bottom" + * parameters mean or do, nor how to calculate the effective output + * frequency. The only examples (and real world usage) are for the audio + * PLL to generate 24.576 and 22.5792 MHz clock rates used by the audio + * peripherals. The author lacks the underlying domain knowledge to + * pursue this. + * + * The goal and function of the following code is to support the two + * clock rates used by the audio subsystem, allowing for proper audio + * playback and capture without any pitch or speed changes. + */ +bool ccu_sdm_helper_has_rate(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate) +{ + unsigned int i; + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return false; + + for (i = 0; i < sdm->table_size; i++) + if (sdm->table[i].rate == rate) + return true; + + return false; +} + +unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + u32 m, u32 n) +{ + unsigned int i; + u32 reg; + + pr_debug("%s: Read sigma-delta modulation setting\n", + clk_hw_get_name(&common->hw)); + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return 0; + + pr_debug("%s: clock is sigma-delta modulated\n", + clk_hw_get_name(&common->hw)); + + reg = readl(common->base + sdm->tuning_reg); + + pr_debug("%s: pattern reg is 0x%x", + clk_hw_get_name(&common->hw), reg); + + for (i = 0; i < sdm->table_size; i++) + if (sdm->table[i].pattern == reg && + sdm->table[i].m == m && sdm->table[i].n == n) + return sdm->table[i].rate; + + /* We can't calculate the effective clock rate, so just fail. */ + return 0; +} + +int ccu_sdm_helper_get_factors(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate, + unsigned long *m, unsigned long *n) +{ + unsigned int i; + + if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD)) + return -EINVAL; + + for (i = 0; i < sdm->table_size; i++) + if (sdm->table[i].rate == rate) { + *m = sdm->table[i].m; + *n = sdm->table[i].n; + return 0; + } + + /* nothing found */ + return -EINVAL; +} diff --git a/drivers/clk/sunxi-ng/ccu_sdm.h b/drivers/clk/sunxi-ng/ccu_sdm.h new file mode 100644 index 000000000000..2a9b4a2584d6 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_sdm.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017 Chen-Yu Tsai. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CCU_SDM_H +#define _CCU_SDM_H + +#include + +#include "ccu_common.h" + +struct ccu_sdm_setting { + unsigned long rate; + + /* + * XXX We don't know what the step and bottom register fields + * mean. Just copy the whole register value from the vendor + * kernel for now. + */ + u32 pattern; + + /* + * M and N factors here should be the values used in + * calculation, not the raw values written to registers + */ + u32 m; + u32 n; +}; + +struct ccu_sdm_internal { + struct ccu_sdm_setting *table; + u32 table_size; + /* early SoCs don't have the SDM enable bit in the PLL register */ + u32 enable; + /* second enable bit in tuning register */ + u32 tuning_enable; + u16 tuning_reg; +}; + +#define _SUNXI_CCU_SDM(_table, _enable, \ + _reg, _reg_enable) \ + { \ + .table = _table, \ + .table_size = ARRAY_SIZE(_table), \ + .enable = _enable, \ + .tuning_enable = _reg_enable, \ + .tuning_reg = _reg, \ + } + +bool ccu_sdm_helper_is_enabled(struct ccu_common *common, + struct ccu_sdm_internal *sdm); +void ccu_sdm_helper_enable(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate); +void ccu_sdm_helper_disable(struct ccu_common *common, + struct ccu_sdm_internal *sdm); + +bool ccu_sdm_helper_has_rate(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate); + +unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + u32 m, u32 n); + +int ccu_sdm_helper_get_factors(struct ccu_common *common, + struct ccu_sdm_internal *sdm, + unsigned long rate, + unsigned long *m, unsigned long *n); + +#endif -- GitLab From 392ba5fafcdf1969d1abd9a637cc40c45f4781bc Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:00 +0800 Subject: [PATCH 1137/2898] clk: sunxi-ng: nm: Add support for sigma-delta modulation Some of the N-M-style clocks, namely the PLLs, support sigma-delta modulation to do fractional-N frequency synthesis. This is used in the audio PLL to generate the exact frequency the audio blocks need. These frequencies can not be generated with integer N-M factors. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu_nm.c | 22 +++++++++++++++++++++- drivers/clk/sunxi-ng/ccu_nm.h | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index 84a5e7f17f6f..7620aa973a6e 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -90,6 +90,14 @@ static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw, if (!m) m++; + if (ccu_sdm_helper_is_enabled(&nm->common, &nm->sdm)) { + unsigned long rate = + ccu_sdm_helper_read_rate(&nm->common, &nm->sdm, + m, n); + if (rate) + return rate; + } + return parent_rate * n / m; } @@ -102,6 +110,9 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) return rate; + if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate)) + return rate; + _nm.min_n = nm->n.min ?: 1; _nm.max_n = nm->n.max ?: 1 << nm->n.width; _nm.min_m = 1; @@ -143,7 +154,16 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, _nm.min_m = 1; _nm.max_m = nm->m.max ?: 1 << nm->m.width; - ccu_nm_find_best(parent_rate, rate, &_nm); + if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate)) { + ccu_sdm_helper_enable(&nm->common, &nm->sdm, rate); + + /* Sigma delta modulation requires specific N and M factors */ + ccu_sdm_helper_get_factors(&nm->common, &nm->sdm, rate, + &_nm.m, &_nm.n); + } else { + ccu_sdm_helper_disable(&nm->common, &nm->sdm); + ccu_nm_find_best(parent_rate, rate, &_nm); + } spin_lock_irqsave(nm->common.lock, flags); diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h index e87fd186da78..c623b0c7a23c 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.h +++ b/drivers/clk/sunxi-ng/ccu_nm.h @@ -20,6 +20,7 @@ #include "ccu_div.h" #include "ccu_frac.h" #include "ccu_mult.h" +#include "ccu_sdm.h" /* * struct ccu_nm - Definition of an N-M clock @@ -33,10 +34,34 @@ struct ccu_nm { struct ccu_mult_internal n; struct ccu_div_internal m; struct ccu_frac_internal frac; + struct ccu_sdm_internal sdm; struct ccu_common common; }; +#define SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(_struct, _name, _parent, _reg, \ + _nshift, _nwidth, \ + _mshift, _mwidth, \ + _sdm_table, _sdm_en, \ + _sdm_reg, _sdm_reg_en, \ + _gate, _lock, _flags) \ + struct ccu_nm _struct = { \ + .enable = _gate, \ + .lock = _lock, \ + .n = _SUNXI_CCU_MULT(_nshift, _nwidth), \ + .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .sdm = _SUNXI_CCU_SDM(_sdm_table, _sdm_en, \ + _sdm_reg, _sdm_reg_en),\ + .common = { \ + .reg = _reg, \ + .features = CCU_FEATURE_SIGMA_DELTA_MOD, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_nm_ops, \ + _flags), \ + }, \ + } + #define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(_struct, _name, _parent, _reg, \ _nshift, _nwidth, \ _mshift, _mwidth, \ -- GitLab From a5e3e2b2ef85efe213c19b4911042bc2937a1aa6 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:01 +0800 Subject: [PATCH 1138/2898] clk: sunxi-ng: sun8i: h3: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. This patch copies the parameters for the H3. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 38 +++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 543c46d0e045..29bc0566b776 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -26,6 +26,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun8i-h3.h" @@ -44,18 +45,29 @@ static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux", * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN8I_H3_PLL_AUDIO_REG 0x008 -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", - "osc24M", 0x008, - 8, 7, /* N */ - 0, 5, /* M */ - BIT(31), /* gate */ - BIT(28), /* lock */ - CLK_SET_RATE_UNGATE); +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + pll_audio_sdm_table, BIT(24), + 0x284, BIT(31), + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", "osc24M", 0x0010, @@ -707,9 +719,9 @@ static struct ccu_common *sun50i_h5_ccu_clks[] = { &gpu_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -1129,10 +1141,10 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN8I_H3_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); + writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); sunxi_ccu_probe(node, reg, desc); -- GitLab From de344851919493033cdaa5736b2bfbcb05b50038 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:02 +0800 Subject: [PATCH 1139/2898] clk: sunxi-ng: sun4i: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. As the PLL hardware is identical in most chips, we can back port the settings from the newer SoC, in this case the H3, onto the A10 and A20. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun4i-a10.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c index a48fde191c0a..ffa5dac221e4 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c @@ -28,6 +28,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun4i-a10.h" @@ -51,16 +52,29 @@ static struct ccu_nkmp pll_core_clk = { * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names. + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN4I_PLL_AUDIO_REG 0x008 + +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + static struct ccu_nm pll_audio_base_clk = { .enable = BIT(31), .n = _SUNXI_CCU_MULT_OFFSET(8, 7, 0), .m = _SUNXI_CCU_DIV_OFFSET(0, 5, 0), + .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, 0, + 0x00c, BIT(31)), .common = { .reg = 0x008, + .features = CCU_FEATURE_SIGMA_DELTA_MOD, .hw.init = CLK_HW_INIT("pll-audio-base", "hosc", &ccu_nm_ops, @@ -1021,9 +1035,9 @@ static struct ccu_common *sun4i_sun7i_ccu_clks[] = { &out_b_clk.common }; -/* Post-divider for pll-audio is hardcoded to 4 */ +/* Post-divider for pll-audio is hardcoded to 1 */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -1420,10 +1434,10 @@ static void __init sun4i_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN4I_PLL_AUDIO_REG); val &= ~GENMASK(29, 26); - writel(val | (4 << 26), reg + SUN4I_PLL_AUDIO_REG); + writel(val | (1 << 26), reg + SUN4I_PLL_AUDIO_REG); /* * Use the peripheral PLL6 as the AHB parent, instead of CPU / -- GitLab From 042f7f8f9715096abce42b944d4a23b0e3c31521 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:03 +0800 Subject: [PATCH 1140/2898] clk: sunxi-ng: sun5i: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. As the PLL hardware is identical in most chips, we can back port the settings from the newer SoC, in this case the H3, onto the sun5i family. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun5i.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c index 2f385a57cd91..fa2c2dd77102 100644 --- a/drivers/clk/sunxi-ng/ccu-sun5i.c +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c @@ -26,6 +26,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun5i.h" @@ -49,11 +50,20 @@ static struct ccu_nkmp pll_core_clk = { * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN5I_PLL_AUDIO_REG 0x008 +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + static struct ccu_nm pll_audio_base_clk = { .enable = BIT(31), .n = _SUNXI_CCU_MULT_OFFSET(8, 7, 0), @@ -63,8 +73,11 @@ static struct ccu_nm pll_audio_base_clk = { * offset */ .m = _SUNXI_CCU_DIV_OFFSET(0, 5, 0), + .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, 0, + 0x00c, BIT(31)), .common = { .reg = 0x008, + .features = CCU_FEATURE_SIGMA_DELTA_MOD, .hw.init = CLK_HW_INIT("pll-audio-base", "hosc", &ccu_nm_ops, @@ -597,9 +610,9 @@ static struct ccu_common *sun5i_a10s_ccu_clks[] = { &iep_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -980,10 +993,10 @@ static void __init sun5i_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN5I_PLL_AUDIO_REG); val &= ~GENMASK(29, 26); - writel(val | (3 << 26), reg + SUN5I_PLL_AUDIO_REG); + writel(val | (0 << 26), reg + SUN5I_PLL_AUDIO_REG); /* * Use the peripheral PLL as the AHB parent, instead of CPU / -- GitLab From ee6501d69217a887cb496c42ff97ba43adff4ab1 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:04 +0800 Subject: [PATCH 1141/2898] clk: sunxi-ng: sun6i: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. As the PLL hardware is identical in most chips, we can back port the settings from the newer SoC, in this case the H3, onto the A31. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 38 ++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 241fb13f1c06..72b16ed1012b 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -31,6 +31,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun6i-a31.h" @@ -48,18 +49,29 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_cpu_clk, "pll-cpu", * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN6I_A31_PLL_AUDIO_REG 0x008 -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", - "osc24M", 0x008, - 8, 7, /* N */ - 0, 5, /* M */ - BIT(31), /* gate */ - BIT(28), /* lock */ - CLK_SET_RATE_UNGATE); +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + pll_audio_sdm_table, BIT(24), + 0x284, BIT(31), + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", "osc24M", 0x010, @@ -950,9 +962,9 @@ static struct ccu_common *sun6i_a31_ccu_clks[] = { &out_c_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -1221,10 +1233,10 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN6I_A31_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN6I_A31_PLL_AUDIO_REG); + writel(val | (0 << 16), reg + SUN6I_A31_PLL_AUDIO_REG); /* Force PLL-MIPI to MIPI mode */ val = readl(reg + SUN6I_A31_PLL_MIPI_REG); -- GitLab From 24ea78a09f8948484e466474c038411a926f670f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 12 Oct 2017 16:37:05 +0800 Subject: [PATCH 1142/2898] clk: sunxi-ng: sun8i: a23: Use sigma-delta modulation for audio PLL The audio blocks require specific clock rates. Until now we were using the closest clock rate possible with integer N-M factors. This resulted in audio playback being slightly slower than it should be. The vendor kernel gets around this (for newer SoCs) by using sigma-delta modulation to generate a fractional-N factor. As the PLL hardware is identical in most chips, we can back port the settings from the newer SoC, in this case the H3, onto the A23. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-a23.c | 38 ++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c index d93b452f0df9..a4fa2945f230 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c @@ -26,6 +26,7 @@ #include "ccu_nkmp.h" #include "ccu_nm.h" #include "ccu_phase.h" +#include "ccu_sdm.h" #include "ccu-sun8i-a23-a33.h" @@ -52,18 +53,29 @@ static struct ccu_nkmp pll_cpux_clk = { * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN8I_A23_PLL_AUDIO_REG 0x008 -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", - "osc24M", 0x008, - 8, 7, /* N */ - 0, 5, /* M */ - BIT(31), /* gate */ - BIT(28), /* lock */ - CLK_SET_RATE_UNGATE); +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + pll_audio_sdm_table, BIT(24), + 0x284, BIT(31), + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", "osc24M", 0x010, @@ -538,9 +550,9 @@ static struct ccu_common *sun8i_a23_ccu_clks[] = { &ats_clk.common, }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", - "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", @@ -720,10 +732,10 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node) return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN8I_A23_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN8I_A23_PLL_AUDIO_REG); + writel(val | (0 << 16), reg + SUN8I_A23_PLL_AUDIO_REG); /* Force PLL-MIPI to MIPI mode */ val = readl(reg + SUN8I_A23_PLL_MIPI_REG); -- GitLab From af41acf8347dd6d11a2a29a11e2866ca4892d600 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 11 Oct 2017 12:46:47 -0400 Subject: [PATCH 1143/2898] printk: Remove superfluous memory barriers from printk_safe The variable printk_safe_irq_ready is set and never cleared at system boot up, when there's only one CPU active. It is set before other CPUs come on line. Also, it is extremely unlikely that an NMI would trigger this early in boot up (which I wonder why we even have this variable at all). Also mark the printk_safe_irq_ready as read mostly, as it is set at system boot up, and never touched again. Link: http://lkml.kernel.org/r/20171011124647.7781f98f@gandalf.local.home Reviewed-by: Petr Mladek Signed-off-by: Steven Rostedt (VMware) --- kernel/printk/printk_safe.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 3cdaeaef9ce1..724d9292d4b9 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -39,7 +39,7 @@ * There are situations when we want to make sure that all buffers * were handled or when IRQs are blocked. */ -static int printk_safe_irq_ready; +static int printk_safe_irq_ready __read_mostly; #define SAFE_LOG_BUF_LEN ((1 << CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT) - \ sizeof(atomic_t) - \ @@ -63,11 +63,8 @@ static DEFINE_PER_CPU(struct printk_safe_seq_buf, nmi_print_seq); /* Get flushed in a more safe context. */ static void queue_flush_work(struct printk_safe_seq_buf *s) { - if (printk_safe_irq_ready) { - /* Make sure that IRQ work is really initialized. */ - smp_rmb(); + if (printk_safe_irq_ready) irq_work_queue(&s->work); - } } /* @@ -398,8 +395,12 @@ void __init printk_safe_init(void) #endif } - /* Make sure that IRQ works are initialized before enabling. */ - smp_wmb(); + /* + * In the highly unlikely event that a NMI were to trigger at + * this moment. Make sure IRQ work is set up before this + * variable is set. + */ + barrier(); printk_safe_irq_ready = 1; /* Flush pending messages that did not have scheduled IRQ works. */ -- GitLab From c3b5b6ed1eb4f429addfd9e8e8eb39d1a38c85d0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 13 Oct 2017 16:22:20 +0200 Subject: [PATCH 1144/2898] tracing: mark trace_test_buffer as __maybe_unused After trace_selftest_startup_sched_switch is removed, trace_test_buffer() is only used sometimes, leading to this warning: kernel/trace/trace_selftest.c:62:12: error: 'trace_test_buffer' defined but not used [-Werror=unused-function] There is no simple #ifdef condition that captures well whether the function is in fact used or not, so marking it as __maybe_unused is probably the best way to shut up the warning. The function will then be silently dropped when there is no user. Link: http://lkml.kernel.org/r/20171013142227.1273469-1-arnd@arndb.de Fixes: d8c4deee6dc6 ("tracing: Remove obsolete sched_switch tracer selftest") Signed-off-by: Arnd Bergmann Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_selftest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 364f78abdf47..eb9ba5c1ba40 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -59,7 +59,7 @@ static int trace_test_buffer_cpu(struct trace_buffer *buf, int cpu) * Test the trace buffer to see if all the elements * are still sane. */ -static int trace_test_buffer(struct trace_buffer *buf, unsigned long *count) +static int __maybe_unused trace_test_buffer(struct trace_buffer *buf, unsigned long *count) { unsigned long flags, cnt = 0; int cpu, ret = 0; -- GitLab From e83543b495598233c3741b23bed7c82161c93e24 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Tue, 10 Oct 2017 19:12:56 -0400 Subject: [PATCH 1145/2898] tracing/xen: Hide events that are not used when X86_PAE is not defined TRACE_EVENTS() take up memory. If they are defined but not used, then they simply waste space. If their use case is behind a define, then the trace events should be as well. The trace events xen_mmu_set_pte_atomic, xen_mmu_pte_clear, and xen_mmu_pmd_clear are not used when CONFIG_X86_PAE is not defined. Link: http://lkml.kernel.org/r/20171010191256.3d6d72cb@gandalf.local.home Reviewed-by: Boris Ostrovsky Reviewed-by: Jeremy Linton Signed-off-by: Steven Rostedt (VMware) --- include/trace/events/xen.h | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 1b4fed72f573..6118d82334ec 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -147,7 +147,6 @@ DECLARE_EVENT_CLASS(xen_mmu__set_pte, TP_ARGS(ptep, pteval)) DEFINE_XEN_MMU_SET_PTE(xen_mmu_set_pte); -DEFINE_XEN_MMU_SET_PTE(xen_mmu_set_pte_atomic); TRACE_EVENT(xen_mmu_set_pte_at, TP_PROTO(struct mm_struct *mm, unsigned long addr, @@ -169,21 +168,6 @@ TRACE_EVENT(xen_mmu_set_pte_at, (int)sizeof(pteval_t) * 2, (unsigned long long)__entry->pteval) ); -TRACE_EVENT(xen_mmu_pte_clear, - TP_PROTO(struct mm_struct *mm, unsigned long addr, pte_t *ptep), - TP_ARGS(mm, addr, ptep), - TP_STRUCT__entry( - __field(struct mm_struct *, mm) - __field(unsigned long, addr) - __field(pte_t *, ptep) - ), - TP_fast_assign(__entry->mm = mm; - __entry->addr = addr; - __entry->ptep = ptep), - TP_printk("mm %p addr %lx ptep %p", - __entry->mm, __entry->addr, __entry->ptep) - ); - TRACE_DEFINE_SIZEOF(pmdval_t); TRACE_EVENT(xen_mmu_set_pmd, @@ -201,6 +185,24 @@ TRACE_EVENT(xen_mmu_set_pmd, (int)sizeof(pmdval_t) * 2, (unsigned long long)__entry->pmdval) ); +#ifdef CONFIG_X86_PAE +DEFINE_XEN_MMU_SET_PTE(xen_mmu_set_pte_atomic); + +TRACE_EVENT(xen_mmu_pte_clear, + TP_PROTO(struct mm_struct *mm, unsigned long addr, pte_t *ptep), + TP_ARGS(mm, addr, ptep), + TP_STRUCT__entry( + __field(struct mm_struct *, mm) + __field(unsigned long, addr) + __field(pte_t *, ptep) + ), + TP_fast_assign(__entry->mm = mm; + __entry->addr = addr; + __entry->ptep = ptep), + TP_printk("mm %p addr %lx ptep %p", + __entry->mm, __entry->addr, __entry->ptep) + ); + TRACE_EVENT(xen_mmu_pmd_clear, TP_PROTO(pmd_t *pmdp), TP_ARGS(pmdp), @@ -210,6 +212,7 @@ TRACE_EVENT(xen_mmu_pmd_clear, TP_fast_assign(__entry->pmdp = pmdp), TP_printk("pmdp %p", __entry->pmdp) ); +#endif #if CONFIG_PGTABLE_LEVELS >= 4 -- GitLab From f40a37cb4916f17806b8a89d8eb76f6943c69189 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Thu, 12 Oct 2017 18:46:32 -0400 Subject: [PATCH 1146/2898] tracing, memcg, vmscan: Hide trace events when not in use When trace events are defined but not used they still create data structures and functions for their use, even though nothing may be using them. The trace events mm_vmscan_memcg_reclaim_begin, mm_vmscan_memcg_softlimit_reclaim_begin, mm_vmscan_memcg_reclaim_end, and mm_vmscan_memcg_softlimit_reclaim_end are not used if CONFIG_MEMCG is not defined. Do not create these trace events unless CONFIG_MEMCG is defined. Link: http://lkml.kernel.org/r/20171012184632.2bd247cd@gandalf.local.home Acked-by: Michal Hocko Signed-off-by: Steven Rostedt (VMware) --- include/trace/events/vmscan.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h index 27e8a5c77579..cde5fea0a179 100644 --- a/include/trace/events/vmscan.h +++ b/include/trace/events/vmscan.h @@ -133,6 +133,7 @@ DEFINE_EVENT(mm_vmscan_direct_reclaim_begin_template, mm_vmscan_direct_reclaim_b TP_ARGS(order, may_writepage, gfp_flags, classzone_idx) ); +#ifdef CONFIG_MEMCG DEFINE_EVENT(mm_vmscan_direct_reclaim_begin_template, mm_vmscan_memcg_reclaim_begin, TP_PROTO(int order, int may_writepage, gfp_t gfp_flags, int classzone_idx), @@ -146,6 +147,7 @@ DEFINE_EVENT(mm_vmscan_direct_reclaim_begin_template, mm_vmscan_memcg_softlimit_ TP_ARGS(order, may_writepage, gfp_flags, classzone_idx) ); +#endif /* CONFIG_MEMCG */ DECLARE_EVENT_CLASS(mm_vmscan_direct_reclaim_end_template, @@ -171,6 +173,7 @@ DEFINE_EVENT(mm_vmscan_direct_reclaim_end_template, mm_vmscan_direct_reclaim_end TP_ARGS(nr_reclaimed) ); +#ifdef CONFIG_MEMCG DEFINE_EVENT(mm_vmscan_direct_reclaim_end_template, mm_vmscan_memcg_reclaim_end, TP_PROTO(unsigned long nr_reclaimed), @@ -184,6 +187,7 @@ DEFINE_EVENT(mm_vmscan_direct_reclaim_end_template, mm_vmscan_memcg_softlimit_re TP_ARGS(nr_reclaimed) ); +#endif /* CONFIG_MEMCG */ TRACE_EVENT(mm_shrink_slab_start, TP_PROTO(struct shrinker *shr, struct shrink_control *sc, -- GitLab From b9bb98424c51437973b854691aa1e9b2bfd348f5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 5 Oct 2017 18:53:19 +0200 Subject: [PATCH 1147/2898] mtd: nand: Export nand_reset() symbol Commit 6e532afaca8e ("mtd: nand: atmel: Add PM ops") started to use the nand_reset() function which was not yet exported by the NAND framework (because it was only used internally before that). Export this symbol to avoid build errors when the driver is enabled as a module. Fixes: 6e532afaca8e ("mtd: nand: atmel: Add PM ops") Cc: Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c63e4a88a653..4c867115c53b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1244,6 +1244,7 @@ int nand_reset(struct nand_chip *chip, int chipnr) return 0; } +EXPORT_SYMBOL_GPL(nand_reset); /** * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data -- GitLab From 1533bfa6f6b6bcca1ea1f172ef4a1c5ce5e7b335 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 5 Oct 2017 18:57:24 +0200 Subject: [PATCH 1148/2898] mtd: nand: atmel: Actually use the PM ops commit 6e532afaca8e ("mtd: nand: atmel: Add PM ops") was defining PM ops but nothing was using/referencing those PM ops. Fixes: 6e532afaca8e ("mtd: nand: atmel: Add PM ops") Cc: Cc: Romain Izard Signed-off-by: Boris Brezillon Acked-by: Wenyou Yang Tested-by: Romain Izard --- drivers/mtd/nand/atmel/nand-controller.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c index 29182160bb5f..90a71a56bc23 100644 --- a/drivers/mtd/nand/atmel/nand-controller.c +++ b/drivers/mtd/nand/atmel/nand-controller.c @@ -2549,6 +2549,7 @@ static struct platform_driver atmel_nand_controller_driver = { .driver = { .name = "atmel-nand-controller", .of_match_table = of_match_ptr(atmel_nand_controller_of_ids), + .pm = &atmel_nand_controller_pm_ops, }, .probe = atmel_nand_controller_probe, .remove = atmel_nand_controller_remove, -- GitLab From 086c321ec57bfda5b15f3553e7def33302955852 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Tue, 10 Oct 2017 14:38:07 +0200 Subject: [PATCH 1149/2898] mtd: nand: omap2: Remove omap_nand_platform_data As driver is now configured using DT, omap_nand_platform_data structure is no longer needed. Signed-off-by: Ladislav Michl Acked-by: Roger Quadros Signed-off-by: Boris Brezillon --- drivers/mtd/nand/omap2.c | 37 +++++--------------- include/linux/platform_data/mtd-nand-omap2.h | 17 --------- 2 files changed, 8 insertions(+), 46 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 54540c8fa1a2..01368a8f9e3f 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1588,8 +1588,7 @@ static bool is_elm_present(struct omap_nand_info *info, return true; } -static bool omap2_nand_ecc_check(struct omap_nand_info *info, - struct omap_nand_platform_data *pdata) +static bool omap2_nand_ecc_check(struct omap_nand_info *info) { bool ecc_needs_bch, ecc_needs_omap_bch, ecc_needs_elm; @@ -1804,7 +1803,6 @@ static const struct mtd_ooblayout_ops omap_sw_ooblayout_ops = { static int omap_nand_probe(struct platform_device *pdev) { struct omap_nand_info *info; - struct omap_nand_platform_data *pdata = NULL; struct mtd_info *mtd; struct nand_chip *nand_chip; int err; @@ -1821,27 +1819,9 @@ static int omap_nand_probe(struct platform_device *pdev) info->pdev = pdev; - if (dev->of_node) { - if (omap_get_dt_info(dev, info)) - return -EINVAL; - } else { - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - dev_err(&pdev->dev, "platform data missing\n"); - return -EINVAL; - } - - info->gpmc_cs = pdata->cs; - info->reg = pdata->reg; - info->ecc_opt = pdata->ecc_opt; - if (pdata->dev_ready) - dev_info(&pdev->dev, "pdata->dev_ready is deprecated\n"); - - info->xfer_type = pdata->xfer_type; - info->devsize = pdata->devsize; - info->elm_of_node = pdata->elm_of_node; - info->flash_bbt = pdata->flash_bbt; - } + err = omap_get_dt_info(dev, info); + if (err) + return err; platform_set_drvdata(pdev, info); info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs); @@ -2002,7 +1982,7 @@ static int omap_nand_probe(struct platform_device *pdev) goto return_error; } - if (!omap2_nand_ecc_check(info, pdata)) { + if (!omap2_nand_ecc_check(info)) { err = -EINVAL; goto return_error; } @@ -2167,10 +2147,9 @@ static int omap_nand_probe(struct platform_device *pdev) if (err) goto return_error; - if (dev->of_node) - mtd_device_register(mtd, NULL, 0); - else - mtd_device_register(mtd, pdata->parts, pdata->nr_parts); + err = mtd_device_register(mtd, NULL, 0); + if (err) + goto return_error; platform_set_drvdata(pdev, mtd); diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index 17d57a18bac5..8b8b124e8aea 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -66,21 +66,4 @@ struct gpmc_nand_regs { /* Deprecated. Do not use */ void __iomem *gpmc_status; }; - -struct omap_nand_platform_data { - int cs; - struct mtd_partition *parts; - int nr_parts; - bool flash_bbt; - enum nand_io xfer_type; - int devsize; - enum omap_ecc ecc_opt; - - struct device_node *elm_of_node; - - /* deprecated */ - struct gpmc_nand_regs reg; - struct device_node *of_node; - bool dev_ready; -}; #endif -- GitLab From f67ae488fd64029460551e34d403aa64562faea0 Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Tue, 10 Oct 2017 15:32:45 +0200 Subject: [PATCH 1150/2898] mtd: nand: omap2: Do not assign omap_nand_info to platform drvdata commit 67ce04bf2746 ("mtd: nand: add OMAP2/OMAP3 NAND driver") assigned pointer to omap_nand_info to the platform drvdata in probe function just to be reasigned later to the pointer to mtd_info, which is what remove function expects it to be. Remove useless assignment. Signed-off-by: Ladislav Michl Acked-by: Roger Quadros Signed-off-by: Boris Brezillon --- drivers/mtd/nand/omap2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 01368a8f9e3f..a97c1aeed55e 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1823,7 +1823,6 @@ static int omap_nand_probe(struct platform_device *pdev) if (err) return err; - platform_set_drvdata(pdev, info); info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs); if (!info->ops) { dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n"); -- GitLab From 73ecf5cf141a0c61775c10fdf3a6fc106f326f8c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 14 Oct 2017 13:18:33 -0400 Subject: [PATCH 1151/2898] do_handle_open() should be static Signed-off-by: Al Viro --- fs/fhandle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/fhandle.c b/fs/fhandle.c index 58a61f55e0d0..75cef4deaa77 100644 --- a/fs/fhandle.c +++ b/fs/fhandle.c @@ -212,8 +212,8 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, return retval; } -long do_handle_open(int mountdirfd, - struct file_handle __user *ufh, int open_flag) +static long do_handle_open(int mountdirfd, struct file_handle __user *ufh, + int open_flag) { long retval = 0; struct path path; -- GitLab From 216ac5297a8083ac4a27a6cbc3d20d13dd17984d Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Mon, 4 Sep 2017 10:51:17 +0200 Subject: [PATCH 1152/2898] clk: rockchip: export clock pclk_efuse_256 for RK3368 SoCs This exports the clock for the pclk gate of the eFuse that is part of the RK3368 SoCs. So we can use it from the dt-bindings. Signed-off-by: Romain Perier Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3368.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index fc56565379dd..7c4d242f19c1 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -711,7 +711,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(PCLK_SIM, "pclk_sim", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 8, GFLAGS), GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 6, GFLAGS), GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 5, GFLAGS), - GATE(0, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS), + GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS), GATE(0, "pclk_efuse_1024", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 0, GFLAGS), /* -- GitLab From 47e3ec0e4dae1714cc76596e38d16913f0e574e2 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 15 Sep 2017 10:33:50 +0200 Subject: [PATCH 1153/2898] clk: rockchip: use new cif/vdpu clock ids on rk3188 Use the new clock-ids for cif, vdpu, vepu on rk3188 Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3188.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 00ad0e5f8d66..67e73fd71f09 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -290,15 +290,15 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS), - COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, + COMPOSITE(ACLK_VEPU, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(3), 9, GFLAGS), - GATE(0, "hclk_vepu", "aclk_vepu", 0, + GATE(HCLK_VEPU, "hclk_vepu", "aclk_vepu", 0, RK2928_CLKGATE_CON(3), 10, GFLAGS), - COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, + COMPOSITE(ACLK_VDPU, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), - GATE(0, "hclk_vdpu", "aclk_vdpu", 0, + GATE(HCLK_VDPU, "hclk_vdpu", "aclk_vdpu", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS), GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, @@ -644,13 +644,13 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), - GATE(0, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS), + GATE(HCLK_CIF1, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS), GATE(0, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 14, GFLAGS), - GATE(0, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS), + GATE(ACLK_CIF1, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS), GATE(PCLK_TIMER1, "pclk_timer1", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 8, GFLAGS), GATE(PCLK_TIMER2, "pclk_timer2", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS), -- GitLab From 53fd88ab61948f711147204c1c5017c7301979e9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 14 Oct 2017 23:00:54 -0400 Subject: [PATCH 1154/2898] make vfs_ustat() static Signed-off-by: Al Viro --- fs/statfs.c | 2 +- include/linux/fs.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/statfs.c b/fs/statfs.c index fab9b6a3c116..6327edf79e0f 100644 --- a/fs/statfs.c +++ b/fs/statfs.c @@ -216,7 +216,7 @@ SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user return error; } -int vfs_ustat(dev_t dev, struct kstatfs *sbuf) +static int vfs_ustat(dev_t dev, struct kstatfs *sbuf) { struct super_block *s = user_get_super(dev); int err; diff --git a/include/linux/fs.h b/include/linux/fs.h index 339e73742e73..89323e03e648 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2169,7 +2169,6 @@ extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *, extern int vfs_statfs(const struct path *, struct kstatfs *); extern int user_statfs(const char __user *, struct kstatfs *); extern int fd_statfs(int, struct kstatfs *); -extern int vfs_ustat(dev_t, struct kstatfs *); extern int freeze_super(struct super_block *super); extern int thaw_super(struct super_block *super); extern bool our_mnt(struct vfsmount *mnt); -- GitLab From f175f307dd0bd1ca3825d244f9b870ff12981d3c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 15 Oct 2017 00:38:00 -0400 Subject: [PATCH 1155/2898] stubs for mount_bdev() and kill_block_super() in !CONFIG_BLOCK case Signed-off-by: Al Viro --- include/linux/fs.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/linux/fs.h b/include/linux/fs.h index 89323e03e648..31f8b2ea358c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2094,9 +2094,18 @@ struct file_system_type { extern struct dentry *mount_ns(struct file_system_type *fs_type, int flags, void *data, void *ns, struct user_namespace *user_ns, int (*fill_super)(struct super_block *, void *, int)); +#ifdef CONFIG_BLOCK extern struct dentry *mount_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, int (*fill_super)(struct super_block *, void *, int)); +#else +static inline struct dentry *mount_bdev(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, + int (*fill_super)(struct super_block *, void *, int)) +{ + return ERR_PTR(-ENODEV); +} +#endif extern struct dentry *mount_single(struct file_system_type *fs_type, int flags, void *data, int (*fill_super)(struct super_block *, void *, int)); @@ -2105,7 +2114,14 @@ extern struct dentry *mount_nodev(struct file_system_type *fs_type, int (*fill_super)(struct super_block *, void *, int)); extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path); void generic_shutdown_super(struct super_block *sb); +#ifdef CONFIG_BLOCK void kill_block_super(struct super_block *sb); +#else +static inline void kill_block_super(struct super_block *sb) +{ + BUG(); +} +#endif void kill_anon_super(struct super_block *sb); void kill_litter_super(struct super_block *sb); void deactivate_super(struct super_block *sb); -- GitLab From 99c18ce580c6cc6763e694b4ce320d7b226ab59b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 13 Oct 2017 16:09:23 -0400 Subject: [PATCH 1156/2898] cramfs: direct memory access support Small embedded systems typically execute the kernel code in place (XIP) directly from flash to save on precious RAM usage. This patch adds to cramfs the ability to consume filesystem data directly from flash as well. Cramfs is particularly well suited to this feature as it is very simple with low RAM usage, and with this feature it is possible to use it with no block device support and consequently even lower RAM usage. This patch was inspired by a similar patch from Shane Nay dated 17 years ago that used to be very popular in embedded circles but never made it into mainline. This is a cleaned-up implementation that uses far fewer ifdef's and gets the actual memory location for the filesystem image via MTD at run time. In the context of small IoT deployments, this functionality has become relevant and useful again. Signed-off-by: Nicolas Pitre Tested-by: Chris Brandt Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/cramfs/Kconfig | 30 ++++++- fs/cramfs/inode.c | 212 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 199 insertions(+), 43 deletions(-) diff --git a/fs/cramfs/Kconfig b/fs/cramfs/Kconfig index 11b29d491b7c..ef86b06bc064 100644 --- a/fs/cramfs/Kconfig +++ b/fs/cramfs/Kconfig @@ -1,6 +1,5 @@ config CRAMFS tristate "Compressed ROM file system support (cramfs) (OBSOLETE)" - depends on BLOCK select ZLIB_INFLATE help Saying Y here includes support for CramFs (Compressed ROM File @@ -20,3 +19,32 @@ config CRAMFS in terms of performance and features. If unsure, say N. + +config CRAMFS_BLOCKDEV + bool "Support CramFs image over a regular block device" if EXPERT + depends on CRAMFS && BLOCK + default y + help + This option allows the CramFs driver to load data from a regular + block device such a disk partition or a ramdisk. + +config CRAMFS_MTD + bool "Support CramFs image directly mapped in physical memory" + depends on CRAMFS && MTD + default y if !CRAMFS_BLOCKDEV + help + This option allows the CramFs driver to load data directly from + a linear adressed memory range (usually non volatile memory + like flash) instead of going through the block device layer. + This saves some memory since no intermediate buffering is + necessary. + + The location of the CramFs image is determined by a + MTD device capable of direct memory mapping e.g. from + the 'physmap' map driver or a resulting MTD partition. + For example, this would mount the cramfs image stored in + the MTD partition named "xip_fs" on the /mnt mountpoint: + + mount -t cramfs mtd:xip_fs /mnt + + If unsure, say N. diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 7919967488cb..bcdccb7a820b 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,6 +38,9 @@ struct cramfs_sb_info { unsigned long blocks; unsigned long files; unsigned long flags; + void *linear_virt_addr; + resource_size_t linear_phys_addr; + size_t mtd_point_size; }; static inline struct cramfs_sb_info *CRAMFS_SB(struct super_block *sb) @@ -140,6 +145,9 @@ static struct inode *get_cramfs_inode(struct super_block *sb, * BLKS_PER_BUF*PAGE_SIZE, so that the caller doesn't need to * worry about end-of-buffer issues even when decompressing a full * page cache. + * + * Note: This is all optimized away at compile time when + * CONFIG_CRAMFS_BLOCKDEV=n. */ #define READ_BUFFERS (2) /* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */ @@ -160,10 +168,10 @@ static struct super_block *buffer_dev[READ_BUFFERS]; static int next_buffer; /* - * Returns a pointer to a buffer containing at least LEN bytes of - * filesystem starting at byte offset OFFSET into the filesystem. + * Populate our block cache and return a pointer to it. */ -static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len) +static void *cramfs_blkdev_read(struct super_block *sb, unsigned int offset, + unsigned int len) { struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; struct page *pages[BLKS_PER_BUF]; @@ -239,11 +247,49 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i return read_buffers[buffer] + offset; } +/* + * Return a pointer to the linearly addressed cramfs image in memory. + */ +static void *cramfs_direct_read(struct super_block *sb, unsigned int offset, + unsigned int len) +{ + struct cramfs_sb_info *sbi = CRAMFS_SB(sb); + + if (!len) + return NULL; + if (len > sbi->size || offset > sbi->size - len) + return page_address(ZERO_PAGE(0)); + return sbi->linear_virt_addr + offset; +} + +/* + * Returns a pointer to a buffer containing at least LEN bytes of + * filesystem starting at byte offset OFFSET into the filesystem. + */ +static void *cramfs_read(struct super_block *sb, unsigned int offset, + unsigned int len) +{ + struct cramfs_sb_info *sbi = CRAMFS_SB(sb); + + if (IS_ENABLED(CONFIG_CRAMFS_MTD) && sbi->linear_virt_addr) + return cramfs_direct_read(sb, offset, len); + else if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV)) + return cramfs_blkdev_read(sb, offset, len); + else + return NULL; +} + static void cramfs_kill_sb(struct super_block *sb) { struct cramfs_sb_info *sbi = CRAMFS_SB(sb); - kill_block_super(sb); + if (IS_ENABLED(CCONFIG_CRAMFS_MTD) && sb->s_mtd) { + if (sbi && sbi->mtd_point_size) + mtd_unpoint(sb->s_mtd, 0, sbi->mtd_point_size); + kill_mtd_super(sb); + } else if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV) && sb->s_bdev) { + kill_block_super(sb); + } kfree(sbi); } @@ -254,34 +300,24 @@ static int cramfs_remount(struct super_block *sb, int *flags, char *data) return 0; } -static int cramfs_fill_super(struct super_block *sb, void *data, int silent) +static int cramfs_read_super(struct super_block *sb, + struct cramfs_super *super, int silent) { - int i; - struct cramfs_super super; + struct cramfs_sb_info *sbi = CRAMFS_SB(sb); unsigned long root_offset; - struct cramfs_sb_info *sbi; - struct inode *root; - - sb->s_flags |= MS_RDONLY; - - sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL); - if (!sbi) - return -ENOMEM; - sb->s_fs_info = sbi; - /* Invalidate the read buffers on mount: think disk change.. */ - mutex_lock(&read_mutex); - for (i = 0; i < READ_BUFFERS; i++) - buffer_blocknr[i] = -1; + /* We don't know the real size yet */ + sbi->size = PAGE_SIZE; /* Read the first block and get the superblock from it */ - memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super)); + mutex_lock(&read_mutex); + memcpy(super, cramfs_read(sb, 0, sizeof(*super)), sizeof(*super)); mutex_unlock(&read_mutex); /* Do sanity checks on the superblock */ - if (super.magic != CRAMFS_MAGIC) { + if (super->magic != CRAMFS_MAGIC) { /* check for wrong endianness */ - if (super.magic == CRAMFS_MAGIC_WEND) { + if (super->magic == CRAMFS_MAGIC_WEND) { if (!silent) pr_err("wrong endianness\n"); return -EINVAL; @@ -289,10 +325,12 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) /* check at 512 byte offset */ mutex_lock(&read_mutex); - memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super)); + memcpy(super, + cramfs_read(sb, 512, sizeof(*super)), + sizeof(*super)); mutex_unlock(&read_mutex); - if (super.magic != CRAMFS_MAGIC) { - if (super.magic == CRAMFS_MAGIC_WEND && !silent) + if (super->magic != CRAMFS_MAGIC) { + if (super->magic == CRAMFS_MAGIC_WEND && !silent) pr_err("wrong endianness\n"); else if (!silent) pr_err("wrong magic\n"); @@ -301,34 +339,34 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) } /* get feature flags first */ - if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { + if (super->flags & ~CRAMFS_SUPPORTED_FLAGS) { pr_err("unsupported filesystem features\n"); return -EINVAL; } /* Check that the root inode is in a sane state */ - if (!S_ISDIR(super.root.mode)) { + if (!S_ISDIR(super->root.mode)) { pr_err("root is not a directory\n"); return -EINVAL; } /* correct strange, hard-coded permissions of mkcramfs */ - super.root.mode |= (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + super->root.mode |= 0555; - root_offset = super.root.offset << 2; - if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { - sbi->size = super.size; - sbi->blocks = super.fsid.blocks; - sbi->files = super.fsid.files; + root_offset = super->root.offset << 2; + if (super->flags & CRAMFS_FLAG_FSID_VERSION_2) { + sbi->size = super->size; + sbi->blocks = super->fsid.blocks; + sbi->files = super->fsid.files; } else { sbi->size = 1<<28; sbi->blocks = 0; sbi->files = 0; } - sbi->magic = super.magic; - sbi->flags = super.flags; + sbi->magic = super->magic; + sbi->flags = super->flags; if (root_offset == 0) pr_info("empty filesystem"); - else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && + else if (!(super->flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && ((root_offset != sizeof(struct cramfs_super)) && (root_offset != 512 + sizeof(struct cramfs_super)))) { @@ -336,9 +374,18 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) return -EINVAL; } + return 0; +} + +static int cramfs_finalize_super(struct super_block *sb, + struct cramfs_inode *cramfs_root) +{ + struct inode *root; + /* Set it all up.. */ + sb->s_flags |= MS_RDONLY; sb->s_op = &cramfs_ops; - root = get_cramfs_inode(sb, &super.root, 0); + root = get_cramfs_inode(sb, cramfs_root, 0); if (IS_ERR(root)) return PTR_ERR(root); sb->s_root = d_make_root(root); @@ -347,10 +394,79 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) return 0; } +static int cramfs_blkdev_fill_super(struct super_block *sb, void *data, + int silent) +{ + struct cramfs_sb_info *sbi; + struct cramfs_super super; + int i, err; + + sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + sb->s_fs_info = sbi; + + /* Invalidate the read buffers on mount: think disk change.. */ + for (i = 0; i < READ_BUFFERS; i++) + buffer_blocknr[i] = -1; + + err = cramfs_read_super(sb, &super, silent); + if (err) + return err; + return cramfs_finalize_super(sb, &super.root); +} + +static int cramfs_mtd_fill_super(struct super_block *sb, void *data, + int silent) +{ + struct cramfs_sb_info *sbi; + struct cramfs_super super; + int err; + + sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + sb->s_fs_info = sbi; + + /* Map only one page for now. Will remap it when fs size is known. */ + err = mtd_point(sb->s_mtd, 0, PAGE_SIZE, &sbi->mtd_point_size, + &sbi->linear_virt_addr, &sbi->linear_phys_addr); + if (err || sbi->mtd_point_size != PAGE_SIZE) { + pr_err("unable to get direct memory access to mtd:%s\n", + sb->s_mtd->name); + return err ? : -ENODATA; + } + + pr_info("checking physical address %pap for linear cramfs image\n", + &sbi->linear_phys_addr); + err = cramfs_read_super(sb, &super, silent); + if (err) + return err; + + /* Remap the whole filesystem now */ + pr_info("linear cramfs image on mtd:%s appears to be %lu KB in size\n", + sb->s_mtd->name, sbi->size/1024); + mtd_unpoint(sb->s_mtd, 0, PAGE_SIZE); + err = mtd_point(sb->s_mtd, 0, sbi->size, &sbi->mtd_point_size, + &sbi->linear_virt_addr, &sbi->linear_phys_addr); + if (err || sbi->mtd_point_size != sbi->size) { + pr_err("unable to get direct memory access to mtd:%s\n", + sb->s_mtd->name); + return err ? : -ENODATA; + } + + return cramfs_finalize_super(sb, &super.root); +} + static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; - u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + u64 id = 0; + + if (sb->s_bdev) + id = huge_encode_dev(sb->s_bdev->bd_dev); + else if (sb->s_dev) + id = huge_encode_dev(sb->s_dev); buf->f_type = CRAMFS_MAGIC; buf->f_bsize = PAGE_SIZE; @@ -573,10 +689,22 @@ static const struct super_operations cramfs_ops = { .statfs = cramfs_statfs, }; -static struct dentry *cramfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static struct dentry *cramfs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) { - return mount_bdev(fs_type, flags, dev_name, data, cramfs_fill_super); + struct dentry *ret = ERR_PTR(-ENOPROTOOPT); + + if (IS_ENABLED(CONFIG_CRAMFS_MTD)) { + ret = mount_mtd(fs_type, flags, dev_name, data, + cramfs_mtd_fill_super); + if (!IS_ERR(ret)) + return ret; + } + if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV)) { + ret = mount_bdev(fs_type, flags, dev_name, data, + cramfs_blkdev_fill_super); + } + return ret; } static struct file_system_type cramfs_fs_type = { -- GitLab From fd4f6f2a78aeaebb7094c1bb9b30623d18a86e4c Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 12 Oct 2017 02:16:11 -0400 Subject: [PATCH 1157/2898] cramfs: implement uncompressed and arbitrary data block positioning Two new capabilities are introduced here: - The ability to store some blocks uncompressed. - The ability to locate blocks anywhere. Those capabilities can be used independently, but the combination opens the possibility for execute-in-place (XIP) of program text segments that must remain uncompressed, and in the MMU case, must have a specific alignment. It is even possible to still have the writable data segments from the same file compressed as they have to be copied into RAM anyway. This is achieved by giving special meanings to some unused block pointer bits while remaining compatible with legacy cramfs images. Signed-off-by: Nicolas Pitre Tested-by: Chris Brandt Signed-off-by: Al Viro --- fs/cramfs/README | 31 +++++++++++- fs/cramfs/inode.c | 90 +++++++++++++++++++++++++++------- include/uapi/linux/cramfs_fs.h | 26 +++++++++- 3 files changed, 126 insertions(+), 21 deletions(-) diff --git a/fs/cramfs/README b/fs/cramfs/README index 9d4e7ea311f4..d71b27e0ff15 100644 --- a/fs/cramfs/README +++ b/fs/cramfs/README @@ -49,17 +49,46 @@ same as the start of the (i+1)'th if there is one). The first immediately follows the last for the file. s are each 32 bits long. +When the CRAMFS_FLAG_EXT_BLOCK_POINTERS capability bit is set, each +'s top bits may contain special flags as follows: + +CRAMFS_BLK_FLAG_UNCOMPRESSED (bit 31): + The block data is not compressed and should be copied verbatim. + +CRAMFS_BLK_FLAG_DIRECT_PTR (bit 30): + The stores the actual block start offset and not + its end, shifted right by 2 bits. The block must therefore be + aligned to a 4-byte boundary. The block size is either blksize + if CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified, otherwise + the compressed data length is included in the first 2 bytes of + the block data. This is used to allow discontiguous data layout + and specific data block alignments e.g. for XIP applications. + + The order of 's is a depth-first descent of the directory tree, i.e. the same order as `find -size +0 \( -type f -o -type l \) -print'. : The i'th is the output of zlib's compress function -applied to the i'th blksize-sized chunk of the input data. +applied to the i'th blksize-sized chunk of the input data if the +corresponding CRAMFS_BLK_FLAG_UNCOMPRESSED bit is not set, +otherwise it is the input data directly. (For the last of the file, the input may of course be smaller.) Each may be a different size. (See above.) + s are merely byte-aligned, not generally u32-aligned. +When CRAMFS_BLK_FLAG_DIRECT_PTR is specified then the corresponding + may be located anywhere and not necessarily contiguous with +the previous/next blocks. In that case it is minimally u32-aligned. +If CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified then the size is always +blksize except for the last block which is limited by the file length. +If CRAMFS_BLK_FLAG_DIRECT_PTR is set and CRAMFS_BLK_FLAG_UNCOMPRESSED +is not set then the first 2 bytes of the block contains the size of the +remaining block data as this cannot be determined from the placement of +logically adjacent blocks. + Holes ----- diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index bcdccb7a820b..19045453a8f3 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -618,34 +618,86 @@ static int cramfs_readpage(struct file *file, struct page *page) if (page->index < maxblock) { struct super_block *sb = inode->i_sb; - u32 blkptr_offset = OFFSET(inode) + page->index*4; - u32 start_offset, compr_len; + u32 blkptr_offset = OFFSET(inode) + page->index * 4; + u32 block_ptr, block_start, block_len; + bool uncompressed, direct; - start_offset = OFFSET(inode) + maxblock*4; mutex_lock(&read_mutex); - if (page->index) - start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, - 4); - compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - - start_offset); - mutex_unlock(&read_mutex); + block_ptr = *(u32 *) cramfs_read(sb, blkptr_offset, 4); + uncompressed = (block_ptr & CRAMFS_BLK_FLAG_UNCOMPRESSED); + direct = (block_ptr & CRAMFS_BLK_FLAG_DIRECT_PTR); + block_ptr &= ~CRAMFS_BLK_FLAGS; + + if (direct) { + /* + * The block pointer is an absolute start pointer, + * shifted by 2 bits. The size is included in the + * first 2 bytes of the data block when compressed, + * or PAGE_SIZE otherwise. + */ + block_start = block_ptr << CRAMFS_BLK_DIRECT_PTR_SHIFT; + if (uncompressed) { + block_len = PAGE_SIZE; + /* if last block: cap to file length */ + if (page->index == maxblock - 1) + block_len = + offset_in_page(inode->i_size); + } else { + block_len = *(u16 *) + cramfs_read(sb, block_start, 2); + block_start += 2; + } + } else { + /* + * The block pointer indicates one past the end of + * the current block (start of next block). If this + * is the first block then it starts where the block + * pointer table ends, otherwise its start comes + * from the previous block's pointer. + */ + block_start = OFFSET(inode) + maxblock * 4; + if (page->index) + block_start = *(u32 *) + cramfs_read(sb, blkptr_offset - 4, 4); + /* Beware... previous ptr might be a direct ptr */ + if (unlikely(block_start & CRAMFS_BLK_FLAG_DIRECT_PTR)) { + /* See comments on earlier code. */ + u32 prev_start = block_start; + block_start = prev_start & ~CRAMFS_BLK_FLAGS; + block_start <<= CRAMFS_BLK_DIRECT_PTR_SHIFT; + if (prev_start & CRAMFS_BLK_FLAG_UNCOMPRESSED) { + block_start += PAGE_SIZE; + } else { + block_len = *(u16 *) + cramfs_read(sb, block_start, 2); + block_start += 2 + block_len; + } + } + block_start &= ~CRAMFS_BLK_FLAGS; + block_len = block_ptr - block_start; + } - if (compr_len == 0) + if (block_len == 0) ; /* hole */ - else if (unlikely(compr_len > (PAGE_SIZE << 1))) { - pr_err("bad compressed blocksize %u\n", - compr_len); + else if (unlikely(block_len > 2*PAGE_SIZE || + (uncompressed && block_len > PAGE_SIZE))) { + mutex_unlock(&read_mutex); + pr_err("bad data blocksize %u\n", block_len); goto err; + } else if (uncompressed) { + memcpy(pgdata, + cramfs_read(sb, block_start, block_len), + block_len); + bytes_filled = block_len; } else { - mutex_lock(&read_mutex); bytes_filled = cramfs_uncompress_block(pgdata, PAGE_SIZE, - cramfs_read(sb, start_offset, compr_len), - compr_len); - mutex_unlock(&read_mutex); - if (unlikely(bytes_filled < 0)) - goto err; + cramfs_read(sb, block_start, block_len), + block_len); } + mutex_unlock(&read_mutex); + if (unlikely(bytes_filled < 0)) + goto err; } memset(pgdata + bytes_filled, 0, PAGE_SIZE - bytes_filled); diff --git a/include/uapi/linux/cramfs_fs.h b/include/uapi/linux/cramfs_fs.h index e4611a9b9243..ce2c885133e2 100644 --- a/include/uapi/linux/cramfs_fs.h +++ b/include/uapi/linux/cramfs_fs.h @@ -73,6 +73,7 @@ struct cramfs_super { #define CRAMFS_FLAG_HOLES 0x00000100 /* support for holes */ #define CRAMFS_FLAG_WRONG_SIGNATURE 0x00000200 /* reserved */ #define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET 0x00000400 /* shifted root fs */ +#define CRAMFS_FLAG_EXT_BLOCK_POINTERS 0x00000800 /* block pointer extensions */ /* * Valid values in super.flags. Currently we refuse to mount @@ -82,7 +83,30 @@ struct cramfs_super { #define CRAMFS_SUPPORTED_FLAGS ( 0x000000ff \ | CRAMFS_FLAG_HOLES \ | CRAMFS_FLAG_WRONG_SIGNATURE \ - | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) + | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET \ + | CRAMFS_FLAG_EXT_BLOCK_POINTERS ) +/* + * Block pointer flags + * + * The maximum block offset that needs to be represented is roughly: + * + * (1 << CRAMFS_OFFSET_WIDTH) * 4 + + * (1 << CRAMFS_SIZE_WIDTH) / PAGE_SIZE * (4 + PAGE_SIZE) + * = 0x11004000 + * + * That leaves room for 3 flag bits in the block pointer table. + */ +#define CRAMFS_BLK_FLAG_UNCOMPRESSED (1 << 31) +#define CRAMFS_BLK_FLAG_DIRECT_PTR (1 << 30) + +#define CRAMFS_BLK_FLAGS ( CRAMFS_BLK_FLAG_UNCOMPRESSED \ + | CRAMFS_BLK_FLAG_DIRECT_PTR ) + +/* + * Direct blocks are at least 4-byte aligned. + * Pointers to direct blocks are shifted down by 2 bits. + */ +#define CRAMFS_BLK_DIRECT_PTR_SHIFT 2 #endif /* _UAPI__CRAMFS_H */ -- GitLab From eddcd97659e31f59fc99c6c3ca3dcce403585f7e Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 12 Oct 2017 02:16:12 -0400 Subject: [PATCH 1158/2898] cramfs: add mmap support When cramfs in physical memory is used then we have the opportunity to map files directly from ROM, directly into user space, saving on RAM usage. This gives us Execute-In-Place (XIP) support. For a file to be mmap()-able, the map area has to correspond to a range of uncompressed and contiguous blocks, and in the MMU case it also has to be page aligned. A version of mkcramfs with appropriate support is necessary to create such a filesystem image. In the MMU case it may happen for a vma structure to extend beyond the actual file size. This is notably the case in binfmt_elf.c:elf_map(). Or the file's last block is shared with other files and cannot be mapped as is. Rather than refusing to mmap it, we do a "mixed" map and let the regular fault handler populate the unmapped area with RAM-backed pages. In practice the unmapped area is seldom accessed so page faults might never occur before this area is discarded. In the non-MMU case it is the get_unmapped_area method that is responsible for providing the address where the actual data can be found. No mapping is necessary of course. Signed-off-by: Nicolas Pitre Tested-by: Chris Brandt Signed-off-by: Al Viro --- fs/cramfs/inode.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 19045453a8f3..9a2ab419ba62 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -15,7 +15,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -51,6 +54,7 @@ static inline struct cramfs_sb_info *CRAMFS_SB(struct super_block *sb) static const struct super_operations cramfs_ops; static const struct inode_operations cramfs_dir_inode_operations; static const struct file_operations cramfs_directory_operations; +static const struct file_operations cramfs_physmem_fops; static const struct address_space_operations cramfs_aops; static DEFINE_MUTEX(read_mutex); @@ -98,6 +102,10 @@ static struct inode *get_cramfs_inode(struct super_block *sb, case S_IFREG: inode->i_fop = &generic_ro_fops; inode->i_data.a_ops = &cramfs_aops; + if (IS_ENABLED(CONFIG_CRAMFS_MTD) && + CRAMFS_SB(sb)->flags & CRAMFS_FLAG_EXT_BLOCK_POINTERS && + CRAMFS_SB(sb)->linear_phys_addr) + inode->i_fop = &cramfs_physmem_fops; break; case S_IFDIR: inode->i_op = &cramfs_dir_inode_operations; @@ -279,6 +287,207 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, return NULL; } +/* + * For a mapping to be possible, we need a range of uncompressed and + * contiguous blocks. Return the offset for the first block and number of + * valid blocks for which that is true, or zero otherwise. + */ +static u32 cramfs_get_block_range(struct inode *inode, u32 pgoff, u32 *pages) +{ + struct cramfs_sb_info *sbi = CRAMFS_SB(inode->i_sb); + int i; + u32 *blockptrs, first_block_addr; + + /* + * We can dereference memory directly here as this code may be + * reached only when there is a direct filesystem image mapping + * available in memory. + */ + blockptrs = (u32 *)(sbi->linear_virt_addr + OFFSET(inode) + pgoff * 4); + first_block_addr = blockptrs[0] & ~CRAMFS_BLK_FLAGS; + i = 0; + do { + u32 block_off = i * (PAGE_SIZE >> CRAMFS_BLK_DIRECT_PTR_SHIFT); + u32 expect = (first_block_addr + block_off) | + CRAMFS_BLK_FLAG_DIRECT_PTR | + CRAMFS_BLK_FLAG_UNCOMPRESSED; + if (blockptrs[i] != expect) { + pr_debug("range: block %d/%d got %#x expects %#x\n", + pgoff+i, pgoff + *pages - 1, + blockptrs[i], expect); + if (i == 0) + return 0; + break; + } + } while (++i < *pages); + + *pages = i; + return first_block_addr << CRAMFS_BLK_DIRECT_PTR_SHIFT; +} + +#ifdef CONFIG_MMU + +/* + * Return true if the last page of a file in the filesystem image contains + * some other data that doesn't belong to that file. It is assumed that the + * last block is CRAMFS_BLK_FLAG_DIRECT_PTR | CRAMFS_BLK_FLAG_UNCOMPRESSED + * (verified by cramfs_get_block_range() and directly accessible in memory. + */ +static bool cramfs_last_page_is_shared(struct inode *inode) +{ + struct cramfs_sb_info *sbi = CRAMFS_SB(inode->i_sb); + u32 partial, last_page, blockaddr, *blockptrs; + char *tail_data; + + partial = offset_in_page(inode->i_size); + if (!partial) + return false; + last_page = inode->i_size >> PAGE_SHIFT; + blockptrs = (u32 *)(sbi->linear_virt_addr + OFFSET(inode)); + blockaddr = blockptrs[last_page] & ~CRAMFS_BLK_FLAGS; + blockaddr <<= CRAMFS_BLK_DIRECT_PTR_SHIFT; + tail_data = sbi->linear_virt_addr + blockaddr + partial; + return memchr_inv(tail_data, 0, PAGE_SIZE - partial) ? true : false; +} + +static int cramfs_physmem_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct inode *inode = file_inode(file); + struct cramfs_sb_info *sbi = CRAMFS_SB(inode->i_sb); + unsigned int pages, max_pages, offset; + unsigned long address, pgoff = vma->vm_pgoff; + char *bailout_reason; + int ret; + + ret = generic_file_readonly_mmap(file, vma); + if (ret) + return ret; + + /* + * Now try to pre-populate ptes for this vma with a direct + * mapping avoiding memory allocation when possible. + */ + + /* Could COW work here? */ + bailout_reason = "vma is writable"; + if (vma->vm_flags & VM_WRITE) + goto bailout; + + max_pages = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT; + bailout_reason = "beyond file limit"; + if (pgoff >= max_pages) + goto bailout; + pages = min(vma_pages(vma), max_pages - pgoff); + + offset = cramfs_get_block_range(inode, pgoff, &pages); + bailout_reason = "unsuitable block layout"; + if (!offset) + goto bailout; + address = sbi->linear_phys_addr + offset; + bailout_reason = "data is not page aligned"; + if (!PAGE_ALIGNED(address)) + goto bailout; + + /* Don't map the last page if it contains some other data */ + if (pgoff + pages == max_pages && cramfs_last_page_is_shared(inode)) { + pr_debug("mmap: %s: last page is shared\n", + file_dentry(file)->d_name.name); + pages--; + } + + if (!pages) { + bailout_reason = "no suitable block remaining"; + goto bailout; + } + + if (pages == vma_pages(vma)) { + /* + * The entire vma is mappable. remap_pfn_range() will + * make it distinguishable from a non-direct mapping + * in /proc//maps by substituting the file offset + * with the actual physical address. + */ + ret = remap_pfn_range(vma, vma->vm_start, address >> PAGE_SHIFT, + pages * PAGE_SIZE, vma->vm_page_prot); + } else { + /* + * Let's create a mixed map if we can't map it all. + * The normal paging machinery will take care of the + * unpopulated ptes via cramfs_readpage(). + */ + int i; + vma->vm_flags |= VM_MIXEDMAP; + for (i = 0; i < pages && !ret; i++) { + unsigned long off = i * PAGE_SIZE; + pfn_t pfn = phys_to_pfn_t(address + off, PFN_DEV); + ret = vm_insert_mixed(vma, vma->vm_start + off, pfn); + } + } + + if (!ret) + pr_debug("mapped %s[%lu] at 0x%08lx (%u/%lu pages) " + "to vma 0x%08lx, page_prot 0x%llx\n", + file_dentry(file)->d_name.name, pgoff, + address, pages, vma_pages(vma), vma->vm_start, + (unsigned long long)pgprot_val(vma->vm_page_prot)); + return ret; + +bailout: + pr_debug("%s[%lu]: direct mmap impossible: %s\n", + file_dentry(file)->d_name.name, pgoff, bailout_reason); + /* Didn't manage any direct map, but normal paging is still possible */ + return 0; +} + +#else /* CONFIG_MMU */ + +static int cramfs_physmem_mmap(struct file *file, struct vm_area_struct *vma) +{ + return vma->vm_flags & (VM_SHARED | VM_MAYSHARE) ? 0 : -ENOSYS; +} + +static unsigned long cramfs_physmem_get_unmapped_area(struct file *file, + unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags) +{ + struct inode *inode = file_inode(file); + struct super_block *sb = inode->i_sb; + struct cramfs_sb_info *sbi = CRAMFS_SB(sb); + unsigned int pages, block_pages, max_pages, offset; + + pages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; + max_pages = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (pgoff >= max_pages || pages > max_pages - pgoff) + return -EINVAL; + block_pages = pages; + offset = cramfs_get_block_range(inode, pgoff, &block_pages); + if (!offset || block_pages != pages) + return -ENOSYS; + addr = sbi->linear_phys_addr + offset; + pr_debug("get_unmapped for %s ofs %#lx siz %lu at 0x%08lx\n", + file_dentry(file)->d_name.name, pgoff*PAGE_SIZE, len, addr); + return addr; +} + +static unsigned int cramfs_physmem_mmap_capabilities(struct file *file) +{ + return NOMMU_MAP_COPY | NOMMU_MAP_DIRECT | + NOMMU_MAP_READ | NOMMU_MAP_EXEC; +} + +#endif /* CONFIG_MMU */ + +static const struct file_operations cramfs_physmem_fops = { + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, + .splice_read = generic_file_splice_read, + .mmap = cramfs_physmem_mmap, +#ifndef CONFIG_MMU + .get_unmapped_area = cramfs_physmem_get_unmapped_area, + .mmap_capabilities = cramfs_physmem_mmap_capabilities, +#endif +}; + static void cramfs_kill_sb(struct super_block *sb) { struct cramfs_sb_info *sbi = CRAMFS_SB(sb); -- GitLab From 8d59598c35dc1071e6c36f86c9a95f26dd08b4e5 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 12 Oct 2017 02:16:13 -0400 Subject: [PATCH 1159/2898] cramfs: rehabilitate it Update documentation, pointer to latest tools, appoint myself as maintainer. Given it's been unloved for so long, I don't expect anyone will protest. Signed-off-by: Nicolas Pitre Tested-by: Chris Brandt Signed-off-by: Al Viro --- Documentation/filesystems/cramfs.txt | 42 ++++++++++++++++++++++++++++ MAINTAINERS | 4 +-- fs/cramfs/Kconfig | 9 ++++-- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/Documentation/filesystems/cramfs.txt b/Documentation/filesystems/cramfs.txt index 4006298f6707..8e19a53d648b 100644 --- a/Documentation/filesystems/cramfs.txt +++ b/Documentation/filesystems/cramfs.txt @@ -45,6 +45,48 @@ you can just change the #define in mkcramfs.c, so long as you don't mind the filesystem becoming unreadable to future kernels. +Memory Mapped cramfs image +-------------------------- + +The CRAMFS_MTD Kconfig option adds support for loading data directly from +a physical linear memory range (usually non volatile memory like Flash) +instead of going through the block device layer. This saves some memory +since no intermediate buffering is necessary to hold the data before +decompressing. + +And when data blocks are kept uncompressed and properly aligned, they will +automatically be mapped directly into user space whenever possible providing +eXecute-In-Place (XIP) from ROM of read-only segments. Data segments mapped +read-write (hence they have to be copied to RAM) may still be compressed in +the cramfs image in the same file along with non compressed read-only +segments. Both MMU and no-MMU systems are supported. This is particularly +handy for tiny embedded systems with very tight memory constraints. + +The location of the cramfs image in memory is system dependent. You must +know the proper physical address where the cramfs image is located and +configure an MTD device for it. Also, that MTD device must be supported +by a map driver that implements the "point" method. Examples of such +MTD drivers are cfi_cmdset_0001 (Intel/Sharp CFI flash) or physmap +(Flash device in physical memory map). MTD partitions based on such devices +are fine too. Then that device should be specified with the "mtd:" prefix +as the mount device argument. For example, to mount the MTD device named +"fs_partition" on the /mnt directory: + +$ mount -t cramfs mtd:fs_partition /mnt + +To boot a kernel with this as root filesystem, suffice to specify +something like "root=mtd:fs_partition" on the kernel command line. + + +Tools +----- + +A version of mkcramfs that can take advantage of the latest capabilities +described above can be found here: + +https://github.com/npitre/cramfs-tools + + For /usr/share/magic -------------------- diff --git a/MAINTAINERS b/MAINTAINERS index 2d3d750b19c0..3438aaa20b73 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3676,8 +3676,8 @@ F: drivers/cpuidle/* F: include/linux/cpuidle.h CRAMFS FILESYSTEM -W: http://sourceforge.net/projects/cramfs/ -S: Orphan / Obsolete +M: Nicolas Pitre +S: Maintained F: Documentation/filesystems/cramfs.txt F: fs/cramfs/ diff --git a/fs/cramfs/Kconfig b/fs/cramfs/Kconfig index ef86b06bc064..f937082f3244 100644 --- a/fs/cramfs/Kconfig +++ b/fs/cramfs/Kconfig @@ -1,5 +1,5 @@ config CRAMFS - tristate "Compressed ROM file system support (cramfs) (OBSOLETE)" + tristate "Compressed ROM file system support (cramfs)" select ZLIB_INFLATE help Saying Y here includes support for CramFs (Compressed ROM File @@ -15,8 +15,11 @@ config CRAMFS cramfs. Note that the root file system (the one containing the directory /) cannot be compiled as a module. - This filesystem is obsoleted by SquashFS, which is much better - in terms of performance and features. + This filesystem is limited in capabilities and performance on + purpose to remain small and low on RAM usage. It is most suitable + for small embedded systems. If you have ample RAM to spare, you may + consider a more capable compressed filesystem such as SquashFS + which is much better in terms of performance and features. If unsure, say N. -- GitLab From 21bffe57f85c24fbb8d54aea4e46d2eac77242f6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Oct 2017 13:04:28 +0200 Subject: [PATCH 1160/2898] clk: renesas: r8a7795: Correct parent clock of INTC-AP According to the R-Car Gen3 Hardware Manual Errata for Rev 0.55 of September 8, 2017, the parent clock of the INTC-AP module clock on R-Car H3 ES2.0 is S0D3. This change has no functional impact. Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 762b2f8824f1..b1d9f48eae9e 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -149,7 +149,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1), DEF_MOD("rwdt", 402, R8A7795_CLK_R), DEF_MOD("intc-ex", 407, R8A7795_CLK_CP), - DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), + DEF_MOD("intc-ap", 408, R8A7795_CLK_S0D3), DEF_MOD("audmac1", 501, R8A7795_CLK_S0D3), DEF_MOD("audmac0", 502, R8A7795_CLK_S0D3), DEF_MOD("drif7", 508, R8A7795_CLK_S3D2), @@ -348,6 +348,7 @@ static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = { { MOD_CLK_ID(217), R8A7795_CLK_S3D1 }, /* SYS-DMAC2 */ { MOD_CLK_ID(218), R8A7795_CLK_S3D1 }, /* SYS-DMAC1 */ { MOD_CLK_ID(219), R8A7795_CLK_S3D1 }, /* SYS-DMAC0 */ + { MOD_CLK_ID(408), R8A7795_CLK_S3D1 }, /* INTC-AP */ { MOD_CLK_ID(501), R8A7795_CLK_S3D1 }, /* AUDMAC1 */ { MOD_CLK_ID(502), R8A7795_CLK_S3D1 }, /* AUDMAC0 */ { MOD_CLK_ID(523), R8A7795_CLK_S3D4 }, /* PWM */ -- GitLab From 6e7ddf89d67c2b0cdd7a392bece9411789dda49b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Oct 2017 13:07:45 +0200 Subject: [PATCH 1161/2898] clk: renesas: r8a7796: Correct parent clock of INTC-AP According to the R-Car Gen3 Hardware Manual Errata for Rev 0.55 of September 8, 2017, the parent clock of the INTC-AP module clock on R-Car M3-W is S0D3. This change has no functional impact. Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index e5e7fb212288..b3767472088a 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -143,7 +143,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("usb-dmac1", 331, R8A7796_CLK_S3D1), DEF_MOD("rwdt", 402, R8A7796_CLK_R), DEF_MOD("intc-ex", 407, R8A7796_CLK_CP), - DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1), + DEF_MOD("intc-ap", 408, R8A7796_CLK_S0D3), DEF_MOD("audmac1", 501, R8A7796_CLK_S0D3), DEF_MOD("audmac0", 502, R8A7796_CLK_S0D3), DEF_MOD("drif7", 508, R8A7796_CLK_S3D2), -- GitLab From 0022e4a2ef8f20257b21b8fa27c0cb683485270b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Oct 2017 13:08:11 +0200 Subject: [PATCH 1162/2898] clk: renesas: r8a77995: Correct parent clock of INTC-AP According to the R-Car Gen3 Hardware Manual Errata for Rev 0.55 of September 8, 2017, the parent clock of the INTC-AP module clock on R-Car D3 is S1D2. This change has no functional impact. Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a77995-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index e594cf8ee63b..ea4cafbe6e85 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -127,7 +127,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { DEF_MOD("usb-dmac1", 331, R8A77995_CLK_S3D1), DEF_MOD("rwdt", 402, R8A77995_CLK_R), DEF_MOD("intc-ex", 407, R8A77995_CLK_CP), - DEF_MOD("intc-ap", 408, R8A77995_CLK_S3D1), + DEF_MOD("intc-ap", 408, R8A77995_CLK_S1D2), DEF_MOD("audmac0", 502, R8A77995_CLK_S3D1), DEF_MOD("hscif3", 517, R8A77995_CLK_S3D1C), DEF_MOD("hscif0", 520, R8A77995_CLK_S3D1C), -- GitLab From 75920aac275a930b4259b46e555d5b90f713e084 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 11 Oct 2017 11:25:11 +0200 Subject: [PATCH 1163/2898] clk: samsung: Instantiate Exynos4412 ISP clocks only when available Some registers for the Exynos 4412 ISP (Camera subsystem) clocks are located in the ISP power domain. Instantiate those clocks only when provided clock registers resource covers those registers. This is a preparation for adding a separate clock driver for ISP clocks, which will be integrated with power domain using runtime PM feature. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index e40b77583c47..bdd68247e054 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -822,6 +822,12 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = { DIV(0, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4), DIV(0, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8), DIV(0, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4), + DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), + DIV(CLK_DIV_C2C, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3), + DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3), +}; + +static struct samsung_div_clock exynos4x12_isp_div_clks[] = { DIV_F(CLK_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3, CLK_GET_RATE_NOCACHE, 0), DIV_F(CLK_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3, @@ -831,9 +837,6 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = { 4, 3, CLK_GET_RATE_NOCACHE, 0), DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3, CLK_GET_RATE_NOCACHE, 0), - DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), - DIV(CLK_DIV_C2C, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3), - DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3), }; /* list of gate clocks supported in all exynos4 soc's */ @@ -1132,6 +1135,13 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = { 0, 0), GATE(CLK_I2S0, "i2s0", "aclk100", E4X12_GATE_IP_MAUDIO, 3, 0, 0), + GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), + GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0), + GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, + 0), +}; + +static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = { GATE(CLK_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0, CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), GATE(CLK_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1, @@ -1184,10 +1194,6 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = { CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0), - GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0), - GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0), - GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, - 0), }; static const struct samsung_clock_alias exynos4_aliases[] __initconst = { @@ -1522,6 +1528,8 @@ static void __init exynos4_clk_init(struct device_node *np, e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d), CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); } else { + struct resource res; + samsung_clk_register_mux(ctx, exynos4x12_mux_clks, ARRAY_SIZE(exynos4x12_mux_clks)); samsung_clk_register_div(ctx, exynos4x12_div_clks, @@ -1533,6 +1541,15 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_fixed_factor(ctx, exynos4x12_fixed_factor_clks, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); + + of_address_to_resource(np, 0, &res); + if (resource_size(&res) > 0x18000) { + samsung_clk_register_div(ctx, exynos4x12_isp_div_clks, + ARRAY_SIZE(exynos4x12_isp_div_clks)); + samsung_clk_register_gate(ctx, exynos4x12_isp_gate_clks, + ARRAY_SIZE(exynos4x12_isp_gate_clks)); + } + if (of_machine_is_compatible("samsung,exynos4412")) { exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, -- GitLab From 8ca8ac1024841781f544427b7ca5684e4c5637a9 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 11 Oct 2017 11:25:12 +0200 Subject: [PATCH 1164/2898] clk: samsung: Add dt bindings for Exynos4412 ISP clock controller Some registers for the Exynos 4412 ISP (Camera subsystem) clocks are located in the ISP power domain. Because those registers are also located in a different memory region than the main clock controller, support for them can be provided by a separate clock controller. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Acked-by: Rob Herring Signed-off-by: Sylwester Nawrocki --- .../bindings/clock/exynos4-clock.txt | 43 +++++++++++++++++++ include/dt-bindings/clock/exynos4.h | 35 +++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt index f5a5b19ed3b2..bc61c952cb0b 100644 --- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt @@ -41,3 +41,46 @@ Example 2: UART controller node that consumes the clock generated by the clock clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>; clock-names = "uart", "clk_uart_baud0"; }; + +Exynos4412 SoC contains some additional clocks for FIMC-ISP (Camera ISP) +subsystem. Registers for those clocks are located in the ISP power domain. +Because those registers are also located in a different memory region than +the main clock controller, a separate clock controller has to be defined for +handling them. + +Required Properties: + +- compatible: should be "samsung,exynos4412-isp-clock". + +- reg: physical base address of the ISP clock controller and length of memory + mapped region. + +- #clock-cells: should be 1. + +- clocks: list of the clock controller input clock identifiers, + from common clock bindings, should point to CLK_ACLK200 and + CLK_ACLK400_MCUISP clocks from the main clock controller. + +- clock-names: list of the clock controller input clock names, + as described in clock-bindings.txt, should be "aclk200" and + "aclk400_mcuisp". + +- power-domains: a phandle to ISP power domain node as described by + generic PM domain bindings. + +Example 3: The clock controllers bindings for Exynos4412 SoCs. + + clock: clock-controller@10030000 { + compatible = "samsung,exynos4412-clock"; + reg = <0x10030000 0x18000>; + #clock-cells = <1>; + }; + + isp_clock: clock-controller@10048000 { + compatible = "samsung,exynos4412-isp-clock"; + reg = <0x10048000 0x1000>; + #clock-cells = <1>; + power-domains = <&pd_isp>; + clocks = <&clock CLK_ACLK200>, <&clock CLK_ACLK400_MCUISP>; + clock-names = "aclk200", "aclk400_mcuisp"; + }; diff --git a/include/dt-bindings/clock/exynos4.h b/include/dt-bindings/clock/exynos4.h index c40111f36d5e..e9f9d400c322 100644 --- a/include/dt-bindings/clock/exynos4.h +++ b/include/dt-bindings/clock/exynos4.h @@ -272,4 +272,39 @@ /* must be greater than maximal clock id */ #define CLK_NR_CLKS 461 +/* Exynos4x12 ISP clocks */ +#define CLK_ISP_FIMC_ISP 1 +#define CLK_ISP_FIMC_DRC 2 +#define CLK_ISP_FIMC_FD 3 +#define CLK_ISP_FIMC_LITE0 4 +#define CLK_ISP_FIMC_LITE1 5 +#define CLK_ISP_MCUISP 6 +#define CLK_ISP_GICISP 7 +#define CLK_ISP_SMMU_ISP 8 +#define CLK_ISP_SMMU_DRC 9 +#define CLK_ISP_SMMU_FD 10 +#define CLK_ISP_SMMU_LITE0 11 +#define CLK_ISP_SMMU_LITE1 12 +#define CLK_ISP_PPMUISPMX 13 +#define CLK_ISP_PPMUISPX 14 +#define CLK_ISP_MCUCTL_ISP 15 +#define CLK_ISP_MPWM_ISP 16 +#define CLK_ISP_I2C0_ISP 17 +#define CLK_ISP_I2C1_ISP 18 +#define CLK_ISP_MTCADC_ISP 19 +#define CLK_ISP_PWM_ISP 20 +#define CLK_ISP_WDT_ISP 21 +#define CLK_ISP_UART_ISP 22 +#define CLK_ISP_ASYNCAXIM 23 +#define CLK_ISP_SMMU_ISPCX 24 +#define CLK_ISP_SPI0_ISP 25 +#define CLK_ISP_SPI1_ISP 26 + +#define CLK_ISP_DIV_ISP0 27 +#define CLK_ISP_DIV_ISP1 28 +#define CLK_ISP_DIV_MCUISP0 29 +#define CLK_ISP_DIV_MCUISP1 30 + +#define CLK_NR_ISP_CLKS 31 + #endif /* _DT_BINDINGS_CLOCK_EXYNOS_4_H */ -- GitLab From 7679eb20353dc74e47fbc97b2d77fd4f88a77c0f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 11 Oct 2017 11:25:13 +0200 Subject: [PATCH 1165/2898] clk: samsung: Add a separate driver for Exynos4412 ISP clocks Some registers for the Exynos 4412 ISP (Camera subsystem) clocks are located in the ISP power domain. Because those registers are also located in a different memory region than the main clock controller, support for them can be provided by a separate clock controller. This in turn allows to almost seamlessly make it aware of the power domain using recently introduced runtime PM support for clocks. Signed-off-by: Marek Szyprowski Acked-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-exynos4412-isp.c | 179 +++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 drivers/clk/samsung/clk-exynos4412-isp.c diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 7afc21dc374e..8a67a3bb6803 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o +obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4412-isp.o obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c new file mode 100644 index 000000000000..d5f1ccb36300 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos4412-isp.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Author: Marek Szyprowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Common Clock Framework support for Exynos4412 ISP module. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +/* Exynos4x12 specific registers, which belong to ISP power domain */ +#define E4X12_DIV_ISP0 0x0300 +#define E4X12_DIV_ISP1 0x0304 +#define E4X12_GATE_ISP0 0x0800 +#define E4X12_GATE_ISP1 0x0804 + +/* + * Support for CMU save/restore across system suspends + */ +static struct samsung_clk_reg_dump *exynos4x12_save_isp; + +static const unsigned long exynos4x12_clk_isp_save[] __initconst = { + E4X12_DIV_ISP0, + E4X12_DIV_ISP1, + E4X12_GATE_ISP0, + E4X12_GATE_ISP1, +}; + +PNAME(mout_user_aclk400_mcuisp_p4x12) = { "fin_pll", "div_aclk400_mcuisp", }; + +static struct samsung_div_clock exynos4x12_isp_div_clks[] = { + DIV(CLK_ISP_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3), + DIV(CLK_ISP_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3), + DIV(CLK_ISP_DIV_MCUISP0, "div_mcuisp0", "aclk400_mcuisp", + E4X12_DIV_ISP1, 4, 3), + DIV(CLK_ISP_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", + E4X12_DIV_ISP1, 8, 3), + DIV(0, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3), +}; + +static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = { + GATE(CLK_ISP_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0, 0, 0), + GATE(CLK_ISP_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1, 0, 0), + GATE(CLK_ISP_FIMC_FD, "fd", "aclk200", E4X12_GATE_ISP0, 2, 0, 0), + GATE(CLK_ISP_FIMC_LITE0, "lite0", "aclk200", E4X12_GATE_ISP0, 3, 0, 0), + GATE(CLK_ISP_FIMC_LITE1, "lite1", "aclk200", E4X12_GATE_ISP0, 4, 0, 0), + GATE(CLK_ISP_MCUISP, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5, 0, 0), + GATE(CLK_ISP_GICISP, "gicisp", "aclk200", E4X12_GATE_ISP0, 7, 0, 0), + GATE(CLK_ISP_SMMU_ISP, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8, 0, 0), + GATE(CLK_ISP_SMMU_DRC, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9, 0, 0), + GATE(CLK_ISP_SMMU_FD, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10, 0, 0), + GATE(CLK_ISP_SMMU_LITE0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11, + 0, 0), + GATE(CLK_ISP_SMMU_LITE1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12, + 0, 0), + GATE(CLK_ISP_PPMUISPMX, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20, + 0, 0), + GATE(CLK_ISP_PPMUISPX, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21, + 0, 0), + GATE(CLK_ISP_MCUCTL_ISP, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23, + 0, 0), + GATE(CLK_ISP_MPWM_ISP, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24, + 0, 0), + GATE(CLK_ISP_I2C0_ISP, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25, + 0, 0), + GATE(CLK_ISP_I2C1_ISP, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26, + 0, 0), + GATE(CLK_ISP_MTCADC_ISP, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27, + 0, 0), + GATE(CLK_ISP_PWM_ISP, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28, 0, 0), + GATE(CLK_ISP_WDT_ISP, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30, 0, 0), + GATE(CLK_ISP_UART_ISP, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31, + 0, 0), + GATE(CLK_ISP_ASYNCAXIM, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0, + 0, 0), + GATE(CLK_ISP_SMMU_ISPCX, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4, + 0, 0), + GATE(CLK_ISP_SPI0_ISP, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12, + 0, 0), + GATE(CLK_ISP_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, + 0, 0), +}; + +static int __maybe_unused exynos4x12_isp_clk_suspend(struct device *dev) +{ + struct samsung_clk_provider *ctx = dev_get_drvdata(dev); + + samsung_clk_save(ctx->reg_base, exynos4x12_save_isp, + ARRAY_SIZE(exynos4x12_clk_isp_save)); + return 0; +} + +static int __maybe_unused exynos4x12_isp_clk_resume(struct device *dev) +{ + struct samsung_clk_provider *ctx = dev_get_drvdata(dev); + + samsung_clk_restore(ctx->reg_base, exynos4x12_save_isp, + ARRAY_SIZE(exynos4x12_clk_isp_save)); + return 0; +} + +static int __init exynos4x12_isp_clk_probe(struct platform_device *pdev) +{ + struct samsung_clk_provider *ctx; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct resource *res; + void __iomem *reg_base; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(reg_base)) { + dev_err(dev, "failed to map registers\n"); + return PTR_ERR(reg_base); + } + + exynos4x12_save_isp = samsung_clk_alloc_reg_dump(exynos4x12_clk_isp_save, + ARRAY_SIZE(exynos4x12_clk_isp_save)); + if (!exynos4x12_save_isp) + return -ENOMEM; + + ctx = samsung_clk_init(np, reg_base, CLK_NR_ISP_CLKS); + ctx->dev = dev; + + platform_set_drvdata(pdev, ctx); + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + samsung_clk_register_div(ctx, exynos4x12_isp_div_clks, + ARRAY_SIZE(exynos4x12_isp_div_clks)); + samsung_clk_register_gate(ctx, exynos4x12_isp_gate_clks, + ARRAY_SIZE(exynos4x12_isp_gate_clks)); + + samsung_clk_of_add_provider(np, ctx); + pm_runtime_put(dev); + + return 0; +} + +static const struct of_device_id exynos4x12_isp_clk_of_match[] = { + { .compatible = "samsung,exynos4412-isp-clock", }, + { }, +}; + +static const struct dev_pm_ops exynos4x12_isp_pm_ops = { + SET_RUNTIME_PM_OPS(exynos4x12_isp_clk_suspend, + exynos4x12_isp_clk_resume, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver exynos4x12_isp_clk_driver __refdata = { + .driver = { + .name = "exynos4x12-isp-clk", + .of_match_table = exynos4x12_isp_clk_of_match, + .suppress_bind_attrs = true, + .pm = &exynos4x12_isp_pm_ops, + }, + .probe = exynos4x12_isp_clk_probe, +}; + +static int __init exynos4x12_isp_clk_init(void) +{ + return platform_driver_register(&exynos4x12_isp_clk_driver); +} +core_initcall(exynos4x12_isp_clk_init); -- GitLab From 414864d765e1431d3ba79051404a1f6e423fc145 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 16 Oct 2017 11:51:54 +0200 Subject: [PATCH 1166/2898] mtd: nand: mxc: lower ECC failed message priority to debug level Having bad ECC is a normal case for NAND, do not spam log with the message. Users like UBI will print a message anyway which is more useful since it contains the PEB number that has bad ECC. Signed-off-by: Sascha Hauer Reviewed-by: Fabio Estevam Signed-off-by: Boris Brezillon --- drivers/mtd/nand/mxc_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index bacdd04e765b..04d31aff43c5 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -634,7 +634,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, do { err = ecc_stat & ecc_bit_mask; if (err > err_limit) { - printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); + dev_dbg(host->dev, "UnCorrectable RS-ECC Error\n"); return -EBADMSG; } else { ret += err; -- GitLab From 1f3df4dc088d927683b292118cd8b4eaaf1af573 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 16 Oct 2017 11:51:55 +0200 Subject: [PATCH 1167/2898] mtd: nand: mxc: use dev_dbg to print debug messages When a struct device * is around use dev_dbg instead of pr_debug to give the messages more context. Signed-off-by: Sascha Hauer Signed-off-by: Boris Brezillon --- drivers/mtd/nand/mxc_nand.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 04d31aff43c5..f3be0b2a8869 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -415,7 +415,7 @@ static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) * waits for completion. */ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) { - pr_debug("send_cmd(host, 0x%x, %d)\n", cmd, useirq); + dev_dbg(host->dev, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); writew(cmd, NFC_V1_V2_FLASH_CMD); writew(NFC_CMD, NFC_V1_V2_CONFIG2); @@ -431,7 +431,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) udelay(1); } if (max_retries < 0) - pr_debug("%s: RESET failed\n", __func__); + dev_dbg(host->dev, "%s: RESET failed\n", __func__); } else { /* Wait for operation to complete */ wait_op_done(host, useirq); @@ -454,7 +454,7 @@ static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast) * a NAND command. */ static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast) { - pr_debug("send_addr(host, 0x%x %d)\n", addr, islast); + dev_dbg(host->dev, "send_addr(host, 0x%x %d)\n", addr, islast); writew(addr, NFC_V1_V2_FLASH_ADDR); writew(NFC_ADDR, NFC_V1_V2_CONFIG2); @@ -607,7 +607,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, uint16_t ecc_status = get_ecc_status_v1(host); if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { - pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); + dev_dbg(host->dev, "HWECC uncorrectable 2-bit ECC error\n"); return -EBADMSG; } @@ -642,7 +642,7 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, ecc_stat >>= 4; } while (--no_subpages); - pr_debug("%d Symbol Correctable RS-ECC Error\n", ret); + dev_dbg(host->dev, "%d Symbol Correctable RS-ECC Error\n", ret); return ret; } @@ -673,7 +673,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) host->buf_start++; } - pr_debug("%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start); + dev_dbg(host->dev, "%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start); return ret; } @@ -1211,7 +1211,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_get_controller_data(nand_chip); - pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", + dev_dbg(host->dev, "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", command, column, page_addr); /* Reset command state information */ -- GitLab From 3c1818275cc65c6d53e0adfde0c989bfe89ab8d7 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Wed, 26 Jul 2017 10:14:55 -0400 Subject: [PATCH 1168/2898] NFS: Create NFS_ACCESS_* flags Passing the NFS v4 flags into the v3 code seems weird to me, even if they are defined to the same values. This patch adds in generic flags to help me feel better Signed-off-by: Anna Schumaker --- fs/nfs/dir.c | 16 ++++++++-------- include/linux/nfs_fs.h | 10 ++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 5ceaeb1f6fb6..80f397dc96bb 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2369,15 +2369,15 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) } EXPORT_SYMBOL_GPL(nfs_access_add_cache); -#define NFS_MAY_READ (NFS4_ACCESS_READ) -#define NFS_MAY_WRITE (NFS4_ACCESS_MODIFY | \ - NFS4_ACCESS_EXTEND | \ - NFS4_ACCESS_DELETE) -#define NFS_FILE_MAY_WRITE (NFS4_ACCESS_MODIFY | \ - NFS4_ACCESS_EXTEND) +#define NFS_MAY_READ (NFS_ACCESS_READ) +#define NFS_MAY_WRITE (NFS_ACCESS_MODIFY | \ + NFS_ACCESS_EXTEND | \ + NFS_ACCESS_DELETE) +#define NFS_FILE_MAY_WRITE (NFS_ACCESS_MODIFY | \ + NFS_ACCESS_EXTEND) #define NFS_DIR_MAY_WRITE NFS_MAY_WRITE -#define NFS_MAY_LOOKUP (NFS4_ACCESS_LOOKUP) -#define NFS_MAY_EXECUTE (NFS4_ACCESS_EXECUTE) +#define NFS_MAY_LOOKUP (NFS_ACCESS_LOOKUP) +#define NFS_MAY_EXECUTE (NFS_ACCESS_EXECUTE) static int nfs_access_calc_mask(u32 access_result, umode_t umode) { diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index a0282ceaa48b..453f491a5fda 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -183,6 +183,16 @@ struct nfs_inode { struct inode vfs_inode; }; +/* + * Access bit flags + */ +#define NFS_ACCESS_READ 0x0001 +#define NFS_ACCESS_LOOKUP 0x0002 +#define NFS_ACCESS_MODIFY 0x0004 +#define NFS_ACCESS_EXTEND 0x0008 +#define NFS_ACCESS_DELETE 0x0010 +#define NFS_ACCESS_EXECUTE 0x0020 + /* * Cache validity bit flags */ -- GitLab From 1750d929b08764dd293d5bdddaa9bc4d3f94d228 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Wed, 26 Jul 2017 12:00:21 -0400 Subject: [PATCH 1169/2898] NFS: Don't compare apples to elephants to determine access bits The NFS_ACCESS_* flags aren't a 1:1 mapping to the MAY_* flags, so checking for MAY_WHATEVER might have surprising results in nfs*_proc_access(). Let's simplify this check when determining which bits to ask for, and do it in a generic place instead of copying code for each NFS version. Signed-off-by: Anna Schumaker --- fs/nfs/dir.c | 11 ++++++++--- fs/nfs/nfs3proc.c | 17 +---------------- fs/nfs/nfs4proc.c | 19 +------------------ 3 files changed, 10 insertions(+), 37 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 80f397dc96bb..db482d4c15d5 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2425,9 +2425,14 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) if (!may_block) goto out; - /* Be clever: ask server to check for all possible rights */ - cache.mask = NFS_MAY_LOOKUP | NFS_MAY_EXECUTE - | NFS_MAY_WRITE | NFS_MAY_READ; + /* + * Determine which access bits we want to ask for... + */ + cache.mask = NFS_ACCESS_READ | NFS_ACCESS_MODIFY | NFS_ACCESS_EXTEND; + if (S_ISDIR(inode->i_mode)) + cache.mask |= NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP; + else + cache.mask |= NFS_ACCESS_EXECUTE; cache.cred = cred; status = NFS_PROTO(inode)->access(inode, &cache); if (status != 0) { diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index d1e87ec0df84..44bf961d5812 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -187,6 +187,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) { struct nfs3_accessargs arg = { .fh = NFS_FH(inode), + .access = entry->mask, }; struct nfs3_accessres res; struct rpc_message msg = { @@ -195,25 +196,9 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) .rpc_resp = &res, .rpc_cred = entry->cred, }; - int mode = entry->mask; int status = -ENOMEM; dprintk("NFS call access\n"); - - if (mode & MAY_READ) - arg.access |= NFS3_ACCESS_READ; - if (S_ISDIR(inode->i_mode)) { - if (mode & MAY_WRITE) - arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE; - if (mode & MAY_EXEC) - arg.access |= NFS3_ACCESS_LOOKUP; - } else { - if (mode & MAY_WRITE) - arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND; - if (mode & MAY_EXEC) - arg.access |= NFS3_ACCESS_EXECUTE; - } - res.fattr = nfs_alloc_fattr(); if (res.fattr == NULL) goto out; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f90090e8c959..7fd642303104 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3889,6 +3889,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry struct nfs4_accessargs args = { .fh = NFS_FH(inode), .bitmask = server->cache_consistency_bitmask, + .access = entry->mask, }; struct nfs4_accessres res = { .server = server, @@ -3899,26 +3900,8 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry .rpc_resp = &res, .rpc_cred = entry->cred, }; - int mode = entry->mask; int status = 0; - /* - * Determine which access bits we want to ask for... - */ - if (mode & MAY_READ) - args.access |= NFS4_ACCESS_READ; - if (S_ISDIR(inode->i_mode)) { - if (mode & MAY_WRITE) - args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE; - if (mode & MAY_EXEC) - args.access |= NFS4_ACCESS_LOOKUP; - } else { - if (mode & MAY_WRITE) - args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND; - if (mode & MAY_EXEC) - args.access |= NFS4_ACCESS_EXECUTE; - } - res.fattr = nfs_alloc_fattr(); if (res.fattr == NULL) return -ENOMEM; -- GitLab From b688741cb06695312f18b730653d6611e1bad28d Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 25 Aug 2017 17:34:41 +1000 Subject: [PATCH 1170/2898] NFS: revalidate "." etc correctly on "open". For correct close-to-open semantics, NFS must validate the change attribute of a directory (or file) on open. Since commit ecf3d1f1aa74 ("vfs: kill FS_REVAL_DOT by adding a d_weak_revalidate dentry op"), open() of "." or a path ending ".." is not revalidated reliably (except when that direct is a mount point). Prior to that commit, "." was revalidated using nfs_lookup_revalidate() which checks the LOOKUP_OPEN flag and forces revalidation if the flag is set. Since that commit, nfs_weak_revalidate() is used for NFSv3 (which ignores the flags) and nothing is used for NFSv4. This is fixed by using nfs_lookup_verify_inode() in nfs_weak_revalidate(). This does the revalidation exactly when needed. Also, add a definition of .d_weak_revalidate for NFSv4. The incorrect behavior is easily demonstrated by running "echo *" in some non-mountpoint NFS directory while watching network traffic. Without this patch, "echo *" sometimes doesn't produce any traffic. With the patch it always does. Fixes: ecf3d1f1aa74 ("vfs: kill FS_REVAL_DOT by adding a d_weak_revalidate dentry op") cc: stable@vger.kernel.org (3.9+) Signed-off-by: NeilBrown Signed-off-by: Anna Schumaker --- fs/nfs/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index db482d4c15d5..c583093a066b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1241,8 +1241,7 @@ static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) return 0; } - if (nfs_mapping_need_revalidate_inode(inode)) - error = __nfs_revalidate_inode(NFS_SERVER(inode), inode); + error = nfs_lookup_verify_inode(inode, flags); dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n", __func__, inode->i_ino, error ? "invalid" : "valid"); return !error; @@ -1393,6 +1392,7 @@ static int nfs4_lookup_revalidate(struct dentry *, unsigned int); const struct dentry_operations nfs4_dentry_operations = { .d_revalidate = nfs4_lookup_revalidate, + .d_weak_revalidate = nfs_weak_revalidate, .d_delete = nfs_dentry_delete, .d_iput = nfs_dentry_iput, .d_automount = nfs_d_automount, -- GitLab From 1fea73ac92f628538032ce746f7dd5d6f8dfcc32 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 25 Aug 2017 17:34:41 +1000 Subject: [PATCH 1171/2898] NFS: remove special-case revalidate in nfs_opendir() Commit f5a73672d181 ("NFS: allow close-to-open cache semantics to apply to root of NFS filesystem") added a call to __nfs_revalidate_inode() to nfs_opendir to as the lookup process wouldn't reliable do this. Subsequent commit a3fbbde70a0c ("VFS: we need to set LOOKUP_JUMPED on mountpoint crossing") make this unnecessary. So remove the unnecessary code. Signed-off-by: NeilBrown Signed-off-by: Anna Schumaker --- fs/nfs/dir.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c583093a066b..15104f719170 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -118,13 +118,6 @@ nfs_opendir(struct inode *inode, struct file *filp) goto out; } filp->private_data = ctx; - if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) { - /* This is a mountpoint, so d_revalidate will never - * have been called, so we need to refresh the - * inode (for close-open consistency) ourselves. - */ - __nfs_revalidate_inode(NFS_SERVER(inode), inode); - } out: put_rpccred(cred); return res; -- GitLab From 8f66b1a529047a972cb9602a919c53a95f3d7a2b Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 9 Oct 2017 12:03:26 -0400 Subject: [PATCH 1172/2898] xprtrdma: Don't defer fencing an async RPC's chunks In current kernels, waiting in xprt_release appears to be safe to do. I had erroneously believed that for ASYNC RPCs, waiting of any kind in xprt_release->xprt_rdma_free would result in deadlock. I've done injection testing and consulted with Trond to confirm that waiting in the RPC release path is safe. For the very few times where RPC resources haven't yet been released earlier by the reply handler, it is safe to wait synchronously in xprt_rdma_free for invalidation rather than defering it to MR recovery. Note: When the QP is error state, posting a LocalInvalidate should flush and mark the MR as bad. There is no way the remote HCA can access that MR via a QP in error state, so it is effectively already inaccessible and thus safe for the Upper Layer to access. The next time the MR is used it should be recognized and cleaned up properly by frwr_op_map. Signed-off-by: Chuck Lever Signed-off-by: Anna Schumaker --- net/sunrpc/xprtrdma/transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index c84e2b644e13..8cf5ccfe180d 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -686,7 +686,7 @@ xprt_rdma_free(struct rpc_task *task) dprintk("RPC: %s: called on 0x%p\n", __func__, req->rl_reply); if (!list_empty(&req->rl_registered)) - ia->ri_ops->ro_unmap_safe(r_xprt, req, !RPC_IS_ASYNC(task)); + ia->ri_ops->ro_unmap_sync(r_xprt, &req->rl_registered); rpcrdma_unmap_sges(ia, req); rpcrdma_buffer_put(req); } -- GitLab From 4ce6c04c2acef91a10d65a3bcb622654bb01d930 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 9 Oct 2017 12:03:34 -0400 Subject: [PATCH 1173/2898] xprtrdma: Use ro_unmap_sync in xprt_rdma_send_request The "safe" version of ro_unmap is used here to avoid waiting unnecessarily. However: - It is safe to wait. After all, we have to wait anyway when using FMR to register memory. - This case is rare: it occurs only after a reconnect. By switching this call site to ro_unmap_sync, the final use of ro_unmap_safe is removed. Signed-off-by: Chuck Lever Signed-off-by: Anna Schumaker --- net/sunrpc/xprtrdma/transport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 8cf5ccfe180d..eb46d2479b09 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -728,7 +728,8 @@ xprt_rdma_send_request(struct rpc_task *task) /* On retransmit, remove any previously registered chunks */ if (unlikely(!list_empty(&req->rl_registered))) - r_xprt->rx_ia.ri_ops->ro_unmap_safe(r_xprt, req, false); + r_xprt->rx_ia.ri_ops->ro_unmap_sync(r_xprt, + &req->rl_registered); rc = rpcrdma_marshal_req(r_xprt, rqst); if (rc < 0) -- GitLab From 2b4f8923ecaafc0c25ee56bc17ea9256d12b747c Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 9 Oct 2017 12:03:42 -0400 Subject: [PATCH 1174/2898] xprtrdma: Remove ro_unmap_safe Clean up: There are no remaining callers of this method. Signed-off-by: Chuck Lever Signed-off-by: Anna Schumaker --- net/sunrpc/xprtrdma/fmr_ops.c | 19 ------------------- net/sunrpc/xprtrdma/frwr_ops.c | 19 ------------------- net/sunrpc/xprtrdma/xprt_rdma.h | 2 -- 3 files changed, 40 deletions(-) diff --git a/net/sunrpc/xprtrdma/fmr_ops.c b/net/sunrpc/xprtrdma/fmr_ops.c index 6c7151341194..30bf713080f1 100644 --- a/net/sunrpc/xprtrdma/fmr_ops.c +++ b/net/sunrpc/xprtrdma/fmr_ops.c @@ -305,28 +305,9 @@ fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct list_head *mws) } } -/* Use a slow, safe mechanism to invalidate all memory regions - * that were registered for "req". - */ -static void -fmr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, - bool sync) -{ - struct rpcrdma_mw *mw; - - while (!list_empty(&req->rl_registered)) { - mw = rpcrdma_pop_mw(&req->rl_registered); - if (sync) - fmr_op_recover_mr(mw); - else - rpcrdma_defer_mr_recovery(mw); - } -} - const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = { .ro_map = fmr_op_map, .ro_unmap_sync = fmr_op_unmap_sync, - .ro_unmap_safe = fmr_op_unmap_safe, .ro_recover_mr = fmr_op_recover_mr, .ro_open = fmr_op_open, .ro_maxpages = fmr_op_maxpages, diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c index df062e086bdb..3053fb0f5cb3 100644 --- a/net/sunrpc/xprtrdma/frwr_ops.c +++ b/net/sunrpc/xprtrdma/frwr_ops.c @@ -558,28 +558,9 @@ frwr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct list_head *mws) goto unmap; } -/* Use a slow, safe mechanism to invalidate all memory regions - * that were registered for "req". - */ -static void -frwr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, - bool sync) -{ - struct rpcrdma_mw *mw; - - while (!list_empty(&req->rl_registered)) { - mw = rpcrdma_pop_mw(&req->rl_registered); - if (sync) - frwr_op_recover_mr(mw); - else - rpcrdma_defer_mr_recovery(mw); - } -} - const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = { .ro_map = frwr_op_map, .ro_unmap_sync = frwr_op_unmap_sync, - .ro_unmap_safe = frwr_op_unmap_safe, .ro_recover_mr = frwr_op_recover_mr, .ro_open = frwr_op_open, .ro_maxpages = frwr_op_maxpages, diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index e26a97d2f922..74e017477e72 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h @@ -473,8 +473,6 @@ struct rpcrdma_memreg_ops { struct rpcrdma_mw **); void (*ro_unmap_sync)(struct rpcrdma_xprt *, struct list_head *); - void (*ro_unmap_safe)(struct rpcrdma_xprt *, - struct rpcrdma_req *, bool); void (*ro_recover_mr)(struct rpcrdma_mw *); int (*ro_open)(struct rpcrdma_ia *, struct rpcrdma_ep *, -- GitLab From 485f2a5811f9d87d5b634d068b5c7574fd1bb09e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 4 Oct 2017 15:30:12 +0200 Subject: [PATCH 1175/2898] platform/x86: silead_dmi: Add entry for the Chuwi Hi8 Pro tablet Add touchscreen platform data for the Chuwi Hi8 Pro tablet. Signed-off-by: Hans de Goede Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/silead_dmi.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c index 1157a7b646d6..a88823086406 100644 --- a/drivers/platform/x86/silead_dmi.c +++ b/drivers/platform/x86/silead_dmi.c @@ -136,6 +136,19 @@ static const struct silead_ts_dmi_data itworks_tw891_data = { .properties = itworks_tw891_props, }; +static const struct property_entry chuwi_hi8_pro_props[] = { + PROPERTY_ENTRY_U32("touchscreen-size-x", 1728), + PROPERTY_ENTRY_U32("touchscreen-size-y", 1148), + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), + PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"), + { } +}; + +static const struct silead_ts_dmi_data chuwi_hi8_pro_data = { + .acpi_name = "MSSL1680:00", + .properties = chuwi_hi8_pro_props, +}; + static const struct dmi_system_id silead_ts_dmi_table[] = { { /* CUBE iwork8 Air */ @@ -219,6 +232,14 @@ static const struct dmi_system_id silead_ts_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "TW891"), }, }, + { + /* Chuwi Hi8 Pro */ + .driver_data = (void *)&chuwi_hi8_pro_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"), + DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"), + }, + }, { }, }; -- GitLab From 36c282b31f648b31373be0dc8c2475c22fcab02a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 5 Oct 2017 11:42:11 +0100 Subject: [PATCH 1176/2898] platform/x86: mlx-platform: make a couple of structures static The structures mlxplat_dev and mlxplat_hotplug are local to the source and do not need to be in global scope, so make them static. Cleans up sparse warnings: symbol 'mlxplat_dev' was not declared. Should it be static? symbol 'mlxplat_hotplug' was not declared. Should it be static? Signed-off-by: Colin Ian King Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/mlx-platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 4f3de2a8c4df..504256c3660d 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -216,8 +216,8 @@ static struct resource mlxplat_mlxcpld_resources[] = { [0] = DEFINE_RES_IRQ_NAMED(17, "mlxcpld-hotplug"), }; -struct platform_device *mlxplat_dev; -struct mlxcpld_hotplug_platform_data *mlxplat_hotplug; +static struct platform_device *mlxplat_dev; +static struct mlxcpld_hotplug_platform_data *mlxplat_hotplug; static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) { -- GitLab From 136412474b77c14a26e018a7f2c1e5fcee700d3d Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 13 Oct 2017 10:06:25 -0400 Subject: [PATCH 1177/2898] tracing, dma-buf: Remove unused trace event dma_fence_annotate_wait_on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit e941759c74 ("fence: dma-buf cross-device synchronization") added trace event fence_annotate_wait_on, but never used it. It was renamed to dma_fence_annotate_wait_on by commit f54d186700 ("dma-buf: Rename struct fence to dma_fence") but still not used. As defined trace events have data structures and functions created for them, it is a waste of memory if they are not used. Remove the unused trace event. Link: http://lkml.kernel.org/r/20171013100625.6c820059@gandalf.local.home Reviewed-by: Christian König Acked-by: Sumit Semwal Signed-off-by: Steven Rostedt (VMware) --- drivers/dma-buf/dma-fence.c | 1 - include/trace/events/dma_fence.h | 40 -------------------------------- 2 files changed, 41 deletions(-) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 9a302799040e..5d101c4053e0 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -27,7 +27,6 @@ #define CREATE_TRACE_POINTS #include -EXPORT_TRACEPOINT_SYMBOL(dma_fence_annotate_wait_on); EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit); EXPORT_TRACEPOINT_SYMBOL(dma_fence_enable_signal); diff --git a/include/trace/events/dma_fence.h b/include/trace/events/dma_fence.h index 1157cb4c3c6f..50fbdefe6c81 100644 --- a/include/trace/events/dma_fence.h +++ b/include/trace/events/dma_fence.h @@ -8,46 +8,6 @@ struct dma_fence; -TRACE_EVENT(dma_fence_annotate_wait_on, - - /* fence: the fence waiting on f1, f1: the fence to be waited on. */ - TP_PROTO(struct dma_fence *fence, struct dma_fence *f1), - - TP_ARGS(fence, f1), - - TP_STRUCT__entry( - __string(driver, fence->ops->get_driver_name(fence)) - __string(timeline, fence->ops->get_timeline_name(fence)) - __field(unsigned int, context) - __field(unsigned int, seqno) - - __string(waiting_driver, f1->ops->get_driver_name(f1)) - __string(waiting_timeline, f1->ops->get_timeline_name(f1)) - __field(unsigned int, waiting_context) - __field(unsigned int, waiting_seqno) - ), - - TP_fast_assign( - __assign_str(driver, fence->ops->get_driver_name(fence)) - __assign_str(timeline, fence->ops->get_timeline_name(fence)) - __entry->context = fence->context; - __entry->seqno = fence->seqno; - - __assign_str(waiting_driver, f1->ops->get_driver_name(f1)) - __assign_str(waiting_timeline, f1->ops->get_timeline_name(f1)) - __entry->waiting_context = f1->context; - __entry->waiting_seqno = f1->seqno; - - ), - - TP_printk("driver=%s timeline=%s context=%u seqno=%u " \ - "waits on driver=%s timeline=%s context=%u seqno=%u", - __get_str(driver), __get_str(timeline), __entry->context, - __entry->seqno, - __get_str(waiting_driver), __get_str(waiting_timeline), - __entry->waiting_context, __entry->waiting_seqno) -); - DECLARE_EVENT_CLASS(dma_fence, TP_PROTO(struct dma_fence *fence), -- GitLab From 8fd0fbbe8888f295eb34172a7e47bf7d3a0a4687 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Oct 2017 09:45:29 +0200 Subject: [PATCH 1178/2898] perf/ftrace: Revert ("perf/ftrace: Fix double traces of perf on ftrace:function") Revert commit: 75e8387685f6 ("perf/ftrace: Fix double traces of perf on ftrace:function") The reason I instantly stumbled on that patch is that it only addresses the ftrace situation and doesn't mention the other _5_ places that use this interface. It doesn't explain why those don't have the problem and if not, why their solution doesn't work for ftrace. It doesn't, but this is just putting more duct tape on. Link: http://lkml.kernel.org/r/20171011080224.200565770@infradead.org Cc: Zhou Chengming Cc: Jiri Olsa Cc: Ingo Molnar Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Steven Rostedt (VMware) --- include/linux/perf_event.h | 2 +- include/linux/trace_events.h | 4 ++-- kernel/events/core.c | 13 ++++--------- kernel/trace/trace_event_perf.c | 4 +--- kernel/trace/trace_kprobe.c | 4 ++-- kernel/trace/trace_syscalls.c | 4 ++-- kernel/trace/trace_uprobe.c | 2 +- 7 files changed, 13 insertions(+), 20 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 8e22f24ded6a..569d1b54e201 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1184,7 +1184,7 @@ extern void perf_event_init(void); extern void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, struct pt_regs *regs, struct hlist_head *head, int rctx, - struct task_struct *task, struct perf_event *event); + struct task_struct *task); extern void perf_bp_event(struct perf_event *event, void *data); #ifndef perf_misc_flags diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 2e0f22298fe9..a6349b76fd39 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -507,9 +507,9 @@ void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx, static inline void perf_trace_buf_submit(void *raw_data, int size, int rctx, u16 type, u64 count, struct pt_regs *regs, void *head, - struct task_struct *task, struct perf_event *event) + struct task_struct *task) { - perf_tp_event(type, count, raw_data, size, regs, head, rctx, task, event); + perf_tp_event(type, count, raw_data, size, regs, head, rctx, task); } #endif diff --git a/kernel/events/core.c b/kernel/events/core.c index 6bc21e202ae4..b8db80c5513b 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7954,15 +7954,16 @@ void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx, } } perf_tp_event(call->event.type, count, raw_data, size, regs, head, - rctx, task, NULL); + rctx, task); } EXPORT_SYMBOL_GPL(perf_trace_run_bpf_submit); void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, struct pt_regs *regs, struct hlist_head *head, int rctx, - struct task_struct *task, struct perf_event *event) + struct task_struct *task) { struct perf_sample_data data; + struct perf_event *event; struct perf_raw_record raw = { .frag = { @@ -7976,15 +7977,9 @@ void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, perf_trace_buf_update(record, event_type); - /* Use the given event instead of the hlist */ - if (event) { + hlist_for_each_entry_rcu(event, head, hlist_entry) { if (perf_tp_event_match(event, &data, regs)) perf_swevent_event(event, count, &data, regs); - } else { - hlist_for_each_entry_rcu(event, head, hlist_entry) { - if (perf_tp_event_match(event, &data, regs)) - perf_swevent_event(event, count, &data, regs); - } } /* diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 13ba2d3f6a91..562fa69df5d3 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -306,7 +306,6 @@ static void perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *ops, struct pt_regs *pt_regs) { - struct perf_event *event; struct ftrace_entry *entry; struct hlist_head *head; struct pt_regs regs; @@ -330,9 +329,8 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, entry->ip = ip; entry->parent_ip = parent_ip; - event = container_of(ops, struct perf_event, ftrace_ops); perf_trace_buf_submit(entry, ENTRY_SIZE, rctx, TRACE_FN, - 1, ®s, head, NULL, event); + 1, ®s, head, NULL); #undef ENTRY_SIZE } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index af6134f2e597..996902a526d4 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1200,7 +1200,7 @@ kprobe_perf_func(struct trace_kprobe *tk, struct pt_regs *regs) memset(&entry[1], 0, dsize); store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize); perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, - head, NULL, NULL); + head, NULL); } NOKPROBE_SYMBOL(kprobe_perf_func); @@ -1236,7 +1236,7 @@ kretprobe_perf_func(struct trace_kprobe *tk, struct kretprobe_instance *ri, entry->ret_ip = (unsigned long)ri->ret_addr; store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize); perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, - head, NULL, NULL); + head, NULL); } NOKPROBE_SYMBOL(kretprobe_perf_func); #endif /* CONFIG_PERF_EVENTS */ diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 696afe72d3b1..934b0da72679 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -622,7 +622,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) perf_trace_buf_submit(rec, size, rctx, sys_data->enter_event->event.type, 1, regs, - head, NULL, NULL); + head, NULL); } static int perf_sysenter_enable(struct trace_event_call *call) @@ -716,7 +716,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) } perf_trace_buf_submit(rec, size, rctx, sys_data->exit_event->event.type, - 1, regs, head, NULL, NULL); + 1, regs, head, NULL); } static int perf_sysexit_enable(struct trace_event_call *call) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index b34965e62fb9..402120ba4594 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -1156,7 +1156,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu, } perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs, - head, NULL, NULL); + head, NULL); out: preempt_enable(); } -- GitLab From 466c81c45b650deca213fda3d0ec4761667379a9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 10 Oct 2017 17:15:47 +0200 Subject: [PATCH 1179/2898] perf/ftrace: Fix function trace events The function-trace <-> perf interface is a tad messed up. Where all the other trace <-> perf interfaces use a single trace hook registration and use per-cpu RCU based hlist to iterate the events, function-trace actually needs multiple hook registrations in order to minimize function entry patching when filters are present. The end result is that we iterate events both on the trace hook and on the hlist, which results in reporting events multiple times. Since function-trace cannot use the regular scheme, fix it the other way around, use singleton hlists. Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Steven Rostedt (VMware) --- include/linux/trace_events.h | 5 +++ kernel/trace/trace_event_perf.c | 80 ++++++++++++++++++++------------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index a6349b76fd39..ca4e67e466a7 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -173,6 +173,11 @@ enum trace_reg { TRACE_REG_PERF_UNREGISTER, TRACE_REG_PERF_OPEN, TRACE_REG_PERF_CLOSE, + /* + * These (ADD/DEL) use a 'boolean' return value, where 1 (true) means a + * custom action was taken and the default action is not to be + * performed. + */ TRACE_REG_PERF_ADD, TRACE_REG_PERF_DEL, #endif diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 562fa69df5d3..e73f9ab15939 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -240,27 +240,41 @@ void perf_trace_destroy(struct perf_event *p_event) int perf_trace_add(struct perf_event *p_event, int flags) { struct trace_event_call *tp_event = p_event->tp_event; - struct hlist_head __percpu *pcpu_list; - struct hlist_head *list; - - pcpu_list = tp_event->perf_events; - if (WARN_ON_ONCE(!pcpu_list)) - return -EINVAL; if (!(flags & PERF_EF_START)) p_event->hw.state = PERF_HES_STOPPED; - list = this_cpu_ptr(pcpu_list); - hlist_add_head_rcu(&p_event->hlist_entry, list); + /* + * If TRACE_REG_PERF_ADD returns false; no custom action was performed + * and we need to take the default action of enqueueing our event on + * the right per-cpu hlist. + */ + if (!tp_event->class->reg(tp_event, TRACE_REG_PERF_ADD, p_event)) { + struct hlist_head __percpu *pcpu_list; + struct hlist_head *list; + + pcpu_list = tp_event->perf_events; + if (WARN_ON_ONCE(!pcpu_list)) + return -EINVAL; + + list = this_cpu_ptr(pcpu_list); + hlist_add_head_rcu(&p_event->hlist_entry, list); + } - return tp_event->class->reg(tp_event, TRACE_REG_PERF_ADD, p_event); + return 0; } void perf_trace_del(struct perf_event *p_event, int flags) { struct trace_event_call *tp_event = p_event->tp_event; - hlist_del_rcu(&p_event->hlist_entry); - tp_event->class->reg(tp_event, TRACE_REG_PERF_DEL, p_event); + + /* + * If TRACE_REG_PERF_DEL returns false; no custom action was performed + * and we need to take the default action of dequeueing our event from + * the right per-cpu hlist. + */ + if (!tp_event->class->reg(tp_event, TRACE_REG_PERF_DEL, p_event)) + hlist_del_rcu(&p_event->hlist_entry); } void *perf_trace_buf_alloc(int size, struct pt_regs **regs, int *rctxp) @@ -307,14 +321,24 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *ops, struct pt_regs *pt_regs) { struct ftrace_entry *entry; - struct hlist_head *head; + struct perf_event *event; + struct hlist_head head; struct pt_regs regs; int rctx; - head = this_cpu_ptr(event_function.perf_events); - if (hlist_empty(head)) + if ((unsigned long)ops->private != smp_processor_id()) return; + event = container_of(ops, struct perf_event, ftrace_ops); + + /* + * @event->hlist entry is NULL (per INIT_HLIST_NODE), and all + * the perf code does is hlist_for_each_entry_rcu(), so we can + * get away with simply setting the @head.first pointer in order + * to create a singular list. + */ + head.first = &event->hlist_entry; + #define ENTRY_SIZE (ALIGN(sizeof(struct ftrace_entry) + sizeof(u32), \ sizeof(u64)) - sizeof(u32)) @@ -330,7 +354,7 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, entry->ip = ip; entry->parent_ip = parent_ip; perf_trace_buf_submit(entry, ENTRY_SIZE, rctx, TRACE_FN, - 1, ®s, head, NULL); + 1, ®s, &head, NULL); #undef ENTRY_SIZE } @@ -339,8 +363,10 @@ static int perf_ftrace_function_register(struct perf_event *event) { struct ftrace_ops *ops = &event->ftrace_ops; - ops->flags |= FTRACE_OPS_FL_PER_CPU | FTRACE_OPS_FL_RCU; - ops->func = perf_ftrace_function_call; + ops->flags |= FTRACE_OPS_FL_RCU; + ops->func = perf_ftrace_function_call; + ops->private = (void *)(unsigned long)nr_cpu_ids; + return register_ftrace_function(ops); } @@ -352,19 +378,11 @@ static int perf_ftrace_function_unregister(struct perf_event *event) return ret; } -static void perf_ftrace_function_enable(struct perf_event *event) -{ - ftrace_function_local_enable(&event->ftrace_ops); -} - -static void perf_ftrace_function_disable(struct perf_event *event) -{ - ftrace_function_local_disable(&event->ftrace_ops); -} - int perf_ftrace_event_register(struct trace_event_call *call, enum trace_reg type, void *data) { + struct perf_event *event = data; + switch (type) { case TRACE_REG_REGISTER: case TRACE_REG_UNREGISTER: @@ -377,11 +395,11 @@ int perf_ftrace_event_register(struct trace_event_call *call, case TRACE_REG_PERF_CLOSE: return perf_ftrace_function_unregister(data); case TRACE_REG_PERF_ADD: - perf_ftrace_function_enable(data); - return 0; + event->ftrace_ops.private = (void *)(unsigned long)smp_processor_id(); + return 1; case TRACE_REG_PERF_DEL: - perf_ftrace_function_disable(data); - return 0; + event->ftrace_ops.private = (void *)(unsigned long)nr_cpu_ids; + return 1; } return -EINVAL; -- GitLab From 1dd311e6dcda4020c603bcf9f390a577d439d509 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Oct 2017 09:45:31 +0200 Subject: [PATCH 1180/2898] perf/ftrace: Small cleanup ops->flags _should_ be 0 at this point, so setting the flag using bitwise or is a bit daft. Link: http://lkml.kernel.org/r/20171011080224.315585202@infradead.org Requested-by: Steven Rostedt Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_event_perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index e73f9ab15939..55d6dff37daf 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -363,7 +363,7 @@ static int perf_ftrace_function_register(struct perf_event *event) { struct ftrace_ops *ops = &event->ftrace_ops; - ops->flags |= FTRACE_OPS_FL_RCU; + ops->flags = FTRACE_OPS_FL_RCU; ops->func = perf_ftrace_function_call; ops->private = (void *)(unsigned long)nr_cpu_ids; -- GitLab From b3a88803ac5b4bda26017b485c8722a8487fefb7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Oct 2017 09:45:32 +0200 Subject: [PATCH 1181/2898] ftrace: Kill FTRACE_OPS_FL_PER_CPU The one and only user of FTRACE_OPS_FL_PER_CPU is gone, remove the lot. Link: http://lkml.kernel.org/r/20171011080224.372422809@infradead.org Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Steven Rostedt (VMware) --- include/linux/ftrace.h | 83 +++++++----------------------------------- kernel/trace/ftrace.c | 55 +++------------------------- 2 files changed, 20 insertions(+), 118 deletions(-) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 1f8545caa691..252e334e7b5f 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -102,10 +102,6 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops); * ENABLED - set/unset when ftrace_ops is registered/unregistered * DYNAMIC - set when ftrace_ops is registered to denote dynamically * allocated ftrace_ops which need special care - * PER_CPU - set manualy by ftrace_ops user to denote the ftrace_ops - * could be controlled by following calls: - * ftrace_function_local_enable - * ftrace_function_local_disable * SAVE_REGS - The ftrace_ops wants regs saved at each function called * and passed to the callback. If this flag is set, but the * architecture does not support passing regs @@ -149,21 +145,20 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops); enum { FTRACE_OPS_FL_ENABLED = 1 << 0, FTRACE_OPS_FL_DYNAMIC = 1 << 1, - FTRACE_OPS_FL_PER_CPU = 1 << 2, - FTRACE_OPS_FL_SAVE_REGS = 1 << 3, - FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 4, - FTRACE_OPS_FL_RECURSION_SAFE = 1 << 5, - FTRACE_OPS_FL_STUB = 1 << 6, - FTRACE_OPS_FL_INITIALIZED = 1 << 7, - FTRACE_OPS_FL_DELETED = 1 << 8, - FTRACE_OPS_FL_ADDING = 1 << 9, - FTRACE_OPS_FL_REMOVING = 1 << 10, - FTRACE_OPS_FL_MODIFYING = 1 << 11, - FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12, - FTRACE_OPS_FL_IPMODIFY = 1 << 13, - FTRACE_OPS_FL_PID = 1 << 14, - FTRACE_OPS_FL_RCU = 1 << 15, - FTRACE_OPS_FL_TRACE_ARRAY = 1 << 16, + FTRACE_OPS_FL_SAVE_REGS = 1 << 2, + FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 3, + FTRACE_OPS_FL_RECURSION_SAFE = 1 << 4, + FTRACE_OPS_FL_STUB = 1 << 5, + FTRACE_OPS_FL_INITIALIZED = 1 << 6, + FTRACE_OPS_FL_DELETED = 1 << 7, + FTRACE_OPS_FL_ADDING = 1 << 8, + FTRACE_OPS_FL_REMOVING = 1 << 9, + FTRACE_OPS_FL_MODIFYING = 1 << 10, + FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 11, + FTRACE_OPS_FL_IPMODIFY = 1 << 12, + FTRACE_OPS_FL_PID = 1 << 13, + FTRACE_OPS_FL_RCU = 1 << 14, + FTRACE_OPS_FL_TRACE_ARRAY = 1 << 15, }; #ifdef CONFIG_DYNAMIC_FTRACE @@ -198,7 +193,6 @@ struct ftrace_ops { unsigned long flags; void *private; ftrace_func_t saved_func; - int __percpu *disabled; #ifdef CONFIG_DYNAMIC_FTRACE struct ftrace_ops_hash local_hash; struct ftrace_ops_hash *func_hash; @@ -230,55 +224,6 @@ int register_ftrace_function(struct ftrace_ops *ops); int unregister_ftrace_function(struct ftrace_ops *ops); void clear_ftrace_function(void); -/** - * ftrace_function_local_enable - enable ftrace_ops on current cpu - * - * This function enables tracing on current cpu by decreasing - * the per cpu control variable. - * It must be called with preemption disabled and only on ftrace_ops - * registered with FTRACE_OPS_FL_PER_CPU. If called without preemption - * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled. - */ -static inline void ftrace_function_local_enable(struct ftrace_ops *ops) -{ - if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_PER_CPU))) - return; - - (*this_cpu_ptr(ops->disabled))--; -} - -/** - * ftrace_function_local_disable - disable ftrace_ops on current cpu - * - * This function disables tracing on current cpu by increasing - * the per cpu control variable. - * It must be called with preemption disabled and only on ftrace_ops - * registered with FTRACE_OPS_FL_PER_CPU. If called without preemption - * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled. - */ -static inline void ftrace_function_local_disable(struct ftrace_ops *ops) -{ - if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_PER_CPU))) - return; - - (*this_cpu_ptr(ops->disabled))++; -} - -/** - * ftrace_function_local_disabled - returns ftrace_ops disabled value - * on current cpu - * - * This function returns value of ftrace_ops::disabled on current cpu. - * It must be called with preemption disabled and only on ftrace_ops - * registered with FTRACE_OPS_FL_PER_CPU. If called without preemption - * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled. - */ -static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) -{ - WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_PER_CPU)); - return *this_cpu_ptr(ops->disabled); -} - extern void ftrace_stub(unsigned long a0, unsigned long a1, struct ftrace_ops *op, struct pt_regs *regs); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index e0a98225666b..2fd3edaec6de 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -203,30 +203,6 @@ void clear_ftrace_function(void) ftrace_trace_function = ftrace_stub; } -static void per_cpu_ops_disable_all(struct ftrace_ops *ops) -{ - int cpu; - - for_each_possible_cpu(cpu) - *per_cpu_ptr(ops->disabled, cpu) = 1; -} - -static int per_cpu_ops_alloc(struct ftrace_ops *ops) -{ - int __percpu *disabled; - - if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_PER_CPU))) - return -EINVAL; - - disabled = alloc_percpu(int); - if (!disabled) - return -ENOMEM; - - ops->disabled = disabled; - per_cpu_ops_disable_all(ops); - return 0; -} - static void ftrace_sync(struct work_struct *work) { /* @@ -262,8 +238,8 @@ static ftrace_func_t ftrace_ops_get_list_func(struct ftrace_ops *ops) * If this is a dynamic, RCU, or per CPU ops, or we force list func, * then it needs to call the list anyway. */ - if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_PER_CPU | - FTRACE_OPS_FL_RCU) || FTRACE_FORCE_LIST_FUNC) + if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_RCU) || + FTRACE_FORCE_LIST_FUNC) return ftrace_ops_list_func; return ftrace_ops_get_func(ops); @@ -422,11 +398,6 @@ static int __register_ftrace_function(struct ftrace_ops *ops) if (!core_kernel_data((unsigned long)ops)) ops->flags |= FTRACE_OPS_FL_DYNAMIC; - if (ops->flags & FTRACE_OPS_FL_PER_CPU) { - if (per_cpu_ops_alloc(ops)) - return -ENOMEM; - } - add_ftrace_ops(&ftrace_ops_list, ops); /* Always save the function, and reset at unregistering */ @@ -2727,11 +2698,6 @@ void __weak arch_ftrace_trampoline_free(struct ftrace_ops *ops) { } -static void per_cpu_ops_free(struct ftrace_ops *ops) -{ - free_percpu(ops->disabled); -} - static void ftrace_startup_enable(int command) { if (saved_ftrace_func != ftrace_trace_function) { @@ -2833,7 +2799,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command) * not currently active, we can just free them * without synchronizing all CPUs. */ - if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_PER_CPU)) + if (ops->flags & FTRACE_OPS_FL_DYNAMIC) goto free_ops; return 0; @@ -2880,7 +2846,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command) * The same goes for freeing the per_cpu data of the per_cpu * ops. */ - if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_PER_CPU)) { + if (ops->flags & FTRACE_OPS_FL_DYNAMIC) { /* * We need to do a hard force of sched synchronization. * This is because we use preempt_disable() to do RCU, but @@ -2903,9 +2869,6 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command) free_ops: arch_ftrace_trampoline_free(ops); - - if (ops->flags & FTRACE_OPS_FL_PER_CPU) - per_cpu_ops_free(ops); } return 0; @@ -6355,10 +6318,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, * If any of the above fails then the op->func() is not executed. */ if ((!(op->flags & FTRACE_OPS_FL_RCU) || rcu_is_watching()) && - (!(op->flags & FTRACE_OPS_FL_PER_CPU) || - !ftrace_function_local_disabled(op)) && ftrace_ops_test(op, ip, regs)) { - if (FTRACE_WARN_ON(!op->func)) { pr_warn("op=%p %pS\n", op, op); goto out; @@ -6416,10 +6376,7 @@ static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip, preempt_disable_notrace(); - if (!(op->flags & FTRACE_OPS_FL_PER_CPU) || - !ftrace_function_local_disabled(op)) { - op->func(ip, parent_ip, op, regs); - } + op->func(ip, parent_ip, op, regs); preempt_enable_notrace(); trace_clear_recursion(bit); @@ -6443,7 +6400,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops) * or does per cpu logic, then we need to call the assist handler. */ if (!(ops->flags & FTRACE_OPS_FL_RECURSION_SAFE) || - ops->flags & (FTRACE_OPS_FL_RCU | FTRACE_OPS_FL_PER_CPU)) + ops->flags & FTRACE_OPS_FL_RCU) return ftrace_ops_assist_func; return ops->func; -- GitLab From 9ba29fcb76a559078491adffc74f66bf92b9dbea Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 9 Oct 2017 10:33:04 +1000 Subject: [PATCH 1182/2898] drm/amd/display: Use DRM new-style object iterators. Use the correct for_each_new/old_* iterators instead of for_each_* The following functions were considered: amdgpu_dm_find_first_crtc_matching_connector: use for_each_new - Old from_state_var flag was always choosing the new state amdgpu_dm_display_resume: use for_each_new - drm_atomic_helper_duplicate_state is called during suspend to cache the state - It sets 'state' within the state triplet to 'new_state' amdgpu_dm_commit_planes: use for_each_old - Called after the state was swapped (via atomic commit tail) amdgpu_dm_atomic_commit: use for_each_new - Called before the state is swapped amdgpu_dm_atomic_commit_tail: use for_each_old - Called after the state was swapped dm_update_crtcs_state: use for_each_new - Called before the state is swapped (via atomic check) amdgpu_dm_atomic_check: use for_each_new - Called before the state is swapped v2: Split out typo fixes to a new patch. v3: Say "functions considered" instead of "affected functions". The latter implies that changes are made to each. [airlied: squashed with my hacks] Reviewed-by: Harry Wentland Reviewed-by: Maarten Lankhorst Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 +++++++------------ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 +- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4f8973182f8a..cc024abb14d5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -570,23 +570,15 @@ static int dm_suspend(void *handle) struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_atomic_state *state, - struct drm_crtc *crtc, - bool from_state_var) + struct drm_crtc *crtc) { uint32_t i; struct drm_connector_state *conn_state; struct drm_connector *connector; struct drm_crtc *crtc_from_state; - for_each_connector_in_state( - state, - connector, - conn_state, - i) { - crtc_from_state = - from_state_var ? - conn_state->crtc : - connector->state->crtc; + for_each_new_connector_in_state(state, connector, conn_state, i) { + crtc_from_state = conn_state->crtc; if (crtc_from_state == crtc) return to_amdgpu_dm_connector(connector); @@ -652,7 +644,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) } /* Force mode set in atomic comit */ - for_each_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i) + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i) crtc_state->active_changed = true; ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); @@ -3890,7 +3882,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, unsigned long flags; /* update planes when needed */ - for_each_plane_in_state(state, plane, old_plane_state, i) { + for_each_old_plane_in_state(state, plane, old_plane_state, i) { struct drm_plane_state *plane_state = plane->state; struct drm_crtc *crtc = plane_state->crtc; struct drm_framebuffer *fb = plane_state->fb; @@ -3987,7 +3979,7 @@ int amdgpu_dm_atomic_commit( * it will update crtc->dm_crtc_state->stream pointer which is used in * the ISRs. */ - for_each_crtc_in_state(state, crtc, new_state, i) { + for_each_new_crtc_in_state(state, crtc, new_state, i) { struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -4024,7 +4016,7 @@ void amdgpu_dm_atomic_commit_tail( dm_state = to_dm_atomic_state(state); /* update changed items */ - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct drm_crtc_state *new_state = crtc->state; @@ -4113,11 +4105,9 @@ void amdgpu_dm_atomic_commit_tail( new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); new_stream = new_acrtc_state->stream; - aconnector = - amdgpu_dm_find_first_crct_matching_connector( + aconnector = amdgpu_dm_find_first_crct_matching_connector( state, - &new_crtcs[i]->base, - false); + &new_crtcs[i]->base); if (!aconnector) { DRM_DEBUG_DRIVER("Atomic commit: Failed to find connector for acrtc id:%d " "skipping freesync init\n", @@ -4151,7 +4141,7 @@ void amdgpu_dm_atomic_commit_tail( } /* Handle scaling and undersacn changes*/ - for_each_connector_in_state(state, connector, old_conn_state, i) { + for_each_old_connector_in_state(state, connector, old_conn_state, i) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *con_new_state = to_dm_connector_state(aconnector->base.state); @@ -4205,7 +4195,7 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed per crtc*/ - for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { + for_each_old_crtc_in_state(state, pcrtc, old_crtc_state, j) { new_acrtc_state = to_dm_crtc_state(pcrtc->state); if (new_acrtc_state->stream) @@ -4218,7 +4208,7 @@ void amdgpu_dm_atomic_commit_tail( * mark consumed event for drm_atomic_helper_commit_hw_done */ spin_lock_irqsave(&adev->ddev->event_lock, flags); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); if (acrtc->base.state->event) @@ -4390,7 +4380,7 @@ static int dm_update_crtcs_state( /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ /* update changed items */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_dm_connector *aconnector = NULL; struct drm_connector_state *conn_state = NULL; @@ -4402,7 +4392,7 @@ static int dm_update_crtcs_state( new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); - aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); + aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc); /* TODO This hack should go away */ if (aconnector) { @@ -4674,7 +4664,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * Hack: Commit needs planes right now, specifically for gamma * TODO rework commit to check CRTC for gamma change */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { if (crtc_state->color_mgmt_changed) { ret = drm_atomic_add_affected_planes(state, crtc); if (ret) @@ -4720,7 +4710,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * new stream into context w\o causing full reset. Need to * decide how to handle. */ - for_each_connector_in_state(state, connector, conn_state, i) { + for_each_new_connector_in_state(state, connector, conn_state, i) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct dm_connector_state *con_old_state = to_dm_connector_state(aconnector->base.state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 630e6cdf84f6..1c55a0b5cd15 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -228,8 +228,7 @@ void amdgpu_dm_update_connector_after_detect( struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_atomic_state *state, - struct drm_crtc *crtc, - bool from_state_var); + struct drm_crtc *crtc); struct amdgpu_framebuffer; -- GitLab From 0bc9706db3a35b6d674d0642f425d768560736b2 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:07 -0400 Subject: [PATCH 1183/2898] drm/amd/display: Use new DRM API where possible To conform to DRM's new API, we should not be accessing a DRM object's internal state directly. Rather, the DRM for_each_old/new_* iterators, and drm_atomic_get_old/new_* interface should be used. This is an ongoing process. For now, update the DRM-facing atomic functions, where the atomic state object is given. Reviewed-by: Harry Wentland Reviewed-by: Maarten Lankhorst Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 131 +++++++++--------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index cc024abb14d5..d4426b326918 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3873,28 +3873,31 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, { uint32_t i; struct drm_plane *plane; - struct drm_plane_state *old_plane_state; + struct drm_plane_state *old_plane_state, *new_plane_state; struct dc_stream_state *dc_stream_attach; struct dc_plane_state *plane_states_constructed[MAX_SURFACES]; struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); - struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state); + struct drm_crtc_state *new_pcrtc_state = + drm_atomic_get_new_crtc_state(state, pcrtc); + struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); int planes_count = 0; unsigned long flags; /* update planes when needed */ - for_each_old_plane_in_state(state, plane, old_plane_state, i) { - struct drm_plane_state *plane_state = plane->state; - struct drm_crtc *crtc = plane_state->crtc; - struct drm_framebuffer *fb = plane_state->fb; + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { + struct drm_crtc *crtc = new_plane_state->crtc; + struct drm_crtc_state *new_crtc_state = + drm_atomic_get_new_crtc_state(state, crtc); + struct drm_framebuffer *fb = new_plane_state->fb; bool pflip_needed; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); + struct dm_plane_state *dm_plane_state = to_dm_plane_state(new_plane_state); if (plane->type == DRM_PLANE_TYPE_CURSOR) { handle_cursor_update(plane, old_plane_state); continue; } - if (!fb || !crtc || pcrtc != crtc || !crtc->state->active) + if (!fb || !crtc || pcrtc != crtc || !new_crtc_state->active) continue; pflip_needed = !state->allow_modeset; @@ -3918,13 +3921,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, dc_stream_attach = acrtc_state->stream; planes_count++; - } else if (crtc->state->planes_changed) { + } else if (new_crtc_state->planes_changed) { /* Assume even ONE crtc with immediate flip means * entire can't wait for VBLANK * TODO Check if it's correct */ *wait_for_vblank = - pcrtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? + new_pcrtc_state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? false : true; /* TODO: Needs rework for multiplane flip */ @@ -3942,7 +3945,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (planes_count) { unsigned long flags; - if (pcrtc->state->event) { + if (new_pcrtc_state->event) { drm_crtc_vblank_get(pcrtc); @@ -3968,7 +3971,7 @@ int amdgpu_dm_atomic_commit( bool nonblock) { struct drm_crtc *crtc; - struct drm_crtc_state *new_state; + struct drm_crtc_state *old_crtc_state, *new_state; struct amdgpu_device *adev = dev->dev_private; int i; @@ -3979,8 +3982,8 @@ int amdgpu_dm_atomic_commit( * it will update crtc->dm_crtc_state->stream pointer which is used in * the ISRs. */ - for_each_new_crtc_in_state(state, crtc, new_state, i) { - struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state); + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_state, i) { + struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(old_crtc_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) @@ -4002,13 +4005,13 @@ void amdgpu_dm_atomic_commit_tail( uint32_t i, j; uint32_t new_crtcs_count = 0; struct drm_crtc *crtc, *pcrtc; - struct drm_crtc_state *old_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; struct dc_stream_state *new_stream = NULL; unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; - struct drm_connector_state *old_conn_state; + struct drm_connector_state *old_conn_state, *new_con_state; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -4016,11 +4019,10 @@ void amdgpu_dm_atomic_commit_tail( dm_state = to_dm_atomic_state(state); /* update changed items */ - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct drm_crtc_state *new_state = crtc->state; - new_acrtc_state = to_dm_crtc_state(new_state); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); old_acrtc_state = to_dm_crtc_state(old_crtc_state); DRM_DEBUG_DRIVER( @@ -4028,18 +4030,18 @@ void amdgpu_dm_atomic_commit_tail( "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", acrtc->crtc_id, - new_state->enable, - new_state->active, - new_state->planes_changed, - new_state->mode_changed, - new_state->active_changed, - new_state->connectors_changed); + new_crtc_state->enable, + new_crtc_state->active, + new_crtc_state->planes_changed, + new_crtc_state->mode_changed, + new_crtc_state->active_changed, + new_crtc_state->connectors_changed); /* handles headless hotplug case, updating new_state and * aconnector as needed */ - if (modeset_required(new_state, new_acrtc_state->stream, old_acrtc_state->stream)) { + if (modeset_required(new_crtc_state, new_acrtc_state->stream, old_acrtc_state->stream)) { DRM_DEBUG_DRIVER("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); @@ -4082,10 +4084,11 @@ void amdgpu_dm_atomic_commit_tail( new_crtcs[new_crtcs_count] = acrtc; new_crtcs_count++; + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); acrtc->enabled = true; - acrtc->hw_mode = crtc->state->mode; - crtc->hwmode = crtc->state->mode; - } else if (modereset_required(new_state)) { + acrtc->hw_mode = new_crtc_state->mode; + crtc->hwmode = new_crtc_state->mode; + } else if (modereset_required(new_crtc_state)) { DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ @@ -4102,7 +4105,9 @@ void amdgpu_dm_atomic_commit_tail( for (i = 0; i < new_crtcs_count; i++) { struct amdgpu_dm_connector *aconnector = NULL; - new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state); + new_crtc_state = drm_atomic_get_new_crtc_state(state, + &new_crtcs[i]->base); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); new_stream = new_acrtc_state->stream; aconnector = amdgpu_dm_find_first_crct_matching_connector( @@ -4123,11 +4128,10 @@ void amdgpu_dm_atomic_commit_tail( if (dm_state->context) WARN_ON(!dc_commit_state(dm->dc, dm_state->context)); - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - new_acrtc_state = to_dm_crtc_state(crtc->state); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); if (new_acrtc_state->stream != NULL) { const struct dc_stream_status *status = @@ -4141,24 +4145,24 @@ void amdgpu_dm_atomic_commit_tail( } /* Handle scaling and undersacn changes*/ - for_each_old_connector_in_state(state, connector, old_conn_state, i) { - struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct dm_connector_state *con_new_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_old_state = - to_dm_connector_state(old_conn_state); + for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_con_state, i) { + struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); + struct dm_connector_state *con_old_state = to_dm_connector_state(old_conn_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); struct dc_stream_status *status = NULL; + if (acrtc) + new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); + /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + if (!acrtc || drm_atomic_crtc_needs_modeset(new_crtc_state)) continue; /* Skip any thing not scale or underscan changes */ if (!is_scaling_state_different(con_new_state, con_old_state)) continue; - new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); update_stream_scaling_settings(&con_new_state->base.crtc->mode, con_new_state, (struct dc_stream_state *)new_acrtc_state->stream); @@ -4185,7 +4189,8 @@ void amdgpu_dm_atomic_commit_tail( */ struct amdgpu_crtc *acrtc = new_crtcs[i]; - new_acrtc_state = to_dm_crtc_state(acrtc->base.state); + new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); if (adev->dm.freesync_module) mod_freesync_notify_mode_change( @@ -4195,8 +4200,8 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed per crtc*/ - for_each_old_crtc_in_state(state, pcrtc, old_crtc_state, j) { - new_acrtc_state = to_dm_crtc_state(pcrtc->state); + for_each_new_crtc_in_state(state, pcrtc, new_crtc_state, j) { + new_acrtc_state = to_dm_crtc_state(new_crtc_state); if (new_acrtc_state->stream) amdgpu_dm_commit_planes(state, dev, dm, pcrtc, &wait_for_vblank); @@ -4208,13 +4213,12 @@ void amdgpu_dm_atomic_commit_tail( * mark consumed event for drm_atomic_helper_commit_hw_done */ spin_lock_irqsave(&adev->ddev->event_lock, flags); - for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - if (acrtc->base.state->event) - drm_send_event_locked(dev, &crtc->state->event->base); + if (new_crtc_state->event) + drm_send_event_locked(dev, &new_crtc_state->event->base); - acrtc->base.state->event = NULL; + new_crtc_state->event = NULL; } spin_unlock_irqrestore(&adev->ddev->event_lock, flags); @@ -4371,7 +4375,7 @@ static int dm_update_crtcs_state( bool *lock_and_validation_needed) { struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *old_crtc_state, *crtc_state; int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); @@ -4380,7 +4384,7 @@ static int dm_update_crtcs_state( /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ /* update changed items */ - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_dm_connector *aconnector = NULL; struct drm_connector_state *conn_state = NULL; @@ -4388,7 +4392,7 @@ static int dm_update_crtcs_state( new_stream = NULL; - old_acrtc_state = to_dm_crtc_state(crtc->state); + old_acrtc_state = to_dm_crtc_state(old_crtc_state); new_acrtc_state = to_dm_crtc_state(crtc_state); acrtc = to_amdgpu_crtc(crtc); @@ -4521,7 +4525,7 @@ static int dm_update_planes_state( bool *lock_and_validation_needed) { struct drm_crtc *new_plane_crtc, *old_plane_crtc; - struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; struct dm_crtc_state *new_acrtc_state, *old_acrtc_state; @@ -4552,10 +4556,9 @@ static int dm_update_planes_state( if (!old_plane_crtc) continue; - old_acrtc_state = to_dm_crtc_state( - drm_atomic_get_old_crtc_state( - state, - old_plane_crtc)); + old_crtc_state = drm_atomic_get_old_crtc_state( + state, old_plane_crtc); + old_acrtc_state = to_dm_crtc_state(old_crtc_state); if (!old_acrtc_state->stream) continue; @@ -4643,7 +4646,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); struct drm_connector *connector; - struct drm_connector_state *conn_state; + struct drm_connector_state *old_con_state, *conn_state; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; @@ -4710,16 +4713,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * new stream into context w\o causing full reset. Need to * decide how to handle. */ - for_each_new_connector_in_state(state, connector, conn_state, i) { - struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct dm_connector_state *con_old_state = - to_dm_connector_state(aconnector->base.state); - struct dm_connector_state *con_new_state = - to_dm_connector_state(conn_state); + for_each_oldnew_connector_in_state(state, connector, old_con_state, conn_state, i) { + struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); + struct dm_connector_state *con_new_state = to_dm_connector_state(conn_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); /* Skip any modesets/resets */ - if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) + if (!acrtc || drm_atomic_crtc_needs_modeset( + drm_atomic_get_new_crtc_state(state, &acrtc->base))) continue; /* Skip any thing not scale or underscan changes */ -- GitLab From c2cea7063b85fc2bcec92997a808f1d3a16f8052 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:08 -0400 Subject: [PATCH 1184/2898] drm/amd/display: Unify DRM state variable namings. Use new_*_state and old_*_state for their respective new/old DRM object states. Reviewed-by: Maarten Lankhorst Reviewed-by: Harry Wentland Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d4426b326918..fe0b658cf3a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -573,12 +573,12 @@ struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( struct drm_crtc *crtc) { uint32_t i; - struct drm_connector_state *conn_state; + struct drm_connector_state *new_con_state; struct drm_connector *connector; struct drm_crtc *crtc_from_state; - for_each_new_connector_in_state(state, connector, conn_state, i) { - crtc_from_state = conn_state->crtc; + for_each_new_connector_in_state(state, connector, new_con_state, i) { + crtc_from_state = new_con_state->crtc; if (crtc_from_state == crtc) return to_amdgpu_dm_connector(connector); @@ -608,7 +608,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *new_crtc_state; int ret = 0; int i; @@ -644,8 +644,8 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) } /* Force mode set in atomic comit */ - for_each_new_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i) - crtc_state->active_changed = true; + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) + new_crtc_state->active_changed = true; ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); @@ -3971,7 +3971,7 @@ int amdgpu_dm_atomic_commit( bool nonblock) { struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state, *new_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct amdgpu_device *adev = dev->dev_private; int i; @@ -3982,11 +3982,11 @@ int amdgpu_dm_atomic_commit( * it will update crtc->dm_crtc_state->stream pointer which is used in * the ISRs. */ - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(old_crtc_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream) + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && old_acrtc_state->stream) manage_dm_interrupts(adev, acrtc, false); } @@ -4011,7 +4011,7 @@ void amdgpu_dm_atomic_commit_tail( unsigned long flags; bool wait_for_vblank = true; struct drm_connector *connector; - struct drm_connector_state *old_conn_state, *new_con_state; + struct drm_connector_state *old_con_state, *new_con_state; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -4145,9 +4145,9 @@ void amdgpu_dm_atomic_commit_tail( } /* Handle scaling and undersacn changes*/ - for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_con_state, i) { + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); - struct dm_connector_state *con_old_state = to_dm_connector_state(old_conn_state); + struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); struct dc_stream_status *status = NULL; @@ -4375,7 +4375,7 @@ static int dm_update_crtcs_state( bool *lock_and_validation_needed) { struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state, *crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; int i; struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); @@ -4384,34 +4384,34 @@ static int dm_update_crtcs_state( /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */ /* update changed items */ - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_dm_connector *aconnector = NULL; - struct drm_connector_state *conn_state = NULL; + struct drm_connector_state *new_con_state = NULL; struct dm_connector_state *dm_conn_state = NULL; new_stream = NULL; old_acrtc_state = to_dm_crtc_state(old_crtc_state); - new_acrtc_state = to_dm_crtc_state(crtc_state); + new_acrtc_state = to_dm_crtc_state(new_crtc_state); acrtc = to_amdgpu_crtc(crtc); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc); /* TODO This hack should go away */ if (aconnector) { - conn_state = drm_atomic_get_connector_state(state, - &aconnector->base); + new_con_state = drm_atomic_get_connector_state(state, + &aconnector->base); - if (IS_ERR(conn_state)) { - ret = PTR_ERR_OR_ZERO(conn_state); + if (IS_ERR(new_con_state)) { + ret = PTR_ERR_OR_ZERO(new_con_state); break; } - dm_conn_state = to_dm_connector_state(conn_state); + dm_conn_state = to_dm_connector_state(new_con_state); new_stream = create_stream_for_sink(aconnector, - &crtc_state->mode, + &new_crtc_state->mode, dm_conn_state); /* @@ -4431,14 +4431,14 @@ static int dm_update_crtcs_state( if (dc_is_stream_unchanged(new_stream, old_acrtc_state->stream)) { - crtc_state->mode_changed = false; + new_crtc_state->mode_changed = false; - DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", - crtc_state->mode_changed); + DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", + new_crtc_state->mode_changed); } - if (!drm_atomic_crtc_needs_modeset(crtc_state)) + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) goto next_crtc; DRM_DEBUG_DRIVER( @@ -4446,12 +4446,12 @@ static int dm_update_crtcs_state( "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", acrtc->crtc_id, - crtc_state->enable, - crtc_state->active, - crtc_state->planes_changed, - crtc_state->mode_changed, - crtc_state->active_changed, - crtc_state->connectors_changed); + new_crtc_state->enable, + new_crtc_state->active, + new_crtc_state->planes_changed, + new_crtc_state->mode_changed, + new_crtc_state->active_changed, + new_crtc_state->connectors_changed); /* Remove stream for any changed/disabled CRTC */ if (!enable) { @@ -4478,10 +4478,10 @@ static int dm_update_crtcs_state( } else {/* Add stream for any updated/enabled CRTC */ - if (modereset_required(crtc_state)) + if (modereset_required(new_crtc_state)) goto next_crtc; - if (modeset_required(crtc_state, new_stream, + if (modeset_required(new_crtc_state, new_stream, old_acrtc_state->stream)) { WARN_ON(new_acrtc_state->stream); @@ -4646,9 +4646,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct dc *dc = adev->dm.dc; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); struct drm_connector *connector; - struct drm_connector_state *old_con_state, *conn_state; + struct drm_connector_state *old_con_state, *new_con_state; struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *new_crtc_state; /* * This bool will be set for true for any modeset/reset @@ -4667,8 +4667,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * Hack: Commit needs planes right now, specifically for gamma * TODO rework commit to check CRTC for gamma change */ - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { - if (crtc_state->color_mgmt_changed) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed) { ret = drm_atomic_add_affected_planes(state, crtc); if (ret) goto fail; @@ -4713,9 +4713,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * new stream into context w\o causing full reset. Need to * decide how to handle. */ - for_each_oldnew_connector_in_state(state, connector, old_con_state, conn_state, i) { + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); - struct dm_connector_state *con_new_state = to_dm_connector_state(conn_state); + struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); /* Skip any modesets/resets */ -- GitLab From 54d76575246798f5f42ca56fe5d54d1f195198b2 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:09 -0400 Subject: [PATCH 1185/2898] drm/amd/display: Unify amdgpu_dm state variable namings. Use dm_new_*_state and dm_old_*_state for their respective amdgpu_dm new and old object states. Helps with readability, and enforces use of new DRM api (choose either new, or old). Reviewed-by: Maarten Lankhorst Reviewed-by: Harry Wentland Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 137 +++++++++--------- 1 file changed, 68 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index fe0b658cf3a6..de88ee1af438 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3890,7 +3890,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, drm_atomic_get_new_crtc_state(state, crtc); struct drm_framebuffer *fb = new_plane_state->fb; bool pflip_needed; - struct dm_plane_state *dm_plane_state = to_dm_plane_state(new_plane_state); + struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state); if (plane->type == DRM_PLANE_TYPE_CURSOR) { handle_cursor_update(plane, old_plane_state); @@ -3914,9 +3914,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); if (!pflip_needed) { - WARN_ON(!dm_plane_state->dc_state); + WARN_ON(!dm_new_plane_state->dc_state); - plane_states_constructed[planes_count] = dm_plane_state->dc_state; + plane_states_constructed[planes_count] = dm_new_plane_state->dc_state; dc_stream_attach = acrtc_state->stream; planes_count++; @@ -3983,10 +3983,10 @@ int amdgpu_dm_atomic_commit( * the ISRs. */ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(old_crtc_state); + struct dm_crtc_state *dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (drm_atomic_crtc_needs_modeset(new_crtc_state) && old_acrtc_state->stream) + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && dm_old_crtc_state->stream) manage_dm_interrupts(adev, acrtc, false); } @@ -4012,7 +4012,7 @@ void amdgpu_dm_atomic_commit_tail( bool wait_for_vblank = true; struct drm_connector *connector; struct drm_connector_state *old_con_state, *new_con_state; - struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -4022,8 +4022,8 @@ void amdgpu_dm_atomic_commit_tail( for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); - old_acrtc_state = to_dm_crtc_state(old_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); DRM_DEBUG_DRIVER( "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " @@ -4041,11 +4041,11 @@ void amdgpu_dm_atomic_commit_tail( * aconnector as needed */ - if (modeset_required(new_crtc_state, new_acrtc_state->stream, old_acrtc_state->stream)) { + if (modeset_required(new_crtc_state, dm_new_crtc_state->stream, dm_old_crtc_state->stream)) { DRM_DEBUG_DRIVER("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); - if (!new_acrtc_state->stream) { + if (!dm_new_crtc_state->stream) { /* * this could happen because of issues with * userspace notifications delivery. @@ -4067,8 +4067,8 @@ void amdgpu_dm_atomic_commit_tail( } - if (old_acrtc_state->stream) - remove_stream(adev, acrtc, old_acrtc_state->stream); + if (dm_old_crtc_state->stream) + remove_stream(adev, acrtc, dm_old_crtc_state->stream); /* @@ -4092,8 +4092,8 @@ void amdgpu_dm_atomic_commit_tail( DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ - if (old_acrtc_state->stream) - remove_stream(adev, acrtc, old_acrtc_state->stream); + if (dm_old_crtc_state->stream) + remove_stream(adev, acrtc, dm_old_crtc_state->stream); } } /* for_each_crtc_in_state() */ @@ -4107,9 +4107,9 @@ void amdgpu_dm_atomic_commit_tail( new_crtc_state = drm_atomic_get_new_crtc_state(state, &new_crtcs[i]->base); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - new_stream = new_acrtc_state->stream; + new_stream = dm_new_crtc_state->stream; aconnector = amdgpu_dm_find_first_crct_matching_connector( state, &new_crtcs[i]->base); @@ -4131,14 +4131,14 @@ void amdgpu_dm_atomic_commit_tail( for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - if (new_acrtc_state->stream != NULL) { + if (dm_new_crtc_state->stream != NULL) { const struct dc_stream_status *status = - dc_stream_get_status(new_acrtc_state->stream); + dc_stream_get_status(dm_new_crtc_state->stream); if (!status) - DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc); + DC_ERR("got no status for stream %p on acrtc%p\n", dm_new_crtc_state->stream, acrtc); else acrtc->otg_inst = status->primary_otg_inst; } @@ -4146,9 +4146,9 @@ void amdgpu_dm_atomic_commit_tail( /* Handle scaling and undersacn changes*/ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { - struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); - struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); struct dc_stream_status *status = NULL; if (acrtc) @@ -4159,19 +4159,19 @@ void amdgpu_dm_atomic_commit_tail( continue; /* Skip any thing not scale or underscan changes */ - if (!is_scaling_state_different(con_new_state, con_old_state)) + if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state)) continue; - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - update_stream_scaling_settings(&con_new_state->base.crtc->mode, - con_new_state, (struct dc_stream_state *)new_acrtc_state->stream); + update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode, + dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream); - status = dc_stream_get_status(new_acrtc_state->stream); + status = dc_stream_get_status(dm_new_crtc_state->stream); WARN_ON(!status); WARN_ON(!status->plane_count); - if (!new_acrtc_state->stream) + if (!dm_new_crtc_state->stream) continue; /*TODO How it works with MPO ?*/ @@ -4179,7 +4179,7 @@ void amdgpu_dm_atomic_commit_tail( dm->dc, status->plane_states, status->plane_count, - new_acrtc_state->stream)) + dm_new_crtc_state->stream)) dm_error("%s: Failed to update stream scaling!\n", __func__); } @@ -4190,20 +4190,20 @@ void amdgpu_dm_atomic_commit_tail( struct amdgpu_crtc *acrtc = new_crtcs[i]; new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); if (adev->dm.freesync_module) mod_freesync_notify_mode_change( - adev->dm.freesync_module, &new_acrtc_state->stream, 1); + adev->dm.freesync_module, &dm_new_crtc_state->stream, 1); manage_dm_interrupts(adev, acrtc, true); } /* update planes when needed per crtc*/ for_each_new_crtc_in_state(state, pcrtc, new_crtc_state, j) { - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - if (new_acrtc_state->stream) + if (dm_new_crtc_state->stream) amdgpu_dm_commit_planes(state, dev, dm, pcrtc, &wait_for_vblank); } @@ -4377,7 +4377,7 @@ static int dm_update_crtcs_state( struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; int i; - struct dm_crtc_state *old_acrtc_state, *new_acrtc_state; + struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); struct dc_stream_state *new_stream; int ret = 0; @@ -4392,8 +4392,8 @@ static int dm_update_crtcs_state( new_stream = NULL; - old_acrtc_state = to_dm_crtc_state(old_crtc_state); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); acrtc = to_amdgpu_crtc(crtc); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc); @@ -4428,8 +4428,7 @@ static int dm_update_crtcs_state( } } - if (dc_is_stream_unchanged(new_stream, - old_acrtc_state->stream)) { + if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream)) { new_crtc_state->mode_changed = false; @@ -4456,7 +4455,7 @@ static int dm_update_crtcs_state( /* Remove stream for any changed/disabled CRTC */ if (!enable) { - if (!old_acrtc_state->stream) + if (!dm_old_crtc_state->stream) goto next_crtc; DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n", @@ -4466,13 +4465,13 @@ static int dm_update_crtcs_state( if (!dc_remove_stream_from_ctx( dc, dm_state->context, - old_acrtc_state->stream)) { + dm_old_crtc_state->stream)) { ret = -EINVAL; goto fail; } - dc_stream_release(old_acrtc_state->stream); - new_acrtc_state->stream = NULL; + dc_stream_release(dm_old_crtc_state->stream); + dm_new_crtc_state->stream = NULL; *lock_and_validation_needed = true; @@ -4482,11 +4481,11 @@ static int dm_update_crtcs_state( goto next_crtc; if (modeset_required(new_crtc_state, new_stream, - old_acrtc_state->stream)) { + dm_old_crtc_state->stream)) { - WARN_ON(new_acrtc_state->stream); + WARN_ON(dm_new_crtc_state->stream); - new_acrtc_state->stream = new_stream; + dm_new_crtc_state->stream = new_stream; dc_stream_retain(new_stream); DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", @@ -4495,7 +4494,7 @@ static int dm_update_crtcs_state( if (!dc_add_stream_to_ctx( dc, dm_state->context, - new_acrtc_state->stream)) { + dm_new_crtc_state->stream)) { ret = -EINVAL; goto fail; } @@ -4528,9 +4527,9 @@ static int dm_update_planes_state( struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; - struct dm_crtc_state *new_acrtc_state, *old_acrtc_state; + struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state; struct dm_atomic_state *dm_state = to_dm_atomic_state(state); - struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state; + struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state; int i ; /* TODO return page_flip_needed() function */ bool pflip_needed = !state->allow_modeset; @@ -4543,8 +4542,8 @@ static int dm_update_planes_state( for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { new_plane_crtc = new_plane_state->crtc; old_plane_crtc = old_plane_state->crtc; - new_dm_plane_state = to_dm_plane_state(new_plane_state); - old_dm_plane_state = to_dm_plane_state(old_plane_state); + dm_new_plane_state = to_dm_plane_state(new_plane_state); + dm_old_plane_state = to_dm_plane_state(old_plane_state); /*TODO Implement atomic check for cursor plane */ if (plane->type == DRM_PLANE_TYPE_CURSOR) @@ -4558,9 +4557,9 @@ static int dm_update_planes_state( old_crtc_state = drm_atomic_get_old_crtc_state( state, old_plane_crtc); - old_acrtc_state = to_dm_crtc_state(old_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); - if (!old_acrtc_state->stream) + if (!dm_old_crtc_state->stream) continue; DRM_DEBUG_DRIVER("Disabling DRM plane: %d on DRM crtc %d\n", @@ -4568,8 +4567,8 @@ static int dm_update_planes_state( if (!dc_remove_plane_from_context( dc, - old_acrtc_state->stream, - old_dm_plane_state->dc_state, + dm_old_crtc_state->stream, + dm_old_plane_state->dc_state, dm_state->context)) { ret = EINVAL; @@ -4577,8 +4576,8 @@ static int dm_update_planes_state( } - dc_plane_state_release(old_dm_plane_state->dc_state); - new_dm_plane_state->dc_state = NULL; + dc_plane_state_release(dm_old_plane_state->dc_state); + dm_new_plane_state->dc_state = NULL; *lock_and_validation_needed = true; @@ -4591,27 +4590,27 @@ static int dm_update_planes_state( continue; new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc); - new_acrtc_state = to_dm_crtc_state(new_crtc_state); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - if (!new_acrtc_state->stream) + if (!dm_new_crtc_state->stream) continue; - WARN_ON(new_dm_plane_state->dc_state); + WARN_ON(dm_new_plane_state->dc_state); - new_dm_plane_state->dc_state = dc_create_plane_state(dc); + dm_new_plane_state->dc_state = dc_create_plane_state(dc); DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", plane->base.id, new_plane_crtc->base.id); - if (!new_dm_plane_state->dc_state) { + if (!dm_new_plane_state->dc_state) { ret = -EINVAL; return ret; } ret = fill_plane_attributes( new_plane_crtc->dev->dev_private, - new_dm_plane_state->dc_state, + dm_new_plane_state->dc_state, new_plane_state, new_crtc_state, false); @@ -4621,8 +4620,8 @@ static int dm_update_planes_state( if (!dc_add_plane_to_context( dc, - new_acrtc_state->stream, - new_dm_plane_state->dc_state, + dm_new_crtc_state->stream, + dm_new_plane_state->dc_state, dm_state->context)) { ret = -EINVAL; @@ -4714,9 +4713,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, * decide how to handle. */ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { - struct dm_connector_state *con_old_state = to_dm_connector_state(old_con_state); - struct dm_connector_state *con_new_state = to_dm_connector_state(new_con_state); - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); + struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); /* Skip any modesets/resets */ if (!acrtc || drm_atomic_crtc_needs_modeset( @@ -4724,7 +4723,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, continue; /* Skip any thing not scale or underscan changes */ - if (!is_scaling_state_different(con_new_state, con_old_state)) + if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state)) continue; lock_and_validation_needed = true; -- GitLab From ebdd27e1a5440cb3f30952d105eb08cadafc431d Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:10 -0400 Subject: [PATCH 1186/2898] drm/amd/display: Fix typo undersacn -> underscan Reviewed-by: Maarten Lankhorst Reviewed-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index de88ee1af438..67222ffac96a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4144,7 +4144,7 @@ void amdgpu_dm_atomic_commit_tail( } } - /* Handle scaling and undersacn changes*/ + /* Handle scaling and underscan changes*/ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); @@ -4707,7 +4707,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - /* Check scaling and undersacn changes*/ + /* Check scaling and underscan changes*/ /*TODO Removed scaling changes validation due to inability to commit * new stream into context w\o causing full reset. Need to * decide how to handle. -- GitLab From 5cc6dcbd45a60be4800cd5cc9a30bcc2e158e6a1 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 12 Oct 2017 17:15:11 -0400 Subject: [PATCH 1187/2898] drm/amd/display: Remove useless pcrtc pointer in amdgpu_dm_atomic_commit_tail. Just use crtc instead. Reviewed-by: Maarten Lankhorst Reviewed-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 67222ffac96a..f9b57697be70 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4004,7 +4004,7 @@ void amdgpu_dm_atomic_commit_tail( struct dm_atomic_state *dm_state; uint32_t i, j; uint32_t new_crtcs_count = 0; - struct drm_crtc *crtc, *pcrtc; + struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct amdgpu_crtc *new_crtcs[MAX_STREAMS]; struct dc_stream_state *new_stream = NULL; @@ -4200,11 +4200,11 @@ void amdgpu_dm_atomic_commit_tail( } /* update planes when needed per crtc*/ - for_each_new_crtc_in_state(state, pcrtc, new_crtc_state, j) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, j) { dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); if (dm_new_crtc_state->stream) - amdgpu_dm_commit_planes(state, dev, dm, pcrtc, &wait_for_vblank); + amdgpu_dm_commit_planes(state, dev, dm, crtc, &wait_for_vblank); } -- GitLab From 1daf8c63480b35b967a63a40457c1b0ad866ee81 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 13 Oct 2017 14:04:26 -0400 Subject: [PATCH 1188/2898] drm/amd/display: fix typo in function name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s/amdgpu_dm_find_first_crct_matching_connector/ amdgpu_dm_find_first_crtc_matching_connector/ And while here, make it static. Reviewed-by: Harry Wentland Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++++----- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 5 ----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f9b57697be70..c2031eb5833f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -568,9 +568,9 @@ static int dm_suspend(void *handle) return ret; } -struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( - struct drm_atomic_state *state, - struct drm_crtc *crtc) +static struct amdgpu_dm_connector * +amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state, + struct drm_crtc *crtc) { uint32_t i; struct drm_connector_state *new_con_state; @@ -4110,7 +4110,7 @@ void amdgpu_dm_atomic_commit_tail( dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); new_stream = dm_new_crtc_state->stream; - aconnector = amdgpu_dm_find_first_crct_matching_connector( + aconnector = amdgpu_dm_find_first_crtc_matching_connector( state, &new_crtcs[i]->base); if (!aconnector) { @@ -4396,7 +4396,7 @@ static int dm_update_crtcs_state( dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); acrtc = to_amdgpu_crtc(crtc); - aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc); + aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc); /* TODO This hack should go away */ if (aconnector) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 1c55a0b5cd15..aca061aa4643 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -226,11 +226,6 @@ extern const struct amdgpu_ip_block_version dm_ip_block; void amdgpu_dm_update_connector_after_detect( struct amdgpu_dm_connector *aconnector); -struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector( - struct drm_atomic_state *state, - struct drm_crtc *crtc); - - struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; -- GitLab From 3ee6b26b78e47825032726f807beb70be86ea20a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Oct 2017 17:44:52 -0400 Subject: [PATCH 1189/2898] drm/amd/display: whitespace cleanup in amdgpu_dm.c/h To match kernel standards. No intended functional change. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 330 ++++++++---------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 91 +++-- 2 files changed, 192 insertions(+), 229 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c2031eb5833f..f282fe8d5089 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -127,7 +127,7 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) } static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, - u32 *vbl, u32 *position) + u32 *vbl, u32 *position) { uint32_t v_blank_start, v_blank_end, h_position, v_position; @@ -184,9 +184,9 @@ static int dm_soft_reset(void *handle) return 0; } -static struct amdgpu_crtc *get_crtc_by_otg_inst( - struct amdgpu_device *adev, - int otg_inst) +static struct amdgpu_crtc * +get_crtc_by_otg_inst(struct amdgpu_device *adev, + int otg_inst) { struct drm_device *dev = adev->ddev; struct drm_crtc *crtc; @@ -738,8 +738,8 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { .atomic_commit_tail = amdgpu_dm_atomic_commit_tail }; -void amdgpu_dm_update_connector_after_detect( - struct amdgpu_dm_connector *aconnector) +void +amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) { struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; @@ -1490,11 +1490,10 @@ static const struct amdgpu_display_funcs dm_display_funcs = { #if defined(CONFIG_DEBUG_KERNEL_DC) -static ssize_t s3_debug_store( - struct device *device, - struct device_attribute *attr, - const char *buf, - size_t count) +static ssize_t s3_debug_store(struct device *device, + struct device_attribute *attr, + const char *buf, + size_t count) { int ret; int s3_state; @@ -1670,9 +1669,8 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { .destroy = amdgpu_dm_encoder_destroy, }; -static bool fill_rects_from_plane_state( - const struct drm_plane_state *state, - struct dc_plane_state *plane_state) +static bool fill_rects_from_plane_state(const struct drm_plane_state *state, + struct dc_plane_state *plane_state) { plane_state->src_rect.x = state->src_x >> 16; plane_state->src_rect.y = state->src_y >> 16; @@ -1721,10 +1719,9 @@ static bool fill_rects_from_plane_state( return true; } -static int get_fb_info( - const struct amdgpu_framebuffer *amdgpu_fb, - uint64_t *tiling_flags, - uint64_t *fb_location) +static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, + uint64_t *tiling_flags, + uint64_t *fb_location) { struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj); int r = amdgpu_bo_reserve(rbo, false); @@ -1745,10 +1742,10 @@ static int get_fb_info( return r; } -static int fill_plane_attributes_from_fb( - struct amdgpu_device *adev, - struct dc_plane_state *plane_state, - const struct amdgpu_framebuffer *amdgpu_fb, bool addReq) +static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, + struct dc_plane_state *plane_state, + const struct amdgpu_framebuffer *amdgpu_fb, + bool addReq) { uint64_t tiling_flags; uint64_t fb_location = 0; @@ -1897,9 +1894,8 @@ static int fill_plane_attributes_from_fb( } -static void fill_gamma_from_crtc_state( - const struct drm_crtc_state *crtc_state, - struct dc_plane_state *plane_state) +static void fill_gamma_from_crtc_state(const struct drm_crtc_state *crtc_state, + struct dc_plane_state *plane_state) { int i; struct dc_gamma *gamma; @@ -1924,12 +1920,11 @@ static void fill_gamma_from_crtc_state( plane_state->gamma_correction = gamma; } -static int fill_plane_attributes( - struct amdgpu_device *adev, - struct dc_plane_state *dc_plane_state, - struct drm_plane_state *plane_state, - struct drm_crtc_state *crtc_state, - bool addrReq) +static int fill_plane_attributes(struct amdgpu_device *adev, + struct dc_plane_state *dc_plane_state, + struct drm_plane_state *plane_state, + struct drm_crtc_state *crtc_state, + bool addrReq) { const struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(plane_state->fb); @@ -1968,8 +1963,8 @@ static int fill_plane_attributes( /*****************************************************************************/ -struct amdgpu_dm_connector *aconnector_from_drm_crtc_id( - const struct drm_crtc *crtc) +struct amdgpu_dm_connector * +aconnector_from_drm_crtc_id(const struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_connector *connector; @@ -1992,10 +1987,9 @@ struct amdgpu_dm_connector *aconnector_from_drm_crtc_id( return NULL; } -static void update_stream_scaling_settings( - const struct drm_display_mode *mode, - const struct dm_connector_state *dm_state, - struct dc_stream_state *stream) +static void update_stream_scaling_settings(const struct drm_display_mode *mode, + const struct dm_connector_state *dm_state, + struct dc_stream_state *stream) { enum amdgpu_rmx_type rmx_type; @@ -2046,8 +2040,8 @@ static void update_stream_scaling_settings( } -static enum dc_color_depth convert_color_depth_from_display_info( - const struct drm_connector *connector) +static enum dc_color_depth +convert_color_depth_from_display_info(const struct drm_connector *connector) { uint32_t bpc = connector->display_info.bpc; @@ -2081,8 +2075,8 @@ static enum dc_color_depth convert_color_depth_from_display_info( } } -static enum dc_aspect_ratio get_aspect_ratio( - const struct drm_display_mode *mode_in) +static enum dc_aspect_ratio +get_aspect_ratio(const struct drm_display_mode *mode_in) { int32_t width = mode_in->crtc_hdisplay * 9; int32_t height = mode_in->crtc_vdisplay * 16; @@ -2093,8 +2087,8 @@ static enum dc_aspect_ratio get_aspect_ratio( return ASPECT_RATIO_4_3; } -static enum dc_color_space get_output_color_space( - const struct dc_crtc_timing *dc_crtc_timing) +static enum dc_color_space +get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing) { enum dc_color_space color_space = COLOR_SPACE_SRGB; @@ -2138,10 +2132,10 @@ static enum dc_color_space get_output_color_space( /*****************************************************************************/ -static void fill_stream_properties_from_drm_display_mode( - struct dc_stream_state *stream, - const struct drm_display_mode *mode_in, - const struct drm_connector *connector) +static void +fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, + const struct drm_display_mode *mode_in, + const struct drm_connector *connector) { struct dc_crtc_timing *timing_out = &stream->timing; @@ -2196,10 +2190,9 @@ static void fill_stream_properties_from_drm_display_mode( } } -static void fill_audio_info( - struct audio_info *audio_info, - const struct drm_connector *drm_connector, - const struct dc_sink *dc_sink) +static void fill_audio_info(struct audio_info *audio_info, + const struct drm_connector *drm_connector, + const struct dc_sink *dc_sink) { int i = 0; int cea_revision = 0; @@ -2244,9 +2237,9 @@ static void fill_audio_info( } -static void copy_crtc_timing_for_drm_display_mode( - const struct drm_display_mode *src_mode, - struct drm_display_mode *dst_mode) +static void +copy_crtc_timing_for_drm_display_mode(const struct drm_display_mode *src_mode, + struct drm_display_mode *dst_mode) { dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay; dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay; @@ -2264,10 +2257,10 @@ static void copy_crtc_timing_for_drm_display_mode( dst_mode->crtc_vtotal = src_mode->crtc_vtotal; } -static void decide_crtc_timing_for_drm_display_mode( - struct drm_display_mode *drm_mode, - const struct drm_display_mode *native_mode, - bool scale_enabled) +static void +decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode, + const struct drm_display_mode *native_mode, + bool scale_enabled) { if (scale_enabled) { copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); @@ -2299,10 +2292,10 @@ static void create_fake_sink(struct amdgpu_dm_connector *aconnector) aconnector->dc_link->local_sink = sink; } -static struct dc_stream_state *create_stream_for_sink( - struct amdgpu_dm_connector *aconnector, - const struct drm_display_mode *drm_mode, - const struct dm_connector_state *dm_state) +static struct dc_stream_state * +create_stream_for_sink(struct amdgpu_dm_connector *aconnector, + const struct drm_display_mode *drm_mode, + const struct dm_connector_state *dm_state) { struct drm_display_mode *preferred_mode = NULL; const struct drm_connector *drm_connector; @@ -2380,7 +2373,7 @@ void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) } static void dm_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) + struct drm_crtc_state *state) { struct dm_crtc_state *cur = to_dm_crtc_state(state); @@ -2466,11 +2459,10 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) connector_status_disconnected); } -int amdgpu_dm_connector_atomic_set_property( - struct drm_connector *connector, - struct drm_connector_state *connector_state, - struct drm_property *property, - uint64_t val) +int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, + struct drm_connector_state *connector_state, + struct drm_property *property, + uint64_t val) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; @@ -2519,11 +2511,10 @@ int amdgpu_dm_connector_atomic_set_property( return ret; } -int amdgpu_dm_connector_atomic_get_property( - struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val) +int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; @@ -2605,8 +2596,8 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) } } -struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( - struct drm_connector *connector) +struct drm_connector_state * +amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) { struct dm_connector_state *state = to_dm_connector_state(connector->state); @@ -2711,9 +2702,8 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector) create_eml_sink(aconnector); } -int amdgpu_dm_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode) +int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) { int result = MODE_ERROR; struct dc_sink *dc_sink; @@ -2780,9 +2770,8 @@ static void dm_crtc_helper_disable(struct drm_crtc *crtc) { } -static int dm_crtc_helper_atomic_check( - struct drm_crtc *crtc, - struct drm_crtc_state *state) +static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) { struct amdgpu_device *adev = crtc->dev->dev_private; struct dc *dc = adev->dm.dc; @@ -2805,10 +2794,9 @@ static int dm_crtc_helper_atomic_check( return ret; } -static bool dm_crtc_helper_mode_fixup( - struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static bool dm_crtc_helper_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return true; } @@ -2824,10 +2812,9 @@ static void dm_encoder_helper_disable(struct drm_encoder *encoder) } -static int dm_encoder_helper_atomic_check( - struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) +static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { return 0; } @@ -2875,7 +2862,7 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) } void dm_drm_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_plane_state *state) { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); @@ -2894,9 +2881,8 @@ static const struct drm_plane_funcs dm_plane_funcs = { .atomic_destroy_state = dm_drm_plane_destroy_state, }; -static int dm_plane_helper_prepare_fb( - struct drm_plane *plane, - struct drm_plane_state *new_state) +static int dm_plane_helper_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) { struct amdgpu_framebuffer *afb; struct drm_gem_object *obj; @@ -2964,9 +2950,8 @@ static int dm_plane_helper_prepare_fb( return 0; } -static void dm_plane_helper_cleanup_fb( - struct drm_plane *plane, - struct drm_plane_state *old_state) +static void dm_plane_helper_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) { struct amdgpu_bo *rbo; struct amdgpu_framebuffer *afb; @@ -2989,7 +2974,8 @@ static void dm_plane_helper_cleanup_fb( } int dm_create_validation_set_for_connector(struct drm_connector *connector, - struct drm_display_mode *mode, struct dc_validation_set *val_set) + struct drm_display_mode *mode, + struct dc_validation_set *val_set) { int result = MODE_ERROR; struct dc_sink *dc_sink = @@ -3027,7 +3013,7 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, } int dm_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) + struct drm_plane_state *state) { struct amdgpu_device *adev = plane->dev->dev_private; struct dc *dc = adev->dm.dc; @@ -3075,8 +3061,8 @@ static const u32 cursor_formats[] = { }; int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs) + struct amdgpu_plane *aplane, + unsigned long possible_crtcs) { int res = -EPERM; @@ -3224,9 +3210,10 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector) } } -static struct drm_display_mode *amdgpu_dm_create_common_mode( - struct drm_encoder *encoder, char *name, - int hdisplay, int vdisplay) +static struct drm_display_mode * +amdgpu_dm_create_common_mode(struct drm_encoder *encoder, + char *name, + int hdisplay, int vdisplay) { struct drm_device *dev = encoder->dev; struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); @@ -3248,7 +3235,7 @@ static struct drm_display_mode *amdgpu_dm_create_common_mode( } static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, - struct drm_connector *connector) + struct drm_connector *connector) { struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_display_mode *mode = NULL; @@ -3306,9 +3293,8 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, } } -static void amdgpu_dm_connector_ddc_get_modes( - struct drm_connector *connector, - struct edid *edid) +static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, + struct edid *edid) { struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); @@ -3342,12 +3328,11 @@ int amdgpu_dm_connector_get_modes(struct drm_connector *connector) return amdgpu_dm_connector->num_modes; } -void amdgpu_dm_connector_init_helper( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, - int connector_type, - struct dc_link *link, - int link_index) +void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, + int connector_type, + struct dc_link *link, + int link_index) { struct amdgpu_device *adev = dm->ddev->dev_private; @@ -3395,7 +3380,7 @@ void amdgpu_dm_connector_init_helper( } int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) + struct i2c_msg *msgs, int num) { struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); struct ddc_service *ddc_service = i2c->ddc_service; @@ -3439,10 +3424,10 @@ static const struct i2c_algorithm amdgpu_dm_i2c_algo = { .functionality = amdgpu_dm_i2c_func, }; -static struct amdgpu_i2c_adapter *create_i2c( - struct ddc_service *ddc_service, - int link_index, - int *res) +static struct amdgpu_i2c_adapter * +create_i2c(struct ddc_service *ddc_service, + int link_index, + int *res) { struct amdgpu_device *adev = ddc_service->ctx->driver_context; struct amdgpu_i2c_adapter *i2c; @@ -3462,11 +3447,10 @@ static struct amdgpu_i2c_adapter *create_i2c( /* Note: this function assumes that dc_link_detect() was called for the * dc_link which will be represented by this aconnector. */ -int amdgpu_dm_connector_init( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, - uint32_t link_index, - struct amdgpu_encoder *aencoder) +int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, + uint32_t link_index, + struct amdgpu_encoder *aencoder) { int res = 0; int connector_type; @@ -3569,10 +3553,9 @@ int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) } } -int amdgpu_dm_encoder_init( - struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index) +int amdgpu_dm_encoder_init(struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index) { struct amdgpu_device *adev = dev->dev_private; @@ -3594,10 +3577,9 @@ int amdgpu_dm_encoder_init( return res; } -static void manage_dm_interrupts( - struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - bool enable) +static void manage_dm_interrupts(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + bool enable) { /* * this is not correct translation but will work as soon as VBLANK @@ -3624,9 +3606,9 @@ static void manage_dm_interrupts( } } -static bool is_scaling_state_different( - const struct dm_connector_state *dm_state, - const struct dm_connector_state *old_dm_state) +static bool +is_scaling_state_different(const struct dm_connector_state *dm_state, + const struct dm_connector_state *old_dm_state) { if (dm_state->scaling != old_dm_state->scaling) return true; @@ -3642,10 +3624,9 @@ static bool is_scaling_state_different( return false; } -static void remove_stream( - struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - struct dc_stream_state *stream) +static void remove_stream(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc, + struct dc_stream_state *stream) { /* this is the update mode case */ if (adev->dm.freesync_module) @@ -3656,7 +3637,7 @@ static void remove_stream( } int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, - struct dc_cursor_position *position) + struct dc_cursor_position *position) { struct amdgpu_crtc *amdgpu_crtc = amdgpu_crtc = to_amdgpu_crtc(crtc); int x, y; @@ -3700,9 +3681,8 @@ int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, return 0; } -static void handle_cursor_update( - struct drm_plane *plane, - struct drm_plane_state *old_plane_state) +static void handle_cursor_update(struct drm_plane *plane, + struct drm_plane_state *old_plane_state) { struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; @@ -3780,10 +3760,9 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc) * * Waits on all BO's fences and for proper vblank count */ -static void amdgpu_dm_do_flip( - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - uint32_t target) +static void amdgpu_dm_do_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + uint32_t target) { unsigned long flags; uint32_t target_vblank; @@ -3866,10 +3845,10 @@ static void amdgpu_dm_do_flip( } static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, - struct drm_device *dev, - struct amdgpu_display_manager *dm, - struct drm_crtc *pcrtc, - bool *wait_for_vblank) + struct drm_device *dev, + struct amdgpu_display_manager *dm, + struct drm_crtc *pcrtc, + bool *wait_for_vblank) { uint32_t i; struct drm_plane *plane; @@ -3965,10 +3944,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, } -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) +int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -3995,8 +3973,7 @@ int amdgpu_dm_atomic_commit( /*TODO Handle EINTR, reenable IRQ*/ } -void amdgpu_dm_atomic_commit_tail( - struct drm_atomic_state *state) +void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; @@ -4294,7 +4271,8 @@ static int dm_force_atomic_commit(struct drm_connector *connector) * This include when the same display is unplugged then plugged back into the * same port and when we are running without usermode desktop manager supprot */ -void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector) +void dm_restore_drm_connector_state(struct drm_device *dev, + struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_crtc *disconnected_acrtc; @@ -4322,9 +4300,8 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector * Grabs all modesetting locks to serialize against any blocking commits, * Waits for completion of all non blocking commits. */ -static int do_aquire_global_lock( - struct drm_device *dev, - struct drm_atomic_state *state) +static int do_aquire_global_lock(struct drm_device *dev, + struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_commit *commit; @@ -4368,11 +4345,10 @@ static int do_aquire_global_lock( return ret < 0 ? ret : 0; } -static int dm_update_crtcs_state( - struct dc *dc, - struct drm_atomic_state *state, - bool enable, - bool *lock_and_validation_needed) +static int dm_update_crtcs_state(struct dc *dc, + struct drm_atomic_state *state, + bool enable, + bool *lock_and_validation_needed) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -4517,11 +4493,10 @@ static int dm_update_crtcs_state( return ret; } -static int dm_update_planes_state( - struct dc *dc, - struct drm_atomic_state *state, - bool enable, - bool *lock_and_validation_needed) +static int dm_update_planes_state(struct dc *dc, + struct drm_atomic_state *state, + bool enable, + bool *lock_and_validation_needed) { struct drm_crtc *new_plane_crtc, *old_plane_crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -4637,7 +4612,7 @@ static int dm_update_planes_state( } int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) + struct drm_atomic_state *state) { int i; int ret; @@ -4766,9 +4741,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, return ret; } -static bool is_dp_capable_without_timing_msa( - struct dc *dc, - struct amdgpu_dm_connector *amdgpu_dm_connector) +static bool is_dp_capable_without_timing_msa(struct dc *dc, + struct amdgpu_dm_connector *amdgpu_dm_connector) { uint8_t dpcd_data; bool capable = false; @@ -4785,9 +4759,8 @@ static bool is_dp_capable_without_timing_msa( return capable; } -void amdgpu_dm_add_sink_to_freesync_module( - struct drm_connector *connector, - struct edid *edid) +void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector, + struct edid *edid) { int i; uint64_t val_capable; @@ -4867,8 +4840,7 @@ void amdgpu_dm_add_sink_to_freesync_module( } -void amdgpu_dm_remove_sink_from_freesync_module( - struct drm_connector *connector) +void amdgpu_dm_remove_sink_from_freesync_module(struct drm_connector *connector) { /* * TODO fill in once we figure out how to deal with freesync in diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index aca061aa4643..eb20642403ae 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -206,12 +206,10 @@ void amdgpu_dm_destroy(void); * * Returns 0 on success */ -int amdgpu_dm_initialize_drm_device( - struct amdgpu_device *adev); +int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev); /* removes and deallocates the drm structures, created by the above function */ -void amdgpu_dm_destroy_drm_device( - struct amdgpu_display_manager *dm); +void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm); /* Locking/Mutex */ bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm); @@ -223,8 +221,8 @@ void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm); extern const struct amdgpu_ip_block_version dm_ip_block; -void amdgpu_dm_update_connector_after_detect( - struct amdgpu_dm_connector *aconnector); +void +amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector); struct amdgpu_framebuffer; struct amdgpu_display_manager; @@ -256,19 +254,18 @@ struct dm_atomic_state { /*TODO Jodan Hersen use the one in amdgpu_dm*/ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs); + struct amdgpu_plane *aplane, + unsigned long possible_crtcs); int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, uint32_t link_index); int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *amdgpu_dm_connector, - uint32_t link_index, - struct amdgpu_encoder *amdgpu_encoder); -int amdgpu_dm_encoder_init( - struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index); + struct amdgpu_dm_connector *amdgpu_dm_connector, + uint32_t link_index, + struct amdgpu_encoder *amdgpu_encoder); +int amdgpu_dm_encoder_init(struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index); void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); void amdgpu_dm_connector_destroy(struct drm_connector *connector); @@ -276,53 +273,47 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); int amdgpu_dm_connector_get_modes(struct drm_connector *connector); -int amdgpu_dm_atomic_commit( - struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock); +int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); -void amdgpu_dm_atomic_commit_tail( - struct drm_atomic_state *state); +void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state); int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state); + struct drm_atomic_state *state); void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); -struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state( - struct drm_connector *connector); -int amdgpu_dm_connector_atomic_set_property( - struct drm_connector *connector, - struct drm_connector_state *state, - struct drm_property *property, - uint64_t val); - -int amdgpu_dm_connector_atomic_get_property( - struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, - uint64_t *val); +struct drm_connector_state * +amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector); +int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val); + +int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val); int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev); -void amdgpu_dm_connector_init_helper( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, - int connector_type, - struct dc_link *link, - int link_index); +void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, + int connector_type, + struct dc_link *link, + int link_index); -int amdgpu_dm_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode); +int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode); -void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector); +void dm_restore_drm_connector_state(struct drm_device *dev, + struct drm_connector *connector); -void amdgpu_dm_add_sink_to_freesync_module( - struct drm_connector *connector, - struct edid *edid); +void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector, + struct edid *edid); -void amdgpu_dm_remove_sink_from_freesync_module( - struct drm_connector *connector); +void +amdgpu_dm_remove_sink_from_freesync_module(struct drm_connector *connector); extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; -- GitLab From 7578ecda14d521f39e74166103270c62b15af96d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Oct 2017 17:51:02 -0400 Subject: [PATCH 1190/2898] drm/amd/display: make a bunch of stuff in amdgpu_dm.c static Not used outside of that file. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 136 ++++++++++++------ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 59 -------- 2 files changed, 91 insertions(+), 104 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f282fe8d5089..051cb371e88b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -70,6 +70,50 @@ #include "i2caux_interface.h" +/* basic init/fini API */ +static int amdgpu_dm_init(struct amdgpu_device *adev); +static void amdgpu_dm_fini(struct amdgpu_device *adev); + +/* initializes drm_device display related structures, based on the information + * provided by DAL. The drm strcutures are: drm_crtc, drm_connector, + * drm_encoder, drm_mode_config + * + * Returns 0 on success + */ +static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev); +/* removes and deallocates the drm structures, created by the above function */ +static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm); + +static void +amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector); + +static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs); +static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t link_index); +static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *amdgpu_dm_connector, + uint32_t link_index, + struct amdgpu_encoder *amdgpu_encoder); +static int amdgpu_dm_encoder_init(struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index); + +static int amdgpu_dm_connector_get_modes(struct drm_connector *connector); + +static int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); + +static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state); + +static int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state); + + + static const enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { DRM_PLANE_TYPE_PRIMARY, @@ -306,7 +350,7 @@ static void hotplug_notify_work_func(struct work_struct *work) /* TODO: Dynamic allocation */ #define AMDGPU_FBC_SIZE (3840 * 2160 * 4) -void amdgpu_dm_initialize_fbc(struct amdgpu_device *adev) +static void amdgpu_dm_initialize_fbc(struct amdgpu_device *adev) { int r; struct dm_comressor_info *compressor = &adev->dm.compressor; @@ -328,7 +372,7 @@ void amdgpu_dm_initialize_fbc(struct amdgpu_device *adev) * * Returns 0 on success */ -int amdgpu_dm_init(struct amdgpu_device *adev) +static int amdgpu_dm_init(struct amdgpu_device *adev) { struct dc_init_data init_data; adev->dm.ddev = adev->ddev; @@ -431,7 +475,7 @@ int amdgpu_dm_init(struct amdgpu_device *adev) return -1; } -void amdgpu_dm_fini(struct amdgpu_device *adev) +static void amdgpu_dm_fini(struct amdgpu_device *adev) { amdgpu_dm_destroy_drm_device(&adev->dm); /* @@ -455,7 +499,7 @@ void amdgpu_dm_fini(struct amdgpu_device *adev) } /* moved from amdgpu_dm_kms.c */ -void amdgpu_dm_destroy() +static void amdgpu_dm_destroy(void) { } @@ -685,7 +729,7 @@ const struct amdgpu_ip_block_version dm_ip_block = }; -struct drm_atomic_state * +static struct drm_atomic_state * dm_atomic_state_alloc(struct drm_device *dev) { struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); @@ -738,7 +782,7 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { .atomic_commit_tail = amdgpu_dm_atomic_commit_tail }; -void +static void amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) { struct drm_connector *connector = &aconnector->base; @@ -1245,7 +1289,8 @@ static const struct backlight_ops amdgpu_dm_backlight_ops = { .update_status = amdgpu_dm_backlight_update_status, }; -void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) +static void +amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) { char bl_name[16]; struct backlight_properties props = { 0 }; @@ -1277,7 +1322,7 @@ void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) * * Returns 0 on success */ -int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) +static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) { struct amdgpu_display_manager *dm = &adev->dm; uint32_t i; @@ -1410,7 +1455,7 @@ int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) return -1; } -void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) +static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) { drm_mode_config_cleanup(dm->ddev); return; @@ -1613,13 +1658,13 @@ static int dm_early_init(void *handle) return 0; } -bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) +static bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) { /* TODO */ return true; } -bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) +static bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) { /* TODO */ return true; @@ -1659,7 +1704,7 @@ static bool modereset_required(struct drm_crtc_state *crtc_state) return !crtc_state->enable || !crtc_state->active; } -void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) +static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) { drm_encoder_cleanup(encoder); kfree(encoder); @@ -1963,7 +2008,7 @@ static int fill_plane_attributes(struct amdgpu_device *adev, /*****************************************************************************/ -struct amdgpu_dm_connector * +static struct amdgpu_dm_connector * aconnector_from_drm_crtc_id(const struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -2366,7 +2411,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, return stream; } -void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) +static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) { drm_crtc_cleanup(crtc); kfree(crtc); @@ -2552,7 +2597,7 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, return ret; } -void amdgpu_dm_connector_destroy(struct drm_connector *connector) +static void amdgpu_dm_connector_destroy(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); const struct dc_link *link = aconnector->dc_link; @@ -2973,9 +3018,10 @@ static void dm_plane_helper_cleanup_fb(struct drm_plane *plane, amdgpu_bo_unref(&rbo); } -int dm_create_validation_set_for_connector(struct drm_connector *connector, - struct drm_display_mode *mode, - struct dc_validation_set *val_set) +static int +dm_create_validation_set_for_connector(struct drm_connector *connector, + struct drm_display_mode *mode, + struct dc_validation_set *val_set) { int result = MODE_ERROR; struct dc_sink *dc_sink = @@ -3012,8 +3058,8 @@ int dm_create_validation_set_for_connector(struct drm_connector *connector, return MODE_OK; } -int dm_plane_atomic_check(struct drm_plane *plane, - struct drm_plane_state *state) +static int dm_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) { struct amdgpu_device *adev = plane->dev->dev_private; struct dc *dc = adev->dm.dc; @@ -3060,9 +3106,9 @@ static const u32 cursor_formats[] = { DRM_FORMAT_ARGB8888 }; -int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs) +static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, + struct amdgpu_plane *aplane, + unsigned long possible_crtcs) { int res = -EPERM; @@ -3106,9 +3152,9 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, return res; } -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct drm_plane *plane, - uint32_t crtc_index) +static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, + struct drm_plane *plane, + uint32_t crtc_index) { struct amdgpu_crtc *acrtc = NULL; struct amdgpu_plane *cursor_plane; @@ -3312,7 +3358,7 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, amdgpu_dm_connector->num_modes = 0; } -int amdgpu_dm_connector_get_modes(struct drm_connector *connector) +static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) { const struct drm_connector_helper_funcs *helper = connector->helper_private; @@ -3379,8 +3425,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, } -int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) +static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) { struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); struct ddc_service *ddc_service = i2c->ddc_service; @@ -3414,7 +3460,7 @@ int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, return result; } -u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) +static u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } @@ -3447,10 +3493,10 @@ create_i2c(struct ddc_service *ddc_service, /* Note: this function assumes that dc_link_detect() was called for the * dc_link which will be represented by this aconnector. */ -int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, - uint32_t link_index, - struct amdgpu_encoder *aencoder) +static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, + uint32_t link_index, + struct amdgpu_encoder *aencoder) { int res = 0; int connector_type; @@ -3553,9 +3599,9 @@ int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev) } } -int amdgpu_dm_encoder_init(struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index) +static int amdgpu_dm_encoder_init(struct drm_device *dev, + struct amdgpu_encoder *aencoder, + uint32_t link_index) { struct amdgpu_device *adev = dev->dev_private; @@ -3636,8 +3682,8 @@ static void remove_stream(struct amdgpu_device *adev, acrtc->enabled = false; } -int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, - struct dc_cursor_position *position) +static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, + struct dc_cursor_position *position) { struct amdgpu_crtc *amdgpu_crtc = amdgpu_crtc = to_amdgpu_crtc(crtc); int x, y; @@ -3944,9 +3990,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, } -int amdgpu_dm_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) +static int amdgpu_dm_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -3973,7 +4019,7 @@ int amdgpu_dm_atomic_commit(struct drm_device *dev, /*TODO Handle EINTR, reenable IRQ*/ } -void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) +static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; struct amdgpu_device *adev = dev->dev_private; @@ -4611,8 +4657,8 @@ static int dm_update_planes_state(struct dc *dc, return ret; } -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) +static int amdgpu_dm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) { int i; int ret; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index eb20642403ae..be3b70d683e7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -193,37 +193,8 @@ struct amdgpu_dm_connector { #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) -/* basic init/fini API */ -int amdgpu_dm_init(struct amdgpu_device *adev); - -void amdgpu_dm_fini(struct amdgpu_device *adev); - -void amdgpu_dm_destroy(void); - -/* initializes drm_device display related structures, based on the information - * provided by DAL. The drm strcutures are: drm_crtc, drm_connector, - * drm_encoder, drm_mode_config - * - * Returns 0 on success - */ -int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev); - -/* removes and deallocates the drm structures, created by the above function */ -void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm); - -/* Locking/Mutex */ -bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm); - -bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm); - -/* Register "Backlight device" accessible by user-mode. */ -void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm); - extern const struct amdgpu_ip_block_version dm_ip_block; -void -amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector); - struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; @@ -252,36 +223,6 @@ struct dm_atomic_state { #define to_dm_atomic_state(x) container_of(x, struct dm_atomic_state, base) -/*TODO Jodan Hersen use the one in amdgpu_dm*/ -int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, - struct amdgpu_plane *aplane, - unsigned long possible_crtcs); -int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, - struct drm_plane *plane, - uint32_t link_index); -int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *amdgpu_dm_connector, - uint32_t link_index, - struct amdgpu_encoder *amdgpu_encoder); -int amdgpu_dm_encoder_init(struct drm_device *dev, - struct amdgpu_encoder *aencoder, - uint32_t link_index); - -void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc); -void amdgpu_dm_connector_destroy(struct drm_connector *connector); -void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); - -int amdgpu_dm_connector_get_modes(struct drm_connector *connector); - -int amdgpu_dm_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock); - -void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state); - -int amdgpu_dm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state); - void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector); struct drm_connector_state * amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector); -- GitLab From b4133c09e47afe4c2a5485eb33c7cf456ce0241f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Oct 2017 17:53:24 -0400 Subject: [PATCH 1191/2898] drm/amd/display: drop unused functions in amdgpu_dm.c Not used anywhere. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 82 ------------------- 1 file changed, 82 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 051cb371e88b..e98bb639268d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -498,11 +498,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) return; } -/* moved from amdgpu_dm_kms.c */ -static void amdgpu_dm_destroy(void) -{ -} - static int dm_sw_init(void *handle) { return 0; @@ -1658,19 +1653,6 @@ static int dm_early_init(void *handle) return 0; } -static bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm) -{ - /* TODO */ - return true; -} - -static bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm) -{ - /* TODO */ - return true; -} - - struct dm_connector_state { struct drm_connector_state base; @@ -2008,30 +1990,6 @@ static int fill_plane_attributes(struct amdgpu_device *adev, /*****************************************************************************/ -static struct amdgpu_dm_connector * -aconnector_from_drm_crtc_id(const struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_connector *connector; - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_dm_connector *aconnector; - - list_for_each_entry(connector, - &dev->mode_config.connector_list, head) { - - aconnector = to_amdgpu_dm_connector(connector); - - if (aconnector->base.state->crtc != &acrtc->base) - continue; - - /* Found the connector */ - return aconnector; - } - - /* If we get here, not found. */ - return NULL; -} - static void update_stream_scaling_settings(const struct drm_display_mode *mode, const struct dm_connector_state *dm_state, struct dc_stream_state *stream) @@ -3018,46 +2976,6 @@ static void dm_plane_helper_cleanup_fb(struct drm_plane *plane, amdgpu_bo_unref(&rbo); } -static int -dm_create_validation_set_for_connector(struct drm_connector *connector, - struct drm_display_mode *mode, - struct dc_validation_set *val_set) -{ - int result = MODE_ERROR; - struct dc_sink *dc_sink = - to_amdgpu_dm_connector(connector)->dc_sink; - /* TODO: Unhardcode stream count */ - struct dc_stream_state *stream; - - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || - (mode->flags & DRM_MODE_FLAG_DBLSCAN)) - return result; - - if (dc_sink == NULL) { - DRM_ERROR("dc_sink is NULL!\n"); - return result; - } - - stream = dc_create_stream_for_sink(dc_sink); - - if (stream == NULL) { - DRM_ERROR("Failed to create stream for sink!\n"); - return result; - } - - drm_mode_set_crtcinfo(mode, 0); - - fill_stream_properties_from_drm_display_mode(stream, mode, connector); - - val_set->stream = stream; - - stream->src.width = mode->hdisplay; - stream->src.height = mode->vdisplay; - stream->dst = stream->src; - - return MODE_OK; -} - static int dm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { -- GitLab From 8ceb1cab8ec4d0beeac42714e27eb681f0afdd1d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 10 Oct 2017 18:33:14 -0400 Subject: [PATCH 1192/2898] drm/amd/display: drop unused functions in amdgpu_dm_services.c not used. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/amdgpu_dm/amdgpu_dm_services.c | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index aefd9ebc7bce..fc0668b2300c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -35,47 +35,6 @@ #include "amdgpu_dm_irq.h" #include "amdgpu_pm.h" -/****************************************************************************** - * IRQ Interfaces. - *****************************************************************************/ - -void dal_register_timer_interrupt( - struct dc_context *ctx, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args) -{ - struct amdgpu_device *adev = ctx->driver_context; - - if (!adev || !int_params) { - DRM_ERROR("DM_IRQ: invalid input!\n"); - return; - } - - if (int_params->int_context != INTERRUPT_LOW_IRQ_CONTEXT) { - /* only low irq ctx is supported. */ - DRM_ERROR("DM_IRQ: invalid context: %d!\n", - int_params->int_context); - return; - } - - amdgpu_dm_irq_register_timer(adev, int_params, ih, args); -} - -void dal_isr_acquire_lock(struct dc_context *ctx) -{ - /*TODO*/ -} - -void dal_isr_release_lock(struct dc_context *ctx) -{ - /*TODO*/ -} - -/****************************************************************************** - * End-of-IRQ Interfaces. - *****************************************************************************/ - bool dm_write_persistent_data(struct dc_context *ctx, const struct dc_sink *sink, const char *module_name, @@ -118,18 +77,6 @@ bool dm_pp_pre_dce_clock_change( return false; } -bool dm_pp_apply_safe_state( - const struct dc_context *ctx) -{ - struct amdgpu_device *adev = ctx->driver_context; - - if (adev->pm.dpm_enabled) { - /* TODO: Does this require PreModeChange event to PPLIB? */ - } - - return true; -} - bool dm_pp_apply_display_requirements( const struct dc_context *ctx, const struct dm_pp_display_configuration *pp_display_cfg) -- GitLab From aaa6346d75e2eaee715f36dd3b88a2a865663235 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 09:44:50 -0400 Subject: [PATCH 1193/2898] drm/amd/display: whitespace cleanup in amdgpu_dm_mst_types.c/h To match kernel standards. No intended functional change. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 39 ++++++++++--------- .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 5 +-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 343645e4070b..eed316a8b096 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -57,10 +57,10 @@ static inline char *side_band_msg_type_to_str(uint32_t address) } void log_dpcd(uint8_t type, - uint32_t address, - uint8_t *data, - uint32_t size, - bool res) + uint32_t address, + uint8_t *data, + uint32_t size, + bool res) { DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n", (type == DP_AUX_NATIVE_READ) || @@ -77,9 +77,11 @@ void log_dpcd(uint8_t type, } #endif -static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) +static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) { - enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? I2C_MOT_TRUE : I2C_MOT_FALSE; + enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ? + I2C_MOT_TRUE : I2C_MOT_FALSE; enum ddc_result res; switch (msg->request & ~DP_AUX_I2C_MOT) { @@ -125,10 +127,10 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg #ifdef TRACE_DPCD log_dpcd(msg->request, - msg->address, - msg->buffer, - msg->size, - r == DDC_RESULT_SUCESSFULL); + msg->address, + msg->buffer, + msg->size, + r == DDC_RESULT_SUCESSFULL); #endif return msg->size; @@ -229,9 +231,10 @@ dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) return amdgpu_encoder; } -static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, - const char *pathprop) +static struct drm_connector * +dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + const char *pathprop) { struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; @@ -311,9 +314,8 @@ static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_ return connector; } -static void dm_dp_destroy_mst_connector( - struct drm_dp_mst_topology_mgr *mgr, - struct drm_connector *connector) +static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, + struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); @@ -438,9 +440,8 @@ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { .register_connector = dm_dp_mst_register_connector }; -void amdgpu_dm_initialize_dp_connector( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector) +void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector) { aconnector->dm_dp_aux.aux.name = "dmdc"; aconnector->dm_dp_aux.aux.dev = dm->adev->dev; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index ba64a408d79c..2da851b40042 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -29,8 +29,7 @@ struct amdgpu_display_manager; struct amdgpu_dm_connector; -void amdgpu_dm_initialize_dp_connector( - struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector); +void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector); #endif -- GitLab From 6563617fbbbe273be4ce99f15000a63eca789d6a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 09:47:04 -0400 Subject: [PATCH 1194/2898] drm/amd/display: make log_dpcd static It's only used in this file. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index eed316a8b096..dfcfb5a722e0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -56,11 +56,11 @@ static inline char *side_band_msg_type_to_str(uint32_t address) return str; } -void log_dpcd(uint8_t type, - uint32_t address, - uint8_t *data, - uint32_t size, - bool res) +static void log_dpcd(uint8_t type, + uint32_t address, + uint8_t *data, + uint32_t size, + bool res) { DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n", (type == DP_AUX_NATIVE_READ) || -- GitLab From e637525659ed04be89a7f79ccf6e94e1e5e40225 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 09:53:16 -0400 Subject: [PATCH 1195/2898] drm/amd/display: whitespace cleanup in amdgpu_dm_irq.c/h To match kernel standards. No intended functional change. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 111 ++++++++---------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 38 +++--- 2 files changed, 64 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 22d41d35249e..743a9a361fc6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -66,11 +66,10 @@ struct amdgpu_dm_timer_handler_data { * Private functions. *****************************************************************************/ -static void init_handler_common_data( - struct handler_common_data *hcd, - void (*ih)(void *), - void *args, - struct amdgpu_display_manager *dm) +static void init_handler_common_data(struct handler_common_data *hcd, + void (*ih)(void *), + void *args, + struct amdgpu_display_manager *dm) { hcd->handler = ih; hcd->handler_arg = args; @@ -115,10 +114,9 @@ static void dm_irq_work_func(struct work_struct *work) * Remove a handler and return a pointer to hander list from which the * handler was removed. */ -static struct list_head *remove_irq_handler( - struct amdgpu_device *adev, - void *ih, - const struct dc_interrupt_params *int_params) +static struct list_head *remove_irq_handler(struct amdgpu_device *adev, + void *ih, + const struct dc_interrupt_params *int_params) { struct list_head *hnd_list; struct list_head *entry, *tmp; @@ -172,9 +170,8 @@ static struct list_head *remove_irq_handler( } /* If 'handler_in == NULL' then remove ALL handlers. */ -static void remove_timer_handler( - struct amdgpu_device *adev, - struct amdgpu_dm_timer_handler_data *handler_in) +static void remove_timer_handler(struct amdgpu_device *adev, + struct amdgpu_dm_timer_handler_data *handler_in) { struct amdgpu_dm_timer_handler_data *handler_temp; struct list_head *handler_list; @@ -236,8 +233,7 @@ static void remove_timer_handler( * * @work: work struct */ -static void dm_timer_work_func( - struct work_struct *work) +static void dm_timer_work_func(struct work_struct *work) { struct amdgpu_dm_timer_handler_data *handler_data = container_of(work, struct amdgpu_dm_timer_handler_data, @@ -253,9 +249,9 @@ static void dm_timer_work_func( remove_timer_handler(handler_data->hcd.dm->adev, handler_data); } -static bool validate_irq_registration_params( - struct dc_interrupt_params *int_params, - void (*ih)(void *)) +static bool +validate_irq_registration_params(struct dc_interrupt_params *int_params, + void (*ih)(void *)) { if (NULL == int_params || NULL == ih) { DRM_ERROR("DM_IRQ: invalid input!\n"); @@ -277,9 +273,8 @@ static bool validate_irq_registration_params( return true; } -static bool validate_irq_unregistration_params( - enum dc_irq_source irq_source, - irq_handler_idx handler_idx) +static bool validate_irq_unregistration_params(enum dc_irq_source irq_source, + irq_handler_idx handler_idx) { if (DAL_INVALID_IRQ_HANDLER_IDX == handler_idx) { DRM_ERROR("DM_IRQ: invalid handler_idx==NULL!\n"); @@ -299,11 +294,10 @@ static bool validate_irq_unregistration_params( * Note: caller is responsible for input validation. *****************************************************************************/ -void *amdgpu_dm_irq_register_interrupt( - struct amdgpu_device *adev, - struct dc_interrupt_params *int_params, - void (*ih)(void *), - void *handler_args) +void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev, + struct dc_interrupt_params *int_params, + void (*ih)(void *), + void *handler_args) { struct list_head *hnd_list; struct amdgpu_dm_irq_handler_data *handler_data; @@ -359,10 +353,9 @@ void *amdgpu_dm_irq_register_interrupt( return handler_data; } -void amdgpu_dm_irq_unregister_interrupt( - struct amdgpu_device *adev, - enum dc_irq_source irq_source, - void *ih) +void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, + enum dc_irq_source irq_source, + void *ih) { struct list_head *handler_list; struct dc_interrupt_params int_params; @@ -394,8 +387,7 @@ void amdgpu_dm_irq_unregister_interrupt( } } -int amdgpu_dm_irq_init( - struct amdgpu_device *adev) +int amdgpu_dm_irq_init(struct amdgpu_device *adev) { int src; struct irq_list_head *lh; @@ -427,11 +419,10 @@ int amdgpu_dm_irq_init( return 0; } -void amdgpu_dm_irq_register_timer( - struct amdgpu_device *adev, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args) +void amdgpu_dm_irq_register_timer(struct amdgpu_device *adev, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args) { unsigned long jf_delay; struct list_head *handler_list; @@ -470,8 +461,7 @@ void amdgpu_dm_irq_register_timer( } /* DM IRQ and timer resource release */ -void amdgpu_dm_irq_fini( - struct amdgpu_device *adev) +void amdgpu_dm_irq_fini(struct amdgpu_device *adev) { int src; struct irq_list_head *lh; @@ -492,8 +482,7 @@ void amdgpu_dm_irq_fini( destroy_workqueue(adev->dm.timer_workqueue); } -int amdgpu_dm_irq_suspend( - struct amdgpu_device *adev) +int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) { int src; struct list_head *hnd_list_h; @@ -576,9 +565,8 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) * amdgpu_dm_irq_schedule_work - schedule all work items registered for the * "irq_source". */ -static void amdgpu_dm_irq_schedule_work( - struct amdgpu_device *adev, - enum dc_irq_source irq_source) +static void amdgpu_dm_irq_schedule_work(struct amdgpu_device *adev, + enum dc_irq_source irq_source) { unsigned long irq_table_flags; struct work_struct *work = NULL; @@ -601,9 +589,8 @@ static void amdgpu_dm_irq_schedule_work( /** amdgpu_dm_irq_immediate_work * Callback high irq work immediately, don't send to work queue */ -static void amdgpu_dm_irq_immediate_work( - struct amdgpu_device *adev, - enum dc_irq_source irq_source) +static void amdgpu_dm_irq_immediate_work(struct amdgpu_device *adev, + enum dc_irq_source irq_source) { struct amdgpu_dm_irq_handler_data *handler_data; struct list_head *entry; @@ -635,10 +622,9 @@ static void amdgpu_dm_irq_immediate_work( * Generic IRQ handler, calls all registered high irq work immediately, and * schedules work for low irq */ -int amdgpu_dm_irq_handler( - struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) +int amdgpu_dm_irq_handler(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) { enum dc_irq_source src = @@ -678,9 +664,9 @@ static enum dc_irq_source amdgpu_dm_hpd_to_dal_irq_source(unsigned type) } static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned type, - enum amdgpu_interrupt_state state) + struct amdgpu_irq_src *source, + unsigned type, + enum amdgpu_interrupt_state state) { enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type); bool st = (state == AMDGPU_IRQ_STATE_ENABLE); @@ -689,13 +675,12 @@ static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev, return 0; } -static inline int dm_irq_state( - struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned crtc_id, - enum amdgpu_interrupt_state state, - const enum irq_type dal_irq_type, - const char *func) +static inline int dm_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state, + const enum irq_type dal_irq_type, + const char *func) { bool st; enum dc_irq_source irq_source; @@ -719,9 +704,9 @@ static inline int dm_irq_state( } static int amdgpu_dm_set_pflip_irq_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned crtc_id, - enum amdgpu_interrupt_state state) + struct amdgpu_irq_src *source, + unsigned crtc_id, + enum amdgpu_interrupt_state state) { return dm_irq_state( adev, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 9d3007634266..0927ed4ab758 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -39,8 +39,7 @@ * 0 - success * non-zero - error */ -int amdgpu_dm_irq_init( - struct amdgpu_device *adev); +int amdgpu_dm_irq_init(struct amdgpu_device *adev); /** * amdgpu_dm_irq_fini - deallocate internal structures of 'amdgpu_dm_irq'. @@ -48,8 +47,7 @@ int amdgpu_dm_irq_init( * This function should be called exactly once - during DM destruction. * */ -void amdgpu_dm_irq_fini( - struct amdgpu_device *adev); +void amdgpu_dm_irq_fini(struct amdgpu_device *adev); /** * amdgpu_dm_irq_register_interrupt - register irq handler for Display block. @@ -65,11 +63,10 @@ void amdgpu_dm_irq_fini( * * Cannot be called from an interrupt handler. */ -void *amdgpu_dm_irq_register_interrupt( - struct amdgpu_device *adev, - struct dc_interrupt_params *int_params, - void (*ih)(void *), - void *handler_args); +void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev, + struct dc_interrupt_params *int_params, + void (*ih)(void *), + void *handler_args); /** * amdgpu_dm_irq_unregister_interrupt - unregister handler which was registered @@ -79,26 +76,23 @@ void *amdgpu_dm_irq_register_interrupt( * @ih_index: irq handler index which was returned by * amdgpu_dm_irq_register_interrupt */ -void amdgpu_dm_irq_unregister_interrupt( - struct amdgpu_device *adev, - enum dc_irq_source irq_source, - void *ih_index); +void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, + enum dc_irq_source irq_source, + void *ih_index); -void amdgpu_dm_irq_register_timer( - struct amdgpu_device *adev, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args); +void amdgpu_dm_irq_register_timer(struct amdgpu_device *adev, + struct dc_timer_interrupt_params *int_params, + interrupt_handler ih, + void *args); /** * amdgpu_dm_irq_handler * Generic IRQ handler, calls all registered high irq work immediately, and * schedules work for low irq */ -int amdgpu_dm_irq_handler( - struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry); +int amdgpu_dm_irq_handler(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry); void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev); -- GitLab From f1548455ce89cbb7708428f6a7989a3fe180ed55 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 09:59:50 -0400 Subject: [PATCH 1196/2898] drm/amd/display: remove unused functions in amdgpu_dm_irq.c Not used. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 62 ------------------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 5 -- 2 files changed, 67 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 743a9a361fc6..1b7df0b6c6d3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -228,27 +228,6 @@ static void remove_timer_handler(struct amdgpu_device *adev, } } -/** - * dm_timer_work_func - Handle a timer. - * - * @work: work struct - */ -static void dm_timer_work_func(struct work_struct *work) -{ - struct amdgpu_dm_timer_handler_data *handler_data = - container_of(work, struct amdgpu_dm_timer_handler_data, - d_work.work); - - DRM_DEBUG_KMS("DM_IRQ: work_func: handler_data=%p\n", handler_data); - - /* Call a DAL subcomponent which registered for timer notification. */ - handler_data->hcd.handler(handler_data->hcd.handler_arg); - - /* We support only "single shot" timers. That means we must delete - * the handler after it was called. */ - remove_timer_handler(handler_data->hcd.dm->adev, handler_data); -} - static bool validate_irq_registration_params(struct dc_interrupt_params *int_params, void (*ih)(void *)) @@ -419,47 +398,6 @@ int amdgpu_dm_irq_init(struct amdgpu_device *adev) return 0; } -void amdgpu_dm_irq_register_timer(struct amdgpu_device *adev, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args) -{ - unsigned long jf_delay; - struct list_head *handler_list; - struct amdgpu_dm_timer_handler_data *handler_data; - unsigned long irq_table_flags; - - handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL); - if (!handler_data) { - DRM_ERROR("DM_IRQ: failed to allocate timer handler!\n"); - return; - } - - memset(handler_data, 0, sizeof(*handler_data)); - - init_handler_common_data(&handler_data->hcd, ih, args, &adev->dm); - - INIT_DELAYED_WORK(&handler_data->d_work, dm_timer_work_func); - - /* Lock the list, add the handler. */ - DM_IRQ_TABLE_LOCK(adev, irq_table_flags); - - handler_list = &adev->dm.timer_handler_list; - - list_add_tail(&handler_data->hcd.list, handler_list); - - DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - - jf_delay = usecs_to_jiffies(int_params->micro_sec_interval); - - queue_delayed_work(adev->dm.timer_workqueue, &handler_data->d_work, - jf_delay); - - DRM_DEBUG_KMS("DM_IRQ: added handler:%p with micro_sec_interval=%u\n", - handler_data, int_params->micro_sec_interval); - return; -} - /* DM IRQ and timer resource release */ void amdgpu_dm_irq_fini(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 0927ed4ab758..393fcf7bbcb4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -80,11 +80,6 @@ void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, enum dc_irq_source irq_source, void *ih_index); -void amdgpu_dm_irq_register_timer(struct amdgpu_device *adev, - struct dc_timer_interrupt_params *int_params, - interrupt_handler ih, - void *args); - /** * amdgpu_dm_irq_handler * Generic IRQ handler, calls all registered high irq work immediately, and -- GitLab From 8db02ca3410b0668d520c0c5d7ba0e7e3eaa811a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 10:03:10 -0400 Subject: [PATCH 1197/2898] drm/amd/display: make amdgpu_dm_irq_handler static It's not used outside the file. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 6 +++--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 9 --------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 1b7df0b6c6d3..52b6e4a91d8b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -560,9 +560,9 @@ static void amdgpu_dm_irq_immediate_work(struct amdgpu_device *adev, * Generic IRQ handler, calls all registered high irq work immediately, and * schedules work for low irq */ -int amdgpu_dm_irq_handler(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) +static int amdgpu_dm_irq_handler(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) { enum dc_irq_source src = diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h index 393fcf7bbcb4..82f8e761beca 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h @@ -80,15 +80,6 @@ void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, enum dc_irq_source irq_source, void *ih_index); -/** - * amdgpu_dm_irq_handler - * Generic IRQ handler, calls all registered high irq work immediately, and - * schedules work for low irq - */ -int amdgpu_dm_irq_handler(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry); - void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev); void amdgpu_dm_hpd_init(struct amdgpu_device *adev); -- GitLab From 4770b18493b3d9fe1f8913e69ec5134b103d5788 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 12:42:30 -0400 Subject: [PATCH 1198/2898] drm/amd/display/dc: drop dm_delay_in_microseconds Use udelay directly. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dm_services.h | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 616431e25b79..5f815cab94b5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -127,7 +127,7 @@ static bool edp_receiver_ready_T9(struct dc_link *link) break; if (result != DC_OK) break; - dm_delay_in_microseconds(link->ctx, 100); //MAx T9 + udelay(100); //MAx T9 } while (++tries < 50); return result; } @@ -271,7 +271,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, pipes[i].stream->sink->link != NULL && pipes[i].stream_res.stream_enc != NULL && pipes[i].stream->sink->link == link) { - dm_delay_in_microseconds(link->ctx, 100); + udelay(100); pipes[i].stream_res.stream_enc->funcs->dp_blank( pipes[i].stream_res.stream_enc); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index f9873cad40e0..3691c7498d08 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -137,7 +137,7 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) if (psr_state == 0) break; } - dm_delay_in_microseconds(dmcu->ctx, 10); + udelay(10); } } } @@ -378,7 +378,7 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) if (psr_state == 0) break; } - dm_delay_in_microseconds(dmcu->ctx, 500); + udelay(500); } /* assert if max retry hit */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index 8166027d2d83..a11991c382de 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -404,9 +404,6 @@ bool dm_read_persistent_data(struct dc_context *ctx, unsigned int size, struct persistent_data_flag *flag); -void dm_delay_in_microseconds - (struct dc_context *ctx, unsigned int microSeconds); - bool dm_query_extended_brightness_caps (struct dc_context *ctx, enum dm_acpi_display_type display, struct dm_acpi_atif_backlight_caps *pCaps); -- GitLab From d7205d5c0f2b09d900231de9026b97105c37d343 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Oct 2017 12:44:13 -0400 Subject: [PATCH 1199/2898] drm/amd/display: drop unused dm_delay_in_microseconds No longer used. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index fc0668b2300c..26bf9918fcb7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -59,13 +59,6 @@ bool dm_read_persistent_data(struct dc_context *ctx, return false; } -void dm_delay_in_microseconds(struct dc_context *ctx, - unsigned int microSeconds) -{ - /*TODO implement*/ - return; -} - /**** power component interfaces ****/ bool dm_pp_pre_dce_clock_change( -- GitLab From 2a0b4d858f7bb3d36d0ca610d9ef02062589edeb Mon Sep 17 00:00:00 2001 From: Martin Tsai Date: Thu, 7 Sep 2017 13:02:05 +0800 Subject: [PATCH 1200/2898] drm/amd/display: To prevent detecting new sink from spurious HPD Signed-off-by: Martin Tsai Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 4a70948c91b1..ee23b609d7dd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -565,8 +565,6 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) link->local_sink) return true; - link_disconnect_sink(link); - if (new_connection_type != dc_connection_none) { link->type = new_connection_type; @@ -638,8 +636,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (link->dpcd_caps.sink_count.bits.SINK_COUNT) link->dpcd_sink_count = link->dpcd_caps.sink_count. bits.SINK_COUNT; - else - link->dpcd_sink_count = 1; + else + link->dpcd_sink_count = 1; dal_ddc_service_set_transaction_type( link->ddc, @@ -651,16 +649,24 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; - sink = dc_sink_create(&sink_init_data); - if (!sink) { - DC_ERROR("Failed to create sink!\n"); - return false; - } + if (link->local_sink) { + sink = link->local_sink; + } else { + link_disconnect_sink(link); + + sink_init_data.link = link; + sink_init_data.sink_signal = sink_caps.signal; - sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; - sink->converter_disable_audio = converter_disable_audio; + sink = dc_sink_create(&sink_init_data); + if (!sink) { + DC_ERROR("Failed to create sink!\n"); + return false; + } + sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->converter_disable_audio = converter_disable_audio; - link->local_sink = sink; + link->local_sink = sink; + } edid_status = dm_helpers_read_local_edid( link->ctx, @@ -752,8 +758,22 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); } - link->type = dc_connection_none; - sink_caps.signal = SIGNAL_TYPE_NONE; + if (link->local_sink) { + sink = link->local_sink; + edid_status = dm_helpers_read_local_edid( + link->ctx, + link, + sink); + if (edid_status != EDID_OK) { + link_disconnect_sink(link); + link->type = dc_connection_none; + sink_caps.signal = SIGNAL_TYPE_NONE; + } + } else { + link_disconnect_sink(link); + link->type = dc_connection_none; + sink_caps.signal = SIGNAL_TYPE_NONE; + } } LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", -- GitLab From 0db188f96b69957dec623c10b474d12b8b6038c2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 29 Sep 2017 13:55:19 -0400 Subject: [PATCH 1201/2898] mtdchar: get rid of pointless access_ok() Signed-off-by: Al Viro --- drivers/mtd/mtdchar.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 3568294d4854..de8c902059b8 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -375,12 +375,7 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd, return -EINVAL; if (!mtd->_write_oob) - ret = -EOPNOTSUPP; - else - ret = access_ok(VERIFY_READ, ptr, length) ? 0 : -EFAULT; - - if (ret) - return ret; + return -EOPNOTSUPP; ops.ooblen = length; ops.ooboffs = start & (mtd->writesize - 1); @@ -419,9 +414,6 @@ static int mtdchar_readoob(struct file *file, struct mtd_info *mtd, if (length > 4096) return -EINVAL; - if (!access_ok(VERIFY_WRITE, ptr, length)) - return -EFAULT; - ops.ooblen = length; ops.ooboffs = start & (mtd->writesize - 1); ops.datbuf = NULL; @@ -618,9 +610,6 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd, usr_data = (const void __user *)(uintptr_t)req.usr_data; usr_oob = (const void __user *)(uintptr_t)req.usr_oob; - if (!access_ok(VERIFY_READ, usr_data, req.len) || - !access_ok(VERIFY_READ, usr_oob, req.ooblen)) - return -EFAULT; if (!mtd->_write_oob) return -EOPNOTSUPP; @@ -662,21 +651,10 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) struct mtd_info *mtd = mfi->mtd; void __user *argp = (void __user *)arg; int ret = 0; - u_long size; struct mtd_info_user info; pr_debug("MTD_ioctl\n"); - size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; - if (cmd & IOC_IN) { - if (!access_ok(VERIFY_READ, argp, size)) - return -EFAULT; - } - if (cmd & IOC_OUT) { - if (!access_ok(VERIFY_WRITE, argp, size)) - return -EFAULT; - } - switch (cmd) { case MEMGETREGIONCOUNT: if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) -- GitLab From a0dbef33863349de5313dff62982d309ded98190 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 29 Sep 2017 13:58:09 -0400 Subject: [PATCH 1202/2898] cxlflash: get rid of pointless access_ok() Signed-off-by: Al Viro --- drivers/scsi/cxlflash/main.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 76b8b7eed0c0..39430c67b522 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -3383,12 +3383,6 @@ static int cxlflash_afu_debug(struct cxlflash_cfg *cfg, goto out; } - if (unlikely(!access_ok(is_write ? VERIFY_READ : VERIFY_WRITE, - ubuf, ulen))) { - rc = -EFAULT; - goto out; - } - buf = kmalloc(ulen + cache_line_size() - 1, GFP_KERNEL); if (unlikely(!buf)) { rc = -ENOMEM; -- GitLab From 023b7b07ccb57317bee4d971be546cc4469f4e7e Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Thu, 31 Aug 2017 11:30:45 +0530 Subject: [PATCH 1203/2898] thermal : Remove const to make same prototype Here, prototype of thermal_zone_device_register is not matching with static inline thermal_zone_device_register. One is using const thermal_zone_params. Other is using non-const. Signed-off-by: Arvind Yadav Signed-off-by: Zhang Rui --- include/linux/thermal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/thermal.h b/include/linux/thermal.h index fd5b959c753c..8c5302374eaa 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -488,7 +488,7 @@ static inline int power_actor_set_power(struct thermal_cooling_device *cdev, static inline struct thermal_zone_device *thermal_zone_device_register( const char *type, int trips, int mask, void *devdata, struct thermal_zone_device_ops *ops, - const struct thermal_zone_params *tzp, + struct thermal_zone_params *tzp, int passive_delay, int polling_delay) { return ERR_PTR(-ENODEV); } static inline void thermal_zone_device_unregister( -- GitLab From d344f3138a473b99f09041a1e6ece9f3b8953858 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 9 Oct 2017 17:21:07 +0530 Subject: [PATCH 1204/2898] thermal/intel_powerclamp: pr_err()/pr_info() strings should end with newlines pr_err()/pr_info() messages should end with a new-line to avoid other messages being concatenated. Signed-off-by: Arvind Yadav Signed-off-by: Zhang Rui --- drivers/thermal/intel_powerclamp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index d718cd179ddb..4540e892b61d 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c @@ -675,13 +675,13 @@ static int __init powerclamp_probe(void) { if (!x86_match_cpu(intel_powerclamp_ids)) { - pr_err("CPU does not support MWAIT"); + pr_err("CPU does not support MWAIT\n"); return -ENODEV; } /* The goal for idle time alignment is to achieve package cstate. */ if (!has_pkg_state_counter()) { - pr_info("No package C-state available"); + pr_info("No package C-state available\n"); return -ENODEV; } -- GitLab From 5eabff1cb9dad4e81ee387ac79f7521d078bfa8f Mon Sep 17 00:00:00 2001 From: Himanshu Jha Date: Tue, 17 Oct 2017 16:01:12 +0200 Subject: [PATCH 1205/2898] video: fbdev: pxa3xx_gcu: Use setup_timer and mod_timer Use setup_timer and mod_timer API instead of structure assignments. This is done using Coccinelle and semantic patch used for this as follows: @@ expression x,y,z,a,b; @@ -init_timer (&x); +setup_timer (&x, y, z); +mod_timer (&a, b); -x.function = y; -x.data = z; -x.expires = b; -add_timer(&a); Signed-off-by: Himanshu Jha Cc: "Gustavo A. R. Silva" Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/pxa3xx-gcu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c index 933619da1a94..3366076f9e0f 100644 --- a/drivers/video/fbdev/pxa3xx-gcu.c +++ b/drivers/video/fbdev/pxa3xx-gcu.c @@ -520,12 +520,8 @@ static void pxa3xx_gcu_debug_timedout(unsigned long ptr) QERROR("Timer DUMP"); /* init the timer structure */ - init_timer(&pxa3xx_gcu_debug_timer); - pxa3xx_gcu_debug_timer.function = pxa3xx_gcu_debug_timedout; - pxa3xx_gcu_debug_timer.data = ptr; - pxa3xx_gcu_debug_timer.expires = jiffies + 5*HZ; /* one second */ - - add_timer(&pxa3xx_gcu_debug_timer); + setup_timer(&pxa3xx_gcu_debug_timer, pxa3xx_gcu_debug_timedout, ptr); + mod_timer(&pxa3xx_gcu_debug_timer, jiffies + 5 * HZ); } static void pxa3xx_gcu_init_debug_timer(void) -- GitLab From ba1d36ba09becdc7f65e0140f13b31762ac31941 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Oct 2017 16:01:12 +0200 Subject: [PATCH 1206/2898] video: sa1100fb: use devm_kzalloc() Use devm_kzalloc() when allocating the private data for the framebuffer device. Signed-off-by: Russell King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sa1100fb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index fc2aaa5aca23..05a80e08dcde 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1132,12 +1132,11 @@ static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev) struct sa1100fb_info *fbi; unsigned i; - fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16, - GFP_KERNEL); + fbi = devm_kzalloc(dev, sizeof(struct sa1100fb_info) + sizeof(u32) * 16, + GFP_KERNEL); if (!fbi) return NULL; - memset(fbi, 0, sizeof(struct sa1100fb_info)); fbi->dev = dev; strcpy(fbi->fb.fix.id, SA1100_NAME); @@ -1292,7 +1291,6 @@ static int sa1100fb_probe(struct platform_device *pdev) iounmap(fbi->base); if (fbi->clk) clk_put(fbi->clk); - kfree(fbi); release_mem_region(res->start, resource_size(res)); return ret; } -- GitLab From e43064ccd4b47fcb25c7f6806da1e7368312edfe Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Oct 2017 16:01:12 +0200 Subject: [PATCH 1207/2898] video: sa1100fb: use devm_clk_get() Use devm_clk_get() to get the clock for the LCD. Signed-off-by: Russell King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sa1100fb.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index 05a80e08dcde..1562d7607dd2 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1230,10 +1230,9 @@ static int sa1100fb_probe(struct platform_device *pdev) if (!fbi) goto failed; - fbi->clk = clk_get(&pdev->dev, NULL); + fbi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(fbi->clk)) { ret = PTR_ERR(fbi->clk); - fbi->clk = NULL; goto failed; } @@ -1289,8 +1288,6 @@ static int sa1100fb_probe(struct platform_device *pdev) failed: if (fbi) iounmap(fbi->base); - if (fbi->clk) - clk_put(fbi->clk); release_mem_region(res->start, resource_size(res)); return ret; } -- GitLab From df6b228768db032608edbc58f87bc77d23f94952 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Oct 2017 16:01:12 +0200 Subject: [PATCH 1208/2898] video: sa1100fb: use devm_ioremap_resource() Use devm_ioremap_resource() to map the LCD controller memory region, and remove the unnecessary cleanup for this. Signed-off-by: Russell King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sa1100fb.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index 1562d7607dd2..ab83970dbfd9 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1217,29 +1217,28 @@ static int sa1100fb_probe(struct platform_device *pdev) return -EINVAL; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (irq < 0 || !res) + if (irq < 0) return -EINVAL; - if (!request_mem_region(res->start, resource_size(res), "LCD")) - return -EBUSY; - fbi = sa1100fb_init_fbinfo(&pdev->dev); ret = -ENOMEM; if (!fbi) goto failed; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + fbi->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(fbi->base)) { + ret = PTR_ERR(fbi->base); + goto failed; + } + fbi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(fbi->clk)) { ret = PTR_ERR(fbi->clk); goto failed; } - fbi->base = ioremap(res->start, resource_size(res)); - if (!fbi->base) - goto failed; - /* Initialize video memory */ ret = sa1100fb_map_video_memory(fbi); if (ret) @@ -1286,9 +1285,6 @@ static int sa1100fb_probe(struct platform_device *pdev) err_free_irq: free_irq(irq, fbi); failed: - if (fbi) - iounmap(fbi->base); - release_mem_region(res->start, resource_size(res)); return ret; } -- GitLab From f6fc8c9dbdc976e4933c5edc13764eafe9897313 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Oct 2017 16:01:12 +0200 Subject: [PATCH 1209/2898] video: sa1100fb: use devm_request_irq() Use devm_request_irq() to request the interrupt (a little earlier too) so we can avoid having to manually clean this up. Signed-off-by: Russell King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sa1100fb.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index ab83970dbfd9..a48fdb676f3e 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1239,22 +1239,23 @@ static int sa1100fb_probe(struct platform_device *pdev) goto failed; } - /* Initialize video memory */ - ret = sa1100fb_map_video_memory(fbi); - if (ret) - goto failed; - - ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi); + ret = devm_request_irq(&pdev->dev, irq, sa1100fb_handle_irq, 0, + "LCD", fbi); if (ret) { dev_err(&pdev->dev, "request_irq failed: %d\n", ret); goto failed; } + /* Initialize video memory */ + ret = sa1100fb_map_video_memory(fbi); + if (ret) + goto failed; + if (machine_is_shannon()) { ret = gpio_request_one(SHANNON_GPIO_DISP_EN, GPIOF_OUT_INIT_LOW, "display enable"); if (ret) - goto err_free_irq; + goto failed; } /* @@ -1282,8 +1283,6 @@ static int sa1100fb_probe(struct platform_device *pdev) err_reg_fb: if (machine_is_shannon()) gpio_free(SHANNON_GPIO_DISP_EN); - err_free_irq: - free_irq(irq, fbi); failed: return ret; } -- GitLab From 5634cbab489e8428f352f257b631c128b8dc869d Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Oct 2017 16:01:12 +0200 Subject: [PATCH 1210/2898] video: sa1100fb: use devm_gpio_request_one() Switch to using devm_gpio_request_one() to request the shannon gpio and move the request before the video memory allocation, so we request all device managed resources before this large allocation attempt. Signed-off-by: Russell King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sa1100fb.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index a48fdb676f3e..7fa6c8f74ec6 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1246,18 +1246,18 @@ static int sa1100fb_probe(struct platform_device *pdev) goto failed; } - /* Initialize video memory */ - ret = sa1100fb_map_video_memory(fbi); - if (ret) - goto failed; - if (machine_is_shannon()) { - ret = gpio_request_one(SHANNON_GPIO_DISP_EN, + ret = devm_gpio_request_one(&pdev->dev, SHANNON_GPIO_DISP_EN, GPIOF_OUT_INIT_LOW, "display enable"); if (ret) goto failed; } + /* Initialize video memory */ + ret = sa1100fb_map_video_memory(fbi); + if (ret) + goto failed; + /* * This makes sure that our colour bitfield * descriptors are correctly initialised. @@ -1268,7 +1268,7 @@ static int sa1100fb_probe(struct platform_device *pdev) ret = register_framebuffer(&fbi->fb); if (ret < 0) - goto err_reg_fb; + goto failed; #ifdef CONFIG_CPU_FREQ fbi->freq_transition.notifier_call = sa1100fb_freq_transition; @@ -1280,9 +1280,6 @@ static int sa1100fb_probe(struct platform_device *pdev) /* This driver cannot be unloaded at the moment */ return 0; - err_reg_fb: - if (machine_is_shannon()) - gpio_free(SHANNON_GPIO_DISP_EN); failed: return ret; } -- GitLab From c244f8e48c9f1875101201eaa0ecd2bfb17a5405 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Oct 2017 16:01:12 +0200 Subject: [PATCH 1211/2898] video: sa1100fb: clean up failure path We merely return from the failed path, so remove all the gotos and use return statements instead. Signed-off-by: Russell King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sa1100fb.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index 7fa6c8f74ec6..16a974471c02 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1222,41 +1222,36 @@ static int sa1100fb_probe(struct platform_device *pdev) return -EINVAL; fbi = sa1100fb_init_fbinfo(&pdev->dev); - ret = -ENOMEM; if (!fbi) - goto failed; + return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); fbi->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(fbi->base)) { - ret = PTR_ERR(fbi->base); - goto failed; - } + if (IS_ERR(fbi->base)) + return PTR_ERR(fbi->base); fbi->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(fbi->clk)) { - ret = PTR_ERR(fbi->clk); - goto failed; - } + if (IS_ERR(fbi->clk)) + return PTR_ERR(fbi->clk); ret = devm_request_irq(&pdev->dev, irq, sa1100fb_handle_irq, 0, "LCD", fbi); if (ret) { dev_err(&pdev->dev, "request_irq failed: %d\n", ret); - goto failed; + return ret; } if (machine_is_shannon()) { ret = devm_gpio_request_one(&pdev->dev, SHANNON_GPIO_DISP_EN, GPIOF_OUT_INIT_LOW, "display enable"); if (ret) - goto failed; + return ret; } /* Initialize video memory */ ret = sa1100fb_map_video_memory(fbi); if (ret) - goto failed; + return ret; /* * This makes sure that our colour bitfield -- GitLab From 0ab76581a9fee0413c54907076fcd79fcc271843 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Oct 2017 16:01:13 +0200 Subject: [PATCH 1212/2898] video: sa1100fb: fix video memory allocation leak Don't leak the video memory allocation if register_framebuffer() fails. Signed-off-by: Russell King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sa1100fb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index 16a974471c02..56d514b5d252 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -1262,8 +1262,11 @@ static int sa1100fb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fbi); ret = register_framebuffer(&fbi->fb); - if (ret < 0) - goto failed; + if (ret < 0) { + dma_free_wc(fbi->dev, fbi->map_size, fbi->map_cpu, + fbi->map_dma); + return ret; + } #ifdef CONFIG_CPU_FREQ fbi->freq_transition.notifier_call = sa1100fb_freq_transition; @@ -1274,9 +1277,6 @@ static int sa1100fb_probe(struct platform_device *pdev) /* This driver cannot be unloaded at the moment */ return 0; - - failed: - return ret; } static struct platform_driver sa1100fb_driver = { -- GitLab From cb6bc3ff59e3ff7a6fba8ca6ee649d532b4e17f2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 17 Oct 2017 16:01:13 +0200 Subject: [PATCH 1213/2898] video: sa1100fb: move pseudo palette into sa1100fb_info structure Move the pseudo palette inside the driver private data structure so we don't have to play tricks to cater for it. Signed-off-by: Russell King Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/sa1100fb.c | 9 +++------ drivers/video/fbdev/sa1100fb.h | 2 ++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index 56d514b5d252..15ae50063296 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -323,13 +323,11 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * according to the RGB bitfield information. */ if (regno < 16) { - u32 *pal = fbi->fb.pseudo_palette; - val = chan_to_field(red, &fbi->fb.var.red); val |= chan_to_field(green, &fbi->fb.var.green); val |= chan_to_field(blue, &fbi->fb.var.blue); - pal[regno] = val; + fbi->pseudo_palette[regno] = val; ret = 0; } break; @@ -1132,8 +1130,7 @@ static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev) struct sa1100fb_info *fbi; unsigned i; - fbi = devm_kzalloc(dev, sizeof(struct sa1100fb_info) + sizeof(u32) * 16, - GFP_KERNEL); + fbi = devm_kzalloc(dev, sizeof(struct sa1100fb_info), GFP_KERNEL); if (!fbi) return NULL; @@ -1158,7 +1155,7 @@ static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev) fbi->fb.fbops = &sa1100fb_ops; fbi->fb.flags = FBINFO_DEFAULT; fbi->fb.monspecs = monspecs; - fbi->fb.pseudo_palette = (fbi + 1); + fbi->fb.pseudo_palette = fbi->pseudo_palette; fbi->rgb[RGB_4] = &rgb_4; fbi->rgb[RGB_8] = &rgb_8; diff --git a/drivers/video/fbdev/sa1100fb.h b/drivers/video/fbdev/sa1100fb.h index 0139d13377a5..7a1a9ca33cec 100644 --- a/drivers/video/fbdev/sa1100fb.h +++ b/drivers/video/fbdev/sa1100fb.h @@ -69,6 +69,8 @@ struct sa1100fb_info { const struct sa1100fb_mach_info *inf; struct clk *clk; + + u32 pseudo_palette[16]; }; #define TO_INF(ptr,member) container_of(ptr,struct sa1100fb_info,member) -- GitLab From 553c7d5ba2fe64cdbfcdf49560ef71ef79810f93 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 17 Oct 2017 11:06:17 +0200 Subject: [PATCH 1214/2898] clk: sunxi-ng: Add A83T display clocks Unfortunately, the A83t display clocks are not children of the de clock, since that clocks doesn't exist at all on the A83t. For now, they are orphans, so let's move them to their true, existing, parent. Fixes: 763c5bd045b1 ("clk: sunxi-ng: add support for DE2 CCU") Reviewed-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 5cdaf52669e4..5cc9d9952121 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -41,11 +41,16 @@ static SUNXI_CCU_GATE(wb_clk, "wb", "wb-div", static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4, CLK_SET_RATE_PARENT); -static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4, - CLK_SET_RATE_PARENT); static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4, CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4, + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4, + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4, + CLK_SET_RATE_PARENT); + static struct ccu_common *sun8i_a83t_de2_clks[] = { &mixer0_clk.common, &mixer1_clk.common, @@ -55,9 +60,9 @@ static struct ccu_common *sun8i_a83t_de2_clks[] = { &bus_mixer1_clk.common, &bus_wb_clk.common, - &mixer0_div_clk.common, - &mixer1_div_clk.common, - &wb_div_clk.common, + &mixer0_div_a83_clk.common, + &mixer1_div_a83_clk.common, + &wb_div_a83_clk.common, }; static struct ccu_common *sun8i_v3s_de2_clks[] = { @@ -81,9 +86,9 @@ static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = { [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, [CLK_BUS_WB] = &bus_wb_clk.common.hw, - [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, - [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, - [CLK_WB_DIV] = &wb_div_clk.common.hw, + [CLK_MIXER0_DIV] = &mixer0_div_a83_clk.common.hw, + [CLK_MIXER1_DIV] = &mixer1_div_a83_clk.common.hw, + [CLK_WB_DIV] = &wb_div_a83_clk.common.hw, }, .num = CLK_NUMBER, }; -- GitLab From 4328a2186e5120cfd34c4f04c6e4b7e74fb8b7b4 Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Tue, 17 Oct 2017 20:18:03 +0800 Subject: [PATCH 1215/2898] clk: sunxi-ng: sun4i: Export video PLLs The video PLLs are used directly by the HDMI controller. Export them so that we can use them in our DT node. Signed-off-by: Jonathan Liu Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun4i-a10.h | 4 ++-- include/dt-bindings/clock/sun4i-a10-ccu.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.h b/drivers/clk/sunxi-ng/ccu-sun4i-a10.h index c5947c7c050e..23c908ad509f 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.h +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.h @@ -29,7 +29,7 @@ #define CLK_PLL_AUDIO_4X 6 #define CLK_PLL_AUDIO_8X 7 #define CLK_PLL_VIDEO0 8 -#define CLK_PLL_VIDEO0_2X 9 +/* The PLL_VIDEO0_2X clock is exported */ #define CLK_PLL_VE 10 #define CLK_PLL_DDR_BASE 11 #define CLK_PLL_DDR 12 @@ -38,7 +38,7 @@ #define CLK_PLL_PERIPH 15 #define CLK_PLL_PERIPH_SATA 16 #define CLK_PLL_VIDEO1 17 -#define CLK_PLL_VIDEO1_2X 18 +/* The PLL_VIDEO1_2X clock is exported */ #define CLK_PLL_GPU 19 /* The CPU clock is exported */ diff --git a/include/dt-bindings/clock/sun4i-a10-ccu.h b/include/dt-bindings/clock/sun4i-a10-ccu.h index c5a53f38d654..e4fa61be5c75 100644 --- a/include/dt-bindings/clock/sun4i-a10-ccu.h +++ b/include/dt-bindings/clock/sun4i-a10-ccu.h @@ -43,6 +43,8 @@ #define _DT_BINDINGS_CLK_SUN4I_A10_H_ #define CLK_HOSC 1 +#define CLK_PLL_VIDEO0_2X 9 +#define CLK_PLL_VIDEO1_2X 18 #define CLK_CPU 20 /* AHB Gates */ -- GitLab From 18a3dde9db78076755275423b754846a2da000ad Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 3 Oct 2017 10:49:20 +0530 Subject: [PATCH 1216/2898] mtd: spi-nor: cadence-quadspi: Add TI 66AK2G SoC specific compatible Update binding documentation to add a new compatible for TI 66AK2G SoC, to handle TI SoC specific quirks in the driver. Signed-off-by: Vignesh R Acked-by: Rob Herring Acked-by: Marek Vasut Signed-off-by: Cyrille Pitchen --- Documentation/devicetree/bindings/mtd/cadence-quadspi.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt b/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt index f248056da24c..7dbe3bd9ac56 100644 --- a/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt +++ b/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt @@ -1,7 +1,9 @@ * Cadence Quad SPI controller Required properties: -- compatible : Should be "cdns,qspi-nor". +- compatible : should be one of the following: + Generic default - "cdns,qspi-nor". + For TI 66AK2G SoC - "ti,k2g-qspi", "cdns,qspi-nor". - reg : Contains two entries, each of which is a tuple consisting of a physical address and length. The first entry is the address and length of the controller register set. The second entry is the -- GitLab From 61dc8493bae9ba82a1c72edbc6c6065f6a94456a Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 3 Oct 2017 10:49:21 +0530 Subject: [PATCH 1217/2898] mtd: spi-nor: cadence-quadspi: add a delay in write sequence As per 66AK2G02 TRM[1] SPRUHY8F section 11.15.5.3 Indirect Access Controller programming sequence, a delay equal to couple of QSPI master clock(~5ns) is required after setting CQSPI_REG_INDIRECTWR_START bit and writing data to the flash. Introduce a quirk flag CQSPI_NEEDS_WR_DELAY to handle this and set this flag for TI 66AK2G SoC. [1]http://www.ti.com/lit/ug/spruhy8f/spruhy8f.pdf Signed-off-by: Vignesh R Acked-by: Marek Vasut Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/cadence-quadspi.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 53c7d8e0327a..5cd5d6f7303f 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -38,6 +38,9 @@ #define CQSPI_NAME "cadence-qspi" #define CQSPI_MAX_CHIPSELECT 16 +/* Quirks */ +#define CQSPI_NEEDS_WR_DELAY BIT(0) + struct cqspi_st; struct cqspi_flash_pdata { @@ -76,6 +79,7 @@ struct cqspi_st { u32 fifo_depth; u32 fifo_width; u32 trigger_address; + u32 wr_delay; struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT]; }; @@ -608,6 +612,15 @@ static int cqspi_indirect_write_execute(struct spi_nor *nor, reinit_completion(&cqspi->transfer_complete); writel(CQSPI_REG_INDIRECTWR_START_MASK, reg_base + CQSPI_REG_INDIRECTWR); + /* + * As per 66AK2G02 TRM SPRUHY8F section 11.15.5.3 Indirect Access + * Controller programming sequence, couple of cycles of + * QSPI_REF_CLK delay is required for the above bit to + * be internally synchronized by the QSPI module. Provide 5 + * cycles of delay. + */ + if (cqspi->wr_delay) + ndelay(cqspi->wr_delay); while (remaining > 0) { write_bytes = remaining > page_size ? page_size : remaining; @@ -1156,6 +1169,7 @@ static int cqspi_probe(struct platform_device *pdev) struct cqspi_st *cqspi; struct resource *res; struct resource *res_ahb; + unsigned long data; int ret; int irq; @@ -1213,6 +1227,10 @@ static int cqspi_probe(struct platform_device *pdev) } cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk); + data = (unsigned long)of_device_get_match_data(dev); + if (data & CQSPI_NEEDS_WR_DELAY) + cqspi->wr_delay = 5 * DIV_ROUND_UP(NSEC_PER_SEC, + cqspi->master_ref_clk_hz); ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0, pdev->name, cqspi); @@ -1284,7 +1302,14 @@ static const struct dev_pm_ops cqspi__dev_pm_ops = { #endif static const struct of_device_id cqspi_dt_ids[] = { - {.compatible = "cdns,qspi-nor",}, + { + .compatible = "cdns,qspi-nor", + .data = (void *)0, + }, + { + .compatible = "ti,k2g-qspi", + .data = (void *)CQSPI_NEEDS_WR_DELAY, + }, { /* end of table */ } }; -- GitLab From 00df263560673cefe3341275990324730d4791d5 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 3 Oct 2017 10:49:22 +0530 Subject: [PATCH 1218/2898] mtd: spi-nor: cadence-quadspi: Add new binding to enable loop-back circuit Cadence QSPI IP has a adapted loop-back circuit which can be enabled by setting BYPASS field to 0 in READCAPTURE register. It enables use of QSPI return clock to latch the data rather than the internal QSPI reference clock. For high speed operations, adapted loop-back circuit using QSPI return clock helps to increase data valid window. Add DT parameter cdns,rclk-en to help enable adapted loop-back circuit for boards which do have QSPI return clock provided. Update binding documentation for the same. Signed-off-by: Vignesh R Acked-by: Rob Herring Acked-by: Marek Vasut Signed-off-by: Cyrille Pitchen --- Documentation/devicetree/bindings/mtd/cadence-quadspi.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt b/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt index 7dbe3bd9ac56..bb2075df9b38 100644 --- a/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt +++ b/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt @@ -16,6 +16,9 @@ Required properties: Optional properties: - cdns,is-decoded-cs : Flag to indicate whether decoder is used or not. +- cdns,rclk-en : Flag to indicate that QSPI return clock is used to latch + the read data rather than the QSPI clock. Make sure that QSPI return + clock is populated on the board before using this property. Optional subnodes: Subnodes of the Cadence Quad SPI controller are spi slave nodes with additional -- GitLab From e2580a4add6b061f1cc9d7bf9bac5a643112d744 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 3 Oct 2017 10:49:23 +0530 Subject: [PATCH 1219/2898] mtd: spi-nor: cadence-quadspi: Add support to enable loop-back clock circuit Cadence QSPI IP has a adapted loop-back circuit which can be enabled by setting BYPASS field to 0 in READCAPTURE register. It enables use of QSPI return clock to latch the data rather than the internal QSPI reference clock. For high speed operations, adapted loop-back circuit using QSPI return clock helps to increase data valid window. Based on DT parameter cdns,rclk-en enable adapted loop-back circuit for boards which do have QSPI return clock provided. This patch also modifies cqspi_readdata_capture() function's bypass parameter to bool to match how its used in the function. Signed-off-by: Vignesh R Acked-by: Marek Vasut Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/cadence-quadspi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 5cd5d6f7303f..d9629e8f4798 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -78,6 +78,7 @@ struct cqspi_st { bool is_decoded_cs; u32 fifo_depth; u32 fifo_width; + bool rclk_en; u32 trigger_address; u32 wr_delay; struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT]; @@ -788,7 +789,7 @@ static void cqspi_config_baudrate_div(struct cqspi_st *cqspi) } static void cqspi_readdata_capture(struct cqspi_st *cqspi, - const unsigned int bypass, + const bool bypass, const unsigned int delay) { void __iomem *reg_base = cqspi->iobase; @@ -852,7 +853,8 @@ static void cqspi_configure(struct spi_nor *nor) cqspi->sclk = sclk; cqspi_config_baudrate_div(cqspi); cqspi_delay(nor); - cqspi_readdata_capture(cqspi, 1, f_pdata->read_delay); + cqspi_readdata_capture(cqspi, !cqspi->rclk_en, + f_pdata->read_delay); } if (switch_cs || switch_ck) @@ -1049,6 +1051,8 @@ static int cqspi_of_get_pdata(struct platform_device *pdev) return -ENXIO; } + cqspi->rclk_en = of_property_read_bool(np, "cdns,rclk-en"); + return 0; } -- GitLab From 329864d35a7f49bed78bc3302fc56317c325f31f Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 3 Oct 2017 10:49:24 +0530 Subject: [PATCH 1220/2898] mtd: spi-nor: cadence-quadspi: Fix error path in probe Fix the reversed goto labels, so that we disable cqspi controller only if its enabled previously. This is a minor cleanup. Signed-off-by: Vignesh R Acked-by: Marek Vasut Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/cadence-quadspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index d9629e8f4798..60b557e00cfb 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -1255,9 +1255,9 @@ static int cqspi_probe(struct platform_device *pdev) } return ret; -probe_irq_failed: - cqspi_controller_enable(cqspi, 0); probe_setup_failed: + cqspi_controller_enable(cqspi, 0); +probe_irq_failed: clk_disable_unprepare(cqspi->clk); return ret; } -- GitLab From 4892b374c9b79729da33bf94612588a6556709be Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 3 Oct 2017 10:49:25 +0530 Subject: [PATCH 1221/2898] mtd: spi-nor: cadence-quadspi: Add runtime PM support Add pm_runtime* calls to cadence-quadspi driver. This is required to switch on QSPI power domain on TI 66AK2G SoC during probe. Signed-off-by: Vignesh R Acked-by: Marek Vasut Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/cadence-quadspi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 60b557e00cfb..75a2bc447a99 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1224,10 +1225,17 @@ static int cqspi_probe(struct platform_device *pdev) return -ENXIO; } + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + return ret; + } + ret = clk_prepare_enable(cqspi->clk); if (ret) { dev_err(dev, "Cannot enable QSPI clock.\n"); - return ret; + goto probe_clk_failed; } cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk); @@ -1259,6 +1267,9 @@ static int cqspi_probe(struct platform_device *pdev) cqspi_controller_enable(cqspi, 0); probe_irq_failed: clk_disable_unprepare(cqspi->clk); +probe_clk_failed: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); return ret; } @@ -1275,6 +1286,9 @@ static int cqspi_remove(struct platform_device *pdev) clk_disable_unprepare(cqspi->clk); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + return 0; } -- GitLab From b5ca66f9c0cf8c1cfeca12f001b86486c670279d Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 13 Oct 2017 10:21:50 -0400 Subject: [PATCH 1222/2898] tracing, thermal: Hide devfreq trace events when not in use As trace events when defined create data structures and functions to process them, defining trace events when not using them is a waste of memory. The trace events thermal_power_devfreq_get_power and thermal_power_devfreq_limit are only used when CONFIG_DEVFREQ_THERMAL is set. Make those events only defined when that is set as well. Link: http://lkml.kernel.org/r/20171013102150.0050cb74@gandalf.local.home Acked-by: Javi Merino Signed-off-by: Steven Rostedt (VMware) --- include/trace/events/thermal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h index 6cde5b3514c2..1fdacdb94e77 100644 --- a/include/trace/events/thermal.h +++ b/include/trace/events/thermal.h @@ -148,6 +148,7 @@ TRACE_EVENT(thermal_power_cpu_limit, __entry->power) ); +#ifdef CONFIG_DEVFREQ_THERMAL TRACE_EVENT(thermal_power_devfreq_get_power, TP_PROTO(struct thermal_cooling_device *cdev, struct devfreq_dev_status *status, unsigned long freq, @@ -203,6 +204,7 @@ TRACE_EVENT(thermal_power_devfreq_limit, __get_str(type), __entry->freq, __entry->cdev_state, __entry->power) ); +#endif /* CONFIG_DEVFREQ_THERMAL */ #endif /* _TRACE_THERMAL_H */ /* This part must be outside protection */ -- GitLab From a96a5037ed0f52e2d86739f4a1ef985bd036e575 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 13 Oct 2017 10:23:09 -0400 Subject: [PATCH 1223/2898] tracing, thermal: Hide cpu cooling trace events when not in use As trace events when defined create data structures and functions to process them, defining trace events when not using them is a waste of memory. The trace events thermal_power_cpu_get_power and thermal_power_cpu_limit are only used when CONFIG_CPU_THERMAL is set. Make those events only defined when that is set as well. Link: http://lkml.kernel.org/r/20171013102309.2c4ef81a@gandalf.local.home Cc: Eduardo Valentin Acked-by: Javi Merino Signed-off-by: Steven Rostedt (VMware) --- include/trace/events/thermal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h index 1fdacdb94e77..8af8f130950e 100644 --- a/include/trace/events/thermal.h +++ b/include/trace/events/thermal.h @@ -90,6 +90,7 @@ TRACE_EVENT(thermal_zone_trip, show_tzt_type(__entry->trip_type)) ); +#ifdef CONFIG_CPU_THERMAL TRACE_EVENT(thermal_power_cpu_get_power, TP_PROTO(const struct cpumask *cpus, unsigned long freq, u32 *load, size_t load_len, u32 dynamic_power, u32 static_power), @@ -147,6 +148,7 @@ TRACE_EVENT(thermal_power_cpu_limit, __get_bitmask(cpumask), __entry->freq, __entry->cdev_state, __entry->power) ); +#endif /* CONFIG_CPU_THERMAL */ #ifdef CONFIG_DEVFREQ_THERMAL TRACE_EVENT(thermal_power_devfreq_get_power, -- GitLab From ec04aa3ae87b895dbc674a7e0b78b670f73a2c22 Mon Sep 17 00:00:00 2001 From: Markus Mayer Date: Wed, 27 Sep 2017 16:02:35 -0700 Subject: [PATCH 1224/2898] tools/thermal: tmon: use "-fstack-protector" only if supported Most, but not all, toolchains support the "-fstack-protector" flag. We check if the compiler supports the flag before using it. This allows tmon to be compiled for more environments. Signed-off-by: Markus Mayer Signed-off-by: Zhang Rui --- tools/thermal/tmon/Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/thermal/tmon/Makefile b/tools/thermal/tmon/Makefile index 3a961e998281..5777bc78173f 100644 --- a/tools/thermal/tmon/Makefile +++ b/tools/thermal/tmon/Makefile @@ -1,8 +1,13 @@ +# We need this for the "cc-option" macro. +include ../../../scripts/Kbuild.include + VERSION = 1.0 BINDIR=usr/bin WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int -CFLAGS+= -O1 ${WARNFLAGS} -fstack-protector +CFLAGS+= -O1 ${WARNFLAGS} +# Add "-fstack-protector" only if toolchain supports it. +CFLAGS+= $(call cc-option,-fstack-protector) CC=$(CROSS_COMPILE)gcc CFLAGS+=-D VERSION=\"$(VERSION)\" -- GitLab From c21568ffabed918882c61eada79146706bd94684 Mon Sep 17 00:00:00 2001 From: Markus Mayer Date: Wed, 27 Sep 2017 16:02:36 -0700 Subject: [PATCH 1225/2898] tools/thermal: tmon: allow $(CC) to be defined externally It can be helpful, especially when using a build system, to set the C compiler externally. Signed-off-by: Markus Mayer Signed-off-by: Zhang Rui --- tools/thermal/tmon/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/thermal/tmon/Makefile b/tools/thermal/tmon/Makefile index 5777bc78173f..581da716ea1c 100644 --- a/tools/thermal/tmon/Makefile +++ b/tools/thermal/tmon/Makefile @@ -8,7 +8,7 @@ WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit- CFLAGS+= -O1 ${WARNFLAGS} # Add "-fstack-protector" only if toolchain supports it. CFLAGS+= $(call cc-option,-fstack-protector) -CC=$(CROSS_COMPILE)gcc +CC?= $(CROSS_COMPILE)gcc CFLAGS+=-D VERSION=\"$(VERSION)\" LDFLAGS+= -- GitLab From 501a5c71d1f754e44142af6cae59042a8c3b2a11 Mon Sep 17 00:00:00 2001 From: Markus Mayer Date: Wed, 27 Sep 2017 16:02:37 -0700 Subject: [PATCH 1226/2898] tools/thermal: tmon: use $(PKG_CONFIG) instead of hard-coding pkg-config To ease cross-compiling, make use of the $(PKG_CONFIG) variable rather than hard-coding calls to pkg-config. Signed-off-by: Markus Mayer Signed-off-by: Zhang Rui --- tools/thermal/tmon/Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/thermal/tmon/Makefile b/tools/thermal/tmon/Makefile index 581da716ea1c..1e11bd38a6b4 100644 --- a/tools/thermal/tmon/Makefile +++ b/tools/thermal/tmon/Makefile @@ -9,6 +9,7 @@ CFLAGS+= -O1 ${WARNFLAGS} # Add "-fstack-protector" only if toolchain supports it. CFLAGS+= $(call cc-option,-fstack-protector) CC?= $(CROSS_COMPILE)gcc +PKG_CONFIG?= pkg-config CFLAGS+=-D VERSION=\"$(VERSION)\" LDFLAGS+= @@ -23,12 +24,12 @@ STATIC := --static endif TMON_LIBS=-lm -lpthread -TMON_LIBS += $(shell pkg-config --libs $(STATIC) panelw ncursesw 2> /dev/null || \ - pkg-config --libs $(STATIC) panel ncurses 2> /dev/null || \ +TMON_LIBS += $(shell $(PKG_CONFIG) --libs $(STATIC) panelw ncursesw 2> /dev/null || \ + $(PKG_CONFIG) --libs $(STATIC) panel ncurses 2> /dev/null || \ echo -lpanel -lncurses) -CFLAGS += $(shell pkg-config --cflags $(STATIC) panelw ncursesw 2> /dev/null || \ - pkg-config --cflags $(STATIC) panel ncurses 2> /dev/null) +CFLAGS += $(shell $(PKG_CONFIG) --cflags $(STATIC) panelw ncursesw 2> /dev/null || \ + $(PKG_CONFIG) --cflags $(STATIC) panel ncurses 2> /dev/null) OBJS = tmon.o tui.o sysfs.o pid.o OBJS += -- GitLab From 531fcdeb71f0be1d4c77838b1a4694c317b1eb98 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 18 Sep 2017 22:48:16 +0200 Subject: [PATCH 1227/2898] thermal: imx: add NVMEM dependency The driver now fails to link into vmlinux when CONFIG_NVMEM is a loadable module: drivers/thermal/imx_thermal.o: In function `imx_thermal_probe': imx_thermal.c:(.text+0x360): undefined reference to `nvmem_cell_read_u32' imx_thermal.c:(.text+0x360): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `nvmem_cell_read_u32' imx_thermal.c:(.text+0x388): undefined reference to `nvmem_cell_read_u32' imx_thermal.c:(.text+0x388): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `nvmem_cell_read_u32' This adds a Kconfig dependency to force it to be a module as well when its dependency is loadable. Fixes: 7fe5ba04fcdc ("thermal: imx: Add support for reading OCOTP through nvmem") Signed-off-by: Arnd Bergmann Reviewed-by: Leonard Crestez Signed-off-by: Zhang Rui --- drivers/thermal/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 07002df4f83a..cb14f1ec5953 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -206,6 +206,7 @@ config HISI_THERMAL config IMX_THERMAL tristate "Temperature sensor driver for Freescale i.MX SoCs" depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST + depends on NVMEM || !NVMEM depends on MFD_SYSCON depends on OF help -- GitLab From 93b138dd9d6e01cd360f347512b6c5bf6f0c4ce2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 18 Sep 2017 00:01:44 +0900 Subject: [PATCH 1228/2898] printk: simplify no_printk() Commit 069f0cd00df0 ("printk: Make the printk*once() variants return a value") surrounded the macro implementation with ({ ... }). Now, the inner do { ... } while (0); is redundant. Link: http://lkml.kernel.org/r/1505660504-11059-1-git-send-email-yamada.masahiro@socionext.com Cc: Andrew Morton Cc: Ingo Molnar Cc: Masahiro Yamada Cc: Steven Rostedt Cc: linux-kernel@vger.kernel.org Signed-off-by: Masahiro Yamada Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- include/linux/printk.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index e10f27468322..7911f7364346 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -131,10 +131,8 @@ struct va_format { */ #define no_printk(fmt, ...) \ ({ \ - do { \ - if (0) \ - printk(fmt, ##__VA_ARGS__); \ - } while (0); \ + if (0) \ + printk(fmt, ##__VA_ARGS__); \ 0; \ }) -- GitLab From 231ca2e583be324012212d10ad913f30c2f66adb Mon Sep 17 00:00:00 2001 From: Timo Alho Date: Thu, 7 Sep 2017 12:31:02 +0300 Subject: [PATCH 1229/2898] clk: tegra: Check BPMP response return code Check return code in BPMP response message(s). The typical error case is when a clock operation is attempted with an invalid clock identifier. Also remove error print from call to clk_get_info() as the implementation loops through the range of all possible identifiers, yet the operation is expected to error out when the clock ID is unused. Signed-off-by: Timo Alho Acked-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-bpmp.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c index 638ace64033b..a896692b74ec 100644 --- a/drivers/clk/tegra/clk-bpmp.c +++ b/drivers/clk/tegra/clk-bpmp.c @@ -55,6 +55,7 @@ struct tegra_bpmp_clk_message { struct { void *data; size_t size; + int ret; } rx; }; @@ -64,6 +65,7 @@ static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp, struct mrq_clk_request request; struct tegra_bpmp_message msg; void *req = &request; + int err; memset(&request, 0, sizeof(request)); request.cmd_and_id = (clk->cmd << 24) | clk->id; @@ -84,7 +86,13 @@ static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp, msg.rx.data = clk->rx.data; msg.rx.size = clk->rx.size; - return tegra_bpmp_transfer(bpmp, &msg); + err = tegra_bpmp_transfer(bpmp, &msg); + if (err < 0) + return err; + else if (msg.rx.ret < 0) + return -EINVAL; + + return 0; } static int tegra_bpmp_clk_prepare(struct clk_hw *hw) @@ -414,11 +422,8 @@ static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp, struct tegra_bpmp_clk_info *info = &clocks[count]; err = tegra_bpmp_clk_get_info(bpmp, id, info); - if (err < 0) { - dev_err(bpmp->dev, "failed to query clock %u: %d\n", - id, err); + if (err < 0) continue; - } if (info->num_parents >= U8_MAX) { dev_err(bpmp->dev, -- GitLab From 8be95190dac73a8b6bfc51a7c3ad6ec3d0a4d5f7 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 30 Aug 2017 12:11:53 +0200 Subject: [PATCH 1230/2898] clk: tegra: Add peripheral clock registration helper There is a common pattern that registers individual peripheral clocks from an initialization table. Add a common implementation to remove the duplication from various call sites. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-periph.c | 8 ++++++++ drivers/clk/tegra/clk.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index cf80831de79d..9475c00b7cf9 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -203,3 +203,11 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, return _tegra_clk_register_periph(name, parent_names, num_parents, periph, clk_base, offset, CLK_SET_RATE_PARENT); } + +struct clk *tegra_clk_register_periph_data(void __iomem *clk_base, + struct tegra_periph_init_data *init) +{ + return _tegra_clk_register_periph(init->name, init->p.parent_names, + init->num_parents, &init->periph, + clk_base, init->offset, init->flags); +} diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 872f1189ad7f..3b2763df51c2 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -662,6 +662,9 @@ struct tegra_periph_init_data { _clk_num, _gate_flags, _clk_id,\ NULL, 0, NULL) +struct clk *tegra_clk_register_periph_data(void __iomem *clk_base, + struct tegra_periph_init_data *init); + /** * struct clk_super_mux - super clock * -- GitLab From 1d7e2c8e5431454f65f0b785f3aa8bdba2ff436d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 30 Aug 2017 12:19:08 +0200 Subject: [PATCH 1231/2898] clk: tegra: Use tegra_clk_register_periph_data() Instead of open-coding the same pattern repeatedly, reuse the newly introduced tegra_clk_register_periph_data() helper that will unpack the initialization structure. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 5 +---- drivers/clk/tegra/clk-tegra114.c | 4 +--- drivers/clk/tegra/clk-tegra20.c | 4 +--- drivers/clk/tegra/clk-tegra30.c | 4 +--- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 848255cc0209..090a5d792341 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -927,10 +927,7 @@ static void __init periph_clk_init(void __iomem *clk_base, continue; data->periph.gate.regs = bank; - clk = tegra_clk_register_periph(data->name, - data->p.parent_names, data->num_parents, - &data->periph, clk_base, data->offset, - data->flags); + clk = tegra_clk_register_periph_data(clk_base, data); *dt_clk = clk; } } diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index fd1a99c05c2d..63087d17c3e2 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1092,9 +1092,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base, for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, - data->p.parent_names, data->num_parents, - &data->periph, clk_base, data->offset, data->flags); + clk = tegra_clk_register_periph_data(clk_base, data); clks[data->clk_id] = clk; } diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 837e5cbd60e9..2b839cb24436 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -850,9 +850,7 @@ static void __init tegra20_periph_clk_init(void) for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, data->p.parent_names, - data->num_parents, &data->periph, - clk_base, data->offset, data->flags); + clk = tegra_clk_register_periph_data(clk_base, data); clks[data->clk_id] = clk; } diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index a2d163f759b4..98e8a55e4e1c 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1079,9 +1079,7 @@ static void __init tegra30_periph_clk_init(void) for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { data = &tegra_periph_clk_list[i]; - clk = tegra_clk_register_periph(data->name, data->p.parent_names, - data->num_parents, &data->periph, - clk_base, data->offset, data->flags); + clk = tegra_clk_register_periph_data(clk_base, data); clks[data->clk_id] = clk; } -- GitLab From bc2e4d2986e9d2b8a99c16eb8222da2a360a581f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 30 Aug 2017 12:21:04 +0200 Subject: [PATCH 1232/2898] clk: tegra: Fix sor1_out clock implementation This clock was previously called sor1_src and was modelled as an input to the sor1 module clock. However, it's really an output clock that can be fed either from the safe, the sor1_pad_clkout or the sor1 module clocks. sor1 itself can take input from either of the display PLLs. The same implementation for the sor1_out clock is used on Tegra186, so this nicely lines up both SoC generations to deal with this clock in a uniform way. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 16 ---------- drivers/clk/tegra/clk-tegra210.c | 47 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 090a5d792341..c7694205573f 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -129,7 +129,6 @@ #define CLK_SOURCE_NVDEC 0x698 #define CLK_SOURCE_NVJPG 0x69c #define CLK_SOURCE_APE 0x6c0 -#define CLK_SOURCE_SOR1 0x410 #define CLK_SOURCE_SDMMC_LEGACY 0x694 #define CLK_SOURCE_QSPI 0x6c4 #define CLK_SOURCE_VI_I2C 0x6c8 @@ -278,7 +277,6 @@ static DEFINE_SPINLOCK(PLLP_OUTA_lock); static DEFINE_SPINLOCK(PLLP_OUTB_lock); static DEFINE_SPINLOCK(PLLP_OUTC_lock); static DEFINE_SPINLOCK(sor0_lock); -static DEFINE_SPINLOCK(sor1_lock); #define MUX_I2S_SPDIF(_id) \ static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \ @@ -604,18 +602,6 @@ static u32 mux_pllp_plld_plld2_clkm_idx[] = { [0] = 0, [1] = 2, [2] = 5, [3] = 6 }; -static const char *mux_sor_safe_sor1_brick_sor1_src[] = { - /* - * Bit 0 of the mux selects sor1_brick, irrespective of bit 1, so the - * sor1_brick parent appears twice in the list below. This is merely - * to support clk_get_parent() if firmware happened to set these bits - * to 0b11. While not an invalid setting, code should always set the - * bits to 0b01 to select sor1_brick. - */ - "sor_safe", "sor1_brick", "sor1_src", "sor1_brick" -}; -#define mux_sor_safe_sor1_brick_sor1_src_idx NULL - static const char *mux_pllp_pllre_clkm[] = { "pll_p", "pll_re_out1", "clk_m" }; @@ -804,8 +790,6 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("nvdec", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVDEC, 194, 0, tegra_clk_nvdec), MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg), MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape), - MUX8_NOGATE_LOCK("sor1_src", mux_pllp_plld_plld2_clkm, CLK_SOURCE_SOR1, tegra_clk_sor1_src, &sor1_lock), - NODIV("sor1", mux_sor_safe_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 14, MASK(2), 183, 0, tegra_clk_sor1, &sor1_lock), MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy), MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi), I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c), diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 6d7a613f2656..be7b736371f6 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -40,6 +40,7 @@ #define CLK_SOURCE_CSITE 0x1d4 #define CLK_SOURCE_EMC 0x19c +#define CLK_SOURCE_SOR1 0x410 #define PLLC_BASE 0x80 #define PLLC_OUT 0x84 @@ -264,6 +265,7 @@ static DEFINE_SPINLOCK(pll_d_lock); static DEFINE_SPINLOCK(pll_e_lock); static DEFINE_SPINLOCK(pll_re_lock); static DEFINE_SPINLOCK(pll_u_lock); +static DEFINE_SPINLOCK(sor1_lock); static DEFINE_SPINLOCK(emc_lock); /* possible OSC frequencies in Hz */ @@ -2628,10 +2630,35 @@ static int tegra210_init_pllu(void) return 0; } +static const char * const sor1_out_parents[] = { + /* + * Bit 0 of the mux selects sor1_pad_clkout, irrespective of bit 1, so + * the sor1_pad_clkout parent appears twice in the list below. This is + * merely to support clk_get_parent() if firmware happened to set + * these bits to 0b11. While not an invalid setting, code should + * always set the bits to 0b01 to select sor1_pad_clkout. + */ + "sor_safe", "sor1_pad_clkout", "sor1", "sor1_pad_clkout", +}; + +static const char * const sor1_parents[] = { + "pll_p", "pll_d_out0", "pll_d2_out0", "clk_m", +}; + +static u32 sor1_parents_idx[] = { 0, 2, 5, 6 }; + +static struct tegra_periph_init_data tegra210_periph[] = { + TEGRA_INIT_DATA_TABLE("sor1", NULL, NULL, sor1_parents, + CLK_SOURCE_SOR1, 29, 0x7, 0, 0, 8, 1, + TEGRA_DIVIDER_ROUND_UP, 183, 0, tegra_clk_sor1, + sor1_parents_idx, 0, &sor1_lock), +}; + static __init void tegra210_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base) { struct clk *clk; + unsigned int i; /* xusb_ss_div2 */ clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0, @@ -2650,6 +2677,12 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, 1, 17, 207); clks[TEGRA210_CLK_DPAUX1] = clk; + clk = clk_register_mux_table(NULL, "sor1_out", sor1_out_parents, + ARRAY_SIZE(sor1_out_parents), 0, + clk_base + CLK_SOURCE_SOR1, 14, 0x3, + 0, NULL, &sor1_lock); + clks[TEGRA210_CLK_SOR1_OUT] = clk; + /* pll_d_dsi_out */ clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, clk_base + PLLD_MISC0, 21, 0, &pll_d_lock); @@ -2694,6 +2727,20 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, 0, NULL); clks[TEGRA210_CLK_ACLK] = clk; + for (i = 0; i < ARRAY_SIZE(tegra210_periph); i++) { + struct tegra_periph_init_data *init = &tegra210_periph[i]; + struct clk **clkp; + + clkp = tegra_lookup_dt_id(init->clk_id, tegra210_clks); + if (!clkp) { + pr_warn("clock %u not found\n", init->clk_id); + continue; + } + + clk = tegra_clk_register_periph_data(clk_base, init); + *clkp = clk; + } + tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params); } -- GitLab From d83b26e0f2b013d29cc1431e35eb10c85e76784a Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 3 Oct 2017 01:42:08 +0530 Subject: [PATCH 1233/2898] clk: tegra: Make tegra_clk_pll_params __ro_after_init These structures are only passed to the functions tegra_clk_register_pll, tegra_clk_register_pll{e/u} or tegra_periph_clk_init during the init phase. These functions modify the structures only during the init phase and after that the structures are never modified. Therefore, make them __ro_after_init. Signed-off-by: Bhumika Goyal Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra30.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 98e8a55e4e1c..455502a42b20 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -359,7 +359,7 @@ static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { }; /* PLL parameters */ -static struct tegra_clk_pll_params pll_c_params = { +static struct tegra_clk_pll_params pll_c_params __ro_after_init = { .input_min = 2000000, .input_max = 31000000, .cf_min = 1000000, @@ -388,7 +388,7 @@ static struct div_nmp pllm_nmp = { .override_divp_shift = 15, }; -static struct tegra_clk_pll_params pll_m_params = { +static struct tegra_clk_pll_params pll_m_params __ro_after_init = { .input_min = 2000000, .input_max = 31000000, .cf_min = 1000000, @@ -409,7 +409,7 @@ static struct tegra_clk_pll_params pll_m_params = { TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_FIXED, }; -static struct tegra_clk_pll_params pll_p_params = { +static struct tegra_clk_pll_params pll_p_params __ro_after_init = { .input_min = 2000000, .input_max = 31000000, .cf_min = 1000000, @@ -444,7 +444,7 @@ static struct tegra_clk_pll_params pll_a_params = { TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_d_params = { +static struct tegra_clk_pll_params pll_d_params __ro_after_init = { .input_min = 2000000, .input_max = 40000000, .cf_min = 1000000, @@ -461,7 +461,7 @@ static struct tegra_clk_pll_params pll_d_params = { TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_d2_params = { +static struct tegra_clk_pll_params pll_d2_params __ro_after_init = { .input_min = 2000000, .input_max = 40000000, .cf_min = 1000000, @@ -478,7 +478,7 @@ static struct tegra_clk_pll_params pll_d2_params = { TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_u_params = { +static struct tegra_clk_pll_params pll_u_params __ro_after_init = { .input_min = 2000000, .input_max = 40000000, .cf_min = 1000000, @@ -496,7 +496,7 @@ static struct tegra_clk_pll_params pll_u_params = { TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_x_params = { +static struct tegra_clk_pll_params pll_x_params __ro_after_init = { .input_min = 2000000, .input_max = 31000000, .cf_min = 1000000, @@ -513,7 +513,7 @@ static struct tegra_clk_pll_params pll_x_params = { TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct tegra_clk_pll_params pll_e_params = { +static struct tegra_clk_pll_params pll_e_params __ro_after_init = { .input_min = 12000000, .input_max = 216000000, .cf_min = 12000000, -- GitLab From 7fc9be3c136c140b02021c7973b91b20fb1981e5 Mon Sep 17 00:00:00 2001 From: Ross Zwisler Date: Wed, 18 Oct 2017 09:40:06 -0600 Subject: [PATCH 1234/2898] MAINTAINERS: Add entry for device DAX And update the entry for filesystem DAX to differentiate them. Signed-off-by: Ross Zwisler Signed-off-by: Dan Williams --- MAINTAINERS | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 6671f375f7fc..456ba0725b8d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4162,7 +4162,7 @@ L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/busses/i2c-diolan-u2c.c -DIRECT ACCESS (DAX) +FILESYSTEM DIRECT ACCESS (DAX) M: Matthew Wilcox M: Ross Zwisler L: linux-fsdevel@vger.kernel.org @@ -4171,6 +4171,12 @@ F: fs/dax.c F: include/linux/dax.h F: include/trace/events/fs_dax.h +DEVICE DIRECT ACCESS (DAX) +M: Dan Williams +L: linux-nvdimm@lists.01.org +S: Supported +F: drivers/dax/ + DIRECTORY NOTIFICATION (DNOTIFY) M: Jan Kara R: Amir Goldstein -- GitLab From 0a3ff78699d1817e711441715d22665475466036 Mon Sep 17 00:00:00 2001 From: Ross Zwisler Date: Wed, 18 Oct 2017 12:21:55 -0600 Subject: [PATCH 1235/2898] dev/dax: fix uninitialized variable build warning Fix this build warning: warning: 'phys' may be used uninitialized in this function [-Wuninitialized] As reported here: https://lkml.org/lkml/2017/10/16/152 http://kisskb.ellerman.id.au/kisskb/buildresult/13181373/log/ Signed-off-by: Ross Zwisler Signed-off-by: Dan Williams --- drivers/dax/device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dax/device.c b/drivers/dax/device.c index e9f3b3e4bbf4..6833ada237ab 100644 --- a/drivers/dax/device.c +++ b/drivers/dax/device.c @@ -222,7 +222,8 @@ __weak phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff, unsigned long size) { struct resource *res; - phys_addr_t phys; + /* gcc-4.6.3-nolibc for i386 complains that this is uninitialized */ + phys_addr_t uninitialized_var(phys); int i; for (i = 0; i < dev_dax->num_resources; i++) { -- GitLab From 4cf8f811c64ab570d40cb2f4bfc723750aec122f Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 16 Oct 2017 17:34:44 +0200 Subject: [PATCH 1236/2898] clk: meson: gxbb: Add VPU and VAPB clockids Add the clkids for the clocks feeding the Video Processing Unit. Acked-by: Jerome Brunet Signed-off-by: Neil Armstrong --- drivers/clk/meson/gxbb.h | 6 +++++- include/dt-bindings/clock/gxbb-clkc.h | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index 5b1d4b374d1c..aee6fbba2004 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -190,8 +190,12 @@ #define CLKID_SD_EMMC_B_CLK0_DIV 121 #define CLKID_SD_EMMC_C_CLK0_SEL 123 #define CLKID_SD_EMMC_C_CLK0_DIV 124 +#define CLKID_VPU_0_DIV 127 +#define CLKID_VPU_1_DIV 130 +#define CLKID_VAPB_0_DIV 134 +#define CLKID_VAPB_1_DIV 137 -#define NR_CLKS 126 +#define NR_CLKS 141 /* include the CLKIDs that have been made part of the DT binding */ #include diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h index c04a76d8facf..7c5a6f3825a5 100644 --- a/include/dt-bindings/clock/gxbb-clkc.h +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -113,5 +113,16 @@ #define CLKID_SD_EMMC_A_CLK0 119 #define CLKID_SD_EMMC_B_CLK0 122 #define CLKID_SD_EMMC_C_CLK0 125 +#define CLKID_VPU_0_SEL 126 +#define CLKID_VPU_0 128 +#define CLKID_VPU_1_SEL 129 +#define CLKID_VPU_1 131 +#define CLKID_VPU 132 +#define CLKID_VAPB_0_SEL 133 +#define CLKID_VAPB_0 135 +#define CLKID_VAPB_1_SEL 136 +#define CLKID_VAPB_1 138 +#define CLKID_VAPB_SEL 139 +#define CLKID_VAPB 140 #endif /* __GXBB_CLKC_H */ -- GitLab From 762a1f2098b2fd4f84ccdb62d5747fff1ad7f816 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 16 Oct 2017 17:34:45 +0200 Subject: [PATCH 1237/2898] clk: meson: gxbb: Add VPU and VAPB clocks data The Amlogic Meson GX SoCs needs these two clocks to power up the VPU power domain. These two clocks are similar to the MALI clocks by having a glitch-free mux and two similar clocks with gate, divider and muxes. Acked-by: Jerome Brunet [narmstrong: removed the CLK_IGNORE_UNUSED on muxes and dividers] Signed-off-by: Neil Armstrong --- drivers/clk/meson/gxbb.c | 292 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index b2d1e8ed7152..ae385310e980 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -1131,6 +1131,253 @@ static struct clk_gate gxbb_sd_emmc_c_clk0 = { }, }; +/* VPU Clock */ + +static u32 mux_table_vpu[] = {0, 1, 2, 3}; +static const char * const gxbb_vpu_parent_names[] = { + "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +}; + +static struct clk_mux gxbb_vpu_0_sel = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .mask = 0x3, + .shift = 9, + .lock = &clk_lock, + .table = mux_table_vpu, + .hw.init = &(struct clk_init_data){ + .name = "vpu_0_sel", + .ops = &clk_mux_ops, + /* + * bits 9:10 selects from 4 possible parents: + * fclk_div4, fclk_div3, fclk_div5, fclk_div7, + */ + .parent_names = gxbb_vpu_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_vpu_0_div = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vpu_0_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "vpu_0_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_gate gxbb_vpu_0 = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .bit_idx = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vpu_0", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vpu_0_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + +static struct clk_mux gxbb_vpu_1_sel = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .mask = 0x3, + .shift = 25, + .lock = &clk_lock, + .table = mux_table_vpu, + .hw.init = &(struct clk_init_data){ + .name = "vpu_1_sel", + .ops = &clk_mux_ops, + /* + * bits 25:26 selects from 4 possible parents: + * fclk_div4, fclk_div3, fclk_div5, fclk_div7, + */ + .parent_names = gxbb_vpu_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_vpu_1_div = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .shift = 16, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vpu_1_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "vpu_1_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_gate gxbb_vpu_1 = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .bit_idx = 24, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vpu_1", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vpu_1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + +static struct clk_mux gxbb_vpu = { + .reg = (void *)HHI_VPU_CLK_CNTL, + .mask = 1, + .shift = 31, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vpu", + .ops = &clk_mux_ops, + /* + * bit 31 selects from 2 possible parents: + * vpu_0 or vpu_1 + */ + .parent_names = (const char *[]){ "vpu_0", "vpu_1" }, + .num_parents = 2, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +/* VAPB Clock */ + +static u32 mux_table_vapb[] = {0, 1, 2, 3}; +static const char * const gxbb_vapb_parent_names[] = { + "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +}; + +static struct clk_mux gxbb_vapb_0_sel = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .mask = 0x3, + .shift = 9, + .lock = &clk_lock, + .table = mux_table_vapb, + .hw.init = &(struct clk_init_data){ + .name = "vapb_0_sel", + .ops = &clk_mux_ops, + /* + * bits 9:10 selects from 4 possible parents: + * fclk_div4, fclk_div3, fclk_div5, fclk_div7, + */ + .parent_names = gxbb_vapb_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_vapb_0_div = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vapb_0_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "vapb_0_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_gate gxbb_vapb_0 = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .bit_idx = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vapb_0", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vapb_0_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + +static struct clk_mux gxbb_vapb_1_sel = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .mask = 0x3, + .shift = 25, + .lock = &clk_lock, + .table = mux_table_vapb, + .hw.init = &(struct clk_init_data){ + .name = "vapb_1_sel", + .ops = &clk_mux_ops, + /* + * bits 25:26 selects from 4 possible parents: + * fclk_div4, fclk_div3, fclk_div5, fclk_div7, + */ + .parent_names = gxbb_vapb_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_vapb_1_div = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .shift = 16, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vapb_1_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "vapb_1_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_gate gxbb_vapb_1 = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .bit_idx = 24, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vapb_1", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vapb_1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + +static struct clk_mux gxbb_vapb_sel = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .mask = 1, + .shift = 31, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vapb_sel", + .ops = &clk_mux_ops, + /* + * bit 31 selects from 2 possible parents: + * vapb_0 or vapb_1 + */ + .parent_names = (const char *[]){ "vapb_0", "vapb_1" }, + .num_parents = 2, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_gate gxbb_vapb = { + .reg = (void *)HHI_VAPBCLK_CNTL, + .bit_idx = 30, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data) { + .name = "vapb", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "vapb_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + }, +}; + /* Everything Else (EE) domain gates */ static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); @@ -1349,6 +1596,21 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, + [CLKID_VPU_0_SEL] = &gxbb_vpu_0_sel.hw, + [CLKID_VPU_0_DIV] = &gxbb_vpu_0_div.hw, + [CLKID_VPU_0] = &gxbb_vpu_0.hw, + [CLKID_VPU_1_SEL] = &gxbb_vpu_1_sel.hw, + [CLKID_VPU_1_DIV] = &gxbb_vpu_1_div.hw, + [CLKID_VPU_1] = &gxbb_vpu_1.hw, + [CLKID_VPU] = &gxbb_vpu.hw, + [CLKID_VAPB_0_SEL] = &gxbb_vapb_0_sel.hw, + [CLKID_VAPB_0_DIV] = &gxbb_vapb_0_div.hw, + [CLKID_VAPB_0] = &gxbb_vapb_0.hw, + [CLKID_VAPB_1_SEL] = &gxbb_vapb_1_sel.hw, + [CLKID_VAPB_1_DIV] = &gxbb_vapb_1_div.hw, + [CLKID_VAPB_1] = &gxbb_vapb_1.hw, + [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, + [CLKID_VAPB] = &gxbb_vapb.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1481,6 +1743,21 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, + [CLKID_VPU_0_SEL] = &gxbb_vpu_0_sel.hw, + [CLKID_VPU_0_DIV] = &gxbb_vpu_0_div.hw, + [CLKID_VPU_0] = &gxbb_vpu_0.hw, + [CLKID_VPU_1_SEL] = &gxbb_vpu_1_sel.hw, + [CLKID_VPU_1_DIV] = &gxbb_vpu_1_div.hw, + [CLKID_VPU_1] = &gxbb_vpu_1.hw, + [CLKID_VPU] = &gxbb_vpu.hw, + [CLKID_VAPB_0_SEL] = &gxbb_vapb_0_sel.hw, + [CLKID_VAPB_0_DIV] = &gxbb_vapb_0_div.hw, + [CLKID_VAPB_0] = &gxbb_vapb_0.hw, + [CLKID_VAPB_1_SEL] = &gxbb_vapb_1_sel.hw, + [CLKID_VAPB_1_DIV] = &gxbb_vapb_1_div.hw, + [CLKID_VAPB_1] = &gxbb_vapb_1.hw, + [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, + [CLKID_VAPB] = &gxbb_vapb.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1600,6 +1877,11 @@ static struct clk_gate *const gxbb_clk_gates[] = { &gxbb_sd_emmc_a_clk0, &gxbb_sd_emmc_b_clk0, &gxbb_sd_emmc_c_clk0, + &gxbb_vpu_0, + &gxbb_vpu_1, + &gxbb_vapb_0, + &gxbb_vapb_1, + &gxbb_vapb, }; static struct clk_mux *const gxbb_clk_muxes[] = { @@ -1615,6 +1897,12 @@ static struct clk_mux *const gxbb_clk_muxes[] = { &gxbb_sd_emmc_a_clk0_sel, &gxbb_sd_emmc_b_clk0_sel, &gxbb_sd_emmc_c_clk0_sel, + &gxbb_vpu_0_sel, + &gxbb_vpu_1_sel, + &gxbb_vpu, + &gxbb_vapb_0_sel, + &gxbb_vapb_1_sel, + &gxbb_vapb_sel, }; static struct clk_divider *const gxbb_clk_dividers[] = { @@ -1627,6 +1915,10 @@ static struct clk_divider *const gxbb_clk_dividers[] = { &gxbb_sd_emmc_a_clk0_div, &gxbb_sd_emmc_b_clk0_div, &gxbb_sd_emmc_c_clk0_div, + &gxbb_vpu_0_div, + &gxbb_vpu_1_div, + &gxbb_vapb_0_div, + &gxbb_vapb_1_div, }; static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { -- GitLab From d454cecc637b90996ab15b2e61a6cc51b7e1463c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 12 Oct 2017 10:54:22 +0200 Subject: [PATCH 1238/2898] clk: renesas: rz: clk-rz is meant for RZ/A1 The RZ family of Renesas SoCs has several different subfamilies (RZ/A, RZ/G, RZ/N, and RZ/T). Clarify that the renesas,rz-cpg-clocks DT bindings and clk-rz driver apply to RZ/A1 only. Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman Acked-by: Rob Herring --- .../devicetree/bindings/clock/renesas,rz-cpg-clocks.txt | 4 ++-- drivers/clk/renesas/clk-rz.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt index bb5d942075fb..8ff3e2774ed8 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt +++ b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt @@ -1,6 +1,6 @@ -* Renesas RZ Clock Pulse Generator (CPG) +* Renesas RZ/A1 Clock Pulse Generator (CPG) -The CPG generates core clocks for the RZ SoCs. It includes the PLL, variable +The CPG generates core clocks for the RZ/A1 SoCs. It includes the PLL, variable CPU and GPU clocks, and several fixed ratio dividers. The CPG also provides a Clock Domain for SoC devices, in combination with the CPG Module Stop (MSTP) Clocks. diff --git a/drivers/clk/renesas/clk-rz.c b/drivers/clk/renesas/clk-rz.c index 5adb934326d1..127c58135c8f 100644 --- a/drivers/clk/renesas/clk-rz.c +++ b/drivers/clk/renesas/clk-rz.c @@ -1,5 +1,5 @@ /* - * rz Core CPG Clocks + * RZ/A1 Core CPG Clocks * * Copyright (C) 2013 Ideas On Board SPRL * Copyright (C) 2014 Wolfram Sang, Sang Engineering -- GitLab From 9dc0ddee8d6dcc201b7f9ebc1c0834b0fa306096 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Fri, 13 Oct 2017 16:22:21 +0100 Subject: [PATCH 1239/2898] clk: renesas: cpg-mssr: Add du1 clock to R8A7745 Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7745-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r8a7745-cpg-mssr.c b/drivers/clk/renesas/r8a7745-cpg-mssr.c index 9e2360a8e14b..2859504cc866 100644 --- a/drivers/clk/renesas/r8a7745-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7745-cpg-mssr.c @@ -129,6 +129,7 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = { DEF_MOD("scif2", 719, R8A7745_CLK_P), DEF_MOD("scif1", 720, R8A7745_CLK_P), DEF_MOD("scif0", 721, R8A7745_CLK_P), + DEF_MOD("du1", 723, R8A7745_CLK_ZX), DEF_MOD("du0", 724, R8A7745_CLK_ZX), DEF_MOD("ipmmu-sgx", 800, R8A7745_CLK_ZX), DEF_MOD("vin1", 810, R8A7745_CLK_ZG), -- GitLab From d9341f2b00c0f2a50e1fada55f6a2a2c51818ae6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Sep 2017 09:44:54 +0200 Subject: [PATCH 1240/2898] MAINTAINERS: Add git repository to Renesas clock driver section Signed-off-by: Geert Uytterhoeven Reviewed-by: Simon Horman Acked-by: Stephen Boyd --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2281af4b41b6..d709a24db7e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11428,6 +11428,7 @@ F: include/linux/rpmsg/ RENESAS CLOCK DRIVERS M: Geert Uytterhoeven L: linux-renesas-soc@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git clk-renesas S: Supported F: drivers/clk/renesas/ -- GitLab From 560869100b99a3daea329efce738a3b7ae357be8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 7 Jun 2017 13:20:06 +0200 Subject: [PATCH 1241/2898] clk: renesas: cpg-mssr: Restore module clocks during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During PSCI system suspend, R-Car Gen3 SoCs are powered down, and their clock register state is lost. Note that as the boot loader skips most initialization after system resume, clock register state differs from the state encountered during normal system boot, too. Hence after s2ram, some operations may fail because module clocks are disabled, while drivers expect them to be still enabled. E.g. EtherAVB fails when Wake-on-LAN has been enabled using "ethtool -s eth0 wol g": ravb e6800000.ethernet eth0: failed to switch device to config mode ravb e6800000.ethernet eth0: device will be stopped after h/w processes are done. ravb e6800000.ethernet eth0: failed to switch device to config PM: Device e6800000.ethernet failed to resume: error -110 In addition, some module clocks that were disabled by clk_disable_unused() may have been re-enabled, wasting power. To fix this, restore all bits of the SMSTPCR registers that represent clocks under control of Linux. Notes: - While this fixes EtherAVB operation after resume from s2ram, EtherAVB cannot be used as an actual wake-up source from s2ram, only from s2idle, due to PSCI limitations, - To avoid overhead on platforms not needing it, the suspend/resume code has a build time dependency on sleep and PSCI support, and a runtime dependency on PSCI. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/renesas-cpg-mssr.c | 84 ++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 1779b0cc7a2a..15fc8679d342 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,8 @@ static const u16 srcr[] = { * @num_core_clks: Number of Core Clocks in clks[] * @num_mod_clks: Number of Module Clocks in clks[] * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control + * @smstpcr_saved[].val: Saved values of SMSTPCR[] */ struct cpg_mssr_priv { #ifdef CONFIG_RESET_CONTROLLER @@ -119,6 +122,11 @@ struct cpg_mssr_priv { unsigned int num_core_clks; unsigned int num_mod_clks; unsigned int last_dt_core_clk; + + struct { + u32 mask; + u32 val; + } smstpcr_saved[ARRAY_SIZE(smstpcr)]; }; @@ -382,6 +390,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk); priv->clks[id] = clk; + priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32); return; fail: @@ -700,6 +709,79 @@ static void cpg_mssr_del_clk_provider(void *data) of_clk_del_provider(data); } +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW) +static int cpg_mssr_suspend_noirq(struct device *dev) +{ + struct cpg_mssr_priv *priv = dev_get_drvdata(dev); + unsigned int reg; + + /* This is the best we can do to check for the presence of PSCI */ + if (!psci_ops.cpu_suspend) + return 0; + + /* Save module registers with bits under our control */ + for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) { + if (priv->smstpcr_saved[reg].mask) + priv->smstpcr_saved[reg].val = + readl(priv->base + SMSTPCR(reg)); + } + + return 0; +} + +static int cpg_mssr_resume_noirq(struct device *dev) +{ + struct cpg_mssr_priv *priv = dev_get_drvdata(dev); + unsigned int reg, i; + u32 mask, oldval, newval; + + /* This is the best we can do to check for the presence of PSCI */ + if (!psci_ops.cpu_suspend) + return 0; + + /* Restore module clocks */ + for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) { + mask = priv->smstpcr_saved[reg].mask; + if (!mask) + continue; + + oldval = readl(priv->base + SMSTPCR(reg)); + newval = oldval & ~mask; + newval |= priv->smstpcr_saved[reg].val & mask; + if (newval == oldval) + continue; + + writel(newval, priv->base + SMSTPCR(reg)); + + /* Wait until enabled clocks are really enabled */ + mask &= ~priv->smstpcr_saved[reg].val; + if (!mask) + continue; + + for (i = 1000; i > 0; --i) { + oldval = readl(priv->base + MSTPSR(reg)); + if (!(oldval & mask)) + break; + cpu_relax(); + } + + if (!i) + dev_warn(dev, "Failed to enable SMSTP %p[0x%x]\n", + priv->base + SMSTPCR(reg), oldval & mask); + } + + return 0; +} + +static const struct dev_pm_ops cpg_mssr_pm = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cpg_mssr_suspend_noirq, + cpg_mssr_resume_noirq) +}; +#define DEV_PM_OPS &cpg_mssr_pm +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */ + static int __init cpg_mssr_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -735,6 +817,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev) if (!clks) return -ENOMEM; + dev_set_drvdata(dev, priv); priv->clks = clks; priv->num_core_clks = info->num_total_core_clks; priv->num_mod_clks = info->num_hw_mod_clks; @@ -775,6 +858,7 @@ static struct platform_driver cpg_mssr_driver = { .driver = { .name = "renesas-cpg-mssr", .of_match_table = cpg_mssr_match, + .pm = DEV_PM_OPS, }, }; -- GitLab From 1f4023cdd1bdbe6cb01d0b2cbd1f46207189e3cf Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Jun 2017 22:24:15 +0200 Subject: [PATCH 1242/2898] clk: renesas: cpg-mssr: Add support to restore core clocks during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On R-Car Gen3 systems, PSCI system suspend powers down the SoC, possibly losing clock configuration. Hence add a notifier chain that can be used by core clocks to save/restore clock state during system suspend/resume. The implementation of the actual clock state save/restore operations is clock-specific, and to be registered with the notifier chain in the SoC or family-specific cpg_mssr_info.cpg_clk_register() callback. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/rcar-gen2-cpg.c | 7 +++---- drivers/clk/renesas/rcar-gen2-cpg.h | 6 +++--- drivers/clk/renesas/rcar-gen3-cpg.c | 3 ++- drivers/clk/renesas/rcar-gen3-cpg.h | 3 ++- drivers/clk/renesas/renesas-cpg-mssr.c | 12 +++++++++++- drivers/clk/renesas/renesas-cpg-mssr.h | 3 ++- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen2-cpg.c b/drivers/clk/renesas/rcar-gen2-cpg.c index 123b1e622179..feb14579a71b 100644 --- a/drivers/clk/renesas/rcar-gen2-cpg.c +++ b/drivers/clk/renesas/rcar-gen2-cpg.c @@ -262,10 +262,9 @@ static unsigned int cpg_pll0_div __initdata; static u32 cpg_mode __initdata; struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev, - const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct clk **clks, - void __iomem *base) + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers) { const struct clk_div_table *table = NULL; const struct clk *parent; diff --git a/drivers/clk/renesas/rcar-gen2-cpg.h b/drivers/clk/renesas/rcar-gen2-cpg.h index 9eba07ff8b11..020a3baad015 100644 --- a/drivers/clk/renesas/rcar-gen2-cpg.h +++ b/drivers/clk/renesas/rcar-gen2-cpg.h @@ -34,9 +34,9 @@ struct rcar_gen2_cpg_pll_config { }; struct clk *rcar_gen2_cpg_clk_register(struct device *dev, - const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base); + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers); int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config, unsigned int pll0_div, u32 mode); diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 951105816547..139985257003 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -265,7 +265,8 @@ static const struct soc_device_attribute cpg_quirks_match[] __initconst = { struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base) + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers) { const struct clk *parent; unsigned int mult = 1; diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index d756ef8b78eb..2e4284399f53 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -44,7 +44,8 @@ struct rcar_gen3_cpg_pll_config { struct clk *rcar_gen3_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base); + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers); int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, unsigned int clk_extalr, u32 mode); diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 15fc8679d342..485dce00a562 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -107,6 +107,7 @@ static const u16 srcr[] = { * @num_core_clks: Number of Core Clocks in clks[] * @num_mod_clks: Number of Module Clocks in clks[] * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @notifiers: Notifier chain to save/restore clock state for system resume * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control * @smstpcr_saved[].val: Saved values of SMSTPCR[] */ @@ -123,6 +124,7 @@ struct cpg_mssr_priv { unsigned int num_mod_clks; unsigned int last_dt_core_clk; + struct raw_notifier_head notifiers; struct { u32 mask; u32 val; @@ -312,7 +314,8 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, default: if (info->cpg_clk_register) clk = info->cpg_clk_register(dev, core, info, - priv->clks, priv->base); + priv->clks, priv->base, + &priv->notifiers); else dev_err(dev, "%s has unsupported core clock type %u\n", core->name, core->type); @@ -726,6 +729,9 @@ static int cpg_mssr_suspend_noirq(struct device *dev) readl(priv->base + SMSTPCR(reg)); } + /* Save core clocks */ + raw_notifier_call_chain(&priv->notifiers, PM_EVENT_SUSPEND, NULL); + return 0; } @@ -739,6 +745,9 @@ static int cpg_mssr_resume_noirq(struct device *dev) if (!psci_ops.cpu_suspend) return 0; + /* Restore core clocks */ + raw_notifier_call_chain(&priv->notifiers, PM_EVENT_RESUME, NULL); + /* Restore module clocks */ for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) { mask = priv->smstpcr_saved[reg].mask; @@ -822,6 +831,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev) priv->num_core_clks = info->num_total_core_clks; priv->num_mod_clks = info->num_hw_mod_clks; priv->last_dt_core_clk = info->last_dt_core_clk; + RAW_INIT_NOTIFIER_HEAD(&priv->notifiers); for (i = 0; i < nclks; i++) clks[i] = ERR_PTR(-ENOENT); diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 66528ce3eb37..0745b0930308 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -127,7 +127,8 @@ struct cpg_mssr_info { struct clk *(*cpg_clk_register)(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, - struct clk **clks, void __iomem *base); + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers); }; extern const struct cpg_mssr_info r8a7743_cpg_mssr_info; -- GitLab From 9f8c71e5134982cdf8ee35acb204715a2a47ba2e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Jun 2017 22:34:33 +0200 Subject: [PATCH 1243/2898] clk: renesas: div6: Restore clock state during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On R-Car Gen3 systems, PSCI system suspend powers down the SoC, losing clock configuration. Register an (optional) notifier to restore the DIV6 clock state during system resume. As DIV6 clocks can be picky w.r.t. modifying multiple register fields at once, restore is not implemented by blindly restoring the register value, but by using the existing cpg_div6_clock_{en,dis}able() helpers. Note that this does not yet support DIV6 clocks with multiple parents, which do not exist on R-Car Gen3 SoCs. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/clk-div6.c | 38 ++++++++++++++++++++++++-- drivers/clk/renesas/clk-div6.h | 3 +- drivers/clk/renesas/renesas-cpg-mssr.c | 3 +- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index 3e0040c0ac87..151336d2ba59 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -14,8 +14,10 @@ #include #include #include +#include #include #include +#include #include #include "clk-div6.h" @@ -32,6 +34,7 @@ * @src_shift: Shift to access the register bits to select the parent clock * @src_width: Number of register bits to select the parent clock (may be 0) * @parents: Array to map from valid parent clocks indices to hardware indices + * @nb: Notifier block to save/restore clock state for system resume */ struct div6_clock { struct clk_hw hw; @@ -40,6 +43,7 @@ struct div6_clock { u32 src_shift; u32 src_width; u8 *parents; + struct notifier_block nb; }; #define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw) @@ -176,6 +180,29 @@ static const struct clk_ops cpg_div6_clock_ops = { .set_rate = cpg_div6_clock_set_rate, }; +static int cpg_div6_clock_notifier_call(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct div6_clock *clock = container_of(nb, struct div6_clock, nb); + + switch (action) { + case PM_EVENT_RESUME: + /* + * TODO: This does not yet support DIV6 clocks with multiple + * parents, as the parent selection bits are not restored. + * Fortunately so far such DIV6 clocks are found only on + * R/SH-Mobile SoCs, while the resume functionality is only + * needed on R-Car Gen3. + */ + if (__clk_get_enable_count(clock->hw.clk)) + cpg_div6_clock_enable(&clock->hw); + else + cpg_div6_clock_disable(&clock->hw); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} /** * cpg_div6_register - Register a DIV6 clock @@ -183,11 +210,13 @@ static const struct clk_ops cpg_div6_clock_ops = { * @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8) * @parent_names: Array containing the names of the parent clocks * @reg: Mapped register used to control the DIV6 clock + * @notifiers: Optional notifier chain to save/restore state for system resume */ struct clk * __init cpg_div6_register(const char *name, unsigned int num_parents, const char **parent_names, - void __iomem *reg) + void __iomem *reg, + struct raw_notifier_head *notifiers) { unsigned int valid_parents; struct clk_init_data init; @@ -258,6 +287,11 @@ struct clk * __init cpg_div6_register(const char *name, if (IS_ERR(clk)) goto free_parents; + if (notifiers) { + clock->nb.notifier_call = cpg_div6_clock_notifier_call; + raw_notifier_chain_register(notifiers, &clock->nb); + } + return clk; free_parents: @@ -301,7 +335,7 @@ static void __init cpg_div6_clock_init(struct device_node *np) for (i = 0; i < num_parents; i++) parent_names[i] = of_clk_get_parent_name(np, i); - clk = cpg_div6_register(clk_name, num_parents, parent_names, reg); + clk = cpg_div6_register(clk_name, num_parents, parent_names, reg, NULL); if (IS_ERR(clk)) { pr_err("%s: failed to register %s DIV6 clock (%ld)\n", __func__, np->name, PTR_ERR(clk)); diff --git a/drivers/clk/renesas/clk-div6.h b/drivers/clk/renesas/clk-div6.h index 567b31d2bfa5..da4807299dda 100644 --- a/drivers/clk/renesas/clk-div6.h +++ b/drivers/clk/renesas/clk-div6.h @@ -2,6 +2,7 @@ #define __RENESAS_CLK_DIV6_H__ struct clk *cpg_div6_register(const char *name, unsigned int num_parents, - const char **parent_names, void __iomem *reg); + const char **parent_names, void __iomem *reg, + struct raw_notifier_head *notifiers); #endif diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 485dce00a562..e3d03ffea4bc 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -303,7 +303,8 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, if (core->type == CLK_TYPE_DIV6P1) { clk = cpg_div6_register(core->name, 1, &parent_name, - priv->base + core->offset); + priv->base + core->offset, + &priv->notifiers); } else { clk = clk_register_fixed_factor(NULL, core->name, parent_name, 0, -- GitLab From 9f55b17ff6387ab9c4caa9280e2e194bb03ad532 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 21 Jun 2017 22:51:21 +0200 Subject: [PATCH 1244/2898] clk: renesas: rcar-gen3: Restore SDHI clocks during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On R-Car Gen3 systems, PSCI system suspend powers down the SoC, losing clock configuration. Register a notifier to save/restore SDHI clock registers during system suspend/resume. This is implemented using the cpg_simple_notifier abstraction, which can be reused for others clocks that just need to save/restore a single register. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/rcar-gen3-cpg.c | 63 +++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 139985257003..267b5629e3bd 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,36 @@ #define CPG_PLL2CR 0x002c #define CPG_PLL4CR 0x01f4 +struct cpg_simple_notifier { + struct notifier_block nb; + void __iomem *reg; + u32 saved; +}; + +static int cpg_simple_notifier_call(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct cpg_simple_notifier *csn = + container_of(nb, struct cpg_simple_notifier, nb); + + switch (action) { + case PM_EVENT_SUSPEND: + csn->saved = readl(csn->reg); + return NOTIFY_OK; + + case PM_EVENT_RESUME: + writel(csn->saved, csn->reg); + return NOTIFY_OK; + } + return NOTIFY_DONE; +} + +static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, + struct cpg_simple_notifier *csn) +{ + csn->nb.notifier_call = cpg_simple_notifier_call; + raw_notifier_chain_register(notifiers, &csn->nb); +} /* * SDn Clock @@ -55,8 +86,8 @@ struct sd_div_table { struct sd_clock { struct clk_hw hw; - void __iomem *reg; const struct sd_div_table *div_table; + struct cpg_simple_notifier csn; unsigned int div_num; unsigned int div_min; unsigned int div_max; @@ -97,12 +128,12 @@ static const struct sd_div_table cpg_sd_div_table[] = { static int cpg_sd_clock_enable(struct clk_hw *hw) { struct sd_clock *clock = to_sd_clock(hw); - u32 val = readl(clock->reg); + u32 val = readl(clock->csn.reg); val &= ~(CPG_SD_STP_MASK); val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK; - writel(val, clock->reg); + writel(val, clock->csn.reg); return 0; } @@ -111,14 +142,14 @@ static void cpg_sd_clock_disable(struct clk_hw *hw) { struct sd_clock *clock = to_sd_clock(hw); - writel(readl(clock->reg) | CPG_SD_STP_MASK, clock->reg); + writel(readl(clock->csn.reg) | CPG_SD_STP_MASK, clock->csn.reg); } static int cpg_sd_clock_is_enabled(struct clk_hw *hw) { struct sd_clock *clock = to_sd_clock(hw); - return !(readl(clock->reg) & CPG_SD_STP_MASK); + return !(readl(clock->csn.reg) & CPG_SD_STP_MASK); } static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, @@ -170,10 +201,10 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, clock->cur_div_idx = i; - val = readl(clock->reg); + val = readl(clock->csn.reg); val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); - writel(val, clock->reg); + writel(val, clock->csn.reg); return 0; } @@ -188,8 +219,8 @@ static const struct clk_ops cpg_sd_clock_ops = { }; static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, - void __iomem *base, - const char *parent_name) + void __iomem *base, const char *parent_name, + struct raw_notifier_head *notifiers) { struct clk_init_data init; struct sd_clock *clock; @@ -207,12 +238,12 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, init.parent_names = &parent_name; init.num_parents = 1; - clock->reg = base + core->offset; + clock->csn.reg = base + core->offset; clock->hw.init = &init; clock->div_table = cpg_sd_div_table; clock->div_num = ARRAY_SIZE(cpg_sd_div_table); - sd_fc = readl(clock->reg) & CPG_SD_FC_MASK; + sd_fc = readl(clock->csn.reg) & CPG_SD_FC_MASK; for (i = 0; i < clock->div_num; i++) if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) break; @@ -233,8 +264,13 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, clk = clk_register(NULL, &clock->hw); if (IS_ERR(clk)) - kfree(clock); + goto free_clock; + + cpg_simple_notifier_register(notifiers, &clock->csn); + return clk; +free_clock: + kfree(clock); return clk; } @@ -332,7 +368,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, break; case CLK_TYPE_GEN3_SD: - return cpg_sd_clk_register(core, base, __clk_get_name(parent)); + return cpg_sd_clk_register(core, base, __clk_get_name(parent), + notifiers); case CLK_TYPE_GEN3_R: if (cpg_quirks & RCKCR_CKSEL) { -- GitLab From 3f7a4d084159c52513d1ff77f3b3b880bcf517d9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 28 Jun 2017 21:15:49 +0200 Subject: [PATCH 1245/2898] clk: renesas: rcar-gen3: Restore R clock during resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On R-Car Gen3 systems, PSCI system suspend powers down the SoC, losing clock configuration. Register a notifier to save/restore the RCKCR register during system suspend/resume. Signed-off-by: Geert Uytterhoeven Tested-by: Niklas Söderlund --- drivers/clk/renesas/rcar-gen3-cpg.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 267b5629e3bd..0904886f5501 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -373,18 +373,27 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_R: if (cpg_quirks & RCKCR_CKSEL) { + struct cpg_simple_notifier *csn; + + csn = kzalloc(sizeof(*csn), GFP_KERNEL); + if (!csn) + return ERR_PTR(-ENOMEM); + + csn->reg = base + CPG_RCKCR; + /* * RINT is default. * Only if EXTALR is populated, we switch to it. */ - value = readl(base + CPG_RCKCR) & 0x3f; + value = readl(csn->reg) & 0x3f; if (clk_get_rate(clks[cpg_clk_extalr])) { parent = clks[cpg_clk_extalr]; value |= BIT(15); } - writel(value, base + CPG_RCKCR); + writel(value, csn->reg); + cpg_simple_notifier_register(notifiers, csn); break; } -- GitLab From 6bf520280f3621d458e2ef3bd3c48acb89a39af7 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 5 Sep 2017 12:20:39 -0400 Subject: [PATCH 1246/2898] drm/amd/display: Driver message to SMU to indicate display off Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 3 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 38 ++++++++++++------- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f41f15faf019..47f16a4b9f27 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -763,7 +763,7 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); - dc->hwss.ready_shared_resources(dc); + dc->hwss.ready_shared_resources(dc, context); for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index de154329b049..b3448a41718e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1889,6 +1889,7 @@ enum dc_status dce110_apply_ctx_to_hw( return status; } + /* pplib is notified if disp_num changed */ dc->hwss.set_bandwidth(dc, context, true); /* to save power */ @@ -2683,7 +2684,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, } } -static void ready_shared_resources(struct dc *dc) {} +static void ready_shared_resources(struct dc *dc, struct dc_state *context) {} static void optimize_shared_resources(struct dc *dc) {} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d3fee15aeb79..e60be00abcf2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -802,18 +802,14 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) IP_REQUEST_EN, 0); } -static void ready_shared_resources(struct dc *dc) -{ - if (dc->current_state->stream_count == 0 && - !dc->debug.disable_stutter) - undo_DEGVIDCN10_253_wa(dc); -} - static void apply_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; struct mem_input *mi = dc->res_pool->mis[0]; + if (dc->debug.disable_stutter) + return; + REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); @@ -824,13 +820,6 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) mi->funcs->set_hubp_blank_en(mi, false); } -static void optimize_shared_resources(struct dc *dc) -{ - if (dc->current_state->stream_count == 0 && - !dc->debug.disable_stutter) - apply_DEGVIDCN10_253_wa(dc); -} - static void bios_golden_init(struct dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; @@ -2445,6 +2434,27 @@ static void dcn10_pplib_apply_display_requirements( dc->prev_display_config = *pp_display_cfg; } +static void optimize_shared_resources(struct dc *dc) +{ + if (dc->current_state->stream_count == 0) { + apply_DEGVIDCN10_253_wa(dc); + /* S0i2 message */ + dcn10_pplib_apply_display_requirements(dc, dc->current_state); + } +} + +static void ready_shared_resources(struct dc *dc, struct dc_state *context) +{ + if (dc->current_state->stream_count == 0 && + !dc->debug.disable_stutter) + undo_DEGVIDCN10_253_wa(dc); + + /* S0i2 message */ + if (dc->current_state->stream_count == 0 && + context->stream_count != 0) + dcn10_pplib_apply_display_requirements(dc, context); +} + static void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index aae7629b1c08..1fa2edc6cfb1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -174,7 +174,7 @@ struct hw_sequencer_funcs { struct resource_pool *res_pool, struct pipe_ctx *pipe_ctx); - void (*ready_shared_resources)(struct dc *dc); + void (*ready_shared_resources)(struct dc *dc, struct dc_state *context); void (*optimize_shared_resources)(struct dc *dc); }; -- GitLab From 5088cc98f59b922a609078c048a25e30f94b9216 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 6 Sep 2017 18:56:46 -0400 Subject: [PATCH 1247/2898] drm/amd/display: Force always scale chroma, set always_scaled to false This allows us to not always have scaling on, which causes issues with validation and causes the text to blur slightly. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 9 +++++---- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 9d9604f05095..f9e43e68fc0c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -159,10 +159,11 @@ bool dpp_get_optimal_number_of_taps( scl_data->taps.h_taps = 1; if (IDENTITY_RATIO(scl_data->ratios.vert)) scl_data->taps.v_taps = 1; - if (IDENTITY_RATIO(scl_data->ratios.horz_c)) - scl_data->taps.h_taps_c = 1; - if (IDENTITY_RATIO(scl_data->ratios.vert_c)) - scl_data->taps.v_taps_c = 1; + /* + * Spreadsheet doesn't handle taps_c is one properly, + * need to force Chroma to always be scaled to pass + * bandwidth validation. + */ } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index dc878f77837b..4f124dc303dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -420,10 +420,6 @@ static const struct dc_debug debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .clock_trace = true, - /* spread sheet doesn't handle taps_c is one properly, - * need to enable scaler for video surface to pass - * bandwidth validation.*/ - .always_scale = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- GitLab From 1049e39fa62f443aae64a2fb6057b96abf20e8de Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 7 Sep 2017 14:53:23 -0400 Subject: [PATCH 1248/2898] drm/amd/display: fix usb-c dongle regression A previous change moved link_disconnect_sink after dpcd read, this causes the sink count to be overwritten which in turn causes another detection to be triggered in the short pulse handler, which brings down the display. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ee23b609d7dd..d5eaebeaeb89 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -652,8 +652,6 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (link->local_sink) { sink = link->local_sink; } else { - link_disconnect_sink(link); - sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; -- GitLab From e008b0bcc63793d3e42fd88f412a90f329a05865 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 7 Sep 2017 17:02:47 -0400 Subject: [PATCH 1249/2898] drm/amd/display: Add FBC on/off to front-end programming - Fixing text mode for cases when VT-switch doesn't result in timing change Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b3448a41718e..590b2ad37105 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2554,6 +2554,15 @@ static void dce110_program_front_end_for_pipe( program_scaler(dc, pipe_ctx); +#ifdef ENABLE_FBC + if (dc->fbc_compressor && old_pipe->stream) { + if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + else + enable_fbc(dc, dc->current_state); + } +#endif + mi->funcs->mem_input_program_surface_config( mi, plane_state->format, -- GitLab From 7d58e72149fa73504fa13e7044d68e79a39996fb Mon Sep 17 00:00:00 2001 From: Martin Tsai Date: Fri, 8 Sep 2017 19:25:35 +0800 Subject: [PATCH 1250/2898] drm/amd/display: To prevent detecting new sink from spurious HPD Signed-off-by: Martin Tsai Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 33 +++++++++++-------- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index d5eaebeaeb89..c7751a31081a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -649,27 +649,34 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) sink_init_data.link = link; sink_init_data.sink_signal = sink_caps.signal; - if (link->local_sink) { - sink = link->local_sink; - } else { - sink_init_data.link = link; - sink_init_data.sink_signal = sink_caps.signal; + sink = dc_sink_create(&sink_init_data); + if (!sink) { + DC_ERROR("Failed to create sink!\n"); + return false; + } - sink = dc_sink_create(&sink_init_data); - if (!sink) { - DC_ERROR("Failed to create sink!\n"); - return false; + if (link->local_sink) { + edid_status = dm_helpers_read_local_edid( + link->ctx, + link, + sink); + + if (edid_status == EDID_OK) { + // Edid is not the same, to update the local sink with new sink. + sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->converter_disable_audio = converter_disable_audio; + link->local_sink = sink; } + } else { sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; sink->converter_disable_audio = converter_disable_audio; - link->local_sink = sink; - } - edid_status = dm_helpers_read_local_edid( + edid_status = dm_helpers_read_local_edid( link->ctx, link, sink); + } switch (edid_status) { case EDID_BAD_CHECKSUM: @@ -762,7 +769,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) link->ctx, link, sink); - if (edid_status != EDID_OK) { + if (edid_status != EDID_OK && edid_status != EDID_THE_SAME) { link_disconnect_sink(link); link->type = dc_connection_none; sink_caps.signal = SIGNAL_TYPE_NONE; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 6b891fde400c..4bd74fc6c782 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -151,6 +151,7 @@ enum dc_edid_status { EDID_BAD_INPUT, EDID_NO_RESPONSE, EDID_BAD_CHECKSUM, + EDID_THE_SAME, }; /* audio capability from EDID*/ -- GitLab From 8580d60baed5c8c9f08a5c3b239e563c8966a9dc Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 17 Aug 2017 14:58:07 -0400 Subject: [PATCH 1251/2898] drm/amd/display: Don't report fake sink as connected This was missed in the previous fake sink change. The fake sink allows us to enable a pipe with a disconnected display. We shouldn't report it as connected. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8cc228ebdc9a..75212f74f027 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2453,7 +2453,8 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) * 2. This interface *is called* in context of user-mode ioctl. Which * makes it a bad place for *any* MST-related activit. */ - if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) + if (aconnector->base.force == DRM_FORCE_UNSPECIFIED && + !aconnector->fake_enable) connected = (aconnector->dc_sink != NULL); else connected = (aconnector->base.force == DRM_FORCE_ON); -- GitLab From 024f0607cfed19a9f6082e4b94267544de4fc584 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Mon, 11 Sep 2017 14:30:02 -0400 Subject: [PATCH 1252/2898] drm/amd/display: Refactor dcn10_dpp_cm_helper to dcn10_cm_common Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../dc/dcn10/{dcn10_dpp_cm_helper.c => dcn10_cm_common.c} | 2 +- .../dc/dcn10/{dcn10_dpp_cm_helper.h => dcn10_cm_common.h} | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename drivers/gpu/drm/amd/display/dc/dcn10/{dcn10_dpp_cm_helper.c => dcn10_cm_common.c} (99%) rename drivers/gpu/drm/amd/display/dc/dcn10/{dcn10_dpp_cm_helper.h => dcn10_cm_common.h} (97%) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 2d6d3a371858..6b19106f4679 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -4,7 +4,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_mem_input.o dcn10_mpc.o \ - dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o + dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c rename to drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index f616e08759de..7f579cb19f4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -26,7 +26,7 @@ #include "reg_helper.h" #include "dcn10_dpp.h" -#include "dcn10_dpp_cm_helper.h" +#include "dcn10_cm_common.h" #define REG(reg) reg diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h similarity index 97% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h rename to drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h index 1155ee522898..64836dcf21f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm_helper.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.h @@ -23,8 +23,8 @@ * */ -#ifndef __DAL_DPP_DCN10_CM_HELPER_H__ -#define __DAL_DPP_DCN10_CM_HELPER_H__ +#ifndef __DAL_DCN10_CM_COMMON_H__ +#define __DAL_DCN10_CM_COMMON_H__ #define TF_HELPER_REG_FIELD_LIST(type) \ type exp_region0_lut_offset; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index d0e72acfc1d5..61e2a8919e9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -29,8 +29,8 @@ #include "reg_helper.h" #include "dcn10_dpp.h" -#include "dcn10_dpp_cm_helper.h" #include "basics/conversion.h" +#include "dcn10_cm_common.h" #define NUM_PHASES 64 #define HORZ_MAX_TAPS 8 -- GitLab From 98b49c2f9c66cf42b6d762498e2d9f327e439416 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Mon, 11 Sep 2017 16:28:21 -0400 Subject: [PATCH 1253/2898] drm/amd/display: fix multi-display on CZ - fixed wrong index in dce110_validate_surface_sets() - formatted for better readability Signed-off-by: Roman Li Reviewed-by: Harry Wentland igned-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_resource.c | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 28e768de744c..8e4ec61d59a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -849,7 +849,7 @@ static bool dce110_validate_bandwidth( static bool dce110_validate_surface_sets( struct dc_state *context) { - int i; + int i, j; for (i = 0; i < context->stream_count; i++) { if (context->stream_status[i].plane_count == 0) @@ -858,14 +858,27 @@ static bool dce110_validate_surface_sets( if (context->stream_status[i].plane_count > 2) return false; - if ((context->stream_status[i].plane_states[i]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) && - (context->stream_status[i].plane_states[i]->src_rect.width > 1920 || - context->stream_status[i].plane_states[i]->src_rect.height > 1080)) - return false; + for (j = 0; j < context->stream_status[i].plane_count; j++) { + struct dc_plane_state *plane = + context->stream_status[i].plane_states[j]; - /* irrespective of plane format, stream should be RGB encoded */ - if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) - return false; + /* underlay validation */ + if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + + if ((plane->src_rect.width > 1920 || + plane->src_rect.height > 1080)) + return false; + + /* irrespective of plane format, + * stream should be RGB encoded + */ + if (context->streams[i]->timing.pixel_encoding + != PIXEL_ENCODING_RGB) + return false; + + } + + } } return true; -- GitLab From 7f4a7253b112c9ed21022e25c7a740d824c56619 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Mon, 11 Sep 2017 16:56:51 -0400 Subject: [PATCH 1254/2898] drm/amd/display: update mpc add/remove functions Signed-off-by: Eric Bernstein Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 17 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 173 ++++++++++++------ drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 10 +- 3 files changed, 130 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e60be00abcf2..82a985a981be 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -881,7 +881,8 @@ static void dcn10_init_hw(struct dc *dc) xfm->funcs->transform_reset(xfm); dc->res_pool->mpc->funcs->remove( - dc->res_pool->mpc, dc->res_pool->opps[i], i); + dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree), + dc->res_pool->opps[i]->inst, i); /* Blank controller using driver code instead of * command table. @@ -1079,7 +1080,8 @@ static void plane_atomic_disconnect(struct dc *dc, if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx); + mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree), + dc->res_pool->opps[opp_id]->inst, fe_idx); } /* disable HW used by plane. @@ -2299,8 +2301,9 @@ static void update_dchubp_dpp( plane_state->format, EXPANSION_MODE_ZERO); - mpcc_cfg.mi = mi; - mpcc_cfg.opp = pipe_ctx->stream_res.opp; + mpcc_cfg.dpp_id = mi->inst; + mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst; + mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree); for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) mpcc_cfg.z_index++; if (dc->debug.surface_visual_confirm) @@ -2317,7 +2320,8 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->output_color_space) && per_pixel_alpha; - dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + mi->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + mi->opp_id = mpcc_cfg.opp_id; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; @@ -2528,7 +2532,8 @@ static void dcn10_apply_ctx_for_surface( /* reset mpc */ dc->res_pool->mpc->funcs->remove( dc->res_pool->mpc, - old_pipe_ctx->stream_res.opp, + &(old_pipe_ctx->stream_res.opp->mpc_tree), + old_pipe_ctx->stream_res.opp->inst, old_pipe_ctx->pipe_idx); old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 082b39a65e6a..8e767c84359c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -118,17 +118,19 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i static void mpc10_mpcc_remove( struct mpc *mpc, - struct output_pixel_processor *opp, + struct mpc_tree_cfg *tree_cfg, + int opp_id, int dpp_id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); int mpcc_id, z_idx; - for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) - if (opp->mpc_tree.dpp[z_idx] == dpp_id) + /* find z_idx for the dpp to be removed */ + for (z_idx = 0; z_idx < tree_cfg->num_pipes; z_idx++) + if (tree_cfg->dpp[z_idx] == dpp_id) break; - if (z_idx == opp->mpc_tree.num_pipes) { + if (z_idx == tree_cfg->num_pipes) { /* In case of resume from S3/S4, remove mpcc from bios left over */ REG_SET(MPCC_OPP_ID[dpp_id], 0, MPCC_OPP_ID, 0xf); @@ -139,7 +141,7 @@ static void mpc10_mpcc_remove( return; } - mpcc_id = opp->mpc_tree.mpcc[z_idx]; + mpcc_id = tree_cfg->mpcc[z_idx]; REG_SET(MPCC_OPP_ID[mpcc_id], 0, MPCC_OPP_ID, 0xf); @@ -149,82 +151,101 @@ static void mpc10_mpcc_remove( MPCC_BOT_SEL, 0xf); if (z_idx > 0) { - int top_mpcc_id = opp->mpc_tree.mpcc[z_idx - 1]; + int top_mpcc_id = tree_cfg->mpcc[z_idx - 1]; - if (z_idx + 1 < opp->mpc_tree.num_pipes) + if (z_idx + 1 < tree_cfg->num_pipes) + /* mpcc to be removed is in the middle of the tree */ REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, - MPCC_BOT_SEL, opp->mpc_tree.mpcc[z_idx + 1]); + MPCC_BOT_SEL, tree_cfg->mpcc[z_idx + 1]); else { + /* mpcc to be removed is at the bottom of the tree */ REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, MPCC_BOT_SEL, 0xf); REG_UPDATE(MPCC_CONTROL[top_mpcc_id], MPCC_MODE, MODE_TOP_ONLY); } - } else if (opp->mpc_tree.num_pipes > 1) - REG_SET(MUX[opp->inst], 0, - MPC_OUT_MUX, opp->mpc_tree.mpcc[z_idx + 1]); + } else if (tree_cfg->num_pipes > 1) + /* mpcc to be removed is at the top of the tree */ + REG_SET(MUX[opp_id], 0, + MPC_OUT_MUX, tree_cfg->mpcc[z_idx + 1]); else - REG_SET(MUX[opp->inst], 0, MPC_OUT_MUX, 0xf); + /* mpcc to be removed is the only one in the tree */ + REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, 0xf); + /* mark this mpcc as not in use */ mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id); - opp->mpc_tree.num_pipes--; - for (; z_idx < opp->mpc_tree.num_pipes; z_idx++) { - opp->mpc_tree.dpp[z_idx] = opp->mpc_tree.dpp[z_idx + 1]; - opp->mpc_tree.mpcc[z_idx] = opp->mpc_tree.mpcc[z_idx + 1]; + tree_cfg->num_pipes--; + for (; z_idx < tree_cfg->num_pipes; z_idx++) { + tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx + 1]; + tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx + 1]; } - opp->mpc_tree.dpp[opp->mpc_tree.num_pipes] = 0xdeadbeef; - opp->mpc_tree.mpcc[opp->mpc_tree.num_pipes] = 0xdeadbeef; + tree_cfg->dpp[tree_cfg->num_pipes] = 0xdeadbeef; + tree_cfg->mpcc[tree_cfg->num_pipes] = 0xdeadbeef; } -static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +static void mpc10_add_to_tree_cfg( + struct mpc *mpc, + struct mpcc_cfg *cfg, + int mpcc_id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_mode = MODE_TOP_ONLY; + int position = cfg->z_index; + struct mpc_tree_cfg *tree_cfg = cfg->tree_cfg; int alpha_blnd_mode = cfg->per_pixel_alpha ? BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; - int mpcc_mode = MODE_TOP_ONLY; - int mpcc_id, z_idx; + int z_idx; - ASSERT(cfg->z_index < mpc10->num_mpcc); + REG_SET(MPCC_OPP_ID[mpcc_id], 0, + MPCC_OPP_ID, cfg->opp_id); - for (z_idx = 0; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++) - if (cfg->opp->mpc_tree.dpp[z_idx] == cfg->mi->inst) - break; - if (z_idx == cfg->opp->mpc_tree.num_pipes) { - ASSERT(cfg->z_index <= cfg->opp->mpc_tree.num_pipes); - mpcc_id = mpc10_get_idle_mpcc_id(mpc10); - /*todo: remove hack*/ - mpcc_id = cfg->mi->inst; - ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); + REG_SET(MPCC_TOP_SEL[mpcc_id], 0, + MPCC_TOP_SEL, cfg->dpp_id); - if (mpc->ctx->dc->debug.sanity_checks) - mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); - } else { - ASSERT(cfg->z_index < cfg->opp->mpc_tree.num_pipes); - mpcc_id = cfg->opp->mpc_tree.mpcc[z_idx]; - mpc10_mpcc_remove(mpc, cfg->opp, cfg->mi->inst); - } + if (position == 0) { + /* idle dpp/mpcc is added to the top layer of tree */ - REG_SET(MPCC_OPP_ID[mpcc_id], 0, - MPCC_OPP_ID, cfg->opp->inst); + if (tree_cfg->num_pipes > 0) { + /* get instance of previous top mpcc */ + int prev_top_mpcc_id = tree_cfg->mpcc[0]; - REG_SET(MPCC_TOP_SEL[mpcc_id], 0, - MPCC_TOP_SEL, cfg->mi->inst); + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, prev_top_mpcc_id); + mpcc_mode = MODE_BLEND; + } + + /* opp will get new output. from new added mpcc */ + REG_SET(MUX[cfg->opp_id], 0, MPC_OUT_MUX, mpcc_id); + + } else if (position == tree_cfg->num_pipes) { + /* idle dpp/mpcc is added to the bottom layer of tree */ - if (cfg->z_index > 0) { - int top_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index - 1]; + /* get instance of previous bottom mpcc, set to middle layer */ + int prev_bot_mpcc_id = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; - REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0, + REG_SET(MPCC_BOT_SEL[prev_bot_mpcc_id], 0, MPCC_BOT_SEL, mpcc_id); - REG_UPDATE(MPCC_CONTROL[top_mpcc_id], + REG_UPDATE(MPCC_CONTROL[prev_bot_mpcc_id], MPCC_MODE, MODE_BLEND); - } else - REG_SET(MUX[cfg->opp->inst], 0, MPC_OUT_MUX, mpcc_id); - if (cfg->z_index < cfg->opp->mpc_tree.num_pipes) { - int bot_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index]; + /* mpcc_id become new bottom mpcc*/ + REG_SET(MPCC_BOT_SEL[mpcc_id], 0, + MPCC_BOT_SEL, 0xf); + + } else { + /* idle dpp/mpcc is added to middle of tree */ + int above_mpcc_id = tree_cfg->mpcc[position - 1]; + int below_mpcc_id = tree_cfg->mpcc[position]; + + /* mpcc above new mpcc_id has new bottom mux*/ + REG_SET(MPCC_BOT_SEL[above_mpcc_id], 0, + MPCC_BOT_SEL, mpcc_id); + REG_UPDATE(MPCC_CONTROL[above_mpcc_id], + MPCC_MODE, MODE_BLEND); + /* mpcc_id bottom mux is from below mpcc*/ REG_SET(MPCC_BOT_SEL[mpcc_id], 0, - MPCC_BOT_SEL, bot_mpcc_id); + MPCC_BOT_SEL, below_mpcc_id); mpcc_mode = MODE_BLEND; } @@ -234,18 +255,50 @@ static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha, MPCC_BLND_ACTIVE_OVERLAP_ONLY, false); + /* update mpc_tree_cfg with new mpcc */ + for (z_idx = tree_cfg->num_pipes; z_idx > position; z_idx--) { + tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx - 1]; + tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx - 1]; + } + tree_cfg->dpp[position] = cfg->dpp_id; + tree_cfg->mpcc[position] = mpcc_id; + tree_cfg->num_pipes++; +} + +static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + + ASSERT(cfg->z_index < mpc10->num_mpcc); + + /* check in dpp already exists in mpc tree */ + for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) + if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) + break; + if (z_idx == cfg->tree_cfg->num_pipes) { + ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes); + mpcc_id = mpc10_get_idle_mpcc_id(mpc10); + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); + + if (mpc->ctx->dc->debug.sanity_checks) + mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id); + } else { + ASSERT(cfg->z_index < cfg->tree_cfg->num_pipes); + mpcc_id = cfg->tree_cfg->mpcc[z_idx]; + mpc10_mpcc_remove(mpc, cfg->tree_cfg, cfg->opp_id, cfg->dpp_id); + } + + /* add dpp/mpcc pair to mpc_tree_cfg and update mpcc registers */ + mpc10_add_to_tree_cfg(mpc, cfg, mpcc_id); + + /* set background color */ mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id); + /* mark this mpcc as in use */ mpc10->mpcc_in_use_mask |= 1 << mpcc_id; - for (z_idx = cfg->opp->mpc_tree.num_pipes; z_idx > cfg->z_index; z_idx--) { - cfg->opp->mpc_tree.dpp[z_idx] = cfg->opp->mpc_tree.dpp[z_idx - 1]; - cfg->opp->mpc_tree.mpcc[z_idx] = cfg->opp->mpc_tree.mpcc[z_idx - 1]; - } - cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst; - cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id; - cfg->opp->mpc_tree.num_pipes++; - cfg->mi->opp_id = cfg->opp->inst; - cfg->mi->mpcc_id = mpcc_id; + + return mpcc_id; } const struct mpc_funcs dcn10_mpc_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 4bbcff48acc8..2d3de5b68e34 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -29,8 +29,9 @@ #include "opp.h" struct mpcc_cfg { - struct mem_input *mi; - struct output_pixel_processor *opp; + int dpp_id; + int opp_id; + struct mpc_tree_cfg *tree_cfg; unsigned int z_index; struct tg_color black_color; @@ -44,9 +45,10 @@ struct mpc { }; struct mpc_funcs { - void (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); void (*remove)(struct mpc *mpc, - struct output_pixel_processor *opp, + struct mpc_tree_cfg *tree_cfg, + int opp_id, int mpcc_inst); void (*wait_for_idle)(struct mpc *mpc, int id); }; -- GitLab From 4f346e655d24140fb40b46f814506ba17ac34ea1 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Thu, 7 Sep 2017 17:05:38 -0400 Subject: [PATCH 1255/2898] drm/amd/display: Match actual state during S3 resume. During system suspend, we: 1. Cache a duplicate of the current DRM atomic state, which calls hooks to duplicate our internal states. 2. Call hooks to disable all functionalities. 3. System suspended. During resume, we attempt to restore the cached state. However, our interal states are now stale, since step 1 was done before step 2. i.e. our cached state does not reflect the disabled nature of things. This change resolves that by destroying all relevant states to reflect the actual state during resume. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 75212f74f027..ecca2862407f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -648,6 +648,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; + struct dm_crtc_state *dm_crtc_state; + struct drm_plane *plane; + struct drm_plane_state *plane_state; + struct dm_plane_state *dm_plane_state; + struct dm_atomic_state *cached_state; int ret = 0; int i; @@ -686,6 +691,37 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) new_crtc_state->active_changed = true; + cached_state = to_dm_atomic_state(adev->dm.cached_state); + + /* + * During suspend, the cached state is saved before all streams are + * disabled. Refresh cached state to match actual current state before + * restoring it. + */ + WARN_ON(kref_read(&cached_state->context->refcount) > 1); + dc_release_state(cached_state->context); + + cached_state->context = dc_create_state(); + dc_resource_state_copy_construct_current(adev->dm.dc, cached_state->context); + + for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { + dm_crtc_state = to_dm_crtc_state(new_crtc_state); + if (dm_crtc_state->stream) { + WARN_ON(kref_read(&dm_crtc_state->stream->refcount) > 1); + dc_stream_release(dm_crtc_state->stream); + dm_crtc_state->stream = NULL; + } + } + + for_each_new_plane_in_state(adev->dm.cached_state, plane, plane_state, i) { + dm_plane_state = to_dm_plane_state(plane_state); + if (dm_plane_state->dc_state) { + WARN_ON(kref_read(&dm_plane_state->dc_state->refcount) > 1); + dc_plane_state_release(dm_plane_state->dc_state); + dm_plane_state->dc_state = NULL; + } + } + ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); drm_atomic_state_put(adev->dm.cached_state); -- GitLab From eade83503a5381ab0292f9653786bec6a638c523 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 12 Sep 2017 12:08:14 -0400 Subject: [PATCH 1256/2898] drm/amd/display: fixing register includes Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 89 +++++++++---------- .../amd/display/dc/dcn10/dcn10_mem_input.h | 2 + 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 2d3a41f744af..589332019a83 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -131,8 +131,6 @@ HWSEQ_PHYPLL_REG_LIST(CRTC) #define HWSEQ_DCN_REG_LIST()\ - HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ - HWSEQ_PHYPLL_REG_LIST(OTG), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 1), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 2), \ @@ -182,22 +180,6 @@ SR(DCHUBBUB_TEST_DEBUG_INDEX), \ SR(DCHUBBUB_TEST_DEBUG_DATA), \ SR(DC_IP_REQUEST_CNTL), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN4_PG_CONFIG), \ - SR(DOMAIN5_PG_CONFIG), \ - SR(DOMAIN6_PG_CONFIG), \ - SR(DOMAIN7_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN4_PG_STATUS), \ - SR(DOMAIN5_PG_STATUS), \ - SR(DOMAIN6_PG_STATUS), \ - SR(DOMAIN7_PG_STATUS), \ SR(DIO_MEM_PWR_CTRL), \ SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL2), \ @@ -223,13 +205,30 @@ #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ + HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ + HWSEQ_PHYPLL_REG_LIST(OTG), \ SR(DCHUBBUB_SDPIF_FB_TOP),\ SR(DCHUBBUB_SDPIF_FB_BASE),\ SR(DCHUBBUB_SDPIF_FB_OFFSET),\ SR(DCHUBBUB_SDPIF_AGP_BASE),\ SR(DCHUBBUB_SDPIF_AGP_BOT),\ - SR(DCHUBBUB_SDPIF_AGP_TOP) - + SR(DCHUBBUB_SDPIF_AGP_TOP),\ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN4_PG_CONFIG), \ + SR(DOMAIN5_PG_CONFIG), \ + SR(DOMAIN6_PG_CONFIG), \ + SR(DOMAIN7_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN4_PG_STATUS), \ + SR(DOMAIN5_PG_STATUS), \ + SR(DOMAIN6_PG_STATUS), \ + SR(DOMAIN7_PG_STATUS) struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; @@ -417,30 +416,6 @@ struct dce_hwseq_registers { HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ @@ -468,7 +443,31 @@ struct dce_hwseq_registers { HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ - HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) + HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh),\ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index aefd3e7bd7eb..0b7d4faff82f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -120,6 +120,8 @@ SR(DCHUBBUB_SDPIF_FB_BASE),\ SR(DCHUBBUB_SDPIF_FB_OFFSET) + + struct dcn_mi_registers { uint32_t DCHUBP_CNTL; uint32_t HUBPREQ_DEBUG_DB; -- GitLab From f4ac176e62fdc74e52ee58461fb7c8912322fc1c Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Fri, 8 Sep 2017 11:52:45 -0400 Subject: [PATCH 1257/2898] drm/amd/display: Exclude MST from fake sink Needs effort to take care of the fake sink scenario in downstream daisy chain device. Exclude MST from fake sink feature for now. Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ecca2862407f..dfea04fed695 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2354,8 +2354,16 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, drm_connector = &aconnector->base; - if (!aconnector->dc_sink) + if (!aconnector->dc_sink) { + /* + * Exclude MST from creating fake_sink + * TODO: need to enable MST into fake_sink feature + */ + if (aconnector->mst_port) + goto stream_create_fail; + create_fake_sink(aconnector); + } stream = dc_create_stream_for_sink(aconnector->dc_sink); @@ -4376,7 +4384,8 @@ static int dm_update_crtcs_state(struct dc *dc, aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc); /* TODO This hack should go away */ - if (aconnector) { + if (aconnector && enable) { + // Make sure fake sink is created in plug-in scenario new_con_state = drm_atomic_get_connector_state(state, &aconnector->base); -- GitLab From fc17235fe65b0179969e0793a086cba93afcc078 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Fri, 8 Sep 2017 16:40:34 -0400 Subject: [PATCH 1258/2898] drm/amd/display: Fix NULL pointer on MST chained mode Prevent NULL pointer on new_stream being added to ctx when added MST connectors cannot be found in existing crtc_state in the chained mode Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index dfea04fed695..f2724713ddd0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4462,6 +4462,13 @@ static int dm_update_crtcs_state(struct dc *dc, *lock_and_validation_needed = true; } else {/* Add stream for any updated/enabled CRTC */ + /* + * Quick fix to prevent NULL pointer on new_stream when + * added MST connectors not found in existing crtc_state in the chained mode + * TODO: need to dig out the root cause of that + */ + if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port)) + continue; if (modereset_required(new_crtc_state)) goto next_crtc; -- GitLab From bc6828e0e6b6c5bcafbb093f9fe475f63dbe47e5 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 12 Sep 2017 13:56:57 -0400 Subject: [PATCH 1259/2898] drm/amd/display: Refactor dc_update_planes_and_stream. Split update_planes_and_stream_state (split Software and Hardware programming) as the state is already build, so we only need to program the hardware Signed-off-by: Andrey Grodzovsky Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 21 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 256 ++++-------------- drivers/gpu/drm/amd/display/dc/dc.h | 36 +-- 3 files changed, 87 insertions(+), 226 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f2724713ddd0..6c04ad1b5859 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3771,7 +3771,8 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc) */ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - uint32_t target) + uint32_t target, + struct dc_state *state) { unsigned long flags; uint32_t target_vblank; @@ -3842,7 +3843,13 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, surface_updates->flip_addr = &addr; - dc_update_planes_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); + dc_commit_updates_for_stream(adev->dm.dc, + surface_updates, + 1, + acrtc_state->stream, + NULL, + &surface_updates->surface, + state); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, @@ -3868,6 +3875,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, struct drm_crtc_state *new_pcrtc_state = drm_atomic_get_new_crtc_state(state, pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); int planes_count = 0; unsigned long flags; @@ -3925,7 +3933,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, amdgpu_dm_do_flip( crtc, fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank); + drm_crtc_vblank_count(crtc) + *wait_for_vblank, + dm_state->context); } } @@ -3945,7 +3954,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (false == dc_commit_planes_to_stream(dm->dc, plane_states_constructed, planes_count, - dc_stream_attach)) + dc_stream_attach, + dm_state->context)) dm_error("%s: Failed to attach plane!\n", __func__); } else { /*TODO BUG Here should go disable planes on CRTC. */ @@ -4165,7 +4175,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm->dc, status->plane_states, status->plane_count, - dm_new_crtc_state->stream)) + dm_new_crtc_state->stream, + dm_state->context)) dm_error("%s: Failed to update stream scaling!\n", __func__); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 47f16a4b9f27..1ec6df9870da 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -869,7 +869,8 @@ bool dc_commit_planes_to_stream( struct dc *dc, struct dc_plane_state **plane_states, uint8_t new_plane_count, - struct dc_stream_state *dc_stream) + struct dc_stream_state *dc_stream, + struct dc_state *state) { struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs flip_addr[MAX_SURFACES]; @@ -920,11 +921,11 @@ bool dc_commit_planes_to_stream( updates[i].scaling_info = &scaling_info[i]; } - dc_update_planes_and_stream( + dc_commit_updates_for_stream( dc, updates, new_plane_count, - dc_stream, stream_update); + dc_stream, stream_update, plane_states, state); dc_post_update_surfaces_to_stream(dc); @@ -1150,192 +1151,20 @@ static struct dc_stream_status *stream_get_status( static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; -void dc_update_planes_and_stream(struct dc *dc, - struct dc_surface_update *srf_updates, int surface_count, + +static void commit_planes_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, struct dc_stream_state *stream, - struct dc_stream_update *stream_update) + struct dc_stream_update *stream_update, + enum surface_update_type update_type, + struct dc_state *context) { - struct dc_state *context; int i, j; - enum surface_update_type update_type; - const struct dc_stream_status *stream_status; - struct dc_context *dc_ctx = dc->ctx; - - stream_status = dc_stream_get_status(stream); - - ASSERT(stream_status); - if (!stream_status) - return; /* Cannot commit surface to stream that is not committed */ - -#ifdef ENABLE_FBC - if (srf_updates->flip_addr) { - if (srf_updates->flip_addr->address.grph.addr.low_part == 0) - ASSERT(0); - } -#endif - context = dc->current_state; - - /* update current stream with the new updates */ - if (stream_update) { - if ((stream_update->src.height != 0) && - (stream_update->src.width != 0)) - stream->src = stream_update->src; - - if ((stream_update->dst.height != 0) && - (stream_update->dst.width != 0)) - stream->dst = stream_update->dst; - - if (stream_update->out_transfer_func && - stream_update->out_transfer_func != - stream->out_transfer_func) { - if (stream->out_transfer_func != NULL) - dc_transfer_func_release(stream->out_transfer_func); - dc_transfer_func_retain(stream_update->out_transfer_func); - stream->out_transfer_func = - stream_update->out_transfer_func; - } - } - - /* do not perform surface update if surface has invalid dimensions - * (all zero) and no scaling_info is provided - */ - if (surface_count > 0 && - srf_updates->surface->src_rect.width == 0 && - srf_updates->surface->src_rect.height == 0 && - srf_updates->surface->dst_rect.width == 0 && - srf_updates->surface->dst_rect.height == 0 && - !srf_updates->scaling_info) { - ASSERT(false); - return; - } - - update_type = dc_check_update_surfaces_for_stream( - dc, srf_updates, surface_count, stream_update, stream_status); - - if (update_type >= update_surface_trace_level) - update_surface_trace(dc, srf_updates, surface_count); - - if (update_type >= UPDATE_TYPE_FULL) { - struct dc_plane_state *new_planes[MAX_SURFACES] = {0}; - - for (i = 0; i < surface_count; i++) - new_planes[i] = srf_updates[i].surface; - - /* initialize scratch memory for building context */ - context = dc_create_state(); - if (context == NULL) { - DC_ERROR("Failed to allocate new validate context!\n"); - return; - } - - dc_resource_state_copy_construct( - dc->current_state, context); - - /*remove old surfaces from context */ - if (!dc_rem_all_planes_for_stream(dc, stream, context)) { - - BREAK_TO_DEBUGGER(); - goto fail; - } - - /* add surface to context */ - if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { - - BREAK_TO_DEBUGGER(); - goto fail; - } - } - - /* save update parameters into surface */ - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = srf_updates[i].surface; - - if (srf_updates[i].flip_addr) { - surface->address = srf_updates[i].flip_addr->address; - surface->flip_immediate = - srf_updates[i].flip_addr->flip_immediate; - } - - if (srf_updates[i].scaling_info) { - surface->scaling_quality = - srf_updates[i].scaling_info->scaling_quality; - surface->dst_rect = - srf_updates[i].scaling_info->dst_rect; - surface->src_rect = - srf_updates[i].scaling_info->src_rect; - surface->clip_rect = - srf_updates[i].scaling_info->clip_rect; - } - - if (srf_updates[i].plane_info) { - surface->color_space = - srf_updates[i].plane_info->color_space; - surface->format = - srf_updates[i].plane_info->format; - surface->plane_size = - srf_updates[i].plane_info->plane_size; - surface->rotation = - srf_updates[i].plane_info->rotation; - surface->horizontal_mirror = - srf_updates[i].plane_info->horizontal_mirror; - surface->stereo_format = - srf_updates[i].plane_info->stereo_format; - surface->tiling_info = - srf_updates[i].plane_info->tiling_info; - surface->visible = - srf_updates[i].plane_info->visible; - surface->per_pixel_alpha = - srf_updates[i].plane_info->per_pixel_alpha; - surface->dcc = - srf_updates[i].plane_info->dcc; - } - - if (update_type >= UPDATE_TYPE_MED) { - for (j = 0; j < dc->res_pool->pipe_count; j++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - - if (pipe_ctx->plane_state != surface) - continue; - - resource_build_scaling_params(pipe_ctx); - } - } - - if (srf_updates[i].gamma && - srf_updates[i].gamma != surface->gamma_correction) { - if (surface->gamma_correction != NULL) - dc_gamma_release(&surface->gamma_correction); - - dc_gamma_retain(srf_updates[i].gamma); - surface->gamma_correction = srf_updates[i].gamma; - } - - if (srf_updates[i].in_transfer_func && - srf_updates[i].in_transfer_func != surface->in_transfer_func) { - if (surface->in_transfer_func != NULL) - dc_transfer_func_release( - surface-> - in_transfer_func); - - dc_transfer_func_retain( - srf_updates[i].in_transfer_func); - surface->in_transfer_func = - srf_updates[i].in_transfer_func; - } - - if (srf_updates[i].hdr_static_metadata) - surface->hdr_static_ctx = - *(srf_updates[i].hdr_static_metadata); - } if (update_type == UPDATE_TYPE_FULL) { - if (!dc->res_pool->funcs->validate_bandwidth(dc, context)) { - BREAK_TO_DEBUGGER(); - goto fail; - } else { - dc->hwss.set_bandwidth(dc, context, false); - context_clock_trace(dc, context); - } + dc->hwss.set_bandwidth(dc, context, false); + context_clock_trace(dc, context); } if (update_type > UPDATE_TYPE_FAST) { @@ -1459,27 +1288,60 @@ void dc_update_planes_and_stream(struct dc *dc, break; } } +} + +void dc_commit_updates_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_plane_state **plane_states, + struct dc_state *state) +{ + const struct dc_stream_status *stream_status; + enum surface_update_type update_type; + struct dc_state *context; + int i; - if (dc->current_state != context) { + stream_status = dc_stream_get_status(stream); + context = dc->current_state; + + update_type = dc_check_update_surfaces_for_stream( + dc, srf_updates, surface_count, stream_update, stream_status); + + if (update_type >= update_surface_trace_level) + update_surface_trace(dc, srf_updates, surface_count); - /* Since memory free requires elevated IRQL, an interrupt - * request is generated by mem free. If this happens - * between freeing and reassigning the context, our vsync - * interrupt will call into dc and cause a memory - * corruption BSOD. Hence, we first reassign the context, - * then free the old context. - */ - struct dc_state *old = dc->current_state; + if (update_type >= UPDATE_TYPE_FULL) + dc_resource_state_copy_construct(state, context); - dc->current_state = context; - dc_release_state(old); + + for (i = 0; i < surface_count; i++) { + struct dc_plane_state *surface = srf_updates[i].surface; + + /* TODO: On flip we don't build the state, so it still has the + * old address. Which is why we are updating the address here + */ + if (srf_updates[i].flip_addr) + surface->address = srf_updates[i].flip_addr->address; } + + + commit_planes_for_stream( + dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + context); + + dc_post_update_surfaces_to_stream(dc); + return; -fail: - dc_release_state(context); } uint8_t dc_get_current_stream_count(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4ff543826476..50440731f83c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -449,23 +449,6 @@ struct dc_flip_addrs { /* TODO: add flip duration for FreeSync */ }; -/* - * Set up surface attributes and associate to a stream - * The surfaces parameter is an absolute set of all surface active for the stream. - * If no surfaces are provided, the stream will be blanked; no memory read. - * Any flip related attribute changes must be done through this interface. - * - * After this call: - * Surfaces attributes are programmed and configured to be composed into stream. - * This does not trigger a flip. No surface address is programmed. - */ - -bool dc_commit_planes_to_stream( - struct dc *dc, - struct dc_plane_state **plane_states, - uint8_t new_plane_count, - struct dc_stream_state *stream); - bool dc_post_update_surfaces_to_stream( struct dc *dc); @@ -571,9 +554,6 @@ bool dc_is_stream_unchanged( struct dc_stream_state *old_stream, struct dc_stream_state *stream); /* - * Setup stream attributes if no stream updates are provided - * there will be no impact on the stream parameters - * * Set up surface attributes and associate to a stream * The surfaces parameter is an absolute set of all surface active for the stream. * If no surfaces are provided, the stream will be blanked; no memory read. @@ -582,14 +562,22 @@ bool dc_is_stream_unchanged( * After this call: * Surfaces attributes are programmed and configured to be composed into stream. * This does not trigger a flip. No surface address is programmed. - * */ -void dc_update_planes_and_stream(struct dc *dc, - struct dc_surface_update *surface_updates, int surface_count, +bool dc_commit_planes_to_stream( + struct dc *dc, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, struct dc_stream_state *dc_stream, - struct dc_stream_update *stream_update); + struct dc_state *state); +void dc_commit_updates_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_plane_state **plane_states, + struct dc_state *state); /* * Log the current stream state. */ -- GitLab From 4b7e7e2b1bb2c7308ee3ccbef3f67cb9ce52e954 Mon Sep 17 00:00:00 2001 From: ShihChen Chen Date: Tue, 12 Sep 2017 11:10:12 +0800 Subject: [PATCH 1260/2898] drm/amd/display: make tile changing run at ISR Signed-off-by: ShihChen Chen Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1ec6df9870da..2cea8de9c9be 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1031,7 +1031,6 @@ static enum surface_update_type get_plane_info_update_type( temp_plane_info.plane_size = u->surface->plane_size; temp_plane_info.rotation = u->surface->rotation; temp_plane_info.stereo_format = u->surface->stereo_format; - temp_plane_info.tiling_info = u->surface->tiling_info; if (surface_index == 0) temp_plane_info.visible = u->plane_info->visible; @@ -1044,10 +1043,26 @@ static enum surface_update_type get_plane_info_update_type( if (pixel_format_to_bpp(u->plane_info->format) != pixel_format_to_bpp(u->surface->format)) { + /* different bytes per element will require full bandwidth + * and DML calculation + */ return UPDATE_TYPE_FULL; - } else { - return UPDATE_TYPE_MED; } + + if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info, + sizeof(union dc_tiling_info)) != 0) { + /* todo: below are HW dependent, we should add a hook to + * DCE/N resource and validated there. + */ + if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) { + /* swizzled mode requires RQ to be setup properly, + * thus need to run DML to calculate RQ settings + */ + return UPDATE_TYPE_FULL; + } + } + + return UPDATE_TYPE_MED; } static enum surface_update_type get_scaling_info_update_type( -- GitLab From 68d77dd8214e5186d535ec7af29722aaad621824 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 13 Sep 2017 11:36:34 -0400 Subject: [PATCH 1261/2898] drm/amd/display: power_down_Hw need signal type to turnoff backlight Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 590b2ad37105..d83a330712f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1171,6 +1171,7 @@ static void power_down_encoders(struct dc *dc) { int i; enum connector_id connector_id; + enum signal_type signal = SIGNAL_TYPE_NONE; for (i = 0; i < dc->link_count; i++) { connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || @@ -1178,10 +1179,12 @@ static void power_down_encoders(struct dc *dc) if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(dc->links[i], false); + if (connector_id == CONNECTOR_ID_EDP) + signal = SIGNAL_TYPE_EDP; } dc->links[i]->link_enc->funcs->disable_output( - dc->links[i]->link_enc, SIGNAL_TYPE_NONE); + dc->links[i]->link_enc, signal); } } -- GitLab From d53d7866a795410f7b6a16b1ef0b37825edc794e Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 14 Sep 2017 11:27:34 -0400 Subject: [PATCH 1262/2898] drm/amd/display: removing remaining register definitions work around Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 16 +++++++------- .../drm/amd/display/dc/dce/dce_link_encoder.h | 21 ++++++++++++------- .../display/dc/dcn10/dcn10_timing_generator.h | 11 +--------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 589332019a83..5798001da770 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -179,16 +179,11 @@ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ SR(DCHUBBUB_TEST_DEBUG_INDEX), \ SR(DCHUBBUB_TEST_DEBUG_DATA), \ - SR(DC_IP_REQUEST_CNTL), \ SR(DIO_MEM_PWR_CTRL), \ SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL2), \ SR(DCFCLK_CNTL),\ SR(DCFCLK_CNTL), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ /* todo: get these from GVM instead of reading registers ourselves */\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ @@ -228,7 +223,12 @@ SR(DOMAIN4_PG_STATUS), \ SR(DOMAIN5_PG_STATUS), \ SR(DOMAIN6_PG_STATUS), \ - SR(DOMAIN7_PG_STATUS) + SR(DOMAIN7_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL) struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; @@ -415,7 +415,6 @@ struct dce_hwseq_registers { HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ @@ -467,7 +466,8 @@ struct dce_hwseq_registers { HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh) + HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index be0a45bdc5e2..05463df7e636 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -44,8 +44,6 @@ SRI(DC_HPD_CONTROL, HPD, id) #define LE_COMMON_REG_LIST_BASE(id) \ - SR(LVTMA_PWRSEQ_CNTL), \ - SR(LVTMA_PWRSEQ_STATE), \ SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_DATA), \ @@ -71,6 +69,10 @@ SRI(DP_DPHY_FAST_TRAINING, DP, id), \ SRI(DP_SEC_CNTL1, DP, id) +#define LE_EDP_REG_LIST(id)\ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE) + #define LE_COMMON_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ @@ -79,33 +81,38 @@ #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_COMMON_REG_LIST_BASE(id) + LE_COMMON_REG_LIST_BASE(id), \ + LE_EDP_REG_LIST(id) #define LE_DCE100_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) + SR(DCI_MEM_PWR_STATUS), \ + LE_EDP_REG_LIST(id) #define LE_DCE110_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) + SR(DCI_MEM_PWR_STATUS), \ + LE_EDP_REG_LIST(id) #define LE_DCE120_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DCI_MEM_PWR_STATUS) + SR(DCI_MEM_PWR_STATUS), \ + LE_EDP_REG_LIST(id) #define LE_DCN10_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DMU_MEM_PWR_CNTL) + SR(DMU_MEM_PWR_CNTL), \ + LE_EDP_REG_LIST(id) struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 69da293e9b4a..0826d73b9809 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -71,11 +71,7 @@ SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ SRI(OPPBUF_CONTROL, OPPBUF, inst),\ SRI(OPPBUF_3D_PARAMETERS_0, OPPBUF, inst),\ - SRI(CONTROL, VTG, inst),\ - SR(D1VGA_CONTROL),\ - SR(D2VGA_CONTROL),\ - SR(D3VGA_CONTROL),\ - SR(D4VGA_CONTROL) + SRI(CONTROL, VTG, inst) #define TG_COMMON_REG_LIST_DCN1_0(inst) \ TG_COMMON_REG_LIST_DCN(inst),\ @@ -128,11 +124,6 @@ struct dcn_tg_registers { uint32_t OPPBUF_CONTROL; uint32_t OPPBUF_3D_PARAMETERS_0; uint32_t CONTROL; - /*todo: move VGA to HWSS */ - uint32_t D1VGA_CONTROL; - uint32_t D2VGA_CONTROL; - uint32_t D3VGA_CONTROL; - uint32_t D4VGA_CONTROL; }; #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ -- GitLab From 25bab0da8f61e7d8f717e4f9be34e97a1aaa0ccc Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 14 Sep 2017 18:50:32 -0400 Subject: [PATCH 1263/2898] drm/amd/display: set cp25201 to use TPS4 [Description] hbr2 compliance eye output is unstable (toggling on and off) with debugger break. This caueses intermittent PHY automation failure. Need to look into the root cause later Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index b735782b8fe0..ced42484dcfc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1700,6 +1700,12 @@ static void dp_test_send_link_training(struct dc_link *link) dp_retrain_link_dp_test(link, &link_settings, false); } +/* TODO hbr2 compliance eye output is unstable + * (toggling on and off) with debugger break + * This caueses intermittent PHY automation failure + * Need to look into the root cause */ +static uint8_t force_tps4_for_cp2520 = 1; + static void dp_test_send_phy_test_pattern(struct dc_link *link) { union phy_test_pattern dpcd_test_pattern; @@ -1758,10 +1764,16 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; break; case PHY_TEST_PATTERN_CP2520_1: - test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; + /* CP2520 pattern is unstable, temporarily use TPS4 instead */ + test_pattern = (force_tps4_for_cp2520 == 1) ? + DP_TEST_PATTERN_TRAINING_PATTERN4 : + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; break; case PHY_TEST_PATTERN_CP2520_2: - test_pattern = DP_TEST_PATTERN_CP2520_2; + /* CP2520 pattern is unstable, temporarily use TPS4 instead */ + test_pattern = (force_tps4_for_cp2520 == 1) ? + DP_TEST_PATTERN_TRAINING_PATTERN4 : + DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; break; case PHY_TEST_PATTERN_CP2520_3: test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; -- GitLab From 904aa42e77aa7fb5f95408b4d1ffb4b2c3a805d7 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 14 Sep 2017 19:03:04 -0400 Subject: [PATCH 1264/2898] drm/amd/display: add back removed hack for mpcc add A previous changed removed the hack to match mpcc_idd with mi instance. This causes pstate hang on resume from hibernate for yet unknown reason. Add the hack back for now to work around the issue. More debugging required in init_hw to root cause the hang. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 8e767c84359c..6e56fa3a135b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -279,6 +279,18 @@ static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) if (z_idx == cfg->tree_cfg->num_pipes) { ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes); mpcc_id = mpc10_get_idle_mpcc_id(mpc10); + + /* + * TODO: remove hack + * Note: currently there is a bug in init_hw such that + * on resume from hibernate, BIOS sets up MPCC0, and + * we do mpcc_remove but the mpcc cannot go to idle + * after remove. This cause us to pick mpcc1 here, + * which causes a pstate hang for yet unknown reason. + */ + mpcc_id = cfg->dpp_id; + /* end hack*/ + ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id)); if (mpc->ctx->dc->debug.sanity_checks) -- GitLab From 62bf6e9b292212b9a821bd3c24adff57ff4b4bd7 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Thu, 14 Sep 2017 18:01:40 -0400 Subject: [PATCH 1265/2898] drm/amd/display: update blending mode and set output denorm Signed-off-by: Eric Bernstein Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 27 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 4 +++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 6e56fa3a135b..334f072cea1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -313,10 +313,34 @@ static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) return mpcc_id; } +static void mpc10_update_blend_mode( + struct mpc *mpc, + struct mpcc_cfg *cfg) +{ + struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); + int mpcc_id, z_idx; + int alpha_blnd_mode = cfg->per_pixel_alpha ? + BLND_PP_ALPHA : BLND_GLOBAL_ALPHA; + + /* find z_idx for the dpp that requires blending mode update*/ + for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++) + if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id) + break; + + ASSERT(z_idx < cfg->tree_cfg->num_pipes); + mpcc_id = cfg->tree_cfg->mpcc[z_idx]; + + REG_UPDATE_2(MPCC_CONTROL[mpcc_id], + MPCC_ALPHA_BLND_MODE, alpha_blnd_mode, + MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha); +} + const struct mpc_funcs dcn10_mpc_funcs = { .add = mpc10_mpcc_add, .remove = mpc10_mpcc_remove, - .wait_for_idle = mpc10_assert_idle_mpcc + .wait_for_idle = mpc10_assert_idle_mpcc, + .set_denorm = NULL, + .update_blend_mode = mpc10_update_blend_mode }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, @@ -337,3 +361,4 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpc10, mpc10->mpcc_in_use_mask = 0; mpc10->num_mpcc = num_mpcc; } + diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 2d3de5b68e34..fb590f5353a0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -51,6 +51,10 @@ struct mpc_funcs { int opp_id, int mpcc_inst); void (*wait_for_idle)(struct mpc *mpc, int id); + void (*set_denorm)(struct mpc *mpc, + int opp_id, + enum dc_color_depth output_depth); + void (*update_blend_mode)(struct mpc *mpc, struct mpcc_cfg *cfg); }; #endif -- GitLab From 5eefbc40173644b5f74d7e074ba6cd8de5563e05 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Fri, 15 Sep 2017 17:42:20 -0400 Subject: [PATCH 1266/2898] drm/amd/display: moving backlight registers to hwsequencer Signed-off-by: Yue Hin Lau Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- .../drm/amd/display/dc/core/dc_link_hwss.c | 11 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 47 ++++++-- .../drm/amd/display/dc/dce/dce_link_encoder.c | 79 +------------- .../drm/amd/display/dc/dce/dce_link_encoder.h | 27 ++--- .../display/dc/dce110/dce110_hw_sequencer.c | 103 +++++++++++++++++- .../drm/amd/display/dc/inc/hw/link_encoder.h | 4 +- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + .../display/dc/virtual/virtual_link_encoder.c | 8 +- 9 files changed, 158 insertions(+), 127 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index c7751a31081a..976f0f136f29 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1807,7 +1807,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) else dp_disable_link_phy_mst(link, signal); } else - link->link_enc->funcs->disable_output(link->link_enc, signal); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); } enum dc_status dc_link_validate_mode_timing( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 5f815cab94b5..fa2250554be5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -94,7 +94,7 @@ void dp_enable_link_phy( link_enc, link_settings, clock_source); - link_enc->funcs->backlight_control(link_enc, true); + link->dc->hwss.backlight_control(link, true); } else link_enc->funcs->enable_dp_output( link_enc, @@ -138,12 +138,12 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { - link->link_enc->funcs->backlight_control(link->link_enc, false); + link->dc->hwss.backlight_control(link, false); edp_receiver_ready_T9(link); - link->link_enc->funcs->disable_output(link->link_enc, signal); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); link->link_enc->funcs->power_control(link->link_enc, false); } else - link->link_enc->funcs->disable_output(link->link_enc, signal); + link->link_enc->funcs->disable_output(link->link_enc, signal, link); /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, @@ -286,7 +286,8 @@ void dp_retrain_link_dp_test(struct dc_link *link, link->link_enc->funcs->disable_output( link->link_enc, - SIGNAL_TYPE_DISPLAY_PORT); + SIGNAL_TYPE_DISPLAY_PORT, + link); /* Clear current link setting. */ memset(&link->cur_link_settings, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 5798001da770..227c9b655b65 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -27,6 +27,10 @@ #include "hw_sequencer.h" +#define BL_REG_LIST()\ + SR(LVTMA_PWRSEQ_CNTL), \ + SR(LVTMA_PWRSEQ_STATE) + #define HWSEQ_DCEF_REG_LIST_DCE8() \ .DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \ .DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \ @@ -86,24 +90,27 @@ SRII(BLND_CONTROL, BLND, 0),\ SRII(BLND_CONTROL, BLND, 1),\ SR(BLNDV_CONTROL),\ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC),\ + BL_REG_LIST() #define HWSEQ_DCE8_REG_LIST() \ HWSEQ_DCEF_REG_LIST_DCE8(), \ HWSEQ_BLND_REG_LIST(), \ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC),\ + BL_REG_LIST() #define HWSEQ_DCE10_REG_LIST() \ HWSEQ_DCEF_REG_LIST(), \ HWSEQ_BLND_REG_LIST(), \ - HWSEQ_PIXEL_RATE_REG_LIST(CRTC) + HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ + BL_REG_LIST() #define HWSEQ_ST_REG_LIST() \ HWSEQ_DCE11_REG_LIST_BASE(), \ .DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \ .CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \ .BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \ - .BLND_CONTROL[2] = mmBLNDV_CONTROL, + .BLND_CONTROL[2] = mmBLNDV_CONTROL #define HWSEQ_CZ_REG_LIST() \ HWSEQ_DCE11_REG_LIST_BASE(), \ @@ -123,12 +130,14 @@ SR(DCHUB_FB_LOCATION),\ SR(DCHUB_AGP_BASE),\ SR(DCHUB_AGP_BOT),\ - SR(DCHUB_AGP_TOP) + SR(DCHUB_AGP_TOP), \ + BL_REG_LIST() #define HWSEQ_DCE112_REG_LIST() \ HWSEQ_DCE10_REG_LIST(), \ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ - HWSEQ_PHYPLL_REG_LIST(CRTC) + HWSEQ_PHYPLL_REG_LIST(CRTC), \ + BL_REG_LIST() #define HWSEQ_DCN_REG_LIST()\ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ @@ -228,9 +237,15 @@ SR(D2VGA_CONTROL), \ SR(D3VGA_CONTROL), \ SR(D4VGA_CONTROL), \ - SR(DC_IP_REQUEST_CNTL) + SR(DC_IP_REQUEST_CNTL), \ + BL_REG_LIST() struct dce_hwseq_registers { + + /* Backlight registers */ + uint32_t LVTMA_PWRSEQ_CNTL; + uint32_t LVTMA_PWRSEQ_STATE; + uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFEV_CLOCK_CONTROL; uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL; @@ -375,20 +390,24 @@ struct dce_hwseq_registers { HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\ - HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) #define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ @@ -396,14 +415,16 @@ struct dce_hwseq_registers { SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\ SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ - SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh) + SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ - HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh) + HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ @@ -467,7 +488,8 @@ struct dce_hwseq_registers { HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh) + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ @@ -497,7 +519,8 @@ struct dce_hwseq_registers { type PHYSICAL_PAGE_NUMBER_LSB;\ type LOGICAL_ADDR; \ type ENABLE_L1_TLB;\ - type SYSTEM_ACCESS_MODE; + type SYSTEM_ACCESS_MODE;\ + type LVTMA_BLON; #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 37aeddfb7431..1cb727bdaa56 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -122,7 +122,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .psr_program_dp_dphy_fast_training = dce110_psr_program_dp_dphy_fast_training, .psr_program_secondary_packet = dce110_psr_program_secondary_packet, - .backlight_control = dce110_link_encoder_edp_backlight_control, .power_control = dce110_link_encoder_edp_power_control, .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, .enable_hpd = dce110_link_encoder_enable_hpd, @@ -674,16 +673,6 @@ static void aux_initialize( } -/*todo: cloned in stream enc, fix*/ -static bool is_panel_backlight_on(struct dce110_link_encoder *enc110) -{ - uint32_t value; - - REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); - - return value; -} - void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc, bool exit_link_training_required) { @@ -718,69 +707,6 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc, DP_SEC_GSP0_PRIORITY, 1); } -/*todo: cloned in stream enc, fix*/ -/* - * @brief - * eDP only. Control the backlight of the eDP panel - */ -void dce110_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - struct bp_transmitter_control cntl = { 0 }; - - if (dal_graphics_object_id_get_connector_id(enc110->base.connector) - != CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if (enable && is_panel_backlight_on(enc110)) { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: panel already powered up. Do nothing.\n", - __func__); - return; - } - - if (!enable && !is_panel_backlight_on(enc110)) { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: panel already powered down. Do nothing.\n", - __func__); - return; - } - - /* Send VBIOS command to control eDP panel backlight */ - - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: backlight action: %s\n", - __func__, (enable ? "On":"Off")); - - cntl.action = enable ? - TRANSMITTER_CONTROL_BACKLIGHT_ON : - TRANSMITTER_CONTROL_BACKLIGHT_OFF; - /*cntl.engine_id = ctx->engine;*/ - cntl.transmitter = enc110->base.transmitter; - cntl.connector_obj_id = enc110->base.connector; - /*todo: unhardcode*/ - cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = enc110->base.hpd_source; - - /* For eDP, the following delays might need to be considered - * after link training completed: - * idle period - min. accounts for required BS-Idle pattern, - * max. allows for source frame synchronization); - * 50 msec max. delay from valid video data from source - * to video on dislpay or backlight enable. - * - * Disable the delay for now. - * Enable it in the future if necessary. - */ - /* dc_service_sleep_in_milliseconds(50); */ - link_transmitter_control(enc110, &cntl); -} - static bool is_dig_enabled(const struct dce110_link_encoder *enc110) { uint32_t value; @@ -1279,7 +1205,8 @@ void dce110_link_encoder_enable_dp_mst_output( */ void dce110_link_encoder_disable_output( struct link_encoder *enc, - enum signal_type signal) + enum signal_type signal, + struct dc_link *link) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); struct dc_context *ctx = enc110->base.ctx; @@ -1291,7 +1218,7 @@ void dce110_link_encoder_disable_output( return; } if (enc110->base.connector.id == CONNECTOR_ID_EDP) - dce110_link_encoder_edp_backlight_control(enc, false); + ctx->dc->hwss.backlight_control(link, false); /* Power-down RX and disable GPU PHY should be paired. * Disabling PHY without powering down RX may cause * symbol lock loss, on which we will get DP Sink interrupt. */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 05463df7e636..c65def5f6a44 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -69,10 +69,6 @@ SRI(DP_DPHY_FAST_TRAINING, DP, id), \ SRI(DP_SEC_CNTL1, DP, id) -#define LE_EDP_REG_LIST(id)\ - SR(LVTMA_PWRSEQ_CNTL), \ - SR(LVTMA_PWRSEQ_STATE) - #define LE_COMMON_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ @@ -81,38 +77,32 @@ #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - LE_COMMON_REG_LIST_BASE(id), \ - LE_EDP_REG_LIST(id) + LE_COMMON_REG_LIST_BASE(id) #define LE_DCE100_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR(DCI_MEM_PWR_STATUS), \ - LE_EDP_REG_LIST(id) + SR(DCI_MEM_PWR_STATUS) #define LE_DCE110_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DCI_MEM_PWR_STATUS), \ - LE_EDP_REG_LIST(id) + SR(DCI_MEM_PWR_STATUS) #define LE_DCE120_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DCI_MEM_PWR_STATUS), \ - LE_EDP_REG_LIST(id) + SR(DCI_MEM_PWR_STATUS) #define LE_DCN10_REG_LIST(id)\ LE_COMMON_REG_LIST_BASE(id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ - SR(DMU_MEM_PWR_CNTL), \ - LE_EDP_REG_LIST(id) + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; @@ -243,7 +233,8 @@ void dce110_link_encoder_enable_dp_mst_output( /* disable PHY output */ void dce110_link_encoder_disable_output( struct link_encoder *link_enc, - enum signal_type signal); + enum signal_type signal, + struct dc_link *link); /* set DP lane settings */ void dce110_link_encoder_dp_set_lane_settings( @@ -259,10 +250,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable); - void dce110_link_encoder_edp_power_control( struct link_encoder *enc, bool power_up); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d83a330712f7..9fc43bcac5bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -56,6 +56,15 @@ #include "dce/dce_11_0_sh_mask.h" #include "custom_float.h" +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + struct dce110_hw_seq_reg_offsets { uint32_t crtc; }; @@ -761,6 +770,92 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) } +/*todo: cloned in stream enc, fix*/ +static bool is_panel_backlight_on(struct dce_hwseq *hws) +{ + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value); + + return value; +} + +static enum bp_result link_transmitter_control( + struct dc_link *link, + struct bp_transmitter_control *cntl) +{ + enum bp_result result; + struct dc_bios *bp = link->dc->ctx->dc_bios; + + result = bp->funcs->transmitter_control(bp, cntl); + + return result; +} + + +/*todo: cloned in stream enc, fix*/ +/* + * @brief + * eDP only. Control the backlight of the eDP panel + */ +void hwss_blacklight_control( + struct dc_link *link, + bool enable) +{ + struct dce_hwseq *hws = link->dc->hwseq; + struct dc_context *ctx = link->dc->ctx; + struct bp_transmitter_control cntl = { 0 }; + + if (dal_graphics_object_id_get_connector_id(link->link_id) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (enable && is_panel_backlight_on(hws)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered up. Do nothing.\n", + __func__); + return; + } + + if (!enable && !is_panel_backlight_on(hws)) { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: panel already powered down. Do nothing.\n", + __func__); + return; + } + + /* Send VBIOS command to control eDP panel backlight */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: backlight action: %s\n", + __func__, (enable ? "On":"Off")); + + cntl.action = enable ? + TRANSMITTER_CONTROL_BACKLIGHT_ON : + TRANSMITTER_CONTROL_BACKLIGHT_OFF; + /*cntl.engine_id = ctx->engine;*/ + cntl.transmitter = link->link_enc->transmitter; + cntl.connector_obj_id = link->link_enc->connector; + /*todo: unhardcode*/ + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = link->link_enc->hpd_source; + + /* For eDP, the following delays might need to be considered + * after link training completed: + * idle period - min. accounts for required BS-Idle pattern, + * max. allows for source frame synchronization); + * 50 msec max. delay from valid video data from source + * to video on dislpay or backlight enable. + * + * Disable the delay for now. + * Enable it in the future if necessary. + */ + /* dc_service_sleep_in_milliseconds(50); */ + link_transmitter_control(link, &cntl); +} + void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; @@ -798,7 +893,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) /* blank at encoder level */ if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) - link->link_enc->funcs->backlight_control(link->link_enc, false); + hwss_blacklight_control(link, false); pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); } link->link_enc->funcs->connect_dig_be_to_fe( @@ -820,7 +915,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); if (link->connector_signal == SIGNAL_TYPE_EDP) - link->link_enc->funcs->backlight_control(link->link_enc, true); + hwss_blacklight_control(link, true); } @@ -1184,7 +1279,7 @@ static void power_down_encoders(struct dc *dc) } dc->links[i]->link_enc->funcs->disable_output( - dc->links[i]->link_enc, signal); + dc->links[i]->link_enc, signal, dc->links[i]); } } @@ -2733,7 +2828,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, - + .backlight_control = hwss_blacklight_control }; void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 961bbcc9202c..6cd6bc7d15fb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -111,7 +111,7 @@ struct link_encoder_funcs { const struct dc_link_settings *link_settings, enum clock_source_id clock_source); void (*disable_output)(struct link_encoder *link_enc, - enum signal_type signal); + enum signal_type signal, struct dc_link *link); void (*dp_set_lane_settings)(struct link_encoder *enc, const struct link_training_settings *link_settings); void (*dp_set_phy_pattern)(struct link_encoder *enc, @@ -123,8 +123,6 @@ struct link_encoder_funcs { bool exit_link_training_required); void (*psr_program_secondary_packet)(struct link_encoder *enc, unsigned int sdp_transmit_line_num_deadline); - void (*backlight_control) (struct link_encoder *enc, - bool enable); void (*power_control) (struct link_encoder *enc, bool power_up); void (*connect_dig_be_to_fe)(struct link_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 1fa2edc6cfb1..210874f37722 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -176,6 +176,10 @@ struct hw_sequencer_funcs { void (*ready_shared_resources)(struct dc *dc, struct dc_state *context); void (*optimize_shared_resources)(struct dc *dc); + + void (*backlight_control)( + struct dc_link *link, + bool enable); }; void color_space_to_black_color( diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index db513abd735a..4f405348130f 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -58,7 +58,8 @@ static void virtual_link_encoder_enable_dp_mst_output( static void virtual_link_encoder_disable_output( struct link_encoder *link_enc, - enum signal_type signal) {} + enum signal_type signal, + struct dc_link *link) {} static void virtual_link_encoder_dp_set_lane_settings( struct link_encoder *enc, @@ -72,10 +73,6 @@ static void virtual_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table) {} -static void virtual_link_encoder_edp_backlight_control( - struct link_encoder *enc, - bool enable) {} - static void virtual_link_encoder_edp_power_control( struct link_encoder *enc, bool power_up) {} @@ -105,7 +102,6 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = { .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = virtual_link_encoder_update_mst_stream_allocation_table, - .backlight_control = virtual_link_encoder_edp_backlight_control, .power_control = virtual_link_encoder_edp_power_control, .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, .destroy = virtual_link_encoder_destroy -- GitLab From dbaed8037c6c606456c182f5fc327f9d405a7ffe Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 19 Sep 2017 11:35:23 -0400 Subject: [PATCH 1267/2898] drm/amd/display: edp backlight regression fix Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 5 +++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index db6c19cd15eb..3e95f7f92c73 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -68,5 +68,10 @@ void dce110_fill_display_configs( uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); + +void hwss_blacklight_control( + struct dc_link *link, + bool enable); + #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 82a985a981be..bf5c9243ba7a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2897,6 +2897,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, + .backlight_control = hwss_blacklight_control }; -- GitLab From 5df921d4c0e3e2065b961ac8d4269be68f80801d Mon Sep 17 00:00:00 2001 From: Ken Chalmers Date: Wed, 20 Sep 2017 11:48:47 -0400 Subject: [PATCH 1268/2898] drm/amd/display: fix ASSERT() caused by missing registers. Signed-off-by: Ken Chalmers Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index bf5c9243ba7a..cdaed0c0a70c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -771,14 +771,16 @@ static void power_on_plane( struct dce_hwseq *hws, int plane_id) { - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dpp_pg_control(hws, plane_id, true); - hubp_pg_control(hws, plane_id, true); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - dm_logger_write(hws->ctx->logger, LOG_DEBUG, - "Un-gated front end for pipe %d\n", plane_id); + if (REG(DC_IP_REQUEST_CNTL)) { + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, plane_id, true); + hubp_pg_control(hws, plane_id, true); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(hws->ctx->logger, LOG_DEBUG, + "Un-gated front end for pipe %d\n", plane_id); + } } static void undo_DEGVIDCN10_253_wa(struct dc *dc) @@ -1130,18 +1132,20 @@ static void plane_atomic_power_down(struct dc *dc, int fe_idx) struct dce_hwseq *hws = dc->hwseq; struct transform *xfm = dc->res_pool->transforms[fe_idx]; - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dpp_pg_control(hws, fe_idx, false); - hubp_pg_control(hws, fe_idx, false); - xfm->funcs->transform_reset(xfm); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - dm_logger_write(dc->ctx->logger, LOG_DEBUG, - "Power gated front end %d\n", fe_idx); + if (REG(DC_IP_REQUEST_CNTL)) { + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 1); + dpp_pg_control(hws, fe_idx, false); + hubp_pg_control(hws, fe_idx, false); + xfm->funcs->transform_reset(xfm); + REG_SET(DC_IP_REQUEST_CNTL, 0, + IP_REQUEST_EN, 0); + dm_logger_write(dc->ctx->logger, LOG_DEBUG, + "Power gated front end %d\n", fe_idx); - if (dc->debug.sanity_checks) - verify_allow_pstate_change_high(dc->hwseq); + if (dc->debug.sanity_checks) + verify_allow_pstate_change_high(dc->hwseq); + } } -- GitLab From 19af33aca4384f840838a781f105726bb24c604f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 20 Sep 2017 14:06:24 -0400 Subject: [PATCH 1269/2898] drm/amd/display: make sure BL off to mainlink off has enough time Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 9fc43bcac5bc..f28fce6e6ba4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -819,13 +819,6 @@ void hwss_blacklight_control( return; } - if (!enable && !is_panel_backlight_on(hws)) { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: panel already powered down. Do nothing.\n", - __func__); - return; - } - /* Send VBIOS command to control eDP panel backlight */ dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, -- GitLab From 6d732e7917064195b65303cab9591f311b621034 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 20 Sep 2017 16:15:18 -0400 Subject: [PATCH 1270/2898] drm/amd/display: add hubp/dpp pg debug key Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 50440731f83c..2e77885fc1ea 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -191,6 +191,8 @@ struct dc_debug { bool disable_dmcu; bool disable_psr; bool force_abm_enable; + bool disable_hbup_pg; + bool disable_dpp_pg; }; struct dc_state; struct resource_pool; -- GitLab From e750d56d2c62875c81f52344afab44220300388d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 20 Sep 2017 17:06:18 -0400 Subject: [PATCH 1271/2898] drm/amd/display: Fixed validation return wrong result. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6c04ad1b5859..0707bec111a5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4748,7 +4748,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - if (!dc_validate_global_state(dc, dm_state->context)) { + if (dc_validate_global_state(dc, dm_state->context) != DC_OK) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 77b3474a7c9e..d9a2d09a1f4f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1716,7 +1716,7 @@ void dc_resource_state_construct( dst_ctx->dis_clk = dc->res_pool->display_clock; } -bool dc_validate_global_state( +enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2e77885fc1ea..1e49b8f9c66e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -654,7 +654,7 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); -bool dc_validate_global_state( +enum dc_status dc_validate_global_state( struct dc *dc, struct dc_state *new_ctx); -- GitLab From 4d1a562659e1414ccb010bea56286ba4302e84e5 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 5 Sep 2017 21:13:55 -0400 Subject: [PATCH 1272/2898] drm/amd/display: version 3.1.02 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1e49b8f9c66e..12601ffc0fe4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.01" +#define DC_VER "3.1.02" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- GitLab From 4f4ee68686c74bf1dfde6fa9fb7124104ff6f283 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 20 Sep 2017 16:30:44 -0400 Subject: [PATCH 1273/2898] drm/amd/display: screen flickers when connected to ext monitor in clone Signed-off-by: Hersen Wu Signed-off-by: Tony Cheng Reviewed-by: Hersen Wu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 8 ++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 3 +++ 3 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 8ca6c3e4e65a..cc99073b7a54 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1018,9 +1018,17 @@ bool dcn_validate_bandwidth( context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); + context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); if (dc->debug.max_disp_clk == true) context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000); + + if (context->bw.dcn.calc_clk.dispclk_khz < + dc->debug.min_disp_clk_khz) { + context->bw.dcn.calc_clk.dispclk_khz = + dc->debug.min_disp_clk_khz; + } + context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 12601ffc0fe4..7a3a48179452 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -178,6 +178,7 @@ struct dc_debug { bool disable_pplib_wm_range; bool use_dml_wm; bool disable_pipe_split; + unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; int sr_exit_time_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4f124dc303dc..82c82b6310ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -420,6 +420,9 @@ static const struct dc_debug debug_defaults_drv = { .force_abm_enable = false, .timing_trace = false, .clock_trace = true, + + .min_disp_clk_khz = 300000, + .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, #if defined(CONFIG_DRM_AMD_DC_DCN1_0) -- GitLab From d596e5d08da0a25be789432ed821e63db9ef72ac Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 21 Sep 2017 10:46:33 -0400 Subject: [PATCH 1274/2898] drm/amd/display: Fixed incorrect return value for validaton Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index d9a2d09a1f4f..bbfec7cb2ad1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1723,10 +1723,11 @@ enum dc_status dc_validate_global_state( enum dc_status result = DC_ERROR_UNEXPECTED; int i, j; - if (dc->res_pool->funcs->validate_global && - dc->res_pool->funcs->validate_global( - dc, new_ctx) != DC_OK) - return false; + if (dc->res_pool->funcs->validate_global) { + result = dc->res_pool->funcs->validate_global(dc, new_ctx); + if (result != DC_OK) + return result; + } for (i = 0; new_ctx && i < new_ctx->stream_count; i++) { struct dc_stream_state *stream = new_ctx->streams[i]; -- GitLab From fcbbe3da0ab65dc114937857fce81902e3fa2a97 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 21 Sep 2017 18:16:01 -0400 Subject: [PATCH 1275/2898] drm/amd/display: Use active + border for bw validation When doing SLS, KMD gives us clipped v_addressable with border. This results in bw validation failure. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index cc99073b7a54..319450d9cfc1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -364,7 +364,8 @@ static void pipe_ctx_to_e2e_pipe_params ( } - input->dest.vactive = pipe->stream->timing.v_addressable; + input->dest.vactive = pipe->stream->timing.v_addressable + pipe->stream->timing.v_border_top + + pipe->stream->timing.v_border_bottom; input->dest.recout_width = pipe->plane_res.scl_data.recout.width; input->dest.recout_height = pipe->plane_res.scl_data.recout.height; @@ -882,10 +883,11 @@ bool dcn_validate_bandwidth( v->htotal[input_idx] = pipe->stream->timing.h_total; v->vtotal[input_idx] = pipe->stream->timing.v_total; + v->vactive[input_idx] = pipe->stream->timing.v_addressable + + pipe->stream->timing.v_border_top + pipe->stream->timing.v_border_bottom; v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total - - pipe->stream->timing.v_addressable + - v->vactive[input_idx] - pipe->stream->timing.v_front_porch; - v->vactive[input_idx] = pipe->stream->timing.v_addressable; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; if (!pipe->plane_state) { -- GitLab From e4ba6335cd91367f31978db1fc62d6bac0489672 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 21 Sep 2017 18:53:40 -0400 Subject: [PATCH 1276/2898] drm/amd/display: update link type to mst before topology discovery [Description] link type is not updated before mst topology discovery. This causes issue when branch device response to link address after before the start topology discovery event finishes. [Solution] update link type to mst before topology discovery Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 976f0f136f29..a58e61b6e9f9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -496,6 +496,7 @@ static void detect_dp( } if (is_mst_supported(link)) { sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + link->type = dc_connection_mst_branch; /* * This call will initiate MST topology discovery. Which @@ -524,12 +525,11 @@ static void detect_dp( if (reason == DETECT_REASON_BOOT) boot = true; - if (dm_helpers_dp_mst_start_top_mgr( + if (!dm_helpers_dp_mst_start_top_mgr( link->ctx, link, boot)) { - link->type = dc_connection_mst_branch; - } else { /* MST not supported */ + link->type = dc_connection_single; sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; } } -- GitLab From 69b516c91cbf459e5fd4b8b6e97cfdfa7ea25126 Mon Sep 17 00:00:00 2001 From: SivapiriyanKumarasamy Date: Fri, 22 Sep 2017 12:48:54 -0400 Subject: [PATCH 1277/2898] drm/amd/display: Program stream's csc matrix instead of using default Signed-off-by: SivapiriyanKumarasamy Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index cdaed0c0a70c..4e4f20ba5643 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2259,7 +2259,6 @@ static void update_dchubp_dpp( struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; - struct default_adjustment ocsc = {0}; struct mpcc_cfg mpcc_cfg = {0}; struct pipe_ctx *top_pipe; bool per_pixel_alpha = plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; @@ -2338,9 +2337,9 @@ static void update_dchubp_dpp( /*gamut remap*/ program_gamut_remap(pipe_ctx); - /*TODO add adjustments parameters*/ - ocsc.out_color_space = pipe_ctx->stream->output_color_space; - pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(pipe_ctx->plane_res.xfm, &ocsc); + program_csc_matrix(pipe_ctx, + pipe_ctx->stream->output_color_space, + pipe_ctx->stream->csc_color_matrix.matrix); mi->funcs->mem_input_program_surface_config( mi, -- GitLab From 671a6246e0d3652c024f99d5641c7cf427b0b5a5 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 22 Sep 2017 13:41:13 -0400 Subject: [PATCH 1278/2898] drm/amd/display: Early return when turn off a plane. In case of two monitor connected and turn off one of the monitors, OTG0 is locked after graphic plane off due to redundant programming front end regs. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2cea8de9c9be..ffc36f5ac50c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1190,8 +1190,14 @@ static void commit_planes_for_stream(struct dc *dc, } } - if (surface_count == 0) + if (surface_count == 0) { + /* + * In case of turning off screen, no need to program front end a second time. + * just return after program front end. + */ dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context); + return; + } /* Lock pipes for provided surfaces, or all active if full update*/ for (i = 0; i < surface_count; i++) { -- GitLab From 56e6ed4561f2962d1220c16bbd2709ced7a84be8 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 22 Sep 2017 16:06:04 -0400 Subject: [PATCH 1279/2898] drm/amd/display: Only reset top pipe back end. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4e4f20ba5643..014911ebdbd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1270,6 +1270,9 @@ static void reset_hw_ctx_wrap( if (!pipe_ctx_old->stream) continue; + if (pipe_ctx_old->top_pipe) + continue; + if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { struct clock_source *old_clk = pipe_ctx_old->clock_source; -- GitLab From 544276514760f293eadb68461f1b45b6ccec073e Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Wed, 20 Sep 2017 15:04:52 -0400 Subject: [PATCH 1280/2898] drm/amd/display: Fix MST daisy chain SST not light up In SST daisy chain scenario, edid is getting read in mst hotplug routine. It is getting conflict with drm send_enum_path_resources kernel thread in terms of i2c bus which is getting locked up in such case. Have edid being read in get_mode hook, instead of in hotplug routine. Signed-off-by: Jerry Zuo Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 110 ++++++++---------- 1 file changed, 49 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index dfcfb5a722e0..610375b2a04b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -174,14 +174,60 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .atomic_get_property = amdgpu_dm_connector_atomic_get_property }; +static int dm_connector_update_modes(struct drm_connector *connector, + struct edid *edid) +{ + int ret; + + ret = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + + return ret; +} + static int dm_dp_mst_get_modes(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); int ret = 0; - ret = drm_add_edid_modes(&aconnector->base, aconnector->edid); + if (!aconnector) + return dm_connector_update_modes(connector, NULL); + + if (!aconnector->edid) { + struct edid *edid; + struct dc_sink *dc_sink; + struct dc_sink_init_data init_params = { + .link = aconnector->dc_link, + .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; + edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); - drm_edid_to_eld(&aconnector->base, aconnector->edid); + if (!edid) { + drm_mode_connector_update_edid_property( + &aconnector->base, + NULL); + return ret; + } + + aconnector->edid = edid; + + dc_sink = dc_link_add_remote_sink( + aconnector->dc_link, + (uint8_t *)edid, + (edid->extensions + 1) * EDID_LENGTH, + &init_params); + + dc_sink->priv = aconnector; + aconnector->dc_sink = dc_sink; + + if (aconnector->dc_sink) + amdgpu_dm_add_sink_to_freesync_module( + connector, edid); + + drm_mode_connector_update_edid_property( + &aconnector->base, edid); + } + + ret = dm_connector_update_modes(connector, aconnector->edid); return ret; } @@ -343,66 +389,8 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) { struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; - struct amdgpu_device *adev = dev->dev_private; - struct drm_connector *connector; - struct amdgpu_dm_connector *aconnector; - struct edid *edid; - struct dc_sink *dc_sink; - - drm_modeset_lock_all(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_dm_connector(connector); - if (aconnector->port && - aconnector->port->pdt != DP_PEER_DEVICE_NONE && - aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING && - !aconnector->dc_sink) { - /* - * This is plug in case, where port has been created but - * sink hasn't been created yet - */ - if (!aconnector->edid) { - struct dc_sink_init_data init_params = { - .link = aconnector->dc_link, - .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST}; - edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); - - if (!edid) { - drm_mode_connector_update_edid_property( - &aconnector->base, - NULL); - continue; - } - - aconnector->edid = edid; - - dc_sink = dc_link_add_remote_sink( - aconnector->dc_link, - (uint8_t *)edid, - (edid->extensions + 1) * EDID_LENGTH, - &init_params); - - dc_sink->priv = aconnector; - aconnector->dc_sink = dc_sink; - - if (aconnector->dc_sink) - amdgpu_dm_add_sink_to_freesync_module( - connector, - edid); - - dm_restore_drm_connector_state(connector->dev, connector); - } else - edid = aconnector->edid; - - DRM_DEBUG_KMS("edid retrieved %p\n", edid); - - drm_mode_connector_update_edid_property( - &aconnector->base, - aconnector->edid); - } - } - drm_modeset_unlock_all(dev); - schedule_work(&adev->dm.mst_hotplug_work); + drm_kms_helper_hotplug_event(dev); } static void dm_dp_mst_register_connector(struct drm_connector *connector) -- GitLab From e778915c916229475ba76267534b70834ba8de8d Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 25 Sep 2017 15:52:49 -0400 Subject: [PATCH 1281/2898] drm/amd/display: temp disable DCC on high res. Signed-off-by: Charlene Liu Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 82c82b6310ca..dd3ff5114d42 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1133,20 +1133,27 @@ static bool get_dcc_compression_cap(const struct dc *dc, output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 256; output->grph.rgb.independent_64b_blks = false; + output->capable = true; + output->const_color_support = false; break; case dcc_control__128_128_xxx: output->grph.rgb.max_uncompressed_blk_size = 128; output->grph.rgb.max_compressed_blk_size = 128; output->grph.rgb.independent_64b_blks = false; + /*temp: not allow dcc on high res*/ + output->capable = false; + output->const_color_support = false; break; case dcc_control__256_64_64: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 64; output->grph.rgb.independent_64b_blks = true; + /*temp: not allow dcc on high res*/ + output->capable = false; + output->const_color_support = false; break; } - output->capable = true; - output->const_color_support = false; + return true; } -- GitLab From db64fbe73288f0b5f2a36ecdd48c9bae978406e0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 25 Sep 2017 10:52:07 -0400 Subject: [PATCH 1282/2898] drm/amd/display: enable optional pipe split for single display also refactor debug option. now pipe_split_policy are dynamic = no hack around dcn_calcs. will split based on HW recommendation avoid = avoid split if we can support the config with higher voltage avoid_multi_display = allow split with single display output. force_single_disp_pipe_split force single display to pipe split to improve stutter efficiency by using DET buffers using 2 HUBP. Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 44 +++++++++++++++++-- drivers/gpu/drm/amd/display/dc/dc.h | 9 +++- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 8 +--- 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 319450d9cfc1..aa56243f2522 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -720,6 +720,46 @@ static bool dcn_bw_apply_registry_override(struct dc *dc) return updated; } +void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v) +{ + /* + * disable optional pipe split by lower dispclk bounding box + * at DPM0 + */ + v->max_dispclk[0] = v->max_dppclk_vmin0p65; +} + +void hack_force_pipe_split(struct dcn_bw_internal_vars *v, + unsigned int pixel_rate_khz) +{ + /* + * force enabling pipe split by lower dpp clock for DPM0 to just + * below the specify pixel_rate, so bw calc would split pipe. + */ + v->max_dppclk[0] = pixel_rate_khz / 1000; +} + +void hack_bounding_box(struct dcn_bw_internal_vars *v, + struct dc_debug *dbg, + struct dc_state *context) +{ + if (dbg->pipe_split_policy == MPC_SPLIT_AVOID) { + hack_disable_optional_pipe_split(v); + } + + if (dbg->pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP && + context->stream_count >= 2) { + hack_disable_optional_pipe_split(v); + } + + if (context->stream_count == 1 && + dbg->force_single_disp_pipe_split) { + struct dc_stream_state *stream0 = context->streams[0]; + + hack_force_pipe_split(v, stream0->timing.pix_clk_khz); + } +} + bool dcn_validate_bandwidth( struct dc *dc, struct dc_state *context) @@ -851,9 +891,7 @@ bool dcn_validate_bandwidth( v->phyclk_per_state[1] = v->phyclkv_mid0p72; v->phyclk_per_state[0] = v->phyclkv_min0p65; - if (dc->debug.disable_pipe_split) { - v->max_dispclk[0] = v->max_dppclk_vmin0p65; - } + hack_bounding_box(v, &dc->debug, context); if (v->voltage_override == dcn_bw_v_max0p9) { v->voltage_override_level = number_of_states - 1; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7a3a48179452..622488efa9e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -162,6 +162,12 @@ struct dc_config { bool disable_disp_pll_sharing; }; +enum pipe_split_policy { + MPC_SPLIT_DYNAMIC = 0, + MPC_SPLIT_AVOID = 1, + MPC_SPLIT_AVOID_MULT_DISP = 2, +}; + struct dc_debug { bool surface_visual_confirm; bool sanity_checks; @@ -177,7 +183,8 @@ struct dc_debug { bool disable_hubp_power_gate; bool disable_pplib_wm_range; bool use_dml_wm; - bool disable_pipe_split; + enum pipe_split_policy pipe_split_policy; + bool force_single_disp_pipe_split; unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index dd3ff5114d42..bd7c86e5800e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -425,10 +425,9 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) .use_dml_wm = false, - .disable_pipe_split = true -#endif + + .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, }; static const struct dc_debug debug_defaults_diags = { @@ -437,12 +436,9 @@ static const struct dc_debug debug_defaults_diags = { .timing_trace = true, .clock_trace = true, .disable_stutter = true, -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, .use_dml_wm = false, - .disable_pipe_split = false -#endif }; static void dcn10_dpp_destroy(struct transform **xfm) -- GitLab From a32a7708ae8b01c191768d503c1af33b85b369d0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Mon, 25 Sep 2017 18:06:11 -0400 Subject: [PATCH 1283/2898] drm/amd/display: add option to disable DCC for DCC 128b request 1. reverts commit e67f51012740 ("dc: temp disable DCC on high res.") - default still DCC enabled 2. add debug options to decide how DCC is disabled - disable DCC - disable DCC if DCC requires 128b (aka. half) request -- observed compressed data corruption result in screen corruption in full (256b) request while half (128b) would cause DCN to hang, result in DF hang Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 11 ++++++++--- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 18 ++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 622488efa9e6..d7afbcfb33ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -56,11 +56,10 @@ struct dc_caps { uint32_t max_planes; uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; - unsigned int max_cursor_size; + bool dcc_const_color; }; - struct dc_dcc_surface_param { struct dc_size surface_size; enum surface_pixel_format format; @@ -162,6 +161,12 @@ struct dc_config { bool disable_disp_pll_sharing; }; +enum dcc_option { + DCC_ENABLE = 0, + DCC_DISABLE = 1, + DCC_HALF_REQ_DISALBE = 2, +}; + enum pipe_split_policy { MPC_SPLIT_DYNAMIC = 0, MPC_SPLIT_AVOID = 1, @@ -177,7 +182,7 @@ struct dc_debug { bool clock_trace; bool validation_trace; bool disable_stutter; - bool disable_dcc; + enum dcc_option disable_dcc; bool disable_dfs_bypass; bool disable_dpp_power_gate; bool disable_hubp_power_gate; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index bd7c86e5800e..30c275e05796 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -414,7 +414,6 @@ static const struct resource_caps res_cap = { }; static const struct dc_debug debug_defaults_drv = { - .disable_dcc = false, .sanity_checks = true, .disable_dmcu = true, .force_abm_enable = false, @@ -428,6 +427,7 @@ static const struct dc_debug debug_defaults_drv = { .use_dml_wm = false, .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, + .disable_dcc = DCC_ENABLE, }; static const struct dc_debug debug_defaults_diags = { @@ -1080,7 +1080,7 @@ static bool get_dcc_compression_cap(const struct dc *dc, memset(output, 0, sizeof(*output)); - if (dc->debug.disable_dcc) + if (dc->debug.disable_dcc == DCC_DISABLE) return false; if (!dcc_support_pixel_format(input->format, @@ -1124,32 +1124,30 @@ static bool get_dcc_compression_cap(const struct dc *dc, dcc_control = dcc_control__128_128_xxx; } + if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE && + dcc_control != dcc_control__256_256_xxx) + return false; + switch (dcc_control) { case dcc_control__256_256_xxx: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 256; output->grph.rgb.independent_64b_blks = false; - output->capable = true; - output->const_color_support = false; break; case dcc_control__128_128_xxx: output->grph.rgb.max_uncompressed_blk_size = 128; output->grph.rgb.max_compressed_blk_size = 128; output->grph.rgb.independent_64b_blks = false; - /*temp: not allow dcc on high res*/ - output->capable = false; - output->const_color_support = false; break; case dcc_control__256_64_64: output->grph.rgb.max_uncompressed_blk_size = 256; output->grph.rgb.max_compressed_blk_size = 64; output->grph.rgb.independent_64b_blks = true; - /*temp: not allow dcc on high res*/ - output->capable = false; - output->const_color_support = false; break; } + output->capable = true; + output->const_color_support = false; return true; } -- GitLab From 966869d07aae2d1becfcb16b55cafd4aae3c6627 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 26 Sep 2017 01:56:00 -0400 Subject: [PATCH 1284/2898] drm/amd/display: option to maximize lb usage experimental change for testing if max line buffer result in better stutter efficiency for 1080p, LB can hold up to 9 line at 10bpcc, potentially add 10 line time of latency hiding. Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 8 ++++++-- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d7afbcfb33ce..427ccbc28f51 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -181,15 +181,19 @@ struct dc_debug { bool timing_trace; bool clock_trace; bool validation_trace; + + /* stutter efficiency related */ bool disable_stutter; + bool use_max_lb; enum dcc_option disable_dcc; + enum pipe_split_policy pipe_split_policy; + bool force_single_disp_pipe_split; + bool disable_dfs_bypass; bool disable_dpp_power_gate; bool disable_hubp_power_gate; bool disable_pplib_wm_range; bool use_dml_wm; - enum pipe_split_policy pipe_split_policy; - bool force_single_disp_pipe_split; unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 82b8887d4973..fa2ab9952388 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -507,6 +507,9 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, { enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; + if (xfm->base.ctx->dc->debug.use_max_lb) + return mem_cfg; + if (xfm->tf_mask->PIXEL_DEPTH) { mem_cfg = dpp10_find_lb_memory_config(scl_data); } -- GitLab From 9f945eab797b042930553388d37c12fed38f3396 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 26 Sep 2017 10:16:34 -0400 Subject: [PATCH 1285/2898] drm/amd/display: fix bug in force_single_disp_pipe_split should only lower dpp clock. Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index aa56243f2522..cf474eb1cde8 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -732,11 +732,14 @@ void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v) void hack_force_pipe_split(struct dcn_bw_internal_vars *v, unsigned int pixel_rate_khz) { + float pixel_rate_mhz = pixel_rate_khz / 1000; + /* * force enabling pipe split by lower dpp clock for DPM0 to just * below the specify pixel_rate, so bw calc would split pipe. */ - v->max_dppclk[0] = pixel_rate_khz / 1000; + if (pixel_rate_mhz < v->max_dppclk[0]) + v->max_dppclk[0] = pixel_rate_mhz; } void hack_bounding_box(struct dcn_bw_internal_vars *v, -- GitLab From 2e1cc334631849b035b24897d6be59d2a57b6f1c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 26 Sep 2017 17:06:26 -0400 Subject: [PATCH 1286/2898] drm/amd/display: dal 3.1.03 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 427ccbc28f51..cf9cd108539f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.02" +#define DC_VER "3.1.03" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- GitLab From 60d671db1c0c02f31bcff3ea5dee244d26b8ed77 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Mon, 25 Sep 2017 16:39:45 -0400 Subject: [PATCH 1287/2898] drm/amd/display: Fix ref_count messed up issue In the full update type, need to add ref_count to the newly created dc_state->stream. It made mistake to add ref_count to dc->current_state->stream which keeps adding up without release. Signed-off-by: Jerry Zuo Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ffc36f5ac50c..3439bc46a4a2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1322,6 +1322,7 @@ void dc_commit_updates_for_stream(struct dc *dc, const struct dc_stream_status *stream_status; enum surface_update_type update_type; struct dc_state *context; + struct dc_context *dc_ctx = dc->ctx; int i; stream_status = dc_stream_get_status(stream); @@ -1334,8 +1335,17 @@ void dc_commit_updates_for_stream(struct dc *dc, update_surface_trace(dc, srf_updates, surface_count); - if (update_type >= UPDATE_TYPE_FULL) + if (update_type >= UPDATE_TYPE_FULL) { + + /* initialize scratch memory for building context */ + context = dc_create_state(); + if (context == NULL) { + DC_ERROR("Failed to allocate new validate context!\n"); + return; + } + dc_resource_state_copy_construct(state, context); + } for (i = 0; i < surface_count; i++) { @@ -1361,6 +1371,15 @@ void dc_commit_updates_for_stream(struct dc *dc, dc_post_update_surfaces_to_stream(dc); + if (dc->current_state != context) { + + struct dc_state *old = dc->current_state; + + dc->current_state = context; + dc_release_state(old); + + } + return; } -- GitLab From b87d78d6aa104b207ff588d2cfd13633c2385994 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 19 Sep 2017 17:29:28 -0400 Subject: [PATCH 1288/2898] drm/amd/display: moving cursor functions from ipp to mem_input Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_stream.c | 32 ++- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 2 + .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 51 +++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 15 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c | 189 ------------------ .../amd/display/dc/dcn10/dcn10_mem_input.c | 163 +++++++++++++++ .../amd/display/dc/dcn10/dcn10_mem_input.h | 57 +++++- .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 10 + .../gpu/drm/amd/display/dc/inc/hw/transform.h | 11 + 9 files changed, 329 insertions(+), 201 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 23df7bc020d2..c19b478bcdc7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -195,13 +195,23 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.ipp) + if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.mi || !pipe_ctx->plane_res.xfm) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; - pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( - pipe_ctx->plane_res.ipp, attributes); + + if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL) + pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( + pipe_ctx->plane_res.ipp, attributes); + + if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( + pipe_ctx->plane_res.mi, attributes); + + if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( + pipe_ctx->plane_res.xfm, attributes); } return true; @@ -231,6 +241,8 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct mem_input *mi = pipe_ctx->plane_res.mi; + struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, @@ -241,7 +253,9 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->plane_res.ipp || !pipe_ctx->plane_state) + !pipe_ctx->plane_res.mi || + !pipe_ctx->plane_state || + !pipe_ctx->plane_res.xfm) continue; if (pipe_ctx->plane_state->address.type @@ -251,7 +265,15 @@ bool dc_stream_set_cursor_position( if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) pos_cpy.enable = false; - ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); + + if (ipp->funcs->ipp_cursor_set_position != NULL) + ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); + + if (mi->funcs->set_cursor_attributes != NULL) + mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); + + if (xfm->funcs->set_cursor_attributes != NULL) + xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, mi->curs_attr.width); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index fa481d481132..d618fdd0cc82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -37,6 +37,7 @@ #define CTX \ ipp_dce->base.ctx + static void dce_ipp_cursor_set_position( struct input_pixel_processor *ipp, const struct dc_cursor_position *position, @@ -133,6 +134,7 @@ static void dce_ipp_cursor_set_attributes( REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false); } + static void dce_ipp_program_prescale( struct input_pixel_processor *ipp, struct ipp_prescale_params *params) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index f9e43e68fc0c..05df3b222945 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -372,6 +372,55 @@ void ippn10_cnv_setup ( } } +void dcn10_set_cursor_attributes( + struct transform *xfm_base, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + enum dc_cursor_color_format color_format = attr->color_format; + + REG_UPDATE_2(CURSOR0_CONTROL, + CUR0_MODE, color_format, + CUR0_EXPANSION_MODE, 0); + + if (color_format == CURSOR_MODE_MONO) { + /* todo: clarify what to program these to */ + REG_UPDATE(CURSOR0_COLOR0, + CUR0_COLOR0, 0x00000000); + REG_UPDATE(CURSOR0_COLOR1, + CUR0_COLOR1, 0xFFFFFFFF); + } + + /* TODO: Fixed vs float */ + + REG_UPDATE_3(FORMAT_CONTROL, + CNVC_BYPASS, 0, + FORMAT_CONTROL__ALPHA_EN, 1, + FORMAT_EXPANSION_MODE, 0); +} + + +void dcn10_set_cursor_position( + struct transform *xfm_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, cur_en); + +} + static const struct transform_funcs dcn10_dpp_funcs = { .transform_reset = dpp_reset, .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, @@ -391,6 +440,8 @@ static const struct transform_funcs dcn10_dpp_funcs = { .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, .ipp_setup = ippn10_cnv_setup, .ipp_full_bypass = ippn10_full_bypass, + .set_cursor_attributes = dcn10_set_cursor_attributes, + .set_cursor_position = dcn10_set_cursor_position, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index a1f6b01a2eb4..7fecdb19761d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -112,7 +112,10 @@ SRI(CM_DGAM_CONTROL, CM, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ - SRI(CURSOR0_CONTROL, CNVC_CUR, id) + SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR1, CNVC_CUR, id) @@ -302,7 +305,9 @@ TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ - TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh) + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh) #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ TF_REG_LIST_SH_MASK_DCN(mask_sh),\ @@ -989,7 +994,9 @@ type CUR0_EXPANSION_MODE; \ type CUR0_ENABLE; \ type CM_BYPASS; \ - type FORMAT_CONTROL__ALPHA_EN + type FORMAT_CONTROL__ALPHA_EN; \ + type CUR0_COLOR0; \ + type CUR0_COLOR1 @@ -1237,6 +1244,8 @@ struct dcn_dpp_registers { uint32_t CNVC_SURFACE_PIXEL_FORMAT; uint32_t CURSOR_CONTROL; uint32_t CURSOR0_CONTROL; + uint32_t CURSOR0_COLOR0; + uint32_t CURSOR0_COLOR1; }; struct dcn10_dpp { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c index 67bd6a738fe9..08db1e6b5166 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_ipp.c @@ -37,188 +37,6 @@ #define CTX \ ippn10->base.ctx -static bool ippn10_cursor_program_control( - struct dcn10_ipp *ippn10, - bool pixel_data_invert, - enum dc_cursor_color_format color_format) -{ - if (REG(CURSOR_SETTINS)) - REG_SET_2(CURSOR_SETTINS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - else - REG_SET_2(CURSOR_SETTINGS, 0, - /* no shift of the cursor HDL schedule */ - CURSOR0_DST_Y_OFFSET, 0, - /* used to shift the cursor chunk request deadline */ - CURSOR0_CHUNK_HDL_ADJUST, 3); - - REG_UPDATE_2(CURSOR0_CONTROL, - CUR0_MODE, color_format, - CUR0_EXPANSION_MODE, 0); - - if (color_format == CURSOR_MODE_MONO) { - /* todo: clarify what to program these to */ - REG_UPDATE(CURSOR0_COLOR0, - CUR0_COLOR0, 0x00000000); - REG_UPDATE(CURSOR0_COLOR1, - CUR0_COLOR1, 0xFFFFFFFF); - } - - /* TODO: Fixed vs float */ - - REG_UPDATE_3(FORMAT_CONTROL, - CNVC_BYPASS, 0, - ALPHA_EN, 1, - FORMAT_EXPANSION_MODE, 0); - - return true; -} - -enum cursor_pitch { - CURSOR_PITCH_64_PIXELS = 0, - CURSOR_PITCH_128_PIXELS, - CURSOR_PITCH_256_PIXELS -}; - -enum cursor_lines_per_chunk { - CURSOR_LINE_PER_CHUNK_2 = 1, - CURSOR_LINE_PER_CHUNK_4, - CURSOR_LINE_PER_CHUNK_8, - CURSOR_LINE_PER_CHUNK_16 -}; - -static enum cursor_pitch ippn10_get_cursor_pitch( - unsigned int pitch) -{ - enum cursor_pitch hw_pitch; - - switch (pitch) { - case 64: - hw_pitch = CURSOR_PITCH_64_PIXELS; - break; - case 128: - hw_pitch = CURSOR_PITCH_128_PIXELS; - break; - case 256: - hw_pitch = CURSOR_PITCH_256_PIXELS; - break; - default: - DC_ERR("Invalid cursor pitch of %d. " - "Only 64/128/256 is supported on DCN.\n", pitch); - hw_pitch = CURSOR_PITCH_64_PIXELS; - break; - } - return hw_pitch; -} - -static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( - unsigned int cur_width, - enum dc_cursor_color_format format) -{ - enum cursor_lines_per_chunk line_per_chunk; - - if (format == CURSOR_MODE_MONO) - /* impl B. expansion in CUR Buffer reader */ - line_per_chunk = CURSOR_LINE_PER_CHUNK_16; - else if (cur_width <= 32) - line_per_chunk = CURSOR_LINE_PER_CHUNK_16; - else if (cur_width <= 64) - line_per_chunk = CURSOR_LINE_PER_CHUNK_8; - else if (cur_width <= 128) - line_per_chunk = CURSOR_LINE_PER_CHUNK_4; - else - line_per_chunk = CURSOR_LINE_PER_CHUNK_2; - - return line_per_chunk; -} - -static void ippn10_cursor_set_attributes( - struct input_pixel_processor *ipp, - const struct dc_cursor_attributes *attr) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); - enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( - attr->width, attr->color_format); - - ippn10->curs_attr = *attr; - - REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, - CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); - REG_UPDATE(CURSOR_SURFACE_ADDRESS, - CURSOR_SURFACE_ADDRESS, attr->address.low_part); - - REG_UPDATE_2(CURSOR_SIZE, - CURSOR_WIDTH, attr->width, - CURSOR_HEIGHT, attr->height); - REG_UPDATE_3(CURSOR_CONTROL, - CURSOR_MODE, attr->color_format, - CURSOR_PITCH, hw_pitch, - CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(ippn10, - attr->attribute_flags.bits.INVERT_PIXEL_DATA, - attr->color_format); -} - -static void ippn10_cursor_set_position( - struct input_pixel_processor *ipp, - const struct dc_cursor_position *pos, - const struct dc_cursor_mi_param *param) -{ - struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp); - int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; - uint32_t cur_en = pos->enable ? 1 : 0; - uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; - - /* - * Guard aganst cursor_set_position() from being called with invalid - * attributes - * - * TODO: Look at combining cursor_set_position() and - * cursor_set_attributes() into cursor_update() - */ - if (ippn10->curs_attr.address.quad_part == 0) - return; - - dst_x_offset *= param->ref_clk_khz; - dst_x_offset /= param->pixel_clk_khz; - - ASSERT(param->h_scale_ratio.value); - - if (param->h_scale_ratio.value) - dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( - dal_fixed31_32_from_int(dst_x_offset), - param->h_scale_ratio)); - - if (src_x_offset >= (int)param->viewport_width) - cur_en = 0; /* not visible beyond right edge*/ - - if (src_x_offset + (int)ippn10->curs_attr.width < 0) - cur_en = 0; /* not visible beyond left edge*/ - - if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr); - REG_UPDATE(CURSOR_CONTROL, - CURSOR_ENABLE, cur_en); - REG_UPDATE(CURSOR0_CONTROL, - CUR0_ENABLE, cur_en); - - REG_SET_2(CURSOR_POSITION, 0, - CURSOR_X_POSITION, pos->x, - CURSOR_Y_POSITION, pos->y); - - REG_SET_2(CURSOR_HOT_SPOT, 0, - CURSOR_HOT_SPOT_X, pos->x_hotspot, - CURSOR_HOT_SPOT_Y, pos->y_hotspot); - - REG_SET(CURSOR_DST_OFFSET, 0, - CURSOR_DST_X_OFFSET, dst_x_offset); - /* TODO Handle surface pixel formats other than 4:4:4 */ -} - /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -230,13 +48,6 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) } static const struct ipp_funcs dcn10_ipp_funcs = { - .ipp_cursor_set_attributes = ippn10_cursor_set_attributes, - .ipp_cursor_set_position = ippn10_cursor_set_position, - .ipp_set_degamma = NULL, - .ipp_program_input_lut = NULL, - .ipp_full_bypass = NULL, - .ipp_setup = NULL, - .ipp_program_degamma_pwl = NULL, .ipp_destroy = dcn10_ipp_destroy }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index a28495d95a15..efa1aca187ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -766,6 +766,167 @@ void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, QoS_LEVEL_HIGH_WM, &s->qos_level_high_wm); } +enum cursor_pitch { + CURSOR_PITCH_64_PIXELS = 0, + CURSOR_PITCH_128_PIXELS, + CURSOR_PITCH_256_PIXELS +}; + +enum cursor_lines_per_chunk { + CURSOR_LINE_PER_CHUNK_2 = 1, + CURSOR_LINE_PER_CHUNK_4, + CURSOR_LINE_PER_CHUNK_8, + CURSOR_LINE_PER_CHUNK_16 +}; + +static bool ippn10_cursor_program_control( + struct dcn10_mem_input *mi, + bool pixel_data_invert, + enum dc_cursor_color_format color_format) +{ + if (REG(CURSOR_SETTINS)) + REG_SET_2(CURSOR_SETTINS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + else + REG_SET_2(CURSOR_SETTINGS, 0, + /* no shift of the cursor HDL schedule */ + CURSOR0_DST_Y_OFFSET, 0, + /* used to shift the cursor chunk request deadline */ + CURSOR0_CHUNK_HDL_ADJUST, 3); + + return true; +} + +static enum cursor_pitch ippn10_get_cursor_pitch( + unsigned int pitch) +{ + enum cursor_pitch hw_pitch; + + switch (pitch) { + case 64: + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + case 128: + hw_pitch = CURSOR_PITCH_128_PIXELS; + break; + case 256: + hw_pitch = CURSOR_PITCH_256_PIXELS; + break; + default: + DC_ERR("Invalid cursor pitch of %d. " + "Only 64/128/256 is supported on DCN.\n", pitch); + hw_pitch = CURSOR_PITCH_64_PIXELS; + break; + } + return hw_pitch; +} + +static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( + unsigned int cur_width, + enum dc_cursor_color_format format) +{ + enum cursor_lines_per_chunk line_per_chunk; + + if (format == CURSOR_MODE_MONO) + /* impl B. expansion in CUR Buffer reader */ + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 32) + line_per_chunk = CURSOR_LINE_PER_CHUNK_16; + else if (cur_width <= 64) + line_per_chunk = CURSOR_LINE_PER_CHUNK_8; + else if (cur_width <= 128) + line_per_chunk = CURSOR_LINE_PER_CHUNK_4; + else + line_per_chunk = CURSOR_LINE_PER_CHUNK_2; + + return line_per_chunk; +} + +static void ippn10_cursor_set_attributes( + struct mem_input *mem_input, + const struct dc_cursor_attributes *attr) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); + enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( + attr->width, attr->color_format); + + mem_input->curs_attr = *attr; + + REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, + CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); + REG_UPDATE(CURSOR_SURFACE_ADDRESS, + CURSOR_SURFACE_ADDRESS, attr->address.low_part); + + REG_UPDATE_2(CURSOR_SIZE, + CURSOR_WIDTH, attr->width, + CURSOR_HEIGHT, attr->height); + REG_UPDATE_3(CURSOR_CONTROL, + CURSOR_MODE, attr->color_format, + CURSOR_PITCH, hw_pitch, + CURSOR_LINES_PER_CHUNK, lpc); + ippn10_cursor_program_control(mi, + attr->attribute_flags.bits.INVERT_PIXEL_DATA, + attr->color_format); +} + +static void ippn10_cursor_set_position( + struct mem_input *mem_input, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param) +{ + struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; + uint32_t cur_en = pos->enable ? 1 : 0; + uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; + + /* + * Guard aganst cursor_set_position() from being called with invalid + * attributes + * + * TODO: Look at combining cursor_set_position() and + * cursor_set_attributes() into cursor_update() + */ + if (mem_input->curs_attr.address.quad_part == 0) + return; + + dst_x_offset *= param->ref_clk_khz; + dst_x_offset /= param->pixel_clk_khz; + + ASSERT(param->h_scale_ratio.value); + + if (param->h_scale_ratio.value) + dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div( + dal_fixed31_32_from_int(dst_x_offset), + param->h_scale_ratio)); + + if (src_x_offset >= (int)param->viewport_width) + cur_en = 0; /* not visible beyond right edge*/ + + if (src_x_offset + (int)mem_input->curs_attr.width < 0) + cur_en = 0; /* not visible beyond left edge*/ + + if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) + ippn10_cursor_set_attributes(mem_input, &mem_input->curs_attr); + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, cur_en); + + REG_SET_2(CURSOR_POSITION, 0, + CURSOR_X_POSITION, pos->x, + CURSOR_Y_POSITION, pos->y); + + REG_SET_2(CURSOR_HOT_SPOT, 0, + CURSOR_HOT_SPOT_X, pos->x_hotspot, + CURSOR_HOT_SPOT_Y, pos->y_hotspot); + + REG_SET(CURSOR_DST_OFFSET, 0, + CURSOR_DST_X_OFFSET, dst_x_offset); + /* TODO Handle surface pixel formats other than 4:4:4 */ +} + static struct mem_input_funcs dcn10_mem_input_funcs = { .mem_input_program_display_marks = min10_program_display_marks, .mem_input_program_surface_flip_and_addr = @@ -780,6 +941,8 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { .dcc_control = min10_dcc_control, .mem_program_viewport = min_set_viewport, .set_hubp_blank_en = min10_set_hubp_blank_en, + .set_cursor_attributes = ippn10_cursor_set_attributes, + .set_cursor_position = ippn10_cursor_set_position, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 0b7d4faff82f..2c79d7aa3f91 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -30,7 +30,6 @@ #define TO_DCN10_MEM_INPUT(mi)\ container_of(mi, struct dcn10_mem_input, base) - #define MI_REG_LIST_DCN(id)\ SRI(DCHUBP_CNTL, HUBP, id),\ SRI(HUBPREQ_DEBUG_DB, HUBP, id),\ @@ -118,7 +117,15 @@ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, HUBPREQ, id),\ SRI(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, HUBPREQ, id),\ SR(DCHUBBUB_SDPIF_FB_BASE),\ - SR(DCHUBBUB_SDPIF_FB_OFFSET) + SR(DCHUBBUB_SDPIF_FB_OFFSET),\ + SRI(CURSOR_SETTINS, HUBPREQ, id), \ + SRI(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR, id), \ + SRI(CURSOR_SURFACE_ADDRESS, CURSOR, id), \ + SRI(CURSOR_SIZE, CURSOR, id), \ + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CURSOR_POSITION, CURSOR, id), \ + SRI(CURSOR_HOT_SPOT, CURSOR, id), \ + SRI(CURSOR_DST_OFFSET, CURSOR, id) @@ -217,6 +224,15 @@ struct dcn_mi_registers { uint32_t DCN_VM_AGP_BASE; uint32_t DCN_VM_AGP_BOT; uint32_t DCN_VM_AGP_TOP; + uint32_t CURSOR_SETTINS; + uint32_t CURSOR_SETTINGS; + uint32_t CURSOR_SURFACE_ADDRESS_HIGH; + uint32_t CURSOR_SURFACE_ADDRESS; + uint32_t CURSOR_SIZE; + uint32_t CURSOR_CONTROL; + uint32_t CURSOR_POSITION; + uint32_t CURSOR_HOT_SPOT; + uint32_t CURSOR_DST_OFFSET; }; #define MI_SF(reg_name, field_name, post_fix)\ @@ -362,7 +378,23 @@ struct dcn_mi_registers { MI_SF(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mask_sh),\ - MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh) + MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mask_sh),\ + MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + MI_SF(HUBPREQ0_CURSOR_SETTINS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + MI_SF(CURSOR0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ + MI_SF(CURSOR0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + MI_SF(CURSOR0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + MI_SF(CURSOR0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh) #define DCN_MI_REG_FIELD_LIST(type) \ type HUBP_BLANK_EN;\ @@ -523,7 +555,24 @@ struct dcn_mi_registers { type PHYSICAL_PAGE_ADDR_LO32;\ type PHYSICAL_PAGE_NUMBER_MSB;\ type PHYSICAL_PAGE_NUMBER_LSB;\ - type LOGICAL_ADDR + type LOGICAL_ADDR;\ + type CURSOR0_DST_Y_OFFSET; \ + type CURSOR0_CHUNK_HDL_ADJUST; \ + type CURSOR_SURFACE_ADDRESS_HIGH; \ + type CURSOR_SURFACE_ADDRESS; \ + type CURSOR_WIDTH; \ + type CURSOR_HEIGHT; \ + type CURSOR_MODE; \ + type CURSOR_2X_MAGNIFY; \ + type CURSOR_PITCH; \ + type CURSOR_LINES_PER_CHUNK; \ + type CURSOR_ENABLE; \ + type CURSOR_X_POSITION; \ + type CURSOR_Y_POSITION; \ + type CURSOR_HOT_SPOT_X; \ + type CURSOR_HOT_SPOT_Y; \ + type CURSOR_DST_X_OFFSET; \ + type OUTPUT_FP struct dcn_mi_shift { DCN_MI_REG_FIELD_LIST(uint8_t); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 6cef9ad0af91..5c8e45ba8f45 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -72,6 +72,7 @@ struct mem_input { int opp_id; int mpcc_id; struct stutter_modes stutter_mode; + struct dc_cursor_attributes curs_attr; }; struct vm_system_aperture_param { @@ -163,6 +164,15 @@ struct mem_input_funcs { void (*set_blank)(struct mem_input *mi, bool blank); void (*set_hubp_blank_en)(struct mem_input *mi, bool blank); + void (*set_cursor_attributes)( + struct mem_input *mem_input, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct mem_input *mem_input, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 785d39706832..f95621dfd4d4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -238,6 +238,17 @@ struct transform_funcs { void (*ipp_full_bypass)(struct transform *xfm_base); + void (*set_cursor_attributes)( + struct transform *xfm_base, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct transform *xfm_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width + ); + }; const uint16_t *get_filter_2tap_16p(void); -- GitLab From 8740196935625dfb171ab115120315060e4a8a41 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Mon, 25 Sep 2017 18:03:14 -0400 Subject: [PATCH 1289/2898] drm/amd/display: Move power control from link encoder to hwsequencer A recent commit moved the backlight control code along with the register defines, but did not move the power control code. This along with remnant fields in the dce110_link_enc_registers struct made it so that the code still compiled, but any attempts to access the LVTMA_PWRSEQ_STATE register led to reading from an address of 0. This patch corrects that. Also, rename blacklight_control to edp_backlight_control (Typo fix). Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 17 +- .../drm/amd/display/dc/core/dc_link_hwss.c | 8 +- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 18 +- .../drm/amd/display/dc/dce/dce_link_encoder.c | 171 +----------------- .../drm/amd/display/dc/dce/dce_link_encoder.h | 8 - .../display/dc/dce110/dce110_hw_sequencer.c | 155 +++++++++++++++- .../display/dc/dce110/dce110_hw_sequencer.h | 6 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 +- .../drm/amd/display/dc/inc/hw/link_encoder.h | 2 - .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 7 +- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 4 + .../display/dc/virtual/virtual_link_encoder.c | 5 - 12 files changed, 190 insertions(+), 214 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a58e61b6e9f9..feb10be0ce4c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -78,14 +78,15 @@ static void destruct(struct dc_link *link) dc_sink_release(link->remote_sinks[i]); } -static struct gpio *get_hpd_gpio(const struct dc_link *link) +struct gpio *get_hpd_gpio(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service) { enum bp_result bp_result; - struct dc_bios *dcb = link->ctx->dc_bios; struct graphics_object_hpd_info hpd_info; struct gpio_pin_info pin_info; - if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK) + if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK) return NULL; bp_result = dcb->funcs->get_gpio_pin_info(dcb, @@ -97,7 +98,7 @@ static struct gpio *get_hpd_gpio(const struct dc_link *link) } return dal_gpio_service_create_irq( - link->ctx->gpio_service, + gpio_service, pin_info.offset, pin_info.mask); } @@ -153,7 +154,7 @@ static bool program_hpd_filter( } /* Obtain HPD handle */ - hpd = get_hpd_gpio(link); + hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (!hpd) return result; @@ -186,7 +187,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type) struct gpio *hpd_pin; /* todo: may need to lock gpio access */ - hpd_pin = get_hpd_gpio(link); + hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd_pin == NULL) goto hpd_gpio_failure; @@ -795,7 +796,7 @@ static enum hpd_source_id get_hpd_line( struct gpio *hpd; enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN; - hpd = get_hpd_gpio(link); + hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd) { switch (dal_irq_get_source(hpd)) { @@ -965,7 +966,7 @@ static bool construct( goto create_fail; } - hpd_gpio = get_hpd_gpio(link); + hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); if (hpd_gpio != NULL) link->irq_source_hpd = dal_irq_get_source(hpd_gpio); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index fa2250554be5..34b6d1cb151e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -89,12 +89,12 @@ void dp_enable_link_phy( if (dc_is_dp_sst_signal(signal)) { if (signal == SIGNAL_TYPE_EDP) { - link_enc->funcs->power_control(link_enc, true); + link->dc->hwss.edp_power_control(link->link_enc, true); link_enc->funcs->enable_dp_output( link_enc, link_settings, clock_source); - link->dc->hwss.backlight_control(link, true); + link->dc->hwss.edp_backlight_control(link, true); } else link_enc->funcs->enable_dp_output( link_enc, @@ -138,10 +138,10 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.backlight_control(link, false); + link->dc->hwss.edp_backlight_control(link, false); edp_receiver_ready_T9(link); link->link_enc->funcs->disable_output(link->link_enc, signal, link); - link->link_enc->funcs->power_control(link->link_enc, false); + link->dc->hwss.edp_power_control(link->link_enc, false); } else link->link_enc->funcs->disable_output(link->link_enc, signal, link); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 227c9b655b65..0a058e0c3fec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -391,23 +391,27 @@ struct dce_hwseq_registers { HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_), \ - HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) #define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ @@ -416,7 +420,8 @@ struct dce_hwseq_registers { SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh), \ - HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ @@ -424,7 +429,8 @@ struct dce_hwseq_registers { HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh), \ - HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ @@ -489,7 +495,8 @@ struct dce_hwseq_registers { HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh) + HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ + HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ @@ -520,7 +527,8 @@ struct dce_hwseq_registers { type LOGICAL_ADDR; \ type ENABLE_L1_TLB;\ type SYSTEM_ACCESS_MODE;\ - type LVTMA_BLON; + type LVTMA_BLON;\ + type LVTMA_PWRSEQ_TARGET_STATE_R; #define HWSEQ_DCN_REG_FIELD_LIST(type) \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 1cb727bdaa56..0cf0fff74d44 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -82,13 +82,6 @@ #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 -/* all values are in milliseconds */ -/* For eDP, after power-up/power/down, - * 300/500 msec max. delay from LCDVCC to black video generation */ -#define PANEL_POWER_UP_TIMEOUT 300 -#define PANEL_POWER_DOWN_TIMEOUT 500 -#define HPD_CHECK_INTERVAL 10 - /* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ #define TMDS_MIN_PIXEL_CLOCK 25000 /* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ @@ -122,7 +115,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .psr_program_dp_dphy_fast_training = dce110_psr_program_dp_dphy_fast_training, .psr_program_secondary_packet = dce110_psr_program_secondary_packet, - .power_control = dce110_link_encoder_edp_power_control, .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, .enable_hpd = dce110_link_encoder_enable_hpd, .disable_hpd = dce110_link_encoder_disable_hpd, @@ -492,165 +484,6 @@ static void configure_encoder( REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); } -static bool is_panel_powered_on(struct dce110_link_encoder *enc110) -{ - bool ret; - uint32_t value; - - REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); - ret = value; - - return ret == 1; -} - - -/* TODO duplicate of dc_link.c version */ -static struct gpio *get_hpd_gpio(const struct link_encoder *enc) -{ - enum bp_result bp_result; - struct dc_bios *dcb = enc->ctx->dc_bios; - struct graphics_object_hpd_info hpd_info; - struct gpio_pin_info pin_info; - - if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK) - return NULL; - - bp_result = dcb->funcs->get_gpio_pin_info(dcb, - hpd_info.hpd_int_gpio_uid, &pin_info); - - if (bp_result != BP_RESULT_OK) { - ASSERT(bp_result == BP_RESULT_NORECORD); - return NULL; - } - - return dal_gpio_service_create_irq( - enc->ctx->gpio_service, - pin_info.offset, - pin_info.mask); -} - -/* - * @brief - * eDP only. - */ -static void link_encoder_edp_wait_for_hpd_ready( - struct dce110_link_encoder *enc110, - bool power_up) -{ - struct dc_context *ctx = enc110->base.ctx; - struct graphics_object_id connector = enc110->base.connector; - struct gpio *hpd; - bool edp_hpd_high = false; - uint32_t time_elapsed = 0; - uint32_t timeout = power_up ? - PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; - - if (dal_graphics_object_id_get_connector_id(connector) != - CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if (!power_up) - /* from KV, we will not HPD low after turning off VCC - - * instead, we will check the SW timer in power_up(). */ - return; - - /* when we power on/off the eDP panel, - * we need to wait until SENSE bit is high/low */ - - /* obtain HPD */ - /* TODO what to do with this? */ - hpd = get_hpd_gpio(&enc110->base); - - if (!hpd) { - BREAK_TO_DEBUGGER(); - return; - } - - dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); - - /* wait until timeout or panel detected */ - - do { - uint32_t detected = 0; - - dal_gpio_get_value(hpd, &detected); - - if (!(detected ^ power_up)) { - edp_hpd_high = true; - break; - } - - msleep(HPD_CHECK_INTERVAL); - - time_elapsed += HPD_CHECK_INTERVAL; - } while (time_elapsed < timeout); - - dal_gpio_close(hpd); - - dal_gpio_destroy_irq(&hpd); - - if (false == edp_hpd_high) { - dm_logger_write(ctx->logger, LOG_ERROR, - "%s: wait timed out!\n", __func__); - } -} - -/* - * @brief - * eDP only. Control the power of the eDP panel. - */ -void dce110_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up) -{ - struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); - struct dc_context *ctx = enc110->base.ctx; - struct bp_transmitter_control cntl = { 0 }; - enum bp_result bp_result; - - if (dal_graphics_object_id_get_connector_id(enc110->base.connector) != - CONNECTOR_ID_EDP) { - BREAK_TO_DEBUGGER(); - return; - } - - if ((power_up && !is_panel_powered_on(enc110)) || - (!power_up && is_panel_powered_on(enc110))) { - - /* Send VBIOS command to prompt eDP panel power */ - - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: Panel Power action: %s\n", - __func__, (power_up ? "On":"Off")); - - cntl.action = power_up ? - TRANSMITTER_CONTROL_POWER_ON : - TRANSMITTER_CONTROL_POWER_OFF; - cntl.transmitter = enc110->base.transmitter; - cntl.connector_obj_id = enc110->base.connector; - cntl.coherent = false; - cntl.lanes_number = LANE_COUNT_FOUR; - cntl.hpd_sel = enc110->base.hpd_source; - - bp_result = link_transmitter_control(enc110, &cntl); - - if (BP_RESULT_OK != bp_result) { - - dm_logger_write(ctx->logger, LOG_ERROR, - "%s: Panel Power bp_result: %d\n", - __func__, bp_result); - } - } else { - dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, - "%s: Skipping Panel Power action: %s\n", - __func__, (power_up ? "On":"Off")); - } - - link_encoder_edp_wait_for_hpd_ready(enc110, true); -} - static void aux_initialize( struct dce110_link_encoder *enc110) { @@ -1018,7 +851,7 @@ void dce110_link_encoder_hw_init( ASSERT(result == BP_RESULT_OK); } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) { - enc->funcs->power_control(&enc110->base, true); + ctx->dc->hwss.edp_power_control(enc, true); } aux_initialize(enc110); @@ -1218,7 +1051,7 @@ void dce110_link_encoder_disable_output( return; } if (enc110->base.connector.id == CONNECTOR_ID_EDP) - ctx->dc->hwss.backlight_control(link, false); + ctx->dc->hwss.edp_backlight_control(link, false); /* Power-down RX and disable GPU PHY should be paired. * Disabling PHY without powering down RX may cause * symbol lock loss, on which we will get DP Sink interrupt. */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index c65def5f6a44..494067dedd03 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -114,10 +114,6 @@ struct dce110_link_enc_hpd_registers { }; struct dce110_link_enc_registers { - /* Backlight registers */ - uint32_t LVTMA_PWRSEQ_CNTL; - uint32_t LVTMA_PWRSEQ_STATE; - /* DMCU registers */ uint32_t MASTER_COMM_DATA_REG1; uint32_t MASTER_COMM_DATA_REG2; @@ -250,10 +246,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table); -void dce110_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up); - void dce110_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f28fce6e6ba4..a891e387ed7b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -32,6 +32,7 @@ #include "dce110_hw_sequencer.h" #include "dce110_timing_generator.h" #include "dce/dce_hwseq.h" +#include "gpio_service_interface.h" #ifdef ENABLE_FBC #include "dce110_compressor.h" @@ -45,10 +46,10 @@ #include "transform.h" #include "stream_encoder.h" #include "link_encoder.h" +#include "link_hwss.h" #include "clock_source.h" #include "abm.h" #include "audio.h" -#include "dce/dce_hwseq.h" #include "reg_helper.h" /* include DCE11 register header files */ @@ -56,6 +57,15 @@ #include "dce/dce_11_0_sh_mask.h" #include "custom_float.h" +/* + * All values are in milliseconds; + * For eDP, after power-up/power/down, + * 300/500 msec max. delay from LCDVCC to black video generation + */ +#define PANEL_POWER_UP_TIMEOUT 300 +#define PANEL_POWER_DOWN_TIMEOUT 500 +#define HPD_CHECK_INTERVAL 10 + #define CTX \ hws->ctx #define REG(reg)\ @@ -780,25 +790,150 @@ static bool is_panel_backlight_on(struct dce_hwseq *hws) return value; } +static bool is_panel_powered_on(struct dce_hwseq *hws) +{ + uint32_t value; + + REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value); + return value == 1; +} + static enum bp_result link_transmitter_control( - struct dc_link *link, + struct dc_bios *bios, struct bp_transmitter_control *cntl) { enum bp_result result; - struct dc_bios *bp = link->dc->ctx->dc_bios; - result = bp->funcs->transmitter_control(bp, cntl); + result = bios->funcs->transmitter_control(bios, cntl); return result; } +/* + * @brief + * eDP only. + */ +void hwss_edp_wait_for_hpd_ready( + struct link_encoder *enc, + bool power_up) +{ + struct dc_context *ctx = enc->ctx; + struct graphics_object_id connector = enc->connector; + struct gpio *hpd; + bool edp_hpd_high = false; + uint32_t time_elapsed = 0; + uint32_t timeout = power_up ? + PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT; + + if (dal_graphics_object_id_get_connector_id(connector) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (!power_up) + /* + * From KV, we will not HPD low after turning off VCC - + * instead, we will check the SW timer in power_up(). + */ + return; + + /* + * When we power on/off the eDP panel, + * we need to wait until SENSE bit is high/low. + */ + + /* obtain HPD */ + /* TODO what to do with this? */ + hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); + + if (!hpd) { + BREAK_TO_DEBUGGER(); + return; + } + + dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); + + /* wait until timeout or panel detected */ + + do { + uint32_t detected = 0; + + dal_gpio_get_value(hpd, &detected); + + if (!(detected ^ power_up)) { + edp_hpd_high = true; + break; + } + + msleep(HPD_CHECK_INTERVAL); + + time_elapsed += HPD_CHECK_INTERVAL; + } while (time_elapsed < timeout); + + dal_gpio_close(hpd); + + dal_gpio_destroy_irq(&hpd); + + if (false == edp_hpd_high) { + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: wait timed out!\n", __func__); + } +} + +void hwss_edp_power_control( + struct link_encoder *enc, + bool power_up) +{ + struct dc_context *ctx = enc->ctx; + struct dce_hwseq *hwseq = ctx->dc->hwseq; + struct bp_transmitter_control cntl = { 0 }; + enum bp_result bp_result; + + + if (dal_graphics_object_id_get_connector_id(enc->connector) + != CONNECTOR_ID_EDP) { + BREAK_TO_DEBUGGER(); + return; + } + + if (power_up != is_panel_powered_on(hwseq)) { + /* Send VBIOS command to prompt eDP panel power */ + + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + + cntl.action = power_up ? + TRANSMITTER_CONTROL_POWER_ON : + TRANSMITTER_CONTROL_POWER_OFF; + cntl.transmitter = enc->transmitter; + cntl.connector_obj_id = enc->connector; + cntl.coherent = false; + cntl.lanes_number = LANE_COUNT_FOUR; + cntl.hpd_sel = enc->hpd_source; + + bp_result = link_transmitter_control(ctx->dc_bios, &cntl); + + if (bp_result != BP_RESULT_OK) + dm_logger_write(ctx->logger, LOG_ERROR, + "%s: Panel Power bp_result: %d\n", + __func__, bp_result); + } else { + dm_logger_write(ctx->logger, LOG_HW_RESUME_S3, + "%s: Skipping Panel Power action: %s\n", + __func__, (power_up ? "On":"Off")); + } + + hwss_edp_wait_for_hpd_ready(enc, true); +} /*todo: cloned in stream enc, fix*/ /* * @brief * eDP only. Control the backlight of the eDP panel */ -void hwss_blacklight_control( +void hwss_edp_backlight_control( struct dc_link *link, bool enable) { @@ -828,6 +963,7 @@ void hwss_blacklight_control( cntl.action = enable ? TRANSMITTER_CONTROL_BACKLIGHT_ON : TRANSMITTER_CONTROL_BACKLIGHT_OFF; + /*cntl.engine_id = ctx->engine;*/ cntl.transmitter = link->link_enc->transmitter; cntl.connector_obj_id = link->link_enc->connector; @@ -846,7 +982,7 @@ void hwss_blacklight_control( * Enable it in the future if necessary. */ /* dc_service_sleep_in_milliseconds(50); */ - link_transmitter_control(link, &cntl); + link_transmitter_control(link->dc->ctx->dc_bios, &cntl); } void dce110_disable_stream(struct pipe_ctx *pipe_ctx) @@ -886,7 +1022,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) /* blank at encoder level */ if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) - hwss_blacklight_control(link, false); + hwss_edp_backlight_control(link, false); pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); } link->link_enc->funcs->connect_dig_be_to_fe( @@ -908,7 +1044,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); if (link->connector_signal == SIGNAL_TYPE_EDP) - hwss_blacklight_control(link, true); + hwss_edp_backlight_control(link, true); } @@ -2821,7 +2957,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, - .backlight_control = hwss_blacklight_control + .edp_backlight_control = hwss_edp_backlight_control, + .edp_power_control = hwss_edp_power_control, }; void dce110_hw_sequencer_construct(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 3e95f7f92c73..a1e964af60ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -69,7 +69,11 @@ uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); -void hwss_blacklight_control( +void hwss_edp_power_control( + struct link_encoder *enc, + bool power_up); + +void hwss_edp_backlight_control( struct dc_link *link, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 014911ebdbd6..efa3f6f97baf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2903,7 +2903,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, .ready_shared_resources = ready_shared_resources, .optimize_shared_resources = optimize_shared_resources, - .backlight_control = hwss_blacklight_control + .edp_backlight_control = hwss_edp_backlight_control, + .edp_power_control = hwss_edp_power_control }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 6cd6bc7d15fb..3d33bcda7059 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -123,8 +123,6 @@ struct link_encoder_funcs { bool exit_link_training_required); void (*psr_program_secondary_packet)(struct link_encoder *enc, unsigned int sdp_transmit_line_num_deadline); - void (*power_control) (struct link_encoder *enc, - bool power_up); void (*connect_dig_be_to_fe)(struct link_encoder *enc, enum engine_id engine, bool connect); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 210874f37722..bf3ab5d7398e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -28,6 +28,7 @@ #include "dc_types.h" #include "clock_source.h" #include "inc/hw/timing_generator.h" +#include "inc/hw/link_encoder.h" #include "core_status.h" enum pipe_gating_control { @@ -176,8 +177,10 @@ struct hw_sequencer_funcs { void (*ready_shared_resources)(struct dc *dc, struct dc_state *context); void (*optimize_shared_resources)(struct dc *dc); - - void (*backlight_control)( + void (*edp_power_control)( + struct link_encoder *enc, + bool enable); + void (*edp_backlight_control)( struct dc_link *link, bool enable); }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index f7994cfc850d..f2b8c9a376d5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -40,6 +40,10 @@ enum dc_status core_link_write_dpcd( const uint8_t *data, uint32_t size); +struct gpio *get_hpd_gpio(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service); + void dp_enable_link_phy( struct dc_link *link, enum signal_type signal, diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 4f405348130f..88c2bde3f039 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -73,10 +73,6 @@ static void virtual_link_encoder_update_mst_stream_allocation_table( struct link_encoder *enc, const struct link_mst_stream_allocation_table *table) {} -static void virtual_link_encoder_edp_power_control( - struct link_encoder *enc, - bool power_up) {} - static void virtual_link_encoder_connect_dig_be_to_fe( struct link_encoder *enc, enum engine_id engine, @@ -102,7 +98,6 @@ static const struct link_encoder_funcs virtual_lnk_enc_funcs = { .dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern, .update_mst_stream_allocation_table = virtual_link_encoder_update_mst_stream_allocation_table, - .power_control = virtual_link_encoder_edp_power_control, .connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe, .destroy = virtual_link_encoder_destroy }; -- GitLab From 6512387a54357c5d3fbea8995d8879ea817a5ec6 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Wed, 27 Sep 2017 09:20:51 -0400 Subject: [PATCH 1290/2898] drm/amd/display: align DCLK to voltage level in past program SMU will use all voltage headroom. RV does not if DAL need higher voltage for DCFCLK or DISPCLK, also increase FCLK to improve stutter as voltage is already Signed-off-by: Tony Cheng Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + 3 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index cf474eb1cde8..9337ccadc321 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1049,6 +1049,10 @@ bool dcn_validate_bandwidth( else bw_consumed = v->fabric_and_dram_bandwidth_vmax0p9; + if (bw_consumed < v->fabric_and_dram_bandwidth) + if (dc->debug.voltage_align_fclk) + bw_consumed = v->fabric_and_dram_bandwidth; + display_pipe_configuration(v); calc_wm_sets_and_perf_params(context, v); context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cf9cd108539f..dbbe1d621bee 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -188,6 +188,7 @@ struct dc_debug { enum dcc_option disable_dcc; enum pipe_split_policy pipe_split_policy; bool force_single_disp_pipe_split; + bool voltage_align_fclk; bool disable_dfs_bypass; bool disable_dpp_power_gate; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 30c275e05796..4018e831eb4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -428,6 +428,7 @@ static const struct dc_debug debug_defaults_drv = { .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .disable_dcc = DCC_ENABLE, + .voltage_align_fclk = true, }; static const struct dc_debug debug_defaults_diags = { -- GitLab From dcf298c3137ace22b92c584781e6092e4eb273fb Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 25 Sep 2017 14:53:14 -0400 Subject: [PATCH 1291/2898] drm/amd/display: disconnect on HPD low even if edid is the same [Description] There are many occasions we need to retrieve sink capability and notify connectivity change to os even if edid is not changed on a HPD toggle. (HDMI2.0 display needs re-enable link on every hpd, display changes other capability outside from edid need to be queried again and possibly reset the mode, etc.) In these cases we cannot keep the same sink without letting DM know. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index feb10be0ce4c..e414e4770789 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -566,6 +566,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) link->local_sink) return true; + link_disconnect_sink(link); + if (new_connection_type != dc_connection_none) { link->type = new_connection_type; @@ -656,28 +658,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) return false; } - if (link->local_sink) { - edid_status = dm_helpers_read_local_edid( - link->ctx, - link, - sink); + sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; + sink->converter_disable_audio = converter_disable_audio; - if (edid_status == EDID_OK) { - // Edid is not the same, to update the local sink with new sink. - sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; - sink->converter_disable_audio = converter_disable_audio; - link->local_sink = sink; - } - } else { - sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock; - sink->converter_disable_audio = converter_disable_audio; - link->local_sink = sink; + link->local_sink = sink; - edid_status = dm_helpers_read_local_edid( + edid_status = dm_helpers_read_local_edid( link->ctx, link, sink); - } switch (edid_status) { case EDID_BAD_CHECKSUM: @@ -758,28 +747,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Disconnected\n", link->link_index); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); link->mst_stream_alloc_table.stream_count = 0; memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); } - if (link->local_sink) { - sink = link->local_sink; - edid_status = dm_helpers_read_local_edid( - link->ctx, - link, - sink); - if (edid_status != EDID_OK && edid_status != EDID_THE_SAME) { - link_disconnect_sink(link); - link->type = dc_connection_none; - sink_caps.signal = SIGNAL_TYPE_NONE; - } - } else { - link_disconnect_sink(link); - link->type = dc_connection_none; - sink_caps.signal = SIGNAL_TYPE_NONE; - } + link->type = dc_connection_none; + sink_caps.signal = SIGNAL_TYPE_NONE; } LINK_INFO("link=%d, dc_sink_in=%p is now %s\n", -- GitLab From 441ad741739e9092f6af231a539781118e23d6df Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 27 Sep 2017 11:44:43 -0400 Subject: [PATCH 1292/2898] drm/amd/display: Add override for reporting wm ranges For verification of watermark select with SMU team, proper implementation will follow Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 47 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 6 +++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 ++ .../drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + 4 files changed, 57 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 9337ccadc321..6318f9f69c92 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1441,6 +1441,53 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) ranges.writer_wm_sets[3].min_drain_clk_khz = max_fclk_khz; ranges.writer_wm_sets[3].max_drain_clk_khz = max_fclk_khz; + if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) { + ranges.reader_wm_sets[0].wm_inst = WM_A; + ranges.reader_wm_sets[0].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[0].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[0].min_fill_clk_khz = 800000; + ranges.reader_wm_sets[0].max_fill_clk_khz = 800000; + ranges.writer_wm_sets[0].wm_inst = WM_A; + ranges.writer_wm_sets[0].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[0].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[0].min_drain_clk_khz = 800000; + ranges.writer_wm_sets[0].max_drain_clk_khz = 800000; + + ranges.reader_wm_sets[1].wm_inst = WM_B; + ranges.reader_wm_sets[1].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[1].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[1].min_fill_clk_khz = 933000; + ranges.reader_wm_sets[1].max_fill_clk_khz = 933000; + ranges.writer_wm_sets[1].wm_inst = WM_B; + ranges.writer_wm_sets[1].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[1].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[1].min_drain_clk_khz = 933000; + ranges.writer_wm_sets[1].max_drain_clk_khz = 933000; + + + ranges.reader_wm_sets[2].wm_inst = WM_C; + ranges.reader_wm_sets[2].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[2].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[2].min_fill_clk_khz = 1067000; + ranges.reader_wm_sets[2].max_fill_clk_khz = 1067000; + ranges.writer_wm_sets[2].wm_inst = WM_C; + ranges.writer_wm_sets[2].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[2].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[2].min_drain_clk_khz = 1067000; + ranges.writer_wm_sets[2].max_drain_clk_khz = 1067000; + + ranges.reader_wm_sets[3].wm_inst = WM_D; + ranges.reader_wm_sets[3].min_drain_clk_khz = 300000; + ranges.reader_wm_sets[3].max_drain_clk_khz = 654000; + ranges.reader_wm_sets[3].min_fill_clk_khz = 1200000; + ranges.reader_wm_sets[3].max_fill_clk_khz = 1200000; + ranges.writer_wm_sets[3].wm_inst = WM_D; + ranges.writer_wm_sets[3].min_fill_clk_khz = 200000; + ranges.writer_wm_sets[3].max_fill_clk_khz = 757000; + ranges.writer_wm_sets[3].min_drain_clk_khz = 1200000; + ranges.writer_wm_sets[3].max_drain_clk_khz = 1200000; + } + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ pp->set_wm_ranges(&pp->pp_smu, &ranges); } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index dbbe1d621bee..d624554efbc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -173,6 +173,11 @@ enum pipe_split_policy { MPC_SPLIT_AVOID_MULT_DISP = 2, }; +enum wm_report_mode { + WM_REPORT_DEFAULT = 0, + WM_REPORT_OVERRIDE = 1, +}; + struct dc_debug { bool surface_visual_confirm; bool sanity_checks; @@ -194,6 +199,7 @@ struct dc_debug { bool disable_dpp_power_gate; bool disable_hubp_power_gate; bool disable_pplib_wm_range; + enum wm_report_mode pplib_wm_report_mode; bool use_dml_wm; unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index efa3f6f97baf..86cfab33feea 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2451,6 +2451,9 @@ static void optimize_shared_resources(struct dc *dc) /* S0i2 message */ dcn10_pplib_apply_display_requirements(dc, dc->current_state); } + + if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) + dcn_bw_notify_pplib_of_wm_ranges(dc); } static void ready_shared_resources(struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4018e831eb4b..5d618e68a744 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -424,6 +424,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, + .pplib_wm_report_mode = WM_REPORT_DEFAULT, .use_dml_wm = false, .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, -- GitLab From ed23cba20d011e1867dea69a45bda88a088585b6 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 27 Sep 2017 16:08:47 -0400 Subject: [PATCH 1293/2898] drm/amd/display: soc_bound_box -update DML based on HW. Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index 0745366d80bc..d40f6ae9622c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -68,7 +68,6 @@ double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum vo return_bw = dml_min( ((double) box->return_bus_width_bytes) * state.dcfclk_mhz, - state.dram_bw_per_chan_gbps * 1000.0 * (double) box->num_chans - * box->ideal_dram_bw_after_urgent_percent / 100.0); + state.dram_bw_per_chan_gbps * 1000.0 * box->ideal_dram_bw_after_urgent_percent / 100.0); return return_bw; } -- GitLab From c73b046f86d0ceac52bfa0a035796c8c017a2de5 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Wed, 27 Sep 2017 15:34:35 -0400 Subject: [PATCH 1294/2898] drm/amd/display: Expose some mem_input functions for reuse Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 1 - .../amd/display/dc/dcn10/dcn10_mem_input.c | 26 ++++---- .../amd/display/dc/dcn10/dcn10_mem_input.h | 60 +++++++++++++++++++ 3 files changed, 73 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 7fecdb19761d..889f91cf47cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -113,7 +113,6 @@ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ - SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ SRI(CURSOR0_COLOR1, CNVC_CUR, id) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index efa1aca187ad..b61f41c61358 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -38,7 +38,7 @@ #define FN(reg_name, field_name) \ mi->mi_shift->field_name, mi->mi_mask->field_name -static void min10_set_blank(struct mem_input *mem_input, bool blank) +void min10_set_blank(struct mem_input *mem_input, bool blank) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; @@ -87,7 +87,7 @@ static void min10_vready_workaround(struct mem_input *mem_input, REG_WRITE(HUBPREQ_DEBUG_DB, value); } -static void min10_program_tiling( +void min10_program_tiling( struct dcn10_mem_input *mi, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) @@ -107,7 +107,7 @@ static void min10_program_tiling( PIPE_ALIGNED, info->gfx9.pipe_aligned); } -static void min10_program_size_and_rotation( +void min10_program_size_and_rotation( struct dcn10_mem_input *mi, enum dc_rotation_angle rotation, enum surface_pixel_format format, @@ -169,7 +169,7 @@ static void min10_program_size_and_rotation( H_MIRROR_EN, mirror); } -static void min10_program_pixel_format( +void min10_program_pixel_format( struct dcn10_mem_input *mi, enum surface_pixel_format format) { @@ -245,7 +245,7 @@ static void min10_program_pixel_format( /* don't see the need of program the xbar in DCN 1.0 */ } -static bool min10_program_surface_flip_and_addr( +bool min10_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate) @@ -395,7 +395,7 @@ static bool min10_program_surface_flip_and_addr( return true; } -static void min10_dcc_control(struct mem_input *mem_input, bool enable, +void min10_dcc_control(struct mem_input *mem_input, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; @@ -425,7 +425,7 @@ static void min10_program_surface_config( min10_program_pixel_format(mi, format); } -static void min10_program_requestor( +void min10_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs) { @@ -459,7 +459,7 @@ static void min10_program_requestor( } -static void min10_program_deadline( +void min10_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) @@ -595,7 +595,7 @@ static void min10_setup( min10_vready_workaround(mem_input, pipe_dest); } -static void min10_program_display_marks( +void min10_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -607,7 +607,7 @@ static void min10_program_display_marks( */ } -static bool min10_is_flip_pending(struct mem_input *mem_input) +bool min10_is_flip_pending(struct mem_input *mem_input) { uint32_t flip_pending = 0; struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -696,7 +696,7 @@ static void min10_set_vm_context0_settings(struct mem_input *mem_input, SYSTEM_ACCESS_MODE, 3); } -static void min_set_viewport( +void min_set_viewport( struct mem_input *mem_input, const struct rect *viewport, const struct rect *viewport_c) @@ -845,7 +845,7 @@ static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( return line_per_chunk; } -static void ippn10_cursor_set_attributes( +void ippn10_cursor_set_attributes( struct mem_input *mem_input, const struct dc_cursor_attributes *attr) { @@ -873,7 +873,7 @@ static void ippn10_cursor_set_attributes( attr->color_format); } -static void ippn10_cursor_set_position( +void ippn10_cursor_set_position( struct mem_input *mem_input, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 2c79d7aa3f91..fdeb0e87463e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -589,6 +589,65 @@ struct dcn10_mem_input { const struct dcn_mi_mask *mi_mask; }; +void min10_program_deadline( + struct mem_input *mem_input, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr); + +void min10_program_requestor( + struct mem_input *mem_input, + struct _vcs_dpi_display_rq_regs_st *rq_regs); + +void min10_program_pixel_format( + struct dcn10_mem_input *mi, + enum surface_pixel_format format); + +void min10_program_size_and_rotation( + struct dcn10_mem_input *mi, + enum dc_rotation_angle rotation, + enum surface_pixel_format format, + const union plane_size *plane_size, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + +void min10_program_tiling( + struct dcn10_mem_input *mi, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format); + +void min10_dcc_control(struct mem_input *mem_input, + bool enable, + bool independent_64b_blks); + +void min10_program_display_marks( + struct mem_input *mem_input, + struct dce_watermarks nbp, + struct dce_watermarks stutter, + struct dce_watermarks urgent, + uint32_t total_dest_line_time_ns); + +bool min10_program_surface_flip_and_addr( + struct mem_input *mem_input, + const struct dc_plane_address *address, + bool flip_immediate); + +bool min10_is_flip_pending(struct mem_input *mem_input); + +void ippn10_cursor_set_attributes( + struct mem_input *mem_input, + const struct dc_cursor_attributes *attr); + +void ippn10_cursor_set_position( + struct mem_input *mem_input, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + +void min10_set_blank(struct mem_input *mem_input, bool blank); + +void min_set_viewport(struct mem_input *mem_input, + const struct rect *viewport, + const struct rect *viewport_c); + void dcn10_mem_input_construct( struct dcn10_mem_input *mi, struct dc_context *ctx, @@ -597,6 +656,7 @@ void dcn10_mem_input_construct( const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask); + struct dcn_hubp_state { uint32_t pixel_format; uint32_t inuse_addr_hi; -- GitLab From 07e9266593e64f6897996c37dcfb28cb21a612c6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:10:19 -0400 Subject: [PATCH 1295/2898] Revert "amdgpu/dc: inline dml_round_to_multiple" This reverts commit d8c893b44b2199f5935fe8667708253c38353782. Unfortunately these clash with our DML update from the HW guys. Will attempt to reroll them after. Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/dml_common_defs.c | 19 +++++++++++++++++++ .../drm/amd/display/dc/dml/dml_common_defs.h | 2 ++ .../drm/amd/display/dc/dml/dml_inline_defs.h | 19 ------------------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index df2d5099b90e..7c0eb52b91b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -39,4 +39,23 @@ double dml_round(double a) return floor; } +unsigned int dml_round_to_multiple( + unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index 81c53d879a16..a2da3da5ef8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -33,5 +33,7 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); double dml_round(double a); +unsigned int dml_round_to_multiple( + unsigned int num, unsigned int multiple, bool up); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h index a91b4a6c6154..1c6c631daad4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -58,23 +58,4 @@ static inline double dml_log(double x, double base) return (double) dcn_bw_log(x, base); } -static inline unsigned int dml_round_to_multiple(unsigned int num, - unsigned int multiple, - bool up) -{ - unsigned int remainder; - - if (multiple == 0) - return num; - - remainder = num % multiple; - - if (remainder == 0) - return num; - - if (up) - return (num + multiple - remainder); - else - return (num - remainder); -} #endif -- GitLab From 78109d230b797077d58600694ca427b9830eb600 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:10:31 -0400 Subject: [PATCH 1296/2898] Revert "amdgpu/dc: drop dml display_mode_support.c (v2)" This reverts commit 5e0adbff084f33202db36be798c583a115990392. Unfortunately these clash with our DML update from the HW guys. Will attempt to reroll them after. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 4 +- .../amd/display/dc/dml/display_mode_support.c | 2327 +++++++++++++++++ .../amd/display/dc/dml/display_mode_support.h | 5 + 3 files changed, 2335 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index ec712d727665..a6bf36466497 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -10,10 +10,12 @@ CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 + DML = display_mode_lib.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o display_watermark.o \ - soc_bounding_box.o dml_common_defs.o + soc_bounding_box.o dml_common_defs.o display_mode_support.o AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c new file mode 100644 index 000000000000..ac573568c10a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -0,0 +1,2327 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_mode_support.h" +#include "display_mode_lib.h" + +#include "dml_inline_defs.h" +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes) +{ + struct _vcs_dpi_ip_params_st *ip; + struct _vcs_dpi_soc_bounding_box_st *soc; + struct _vcs_dpi_mode_evaluation_st *me; + struct dml_ms_internal_vars *v; + int num_planes, i, j, ij, k, ijk; + + ip = &(mode_lib->ip); + soc = &(mode_lib->soc); + me = &(mode_lib->me); + v = &(mode_lib->vars); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); + + //instantiating variables to zero + v->MacroTileBlockWidthC = 0; + v->SwathWidthGranularityC = 0; + + v->DCFCLKPerState[5] = 0; + v->DCFCLKPerState[4] = 0; + v->DCFCLKPerState[3] = 0; + v->DCFCLKPerState[2] = 0; + v->DCFCLKPerState[1] = 0; + v->DCFCLKPerState[0] = 0; + + if (soc->vmin.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; + } + + if (soc->vmid.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; + } + + if (soc->vnom.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; + } + + if (soc->vmax.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; + } + + v->FabricAndDRAMBandwidthPerState[5] = 0; + v->FabricAndDRAMBandwidthPerState[4] = 0; + v->FabricAndDRAMBandwidthPerState[3] = 0; + v->FabricAndDRAMBandwidthPerState[2] = 0; + v->FabricAndDRAMBandwidthPerState[1] = 0; + v->FabricAndDRAMBandwidthPerState[0] = 0; + + if (soc->vmin.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; + } + + if (soc->vmid.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; + } + + if (soc->vnom.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; + } + + if (soc->vmax.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; + } + + v->PHYCLKPerState[5] = 0; + v->PHYCLKPerState[4] = 0; + v->PHYCLKPerState[3] = 0; + v->PHYCLKPerState[2] = 0; + v->PHYCLKPerState[1] = 0; + v->PHYCLKPerState[0] = 0; + + if (soc->vmin.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; + } + + if (soc->vmid.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; + } + + if (soc->vnom.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; + } + + if (soc->vmax.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; + } + + v->MaxDispclk[5] = 0; + v->MaxDispclk[4] = 0; + v->MaxDispclk[3] = 0; + v->MaxDispclk[2] = 0; + v->MaxDispclk[1] = 0; + v->MaxDispclk[0] = 0; + + if (soc->vmin.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmin.dispclk_mhz; + v->MaxDispclk[4] = soc->vmin.dispclk_mhz; + v->MaxDispclk[3] = soc->vmin.dispclk_mhz; + v->MaxDispclk[2] = soc->vmin.dispclk_mhz; + v->MaxDispclk[1] = soc->vmin.dispclk_mhz; + v->MaxDispclk[0] = soc->vmin.dispclk_mhz; + } + + if (soc->vmid.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmid.dispclk_mhz; + v->MaxDispclk[4] = soc->vmid.dispclk_mhz; + v->MaxDispclk[3] = soc->vmid.dispclk_mhz; + v->MaxDispclk[2] = soc->vmid.dispclk_mhz; + v->MaxDispclk[1] = soc->vmid.dispclk_mhz; + } + + if (soc->vnom.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vnom.dispclk_mhz; + v->MaxDispclk[4] = soc->vnom.dispclk_mhz; + v->MaxDispclk[3] = soc->vnom.dispclk_mhz; + v->MaxDispclk[2] = soc->vnom.dispclk_mhz; + } + + if (soc->vmax.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmax.dispclk_mhz; + v->MaxDispclk[4] = soc->vmax.dispclk_mhz; + v->MaxDispclk[3] = soc->vmax.dispclk_mhz; + } + + v->MaxDppclk[5] = 0; + v->MaxDppclk[4] = 0; + v->MaxDppclk[3] = 0; + v->MaxDppclk[2] = 0; + v->MaxDppclk[1] = 0; + v->MaxDppclk[0] = 0; + + if (soc->vmin.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmin.dppclk_mhz; + v->MaxDppclk[4] = soc->vmin.dppclk_mhz; + v->MaxDppclk[3] = soc->vmin.dppclk_mhz; + v->MaxDppclk[2] = soc->vmin.dppclk_mhz; + v->MaxDppclk[1] = soc->vmin.dppclk_mhz; + v->MaxDppclk[0] = soc->vmin.dppclk_mhz; + } + + if (soc->vmid.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmid.dppclk_mhz; + v->MaxDppclk[4] = soc->vmid.dppclk_mhz; + v->MaxDppclk[3] = soc->vmid.dppclk_mhz; + v->MaxDppclk[2] = soc->vmid.dppclk_mhz; + v->MaxDppclk[1] = soc->vmid.dppclk_mhz; + } + + if (soc->vnom.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vnom.dppclk_mhz; + v->MaxDppclk[4] = soc->vnom.dppclk_mhz; + v->MaxDppclk[3] = soc->vnom.dppclk_mhz; + v->MaxDppclk[2] = soc->vnom.dppclk_mhz; + } + + if (soc->vmax.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmax.dppclk_mhz; + v->MaxDppclk[4] = soc->vmax.dppclk_mhz; + v->MaxDppclk[3] = soc->vmax.dppclk_mhz; + } + + if (me->voltage_override == dm_vmax) { + v->VoltageOverrideLevel = NumberOfStates - 1; + } else if (me->voltage_override == dm_vnom) { + v->VoltageOverrideLevel = NumberOfStates - 2; + } else if (me->voltage_override == dm_vmid) { + v->VoltageOverrideLevel = NumberOfStates - 3; + } else { + v->VoltageOverrideLevel = 0; + } + + // Scale Ratio Support Check + + v->ScaleRatioSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio + || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio + || scale_ratio_depth.hscl_ratio > scale_taps.htaps + || scale_ratio_depth.vscl_ratio > scale_taps.vtaps + || (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16 + && ((scale_ratio_depth.hscl_ratio / 2 + > scale_taps.htaps_c) + || (scale_ratio_depth.vscl_ratio / 2 + > scale_taps.vtaps_c)))) + + { + v->ScaleRatioSupport = 0; + } + } + + // Source Format, Pixel Format and Scan Support Check + + v->SourceFormatPixelAndScanSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) + || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x + || src.sw_mode == dm_sw_var_d + || src.sw_mode == dm_sw_var_d_x) + && (src.source_format != dm_444_64))) { + v->SourceFormatPixelAndScanSupport = 0; + } + } + + // Bandwidth Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_scan == dm_horz) { + v->SwathWidthYSingleDPP[k] = src.viewport_width; + } else { + v->SwathWidthYSingleDPP[k] = src.viewport_height; + } + + if (src.source_format == dm_444_64) { + v->BytePerPixelInDETY[k] = 8; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_32) { + v->BytePerPixelInDETY[k] = 4; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_16) { + v->BytePerPixelInDETY[k] = 2; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_420_8) { + v->BytePerPixelInDETY[k] = 1; + v->BytePerPixelInDETC[k] = 2; + } else { + v->BytePerPixelInDETY[k] = 4.00 / 3.00; + v->BytePerPixelInDETC[k] = 8.00 / 3.00; + } + } + + v->TotalReadBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + + v->ReadBandwidth[k] = + v->SwathWidthYSingleDPP[k] + * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + * scale_ratio_depth.vscl_ratio + + (dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) / 2) + * (scale_ratio_depth.vscl_ratio + / 2)) + / (dest.htotal / dest.pixel_rate_mhz); + + if (src.dcc == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } + + if (ip->pte_enable == 1 && src.source_scan != dm_horz + && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); + } else if (ip->pte_enable == 1 && src.source_scan == dm_horz + && (src.source_format == dm_444_64 || src.source_format == dm_444_32) + && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } else if (ip->pte_enable == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); + } + + v->TotalReadBandwidthConsumedGBytePerSecond = + v->TotalReadBandwidthConsumedGBytePerSecond + + v->ReadBandwidth[k] / 1000; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 4; + } else if (dout.output_type == dm_wb) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 1.5; + } else { + v->WriteBandwidth[k] = 0; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = + v->TotalWriteBandwidthConsumedGBytePerSecond + + v->WriteBandwidth[k] / 1000; + } + + v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond + + v->TotalWriteBandwidthConsumedGBytePerSecond; + + v->DCCEnabledInAnyPlane = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.dcc == 1) { + v->DCCEnabledInAnyPlane = 1; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent / 100); + + v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000); + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) + && (v->TotalBandwidthConsumedGBytePerSecond * 1000 + <= v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent + / 100)) { + v->BandwidthSupport[i] = 1; + } else { + v->BandwidthSupport[i] = 0; + } + } + + // Writeback Latency support check + + v->WritebackLatencySupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444 + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) + > ((ip->writeback_luma_buffer_size_kbytes + + ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } else if (dout.output_type == dm_wb + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) + > (dml_min( + ip->writeback_luma_buffer_size_kbytes, + 2 + * ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } + } + + // Re-ordering Buffer Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = + (soc->round_trip_ping_latency_dcfclk_cycles + 32) + / v->DCFCLKPerState[i] + + soc->urgent_out_of_order_return_per_channel_bytes + * soc->num_chans + / v->ReturnBWPerState[i]; + + if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 + / v->ReturnBWPerState[i] + > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { + v->ROBSupport[i] = 1; + } else { + v->ROBSupport[i] = 0; + } + } + + // Display IO Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_format == dm_420) { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; + } else { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3; + } + + if (dout.output_type == dm_hdmi) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; + } else if (dout.output_type == dm_dp) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; + } else { + v->RequiredPHYCLK[k] = 0; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->DIOSupport[i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + + if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) + || (dout.output_type == dm_hdmi + && v->RequiredPHYCLK[k] > 600)) { + v->DIOSupport[i] = 0; + } + } + } + + // Total Available Writeback Support Check + + v->TotalNumberOfActiveWriteback = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb) { + v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; + } + } + + if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { + v->TotalAvailableWritebackSupport = 1; + } else { + v->TotalAvailableWritebackSupport = 0; + } + + // Maximum DISPCLK/DPPCLK Support check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (scale_ratio_depth.hscl_ratio > 1) { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio + / dml_ceil_ex(scale_taps.htaps / 6, 1)); + } else { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->PSCL_FACTOR_CHROMA[k] = 0; + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + scale_taps.vtaps / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + dml_max( + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k], + 1)); + + } else { + if (scale_ratio_depth.hscl_ratio / 2 > 1) { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio / 2 + / dml_ceil_ex( + scale_taps.htaps_c + / 6, + 1)); + } else { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + dml_max( + scale_taps.vtaps + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k]), + dml_max( + dml_max( + scale_taps.vtaps_c + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio + / 2), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / 4 + / v->PSCL_FACTOR_CHROMA[k]), + 1)); + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + } else if (src.source_format == dm_444_64) { + v->Read256BlockHeightY[k] = 4; + } else { + v->Read256BlockHeightY[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockHeightC[k] = 0; + v->Read256BlockWidthC[k] = 0; + } else { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + v->Read256BlockHeightC[k] = 1; + } else if (src.source_format == dm_420_8) { + v->Read256BlockHeightY[k] = 16; + v->Read256BlockHeightC[k] = 8; + } else { + v->Read256BlockHeightY[k] = 8; + v->Read256BlockHeightC[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->Read256BlockHeightC[k]; + } + + if (src.source_scan == dm_horz) { + v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; + } else { + v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; + } + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear + || (src.source_format == dm_444_64 + && (src.sw_mode == dm_sw_4kb_s + || src.sw_mode + == dm_sw_4kb_s_x + || src.sw_mode + == dm_sw_64kb_s + || src.sw_mode + == dm_sw_64kb_s_t + || src.sw_mode + == dm_sw_64kb_s_x + || src.sw_mode + == dm_sw_var_s + || src.sw_mode + == dm_sw_var_s_x) + && src.source_scan == dm_horz)) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + if (src.sw_mode == dm_sw_linear) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + } + } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } + } + + if (src.sw_mode == dm_sw_linear) { + v->MaximumSwathWidth = 8192; + } else { + v->MaximumSwathWidth = 5120; + } + + v->NumberOfDPPRequiredForDETSize = + dml_ceil_ex( + v->SwathWidthYSingleDPP[k] + / dml_min( + v->MaximumSwathWidth, + ip->det_buffer_size_kbytes + * 1024 + / 2 + / (v->BytePerPixelInDETY[k] + * v->MinSwathHeightY[k] + + v->BytePerPixelInDETC[k] + / 2 + * v->MinSwathHeightC[k])), + 1); + + if (v->BytePerPixelInDETC[k] == 0) { + v->NumberOfDPPRequiredForLBSize = + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1); + } else { + v->NumberOfDPPRequiredForLBSize = + dml_max( + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1), + dml_ceil_ex( + (scale_taps.vtaps_c + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio + / 2, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1)); + } + + v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( + v->NumberOfDPPRequiredForDETSize, + v->NumberOfDPPRequiredForLBSize); + + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->MinDispclkUsingSingleDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i]) + && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + } else if (v->MinDispclkUsingDualDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i])) { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = + 0; + } + + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + + i] + v->NoOfDPP[ijk]; + } + + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + > ip->max_num_dpp) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + if (v->MinDispclkUsingSingleDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + if (v->MinDispclkUsingDualDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j + * NumberOfStatesPlusTwo + i] + + v->NoOfDPP[ijk]; + } + } + } + } + + // Viewport Size Check + + v->ViewportSizeSupport = 1; + + for (k = 0; k < num_planes; k++) { + if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { + v->ViewportSizeSupport = 0; + } + } + + // Total Available Pipes Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + <= ip->max_num_dpp) { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; + } else { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; + } + } + } + + // Urgent Latency Support Check + + for (j = 0; j < 2; j++) { + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + ij = j * NumberOfStatesPlusTwo + i; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] + / v->NoOfDPP[ijk]; + + v->SwathWidthGranularityY = 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MaxSwathHeightY[k]; + v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] - 1, + v->SwathWidthGranularityY) + + v->SwathWidthGranularityY) + * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesY, + 256) + 256; + } + if (v->MaxSwathHeightC[k] > 0) { + v->SwathWidthGranularityC = 256 + / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->MaxSwathHeightC[k]; + } + v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] / 2 - 1, + v->SwathWidthGranularityC) + + v->SwathWidthGranularityC) + * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesC, + 256) + 256; + } + + if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC + <= ip->det_buffer_size_kbytes * 1024 / 2) { + v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; + } else { + v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + + v->LinesInDETChroma = 0; + } else if (v->SwathHeightYPerState[ijk] + <= v->SwathHeightCPerState[ijk]) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETC[k] + / (v->SwathWidthYPerState[ijk] / 2); + } else { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 + / 3 / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 + / v->BytePerPixelInDETY[k] + / (v->SwathWidthYPerState[ijk] / 2); + } + + v->EffectiveLBLatencyHidingSourceLinesLuma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1)), + 1)) + - (scale_taps.vtaps - 1); + + v->EffectiveLBLatencyHidingSourceLinesChroma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1)), + 1)) + - (scale_taps.vtaps_c - 1); + + v->EffectiveDETLBLinesLuma = + dml_floor_ex( + v->LinesInDETLuma + + dml_min( + v->LinesInDETLuma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETY[k] + * v->PSCL_FACTOR[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesLuma), + v->SwathHeightYPerState[ijk]); + + v->EffectiveDETLBLinesChroma = + dml_floor_ex( + v->LinesInDETChroma + + dml_min( + v->LinesInDETChroma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETC[k] + * v->PSCL_FACTOR_CHROMA[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesChroma), + v->SwathHeightCPerState[ijk]); + + if (v->BytePerPixelInDETC[k] == 0) { + v->UrgentLatencySupportUsPerState[ijk] = + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]); + } else { + v->UrgentLatencySupportUsPerState[ijk] = + dml_min( + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]), + v->EffectiveDETLBLinesChroma + * (dest.htotal + / dest.pixel_rate_mhz) + / (scale_ratio_depth.vscl_ratio + / 2) + - v->EffectiveDETLBLinesChroma + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk])); + } + + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->UrgentLatencySupport[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->UrgentLatencySupportUsPerState[ijk] + < soc->urgent_latency_us / 1) { + v->UrgentLatencySupport[ij] = 0; + } + } + } + } + + // Prefetch Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->TotalNumberOfDCCActiveDPP[ij] = 0; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->TotalNumberOfDCCActiveDPP[ij] = + v->TotalNumberOfDCCActiveDPP[ij] + + v->NoOfDPP[ijk]; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = 8; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = dml_max( + v->ProjectedDCFCLKDeepSleep, + dest.pixel_rate_mhz / 16); + if (v->BytePerPixelInDETC[k] == 0) { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } else { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * scale_ratio_depth.hscl_ratio + / 2 + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * v->PSCL_FACTOR_CHROMA[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; + v->MetaReqWidthY = 64 * 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MetaReqHeightY; + v->MetaSurfaceWidthY = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] - 1, + v->MetaReqWidthY) + v->MetaReqWidthY; + v->MetaSurfaceHeightY = dml_ceil_ex( + src.viewport_height - 1, + v->MetaReqHeightY) + v->MetaReqHeightY; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameY = + (dml_ceil_ex( + (v->MetaSurfaceWidthY + * v->MetaSurfaceHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) * 64; + } else { + v->MetaPteBytesPerFrameY = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesY = + v->MetaSurfaceWidthY + * v->MetaReqHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } else { + v->MetaRowBytesY = + v->MetaSurfaceHeightY + * v->MetaReqWidthY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } + } else { + v->MetaPteBytesPerFrameY = 0; + v->MetaRowBytesY = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesY = 256; + v->MacroTileBlockHeightY = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesY = 4096; + v->MacroTileBlockHeightY = 4 + * v->Read256BlockHeightY[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesY = 64 * 1024; + v->MacroTileBlockHeightY = 16 + * v->Read256BlockHeightY[k]; + } else { + v->MacroTileBlockSizeBytesY = 256 * 1024; + v->MacroTileBlockHeightY = 32 + * v->Read256BlockHeightY[k]; + } + if (v->MacroTileBlockSizeBytesY <= 65536) { + v->DataPTEReqHeightY = v->MacroTileBlockHeightY; + } else { + v->DataPTEReqHeightY = 16 + * v->Read256BlockHeightY[k]; + } + v->DataPTEReqWidthY = 4096 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->DataPTEReqHeightY * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthY + / (src.viewport_width + / v->NoOfDPP[ijk]), + 2), + 1))) + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_height + - 1) + / v->DataPTEReqHeightY, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowY = 0; + } + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + if (src.dcc == 1) { + v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; + v->MetaReqWidthC = + 64 * 256 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MetaReqHeightC; + v->MetaSurfaceWidthC = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] + / 2 - 1, + v->MetaReqWidthC) + + v->MetaReqWidthC; + v->MetaSurfaceHeightC = dml_ceil_ex( + src.viewport_height / 2 - 1, + v->MetaReqHeightC) + + v->MetaReqHeightC; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameC = + (dml_ceil_ex( + (v->MetaSurfaceWidthC + * v->MetaSurfaceHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) + * 64; + } else { + v->MetaPteBytesPerFrameC = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesC = + v->MetaSurfaceWidthC + * v->MetaReqHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } else { + v->MetaRowBytesC = + v->MetaSurfaceHeightC + * v->MetaReqWidthC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } + } else { + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesC = 256; + v->MacroTileBlockHeightC = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesC = 4096; + v->MacroTileBlockHeightC = 4 + * v->Read256BlockHeightC[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesC = 64 * 1024; + v->MacroTileBlockHeightC = 16 + * v->Read256BlockHeightC[k]; + } else { + v->MacroTileBlockSizeBytesC = 256 * 1024; + v->MacroTileBlockHeightC = 32 + * v->Read256BlockHeightC[k]; + } + v->MacroTileBlockWidthC = + v->MacroTileBlockSizeBytesC + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MacroTileBlockHeightC; + if (v->MacroTileBlockSizeBytesC <= 65536) { + v->DataPTEReqHeightC = + v->MacroTileBlockHeightC; + } else { + v->DataPTEReqHeightC = 16 + * v->Read256BlockHeightC[k]; + } + v->DataPTEReqWidthC = + 4096 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->DataPTEReqHeightC + * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthC + / (src.viewport_width + / v->NoOfDPP[ijk] + / 2), + 2), + 1))) + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_height + / 2 + - 1) + / v->DataPTEReqHeightC, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowC = 0; + } + } else { + v->DPTEBytesPerRowC = 0; + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; + v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY + + v->MetaPteBytesPerFrameC; + v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; + + v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio) + / 2.0; + v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); + v->MaxNumSwY[k] = dml_ceil_ex( + (v->PrefillY[k] - 1.0) + / v->SwathHeightYPerState[ijk], + 1) + 1.0; + + if (v->PrefillY[k] > 1) { + v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } else { + v->MaxPartialSwY = ((int) (v->PrefillY[k] + + v->SwathHeightYPerState[ijk] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } + v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); + + v->PrefetchLinesY[k] = v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + v->VInitC = + (scale_ratio_depth.vscl_ratio / 2 + + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio + / 2) / 2.0; + v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); + v->MaxNumSwC[k] = + dml_ceil_ex( + (v->PrefillC[k] - 1.0) + / v->SwathHeightCPerState[ijk], + 1) + 1.0; + if (v->PrefillC[k] > 1) { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } else { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] + + v->SwathHeightCPerState[ijk] + - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } + v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); + + v->PrefetchLinesC[k] = v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk] + + v->MaxPartialSwC; + } else { + v->PrefetchLinesC[k] = 0; + } + + v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz + / (v->RequiredDISPCLK[ij] / (j + 1)) + + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; + if (v->NoOfDPP[ijk] > 1) { + v->dst_x_after_scaler = v->dst_x_after_scaler + + dest.recout_width / 2.0; + } + + if (dout.output_format == dm_420) { + v->dst_y_after_scaler = 1; + } else { + v->dst_y_after_scaler = 0; + } + + v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; + + v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); + v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters + * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) + + 3 / v->RequiredDISPCLK[ij]); + v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep + + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) + + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; + v->VReadyOffset = + dml_max( + 150 + / (v->RequiredDISPCLK[ij] + / (j + + 1)), + v->TotalRepeaterDelay + + 20 + / v->ProjectedDCFCLKDeepSleep + + 10 + / (v->RequiredDISPCLK[ij] + / (j + + 1))) + * dest.pixel_rate_mhz; + + v->TimeSetup = + (v->VUpdateOffset + v->VUpdateWidth + + v->VReadyOffset) + / dest.pixel_rate_mhz; + + v->ExtraLatency = + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] + + (v->TotalNumberOfActiveDPP[ij] + * ip->pixel_chunk_size_kbytes + + v->TotalNumberOfDCCActiveDPP[ij] + * ip->meta_chunk_size_kbytes) + * 1024 + / v->ReturnBWPerState[i]; + + if (ip->pte_enable == 1) { + v->ExtraLatency = v->ExtraLatency + + v->TotalNumberOfActiveDPP[ij] + * ip->pte_chunk_size_kbytes + * 1024 + / v->ReturnBWPerState[i]; + } + + if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == 1) { + v->MaximumVStartup = dest.vtotal - dest.vactive - 1; + } else { + v->MaximumVStartup = dest.vsync_plus_back_porch - 1; + } + + v->LineTimesForPrefetch[k] = + v->MaximumVStartup + - soc->urgent_latency_us + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->TimeCalc + v->TimeSetup) + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->dst_y_after_scaler + + v->dst_x_after_scaler + / dest.htotal); + + v->LineTimesForPrefetch[k] = dml_floor_ex( + 4.0 * (v->LineTimesForPrefetch[k] + 0.125), + 1) / 4; + + v->PrefetchBW[k] = + (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] + + 2 * v->DPTEBytesPerRow[k] + + v->PrefetchLinesY[k] + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2)) + / (v->LineTimesForPrefetch[k] + * dest.htotal + / dest.pixel_rate_mhz); + } + + v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; + + for (k = 0; k < num_planes; k++) { + v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip + - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); + } + + v->TotalImmediateFlipBytes = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes + + v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]; + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (ip->pte_enable == 1 && src.dcc == 1) { + v->TimeForMetaPTEWithImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->MetaPTEBytesPerFrame[k] + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + v->ExtraLatency, + dml_max( + soc->urgent_latency_us, + dest.htotal + / dest.pixel_rate_mhz + / 4)))); + + v->TimeForMetaPTEWithoutImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->ExtraLatency, + dest.htotal + / dest.pixel_rate_mhz + / 4)); + } else { + v->TimeForMetaPTEWithImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + } + + if (ip->pte_enable == 1 || src.dcc == 1) { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + dml_max( + v->ExtraLatency, + 2 + * soc->urgent_latency_us)))); + + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency)); + } else { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithImmediateFlip); + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithoutImmediateFlip); + } + + v->LinesForMetaPTEWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaPTEWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; + + v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithoutImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; + + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = 999999; + v->VRatioPreCWithImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + 999999; + } + + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithoutImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithoutImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithoutImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; + v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) + + dml_max( + v->MetaPTEBytesPerFrame[k] + / (v->LinesForMetaPTEWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz), + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz)); + } else { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + } + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + + v->PrefetchSupportedWithImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + + v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (((src.source_format != dm_420_8 + && src.source_format != dm_420_10) + && (v->VRatioPreYWithImmediateFlip[ijk] > 4 + || v->VRatioPreCWithImmediateFlip[ijk] + > 4)) + || ((src.source_format == dm_420_8 + || src.source_format == dm_420_10) + && (v->VRatioPreYWithoutImmediateFlip[ijk] + > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] + > 4))) { + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + // Mode Support, Voltage State and SOC Configuration + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 + && v->ViewportSizeSupport == 1 + && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 + && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 + && v->DISPCLK_DPPCLK_Support[ij] == 1 + && v->TotalAvailablePipesSupport[ij] == 1 + && v->TotalAvailableWritebackSupport == 1 + && v->WritebackLatencySupport == 1) { + if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] + == 1) { + v->ModeSupportWithImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + } + if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] + == 1) { + v->ModeSupportWithoutImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithImmediateFlip = i; + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithoutImmediateFlip = i; + } + } + + if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { + v->ImmediateFlipSupported = 0; + v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; + } else { + v->ImmediateFlipSupported = 1; + v->VoltageLevel = v->VoltageLevelWithImmediateFlip; + } + + v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; + v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; + + for (j = 0; j < 2; j++) { + v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + (int) v->VoltageLevel]; + for (k = 0; k < num_planes; k++) { + v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + + ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); + + return (v->VoltageLevel); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h index d4ea0371cde2..ead4942f998c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h @@ -191,4 +191,9 @@ struct dml_ms_internal_vars { struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; }; +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes); + #endif -- GitLab From e168df36a807dff8e5cc78c1daeb9dec89e4118c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:10:54 -0400 Subject: [PATCH 1297/2898] Revert "amdgpu/dc: drop dml_util_is_420" This reverts commit e5bcf3d83e40cc7acc9d111519b7bacaf4a01070. Unfortunately these clash with our DML update from the HW guys. Will attempt to reroll them after. Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/dml_common_defs.c | 33 +++++++++++++++++++ .../drm/amd/display/dc/dml/dml_common_defs.h | 1 + 2 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 7c0eb52b91b8..c242b8d41b8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -59,3 +59,36 @@ unsigned int dml_round_to_multiple( else return (num - remainder); } + +bool dml_util_is_420(enum source_format_class sorce_format) +{ + bool val = false; + + switch (sorce_format) { + case dm_444_16: + val = false; + break; + case dm_444_32: + val = false; + break; + case dm_444_64: + val = false; + break; + case dm_420_8: + val = true; + break; + case dm_420_10: + val = true; + break; + case dm_422_8: + val = false; + break; + case dm_422_10: + val = false; + break; + default: + BREAK_TO_DEBUGGER(); + } + + return val; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index a2da3da5ef8f..c621f8321b03 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -32,6 +32,7 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); +bool dml_util_is_420(enum source_format_class sorce_format); double dml_round(double a); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -- GitLab From 711b55f3fca418de8c6484a1aa38bcc241acc536 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:11:04 -0400 Subject: [PATCH 1298/2898] Revert "amdgpu/dc: inline a bunch of the dml wrappers." This reverts commit 3e8c3108dab197858e74dbb740c5312ae636ea9b. Unfortunately these clash with our DML update from the HW guys. Will attempt to reroll them after. Signed-off-by: Alex Deucher --- .../amd/display/dc/dml/display_mode_support.c | 1 - .../amd/display/dc/dml/display_rq_dlg_calc.c | 2 - .../amd/display/dc/dml/display_watermark.c | 1 - .../drm/amd/display/dc/dml/dml_common_defs.c | 56 ++++++++++++++++- .../drm/amd/display/dc/dml/dml_common_defs.h | 11 ++++ .../drm/amd/display/dc/dml/dml_inline_defs.h | 61 ------------------- .../drm/amd/display/dc/dml/soc_bounding_box.c | 1 - 7 files changed, 66 insertions(+), 67 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c index ac573568c10a..3b4ee74527f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -26,7 +26,6 @@ #include "display_mode_support.h" #include "display_mode_lib.h" -#include "dml_inline_defs.h" int dml_ms_check( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_e2e_pipe_params_st *e2e, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 7a5fb1cef303..9fccbbffe129 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -25,8 +25,6 @@ #include "display_rq_dlg_calc.h" #include "display_mode_lib.h" -#include "dml_inline_defs.h" - static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c index 142a3284ac44..390f09391433 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c @@ -24,7 +24,6 @@ */ #include "display_watermark.h" #include "display_mode_lib.h" -#include "dml_inline_defs.h" static void get_bytes_per_pixel( enum source_format_class format, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index c242b8d41b8a..21349a022de3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -26,7 +26,26 @@ #include "dml_common_defs.h" #include "../calcs/dcn_calc_math.h" -#include "dml_inline_defs.h" +double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +double dml_ceil(double a) +{ + return (double) dcn_bw_ceil2(a, 1); +} + +double dml_floor(double a) +{ + return (double) dcn_bw_floor2(a, 1); +} + double dml_round(double a) { double round_pt = 0.5; @@ -39,6 +58,16 @@ double dml_round(double a) return floor; } +int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, @@ -60,6 +89,16 @@ unsigned int dml_round_to_multiple( return (num - remainder); } +double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + bool dml_util_is_420(enum source_format_class sorce_format) { bool val = false; @@ -92,3 +131,18 @@ bool dml_util_is_420(enum source_format_class sorce_format) return val; } + +double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index c621f8321b03..c5340d41eedb 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -32,9 +32,20 @@ #define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); +double dml_min(double a, double b); +double dml_max(double a, double b); bool dml_util_is_420(enum source_format_class sorce_format); +double dml_ceil_ex(double x, double granularity); +double dml_floor_ex(double x, double granularity); +double dml_log(double x, double base); +double dml_ceil(double a); +double dml_floor(double a); double dml_round(double a); +int dml_log2(double x); +double dml_pow(double a, int exp); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); +double dml_fmod(double f, int val); +double dml_ceil_2(double f); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h deleted file mode 100644 index 1c6c631daad4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef __DML_INLINE_DEFS_H__ -#define __DML_INLINE_DEFS_H__ -#include "dml_common_defs.h" -#include "../calcs/dcn_calc_math.h" - -static inline double dml_min(double a, double b) -{ - return (double) dcn_bw_min2(a, b); -} - -static inline double dml_max(double a, double b) -{ - return (double) dcn_bw_max2(a, b); -} - -static inline double dml_ceil(double a) -{ - return (double) dcn_bw_ceil2(a, 1); -} - -static inline double dml_floor(double a) -{ - return (double) dcn_bw_floor2(a, 1); -} - -static inline int dml_log2(double x) -{ - return dml_round((double)dcn_bw_log(x, 2)); -} - -static inline double dml_pow(double a, int exp) -{ - return (double) dcn_bw_pow(a, exp); -} - -static inline double dml_fmod(double f, int val) -{ - return (double) dcn_bw_mod(f, val); -} - -static inline double dml_ceil_2(double f) -{ - return (double) dcn_bw_ceil2(f, 2); -} - -static inline double dml_ceil_ex(double x, double granularity) -{ - return (double) dcn_bw_ceil2(x, granularity); -} - -static inline double dml_floor_ex(double x, double granularity) -{ - return (double) dcn_bw_floor2(x, granularity); -} - -static inline double dml_log(double x, double base) -{ - return (double) dcn_bw_log(x, base); -} - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index d40f6ae9622c..112b0b728b4d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -25,7 +25,6 @@ #include "soc_bounding_box.h" #include "display_mode_lib.h" -#include "dml_inline_defs.h" void dml_socbb_set_latencies( struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box) -- GitLab From 378c4a2d609dfc048c4416a387ddec06994cc307 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:11:18 -0400 Subject: [PATCH 1299/2898] Revert "amdgpu/dc: drop display_pipe_clocks.c." This reverts commit b3fbdcec5e6c16c93867289ae0960a64c423eb34. Unfortunately these clash with our DML update from the HW guys as it's starting to get used now. Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +- .../drm/amd/display/dc/dml/display_mode_lib.h | 1 + .../amd/display/dc/dml/display_pipe_clocks.c | 367 ++++++++++++++++++ .../amd/display/dc/dml/display_pipe_clocks.h | 41 ++ 4 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index a6bf36466497..9d7791d00e97 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -13,7 +13,7 @@ CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 -DML = display_mode_lib.o display_rq_dlg_calc.o \ +DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o display_watermark.o \ soc_bounding_box.o dml_common_defs.o display_mode_support.o diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index eb1c8e6e7f23..e2e311138358 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -28,6 +28,7 @@ #include "dml_common_defs.h" #include "soc_bounding_box.h" #include "display_watermark.h" +#include "display_pipe_clocks.h" #include "display_rq_dlg_calc.h" #include "display_mode_support.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c new file mode 100644 index 000000000000..2e4dc57cafa0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c @@ -0,0 +1,367 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "display_pipe_clocks.h" +#include "display_mode_lib.h" +#include "soc_bounding_box.h" + +static enum voltage_state power_state( + struct display_mode_lib *mode_lib, + double dispclk, + double dppclk) +{ + enum voltage_state state1; + enum voltage_state state2; + + if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) + state1 = dm_vmin; + else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) + state1 = dm_vnom; + else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) + state1 = dm_vmax; + else + state1 = dm_vmax_exceeded; + + if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) + state2 = dm_vmin; + else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) + state2 = dm_vnom; + else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) + state2 = dm_vmax; + else + state2 = dm_vmax_exceeded; + + if (state1 > state2) + return state1; + else + return state2; +} + +static unsigned int dpp_in_grp( + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + unsigned int hsplit_grp) +{ + unsigned int num_dpp = 0; + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.is_hsplit) { + if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { + num_dpp++; + } + } + } + + if (0 == num_dpp) + num_dpp = 1; + + return num_dpp; +} + +static void calculate_pipe_clk_requirement( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp, + double *dppclk, + double *dispclk, + bool *dppdiv) +{ + double pscl_throughput = 0.0; + double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; + double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; + double max_htaps = e2e->pipe.scale_taps.htaps; + double max_vtaps = e2e->pipe.scale_taps.vtaps; + double dpp_clock_divider = (double) num_dpp_in_grp; + double dispclk_dppclk_ratio; + double dispclk_ramp_margin_percent; + + if (max_hratio > 1.0) { + double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) + / dml_ceil(max_htaps / 6.0); + pscl_throughput = dml_min( + pscl_to_lb, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } else { + pscl_throughput = dml_min( + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } + + DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); + DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); + *dppclk = dml_max( + max_vtaps / 6.0 * dml_min(1.0, max_hratio), + max_hratio * max_vratio / pscl_throughput); + DTRACE("pixel rate multiplier: %f", *dppclk); + *dppclk = dml_max(*dppclk, 1.0); + DTRACE("pixel rate multiplier clamped: %f", *dppclk); + *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; + + *dppclk = *dppclk / dpp_clock_divider; + DTRACE("dppclk after split: %f", *dppclk); + + if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { + dispclk_dppclk_ratio = 2.0; + *dppdiv = true; + } else { + dispclk_dppclk_ratio = 1.0; + *dppdiv = false; + } + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + /* Comment this out because of Gabes possible bug in spreadsheet, + * just to make other cases evident during debug + * + *if(e2e->clks_cfg.voltage == dm_vmax) + * dispclk_ramp_margin_percent = 0.0; + */ + + /* account for ramping margin and downspread */ + *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + return; +} + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp) +{ + double dppclk = 0; + double dispclk = 0; + bool dppdiv = 0; + + calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); + + if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { + return false; + } + + return true; +} + +static void get_plane_clks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dppclks, + double *dispclks, + bool *dppdiv) +{ + /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated + * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to + * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently + * and we would expect the same result on any split pipes, which would be handled + */ + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + double num_dpp_in_grp; + double dispclk_ramp_margin_percent; + double dispclk_margined; + + if (e2e[i].pipe.src.is_hsplit) + num_dpp_in_grp = (double) dpp_in_grp( + e2e, + num_pipes, + e2e[i].pipe.src.hsplit_grp); + else + num_dpp_in_grp = 1; + + calculate_pipe_clk_requirement( + mode_lib, + &e2e[i], + num_dpp_in_grp, + &dppclks[i], + &dispclks[i], + &dppdiv[i]); + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); + + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > power_state(mode_lib, dispclk_margined, dispclk_margined) + && dispclk_margined > dppclks[i]) { + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > e2e[0].clks_cfg.voltage) { + dispclks[i] = dispclk_margined; + dppclks[i] = dispclk_margined; + dppdiv[i] = false; + } + } + + DTRACE("p%d: dispclk: %f", i, dispclks[i]); + } +} + +static void get_dcfclk( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dcfclk_mhz) +{ + double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; + double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; + double swath_width_y[DC__NUM_PIPES__MAX]; + unsigned int i; + double total_read_bandwidth_gbps = 0.0; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.source_scan == dm_horz) { + swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; + } else { + swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; + } + + switch (e2e[i].pipe.src.source_format) { + case dm_444_64: + bytes_per_pixel_det_y[i] = 8.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_32: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_16: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_8: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_10: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_420_8: + bytes_per_pixel_det_y[i] = 1.0; + bytes_per_pixel_det_c[i] = 2.0; + break; + case dm_420_10: + bytes_per_pixel_det_y[i] = 4.0 / 3.0; + bytes_per_pixel_det_c[i] = 8.0 / 3.0; + break; + default: + BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ + } + } + + for (i = 0; i < num_pipes; i++) { + double read_bandwidth_plane_mbps = 0.0; + read_bandwidth_plane_mbps = (double) swath_width_y[i] + * ((double) bytes_per_pixel_det_y[i] + + (double) bytes_per_pixel_det_c[i] / 2.0) + / ((double) e2e[i].pipe.dest.htotal + / (double) e2e[i].pipe.dest.pixel_rate_mhz) + * e2e[i].pipe.scale_ratio_depth.vscl_ratio; + + if (e2e[i].pipe.src.dcc) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); + } + + if (e2e[i].pipe.src.vm) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); + } + + total_read_bandwidth_gbps = total_read_bandwidth_gbps + + read_bandwidth_plane_mbps / 1000.0; + } + + DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); + + (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; + + DTRACE( + "minimum theoretical dcfclk without stutter and full utilization = %f MHz", + (*dcfclk_mhz)); + +} + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + struct _vcs_dpi_display_pipe_clock_st clocks; + double max_dispclk = 0.0; + double dcfclk; + double dispclks[DC__NUM_PIPES__MAX]; + double dppclks[DC__NUM_PIPES__MAX]; + bool dppdiv[DC__NUM_PIPES__MAX]; + unsigned int i; + + DTRACE("Calculating pipe clocks..."); + + /* this is the theoretical minimum, have to adjust based on valid values for soc */ + get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); + + /* if(dcfclk > soc.vnom.dcfclk_mhz) + * dcfclk = soc.vmax.dcfclk_mhz; + * else if(dcfclk > soc.vmin.dcfclk_mhz) + * dcfclk = soc.vnom.dcfclk_mhz; + * else + * dcfclk = soc.vmin.dcfclk_mhz; + */ + + dcfclk = dml_socbb_voltage_scaling( + &mode_lib->soc, + (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; + clocks.dcfclk_mhz = dcfclk; + + get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); + + for (i = 0; i < num_pipes; i++) { + max_dispclk = dml_max(max_dispclk, dispclks[i]); + } + + clocks.dispclk_mhz = max_dispclk; + DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); + DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); + + for (i = 0; i < num_pipes; i++) { + if (dppclks[i] * 2 < max_dispclk) + dppdiv[i] = 1; + + if (dppdiv[i]) + clocks.dppclk_div[i] = 1; + else + clocks.dppclk_div[i] = 0; + + clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); + DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + } + + return clocks; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h new file mode 100644 index 000000000000..aed5f33bb04f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DISPLAY_PIPE_CLOCKS_H__ +#define __DISPLAY_PIPE_CLOCKS_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp); +#endif -- GitLab From 19b7fe4a48efbe0f7e8c496b040c4eb16ff02313 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:15:57 -0400 Subject: [PATCH 1300/2898] Revert "amdgpu/dc: inline a bunch of float operations." This reverts commit d1209512e028a917e6e70b13297ff185234ba24d. Unfortunately these clash with our DML update from the HW guys. Rerolling this after the fact won't save us anything anymore, unfortunately so we're back to non-inline for this. Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/dcn_calc_math.c | 29 +++++++++++++++ .../drm/amd/display/dc/calcs/dcn_calc_math.h | 36 ++++--------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index 05cf5f77ec60..a18474437990 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -25,6 +25,25 @@ #include "dcn_calc_math.h" +float dcn_bw_mod(const float arg1, const float arg2) +{ + return arg1 - arg1 * ((int) (arg1 / arg2)); +} + +float dcn_bw_min2(const float arg1, const float arg2) +{ + return arg1 < arg2 ? arg1 : arg2; +} + +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} +float dcn_bw_max2(const float arg1, const float arg2) +{ + return arg1 > arg2 ? arg1 : arg2; +} + float dcn_bw_floor2(const float arg, const float significance) { if (significance == 0) @@ -40,6 +59,16 @@ float dcn_bw_ceil2(const float arg, const float significance) return flr + 0.00001 >= arg ? arg : flr + significance; } +float dcn_bw_max3(float v1, float v2, float v3) +{ + return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); +} + +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) +{ + return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); +} + float dcn_bw_pow(float a, float exp) { float temp; diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h index 6f66d9d164d1..f46ab0e24ca1 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h @@ -26,38 +26,14 @@ #ifndef _DCN_CALC_MATH_H_ #define _DCN_CALC_MATH_H_ -static inline float dcn_bw_mod(const float arg1, const float arg2) -{ - return arg1 - arg1 * ((int) (arg1 / arg2)); -} - -static inline float dcn_bw_min2(const float arg1, const float arg2) -{ - return arg1 < arg2 ? arg1 : arg2; -} - -static inline unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} - -static inline float dcn_bw_max2(const float arg1, const float arg2) -{ - return arg1 > arg2 ? arg1 : arg2; -} - -static inline float dcn_bw_max3(float v1, float v2, float v3) -{ - return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2); -} - -static inline float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5) -{ - return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5); -} - +float dcn_bw_mod(const float arg1, const float arg2); +float dcn_bw_min2(const float arg1, const float arg2); +unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2); +float dcn_bw_max2(const float arg1, const float arg2); float dcn_bw_floor2(const float arg, const float significance); float dcn_bw_ceil2(const float arg, const float significance); +float dcn_bw_max3(float v1, float v2, float v3); +float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5); float dcn_bw_pow(float a, float exp); float dcn_bw_log(float a, float b); -- GitLab From 6d04ee9dc10149db842d41de66eca201c9d91b60 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 23 Aug 2017 16:43:17 -0400 Subject: [PATCH 1301/2898] drm/amd/display: Restructuring and cleaning up DML Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/calcs/dcn_calc_math.c | 16 + .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 103 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 - .../drm/amd/display/dc/dcn10/dcn10_resource.c | 5 +- drivers/gpu/drm/amd/display/dc/dml/Makefile | 8 +- .../gpu/drm/amd/display/dc/dml/dc_features.h | 2 + .../amd/display/dc/dml/display_mode_enums.h | 52 +- .../drm/amd/display/dc/dml/display_mode_lib.c | 7 +- .../drm/amd/display/dc/dml/display_mode_lib.h | 8 +- .../amd/display/dc/dml/display_mode_structs.h | 898 +++-- .../amd/display/dc/dml/display_mode_support.c | 2326 ------------ .../amd/display/dc/dml/display_mode_support.h | 199 - .../drm/amd/display/dc/dml/display_mode_vba.c | 3263 +++++++++++++++++ .../drm/amd/display/dc/dml/display_mode_vba.h | 410 +++ .../amd/display/dc/dml/display_pipe_clocks.c | 377 +- .../amd/display/dc/dml/display_pipe_clocks.h | 8 +- .../amd/display/dc/dml/display_rq_dlg_calc.c | 2457 +++++-------- .../amd/display/dc/dml/display_rq_dlg_calc.h | 151 +- .../display/dc/dml/display_rq_dlg_helpers.c | 482 +-- .../display/dc/dml/display_rq_dlg_helpers.h | 41 +- .../amd/display/dc/dml/display_watermark.c | 1281 ------- .../amd/display/dc/dml/display_watermark.h | 98 - .../display/dc/dml/dml1_display_rq_dlg_calc.c | 1903 ++++++++++ .../display/dc/dml/dml1_display_rq_dlg_calc.h | 67 + .../drm/amd/display/dc/dml/dml_common_defs.c | 12 +- .../drm/amd/display/dc/dml/dml_common_defs.h | 8 +- .../drm/amd/display/dc/dml/soc_bounding_box.c | 48 +- .../drm/amd/display/dc/dml/soc_bounding_box.h | 9 +- 28 files changed, 7658 insertions(+), 6582 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c index a18474437990..b6abe0f3bb15 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c @@ -27,20 +27,36 @@ float dcn_bw_mod(const float arg1, const float arg2) { + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; return arg1 - arg1 * ((int) (arg1 / arg2)); } float dcn_bw_min2(const float arg1, const float arg2) { + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; return arg1 < arg2 ? arg1 : arg2; } unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2) { + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; return arg1 > arg2 ? arg1 : arg2; } float dcn_bw_max2(const float arg1, const float arg2) { + if (arg1 != arg1) + return arg2; + if (arg2 != arg2) + return arg1; return arg1 > arg2 ? arg1 : arg2; } diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 6318f9f69c92..fd1db8dc2f35 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -386,10 +386,6 @@ static void pipe_ctx_to_e2e_pipe_params ( - pipe->stream->timing.v_addressable - pipe->stream->timing.v_border_bottom - pipe->stream->timing.v_border_top; - - input->dest.vsync_plus_back_porch = pipe->stream->timing.v_total - - pipe->stream->timing.v_addressable - - pipe->stream->timing.v_front_porch; input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0; input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; @@ -459,9 +455,9 @@ static void dcn_bw_calc_rq_dlg_ttu( /*todo: soc->sr_enter_plus_exit_time??*/ dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; - dml_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); - extract_rq_regs(dml, rq_regs, rq_param); - dml_rq_dlg_get_dlg_params( + dml1_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); + dml1_extract_rq_regs(dml, rq_regs, rq_param); + dml1_rq_dlg_get_dlg_params( dml, dlg_regs, ttu_regs, @@ -474,96 +470,6 @@ static void dcn_bw_calc_rq_dlg_ttu( pipe->plane_state->flip_immediate); } -static void dcn_dml_wm_override( - const struct dcn_bw_internal_vars *v, - struct display_mode_lib *dml, - struct dc_state *context, - const struct resource_pool *pool) -{ - int i, in_idx, active_count; - - struct _vcs_dpi_display_e2e_pipe_params_st *input = kzalloc(pool->pipe_count * sizeof(struct _vcs_dpi_display_e2e_pipe_params_st), - GFP_KERNEL); - struct wm { - double urgent; - struct _vcs_dpi_cstate_pstate_watermarks_st cpstate; - double pte_meta_urgent; - } a; - - - for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (!pipe->stream || !pipe->plane_state) - continue; - - input[in_idx].clks_cfg.dcfclk_mhz = v->dcfclk; - input[in_idx].clks_cfg.dispclk_mhz = v->dispclk; - input[in_idx].clks_cfg.dppclk_mhz = v->dppclk; - input[in_idx].clks_cfg.refclk_mhz = pool->ref_clock_inKhz / 1000; - input[in_idx].clks_cfg.socclk_mhz = v->socclk; - input[in_idx].clks_cfg.voltage = v->voltage_level; - input[in_idx].dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; - input[in_idx].dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; - //input[in_idx].dout.output_standard; - switch (v->output_deep_color[in_idx]) { - case dcn_bw_encoder_12bpc: - input[in_idx].dout.output_bpc = dm_out_12; - break; - case dcn_bw_encoder_10bpc: - input[in_idx].dout.output_bpc = dm_out_10; - break; - case dcn_bw_encoder_8bpc: - default: - input[in_idx].dout.output_bpc = dm_out_8; - break; - } - pipe_ctx_to_e2e_pipe_params(pipe, &input[in_idx].pipe); - dml_rq_dlg_get_rq_reg( - dml, - &pipe->rq_regs, - input[in_idx].pipe.src); - in_idx++; - } - active_count = in_idx; - - a.urgent = dml_wm_urgent_e2e(dml, input, active_count); - a.cpstate = dml_wm_cstate_pstate_e2e(dml, input, active_count); - a.pte_meta_urgent = dml_wm_pte_meta_urgent(dml, a.urgent); - - context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = - a.cpstate.cstate_exit_us * 1000; - context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = - a.cpstate.cstate_enter_plus_exit_us * 1000; - context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = - a.cpstate.pstate_change_us * 1000; - context->bw.dcn.watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000; - context->bw.dcn.watermarks.a.urgent_ns = a.urgent * 1000; - context->bw.dcn.watermarks.b = context->bw.dcn.watermarks.a; - context->bw.dcn.watermarks.c = context->bw.dcn.watermarks.a; - context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a; - - - for (i = 0, in_idx = 0; i < pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (!pipe->stream || !pipe->plane_state) - continue; - - dml_rq_dlg_get_dlg_reg(dml, - &pipe->dlg_regs, - &pipe->ttu_regs, - input, active_count, - in_idx, - true, - true, - v->pte_enable == dcn_bw_yes, - pipe->plane_state->flip_immediate); - in_idx++; - } - kfree(input); -} - static void split_stream_across_pipes( struct resource_context *res_ctx, const struct resource_pool *pool, @@ -1163,9 +1069,6 @@ bool dcn_validate_bandwidth( input_idx++; } - if (dc->debug.use_dml_wm) - dcn_dml_wm_override(v, (struct display_mode_lib *) - &dc->dml, context, pool); } if (v->voltage_level == 0) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d624554efbc7..bf83459456a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -200,7 +200,6 @@ struct dc_debug { bool disable_hubp_power_gate; bool disable_pplib_wm_range; enum wm_report_mode pplib_wm_report_mode; - bool use_dml_wm; unsigned int min_disp_clk_khz; int sr_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 5d618e68a744..3000ddab2357 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -425,8 +425,6 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = false, .pplib_wm_report_mode = WM_REPORT_DEFAULT, - .use_dml_wm = false, - .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .disable_dcc = DCC_ENABLE, .voltage_align_fclk = true, @@ -439,8 +437,7 @@ static const struct dc_debug debug_defaults_diags = { .clock_trace = true, .disable_stutter = true, .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, - .use_dml_wm = false, + .disable_pplib_wm_range = true }; static void dcn10_dpp_destroy(struct transform **xfm) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 9d7791d00e97..c6d9d9530d75 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -3,19 +3,19 @@ # It provides the general basic services required by other DAL # subcomponents. +CFLAGS_display_mode_vba.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_mode_lib.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_pipe_clocks.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dml1_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ - display_rq_dlg_helpers.o display_watermark.o \ - soc_bounding_box.o dml_common_defs.o display_mode_support.o + display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ + soc_bounding_box.o dml_common_defs.o display_mode_vba.o AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h index 745c04cb764a..ea4cde952f4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h @@ -25,9 +25,11 @@ #ifndef __DC_FEATURES_H__ #define __DC_FEATURES_H__ +// local features #define DC__PRESENT 1 #define DC__PRESENT__1 1 #define DC__NUM_DPP 4 +#define DC__VOLTAGE_STATES 7 #define DC__NUM_DPP__4 1 #define DC__NUM_DPP__0_PRESENT 1 #define DC__NUM_DPP__1_PRESENT 1 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index 143a3d418de0..eebaeb1fb61c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -24,14 +24,12 @@ */ #ifndef __DISPLAY_MODE_ENUMS_H__ #define __DISPLAY_MODE_ENUMS_H__ + enum output_encoder_class { - dm_dp = 0, - dm_hdmi = 1, - dm_wb = 2 + dm_dp = 0, dm_hdmi = 1, dm_wb = 2 }; enum output_format_class { - dm_444 = 0, - dm_420 = 1 + dm_444 = 0, dm_420 = 1, dm_n422, dm_s422 }; enum source_format_class { dm_444_16 = 0, @@ -40,18 +38,14 @@ enum source_format_class { dm_420_8 = 3, dm_420_10 = 4, dm_422_8 = 5, - dm_422_10 = 6 + dm_422_10 = 6, + dm_444_8 = 7 }; enum output_bpc_class { - dm_out_6 = 0, - dm_out_8 = 1, - dm_out_10 = 2, - dm_out_12 = 3, - dm_out_16 = 4 + dm_out_6 = 0, dm_out_8 = 1, dm_out_10 = 2, dm_out_12 = 3, dm_out_16 = 4 }; enum scan_direction_class { - dm_horz = 0, - dm_vert = 1 + dm_horz = 0, dm_vert = 1 }; enum dm_swizzle_mode { dm_sw_linear = 0, @@ -84,28 +78,30 @@ enum dm_swizzle_mode { dm_sw_SPARE_14 = 27, dm_sw_SPARE_15 = 28, dm_sw_var_s_x = 29, - dm_sw_var_d_x = 30 + dm_sw_var_d_x = 30, + dm_sw_64kb_r_x }; enum lb_depth { - dm_lb_10 = 30, - dm_lb_8 = 24, - dm_lb_6 = 18, - dm_lb_12 = 36 + dm_lb_10 = 0, dm_lb_8 = 1, dm_lb_6 = 2, dm_lb_12 = 3, dm_lb_16 }; enum voltage_state { - dm_vmin = 0, - dm_vmid = 1, - dm_vnom = 2, - dm_vmax = 3, - dm_vmax_exceeded = 4 + dm_vmin = 0, dm_vmid = 1, dm_vnom = 2, dm_vmax = 3 }; enum source_macro_tile_size { - dm_4k_tile = 0, - dm_64k_tile = 1, - dm_256k_tile = 2 + dm_4k_tile = 0, dm_64k_tile = 1, dm_256k_tile = 2 }; enum cursor_bpp { - dm_cur_2bit = 0, - dm_cur_32bit = 1 + dm_cur_2bit = 0, dm_cur_32bit = 1, dm_cur_64bit = 2 }; +enum clock_change_support { + dm_dram_clock_change_uninitialized = 0, + dm_dram_clock_change_vactive, + dm_dram_clock_change_vblank, + dm_dram_clock_change_unsupported +}; + +enum output_standard { + dm_std_uninitialized = 0, dm_std_cvtr2, dm_std_cvt +}; + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index c02c5522613b..09d232806de7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -24,6 +24,7 @@ */ #include "display_mode_lib.h" +#include "dc_features.h" static void set_soc_bounding_box(struct _vcs_dpi_soc_bounding_box_st *soc, enum dml_project project) { @@ -128,11 +129,7 @@ static void set_ip_params(struct _vcs_dpi_ip_params_st *ip, enum dml_project pro static void set_mode_evaluation(struct _vcs_dpi_mode_evaluation_st *me, enum dml_project project) { - if (project == DML_PROJECT_RAVEN1) { - me->voltage_override = dm_vmin; - } else { - BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ - } + me->voltage_override = dm_vmin; } void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index e2e311138358..57f49d29c6b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -25,12 +25,13 @@ #ifndef __DISPLAY_MODE_LIB_H__ #define __DISPLAY_MODE_LIB_H__ + #include "dml_common_defs.h" #include "soc_bounding_box.h" -#include "display_watermark.h" +#include "display_mode_vba.h" #include "display_pipe_clocks.h" #include "display_rq_dlg_calc.h" -#include "display_mode_support.h" +#include "dml1_display_rq_dlg_calc.h" enum dml_project { DML_PROJECT_UNDEFINED, @@ -42,8 +43,7 @@ struct display_mode_lib { struct _vcs_dpi_soc_bounding_box_st soc; struct _vcs_dpi_mode_evaluation_st me; enum dml_project project; - struct dml_ms_internal_vars vars; - struct _vcs_dpi_wm_calc_pipe_params_st wm_param[DC__NUM_PIPES__MAX]; + struct vba_vars_st vba; struct dal_logger *logger; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index e589a5eadb6a..e5b7f7042e0b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -25,405 +25,531 @@ #ifndef __DISPLAY_MODE_STRUCTS_H__ #define __DISPLAY_MODE_STRUCTS_H__ +typedef struct _vcs_dpi_voltage_scaling_st voltage_scaling_st; +typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st; +typedef struct _vcs_dpi_mode_evaluation_st mode_evaluation_st; +typedef struct _vcs_dpi_ip_params_st ip_params_st; +typedef struct _vcs_dpi_display_pipe_source_params_st display_pipe_source_params_st; +typedef struct _vcs_dpi_display_output_params_st display_output_params_st; +typedef struct _vcs_dpi_display_bandwidth_st display_bandwidth_st; +typedef struct _vcs_dpi_scaler_ratio_depth_st scaler_ratio_depth_st; +typedef struct _vcs_dpi_scaler_taps_st scaler_taps_st; +typedef struct _vcs_dpi_display_pipe_dest_params_st display_pipe_dest_params_st; +typedef struct _vcs_dpi_display_pipe_params_st display_pipe_params_st; +typedef struct _vcs_dpi_display_clocks_and_cfg_st display_clocks_and_cfg_st; +typedef struct _vcs_dpi_display_e2e_pipe_params_st display_e2e_pipe_params_st; +typedef struct _vcs_dpi_dchub_buffer_sizing_st dchub_buffer_sizing_st; +typedef struct _vcs_dpi_watermarks_perf_st watermarks_perf_st; +typedef struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_watermarks_st; +typedef struct _vcs_dpi_wm_calc_pipe_params_st wm_calc_pipe_params_st; +typedef struct _vcs_dpi_vratio_pre_st vratio_pre_st; +typedef struct _vcs_dpi_display_data_rq_misc_params_st display_data_rq_misc_params_st; +typedef struct _vcs_dpi_display_data_rq_sizing_params_st display_data_rq_sizing_params_st; +typedef struct _vcs_dpi_display_data_rq_dlg_params_st display_data_rq_dlg_params_st; +typedef struct _vcs_dpi_display_cur_rq_dlg_params_st display_cur_rq_dlg_params_st; +typedef struct _vcs_dpi_display_rq_dlg_params_st display_rq_dlg_params_st; +typedef struct _vcs_dpi_display_rq_sizing_params_st display_rq_sizing_params_st; +typedef struct _vcs_dpi_display_rq_misc_params_st display_rq_misc_params_st; +typedef struct _vcs_dpi_display_rq_params_st display_rq_params_st; +typedef struct _vcs_dpi_display_dlg_regs_st display_dlg_regs_st; +typedef struct _vcs_dpi_display_ttu_regs_st display_ttu_regs_st; +typedef struct _vcs_dpi_display_data_rq_regs_st display_data_rq_regs_st; +typedef struct _vcs_dpi_display_rq_regs_st display_rq_regs_st; +typedef struct _vcs_dpi_display_dlg_sys_params_st display_dlg_sys_params_st; +typedef struct _vcs_dpi_display_dlg_prefetch_param_st display_dlg_prefetch_param_st; +typedef struct _vcs_dpi_display_pipe_clock_st display_pipe_clock_st; +typedef struct _vcs_dpi_display_arb_params_st display_arb_params_st; + +struct _vcs_dpi_mode_evaluation_st { + int voltage_override; +}; + struct _vcs_dpi_voltage_scaling_st { + int state; double dcfclk_mhz; + double socclk_mhz; + double dram_speed_mhz; + double fabricclk_mhz; double dispclk_mhz; - double dppclk_mhz; double dram_bw_per_chan_gbps; double phyclk_mhz; - double socclk_mhz; + double dppclk_mhz; }; -struct _vcs_dpi_soc_bounding_box_st { - double sr_exit_time_us; - double sr_enter_plus_exit_time_us; - double urgent_latency_us; - double writeback_latency_us; - double ideal_dram_bw_after_urgent_percent; - unsigned int max_request_size_bytes; - struct _vcs_dpi_voltage_scaling_st vmin; - struct _vcs_dpi_voltage_scaling_st vmid; - struct _vcs_dpi_voltage_scaling_st vnom; - struct _vcs_dpi_voltage_scaling_st vmax; - double downspread_percent; - double dram_page_open_time_ns; - double dram_rw_turnaround_time_ns; - double dram_return_buffer_per_channel_bytes; - unsigned int round_trip_ping_latency_dcfclk_cycles; - unsigned int urgent_out_of_order_return_per_channel_bytes; - unsigned int channel_interleave_bytes; - unsigned int num_banks; - unsigned int num_chans; - unsigned int vmm_page_size_bytes; - double dram_clock_change_latency_us; - double writeback_dram_clock_change_latency_us; - unsigned int return_bus_width_bytes; -}; - -struct _vcs_dpi_ip_params_st { - unsigned int rob_buffer_size_kbytes; - unsigned int det_buffer_size_kbytes; - unsigned int dpte_buffer_size_in_pte_reqs; - unsigned int dpp_output_buffer_pixels; - unsigned int opp_output_buffer_lines; - unsigned int pixel_chunk_size_kbytes; - unsigned char pte_enable; - unsigned int pte_chunk_size_kbytes; - unsigned int meta_chunk_size_kbytes; - unsigned int writeback_chunk_size_kbytes; - unsigned int line_buffer_size_bits; - unsigned int max_line_buffer_lines; +struct _vcs_dpi_soc_bounding_box_st { + double sr_exit_time_us; + double sr_enter_plus_exit_time_us; + double urgent_latency_us; + double writeback_latency_us; + double ideal_dram_bw_after_urgent_percent; + unsigned int max_request_size_bytes; + struct _vcs_dpi_voltage_scaling_st vmin; + struct _vcs_dpi_voltage_scaling_st vmid; + struct _vcs_dpi_voltage_scaling_st vnom; + struct _vcs_dpi_voltage_scaling_st vmax; + double downspread_percent; + double dram_page_open_time_ns; + double dram_rw_turnaround_time_ns; + double dram_return_buffer_per_channel_bytes; + double dram_channel_width_bytes; + double fabric_datapath_to_dcn_data_return_bytes; + double dcn_downspread_percent; + double dispclk_dppclk_vco_speed_mhz; + unsigned int round_trip_ping_latency_dcfclk_cycles; + unsigned int urgent_out_of_order_return_per_channel_bytes; + unsigned int channel_interleave_bytes; + unsigned int num_banks; + unsigned int num_chans; + unsigned int vmm_page_size_bytes; + double dram_clock_change_latency_us; + double writeback_dram_clock_change_latency_us; + unsigned int return_bus_width_bytes; + double xfc_bus_transport_time_us; + double xfc_xbuf_latency_tolerance_us; + struct _vcs_dpi_voltage_scaling_st clock_limits[7]; +}; + +struct _vcs_dpi_ip_params_st { + unsigned int max_inter_dcn_tile_repeaters; + unsigned int num_dsc; + unsigned int odm_capable; + unsigned int rob_buffer_size_kbytes; + unsigned int det_buffer_size_kbytes; + unsigned int dpte_buffer_size_in_pte_reqs; + unsigned int pde_proc_buffer_size_64k_reqs; + unsigned int dpp_output_buffer_pixels; + unsigned int opp_output_buffer_lines; + unsigned int pixel_chunk_size_kbytes; + unsigned char pte_enable; + unsigned int pte_chunk_size_kbytes; + unsigned int meta_chunk_size_kbytes; + unsigned int writeback_chunk_size_kbytes; + unsigned int line_buffer_size_bits; + unsigned int max_line_buffer_lines; + unsigned int writeback_luma_buffer_size_kbytes; + unsigned int writeback_chroma_buffer_size_kbytes; + unsigned int writeback_chroma_line_buffer_width_pixels; + unsigned int max_page_table_levels; + unsigned int max_num_dpp; + unsigned int max_num_wb; + unsigned int max_dchub_pscl_bw_pix_per_clk; + unsigned int max_pscl_lb_bw_pix_per_clk; + unsigned int max_lb_vscl_bw_pix_per_clk; + unsigned int max_vscl_hscl_bw_pix_per_clk; + double max_hscl_ratio; + double max_vscl_ratio; + unsigned int hscl_mults; + unsigned int vscl_mults; + unsigned int max_hscl_taps; + unsigned int max_vscl_taps; + unsigned int xfc_supported; + unsigned int ptoi_supported; + unsigned int xfc_fill_constant_bytes; + double dispclk_ramp_margin_percent; + double xfc_fill_bw_overhead_percent; + double underscan_factor; + unsigned int min_vblank_lines; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int dcfclk_cstate_latency; + unsigned int dppclk_delay_scl; + unsigned int dppclk_delay_scl_lb_only; + unsigned int dppclk_delay_cnvc_formatter; + unsigned int dppclk_delay_cnvc_cursor; + unsigned int is_line_buffer_bpp_fixed; + unsigned int line_buffer_fixed_bpp; + unsigned int dcc_supported; + unsigned int IsLineBufferBppFixed; unsigned int LineBufferFixedBpp; - unsigned int writeback_luma_buffer_size_kbytes; - unsigned int writeback_chroma_buffer_size_kbytes; - unsigned int max_num_dpp; - unsigned int max_num_wb; - unsigned int max_dchub_pscl_bw_pix_per_clk; - unsigned int max_pscl_lb_bw_pix_per_clk; - unsigned int max_lb_vscl_bw_pix_per_clk; - unsigned int max_vscl_hscl_bw_pix_per_clk; - double max_hscl_ratio; - double max_vscl_ratio; - unsigned int hscl_mults; - unsigned int vscl_mults; - unsigned int max_hscl_taps; - unsigned int max_vscl_taps; - double dispclk_ramp_margin_percent; - double underscan_factor; - unsigned int min_vblank_lines; - unsigned int dppclk_delay_subtotal; - unsigned int dispclk_delay_subtotal; - unsigned int dcfclk_cstate_latency; - unsigned int max_inter_dcn_tile_repeaters; unsigned int can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; unsigned int bug_forcing_LC_req_same_size_fixed; }; -struct _vcs_dpi_display_pipe_source_params_st { - int source_format; - unsigned char dcc; - unsigned int dcc_rate; - unsigned char vm; - int source_scan; - int sw_mode; - int macro_tile_size; - unsigned char is_display_sw; - unsigned int viewport_width; - unsigned int viewport_height; - unsigned int viewport_width_c; - unsigned int viewport_height_c; - unsigned int data_pitch; - unsigned int data_pitch_c; - unsigned int meta_pitch; - unsigned int meta_pitch_c; - unsigned int cur0_src_width; - int cur0_bpp; - unsigned char is_hsplit; - unsigned int hsplit_grp; -}; - -struct _vcs_dpi_display_output_params_st { - int output_bpc; - int output_type; - int output_format; - int output_standard; -}; - -struct _vcs_dpi_display_bandwidth_st { - double total_bw_consumed_gbps; - double guaranteed_urgent_return_bw_gbps; -}; - -struct _vcs_dpi_scaler_ratio_depth_st { - double hscl_ratio; - double vscl_ratio; - double hscl_ratio_c; - double vscl_ratio_c; - double vinit; - double vinit_c; - double vinit_bot; - double vinit_bot_c; - int lb_depth; -}; - -struct _vcs_dpi_scaler_taps_st { - unsigned int htaps; - unsigned int vtaps; - unsigned int htaps_c; - unsigned int vtaps_c; -}; - -struct _vcs_dpi_display_pipe_dest_params_st { - unsigned int recout_width; - unsigned int recout_height; - unsigned int full_recout_width; - unsigned int full_recout_height; - unsigned int hblank_start; - unsigned int hblank_end; - unsigned int vblank_start; - unsigned int vblank_end; - unsigned int htotal; - unsigned int vtotal; - unsigned int vactive; - unsigned int vstartup_start; - unsigned int vupdate_offset; - unsigned int vupdate_width; - unsigned int vready_offset; - unsigned int vsync_plus_back_porch; - unsigned char interlaced; - unsigned char underscan; - double pixel_rate_mhz; - unsigned char syncronized_vblank_all_planes; -}; - -struct _vcs_dpi_display_pipe_params_st { - struct _vcs_dpi_display_pipe_source_params_st src; - struct _vcs_dpi_display_pipe_dest_params_st dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps; -}; - -struct _vcs_dpi_display_clocks_and_cfg_st { - int voltage; - double dppclk_mhz; - double refclk_mhz; - double dispclk_mhz; - double dcfclk_mhz; - double socclk_mhz; -}; - -struct _vcs_dpi_display_e2e_pipe_params_st { - struct _vcs_dpi_display_pipe_params_st pipe; - struct _vcs_dpi_display_output_params_st dout; - struct _vcs_dpi_display_clocks_and_cfg_st clks_cfg; -}; - -struct _vcs_dpi_dchub_buffer_sizing_st { - unsigned int swath_width_y; - unsigned int swath_height_y; - unsigned int swath_height_c; - unsigned int detail_buffer_size_y; -}; - -struct _vcs_dpi_watermarks_perf_st { - double stutter_eff_in_active_region_percent; - double urgent_latency_supported_us; - double non_urgent_latency_supported_us; - double dram_clock_change_margin_us; - double dram_access_eff_percent; -}; - -struct _vcs_dpi_cstate_pstate_watermarks_st { - double cstate_exit_us; - double cstate_enter_plus_exit_us; - double pstate_change_us; -}; - -struct _vcs_dpi_wm_calc_pipe_params_st { - unsigned int num_dpp; - int voltage; - int output_type; - double dcfclk_mhz; - double socclk_mhz; - double dppclk_mhz; - double pixclk_mhz; - unsigned char interlace_en; - unsigned char pte_enable; - unsigned char dcc_enable; - double dcc_rate; - double bytes_per_pixel_c; - double bytes_per_pixel_y; - unsigned int swath_width_y; - unsigned int swath_height_y; - unsigned int swath_height_c; - unsigned int det_buffer_size_y; - double h_ratio; - double v_ratio; - unsigned int h_taps; - unsigned int h_total; - unsigned int v_total; - unsigned int v_active; - unsigned int e2e_index; - double display_pipe_line_delivery_time; - double read_bw; - unsigned int lines_in_det_y; - unsigned int lines_in_det_y_rounded_down_to_swath; - double full_det_buffering_time; - double dcfclk_deepsleep_mhz_per_plane; -}; - -struct _vcs_dpi_vratio_pre_st { - double vratio_pre_l; - double vratio_pre_c; -}; - -struct _vcs_dpi_display_data_rq_misc_params_st { - unsigned int full_swath_bytes; - unsigned int stored_swath_bytes; - unsigned int blk256_height; - unsigned int blk256_width; - unsigned int req_height; - unsigned int req_width; -}; - -struct _vcs_dpi_display_data_rq_sizing_params_st { - unsigned int chunk_bytes; - unsigned int min_chunk_bytes; - unsigned int meta_chunk_bytes; - unsigned int min_meta_chunk_bytes; - unsigned int mpte_group_bytes; - unsigned int dpte_group_bytes; -}; - -struct _vcs_dpi_display_data_rq_dlg_params_st { - unsigned int swath_width_ub; - unsigned int swath_height; - unsigned int req_per_swath_ub; - unsigned int meta_pte_bytes_per_frame_ub; - unsigned int dpte_req_per_row_ub; - unsigned int dpte_groups_per_row_ub; - unsigned int dpte_row_height; - unsigned int dpte_bytes_per_row_ub; - unsigned int meta_chunks_per_row_ub; - unsigned int meta_req_per_row_ub; - unsigned int meta_row_height; - unsigned int meta_bytes_per_row_ub; -}; - -struct _vcs_dpi_display_cur_rq_dlg_params_st { - unsigned char enable; - unsigned int swath_height; - unsigned int req_per_line; -}; - -struct _vcs_dpi_display_rq_dlg_params_st { - struct _vcs_dpi_display_data_rq_dlg_params_st rq_l; - struct _vcs_dpi_display_data_rq_dlg_params_st rq_c; - struct _vcs_dpi_display_cur_rq_dlg_params_st rq_cur0; -}; - -struct _vcs_dpi_display_rq_sizing_params_st { - struct _vcs_dpi_display_data_rq_sizing_params_st rq_l; - struct _vcs_dpi_display_data_rq_sizing_params_st rq_c; -}; - -struct _vcs_dpi_display_rq_misc_params_st { - struct _vcs_dpi_display_data_rq_misc_params_st rq_l; - struct _vcs_dpi_display_data_rq_misc_params_st rq_c; -}; - -struct _vcs_dpi_display_rq_params_st { - unsigned char yuv420; - unsigned char yuv420_10bpc; - struct _vcs_dpi_display_rq_misc_params_st misc; - struct _vcs_dpi_display_rq_sizing_params_st sizing; - struct _vcs_dpi_display_rq_dlg_params_st dlg; -}; - -struct _vcs_dpi_display_dlg_regs_st { - unsigned int refcyc_h_blank_end; - unsigned int dlg_vblank_end; - unsigned int min_dst_y_next_start; - unsigned int refcyc_per_htotal; - unsigned int refcyc_x_after_scaler; - unsigned int dst_y_after_scaler; - unsigned int dst_y_prefetch; - unsigned int dst_y_per_vm_vblank; - unsigned int dst_y_per_row_vblank; - unsigned int ref_freq_to_pix_freq; - unsigned int vratio_prefetch; - unsigned int vratio_prefetch_c; - unsigned int refcyc_per_pte_group_vblank_l; - unsigned int refcyc_per_pte_group_vblank_c; - unsigned int refcyc_per_meta_chunk_vblank_l; - unsigned int refcyc_per_meta_chunk_vblank_c; - unsigned int dst_y_per_pte_row_nom_l; - unsigned int dst_y_per_pte_row_nom_c; - unsigned int refcyc_per_pte_group_nom_l; - unsigned int refcyc_per_pte_group_nom_c; - unsigned int dst_y_per_meta_row_nom_l; - unsigned int dst_y_per_meta_row_nom_c; - unsigned int refcyc_per_meta_chunk_nom_l; - unsigned int refcyc_per_meta_chunk_nom_c; - unsigned int refcyc_per_line_delivery_pre_l; - unsigned int refcyc_per_line_delivery_pre_c; - unsigned int refcyc_per_line_delivery_l; - unsigned int refcyc_per_line_delivery_c; - unsigned int chunk_hdl_adjust_cur0; -}; - -struct _vcs_dpi_display_ttu_regs_st { - unsigned int qos_level_low_wm; - unsigned int qos_level_high_wm; - unsigned int min_ttu_vblank; - unsigned int qos_level_flip; - unsigned int refcyc_per_req_delivery_l; - unsigned int refcyc_per_req_delivery_c; - unsigned int refcyc_per_req_delivery_cur0; - unsigned int refcyc_per_req_delivery_pre_l; - unsigned int refcyc_per_req_delivery_pre_c; - unsigned int refcyc_per_req_delivery_pre_cur0; - unsigned int qos_level_fixed_l; - unsigned int qos_level_fixed_c; - unsigned int qos_level_fixed_cur0; - unsigned int qos_ramp_disable_l; - unsigned int qos_ramp_disable_c; - unsigned int qos_ramp_disable_cur0; -}; - -struct _vcs_dpi_display_data_rq_regs_st { - unsigned int chunk_size; - unsigned int min_chunk_size; - unsigned int meta_chunk_size; - unsigned int min_meta_chunk_size; - unsigned int dpte_group_size; - unsigned int mpte_group_size; - unsigned int swath_height; - unsigned int pte_row_height_linear; -}; - -struct _vcs_dpi_display_rq_regs_st { - struct _vcs_dpi_display_data_rq_regs_st rq_regs_l; - struct _vcs_dpi_display_data_rq_regs_st rq_regs_c; - unsigned int drq_expansion_mode; - unsigned int prq_expansion_mode; - unsigned int mrq_expansion_mode; - unsigned int crq_expansion_mode; - unsigned int plane1_base_address; -}; - -struct _vcs_dpi_display_dlg_sys_params_st { - double t_mclk_wm_us; - double t_urg_wm_us; - double t_sr_wm_us; - double t_extra_us; - double t_srx_delay_us; - double deepsleep_dcfclk_mhz; - double total_flip_bw; - unsigned int total_flip_bytes; -}; - -struct _vcs_dpi_display_dlg_prefetch_param_st { - double prefetch_bw; - unsigned int flip_bytes; -}; - -struct _vcs_dpi_display_pipe_clock_st { - double dcfclk_mhz; - double dispclk_mhz; - double dppclk_mhz[4]; - unsigned char dppclk_div[4]; -}; - -struct _vcs_dpi_display_arb_params_st { - int max_req_outstanding; - int min_req_outstanding; - int sat_level_us; -}; - -struct _vcs_dpi_mode_evaluation_st { - int voltage_override; +struct _vcs_dpi_display_xfc_params_st { + double xfc_tslv_vready_offset_us; + double xfc_tslv_vupdate_width_us; + double xfc_tslv_vupdate_offset_us; + int xfc_slv_chunk_size_bytes; +}; + +struct _vcs_dpi_display_pipe_source_params_st { + int source_format; + unsigned char dcc; + unsigned int dcc_override; + unsigned int dcc_rate; + unsigned char dcc_use_global; + unsigned char vm; + unsigned char vm_levels_force_en; + unsigned int vm_levels_force; + int source_scan; + int sw_mode; + int macro_tile_size; + unsigned char is_display_sw; + unsigned int viewport_width; + unsigned int viewport_height; + unsigned int viewport_y_y; + unsigned int viewport_y_c; + unsigned int viewport_width_c; + unsigned int viewport_height_c; + unsigned int data_pitch; + unsigned int data_pitch_c; + unsigned int meta_pitch; + unsigned int meta_pitch_c; + unsigned int cur0_src_width; + int cur0_bpp; + unsigned int cur1_src_width; + int cur1_bpp; + int num_cursors; + unsigned char is_hsplit; + unsigned char dynamic_metadata_enable; + unsigned int dynamic_metadata_lines_before_active; + unsigned int dynamic_metadata_xmit_bytes; + unsigned int hsplit_grp; + unsigned char xfc_enable; + unsigned char xfc_slave; + struct _vcs_dpi_display_xfc_params_st xfc_params; +}; +struct writeback_st { + int wb_src_height; + int wb_dst_width; + int wb_dst_height; + int wb_pixel_format; + int wb_htaps_luma; + int wb_vtaps_luma; + int wb_htaps_chroma; + int wb_vtaps_chroma; + int wb_hratio; + int wb_vratio; +}; + +struct _vcs_dpi_display_output_params_st { + int output_bpp; + int dsc_enable; + int wb_enable; + int output_bpc; + int output_type; + int output_format; + int output_standard; + int dsc_slices; + struct writeback_st wb; +}; + +struct _vcs_dpi_display_bandwidth_st { + double total_bw_consumed_gbps; + double guaranteed_urgent_return_bw_gbps; +}; + +struct _vcs_dpi_scaler_ratio_depth_st { + double hscl_ratio; + double vscl_ratio; + double hscl_ratio_c; + double vscl_ratio_c; + double vinit; + double vinit_c; + double vinit_bot; + double vinit_bot_c; + int lb_depth; + int scl_enable; +}; + +struct _vcs_dpi_scaler_taps_st { + unsigned int htaps; + unsigned int vtaps; + unsigned int htaps_c; + unsigned int vtaps_c; +}; + +struct _vcs_dpi_display_pipe_dest_params_st { + unsigned int recout_width; + unsigned int recout_height; + unsigned int full_recout_width; + unsigned int full_recout_height; + unsigned int hblank_start; + unsigned int hblank_end; + unsigned int vblank_start; + unsigned int vblank_end; + unsigned int htotal; + unsigned int vtotal; + unsigned int vactive; + unsigned int hactive; + unsigned int vstartup_start; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned char interlaced; + unsigned char underscan; + double pixel_rate_mhz; + unsigned char synchronized_vblank_all_planes; + unsigned char otg_inst; + unsigned char odm_split_cnt; + unsigned char odm_combine; +}; + +struct _vcs_dpi_display_pipe_params_st { + display_pipe_source_params_st src; + display_pipe_dest_params_st dest; + scaler_ratio_depth_st scale_ratio_depth; + scaler_taps_st scale_taps; +}; + +struct _vcs_dpi_display_clocks_and_cfg_st { + int voltage; + double dppclk_mhz; + double refclk_mhz; + double dispclk_mhz; + double dcfclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_display_e2e_pipe_params_st { + display_pipe_params_st pipe; + display_output_params_st dout; + display_clocks_and_cfg_st clks_cfg; +}; + +struct _vcs_dpi_dchub_buffer_sizing_st { + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int detail_buffer_size_y; +}; + +struct _vcs_dpi_watermarks_perf_st { + double stutter_eff_in_active_region_percent; + double urgent_latency_supported_us; + double non_urgent_latency_supported_us; + double dram_clock_change_margin_us; + double dram_access_eff_percent; +}; + +struct _vcs_dpi_cstate_pstate_watermarks_st { + double cstate_exit_us; + double cstate_enter_plus_exit_us; + double pstate_change_us; +}; + +struct _vcs_dpi_wm_calc_pipe_params_st { + unsigned int num_dpp; + int voltage; + int output_type; + double dcfclk_mhz; + double socclk_mhz; + double dppclk_mhz; + double pixclk_mhz; + unsigned char interlace_en; + unsigned char pte_enable; + unsigned char dcc_enable; + double dcc_rate; + double bytes_per_pixel_c; + double bytes_per_pixel_y; + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int det_buffer_size_y; + double h_ratio; + double v_ratio; + unsigned int h_taps; + unsigned int h_total; + unsigned int v_total; + unsigned int v_active; + unsigned int e2e_index; + double display_pipe_line_delivery_time; + double read_bw; + unsigned int lines_in_det_y; + unsigned int lines_in_det_y_rounded_down_to_swath; + double full_det_buffering_time; + double dcfclk_deepsleep_mhz_per_plane; +}; + +struct _vcs_dpi_vratio_pre_st { + double vratio_pre_l; + double vratio_pre_c; +}; + +struct _vcs_dpi_display_data_rq_misc_params_st { + unsigned int full_swath_bytes; + unsigned int stored_swath_bytes; + unsigned int blk256_height; + unsigned int blk256_width; + unsigned int req_height; + unsigned int req_width; +}; + +struct _vcs_dpi_display_data_rq_sizing_params_st { + unsigned int chunk_bytes; + unsigned int min_chunk_bytes; + unsigned int meta_chunk_bytes; + unsigned int min_meta_chunk_bytes; + unsigned int mpte_group_bytes; + unsigned int dpte_group_bytes; +}; + +struct _vcs_dpi_display_data_rq_dlg_params_st { + unsigned int swath_width_ub; + unsigned int swath_height; + unsigned int req_per_swath_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int dpte_req_per_row_ub; + unsigned int dpte_groups_per_row_ub; + unsigned int dpte_row_height; + unsigned int dpte_bytes_per_row_ub; + unsigned int meta_chunks_per_row_ub; + unsigned int meta_req_per_row_ub; + unsigned int meta_row_height; + unsigned int meta_bytes_per_row_ub; +}; + +struct _vcs_dpi_display_cur_rq_dlg_params_st { + unsigned char enable; + unsigned int swath_height; + unsigned int req_per_line; +}; + +struct _vcs_dpi_display_rq_dlg_params_st { + display_data_rq_dlg_params_st rq_l; + display_data_rq_dlg_params_st rq_c; + display_cur_rq_dlg_params_st rq_cur0; +}; + +struct _vcs_dpi_display_rq_sizing_params_st { + display_data_rq_sizing_params_st rq_l; + display_data_rq_sizing_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_misc_params_st { + display_data_rq_misc_params_st rq_l; + display_data_rq_misc_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_params_st { + unsigned char yuv420; + unsigned char yuv420_10bpc; + display_rq_misc_params_st misc; + display_rq_sizing_params_st sizing; + display_rq_dlg_params_st dlg; +}; + +struct _vcs_dpi_display_dlg_regs_st { + unsigned int refcyc_h_blank_end; + unsigned int dlg_vblank_end; + unsigned int min_dst_y_next_start; + unsigned int refcyc_per_htotal; + unsigned int refcyc_x_after_scaler; + unsigned int dst_y_after_scaler; + unsigned int dst_y_prefetch; + unsigned int dst_y_per_vm_vblank; + unsigned int dst_y_per_row_vblank; + unsigned int dst_y_per_vm_flip; + unsigned int dst_y_per_row_flip; + unsigned int ref_freq_to_pix_freq; + unsigned int vratio_prefetch; + unsigned int vratio_prefetch_c; + unsigned int refcyc_per_pte_group_vblank_l; + unsigned int refcyc_per_pte_group_vblank_c; + unsigned int refcyc_per_meta_chunk_vblank_l; + unsigned int refcyc_per_meta_chunk_vblank_c; + unsigned int refcyc_per_pte_group_flip_l; + unsigned int refcyc_per_pte_group_flip_c; + unsigned int refcyc_per_meta_chunk_flip_l; + unsigned int refcyc_per_meta_chunk_flip_c; + unsigned int dst_y_per_pte_row_nom_l; + unsigned int dst_y_per_pte_row_nom_c; + unsigned int refcyc_per_pte_group_nom_l; + unsigned int refcyc_per_pte_group_nom_c; + unsigned int dst_y_per_meta_row_nom_l; + unsigned int dst_y_per_meta_row_nom_c; + unsigned int refcyc_per_meta_chunk_nom_l; + unsigned int refcyc_per_meta_chunk_nom_c; + unsigned int refcyc_per_line_delivery_pre_l; + unsigned int refcyc_per_line_delivery_pre_c; + unsigned int refcyc_per_line_delivery_l; + unsigned int refcyc_per_line_delivery_c; + unsigned int chunk_hdl_adjust_cur0; + unsigned int chunk_hdl_adjust_cur1; + unsigned int vready_after_vcount0; + unsigned int dst_y_offset_cur0; + unsigned int dst_y_offset_cur1; + unsigned int xfc_reg_transfer_delay; + unsigned int xfc_reg_precharge_delay; + unsigned int xfc_reg_remote_surface_flip_latency; + unsigned int xfc_reg_prefetch_margin; + unsigned int dst_y_delta_drq_limit; +}; + +struct _vcs_dpi_display_ttu_regs_st { + unsigned int qos_level_low_wm; + unsigned int qos_level_high_wm; + unsigned int min_ttu_vblank; + unsigned int qos_level_flip; + unsigned int refcyc_per_req_delivery_l; + unsigned int refcyc_per_req_delivery_c; + unsigned int refcyc_per_req_delivery_cur0; + unsigned int refcyc_per_req_delivery_cur1; + unsigned int refcyc_per_req_delivery_pre_l; + unsigned int refcyc_per_req_delivery_pre_c; + unsigned int refcyc_per_req_delivery_pre_cur0; + unsigned int refcyc_per_req_delivery_pre_cur1; + unsigned int qos_level_fixed_l; + unsigned int qos_level_fixed_c; + unsigned int qos_level_fixed_cur0; + unsigned int qos_level_fixed_cur1; + unsigned int qos_ramp_disable_l; + unsigned int qos_ramp_disable_c; + unsigned int qos_ramp_disable_cur0; + unsigned int qos_ramp_disable_cur1; +}; + +struct _vcs_dpi_display_data_rq_regs_st { + unsigned int chunk_size; + unsigned int min_chunk_size; + unsigned int meta_chunk_size; + unsigned int min_meta_chunk_size; + unsigned int dpte_group_size; + unsigned int mpte_group_size; + unsigned int swath_height; + unsigned int pte_row_height_linear; +}; + +struct _vcs_dpi_display_rq_regs_st { + display_data_rq_regs_st rq_regs_l; + display_data_rq_regs_st rq_regs_c; + unsigned int drq_expansion_mode; + unsigned int prq_expansion_mode; + unsigned int mrq_expansion_mode; + unsigned int crq_expansion_mode; + unsigned int plane1_base_address; +}; + +struct _vcs_dpi_display_dlg_sys_params_st { + double t_mclk_wm_us; + double t_urg_wm_us; + double t_sr_wm_us; + double t_extra_us; + double mem_trip_us; + double t_srx_delay_us; + double deepsleep_dcfclk_mhz; + double total_flip_bw; + unsigned int total_flip_bytes; +}; + +struct _vcs_dpi_display_dlg_prefetch_param_st { + double prefetch_bw; + unsigned int flip_bytes; +}; + +struct _vcs_dpi_display_pipe_clock_st { + double dcfclk_mhz; + double dispclk_mhz; + double socclk_mhz; + double dscclk_mhz[6]; + double dppclk_mhz[6]; +}; + +struct _vcs_dpi_display_arb_params_st { + int max_req_outstanding; + int min_req_outstanding; + int sat_level_us; }; #endif /*__DISPLAY_MODE_STRUCTS_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c deleted file mode 100644 index 3b4ee74527f5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c +++ /dev/null @@ -1,2326 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "display_mode_support.h" -#include "display_mode_lib.h" - -int dml_ms_check( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - int num_pipes) -{ - struct _vcs_dpi_ip_params_st *ip; - struct _vcs_dpi_soc_bounding_box_st *soc; - struct _vcs_dpi_mode_evaluation_st *me; - struct dml_ms_internal_vars *v; - int num_planes, i, j, ij, k, ijk; - - ip = &(mode_lib->ip); - soc = &(mode_lib->soc); - me = &(mode_lib->me); - v = &(mode_lib->vars); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); - - //instantiating variables to zero - v->MacroTileBlockWidthC = 0; - v->SwathWidthGranularityC = 0; - - v->DCFCLKPerState[5] = 0; - v->DCFCLKPerState[4] = 0; - v->DCFCLKPerState[3] = 0; - v->DCFCLKPerState[2] = 0; - v->DCFCLKPerState[1] = 0; - v->DCFCLKPerState[0] = 0; - - if (soc->vmin.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; - v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; - } - - if (soc->vmid.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; - v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; - } - - if (soc->vnom.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; - v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; - } - - if (soc->vmax.dcfclk_mhz > 0) { - v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; - v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; - v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; - } - - v->FabricAndDRAMBandwidthPerState[5] = 0; - v->FabricAndDRAMBandwidthPerState[4] = 0; - v->FabricAndDRAMBandwidthPerState[3] = 0; - v->FabricAndDRAMBandwidthPerState[2] = 0; - v->FabricAndDRAMBandwidthPerState[1] = 0; - v->FabricAndDRAMBandwidthPerState[0] = 0; - - if (soc->vmin.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; - } - - if (soc->vmid.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; - } - - if (soc->vnom.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; - } - - if (soc->vmax.dram_bw_per_chan_gbps > 0) { - v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; - v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; - } - - v->PHYCLKPerState[5] = 0; - v->PHYCLKPerState[4] = 0; - v->PHYCLKPerState[3] = 0; - v->PHYCLKPerState[2] = 0; - v->PHYCLKPerState[1] = 0; - v->PHYCLKPerState[0] = 0; - - if (soc->vmin.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; - v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; - } - - if (soc->vmid.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; - v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; - } - - if (soc->vnom.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; - v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; - } - - if (soc->vmax.phyclk_mhz > 0) { - v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; - v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; - v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; - } - - v->MaxDispclk[5] = 0; - v->MaxDispclk[4] = 0; - v->MaxDispclk[3] = 0; - v->MaxDispclk[2] = 0; - v->MaxDispclk[1] = 0; - v->MaxDispclk[0] = 0; - - if (soc->vmin.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmin.dispclk_mhz; - v->MaxDispclk[4] = soc->vmin.dispclk_mhz; - v->MaxDispclk[3] = soc->vmin.dispclk_mhz; - v->MaxDispclk[2] = soc->vmin.dispclk_mhz; - v->MaxDispclk[1] = soc->vmin.dispclk_mhz; - v->MaxDispclk[0] = soc->vmin.dispclk_mhz; - } - - if (soc->vmid.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmid.dispclk_mhz; - v->MaxDispclk[4] = soc->vmid.dispclk_mhz; - v->MaxDispclk[3] = soc->vmid.dispclk_mhz; - v->MaxDispclk[2] = soc->vmid.dispclk_mhz; - v->MaxDispclk[1] = soc->vmid.dispclk_mhz; - } - - if (soc->vnom.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vnom.dispclk_mhz; - v->MaxDispclk[4] = soc->vnom.dispclk_mhz; - v->MaxDispclk[3] = soc->vnom.dispclk_mhz; - v->MaxDispclk[2] = soc->vnom.dispclk_mhz; - } - - if (soc->vmax.dispclk_mhz > 0) { - v->MaxDispclk[5] = soc->vmax.dispclk_mhz; - v->MaxDispclk[4] = soc->vmax.dispclk_mhz; - v->MaxDispclk[3] = soc->vmax.dispclk_mhz; - } - - v->MaxDppclk[5] = 0; - v->MaxDppclk[4] = 0; - v->MaxDppclk[3] = 0; - v->MaxDppclk[2] = 0; - v->MaxDppclk[1] = 0; - v->MaxDppclk[0] = 0; - - if (soc->vmin.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmin.dppclk_mhz; - v->MaxDppclk[4] = soc->vmin.dppclk_mhz; - v->MaxDppclk[3] = soc->vmin.dppclk_mhz; - v->MaxDppclk[2] = soc->vmin.dppclk_mhz; - v->MaxDppclk[1] = soc->vmin.dppclk_mhz; - v->MaxDppclk[0] = soc->vmin.dppclk_mhz; - } - - if (soc->vmid.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmid.dppclk_mhz; - v->MaxDppclk[4] = soc->vmid.dppclk_mhz; - v->MaxDppclk[3] = soc->vmid.dppclk_mhz; - v->MaxDppclk[2] = soc->vmid.dppclk_mhz; - v->MaxDppclk[1] = soc->vmid.dppclk_mhz; - } - - if (soc->vnom.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vnom.dppclk_mhz; - v->MaxDppclk[4] = soc->vnom.dppclk_mhz; - v->MaxDppclk[3] = soc->vnom.dppclk_mhz; - v->MaxDppclk[2] = soc->vnom.dppclk_mhz; - } - - if (soc->vmax.dppclk_mhz > 0) { - v->MaxDppclk[5] = soc->vmax.dppclk_mhz; - v->MaxDppclk[4] = soc->vmax.dppclk_mhz; - v->MaxDppclk[3] = soc->vmax.dppclk_mhz; - } - - if (me->voltage_override == dm_vmax) { - v->VoltageOverrideLevel = NumberOfStates - 1; - } else if (me->voltage_override == dm_vnom) { - v->VoltageOverrideLevel = NumberOfStates - 2; - } else if (me->voltage_override == dm_vmid) { - v->VoltageOverrideLevel = NumberOfStates - 3; - } else { - v->VoltageOverrideLevel = 0; - } - - // Scale Ratio Support Check - - v->ScaleRatioSupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio - || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio - || scale_ratio_depth.hscl_ratio > scale_taps.htaps - || scale_ratio_depth.vscl_ratio > scale_taps.vtaps - || (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16 - && ((scale_ratio_depth.hscl_ratio / 2 - > scale_taps.htaps_c) - || (scale_ratio_depth.vscl_ratio / 2 - > scale_taps.vtaps_c)))) - - { - v->ScaleRatioSupport = 0; - } - } - - // Source Format, Pixel Format and Scan Support Check - - v->SourceFormatPixelAndScanSupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) - || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x - || src.sw_mode == dm_sw_var_d - || src.sw_mode == dm_sw_var_d_x) - && (src.source_format != dm_444_64))) { - v->SourceFormatPixelAndScanSupport = 0; - } - } - - // Bandwidth Support Check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.source_scan == dm_horz) { - v->SwathWidthYSingleDPP[k] = src.viewport_width; - } else { - v->SwathWidthYSingleDPP[k] = src.viewport_height; - } - - if (src.source_format == dm_444_64) { - v->BytePerPixelInDETY[k] = 8; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_444_32) { - v->BytePerPixelInDETY[k] = 4; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_444_16) { - v->BytePerPixelInDETY[k] = 2; - v->BytePerPixelInDETC[k] = 0; - } else if (src.source_format == dm_420_8) { - v->BytePerPixelInDETY[k] = 1; - v->BytePerPixelInDETC[k] = 2; - } else { - v->BytePerPixelInDETY[k] = 4.00 / 3.00; - v->BytePerPixelInDETC[k] = 8.00 / 3.00; - } - } - - v->TotalReadBandwidthConsumedGBytePerSecond = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - - v->ReadBandwidth[k] = - v->SwathWidthYSingleDPP[k] - * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - * scale_ratio_depth.vscl_ratio - + (dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) / 2) - * (scale_ratio_depth.vscl_ratio - / 2)) - / (dest.htotal / dest.pixel_rate_mhz); - - if (src.dcc == 1) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); - } - - if (ip->pte_enable == 1 && src.source_scan != dm_horz - && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x)) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); - } else if (ip->pte_enable == 1 && src.source_scan == dm_horz - && (src.source_format == dm_444_64 || src.source_format == dm_444_32) - && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x)) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); - } else if (ip->pte_enable == 1) { - v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); - } - - v->TotalReadBandwidthConsumedGBytePerSecond = - v->TotalReadBandwidthConsumedGBytePerSecond - + v->ReadBandwidth[k] / 1000; - } - - v->TotalWriteBandwidthConsumedGBytePerSecond = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb && dout.output_format == dm_444) { - v->WriteBandwidth[k] = dest.recout_width - / (dest.htotal / dest.pixel_rate_mhz) * 4; - } else if (dout.output_type == dm_wb) { - v->WriteBandwidth[k] = dest.recout_width - / (dest.htotal / dest.pixel_rate_mhz) * 1.5; - } else { - v->WriteBandwidth[k] = 0; - } - - v->TotalWriteBandwidthConsumedGBytePerSecond = - v->TotalWriteBandwidthConsumedGBytePerSecond - + v->WriteBandwidth[k] / 1000; - } - - v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond - + v->TotalWriteBandwidthConsumedGBytePerSecond; - - v->DCCEnabledInAnyPlane = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.dcc == 1) { - v->DCCEnabledInAnyPlane = 1; - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->ReturnBWToDCNPerState = dml_min( - soc->return_bus_width_bytes * v->DCFCLKPerState[i], - v->FabricAndDRAMBandwidthPerState[i] * 1000 - * soc->ideal_dram_bw_after_urgent_percent / 100); - - v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; - - if (v->DCCEnabledInAnyPlane == 1 - && v->ReturnBWToDCNPerState - > (v->DCFCLKPerState[i] - * soc->return_bus_width_bytes / 4)) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - v->ReturnBWToDCNPerState * 4 - * (1 - - soc->urgent_latency_us - / ((ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - / (v->ReturnBWToDCNPerState - - v->DCFCLKPerState[i] - * soc->return_bus_width_bytes - / 4) - + soc->urgent_latency_us))); - } - - v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / (v->ReturnBWToDCNPerState * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024); - - if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - 4 * v->ReturnBWToDCNPerState - * (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - * soc->return_bus_width_bytes - * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / dml_pow( - (v->ReturnBWToDCNPerState - * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024), - 2)); - } - - v->ReturnBWToDCNPerState = dml_min( - soc->return_bus_width_bytes * v->DCFCLKPerState[i], - v->FabricAndDRAMBandwidthPerState[i] * 1000); - - if (v->DCCEnabledInAnyPlane == 1 - && v->ReturnBWToDCNPerState - > (v->DCFCLKPerState[i] - * soc->return_bus_width_bytes / 4)) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - v->ReturnBWToDCNPerState * 4 - * (1 - - soc->urgent_latency_us - / ((ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - / (v->ReturnBWToDCNPerState - - v->DCFCLKPerState[i] - * soc->return_bus_width_bytes - / 4) - + soc->urgent_latency_us))); - } - - v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / (v->ReturnBWToDCNPerState * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024); - - if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { - v->ReturnBWPerState[i] = - dml_min( - v->ReturnBWPerState[i], - 4 * v->ReturnBWToDCNPerState - * (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024 - * soc->return_bus_width_bytes - * v->DCFCLKPerState[i] - * soc->urgent_latency_us - / dml_pow( - (v->ReturnBWToDCNPerState - * soc->urgent_latency_us - + (ip->rob_buffer_size_kbytes - - ip->pixel_chunk_size_kbytes) - * 1024), - 2)); - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) - && (v->TotalBandwidthConsumedGBytePerSecond * 1000 - <= v->FabricAndDRAMBandwidthPerState[i] * 1000 - * soc->ideal_dram_bw_after_urgent_percent - / 100)) { - v->BandwidthSupport[i] = 1; - } else { - v->BandwidthSupport[i] = 0; - } - } - - // Writeback Latency support check - - v->WritebackLatencySupport = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb && dout.output_format == dm_444 - && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) - > ((ip->writeback_luma_buffer_size_kbytes - + ip->writeback_chroma_buffer_size_kbytes) - * 1024 / soc->writeback_latency_us)) { - v->WritebackLatencySupport = 0; - } else if (dout.output_type == dm_wb - && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) - > (dml_min( - ip->writeback_luma_buffer_size_kbytes, - 2 - * ip->writeback_chroma_buffer_size_kbytes) - * 1024 / soc->writeback_latency_us)) { - v->WritebackLatencySupport = 0; - } - } - - // Re-ordering Buffer Support Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = - (soc->round_trip_ping_latency_dcfclk_cycles + 32) - / v->DCFCLKPerState[i] - + soc->urgent_out_of_order_return_per_channel_bytes - * soc->num_chans - / v->ReturnBWPerState[i]; - - if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 - / v->ReturnBWPerState[i] - > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { - v->ROBSupport[i] = 1; - } else { - v->ROBSupport[i] = 0; - } - } - - // Display IO Support Check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_format == dm_420) { - v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; - } else { - v->RequiredOutputBW = dest.pixel_rate_mhz * 3; - } - - if (dout.output_type == dm_hdmi) { - v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; - } else if (dout.output_type == dm_dp) { - v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; - } else { - v->RequiredPHYCLK[k] = 0; - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - v->DIOSupport[i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_output_params_st dout = - e2e[v->planes[k].e2e_index].dout; - - if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) - || (dout.output_type == dm_hdmi - && v->RequiredPHYCLK[k] > 600)) { - v->DIOSupport[i] = 0; - } - } - } - - // Total Available Writeback Support Check - - v->TotalNumberOfActiveWriteback = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; - - if (dout.output_type == dm_wb) { - v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; - } - } - - if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { - v->TotalAvailableWritebackSupport = 1; - } else { - v->TotalAvailableWritebackSupport = 0; - } - - // Maximum DISPCLK/DPPCLK Support check - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - - if (scale_ratio_depth.hscl_ratio > 1) { - v->PSCL_FACTOR[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk - * scale_ratio_depth.hscl_ratio - / dml_ceil_ex(scale_taps.htaps / 6, 1)); - } else { - v->PSCL_FACTOR[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk); - } - - if (v->BytePerPixelInDETC[k] == 0) { - v->PSCL_FACTOR_CHROMA[k] = 0; - v->MinDPPCLKUsingSingleDPP[k] = - dest.pixel_rate_mhz - * dml_max( - scale_taps.vtaps / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio), - dml_max( - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / v->PSCL_FACTOR[k], - 1)); - - } else { - if (scale_ratio_depth.hscl_ratio / 2 > 1) { - v->PSCL_FACTOR_CHROMA[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk - * scale_ratio_depth.hscl_ratio / 2 - / dml_ceil_ex( - scale_taps.htaps_c - / 6, - 1)); - } else { - v->PSCL_FACTOR_CHROMA[k] = dml_min( - ip->max_dchub_pscl_bw_pix_per_clk, - ip->max_pscl_lb_bw_pix_per_clk); - } - v->MinDPPCLKUsingSingleDPP[k] = - dest.pixel_rate_mhz - * dml_max( - dml_max( - scale_taps.vtaps - / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio), - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / v->PSCL_FACTOR[k]), - dml_max( - dml_max( - scale_taps.vtaps_c - / 6 - * dml_min( - 1, - scale_ratio_depth.hscl_ratio - / 2), - scale_ratio_depth.hscl_ratio - * scale_ratio_depth.vscl_ratio - / 4 - / v->PSCL_FACTOR_CHROMA[k]), - 1)); - - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - - if (src.source_format == dm_444_64 || src.source_format == dm_444_32 - || src.source_format == dm_444_16) { - if (src.sw_mode == dm_sw_linear) { - v->Read256BlockHeightY[k] = 1; - } else if (src.source_format == dm_444_64) { - v->Read256BlockHeightY[k] = 4; - } else { - v->Read256BlockHeightY[k] = 8; - } - - v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->Read256BlockHeightY[k]; - v->Read256BlockHeightC[k] = 0; - v->Read256BlockWidthC[k] = 0; - } else { - if (src.sw_mode == dm_sw_linear) { - v->Read256BlockHeightY[k] = 1; - v->Read256BlockHeightC[k] = 1; - } else if (src.source_format == dm_420_8) { - v->Read256BlockHeightY[k] = 16; - v->Read256BlockHeightC[k] = 8; - } else { - v->Read256BlockHeightY[k] = 8; - v->Read256BlockHeightC[k] = 8; - } - - v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->Read256BlockHeightY[k]; - v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) - / v->Read256BlockHeightC[k]; - } - - if (src.source_scan == dm_horz) { - v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; - v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; - } else { - v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; - v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; - } - - if (src.source_format == dm_444_64 || src.source_format == dm_444_32 - || src.source_format == dm_444_16) { - if (src.sw_mode == dm_sw_linear - || (src.source_format == dm_444_64 - && (src.sw_mode == dm_sw_4kb_s - || src.sw_mode - == dm_sw_4kb_s_x - || src.sw_mode - == dm_sw_64kb_s - || src.sw_mode - == dm_sw_64kb_s_t - || src.sw_mode - == dm_sw_64kb_s_x - || src.sw_mode - == dm_sw_var_s - || src.sw_mode - == dm_sw_var_s_x) - && src.source_scan == dm_horz)) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - } - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else { - if (src.sw_mode == dm_sw_linear) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - if (ip->bug_forcing_LC_req_same_size_fixed == 1) { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } else { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; - } - } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; - if (ip->bug_forcing_LC_req_same_size_fixed == 1) { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; - } - } else { - v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; - v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; - } - } - - if (src.sw_mode == dm_sw_linear) { - v->MaximumSwathWidth = 8192; - } else { - v->MaximumSwathWidth = 5120; - } - - v->NumberOfDPPRequiredForDETSize = - dml_ceil_ex( - v->SwathWidthYSingleDPP[k] - / dml_min( - v->MaximumSwathWidth, - ip->det_buffer_size_kbytes - * 1024 - / 2 - / (v->BytePerPixelInDETY[k] - * v->MinSwathHeightY[k] - + v->BytePerPixelInDETC[k] - / 2 - * v->MinSwathHeightC[k])), - 1); - - if (v->BytePerPixelInDETC[k] == 0) { - v->NumberOfDPPRequiredForLBSize = - dml_ceil_ex( - (scale_taps.vtaps - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1); - } else { - v->NumberOfDPPRequiredForLBSize = - dml_max( - dml_ceil_ex( - (scale_taps.vtaps - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1), - dml_ceil_ex( - (scale_taps.vtaps_c - + dml_max( - dml_ceil_ex( - scale_ratio_depth.vscl_ratio - / 2, - 1) - - 2, - 0)) - * v->SwathWidthYSingleDPP[k] - / 2 - / dml_max( - scale_ratio_depth.hscl_ratio - / 2, - 1) - * scale_ratio_depth.lb_depth - / ip->line_buffer_size_bits, - 1)); - } - - v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( - v->NumberOfDPPRequiredForDETSize, - v->NumberOfDPPRequiredForLBSize); - - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->MinDispclkUsingSingleDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) - * (1 + soc->downspread_percent / 100); - v->MinDispclkUsingDualDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) - * (1 + soc->downspread_percent / 100); - - if (i < NumberOfStates) { - v->MinDispclkUsingSingleDPP = - v->MinDispclkUsingSingleDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - v->MinDispclkUsingDualDPP = - v->MinDispclkUsingDualDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - } - - if (v->MinDispclkUsingSingleDPP - <= dml_min( - v->MaxDispclk[i], - (j + 1) * v->MaxDppclk[i]) - && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { - v->NoOfDPP[ijk] = 1; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingSingleDPP); - } else if (v->MinDispclkUsingDualDPP - <= dml_min( - v->MaxDispclk[i], - (j + 1) * v->MaxDppclk[i])) { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - } else { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = - 0; - } - - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo - + i] + v->NoOfDPP[ijk]; - } - - if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] - > ip->max_num_dpp) { - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; - v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo - + j * NumberOfStatesPlusTwo + i; - - v->MinDispclkUsingSingleDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) - * (1 + soc->downspread_percent / 100); - v->MinDispclkUsingDualDPP = dml_max( - dest.pixel_rate_mhz, - v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) - * (1 + soc->downspread_percent / 100); - - if (i < NumberOfStates) { - v->MinDispclkUsingSingleDPP = - v->MinDispclkUsingSingleDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - v->MinDispclkUsingDualDPP = - v->MinDispclkUsingDualDPP - * (1 - + ip->dispclk_ramp_margin_percent - / 100); - } - - if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { - v->NoOfDPP[ijk] = 1; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = - dml_max( - v->RequiredDISPCLK[j - * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingSingleDPP); - if (v->MinDispclkUsingSingleDPP - > dml_min( - v->MaxDispclk[i], - (j + 1) - * v->MaxDppclk[i])) { - v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + i] = - 0; - } - } else { - v->NoOfDPP[ijk] = 2; - v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = - dml_max( - v->RequiredDISPCLK[j - * NumberOfStatesPlusTwo - + i], - v->MinDispclkUsingDualDPP); - if (v->MinDispclkUsingDualDPP - > dml_min( - v->MaxDispclk[i], - (j + 1) - * v->MaxDppclk[i])) { - v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + i] = - 0; - } - } - v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = - v->TotalNumberOfActiveDPP[j - * NumberOfStatesPlusTwo + i] - + v->NoOfDPP[ijk]; - } - } - } - } - - // Viewport Size Check - - v->ViewportSizeSupport = 1; - - for (k = 0; k < num_planes; k++) { - if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { - v->ViewportSizeSupport = 0; - } - } - - // Total Available Pipes Support Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] - <= ip->max_num_dpp) { - v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; - } else { - v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; - } - } - } - - // Urgent Latency Support Check - - for (j = 0; j < 2; j++) { - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - ij = j * NumberOfStatesPlusTwo + i; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] - / v->NoOfDPP[ijk]; - - v->SwathWidthGranularityY = 256 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->MaxSwathHeightY[k]; - v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( - v->SwathWidthYPerState[ijk] - 1, - v->SwathWidthGranularityY) - + v->SwathWidthGranularityY) - * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; - if (src.source_format == dm_420_10) { - v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( - v->RoundedUpMaxSwathSizeBytesY, - 256) + 256; - } - if (v->MaxSwathHeightC[k] > 0) { - v->SwathWidthGranularityC = 256 - / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) - / v->MaxSwathHeightC[k]; - } - v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( - v->SwathWidthYPerState[ijk] / 2 - 1, - v->SwathWidthGranularityC) - + v->SwathWidthGranularityC) - * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; - if (src.source_format == dm_420_10) { - v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( - v->RoundedUpMaxSwathSizeBytesC, - 256) + 256; - } - - if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC - <= ip->det_buffer_size_kbytes * 1024 / 2) { - v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; - v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; - } else { - v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; - v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; - } - - if (v->BytePerPixelInDETC[k] == 0) { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 - / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - - v->LinesInDETChroma = 0; - } else if (v->SwathHeightYPerState[ijk] - <= v->SwathHeightCPerState[ijk]) { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 - / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 - / v->BytePerPixelInDETC[k] - / (v->SwathWidthYPerState[ijk] / 2); - } else { - v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 - / 3 / v->BytePerPixelInDETY[k] - / v->SwathWidthYPerState[ijk]; - v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 - / v->BytePerPixelInDETY[k] - / (v->SwathWidthYPerState[ijk] / 2); - } - - v->EffectiveLBLatencyHidingSourceLinesLuma = - dml_min( - ip->max_line_buffer_lines, - dml_floor_ex( - ip->line_buffer_size_bits - / scale_ratio_depth.lb_depth - / (v->SwathWidthYPerState[ijk] - / dml_max( - scale_ratio_depth.hscl_ratio, - 1)), - 1)) - - (scale_taps.vtaps - 1); - - v->EffectiveLBLatencyHidingSourceLinesChroma = - dml_min( - ip->max_line_buffer_lines, - dml_floor_ex( - ip->line_buffer_size_bits - / scale_ratio_depth.lb_depth - / (v->SwathWidthYPerState[ijk] - / 2 - / dml_max( - scale_ratio_depth.hscl_ratio - / 2, - 1)), - 1)) - - (scale_taps.vtaps_c - 1); - - v->EffectiveDETLBLinesLuma = - dml_floor_ex( - v->LinesInDETLuma - + dml_min( - v->LinesInDETLuma - * v->RequiredDISPCLK[ij] - * v->BytePerPixelInDETY[k] - * v->PSCL_FACTOR[k] - / v->ReturnBWPerState[i], - v->EffectiveLBLatencyHidingSourceLinesLuma), - v->SwathHeightYPerState[ijk]); - - v->EffectiveDETLBLinesChroma = - dml_floor_ex( - v->LinesInDETChroma - + dml_min( - v->LinesInDETChroma - * v->RequiredDISPCLK[ij] - * v->BytePerPixelInDETC[k] - * v->PSCL_FACTOR_CHROMA[k] - / v->ReturnBWPerState[i], - v->EffectiveLBLatencyHidingSourceLinesChroma), - v->SwathHeightCPerState[ijk]); - - if (v->BytePerPixelInDETC[k] == 0) { - v->UrgentLatencySupportUsPerState[ijk] = - v->EffectiveDETLBLinesLuma - * (dest.htotal - / dest.pixel_rate_mhz) - / scale_ratio_depth.vscl_ratio - - v->EffectiveDETLBLinesLuma - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk]); - } else { - v->UrgentLatencySupportUsPerState[ijk] = - dml_min( - v->EffectiveDETLBLinesLuma - * (dest.htotal - / dest.pixel_rate_mhz) - / scale_ratio_depth.vscl_ratio - - v->EffectiveDETLBLinesLuma - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk]), - v->EffectiveDETLBLinesChroma - * (dest.htotal - / dest.pixel_rate_mhz) - / (scale_ratio_depth.vscl_ratio - / 2) - - v->EffectiveDETLBLinesChroma - * v->SwathWidthYPerState[ijk] - / 2 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / (v->ReturnBWPerState[i] - / v->NoOfDPP[ijk])); - } - - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->UrgentLatencySupport[ij] = 1; - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (v->UrgentLatencySupportUsPerState[ijk] - < soc->urgent_latency_us / 1) { - v->UrgentLatencySupport[ij] = 0; - } - } - } - } - - // Prefetch Check - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->TotalNumberOfDCCActiveDPP[ij] = 0; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.dcc == 1) { - v->TotalNumberOfDCCActiveDPP[ij] = - v->TotalNumberOfDCCActiveDPP[ij] - + v->NoOfDPP[ijk]; - } - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->ProjectedDCFCLKDeepSleep = 8; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->ProjectedDCFCLKDeepSleep = dml_max( - v->ProjectedDCFCLKDeepSleep, - dest.pixel_rate_mhz / 16); - if (v->BytePerPixelInDETC[k] == 0) { - if (scale_ratio_depth.vscl_ratio <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 64 - * scale_ratio_depth.hscl_ratio - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 64 - * v->PSCL_FACTOR[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - - } else { - if (scale_ratio_depth.vscl_ratio <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 32 - * scale_ratio_depth.hscl_ratio - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 32 - * v->PSCL_FACTOR[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 32 - * scale_ratio_depth.hscl_ratio - / 2 - * dest.pixel_rate_mhz - / v->NoOfDPP[ijk]); - } else { - v->ProjectedDCFCLKDeepSleep = - dml_max( - v->ProjectedDCFCLKDeepSleep, - 1.1 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 32 - * v->PSCL_FACTOR_CHROMA[k] - * v->RequiredDISPCLK[ij] - / (1 - + j)); - } - - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = - e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; - struct _vcs_dpi_scaler_taps_st scale_taps = - e2e[v->planes[k].e2e_index].pipe.scale_taps; - struct _vcs_dpi_display_output_params_st dout = - e2e[v->planes[k].e2e_index].dout; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.dcc == 1) { - v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; - v->MetaReqWidthY = 64 * 256 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->MetaReqHeightY; - v->MetaSurfaceWidthY = dml_ceil_ex( - src.viewport_width / v->NoOfDPP[ijk] - 1, - v->MetaReqWidthY) + v->MetaReqWidthY; - v->MetaSurfaceHeightY = dml_ceil_ex( - src.viewport_height - 1, - v->MetaReqHeightY) + v->MetaReqHeightY; - if (ip->pte_enable == 1) { - v->MetaPteBytesPerFrameY = - (dml_ceil_ex( - (v->MetaSurfaceWidthY - * v->MetaSurfaceHeightY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256.0 - - 4096) - / 8 - / 4096, - 1) + 1) * 64; - } else { - v->MetaPteBytesPerFrameY = 0; - } - if (src.source_scan == dm_horz) { - v->MetaRowBytesY = - v->MetaSurfaceWidthY - * v->MetaReqHeightY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256; - } else { - v->MetaRowBytesY = - v->MetaSurfaceHeightY - * v->MetaReqWidthY - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - / 256; - } - } else { - v->MetaPteBytesPerFrameY = 0; - v->MetaRowBytesY = 0; - } - - if (ip->pte_enable == 1) { - if (src.sw_mode == dm_sw_linear) { - v->MacroTileBlockSizeBytesY = 256; - v->MacroTileBlockHeightY = 1; - } else if (src.sw_mode == dm_sw_4kb_s - || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x) { - v->MacroTileBlockSizeBytesY = 4096; - v->MacroTileBlockHeightY = 4 - * v->Read256BlockHeightY[k]; - } else if (src.sw_mode == dm_sw_64kb_s - || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x) { - v->MacroTileBlockSizeBytesY = 64 * 1024; - v->MacroTileBlockHeightY = 16 - * v->Read256BlockHeightY[k]; - } else { - v->MacroTileBlockSizeBytesY = 256 * 1024; - v->MacroTileBlockHeightY = 32 - * v->Read256BlockHeightY[k]; - } - if (v->MacroTileBlockSizeBytesY <= 65536) { - v->DataPTEReqHeightY = v->MacroTileBlockHeightY; - } else { - v->DataPTEReqHeightY = 16 - * v->Read256BlockHeightY[k]; - } - v->DataPTEReqWidthY = 4096 - / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) - / v->DataPTEReqHeightY * 8; - if (src.sw_mode == dm_sw_linear) { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - * dml_min( - 128, - dml_pow( - 2, - dml_floor_ex( - dml_log( - ip->dpte_buffer_size_in_pte_reqs - * v->DataPTEReqWidthY - / (src.viewport_width - / v->NoOfDPP[ijk]), - 2), - 1))) - - 1) - / v->DataPTEReqWidthY, - 1) - + 1); - } else if (src.source_scan == dm_horz) { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - - 1) - / v->DataPTEReqWidthY, - 1) - + 1); - } else { - v->DPTEBytesPerRowY = - 64 - * (dml_ceil_ex( - (src.viewport_height - - 1) - / v->DataPTEReqHeightY, - 1) - + 1); - } - } else { - v->DPTEBytesPerRowY = 0; - } - - if (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16) { - if (src.dcc == 1) { - v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; - v->MetaReqWidthC = - 64 * 256 - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->MetaReqHeightC; - v->MetaSurfaceWidthC = dml_ceil_ex( - src.viewport_width / v->NoOfDPP[ijk] - / 2 - 1, - v->MetaReqWidthC) - + v->MetaReqWidthC; - v->MetaSurfaceHeightC = dml_ceil_ex( - src.viewport_height / 2 - 1, - v->MetaReqHeightC) - + v->MetaReqHeightC; - if (ip->pte_enable == 1) { - v->MetaPteBytesPerFrameC = - (dml_ceil_ex( - (v->MetaSurfaceWidthC - * v->MetaSurfaceHeightC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256.0 - - 4096) - / 8 - / 4096, - 1) + 1) - * 64; - } else { - v->MetaPteBytesPerFrameC = 0; - } - if (src.source_scan == dm_horz) { - v->MetaRowBytesC = - v->MetaSurfaceWidthC - * v->MetaReqHeightC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256; - } else { - v->MetaRowBytesC = - v->MetaSurfaceHeightC - * v->MetaReqWidthC - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 256; - } - } else { - v->MetaPteBytesPerFrameC = 0; - v->MetaRowBytesC = 0; - } - - if (ip->pte_enable == 1) { - if (src.sw_mode == dm_sw_linear) { - v->MacroTileBlockSizeBytesC = 256; - v->MacroTileBlockHeightC = 1; - } else if (src.sw_mode == dm_sw_4kb_s - || src.sw_mode == dm_sw_4kb_s_x - || src.sw_mode == dm_sw_4kb_d - || src.sw_mode == dm_sw_4kb_d_x) { - v->MacroTileBlockSizeBytesC = 4096; - v->MacroTileBlockHeightC = 4 - * v->Read256BlockHeightC[k]; - } else if (src.sw_mode == dm_sw_64kb_s - || src.sw_mode == dm_sw_64kb_s_t - || src.sw_mode == dm_sw_64kb_s_x - || src.sw_mode == dm_sw_64kb_d - || src.sw_mode == dm_sw_64kb_d_t - || src.sw_mode == dm_sw_64kb_d_x) { - v->MacroTileBlockSizeBytesC = 64 * 1024; - v->MacroTileBlockHeightC = 16 - * v->Read256BlockHeightC[k]; - } else { - v->MacroTileBlockSizeBytesC = 256 * 1024; - v->MacroTileBlockHeightC = 32 - * v->Read256BlockHeightC[k]; - } - v->MacroTileBlockWidthC = - v->MacroTileBlockSizeBytesC - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->MacroTileBlockHeightC; - if (v->MacroTileBlockSizeBytesC <= 65536) { - v->DataPTEReqHeightC = - v->MacroTileBlockHeightC; - } else { - v->DataPTEReqHeightC = 16 - * v->Read256BlockHeightC[k]; - } - v->DataPTEReqWidthC = - 4096 - / dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / v->DataPTEReqHeightC - * 8; - if (src.sw_mode == dm_sw_linear) { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - / 2 - * dml_min( - 128, - dml_pow( - 2, - dml_floor_ex( - dml_log( - ip->dpte_buffer_size_in_pte_reqs - * v->DataPTEReqWidthC - / (src.viewport_width - / v->NoOfDPP[ijk] - / 2), - 2), - 1))) - - 1) - / v->DataPTEReqWidthC, - 1) - + 1); - } else if (src.source_scan == dm_horz) { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_width - / v->NoOfDPP[ijk] - / 2 - - 1) - / v->DataPTEReqWidthC, - 1) - + 1); - } else { - v->DPTEBytesPerRowC = - 64 - * (dml_ceil_ex( - (src.viewport_height - / 2 - - 1) - / v->DataPTEReqHeightC, - 1) - + 1); - } - } else { - v->DPTEBytesPerRowC = 0; - } - } else { - v->DPTEBytesPerRowC = 0; - v->MetaPteBytesPerFrameC = 0; - v->MetaRowBytesC = 0; - } - - v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; - v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY - + v->MetaPteBytesPerFrameC; - v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; - - v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 - + dest.interlaced * 0.5 - * scale_ratio_depth.vscl_ratio) - / 2.0; - v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); - v->MaxNumSwY[k] = dml_ceil_ex( - (v->PrefillY[k] - 1.0) - / v->SwathHeightYPerState[ijk], - 1) + 1.0; - - if (v->PrefillY[k] > 1) { - v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) - % ((int) v->SwathHeightYPerState[ijk]); - } else { - v->MaxPartialSwY = ((int) (v->PrefillY[k] - + v->SwathHeightYPerState[ijk] - 2)) - % ((int) v->SwathHeightYPerState[ijk]); - } - v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); - - v->PrefetchLinesY[k] = v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; - - if (src.source_format != dm_444_64 && src.source_format != dm_444_32 - && src.source_format != dm_444_16) { - v->VInitC = - (scale_ratio_depth.vscl_ratio / 2 - + scale_taps.vtaps + 1 - + dest.interlaced * 0.5 - * scale_ratio_depth.vscl_ratio - / 2) / 2.0; - v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); - v->MaxNumSwC[k] = - dml_ceil_ex( - (v->PrefillC[k] - 1.0) - / v->SwathHeightCPerState[ijk], - 1) + 1.0; - if (v->PrefillC[k] > 1) { - v->MaxPartialSwC = - ((int) (v->PrefillC[k] - 2)) - % ((int) v->SwathHeightCPerState[ijk]); - } else { - v->MaxPartialSwC = - ((int) (v->PrefillC[k] - + v->SwathHeightCPerState[ijk] - - 2)) - % ((int) v->SwathHeightCPerState[ijk]); - } - v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); - - v->PrefetchLinesC[k] = v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk] - + v->MaxPartialSwC; - } else { - v->PrefetchLinesC[k] = 0; - } - - v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz - / (v->RequiredDISPCLK[ij] / (j + 1)) - + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; - if (v->NoOfDPP[ijk] > 1) { - v->dst_x_after_scaler = v->dst_x_after_scaler - + dest.recout_width / 2.0; - } - - if (dout.output_format == dm_420) { - v->dst_y_after_scaler = 1; - } else { - v->dst_y_after_scaler = 0; - } - - v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; - - v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); - v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters - * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) - + 3 / v->RequiredDISPCLK[ij]); - v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep - + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) - + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; - v->VReadyOffset = - dml_max( - 150 - / (v->RequiredDISPCLK[ij] - / (j - + 1)), - v->TotalRepeaterDelay - + 20 - / v->ProjectedDCFCLKDeepSleep - + 10 - / (v->RequiredDISPCLK[ij] - / (j - + 1))) - * dest.pixel_rate_mhz; - - v->TimeSetup = - (v->VUpdateOffset + v->VUpdateWidth - + v->VReadyOffset) - / dest.pixel_rate_mhz; - - v->ExtraLatency = - v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] - + (v->TotalNumberOfActiveDPP[ij] - * ip->pixel_chunk_size_kbytes - + v->TotalNumberOfDCCActiveDPP[ij] - * ip->meta_chunk_size_kbytes) - * 1024 - / v->ReturnBWPerState[i]; - - if (ip->pte_enable == 1) { - v->ExtraLatency = v->ExtraLatency - + v->TotalNumberOfActiveDPP[ij] - * ip->pte_chunk_size_kbytes - * 1024 - / v->ReturnBWPerState[i]; - } - - if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one - == 1) { - v->MaximumVStartup = dest.vtotal - dest.vactive - 1; - } else { - v->MaximumVStartup = dest.vsync_plus_back_porch - 1; - } - - v->LineTimesForPrefetch[k] = - v->MaximumVStartup - - soc->urgent_latency_us - / (dest.htotal - / dest.pixel_rate_mhz) - - (v->TimeCalc + v->TimeSetup) - / (dest.htotal - / dest.pixel_rate_mhz) - - (v->dst_y_after_scaler - + v->dst_x_after_scaler - / dest.htotal); - - v->LineTimesForPrefetch[k] = dml_floor_ex( - 4.0 * (v->LineTimesForPrefetch[k] + 0.125), - 1) / 4; - - v->PrefetchBW[k] = - (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] - + 2 * v->DPTEBytesPerRow[k] - + v->PrefetchLinesY[k] - * v->SwathWidthYPerState[ijk] - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - * v->SwathWidthYPerState[ijk] - / 2 - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2)) - / (v->LineTimesForPrefetch[k] - * dest.htotal - / dest.pixel_rate_mhz); - } - - v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; - - for (k = 0; k < num_planes; k++) { - v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip - - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); - } - - v->TotalImmediateFlipBytes = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - - if (src.source_format != dm_420_8 - && src.source_format != dm_420_10) { - v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes - + v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]; - } - } - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (ip->pte_enable == 1 && src.dcc == 1) { - v->TimeForMetaPTEWithImmediateFlip = - dml_max( - v->MetaPTEBytesPerFrame[k] - / v->PrefetchBW[k], - dml_max( - v->MetaPTEBytesPerFrame[k] - * v->TotalImmediateFlipBytes - / (v->BWAvailableForImmediateFlip - * (v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k])), - dml_max( - v->ExtraLatency, - dml_max( - soc->urgent_latency_us, - dest.htotal - / dest.pixel_rate_mhz - / 4)))); - - v->TimeForMetaPTEWithoutImmediateFlip = - dml_max( - v->MetaPTEBytesPerFrame[k] - / v->PrefetchBW[k], - dml_max( - v->ExtraLatency, - dest.htotal - / dest.pixel_rate_mhz - / 4)); - } else { - v->TimeForMetaPTEWithImmediateFlip = dest.htotal - / dest.pixel_rate_mhz / 4; - v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal - / dest.pixel_rate_mhz / 4; - } - - if (ip->pte_enable == 1 || src.dcc == 1) { - v->TimeForMetaAndDPTERowWithImmediateFlip = - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / v->PrefetchBW[k], - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - * v->TotalImmediateFlipBytes - / (v->BWAvailableForImmediateFlip - * (v->MetaPTEBytesPerFrame[k] - + v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k])), - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithImmediateFlip, - dml_max( - v->ExtraLatency, - 2 - * soc->urgent_latency_us)))); - - v->TimeForMetaAndDPTERowWithoutImmediateFlip = - dml_max( - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / v->PrefetchBW[k], - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithoutImmediateFlip, - v->ExtraLatency)); - } else { - v->TimeForMetaAndDPTERowWithImmediateFlip = - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithImmediateFlip, - v->ExtraLatency - - v->TimeForMetaPTEWithImmediateFlip); - v->TimeForMetaAndDPTERowWithoutImmediateFlip = - dml_max( - dest.htotal - / dest.pixel_rate_mhz - - v->TimeForMetaPTEWithoutImmediateFlip, - v->ExtraLatency - - v->TimeForMetaPTEWithoutImmediateFlip); - } - - v->LinesForMetaPTEWithImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaPTEWithImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaPTEWithoutImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaPTEWithoutImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaAndDPTERowWithImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaAndDPTERowWithImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = - dml_floor_ex( - 4.0 - * (v->TimeForMetaAndDPTERowWithoutImmediateFlip - / (dest.htotal - / dest.pixel_rate_mhz) - + 0.125), - 1) / 4.0; - - v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = - v->LineTimesForPrefetch[k] - - v->LinesForMetaPTEWithImmediateFlip[k] - - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; - - v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = - v->LineTimesForPrefetch[k] - - v->LinesForMetaPTEWithoutImmediateFlip[k] - - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; - - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { - v->VRatioPreYWithImmediateFlip[ijk] = - v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - if (v->SwathHeightYPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillY[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreYWithImmediateFlip[ijk] = - dml_max( - v->VRatioPreYWithImmediateFlip[ijk], - (v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillY[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreYWithImmediateFlip[ijk] = - 999999; - } - } - v->VRatioPreCWithImmediateFlip[ijk] = - v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - if (v->SwathHeightCPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillC[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreCWithImmediateFlip[ijk] = - dml_max( - v->VRatioPreCWithImmediateFlip[ijk], - (v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - - (v->PrefillC[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreCWithImmediateFlip[ijk] = - 999999; - } - } - - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = - v->NoOfDPP[ijk] - * (v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 2) - * v->SwathWidthYPerState[ijk] - / (dest.htotal - / dest.pixel_rate_mhz); - } else { - v->VRatioPreYWithImmediateFlip[ijk] = 999999; - v->VRatioPreCWithImmediateFlip[ijk] = 999999; - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = - 999999; - } - - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - > 0) { - v->VRatioPreYWithoutImmediateFlip[ijk] = - v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - if (v->SwathHeightYPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillY[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreYWithoutImmediateFlip[ijk] = - dml_max( - v->VRatioPreYWithoutImmediateFlip[ijk], - (v->MaxNumSwY[k] - * v->SwathHeightYPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillY[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreYWithoutImmediateFlip[ijk] = - 999999; - } - } - v->VRatioPreCWithoutImmediateFlip[ijk] = - v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - if (v->SwathHeightCPerState[ijk] > 4) { - if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillC[k] - 3.0) / 2.0 - > 0) { - v->VRatioPreCWithoutImmediateFlip[ijk] = - dml_max( - v->VRatioPreCWithoutImmediateFlip[ijk], - (v->MaxNumSwC[k] - * v->SwathHeightCPerState[ijk]) - / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - - (v->PrefillC[k] - - 3.0) - / 2.0)); - } else { - v->VRatioPreCWithoutImmediateFlip[ijk] = - 999999; - } - } - - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = - v->NoOfDPP[ijk] - * (v->PrefetchLinesY[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETY[k], - 1) - + v->PrefetchLinesC[k] - / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip - * dml_ceil_ex( - v->BytePerPixelInDETC[k], - 2) - / 2) - * v->SwathWidthYPerState[ijk] - / (dest.htotal - / dest.pixel_rate_mhz); - } else { - v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; - v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = - 999999; - } - } - - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; - - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - struct _vcs_dpi_display_pipe_dest_params_st dest = - e2e[v->planes[k].e2e_index].pipe.dest; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (src.source_format != dm_420_8 - && src.source_format != dm_420_10) { - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) - + dml_max( - v->MetaPTEBytesPerFrame[k] - / (v->LinesForMetaPTEWithImmediateFlip[k] - * dest.htotal - / dest.pixel_rate_mhz), - (v->MetaRowBytes[k] - + v->DPTEBytesPerRow[k]) - / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] - * dest.htotal - / dest.pixel_rate_mhz)); - } else { - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); - } - } - - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; - - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = - v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip - + dml_max( - v->ReadBandwidth[k], - v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); - } - - v->PrefetchSupportedWithImmediateFlip[ij] = 1; - if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip - > v->ReturnBWPerState[i]) { - v->PrefetchSupportedWithImmediateFlip[ij] = 0; - } - for (k = 0; k < num_planes; k++) { - if (v->LineTimesForPrefetch[k] < 2 - || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 - || v->LinesForMetaAndDPTERowWithImmediateFlip[k] - >= 16) { - v->PrefetchSupportedWithImmediateFlip[ij] = 0; - } - } - - v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; - if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip - > v->ReturnBWPerState[i]) { - v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - for (k = 0; k < num_planes; k++) { - if (v->LineTimesForPrefetch[k] < 2 - || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 - || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] - >= 16) { - v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - } - } - } - - for (i = 0; i < NumberOfStatesPlusTwo; i++) { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; - for (k = 0; k < num_planes; k++) { - struct _vcs_dpi_display_pipe_source_params_st src = - e2e[v->planes[k].e2e_index].pipe.src; - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (((src.source_format != dm_420_8 - && src.source_format != dm_420_10) - && (v->VRatioPreYWithImmediateFlip[ijk] > 4 - || v->VRatioPreCWithImmediateFlip[ijk] - > 4)) - || ((src.source_format == dm_420_8 - || src.source_format == dm_420_10) - && (v->VRatioPreYWithoutImmediateFlip[ijk] - > 4 - || v->VRatioPreCWithoutImmediateFlip[ijk] - > 4))) { - v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; - } - } - v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; - for (k = 0; k < num_planes; k++) { - ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; - - if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 - || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { - v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; - } - } - } - } - - // Mode Support, Voltage State and SOC Configuration - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - for (j = 0; j < 2; j++) { - ij = j * NumberOfStatesPlusTwo + i; - - if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 - && v->ViewportSizeSupport == 1 - && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 - && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 - && v->DISPCLK_DPPCLK_Support[ij] == 1 - && v->TotalAvailablePipesSupport[ij] == 1 - && v->TotalAvailableWritebackSupport == 1 - && v->WritebackLatencySupport == 1) { - if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 - && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] - == 1) { - v->ModeSupportWithImmediateFlip[ij] = 1; - } else { - v->ModeSupportWithImmediateFlip[ij] = 0; - } - if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 - && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] - == 1) { - v->ModeSupportWithoutImmediateFlip[ij] = 1; - } else { - v->ModeSupportWithoutImmediateFlip[ij] = 0; - } - } else { - v->ModeSupportWithImmediateFlip[ij] = 0; - v->ModeSupportWithoutImmediateFlip[ij] = 0; - } - } - } - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - if ((i == (NumberOfStatesPlusTwo - 1) - || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] - == 1 - || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] - == 1) && i >= v->VoltageOverrideLevel) { - v->VoltageLevelWithImmediateFlip = i; - } - } - - for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here - { - if ((i == (NumberOfStatesPlusTwo - 1) - || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] - == 1 - || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] - == 1) && i >= v->VoltageOverrideLevel) { - v->VoltageLevelWithoutImmediateFlip = i; - } - } - - if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { - v->ImmediateFlipSupported = 0; - v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; - } else { - v->ImmediateFlipSupported = 1; - v->VoltageLevel = v->VoltageLevelWithImmediateFlip; - } - - v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; - v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; - - for (j = 0; j < 2; j++) { - v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo - + (int) v->VoltageLevel]; - for (k = 0; k < num_planes; k++) { - v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo - + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; - } - v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j - * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; - } - - ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); - - return (v->VoltageLevel); -} - diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h deleted file mode 100644 index ead4942f998c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DISPLAY_MODE_SUPPORT_H__ -#define __DISPLAY_MODE_SUPPORT_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -#define NumberOfStates 4 -#define NumberOfStatesPlusTwo (NumberOfStates+2) - -struct dml_ms_internal_vars { - double ScaleRatioSupport; - double SourceFormatPixelAndScanSupport; - double TotalReadBandwidthConsumedGBytePerSecond; - double TotalWriteBandwidthConsumedGBytePerSecond; - double TotalBandwidthConsumedGBytePerSecond; - double DCCEnabledInAnyPlane; - double ReturnBWToDCNPerState; - double CriticalPoint; - double WritebackLatencySupport; - double RequiredOutputBW; - double TotalNumberOfActiveWriteback; - double TotalAvailableWritebackSupport; - double MaximumSwathWidth; - double NumberOfDPPRequiredForDETSize; - double NumberOfDPPRequiredForLBSize; - double MinDispclkUsingSingleDPP; - double MinDispclkUsingDualDPP; - double ViewportSizeSupport; - double SwathWidthGranularityY; - double RoundedUpMaxSwathSizeBytesY; - double SwathWidthGranularityC; - double RoundedUpMaxSwathSizeBytesC; - double LinesInDETLuma; - double LinesInDETChroma; - double EffectiveLBLatencyHidingSourceLinesLuma; - double EffectiveLBLatencyHidingSourceLinesChroma; - double EffectiveDETLBLinesLuma; - double EffectiveDETLBLinesChroma; - double ProjectedDCFCLKDeepSleep; - double MetaReqHeightY; - double MetaReqWidthY; - double MetaSurfaceWidthY; - double MetaSurfaceHeightY; - double MetaPteBytesPerFrameY; - double MetaRowBytesY; - double MacroTileBlockSizeBytesY; - double MacroTileBlockHeightY; - double DataPTEReqHeightY; - double DataPTEReqWidthY; - double DPTEBytesPerRowY; - double MetaReqHeightC; - double MetaReqWidthC; - double MetaSurfaceWidthC; - double MetaSurfaceHeightC; - double MetaPteBytesPerFrameC; - double MetaRowBytesC; - double MacroTileBlockSizeBytesC; - double MacroTileBlockHeightC; - double MacroTileBlockWidthC; - double DataPTEReqHeightC; - double DataPTEReqWidthC; - double DPTEBytesPerRowC; - double VInitY; - double MaxPartialSwY; - double VInitC; - double MaxPartialSwC; - double dst_x_after_scaler; - double dst_y_after_scaler; - double TimeCalc; - double VUpdateOffset; - double TotalRepeaterDelay; - double VUpdateWidth; - double VReadyOffset; - double TimeSetup; - double ExtraLatency; - double MaximumVStartup; - double BWAvailableForImmediateFlip; - double TotalImmediateFlipBytes; - double TimeForMetaPTEWithImmediateFlip; - double TimeForMetaPTEWithoutImmediateFlip; - double TimeForMetaAndDPTERowWithImmediateFlip; - double TimeForMetaAndDPTERowWithoutImmediateFlip; - double LineTimesToRequestPrefetchPixelDataWithImmediateFlip; - double LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; - double MaximumReadBandwidthWithPrefetchWithImmediateFlip; - double MaximumReadBandwidthWithPrefetchWithoutImmediateFlip; - double VoltageOverrideLevel; - double VoltageLevelWithImmediateFlip; - double VoltageLevelWithoutImmediateFlip; - double ImmediateFlipSupported; - double VoltageLevel; - double DCFCLK; - double FabricAndDRAMBandwidth; - double SwathWidthYSingleDPP[DC__NUM_PIPES__MAX]; - double BytePerPixelInDETY[DC__NUM_PIPES__MAX]; - double BytePerPixelInDETC[DC__NUM_PIPES__MAX]; - double ReadBandwidth[DC__NUM_PIPES__MAX]; - double WriteBandwidth[DC__NUM_PIPES__MAX]; - double DCFCLKPerState[NumberOfStatesPlusTwo]; - double FabricAndDRAMBandwidthPerState[NumberOfStatesPlusTwo]; - double ReturnBWPerState[NumberOfStatesPlusTwo]; - double BandwidthSupport[NumberOfStatesPlusTwo]; - double UrgentRoundTripAndOutOfOrderLatencyPerState[NumberOfStatesPlusTwo]; - double ROBSupport[NumberOfStatesPlusTwo]; - double RequiredPHYCLK[DC__NUM_PIPES__MAX]; - double DIOSupport[NumberOfStatesPlusTwo]; - double PHYCLKPerState[NumberOfStatesPlusTwo]; - double PSCL_FACTOR[DC__NUM_PIPES__MAX]; - double PSCL_FACTOR_CHROMA[DC__NUM_PIPES__MAX]; - double MinDPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; - double Read256BlockHeightY[DC__NUM_PIPES__MAX]; - double Read256BlockWidthY[DC__NUM_PIPES__MAX]; - double Read256BlockHeightC[DC__NUM_PIPES__MAX]; - double Read256BlockWidthC[DC__NUM_PIPES__MAX]; - double MaxSwathHeightY[DC__NUM_PIPES__MAX]; - double MaxSwathHeightC[DC__NUM_PIPES__MAX]; - double MinSwathHeightY[DC__NUM_PIPES__MAX]; - double MinSwathHeightC[DC__NUM_PIPES__MAX]; - double NumberOfDPPRequiredForDETAndLBSize[DC__NUM_PIPES__MAX]; - double TotalNumberOfActiveDPP[NumberOfStatesPlusTwo * 2]; - double RequiredDISPCLK[NumberOfStatesPlusTwo * 2]; - double DISPCLK_DPPCLK_Support[NumberOfStatesPlusTwo * 2]; - double MaxDispclk[NumberOfStatesPlusTwo]; - double MaxDppclk[NumberOfStatesPlusTwo]; - double NoOfDPP[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double TotalAvailablePipesSupport[NumberOfStatesPlusTwo * 2]; - double SwathWidthYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double SwathHeightYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double SwathHeightCPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double DETBufferSizeYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double UrgentLatencySupportUsPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double UrgentLatencySupport[NumberOfStatesPlusTwo * 2]; - double TotalNumberOfDCCActiveDPP[NumberOfStatesPlusTwo * 2]; - double DPTEBytesPerRow[DC__NUM_PIPES__MAX]; - double MetaPTEBytesPerFrame[DC__NUM_PIPES__MAX]; - double MetaRowBytes[DC__NUM_PIPES__MAX]; - double PrefillY[DC__NUM_PIPES__MAX]; - double MaxNumSwY[DC__NUM_PIPES__MAX]; - double PrefetchLinesY[DC__NUM_PIPES__MAX]; - double PrefillC[DC__NUM_PIPES__MAX]; - double MaxNumSwC[DC__NUM_PIPES__MAX]; - double PrefetchLinesC[DC__NUM_PIPES__MAX]; - double LineTimesForPrefetch[DC__NUM_PIPES__MAX]; - double PrefetchBW[DC__NUM_PIPES__MAX]; - double LinesForMetaPTEWithImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaPTEWithoutImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaAndDPTERowWithImmediateFlip[DC__NUM_PIPES__MAX]; - double LinesForMetaAndDPTERowWithoutImmediateFlip[DC__NUM_PIPES__MAX]; - double VRatioPreYWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double VRatioPreCWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double RequiredPrefetchPixelDataBWWithImmediateFlip[NumberOfStatesPlusTwo * 2 - * DC__NUM_PIPES__MAX]; - double VRatioPreYWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double VRatioPreCWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; - double RequiredPrefetchPixelDataBWWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 - * DC__NUM_PIPES__MAX]; - double PrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double PrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double VRatioInPrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double VRatioInPrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double ModeSupportWithImmediateFlip[NumberOfStatesPlusTwo * 2]; - double ModeSupportWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; - double RequiredDISPCLKPerRatio[2]; - double DPPPerPlanePerRatio[2 * DC__NUM_PIPES__MAX]; - double DISPCLK_DPPCLK_SupportPerRatio[2]; - struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; -}; - -int dml_ms_check( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - int num_pipes); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c new file mode 100644 index 000000000000..ada0eeed3301 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -0,0 +1,3263 @@ +#include "display_mode_lib.h" +#include "display_mode_vba.h" + +static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; + +static void fetch_socbb_params(struct display_mode_lib *mode_lib); +static void fetch_ip_params(struct display_mode_lib *mode_lib); +static void fetch_pipe_params(struct display_mode_lib *mode_lib); +static void recalculate_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +static void recalculate(struct display_mode_lib *mode_lib); +static double adjust_ReturnBW(struct display_mode_lib *mode_lib, double ReturnBW, bool DCCEnabledAnyPlane, double ReturnBandwidthToDCN); +static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib); +static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib); +static unsigned int dscceComputeDelay(unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat); +static unsigned int dscComputeDelay(enum output_format_class pixelFormat); +// Super monster function with some 45 argument +static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw); +static double CeilToDFSGranularity(double Clock, double VCOSpeed); +static double FloorToDFSGranularity(double Clock, double VCOSpeed); +static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath); +static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidthY, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height); +static double CalculateTWait(unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime); +static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk); +static double CalculateWriteBackDISPCLK(enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth); +static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw); +static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe); +static double CalculateWriteBackDelay(enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth); +static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib); +static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp); + +void set_prefetch_mode(struct display_mode_lib *mode_lib, + bool cstate_en, + bool pstate_en, + bool ignore_viewport_pos, + bool immediate_flip_support) +{ + unsigned int prefetch_mode; + + if (cstate_en && pstate_en) + prefetch_mode = 0; + else if (cstate_en) + prefetch_mode = 1; + else + prefetch_mode = 2; + if (prefetch_mode != mode_lib->vba.PrefetchMode || ignore_viewport_pos != mode_lib->vba.IgnoreViewportPositioning + || immediate_flip_support != mode_lib->vba.ImmediateFlipSupport) { + DTRACE(" Prefetch mode has changed from %i to %i. Recalculating.", + prefetch_mode, + mode_lib->vba.PrefetchMode); + mode_lib->vba.PrefetchMode = prefetch_mode; + mode_lib->vba.IgnoreViewportPositioning = ignore_viewport_pos; + mode_lib->vba.ImmediateFlipSupport = immediate_flip_support; + recalculate(mode_lib); + } +} + +#define dml_get_attr_func(attr, var) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) \ +{ \ + recalculate_params(mode_lib, pipes, num_pipes); \ + return var; \ +} + +dml_get_attr_func(clk_dcf_deepsleep, mode_lib->vba.DCFClkDeepSleep); +dml_get_attr_func(wm_urgent, mode_lib->vba.UrgentWatermark); +dml_get_attr_func(wm_memory_trip, mode_lib->vba.MemoryTripWatermark); +dml_get_attr_func(wm_writeback_urgent, mode_lib->vba.WritebackUrgentWatermark); +dml_get_attr_func(wm_stutter_exit, mode_lib->vba.StutterExitWatermark); +dml_get_attr_func(wm_stutter_enter_exit, mode_lib->vba.StutterEnterPlusExitWatermark); +dml_get_attr_func(wm_dram_clock_change, mode_lib->vba.DRAMClockChangeWatermark); +dml_get_attr_func(wm_writeback_dram_clock_change, mode_lib->vba.WritebackDRAMClockChangeWatermark); +dml_get_attr_func(wm_xfc_underflow, mode_lib->vba.UrgentWatermark); // xfc_underflow maps to urgent +dml_get_attr_func(stutter_efficiency, mode_lib->vba.StutterEfficiency); +dml_get_attr_func(stutter_efficiency_no_vblank, mode_lib->vba.StutterEfficiencyNotIncludingVBlank); +dml_get_attr_func(urgent_latency, mode_lib->vba.MinUrgentLatencySupportUs); +dml_get_attr_func(urgent_extra_latency, mode_lib->vba.UrgentExtraLatency); +dml_get_attr_func(nonurgent_latency, mode_lib->vba.NonUrgentLatencyTolerance); +dml_get_attr_func(dram_clock_change_latency, mode_lib->vba.MinActiveDRAMClockChangeLatencySupported); +dml_get_attr_func(dispclk_calculated, mode_lib->vba.DISPCLK_calculated); +dml_get_attr_func(total_data_read_bw, mode_lib->vba.TotalDataReadBandwidth); +dml_get_attr_func(return_bw, mode_lib->vba.ReturnBW); +dml_get_attr_func(tcalc, mode_lib->vba.TCalc); + +#define dml_get_pipe_attr_func(attr, var) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes, unsigned int which_pipe) \ +{\ + unsigned int which_plane; \ + recalculate_params(mode_lib, pipes, num_pipes); \ + which_plane = mode_lib->vba.pipe_plane[which_pipe]; \ + return var[which_plane]; \ +} + +dml_get_pipe_attr_func(dsc_delay, mode_lib->vba.DSCDelay); +dml_get_pipe_attr_func(dppclk_calculated, mode_lib->vba.DPPCLK_calculated); +dml_get_pipe_attr_func(dscclk_calculated, mode_lib->vba.DSCCLK_calculated); +dml_get_pipe_attr_func(min_ttu_vblank, mode_lib->vba.MinTTUVBlank); +dml_get_pipe_attr_func(vratio_prefetch_l, mode_lib->vba.VRatioPrefetchY); +dml_get_pipe_attr_func(vratio_prefetch_c, mode_lib->vba.VRatioPrefetchC); +dml_get_pipe_attr_func(dst_x_after_scaler, mode_lib->vba.DSTXAfterScaler); +dml_get_pipe_attr_func(dst_y_after_scaler, mode_lib->vba.DSTYAfterScaler); +dml_get_pipe_attr_func(dst_y_per_vm_vblank, mode_lib->vba.DestinationLinesToRequestVMInVBlank); +dml_get_pipe_attr_func(dst_y_per_row_vblank, mode_lib->vba.DestinationLinesToRequestRowInVBlank); +dml_get_pipe_attr_func(dst_y_prefetch, mode_lib->vba.DestinationLinesForPrefetch); +dml_get_pipe_attr_func(dst_y_per_vm_flip, mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip); +dml_get_pipe_attr_func(dst_y_per_row_flip, mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip); + +dml_get_pipe_attr_func(xfc_transfer_delay, mode_lib->vba.XFCTransferDelay); +dml_get_pipe_attr_func(xfc_precharge_delay, mode_lib->vba.XFCPrechargeDelay); +dml_get_pipe_attr_func(xfc_remote_surface_flip_latency, mode_lib->vba.XFCRemoteSurfaceFlipLatency); +dml_get_pipe_attr_func(xfc_prefetch_margin, mode_lib->vba.XFCPrefetchMargin); + +unsigned int get_vstartup_calculated(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes, + unsigned int which_pipe) +{ + unsigned int which_plane; + + recalculate_params(mode_lib, pipes, num_pipes); + which_plane = mode_lib->vba.pipe_plane[which_pipe]; + return mode_lib->vba.VStartup[which_plane]; +} + +double get_total_immediate_flip_bytes(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + recalculate_params(mode_lib, pipes, num_pipes); + return mode_lib->vba.TotImmediateFlipBytes; +} + +double get_total_immediate_flip_bw(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + recalculate_params(mode_lib, pipes, num_pipes); + return mode_lib->vba.ImmediateFlipBW; +} + +double get_total_prefetch_bw(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int k; + double total_prefetch_bw = 0.0; + + recalculate_params(mode_lib, pipes, num_pipes); + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + total_prefetch_bw += mode_lib->vba.PrefetchBandwidth[k]; + return total_prefetch_bw; +} + +static void fetch_socbb_params(struct display_mode_lib *mode_lib) +{ + soc_bounding_box_st *soc = &mode_lib->vba.soc; + unsigned int i; + + // SOC Bounding Box Parameters + mode_lib->vba.ReturnBusWidth = soc->return_bus_width_bytes; + mode_lib->vba.NumberOfChannels = soc->num_chans; + mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency = + soc->ideal_dram_bw_after_urgent_percent; // there's always that one bastard variable that's so long it throws everything out of alignment! + mode_lib->vba.UrgentLatency = soc->urgent_latency_us; + mode_lib->vba.RoundTripPingLatencyCycles = soc->round_trip_ping_latency_dcfclk_cycles; + mode_lib->vba.UrgentOutOfOrderReturnPerChannel = soc->urgent_out_of_order_return_per_channel_bytes; + mode_lib->vba.WritebackLatency = soc->writeback_latency_us; + mode_lib->vba.SRExitTime = soc->sr_exit_time_us; + mode_lib->vba.SREnterPlusExitTime = soc->sr_enter_plus_exit_time_us; + mode_lib->vba.DRAMClockChangeLatency = soc->dram_clock_change_latency_us; + mode_lib->vba.Downspreading = soc->downspread_percent; + mode_lib->vba.DRAMChannelWidth = soc->dram_channel_width_bytes; // new! + mode_lib->vba.FabricDatapathToDCNDataReturn = soc->fabric_datapath_to_dcn_data_return_bytes; // new! + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading = soc->dcn_downspread_percent; // new + mode_lib->vba.DISPCLKDPPCLKVCOSpeed = soc->dispclk_dppclk_vco_speed_mhz; // new + mode_lib->vba.VMMPageSize = soc->vmm_page_size_bytes; + // Set the voltage scaling clocks as the defaults. Most of these will + // be set to different values by the test + for (i = 0; i < DC__VOLTAGE_STATES; ++i) + if (soc->clock_limits[i].state == mode_lib->vba.VoltageLevel) + break; + + mode_lib->vba.DCFCLK = soc->clock_limits[i].dcfclk_mhz; + mode_lib->vba.SOCCLK = soc->clock_limits[i].socclk_mhz; + mode_lib->vba.DRAMSpeed = soc->clock_limits[i].dram_speed_mhz; + mode_lib->vba.FabricClock = soc->clock_limits[i].fabricclk_mhz; + + mode_lib->vba.XFCBusTransportTime = soc->xfc_bus_transport_time_us; + mode_lib->vba.XFCXBUFLatencyTolerance = soc->xfc_xbuf_latency_tolerance_us; +} + +static void fetch_ip_params(struct display_mode_lib *mode_lib) +{ + ip_params_st *ip = &mode_lib->vba.ip; + + // IP Parameters + mode_lib->vba.MaxDCHUBToPSCLThroughput = ip->max_dchub_pscl_bw_pix_per_clk; + mode_lib->vba.MaxPSCLToLBThroughput = ip->max_pscl_lb_bw_pix_per_clk; + mode_lib->vba.ROBBufferSizeInKByte = ip->rob_buffer_size_kbytes; + mode_lib->vba.DETBufferSizeInKByte = ip->det_buffer_size_kbytes; + mode_lib->vba.PixelChunkSizeInKByte = ip->pixel_chunk_size_kbytes; + mode_lib->vba.MetaChunkSize = ip->meta_chunk_size_kbytes; + mode_lib->vba.PTEChunkSize = ip->pte_chunk_size_kbytes; + mode_lib->vba.WritebackChunkSize = ip->writeback_chunk_size_kbytes; + mode_lib->vba.LineBufferSize = ip->line_buffer_size_bits; + mode_lib->vba.MaxLineBufferLines = ip->max_line_buffer_lines; + mode_lib->vba.PTEBufferSizeInRequests = ip->dpte_buffer_size_in_pte_reqs; + mode_lib->vba.DPPOutputBufferPixels = ip->dpp_output_buffer_pixels; + mode_lib->vba.OPPOutputBufferLines = ip->opp_output_buffer_lines; + mode_lib->vba.WritebackInterfaceLumaBufferSize = ip->writeback_luma_buffer_size_kbytes; + mode_lib->vba.WritebackInterfaceChromaBufferSize = ip->writeback_chroma_buffer_size_kbytes; + mode_lib->vba.WritebackChromaLineBufferWidth = ip->writeback_chroma_line_buffer_width_pixels; + mode_lib->vba.MaxPageTableLevels = ip->max_page_table_levels; + mode_lib->vba.MaxInterDCNTileRepeaters = ip->max_inter_dcn_tile_repeaters; + mode_lib->vba.NumberOfDSC = ip->num_dsc; + mode_lib->vba.ODMCapability = ip->odm_capable; + mode_lib->vba.DISPCLKRampingMargin = ip->dispclk_ramp_margin_percent; + + mode_lib->vba.XFCSupported = ip->xfc_supported; + mode_lib->vba.XFCFillBWOverhead = ip->xfc_fill_bw_overhead_percent; + mode_lib->vba.XFCFillConstant = ip->xfc_fill_constant_bytes; + mode_lib->vba.DPPCLKDelaySubtotal = ip->dppclk_delay_subtotal; + mode_lib->vba.DPPCLKDelaySCL = ip->dppclk_delay_scl; + mode_lib->vba.DPPCLKDelaySCLLBOnly = ip->dppclk_delay_scl_lb_only; + mode_lib->vba.DPPCLKDelayCNVCFormater = ip->dppclk_delay_cnvc_formatter; + mode_lib->vba.DPPCLKDelayCNVCCursor = ip->dppclk_delay_cnvc_cursor; + mode_lib->vba.DISPCLKDelaySubtotal = ip->dispclk_delay_subtotal; + + mode_lib->vba.ProgressiveToInterlaceUnitInOPP = ip->ptoi_supported; + + mode_lib->vba.PDEProcessingBufIn64KBReqs = ip->pde_proc_buffer_size_64k_reqs; +} + +static void fetch_pipe_params(struct display_mode_lib *mode_lib) +{ + display_e2e_pipe_params_st *pipes = mode_lib->vba.cache_pipes; + ip_params_st *ip = &mode_lib->vba.ip; + + unsigned int OTGInstPlane[DC__NUM_DPP]; + unsigned int j, k; + bool PlaneVisited[DC__NUM_DPP]; + bool visited[DC__NUM_PIPES__MAX]; + + // Convert Pipes to Planes + for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) + visited[k] = false; + + mode_lib->vba.NumberOfActivePlanes = 0; + for (j = 0; j < mode_lib->vba.cache_num_pipes; ++j) { + display_pipe_source_params_st *src = &pipes[j].pipe.src; + display_pipe_dest_params_st *dst = &pipes[j].pipe.dest; + scaler_ratio_depth_st *scl = &pipes[j].pipe.scale_ratio_depth; + scaler_taps_st *taps = &pipes[j].pipe.scale_taps; + display_output_params_st *dout = &pipes[j].dout; + display_clocks_and_cfg_st *clks = &pipes[j].clks_cfg; + + if (visited[j]) + continue; + visited[j] = true; + + mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; + + mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; + mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = (enum scan_direction_class)(src->source_scan); + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width; + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height; + mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_y; + mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_c; + mode_lib->vba.PitchY[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch; + mode_lib->vba.PitchC[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch_c; + mode_lib->vba.DCCMetaPitchY[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch; + mode_lib->vba.HRatio[mode_lib->vba.NumberOfActivePlanes] = scl->hscl_ratio; + mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] = scl->vscl_ratio; + mode_lib->vba.ScalerEnabled[mode_lib->vba.NumberOfActivePlanes] = scl->scl_enable; + mode_lib->vba.Interlace[mode_lib->vba.NumberOfActivePlanes] = dst->interlaced; + if (mode_lib->vba.Interlace[mode_lib->vba.NumberOfActivePlanes]) + mode_lib->vba.VRatio[mode_lib->vba.NumberOfActivePlanes] *= 2.0; + mode_lib->vba.htaps[mode_lib->vba.NumberOfActivePlanes] = taps->htaps; + mode_lib->vba.vtaps[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps; + mode_lib->vba.HTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->htaps_c; + mode_lib->vba.VTAPsChroma[mode_lib->vba.NumberOfActivePlanes] = taps->vtaps_c; + mode_lib->vba.HTotal[mode_lib->vba.NumberOfActivePlanes] = dst->htotal; + mode_lib->vba.VTotal[mode_lib->vba.NumberOfActivePlanes] = dst->vtotal; + mode_lib->vba.DCCEnable[mode_lib->vba.NumberOfActivePlanes] = + src->dcc_use_global ? ip->dcc_supported : src->dcc & ip->dcc_supported; + mode_lib->vba.DCCRate[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate; + mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class)(src->source_format); + mode_lib->vba.HActive[mode_lib->vba.NumberOfActivePlanes] = dst->hactive; + mode_lib->vba.VActive[mode_lib->vba.NumberOfActivePlanes] = dst->vactive; + mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] = (enum dm_swizzle_mode)(src->sw_mode); + mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] = dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode? + mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] = dst->odm_combine; + mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] = (enum output_format_class)(dout->output_format); + mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] = (enum output_encoder_class)(dout->output_type); + mode_lib->vba.OutputBpp[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp; + mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; + mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; + mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = + dout->output_bpc == 0 ? 12 : dout->output_bpc; + mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable; + mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_src_height; + mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_dst_width; + mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_dst_height; + mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class)(dout->wb.wb_pixel_format); + mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_htaps_luma; + mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vtaps_luma; + mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_htaps_chroma; + mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vtaps_chroma; + mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_hratio; + mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vratio; + + mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] = src->dynamic_metadata_enable; + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_lines_before_active; + mode_lib->vba.DynamicMetadataTransmittedBytes[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_xmit_bytes; + + mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable && ip->xfc_supported; + mode_lib->vba.XFCSlvChunkSize = src->xfc_params.xfc_slv_chunk_size_bytes; + mode_lib->vba.XFCTSlvVupdateOffset = src->xfc_params.xfc_tslv_vupdate_offset_us; + mode_lib->vba.XFCTSlvVupdateWidth = src->xfc_params.xfc_tslv_vupdate_width_us; + mode_lib->vba.XFCTSlvVreadyOffset = src->xfc_params.xfc_tslv_vready_offset_us; + mode_lib->vba.PixelClock[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz; + mode_lib->vba.DPPCLK[mode_lib->vba.NumberOfActivePlanes] = clks->dppclk_mhz; + if (ip->is_line_buffer_bpp_fixed) + mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = ip->line_buffer_fixed_bpp; + else { + unsigned int lb_depth; + + switch (scl->lb_depth) { + case dm_lb_6: + lb_depth = 18; + break; + case dm_lb_8: + lb_depth = 24; + break; + case dm_lb_10: + lb_depth = 30; + break; + case dm_lb_12: + lb_depth = 36; + break; + case dm_lb_16: + lb_depth = 48; + break; + default: + lb_depth = 36; + } + mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = lb_depth; + } + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes] = 0; + // The DML spreadsheet assumes that the two cursors utilize the same amount of bandwidth. We'll + // calculate things a little more accurately + for (k = 0; k < DC__NUM_CURSOR; ++k) { + switch (k) { + case 0: + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = CursorBppEnumToBits((enum cursor_bpp)(src->cur0_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] = src->cur0_src_width; + if (src->cur0_src_width > 0) + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; + break; + case 1: + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] = CursorBppEnumToBits((enum cursor_bpp)(src->cur1_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] = src->cur1_src_width; + if (src->cur1_src_width > 0) + mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; + break; + default: + dml_print("ERROR: Number of cursors specified exceeds supported maximum\n"); + } + } + + OTGInstPlane[mode_lib->vba.NumberOfActivePlanes] = dst->otg_inst; + + if (dst->odm_combine && !src->is_hsplit) + dml_print("ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n", + j); + + if (src->is_hsplit) { + for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) { + display_pipe_source_params_st *src_k = &pipes[k].pipe.src; + display_output_params_st *dout_k = &pipes[k].dout; + + if (src_k->is_hsplit && !visited[k] + && src->hsplit_grp == src_k->hsplit_grp) { + mode_lib->vba.pipe_plane[k] = mode_lib->vba.NumberOfActivePlanes; + mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++; + if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] == dm_horz) + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] += + src_k->viewport_width; + else + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] += + src_k->viewport_height; + + mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] += + dout_k->dsc_slices; + visited[k] = true; + } + } + } + + mode_lib->vba.NumberOfActivePlanes++; + } + + // handle overlays through dml_ml->vba.BlendingAndTiming + // dml_ml->vba.BlendingAndTiming tells you which instance to look at to get timing, the so called 'master' + + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + PlaneVisited[j] = false; + + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + for (k = j + 1; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (!PlaneVisited[k] && OTGInstPlane[j] == OTGInstPlane[k]) { + // doesn't matter, so choose the smaller one + mode_lib->vba.BlendingAndTiming[j] = j; + PlaneVisited[j] = true; + mode_lib->vba.BlendingAndTiming[k] = j; + PlaneVisited[k] = true; + } + } + + if (!PlaneVisited[j]) { + mode_lib->vba.BlendingAndTiming[j] = j; + PlaneVisited[j] = true; + } + } + + // TODO: dml_ml->vba.ODMCombineEnabled => 2 * dml_ml->vba.DPPPerPlane...actually maybe not since all pipes are specified + // Do we want the dscclk to automatically be halved? Guess not since the value is specified + + mode_lib->vba.SynchronizedVBlank = pipes[0].pipe.dest.synchronized_vblank_all_planes; + for (k = 1; k < mode_lib->vba.cache_num_pipes; ++k) + ASSERT(mode_lib->vba.SynchronizedVBlank == pipes[k].pipe.dest.synchronized_vblank_all_planes); + + mode_lib->vba.VirtualMemoryEnable = 0; + mode_lib->vba.OverridePageTableLevels = 0; + + for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) { + mode_lib->vba.VirtualMemoryEnable |= pipes[k].pipe.src.vm; + mode_lib->vba.OverridePageTableLevels = + (pipes[k].pipe.src.vm_levels_force_en + && mode_lib->vba.OverridePageTableLevels + < pipes[k].pipe.src.vm_levels_force) ? + pipes[k].pipe.src.vm_levels_force : + mode_lib->vba.OverridePageTableLevels; + } + + if (mode_lib->vba.OverridePageTableLevels) + mode_lib->vba.MaxPageTableLevels = mode_lib->vba.OverridePageTableLevels; + + mode_lib->vba.VirtualMemoryEnable &= ip->pte_enable; + + mode_lib->vba.FabricAndDRAMBandwidth = dml_min(mode_lib->vba.DRAMSpeed * mode_lib->vba.NumberOfChannels * mode_lib->vba.DRAMChannelWidth, + mode_lib->vba.FabricClock * mode_lib->vba.FabricDatapathToDCNDataReturn) / 1000.0; + + // TODO: Must be consistent across all pipes + // DCCProgrammingAssumesScanDirectionUnknown = src.dcc_scan_dir_unknown; +} + +static void recalculate(struct display_mode_lib *mode_lib) +{ + ModeSupportAndSystemConfiguration(mode_lib); + PixelClockAdjustmentForProgressiveToInterlaceUnit(mode_lib); + DisplayPipeConfiguration(mode_lib); + DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(mode_lib); +} + +// in wm mode we pull the parameters needed from the display_e2e_pipe_params_st structs +// rather than working them out as in recalculate_ms +static void recalculate_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + // This is only safe to use memcmp because there are non-POD types in struct display_mode_lib + if (memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 + || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 + || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 + || num_pipes != mode_lib->vba.cache_num_pipes + || memcmp(pipes, mode_lib->vba.cache_pipes, sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { + mode_lib->vba.soc = mode_lib->soc; + mode_lib->vba.ip = mode_lib->ip; + mode_lib->vba.me = mode_lib->me; + memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); + mode_lib->vba.cache_num_pipes = num_pipes; + recalculate(mode_lib); + } +} + +static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib) +{ + soc_bounding_box_st *soc = &mode_lib->vba.soc; + unsigned int i, k; + unsigned int total_pipes = 0; + + mode_lib->vba.VoltageLevel = mode_lib->vba.cache_pipes[0].clks_cfg.voltage; + for (i = 1; i < mode_lib->vba.cache_num_pipes; ++i) + ASSERT(mode_lib->vba.VoltageLevel == -1 || mode_lib->vba.VoltageLevel == mode_lib->vba.cache_pipes[i].clks_cfg.voltage); + + mode_lib->vba.DCFCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dcfclk_mhz; + mode_lib->vba.SOCCLK = mode_lib->vba.cache_pipes[0].clks_cfg.socclk_mhz; + + if (mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz > 0.0) + mode_lib->vba.DISPCLK = mode_lib->vba.cache_pipes[0].clks_cfg.dispclk_mhz; + else + mode_lib->vba.DISPCLK = soc->clock_limits[mode_lib->vba.VoltageLevel].dispclk_mhz; + + fetch_socbb_params(mode_lib); + fetch_ip_params(mode_lib); + fetch_pipe_params(mode_lib); + + // Total Available Pipes Support Check + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + total_pipes += mode_lib->vba.DPPPerPlane[k]; + ASSERT(total_pipes <= DC__NUM_DPP); +} + +static double adjust_ReturnBW(struct display_mode_lib *mode_lib, double ReturnBW, bool DCCEnabledAnyPlane, double ReturnBandwidthToDCN) +{ + double CriticalCompression; + + if (DCCEnabledAnyPlane && ReturnBandwidthToDCN > mode_lib->vba.DCFCLK * mode_lib->vba.ReturnBusWidth / 4.0) + ReturnBW = + dml_min(ReturnBW, + ReturnBandwidthToDCN * 4 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 + / ReturnBandwidthToDCN + - mode_lib->vba.DCFCLK + * mode_lib->vba.ReturnBusWidth + / 4) + + mode_lib->vba.UrgentLatency)); + + CriticalCompression = 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK * mode_lib->vba.UrgentLatency + / (ReturnBandwidthToDCN * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) * 1024); + + if (DCCEnabledAnyPlane && CriticalCompression > 1.0 && CriticalCompression < 4.0) + ReturnBW = + dml_min(ReturnBW, + 4.0 * ReturnBandwidthToDCN + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK + * mode_lib->vba.UrgentLatency + / dml_pow((ReturnBandwidthToDCN + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024), + 2)); + + return ReturnBW; +} + +static unsigned int dscceComputeDelay(unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat) +{ + // valid bpc = source bits per component in the set of {8, 10, 12} + // valid bpp = increments of 1/16 of a bit + // min = 6/7/8 in N420/N422/444, respectively + // max = such that compression is 1:1 + //valid sliceWidth = number of pixels per slice line, must be less than or equal to 5184/numSlices (or 4096/numSlices in 420 mode) + //valid numSlices = number of slices in the horiziontal direction per DSC engine in the set of {1, 2, 3, 4} + //valid pixelFormat = pixel/color format in the set of {:N444_RGB, :S422, :N422, :N420} + + // fixed value + unsigned int rcModelSize = 8192; + + // N422/N420 operate at 2 pixels per clock + unsigned int pixelsPerClock, lstall, D, initalXmitDelay, w, s, ix, wx, p, l0, a, ax, l, Delay, + pixels; + + if (pixelFormat == dm_n422 || pixelFormat == dm_420) + pixelsPerClock = 2; + // #all other modes operate at 1 pixel per clock + else + pixelsPerClock = 1; + + //initial transmit delay as per PPS + initalXmitDelay = dml_round(rcModelSize / 2.0 / bpp / pixelsPerClock); + + //compute ssm delay + if (bpc == 8) + D = 81; + else if (bpc == 10) + D = 89; + else + D = 113; + + //divide by pixel per cycle to compute slice width as seen by DSC + w = sliceWidth / pixelsPerClock; + + //422 mode has an additional cycle of delay + if (pixelFormat == dm_s422) + s = 1; + else + s = 0; + + //main calculation for the dscce + ix = initalXmitDelay + 45; + wx = (w + 2) / 3; + p = 3 * wx - w; + l0 = ix / w; + a = ix + p * l0; + ax = (a + 2) / 3 + D + 6 + 1; + l = (ax + wx - 1) / wx; + if ((ix % w) == 0 && p != 0) + lstall = 1; + else + lstall = 0; + Delay = l * wx * (numSlices - 1) + ax + s + lstall + 22; + + //dsc processes 3 pixel containers per cycle and a container can contain 1 or 2 pixels + pixels = Delay * 3 * pixelsPerClock; + return pixels; +} + +static unsigned int dscComputeDelay(enum output_format_class pixelFormat) +{ + unsigned int Delay = 0; + + if (pixelFormat == dm_420) { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 0; + // dscc - input deserializer + Delay = Delay + 3; + // dscc gets pixels every other cycle + Delay = Delay + 2; + // dscc - input cdc fifo + Delay = Delay + 12; + // dscc gets pixels every other cycle + Delay = Delay + 13; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 7; + // dscc gets pixels every other cycle + Delay = Delay + 3; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output serializer + Delay = Delay + 1; + // sft + Delay = Delay + 1; + } else if (pixelFormat == dm_n422) { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 1; + // dscc - input deserializer + Delay = Delay + 5; + // dscc - input cdc fifo + Delay = Delay + 25; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 10; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output serializer + Delay = Delay + 1; + // sft + Delay = Delay + 1; + } else { + // sfr + Delay = Delay + 2; + // dsccif + Delay = Delay + 0; + // dscc - input deserializer + Delay = Delay + 3; + // dscc - input cdc fifo + Delay = Delay + 12; + // dscc - cdc uncertainty + Delay = Delay + 2; + // dscc - output cdc fifo + Delay = Delay + 7; + // dscc - output serializer + Delay = Delay + 1; + // dscc - cdc uncertainty + Delay = Delay + 2; + // sft + Delay = Delay + 1; + } + + return Delay; +} + +static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw) +{ + bool MyError = false; + unsigned int DPPCycles, DISPCLKCycles, VUpdateOffsetPix, VUpdateWidthPix, VReadyOffsetPix; + double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime; + double Tdm, LineTime, Tsetup; + double dst_y_prefetch_equ; + double Tsw_oto; + double prefetch_bw_oto; + double Tvm_oto; + double Tr0_oto; + double Tpre_oto; + double dst_y_prefetch_oto; + double TimeForFetchingMetaPTE = 0; + double TimeForFetchingRowInVBlank = 0; + double LinesToRequestPrefetchPixelData = 0; + + if (ScalerEnabled) + DPPCycles = DPPCLKDelaySubtotal + DPPCLKDelaySCL; + else + DPPCycles = DPPCLKDelaySubtotal + DPPCLKDelaySCLLBOnly; + + DPPCycles = DPPCycles + DPPCLKDelayCNVCFormater + NumberOfCursors * DPPCLKDelayCNVCCursor; + + DISPCLKCycles = DISPCLKDelaySubtotal; + + if (DPPCLK == 0.0 || DISPCLK == 0.0) + return true; + + *DSTXAfterScaler = DPPCycles * PixelClock / DPPCLK + DISPCLKCycles * PixelClock / DISPCLK + + DSCDelay; + + if (DPPPerPlane > 1) + *DSTXAfterScaler = *DSTXAfterScaler + ScalerRecoutWidth; + + if (OutputFormat == dm_420 || (InterlaceEnable && ProgressiveToInterlaceUnitInOPP)) + *DSTYAfterScaler = 1; + else + *DSTYAfterScaler = 0; + + DSTTotalPixelsAfterScaler = ((double)(*DSTYAfterScaler * HTotal)) + *DSTXAfterScaler; + *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / HTotal, 1); + *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double)(*DSTYAfterScaler * HTotal)); + + VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); + TotalRepeaterDelayTime = MaxInterDCNTileRepeaters * (2.0 / DPPCLK + 3.0 / DISPCLK); + VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) + * PixelClock; + + VReadyOffsetPix = dml_max(150.0 / DPPCLK, + TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) + * PixelClock; + + Tsetup = (double)(VUpdateOffsetPix + VUpdateWidthPix + VReadyOffsetPix) / PixelClock; + + LineTime = (double)HTotal / PixelClock; + + if (DynamicMetadataEnable) { + double Tdmbf, Tdmec, Tdmsks; + + Tdm = dml_max(0.0, UrgentExtraLatency - TCalc); + Tdmbf = DynamicMetadataTransmittedBytes / 4.0 / DISPCLK; + Tdmec = LineTime; + if (DynamicMetadataLinesBeforeActiveRequired == 0) + Tdmsks = VBlank * LineTime / 2.0; + else + Tdmsks = DynamicMetadataLinesBeforeActiveRequired * LineTime; + if (InterlaceEnable && !ProgressiveToInterlaceUnitInOPP) + Tdmsks = Tdmsks / 2; + if (VStartup * LineTime + < Tsetup + TWait + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) { + MyError = true; + *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = (Tsetup + TWait + + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) / LineTime; + } else + *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = 0.0; + } else + Tdm = 0; + + if (VirtualMemoryEnable) { + if (PageTableLevels == 4) + *Tno_bw = UrgentExtraLatency + UrgentLatency; + else if (PageTableLevels == 3) + *Tno_bw = UrgentExtraLatency; + else + Tno_bw = 0; + } else if (DCCEnable) + *Tno_bw = LineTime; + else + *Tno_bw = LineTime / 4; + + dst_y_prefetch_equ = VStartup - dml_max(TCalc + TWait, XFCRemoteSurfaceFlipDelay) / LineTime + - (Tsetup + Tdm) / LineTime + - (*DSTYAfterScaler + *DSTXAfterScaler / HTotal); + + Tsw_oto = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; + + prefetch_bw_oto = (MetaRowByte + PixelPTEBytesPerRow + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 * dml_ceil(BytePerPixelDETC, 2)) + / Tsw_oto; + + if (VirtualMemoryEnable == true) { + Tvm_oto = + dml_max(*Tno_bw + PDEAndMetaPTEBytesFrame / prefetch_bw_oto, + dml_max(UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4.0)); + } else + Tvm_oto = LineTime / 4.0; + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + Tr0_oto = dml_max((MetaRowByte + PixelPTEBytesPerRow) / prefetch_bw_oto, + dml_max(UrgentLatency, dml_max(LineTime - Tvm_oto, LineTime / 4))); + } else + Tr0_oto = LineTime - Tvm_oto; + + Tpre_oto = Tvm_oto + Tr0_oto + Tsw_oto; + + dst_y_prefetch_oto = Tpre_oto / LineTime; + + if (dst_y_prefetch_oto < dst_y_prefetch_equ) + *DestinationLinesForPrefetch = dst_y_prefetch_oto; + else + *DestinationLinesForPrefetch = dst_y_prefetch_equ; + + *DestinationLinesForPrefetch = dml_floor(4.0 * (*DestinationLinesForPrefetch + 0.125), 1) / 4; + + dml_print("DML: VStartup: %d\n", VStartup); + dml_print("DML: TCalc: %f\n", TCalc); + dml_print("DML: TWait: %f\n", TWait); + dml_print("DML: XFCRemoteSurfaceFlipDelay: %f\n", XFCRemoteSurfaceFlipDelay); + dml_print("DML: LineTime: %f\n", LineTime); + dml_print("DML: Tsetup: %f\n", Tsetup); + dml_print("DML: Tdm: %f\n", Tdm); + dml_print("DML: DSTYAfterScaler: %f\n", *DSTYAfterScaler); + dml_print("DML: DSTXAfterScaler: %f\n", *DSTXAfterScaler); + dml_print("DML: HTotal: %d\n", HTotal); + + *PrefetchBandwidth = 0; + *DestinationLinesToRequestVMInVBlank = 0; + *DestinationLinesToRequestRowInVBlank = 0; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + if (*DestinationLinesForPrefetch > 1) { + *PrefetchBandwidth = (PDEAndMetaPTEBytesFrame + 2 * MetaRowByte + + 2 * PixelPTEBytesPerRow + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 + * dml_ceil(BytePerPixelDETC, 2)) + / (*DestinationLinesForPrefetch * LineTime - *Tno_bw); + if (VirtualMemoryEnable) { + TimeForFetchingMetaPTE = + dml_max(*Tno_bw + + (double)PDEAndMetaPTEBytesFrame + / *PrefetchBandwidth, + dml_max(UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4)); + } else { + if (NumberOfCursors > 0 || XFCEnabled) + TimeForFetchingMetaPTE = LineTime / 4; + else + TimeForFetchingMetaPTE = 0.0; + } + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + TimeForFetchingRowInVBlank = + dml_max((MetaRowByte + PixelPTEBytesPerRow) + / *PrefetchBandwidth, + dml_max(UrgentLatency, + dml_max(LineTime + - TimeForFetchingMetaPTE, + LineTime + / 4.0))); + } else { + if (NumberOfCursors > 0 || XFCEnabled) + TimeForFetchingRowInVBlank = LineTime - TimeForFetchingMetaPTE; + else + TimeForFetchingRowInVBlank = 0.0; + } + + *DestinationLinesToRequestVMInVBlank = dml_floor(4.0 * (TimeForFetchingMetaPTE / LineTime + 0.125), + 1) / 4.0; + + *DestinationLinesToRequestRowInVBlank = dml_floor(4.0 * (TimeForFetchingRowInVBlank / LineTime + 0.125), + 1) / 4.0; + + LinesToRequestPrefetchPixelData = + *DestinationLinesForPrefetch + - ((NumberOfCursors > 0 || VirtualMemoryEnable + || DCCEnable) ? + (*DestinationLinesToRequestVMInVBlank + + *DestinationLinesToRequestRowInVBlank) : + 0.0); + + if (LinesToRequestPrefetchPixelData > 0) { + + *VRatioPrefetchY = (double)PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData; + *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); + if ((SwathHeightY > 4) && (VInitPreFillY > 3)) { + if (LinesToRequestPrefetchPixelData > (VInitPreFillY - 3.0) / 2.0) { + *VRatioPrefetchY = + dml_max((double)PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData, + (double)MaxNumSwathY + * SwathHeightY + / (LinesToRequestPrefetchPixelData + - (VInitPreFillY + - 3.0) + / 2.0)); + *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); + } else { + MyError = true; + *VRatioPrefetchY = 0; + } + } + + *VRatioPrefetchC = (double)PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData; + *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); + + if ((SwathHeightC > 4)) { + if (LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) { + *VRatioPrefetchC = + dml_max(*VRatioPrefetchC, + (double)MaxNumSwathC + * SwathHeightC + / (LinesToRequestPrefetchPixelData + - (VInitPreFillC + - 3.0) + / 2.0)); + *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); + } else { + MyError = true; + *VRatioPrefetchC = 0; + } + } + + *RequiredPrefetchPixDataBW = + DPPPerPlane + * ((double)PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData + * dml_ceil(BytePerPixelDETY, + 1) + + (double)PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData + * dml_ceil(BytePerPixelDETC, + 2) + / 2) + * SwathWidthY / LineTime; + } else { + MyError = true; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + } + + } else { + MyError = true; + } + + if (MyError) { + *PrefetchBandwidth = 0; + TimeForFetchingMetaPTE = 0; + TimeForFetchingRowInVBlank = 0; + *DestinationLinesToRequestVMInVBlank = 0; + *DestinationLinesToRequestRowInVBlank = 0; + *DestinationLinesForPrefetch = 0; + LinesToRequestPrefetchPixelData = 0; + *VRatioPrefetchY = 0; + *VRatioPrefetchC = 0; + *RequiredPrefetchPixDataBW = 0; + } + + return MyError; +} + +static double CeilToDFSGranularity(double Clock, double VCOSpeed) +{ + return VCOSpeed * 4 / dml_floor(VCOSpeed * 4 / Clock, 1); +} + +static double FloorToDFSGranularity(double Clock, double VCOSpeed) +{ + return VCOSpeed * 4 / dml_ceil(VCOSpeed * 4 / Clock, 1); +} + +static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath) +{ + unsigned int MaxPartialSwath; + + if (ProgressiveToInterlaceUnitInOPP) + *VInitPreFill = dml_floor((VRatio + vtaps + 1) / 2.0, 1); + else + *VInitPreFill = dml_floor((VRatio + vtaps + 1 + Interlace * 0.5 * VRatio) / 2.0, 1); + + if (!mode_lib->vba.IgnoreViewportPositioning) { + + *MaxNumSwath = dml_ceil((*VInitPreFill - 1.0) / SwathHeight, 1) + 1.0; + + if (*VInitPreFill > 1.0) + MaxPartialSwath = (unsigned int)(*VInitPreFill - 2) % SwathHeight; + else + MaxPartialSwath = (unsigned int)(*VInitPreFill + SwathHeight - 2) % SwathHeight; + MaxPartialSwath = dml_max(1U, MaxPartialSwath); + + } else { + + if (ViewportYStart != 0) + dml_print("WARNING DML: using viewport y position of 0 even though actual viewport y position is non-zero in prefetch source lines calculation\n"); + + *MaxNumSwath = dml_ceil(*VInitPreFill / SwathHeight, 1); + + if (*VInitPreFill > 1.0) + MaxPartialSwath = (unsigned int)(*VInitPreFill - 1) % SwathHeight; + else + MaxPartialSwath = (unsigned int)(*VInitPreFill + SwathHeight - 1) % SwathHeight; + } + + return *MaxNumSwath * SwathHeight + MaxPartialSwath; +} + +static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidth, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height) +{ + unsigned int MetaRequestHeight; + unsigned int MetaRequestWidth; + unsigned int MetaSurfWidth; + unsigned int MetaSurfHeight; + unsigned int MPDEBytesFrame; + unsigned int MetaPTEBytesFrame; + unsigned int DCCMetaSurfaceBytes; + + unsigned int MacroTileSizeBytes; + unsigned int MacroTileHeight; + unsigned int DPDE0BytesFrame; + unsigned int ExtraDPDEBytesFrame; + unsigned int PDEAndMetaPTEBytesFrame; + + if (DCCEnable == true) { + MetaRequestHeight = 8 * BlockHeight256Bytes; + MetaRequestWidth = 8 * BlockWidth256Bytes; + if (ScanDirection == dm_horz) { + *meta_row_height = MetaRequestHeight; + MetaSurfWidth = dml_ceil((double)SwathWidth - 1, MetaRequestWidth) + + MetaRequestWidth; + *MetaRowByte = MetaSurfWidth * MetaRequestHeight * BytePerPixel / 256.0; + } else { + *meta_row_height = MetaRequestWidth; + MetaSurfHeight = dml_ceil((double)SwathWidth - 1, MetaRequestHeight) + + MetaRequestHeight; + *MetaRowByte = MetaSurfHeight * MetaRequestWidth * BytePerPixel / 256.0; + } + if (ScanDirection == dm_horz) { + DCCMetaSurfaceBytes = DCCMetaPitch + * (dml_ceil(ViewportHeight - 1, 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; + } else { + DCCMetaSurfaceBytes = DCCMetaPitch + * (dml_ceil((double)ViewportHeight - 1, + 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; + } + if (VirtualMemoryEnable == true) { + MetaPTEBytesFrame = (dml_ceil((double)(DCCMetaSurfaceBytes - VMMPageSize) + / (8 * VMMPageSize), + 1) + 1) * 64; + MPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 1); + } else { + MetaPTEBytesFrame = 0; + MPDEBytesFrame = 0; + } + } else { + MetaPTEBytesFrame = 0; + MPDEBytesFrame = 0; + *MetaRowByte = 0; + } + + if (SurfaceTiling == dm_sw_linear) { + MacroTileSizeBytes = 256; + MacroTileHeight = 1; + } else if (SurfaceTiling == dm_sw_4kb_s || SurfaceTiling == dm_sw_4kb_s_x + || SurfaceTiling == dm_sw_4kb_d || SurfaceTiling == dm_sw_4kb_d_x) { + MacroTileSizeBytes = 4096; + MacroTileHeight = 4 * BlockHeight256Bytes; + } else if (SurfaceTiling == dm_sw_64kb_s || SurfaceTiling == dm_sw_64kb_s_t + || SurfaceTiling == dm_sw_64kb_s_x || SurfaceTiling == dm_sw_64kb_d + || SurfaceTiling == dm_sw_64kb_d_t || SurfaceTiling == dm_sw_64kb_d_x + || SurfaceTiling == dm_sw_64kb_r_x) { + MacroTileSizeBytes = 65536; + MacroTileHeight = 16 * BlockHeight256Bytes; + } else { + MacroTileSizeBytes = 262144; + MacroTileHeight = 32 * BlockHeight256Bytes; + } + *MacroTileWidth = MacroTileSizeBytes / BytePerPixel / MacroTileHeight; + + if (VirtualMemoryEnable == true && mode_lib->vba.MaxPageTableLevels > 1) { + if (ScanDirection == dm_horz) { + DPDE0BytesFrame = + 64 + * (dml_ceil(((Pitch + * (dml_ceil(ViewportHeight + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); + } else { + DPDE0BytesFrame = + 64 + * (dml_ceil(((Pitch + * (dml_ceil((double)SwathWidth + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); + } + ExtraDPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 2); + } else { + DPDE0BytesFrame = 0; + ExtraDPDEBytesFrame = 0; + } + + PDEAndMetaPTEBytesFrame = MetaPTEBytesFrame + MPDEBytesFrame + DPDE0BytesFrame + + ExtraDPDEBytesFrame; + + if (VirtualMemoryEnable == true) { + unsigned int PTERequestSize; + unsigned int PixelPTEReqHeight; + unsigned int PixelPTEReqWidth; + double FractionOfPTEReturnDrop; + unsigned int EffectivePDEProcessingBufIn64KBReqs; + + if (SurfaceTiling == dm_sw_linear) { + PixelPTEReqHeight = 1; + PixelPTEReqWidth = 8.0 * VMMPageSize / BytePerPixel; + PTERequestSize = 64; + FractionOfPTEReturnDrop = 0; + } else if (MacroTileSizeBytes == 4096) { + PixelPTEReqHeight = MacroTileHeight; + PixelPTEReqWidth = 8 * *MacroTileWidth; + PTERequestSize = 64; + if (ScanDirection == dm_horz) + FractionOfPTEReturnDrop = 0; + else + FractionOfPTEReturnDrop = 7 / 8; + } else if (VMMPageSize == 4096 && MacroTileSizeBytes > 4096) { + PixelPTEReqHeight = 16 * BlockHeight256Bytes; + PixelPTEReqWidth = 16 * BlockWidth256Bytes; + PTERequestSize = 128; + FractionOfPTEReturnDrop = 0; + } else { + PixelPTEReqHeight = MacroTileHeight; + PixelPTEReqWidth = 8 * *MacroTileWidth; + PTERequestSize = 64; + FractionOfPTEReturnDrop = 0; + } + + if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) + EffectivePDEProcessingBufIn64KBReqs = PDEProcessingBufIn64KBReqs / 2; + else + EffectivePDEProcessingBufIn64KBReqs = PDEProcessingBufIn64KBReqs; + + if (SurfaceTiling == dm_sw_linear) { + *dpte_row_height = + dml_min(128, + 1 + << (unsigned int)dml_floor(dml_log2(dml_min((double)PTEBufferSizeInRequests + * PixelPTEReqWidth, + EffectivePDEProcessingBufIn64KBReqs + * 65536.0 + / BytePerPixel) + / Pitch), + 1)); + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil((double)(Pitch * *dpte_row_height - 1) + / PixelPTEReqWidth, + 1) + 1); + } else if (ScanDirection == dm_horz) { + *dpte_row_height = PixelPTEReqHeight; + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil(((double)SwathWidth - 1) / PixelPTEReqWidth, 1) + + 1); + } else { + *dpte_row_height = dml_min(PixelPTEReqWidth, *MacroTileWidth); + *PixelPTEBytesPerRow = PTERequestSize + * (dml_ceil(((double)SwathWidth - 1) + / PixelPTEReqHeight, + 1) + 1); + } + if (*PixelPTEBytesPerRow * (1 - FractionOfPTEReturnDrop) + <= 64 * PTEBufferSizeInRequests) { + *PTEBufferSizeNotExceeded = true; + } else { + *PTEBufferSizeNotExceeded = false; + } + } else { + *PixelPTEBytesPerRow = 0; + *PTEBufferSizeNotExceeded = true; + } + + return PDEAndMetaPTEBytesFrame; +} + +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib) +{ + unsigned int j, k; + + mode_lib->vba.WritebackDISPCLK = 0.0; + mode_lib->vba.DISPCLKWithRamping = 0; + mode_lib->vba.DISPCLKWithoutRamping = 0; + mode_lib->vba.GlobalDPPCLK = 0.0; + + // dml_ml->vba.DISPCLK and dml_ml->vba.DPPCLK Calculation + // + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.WritebackEnable[k]) { + mode_lib->vba.WritebackDISPCLK = dml_max(mode_lib->vba.WritebackDISPCLK, + CalculateWriteBackDISPCLK(mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.PixelClock[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.WritebackChromaLineBufferWidth)); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.HRatio[k] > 1) { + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput * mode_lib->vba.HRatio[k] + / dml_ceil(mode_lib->vba.htaps[k] / 6.0, 1)); + } else { + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + + mode_lib->vba.DPPCLKUsingSingleDPPLuma = + mode_lib->vba.PixelClock[k] + * dml_max(mode_lib->vba.vtaps[k] / 6.0 + * dml_min(1.0, + mode_lib->vba.HRatio[k]), + dml_max(mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k], + 1.0)); + + if ((mode_lib->vba.htaps[k] > 6 || mode_lib->vba.vtaps[k] > 6) + && mode_lib->vba.DPPCLKUsingSingleDPPLuma < 2 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.DPPCLKUsingSingleDPPLuma = 2 * mode_lib->vba.PixelClock[k]; + } + + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = 0.0; + mode_lib->vba.DPPCLKUsingSingleDPP[k] = mode_lib->vba.DPPCLKUsingSingleDPPLuma; + } else { + if (mode_lib->vba.HRatio[k] > 1) { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = + dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput * mode_lib->vba.HRatio[k] + / 2 + / dml_ceil(mode_lib->vba.HTAPsChroma[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + mode_lib->vba.DPPCLKUsingSingleDPPChroma = + mode_lib->vba.PixelClock[k] + * dml_max(mode_lib->vba.VTAPsChroma[k] / 6.0 + * dml_min(1.0, + mode_lib->vba.HRatio[k] + / 2), + dml_max(mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / 4 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k], + 1.0)); + + if ((mode_lib->vba.HTAPsChroma[k] > 6 || mode_lib->vba.VTAPsChroma[k] > 6) + && mode_lib->vba.DPPCLKUsingSingleDPPChroma < 2 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.DPPCLKUsingSingleDPPChroma = 2 * mode_lib->vba.PixelClock[k]; + } + + mode_lib->vba.DPPCLKUsingSingleDPP[k] = dml_max(mode_lib->vba.DPPCLKUsingSingleDPPLuma, + mode_lib->vba.DPPCLKUsingSingleDPPChroma); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.BlendingAndTiming[k] != k) + continue; + if (mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DISPCLKWithRamping = + dml_max(mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100) + * (1 + + mode_lib->vba.DISPCLKRampingMargin + / 100)); + mode_lib->vba.DISPCLKWithoutRamping = + dml_max(mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); + } else if (!mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DISPCLKWithRamping = dml_max(mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100) + * (1 + mode_lib->vba.DISPCLKRampingMargin / 100)); + mode_lib->vba.DISPCLKWithoutRamping = + dml_max(mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); + } + } + + mode_lib->vba.DISPCLKWithRamping = dml_max(mode_lib->vba.DISPCLKWithRamping, mode_lib->vba.WritebackDISPCLK); + mode_lib->vba.DISPCLKWithoutRamping = dml_max(mode_lib->vba.DISPCLKWithoutRamping, mode_lib->vba.WritebackDISPCLK); + + mode_lib->vba.MaxDispclk = mode_lib->vba.soc.clock_limits[NumberOfStates - 1].dispclk_mhz; + ASSERT(mode_lib->vba.DISPCLKDPPCLKVCOSpeed != 0); + mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity = CeilToDFSGranularity( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity = CeilToDFSGranularity( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.MaxDispclkRoundedToDFSGranularity = FloorToDFSGranularity( + mode_lib->vba.MaxDispclk, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + if (mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + mode_lib->vba.DISPCLK_calculated = mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity; + } else if (mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + mode_lib->vba.DISPCLK_calculated = mode_lib->vba.MaxDispclkRoundedToDFSGranularity; + } else { + mode_lib->vba.DISPCLK_calculated = mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity; + } + DTRACE(" dispclk_mhz (calculated) = %f", mode_lib->vba.DISPCLK_calculated); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.DPPCLKUsingSingleDPP[k] / mode_lib->vba.DPPPerPlane[k] + * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.GlobalDPPCLK = dml_max(mode_lib->vba.GlobalDPPCLK, mode_lib->vba.DPPCLK_calculated[k]); + } + mode_lib->vba.GlobalDPPCLK = CeilToDFSGranularity(mode_lib->vba.GlobalDPPCLK, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.GlobalDPPCLK / 255 + * dml_ceil(mode_lib->vba.DPPCLK_calculated[k] * 255 / mode_lib->vba.GlobalDPPCLK, 1); + DTRACE(" dppclk_mhz[%i] (calculated) = %f", k, mode_lib->vba.DPPCLK_calculated[k]); + } + + // Urgent Watermark + mode_lib->vba.DCCEnabledAnyPlane = false; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + if (mode_lib->vba.DCCEnable[k]) + mode_lib->vba.DCCEnabledAnyPlane = true; + + mode_lib->vba.ReturnBandwidthToDCN = dml_min(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, mode_lib->vba.FabricAndDRAMBandwidth * 1000) + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency / 100; + + mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBandwidthToDCN; + mode_lib->vba.ReturnBW = adjust_ReturnBW(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.DCCEnabledAnyPlane, mode_lib->vba.ReturnBandwidthToDCN); + + // Let's do this calculation again?? + mode_lib->vba.ReturnBandwidthToDCN = dml_min(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, mode_lib->vba.FabricAndDRAMBandwidth * 1000); + mode_lib->vba.ReturnBW = adjust_ReturnBW(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.DCCEnabledAnyPlane, mode_lib->vba.ReturnBandwidthToDCN); + + DTRACE(" dcfclk_mhz = %f", mode_lib->vba.DCFCLK); + DTRACE(" return_bw_to_dcn = %f", mode_lib->vba.ReturnBandwidthToDCN); + DTRACE(" return_bus_bw = %f", mode_lib->vba.ReturnBW); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + bool MainPlaneDoesODMCombine = false; + + if (mode_lib->vba.SourceScan[k] == dm_horz) + mode_lib->vba.SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportWidth[k]; + else + mode_lib->vba.SwathWidthSingleDPPY[k] = mode_lib->vba.ViewportHeight[k]; + + if (mode_lib->vba.ODMCombineEnabled[k] == true) + MainPlaneDoesODMCombine = true; + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + if (mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.ODMCombineEnabled[j] == true) + MainPlaneDoesODMCombine = true; + + if (MainPlaneDoesODMCombine == true) + mode_lib->vba.SwathWidthY[k] = dml_min((double)mode_lib->vba.SwathWidthSingleDPPY[k], + dml_round(mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k])); + else + mode_lib->vba.SwathWidthY[k] = mode_lib->vba.SwathWidthSingleDPPY[k] / mode_lib->vba.DPPPerPlane[k]; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + mode_lib->vba.BytePerPixelDETY[k] = 8; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + mode_lib->vba.BytePerPixelDETY[k] = 4; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + mode_lib->vba.BytePerPixelDETY[k] = 2; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8) { + mode_lib->vba.BytePerPixelDETY[k] = 1; + mode_lib->vba.BytePerPixelDETC[k] = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + mode_lib->vba.BytePerPixelDETY[k] = 1; + mode_lib->vba.BytePerPixelDETC[k] = 2; + } else { // dm_420_10 + mode_lib->vba.BytePerPixelDETY[k] = 4.0 / 3.0; + mode_lib->vba.BytePerPixelDETC[k] = 8.0 / 3.0; + } + } + + mode_lib->vba.TotalDataReadBandwidth = 0.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.ReadBandwidthPlaneLuma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + mode_lib->vba.ReadBandwidthPlaneChroma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] / 2 + * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k] / 2; + DTRACE(" read_bw[%i] = %fBps", + k, + mode_lib->vba.ReadBandwidthPlaneLuma[k] + mode_lib->vba.ReadBandwidthPlaneChroma[k]); + mode_lib->vba.TotalDataReadBandwidth += mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k]; + } + + mode_lib->vba.TotalDCCActiveDPP = 0; + mode_lib->vba.TotalActiveDPP = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP + mode_lib->vba.DPPPerPlane[k]; + if (mode_lib->vba.DCCEnable[k]) + mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP + mode_lib->vba.DPPPerPlane[k]; + } + + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency = (mode_lib->vba.RoundTripPingLatencyCycles + 32) / mode_lib->vba.DCFCLK + + mode_lib->vba.UrgentOutOfOrderReturnPerChannel * mode_lib->vba.NumberOfChannels / mode_lib->vba.ReturnBW; + + mode_lib->vba.LastPixelOfLineExtraWatermark = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double DataFabricLineDeliveryTimeLuma, DataFabricLineDeliveryTimeChroma; + + if (mode_lib->vba.VRatio[k] <= 1.0) + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = (double)mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] / mode_lib->vba.PixelClock[k]; + else + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = (double)mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] / mode_lib->vba.DPPCLK[k]; + + DataFabricLineDeliveryTimeLuma = + mode_lib->vba.SwathWidthSingleDPPY[k] * mode_lib->vba.SwathHeightY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) + / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneLuma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max(mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeLuma + - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]); + + if (mode_lib->vba.BytePerPixelDETC[k] == 0) + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = 0.0; + else if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0) + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = mode_lib->vba.SwathWidthY[k] / 2.0 + * mode_lib->vba.DPPPerPlane[k] / (mode_lib->vba.HRatio[k] / 2.0) / mode_lib->vba.PixelClock[k]; + else + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = mode_lib->vba.SwathWidthY[k] / 2.0 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] / mode_lib->vba.DPPCLK[k]; + + DataFabricLineDeliveryTimeChroma = mode_lib->vba.SwathWidthSingleDPPY[k] / 2.0 + * mode_lib->vba.SwathHeightC[k] * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) + / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max(mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeChroma + - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + } + + mode_lib->vba.UrgentExtraLatency = mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency + + (mode_lib->vba.TotalActiveDPP * mode_lib->vba.PixelChunkSizeInKByte + + mode_lib->vba.TotalDCCActiveDPP * mode_lib->vba.MetaChunkSize) * 1024.0 + / mode_lib->vba.ReturnBW; + + if (mode_lib->vba.VirtualMemoryEnable) + mode_lib->vba.UrgentExtraLatency += mode_lib->vba.TotalActiveDPP * mode_lib->vba.PTEChunkSize * 1024.0 / mode_lib->vba.ReturnBW; + + mode_lib->vba.UrgentWatermark = mode_lib->vba.UrgentLatency + mode_lib->vba.LastPixelOfLineExtraWatermark + mode_lib->vba.UrgentExtraLatency; + + DTRACE(" urgent_extra_latency = %fus", mode_lib->vba.UrgentExtraLatency); + DTRACE(" wm_urgent = %fus", mode_lib->vba.UrgentWatermark); + + mode_lib->vba.MemoryTripWatermark = mode_lib->vba.UrgentLatency; + + mode_lib->vba.TotalActiveWriteback = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.WritebackEnable[k]) + mode_lib->vba.TotalActiveWriteback = mode_lib->vba.TotalActiveWriteback + 1; + } + + if (mode_lib->vba.TotalActiveWriteback <= 1) + mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency; + else + mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 / mode_lib->vba.SOCCLK; + + DTRACE(" wm_wb_urgent = %fus", mode_lib->vba.WritebackUrgentWatermark); + + // NB P-State/DRAM Clock Change Watermark + mode_lib->vba.DRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.UrgentWatermark; + + DTRACE(" wm_pstate_change = %fus", mode_lib->vba.DRAMClockChangeWatermark); + + DTRACE(" calculating wb pstate watermark"); + DTRACE(" total wb outputs %d", mode_lib->vba.TotalActiveWriteback); + DTRACE(" socclk frequency %f Mhz", mode_lib->vba.SOCCLK); + + if (mode_lib->vba.TotalActiveWriteback <= 1) + mode_lib->vba.WritebackDRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.WritebackLatency; + else + mode_lib->vba.WritebackDRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.WritebackLatency + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 / mode_lib->vba.SOCCLK; + + DTRACE(" wm_wb_pstate %fus", mode_lib->vba.WritebackDRAMClockChangeWatermark); + + // Stutter Efficiency + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.LinesInDETY[k] = mode_lib->vba.DETBufferSizeY[k] / mode_lib->vba.BytePerPixelDETY[k] + / mode_lib->vba.SwathWidthY[k]; + mode_lib->vba.LinesInDETYRoundedDownToSwath[k] = dml_floor(mode_lib->vba.LinesInDETY[k], + mode_lib->vba.SwathHeightY[k]); + mode_lib->vba.FullDETBufferingTimeY[k] = mode_lib->vba.LinesInDETYRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / mode_lib->vba.VRatio[k]; + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.LinesInDETC[k] = mode_lib->vba.DETBufferSizeC[k] / mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.SwathWidthY[k] / 2); + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = dml_floor(mode_lib->vba.LinesInDETC[k], + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.FullDETBufferingTimeC[k] = mode_lib->vba.LinesInDETCRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / (mode_lib->vba.VRatio[k] / 2); + } else { + mode_lib->vba.LinesInDETC[k] = 0; + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = 0; + mode_lib->vba.FullDETBufferingTimeC[k] = 999999; + } + } + + mode_lib->vba.MinFullDETBufferingTime = 999999.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.FullDETBufferingTimeY[k] < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = mode_lib->vba.FullDETBufferingTimeY[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = (double)mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } + if (mode_lib->vba.FullDETBufferingTimeC[k] < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = mode_lib->vba.FullDETBufferingTimeC[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = (double)mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } + } + + mode_lib->vba.AverageReadBandwidthGBytePerSecond = 0.0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.DCCEnable[k]) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] / mode_lib->vba.DCCRate[k] + / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.DCCRate[k] / 1000; + } else { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000; + } + if (mode_lib->vba.DCCEnable[k]) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 / 256 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000 + / 256; + } + if (mode_lib->vba.VirtualMemoryEnable) { + mode_lib->vba.AverageReadBandwidthGBytePerSecond = + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 / 512 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000 + / 512; + } + } + + mode_lib->vba.PartOfBurstThatFitsInROB = dml_min(mode_lib->vba.MinFullDETBufferingTime * mode_lib->vba.TotalDataReadBandwidth, + mode_lib->vba.ROBBufferSizeInKByte * 1024 * mode_lib->vba.TotalDataReadBandwidth + / (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000)); + mode_lib->vba.StutterBurstTime = mode_lib->vba.PartOfBurstThatFitsInROB + * (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000) / mode_lib->vba.TotalDataReadBandwidth + / mode_lib->vba.ReturnBW + + (mode_lib->vba.MinFullDETBufferingTime * mode_lib->vba.TotalDataReadBandwidth + - mode_lib->vba.PartOfBurstThatFitsInROB) / (mode_lib->vba.DCFCLK * 64); + if (mode_lib->vba.TotalActiveWriteback == 0) { + mode_lib->vba.StutterEfficiencyNotIncludingVBlank = (1 + - (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime) / mode_lib->vba.MinFullDETBufferingTime) + * 100; + } else { + mode_lib->vba.StutterEfficiencyNotIncludingVBlank = 0; + } + + mode_lib->vba.SmallestVBlank = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { + mode_lib->vba.VBlankTime = (double)(mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k]) * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.VBlankTime = 0; + } + mode_lib->vba.SmallestVBlank = dml_min(mode_lib->vba.SmallestVBlank, mode_lib->vba.VBlankTime); + } + + mode_lib->vba.StutterEfficiency = (mode_lib->vba.StutterEfficiencyNotIncludingVBlank / 100 + * (mode_lib->vba.FrameTimeForMinFullDETBufferingTime - mode_lib->vba.SmallestVBlank) + + mode_lib->vba.SmallestVBlank) / mode_lib->vba.FrameTimeForMinFullDETBufferingTime * 100; + + // dml_ml->vba.DCFCLK Deep Sleep + mode_lib->vba.DCFClkDeepSleep = 8.0; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; k++) { + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max(1.1 * mode_lib->vba.SwathWidthY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k], + 1.1 * mode_lib->vba.SwathWidthY[k] / 2.0 + * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + } else + mode_lib->vba.DCFCLKDeepSleepPerPlane = 1.1 * mode_lib->vba.SwathWidthY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 64.0 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]; + mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max(mode_lib->vba.DCFCLKDeepSleepPerPlane, + mode_lib->vba.PixelClock[k] / 16.0); + mode_lib->vba.DCFClkDeepSleep = dml_max(mode_lib->vba.DCFClkDeepSleep, mode_lib->vba.DCFCLKDeepSleepPerPlane); + + DTRACE(" dcfclk_deepsleep_per_plane[%i] = %fMHz", k, mode_lib->vba.DCFCLKDeepSleepPerPlane); + } + + DTRACE(" dcfclk_deepsleep_mhz = %fMHz", mode_lib->vba.DCFClkDeepSleep); + + // Stutter Watermark + mode_lib->vba.StutterExitWatermark = mode_lib->vba.SRExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark + mode_lib->vba.UrgentExtraLatency + + 10 / mode_lib->vba.DCFClkDeepSleep; + mode_lib->vba.StutterEnterPlusExitWatermark = mode_lib->vba.SREnterPlusExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency; + + DTRACE(" wm_cstate_exit = %fus", mode_lib->vba.StutterExitWatermark); + DTRACE(" wm_cstate_enter_exit = %fus", mode_lib->vba.StutterEnterPlusExitWatermark); + + // Urgent Latency Supported + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.EffectiveDETPlusLBLinesLuma = + dml_floor(mode_lib->vba.LinesInDETY[k] + + dml_min(mode_lib->vba.LinesInDETY[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETY[k] + * mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double)mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), + mode_lib->vba.SwathHeightY[k]); + + mode_lib->vba.UrgentLatencySupportUsLuma = mode_lib->vba.EffectiveDETPlusLBLinesLuma + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETPlusLBLinesLuma * mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.BytePerPixelDETY[k] + / (mode_lib->vba.ReturnBW / mode_lib->vba.DPPPerPlane[k]); + + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + mode_lib->vba.EffectiveDETPlusLBLinesChroma = + dml_floor(mode_lib->vba.LinesInDETC[k] + + dml_min(mode_lib->vba.LinesInDETC[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETC[k] + * mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double)mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.UrgentLatencySupportUsChroma = mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / (mode_lib->vba.VRatio[k] / 2) + - mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.SwathWidthY[k] / 2) + * mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.ReturnBW / mode_lib->vba.DPPPerPlane[k]); + mode_lib->vba.UrgentLatencySupportUs[k] = dml_min(mode_lib->vba.UrgentLatencySupportUsLuma, + mode_lib->vba.UrgentLatencySupportUsChroma); + } else { + mode_lib->vba.UrgentLatencySupportUs[k] = mode_lib->vba.UrgentLatencySupportUsLuma; + } + } + + mode_lib->vba.MinUrgentLatencySupportUs = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.MinUrgentLatencySupportUs = dml_min(mode_lib->vba.MinUrgentLatencySupportUs, + mode_lib->vba.UrgentLatencySupportUs[k]); + } + + // Non-Urgent Latency Tolerance + mode_lib->vba.NonUrgentLatencyTolerance = mode_lib->vba.MinUrgentLatencySupportUs - mode_lib->vba.UrgentWatermark; + + // DSCCLK + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if ((mode_lib->vba.BlendingAndTiming[k] != k) || !mode_lib->vba.DSCEnabled[k]) { + mode_lib->vba.DSCCLK_calculated[k] = 0.0; + } else { + if (mode_lib->vba.OutputFormat[k] == dm_420 || mode_lib->vba.OutputFormat[k] == dm_n422) + mode_lib->vba.DSCFormatFactor = 2; + else + mode_lib->vba.DSCFormatFactor = 1; + if (mode_lib->vba.ODMCombineEnabled[k]) + mode_lib->vba.DSCCLK_calculated[k] = mode_lib->vba.PixelClockBackEnd[k] / 6 + / mode_lib->vba.DSCFormatFactor + / (1 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + else + mode_lib->vba.DSCCLK_calculated[k] = mode_lib->vba.PixelClockBackEnd[k] / 3 + / mode_lib->vba.DSCFormatFactor + / (1 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + } + } + + // DSC Delay + // TODO + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double bpp = mode_lib->vba.OutputBpp[k]; + unsigned int slices = mode_lib->vba.NumberOfDSCSlices[k]; + + if (mode_lib->vba.DSCEnabled[k] && bpp != 0) { + if (!mode_lib->vba.ODMCombineEnabled[k]) { + mode_lib->vba.DSCDelay[k] = + dscceComputeDelay(mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil((double)mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay(mode_lib->vba.OutputFormat[k]); + } else { + mode_lib->vba.DSCDelay[k] = + 2 + * (dscceComputeDelay(mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil((double)mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices / 2.0, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay(mode_lib->vba.OutputFormat[k])); + } + mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[k] * mode_lib->vba.PixelClock[k] / mode_lib->vba.PixelClockBackEnd[k]; + } else { + mode_lib->vba.DSCDelay[k] = 0; + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) // NumberOfPlanes + if (j != k && mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.DSCEnabled[j]) + mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[j]; + + // Prefetch + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + unsigned int PDEAndMetaPTEBytesFrameY; + unsigned int PixelPTEBytesPerRowY; + unsigned int MetaRowByteY; + unsigned int MetaRowByteC; + unsigned int PDEAndMetaPTEBytesFrameC; + unsigned int PixelPTEBytesPerRowC; + + Calculate256BBlockSizes(mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), + &mode_lib->vba.BlockHeight256BytesY[k], + &mode_lib->vba.BlockHeight256BytesC[k], + &mode_lib->vba.BlockWidth256BytesY[k], + &mode_lib->vba.BlockWidth256BytesC[k]); + PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes(mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesY[k], + mode_lib->vba.BlockWidth256BytesY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k], + mode_lib->vba.ViewportHeight[k], + mode_lib->vba.SwathWidthY[k], + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchY[k], + mode_lib->vba.DCCMetaPitchY[k], + &mode_lib->vba.MacroTileWidthY, + &MetaRowByteY, + &PixelPTEBytesPerRowY, + &mode_lib->vba.PTEBufferSizeNotExceeded, + &mode_lib->vba.dpte_row_height[k], + &mode_lib->vba.meta_row_height[k]); + mode_lib->vba.PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines(mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.vtaps[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.ViewportYStartY[k], + &mode_lib->vba.VInitPreFillY[k], + &mode_lib->vba.MaxNumSwathY[k]); + + if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_8)) { + PDEAndMetaPTEBytesFrameC = CalculateVMAndRowBytes(mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesC[k], + mode_lib->vba.BlockWidth256BytesC[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k] / 2, + mode_lib->vba.ViewportHeight[k] / 2, + mode_lib->vba.SwathWidthY[k] / 2, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchC[k], + 0, + &mode_lib->vba.MacroTileWidthC, + &MetaRowByteC, + &PixelPTEBytesPerRowC, + &mode_lib->vba.PTEBufferSizeNotExceeded, + &mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_height_chroma[k]); + mode_lib->vba.PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines(mode_lib, + mode_lib->vba.VRatio[k] / 2, + mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightC[k], + mode_lib->vba.ViewportYStartC[k], + &mode_lib->vba.VInitPreFillC[k], + &mode_lib->vba.MaxNumSwathC[k]); + } else { + PixelPTEBytesPerRowC = 0; + PDEAndMetaPTEBytesFrameC = 0; + MetaRowByteC = 0; + mode_lib->vba.MaxNumSwathC[k] = 0; + mode_lib->vba.PrefetchSourceLinesC[k] = 0; + } + + mode_lib->vba.PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY + PixelPTEBytesPerRowC; + mode_lib->vba.PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + PDEAndMetaPTEBytesFrameC; + mode_lib->vba.MetaRowByte[k] = MetaRowByteY + MetaRowByteC; + + CalculateActiveRowBandwidth(mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + MetaRowByteY, + MetaRowByteC, + mode_lib->vba.meta_row_height[k], + mode_lib->vba.meta_row_height_chroma[k], + PixelPTEBytesPerRowY, + PixelPTEBytesPerRowC, + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_bw[k], + &mode_lib->vba.dpte_row_bw[k], + &mode_lib->vba.qual_row_bw[k]); + } + + mode_lib->vba.TCalc = 24.0 / mode_lib->vba.DCFClkDeepSleep; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackDelay[k] = mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay(mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k]) + / mode_lib->vba.DISPCLK; + } else + mode_lib->vba.WritebackDelay[k] = 0; + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + if (mode_lib->vba.BlendingAndTiming[j] == k && mode_lib->vba.WritebackEnable[j] == true) { + mode_lib->vba.WritebackDelay[k] = + dml_max(mode_lib->vba.WritebackDelay[k], + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay(mode_lib->vba.WritebackPixelFormat[j], + mode_lib->vba.WritebackHRatio[j], + mode_lib->vba.WritebackVRatio[j], + mode_lib->vba.WritebackLumaHTaps[j], + mode_lib->vba.WritebackLumaVTaps[j], + mode_lib->vba.WritebackChromaHTaps[j], + mode_lib->vba.WritebackChromaVTaps[j], + mode_lib->vba.WritebackDestinationWidth[j]) + / mode_lib->vba.DISPCLK); + } + } + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) + if (mode_lib->vba.BlendingAndTiming[k] == j) + mode_lib->vba.WritebackDelay[k] = mode_lib->vba.WritebackDelay[j]; + + mode_lib->vba.VStartupLines = 13; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.MaxVStartupLines[k] = + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] + - dml_max(1.0, + dml_ceil(mode_lib->vba.WritebackDelay[k] + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1)); + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) + mode_lib->vba.MaximumMaxVStartupLines = dml_max(mode_lib->vba.MaximumMaxVStartupLines, mode_lib->vba.MaxVStartupLines[k]); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.cursor_bw[k] = 0.0; + for (j = 0; j < mode_lib->vba.NumberOfCursors[k]; ++j) + mode_lib->vba.cursor_bw[k] += mode_lib->vba.CursorWidth[k][j] * mode_lib->vba.CursorBPP[k][j] / 8.0 + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * mode_lib->vba.VRatio[k]; + } + + do { + double MaxTotalRDBandwidth = 0; + bool DestinationLineTimesForPrefetchLessThan2 = false; + bool VRatioPrefetchMoreThan4 = false; + bool prefetch_vm_bw_valid = true; + bool prefetch_row_bw_valid = true; + double TWait = CalculateTWait(mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.XFCEnabled[k] == true) { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + } else { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0; + } + mode_lib->vba.ErrorResult[k] = CalculatePrefetchSchedule(mode_lib, + mode_lib->vba.DPPCLK[k], + mode_lib->vba.DISPCLK, + mode_lib->vba.PixelClock[k], + mode_lib->vba.DCFClkDeepSleep, + mode_lib->vba.DSCDelay[k], + mode_lib->vba.DPPPerPlane[k], + mode_lib->vba.ScalerEnabled[k], + mode_lib->vba.NumberOfCursors[k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + (unsigned int)(mode_lib->vba.SwathWidthY[k] / mode_lib->vba.HRatio[k]), + mode_lib->vba.OutputFormat[k], + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + dml_min(mode_lib->vba.VStartupLines, mode_lib->vba.MaxVStartupLines[k]), + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.TCalc, + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.PrefetchSourceLinesY[k], + mode_lib->vba.SwathWidthY[k], + mode_lib->vba.BytePerPixelDETY[k], + mode_lib->vba.VInitPreFillY[k], + mode_lib->vba.MaxNumSwathY[k], + mode_lib->vba.PrefetchSourceLinesC[k], + mode_lib->vba.BytePerPixelDETC[k], + mode_lib->vba.VInitPreFillC[k], + mode_lib->vba.MaxNumSwathC[k], + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.SwathHeightC[k], + TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + &mode_lib->vba.DSTXAfterScaler[k], + &mode_lib->vba.DSTYAfterScaler[k], + &mode_lib->vba.DestinationLinesForPrefetch[k], + &mode_lib->vba.PrefetchBandwidth[k], + &mode_lib->vba.DestinationLinesToRequestVMInVBlank[k], + &mode_lib->vba.DestinationLinesToRequestRowInVBlank[k], + &mode_lib->vba.VRatioPrefetchY[k], + &mode_lib->vba.VRatioPrefetchC[k], + &mode_lib->vba.RequiredPrefetchPixDataBW[k], + &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &mode_lib->vba.Tno_bw[k]); + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.VStartup[k] = dml_min(mode_lib->vba.VStartupLines, mode_lib->vba.MaxVStartupLines[k]); + if (mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata != 0) { + mode_lib->vba.VStartup[k] = + mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; + } + } else { + mode_lib->vba.VStartup[k] = dml_min(mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]); + } + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + + if (mode_lib->vba.PDEAndMetaPTEBytesFrame[k] == 0) + mode_lib->vba.prefetch_vm_bw[k] = 0; + else if (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] > 0) { + mode_lib->vba.prefetch_vm_bw[k] = (double)mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + / (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_vm_bw[k] = 0; + prefetch_vm_bw_valid = false; + } + if (mode_lib->vba.MetaRowByte[k] + mode_lib->vba.PixelPTEBytesPerRow[k] == 0) + mode_lib->vba.prefetch_row_bw[k] = 0; + else if (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] > 0) { + mode_lib->vba.prefetch_row_bw[k] = (double)(mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]) + / (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] + * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_row_bw[k] = 0; + prefetch_row_bw_valid = false; + } + + MaxTotalRDBandwidth = + MaxTotalRDBandwidth + mode_lib->vba.cursor_bw[k] + + dml_max(mode_lib->vba.prefetch_vm_bw[k], + dml_max(mode_lib->vba.prefetch_row_bw[k], + dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]) + + mode_lib->vba.meta_row_bw[k] + + mode_lib->vba.dpte_row_bw[k])); + + if (mode_lib->vba.DestinationLinesForPrefetch[k] < 2) + DestinationLineTimesForPrefetchLessThan2 = true; + if (mode_lib->vba.VRatioPrefetchY[k] > 4 || mode_lib->vba.VRatioPrefetchC[k] > 4) + VRatioPrefetchMoreThan4 = true; + } + + if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && prefetch_vm_bw_valid && prefetch_row_bw_valid + && !VRatioPrefetchMoreThan4 + && !DestinationLineTimesForPrefetchLessThan2) + mode_lib->vba.PrefetchModeSupported = true; + else { + mode_lib->vba.PrefetchModeSupported = false; + dml_print("DML: CalculatePrefetchSchedule ***failed***. Bandwidth violation. Results are NOT valid\n"); + } + + if (mode_lib->vba.PrefetchModeSupported == true) { + double final_flip_bw[DC__NUM_PIPES__MAX]; + unsigned int ImmediateFlipBytes[DC__NUM_PIPES__MAX]; + double total_dcn_read_bw_with_flip = 0; + + mode_lib->vba.BandwidthAvailableForImmediateFlip = mode_lib->vba.ReturnBW; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.BandwidthAvailableForImmediateFlip - mode_lib->vba.cursor_bw[k] + - dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + + mode_lib->vba.qual_row_bw[k], + mode_lib->vba.PrefetchBandwidth[k]); + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + ImmediateFlipBytes[k] = 0; + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + ImmediateFlipBytes[k] = mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + + mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]; + } + } + mode_lib->vba.TotImmediateFlipBytes = 0; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.TotImmediateFlipBytes = mode_lib->vba.TotImmediateFlipBytes + + ImmediateFlipBytes[k]; + } + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + CalculateFlipSchedule(mode_lib, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.BandwidthAvailableForImmediateFlip, + mode_lib->vba.TotImmediateFlipBytes, + mode_lib->vba.SourcePixelFormat[k], + ImmediateFlipBytes[k], + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.Tno_bw[k], + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.meta_row_height[k], + mode_lib->vba.qual_row_bw[k], + &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], + &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], + &final_flip_bw[k], + &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + total_dcn_read_bw_with_flip = + total_dcn_read_bw_with_flip + mode_lib->vba.cursor_bw[k] + + dml_max(mode_lib->vba.prefetch_vm_bw[k], + dml_max(mode_lib->vba.prefetch_row_bw[k], + final_flip_bw[k] + + dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]))); + } + mode_lib->vba.ImmediateFlipSupported = true; + if (total_dcn_read_bw_with_flip > mode_lib->vba.ReturnBW) { + mode_lib->vba.ImmediateFlipSupported = false; + } + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ImmediateFlipSupportedForPipe[k] == false) { + mode_lib->vba.ImmediateFlipSupported = false; + } + } + } else { + mode_lib->vba.ImmediateFlipSupported = false; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ErrorResult[k]) { + mode_lib->vba.PrefetchModeSupported = false; + dml_print("DML: CalculatePrefetchSchedule ***failed***. Prefetch schedule violation. Results are NOT valid\n"); + } + } + + mode_lib->vba.VStartupLines = mode_lib->vba.VStartupLines + 1; + } while (!((mode_lib->vba.PrefetchModeSupported + && (!mode_lib->vba.ImmediateFlipSupport || mode_lib->vba.ImmediateFlipSupported)) + || mode_lib->vba.MaximumMaxVStartupLines < mode_lib->vba.VStartupLines)); + + //Display Pipeline Delivery Time in Prefetch + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.VRatioPrefetchY[k] <= 1) { + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] / mode_lib->vba.DPPCLK[k]; + } + if (mode_lib->vba.BytePerPixelDETC[k] == 0) { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = 0; + } else { + if (mode_lib->vba.VRatioPrefetchC[k] <= 1) { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; + } + } + } + + // Min TTUVBlank + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.PrefetchMode == 0) { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = true; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; + mode_lib->vba.MinTTUVBlank[k] = dml_max(mode_lib->vba.DRAMClockChangeWatermark, + dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark)); + } else if (mode_lib->vba.PrefetchMode == 1) { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; + mode_lib->vba.MinTTUVBlank[k] = dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark); + } else { + mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; + mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = false; + mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.UrgentWatermark; + } + if (!mode_lib->vba.DynamicMetadataEnable[k]) + mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.TCalc + mode_lib->vba.MinTTUVBlank[k]; + } + + // DCC Configuration + mode_lib->vba.ActiveDPPs = 0; + // NB P-State/DRAM Clock Change Support + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.ActiveDPPs = mode_lib->vba.ActiveDPPs + mode_lib->vba.DPPPerPlane[k]; + } + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + double EffectiveLBLatencyHidingY; + double EffectiveLBLatencyHidingC; + double DPPOutputBufferLinesY; + double DPPOutputBufferLinesC; + double DPPOPPBufferingY; + double MaxDETBufferingTimeY; + double ActiveDRAMClockChangeLatencyMarginY; + + mode_lib->vba.LBLatencyHidingSourceLinesY = + dml_min(mode_lib->vba.MaxLineBufferLines, + (unsigned int)dml_floor((double)mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / dml_max(mode_lib->vba.HRatio[k], + 1.0)), + 1)) - (mode_lib->vba.vtaps[k] - 1); + + mode_lib->vba.LBLatencyHidingSourceLinesC = + dml_min(mode_lib->vba.MaxLineBufferLines, + (unsigned int)dml_floor((double)mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / 2.0 + / dml_max(mode_lib->vba.HRatio[k] + / 2, + 1.0)), + 1)) - (mode_lib->vba.VTAPsChroma[k] - 1); + + EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY / mode_lib->vba.VRatio[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC / (mode_lib->vba.VRatio[k] / 2) + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + if (mode_lib->vba.SwathWidthY[k] > 2 * mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesY = mode_lib->vba.DPPOutputBufferPixels / mode_lib->vba.SwathWidthY[k]; + } else if (mode_lib->vba.SwathWidthY[k] > mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesY = 0.5; + } else { + DPPOutputBufferLinesY = 1; + } + + if (mode_lib->vba.SwathWidthY[k] / 2 > 2 * mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesC = mode_lib->vba.DPPOutputBufferPixels / (mode_lib->vba.SwathWidthY[k] / 2); + } else if (mode_lib->vba.SwathWidthY[k] / 2 > mode_lib->vba.DPPOutputBufferPixels) { + DPPOutputBufferLinesC = 0.5; + } else { + DPPOutputBufferLinesC = 1; + } + + DPPOPPBufferingY = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * (DPPOutputBufferLinesY + mode_lib->vba.OPPOutputBufferLines); + MaxDETBufferingTimeY = mode_lib->vba.FullDETBufferingTimeY[k] + + (mode_lib->vba.LinesInDETY[k] - mode_lib->vba.LinesInDETYRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightY[k] * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + ActiveDRAMClockChangeLatencyMarginY = DPPOPPBufferingY + EffectiveLBLatencyHidingY + + MaxDETBufferingTimeY - mode_lib->vba.DRAMClockChangeWatermark; + + if (mode_lib->vba.ActiveDPPs > 1) { + ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY + - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) * mode_lib->vba.SwathHeightY[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + } + + if (mode_lib->vba.BytePerPixelDETC[k] > 0) { + double DPPOPPBufferingC = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * (DPPOutputBufferLinesC + mode_lib->vba.OPPOutputBufferLines); + double MaxDETBufferingTimeC = + mode_lib->vba.FullDETBufferingTimeC[k] + + (mode_lib->vba.LinesInDETC[k] + - mode_lib->vba.LinesInDETCRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + double ActiveDRAMClockChangeLatencyMarginC = DPPOPPBufferingC + + EffectiveLBLatencyHidingC + MaxDETBufferingTimeC + - mode_lib->vba.DRAMClockChangeWatermark; + + if (mode_lib->vba.ActiveDPPs > 1) { + ActiveDRAMClockChangeLatencyMarginC = + ActiveDRAMClockChangeLatencyMarginC + - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) + * mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMarginY, + ActiveDRAMClockChangeLatencyMarginC); + } else { + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = + ActiveDRAMClockChangeLatencyMarginY; + } + + if (mode_lib->vba.WritebackEnable[k]) { + double WritebackDRAMClockChangeLatencyMargin; + + if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + WritebackDRAMClockChangeLatencyMargin = + (double)(mode_lib->vba.WritebackInterfaceLumaBufferSize + + mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + * 4) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } else if (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + WritebackDRAMClockChangeLatencyMargin = dml_min((double)mode_lib->vba.WritebackInterfaceLumaBufferSize * 8.0 + / 10, + 2.0 * mode_lib->vba.WritebackInterfaceChromaBufferSize * 8 / 10) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } else { + WritebackDRAMClockChangeLatencyMargin = dml_min((double)mode_lib->vba.WritebackInterfaceLumaBufferSize, + 2.0 * mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; + } + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k], + WritebackDRAMClockChangeLatencyMargin); + } + } + + mode_lib->vba.MinActiveDRAMClockChangeMargin = 999999; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] + < mode_lib->vba.MinActiveDRAMClockChangeMargin) { + mode_lib->vba.MinActiveDRAMClockChangeMargin = + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; + } + } + + mode_lib->vba.MinActiveDRAMClockChangeLatencySupported = mode_lib->vba.MinActiveDRAMClockChangeMargin + + mode_lib->vba.DRAMClockChangeLatency; + + if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vactive; + } else { + if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vblank; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (!mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k]) { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_unsupported; + } + } + } else { + mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_unsupported; + } + } + + //XFC Parameters: + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (mode_lib->vba.XFCEnabled[k] == true) { + double TWait; + + mode_lib->vba.XFCSlaveVUpdateOffset[k] = mode_lib->vba.XFCTSlvVupdateOffset; + mode_lib->vba.XFCSlaveVupdateWidth[k] = mode_lib->vba.XFCTSlvVupdateWidth; + mode_lib->vba.XFCSlaveVReadyOffset[k] = mode_lib->vba.XFCTSlvVreadyOffset; + TWait = CalculateTWait(mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = dml_floor(mode_lib->vba.XFCRemoteSurfaceFlipDelay / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCTransferDelay[k] = dml_ceil(mode_lib->vba.XFCBusTransportTime / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCPrechargeDelay[k] = dml_ceil((mode_lib->vba.XFCBusTransportTime + mode_lib->vba.TInitXFill + mode_lib->vba.TslvChk) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.InitFillLevel = mode_lib->vba.XFCXBUFLatencyTolerance * mode_lib->vba.SrcActiveDrainRate; + mode_lib->vba.FinalFillMargin = (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k] * mode_lib->vba.SrcActiveDrainRate + mode_lib->vba.XFCFillConstant; + mode_lib->vba.FinalFillLevel = mode_lib->vba.XFCRemoteSurfaceFlipDelay * mode_lib->vba.SrcActiveDrainRate + + mode_lib->vba.FinalFillMargin; + mode_lib->vba.RemainingFillLevel = dml_max(0.0, + mode_lib->vba.FinalFillLevel - mode_lib->vba.InitFillLevel); + mode_lib->vba.TFinalxFill = mode_lib->vba.RemainingFillLevel + / (mode_lib->vba.SrcActiveDrainRate * mode_lib->vba.XFCFillBWOverhead / 100); + mode_lib->vba.XFCPrefetchMargin[k] = mode_lib->vba.XFCRemoteSurfaceFlipDelay + mode_lib->vba.TFinalxFill + + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) + * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]; + } else { + mode_lib->vba.XFCSlaveVUpdateOffset[k] = 0; + mode_lib->vba.XFCSlaveVupdateWidth[k] = 0; + mode_lib->vba.XFCSlaveVReadyOffset[k] = 0; + mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = 0; + mode_lib->vba.XFCPrechargeDelay[k] = 0; + mode_lib->vba.XFCTransferDelay[k] = 0; + mode_lib->vba.XFCPrefetchMargin[k] = 0; + } + } +} + +static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) +{ + double BytePerPixDETY; + double BytePerPixDETC; + double Read256BytesBlockHeightY; + double Read256BytesBlockHeightC; + double Read256BytesBlockWidthY; + double Read256BytesBlockWidthC; + double MaximumSwathHeightY; + double MaximumSwathHeightC; + double MinimumSwathHeightY; + double MinimumSwathHeightC; + double SwathWidth; + double SwathWidthGranularityY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesY; + double RoundedUpMaxSwathSizeBytesC; + unsigned int j, k; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + bool MainPlaneDoesODMCombine = false; + + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + BytePerPixDETY = 8; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + BytePerPixDETY = 4; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + BytePerPixDETY = 2; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8) { + BytePerPixDETY = 1; + BytePerPixDETC = 0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + BytePerPixDETY = 1; + BytePerPixDETC = 2; + } else { + BytePerPixDETY = 4.0 / 3.0; + BytePerPixDETC = 8.0 / 3.0; + } + + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + Read256BytesBlockHeightY = 1; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + Read256BytesBlockHeightY = 4; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + Read256BytesBlockHeightY = 8; + } else { + Read256BytesBlockHeightY = 16; + } + Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) + / Read256BytesBlockHeightY; + Read256BytesBlockHeightC = 0; + Read256BytesBlockWidthC = 0; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + Read256BytesBlockHeightY = 1; + Read256BytesBlockHeightC = 1; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + Read256BytesBlockHeightY = 16; + Read256BytesBlockHeightC = 8; + } else { + Read256BytesBlockHeightY = 8; + Read256BytesBlockHeightC = 8; + } + Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) + / Read256BytesBlockHeightY; + Read256BytesBlockWidthC = 256 / dml_ceil(BytePerPixDETC, 2) + / Read256BytesBlockHeightC; + } + + if (mode_lib->vba.SourceScan[k] == dm_horz) { + MaximumSwathHeightY = Read256BytesBlockHeightY; + MaximumSwathHeightC = Read256BytesBlockHeightC; + } else { + MaximumSwathHeightY = Read256BytesBlockWidthY; + MaximumSwathHeightC = Read256BytesBlockWidthC; + } + + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + && (mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s_x) + && mode_lib->vba.SourceScan[k] == dm_horz)) { + MinimumSwathHeightY = MaximumSwathHeightY; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8 && mode_lib->vba.SourceScan[k] != dm_horz) { + MinimumSwathHeightY = MaximumSwathHeightY; + } else { + MinimumSwathHeightY = MaximumSwathHeightY / 2.0; + } + MinimumSwathHeightC = MaximumSwathHeightC; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + MinimumSwathHeightY = MaximumSwathHeightY; + MinimumSwathHeightC = MaximumSwathHeightC; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 && mode_lib->vba.SourceScan[k] == dm_horz) { + MinimumSwathHeightY = MaximumSwathHeightY / 2.0; + MinimumSwathHeightC = MaximumSwathHeightC; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 && mode_lib->vba.SourceScan[k] == dm_horz) { + MinimumSwathHeightC = MaximumSwathHeightC / 2.0; + MinimumSwathHeightY = MaximumSwathHeightY; + } else { + MinimumSwathHeightY = MaximumSwathHeightY; + MinimumSwathHeightC = MaximumSwathHeightC; + } + } + + if (mode_lib->vba.SourceScan[k] == dm_horz) { + SwathWidth = mode_lib->vba.ViewportWidth[k]; + } else { + SwathWidth = mode_lib->vba.ViewportHeight[k]; + } + + if (mode_lib->vba.ODMCombineEnabled[k] == true) { + MainPlaneDoesODMCombine = true; + } + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + if (mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.ODMCombineEnabled[j] == true) { + MainPlaneDoesODMCombine = true; + } + } + + if (MainPlaneDoesODMCombine == true) { + SwathWidth = dml_min(SwathWidth, mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]); + } else { + SwathWidth = SwathWidth / mode_lib->vba.DPPPerPlane[k]; + } + + SwathWidthGranularityY = 256 / dml_ceil(BytePerPixDETY, 1) / MaximumSwathHeightY; + RoundedUpMaxSwathSizeBytesY = (dml_ceil((double)(SwathWidth - 1), + SwathWidthGranularityY) + SwathWidthGranularityY) * BytePerPixDETY + * MaximumSwathHeightY; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + RoundedUpMaxSwathSizeBytesY = dml_ceil(RoundedUpMaxSwathSizeBytesY, 256) + + 256; + } + if (MaximumSwathHeightC > 0) { + SwathWidthGranularityC = 256.0 / dml_ceil(BytePerPixDETC, 2) + / MaximumSwathHeightC; + RoundedUpMaxSwathSizeBytesC = (dml_ceil((double)(SwathWidth / 2.0 - 1), + SwathWidthGranularityC) + SwathWidthGranularityC) + * BytePerPixDETC * MaximumSwathHeightC; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + RoundedUpMaxSwathSizeBytesC = dml_ceil(RoundedUpMaxSwathSizeBytesC, + 256) + 256; + } + } else + RoundedUpMaxSwathSizeBytesC = 0.0; + + if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC + <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY; + mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC; + } else { + mode_lib->vba.SwathHeightY[k] = MinimumSwathHeightY; + mode_lib->vba.SwathHeightC[k] = MinimumSwathHeightC; + } + + if (mode_lib->vba.SwathHeightC[k] == 0) { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024; + mode_lib->vba.DETBufferSizeC[k] = 0; + } else if (mode_lib->vba.SwathHeightY[k] <= mode_lib->vba.SwathHeightC[k]) { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2; + } else { + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 * 2 / 3; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 3; + } + } +} + +bool Calculate256BBlockSizes(enum source_format_class SourcePixelFormat, + enum dm_swizzle_mode SurfaceTiling, + unsigned int BytePerPixelY, + unsigned int BytePerPixelC, + unsigned int *BlockHeight256BytesY, + unsigned int *BlockHeight256BytesC, + unsigned int *BlockWidth256BytesY, + unsigned int *BlockWidth256BytesC) +{ + if ((SourcePixelFormat == dm_444_64 || SourcePixelFormat == dm_444_32 + || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16 + || SourcePixelFormat == dm_444_8)) { + if (SurfaceTiling == dm_sw_linear) { + *BlockHeight256BytesY = 1; + } else if (SourcePixelFormat == dm_444_64) { + *BlockHeight256BytesY = 4; + } else if (SourcePixelFormat == dm_444_8) { + *BlockHeight256BytesY = 16; + } else { + *BlockHeight256BytesY = 8; + } + *BlockWidth256BytesY = 256 / BytePerPixelY / *BlockHeight256BytesY; + *BlockHeight256BytesC = 0; + *BlockWidth256BytesC = 0; + } else { + if (SurfaceTiling == dm_sw_linear) { + *BlockHeight256BytesY = 1; + *BlockHeight256BytesC = 1; + } else if (SourcePixelFormat == dm_420_8) { + *BlockHeight256BytesY = 16; + *BlockHeight256BytesC = 8; + } else { + *BlockHeight256BytesY = 8; + *BlockHeight256BytesC = 8; + } + *BlockWidth256BytesY = 256 / BytePerPixelY / *BlockHeight256BytesY; + *BlockWidth256BytesC = 256 / BytePerPixelC / *BlockHeight256BytesC; + } + return true; +} + +static double CalculateTWait(unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime) +{ + if (PrefetchMode == 0) { + return dml_max(DRAMClockChangeLatency + UrgentLatency, + dml_max(SREnterPlusExitTime, UrgentLatency)); + } else if (PrefetchMode == 1) { + return dml_max(SREnterPlusExitTime, UrgentLatency); + } else { + return UrgentLatency; + } +} + +static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk) +{ + double TSlvSetup, AvgfillRate, result; + + *SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime; + TSlvSetup = XFCTSlvVupdateOffset + XFCTSlvVupdateWidth + XFCTSlvVreadyOffset; + *TInitXFill = XFCXBUFLatencyTolerance / (1 + XFCFillBWOverhead / 100); + AvgfillRate = *SrcActiveDrainRate * (1 + XFCFillBWOverhead / 100); + *TslvChk = XFCSlvChunkSize / AvgfillRate; + dml_print("DML::CalculateRemoteSurfaceFlipDelay: SrcActiveDrainRate: %f\n", + *SrcActiveDrainRate); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TSlvSetup: %f\n", TSlvSetup); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TInitXFill: %f\n", *TInitXFill); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: AvgfillRate: %f\n", AvgfillRate); + dml_print("DML::CalculateRemoteSurfaceFlipDelay: TslvChk: %f\n", *TslvChk); + result = 2 * XFCBusTransportTime + TSlvSetup + TCalc + TWait + *TslvChk + *TInitXFill; // TODO: This doesn't seem to match programming guide + dml_print("DML::CalculateRemoteSurfaceFlipDelay: RemoteSurfaceFlipDelay: %f\n", result); + return result; +} + +static double CalculateWriteBackDISPCLK(enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth) +{ + double CalculateWriteBackDISPCLK = 1.01 * PixelClock + * dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, + dml_max( + (WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) + * dml_ceil(WritebackDestinationWidth / 4.0, 1) + + dml_ceil(WritebackDestinationWidth / 4.0, 1)) / (double)HTotal + + dml_ceil(1.0 / WritebackVRatio, 1) * (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4.0) + / (double)HTotal, + dml_ceil(1.0 / WritebackVRatio, 1) * WritebackDestinationWidth / (double)HTotal)); + if (WritebackPixelFormat != dm_444_32) { + CalculateWriteBackDISPCLK = dml_max( + CalculateWriteBackDISPCLK, + 1.01 * PixelClock + * dml_max( + dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio), + dml_max( + (WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) + * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1) + + dml_ceil(WritebackDestinationWidth / 2.0 / WritebackChromaLineBufferWidth, 1)) + / HTotal + + dml_ceil(1 / (2 * WritebackVRatio), 1) + * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4) / HTotal, + dml_ceil(1.0 / (2 * WritebackVRatio), 1) * WritebackDestinationWidth / 2.0 + / HTotal))); + } + return CalculateWriteBackDISPCLK; +} + +static double CalculateWriteBackDelay( +enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth) +{ + double CalculateWriteBackDelay = dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, + WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) + * dml_ceil(WritebackDestinationWidth / 4.0, 1) + + dml_ceil(1.0 / WritebackVRatio, 1) * (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4)); + + if (WritebackPixelFormat != dm_444_32) { + CalculateWriteBackDelay = dml_max( + CalculateWriteBackDelay, + dml_max( + dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio), + WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) + * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1) + + dml_ceil(1 / (2 * WritebackVRatio), 1) + * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4))); + } + return CalculateWriteBackDelay; +} + +static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw) +{ + if (DCCEnable != true) { + *meta_row_bw = 0; + } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime) + + VRatio / 2 * MetaRowByteChroma + / (meta_row_height_chroma * LineTime); + } else { + *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime); + } + + if (VirtualMemoryEnable != true) { + *dpte_row_bw = 0; + } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime) + + VRatio / 2 * PixelPTEBytesPerRowChroma + / (dpte_row_height_chroma * LineTime); + } else { + *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime); + } + + if ((SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10)) { + *qual_row_bw = *meta_row_bw + *dpte_row_bw; + } else { + *qual_row_bw = 0; + } +} + +static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe) +{ + double min_row_time = 0.0; + + if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { + *DestinationLinesToRequestVMInImmediateFlip = 0.0; + *DestinationLinesToRequestRowInImmediateFlip = 0.0; + *final_flip_bw = qual_row_bw; + *ImmediateFlipSupportedForPipe = true; + } else { + double TimeForFetchingMetaPTEImmediateFlip; + double TimeForFetchingRowInVBlankImmediateFlip; + + if (VirtualMemoryEnable == true) { + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip * ImmediateFlipBytes + / TotImmediateFlipBytes; + TimeForFetchingMetaPTEImmediateFlip = + dml_max(Tno_bw + + PDEAndMetaPTEBytesFrame + / mode_lib->vba.ImmediateFlipBW, + dml_max(UrgentExtraLatency + + UrgentLatency + * (MaxPageTableLevels + - 1), + LineTime / 4.0)); + } else { + TimeForFetchingMetaPTEImmediateFlip = 0; + } + + *DestinationLinesToRequestVMInImmediateFlip = dml_floor(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime + 0.125), + 1) / 4.0; + + if ((VirtualMemoryEnable == true || DCCEnable == true)) { + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip * ImmediateFlipBytes + / TotImmediateFlipBytes; + TimeForFetchingRowInVBlankImmediateFlip = dml_max((MetaRowByte + PixelPTEBytesPerRow) / mode_lib->vba.ImmediateFlipBW, + dml_max(UrgentLatency, LineTime / 4.0)); + } else { + TimeForFetchingRowInVBlankImmediateFlip = 0; + } + + *DestinationLinesToRequestRowInImmediateFlip = dml_floor(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime + 0.125), + 1) / 4.0; + + if (VirtualMemoryEnable == true) { + *final_flip_bw = + dml_max(PDEAndMetaPTEBytesFrame + / (*DestinationLinesToRequestVMInImmediateFlip + * LineTime), + (MetaRowByte + PixelPTEBytesPerRow) + / (TimeForFetchingRowInVBlankImmediateFlip + * LineTime)); + } else if (MetaRowByte + PixelPTEBytesPerRow > 0) { + *final_flip_bw = (MetaRowByte + PixelPTEBytesPerRow) + / (TimeForFetchingRowInVBlankImmediateFlip * LineTime); + } else { + *final_flip_bw = 0; + } + + if (VirtualMemoryEnable && !DCCEnable) + min_row_time = dpte_row_height * LineTime / VRatio; + else if (!VirtualMemoryEnable && DCCEnable) + min_row_time = meta_row_height * LineTime / VRatio; + else + min_row_time = dml_min(dpte_row_height, meta_row_height) * LineTime + / VRatio; + + if (*DestinationLinesToRequestVMInImmediateFlip >= 8 + || *DestinationLinesToRequestRowInImmediateFlip >= 16 + || TimeForFetchingMetaPTEImmediateFlip + + 2 * TimeForFetchingRowInVBlankImmediateFlip > min_row_time) + *ImmediateFlipSupportedForPipe = false; + else + *ImmediateFlipSupportedForPipe = true; + } +} + +static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib) +{ + unsigned int k; + + //Progressive To dml_ml->vba.Interlace Unit Effect + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + mode_lib->vba.PixelClockBackEnd[k] = mode_lib->vba.PixelClock[k]; + if (mode_lib->vba.Interlace[k] == 1 && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) { + mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClock[k]; + } + } +} + +static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp) +{ + switch (ebpp) { + case dm_cur_2bit: + return 2; + case dm_cur_32bit: + return 32; + case dm_cur_64bit: + return 64; + default: + return 0; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h new file mode 100644 index 000000000000..a24fe9a0383d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -0,0 +1,410 @@ +/* + * display_mode_vba.h + * + * Created on: Aug 18, 2017 + * Author: dlaktyus + */ + +#ifndef __DML2_DISPLAY_MODE_VBA_H__ +#define __DML2_DISPLAY_MODE_VBA_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +void set_prefetch_mode(struct display_mode_lib *mode_lib, + bool cstate_en, + bool pstate_en, + bool ignore_viewport_pos, + bool immediate_flip_support); + +#define dml_get_attr_decl(attr) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) + +dml_get_attr_decl(clk_dcf_deepsleep); +dml_get_attr_decl(wm_urgent); +dml_get_attr_decl(wm_memory_trip); +dml_get_attr_decl(wm_writeback_urgent); +dml_get_attr_decl(wm_stutter_exit); +dml_get_attr_decl(wm_stutter_enter_exit); +dml_get_attr_decl(wm_dram_clock_change); +dml_get_attr_decl(wm_writeback_dram_clock_change); +dml_get_attr_decl(wm_xfc_underflow); +dml_get_attr_decl(stutter_efficiency_no_vblank); +dml_get_attr_decl(stutter_efficiency); +dml_get_attr_decl(urgent_latency); +dml_get_attr_decl(urgent_extra_latency); +dml_get_attr_decl(nonurgent_latency); +dml_get_attr_decl(dram_clock_change_latency); +dml_get_attr_decl(dispclk_calculated); +dml_get_attr_decl(total_data_read_bw); +dml_get_attr_decl(return_bw); +dml_get_attr_decl(tcalc); + +#define dml_get_pipe_attr_decl(attr) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes, unsigned int which_pipe) + +dml_get_pipe_attr_decl(dsc_delay); +dml_get_pipe_attr_decl(dppclk_calculated); +dml_get_pipe_attr_decl(dscclk_calculated); +dml_get_pipe_attr_decl(min_ttu_vblank); +dml_get_pipe_attr_decl(vratio_prefetch_l); +dml_get_pipe_attr_decl(vratio_prefetch_c); +dml_get_pipe_attr_decl(dst_x_after_scaler); +dml_get_pipe_attr_decl(dst_y_after_scaler); +dml_get_pipe_attr_decl(dst_y_per_vm_vblank); +dml_get_pipe_attr_decl(dst_y_per_row_vblank); +dml_get_pipe_attr_decl(dst_y_prefetch); +dml_get_pipe_attr_decl(dst_y_per_vm_flip); +dml_get_pipe_attr_decl(dst_y_per_row_flip); +dml_get_pipe_attr_decl(xfc_transfer_delay); +dml_get_pipe_attr_decl(xfc_precharge_delay); +dml_get_pipe_attr_decl(xfc_remote_surface_flip_latency); +dml_get_pipe_attr_decl(xfc_prefetch_margin); + +unsigned int get_vstartup_calculated( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes, + unsigned int which_pipe); + +double get_total_immediate_flip_bytes( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double get_total_immediate_flip_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double get_total_prefetch_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); + +bool Calculate256BBlockSizes( + enum source_format_class SourcePixelFormat, + enum dm_swizzle_mode SurfaceTiling, + unsigned int BytePerPixelY, + unsigned int BytePerPixelC, + unsigned int *BlockHeight256BytesY, + unsigned int *BlockHeight256BytesC, + unsigned int *BlockWidth256BytesY, + unsigned int *BlockWidth256BytesC); + + +struct vba_vars_st { + ip_params_st ip; + soc_bounding_box_st soc; + mode_evaluation_st me; + + unsigned int MaximumMaxVStartupLines; + double cursor_bw[DC__NUM_PIPES__MAX]; + double meta_row_bw[DC__NUM_PIPES__MAX]; + double dpte_row_bw[DC__NUM_PIPES__MAX]; + double qual_row_bw[DC__NUM_PIPES__MAX]; + double WritebackDISPCLK; + double PSCL_THROUGHPUT_LUMA[DC__NUM_PIPES__MAX]; + double PSCL_THROUGHPUT_CHROMA[DC__NUM_PIPES__MAX]; + double DPPCLKUsingSingleDPPLuma; + double DPPCLKUsingSingleDPPChroma; + double DPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; + double DISPCLKWithRamping; + double DISPCLKWithoutRamping; + double GlobalDPPCLK; + double MaxDispclk; + double DISPCLKWithRampingRoundedToDFSGranularity; + double DISPCLKWithoutRampingRoundedToDFSGranularity; + double MaxDispclkRoundedToDFSGranularity; + bool DCCEnabledAnyPlane; + double ReturnBandwidthToDCN; + unsigned int SwathWidthY[DC__NUM_PIPES__MAX]; + unsigned int SwathWidthSingleDPPY[DC__NUM_PIPES__MAX]; + double BytePerPixelDETY[DC__NUM_PIPES__MAX]; + double BytePerPixelDETC[DC__NUM_PIPES__MAX]; + double ReadBandwidthPlaneLuma[DC__NUM_PIPES__MAX]; + double ReadBandwidthPlaneChroma[DC__NUM_PIPES__MAX]; + unsigned int TotalActiveDPP; + unsigned int TotalDCCActiveDPP; + double UrgentRoundTripAndOutOfOrderLatency; + double DisplayPipeLineDeliveryTimeLuma[DC__NUM_PIPES__MAX]; // WM + double DisplayPipeLineDeliveryTimeChroma[DC__NUM_PIPES__MAX]; // WM + double LinesInDETY[DC__NUM_PIPES__MAX]; // WM + double LinesInDETC[DC__NUM_PIPES__MAX]; // WM + unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_PIPES__MAX]; // WM + unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_PIPES__MAX]; // WM + double FullDETBufferingTimeY[DC__NUM_PIPES__MAX]; // WM + double FullDETBufferingTimeC[DC__NUM_PIPES__MAX]; // WM + double MinFullDETBufferingTime; + double FrameTimeForMinFullDETBufferingTime; + double AverageReadBandwidthGBytePerSecond; + double PartOfBurstThatFitsInROB; + double StutterBurstTime; + //unsigned int NextPrefetchMode; + double VBlankTime; + double SmallestVBlank; + double DCFCLKDeepSleepPerPlane; + double EffectiveDETPlusLBLinesLuma; + double EffectiveDETPlusLBLinesChroma; + double UrgentLatencySupportUsLuma; + double UrgentLatencySupportUsChroma; + double UrgentLatencySupportUs[DC__NUM_PIPES__MAX]; + unsigned int DSCFormatFactor; + unsigned int BlockHeight256BytesY[DC__NUM_PIPES__MAX]; + unsigned int BlockHeight256BytesC[DC__NUM_PIPES__MAX]; + unsigned int BlockWidth256BytesY[DC__NUM_PIPES__MAX]; + unsigned int BlockWidth256BytesC[DC__NUM_PIPES__MAX]; + double VInitPreFillY[DC__NUM_PIPES__MAX]; + double VInitPreFillC[DC__NUM_PIPES__MAX]; + unsigned int MaxNumSwathY[DC__NUM_PIPES__MAX]; + unsigned int MaxNumSwathC[DC__NUM_PIPES__MAX]; + double PrefetchSourceLinesY[DC__NUM_PIPES__MAX]; + double PrefetchSourceLinesC[DC__NUM_PIPES__MAX]; + double PixelPTEBytesPerRow[DC__NUM_PIPES__MAX]; + double MetaRowByte[DC__NUM_PIPES__MAX]; + bool PTEBufferSizeNotExceeded; // not used + unsigned int dpte_row_height[DC__NUM_PIPES__MAX]; + unsigned int dpte_row_height_chroma[DC__NUM_PIPES__MAX]; + unsigned int meta_row_height[DC__NUM_PIPES__MAX]; + unsigned int meta_row_height_chroma[DC__NUM_PIPES__MAX]; + + unsigned int MacroTileWidthY; + unsigned int MacroTileWidthC; + unsigned int MaxVStartupLines[DC__NUM_PIPES__MAX]; + double WritebackDelay[DC__NUM_PIPES__MAX]; + bool PrefetchModeSupported; + bool AllowDRAMClockChangeDuringVBlank[DC__NUM_PIPES__MAX]; + bool AllowDRAMSelfRefreshDuringVBlank[DC__NUM_PIPES__MAX]; + double RequiredPrefetchPixDataBW[DC__NUM_PIPES__MAX]; + double XFCRemoteSurfaceFlipDelay; + double TInitXFill; + double TslvChk; + double SrcActiveDrainRate; + double Tno_bw[DC__NUM_PIPES__MAX]; + bool ImmediateFlipSupported; + + double prefetch_vm_bw[DC__NUM_PIPES__MAX]; + double prefetch_row_bw[DC__NUM_PIPES__MAX]; + bool ImmediateFlipSupportedForPipe[DC__NUM_PIPES__MAX]; + unsigned int VStartupLines; + double DisplayPipeLineDeliveryTimeLumaPrefetch[DC__NUM_PIPES__MAX]; + double DisplayPipeLineDeliveryTimeChromaPrefetch[DC__NUM_PIPES__MAX]; + unsigned int ActiveDPPs; + unsigned int LBLatencyHidingSourceLinesY; + unsigned int LBLatencyHidingSourceLinesC; + double ActiveDRAMClockChangeLatencyMargin[DC__NUM_PIPES__MAX]; + double MinActiveDRAMClockChangeMargin; + double XFCSlaveVUpdateOffset[DC__NUM_PIPES__MAX]; + double XFCSlaveVupdateWidth[DC__NUM_PIPES__MAX]; + double XFCSlaveVReadyOffset[DC__NUM_PIPES__MAX]; + double InitFillLevel; + double FinalFillMargin; + double FinalFillLevel; + double RemainingFillLevel; + double TFinalxFill; + + + // + // SOC Bounding Box Parameters + // + double SRExitTime; + double SREnterPlusExitTime; + double UrgentLatency; + double WritebackLatency; + double PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency; + double NumberOfChannels; + double DRAMChannelWidth; + double FabricDatapathToDCNDataReturn; + double ReturnBusWidth; + double Downspreading; + double DISPCLKDPPCLKDSCCLKDownSpreading; + double DISPCLKDPPCLKVCOSpeed; + double RoundTripPingLatencyCycles; + double UrgentOutOfOrderReturnPerChannel; + unsigned int VMMPageSize; + double DRAMClockChangeLatency; + double XFCBusTransportTime; + double XFCXBUFLatencyTolerance; + + // + // IP Parameters + // + unsigned int ROBBufferSizeInKByte; + double DETBufferSizeInKByte; + unsigned int DPPOutputBufferPixels; + unsigned int OPPOutputBufferLines; + unsigned int PixelChunkSizeInKByte; + double ReturnBW; + bool VirtualMemoryEnable; + unsigned int MaxPageTableLevels; + unsigned int OverridePageTableLevels; + unsigned int PTEChunkSize; + unsigned int MetaChunkSize; + unsigned int WritebackChunkSize; + bool ODMCapability; + unsigned int NumberOfDSC; + unsigned int LineBufferSize; + unsigned int MaxLineBufferLines; + unsigned int WritebackInterfaceLumaBufferSize; + unsigned int WritebackInterfaceChromaBufferSize; + unsigned int WritebackChromaLineBufferWidth; + double MaxDCHUBToPSCLThroughput; + double MaxPSCLToLBThroughput; + unsigned int PTEBufferSizeInRequests; + double DISPCLKRampingMargin; + unsigned int MaxInterDCNTileRepeaters; + bool XFCSupported; + double XFCSlvChunkSize; + double XFCFillBWOverhead; + double XFCFillConstant; + double XFCTSlvVupdateOffset; + double XFCTSlvVupdateWidth; + double XFCTSlvVreadyOffset; + double DPPCLKDelaySubtotal; + double DPPCLKDelaySCL; + double DPPCLKDelaySCLLBOnly; + double DPPCLKDelayCNVCFormater; + double DPPCLKDelayCNVCCursor; + double DISPCLKDelaySubtotal; + bool ProgressiveToInterlaceUnitInOPP; + unsigned int PDEProcessingBufIn64KBReqs; + + // Pipe/Plane Parameters + int VoltageLevel; + double FabricAndDRAMBandwidth; + double FabricClock; + double DRAMSpeed; + double DISPCLK; + double SOCCLK; + double DCFCLK; + + unsigned int NumberOfActivePlanes; + unsigned int ViewportWidth[DC__NUM_DPP]; + unsigned int ViewportHeight[DC__NUM_DPP]; + unsigned int ViewportYStartY[DC__NUM_DPP]; + unsigned int ViewportYStartC[DC__NUM_DPP]; + unsigned int PitchY[DC__NUM_DPP]; + unsigned int PitchC[DC__NUM_DPP]; + double HRatio[DC__NUM_DPP]; + double VRatio[DC__NUM_DPP]; + unsigned int htaps[DC__NUM_DPP]; + unsigned int vtaps[DC__NUM_DPP]; + unsigned int HTAPsChroma[DC__NUM_DPP]; + unsigned int VTAPsChroma[DC__NUM_DPP]; + unsigned int HTotal[DC__NUM_DPP]; + unsigned int VTotal[DC__NUM_DPP]; + unsigned int DPPPerPlane[DC__NUM_DPP]; + double PixelClock[DC__NUM_DPP]; + double PixelClockBackEnd[DC__NUM_DPP]; + double DPPCLK[DC__NUM_DPP]; + bool DCCEnable[DC__NUM_DPP]; + unsigned int DCCMetaPitchY[DC__NUM_DPP]; + enum scan_direction_class SourceScan[DC__NUM_DPP]; + enum source_format_class SourcePixelFormat[DC__NUM_DPP]; + bool WritebackEnable[DC__NUM_DPP]; + double WritebackDestinationWidth[DC__NUM_DPP]; + double WritebackDestinationHeight[DC__NUM_DPP]; + double WritebackSourceHeight[DC__NUM_DPP]; + enum source_format_class WritebackPixelFormat[DC__NUM_DPP]; + unsigned int WritebackLumaHTaps[DC__NUM_DPP]; + unsigned int WritebackLumaVTaps[DC__NUM_DPP]; + unsigned int WritebackChromaHTaps[DC__NUM_DPP]; + unsigned int WritebackChromaVTaps[DC__NUM_DPP]; + double WritebackHRatio[DC__NUM_DPP]; + double WritebackVRatio[DC__NUM_DPP]; + unsigned int HActive[DC__NUM_DPP]; + unsigned int VActive[DC__NUM_DPP]; + bool Interlace[DC__NUM_DPP]; + enum dm_swizzle_mode SurfaceTiling[DC__NUM_DPP]; + unsigned int ScalerRecoutWidth[DC__NUM_DPP]; + bool DynamicMetadataEnable[DC__NUM_DPP]; + unsigned int DynamicMetadataLinesBeforeActiveRequired[DC__NUM_DPP]; + unsigned int DynamicMetadataTransmittedBytes[DC__NUM_DPP]; + double DCCRate[DC__NUM_DPP]; + bool ODMCombineEnabled[DC__NUM_DPP]; + double OutputBpp[DC__NUM_DPP]; + unsigned int NumberOfDSCSlices[DC__NUM_DPP]; + bool DSCEnabled[DC__NUM_DPP]; + unsigned int DSCDelay[DC__NUM_DPP]; + unsigned int DSCInputBitPerComponent[DC__NUM_DPP]; + enum output_format_class OutputFormat[DC__NUM_DPP]; + enum output_encoder_class Output[DC__NUM_DPP]; + unsigned int BlendingAndTiming[DC__NUM_DPP]; + bool SynchronizedVBlank; + unsigned int NumberOfCursors[DC__NUM_DPP]; + unsigned int CursorWidth[DC__NUM_DPP][DC__NUM_CURSOR]; + unsigned int CursorBPP[DC__NUM_DPP][DC__NUM_CURSOR]; + bool XFCEnabled[DC__NUM_DPP]; + bool ScalerEnabled[DC__NUM_DPP]; + + // Intermediates/Informational + bool ImmediateFlipSupport; + unsigned int SwathHeightY[DC__NUM_DPP]; + unsigned int SwathHeightC[DC__NUM_DPP]; + unsigned int DETBufferSizeY[DC__NUM_DPP]; + unsigned int DETBufferSizeC[DC__NUM_DPP]; + unsigned int LBBitPerPixel[DC__NUM_DPP]; + double LastPixelOfLineExtraWatermark; + double TotalDataReadBandwidth; + unsigned int TotalActiveWriteback; + unsigned int EffectiveLBLatencyHidingSourceLinesLuma; + unsigned int EffectiveLBLatencyHidingSourceLinesChroma; + double BandwidthAvailableForImmediateFlip; + unsigned int PrefetchMode; + bool IgnoreViewportPositioning; + double PrefetchBandwidth[DC__NUM_DPP]; + bool ErrorResult[DC__NUM_DPP]; + double PDEAndMetaPTEBytesFrame[DC__NUM_DPP]; + + // + // Calculated dml_ml->vba.Outputs + // + double DCFClkDeepSleep; + double UrgentWatermark; + double UrgentExtraLatency; + double MemoryTripWatermark; + double WritebackUrgentWatermark; + double StutterExitWatermark; + double StutterEnterPlusExitWatermark; + double DRAMClockChangeWatermark; + double WritebackDRAMClockChangeWatermark; + double StutterEfficiency; + double StutterEfficiencyNotIncludingVBlank; + double MinUrgentLatencySupportUs; + double NonUrgentLatencyTolerance; + double MinActiveDRAMClockChangeLatencySupported; + enum clock_change_support DRAMClockChangeSupport; + + // These are the clocks calcuated by the library but they are not actually + // used explicitly. They are fetched by tests and then possibly used. The + // ultimate values to use are the ones specified by the parameters to DML + double DISPCLK_calculated; + double DSCCLK_calculated[DC__NUM_DPP]; + double DPPCLK_calculated[DC__NUM_DPP]; + + unsigned int VStartup[DC__NUM_DPP]; + unsigned int VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; + + double ImmediateFlipBW; + unsigned int TotImmediateFlipBytes; + double TCalc; + double MinTTUVBlank[DC__NUM_DPP]; + double VRatioPrefetchY[DC__NUM_DPP]; + double VRatioPrefetchC[DC__NUM_DPP]; + double DSTXAfterScaler[DC__NUM_DPP]; + double DSTYAfterScaler[DC__NUM_DPP]; + + double DestinationLinesToRequestVMInVBlank[DC__NUM_DPP]; + double DestinationLinesToRequestRowInVBlank[DC__NUM_DPP]; + double DestinationLinesForPrefetch[DC__NUM_DPP]; + double DestinationLinesToRequestRowInImmediateFlip[DC__NUM_DPP]; + double DestinationLinesToRequestVMInImmediateFlip[DC__NUM_DPP]; + + double XFCTransferDelay[DC__NUM_DPP]; + double XFCPrechargeDelay[DC__NUM_DPP]; + double XFCRemoteSurfaceFlipLatency[DC__NUM_DPP]; + double XFCPrefetchMargin[DC__NUM_DPP]; + + display_e2e_pipe_params_st cache_pipes[DC__NUM_DPP]; + unsigned int cache_num_pipes; + unsigned int pipe_plane[DC__NUM_PIPES__MAX]; +}; + +#endif /* _DML2_DISPLAY_MODE_VBA_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c index 2e4dc57cafa0..30c379d95156 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c @@ -27,340 +27,79 @@ #include "display_mode_lib.h" #include "soc_bounding_box.h" -static enum voltage_state power_state( +display_pipe_clock_st dml_clks_get_pipe_clocks( struct display_mode_lib *mode_lib, - double dispclk, - double dppclk) -{ - enum voltage_state state1; - enum voltage_state state2; - - if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) - state1 = dm_vmin; - else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) - state1 = dm_vnom; - else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) - state1 = dm_vmax; - else - state1 = dm_vmax_exceeded; - - if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) - state2 = dm_vmin; - else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) - state2 = dm_vnom; - else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) - state2 = dm_vmax; - else - state2 = dm_vmax_exceeded; - - if (state1 > state2) - return state1; - else - return state2; -} - -static unsigned int dpp_in_grp( - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - unsigned int hsplit_grp) -{ - unsigned int num_dpp = 0; - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - if (e2e[i].pipe.src.is_hsplit) { - if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { - num_dpp++; - } - } - } - - if (0 == num_dpp) - num_dpp = 1; - - return num_dpp; -} - -static void calculate_pipe_clk_requirement( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp, - double *dppclk, - double *dispclk, - bool *dppdiv) -{ - double pscl_throughput = 0.0; - double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; - double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; - double max_htaps = e2e->pipe.scale_taps.htaps; - double max_vtaps = e2e->pipe.scale_taps.vtaps; - double dpp_clock_divider = (double) num_dpp_in_grp; - double dispclk_dppclk_ratio; - double dispclk_ramp_margin_percent; - - if (max_hratio > 1.0) { - double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) - / dml_ceil(max_htaps / 6.0); - pscl_throughput = dml_min( - pscl_to_lb, - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); - } else { - pscl_throughput = dml_min( - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); - } - - DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); - DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); - *dppclk = dml_max( - max_vtaps / 6.0 * dml_min(1.0, max_hratio), - max_hratio * max_vratio / pscl_throughput); - DTRACE("pixel rate multiplier: %f", *dppclk); - *dppclk = dml_max(*dppclk, 1.0); - DTRACE("pixel rate multiplier clamped: %f", *dppclk); - *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; - - *dppclk = *dppclk / dpp_clock_divider; - DTRACE("dppclk after split: %f", *dppclk); - - if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { - dispclk_dppclk_ratio = 2.0; - *dppdiv = true; - } else { - dispclk_dppclk_ratio = 1.0; - *dppdiv = false; - } - - dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; - - /* Comment this out because of Gabes possible bug in spreadsheet, - * just to make other cases evident during debug - * - *if(e2e->clks_cfg.voltage == dm_vmax) - * dispclk_ramp_margin_percent = 0.0; - */ - - /* account for ramping margin and downspread */ - *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) - * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) - * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); - - return; -} - -bool dml_clks_pipe_clock_requirement_fit_power_constraint( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp) -{ - double dppclk = 0; - double dispclk = 0; - bool dppdiv = 0; - - calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); - - if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { - return false; - } - - return true; -} - -static void get_plane_clks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - double *dppclks, - double *dispclks, - bool *dppdiv) -{ - /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated - * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to - * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently - * and we would expect the same result on any split pipes, which would be handled - */ - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - double num_dpp_in_grp; - double dispclk_ramp_margin_percent; - double dispclk_margined; - - if (e2e[i].pipe.src.is_hsplit) - num_dpp_in_grp = (double) dpp_in_grp( - e2e, - num_pipes, - e2e[i].pipe.src.hsplit_grp); - else - num_dpp_in_grp = 1; - - calculate_pipe_clk_requirement( - mode_lib, - &e2e[i], - num_dpp_in_grp, - &dppclks[i], - &dispclks[i], - &dppdiv[i]); - - dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; - - dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz - * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) - * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); - - DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); - - if (power_state(mode_lib, dispclks[i], dppclks[i]) - > power_state(mode_lib, dispclk_margined, dispclk_margined) - && dispclk_margined > dppclks[i]) { - if (power_state(mode_lib, dispclks[i], dppclks[i]) - > e2e[0].clks_cfg.voltage) { - dispclks[i] = dispclk_margined; - dppclks[i] = dispclk_margined; - dppdiv[i] = false; - } - } - - DTRACE("p%d: dispclk: %f", i, dispclks[i]); - } -} - -static void get_dcfclk( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - double *dcfclk_mhz) -{ - double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; - double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; - double swath_width_y[DC__NUM_PIPES__MAX]; - unsigned int i; - double total_read_bandwidth_gbps = 0.0; - - for (i = 0; i < num_pipes; i++) { - if (e2e[i].pipe.src.source_scan == dm_horz) { - swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; - } else { - swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; - } - - switch (e2e[i].pipe.src.source_format) { - case dm_444_64: - bytes_per_pixel_det_y[i] = 8.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_444_32: - bytes_per_pixel_det_y[i] = 4.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_444_16: - bytes_per_pixel_det_y[i] = 2.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_422_8: - bytes_per_pixel_det_y[i] = 2.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_422_10: - bytes_per_pixel_det_y[i] = 4.0; - bytes_per_pixel_det_c[i] = 0.0; - break; - case dm_420_8: - bytes_per_pixel_det_y[i] = 1.0; - bytes_per_pixel_det_c[i] = 2.0; - break; - case dm_420_10: - bytes_per_pixel_det_y[i] = 4.0 / 3.0; - bytes_per_pixel_det_c[i] = 8.0 / 3.0; - break; - default: - BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ - } - } - - for (i = 0; i < num_pipes; i++) { - double read_bandwidth_plane_mbps = 0.0; - read_bandwidth_plane_mbps = (double) swath_width_y[i] - * ((double) bytes_per_pixel_det_y[i] - + (double) bytes_per_pixel_det_c[i] / 2.0) - / ((double) e2e[i].pipe.dest.htotal - / (double) e2e[i].pipe.dest.pixel_rate_mhz) - * e2e[i].pipe.scale_ratio_depth.vscl_ratio; - - if (e2e[i].pipe.src.dcc) { - read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); - } - - if (e2e[i].pipe.src.vm) { - read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); - } - - total_read_bandwidth_gbps = total_read_bandwidth_gbps - + read_bandwidth_plane_mbps / 1000.0; - } - - DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); - - (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; - - DTRACE( - "minimum theoretical dcfclk without stutter and full utilization = %f MHz", - (*dcfclk_mhz)); - -} - -struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + display_e2e_pipe_params_st *e2e, unsigned int num_pipes) { - struct _vcs_dpi_display_pipe_clock_st clocks; - double max_dispclk = 0.0; - double dcfclk; - double dispclks[DC__NUM_PIPES__MAX]; - double dppclks[DC__NUM_PIPES__MAX]; - bool dppdiv[DC__NUM_PIPES__MAX]; - unsigned int i; + display_pipe_clock_st clocks; + bool visited[DC__NUM_PIPES__MAX]; + double max_dispclk = 25.0; //the min dispclk is 25MHz, so keep the min dispclk caculated larger thant 25MHz + double dcfclk, socclk; + unsigned int i, j, k; + unsigned int dsc_inst = 0; DTRACE("Calculating pipe clocks..."); - /* this is the theoretical minimum, have to adjust based on valid values for soc */ - get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); - - /* if(dcfclk > soc.vnom.dcfclk_mhz) - * dcfclk = soc.vmax.dcfclk_mhz; - * else if(dcfclk > soc.vmin.dcfclk_mhz) - * dcfclk = soc.vnom.dcfclk_mhz; - * else - * dcfclk = soc.vmin.dcfclk_mhz; - */ - dcfclk = dml_socbb_voltage_scaling( &mode_lib->soc, (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; + socclk = dml_socbb_voltage_scaling( + &mode_lib->soc, + (enum voltage_state) e2e[0].clks_cfg.voltage).socclk_mhz; clocks.dcfclk_mhz = dcfclk; + clocks.socclk_mhz = socclk; - get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); - - for (i = 0; i < num_pipes; i++) { - max_dispclk = dml_max(max_dispclk, dispclks[i]); - } - + max_dispclk = dml_max(max_dispclk, get_dispclk_calculated(mode_lib, e2e, num_pipes)); clocks.dispclk_mhz = max_dispclk; - DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); - DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); + DTRACE(" dispclk: %f Mhz", clocks.dispclk_mhz); + DTRACE(" dcfclk: %f Mhz", clocks.dcfclk_mhz); + DTRACE(" socclk: %f Mhz", clocks.socclk_mhz); - for (i = 0; i < num_pipes; i++) { - if (dppclks[i] * 2 < max_dispclk) - dppdiv[i] = 1; + for (k = 0; k < num_pipes; ++k) + visited[k] = false; - if (dppdiv[i]) - clocks.dppclk_div[i] = 1; - else - clocks.dppclk_div[i] = 0; + for (i = 0; i < num_pipes; i++) { + clocks.dppclk_mhz[i] = get_dppclk_calculated(mode_lib, e2e, num_pipes, i); + DTRACE(" dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + + if (e2e[i].pipe.src.is_hsplit && !visited[i]) { + unsigned int grp = e2e[i].pipe.src.hsplit_grp; + + for (j = i; j < num_pipes; j++) { + if (e2e[j].pipe.src.hsplit_grp == grp && e2e[j].pipe.src.is_hsplit + && !visited[j]) { + clocks.dscclk_mhz[j] = get_dscclk_calculated( + mode_lib, + e2e, + num_pipes, + dsc_inst); + DTRACE(" dscclk%d: %f Mhz", j, clocks.dscclk_mhz[j]); + visited[j] = true; + } + } + dsc_inst++; + } - clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); - DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + if (!visited[i]) { + unsigned int otg_inst = e2e[i].pipe.dest.otg_inst; + + for (j = i; j < num_pipes; j++) { + // assign dscclk to all planes with this otg, except if they're doing odm combine, or mpc combine + // which is handled by the conditions above, the odm_combine is not required, but it helps make sense of this code + if (e2e[j].pipe.dest.otg_inst == otg_inst + && !e2e[j].pipe.dest.odm_combine && !visited[j]) { + clocks.dscclk_mhz[j] = get_dscclk_calculated( + mode_lib, + e2e, + num_pipes, + dsc_inst); + DTRACE(" dscclk%d: %f Mhz", j, clocks.dscclk_mhz[j]); + visited[j] = true; + } + } + dsc_inst++; + } } return clocks; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h index aed5f33bb04f..a712dc3ecf4b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h @@ -29,13 +29,9 @@ struct display_mode_lib; -struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( +display_pipe_clock_st dml_clks_get_pipe_clocks( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + display_e2e_pipe_params_st *e2e, unsigned int num_pipes); -bool dml_clks_pipe_clock_requirement_fit_power_constraint( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_dpp_in_grp); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 9fccbbffe129..657b7386021d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -22,8 +22,22 @@ * Authors: AMD * */ -#include "display_rq_dlg_calc.h" + #include "display_mode_lib.h" +#include "display_mode_vba.h" +#include "display_rq_dlg_calc.h" + +static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, + double *refcyc_per_req_delivery_pre_cur, + double *refcyc_per_req_delivery_cur, + double refclk_freq_in_mhz, + double ref_freq_to_pix_freq, + double hscale_pixel_rate_l, + double hscl_ratio, + double vratio_pre_l, + double vratio_l, + unsigned int cur_width, + enum cursor_bpp cur_bpp); static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { @@ -48,6 +62,8 @@ static unsigned int get_bytes_per_element(enum source_format_class source_format ret_val = 4; else ret_val = 2; + } else if (source_format == dm_444_8) { + ret_val = 1; } return ret_val; } @@ -62,123 +78,43 @@ static bool is_dual_plane(enum source_format_class source_format) return ret_val; } -static void get_blk256_size( - unsigned int *blk256_width, - unsigned int *blk256_height, - unsigned int bytes_per_element) -{ - if (bytes_per_element == 1) { - *blk256_width = 16; - *blk256_height = 16; - } else if (bytes_per_element == 2) { - *blk256_width = 16; - *blk256_height = 8; - } else if (bytes_per_element == 4) { - *blk256_width = 8; - *blk256_height = 8; - } else if (bytes_per_element == 8) { - *blk256_width = 8; - *blk256_height = 4; - } -} - -static double get_refcyc_per_delivery( - struct display_mode_lib *mode_lib, +static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib, double refclk_freq_in_mhz, double pclk_freq_in_mhz, - int unsigned recout_width, + bool odm_combine, + unsigned int recout_width, + unsigned int hactive, double vratio, double hscale_pixel_rate, - int unsigned delivery_width, - int unsigned req_per_swath_ub) + unsigned int delivery_width, + unsigned int req_per_swath_ub) { double refcyc_per_delivery = 0.0; + if (vratio <= 1.0) { - refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width - / pclk_freq_in_mhz / (double) req_per_swath_ub; + if (odm_combine) + refcyc_per_delivery = (double) refclk_freq_in_mhz + * dml_min((double) recout_width, (double) hactive / 2.0) + / pclk_freq_in_mhz / (double) req_per_swath_ub; + else + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; } else { refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width / (double) hscale_pixel_rate / (double) req_per_swath_ub; } - DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); - DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); - DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); - DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); - DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); - DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + dml_print("DML_DLG: %s: refclk_freq_in_mhz = %3.2f\n", __func__, refclk_freq_in_mhz); + dml_print("DML_DLG: %s: pclk_freq_in_mhz = %3.2f\n", __func__, pclk_freq_in_mhz); + dml_print("DML_DLG: %s: recout_width = %d\n", __func__, recout_width); + dml_print("DML_DLG: %s: vratio = %3.2f\n", __func__, vratio); + dml_print("DML_DLG: %s: req_per_swath_ub = %d\n", __func__, req_per_swath_ub); + dml_print("DML_DLG: %s: refcyc_per_delivery= %3.2f\n", __func__, refcyc_per_delivery); return refcyc_per_delivery; } -static double get_vratio_pre( - struct display_mode_lib *mode_lib, - unsigned int max_num_sw, - unsigned int max_partial_sw, - unsigned int swath_height, - double vinit, - double l_sw) -{ - double prefill = dml_floor(vinit); - double vratio_pre = 1.0; - - vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; - - if (swath_height > 4) { - double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); - if (tmp0 > vratio_pre) - vratio_pre = tmp0; - } - - DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); - DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); - DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); - DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); - DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); - - if (vratio_pre < 1.0) { - DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); - vratio_pre = 1.0; - } - - if (vratio_pre > 4.0) { - DTRACE( - "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", - __func__, - vratio_pre); - vratio_pre = 4.0; - } - - return vratio_pre; -} - -static void get_swath_need( - struct display_mode_lib *mode_lib, - unsigned int *max_num_sw, - unsigned int *max_partial_sw, - unsigned int swath_height, - double vinit) -{ - double prefill = dml_floor(vinit); - unsigned int max_partial_sw_int; - - DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); - DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); - - ASSERT(prefill > 0.0 && prefill <= 8.0); - - *max_num_sw = (int unsigned) (dml_ceil((prefill - 1.0) / (double) swath_height) + 1.0); /* prefill has to be >= 1 */ - max_partial_sw_int = - (prefill == 1) ? - (swath_height - 1) : - ((int unsigned) (prefill - 2.0) % swath_height); - *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ - - DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); - DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); -} - static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) { if (tile_size == dm_256k_tile) @@ -189,12 +125,11 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si return (4 * 1024); } -static void extract_rq_sizing_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, + display_data_rq_regs_st *rq_regs, + const display_data_rq_sizing_params_st rq_sizing) { - DTRACE("DLG: %s: rq_sizing param", __func__); + dml_print("DML_DLG: %s: rq_sizing param\n", __func__); print__data_rq_sizing_params_st(mode_lib, rq_sizing); rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; @@ -214,25 +149,30 @@ static void extract_rq_sizing_regs( rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; } -void extract_rq_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_rq_params_st rq_param) +static void extract_rq_regs(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, + const display_rq_params_st rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); - if (rq_param.yuv420) + + rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), + 1) - 3; + + if (rq_param.yuv420) { extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), + 1) - 3; + } rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); - /* FIXME: take the max between luma, chroma chunk size? - * okay for now, as we are setting chunk_bytes to 8kb anyways - */ - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + // FIXME: take the max between luma, chroma chunk size? + // okay for now, as we are setting chunk_bytes to 8kb anyways + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -244,21 +184,19 @@ void extract_rq_regs( if (rq_param.yuv420) { if ((double) rq_param.misc.rq_l.stored_swath_bytes / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { - detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); // half to chroma } else { - detile_buf_plane1_addr = dml_round_to_multiple( - (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + detile_buf_plane1_addr = dml_round_to_multiple((unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), 256, - 0) / 64.0; /* 2/3 to chroma */ + 0) / 64.0; // 2/3 to chroma } } rq_regs->plane1_base_address = detile_buf_plane1_addr; } -static void handle_det_buf_split( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +static void handle_det_buf_split(struct display_mode_lib *mode_lib, + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -277,12 +215,10 @@ static void handle_det_buf_split( full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; if (rq_param->yuv420_10bpc) { - full_swath_bytes_packed_l = dml_round_to_multiple( - rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + full_swath_bytes_packed_l = dml_round_to_multiple(rq_param->misc.rq_l.full_swath_bytes * 2 / 3, 256, 1) + 256; - full_swath_bytes_packed_c = dml_round_to_multiple( - rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + full_swath_bytes_packed_c = dml_round_to_multiple(rq_param->misc.rq_c.full_swath_bytes * 2 / 3, 256, 1) + 256; } @@ -290,29 +226,19 @@ static void handle_det_buf_split( if (rq_param->yuv420) { total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; - if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + if (total_swath_bytes <= detile_buf_size_in_bytes) { //full 256b request req128_l = 0; req128_c = 0; swath_bytes_l = full_swath_bytes_packed_l; swath_bytes_c = full_swath_bytes_packed_c; - } else { /*128b request (for luma only for yuv420 8bpc) */ + } else { //128b request (for luma only for yuv420 8bpc) req128_l = 1; req128_c = 0; swath_bytes_l = full_swath_bytes_packed_l / 2; swath_bytes_c = full_swath_bytes_packed_c; } - - /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) - * TODO: Remove after rtl fix - */ - if (req128_l == 1) { - req128_c = 1; - DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); - } - - /* Note: assumption, the config that pass in will fit into - * the detiled buffer. - */ + // Note: assumption, the config that pass in will fit into + // the detiled buffer. } else { total_swath_bytes = 2 * full_swath_bytes_packed_l; @@ -340,207 +266,47 @@ static void handle_det_buf_split( rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; - DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); - DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); - DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); - DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); + dml_print("DML_DLG: %s: req128_l = %0d\n", __func__, req128_l); + dml_print("DML_DLG: %s: req128_c = %0d\n", __func__, req128_c); + dml_print("DML_DLG: %s: full_swath_bytes_packed_l = %0d\n", + __func__, + full_swath_bytes_packed_l); + dml_print("DML_DLG: %s: full_swath_bytes_packed_c = %0d\n", + __func__, + full_swath_bytes_packed_c); } -/* Need refactor. */ -void dml_rq_dlg_get_row_heights( - struct display_mode_lib *mode_lib, - unsigned int *o_dpte_row_height, - unsigned int *o_meta_row_height, +static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, + display_data_rq_sizing_params_st *rq_sizing_param, unsigned int vp_width, + unsigned int vp_height, unsigned int data_pitch, - int source_format, - int tiling, - int macro_tile_size, - int source_scan, - int is_chroma) + unsigned int meta_pitch, + unsigned int source_format, + unsigned int tiling, + unsigned int macro_tile_size, + unsigned int source_scan, + unsigned int is_chroma) { bool surf_linear = (tiling == dm_sw_linear); bool surf_vert = (source_scan == dm_vert); - unsigned int bytes_per_element = get_bytes_per_element( - (enum source_format_class) source_format, - is_chroma); - unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int bytes_per_element; + unsigned int bytes_per_element_y = get_bytes_per_element((enum source_format_class)(source_format), + false); + unsigned int bytes_per_element_c = get_bytes_per_element((enum source_format_class)(source_format), + true); + unsigned int blk256_width = 0; unsigned int blk256_height = 0; - unsigned int log2_blk256_height; - unsigned int blk_bytes; - unsigned int log2_blk_bytes; - unsigned int log2_blk_height; - unsigned int log2_blk_width; - unsigned int log2_meta_req_bytes; - unsigned int log2_meta_req_height; - unsigned int log2_meta_req_width; - unsigned int log2_meta_row_height; - unsigned int log2_vmpg_bytes; - unsigned int dpte_buf_in_pte_reqs; - unsigned int log2_vmpg_height; - unsigned int log2_vmpg_width; - unsigned int log2_dpte_req_height_ptes; - unsigned int log2_dpte_req_width_ptes; - unsigned int log2_dpte_req_height; - unsigned int log2_dpte_req_width; - unsigned int log2_dpte_row_height_linear; - unsigned int log2_dpte_row_height; - unsigned int dpte_req_width; - - if (surf_linear) { - blk256_width = 256; - blk256_height = 1; - } else { - get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); - } - - log2_blk256_height = dml_log2((double) blk256_height); - blk_bytes = surf_linear ? - 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); - log2_blk_bytes = dml_log2((double) blk_bytes); - log2_blk_height = 0; - log2_blk_width = 0; - - /* remember log rule - * "+" in log is multiply - * "-" in log is divide - * "/2" is like square root - * blk is vertical biased - */ - if (tiling != dm_sw_linear) - log2_blk_height = log2_blk256_height - + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); - else - log2_blk_height = 0; /* blk height of 1 */ - - log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; - - /* ------- */ - /* meta */ - /* ------- */ - log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ - - /* each 64b meta request for dcn is 8x8 meta elements and - * a meta element covers one 256b block of the the data surface. - */ - log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ - log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element - - log2_meta_req_height; - log2_meta_row_height = 0; - - /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. - * calculate upper bound of the meta_row_width - */ - if (!surf_vert) - log2_meta_row_height = log2_meta_req_height; - else - log2_meta_row_height = log2_meta_req_width; - - *o_meta_row_height = 1 << log2_meta_row_height; - - /* ------ */ - /* dpte */ - /* ------ */ - log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); - dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; - - log2_vmpg_height = 0; - log2_vmpg_width = 0; - log2_dpte_req_height_ptes = 0; - log2_dpte_req_width_ptes = 0; - log2_dpte_req_height = 0; - log2_dpte_req_width = 0; - log2_dpte_row_height_linear = 0; - log2_dpte_row_height = 0; - dpte_req_width = 0; /* 64b dpte req width in data element */ - - if (surf_linear) { - log2_vmpg_height = 0; /* one line high */ - } else { - log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; - } - log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; - - /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ - if (log2_blk_bytes <= log2_vmpg_bytes) - log2_dpte_req_height_ptes = 0; - else if (log2_blk_height - log2_vmpg_height >= 2) - log2_dpte_req_height_ptes = 2; - else - log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; - log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; - - ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ - (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ - (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ - - /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height - * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent - */ - log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; - log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; - dpte_req_width = 1 << log2_dpte_req_width; - - /* calculate pitch dpte row buffer can hold - * round the result down to a power of two. - */ - if (surf_linear) { - log2_dpte_row_height_linear = dml_floor( - dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); - - ASSERT(log2_dpte_row_height_linear >= 3); - - if (log2_dpte_row_height_linear > 7) - log2_dpte_row_height_linear = 7; - - log2_dpte_row_height = log2_dpte_row_height_linear; - } else { - /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ - if (!surf_vert) { - log2_dpte_row_height = log2_dpte_req_height; - } else { - log2_dpte_row_height = - (log2_blk_width < log2_dpte_req_width) ? - log2_blk_width : log2_dpte_req_width; - } - } - - /* From programming guide: - * There is a special case of saving only half of ptes returned due to buffer space limits. - * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 - * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). - */ - if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 - && log2_blk_bytes >= 16) { - log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ - } - - *o_dpte_row_height = 1 << log2_dpte_row_height; -} - -static void get_surf_rq_param( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, - struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, - struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, - bool is_chroma) -{ - bool mode_422 = 0; - unsigned int vp_width = 0; - unsigned int vp_height = 0; - unsigned int data_pitch = 0; - unsigned int meta_pitch = 0; - unsigned int ppe = mode_422 ? 2 : 1; - bool surf_linear; - bool surf_vert; - unsigned int bytes_per_element; + unsigned int blk256_width_y = 0; + unsigned int blk256_height_y = 0; + unsigned int blk256_width_c = 0; + unsigned int blk256_height_c = 0; unsigned int log2_bytes_per_element; - unsigned int blk256_width; - unsigned int blk256_height; unsigned int log2_blk256_width; unsigned int log2_blk256_height; unsigned int blk_bytes; @@ -556,6 +322,8 @@ static void get_surf_rq_param( unsigned int meta_row_width_ub; unsigned int log2_meta_chunk_bytes; unsigned int log2_meta_chunk_height; + + //full sized meta chunk width in unit of data elements unsigned int log2_meta_chunk_width; unsigned int log2_min_meta_chunk_bytes; unsigned int min_meta_chunk_width; @@ -570,93 +338,72 @@ static void get_surf_rq_param( unsigned int vmpg_bytes; unsigned int meta_pte_req_per_frame_ub; unsigned int meta_pte_bytes_per_frame_ub; - unsigned int log2_vmpg_bytes; - unsigned int dpte_buf_in_pte_reqs; - unsigned int log2_vmpg_height; - unsigned int log2_vmpg_width; - unsigned int log2_dpte_req_height_ptes; - unsigned int log2_dpte_req_width_ptes; - unsigned int log2_dpte_req_height; - unsigned int log2_dpte_req_width; - unsigned int log2_dpte_row_height_linear; - unsigned int log2_dpte_row_height; - unsigned int log2_dpte_group_width; - unsigned int dpte_row_width_ub; - unsigned int dpte_row_height; - unsigned int dpte_req_height; - unsigned int dpte_req_width; - unsigned int dpte_group_width; - unsigned int log2_dpte_group_bytes; - unsigned int log2_dpte_group_length; - unsigned int func_meta_row_height, func_dpte_row_height; - - /* FIXME check if ppe apply for both luma and chroma in 422 case */ - if (is_chroma) { - vp_width = pipe_src_param.viewport_width_c / ppe; - vp_height = pipe_src_param.viewport_height_c; - data_pitch = pipe_src_param.data_pitch_c; - meta_pitch = pipe_src_param.meta_pitch_c; + const unsigned int log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + const unsigned int dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + const unsigned int pde_proc_buffer_size_64k_reqs = + mode_lib->ip.pde_proc_buffer_size_64k_reqs; + + unsigned int log2_vmpg_height = 0; + unsigned int log2_vmpg_width = 0; + unsigned int log2_dpte_req_height_ptes = 0; + unsigned int log2_dpte_req_height = 0; + unsigned int log2_dpte_req_width = 0; + unsigned int log2_dpte_row_height_linear = 0; + unsigned int log2_dpte_row_height = 0; + unsigned int log2_dpte_group_width = 0; + unsigned int dpte_row_width_ub = 0; + unsigned int dpte_req_height = 0; + unsigned int dpte_req_width = 0; + unsigned int dpte_group_width = 0; + unsigned int log2_dpte_group_bytes = 0; + unsigned int log2_dpte_group_length = 0; + unsigned int pde_buf_entries; + bool yuv420 = (source_format == dm_420_8 || source_format == dm_420_10); + + Calculate256BBlockSizes((enum source_format_class)(source_format), + (enum dm_swizzle_mode)(tiling), + bytes_per_element_y, + bytes_per_element_c, + &blk256_height_y, + &blk256_height_c, + &blk256_width_y, + &blk256_width_c); + + if (!is_chroma) { + blk256_width = blk256_width_y; + blk256_height = blk256_height_y; + bytes_per_element = bytes_per_element_y; } else { - vp_width = pipe_src_param.viewport_width / ppe; - vp_height = pipe_src_param.viewport_height; - data_pitch = pipe_src_param.data_pitch; - meta_pitch = pipe_src_param.meta_pitch; + blk256_width = blk256_width_c; + blk256_height = blk256_height_c; + bytes_per_element = bytes_per_element_c; } - rq_sizing_param->chunk_bytes = 8192; - - if (rq_sizing_param->chunk_bytes == 64 * 1024) - rq_sizing_param->min_chunk_bytes = 0; - else - rq_sizing_param->min_chunk_bytes = 1024; - - rq_sizing_param->meta_chunk_bytes = 2048; - rq_sizing_param->min_meta_chunk_bytes = 256; - - rq_sizing_param->mpte_group_bytes = 2048; - - surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - surf_vert = (pipe_src_param.source_scan == dm_vert); - - bytes_per_element = get_bytes_per_element( - (enum source_format_class) pipe_src_param.source_format, - is_chroma); log2_bytes_per_element = dml_log2(bytes_per_element); - blk256_width = 0; - blk256_height = 0; - - if (surf_linear) { - blk256_width = 256 / bytes_per_element; - blk256_height = 1; - } else { - get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); - } - DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); - DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); - DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); - DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + dml_print("DML_DLG: %s: surf_linear = %d\n", __func__, surf_linear); + dml_print("DML_DLG: %s: surf_vert = %d\n", __func__, surf_vert); + dml_print("DML_DLG: %s: blk256_width = %d\n", __func__, blk256_width); + dml_print("DML_DLG: %s: blk256_height = %d\n", __func__, blk256_height); log2_blk256_width = dml_log2((double) blk256_width); log2_blk256_height = dml_log2((double) blk256_height); - blk_bytes = - surf_linear ? 256 : get_blk_size_bytes( - (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); log2_blk_bytes = dml_log2((double) blk_bytes); log2_blk_height = 0; log2_blk_width = 0; - /* remember log rule - * "+" in log is multiply - * "-" in log is divide - * "/2" is like square root - * blk is vertical biased - */ - if (pipe_src_param.sw_mode != dm_sw_linear) + // remember log rule + // "+" in log is multiply + // "-" in log is divide + // "/2" is like square root + // blk is vertical biased + if (tiling != dm_sw_linear) log2_blk_height = log2_blk256_height - + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); else - log2_blk_height = 0; /* blk height of 1 */ + log2_blk_height = 0; // blk height of 1 log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; @@ -665,10 +412,8 @@ static void get_surf_rq_param( + blk256_width; rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; } else { - rq_dlg_param->swath_width_ub = dml_round_to_multiple( - vp_height - 1, - blk256_height, - 1) + blk256_height; + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_height - 1, blk256_height, 1) + + blk256_height; rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; } @@ -682,15 +427,14 @@ static void get_surf_rq_param( rq_misc_param->blk256_height = blk256_height; rq_misc_param->blk256_width = blk256_width; - /* ------- */ - /* meta */ - /* ------- */ - log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + // ------- + // meta + // ------- + log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element - /* each 64b meta request for dcn is 8x8 meta elements and - * a meta element covers one 256b block of the the data surface. - */ - log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + // each 64b meta request for dcn is 8x8 meta elements and + // a meta element covers one 256b block of the the data surface. + log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256 log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element - log2_meta_req_height; meta_req_width = 1 << log2_meta_req_width; @@ -698,9 +442,8 @@ static void get_surf_rq_param( log2_meta_row_height = 0; meta_row_width_ub = 0; - /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. - * calculate upper bound of the meta_row_width - */ + // the dimensions of a meta row are meta_row_width x meta_row_height in elements. + // calculate upper bound of the meta_row_width if (!surf_vert) { log2_meta_row_height = log2_meta_req_height; meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) @@ -714,10 +457,12 @@ static void get_surf_rq_param( } rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); log2_meta_chunk_height = log2_meta_row_height; - /*full sized meta chunk width in unit of data elements */ + //full sized meta chunk width in unit of data elements log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element - log2_meta_chunk_height; log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); @@ -732,21 +477,24 @@ static void get_surf_rq_param( meta_blk_height = blk256_height * 64; meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; meta_surface_bytes = meta_pitch - * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) - + meta_blk_height) * bytes_per_element / 256; + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + meta_blk_height) + * bytes_per_element / 256; vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; - meta_pte_req_per_frame_ub = (dml_round_to_multiple( - meta_surface_bytes - vmpg_bytes, + meta_pte_req_per_frame_ub = (dml_round_to_multiple(meta_surface_bytes - vmpg_bytes, 8 * vmpg_bytes, 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); - meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; //64B mpte request rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; - DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); - DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); - DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); - DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); - DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + dml_print("DML_DLG: %s: meta_blk_height = %d\n", __func__, meta_blk_height); + dml_print("DML_DLG: %s: meta_blk_width = %d\n", __func__, meta_blk_width); + dml_print("DML_DLG: %s: meta_surface_bytes = %d\n", __func__, meta_surface_bytes); + dml_print("DML_DLG: %s: meta_pte_req_per_frame_ub = %d\n", + __func__, + meta_pte_req_per_frame_ub); + dml_print("DML_DLG: %s: meta_pte_bytes_per_frame_ub = %d\n", + __func__, + meta_pte_bytes_per_frame_ub); if (!surf_vert) meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; @@ -758,67 +506,58 @@ static void get_surf_rq_param( else rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; - rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; - - /* ------ */ - /* dpte */ - /* ------ */ - log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); - dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; - - log2_vmpg_height = 0; - log2_vmpg_width = 0; - log2_dpte_req_height_ptes = 0; - log2_dpte_req_width_ptes = 0; - log2_dpte_req_height = 0; - log2_dpte_req_width = 0; - log2_dpte_row_height_linear = 0; - log2_dpte_row_height = 0; - log2_dpte_group_width = 0; - dpte_row_width_ub = 0; - dpte_row_height = 0; - dpte_req_height = 0; /* 64b dpte req height in data element */ - dpte_req_width = 0; /* 64b dpte req width in data element */ - dpte_group_width = 0; - log2_dpte_group_bytes = 0; - log2_dpte_group_length = 0; - + // ------ + // dpte + // ------ if (surf_linear) { - log2_vmpg_height = 0; /* one line high */ + log2_vmpg_height = 0; // one line high } else { log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; } log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; - /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ - if (log2_blk_bytes <= log2_vmpg_bytes) + // only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. + if (surf_linear) { //one 64B PTE request returns 8 PTEs log2_dpte_req_height_ptes = 0; - else if (log2_blk_height - log2_vmpg_height >= 2) - log2_dpte_req_height_ptes = 2; - else - log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; - log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; - - /* Ensure we only have the 3 shapes */ - ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ - (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ - (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ - - /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height - * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent - * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) - */ - log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; - log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + log2_dpte_req_width = log2_vmpg_width + 3; + log2_dpte_req_height = 0; + } else if (log2_blk_bytes == 12) { //4KB tile means 4kB page size + //one 64B req gives 8x1 PTEs for 4KB tile + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width = log2_blk_width + 3; + log2_dpte_req_height = log2_blk_height + 0; + } else if ((log2_blk_bytes >= 16) && (log2_vmpg_bytes == 12)) { // tile block >= 64KB + //two 64B reqs of 2x4 PTEs give 16 PTEs to cover 64KB + log2_dpte_req_height_ptes = 4; + log2_dpte_req_width = log2_blk256_width + 4; // log2_64KB_width + log2_dpte_req_height = log2_blk256_height + 4; // log2_64KB_height + } else { //64KB page size and must 64KB tile block + //one 64B req gives 8x1 PTEs for 64KB tile + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width = log2_blk_width + 3; + log2_dpte_req_height = log2_blk_height + 0; + } + + // The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + // log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + // That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + //log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + //log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; dpte_req_height = 1 << log2_dpte_req_height; dpte_req_width = 1 << log2_dpte_req_width; - /* calculate pitch dpte row buffer can hold - * round the result down to a power of two. - */ + // calculate pitch dpte row buffer can hold + // round the result down to a power of two. + pde_buf_entries = yuv420 ? (pde_proc_buffer_size_64k_reqs >> 1) : pde_proc_buffer_size_64k_reqs; if (surf_linear) { - log2_dpte_row_height_linear = dml_floor( - dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + unsigned int dpte_row_height; + + log2_dpte_row_height_linear = dml_floor(dml_log2(dml_min(64 * 1024 * pde_buf_entries + / bytes_per_element, + dpte_buf_in_pte_reqs + * dpte_req_width) + / data_pitch), + 1); ASSERT(log2_dpte_row_height_linear >= 3); @@ -826,18 +565,16 @@ static void get_surf_rq_param( log2_dpte_row_height_linear = 7; log2_dpte_row_height = log2_dpte_row_height_linear; - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; - - /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. - * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. - */ - dpte_row_width_ub = dml_round_to_multiple( - data_pitch * dpte_row_height - 1, + // For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + // the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + dpte_row_height = 1 << log2_dpte_row_height; + dpte_row_width_ub = dml_round_to_multiple(data_pitch * dpte_row_height - 1, dpte_req_width, 1) + dpte_req_width; rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; } else { - /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + // the upper bound of the dpte_row_width without dependency on viewport position follows. + // for tiled mode, row height is the same as req height and row store up to vp size upper bound if (!surf_vert) { log2_dpte_row_height = log2_dpte_req_height; dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) @@ -851,103 +588,117 @@ static void get_surf_rq_param( + dpte_req_height; rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; } - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; - } - rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; - - /* From programming guide: - * There is a special case of saving only half of ptes returned due to buffer space limits. - * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 - * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). - */ - if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 - && log2_blk_bytes >= 16) { - log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ - rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; } + if (log2_blk_bytes >= 16 && log2_vmpg_bytes == 12) // tile block >= 64KB + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 128; //2*64B dpte request + else + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; //64B dpte request - /* the dpte_group_bytes is reduced for the specific case of vertical - * access of a tile surface that has dpte request of 8x1 ptes. - */ - if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + + // the dpte_group_bytes is reduced for the specific case of vertical + // access of a tile surface that has dpte request of 8x1 ptes. + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) //reduced, in this case, will have page fault within a group rq_sizing_param->dpte_group_bytes = 512; else - /*full size */ + //full size rq_sizing_param->dpte_group_bytes = 2048; - /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + //since pte request size is 64byte, the number of data pte requests per full sized group is as follows. log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); - log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + log2_dpte_group_length = log2_dpte_group_bytes - 6; //length in 64b requests - /* full sized data pte group width in elements */ + // full sized data pte group width in elements if (!surf_vert) log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; else log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + //But if the tile block >=64KB and the page size is 4KB, then each dPTE request is 2*64B + if ((log2_blk_bytes >= 16) && (log2_vmpg_bytes == 12)) // tile block >= 64KB + log2_dpte_group_width = log2_dpte_group_width - 1; + dpte_group_width = 1 << log2_dpte_group_width; - /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, - * the upper bound for the dpte groups per row is as follows. - */ - rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( - (double) dpte_row_width_ub / dpte_group_width); + // since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + // the upper bound for the dpte groups per row is as follows. + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil((double) dpte_row_width_ub / dpte_group_width, + 1); +} + +static void get_surf_rq_param(struct display_mode_lib *mode_lib, + display_data_rq_sizing_params_st *rq_sizing_param, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, + const display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + + // FIXME check if ppe apply for both luma and chroma in 422 case + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + + rq_sizing_param->mpte_group_bytes = 2048; - dml_rq_dlg_get_row_heights( - mode_lib, - &func_dpte_row_height, - &func_meta_row_height, + get_meta_and_pte_attr(mode_lib, + rq_dlg_param, + rq_misc_param, + rq_sizing_param, vp_width, + vp_height, data_pitch, + meta_pitch, pipe_src_param.source_format, pipe_src_param.sw_mode, pipe_src_param.macro_tile_size, pipe_src_param.source_scan, is_chroma); - - /* Just a check to make sure this function and the new one give the same - * result. The standalone get_row_heights() function is based off of the - * code in this function so the same changes need to be made to both. - */ - if (rq_dlg_param->meta_row_height != func_meta_row_height) { - DTRACE( - "MISMATCH: rq_dlg_param->meta_row_height = %d", - rq_dlg_param->meta_row_height); - DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); - ASSERT(0); - } - - if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { - DTRACE( - "MISMATCH: rq_dlg_param->dpte_row_height = %d", - rq_dlg_param->dpte_row_height); - DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); - ASSERT(0); - } } -void dml_rq_dlg_get_rq_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param) { - /* get param for luma surface */ + // get param for luma surface rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 || pipe_src_param.source_format == dm_420_10; rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; - get_surf_rq_param( - mode_lib, + get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), &(rq_param->dlg.rq_l), &(rq_param->misc.rq_l), pipe_src_param, 0); - if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { - /* get param for chroma surface */ - get_surf_rq_param( - mode_lib, + if (is_dual_plane((enum source_format_class)(pipe_src_param.source_format))) { + // get param for chroma surface + get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), &(rq_param->dlg.rq_c), &(rq_param->misc.rq_c), @@ -955,355 +706,126 @@ void dml_rq_dlg_get_rq_params( 1); } - /* calculate how to split the det buffer space between luma and chroma */ + // calculate how to split the det buffer space between luma and chroma handle_det_buf_split(mode_lib, rq_param, pipe_src_param); print__rq_params_st(mode_lib, *rq_param); } -void dml_rq_dlg_get_rq_reg( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +void dml_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, + const display_pipe_source_params_st pipe_src_param) { - struct _vcs_dpi_display_rq_params_st rq_param = {0}; + display_rq_params_st rq_param = {0}; memset(rq_regs, 0, sizeof(*rq_regs)); - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_src_param); extract_rq_regs(mode_lib, rq_regs, rq_param); print__rq_regs_st(mode_lib, *rq_regs); } -/* TODO: Need refactor, so this is used by dml_rq_dlg_get_dlg_params as well - * The problem is that there are some intermediate terms that would need by - * some dlg calculation (i.e. rest of prefetch and active prog guide calculation) - */ -void dml_rq_dlg_get_dlg_params_prefetch( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, +// Note: currently taken in as is. +// Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. +void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + display_dlg_regs_st *disp_dlg_regs, + display_ttu_regs_st *disp_ttu_regs, + const display_rq_dlg_params_st rq_dlg_param, + const display_dlg_sys_params_st dlg_sys_param, const bool cstate_en, const bool pstate_en, - const bool vm_en) + const bool vm_en, + const bool ignore_viewport_pos, + const bool immediate_flip_support) { - /* Prefetch */ - unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; - bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src; + const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest; + const display_output_params_st *dout = &e2e_pipe_param[pipe_idx].dout; + const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg; + const scaler_ratio_depth_st *scl = &e2e_pipe_param[pipe_idx].pipe.scale_ratio_depth; + const scaler_taps_st *taps = &e2e_pipe_param[pipe_idx].pipe.scale_taps; + + // ------------------------- + // Section 1.15.2.1: OTG dependent Params + // ------------------------- + // Timing + unsigned int htotal = dst->htotal; +// unsigned int hblank_start = dst.hblank_start; // TODO: Remove + unsigned int hblank_end = dst->hblank_end; + unsigned int vblank_start = dst->vblank_start; + unsigned int vblank_end = dst->vblank_end; unsigned int min_vblank = mode_lib->ip.min_vblank_lines; - const double prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ - double min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; - double t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; - - bool dcc_en = e2e_pipe_param.pipe.src.dcc; - bool dual_plane = is_dual_plane( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format); - unsigned int bytes_per_element_l = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 0); - unsigned int bytes_per_element_c = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 1); - - double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; - double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; - double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; - - double line_time_in_us = (htotal / pclk_freq_in_mhz); - double vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; - double vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; - double vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; - double vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; - - unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; - unsigned int swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; - unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; - unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; - - unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; - unsigned int swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - unsigned int dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; - unsigned int vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; - unsigned int vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; - unsigned int vready_offset = e2e_pipe_param.pipe.dest.vready_offset; - - const unsigned int dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; - const unsigned int dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; - unsigned int pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz - / dppclk_freq_in_mhz - + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; - unsigned int dst_y_after_scaler = 0; - unsigned int dst_x_after_scaler = 0; - unsigned int vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + double dppclk_freq_in_mhz = clks->dppclk_mhz; + double dispclk_freq_in_mhz = clks->dispclk_mhz; + double refclk_freq_in_mhz = clks->refclk_mhz; + double pclk_freq_in_mhz = dst->pixel_rate_mhz; + bool interlaced = dst->interlaced; - double line_wait; - double line_o; - double line_setup; - double line_calc; - double dst_y_prefetch; - double t_pre_us; - int unsigned vm_bytes; - int unsigned meta_row_bytes; - int unsigned max_num_sw_l; - int unsigned max_num_sw_c; - int unsigned max_partial_sw_l; - int unsigned max_partial_sw_c; - - double max_vinit_l; - double max_vinit_c; - int unsigned lsw_l; - int unsigned lsw_c; - int unsigned sw_bytes_ub_l; - int unsigned sw_bytes_ub_c; - int unsigned sw_bytes; - int unsigned dpte_row_bytes; + double ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; - if (interlaced) - vstartup_start = vstartup_start / 2; + double min_dcfclk_mhz; + double t_calc_us; + double min_ttu_vblank; - if (vstartup_start >= min_vblank) { - min_vblank = vstartup_start + 1; - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", - __func__, - vstartup_start, - min_vblank); - } + double min_dst_y_ttu_vblank; + unsigned int dlg_vblank_start; + bool dual_plane; + bool mode_422; + unsigned int access_dir; + unsigned int vp_height_l; + unsigned int vp_width_l; + unsigned int vp_height_c; + unsigned int vp_width_c; - if (e2e_pipe_param.pipe.src.is_hsplit) - dst_x_after_scaler = pixel_rate_delay_subtotal - + e2e_pipe_param.pipe.dest.recout_width; - else - dst_x_after_scaler = pixel_rate_delay_subtotal; + // Scaling + unsigned int htaps_l; + unsigned int htaps_c; + double hratio_l; + double hratio_c; + double vratio_l; + double vratio_c; + bool scl_enable; - if (e2e_pipe_param.dout.output_format == dm_420) - dst_y_after_scaler = 1; - else - dst_y_after_scaler = 0; + double line_time_in_us; + // double vinit_l; + // double vinit_c; + // double vinit_bot_l; + // double vinit_bot_c; - if (dst_x_after_scaler >= htotal) { - dst_x_after_scaler = dst_x_after_scaler - htotal; - dst_y_after_scaler = dst_y_after_scaler + 1; - } - - DTRACE("DLG: %s: htotal = %d", __func__, htotal); - DTRACE( - "DLG: %s: pixel_rate_delay_subtotal = %d", - __func__, - pixel_rate_delay_subtotal); - DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); - DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); - - line_wait = mode_lib->soc.urgent_latency_us; - if (cstate_en) - line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); - if (pstate_en) - line_wait = dml_max( - mode_lib->soc.dram_clock_change_latency_us - + mode_lib->soc.urgent_latency_us, - line_wait); - line_wait = line_wait / line_time_in_us; - - line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; - line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; - line_calc = t_calc_us / line_time_in_us; - - DTRACE( - "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", - __func__, - (double) mode_lib->soc.sr_enter_plus_exit_time_us); - DTRACE( - "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", - __func__, - (double) mode_lib->soc.dram_clock_change_latency_us); - - DTRACE("DLG: %s: urgent_latency_us = %3.2f", __func__, mode_lib->soc.urgent_latency_us); - DTRACE( - "DLG: %s: t_srx_delay_us = %3.2f", - __func__, - (double) dlg_sys_param.t_srx_delay_us); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); - DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); - DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); - DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); - DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); - DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); - DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); - DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); - - dst_y_prefetch = ((double) min_vblank - 1.0) - - (line_setup + line_calc + line_wait + line_o); - DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); - ASSERT(dst_y_prefetch >= 2.0); - - dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; - DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); - - t_pre_us = dst_y_prefetch * line_time_in_us; - vm_bytes = 0; - meta_row_bytes = 0; - - if (dcc_en && vm_en) - vm_bytes = meta_pte_bytes_per_frame_ub_l; - if (dcc_en) - meta_row_bytes = meta_bytes_per_row_ub_l; - - max_num_sw_l = 0; - max_num_sw_c = 0; - max_partial_sw_l = 0; - max_partial_sw_c = 0; - - max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; - max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; - - get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); - if (dual_plane) - get_swath_need( - mode_lib, - &max_num_sw_c, - &max_partial_sw_c, - swath_height_c, - max_vinit_c); - - lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; - lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; - sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; - sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; - sw_bytes = 0; - dpte_row_bytes = 0; - - if (vm_en) { - if (dual_plane) - dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; - else - dpte_row_bytes = dpte_bytes_per_row_ub_l; - } else { - dpte_row_bytes = 0; - } - - if (dual_plane) - sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; - else - sw_bytes = sw_bytes_ub_l; - - DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); - DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); - DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); - DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); - DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); - DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); - - prefetch_param->prefetch_bw = - (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; - prefetch_param->flip_bytes = (vm_bytes + dpte_row_bytes + meta_row_bytes); -} - -/* Note: currently taken in as is. - * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. - */ -void dml_rq_dlg_get_dlg_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, - const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, - const bool cstate_en, - const bool pstate_en, - const bool vm_en, - const bool iflip_en) -{ - /* Timing */ - unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; - unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; - unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; - unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; - bool interlaced = e2e_pipe_param.pipe.dest.interlaced; - unsigned int min_vblank = mode_lib->ip.min_vblank_lines; - - double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; - double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; - double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; - double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; - - double ref_freq_to_pix_freq; - double prefetch_xy_calc_in_dcfclk; - double min_dcfclk_mhz; - double t_calc_us; - double min_ttu_vblank; - double min_dst_y_ttu_vblank; - int unsigned dlg_vblank_start; - bool dcc_en; - bool dual_plane; - bool mode_422; - unsigned int access_dir; - unsigned int bytes_per_element_l; - unsigned int bytes_per_element_c; - unsigned int vp_height_l; - unsigned int vp_width_l; - unsigned int vp_height_c; - unsigned int vp_width_c; - unsigned int htaps_l; - unsigned int htaps_c; - double hratios_l; - double hratios_c; - double vratio_l; - double vratio_c; - double line_time_in_us; - double vinit_l; - double vinit_c; - double vinit_bot_l; - double vinit_bot_c; - unsigned int swath_height_l; + // unsigned int swath_height_l; unsigned int swath_width_ub_l; - unsigned int dpte_bytes_per_row_ub_l; + // unsigned int dpte_bytes_per_row_ub_l; unsigned int dpte_groups_per_row_ub_l; - unsigned int meta_pte_bytes_per_frame_ub_l; - unsigned int meta_bytes_per_row_ub_l; - unsigned int swath_height_c; + // unsigned int meta_pte_bytes_per_frame_ub_l; + // unsigned int meta_bytes_per_row_ub_l; + + // unsigned int swath_height_c; unsigned int swath_width_ub_c; - unsigned int dpte_bytes_per_row_ub_c; + // unsigned int dpte_bytes_per_row_ub_c; unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int meta_chunks_per_row_ub_c; unsigned int vupdate_offset; unsigned int vupdate_width; unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; unsigned int dispclk_delay_subtotal; unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; unsigned int dst_x_after_scaler; unsigned int dst_y_after_scaler; double line_wait; - double line_o; - double line_setup; - double line_calc; double dst_y_prefetch; - double t_pre_us; - int unsigned vm_bytes; - int unsigned meta_row_bytes; - int unsigned max_num_sw_l; - int unsigned max_num_sw_c; - int unsigned max_partial_sw_l; - int unsigned max_partial_sw_c; - double max_vinit_l; - double max_vinit_c; - int unsigned lsw_l; - int unsigned lsw_c; - int unsigned sw_bytes_ub_l; - int unsigned sw_bytes_ub_c; - int unsigned sw_bytes; - int unsigned dpte_row_bytes; - double prefetch_bw; - double flip_bw; - double t_vm_us; - double t_r0_us; double dst_y_per_vm_vblank; double dst_y_per_row_vblank; + double dst_y_per_vm_flip; + double dst_y_per_row_flip; double min_dst_y_per_vm_vblank; double min_dst_y_per_row_vblank; double lsw; @@ -1312,6 +834,7 @@ void dml_rq_dlg_get_dlg_params( unsigned int req_per_swath_ub_l; unsigned int req_per_swath_ub_c; unsigned int meta_row_height_l; + unsigned int meta_row_height_c; unsigned int swath_width_pixels_ub_l; unsigned int swath_width_pixels_ub_c; unsigned int scaler_rec_in_width_l; @@ -1326,59 +849,52 @@ void dml_rq_dlg_get_dlg_params( double refcyc_per_line_delivery_pre_c; double refcyc_per_line_delivery_l; double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; double refcyc_per_req_delivery_pre_c; double refcyc_per_req_delivery_l; double refcyc_per_req_delivery_c; + + unsigned int full_recout_width; + double xfc_transfer_delay; + double xfc_precharge_delay; + double xfc_remote_surface_flip_latency; + double xfc_dst_y_delta_drq_limit; + double xfc_prefetch_margin; double refcyc_per_req_delivery_pre_cur0; double refcyc_per_req_delivery_cur0; - int unsigned full_recout_width; - double hratios_cur0; - unsigned int cur0_src_width; - enum cursor_bpp cur0_bpp; - unsigned int cur0_req_size; - unsigned int cur0_req_width; - double cur0_width_ub; - double cur0_req_per_width; - double hactive_cur0; + double refcyc_per_req_delivery_pre_cur1; + double refcyc_per_req_delivery_cur1; memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); - DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); - DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); - DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); - DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); - - /* ------------------------- */ - /* Section 1.5.2.1: OTG dependent Params */ - /* ------------------------- */ - DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); - DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); - DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); - DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); - DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); - - ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + dml_print("DML_DLG: %s: cstate_en = %d\n", __func__, cstate_en); + dml_print("DML_DLG: %s: pstate_en = %d\n", __func__, pstate_en); + dml_print("DML_DLG: %s: vm_en = %d\n", __func__, vm_en); + dml_print("DML_DLG: %s: ignore_viewport_pos = %d\n", __func__, ignore_viewport_pos); + dml_print("DML_DLG: %s: immediate_flip_support = %d\n", __func__, immediate_flip_support); + + dml_print("DML_DLG: %s: dppclk_freq_in_mhz = %3.2f\n", __func__, dppclk_freq_in_mhz); + dml_print("DML_DLG: %s: dispclk_freq_in_mhz = %3.2f\n", __func__, dispclk_freq_in_mhz); + dml_print("DML_DLG: %s: refclk_freq_in_mhz = %3.2f\n", __func__, refclk_freq_in_mhz); + dml_print("DML_DLG: %s: pclk_freq_in_mhz = %3.2f\n", __func__, pclk_freq_in_mhz); + dml_print("DML_DLG: %s: interlaced = %d\n", __func__, interlaced); ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal * dml_pow(2, 8)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; // 15 bits disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end * (double) ref_freq_to_pix_freq); ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); - disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ - prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; - t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; - min_ttu_vblank = dlg_sys_param.t_urg_wm_us; - if (cstate_en) - min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); - if (pstate_en) - min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); - min_ttu_vblank = min_ttu_vblank + t_calc_us; + set_prefetch_mode(mode_lib, cstate_en, pstate_en, ignore_viewport_pos, immediate_flip_support); + t_calc_us = get_tcalc(mode_lib, e2e_pipe_param, num_pipes); + min_ttu_vblank = get_min_ttu_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; @@ -1387,383 +903,202 @@ void dml_rq_dlg_get_dlg_params( + min_dst_y_ttu_vblank) * dml_pow(2, 2)); ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); - DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); - DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); - DTRACE( - "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + dml_print("DML_DLG: %s: min_dcfclk_mhz = %3.2f\n", + __func__, + min_dcfclk_mhz); + dml_print("DML_DLG: %s: min_ttu_vblank = %3.2f\n", + __func__, + min_ttu_vblank); + dml_print("DML_DLG: %s: min_dst_y_ttu_vblank = %3.2f\n", __func__, min_dst_y_ttu_vblank); - DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); - DTRACE( - "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + dml_print("DML_DLG: %s: t_calc_us = %3.2f\n", + __func__, + t_calc_us); + dml_print("DML_DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x\n", __func__, disp_dlg_regs->min_dst_y_next_start); - DTRACE( - "DLG: %s: ref_freq_to_pix_freq = %3.2f", + dml_print("DML_DLG: %s: ref_freq_to_pix_freq = %3.2f\n", __func__, ref_freq_to_pix_freq); - /* ------------------------- */ - /* Section 1.5.2.2: Prefetch, Active and TTU */ - /* ------------------------- */ - /* Prefetch Calc */ - /* Source */ - dcc_en = e2e_pipe_param.pipe.src.dcc; - dual_plane = is_dual_plane( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format); - mode_422 = 0; /* FIXME */ - access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ - bytes_per_element_l = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 0); - bytes_per_element_c = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, - 1); - vp_height_l = e2e_pipe_param.pipe.src.viewport_height; - vp_width_l = e2e_pipe_param.pipe.src.viewport_width; - vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; - vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; - - /* Scaling */ - htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; - htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; - hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; - hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; - vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; - vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + // ------------------------- + // Section 1.15.2.2: Prefetch, Active and TTU + // ------------------------- + // Prefetch Calc + // Source +// dcc_en = src.dcc; + dual_plane = is_dual_plane((enum source_format_class)(src->source_format)); + mode_422 = 0; // FIXME + access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed +// bytes_per_element_l = get_bytes_per_element(source_format_class(src.source_format), 0); +// bytes_per_element_c = get_bytes_per_element(source_format_class(src.source_format), 1); + vp_height_l = src->viewport_height; + vp_width_l = src->viewport_width; + vp_height_c = src->viewport_height_c; + vp_width_c = src->viewport_width_c; + + // Scaling + htaps_l = taps->htaps; + htaps_c = taps->htaps_c; + hratio_l = scl->hscl_ratio; + hratio_c = scl->hscl_ratio_c; + vratio_l = scl->vscl_ratio; + vratio_c = scl->vscl_ratio_c; + scl_enable = scl->scl_enable; line_time_in_us = (htotal / pclk_freq_in_mhz); - vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; - vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; - vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; - vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; +// vinit_l = scl.vinit; +// vinit_c = scl.vinit_c; +// vinit_bot_l = scl.vinit_bot; +// vinit_bot_c = scl.vinit_bot_c; - swath_height_l = rq_dlg_param.rq_l.swath_height; +// unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; +// unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; - meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; - meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; +// unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; +// unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; - swath_height_c = rq_dlg_param.rq_c.swath_height; +// unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + // dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; - vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; - vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; - vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + meta_chunks_per_row_ub_c = rq_dlg_param.rq_c.meta_chunks_per_row_ub; + vupdate_offset = dst->vupdate_offset; + vupdate_width = dst->vupdate_width; + vready_offset = dst->vready_offset; dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + + if (scl_enable) + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_scl; + else + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_scl_lb_only; + + dppclk_delay_subtotal += mode_lib->ip.dppclk_delay_cnvc_formatter + + src->num_cursors * mode_lib->ip.dppclk_delay_cnvc_cursor; + + if (dout->dsc_enable) { + double dsc_delay = get_dsc_delay(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + + dispclk_delay_subtotal += dsc_delay; + } + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; - vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + vstartup_start = dst->vstartup_start; + if (interlaced) { + if (vstartup_start / 2.0 + - (double) (vready_offset + vupdate_width + vupdate_offset) / htotal + <= vblank_end / 2.0) + disp_dlg_regs->vready_after_vcount0 = 1; + else + disp_dlg_regs->vready_after_vcount0 = 0; + } else { + if (vstartup_start + - (double) (vready_offset + vupdate_width + vupdate_offset) / htotal + <= vblank_end) + disp_dlg_regs->vready_after_vcount0 = 1; + else + disp_dlg_regs->vready_after_vcount0 = 0; + } + // TODO: Where is this coming from? if (interlaced) vstartup_start = vstartup_start / 2; + // TODO: What if this min_vblank doesn't match the value in the dml_config_settings.cpp? if (vstartup_start >= min_vblank) { - DTRACE( - "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + dml_print("WARNING: DML_DLG: %s: vblank_start=%d vblank_end=%d\n", __func__, vblank_start, vblank_end); - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + dml_print("WARNING: DML_DLG: %s: vstartup_start=%d should be less than min_vblank=%d\n", __func__, vstartup_start, min_vblank); min_vblank = vstartup_start + 1; - DTRACE( - "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + dml_print("WARNING: DML_DLG: %s: vstartup_start=%d should be less than min_vblank=%d\n", __func__, vstartup_start, min_vblank); } - dst_x_after_scaler = 0; - dst_y_after_scaler = 0; - - if (e2e_pipe_param.pipe.src.is_hsplit) - dst_x_after_scaler = pixel_rate_delay_subtotal - + e2e_pipe_param.pipe.dest.recout_width; - else - dst_x_after_scaler = pixel_rate_delay_subtotal; - - if (e2e_pipe_param.dout.output_format == dm_420) - dst_y_after_scaler = 1; - else - dst_y_after_scaler = 0; - - if (dst_x_after_scaler >= htotal) { - dst_x_after_scaler = dst_x_after_scaler - htotal; - dst_y_after_scaler = dst_y_after_scaler + 1; - } + dst_x_after_scaler = get_dst_x_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dst_y_after_scaler = get_dst_y_after_scaler(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); - DTRACE("DLG: %s: htotal = %d", __func__, htotal); - DTRACE( - "DLG: %s: pixel_rate_delay_subtotal = %d", + dml_print("DML_DLG: %s: htotal = %d\n", __func__, htotal); + dml_print("DML_DLG: %s: pixel_rate_delay_subtotal = %d\n", __func__, pixel_rate_delay_subtotal); - DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); - DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + dml_print("DML_DLG: %s: dst_x_after_scaler = %d\n", + __func__, + dst_x_after_scaler); + dml_print("DML_DLG: %s: dst_y_after_scaler = %d\n", + __func__, + dst_y_after_scaler); + // Lwait line_wait = mode_lib->soc.urgent_latency_us; if (cstate_en) line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); if (pstate_en) - line_wait = dml_max( - mode_lib->soc.dram_clock_change_latency_us + line_wait = dml_max(mode_lib->soc.dram_clock_change_latency_us + mode_lib->soc.urgent_latency_us, line_wait); line_wait = line_wait / line_time_in_us; - line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; - line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; - line_calc = t_calc_us / line_time_in_us; + dst_y_prefetch = get_dst_y_prefetch(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dml_print("DML_DLG: %s: dst_y_prefetch (after rnd) = %3.2f\n", __func__, dst_y_prefetch); - DTRACE( - "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", - __func__, - (double) mode_lib->soc.sr_enter_plus_exit_time_us); - DTRACE( - "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", - __func__, - (double) mode_lib->soc.dram_clock_change_latency_us); - DTRACE( - "DLG: %s: soc.urgent_latency_us = %3.2f", - __func__, - mode_lib->soc.urgent_latency_us); - - DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); - if (dual_plane) - DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); - - DTRACE( - "DLG: %s: t_srx_delay_us = %3.2f", - __func__, - (double) dlg_sys_param.t_srx_delay_us); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); - DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); - DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); - DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); - DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); - DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); - DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); - DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); - DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); - - dst_y_prefetch = ((double) min_vblank - 1.0) - - (line_setup + line_calc + line_wait + line_o); - DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); - ASSERT(dst_y_prefetch >= 2.0); - - dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; - DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); - - t_pre_us = dst_y_prefetch * line_time_in_us; - vm_bytes = 0; - meta_row_bytes = 0; - - if (dcc_en && vm_en) - vm_bytes = meta_pte_bytes_per_frame_ub_l; - if (dcc_en) - meta_row_bytes = meta_bytes_per_row_ub_l; - - max_num_sw_l = 0; - max_num_sw_c = 0; - max_partial_sw_l = 0; - max_partial_sw_c = 0; - - max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; - max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; - - get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); - if (dual_plane) - get_swath_need( - mode_lib, - &max_num_sw_c, - &max_partial_sw_c, - swath_height_c, - max_vinit_c); - - lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; - lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; - sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; - sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; - sw_bytes = 0; - dpte_row_bytes = 0; - - if (vm_en) { - if (dual_plane) - dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; - else - dpte_row_bytes = dpte_bytes_per_row_ub_l; - } else { - dpte_row_bytes = 0; - } - - if (dual_plane) - sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; - else - sw_bytes = sw_bytes_ub_l; - - DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); - DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); - DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); - DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); - DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); - DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); - - prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; - flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) - / (double) dlg_sys_param.total_flip_bytes; - t_vm_us = line_time_in_us / 4.0; - if (vm_en && dcc_en) { - t_vm_us = dml_max( - dlg_sys_param.t_extra_us, - dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); - - if (iflip_en && !dual_plane) { - t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); - if (flip_bw > 0.) - t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); - } - } - - t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); - - if (vm_en || dcc_en) { - t_r0_us = dml_max( - (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, - dlg_sys_param.t_extra_us); - t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); - - if (iflip_en && !dual_plane) { - t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); - if (flip_bw > 0.) - t_r0_us = dml_max( - (dpte_row_bytes + meta_row_bytes) / flip_bw, - t_r0_us); - } - } - - disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ - disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ - ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); - DTRACE( - "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", - __func__, - disp_dlg_regs->dst_y_after_scaler); - DTRACE( - "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", - __func__, - disp_dlg_regs->refcyc_x_after_scaler); - - disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); - DTRACE( - "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", - __func__, - disp_dlg_regs->dst_y_prefetch); - - dst_y_per_vm_vblank = 0.0; - dst_y_per_row_vblank = 0.0; - - dst_y_per_vm_vblank = t_vm_us / line_time_in_us; - dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125)) / 4.0; - disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); - - dst_y_per_row_vblank = t_r0_us / line_time_in_us; - dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125)) / 4.0; - disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); - - DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); - DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); - DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); - DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); - - DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); - DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); - DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); - DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); - DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); - DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); - DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); - DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + dst_y_per_vm_vblank = get_dst_y_per_vm_vblank(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + dst_y_per_row_vblank = get_dst_y_per_row_vblank(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + dst_y_per_vm_flip = get_dst_y_per_vm_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + dst_y_per_row_flip = get_dst_y_per_row_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); min_dst_y_per_vm_vblank = 8.0; min_dst_y_per_row_vblank = 16.0; + + // magic! if (htotal <= 75) { min_vblank = 300; min_dst_y_per_vm_vblank = 100.0; min_dst_y_per_row_vblank = 100.0; } + dml_print("DML_DLG: %s: dst_y_per_vm_vblank = %3.2f\n", __func__, dst_y_per_vm_vblank); + dml_print("DML_DLG: %s: dst_y_per_row_vblank = %3.2f\n", __func__, dst_y_per_row_vblank); + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); - DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); - - vratio_pre_l = get_vratio_pre( - mode_lib, - max_num_sw_l, - max_partial_sw_l, - swath_height_l, - max_vinit_l, - lsw); - vratio_pre_c = 1.0; - if (dual_plane) - vratio_pre_c = get_vratio_pre( - mode_lib, - max_num_sw_c, - max_partial_sw_c, - swath_height_c, - max_vinit_c, - lsw); - - DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); - DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); - - ASSERT(vratio_pre_l <= 4.0); - if (vratio_pre_l >= 4.0) - disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; - else - disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); - - ASSERT(vratio_pre_c <= 4.0); - if (vratio_pre_c >= 4.0) - disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; - else - disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); - - disp_dlg_regs->refcyc_per_pte_group_vblank_l = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); - ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); - - disp_dlg_regs->refcyc_per_pte_group_vblank_c = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); - ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); + dml_print("DML_DLG: %s: lsw = %3.2f\n", __func__, lsw); - disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = - (unsigned int) (dst_y_per_row_vblank * (double) htotal - * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); - ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + vratio_pre_l = get_vratio_prefetch_l(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + vratio_pre_c = get_vratio_prefetch_c(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); - disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = - disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + dml_print("DML_DLG: %s: vratio_pre_l=%3.2f\n", __func__, vratio_pre_l); + dml_print("DML_DLG: %s: vratio_pre_c=%3.2f\n", __func__, vratio_pre_c); - /* Active */ + // Active req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + meta_row_height_c = rq_dlg_param.rq_c.meta_row_height; swath_width_pixels_ub_l = 0; swath_width_pixels_ub_c = 0; scaler_rec_in_width_l = 0; @@ -1771,40 +1106,8 @@ void dml_rq_dlg_get_dlg_params( dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; - disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l - / (double) vratio_l * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c - / (double) vratio_c * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l - / (double) vratio_l * dml_pow(2, 2)); - ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); - - disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ - - disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l - / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq - / (double) dpte_groups_per_row_ub_l); - if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; - - disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c - / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq - / (double) dpte_groups_per_row_ub_c); - if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; - - disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l - / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq - / (double) meta_chunks_per_row_ub_l); - if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) - disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; - if (mode_422) { - swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element swath_width_pixels_ub_c = swath_width_ub_c * 2; } else { swath_width_pixels_ub_l = swath_width_ub_l * 1; @@ -1819,15 +1122,15 @@ void dml_rq_dlg_get_dlg_params( if (htaps_l <= 1) min_hratio_fact_l = 2.0; else if (htaps_l <= 6) { - if ((hratios_l * 2.0) > 4.0) + if ((hratio_l * 2.0) > 4.0) min_hratio_fact_l = 4.0; else - min_hratio_fact_l = hratios_l * 2.0; + min_hratio_fact_l = hratio_l * 2.0; } else { - if (hratios_l > 4.0) + if (hratio_l > 4.0) min_hratio_fact_l = 4.0; else - min_hratio_fact_l = hratios_l; + min_hratio_fact_l = hratio_l; } hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; @@ -1835,15 +1138,15 @@ void dml_rq_dlg_get_dlg_params( if (htaps_c <= 1) min_hratio_fact_c = 2.0; else if (htaps_c <= 6) { - if ((hratios_c * 2.0) > 4.0) + if ((hratio_c * 2.0) > 4.0) min_hratio_fact_c = 4.0; else - min_hratio_fact_c = hratios_c * 2.0; + min_hratio_fact_c = hratio_c * 2.0; } else { - if (hratios_c > 4.0) + if (hratio_c > 4.0) min_hratio_fact_c = 4.0; else - min_hratio_fact_c = hratios_c; + min_hratio_fact_c = hratio_c; } hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; @@ -1857,97 +1160,90 @@ void dml_rq_dlg_get_dlg_params( refcyc_per_req_delivery_pre_c = 0.; refcyc_per_req_delivery_l = 0.; refcyc_per_req_delivery_c = 0.; - refcyc_per_req_delivery_pre_cur0 = 0.; - refcyc_per_req_delivery_cur0 = 0.; full_recout_width = 0; - if (e2e_pipe_param.pipe.src.is_hsplit) { - if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { - DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); - full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + // In ODM + if (src->is_hsplit) { + // This "hack" is only allowed (and valid) for MPC combine. In ODM + // combine, you MUST specify the full_recout_width...according to Oswin + if (dst->full_recout_width == 0 && !dst->odm_combine) { + dml_print("DML_DLG: %s: Warning: full_recout_width not set in hsplit mode\n", + __func__); + full_recout_width = dst->recout_width * 2; // assume half split for dcn1 } else - full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + full_recout_width = dst->full_recout_width; } else - full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + full_recout_width = dst->recout_width; - refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( - mode_lib, + // mpc_combine and odm_combine are mutually exclusive + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_l, hscale_pixel_rate_l, swath_width_pixels_ub_l, - 1); /* per line */ + 1); // per line - refcyc_per_line_delivery_l = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_l, hscale_pixel_rate_l, swath_width_pixels_ub_l, - 1); /* per line */ + 1); // per line - DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); - DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + dml_print("DML_DLG: %s: full_recout_width = %d\n", __func__, - refcyc_per_line_delivery_pre_l); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + full_recout_width); + dml_print("DML_DLG: %s: hscale_pixel_rate_l = %3.2f\n", + __func__, + hscale_pixel_rate_l); + dml_print("DML_DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f\n", __func__, - refcyc_per_line_delivery_l); - - disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( refcyc_per_line_delivery_pre_l); - disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + dml_print("DML_DLG: %s: refcyc_per_line_delivery_l = %3.2f\n", + __func__, refcyc_per_line_delivery_l); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); if (dual_plane) { - refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_c, hscale_pixel_rate_c, swath_width_pixels_ub_c, - 1); /* per line */ + 1); // per line - refcyc_per_line_delivery_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_line_delivery_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_c, hscale_pixel_rate_c, swath_width_pixels_ub_c, - 1); /* per line */ + 1); // per line - DTRACE( - "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f\n", __func__, refcyc_per_line_delivery_pre_c); - DTRACE( - "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_line_delivery_c = %3.2f\n", __func__, refcyc_per_line_delivery_c); - - disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( - refcyc_per_line_delivery_pre_c); - disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( - refcyc_per_line_delivery_c); - ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); } - disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; - /* TTU - Luma / Chroma */ - if (access_dir) { /* vertical access */ + // TTU - Luma / Chroma + if (access_dir) { // vertical access scaler_rec_in_width_l = vp_height_l; scaler_rec_in_width_c = vp_height_c; } else { @@ -1955,167 +1251,264 @@ void dml_rq_dlg_get_dlg_params( scaler_rec_in_width_c = vp_width_c; } - refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( - mode_lib, + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_l, hscale_pixel_rate_l, scaler_rec_in_width_l, - req_per_swath_ub_l); /* per req */ - refcyc_per_req_delivery_l = get_refcyc_per_delivery( - mode_lib, + req_per_swath_ub_l); // per req + refcyc_per_req_delivery_l = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_l, hscale_pixel_rate_l, scaler_rec_in_width_l, - req_per_swath_ub_l); /* per req */ + req_per_swath_ub_l); // per req - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f\n", __func__, refcyc_per_req_delivery_pre_l); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_l = %3.2f\n", __func__, refcyc_per_req_delivery_l); - disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l - * dml_pow(2, 10)); - disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l - * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); if (dual_plane) { - refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( - mode_lib, + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_pre_c, hscale_pixel_rate_c, scaler_rec_in_width_c, - req_per_swath_ub_c); /* per req */ - refcyc_per_req_delivery_c = get_refcyc_per_delivery( - mode_lib, + req_per_swath_ub_c); // per req + refcyc_per_req_delivery_c = get_refcyc_per_delivery(mode_lib, refclk_freq_in_mhz, pclk_freq_in_mhz, + dst->odm_combine, full_recout_width, + dst->hactive, vratio_c, hscale_pixel_rate_c, scaler_rec_in_width_c, - req_per_swath_ub_c); /* per req */ + req_per_swath_ub_c); // per req - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f\n", __func__, refcyc_per_req_delivery_pre_c); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + dml_print("DML_DLG: %s: refcyc_per_req_delivery_c = %3.2f\n", __func__, refcyc_per_req_delivery_c); - disp_ttu_regs->refcyc_per_req_delivery_pre_c = - (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); - disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c - * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); } - /* TTU - Cursor */ - hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; - cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ - cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; - cur0_req_size = 0; - cur0_req_width = 0; - cur0_width_ub = 0.0; - cur0_req_per_width = 0.0; - hactive_cur0 = 0.0; - - ASSERT(cur0_src_width <= 256); - - if (cur0_src_width > 0) { - unsigned int cur0_bit_per_pixel = 0; - - if (cur0_bpp == dm_cur_2bit) { - cur0_req_size = 64; /* byte */ - cur0_bit_per_pixel = 2; - } else { /* 32bit */ - cur0_bit_per_pixel = 32; - if (cur0_src_width >= 1 && cur0_src_width <= 16) - cur0_req_size = 64; - else if (cur0_src_width >= 17 && cur0_src_width <= 31) - cur0_req_size = 128; - else - cur0_req_size = 256; - } + // XFC + xfc_transfer_delay = get_xfc_transfer_delay(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); + xfc_precharge_delay = get_xfc_precharge_delay(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + xfc_remote_surface_flip_latency = get_xfc_remote_surface_flip_latency(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + xfc_dst_y_delta_drq_limit = xfc_remote_surface_flip_latency; + xfc_prefetch_margin = get_xfc_prefetch_margin(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx); + + // TTU - Cursor + refcyc_per_req_delivery_pre_cur0 = 0.0; + refcyc_per_req_delivery_cur0 = 0.0; + if (src->num_cursors > 0) { + calculate_ttu_cursor(mode_lib, + &refcyc_per_req_delivery_pre_cur0, + &refcyc_per_req_delivery_cur0, + refclk_freq_in_mhz, + ref_freq_to_pix_freq, + hscale_pixel_rate_l, + scl->hscl_ratio, + vratio_pre_l, + vratio_l, + src->cur0_src_width, + (enum cursor_bpp)(src->cur0_bpp)); + } + + refcyc_per_req_delivery_pre_cur1 = 0.0; + refcyc_per_req_delivery_cur1 = 0.0; + if (src->num_cursors > 1) { + calculate_ttu_cursor(mode_lib, + &refcyc_per_req_delivery_pre_cur1, + &refcyc_per_req_delivery_cur1, + refclk_freq_in_mhz, + ref_freq_to_pix_freq, + hscale_pixel_rate_l, + scl->hscl_ratio, + vratio_pre_l, + vratio_l, + src->cur1_src_width, + (enum cursor_bpp)(src->cur1_bpp)); + } - cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); - cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width) - * (double) cur0_req_width; - cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; - hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + // TTU - Misc + // all hard-coded - if (vratio_pre_l <= 1.0) { - refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq - / (double) cur0_req_per_width; - } else { - refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz - * (double) cur0_src_width / hscale_pixel_rate_l - / (double) cur0_req_per_width; - } + // Assignment to register structures + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; // in terms of line + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; // in terms of refclk + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_vm_flip = (unsigned int) (dst_y_per_vm_flip * dml_pow(2, 2)); + disp_dlg_regs->dst_y_per_row_flip = (unsigned int) (dst_y_per_row_flip * dml_pow(2, 2)); - disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = - (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); - if (vratio_l <= 1.0) { - refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq - / (double) cur0_req_per_width; - } else { - refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz - * (double) cur0_src_width / hscale_pixel_rate_l - / (double) cur0_req_per_width; + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_vblank_c = (unsigned int) (dst_y_per_row_vblank + * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c + < (unsigned int) dml_pow(2, 13)); + } + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l; // dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now + + disp_dlg_regs->refcyc_per_pte_group_flip_l = (unsigned int) (dst_y_per_row_flip * htotal + * ref_freq_to_pix_freq) / dpte_groups_per_row_ub_l; + disp_dlg_regs->refcyc_per_meta_chunk_flip_l = (unsigned int) (dst_y_per_row_flip * htotal + * ref_freq_to_pix_freq) / meta_chunks_per_row_ub_l; + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_flip_c = (unsigned int) (dst_y_per_row_flip + * htotal * ref_freq_to_pix_freq) / dpte_groups_per_row_ub_c; + disp_dlg_regs->refcyc_per_meta_chunk_flip_c = (unsigned int) (dst_y_per_row_flip + * htotal * ref_freq_to_pix_freq) / meta_chunks_per_row_ub_c; + } + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + if (dual_plane) { + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + if (disp_dlg_regs->dst_y_per_pte_row_nom_c >= (unsigned int) dml_pow(2, 17)) { + dml_print("DML_DLG: %s: Warning dst_y_per_pte_row_nom_c %u larger than supported by register format U15.2 %u\n", + __func__, + disp_dlg_regs->dst_y_per_pte_row_nom_c, + (unsigned int) dml_pow(2, 17) - 1); } + } - DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); - DTRACE( - "DLG: %s: cur0_width_ub = %3.2f", - __func__, - cur0_width_ub); - DTRACE( - "DLG: %s: cur0_req_per_width = %3.2f", - __func__, - cur0_req_per_width); - DTRACE( - "DLG: %s: hactive_cur0 = %3.2f", - __func__, - hactive_cur0); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", - __func__, - refcyc_per_req_delivery_pre_cur0); - DTRACE( - "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", - __func__, - refcyc_per_req_delivery_cur0); + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); - disp_ttu_regs->refcyc_per_req_delivery_cur0 = - (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); - ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); - } else { - disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; - disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; // TODO: dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (dual_plane) { + disp_dlg_regs->refcyc_per_pte_group_nom_c = + (unsigned int) ((double) dpte_row_height_c / (double) vratio_c + * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + // TODO: Is this the right calculation? Does htotal need to be halved? + disp_dlg_regs->refcyc_per_meta_chunk_nom_c = + (unsigned int) ((double) meta_row_height_c / (double) vratio_c + * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_c = dml_pow(2, 23) - 1; } - /* TTU - Misc */ + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor(refcyc_per_line_delivery_pre_l, + 1); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor(refcyc_per_line_delivery_l, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor(refcyc_per_line_delivery_pre_c, + 1); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor(refcyc_per_line_delivery_c, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + disp_dlg_regs->dst_y_offset_cur0 = 0; + disp_dlg_regs->chunk_hdl_adjust_cur1 = 3; + disp_dlg_regs->dst_y_offset_cur1 = 0; + + disp_dlg_regs->xfc_reg_transfer_delay = xfc_transfer_delay; + disp_dlg_regs->xfc_reg_precharge_delay = xfc_precharge_delay; + disp_dlg_regs->xfc_reg_remote_surface_flip_latency = xfc_remote_surface_flip_latency; + disp_dlg_regs->xfc_reg_prefetch_margin = dml_ceil(xfc_prefetch_margin * refclk_freq_in_mhz, + 1); + + // slave has to have this value also set to off + if (src->xfc_enable && !src->xfc_slave) + disp_dlg_regs->dst_y_delta_drq_limit = dml_ceil(xfc_dst_y_delta_drq_limit, 1); + else + disp_dlg_regs->dst_y_delta_drq_limit = 0x7fff; // off + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_c = (unsigned int) (refcyc_per_req_delivery_pre_c + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_cur0 = (unsigned int) (refcyc_per_req_delivery_cur0 + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_pre_cur1 = + (unsigned int) (refcyc_per_req_delivery_pre_cur1 * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_cur1 = (unsigned int) (refcyc_per_req_delivery_cur1 + * dml_pow(2, 10)); disp_ttu_regs->qos_level_low_wm = 0; ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal @@ -2137,118 +1530,232 @@ void dml_rq_dlg_get_dlg_params( print__dlg_regs_st(mode_lib, *disp_dlg_regs); } -void dml_rq_dlg_get_dlg_reg( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, - const int unsigned num_pipes, - const int unsigned pipe_idx, +void dml_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en) + const bool ignore_viewport_pos, + const bool immediate_flip_support) { - struct _vcs_dpi_display_rq_params_st rq_param = {0}; - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; - struct _vcs_dpi_wm_calc_pipe_params_st *wm_param = mode_lib->wm_param; - struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; - struct _vcs_dpi_display_dlg_prefetch_param_st prefetch_param; - double total_ret_bw; - double total_active_bw; - double total_prefetch_bw; - int unsigned total_flip_bytes; - int unsigned num_planes; - int i; - - memset(wm_param, 0, sizeof(mode_lib->wm_param)); - - /* Get watermark and Tex. */ - DTRACE("DLG: Start calculating system setting related parameters. num_pipes=%d", num_pipes); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e_pipe_param, num_pipes, wm_param); - - cstate_pstate_wm = dml_wm_cstate_pstate_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_mclk_wm_us = cstate_pstate_wm.pstate_change_us; - dlg_sys_param.t_sr_wm_us = cstate_pstate_wm.cstate_enter_plus_exit_us; - dlg_sys_param.t_urg_wm_us = dml_wm_urgent_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency - / dml_wm_dcfclk_deepsleep_mhz_e2e(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_extra_us = dml_wm_urgent_extra(mode_lib, wm_param, num_planes); - dlg_sys_param.deepsleep_dcfclk_mhz = dml_wm_dcfclk_deepsleep_mhz_e2e( - mode_lib, + display_rq_params_st rq_param = {0}; + display_dlg_sys_params_st dlg_sys_param = {0}; + + // Get watermark and Tex. + dlg_sys_param.t_urg_wm_us = get_wm_urgent(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.deepsleep_dcfclk_mhz = get_clk_dcf_deepsleep(mode_lib, + e2e_pipe_param, + num_pipes); + dlg_sys_param.t_extra_us = get_urgent_extra_latency(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.mem_trip_us = get_wm_memory_trip(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_mclk_wm_us = get_wm_dram_clock_change(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_sr_wm_us = get_wm_stutter_enter_exit(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.total_flip_bw = get_total_immediate_flip_bw(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.total_flip_bytes = get_total_immediate_flip_bytes(mode_lib, + e2e_pipe_param, + num_pipes); + dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency + / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated print__dlg_sys_params_st(mode_lib, dlg_sys_param); - DTRACE("DLG: Start calculating total prefetch bw. num_planes=%d", num_planes); - total_ret_bw = dml_wm_calc_return_bw(mode_lib, wm_param, num_planes); - total_active_bw = dml_wm_calc_total_data_read_bw(mode_lib, wm_param, num_planes); - total_prefetch_bw = 0.0; - total_flip_bytes = 0; + // system parameter calculation done - for (i = 0; i < num_pipes; i++) { - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[i].pipe.src); - dml_rq_dlg_get_dlg_params_prefetch( - mode_lib, - &prefetch_param, - rq_param.dlg, - dlg_sys_param, - e2e_pipe_param[i], - cstate_en, - pstate_en, - vm_en); - total_prefetch_bw += prefetch_param.prefetch_bw; - total_flip_bytes += prefetch_param.flip_bytes; - DTRACE( - "DLG: pipe=%d, total_prefetch_bw=%3.2f total_flip_bytes=%d", - i, - total_prefetch_bw, - total_flip_bytes); - } - - dlg_sys_param.total_flip_bw = total_ret_bw - dml_max(total_active_bw, total_prefetch_bw); - - DTRACE("DLG: Done calculating total prefetch bw"); - DTRACE("DLG: num_pipes = %d", num_pipes); - DTRACE("DLG: total_ret_bw = %3.2f", total_ret_bw); - DTRACE("DLG: total_active_bw = %3.2f", total_active_bw); - DTRACE("DLG: total_prefetch_bw = %3.2f", total_prefetch_bw); - DTRACE("DLG: total_flip_bw = %3.2f", dlg_sys_param.total_flip_bw); - - if (dlg_sys_param.total_flip_bw < 0.0 && iflip_en) { - DTRACE("WARNING_DLG Insufficient bw for immediate flip!"); - dlg_sys_param.total_flip_bw = 0; - } - - dlg_sys_param.total_flip_bytes = total_flip_bytes; - DTRACE("DLG: total_flip_bytes = %d", dlg_sys_param.total_flip_bytes); - DTRACE("DLG: Done calculating system setting related parameters."); - - /* system parameter calculation done */ - - DTRACE("DLG: Calculation for pipe[%d] start", pipe_idx); + dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe.src); - dml_rq_dlg_get_dlg_params( - mode_lib, + dml_rq_dlg_get_dlg_params(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_idx, dlg_regs, ttu_regs, rq_param.dlg, dlg_sys_param, - e2e_pipe_param[pipe_idx], cstate_en, pstate_en, vm_en, - iflip_en); - DTRACE("DLG: Calculation for pipe[%d] end", pipe_idx); + ignore_viewport_pos, + immediate_flip_support); + dml_print("DML_DLG: Calculation for pipe[%d] end\n", pipe_idx); } -void dml_rq_dlg_get_arb_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_arb_params_st *arb_param) +void dml_rq_dlg_get_arb_params(struct display_mode_lib *mode_lib, display_arb_params_st *arb_param) { memset(arb_param, 0, sizeof(*arb_param)); arb_param->max_req_outstanding = 256; arb_param->min_req_outstanding = 68; arb_param->sat_level_us = 60; } + +void calculate_ttu_cursor(struct display_mode_lib *mode_lib, + double *refcyc_per_req_delivery_pre_cur, + double *refcyc_per_req_delivery_cur, + double refclk_freq_in_mhz, + double ref_freq_to_pix_freq, + double hscale_pixel_rate_l, + double hscl_ratio, + double vratio_pre_l, + double vratio_l, + unsigned int cur_width, + enum cursor_bpp cur_bpp) +{ + unsigned int cur_src_width = cur_width; + unsigned int cur_req_size = 0; + unsigned int cur_req_width = 0; + double cur_width_ub = 0.0; + double cur_req_per_width = 0.0; + double hactive_cur = 0.0; + + ASSERT(cur_src_width <= 256); + + *refcyc_per_req_delivery_pre_cur = 0.0; + *refcyc_per_req_delivery_cur = 0.0; + if (cur_src_width > 0) { + unsigned int cur_bit_per_pixel = 0; + + if (cur_bpp == dm_cur_2bit) { + cur_req_size = 64; // byte + cur_bit_per_pixel = 2; + } else { // 32bit + cur_bit_per_pixel = 32; + if (cur_src_width >= 1 && cur_src_width <= 16) + cur_req_size = 64; + else if (cur_src_width >= 17 && cur_src_width <= 31) + cur_req_size = 128; + else + cur_req_size = 256; + } + + cur_req_width = (double) cur_req_size / ((double) cur_bit_per_pixel / 8.0); + cur_width_ub = dml_ceil((double) cur_src_width / (double) cur_req_width, 1) + * (double) cur_req_width; + cur_req_per_width = cur_width_ub / (double) cur_req_width; + hactive_cur = (double) cur_src_width / hscl_ratio; // FIXME: oswin to think about what to do for cursor + + if (vratio_pre_l <= 1.0) { + *refcyc_per_req_delivery_pre_cur = hactive_cur * ref_freq_to_pix_freq + / (double) cur_req_per_width; + } else { + *refcyc_per_req_delivery_pre_cur = (double) refclk_freq_in_mhz + * (double) cur_src_width / hscale_pixel_rate_l + / (double) cur_req_per_width; + } + + ASSERT(*refcyc_per_req_delivery_pre_cur < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + *refcyc_per_req_delivery_cur = hactive_cur * ref_freq_to_pix_freq + / (double) cur_req_per_width; + } else { + *refcyc_per_req_delivery_cur = (double) refclk_freq_in_mhz + * (double) cur_src_width / hscale_pixel_rate_l + / (double) cur_req_per_width; + } + + dml_print("DML_DLG: %s: cur_req_width = %d\n", + __func__, + cur_req_width); + dml_print("DML_DLG: %s: cur_width_ub = %3.2f\n", + __func__, + cur_width_ub); + dml_print("DML_DLG: %s: cur_req_per_width = %3.2f\n", + __func__, + cur_req_per_width); + dml_print("DML_DLG: %s: hactive_cur = %3.2f\n", + __func__, + hactive_cur); + dml_print("DML_DLG: %s: refcyc_per_req_delivery_pre_cur = %3.2f\n", + __func__, + *refcyc_per_req_delivery_pre_cur); + dml_print("DML_DLG: %s: refcyc_per_req_delivery_cur = %3.2f\n", + __func__, + *refcyc_per_req_delivery_cur); + + ASSERT(*refcyc_per_req_delivery_cur < dml_pow(2, 13)); + } +} + +unsigned int dml_rq_dlg_get_calculated_vstartup(struct display_mode_lib *mode_lib, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx) +{ + unsigned int vstartup_pipe[DC__NUM_PIPES__MAX]; + bool visited[DC__NUM_PIPES__MAX]; + unsigned int pipe_inst = 0; + unsigned int i, j, k; + + for (k = 0; k < num_pipes; ++k) + visited[k] = false; + + for (i = 0; i < num_pipes; i++) { + if (e2e_pipe_param[i].pipe.src.is_hsplit && !visited[i]) { + unsigned int grp = e2e_pipe_param[i].pipe.src.hsplit_grp; + + for (j = i; j < num_pipes; j++) { + if (e2e_pipe_param[j].pipe.src.hsplit_grp == grp + && e2e_pipe_param[j].pipe.src.is_hsplit + && !visited[j]) { + vstartup_pipe[j] = get_vstartup_calculated(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_inst); + visited[j] = true; + } + } + + pipe_inst++; + } + + if (!visited[i]) { + vstartup_pipe[i] = get_vstartup_calculated(mode_lib, + e2e_pipe_param, + num_pipes, + pipe_inst); + visited[i] = true; + pipe_inst++; + } + } + + return vstartup_pipe[pipe_idx]; + +} + +void dml_rq_dlg_get_row_heights(struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + display_data_rq_dlg_params_st rq_dlg_param; + display_data_rq_misc_params_st rq_misc_param; + display_data_rq_sizing_params_st rq_sizing_param; + + get_meta_and_pte_attr(mode_lib, + &rq_dlg_param, + &rq_misc_param, + &rq_sizing_param, + vp_width, + 0, // dummy + data_pitch, + 0, // dummy + source_format, + tiling, + macro_tile_size, + source_scan, + is_chroma); + + *o_dpte_row_height = rq_dlg_param.dpte_row_height; + *o_meta_row_height = rq_dlg_param.meta_row_height; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h index e63b13fb2887..efdd4c73d8f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h @@ -22,103 +22,114 @@ * Authors: AMD * */ -#ifndef __DISPLAY_RQ_DLG_CALC_H__ -#define __DISPLAY_RQ_DLG_CALC_H__ + +#ifndef __DML2_DISPLAY_RQ_DLG_CALC_H__ +#define __DML2_DISPLAY_RQ_DLG_CALC_H__ #include "dml_common_defs.h" #include "display_rq_dlg_helpers.h" struct display_mode_lib; -void extract_rq_regs( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_rq_params_st rq_param); -/* Function: dml_rq_dlg_get_rq_params - * Calculate requestor related parameters that register definition agnostic - * (i.e. this layer does try to separate real values from register defintion) - * Input: - * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) - * Output: - * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) - */ +// Function: dml_rq_dlg_get_rq_params +// Calculate requestor related parameters that register definition agnostic +// (i.e. this layer does try to separate real values from register definition) +// Input: +// pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) +// Output: +// rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) +// void dml_rq_dlg_get_rq_params( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + display_rq_params_st *rq_param, + const display_pipe_source_params_st pipe_src_param); -/* Function: dml_rq_dlg_get_rq_reg - * Main entry point for test to get the register values out of this DML class. - * This function calls and fucntions to calculate - * and then populate the rq_regs struct - * Input: - * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) - * Output: - * rq_regs - struct that holds all the RQ registers field value. - * See also: - */ +// Function: dml_rq_dlg_get_rq_reg +// Main entry point for test to get the register values out of this DML class. +// This function calls and fucntions to calculate +// and then populate the rq_regs struct +// Input: +// pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) +// Output: +// rq_regs - struct that holds all the RQ registers field value. +// See also: void dml_rq_dlg_get_rq_reg( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + display_rq_regs_st *rq_regs, + const display_pipe_source_params_st pipe_src_param); -/* Function: dml_rq_dlg_get_dlg_params - * Calculate deadline related parameters - */ -void dml_rq_dlg_get_dlg_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, +// Function: dml_rq_dlg_get_dlg_params +// Calculate deadline related parameters +// +void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + display_dlg_regs_st *disp_dlg_regs, + display_ttu_regs_st *disp_ttu_regs, + const display_rq_dlg_params_st rq_dlg_param, + const display_dlg_sys_params_st dlg_sys_param, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en); + const bool ignore_viewport_pos, + const bool immediate_flip_support); -/* Function: dml_rq_dlg_get_dlg_param_prefetch - * For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw - * for ALL pipes and use this info to calculate the prefetch programming. - * Output: prefetch_param.prefetch_bw and flip_bytes - */ +// Function: dml_rq_dlg_get_dlg_param_prefetch +// For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw +// for ALL pipes and use this info to calculate the prefetch programming. +// Output: prefetch_param.prefetch_bw and flip_bytes void dml_rq_dlg_get_dlg_params_prefetch( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + display_dlg_prefetch_param_st *prefetch_param, + display_rq_dlg_params_st rq_dlg_param, + display_dlg_sys_params_st dlg_sys_param, + display_e2e_pipe_params_st e2e_pipe_param, const bool cstate_en, const bool pstate_en, const bool vm_en); -/* Function: dml_rq_dlg_get_dlg_reg - * Calculate and return DLG and TTU register struct given the system setting - * Output: - * dlg_regs - output DLG register struct - * ttu_regs - output DLG TTU register struct - * Input: - * e2e_pipe_param - "compacted" array of e2e pipe param struct - * num_pipes - num of active "pipe" or "route" - * pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg - * cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. - * Added for legacy or unrealistic timing tests. - */ +// Function: dml_rq_dlg_get_dlg_reg +// Calculate and return DLG and TTU register struct given the system setting +// Output: +// dlg_regs - output DLG register struct +// ttu_regs - output DLG TTU register struct +// Input: +// e2e_pipe_param - "compacted" array of e2e pipe param struct +// num_pipes - num of active "pipe" or "route" +// pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg +// cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. +// Added for legacy or unrealistic timing tests. void dml_rq_dlg_get_dlg_reg( struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st *dlg_regs, - struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, + display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, const bool pstate_en, const bool vm_en, - const bool iflip_en); + const bool ignore_viewport_pos, + const bool immediate_flip_support); -/* Function: dml_rq_dlg_get_row_heights - * Calculate dpte and meta row heights - */ +// Function: dml_rq_dlg_get_calculated_vstartup +// Calculate and return vstartup +// Output: +// unsigned int vstartup +// Input: +// e2e_pipe_param - "compacted" array of e2e pipe param struct +// num_pipes - num of active "pipe" or "route" +// pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg +// NOTE: this MUST be called after setting the prefetch mode! +unsigned int dml_rq_dlg_get_calculated_vstartup( + struct display_mode_lib *mode_lib, + display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx); + +// Function: dml_rq_dlg_get_row_heights +// Calculate dpte and meta row heights void dml_rq_dlg_get_row_heights( struct display_mode_lib *mode_lib, unsigned int *o_dpte_row_height, @@ -131,9 +142,7 @@ void dml_rq_dlg_get_row_heights( int source_scan, int is_chroma); -/* Function: dml_rq_dlg_get_arb_params */ -void dml_rq_dlg_get_arb_params( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_arb_params_st *arb_param); +// Function: dml_rq_dlg_get_arb_params +void dml_rq_dlg_get_arb_params(struct display_mode_lib *mode_lib, display_arb_params_st *arb_param); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c index 3dc11366cd36..189052e911fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -25,296 +25,368 @@ #include "display_rq_dlg_helpers.h" -void print__rq_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st rq_param) +void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param) { - DTRACE("RQ_DLG_CALC: *************************** "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST"); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: ***************************\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_l); - DTRACE("RQ_DLG_CALC: === "); + dml_print("DML_RQ_DLG_CALC: ===\n"); print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_c); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_l); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_c); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_l); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_c); - DTRACE("RQ_DLG_CALC: *************************** "); + dml_print("DML_RQ_DLG_CALC: ***************************\n"); } -void print__data_rq_sizing_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st rq_sizing) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST"); - DTRACE("RQ_DLG_CALC: chunk_bytes = %0d", rq_sizing.chunk_bytes); - DTRACE("RQ_DLG_CALC: min_chunk_bytes = %0d", rq_sizing.min_chunk_bytes); - DTRACE("RQ_DLG_CALC: meta_chunk_bytes = %0d", rq_sizing.meta_chunk_bytes); - DTRACE("RQ_DLG_CALC: min_meta_chunk_bytes = %0d", rq_sizing.min_meta_chunk_bytes); - DTRACE("RQ_DLG_CALC: mpte_group_bytes = %0d", rq_sizing.mpte_group_bytes); - DTRACE("RQ_DLG_CALC: dpte_group_bytes = %0d", rq_sizing.dpte_group_bytes); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: chunk_bytes = %0d\n", rq_sizing.chunk_bytes); + dml_print("DML_RQ_DLG_CALC: min_chunk_bytes = %0d\n", rq_sizing.min_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: meta_chunk_bytes = %0d\n", rq_sizing.meta_chunk_bytes); + dml_print( + "DML_RQ_DLG_CALC: min_meta_chunk_bytes = %0d\n", + rq_sizing.min_meta_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: mpte_group_bytes = %0d\n", rq_sizing.mpte_group_bytes); + dml_print("DML_RQ_DLG_CALC: dpte_group_bytes = %0d\n", rq_sizing.dpte_group_bytes); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param) +void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, display_data_rq_dlg_params_st rq_dlg_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: swath_width_ub = %0d", rq_dlg_param.swath_width_ub); - DTRACE("RQ_DLG_CALC: swath_height = %0d", rq_dlg_param.swath_height); - DTRACE("RQ_DLG_CALC: req_per_swath_ub = %0d", rq_dlg_param.req_per_swath_ub); - DTRACE( - "RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: swath_width_ub = %0d\n", + rq_dlg_param.swath_width_ub); + dml_print( + "DML_RQ_DLG_CALC: swath_height = %0d\n", + rq_dlg_param.swath_height); + dml_print( + "DML_RQ_DLG_CALC: req_per_swath_ub = %0d\n", + rq_dlg_param.req_per_swath_ub); + dml_print( + "DML_RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d\n", rq_dlg_param.meta_pte_bytes_per_frame_ub); - DTRACE( - "RQ_DLG_CALC: dpte_req_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_req_per_row_ub = %0d\n", rq_dlg_param.dpte_req_per_row_ub); - DTRACE( - "RQ_DLG_CALC: dpte_groups_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_groups_per_row_ub = %0d\n", rq_dlg_param.dpte_groups_per_row_ub); - DTRACE("RQ_DLG_CALC: dpte_row_height = %0d", rq_dlg_param.dpte_row_height); - DTRACE( - "RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: dpte_row_height = %0d\n", + rq_dlg_param.dpte_row_height); + dml_print( + "DML_RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d\n", rq_dlg_param.dpte_bytes_per_row_ub); - DTRACE( - "RQ_DLG_CALC: meta_chunks_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_chunks_per_row_ub = %0d\n", rq_dlg_param.meta_chunks_per_row_ub); - DTRACE( - "RQ_DLG_CALC: meta_req_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_req_per_row_ub = %0d\n", rq_dlg_param.meta_req_per_row_ub); - DTRACE("RQ_DLG_CALC: meta_row_height = %0d", rq_dlg_param.meta_row_height); - DTRACE( - "RQ_DLG_CALC: meta_bytes_per_row_ub = %0d", + dml_print( + "DML_RQ_DLG_CALC: meta_row_height = %0d\n", + rq_dlg_param.meta_row_height); + dml_print( + "DML_RQ_DLG_CALC: meta_bytes_per_row_ub = %0d\n", rq_dlg_param.meta_bytes_per_row_ub); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_misc_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param) +void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, display_data_rq_misc_params_st rq_misc_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST"); - DTRACE("RQ_DLG_CALC: full_swath_bytes = %0d", rq_misc_param.full_swath_bytes); - DTRACE("RQ_DLG_CALC: stored_swath_bytes = %0d", rq_misc_param.stored_swath_bytes); - DTRACE("RQ_DLG_CALC: blk256_width = %0d", rq_misc_param.blk256_width); - DTRACE("RQ_DLG_CALC: blk256_height = %0d", rq_misc_param.blk256_height); - DTRACE("RQ_DLG_CALC: req_width = %0d", rq_misc_param.req_width); - DTRACE("RQ_DLG_CALC: req_height = %0d", rq_misc_param.req_height); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: full_swath_bytes = %0d\n", + rq_misc_param.full_swath_bytes); + dml_print( + "DML_RQ_DLG_CALC: stored_swath_bytes = %0d\n", + rq_misc_param.stored_swath_bytes); + dml_print("DML_RQ_DLG_CALC: blk256_width = %0d\n", rq_misc_param.blk256_width); + dml_print("DML_RQ_DLG_CALC: blk256_height = %0d\n", rq_misc_param.blk256_height); + dml_print("DML_RQ_DLG_CALC: req_width = %0d\n", rq_misc_param.req_width); + dml_print("DML_RQ_DLG_CALC: req_height = %0d\n", rq_misc_param.req_height); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param) +void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, display_rq_dlg_params_st rq_dlg_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_l); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_c); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__dlg_sys_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param) +void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, display_dlg_sys_params_st dlg_sys_param) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); - DTRACE("RQ_DLG_CALC: t_mclk_wm_us = %3.2f", dlg_sys_param.t_mclk_wm_us); - DTRACE("RQ_DLG_CALC: t_urg_wm_us = %3.2f", dlg_sys_param.t_urg_wm_us); - DTRACE("RQ_DLG_CALC: t_sr_wm_us = %3.2f", dlg_sys_param.t_sr_wm_us); - DTRACE("RQ_DLG_CALC: t_extra_us = %3.2f", dlg_sys_param.t_extra_us); - DTRACE("RQ_DLG_CALC: t_srx_delay_us = %3.2f", dlg_sys_param.t_srx_delay_us); - DTRACE("RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f", dlg_sys_param.deepsleep_dcfclk_mhz); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); + dml_print("DML_RQ_DLG_CALC: t_mclk_wm_us = %3.2f\n", dlg_sys_param.t_mclk_wm_us); + dml_print("DML_RQ_DLG_CALC: t_urg_wm_us = %3.2f\n", dlg_sys_param.t_urg_wm_us); + dml_print("DML_RQ_DLG_CALC: t_sr_wm_us = %3.2f\n", dlg_sys_param.t_sr_wm_us); + dml_print("DML_RQ_DLG_CALC: t_extra_us = %3.2f\n", dlg_sys_param.t_extra_us); + dml_print( + "DML_RQ_DLG_CALC: t_srx_delay_us = %3.2f\n", + dlg_sys_param.t_srx_delay_us); + dml_print( + "DML_RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f\n", + dlg_sys_param.deepsleep_dcfclk_mhz); + dml_print( + "DML_RQ_DLG_CALC: total_flip_bw = %3.2f\n", + dlg_sys_param.total_flip_bw); + dml_print( + "DML_RQ_DLG_CALC: total_flip_bytes = %i\n", + dlg_sys_param.total_flip_bytes); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st rq_regs) +void print__data_rq_regs_st(struct display_mode_lib *mode_lib, display_data_rq_regs_st rq_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST"); - DTRACE("RQ_DLG_CALC: chunk_size = 0x%0x", rq_regs.chunk_size); - DTRACE("RQ_DLG_CALC: min_chunk_size = 0x%0x", rq_regs.min_chunk_size); - DTRACE("RQ_DLG_CALC: meta_chunk_size = 0x%0x", rq_regs.meta_chunk_size); - DTRACE("RQ_DLG_CALC: min_meta_chunk_size = 0x%0x", rq_regs.min_meta_chunk_size); - DTRACE("RQ_DLG_CALC: dpte_group_size = 0x%0x", rq_regs.dpte_group_size); - DTRACE("RQ_DLG_CALC: mpte_group_size = 0x%0x", rq_regs.mpte_group_size); - DTRACE("RQ_DLG_CALC: swath_height = 0x%0x", rq_regs.swath_height); - DTRACE("RQ_DLG_CALC: pte_row_height_linear = 0x%0x", rq_regs.pte_row_height_linear); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST\n"); + dml_print("DML_RQ_DLG_CALC: chunk_size = 0x%0x\n", rq_regs.chunk_size); + dml_print("DML_RQ_DLG_CALC: min_chunk_size = 0x%0x\n", rq_regs.min_chunk_size); + dml_print("DML_RQ_DLG_CALC: meta_chunk_size = 0x%0x\n", rq_regs.meta_chunk_size); + dml_print( + "DML_RQ_DLG_CALC: min_meta_chunk_size = 0x%0x\n", + rq_regs.min_meta_chunk_size); + dml_print("DML_RQ_DLG_CALC: dpte_group_size = 0x%0x\n", rq_regs.dpte_group_size); + dml_print("DML_RQ_DLG_CALC: mpte_group_size = 0x%0x\n", rq_regs.mpte_group_size); + dml_print("DML_RQ_DLG_CALC: swath_height = 0x%0x\n", rq_regs.swath_height); + dml_print( + "DML_RQ_DLG_CALC: pte_row_height_linear = 0x%0x\n", + rq_regs.pte_row_height_linear); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st rq_regs) +void print__rq_regs_st(struct display_mode_lib *mode_lib, display_rq_regs_st rq_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_RQ_REGS_ST"); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_REGS_ST\n"); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_l); - DTRACE("RQ_DLG_CALC: "); + dml_print("DML_RQ_DLG_CALC: \n"); print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_c); - DTRACE("RQ_DLG_CALC: drq_expansion_mode = 0x%0x", rq_regs.drq_expansion_mode); - DTRACE("RQ_DLG_CALC: prq_expansion_mode = 0x%0x", rq_regs.prq_expansion_mode); - DTRACE("RQ_DLG_CALC: mrq_expansion_mode = 0x%0x", rq_regs.mrq_expansion_mode); - DTRACE("RQ_DLG_CALC: crq_expansion_mode = 0x%0x", rq_regs.crq_expansion_mode); - DTRACE("RQ_DLG_CALC: plane1_base_address = 0x%0x", rq_regs.plane1_base_address); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print("DML_RQ_DLG_CALC: drq_expansion_mode = 0x%0x\n", rq_regs.drq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: prq_expansion_mode = 0x%0x\n", rq_regs.prq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: mrq_expansion_mode = 0x%0x\n", rq_regs.mrq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: crq_expansion_mode = 0x%0x\n", rq_regs.crq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: plane1_base_address = 0x%0x\n", rq_regs.plane1_base_address); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__dlg_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st dlg_regs) +void print__dlg_regs_st(struct display_mode_lib *mode_lib, display_dlg_regs_st dlg_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_DLG_REGS_ST "); - DTRACE( - "RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_DLG_REGS_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x\n", dlg_regs.refcyc_h_blank_end); - DTRACE("RQ_DLG_CALC: dlg_vblank_end = 0x%0x", dlg_regs.dlg_vblank_end); - DTRACE( - "RQ_DLG_CALC: min_dst_y_next_start = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dlg_vblank_end = 0x%0x\n", + dlg_regs.dlg_vblank_end); + dml_print( + "DML_RQ_DLG_CALC: min_dst_y_next_start = 0x%0x\n", dlg_regs.min_dst_y_next_start); - DTRACE( - "RQ_DLG_CALC: refcyc_per_htotal = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_htotal = 0x%0x\n", dlg_regs.refcyc_per_htotal); - DTRACE( - "RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x\n", dlg_regs.refcyc_x_after_scaler); - DTRACE( - "RQ_DLG_CALC: dst_y_after_scaler = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_after_scaler = 0x%0x\n", dlg_regs.dst_y_after_scaler); - DTRACE("RQ_DLG_CALC: dst_y_prefetch = 0x%0x", dlg_regs.dst_y_prefetch); - DTRACE( - "RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_prefetch = 0x%0x\n", + dlg_regs.dst_y_prefetch); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x\n", dlg_regs.dst_y_per_vm_vblank); - DTRACE( - "RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x\n", dlg_regs.dst_y_per_row_vblank); - DTRACE( - "RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_vm_flip = 0x%0x\n", + dlg_regs.dst_y_per_vm_flip); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_row_flip = 0x%0x\n", + dlg_regs.dst_y_per_row_flip); + dml_print( + "DML_RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x\n", dlg_regs.ref_freq_to_pix_freq); - DTRACE("RQ_DLG_CALC: vratio_prefetch = 0x%0x", dlg_regs.vratio_prefetch); - DTRACE( - "RQ_DLG_CALC: vratio_prefetch_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: vratio_prefetch = 0x%0x\n", + dlg_regs.vratio_prefetch); + dml_print( + "DML_RQ_DLG_CALC: vratio_prefetch_c = 0x%0x\n", dlg_regs.vratio_prefetch_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x\n", dlg_regs.refcyc_per_pte_group_vblank_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x\n", dlg_regs.refcyc_per_pte_group_vblank_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_vblank_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_vblank_c); - DTRACE( - "RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_flip_l = 0x%0x\n", + dlg_regs.refcyc_per_pte_group_flip_l); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_flip_c = 0x%0x\n", + dlg_regs.refcyc_per_pte_group_flip_c); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_flip_l = 0x%0x\n", + dlg_regs.refcyc_per_meta_chunk_flip_l); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_flip_c = 0x%0x\n", + dlg_regs.refcyc_per_meta_chunk_flip_c); + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x\n", dlg_regs.dst_y_per_pte_row_nom_l); - DTRACE( - "RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x\n", dlg_regs.dst_y_per_pte_row_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x\n", dlg_regs.refcyc_per_pte_group_nom_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x\n", dlg_regs.refcyc_per_pte_group_nom_c); - DTRACE( - "RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x\n", dlg_regs.dst_y_per_meta_row_nom_l); - DTRACE( - "RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x\n", dlg_regs.dst_y_per_meta_row_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_nom_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x\n", dlg_regs.refcyc_per_meta_chunk_nom_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_pre_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_pre_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x\n", dlg_regs.refcyc_per_line_delivery_c); - DTRACE( - "RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x\n", dlg_regs.chunk_hdl_adjust_cur0); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print( + "DML_RQ_DLG_CALC: dst_y_offset_cur1 = 0x%0x\n", + dlg_regs.dst_y_offset_cur1); + dml_print( + "DML_RQ_DLG_CALC: chunk_hdl_adjust_cur1 = 0x%0x\n", + dlg_regs.chunk_hdl_adjust_cur1); + dml_print( + "DML_RQ_DLG_CALC: vready_after_vcount0 = 0x%0x\n", + dlg_regs.vready_after_vcount0); + dml_print( + "DML_RQ_DLG_CALC: dst_y_delta_drq_limit = 0x%0x\n", + dlg_regs.dst_y_delta_drq_limit); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_transfer_delay = 0x%0x\n", + dlg_regs.xfc_reg_transfer_delay); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_precharge_delay = 0x%0x\n", + dlg_regs.xfc_reg_precharge_delay); + dml_print( + "DML_RQ_DLG_CALC: xfc_reg_remote_surface_flip_latency = 0x%0x\n", + dlg_regs.xfc_reg_remote_surface_flip_latency); + + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__ttu_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_ttu_regs_st ttu_regs) +void print__ttu_regs_st(struct display_mode_lib *mode_lib, display_ttu_regs_st ttu_regs) { - DTRACE("RQ_DLG_CALC: ===================================== "); - DTRACE("RQ_DLG_CALC: DISPLAY_TTU_REGS_ST "); - DTRACE( - "RQ_DLG_CALC: qos_level_low_wm = 0x%0x", + dml_print("DML_RQ_DLG_CALC: =====================================\n"); + dml_print("DML_RQ_DLG_CALC: DISPLAY_TTU_REGS_ST\n"); + dml_print( + "DML_RQ_DLG_CALC: qos_level_low_wm = 0x%0x\n", ttu_regs.qos_level_low_wm); - DTRACE( - "RQ_DLG_CALC: qos_level_high_wm = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_high_wm = 0x%0x\n", ttu_regs.qos_level_high_wm); - DTRACE("RQ_DLG_CALC: min_ttu_vblank = 0x%0x", ttu_regs.min_ttu_vblank); - DTRACE("RQ_DLG_CALC: qos_level_flip = 0x%0x", ttu_regs.qos_level_flip); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: min_ttu_vblank = 0x%0x\n", + ttu_regs.min_ttu_vblank); + dml_print( + "DML_RQ_DLG_CALC: qos_level_flip = 0x%0x\n", + ttu_regs.qos_level_flip); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_l); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_c); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_cur0); - DTRACE( - "RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x\n", ttu_regs.refcyc_per_req_delivery_pre_cur0); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_cur1 = 0x%0x\n", + ttu_regs.refcyc_per_req_delivery_cur1); + dml_print( + "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur1 = 0x%0x\n", + ttu_regs.refcyc_per_req_delivery_pre_cur1); + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_l = 0x%0x\n", ttu_regs.qos_level_fixed_l); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x\n", ttu_regs.qos_ramp_disable_l); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_c = 0x%0x\n", ttu_regs.qos_level_fixed_c); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x\n", ttu_regs.qos_ramp_disable_c); - DTRACE( - "RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x\n", ttu_regs.qos_level_fixed_cur0); - DTRACE( - "RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x", + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x\n", ttu_regs.qos_ramp_disable_cur0); - DTRACE("RQ_DLG_CALC: ===================================== "); + dml_print( + "DML_RQ_DLG_CALC: qos_level_fixed_cur1 = 0x%0x\n", + ttu_regs.qos_level_fixed_cur1); + dml_print( + "DML_RQ_DLG_CALC: qos_ramp_disable_cur1 = 0x%0x\n", + ttu_regs.qos_ramp_disable_cur1); + dml_print("DML_RQ_DLG_CALC: =====================================\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h index 7403ccaf637b..1f24db830737 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h @@ -22,6 +22,7 @@ * Authors: AMD * */ + #ifndef __DISPLAY_RQ_DLG_HELPERS_H__ #define __DISPLAY_RQ_DLG_HELPERS_H__ @@ -31,36 +32,16 @@ /* Function: Printer functions * Print various struct */ -void print__rq_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_params_st rq_param); -void print__data_rq_sizing_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing); -void print__data_rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param); -void print__data_rq_misc_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param); -void print__rq_dlg_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param); -void print__dlg_sys_params_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param); +void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param); +void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st rq_sizing); +void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, display_data_rq_dlg_params_st rq_dlg_param); +void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, display_data_rq_misc_params_st rq_misc_param); +void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, display_rq_dlg_params_st rq_dlg_param); +void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, display_dlg_sys_params_st dlg_sys_param); -void print__data_rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_data_rq_regs_st data_rq_regs); -void print__rq_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_rq_regs_st rq_regs); -void print__dlg_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_dlg_regs_st dlg_regs); -void print__ttu_regs_st( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_ttu_regs_st ttu_regs); +void print__data_rq_regs_st(struct display_mode_lib *mode_lib, display_data_rq_regs_st data_rq_regs); +void print__rq_regs_st(struct display_mode_lib *mode_lib, display_rq_regs_st rq_regs); +void print__dlg_regs_st(struct display_mode_lib *mode_lib, display_dlg_regs_st dlg_regs); +void print__ttu_regs_st(struct display_mode_lib *mode_lib, display_ttu_regs_st ttu_regs); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c deleted file mode 100644 index 390f09391433..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c +++ /dev/null @@ -1,1281 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#include "display_watermark.h" -#include "display_mode_lib.h" - -static void get_bytes_per_pixel( - enum source_format_class format, - struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - switch (format) { - case dm_444_64: - plane->bytes_per_pixel_y = 8.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_444_32: - plane->bytes_per_pixel_y = 4.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_444_16: - plane->bytes_per_pixel_y = 2.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_422_10: - plane->bytes_per_pixel_y = 4.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_422_8: - plane->bytes_per_pixel_y = 2.0; - plane->bytes_per_pixel_c = 0.0; - break; - case dm_420_8: - plane->bytes_per_pixel_y = 1.0; - plane->bytes_per_pixel_c = 2.0; - break; - case dm_420_10: - plane->bytes_per_pixel_y = 4.0 / 3; - plane->bytes_per_pixel_c = 8.0 / 3; - break; - default: - BREAK_TO_DEBUGGER(); /* invalid format in get_bytes_per_pixel */ - } -} - -static unsigned int get_swath_width_y( - struct _vcs_dpi_display_pipe_source_params_st *src_param, - unsigned int num_dpp) -{ - unsigned int val; - - /* note that we don't divide by num_dpp here because we have an interface which has already split - * any viewports - */ - if (src_param->source_scan == dm_horz) { - val = src_param->viewport_width; - } else { - val = src_param->viewport_height; - } - - return val; -} - -static void get_swath_height( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_pipe_source_params_st *src_param, - struct _vcs_dpi_wm_calc_pipe_params_st *plane, - unsigned int swath_width_y) -{ - double buffer_width; - - if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 - || src_param->source_format == dm_444_16) { - if (src_param->sw_mode == dm_sw_linear) { - plane->swath_height_y = 1; - } else if (src_param->source_format == dm_444_64) { - plane->swath_height_y = 4; - } else { - plane->swath_height_y = 8; - } - - if (src_param->source_scan != dm_horz) { - plane->swath_height_y = 256 / (unsigned int) plane->bytes_per_pixel_y - / plane->swath_height_y; - } - - plane->swath_height_c = 0; - - } else { - if (src_param->sw_mode == dm_sw_linear) { - plane->swath_height_y = 1; - plane->swath_height_c = 1; - } else if (src_param->source_format == dm_420_8) { - plane->swath_height_y = 16; - plane->swath_height_c = 8; - } else { - plane->swath_height_y = 8; - plane->swath_height_c = 8; - } - - if (src_param->source_scan != dm_horz) { - double bytes_per_pixel_c_ceil; - - plane->swath_height_y = 256 / dml_ceil(plane->bytes_per_pixel_y) - / plane->swath_height_y; - - bytes_per_pixel_c_ceil = dml_ceil_2(plane->bytes_per_pixel_c); - - plane->swath_height_c = 256 / bytes_per_pixel_c_ceil - / plane->swath_height_c; - } - } - - /* use swath height min if buffer isn't big enough */ - - buffer_width = ((double) mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0) - / (plane->bytes_per_pixel_y * (double) plane->swath_height_y - + (plane->bytes_per_pixel_c / 2.0 - * (double) plane->swath_height_c)); - - if ((double) swath_width_y <= buffer_width) { - /* do nothing, just keep code structure from Gabes vba */ - } else { - /* substitute swath height with swath height min */ - if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 - || src_param->source_format == dm_444_16) { - if ((src_param->sw_mode == dm_sw_linear) - || (src_param->source_format == dm_444_64 - && (src_param->sw_mode == dm_sw_4kb_s - || src_param->sw_mode - == dm_sw_4kb_s_x - || src_param->sw_mode - == dm_sw_64kb_s - || src_param->sw_mode - == dm_sw_64kb_s_t - || src_param->sw_mode - == dm_sw_64kb_s_x - || src_param->sw_mode - == dm_sw_var_s - || src_param->sw_mode - == dm_sw_var_s_x) - && src_param->source_scan == dm_horz)) { - /* do nothing, just keep code structure from Gabes vba */ - } else { - plane->swath_height_y = plane->swath_height_y / 2; - } - } else { - if (src_param->sw_mode == dm_sw_linear) { - /* do nothing, just keep code structure from Gabes vba */ - } else if (src_param->source_format == dm_420_8 - && src_param->source_scan == dm_horz) { - plane->swath_height_y = plane->swath_height_y / 2; - } else if (src_param->source_format == dm_420_10 - && src_param->source_scan == dm_horz) { - plane->swath_height_c = plane->swath_height_c / 2; - } - } - } - - if (plane->swath_height_c == 0) { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0; - } else if (plane->swath_height_c <= plane->swath_height_y) { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0; - } else { - plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 * 2.0 / 3.0; - } -} - -static void calc_display_pipe_line_delivery_time( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].v_ratio <= 1.0) { - planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y - * planes[i].num_dpp / planes[i].h_ratio - / planes[i].pixclk_mhz; - } else { - double dchub_pscl_bw_per_clk; - - if (planes[i].h_ratio > 1) { - double num_hscl_kernels; - - num_hscl_kernels = dml_ceil((double) planes[i].h_taps / 6); - dchub_pscl_bw_per_clk = - dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - mode_lib->ip.max_pscl_lb_bw_pix_per_clk - * planes[i].h_ratio - / num_hscl_kernels); - } else { - dchub_pscl_bw_per_clk = - dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); - } - - planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y - / dchub_pscl_bw_per_clk / planes[i].dppclk_mhz; - } - } -} - -static double calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 0.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - double swath_width_y_plane = planes[i].swath_width_y * planes[i].num_dpp; - - planes[i].read_bw = swath_width_y_plane - * (dml_ceil(planes[i].bytes_per_pixel_y) - + dml_ceil_2(planes[i].bytes_per_pixel_c) / 2) - / (planes[i].h_total / planes[i].pixclk_mhz) * planes[i].v_ratio; - - val += planes[i].read_bw; - - DTRACE("plane[%d] start", i); - DTRACE("read_bw = %f", planes[i].read_bw); - DTRACE("plane[%d] end", i); - } - - return val; -} - -double dml_wm_calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - return calc_total_data_read_bw(mode_lib, planes, num_planes); -} - -static double calc_dcfclk_mhz( - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double dcfclk_mhz = -1.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == planes[i].dcfclk_mhz); - dcfclk_mhz = planes[i].dcfclk_mhz; - } - - return dcfclk_mhz; -} - -static enum voltage_state find_voltage( - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - int voltage = -1; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - ASSERT(voltage == -1 || voltage == planes[i].voltage); - voltage = planes[i].voltage; - } - - return (enum voltage_state) voltage; -} - -static bool find_dcc_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - return true; - } - } - - return false; -} - -static double calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - struct _vcs_dpi_soc_bounding_box_st *soc; - double return_bw_mbps; - double dcfclk_mhz; - double return_bus_bw; - enum voltage_state voltage; - double return_bw_to_dcn; - bool dcc_enable; - double rob_chunk_diff; - double urgent_latency_traffic; - double critical_compression; - struct _vcs_dpi_voltage_scaling_st state; - - soc = &mode_lib->soc; - - dcfclk_mhz = calc_dcfclk_mhz(planes, num_planes); - return_bus_bw = dcfclk_mhz * soc->return_bus_width_bytes; - - DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); - DTRACE("INTERMEDIATE return_bus_bw = %f", return_bus_bw); - - voltage = find_voltage(planes, num_planes); - return_bw_to_dcn = dml_socbb_return_bw_mhz(soc, voltage); - - dcc_enable = find_dcc_enable(planes, num_planes); - - return_bw_mbps = return_bw_to_dcn; - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - - rob_chunk_diff = - (mode_lib->ip.rob_buffer_size_kbytes - mode_lib->ip.pixel_chunk_size_kbytes) - * 1024.0; - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - - if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { - double dcc_return_bw = - return_bw_to_dcn * 4.0 - * (1.0 - - soc->urgent_latency_us - / (rob_chunk_diff - / (return_bw_to_dcn - - return_bus_bw - / 4.0) - + soc->urgent_latency_us)); - return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); - DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); - } - - urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - critical_compression = 2.0 * urgent_latency_traffic - / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); - DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); - - if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { - double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff - * urgent_latency_traffic); - crit_return_bw = crit_return_bw - / dml_pow( - return_bw_to_dcn * soc->urgent_latency_us - + rob_chunk_diff, - 2); - DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); - return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); - } - - /* Gabe does this again for some reason using the value of return_bw_mpbs from the previous calculation - * and a lightly different return_bw_to_dcn - */ - - state = dml_socbb_voltage_scaling(soc, voltage); - return_bw_to_dcn = dml_min( - soc->return_bus_width_bytes * dcfclk_mhz, - state.dram_bw_per_chan_gbps * 1000.0 * (double) soc->num_chans); - - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - - if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { - double dcc_return_bw = - return_bw_to_dcn * 4.0 - * (1.0 - - soc->urgent_latency_us - / (rob_chunk_diff - / (return_bw_to_dcn - - return_bus_bw - / 4.0) - + soc->urgent_latency_us)); - return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); - DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); - } - - urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - critical_compression = 2.0 * urgent_latency_traffic - / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); - DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); - - /* problem here? */ - if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { - double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff - * urgent_latency_traffic); - crit_return_bw = crit_return_bw - / dml_pow( - return_bw_to_dcn * soc->urgent_latency_us - + rob_chunk_diff, - 2); - DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); - DTRACE("INTERMEDIATE return_bw_to_dcn = %f", return_bw_to_dcn); - DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); - DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); - - return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); - } - - DTRACE("INTERMEDIATE final return_bw_mbps = %f", return_bw_mbps); - return return_bw_mbps; -} - -double dml_wm_calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - return calc_return_bw(mode_lib, planes, num_planes); -} - -static double calc_last_pixel_of_line_extra_wm_us( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 0.0; - double total_data_read_bw = calc_total_data_read_bw(mode_lib, planes, num_planes); - int voltage = -1; - unsigned int i; - double return_bw_mbps; - - for (i = 0; i < num_planes; i++) { - /* voltage mode must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == planes[i].voltage); - voltage = planes[i].voltage; - } - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - for (i = 0; i < num_planes; i++) { - double bytes_pp_y = dml_ceil(planes[i].bytes_per_pixel_y); - double bytes_pp_c = dml_ceil_2(planes[i].bytes_per_pixel_c); - double swath_bytes_y = (double) planes[i].swath_width_y - * (double) planes[i].swath_height_y * (double) bytes_pp_y; - double swath_bytes_c = ((double) planes[i].swath_width_y / 2.0) - * (double) planes[i].swath_height_c * (double) bytes_pp_c; - double data_fabric_line_delivery_time = (swath_bytes_y + swath_bytes_c) - / (return_bw_mbps * planes[i].read_bw / (double) planes[i].num_dpp - / total_data_read_bw); - - DTRACE( - "bytes_pp_y = %f, swath_width_y = %f, swath_height_y = %f, swath_bytes_y = %f", - bytes_pp_y, - (double) planes[i].swath_width_y, - (double) planes[i].swath_height_y, - swath_bytes_y); - DTRACE( - "bytes_pp_c = %f, swath_width_c = %f, swath_height_c = %f, swath_bytes_c = %f", - bytes_pp_c, - ((double) planes[i].swath_width_y / 2.0), - (double) planes[i].swath_height_c, - swath_bytes_c); - DTRACE( - "return_bw_mbps = %f, read_bw = %f, num_dpp = %d, total_data_read_bw = %f", - return_bw_mbps, - planes[i].read_bw, - planes[i].num_dpp, - total_data_read_bw); - DTRACE("data_fabric_line_delivery_time = %f", data_fabric_line_delivery_time); - DTRACE( - "display_pipe_line_delivery_time = %f", - planes[i].display_pipe_line_delivery_time); - - val = dml_max( - val, - data_fabric_line_delivery_time - - planes[i].display_pipe_line_delivery_time); - } - - DTRACE("last_pixel_of_line_extra_wm is %f us", val); - return val; -} - -static bool calc_pte_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) -{ - unsigned int i; - - for (i = 0; i < num_planes; i++) { - if (planes[i].pte_enable) { - return true; - } - } - - return false; -} - -static void calc_lines_in_det_y(struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - plane->lines_in_det_y = plane->det_buffer_size_y / plane->bytes_per_pixel_y - / plane->swath_width_y; - plane->lines_in_det_y_rounded_down_to_swath = dml_floor( - (double) plane->lines_in_det_y / plane->swath_height_y) - * plane->swath_height_y; - plane->full_det_buffering_time = plane->lines_in_det_y_rounded_down_to_swath - * (plane->h_total / plane->pixclk_mhz); -} - -/* CHECKME: not obviously 1:1 with calculation described in architectural - * document or spreadsheet */ -static void calc_dcfclk_deepsleep_mhz_per_plane( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *plane) -{ - double bus_width_per_pixel; - - if (plane->swath_height_c == 0) { - bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 64; - } else { - double bus_width_per_pixel_c; - - bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 32; - bus_width_per_pixel_c = dml_ceil(plane->bytes_per_pixel_c) / 32; - if (bus_width_per_pixel < bus_width_per_pixel_c) - bus_width_per_pixel = bus_width_per_pixel_c; - } - - if (plane->v_ratio <= 1) { - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->pixclk_mhz / plane->num_dpp - * plane->h_ratio * bus_width_per_pixel; - } else if (plane->h_ratio > 1) { - double num_hscl_kernels = dml_ceil((double) plane->h_taps / 6); - double dchub_pscl_bw_per_clk = dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - mode_lib->ip.max_pscl_lb_bw_pix_per_clk * plane->h_ratio - / num_hscl_kernels); - - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz - * dchub_pscl_bw_per_clk * bus_width_per_pixel; - } else { - double dchub_pscl_bw_per_clk = dml_min( - (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, - (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); - - plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz - * dchub_pscl_bw_per_clk * bus_width_per_pixel; - } - - plane->dcfclk_deepsleep_mhz_per_plane = dml_max( - plane->dcfclk_deepsleep_mhz_per_plane, - plane->pixclk_mhz / 16); -} - -/* Implementation of expected stutter efficiency from DCN1_Display_Mode.docx */ -double dml_wm_expected_stutter_eff_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - double min_full_det_buffering_time_us; - double frame_time_for_min_full_det_buffering_time_us = 0.0; - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - unsigned int i; - double total_data_read_bw_mbps; - double average_read_bw_gbps; - double min_full_det_buffer_size_bytes; - double rob_fill_size_bytes; - double part_of_burst_that_fits_in_rob; - int voltage; - double dcfclk_mhz; - unsigned int total_writeback; - double return_bw_mbps; - double stutter_burst_time_us; - double stutter_eff_not_including_vblank; - double smallest_vblank_us; - double stutter_eff; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - DTRACE("calculating expected stutter efficiency"); - - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); - - for (i = 0; i < num_planes; i++) { - calc_lines_in_det_y(&planes[i]); - - DTRACE("swath width y plane %d = %d", i, planes[i].swath_width_y); - DTRACE("swath height y plane %d = %d", i, planes[i].swath_height_y); - DTRACE( - "bytes per pixel det y plane %d = %f", - i, - planes[i].bytes_per_pixel_y); - DTRACE( - "bytes per pixel det c plane %d = %f", - i, - planes[i].bytes_per_pixel_c); - DTRACE( - "det buffer size plane %d = %d", - i, - planes[i].det_buffer_size_y); - DTRACE("lines in det plane %d = %d", i, planes[i].lines_in_det_y); - DTRACE( - "lines in det rounded to swaths plane %d = %d", - i, - planes[i].lines_in_det_y_rounded_down_to_swath); - } - - min_full_det_buffering_time_us = 9999.0; - for (i = 0; i < num_planes; i++) { - if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { - min_full_det_buffering_time_us = planes[i].full_det_buffering_time; - frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total - * planes[i].h_total / planes[i].pixclk_mhz; - } - } - - DTRACE("INTERMEDIATE: min_full_det_buffering_time_us = %f", min_full_det_buffering_time_us); - - total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); - - average_read_bw_gbps = 0.0; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; - } else { - average_read_bw_gbps += planes[i].read_bw / 1000; - } - - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 256; - } - - if (planes[i].pte_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 512; - } - } - - min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; - rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps - / (average_read_bw_gbps * 1000); - part_of_burst_that_fits_in_rob = dml_min( - min_full_det_buffer_size_bytes, - rob_fill_size_bytes); - - voltage = -1; - dcfclk_mhz = -1.0; - total_writeback = 0; - - for (i = 0; i < num_pipes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); - voltage = e2e[i].clks_cfg.voltage; - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); - dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - - if (e2e[i].dout.output_type == dm_wb) - total_writeback++; - } - - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - DTRACE("INTERMEDIATE: part_of_burst_that_fits_in_rob = %f", part_of_burst_that_fits_in_rob); - DTRACE("INTERMEDIATE: average_read_bw_gbps = %f", average_read_bw_gbps); - DTRACE("INTERMEDIATE: total_data_read_bw_mbps = %f", total_data_read_bw_mbps); - DTRACE("INTERMEDIATE: return_bw_mbps = %f", return_bw_mbps); - - stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) - / total_data_read_bw_mbps / return_bw_mbps - + (min_full_det_buffering_time_us * total_data_read_bw_mbps - - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); - DTRACE("INTERMEDIATE: stutter_burst_time_us = %f", stutter_burst_time_us); - - if (total_writeback == 0) { - stutter_eff_not_including_vblank = (1.0 - - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) - / min_full_det_buffering_time_us)) * 100.0; - } else { - stutter_eff_not_including_vblank = 0.0; - } - - DTRACE("stutter_efficiency_not_including_vblank = %f", stutter_eff_not_including_vblank); - - smallest_vblank_us = 9999.0; - - for (i = 0; i < num_pipes; i++) { - double vblank_us; - if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { - vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 - - e2e[i].pipe.dest.vblank_start - + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) - / e2e[i].pipe.dest.pixel_rate_mhz; - } else { - vblank_us = 0.0; - } - - smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); - } - - DTRACE("smallest vblank = %f us", smallest_vblank_us); - - stutter_eff = 100.0 - * (((stutter_eff_not_including_vblank / 100.0) - * (frame_time_for_min_full_det_buffering_time_us - - smallest_vblank_us) + smallest_vblank_us) - / frame_time_for_min_full_det_buffering_time_us); - - DTRACE("stutter_efficiency = %f", stutter_eff); - - return stutter_eff_not_including_vblank; -} - -double dml_wm_expected_stutter_eff_e2e_with_vblank( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - double min_full_det_buffering_time_us; - double frame_time_for_min_full_det_buffering_time_us = 0.0; - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - unsigned int i; - double total_data_read_bw_mbps; - double average_read_bw_gbps; - double min_full_det_buffer_size_bytes; - double rob_fill_size_bytes; - double part_of_burst_that_fits_in_rob; - int voltage; - double dcfclk_mhz; - unsigned int total_writeback; - double return_bw_mbps; - double stutter_burst_time_us; - double stutter_eff_not_including_vblank; - double smallest_vblank_us; - double stutter_eff; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); - - for (i = 0; i < num_planes; i++) { - calc_lines_in_det_y(&planes[i]); - } - - min_full_det_buffering_time_us = 9999.0; - for (i = 0; i < num_planes; i++) { - if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { - min_full_det_buffering_time_us = planes[i].full_det_buffering_time; - frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total - * planes[i].h_total / planes[i].pixclk_mhz; - } - } - - total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); - average_read_bw_gbps = 0.0; - - for (i = 0; i < num_planes; i++) { - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; - } else { - average_read_bw_gbps += planes[i].read_bw / 1000; - } - - if (planes[i].dcc_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 256; - } - - if (planes[i].pte_enable) { - average_read_bw_gbps += planes[i].read_bw / 1000 / 512; - } - } - - min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; - rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps - / (average_read_bw_gbps * 1000); - part_of_burst_that_fits_in_rob = dml_min( - min_full_det_buffer_size_bytes, - rob_fill_size_bytes); - - voltage = -1; - dcfclk_mhz = -1.0; - total_writeback = 0; - - for (i = 0; i < num_pipes; i++) { - /* voltage and dcfclk must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); - voltage = e2e[i].clks_cfg.voltage; - ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); - dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - - if (e2e[i].dout.output_type == dm_wb) - total_writeback++; - } - - return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); - - stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) - / total_data_read_bw_mbps / return_bw_mbps - + (min_full_det_buffering_time_us * total_data_read_bw_mbps - - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); - - if (total_writeback == 0) { - stutter_eff_not_including_vblank = (1.0 - - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) - / min_full_det_buffering_time_us)) * 100.0; - } else { - stutter_eff_not_including_vblank = 0.0; - } - - smallest_vblank_us = 9999.0; - - for (i = 0; i < num_pipes; i++) { - double vblank_us; - if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { - vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 - - e2e[i].pipe.dest.vblank_start - + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) - / e2e[i].pipe.dest.pixel_rate_mhz; - } else { - vblank_us = 0.0; - } - - smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); - } - - stutter_eff = 100.0 - * (((stutter_eff_not_including_vblank / 100.0) - * (frame_time_for_min_full_det_buffering_time_us - - smallest_vblank_us) + smallest_vblank_us) - / frame_time_for_min_full_det_buffering_time_us); - - - return stutter_eff; -} - -double urgent_extra_calc( - struct display_mode_lib *mode_lib, - double dcfclk_mhz, - double return_bw_mbps, - unsigned int total_active_dpp, - unsigned int total_dcc_active_dpp) -{ - double urgent_extra_latency_us = 0.0; - double urgent_round_trip_ooo_latency_us; - - urgent_round_trip_ooo_latency_us = - (((double) mode_lib->soc.round_trip_ping_latency_dcfclk_cycles + 32) - / dcfclk_mhz) - + (((double) (mode_lib->soc.urgent_out_of_order_return_per_channel_bytes - * mode_lib->soc.num_chans)) / return_bw_mbps); - - DTRACE( - "INTERMEDIATE round_trip_ping_latency_dcfclk_cycles = %d", - mode_lib->soc.round_trip_ping_latency_dcfclk_cycles); - DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); - DTRACE( - "INTERMEDIATE urgent_out_of_order_return_per_channel_bytes = %d", - mode_lib->soc.urgent_out_of_order_return_per_channel_bytes); - - urgent_extra_latency_us = urgent_round_trip_ooo_latency_us - + ((double) total_active_dpp * mode_lib->ip.pixel_chunk_size_kbytes - + (double) total_dcc_active_dpp - * mode_lib->ip.meta_chunk_size_kbytes) - * 1024.0 / return_bw_mbps; /* to us */ - - DTRACE( - "INTERMEDIATE urgent_round_trip_ooo_latency_us = %f", - urgent_round_trip_ooo_latency_us); - DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); - DTRACE( - "INTERMEDIATE pixel_chunk_size_kbytes = %d", - mode_lib->ip.pixel_chunk_size_kbytes); - DTRACE("INTERMEDIATE total_dcc_active_dpp = %d", total_dcc_active_dpp); - DTRACE( - "INTERMEDIATE meta_chunk_size_kbyte = %d", - mode_lib->ip.meta_chunk_size_kbytes); - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - - return urgent_extra_latency_us; -} - -double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib) -{ - unsigned int total_active_dpp = DC__NUM_DPP; - unsigned int total_dcc_active_dpp = total_active_dpp; - double urgent_extra_latency_us = 0.0; - double dcfclk_mhz = 0.0; - double return_bw_mbps = 0.0; - int voltage = dm_vmin; - - /* use minimum voltage */ - return_bw_mbps = dml_socbb_return_bw_mhz(&mode_lib->soc, (enum voltage_state) voltage); - /* use minimum dcfclk */ - dcfclk_mhz = mode_lib->soc.vmin.dcfclk_mhz; - /* use max dpps and dpps with dcc */ - - urgent_extra_latency_us = urgent_extra_calc( - mode_lib, - dcfclk_mhz, - return_bw_mbps, - total_active_dpp, - total_dcc_active_dpp); - - DTRACE("urgent extra max = %f", urgent_extra_latency_us); - return urgent_extra_latency_us; -} - -double dml_wm_urgent_extra( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - unsigned int total_active_dpp = 0; - unsigned int total_dcc_active_dpp = 0; - double urgent_extra_latency_us = 0.0; - double dcfclk_mhz = 0.0; - double return_bw_mbps = 0.0; - int voltage = -1; - bool pte_enable = false; - unsigned int i; - - for (i = 0; i < num_pipes; i++) { - /* num_dpp must be greater than 0 */ - ASSERT(pipes[i].num_dpp > 0); - - /* voltage mode must be the same for all pipes */ - ASSERT(voltage == -1 || voltage == pipes[i].voltage); - voltage = pipes[i].voltage; - - /* dcfclk for all pipes must be the same */ - ASSERT(dcfclk_mhz == 0.0 || dcfclk_mhz == pipes[i].dcfclk_mhz); - dcfclk_mhz = pipes[i].dcfclk_mhz; - - total_active_dpp += pipes[i].num_dpp; - - if (pipes[i].dcc_enable) { - total_dcc_active_dpp += pipes[i].num_dpp; - } - } - - DTRACE("total active dpps %d", total_active_dpp); - DTRACE("total active dpps with dcc %d", total_dcc_active_dpp); - DTRACE("voltage state is %d", voltage); - - return_bw_mbps = calc_return_bw(mode_lib, pipes, num_pipes); - - DTRACE("return_bandwidth is %f MBps", return_bw_mbps); - - pte_enable = calc_pte_enable(pipes, num_pipes); - - /* calculate the maximum extra latency just for comparison purposes */ - /* dml_wm_urgent_extra_max(); */ - urgent_extra_latency_us = urgent_extra_calc( - mode_lib, - dcfclk_mhz, - return_bw_mbps, - total_active_dpp, - total_dcc_active_dpp); - - DTRACE("INTERMEDIATE urgent_extra_latency_us_before_pte = %f", urgent_extra_latency_us); - - if (pte_enable) { - urgent_extra_latency_us += total_active_dpp * mode_lib->ip.pte_chunk_size_kbytes - * 1024.0 / return_bw_mbps; - - DTRACE("INTERMEDIATE pte_enable = true"); - DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); - DTRACE( - "INTERMEDIATE pte_chunk_size_kbytes = %d", - mode_lib->ip.pte_chunk_size_kbytes); - DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); - } - - return urgent_extra_latency_us; -} - -double dml_wm_urgent_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - double urgent_wm; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - - urgent_wm = dml_wm_urgent(mode_lib, wm, combined_pipes); - - return urgent_wm; -} - -double dml_wm_urgent( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double urgent_watermark; - double urgent_extra_latency_us; - double last_pixel_of_line_extra_wm_us = 0.0; - - DTRACE("calculating urgent watermark"); - calc_display_pipe_line_delivery_time(mode_lib, planes, num_planes); - urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, planes, num_planes); - - last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( - mode_lib, - planes, - num_planes); - - urgent_watermark = mode_lib->soc.urgent_latency_us + last_pixel_of_line_extra_wm_us - + urgent_extra_latency_us; - - DTRACE("INTERMEDIATE urgent_latency_us = %f", mode_lib->soc.urgent_latency_us); - DTRACE("INTERMEDIATE last_pixel_of_line_extra_wm_us = %f", last_pixel_of_line_extra_wm_us); - DTRACE("INTERMEDIATE urgent_extra_latency_us = %f", urgent_extra_latency_us); - - DTRACE("urgent_watermark_us = %f", urgent_watermark); - return urgent_watermark; -} - -double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us) -{ - double val; - - val = urgent_wm_us + 2.0 * mode_lib->soc.urgent_latency_us; - DTRACE("pte_meta_urgent_watermark_us = %f", val); - - return val; -} - -double dml_wm_dcfclk_deepsleep_mhz_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; - unsigned int num_planes; - double val; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - num_planes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, planes); - - val = dml_wm_dcfclk_deepsleep_mhz(mode_lib, planes, num_planes); - - return val; -} - -double dml_wm_dcfclk_deepsleep_mhz( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes) -{ - double val = 8.0; - unsigned int i; - - for (i = 0; i < num_planes; i++) { - calc_dcfclk_deepsleep_mhz_per_plane(mode_lib, &planes[i]); - - if (val < planes[i].dcfclk_deepsleep_mhz_per_plane) { - val = planes[i].dcfclk_deepsleep_mhz_per_plane; - } - - DTRACE("plane[%d] start", i); - DTRACE("dcfclk_deepsleep_per_plane = %f", planes[i].dcfclk_deepsleep_mhz_per_plane); - DTRACE("plane[%d] end", i); - } - - DTRACE("dcfclk_deepsleep_mhz = %f", val); - - return val; -} - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - cstate_pstate_wm = dml_wm_cstate_pstate(mode_lib, wm, combined_pipes); - - - return cstate_pstate_wm; -} - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_cstate_pstate_watermarks_st wm; - double urgent_extra_latency_us; - double urgent_watermark_us; - double last_pixel_of_line_extra_wm_us; - double dcfclk_deepsleep_freq; - - DTRACE("calculating cstate and pstate watermarks"); - urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, pipes, num_pipes); - urgent_watermark_us = dml_wm_urgent(mode_lib, pipes, num_pipes); - - last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( - mode_lib, - pipes, - num_pipes); - dcfclk_deepsleep_freq = dml_wm_dcfclk_deepsleep_mhz(mode_lib, pipes, num_pipes); - - wm.cstate_exit_us = mode_lib->soc.sr_exit_time_us + last_pixel_of_line_extra_wm_us - + urgent_extra_latency_us - + mode_lib->ip.dcfclk_cstate_latency / dcfclk_deepsleep_freq; - wm.cstate_enter_plus_exit_us = mode_lib->soc.sr_enter_plus_exit_time_us - + last_pixel_of_line_extra_wm_us + urgent_extra_latency_us; - wm.pstate_change_us = mode_lib->soc.dram_clock_change_latency_us + urgent_watermark_us; - - DTRACE("stutter_exit_watermark_us = %f", wm.cstate_exit_us); - DTRACE("stutter_enter_plus_exit_watermark_us = %f", wm.cstate_enter_plus_exit_us); - DTRACE("dram_clock_change_watermark_us = %f", wm.pstate_change_us); - - return wm; -} - -double dml_wm_writeback_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) -{ - struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; - unsigned int combined_pipes; - - memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); - combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); - - - return dml_wm_writeback_pstate(mode_lib, wm, combined_pipes); -} - -double dml_wm_writeback_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes) -{ - unsigned int total_active_wb = 0; - double wm = 0.0; - double socclk_mhz = 0.0; - unsigned int i; - - DTRACE("calculating wb pstate watermark"); - for (i = 0; i < num_pipes; i++) { - if (pipes[i].output_type == dm_wb) - total_active_wb++; - ASSERT(socclk_mhz == 0.0 || socclk_mhz == pipes[i].socclk_mhz); - socclk_mhz = pipes[i].socclk_mhz; - } - - DTRACE("total wb outputs %d", total_active_wb); - DTRACE("socclk frequency %f Mhz", socclk_mhz); - - if (total_active_wb <= 1) { - wm = mode_lib->soc.writeback_dram_clock_change_latency_us; - } else { - wm = mode_lib->soc.writeback_dram_clock_change_latency_us - + (mode_lib->ip.writeback_chunk_size_kbytes * 1024.0) / 32.0 - / socclk_mhz; - } - - DTRACE("wb pstate watermark %f us", wm); - return wm; -} - -unsigned int dml_wm_e2e_to_wm( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - struct _vcs_dpi_wm_calc_pipe_params_st *wm) -{ - unsigned int num_planes = 0; - bool visited[DC__NUM_PIPES]; - unsigned int i, j; - - for (i = 0; i < num_pipes; i++) { - visited[i] = false; - } - - for (i = 0; i < num_pipes; i++) { - unsigned int num_dpp = 1; - - if (visited[i]) { - continue; - } - - visited[i] = true; - - if (e2e[i].pipe.src.is_hsplit) { - for (j = i + 1; j < num_pipes; j++) { - if (e2e[j].pipe.src.is_hsplit && !visited[j] - && (e2e[i].pipe.src.hsplit_grp - == e2e[j].pipe.src.hsplit_grp)) { - num_dpp++; - visited[j] = true; - } - } - } - - wm[num_planes].num_dpp = num_dpp; - wm[num_planes].voltage = e2e[i].clks_cfg.voltage; - wm[num_planes].output_type = e2e[i].dout.output_type; - wm[num_planes].dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; - wm[num_planes].socclk_mhz = e2e[i].clks_cfg.socclk_mhz; - wm[num_planes].dppclk_mhz = e2e[i].clks_cfg.dppclk_mhz; - wm[num_planes].pixclk_mhz = e2e[i].pipe.dest.pixel_rate_mhz; - - wm[num_planes].pte_enable = e2e[i].pipe.src.vm; - wm[num_planes].dcc_enable = e2e[i].pipe.src.dcc; - wm[num_planes].dcc_rate = e2e[i].pipe.src.dcc_rate; - - get_bytes_per_pixel( - (enum source_format_class) e2e[i].pipe.src.source_format, - &wm[num_planes]); - wm[num_planes].swath_width_y = get_swath_width_y(&e2e[i].pipe.src, num_dpp); - get_swath_height( - mode_lib, - &e2e[i].pipe.src, - &wm[num_planes], - wm[num_planes].swath_width_y); - - wm[num_planes].interlace_en = e2e[i].pipe.dest.interlaced; - wm[num_planes].h_ratio = e2e[i].pipe.scale_ratio_depth.hscl_ratio; - wm[num_planes].v_ratio = e2e[i].pipe.scale_ratio_depth.vscl_ratio; - if (wm[num_planes].interlace_en) { - wm[num_planes].v_ratio = 2 * wm[num_planes].v_ratio; - } - wm[num_planes].h_taps = e2e[i].pipe.scale_taps.htaps; - wm[num_planes].h_total = e2e[i].pipe.dest.htotal; - wm[num_planes].v_total = e2e[i].pipe.dest.vtotal; - wm[num_planes].v_active = e2e[i].pipe.dest.vactive; - wm[num_planes].e2e_index = i; - num_planes++; - } - - for (i = 0; i < num_planes; i++) { - DTRACE("plane[%d] start", i); - DTRACE("voltage = %d", wm[i].voltage); - DTRACE("v_active = %d", wm[i].v_active); - DTRACE("h_total = %d", wm[i].h_total); - DTRACE("v_total = %d", wm[i].v_total); - DTRACE("pixclk_mhz = %f", wm[i].pixclk_mhz); - DTRACE("dcfclk_mhz = %f", wm[i].dcfclk_mhz); - DTRACE("dppclk_mhz = %f", wm[i].dppclk_mhz); - DTRACE("h_ratio = %f", wm[i].h_ratio); - DTRACE("v_ratio = %f", wm[i].v_ratio); - DTRACE("interlaced = %d", wm[i].interlace_en); - DTRACE("h_taps = %d", wm[i].h_taps); - DTRACE("num_dpp = %d", wm[i].num_dpp); - DTRACE("swath_width_y = %d", wm[i].swath_width_y); - DTRACE("swath_height_y = %d", wm[i].swath_height_y); - DTRACE("swath_height_c = %d", wm[i].swath_height_c); - DTRACE("det_buffer_size_y = %d", wm[i].det_buffer_size_y); - DTRACE("dcc_rate = %f", wm[i].dcc_rate); - DTRACE("dcc_enable = %s", wm[i].dcc_enable ? "true" : "false"); - DTRACE("pte_enable = %s", wm[i].pte_enable ? "true" : "false"); - DTRACE("plane[%d] end", i); - } - - return num_planes; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h deleted file mode 100644 index 94cde8b55e08..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DISPLAY_WATERMARK_H__ -#define __DISPLAY_WATERMARK_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -double dml_wm_urgent_extra( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib); - -double dml_wm_urgent_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_urgent( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); -double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us); -double dml_wm_dcfclk_deepsleep_mhz_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_dcfclk_deepsleep_mhz( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); - -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); - -double dml_wm_writeback_pstate_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); -double dml_wm_writeback_pstate( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *pipes, - unsigned int num_pipes); - -double dml_wm_expected_stutter_eff_e2e( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); -double dml_wm_expected_stutter_eff_e2e_with_vblank( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); - -unsigned int dml_wm_e2e_to_wm( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_display_e2e_pipe_params_st *e2e, - unsigned int num_pipes, - struct _vcs_dpi_wm_calc_pipe_params_st *wm); - -double dml_wm_calc_total_data_read_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); -double dml_wm_calc_return_bw( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_wm_calc_pipe_params_st *planes, - unsigned int num_planes); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c new file mode 100644 index 000000000000..8229f782260b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -0,0 +1,1903 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dml1_display_rq_dlg_calc.h" +#include "display_mode_lib.h" + +static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) +{ + unsigned int ret_val = 0; + + if (source_format == dm_444_16) { + if (!is_chroma) + ret_val = 2; + } else if (source_format == dm_444_32) { + if (!is_chroma) + ret_val = 4; + } else if (source_format == dm_444_64) { + if (!is_chroma) + ret_val = 8; + } else if (source_format == dm_420_8) { + if (is_chroma) + ret_val = 2; + else + ret_val = 1; + } else if (source_format == dm_420_10) { + if (is_chroma) + ret_val = 4; + else + ret_val = 2; + } + return ret_val; +} + +static bool is_dual_plane(enum source_format_class source_format) +{ + bool ret_val = 0; + + if ((source_format == dm_420_8) || (source_format == dm_420_10)) + ret_val = 1; + + return ret_val; +} + +static void get_blk256_size( + unsigned int *blk256_width, + unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + if (bytes_per_element == 1) { + *blk256_width = 16; + *blk256_height = 16; + } else if (bytes_per_element == 2) { + *blk256_width = 16; + *blk256_height = 8; + } else if (bytes_per_element == 4) { + *blk256_width = 8; + *blk256_height = 8; + } else if (bytes_per_element == 8) { + *blk256_width = 8; + *blk256_height = 4; + } +} + +static double get_refcyc_per_delivery( + struct display_mode_lib *mode_lib, + double refclk_freq_in_mhz, + double pclk_freq_in_mhz, + unsigned int recout_width, + double vratio, + double hscale_pixel_rate, + unsigned int delivery_width, + unsigned int req_per_swath_ub) +{ + double refcyc_per_delivery = 0.0; + + if (vratio <= 1.0) { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; + } else { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width + / (double) hscale_pixel_rate / (double) req_per_swath_ub; + } + + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); + DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); + DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); + DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + + return refcyc_per_delivery; + +} + +static double get_vratio_pre( + struct display_mode_lib *mode_lib, + unsigned int max_num_sw, + unsigned int max_partial_sw, + unsigned int swath_height, + double vinit, + double l_sw) +{ + double prefill = dml_floor(vinit, 1); + double vratio_pre = 1.0; + + vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; + + if (swath_height > 4) { + double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); + + if (tmp0 > vratio_pre) + vratio_pre = tmp0; + } + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); + + if (vratio_pre < 1.0) { + DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); + vratio_pre = 1.0; + } + + if (vratio_pre > 4.0) { + DTRACE( + "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", + __func__, + vratio_pre); + vratio_pre = 4.0; + } + + return vratio_pre; +} + +static void get_swath_need( + struct display_mode_lib *mode_lib, + unsigned int *max_num_sw, + unsigned int *max_partial_sw, + unsigned int swath_height, + double vinit) +{ + double prefill = dml_floor(vinit, 1); + unsigned int max_partial_sw_int; + + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + + ASSERT(prefill > 0.0 && prefill <= 8.0); + + *max_num_sw = (unsigned int) (dml_ceil((prefill - 1.0) / (double) swath_height, 1) + 1.0); /* prefill has to be >= 1 */ + max_partial_sw_int = + (prefill == 1) ? + (swath_height - 1) : + ((unsigned int) (prefill - 2.0) % swath_height); + *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); +} + +static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) +{ + if (tile_size == dm_256k_tile) + return (256 * 1024); + else if (tile_size == dm_64k_tile) + return (64 * 1024); + else + return (4 * 1024); +} + +static void extract_rq_sizing_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("DLG: %s: rq_sizing param", __func__); + print__data_rq_sizing_params_st(mode_lib, rq_sizing); + + rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + + if (rq_sizing.min_chunk_bytes == 0) + rq_regs->min_chunk_size = 0; + else + rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + + rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; + if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->min_meta_chunk_size = 0; + else + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + + rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; +} + +void dml1_extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param) +{ + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + unsigned int detile_buf_plane1_addr = 0; + + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + if (rq_param.yuv420) + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + + /* FIXME: take the max between luma, chroma chunk size? + * okay for now, as we are setting chunk_bytes to 8kb anyways + */ + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + rq_regs->drq_expansion_mode = 0; + } else { + rq_regs->drq_expansion_mode = 2; + } + rq_regs->prq_expansion_mode = 1; + rq_regs->mrq_expansion_mode = 1; + rq_regs->crq_expansion_mode = 1; + + if (rq_param.yuv420) { + if ((double) rq_param.misc.rq_l.stored_swath_bytes + / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + } else { + detile_buf_plane1_addr = dml_round_to_multiple( + (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + 256, + 0) / 64.0; /* 2/3 to chroma */ + } + } + rq_regs->plane1_base_address = detile_buf_plane1_addr; +} + +static void handle_det_buf_split( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + unsigned int total_swath_bytes = 0; + unsigned int swath_bytes_l = 0; + unsigned int swath_bytes_c = 0; + unsigned int full_swath_bytes_packed_l = 0; + unsigned int full_swath_bytes_packed_c = 0; + bool req128_l = 0; + bool req128_c = 0; + bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param.source_scan == dm_vert); + unsigned int log2_swath_height_l = 0; + unsigned int log2_swath_height_c = 0; + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + + full_swath_bytes_packed_l = rq_param->misc.rq_l.full_swath_bytes; + full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; + + if (rq_param->yuv420_10bpc) { + full_swath_bytes_packed_l = dml_round_to_multiple( + rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + full_swath_bytes_packed_c = dml_round_to_multiple( + rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + } + + if (rq_param->yuv420) { + total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; + + if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + req128_l = 0; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l; + swath_bytes_c = full_swath_bytes_packed_c; + } else { /*128b request (for luma only for yuv420 8bpc) */ + req128_l = 1; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l / 2; + swath_bytes_c = full_swath_bytes_packed_c; + } + + /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) + * TODO: Remove after rtl fix + */ + if (req128_l == 1) { + req128_c = 1; + DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); + } + + /* Note: assumption, the config that pass in will fit into + * the detiled buffer. + */ + } else { + total_swath_bytes = 2 * full_swath_bytes_packed_l; + + if (total_swath_bytes <= detile_buf_size_in_bytes) + req128_l = 0; + else + req128_l = 1; + + swath_bytes_l = total_swath_bytes; + swath_bytes_c = 0; + } + rq_param->misc.rq_l.stored_swath_bytes = swath_bytes_l; + rq_param->misc.rq_c.stored_swath_bytes = swath_bytes_c; + + if (surf_linear) { + log2_swath_height_l = 0; + log2_swath_height_c = 0; + } else if (!surf_vert) { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; + } else { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; + rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; + + DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); + DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); + DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); + DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); +} + +/* Need refactor. */ +static void dml1_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + bool surf_linear = (tiling == dm_sw_linear); + bool surf_vert = (source_scan == dm_vert); + + unsigned int bytes_per_element = get_bytes_per_element( + (enum source_format_class) source_format, + is_chroma); + unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int blk256_width = 0; + unsigned int blk256_height = 0; + + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int log2_meta_row_height; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int dpte_req_width; + + if (surf_linear) { + blk256_width = 256; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (tiling != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + log2_meta_row_height = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) + log2_meta_row_height = log2_meta_req_height; + else + log2_meta_row_height = log2_meta_req_width; + + *o_meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + dpte_req_width = 0; /* 64b dpte req width in data element */ + + if (surf_linear) + log2_vmpg_height = 0; /* one line high */ + else + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch), + 1); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + } else { + /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ + if (!surf_vert) + log2_dpte_row_height = log2_dpte_req_height; + else + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + } + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + + *o_dpte_row_height = 1 << log2_dpte_row_height; +} + +static void get_surf_rq_param( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, + struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, + struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + bool surf_linear; + bool surf_vert; + unsigned int bytes_per_element; + unsigned int log2_bytes_per_element; + unsigned int blk256_width; + unsigned int blk256_height; + unsigned int log2_blk256_width; + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int meta_req_width; + unsigned int meta_req_height; + unsigned int log2_meta_row_height; + unsigned int meta_row_width_ub; + unsigned int log2_meta_chunk_bytes; + unsigned int log2_meta_chunk_height; + unsigned int log2_meta_chunk_width; + unsigned int log2_min_meta_chunk_bytes; + unsigned int min_meta_chunk_width; + unsigned int meta_chunk_width; + unsigned int meta_chunk_per_row_int; + unsigned int meta_row_remainder; + unsigned int meta_chunk_threshold; + unsigned int meta_blk_bytes; + unsigned int meta_blk_height; + unsigned int meta_blk_width; + unsigned int meta_surface_bytes; + unsigned int vmpg_bytes; + unsigned int meta_pte_req_per_frame_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int log2_dpte_group_width; + unsigned int dpte_row_width_ub; + unsigned int dpte_row_height; + unsigned int dpte_req_height; + unsigned int dpte_req_width; + unsigned int dpte_group_width; + unsigned int log2_dpte_group_bytes; + unsigned int log2_dpte_group_length; + unsigned int func_meta_row_height, func_dpte_row_height; + + /* FIXME check if ppe apply for both luma and chroma in 422 case */ + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + + rq_sizing_param->mpte_group_bytes = 2048; + + surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + surf_vert = (pipe_src_param.source_scan == dm_vert); + + bytes_per_element = get_bytes_per_element( + (enum source_format_class) pipe_src_param.source_format, + is_chroma); + log2_bytes_per_element = dml_log2(bytes_per_element); + blk256_width = 0; + blk256_height = 0; + + if (surf_linear) { + blk256_width = 256 / bytes_per_element; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); + DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); + DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); + DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + + log2_blk256_width = dml_log2((double) blk256_width); + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = + surf_linear ? 256 : get_blk_size_bytes( + (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (pipe_src_param.sw_mode != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + if (!surf_vert) { + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_width - 1, blk256_width, 1) + + blk256_width; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; + } else { + rq_dlg_param->swath_width_ub = dml_round_to_multiple( + vp_height - 1, + blk256_height, + 1) + blk256_height; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; + } + + if (!surf_vert) + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_height + * bytes_per_element; + else + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_width + * bytes_per_element; + + rq_misc_param->blk256_height = blk256_height; + rq_misc_param->blk256_width = blk256_width; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + meta_req_width = 1 << log2_meta_req_width; + meta_req_height = 1 << log2_meta_req_height; + log2_meta_row_height = 0; + meta_row_width_ub = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) { + log2_meta_row_height = log2_meta_req_height; + meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) + + meta_req_width; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_width; + } else { + log2_meta_row_height = log2_meta_req_width; + meta_row_width_ub = dml_round_to_multiple(vp_height - 1, meta_req_height, 1) + + meta_req_height; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_height; + } + rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); + log2_meta_chunk_height = log2_meta_row_height; + + /*full sized meta chunk width in unit of data elements */ + log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height; + log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); + min_meta_chunk_width = 1 + << (log2_min_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height); + meta_chunk_width = 1 << log2_meta_chunk_width; + meta_chunk_per_row_int = (unsigned int) (meta_row_width_ub / meta_chunk_width); + meta_row_remainder = meta_row_width_ub % meta_chunk_width; + meta_chunk_threshold = 0; + meta_blk_bytes = 4096; + meta_blk_height = blk256_height * 64; + meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; + meta_surface_bytes = meta_pitch + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + + meta_blk_height) * bytes_per_element / 256; + vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; + meta_pte_req_per_frame_ub = (dml_round_to_multiple( + meta_surface_bytes - vmpg_bytes, + 8 * vmpg_bytes, + 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; + + DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); + DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); + DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); + DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); + DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + + if (!surf_vert) + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; + else + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_height; + + if (meta_row_remainder <= meta_chunk_threshold) + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 1; + else + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; + + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + log2_dpte_group_width = 0; + dpte_row_width_ub = 0; + dpte_row_height = 0; + dpte_req_height = 0; /* 64b dpte req height in data element */ + dpte_req_width = 0; /* 64b dpte req width in data element */ + dpte_group_width = 0; + log2_dpte_group_bytes = 0; + log2_dpte_group_length = 0; + + if (surf_linear) + log2_vmpg_height = 0; /* one line high */ + else + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + /* Ensure we only have the 3 shapes */ + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_height = 1 << log2_dpte_req_height; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch), + 1); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + + /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + */ + dpte_row_width_ub = dml_round_to_multiple( + data_pitch * dpte_row_height - 1, + dpte_req_width, + 1) + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) + + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + dpte_row_width_ub = dml_round_to_multiple(vp_height - 1, dpte_req_height, 1) + + dpte_req_height; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; + } + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + + /* the dpte_group_bytes is reduced for the specific case of vertical + * access of a tile surface that has dpte request of 8x1 ptes. + */ + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + rq_sizing_param->dpte_group_bytes = 512; + else + /*full size */ + rq_sizing_param->dpte_group_bytes = 2048; + + /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); + log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + + /* full sized data pte group width in elements */ + if (!surf_vert) + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; + else + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + + dpte_group_width = 1 << log2_dpte_group_width; + + /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + * the upper bound for the dpte groups per row is as follows. + */ + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( + (double) dpte_row_width_ub / dpte_group_width, + 1); + + dml1_rq_dlg_get_row_heights( + mode_lib, + &func_dpte_row_height, + &func_meta_row_height, + vp_width, + data_pitch, + pipe_src_param.source_format, + pipe_src_param.sw_mode, + pipe_src_param.macro_tile_size, + pipe_src_param.source_scan, + is_chroma); + + /* Just a check to make sure this function and the new one give the same + * result. The standalone get_row_heights() function is based off of the + * code in this function so the same changes need to be made to both. + */ + if (rq_dlg_param->meta_row_height != func_meta_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->meta_row_height = %d", + rq_dlg_param->meta_row_height); + DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); + ASSERT(0); + } + + if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->dpte_row_height = %d", + rq_dlg_param->dpte_row_height); + DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); + ASSERT(0); + } +} + +void dml1_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + /* get param for luma surface */ + rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 + || pipe_src_param.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_l), + &(rq_param->dlg.rq_l), + &(rq_param->misc.rq_l), + pipe_src_param, + 0); + + if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { + /* get param for chroma surface */ + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_c), + &(rq_param->dlg.rq_c), + &(rq_param->misc.rq_c), + pipe_src_param, + 1); + } + + /* calculate how to split the det buffer space between luma and chroma */ + handle_det_buf_split(mode_lib, rq_param, pipe_src_param); + print__rq_params_st(mode_lib, *rq_param); +} + +/* Note: currently taken in as is. + * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. + */ +void dml1_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + /* Timing */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; + unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; + unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double ref_freq_to_pix_freq; + double prefetch_xy_calc_in_dcfclk; + double min_dcfclk_mhz; + double t_calc_us; + double min_ttu_vblank; + double min_dst_y_ttu_vblank; + unsigned int dlg_vblank_start; + bool dcc_en; + bool dual_plane; + bool mode_422; + unsigned int access_dir; + unsigned int bytes_per_element_l; + unsigned int bytes_per_element_c; + unsigned int vp_height_l; + unsigned int vp_width_l; + unsigned int vp_height_c; + unsigned int vp_width_c; + unsigned int htaps_l; + unsigned int htaps_c; + double hratios_l; + double hratios_c; + double vratio_l; + double vratio_c; + double line_time_in_us; + double vinit_l; + double vinit_c; + double vinit_bot_l; + double vinit_bot_c; + unsigned int swath_height_l; + unsigned int swath_width_ub_l; + unsigned int dpte_bytes_per_row_ub_l; + unsigned int dpte_groups_per_row_ub_l; + unsigned int meta_pte_bytes_per_frame_ub_l; + unsigned int meta_bytes_per_row_ub_l; + unsigned int swath_height_c; + unsigned int swath_width_ub_c; + unsigned int dpte_bytes_per_row_ub_c; + unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; + unsigned int dst_x_after_scaler; + unsigned int dst_y_after_scaler; + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + unsigned int vm_bytes; + unsigned int meta_row_bytes; + unsigned int max_num_sw_l; + unsigned int max_num_sw_c; + unsigned int max_partial_sw_l; + unsigned int max_partial_sw_c; + double max_vinit_l; + double max_vinit_c; + unsigned int lsw_l; + unsigned int lsw_c; + unsigned int sw_bytes_ub_l; + unsigned int sw_bytes_ub_c; + unsigned int sw_bytes; + unsigned int dpte_row_bytes; + double prefetch_bw; + double flip_bw; + double t_vm_us; + double t_r0_us; + double dst_y_per_vm_vblank; + double dst_y_per_row_vblank; + double min_dst_y_per_vm_vblank; + double min_dst_y_per_row_vblank; + double lsw; + double vratio_pre_l; + double vratio_pre_c; + unsigned int req_per_swath_ub_l; + unsigned int req_per_swath_ub_c; + unsigned int meta_row_height_l; + unsigned int swath_width_pixels_ub_l; + unsigned int swath_width_pixels_ub_c; + unsigned int scaler_rec_in_width_l; + unsigned int scaler_rec_in_width_c; + unsigned int dpte_row_height_l; + unsigned int dpte_row_height_c; + double hscale_pixel_rate_l; + double hscale_pixel_rate_c; + double min_hratio_fact_l; + double min_hratio_fact_c; + double refcyc_per_line_delivery_pre_l; + double refcyc_per_line_delivery_pre_c; + double refcyc_per_line_delivery_l; + double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; + double refcyc_per_req_delivery_pre_c; + double refcyc_per_req_delivery_l; + double refcyc_per_req_delivery_c; + double refcyc_per_req_delivery_pre_cur0; + double refcyc_per_req_delivery_cur0; + unsigned int full_recout_width; + double hratios_cur0; + unsigned int cur0_src_width; + enum cursor_bpp cur0_bpp; + unsigned int cur0_req_size; + unsigned int cur0_req_width; + double cur0_width_ub; + double cur0_req_per_width; + double hactive_cur0; + + memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); + memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); + + DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); + DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); + DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); + DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); + + /* ------------------------- */ + /* Section 1.5.2.1: OTG dependent Params */ + /* ------------------------- */ + DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); + DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); + + ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = + (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); + disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal + * dml_pow(2, 8)); + disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end + * (double) ref_freq_to_pix_freq); + ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ + + prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + min_ttu_vblank = dlg_sys_param.t_urg_wm_us; + if (cstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); + if (pstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); + min_ttu_vblank = min_ttu_vblank + t_calc_us; + + min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; + dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; + + disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start + + min_dst_y_ttu_vblank) * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); + + DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); + DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); + DTRACE( + "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + __func__, + min_dst_y_ttu_vblank); + DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); + DTRACE( + "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + __func__, + disp_dlg_regs->min_dst_y_next_start); + DTRACE( + "DLG: %s: ref_freq_to_pix_freq = %3.2f", + __func__, + ref_freq_to_pix_freq); + + /* ------------------------- */ + /* Section 1.5.2.2: Prefetch, Active and TTU */ + /* ------------------------- */ + /* Prefetch Calc */ + /* Source */ + dcc_en = e2e_pipe_param.pipe.src.dcc; + dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + mode_422 = 0; /* FIXME */ + access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ + bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + vp_height_l = e2e_pipe_param.pipe.src.viewport_height; + vp_width_l = e2e_pipe_param.pipe.src.viewport_width; + vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; + vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; + + /* Scaling */ + htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; + htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; + hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; + vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; + vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + + line_time_in_us = (htotal / pclk_freq_in_mhz); + vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + swath_height_l = rq_dlg_param.rq_l.swath_height; + swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; + meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + swath_height_c = rq_dlg_param.rq_c.swath_height; + swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; + + meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; + vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + + vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + DTRACE( + "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + __func__, + vblank_start, + vblank_end); + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + dst_x_after_scaler = 0; + dst_y_after_scaler = 0; + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + DTRACE( + "DLG: %s: soc.urgent_latency_us = %3.2f", + __func__, + mode_lib->soc.urgent_latency_us); + + DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); + if (dual_plane) + DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); + + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125), 1) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) + / (double) dlg_sys_param.total_flip_bytes; + t_vm_us = line_time_in_us / 4.0; + if (vm_en && dcc_en) { + t_vm_us = dml_max( + dlg_sys_param.t_extra_us, + dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); + + if (iflip_en && !dual_plane) { + t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); + if (flip_bw > 0.) + t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); + } + } + + t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); + + if (vm_en || dcc_en) { + t_r0_us = dml_max( + (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, + dlg_sys_param.t_extra_us); + t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); + + if (iflip_en && !dual_plane) { + t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); + if (flip_bw > 0.) + t_r0_us = dml_max( + (dpte_row_bytes + meta_row_bytes) / flip_bw, + t_r0_us); + } + } + + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->dst_y_after_scaler); + DTRACE( + "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->refcyc_x_after_scaler); + + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", + __func__, + disp_dlg_regs->dst_y_prefetch); + + dst_y_per_vm_vblank = 0.0; + dst_y_per_row_vblank = 0.0; + + dst_y_per_vm_vblank = t_vm_us / line_time_in_us; + dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125), 1) / 4.0; + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + + dst_y_per_row_vblank = t_r0_us / line_time_in_us; + dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125), 1) / 4.0; + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + + DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); + DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); + + DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); + DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); + DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); + DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); + DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); + DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); + DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); + DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + + min_dst_y_per_vm_vblank = 8.0; + min_dst_y_per_row_vblank = 16.0; + if (htotal <= 75) { + min_vblank = 300; + min_dst_y_per_vm_vblank = 100.0; + min_dst_y_per_row_vblank = 100.0; + } + + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); + ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); + + ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); + lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); + + DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); + + vratio_pre_l = get_vratio_pre( + mode_lib, + max_num_sw_l, + max_partial_sw_l, + swath_height_l, + max_vinit_l, + lsw); + vratio_pre_c = 1.0; + if (dual_plane) + vratio_pre_c = get_vratio_pre( + mode_lib, + max_num_sw_c, + max_partial_sw_c, + swath_height_c, + max_vinit_c, + lsw); + + DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); + DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); + + ASSERT(vratio_pre_l <= 4.0); + if (vratio_pre_l >= 4.0) + disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + + ASSERT(vratio_pre_c <= 4.0); + if (vratio_pre_c >= 4.0) + disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_c = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + /* Active */ + req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + swath_width_pixels_ub_l = 0; + swath_width_pixels_ub_c = 0; + scaler_rec_in_width_l = 0; + scaler_rec_in_width_c = 0; + dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (mode_422) { + swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_c = swath_width_ub_c * 2; + } else { + swath_width_pixels_ub_l = swath_width_ub_l * 1; + swath_width_pixels_ub_c = swath_width_ub_c * 1; + } + + hscale_pixel_rate_l = 0.; + hscale_pixel_rate_c = 0.; + min_hratio_fact_l = 1.0; + min_hratio_fact_c = 1.0; + + if (htaps_l <= 1) + min_hratio_fact_l = 2.0; + else if (htaps_l <= 6) { + if ((hratios_l * 2.0) > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l * 2.0; + } else { + if (hratios_l > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l; + } + + hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; + + if (htaps_c <= 1) + min_hratio_fact_c = 2.0; + else if (htaps_c <= 6) { + if ((hratios_c * 2.0) > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c * 2.0; + } else { + if (hratios_c > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c; + } + + hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; + + refcyc_per_line_delivery_pre_l = 0.; + refcyc_per_line_delivery_pre_c = 0.; + refcyc_per_line_delivery_l = 0.; + refcyc_per_line_delivery_c = 0.; + + refcyc_per_req_delivery_pre_l = 0.; + refcyc_per_req_delivery_pre_c = 0.; + refcyc_per_req_delivery_l = 0.; + refcyc_per_req_delivery_c = 0.; + refcyc_per_req_delivery_pre_cur0 = 0.; + refcyc_per_req_delivery_cur0 = 0.; + + full_recout_width = 0; + if (e2e_pipe_param.pipe.src.is_hsplit) { + if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { + DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); + full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + } else + full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + } else + full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + refcyc_per_line_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); + DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + __func__, + refcyc_per_line_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + __func__, + refcyc_per_line_delivery_l); + + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_l, + 1); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_l, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + refcyc_per_line_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + __func__, + refcyc_per_line_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + __func__, + refcyc_per_line_delivery_c); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_c, + 1); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_c, + 1); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + } + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + + /* TTU - Luma / Chroma */ + if (access_dir) { /* vertical access */ + scaler_rec_in_width_l = vp_height_l; + scaler_rec_in_width_c = vp_height_c; + } else { + scaler_rec_in_width_l = vp_width_l; + scaler_rec_in_width_c = vp_width_c; + } + + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + refcyc_per_req_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + __func__, + refcyc_per_req_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + __func__, + refcyc_per_req_delivery_l); + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + refcyc_per_req_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + __func__, + refcyc_per_req_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + __func__, + refcyc_per_req_delivery_c); + + disp_ttu_regs->refcyc_per_req_delivery_pre_c = + (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); + } + + /* TTU - Cursor */ + hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ + cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; + cur0_req_size = 0; + cur0_req_width = 0; + cur0_width_ub = 0.0; + cur0_req_per_width = 0.0; + hactive_cur0 = 0.0; + + ASSERT(cur0_src_width <= 256); + + if (cur0_src_width > 0) { + unsigned int cur0_bit_per_pixel = 0; + + if (cur0_bpp == dm_cur_2bit) { + cur0_req_size = 64; /* byte */ + cur0_bit_per_pixel = 2; + } else { /* 32bit */ + cur0_bit_per_pixel = 32; + if (cur0_src_width >= 1 && cur0_src_width <= 16) + cur0_req_size = 64; + else if (cur0_src_width >= 17 && cur0_src_width <= 31) + cur0_req_size = 128; + else + cur0_req_size = 256; + } + + cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); + cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width, 1) + * (double) cur0_req_width; + cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; + hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + + if (vratio_pre_l <= 1.0) { + refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); + DTRACE( + "DLG: %s: cur0_width_ub = %3.2f", + __func__, + cur0_width_ub); + DTRACE( + "DLG: %s: cur0_req_per_width = %3.2f", + __func__, + cur0_req_per_width); + DTRACE( + "DLG: %s: hactive_cur0 = %3.2f", + __func__, + hactive_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_pre_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_cur0); + + disp_ttu_regs->refcyc_per_req_delivery_cur0 = + (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); + } else { + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; + disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + } + + /* TTU - Misc */ + disp_ttu_regs->qos_level_low_wm = 0; + ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); + disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal + * ref_freq_to_pix_freq); + ASSERT(disp_ttu_regs->qos_level_high_wm < dml_pow(2, 14)); + + disp_ttu_regs->qos_level_flip = 14; + disp_ttu_regs->qos_level_fixed_l = 8; + disp_ttu_regs->qos_level_fixed_c = 8; + disp_ttu_regs->qos_level_fixed_cur0 = 8; + disp_ttu_regs->qos_ramp_disable_l = 0; + disp_ttu_regs->qos_ramp_disable_c = 0; + disp_ttu_regs->qos_ramp_disable_cur0 = 0; + + disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; + ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); + + print__ttu_regs_st(mode_lib, *disp_ttu_regs); + print__dlg_regs_st(mode_lib, *disp_dlg_regs); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h new file mode 100644 index 000000000000..987d7671cd0f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DISPLAY_RQ_DLG_CALC_H__ +#define __DISPLAY_RQ_DLG_CALC_H__ + +#include "dml_common_defs.h" +#include "display_rq_dlg_helpers.h" + +struct display_mode_lib; + +void dml1_extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param); +/* Function: dml_rq_dlg_get_rq_params + * Calculate requestor related parameters that register definition agnostic + * (i.e. this layer does try to separate real values from register definition) + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) + */ +void dml1_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + + +/* Function: dml_rq_dlg_get_dlg_params + * Calculate deadline related parameters + */ +void dml1_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 21349a022de3..9cbd415e508d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -36,21 +36,21 @@ double dml_max(double a, double b) return (double) dcn_bw_max2(a, b); } -double dml_ceil(double a) +double dml_ceil(double a, double granularity) { - return (double) dcn_bw_ceil2(a, 1); + return (double) dcn_bw_ceil2(a, granularity); } -double dml_floor(double a) +double dml_floor(double a, double granularity) { - return (double) dcn_bw_floor2(a, 1); + return (double) dcn_bw_floor2(a, granularity); } double dml_round(double a) { double round_pt = 0.5; - double ceil = dml_ceil(a); - double floor = dml_floor(a); + double ceil = dml_ceil(a, 1); + double floor = dml_floor(a, 1); if (a - floor >= round_pt) return ceil; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index c5340d41eedb..19271e79abcc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -22,6 +22,7 @@ * Authors: AMD * */ + #ifndef __DC_COMMON_DEFS_H__ #define __DC_COMMON_DEFS_H__ @@ -30,7 +31,8 @@ #include "display_mode_structs.h" #include "display_mode_enums.h" -#define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); +#define dml_print(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } +#define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } double dml_min(double a, double b); double dml_max(double a, double b); @@ -38,8 +40,8 @@ bool dml_util_is_420(enum source_format_class sorce_format); double dml_ceil_ex(double x, double granularity); double dml_floor_ex(double x, double granularity); double dml_log(double x, double base); -double dml_ceil(double a); -double dml_floor(double a); +double dml_ceil(double a, double granularity); +double dml_floor(double a, double granularity); double dml_round(double a); int dml_log2(double x); double dml_pow(double a, int exp); diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index 112b0b728b4d..8b8512528af5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -24,49 +24,45 @@ */ #include "soc_bounding_box.h" #include "display_mode_lib.h" +#include "dc_features.h" -void dml_socbb_set_latencies( - struct display_mode_lib *mode_lib, - struct _vcs_dpi_soc_bounding_box_st *from_box) +void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box) { - struct _vcs_dpi_soc_bounding_box_st *to_box = &mode_lib->soc; - to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; to_box->sr_exit_time_us = from_box->sr_exit_time_us; to_box->sr_enter_plus_exit_time_us = from_box->sr_enter_plus_exit_time_us; to_box->urgent_latency_us = from_box->urgent_latency_us; to_box->writeback_latency_us = from_box->writeback_latency_us; - DTRACE("box.dram_clock_change_latency_us: %f", from_box->dram_clock_change_latency_us); - DTRACE("box.sr_exit_time_us: %f", from_box->sr_exit_time_us); - DTRACE("box.sr_enter_plus_exit_time_us: %f", from_box->sr_enter_plus_exit_time_us); - DTRACE("box.urgent_latency_us: %f", from_box->urgent_latency_us); - DTRACE("box.writeback_latency_us: %f", from_box->writeback_latency_us); - } -struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling( - struct _vcs_dpi_soc_bounding_box_st *box, +voltage_scaling_st dml_socbb_voltage_scaling( + const soc_bounding_box_st *soc, enum voltage_state voltage) { - switch (voltage) { - case dm_vmin: - return box->vmin; - case dm_vnom: - return box->vnom; - case dm_vmax: - default: - return box->vmax; + const voltage_scaling_st *voltage_state; + const voltage_scaling_st * const voltage_end = soc->clock_limits + DC__VOLTAGE_STATES; + + for (voltage_state = soc->clock_limits; + voltage_state < voltage_end && voltage_state->state != voltage; + voltage_state++) { } + + if (voltage_state < voltage_end) + return *voltage_state; + return soc->clock_limits[DC__VOLTAGE_STATES - 1]; } -double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage) +double dml_socbb_return_bw_mhz(soc_bounding_box_st *box, enum voltage_state voltage) { double return_bw; - struct _vcs_dpi_voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); + voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); + + return_bw = dml_min((double) box->return_bus_width_bytes * state.dcfclk_mhz, + state.dram_bw_per_chan_gbps * 1000.0 * (double) box->num_chans + * box->ideal_dram_bw_after_urgent_percent / 100.0); + + return_bw = dml_min((double) box->return_bus_width_bytes * state.fabricclk_mhz, return_bw); - return_bw = dml_min( - ((double) box->return_bus_width_bytes) * state.dcfclk_mhz, - state.dram_bw_per_chan_gbps * 1000.0 * box->ideal_dram_bw_after_urgent_percent / 100.0); return return_bw; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h index 7bbae33f163e..7a65206a6d21 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h @@ -22,15 +22,14 @@ * Authors: AMD * */ + #ifndef __SOC_BOUNDING_BOX_H__ #define __SOC_BOUNDING_BOX_H__ #include "dml_common_defs.h" -struct display_mode_lib; - -void dml_socbb_set_latencies(struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box); -struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); -double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); +void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box); +voltage_scaling_st dml_socbb_voltage_scaling(const soc_bounding_box_st *box, enum voltage_state voltage); +double dml_socbb_return_bw_mhz(soc_bounding_box_st *box, enum voltage_state voltage); #endif -- GitLab From cb94f78e3665ef23aabfe547962748d49471cf45 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 15 Sep 2017 16:03:09 -0400 Subject: [PATCH 1302/2898] drm/amd/display: add mode support check to dml vba code Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dml/display_mode_enums.h | 10 +- .../amd/display/dc/dml/display_mode_structs.h | 5 + .../drm/amd/display/dc/dml/display_mode_vba.c | 5701 ++++++++++++----- .../drm/amd/display/dc/dml/display_mode_vba.h | 456 +- .../drm/amd/display/dc/dml/dml_common_defs.c | 12 + .../drm/amd/display/dc/dml/dml_common_defs.h | 3 + 6 files changed, 4604 insertions(+), 1583 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index eebaeb1fb61c..b1ad3553f900 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -26,7 +26,7 @@ #define __DISPLAY_MODE_ENUMS_H__ enum output_encoder_class { - dm_dp = 0, dm_hdmi = 1, dm_wb = 2 + dm_dp = 0, dm_hdmi = 1, dm_wb = 2, dm_edp }; enum output_format_class { dm_444 = 0, dm_420 = 1, dm_n422, dm_s422 @@ -39,7 +39,9 @@ enum source_format_class { dm_420_10 = 4, dm_422_8 = 5, dm_422_10 = 6, - dm_444_8 = 7 + dm_444_8 = 7, + dm_mono_8, + dm_mono_16 }; enum output_bpc_class { dm_out_6 = 0, dm_out_8 = 1, dm_out_10 = 2, dm_out_12 = 3, dm_out_16 = 4 @@ -79,7 +81,9 @@ enum dm_swizzle_mode { dm_sw_SPARE_15 = 28, dm_sw_var_s_x = 29, dm_sw_var_d_x = 30, - dm_sw_64kb_r_x + dm_sw_64kb_r_x, + dm_sw_gfx7_2d_thin_lvp, + dm_sw_gfx7_2d_thin_gl }; enum lb_depth { dm_lb_10 = 0, dm_lb_8 = 1, dm_lb_6 = 2, dm_lb_12 = 3, dm_lb_16 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index e5b7f7042e0b..27e20460c71b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -66,6 +66,7 @@ struct _vcs_dpi_mode_evaluation_st { struct _vcs_dpi_voltage_scaling_st { int state; + double dscclk_mhz; double dcfclk_mhz; double socclk_mhz; double dram_speed_mhz; @@ -131,6 +132,9 @@ struct _vcs_dpi_ip_params_st { unsigned int writeback_chroma_line_buffer_width_pixels; unsigned int max_page_table_levels; unsigned int max_num_dpp; + unsigned int max_num_otg; + unsigned int cursor_chunk_size; + unsigned int cursor_buffer_size; unsigned int max_num_wb; unsigned int max_dchub_pscl_bw_pix_per_clk; unsigned int max_pscl_lb_bw_pix_per_clk; @@ -224,6 +228,7 @@ struct writeback_st { }; struct _vcs_dpi_display_output_params_st { + int dp_lanes; int output_bpp; int dsc_enable; int wb_enable; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index ada0eeed3301..e1a3182d58b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -6,202 +6,220 @@ static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; static void fetch_socbb_params(struct display_mode_lib *mode_lib); static void fetch_ip_params(struct display_mode_lib *mode_lib); static void fetch_pipe_params(struct display_mode_lib *mode_lib); -static void recalculate_params(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes); +static void recalculate_params( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); static void recalculate(struct display_mode_lib *mode_lib); -static double adjust_ReturnBW(struct display_mode_lib *mode_lib, double ReturnBW, bool DCCEnabledAnyPlane, double ReturnBandwidthToDCN); +static double adjust_ReturnBW( + struct display_mode_lib *mode_lib, + double ReturnBW, + bool DCCEnabledAnyPlane, + double ReturnBandwidthToDCN); static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib); static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); -static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib); -static unsigned int dscceComputeDelay(unsigned int bpc, - double bpp, - unsigned int sliceWidth, - unsigned int numSlices, - enum output_format_class pixelFormat); +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( + struct display_mode_lib *mode_lib); +static unsigned int dscceComputeDelay( + unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat); static unsigned int dscComputeDelay(enum output_format_class pixelFormat); // Super monster function with some 45 argument -static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, - double DPPCLK, - double DISPCLK, - double PixelClock, - double DCFClkDeepSleep, - unsigned int DSCDelay, - unsigned int DPPPerPlane, - bool ScalerEnabled, - unsigned int NumberOfCursors, - double DPPCLKDelaySubtotal, - double DPPCLKDelaySCL, - double DPPCLKDelaySCLLBOnly, - double DPPCLKDelayCNVCFormater, - double DPPCLKDelayCNVCCursor, - double DISPCLKDelaySubtotal, - unsigned int ScalerRecoutWidth, - enum output_format_class OutputFormat, - unsigned int VBlank, - unsigned int HTotal, - unsigned int MaxInterDCNTileRepeaters, - unsigned int VStartup, - unsigned int PageTableLevels, - bool VirtualMemoryEnable, - bool DynamicMetadataEnable, - unsigned int DynamicMetadataLinesBeforeActiveRequired, - unsigned int DynamicMetadataTransmittedBytes, - bool DCCEnable, - double UrgentLatency, - double UrgentExtraLatency, - double TCalc, - unsigned int PDEAndMetaPTEBytesFrame, - unsigned int MetaRowByte, - unsigned int PixelPTEBytesPerRow, - double PrefetchSourceLinesY, - unsigned int SwathWidthY, - double BytePerPixelDETY, - double VInitPreFillY, - unsigned int MaxNumSwathY, - double PrefetchSourceLinesC, - double BytePerPixelDETC, - double VInitPreFillC, - unsigned int MaxNumSwathC, - unsigned int SwathHeightY, - unsigned int SwathHeightC, - double TWait, - bool XFCEnabled, - double XFCRemoteSurfaceFlipDelay, - bool InterlaceEnable, - bool ProgressiveToInterlaceUnitInOPP, - double *DSTXAfterScaler, - double *DSTYAfterScaler, - double *DestinationLinesForPrefetch, - double *PrefetchBandwidth, - double *DestinationLinesToRequestVMInVBlank, - double *DestinationLinesToRequestRowInVBlank, - double *VRatioPrefetchY, - double *VRatioPrefetchC, - double *RequiredPrefetchPixDataBW, - unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - double *Tno_bw); -static double CeilToDFSGranularity(double Clock, double VCOSpeed); -static double FloorToDFSGranularity(double Clock, double VCOSpeed); -static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, - double VRatio, - double vtaps, - bool Interlace, - bool ProgressiveToInterlaceUnitInOPP, - unsigned int SwathHeight, - unsigned int ViewportYStart, - double *VInitPreFill, - unsigned int *MaxNumSwath); -static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, - bool DCCEnable, - unsigned int BlockHeight256Bytes, - unsigned int BlockWidth256Bytes, - enum source_format_class SourcePixelFormat, - unsigned int SurfaceTiling, - unsigned int BytePerPixel, - enum scan_direction_class ScanDirection, - unsigned int ViewportWidth, - unsigned int ViewportHeight, - unsigned int SwathWidthY, - bool VirtualMemoryEnable, - unsigned int VMMPageSize, - unsigned int PTEBufferSizeInRequests, - unsigned int PDEProcessingBufIn64KBReqs, - unsigned int Pitch, - unsigned int DCCMetaPitch, - unsigned int *MacroTileWidth, - unsigned int *MetaRowByte, - unsigned int *PixelPTEBytesPerRow, - bool *PTEBufferSizeNotExceeded, - unsigned int *dpte_row_height, - unsigned int *meta_row_height); -static double CalculateTWait(unsigned int PrefetchMode, - double DRAMClockChangeLatency, - double UrgentLatency, - double SREnterPlusExitTime); -static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, - double VRatio, - double SwathWidth, - double Bpp, - double LineTime, - double XFCTSlvVupdateOffset, - double XFCTSlvVupdateWidth, - double XFCTSlvVreadyOffset, - double XFCXBUFLatencyTolerance, - double XFCFillBWOverhead, - double XFCSlvChunkSize, - double XFCBusTransportTime, - double TCalc, - double TWait, - double *SrcActiveDrainRate, - double *TInitXFill, - double *TslvChk); -static double CalculateWriteBackDISPCLK(enum source_format_class WritebackPixelFormat, - double PixelClock, - double WritebackHRatio, - double WritebackVRatio, - unsigned int WritebackLumaHTaps, - unsigned int WritebackLumaVTaps, - unsigned int WritebackChromaHTaps, - unsigned int WritebackChromaVTaps, - double WritebackDestinationWidth, - unsigned int HTotal, - unsigned int WritebackChromaLineBufferWidth); -static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, - enum source_format_class SourcePixelFormat, - double VRatio, - bool DCCEnable, - double LineTime, - unsigned int MetaRowByteLuma, - unsigned int MetaRowByteChroma, - unsigned int meta_row_height_luma, - unsigned int meta_row_height_chroma, - unsigned int PixelPTEBytesPerRowLuma, - unsigned int PixelPTEBytesPerRowChroma, - unsigned int dpte_row_height_luma, - unsigned int dpte_row_height_chroma, - double *meta_row_bw, - double *dpte_row_bw, - double *qual_row_bw); -static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, - double UrgentExtraLatency, - double UrgentLatency, - unsigned int MaxPageTableLevels, - bool VirtualMemoryEnable, - double BandwidthAvailableForImmediateFlip, - unsigned int TotImmediateFlipBytes, - enum source_format_class SourcePixelFormat, - unsigned int ImmediateFlipBytes, - double LineTime, - double Tno_bw, - double VRatio, - double PDEAndMetaPTEBytesFrame, - unsigned int MetaRowByte, - unsigned int PixelPTEBytesPerRow, - bool DCCEnable, - unsigned int dpte_row_height, - unsigned int meta_row_height, - double qual_row_bw, - double *DestinationLinesToRequestVMInImmediateFlip, - double *DestinationLinesToRequestRowInImmediateFlip, - double *final_flip_bw, - bool *ImmediateFlipSupportedForPipe); -static double CalculateWriteBackDelay(enum source_format_class WritebackPixelFormat, - double WritebackHRatio, - double WritebackVRatio, - unsigned int WritebackLumaHTaps, - unsigned int WritebackLumaVTaps, - unsigned int WritebackChromaHTaps, - unsigned int WritebackChromaVTaps, - unsigned int WritebackDestinationWidth); +static bool CalculatePrefetchSchedule( + struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw); +static double RoundToDFSGranularityUp(double Clock, double VCOSpeed); +static double RoundToDFSGranularityDown(double Clock, double VCOSpeed); +static double CalculatePrefetchSourceLines( + struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath); +static unsigned int CalculateVMAndRowBytes( + struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidthY, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height); +static double CalculateTWait( + unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime); +static double CalculateRemoteSurfaceFlipDelay( + struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk); +static double CalculateWriteBackDISPCLK( + enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth); +static void CalculateActiveRowBandwidth( + bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw); +static void CalculateFlipSchedule( + struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe); +static double CalculateWriteBackDelay( + enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth); static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mode_lib *mode_lib); static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp); - -void set_prefetch_mode(struct display_mode_lib *mode_lib, - bool cstate_en, - bool pstate_en, - bool ignore_viewport_pos, - bool immediate_flip_support) +static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib); + +void set_prefetch_mode( + struct display_mode_lib *mode_lib, + bool cstate_en, + bool pstate_en, + bool ignore_viewport_pos, + bool immediate_flip_support) { unsigned int prefetch_mode; @@ -211,11 +229,13 @@ void set_prefetch_mode(struct display_mode_lib *mode_lib, prefetch_mode = 1; else prefetch_mode = 2; - if (prefetch_mode != mode_lib->vba.PrefetchMode || ignore_viewport_pos != mode_lib->vba.IgnoreViewportPositioning - || immediate_flip_support != mode_lib->vba.ImmediateFlipSupport) { - DTRACE(" Prefetch mode has changed from %i to %i. Recalculating.", - prefetch_mode, - mode_lib->vba.PrefetchMode); + if (prefetch_mode != mode_lib->vba.PrefetchMode + || ignore_viewport_pos != mode_lib->vba.IgnoreViewportPositioning + || immediate_flip_support != mode_lib->vba.ImmediateFlipSupport) { + DTRACE( + " Prefetch mode has changed from %i to %i. Recalculating.", + prefetch_mode, + mode_lib->vba.PrefetchMode); mode_lib->vba.PrefetchMode = prefetch_mode; mode_lib->vba.IgnoreViewportPositioning = ignore_viewport_pos; mode_lib->vba.ImmediateFlipSupport = immediate_flip_support; @@ -223,6 +243,39 @@ void set_prefetch_mode(struct display_mode_lib *mode_lib, } } +unsigned int dml_get_voltage_level( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + bool need_recalculate = memcmp( + &mode_lib->soc, + &mode_lib->vba.soc, + sizeof(mode_lib->vba.soc)) != 0 + || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 + || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 + || num_pipes != mode_lib->vba.cache_num_pipes + || memcmp(pipes, mode_lib->vba.cache_pipes, + sizeof(display_e2e_pipe_params_st) * num_pipes) != 0; + + mode_lib->vba.soc = mode_lib->soc; + mode_lib->vba.ip = mode_lib->ip; + mode_lib->vba.me = mode_lib->me; + memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); + mode_lib->vba.cache_num_pipes = num_pipes; + + if (need_recalculate) + recalculate(mode_lib); + else { + fetch_socbb_params(mode_lib); + fetch_ip_params(mode_lib); + fetch_pipe_params(mode_lib); + } + ModeSupportAndSystemConfigurationFull(mode_lib); + + return mode_lib->vba.VoltageLevel; +} + #define dml_get_attr_func(attr, var) double get_##attr(struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) \ { \ recalculate_params(mode_lib, pipes, num_pipes); \ @@ -243,7 +296,9 @@ dml_get_attr_func(stutter_efficiency_no_vblank, mode_lib->vba.StutterEfficiencyN dml_get_attr_func(urgent_latency, mode_lib->vba.MinUrgentLatencySupportUs); dml_get_attr_func(urgent_extra_latency, mode_lib->vba.UrgentExtraLatency); dml_get_attr_func(nonurgent_latency, mode_lib->vba.NonUrgentLatencyTolerance); -dml_get_attr_func(dram_clock_change_latency, mode_lib->vba.MinActiveDRAMClockChangeLatencySupported); +dml_get_attr_func( + dram_clock_change_latency, + mode_lib->vba.MinActiveDRAMClockChangeLatencySupported); dml_get_attr_func(dispclk_calculated, mode_lib->vba.DISPCLK_calculated); dml_get_attr_func(total_data_read_bw, mode_lib->vba.TotalDataReadBandwidth); dml_get_attr_func(return_bw, mode_lib->vba.ReturnBW); @@ -269,17 +324,20 @@ dml_get_pipe_attr_func(dst_y_per_vm_vblank, mode_lib->vba.DestinationLinesToRequ dml_get_pipe_attr_func(dst_y_per_row_vblank, mode_lib->vba.DestinationLinesToRequestRowInVBlank); dml_get_pipe_attr_func(dst_y_prefetch, mode_lib->vba.DestinationLinesForPrefetch); dml_get_pipe_attr_func(dst_y_per_vm_flip, mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip); -dml_get_pipe_attr_func(dst_y_per_row_flip, mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip); +dml_get_pipe_attr_func( + dst_y_per_row_flip, + mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip); dml_get_pipe_attr_func(xfc_transfer_delay, mode_lib->vba.XFCTransferDelay); dml_get_pipe_attr_func(xfc_precharge_delay, mode_lib->vba.XFCPrechargeDelay); dml_get_pipe_attr_func(xfc_remote_surface_flip_latency, mode_lib->vba.XFCRemoteSurfaceFlipLatency); dml_get_pipe_attr_func(xfc_prefetch_margin, mode_lib->vba.XFCPrefetchMargin); -unsigned int get_vstartup_calculated(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes, - unsigned int which_pipe) +unsigned int get_vstartup_calculated( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes, + unsigned int which_pipe) { unsigned int which_plane; @@ -288,25 +346,28 @@ unsigned int get_vstartup_calculated(struct display_mode_lib *mode_lib, return mode_lib->vba.VStartup[which_plane]; } -double get_total_immediate_flip_bytes(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) +double get_total_immediate_flip_bytes( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) { recalculate_params(mode_lib, pipes, num_pipes); return mode_lib->vba.TotImmediateFlipBytes; } -double get_total_immediate_flip_bw(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) +double get_total_immediate_flip_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) { recalculate_params(mode_lib, pipes, num_pipes); return mode_lib->vba.ImmediateFlipBW; } -double get_total_prefetch_bw(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) +double get_total_prefetch_bw( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) { unsigned int k; double total_prefetch_bw = 0.0; @@ -326,10 +387,11 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib) mode_lib->vba.ReturnBusWidth = soc->return_bus_width_bytes; mode_lib->vba.NumberOfChannels = soc->num_chans; mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency = - soc->ideal_dram_bw_after_urgent_percent; // there's always that one bastard variable that's so long it throws everything out of alignment! + soc->ideal_dram_bw_after_urgent_percent; // there's always that one bastard variable that's so long it throws everything out of alignment! mode_lib->vba.UrgentLatency = soc->urgent_latency_us; mode_lib->vba.RoundTripPingLatencyCycles = soc->round_trip_ping_latency_dcfclk_cycles; - mode_lib->vba.UrgentOutOfOrderReturnPerChannel = soc->urgent_out_of_order_return_per_channel_bytes; + mode_lib->vba.UrgentOutOfOrderReturnPerChannel = + soc->urgent_out_of_order_return_per_channel_bytes; mode_lib->vba.WritebackLatency = soc->writeback_latency_us; mode_lib->vba.SRExitTime = soc->sr_exit_time_us; mode_lib->vba.SREnterPlusExitTime = soc->sr_enter_plus_exit_time_us; @@ -342,7 +404,7 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib) mode_lib->vba.VMMPageSize = soc->vmm_page_size_bytes; // Set the voltage scaling clocks as the defaults. Most of these will // be set to different values by the test - for (i = 0; i < DC__VOLTAGE_STATES; ++i) + for (i = 0; i < DC__VOLTAGE_STATES; i++) if (soc->clock_limits[i].state == mode_lib->vba.VoltageLevel) break; @@ -353,6 +415,23 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib) mode_lib->vba.XFCBusTransportTime = soc->xfc_bus_transport_time_us; mode_lib->vba.XFCXBUFLatencyTolerance = soc->xfc_xbuf_latency_tolerance_us; + + mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp = false; + mode_lib->vba.MaxHSCLRatio = 4; + mode_lib->vba.MaxVSCLRatio = 4; + mode_lib->vba.MaxNumWriteback = 0; /*TODO*/ + mode_lib->vba.WritebackLumaAndChromaScalingSupported = true; + mode_lib->vba.Cursor64BppSupport = true; + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.DCFCLKPerState[i] = soc->clock_limits[i].dcfclk_mhz; + mode_lib->vba.FabricClockPerState[i] = soc->clock_limits[i].fabricclk_mhz; + mode_lib->vba.SOCCLKPerState[i] = soc->clock_limits[i].socclk_mhz; + mode_lib->vba.PHYCLKPerState[i] = soc->clock_limits[i].phyclk_mhz; + mode_lib->vba.MaxDppclk[i] = soc->clock_limits[i].dppclk_mhz; + mode_lib->vba.MaxDSCCLK[i] = soc->clock_limits[i].dscclk_mhz; + mode_lib->vba.DRAMSpeedPerState[i] = soc->clock_limits[i].dram_speed_mhz; + mode_lib->vba.MaxDispclk[i] = soc->clock_limits[i].dispclk_mhz; + } } static void fetch_ip_params(struct display_mode_lib *mode_lib) @@ -360,6 +439,11 @@ static void fetch_ip_params(struct display_mode_lib *mode_lib) ip_params_st *ip = &mode_lib->vba.ip; // IP Parameters + mode_lib->vba.MaxNumDPP = ip->max_num_dpp; + mode_lib->vba.MaxNumOTG = ip->max_num_otg; + mode_lib->vba.CursorChunkSize = ip->cursor_chunk_size; + mode_lib->vba.CursorBufferSize = ip->cursor_buffer_size; + mode_lib->vba.MaxDCHUBToPSCLThroughput = ip->max_dchub_pscl_bw_pix_per_clk; mode_lib->vba.MaxPSCLToLBThroughput = ip->max_pscl_lb_bw_pix_per_clk; mode_lib->vba.ROBBufferSizeInKByte = ip->rob_buffer_size_kbytes; @@ -375,7 +459,8 @@ static void fetch_ip_params(struct display_mode_lib *mode_lib) mode_lib->vba.OPPOutputBufferLines = ip->opp_output_buffer_lines; mode_lib->vba.WritebackInterfaceLumaBufferSize = ip->writeback_luma_buffer_size_kbytes; mode_lib->vba.WritebackInterfaceChromaBufferSize = ip->writeback_chroma_buffer_size_kbytes; - mode_lib->vba.WritebackChromaLineBufferWidth = ip->writeback_chroma_line_buffer_width_pixels; + mode_lib->vba.WritebackChromaLineBufferWidth = + ip->writeback_chroma_line_buffer_width_pixels; mode_lib->vba.MaxPageTableLevels = ip->max_page_table_levels; mode_lib->vba.MaxInterDCNTileRepeaters = ip->max_inter_dcn_tile_repeaters; mode_lib->vba.NumberOfDSC = ip->num_dsc; @@ -402,10 +487,10 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) display_e2e_pipe_params_st *pipes = mode_lib->vba.cache_pipes; ip_params_st *ip = &mode_lib->vba.ip; - unsigned int OTGInstPlane[DC__NUM_DPP]; + unsigned int OTGInstPlane[DC__NUM_DPP__MAX]; unsigned int j, k; - bool PlaneVisited[DC__NUM_DPP]; - bool visited[DC__NUM_PIPES__MAX]; + bool PlaneVisited[DC__NUM_DPP__MAX]; + bool visited[DC__NUM_DPP__MAX]; // Convert Pipes to Planes for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) @@ -427,11 +512,16 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.pipe_plane[j] = mode_lib->vba.NumberOfActivePlanes; mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes] = 1; - mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = (enum scan_direction_class)(src->source_scan); - mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width; - mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height; - mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_y; - mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] = src->viewport_y_c; + mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] = + (enum scan_direction_class) (src->source_scan); + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_width; + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_height; + mode_lib->vba.ViewportYStartY[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_y_y; + mode_lib->vba.ViewportYStartC[mode_lib->vba.NumberOfActivePlanes] = + src->viewport_y_c; mode_lib->vba.PitchY[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch; mode_lib->vba.PitchC[mode_lib->vba.NumberOfActivePlanes] = src->data_pitch_c; mode_lib->vba.DCCMetaPitchY[mode_lib->vba.NumberOfActivePlanes] = src->meta_pitch; @@ -448,40 +538,62 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.HTotal[mode_lib->vba.NumberOfActivePlanes] = dst->htotal; mode_lib->vba.VTotal[mode_lib->vba.NumberOfActivePlanes] = dst->vtotal; mode_lib->vba.DCCEnable[mode_lib->vba.NumberOfActivePlanes] = - src->dcc_use_global ? ip->dcc_supported : src->dcc & ip->dcc_supported; + src->dcc_use_global ? + ip->dcc_supported : src->dcc && ip->dcc_supported; mode_lib->vba.DCCRate[mode_lib->vba.NumberOfActivePlanes] = src->dcc_rate; - mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class)(src->source_format); + mode_lib->vba.SourcePixelFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum source_format_class) (src->source_format); mode_lib->vba.HActive[mode_lib->vba.NumberOfActivePlanes] = dst->hactive; mode_lib->vba.VActive[mode_lib->vba.NumberOfActivePlanes] = dst->vactive; - mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] = (enum dm_swizzle_mode)(src->sw_mode); - mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] = dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode? - mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] = dst->odm_combine; - mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] = (enum output_format_class)(dout->output_format); - mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] = (enum output_encoder_class)(dout->output_type); + mode_lib->vba.SurfaceTiling[mode_lib->vba.NumberOfActivePlanes] = + (enum dm_swizzle_mode) (src->sw_mode); + mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] = + dst->recout_width; // TODO: or should this be full_recout_width???...maybe only when in hsplit mode? + mode_lib->vba.ODMCombineEnabled[mode_lib->vba.NumberOfActivePlanes] = + dst->odm_combine; + mode_lib->vba.OutputFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum output_format_class) (dout->output_format); + mode_lib->vba.Output[mode_lib->vba.NumberOfActivePlanes] = + (enum output_encoder_class) (dout->output_type); mode_lib->vba.OutputBpp[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpp; + mode_lib->vba.OutputLinkDPLanes[mode_lib->vba.NumberOfActivePlanes] = + dout->dp_lanes; mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; - mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; + mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = + dout->dsc_slices; mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = - dout->output_bpc == 0 ? 12 : dout->output_bpc; + dout->output_bpc == 0 ? 12 : dout->output_bpc; mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable; - mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_src_height; - mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_dst_width; - mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_dst_height; - mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] = (enum source_format_class)(dout->wb.wb_pixel_format); - mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_htaps_luma; - mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vtaps_luma; - mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_htaps_chroma; - mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vtaps_chroma; - mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_hratio; - mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] = dout->wb.wb_vratio; - - mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] = src->dynamic_metadata_enable; + mode_lib->vba.WritebackSourceHeight[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_src_height; + mode_lib->vba.WritebackDestinationWidth[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_dst_width; + mode_lib->vba.WritebackDestinationHeight[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_dst_height; + mode_lib->vba.WritebackPixelFormat[mode_lib->vba.NumberOfActivePlanes] = + (enum source_format_class) (dout->wb.wb_pixel_format); + mode_lib->vba.WritebackLumaHTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_htaps_luma; + mode_lib->vba.WritebackLumaVTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vtaps_luma; + mode_lib->vba.WritebackChromaHTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_htaps_chroma; + mode_lib->vba.WritebackChromaVTaps[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vtaps_chroma; + mode_lib->vba.WritebackHRatio[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_hratio; + mode_lib->vba.WritebackVRatio[mode_lib->vba.NumberOfActivePlanes] = + dout->wb.wb_vratio; + + mode_lib->vba.DynamicMetadataEnable[mode_lib->vba.NumberOfActivePlanes] = + src->dynamic_metadata_enable; mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[mode_lib->vba.NumberOfActivePlanes] = - src->dynamic_metadata_lines_before_active; + src->dynamic_metadata_lines_before_active; mode_lib->vba.DynamicMetadataTransmittedBytes[mode_lib->vba.NumberOfActivePlanes] = - src->dynamic_metadata_xmit_bytes; + src->dynamic_metadata_xmit_bytes; - mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable && ip->xfc_supported; + mode_lib->vba.XFCEnabled[mode_lib->vba.NumberOfActivePlanes] = src->xfc_enable + && ip->xfc_supported; mode_lib->vba.XFCSlvChunkSize = src->xfc_params.xfc_slv_chunk_size_bytes; mode_lib->vba.XFCTSlvVupdateOffset = src->xfc_params.xfc_tslv_vupdate_offset_us; mode_lib->vba.XFCTSlvVupdateWidth = src->xfc_params.xfc_tslv_vupdate_width_us; @@ -489,7 +601,8 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.PixelClock[mode_lib->vba.NumberOfActivePlanes] = dst->pixel_rate_mhz; mode_lib->vba.DPPCLK[mode_lib->vba.NumberOfActivePlanes] = clks->dppclk_mhz; if (ip->is_line_buffer_bpp_fixed) - mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = ip->line_buffer_fixed_bpp; + mode_lib->vba.LBBitPerPixel[mode_lib->vba.NumberOfActivePlanes] = + ip->line_buffer_fixed_bpp; else { unsigned int lb_depth; @@ -520,27 +633,36 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) for (k = 0; k < DC__NUM_CURSOR; ++k) { switch (k) { case 0: - mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = CursorBppEnumToBits((enum cursor_bpp)(src->cur0_bpp)); - mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] = src->cur0_src_width; + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = + CursorBppEnumToBits( + (enum cursor_bpp) (src->cur0_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][0] = + src->cur0_src_width; if (src->cur0_src_width > 0) mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; break; case 1: - mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] = CursorBppEnumToBits((enum cursor_bpp)(src->cur1_bpp)); - mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] = src->cur1_src_width; + mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][1] = + CursorBppEnumToBits( + (enum cursor_bpp) (src->cur1_bpp)); + mode_lib->vba.CursorWidth[mode_lib->vba.NumberOfActivePlanes][1] = + src->cur1_src_width; if (src->cur1_src_width > 0) mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes]++; break; default: - dml_print("ERROR: Number of cursors specified exceeds supported maximum\n"); + dml_print( + "ERROR: Number of cursors specified exceeds supported maximum\n") + ; } } OTGInstPlane[mode_lib->vba.NumberOfActivePlanes] = dst->otg_inst; if (dst->odm_combine && !src->is_hsplit) - dml_print("ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n", - j); + dml_print( + "ERROR: ODM Combine is specified but is_hsplit has not be specified for pipe %i\n", + j); if (src->is_hsplit) { for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) { @@ -548,18 +670,20 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) display_output_params_st *dout_k = &pipes[k].dout; if (src_k->is_hsplit && !visited[k] - && src->hsplit_grp == src_k->hsplit_grp) { - mode_lib->vba.pipe_plane[k] = mode_lib->vba.NumberOfActivePlanes; + && src->hsplit_grp == src_k->hsplit_grp) { + mode_lib->vba.pipe_plane[k] = + mode_lib->vba.NumberOfActivePlanes; mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++; - if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] == dm_horz) + if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] + == dm_horz) mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] += - src_k->viewport_width; + src_k->viewport_width; else mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] += - src_k->viewport_height; + src_k->viewport_height; mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] += - dout_k->dsc_slices; + dout_k->dsc_slices; visited[k] = true; } } @@ -598,26 +722,30 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) for (k = 1; k < mode_lib->vba.cache_num_pipes; ++k) ASSERT(mode_lib->vba.SynchronizedVBlank == pipes[k].pipe.dest.synchronized_vblank_all_planes); - mode_lib->vba.VirtualMemoryEnable = 0; + mode_lib->vba.VirtualMemoryEnable = false; mode_lib->vba.OverridePageTableLevels = 0; for (k = 0; k < mode_lib->vba.cache_num_pipes; ++k) { - mode_lib->vba.VirtualMemoryEnable |= pipes[k].pipe.src.vm; + mode_lib->vba.VirtualMemoryEnable = mode_lib->vba.VirtualMemoryEnable + || !!pipes[k].pipe.src.vm; mode_lib->vba.OverridePageTableLevels = - (pipes[k].pipe.src.vm_levels_force_en - && mode_lib->vba.OverridePageTableLevels - < pipes[k].pipe.src.vm_levels_force) ? - pipes[k].pipe.src.vm_levels_force : - mode_lib->vba.OverridePageTableLevels; + (pipes[k].pipe.src.vm_levels_force_en + && mode_lib->vba.OverridePageTableLevels + < pipes[k].pipe.src.vm_levels_force) ? + pipes[k].pipe.src.vm_levels_force : + mode_lib->vba.OverridePageTableLevels; } if (mode_lib->vba.OverridePageTableLevels) mode_lib->vba.MaxPageTableLevels = mode_lib->vba.OverridePageTableLevels; - mode_lib->vba.VirtualMemoryEnable &= ip->pte_enable; + mode_lib->vba.VirtualMemoryEnable = mode_lib->vba.VirtualMemoryEnable && !!ip->pte_enable; - mode_lib->vba.FabricAndDRAMBandwidth = dml_min(mode_lib->vba.DRAMSpeed * mode_lib->vba.NumberOfChannels * mode_lib->vba.DRAMChannelWidth, - mode_lib->vba.FabricClock * mode_lib->vba.FabricDatapathToDCNDataReturn) / 1000.0; + mode_lib->vba.FabricAndDRAMBandwidth = dml_min( + mode_lib->vba.DRAMSpeed * mode_lib->vba.NumberOfChannels + * mode_lib->vba.DRAMChannelWidth, + mode_lib->vba.FabricClock * mode_lib->vba.FabricDatapathToDCNDataReturn) + / 1000.0; // TODO: Must be consistent across all pipes // DCCProgrammingAssumesScanDirectionUnknown = src.dcc_scan_dir_unknown; @@ -633,16 +761,20 @@ static void recalculate(struct display_mode_lib *mode_lib) // in wm mode we pull the parameters needed from the display_e2e_pipe_params_st structs // rather than working them out as in recalculate_ms -static void recalculate_params(struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes) +static void recalculate_params( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) { // This is only safe to use memcmp because there are non-POD types in struct display_mode_lib if (memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 || num_pipes != mode_lib->vba.cache_num_pipes - || memcmp(pipes, mode_lib->vba.cache_pipes, sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { + || memcmp( + pipes, + mode_lib->vba.cache_pipes, + sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { mode_lib->vba.soc = mode_lib->soc; mode_lib->vba.ip = mode_lib->ip; mode_lib->vba.me = mode_lib->me; @@ -677,55 +809,70 @@ static void ModeSupportAndSystemConfiguration(struct display_mode_lib *mode_lib) // Total Available Pipes Support Check for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) total_pipes += mode_lib->vba.DPPPerPlane[k]; - ASSERT(total_pipes <= DC__NUM_DPP); + ASSERT(total_pipes <= DC__NUM_DPP__MAX); } -static double adjust_ReturnBW(struct display_mode_lib *mode_lib, double ReturnBW, bool DCCEnabledAnyPlane, double ReturnBandwidthToDCN) +static double adjust_ReturnBW( + struct display_mode_lib *mode_lib, + double ReturnBW, + bool DCCEnabledAnyPlane, + double ReturnBandwidthToDCN) { double CriticalCompression; - if (DCCEnabledAnyPlane && ReturnBandwidthToDCN > mode_lib->vba.DCFCLK * mode_lib->vba.ReturnBusWidth / 4.0) + if (DCCEnabledAnyPlane + && ReturnBandwidthToDCN + > mode_lib->vba.DCFCLK * mode_lib->vba.ReturnBusWidth / 4.0) ReturnBW = - dml_min(ReturnBW, - ReturnBandwidthToDCN * 4 - * (1.0 - - mode_lib->vba.UrgentLatency - / ((mode_lib->vba.ROBBufferSizeInKByte - - mode_lib->vba.PixelChunkSizeInKByte) - * 1024 - / ReturnBandwidthToDCN - - mode_lib->vba.DCFCLK - * mode_lib->vba.ReturnBusWidth - / 4) - + mode_lib->vba.UrgentLatency)); - - CriticalCompression = 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK * mode_lib->vba.UrgentLatency - / (ReturnBandwidthToDCN * mode_lib->vba.UrgentLatency - + (mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) * 1024); + dml_min( + ReturnBW, + ReturnBandwidthToDCN * 4 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 + / ReturnBandwidthToDCN + - mode_lib->vba.DCFCLK + * mode_lib->vba.ReturnBusWidth + / 4) + + mode_lib->vba.UrgentLatency)); + + CriticalCompression = 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK + * mode_lib->vba.UrgentLatency + / (ReturnBandwidthToDCN * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024); if (DCCEnabledAnyPlane && CriticalCompression > 1.0 && CriticalCompression < 4.0) ReturnBW = - dml_min(ReturnBW, - 4.0 * ReturnBandwidthToDCN - * (mode_lib->vba.ROBBufferSizeInKByte - - mode_lib->vba.PixelChunkSizeInKByte) - * 1024 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK - * mode_lib->vba.UrgentLatency - / dml_pow((ReturnBandwidthToDCN - * mode_lib->vba.UrgentLatency - + (mode_lib->vba.ROBBufferSizeInKByte - - mode_lib->vba.PixelChunkSizeInKByte) - * 1024), - 2)); + dml_min( + ReturnBW, + 4.0 * ReturnBandwidthToDCN + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLK + * mode_lib->vba.UrgentLatency + / dml_pow( + (ReturnBandwidthToDCN + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024), + 2)); return ReturnBW; } -static unsigned int dscceComputeDelay(unsigned int bpc, - double bpp, - unsigned int sliceWidth, - unsigned int numSlices, - enum output_format_class pixelFormat) +static unsigned int dscceComputeDelay( + unsigned int bpc, + double bpp, + unsigned int sliceWidth, + unsigned int numSlices, + enum output_format_class pixelFormat) { // valid bpc = source bits per component in the set of {8, 10, 12} // valid bpp = increments of 1/16 of a bit @@ -739,12 +886,12 @@ static unsigned int dscceComputeDelay(unsigned int bpc, unsigned int rcModelSize = 8192; // N422/N420 operate at 2 pixels per clock - unsigned int pixelsPerClock, lstall, D, initalXmitDelay, w, s, ix, wx, p, l0, a, ax, l, Delay, - pixels; + unsigned int pixelsPerClock, lstall, D, initalXmitDelay, w, s, ix, wx, p, l0, a, ax, l, + Delay, pixels; if (pixelFormat == dm_n422 || pixelFormat == dm_420) pixelsPerClock = 2; - // #all other modes operate at 1 pixel per clock + // #all other modes operate at 1 pixel per clock else pixelsPerClock = 1; @@ -859,66 +1006,67 @@ static unsigned int dscComputeDelay(enum output_format_class pixelFormat) return Delay; } -static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, - double DPPCLK, - double DISPCLK, - double PixelClock, - double DCFClkDeepSleep, - unsigned int DSCDelay, - unsigned int DPPPerPlane, - bool ScalerEnabled, - unsigned int NumberOfCursors, - double DPPCLKDelaySubtotal, - double DPPCLKDelaySCL, - double DPPCLKDelaySCLLBOnly, - double DPPCLKDelayCNVCFormater, - double DPPCLKDelayCNVCCursor, - double DISPCLKDelaySubtotal, - unsigned int ScalerRecoutWidth, - enum output_format_class OutputFormat, - unsigned int VBlank, - unsigned int HTotal, - unsigned int MaxInterDCNTileRepeaters, - unsigned int VStartup, - unsigned int PageTableLevels, - bool VirtualMemoryEnable, - bool DynamicMetadataEnable, - unsigned int DynamicMetadataLinesBeforeActiveRequired, - unsigned int DynamicMetadataTransmittedBytes, - bool DCCEnable, - double UrgentLatency, - double UrgentExtraLatency, - double TCalc, - unsigned int PDEAndMetaPTEBytesFrame, - unsigned int MetaRowByte, - unsigned int PixelPTEBytesPerRow, - double PrefetchSourceLinesY, - unsigned int SwathWidthY, - double BytePerPixelDETY, - double VInitPreFillY, - unsigned int MaxNumSwathY, - double PrefetchSourceLinesC, - double BytePerPixelDETC, - double VInitPreFillC, - unsigned int MaxNumSwathC, - unsigned int SwathHeightY, - unsigned int SwathHeightC, - double TWait, - bool XFCEnabled, - double XFCRemoteSurfaceFlipDelay, - bool InterlaceEnable, - bool ProgressiveToInterlaceUnitInOPP, - double *DSTXAfterScaler, - double *DSTYAfterScaler, - double *DestinationLinesForPrefetch, - double *PrefetchBandwidth, - double *DestinationLinesToRequestVMInVBlank, - double *DestinationLinesToRequestRowInVBlank, - double *VRatioPrefetchY, - double *VRatioPrefetchC, - double *RequiredPrefetchPixDataBW, - unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - double *Tno_bw) +static bool CalculatePrefetchSchedule( + struct display_mode_lib *mode_lib, + double DPPCLK, + double DISPCLK, + double PixelClock, + double DCFClkDeepSleep, + unsigned int DSCDelay, + unsigned int DPPPerPlane, + bool ScalerEnabled, + unsigned int NumberOfCursors, + double DPPCLKDelaySubtotal, + double DPPCLKDelaySCL, + double DPPCLKDelaySCLLBOnly, + double DPPCLKDelayCNVCFormater, + double DPPCLKDelayCNVCCursor, + double DISPCLKDelaySubtotal, + unsigned int ScalerRecoutWidth, + enum output_format_class OutputFormat, + unsigned int VBlank, + unsigned int HTotal, + unsigned int MaxInterDCNTileRepeaters, + unsigned int VStartup, + unsigned int PageTableLevels, + bool VirtualMemoryEnable, + bool DynamicMetadataEnable, + unsigned int DynamicMetadataLinesBeforeActiveRequired, + unsigned int DynamicMetadataTransmittedBytes, + bool DCCEnable, + double UrgentLatency, + double UrgentExtraLatency, + double TCalc, + unsigned int PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + double PrefetchSourceLinesY, + unsigned int SwathWidthY, + double BytePerPixelDETY, + double VInitPreFillY, + unsigned int MaxNumSwathY, + double PrefetchSourceLinesC, + double BytePerPixelDETC, + double VInitPreFillC, + unsigned int MaxNumSwathC, + unsigned int SwathHeightY, + unsigned int SwathHeightC, + double TWait, + bool XFCEnabled, + double XFCRemoteSurfaceFlipDelay, + bool InterlaceEnable, + bool ProgressiveToInterlaceUnitInOPP, + double *DSTXAfterScaler, + double *DSTYAfterScaler, + double *DestinationLinesForPrefetch, + double *PrefetchBandwidth, + double *DestinationLinesToRequestVMInVBlank, + double *DestinationLinesToRequestRowInVBlank, + double *VRatioPrefetchY, + double *VRatioPrefetchC, + double *RequiredPrefetchPixDataBW, + unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + double *Tno_bw) { bool MyError = false; unsigned int DPPCycles, DISPCLKCycles, VUpdateOffsetPix, VUpdateWidthPix, VReadyOffsetPix; @@ -948,7 +1096,7 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, return true; *DSTXAfterScaler = DPPCycles * PixelClock / DPPCLK + DISPCLKCycles * PixelClock / DISPCLK - + DSCDelay; + + DSCDelay; if (DPPPerPlane > 1) *DSTXAfterScaler = *DSTXAfterScaler + ScalerRecoutWidth; @@ -958,22 +1106,23 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, else *DSTYAfterScaler = 0; - DSTTotalPixelsAfterScaler = ((double)(*DSTYAfterScaler * HTotal)) + *DSTXAfterScaler; + DSTTotalPixelsAfterScaler = ((double) (*DSTYAfterScaler * HTotal)) + *DSTXAfterScaler; *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / HTotal, 1); - *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double)(*DSTYAfterScaler * HTotal)); + *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double) (*DSTYAfterScaler * HTotal)); VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); TotalRepeaterDelayTime = MaxInterDCNTileRepeaters * (2.0 / DPPCLK + 3.0 / DISPCLK); VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) - * PixelClock; + * PixelClock; - VReadyOffsetPix = dml_max(150.0 / DPPCLK, - TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) - * PixelClock; + VReadyOffsetPix = dml_max( + 150.0 / DPPCLK, + TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) + * PixelClock; - Tsetup = (double)(VUpdateOffsetPix + VUpdateWidthPix + VReadyOffsetPix) / PixelClock; + Tsetup = (double) (VUpdateOffsetPix + VUpdateWidthPix + VReadyOffsetPix) / PixelClock; - LineTime = (double)HTotal / PixelClock; + LineTime = (double) HTotal / PixelClock; if (DynamicMetadataEnable) { double Tdmbf, Tdmec, Tdmsks; @@ -988,10 +1137,10 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, if (InterlaceEnable && !ProgressiveToInterlaceUnitInOPP) Tdmsks = Tdmsks / 2; if (VStartup * LineTime - < Tsetup + TWait + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) { + < Tsetup + TWait + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) { MyError = true; *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = (Tsetup + TWait - + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) / LineTime; + + UrgentExtraLatency + Tdmbf + Tdmec + Tdmsks) / LineTime; } else *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata = 0.0; } else @@ -1010,30 +1159,33 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, *Tno_bw = LineTime / 4; dst_y_prefetch_equ = VStartup - dml_max(TCalc + TWait, XFCRemoteSurfaceFlipDelay) / LineTime - - (Tsetup + Tdm) / LineTime - - (*DSTYAfterScaler + *DSTXAfterScaler / HTotal); + - (Tsetup + Tdm) / LineTime + - (*DSTYAfterScaler + *DSTXAfterScaler / HTotal); Tsw_oto = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; prefetch_bw_oto = (MetaRowByte + PixelPTEBytesPerRow - + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) - + PrefetchSourceLinesC * SwathWidthY / 2 * dml_ceil(BytePerPixelDETC, 2)) - / Tsw_oto; + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 * dml_ceil(BytePerPixelDETC, 2)) + / Tsw_oto; if (VirtualMemoryEnable == true) { Tvm_oto = - dml_max(*Tno_bw + PDEAndMetaPTEBytesFrame / prefetch_bw_oto, - dml_max(UrgentExtraLatency - + UrgentLatency - * (PageTableLevels - - 1), - LineTime / 4.0)); + dml_max( + *Tno_bw + PDEAndMetaPTEBytesFrame / prefetch_bw_oto, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4.0)); } else Tvm_oto = LineTime / 4.0; if ((VirtualMemoryEnable == true || DCCEnable == true)) { - Tr0_oto = dml_max((MetaRowByte + PixelPTEBytesPerRow) / prefetch_bw_oto, - dml_max(UrgentLatency, dml_max(LineTime - Tvm_oto, LineTime / 4))); + Tr0_oto = dml_max( + (MetaRowByte + PixelPTEBytesPerRow) / prefetch_bw_oto, + dml_max(UrgentLatency, dml_max(LineTime - Tvm_oto, LineTime / 4))); } else Tr0_oto = LineTime - Tvm_oto; @@ -1046,7 +1198,8 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, else *DestinationLinesForPrefetch = dst_y_prefetch_equ; - *DestinationLinesForPrefetch = dml_floor(4.0 * (*DestinationLinesForPrefetch + 0.125), 1) / 4; + *DestinationLinesForPrefetch = dml_floor(4.0 * (*DestinationLinesForPrefetch + 0.125), 1) + / 4; dml_print("DML: VStartup: %d\n", VStartup); dml_print("DML: TCalc: %f\n", TCalc); @@ -1067,21 +1220,23 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, *RequiredPrefetchPixDataBW = 0; if (*DestinationLinesForPrefetch > 1) { *PrefetchBandwidth = (PDEAndMetaPTEBytesFrame + 2 * MetaRowByte - + 2 * PixelPTEBytesPerRow - + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) - + PrefetchSourceLinesC * SwathWidthY / 2 - * dml_ceil(BytePerPixelDETC, 2)) - / (*DestinationLinesForPrefetch * LineTime - *Tno_bw); + + 2 * PixelPTEBytesPerRow + + PrefetchSourceLinesY * SwathWidthY * dml_ceil(BytePerPixelDETY, 1) + + PrefetchSourceLinesC * SwathWidthY / 2 + * dml_ceil(BytePerPixelDETC, 2)) + / (*DestinationLinesForPrefetch * LineTime - *Tno_bw); if (VirtualMemoryEnable) { TimeForFetchingMetaPTE = - dml_max(*Tno_bw - + (double)PDEAndMetaPTEBytesFrame - / *PrefetchBandwidth, - dml_max(UrgentExtraLatency - + UrgentLatency - * (PageTableLevels - - 1), - LineTime / 4)); + dml_max( + *Tno_bw + + (double) PDEAndMetaPTEBytesFrame + / *PrefetchBandwidth, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (PageTableLevels + - 1), + LineTime / 4)); } else { if (NumberOfCursors > 0 || XFCEnabled) TimeForFetchingMetaPTE = LineTime / 4; @@ -1091,13 +1246,16 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, if ((VirtualMemoryEnable == true || DCCEnable == true)) { TimeForFetchingRowInVBlank = - dml_max((MetaRowByte + PixelPTEBytesPerRow) - / *PrefetchBandwidth, - dml_max(UrgentLatency, - dml_max(LineTime - - TimeForFetchingMetaPTE, - LineTime - / 4.0))); + dml_max( + (MetaRowByte + PixelPTEBytesPerRow) + / *PrefetchBandwidth, + dml_max( + UrgentLatency, + dml_max( + LineTime + - TimeForFetchingMetaPTE, + LineTime + / 4.0))); } else { if (NumberOfCursors > 0 || XFCEnabled) TimeForFetchingRowInVBlank = LineTime - TimeForFetchingMetaPTE; @@ -1105,36 +1263,39 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, TimeForFetchingRowInVBlank = 0.0; } - *DestinationLinesToRequestVMInVBlank = dml_floor(4.0 * (TimeForFetchingMetaPTE / LineTime + 0.125), - 1) / 4.0; + *DestinationLinesToRequestVMInVBlank = dml_floor( + 4.0 * (TimeForFetchingMetaPTE / LineTime + 0.125), + 1) / 4.0; - *DestinationLinesToRequestRowInVBlank = dml_floor(4.0 * (TimeForFetchingRowInVBlank / LineTime + 0.125), - 1) / 4.0; + *DestinationLinesToRequestRowInVBlank = dml_floor( + 4.0 * (TimeForFetchingRowInVBlank / LineTime + 0.125), + 1) / 4.0; LinesToRequestPrefetchPixelData = - *DestinationLinesForPrefetch - - ((NumberOfCursors > 0 || VirtualMemoryEnable - || DCCEnable) ? - (*DestinationLinesToRequestVMInVBlank - + *DestinationLinesToRequestRowInVBlank) : - 0.0); + *DestinationLinesForPrefetch + - ((NumberOfCursors > 0 || VirtualMemoryEnable + || DCCEnable) ? + (*DestinationLinesToRequestVMInVBlank + + *DestinationLinesToRequestRowInVBlank) : + 0.0); if (LinesToRequestPrefetchPixelData > 0) { - *VRatioPrefetchY = (double)PrefetchSourceLinesY - / LinesToRequestPrefetchPixelData; + *VRatioPrefetchY = (double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData; *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); if ((SwathHeightY > 4) && (VInitPreFillY > 3)) { if (LinesToRequestPrefetchPixelData > (VInitPreFillY - 3.0) / 2.0) { *VRatioPrefetchY = - dml_max((double)PrefetchSourceLinesY - / LinesToRequestPrefetchPixelData, - (double)MaxNumSwathY - * SwathHeightY - / (LinesToRequestPrefetchPixelData - - (VInitPreFillY - - 3.0) - / 2.0)); + dml_max( + (double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData, + (double) MaxNumSwathY + * SwathHeightY + / (LinesToRequestPrefetchPixelData + - (VInitPreFillY + - 3.0) + / 2.0)); *VRatioPrefetchY = dml_max(*VRatioPrefetchY, 1.0); } else { MyError = true; @@ -1142,20 +1303,21 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, } } - *VRatioPrefetchC = (double)PrefetchSourceLinesC - / LinesToRequestPrefetchPixelData; + *VRatioPrefetchC = (double) PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData; *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); if ((SwathHeightC > 4)) { if (LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) { *VRatioPrefetchC = - dml_max(*VRatioPrefetchC, - (double)MaxNumSwathC - * SwathHeightC - / (LinesToRequestPrefetchPixelData - - (VInitPreFillC - - 3.0) - / 2.0)); + dml_max( + *VRatioPrefetchC, + (double) MaxNumSwathC + * SwathHeightC + / (LinesToRequestPrefetchPixelData + - (VInitPreFillC + - 3.0) + / 2.0)); *VRatioPrefetchC = dml_max(*VRatioPrefetchC, 1.0); } else { MyError = true; @@ -1164,17 +1326,19 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, } *RequiredPrefetchPixDataBW = - DPPPerPlane - * ((double)PrefetchSourceLinesY - / LinesToRequestPrefetchPixelData - * dml_ceil(BytePerPixelDETY, - 1) - + (double)PrefetchSourceLinesC - / LinesToRequestPrefetchPixelData - * dml_ceil(BytePerPixelDETC, - 2) - / 2) - * SwathWidthY / LineTime; + DPPPerPlane + * ((double) PrefetchSourceLinesY + / LinesToRequestPrefetchPixelData + * dml_ceil( + BytePerPixelDETY, + 1) + + (double) PrefetchSourceLinesC + / LinesToRequestPrefetchPixelData + * dml_ceil( + BytePerPixelDETC, + 2) + / 2) + * SwathWidthY / LineTime; } else { MyError = true; *VRatioPrefetchY = 0; @@ -1202,25 +1366,26 @@ static bool CalculatePrefetchSchedule(struct display_mode_lib *mode_lib, return MyError; } -static double CeilToDFSGranularity(double Clock, double VCOSpeed) +static double RoundToDFSGranularityUp(double Clock, double VCOSpeed) { return VCOSpeed * 4 / dml_floor(VCOSpeed * 4 / Clock, 1); } -static double FloorToDFSGranularity(double Clock, double VCOSpeed) +static double RoundToDFSGranularityDown(double Clock, double VCOSpeed) { return VCOSpeed * 4 / dml_ceil(VCOSpeed * 4 / Clock, 1); } -static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, - double VRatio, - double vtaps, - bool Interlace, - bool ProgressiveToInterlaceUnitInOPP, - unsigned int SwathHeight, - unsigned int ViewportYStart, - double *VInitPreFill, - unsigned int *MaxNumSwath) +static double CalculatePrefetchSourceLines( + struct display_mode_lib *mode_lib, + double VRatio, + double vtaps, + bool Interlace, + bool ProgressiveToInterlaceUnitInOPP, + unsigned int SwathHeight, + unsigned int ViewportYStart, + double *VInitPreFill, + unsigned int *MaxNumSwath) { unsigned int MaxPartialSwath; @@ -1234,50 +1399,54 @@ static double CalculatePrefetchSourceLines(struct display_mode_lib *mode_lib, *MaxNumSwath = dml_ceil((*VInitPreFill - 1.0) / SwathHeight, 1) + 1.0; if (*VInitPreFill > 1.0) - MaxPartialSwath = (unsigned int)(*VInitPreFill - 2) % SwathHeight; + MaxPartialSwath = (unsigned int) (*VInitPreFill - 2) % SwathHeight; else - MaxPartialSwath = (unsigned int)(*VInitPreFill + SwathHeight - 2) % SwathHeight; + MaxPartialSwath = (unsigned int) (*VInitPreFill + SwathHeight - 2) + % SwathHeight; MaxPartialSwath = dml_max(1U, MaxPartialSwath); } else { if (ViewportYStart != 0) - dml_print("WARNING DML: using viewport y position of 0 even though actual viewport y position is non-zero in prefetch source lines calculation\n"); + dml_print( + "WARNING DML: using viewport y position of 0 even though actual viewport y position is non-zero in prefetch source lines calculation\n"); *MaxNumSwath = dml_ceil(*VInitPreFill / SwathHeight, 1); if (*VInitPreFill > 1.0) - MaxPartialSwath = (unsigned int)(*VInitPreFill - 1) % SwathHeight; + MaxPartialSwath = (unsigned int) (*VInitPreFill - 1) % SwathHeight; else - MaxPartialSwath = (unsigned int)(*VInitPreFill + SwathHeight - 1) % SwathHeight; + MaxPartialSwath = (unsigned int) (*VInitPreFill + SwathHeight - 1) + % SwathHeight; } return *MaxNumSwath * SwathHeight + MaxPartialSwath; } -static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, - bool DCCEnable, - unsigned int BlockHeight256Bytes, - unsigned int BlockWidth256Bytes, - enum source_format_class SourcePixelFormat, - unsigned int SurfaceTiling, - unsigned int BytePerPixel, - enum scan_direction_class ScanDirection, - unsigned int ViewportWidth, - unsigned int ViewportHeight, - unsigned int SwathWidth, - bool VirtualMemoryEnable, - unsigned int VMMPageSize, - unsigned int PTEBufferSizeInRequests, - unsigned int PDEProcessingBufIn64KBReqs, - unsigned int Pitch, - unsigned int DCCMetaPitch, - unsigned int *MacroTileWidth, - unsigned int *MetaRowByte, - unsigned int *PixelPTEBytesPerRow, - bool *PTEBufferSizeNotExceeded, - unsigned int *dpte_row_height, - unsigned int *meta_row_height) +static unsigned int CalculateVMAndRowBytes( + struct display_mode_lib *mode_lib, + bool DCCEnable, + unsigned int BlockHeight256Bytes, + unsigned int BlockWidth256Bytes, + enum source_format_class SourcePixelFormat, + unsigned int SurfaceTiling, + unsigned int BytePerPixel, + enum scan_direction_class ScanDirection, + unsigned int ViewportWidth, + unsigned int ViewportHeight, + unsigned int SwathWidth, + bool VirtualMemoryEnable, + unsigned int VMMPageSize, + unsigned int PTEBufferSizeInRequests, + unsigned int PDEProcessingBufIn64KBReqs, + unsigned int Pitch, + unsigned int DCCMetaPitch, + unsigned int *MacroTileWidth, + unsigned int *MetaRowByte, + unsigned int *PixelPTEBytesPerRow, + bool *PTEBufferSizeNotExceeded, + unsigned int *dpte_row_height, + unsigned int *meta_row_height) { unsigned int MetaRequestHeight; unsigned int MetaRequestWidth; @@ -1298,31 +1467,33 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, MetaRequestWidth = 8 * BlockWidth256Bytes; if (ScanDirection == dm_horz) { *meta_row_height = MetaRequestHeight; - MetaSurfWidth = dml_ceil((double)SwathWidth - 1, MetaRequestWidth) - + MetaRequestWidth; + MetaSurfWidth = dml_ceil((double) SwathWidth - 1, MetaRequestWidth) + + MetaRequestWidth; *MetaRowByte = MetaSurfWidth * MetaRequestHeight * BytePerPixel / 256.0; } else { *meta_row_height = MetaRequestWidth; - MetaSurfHeight = dml_ceil((double)SwathWidth - 1, MetaRequestHeight) - + MetaRequestHeight; + MetaSurfHeight = dml_ceil((double) SwathWidth - 1, MetaRequestHeight) + + MetaRequestHeight; *MetaRowByte = MetaSurfHeight * MetaRequestWidth * BytePerPixel / 256.0; } if (ScanDirection == dm_horz) { DCCMetaSurfaceBytes = DCCMetaPitch - * (dml_ceil(ViewportHeight - 1, 64 * BlockHeight256Bytes) - + 64 * BlockHeight256Bytes) * BytePerPixel - / 256; + * (dml_ceil(ViewportHeight - 1, 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; } else { DCCMetaSurfaceBytes = DCCMetaPitch - * (dml_ceil((double)ViewportHeight - 1, - 64 * BlockHeight256Bytes) - + 64 * BlockHeight256Bytes) * BytePerPixel - / 256; + * (dml_ceil( + (double) ViewportHeight - 1, + 64 * BlockHeight256Bytes) + + 64 * BlockHeight256Bytes) * BytePerPixel + / 256; } if (VirtualMemoryEnable == true) { - MetaPTEBytesFrame = (dml_ceil((double)(DCCMetaSurfaceBytes - VMMPageSize) - / (8 * VMMPageSize), - 1) + 1) * 64; + MetaPTEBytesFrame = (dml_ceil( + (double) (DCCMetaSurfaceBytes - VMMPageSize) + / (8 * VMMPageSize), + 1) + 1) * 64; MPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 1); } else { MetaPTEBytesFrame = 0; @@ -1338,13 +1509,13 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, MacroTileSizeBytes = 256; MacroTileHeight = 1; } else if (SurfaceTiling == dm_sw_4kb_s || SurfaceTiling == dm_sw_4kb_s_x - || SurfaceTiling == dm_sw_4kb_d || SurfaceTiling == dm_sw_4kb_d_x) { + || SurfaceTiling == dm_sw_4kb_d || SurfaceTiling == dm_sw_4kb_d_x) { MacroTileSizeBytes = 4096; MacroTileHeight = 4 * BlockHeight256Bytes; } else if (SurfaceTiling == dm_sw_64kb_s || SurfaceTiling == dm_sw_64kb_s_t - || SurfaceTiling == dm_sw_64kb_s_x || SurfaceTiling == dm_sw_64kb_d - || SurfaceTiling == dm_sw_64kb_d_t || SurfaceTiling == dm_sw_64kb_d_x - || SurfaceTiling == dm_sw_64kb_r_x) { + || SurfaceTiling == dm_sw_64kb_s_x || SurfaceTiling == dm_sw_64kb_d + || SurfaceTiling == dm_sw_64kb_d_t || SurfaceTiling == dm_sw_64kb_d_x + || SurfaceTiling == dm_sw_64kb_r_x) { MacroTileSizeBytes = 65536; MacroTileHeight = 16 * BlockHeight256Bytes; } else { @@ -1356,30 +1527,34 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, if (VirtualMemoryEnable == true && mode_lib->vba.MaxPageTableLevels > 1) { if (ScanDirection == dm_horz) { DPDE0BytesFrame = - 64 - * (dml_ceil(((Pitch - * (dml_ceil(ViewportHeight - - 1, - MacroTileHeight) - + MacroTileHeight) - * BytePerPixel) - - MacroTileSizeBytes) - / (8 - * 2097152), - 1) + 1); + 64 + * (dml_ceil( + ((Pitch + * (dml_ceil( + ViewportHeight + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); } else { DPDE0BytesFrame = - 64 - * (dml_ceil(((Pitch - * (dml_ceil((double)SwathWidth - - 1, - MacroTileHeight) - + MacroTileHeight) - * BytePerPixel) - - MacroTileSizeBytes) - / (8 - * 2097152), - 1) + 1); + 64 + * (dml_ceil( + ((Pitch + * (dml_ceil( + (double) SwathWidth + - 1, + MacroTileHeight) + + MacroTileHeight) + * BytePerPixel) + - MacroTileSizeBytes) + / (8 + * 2097152), + 1) + 1); } ExtraDPDEBytesFrame = 128 * (mode_lib->vba.MaxPageTableLevels - 2); } else { @@ -1388,7 +1563,7 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, } PDEAndMetaPTEBytesFrame = MetaPTEBytesFrame + MPDEBytesFrame + DPDE0BytesFrame - + ExtraDPDEBytesFrame; + + ExtraDPDEBytesFrame; if (VirtualMemoryEnable == true) { unsigned int PTERequestSize; @@ -1429,33 +1604,39 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, if (SurfaceTiling == dm_sw_linear) { *dpte_row_height = - dml_min(128, - 1 - << (unsigned int)dml_floor(dml_log2(dml_min((double)PTEBufferSizeInRequests - * PixelPTEReqWidth, - EffectivePDEProcessingBufIn64KBReqs - * 65536.0 - / BytePerPixel) - / Pitch), - 1)); + dml_min( + 128, + 1 + << (unsigned int) dml_floor( + dml_log2( + dml_min( + (double) PTEBufferSizeInRequests + * PixelPTEReqWidth, + EffectivePDEProcessingBufIn64KBReqs + * 65536.0 + / BytePerPixel) + / Pitch), + 1)); *PixelPTEBytesPerRow = PTERequestSize - * (dml_ceil((double)(Pitch * *dpte_row_height - 1) - / PixelPTEReqWidth, - 1) + 1); + * (dml_ceil( + (double) (Pitch * *dpte_row_height - 1) + / PixelPTEReqWidth, + 1) + 1); } else if (ScanDirection == dm_horz) { *dpte_row_height = PixelPTEReqHeight; *PixelPTEBytesPerRow = PTERequestSize - * (dml_ceil(((double)SwathWidth - 1) / PixelPTEReqWidth, 1) - + 1); + * (dml_ceil(((double) SwathWidth - 1) / PixelPTEReqWidth, 1) + + 1); } else { *dpte_row_height = dml_min(PixelPTEReqWidth, *MacroTileWidth); *PixelPTEBytesPerRow = PTERequestSize - * (dml_ceil(((double)SwathWidth - 1) - / PixelPTEReqHeight, - 1) + 1); + * (dml_ceil( + ((double) SwathWidth - 1) + / PixelPTEReqHeight, + 1) + 1); } if (*PixelPTEBytesPerRow * (1 - FractionOfPTEReturnDrop) - <= 64 * PTEBufferSizeInRequests) { + <= 64 * PTEBufferSizeInRequests) { *PTEBufferSizeNotExceeded = true; } else { *PTEBufferSizeNotExceeded = false; @@ -1468,7 +1649,8 @@ static unsigned int CalculateVMAndRowBytes(struct display_mode_lib *mode_lib, return PDEAndMetaPTEBytesFrame; } -static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation(struct display_mode_lib *mode_lib) +static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( + struct display_mode_lib *mode_lib) { unsigned int j, k; @@ -1481,81 +1663,107 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman // for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.WritebackEnable[k]) { - mode_lib->vba.WritebackDISPCLK = dml_max(mode_lib->vba.WritebackDISPCLK, - CalculateWriteBackDISPCLK(mode_lib->vba.WritebackPixelFormat[k], - mode_lib->vba.PixelClock[k], - mode_lib->vba.WritebackHRatio[k], - mode_lib->vba.WritebackVRatio[k], - mode_lib->vba.WritebackLumaHTaps[k], - mode_lib->vba.WritebackLumaVTaps[k], - mode_lib->vba.WritebackChromaHTaps[k], - mode_lib->vba.WritebackChromaVTaps[k], - mode_lib->vba.WritebackDestinationWidth[k], - mode_lib->vba.HTotal[k], - mode_lib->vba.WritebackChromaLineBufferWidth)); + mode_lib->vba.WritebackDISPCLK = + dml_max( + mode_lib->vba.WritebackDISPCLK, + CalculateWriteBackDISPCLK( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.PixelClock[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.WritebackChromaLineBufferWidth)); } } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.HRatio[k] > 1) { - mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, - mode_lib->vba.MaxPSCLToLBThroughput * mode_lib->vba.HRatio[k] - / dml_ceil(mode_lib->vba.htaps[k] / 6.0, 1)); + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / dml_ceil( + mode_lib->vba.htaps[k] + / 6.0, + 1)); } else { - mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, - mode_lib->vba.MaxPSCLToLBThroughput); + mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); } mode_lib->vba.DPPCLKUsingSingleDPPLuma = - mode_lib->vba.PixelClock[k] - * dml_max(mode_lib->vba.vtaps[k] / 6.0 - * dml_min(1.0, - mode_lib->vba.HRatio[k]), - dml_max(mode_lib->vba.HRatio[k] - * mode_lib->vba.VRatio[k] - / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k], - 1.0)); + mode_lib->vba.PixelClock[k] + * dml_max( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + dml_max( + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k], + 1.0)); if ((mode_lib->vba.htaps[k] > 6 || mode_lib->vba.vtaps[k] > 6) - && mode_lib->vba.DPPCLKUsingSingleDPPLuma < 2 * mode_lib->vba.PixelClock[k]) { + && mode_lib->vba.DPPCLKUsingSingleDPPLuma + < 2 * mode_lib->vba.PixelClock[k]) { mode_lib->vba.DPPCLKUsingSingleDPPLuma = 2 * mode_lib->vba.PixelClock[k]; } - if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = 0.0; - mode_lib->vba.DPPCLKUsingSingleDPP[k] = mode_lib->vba.DPPCLKUsingSingleDPPLuma; + mode_lib->vba.DPPCLKUsingSingleDPP[k] = + mode_lib->vba.DPPCLKUsingSingleDPPLuma; } else { if (mode_lib->vba.HRatio[k] > 1) { mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = - dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, - mode_lib->vba.MaxPSCLToLBThroughput * mode_lib->vba.HRatio[k] - / 2 - / dml_ceil(mode_lib->vba.HTAPsChroma[k] - / 6.0, - 1.0)); + dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / 2 + / dml_ceil( + mode_lib->vba.HTAPsChroma[k] + / 6.0, + 1.0)); } else { - mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = dml_min(mode_lib->vba.MaxDCHUBToPSCLThroughput, - mode_lib->vba.MaxPSCLToLBThroughput); + mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); } mode_lib->vba.DPPCLKUsingSingleDPPChroma = - mode_lib->vba.PixelClock[k] - * dml_max(mode_lib->vba.VTAPsChroma[k] / 6.0 - * dml_min(1.0, - mode_lib->vba.HRatio[k] - / 2), - dml_max(mode_lib->vba.HRatio[k] - * mode_lib->vba.VRatio[k] - / 4 - / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k], - 1.0)); + mode_lib->vba.PixelClock[k] + * dml_max( + mode_lib->vba.VTAPsChroma[k] + / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k] + / 2), + dml_max( + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / 4 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k], + 1.0)); if ((mode_lib->vba.HTAPsChroma[k] > 6 || mode_lib->vba.VTAPsChroma[k] > 6) - && mode_lib->vba.DPPCLKUsingSingleDPPChroma < 2 * mode_lib->vba.PixelClock[k]) { - mode_lib->vba.DPPCLKUsingSingleDPPChroma = 2 * mode_lib->vba.PixelClock[k]; + && mode_lib->vba.DPPCLKUsingSingleDPPChroma + < 2 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.DPPCLKUsingSingleDPPChroma = 2 + * mode_lib->vba.PixelClock[k]; } - mode_lib->vba.DPPCLKUsingSingleDPP[k] = dml_max(mode_lib->vba.DPPCLKUsingSingleDPPLuma, - mode_lib->vba.DPPCLKUsingSingleDPPChroma); + mode_lib->vba.DPPCLKUsingSingleDPP[k] = dml_max( + mode_lib->vba.DPPCLKUsingSingleDPPLuma, + mode_lib->vba.DPPCLKUsingSingleDPPChroma); } } @@ -1564,67 +1772,90 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman continue; if (mode_lib->vba.ODMCombineEnabled[k]) { mode_lib->vba.DISPCLKWithRamping = - dml_max(mode_lib->vba.DISPCLKWithRamping, - mode_lib->vba.PixelClock[k] / 2 - * (1 - + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading - / 100) - * (1 - + mode_lib->vba.DISPCLKRampingMargin - / 100)); + dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100) + * (1 + + mode_lib->vba.DISPCLKRampingMargin + / 100)); mode_lib->vba.DISPCLKWithoutRamping = - dml_max(mode_lib->vba.DISPCLKWithoutRamping, - mode_lib->vba.PixelClock[k] / 2 - * (1 - + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading - / 100)); + dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] / 2 + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); } else if (!mode_lib->vba.ODMCombineEnabled[k]) { - mode_lib->vba.DISPCLKWithRamping = dml_max(mode_lib->vba.DISPCLKWithRamping, - mode_lib->vba.PixelClock[k] * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100) - * (1 + mode_lib->vba.DISPCLKRampingMargin / 100)); + mode_lib->vba.DISPCLKWithRamping = + dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.PixelClock[k] + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100) + * (1 + + mode_lib->vba.DISPCLKRampingMargin + / 100)); mode_lib->vba.DISPCLKWithoutRamping = - dml_max(mode_lib->vba.DISPCLKWithoutRamping, - mode_lib->vba.PixelClock[k] - * (1 - + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading - / 100)); + dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.PixelClock[k] + * (1 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100)); } } - mode_lib->vba.DISPCLKWithRamping = dml_max(mode_lib->vba.DISPCLKWithRamping, mode_lib->vba.WritebackDISPCLK); - mode_lib->vba.DISPCLKWithoutRamping = dml_max(mode_lib->vba.DISPCLKWithoutRamping, mode_lib->vba.WritebackDISPCLK); + mode_lib->vba.DISPCLKWithRamping = dml_max( + mode_lib->vba.DISPCLKWithRamping, + mode_lib->vba.WritebackDISPCLK); + mode_lib->vba.DISPCLKWithoutRamping = dml_max( + mode_lib->vba.DISPCLKWithoutRamping, + mode_lib->vba.WritebackDISPCLK); - mode_lib->vba.MaxDispclk = mode_lib->vba.soc.clock_limits[NumberOfStates - 1].dispclk_mhz; ASSERT(mode_lib->vba.DISPCLKDPPCLKVCOSpeed != 0); - mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity = CeilToDFSGranularity( + mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity = RoundToDFSGranularityUp( mode_lib->vba.DISPCLKWithRamping, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); - mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity = CeilToDFSGranularity( + mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity = RoundToDFSGranularityUp( mode_lib->vba.DISPCLKWithoutRamping, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); - mode_lib->vba.MaxDispclkRoundedToDFSGranularity = FloorToDFSGranularity( - mode_lib->vba.MaxDispclk, + mode_lib->vba.MaxDispclkRoundedToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.soc.clock_limits[NumberOfStates - 1].dispclk_mhz, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); if (mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity - > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { - mode_lib->vba.DISPCLK_calculated = mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity; + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + mode_lib->vba.DISPCLK_calculated = + mode_lib->vba.DISPCLKWithoutRampingRoundedToDFSGranularity; } else if (mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity - > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { + > mode_lib->vba.MaxDispclkRoundedToDFSGranularity) { mode_lib->vba.DISPCLK_calculated = mode_lib->vba.MaxDispclkRoundedToDFSGranularity; } else { - mode_lib->vba.DISPCLK_calculated = mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity; + mode_lib->vba.DISPCLK_calculated = + mode_lib->vba.DISPCLKWithRampingRoundedToDFSGranularity; } DTRACE(" dispclk_mhz (calculated) = %f", mode_lib->vba.DISPCLK_calculated); for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.DPPCLKUsingSingleDPP[k] / mode_lib->vba.DPPPerPlane[k] - * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); - mode_lib->vba.GlobalDPPCLK = dml_max(mode_lib->vba.GlobalDPPCLK, mode_lib->vba.DPPCLK_calculated[k]); + mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.DPPCLKUsingSingleDPP[k] + / mode_lib->vba.DPPPerPlane[k] + * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.GlobalDPPCLK = dml_max( + mode_lib->vba.GlobalDPPCLK, + mode_lib->vba.DPPCLK_calculated[k]); } - mode_lib->vba.GlobalDPPCLK = CeilToDFSGranularity(mode_lib->vba.GlobalDPPCLK, mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.GlobalDPPCLK = RoundToDFSGranularityUp( + mode_lib->vba.GlobalDPPCLK, + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.DPPCLK_calculated[k] = mode_lib->vba.GlobalDPPCLK / 255 - * dml_ceil(mode_lib->vba.DPPCLK_calculated[k] * 255 / mode_lib->vba.GlobalDPPCLK, 1); + * dml_ceil( + mode_lib->vba.DPPCLK_calculated[k] * 255 + / mode_lib->vba.GlobalDPPCLK, + 1); DTRACE(" dppclk_mhz[%i] (calculated) = %f", k, mode_lib->vba.DPPCLK_calculated[k]); } @@ -1634,15 +1865,27 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.DCCEnable[k]) mode_lib->vba.DCCEnabledAnyPlane = true; - mode_lib->vba.ReturnBandwidthToDCN = dml_min(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, mode_lib->vba.FabricAndDRAMBandwidth * 1000) - * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency / 100; + mode_lib->vba.ReturnBandwidthToDCN = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, + mode_lib->vba.FabricAndDRAMBandwidth * 1000) + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency / 100; mode_lib->vba.ReturnBW = mode_lib->vba.ReturnBandwidthToDCN; - mode_lib->vba.ReturnBW = adjust_ReturnBW(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.DCCEnabledAnyPlane, mode_lib->vba.ReturnBandwidthToDCN); + mode_lib->vba.ReturnBW = adjust_ReturnBW( + mode_lib, + mode_lib->vba.ReturnBW, + mode_lib->vba.DCCEnabledAnyPlane, + mode_lib->vba.ReturnBandwidthToDCN); // Let's do this calculation again?? - mode_lib->vba.ReturnBandwidthToDCN = dml_min(mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, mode_lib->vba.FabricAndDRAMBandwidth * 1000); - mode_lib->vba.ReturnBW = adjust_ReturnBW(mode_lib, mode_lib->vba.ReturnBW, mode_lib->vba.DCCEnabledAnyPlane, mode_lib->vba.ReturnBandwidthToDCN); + mode_lib->vba.ReturnBandwidthToDCN = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLK, + mode_lib->vba.FabricAndDRAMBandwidth * 1000); + mode_lib->vba.ReturnBW = adjust_ReturnBW( + mode_lib, + mode_lib->vba.ReturnBW, + mode_lib->vba.DCCEnabledAnyPlane, + mode_lib->vba.ReturnBandwidthToDCN); DTRACE(" dcfclk_mhz = %f", mode_lib->vba.DCFCLK); DTRACE(" return_bw_to_dcn = %f", mode_lib->vba.ReturnBandwidthToDCN); @@ -1659,14 +1902,19 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.ODMCombineEnabled[k] == true) MainPlaneDoesODMCombine = true; for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) - if (mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.ODMCombineEnabled[j] == true) + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.ODMCombineEnabled[j] == true) MainPlaneDoesODMCombine = true; if (MainPlaneDoesODMCombine == true) - mode_lib->vba.SwathWidthY[k] = dml_min((double)mode_lib->vba.SwathWidthSingleDPPY[k], - dml_round(mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k])); + mode_lib->vba.SwathWidthY[k] = dml_min( + (double) mode_lib->vba.SwathWidthSingleDPPY[k], + dml_round( + mode_lib->vba.HActive[k] / 2.0 + * mode_lib->vba.HRatio[k])); else - mode_lib->vba.SwathWidthY[k] = mode_lib->vba.SwathWidthSingleDPPY[k] / mode_lib->vba.DPPPerPlane[k]; + mode_lib->vba.SwathWidthY[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + / mode_lib->vba.DPPPerPlane[k]; } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { @@ -1694,76 +1942,104 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.TotalDataReadBandwidth = 0.0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.ReadBandwidthPlaneLuma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] - * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) - * mode_lib->vba.VRatio[k]; - mode_lib->vba.ReadBandwidthPlaneChroma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] / 2 - * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) - * mode_lib->vba.VRatio[k] / 2; - DTRACE(" read_bw[%i] = %fBps", - k, - mode_lib->vba.ReadBandwidthPlaneLuma[k] + mode_lib->vba.ReadBandwidthPlaneChroma[k]); + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + mode_lib->vba.ReadBandwidthPlaneChroma[k] = mode_lib->vba.SwathWidthSingleDPPY[k] + / 2 * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k] / 2; + DTRACE( + " read_bw[%i] = %fBps", + k, + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k]); mode_lib->vba.TotalDataReadBandwidth += mode_lib->vba.ReadBandwidthPlaneLuma[k] - + mode_lib->vba.ReadBandwidthPlaneChroma[k]; + + mode_lib->vba.ReadBandwidthPlaneChroma[k]; } mode_lib->vba.TotalDCCActiveDPP = 0; mode_lib->vba.TotalActiveDPP = 0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP + mode_lib->vba.DPPPerPlane[k]; + mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP + + mode_lib->vba.DPPPerPlane[k]; if (mode_lib->vba.DCCEnable[k]) - mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP + mode_lib->vba.DPPPerPlane[k]; + mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP + + mode_lib->vba.DPPPerPlane[k]; } - mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency = (mode_lib->vba.RoundTripPingLatencyCycles + 32) / mode_lib->vba.DCFCLK - + mode_lib->vba.UrgentOutOfOrderReturnPerChannel * mode_lib->vba.NumberOfChannels / mode_lib->vba.ReturnBW; + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency = + (mode_lib->vba.RoundTripPingLatencyCycles + 32) / mode_lib->vba.DCFCLK + + mode_lib->vba.UrgentOutOfOrderReturnPerChannel + * mode_lib->vba.NumberOfChannels + / mode_lib->vba.ReturnBW; mode_lib->vba.LastPixelOfLineExtraWatermark = 0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { double DataFabricLineDeliveryTimeLuma, DataFabricLineDeliveryTimeChroma; if (mode_lib->vba.VRatio[k] <= 1.0) - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = (double)mode_lib->vba.SwathWidthY[k] - * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] / mode_lib->vba.PixelClock[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = + (double) mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; else - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = (double)mode_lib->vba.SwathWidthY[k] - / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] / mode_lib->vba.DPPCLK[k]; - - DataFabricLineDeliveryTimeLuma = - mode_lib->vba.SwathWidthSingleDPPY[k] * mode_lib->vba.SwathHeightY[k] - * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) - / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneLuma[k] - / mode_lib->vba.TotalDataReadBandwidth); - mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max(mode_lib->vba.LastPixelOfLineExtraWatermark, - DataFabricLineDeliveryTimeLuma - - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]); + mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k] = + (double) mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; + + DataFabricLineDeliveryTimeLuma = mode_lib->vba.SwathWidthSingleDPPY[k] + * mode_lib->vba.SwathHeightY[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) + / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneLuma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max( + mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeLuma + - mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]); if (mode_lib->vba.BytePerPixelDETC[k] == 0) mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = 0.0; else if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0) - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = mode_lib->vba.SwathWidthY[k] / 2.0 - * mode_lib->vba.DPPPerPlane[k] / (mode_lib->vba.HRatio[k] / 2.0) / mode_lib->vba.PixelClock[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = + mode_lib->vba.SwathWidthY[k] / 2.0 + * mode_lib->vba.DPPPerPlane[k] + / (mode_lib->vba.HRatio[k] / 2.0) + / mode_lib->vba.PixelClock[k]; else - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = mode_lib->vba.SwathWidthY[k] / 2.0 - / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] / mode_lib->vba.DPPCLK[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k] = + mode_lib->vba.SwathWidthY[k] / 2.0 + / mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] + / mode_lib->vba.DPPCLK[k]; DataFabricLineDeliveryTimeChroma = mode_lib->vba.SwathWidthSingleDPPY[k] / 2.0 - * mode_lib->vba.SwathHeightC[k] * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) - / (mode_lib->vba.ReturnBW * mode_lib->vba.ReadBandwidthPlaneChroma[k] - / mode_lib->vba.TotalDataReadBandwidth); - mode_lib->vba.LastPixelOfLineExtraWatermark = dml_max(mode_lib->vba.LastPixelOfLineExtraWatermark, - DataFabricLineDeliveryTimeChroma - - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + * mode_lib->vba.SwathHeightC[k] + * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) + / (mode_lib->vba.ReturnBW + * mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.TotalDataReadBandwidth); + mode_lib->vba.LastPixelOfLineExtraWatermark = + dml_max( + mode_lib->vba.LastPixelOfLineExtraWatermark, + DataFabricLineDeliveryTimeChroma + - mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); } mode_lib->vba.UrgentExtraLatency = mode_lib->vba.UrgentRoundTripAndOutOfOrderLatency - + (mode_lib->vba.TotalActiveDPP * mode_lib->vba.PixelChunkSizeInKByte - + mode_lib->vba.TotalDCCActiveDPP * mode_lib->vba.MetaChunkSize) * 1024.0 - / mode_lib->vba.ReturnBW; + + (mode_lib->vba.TotalActiveDPP * mode_lib->vba.PixelChunkSizeInKByte + + mode_lib->vba.TotalDCCActiveDPP + * mode_lib->vba.MetaChunkSize) * 1024.0 + / mode_lib->vba.ReturnBW; if (mode_lib->vba.VirtualMemoryEnable) - mode_lib->vba.UrgentExtraLatency += mode_lib->vba.TotalActiveDPP * mode_lib->vba.PTEChunkSize * 1024.0 / mode_lib->vba.ReturnBW; + mode_lib->vba.UrgentExtraLatency += mode_lib->vba.TotalActiveDPP + * mode_lib->vba.PTEChunkSize * 1024.0 / mode_lib->vba.ReturnBW; - mode_lib->vba.UrgentWatermark = mode_lib->vba.UrgentLatency + mode_lib->vba.LastPixelOfLineExtraWatermark + mode_lib->vba.UrgentExtraLatency; + mode_lib->vba.UrgentWatermark = mode_lib->vba.UrgentLatency + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency; DTRACE(" urgent_extra_latency = %fus", mode_lib->vba.UrgentExtraLatency); DTRACE(" wm_urgent = %fus", mode_lib->vba.UrgentWatermark); @@ -1780,12 +2056,14 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency; else mode_lib->vba.WritebackUrgentWatermark = mode_lib->vba.WritebackLatency - + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 / mode_lib->vba.SOCCLK; + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 + / mode_lib->vba.SOCCLK; DTRACE(" wm_wb_urgent = %fus", mode_lib->vba.WritebackUrgentWatermark); // NB P-State/DRAM Clock Change Watermark - mode_lib->vba.DRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.UrgentWatermark; + mode_lib->vba.DRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.UrgentWatermark; DTRACE(" wm_pstate_change = %fus", mode_lib->vba.DRAMClockChangeWatermark); @@ -1794,28 +2072,42 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman DTRACE(" socclk frequency %f Mhz", mode_lib->vba.SOCCLK); if (mode_lib->vba.TotalActiveWriteback <= 1) - mode_lib->vba.WritebackDRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.WritebackLatency; + mode_lib->vba.WritebackDRAMClockChangeWatermark = + mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.WritebackLatency; else - mode_lib->vba.WritebackDRAMClockChangeWatermark = mode_lib->vba.DRAMClockChangeLatency + mode_lib->vba.WritebackLatency - + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 / mode_lib->vba.SOCCLK; + mode_lib->vba.WritebackDRAMClockChangeWatermark = + mode_lib->vba.DRAMClockChangeLatency + + mode_lib->vba.WritebackLatency + + mode_lib->vba.WritebackChunkSize * 1024.0 / 32 + / mode_lib->vba.SOCCLK; DTRACE(" wm_wb_pstate %fus", mode_lib->vba.WritebackDRAMClockChangeWatermark); // Stutter Efficiency for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - mode_lib->vba.LinesInDETY[k] = mode_lib->vba.DETBufferSizeY[k] / mode_lib->vba.BytePerPixelDETY[k] - / mode_lib->vba.SwathWidthY[k]; - mode_lib->vba.LinesInDETYRoundedDownToSwath[k] = dml_floor(mode_lib->vba.LinesInDETY[k], - mode_lib->vba.SwathHeightY[k]); - mode_lib->vba.FullDETBufferingTimeY[k] = mode_lib->vba.LinesInDETYRoundedDownToSwath[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / mode_lib->vba.VRatio[k]; + mode_lib->vba.LinesInDETY[k] = mode_lib->vba.DETBufferSizeY[k] + / mode_lib->vba.BytePerPixelDETY[k] / mode_lib->vba.SwathWidthY[k]; + mode_lib->vba.LinesInDETYRoundedDownToSwath[k] = dml_floor( + mode_lib->vba.LinesInDETY[k], + mode_lib->vba.SwathHeightY[k]); + mode_lib->vba.FullDETBufferingTimeY[k] = + mode_lib->vba.LinesInDETYRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k]; if (mode_lib->vba.BytePerPixelDETC[k] > 0) { - mode_lib->vba.LinesInDETC[k] = mode_lib->vba.DETBufferSizeC[k] / mode_lib->vba.BytePerPixelDETC[k] - / (mode_lib->vba.SwathWidthY[k] / 2); - mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = dml_floor(mode_lib->vba.LinesInDETC[k], - mode_lib->vba.SwathHeightC[k]); - mode_lib->vba.FullDETBufferingTimeC[k] = mode_lib->vba.LinesInDETCRoundedDownToSwath[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / (mode_lib->vba.VRatio[k] / 2); + mode_lib->vba.LinesInDETC[k] = mode_lib->vba.DETBufferSizeC[k] + / mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.SwathWidthY[k] / 2); + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = dml_floor( + mode_lib->vba.LinesInDETC[k], + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.FullDETBufferingTimeC[k] = + mode_lib->vba.LinesInDETCRoundedDownToSwath[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] / 2); } else { mode_lib->vba.LinesInDETC[k] = 0; mode_lib->vba.LinesInDETCRoundedDownToSwath[k] = 0; @@ -1825,15 +2117,21 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.MinFullDETBufferingTime = 999999.0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - if (mode_lib->vba.FullDETBufferingTimeY[k] < mode_lib->vba.MinFullDETBufferingTime) { - mode_lib->vba.MinFullDETBufferingTime = mode_lib->vba.FullDETBufferingTimeY[k]; - mode_lib->vba.FrameTimeForMinFullDETBufferingTime = (double)mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]; + if (mode_lib->vba.FullDETBufferingTimeY[k] + < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = + mode_lib->vba.FullDETBufferingTimeY[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = + (double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; } - if (mode_lib->vba.FullDETBufferingTimeC[k] < mode_lib->vba.MinFullDETBufferingTime) { - mode_lib->vba.MinFullDETBufferingTime = mode_lib->vba.FullDETBufferingTimeC[k]; - mode_lib->vba.FrameTimeForMinFullDETBufferingTime = (double)mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]; + if (mode_lib->vba.FullDETBufferingTimeC[k] + < mode_lib->vba.MinFullDETBufferingTime) { + mode_lib->vba.MinFullDETBufferingTime = + mode_lib->vba.FullDETBufferingTimeC[k]; + mode_lib->vba.FrameTimeForMinFullDETBufferingTime = + (double) mode_lib->vba.VTotal[k] * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; } } @@ -1841,45 +2139,58 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.DCCEnable[k]) { mode_lib->vba.AverageReadBandwidthGBytePerSecond = - mode_lib->vba.AverageReadBandwidthGBytePerSecond - + mode_lib->vba.ReadBandwidthPlaneLuma[k] / mode_lib->vba.DCCRate[k] - / 1000 - + mode_lib->vba.ReadBandwidthPlaneChroma[k] - / mode_lib->vba.DCCRate[k] / 1000; + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / mode_lib->vba.DCCRate[k] + / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / mode_lib->vba.DCCRate[k] + / 1000; } else { mode_lib->vba.AverageReadBandwidthGBytePerSecond = - mode_lib->vba.AverageReadBandwidthGBytePerSecond - + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 - + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000; + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000; } if (mode_lib->vba.DCCEnable[k]) { mode_lib->vba.AverageReadBandwidthGBytePerSecond = - mode_lib->vba.AverageReadBandwidthGBytePerSecond - + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 / 256 - + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000 - / 256; + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 / 256 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000 / 256; } if (mode_lib->vba.VirtualMemoryEnable) { mode_lib->vba.AverageReadBandwidthGBytePerSecond = - mode_lib->vba.AverageReadBandwidthGBytePerSecond - + mode_lib->vba.ReadBandwidthPlaneLuma[k] / 1000 / 512 - + mode_lib->vba.ReadBandwidthPlaneChroma[k] / 1000 - / 512; + mode_lib->vba.AverageReadBandwidthGBytePerSecond + + mode_lib->vba.ReadBandwidthPlaneLuma[k] + / 1000 / 512 + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + / 1000 / 512; } } - mode_lib->vba.PartOfBurstThatFitsInROB = dml_min(mode_lib->vba.MinFullDETBufferingTime * mode_lib->vba.TotalDataReadBandwidth, - mode_lib->vba.ROBBufferSizeInKByte * 1024 * mode_lib->vba.TotalDataReadBandwidth - / (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000)); + mode_lib->vba.PartOfBurstThatFitsInROB = + dml_min( + mode_lib->vba.MinFullDETBufferingTime + * mode_lib->vba.TotalDataReadBandwidth, + mode_lib->vba.ROBBufferSizeInKByte * 1024 + * mode_lib->vba.TotalDataReadBandwidth + / (mode_lib->vba.AverageReadBandwidthGBytePerSecond + * 1000)); mode_lib->vba.StutterBurstTime = mode_lib->vba.PartOfBurstThatFitsInROB - * (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000) / mode_lib->vba.TotalDataReadBandwidth - / mode_lib->vba.ReturnBW - + (mode_lib->vba.MinFullDETBufferingTime * mode_lib->vba.TotalDataReadBandwidth - - mode_lib->vba.PartOfBurstThatFitsInROB) / (mode_lib->vba.DCFCLK * 64); + * (mode_lib->vba.AverageReadBandwidthGBytePerSecond * 1000) + / mode_lib->vba.TotalDataReadBandwidth / mode_lib->vba.ReturnBW + + (mode_lib->vba.MinFullDETBufferingTime + * mode_lib->vba.TotalDataReadBandwidth + - mode_lib->vba.PartOfBurstThatFitsInROB) + / (mode_lib->vba.DCFCLK * 64); if (mode_lib->vba.TotalActiveWriteback == 0) { mode_lib->vba.StutterEfficiencyNotIncludingVBlank = (1 - - (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime) / mode_lib->vba.MinFullDETBufferingTime) - * 100; + - (mode_lib->vba.SRExitTime + mode_lib->vba.StutterBurstTime) + / mode_lib->vba.MinFullDETBufferingTime) * 100; } else { mode_lib->vba.StutterEfficiencyNotIncludingVBlank = 0; } @@ -1887,47 +2198,66 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.SmallestVBlank = 999999; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { - mode_lib->vba.VBlankTime = (double)(mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k]) * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]; + mode_lib->vba.VBlankTime = (double) (mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k]) * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; } else { mode_lib->vba.VBlankTime = 0; } - mode_lib->vba.SmallestVBlank = dml_min(mode_lib->vba.SmallestVBlank, mode_lib->vba.VBlankTime); + mode_lib->vba.SmallestVBlank = dml_min( + mode_lib->vba.SmallestVBlank, + mode_lib->vba.VBlankTime); } mode_lib->vba.StutterEfficiency = (mode_lib->vba.StutterEfficiencyNotIncludingVBlank / 100 - * (mode_lib->vba.FrameTimeForMinFullDETBufferingTime - mode_lib->vba.SmallestVBlank) - + mode_lib->vba.SmallestVBlank) / mode_lib->vba.FrameTimeForMinFullDETBufferingTime * 100; + * (mode_lib->vba.FrameTimeForMinFullDETBufferingTime + - mode_lib->vba.SmallestVBlank) + + mode_lib->vba.SmallestVBlank) + / mode_lib->vba.FrameTimeForMinFullDETBufferingTime * 100; // dml_ml->vba.DCFCLK Deep Sleep mode_lib->vba.DCFClkDeepSleep = 8.0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; k++) { if (mode_lib->vba.BytePerPixelDETC[k] > 0) { - mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max(1.1 * mode_lib->vba.SwathWidthY[k] - * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 32 - / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k], - 1.1 * mode_lib->vba.SwathWidthY[k] / 2.0 - * dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2) / 32 - / mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); + mode_lib->vba.DCFCLKDeepSleepPerPlane = + dml_max( + 1.1 * mode_lib->vba.SwathWidthY[k] + * dml_ceil( + mode_lib->vba.BytePerPixelDETY[k], + 1) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k], + 1.1 * mode_lib->vba.SwathWidthY[k] / 2.0 + * dml_ceil( + mode_lib->vba.BytePerPixelDETC[k], + 2) / 32 + / mode_lib->vba.DisplayPipeLineDeliveryTimeChroma[k]); } else mode_lib->vba.DCFCLKDeepSleepPerPlane = 1.1 * mode_lib->vba.SwathWidthY[k] - * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 64.0 - / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]; - mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max(mode_lib->vba.DCFCLKDeepSleepPerPlane, - mode_lib->vba.PixelClock[k] / 16.0); - mode_lib->vba.DCFClkDeepSleep = dml_max(mode_lib->vba.DCFClkDeepSleep, mode_lib->vba.DCFCLKDeepSleepPerPlane); + * dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1) / 64.0 + / mode_lib->vba.DisplayPipeLineDeliveryTimeLuma[k]; + mode_lib->vba.DCFCLKDeepSleepPerPlane = dml_max( + mode_lib->vba.DCFCLKDeepSleepPerPlane, + mode_lib->vba.PixelClock[k] / 16.0); + mode_lib->vba.DCFClkDeepSleep = dml_max( + mode_lib->vba.DCFClkDeepSleep, + mode_lib->vba.DCFCLKDeepSleepPerPlane); - DTRACE(" dcfclk_deepsleep_per_plane[%i] = %fMHz", k, mode_lib->vba.DCFCLKDeepSleepPerPlane); + DTRACE( + " dcfclk_deepsleep_per_plane[%i] = %fMHz", + k, + mode_lib->vba.DCFCLKDeepSleepPerPlane); } DTRACE(" dcfclk_deepsleep_mhz = %fMHz", mode_lib->vba.DCFClkDeepSleep); // Stutter Watermark - mode_lib->vba.StutterExitWatermark = mode_lib->vba.SRExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark + mode_lib->vba.UrgentExtraLatency - + 10 / mode_lib->vba.DCFClkDeepSleep; - mode_lib->vba.StutterEnterPlusExitWatermark = mode_lib->vba.SREnterPlusExitTime + mode_lib->vba.LastPixelOfLineExtraWatermark - + mode_lib->vba.UrgentExtraLatency; + mode_lib->vba.StutterExitWatermark = mode_lib->vba.SRExitTime + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency + 10 / mode_lib->vba.DCFClkDeepSleep; + mode_lib->vba.StutterEnterPlusExitWatermark = mode_lib->vba.SREnterPlusExitTime + + mode_lib->vba.LastPixelOfLineExtraWatermark + + mode_lib->vba.UrgentExtraLatency; DTRACE(" wm_cstate_exit = %fus", mode_lib->vba.StutterExitWatermark); DTRACE(" wm_cstate_enter_exit = %fus", mode_lib->vba.StutterEnterPlusExitWatermark); @@ -1935,72 +2265,95 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman // Urgent Latency Supported for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.EffectiveDETPlusLBLinesLuma = - dml_floor(mode_lib->vba.LinesInDETY[k] - + dml_min(mode_lib->vba.LinesInDETY[k] - * mode_lib->vba.DPPCLK[k] - * mode_lib->vba.BytePerPixelDETY[k] - * mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] - / (mode_lib->vba.ReturnBW - / mode_lib->vba.DPPPerPlane[k]), - (double)mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), - mode_lib->vba.SwathHeightY[k]); + dml_floor( + mode_lib->vba.LinesInDETY[k] + + dml_min( + mode_lib->vba.LinesInDETY[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETY[k] + * mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double) mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), + mode_lib->vba.SwathHeightY[k]); mode_lib->vba.UrgentLatencySupportUsLuma = mode_lib->vba.EffectiveDETPlusLBLinesLuma - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / mode_lib->vba.VRatio[k] - - mode_lib->vba.EffectiveDETPlusLBLinesLuma * mode_lib->vba.SwathWidthY[k] - * mode_lib->vba.BytePerPixelDETY[k] - / (mode_lib->vba.ReturnBW / mode_lib->vba.DPPPerPlane[k]); + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETPlusLBLinesLuma + * mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.BytePerPixelDETY[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]); if (mode_lib->vba.BytePerPixelDETC[k] > 0) { mode_lib->vba.EffectiveDETPlusLBLinesChroma = - dml_floor(mode_lib->vba.LinesInDETC[k] - + dml_min(mode_lib->vba.LinesInDETC[k] - * mode_lib->vba.DPPCLK[k] - * mode_lib->vba.BytePerPixelDETC[k] - * mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] - / (mode_lib->vba.ReturnBW - / mode_lib->vba.DPPPerPlane[k]), - (double)mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), - mode_lib->vba.SwathHeightC[k]); - mode_lib->vba.UrgentLatencySupportUsChroma = mode_lib->vba.EffectiveDETPlusLBLinesChroma - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) / (mode_lib->vba.VRatio[k] / 2) - - mode_lib->vba.EffectiveDETPlusLBLinesChroma - * (mode_lib->vba.SwathWidthY[k] / 2) - * mode_lib->vba.BytePerPixelDETC[k] - / (mode_lib->vba.ReturnBW / mode_lib->vba.DPPPerPlane[k]); - mode_lib->vba.UrgentLatencySupportUs[k] = dml_min(mode_lib->vba.UrgentLatencySupportUsLuma, - mode_lib->vba.UrgentLatencySupportUsChroma); + dml_floor( + mode_lib->vba.LinesInDETC[k] + + dml_min( + mode_lib->vba.LinesInDETC[k] + * mode_lib->vba.DPPCLK[k] + * mode_lib->vba.BytePerPixelDETC[k] + * mode_lib->vba.PSCL_THROUGHPUT_CHROMA[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]), + (double) mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), + mode_lib->vba.SwathHeightC[k]); + mode_lib->vba.UrgentLatencySupportUsChroma = + mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] / 2) + - mode_lib->vba.EffectiveDETPlusLBLinesChroma + * (mode_lib->vba.SwathWidthY[k] + / 2) + * mode_lib->vba.BytePerPixelDETC[k] + / (mode_lib->vba.ReturnBW + / mode_lib->vba.DPPPerPlane[k]); + mode_lib->vba.UrgentLatencySupportUs[k] = dml_min( + mode_lib->vba.UrgentLatencySupportUsLuma, + mode_lib->vba.UrgentLatencySupportUsChroma); } else { - mode_lib->vba.UrgentLatencySupportUs[k] = mode_lib->vba.UrgentLatencySupportUsLuma; + mode_lib->vba.UrgentLatencySupportUs[k] = + mode_lib->vba.UrgentLatencySupportUsLuma; } } mode_lib->vba.MinUrgentLatencySupportUs = 999999; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - mode_lib->vba.MinUrgentLatencySupportUs = dml_min(mode_lib->vba.MinUrgentLatencySupportUs, - mode_lib->vba.UrgentLatencySupportUs[k]); + mode_lib->vba.MinUrgentLatencySupportUs = dml_min( + mode_lib->vba.MinUrgentLatencySupportUs, + mode_lib->vba.UrgentLatencySupportUs[k]); } // Non-Urgent Latency Tolerance - mode_lib->vba.NonUrgentLatencyTolerance = mode_lib->vba.MinUrgentLatencySupportUs - mode_lib->vba.UrgentWatermark; + mode_lib->vba.NonUrgentLatencyTolerance = mode_lib->vba.MinUrgentLatencySupportUs + - mode_lib->vba.UrgentWatermark; // DSCCLK for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if ((mode_lib->vba.BlendingAndTiming[k] != k) || !mode_lib->vba.DSCEnabled[k]) { mode_lib->vba.DSCCLK_calculated[k] = 0.0; } else { - if (mode_lib->vba.OutputFormat[k] == dm_420 || mode_lib->vba.OutputFormat[k] == dm_n422) + if (mode_lib->vba.OutputFormat[k] == dm_420 + || mode_lib->vba.OutputFormat[k] == dm_n422) mode_lib->vba.DSCFormatFactor = 2; else mode_lib->vba.DSCFormatFactor = 1; if (mode_lib->vba.ODMCombineEnabled[k]) - mode_lib->vba.DSCCLK_calculated[k] = mode_lib->vba.PixelClockBackEnd[k] / 6 - / mode_lib->vba.DSCFormatFactor - / (1 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.DSCCLK_calculated[k] = + mode_lib->vba.PixelClockBackEnd[k] / 6 + / mode_lib->vba.DSCFormatFactor + / (1 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100); else - mode_lib->vba.DSCCLK_calculated[k] = mode_lib->vba.PixelClockBackEnd[k] / 3 - / mode_lib->vba.DSCFormatFactor - / (1 - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100); + mode_lib->vba.DSCCLK_calculated[k] = + mode_lib->vba.PixelClockBackEnd[k] / 3 + / mode_lib->vba.DSCFormatFactor + / (1 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100); } } @@ -2013,27 +2366,35 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.DSCEnabled[k] && bpp != 0) { if (!mode_lib->vba.ODMCombineEnabled[k]) { mode_lib->vba.DSCDelay[k] = - dscceComputeDelay(mode_lib->vba.DSCInputBitPerComponent[k], - bpp, - dml_ceil((double)mode_lib->vba.HActive[k] - / mode_lib->vba.NumberOfDSCSlices[k], - 1), - slices, - mode_lib->vba.OutputFormat[k]) - + dscComputeDelay(mode_lib->vba.OutputFormat[k]); + dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil( + (double) mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k]); } else { mode_lib->vba.DSCDelay[k] = - 2 - * (dscceComputeDelay(mode_lib->vba.DSCInputBitPerComponent[k], - bpp, - dml_ceil((double)mode_lib->vba.HActive[k] - / mode_lib->vba.NumberOfDSCSlices[k], - 1), - slices / 2.0, - mode_lib->vba.OutputFormat[k]) - + dscComputeDelay(mode_lib->vba.OutputFormat[k])); - } - mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[k] * mode_lib->vba.PixelClock[k] / mode_lib->vba.PixelClockBackEnd[k]; + 2 + * (dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + bpp, + dml_ceil( + (double) mode_lib->vba.HActive[k] + / mode_lib->vba.NumberOfDSCSlices[k], + 1), + slices / 2.0, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k])); + } + mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.PixelClockBackEnd[k]; } else { mode_lib->vba.DSCDelay[k] = 0; } @@ -2041,7 +2402,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) // NumberOfPlanes - if (j != k && mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.DSCEnabled[j]) + if (j != k && mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.DSCEnabled[j]) mode_lib->vba.DSCDelay[k] = mode_lib->vba.DSCDelay[j]; // Prefetch @@ -2053,82 +2415,91 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman unsigned int PDEAndMetaPTEBytesFrameC; unsigned int PixelPTEBytesPerRowC; - Calculate256BBlockSizes(mode_lib->vba.SourcePixelFormat[k], - mode_lib->vba.SurfaceTiling[k], - dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), - dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), - &mode_lib->vba.BlockHeight256BytesY[k], - &mode_lib->vba.BlockHeight256BytesC[k], - &mode_lib->vba.BlockWidth256BytesY[k], - &mode_lib->vba.BlockWidth256BytesC[k]); - PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes(mode_lib, - mode_lib->vba.DCCEnable[k], - mode_lib->vba.BlockHeight256BytesY[k], - mode_lib->vba.BlockWidth256BytesY[k], - mode_lib->vba.SourcePixelFormat[k], - mode_lib->vba.SurfaceTiling[k], - dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), - mode_lib->vba.SourceScan[k], - mode_lib->vba.ViewportWidth[k], - mode_lib->vba.ViewportHeight[k], - mode_lib->vba.SwathWidthY[k], - mode_lib->vba.VirtualMemoryEnable, - mode_lib->vba.VMMPageSize, - mode_lib->vba.PTEBufferSizeInRequests, - mode_lib->vba.PDEProcessingBufIn64KBReqs, - mode_lib->vba.PitchY[k], - mode_lib->vba.DCCMetaPitchY[k], - &mode_lib->vba.MacroTileWidthY, - &MetaRowByteY, - &PixelPTEBytesPerRowY, - &mode_lib->vba.PTEBufferSizeNotExceeded, - &mode_lib->vba.dpte_row_height[k], - &mode_lib->vba.meta_row_height[k]); - mode_lib->vba.PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines(mode_lib, - mode_lib->vba.VRatio[k], - mode_lib->vba.vtaps[k], - mode_lib->vba.Interlace[k], - mode_lib->vba.ProgressiveToInterlaceUnitInOPP, - mode_lib->vba.SwathHeightY[k], - mode_lib->vba.ViewportYStartY[k], - &mode_lib->vba.VInitPreFillY[k], - &mode_lib->vba.MaxNumSwathY[k]); - - if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 - && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 - && mode_lib->vba.SourcePixelFormat[k] != dm_444_8)) { - PDEAndMetaPTEBytesFrameC = CalculateVMAndRowBytes(mode_lib, - mode_lib->vba.DCCEnable[k], - mode_lib->vba.BlockHeight256BytesC[k], - mode_lib->vba.BlockWidth256BytesC[k], + Calculate256BBlockSizes( mode_lib->vba.SourcePixelFormat[k], mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), dml_ceil(mode_lib->vba.BytePerPixelDETC[k], 2), + &mode_lib->vba.BlockHeight256BytesY[k], + &mode_lib->vba.BlockHeight256BytesC[k], + &mode_lib->vba.BlockWidth256BytesY[k], + &mode_lib->vba.BlockWidth256BytesC[k]); + PDEAndMetaPTEBytesFrameY = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesY[k], + mode_lib->vba.BlockWidth256BytesY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), mode_lib->vba.SourceScan[k], - mode_lib->vba.ViewportWidth[k] / 2, - mode_lib->vba.ViewportHeight[k] / 2, - mode_lib->vba.SwathWidthY[k] / 2, + mode_lib->vba.ViewportWidth[k], + mode_lib->vba.ViewportHeight[k], + mode_lib->vba.SwathWidthY[k], mode_lib->vba.VirtualMemoryEnable, mode_lib->vba.VMMPageSize, mode_lib->vba.PTEBufferSizeInRequests, mode_lib->vba.PDEProcessingBufIn64KBReqs, - mode_lib->vba.PitchC[k], - 0, - &mode_lib->vba.MacroTileWidthC, - &MetaRowByteC, - &PixelPTEBytesPerRowC, - &mode_lib->vba.PTEBufferSizeNotExceeded, - &mode_lib->vba.dpte_row_height_chroma[k], - &mode_lib->vba.meta_row_height_chroma[k]); - mode_lib->vba.PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines(mode_lib, - mode_lib->vba.VRatio[k] / 2, - mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.PitchY[k], + mode_lib->vba.DCCMetaPitchY[k], + &mode_lib->vba.MacroTileWidthY[k], + &MetaRowByteY, + &PixelPTEBytesPerRowY, + &mode_lib->vba.PTEBufferSizeNotExceeded[mode_lib->vba.VoltageLevel], + &mode_lib->vba.dpte_row_height[k], + &mode_lib->vba.meta_row_height[k]); + mode_lib->vba.PrefetchSourceLinesY[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.vtaps[k], mode_lib->vba.Interlace[k], mode_lib->vba.ProgressiveToInterlaceUnitInOPP, - mode_lib->vba.SwathHeightC[k], - mode_lib->vba.ViewportYStartC[k], - &mode_lib->vba.VInitPreFillC[k], - &mode_lib->vba.MaxNumSwathC[k]); + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.ViewportYStartY[k], + &mode_lib->vba.VInitPreFillY[k], + &mode_lib->vba.MaxNumSwathY[k]); + + if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_8)) { + PDEAndMetaPTEBytesFrameC = + CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.BlockHeight256BytesC[k], + mode_lib->vba.BlockWidth256BytesC[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil( + mode_lib->vba.BytePerPixelDETC[k], + 2), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k] / 2, + mode_lib->vba.ViewportHeight[k] / 2, + mode_lib->vba.SwathWidthY[k] / 2, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchC[k], + 0, + &mode_lib->vba.MacroTileWidthC[k], + &MetaRowByteC, + &PixelPTEBytesPerRowC, + &mode_lib->vba.PTEBufferSizeNotExceeded[mode_lib->vba.VoltageLevel], + &mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_height_chroma[k]); + mode_lib->vba.PrefetchSourceLinesC[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k] / 2, + mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightC[k], + mode_lib->vba.ViewportYStartC[k], + &mode_lib->vba.VInitPreFillC[k], + &mode_lib->vba.MaxNumSwathC[k]); } else { PixelPTEBytesPerRowC = 0; PDEAndMetaPTEBytesFrameC = 0; @@ -2138,25 +2509,27 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman } mode_lib->vba.PixelPTEBytesPerRow[k] = PixelPTEBytesPerRowY + PixelPTEBytesPerRowC; - mode_lib->vba.PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + PDEAndMetaPTEBytesFrameC; + mode_lib->vba.PDEAndMetaPTEBytesFrame[k] = PDEAndMetaPTEBytesFrameY + + PDEAndMetaPTEBytesFrameC; mode_lib->vba.MetaRowByte[k] = MetaRowByteY + MetaRowByteC; - CalculateActiveRowBandwidth(mode_lib->vba.VirtualMemoryEnable, - mode_lib->vba.SourcePixelFormat[k], - mode_lib->vba.VRatio[k], - mode_lib->vba.DCCEnable[k], - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - MetaRowByteY, - MetaRowByteC, - mode_lib->vba.meta_row_height[k], - mode_lib->vba.meta_row_height_chroma[k], - PixelPTEBytesPerRowY, - PixelPTEBytesPerRowC, - mode_lib->vba.dpte_row_height[k], - mode_lib->vba.dpte_row_height_chroma[k], - &mode_lib->vba.meta_row_bw[k], - &mode_lib->vba.dpte_row_bw[k], - &mode_lib->vba.qual_row_bw[k]); + CalculateActiveRowBandwidth( + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + MetaRowByteY, + MetaRowByteC, + mode_lib->vba.meta_row_height[k], + mode_lib->vba.meta_row_height_chroma[k], + PixelPTEBytesPerRowY, + PixelPTEBytesPerRowC, + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_bw[k], + &mode_lib->vba.dpte_row_bw[k], + &mode_lib->vba.qual_row_bw[k]); } mode_lib->vba.TCalc = 24.0 / mode_lib->vba.DCFClkDeepSleep; @@ -2164,32 +2537,37 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.BlendingAndTiming[k] == k) { if (mode_lib->vba.WritebackEnable[k] == true) { - mode_lib->vba.WritebackDelay[k] = mode_lib->vba.WritebackLatency - + CalculateWriteBackDelay(mode_lib->vba.WritebackPixelFormat[k], - mode_lib->vba.WritebackHRatio[k], - mode_lib->vba.WritebackVRatio[k], - mode_lib->vba.WritebackLumaHTaps[k], - mode_lib->vba.WritebackLumaVTaps[k], - mode_lib->vba.WritebackChromaHTaps[k], - mode_lib->vba.WritebackChromaVTaps[k], - mode_lib->vba.WritebackDestinationWidth[k]) - / mode_lib->vba.DISPCLK; + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k]) + / mode_lib->vba.DISPCLK; } else - mode_lib->vba.WritebackDelay[k] = 0; + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = 0; for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { - if (mode_lib->vba.BlendingAndTiming[j] == k && mode_lib->vba.WritebackEnable[j] == true) { - mode_lib->vba.WritebackDelay[k] = - dml_max(mode_lib->vba.WritebackDelay[k], - mode_lib->vba.WritebackLatency - + CalculateWriteBackDelay(mode_lib->vba.WritebackPixelFormat[j], - mode_lib->vba.WritebackHRatio[j], - mode_lib->vba.WritebackVRatio[j], - mode_lib->vba.WritebackLumaHTaps[j], - mode_lib->vba.WritebackLumaVTaps[j], - mode_lib->vba.WritebackChromaHTaps[j], - mode_lib->vba.WritebackChromaVTaps[j], - mode_lib->vba.WritebackDestinationWidth[j]) - / mode_lib->vba.DISPCLK); + if (mode_lib->vba.BlendingAndTiming[j] == k + && mode_lib->vba.WritebackEnable[j] == true) { + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + dml_max( + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k], + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[j], + mode_lib->vba.WritebackHRatio[j], + mode_lib->vba.WritebackVRatio[j], + mode_lib->vba.WritebackLumaHTaps[j], + mode_lib->vba.WritebackLumaVTaps[j], + mode_lib->vba.WritebackChromaHTaps[j], + mode_lib->vba.WritebackChromaVTaps[j], + mode_lib->vba.WritebackDestinationWidth[j]) + / mode_lib->vba.DISPCLK); } } } @@ -2198,27 +2576,34 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) if (mode_lib->vba.BlendingAndTiming[k] == j) - mode_lib->vba.WritebackDelay[k] = mode_lib->vba.WritebackDelay[j]; + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] = + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][j]; mode_lib->vba.VStartupLines = 13; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.MaxVStartupLines[k] = - mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] - - dml_max(1.0, - dml_ceil(mode_lib->vba.WritebackDelay[k] - / (mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]), - 1)); + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] + - dml_max( + 1.0, + dml_ceil( + mode_lib->vba.WritebackDelay[mode_lib->vba.VoltageLevel][k] + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1)); } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) - mode_lib->vba.MaximumMaxVStartupLines = dml_max(mode_lib->vba.MaximumMaxVStartupLines, mode_lib->vba.MaxVStartupLines[k]); + mode_lib->vba.MaximumMaxVStartupLines = dml_max( + mode_lib->vba.MaximumMaxVStartupLines, + mode_lib->vba.MaxVStartupLines[k]); for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.cursor_bw[k] = 0.0; for (j = 0; j < mode_lib->vba.NumberOfCursors[k]; ++j) - mode_lib->vba.cursor_bw[k] += mode_lib->vba.CursorWidth[k][j] * mode_lib->vba.CursorBPP[k][j] / 8.0 - / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * mode_lib->vba.VRatio[k]; + mode_lib->vba.cursor_bw[k] += mode_lib->vba.CursorWidth[k][j] + * mode_lib->vba.CursorBPP[k][j] / 8.0 + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; } do { @@ -2227,102 +2612,119 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman bool VRatioPrefetchMoreThan4 = false; bool prefetch_vm_bw_valid = true; bool prefetch_row_bw_valid = true; - double TWait = CalculateTWait(mode_lib->vba.PrefetchMode, - mode_lib->vba.DRAMClockChangeLatency, - mode_lib->vba.UrgentLatency, - mode_lib->vba.SREnterPlusExitTime); + double TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.XFCEnabled[k] == true) { - mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(mode_lib, - mode_lib->vba.VRatio[k], - mode_lib->vba.SwathWidthY[k], - dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - mode_lib->vba.XFCTSlvVupdateOffset, - mode_lib->vba.XFCTSlvVupdateWidth, - mode_lib->vba.XFCTSlvVreadyOffset, - mode_lib->vba.XFCXBUFLatencyTolerance, - mode_lib->vba.XFCFillBWOverhead, - mode_lib->vba.XFCSlvChunkSize, - mode_lib->vba.XFCBusTransportTime, - mode_lib->vba.TCalc, - TWait, - &mode_lib->vba.SrcActiveDrainRate, - &mode_lib->vba.TInitXFill, - &mode_lib->vba.TslvChk); + mode_lib->vba.XFCRemoteSurfaceFlipDelay = + CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil( + mode_lib->vba.BytePerPixelDETY[k], + 1), + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); } else { mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0; } - mode_lib->vba.ErrorResult[k] = CalculatePrefetchSchedule(mode_lib, - mode_lib->vba.DPPCLK[k], - mode_lib->vba.DISPCLK, - mode_lib->vba.PixelClock[k], - mode_lib->vba.DCFClkDeepSleep, - mode_lib->vba.DSCDelay[k], - mode_lib->vba.DPPPerPlane[k], - mode_lib->vba.ScalerEnabled[k], - mode_lib->vba.NumberOfCursors[k], - mode_lib->vba.DPPCLKDelaySubtotal, - mode_lib->vba.DPPCLKDelaySCL, - mode_lib->vba.DPPCLKDelaySCLLBOnly, - mode_lib->vba.DPPCLKDelayCNVCFormater, - mode_lib->vba.DPPCLKDelayCNVCCursor, - mode_lib->vba.DISPCLKDelaySubtotal, - (unsigned int)(mode_lib->vba.SwathWidthY[k] / mode_lib->vba.HRatio[k]), - mode_lib->vba.OutputFormat[k], - mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k], - mode_lib->vba.HTotal[k], - mode_lib->vba.MaxInterDCNTileRepeaters, - dml_min(mode_lib->vba.VStartupLines, mode_lib->vba.MaxVStartupLines[k]), - mode_lib->vba.MaxPageTableLevels, - mode_lib->vba.VirtualMemoryEnable, - mode_lib->vba.DynamicMetadataEnable[k], - mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], - mode_lib->vba.DynamicMetadataTransmittedBytes[k], - mode_lib->vba.DCCEnable[k], - mode_lib->vba.UrgentLatency, - mode_lib->vba.UrgentExtraLatency, - mode_lib->vba.TCalc, - mode_lib->vba.PDEAndMetaPTEBytesFrame[k], - mode_lib->vba.MetaRowByte[k], - mode_lib->vba.PixelPTEBytesPerRow[k], - mode_lib->vba.PrefetchSourceLinesY[k], - mode_lib->vba.SwathWidthY[k], - mode_lib->vba.BytePerPixelDETY[k], - mode_lib->vba.VInitPreFillY[k], - mode_lib->vba.MaxNumSwathY[k], - mode_lib->vba.PrefetchSourceLinesC[k], - mode_lib->vba.BytePerPixelDETC[k], - mode_lib->vba.VInitPreFillC[k], - mode_lib->vba.MaxNumSwathC[k], - mode_lib->vba.SwathHeightY[k], - mode_lib->vba.SwathHeightC[k], - TWait, - mode_lib->vba.XFCEnabled[k], - mode_lib->vba.XFCRemoteSurfaceFlipDelay, - mode_lib->vba.Interlace[k], - mode_lib->vba.ProgressiveToInterlaceUnitInOPP, - &mode_lib->vba.DSTXAfterScaler[k], - &mode_lib->vba.DSTYAfterScaler[k], - &mode_lib->vba.DestinationLinesForPrefetch[k], - &mode_lib->vba.PrefetchBandwidth[k], - &mode_lib->vba.DestinationLinesToRequestVMInVBlank[k], - &mode_lib->vba.DestinationLinesToRequestRowInVBlank[k], - &mode_lib->vba.VRatioPrefetchY[k], - &mode_lib->vba.VRatioPrefetchC[k], - &mode_lib->vba.RequiredPrefetchPixDataBW[k], - &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - &mode_lib->vba.Tno_bw[k]); + mode_lib->vba.ErrorResult[k] = + CalculatePrefetchSchedule( + mode_lib, + mode_lib->vba.DPPCLK[k], + mode_lib->vba.DISPCLK, + mode_lib->vba.PixelClock[k], + mode_lib->vba.DCFClkDeepSleep, + mode_lib->vba.DSCDelay[k], + mode_lib->vba.DPPPerPlane[k], + mode_lib->vba.ScalerEnabled[k], + mode_lib->vba.NumberOfCursors[k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + (unsigned int) (mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.HRatio[k]), + mode_lib->vba.OutputFormat[k], + mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[k]), + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.TCalc, + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.PrefetchSourceLinesY[k], + mode_lib->vba.SwathWidthY[k], + mode_lib->vba.BytePerPixelDETY[k], + mode_lib->vba.VInitPreFillY[k], + mode_lib->vba.MaxNumSwathY[k], + mode_lib->vba.PrefetchSourceLinesC[k], + mode_lib->vba.BytePerPixelDETC[k], + mode_lib->vba.VInitPreFillC[k], + mode_lib->vba.MaxNumSwathC[k], + mode_lib->vba.SwathHeightY[k], + mode_lib->vba.SwathHeightC[k], + TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + &mode_lib->vba.DSTXAfterScaler[k], + &mode_lib->vba.DSTYAfterScaler[k], + &mode_lib->vba.DestinationLinesForPrefetch[k], + &mode_lib->vba.PrefetchBandwidth[k], + &mode_lib->vba.DestinationLinesToRequestVMInVBlank[k], + &mode_lib->vba.DestinationLinesToRequestRowInVBlank[k], + &mode_lib->vba.VRatioPrefetchY[k], + &mode_lib->vba.VRatioPrefetchC[k], + &mode_lib->vba.RequiredPrefetchPixDataBW[k], + &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &mode_lib->vba.Tno_bw[k]); if (mode_lib->vba.BlendingAndTiming[k] == k) { - mode_lib->vba.VStartup[k] = dml_min(mode_lib->vba.VStartupLines, mode_lib->vba.MaxVStartupLines[k]); - if (mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata != 0) { + mode_lib->vba.VStartup[k] = dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[k]); + if (mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata + != 0) { mode_lib->vba.VStartup[k] = - mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; + mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; } } else { - mode_lib->vba.VStartup[k] = dml_min(mode_lib->vba.VStartupLines, - mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]); + mode_lib->vba.VStartup[k] = + dml_min( + mode_lib->vba.VStartupLines, + mode_lib->vba.MaxVStartupLines[mode_lib->vba.BlendingAndTiming[k]]); } } @@ -2331,116 +2733,136 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.PDEAndMetaPTEBytesFrame[k] == 0) mode_lib->vba.prefetch_vm_bw[k] = 0; else if (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] > 0) { - mode_lib->vba.prefetch_vm_bw[k] = (double)mode_lib->vba.PDEAndMetaPTEBytesFrame[k] - / (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] - * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + mode_lib->vba.prefetch_vm_bw[k] = + (double) mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + / (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); } else { mode_lib->vba.prefetch_vm_bw[k] = 0; prefetch_vm_bw_valid = false; } - if (mode_lib->vba.MetaRowByte[k] + mode_lib->vba.PixelPTEBytesPerRow[k] == 0) + if (mode_lib->vba.MetaRowByte[k] + mode_lib->vba.PixelPTEBytesPerRow[k] + == 0) mode_lib->vba.prefetch_row_bw[k] = 0; else if (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] > 0) { - mode_lib->vba.prefetch_row_bw[k] = (double)(mode_lib->vba.MetaRowByte[k] - + mode_lib->vba.PixelPTEBytesPerRow[k]) - / (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] - * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + mode_lib->vba.prefetch_row_bw[k] = + (double) (mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]) + / (mode_lib->vba.DestinationLinesToRequestRowInVBlank[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); } else { mode_lib->vba.prefetch_row_bw[k] = 0; prefetch_row_bw_valid = false; } MaxTotalRDBandwidth = - MaxTotalRDBandwidth + mode_lib->vba.cursor_bw[k] - + dml_max(mode_lib->vba.prefetch_vm_bw[k], - dml_max(mode_lib->vba.prefetch_row_bw[k], - dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] - + mode_lib->vba.ReadBandwidthPlaneChroma[k], - mode_lib->vba.RequiredPrefetchPixDataBW[k]) - + mode_lib->vba.meta_row_bw[k] - + mode_lib->vba.dpte_row_bw[k])); + MaxTotalRDBandwidth + mode_lib->vba.cursor_bw[k] + + dml_max( + mode_lib->vba.prefetch_vm_bw[k], + dml_max( + mode_lib->vba.prefetch_row_bw[k], + dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]) + + mode_lib->vba.meta_row_bw[k] + + mode_lib->vba.dpte_row_bw[k])); if (mode_lib->vba.DestinationLinesForPrefetch[k] < 2) DestinationLineTimesForPrefetchLessThan2 = true; - if (mode_lib->vba.VRatioPrefetchY[k] > 4 || mode_lib->vba.VRatioPrefetchC[k] > 4) + if (mode_lib->vba.VRatioPrefetchY[k] > 4 + || mode_lib->vba.VRatioPrefetchC[k] > 4) VRatioPrefetchMoreThan4 = true; } - if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && prefetch_vm_bw_valid && prefetch_row_bw_valid - && !VRatioPrefetchMoreThan4 + if (MaxTotalRDBandwidth <= mode_lib->vba.ReturnBW && prefetch_vm_bw_valid + && prefetch_row_bw_valid && !VRatioPrefetchMoreThan4 && !DestinationLineTimesForPrefetchLessThan2) mode_lib->vba.PrefetchModeSupported = true; else { mode_lib->vba.PrefetchModeSupported = false; - dml_print("DML: CalculatePrefetchSchedule ***failed***. Bandwidth violation. Results are NOT valid\n"); + dml_print( + "DML: CalculatePrefetchSchedule ***failed***. Bandwidth violation. Results are NOT valid\n"); } if (mode_lib->vba.PrefetchModeSupported == true) { - double final_flip_bw[DC__NUM_PIPES__MAX]; - unsigned int ImmediateFlipBytes[DC__NUM_PIPES__MAX]; + double final_flip_bw[DC__NUM_DPP__MAX]; + unsigned int ImmediateFlipBytes[DC__NUM_DPP__MAX]; double total_dcn_read_bw_with_flip = 0; mode_lib->vba.BandwidthAvailableForImmediateFlip = mode_lib->vba.ReturnBW; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.BandwidthAvailableForImmediateFlip = - mode_lib->vba.BandwidthAvailableForImmediateFlip - mode_lib->vba.cursor_bw[k] - - dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] - + mode_lib->vba.ReadBandwidthPlaneChroma[k] - + mode_lib->vba.qual_row_bw[k], - mode_lib->vba.PrefetchBandwidth[k]); + mode_lib->vba.BandwidthAvailableForImmediateFlip + - mode_lib->vba.cursor_bw[k] + - dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k] + + mode_lib->vba.qual_row_bw[k], + mode_lib->vba.PrefetchBandwidth[k]); } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { ImmediateFlipBytes[k] = 0; if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 - && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { - ImmediateFlipBytes[k] = mode_lib->vba.PDEAndMetaPTEBytesFrame[k] - + mode_lib->vba.MetaRowByte[k] - + mode_lib->vba.PixelPTEBytesPerRow[k]; + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + ImmediateFlipBytes[k] = + mode_lib->vba.PDEAndMetaPTEBytesFrame[k] + + mode_lib->vba.MetaRowByte[k] + + mode_lib->vba.PixelPTEBytesPerRow[k]; } } mode_lib->vba.TotImmediateFlipBytes = 0; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 - && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { - mode_lib->vba.TotImmediateFlipBytes = mode_lib->vba.TotImmediateFlipBytes - + ImmediateFlipBytes[k]; + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.TotImmediateFlipBytes = + mode_lib->vba.TotImmediateFlipBytes + + ImmediateFlipBytes[k]; } } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - CalculateFlipSchedule(mode_lib, - mode_lib->vba.UrgentExtraLatency, - mode_lib->vba.UrgentLatency, - mode_lib->vba.MaxPageTableLevels, - mode_lib->vba.VirtualMemoryEnable, - mode_lib->vba.BandwidthAvailableForImmediateFlip, - mode_lib->vba.TotImmediateFlipBytes, - mode_lib->vba.SourcePixelFormat[k], - ImmediateFlipBytes[k], - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - mode_lib->vba.VRatio[k], - mode_lib->vba.Tno_bw[k], - mode_lib->vba.PDEAndMetaPTEBytesFrame[k], - mode_lib->vba.MetaRowByte[k], - mode_lib->vba.PixelPTEBytesPerRow[k], - mode_lib->vba.DCCEnable[k], - mode_lib->vba.dpte_row_height[k], - mode_lib->vba.meta_row_height[k], - mode_lib->vba.qual_row_bw[k], - &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], - &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], - &final_flip_bw[k], - &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); + CalculateFlipSchedule( + mode_lib, + mode_lib->vba.UrgentExtraLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.BandwidthAvailableForImmediateFlip, + mode_lib->vba.TotImmediateFlipBytes, + mode_lib->vba.SourcePixelFormat[k], + ImmediateFlipBytes[k], + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.Tno_bw[k], + mode_lib->vba.PDEAndMetaPTEBytesFrame[k], + mode_lib->vba.MetaRowByte[k], + mode_lib->vba.PixelPTEBytesPerRow[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.meta_row_height[k], + mode_lib->vba.qual_row_bw[k], + &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], + &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], + &final_flip_bw[k], + &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); } for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { total_dcn_read_bw_with_flip = - total_dcn_read_bw_with_flip + mode_lib->vba.cursor_bw[k] - + dml_max(mode_lib->vba.prefetch_vm_bw[k], - dml_max(mode_lib->vba.prefetch_row_bw[k], - final_flip_bw[k] - + dml_max(mode_lib->vba.ReadBandwidthPlaneLuma[k] - + mode_lib->vba.ReadBandwidthPlaneChroma[k], - mode_lib->vba.RequiredPrefetchPixDataBW[k]))); + total_dcn_read_bw_with_flip + + mode_lib->vba.cursor_bw[k] + + dml_max( + mode_lib->vba.prefetch_vm_bw[k], + dml_max( + mode_lib->vba.prefetch_row_bw[k], + final_flip_bw[k] + + dml_max( + mode_lib->vba.ReadBandwidthPlaneLuma[k] + + mode_lib->vba.ReadBandwidthPlaneChroma[k], + mode_lib->vba.RequiredPrefetchPixDataBW[k]))); } mode_lib->vba.ImmediateFlipSupported = true; if (total_dcn_read_bw_with_flip > mode_lib->vba.ReturnBW) { @@ -2458,35 +2880,44 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.ErrorResult[k]) { mode_lib->vba.PrefetchModeSupported = false; - dml_print("DML: CalculatePrefetchSchedule ***failed***. Prefetch schedule violation. Results are NOT valid\n"); + dml_print( + "DML: CalculatePrefetchSchedule ***failed***. Prefetch schedule violation. Results are NOT valid\n"); } } mode_lib->vba.VStartupLines = mode_lib->vba.VStartupLines + 1; } while (!((mode_lib->vba.PrefetchModeSupported - && (!mode_lib->vba.ImmediateFlipSupport || mode_lib->vba.ImmediateFlipSupported)) - || mode_lib->vba.MaximumMaxVStartupLines < mode_lib->vba.VStartupLines)); + && (!mode_lib->vba.ImmediateFlipSupport + || mode_lib->vba.ImmediateFlipSupported)) + || mode_lib->vba.MaximumMaxVStartupLines < mode_lib->vba.VStartupLines)); //Display Pipeline Delivery Time in Prefetch for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.VRatioPrefetchY[k] <= 1) { - mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->vba.SwathWidthY[k] - * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] / mode_lib->vba.PixelClock[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; } else { - mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = mode_lib->vba.SwathWidthY[k] - / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] / mode_lib->vba.DPPCLK[k]; + mode_lib->vba.DisplayPipeLineDeliveryTimeLumaPrefetch[k] = + mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; } if (mode_lib->vba.BytePerPixelDETC[k] == 0) { mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = 0; } else { if (mode_lib->vba.VRatioPrefetchC[k] <= 1) { mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = - mode_lib->vba.SwathWidthY[k] * mode_lib->vba.DPPPerPlane[k] / mode_lib->vba.HRatio[k] - / mode_lib->vba.PixelClock[k]; + mode_lib->vba.SwathWidthY[k] + * mode_lib->vba.DPPPerPlane[k] + / mode_lib->vba.HRatio[k] + / mode_lib->vba.PixelClock[k]; } else { mode_lib->vba.DisplayPipeLineDeliveryTimeChromaPrefetch[k] = - mode_lib->vba.SwathWidthY[k] / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] - / mode_lib->vba.DPPCLK[k]; + mode_lib->vba.SwathWidthY[k] + / mode_lib->vba.PSCL_THROUGHPUT_LUMA[k] + / mode_lib->vba.DPPCLK[k]; } } } @@ -2496,19 +2927,25 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.PrefetchMode == 0) { mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = true; mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; - mode_lib->vba.MinTTUVBlank[k] = dml_max(mode_lib->vba.DRAMClockChangeWatermark, - dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark)); + mode_lib->vba.MinTTUVBlank[k] = dml_max( + mode_lib->vba.DRAMClockChangeWatermark, + dml_max( + mode_lib->vba.StutterEnterPlusExitWatermark, + mode_lib->vba.UrgentWatermark)); } else if (mode_lib->vba.PrefetchMode == 1) { mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = true; - mode_lib->vba.MinTTUVBlank[k] = dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark); + mode_lib->vba.MinTTUVBlank[k] = dml_max( + mode_lib->vba.StutterEnterPlusExitWatermark, + mode_lib->vba.UrgentWatermark); } else { mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k] = false; mode_lib->vba.AllowDRAMSelfRefreshDuringVBlank[k] = false; mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.UrgentWatermark; } if (!mode_lib->vba.DynamicMetadataEnable[k]) - mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.TCalc + mode_lib->vba.MinTTUVBlank[k]; + mode_lib->vba.MinTTUVBlank[k] = mode_lib->vba.TCalc + + mode_lib->vba.MinTTUVBlank[k]; } // DCC Configuration @@ -2528,33 +2965,43 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman double ActiveDRAMClockChangeLatencyMarginY; mode_lib->vba.LBLatencyHidingSourceLinesY = - dml_min(mode_lib->vba.MaxLineBufferLines, - (unsigned int)dml_floor((double)mode_lib->vba.LineBufferSize - / mode_lib->vba.LBBitPerPixel[k] - / (mode_lib->vba.SwathWidthY[k] - / dml_max(mode_lib->vba.HRatio[k], - 1.0)), - 1)) - (mode_lib->vba.vtaps[k] - 1); + dml_min( + mode_lib->vba.MaxLineBufferLines, + (unsigned int) dml_floor( + (double) mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / dml_max( + mode_lib->vba.HRatio[k], + 1.0)), + 1)) - (mode_lib->vba.vtaps[k] - 1); mode_lib->vba.LBLatencyHidingSourceLinesC = - dml_min(mode_lib->vba.MaxLineBufferLines, - (unsigned int)dml_floor((double)mode_lib->vba.LineBufferSize - / mode_lib->vba.LBBitPerPixel[k] - / (mode_lib->vba.SwathWidthY[k] - / 2.0 - / dml_max(mode_lib->vba.HRatio[k] - / 2, - 1.0)), - 1)) - (mode_lib->vba.VTAPsChroma[k] - 1); - - EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY / mode_lib->vba.VRatio[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); - - EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC / (mode_lib->vba.VRatio[k] / 2) - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + dml_min( + mode_lib->vba.MaxLineBufferLines, + (unsigned int) dml_floor( + (double) mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthY[k] + / 2.0 + / dml_max( + mode_lib->vba.HRatio[k] + / 2, + 1.0)), + 1)) + - (mode_lib->vba.VTAPsChroma[k] - 1); + + EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY + / mode_lib->vba.VRatio[k] + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC + / (mode_lib->vba.VRatio[k] / 2) + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); if (mode_lib->vba.SwathWidthY[k] > 2 * mode_lib->vba.DPPOutputBufferPixels) { - DPPOutputBufferLinesY = mode_lib->vba.DPPOutputBufferPixels / mode_lib->vba.SwathWidthY[k]; + DPPOutputBufferLinesY = mode_lib->vba.DPPOutputBufferPixels + / mode_lib->vba.SwathWidthY[k]; } else if (mode_lib->vba.SwathWidthY[k] > mode_lib->vba.DPPOutputBufferPixels) { DPPOutputBufferLinesY = 0.5; } else { @@ -2562,7 +3009,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman } if (mode_lib->vba.SwathWidthY[k] / 2 > 2 * mode_lib->vba.DPPOutputBufferPixels) { - DPPOutputBufferLinesC = mode_lib->vba.DPPOutputBufferPixels / (mode_lib->vba.SwathWidthY[k] / 2); + DPPOutputBufferLinesC = mode_lib->vba.DPPOutputBufferPixels + / (mode_lib->vba.SwathWidthY[k] / 2); } else if (mode_lib->vba.SwathWidthY[k] / 2 > mode_lib->vba.DPPOutputBufferPixels) { DPPOutputBufferLinesC = 0.5; } else { @@ -2570,46 +3018,59 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman } DPPOPPBufferingY = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) - * (DPPOutputBufferLinesY + mode_lib->vba.OPPOutputBufferLines); + * (DPPOutputBufferLinesY + mode_lib->vba.OPPOutputBufferLines); MaxDETBufferingTimeY = mode_lib->vba.FullDETBufferingTimeY[k] - + (mode_lib->vba.LinesInDETY[k] - mode_lib->vba.LinesInDETYRoundedDownToSwath[k]) - / mode_lib->vba.SwathHeightY[k] * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + + (mode_lib->vba.LinesInDETY[k] + - mode_lib->vba.LinesInDETYRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightY[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); ActiveDRAMClockChangeLatencyMarginY = DPPOPPBufferingY + EffectiveLBLatencyHidingY - + MaxDETBufferingTimeY - mode_lib->vba.DRAMClockChangeWatermark; + + MaxDETBufferingTimeY - mode_lib->vba.DRAMClockChangeWatermark; if (mode_lib->vba.ActiveDPPs > 1) { - ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY - - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) * mode_lib->vba.SwathHeightY[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + ActiveDRAMClockChangeLatencyMarginY = + ActiveDRAMClockChangeLatencyMarginY + - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) + * mode_lib->vba.SwathHeightY[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); } if (mode_lib->vba.BytePerPixelDETC[k] > 0) { - double DPPOPPBufferingC = (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) - * (DPPOutputBufferLinesC + mode_lib->vba.OPPOutputBufferLines); + double DPPOPPBufferingC = (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + * (DPPOutputBufferLinesC + + mode_lib->vba.OPPOutputBufferLines); double MaxDETBufferingTimeC = - mode_lib->vba.FullDETBufferingTimeC[k] - + (mode_lib->vba.LinesInDETC[k] - - mode_lib->vba.LinesInDETCRoundedDownToSwath[k]) - / mode_lib->vba.SwathHeightC[k] - * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + mode_lib->vba.FullDETBufferingTimeC[k] + + (mode_lib->vba.LinesInDETC[k] + - mode_lib->vba.LinesInDETCRoundedDownToSwath[k]) + / mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); double ActiveDRAMClockChangeLatencyMarginC = DPPOPPBufferingC - + EffectiveLBLatencyHidingC + MaxDETBufferingTimeC - - mode_lib->vba.DRAMClockChangeWatermark; + + EffectiveLBLatencyHidingC + MaxDETBufferingTimeC + - mode_lib->vba.DRAMClockChangeWatermark; if (mode_lib->vba.ActiveDPPs > 1) { ActiveDRAMClockChangeLatencyMarginC = - ActiveDRAMClockChangeLatencyMarginC - - (1 - 1 / (mode_lib->vba.ActiveDPPs - 1)) - * mode_lib->vba.SwathHeightC[k] - * (mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]); - } - mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMarginY, - ActiveDRAMClockChangeLatencyMarginC); + ActiveDRAMClockChangeLatencyMarginC + - (1 + - 1 + / (mode_lib->vba.ActiveDPPs + - 1)) + * mode_lib->vba.SwathHeightC[k] + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min( + ActiveDRAMClockChangeLatencyMarginY, + ActiveDRAMClockChangeLatencyMarginC); } else { mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = - ActiveDRAMClockChangeLatencyMarginY; + ActiveDRAMClockChangeLatencyMarginY; } if (mode_lib->vba.WritebackEnable[k]) { @@ -2617,51 +3078,60 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { WritebackDRAMClockChangeLatencyMargin = - (double)(mode_lib->vba.WritebackInterfaceLumaBufferSize - + mode_lib->vba.WritebackInterfaceChromaBufferSize) - / (mode_lib->vba.WritebackDestinationWidth[k] - * mode_lib->vba.WritebackDestinationHeight[k] - / (mode_lib->vba.WritebackSourceHeight[k] - * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k]) - * 4) - - mode_lib->vba.WritebackDRAMClockChangeWatermark; + (double) (mode_lib->vba.WritebackInterfaceLumaBufferSize + + mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + * 4) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; } else if (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { - WritebackDRAMClockChangeLatencyMargin = dml_min((double)mode_lib->vba.WritebackInterfaceLumaBufferSize * 8.0 - / 10, - 2.0 * mode_lib->vba.WritebackInterfaceChromaBufferSize * 8 / 10) - / (mode_lib->vba.WritebackDestinationWidth[k] - * mode_lib->vba.WritebackDestinationHeight[k] - / (mode_lib->vba.WritebackSourceHeight[k] - * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k])) - - mode_lib->vba.WritebackDRAMClockChangeWatermark; + WritebackDRAMClockChangeLatencyMargin = + dml_min( + (double) mode_lib->vba.WritebackInterfaceLumaBufferSize + * 8.0 / 10, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize + * 8 / 10) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; } else { - WritebackDRAMClockChangeLatencyMargin = dml_min((double)mode_lib->vba.WritebackInterfaceLumaBufferSize, - 2.0 * mode_lib->vba.WritebackInterfaceChromaBufferSize) - / (mode_lib->vba.WritebackDestinationWidth[k] - * mode_lib->vba.WritebackDestinationHeight[k] - / (mode_lib->vba.WritebackSourceHeight[k] - * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k])) - - mode_lib->vba.WritebackDRAMClockChangeWatermark; + WritebackDRAMClockChangeLatencyMargin = + dml_min( + (double) mode_lib->vba.WritebackInterfaceLumaBufferSize, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize) + / (mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k])) + - mode_lib->vba.WritebackDRAMClockChangeWatermark; } - mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k], - WritebackDRAMClockChangeLatencyMargin); + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min( + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k], + WritebackDRAMClockChangeLatencyMargin); } } mode_lib->vba.MinActiveDRAMClockChangeMargin = 999999; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] - < mode_lib->vba.MinActiveDRAMClockChangeMargin) { + < mode_lib->vba.MinActiveDRAMClockChangeMargin) { mode_lib->vba.MinActiveDRAMClockChangeMargin = - mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; } } - mode_lib->vba.MinActiveDRAMClockChangeLatencySupported = mode_lib->vba.MinActiveDRAMClockChangeMargin - + mode_lib->vba.DRAMClockChangeLatency; + mode_lib->vba.MinActiveDRAMClockChangeLatencySupported = + mode_lib->vba.MinActiveDRAMClockChangeMargin + + mode_lib->vba.DRAMClockChangeLatency; if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vactive; @@ -2670,7 +3140,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_vblank; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (!mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k]) { - mode_lib->vba.DRAMClockChangeSupport = dm_dram_clock_change_unsupported; + mode_lib->vba.DRAMClockChangeSupport = + dm_dram_clock_change_unsupported; } } } else { @@ -2686,48 +3157,74 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.XFCSlaveVUpdateOffset[k] = mode_lib->vba.XFCTSlvVupdateOffset; mode_lib->vba.XFCSlaveVupdateWidth[k] = mode_lib->vba.XFCTSlvVupdateWidth; mode_lib->vba.XFCSlaveVReadyOffset[k] = mode_lib->vba.XFCTSlvVreadyOffset; - TWait = CalculateTWait(mode_lib->vba.PrefetchMode, - mode_lib->vba.DRAMClockChangeLatency, - mode_lib->vba.UrgentLatency, - mode_lib->vba.SREnterPlusExitTime); - mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay(mode_lib, - mode_lib->vba.VRatio[k], - mode_lib->vba.SwathWidthY[k], - dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - mode_lib->vba.XFCTSlvVupdateOffset, - mode_lib->vba.XFCTSlvVupdateWidth, - mode_lib->vba.XFCTSlvVreadyOffset, - mode_lib->vba.XFCXBUFLatencyTolerance, - mode_lib->vba.XFCFillBWOverhead, - mode_lib->vba.XFCSlvChunkSize, - mode_lib->vba.XFCBusTransportTime, - mode_lib->vba.TCalc, - TWait, - &mode_lib->vba.SrcActiveDrainRate, - &mode_lib->vba.TInitXFill, - &mode_lib->vba.TslvChk); - mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = dml_floor(mode_lib->vba.XFCRemoteSurfaceFlipDelay / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), - 1); - mode_lib->vba.XFCTransferDelay[k] = dml_ceil(mode_lib->vba.XFCBusTransportTime / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), - 1); - mode_lib->vba.XFCPrechargeDelay[k] = dml_ceil((mode_lib->vba.XFCBusTransportTime + mode_lib->vba.TInitXFill + mode_lib->vba.TslvChk) - / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]), - 1); - mode_lib->vba.InitFillLevel = mode_lib->vba.XFCXBUFLatencyTolerance * mode_lib->vba.SrcActiveDrainRate; - mode_lib->vba.FinalFillMargin = (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] - + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) * mode_lib->vba.HTotal[k] - / mode_lib->vba.PixelClock[k] * mode_lib->vba.SrcActiveDrainRate + mode_lib->vba.XFCFillConstant; - mode_lib->vba.FinalFillLevel = mode_lib->vba.XFCRemoteSurfaceFlipDelay * mode_lib->vba.SrcActiveDrainRate - + mode_lib->vba.FinalFillMargin; - mode_lib->vba.RemainingFillLevel = dml_max(0.0, - mode_lib->vba.FinalFillLevel - mode_lib->vba.InitFillLevel); + TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + mode_lib->vba.XFCRemoteSurfaceFlipDelay = CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthY[k], + dml_ceil(mode_lib->vba.BytePerPixelDETY[k], 1), + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TCalc, + TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + mode_lib->vba.XFCRemoteSurfaceFlipLatency[k] = + dml_floor( + mode_lib->vba.XFCRemoteSurfaceFlipDelay + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCTransferDelay[k] = + dml_ceil( + mode_lib->vba.XFCBusTransportTime + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.XFCPrechargeDelay[k] = + dml_ceil( + (mode_lib->vba.XFCBusTransportTime + + mode_lib->vba.TInitXFill + + mode_lib->vba.TslvChk) + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1); + mode_lib->vba.InitFillLevel = mode_lib->vba.XFCXBUFLatencyTolerance + * mode_lib->vba.SrcActiveDrainRate; + mode_lib->vba.FinalFillMargin = + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k] + * mode_lib->vba.SrcActiveDrainRate + + mode_lib->vba.XFCFillConstant; + mode_lib->vba.FinalFillLevel = mode_lib->vba.XFCRemoteSurfaceFlipDelay + * mode_lib->vba.SrcActiveDrainRate + + mode_lib->vba.FinalFillMargin; + mode_lib->vba.RemainingFillLevel = dml_max( + 0.0, + mode_lib->vba.FinalFillLevel - mode_lib->vba.InitFillLevel); mode_lib->vba.TFinalxFill = mode_lib->vba.RemainingFillLevel - / (mode_lib->vba.SrcActiveDrainRate * mode_lib->vba.XFCFillBWOverhead / 100); - mode_lib->vba.XFCPrefetchMargin[k] = mode_lib->vba.XFCRemoteSurfaceFlipDelay + mode_lib->vba.TFinalxFill - + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] - + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) - * mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]; + / (mode_lib->vba.SrcActiveDrainRate + * mode_lib->vba.XFCFillBWOverhead / 100); + mode_lib->vba.XFCPrefetchMargin[k] = + mode_lib->vba.XFCRemoteSurfaceFlipDelay + + mode_lib->vba.TFinalxFill + + (mode_lib->vba.DestinationLinesToRequestVMInVBlank[k] + + mode_lib->vba.DestinationLinesToRequestRowInVBlank[k]) + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]; } else { mode_lib->vba.XFCSlaveVUpdateOffset[k] = 0; mode_lib->vba.XFCSlaveVupdateWidth[k] = 0; @@ -2782,21 +3279,22 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) BytePerPixDETC = 8.0 / 3.0; } - if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { Read256BytesBlockHeightY = 1; } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { Read256BytesBlockHeightY = 4; } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16) { Read256BytesBlockHeightY = 8; } else { Read256BytesBlockHeightY = 16; } Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) - / Read256BytesBlockHeightY; + / Read256BytesBlockHeightY; Read256BytesBlockHeightC = 0; Read256BytesBlockWidthC = 0; } else { @@ -2811,9 +3309,9 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) Read256BytesBlockHeightC = 8; } Read256BytesBlockWidthY = 256 / dml_ceil(BytePerPixDETY, 1) - / Read256BytesBlockHeightY; + / Read256BytesBlockHeightY; Read256BytesBlockWidthC = 256 / dml_ceil(BytePerPixDETC, 2) - / Read256BytesBlockHeightC; + / Read256BytesBlockHeightC; } if (mode_lib->vba.SourceScan[k] == dm_horz) { @@ -2824,27 +3322,30 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) MaximumSwathHeightC = Read256BytesBlockWidthC; } - if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 - || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_8)) { if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear - || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 - && (mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_4kb_s_x - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_64kb_s - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_64kb_s_t - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_64kb_s_x - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_var_s - || mode_lib->vba.SurfaceTiling[k] - == dm_sw_var_s_x) - && mode_lib->vba.SourceScan[k] == dm_horz)) { + || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s_x) + && mode_lib->vba.SourceScan[k] == dm_horz)) { MinimumSwathHeightY = MaximumSwathHeightY; - } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8 && mode_lib->vba.SourceScan[k] != dm_horz) { + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_8 + && mode_lib->vba.SourceScan[k] != dm_horz) { MinimumSwathHeightY = MaximumSwathHeightY; } else { MinimumSwathHeightY = MaximumSwathHeightY / 2.0; @@ -2854,10 +3355,12 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { MinimumSwathHeightY = MaximumSwathHeightY; MinimumSwathHeightC = MaximumSwathHeightC; - } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 && mode_lib->vba.SourceScan[k] == dm_horz) { + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 + && mode_lib->vba.SourceScan[k] == dm_horz) { MinimumSwathHeightY = MaximumSwathHeightY / 2.0; MinimumSwathHeightC = MaximumSwathHeightC; - } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 && mode_lib->vba.SourceScan[k] == dm_horz) { + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 + && mode_lib->vba.SourceScan[k] == dm_horz) { MinimumSwathHeightC = MaximumSwathHeightC / 2.0; MinimumSwathHeightY = MaximumSwathHeightY; } else { @@ -2876,40 +3379,46 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) MainPlaneDoesODMCombine = true; } for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { - if (mode_lib->vba.BlendingAndTiming[k] == j && mode_lib->vba.ODMCombineEnabled[j] == true) { + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.ODMCombineEnabled[j] == true) { MainPlaneDoesODMCombine = true; } } if (MainPlaneDoesODMCombine == true) { - SwathWidth = dml_min(SwathWidth, mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]); + SwathWidth = dml_min( + SwathWidth, + mode_lib->vba.HActive[k] / 2.0 * mode_lib->vba.HRatio[k]); } else { SwathWidth = SwathWidth / mode_lib->vba.DPPPerPlane[k]; } SwathWidthGranularityY = 256 / dml_ceil(BytePerPixDETY, 1) / MaximumSwathHeightY; - RoundedUpMaxSwathSizeBytesY = (dml_ceil((double)(SwathWidth - 1), - SwathWidthGranularityY) + SwathWidthGranularityY) * BytePerPixDETY - * MaximumSwathHeightY; + RoundedUpMaxSwathSizeBytesY = (dml_ceil( + (double) (SwathWidth - 1), + SwathWidthGranularityY) + SwathWidthGranularityY) * BytePerPixDETY + * MaximumSwathHeightY; if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { RoundedUpMaxSwathSizeBytesY = dml_ceil(RoundedUpMaxSwathSizeBytesY, 256) - + 256; + + 256; } if (MaximumSwathHeightC > 0) { SwathWidthGranularityC = 256.0 / dml_ceil(BytePerPixDETC, 2) - / MaximumSwathHeightC; - RoundedUpMaxSwathSizeBytesC = (dml_ceil((double)(SwathWidth / 2.0 - 1), - SwathWidthGranularityC) + SwathWidthGranularityC) - * BytePerPixDETC * MaximumSwathHeightC; + / MaximumSwathHeightC; + RoundedUpMaxSwathSizeBytesC = (dml_ceil( + (double) (SwathWidth / 2.0 - 1), + SwathWidthGranularityC) + SwathWidthGranularityC) + * BytePerPixDETC * MaximumSwathHeightC; if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { - RoundedUpMaxSwathSizeBytesC = dml_ceil(RoundedUpMaxSwathSizeBytesC, - 256) + 256; + RoundedUpMaxSwathSizeBytesC = dml_ceil( + RoundedUpMaxSwathSizeBytesC, + 256) + 256; } } else RoundedUpMaxSwathSizeBytesC = 0.0; if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC - <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY; mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC; } else { @@ -2921,27 +3430,32 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024; mode_lib->vba.DETBufferSizeC[k] = 0; } else if (mode_lib->vba.SwathHeightY[k] <= mode_lib->vba.SwathHeightC[k]) { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2; - mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2; + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2; } else { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 * 2 / 3; - mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 3; + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 * 2 / 3; + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 3; } } } -bool Calculate256BBlockSizes(enum source_format_class SourcePixelFormat, - enum dm_swizzle_mode SurfaceTiling, - unsigned int BytePerPixelY, - unsigned int BytePerPixelC, - unsigned int *BlockHeight256BytesY, - unsigned int *BlockHeight256BytesC, - unsigned int *BlockWidth256BytesY, - unsigned int *BlockWidth256BytesC) +bool Calculate256BBlockSizes( + enum source_format_class SourcePixelFormat, + enum dm_swizzle_mode SurfaceTiling, + unsigned int BytePerPixelY, + unsigned int BytePerPixelC, + unsigned int *BlockHeight256BytesY, + unsigned int *BlockHeight256BytesC, + unsigned int *BlockWidth256BytesY, + unsigned int *BlockWidth256BytesC) { if ((SourcePixelFormat == dm_444_64 || SourcePixelFormat == dm_444_32 - || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16 - || SourcePixelFormat == dm_444_8)) { + || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16 + || SourcePixelFormat == dm_444_8)) { if (SurfaceTiling == dm_sw_linear) { *BlockHeight256BytesY = 1; } else if (SourcePixelFormat == dm_444_64) { @@ -2971,14 +3485,16 @@ bool Calculate256BBlockSizes(enum source_format_class SourcePixelFormat, return true; } -static double CalculateTWait(unsigned int PrefetchMode, - double DRAMClockChangeLatency, - double UrgentLatency, - double SREnterPlusExitTime) +static double CalculateTWait( + unsigned int PrefetchMode, + double DRAMClockChangeLatency, + double UrgentLatency, + double SREnterPlusExitTime) { if (PrefetchMode == 0) { - return dml_max(DRAMClockChangeLatency + UrgentLatency, - dml_max(SREnterPlusExitTime, UrgentLatency)); + return dml_max( + DRAMClockChangeLatency + UrgentLatency, + dml_max(SREnterPlusExitTime, UrgentLatency)); } else if (PrefetchMode == 1) { return dml_max(SREnterPlusExitTime, UrgentLatency); } else { @@ -2986,23 +3502,24 @@ static double CalculateTWait(unsigned int PrefetchMode, } } -static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, - double VRatio, - double SwathWidth, - double Bpp, - double LineTime, - double XFCTSlvVupdateOffset, - double XFCTSlvVupdateWidth, - double XFCTSlvVreadyOffset, - double XFCXBUFLatencyTolerance, - double XFCFillBWOverhead, - double XFCSlvChunkSize, - double XFCBusTransportTime, - double TCalc, - double TWait, - double *SrcActiveDrainRate, - double *TInitXFill, - double *TslvChk) +static double CalculateRemoteSurfaceFlipDelay( + struct display_mode_lib *mode_lib, + double VRatio, + double SwathWidth, + double Bpp, + double LineTime, + double XFCTSlvVupdateOffset, + double XFCTSlvVupdateWidth, + double XFCTSlvVreadyOffset, + double XFCXBUFLatencyTolerance, + double XFCFillBWOverhead, + double XFCSlvChunkSize, + double XFCBusTransportTime, + double TCalc, + double TWait, + double *SrcActiveDrainRate, + double *TInitXFill, + double *TslvChk) { double TSlvSetup, AvgfillRate, result; @@ -3011,8 +3528,9 @@ static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, *TInitXFill = XFCXBUFLatencyTolerance / (1 + XFCFillBWOverhead / 100); AvgfillRate = *SrcActiveDrainRate * (1 + XFCFillBWOverhead / 100); *TslvChk = XFCSlvChunkSize / AvgfillRate; - dml_print("DML::CalculateRemoteSurfaceFlipDelay: SrcActiveDrainRate: %f\n", - *SrcActiveDrainRate); + dml_print( + "DML::CalculateRemoteSurfaceFlipDelay: SrcActiveDrainRate: %f\n", + *SrcActiveDrainRate); dml_print("DML::CalculateRemoteSurfaceFlipDelay: TSlvSetup: %f\n", TSlvSetup); dml_print("DML::CalculateRemoteSurfaceFlipDelay: TInitXFill: %f\n", *TInitXFill); dml_print("DML::CalculateRemoteSurfaceFlipDelay: AvgfillRate: %f\n", AvgfillRate); @@ -3022,99 +3540,192 @@ static double CalculateRemoteSurfaceFlipDelay(struct display_mode_lib *mode_lib, return result; } -static double CalculateWriteBackDISPCLK(enum source_format_class WritebackPixelFormat, - double PixelClock, - double WritebackHRatio, - double WritebackVRatio, - unsigned int WritebackLumaHTaps, - unsigned int WritebackLumaVTaps, - unsigned int WritebackChromaHTaps, - unsigned int WritebackChromaVTaps, - double WritebackDestinationWidth, - unsigned int HTotal, - unsigned int WritebackChromaLineBufferWidth) +static double CalculateWriteBackDISPCLK( + enum source_format_class WritebackPixelFormat, + double PixelClock, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + double WritebackDestinationWidth, + unsigned int HTotal, + unsigned int WritebackChromaLineBufferWidth) { - double CalculateWriteBackDISPCLK = 1.01 * PixelClock - * dml_max( - dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, - dml_max( - (WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) - * dml_ceil(WritebackDestinationWidth / 4.0, 1) - + dml_ceil(WritebackDestinationWidth / 4.0, 1)) / (double)HTotal - + dml_ceil(1.0 / WritebackVRatio, 1) * (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4.0) - / (double)HTotal, - dml_ceil(1.0 / WritebackVRatio, 1) * WritebackDestinationWidth / (double)HTotal)); - if (WritebackPixelFormat != dm_444_32) { - CalculateWriteBackDISPCLK = dml_max( - CalculateWriteBackDISPCLK, + double CalculateWriteBackDISPCLK = 1.01 * PixelClock - * dml_max( - dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio), + * dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) + / WritebackHRatio, + dml_max( + (WritebackLumaVTaps + * dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * dml_ceil( + WritebackDestinationWidth + / 4.0, + 1) + + dml_ceil( + WritebackDestinationWidth + / 4.0, + 1)) + / (double) HTotal + + dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * (dml_ceil( + WritebackLumaVTaps + / 4.0, + 1) + + 4.0) + / (double) HTotal, + dml_ceil( + 1.0 + / WritebackVRatio, + 1) + * WritebackDestinationWidth + / (double) HTotal)); + if (WritebackPixelFormat != dm_444_32) { + CalculateWriteBackDISPCLK = dml_max( - (WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) - * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1) - + dml_ceil(WritebackDestinationWidth / 2.0 / WritebackChromaLineBufferWidth, 1)) - / HTotal - + dml_ceil(1 / (2 * WritebackVRatio), 1) - * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4) / HTotal, - dml_ceil(1.0 / (2 * WritebackVRatio), 1) * WritebackDestinationWidth / 2.0 - / HTotal))); + CalculateWriteBackDISPCLK, + 1.01 * PixelClock + * dml_max( + dml_ceil( + WritebackChromaHTaps + / 2.0, + 1) + / (2 + * WritebackHRatio), + dml_max( + (WritebackChromaVTaps + * dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * dml_ceil( + WritebackDestinationWidth + / 2.0 + / 2.0, + 1) + + dml_ceil( + WritebackDestinationWidth + / 2.0 + / WritebackChromaLineBufferWidth, + 1)) + / HTotal + + dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * (dml_ceil( + WritebackChromaVTaps + / 4.0, + 1) + + 4) + / HTotal, + dml_ceil( + 1.0 + / (2 + * WritebackVRatio), + 1) + * WritebackDestinationWidth + / 2.0 + / HTotal))); } return CalculateWriteBackDISPCLK; } static double CalculateWriteBackDelay( -enum source_format_class WritebackPixelFormat, - double WritebackHRatio, - double WritebackVRatio, - unsigned int WritebackLumaHTaps, - unsigned int WritebackLumaVTaps, - unsigned int WritebackChromaHTaps, - unsigned int WritebackChromaVTaps, - unsigned int WritebackDestinationWidth) + enum source_format_class WritebackPixelFormat, + double WritebackHRatio, + double WritebackVRatio, + unsigned int WritebackLumaHTaps, + unsigned int WritebackLumaVTaps, + unsigned int WritebackChromaHTaps, + unsigned int WritebackChromaVTaps, + unsigned int WritebackDestinationWidth) { - double CalculateWriteBackDelay = dml_max( - dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, - WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) - * dml_ceil(WritebackDestinationWidth / 4.0, 1) - + dml_ceil(1.0 / WritebackVRatio, 1) * (dml_ceil(WritebackLumaVTaps / 4.0, 1) + 4)); + double CalculateWriteBackDelay = + dml_max( + dml_ceil(WritebackLumaHTaps / 4.0, 1) / WritebackHRatio, + WritebackLumaVTaps * dml_ceil(1.0 / WritebackVRatio, 1) + * dml_ceil( + WritebackDestinationWidth + / 4.0, + 1) + + dml_ceil(1.0 / WritebackVRatio, 1) + * (dml_ceil( + WritebackLumaVTaps + / 4.0, + 1) + 4)); if (WritebackPixelFormat != dm_444_32) { - CalculateWriteBackDelay = dml_max( - CalculateWriteBackDelay, - dml_max( - dml_ceil(WritebackChromaHTaps / 2.0, 1) / (2 * WritebackHRatio), - WritebackChromaVTaps * dml_ceil(1 / (2 * WritebackVRatio), 1) - * dml_ceil(WritebackDestinationWidth / 2.0 / 2.0, 1) - + dml_ceil(1 / (2 * WritebackVRatio), 1) - * (dml_ceil(WritebackChromaVTaps / 4.0, 1) + 4))); + CalculateWriteBackDelay = + dml_max( + CalculateWriteBackDelay, + dml_max( + dml_ceil( + WritebackChromaHTaps + / 2.0, + 1) + / (2 + * WritebackHRatio), + WritebackChromaVTaps + * dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * dml_ceil( + WritebackDestinationWidth + / 2.0 + / 2.0, + 1) + + dml_ceil( + 1 + / (2 + * WritebackVRatio), + 1) + * (dml_ceil( + WritebackChromaVTaps + / 4.0, + 1) + + 4))); } return CalculateWriteBackDelay; } -static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, - enum source_format_class SourcePixelFormat, - double VRatio, - bool DCCEnable, - double LineTime, - unsigned int MetaRowByteLuma, - unsigned int MetaRowByteChroma, - unsigned int meta_row_height_luma, - unsigned int meta_row_height_chroma, - unsigned int PixelPTEBytesPerRowLuma, - unsigned int PixelPTEBytesPerRowChroma, - unsigned int dpte_row_height_luma, - unsigned int dpte_row_height_chroma, - double *meta_row_bw, - double *dpte_row_bw, - double *qual_row_bw) +static void CalculateActiveRowBandwidth( + bool VirtualMemoryEnable, + enum source_format_class SourcePixelFormat, + double VRatio, + bool DCCEnable, + double LineTime, + unsigned int MetaRowByteLuma, + unsigned int MetaRowByteChroma, + unsigned int meta_row_height_luma, + unsigned int meta_row_height_chroma, + unsigned int PixelPTEBytesPerRowLuma, + unsigned int PixelPTEBytesPerRowChroma, + unsigned int dpte_row_height_luma, + unsigned int dpte_row_height_chroma, + double *meta_row_bw, + double *dpte_row_bw, + double *qual_row_bw) { if (DCCEnable != true) { *meta_row_bw = 0; } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime) - + VRatio / 2 * MetaRowByteChroma - / (meta_row_height_chroma * LineTime); + + VRatio / 2 * MetaRowByteChroma + / (meta_row_height_chroma * LineTime); } else { *meta_row_bw = VRatio * MetaRowByteLuma / (meta_row_height_luma * LineTime); } @@ -3123,8 +3734,8 @@ static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, *dpte_row_bw = 0; } else if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime) - + VRatio / 2 * PixelPTEBytesPerRowChroma - / (dpte_row_height_chroma * LineTime); + + VRatio / 2 * PixelPTEBytesPerRowChroma + / (dpte_row_height_chroma * LineTime); } else { *dpte_row_bw = VRatio * PixelPTEBytesPerRowLuma / (dpte_row_height_luma * LineTime); } @@ -3136,29 +3747,30 @@ static void CalculateActiveRowBandwidth(bool VirtualMemoryEnable, } } -static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, - double UrgentExtraLatency, - double UrgentLatency, - unsigned int MaxPageTableLevels, - bool VirtualMemoryEnable, - double BandwidthAvailableForImmediateFlip, - unsigned int TotImmediateFlipBytes, - enum source_format_class SourcePixelFormat, - unsigned int ImmediateFlipBytes, - double LineTime, - double Tno_bw, - double VRatio, - double PDEAndMetaPTEBytesFrame, - unsigned int MetaRowByte, - unsigned int PixelPTEBytesPerRow, - bool DCCEnable, - unsigned int dpte_row_height, - unsigned int meta_row_height, - double qual_row_bw, - double *DestinationLinesToRequestVMInImmediateFlip, - double *DestinationLinesToRequestRowInImmediateFlip, - double *final_flip_bw, - bool *ImmediateFlipSupportedForPipe) +static void CalculateFlipSchedule( + struct display_mode_lib *mode_lib, + double UrgentExtraLatency, + double UrgentLatency, + unsigned int MaxPageTableLevels, + bool VirtualMemoryEnable, + double BandwidthAvailableForImmediateFlip, + unsigned int TotImmediateFlipBytes, + enum source_format_class SourcePixelFormat, + unsigned int ImmediateFlipBytes, + double LineTime, + double Tno_bw, + double VRatio, + double PDEAndMetaPTEBytesFrame, + unsigned int MetaRowByte, + unsigned int PixelPTEBytesPerRow, + bool DCCEnable, + unsigned int dpte_row_height, + unsigned int meta_row_height, + double qual_row_bw, + double *DestinationLinesToRequestVMInImmediateFlip, + double *DestinationLinesToRequestRowInImmediateFlip, + double *final_flip_bw, + bool *ImmediateFlipSupportedForPipe) { double min_row_time = 0.0; @@ -3172,47 +3784,54 @@ static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, double TimeForFetchingRowInVBlankImmediateFlip; if (VirtualMemoryEnable == true) { - mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip * ImmediateFlipBytes - / TotImmediateFlipBytes; + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip + * ImmediateFlipBytes / TotImmediateFlipBytes; TimeForFetchingMetaPTEImmediateFlip = - dml_max(Tno_bw - + PDEAndMetaPTEBytesFrame - / mode_lib->vba.ImmediateFlipBW, - dml_max(UrgentExtraLatency - + UrgentLatency - * (MaxPageTableLevels - - 1), - LineTime / 4.0)); + dml_max( + Tno_bw + + PDEAndMetaPTEBytesFrame + / mode_lib->vba.ImmediateFlipBW, + dml_max( + UrgentExtraLatency + + UrgentLatency + * (MaxPageTableLevels + - 1), + LineTime / 4.0)); } else { TimeForFetchingMetaPTEImmediateFlip = 0; } - *DestinationLinesToRequestVMInImmediateFlip = dml_floor(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime + 0.125), - 1) / 4.0; + *DestinationLinesToRequestVMInImmediateFlip = dml_floor( + 4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime + 0.125), + 1) / 4.0; if ((VirtualMemoryEnable == true || DCCEnable == true)) { - mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip * ImmediateFlipBytes - / TotImmediateFlipBytes; - TimeForFetchingRowInVBlankImmediateFlip = dml_max((MetaRowByte + PixelPTEBytesPerRow) / mode_lib->vba.ImmediateFlipBW, - dml_max(UrgentLatency, LineTime / 4.0)); + mode_lib->vba.ImmediateFlipBW = BandwidthAvailableForImmediateFlip + * ImmediateFlipBytes / TotImmediateFlipBytes; + TimeForFetchingRowInVBlankImmediateFlip = dml_max( + (MetaRowByte + PixelPTEBytesPerRow) + / mode_lib->vba.ImmediateFlipBW, + dml_max(UrgentLatency, LineTime / 4.0)); } else { TimeForFetchingRowInVBlankImmediateFlip = 0; } - *DestinationLinesToRequestRowInImmediateFlip = dml_floor(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime + 0.125), - 1) / 4.0; + *DestinationLinesToRequestRowInImmediateFlip = dml_floor( + 4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime + 0.125), + 1) / 4.0; if (VirtualMemoryEnable == true) { *final_flip_bw = - dml_max(PDEAndMetaPTEBytesFrame - / (*DestinationLinesToRequestVMInImmediateFlip - * LineTime), - (MetaRowByte + PixelPTEBytesPerRow) - / (TimeForFetchingRowInVBlankImmediateFlip - * LineTime)); + dml_max( + PDEAndMetaPTEBytesFrame + / (*DestinationLinesToRequestVMInImmediateFlip + * LineTime), + (MetaRowByte + PixelPTEBytesPerRow) + / (TimeForFetchingRowInVBlankImmediateFlip + * LineTime)); } else if (MetaRowByte + PixelPTEBytesPerRow > 0) { *final_flip_bw = (MetaRowByte + PixelPTEBytesPerRow) - / (TimeForFetchingRowInVBlankImmediateFlip * LineTime); + / (TimeForFetchingRowInVBlankImmediateFlip * LineTime); } else { *final_flip_bw = 0; } @@ -3223,12 +3842,13 @@ static void CalculateFlipSchedule(struct display_mode_lib *mode_lib, min_row_time = meta_row_height * LineTime / VRatio; else min_row_time = dml_min(dpte_row_height, meta_row_height) * LineTime - / VRatio; + / VRatio; if (*DestinationLinesToRequestVMInImmediateFlip >= 8 || *DestinationLinesToRequestRowInImmediateFlip >= 16 || TimeForFetchingMetaPTEImmediateFlip - + 2 * TimeForFetchingRowInVBlankImmediateFlip > min_row_time) + + 2 * TimeForFetchingRowInVBlankImmediateFlip + > min_row_time) *ImmediateFlipSupportedForPipe = false; else *ImmediateFlipSupportedForPipe = true; @@ -3242,7 +3862,8 @@ static void PixelClockAdjustmentForProgressiveToInterlaceUnit(struct display_mod //Progressive To dml_ml->vba.Interlace Unit Effect for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { mode_lib->vba.PixelClockBackEnd[k] = mode_lib->vba.PixelClock[k]; - if (mode_lib->vba.Interlace[k] == 1 && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) { + if (mode_lib->vba.Interlace[k] == 1 + && mode_lib->vba.ProgressiveToInterlaceUnitInOPP == true) { mode_lib->vba.PixelClock[k] = 2 * mode_lib->vba.PixelClock[k]; } } @@ -3261,3 +3882,2211 @@ static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp) return 0; } } + +static unsigned int TruncToValidBPP( + double DecimalBPP, + bool DSCEnabled, + enum output_encoder_class Output, + enum output_format_class Format, + unsigned int DSCInputBitPerComponent) +{ + if (Output == dm_hdmi) { + if (Format == dm_420) { + if (DecimalBPP >= 18) + return 18; + else if (DecimalBPP >= 15) + return 15; + else if (DecimalBPP >= 12) + return 12; + else + return 0; + } else if (Format == dm_444) { + if (DecimalBPP >= 36) + return 36; + else if (DecimalBPP >= 30) + return 30; + else if (DecimalBPP >= 24) + return 24; + else + return 0; + } else { + if (DecimalBPP / 1.5 >= 24) + return 24; + else if (DecimalBPP / 1.5 >= 20) + return 20; + else if (DecimalBPP / 1.5 >= 16) + return 16; + else + return 0; + } + } else { + if (DSCEnabled) { + if (Format == dm_420) { + if (DecimalBPP < 6) + return 0; + else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1 / 16) + return 1.5 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } else if (Format == dm_n422) { + if (DecimalBPP < 7) + return 0; + else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1 / 16) + return 2 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } else { + if (DecimalBPP < 8) + return 0; + else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1 / 16) + return 3 * DSCInputBitPerComponent - 1 / 16; + else + return dml_floor(16 * DecimalBPP, 1) / 16; + } + } else if (Format == dm_420) { + if (DecimalBPP >= 18) + return 18; + else if (DecimalBPP >= 15) + return 15; + else if (DecimalBPP >= 12) + return 12; + else + return 0; + } else if (Format == dm_s422 || Format == dm_n422) { + if (DecimalBPP >= 24) + return 24; + else if (DecimalBPP >= 20) + return 20; + else if (DecimalBPP >= 16) + return 16; + else + return 0; + } else { + if (DecimalBPP >= 36) + return 36; + else if (DecimalBPP >= 30) + return 30; + else if (DecimalBPP >= 24) + return 24; + else + return 0; + } + } +} + +static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib) +{ + int i; + unsigned int j, k; + /*MODE SUPPORT, VOLTAGE STATE AND SOC CONFIGURATION*/ + + /*Scale Ratio, taps Support Check*/ + + mode_lib->vba.ScaleRatioAndTapsSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ScalerEnabled[k] == false + && ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8) + || mode_lib->vba.HRatio[k] != 1.0 + || mode_lib->vba.htaps[k] != 1.0 + || mode_lib->vba.VRatio[k] != 1.0 + || mode_lib->vba.vtaps[k] != 1.0)) { + mode_lib->vba.ScaleRatioAndTapsSupport = false; + } else if (mode_lib->vba.vtaps[k] < 1.0 || mode_lib->vba.vtaps[k] > 8.0 + || mode_lib->vba.htaps[k] < 1.0 || mode_lib->vba.htaps[k] > 8.0 + || (mode_lib->vba.htaps[k] > 1.0 + && (mode_lib->vba.htaps[k] % 2) == 1) + || mode_lib->vba.HRatio[k] > mode_lib->vba.MaxHSCLRatio + || mode_lib->vba.VRatio[k] > mode_lib->vba.MaxVSCLRatio + || mode_lib->vba.HRatio[k] > mode_lib->vba.htaps[k] + || mode_lib->vba.VRatio[k] > mode_lib->vba.vtaps[k] + || (mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8 + && (mode_lib->vba.HRatio[k] / 2.0 + > mode_lib->vba.HTAPsChroma[k] + || mode_lib->vba.VRatio[k] / 2.0 + > mode_lib->vba.VTAPsChroma[k]))) { + mode_lib->vba.ScaleRatioAndTapsSupport = false; + } + } + /*Source Format, Pixel Format and Scan Support Check*/ + + mode_lib->vba.SourceFormatPixelAndScanSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if ((mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + && mode_lib->vba.SourceScan[k] != dm_horz) + || ((mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_var_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_var_d_x) + && mode_lib->vba.SourcePixelFormat[k] != dm_444_64) + || (mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_r_x + && (mode_lib->vba.SourcePixelFormat[k] == dm_mono_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_10)) + || (((mode_lib->vba.SurfaceTiling[k] + == dm_sw_gfx7_2d_thin_gl + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_gfx7_2d_thin_lvp) + && !((mode_lib->vba.SourcePixelFormat[k] + == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] + == dm_444_32) + && mode_lib->vba.SourceScan[k] + == dm_horz + && mode_lib->vba.SupportGFX7CompatibleTilingIn32bppAnd64bpp + == true + && mode_lib->vba.DCCEnable[k] + == false)) + || (mode_lib->vba.DCCEnable[k] == true + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_linear + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_8 + || mode_lib->vba.SourcePixelFormat[k] + == dm_420_10)))) { + mode_lib->vba.SourceFormatPixelAndScanSupport = false; + } + } + /*Bandwidth Support Check*/ + + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.SwathWidthYSingleDPP[k] = mode_lib->vba.ViewportWidth[k]; + } else { + mode_lib->vba.SwathWidthYSingleDPP[k] = mode_lib->vba.ViewportHeight[k]; + } + if (mode_lib->vba.SourcePixelFormat[k] == dm_444_64) { + mode_lib->vba.BytePerPixelInDETY[k] = 8.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_32) { + mode_lib->vba.BytePerPixelInDETY[k] = 4.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_16) { + mode_lib->vba.BytePerPixelInDETY[k] = 2.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_mono_8) { + mode_lib->vba.BytePerPixelInDETY[k] = 1.0; + mode_lib->vba.BytePerPixelInDETC[k] = 0.0; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8) { + mode_lib->vba.BytePerPixelInDETY[k] = 1.0; + mode_lib->vba.BytePerPixelInDETC[k] = 2.0; + } else { + mode_lib->vba.BytePerPixelInDETY[k] = 4.0 / 3; + mode_lib->vba.BytePerPixelInDETC[k] = 8.0 / 3; + } + } + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.SwathWidthYSingleDPP[k] + * (dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0) + * mode_lib->vba.VRatio[k] + + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0) + / 2.0 * mode_lib->vba.VRatio[k] / 2) + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]); + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 256); + } + if (mode_lib->vba.VirtualMemoryEnable == true + && mode_lib->vba.SourceScan[k] != dm_horz + && (mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_4kb_d_x)) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 64); + } else if (mode_lib->vba.VirtualMemoryEnable == true + && mode_lib->vba.SourceScan[k] == dm_horz + && (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32) + && (mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_t + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_d_x + || mode_lib->vba.SurfaceTiling[k] == dm_sw_64kb_r_x)) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 256); + } else if (mode_lib->vba.VirtualMemoryEnable == true) { + mode_lib->vba.ReadBandwidth[k] = mode_lib->vba.ReadBandwidth[k] + * (1 + 1 / 512); + } + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond + + mode_lib->vba.ReadBandwidth[k] / 1000.0; + } + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 4.0; + } else if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 3.0; + } else if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WriteBandwidth[k] = mode_lib->vba.WritebackDestinationWidth[k] + * mode_lib->vba.WritebackDestinationHeight[k] + / (mode_lib->vba.WritebackSourceHeight[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) * 1.5; + } else { + mode_lib->vba.WriteBandwidth[k] = 0.0; + } + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond + + mode_lib->vba.WriteBandwidth[k] / 1000.0; + } + mode_lib->vba.TotalBandwidthConsumedGBytePerSecond = + mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond + + mode_lib->vba.TotalWriteBandwidthConsumedGBytePerSecond; + mode_lib->vba.DCCEnabledInAnyPlane = false; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.DCCEnabledInAnyPlane = true; + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] = dml_min( + mode_lib->vba.DRAMSpeedPerState[i] * mode_lib->vba.NumberOfChannels + * mode_lib->vba.DRAMChannelWidth, + mode_lib->vba.FabricClockPerState[i] + * mode_lib->vba.FabricDatapathToDCNDataReturn) + / 1000; + mode_lib->vba.ReturnBWToDCNPerState = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i], + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] * 1000.0) + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency + / 100; + mode_lib->vba.ReturnBWPerState[i] = mode_lib->vba.ReturnBWToDCNPerState; + if (mode_lib->vba.DCCEnabledInAnyPlane == true + && mode_lib->vba.ReturnBWToDCNPerState + > mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.ReturnBWToDCNPerState * 4.0 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + / (mode_lib->vba.ReturnBWToDCNPerState + - mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) + + mode_lib->vba.UrgentLatency))); + } + mode_lib->vba.CriticalPoint = + 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true && mode_lib->vba.CriticalPoint > 1.0 + && mode_lib->vba.CriticalPoint < 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + dml_pow( + 4.0 + * mode_lib->vba.ReturnBWToDCNPerState + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0), + 2)); + } + mode_lib->vba.ReturnBWToDCNPerState = dml_min( + mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i], + mode_lib->vba.FabricAndDRAMBandwidthPerState[i] * 1000.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true + && mode_lib->vba.ReturnBWToDCNPerState + > mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.ReturnBWToDCNPerState * 4.0 + * (1.0 + - mode_lib->vba.UrgentLatency + / ((mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + / (mode_lib->vba.ReturnBWToDCNPerState + - mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.ReturnBusWidth + / 4.0) + + mode_lib->vba.UrgentLatency))); + } + mode_lib->vba.CriticalPoint = + 2.0 * mode_lib->vba.ReturnBusWidth * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0); + if (mode_lib->vba.DCCEnabledInAnyPlane == true && mode_lib->vba.CriticalPoint > 1.0 + && mode_lib->vba.CriticalPoint < 4.0) { + mode_lib->vba.ReturnBWPerState[i] = + dml_min( + mode_lib->vba.ReturnBWPerState[i], + dml_pow( + 4.0 + * mode_lib->vba.ReturnBWToDCNPerState + * (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 + * mode_lib->vba.ReturnBusWidth + * mode_lib->vba.DCFCLKPerState[i] + * mode_lib->vba.UrgentLatency + / (mode_lib->vba.ReturnBWToDCNPerState + * mode_lib->vba.UrgentLatency + + (mode_lib->vba.ROBBufferSizeInKByte + - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0), + 2)); + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if ((mode_lib->vba.TotalReadBandwidthConsumedGBytePerSecond * 1000.0 + <= mode_lib->vba.ReturnBWPerState[i]) + && (mode_lib->vba.TotalBandwidthConsumedGBytePerSecond * 1000.0 + <= mode_lib->vba.FabricAndDRAMBandwidthPerState[i] + * 1000.0 + * mode_lib->vba.PercentOfIdealDRAMAndFabricBWReceivedAfterUrgLatency + / 100.0)) { + mode_lib->vba.BandwidthSupport[i] = true; + } else { + mode_lib->vba.BandwidthSupport[i] = false; + } + } + /*Writeback Latency support check*/ + + mode_lib->vba.WritebackLatencySupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + if (mode_lib->vba.WritebackPixelFormat[k] == dm_444_32) { + if (mode_lib->vba.WriteBandwidth[k] + > (mode_lib->vba.WritebackInterfaceLumaBufferSize + + mode_lib->vba.WritebackInterfaceChromaBufferSize) + / mode_lib->vba.WritebackLatency) { + mode_lib->vba.WritebackLatencySupport = false; + } + } else { + if (mode_lib->vba.WriteBandwidth[k] + > 1.5 + * dml_min( + mode_lib->vba.WritebackInterfaceLumaBufferSize, + 2.0 + * mode_lib->vba.WritebackInterfaceChromaBufferSize) + / mode_lib->vba.WritebackLatency) { + mode_lib->vba.WritebackLatencySupport = false; + } + } + } + } + /*Re-ordering Buffer Support Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i] = + (mode_lib->vba.RoundTripPingLatencyCycles + 32.0) + / mode_lib->vba.DCFCLKPerState[i] + + mode_lib->vba.UrgentOutOfOrderReturnPerChannel + * mode_lib->vba.NumberOfChannels + / mode_lib->vba.ReturnBWPerState[i]; + if ((mode_lib->vba.ROBBufferSizeInKByte - mode_lib->vba.PixelChunkSizeInKByte) + * 1024.0 / mode_lib->vba.ReturnBWPerState[i] + > mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { + mode_lib->vba.ROBSupport[i] = true; + } else { + mode_lib->vba.ROBSupport[i] = false; + } + } + /*Writeback Mode Support Check*/ + + mode_lib->vba.TotalNumberOfActiveWriteback = 0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.TotalNumberOfActiveWriteback = + mode_lib->vba.TotalNumberOfActiveWriteback + 1; + } + } + mode_lib->vba.WritebackModeSupport = true; + if (mode_lib->vba.TotalNumberOfActiveWriteback > mode_lib->vba.MaxNumWriteback) { + mode_lib->vba.WritebackModeSupport = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true + && mode_lib->vba.Writeback10bpc420Supported != true + && mode_lib->vba.WritebackPixelFormat[k] == dm_420_10) { + mode_lib->vba.WritebackModeSupport = false; + } + } + /*Writeback Scale Ratio and Taps Support Check*/ + + mode_lib->vba.WritebackScaleRatioAndTapsSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + if (mode_lib->vba.WritebackLumaAndChromaScalingSupported == false + && (mode_lib->vba.WritebackHRatio[k] != 1.0 + || mode_lib->vba.WritebackVRatio[k] != 1.0)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (mode_lib->vba.WritebackHRatio[k] > mode_lib->vba.WritebackMaxHSCLRatio + || mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackMaxVSCLRatio + || mode_lib->vba.WritebackHRatio[k] + < mode_lib->vba.WritebackMinHSCLRatio + || mode_lib->vba.WritebackVRatio[k] + < mode_lib->vba.WritebackMinVSCLRatio + || mode_lib->vba.WritebackLumaHTaps[k] + > mode_lib->vba.WritebackMaxHSCLTaps + || mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackMaxVSCLTaps + || mode_lib->vba.WritebackHRatio[k] + > mode_lib->vba.WritebackLumaHTaps[k] + || mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackLumaVTaps[k] + || (mode_lib->vba.WritebackLumaHTaps[k] > 2.0 + && ((mode_lib->vba.WritebackLumaHTaps[k] % 2) + == 1)) + || (mode_lib->vba.WritebackPixelFormat[k] != dm_444_32 + && (mode_lib->vba.WritebackChromaHTaps[k] + > mode_lib->vba.WritebackMaxHSCLTaps + || mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackMaxVSCLTaps + || 2.0 + * mode_lib->vba.WritebackHRatio[k] + > mode_lib->vba.WritebackChromaHTaps[k] + || 2.0 + * mode_lib->vba.WritebackVRatio[k] + > mode_lib->vba.WritebackChromaVTaps[k] + || (mode_lib->vba.WritebackChromaHTaps[k] > 2.0 + && ((mode_lib->vba.WritebackChromaHTaps[k] % 2) == 1))))) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (mode_lib->vba.WritebackVRatio[k] < 1.0) { + mode_lib->vba.WritebackLumaVExtra = + dml_max(1.0 - 2.0 / dml_ceil(1.0 / mode_lib->vba.WritebackVRatio[k], 1.0), 0.0); + } else { + mode_lib->vba.WritebackLumaVExtra = -1; + } + if ((mode_lib->vba.WritebackPixelFormat[k] == dm_444_32 + && mode_lib->vba.WritebackLumaVTaps[k] + > (mode_lib->vba.WritebackLineBufferLumaBufferSize + + mode_lib->vba.WritebackLineBufferChromaBufferSize) + / 3.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_8 + && mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackLineBufferLumaBufferSize + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10 + && mode_lib->vba.WritebackLumaVTaps[k] + > mode_lib->vba.WritebackLineBufferLumaBufferSize + * 8.0 / 10.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackLumaVExtra)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + if (2.0 * mode_lib->vba.WritebackVRatio[k] < 1) { + mode_lib->vba.WritebackChromaVExtra = 0.0; + } else { + mode_lib->vba.WritebackChromaVExtra = -1; + } + if ((mode_lib->vba.WritebackPixelFormat[k] == dm_420_8 + && mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackLineBufferChromaBufferSize + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackChromaVExtra) + || (mode_lib->vba.WritebackPixelFormat[k] == dm_420_10 + && mode_lib->vba.WritebackChromaVTaps[k] + > mode_lib->vba.WritebackLineBufferChromaBufferSize + * 8.0 / 10.0 + / mode_lib->vba.WritebackDestinationWidth[k] + - mode_lib->vba.WritebackChromaVExtra)) { + mode_lib->vba.WritebackScaleRatioAndTapsSupport = false; + } + } + } + /*Maximum DISPCLK/DPPCLK Support check*/ + + mode_lib->vba.WritebackRequiredDISPCLK = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackRequiredDISPCLK = + dml_max( + mode_lib->vba.WritebackRequiredDISPCLK, + CalculateWriteBackDISPCLK( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.PixelClock[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.WritebackChromaLineBufferWidth)); + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.HRatio[k] > 1.0) { + mode_lib->vba.PSCL_FACTOR[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / dml_ceil( + mode_lib->vba.htaps[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_FACTOR[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = 0.0; + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = + mode_lib->vba.PixelClock[k] + * dml_max3( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_FACTOR[k], + 1.0); + if ((mode_lib->vba.htaps[k] > 6.0 || mode_lib->vba.vtaps[k] > 6.0) + && mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + < 2.0 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = 2.0 + * mode_lib->vba.PixelClock[k]; + } + } else { + if (mode_lib->vba.HRatio[k] / 2.0 > 1.0) { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = + dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput + * mode_lib->vba.HRatio[k] + / 2.0 + / dml_ceil( + mode_lib->vba.HTAPsChroma[k] + / 6.0, + 1.0)); + } else { + mode_lib->vba.PSCL_FACTOR_CHROMA[k] = dml_min( + mode_lib->vba.MaxDCHUBToPSCLThroughput, + mode_lib->vba.MaxPSCLToLBThroughput); + } + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = + mode_lib->vba.PixelClock[k] + * dml_max5( + mode_lib->vba.vtaps[k] / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k]), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / mode_lib->vba.PSCL_FACTOR[k], + mode_lib->vba.VTAPsChroma[k] + / 6.0 + * dml_min( + 1.0, + mode_lib->vba.HRatio[k] + / 2.0), + mode_lib->vba.HRatio[k] + * mode_lib->vba.VRatio[k] + / 4.0 + / mode_lib->vba.PSCL_FACTOR_CHROMA[k], + 1.0); + if ((mode_lib->vba.htaps[k] > 6.0 || mode_lib->vba.vtaps[k] > 6.0 + || mode_lib->vba.HTAPsChroma[k] > 6.0 + || mode_lib->vba.VTAPsChroma[k] > 6.0) + && mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + < 2.0 * mode_lib->vba.PixelClock[k]) { + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] = 2.0 + * mode_lib->vba.PixelClock[k]; + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + Calculate256BBlockSizes( + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0), + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0), + &mode_lib->vba.Read256BlockHeightY[k], + &mode_lib->vba.Read256BlockHeightC[k], + &mode_lib->vba.Read256BlockWidthY[k], + &mode_lib->vba.Read256BlockWidthC[k]); + if (mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MaxSwathHeightY[k] = mode_lib->vba.Read256BlockHeightY[k]; + mode_lib->vba.MaxSwathHeightC[k] = mode_lib->vba.Read256BlockHeightC[k]; + } else { + mode_lib->vba.MaxSwathHeightY[k] = mode_lib->vba.Read256BlockWidthY[k]; + mode_lib->vba.MaxSwathHeightC[k] = mode_lib->vba.Read256BlockWidthC[k]; + } + if ((mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_32 + || mode_lib->vba.SourcePixelFormat[k] == dm_444_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_16 + || mode_lib->vba.SourcePixelFormat[k] == dm_mono_8)) { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear + || (mode_lib->vba.SourcePixelFormat[k] == dm_444_64 + && (mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_4kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_t + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_64kb_s_x + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s + || mode_lib->vba.SurfaceTiling[k] + == dm_sw_var_s_x) + && mode_lib->vba.SourceScan[k] == dm_horz)) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + } else { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k] + / 2.0; + } + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else { + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_8 + && mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k] + / 2.0; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } else if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10 + && mode_lib->vba.SourceScan[k] == dm_horz) { + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k] + / 2.0; + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + } else { + mode_lib->vba.MinSwathHeightY[k] = mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.MinSwathHeightC[k] = mode_lib->vba.MaxSwathHeightC[k]; + } + } + if (mode_lib->vba.SurfaceTiling[k] == dm_sw_linear) { + mode_lib->vba.MaximumSwathWidthSupport = 8192.0; + } else { + mode_lib->vba.MaximumSwathWidthSupport = 5120.0; + } + mode_lib->vba.MaximumSwathWidthInDETBuffer = + dml_min( + mode_lib->vba.MaximumSwathWidthSupport, + mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0 + / (mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.MinSwathHeightY[k] + + mode_lib->vba.BytePerPixelInDETC[k] + / 2.0 + * mode_lib->vba.MinSwathHeightC[k])); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.MaximumSwathWidthInLineBuffer = + mode_lib->vba.LineBufferSize + * dml_max(mode_lib->vba.HRatio[k], 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.vtaps[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k], + 1.0) + - 2, + 0.0)); + } else { + mode_lib->vba.MaximumSwathWidthInLineBuffer = + dml_min( + mode_lib->vba.LineBufferSize + * dml_max( + mode_lib->vba.HRatio[k], + 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.vtaps[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k], + 1.0) + - 2, + 0.0)), + 2.0 * mode_lib->vba.LineBufferSize + * dml_max( + mode_lib->vba.HRatio[k] + / 2.0, + 1.0) + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.VTAPsChroma[k] + + dml_max( + dml_ceil( + mode_lib->vba.VRatio[k] + / 2.0, + 1.0) + - 2, + 0.0))); + } + mode_lib->vba.MaximumSwathWidth[k] = dml_min( + mode_lib->vba.MaximumSwathWidthInDETBuffer, + mode_lib->vba.MaximumSwathWidthInLineBuffer); + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.MaxDispclk[i], + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity = RoundToDFSGranularityDown( + mode_lib->vba.MaxDppclk[i], + mode_lib->vba.DISPCLKDPPCLKVCOSpeed); + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * (1.0 + + mode_lib->vba.DISPCLKRampingMargin + / 100.0); + if (mode_lib->vba.ODMCapability == true + && mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = true; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + / 2.0; + } else { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine; + } + if (mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + <= mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity + && mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k] + && mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { + mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + if ((mode_lib->vba.MaxDispclk[i] == mode_lib->vba.MaxDispclk[DC__VOLTAGE_STATES] + && mode_lib->vba.MaxDppclk[i] + == mode_lib->vba.MaxDppclk[DC__VOLTAGE_STATES]) + && (mode_lib->vba.TotalNumberOfActiveDPP[i] + > mode_lib->vba.MaxNumDPP + || mode_lib->vba.DISPCLK_DPPCLK_Support[i] == false)) { + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + if (mode_lib->vba.ODMCapability == true + && mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = true; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine + / 2.0; + } else { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine; + } + if (mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + <= mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity + && mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k] + && mode_lib->vba.ODMCombineEnablePerState[i][k] + == false) { + mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + if (mode_lib->vba.TotalNumberOfActiveDPP[i] > mode_lib->vba.MaxNumDPP) { + mode_lib->vba.RequiredDISPCLK[i] = 0.0; + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ODMCombineEnablePerState[i][k] = false; + if (mode_lib->vba.SwathWidthYSingleDPP[k] + <= mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } else { + mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.RequiredDPPCLK[i][k] = + mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + / 2.0; + } + if (!(mode_lib->vba.MaxDispclk[i] + == mode_lib->vba.MaxDispclk[DC__VOLTAGE_STATES] + && mode_lib->vba.MaxDppclk[i] + == mode_lib->vba.MaxDppclk[DC__VOLTAGE_STATES])) { + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * (1.0 + + mode_lib->vba.DISPCLKRampingMargin + / 100.0); + } else { + mode_lib->vba.PlaneRequiredDISPCLK = + mode_lib->vba.PixelClock[k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0); + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PlaneRequiredDISPCLK); + if ((mode_lib->vba.MinDPPCLKUsingSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k] + * (1.0 + + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + > mode_lib->vba.MaxDppclkRoundedDownToDFSGranularity) + || (mode_lib->vba.PlaneRequiredDISPCLK + > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity)) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + mode_lib->vba.TotalNumberOfActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.TotalNumberOfActiveDPP[i] = + mode_lib->vba.TotalNumberOfActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + mode_lib->vba.RequiredDISPCLK[i] = dml_max( + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.WritebackRequiredDISPCLK); + if (mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity + < mode_lib->vba.WritebackRequiredDISPCLK) { + mode_lib->vba.DISPCLK_DPPCLK_Support[i] = false; + } + } + /*Viewport Size Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.ViewportSizeSupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + if (dml_min( + mode_lib->vba.SwathWidthYSingleDPP[k], + dml_round( + mode_lib->vba.HActive[k] / 2.0 + * mode_lib->vba.HRatio[k])) + > mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.ViewportSizeSupport[i] = false; + } + } else { + if (mode_lib->vba.SwathWidthYSingleDPP[k] / 2.0 + > mode_lib->vba.MaximumSwathWidth[k]) { + mode_lib->vba.ViewportSizeSupport[i] = false; + } + } + } + } + /*Total Available Pipes Support Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if (mode_lib->vba.TotalNumberOfActiveDPP[i] <= mode_lib->vba.MaxNumDPP) { + mode_lib->vba.TotalAvailablePipesSupport[i] = true; + } else { + mode_lib->vba.TotalAvailablePipesSupport[i] = false; + } + } + /*Total Available OTG Support Check*/ + + mode_lib->vba.TotalNumberOfActiveOTG = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.TotalNumberOfActiveOTG = mode_lib->vba.TotalNumberOfActiveOTG + + 1.0; + } + } + if (mode_lib->vba.TotalNumberOfActiveOTG <= mode_lib->vba.MaxNumOTG) { + mode_lib->vba.NumberOfOTGSupport = true; + } else { + mode_lib->vba.NumberOfOTGSupport = false; + } + /*Display IO and DSC Support Check*/ + + mode_lib->vba.NonsupportedDSCInputBPC = false; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (!(mode_lib->vba.DSCInputBitPerComponent[k] == 12.0 + || mode_lib->vba.DSCInputBitPerComponent[k] == 10.0 + || mode_lib->vba.DSCInputBitPerComponent[k] == 8.0)) { + mode_lib->vba.NonsupportedDSCInputBPC = true; + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.RequiresDSC[i][k] = 0; + mode_lib->vba.RequiresFEC[i][k] = 0; + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.Output[k] == dm_hdmi) { + mode_lib->vba.RequiresDSC[i][k] = 0; + mode_lib->vba.RequiresFEC[i][k] = 0; + mode_lib->vba.OutputBppPerState[i][k] = + TruncToValidBPP( + dml_min( + 600.0, + mode_lib->vba.PHYCLKPerState[i]) + / mode_lib->vba.PixelClockBackEnd[k] + * 24, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + } else if (mode_lib->vba.Output[k] == dm_dp + || mode_lib->vba.Output[k] == dm_edp) { + if (mode_lib->vba.Output[k] == dm_edp) { + mode_lib->vba.EffectiveFECOverhead = 0.0; + } else { + mode_lib->vba.EffectiveFECOverhead = + mode_lib->vba.FECOverhead; + } + if (mode_lib->vba.PHYCLKPerState[i] >= 270.0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 270.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 270.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + if (mode_lib->vba.Outbpp == 0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 540.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 540.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + if (mode_lib->vba.Outbpp == 0 + && mode_lib->vba.PHYCLKPerState[i] + >= 810.0) { + mode_lib->vba.Outbpp = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * 810.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + false, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + mode_lib->vba.OutbppDSC = + TruncToValidBPP( + (1.0 + - mode_lib->vba.Downspreading + / 100.0) + * (1.0 + - mode_lib->vba.EffectiveFECOverhead + / 100.0) + * 810.0 + * mode_lib->vba.OutputLinkDPLanes[k] + / mode_lib->vba.PixelClockBackEnd[k] + * 8.0, + true, + mode_lib->vba.Output[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.DSCInputBitPerComponent[k]); + if (mode_lib->vba.DSCEnabled[k] == true + || mode_lib->vba.Outbpp == 0) { + mode_lib->vba.RequiresDSC[i][k] = true; + if (mode_lib->vba.Output[k] == dm_dp) { + mode_lib->vba.RequiresFEC[i][k] = + true; + } else { + mode_lib->vba.RequiresFEC[i][k] = + false; + } + mode_lib->vba.Outbpp = + mode_lib->vba.OutbppDSC; + } else { + mode_lib->vba.RequiresDSC[i][k] = false; + mode_lib->vba.RequiresFEC[i][k] = false; + } + mode_lib->vba.OutputBppPerState[i][k] = + mode_lib->vba.Outbpp; + } + } + } else { + mode_lib->vba.OutputBppPerState[i][k] = 0; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.DIOSupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.OutputBppPerState[i][k] == 0 + || (mode_lib->vba.OutputFormat[k] == dm_420 + && mode_lib->vba.ProgressiveToInterlaceUnitInOPP + == true)) { + mode_lib->vba.DIOSupport[i] = false; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = false; + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if ((mode_lib->vba.Output[k] == dm_dp + || mode_lib->vba.Output[k] == dm_edp)) { + if (mode_lib->vba.OutputFormat[k] == dm_420 + || mode_lib->vba.OutputFormat[k] + == dm_n422) { + mode_lib->vba.DSCFormatFactor = 2; + } else { + mode_lib->vba.DSCFormatFactor = 1; + } + if (mode_lib->vba.RequiresDSC[i][k] == true) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] + == true) { + if (mode_lib->vba.PixelClockBackEnd[k] / 6.0 + / mode_lib->vba.DSCFormatFactor + > (1.0 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * mode_lib->vba.MaxDSCCLK[i]) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = + true; + } + } else { + if (mode_lib->vba.PixelClockBackEnd[k] / 3.0 + / mode_lib->vba.DSCFormatFactor + > (1.0 + - mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading + / 100.0) + * mode_lib->vba.MaxDSCCLK[i]) { + mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] = + true; + } + } + } + } + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.NotEnoughDSCUnits[i] = false; + mode_lib->vba.TotalDSCUnitsRequired = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.RequiresDSC[i][k] == true) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + mode_lib->vba.TotalDSCUnitsRequired = + mode_lib->vba.TotalDSCUnitsRequired + 2.0; + } else { + mode_lib->vba.TotalDSCUnitsRequired = + mode_lib->vba.TotalDSCUnitsRequired + 1.0; + } + } + } + if (mode_lib->vba.TotalDSCUnitsRequired > mode_lib->vba.NumberOfDSC) { + mode_lib->vba.NotEnoughDSCUnits[i] = true; + } + } + /*DSC Delay per state*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] != k) { + mode_lib->vba.slices = 0; + } else if (mode_lib->vba.RequiresDSC[i][k] == 0 + || mode_lib->vba.RequiresDSC[i][k] == false) { + mode_lib->vba.slices = 0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 3200.0) { + mode_lib->vba.slices = dml_ceil( + mode_lib->vba.PixelClockBackEnd[k] / 400.0, + 4.0); + } else if (mode_lib->vba.PixelClockBackEnd[k] > 1360.0) { + mode_lib->vba.slices = 8.0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 680.0) { + mode_lib->vba.slices = 4.0; + } else if (mode_lib->vba.PixelClockBackEnd[k] > 340.0) { + mode_lib->vba.slices = 2.0; + } else { + mode_lib->vba.slices = 1.0; + } + if (mode_lib->vba.OutputBppPerState[i][k] == 0 + || mode_lib->vba.OutputBppPerState[i][k] == 0) { + mode_lib->vba.bpp = 0.0; + } else { + mode_lib->vba.bpp = mode_lib->vba.OutputBppPerState[i][k]; + } + if (mode_lib->vba.RequiresDSC[i][k] == true && mode_lib->vba.bpp != 0.0) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { + mode_lib->vba.DSCDelayPerState[i][k] = + dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + mode_lib->vba.bpp, + dml_ceil( + mode_lib->vba.HActive[k] + / mode_lib->vba.slices, + 1.0), + mode_lib->vba.slices, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k]); + } else { + mode_lib->vba.DSCDelayPerState[i][k] = + 2.0 + * (dscceComputeDelay( + mode_lib->vba.DSCInputBitPerComponent[k], + mode_lib->vba.bpp, + dml_ceil( + mode_lib->vba.HActive[k] + / mode_lib->vba.slices, + 1.0), + mode_lib->vba.slices + / 2, + mode_lib->vba.OutputFormat[k]) + + dscComputeDelay( + mode_lib->vba.OutputFormat[k])); + } + mode_lib->vba.DSCDelayPerState[i][k] = + mode_lib->vba.DSCDelayPerState[i][k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.PixelClockBackEnd[k]; + } else { + mode_lib->vba.DSCDelayPerState[i][k] = 0.0; + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[k] == j + && mode_lib->vba.RequiresDSC[i][j] == true) { + mode_lib->vba.DSCDelayPerState[i][k] = + mode_lib->vba.DSCDelayPerState[i][j]; + } + } + } + } + /*Urgent Latency Support Check*/ + + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + if (mode_lib->vba.ODMCombineEnablePerState[i][k] == true) { + mode_lib->vba.SwathWidthYPerState[i][k] = + dml_min( + mode_lib->vba.SwathWidthYSingleDPP[k], + dml_round( + mode_lib->vba.HActive[k] + / 2.0 + * mode_lib->vba.HRatio[k])); + } else { + mode_lib->vba.SwathWidthYPerState[i][k] = + mode_lib->vba.SwathWidthYSingleDPP[k] + / mode_lib->vba.NoOfDPP[i][k]; + } + mode_lib->vba.SwathWidthGranularityY = 256.0 + / dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0) + / mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.RoundedUpMaxSwathSizeBytesY = (dml_ceil( + mode_lib->vba.SwathWidthYPerState[i][k] - 1.0, + mode_lib->vba.SwathWidthGranularityY) + + mode_lib->vba.SwathWidthGranularityY) + * mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.MaxSwathHeightY[k]; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + mode_lib->vba.RoundedUpMaxSwathSizeBytesY = dml_ceil( + mode_lib->vba.RoundedUpMaxSwathSizeBytesY, + 256.0) + 256; + } + if (mode_lib->vba.MaxSwathHeightC[k] > 0.0) { + mode_lib->vba.SwathWidthGranularityC = 256.0 + / dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0) + / mode_lib->vba.MaxSwathHeightC[k]; + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = (dml_ceil( + mode_lib->vba.SwathWidthYPerState[i][k] / 2.0 - 1.0, + mode_lib->vba.SwathWidthGranularityC) + + mode_lib->vba.SwathWidthGranularityC) + * mode_lib->vba.BytePerPixelInDETC[k] + * mode_lib->vba.MaxSwathHeightC[k]; + if (mode_lib->vba.SourcePixelFormat[k] == dm_420_10) { + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = dml_ceil( + mode_lib->vba.RoundedUpMaxSwathSizeBytesC, + 256.0) + 256; + } + } else { + mode_lib->vba.RoundedUpMaxSwathSizeBytesC = 0.0; + } + if (mode_lib->vba.RoundedUpMaxSwathSizeBytesY + + mode_lib->vba.RoundedUpMaxSwathSizeBytesC + <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + mode_lib->vba.SwathHeightYPerState[i][k] = + mode_lib->vba.MaxSwathHeightY[k]; + mode_lib->vba.SwathHeightCPerState[i][k] = + mode_lib->vba.MaxSwathHeightC[k]; + } else { + mode_lib->vba.SwathHeightYPerState[i][k] = + mode_lib->vba.MinSwathHeightY[k]; + mode_lib->vba.SwathHeightCPerState[i][k] = + mode_lib->vba.MinSwathHeightC[k]; + } + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = 0.0; + } else if (mode_lib->vba.SwathHeightYPerState[i][k] + <= mode_lib->vba.SwathHeightCPerState[i][k]) { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2.0 / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 2.0 / mode_lib->vba.BytePerPixelInDETC[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] / 2.0); + } else { + mode_lib->vba.LinesInDETLuma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 * 2.0 / 3.0 + / mode_lib->vba.BytePerPixelInDETY[k] + / mode_lib->vba.SwathWidthYPerState[i][k]; + mode_lib->vba.LinesInDETChroma = mode_lib->vba.DETBufferSizeInKByte + * 1024.0 / 3.0 / mode_lib->vba.BytePerPixelInDETY[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] / 2.0); + } + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma = + dml_min( + mode_lib->vba.MaxLineBufferLines, + dml_floor( + mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] + / dml_max( + mode_lib->vba.HRatio[k], + 1.0)), + 1.0)) + - (mode_lib->vba.vtaps[k] - 1.0); + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma = + dml_min( + mode_lib->vba.MaxLineBufferLines, + dml_floor( + mode_lib->vba.LineBufferSize + / mode_lib->vba.LBBitPerPixel[k] + / (mode_lib->vba.SwathWidthYPerState[i][k] + / 2.0 + / dml_max( + mode_lib->vba.HRatio[k] + / 2.0, + 1.0)), + 1.0)) + - (mode_lib->vba.VTAPsChroma[k] - 1.0); + mode_lib->vba.EffectiveDETLBLinesLuma = + dml_floor( + mode_lib->vba.LinesInDETLuma + + dml_min( + mode_lib->vba.LinesInDETLuma + * mode_lib->vba.RequiredDISPCLK[i] + * mode_lib->vba.BytePerPixelInDETY[k] + * mode_lib->vba.PSCL_FACTOR[k] + / mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesLuma), + mode_lib->vba.SwathHeightYPerState[i][k]); + mode_lib->vba.EffectiveDETLBLinesChroma = + dml_floor( + mode_lib->vba.LinesInDETChroma + + dml_min( + mode_lib->vba.LinesInDETChroma + * mode_lib->vba.RequiredDISPCLK[i] + * mode_lib->vba.BytePerPixelInDETC[k] + * mode_lib->vba.PSCL_FACTOR_CHROMA[k] + / mode_lib->vba.ReturnBWPerState[i], + mode_lib->vba.EffectiveLBLatencyHidingSourceLinesChroma), + mode_lib->vba.SwathHeightCPerState[i][k]); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + mode_lib->vba.UrgentLatencySupportUsPerState[i][k] = + mode_lib->vba.EffectiveDETLBLinesLuma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETLBLinesLuma + * mode_lib->vba.SwathWidthYPerState[i][k] + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.UrgentLatencySupportUsPerState[i][k] = + dml_min( + mode_lib->vba.EffectiveDETLBLinesLuma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] + - mode_lib->vba.EffectiveDETLBLinesLuma + * mode_lib->vba.SwathWidthYPerState[i][k] + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k]), + mode_lib->vba.EffectiveDETLBLinesChroma + * (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]) + / (mode_lib->vba.VRatio[k] + / 2.0) + - mode_lib->vba.EffectiveDETLBLinesChroma + * mode_lib->vba.SwathWidthYPerState[i][k] + / 2.0 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / (mode_lib->vba.ReturnBWPerState[i] + / mode_lib->vba.NoOfDPP[i][k])); + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.UrgentLatencySupport[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.UrgentLatencySupportUsPerState[i][k] + < mode_lib->vba.UrgentLatency / 1.0) { + mode_lib->vba.UrgentLatencySupport[i] = false; + } + } + } + /*Prefetch Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] = + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] + + mode_lib->vba.NoOfDPP[i][k]; + } + } + } + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = 8.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + mode_lib->vba.PixelClock[k] / 16.0); + if (mode_lib->vba.BytePerPixelInDETC[k] == 0.0) { + if (mode_lib->vba.VRatio[k] <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 64.0 + * mode_lib->vba.HRatio[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 64.0 + * mode_lib->vba.PSCL_FACTOR[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + } else { + if (mode_lib->vba.VRatio[k] <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 32.0 + * mode_lib->vba.HRatio[k] + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0) + / 32.0 + * mode_lib->vba.PSCL_FACTOR[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + if (mode_lib->vba.VRatio[k] / 2.0 <= 1.0) { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / 32.0 + * mode_lib->vba.HRatio[k] + / 2.0 + * mode_lib->vba.PixelClock[k] + / mode_lib->vba.NoOfDPP[i][k]); + } else { + mode_lib->vba.ProjectedDCFCLKDeepSleep = + dml_max( + mode_lib->vba.ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil( + mode_lib->vba.BytePerPixelInDETC[k], + 2.0) + / 32.0 + * mode_lib->vba.PSCL_FACTOR_CHROMA[k] + * mode_lib->vba.RequiredDPPCLK[i][k]); + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameY = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.Read256BlockHeightY[k], + mode_lib->vba.Read256BlockWidthY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETY[k], 1.0), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k], + mode_lib->vba.ViewportHeight[k], + mode_lib->vba.SwathWidthYPerState[i][k], + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchY[k], + mode_lib->vba.DCCMetaPitchY[k], + &mode_lib->vba.MacroTileWidthY[k], + &mode_lib->vba.MetaRowBytesY, + &mode_lib->vba.DPTEBytesPerRowY, + &mode_lib->vba.PTEBufferSizeNotExceededY[i][k], + &mode_lib->vba.dpte_row_height[k], + &mode_lib->vba.meta_row_height[k]); + mode_lib->vba.PrefetchLinesY[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.vtaps[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightYPerState[i][k], + mode_lib->vba.ViewportYStartY[k], + &mode_lib->vba.PrefillY[k], + &mode_lib->vba.MaxNumSwY[k]); + if ((mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8)) { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC = CalculateVMAndRowBytes( + mode_lib, + mode_lib->vba.DCCEnable[k], + mode_lib->vba.Read256BlockHeightY[k], + mode_lib->vba.Read256BlockWidthY[k], + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.SurfaceTiling[k], + dml_ceil(mode_lib->vba.BytePerPixelInDETC[k], 2.0), + mode_lib->vba.SourceScan[k], + mode_lib->vba.ViewportWidth[k] / 2.0, + mode_lib->vba.ViewportHeight[k] / 2.0, + mode_lib->vba.SwathWidthYPerState[i][k] / 2.0, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.VMMPageSize, + mode_lib->vba.PTEBufferSizeInRequests, + mode_lib->vba.PDEProcessingBufIn64KBReqs, + mode_lib->vba.PitchC[k], + 0.0, + &mode_lib->vba.MacroTileWidthC[k], + &mode_lib->vba.MetaRowBytesC, + &mode_lib->vba.DPTEBytesPerRowC, + &mode_lib->vba.PTEBufferSizeNotExceededC[i][k], + &mode_lib->vba.dpte_row_height_chroma[k], + &mode_lib->vba.meta_row_height_chroma[k]); + mode_lib->vba.PrefetchLinesC[k] = CalculatePrefetchSourceLines( + mode_lib, + mode_lib->vba.VRatio[k] / 2.0, + mode_lib->vba.VTAPsChroma[k], + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.SwathHeightCPerState[i][k], + mode_lib->vba.ViewportYStartC[k], + &mode_lib->vba.PrefillC[k], + &mode_lib->vba.MaxNumSwC[k]); + } else { + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC = 0.0; + mode_lib->vba.MetaRowBytesC = 0.0; + mode_lib->vba.DPTEBytesPerRowC = 0.0; + mode_lib->vba.PrefetchLinesC[k] = 0.0; + mode_lib->vba.PTEBufferSizeNotExceededC[i][k] = true; + } + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrameY + + mode_lib->vba.PDEAndMetaPTEBytesPerFrameC; + mode_lib->vba.MetaRowBytes[k] = mode_lib->vba.MetaRowBytesY + + mode_lib->vba.MetaRowBytesC; + mode_lib->vba.DPTEBytesPerRow[k] = mode_lib->vba.DPTEBytesPerRowY + + mode_lib->vba.DPTEBytesPerRowC; + } + mode_lib->vba.ExtraLatency = + mode_lib->vba.UrgentRoundTripAndOutOfOrderLatencyPerState[i] + + (mode_lib->vba.TotalNumberOfActiveDPP[i] + * mode_lib->vba.PixelChunkSizeInKByte + + mode_lib->vba.TotalNumberOfDCCActiveDPP[i] + * mode_lib->vba.MetaChunkSize) + * 1024.0 + / mode_lib->vba.ReturnBWPerState[i]; + if (mode_lib->vba.VirtualMemoryEnable == true) { + mode_lib->vba.ExtraLatency = mode_lib->vba.ExtraLatency + + mode_lib->vba.TotalNumberOfActiveDPP[i] + * mode_lib->vba.PTEChunkSize * 1024.0 + / mode_lib->vba.ReturnBWPerState[i]; + } + mode_lib->vba.TimeCalc = 24.0 / mode_lib->vba.ProjectedDCFCLKDeepSleep; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + if (mode_lib->vba.WritebackEnable[k] == true) { + mode_lib->vba.WritebackDelay[i][k] = + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[k], + mode_lib->vba.WritebackHRatio[k], + mode_lib->vba.WritebackVRatio[k], + mode_lib->vba.WritebackLumaHTaps[k], + mode_lib->vba.WritebackLumaVTaps[k], + mode_lib->vba.WritebackChromaHTaps[k], + mode_lib->vba.WritebackChromaVTaps[k], + mode_lib->vba.WritebackDestinationWidth[k]) + / mode_lib->vba.RequiredDISPCLK[i]; + } else { + mode_lib->vba.WritebackDelay[i][k] = 0.0; + } + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[j] == k + && mode_lib->vba.WritebackEnable[j] + == true) { + mode_lib->vba.WritebackDelay[i][k] = + dml_max( + mode_lib->vba.WritebackDelay[i][k], + mode_lib->vba.WritebackLatency + + CalculateWriteBackDelay( + mode_lib->vba.WritebackPixelFormat[j], + mode_lib->vba.WritebackHRatio[j], + mode_lib->vba.WritebackVRatio[j], + mode_lib->vba.WritebackLumaHTaps[j], + mode_lib->vba.WritebackLumaVTaps[j], + mode_lib->vba.WritebackChromaHTaps[j], + mode_lib->vba.WritebackChromaVTaps[j], + mode_lib->vba.WritebackDestinationWidth[j]) + / mode_lib->vba.RequiredDISPCLK[i]); + } + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + for (j = 0; j <= mode_lib->vba.NumberOfActivePlanes - 1; j++) { + if (mode_lib->vba.BlendingAndTiming[k] == j) { + mode_lib->vba.WritebackDelay[i][k] = + mode_lib->vba.WritebackDelay[i][j]; + } + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.MaximumVStartup[k] = + mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k] + - dml_max( + 1.0, + dml_ceil( + mode_lib->vba.WritebackDelay[i][k] + / (mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]), + 1.0)); + } + mode_lib->vba.TWait = CalculateTWait( + mode_lib->vba.PrefetchMode, + mode_lib->vba.DRAMClockChangeLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.SREnterPlusExitTime); + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.XFCEnabled[k] == true) { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = + CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + mode_lib->vba.SwathWidthYPerState[i][k], + dml_ceil( + mode_lib->vba.BytePerPixelInDETY[k], + 1.0), + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TimeCalc, + mode_lib->vba.TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + } else { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0.0; + } + mode_lib->vba.IsErrorResult[i][k] = + CalculatePrefetchSchedule( + mode_lib, + mode_lib->vba.RequiredDPPCLK[i][k], + mode_lib->vba.RequiredDISPCLK[i], + mode_lib->vba.PixelClock[k], + mode_lib->vba.ProjectedDCFCLKDeepSleep, + mode_lib->vba.DSCDelayPerState[i][k], + mode_lib->vba.NoOfDPP[i][k], + mode_lib->vba.ScalerEnabled[k], + mode_lib->vba.NumberOfCursors[k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + mode_lib->vba.SwathWidthYPerState[i][k] + / mode_lib->vba.HRatio[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.VTotal[k] + - mode_lib->vba.VActive[k], + mode_lib->vba.HTotal[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + mode_lib->vba.MaximumVStartup[k], + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.ExtraLatency, + mode_lib->vba.TimeCalc, + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k], + mode_lib->vba.MetaRowBytes[k], + mode_lib->vba.DPTEBytesPerRow[k], + mode_lib->vba.PrefetchLinesY[k], + mode_lib->vba.SwathWidthYPerState[i][k], + mode_lib->vba.BytePerPixelInDETY[k], + mode_lib->vba.PrefillY[k], + mode_lib->vba.MaxNumSwY[k], + mode_lib->vba.PrefetchLinesC[k], + mode_lib->vba.BytePerPixelInDETC[k], + mode_lib->vba.PrefillC[k], + mode_lib->vba.MaxNumSwC[k], + mode_lib->vba.SwathHeightYPerState[i][k], + mode_lib->vba.SwathHeightCPerState[i][k], + mode_lib->vba.TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.Interlace[k], + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + mode_lib->vba.DSTXAfterScaler, + mode_lib->vba.DSTYAfterScaler, + &mode_lib->vba.LineTimesForPrefetch[k], + &mode_lib->vba.PrefetchBW[k], + &mode_lib->vba.LinesForMetaPTE[k], + &mode_lib->vba.LinesForMetaAndDPTERow[k], + &mode_lib->vba.VRatioPreY[i][k], + &mode_lib->vba.VRatioPreC[i][k], + &mode_lib->vba.RequiredPrefetchPixelDataBW[i][k], + &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &mode_lib->vba.Tno_bw[k]); + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.cursor_bw[k] = mode_lib->vba.NumberOfCursors[k] + * mode_lib->vba.CursorWidth[k][0] + * mode_lib->vba.CursorBPP[k][0] / 8.0 + / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + * mode_lib->vba.VRatio[k]; + } + mode_lib->vba.MaximumReadBandwidthWithPrefetch = 0.0; + mode_lib->vba.prefetch_vm_bw_valid = true; + mode_lib->vba.prefetch_row_bw_valid = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] == 0.0) { + mode_lib->vba.prefetch_vm_bw[k] = 0.0; + } else if (mode_lib->vba.LinesForMetaPTE[k] > 0.0) { + mode_lib->vba.prefetch_vm_bw[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] + / (mode_lib->vba.LinesForMetaPTE[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_vm_bw[k] = 0.0; + mode_lib->vba.prefetch_vm_bw_valid = false; + } + if (mode_lib->vba.MetaRowBytes[k] + mode_lib->vba.DPTEBytesPerRow[k] + == 0.0) { + mode_lib->vba.prefetch_row_bw[k] = 0.0; + } else if (mode_lib->vba.LinesForMetaAndDPTERow[k] > 0.0) { + mode_lib->vba.prefetch_row_bw[k] = (mode_lib->vba.MetaRowBytes[k] + + mode_lib->vba.DPTEBytesPerRow[k]) + / (mode_lib->vba.LinesForMetaAndDPTERow[k] + * mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k]); + } else { + mode_lib->vba.prefetch_row_bw[k] = 0.0; + mode_lib->vba.prefetch_row_bw_valid = false; + } + mode_lib->vba.MaximumReadBandwidthWithPrefetch = + mode_lib->vba.MaximumReadBandwidthWithPrefetch + + mode_lib->vba.cursor_bw[k] + + dml_max4( + mode_lib->vba.prefetch_vm_bw[k], + mode_lib->vba.prefetch_row_bw[k], + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.RequiredPrefetchPixelDataBW[i][k]); + } + mode_lib->vba.PrefetchSupported[i] = true; + if (mode_lib->vba.MaximumReadBandwidthWithPrefetch + > mode_lib->vba.ReturnBWPerState[i] + || mode_lib->vba.prefetch_vm_bw_valid == false + || mode_lib->vba.prefetch_row_bw_valid == false) { + mode_lib->vba.PrefetchSupported[i] = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.LineTimesForPrefetch[k] < 2.0 + || mode_lib->vba.LinesForMetaPTE[k] >= 8.0 + || mode_lib->vba.LinesForMetaAndDPTERow[k] >= 16.0 + || mode_lib->vba.IsErrorResult[i][k] == true) { + mode_lib->vba.PrefetchSupported[i] = false; + } + } + mode_lib->vba.VRatioInPrefetchSupported[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.VRatioPreY[i][k] > 4.0 + || mode_lib->vba.VRatioPreC[i][k] > 4.0 + || mode_lib->vba.IsErrorResult[i][k] == true) { + mode_lib->vba.VRatioInPrefetchSupported[i] = false; + } + } + if (mode_lib->vba.PrefetchSupported[i] == true + && mode_lib->vba.VRatioInPrefetchSupported[i] == true) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.ReturnBWPerState[i]; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.BandwidthAvailableForImmediateFlip = + mode_lib->vba.BandwidthAvailableForImmediateFlip + - mode_lib->vba.cursor_bw[k] + - dml_max( + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.PrefetchBW[k]); + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.ImmediateFlipBytes[k] = 0.0; + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.ImmediateFlipBytes[k] = + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k] + + mode_lib->vba.MetaRowBytes[k] + + mode_lib->vba.DPTEBytesPerRow[k]; + } + } + mode_lib->vba.TotImmediateFlipBytes = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if ((mode_lib->vba.SourcePixelFormat[k] != dm_420_8 + && mode_lib->vba.SourcePixelFormat[k] != dm_420_10)) { + mode_lib->vba.TotImmediateFlipBytes = + mode_lib->vba.TotImmediateFlipBytes + + mode_lib->vba.ImmediateFlipBytes[k]; + } + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + CalculateFlipSchedule( + mode_lib, + mode_lib->vba.ExtraLatency, + mode_lib->vba.UrgentLatency, + mode_lib->vba.MaxPageTableLevels, + mode_lib->vba.VirtualMemoryEnable, + mode_lib->vba.BandwidthAvailableForImmediateFlip, + mode_lib->vba.TotImmediateFlipBytes, + mode_lib->vba.SourcePixelFormat[k], + mode_lib->vba.ImmediateFlipBytes[k], + mode_lib->vba.HTotal[k] + / mode_lib->vba.PixelClock[k], + mode_lib->vba.VRatio[k], + mode_lib->vba.Tno_bw[k], + mode_lib->vba.PDEAndMetaPTEBytesPerFrame[k], + mode_lib->vba.MetaRowBytes[k], + mode_lib->vba.DPTEBytesPerRow[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.dpte_row_height[k], + mode_lib->vba.meta_row_height[k], + mode_lib->vba.qual_row_bw[k], + &mode_lib->vba.DestinationLinesToRequestVMInImmediateFlip[k], + &mode_lib->vba.DestinationLinesToRequestRowInImmediateFlip[k], + &mode_lib->vba.final_flip_bw[k], + &mode_lib->vba.ImmediateFlipSupportedForPipe[k]); + } + mode_lib->vba.total_dcn_read_bw_with_flip = 0.0; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.total_dcn_read_bw_with_flip = + mode_lib->vba.total_dcn_read_bw_with_flip + + mode_lib->vba.cursor_bw[k] + + dml_max3( + mode_lib->vba.prefetch_vm_bw[k], + mode_lib->vba.prefetch_row_bw[k], + mode_lib->vba.final_flip_bw[k] + + dml_max( + mode_lib->vba.ReadBandwidth[k], + mode_lib->vba.RequiredPrefetchPixelDataBW[i][k])); + } + mode_lib->vba.ImmediateFlipSupportedForState[i] = true; + if (mode_lib->vba.total_dcn_read_bw_with_flip + > mode_lib->vba.ReturnBWPerState[i]) { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.ImmediateFlipSupportedForPipe[k] == false) { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + } + } else { + mode_lib->vba.ImmediateFlipSupportedForState[i] = false; + } + } + /*PTE Buffer Size Check*/ + + for (i = 0; i <= DC__VOLTAGE_STATES; i++) { + mode_lib->vba.PTEBufferSizeNotExceeded[i] = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.PTEBufferSizeNotExceededY[i][k] == false + || mode_lib->vba.PTEBufferSizeNotExceededC[i][k] == false) { + mode_lib->vba.PTEBufferSizeNotExceeded[i] = false; + } + } + } + /*Cursor Support Check*/ + + mode_lib->vba.CursorSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.CursorWidth[k][0] > 0.0) { + if (dml_floor( + dml_floor( + mode_lib->vba.CursorBufferSize + - mode_lib->vba.CursorChunkSize, + mode_lib->vba.CursorChunkSize) * 1024.0 + / (mode_lib->vba.CursorWidth[k][0] + * mode_lib->vba.CursorBPP[k][0] + / 8.0), + 1.0) + * (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) + / mode_lib->vba.VRatio[k] < mode_lib->vba.UrgentLatency + || (mode_lib->vba.CursorBPP[k][0] == 64.0 + && mode_lib->vba.Cursor64BppSupport == false)) { + mode_lib->vba.CursorSupport = false; + } + } + } + /*Valid Pitch Check*/ + + mode_lib->vba.PitchSupport = true; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.AlignedYPitch[k] = dml_ceil( + dml_max(mode_lib->vba.PitchY[k], mode_lib->vba.ViewportWidth[k]), + mode_lib->vba.MacroTileWidthY[k]); + if (mode_lib->vba.AlignedYPitch[k] > mode_lib->vba.PitchY[k]) { + mode_lib->vba.PitchSupport = false; + } + if (mode_lib->vba.DCCEnable[k] == true) { + mode_lib->vba.AlignedDCCMetaPitch[k] = dml_ceil( + dml_max( + mode_lib->vba.DCCMetaPitchY[k], + mode_lib->vba.ViewportWidth[k]), + 64.0 * mode_lib->vba.Read256BlockWidthY[k]); + } else { + mode_lib->vba.AlignedDCCMetaPitch[k] = mode_lib->vba.DCCMetaPitchY[k]; + } + if (mode_lib->vba.AlignedDCCMetaPitch[k] > mode_lib->vba.DCCMetaPitchY[k]) { + mode_lib->vba.PitchSupport = false; + } + if (mode_lib->vba.SourcePixelFormat[k] != dm_444_64 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_32 + && mode_lib->vba.SourcePixelFormat[k] != dm_444_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_16 + && mode_lib->vba.SourcePixelFormat[k] != dm_mono_8) { + mode_lib->vba.AlignedCPitch[k] = dml_ceil( + dml_max( + mode_lib->vba.PitchC[k], + mode_lib->vba.ViewportWidth[k] / 2.0), + mode_lib->vba.MacroTileWidthC[k]); + } else { + mode_lib->vba.AlignedCPitch[k] = mode_lib->vba.PitchC[k]; + } + if (mode_lib->vba.AlignedCPitch[k] > mode_lib->vba.PitchC[k]) { + mode_lib->vba.PitchSupport = false; + } + } + /*Mode Support, Voltage State and SOC Configuration*/ + + for (i = DC__VOLTAGE_STATES; i >= 0; i--) { + if (mode_lib->vba.ScaleRatioAndTapsSupport == true + && mode_lib->vba.SourceFormatPixelAndScanSupport == true + && mode_lib->vba.ViewportSizeSupport[i] == true + && mode_lib->vba.BandwidthSupport[i] == true + && mode_lib->vba.DIOSupport[i] == true + && mode_lib->vba.NotEnoughDSCUnits[i] == false + && mode_lib->vba.DSCCLKRequiredMoreThanSupported[i] == false + && mode_lib->vba.UrgentLatencySupport[i] == true + && mode_lib->vba.ROBSupport[i] == true + && mode_lib->vba.DISPCLK_DPPCLK_Support[i] == true + && mode_lib->vba.TotalAvailablePipesSupport[i] == true + && mode_lib->vba.NumberOfOTGSupport == true + && mode_lib->vba.WritebackModeSupport == true + && mode_lib->vba.WritebackLatencySupport == true + && mode_lib->vba.WritebackScaleRatioAndTapsSupport == true + && mode_lib->vba.CursorSupport == true + && mode_lib->vba.PitchSupport == true + && mode_lib->vba.PrefetchSupported[i] == true + && mode_lib->vba.VRatioInPrefetchSupported[i] == true + && mode_lib->vba.PTEBufferSizeNotExceeded[i] == true + && mode_lib->vba.NonsupportedDSCInputBPC == false) { + mode_lib->vba.ModeSupport[i] = true; + } else { + mode_lib->vba.ModeSupport[i] = false; + } + } + for (i = DC__VOLTAGE_STATES; i >= 0; i--) { + if (i == DC__VOLTAGE_STATES || mode_lib->vba.ModeSupport[i] == true) { + mode_lib->vba.VoltageLevel = i; + } + } + mode_lib->vba.DCFCLK = mode_lib->vba.DCFCLKPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.DRAMSpeed = mode_lib->vba.DRAMSpeedPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.FabricClock = mode_lib->vba.FabricClockPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.SOCCLK = mode_lib->vba.SOCCLKPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.FabricAndDRAMBandwidth = + mode_lib->vba.FabricAndDRAMBandwidthPerState[mode_lib->vba.VoltageLevel]; + mode_lib->vba.ImmediateFlipSupport = + mode_lib->vba.ImmediateFlipSupportedForState[mode_lib->vba.VoltageLevel]; + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + mode_lib->vba.DPPPerPlane[k] = mode_lib->vba.NoOfDPP[mode_lib->vba.VoltageLevel][k]; + } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { + if (mode_lib->vba.BlendingAndTiming[k] == k) { + mode_lib->vba.ODMCombineEnabled[k] = + mode_lib->vba.ODMCombineEnablePerState[mode_lib->vba.VoltageLevel][k]; + } else { + mode_lib->vba.ODMCombineEnabled[k] = 0; + } + mode_lib->vba.DSCEnabled[k] = + mode_lib->vba.RequiresDSC[mode_lib->vba.VoltageLevel][k]; + mode_lib->vba.OutputBpp[k] = + mode_lib->vba.OutputBppPerState[mode_lib->vba.VoltageLevel][k]; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index a24fe9a0383d..346ffea843c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -79,6 +79,11 @@ double get_total_prefetch_bw( const display_e2e_pipe_params_st *pipes, unsigned int num_pipes); +unsigned int dml_get_voltage_level( + struct display_mode_lib *mode_lib, + const display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); + bool Calculate256BBlockSizes( enum source_format_class SourcePixelFormat, enum dm_swizzle_mode SurfaceTiling, @@ -96,42 +101,41 @@ struct vba_vars_st { mode_evaluation_st me; unsigned int MaximumMaxVStartupLines; - double cursor_bw[DC__NUM_PIPES__MAX]; - double meta_row_bw[DC__NUM_PIPES__MAX]; - double dpte_row_bw[DC__NUM_PIPES__MAX]; - double qual_row_bw[DC__NUM_PIPES__MAX]; + double cursor_bw[DC__NUM_DPP__MAX]; + double meta_row_bw[DC__NUM_DPP__MAX]; + double dpte_row_bw[DC__NUM_DPP__MAX]; + double qual_row_bw[DC__NUM_DPP__MAX]; double WritebackDISPCLK; - double PSCL_THROUGHPUT_LUMA[DC__NUM_PIPES__MAX]; - double PSCL_THROUGHPUT_CHROMA[DC__NUM_PIPES__MAX]; + double PSCL_THROUGHPUT_LUMA[DC__NUM_DPP__MAX]; + double PSCL_THROUGHPUT_CHROMA[DC__NUM_DPP__MAX]; double DPPCLKUsingSingleDPPLuma; double DPPCLKUsingSingleDPPChroma; - double DPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; + double DPPCLKUsingSingleDPP[DC__NUM_DPP__MAX]; double DISPCLKWithRamping; double DISPCLKWithoutRamping; double GlobalDPPCLK; - double MaxDispclk; double DISPCLKWithRampingRoundedToDFSGranularity; double DISPCLKWithoutRampingRoundedToDFSGranularity; double MaxDispclkRoundedToDFSGranularity; bool DCCEnabledAnyPlane; double ReturnBandwidthToDCN; - unsigned int SwathWidthY[DC__NUM_PIPES__MAX]; - unsigned int SwathWidthSingleDPPY[DC__NUM_PIPES__MAX]; - double BytePerPixelDETY[DC__NUM_PIPES__MAX]; - double BytePerPixelDETC[DC__NUM_PIPES__MAX]; - double ReadBandwidthPlaneLuma[DC__NUM_PIPES__MAX]; - double ReadBandwidthPlaneChroma[DC__NUM_PIPES__MAX]; + unsigned int SwathWidthY[DC__NUM_DPP__MAX]; + unsigned int SwathWidthSingleDPPY[DC__NUM_DPP__MAX]; + double BytePerPixelDETY[DC__NUM_DPP__MAX]; + double BytePerPixelDETC[DC__NUM_DPP__MAX]; + double ReadBandwidthPlaneLuma[DC__NUM_DPP__MAX]; + double ReadBandwidthPlaneChroma[DC__NUM_DPP__MAX]; unsigned int TotalActiveDPP; unsigned int TotalDCCActiveDPP; double UrgentRoundTripAndOutOfOrderLatency; - double DisplayPipeLineDeliveryTimeLuma[DC__NUM_PIPES__MAX]; // WM - double DisplayPipeLineDeliveryTimeChroma[DC__NUM_PIPES__MAX]; // WM - double LinesInDETY[DC__NUM_PIPES__MAX]; // WM - double LinesInDETC[DC__NUM_PIPES__MAX]; // WM - unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_PIPES__MAX]; // WM - unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_PIPES__MAX]; // WM - double FullDETBufferingTimeY[DC__NUM_PIPES__MAX]; // WM - double FullDETBufferingTimeC[DC__NUM_PIPES__MAX]; // WM + double DisplayPipeLineDeliveryTimeLuma[DC__NUM_DPP__MAX]; // WM + double DisplayPipeLineDeliveryTimeChroma[DC__NUM_DPP__MAX]; // WM + double LinesInDETY[DC__NUM_DPP__MAX]; // WM + double LinesInDETC[DC__NUM_DPP__MAX]; // WM + unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX]; // WM + unsigned int LinesInDETCRoundedDownToSwath[DC__NUM_DPP__MAX]; // WM + double FullDETBufferingTimeY[DC__NUM_DPP__MAX]; // WM + double FullDETBufferingTimeC[DC__NUM_DPP__MAX]; // WM double MinFullDETBufferingTime; double FrameTimeForMinFullDETBufferingTime; double AverageReadBandwidthGBytePerSecond; @@ -145,55 +149,54 @@ struct vba_vars_st { double EffectiveDETPlusLBLinesChroma; double UrgentLatencySupportUsLuma; double UrgentLatencySupportUsChroma; - double UrgentLatencySupportUs[DC__NUM_PIPES__MAX]; + double UrgentLatencySupportUs[DC__NUM_DPP__MAX]; unsigned int DSCFormatFactor; - unsigned int BlockHeight256BytesY[DC__NUM_PIPES__MAX]; - unsigned int BlockHeight256BytesC[DC__NUM_PIPES__MAX]; - unsigned int BlockWidth256BytesY[DC__NUM_PIPES__MAX]; - unsigned int BlockWidth256BytesC[DC__NUM_PIPES__MAX]; - double VInitPreFillY[DC__NUM_PIPES__MAX]; - double VInitPreFillC[DC__NUM_PIPES__MAX]; - unsigned int MaxNumSwathY[DC__NUM_PIPES__MAX]; - unsigned int MaxNumSwathC[DC__NUM_PIPES__MAX]; - double PrefetchSourceLinesY[DC__NUM_PIPES__MAX]; - double PrefetchSourceLinesC[DC__NUM_PIPES__MAX]; - double PixelPTEBytesPerRow[DC__NUM_PIPES__MAX]; - double MetaRowByte[DC__NUM_PIPES__MAX]; - bool PTEBufferSizeNotExceeded; // not used - unsigned int dpte_row_height[DC__NUM_PIPES__MAX]; - unsigned int dpte_row_height_chroma[DC__NUM_PIPES__MAX]; - unsigned int meta_row_height[DC__NUM_PIPES__MAX]; - unsigned int meta_row_height_chroma[DC__NUM_PIPES__MAX]; - - unsigned int MacroTileWidthY; - unsigned int MacroTileWidthC; - unsigned int MaxVStartupLines[DC__NUM_PIPES__MAX]; - double WritebackDelay[DC__NUM_PIPES__MAX]; + unsigned int BlockHeight256BytesY[DC__NUM_DPP__MAX]; + unsigned int BlockHeight256BytesC[DC__NUM_DPP__MAX]; + unsigned int BlockWidth256BytesY[DC__NUM_DPP__MAX]; + unsigned int BlockWidth256BytesC[DC__NUM_DPP__MAX]; + double VInitPreFillY[DC__NUM_DPP__MAX]; + double VInitPreFillC[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwathY[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwathC[DC__NUM_DPP__MAX]; + double PrefetchSourceLinesY[DC__NUM_DPP__MAX]; + double PrefetchSourceLinesC[DC__NUM_DPP__MAX]; + double PixelPTEBytesPerRow[DC__NUM_DPP__MAX]; + double MetaRowByte[DC__NUM_DPP__MAX]; + unsigned int dpte_row_height[DC__NUM_DPP__MAX]; + unsigned int dpte_row_height_chroma[DC__NUM_DPP__MAX]; + unsigned int meta_row_height[DC__NUM_DPP__MAX]; + unsigned int meta_row_height_chroma[DC__NUM_DPP__MAX]; + + unsigned int MacroTileWidthY[DC__NUM_DPP__MAX]; + unsigned int MacroTileWidthC[DC__NUM_DPP__MAX]; + unsigned int MaxVStartupLines[DC__NUM_DPP__MAX]; + double WritebackDelay[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; bool PrefetchModeSupported; - bool AllowDRAMClockChangeDuringVBlank[DC__NUM_PIPES__MAX]; - bool AllowDRAMSelfRefreshDuringVBlank[DC__NUM_PIPES__MAX]; - double RequiredPrefetchPixDataBW[DC__NUM_PIPES__MAX]; + bool AllowDRAMClockChangeDuringVBlank[DC__NUM_DPP__MAX]; + bool AllowDRAMSelfRefreshDuringVBlank[DC__NUM_DPP__MAX]; + double RequiredPrefetchPixDataBW[DC__NUM_DPP__MAX]; double XFCRemoteSurfaceFlipDelay; double TInitXFill; double TslvChk; double SrcActiveDrainRate; - double Tno_bw[DC__NUM_PIPES__MAX]; + double Tno_bw[DC__NUM_DPP__MAX]; bool ImmediateFlipSupported; - double prefetch_vm_bw[DC__NUM_PIPES__MAX]; - double prefetch_row_bw[DC__NUM_PIPES__MAX]; - bool ImmediateFlipSupportedForPipe[DC__NUM_PIPES__MAX]; + double prefetch_vm_bw[DC__NUM_DPP__MAX]; + double prefetch_row_bw[DC__NUM_DPP__MAX]; + bool ImmediateFlipSupportedForPipe[DC__NUM_DPP__MAX]; unsigned int VStartupLines; - double DisplayPipeLineDeliveryTimeLumaPrefetch[DC__NUM_PIPES__MAX]; - double DisplayPipeLineDeliveryTimeChromaPrefetch[DC__NUM_PIPES__MAX]; + double DisplayPipeLineDeliveryTimeLumaPrefetch[DC__NUM_DPP__MAX]; + double DisplayPipeLineDeliveryTimeChromaPrefetch[DC__NUM_DPP__MAX]; unsigned int ActiveDPPs; unsigned int LBLatencyHidingSourceLinesY; unsigned int LBLatencyHidingSourceLinesC; - double ActiveDRAMClockChangeLatencyMargin[DC__NUM_PIPES__MAX]; + double ActiveDRAMClockChangeLatencyMargin[DC__NUM_DPP__MAX]; double MinActiveDRAMClockChangeMargin; - double XFCSlaveVUpdateOffset[DC__NUM_PIPES__MAX]; - double XFCSlaveVupdateWidth[DC__NUM_PIPES__MAX]; - double XFCSlaveVReadyOffset[DC__NUM_PIPES__MAX]; + double XFCSlaveVUpdateOffset[DC__NUM_DPP__MAX]; + double XFCSlaveVupdateWidth[DC__NUM_DPP__MAX]; + double XFCSlaveVReadyOffset[DC__NUM_DPP__MAX]; double InitFillLevel; double FinalFillMargin; double FinalFillLevel; @@ -276,71 +279,71 @@ struct vba_vars_st { double DCFCLK; unsigned int NumberOfActivePlanes; - unsigned int ViewportWidth[DC__NUM_DPP]; - unsigned int ViewportHeight[DC__NUM_DPP]; - unsigned int ViewportYStartY[DC__NUM_DPP]; - unsigned int ViewportYStartC[DC__NUM_DPP]; - unsigned int PitchY[DC__NUM_DPP]; - unsigned int PitchC[DC__NUM_DPP]; - double HRatio[DC__NUM_DPP]; - double VRatio[DC__NUM_DPP]; - unsigned int htaps[DC__NUM_DPP]; - unsigned int vtaps[DC__NUM_DPP]; - unsigned int HTAPsChroma[DC__NUM_DPP]; - unsigned int VTAPsChroma[DC__NUM_DPP]; - unsigned int HTotal[DC__NUM_DPP]; - unsigned int VTotal[DC__NUM_DPP]; - unsigned int DPPPerPlane[DC__NUM_DPP]; - double PixelClock[DC__NUM_DPP]; - double PixelClockBackEnd[DC__NUM_DPP]; - double DPPCLK[DC__NUM_DPP]; - bool DCCEnable[DC__NUM_DPP]; - unsigned int DCCMetaPitchY[DC__NUM_DPP]; - enum scan_direction_class SourceScan[DC__NUM_DPP]; - enum source_format_class SourcePixelFormat[DC__NUM_DPP]; - bool WritebackEnable[DC__NUM_DPP]; - double WritebackDestinationWidth[DC__NUM_DPP]; - double WritebackDestinationHeight[DC__NUM_DPP]; - double WritebackSourceHeight[DC__NUM_DPP]; - enum source_format_class WritebackPixelFormat[DC__NUM_DPP]; - unsigned int WritebackLumaHTaps[DC__NUM_DPP]; - unsigned int WritebackLumaVTaps[DC__NUM_DPP]; - unsigned int WritebackChromaHTaps[DC__NUM_DPP]; - unsigned int WritebackChromaVTaps[DC__NUM_DPP]; - double WritebackHRatio[DC__NUM_DPP]; - double WritebackVRatio[DC__NUM_DPP]; - unsigned int HActive[DC__NUM_DPP]; - unsigned int VActive[DC__NUM_DPP]; - bool Interlace[DC__NUM_DPP]; - enum dm_swizzle_mode SurfaceTiling[DC__NUM_DPP]; - unsigned int ScalerRecoutWidth[DC__NUM_DPP]; - bool DynamicMetadataEnable[DC__NUM_DPP]; - unsigned int DynamicMetadataLinesBeforeActiveRequired[DC__NUM_DPP]; - unsigned int DynamicMetadataTransmittedBytes[DC__NUM_DPP]; - double DCCRate[DC__NUM_DPP]; - bool ODMCombineEnabled[DC__NUM_DPP]; - double OutputBpp[DC__NUM_DPP]; - unsigned int NumberOfDSCSlices[DC__NUM_DPP]; - bool DSCEnabled[DC__NUM_DPP]; - unsigned int DSCDelay[DC__NUM_DPP]; - unsigned int DSCInputBitPerComponent[DC__NUM_DPP]; - enum output_format_class OutputFormat[DC__NUM_DPP]; - enum output_encoder_class Output[DC__NUM_DPP]; - unsigned int BlendingAndTiming[DC__NUM_DPP]; + unsigned int ViewportWidth[DC__NUM_DPP__MAX]; + unsigned int ViewportHeight[DC__NUM_DPP__MAX]; + unsigned int ViewportYStartY[DC__NUM_DPP__MAX]; + unsigned int ViewportYStartC[DC__NUM_DPP__MAX]; + unsigned int PitchY[DC__NUM_DPP__MAX]; + unsigned int PitchC[DC__NUM_DPP__MAX]; + double HRatio[DC__NUM_DPP__MAX]; + double VRatio[DC__NUM_DPP__MAX]; + unsigned int htaps[DC__NUM_DPP__MAX]; + unsigned int vtaps[DC__NUM_DPP__MAX]; + unsigned int HTAPsChroma[DC__NUM_DPP__MAX]; + unsigned int VTAPsChroma[DC__NUM_DPP__MAX]; + unsigned int HTotal[DC__NUM_DPP__MAX]; + unsigned int VTotal[DC__NUM_DPP__MAX]; + unsigned int DPPPerPlane[DC__NUM_DPP__MAX]; + double PixelClock[DC__NUM_DPP__MAX]; + double PixelClockBackEnd[DC__NUM_DPP__MAX]; + double DPPCLK[DC__NUM_DPP__MAX]; + bool DCCEnable[DC__NUM_DPP__MAX]; + unsigned int DCCMetaPitchY[DC__NUM_DPP__MAX]; + enum scan_direction_class SourceScan[DC__NUM_DPP__MAX]; + enum source_format_class SourcePixelFormat[DC__NUM_DPP__MAX]; + bool WritebackEnable[DC__NUM_DPP__MAX]; + double WritebackDestinationWidth[DC__NUM_DPP__MAX]; + double WritebackDestinationHeight[DC__NUM_DPP__MAX]; + double WritebackSourceHeight[DC__NUM_DPP__MAX]; + enum source_format_class WritebackPixelFormat[DC__NUM_DPP__MAX]; + unsigned int WritebackLumaHTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackLumaVTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackChromaHTaps[DC__NUM_DPP__MAX]; + unsigned int WritebackChromaVTaps[DC__NUM_DPP__MAX]; + double WritebackHRatio[DC__NUM_DPP__MAX]; + double WritebackVRatio[DC__NUM_DPP__MAX]; + unsigned int HActive[DC__NUM_DPP__MAX]; + unsigned int VActive[DC__NUM_DPP__MAX]; + bool Interlace[DC__NUM_DPP__MAX]; + enum dm_swizzle_mode SurfaceTiling[DC__NUM_DPP__MAX]; + unsigned int ScalerRecoutWidth[DC__NUM_DPP__MAX]; + bool DynamicMetadataEnable[DC__NUM_DPP__MAX]; + unsigned int DynamicMetadataLinesBeforeActiveRequired[DC__NUM_DPP__MAX]; + unsigned int DynamicMetadataTransmittedBytes[DC__NUM_DPP__MAX]; + double DCCRate[DC__NUM_DPP__MAX]; + bool ODMCombineEnabled[DC__NUM_DPP__MAX]; + double OutputBpp[DC__NUM_DPP__MAX]; + unsigned int NumberOfDSCSlices[DC__NUM_DPP__MAX]; + bool DSCEnabled[DC__NUM_DPP__MAX]; + unsigned int DSCDelay[DC__NUM_DPP__MAX]; + unsigned int DSCInputBitPerComponent[DC__NUM_DPP__MAX]; + enum output_format_class OutputFormat[DC__NUM_DPP__MAX]; + enum output_encoder_class Output[DC__NUM_DPP__MAX]; + unsigned int BlendingAndTiming[DC__NUM_DPP__MAX]; bool SynchronizedVBlank; - unsigned int NumberOfCursors[DC__NUM_DPP]; - unsigned int CursorWidth[DC__NUM_DPP][DC__NUM_CURSOR]; - unsigned int CursorBPP[DC__NUM_DPP][DC__NUM_CURSOR]; - bool XFCEnabled[DC__NUM_DPP]; - bool ScalerEnabled[DC__NUM_DPP]; + unsigned int NumberOfCursors[DC__NUM_DPP__MAX]; + unsigned int CursorWidth[DC__NUM_DPP__MAX][DC__NUM_CURSOR]; + unsigned int CursorBPP[DC__NUM_DPP__MAX][DC__NUM_CURSOR]; + bool XFCEnabled[DC__NUM_DPP__MAX]; + bool ScalerEnabled[DC__NUM_DPP__MAX]; // Intermediates/Informational bool ImmediateFlipSupport; - unsigned int SwathHeightY[DC__NUM_DPP]; - unsigned int SwathHeightC[DC__NUM_DPP]; - unsigned int DETBufferSizeY[DC__NUM_DPP]; - unsigned int DETBufferSizeC[DC__NUM_DPP]; - unsigned int LBBitPerPixel[DC__NUM_DPP]; + unsigned int SwathHeightY[DC__NUM_DPP__MAX]; + unsigned int SwathHeightC[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeY[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeC[DC__NUM_DPP__MAX]; + unsigned int LBBitPerPixel[DC__NUM_DPP__MAX]; double LastPixelOfLineExtraWatermark; double TotalDataReadBandwidth; unsigned int TotalActiveWriteback; @@ -349,9 +352,9 @@ struct vba_vars_st { double BandwidthAvailableForImmediateFlip; unsigned int PrefetchMode; bool IgnoreViewportPositioning; - double PrefetchBandwidth[DC__NUM_DPP]; - bool ErrorResult[DC__NUM_DPP]; - double PDEAndMetaPTEBytesFrame[DC__NUM_DPP]; + double PrefetchBandwidth[DC__NUM_DPP__MAX]; + bool ErrorResult[DC__NUM_DPP__MAX]; + double PDEAndMetaPTEBytesFrame[DC__NUM_DPP__MAX]; // // Calculated dml_ml->vba.Outputs @@ -376,35 +379,200 @@ struct vba_vars_st { // used explicitly. They are fetched by tests and then possibly used. The // ultimate values to use are the ones specified by the parameters to DML double DISPCLK_calculated; - double DSCCLK_calculated[DC__NUM_DPP]; - double DPPCLK_calculated[DC__NUM_DPP]; + double DSCCLK_calculated[DC__NUM_DPP__MAX]; + double DPPCLK_calculated[DC__NUM_DPP__MAX]; - unsigned int VStartup[DC__NUM_DPP]; + unsigned int VStartup[DC__NUM_DPP__MAX]; unsigned int VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; double ImmediateFlipBW; unsigned int TotImmediateFlipBytes; double TCalc; - double MinTTUVBlank[DC__NUM_DPP]; - double VRatioPrefetchY[DC__NUM_DPP]; - double VRatioPrefetchC[DC__NUM_DPP]; - double DSTXAfterScaler[DC__NUM_DPP]; - double DSTYAfterScaler[DC__NUM_DPP]; - - double DestinationLinesToRequestVMInVBlank[DC__NUM_DPP]; - double DestinationLinesToRequestRowInVBlank[DC__NUM_DPP]; - double DestinationLinesForPrefetch[DC__NUM_DPP]; - double DestinationLinesToRequestRowInImmediateFlip[DC__NUM_DPP]; - double DestinationLinesToRequestVMInImmediateFlip[DC__NUM_DPP]; - - double XFCTransferDelay[DC__NUM_DPP]; - double XFCPrechargeDelay[DC__NUM_DPP]; - double XFCRemoteSurfaceFlipLatency[DC__NUM_DPP]; - double XFCPrefetchMargin[DC__NUM_DPP]; - - display_e2e_pipe_params_st cache_pipes[DC__NUM_DPP]; + double MinTTUVBlank[DC__NUM_DPP__MAX]; + double VRatioPrefetchY[DC__NUM_DPP__MAX]; + double VRatioPrefetchC[DC__NUM_DPP__MAX]; + double DSTXAfterScaler[DC__NUM_DPP__MAX]; + double DSTYAfterScaler[DC__NUM_DPP__MAX]; + + double DestinationLinesToRequestVMInVBlank[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestRowInVBlank[DC__NUM_DPP__MAX]; + double DestinationLinesForPrefetch[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestRowInImmediateFlip[DC__NUM_DPP__MAX]; + double DestinationLinesToRequestVMInImmediateFlip[DC__NUM_DPP__MAX]; + + double XFCTransferDelay[DC__NUM_DPP__MAX]; + double XFCPrechargeDelay[DC__NUM_DPP__MAX]; + double XFCRemoteSurfaceFlipLatency[DC__NUM_DPP__MAX]; + double XFCPrefetchMargin[DC__NUM_DPP__MAX]; + + display_e2e_pipe_params_st cache_pipes[DC__NUM_DPP__MAX]; unsigned int cache_num_pipes; - unsigned int pipe_plane[DC__NUM_PIPES__MAX]; + unsigned int pipe_plane[DC__NUM_DPP__MAX]; + + /* vba mode support */ + /*inputs*/ + bool SupportGFX7CompatibleTilingIn32bppAnd64bpp; + double MaxHSCLRatio; + double MaxVSCLRatio; + unsigned int MaxNumWriteback; + bool WritebackLumaAndChromaScalingSupported; + bool Cursor64BppSupport; + double DCFCLKPerState[DC__VOLTAGE_STATES + 1]; + double FabricClockPerState[DC__VOLTAGE_STATES + 1]; + double SOCCLKPerState[DC__VOLTAGE_STATES + 1]; + double PHYCLKPerState[DC__VOLTAGE_STATES + 1]; + double MaxDppclk[DC__VOLTAGE_STATES + 1]; + double MaxDSCCLK[DC__VOLTAGE_STATES + 1]; + double DRAMSpeedPerState[DC__VOLTAGE_STATES + 1]; + double MaxDispclk[DC__VOLTAGE_STATES + 1]; + + /*outputs*/ + bool ScaleRatioAndTapsSupport; + bool SourceFormatPixelAndScanSupport; + unsigned int SwathWidthYSingleDPP[DC__NUM_DPP__MAX]; + double BytePerPixelInDETY[DC__NUM_DPP__MAX]; + double BytePerPixelInDETC[DC__NUM_DPP__MAX]; + double TotalReadBandwidthConsumedGBytePerSecond; + double ReadBandwidth[DC__NUM_DPP__MAX]; + double TotalWriteBandwidthConsumedGBytePerSecond; + double WriteBandwidth[DC__NUM_DPP__MAX]; + double TotalBandwidthConsumedGBytePerSecond; + bool DCCEnabledInAnyPlane; + bool WritebackLatencySupport; + bool WritebackModeSupport; + bool Writeback10bpc420Supported; + bool BandwidthSupport[DC__VOLTAGE_STATES + 1]; + unsigned int TotalNumberOfActiveWriteback; + double CriticalPoint; + double ReturnBWToDCNPerState; + double FabricAndDRAMBandwidthPerState[DC__VOLTAGE_STATES + 1]; + double ReturnBWPerState[DC__VOLTAGE_STATES + 1]; + double UrgentRoundTripAndOutOfOrderLatencyPerState[DC__VOLTAGE_STATES + 1]; + bool ODMCombineEnablePerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PTEBufferSizeNotExceededY[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PTEBufferSizeNotExceededC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool PrefetchSupported[DC__VOLTAGE_STATES + 1]; + bool VRatioInPrefetchSupported[DC__VOLTAGE_STATES + 1]; + bool DISPCLK_DPPCLK_Support[DC__VOLTAGE_STATES + 1]; + bool TotalAvailablePipesSupport[DC__VOLTAGE_STATES + 1]; + bool UrgentLatencySupport[DC__VOLTAGE_STATES + 1]; + bool ModeSupport[DC__VOLTAGE_STATES + 1]; + bool DIOSupport[DC__VOLTAGE_STATES + 1]; + bool NotEnoughDSCUnits[DC__VOLTAGE_STATES + 1]; + bool DSCCLKRequiredMoreThanSupported[DC__VOLTAGE_STATES + 1]; + bool ROBSupport[DC__VOLTAGE_STATES + 1]; + bool PTEBufferSizeNotExceeded[DC__VOLTAGE_STATES + 1]; + bool RequiresDSC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool IsErrorResult[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + bool ViewportSizeSupport[DC__VOLTAGE_STATES + 1]; + bool prefetch_vm_bw_valid; + bool prefetch_row_bw_valid; + bool NumberOfOTGSupport; + bool NonsupportedDSCInputBPC; + bool WritebackScaleRatioAndTapsSupport; + bool CursorSupport; + bool PitchSupport; + + double WritebackLineBufferLumaBufferSize; + double WritebackLineBufferChromaBufferSize; + double WritebackMinHSCLRatio; + double WritebackMinVSCLRatio; + double WritebackMaxHSCLRatio; + double WritebackMaxVSCLRatio; + double WritebackMaxHSCLTaps; + double WritebackMaxVSCLTaps; + unsigned int MaxNumDPP; + unsigned int MaxNumOTG; + double CursorBufferSize; + double CursorChunkSize; + unsigned int Mode; + double NoOfDPP[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double OutputLinkDPLanes[DC__NUM_DPP__MAX]; + double SwathWidthYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double SwathHeightYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double SwathHeightCPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double UrgentLatencySupportUsPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double VRatioPreY[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double VRatioPreC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredPrefetchPixelDataBW[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredDPPCLK[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double RequiredDISPCLK[DC__VOLTAGE_STATES + 1]; + double TotalNumberOfActiveDPP[DC__VOLTAGE_STATES + 1]; + double TotalNumberOfDCCActiveDPP[DC__VOLTAGE_STATES + 1]; + double PrefetchBW[DC__NUM_DPP__MAX]; + double PDEAndMetaPTEBytesPerFrame[DC__NUM_DPP__MAX]; + double MetaRowBytes[DC__NUM_DPP__MAX]; + double DPTEBytesPerRow[DC__NUM_DPP__MAX]; + double PrefetchLinesY[DC__NUM_DPP__MAX]; + double PrefetchLinesC[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwY[DC__NUM_DPP__MAX]; + unsigned int MaxNumSwC[DC__NUM_DPP__MAX]; + double PrefillY[DC__NUM_DPP__MAX]; + double PrefillC[DC__NUM_DPP__MAX]; + double LineTimesForPrefetch[DC__NUM_DPP__MAX]; + double LinesForMetaPTE[DC__NUM_DPP__MAX]; + double LinesForMetaAndDPTERow[DC__NUM_DPP__MAX]; + double MinDPPCLKUsingSingleDPP[DC__NUM_DPP__MAX]; + double RequiresFEC[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + unsigned int OutputBppPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + double DSCDelayPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + unsigned int Read256BlockHeightY[DC__NUM_DPP__MAX]; + unsigned int Read256BlockWidthY[DC__NUM_DPP__MAX]; + unsigned int Read256BlockHeightC[DC__NUM_DPP__MAX]; + unsigned int Read256BlockWidthC[DC__NUM_DPP__MAX]; + unsigned int ImmediateFlipBytes[DC__NUM_DPP__MAX]; + double MaxSwathHeightY[DC__NUM_DPP__MAX]; + double MaxSwathHeightC[DC__NUM_DPP__MAX]; + double MinSwathHeightY[DC__NUM_DPP__MAX]; + double MinSwathHeightC[DC__NUM_DPP__MAX]; + double PSCL_FACTOR[DC__NUM_DPP__MAX]; + double PSCL_FACTOR_CHROMA[DC__NUM_DPP__MAX]; + double MaximumVStartup[DC__NUM_DPP__MAX]; + double AlignedDCCMetaPitch[DC__NUM_DPP__MAX]; + double AlignedYPitch[DC__NUM_DPP__MAX]; + double AlignedCPitch[DC__NUM_DPP__MAX]; + double MaximumSwathWidth[DC__NUM_DPP__MAX]; + double final_flip_bw[DC__NUM_DPP__MAX]; + double ImmediateFlipSupportedForState[DC__VOLTAGE_STATES + 1]; + + double WritebackLumaVExtra; + double WritebackChromaVExtra; + double WritebackRequiredDISPCLK; + double MaximumSwathWidthSupport; + double MaximumSwathWidthInDETBuffer; + double MaximumSwathWidthInLineBuffer; + double MaxDispclkRoundedDownToDFSGranularity; + double MaxDppclkRoundedDownToDFSGranularity; + double PlaneRequiredDISPCLKWithoutODMCombine; + double PlaneRequiredDISPCLK; + double TotalNumberOfActiveOTG; + double FECOverhead; + double EffectiveFECOverhead; + unsigned int Outbpp; + unsigned int OutbppDSC; + double TotalDSCUnitsRequired; + double bpp; + unsigned int slices; + double SwathWidthGranularityY; + double RoundedUpMaxSwathSizeBytesY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesC; + double LinesInDETLuma; + double LinesInDETChroma; + double EffectiveDETLBLinesLuma; + double EffectiveDETLBLinesChroma; + double ProjectedDCFCLKDeepSleep; + double PDEAndMetaPTEBytesPerFrameY; + double PDEAndMetaPTEBytesPerFrameC; + unsigned int MetaRowBytesY; + unsigned int MetaRowBytesC; + unsigned int DPTEBytesPerRowC; + unsigned int DPTEBytesPerRowY; + double ExtraLatency; + double TimeCalc; + double TWait; + double MaximumReadBandwidthWithPrefetch; + double total_dcn_read_bw_with_flip; }; #endif /* _DML2_DISPLAY_MODE_VBA_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 9cbd415e508d..2af6d150cc46 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -35,6 +35,18 @@ double dml_max(double a, double b) { return (double) dcn_bw_max2(a, b); } +double dml_max3(double a, double b, double c) +{ + return dml_max(dml_max(a, b), c); +} +double dml_max4(double a, double b, double c, double d) +{ + return dml_max(dml_max(a, b), dml_max(c, d)); +} +double dml_max5(double a, double b, double c, double d, double e) +{ + return dml_max(dml_max4(a, b, c, d), e); +} double dml_ceil(double a, double granularity) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index 19271e79abcc..ba01bbb007fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -36,6 +36,9 @@ double dml_min(double a, double b); double dml_max(double a, double b); +double dml_max3(double a, double b, double c); +double dml_max4(double a, double b, double c, double d); +double dml_max5(double a, double b, double c, double d, double e); bool dml_util_is_420(enum source_format_class sorce_format); double dml_ceil_ex(double x, double granularity); double dml_floor_ex(double x, double granularity); -- GitLab From c81a351ab9c054e28544f31f715ad50cfe54089d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 20 Sep 2017 17:50:02 -0400 Subject: [PATCH 1303/2898] drm/amd/display: extract global sync params from vba Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/display_mode_vba.c | 32 +++++++++++++------ .../drm/amd/display/dc/dml/display_mode_vba.h | 3 ++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index e1a3182d58b3..054b5067fc17 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -88,7 +88,10 @@ static bool CalculatePrefetchSchedule( double *VRatioPrefetchC, double *RequiredPrefetchPixDataBW, unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - double *Tno_bw); + double *Tno_bw, + unsigned int *VUpdateOffsetPix, + unsigned int *VUpdateWidthPix, + unsigned int *VReadyOffsetPix); static double RoundToDFSGranularityUp(double Clock, double VCOSpeed); static double RoundToDFSGranularityDown(double Clock, double VCOSpeed); static double CalculatePrefetchSourceLines( @@ -264,7 +267,7 @@ unsigned int dml_get_voltage_level( memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); mode_lib->vba.cache_num_pipes = num_pipes; - if (need_recalculate) + if (need_recalculate && pipes[0].clks_cfg.dppclk_mhz != 0) recalculate(mode_lib); else { fetch_socbb_params(mode_lib); @@ -1066,10 +1069,13 @@ static bool CalculatePrefetchSchedule( double *VRatioPrefetchC, double *RequiredPrefetchPixDataBW, unsigned int *VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - double *Tno_bw) + double *Tno_bw, + unsigned int *VUpdateOffsetPix, + unsigned int *VUpdateWidthPix, + unsigned int *VReadyOffsetPix) { bool MyError = false; - unsigned int DPPCycles, DISPCLKCycles, VUpdateOffsetPix, VUpdateWidthPix, VReadyOffsetPix; + unsigned int DPPCycles, DISPCLKCycles; double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime; double Tdm, LineTime, Tsetup; double dst_y_prefetch_equ; @@ -1110,17 +1116,17 @@ static bool CalculatePrefetchSchedule( *DSTYAfterScaler = dml_floor(DSTTotalPixelsAfterScaler / HTotal, 1); *DSTXAfterScaler = DSTTotalPixelsAfterScaler - ((double) (*DSTYAfterScaler * HTotal)); - VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); + *VUpdateOffsetPix = dml_ceil(HTotal / 4.0, 1); TotalRepeaterDelayTime = MaxInterDCNTileRepeaters * (2.0 / DPPCLK + 3.0 / DISPCLK); - VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) + *VUpdateWidthPix = (14.0 / DCFClkDeepSleep + 12.0 / DPPCLK + TotalRepeaterDelayTime) * PixelClock; - VReadyOffsetPix = dml_max( + *VReadyOffsetPix = dml_max( 150.0 / DPPCLK, TotalRepeaterDelayTime + 20.0 / DCFClkDeepSleep + 10.0 / DPPCLK) * PixelClock; - Tsetup = (double) (VUpdateOffsetPix + VUpdateWidthPix + VReadyOffsetPix) / PixelClock; + Tsetup = (double) (*VUpdateOffsetPix + *VUpdateWidthPix + *VReadyOffsetPix) / PixelClock; LineTime = (double) HTotal / PixelClock; @@ -2710,7 +2716,10 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman &mode_lib->vba.VRatioPrefetchC[k], &mode_lib->vba.RequiredPrefetchPixDataBW[k], &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - &mode_lib->vba.Tno_bw[k]); + &mode_lib->vba.Tno_bw[k], + &mode_lib->vba.VUpdateOffsetPix[k], + &mode_lib->vba.VUpdateWidthPix[k], + &mode_lib->vba.VReadyOffsetPix[k]); if (mode_lib->vba.BlendingAndTiming[k] == k) { mode_lib->vba.VStartup[k] = dml_min( mode_lib->vba.VStartupLines, @@ -5805,7 +5814,10 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ &mode_lib->vba.VRatioPreC[i][k], &mode_lib->vba.RequiredPrefetchPixelDataBW[i][k], &mode_lib->vba.VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - &mode_lib->vba.Tno_bw[k]); + &mode_lib->vba.Tno_bw[k], + &mode_lib->vba.VUpdateOffsetPix[k], + &mode_lib->vba.VUpdateWidthPix[k], + &mode_lib->vba.VReadyOffsetPix[k]); } for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { mode_lib->vba.cursor_bw[k] = mode_lib->vba.NumberOfCursors[k] diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 346ffea843c9..5758c3fd39ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -383,6 +383,9 @@ struct vba_vars_st { double DPPCLK_calculated[DC__NUM_DPP__MAX]; unsigned int VStartup[DC__NUM_DPP__MAX]; + unsigned int VUpdateOffsetPix[DC__NUM_DPP__MAX]; + unsigned int VUpdateWidthPix[DC__NUM_DPP__MAX]; + unsigned int VReadyOffsetPix[DC__NUM_DPP__MAX]; unsigned int VStartupRequiredWhenNotEnoughTimeForDynamicMetadata; double ImmediateFlipBW; -- GitLab From 09f2317be4e86a60b481ce14da84c0752f848235 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Wed, 20 Sep 2017 18:32:51 -0400 Subject: [PATCH 1304/2898] drm/amd/display: change dml vba cursor count define to correct one Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 054b5067fc17..a11b37c50d96 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -633,7 +633,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.NumberOfCursors[mode_lib->vba.NumberOfActivePlanes] = 0; // The DML spreadsheet assumes that the two cursors utilize the same amount of bandwidth. We'll // calculate things a little more accurately - for (k = 0; k < DC__NUM_CURSOR; ++k) { + for (k = 0; k < DC__NUM_CURSOR__MAX; ++k) { switch (k) { case 0: mode_lib->vba.CursorBPP[mode_lib->vba.NumberOfActivePlanes][0] = diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 5758c3fd39ba..63ad4a7bfeb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -332,8 +332,8 @@ struct vba_vars_st { unsigned int BlendingAndTiming[DC__NUM_DPP__MAX]; bool SynchronizedVBlank; unsigned int NumberOfCursors[DC__NUM_DPP__MAX]; - unsigned int CursorWidth[DC__NUM_DPP__MAX][DC__NUM_CURSOR]; - unsigned int CursorBPP[DC__NUM_DPP__MAX][DC__NUM_CURSOR]; + unsigned int CursorWidth[DC__NUM_DPP__MAX][DC__NUM_CURSOR__MAX]; + unsigned int CursorBPP[DC__NUM_DPP__MAX][DC__NUM_CURSOR__MAX]; bool XFCEnabled[DC__NUM_DPP__MAX]; bool ScalerEnabled[DC__NUM_DPP__MAX]; -- GitLab From 0fc899b0f1d522efc171c09cb36ce1d27cd75de2 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 27 Sep 2017 17:28:11 -0400 Subject: [PATCH 1305/2898] drm/amd/display: Enable double buffer as per vertical interrupt enabled. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 11 +++++++++++ .../drm/amd/display/dc/dcn10/dcn10_timing_generator.h | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 7cd10cbc5497..8dbc82ff9b3a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -299,6 +299,17 @@ static void tgn10_program_timing( static void tgn10_unblank_crtc(struct timing_generator *tg) { struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); + uint32_t vertical_interrupt_enable = 0; + + REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, + OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &vertical_interrupt_enable); + + /* temporary work around for vertical interrupt, once vertical interrupt enabled, + * this check will be removed. + */ + if (vertical_interrupt_enable) + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, 1); REG_UPDATE_2(OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h index 0826d73b9809..7d4818d7aa31 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h @@ -65,6 +65,7 @@ SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ SRI(OTG_BLACK_COLOR, OTG, inst),\ SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ @@ -117,6 +118,7 @@ struct dcn_tg_registers { uint32_t OTG_TEST_PATTERN_CONTROL; uint32_t OTG_TEST_PATTERN_COLOR; uint32_t OTG_CLOCK_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; uint32_t OPTC_INPUT_CLOCK_CONTROL; uint32_t OPTC_DATA_SOURCE_SELECT; @@ -196,6 +198,7 @@ struct dcn_tg_registers { SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ @@ -302,6 +305,7 @@ struct dcn_tg_registers { type OTG_CLOCK_EN;\ type OTG_CLOCK_ON;\ type OTG_CLOCK_GATE_DIS;\ + type OTG_VERTICAL_INTERRUPT2_INT_ENABLE;\ type OTG_VERTICAL_INTERRUPT2_LINE_START;\ type OPTC_INPUT_CLK_EN;\ type OPTC_INPUT_CLK_ON;\ -- GitLab From 6a2b691f0985d16c16b70dbc4b5727afabde6ba9 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 26 Sep 2017 22:16:11 -0400 Subject: [PATCH 1306/2898] drm/amd/display: wrong VM setting cause invalid DF request from DCN fix typo in register field. we are lucky the shift/mask is the same, no behavior change add globals to experiment with using different VM settings Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 11 +++++++---- .../gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index b61f41c61358..c09e65a0031a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -632,6 +632,9 @@ bool min10_is_flip_pending(struct mem_input *mem_input) return false; } +uint32_t aperture_default_system = 1; +uint32_t context0_default_system; /* = 0;*/ + static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, struct vm_system_aperture_param *apt) { @@ -645,7 +648,7 @@ static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12; REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0, - MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, 1, /* 1 = system physical memory */ + MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, aperture_default_system, /* 1 = system physical memory */ MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part); REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part); @@ -684,9 +687,9 @@ static void min10_set_vm_context0_settings(struct mem_input *mem_input, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part); /* fault handling */ - REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, - VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->fault_default.high_part); - /* VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, 0 */ + REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, vm0->fault_default.high_part, + VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, context0_default_system); REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index fdeb0e87463e..15231e86e6c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -369,6 +369,7 @@ struct dcn_mi_registers { MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, mask_sh),\ + MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mask_sh),\ MI_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mask_sh),\ @@ -522,6 +523,7 @@ struct dcn_mi_registers { type VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB;\ type VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB;\ type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB;\ + type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM;\ type VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB;\ type ENABLE_L1_TLB;\ type SYSTEM_ACCESS_MODE;\ -- GitLab From 96687275555a166951d77d845a924ee07b854822 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 27 Sep 2017 17:57:37 -0400 Subject: [PATCH 1307/2898] drm/amd/display: Fix hotplug after s3 resume. On S3 resume the HPD6 irq source was not reenabled due to loop boundary bug. Signed-off-by: Roman Li Reviewed-by: Mikita Lipski Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 52b6e4a91d8b..8de19ba5b2e3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -462,7 +462,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) DRM_DEBUG_KMS("DM_IRQ: early resume\n"); /* re-enable short pulse interrupts HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1RX; src < DC_IRQ_SOURCE_HPD6RX + 1; src++) { + for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX + 1; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) @@ -488,7 +488,7 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) * Renable HW interrupt for HPD and only since FLIP and VBLANK * will be enabled from manage_dm_interrupts on enable CRTC. */ - for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6; src++) { + for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) -- GitLab From 3eab79163fcb0f7777440dfe360d2eedbbcc47b9 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Tue, 26 Sep 2017 15:35:42 +0530 Subject: [PATCH 1308/2898] drm/amd/display: make FBC configurable option Currently FBC is guarded with ENABLE_FBC macro, which needs to be manually enabled in Makefile. This patch moves it to Kconfig so that there wont be any need to additional patch to be carried for enabling or disabling on every SoC. Signed-off-by: Shirish S Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 4 ++-- drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- .../amd/display/dc/dce110/dce110_compressor.c | 2 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 16 ++++++++-------- .../drm/amd/display/dc/dce110/dce110_resource.c | 4 ++-- 7 files changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 6d1086d0a277..ec3285f65517 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -17,6 +17,16 @@ config DRM_AMD_DC_PRE_VEGA by default. This includes Polaris, Carrizo, Tonga, Bonaire, and Hawaii. +config DRM_AMD_DC_FBC + bool "AMD FBC - Enable Frame Buffer Compression" + depends on DRM_AMD_DC + help + Choose this option if you want to use frame buffer compression + support. + This is a power optimisation feature, check its availability + on your hardware before enabling this option. + + config DRM_AMD_DC_DCN1_0 bool "DCN 1.0 Raven family" depends on DRM_AMD_DC && X86 diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 3439bc46a4a2..a5c72dbc2dcc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -507,7 +507,7 @@ static bool construct(struct dc *dc, dc_version = resource_parse_asic_id(init_params->asic_id); dc->ctx->dce_version = dc_version; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; #endif /* Resource should construct all asic specific resources. diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bf83459456a8..adadfad2bd51 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -258,7 +258,7 @@ struct dc { struct dm_pp_display_configuration prev_display_config; /* FBC compressor */ -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) struct compressor *fbc_compressor; #endif }; @@ -293,7 +293,7 @@ struct dc_init_data { struct dc_config flags; uint32_t log_mask; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) uint64_t fbc_gpu_addr; #endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 4bd74fc6c782..a8698e399111 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -92,7 +92,7 @@ struct dc_context { bool created_bios; struct gpio_service *gpio_service; struct i2caux *i2caux; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) uint64_t fbc_gpu_addr; #endif }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 3872febb4f6b..6923662413cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -514,7 +514,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor, compressor->base.lpt_channels_num = 0; compressor->base.attached_inst = 0; compressor->base.is_enabled = false; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) compressor->base.funcs = &dce110_compressor_funcs; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index a891e387ed7b..247e81806c4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -34,7 +34,7 @@ #include "dce/dce_hwseq.h" #include "gpio_service_interface.h" -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) #include "dce110_compressor.h" #endif @@ -1445,7 +1445,7 @@ static void power_down_all_hw_blocks(struct dc *dc) power_down_clock_sources(dc); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif @@ -1618,7 +1618,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, if (events->cursor_update) value |= 0x2; -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) value |= 0x84; #endif @@ -1748,7 +1748,7 @@ static void apply_min_clocks( } } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) /* * Check if FBC can be enabled @@ -1940,7 +1940,7 @@ enum dc_status dce110_apply_ctx_to_hw( set_safe_displaymarks(&context->res_ctx, dc->res_pool); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); #endif @@ -2124,7 +2124,7 @@ enum dc_status dce110_apply_ctx_to_hw( dcb->funcs->set_scratch_critical_state(dcb, false); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) enable_fbc(dc, context); @@ -2533,7 +2533,7 @@ static void init_hw(struct dc *dc) abm->funcs->init_backlight(abm); abm->funcs->abm_init(abm); } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor) dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); #endif @@ -2781,7 +2781,7 @@ static void dce110_program_front_end_for_pipe( program_scaler(dc, pipe_ctx); -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) if (dc->fbc_compressor && old_pipe->stream) { if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 8e4ec61d59a4..db96d2b47ff1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -52,7 +52,7 @@ #include "dce/dce_abm.h" #include "dce/dce_dmcu.h" -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) #include "dce110/dce110_compressor.h" #endif @@ -1279,7 +1279,7 @@ static bool construct( } } -#ifdef ENABLE_FBC +#if defined(CONFIG_DRM_AMD_DC_FBC) dc->fbc_compressor = dce110_compressor_create(ctx); -- GitLab From 50d4cfdc118122f58ffdb09607a57c621e24d777 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 28 Sep 2017 10:40:10 -0400 Subject: [PATCH 1309/2898] drm/amd/display: Program front end first when set mode. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 27 ++++++++++++------- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 5 ++-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a5c72dbc2dcc..f9bac11d3950 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -763,16 +763,6 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) if (!dcb->funcs->is_accelerated_mode(dcb)) dc->hwss.enable_accelerated_mode(dc); - dc->hwss.ready_shared_resources(dc, context); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; - dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); - } - result = dc->hwss.apply_ctx_to_hw(dc, context); - - program_timing_sync(dc, context); - for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; @@ -798,6 +788,13 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) } } + for (j = 0; j < MAX_PIPES; j++) { + pipe = &context->res_ctx.pipe_ctx[j]; + + if (!pipe->top_pipe && pipe->stream == context->streams[i]) + dc->hwss.pipe_control_lock(dc, pipe, false); + } + CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", context->streams[i]->timing.h_addressable, context->streams[i]->timing.v_addressable, @@ -806,6 +803,16 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) context->streams[i]->timing.pix_clk_khz); } + dc->hwss.ready_shared_resources(dc, context); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; + dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe); + } + result = dc->hwss.apply_ctx_to_hw(dc, context); + + program_timing_sync(dc, context); + dc_enable_stereo(dc, context, dc_streams, context->stream_count); dc_release_state(dc->current_state); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 86cfab33feea..84d9d202d3b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2283,8 +2283,6 @@ static void update_dchubp_dpp( */ REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); - dc->hwss.update_plane_addr(dc, pipe_ctx); - mi->funcs->mem_input_setup( mi, &pipe_ctx->dlg_regs, @@ -2353,6 +2351,8 @@ static void update_dchubp_dpp( &plane_state->dcc, plane_state->horizontal_mirror); + dc->hwss.update_plane_addr(dc, pipe_ctx); + if (is_pipe_tree_visible(pipe_ctx)) mi->funcs->set_blank(mi, false); } @@ -2556,6 +2556,7 @@ static void dcn10_apply_ctx_for_surface( old_pipe_ctx->top_pipe = NULL; old_pipe_ctx->bottom_pipe = NULL; old_pipe_ctx->plane_state = NULL; + old_pipe_ctx->stream = NULL; dm_logger_write(dc->ctx->logger, LOG_DC, "Reset mpcc for pipe %d\n", -- GitLab From 4176664b1fc8aa052f886037590cac4fb0dd8afb Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Wed, 27 Sep 2017 23:23:16 -0400 Subject: [PATCH 1310/2898] drm/amd/display: audio dynamic resource acquired related Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- .../drm/amd/display/dc/core/dc_link_hwss.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 24 ++++++++++++++----- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../display/dc/dce110/dce110_hw_sequencer.c | 12 ++++++++-- .../display/dc/dce110/dce110_hw_sequencer.h | 2 +- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 7 +++++- .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++- drivers/gpu/drm/amd/display/dc/inc/resource.h | 5 ++++ 10 files changed, 47 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index e414e4770789..2d59f77fa9a2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2323,14 +2323,14 @@ void core_link_enable_stream( allocate_mst_payload(pipe_ctx); } -void core_link_disable_stream(struct pipe_ctx *pipe_ctx) +void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) { struct dc *core_dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); - core_dc->hwss.disable_stream(pipe_ctx); + core_dc->hwss.disable_stream(pipe_ctx, option); disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 34b6d1cb151e..9a33b471270a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -282,7 +282,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, dp_receiver_power_ctrl(link, false); - link->dc->hwss.disable_stream(&pipes[i]); + link->dc->hwss.disable_stream(&pipes[i], KEEP_ACQUIRED_RESOURCE); link->link_enc->funcs->disable_output( link->link_enc, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index bbfec7cb2ad1..68c613229a10 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -242,7 +242,10 @@ bool resource_construct( pool->stream_enc_count++; } } - + dc->caps.dynamic_audio = false; + if (pool->audio_count < pool->stream_enc_count) { + dc->caps.dynamic_audio = true; + } for (i = 0; i < num_virtual_links; i++) { pool->stream_enc[pool->stream_enc_count] = virtual_stream_encoder_create( @@ -1330,7 +1333,7 @@ static void update_stream_engine_usage( } /* TODO: release audio object */ -static void update_audio_usage( +void update_audio_usage( struct resource_context *res_ctx, const struct resource_pool *pool, struct audio *audio, @@ -1414,12 +1417,21 @@ static struct audio *find_first_free_audio( const struct resource_pool *pool) { int i; - for (i = 0; i < pool->audio_count; i++) { - if (res_ctx->is_audio_acquired[i] == false) { - return pool->audios[i]; + if (pool->audio_count >= pool->stream_enc_count) { + for (i = 0; i < pool->audio_count; i++) { + if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { + /*we have enough audio endpoint, no need to do dynamic distribution*/ + return pool->audios[i]; + } } - } + } else { /*first come first serve*/ + for (i = 0; i < pool->audio_count; i++) { + if (res_ctx->is_audio_acquired[i] == false) { + return pool->audios[i]; + } + } + } return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index adadfad2bd51..2517fb821fff 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -58,6 +58,7 @@ struct dc_caps { uint32_t i2c_speed_in_khz; unsigned int max_cursor_size; bool dcc_const_color; + bool dynamic_audio; }; struct dc_dcc_surface_param { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 247e81806c4a..453d2ffd5c4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -985,10 +985,11 @@ void hwss_edp_backlight_control( link_transmitter_control(link->dc->ctx->dc_bios, &cntl); } -void dce110_disable_stream(struct pipe_ctx *pipe_ctx) +void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; + struct dc *dc = pipe_ctx->stream->ctx->dc; if (pipe_ctx->stream_res.audio) { pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); @@ -999,6 +1000,13 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); + /*don't free audio if it is from retrain or internal disable stream*/ + if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) { + /*we have to dynamic arbitrate the audio endpoints*/ + pipe_ctx->stream_res.audio = NULL; + /*we free the resource, need reset is_audio_acquired*/ + update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); + } /* TODO: notify audio driver for if audio modes list changed * add audio mode list change flag */ @@ -1871,7 +1879,7 @@ static void dce110_reset_hw_ctx_wrap( pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { struct clock_source *old_clk = pipe_ctx_old->clock_source; - core_link_disable_stream(pipe_ctx_old); + core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { dm_error("DC: failed to blank crtc!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index a1e964af60ac..4d72bb99be93 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -47,7 +47,7 @@ void dce110_set_displaymarks( void dce110_enable_stream(struct pipe_ctx *pipe_ctx); -void dce110_disable_stream(struct pipe_ctx *pipe_ctx); +void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option); void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 84d9d202d3b5..072c48188b79 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1025,7 +1025,7 @@ static void reset_back_end_for_pipe( * which is used by otg. Move disable_link after disable_crtc */ if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - core_link_disable_stream(pipe_ctx); + core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); /* by upper caller loop, parent pipe: pipe0, will be reset last. * back end share by all pipes and will be disable only when disable diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index ff23f268fe02..5230dddc8617 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -58,6 +58,11 @@ struct link_init_data { TODO: remove it when DC is complete. */ }; +enum { + FREE_ACQUIRED_RESOURCE = 0, + KEEP_ACQUIRED_RESOURCE = 1, +}; + struct dc_link *link_create(const struct link_init_data *init_params); void link_destroy(struct dc_link **link); @@ -72,7 +77,7 @@ void core_link_enable_stream( struct dc_state *state, struct pipe_ctx *pipe_ctx); -void core_link_disable_stream(struct pipe_ctx *pipe_ctx); +void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option); void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); /********** DAL Core*********************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index bf3ab5d7398e..8734689a9245 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -134,7 +134,8 @@ struct hw_sequencer_funcs { void (*enable_stream)(struct pipe_ctx *pipe_ctx); - void (*disable_stream)(struct pipe_ctx *pipe_ctx); + void (*disable_stream)(struct pipe_ctx *pipe_ctx, + int option); void (*unblank_stream)(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 614bb691ab59..5467332faf7b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -164,4 +164,9 @@ bool pipe_need_reprogram( void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, struct bit_depth_reduction_params *fmt_bit_depth); +void update_audio_usage( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct audio *audio, + bool acquired); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ -- GitLab From b7901be0ed5d43525ac2c3fc2a3f9a0cdc5d069c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 28 Sep 2017 14:54:58 -0400 Subject: [PATCH 1311/2898] drm/amd/display: renaming mem input to hubp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_mem_input.c | 76 +++++++++---------- .../amd/display/dc/dcn10/dcn10_mem_input.h | 24 +++--- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index c09e65a0031a..46086bec9982 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -38,7 +38,7 @@ #define FN(reg_name, field_name) \ mi->mi_shift->field_name, mi->mi_mask->field_name -void min10_set_blank(struct mem_input *mem_input, bool blank) +void hubp1_set_blank(struct mem_input *mem_input, bool blank) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; @@ -56,7 +56,7 @@ void min10_set_blank(struct mem_input *mem_input, bool blank) } } -static void min10_set_hubp_blank_en(struct mem_input *mem_input, bool blank) +static void hubp1_set_hubp_blank_en(struct mem_input *mem_input, bool blank) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); uint32_t blank_en = blank ? 1 : 0; @@ -64,7 +64,7 @@ static void min10_set_hubp_blank_en(struct mem_input *mem_input, bool blank) REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); } -static void min10_vready_workaround(struct mem_input *mem_input, +static void hubp1_vready_workaround(struct mem_input *mem_input, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { uint32_t value = 0; @@ -87,7 +87,7 @@ static void min10_vready_workaround(struct mem_input *mem_input, REG_WRITE(HUBPREQ_DEBUG_DB, value); } -void min10_program_tiling( +void hubp1_program_tiling( struct dcn10_mem_input *mi, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) @@ -107,7 +107,7 @@ void min10_program_tiling( PIPE_ALIGNED, info->gfx9.pipe_aligned); } -void min10_program_size_and_rotation( +void hubp1_program_size_and_rotation( struct dcn10_mem_input *mi, enum dc_rotation_angle rotation, enum surface_pixel_format format, @@ -169,7 +169,7 @@ void min10_program_size_and_rotation( H_MIRROR_EN, mirror); } -void min10_program_pixel_format( +void hubp1_program_pixel_format( struct dcn10_mem_input *mi, enum surface_pixel_format format) { @@ -245,7 +245,7 @@ void min10_program_pixel_format( /* don't see the need of program the xbar in DCN 1.0 */ } -bool min10_program_surface_flip_and_addr( +bool hubp1_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate) @@ -395,7 +395,7 @@ bool min10_program_surface_flip_and_addr( return true; } -void min10_dcc_control(struct mem_input *mem_input, bool enable, +void hubp1_dcc_control(struct mem_input *mem_input, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; @@ -407,7 +407,7 @@ void min10_dcc_control(struct mem_input *mem_input, bool enable, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); } -static void min10_program_surface_config( +static void hubp1_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -418,14 +418,14 @@ static void min10_program_surface_config( { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); - min10_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); - min10_program_tiling(mi, tiling_info, format); - min10_program_size_and_rotation( + hubp1_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); + hubp1_program_tiling(mi, tiling_info, format); + hubp1_program_size_and_rotation( mi, rotation, format, plane_size, dcc, horizontal_mirror); - min10_program_pixel_format(mi, format); + hubp1_program_pixel_format(mi, format); } -void min10_program_requestor( +void hubp1_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs) { @@ -459,7 +459,7 @@ void min10_program_requestor( } -void min10_program_deadline( +void hubp1_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) @@ -580,7 +580,7 @@ void min10_program_deadline( ttu_attr->refcyc_per_req_delivery_pre_c); } -static void min10_setup( +static void hubp1_setup( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr, @@ -590,12 +590,12 @@ static void min10_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - min10_program_requestor(mem_input, rq_regs); - min10_program_deadline(mem_input, dlg_attr, ttu_attr); - min10_vready_workaround(mem_input, pipe_dest); + hubp1_program_requestor(mem_input, rq_regs); + hubp1_program_deadline(mem_input, dlg_attr, ttu_attr); + hubp1_vready_workaround(mem_input, pipe_dest); } -void min10_program_display_marks( +void hubp1_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, @@ -607,7 +607,7 @@ void min10_program_display_marks( */ } -bool min10_is_flip_pending(struct mem_input *mem_input) +bool hubp1_is_flip_pending(struct mem_input *mem_input) { uint32_t flip_pending = 0; struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -635,7 +635,7 @@ bool min10_is_flip_pending(struct mem_input *mem_input) uint32_t aperture_default_system = 1; uint32_t context0_default_system; /* = 0;*/ -static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, +static void hubp1_set_vm_system_aperture_settings(struct mem_input *mem_input, struct vm_system_aperture_param *apt) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -664,7 +664,7 @@ static void min10_set_vm_system_aperture_settings(struct mem_input *mem_input, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); } -static void min10_set_vm_context0_settings(struct mem_input *mem_input, +static void hubp1_set_vm_context0_settings(struct mem_input *mem_input, const struct vm_context0_param *vm0) { struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); @@ -848,7 +848,7 @@ static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( return line_per_chunk; } -void ippn10_cursor_set_attributes( +void hubp1_cursor_set_attributes( struct mem_input *mem_input, const struct dc_cursor_attributes *attr) { @@ -876,7 +876,7 @@ void ippn10_cursor_set_attributes( attr->color_format); } -void ippn10_cursor_set_position( +void hubp1_cursor_set_position( struct mem_input *mem_input, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param) @@ -913,7 +913,7 @@ void ippn10_cursor_set_position( cur_en = 0; /* not visible beyond left edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - ippn10_cursor_set_attributes(mem_input, &mem_input->curs_attr); + hubp1_cursor_set_attributes(mem_input, &mem_input->curs_attr); REG_UPDATE(CURSOR_CONTROL, CURSOR_ENABLE, cur_en); @@ -931,21 +931,21 @@ void ippn10_cursor_set_position( } static struct mem_input_funcs dcn10_mem_input_funcs = { - .mem_input_program_display_marks = min10_program_display_marks, + .mem_input_program_display_marks = hubp1_program_display_marks, .mem_input_program_surface_flip_and_addr = - min10_program_surface_flip_and_addr, + hubp1_program_surface_flip_and_addr, .mem_input_program_surface_config = - min10_program_surface_config, - .mem_input_is_flip_pending = min10_is_flip_pending, - .mem_input_setup = min10_setup, - .mem_input_set_vm_system_aperture_settings = min10_set_vm_system_aperture_settings, - .mem_input_set_vm_context0_settings = min10_set_vm_context0_settings, - .set_blank = min10_set_blank, - .dcc_control = min10_dcc_control, + hubp1_program_surface_config, + .mem_input_is_flip_pending = hubp1_is_flip_pending, + .mem_input_setup = hubp1_setup, + .mem_input_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, + .mem_input_set_vm_context0_settings = hubp1_set_vm_context0_settings, + .set_blank = hubp1_set_blank, + .dcc_control = hubp1_dcc_control, .mem_program_viewport = min_set_viewport, - .set_hubp_blank_en = min10_set_hubp_blank_en, - .set_cursor_attributes = ippn10_cursor_set_attributes, - .set_cursor_position = ippn10_cursor_set_position, + .set_hubp_blank_en = hubp1_set_hubp_blank_en, + .set_cursor_attributes = hubp1_cursor_set_attributes, + .set_cursor_position = hubp1_cursor_set_position, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 15231e86e6c6..653875285b70 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -591,20 +591,20 @@ struct dcn10_mem_input { const struct dcn_mi_mask *mi_mask; }; -void min10_program_deadline( +void hubp1_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr); -void min10_program_requestor( +void hubp1_program_requestor( struct mem_input *mem_input, struct _vcs_dpi_display_rq_regs_st *rq_regs); -void min10_program_pixel_format( +void hubp1_program_pixel_format( struct dcn10_mem_input *mi, enum surface_pixel_format format); -void min10_program_size_and_rotation( +void hubp1_program_size_and_rotation( struct dcn10_mem_input *mi, enum dc_rotation_angle rotation, enum surface_pixel_format format, @@ -612,39 +612,39 @@ void min10_program_size_and_rotation( struct dc_plane_dcc_param *dcc, bool horizontal_mirror); -void min10_program_tiling( +void hubp1_program_tiling( struct dcn10_mem_input *mi, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format); -void min10_dcc_control(struct mem_input *mem_input, +void hubp1_dcc_control(struct mem_input *mem_input, bool enable, bool independent_64b_blks); -void min10_program_display_marks( +void hubp1_program_display_marks( struct mem_input *mem_input, struct dce_watermarks nbp, struct dce_watermarks stutter, struct dce_watermarks urgent, uint32_t total_dest_line_time_ns); -bool min10_program_surface_flip_and_addr( +bool hubp1_program_surface_flip_and_addr( struct mem_input *mem_input, const struct dc_plane_address *address, bool flip_immediate); -bool min10_is_flip_pending(struct mem_input *mem_input); +bool hubp1_is_flip_pending(struct mem_input *mem_input); -void ippn10_cursor_set_attributes( +void hubp1_cursor_set_attributes( struct mem_input *mem_input, const struct dc_cursor_attributes *attr); -void ippn10_cursor_set_position( +void hubp1_cursor_set_position( struct mem_input *mem_input, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param); -void min10_set_blank(struct mem_input *mem_input, bool blank); +void hubp1_set_blank(struct mem_input *mem_input, bool blank); void min_set_viewport(struct mem_input *mem_input, const struct rect *viewport, -- GitLab From 66bfd4fd17737d0a644fa74e0cb309c0daf8fb22 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 28 Sep 2017 15:38:01 -0400 Subject: [PATCH 1312/2898] drm/amd/display: arbitration find the matching dig-az first. [Description] this change is in branch already. without this change, after resume, az_inst might swapped. Signed-off-by: Charlene Liu Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 68c613229a10..c31dccdc3d2e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1417,19 +1417,15 @@ static struct audio *find_first_free_audio( const struct resource_pool *pool) { int i; - if (pool->audio_count >= pool->stream_enc_count) { - for (i = 0; i < pool->audio_count; i++) { - if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { - /*we have enough audio endpoint, no need to do dynamic distribution*/ - return pool->audios[i]; - } + for (i = 0; i < pool->audio_count; i++) { + if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { + return pool->audios[i]; } - } else { /*first come first serve*/ - for (i = 0; i < pool->audio_count; i++) { - if (res_ctx->is_audio_acquired[i] == false) { - - return pool->audios[i]; - } + } + /*not found the matching one, first come first serve*/ + for (i = 0; i < pool->audio_count; i++) { + if (res_ctx->is_audio_acquired[i] == false) { + return pool->audios[i]; } } return 0; -- GitLab From e4b3b5ccd9835bafab67851a7cc759c9250a8a9d Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 28 Sep 2017 16:09:56 -0400 Subject: [PATCH 1313/2898] drm/amd/display: Making hubp1_program_surface_config public Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c | 3 ++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 46086bec9982..2336da54000c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -407,7 +407,7 @@ void hubp1_dcc_control(struct mem_input *mem_input, bool enable, PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk); } -static void hubp1_program_surface_config( +void hubp1_program_surface_config( struct mem_input *mem_input, enum surface_pixel_format format, union dc_tiling_info *tiling_info, @@ -970,3 +970,4 @@ void dcn10_mem_input_construct( mi->base.mpcc_id = 0xf; } + diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 653875285b70..5c5eed5c95d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -591,6 +591,15 @@ struct dcn10_mem_input { const struct dcn_mi_mask *mi_mask; }; +void hubp1_program_surface_config( + struct mem_input *mem_input, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + void hubp1_program_deadline( struct mem_input *mem_input, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, -- GitLab From c018b04b7c17e0814bc75b09d782204d73c64b1b Mon Sep 17 00:00:00 2001 From: Roman Li Date: Thu, 28 Sep 2017 12:57:21 -0400 Subject: [PATCH 1314/2898] drm/amd/display: Fix irq enable/disable on resume. Fixing loop boundaries in irq enable/disable on resume. Signed-off-by: Roman Li Reviewed-by: Mikita Lipski Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 8de19ba5b2e3..b9e4d3831001 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -435,7 +435,7 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) * Disable HW interrupt for HPD and HPDRX only since FLIP and VBLANK * will be disabled from manage_dm_interrupts on disable CRTC. */ - for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6RX; src++) { + for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6RX; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) @@ -462,7 +462,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) DRM_DEBUG_KMS("DM_IRQ: early resume\n"); /* re-enable short pulse interrupts HW interrupt */ - for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX + 1; src++) { + for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX; src++) { hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) -- GitLab From 4bd29c34988be0c24759d5d58df424f861a8bf24 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 28 Sep 2017 16:20:30 -0400 Subject: [PATCH 1315/2898] drm/amd/display: Do not access fbdev helper members Original code is no longer needed and tested without loop. Signed-off-by: Harry Wentland Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 610375b2a04b..382f499cb60d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -397,21 +397,10 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; - int i; drm_modeset_lock_all(dev); - if (adev->mode_info.rfbdev) { - /*Do not add if already registered in past*/ - for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) { - if (adev->mode_info.rfbdev->helper.connector_info[i]->connector - == connector) { - drm_modeset_unlock_all(dev); - return; - } - } - + if (adev->mode_info.rfbdev) drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); - } else DRM_ERROR("adev->mode_info.rfbdev is NULL\n"); -- GitLab From 365c7c975dcd1a2158ed33dab76c1d308f9f9906 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 28 Sep 2017 16:58:32 -0400 Subject: [PATCH 1316/2898] drm/amd/display: Remove drm_modeset_lock in MST code Locks are no longer needed since the drm framework takes care of correct locking. Signed-off-by: Harry Wentland Signed-off-by: Jerry Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 382f499cb60d..3b05da7a90e8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -287,9 +287,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { aconnector = to_amdgpu_dm_connector(connector); if (aconnector->mst_port == master && !aconnector->port) { @@ -299,11 +300,11 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, aconnector->port = port; drm_mode_connector_set_path_property(connector, pathprop); - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_connector_list_iter_end(&conn_iter); return &aconnector->base; } } - drm_modeset_unlock(&dev->mode_config.connection_mutex); + drm_connector_list_iter_end(&conn_iter); aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) @@ -398,14 +399,11 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector) struct drm_device *dev = connector->dev; struct amdgpu_device *adev = dev->dev_private; - drm_modeset_lock_all(dev); if (adev->mode_info.rfbdev) drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); else DRM_ERROR("adev->mode_info.rfbdev is NULL\n"); - drm_modeset_unlock_all(dev); - drm_connector_register(connector); } -- GitLab From 734a092b1fe407319c8a4f38f9b4a647ddb54c2c Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Fri, 29 Sep 2017 15:30:17 -0400 Subject: [PATCH 1317/2898] drm/amd/display: clean up dcn10 dpp after HW review Signed-off-by: Eric Bernstein Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 + .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 20 +++++ .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 85 ++++++++++--------- 3 files changed, 65 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 4ab109314e4b..1a9f57fb0838 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -204,6 +204,8 @@ enum surface_pixel_format { /*grow 444 video here if necessary */ }; + + /* Pixel format */ enum pixel_format { /*graph*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 889f91cf47cf..153aa3c32762 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1265,6 +1265,21 @@ struct dcn10_dpp { }; +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; enum dcn10_input_csc_select { INPUT_CSC_SELECT_BYPASS = 0, @@ -1272,6 +1287,11 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; +bool is_lb_conf_valid( + int ceil_vratio, + int num_partitions, + int vtaps); + void ippn10_degamma_ram_select( struct transform *xfm_base, bool use_ram_a); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index fa2ab9952388..c5267e42a2f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -57,22 +57,6 @@ enum dcn10_coef_filter_type_sel { SCL_COEF_ALPHA_HORZ_FILTER = 5 }; -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dscl_autocal_mode { AUTOCAL_MODE_OFF = 0, @@ -161,23 +145,37 @@ static int get_pixel_depth_val(enum lb_pixel_depth depth) } } -static enum dscl_mode_sel get_dscl_mode( - const struct scaler_data *data, bool dbg_always_scale) +static bool is_video_format(enum pixel_format format) { - const long long one = dal_fixed31_32_one.value; - bool ycbcr = false; - bool format420 = false; + if (format >= PIXEL_FORMAT_VIDEO_BEGIN + && format <= PIXEL_FORMAT_VIDEO_END) + return true; + else + return false; +} - if (data->format == PIXEL_FORMAT_FP16) - return DSCL_MODE_DSCL_BYPASS; +static bool is_420_format(enum pixel_format format) +{ + if (format == PIXEL_FORMAT_420BPP8 || + format == PIXEL_FORMAT_420BPP10) + return true; + else + return false; +} - if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN - && data->format <= PIXEL_FORMAT_VIDEO_END) - ycbcr = true; +static enum dscl_mode_sel get_dscl_mode( + struct transform *xfm_base, + const struct scaler_data *data, + bool dbg_always_scale) +{ + struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + const long long one = dal_fixed31_32_one.value; - if (data->format == PIXEL_FORMAT_420BPP8 || - data->format == PIXEL_FORMAT_420BPP10) - format420 = true; + if (xfm->tf_mask->PIXEL_DEPTH) { + /* DSCL caps: LB data is fixed format */ + if (data->format == PIXEL_FORMAT_FP16) + return DSCL_MODE_DSCL_BYPASS; + } if (data->ratios.horz.value == one && data->ratios.vert.value == one @@ -186,8 +184,8 @@ static enum dscl_mode_sel get_dscl_mode( && !dbg_always_scale) return DSCL_MODE_SCALING_444_BYPASS; - if (!format420) { - if (ycbcr) + if (!is_420_format(data->format)) { + if (is_video_format(data->format)) return DSCL_MODE_SCALING_444_YCBCR_ENABLE; else return DSCL_MODE_SCALING_444_RGB_ENABLE; @@ -205,11 +203,12 @@ static void dpp_set_lb( const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) { - uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); - uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; - /* LB */ if (xfm->tf_mask->PIXEL_DEPTH) { + /* DSCL caps: LB data is fixed format */ + uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; + REG_SET_7(LB_DATA_FORMAT, 0, PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */ PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */ @@ -401,7 +400,7 @@ static int get_lb_depth_bpc(enum lb_pixel_depth depth) } } -static void calc_lb_num_partitions( +static void dscl1_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, @@ -426,6 +425,7 @@ static void calc_lb_num_partitions( lb_memory_size_c = 1088; lb_memory_size_a = 1312; } else if (lb_config == LB_MEMORY_CONFIG_3) { + /* 420 mode: using 3rd mem from Y, Cr and Cb */ lb_memory_size = 816 + 1088 + 848 + 848 + 848; lb_memory_size_c = 816 + 1088; lb_memory_size_a = 984 + 1312 + 456; @@ -449,7 +449,7 @@ static void calc_lb_num_partitions( } -static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) { if (ceil_vratio > 2) return vtaps <= (num_partitions - ceil_vratio + 2); @@ -467,14 +467,14 @@ static enum lb_memory_config dpp10_find_lb_memory_config( int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); - calc_lb_num_partitions( + dscl1_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; - calc_lb_num_partitions( + dscl1_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -483,7 +483,7 @@ static enum lb_memory_config dpp10_find_lb_memory_config( if (scl_data->format == PIXEL_FORMAT_420BPP8 || scl_data->format == PIXEL_FORMAT_420BPP10) { - calc_lb_num_partitions( + dscl1_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -491,7 +491,7 @@ static enum lb_memory_config dpp10_find_lb_memory_config( return LB_MEMORY_CONFIG_3; } - calc_lb_num_partitions( + dscl1_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ @@ -511,6 +511,7 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, return mem_cfg; if (xfm->tf_mask->PIXEL_DEPTH) { + /* DSCL caps: LB data is fixed format */ mem_cfg = dpp10_find_lb_memory_config(scl_data); } return mem_cfg; @@ -523,7 +524,7 @@ void dpp_set_scaler_auto_scale( enum lb_memory_config lb_config; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); + xfm_base, scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; @@ -655,7 +656,7 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( enum lb_memory_config lb_config; struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( - scl_data, xfm_base->ctx->dc->debug.always_scale); + xfm_base, scl_data, xfm_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; -- GitLab From 3af89b96b2f22119556b8e89edde72951f6bd410 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Sat, 30 Sep 2017 21:03:40 -0400 Subject: [PATCH 1318/2898] drm/amd/display: Add stereo_support debug flag Signed-off-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2517fb821fff..172050ad845d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -217,6 +217,7 @@ struct dc_debug { bool force_abm_enable; bool disable_hbup_pg; bool disable_dpp_pg; + bool stereo_support; }; struct dc_state; struct resource_pool; -- GitLab From 13ab1b44151195823fa0e2ceace1cf4687266dba Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Thu, 28 Sep 2017 17:18:27 -0400 Subject: [PATCH 1319/2898] drm/amd/display: Fixed extend to second screen mode hang 1. Fixed acquire free split pipe bug. 2. Change return value for dc_add_stream_to_ctx from bool to enum. 4. Remove redundant apply_ctx_for_surface calling 5. Unlock pipe after back end programming. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 48 ++++++++++--------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0707bec111a5..8653453566b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4495,10 +4495,10 @@ static int dm_update_crtcs_state(struct dc *dc, DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", crtc->base.id); - if (!dc_add_stream_to_ctx( + if (dc_add_stream_to_ctx( dc, dm_state->context, - dm_new_crtc_state->stream)) { + dm_new_crtc_state->stream) != DC_OK) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f9bac11d3950..33a63c7d7a8e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -766,34 +766,27 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) for (i = 0; i < context->stream_count; i++) { const struct dc_sink *sink = context->streams[i]->sink; - for (j = 0; j < context->stream_status[i].plane_count; j++) { - dc->hwss.apply_ctx_for_surface( - dc, context->streams[i], - context->stream_status[i].plane_count, - context); + dc->hwss.apply_ctx_for_surface( + dc, context->streams[i], + context->stream_status[i].plane_count, + context); - /* - * enable stereo - * TODO rework dc_enable_stereo call to work with validation sets? - */ - for (k = 0; k < MAX_PIPES; k++) { - pipe = &context->res_ctx.pipe_ctx[k]; - - for (l = 0 ; pipe && l < context->stream_count; l++) { - if (context->streams[l] && - context->streams[l] == pipe->stream && - dc->hwss.setup_stereo) - dc->hwss.setup_stereo(pipe, dc); - } + /* + * enable stereo + * TODO rework dc_enable_stereo call to work with validation sets? + */ + for (k = 0; k < MAX_PIPES; k++) { + pipe = &context->res_ctx.pipe_ctx[k]; + + for (l = 0 ; pipe && l < context->stream_count; l++) { + if (context->streams[l] && + context->streams[l] == pipe->stream && + dc->hwss.setup_stereo) + dc->hwss.setup_stereo(pipe, dc); } } - for (j = 0; j < MAX_PIPES; j++) { - pipe = &context->res_ctx.pipe_ctx[j]; - if (!pipe->top_pipe && pipe->stream == context->streams[i]) - dc->hwss.pipe_control_lock(dc, pipe, false); - } CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", context->streams[i]->timing.h_addressable, @@ -815,6 +808,15 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) dc_enable_stereo(dc, context, dc_streams, context->stream_count); + for (i = 0; i < context->stream_count; i++) { + for (j = 0; j < MAX_PIPES; j++) { + pipe = &context->res_ctx.pipe_ctx[j]; + + if (!pipe->top_pipe && pipe->stream == context->streams[i]) + dc->hwss.pipe_control_lock(dc, pipe, false); + } + } + dc_release_state(dc->current_state); dc->current_state = context; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c31dccdc3d2e..c60f53069708 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1446,7 +1446,7 @@ bool resource_is_stream_unchanged( return false; } -bool dc_add_stream_to_ctx( +enum dc_status dc_add_stream_to_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream) @@ -1467,7 +1467,7 @@ bool dc_add_stream_to_ctx( if (res != DC_OK) DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res); - return res == DC_OK; + return res; } bool dc_remove_stream_from_ctx( @@ -1640,10 +1640,9 @@ enum dc_status resource_map_pool_resources( /* acquire new resources */ pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (pipe_idx < 0) - acquire_first_split_pipe(&context->res_ctx, pool, stream); -#endif + pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); + if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 172050ad845d..eeb8ee5acdc1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -631,7 +631,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, uint32_t *h_position, uint32_t *v_position); -bool dc_add_stream_to_ctx( +enum dc_status dc_add_stream_to_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream); -- GitLab From 309c42efdab945071c693a51334fbaeb0a700b0d Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Mon, 2 Oct 2017 17:08:24 -0400 Subject: [PATCH 1320/2898] drm/amd/display: wa to program split pipedegamma regs after mode set. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 33a63c7d7a8e..09bab93815a3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1282,7 +1282,9 @@ static void commit_planes_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FAST) continue; - if (srf_updates[i].in_transfer_func) + /* work around to program degamma regs for split pipe after set mode. */ + if (srf_updates[i].in_transfer_func || (pipe_ctx->top_pipe && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state)) dc->hwss.set_input_transfer_func( pipe_ctx, pipe_ctx->plane_state); -- GitLab From f6cb588a42a7812e65eff368d3d1134ee1a88489 Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 2 Oct 2017 16:25:58 -0400 Subject: [PATCH 1321/2898] drm/amd/display: Add debug flag for VSR support Signed-off-by: Charlene Liu Reviewed-by: Krunoslav Kovac Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index eeb8ee5acdc1..defc44393b38 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -218,6 +218,7 @@ struct dc_debug { bool disable_hbup_pg; bool disable_dpp_pg; bool stereo_support; + bool vsr_support; }; struct dc_state; struct resource_pool; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 3000ddab2357..1b108ae2e656 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -428,6 +428,7 @@ static const struct dc_debug debug_defaults_drv = { .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .disable_dcc = DCC_ENABLE, .voltage_align_fclk = true, + .vsr_support = true, }; static const struct dc_debug debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 8dbc82ff9b3a..178dadda74f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -25,6 +25,7 @@ #include "reg_helper.h" #include "dcn10_timing_generator.h" +#include "dc.h" #define REG(reg)\ tgn10->tg_regs->reg -- GitLab From 458e9d03875ec6cb2ee37b64cf201bc80401bf92 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 2 Oct 2017 12:00:24 -0400 Subject: [PATCH 1322/2898] drm/amd/display: fix re-enabling stutter for raven We were overwriting the whole register which was re-enabling stutter for raven. Now we are reading the register then setting the values only for pstate. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 4 ++++ .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 0a058e0c3fec..9a04b8758888 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -446,6 +446,8 @@ struct dce_hwseq_registers { HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) @@ -554,6 +556,8 @@ struct dce_hwseq_registers { type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ + type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE;\ + type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE;\ type DCHUBBUB_ARB_SAT_LEVEL;\ type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ type OPP_PIPE_CLOCK_EN;\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 072c48188b79..db774b3c3721 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -253,7 +253,6 @@ static void verify_allow_pstate_change_high( unsigned int debug_index = 0x7; unsigned int debug_data; - unsigned int force_allow_pstate = 0x30; unsigned int i; if (forced_pstate_allow) { @@ -261,7 +260,9 @@ static void verify_allow_pstate_change_high( * we verify_allow_pstate_change_high. so disable force * here so we can check status */ - REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, 0); + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 0); forced_pstate_allow = false; } @@ -304,7 +305,9 @@ static void verify_allow_pstate_change_high( /* force pstate allow to prevent system hang * and break to debugger to investigate */ - REG_WRITE(DCHUBBUB_ARB_DRAM_STATE_CNTL, force_allow_pstate); + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 1, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1); forced_pstate_allow = true; if (should_log_hw_state) { -- GitLab From 73fb63e74fb26c12bc847fd28596cc4e088e870b Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Mon, 2 Oct 2017 18:01:36 -0400 Subject: [PATCH 1323/2898] drm/amd/display: reject 3D mode based on static debug flag. Signed-off-by: Charlene Liu Reviewed-by: Krunoslav Kovac Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index defc44393b38..4c47a489c87a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -217,7 +217,7 @@ struct dc_debug { bool force_abm_enable; bool disable_hbup_pg; bool disable_dpp_pg; - bool stereo_support; + bool disable_stereo_support; bool vsr_support; }; struct dc_state; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 1b108ae2e656..f168335e95bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -428,6 +428,7 @@ static const struct dc_debug debug_defaults_drv = { .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .disable_dcc = DCC_ENABLE, .voltage_align_fclk = true, + .disable_stereo_support = true, .vsr_support = true, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 178dadda74f9..1994865d4351 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -499,6 +499,9 @@ static bool tgn10_validate_timing( timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) return false; + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && + tg->ctx->dc->debug.disable_stereo_support) + return false; /* Temporarily blocking interlacing mode until it's supported */ if (timing->flags.INTERLACE == 1) return false; -- GitLab From ff79cbdccea94935ff9d2111458e439e28c86e74 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 2 Oct 2017 13:40:02 -0400 Subject: [PATCH 1324/2898] drm/amd/display: increase pstate wait timeout For linux it takes longer than 40us so increasing it to 200us. Also added debug prints regarding the change Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index db774b3c3721..012ba7c9ca8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -245,8 +245,13 @@ static void verify_allow_pstate_change_high( { /* pstate latency is ~20us so if we wait over 40us and pstate allow * still not asserted, we are probably stuck and going to hang + * + * TODO: Figure out why it takes ~100us on linux + * pstate takes around ~100us on linux. Unknown currently as to + * why it takes that long on linux */ - static unsigned int pstate_wait_timeout_us = 40; + static unsigned int pstate_wait_timeout_us = 200; + static unsigned int pstate_wait_expected_timeout_us = 40; static unsigned int max_sampled_pstate_wait_us; /* data collection */ static bool forced_pstate_allow; /* help with revert wa */ static bool should_log_hw_state; /* prevent hw state log by default */ @@ -293,9 +298,15 @@ static void verify_allow_pstate_change_high( for (i = 0; i < pstate_wait_timeout_us; i++) { debug_data = REG_READ(DCHUBBUB_TEST_DEBUG_DATA); - if (debug_data & (1 << 30)) - return; + if (debug_data & (1 << 30)) { + + if (i > pstate_wait_expected_timeout_us) + dm_logger_write(hws->ctx->logger, LOG_WARNING, + "pstate took longer than expected ~%dus", + i); + return; + } if (max_sampled_pstate_wait_us < i) max_sampled_pstate_wait_us = i; @@ -314,6 +325,9 @@ static void verify_allow_pstate_change_high( dcn10_log_hw_state(hws->ctx->dc); } + dm_logger_write(hws->ctx->logger, LOG_WARNING, + "pstate TEST_DEBUG_DATA: 0x%X", + debug_data); BREAK_TO_DEBUGGER(); } -- GitLab From bac4c5592774fef2503c3204e8f947ce595bfcdf Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 3 Oct 2017 11:11:28 -0400 Subject: [PATCH 1325/2898] drm/amd/display: block video planes >4k on dcn10 Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index f168335e95bf..4dd7c3af51e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1163,6 +1163,14 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } +enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state) +{ + if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN + && plane_state->src_rect.width > 3840) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} static struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = get_dcc_compression_cap @@ -1174,6 +1182,7 @@ static struct resource_funcs dcn10_res_pool_funcs = { .validate_guaranteed = dcn10_validate_guaranteed, .validate_bandwidth = dcn_validate_bandwidth, .acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer, + .validate_plane = dcn10_validate_plane, .add_stream_to_ctx = dcn10_add_stream_to_ctx }; -- GitLab From 8e7095b909dd5451c92dc04420891a578e2f3152 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 3 Oct 2017 12:54:18 -0400 Subject: [PATCH 1326/2898] drm/amd/display: add max_video_width cap to dc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 6 ++---- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c60f53069708..7d750369b78b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2750,11 +2750,9 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) { - struct dc *core_dc = dc; - /* TODO For now validates pixel format only */ - if (core_dc->res_pool->funcs->validate_plane) - return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK; + if (dc->res_pool->funcs->validate_plane) + return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps) == DC_OK; return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4c47a489c87a..5a378cc5daaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -57,6 +57,7 @@ struct dc_caps { uint32_t max_downscale_ratio; uint32_t i2c_speed_in_khz; unsigned int max_cursor_size; + unsigned int max_video_width; bool dcc_const_color; bool dynamic_audio; }; diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index b1cf591b3408..90911258bdb3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -743,7 +743,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state) +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) { if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h index f52cae24ee23..de8fdf438f9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h @@ -16,7 +16,7 @@ struct resource_pool *dce100_create_resource_pool( uint8_t num_virtual_links, struct dc *dc); -enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps); enum dc_status dce100_add_stream_to_ctx( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4dd7c3af51e6..2caad73257e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1163,10 +1163,11 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state) +static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) { if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN - && plane_state->src_rect.width > 3840) + && caps->max_video_width != 0 + && plane_state->src_rect.width > caps->max_video_width) return DC_FAIL_SURFACE_VALIDATE; return DC_OK; @@ -1222,6 +1223,7 @@ static bool construct( /* max pipe num for ASIC before check pipe fuses */ pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_video_width = 3840; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 100; dc->caps.max_cursor_size = 256; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 5230dddc8617..118122d12e2b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -111,7 +111,7 @@ struct resource_funcs { const struct resource_pool *pool, struct dc_stream_state *stream); - enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state); + enum dc_status (*validate_plane)(const struct dc_plane_state *plane_state, struct dc_caps *caps); enum dc_status (*add_stream_to_ctx)( struct dc *dc, -- GitLab From d050f8ed14494ea23c6e10b5893010946ef0f78b Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Fri, 29 Sep 2017 16:36:34 -0400 Subject: [PATCH 1327/2898] drm/amd/display: add dpms state to DC - avoid eDP screen flash 4 times when resume from s3 - improve s3 and boot time Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 39 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++ drivers/gpu/drm/amd/display/dc/dc.h | 5 +++ .../display/dc/dce110/dce110_hw_sequencer.c | 13 +++---- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 11 +++--- 5 files changed, 58 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 09bab93815a3..d963de753e63 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -332,7 +332,16 @@ static void set_dither_option(struct dc_stream_state *stream, { struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; + struct pipe_ctx *pipes; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (link->dc->current_state->res_ctx.pipe_ctx[i].stream == + stream) { + pipes = &link->dc->current_state->res_ctx.pipe_ctx[i]; + break; + } + } memset(¶ms, 0, sizeof(params)); if (!stream) @@ -349,6 +358,31 @@ static void set_dither_option(struct dc_stream_state *stream, opp_program_bit_depth_reduction(pipes->stream_res.opp, ¶ms); } +void set_dpms( + struct dc *dc, + struct dc_stream_state *stream, + bool dpms_off) +{ + struct pipe_ctx *pipe_ctx; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { + pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + break; + } + } + + if (stream->dpms_off != dpms_off) { + stream->dpms_off = dpms_off; + if (dpms_off) + core_link_disable_stream(pipe_ctx, + KEEP_ACQUIRED_RESOURCE); + else + core_link_enable_stream(dc->current_state, pipe_ctx); + } +} + static void allocate_dc_stream_funcs(struct dc *dc) { if (dc->hwss.set_drr != NULL) { @@ -371,6 +405,9 @@ static void allocate_dc_stream_funcs(struct dc *dc) dc->stream_funcs.set_dither_option = set_dither_option; + dc->stream_funcs.set_dpms = + set_dpms; + dc->link_funcs.set_drive_settings = set_drive_settings; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2d59f77fa9a2..72e56fbe4a42 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2321,6 +2321,10 @@ void core_link_enable_stream( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) allocate_mst_payload(pipe_ctx); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + core_dc->hwss.unblank_stream(pipe_ctx, + &pipe_ctx->stream->sink->link->cur_link_settings); } void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5a378cc5daaf..7a5e53ffac2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -133,6 +133,10 @@ struct dc_stream_state_funcs { void (*set_dither_option)(struct dc_stream_state *stream, enum dc_dither_option option); + + void (*set_dpms)(struct dc *dc, + struct dc_stream_state *stream, + bool dpms_off); }; struct link_training_settings; @@ -566,6 +570,7 @@ struct dc_stream_state { int phy_pix_clk; enum signal_type signal; + bool dpms_off; struct dc_stream_status status; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 453d2ffd5c4a..81ebf2b9c71d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1364,12 +1364,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( resource_build_info_frame(pipe_ctx); dce110_update_info_frame(pipe_ctx); if (!pipe_ctx_old->stream) { - core_link_enable_stream(context, pipe_ctx); - - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dce110_unblank_stream(pipe_ctx, - &stream->sink->link->cur_link_settings); + if (!pipe_ctx->stream->dpms_off) + core_link_enable_stream(context, pipe_ctx); } pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; @@ -1879,7 +1875,10 @@ static void dce110_reset_hw_ctx_wrap( pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { struct clock_source *old_clk = pipe_ctx_old->clock_source; - core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); + /* disable already, no need to disable again */ + if (!pipe_ctx->stream->dpms_off) + core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); + pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { dm_error("DC: failed to blank crtc!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 012ba7c9ca8d..494f833208f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1037,12 +1037,11 @@ static void reset_back_end_for_pipe( return; } - /* TODOFPGA break core_link_disable_stream into 2 functions: - * disable_stream and disable_link. disable_link will disable PHYPLL - * which is used by otg. Move disable_link after disable_crtc - */ - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + /* DPMS may already disable */ + if (!pipe_ctx->stream->dpms_off) + core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + } /* by upper caller loop, parent pipe: pipe0, will be reset last. * back end share by all pipes and will be disable only when disable -- GitLab From 067c878a220cbe6198b3cfdc7f372adab4762ad8 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 3 Oct 2017 15:03:49 -0400 Subject: [PATCH 1328/2898] drm/amd/display: Fixed switching mode half screen gamma incorrect. Half screen gamma setting and cursor are incorrect when switching mode through win+p due to wrong programming gamma sequence (In case of bottom pipe, gamma and cursor are programmed before front end programmed, pipe is power gated). change: 1. Cache curor attributes to stream 2. Move set gamma and cursor inside front end programming. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 15 --------------- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 9 ++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 4 +++- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 10 ++++++++++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 17 +++++++++++++++++ 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d963de753e63..92fab09843e4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1269,10 +1269,6 @@ static void commit_planes_for_stream(struct dc *dc, /* Full fe update*/ for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; - struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j]; - bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state; - struct dc_cursor_position position = { 0 }; - if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) continue; @@ -1283,17 +1279,6 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.apply_ctx_for_surface( dc, pipe_ctx->stream, stream_status->plane_count, context); } - - /* TODO: this is a hack w/a for switching from mpo to pipe split */ - dc_stream_set_cursor_position(pipe_ctx->stream, &position); - - if (is_new_pipe_surface) { - dc->hwss.update_plane_addr(dc, pipe_ctx); - dc->hwss.set_input_transfer_func( - pipe_ctx, pipe_ctx->plane_state); - dc->hwss.set_output_transfer_func( - pipe_ctx, pipe_ctx->stream); - } } if (update_type > UPDATE_TYPE_FAST) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index c19b478bcdc7..3dd44bef56eb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -173,7 +173,7 @@ struct dc_stream_status *dc_stream_get_status( * Update the cursor attributes and set cursor surface address */ bool dc_stream_set_cursor_attributes( - const struct dc_stream_state *stream, + struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes) { int i; @@ -189,6 +189,11 @@ bool dc_stream_set_cursor_attributes( return false; } + if (attributes->address.quad_part == 0) { + dm_error("DC: Cursor address is 0!\n"); + return false; + } + core_dc = stream->ctx->dc; res_ctx = &core_dc->current_state->res_ctx; @@ -214,6 +219,8 @@ bool dc_stream_set_cursor_attributes( pipe_ctx->plane_res.xfm, attributes); } + stream->cursor_attributes = *attributes; + return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7a5e53ffac2e..c832d5abbbdf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -574,6 +574,8 @@ struct dc_stream_state { struct dc_stream_status status; + struct dc_cursor_attributes cursor_attributes; + /* from stream struct */ struct kref refcount; }; @@ -1013,7 +1015,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); ******************************************************************************/ /* TODO: Deprecated once we switch to dc_set_cursor_position */ bool dc_stream_set_cursor_attributes( - const struct dc_stream_state *stream, + struct dc_stream_state *stream, const struct dc_cursor_attributes *attributes); bool dc_stream_set_cursor_position( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 81ebf2b9c71d..bf7318246401 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2725,6 +2725,8 @@ static void dce110_program_front_end_for_pipe( struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct xfm_grph_csc_adjustment adjust; struct out_csc_color_matrix tbl_entry; + struct pipe_ctx *cur_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; unsigned int i; memset(&tbl_entry, 0, sizeof(tbl_entry)); @@ -2815,6 +2817,14 @@ static void dce110_program_front_end_for_pipe( &plane_state->tiling_info, plane_state->rotation); + /* Moved programming gamma from dc to hwss */ + if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { + dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->plane_state); + dc->hwss.set_output_transfer_func( + pipe_ctx, pipe_ctx->stream); + } + dm_logger_write(dc->ctx->logger, LOG_SURFACE, "Pipe:%d 0x%x: addr hi:0x%x, " "addr low:0x%x, " diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 494f833208f9..ee63155c1895 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2408,6 +2408,10 @@ static void program_all_pipe_in_tree( } if (pipe_ctx->plane_state != NULL) { + struct dc_cursor_position position = { 0 }; + struct pipe_ctx *cur_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; + dcn10_power_on_fe(dc, pipe_ctx, context); /* temporary dcn1 wa: @@ -2422,6 +2426,19 @@ static void program_all_pipe_in_tree( toggle_watermark_change_req(dc->hwseq); update_dchubp_dpp(dc, pipe_ctx, context); + + /* TODO: this is a hack w/a for switching from mpo to pipe split */ + dc_stream_set_cursor_position(pipe_ctx->stream, &position); + + dc_stream_set_cursor_attributes(pipe_ctx->stream, + &pipe_ctx->stream->cursor_attributes); + + if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) { + dc->hwss.set_input_transfer_func( + pipe_ctx, pipe_ctx->plane_state); + dc->hwss.set_output_transfer_func( + pipe_ctx, pipe_ctx->stream); + } } if (dc->debug.sanity_checks) { -- GitLab From c196cbe065da1c9b5f7683af9cdd0889760151c1 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 3 Oct 2017 16:47:02 -0400 Subject: [PATCH 1329/2898] drm/amd/display: add dpms state to DC follow up Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 92fab09843e4..4cdb855ef855 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -332,7 +332,7 @@ static void set_dither_option(struct dc_stream_state *stream, { struct bit_depth_reduction_params params; struct dc_link *link = stream->status.link; - struct pipe_ctx *pipes; + struct pipe_ctx *pipes = NULL; int i; for (i = 0; i < MAX_PIPES; i++) { @@ -344,7 +344,7 @@ static void set_dither_option(struct dc_stream_state *stream, } memset(¶ms, 0, sizeof(params)); - if (!stream) + if (!pipes) return; if (option > DITHER_OPTION_MAX) return; -- GitLab From 8459f633b65a81979b9b233ed0a91a9fdc98b7bd Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Tue, 3 Oct 2017 18:15:51 -0400 Subject: [PATCH 1330/2898] drm/amd/display: Handle case when stream not found in set_dpms When validate with context fail to add stream to the context, we have a case where set_dpms won't be able to find the stream that need to be disabled. Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4cdb855ef855..fe66c6a21bc3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -363,7 +363,7 @@ void set_dpms( struct dc_stream_state *stream, bool dpms_off) { - struct pipe_ctx *pipe_ctx; + struct pipe_ctx *pipe_ctx = NULL; int i; for (i = 0; i < MAX_PIPES; i++) { @@ -373,6 +373,11 @@ void set_dpms( } } + if (!pipe_ctx) { + ASSERT(0); + return; + } + if (stream->dpms_off != dpms_off) { stream->dpms_off = dpms_off; if (dpms_off) -- GitLab From 410d0b39e2247778db5ead9d40330837fecb7a43 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 2 Oct 2017 15:27:26 -0400 Subject: [PATCH 1331/2898] drm/amd/display: Ignore wrong tautological warning Some of our HW calcs functions compares a var against itself to check for NaN. Gcc isn't fond of it and wrongfully warns about a tautological comparison. Disable this check for dcn_calcs_math.c. Signed-off-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index a095472bf4b5..41ef35995b02 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -5,7 +5,7 @@ CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 -CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 -Wno-tautological-compare BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o -- GitLab From 4e9ba34f7bd54bcf4bf97ecfdd18fa60c152978c Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Tue, 3 Oct 2017 18:19:01 -0400 Subject: [PATCH 1332/2898] drm/amd/display: dal 3.1.04 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c832d5abbbdf..8fa9ef1167fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.03" +#define DC_VER "3.1.04" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- GitLab From 0c63c115f254c1024d0679de859283ae48d2cf1b Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Wed, 4 Oct 2017 16:56:27 -0400 Subject: [PATCH 1333/2898] drm/amd/display: group DCN watermark registers Signed-off-by: Eric Bernstein Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_hwseq.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 9a04b8758888..52506155e361 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -163,23 +163,15 @@ SR(REFCLK_CNTL), \ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ - SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ @@ -207,8 +199,19 @@ MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) +#define HWSEQ_SR_WATERMARK_REG_LIST()\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\ + SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D) + #define HWSEQ_DCN1_REG_LIST()\ HWSEQ_DCN_REG_LIST(), \ + HWSEQ_SR_WATERMARK_REG_LIST(), \ HWSEQ_PIXEL_RATE_REG_LIST(OTG), \ HWSEQ_PHYPLL_REG_LIST(OTG), \ SR(DCHUBBUB_SDPIF_FB_TOP),\ -- GitLab From 8feabd03d34e4555c119e69269dae28f52e0d86c Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Mon, 2 Oct 2017 14:39:42 -0400 Subject: [PATCH 1334/2898] drm/amd/display: rename struct mem_input to hubp for dcn Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + .../gpu/drm/amd/display/dc/core/dc_resource.c | 3 +- .../gpu/drm/amd/display/dc/core/dc_stream.c | 22 ++- .../drm/amd/display/dc/dce/dce_mem_input.c | 3 - .../display/dc/dce110/dce110_hw_sequencer.c | 19 ++- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 88 +++++----- .../amd/display/dc/dcn10/dcn10_mem_input.c | 157 ++++++++---------- .../amd/display/dc/dcn10/dcn10_mem_input.h | 49 +++--- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 26 +-- .../gpu/drm/amd/display/dc/inc/core_types.h | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 105 ++++++++++++ .../gpu/drm/amd/display/dc/inc/hw/mem_input.h | 3 - 13 files changed, 286 insertions(+), 195 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index fd1db8dc2f35..c37f130b0170 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -485,6 +485,7 @@ static void split_stream_across_pipes( secondary_pipe->pipe_idx = pipe_idx; secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index fe66c6a21bc3..4df5bf750257 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -47,6 +47,7 @@ #include "dc_link_ddc.h" #include "dm_helpers.h" #include "mem_input.h" +#include "hubp.h" /******************************************************************************* diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7d750369b78b..4fb4f0068f1b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1024,7 +1024,7 @@ static int acquire_first_split_pipe( memset(pipe_ctx, 0, sizeof(*pipe_ctx)); pipe_ctx->stream_res.tg = pool->timing_generators[i]; - pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->stream_res.opp = pool->opps[i]; @@ -1359,6 +1359,7 @@ static int acquire_first_free_pipe( pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.mi = pool->mis[i]; + pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->stream_res.opp = pool->opps[i]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 3dd44bef56eb..411678736ed4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -200,7 +200,7 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.mi || !pipe_ctx->plane_res.xfm) + if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.xfm) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; @@ -210,10 +210,15 @@ bool dc_stream_set_cursor_attributes( pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( pipe_ctx->plane_res.ipp, attributes); - if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) + if (pipe_ctx->plane_res.hubp != NULL) + pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( + pipe_ctx->plane_res.hubp, attributes); + + if (pipe_ctx->plane_res.mi != NULL) pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( pipe_ctx->plane_res.mi, attributes); + if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( pipe_ctx->plane_res.xfm, attributes); @@ -248,7 +253,7 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; - struct mem_input *mi = pipe_ctx->plane_res.mi; + struct hubp *hubp = pipe_ctx->plane_res.hubp; struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { @@ -260,7 +265,7 @@ bool dc_stream_set_cursor_position( }; if (pipe_ctx->stream != stream || - !pipe_ctx->plane_res.mi || + (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || !pipe_ctx->plane_state || !pipe_ctx->plane_res.xfm) continue; @@ -276,11 +281,12 @@ bool dc_stream_set_cursor_position( if (ipp->funcs->ipp_cursor_set_position != NULL) ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); - if (mi->funcs->set_cursor_attributes != NULL) - mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); + if (hubp != NULL) + hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); + + if (xfm != NULL) + xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, hubp->curs_attr.width); - if (xfm->funcs->set_cursor_attributes != NULL) - xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, mi->curs_attr.width); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 83d9caa4f438..ed301c3b2736 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -685,9 +685,6 @@ void dce_mem_input_construct( dce_mi->regs = regs; dce_mi->shifts = mi_shift; dce_mi->masks = mi_mask; - - dce_mi->base.mpcc_id = 0xf; - dce_mi->base.opp_id = 0xf; } void dce112_mem_input_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index bf7318246401..867a0eb9f2e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1378,15 +1378,14 @@ static enum dc_status apply_single_controller_ctx_to_hw( } /* mst support - use total stream count */ -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) - if (pipe_ctx->plane_res.mi->funcs->allocate_mem_input != NULL) -#endif + if (pipe_ctx->plane_res.mi != NULL) { pipe_ctx->plane_res.mi->funcs->allocate_mem_input( - pipe_ctx->plane_res.mi, - stream->timing.h_total, - stream->timing.v_total, - stream->timing.pix_clk_khz, - context->stream_count); + pipe_ctx->plane_res.mi, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pix_clk_khz, + context->stream_count); + } pipe_ctx->stream->sink->link->psr_enabled = false; @@ -1556,7 +1555,7 @@ static void set_safe_displaymarks( SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; for (i = 0; i < MAX_PIPES; i++) { - if (res_ctx->pipe_ctx[i].stream == NULL) + if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL) continue; res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( @@ -1565,6 +1564,7 @@ static void set_safe_displaymarks( max_marks, max_marks, MAX_WATERMARK); + if (i == underlay_idx) res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( res_ctx->pipe_ctx[i].plane_res.mi, @@ -1572,6 +1572,7 @@ static void set_safe_displaymarks( max_marks, max_marks, MAX_WATERMARK); + } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ee63155c1895..c34dbcd1fba4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -172,10 +172,10 @@ static void dcn10_log_hw_state(struct dc *dc) "min_ttu_vblank \t qos_low_wm \t qos_high_wm \n"); for (i = 0; i < pool->pipe_count; i++) { - struct mem_input *mi = pool->mis[i]; + struct hubp *hubp = pool->hubps[i]; struct dcn_hubp_state s; - dcn10_mem_input_read_state(TO_DCN10_MEM_INPUT(mi), &s); + hubp1_read_state(TO_DCN10_HUBP(hubp), &s); DTN_INFO("[%d]:\t %xh \t %xh \t %d \t %d \t " "%xh \t %xh \t %xh \t " @@ -803,7 +803,7 @@ static void power_on_plane( static void undo_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[0]; + struct hubp *hubp = dc->res_pool->hubps[0]; int pwr_status = 0; REG_GET(DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, &pwr_status); @@ -811,7 +811,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) if (pwr_status == 2) return; - mi->funcs->set_blank(mi, true); + hubp->funcs->set_blank(hubp, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); @@ -824,7 +824,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) static void apply_DEGVIDCN10_253_wa(struct dc *dc) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[0]; + struct hubp *hubp = dc->res_pool->hubps[0]; if (dc->debug.disable_stutter) return; @@ -836,7 +836,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); - mi->funcs->set_hubp_blank_en(mi, false); + hubp->funcs->set_hubp_blank_en(hubp, false); } static void bios_golden_init(struct dc *dc) @@ -1070,7 +1070,7 @@ static void reset_back_end_for_pipe( static void plane_atomic_disconnect(struct dc *dc, int fe_idx) { - struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; int opp_id, z_idx; int mpcc_id = -1; @@ -1094,7 +1094,7 @@ static void plane_atomic_disconnect(struct dc *dc, if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); - mi->funcs->dcc_control(mi, false, false); + hubp->funcs->dcc_control(hubp, false, false); if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -1108,20 +1108,20 @@ static void plane_atomic_disable(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = dc->res_pool->mis[fe_idx]; + struct hubp *hubp = dc->res_pool->hubps[fe_idx]; struct mpc *mpc = dc->res_pool->mpc; - int opp_id = mi->opp_id; + int opp_id = hubp->opp_id; if (opp_id == 0xf) return; - mpc->funcs->wait_for_idle(mpc, mi->mpcc_id); - dc->res_pool->opps[mi->opp_id]->mpcc_disconnect_pending[mi->mpcc_id] = false; + mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id); + dc->res_pool->opps[hubp->opp_id]->mpcc_disconnect_pending[hubp->mpcc_id] = false; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: atomic disable finished on mpcc %d]\n", fe_idx);*/ - mi->funcs->set_blank(mi, true); + hubp->funcs->set_blank(hubp, true); if (dc->debug.sanity_checks) verify_allow_pstate_change_high(dc->hwseq); @@ -1171,7 +1171,7 @@ static void reset_front_end( { struct dce_hwseq *hws = dc->hwseq; struct timing_generator *tg; - int opp_id = dc->res_pool->mis[fe_idx]->opp_id; + int opp_id = dc->res_pool->hubps[fe_idx]->opp_id; /*Already reset*/ if (opp_id == 0xf) @@ -1353,8 +1353,8 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c if (plane_state == NULL) return; addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); - pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr( - pipe_ctx->plane_res.mi, + pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr( + pipe_ctx->plane_res.hubp, &plane_state->address, plane_state->flip_immediate); plane_state->status.requested_address = plane_state->address; @@ -1759,8 +1759,8 @@ static void dcn10_pipe_control_lock( struct pipe_ctx *pipe, bool lock) { - struct mem_input *mi = NULL; - mi = dc->res_pool->mis[pipe->pipe_idx]; + struct hubp *hubp = NULL; + hubp = dc->res_pool->hubps[pipe->pipe_idx]; /* use TG master update lock to lock everything on the TG * therefore only top pipe need to lock */ @@ -2181,7 +2181,7 @@ static void dcn10_get_surface_visual_confirm_color( } } -static void mmhub_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, +static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1, struct vm_system_aperture_param *apt, struct dce_hwseq *hws) { @@ -2206,7 +2206,7 @@ static void mmhub_read_vm_system_aperture_settings(struct dcn10_mem_input *mi, } /* Temporary read settings, future will get values from kmd directly */ -static void mmhub_read_vm_context0_settings(struct dcn10_mem_input *mi, +static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1, struct vm_context0_param *vm0, struct dce_hwseq *hws) { @@ -2250,22 +2250,22 @@ static void mmhub_read_vm_context0_settings(struct dcn10_mem_input *mi, vm0->pte_base.quad_part -= fb_offset.quad_part; } -static void dcn10_program_pte_vm(struct mem_input *mem_input, +static void dcn10_program_pte_vm(struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, enum dc_rotation_angle rotation, struct dce_hwseq *hws) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct vm_system_aperture_param apt = { {{ 0 } } }; struct vm_context0_param vm0 = { { { 0 } } }; - mmhub_read_vm_system_aperture_settings(mi, &apt, hws); - mmhub_read_vm_context0_settings(mi, &vm0, hws); + mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws); + mmhub_read_vm_context0_settings(hubp1, &vm0, hws); - mem_input->funcs->mem_input_set_vm_system_aperture_settings(mem_input, &apt); - mem_input->funcs->mem_input_set_vm_context0_settings(mem_input, &vm0); + hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt); + hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0); } static void update_dchubp_dpp( @@ -2274,7 +2274,7 @@ static void update_dchubp_dpp( struct dc_state *context) { struct dce_hwseq *hws = dc->hwseq; - struct mem_input *mi = pipe_ctx->plane_res.mi; + struct hubp *hubp = pipe_ctx->plane_res.hubp; struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; @@ -2299,8 +2299,8 @@ static void update_dchubp_dpp( */ REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->stream_res.tg->inst); - mi->funcs->mem_input_setup( - mi, + hubp->funcs->hubp_setup( + hubp, &pipe_ctx->dlg_regs, &pipe_ctx->ttu_regs, &pipe_ctx->rq_regs, @@ -2310,7 +2310,7 @@ static void update_dchubp_dpp( if (dc->config.gpu_vm_support) dcn10_program_pte_vm( - pipe_ctx->plane_res.mi, + pipe_ctx->plane_res.hubp, plane_state->format, &plane_state->tiling_info, plane_state->rotation, @@ -2321,7 +2321,7 @@ static void update_dchubp_dpp( plane_state->format, EXPANSION_MODE_ZERO); - mpcc_cfg.dpp_id = mi->inst; + mpcc_cfg.dpp_id = hubp->inst; mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst; mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree); for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe) @@ -2340,15 +2340,15 @@ static void update_dchubp_dpp( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( pipe_ctx->stream->output_color_space) && per_pixel_alpha; - mi->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); - mi->opp_id = mpcc_cfg.opp_id; + hubp->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg); + hubp->opp_id = mpcc_cfg.opp_id; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ pipe_ctx->plane_res.xfm->funcs->transform_set_scaler( pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); - mi->funcs->mem_program_viewport(mi, + hubp->funcs->mem_program_viewport(hubp, &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); /*gamut remap*/ @@ -2358,8 +2358,8 @@ static void update_dchubp_dpp( pipe_ctx->stream->output_color_space, pipe_ctx->stream->csc_color_matrix.matrix); - mi->funcs->mem_input_program_surface_config( - mi, + hubp->funcs->hubp_program_surface_config( + hubp, plane_state->format, &plane_state->tiling_info, &size, @@ -2370,7 +2370,7 @@ static void update_dchubp_dpp( dc->hwss.update_plane_addr(dc, pipe_ctx); if (is_pipe_tree_visible(pipe_ctx)) - mi->funcs->set_blank(mi, false); + hubp->funcs->set_blank(hubp, false); } @@ -2550,7 +2550,7 @@ static void dcn10_apply_ctx_for_surface( */ if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { - if (pipe_ctx->plane_res.mi->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { + if (pipe_ctx->plane_res.hubp->opp_id != 0xf && pipe_ctx->stream_res.tg->inst == be_idx) { dcn10_power_down_fe(dc, pipe_ctx->pipe_idx); /* * power down fe will unlock when calling reset, need @@ -2577,7 +2577,7 @@ static void dcn10_apply_ctx_for_surface( &(old_pipe_ctx->stream_res.opp->mpc_tree), old_pipe_ctx->stream_res.opp->inst, old_pipe_ctx->pipe_idx); - old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true; + old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.hubp->mpcc_id] = true; /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: apply_ctx disconnect pending on mpcc %d]\n", @@ -2861,7 +2861,7 @@ static void dcn10_wait_for_mpcc_disconnect( if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i]) { res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, i); pipe_ctx->stream_res.opp->mpcc_disconnect_pending[i] = false; - res_pool->mis[i]->funcs->set_blank(res_pool->mis[i], true); + res_pool->hubps[i]->funcs->set_blank(res_pool->hubps[i], true); /*dm_logger_write(dc->ctx->logger, LOG_ERROR, "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", i);*/ @@ -2892,11 +2892,11 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) return; plane_state->status.is_flip_pending = - pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending( - pipe_ctx->plane_res.mi); + pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending( + pipe_ctx->plane_res.hubp); - plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address; - if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && + plane_state->status.current_address = pipe_ctx->plane_res.hubp->current_address; + if (pipe_ctx->plane_res.hubp->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && tg->funcs->is_stereo_left_eye) { plane_state->status.is_right_eye = !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c index 2336da54000c..9ee42d9840fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c @@ -29,18 +29,18 @@ #include "basics/conversion.h" #define REG(reg)\ - mi->mi_regs->reg + hubp1->mi_regs->reg #define CTX \ - mi->base.ctx + hubp1->base.ctx #undef FN #define FN(reg_name, field_name) \ - mi->mi_shift->field_name, mi->mi_mask->field_name + hubp1->mi_shift->field_name, hubp1->mi_mask->field_name -void hubp1_set_blank(struct mem_input *mem_input, bool blank) +void hubp1_set_blank(struct hubp *hubp, bool blank) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t blank_en = blank ? 1 : 0; REG_UPDATE_2(DCHUBP_CNTL, @@ -51,24 +51,24 @@ void hubp1_set_blank(struct mem_input *mem_input, bool blank) REG_WAIT(DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, 1, 1, 200); - mem_input->mpcc_id = 0xf; - mem_input->opp_id = 0xf; + hubp->mpcc_id = 0xf; + hubp->opp_id = 0xf; } } -static void hubp1_set_hubp_blank_en(struct mem_input *mem_input, bool blank) +static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); uint32_t blank_en = blank ? 1 : 0; REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, blank_en); } -static void hubp1_vready_workaround(struct mem_input *mem_input, +static void hubp1_vready_workaround(struct hubp *hubp, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { uint32_t value = 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* set HBUBREQ_DEBUG_DB[12] = 1 */ value = REG_READ(HUBPREQ_DEBUG_DB); @@ -88,7 +88,7 @@ static void hubp1_vready_workaround(struct mem_input *mem_input, } void hubp1_program_tiling( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp1, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format) { @@ -108,7 +108,7 @@ void hubp1_program_tiling( } void hubp1_program_size_and_rotation( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp1, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, @@ -170,7 +170,7 @@ void hubp1_program_size_and_rotation( } void hubp1_program_pixel_format( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp1, enum surface_pixel_format format) { uint32_t red_bar = 3; @@ -246,11 +246,11 @@ void hubp1_program_pixel_format( } bool hubp1_program_surface_flip_and_addr( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_plane_address *address, bool flip_immediate) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* program flip type */ REG_SET(DCSURF_FLIP_CONTROL, 0, @@ -387,20 +387,20 @@ bool hubp1_program_surface_flip_and_addr( break; } - mem_input->request_address = *address; + hubp->request_address = *address; if (flip_immediate) - mem_input->current_address = *address; + hubp->current_address = *address; return true; } -void hubp1_dcc_control(struct mem_input *mem_input, bool enable, +void hubp1_dcc_control(struct hubp *hubp, bool enable, bool independent_64b_blks) { uint32_t dcc_en = enable ? 1 : 0; uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_UPDATE_2(DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, dcc_en, @@ -408,7 +408,7 @@ void hubp1_dcc_control(struct mem_input *mem_input, bool enable, } void hubp1_program_surface_config( - struct mem_input *mem_input, + struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -416,20 +416,20 @@ void hubp1_program_surface_config( struct dc_plane_dcc_param *dcc, bool horizontal_mirror) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); - hubp1_dcc_control(mem_input, dcc->enable, dcc->grph.independent_64b_blks); - hubp1_program_tiling(mi, tiling_info, format); + hubp1_dcc_control(hubp, dcc->enable, dcc->grph.independent_64b_blks); + hubp1_program_tiling(hubp1, tiling_info, format); hubp1_program_size_and_rotation( - mi, rotation, format, plane_size, dcc, horizontal_mirror); - hubp1_program_pixel_format(mi, format); + hubp1, rotation, format, plane_size, dcc, horizontal_mirror); + hubp1_program_pixel_format(hubp1, format); } void hubp1_program_requestor( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_rq_regs_st *rq_regs) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_UPDATE(HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address); @@ -460,11 +460,11 @@ void hubp1_program_requestor( void hubp1_program_deadline( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* DLG - Per hubp */ REG_SET_2(BLANK_OFFSET_0, 0, @@ -581,7 +581,7 @@ void hubp1_program_deadline( } static void hubp1_setup( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr, struct _vcs_dpi_display_rq_regs_st *rq_regs, @@ -590,27 +590,15 @@ static void hubp1_setup( /* otg is locked when this func is called. Register are double buffered. * disable the requestors is not needed */ - hubp1_program_requestor(mem_input, rq_regs); - hubp1_program_deadline(mem_input, dlg_attr, ttu_attr); - hubp1_vready_workaround(mem_input, pipe_dest); + hubp1_program_requestor(hubp, rq_regs); + hubp1_program_deadline(hubp, dlg_attr, ttu_attr); + hubp1_vready_workaround(hubp, pipe_dest); } -void hubp1_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns) -{ - /* only for dce - * dcn use only program_watermarks - */ -} - -bool hubp1_is_flip_pending(struct mem_input *mem_input) +bool hubp1_is_flip_pending(struct hubp *hubp) { uint32_t flip_pending = 0; - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct dc_plane_address earliest_inuse_address; REG_GET(DCSURF_FLIP_CONTROL, @@ -625,20 +613,20 @@ bool hubp1_is_flip_pending(struct mem_input *mem_input) if (flip_pending) return true; - if (earliest_inuse_address.grph.addr.quad_part != mem_input->request_address.grph.addr.quad_part) + if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) return true; - mem_input->current_address = mem_input->request_address; + hubp->current_address = hubp->request_address; return false; } uint32_t aperture_default_system = 1; uint32_t context0_default_system; /* = 0;*/ -static void hubp1_set_vm_system_aperture_settings(struct mem_input *mem_input, +static void hubp1_set_vm_system_aperture_settings(struct hubp *hubp, struct vm_system_aperture_param *apt) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); PHYSICAL_ADDRESS_LOC mc_vm_apt_default; PHYSICAL_ADDRESS_LOC mc_vm_apt_low; PHYSICAL_ADDRESS_LOC mc_vm_apt_high; @@ -664,10 +652,10 @@ static void hubp1_set_vm_system_aperture_settings(struct mem_input *mem_input, MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part); } -static void hubp1_set_vm_context0_settings(struct mem_input *mem_input, +static void hubp1_set_vm_context0_settings(struct hubp *hubp, const struct vm_context0_param *vm0) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); /* pte base */ REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0, VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part); @@ -700,11 +688,11 @@ static void hubp1_set_vm_context0_settings(struct mem_input *mem_input, } void min_set_viewport( - struct mem_input *mem_input, + struct hubp *hubp, const struct rect *viewport, const struct rect *viewport_c) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0, PRI_VIEWPORT_WIDTH, viewport->width, @@ -733,7 +721,7 @@ void min_set_viewport( PRI_VIEWPORT_Y_START_C, viewport_c->y); } -void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, +void hubp1_read_state(struct dcn10_hubp *hubp1, struct dcn_hubp_state *s) { REG_GET(DCSURF_SURFACE_CONFIG, @@ -783,7 +771,7 @@ enum cursor_lines_per_chunk { }; static bool ippn10_cursor_program_control( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp1, bool pixel_data_invert, enum dc_cursor_color_format color_format) { @@ -849,15 +837,15 @@ static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk( } void hubp1_cursor_set_attributes( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_cursor_attributes *attr) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch); enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk( attr->width, attr->color_format); - mem_input->curs_attr = *attr; + hubp->curs_attr = *attr; REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part); @@ -871,17 +859,17 @@ void hubp1_cursor_set_attributes( CURSOR_MODE, attr->color_format, CURSOR_PITCH, hw_pitch, CURSOR_LINES_PER_CHUNK, lpc); - ippn10_cursor_program_control(mi, + ippn10_cursor_program_control(hubp1, attr->attribute_flags.bits.INVERT_PIXEL_DATA, attr->color_format); } void hubp1_cursor_set_position( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param) { - struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input); + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; uint32_t cur_en = pos->enable ? 1 : 0; uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; @@ -893,7 +881,7 @@ void hubp1_cursor_set_position( * TODO: Look at combining cursor_set_position() and * cursor_set_attributes() into cursor_update() */ - if (mem_input->curs_attr.address.quad_part == 0) + if (hubp->curs_attr.address.quad_part == 0) return; dst_x_offset *= param->ref_clk_khz; @@ -909,11 +897,11 @@ void hubp1_cursor_set_position( if (src_x_offset >= (int)param->viewport_width) cur_en = 0; /* not visible beyond right edge*/ - if (src_x_offset + (int)mem_input->curs_attr.width < 0) + if (src_x_offset + (int)hubp->curs_attr.width < 0) cur_en = 0; /* not visible beyond left edge*/ if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) - hubp1_cursor_set_attributes(mem_input, &mem_input->curs_attr); + hubp1_cursor_set_attributes(hubp, &hubp->curs_attr); REG_UPDATE(CURSOR_CONTROL, CURSOR_ENABLE, cur_en); @@ -930,16 +918,15 @@ void hubp1_cursor_set_position( /* TODO Handle surface pixel formats other than 4:4:4 */ } -static struct mem_input_funcs dcn10_mem_input_funcs = { - .mem_input_program_display_marks = hubp1_program_display_marks, - .mem_input_program_surface_flip_and_addr = +static struct hubp_funcs dcn10_hubp_funcs = { + .hubp_program_surface_flip_and_addr = hubp1_program_surface_flip_and_addr, - .mem_input_program_surface_config = + .hubp_program_surface_config = hubp1_program_surface_config, - .mem_input_is_flip_pending = hubp1_is_flip_pending, - .mem_input_setup = hubp1_setup, - .mem_input_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, - .mem_input_set_vm_context0_settings = hubp1_set_vm_context0_settings, + .hubp_is_flip_pending = hubp1_is_flip_pending, + .hubp_setup = hubp1_setup, + .hubp_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, + .hubp_set_vm_context0_settings = hubp1_set_vm_context0_settings, .set_blank = hubp1_set_blank, .dcc_control = hubp1_dcc_control, .mem_program_viewport = min_set_viewport, @@ -952,22 +939,22 @@ static struct mem_input_funcs dcn10_mem_input_funcs = { /* Constructor, Destructor */ /*****************************************/ -void dcn10_mem_input_construct( - struct dcn10_mem_input *mi, +void dcn10_hubp_construct( + struct dcn10_hubp *hubp1, struct dc_context *ctx, uint32_t inst, const struct dcn_mi_registers *mi_regs, const struct dcn_mi_shift *mi_shift, const struct dcn_mi_mask *mi_mask) { - mi->base.funcs = &dcn10_mem_input_funcs; - mi->base.ctx = ctx; - mi->mi_regs = mi_regs; - mi->mi_shift = mi_shift; - mi->mi_mask = mi_mask; - mi->base.inst = inst; - mi->base.opp_id = 0xf; - mi->base.mpcc_id = 0xf; + hubp1->base.funcs = &dcn10_hubp_funcs; + hubp1->base.ctx = ctx; + hubp1->mi_regs = mi_regs; + hubp1->mi_shift = mi_shift; + hubp1->mi_mask = mi_mask; + hubp1->base.inst = inst; + hubp1->base.opp_id = 0xf; + hubp1->base.mpcc_id = 0xf; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h index 5c5eed5c95d5..66db453c801b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h @@ -25,10 +25,10 @@ #ifndef __DC_MEM_INPUT_DCN10_H__ #define __DC_MEM_INPUT_DCN10_H__ -#include "mem_input.h" +#include "hubp.h" -#define TO_DCN10_MEM_INPUT(mi)\ - container_of(mi, struct dcn10_mem_input, base) +#define TO_DCN10_HUBP(hubp)\ + container_of(hubp, struct dcn10_hubp, base) #define MI_REG_LIST_DCN(id)\ SRI(DCHUBP_CNTL, HUBP, id),\ @@ -584,15 +584,15 @@ struct dcn_mi_mask { DCN_MI_REG_FIELD_LIST(uint32_t); }; -struct dcn10_mem_input { - struct mem_input base; +struct dcn10_hubp { + struct hubp base; const struct dcn_mi_registers *mi_regs; const struct dcn_mi_shift *mi_shift; const struct dcn_mi_mask *mi_mask; }; void hubp1_program_surface_config( - struct mem_input *mem_input, + struct hubp *hubp, enum surface_pixel_format format, union dc_tiling_info *tiling_info, union plane_size *plane_size, @@ -601,20 +601,20 @@ void hubp1_program_surface_config( bool horizontal_mirror); void hubp1_program_deadline( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_dlg_regs_st *dlg_attr, struct _vcs_dpi_display_ttu_regs_st *ttu_attr); void hubp1_program_requestor( - struct mem_input *mem_input, + struct hubp *hubp, struct _vcs_dpi_display_rq_regs_st *rq_regs); void hubp1_program_pixel_format( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp, enum surface_pixel_format format); void hubp1_program_size_and_rotation( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp, enum dc_rotation_angle rotation, enum surface_pixel_format format, const union plane_size *plane_size, @@ -622,45 +622,38 @@ void hubp1_program_size_and_rotation( bool horizontal_mirror); void hubp1_program_tiling( - struct dcn10_mem_input *mi, + struct dcn10_hubp *hubp, const union dc_tiling_info *info, const enum surface_pixel_format pixel_format); -void hubp1_dcc_control(struct mem_input *mem_input, +void hubp1_dcc_control(struct hubp *hubp, bool enable, bool independent_64b_blks); -void hubp1_program_display_marks( - struct mem_input *mem_input, - struct dce_watermarks nbp, - struct dce_watermarks stutter, - struct dce_watermarks urgent, - uint32_t total_dest_line_time_ns); - bool hubp1_program_surface_flip_and_addr( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_plane_address *address, bool flip_immediate); -bool hubp1_is_flip_pending(struct mem_input *mem_input); +bool hubp1_is_flip_pending(struct hubp *hubp); void hubp1_cursor_set_attributes( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_cursor_attributes *attr); void hubp1_cursor_set_position( - struct mem_input *mem_input, + struct hubp *hubp, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param); -void hubp1_set_blank(struct mem_input *mem_input, bool blank); +void hubp1_set_blank(struct hubp *hubp, bool blank); -void min_set_viewport(struct mem_input *mem_input, +void min_set_viewport(struct hubp *hubp, const struct rect *viewport, const struct rect *viewport_c); -void dcn10_mem_input_construct( - struct dcn10_mem_input *mi, +void dcn10_hubp_construct( + struct dcn10_hubp *hubp1, struct dc_context *ctx, uint32_t inst, const struct dcn_mi_registers *mi_regs, @@ -684,7 +677,7 @@ struct dcn_hubp_state { uint32_t qos_level_low_wm; uint32_t qos_level_high_wm; }; -void dcn10_mem_input_read_state(struct dcn10_mem_input *mi, +void hubp1_read_state(struct dcn10_hubp *hubp1, struct dcn_hubp_state *s); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 2caad73257e0..93edbba762e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -704,9 +704,9 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.ipps[i] != NULL) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - if (pool->base.mis[i] != NULL) { - kfree(TO_DCN10_MEM_INPUT(pool->base.mis[i])); - pool->base.mis[i] = NULL; + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN10_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; } if (pool->base.irqs != NULL) { @@ -753,19 +753,19 @@ static void destruct(struct dcn10_resource_pool *pool) kfree(pool->base.pp_smu); } -static struct mem_input *dcn10_mem_input_create( +static struct hubp *dcn10_hubp_create( struct dc_context *ctx, uint32_t inst) { - struct dcn10_mem_input *mem_inputn10 = - kzalloc(sizeof(struct dcn10_mem_input), GFP_KERNEL); + struct dcn10_hubp *hubp1 = + kzalloc(sizeof(struct dcn10_hubp), GFP_KERNEL); - if (!mem_inputn10) + if (!hubp1) return NULL; - dcn10_mem_input_construct(mem_inputn10, ctx, inst, - &mi_regs[inst], &mi_shift, &mi_mask); - return &mem_inputn10->base; + dcn10_hubp_construct(hubp1, ctx, inst, + &mi_regs[inst], &mi_shift, &mi_mask); + return &hubp1->base; } static void get_pixel_clock_parameters( @@ -918,7 +918,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->stream_res.tg = head_pipe->stream_res.tg; idle_pipe->stream_res.opp = head_pipe->stream_res.opp; - idle_pipe->plane_res.mi = pool->mis[idle_pipe->pipe_idx]; + idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; idle_pipe->plane_res.xfm = pool->transforms[idle_pipe->pipe_idx]; @@ -1357,8 +1357,8 @@ static bool construct( if ((pipe_fuses & (1 << i)) != 0) continue; - pool->base.mis[j] = dcn10_mem_input_create(ctx, i); - if (pool->base.mis[j] == NULL) { + pool->base.hubps[j] = dcn10_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create memory input!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 118122d12e2b..45518c05e846 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -32,6 +32,7 @@ #include "ddc_service_types.h" #include "dc_bios_types.h" #include "mem_input.h" +#include "hubp.h" #if defined(CONFIG_DRM_AMD_DC_DCN1_0) #include "mpc.h" #endif @@ -129,6 +130,7 @@ struct audio_support{ struct resource_pool { struct mem_input *mis[MAX_PIPES]; + struct hubp *hubps[MAX_PIPES]; struct input_pixel_processor *ipps[MAX_PIPES]; struct transform *transforms[MAX_PIPES]; struct output_pixel_processor *opps[MAX_PIPES]; @@ -178,7 +180,7 @@ struct stream_resource { struct plane_resource { struct scaler_data scl_data; - + struct hubp *hubp; struct mem_input *mi; struct input_pixel_processor *ipp; struct transform *xfm; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h new file mode 100644 index 000000000000..0d186be24cf4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -0,0 +1,105 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HUBP_H__ +#define __DAL_HUBP_H__ + +#include "mem_input.h" + +struct hubp { + struct hubp_funcs *funcs; + struct dc_context *ctx; + struct dc_plane_address request_address; + struct dc_plane_address current_address; + int inst; + int opp_id; + int mpcc_id; + struct dc_cursor_attributes curs_attr; +}; + + +struct hubp_funcs { + void (*hubp_setup)( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); + + void (*dcc_control)(struct hubp *hubp, bool enable, + bool independent_64b_blks); + void (*mem_program_viewport)( + struct hubp *hubp, + const struct rect *viewport, + const struct rect *viewport_c); + + bool (*hubp_program_surface_flip_and_addr)( + struct hubp *hubp, + const struct dc_plane_address *address, + bool flip_immediate); + + void (*hubp_program_pte_vm)( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + enum dc_rotation_angle rotation); + + void (*hubp_set_vm_system_aperture_settings)( + struct hubp *hubp, + struct vm_system_aperture_param *apt); + + void (*hubp_set_vm_context0_settings)( + struct hubp *hubp, + const struct vm_context0_param *vm0); + + void (*hubp_program_surface_config)( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + union plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror); + + bool (*hubp_is_flip_pending)(struct hubp *hubp); + + void (*hubp_update_dchub)(struct hubp *hubp, + struct dchub_init_data *dh_data); + + void (*set_blank)(struct hubp *hubp, bool blank); + void (*set_hubp_blank_en)(struct hubp *hubp, bool blank); + + void (*set_cursor_attributes)( + struct hubp *hubp, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct hubp *hubp, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param); + +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 5c8e45ba8f45..3e1e7e6a8792 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -69,10 +69,7 @@ struct mem_input { struct dc_plane_address request_address; struct dc_plane_address current_address; int inst; - int opp_id; - int mpcc_id; struct stutter_modes stutter_mode; - struct dc_cursor_attributes curs_attr; }; struct vm_system_aperture_param { -- GitLab From 81739b7f49bfded3bbd0b29c5213e9bcbea3c58d Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Mon, 2 Oct 2017 15:03:50 -0400 Subject: [PATCH 1335/2898] drm/amd/display: Add DPP capabilities Signed-off-by: Eric Bernstein Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 5 ++ .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 23 +++------- .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 42 ++++++----------- .../gpu/drm/amd/display/dc/inc/hw/transform.h | 46 +++++++++++++++++++ 4 files changed, 72 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 05df3b222945..fb3c78858ebe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -444,6 +444,10 @@ static const struct transform_funcs dcn10_dpp_funcs = { .set_cursor_position = dcn10_set_cursor_position, }; +static struct dpp_caps dcn10_dpp_cap = { + .dscl_data_proc_format = DSCL_DATA_PRCESSING_FIXED_FORMAT, + .dscl_calc_lb_num_partitions = dscl1_calc_lb_num_partitions, +}; /*****************************************/ /* Constructor, Destructor */ @@ -461,6 +465,7 @@ void dcn10_dpp_construct( xfm->base.inst = inst; xfm->base.funcs = &dcn10_dpp_funcs; + xfm->base.caps = &dcn10_dpp_cap; xfm->tf_regs = tf_regs; xfm->tf_shift = tf_shift; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 153aa3c32762..4cf18a500dcd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1264,23 +1264,6 @@ struct dcn10_dpp { bool is_write_to_ram_a_safe; }; - -enum lb_memory_config { - /* Enable all 3 pieces of memory */ - LB_MEMORY_CONFIG_0 = 0, - - /* Enable only the first piece of memory */ - LB_MEMORY_CONFIG_1 = 1, - - /* Enable only the second piece of memory */ - LB_MEMORY_CONFIG_2 = 2, - - /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the - * last piece of chroma memory used for the luma storage - */ - LB_MEMORY_CONFIG_3 = 3 -}; - enum dcn10_input_csc_select { INPUT_CSC_SELECT_BYPASS = 0, INPUT_CSC_SELECT_ICSC, @@ -1292,6 +1275,12 @@ bool is_lb_conf_valid( int num_partitions, int vtaps); +void dscl1_calc_lb_num_partitions( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c); + void ippn10_degamma_ram_select( struct transform *xfm_base, bool use_ram_a); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index c5267e42a2f2..830dbd5d4144 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -31,6 +31,7 @@ #include "dcn10_dpp.h" #include "basics/conversion.h" + #define NUM_PHASES 64 #define HORZ_MAX_TAPS 8 #define VERT_MAX_TAPS 8 @@ -168,11 +169,10 @@ static enum dscl_mode_sel get_dscl_mode( const struct scaler_data *data, bool dbg_always_scale) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); const long long one = dal_fixed31_32_one.value; - if (xfm->tf_mask->PIXEL_DEPTH) { - /* DSCL caps: LB data is fixed format */ + if (xfm_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + /* DSCL is processing data in fixed format */ if (data->format == PIXEL_FORMAT_FP16) return DSCL_MODE_DSCL_BYPASS; } @@ -204,8 +204,8 @@ static void dpp_set_lb( enum lb_memory_config mem_size_config) { /* LB */ - if (xfm->tf_mask->PIXEL_DEPTH) { - /* DSCL caps: LB data is fixed format */ + if (xfm->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + /* DSCL caps: pixel data processed in fixed format */ uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; @@ -400,7 +400,7 @@ static int get_lb_depth_bpc(enum lb_pixel_depth depth) } } -static void dscl1_calc_lb_num_partitions( +void dscl1_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, @@ -458,7 +458,7 @@ bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config dpp10_find_lb_memory_config( +static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, const struct scaler_data *scl_data) { int num_part_y, num_part_c; @@ -466,15 +466,19 @@ static enum lb_memory_config dpp10_find_lb_memory_config( int vtaps_c = scl_data->taps.v_taps_c; int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert); int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); + enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; + + if (xfm->base.ctx->dc->debug.use_max_lb) + return mem_cfg; - dscl1_calc_lb_num_partitions( + xfm->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; - dscl1_calc_lb_num_partitions( + xfm->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -483,7 +487,7 @@ static enum lb_memory_config dpp10_find_lb_memory_config( if (scl_data->format == PIXEL_FORMAT_420BPP8 || scl_data->format == PIXEL_FORMAT_420BPP10) { - dscl1_calc_lb_num_partitions( + xfm->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -491,7 +495,7 @@ static enum lb_memory_config dpp10_find_lb_memory_config( return LB_MEMORY_CONFIG_3; } - dscl1_calc_lb_num_partitions( + xfm->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ @@ -501,22 +505,6 @@ static enum lb_memory_config dpp10_find_lb_memory_config( return LB_MEMORY_CONFIG_0; } -/*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, - const struct scaler_data *scl_data) -{ - enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; - - if (xfm->base.ctx->dc->debug.use_max_lb) - return mem_cfg; - - if (xfm->tf_mask->PIXEL_DEPTH) { - /* DSCL caps: LB data is fixed format */ - mem_cfg = dpp10_find_lb_memory_config(scl_data); - } - return mem_cfg; -} - void dpp_set_scaler_auto_scale( struct transform *xfm_base, const struct scaler_data *scl_data) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index f95621dfd4d4..7c08bc62c1f5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -38,6 +38,7 @@ struct transform { const struct transform_funcs *funcs; struct dc_context *ctx; int inst; + struct dpp_caps *caps; struct pwl_params regamma_params; }; @@ -109,6 +110,22 @@ enum graphics_gamut_adjust_type { GRAPHICS_GAMUT_ADJUST_TYPE_SW /* use adjustments */ }; +enum lb_memory_config { + /* Enable all 3 pieces of memory */ + LB_MEMORY_CONFIG_0 = 0, + + /* Enable only the first piece of memory */ + LB_MEMORY_CONFIG_1 = 1, + + /* Enable only the second piece of memory */ + LB_MEMORY_CONFIG_2 = 2, + + /* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the + * last piece of chroma memory used for the luma storage + */ + LB_MEMORY_CONFIG_3 = 3 +}; + struct xfm_grph_csc_adjustment { struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; enum graphics_gamut_adjust_type gamut_adjust_type; @@ -262,4 +279,33 @@ const uint16_t *get_filter_6tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_7tap_64p(struct fixed31_32 ratio); const uint16_t *get_filter_8tap_64p(struct fixed31_32 ratio); + +/* Defines the pixel processing capability of the DSCL */ +enum dscl_data_processing_format { + DSCL_DATA_PRCESSING_FIXED_FORMAT, /* The DSCL processes pixel data in fixed format */ + DSCL_DATA_PRCESSING_FLOAT_FORMAT, /* The DSCL processes pixel data in float format */ +}; + +/* + * The DPP capabilities structure contains enumerations to specify the + * HW processing features and an associated function pointers to + * provide the function interface that can be overloaded for implementations + * based on different capabilities + */ +struct dpp_caps { + /* DSCL processing pixel data in fixed or float format */ + enum dscl_data_processing_format dscl_data_proc_format; + + /* Calculates the number of partitions in the line buffer. + * The implementation of this function is overloaded for + * different versions of DSCL LB. + */ + void (*dscl_calc_lb_num_partitions)( + const struct scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c); +}; + + #endif -- GitLab From e66a575508b5a11df7a670265c91981e4d735749 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 4 Oct 2017 14:10:16 -0400 Subject: [PATCH 1336/2898] drm/amd/display: Add missing newlines in pstate wait debug messages These were spamming the debugger logs. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index c34dbcd1fba4..059da7882a68 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -302,7 +302,7 @@ static void verify_allow_pstate_change_high( if (i > pstate_wait_expected_timeout_us) dm_logger_write(hws->ctx->logger, LOG_WARNING, - "pstate took longer than expected ~%dus", + "pstate took longer than expected ~%dus\n", i); return; @@ -326,7 +326,7 @@ static void verify_allow_pstate_change_high( } dm_logger_write(hws->ctx->logger, LOG_WARNING, - "pstate TEST_DEBUG_DATA: 0x%X", + "pstate TEST_DEBUG_DATA: 0x%X\n", debug_data); BREAK_TO_DEBUGGER(); } -- GitLab From abb4986eea1670922a0b89ef62688b4b649bd3c6 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 4 Oct 2017 15:55:45 -0400 Subject: [PATCH 1337/2898] drm/amd/display: Fix up plane_states add/remove logic Our plane_states array trimming logic was faulty, we should be starting to shuffle from the plane that was just released, not from the very beginning of the array. Also get rid of a leftover line that was setting the plane state at the stream index to null, leading to issues. Also move the dc_plane_state_retain call to where we reference plane_state, in case we do hit the error case where we can't get a free pipe. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4fb4f0068f1b..c80bde94472f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1073,9 +1073,6 @@ bool dc_add_plane_to_context( return false; } - /* retain new surfaces */ - dc_plane_state_retain(plane_state); - free_pipe = acquire_free_pipe_for_stream(context, pool, stream); #if defined(CONFIG_DRM_AMD_DC_DCN1_0) @@ -1085,11 +1082,11 @@ bool dc_add_plane_to_context( free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; } #endif - if (!free_pipe) { - stream_status->plane_states[i] = NULL; + if (!free_pipe) return false; - } + /* retain new surfaces */ + dc_plane_state_retain(plane_state); free_pipe->plane_state = plane_state; if (head_pipe != free_pipe) { @@ -1181,8 +1178,8 @@ bool dc_remove_plane_from_context( stream_status->plane_count--; - /* Trim back arrays */ - for (i = 0; i < stream_status->plane_count; i++) + /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ + for (; i < stream_status->plane_count; i++) stream_status->plane_states[i] = stream_status->plane_states[i + 1]; stream_status->plane_states[stream_status->plane_count] = NULL; -- GitLab From 179584ef6d9d763f9f17d2fe627c2d801e9a0973 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 5 Oct 2017 14:15:44 -0400 Subject: [PATCH 1338/2898] drm/amd/display: dal 3.1.05 Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8fa9ef1167fa..6e9b21928d4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.04" +#define DC_VER "3.1.05" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- GitLab From 86be9a0495c6b4ca8ec37b652152df947c155848 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 5 Oct 2017 12:30:14 -0400 Subject: [PATCH 1339/2898] drm/amd/display: renaming filename for hubp Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../amd/display/dc/dcn10/{dcn10_mem_input.c => dcn10_hubp.c} | 2 +- .../amd/display/dc/dcn10/{dcn10_mem_input.h => dcn10_hubp.h} | 0 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename drivers/gpu/drm/amd/display/dc/dcn10/{dcn10_mem_input.c => dcn10_hubp.c} (99%) rename drivers/gpu/drm/amd/display/dc/dcn10/{dcn10_mem_input.h => dcn10_hubp.h} (100%) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 6b19106f4679..ebeb88283a14 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -3,7 +3,7 @@ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ - dcn10_mem_input.o dcn10_mpc.o \ + dcn10_hubp.o dcn10_mpc.o \ dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c rename to drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index 9ee42d9840fb..b13dee64e0ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -24,9 +24,9 @@ */ #include "dm_services.h" #include "dce_calcs.h" -#include "dcn10_mem_input.h" #include "reg_helper.h" #include "basics/conversion.h" +#include "dcn10_hubp.h" #define REG(reg)\ hubp1->mi_regs->reg diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h similarity index 100% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mem_input.h rename to drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 059da7882a68..6b866b169985 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -31,7 +31,6 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce/dce_hwseq.h" #include "abm.h" -#include "dcn10/dcn10_mem_input.h" #include "dcn10/dcn10_timing_generator.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" @@ -41,6 +40,7 @@ #include "mpc.h" #include "reg_helper.h" #include "custom_float.h" +#include "dcn10_hubp.h" #define CTX \ hws->ctx diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 93edbba762e8..1da5105ed30a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -42,12 +42,12 @@ #include "dce/dce_stream_encoder.h" #include "dce/dce_clocks.h" #include "dce/dce_clock_source.h" -#include "dcn10/dcn10_mem_input.h" #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" #include "../virtual/virtual_stream_encoder.h" #include "dce110/dce110_resource.h" #include "dce112/dce112_resource.h" +#include "dcn10_hubp.h" #include "vega10/soc15ip.h" -- GitLab From 2938bbb646107d4e39bf850a5bc09385abd012e8 Mon Sep 17 00:00:00 2001 From: SivapiriyanKumarasamy Date: Wed, 4 Oct 2017 14:24:53 -0400 Subject: [PATCH 1340/2898] drm/amd/display: Pull transfer func defines into DC Signed-off-by: SivapiriyanKumarasamy Reviewed-by: Anthony Koo Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6e9b21928d4f..c7b31adc736e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -318,6 +318,38 @@ enum { TRANSFER_FUNC_POINTS = 1025 }; +// Moved here from color module for linux +enum color_transfer_func { + transfer_func_unknown, + transfer_func_srgb, + transfer_func_bt709, + transfer_func_pq2084, + transfer_func_pq2084_interim, + transfer_func_linear_0_1, + transfer_func_linear_0_125, + transfer_func_dolbyvision, + transfer_func_gamma_22, + transfer_func_gamma_26 +}; + +enum color_color_space { + color_space_unsupported, + color_space_srgb, + color_space_bt601, + color_space_bt709, + color_space_xv_ycc_bt601, + color_space_xv_ycc_bt709, + color_space_xr_rgb, + color_space_bt2020, + color_space_adobe, + color_space_dci_p3, + color_space_sc_rgb_ms_ref, + color_space_display_native, + color_space_app_ctrl, + color_space_dolby_vision, + color_space_custom_coordinates +}; + struct dc_hdr_static_metadata { /* display chromaticities and white point in units of 0.00001 */ unsigned int chromaticity_green_x; @@ -398,6 +430,12 @@ struct dc_plane_state { struct dc_gamma *gamma_correction; struct dc_transfer_func *in_transfer_func; + // sourceContentAttribute cache + bool is_source_input_valid; + struct dc_hdr_static_metadata source_input_mastering_info; + enum color_color_space source_input_color_space; + enum color_transfer_func source_input_tf; + enum dc_color_space color_space; enum surface_pixel_format format; enum dc_rotation_angle rotation; -- GitLab From 80e80ec817f161560b4159608fb41bd289abede3 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 3 Oct 2017 13:53:51 -0400 Subject: [PATCH 1341/2898] drm/amd/display: Fix underscan not using proper scaling fix underscan not being set correctly Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4df5bf750257..12aeb6d83f42 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1362,7 +1362,7 @@ void dc_commit_updates_for_stream(struct dc *dc, enum surface_update_type update_type; struct dc_state *context; struct dc_context *dc_ctx = dc->ctx; - int i; + int i, j; stream_status = dc_stream_get_status(stream); context = dc->current_state; @@ -1396,8 +1396,17 @@ void dc_commit_updates_for_stream(struct dc *dc, if (srf_updates[i].flip_addr) surface->address = srf_updates[i].flip_addr->address; - } + if (update_type >= UPDATE_TYPE_MED) { + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (pipe_ctx->plane_state != surface) + continue; + resource_build_scaling_params(pipe_ctx); + } + } + } commit_planes_for_stream( dc, -- GitLab From 8534575fed085a78a847f88fbc929d9c4a8c3255 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Thu, 5 Oct 2017 14:27:27 -0400 Subject: [PATCH 1342/2898] drm/amd/display: Expose some MPC functions for reuse Signed-off-by: Eric Bernstein Reviewed-by: Eric Bernstein Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 11 +++-- .../gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 45 ++++++++++++++----- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 6 ++- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 7 +-- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index 334f072cea1d..76573e1f5b01 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -65,7 +65,7 @@ static void mpc10_set_bg_color( MPCC_BG_B_CB, bg_b_cb); } -static void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) +void mpc10_assert_idle_mpcc(struct mpc *mpc, int id) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); @@ -116,7 +116,7 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i } } -static void mpc10_mpcc_remove( +void mpc10_mpcc_remove( struct mpc *mpc, struct mpc_tree_cfg *tree_cfg, int opp_id, @@ -265,7 +265,7 @@ static void mpc10_add_to_tree_cfg( tree_cfg->num_pipes++; } -static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) +int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) { struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc); int mpcc_id, z_idx; @@ -313,7 +313,7 @@ static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg) return mpcc_id; } -static void mpc10_update_blend_mode( +void mpc10_update_blend_mode( struct mpc *mpc, struct mpcc_cfg *cfg) { @@ -339,8 +339,7 @@ const struct mpc_funcs dcn10_mpc_funcs = { .add = mpc10_mpcc_add, .remove = mpc10_mpcc_remove, .wait_for_idle = mpc10_assert_idle_mpcc, - .set_denorm = NULL, - .update_blend_mode = mpc10_update_blend_mode + .update_blend_mode = mpc10_update_blend_mode, }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 94f890a0ad40..683ce4aaa76e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h @@ -34,7 +34,6 @@ #define MAX_OPP 6 #define MPC_COMMON_REG_LIST_DCN1_0(inst) \ - SRII(MUX, MPC_OUT, inst),\ SRII(MPCC_TOP_SEL, MPCC, inst),\ SRII(MPCC_BOT_SEL, MPCC, inst),\ SRII(MPCC_CONTROL, MPCC, inst),\ @@ -45,17 +44,19 @@ SRII(MPCC_BG_B_CB, MPCC, inst),\ SRII(MPCC_BG_B_CB, MPCC, inst) -struct dcn_mpc_registers { - uint32_t MPCC_TOP_SEL[MAX_MPCC]; - uint32_t MPCC_BOT_SEL[MAX_MPCC]; - uint32_t MPCC_CONTROL[MAX_MPCC]; - uint32_t MPCC_STATUS[MAX_MPCC]; - uint32_t MPCC_OPP_ID[MAX_MPCC]; - uint32_t MPCC_BG_G_Y[MAX_MPCC]; - uint32_t MPCC_BG_R_CR[MAX_MPCC]; - uint32_t MPCC_BG_B_CB[MAX_MPCC]; +#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst) \ + SRII(MUX, MPC_OUT, inst) + +#define MPC_COMMON_REG_VARIABLE_LIST \ + uint32_t MPCC_TOP_SEL[MAX_MPCC]; \ + uint32_t MPCC_BOT_SEL[MAX_MPCC]; \ + uint32_t MPCC_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_STATUS[MAX_MPCC]; \ + uint32_t MPCC_OPP_ID[MAX_MPCC]; \ + uint32_t MPCC_BG_G_Y[MAX_MPCC]; \ + uint32_t MPCC_BG_R_CR[MAX_MPCC]; \ + uint32_t MPCC_BG_B_CB[MAX_MPCC]; \ uint32_t MUX[MAX_OPP]; -}; #define MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\ @@ -87,6 +88,10 @@ struct dcn_mpc_registers { type MPCC_BG_B_CB;\ type MPC_OUT_MUX; +struct dcn_mpc_registers { + MPC_COMMON_REG_VARIABLE_LIST +}; + struct dcn_mpc_shift { MPC_REG_FIELD_LIST(uint8_t) }; @@ -112,4 +117,22 @@ void dcn10_mpc_construct(struct dcn10_mpc *mpcc10, const struct dcn_mpc_mask *mpc_mask, int num_mpcc); +int mpc10_mpcc_add( + struct mpc *mpc, + struct mpcc_cfg *cfg); + +void mpc10_mpcc_remove( + struct mpc *mpc, + struct mpc_tree_cfg *tree_cfg, + int opp_id, + int dpp_id); + +void mpc10_assert_idle_mpcc( + struct mpc *mpc, + int id); + +void mpc10_update_blend_mode( + struct mpc *mpc, + struct mpcc_cfg *cfg); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 1da5105ed30a..4764590f9097 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -329,7 +329,11 @@ static const struct dcn_mpc_registers mpc_regs = { MPC_COMMON_REG_LIST_DCN1_0(0), MPC_COMMON_REG_LIST_DCN1_0(1), MPC_COMMON_REG_LIST_DCN1_0(2), - MPC_COMMON_REG_LIST_DCN1_0(3) + MPC_COMMON_REG_LIST_DCN1_0(3), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(0), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(1), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(2), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(3) }; static const struct dcn_mpc_shift mpc_shift = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index fb590f5353a0..d4188b2c0626 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -46,15 +46,16 @@ struct mpc { struct mpc_funcs { int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg); + void (*remove)(struct mpc *mpc, struct mpc_tree_cfg *tree_cfg, int opp_id, int mpcc_inst); + void (*wait_for_idle)(struct mpc *mpc, int id); - void (*set_denorm)(struct mpc *mpc, - int opp_id, - enum dc_color_depth output_depth); + void (*update_blend_mode)(struct mpc *mpc, struct mpcc_cfg *cfg); + }; #endif -- GitLab From be5a55dc3de9bc5764b3eb4ba6f743783584aa58 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 5 Oct 2017 13:32:29 -0400 Subject: [PATCH 1343/2898] drm/amd/display: change when to set tap_hardcode_coeff Set hardcode_coeff only when BOTH chroma and luma taps are more than 1 without this underscan with h or v set to 0 darkens the screen (either h or v set to 0, not both) Signed-off-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 830dbd5d4144..eda6c8010fb8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -306,10 +306,10 @@ static void dpp_set_scl_filter( h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3 && scl_data->taps.h_taps_c < 3 - && (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1); + && (scl_data->taps.h_taps > 1 && scl_data->taps.h_taps_c > 1); v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3 && scl_data->taps.v_taps_c < 3 - && (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1); + && (scl_data->taps.v_taps > 1 && scl_data->taps.v_taps_c > 1); h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0; v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0; -- GitLab From 3411eac1a144ac5ad5a7ab994645724130bb2996 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Thu, 5 Oct 2017 10:45:50 -0500 Subject: [PATCH 1344/2898] drm/amd/display: [RV] bug in cm programming When surface bigger then 10 bpc the output pixel does not match to the required value.Update CRC's. Signed-off-by: Vitaly Prosyak Reviewed-by: Jordan Lazare Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 6 +++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index 4cf18a500dcd..c2e3ff883537 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -164,7 +164,8 @@ SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ - SRI(CURSOR_CONTROL, CURSOR, id) + SRI(CURSOR_CONTROL, CURSOR, id), \ + SRI(CM_CMOUT_CONTROL, CM, id) #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ @@ -401,6 +402,7 @@ TF_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ TF_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ TF_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh), \ + TF_SF(CM0_CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ @@ -549,6 +551,7 @@ type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_RGAM_LUT_MODE; \ + type CM_CMOUT_ROUND_TRUNC_MODE; \ type OBUF_BYPASS; \ type OBUF_H_2X_UPSCALE_EN; \ type CM_BLNDGAM_LUT_MODE; \ @@ -1081,6 +1084,7 @@ struct dcn_dpp_registers { uint32_t CM_RGAM_RAMA_REGION_0_1; uint32_t CM_RGAM_RAMA_REGION_32_33; uint32_t CM_RGAM_CONTROL; + uint32_t CM_CMOUT_CONTROL; uint32_t OBUF_CONTROL; uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; uint32_t CM_BLNDGAM_CONTROL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 61e2a8919e9c..f88fd2e2e0aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -602,7 +602,7 @@ static void ippn10_enable_cm_block( struct transform *xfm_base) { struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - + REG_UPDATE(CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, 8); REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } -- GitLab From 886daac91d4c794fa76a0e5cf1101bdb329f3fe3 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Thu, 5 Oct 2017 15:37:46 -0400 Subject: [PATCH 1345/2898] drm/amd/display: Fix a logic defect in cursor move Regression caused by: Ib98354194d7 Need to check crtc->stream before updating cursor attributes and position. Signed-off-by: Jerry Zuo Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8653453566b8..17fb636648f4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3736,14 +3736,15 @@ static void handle_cursor_update(struct drm_plane *plane, attributes.pitch = attributes.width; - if (!dc_stream_set_cursor_attributes(crtc_state->stream, - &attributes)) - DRM_ERROR("DC failed to set cursor attributes\n"); + if (crtc_state->stream) { + if (!dc_stream_set_cursor_attributes(crtc_state->stream, + &attributes)) + DRM_ERROR("DC failed to set cursor attributes\n"); - if (crtc_state->stream) if (!dc_stream_set_cursor_position(crtc_state->stream, &position)) DRM_ERROR("DC failed to set cursor position\n"); + } } static void prepare_flip_isr(struct amdgpu_crtc *acrtc) -- GitLab From e6f4f9cfde0f586c276190f541ecfc80d9b688bc Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Thu, 5 Oct 2017 16:00:29 -0400 Subject: [PATCH 1346/2898] drm/amd/display: fix null dereference in reset hw ctx Signed-off-by: Eric Yang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 867a0eb9f2e0..5e5763c0ee94 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1877,7 +1877,7 @@ static void dce110_reset_hw_ctx_wrap( struct clock_source *old_clk = pipe_ctx_old->clock_source; /* disable already, no need to disable again */ - if (!pipe_ctx->stream->dpms_off) + if (pipe_ctx->stream && !pipe_ctx->stream->dpms_off) core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); -- GitLab From 39a4e6608f28586dee77daf8dc3af53e7829d2a8 Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 5 Oct 2017 17:57:35 -0400 Subject: [PATCH 1347/2898] drm/amd/display: add null check for cursor functions Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 411678736ed4..10421ea31373 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -210,11 +210,13 @@ bool dc_stream_set_cursor_attributes( pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( pipe_ctx->plane_res.ipp, attributes); - if (pipe_ctx->plane_res.hubp != NULL) + if (pipe_ctx->plane_res.hubp != NULL && + pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( pipe_ctx->plane_res.hubp, attributes); - if (pipe_ctx->plane_res.mi != NULL) + if (pipe_ctx->plane_res.mi != NULL && + pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( pipe_ctx->plane_res.mi, attributes); @@ -253,6 +255,7 @@ bool dc_stream_set_cursor_position( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; + struct mem_input *mi = pipe_ctx->plane_res.mi; struct hubp *hubp = pipe_ctx->plane_res.hubp; struct transform *xfm = pipe_ctx->plane_res.xfm; struct dc_cursor_position pos_cpy = *position; @@ -281,10 +284,13 @@ bool dc_stream_set_cursor_position( if (ipp->funcs->ipp_cursor_set_position != NULL) ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); - if (hubp != NULL) + if (mi != NULL && mi->funcs->set_cursor_position != NULL) + mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); + + if (hubp != NULL && hubp->funcs->set_cursor_position != NULL) hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); - if (xfm != NULL) + if (xfm != NULL && xfm->funcs->set_cursor_position != NULL) xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, hubp->curs_attr.width); } -- GitLab From d94585a06b8197a723787c6c5502872abcff0e8e Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Thu, 5 Oct 2017 16:47:49 -0400 Subject: [PATCH 1348/2898] drm/amd/display: rename transform to dpp for dcn Signed-off-by: Yue Hin Lau Reviewed-by: Eric Bernstein Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 1 + drivers/gpu/drm/amd/display/dc/core/dc.c | 1 + .../gpu/drm/amd/display/dc/core/dc_resource.c | 16 +- .../gpu/drm/amd/display/dc/core/dc_stream.c | 16 +- .../gpu/drm/amd/display/dc/core/dc_surface.c | 1 + .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 144 +++++----- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 94 +++---- .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 261 +++++++++--------- .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 104 +++---- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 59 ++-- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 22 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 + drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 134 +++++++++ 13 files changed, 509 insertions(+), 347 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index c37f130b0170..cf0c1459f546 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -488,6 +488,7 @@ static void split_stream_across_pipes( secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx]; if (primary_pipe->bottom_pipe) { ASSERT(primary_pipe->bottom_pipe != secondary_pipe); secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 12aeb6d83f42..80ddccc2570a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -38,6 +38,7 @@ #include "bios_parser_interface.h" #include "include/irq_service_interface.h" #include "transform.h" +#include "dpp.h" #include "timing_generator.h" #include "virtual/virtual_link_encoder.h" diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c80bde94472f..303d7ec684d9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -31,6 +31,7 @@ #include "opp.h" #include "timing_generator.h" #include "transform.h" +#include "dpp.h" #include "core_types.h" #include "set_mode_types.h" #include "virtual/virtual_stream_encoder.h" @@ -853,8 +854,13 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; /* Taps calculations */ - res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( - pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + if (pipe_ctx->plane_res.xfm != NULL) + res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( + pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + + if (pipe_ctx->plane_res.dpp != NULL) + res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); if (!res) { /* Try 24 bpp linebuffer */ @@ -862,6 +868,9 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); + + res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); } if (res) @@ -1026,7 +1035,7 @@ static int acquire_first_split_pipe( pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; - pipe_ctx->plane_res.xfm = pool->transforms[i]; + pipe_ctx->plane_res.dpp = pool->dpps[i]; pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->pipe_idx = i; @@ -1359,6 +1368,7 @@ static int acquire_first_free_pipe( pipe_ctx->plane_res.hubp = pool->hubps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.xfm = pool->transforms[i]; + pipe_ctx->plane_res.dpp = pool->dpps[i]; pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->pipe_idx = i; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 10421ea31373..97f040a25820 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -200,7 +200,7 @@ bool dc_stream_set_cursor_attributes( for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; - if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.xfm) + if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) continue; if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) continue; @@ -221,9 +221,15 @@ bool dc_stream_set_cursor_attributes( pipe_ctx->plane_res.mi, attributes); - if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) + if (pipe_ctx->plane_res.xfm != NULL && + pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( pipe_ctx->plane_res.xfm, attributes); + + if (pipe_ctx->plane_res.dpp != NULL && + pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL) + pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( + pipe_ctx->plane_res.dpp, attributes); } stream->cursor_attributes = *attributes; @@ -258,6 +264,7 @@ bool dc_stream_set_cursor_position( struct mem_input *mi = pipe_ctx->plane_res.mi; struct hubp *hubp = pipe_ctx->plane_res.hubp; struct transform *xfm = pipe_ctx->plane_res.xfm; + struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_cursor_position pos_cpy = *position; struct dc_cursor_mi_param param = { .pixel_clk_khz = stream->timing.pix_clk_khz, @@ -270,7 +277,7 @@ bool dc_stream_set_cursor_position( if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || !pipe_ctx->plane_state || - !pipe_ctx->plane_res.xfm) + (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp)) continue; if (pipe_ctx->plane_state->address.type @@ -293,6 +300,9 @@ bool dc_stream_set_cursor_position( if (xfm != NULL && xfm->funcs->set_cursor_position != NULL) xfm->funcs->set_cursor_position(xfm, &pos_cpy, ¶m, hubp->curs_attr.width); + if (dpp != NULL && dpp->funcs->set_cursor_position != NULL) + dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width); + } return true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index d43783a45ab6..5aa2270f36fd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -30,6 +30,7 @@ /* DC core (private) */ #include "core_types.h" #include "transform.h" +#include "dpp.h" /******************************************************************************* * Private functions diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index fb3c78858ebe..5960e491159d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -39,14 +39,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name enum pixel_format_description { PIXEL_FORMAT_FIXED = 0, @@ -99,7 +99,7 @@ enum gamut_remap_select { }; /* Program gamut remap in bypass mode */ -void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) +void dpp_set_gamut_remap_bypass(struct dcn10_dpp *dpp) { REG_SET(CM_GAMUT_REMAP_CONTROL, 0, CM_GAMUT_REMAP_MODE, 0); @@ -110,7 +110,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) bool dpp_get_optimal_number_of_taps( - struct transform *xfm, + struct dpp *dpp, struct scaler_data *scl_data, const struct scaling_taps *in_taps) { @@ -154,7 +154,7 @@ bool dpp_get_optimal_number_of_taps( else scl_data->taps.h_taps_c = in_taps->h_taps_c; - if (!xfm->ctx->dc->debug.always_scale) { + if (!dpp->ctx->dc->debug.always_scale) { if (IDENTITY_RATIO(scl_data->ratios.horz)) scl_data->taps.h_taps = 1; if (IDENTITY_RATIO(scl_data->ratios.vert)) @@ -169,14 +169,14 @@ bool dpp_get_optimal_number_of_taps( return true; } -void dpp_reset(struct transform *xfm_base) +void dpp_reset(struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - xfm->filter_h_c = NULL; - xfm->filter_v_c = NULL; - xfm->filter_h = NULL; - xfm->filter_v = NULL; + dpp->filter_h_c = NULL; + dpp->filter_v_c = NULL; + dpp->filter_h = NULL; + dpp->filter_v = NULL; /* set boundary mode to 0 */ REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); @@ -184,28 +184,28 @@ void dpp_reset(struct transform *xfm_base) -static void dcn10_dpp_cm_set_regamma_pwl( - struct transform *xfm_base, const struct pwl_params *params) +static void dpp1_cm_set_regamma_pwl( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - dcn10_dpp_cm_power_on_regamma_lut(xfm_base, true); - dcn10_dpp_cm_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); + dpp1_cm_power_on_regamma_lut(dpp_base, true); + dpp1_cm_configure_regamma_lut(dpp_base, dpp->is_write_to_ram_a_safe); - if (xfm->is_write_to_ram_a_safe) - dcn10_dpp_cm_program_regamma_luta_settings(xfm_base, params); + if (dpp->is_write_to_ram_a_safe) + dpp1_cm_program_regamma_luta_settings(dpp_base, params); else - dcn10_dpp_cm_program_regamma_lutb_settings(xfm_base, params); + dpp1_cm_program_regamma_lutb_settings(dpp_base, params); - dcn10_dpp_cm_program_regamma_lut( - xfm_base, params->rgb_resulted, params->hw_points_num); + dpp1_cm_program_regamma_lut( + dpp_base, params->rgb_resulted, params->hw_points_num); } -static void dcn10_dpp_cm_set_regamma_mode( - struct transform *xfm_base, +static void dpp1_cm_set_regamma_mode( + struct dpp *dpp_base, enum opp_regamma mode) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); uint32_t re_mode = 0; uint32_t obuf_bypass = 0; /* need for pipe split */ uint32_t obuf_hupscale = 0; @@ -221,8 +221,8 @@ static void dcn10_dpp_cm_set_regamma_mode( re_mode = 2; break; case OPP_REGAMMA_USER: - re_mode = xfm->is_write_to_ram_a_safe ? 3 : 4; - xfm->is_write_to_ram_a_safe = !xfm->is_write_to_ram_a_safe; + re_mode = dpp->is_write_to_ram_a_safe ? 3 : 4; + dpp->is_write_to_ram_a_safe = !dpp->is_write_to_ram_a_safe; break; default: break; @@ -234,7 +234,7 @@ static void dcn10_dpp_cm_set_regamma_mode( OBUF_H_2X_UPSCALE_EN, obuf_hupscale); } -static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ +static void dpp1_setup_format_flags(enum surface_pixel_format input_format,\ enum pixel_format_description *fmt) { @@ -247,11 +247,11 @@ static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ *fmt = PIXEL_FORMAT_FIXED; } -static void ippn10_set_degamma_format_float( - struct transform *xfm_base, +static void dpp1_set_degamma_format_float( + struct dpp *dpp_base, bool is_float) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (is_float) { REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); @@ -262,8 +262,8 @@ static void ippn10_set_degamma_format_float( } } -void ippn10_cnv_setup ( - struct transform *xfm_base, +void dpp1_cnv_setup ( + struct dpp *dpp_base, enum surface_pixel_format input_format, enum expansion_mode mode) { @@ -273,10 +273,10 @@ void ippn10_cnv_setup ( enum dc_color_space color_space; enum dcn10_input_csc_select select; bool is_float; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); bool force_disable_cursor = false; - ippn10_setup_format_flags(input_format, &fmt); + dpp1_setup_format_flags(input_format, &fmt); alpha_en = 1; pixel_format = 0; color_space = COLOR_SPACE_SRGB; @@ -304,7 +304,7 @@ void ippn10_cnv_setup ( break; } - ippn10_set_degamma_format_float(xfm_base, is_float); + dpp1_set_degamma_format_float(dpp_base, is_float); switch (input_format) { case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: @@ -362,7 +362,7 @@ void ippn10_cnv_setup ( CNVC_SURFACE_PIXEL_FORMAT, pixel_format); REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); - ippn10_program_input_csc(xfm_base, color_space, select); + dpp1_program_input_csc(dpp_base, color_space, select); if (force_disable_cursor) { REG_UPDATE(CURSOR_CONTROL, @@ -373,10 +373,10 @@ void ippn10_cnv_setup ( } void dcn10_set_cursor_attributes( - struct transform *xfm_base, + struct dpp *dpp_base, const struct dc_cursor_attributes *attr) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); enum dc_cursor_color_format color_format = attr->color_format; REG_UPDATE_2(CURSOR0_CONTROL, @@ -401,12 +401,12 @@ void dcn10_set_cursor_attributes( void dcn10_set_cursor_position( - struct transform *xfm_base, + struct dpp *dpp_base, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param, uint32_t width) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start; uint32_t cur_en = pos->enable ? 1 : 0; @@ -421,25 +421,25 @@ void dcn10_set_cursor_position( } -static const struct transform_funcs dcn10_dpp_funcs = { - .transform_reset = dpp_reset, - .transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, - .transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, - .transform_set_gamut_remap = dcn10_dpp_cm_set_gamut_remap, - .opp_set_csc_adjustment = dcn10_dpp_cm_set_output_csc_adjustment, - .opp_set_csc_default = dcn10_dpp_cm_set_output_csc_default, - .opp_power_on_regamma_lut = dcn10_dpp_cm_power_on_regamma_lut, - .opp_program_regamma_lut = dcn10_dpp_cm_program_regamma_lut, - .opp_configure_regamma_lut = dcn10_dpp_cm_configure_regamma_lut, - .opp_program_regamma_lutb_settings = dcn10_dpp_cm_program_regamma_lutb_settings, - .opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings, - .opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl, - .opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode, - .ipp_set_degamma = ippn10_set_degamma, - .ipp_program_input_lut = ippn10_program_input_lut, - .ipp_program_degamma_pwl = ippn10_set_degamma_pwl, - .ipp_setup = ippn10_cnv_setup, - .ipp_full_bypass = ippn10_full_bypass, +static const struct dpp_funcs dcn10_dpp_funcs = { + .dpp_reset = dpp_reset, + .dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale, + .dpp_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, + .dpp_set_gamut_remap = dpp1_cm_set_gamut_remap, + .opp_set_csc_adjustment = dpp1_cm_set_output_csc_adjustment, + .opp_set_csc_default = dpp1_cm_set_output_csc_default, + .opp_power_on_regamma_lut = dpp1_cm_power_on_regamma_lut, + .opp_program_regamma_lut = dpp1_cm_program_regamma_lut, + .opp_configure_regamma_lut = dpp1_cm_configure_regamma_lut, + .opp_program_regamma_lutb_settings = dpp1_cm_program_regamma_lutb_settings, + .opp_program_regamma_luta_settings = dpp1_cm_program_regamma_luta_settings, + .opp_program_regamma_pwl = dpp1_cm_set_regamma_pwl, + .opp_set_regamma_mode = dpp1_cm_set_regamma_mode, + .ipp_set_degamma = dpp1_set_degamma, + .ipp_program_input_lut = dpp1_program_input_lut, + .ipp_program_degamma_pwl = dpp1_set_degamma_pwl, + .ipp_setup = dpp1_cnv_setup, + .ipp_full_bypass = dpp1_full_bypass, .set_cursor_attributes = dcn10_set_cursor_attributes, .set_cursor_position = dcn10_set_cursor_position, }; @@ -453,29 +453,29 @@ static struct dpp_caps dcn10_dpp_cap = { /* Constructor, Destructor */ /*****************************************/ -void dcn10_dpp_construct( - struct dcn10_dpp *xfm, +void dpp1_construct( + struct dcn10_dpp *dpp, struct dc_context *ctx, uint32_t inst, const struct dcn_dpp_registers *tf_regs, const struct dcn_dpp_shift *tf_shift, const struct dcn_dpp_mask *tf_mask) { - xfm->base.ctx = ctx; + dpp->base.ctx = ctx; - xfm->base.inst = inst; - xfm->base.funcs = &dcn10_dpp_funcs; - xfm->base.caps = &dcn10_dpp_cap; + dpp->base.inst = inst; + dpp->base.funcs = &dcn10_dpp_funcs; + dpp->base.caps = &dcn10_dpp_cap; - xfm->tf_regs = tf_regs; - xfm->tf_shift = tf_shift; - xfm->tf_mask = tf_mask; + dpp->tf_regs = tf_regs; + dpp->tf_shift = tf_shift; + dpp->tf_mask = tf_mask; - xfm->lb_pixel_depth_supported = + dpp->lb_pixel_depth_supported = LB_PIXEL_DEPTH_18BPP | LB_PIXEL_DEPTH_24BPP | LB_PIXEL_DEPTH_30BPP; - xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; - xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ + dpp->lb_bits_per_entry = LB_BITS_PER_ENTRY; + dpp->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index c2e3ff883537..fe6c0aa13da4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -25,10 +25,10 @@ #ifndef __DAL_DPP_DCN10_H__ #define __DAL_DPP_DCN10_H__ -#include "transform.h" +#include "dpp.h" -#define TO_DCN10_DPP(transform)\ - container_of(transform, struct dcn10_dpp, base) +#define TO_DCN10_DPP(dpp)\ + container_of(dpp, struct dcn10_dpp, base) /* TODO: Use correct number of taps. Using polaris values for now */ #define LB_TOTAL_NUMBER_OF_ENTRIES 5124 @@ -1252,7 +1252,7 @@ struct dcn_dpp_registers { }; struct dcn10_dpp { - struct transform base; + struct dpp base; const struct dcn_dpp_registers *tf_regs; const struct dcn_dpp_shift *tf_shift; @@ -1285,99 +1285,99 @@ void dscl1_calc_lb_num_partitions( int *num_part_y, int *num_part_c); -void ippn10_degamma_ram_select( - struct transform *xfm_base, +void dpp1_degamma_ram_select( + struct dpp *dpp_base, bool use_ram_a); -void ippn10_program_degamma_luta_settings( - struct transform *xfm_base, +void dpp1_program_degamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void ippn10_program_degamma_lutb_settings( - struct transform *xfm_base, +void dpp1_program_degamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void ippn10_program_degamma_lut( - struct transform *xfm_base, +void dpp1_program_degamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num, bool is_ram_a); -void ippn10_power_on_degamma_lut( - struct transform *xfm_base, +void dpp1_power_on_degamma_lut( + struct dpp *dpp_base, bool power_on); -void ippn10_program_input_csc( - struct transform *xfm_base, +void dpp1_program_input_csc( + struct dpp *dpp_base, enum dc_color_space color_space, enum dcn10_input_csc_select select); -void ippn10_program_input_lut( - struct transform *xfm_base, +void dpp1_program_input_lut( + struct dpp *dpp_base, const struct dc_gamma *gamma); -void ippn10_full_bypass(struct transform *xfm_base); +void dpp1_full_bypass(struct dpp *dpp_base); -void ippn10_set_degamma( - struct transform *xfm_base, +void dpp1_set_degamma( + struct dpp *dpp_base, enum ipp_degamma_mode mode); -void ippn10_set_degamma_pwl(struct transform *xfm_base, +void dpp1_set_degamma_pwl(struct dpp *dpp_base, const struct pwl_params *params); bool dpp_get_optimal_number_of_taps( - struct transform *xfm, + struct dpp *dpp, struct scaler_data *scl_data, const struct scaling_taps *in_taps); -void dpp_reset(struct transform *xfm_base); +void dpp_reset(struct dpp *dpp_base); -void dcn10_dpp_cm_program_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num); -void dcn10_dpp_cm_power_on_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_power_on_regamma_lut( + struct dpp *dpp_base, bool power_on); -void dcn10_dpp_cm_configure_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_configure_regamma_lut( + struct dpp *dpp_base, bool is_ram_a); /*program re gamma RAM A*/ -void dcn10_dpp_cm_program_regamma_luta_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params); /*program re gamma RAM B*/ -void dcn10_dpp_cm_program_regamma_lutb_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params); -void dcn10_dpp_cm_set_output_csc_adjustment( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_adjustment( + struct dpp *dpp_base, const struct out_csc_color_matrix *tbl_entry); -void dcn10_dpp_cm_set_output_csc_default( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_default( + struct dpp *dpp_base, const struct default_adjustment *default_adjust); -void dcn10_dpp_cm_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust); +void dpp1_cm_set_gamut_remap( + struct dpp *dpp, + const struct dpp_grph_csc_adjustment *adjust); -void dcn10_dpp_dscl_set_scaler_manual_scale( - struct transform *xfm_base, +void dpp1_dscl_set_scaler_manual_scale( + struct dpp *dpp_base, const struct scaler_data *scl_data); -void ippn10_cnv_setup ( - struct transform *xfm_base, +void dpp1_cnv_setup ( + struct dpp *dpp_base, enum surface_pixel_format input_format, enum expansion_mode mode); -void ippn10_full_bypass(struct transform *xfm_base); +void dpp1_full_bypass(struct dpp *dpp_base); -void dcn10_dpp_construct(struct dcn10_dpp *xfm110, +void dpp1_construct(struct dcn10_dpp *dpp1, struct dc_context *ctx, uint32_t inst, const struct dcn_dpp_registers *tf_regs, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index f88fd2e2e0aa..7784001c3a17 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -40,14 +40,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name struct dcn10_input_csc_matrix { enum dc_color_space color_space; @@ -120,7 +120,7 @@ static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = { static void program_gamut_remap( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const uint16_t *regval, enum gamut_remap_select select) { @@ -146,10 +146,10 @@ static void program_gamut_remap( break; } - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_GAMUT_REMAP_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_GAMUT_REMAP_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_GAMUT_REMAP_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_GAMUT_REMAP_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_GAMUT_REMAP_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12; if (select == GAMUT_REMAP_COEFF) { @@ -157,7 +157,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); @@ -167,7 +167,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); @@ -177,7 +177,7 @@ static void program_gamut_remap( gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } @@ -188,15 +188,15 @@ static void program_gamut_remap( } -void dcn10_dpp_cm_set_gamut_remap( - struct transform *xfm, - const struct xfm_grph_csc_adjustment *adjust) +void dpp1_cm_set_gamut_remap( + struct dpp *dpp_base, + const struct dpp_grph_csc_adjustment *adjust) { - struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) /* Bypass if type is bypass or hw */ - program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS); + program_gamut_remap(dpp, NULL, GAMUT_REMAP_BYPASS); else { struct fixed31_32 arr_matrix[12]; uint16_t arr_reg_val[12]; @@ -219,16 +219,16 @@ void dcn10_dpp_cm_set_gamut_remap( convert_float_matrix( arr_reg_val, arr_matrix, 12); - program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF); + program_gamut_remap(dpp, arr_reg_val, GAMUT_REMAP_COEFF); } } -void dcn10_dpp_cm_set_output_csc_default( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_default( + struct dpp *dpp_base, const struct default_adjustment *default_adjust) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); uint32_t ocsc_mode = 0; if (default_adjust != NULL) { @@ -260,35 +260,35 @@ void dcn10_dpp_cm_set_output_csc_default( } -static void dcn10_dpp_cm_get_reg_field( - struct dcn10_dpp *xfm, +static void dpp1_cm_get_reg_field( + struct dcn10_dpp *dpp, struct xfer_func_reg *reg) { - reg->shifts.exp_region0_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; - reg->masks.exp_region0_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; - reg->shifts.exp_region0_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; - reg->masks.exp_region0_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; - reg->shifts.exp_region1_lut_offset = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; - reg->masks.exp_region1_lut_offset = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; - reg->shifts.exp_region1_num_segments = xfm->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; - reg->masks.exp_region1_num_segments = xfm->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; - - reg->shifts.field_region_end = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; - reg->masks.field_region_end = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; - reg->shifts.field_region_end_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; - reg->masks.field_region_end_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; - reg->shifts.field_region_end_base = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; - reg->masks.field_region_end_base = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; - reg->shifts.field_region_linear_slope = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; - reg->masks.field_region_linear_slope = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; - reg->shifts.exp_region_start = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; - reg->masks.exp_region_start = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; - reg->shifts.exp_resion_start_segment = xfm->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; - reg->masks.exp_resion_start_segment = xfm->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->masks.field_region_end = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->masks.field_region_linear_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; + reg->shifts.exp_region_start = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->masks.exp_region_start = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; } -static void dcn10_dpp_cm_program_color_matrix( - struct dcn10_dpp *xfm, +static void dpp1_cm_program_color_matrix( + struct dcn10_dpp *dpp, const struct out_csc_color_matrix *tbl_entry) { uint32_t mode; @@ -301,10 +301,10 @@ static void dcn10_dpp_cm_program_color_matrix( return; } - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_OCSC_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_OCSC_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_OCSC_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_OCSC_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_OCSC_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_OCSC_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_OCSC_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_OCSC_C12; if (mode == 4) { @@ -312,7 +312,7 @@ static void dcn10_dpp_cm_program_color_matrix( gam_regs.csc_c33_c34 = REG(CM_OCSC_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, tbl_entry->regval, &gam_regs); @@ -322,17 +322,17 @@ static void dcn10_dpp_cm_program_color_matrix( gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, tbl_entry->regval, &gam_regs); } } -void dcn10_dpp_cm_set_output_csc_adjustment( - struct transform *xfm_base, +void dpp1_cm_set_output_csc_adjustment( + struct dpp *dpp_base, const struct out_csc_color_matrix *tbl_entry) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); //enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; uint32_t ocsc_mode = 4; @@ -364,26 +364,26 @@ void dcn10_dpp_cm_set_output_csc_adjustment( */ REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode); - dcn10_dpp_cm_program_color_matrix(xfm, tbl_entry); + dpp1_cm_program_color_matrix(dpp, tbl_entry); } -void dcn10_dpp_cm_power_on_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_power_on_regamma_lut( + struct dpp *dpp_base, bool power_on) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_SET(CM_MEM_PWR_CTRL, 0, RGAM_MEM_PWR_FORCE, power_on == true ? 0:1); } -void dcn10_dpp_cm_program_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num) { uint32_t i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); for (i = 0 ; i < num; i++) { REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg); REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg); @@ -400,11 +400,11 @@ void dcn10_dpp_cm_program_regamma_lut( } -void dcn10_dpp_cm_configure_regamma_lut( - struct transform *xfm_base, +void dpp1_cm_configure_regamma_lut( + struct dpp *dpp_base, bool is_ram_a) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK, CM_RGAM_LUT_WRITE_EN_MASK, 7); @@ -414,14 +414,14 @@ void dcn10_dpp_cm_configure_regamma_lut( } /*program re gamma RAM A*/ -void dcn10_dpp_cm_program_regamma_luta_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMA_START_CNTL_G); @@ -438,19 +438,19 @@ void dcn10_dpp_cm_program_regamma_luta_settings( gam_regs.region_start = REG(CM_RGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMA_REGION_32_33); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } /*program re gamma RAM B*/ -void dcn10_dpp_cm_program_regamma_lutb_settings( - struct transform *xfm_base, +void dpp1_cm_program_regamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_RGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_RGAM_RAMB_START_CNTL_G); @@ -467,15 +467,15 @@ void dcn10_dpp_cm_program_regamma_lutb_settings( gam_regs.region_start = REG(CM_RGAM_RAMB_REGION_0_1); gam_regs.region_end = REG(CM_RGAM_RAMB_REGION_32_33); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } -void ippn10_program_input_csc( - struct transform *xfm_base, +void dpp1_program_input_csc( + struct dpp *dpp_base, enum dc_color_space color_space, enum dcn10_input_csc_select select) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); int i; int arr_size = sizeof(dcn10_input_csc_matrix)/sizeof(struct dcn10_input_csc_matrix); const uint16_t *regval = NULL; @@ -503,10 +503,10 @@ void ippn10_program_input_csc( REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, selection); - gam_regs.shifts.csc_c11 = xfm->tf_shift->CM_ICSC_C11; - gam_regs.masks.csc_c11 = xfm->tf_mask->CM_ICSC_C11; - gam_regs.shifts.csc_c12 = xfm->tf_shift->CM_ICSC_C12; - gam_regs.masks.csc_c12 = xfm->tf_mask->CM_ICSC_C12; + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_ICSC_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12; if (select == INPUT_CSC_SELECT_ICSC) { @@ -515,7 +515,7 @@ void ippn10_program_input_csc( gam_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } else { @@ -524,21 +524,21 @@ void ippn10_program_input_csc( gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34); cm_helper_program_color_matrices( - xfm->base.ctx, + dpp->base.ctx, regval, &gam_regs); } } /*program de gamma RAM B*/ -void ippn10_program_degamma_lutb_settings( - struct transform *xfm_base, +void dpp1_program_degamma_lutb_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G); @@ -556,18 +556,18 @@ void ippn10_program_degamma_lutb_settings( gam_regs.region_end = REG(CM_DGAM_RAMB_REGION_14_15); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } /*program de gamma RAM A*/ -void ippn10_program_degamma_luta_settings( - struct transform *xfm_base, +void dpp1_program_degamma_luta_settings( + struct dpp *dpp_base, const struct pwl_params *params) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct xfer_func_reg gam_regs; - dcn10_dpp_cm_get_reg_field(xfm, &gam_regs); + dpp1_cm_get_reg_field(dpp, &gam_regs); gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B); gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G); @@ -584,34 +584,35 @@ void ippn10_program_degamma_luta_settings( gam_regs.region_start = REG(CM_DGAM_RAMA_REGION_0_1); gam_regs.region_end = REG(CM_DGAM_RAMA_REGION_14_15); - cm_helper_program_xfer_func(xfm->base.ctx, params, &gam_regs); + cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs); } -void ippn10_power_on_degamma_lut( - struct transform *xfm_base, +void dpp1_power_on_degamma_lut( + struct dpp *dpp_base, bool power_on) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, power_on == true ? 0:1); } -static void ippn10_enable_cm_block( - struct transform *xfm_base) +static void dpp1_enable_cm_block( + struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + REG_UPDATE(CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, 8); REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0); } -void ippn10_set_degamma( - struct transform *xfm_base, +void dpp1_set_degamma( + struct dpp *dpp_base, enum ipp_degamma_mode mode) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); - ippn10_enable_cm_block(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + dpp1_enable_cm_block(dpp_base); switch (mode) { case IPP_DEGAMMA_MODE_BYPASS: @@ -630,11 +631,11 @@ void ippn10_set_degamma( } } -void ippn10_degamma_ram_select( - struct transform *xfm_base, +void dpp1_degamma_ram_select( + struct dpp *dpp_base, bool use_ram_a) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); if (use_ram_a) REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3); @@ -643,13 +644,13 @@ void ippn10_degamma_ram_select( } -static bool ippn10_degamma_ram_inuse( - struct transform *xfm_base, +static bool dpp1_degamma_ram_inuse( + struct dpp *dpp_base, bool *ram_a_inuse) { bool ret = false; uint32_t status_reg = 0; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, &status_reg); @@ -664,15 +665,15 @@ static bool ippn10_degamma_ram_inuse( return ret; } -void ippn10_program_degamma_lut( - struct transform *xfm_base, +void dpp1_program_degamma_lut( + struct dpp *dpp_base, const struct pwl_result_data *rgb, uint32_t num, bool is_ram_a) { uint32_t i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0); REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_EN_MASK, 7); @@ -694,27 +695,27 @@ void ippn10_program_degamma_lut( } } -void ippn10_set_degamma_pwl(struct transform *xfm_base, +void dpp1_set_degamma_pwl(struct dpp *dpp_base, const struct pwl_params *params) { bool is_ram_a = true; - ippn10_power_on_degamma_lut(xfm_base, true); - ippn10_enable_cm_block(xfm_base); - ippn10_degamma_ram_inuse(xfm_base, &is_ram_a); + dpp1_power_on_degamma_lut(dpp_base, true); + dpp1_enable_cm_block(dpp_base); + dpp1_degamma_ram_inuse(dpp_base, &is_ram_a); if (is_ram_a == true) - ippn10_program_degamma_lutb_settings(xfm_base, params); + dpp1_program_degamma_lutb_settings(dpp_base, params); else - ippn10_program_degamma_luta_settings(xfm_base, params); + dpp1_program_degamma_luta_settings(dpp_base, params); - ippn10_program_degamma_lut(xfm_base, params->rgb_resulted, + dpp1_program_degamma_lut(dpp_base, params->rgb_resulted, params->hw_points_num, !is_ram_a); - ippn10_degamma_ram_select(xfm_base, !is_ram_a); + dpp1_degamma_ram_select(dpp_base, !is_ram_a); } -void ippn10_full_bypass(struct transform *xfm_base) +void dpp1_full_bypass(struct dpp *dpp_base) { - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); /* Input pixel format: ARGB8888 */ REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0, @@ -727,19 +728,19 @@ void ippn10_full_bypass(struct transform *xfm_base) FORMAT_EXPANSION_MODE, 0); /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */ - if (xfm->tf_mask->CM_BYPASS_EN) + if (dpp->tf_mask->CM_BYPASS_EN) REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1); /* Setting degamma bypass for now */ REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0); } -static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, +static bool dpp1_ingamma_ram_inuse(struct dpp *dpp_base, bool *ram_a_inuse) { bool in_use = false; uint32_t status_reg = 0; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS, &status_reg); @@ -765,19 +766,19 @@ static bool ippn10_ingamma_ram_inuse(struct transform *xfm_base, * In the future, this function should support additional input gamma methods, * such as piecewise linear mapping, and input gamma bypass. */ -void ippn10_program_input_lut( - struct transform *xfm_base, +void dpp1_program_input_lut( + struct dpp *dpp_base, const struct dc_gamma *gamma) { int i; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); bool rama_occupied = false; uint32_t ram_num; // Power on LUT memory. REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1); - ippn10_enable_cm_block(xfm_base); + dpp1_enable_cm_block(dpp_base); // Determine whether to use RAM A or RAM B - ippn10_ingamma_ram_inuse(xfm_base, &rama_occupied); + dpp1_ingamma_ram_inuse(dpp_base, &rama_occupied); if (!rama_occupied) REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0); else diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index eda6c8010fb8..b443a90974b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -40,14 +40,14 @@ #define BLACK_OFFSET_CBCR 0x8000 #define REG(reg)\ - xfm->tf_regs->reg + dpp->tf_regs->reg #define CTX \ - xfm->base.ctx + dpp->base.ctx #undef FN #define FN(reg_name, field_name) \ - xfm->tf_shift->field_name, xfm->tf_mask->field_name + dpp->tf_shift->field_name, dpp->tf_mask->field_name enum dcn10_coef_filter_type_sel { SCL_COEF_LUMA_VERT_FILTER = 0, @@ -86,7 +86,7 @@ enum dscl_mode_sel { }; static void dpp_set_overscan( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t left = data->recout.x; @@ -114,7 +114,7 @@ static void dpp_set_overscan( } static void dpp_set_otg_blank( - struct dcn10_dpp *xfm, const struct scaler_data *data) + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t h_blank_start = data->h_active; uint32_t h_blank_end = 0; @@ -165,13 +165,13 @@ static bool is_420_format(enum pixel_format format) } static enum dscl_mode_sel get_dscl_mode( - struct transform *xfm_base, + struct dpp *dpp_base, const struct scaler_data *data, bool dbg_always_scale) { const long long one = dal_fixed31_32_one.value; - if (xfm_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + if (dpp_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { /* DSCL is processing data in fixed format */ if (data->format == PIXEL_FORMAT_FP16) return DSCL_MODE_DSCL_BYPASS; @@ -199,12 +199,12 @@ static enum dscl_mode_sel get_dscl_mode( } static void dpp_set_lb( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) { /* LB */ - if (xfm->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { + if (dpp->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { /* DSCL caps: pixel data processed in fixed format */ uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; @@ -250,7 +250,7 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) } static void dpp_set_scaler_filter( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, uint32_t taps, enum dcn10_coef_filter_type_sel filter_type, const uint16_t *filter) @@ -288,7 +288,7 @@ static void dpp_set_scaler_filter( } static void dpp_set_scl_filter( - struct dcn10_dpp *xfm, + struct dcn10_dpp *dpp, const struct scaler_data *scl_data, bool chroma_coef_mode) { @@ -330,16 +330,16 @@ static void dpp_set_scl_filter( filter_v = get_filter_coeffs_64p( scl_data->taps.v_taps, scl_data->ratios.vert); - filter_updated = (filter_h && (filter_h != xfm->filter_h)) - || (filter_v && (filter_v != xfm->filter_v)); + filter_updated = (filter_h && (filter_h != dpp->filter_h)) + || (filter_v && (filter_v != dpp->filter_v)); if (chroma_coef_mode) { filter_h_c = get_filter_coeffs_64p( scl_data->taps.h_taps_c, scl_data->ratios.horz_c); filter_v_c = get_filter_coeffs_64p( scl_data->taps.v_taps_c, scl_data->ratios.vert_c); - filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c)) - || (filter_v_c && (filter_v_c != xfm->filter_v_c)); + filter_updated = filter_updated || (filter_h_c && (filter_h_c != dpp->filter_h_c)) + || (filter_v_c && (filter_v_c != dpp->filter_v_c)); } if (filter_updated) { @@ -347,34 +347,34 @@ static void dpp_set_scl_filter( if (!h_2tap_hardcode_coef_en && filter_h) { dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps, + dpp, scl_data->taps.h_taps, SCL_COEF_LUMA_HORZ_FILTER, filter_h); } - xfm->filter_h = filter_h; + dpp->filter_h = filter_h; if (!v_2tap_hardcode_coef_en && filter_v) { dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps, + dpp, scl_data->taps.v_taps, SCL_COEF_LUMA_VERT_FILTER, filter_v); } - xfm->filter_v = filter_v; + dpp->filter_v = filter_v; if (chroma_coef_mode) { if (!h_2tap_hardcode_coef_en && filter_h_c) { dpp_set_scaler_filter( - xfm, scl_data->taps.h_taps_c, + dpp, scl_data->taps.h_taps_c, SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); } if (!v_2tap_hardcode_coef_en && filter_v_c) { dpp_set_scaler_filter( - xfm, scl_data->taps.v_taps_c, + dpp, scl_data->taps.v_taps_c, SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); } } - xfm->filter_h_c = filter_h_c; - xfm->filter_v_c = filter_v_c; + dpp->filter_h_c = filter_h_c; + dpp->filter_v_c = filter_v_c; coef_ram_current = get_reg_field_value_ex( - scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, - xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); + scl_mode, dpp->tf_mask->SCL_COEF_RAM_SELECT_CURRENT, + dpp->tf_shift->SCL_COEF_RAM_SELECT_CURRENT); /* Swap coefficient RAM and set chroma coefficient mode */ REG_SET_2(SCL_MODE, scl_mode, @@ -458,7 +458,7 @@ bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, +static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, const struct scaler_data *scl_data) { int num_part_y, num_part_c; @@ -468,17 +468,17 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c); enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; - if (xfm->base.ctx->dc->debug.use_max_lb) + if (dpp->base.ctx->dc->debug.use_max_lb) return mem_cfg; - xfm->base.caps->dscl_calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; - xfm->base.caps->dscl_calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -487,7 +487,7 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, if (scl_data->format == PIXEL_FORMAT_420BPP8 || scl_data->format == PIXEL_FORMAT_420BPP10) { - xfm->base.caps->dscl_calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) @@ -495,7 +495,7 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, return LB_MEMORY_CONFIG_3; } - xfm->base.caps->dscl_calc_lb_num_partitions( + dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ @@ -506,27 +506,27 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *xfm, } void dpp_set_scaler_auto_scale( - struct transform *xfm_base, + struct dpp *dpp_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( - xfm_base, scl_data, xfm_base->ctx->dc->debug.always_scale); + dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - dpp_set_overscan(xfm, scl_data); + dpp_set_overscan(dpp, scl_data); - dpp_set_otg_blank(xfm, scl_data); + dpp_set_otg_blank(dpp, scl_data); REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; - lb_config = find_lb_memory_config(xfm, scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + lb_config = find_lb_memory_config(dpp, scl_data); + dpp_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -554,12 +554,12 @@ void dpp_set_scaler_auto_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(xfm, scl_data, ycbcr); + dpp_set_scl_filter(dpp, scl_data, ycbcr); } static void dpp_set_manual_ratio_init( - struct dcn10_dpp *xfm, const struct scaler_data *data) + struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t init_frac = 0; uint32_t init_int = 0; @@ -619,7 +619,7 @@ static void dpp_set_manual_ratio_init( static void dpp_set_recout( - struct dcn10_dpp *xfm, const struct rect *recout) + struct dcn10_dpp *dpp, const struct rect *recout) { REG_SET_2(RECOUT_START, 0, /* First pixel of RECOUT */ @@ -632,24 +632,24 @@ static void dpp_set_recout( RECOUT_WIDTH, recout->width, /* Number of RECOUT vertical lines */ RECOUT_HEIGHT, recout->height - - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 * - (xfm->base.inst + 1)); + - dpp->base.ctx->dc->debug.surface_visual_confirm * 4 * + (dpp->base.inst + 1)); } /* Main function to program scaler and line buffer in manual scaling mode */ -void dcn10_dpp_dscl_set_scaler_manual_scale( - struct transform *xfm_base, +void dpp1_dscl_set_scaler_manual_scale( + struct dpp *dpp_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; - struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); enum dscl_mode_sel dscl_mode = get_dscl_mode( - xfm_base, scl_data, xfm_base->ctx->dc->debug.always_scale); + dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; /* Recout */ - dpp_set_recout(xfm, &scl_data->recout); + dpp_set_recout(dpp, &scl_data->recout); /* MPC Size */ REG_SET_2(MPC_SIZE, 0, @@ -665,8 +665,8 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( return; /* LB */ - lb_config = find_lb_memory_config(xfm, scl_data); - dpp_set_lb(xfm, &scl_data->lb_params, lb_config); + lb_config = find_lb_memory_config(dpp, scl_data); + dpp_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -689,7 +689,7 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); /* Manually calculate scale ratio and init values */ - dpp_set_manual_ratio_init(xfm, scl_data); + dpp_set_manual_ratio_init(dpp, scl_data); /* HTaps/VTaps */ REG_SET_4(SCL_TAP_CONTROL, 0, @@ -698,5 +698,5 @@ void dcn10_dpp_dscl_set_scaler_manual_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(xfm, scl_data, ycbcr); + dpp_set_scl_filter(dpp, scl_data, ycbcr); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6b866b169985..b69884549fc5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -895,10 +895,10 @@ static void dcn10_init_hw(struct dc *dc) } for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct transform *xfm = dc->res_pool->transforms[i]; + struct dpp *dpp = dc->res_pool->dpps[i]; struct timing_generator *tg = dc->res_pool->timing_generators[i]; - xfm->funcs->transform_reset(xfm); + dpp->funcs->dpp_reset(dpp); dc->res_pool->mpc->funcs->remove( dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree), dc->res_pool->opps[i]->inst, i); @@ -1146,14 +1146,14 @@ static void plane_atomic_disable(struct dc *dc, static void plane_atomic_power_down(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct transform *xfm = dc->res_pool->transforms[fe_idx]; + struct dpp *dpp = dc->res_pool->dpps[fe_idx]; if (REG(DC_IP_REQUEST_CNTL)) { REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); - xfm->funcs->transform_reset(xfm); + dpp->funcs->dpp_reset(dpp); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DEBUG, @@ -1203,7 +1203,7 @@ static void reset_front_end( static void dcn10_power_down_fe(struct dc *dc, int fe_idx) { struct dce_hwseq *hws = dc->hwseq; - struct transform *xfm = dc->res_pool->transforms[fe_idx]; + struct dpp *dpp = dc->res_pool->dpps[fe_idx]; reset_front_end(dc, fe_idx); @@ -1211,7 +1211,7 @@ static void dcn10_power_down_fe(struct dc *dc, int fe_idx) IP_REQUEST_EN, 1); dpp_pg_control(hws, fe_idx, false); hubp_pg_control(hws, fe_idx, false); - xfm->funcs->transform_reset(xfm); + dpp->funcs->dpp_reset(dpp); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); dm_logger_write(dc->ctx->logger, LOG_DEBUG, @@ -1365,34 +1365,34 @@ static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_c static bool dcn10_set_input_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) { - struct transform *xfm_base = pipe_ctx->plane_res.xfm; + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; const struct dc_transfer_func *tf = NULL; bool result = true; - if (xfm_base == NULL) + if (dpp_base == NULL) return false; if (plane_state->in_transfer_func) tf = plane_state->in_transfer_func; if (plane_state->gamma_correction && dce_use_lut(plane_state)) - xfm_base->funcs->ipp_program_input_lut(xfm_base, + dpp_base->funcs->ipp_program_input_lut(dpp_base, plane_state->gamma_correction); if (tf == NULL) - xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); else if (tf->type == TF_TYPE_PREDEFINED) { switch (tf->tf) { case TRANSFER_FUNCTION_SRGB: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB); break; case TRANSFER_FUNCTION_BT709: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC); break; case TRANSFER_FUNCTION_LINEAR: - xfm_base->funcs->ipp_set_degamma(xfm_base, + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); break; case TRANSFER_FUNCTION_PQ: @@ -1403,7 +1403,7 @@ static bool dcn10_set_input_transfer_func( break; } } else if (tf->type == TF_TYPE_BYPASS) { - xfm_base->funcs->ipp_set_degamma(xfm_base, IPP_DEGAMMA_MODE_BYPASS); + dpp_base->funcs->ipp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); } else { /*TF_TYPE_DISTRIBUTED_POINTS*/ result = false; @@ -1730,25 +1730,25 @@ static bool dcn10_set_output_transfer_func( struct pipe_ctx *pipe_ctx, const struct dc_stream_state *stream) { - struct transform *xfm = pipe_ctx->plane_res.xfm; + struct dpp *dpp = pipe_ctx->plane_res.dpp; - if (xfm == NULL) + if (dpp == NULL) return false; - xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; + dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; if (stream->out_transfer_func && stream->out_transfer_func->type == TF_TYPE_PREDEFINED && stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_SRGB); } else if (dcn10_translate_regamma_to_hw_format( - stream->out_transfer_func, &xfm->regamma_params)) { - xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); + stream->out_transfer_func, &dpp->regamma_params)) { + dpp->funcs->opp_program_regamma_pwl(dpp, &dpp->regamma_params); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_USER); } else { - xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS); + dpp->funcs->opp_set_regamma_mode(dpp, OPP_REGAMMA_BYPASS); } return true; @@ -2033,7 +2033,7 @@ static void dcn10_power_on_fe( static void program_gamut_remap(struct pipe_ctx *pipe_ctx) { - struct xfm_grph_csc_adjustment adjust; + struct dpp_grph_csc_adjustment adjust; memset(&adjust, 0, sizeof(adjust)); adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; @@ -2069,7 +2069,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx) gamut_remap_matrix.matrix[10]; } - pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); + pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust); } @@ -2091,7 +2091,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, tbl_entry.color_space = color_space; //tbl_entry.regval = matrix; - pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry); + pipe_ctx->plane_res.dpp->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.dpp, &tbl_entry); } } static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) @@ -2275,7 +2275,7 @@ static void update_dchubp_dpp( { struct dce_hwseq *hws = dc->hwseq; struct hubp *hubp = pipe_ctx->plane_res.hubp; - struct transform *xfm = pipe_ctx->plane_res.xfm; + struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_plane_state *plane_state = pipe_ctx->plane_state; union plane_size size = plane_state->plane_size; struct mpcc_cfg mpcc_cfg = {0}; @@ -2317,7 +2317,7 @@ static void update_dchubp_dpp( hws ); - xfm->funcs->ipp_setup(xfm, + dpp->funcs->ipp_setup(dpp, plane_state->format, EXPANSION_MODE_ZERO); @@ -2346,8 +2346,9 @@ static void update_dchubp_dpp( pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; /* scaler configuration */ - pipe_ctx->plane_res.xfm->funcs->transform_set_scaler( - pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data); + pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); + hubp->funcs->mem_program_viewport(hubp, &pipe_ctx->plane_res.scl_data.viewport, &pipe_ctx->plane_res.scl_data.viewport_c); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4764590f9097..4dbaf9a2f275 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -446,13 +446,13 @@ static const struct dc_debug debug_defaults_diags = { .disable_pplib_wm_range = true }; -static void dcn10_dpp_destroy(struct transform **xfm) +static void dcn10_dpp_destroy(struct dpp **dpp) { - kfree(TO_DCN10_DPP(*xfm)); - *xfm = NULL; + kfree(TO_DCN10_DPP(*dpp)); + *dpp = NULL; } -static struct transform *dcn10_dpp_create( +static struct dpp *dcn10_dpp_create( struct dc_context *ctx, uint32_t inst) { @@ -462,8 +462,8 @@ static struct transform *dcn10_dpp_create( if (!dpp) return NULL; - dcn10_dpp_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask); + dpp1_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask); return &dpp->base; } @@ -702,8 +702,8 @@ static void destruct(struct dcn10_resource_pool *pool) if (pool->base.opps[i] != NULL) pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - if (pool->base.transforms[i] != NULL) - dcn10_dpp_destroy(&pool->base.transforms[i]); + if (pool->base.dpps[i] != NULL) + dcn10_dpp_destroy(&pool->base.dpps[i]); if (pool->base.ipps[i] != NULL) pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); @@ -924,7 +924,7 @@ static struct pipe_ctx *dcn10_acquire_idle_pipe_for_layer( idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.xfm = pool->transforms[idle_pipe->pipe_idx]; + idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; return idle_pipe; } @@ -1377,8 +1377,8 @@ static bool construct( goto ipp_create_fail; } - pool->base.transforms[j] = dcn10_dpp_create(ctx, i); - if (pool->base.transforms[j] == NULL) { + pool->base.dpps[j] = dcn10_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { BREAK_TO_DEBUGGER(); dm_error( "DC: failed to create dpp!\n"); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 45518c05e846..b69f321e2ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -84,6 +84,7 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); /********** DAL Core*********************/ #include "display_clock.h" #include "transform.h" +#include "dpp.h" struct resource_pool; struct dc_state; @@ -133,6 +134,7 @@ struct resource_pool { struct hubp *hubps[MAX_PIPES]; struct input_pixel_processor *ipps[MAX_PIPES]; struct transform *transforms[MAX_PIPES]; + struct dpp *dpps[MAX_PIPES]; struct output_pixel_processor *opps[MAX_PIPES]; struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; @@ -184,6 +186,7 @@ struct plane_resource { struct mem_input *mi; struct input_pixel_processor *ipp; struct transform *xfm; + struct dpp *dpp; }; struct pipe_ctx { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h new file mode 100644 index 000000000000..83a68460edcd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -0,0 +1,134 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef __DAL_DPP_H__ +#define __DAL_DPP_H__ + +#include "transform.h" + +struct dpp { + const struct dpp_funcs *funcs; + struct dc_context *ctx; + int inst; + struct dpp_caps *caps; + struct pwl_params regamma_params; +}; + +struct dpp_grph_csc_adjustment { + struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; + enum graphics_gamut_adjust_type gamut_adjust_type; +}; + +struct dpp_funcs { + void (*dpp_reset)(struct dpp *dpp); + + void (*dpp_set_scaler)(struct dpp *dpp, + const struct scaler_data *scl_data); + + void (*dpp_set_pixel_storage_depth)( + struct dpp *dpp, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params); + + bool (*dpp_get_optimal_number_of_taps)( + struct dpp *dpp, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); + + void (*dpp_set_gamut_remap)( + struct dpp *dpp, + const struct dpp_grph_csc_adjustment *adjust); + + void (*opp_set_csc_default)( + struct dpp *dpp, + const struct default_adjustment *default_adjust); + + void (*opp_set_csc_adjustment)( + struct dpp *dpp, + const struct out_csc_color_matrix *tbl_entry); + + void (*opp_power_on_regamma_lut)( + struct dpp *dpp, + bool power_on); + + void (*opp_program_regamma_lut)( + struct dpp *dpp, + const struct pwl_result_data *rgb, + uint32_t num); + + void (*opp_configure_regamma_lut)( + struct dpp *dpp, + bool is_ram_a); + + void (*opp_program_regamma_lutb_settings)( + struct dpp *dpp, + const struct pwl_params *params); + + void (*opp_program_regamma_luta_settings)( + struct dpp *dpp, + const struct pwl_params *params); + + void (*opp_program_regamma_pwl)( + struct dpp *dpp, const struct pwl_params *params); + + void (*opp_set_regamma_mode)( + struct dpp *dpp_base, + enum opp_regamma mode); + + void (*ipp_set_degamma)( + struct dpp *dpp_base, + enum ipp_degamma_mode mode); + + void (*ipp_program_input_lut)( + struct dpp *dpp_base, + const struct dc_gamma *gamma); + + void (*ipp_program_degamma_pwl)(struct dpp *dpp_base, + const struct pwl_params *params); + + void (*ipp_setup)( + struct dpp *dpp_base, + enum surface_pixel_format input_format, + enum expansion_mode mode); + + void (*ipp_full_bypass)(struct dpp *dpp_base); + + void (*set_cursor_attributes)( + struct dpp *dpp_base, + const struct dc_cursor_attributes *attr); + + void (*set_cursor_position)( + struct dpp *dpp_base, + const struct dc_cursor_position *pos, + const struct dc_cursor_mi_param *param, + uint32_t width + ); + +}; + + + +#endif -- GitLab From 3df8fcafb7edab79d76c4c76c93446b91eb4916f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Wed, 4 Oct 2017 12:47:13 -0400 Subject: [PATCH 1349/2898] drm/amd/display: Do not set bandwidth on page flips. Which removes a lockdep warning for a possible deadlock situation: While holding the drm event mutex (hard irq safe), dc_post_update_surfaces_to_stream eventually acquires the atom context lock, which is hard irq unsafe. We should only be calling it on full updates anyways. Also remove a redundant call to dc_post_update_surfaces_to_stream, dc_commit_updates_for_stream already calls it. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 80ddccc2570a..9d750fa29a87 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -980,8 +980,6 @@ bool dc_commit_planes_to_stream( new_plane_count, dc_stream, stream_update, plane_states, state); - dc_post_update_surfaces_to_stream(dc); - kfree(stream_update); return true; } @@ -1418,7 +1416,8 @@ void dc_commit_updates_for_stream(struct dc *dc, update_type, context); - dc_post_update_surfaces_to_stream(dc); + if (update_type >= UPDATE_TYPE_FULL) + dc_post_update_surfaces_to_stream(dc); if (dc->current_state != context) { -- GitLab From 9bbc30310f240c9400e31c7ab7b7edd2b76b3589 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Fri, 6 Oct 2017 15:08:07 -0400 Subject: [PATCH 1350/2898] drm/amd/display: Remove a false-positive error message To avoid confusion, need to suppress the error message when get -ERESTARTSYS error code. It is normal when getting interrupted by signals in the process of a wait for the buffer to become unreserved. Only propagate to user-mode for further action, no need to pop up error message. Signed-off-by: Jerry Zuo Reviewed-by: Sun peng Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 17fb636648f4..09163d8d9332 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1790,7 +1790,9 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, int r = amdgpu_bo_reserve(rbo, false); if (unlikely(r)) { - DRM_ERROR("Unable to reserve buffer\n"); + // Don't show error msg. when return -ERESTARTSYS + if (r != -ERESTARTSYS) + DRM_ERROR("Unable to reserve buffer: %d\n", r); return r; } -- GitLab From 215a6f05bcc18ffcd953a8527639ea1f571f4d81 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 6 Oct 2017 15:40:07 -0400 Subject: [PATCH 1351/2898] drm/amd/display: add performance trace macro to dc Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/amdgpu_dm/amdgpu_dm_services.c | 6 ++ .../gpu/drm/amd/display/dc/basics/logger.c | 78 ++++++------------- .../gpu/drm/amd/display/dc/basics/logger.h | 37 --------- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 5 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../drm/amd/display/dc/dce/dce_link_encoder.c | 5 -- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 40 +++++----- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + drivers/gpu/drm/amd/display/dc/dm_services.h | 2 + .../amd/display/include/logger_interface.h | 28 +++++++ .../drm/amd/display/include/logger_types.h | 36 ++++++++- 11 files changed, 118 insertions(+), 121 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index 26bf9918fcb7..5df8fd5b537c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -35,6 +35,12 @@ #include "amdgpu_dm_irq.h" #include "amdgpu_pm.h" +unsigned long long dm_get_timestamp(struct dc_context *ctx) +{ + /* TODO: return actual timestamp */ + return 0; +} + bool dm_write_persistent_data(struct dc_context *ctx, const struct dc_sink *sink, const char *module_name, diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c index afb6d2d80e0c..e04e8ecd4874 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.c +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c @@ -80,8 +80,6 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, logger->buffer_read_offset = 0; logger->buffer_write_offset = 0; - logger->write_wrap_count = 0; - logger->read_wrap_count = 0; logger->open_count = 0; logger->flags.bits.ENABLE_CONSOLE = 1; @@ -162,23 +160,24 @@ static void log_to_debug_console(struct log_entry *entry) } /* Print everything unread existing in log_buffer to debug console*/ -static void flush_to_debug_console(struct dal_logger *logger) +void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn) { - int i = logger->buffer_read_offset; - char *string_start = &logger->log_buffer[i]; + char *string_start = &logger->log_buffer[logger->buffer_read_offset]; - dm_output_to_console( - "---------------- FLUSHING LOG BUFFER ----------------\n"); - while (i < logger->buffer_write_offset) { + if (should_warn) + dm_output_to_console( + "---------------- FLUSHING LOG BUFFER ----------------\n"); + while (logger->buffer_read_offset < logger->buffer_write_offset) { - if (logger->log_buffer[i] == '\0') { + if (logger->log_buffer[logger->buffer_read_offset] == '\0') { dm_output_to_console("%s", string_start); - string_start = (char *)logger->log_buffer + i + 1; + string_start = logger->log_buffer + logger->buffer_read_offset + 1; } - i++; + logger->buffer_read_offset++; } - dm_output_to_console( - "-------------- END FLUSHING LOG BUFFER --------------\n\n"); + if (should_warn) + dm_output_to_console( + "-------------- END FLUSHING LOG BUFFER --------------\n\n"); } static void log_to_internal_buffer(struct log_entry *entry) @@ -195,35 +194,17 @@ static void log_to_internal_buffer(struct log_entry *entry) if (size > 0 && size < logger->log_buffer_size) { - int total_free_space = 0; - int space_before_wrap = 0; - - if (logger->buffer_write_offset > logger->buffer_read_offset) { - total_free_space = logger->log_buffer_size - - logger->buffer_write_offset + - logger->buffer_read_offset; - space_before_wrap = logger->log_buffer_size - - logger->buffer_write_offset; - } else if (logger->buffer_write_offset < - logger->buffer_read_offset) { - total_free_space = logger->log_buffer_size - - logger->buffer_read_offset + - logger->buffer_write_offset; - space_before_wrap = total_free_space; - } else if (logger->write_wrap_count != - logger->read_wrap_count) { - /* Buffer is completely full already */ - total_free_space = 0; - space_before_wrap = 0; - } else { + int buffer_space = logger->log_buffer_size - + logger->buffer_write_offset; + + if (logger->buffer_write_offset == logger->buffer_read_offset) { /* Buffer is empty, start writing at beginning */ - total_free_space = logger->log_buffer_size; - space_before_wrap = logger->log_buffer_size; + buffer_space = logger->log_buffer_size; logger->buffer_write_offset = 0; logger->buffer_read_offset = 0; } - if (space_before_wrap > size) { + if (buffer_space > size) { /* No wrap around, copy 'size' bytes * from 'entry->buf' to 'log_buffer' */ @@ -232,28 +213,12 @@ static void log_to_internal_buffer(struct log_entry *entry) entry->buf, size); logger->buffer_write_offset += size; - } else if (total_free_space > size) { - /* We have enough room without flushing, - * but need to wrap around */ - - int space_after_wrap = total_free_space - - space_before_wrap; - - memmove(logger->log_buffer + - logger->buffer_write_offset, - entry->buf, space_before_wrap); - memmove(logger->log_buffer, entry->buf + - space_before_wrap, space_after_wrap); - - logger->buffer_write_offset = space_after_wrap; - logger->write_wrap_count++; - } else { /* Not enough room remaining, we should flush * existing logs */ /* Flush existing unread logs to console */ - flush_to_debug_console(logger); + dm_logger_flush_buffer(logger, true); /* Start writing to beginning of buffer */ memmove(logger->log_buffer, entry->buf, size); @@ -325,9 +290,10 @@ void dm_logger_write( log_heading(&entry); size = dm_log_to_buffer( - buffer, LOG_MAX_LINE_SIZE, msg, args); + buffer, LOG_MAX_LINE_SIZE - 1, msg, args); - entry.buf_offset += size; + buffer[entry.buf_offset + size] = '\0'; + entry.buf_offset += size + 1; /* --Flush log_entry buffer-- */ /* print to kernel console */ diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.h b/drivers/gpu/drm/amd/display/dc/basics/logger.h index 2f7a5df4c811..09722f0f8aa3 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/logger.h +++ b/drivers/gpu/drm/amd/display/dc/basics/logger.h @@ -26,42 +26,5 @@ #ifndef __DAL_LOGGER_H__ #define __DAL_LOGGER_H__ -/* Structure for keeping track of offsets, buffer, etc */ - -#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 - -/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes, - * change log line size to 896 to meet the request. - */ -#define LOG_MAX_LINE_SIZE 896 - -#include "include/logger_types.h" - -struct dal_logger { - - /* How far into the circular buffer has been read by dsat - * Read offset should never cross write offset. Write \0's to - * read data just to be sure? - */ - uint32_t buffer_read_offset; - - /* How far into the circular buffer we have written - * Write offset should never cross read offset - */ - uint32_t buffer_write_offset; - - uint32_t write_wrap_count; - uint32_t read_wrap_count; - - uint32_t open_count; - - char *log_buffer; /* Pointer to malloc'ed buffer */ - uint32_t log_buffer_size; /* Size of circular buffer */ - - uint32_t mask; /*array of masks for major elements*/ - - union logger_flags flags; - struct dc_context *ctx; -}; #endif /* __DAL_LOGGER_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index cf0c1459f546..e1515230c661 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -682,6 +682,7 @@ bool dcn_validate_bandwidth( bool bw_limit_pass; float bw_limit; + PERFORMANCE_TRACE_START(); if (dcn_bw_apply_registry_override(dc)) dcn_bw_sync_calcs_and_dml(dc); @@ -1089,6 +1090,8 @@ bool dcn_validate_bandwidth( kernel_fpu_end(); + PERFORMANCE_TRACE_END(); + if (bw_limit_pass && v->voltage_level != 5) return true; else @@ -1223,7 +1226,7 @@ unsigned int dcn_find_dcfclk_suits_all( else dcf_clk = dc->dcn_soc->dcfclkv_min0p65*1000; - dm_logger_write(dc->ctx->logger, LOG_HW_MARKS, + dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS, "\tdcf_clk for voltage = %d\n", dcf_clk); return dcf_clk; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c7b31adc736e..ace17d13683a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -224,6 +224,7 @@ struct dc_debug { bool disable_dpp_pg; bool disable_stereo_support; bool vsr_support; + bool performance_trace; }; struct dc_state; struct resource_pool; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 0cf0fff74d44..fe88852b4774 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -757,11 +757,6 @@ void dce110_link_encoder_construct( enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; } - dm_logger_write(init_data->ctx->logger, LOG_I2C_AUX, - "Using channel: %s [%d]\n", - DECODE_CHANNEL_ID(init_data->channel), - init_data->channel); - /* Override features with DCE-specific values */ if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( enc110->base.ctx->dc_bios, enc110->base.id, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b69884549fc5..6e2cec643f31 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -468,7 +468,7 @@ static void program_watermarks( refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.urgent_ns, prog_wm_value); @@ -476,7 +476,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp(watermarks->a.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.pte_meta_urgent_ns, prog_wm_value); @@ -487,7 +487,7 @@ static void program_watermarks( refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); @@ -497,7 +497,7 @@ static void program_watermarks( watermarks->a.cstate_pstate.cstate_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_EXIT_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n", watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); @@ -507,7 +507,7 @@ static void program_watermarks( watermarks->a.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -517,7 +517,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->b.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.urgent_ns, prog_wm_value); @@ -527,7 +527,7 @@ static void program_watermarks( watermarks->b.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.pte_meta_urgent_ns, prog_wm_value); @@ -537,7 +537,7 @@ static void program_watermarks( watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_ENTER_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); @@ -547,7 +547,7 @@ static void program_watermarks( watermarks->b.cstate_pstate.cstate_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_EXIT_WATERMARK_B calculated =%d\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); @@ -556,7 +556,7 @@ static void program_watermarks( watermarks->b.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n\n" "HW register value = 0x%x\n", watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -565,7 +565,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->c.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.urgent_ns, prog_wm_value); @@ -575,7 +575,7 @@ static void program_watermarks( watermarks->c.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.pte_meta_urgent_ns, prog_wm_value); @@ -585,7 +585,7 @@ static void program_watermarks( watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_ENTER_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); @@ -595,7 +595,7 @@ static void program_watermarks( watermarks->c.cstate_pstate.cstate_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_EXIT_WATERMARK_C calculated =%d\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); @@ -605,7 +605,7 @@ static void program_watermarks( watermarks->c.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n\n" "HW register value = 0x%x\n", watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); @@ -614,7 +614,7 @@ static void program_watermarks( prog_wm_value = convert_and_clamp( watermarks->d.urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.urgent_ns, prog_wm_value); @@ -623,7 +623,7 @@ static void program_watermarks( watermarks->d.pte_meta_urgent_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "PTE_META_URGENCY_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.pte_meta_urgent_ns, prog_wm_value); @@ -633,7 +633,7 @@ static void program_watermarks( watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_ENTER_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); @@ -643,7 +643,7 @@ static void program_watermarks( watermarks->d.cstate_pstate.cstate_exit_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "SR_EXIT_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n", watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); @@ -653,7 +653,7 @@ static void program_watermarks( watermarks->d.cstate_pstate.pstate_change_ns, refclk_mhz, 0x1fffff); REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_HW_MARKS, + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, "DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" "HW register value = 0x%x\n\n", watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 4dbaf9a2f275..d47ff7e6a525 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -434,6 +434,7 @@ static const struct dc_debug debug_defaults_drv = { .voltage_align_fclk = true, .disable_stereo_support = true, .vsr_support = true, + .performance_trace = false, }; static const struct dc_debug debug_defaults_diags = { diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index a11991c382de..d6b3b832986b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -418,6 +418,8 @@ bool dm_dmcu_set_pipe(struct dc_context *ctx, unsigned int controller_id); #define dm_log_to_buffer(buffer, size, fmt, args)\ vsnprintf(buffer, size, fmt, args) +unsigned long long dm_get_timestamp(struct dc_context *ctx); + /* * Debug and verification hooks */ diff --git a/drivers/gpu/drm/amd/display/include/logger_interface.h b/drivers/gpu/drm/amd/display/include/logger_interface.h index 5aaf2dacfe38..8e1fe70097be 100644 --- a/drivers/gpu/drm/amd/display/include/logger_interface.h +++ b/drivers/gpu/drm/amd/display/include/logger_interface.h @@ -44,6 +44,8 @@ struct dal_logger *dal_logger_create(struct dc_context *ctx, uint32_t log_mask); uint32_t dal_logger_destroy(struct dal_logger **logger); +void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn); + void dm_logger_write( struct dal_logger *logger, enum dc_log_type log_type, @@ -157,4 +159,30 @@ void context_clock_trace( #define DTN_INFO_END() \ dm_dtn_log_end(dc_ctx) +#define PERFORMANCE_TRACE_START() \ + unsigned long long perf_trc_start_stmp = dm_get_timestamp(dc->ctx); \ + unsigned long long perf_trc_start_log_msk = dc->ctx->logger->mask; \ + unsigned int perf_trc_start_log_flags = dc->ctx->logger->flags.value; \ + if (dc->debug.performance_trace) {\ + dm_logger_flush_buffer(dc->ctx->logger, false);\ + dc->ctx->logger->mask = 1<ctx->logger->flags.bits.ENABLE_CONSOLE = 0;\ + dc->ctx->logger->flags.bits.ENABLE_BUFFER = 1;\ + } + +#define PERFORMANCE_TRACE_END() do {\ + unsigned long long perf_trc_end_stmp = dm_get_timestamp(dc->ctx);\ + if (dc->debug.performance_trace) {\ + dm_logger_write(dc->ctx->logger, \ + LOG_PERF_TRACE, \ + "%s duration: %d ticks\n", __func__,\ + perf_trc_end_stmp - perf_trc_start_stmp); \ + if (perf_trc_start_log_msk != 1<ctx->logger->mask = perf_trc_start_log_msk;\ + dc->ctx->logger->flags.value = perf_trc_start_log_flags;\ + dm_logger_flush_buffer(dc->ctx->logger, false);\ + } \ + } \ +} while (0) + #endif /* __DAL_LOGGER_INTERFACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 1f22e84cedb9..e2ff8cd423d6 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -64,8 +64,7 @@ enum dc_log_type { LOG_EVENT_LINK_LOSS, LOG_EVENT_UNDERFLOW, LOG_IF_TRACE, - LOG_HW_MARKS, - LOG_PPLIB, + LOG_PERF_TRACE, LOG_SECTION_TOTAL_COUNT }; @@ -131,4 +130,37 @@ struct dc_log_type_info { char name[MAX_NAME_LEN]; }; +/* Structure for keeping track of offsets, buffer, etc */ + +#define DAL_LOGGER_BUFFER_MAX_SIZE 2048 + +/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes, + * change log line size to 896 to meet the request. + */ +#define LOG_MAX_LINE_SIZE 896 + +struct dal_logger { + + /* How far into the circular buffer has been read by dsat + * Read offset should never cross write offset. Write \0's to + * read data just to be sure? + */ + uint32_t buffer_read_offset; + + /* How far into the circular buffer we have written + * Write offset should never cross read offset + */ + uint32_t buffer_write_offset; + + uint32_t open_count; + + char *log_buffer; /* Pointer to malloc'ed buffer */ + uint32_t log_buffer_size; /* Size of circular buffer */ + + uint32_t mask; /*array of masks for major elements*/ + + union logger_flags flags; + struct dc_context *ctx; +}; + #endif /* __DAL_LOGGER_TYPES_H__ */ -- GitLab From 199e458aafc241a2792b3f8a99d5a11aa7726a7d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 5 Oct 2017 19:15:25 -0400 Subject: [PATCH 1352/2898] drm/amd/display: Set addressable region as active + border This ensures that we do not draw the blank region onscreen, and that we do underscan instead. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 303d7ec684d9..454a521a268d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -850,6 +850,20 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) */ pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + /** + * KMD sends us h and v_addressable without the borders, which causes us sometimes to draw + * the blank region on-screen. Correct for this by adding the borders back to their + * respective addressable values, and by shifting recout. + */ + timing->h_addressable += timing->h_border_left + timing->h_border_right; + timing->v_addressable += timing->v_border_top + timing->v_border_bottom; + pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; + pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; + timing->v_border_top = 0; + timing->v_border_bottom = 0; + timing->h_border_left = 0; + timing->h_border_right = 0; + pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; -- GitLab From 9a5d9c48d883db4f7f3e5409062bef7d25165a95 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Fri, 6 Oct 2017 11:57:40 -0400 Subject: [PATCH 1353/2898] drm/amd/display: Report stream as different on scaling change When scaling is enabled, our preference is to scale up to the prefered (native) mode. This means that hardware timings will be the same across a modeset. Therefore, also report mode as changed if source or destination rectangle is different. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++-- .../gpu/drm/amd/display/dc/core/dc_resource.c | 22 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 09163d8d9332..fad40da8422e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4428,12 +4428,13 @@ static int dm_update_crtcs_state(struct dc *dc, } } - if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream)) { + if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && + dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) { new_crtc_state->mode_changed = false; DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", - new_crtc_state->mode_changed); + new_crtc_state->mode_changed); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 454a521a268d..2a5c91772473 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1335,6 +1335,28 @@ bool dc_is_stream_unchanged( return true; } +bool dc_is_stream_scaling_unchanged( + struct dc_stream_state *old_stream, struct dc_stream_state *stream) +{ + if (old_stream == stream) + return true; + + if (old_stream == NULL || stream == NULL) + return false; + + if (memcmp(&old_stream->src, + &stream->src, + sizeof(struct rect)) != 0) + return false; + + if (memcmp(&old_stream->dst, + &stream->dst, + sizeof(struct rect)) != 0) + return false; + + return true; +} + /* Maximum TMDS single link pixel clock 165MHz */ #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ace17d13683a..f60191d9c7e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -627,6 +627,8 @@ struct dc_stream_update { bool dc_is_stream_unchanged( struct dc_stream_state *old_stream, struct dc_stream_state *stream); +bool dc_is_stream_scaling_unchanged( + struct dc_stream_state *old_stream, struct dc_stream_state *stream); /* * Set up surface attributes and associate to a stream -- GitLab From 5771ec8fe8cb99c0db3115e81b4f69b1543c6982 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Fri, 6 Oct 2017 15:11:41 -0400 Subject: [PATCH 1354/2898] drm/amd/display: ASSERT on dc_create_state failing. dc_create_state() returns NULL on allocation failure. Raise warning when that happens. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index fad40da8422e..e439363ed54b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -702,6 +702,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) dc_release_state(cached_state->context); cached_state->context = dc_create_state(); + ASSERT(cached_state->context); dc_resource_state_copy_construct_current(adev->dm.dc, cached_state->context); for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { -- GitLab From 94c6d735e9ca13018da40f633fd602af6e272cc6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 13 Oct 2017 12:42:01 -0400 Subject: [PATCH 1355/2898] drm/amd/display: Fix non-DCN build Acquire_first_split_pipe only makes sense for DCN. Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 2a5c91772473..55feb16b1fd7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1684,8 +1684,10 @@ enum dc_status resource_map_pool_resources( /* acquire new resources */ pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); +#ifdef CONFIG_DRM_AMD_DC_DCN1_0 if (pipe_idx < 0) pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); +#endif if (pipe_idx < 0) return DC_NO_CONTROLLER_RESOURCE; -- GitLab From 085b017bf81ad5c76118b3e1a9165c743927556b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 10 Oct 2017 11:23:50 -0400 Subject: [PATCH 1356/2898] drm/amd/display: Fix warning about overflow v2: convert value to bool using !! Signed-off-by: Harry Wentland Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index cb94e18cc455..43e9a9959288 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1042,13 +1042,13 @@ static enum bp_result get_embedded_panel_info_v2_1( info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0; info->lcd_timing.misc_info.H_REPLICATION_BY2 = - lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2; + !!(lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2); info->lcd_timing.misc_info.V_REPLICATION_BY2 = - lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2; + !!(lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2); info->lcd_timing.misc_info.COMPOSITE_SYNC = - lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC; + !!(lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC); info->lcd_timing.misc_info.INTERLACE = - lvds->lcd_timing.miscinfo & ATOM_INTERLACE; + !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE); /* not provided by VBIOS*/ info->lcd_timing.misc_info.DOUBLE_CLOCK = 0; @@ -1056,7 +1056,7 @@ static enum bp_result get_embedded_panel_info_v2_1( info->ss_id = 0; info->realtek_eDPToLVDS = - (lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID ? 1:0); + !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID); return BP_RESULT_OK; } -- GitLab From 1a7e4f7407e8869759be7e715bce18698aadbe98 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 13 Oct 2017 07:35:54 +0800 Subject: [PATCH 1357/2898] drm/amd/dc: fix semicolon.cocci warnings drivers/gpu/drm/amd/amdgpu/../display/dc/gpio/gpio_service.c:134:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Fixes: 80be23c57868 ("drm/amd/dc: Add dc display driver (v2)") CC: Harry Wentland Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index d4e5ef64e489..ff9d36b5866e 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -132,7 +132,7 @@ struct gpio_service *dal_gpio_service_create( if (slot) kfree(slot); - }; + } failure_1: kfree(service); -- GitLab From 2979d7e973464c00154fa4fe029de128de3e51db Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 13 Oct 2017 07:17:48 +0800 Subject: [PATCH 1358/2898] drm/amd/display: fix ifnullfree.cocci warnings drivers/gpu/drm/amd/amdgpu/../display/dc/gpio/gpio_service.c:134:3-8: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. drivers/gpu/drm/amd/amdgpu/../display/dc/gpio/gpio_service.c:175:4-9: WARNING: NULL check before freeing functions like kfree, debugfs_remove, debugfs_remove_recursive or usb_free_urb is not needed. Maybe consider reorganizing relevant code to avoid passing NULL values. NULL check before some freeing functions is not needed. Based on checkpatch warning "kfree(NULL) is safe this check is probably not required" and kfreeaddr.cocci by Julia Lawall. Generated by: scripts/coccinelle/free/ifnullfree.cocci Fixes: f09cd1f46388 ("drm/amd/display: Use kernel alloc/free") Signed-off-by: Fengguang Wu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index ff9d36b5866e..80038e0e610f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -130,8 +130,7 @@ struct gpio_service *dal_gpio_service_create( slot = service->busyness[index_of_id]; - if (slot) - kfree(slot); + kfree(slot); } failure_1: @@ -171,8 +170,7 @@ void dal_gpio_service_destroy( do { uint32_t *slot = (*ptr)->busyness[index_of_id]; - if (slot) - kfree(slot); + kfree(slot); ++index_of_id; } while (index_of_id < GPIO_ID_COUNT); -- GitLab From b0f8d4e963de8cd77c237a8ea37799f6f5ce995a Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Fri, 6 Oct 2017 18:02:23 -0400 Subject: [PATCH 1359/2898] drm/amd/display: Don't set cursor address is 0 logging as errors This actually happens quite a bit, and having it as an error causes false positive messages when running tests. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 97f040a25820..5cf69af9693d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -190,7 +190,7 @@ bool dc_stream_set_cursor_attributes( } if (attributes->address.quad_part == 0) { - dm_error("DC: Cursor address is 0!\n"); + dm_output_to_console("DC: Cursor address is 0!\n"); return false; } -- GitLab From 4beb50ff5e96014787d8588a78d07e49df0d114a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 4 Oct 2017 13:54:35 -0400 Subject: [PATCH 1360/2898] drm/amd/display: Fix warning about uninitialized variable Signed-off-by: Harry Wentland Reviewed-by: Bhawanpreet Lakha Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index ed301c3b2736..0790f25c7b3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -361,7 +361,7 @@ static void program_grph_pixel_format( enum surface_pixel_format format) { uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ - uint32_t grph_depth, grph_format; + uint32_t grph_depth = 0, grph_format = 0; uint32_t sign = 0, floating = 0; if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || -- GitLab From c12a7ba543d16c1770fb44670e5eb42ae524c502 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 20:04:48 -0400 Subject: [PATCH 1361/2898] drm/amd/display: Fix up some whitespace in handle_cursor_update Use combo of tabs and spaces Signed-off-by: Harry Wentland Acked-by: Alex Deucher Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e439363ed54b..60587d6f81d7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3709,10 +3709,10 @@ static void handle_cursor_update(struct drm_plane *plane, return; DRM_DEBUG_DRIVER("%s: crtc_id=%d with size %d to %d\n", - __func__, - amdgpu_crtc->crtc_id, - plane->state->crtc_w, - plane->state->crtc_h); + __func__, + amdgpu_crtc->crtc_id, + plane->state->crtc_w, + plane->state->crtc_h); ret = get_cursor_position(plane, crtc, &position); if (ret) -- GitLab From 2126732fdaaa4101b186a76b4df52f575b5df4e5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:10:22 +1000 Subject: [PATCH 1362/2898] drm/amd/display: drop display_pipe_clocks.c. This code isn't used at all in the kernel tree, perhaps it can wait to be imported when it is. It also does a lot of floating point calcs, so probably good to drop it until it's needed and we can ensure proper fpu accessors. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 +- .../drm/amd/display/dc/dml/display_mode_lib.h | 1 - .../amd/display/dc/dml/display_pipe_clocks.c | 106 ------------------ .../amd/display/dc/dml/display_pipe_clocks.h | 37 ------ 4 files changed, 1 insertion(+), 145 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index c6d9d9530d75..87bab8e8139f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -13,7 +13,7 @@ CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 -DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ +DML = display_mode_lib.o display_rq_dlg_calc.o \ display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ soc_bounding_box.o dml_common_defs.o display_mode_vba.o diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index 57f49d29c6b9..ed77f96016dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -29,7 +29,6 @@ #include "dml_common_defs.h" #include "soc_bounding_box.h" #include "display_mode_vba.h" -#include "display_pipe_clocks.h" #include "display_rq_dlg_calc.h" #include "dml1_display_rq_dlg_calc.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c deleted file mode 100644 index 30c379d95156..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "display_pipe_clocks.h" -#include "display_mode_lib.h" -#include "soc_bounding_box.h" - -display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - display_e2e_pipe_params_st *e2e, - unsigned int num_pipes) -{ - display_pipe_clock_st clocks; - bool visited[DC__NUM_PIPES__MAX]; - double max_dispclk = 25.0; //the min dispclk is 25MHz, so keep the min dispclk caculated larger thant 25MHz - double dcfclk, socclk; - unsigned int i, j, k; - unsigned int dsc_inst = 0; - - DTRACE("Calculating pipe clocks..."); - - dcfclk = dml_socbb_voltage_scaling( - &mode_lib->soc, - (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; - socclk = dml_socbb_voltage_scaling( - &mode_lib->soc, - (enum voltage_state) e2e[0].clks_cfg.voltage).socclk_mhz; - clocks.dcfclk_mhz = dcfclk; - clocks.socclk_mhz = socclk; - - max_dispclk = dml_max(max_dispclk, get_dispclk_calculated(mode_lib, e2e, num_pipes)); - clocks.dispclk_mhz = max_dispclk; - DTRACE(" dispclk: %f Mhz", clocks.dispclk_mhz); - DTRACE(" dcfclk: %f Mhz", clocks.dcfclk_mhz); - DTRACE(" socclk: %f Mhz", clocks.socclk_mhz); - - for (k = 0; k < num_pipes; ++k) - visited[k] = false; - - for (i = 0; i < num_pipes; i++) { - clocks.dppclk_mhz[i] = get_dppclk_calculated(mode_lib, e2e, num_pipes, i); - DTRACE(" dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); - - if (e2e[i].pipe.src.is_hsplit && !visited[i]) { - unsigned int grp = e2e[i].pipe.src.hsplit_grp; - - for (j = i; j < num_pipes; j++) { - if (e2e[j].pipe.src.hsplit_grp == grp && e2e[j].pipe.src.is_hsplit - && !visited[j]) { - clocks.dscclk_mhz[j] = get_dscclk_calculated( - mode_lib, - e2e, - num_pipes, - dsc_inst); - DTRACE(" dscclk%d: %f Mhz", j, clocks.dscclk_mhz[j]); - visited[j] = true; - } - } - dsc_inst++; - } - - if (!visited[i]) { - unsigned int otg_inst = e2e[i].pipe.dest.otg_inst; - - for (j = i; j < num_pipes; j++) { - // assign dscclk to all planes with this otg, except if they're doing odm combine, or mpc combine - // which is handled by the conditions above, the odm_combine is not required, but it helps make sense of this code - if (e2e[j].pipe.dest.otg_inst == otg_inst - && !e2e[j].pipe.dest.odm_combine && !visited[j]) { - clocks.dscclk_mhz[j] = get_dscclk_calculated( - mode_lib, - e2e, - num_pipes, - dsc_inst); - DTRACE(" dscclk%d: %f Mhz", j, clocks.dscclk_mhz[j]); - visited[j] = true; - } - } - dsc_inst++; - } - } - - return clocks; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h deleted file mode 100644 index a712dc3ecf4b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ -#ifndef __DISPLAY_PIPE_CLOCKS_H__ -#define __DISPLAY_PIPE_CLOCKS_H__ - -#include "dml_common_defs.h" - -struct display_mode_lib; - -display_pipe_clock_st dml_clks_get_pipe_clocks( - struct display_mode_lib *mode_lib, - display_e2e_pipe_params_st *e2e, - unsigned int num_pipes); - -#endif -- GitLab From 9a5bcd47ea0eb40c8a9e00f6797453c90fbd74d1 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Wed, 11 Oct 2017 15:14:46 -0400 Subject: [PATCH 1363/2898] drm/amd/display: check SR_WATERMARK regs prior to write Signed-off-by: Eric Bernstein Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 144 +++++++++--------- 1 file changed, 74 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 6e2cec643f31..741b5e06d314 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -481,27 +481,26 @@ static void program_watermarks( "HW register value = 0x%x\n", watermarks->a.pte_meta_urgent_ns, prog_wm_value); - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - - - prog_wm_value = convert_and_clamp( - watermarks->a.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_A calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); - + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A)) { + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + + + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_A calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.pstate_change_ns, @@ -533,24 +532,26 @@ static void program_watermarks( watermarks->b.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B)) { + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->b.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_B calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_B calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.pstate_change_ns, @@ -581,25 +582,26 @@ static void program_watermarks( watermarks->c.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C)) { + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->c.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_C calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); - + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_C calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.pstate_change_ns, @@ -629,24 +631,26 @@ static void program_watermarks( watermarks->d.pte_meta_urgent_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_ENTER_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); + if (REG(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D)) { + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_ENTER_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); - prog_wm_value = convert_and_clamp( - watermarks->d.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); - REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); - dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, - "SR_EXIT_WATERMARK_D calculated =%d\n" - "HW register value = 0x%x\n", - watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, + refclk_mhz, 0x1fffff); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + dm_logger_write(hws->ctx->logger, LOG_BANDWIDTH_CALCS, + "SR_EXIT_WATERMARK_D calculated =%d\n" + "HW register value = 0x%x\n", + watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); + } prog_wm_value = convert_and_clamp( -- GitLab From 58bb0e63dd99c4bdb84e79a95311bb6899789681 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Tue, 10 Oct 2017 14:36:39 -0400 Subject: [PATCH 1364/2898] drm/amd/display: Correct timings in build scaling params A previous patch set the addressable timing as active + border, when in fact, the VESA standard specifies active as equal to addressable + border. This patch makes the fix more correct and in line with the standard. Signed-off-by: Andrew Jiang Reviewed-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 55feb16b1fd7..0aca7a3d3dd6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -850,22 +850,11 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) */ pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; - /** - * KMD sends us h and v_addressable without the borders, which causes us sometimes to draw - * the blank region on-screen. Correct for this by adding the borders back to their - * respective addressable values, and by shifting recout. - */ - timing->h_addressable += timing->h_border_left + timing->h_border_right; - timing->v_addressable += timing->v_border_top + timing->v_border_bottom; - pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; - timing->v_border_top = 0; - timing->v_border_bottom = 0; - timing->h_border_left = 0; - timing->h_border_right = 0; + pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; - pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; - pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; + pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; + pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; /* Taps calculations */ if (pipe_ctx->plane_res.xfm != NULL) -- GitLab From 3e5e22154acfd89810d37aa4b3fac14014eb7ca8 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 11 Oct 2017 14:59:51 -0400 Subject: [PATCH 1365/2898] drm/amd/display: Add chip mask to HDMI retimer/redriver check There were cases where the chip caps held additional bits that led to the retimer/redriver check failing; use the proper mask to ensure that we have only the bits that we care about for the check in question. Signed-off-by: Andrew Jiang Reviewed-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 72e56fbe4a42..004e0b0aad8a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -45,6 +45,7 @@ #include "dce/dce_11_0_enum.h" #include "dce/dce_11_0_sh_mask.h" +#define EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK 0x007C /* Copied from atombios.h */ #define LINK_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ __VA_ARGS__) @@ -1345,7 +1346,6 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); result = true; break; - default: break; } @@ -1682,7 +1682,9 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) is_over_340mhz = true; if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { - if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x2) { + unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps & + EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK; + if (masked_chip_caps == (0x2 << 2)) { /* DP159, Retimer settings */ eng_id = pipe_ctx->stream_res.stream_enc->id; @@ -1693,7 +1695,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) write_i2c_default_retimer_setting(pipe_ctx, is_vga_mode, is_over_340mhz); } - } else if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x1) { + } else if (masked_chip_caps == (0x1 << 2)) { /* PI3EQX1204, Redriver settings */ write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); } -- GitLab From 4e527c01aa7a31b7aad98fa5493944891b69238d Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Wed, 11 Oct 2017 15:12:58 -0400 Subject: [PATCH 1366/2898] drm/amd/display: Add DIGD case when getting retimer settings One of the HDMI ports map to DIGD, which we did not map to DP3 ext HDMI settings. Add the DIGD case so that we can get proper retimer settings from SBIOS for that port. Signed-off-by: Andrew Jiang Reviewed-by: Charlene Liu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 004e0b0aad8a..c47da645d3b8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1346,6 +1346,18 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); result = true; break; + case ENGINE_ID_DIGD: + settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr; + settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num; + settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num; + memmove(settings->reg_settings, + integrated_info->dp3_ext_hdmi_reg_settings, + sizeof(integrated_info->dp3_ext_hdmi_reg_settings)); + memmove(settings->reg_settings_6g, + integrated_info->dp3_ext_hdmi_6g_reg_settings, + sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings)); + result = true; + break; default: break; } -- GitLab From 62c933f9c6bf287b5b911a1eb838bc942eaa7202 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 10 Oct 2017 14:01:33 -0400 Subject: [PATCH 1367/2898] drm/amd/display: WA for 3 display play video hot plug. Three monitor connected and playing a video will occupy all 4 pipes, if hot plug forth display, commit streams will be failed due to no free pipe can be found. Work around: When forth monitor connected, mark video plane as a fake plane, remove it in dc, keep it in dm and report address to OS, until OS turn off MPO. Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++++----- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 14 ++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 6 +++--- drivers/gpu/drm/amd/display/dc/inc/core_status.h | 15 ++++++++------- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 60587d6f81d7..0d1b41298990 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2794,7 +2794,7 @@ int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, stream->src.height = mode->vdisplay; stream->dst = stream->src; - if (dc_validate_stream(adev->dm.dc, stream)) + if (dc_validate_stream(adev->dm.dc, stream) == DC_OK) result = MODE_OK; dc_stream_release(stream); @@ -2839,7 +2839,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, if (!dm_crtc_state->stream) return 0; - if (dc_validate_stream(dc, dm_crtc_state->stream)) + if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK) return 0; return ret; @@ -3034,7 +3034,7 @@ static int dm_plane_atomic_check(struct drm_plane *plane, if (!dm_plane_state->dc_state) return 0; - if (dc_validate_plane(dc, dm_plane_state->dc_state)) + if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK) return 0; return -EINVAL; @@ -4464,10 +4464,10 @@ static int dm_update_crtcs_state(struct dc *dc, crtc->base.id); /* i.e. reset mode */ - if (!dc_remove_stream_from_ctx( + if (dc_remove_stream_from_ctx( dc, dm_state->context, - dm_old_crtc_state->stream)) { + dm_old_crtc_state->stream) != DC_OK) { ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9d750fa29a87..ff6bd384aece 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -793,7 +793,7 @@ bool dc_enable_stereo( * Applies given context to HW and copy it into current context. * It's up to the user to release the src context afterwards. */ -static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) +static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context) { struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status result = DC_ERROR_UNEXPECTED; @@ -869,7 +869,7 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) dc->hwss.optimize_shared_resources(dc); - return (result == DC_OK); + return result; } bool dc_commit_state(struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 0aca7a3d3dd6..d1cdf9f8853d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1503,7 +1503,7 @@ enum dc_status dc_add_stream_to_ctx( return res; } -bool dc_remove_stream_from_ctx( +enum dc_status dc_remove_stream_from_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream) @@ -2756,7 +2756,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, fmt_bit_depth->pixel_encoding = pixel_encoding; } -bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) +enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) { struct dc *core_dc = dc; struct dc_link *link = stream->sink->link; @@ -2780,14 +2780,16 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) link, &stream->timing); - return res == DC_OK; + return res; } -bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) +enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) { + enum dc_status res = DC_OK; + /* TODO For now validates pixel format only */ if (dc->res_pool->funcs->validate_plane) - return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps) == DC_OK; + return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); - return true; + return res; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f60191d9c7e5..6c0de093a59e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -686,7 +686,7 @@ enum dc_status dc_add_stream_to_ctx( struct dc_state *new_ctx, struct dc_stream_state *stream); -bool dc_remove_stream_from_ctx( +enum dc_status dc_remove_stream_from_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream); @@ -725,9 +725,9 @@ struct dc_validation_set { uint8_t plane_count; }; -bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); +enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); -bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); +enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); enum dc_status dc_validate_global_state( struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index b5759c0e5a2f..01df85641684 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -35,13 +35,14 @@ enum dc_status { DC_FAIL_CONTROLLER_VALIDATE = 5, DC_FAIL_ENC_VALIDATE = 6, DC_FAIL_ATTACH_SURFACES = 7, - DC_FAIL_SURFACE_VALIDATE = 8, - DC_NO_DP_LINK_BANDWIDTH = 9, - DC_EXCEED_DONGLE_MAX_CLK = 10, - DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 11, - DC_FAIL_BANDWIDTH_VALIDATE = 12, /* BW and Watermark validation */ - DC_FAIL_SCALING = 13, - DC_FAIL_DP_LINK_TRAINING = 14, + DC_FAIL_DETACH_SURFACES = 8, + DC_FAIL_SURFACE_VALIDATE = 9, + DC_NO_DP_LINK_BANDWIDTH = 10, + DC_EXCEED_DONGLE_MAX_CLK = 11, + DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED = 12, + DC_FAIL_BANDWIDTH_VALIDATE = 13, /* BW and Watermark validation */ + DC_FAIL_SCALING = 14, + DC_FAIL_DP_LINK_TRAINING = 15, DC_ERROR_UNEXPECTED = -1 }; -- GitLab From dd93752b6483094ec879efbbdb854967355b91ac Mon Sep 17 00:00:00 2001 From: Yue Hin Lau Date: Tue, 10 Oct 2017 17:58:41 -0400 Subject: [PATCH 1368/2898] drm/amd/display: rename dscl functions Signed-off-by: Yue Hin Lau Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c | 10 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h | 4 +- .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 98 +++++++++---------- 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 5960e491159d..74e7c82bdc76 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -372,7 +372,7 @@ void dpp1_cnv_setup ( } } -void dcn10_set_cursor_attributes( +void dpp1_set_cursor_attributes( struct dpp *dpp_base, const struct dc_cursor_attributes *attr) { @@ -400,7 +400,7 @@ void dcn10_set_cursor_attributes( } -void dcn10_set_cursor_position( +void dpp1_set_cursor_position( struct dpp *dpp_base, const struct dc_cursor_position *pos, const struct dc_cursor_mi_param *param, @@ -440,13 +440,13 @@ static const struct dpp_funcs dcn10_dpp_funcs = { .ipp_program_degamma_pwl = dpp1_set_degamma_pwl, .ipp_setup = dpp1_cnv_setup, .ipp_full_bypass = dpp1_full_bypass, - .set_cursor_attributes = dcn10_set_cursor_attributes, - .set_cursor_position = dcn10_set_cursor_position, + .set_cursor_attributes = dpp1_set_cursor_attributes, + .set_cursor_position = dpp1_set_cursor_position, }; static struct dpp_caps dcn10_dpp_cap = { .dscl_data_proc_format = DSCL_DATA_PRCESSING_FIXED_FORMAT, - .dscl_calc_lb_num_partitions = dscl1_calc_lb_num_partitions, + .dscl_calc_lb_num_partitions = dpp1_dscl_calc_lb_num_partitions, }; /*****************************************/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h index fe6c0aa13da4..a9782b1aba47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h @@ -1274,12 +1274,12 @@ enum dcn10_input_csc_select { INPUT_CSC_SELECT_COMA }; -bool is_lb_conf_valid( +bool dpp1_dscl_is_lb_conf_valid( int ceil_vratio, int num_partitions, int vtaps); -void dscl1_calc_lb_num_partitions( +void dpp1_dscl_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index b443a90974b9..cbad36410b32 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -85,7 +85,7 @@ enum dscl_mode_sel { DSCL_MODE_DSCL_BYPASS = 6 }; -static void dpp_set_overscan( +static void dpp1_dscl_set_overscan( struct dcn10_dpp *dpp, const struct scaler_data *data) { @@ -113,7 +113,7 @@ static void dpp_set_overscan( EXT_OVERSCAN_TOP, top); } -static void dpp_set_otg_blank( +static void dpp1_dscl_set_otg_blank( struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t h_blank_start = data->h_active; @@ -130,7 +130,7 @@ static void dpp_set_otg_blank( OTG_V_BLANK_END, v_blank_end); } -static int get_pixel_depth_val(enum lb_pixel_depth depth) +static int dpp1_dscl_get_pixel_depth_val(enum lb_pixel_depth depth) { if (depth == LB_PIXEL_DEPTH_30BPP) return 0; /* 10 bpc */ @@ -146,7 +146,7 @@ static int get_pixel_depth_val(enum lb_pixel_depth depth) } } -static bool is_video_format(enum pixel_format format) +static bool dpp1_dscl_is_video_format(enum pixel_format format) { if (format >= PIXEL_FORMAT_VIDEO_BEGIN && format <= PIXEL_FORMAT_VIDEO_END) @@ -155,7 +155,7 @@ static bool is_video_format(enum pixel_format format) return false; } -static bool is_420_format(enum pixel_format format) +static bool dpp1_dscl_is_420_format(enum pixel_format format) { if (format == PIXEL_FORMAT_420BPP8 || format == PIXEL_FORMAT_420BPP10) @@ -164,7 +164,7 @@ static bool is_420_format(enum pixel_format format) return false; } -static enum dscl_mode_sel get_dscl_mode( +static enum dscl_mode_sel dpp1_dscl_get_dscl_mode( struct dpp *dpp_base, const struct scaler_data *data, bool dbg_always_scale) @@ -184,8 +184,8 @@ static enum dscl_mode_sel get_dscl_mode( && !dbg_always_scale) return DSCL_MODE_SCALING_444_BYPASS; - if (!is_420_format(data->format)) { - if (is_video_format(data->format)) + if (!dpp1_dscl_is_420_format(data->format)) { + if (dpp1_dscl_is_video_format(data->format)) return DSCL_MODE_SCALING_444_YCBCR_ENABLE; else return DSCL_MODE_SCALING_444_RGB_ENABLE; @@ -198,7 +198,7 @@ static enum dscl_mode_sel get_dscl_mode( return DSCL_MODE_SCALING_420_YCBCR_ENABLE; } -static void dpp_set_lb( +static void dpp1_dscl_set_lb( struct dcn10_dpp *dpp, const struct line_buffer_params *lb_params, enum lb_memory_config mem_size_config) @@ -206,7 +206,7 @@ static void dpp_set_lb( /* LB */ if (dpp->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) { /* DSCL caps: pixel data processed in fixed format */ - uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth); + uint32_t pixel_depth = dpp1_dscl_get_pixel_depth_val(lb_params->depth); uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth; REG_SET_7(LB_DATA_FORMAT, 0, @@ -224,7 +224,7 @@ static void dpp_set_lb( LB_MAX_PARTITIONS, 63); } -static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) +static const uint16_t *dpp1_dscl_get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) { if (taps == 8) return get_filter_8tap_64p(ratio); @@ -249,7 +249,7 @@ static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) } } -static void dpp_set_scaler_filter( +static void dpp1_dscl_set_scaler_filter( struct dcn10_dpp *dpp, uint32_t taps, enum dcn10_coef_filter_type_sel filter_type, @@ -287,7 +287,7 @@ static void dpp_set_scaler_filter( } -static void dpp_set_scl_filter( +static void dpp1_dscl_set_scl_filter( struct dcn10_dpp *dpp, const struct scaler_data *scl_data, bool chroma_coef_mode) @@ -325,18 +325,18 @@ static void dpp_set_scl_filter( if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) { bool filter_updated = false; - filter_h = get_filter_coeffs_64p( + filter_h = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.h_taps, scl_data->ratios.horz); - filter_v = get_filter_coeffs_64p( + filter_v = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.v_taps, scl_data->ratios.vert); filter_updated = (filter_h && (filter_h != dpp->filter_h)) || (filter_v && (filter_v != dpp->filter_v)); if (chroma_coef_mode) { - filter_h_c = get_filter_coeffs_64p( + filter_h_c = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.h_taps_c, scl_data->ratios.horz_c); - filter_v_c = get_filter_coeffs_64p( + filter_v_c = dpp1_dscl_get_filter_coeffs_64p( scl_data->taps.v_taps_c, scl_data->ratios.vert_c); filter_updated = filter_updated || (filter_h_c && (filter_h_c != dpp->filter_h_c)) || (filter_v_c && (filter_v_c != dpp->filter_v_c)); @@ -346,25 +346,25 @@ static void dpp_set_scl_filter( uint32_t scl_mode = REG_READ(SCL_MODE); if (!h_2tap_hardcode_coef_en && filter_h) { - dpp_set_scaler_filter( + dpp1_dscl_set_scaler_filter( dpp, scl_data->taps.h_taps, SCL_COEF_LUMA_HORZ_FILTER, filter_h); } dpp->filter_h = filter_h; if (!v_2tap_hardcode_coef_en && filter_v) { - dpp_set_scaler_filter( + dpp1_dscl_set_scaler_filter( dpp, scl_data->taps.v_taps, SCL_COEF_LUMA_VERT_FILTER, filter_v); } dpp->filter_v = filter_v; if (chroma_coef_mode) { if (!h_2tap_hardcode_coef_en && filter_h_c) { - dpp_set_scaler_filter( + dpp1_dscl_set_scaler_filter( dpp, scl_data->taps.h_taps_c, SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c); } if (!v_2tap_hardcode_coef_en && filter_v_c) { - dpp_set_scaler_filter( + dpp1_dscl_set_scaler_filter( dpp, scl_data->taps.v_taps_c, SCL_COEF_CHROMA_VERT_FILTER, filter_v_c); } @@ -384,7 +384,7 @@ static void dpp_set_scl_filter( } } -static int get_lb_depth_bpc(enum lb_pixel_depth depth) +static int dpp1_dscl_get_lb_depth_bpc(enum lb_pixel_depth depth) { if (depth == LB_PIXEL_DEPTH_30BPP) return 10; @@ -400,7 +400,7 @@ static int get_lb_depth_bpc(enum lb_pixel_depth depth) } } -void dscl1_calc_lb_num_partitions( +void dpp1_dscl_calc_lb_num_partitions( const struct scaler_data *scl_data, enum lb_memory_config lb_config, int *num_part_y, @@ -410,7 +410,7 @@ void dscl1_calc_lb_num_partitions( scl_data->viewport.width : scl_data->recout.width; int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? scl_data->viewport_c.width : scl_data->recout.width; - int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth); + int lb_bpc = dpp1_dscl_get_lb_depth_bpc(scl_data->lb_params.depth); int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */ int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */ int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ @@ -449,7 +449,7 @@ void dscl1_calc_lb_num_partitions( } -bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) +bool dpp1_dscl_is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) { if (ceil_vratio > 2) return vtaps <= (num_partitions - ceil_vratio + 2); @@ -458,7 +458,7 @@ bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps) } /*find first match configuration which meets the min required lb size*/ -static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, +static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *dpp, const struct scaler_data *scl_data) { int num_part_y, num_part_c; @@ -474,15 +474,15 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_1; dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_2; if (scl_data->format == PIXEL_FORMAT_420BPP8 @@ -490,8 +490,8 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); - if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) + if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_3; } @@ -499,34 +499,34 @@ static enum lb_memory_config find_lb_memory_config(struct dcn10_dpp *dpp, scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c); /*Ensure we can support the requested number of vtaps*/ - ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) - && is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); + ASSERT(dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps) + && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)); return LB_MEMORY_CONFIG_0; } -void dpp_set_scaler_auto_scale( +void dpp1_dscl_set_scaler_auto_scale( struct dpp *dpp_base, const struct scaler_data *scl_data) { enum lb_memory_config lb_config; struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( + enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode( dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; - dpp_set_overscan(dpp, scl_data); + dpp1_dscl_set_overscan(dpp, scl_data); - dpp_set_otg_blank(dpp, scl_data); + dpp1_dscl_set_otg_blank(dpp, scl_data); REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode); if (dscl_mode == DSCL_MODE_DSCL_BYPASS) return; - lb_config = find_lb_memory_config(dpp, scl_data); - dpp_set_lb(dpp, &scl_data->lb_params, lb_config); + lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data); + dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -554,11 +554,11 @@ void dpp_set_scaler_auto_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(dpp, scl_data, ycbcr); + dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr); } -static void dpp_set_manual_ratio_init( +static void dpp1_dscl_set_manual_ratio_init( struct dcn10_dpp *dpp, const struct scaler_data *data) { uint32_t init_frac = 0; @@ -618,7 +618,7 @@ static void dpp_set_manual_ratio_init( -static void dpp_set_recout( +static void dpp1_dscl_set_recout( struct dcn10_dpp *dpp, const struct rect *recout) { REG_SET_2(RECOUT_START, 0, @@ -643,13 +643,13 @@ void dpp1_dscl_set_scaler_manual_scale( { enum lb_memory_config lb_config; struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - enum dscl_mode_sel dscl_mode = get_dscl_mode( + enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode( dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale); bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN && scl_data->format <= PIXEL_FORMAT_VIDEO_END; /* Recout */ - dpp_set_recout(dpp, &scl_data->recout); + dpp1_dscl_set_recout(dpp, &scl_data->recout); /* MPC Size */ REG_SET_2(MPC_SIZE, 0, @@ -665,8 +665,8 @@ void dpp1_dscl_set_scaler_manual_scale( return; /* LB */ - lb_config = find_lb_memory_config(dpp, scl_data); - dpp_set_lb(dpp, &scl_data->lb_params, lb_config); + lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data); + dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config); if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) return; @@ -689,7 +689,7 @@ void dpp1_dscl_set_scaler_manual_scale( SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y); /* Manually calculate scale ratio and init values */ - dpp_set_manual_ratio_init(dpp, scl_data); + dpp1_dscl_set_manual_ratio_init(dpp, scl_data); /* HTaps/VTaps */ REG_SET_4(SCL_TAP_CONTROL, 0, @@ -698,5 +698,5 @@ void dpp1_dscl_set_scaler_manual_scale( SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1, SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1); - dpp_set_scl_filter(dpp, scl_data, ycbcr); + dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr); } -- GitLab From 6b29f4424e39d279fa1c7b465bc1b508ea6fc98e Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 12 Oct 2017 10:59:42 -0400 Subject: [PATCH 1369/2898] drm/amd/display: DAL 3.1.06 Raven bug fixes - RS3 MPO stability improvement - SLS fixes - AM4 fixes DAL 3.1 - merge in upstream patches from DRM maintainer Dave Arilie - hubp, dpp HW objects Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6c0de093a59e..37a779ead4fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,8 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.05" +#define DC_VER "3.1.06" + #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- GitLab From b9b171fffc9358be9e98cbc2bc7ef3fbe029f170 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 10 Oct 2017 16:28:02 -0400 Subject: [PATCH 1370/2898] drm/amd/display: LGD panel willl flash line under window Signed-off-by: Hersen Wu Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 5e5763c0ee94..e8b8daeeed97 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1399,6 +1399,15 @@ static void power_down_encoders(struct dc *dc) int i; enum connector_id connector_id; enum signal_type signal = SIGNAL_TYPE_NONE; + + /* do not know BIOS back-front mapping, simply blank all. It will not + * hurt for non-DP + */ + for (i = 0; i < dc->res_pool->stream_enc_count; i++) { + dc->res_pool->stream_enc[i]->funcs->dp_blank( + dc->res_pool->stream_enc[i]); + } + for (i = 0; i < dc->link_count; i++) { connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || -- GitLab From 75e68891200e3404fb3283e47ed74184932a748a Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 12 Oct 2017 12:27:48 -0400 Subject: [PATCH 1371/2898] drm/amd/display: Move OS types to os_types.h Some of this stuff is not really dm_services Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 45 -------------------- drivers/gpu/drm/amd/display/dc/os_types.h | 40 +++++++++++++++++ 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index d6b3b832986b..c8190c38a644 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -38,51 +38,6 @@ #undef DEPRECATED -/* - * - * general debug capabilities - * - */ -#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) - -#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) -#define ASSERT_CRITICAL(expr) do { \ - if (WARN_ON(!(expr))) { \ - kgdb_breakpoint(); \ - } \ -} while (0) -#else -#define ASSERT_CRITICAL(expr) do { \ - if (WARN_ON(!(expr))) { \ - ; \ - } \ -} while (0) -#endif - -#if defined(CONFIG_DEBUG_KERNEL_DC) -#define ASSERT(expr) ASSERT_CRITICAL(expr) - -#else -#define ASSERT(expr) WARN_ON(!(expr)) -#endif - -#define BREAK_TO_DEBUGGER() ASSERT(0) - -#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ - -#define DC_ERR(...) do { \ - dm_error(__VA_ARGS__); \ - BREAK_TO_DEBUGGER(); \ -} while (0) - -#if defined(CONFIG_DRM_AMD_DC_DCN1_0) -#include -#endif - -#define dm_alloc(size) kzalloc(size, GFP_KERNEL) -#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL) -#define dm_free(ptr) kfree(ptr) - irq_handler_idx dm_register_interrupt( struct dc_context *ctx, struct dc_interrupt_params *int_params, diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index e0cd5278aae8..86170b40b5c5 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -56,5 +56,45 @@ #endif +/* + * + * general debug capabilities + * + */ +#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) + +#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + kgdb_breakpoint(); \ + } \ +} while (0) +#else +#define ASSERT_CRITICAL(expr) do { \ + if (WARN_ON(!(expr))) { \ + ; \ + } \ +} while (0) +#endif + +#if defined(CONFIG_DEBUG_KERNEL_DC) +#define ASSERT(expr) ASSERT_CRITICAL(expr) + +#else +#define ASSERT(expr) WARN_ON(!(expr)) +#endif + +#define BREAK_TO_DEBUGGER() ASSERT(0) + +#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ + +#define DC_ERR(...) do { \ + dm_error(__VA_ARGS__); \ + BREAK_TO_DEBUGGER(); \ +} while (0) + +#if defined(CONFIG_DRM_AMD_DC_DCN1_0) +#include +#endif #endif /* _OS_TYPES_H_ */ -- GitLab From 1bed4d09a4cc5a7d4449da86832d9bd816ae44ff Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Sep 2017 17:10:25 +0100 Subject: [PATCH 1372/2898] drm/amd/display: Fix one more place for dc_stream_state leak One more thing that happened due to uneven applying of patches. This mirrors what Darren Salt fixed. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0d1b41298990..58143fe49e4a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4484,7 +4484,7 @@ static int dm_update_crtcs_state(struct dc *dc, * TODO: need to dig out the root cause of that */ if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port)) - continue; + goto next_crtc; if (modereset_required(new_crtc_state)) goto next_crtc; -- GitLab From bb16bee4b394bafd6168c7719b7b07e19d1f0ce1 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 12 Oct 2017 14:15:26 -0400 Subject: [PATCH 1373/2898] drm/amd/display: Reduce stack size of commit_planes_to_stream This function likes to blow 1024 stack size when something is added to the addr struct. For now just dynamically allocate. Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ff6bd384aece..7a0593d4ca62 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -926,9 +926,9 @@ bool dc_commit_planes_to_stream( struct dc_state *state) { struct dc_surface_update updates[MAX_SURFACES]; - struct dc_flip_addrs flip_addr[MAX_SURFACES]; - struct dc_plane_info plane_info[MAX_SURFACES]; - struct dc_scaling_info scaling_info[MAX_SURFACES]; + struct dc_flip_addrs *flip_addr; + struct dc_plane_info *plane_info; + struct dc_scaling_info *scaling_info; int i; struct dc_stream_update *stream_update = kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL); @@ -938,10 +938,14 @@ bool dc_commit_planes_to_stream( return false; } + flip_addr = kcalloc(MAX_SURFACES, sizeof(struct dc_flip_addrs), + GFP_KERNEL); + plane_info = kcalloc(MAX_SURFACES, sizeof(struct dc_plane_info), + GFP_KERNEL); + scaling_info = kcalloc(MAX_SURFACES, sizeof(struct dc_scaling_info), + GFP_KERNEL); + memset(updates, 0, sizeof(updates)); - memset(flip_addr, 0, sizeof(flip_addr)); - memset(plane_info, 0, sizeof(plane_info)); - memset(scaling_info, 0, sizeof(scaling_info)); stream_update->src = dc_stream->src; stream_update->dst = dc_stream->dst; @@ -980,6 +984,9 @@ bool dc_commit_planes_to_stream( new_plane_count, dc_stream, stream_update, plane_states, state); + kfree(flip_addr); + kfree(plane_info); + kfree(scaling_info); kfree(stream_update); return true; } -- GitLab From 9e7da3268aedd21d559f0f27406874cf92ff582a Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 12 Oct 2017 22:18:12 -0400 Subject: [PATCH 1374/2898] drm/amd/display: dal 3.1.07 - regression fixes in dal 3.1.06 - more linux upstream backport Signed-off-by: Tony Cheng Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 37a779ead4fb..9d8f4a55c74e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,8 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.06" - +#define DC_VER "3.1.07" #define MAX_SURFACES 3 #define MAX_STREAMS 6 -- GitLab From be11749177d74b2e2c8a4cf2526e88355c40ad00 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 13 Oct 2017 15:12:04 -0400 Subject: [PATCH 1375/2898] drm/amd/display: Remove redundant condition in dml vba Found by 0-day https://lists.freedesktop.org/archives/dri-devel/2017-October/154698.html Signed-off-by: Harry Wentland Reviewed-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index a11b37c50d96..117ec11ef304 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -3463,7 +3463,7 @@ bool Calculate256BBlockSizes( unsigned int *BlockWidth256BytesC) { if ((SourcePixelFormat == dm_444_64 || SourcePixelFormat == dm_444_32 - || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16 + || SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_8)) { if (SurfaceTiling == dm_sw_linear) { *BlockHeight256BytesY = 1; -- GitLab From e92b44fdee3ec0b679bacdb9c7e95e55699167f0 Mon Sep 17 00:00:00 2001 From: Tony Cheng Date: Thu, 5 Oct 2017 14:38:46 -0400 Subject: [PATCH 1376/2898] drm/amd/display: default force_single_disp_pipe_split = 1 on RV 1080p idle, stutter efficiency goes up from 95.8% to 97.8% result in 5mW saving from APU and 8mW saving from DDR4 Signed-off-by: Tony Cheng Reviewed-by: Yongqiang Sun Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index d47ff7e6a525..d911590d08bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -430,6 +430,7 @@ static const struct dc_debug debug_defaults_drv = { .disable_pplib_wm_range = false, .pplib_wm_report_mode = WM_REPORT_DEFAULT, .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, + .force_single_disp_pipe_split = true, .disable_dcc = DCC_ENABLE, .voltage_align_fclk = true, .disable_stereo_support = true, -- GitLab From f63d89066fb29a47ad3e9530214de7ea87e82e57 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 13 Oct 2017 12:53:38 -0400 Subject: [PATCH 1377/2898] drm/amd/display: change dml numdpp var to uint Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml/display_mode_vba.c | 14 +++++++------- .../gpu/drm/amd/display/dc/dml/display_mode_vba.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 117ec11ef304..ffd1d8d10bdf 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -1158,7 +1158,7 @@ static bool CalculatePrefetchSchedule( else if (PageTableLevels == 3) *Tno_bw = UrgentExtraLatency; else - Tno_bw = 0; + *Tno_bw = 0; } else if (DCCEnable) *Tno_bw = LineTime; else @@ -4721,14 +4721,14 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ && mode_lib->vba.SwathWidthYSingleDPP[k] <= mode_lib->vba.MaximumSwathWidth[k] && mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { - mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.NoOfDPP[i][k] = 1; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } else { - mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.NoOfDPP[i][k] = 2; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 @@ -4790,14 +4790,14 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ <= mode_lib->vba.MaximumSwathWidth[k] && mode_lib->vba.ODMCombineEnablePerState[i][k] == false) { - mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.NoOfDPP[i][k] = 1; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } else { - mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.NoOfDPP[i][k] = 2; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 @@ -4833,14 +4833,14 @@ static void ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_ mode_lib->vba.ODMCombineEnablePerState[i][k] = false; if (mode_lib->vba.SwathWidthYSingleDPP[k] <= mode_lib->vba.MaximumSwathWidth[k]) { - mode_lib->vba.NoOfDPP[i][k] = 1.0; + mode_lib->vba.NoOfDPP[i][k] = 1; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } else { - mode_lib->vba.NoOfDPP[i][k] = 2.0; + mode_lib->vba.NoOfDPP[i][k] = 2; mode_lib->vba.RequiredDPPCLK[i][k] = mode_lib->vba.MinDPPCLKUsingSingleDPP[k] * (1.0 diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 63ad4a7bfeb5..4b8c1b911f17 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -489,7 +489,7 @@ struct vba_vars_st { double CursorBufferSize; double CursorChunkSize; unsigned int Mode; - double NoOfDPP[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; + unsigned int NoOfDPP[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; double OutputLinkDPLanes[DC__NUM_DPP__MAX]; double SwathWidthYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; double SwathHeightYPerState[DC__VOLTAGE_STATES + 1][DC__NUM_DPP__MAX]; -- GitLab From 3eea71e36fcd04d0a3e735ee3cf4dbbe9934e3c8 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 12 Oct 2017 22:45:25 -0400 Subject: [PATCH 1378/2898] drm/amd/display: Minor update to DML Signed-off-by: Dmytro Laktyushkin Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 3 ++- drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c | 6 ------ drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h | 1 - .../gpu/drm/amd/display/dc/dml/display_mode_structs.h | 7 ++----- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 9 +-------- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h | 1 - 6 files changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 741b5e06d314..63c2f5266142 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2015,10 +2015,11 @@ static void dcn10_power_on_fe( plane_state->dst_rect.height); dm_logger_write(dc->ctx->logger, LOG_DC, - "Pipe %d: width, height, x, y\n" + "Pipe %d: width, height, x, y format:%d\n" "viewport:%d, %d, %d, %d\n" "recout: %d, %d, %d, %d\n", pipe_ctx->pipe_idx, + plane_state->format, pipe_ctx->plane_res.scl_data.viewport.width, pipe_ctx->plane_res.scl_data.viewport.height, pipe_ctx->plane_res.scl_data.viewport.x, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index 09d232806de7..4c31fa54af39 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -127,17 +127,11 @@ static void set_ip_params(struct _vcs_dpi_ip_params_st *ip, enum dml_project pro } } -static void set_mode_evaluation(struct _vcs_dpi_mode_evaluation_st *me, enum dml_project project) -{ - me->voltage_override = dm_vmin; -} - void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) { if (lib->project != project) { set_soc_bounding_box(&lib->soc, project); set_ip_params(&lib->ip, project); - set_mode_evaluation(&lib->me, project); lib->project = project; } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index ed77f96016dd..26f4f2a3d90d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -40,7 +40,6 @@ enum dml_project { struct display_mode_lib { struct _vcs_dpi_ip_params_st ip; struct _vcs_dpi_soc_bounding_box_st soc; - struct _vcs_dpi_mode_evaluation_st me; enum dml_project project; struct vba_vars_st vba; struct dal_logger *logger; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 27e20460c71b..baf182177736 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -27,7 +27,6 @@ typedef struct _vcs_dpi_voltage_scaling_st voltage_scaling_st; typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st; -typedef struct _vcs_dpi_mode_evaluation_st mode_evaluation_st; typedef struct _vcs_dpi_ip_params_st ip_params_st; typedef struct _vcs_dpi_display_pipe_source_params_st display_pipe_source_params_st; typedef struct _vcs_dpi_display_output_params_st display_output_params_st; @@ -60,10 +59,6 @@ typedef struct _vcs_dpi_display_dlg_prefetch_param_st display_dlg_prefetch_param typedef struct _vcs_dpi_display_pipe_clock_st display_pipe_clock_st; typedef struct _vcs_dpi_display_arb_params_st display_arb_params_st; -struct _vcs_dpi_mode_evaluation_st { - int voltage_override; -}; - struct _vcs_dpi_voltage_scaling_st { int state; double dscclk_mhz; @@ -96,6 +91,7 @@ struct _vcs_dpi_soc_bounding_box_st { double fabric_datapath_to_dcn_data_return_bytes; double dcn_downspread_percent; double dispclk_dppclk_vco_speed_mhz; + double dfs_vco_period_ps; unsigned int round_trip_ping_latency_dcfclk_cycles; unsigned int urgent_out_of_order_return_per_channel_bytes; unsigned int channel_interleave_bytes; @@ -105,6 +101,7 @@ struct _vcs_dpi_soc_bounding_box_st { double dram_clock_change_latency_us; double writeback_dram_clock_change_latency_us; unsigned int return_bus_width_bytes; + unsigned int voltage_override; double xfc_bus_transport_time_us; double xfc_xbuf_latency_tolerance_us; struct _vcs_dpi_voltage_scaling_st clock_limits[7]; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index ffd1d8d10bdf..e337c2cf2c09 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -251,19 +251,14 @@ unsigned int dml_get_voltage_level( const display_e2e_pipe_params_st *pipes, unsigned int num_pipes) { - bool need_recalculate = memcmp( - &mode_lib->soc, - &mode_lib->vba.soc, - sizeof(mode_lib->vba.soc)) != 0 + bool need_recalculate = memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 - || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 || num_pipes != mode_lib->vba.cache_num_pipes || memcmp(pipes, mode_lib->vba.cache_pipes, sizeof(display_e2e_pipe_params_st) * num_pipes) != 0; mode_lib->vba.soc = mode_lib->soc; mode_lib->vba.ip = mode_lib->ip; - mode_lib->vba.me = mode_lib->me; memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); mode_lib->vba.cache_num_pipes = num_pipes; @@ -772,7 +767,6 @@ static void recalculate_params( // This is only safe to use memcmp because there are non-POD types in struct display_mode_lib if (memcmp(&mode_lib->soc, &mode_lib->vba.soc, sizeof(mode_lib->vba.soc)) != 0 || memcmp(&mode_lib->ip, &mode_lib->vba.ip, sizeof(mode_lib->vba.ip)) != 0 - || memcmp(&mode_lib->me, &mode_lib->vba.me, sizeof(mode_lib->vba.me)) != 0 || num_pipes != mode_lib->vba.cache_num_pipes || memcmp( pipes, @@ -780,7 +774,6 @@ static void recalculate_params( sizeof(display_e2e_pipe_params_st) * num_pipes) != 0) { mode_lib->vba.soc = mode_lib->soc; mode_lib->vba.ip = mode_lib->ip; - mode_lib->vba.me = mode_lib->me; memcpy(mode_lib->vba.cache_pipes, pipes, sizeof(*pipes) * num_pipes); mode_lib->vba.cache_num_pipes = num_pipes; recalculate(mode_lib); diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 4b8c1b911f17..c8d1a0539541 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -98,7 +98,6 @@ bool Calculate256BBlockSizes( struct vba_vars_st { ip_params_st ip; soc_bounding_box_st soc; - mode_evaluation_st me; unsigned int MaximumMaxVStartupLines; double cursor_bw[DC__NUM_DPP__MAX]; -- GitLab From 565f26a39d8e49745fda00d2303138aea831fd29 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 20:10:00 -0400 Subject: [PATCH 1379/2898] drm/amd/display: Small comment on dc_commit_planes_to_stream Having one struct on the stack was somewhat confusing. Also mention that the whole function should eventually go. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7a0593d4ca62..a71392ffc46d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -918,6 +918,12 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) return true; } +/* + * TODO this whole function needs to go + * + * dc_surface_update is needlessly complex. See if we can just replace this + * with a dc_plane_state and follow the atomic model a bit more closely here. + */ bool dc_commit_planes_to_stream( struct dc *dc, struct dc_plane_state **plane_states, @@ -925,6 +931,7 @@ bool dc_commit_planes_to_stream( struct dc_stream_state *dc_stream, struct dc_state *state) { + /* no need to dynamically allocate this. it's pretty small */ struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs *flip_addr; struct dc_plane_info *plane_info; -- GitLab From 16b2f2ed5f2ece5bf44d94883412048856ca2966 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 28 Sep 2017 10:45:26 +1000 Subject: [PATCH 1380/2898] amdgpu/dc: inline a bunch of the dml wrappers. This reduces the code size. This is basically a redo of Dave's change with the same name on top of the latest DML. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/display_mode_vba.c | 2 + .../amd/display/dc/dml/display_rq_dlg_calc.c | 2 + .../display/dc/dml/dml1_display_rq_dlg_calc.c | 2 + .../drm/amd/display/dc/dml/dml_common_defs.c | 67 +----------- .../drm/amd/display/dc/dml/dml_common_defs.h | 14 --- .../drm/amd/display/dc/dml/dml_inline_defs.h | 102 ++++++++++++++++++ .../drm/amd/display/dc/dml/soc_bounding_box.c | 1 + 7 files changed, 110 insertions(+), 80 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index e337c2cf2c09..f51a36449410 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -1,6 +1,8 @@ #include "display_mode_lib.h" #include "display_mode_vba.h" +#include "dml_inline_defs.h" + static const unsigned int NumberOfStates = DC__VOLTAGE_STATES; static void fetch_socbb_params(struct display_mode_lib *mode_lib); diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c index 657b7386021d..8ba962df42e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -39,6 +39,8 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, unsigned int cur_width, enum cursor_bpp cur_bpp); +#include "dml_inline_defs.h" + static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 8229f782260b..1e4b1e383401 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -26,6 +26,8 @@ #include "dml1_display_rq_dlg_calc.h" #include "display_mode_lib.h" +#include "dml_inline_defs.h" + static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) { unsigned int ret_val = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 2af6d150cc46..101fb6f19c43 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -26,37 +26,7 @@ #include "dml_common_defs.h" #include "../calcs/dcn_calc_math.h" -double dml_min(double a, double b) -{ - return (double) dcn_bw_min2(a, b); -} - -double dml_max(double a, double b) -{ - return (double) dcn_bw_max2(a, b); -} -double dml_max3(double a, double b, double c) -{ - return dml_max(dml_max(a, b), c); -} -double dml_max4(double a, double b, double c, double d) -{ - return dml_max(dml_max(a, b), dml_max(c, d)); -} -double dml_max5(double a, double b, double c, double d, double e) -{ - return dml_max(dml_max4(a, b, c, d), e); -} - -double dml_ceil(double a, double granularity) -{ - return (double) dcn_bw_ceil2(a, granularity); -} - -double dml_floor(double a, double granularity) -{ - return (double) dcn_bw_floor2(a, granularity); -} +#include "dml_inline_defs.h" double dml_round(double a) { @@ -70,16 +40,6 @@ double dml_round(double a) return floor; } -int dml_log2(double x) -{ - return dml_round((double)dcn_bw_log(x, 2)); -} - -double dml_pow(double a, int exp) -{ - return (double) dcn_bw_pow(a, exp); -} - unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, @@ -101,16 +61,6 @@ unsigned int dml_round_to_multiple( return (num - remainder); } -double dml_fmod(double f, int val) -{ - return (double) dcn_bw_mod(f, val); -} - -double dml_ceil_2(double f) -{ - return (double) dcn_bw_ceil2(f, 2); -} - bool dml_util_is_420(enum source_format_class sorce_format) { bool val = false; @@ -143,18 +93,3 @@ bool dml_util_is_420(enum source_format_class sorce_format) return val; } - -double dml_ceil_ex(double x, double granularity) -{ - return (double) dcn_bw_ceil2(x, granularity); -} - -double dml_floor_ex(double x, double granularity) -{ - return (double) dcn_bw_floor2(x, granularity); -} - -double dml_log(double x, double base) -{ - return (double) dcn_bw_log(x, base); -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index ba01bbb007fc..a55f4d5af36c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -34,23 +34,9 @@ #define dml_print(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } #define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } -double dml_min(double a, double b); -double dml_max(double a, double b); -double dml_max3(double a, double b, double c); -double dml_max4(double a, double b, double c, double d); -double dml_max5(double a, double b, double c, double d, double e); bool dml_util_is_420(enum source_format_class sorce_format); -double dml_ceil_ex(double x, double granularity); -double dml_floor_ex(double x, double granularity); -double dml_log(double x, double base); -double dml_ceil(double a, double granularity); -double dml_floor(double a, double granularity); double dml_round(double a); -int dml_log2(double x); -double dml_pow(double a, int exp); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -double dml_fmod(double f, int val); -double dml_ceil_2(double f); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h new file mode 100644 index 000000000000..105c6721f901 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DML_INLINE_DEFS_H__ +#define __DML_INLINE_DEFS_H__ + +#include "dml_common_defs.h" +#include "../calcs/dcn_calc_math.h" + +static inline double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +static inline double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +static inline double dml_max3(double a, double b, double c) +{ + return dml_max(dml_max(a, b), c); +} + +static inline double dml_max4(double a, double b, double c, double d) +{ + return dml_max(dml_max(a, b), dml_max(c, d)); +} + +static inline double dml_max5(double a, double b, double c, double d, double e) +{ + return dml_max(dml_max4(a, b, c, d), e); +} + +static inline double dml_ceil(double a, double granularity) +{ + return (double) dcn_bw_ceil2(a, granularity); +} + +static inline double dml_floor(double a, double granularity) +{ + return (double) dcn_bw_floor2(a, granularity); +} + +static inline int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +static inline double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + +static inline double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +static inline double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + +static inline double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +static inline double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +static inline double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c index 8b8512528af5..bc7d8c707221 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -26,6 +26,7 @@ #include "display_mode_lib.h" #include "dc_features.h" +#include "dml_inline_defs.h" void dml_socbb_set_latencies(soc_bounding_box_st *to_box, soc_bounding_box_st *from_box) { to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; -- GitLab From c6ca4496177d89e3f6eef7d7b6200798b19250ee Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Oct 2017 22:58:18 -0400 Subject: [PATCH 1381/2898] drm/amd/display: Add bunch of missing license headers in DML All files should have MIT headers. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/display_mode_vba.c | 25 +++++++++++++++++++ .../drm/amd/display/dc/dml/display_mode_vba.h | 24 +++++++++++++++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index f51a36449410..ea661ee44674 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -1,3 +1,28 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + #include "display_mode_lib.h" #include "display_mode_vba.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index c8d1a0539541..4112409cd974 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -1,8 +1,26 @@ /* - * display_mode_vba.h + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD * - * Created on: Aug 18, 2017 - * Author: dlaktyus */ #ifndef __DML2_DISPLAY_MODE_VBA_H__ -- GitLab From b2484b6237ef3ed60af0400027c053ec973b60cc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 28 Sep 2017 10:55:25 +1000 Subject: [PATCH 1382/2898] amdgpu/dc: drop dml_util_is_420 This is unused code. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/dml_common_defs.c | 33 ------------------- .../drm/amd/display/dc/dml/dml_common_defs.h | 1 - 2 files changed, 34 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 101fb6f19c43..1683514ed0e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -60,36 +60,3 @@ unsigned int dml_round_to_multiple( else return (num - remainder); } - -bool dml_util_is_420(enum source_format_class sorce_format) -{ - bool val = false; - - switch (sorce_format) { - case dm_444_16: - val = false; - break; - case dm_444_32: - val = false; - break; - case dm_444_64: - val = false; - break; - case dm_420_8: - val = true; - break; - case dm_420_10: - val = true; - break; - case dm_422_8: - val = false; - break; - case dm_422_10: - val = false; - break; - default: - BREAK_TO_DEBUGGER(); - } - - return val; -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index a55f4d5af36c..e11d123ab8d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -34,7 +34,6 @@ #define dml_print(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } #define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } -bool dml_util_is_420(enum source_format_class sorce_format); double dml_round(double a); unsigned int dml_round_to_multiple( unsigned int num, unsigned int multiple, bool up); -- GitLab From 299f27fd370f34cb6e22e2ffb84b61e91dd6a4c1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 29 Sep 2017 17:13:31 +1000 Subject: [PATCH 1383/2898] amdgpu/dc: inline dml_round_to_multiple turns out to be a win to inline this. Signed-off-by: Dave Airlie Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/dml_common_defs.c | 19 ------------------- .../drm/amd/display/dc/dml/dml_common_defs.h | 2 -- .../drm/amd/display/dc/dml/dml_inline_defs.h | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c index 1683514ed0e3..b953b02a1512 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -40,23 +40,4 @@ double dml_round(double a) return floor; } -unsigned int dml_round_to_multiple( - unsigned int num, - unsigned int multiple, - bool up) -{ - unsigned int remainder; - - if (multiple == 0) - return num; - - remainder = num % multiple; - if (remainder == 0) - return num; - - if (up) - return (num + multiple - remainder); - else - return (num - remainder); -} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h index e11d123ab8d9..b2847bc469fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -35,7 +35,5 @@ #define DTRACE(str, ...) {dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); } double dml_round(double a); -unsigned int dml_round_to_multiple( - unsigned int num, unsigned int multiple, bool up); #endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h index 105c6721f901..e68086b8a22f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h @@ -99,4 +99,23 @@ static inline double dml_log(double x, double base) return (double) dcn_bw_log(x, base); } +static inline unsigned int dml_round_to_multiple(unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} #endif -- GitLab From 33be2785477e470087ea1c5b203881d644cdb0f3 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 08:47:25 -0400 Subject: [PATCH 1384/2898] drm/amd/display: Simplify dm_late_init() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 58143fe49e4a..d8fcf24a041e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -538,9 +538,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) static int dm_late_init(void *handle) { struct drm_device *dev = ((struct amdgpu_device *)handle)->ddev; - int r = detect_mst_link_for_all_connectors(dev); - return r; + return detect_mst_link_for_all_connectors(dev); } static void s3_handle_mst(struct drm_device *dev, bool suspend) -- GitLab From 32f5062d1c7dc2a4d974bb10cf67a98043d9c901 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 08:48:44 -0400 Subject: [PATCH 1385/2898] drm/amd/display: Fix indentation in dm_suspend() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d8fcf24a041e..893213b9c11e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -598,10 +598,7 @@ static int dm_suspend(void *handle) WARN_ON(adev->dm.cached_state); adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); - dc_set_power_state( - dm->dc, - DC_ACPI_CM_POWER_STATE_D3 - ); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); return ret; } -- GitLab From 1fb0c9ccb311cdf16f6ec617fb30c249888c5f97 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 08:49:13 -0400 Subject: [PATCH 1386/2898] drm/amd/display: Fix indentation in dm_resume() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 893213b9c11e..a7bbd22e8f12 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -628,10 +628,7 @@ static int dm_resume(void *handle) struct amdgpu_display_manager *dm = &adev->dm; /* power on hardware */ - dc_set_power_state( - dm->dc, - DC_ACPI_CM_POWER_STATE_D0 - ); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); return 0; } -- GitLab From 900b3cb1833883de9be62e48ff748663c7b6ef96 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 08:59:18 -0400 Subject: [PATCH 1387/2898] drm/amd/display: Fix brace style in amdgpu_dm_update_connector_after_detect() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a7bbd22e8f12..7999eadddd75 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -890,9 +890,9 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) connector); aconnector->dc_sink = sink; - if (sink->dc_edid.length == 0) + if (sink->dc_edid.length == 0) { aconnector->edid = NULL; - else { + } else { aconnector->edid = (struct edid *) sink->dc_edid.raw_edid; -- GitLab From d4a6e8a90ffa281918d9ba75a08f1f917c7eb183 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 09:00:33 -0400 Subject: [PATCH 1388/2898] drm/amd/display: Fix brace style in dm_handle_hpd_rx_irq() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7999eadddd75..2b57bfc8ec40 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1010,8 +1010,9 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) dpcd_bytes_to_read); new_irq_handled = false; - } else + } else { break; + } } if (process_count == max_process_count) -- GitLab From 53cbf65c145450e35fbca50a33c56f5a066e3fe8 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 09:04:25 -0400 Subject: [PATCH 1389/2898] drm/amd/display: Simplify handle_hpd_rx_irq() There is a local reference to the dc_link that wasn't being used so we shorten references throughout the function. Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2b57bfc8ec40..bb83da6fd31b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1024,20 +1024,20 @@ static void handle_hpd_rx_irq(void *param) struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; - const struct dc_link *dc_link = aconnector->dc_link; + struct dc_link *dc_link = aconnector->dc_link; bool is_mst_root_connector = aconnector->mst_mgr.mst_state; /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio * conflict, after implement i2c helper, this mutex should be * retired. */ - if (aconnector->dc_link->type != dc_connection_mst_branch) + if (dc_link->type != dc_connection_mst_branch) mutex_lock(&aconnector->hpd_lock); - if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && + if (dc_link_handle_hpd_rx_irq(dc_link, NULL) && !is_mst_root_connector) { /* Downstream Port status changed. */ - if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPDRX)) { + if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -1049,10 +1049,10 @@ static void handle_hpd_rx_irq(void *param) } } if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - (dc_link->type == dc_connection_mst_branch)) + (dc_link->type == dc_connection_mst_branch)) dm_handle_hpd_rx_irq(aconnector); - if (aconnector->dc_link->type != dc_connection_mst_branch) + if (dc_link->type != dc_connection_mst_branch) mutex_unlock(&aconnector->hpd_lock); } -- GitLab From 8440c30463f3c6d312a5a65be634e6c6c1b6a5b3 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 09:09:42 -0400 Subject: [PATCH 1390/2898] drm/amd/display: Fix brace style in amdgpu_dm_initialize_drm_device() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index bb83da6fd31b..fb24ba69b2a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1412,9 +1412,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail_free_planes; aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); - if (!aencoder) { + if (!aencoder) goto fail_free_connector; - } if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { DRM_ERROR("KMS: Failed to initialize encoder\n"); -- GitLab From d2b2562c23e5e2a122a73627b0c658c5cfedb01a Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 09:46:54 -0400 Subject: [PATCH 1391/2898] drm/amd/display: Replace block with strncpy() in fill_audio_info() Replace inlined strncpy with library call. Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index fb24ba69b2a6..3f405976f882 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2238,11 +2238,9 @@ static void fill_audio_info(struct audio_info *audio_info, cea_revision = drm_connector->display_info.cea_rev; - while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && - edid_caps->display_name[i]) { - audio_info->display_name[i] = edid_caps->display_name[i]; - i++; - } + strncpy(audio_info->display_name, + edid_caps->display_name, + AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS - 1); if (cea_revision >= 3) { audio_info->mode_count = edid_caps->audio_mode_count; -- GitLab From a68d90e7aed55e274cb117bbca34913d5fb8afd2 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 10:15:12 -0400 Subject: [PATCH 1392/2898] drm/amd/display: Fix indentation in create_eml_sink() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 3f405976f882..ce975aef27a7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2720,8 +2720,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) (edid->extensions + 1) * EDID_LENGTH, &init_params); - if (aconnector->base.force - == DRM_FORCE_ON) + if (aconnector->base.force == DRM_FORCE_ON) aconnector->dc_sink = aconnector->dc_link->local_sink ? aconnector->dc_link->local_sink : aconnector->dc_em_sink; -- GitLab From f922237daa7f2de4a8eae0ecdc99e944333fffc2 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 10:16:39 -0400 Subject: [PATCH 1393/2898] drm/amd/display: Tidy up dm_drm_plane_reset() Move WARN_ON higher up and in doing so fix brace style. Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ce975aef27a7..46fac2bccc57 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2873,13 +2873,13 @@ static void dm_drm_plane_reset(struct drm_plane *plane) plane->funcs->atomic_destroy_state(plane, plane->state); amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); - + WARN_ON(amdgpu_state == NULL); + if (amdgpu_state) { plane->state = &amdgpu_state->base; plane->state->plane = plane; plane->state->rotation = DRM_MODE_ROTATE_0; - } else - WARN_ON(1); + } } static struct drm_plane_state * -- GitLab From a8d8d3dc9ad8dc4ba6155bdd88f01e23bfc7dfbc Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 10:38:27 -0400 Subject: [PATCH 1394/2898] drm/amd/display: Fix brace style in amdgpu_dm_connector_ddc_get_modes() Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 46fac2bccc57..d7fc237851c5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3310,8 +3310,9 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, drm_edid_to_eld(connector, edid); amdgpu_dm_get_native_mode(connector); - } else + } else { amdgpu_dm_connector->num_modes = 0; + } } static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) -- GitLab From 9a227d263d44572583be5dd9e9f215cceb4297a1 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 10:40:08 -0400 Subject: [PATCH 1395/2898] drm/amd/display: Remove needless cast in amdgpu_dm_connector_init() The cast of dc_link is redundant. Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d7fc237851c5..6ef71e192845 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3460,7 +3460,8 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, struct dc *dc = dm->dc; struct dc_link *link = dc_get_link_at_index(dc, link_index); struct amdgpu_i2c_adapter *i2c; - ((struct dc_link *)link)->priv = aconnector; + + link->priv = aconnector; DRM_DEBUG_DRIVER("%s()\n", __func__); -- GitLab From 634086b464ac92d215aeaa3653759b0fbcde1a02 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Tue, 17 Oct 2017 12:13:39 -0400 Subject: [PATCH 1396/2898] drm/amd/display: Fix brace style Signed-off-by: Tom St Denis Acked-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index b9e4d3831001..ca5d0d1581dc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -208,24 +208,21 @@ static void remove_timer_handler(struct amdgpu_device *adev, DM_IRQ_TABLE_LOCK(adev, irq_table_flags); } - if (handler_in == NULL) { - /* Remove ALL handlers. */ + /* Remove ALL handlers. */ + if (handler_in == NULL) continue; - } - if (handler_in == handler_temp) { - /* Remove a SPECIFIC handler. - * Found our handler - we can stop here. */ + /* Remove a SPECIFIC handler. + * Found our handler - we can stop here. */ + if (handler_in == handler_temp) break; - } } DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - if (handler_in != NULL && handler_removed == false) { + if (handler_in != NULL && handler_removed == false) DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n", handler_in); - } } static bool -- GitLab From fc9e9920b1d3a7a6af7eb993d531c36beb985570 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Wed, 27 Sep 2017 15:15:38 +0530 Subject: [PATCH 1397/2898] drm/amd/display: add hardware_planes_only to list of affected planes For SoC's having software designed cursor plane, should be treated differently than hardware cursor planes. The DRM core initializes cursor plane by default with legacy_cursor_update set. Hence legacy_cursor_update can be use effectively to handle software cursor planes' update and atomicity functionalities. This patch uses this variable to decide in the atomic_check to whether add a requested plane to the list of affected planes or not, hence fixing the issue of co-existence of MPO, i.e, setting of available hardware planes like underlay and updation of cursor planes as well. Without this patch when underlay is set from user space, only blank screen with backlight is visible. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6ef71e192845..51258d045167 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3982,6 +3982,8 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, if (drm_atomic_crtc_needs_modeset(new_crtc_state) && dm_old_crtc_state->stream) manage_dm_interrupts(adev, acrtc, false); } + /* Add check here for SoC's that support hardware cursor plane, to + * unset legacy_cursor_update */ return drm_atomic_helper_commit(dev, state, nonblock); @@ -4647,7 +4649,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_connector *connector; struct drm_connector_state *old_con_state, *new_con_state; struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; /* * This bool will be set for true for any modeset/reset @@ -4656,18 +4658,34 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, bool lock_and_validation_needed = false; ret = drm_atomic_helper_check_modeset(dev, state); - if (ret) { DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); return ret; } /* - * Hack: Commit needs planes right now, specifically for gamma - * TODO rework commit to check CRTC for gamma change + * legacy_cursor_update should be made false for SoC's having + * a dedicated hardware plane for cursor in amdgpu_dm_atomic_commit(), + * otherwise for software cursor plane, + * we should not add it to list of affected planes. */ - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - if (new_crtc_state->color_mgmt_changed) { + if (state->legacy_cursor_update) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed) { + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + goto fail; + } + } + } else { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + if (!new_crtc_state->enable) + continue; + + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret) + return ret; + ret = drm_atomic_add_affected_planes(state, crtc); if (ret) goto fail; -- GitLab From af09e48aa52377eb807709e2a1cdc33e9fd1ac94 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Fri, 20 Oct 2017 13:59:53 -0400 Subject: [PATCH 1398/2898] drm/amd/display: Fix memoryleak during S3 resume. Do not create dc_state within display_resume, since it's being constructed within atomic check. Reviewed-by: Harry Wentland Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 51258d045167..d0ee1b3b8b5c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -694,10 +694,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) WARN_ON(kref_read(&cached_state->context->refcount) > 1); dc_release_state(cached_state->context); - cached_state->context = dc_create_state(); - ASSERT(cached_state->context); - dc_resource_state_copy_construct_current(adev->dm.dc, cached_state->context); - for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { dm_crtc_state = to_dm_crtc_state(new_crtc_state); if (dm_crtc_state->stream) { -- GitLab From 9b38bd1b8f5c874c3d1f330e0dcf4e7d84137477 Mon Sep 17 00:00:00 2001 From: "Jerry (Fangzhi) Zuo" Date: Fri, 20 Oct 2017 16:45:53 -0400 Subject: [PATCH 1399/2898] drm/amd/display:: Fix NULL pointer in Raven hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Programming sequence to frontend and backend has been switched. In such case, program_scaler() is getting called when programming frontend, and should be removed from backend programming routine. Reviewed-by: Harry Wentland Signed-off-by: Jerry (Fangzhi) Zuo Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e8b8daeeed97..2a6d3ca12954 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1369,13 +1369,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( } pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; - /* program_scaler and allocate_mem_input are not new asic */ - if ((!pipe_ctx_old || - memcmp(&pipe_ctx_old->plane_res.scl_data, &pipe_ctx->plane_res.scl_data, - sizeof(struct scaler_data)) != 0) && - pipe_ctx->plane_state) { - program_scaler(dc, pipe_ctx); - } /* mst support - use total stream count */ if (pipe_ctx->plane_res.mi != NULL) { -- GitLab From ace3cbdd23dc49729696b5f9a901f653a278e4f8 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 28 Aug 2017 15:11:33 +0200 Subject: [PATCH 1400/2898] mtd: spi-nor: Add support for Winbond w25q16dw Add JEDEC entry for the Winbond w25q16fw/w25q16dw with similar flags and format than the Winbond w25q32dw entry. Tested on a Khadas VIM2 SBC board with an Amlogic S912 SoC. Signed-off-by: Neil Armstrong Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 3128d8c4fa6f..51230cdb6a4d 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1152,6 +1152,11 @@ static const struct flash_info spi_nor_ids[] = { { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, + { + "w25q16dw", INFO(0xef6015, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, { "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) }, { "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) }, -- GitLab From f0d962392abc5b41d66ac4f7b723c82ba4f80582 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 11 Oct 2017 10:30:10 +0100 Subject: [PATCH 1401/2898] platform/x86: intel_cht_int33fe: make a couple of local functions static The functions cht_int33fe_check_for_max17047 and cht_int33fe_find_max17047 are local to the source and do not need to be in global scope, so make them static. Cleans up sparse warnings: symbol 'cht_int33fe_check_for_max17047' was not declared. Should it be static? symbol 'cht_int33fe_find_max17047' was not declared. Should it be static? Signed-off-by: Colin Ian King Reviewed-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_cht_int33fe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index 94716b2fbc00..286c6207765d 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c @@ -42,7 +42,7 @@ struct cht_int33fe_data { * These helpers are used to work around this by checking if an i2c-client * for the max17047 has already been registered. */ -int cht_int33fe_check_for_max17047(struct device *dev, void *data) +static int cht_int33fe_check_for_max17047(struct device *dev, void *data) { struct i2c_client **max17047 = data; struct acpi_device *adev; @@ -62,7 +62,7 @@ int cht_int33fe_check_for_max17047(struct device *dev, void *data) return 1; } -struct i2c_client *cht_int33fe_find_max17047(void) +static struct i2c_client *cht_int33fe_find_max17047(void) { struct i2c_client *max17047 = NULL; -- GitLab From 2cb81ac0787774e63fa48ca1a10c667f0d091a8f Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 10 Oct 2017 15:35:17 +0530 Subject: [PATCH 1402/2898] platform/x86: intel_telemetry: Fix load failure info Intel Telemetry driver depends on IPC1 interface. If IPC1 interface is disabled on a given platform by the system firmware, the driver does not load but prints misleading information in the dmesg logs. Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_telemetry_pltdrv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c index e0424d5a795a..136507a0d391 100644 --- a/drivers/platform/x86/intel_telemetry_pltdrv.c +++ b/drivers/platform/x86/intel_telemetry_pltdrv.c @@ -1234,7 +1234,6 @@ static struct platform_driver telemetry_soc_driver = { static int __init telemetry_module_init(void) { - pr_info(DRIVER_NAME ": version %s loaded\n", DRIVER_VERSION); return platform_driver_register(&telemetry_soc_driver); } -- GitLab From 999c8397df590aad2ed8e67250ccf4816484153b Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 10 Oct 2017 15:35:18 +0530 Subject: [PATCH 1403/2898] platform/x86: intel_telemetry: Fix typos Telemetry word is misspelled several times in this file as Telemtry. This fixes the spelling mistake and folds in another minor typo. Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_telemetry_pltdrv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c index 136507a0d391..3daf92e1282f 100644 --- a/drivers/platform/x86/intel_telemetry_pltdrv.c +++ b/drivers/platform/x86/intel_telemetry_pltdrv.c @@ -256,7 +256,7 @@ static int telemetry_check_evtid(enum telemetry_unit telem_unit, break; default: - pr_err("Unknown Telemetry action Specified %d\n", action); + pr_err("Unknown Telemetry action specified %d\n", action); return -EINVAL; } @@ -659,7 +659,7 @@ static int telemetry_setup(struct platform_device *pdev) ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig, TELEM_RESET); if (ret) { - dev_err(&pdev->dev, "TELEMTRY Setup Failed\n"); + dev_err(&pdev->dev, "TELEMETRY Setup Failed\n"); return ret; } return 0; @@ -685,7 +685,7 @@ static int telemetry_plt_update_events(struct telemetry_evtconfig pss_evtconfig, ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig, TELEM_UPDATE); if (ret) - pr_err("TELEMTRY Config Failed\n"); + pr_err("TELEMETRY Config Failed\n"); return ret; } @@ -822,7 +822,7 @@ static int telemetry_plt_reset_events(void) ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig, TELEM_RESET); if (ret) - pr_err("TELEMTRY Reset Failed\n"); + pr_err("TELEMETRY Reset Failed\n"); return ret; } @@ -885,7 +885,7 @@ static int telemetry_plt_add_events(u8 num_pss_evts, u8 num_ioss_evts, ret = telemetry_setup_evtconfig(pss_evtconfig, ioss_evtconfig, TELEM_ADD); if (ret) - pr_err("TELEMTRY ADD Failed\n"); + pr_err("TELEMETRY ADD Failed\n"); return ret; } @@ -1195,7 +1195,7 @@ static int telemetry_pltdrv_probe(struct platform_device *pdev) ret = telemetry_set_pltdata(&telm_pltops, telm_conf); if (ret) { - dev_err(&pdev->dev, "TELEMTRY Set Pltops Failed.\n"); + dev_err(&pdev->dev, "TELEMETRY Set Pltops Failed.\n"); goto out; } @@ -1210,7 +1210,7 @@ static int telemetry_pltdrv_probe(struct platform_device *pdev) iounmap(telm_conf->pss_config.regmap); if (telm_conf->ioss_config.regmap) iounmap(telm_conf->ioss_config.regmap); - dev_err(&pdev->dev, "TELEMTRY Setup Failed.\n"); + dev_err(&pdev->dev, "TELEMETRY Setup Failed.\n"); return ret; } -- GitLab From a5e50220edbdd1ec8912c191a0f5272d629743bf Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 10 Oct 2017 15:35:19 +0530 Subject: [PATCH 1404/2898] platform/x86: intel_telemetry: cleanup redundant headers Removes unnecessary header files included in the driver and sorts the remaining ones in the alphabetical order. Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_telemetry_core.c | 3 +-- drivers/platform/x86/intel_telemetry_debugfs.c | 8 +++----- drivers/platform/x86/intel_telemetry_pltdrv.c | 8 -------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/platform/x86/intel_telemetry_core.c b/drivers/platform/x86/intel_telemetry_core.c index 0d4c3808a6d8..f378621b5fe9 100644 --- a/drivers/platform/x86/intel_telemetry_core.c +++ b/drivers/platform/x86/intel_telemetry_core.c @@ -15,9 +15,8 @@ * Telemetry Framework provides platform related PM and performance statistics. * This file provides the core telemetry API implementation. */ -#include -#include #include +#include #include diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c index 74e518dd237c..4249e8267bbc 100644 --- a/drivers/platform/x86/intel_telemetry_debugfs.c +++ b/drivers/platform/x86/intel_telemetry_debugfs.c @@ -21,14 +21,12 @@ * /sys/kernel/debug/telemetry/ioss_race_verbosity: Write and Change Tracing * Verbosity via firmware */ -#include -#include -#include #include -#include +#include #include -#include +#include #include +#include #include #include diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c index 3daf92e1282f..678abf2e9e92 100644 --- a/drivers/platform/x86/intel_telemetry_pltdrv.c +++ b/drivers/platform/x86/intel_telemetry_pltdrv.c @@ -17,14 +17,6 @@ * The accumulated results are fetched from SRAM. */ #include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -- GitLab From e3075fd6f80c9a6ce678fa2f5bbdb2824c506c6c Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sat, 7 Oct 2017 15:19:51 -0700 Subject: [PATCH 1405/2898] platform/x86: intel_pmc_ipc: Use spin_lock to protect GCR updates Currently, update_no_reboot_bit() function implemented in this driver uses mutex_lock() to protect its register updates. But this function is called with in atomic context in iTCO_wdt_start() and iTCO_wdt_stop() functions in iTCO_wdt.c driver, which in turn causes "sleeping into atomic context" issue. This patch fixes this issue by replacing the mutex_lock() with spin_lock() to protect the GCR read/write/update APIs. Fixes: 9d855d4 ("platform/x86: intel_pmc_ipc: Fix iTCO_wdt GCS memory mapping failure") Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_pmc_ipc.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index 751b1212d01c..e03fa31446ca 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -131,6 +132,7 @@ static struct intel_pmc_ipc_dev { /* gcr */ void __iomem *gcr_mem_base; bool has_gcr_regs; + spinlock_t gcr_lock; /* punit */ struct platform_device *punit_dev; @@ -225,17 +227,17 @@ int intel_pmc_gcr_read(u32 offset, u32 *data) { int ret; - mutex_lock(&ipclock); + spin_lock(&ipcdev.gcr_lock); ret = is_gcr_valid(offset); if (ret < 0) { - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return ret; } *data = readl(ipcdev.gcr_mem_base + offset); - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return 0; } @@ -255,17 +257,17 @@ int intel_pmc_gcr_write(u32 offset, u32 data) { int ret; - mutex_lock(&ipclock); + spin_lock(&ipcdev.gcr_lock); ret = is_gcr_valid(offset); if (ret < 0) { - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return ret; } writel(data, ipcdev.gcr_mem_base + offset); - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return 0; } @@ -287,7 +289,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) u32 new_val; int ret = 0; - mutex_lock(&ipclock); + spin_lock(&ipcdev.gcr_lock); ret = is_gcr_valid(offset); if (ret < 0) @@ -309,7 +311,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) } gcr_ipc_unlock: - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return ret; } EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); @@ -489,6 +491,8 @@ static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) pmc->irq_mode = IPC_TRIGGER_MODE_IRQ; + spin_lock_init(&ipcdev.gcr_lock); + ret = pcim_enable_device(pdev); if (ret) return ret; @@ -903,6 +907,7 @@ static int ipc_plat_probe(struct platform_device *pdev) ipcdev.dev = &pdev->dev; ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; init_completion(&ipcdev.cmd_complete); + spin_lock_init(&ipcdev.gcr_lock); ipcdev.irq = platform_get_irq(pdev, 0); if (ipcdev.irq < 0) { -- GitLab From 8ee031631546cf2f7859cc69593bd60bbdd70b46 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Wed, 6 Sep 2017 17:59:07 +0300 Subject: [PATCH 1406/2898] fs/9p: Compare qid.path in v9fs_test_inode Commit fd2421f54423 ("fs/9p: When doing inode lookup compare qid details and inode mode bits.") transformed v9fs_qid_iget() to use iget5_locked() instead of iget_locked(). However, the test() callback is not checking fid.path at all, which means that a lookup in the inode cache can now accidentally locate a completely wrong inode from the same inode hash bucket if the other fields (qid.type and qid.version) match. Fixes: fd2421f54423 ("fs/9p: When doing inode lookup compare qid details and inode mode bits.") Cc: stable@vger.kernel.org Reviewed-by: Latchesar Ionkov Signed-off-by: Tuomas Tynkkynen Signed-off-by: Al Viro --- fs/9p/vfs_inode.c | 3 +++ fs/9p/vfs_inode_dotl.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 2a5de610dd8f..bdabb2765d1b 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -483,6 +483,9 @@ static int v9fs_test_inode(struct inode *inode, void *data) if (v9inode->qid.type != st->qid.type) return 0; + + if (v9inode->qid.path != st->qid.path) + return 0; return 1; } diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 70f9887c59a9..7f6ae21a27b3 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -87,6 +87,9 @@ static int v9fs_test_inode_dotl(struct inode *inode, void *data) if (v9inode->qid.type != st->qid.type) return 0; + + if (v9inode->qid.path != st->qid.path) + return 0; return 1; } -- GitLab From 9523feac272ccad2ad8186ba4fcc89103754de52 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Wed, 6 Sep 2017 17:59:08 +0300 Subject: [PATCH 1407/2898] net/9p: Switch to wait_event_killable() Because userspace gets Very Unhappy when calls like stat() and execve() return -EINTR on 9p filesystem mounts. For instance, when bash is looking in PATH for things to execute and some SIGCHLD interrupts stat(), bash can throw a spurious 'command not found' since it doesn't retry the stat(). In practice, hitting the problem is rare and needs a really slow/bogged down 9p server. Cc: stable@vger.kernel.org Signed-off-by: Tuomas Tynkkynen Signed-off-by: Al Viro --- net/9p/client.c | 3 +-- net/9p/trans_virtio.c | 13 ++++++------- net/9p/trans_xen.c | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 4674235b0d9b..1beb131dd3e1 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -773,8 +773,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) } again: /* Wait for the response */ - err = wait_event_interruptible(*req->wq, - req->status >= REQ_STATUS_RCVD); + err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD); /* * Make sure our req is coherent with regard to updates in other diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index f24b25c25106..f3a4efcf1456 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -286,8 +286,8 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) if (err == -ENOSPC) { chan->ring_bufs_avail = 0; spin_unlock_irqrestore(&chan->lock, flags); - err = wait_event_interruptible(*chan->vc_wq, - chan->ring_bufs_avail); + err = wait_event_killable(*chan->vc_wq, + chan->ring_bufs_avail); if (err == -ERESTARTSYS) return err; @@ -327,7 +327,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, * Other zc request to finish here */ if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { - err = wait_event_interruptible(vp_wq, + err = wait_event_killable(vp_wq, (atomic_read(&vp_pinned) < chan->p9_max_pages)); if (err == -ERESTARTSYS) return err; @@ -471,8 +471,8 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, if (err == -ENOSPC) { chan->ring_bufs_avail = 0; spin_unlock_irqrestore(&chan->lock, flags); - err = wait_event_interruptible(*chan->vc_wq, - chan->ring_bufs_avail); + err = wait_event_killable(*chan->vc_wq, + chan->ring_bufs_avail); if (err == -ERESTARTSYS) goto err_out; @@ -489,8 +489,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, virtqueue_kick(chan->vq); spin_unlock_irqrestore(&chan->lock, flags); p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); - err = wait_event_interruptible(*req->wq, - req->status >= REQ_STATUS_RCVD); + err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD); /* * Non kernel buffers are pinned, unpin them */ diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index 6ad3e043c617..325c56043007 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c @@ -156,8 +156,8 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) ring = &priv->rings[num]; again: - while (wait_event_interruptible(ring->wq, - p9_xen_write_todo(ring, size)) != 0) + while (wait_event_killable(ring->wq, + p9_xen_write_todo(ring, size)) != 0) ; spin_lock_irqsave(&ring->lock, flags); -- GitLab From 3c535c94a0ba94e9852de3aae7b6c62413eb2af7 Mon Sep 17 00:00:00 2001 From: Guochun Mao Date: Thu, 21 Sep 2017 20:45:05 +0800 Subject: [PATCH 1408/2898] dt-bindings: mtd: add new compatible strings and improve description Add "mediatak,mt2712-nor" and "mediatek,mt7622-nor" for nor flash node's compatible strings. Explicate the fallback compatible. Acked-by: Rob Herring Signed-off-by: Guochun Mao Signed-off-by: Cyrille Pitchen --- .../devicetree/bindings/mtd/mtk-quadspi.txt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/mtd/mtk-quadspi.txt b/Documentation/devicetree/bindings/mtd/mtk-quadspi.txt index 840f9405dcf0..56d3668e2c50 100644 --- a/Documentation/devicetree/bindings/mtd/mtk-quadspi.txt +++ b/Documentation/devicetree/bindings/mtd/mtk-quadspi.txt @@ -1,13 +1,16 @@ * Serial NOR flash controller for MTK MT81xx (and similar) Required properties: -- compatible: The possible values are: - "mediatek,mt2701-nor" - "mediatek,mt7623-nor" +- compatible: For mt8173, compatible should be "mediatek,mt8173-nor", + and it's the fallback compatible for other Soc. + For every other SoC, should contain both the SoC-specific compatible + string and "mediatek,mt8173-nor". + The possible values are: + "mediatek,mt2701-nor", "mediatek,mt8173-nor" + "mediatek,mt2712-nor", "mediatek,mt8173-nor" + "mediatek,mt7622-nor", "mediatek,mt8173-nor" + "mediatek,mt7623-nor", "mediatek,mt8173-nor" "mediatek,mt8173-nor" - For mt8173, compatible should be "mediatek,mt8173-nor". - For every other SoC, should contain both the SoC-specific compatible string - and "mediatek,mt8173-nor". - reg: physical base address and length of the controller's register - clocks: the phandle of the clocks needed by the nor controller - clock-names: the names of the clocks -- GitLab From 2ea68b75411b137f5782afa1052a5f1d99ef66f1 Mon Sep 17 00:00:00 2001 From: Guochun Mao Date: Thu, 21 Sep 2017 20:45:06 +0800 Subject: [PATCH 1409/2898] mtd: mtk-nor: add suspend/resume support Abstract functions of clock setting, to avoid duplicated code, these functions been used in new feature. Implement suspend/resume functions. Signed-off-by: Guochun Mao Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/mtk-quadspi.c | 70 +++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c index c258c7adf1c5..abe455ccd68b 100644 --- a/drivers/mtd/spi-nor/mtk-quadspi.c +++ b/drivers/mtd/spi-nor/mtk-quadspi.c @@ -404,6 +404,29 @@ static int mt8173_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, return ret; } +static void mt8173_nor_disable_clk(struct mt8173_nor *mt8173_nor) +{ + clk_disable_unprepare(mt8173_nor->spi_clk); + clk_disable_unprepare(mt8173_nor->nor_clk); +} + +static int mt8173_nor_enable_clk(struct mt8173_nor *mt8173_nor) +{ + int ret; + + ret = clk_prepare_enable(mt8173_nor->spi_clk); + if (ret) + return ret; + + ret = clk_prepare_enable(mt8173_nor->nor_clk); + if (ret) { + clk_disable_unprepare(mt8173_nor->spi_clk); + return ret; + } + + return 0; +} + static int mtk_nor_init(struct mt8173_nor *mt8173_nor, struct device_node *flash_node) { @@ -468,15 +491,11 @@ static int mtk_nor_drv_probe(struct platform_device *pdev) return PTR_ERR(mt8173_nor->nor_clk); mt8173_nor->dev = &pdev->dev; - ret = clk_prepare_enable(mt8173_nor->spi_clk); + + ret = mt8173_nor_enable_clk(mt8173_nor); if (ret) return ret; - ret = clk_prepare_enable(mt8173_nor->nor_clk); - if (ret) { - clk_disable_unprepare(mt8173_nor->spi_clk); - return ret; - } /* only support one attached flash */ flash_np = of_get_next_available_child(pdev->dev.of_node, NULL); if (!flash_np) { @@ -487,10 +506,9 @@ static int mtk_nor_drv_probe(struct platform_device *pdev) ret = mtk_nor_init(mt8173_nor, flash_np); nor_free: - if (ret) { - clk_disable_unprepare(mt8173_nor->spi_clk); - clk_disable_unprepare(mt8173_nor->nor_clk); - } + if (ret) + mt8173_nor_disable_clk(mt8173_nor); + return ret; } @@ -498,11 +516,38 @@ static int mtk_nor_drv_remove(struct platform_device *pdev) { struct mt8173_nor *mt8173_nor = platform_get_drvdata(pdev); - clk_disable_unprepare(mt8173_nor->spi_clk); - clk_disable_unprepare(mt8173_nor->nor_clk); + mt8173_nor_disable_clk(mt8173_nor); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mtk_nor_suspend(struct device *dev) +{ + struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev); + + mt8173_nor_disable_clk(mt8173_nor); + return 0; } +static int mtk_nor_resume(struct device *dev) +{ + struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev); + + return mt8173_nor_enable_clk(mt8173_nor); +} + +static const struct dev_pm_ops mtk_nor_dev_pm_ops = { + .suspend = mtk_nor_suspend, + .resume = mtk_nor_resume, +}; + +#define MTK_NOR_DEV_PM_OPS (&mtk_nor_dev_pm_ops) +#else +#define MTK_NOR_DEV_PM_OPS NULL +#endif + static const struct of_device_id mtk_nor_of_ids[] = { { .compatible = "mediatek,mt8173-nor"}, { /* sentinel */ } @@ -514,6 +559,7 @@ static struct platform_driver mtk_nor_driver = { .remove = mtk_nor_drv_remove, .driver = { .name = "mtk-nor", + .pm = MTK_NOR_DEV_PM_OPS, .of_match_table = mtk_nor_of_ids, }, }; -- GitLab From b8cc0012917d9a1ab1497a38c8675ecc4d9d94f2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 24 Oct 2017 00:40:53 -0700 Subject: [PATCH 1410/2898] spi-nor: intel-spi: Remove EXPERT dependency The idea to have the intel-spi driver dependent on EXPERT was exactly because we did not want ordinary users playing with the device and inadvertently overwrite their BIOSes (if it is not protected). This seems to be superfluous hence remove it. Suggested-by: Arnd Bergmann Signed-off-by: Bin Meng Acked-by: Mika Westerberg Acked-by: Arnd Bergmann Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index f26aaa6d1430..89da88e59121 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -90,7 +90,7 @@ config SPI_INTEL_SPI tristate config SPI_INTEL_SPI_PCI - tristate "Intel PCH/PCU SPI flash PCI driver" if EXPERT + tristate "Intel PCH/PCU SPI flash PCI driver" depends on X86 && PCI select SPI_INTEL_SPI help @@ -106,7 +106,7 @@ config SPI_INTEL_SPI_PCI will be called intel-spi-pci. config SPI_INTEL_SPI_PLATFORM - tristate "Intel PCH/PCU SPI flash platform driver" if EXPERT + tristate "Intel PCH/PCU SPI flash platform driver" depends on X86 select SPI_INTEL_SPI help -- GitLab From 8a25c8f66c46077bd5ae8ea5f6fd6fa08ea8231a Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 29 Sep 2017 11:23:25 +0100 Subject: [PATCH 1411/2898] rtc: clarify the RTC offset correction The RTC offset correction documentation is not very clear about the exact relationship between "offset" and the effect it has on the RTC. Supplement the documentation with an equation giving the relationship. Signed-off-by: Russell King Signed-off-by: Alexandre Belloni --- drivers/rtc/interface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 9eb32ead63db..672b192f8153 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -1004,6 +1004,10 @@ int rtc_read_offset(struct rtc_device *rtc, long *offset) * to compensate for differences in the actual clock rate due to temperature, * the crystal, capacitor, etc. * + * The adjustment applied is as follows: + * t = t0 * (1 + offset * 1e-9) + * where t0 is the measured length of 1 RTC second with offset = 0 + * * Kernel interface to adjust an rtc clock offset. * Return 0 on success, or a negative number on error. * If the rtc offset is not setable (or not implemented), return -EINVAL -- GitLab From f94ffbc2c2a4128c4412bb483d0807722dfb682b Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 29 Sep 2017 11:23:31 +0100 Subject: [PATCH 1412/2898] rtc: armada38x: add support for trimming the RTC Add support for trimming the RTC using the offset mechanism. This RTC supports two modes: low update mode and high update mode. Low update mode has finer precision than high update mode, so we use the low mode where possible. Signed-off-by: Russell King Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-armada38x.c | 101 ++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index 21f355c37eab..1e4978c96ffd 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -28,6 +28,8 @@ #define RTC_IRQ_AL_EN BIT(0) #define RTC_IRQ_FREQ_EN BIT(1) #define RTC_IRQ_FREQ_1HZ BIT(2) +#define RTC_CCR 0x18 +#define RTC_CCR_MODE BIT(15) #define RTC_TIME 0xC #define RTC_ALARM1 0x10 @@ -343,18 +345,117 @@ static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data) return IRQ_HANDLED; } +/* + * The information given in the Armada 388 functional spec is complex. + * They give two different formulas for calculating the offset value, + * but when considering "Offset" as an 8-bit signed integer, they both + * reduce down to (we shall rename "Offset" as "val" here): + * + * val = (f_ideal / f_measured - 1) / resolution where f_ideal = 32768 + * + * Converting to time, f = 1/t: + * val = (t_measured / t_ideal - 1) / resolution where t_ideal = 1/32768 + * + * => t_measured / t_ideal = val * resolution + 1 + * + * "offset" in the RTC interface is defined as: + * t = t0 * (1 + offset * 1e-9) + * where t is the desired period, t0 is the measured period with a zero + * offset, which is t_measured above. With t0 = t_measured and t = t_ideal, + * offset = (t_ideal / t_measured - 1) / 1e-9 + * + * => t_ideal / t_measured = offset * 1e-9 + 1 + * + * so: + * + * offset * 1e-9 + 1 = 1 / (val * resolution + 1) + * + * We want "resolution" to be an integer, so resolution = R * 1e-9, giving + * offset = 1e18 / (val * R + 1e9) - 1e9 + * val = (1e18 / (offset + 1e9) - 1e9) / R + * with a common transformation: + * f(x) = 1e18 / (x + 1e9) - 1e9 + * offset = f(val * R) + * val = f(offset) / R + * + * Armada 38x supports two modes, fine mode (954ppb) and coarse mode (3815ppb). + */ +static long armada38x_ppb_convert(long ppb) +{ + long div = ppb + 1000000000L; + + return div_s64(1000000000000000000LL + div / 2, div) - 1000000000L; +} + +static int armada38x_rtc_read_offset(struct device *dev, long *offset) +{ + struct armada38x_rtc *rtc = dev_get_drvdata(dev); + unsigned long ccr, flags; + long ppb_cor; + + spin_lock_irqsave(&rtc->lock, flags); + ccr = rtc->data->read_rtc_reg(rtc, RTC_CCR); + spin_unlock_irqrestore(&rtc->lock, flags); + + ppb_cor = (ccr & RTC_CCR_MODE ? 3815 : 954) * (s8)ccr; + /* ppb_cor + 1000000000L can never be zero */ + *offset = armada38x_ppb_convert(ppb_cor); + + return 0; +} + +static int armada38x_rtc_set_offset(struct device *dev, long offset) +{ + struct armada38x_rtc *rtc = dev_get_drvdata(dev); + unsigned long ccr = 0; + long ppb_cor, off; + + /* + * The maximum ppb_cor is -128 * 3815 .. 127 * 3815, but we + * need to clamp the input. This equates to -484270 .. 488558. + * Not only is this to stop out of range "off" but also to + * avoid the division by zero in armada38x_ppb_convert(). + */ + offset = clamp(offset, -484270L, 488558L); + + ppb_cor = armada38x_ppb_convert(offset); + + /* + * Use low update mode where possible, which gives a better + * resolution of correction. + */ + off = DIV_ROUND_CLOSEST(ppb_cor, 954); + if (off > 127 || off < -128) { + ccr = RTC_CCR_MODE; + off = DIV_ROUND_CLOSEST(ppb_cor, 3815); + } + + /* + * Armada 388 requires a bit pattern in bits 14..8 depending on + * the sign bit: { 0, ~S, S, S, S, S, S } + */ + ccr |= (off & 0x3fff) ^ 0x2000; + rtc_delayed_write(ccr, rtc, RTC_CCR); + + return 0; +} + static const struct rtc_class_ops armada38x_rtc_ops = { .read_time = armada38x_rtc_read_time, .set_time = armada38x_rtc_set_time, .read_alarm = armada38x_rtc_read_alarm, .set_alarm = armada38x_rtc_set_alarm, .alarm_irq_enable = armada38x_rtc_alarm_irq_enable, + .read_offset = armada38x_rtc_read_offset, + .set_offset = armada38x_rtc_set_offset, }; static const struct rtc_class_ops armada38x_rtc_ops_noirq = { .read_time = armada38x_rtc_read_time, .set_time = armada38x_rtc_set_time, .read_alarm = armada38x_rtc_read_alarm, + .read_offset = armada38x_rtc_read_offset, + .set_offset = armada38x_rtc_set_offset, }; static const struct armada38x_rtc_data armada38x_data = { -- GitLab From bc3bee0252725240ffa62180d387cc245179c549 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 29 Sep 2017 11:23:36 +0100 Subject: [PATCH 1413/2898] rtc: pcf8523: add support for trimming the RTC oscillator Add support for reading and writing the RTC offset register, converting it to the corresponding parts-per-billion value. When setting the drift, the PCF8523 has two modes: one applies the adjustment every two hours, the other applies the adjustment every minute. We select between these two modes according to which ever gives the closest PPB value to the one requested. Signed-off-by: Russell King Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf8523.c | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 28c48b3c1946..c312af0db729 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -35,6 +35,9 @@ #define REG_MONTHS 0x08 #define REG_YEARS 0x09 +#define REG_OFFSET 0x0e +#define REG_OFFSET_MODE BIT(7) + struct pcf8523 { struct rtc_device *rtc; }; @@ -272,10 +275,47 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, #define pcf8523_rtc_ioctl NULL #endif +static int pcf8523_rtc_read_offset(struct device *dev, long *offset) +{ + struct i2c_client *client = to_i2c_client(dev); + int err; + u8 value; + s8 val; + + err = pcf8523_read(client, REG_OFFSET, &value); + if (err < 0) + return err; + + /* sign extend the 7-bit offset value */ + val = value << 1; + *offset = (value & REG_OFFSET_MODE ? 4069 : 4340) * (val >> 1); + + return 0; +} + +static int pcf8523_rtc_set_offset(struct device *dev, long offset) +{ + struct i2c_client *client = to_i2c_client(dev); + long reg_m0, reg_m1; + u8 value; + + reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L); + reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L); + + if (abs(reg_m0 * 4340 - offset) < abs(reg_m1 * 4069 - offset)) + value = reg_m0 & 0x7f; + else + value = (reg_m1 & 0x7f) | REG_OFFSET_MODE; + + return pcf8523_write(client, REG_OFFSET, value); +} + static const struct rtc_class_ops pcf8523_rtc_ops = { .read_time = pcf8523_rtc_read_time, .set_time = pcf8523_rtc_set_time, .ioctl = pcf8523_rtc_ioctl, + .read_offset = pcf8523_rtc_read_offset, + .set_offset = pcf8523_rtc_set_offset, }; static int pcf8523_probe(struct i2c_client *client, -- GitLab From 1901142ba8d5bf9f21b86d33770be8309071c25d Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 23 Oct 2017 15:16:44 +0800 Subject: [PATCH 1414/2898] dt-bindings: rtc: mediatek: add bindings for MediaTek SoC based RTC Add device-tree binding for MediaTek SoC based RTC Cc: devicetree@vger.kernel.org Signed-off-by: Sean Wang Acked-by: Rob Herring Signed-off-by: Alexandre Belloni --- .../devicetree/bindings/rtc/rtc-mt7622.txt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/rtc-mt7622.txt diff --git a/Documentation/devicetree/bindings/rtc/rtc-mt7622.txt b/Documentation/devicetree/bindings/rtc/rtc-mt7622.txt new file mode 100644 index 000000000000..09fe8f51476f --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-mt7622.txt @@ -0,0 +1,21 @@ +Device-Tree bindings for MediaTek SoC based RTC + +Required properties: +- compatible : Should be + "mediatek,mt7622-rtc", "mediatek,soc-rtc" : for MT7622 SoC +- reg : Specifies base physical address and size of the registers; +- interrupts : Should contain the interrupt for RTC alarm; +- clocks : Specifies list of clock specifiers, corresponding to + entries in clock-names property; +- clock-names : Should contain "rtc" entries + +Example: + +rtc: rtc@10212800 { + compatible = "mediatek,mt7622-rtc", + "mediatek,soc-rtc"; + reg = <0 0x10212800 0 0x200>; + interrupts = ; + clocks = <&topckgen CLK_TOP_RTC>; + clock-names = "rtc"; +}; -- GitLab From 4d91d7b099508831e82ef209bba71c8b636886a2 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Thu, 5 Oct 2017 22:13:20 +0530 Subject: [PATCH 1415/2898] rpmsg: Allow RPMSG_VIRTIO to be enabled via menuconfig or defconfig Currently, RPMSG_VIRTIO can only be enabled if some other kconfig option selects it. This does not allow it to be enabled for virtualized systems where Virtio RPMSG is available over Virtio MMIO or PCI transport. This patch updates RPMSG_VIRTIO kconfig option so that we can enable the VirtIO RPMSG driver via menuconfig or defconfig. The patch also removes "select RPMSG_VIRTIO" from various remoteproc kconfig options because it is now user selectable. Signed-off-by: Anup Patel Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 4 ---- drivers/rpmsg/Kconfig | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index bf04479456a0..b609e1d3654b 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -28,7 +28,6 @@ config OMAP_REMOTEPROC depends on OMAP_IOMMU select MAILBOX select OMAP2PLUS_MBOX - select RPMSG_VIRTIO help Say y here to support OMAP's remote processors (dual M3 and DSP on OMAP4) via the remote processor framework. @@ -58,7 +57,6 @@ config DA8XX_REMOTEPROC tristate "DA8xx/OMAP-L13x remoteproc support" depends on ARCH_DAVINCI_DA8XX depends on DMA_CMA - select RPMSG_VIRTIO help Say y here to support DA8xx/OMAP-L13x remote processors via the remote processor framework. @@ -79,7 +77,6 @@ config DA8XX_REMOTEPROC config KEYSTONE_REMOTEPROC tristate "Keystone Remoteproc support" depends on ARCH_KEYSTONE - select RPMSG_VIRTIO help Say Y here here to support Keystone remote processors (DSP) via the remote processor framework. @@ -135,7 +132,6 @@ config ST_REMOTEPROC depends on ARCH_STI select MAILBOX select STI_MBOX - select RPMSG_VIRTIO help Say y here to support ST's adjunct processors via the remote processor framework. diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index 0fe6eac46512..65a9f6b892f0 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -47,7 +47,8 @@ config RPMSG_QCOM_SMD platforms. config RPMSG_VIRTIO - tristate + tristate "Virtio RPMSG bus driver" + depends on HAS_DMA select RPMSG select VIRTIO -- GitLab From ba5d018135ef4eb59e6143bff0aaeef118ff78a1 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 23 Oct 2017 15:16:45 +0800 Subject: [PATCH 1416/2898] rtc: mediatek: add driver for RTC on MT7622 SoC This patch introduces the driver for the RTC on MT7622 SoC. Signed-off-by: Sean Wang Reviewed-by: Yingjoe Chen Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-mt7622.c | 422 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 433 insertions(+) create mode 100644 drivers/rtc/rtc-mt7622.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e0e58f3b1420..322752ebc5a7 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1715,6 +1715,16 @@ config RTC_DRV_MT6397 If you want to use Mediatek(R) RTC interface, select Y or M here. +config RTC_DRV_MT7622 + tristate "MediaTek SoC based RTC" + depends on ARCH_MEDIATEK || COMPILE_TEST + help + This enables support for the real time clock built in the MediaTek + SoCs. + + This drive can also be built as a module. If so, the module + will be called rtc-mt7622. + config RTC_DRV_XGENE tristate "APM X-Gene RTC" depends on HAS_IOMEM diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7230014c92af..5ec891a81f4f 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o +obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c new file mode 100644 index 000000000000..d79b9ae4d237 --- /dev/null +++ b/drivers/rtc/rtc-mt7622.c @@ -0,0 +1,422 @@ +/* + * Driver for MediaTek SoC based RTC + * + * Copyright (C) 2017 Sean Wang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MTK_RTC_DEV KBUILD_MODNAME + +#define MTK_RTC_PWRCHK1 0x4 +#define RTC_PWRCHK1_MAGIC 0xc6 + +#define MTK_RTC_PWRCHK2 0x8 +#define RTC_PWRCHK2_MAGIC 0x9a + +#define MTK_RTC_KEY 0xc +#define RTC_KEY_MAGIC 0x59 + +#define MTK_RTC_PROT1 0x10 +#define RTC_PROT1_MAGIC 0xa3 + +#define MTK_RTC_PROT2 0x14 +#define RTC_PROT2_MAGIC 0x57 + +#define MTK_RTC_PROT3 0x18 +#define RTC_PROT3_MAGIC 0x67 + +#define MTK_RTC_PROT4 0x1c +#define RTC_PROT4_MAGIC 0xd2 + +#define MTK_RTC_CTL 0x20 +#define RTC_RC_STOP BIT(0) + +#define MTK_RTC_DEBNCE 0x2c +#define RTC_DEBNCE_MASK GENMASK(2, 0) + +#define MTK_RTC_INT 0x30 +#define RTC_INT_AL_STA BIT(4) + +/* + * Ranges from 0x40 to 0x78 provide RTC time setup for year, month, + * day of month, day of week, hour, minute and second. + */ +#define MTK_RTC_TREG(_t, _f) (0x40 + (0x4 * (_f)) + ((_t) * 0x20)) + +#define MTK_RTC_AL_CTL 0x7c +#define RTC_AL_EN BIT(0) +#define RTC_AL_ALL GENMASK(7, 0) + +/* + * The offset is used in the translation for the year between in struct + * rtc_time and in hardware register MTK_RTC_TREG(x,MTK_YEA) + */ +#define MTK_RTC_TM_YR_OFFSET 100 + +/* + * The lowest value for the valid tm_year. RTC hardware would take incorrectly + * tm_year 100 as not a leap year and thus it is also required being excluded + * from the valid options. + */ +#define MTK_RTC_TM_YR_L (MTK_RTC_TM_YR_OFFSET + 1) + +/* + * The most year the RTC can hold is 99 and the next to 99 in year register + * would be wraparound to 0, for MT7622. + */ +#define MTK_RTC_HW_YR_LIMIT 99 + +/* The highest value for the valid tm_year */ +#define MTK_RTC_TM_YR_H (MTK_RTC_TM_YR_OFFSET + MTK_RTC_HW_YR_LIMIT) + +/* Simple macro helps to check whether the hardware supports the tm_year */ +#define MTK_RTC_TM_YR_VALID(_y) ((_y) >= MTK_RTC_TM_YR_L && \ + (_y) <= MTK_RTC_TM_YR_H) + +/* Types of the function the RTC provides are time counter and alarm. */ +enum { + MTK_TC, + MTK_AL, +}; + +/* Indexes are used for the pointer to relevant registers in MTK_RTC_TREG */ +enum { + MTK_YEA, + MTK_MON, + MTK_DOM, + MTK_DOW, + MTK_HOU, + MTK_MIN, + MTK_SEC +}; + +struct mtk_rtc { + struct rtc_device *rtc; + void __iomem *base; + int irq; + struct clk *clk; +}; + +static void mtk_w32(struct mtk_rtc *rtc, u32 reg, u32 val) +{ + writel_relaxed(val, rtc->base + reg); +} + +static u32 mtk_r32(struct mtk_rtc *rtc, u32 reg) +{ + return readl_relaxed(rtc->base + reg); +} + +static void mtk_rmw(struct mtk_rtc *rtc, u32 reg, u32 mask, u32 set) +{ + u32 val; + + val = mtk_r32(rtc, reg); + val &= ~mask; + val |= set; + mtk_w32(rtc, reg, val); +} + +static void mtk_set(struct mtk_rtc *rtc, u32 reg, u32 val) +{ + mtk_rmw(rtc, reg, 0, val); +} + +static void mtk_clr(struct mtk_rtc *rtc, u32 reg, u32 val) +{ + mtk_rmw(rtc, reg, val, 0); +} + +static void mtk_rtc_hw_init(struct mtk_rtc *hw) +{ + /* The setup of the init sequence is for allowing RTC got to work */ + mtk_w32(hw, MTK_RTC_PWRCHK1, RTC_PWRCHK1_MAGIC); + mtk_w32(hw, MTK_RTC_PWRCHK2, RTC_PWRCHK2_MAGIC); + mtk_w32(hw, MTK_RTC_KEY, RTC_KEY_MAGIC); + mtk_w32(hw, MTK_RTC_PROT1, RTC_PROT1_MAGIC); + mtk_w32(hw, MTK_RTC_PROT2, RTC_PROT2_MAGIC); + mtk_w32(hw, MTK_RTC_PROT3, RTC_PROT3_MAGIC); + mtk_w32(hw, MTK_RTC_PROT4, RTC_PROT4_MAGIC); + mtk_rmw(hw, MTK_RTC_DEBNCE, RTC_DEBNCE_MASK, 0); + mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP); +} + +static void mtk_rtc_get_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm, + int time_alarm) +{ + u32 year, mon, mday, wday, hour, min, sec; + + /* + * Read again until the field of the second is not changed which + * ensures all fields in the consistent state. Note that MTK_SEC must + * be read first. In this way, it guarantees the others remain not + * changed when the results for two MTK_SEC consecutive reads are same. + */ + do { + sec = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC)); + min = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN)); + hour = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU)); + wday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW)); + mday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM)); + mon = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MON)); + year = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA)); + } while (sec != mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC))); + + tm->tm_sec = sec; + tm->tm_min = min; + tm->tm_hour = hour; + tm->tm_wday = wday; + tm->tm_mday = mday; + tm->tm_mon = mon - 1; + + /* Rebase to the absolute year which userspace queries */ + tm->tm_year = year + MTK_RTC_TM_YR_OFFSET; +} + +static void mtk_rtc_set_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm, + int time_alarm) +{ + u32 year; + + /* Rebase to the relative year which RTC hardware requires */ + year = tm->tm_year - MTK_RTC_TM_YR_OFFSET; + + mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA), year); + mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_MON), tm->tm_mon + 1); + mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW), tm->tm_wday); + mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM), tm->tm_mday); + mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU), tm->tm_hour); + mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN), tm->tm_min); + mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC), tm->tm_sec); +} + +static irqreturn_t mtk_rtc_alarmirq(int irq, void *id) +{ + struct mtk_rtc *hw = (struct mtk_rtc *)id; + u32 irq_sta; + + irq_sta = mtk_r32(hw, MTK_RTC_INT); + if (irq_sta & RTC_INT_AL_STA) { + /* Stop alarm also implicitly disables the alarm interrupt */ + mtk_w32(hw, MTK_RTC_AL_CTL, 0); + rtc_update_irq(hw->rtc, 1, RTC_IRQF | RTC_AF); + + /* Ack alarm interrupt status */ + mtk_w32(hw, MTK_RTC_INT, RTC_INT_AL_STA); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int mtk_rtc_gettime(struct device *dev, struct rtc_time *tm) +{ + struct mtk_rtc *hw = dev_get_drvdata(dev); + + mtk_rtc_get_alarm_or_time(hw, tm, MTK_TC); + + return rtc_valid_tm(tm); +} + +static int mtk_rtc_settime(struct device *dev, struct rtc_time *tm) +{ + struct mtk_rtc *hw = dev_get_drvdata(dev); + + if (!MTK_RTC_TM_YR_VALID(tm->tm_year)) + return -EINVAL; + + /* Stop time counter before setting a new one*/ + mtk_set(hw, MTK_RTC_CTL, RTC_RC_STOP); + + mtk_rtc_set_alarm_or_time(hw, tm, MTK_TC); + + /* Restart the time counter */ + mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP); + + return 0; +} + +static int mtk_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct mtk_rtc *hw = dev_get_drvdata(dev); + struct rtc_time *alrm_tm = &wkalrm->time; + + mtk_rtc_get_alarm_or_time(hw, alrm_tm, MTK_AL); + + wkalrm->enabled = !!(mtk_r32(hw, MTK_RTC_AL_CTL) & RTC_AL_EN); + wkalrm->pending = !!(mtk_r32(hw, MTK_RTC_INT) & RTC_INT_AL_STA); + + return 0; +} + +static int mtk_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + struct mtk_rtc *hw = dev_get_drvdata(dev); + struct rtc_time *alrm_tm = &wkalrm->time; + + if (!MTK_RTC_TM_YR_VALID(alrm_tm->tm_year)) + return -EINVAL; + + /* + * Stop the alarm also implicitly including disables interrupt before + * setting a new one. + */ + mtk_clr(hw, MTK_RTC_AL_CTL, RTC_AL_EN); + + /* + * Avoid contention between mtk_rtc_setalarm and IRQ handler so that + * disabling the interrupt and awaiting for pending IRQ handler to + * complete. + */ + synchronize_irq(hw->irq); + + mtk_rtc_set_alarm_or_time(hw, alrm_tm, MTK_AL); + + /* Restart the alarm with the new setup */ + mtk_w32(hw, MTK_RTC_AL_CTL, RTC_AL_ALL); + + return 0; +} + +static const struct rtc_class_ops mtk_rtc_ops = { + .read_time = mtk_rtc_gettime, + .set_time = mtk_rtc_settime, + .read_alarm = mtk_rtc_getalarm, + .set_alarm = mtk_rtc_setalarm, +}; + +static const struct of_device_id mtk_rtc_match[] = { + { .compatible = "mediatek,mt7622-rtc" }, + { .compatible = "mediatek,soc-rtc" }, + {}, +}; + +static int mtk_rtc_probe(struct platform_device *pdev) +{ + struct mtk_rtc *hw; + struct resource *res; + int ret; + + hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL); + if (!hw) + return -ENOMEM; + + platform_set_drvdata(pdev, hw); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hw->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hw->base)) + return PTR_ERR(hw->base); + + hw->clk = devm_clk_get(&pdev->dev, "rtc"); + if (IS_ERR(hw->clk)) { + dev_err(&pdev->dev, "No clock\n"); + return PTR_ERR(hw->clk); + } + + ret = clk_prepare_enable(hw->clk); + if (ret) + return ret; + + hw->irq = platform_get_irq(pdev, 0); + if (hw->irq < 0) { + dev_err(&pdev->dev, "No IRQ resource\n"); + ret = hw->irq; + goto err; + } + + ret = devm_request_irq(&pdev->dev, hw->irq, mtk_rtc_alarmirq, + 0, dev_name(&pdev->dev), hw); + if (ret) { + dev_err(&pdev->dev, "Can't request IRQ\n"); + goto err; + } + + mtk_rtc_hw_init(hw); + + device_init_wakeup(&pdev->dev, true); + + hw->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, + &mtk_rtc_ops, THIS_MODULE); + if (IS_ERR(hw->rtc)) { + ret = PTR_ERR(hw->rtc); + dev_err(&pdev->dev, "Unable to register device\n"); + goto err; + } + + return 0; +err: + clk_disable_unprepare(hw->clk); + + return ret; +} + +static int mtk_rtc_remove(struct platform_device *pdev) +{ + struct mtk_rtc *hw = platform_get_drvdata(pdev); + + clk_disable_unprepare(hw->clk); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mtk_rtc_suspend(struct device *dev) +{ + struct mtk_rtc *hw = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(hw->irq); + + return 0; +} + +static int mtk_rtc_resume(struct device *dev) +{ + struct mtk_rtc *hw = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(hw->irq); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(mtk_rtc_pm_ops, mtk_rtc_suspend, mtk_rtc_resume); + +#define MTK_RTC_PM_OPS (&mtk_rtc_pm_ops) +#else /* CONFIG_PM */ +#define MTK_RTC_PM_OPS NULL +#endif /* CONFIG_PM */ + +static struct platform_driver mtk_rtc_driver = { + .probe = mtk_rtc_probe, + .remove = mtk_rtc_remove, + .driver = { + .name = MTK_RTC_DEV, + .of_match_table = mtk_rtc_match, + .pm = MTK_RTC_PM_OPS, + }, +}; + +module_platform_driver(mtk_rtc_driver); + +MODULE_DESCRIPTION("MediaTek SoC based RTC Driver"); +MODULE_AUTHOR("Sean Wang "); +MODULE_LICENSE("GPL"); -- GitLab From d00a7ed288e7943fcf253c6402abb09f0f9689d0 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 23 Oct 2017 15:16:46 +0800 Subject: [PATCH 1417/2898] rtc: mediatek: enhance the description for MediaTek PMIC based RTC Give a better description for original MediaTek RTC driver as PMIC based RTC in order to distinguish SoC based RTC. Also turning all words with Mediatek to MediaTek here. Cc: Eddie Huang Signed-off-by: Sean Wang Acked-by: Eddie Huang Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 322752ebc5a7..616fe53c788e 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1706,14 +1706,14 @@ config RTC_DRV_MOXART will be called rtc-moxart config RTC_DRV_MT6397 - tristate "Mediatek Real Time Clock driver" + tristate "MediaTek PMIC based RTC" depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN) help - This selects the Mediatek(R) RTC driver. RTC is part of Mediatek + This selects the MediaTek(R) RTC driver. RTC is part of MediaTek MT6397 PMIC. You should enable MT6397 PMIC MFD before select - Mediatek(R) RTC driver. + MediaTek(R) RTC driver. - If you want to use Mediatek(R) RTC interface, select Y or M here. + If you want to use MediaTek(R) RTC interface, select Y or M here. config RTC_DRV_MT7622 tristate "MediaTek SoC based RTC" -- GitLab From 1bb5a74b31151008480ebaa831c1ec1b007e8f43 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 23 Oct 2017 15:16:47 +0800 Subject: [PATCH 1418/2898] rtc: mediatek: update MAINTAINERS entry with MediaTek RTC driver I work for MediaTek on maintaining the MediaTek SoC based RTC driver for the existing SoCs and keep adding support for the following SoCs in the future. Cc: Eddie Huang Signed-off-by: Sean Wang Signed-off-by: Alexandre Belloni --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2281af4b41b6..332c04ccc05f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1579,10 +1579,13 @@ F: drivers/rtc/rtc-armada38x.c ARM/Mediatek RTC DRIVER M: Eddie Huang +M: Sean Wang L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) S: Maintained +F: Documentation/devicetree/bindings/rtc/rtc-mt7622.txt F: drivers/rtc/rtc-mt6397.c +F: drivers/rtc/rtc-mt7622.c ARM/Mediatek SoC support M: Matthias Brugger -- GitLab From df16aaac26e92e97ab7234d3f93c953466adc4b5 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Sat, 7 Oct 2017 13:23:23 -0700 Subject: [PATCH 1419/2898] kbuild: clang: remove crufty HOSTCFLAGS When compiling with `make CC=clang HOSTCC=clang`, I was seeing warnings that clang did not recognize -fno-delete-null-pointer-checks for HOSTCC targets. These were added in commit 61163efae020 ("kbuild: LLVMLinux: Add Kbuild support for building kernel with Clang"). Clang does not support -fno-delete-null-pointer-checks, so adding it to HOSTCFLAGS if HOSTCC is clang does not make sense. It's not clear why the other warnings were disabled, and just for HOSTCFLAGS, but I can remove them, add -Werror to HOSTCFLAGS and compile with clang just fine. Suggested-by: Masahiro Yamada Signed-off-by: Nick Desaulniers Signed-off-by: Masahiro Yamada --- Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Makefile b/Makefile index 1ec97b902e52..1254719958ca 100644 --- a/Makefile +++ b/Makefile @@ -365,11 +365,6 @@ HOSTCXXFLAGS := -O2 $(HOST_LFS_CFLAGS) HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) HOST_LOADLIBES := $(HOST_LFS_LIBS) -ifeq ($(shell $(HOSTCC) -v 2>&1 | grep -c "clang version"), 1) -HOSTCFLAGS += -Wno-unused-value -Wno-unused-parameter \ - -Wno-missing-field-initializers -fno-delete-null-pointer-checks -endif - # Make variables (CC, etc...) AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld -- GitLab From 8fdc3fbbd5b646650efa66d577b88807a948a1d1 Mon Sep 17 00:00:00 2001 From: Cao jin Date: Mon, 9 Oct 2017 11:49:11 +0800 Subject: [PATCH 1420/2898] kbuild: comments cleanup in Makefile.lib It has: 1. Move comments close to what it want to comment. 2. Comments cleanup & improvement. Signed-off-by: Cao jin Signed-off-by: Masahiro Yamada --- scripts/Makefile.lib | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 5e975fee0f5b..580e605118e4 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -4,8 +4,7 @@ ccflags-y += $(EXTRA_CFLAGS) cppflags-y += $(EXTRA_CPPFLAGS) ldflags-y += $(EXTRA_LDFLAGS) -# -# flags that take effect in sub directories +# flags that take effect in current and sub directories export KBUILD_SUBDIR_ASFLAGS := $(KBUILD_SUBDIR_ASFLAGS) $(subdir-asflags-y) export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y) @@ -14,14 +13,16 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y) # When an object is listed to be built compiled-in and modular, # only build the compiled-in version - obj-m := $(filter-out $(obj-y),$(obj-m)) # Libraries are always collected in one lib file. # Filter out objects already built-in - lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) +# Determine modorder. +# Unfortunately, we don't have information about ordering between -y +# and -m subdirs. Just put -y's first. +modorder := $(patsubst %/,%/modules.order, $(filter %/, $(obj-y)) $(obj-m:.o=.ko)) # Handle objects in subdirs # --------------------------------------------------------------------------- @@ -29,12 +30,6 @@ lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) # and add the directory to the list of dirs to descend into: $(subdir-y) # o if we encounter foo/ in $(obj-m), remove it from $(obj-m) # and add the directory to the list of dirs to descend into: $(subdir-m) - -# Determine modorder. -# Unfortunately, we don't have information about ordering between -y -# and -m subdirs. Just put -y's first. -modorder := $(patsubst %/,%/modules.order, $(filter %/, $(obj-y)) $(obj-m:.o=.ko)) - __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) subdir-y += $(__subdir-y) __subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) @@ -43,10 +38,9 @@ obj-y := $(patsubst %/, %/built-in.o, $(obj-y)) obj-m := $(filter-out %/, $(obj-m)) # Subdirectories we need to descend into - subdir-ym := $(sort $(subdir-y) $(subdir-m)) -# if $(foo-objs) exists, foo.o is a composite object +# if $(foo-objs), $(foo-y), or $(foo-m) exists, foo.o is a composite object multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))), $(m)))) multi-used := $(multi-used-y) $(multi-used-m) @@ -90,8 +84,7 @@ subdir-ym := $(addprefix $(obj)/,$(subdir-ym)) obj-dirs := $(addprefix $(obj)/,$(obj-dirs)) # These flags are needed for modversions and compiling, so we define them here -# already -# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will +# $(modname_flags) defines KBUILD_MODNAME as the name of the module it will # end up in (or would, if it gets compiled in) # Note: Files that end up in two or more modules are compiled without the # KBUILD_MODNAME definition. The reason is that any made-up name would -- GitLab From 47dd47292828a552d62d0e68b7cd6bdc99d9e0aa Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Tue, 17 Oct 2017 14:46:07 +0200 Subject: [PATCH 1421/2898] rtc: ds1307: add OF and ACPI entries for Epson RX8130 Make Epson RX8130 device tree and ACPI aware. Fixes: ee0981be7704 ("rtc: ds1307: Add support for Epson RX8130CE") Signed-off-by: Bastian Stender Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 1cca20fdd025..923dde912f60 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -325,6 +325,10 @@ static const struct of_device_id ds1307_of_match[] = { .compatible = "isil,isl12057", .data = (void *)ds_1337 }, + { + .compatible = "epson,rx8130", + .data = (void *)rx_8130 + }, { } }; MODULE_DEVICE_TABLE(of, ds1307_of_match); @@ -348,6 +352,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = { { .id = "PT7C4338", .driver_data = ds_1307 }, { .id = "RX8025", .driver_data = rx_8025 }, { .id = "ISL12057", .driver_data = ds_1337 }, + { .id = "RX8130", .driver_data = rx_8130 }, { } }; MODULE_DEVICE_TABLE(acpi, ds1307_acpi_ids); -- GitLab From 3ba2c76a9d3a339cd1b77e88915680ae2e9ac2da Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 27 Oct 2017 13:09:47 +0200 Subject: [PATCH 1422/2898] rtc: ds1390: Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. Worse, the compatible is documented but doesn't currently match the driver. Add the proper compatible to the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1390.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index aa0d2c6f1edc..4d5b007d7fc6 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c @@ -216,9 +216,16 @@ static int ds1390_probe(struct spi_device *spi) return res; } +static const struct of_device_id ds1390_of_match[] = { + { .compatible = "dallas,ds1390" }, + {} +}; +MODULE_DEVICE_TABLE(of, ds1390_of_match); + static struct spi_driver ds1390_driver = { .driver = { .name = "rtc-ds1390", + .of_match_table = of_match_ptr(ds1390_of_match), }, .probe = ds1390_probe, }; -- GitLab From 739c64414f01748a36e7d82c8e0611dea94412bd Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 20 Oct 2017 15:16:21 +0300 Subject: [PATCH 1423/2898] mtd: nand: omap2: Fix subpage write Since v4.12, NAND subpage writes were causing a NULL pointer dereference on OMAP platforms (omap2-nand) using OMAP_ECC_BCH4_CODE_HW, OMAP_ECC_BCH8_CODE_HW and OMAP_ECC_BCH16_CODE_HW. This is because for those ECC modes, omap_calculate_ecc_bch() generates ECC bytes for the entire (multi-sector) page and this can overflow the ECC buffer provided by nand_write_subpage_hwecc() as it expects ecc.calculate() to return ECC bytes for just one sector. However, the root cause of the problem is present since v3.9 but was not seen then as NAND buffers were being allocated as one big chunk prior to commit 3deb9979c731 ("mtd: nand: allocate aligned buffers if NAND_OWN_BUFFERS is unset"). Fix the issue by providing a OMAP optimized write_subpage() implementation. Fixes: 62116e5171e0 ("mtd: nand: omap2: Support for hardware BCH error correction.") Cc: Signed-off-by: Roger Quadros Signed-off-by: Boris Brezillon --- drivers/mtd/nand/omap2.c | 339 ++++++++++++++++++++++++++------------- 1 file changed, 224 insertions(+), 115 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index a97c1aeed55e..dad438c4906a 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1133,129 +1133,172 @@ static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2, 0x97, 0x79, 0xe5, 0x24, 0xb5}; /** - * omap_calculate_ecc_bch - Generate bytes of ECC bytes + * _omap_calculate_ecc_bch - Generate ECC bytes for one sector * @mtd: MTD device structure * @dat: The pointer to data on which ecc is computed * @ecc_code: The ecc_code buffer + * @i: The sector number (for a multi sector page) * - * Support calculating of BCH4/8 ecc vectors for the page + * Support calculating of BCH4/8/16 ECC vectors for one sector + * within a page. Sector number is in @i. */ -static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, - const u_char *dat, u_char *ecc_calc) +static int _omap_calculate_ecc_bch(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_calc, int i) { struct omap_nand_info *info = mtd_to_omap(mtd); int eccbytes = info->nand.ecc.bytes; struct gpmc_nand_regs *gpmc_regs = &info->reg; u8 *ecc_code; - unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; + unsigned long bch_val1, bch_val2, bch_val3, bch_val4; u32 val; - int i, j; + int j; + + ecc_code = ecc_calc; + switch (info->ecc_opt) { + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: + case OMAP_ECC_BCH8_CODE_HW: + bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); + bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); + bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]); + bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]); + *ecc_code++ = (bch_val4 & 0xFF); + *ecc_code++ = ((bch_val3 >> 24) & 0xFF); + *ecc_code++ = ((bch_val3 >> 16) & 0xFF); + *ecc_code++ = ((bch_val3 >> 8) & 0xFF); + *ecc_code++ = (bch_val3 & 0xFF); + *ecc_code++ = ((bch_val2 >> 24) & 0xFF); + *ecc_code++ = ((bch_val2 >> 16) & 0xFF); + *ecc_code++ = ((bch_val2 >> 8) & 0xFF); + *ecc_code++ = (bch_val2 & 0xFF); + *ecc_code++ = ((bch_val1 >> 24) & 0xFF); + *ecc_code++ = ((bch_val1 >> 16) & 0xFF); + *ecc_code++ = ((bch_val1 >> 8) & 0xFF); + *ecc_code++ = (bch_val1 & 0xFF); + break; + case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: + case OMAP_ECC_BCH4_CODE_HW: + bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); + bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); + *ecc_code++ = ((bch_val2 >> 12) & 0xFF); + *ecc_code++ = ((bch_val2 >> 4) & 0xFF); + *ecc_code++ = ((bch_val2 & 0xF) << 4) | + ((bch_val1 >> 28) & 0xF); + *ecc_code++ = ((bch_val1 >> 20) & 0xFF); + *ecc_code++ = ((bch_val1 >> 12) & 0xFF); + *ecc_code++ = ((bch_val1 >> 4) & 0xFF); + *ecc_code++ = ((bch_val1 & 0xF) << 4); + break; + case OMAP_ECC_BCH16_CODE_HW: + val = readl(gpmc_regs->gpmc_bch_result6[i]); + ecc_code[0] = ((val >> 8) & 0xFF); + ecc_code[1] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result5[i]); + ecc_code[2] = ((val >> 24) & 0xFF); + ecc_code[3] = ((val >> 16) & 0xFF); + ecc_code[4] = ((val >> 8) & 0xFF); + ecc_code[5] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result4[i]); + ecc_code[6] = ((val >> 24) & 0xFF); + ecc_code[7] = ((val >> 16) & 0xFF); + ecc_code[8] = ((val >> 8) & 0xFF); + ecc_code[9] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result3[i]); + ecc_code[10] = ((val >> 24) & 0xFF); + ecc_code[11] = ((val >> 16) & 0xFF); + ecc_code[12] = ((val >> 8) & 0xFF); + ecc_code[13] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result2[i]); + ecc_code[14] = ((val >> 24) & 0xFF); + ecc_code[15] = ((val >> 16) & 0xFF); + ecc_code[16] = ((val >> 8) & 0xFF); + ecc_code[17] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result1[i]); + ecc_code[18] = ((val >> 24) & 0xFF); + ecc_code[19] = ((val >> 16) & 0xFF); + ecc_code[20] = ((val >> 8) & 0xFF); + ecc_code[21] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result0[i]); + ecc_code[22] = ((val >> 24) & 0xFF); + ecc_code[23] = ((val >> 16) & 0xFF); + ecc_code[24] = ((val >> 8) & 0xFF); + ecc_code[25] = ((val >> 0) & 0xFF); + break; + default: + return -EINVAL; + } + + /* ECC scheme specific syndrome customizations */ + switch (info->ecc_opt) { + case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: + /* Add constant polynomial to remainder, so that + * ECC of blank pages results in 0x0 on reading back + */ + for (j = 0; j < eccbytes; j++) + ecc_calc[j] ^= bch4_polynomial[j]; + break; + case OMAP_ECC_BCH4_CODE_HW: + /* Set 8th ECC byte as 0x0 for ROM compatibility */ + ecc_calc[eccbytes - 1] = 0x0; + break; + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: + /* Add constant polynomial to remainder, so that + * ECC of blank pages results in 0x0 on reading back + */ + for (j = 0; j < eccbytes; j++) + ecc_calc[j] ^= bch8_polynomial[j]; + break; + case OMAP_ECC_BCH8_CODE_HW: + /* Set 14th ECC byte as 0x0 for ROM compatibility */ + ecc_calc[eccbytes - 1] = 0x0; + break; + case OMAP_ECC_BCH16_CODE_HW: + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * omap_calculate_ecc_bch_sw - ECC generator for sector for SW based correction + * @mtd: MTD device structure + * @dat: The pointer to data on which ecc is computed + * @ecc_code: The ecc_code buffer + * + * Support calculating of BCH4/8/16 ECC vectors for one sector. This is used + * when SW based correction is required as ECC is required for one sector + * at a time. + */ +static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_calc) +{ + return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0); +} + +/** + * omap_calculate_ecc_bch_multi - Generate ECC for multiple sectors + * @mtd: MTD device structure + * @dat: The pointer to data on which ecc is computed + * @ecc_code: The ecc_code buffer + * + * Support calculating of BCH4/8/16 ecc vectors for the entire page in one go. + */ +static int omap_calculate_ecc_bch_multi(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_calc) +{ + struct omap_nand_info *info = mtd_to_omap(mtd); + int eccbytes = info->nand.ecc.bytes; + unsigned long nsectors; + int i, ret; nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; for (i = 0; i < nsectors; i++) { - ecc_code = ecc_calc; - switch (info->ecc_opt) { - case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: - case OMAP_ECC_BCH8_CODE_HW: - bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); - bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); - bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]); - bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]); - *ecc_code++ = (bch_val4 & 0xFF); - *ecc_code++ = ((bch_val3 >> 24) & 0xFF); - *ecc_code++ = ((bch_val3 >> 16) & 0xFF); - *ecc_code++ = ((bch_val3 >> 8) & 0xFF); - *ecc_code++ = (bch_val3 & 0xFF); - *ecc_code++ = ((bch_val2 >> 24) & 0xFF); - *ecc_code++ = ((bch_val2 >> 16) & 0xFF); - *ecc_code++ = ((bch_val2 >> 8) & 0xFF); - *ecc_code++ = (bch_val2 & 0xFF); - *ecc_code++ = ((bch_val1 >> 24) & 0xFF); - *ecc_code++ = ((bch_val1 >> 16) & 0xFF); - *ecc_code++ = ((bch_val1 >> 8) & 0xFF); - *ecc_code++ = (bch_val1 & 0xFF); - break; - case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: - case OMAP_ECC_BCH4_CODE_HW: - bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); - bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); - *ecc_code++ = ((bch_val2 >> 12) & 0xFF); - *ecc_code++ = ((bch_val2 >> 4) & 0xFF); - *ecc_code++ = ((bch_val2 & 0xF) << 4) | - ((bch_val1 >> 28) & 0xF); - *ecc_code++ = ((bch_val1 >> 20) & 0xFF); - *ecc_code++ = ((bch_val1 >> 12) & 0xFF); - *ecc_code++ = ((bch_val1 >> 4) & 0xFF); - *ecc_code++ = ((bch_val1 & 0xF) << 4); - break; - case OMAP_ECC_BCH16_CODE_HW: - val = readl(gpmc_regs->gpmc_bch_result6[i]); - ecc_code[0] = ((val >> 8) & 0xFF); - ecc_code[1] = ((val >> 0) & 0xFF); - val = readl(gpmc_regs->gpmc_bch_result5[i]); - ecc_code[2] = ((val >> 24) & 0xFF); - ecc_code[3] = ((val >> 16) & 0xFF); - ecc_code[4] = ((val >> 8) & 0xFF); - ecc_code[5] = ((val >> 0) & 0xFF); - val = readl(gpmc_regs->gpmc_bch_result4[i]); - ecc_code[6] = ((val >> 24) & 0xFF); - ecc_code[7] = ((val >> 16) & 0xFF); - ecc_code[8] = ((val >> 8) & 0xFF); - ecc_code[9] = ((val >> 0) & 0xFF); - val = readl(gpmc_regs->gpmc_bch_result3[i]); - ecc_code[10] = ((val >> 24) & 0xFF); - ecc_code[11] = ((val >> 16) & 0xFF); - ecc_code[12] = ((val >> 8) & 0xFF); - ecc_code[13] = ((val >> 0) & 0xFF); - val = readl(gpmc_regs->gpmc_bch_result2[i]); - ecc_code[14] = ((val >> 24) & 0xFF); - ecc_code[15] = ((val >> 16) & 0xFF); - ecc_code[16] = ((val >> 8) & 0xFF); - ecc_code[17] = ((val >> 0) & 0xFF); - val = readl(gpmc_regs->gpmc_bch_result1[i]); - ecc_code[18] = ((val >> 24) & 0xFF); - ecc_code[19] = ((val >> 16) & 0xFF); - ecc_code[20] = ((val >> 8) & 0xFF); - ecc_code[21] = ((val >> 0) & 0xFF); - val = readl(gpmc_regs->gpmc_bch_result0[i]); - ecc_code[22] = ((val >> 24) & 0xFF); - ecc_code[23] = ((val >> 16) & 0xFF); - ecc_code[24] = ((val >> 8) & 0xFF); - ecc_code[25] = ((val >> 0) & 0xFF); - break; - default: - return -EINVAL; - } + ret = _omap_calculate_ecc_bch(mtd, dat, ecc_calc, i); + if (ret) + return ret; - /* ECC scheme specific syndrome customizations */ - switch (info->ecc_opt) { - case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: - /* Add constant polynomial to remainder, so that - * ECC of blank pages results in 0x0 on reading back */ - for (j = 0; j < eccbytes; j++) - ecc_calc[j] ^= bch4_polynomial[j]; - break; - case OMAP_ECC_BCH4_CODE_HW: - /* Set 8th ECC byte as 0x0 for ROM compatibility */ - ecc_calc[eccbytes - 1] = 0x0; - break; - case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: - /* Add constant polynomial to remainder, so that - * ECC of blank pages results in 0x0 on reading back */ - for (j = 0; j < eccbytes; j++) - ecc_calc[j] ^= bch8_polynomial[j]; - break; - case OMAP_ECC_BCH8_CODE_HW: - /* Set 14th ECC byte as 0x0 for ROM compatibility */ - ecc_calc[eccbytes - 1] = 0x0; - break; - case OMAP_ECC_BCH16_CODE_HW: - break; - default: - return -EINVAL; - } - - ecc_calc += eccbytes; + ecc_calc += eccbytes; } return 0; @@ -1496,7 +1539,7 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, chip->write_buf(mtd, buf, mtd->writesize); /* Update ecc vector from GPMC result registers */ - chip->ecc.calculate(mtd, buf, &ecc_calc[0]); + omap_calculate_ecc_bch_multi(mtd, buf, &ecc_calc[0]); ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, chip->ecc.total); @@ -1508,6 +1551,72 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, return 0; } +/** + * omap_write_subpage_bch - BCH hardware ECC based subpage write + * @mtd: mtd info structure + * @chip: nand chip info structure + * @offset: column address of subpage within the page + * @data_len: data length + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB + * @page: page number to write + * + * OMAP optimized subpage write method. + */ +static int omap_write_subpage_bch(struct mtd_info *mtd, + struct nand_chip *chip, u32 offset, + u32 data_len, const u8 *buf, + int oob_required, int page) +{ + u8 *ecc_calc = chip->buffers->ecccalc; + int ecc_size = chip->ecc.size; + int ecc_bytes = chip->ecc.bytes; + int ecc_steps = chip->ecc.steps; + u32 start_step = offset / ecc_size; + u32 end_step = (offset + data_len - 1) / ecc_size; + int step, ret = 0; + + /* + * Write entire page at one go as it would be optimal + * as ECC is calculated by hardware. + * ECC is calculated for all subpages but we choose + * only what we want. + */ + + /* Enable GPMC ECC engine */ + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + + /* Write data */ + chip->write_buf(mtd, buf, mtd->writesize); + + for (step = 0; step < ecc_steps; step++) { + /* mask ECC of un-touched subpages by padding 0xFF */ + if (step < start_step || step > end_step) + memset(ecc_calc, 0xff, ecc_bytes); + else + ret = _omap_calculate_ecc_bch(mtd, buf, ecc_calc, step); + + if (ret) + return ret; + + buf += ecc_size; + ecc_calc += ecc_bytes; + } + + /* copy calculated ECC for whole page to chip->buffer->oob */ + /* this include masked-value(0xFF) for unwritten subpages */ + ecc_calc = chip->buffers->ecccalc; + ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; + + /* write OOB buffer to NAND device */ + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; +} + /** * omap_read_page_bch - BCH ecc based page read function for entire page * @mtd: mtd info structure @@ -1544,7 +1653,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, chip->ecc.total); /* Calculate ecc bytes */ - chip->ecc.calculate(mtd, buf, ecc_calc); + omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc); ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, chip->ecc.total); @@ -2023,7 +2132,7 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.strength = 4; nand_chip->ecc.hwctl = omap_enable_hwecc_bch; nand_chip->ecc.correct = nand_bch_correct_data; - nand_chip->ecc.calculate = omap_calculate_ecc_bch; + nand_chip->ecc.calculate = omap_calculate_ecc_bch_sw; mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops); /* Reserve one byte for the OMAP marker */ oobbytes_per_step = nand_chip->ecc.bytes + 1; @@ -2045,9 +2154,9 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.strength = 4; nand_chip->ecc.hwctl = omap_enable_hwecc_bch; nand_chip->ecc.correct = omap_elm_correct_data; - nand_chip->ecc.calculate = omap_calculate_ecc_bch; nand_chip->ecc.read_page = omap_read_page_bch; nand_chip->ecc.write_page = omap_write_page_bch; + nand_chip->ecc.write_subpage = omap_write_subpage_bch; mtd_set_ooblayout(mtd, &omap_ooblayout_ops); oobbytes_per_step = nand_chip->ecc.bytes; @@ -2066,7 +2175,7 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.strength = 8; nand_chip->ecc.hwctl = omap_enable_hwecc_bch; nand_chip->ecc.correct = nand_bch_correct_data; - nand_chip->ecc.calculate = omap_calculate_ecc_bch; + nand_chip->ecc.calculate = omap_calculate_ecc_bch_sw; mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops); /* Reserve one byte for the OMAP marker */ oobbytes_per_step = nand_chip->ecc.bytes + 1; @@ -2088,9 +2197,9 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.strength = 8; nand_chip->ecc.hwctl = omap_enable_hwecc_bch; nand_chip->ecc.correct = omap_elm_correct_data; - nand_chip->ecc.calculate = omap_calculate_ecc_bch; nand_chip->ecc.read_page = omap_read_page_bch; nand_chip->ecc.write_page = omap_write_page_bch; + nand_chip->ecc.write_subpage = omap_write_subpage_bch; mtd_set_ooblayout(mtd, &omap_ooblayout_ops); oobbytes_per_step = nand_chip->ecc.bytes; @@ -2110,9 +2219,9 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->ecc.strength = 16; nand_chip->ecc.hwctl = omap_enable_hwecc_bch; nand_chip->ecc.correct = omap_elm_correct_data; - nand_chip->ecc.calculate = omap_calculate_ecc_bch; nand_chip->ecc.read_page = omap_read_page_bch; nand_chip->ecc.write_page = omap_write_page_bch; + nand_chip->ecc.write_subpage = omap_write_subpage_bch; mtd_set_ooblayout(mtd, &omap_ooblayout_ops); oobbytes_per_step = nand_chip->ecc.bytes; -- GitLab From cfab22c01258389578358eb93cb8e973307df6f2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 27 Oct 2017 17:25:50 +0300 Subject: [PATCH 1424/2898] platform/x86: intel_telemetry: Add needed inclusion linux/io.h defines readq() and ioremap_nocache() / iounmap() functions. If not included, the build fails: intel_telemetry_pltdrv.c:1165:31: warning: assignment makes pointer from integer without a cast [-Wint-conversion] intel_telemetry_pltdrv.c:1165:33: error: implicit declaration of function 'ioremap_nocache' [-Werror=implicit-function-declaration] intel_telemetry_pltdrv.c:1202:3: error: implicit declaration of function 'iounmap' [-Werror=implicit-function-declaration] intel_telemetry_pltdrv.c:900:20: error: implicit declaration of function 'readq' [-Werror=implicit-function-declaration] Fix this by including linux/io.h. Reported-by: kbuild test robot Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_telemetry_pltdrv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c index 678abf2e9e92..2f889d6c270e 100644 --- a/drivers/platform/x86/intel_telemetry_pltdrv.c +++ b/drivers/platform/x86/intel_telemetry_pltdrv.c @@ -16,6 +16,8 @@ * It used the PUNIT and PMC IPC interfaces for configuring the counters. * The accumulated results are fetched from SRAM. */ + +#include #include #include -- GitLab From 026930bc06e95b93c3200036ab3b44b783dc6f9d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 27 Oct 2017 17:30:16 +0300 Subject: [PATCH 1425/2898] platform/x86: intel_telemetry: Remove useless default in Kconfig 'default n' is a default behaviour of Kconfig options. So, remove explicit line from Kconfig. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 1f7959ff055c..0fdf68865c5e 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -1101,7 +1101,6 @@ config INTEL_PUNIT_IPC config INTEL_TELEMETRY tristate "Intel SoC Telemetry Driver" - default n depends on INTEL_PMC_IPC && INTEL_PUNIT_IPC && X86_64 ---help--- This driver provides interfaces to configure and use -- GitLab From 9a68db7220d05fb28de139a7db93bd6866cc86fa Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 26 Oct 2017 00:03:27 -0400 Subject: [PATCH 1426/2898] Revert "drm/amd/display: Match actual state during S3 resume." This reverts commit 4f346e655d24140fb40b46f814506ba17ac34ea1. fix s3 hang issue. Acked-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d0ee1b3b8b5c..bb134a6320bf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -641,11 +641,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) struct drm_connector *connector; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; - struct dm_crtc_state *dm_crtc_state; - struct drm_plane *plane; - struct drm_plane_state *plane_state; - struct dm_plane_state *dm_plane_state; - struct dm_atomic_state *cached_state; int ret = 0; int i; @@ -684,34 +679,6 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) new_crtc_state->active_changed = true; - cached_state = to_dm_atomic_state(adev->dm.cached_state); - - /* - * During suspend, the cached state is saved before all streams are - * disabled. Refresh cached state to match actual current state before - * restoring it. - */ - WARN_ON(kref_read(&cached_state->context->refcount) > 1); - dc_release_state(cached_state->context); - - for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) { - dm_crtc_state = to_dm_crtc_state(new_crtc_state); - if (dm_crtc_state->stream) { - WARN_ON(kref_read(&dm_crtc_state->stream->refcount) > 1); - dc_stream_release(dm_crtc_state->stream); - dm_crtc_state->stream = NULL; - } - } - - for_each_new_plane_in_state(adev->dm.cached_state, plane, plane_state, i) { - dm_plane_state = to_dm_plane_state(plane_state); - if (dm_plane_state->dc_state) { - WARN_ON(kref_read(&dm_plane_state->dc_state->refcount) > 1); - dc_plane_state_release(dm_plane_state->dc_state); - dm_plane_state->dc_state = NULL; - } - } - ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); drm_atomic_state_put(adev->dm.cached_state); -- GitLab From 3b21b6d239f43c0d797bf0deb8c0f8c846862eb1 Mon Sep 17 00:00:00 2001 From: Jerry Zuo Date: Tue, 17 Oct 2017 15:36:13 -0400 Subject: [PATCH 1427/2898] drm/amd/display: Fix no display on Fiji MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allocate memory for the second pipe allocate_mem_input() needs to be done prior to program pipe front end. It shows sensitive to Fiji. Failure to do so will cause error in allocate memory  allocate_mem_input() on the second connected display. Signed-off-by: Jerry Zuo Signed-off-by: Yongqiang Sun Reviewed-by: Tony Cheng Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2a6d3ca12954..399a5984ada3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1370,16 +1370,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; - /* mst support - use total stream count */ - if (pipe_ctx->plane_res.mi != NULL) { - pipe_ctx->plane_res.mi->funcs->allocate_mem_input( - pipe_ctx->plane_res.mi, - stream->timing.h_total, - stream->timing.v_total, - stream->timing.pix_clk_khz, - context->stream_count); - } - pipe_ctx->stream->sink->link->psr_enabled = false; return DC_OK; @@ -2891,6 +2881,15 @@ static void dce110_apply_ctx_for_surface( if (pipe_ctx->stream != stream) continue; + /* Need to allocate mem before program front end for Fiji */ + if (pipe_ctx->plane_res.mi != NULL) + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, + pipe_ctx->stream->timing.pix_clk_khz, + context->stream_count); + dce110_program_front_end_for_pipe(dc, pipe_ctx); program_surface_visibility(dc, pipe_ctx); -- GitLab From 4d3e00dad80a2c317d542358620facd8ca698428 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 19 Oct 2017 22:34:15 +0530 Subject: [PATCH 1428/2898] drm/amd/display : add high part address calculation for underlay Currently the high part of the address structure is not populated in case of luma and chroma. This patch adds this calculation. Signed-off-by: Shirish S Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index bb134a6320bf..635a8a3df369 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1771,6 +1771,7 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, { uint64_t tiling_flags; uint64_t fb_location = 0; + uint64_t chroma_addr = 0; unsigned int awidth; const struct drm_framebuffer *fb = &amdgpu_fb->base; int ret = 0; @@ -1833,9 +1834,13 @@ static int fill_plane_attributes_from_fb(struct amdgpu_device *adev, plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; plane_state->address.video_progressive.luma_addr.low_part = lower_32_bits(fb_location); + plane_state->address.video_progressive.luma_addr.high_part + = upper_32_bits(fb_location); + chroma_addr = fb_location + (u64)(awidth * fb->height); plane_state->address.video_progressive.chroma_addr.low_part - = lower_32_bits(fb_location) + - (awidth * fb->height); + = lower_32_bits(chroma_addr); + plane_state->address.video_progressive.chroma_addr.high_part + = upper_32_bits(chroma_addr); plane_state->plane_size.video.luma_size.x = 0; plane_state->plane_size.video.luma_size.y = 0; plane_state->plane_size.video.luma_size.width = awidth; -- GitLab From 56087b31f4b2861c773185ec45d313b55dbbb69d Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 26 Oct 2017 16:15:01 +0530 Subject: [PATCH 1429/2898] drm/amd/display: fix high part address in dm_plane_helper_prepare_fb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The high part calculation of luma and chroma address' was missing in dm_plane_helper_prepare_fb(). This fix brings uniformity in the address' at atomic_check and atomic_commit for both RGB & YUV planes. Signed-off-by: Shirish S Reviewed-by: Michel Dänzer Reviewed-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 635a8a3df369..c2fefd3e657e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2896,6 +2896,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, struct amdgpu_framebuffer *afb; struct drm_gem_object *obj; struct amdgpu_bo *rbo; + uint64_t chroma_addr = 0; int r; struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old; unsigned int awidth; @@ -2937,11 +2938,16 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, plane_state->address.grph.addr.high_part = upper_32_bits(afb->address); } else { awidth = ALIGN(new_state->fb->width, 64); + plane_state->address.type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE; plane_state->address.video_progressive.luma_addr.low_part = lower_32_bits(afb->address); + plane_state->address.video_progressive.luma_addr.high_part + = upper_32_bits(afb->address); + chroma_addr = afb->address + (u64)(awidth * new_state->fb->height); plane_state->address.video_progressive.chroma_addr.low_part - = lower_32_bits(afb->address) + - (awidth * new_state->fb->height); + = lower_32_bits(chroma_addr); + plane_state->address.video_progressive.chroma_addr.high_part + = upper_32_bits(chroma_addr); } } -- GitLab From 7bef1af3b9c2a5690a41298b5986dbde82fbedbc Mon Sep 17 00:00:00 2001 From: Shirish S Date: Fri, 27 Oct 2017 03:25:55 +0000 Subject: [PATCH 1430/2898] drm/amd/display: check if modeset is required before adding plane Adding affected planes without checking if modeset is requested from the user space causes performance regression in video p/b scenarios when full screen p/b is not composited. Hence add a check before adding a plane as affected. bug: https://bugs.freedesktop.org/show_bug.cgi?id=103408 Acked-by: Alex Deucher Reviewed-by: Harry Wentland Signed-off-by: Shirish S Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c2fefd3e657e..fd3e995fc426 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4653,6 +4653,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } else { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) + continue; + if (!new_crtc_state->enable) continue; -- GitLab From 5520437bebf7c65507a12bb111eba79f35efba1d Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Sat, 21 Oct 2017 09:52:00 -0700 Subject: [PATCH 1431/2898] platform/x86: intel_turbo_max_3: Add Skylake platform Ev Kontsevoy reported that he can't see the presence of "/proc/sys/kernel/sched_itmt_enabled" on i9-7900x with Asrock x299 Taichi system even if he enabled "Turbo 3.0" in the BIOS. The problem is that even if one core max is 200MHz more than others, the current implementation couldn't enumerate that with the way the system is configured. The system by default configured for legacy mode (no HWP or speed shift technology), in this mode only way we can enumerate via the mail box interface as implemented in this driver. We were planing to only use this driver for Broadwell, but we need to extend this because some Skylake system has same issue as Braodwell systems. On this system BIOS allows to change to HWP mode, where we expect that we can enumerate favored core with ACPI-CPPC. But on this system the core priority is 0xff for all cores in CPPC object. So this is not an option. Hence this change allows Skylake systems to be enumerate favored core similar to Broadwell in legacy mode. Reported-and-tested-by: Ev Kontsevoy Signed-off-by: Srinivas Pandruvada Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_turbo_max_3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/intel_turbo_max_3.c b/drivers/platform/x86/intel_turbo_max_3.c index 4f60d8e32a0a..d4ea01805879 100644 --- a/drivers/platform/x86/intel_turbo_max_3.c +++ b/drivers/platform/x86/intel_turbo_max_3.c @@ -125,6 +125,7 @@ static int itmt_legacy_cpu_online(unsigned int cpu) static const struct x86_cpu_id itmt_legacy_cpu_ids[] = { ICPU(INTEL_FAM6_BROADWELL_X), + ICPU(INTEL_FAM6_SKYLAKE_X), {} }; -- GitLab From 163ca80013aafb6dc9cb295de3db7aeab9ab43f8 Mon Sep 17 00:00:00 2001 From: Osama Khan Date: Sat, 21 Oct 2017 10:42:21 +0000 Subject: [PATCH 1432/2898] platform/x86: hp_accel: Add quirk for HP ProBook 440 G4 Added support for HP ProBook 440 G4 laptops by including the accelerometer orientation quirk for that device. Testing was performed based on the axis orientation guidelines here: https://www.kernel.org/doc/Documentation/misc-devices/lis3lv02d which states "If the left side is elevated, X increases (becomes positive)". When tested, on lifting the left edge, x values became increasingly negative thus indicating an inverted x-axis on the installed lis3lv02d chip. This was compensated by adding an entry for this device in hp_accel.c specifying the quirk as x_inverted. The patch was tested on a ProBook 440 G4 device and x-axis as well as y and z-axis values are now generated as per spec. Signed-off-by: Osama Khan Signed-off-by: Andy Shevchenko --- drivers/platform/x86/hp_accel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 493d8910a74e..7b12abe86b94 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -240,6 +240,7 @@ static const struct dmi_system_id lis3lv02d_dmi_ids[] = { AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted), AXIS_DMI_MATCH("HPB432x", "HP ProBook 432", xy_rotated_left), AXIS_DMI_MATCH("HPB440G3", "HP ProBook 440 G3", x_inverted_usd), + AXIS_DMI_MATCH("HPB440G4", "HP ProBook 440 G4", x_inverted), AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left), AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted), AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap), -- GitLab From 05521bd3d117704a1458eb4d0c3ae821858658f2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 26 Oct 2017 17:12:33 +0200 Subject: [PATCH 1433/2898] mtd: spi-nor: stm32-quadspi: Fix uninitialized error return code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With gcc 4.1.2: drivers/mtd/spi-nor/stm32-quadspi.c: In function ‘stm32_qspi_tx_poll’: drivers/mtd/spi-nor/stm32-quadspi.c:230: warning: ‘ret’ may be used uninitialized in this function Indeed, if stm32_qspi_cmd.len is zero, ret will be uninitialized. This length is passed from outside the driver using the spi_nor.{read,write}{,_reg}() callbacks. Several functions in drivers/mtd/spi-nor/spi-nor.c (e.g. write_enable(), write_disable(), and erase_chip()) call spi_nor.write_reg() with a zero length. Fix this by returning an explicit zero on success. Fixes: 0d43d7ab277a048c ("mtd: spi-nor: add driver for STM32 quad spi flash controller") Signed-off-by: Geert Uytterhoeven Acked-by: Ludovic Barre Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/stm32-quadspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c b/drivers/mtd/spi-nor/stm32-quadspi.c index 86c0931543c5..ad6a3e1844cb 100644 --- a/drivers/mtd/spi-nor/stm32-quadspi.c +++ b/drivers/mtd/spi-nor/stm32-quadspi.c @@ -240,12 +240,12 @@ static int stm32_qspi_tx_poll(struct stm32_qspi *qspi, STM32_QSPI_FIFO_TIMEOUT_US); if (ret) { dev_err(qspi->dev, "fifo timeout (stat:%#x)\n", sr); - break; + return ret; } tx_fifo(buf++, qspi->io_base + QUADSPI_DR); } - return ret; + return 0; } static int stm32_qspi_tx_mm(struct stm32_qspi *qspi, -- GitLab From e812963b918656d875beb47c277fd0e29bd826af Mon Sep 17 00:00:00 2001 From: Ludovic Barre Date: Thu, 26 Oct 2017 17:12:35 +0200 Subject: [PATCH 1434/2898] mtd: spi-nor: stm32-quadspi: change license text -Change the license text with long template. -Change Copyright to STMicroelectronics. Signed-off-by: Ludovic Barre Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/stm32-quadspi.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c b/drivers/mtd/spi-nor/stm32-quadspi.c index ad6a3e1844cb..56b75fc226c3 100644 --- a/drivers/mtd/spi-nor/stm32-quadspi.c +++ b/drivers/mtd/spi-nor/stm32-quadspi.c @@ -1,9 +1,22 @@ /* - * stm32_quadspi.c + * Driver for stm32 quadspi controller * - * Copyright (C) 2017, Ludovic Barre + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Ludovic Barre author . * - * License terms: GNU General Public License (GPL), version 2 + * License terms: GPL V2.0. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * This program. If not, see . */ #include #include -- GitLab From 10cd4b7b7432d529d7f8b73979a846e33a573a9e Mon Sep 17 00:00:00 2001 From: Ludovic Barre Date: Thu, 26 Oct 2017 17:12:34 +0200 Subject: [PATCH 1435/2898] mtd: spi-nor: stm32-quadspi: fix prefetching outside fsize When memory-mapped mode is used, a prefetching mechanism fully managed by the hardware allows to optimize the read from external the QSPI memory. A 32-bytes FIFO is used for prefetching. When the limit of flash size - fifo size is reached the prefetching mechanism tries to read outside the fsize. The stm32 quadspi hardware become busy and should be aborted. Signed-off-by: Ludovic Barre Reported-by: Bruno Herrera Tested-by: Bruno Herrera Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/stm32-quadspi.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c b/drivers/mtd/spi-nor/stm32-quadspi.c index 56b75fc226c3..b3c7f6addba7 100644 --- a/drivers/mtd/spi-nor/stm32-quadspi.c +++ b/drivers/mtd/spi-nor/stm32-quadspi.c @@ -126,6 +126,7 @@ #define STM32_MAX_MMAP_SZ SZ_256M #define STM32_MAX_NORCHIP 2 +#define STM32_QSPI_FIFO_SZ 32 #define STM32_QSPI_FIFO_TIMEOUT_US 30000 #define STM32_QSPI_BUSY_TIMEOUT_US 100000 @@ -137,6 +138,7 @@ struct stm32_qspi_flash { u32 presc; u32 read_mode; bool registered; + u32 prefetch_limit; }; struct stm32_qspi { @@ -285,6 +287,7 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash, { struct stm32_qspi *qspi = flash->qspi; u32 ccr, dcr, cr; + u32 last_byte; int err; err = stm32_qspi_wait_nobusy(qspi); @@ -327,6 +330,10 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash, if (err) goto abort; writel_relaxed(FCR_CTCF, qspi->io_base + QUADSPI_FCR); + } else { + last_byte = cmd->addr + cmd->len; + if (last_byte > flash->prefetch_limit) + goto abort; } return err; @@ -335,7 +342,9 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash, cr = readl_relaxed(qspi->io_base + QUADSPI_CR) | CR_ABORT; writel_relaxed(cr, qspi->io_base + QUADSPI_CR); - dev_err(qspi->dev, "%s abort err:%d\n", __func__, err); + if (err) + dev_err(qspi->dev, "%s abort err:%d\n", __func__, err); + return err; } @@ -563,6 +572,7 @@ static int stm32_qspi_flash_setup(struct stm32_qspi *qspi, } flash->fsize = FSIZE_VAL(mtd->size); + flash->prefetch_limit = mtd->size - STM32_QSPI_FIFO_SZ; flash->read_mode = CCR_FMODE_MM; if (mtd->size > qspi->mm_size) -- GitLab From d342b6a973af459f6104cad6effc8efc71a0558d Mon Sep 17 00:00:00 2001 From: Roman Yeryomin Date: Mon, 18 Sep 2017 00:54:16 +0300 Subject: [PATCH 1436/2898] mtd: spi-nor: enable 4B opcodes for mx66l51235l Signed-off-by: Roman Yeryomin Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 51230cdb6a4d..31d308ab51cd 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1039,7 +1039,7 @@ static const struct flash_info spi_nor_ids[] = { { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, - { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, -- GitLab From b9b1504d3c6d6831c822cd785e095fc5fb155346 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 29 Oct 2017 12:13:07 -0700 Subject: [PATCH 1437/2898] acpi, nfit: hide unknown commands from nmemX/commands For vendor specific commands that do not have a common kernel translation, hide them from nmemX/commands. For example, the following results from new enabling to probe for support of the new NVDIMM_FAMILY_INTEL DSMs specified in v1.6 of the command specification [1]: # cat /sys/bus/nd/devices/nmem0/commands smart smart_thresh flags get_size get_data set_data effect_size effect_log vendor cmd_call unknown unknown unknown unknown unknown unknown unknown unknown [1]: https://pmem.io/documents/NVDIMM_DSM_Interface-V1.6.pdf Signed-off-by: Dan Williams --- drivers/acpi/nfit/core.c | 10 ++++++++-- drivers/acpi/nfit/nfit.h | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index ebe0857ac346..444832b372ec 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -1769,8 +1769,14 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc) * userspace interface. */ cmd_mask = 1UL << ND_CMD_CALL; - if (nfit_mem->family == NVDIMM_FAMILY_INTEL) - cmd_mask |= nfit_mem->dsm_mask; + if (nfit_mem->family == NVDIMM_FAMILY_INTEL) { + /* + * These commands have a 1:1 correspondence + * between DSM payload and libnvdimm ioctl + * payload format. + */ + cmd_mask |= nfit_mem->dsm_mask & NVDIMM_STANDARD_CMDMASK; + } if (nfit_mem->has_lsi) set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask); diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index 3976d649f27c..b987196bf132 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -38,6 +38,12 @@ | ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \ | ACPI_NFIT_MEM_NOT_ARMED | ACPI_NFIT_MEM_MAP_FAILED) +#define NVDIMM_STANDARD_CMDMASK \ +(1 << ND_CMD_SMART | 1 << ND_CMD_SMART_THRESHOLD | 1 << ND_CMD_DIMM_FLAGS \ + | 1 << ND_CMD_GET_CONFIG_SIZE | 1 << ND_CMD_GET_CONFIG_DATA \ + | 1 << ND_CMD_SET_CONFIG_DATA | 1 << ND_CMD_VENDOR_EFFECT_LOG_SIZE \ + | 1 << ND_CMD_VENDOR_EFFECT_LOG | 1 << ND_CMD_VENDOR) + enum nfit_uuids { /* for simplicity alias the uuid index with the family id */ NFIT_DEV_DIMM = NVDIMM_FAMILY_INTEL, -- GitLab From 1c782b9a851770b152ddd711d0a0cb295872ab50 Mon Sep 17 00:00:00 2001 From: Xiaolei Li Date: Sat, 28 Oct 2017 14:52:23 +0800 Subject: [PATCH 1438/2898] mtd: nand: mtk: change the compile sequence of mtk_nand.o and mtk_ecc.o There will get mtk ecc handler during mtk nand probe now. If mtk ecc module is not initialized, then mtk nand probe will return -EPROBE_DEFER, and retry later. Change the compile sequence of mtk_nand.o and mtk_ecc.o, initialize mtk ecc module before mtk nand module. This makes mtk nand module initialized as soon as possible. Signed-off-by: Xiaolei Li Signed-off-by: Boris Brezillon --- drivers/mtd/nand/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index ade5fc4c3819..57f4cdedf137 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -58,7 +58,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o -obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o +obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_amd.o -- GitLab From 282e45dc64d1832c9b51d2c6f6eb0a634c924fa7 Mon Sep 17 00:00:00 2001 From: Philipp Puschmann Date: Thu, 19 Oct 2017 10:12:47 +0200 Subject: [PATCH 1439/2898] mtd: spi-nor: Add support for mr25h128 Add Everspin mr25h128 16KB MRAM to the list of supported chips. Signed-off-by: Philipp Puschmann Signed-off-by: Cyrille Pitchen --- Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt | 1 + drivers/mtd/devices/m25p80.c | 1 + drivers/mtd/spi-nor/spi-nor.c | 1 + 3 files changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt index 9ce35af8507c..956bb046e599 100644 --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt @@ -13,6 +13,7 @@ Required properties: at25df321a at25df641 at26df081a + mr25h128 mr25h256 mr25h10 mr25h40 diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 00eea6fd379c..dbe6a1de2bb8 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -359,6 +359,7 @@ static const struct spi_device_id m25p_ids[] = { {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"}, /* Everspin MRAMs (non-JEDEC) */ + { "mr25h128" }, /* 128 Kib, 40 MHz */ { "mr25h256" }, /* 256 Kib, 40 MHz */ { "mr25h10" }, /* 1 Mib, 40 MHz */ { "mr25h40" }, /* 4 Mib, 40 MHz */ diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 31d308ab51cd..bc266f70a15b 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -968,6 +968,7 @@ static const struct flash_info spi_nor_ids[] = { { "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_LOCK) }, /* Everspin */ + { "mr25h128", CAT25_INFO( 16 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "mr25h40", CAT25_INFO(512 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -- GitLab From 4fbaf649ebbc625189e349fd6d07a4fe22a863f8 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 27 Oct 2017 15:23:44 -0700 Subject: [PATCH 1440/2898] ARC: [plat-axs10x] auto-select AXS101 or AXS103 given the ISA config AXS10x platform has two flavours: - AXS101 (ARC700 cpu, ARCompact ISA) - AXS103 (ARC HS38x cpu, ARCv2 ISA) So depending on the ISA support configured, pre-select the AXS10x variant. Signed-off-by: Vineet Gupta --- arch/arc/plat-axs10x/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig index c54d1ae57fe0..4e0df7b7a248 100644 --- a/arch/arc/plat-axs10x/Kconfig +++ b/arch/arc/plat-axs10x/Kconfig @@ -14,6 +14,8 @@ menuconfig ARC_PLAT_AXS10X select MIGHT_HAVE_PCI select GENERIC_IRQ_CHIP select GPIOLIB + select AXS101 if ISA_ARCOMPACT + select AXS103 if ISA_ARCV2 help Support for the ARC AXS10x Software Development Platforms. -- GitLab From 1d2fcdcf33339c7c8016243de0f7f31cf6845e8d Mon Sep 17 00:00:00 2001 From: Xiaolei Li Date: Mon, 30 Oct 2017 10:39:56 +0800 Subject: [PATCH 1441/2898] mtd: nand: mtk: fix infinite ECC decode IRQ issue For MT2701 NAND Controller, there may generate infinite ECC decode IRQ during long time burn test on some platforms. Once this issue occurred, the ECC decode IRQ status cannot be cleared in the IRQ handler function, and threads cannot be scheduled. ECC HW generates decode IRQ each sector, so there will have more than one decode IRQ if read one page of large page NAND. Currently, ECC IRQ handle flow is that we will check whether it is decode IRQ at first by reading the register ECC_DECIRQ_STA. This is a read-clear type register. If this IRQ is decode IRQ, then the ECC IRQ signal will be cleared at the same time. Secondly, we will check whether all sectors are decoded by reading the register ECC_DECDONE. This is because the current IRQ may be not dealed in time, and the next sectors have been decoded before reading the register ECC_DECIRQ_STA. Then, the next sectors's decode IRQs will not be generated. Thirdly, if all sectors are decoded by comparing with ecc->sectors, then we will complete ecc->done, set ecc->sectors as 0, and disable ECC IRQ by programming the register ECC_IRQ_REG(op) as 0. Otherwise, wait for the next ECC IRQ. But, there is a timing issue between step one and two. When we read the reigster ECC_DECIRQ_STA, all sectors are decoded except the last sector, and the ECC IRQ signal is cleared. But the last sector is decoded before reading ECC_DECDONE, so the ECC IRQ signal is enabled again by ECC HW, and it means we will receive one extra ECC IRQ later. In step three, we will find that all sectors were decoded, then disable ECC IRQ and return. When deal with the extra ECC IRQ, the ECC IRQ status cannot be cleared anymore. That is because the register ECC_DECIRQ_STA can only be cleared when the register ECC_IRQ_REG(op) is enabled. But actually we have disabled ECC IRQ in the previous ECC IRQ handle. So, there will keep receiving ECC decode IRQ. Now, we read the register ECC_DECIRQ_STA once again before completing the ecc done event. This ensures that there will be no extra ECC decode IRQ. Also, remove writel(0, ecc->regs + ECC_IRQ_REG(op)) from irq handler, because ECC IRQ is disabled in mtk_ecc_disable(). And clear ECC_DECIRQ_STA in mtk_ecc_disable() in case there is a timeout to wait decode IRQ. Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device") Cc: Signed-off-by: Xiaolei Li Signed-off-by: Boris Brezillon --- drivers/mtd/nand/mtk_ecc.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c index 7f3b065b6b8f..c51d214d169e 100644 --- a/drivers/mtd/nand/mtk_ecc.c +++ b/drivers/mtd/nand/mtk_ecc.c @@ -115,6 +115,11 @@ static irqreturn_t mtk_ecc_irq(int irq, void *id) op = ECC_DECODE; dec = readw(ecc->regs + ECC_DECDONE); if (dec & ecc->sectors) { + /* + * Clear decode IRQ status once again to ensure that + * there will be no extra IRQ. + */ + readw(ecc->regs + ECC_DECIRQ_STA); ecc->sectors = 0; complete(&ecc->done); } else { @@ -130,8 +135,6 @@ static irqreturn_t mtk_ecc_irq(int irq, void *id) } } - writel(0, ecc->regs + ECC_IRQ_REG(op)); - return IRQ_HANDLED; } @@ -307,6 +310,12 @@ void mtk_ecc_disable(struct mtk_ecc *ecc) /* disable it */ mtk_ecc_wait_idle(ecc, op); + if (op == ECC_DECODE) + /* + * Clear decode IRQ status in case there is a timeout to wait + * decode IRQ. + */ + readw(ecc->regs + ECC_DECIRQ_STA); writew(0, ecc->regs + ECC_IRQ_REG(op)); writew(ECC_OP_DISABLE, ecc->regs + ECC_CTL_REG(op)); -- GitLab From ec0a9f62b393ed0c5bb9185a8efebb0ad00b7d0d Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 29 Oct 2017 15:17:35 -0700 Subject: [PATCH 1442/2898] mtd: intel-spi: Add Intel Lewisburg PCH SPI super SKU PCI ID This patch adds Intel Lewisburg PCH SPI serial flash controller super SKU PCI ID. Signed-off-by: Kuppuswamy Sathyanarayanan Acked-by: Mika Westerberg Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/intel-spi-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi-nor/intel-spi-pci.c b/drivers/mtd/spi-nor/intel-spi-pci.c index a5a5c5897aad..c0976f2e3dd1 100644 --- a/drivers/mtd/spi-nor/intel-spi-pci.c +++ b/drivers/mtd/spi-nor/intel-spi-pci.c @@ -66,6 +66,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info }, + { PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info }, { }, }; MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids); -- GitLab From c7b3e98e4d0ada6aeaa8cc37a7e9ab16e7b3a4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Wed, 25 Oct 2017 06:29:46 +0200 Subject: [PATCH 1443/2898] platform/x86: fujitsu-laptop: Fix radio LED detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Radio LED detection method implemented in commit 4f62568c1fcf ("fujitsu-laptop: Support radio LED") turned out to be incorrect as it causes a radio LED to be erroneously detected on a Fujitsu Lifebook E751 which has a slide switch (and thus no radio LED). Use bit 17 of flags_supported (the value returned by method S000 of ACPI device FUJ02E3) to determine whether a radio LED is present as it seems to be a more reliable indicator, based on comparing DSDT tables of four Fujitsu Lifebook models (E744, E751, S7110, S8420). Fixes: 4f62568c1fcf ("fujitsu-laptop: Support radio LED") Reported-by: Heinrich Siebmanns Signed-off-by: Michał Kępień Tested-by: Heinrich Siebmanns Signed-off-by: Andy Shevchenko --- drivers/platform/x86/fujitsu-laptop.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 56a8195096a2..2cfbd3fa5136 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -691,6 +691,7 @@ static enum led_brightness eco_led_get(struct led_classdev *cdev) static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) { + struct fujitsu_laptop *priv = acpi_driver_data(device); struct led_classdev *led; int result; @@ -724,12 +725,15 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device) } /* - * BTNI bit 24 seems to indicate the presence of a radio toggle - * button in place of a slide switch, and all such machines appear - * to also have an RF LED. Therefore use bit 24 as an indicator - * that an RF LED is present. + * Some Fujitsu laptops have a radio toggle button in place of a slide + * switch and all such machines appear to also have an RF LED. Based on + * comparing DSDT tables of four Fujitsu Lifebook models (E744, E751, + * S7110, S8420; the first one has a radio toggle button, the other + * three have slide switches), bit 17 of flags_supported (the value + * returned by method S000 of ACPI device FUJ02E3) seems to indicate + * whether given model has a radio toggle button. */ - if (call_fext_func(device, FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) { + if (priv->flags_supported & BIT(17)) { led = devm_kzalloc(&device->dev, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; -- GitLab From da25f490a0b3d9c234d659b21024d61fe2d08c8e Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Thu, 26 Oct 2017 11:43:34 +0300 Subject: [PATCH 1444/2898] microblaze: add missing include to mmu_context_mm.h mmu_context_mm.h is using struct task_struct, which is defined in linux/sched.h. Source files that include mm_context_mm.h (directly or indirectly) and doesn't include linux/sched.h will generate an error. An example of that is drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c This patch adds an include of linux/sched.h to mmu_context_mm.h to avoid such errors. Signed-off-by: Oded Gabbay Signed-off-by: Michal Simek --- arch/microblaze/include/asm/mmu_context_mm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/microblaze/include/asm/mmu_context_mm.h b/arch/microblaze/include/asm/mmu_context_mm.h index 99472d2ca340..97559fe0b953 100644 --- a/arch/microblaze/include/asm/mmu_context_mm.h +++ b/arch/microblaze/include/asm/mmu_context_mm.h @@ -13,6 +13,7 @@ #include #include +#include #include #include -- GitLab From bc8293663b953c23ff7b73eb15f82393425e5e47 Mon Sep 17 00:00:00 2001 From: Baoquan He Date: Sun, 22 Oct 2017 22:30:55 +0800 Subject: [PATCH 1445/2898] printk: fix typo in printk_safe.c Link: http://lkml.kernel.org/r/1508682655-27293-1-git-send-email-bhe@redhat.com Cc: rostedt@goodmis.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Baoquan He Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk_safe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 3cdaeaef9ce1..89558b85f45c 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -75,7 +75,7 @@ static void queue_flush_work(struct printk_safe_seq_buf *s) * have dedicated buffers, because otherwise printk-safe preempted by * NMI-printk would have overwritten the NMI messages. * - * The messages are fushed from irq work (or from panic()), possibly, + * The messages are flushed from irq work (or from panic()), possibly, * from other CPU, concurrently with printk_safe_log_store(). Should this * happen, printk_safe_log_store() will notice the buffer->len mismatch * and repeat the write. -- GitLab From 9afe77ed849de6af8532b4c1b9310102eed9edf7 Mon Sep 17 00:00:00 2001 From: Maxim Akristiniy Date: Mon, 23 Oct 2017 19:51:48 +0300 Subject: [PATCH 1446/2898] added new line symbol after warning about dropped messages so this message will not mess with the next one Cc: Steven Rostedt Signed-off-by: Maxim Akristiniy Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 512f7c2baedd..5d81206a572d 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2190,7 +2190,7 @@ void console_unlock(void) } if (console_seq < log_first_seq) { - len = sprintf(text, "** %u printk messages dropped ** ", + len = sprintf(text, "** %u printk messages dropped **\n", (unsigned)(log_first_seq - console_seq)); /* messages are gone, move to first one */ -- GitLab From 336303ae7fad4a491290a800547b3fde80ac8865 Mon Sep 17 00:00:00 2001 From: Cao jin Date: Mon, 9 Oct 2017 15:11:45 +0800 Subject: [PATCH 1447/2898] arm/kbuild: replace {C, LD}FLAGS_MODULE with KBUILD_{C, LD}FLAGS_MODULE As kbuild document & commit 6588169d51 says: KBUILD_{C,LD}FLAGS_MODULE are used to add arch-specific options for $(CC) and $(LD). From commandline, {C,LD}FLAGS_MODULE shall be used. Doesn't have any functional change, but just follow kbuild rules. Signed-off-by: Cao jin CC: Russell King CC: linux-arm-kernel@lists.infradead.org Signed-off-by: Masahiro Yamada --- arch/arm/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 47d3a1ab08d2..a945b1fad0d1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -16,11 +16,11 @@ LDFLAGS := LDFLAGS_vmlinux :=-p --no-undefined -X --pic-veneer ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 -LDFLAGS_MODULE += --be8 +KBUILD_LDFLAGS_MODULE += --be8 endif ifeq ($(CONFIG_ARM_MODULE_PLTS),y) -LDFLAGS_MODULE += -T $(srctree)/arch/arm/kernel/module.lds +KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/arm/kernel/module.lds endif GZFLAGS :=-9 @@ -120,7 +120,7 @@ CFLAGS_ISA :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) AFLAGS_ISA :=$(CFLAGS_ISA) -Wa$(comma)-mthumb # Work around buggy relocation from gas if requested: ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y) -CFLAGS_MODULE +=-fno-optimize-sibling-calls +KBUILD_CFLAGS_MODULE +=-fno-optimize-sibling-calls endif else CFLAGS_ISA :=$(call cc-option,-marm,) -- GitLab From 265444a008ae4451f69a24efda7b3f542cb30f7d Mon Sep 17 00:00:00 2001 From: Cao jin Date: Mon, 9 Oct 2017 15:11:46 +0800 Subject: [PATCH 1448/2898] c6x/kbuild: replace CFLAGS_MODULE with KBUILD_CFLAGS_MODULE As kbuild document & commit 6588169d51 says: KBUILD_CFLAGS_MODULE is used to add arch-specific options for $(CC). From commandline, CFLAGS_MODULE shall be used. Doesn't have any functional change, but just follow kbuild rules. Signed-off-by: Cao jin CC: Mark Salter CC: Aurelien Jacquiot CC: linux-c6x-dev@linux-c6x.org Signed-off-by: Masahiro Yamada --- arch/c6x/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/c6x/Makefile b/arch/c6x/Makefile index 6b0be670ddfa..6f6096ff05a4 100644 --- a/arch/c6x/Makefile +++ b/arch/c6x/Makefile @@ -12,7 +12,7 @@ cflags-y += -mno-dsbt -msdata=none -D__linux__ cflags-$(CONFIG_C6X_BIG_KERNEL) += -mlong-calls -CFLAGS_MODULE += -mlong-calls -mno-dsbt -msdata=none +KBUILD_CFLAGS_MODULE += -mlong-calls -mno-dsbt -msdata=none CHECKFLAGS += -- GitLab From 3a5befc146175de8bf6c4eb68866a4f5ad46265a Mon Sep 17 00:00:00 2001 From: Cao jin Date: Mon, 9 Oct 2017 15:11:47 +0800 Subject: [PATCH 1449/2898] hexagon/kbuild: replace CFLAGS_MODULE with KBUILD_CFLAGS_MODULE As kbuild document & commit 6588169d51 says: KBUILD_CFLAGS_MODULE is used to add arch-specific options for $(CC). From commandline, CFLAGS_MODULE shall be used. Doesn't have any functional change, but just follow kbuild rules. Signed-off-by: Cao jin CC: linux-hexagon@vger.kernel.org Acked-by: Richard Kuo Signed-off-by: Masahiro Yamada --- arch/hexagon/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile index 207711a0fd0c..4f5c84c4bbb4 100644 --- a/arch/hexagon/Makefile +++ b/arch/hexagon/Makefile @@ -11,9 +11,9 @@ KBUILD_CFLAGS += -fno-short-enums # Modules must use either long-calls, or use pic/plt. # Use long-calls for now, it's easier. And faster. -# CFLAGS_MODULE += -fPIC -# LDFLAGS_MODULE += -shared -CFLAGS_MODULE += -mlong-calls +# KBUILD_CFLAGS_MODULE += -fPIC +# KBUILD_LDFLAGS_MODULE += -shared +KBUILD_CFLAGS_MODULE += -mlong-calls cflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION}) aflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION}) -- GitLab From 4e13d47c5806bafb5e524b08a9d759b606b1851c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 10 Oct 2017 20:43:21 +0900 Subject: [PATCH 1450/2898] kbuild: remove KBUILD_SUBDIR_ASFLAGS and KBUILD_SUBDIR_CCFLAGS Accumulate subdir-{cc,as}flags-y directly to KBUILD_{A,C}FLAGS. Remove KBUILD_SUBDIR_{AS,CC}FLAGS. Signed-off-by: Masahiro Yamada Reviewed-by: Cao jin --- scripts/Makefile.lib | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 580e605118e4..4d88ad70fd96 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -5,8 +5,8 @@ cppflags-y += $(EXTRA_CPPFLAGS) ldflags-y += $(EXTRA_LDFLAGS) # flags that take effect in current and sub directories -export KBUILD_SUBDIR_ASFLAGS := $(KBUILD_SUBDIR_ASFLAGS) $(subdir-asflags-y) -export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y) +KBUILD_AFLAGS += $(subdir-asflags-y) +KBUILD_CFLAGS += $(subdir-ccflags-y) # Figure out what we need to build from the various variables # =========================================================================== @@ -94,10 +94,10 @@ basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget)) modname_flags = $(if $(filter 1,$(words $(modname))),\ -DKBUILD_MODNAME=$(call name-fix,$(modname))) -orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \ +orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \ $(ccflags-y) $(CFLAGS_$(basetarget).o) _c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags)) -orig_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \ +orig_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) \ $(asflags-y) $(AFLAGS_$(basetarget).o) _a_flags = $(filter-out $(AFLAGS_REMOVE_$(basetarget).o), $(orig_a_flags)) _cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F)) -- GitLab From 11e142701609546632ba1fda586252d391026a3f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 20 Oct 2017 15:39:43 -0700 Subject: [PATCH 1451/2898] acpi, nfit: add support for NVDIMM_FAMILY_INTEL v1.6 DSMs Per v1.6 of the NVDIMM_FAMILY_INTEL command set [1] some of the new commands require rev-id 2. In addition to enabling ND_CMD_CALL for these new function numbers, add a lookup table for revision-ids by family and function number. [1]: http://pmem.io/documents/NVDIMM_DSM_Interface-V1.6.pdf Signed-off-by: Dan Williams --- drivers/acpi/nfit/core.c | 45 +++++++++++++++++++++++++++++++++++----- drivers/acpi/nfit/nfit.h | 26 ++++++++++++++++++++++- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 444832b372ec..aa75d67ceee9 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -370,6 +370,32 @@ static union acpi_object *acpi_label_info(acpi_handle handle) return pkg_to_buf(buf.pointer); } +static u8 nfit_dsm_revid(unsigned family, unsigned func) +{ + static const u8 revid_table[NVDIMM_FAMILY_MAX+1][32] = { + [NVDIMM_FAMILY_INTEL] = { + [NVDIMM_INTEL_GET_MODES] = 2, + [NVDIMM_INTEL_GET_FWINFO] = 2, + [NVDIMM_INTEL_START_FWUPDATE] = 2, + [NVDIMM_INTEL_SEND_FWUPDATE] = 2, + [NVDIMM_INTEL_FINISH_FWUPDATE] = 2, + [NVDIMM_INTEL_QUERY_FWUPDATE] = 2, + [NVDIMM_INTEL_SET_THRESHOLD] = 2, + [NVDIMM_INTEL_INJECT_ERROR] = 2, + }, + }; + u8 id; + + if (family > NVDIMM_FAMILY_MAX) + return 0; + if (func > 31) + return 0; + id = revid_table[family][func]; + if (id == 0) + return 1; /* default */ + return id; +} + int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) { @@ -468,8 +494,15 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, out_obj = acpi_label_write(handle, p->in_offset, p->in_length, p->in_buf); - } else - out_obj = acpi_evaluate_dsm(handle, guid, 1, func, &in_obj); + } else { + u8 revid; + + if (nfit_mem) + revid = nfit_dsm_revid(nfit_mem->family, func); + else + revid = 1; + out_obj = acpi_evaluate_dsm(handle, guid, revid, func, &in_obj); + } if (!out_obj) { dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name, @@ -1640,7 +1673,7 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, * different command sets. Note, that checking for function0 (bit0) * tells us if any commands are reachable through this GUID. */ - for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_MSFT; i++) + for (i = 0; i <= NVDIMM_FAMILY_MAX; i++) if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1)) if (family < 0 || i == default_dsm_family) family = i; @@ -1650,7 +1683,7 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, if (override_dsm_mask && !disable_vendor_specific) dsm_mask = override_dsm_mask; else if (nfit_mem->family == NVDIMM_FAMILY_INTEL) { - dsm_mask = 0x3fe; + dsm_mask = NVDIMM_INTEL_CMDMASK; if (disable_vendor_specific) dsm_mask &= ~(1 << ND_CMD_VENDOR); } else if (nfit_mem->family == NVDIMM_FAMILY_HPE1) { @@ -1670,7 +1703,9 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, guid = to_nfit_uuid(nfit_mem->family); for_each_set_bit(i, &dsm_mask, BITS_PER_LONG) - if (acpi_check_dsm(adev_dimm->handle, guid, 1, 1ULL << i)) + if (acpi_check_dsm(adev_dimm->handle, guid, + nfit_dsm_revid(nfit_mem->family, i), + 1ULL << i)) set_bit(i, &nfit_mem->dsm_mask); obj = acpi_label_info(adev_dimm->handle); diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index b987196bf132..341be9511d0e 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -24,7 +24,7 @@ /* ACPI 6.1 */ #define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba" -/* http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf */ +/* http://pmem.io/documents/NVDIMM_DSM_Interface-V1.6.pdf */ #define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66" /* https://github.com/HewlettPackard/hpe-nvm/blob/master/Documentation/ */ @@ -38,12 +38,36 @@ | ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \ | ACPI_NFIT_MEM_NOT_ARMED | ACPI_NFIT_MEM_MAP_FAILED) +#define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_MSFT + #define NVDIMM_STANDARD_CMDMASK \ (1 << ND_CMD_SMART | 1 << ND_CMD_SMART_THRESHOLD | 1 << ND_CMD_DIMM_FLAGS \ | 1 << ND_CMD_GET_CONFIG_SIZE | 1 << ND_CMD_GET_CONFIG_DATA \ | 1 << ND_CMD_SET_CONFIG_DATA | 1 << ND_CMD_VENDOR_EFFECT_LOG_SIZE \ | 1 << ND_CMD_VENDOR_EFFECT_LOG | 1 << ND_CMD_VENDOR) +/* + * Command numbers that the kernel needs to know about to handle + * non-default DSM revision ids + */ +enum nvdimm_family_cmds { + NVDIMM_INTEL_GET_MODES = 11, + NVDIMM_INTEL_GET_FWINFO = 12, + NVDIMM_INTEL_START_FWUPDATE = 13, + NVDIMM_INTEL_SEND_FWUPDATE = 14, + NVDIMM_INTEL_FINISH_FWUPDATE = 15, + NVDIMM_INTEL_QUERY_FWUPDATE = 16, + NVDIMM_INTEL_SET_THRESHOLD = 17, + NVDIMM_INTEL_INJECT_ERROR = 18, +}; + +#define NVDIMM_INTEL_CMDMASK \ +(NVDIMM_STANDARD_CMDMASK | 1 << NVDIMM_INTEL_GET_MODES \ + | 1 << NVDIMM_INTEL_GET_FWINFO | 1 << NVDIMM_INTEL_START_FWUPDATE \ + | 1 << NVDIMM_INTEL_SEND_FWUPDATE | 1 << NVDIMM_INTEL_FINISH_FWUPDATE \ + | 1 << NVDIMM_INTEL_QUERY_FWUPDATE | 1 << NVDIMM_INTEL_SET_THRESHOLD \ + | 1 << NVDIMM_INTEL_INJECT_ERROR) + enum nfit_uuids { /* for simplicity alias the uuid index with the family id */ NFIT_DEV_DIMM = NVDIMM_FAMILY_INTEL, -- GitLab From d82bd359972a7fe71a778396cf287bc9f9f3b981 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 24 Oct 2017 21:22:24 +0530 Subject: [PATCH 1452/2898] firmware: scm: Add new SCM call API for switching memory ownership Two different processors on a SOC need to switch memory ownership during load/unload. To enable this, second level memory map table need to be updated, which is done by secure layer. This patch adds the interface for making secure monitor call for memory ownership switching request. Acked-by: Andy Gross Signed-off-by: Avaneesh Kumar Dwivedi [bjorn: Minor style and kerneldoc updates] Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom_scm-32.c | 7 +++ drivers/firmware/qcom_scm-64.c | 27 ++++++++++ drivers/firmware/qcom_scm.c | 95 ++++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.h | 5 ++ include/linux/qcom_scm.h | 16 ++++++ 5 files changed, 150 insertions(+) diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c index 93e3b96b6dfa..60d96bcf6694 100644 --- a/drivers/firmware/qcom_scm-32.c +++ b/drivers/firmware/qcom_scm-32.c @@ -579,6 +579,13 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) return ret ? : le32_to_cpu(scm_ret); } +int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, + size_t mem_sz, phys_addr_t src, size_t src_sz, + phys_addr_t dest, size_t dest_sz) +{ + return -ENODEV; +} + int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) { diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 6e6d561708e2..ea5b1e680f67 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -382,6 +382,33 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) return ret ? : res.a1; } +int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, + size_t mem_sz, phys_addr_t src, size_t src_sz, + phys_addr_t dest, size_t dest_sz) +{ + int ret; + struct qcom_scm_desc desc = {0}; + struct arm_smccc_res res; + + desc.args[0] = mem_region; + desc.args[1] = mem_sz; + desc.args[2] = src; + desc.args[3] = src_sz; + desc.args[4] = dest; + desc.args[5] = dest_sz; + desc.args[6] = 0; + + desc.arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL, + QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, + QCOM_MEM_PROT_ASSIGN_ID, + &desc, &res); + + return ret ? : res.a1; +} + int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare) { struct qcom_scm_desc desc = {0}; diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index bb16510d75ba..334eaa341828 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -40,6 +40,19 @@ struct qcom_scm { struct reset_controller_dev reset; }; +struct qcom_scm_current_perm_info { + __le32 vmid; + __le32 perm; + __le64 ctx; + __le32 ctx_size; + __le32 unused; +}; + +struct qcom_scm_mem_map_info { + __le64 mem_addr; + __le64 mem_size; +}; + static struct qcom_scm *__scm; static int qcom_scm_clk_enable(void) @@ -348,6 +361,88 @@ int qcom_scm_set_remote_state(u32 state, u32 id) } EXPORT_SYMBOL(qcom_scm_set_remote_state); +/** + * qcom_scm_assign_mem() - Make a secure call to reassign memory ownership + * @mem_addr: mem region whose ownership need to be reassigned + * @mem_sz: size of the region. + * @srcvm: vmid for current set of owners, each set bit in + * flag indicate a unique owner + * @newvm: array having new owners and corrsponding permission + * flags + * @dest_cnt: number of owners in next set. + * + * Return negative errno on failure, 0 on success, with @srcvm updated. + */ +int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, + unsigned int *srcvm, + struct qcom_scm_vmperm *newvm, int dest_cnt) +{ + struct qcom_scm_current_perm_info *destvm; + struct qcom_scm_mem_map_info *mem_to_map; + phys_addr_t mem_to_map_phys; + phys_addr_t dest_phys; + phys_addr_t ptr_phys; + size_t mem_to_map_sz; + size_t dest_sz; + size_t src_sz; + size_t ptr_sz; + int next_vm; + __le32 *src; + void *ptr; + int ret; + int len; + int i; + + src_sz = hweight_long(*srcvm) * sizeof(*src); + mem_to_map_sz = sizeof(*mem_to_map); + dest_sz = dest_cnt * sizeof(*destvm); + ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) + + ALIGN(dest_sz, SZ_64); + + ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_phys, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + /* Fill source vmid detail */ + src = ptr; + len = hweight_long(*srcvm); + for (i = 0; i < len; i++) { + src[i] = cpu_to_le32(ffs(*srcvm) - 1); + *srcvm ^= 1 << (ffs(*srcvm) - 1); + } + + /* Fill details of mem buff to map */ + mem_to_map = ptr + ALIGN(src_sz, SZ_64); + mem_to_map_phys = ptr_phys + ALIGN(src_sz, SZ_64); + mem_to_map[0].mem_addr = cpu_to_le64(mem_addr); + mem_to_map[0].mem_size = cpu_to_le64(mem_sz); + + next_vm = 0; + /* Fill details of next vmid detail */ + destvm = ptr + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64); + dest_phys = ptr_phys + ALIGN(mem_to_map_sz, SZ_64) + ALIGN(src_sz, SZ_64); + for (i = 0; i < dest_cnt; i++) { + destvm[i].vmid = cpu_to_le32(newvm[i].vmid); + destvm[i].perm = cpu_to_le32(newvm[i].perm); + destvm[i].ctx = 0; + destvm[i].ctx_size = 0; + next_vm |= BIT(newvm[i].vmid); + } + + ret = __qcom_scm_assign_mem(__scm->dev, mem_to_map_phys, mem_to_map_sz, + ptr_phys, src_sz, dest_phys, dest_sz); + dma_free_coherent(__scm->dev, ALIGN(ptr_sz, SZ_64), ptr, ptr_phys); + if (ret) { + dev_err(__scm->dev, + "Assign memory protection call failed %d.\n", ret); + return -EINVAL; + } + + *srcvm = next_vm; + return 0; +} +EXPORT_SYMBOL(qcom_scm_assign_mem); + static int qcom_scm_probe(struct platform_device *pdev) { struct qcom_scm *scm; diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 9bea691f30fb..fe54b7ba4db4 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -95,5 +95,10 @@ extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, size_t *size); extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, u32 spare); +#define QCOM_MEM_PROT_ASSIGN_ID 0x16 +extern int __qcom_scm_assign_mem(struct device *dev, + phys_addr_t mem_region, size_t mem_sz, + phys_addr_t src, size_t src_sz, + phys_addr_t dest, size_t dest_sz); #endif diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index e5380471c2cd..6f8da9e182f9 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -23,6 +23,19 @@ struct qcom_scm_hdcp_req { u32 val; }; +struct qcom_scm_vmperm { + int vmid; + int perm; +}; + +#define QCOM_SCM_VMID_HLOS 0x3 +#define QCOM_SCM_VMID_MSS_MSA 0xF +#define QCOM_SCM_PERM_READ 0x4 +#define QCOM_SCM_PERM_WRITE 0x2 +#define QCOM_SCM_PERM_EXEC 0x1 +#define QCOM_SCM_PERM_RW (QCOM_SCM_PERM_READ | QCOM_SCM_PERM_WRITE) +#define QCOM_SCM_PERM_RWX (QCOM_SCM_PERM_RW | QCOM_SCM_PERM_EXEC) + #if IS_ENABLED(CONFIG_QCOM_SCM) extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); @@ -37,6 +50,9 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size); extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); +extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, + unsigned int *src, struct qcom_scm_vmperm *newvm, + int dest_cnt); extern void qcom_scm_cpu_power_down(u32 flags); extern u32 qcom_scm_get_version(void); extern int qcom_scm_set_remote_state(u32 state, u32 id); -- GitLab From 94c907859a4c678de8e74eeece5c0487b5629361 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 24 Oct 2017 21:22:25 +0530 Subject: [PATCH 1453/2898] remoteproc: qcom: refactor mss fw image loading sequence This patch refactor code to first load all firmware blobs and then update modem proc to authenticate and boot fw. Tested-and-acked-by: Bjorn Andersson Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 2d3d5ac92c06..39b9ee4a63b7 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -504,7 +504,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) bool relocate = false; char seg_name[10]; ssize_t offset; - size_t size; + size_t size = 0; void *ptr; int ret; int i; @@ -542,7 +542,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) } mpss_reloc = relocate ? min_addr : qproc->mpss_phys; - + /* Load firmware segments */ for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; @@ -575,18 +575,15 @@ static int q6v5_mpss_load(struct q6v5 *qproc) memset(ptr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); } - - size = readl(qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); - if (!size) { - boot_addr = relocate ? qproc->mpss_phys : min_addr; - writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG); - writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG); - } - size += phdr->p_memsz; - writel(size, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); } + /* Transfer ownership of modem ddr region with q6*/ + boot_addr = relocate ? qproc->mpss_phys : min_addr; + writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG); + writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG); + writel(size, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); + ret = q6v5_rmb_mba_wait(qproc, RMB_MBA_AUTH_COMPLETE, 10000); if (ret == -ETIMEDOUT) dev_err(qproc->dev, "MPSS authentication timed out\n"); -- GitLab From 6c5a9dc2481b4819c00bbcef8005b59c04d64963 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 24 Oct 2017 21:22:26 +0530 Subject: [PATCH 1454/2898] remoteproc: qcom: Make secure world call for mem ownership switch MSS proc on msm8996 can not access fw loaded region without stage second translation of memory pages where mpss image are loaded. This patch in order to enable mss boot on msm8996 invoke scm call to switch or share ownership between apps and modem. Signed-off-by: Avaneesh Kumar Dwivedi [bjorn: Corrected error path in q6v5_start()] Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 106 +++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 39b9ee4a63b7..728179ba7db2 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -110,6 +110,7 @@ struct rproc_hexagon_res { struct qcom_mss_reg_res *active_supply; char **proxy_clk_names; char **active_clk_names; + bool need_mem_protection; }; struct q6v5 { @@ -154,6 +155,10 @@ struct q6v5 { struct qcom_rproc_subdev smd_subdev; struct qcom_rproc_ssr ssr_subdev; + bool need_mem_protection; + int mpss_perm; + int mba_perm; + }; static int q6v5_regulator_init(struct device *dev, struct reg_info *regs, @@ -289,6 +294,35 @@ static struct resource_table *q6v5_find_rsc_table(struct rproc *rproc, return &table; } +static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm, + bool remote_owner, phys_addr_t addr, + size_t size) +{ + struct qcom_scm_vmperm next; + int ret; + + if (!qproc->need_mem_protection) + return 0; + if (remote_owner && *current_perm == BIT(QCOM_SCM_VMID_MSS_MSA)) + return 0; + if (!remote_owner && *current_perm == BIT(QCOM_SCM_VMID_HLOS)) + return 0; + + next.vmid = remote_owner ? QCOM_SCM_VMID_MSS_MSA : QCOM_SCM_VMID_HLOS; + next.perm = remote_owner ? QCOM_SCM_PERM_RW : QCOM_SCM_PERM_RWX; + + ret = qcom_scm_assign_mem(addr, ALIGN(size, SZ_4K), + current_perm, &next, 1); + if (ret < 0) { + pr_err("Failed to assign memory access in range %p to %p to %s ret = %d\n", + (void *)addr, (void *)(addr + size), + remote_owner ? "mss" : "hlos", ret); + return ret; + } + + return 0; +} + static int q6v5_load(struct rproc *rproc, const struct firmware *fw) { struct q6v5 *qproc = rproc->priv; @@ -451,6 +485,8 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) { unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; dma_addr_t phys; + int mdata_perm; + int xferop_ret; void *ptr; int ret; @@ -462,6 +498,13 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) memcpy(ptr, fw->data, fw->size); + /* Hypervisor mapping to access metadata by modem */ + mdata_perm = BIT(QCOM_SCM_VMID_HLOS); + ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, + true, phys, fw->size); + if (ret) + return -EAGAIN; + writel(phys, qproc->rmb_base + RMB_PMI_META_DATA_REG); writel(RMB_CMD_META_DATA_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG); @@ -471,6 +514,13 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) else if (ret < 0) dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret); + /* Metadata authentication done, remove modem access */ + xferop_ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, + false, phys, fw->size); + if (xferop_ret) + dev_warn(qproc->dev, + "mdt buffer not reclaimed system may become unstable\n"); + dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs); return ret < 0 ? ret : 0; @@ -578,7 +628,12 @@ static int q6v5_mpss_load(struct q6v5 *qproc) size += phdr->p_memsz; } - /* Transfer ownership of modem ddr region with q6*/ + /* Transfer ownership of modem ddr region to q6 */ + ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, true, + qproc->mpss_phys, qproc->mpss_size); + if (ret) + return -EAGAIN; + boot_addr = relocate ? qproc->mpss_phys : min_addr; writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG); writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG); @@ -599,6 +654,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) static int q6v5_start(struct rproc *rproc) { struct q6v5 *qproc = (struct q6v5 *)rproc->priv; + int xfermemop_ret; int ret; ret = q6v5_regulator_enable(qproc, qproc->proxy_regs, @@ -634,11 +690,18 @@ static int q6v5_start(struct rproc *rproc) goto assert_reset; } + /* Assign MBA image access in DDR to q6 */ + xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true, + qproc->mba_phys, + qproc->mba_size); + if (xfermemop_ret) + goto disable_active_clks; + writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG); ret = q6v5proc_reset(qproc); if (ret) - goto halt_axi_ports; + goto reclaim_mba; ret = q6v5_rmb_mba_wait(qproc, 0, 5000); if (ret == -ETIMEDOUT) { @@ -655,16 +718,22 @@ static int q6v5_start(struct rproc *rproc) ret = q6v5_mpss_load(qproc); if (ret) - goto halt_axi_ports; + goto reclaim_mpss; ret = wait_for_completion_timeout(&qproc->start_done, msecs_to_jiffies(5000)); if (ret == 0) { dev_err(qproc->dev, "start timed out\n"); ret = -ETIMEDOUT; - goto halt_axi_ports; + goto reclaim_mpss; } + xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, false, + qproc->mba_phys, + qproc->mba_size); + if (xfermemop_ret) + dev_err(qproc->dev, + "Failed to reclaim mba buffer system may become unstable\n"); qproc->running = true; q6v5_clk_disable(qproc->dev, qproc->proxy_clks, @@ -674,12 +743,30 @@ static int q6v5_start(struct rproc *rproc) return 0; +reclaim_mpss: + xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, + false, qproc->mpss_phys, + qproc->mpss_size); + WARN_ON(xfermemop_ret); + halt_axi_ports: q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); + +reclaim_mba: + xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, false, + qproc->mba_phys, + qproc->mba_size); + if (xfermemop_ret) { + dev_err(qproc->dev, + "Failed to reclaim mba buffer, system may become unstable\n"); + } + +disable_active_clks: q6v5_clk_disable(qproc->dev, qproc->active_clks, qproc->active_clk_count); + assert_reset: reset_control_assert(qproc->mss_restart); disable_vdd: @@ -699,6 +786,7 @@ static int q6v5_stop(struct rproc *rproc) { struct q6v5 *qproc = (struct q6v5 *)rproc->priv; int ret; + u32 val; qproc->running = false; @@ -716,6 +804,10 @@ static int q6v5_stop(struct rproc *rproc) q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); + ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, false, + qproc->mpss_phys, qproc->mpss_size); + WARN_ON(ret); + reset_control_assert(qproc->mss_restart); q6v5_clk_disable(qproc->dev, qproc->active_clks, qproc->active_clk_count); @@ -1014,6 +1106,7 @@ static int q6v5_probe(struct platform_device *pdev) if (ret) goto free_rproc; + qproc->need_mem_protection = desc->need_mem_protection; ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt); if (ret < 0) goto free_rproc; @@ -1035,7 +1128,8 @@ static int q6v5_probe(struct platform_device *pdev) ret = PTR_ERR(qproc->state); goto free_rproc; } - + qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS); + qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS); qcom_add_smd_subdev(rproc, &qproc->smd_subdev); qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); @@ -1091,6 +1185,7 @@ static const struct rproc_hexagon_res msm8916_mss = { "mem", NULL }, + .need_mem_protection = false, }; static const struct rproc_hexagon_res msm8974_mss = { @@ -1128,6 +1223,7 @@ static const struct rproc_hexagon_res msm8974_mss = { "mem", NULL }, + .need_mem_protection = false, }; static const struct of_device_id q6v5_of_match[] = { -- GitLab From 9f058fa2efb10cd75884c4ee6c357bab07715f02 Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Tue, 24 Oct 2017 21:22:27 +0530 Subject: [PATCH 1455/2898] remoteproc: qcom: Add support for mss remoteproc on msm8996 This patch add support for mss boot on msm8996. Major changes include initializing mss rproc for msm8996, making appropriate change for executing mss reset sequence etc. Tested-and-acked-by: Bjorn Andersson Signed-off-by: Avaneesh Kumar Dwivedi Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,q6v5.txt | 1 + drivers/remoteproc/qcom_q6v5_pil.c | 164 +++++++++++++++--- 2 files changed, 141 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt index 7ff3f7903f26..00d3d58a102f 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt +++ b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt @@ -10,6 +10,7 @@ on the Qualcomm Hexagon core. "qcom,q6v5-pil", "qcom,msm8916-mss-pil", "qcom,msm8974-mss-pil" + "qcom,msm8996-mss-pil" - reg: Usage: required diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 728179ba7db2..5460f61ee21c 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "remoteproc_internal.h" #include "qcom_common.h" @@ -64,6 +65,8 @@ #define QDSP6SS_RESET_REG 0x014 #define QDSP6SS_GFMUX_CTL_REG 0x020 #define QDSP6SS_PWR_CTL_REG 0x030 +#define QDSP6SS_MEM_PWR_CTL 0x0B0 +#define QDSP6SS_STRAP_ACC 0x110 /* AXI Halt Register Offsets */ #define AXI_HALTREQ_REG 0x0 @@ -92,6 +95,15 @@ #define QDSS_BHS_ON BIT(21) #define QDSS_LDO_BYP BIT(22) +/* QDSP6v56 parameters */ +#define QDSP6v56_LDO_BYP BIT(25) +#define QDSP6v56_BHS_ON BIT(24) +#define QDSP6v56_CLAMP_WL BIT(21) +#define QDSP6v56_CLAMP_QMC_MEM BIT(22) +#define HALT_CHECK_MAX_LOOPS 200 +#define QDSP6SS_XO_CBCR 0x0038 +#define QDSP6SS_ACC_OVERRIDE_VAL 0x20 + struct reg_info { struct regulator *reg; int uV; @@ -110,6 +122,7 @@ struct rproc_hexagon_res { struct qcom_mss_reg_res *active_supply; char **proxy_clk_names; char **active_clk_names; + int version; bool need_mem_protection; }; @@ -158,7 +171,13 @@ struct q6v5 { bool need_mem_protection; int mpss_perm; int mba_perm; + int version; +}; +enum { + MSS_MSM8916, + MSS_MSM8974, + MSS_MSM8996, }; static int q6v5_regulator_init(struct device *dev, struct reg_info *regs, @@ -387,33 +406,98 @@ static int q6v5proc_reset(struct q6v5 *qproc) { u32 val; int ret; + int i; - /* Assert resets, stop core */ - val = readl(qproc->reg_base + QDSP6SS_RESET_REG); - val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE); - writel(val, qproc->reg_base + QDSP6SS_RESET_REG); - /* Enable power block headswitch, and wait for it to stabilize */ - val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); - val |= QDSS_BHS_ON | QDSS_LDO_BYP; - writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); - udelay(1); - - /* - * Turn on memories. L2 banks should be done individually - * to minimize inrush current. - */ - val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); - val |= Q6SS_SLP_RET_N | Q6SS_L2TAG_SLP_NRET_N | - Q6SS_ETB_SLP_NRET_N | Q6SS_L2DATA_STBY_N; - writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); - val |= Q6SS_L2DATA_SLP_NRET_N_2; - writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); - val |= Q6SS_L2DATA_SLP_NRET_N_1; - writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); - val |= Q6SS_L2DATA_SLP_NRET_N_0; - writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + if (qproc->version == MSS_MSM8996) { + /* Override the ACC value if required */ + writel(QDSP6SS_ACC_OVERRIDE_VAL, + qproc->reg_base + QDSP6SS_STRAP_ACC); + /* Assert resets, stop core */ + val = readl(qproc->reg_base + QDSP6SS_RESET_REG); + val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE; + writel(val, qproc->reg_base + QDSP6SS_RESET_REG); + + /* BHS require xo cbcr to be enabled */ + val = readl(qproc->reg_base + QDSP6SS_XO_CBCR); + val |= 0x1; + writel(val, qproc->reg_base + QDSP6SS_XO_CBCR); + + /* Read CLKOFF bit to go low indicating CLK is enabled */ + ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_XO_CBCR, + val, !(val & BIT(31)), 1, + HALT_CHECK_MAX_LOOPS); + if (ret) { + dev_err(qproc->dev, + "xo cbcr enabling timed out (rc:%d)\n", ret); + return ret; + } + /* Enable power block headswitch and wait for it to stabilize */ + val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= QDSP6v56_BHS_ON; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + udelay(1); + + /* Put LDO in bypass mode */ + val |= QDSP6v56_LDO_BYP; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + + /* Deassert QDSP6 compiler memory clamp */ + val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val &= ~QDSP6v56_CLAMP_QMC_MEM; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + + /* Deassert memory peripheral sleep and L2 memory standby */ + val |= Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + + /* Turn on L1, L2, ETB and JU memories 1 at a time */ + val = readl(qproc->reg_base + QDSP6SS_MEM_PWR_CTL); + for (i = 19; i >= 0; i--) { + val |= BIT(i); + writel(val, qproc->reg_base + + QDSP6SS_MEM_PWR_CTL); + /* + * Read back value to ensure the write is done then + * wait for 1us for both memory peripheral and data + * array to turn on. + */ + val |= readl(qproc->reg_base + QDSP6SS_MEM_PWR_CTL); + udelay(1); + } + /* Remove word line clamp */ + val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val &= ~QDSP6v56_CLAMP_WL; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + } else { + /* Assert resets, stop core */ + val = readl(qproc->reg_base + QDSP6SS_RESET_REG); + val |= Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE; + writel(val, qproc->reg_base + QDSP6SS_RESET_REG); + + /* Enable power block headswitch and wait for it to stabilize */ + val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= QDSS_BHS_ON | QDSS_LDO_BYP; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + udelay(1); + /* + * Turn on memories. L2 banks should be done individually + * to minimize inrush current. + */ + val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= Q6SS_SLP_RET_N | Q6SS_L2TAG_SLP_NRET_N | + Q6SS_ETB_SLP_NRET_N | Q6SS_L2DATA_STBY_N; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= Q6SS_L2DATA_SLP_NRET_N_2; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= Q6SS_L2DATA_SLP_NRET_N_1; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= Q6SS_L2DATA_SLP_NRET_N_0; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + } /* Remove IO clamp */ val &= ~Q6SS_CLAMP_IO; writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); @@ -803,6 +887,16 @@ static int q6v5_stop(struct rproc *rproc) q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem); q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); + if (qproc->version == MSS_MSM8996) { + /* + * To avoid high MX current during LPASS/MSS restart. + */ + val = readl(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= Q6SS_CLAMP_IO | QDSP6v56_CLAMP_WL | + QDSP6v56_CLAMP_QMC_MEM; + writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + } + ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, false, qproc->mpss_phys, qproc->mpss_size); @@ -1106,6 +1200,7 @@ static int q6v5_probe(struct platform_device *pdev) if (ret) goto free_rproc; + qproc->version = desc->version; qproc->need_mem_protection = desc->need_mem_protection; ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt); if (ret < 0) @@ -1158,6 +1253,24 @@ static int q6v5_remove(struct platform_device *pdev) return 0; } +static const struct rproc_hexagon_res msm8996_mss = { + .hexagon_mba_image = "mba.mbn", + .proxy_clk_names = (char*[]){ + "xo", + "pnoc", + NULL + }, + .active_clk_names = (char*[]){ + "iface", + "bus", + "mem", + "gpll0_mss_clk", + NULL + }, + .need_mem_protection = true, + .version = MSS_MSM8996, +}; + static const struct rproc_hexagon_res msm8916_mss = { .hexagon_mba_image = "mba.mbn", .proxy_supply = (struct qcom_mss_reg_res[]) { @@ -1186,6 +1299,7 @@ static const struct rproc_hexagon_res msm8916_mss = { NULL }, .need_mem_protection = false, + .version = MSS_MSM8916, }; static const struct rproc_hexagon_res msm8974_mss = { @@ -1224,12 +1338,14 @@ static const struct rproc_hexagon_res msm8974_mss = { NULL }, .need_mem_protection = false, + .version = MSS_MSM8974, }; static const struct of_device_id q6v5_of_match[] = { { .compatible = "qcom,q6v5-pil", .data = &msm8916_mss}, { .compatible = "qcom,msm8916-mss-pil", .data = &msm8916_mss}, { .compatible = "qcom,msm8974-mss-pil", .data = &msm8974_mss}, + { .compatible = "qcom,msm8996-mss-pil", .data = &msm8996_mss}, { }, }; MODULE_DEVICE_TABLE(of, q6v5_of_match); -- GitLab From 2394facb17bcace4b3c19b50202177a5d8903b64 Mon Sep 17 00:00:00 2001 From: Arun Kumar Neelakantam Date: Mon, 30 Oct 2017 11:11:24 +0530 Subject: [PATCH 1456/2898] rpmsg: glink: Initialize the "intent_req_comp" completion variable The "intent_req_comp" variable is used without initialization which results in NULL pointer dereference in qcom_glink_request_intent(). we need to initialize the completion variable before using it. Fixes: 27b9c5b66b23 ("rpmsg: glink: Request for intents when unavailable") Signed-off-by: Arun Kumar Neelakantam Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 5dcc9bf1c5bc..fcd46ab090a7 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -227,6 +227,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, init_completion(&channel->open_req); init_completion(&channel->open_ack); + init_completion(&channel->intent_req_comp); INIT_LIST_HEAD(&channel->done_intents); INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work); -- GitLab From eace566c3406cac3131d44198f05b7b55f79651f Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Thu, 26 Oct 2017 15:28:54 -0700 Subject: [PATCH 1457/2898] dt-bindings: soc: qcom: Support GLINK intents Virtual GLINK channels may know what throughput to expect from a remoteproc. An intent advertises to the remoteproc this channel is ready to receive data. Allow a channel to define the size and amount of intents to be prequeued. Acked-by: Rob Herring Signed-off-by: Chris Lew Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/soc/qcom/qcom,glink.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt index b277eca861f7..9663cab52246 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt @@ -39,6 +39,14 @@ of these nodes are defined by the individual bindings for the specific function Definition: a list of channels tied to this function, used for matching the function to a set of virtual channels +- qcom,intents: + Usage: optional + Value type: + Definition: a list of size,amount pairs describing what intents should + be preallocated for this virtual channel. This can be used + to tweak the default intents available for the channel to + meet expectations of the remote. + = EXAMPLE The following example represents the GLINK RPM node on a MSM8996 device, with the function for the "rpm_request" channel defined, which is used for @@ -69,6 +77,8 @@ regualtors and root clocks. compatible = "qcom,rpm-msm8996"; qcom,glink-channels = "rpm_requests"; + qcom,intents = <0x400 5 + 0x800 1>; ... }; }; -- GitLab From 073893778dc2f68e41d65d79925ca89db526b4ab Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Thu, 26 Oct 2017 15:28:55 -0700 Subject: [PATCH 1458/2898] rpmsg: glink: Add support to preallocate intents The base intents prequeued during channel creation may not satisfy a channel's throughput requirement. Add support for intents dt-binding to allow channels to specify the size and amount of intents to prequeue during endpoint announcement. Signed-off-by: Chris Lew [bjorn: Altered how defaults are expressed] Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index fcd46ab090a7..2dff77882ced 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1149,19 +1149,38 @@ static struct rpmsg_endpoint *qcom_glink_create_ept(struct rpmsg_device *rpdev, static int qcom_glink_announce_create(struct rpmsg_device *rpdev) { struct glink_channel *channel = to_glink_channel(rpdev->ept); - struct glink_core_rx_intent *intent; + struct device_node *np = rpdev->dev.of_node; struct qcom_glink *glink = channel->glink; - int num_intents = glink->intentless ? 0 : 5; + struct glink_core_rx_intent *intent; + const struct property *prop = NULL; + __be32 defaults[] = { cpu_to_be32(SZ_1K), cpu_to_be32(5) }; + int num_intents; + int num_groups = 1; + __be32 *val = defaults; + int size; + + if (glink->intentless) + return 0; + + prop = of_find_property(np, "qcom,intents", NULL); + if (prop) { + val = prop->value; + num_groups = prop->length / sizeof(u32) / 2; + } /* Channel is now open, advertise base set of intents */ - while (num_intents--) { - intent = qcom_glink_alloc_intent(glink, channel, SZ_1K, true); - if (!intent) - break; + while (num_groups--) { + size = be32_to_cpup(val++); + num_intents = be32_to_cpup(val++); + while (num_intents--) { + intent = qcom_glink_alloc_intent(glink, channel, size, + true); + if (!intent) + break; - qcom_glink_advertise_intent(glink, channel, intent); + qcom_glink_advertise_intent(glink, channel, intent); + } } - return 0; } -- GitLab From 290318702bb2e7d74c24fbe52d8184fc79a17e93 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Thu, 26 Oct 2017 15:28:56 -0700 Subject: [PATCH 1459/2898] rpmsg: glink: Use best fit intent during tx Intents can vary in size, try to find the best fitting remote intent instead of first fit when sending a message to the remote proc. Signed-off-by: Chris Lew Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 2dff77882ced..80d9af307b40 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1257,11 +1257,16 @@ static int __qcom_glink_send(struct glink_channel *channel, spin_lock_irqsave(&channel->intent_lock, flags); idr_for_each_entry(&channel->riids, tmp, iid) { if (tmp->size >= len && !tmp->in_use) { - tmp->in_use = true; - intent = tmp; - break; + if (!intent) + intent = tmp; + else if (intent->size > tmp->size) + intent = tmp; + if (intent->size == len) + break; } } + if (intent) + intent->in_use = true; spin_unlock_irqrestore(&channel->intent_lock, flags); /* We found an available intent */ -- GitLab From 30863e38ebeb500a31cecee8096fb5002677dd9b Mon Sep 17 00:00:00 2001 From: Brent Taylor Date: Mon, 30 Oct 2017 22:32:45 -0500 Subject: [PATCH 1460/2898] mtd: nand: Fix writing mtdoops to nand flash. When mtdoops calls mtd_panic_write(), it eventually calls panic_nand_write() in nand_base.c. In order to properly wait for the nand chip to be ready in panic_nand_wait(), the chip must first be selected. When using the atmel nand flash controller, a panic would occur due to a NULL pointer exception. Fixes: 2af7c6539931 ("mtd: Add panic_write for NAND flashes") Cc: Signed-off-by: Brent Taylor Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 4c867115c53b..e48bf8260f54 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2799,15 +2799,18 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) { struct nand_chip *chip = mtd_to_nand(mtd); + int chipnr = (int)(to >> chip->chip_shift); struct mtd_oob_ops ops; int ret; - /* Wait for the device to get ready */ - panic_nand_wait(mtd, chip, 400); - /* Grab the device */ panic_nand_get_device(chip, mtd, FL_WRITING); + chip->select_chip(mtd, chipnr); + + /* Wait for the device to get ready */ + panic_nand_wait(mtd, chip, 400); + memset(&ops, 0, sizeof(ops)); ops.len = len; ops.datbuf = (uint8_t *)buf; -- GitLab From 26e480f7bb7840fc0daa9c3af7c4501b2cf5902f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:06:44 +0200 Subject: [PATCH 1461/2898] rtc: omap: fix error path when pinctrl_register fails If pinctrl_register() fails probe will return with an error without locking the RTC and disabling pm_runtime. Set ret and jump to err instead. Fixes: 97ea1906b3c2 ("rtc: omap: Support ext_wakeup configuration") Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 13f7cd11c07e..3bdc041fc2e9 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -830,7 +830,8 @@ static int omap_rtc_probe(struct platform_device *pdev) rtc->pctldev = pinctrl_register(&rtc_pinctrl_desc, &pdev->dev, rtc); if (IS_ERR(rtc->pctldev)) { dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); - return PTR_ERR(rtc->pctldev); + ret = PTR_ERR(rtc->pctldev); + goto err; } return 0; -- GitLab From 57072758623fa4f3019bce65e2b00f24af8dfdd7 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Fri, 13 Oct 2017 00:06:45 +0200 Subject: [PATCH 1462/2898] rtc: omap: switch to rtc_register_device This removes a possible race condition and crash and allows for further improvement of the driver. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 3bdc041fc2e9..d56d937966dc 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -797,13 +797,14 @@ static int omap_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, true); - rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &omap_rtc_ops, THIS_MODULE); + rtc->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); goto err; } + rtc->rtc->ops = &omap_rtc_ops; + /* handle periodic and alarm irqs */ ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0, dev_name(&rtc->rtc->dev), rtc); @@ -834,6 +835,10 @@ static int omap_rtc_probe(struct platform_device *pdev) goto err; } + ret = rtc_register_device(rtc->rtc); + if (ret) + goto err; + return 0; err: -- GitLab From b231669ca350d98cd126841627d3f083046a81ef Mon Sep 17 00:00:00 2001 From: Philipp Hug Date: Tue, 24 Oct 2017 16:32:22 +0200 Subject: [PATCH 1463/2898] platform/x86: ideapad-laptop: Add Lenovo Yoga 920-13IKB to no_hw_rfkill dmi list The Lenovo Yoga 920-13IKB does not have a hw rfkill switch, and trying to read the hw rfkill switch through the ideapad module causes it to always report as blocked. This commit adds the Lenovo Yoga 920-13IKB to the no_hw_rfkill dmi list, fixing the WiFI breakage. Signed-off-by: Philipp Hug Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/ideapad-laptop.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index fe98d4ac0df3..53ab4e0f8962 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -1166,6 +1166,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 910-13IKB"), }, }, + { + .ident = "Lenovo YOGA 920-13IKB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920-13IKB"), + }, + }, {} }; -- GitLab From 1027d759c9517a255f663d4365d98d78d8680b20 Mon Sep 17 00:00:00 2001 From: Rocky Hao Date: Thu, 24 Aug 2017 18:27:51 +0800 Subject: [PATCH 1464/2898] dt-bindings: rockchip-thermal: Support the RV1108 SoC compatible Add a new compatible for thermal founding on RV1108 SoCs. Acked-by: Rob Herring Signed-off-by: Rocky Hao Signed-off-by: Eduardo Valentin --- Documentation/devicetree/bindings/thermal/rockchip-thermal.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt index e3a6234fb1ac..43d744e5305e 100644 --- a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt @@ -2,6 +2,7 @@ Required properties: - compatible : should be "rockchip,-tsadc" + "rockchip,rv1108-tsadc": found on RV1108 SoCs "rockchip,rk3228-tsadc": found on RK3228 SoCs "rockchip,rk3288-tsadc": found on RK3288 SoCs "rockchip,rk3328-tsadc": found on RK3328 SoCs -- GitLab From 4eca8cac256a9557f9e1295147df8135c0b3540f Mon Sep 17 00:00:00 2001 From: Rocky Hao Date: Thu, 24 Aug 2017 18:27:52 +0800 Subject: [PATCH 1465/2898] thermal: rockchip: Support the RV1108 SoC in thermal driver RV1108 SOC has one Temperature Sensor for CPU. Reviewed-by: Caesar Wang Signed-off-by: Rocky Hao Signed-off-by: Eduardo Valentin --- drivers/thermal/rockchip_thermal.c | 67 ++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 206035139110..f36375d5a16c 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -242,6 +242,45 @@ struct tsadc_table { int temp; }; +static const struct tsadc_table rv1108_table[] = { + {0, -40000}, + {374, -40000}, + {382, -35000}, + {389, -30000}, + {397, -25000}, + {405, -20000}, + {413, -15000}, + {421, -10000}, + {429, -5000}, + {436, 0}, + {444, 5000}, + {452, 10000}, + {460, 15000}, + {468, 20000}, + {476, 25000}, + {483, 30000}, + {491, 35000}, + {499, 40000}, + {507, 45000}, + {515, 50000}, + {523, 55000}, + {531, 60000}, + {539, 65000}, + {547, 70000}, + {555, 75000}, + {562, 80000}, + {570, 85000}, + {578, 90000}, + {586, 95000}, + {594, 100000}, + {602, 105000}, + {610, 110000}, + {618, 115000}, + {626, 120000}, + {634, 125000}, + {TSADCV2_DATA_MASK, 125000}, +}; + static const struct tsadc_table rk3228_code_table[] = { {0, -40000}, {588, -40000}, @@ -779,6 +818,30 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, writel_relaxed(val, regs + TSADCV2_INT_EN); } +static const struct rockchip_tsadc_chip rv1108_tsadc_data = { + .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ + .chn_num = 1, /* one channel for tsadc */ + + .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ + .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ + .tshut_temp = 95000, + + .initialize = rk_tsadcv2_initialize, + .irq_ack = rk_tsadcv3_irq_ack, + .control = rk_tsadcv3_control, + .get_temp = rk_tsadcv2_get_temp, + .set_alarm_temp = rk_tsadcv2_alarm_temp, + .set_tshut_temp = rk_tsadcv2_tshut_temp, + .set_tshut_mode = rk_tsadcv2_tshut_mode, + + .table = { + .id = rv1108_table, + .length = ARRAY_SIZE(rv1108_table), + .data_mask = TSADCV2_DATA_MASK, + .mode = ADC_INCREMENT, + }, +}; + static const struct rockchip_tsadc_chip rk3228_tsadc_data = { .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ .chn_num = 1, /* one channel for tsadc */ @@ -927,6 +990,10 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = { }; static const struct of_device_id of_rockchip_thermal_match[] = { + { + .compatible = "rockchip,rv1108-tsadc", + .data = (void *)&rv1108_tsadc_data, + }, { .compatible = "rockchip,rk3228-tsadc", .data = (void *)&rk3228_tsadc_data, -- GitLab From fec3624f0bcdb6b20ef9ccf9d9d55d0d75d776f8 Mon Sep 17 00:00:00 2001 From: Allen Wild Date: Tue, 26 Sep 2017 19:37:44 +0200 Subject: [PATCH 1466/2898] thermal: enable broadcom menu for arm64 bcm2835 Moving the bcm2835 thermal driver to the broadcom directory prevented it from getting enabled for arm64 builds, since the broadcom directory is only available when 32-bit specific ARCH_BCM is set. Fix this by enabling the Broadcom menu for ARCH_BCM or ARCH_BCM2835. Fixes: 6892cf07e733 ("thermal: bcm2835: move to the broadcom subdirectory") Reviewed-by: Eric Anholt Signed-off-by: Allen Wild Signed-off-by: Stefan Wahren Signed-off-by: Eduardo Valentin --- drivers/thermal/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 07002df4f83a..e3f0d1fd1720 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -408,7 +408,7 @@ config MTK_THERMAL controller present in Mediatek SoCs menu "Broadcom thermal drivers" -depends on ARCH_BCM || COMPILE_TEST +depends on ARCH_BCM || ARCH_BCM2835 || COMPILE_TEST source "drivers/thermal/broadcom/Kconfig" endmenu -- GitLab From 1fba81cc09bd3cd71ca43cd66ca7223217eaa054 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Tue, 5 Sep 2017 00:41:16 -0700 Subject: [PATCH 1467/2898] thermal: tegra: remove null check for dev pointer The dev pointer is going through a null check after a dereference. So this patch removes that useless check since the driver does not pass a null dev pointer in any case. Signed-off-by: Nicolin Chen Signed-off-by: Eduardo Valentin --- drivers/thermal/tegra/soctherm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 7d2db23d71a3..075db1de5e53 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -483,7 +483,7 @@ static int throttrip_program(struct device *dev, unsigned int throt; u32 r, reg_off; - if (!dev || !sg || !stc || !stc->init) + if (!sg || !stc || !stc->init) return -EINVAL; temp = enforce_temp_range(dev, trip_temp) / ts->soc->thresh_grain; -- GitLab From 0cf3a1ac3e10a5920531e38cf2ae99fa1e4d45a2 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 14 Sep 2017 18:06:57 +0300 Subject: [PATCH 1468/2898] thermal: armada: fix formula documentation comment The formula implementation at armada_get_temp() indicates that the sign in the formula is inverted. Cc: Ezequiel Garcia Signed-off-by: Baruch Siach Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index ae75328945f7..706d74798cbe 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -58,7 +58,7 @@ struct armada_thermal_data { /* Test for a valid sensor value (optional) */ bool (*is_valid)(struct armada_thermal_priv *); - /* Formula coeficients: temp = (b + m * reg) / div */ + /* Formula coeficients: temp = (b - m * reg) / div */ unsigned long coef_b; unsigned long coef_m; unsigned long coef_div; -- GitLab From d668c807aa6ef3c3eef57b4e9e785ec0cfab4f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 17 Oct 2017 13:36:13 +0200 Subject: [PATCH 1469/2898] thermal: rcar_gen3_thermal: fix initialization sequence for H3 ES2.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initialization sequence for H3 (r8a7795) ES1.x and ES2.0 is different. H3 ES2.0 and later uses the same sequence as M3 (r8a7796) ES1.0. Fix this by not looking at compatible strings and instead defaulting to the r8a7796 initialization sequence and use soc_device_match() to check for H3 ES1.x. Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Acked-by: Wolfram Sang Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_gen3_thermal.c | 34 +++++++++++++---------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 203aca44a2bb..561a0a332208 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "thermal_core.h" @@ -90,10 +91,6 @@ struct rcar_gen3_thermal_priv { struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; unsigned int num_tscs; spinlock_t lock; /* Protect interrupts on and off */ - const struct rcar_gen3_thermal_data *data; -}; - -struct rcar_gen3_thermal_data { void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc); }; @@ -278,7 +275,12 @@ static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc) +static const struct soc_device_attribute r8a7795es1[] = { + { .soc_id = "r8a7795", .revision = "ES1.*" }, + { /* sentinel */ } +}; + +static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_tsc *tsc) { rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR); rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 0x0); @@ -303,7 +305,7 @@ static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc) usleep_range(1000, 2000); } -static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc) +static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc) { u32 reg_val; @@ -324,17 +326,9 @@ static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc) usleep_range(1000, 2000); } -static const struct rcar_gen3_thermal_data r8a7795_data = { - .thermal_init = r8a7795_thermal_init, -}; - -static const struct rcar_gen3_thermal_data r8a7796_data = { - .thermal_init = r8a7796_thermal_init, -}; - static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { - { .compatible = "renesas,r8a7795-thermal", .data = &r8a7795_data}, - { .compatible = "renesas,r8a7796-thermal", .data = &r8a7796_data}, + { .compatible = "renesas,r8a7795-thermal", }, + { .compatible = "renesas,r8a7796-thermal", }, {}, }; MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); @@ -371,7 +365,9 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - priv->data = of_device_get_match_data(dev); + priv->thermal_init = rcar_gen3_thermal_init; + if (soc_device_match(r8a7795es1)) + priv->thermal_init = rcar_gen3_thermal_init_r8a7795es1; spin_lock_init(&priv->lock); @@ -423,7 +419,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) priv->tscs[i] = tsc; - priv->data->thermal_init(tsc); + priv->thermal_init(tsc); rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]); zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, @@ -476,7 +472,7 @@ static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev) for (i = 0; i < priv->num_tscs; i++) { struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; - priv->data->thermal_init(tsc); + priv->thermal_init(tsc); rcar_gen3_thermal_set_trips(tsc, tsc->low, tsc->high); } -- GitLab From ba817a8cfc2e128b59af7fe8b6af72ed38763b87 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 16 Oct 2017 14:07:14 -0700 Subject: [PATCH 1470/2898] thermal: ti-soc-thermal: Fix ti_thermal_unregister_cpu_cooling NULL pointer on unload While debugging some PM issues and trying to remove all the loaded modules, I ran across the following when unloading ti-soc-thermal: Unable to handle kernel NULL pointer dereference at virtual address 000000b4 ... [] (kobject_put) from [] (ti_thermal_unregister_cpu_cooling+0x20/0x28 [ti_soc_thermal]) [] (ti_thermal_unregister_cpu_cooling [ti_soc_thermal]) from [] (ti_bandgap_remove+0x3c/0x104 [ti_soc_thermal]) [] (ti_bandgap_remove [ti_soc_thermal]) from [] (platform_drv_remove+0x24/0x3c) [] (platform_drv_remove) from [] (device_release_driver_internal+0x160/0x208) [] (device_release_driver_internal) from [] (driver_detach+0x38/0x6c) [] (driver_detach) from [] (bus_remove_driver+0x4c/0xa0) [] (bus_remove_driver) from [] (SyS_delete_module+0x168/0x238) [] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x28) Cc: Keerthy Signed-off-by: Tony Lindgren Signed-off-by: Eduardo Valentin --- drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index c211a8e4a210..b4f981daeaf2 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -278,7 +278,8 @@ int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id) if (data) { cpufreq_cooling_unregister(data->cool_dev); - cpufreq_cpu_put(data->policy); + if (data->policy) + cpufreq_cpu_put(data->policy); } return 0; -- GitLab From c176b10b025acee4dc8f2ab1cd64eb73b5ccef53 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:43 +0200 Subject: [PATCH 1471/2898] thermal/drivers/hisi: Fix missing interrupt enablement The interrupt for the temperature threshold is not enabled at the end of the probe function, enable it after the setup is complete. On the other side, the irq_enabled is not correctly set as we are checking if the interrupt is masked where 'yes' means irq_enabled=false. irq_get_irqchip_state(data->irq, IRQCHIP_STATE_MASKED, &data->irq_enabled); As we are always enabling the interrupt, it is pointless to check if the interrupt is masked or not, just set irq_enabled to 'true'. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Tested-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index bd3572c41585..8381696241d6 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -345,8 +345,7 @@ static int hisi_thermal_probe(struct platform_device *pdev) } hisi_thermal_enable_bind_irq_sensor(data); - irq_get_irqchip_state(data->irq, IRQCHIP_STATE_MASKED, - &data->irq_enabled); + data->irq_enabled = true; for (i = 0; i < HISI_MAX_SENSORS; ++i) { ret = hisi_thermal_register_sensor(pdev, data, @@ -358,6 +357,8 @@ static int hisi_thermal_probe(struct platform_device *pdev) hisi_thermal_toggle_sensor(&data->sensors[i], true); } + enable_irq(data->irq); + return 0; } -- GitLab From ff4ec2997df8fe7cc40513dbe5f86d9f88fb6be7 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:44 +0200 Subject: [PATCH 1472/2898] thermal/drivers/hisi: Remove the multiple sensors support By essence, the tsensor does not really support multiple sensor at the same time. It allows to set a sensor and use it to get the temperature, another sensor could be switched but with a delay of 3-5ms. It is difficult to read simultaneously several sensors without a big delay. Today, just one sensor is used, it is not necessary to deal with multiple sensors in the code. Remove them and if it is needed in the future add them on top of a code which will be clean up in the meantime. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Acked-by: Wangtao (Kevin, Kirin) Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 75 +++++++++------------------------- 1 file changed, 19 insertions(+), 56 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 8381696241d6..725d0d434d83 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -39,6 +39,7 @@ #define HISI_TEMP_RESET (100000) #define HISI_MAX_SENSORS 4 +#define HISI_DEFAULT_SENSOR 2 struct hisi_thermal_sensor { struct hisi_thermal_data *thermal; @@ -53,9 +54,8 @@ struct hisi_thermal_data { struct mutex thermal_lock; /* protects register data */ struct platform_device *pdev; struct clk *clk; - struct hisi_thermal_sensor sensors[HISI_MAX_SENSORS]; - - int irq, irq_bind_sensor; + struct hisi_thermal_sensor sensors; + int irq; bool irq_enabled; void __iomem *regs; @@ -113,7 +113,7 @@ static void hisi_thermal_enable_bind_irq_sensor mutex_lock(&data->thermal_lock); - sensor = &data->sensors[data->irq_bind_sensor]; + sensor = &data->sensors; /* setting the hdak time */ writel(0x0, data->regs + TEMP0_CFG); @@ -160,31 +160,8 @@ static int hisi_thermal_get_temp(void *_sensor, int *temp) struct hisi_thermal_sensor *sensor = _sensor; struct hisi_thermal_data *data = sensor->thermal; - int sensor_id = -1, i; - long max_temp = 0; - *temp = hisi_thermal_get_sensor_temp(data, sensor); - sensor->sensor_temp = *temp; - - for (i = 0; i < HISI_MAX_SENSORS; i++) { - if (!data->sensors[i].tzd) - continue; - - if (data->sensors[i].sensor_temp >= max_temp) { - max_temp = data->sensors[i].sensor_temp; - sensor_id = i; - } - } - - /* If no sensor has been enabled, then skip to enable irq */ - if (sensor_id == -1) - return 0; - - mutex_lock(&data->thermal_lock); - data->irq_bind_sensor = sensor_id; - mutex_unlock(&data->thermal_lock); - dev_dbg(&data->pdev->dev, "id=%d, irq=%d, temp=%d, thres=%d\n", sensor->id, data->irq_enabled, *temp, sensor->thres_temp); /* @@ -197,7 +174,7 @@ static int hisi_thermal_get_temp(void *_sensor, int *temp) return 0; } - if (max_temp < sensor->thres_temp) { + if (*temp < sensor->thres_temp) { data->irq_enabled = true; hisi_thermal_enable_bind_irq_sensor(data); enable_irq(data->irq); @@ -224,22 +201,16 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) { struct hisi_thermal_data *data = dev; struct hisi_thermal_sensor *sensor; - int i; mutex_lock(&data->thermal_lock); - sensor = &data->sensors[data->irq_bind_sensor]; + sensor = &data->sensors; dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", sensor->thres_temp / 1000); mutex_unlock(&data->thermal_lock); - for (i = 0; i < HISI_MAX_SENSORS; i++) { - if (!data->sensors[i].tzd) - continue; - - thermal_zone_device_update(data->sensors[i].tzd, - THERMAL_EVENT_UNSPECIFIED); - } + thermal_zone_device_update(data->sensors.tzd, + THERMAL_EVENT_UNSPECIFIED); return IRQ_HANDLED; } @@ -296,7 +267,6 @@ static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; struct resource *res; - int i; int ret; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); @@ -347,16 +317,17 @@ static int hisi_thermal_probe(struct platform_device *pdev) hisi_thermal_enable_bind_irq_sensor(data); data->irq_enabled = true; - for (i = 0; i < HISI_MAX_SENSORS; ++i) { - ret = hisi_thermal_register_sensor(pdev, data, - &data->sensors[i], i); - if (ret) - dev_err(&pdev->dev, - "failed to register thermal sensor: %d\n", ret); - else - hisi_thermal_toggle_sensor(&data->sensors[i], true); + ret = hisi_thermal_register_sensor(pdev, data, + &data->sensors, + HISI_DEFAULT_SENSOR); + if (ret) { + dev_err(&pdev->dev, "failed to register thermal sensor: %d\n", + ret); + return ret; } + hisi_thermal_toggle_sensor(&data->sensors, true); + enable_irq(data->irq); return 0; @@ -365,17 +336,9 @@ static int hisi_thermal_probe(struct platform_device *pdev) static int hisi_thermal_remove(struct platform_device *pdev) { struct hisi_thermal_data *data = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < HISI_MAX_SENSORS; i++) { - struct hisi_thermal_sensor *sensor = &data->sensors[i]; - - if (!sensor->tzd) - continue; - - hisi_thermal_toggle_sensor(sensor, false); - } + struct hisi_thermal_sensor *sensor = &data->sensors; + hisi_thermal_toggle_sensor(sensor, false); hisi_thermal_disable_sensor(data); clk_disable_unprepare(data->clk); -- GitLab From 2cb4de785c40d4a2132cfc13e63828f5a28c3351 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:45 +0200 Subject: [PATCH 1473/2898] thermal/drivers/hisi: Fix kernel panic on alarm interrupt The threaded interrupt for the alarm interrupt is requested before the temperature controller is setup. This one can fire an interrupt immediately leading to a kernel panic as the sensor data is not initialized. In order to prevent that, move the threaded irq after the Tsensor is setup. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Tested-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 725d0d434d83..f69aea0b2fe3 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -287,15 +287,6 @@ static int hisi_thermal_probe(struct platform_device *pdev) if (data->irq < 0) return data->irq; - ret = devm_request_threaded_irq(&pdev->dev, data->irq, - hisi_thermal_alarm_irq, - hisi_thermal_alarm_irq_thread, - 0, "hisi_thermal", data); - if (ret < 0) { - dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); - return ret; - } - platform_set_drvdata(pdev, data); data->clk = devm_clk_get(&pdev->dev, "thermal_clk"); @@ -328,6 +319,15 @@ static int hisi_thermal_probe(struct platform_device *pdev) hisi_thermal_toggle_sensor(&data->sensors, true); + ret = devm_request_threaded_irq(&pdev->dev, data->irq, + hisi_thermal_alarm_irq, + hisi_thermal_alarm_irq_thread, + 0, "hisi_thermal", data); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); + return ret; + } + enable_irq(data->irq); return 0; -- GitLab From 48880b979cdc9ef5a70af020f42b8ba1e51dbd34 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:46 +0200 Subject: [PATCH 1474/2898] thermal/drivers/hisi: Simplify the temperature/step computation The step and the base temperature are fixed values, we can simplify the computation by converting the base temperature to milli celsius and use a pre-computed step value. That saves us a lot of mult + div for nothing at runtime. Take also the opportunity to change the function names to be consistent with the rest of the code. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Tested-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 41 +++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index f69aea0b2fe3..583bc1934127 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -35,8 +35,9 @@ #define TEMP0_RST_MSK (0x1C) #define TEMP0_VALUE (0x28) -#define HISI_TEMP_BASE (-60) +#define HISI_TEMP_BASE (-60000) #define HISI_TEMP_RESET (100000) +#define HISI_TEMP_STEP (784) #define HISI_MAX_SENSORS 4 #define HISI_DEFAULT_SENSOR 2 @@ -61,19 +62,32 @@ struct hisi_thermal_data { void __iomem *regs; }; -/* in millicelsius */ -static inline int _step_to_temp(int step) +/* + * The temperature computation on the tsensor is as follow: + * Unit: millidegree Celsius + * Step: 255/200 (0.7843) + * Temperature base: -60°C + * + * The register is programmed in temperature steps, every step is 784 + * millidegree and begins at -60 000 m°C + * + * The temperature from the steps: + * + * Temp = TempBase + (steps x 784) + * + * and the steps from the temperature: + * + * steps = (Temp - TempBase) / 784 + * + */ +static inline int hisi_thermal_step_to_temp(int step) { - /* - * Every step equals (1 * 200) / 255 celsius, and finally - * need convert to millicelsius. - */ - return (HISI_TEMP_BASE * 1000 + (step * 200000 / 255)); + return HISI_TEMP_BASE + (step * HISI_TEMP_STEP); } -static inline long _temp_to_step(long temp) +static inline long hisi_thermal_temp_to_step(long temp) { - return ((temp - HISI_TEMP_BASE * 1000) * 255) / 200000; + return (temp - HISI_TEMP_BASE) / HISI_TEMP_STEP; } static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, @@ -99,7 +113,7 @@ static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, usleep_range(3000, 5000); val = readl(data->regs + TEMP0_VALUE); - val = _step_to_temp(val); + val = hisi_thermal_step_to_temp(val); mutex_unlock(&data->thermal_lock); @@ -126,10 +140,11 @@ static void hisi_thermal_enable_bind_irq_sensor writel((sensor->id << 12), data->regs + TEMP0_CFG); /* enable for interrupt */ - writel(_temp_to_step(sensor->thres_temp) | 0x0FFFFFF00, + writel(hisi_thermal_temp_to_step(sensor->thres_temp) | 0x0FFFFFF00, data->regs + TEMP0_TH); - writel(_temp_to_step(HISI_TEMP_RESET), data->regs + TEMP0_RST_TH); + writel(hisi_thermal_temp_to_step(HISI_TEMP_RESET), + data->regs + TEMP0_RST_TH); /* enable module */ writel(0x1, data->regs + TEMP0_RST_MSK); -- GitLab From db2b0332608c8e648ea1e44727d36ad37cdb56cb Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:47 +0200 Subject: [PATCH 1475/2898] thermal/drivers/hisi: Fix multiple alarm interrupts firing The DT specifies a threshold of 65000, we setup the register with a value in the temperature resolution for the controller, 64656. When we reach 64656, the interrupt fires, the interrupt is disabled. Then the irq thread runs and calls thermal_zone_device_update() which will call in turn hisi_thermal_get_temp(). The function will look if the temperature decreased, assuming it was more than 65000, but that is not the case because the current temperature is 64656 (because of the rounding when setting the threshold). This condition being true, we re-enable the interrupt which fires immediately after exiting the irq thread. That happens again and again until the temperature goes to more than 65000. Potentially, there is here an interrupt storm if the temperature stabilizes at this temperature. A very unlikely case but possible. In any case, it does not make sense to handle dozens of alarm interrupt for nothing. Fix this by rounding the threshold value to the controller resolution so the check against the threshold is consistent with the one set in the controller. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Tested-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 583bc1934127..f5231974504c 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -90,6 +90,12 @@ static inline long hisi_thermal_temp_to_step(long temp) return (temp - HISI_TEMP_BASE) / HISI_TEMP_STEP; } +static inline long hisi_thermal_round_temp(int temp) +{ + return hisi_thermal_step_to_temp( + hisi_thermal_temp_to_step(temp)); +} + static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, struct hisi_thermal_sensor *sensor) { @@ -221,7 +227,7 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) sensor = &data->sensors; dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", - sensor->thres_temp / 1000); + sensor->thres_temp); mutex_unlock(&data->thermal_lock); thermal_zone_device_update(data->sensors.tzd, @@ -255,7 +261,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { if (trip[i].type == THERMAL_TRIP_PASSIVE) { - sensor->thres_temp = trip[i].temperature; + sensor->thres_temp = hisi_thermal_round_temp(trip[i].temperature); break; } } -- GitLab From 2d4fa7b4c6f8080ced2e8237c9f46fb1fc110d64 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:48 +0200 Subject: [PATCH 1476/2898] thermal/drivers/hisi: Remove pointless lock The threaded interrupt inspect the sensors structure to look in the temp threshold field, but this field is read-only in all the code, except in the probe function before the threaded interrupt is set. In other words there is not race window in the threaded interrupt when reading the field value. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index f5231974504c..9ec5f290b850 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -221,14 +221,10 @@ static irqreturn_t hisi_thermal_alarm_irq(int irq, void *dev) static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) { struct hisi_thermal_data *data = dev; - struct hisi_thermal_sensor *sensor; - - mutex_lock(&data->thermal_lock); - sensor = &data->sensors; + struct hisi_thermal_sensor *sensor = &data->sensors; dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", sensor->thres_temp); - mutex_unlock(&data->thermal_lock); thermal_zone_device_update(data->sensors.tzd, THERMAL_EVENT_UNSPECIFIED); -- GitLab From 1e11b014271ceccb5ea04ae58f4829ac8209a86d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:49 +0200 Subject: [PATCH 1477/2898] thermal/drivers/hisi: Encapsulate register writes into helpers Hopefully, the function name can help to clarify the semantic of the operations when writing in the register. Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 92 ++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 9ec5f290b850..7747b96002e3 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -26,6 +26,7 @@ #include "thermal_core.h" +#define TEMP0_LAG (0x0) #define TEMP0_TH (0x4) #define TEMP0_RST_TH (0x8) #define TEMP0_CFG (0xC) @@ -96,6 +97,56 @@ static inline long hisi_thermal_round_temp(int temp) hisi_thermal_temp_to_step(temp)); } +static inline void hisi_thermal_set_lag(void __iomem *addr, int value) +{ + writel(value, addr + TEMP0_LAG); +} + +static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) +{ + writel(value, addr + TEMP0_INT_CLR); +} + +static inline void hisi_thermal_alarm_enable(void __iomem *addr, int value) +{ + writel(value, addr + TEMP0_INT_EN); +} + +static inline void hisi_thermal_alarm_set(void __iomem *addr, int temp) +{ + writel(hisi_thermal_temp_to_step(temp) | 0x0FFFFFF00, addr + TEMP0_TH); +} + +static inline void hisi_thermal_reset_set(void __iomem *addr, int temp) +{ + writel(hisi_thermal_temp_to_step(temp), addr + TEMP0_RST_TH); +} + +static inline void hisi_thermal_reset_enable(void __iomem *addr, int value) +{ + writel(value, addr + TEMP0_RST_MSK); +} + +static inline void hisi_thermal_enable(void __iomem *addr, int value) +{ + writel(value, addr + TEMP0_EN); +} + +static inline void hisi_thermal_sensor_select(void __iomem *addr, int sensor) +{ + writel((sensor << 12), addr + TEMP0_CFG); +} + +static inline int hisi_thermal_get_temperature(void __iomem *addr) +{ + return hisi_thermal_step_to_temp(readl(addr + TEMP0_VALUE)); +} + +static inline void hisi_thermal_hdak_set(void __iomem *addr, int value) +{ + writel(value, addr + TEMP0_CFG); +} + static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, struct hisi_thermal_sensor *sensor) { @@ -104,22 +155,21 @@ static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, mutex_lock(&data->thermal_lock); /* disable interrupt */ - writel(0x0, data->regs + TEMP0_INT_EN); - writel(0x1, data->regs + TEMP0_INT_CLR); + hisi_thermal_alarm_enable(data->regs, 0); + hisi_thermal_alarm_clear(data->regs, 1); /* disable module firstly */ - writel(0x0, data->regs + TEMP0_EN); + hisi_thermal_enable(data->regs, 0); /* select sensor id */ - writel((sensor->id << 12), data->regs + TEMP0_CFG); + hisi_thermal_sensor_select(data->regs, sensor->id); /* enable module */ - writel(0x1, data->regs + TEMP0_EN); + hisi_thermal_enable(data->regs, 1); usleep_range(3000, 5000); - val = readl(data->regs + TEMP0_VALUE); - val = hisi_thermal_step_to_temp(val); + val = hisi_thermal_get_temperature(data->regs); mutex_unlock(&data->thermal_lock); @@ -136,28 +186,26 @@ static void hisi_thermal_enable_bind_irq_sensor sensor = &data->sensors; /* setting the hdak time */ - writel(0x0, data->regs + TEMP0_CFG); + hisi_thermal_hdak_set(data->regs, 0); /* disable module firstly */ - writel(0x0, data->regs + TEMP0_RST_MSK); - writel(0x0, data->regs + TEMP0_EN); + hisi_thermal_reset_enable(data->regs, 0); + hisi_thermal_enable(data->regs, 0); /* select sensor id */ - writel((sensor->id << 12), data->regs + TEMP0_CFG); + hisi_thermal_sensor_select(data->regs, sensor->id); /* enable for interrupt */ - writel(hisi_thermal_temp_to_step(sensor->thres_temp) | 0x0FFFFFF00, - data->regs + TEMP0_TH); + hisi_thermal_alarm_set(data->regs, sensor->thres_temp); - writel(hisi_thermal_temp_to_step(HISI_TEMP_RESET), - data->regs + TEMP0_RST_TH); + hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); /* enable module */ - writel(0x1, data->regs + TEMP0_RST_MSK); - writel(0x1, data->regs + TEMP0_EN); + hisi_thermal_reset_enable(data->regs, 1); + hisi_thermal_enable(data->regs, 1); - writel(0x0, data->regs + TEMP0_INT_CLR); - writel(0x1, data->regs + TEMP0_INT_EN); + hisi_thermal_alarm_clear(data->regs, 0); + hisi_thermal_alarm_enable(data->regs, 1); usleep_range(3000, 5000); @@ -169,9 +217,9 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) mutex_lock(&data->thermal_lock); /* disable sensor module */ - writel(0x0, data->regs + TEMP0_INT_EN); - writel(0x0, data->regs + TEMP0_RST_MSK); - writel(0x0, data->regs + TEMP0_EN); + hisi_thermal_enable(data->regs, 0); + hisi_thermal_alarm_enable(data->regs, 0); + hisi_thermal_reset_enable(data->regs, 0); mutex_unlock(&data->thermal_lock); } -- GitLab From b424315a287c70eeb5f920f84c92492bd2f5658e Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:50 +0200 Subject: [PATCH 1478/2898] thermal/drivers/hisi: Fix configuration register setting The TEMP0_CFG configuration register contains different field to set up the temperature controller. However in the code, nothing prevents a setup to overwrite the previous one: eg. writing the hdak value overwrites the sensor selection, the sensor selection overwrites the hdak value. In order to prevent such thing, use a regmap-like mechanism by reading the value before, set the corresponding bits and write the result. Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 7747b96002e3..f3fb8e2a7f0c 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -30,6 +30,8 @@ #define TEMP0_TH (0x4) #define TEMP0_RST_TH (0x8) #define TEMP0_CFG (0xC) +#define TEMP0_CFG_SS_MSK (0xF000) +#define TEMP0_CFG_HDAK_MSK (0x30) #define TEMP0_EN (0x10) #define TEMP0_INT_EN (0x14) #define TEMP0_INT_CLR (0x18) @@ -132,19 +134,41 @@ static inline void hisi_thermal_enable(void __iomem *addr, int value) writel(value, addr + TEMP0_EN); } -static inline void hisi_thermal_sensor_select(void __iomem *addr, int sensor) +static inline int hisi_thermal_get_temperature(void __iomem *addr) { - writel((sensor << 12), addr + TEMP0_CFG); + return hisi_thermal_step_to_temp(readl(addr + TEMP0_VALUE)); } -static inline int hisi_thermal_get_temperature(void __iomem *addr) +/* + * Temperature configuration register - Sensor selection + * + * Bits [19:12] + * + * 0x0: local sensor (default) + * 0x1: remote sensor 1 (ACPU cluster 1) + * 0x2: remote sensor 2 (ACPU cluster 0) + * 0x3: remote sensor 3 (G3D) + */ +static inline void hisi_thermal_sensor_select(void __iomem *addr, int sensor) { - return hisi_thermal_step_to_temp(readl(addr + TEMP0_VALUE)); + writel((readl(addr + TEMP0_CFG) & ~TEMP0_CFG_SS_MSK) | + (sensor << 12), addr + TEMP0_CFG); } +/* + * Temperature configuration register - Hdak conversion polling interval + * + * Bits [5:4] + * + * 0x0 : 0.768 ms + * 0x1 : 6.144 ms + * 0x2 : 49.152 ms + * 0x3 : 393.216 ms + */ static inline void hisi_thermal_hdak_set(void __iomem *addr, int value) { - writel(value, addr + TEMP0_CFG); + writel((readl(addr + TEMP0_CFG) & ~TEMP0_CFG_HDAK_MSK) | + (value << 4), addr + TEMP0_CFG); } static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, -- GitLab From 10d7e9a9181f4637640f388d334c6740c1b5d0e8 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:51 +0200 Subject: [PATCH 1479/2898] thermal/drivers/hisi: Remove costly sensor inspection The sensor is all setup, bind, resetted, acked, etc... every single second. That was the way to workaround a problem with the interrupt bouncing again and again. With the following changes, we fix all in one: - Do the setup, one time, at probe time - Add the IRQF_ONESHOT, ack the interrupt in the threaded handler - Remove the interrupt handler - Set the correct value for the LAG register - Remove all the irq_enabled stuff in the code as the interruption handling is fixed - Remove the 3ms delay - Reorder the initialization routine to be in the right order It ends up to a nicer code and more efficient, the 3-5ms delay is removed from the get_temp() path. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Tested-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 203 +++++++++++++++------------------ 1 file changed, 93 insertions(+), 110 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index f3fb8e2a7f0c..7c5d4647cb5e 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -41,6 +41,7 @@ #define HISI_TEMP_BASE (-60000) #define HISI_TEMP_RESET (100000) #define HISI_TEMP_STEP (784) +#define HISI_TEMP_LAG (3500) #define HISI_MAX_SENSORS 4 #define HISI_DEFAULT_SENSOR 2 @@ -60,8 +61,6 @@ struct hisi_thermal_data { struct clk *clk; struct hisi_thermal_sensor sensors; int irq; - bool irq_enabled; - void __iomem *regs; }; @@ -99,9 +98,40 @@ static inline long hisi_thermal_round_temp(int temp) hisi_thermal_temp_to_step(temp)); } +/* + * The lag register contains 5 bits encoding the temperature in steps. + * + * Each time the temperature crosses the threshold boundary, an + * interrupt is raised. It could be when the temperature is going + * above the threshold or below. However, if the temperature is + * fluctuating around this value due to the load, we can receive + * several interrupts which may not desired. + * + * We can setup a temperature representing the delta between the + * threshold and the current temperature when the temperature is + * decreasing. + * + * For instance: the lag register is 5°C, the threshold is 65°C, when + * the temperature reaches 65°C an interrupt is raised and when the + * temperature decrease to 65°C - 5°C another interrupt is raised. + * + * A very short lag can lead to an interrupt storm, a long lag + * increase the latency to react to the temperature changes. In our + * case, that is not really a problem as we are polling the + * temperature. + * + * [0:4] : lag register + * + * The temperature is coded in steps, cf. HISI_TEMP_STEP. + * + * Min : 0x00 : 0.0 °C + * Max : 0x1F : 24.3 °C + * + * The 'value' parameter is in milliCelsius. + */ static inline void hisi_thermal_set_lag(void __iomem *addr, int value) { - writel(value, addr + TEMP0_LAG); + writel((value / HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); } static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) @@ -171,71 +201,6 @@ static inline void hisi_thermal_hdak_set(void __iomem *addr, int value) (value << 4), addr + TEMP0_CFG); } -static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, - struct hisi_thermal_sensor *sensor) -{ - long val; - - mutex_lock(&data->thermal_lock); - - /* disable interrupt */ - hisi_thermal_alarm_enable(data->regs, 0); - hisi_thermal_alarm_clear(data->regs, 1); - - /* disable module firstly */ - hisi_thermal_enable(data->regs, 0); - - /* select sensor id */ - hisi_thermal_sensor_select(data->regs, sensor->id); - - /* enable module */ - hisi_thermal_enable(data->regs, 1); - - usleep_range(3000, 5000); - - val = hisi_thermal_get_temperature(data->regs); - - mutex_unlock(&data->thermal_lock); - - return val; -} - -static void hisi_thermal_enable_bind_irq_sensor - (struct hisi_thermal_data *data) -{ - struct hisi_thermal_sensor *sensor; - - mutex_lock(&data->thermal_lock); - - sensor = &data->sensors; - - /* setting the hdak time */ - hisi_thermal_hdak_set(data->regs, 0); - - /* disable module firstly */ - hisi_thermal_reset_enable(data->regs, 0); - hisi_thermal_enable(data->regs, 0); - - /* select sensor id */ - hisi_thermal_sensor_select(data->regs, sensor->id); - - /* enable for interrupt */ - hisi_thermal_alarm_set(data->regs, sensor->thres_temp); - - hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); - - /* enable module */ - hisi_thermal_reset_enable(data->regs, 1); - hisi_thermal_enable(data->regs, 1); - - hisi_thermal_alarm_clear(data->regs, 0); - hisi_thermal_alarm_enable(data->regs, 1); - - usleep_range(3000, 5000); - - mutex_unlock(&data->thermal_lock); -} - static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) { mutex_lock(&data->thermal_lock); @@ -253,25 +218,10 @@ static int hisi_thermal_get_temp(void *_sensor, int *temp) struct hisi_thermal_sensor *sensor = _sensor; struct hisi_thermal_data *data = sensor->thermal; - *temp = hisi_thermal_get_sensor_temp(data, sensor); - - dev_dbg(&data->pdev->dev, "id=%d, irq=%d, temp=%d, thres=%d\n", - sensor->id, data->irq_enabled, *temp, sensor->thres_temp); - /* - * Bind irq to sensor for two cases: - * Reenable alarm IRQ if temperature below threshold; - * if irq has been enabled, always set it; - */ - if (data->irq_enabled) { - hisi_thermal_enable_bind_irq_sensor(data); - return 0; - } + *temp = hisi_thermal_get_temperature(data->regs); - if (*temp < sensor->thres_temp) { - data->irq_enabled = true; - hisi_thermal_enable_bind_irq_sensor(data); - enable_irq(data->irq); - } + dev_dbg(&data->pdev->dev, "id=%d, temp=%d, thres=%d\n", + sensor->id, *temp, sensor->thres_temp); return 0; } @@ -280,26 +230,27 @@ static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = { .get_temp = hisi_thermal_get_temp, }; -static irqreturn_t hisi_thermal_alarm_irq(int irq, void *dev) +static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) { struct hisi_thermal_data *data = dev; + struct hisi_thermal_sensor *sensor = &data->sensors; + int temp; - disable_irq_nosync(irq); - data->irq_enabled = false; + hisi_thermal_alarm_clear(data->regs, 1); - return IRQ_WAKE_THREAD; -} + temp = hisi_thermal_get_temperature(data->regs); -static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) -{ - struct hisi_thermal_data *data = dev; - struct hisi_thermal_sensor *sensor = &data->sensors; + if (temp >= sensor->thres_temp) { + dev_crit(&data->pdev->dev, "THERMAL ALARM: %d > %d\n", + temp, sensor->thres_temp); - dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", - sensor->thres_temp); + thermal_zone_device_update(data->sensors.tzd, + THERMAL_EVENT_UNSPECIFIED); - thermal_zone_device_update(data->sensors.tzd, - THERMAL_EVENT_UNSPECIFIED); + } else if (temp < sensor->thres_temp) { + dev_crit(&data->pdev->dev, "THERMAL ALARM stopped: %d < %d\n", + temp, sensor->thres_temp); + } return IRQ_HANDLED; } @@ -352,6 +303,40 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); } +static int hisi_thermal_setup(struct hisi_thermal_data *data) +{ + struct hisi_thermal_sensor *sensor; + + sensor = &data->sensors; + + /* disable module firstly */ + hisi_thermal_reset_enable(data->regs, 0); + hisi_thermal_enable(data->regs, 0); + + /* select sensor id */ + hisi_thermal_sensor_select(data->regs, sensor->id); + + /* setting the hdak time */ + hisi_thermal_hdak_set(data->regs, 0); + + /* setting lag value between current temp and the threshold */ + hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); + + /* enable for interrupt */ + hisi_thermal_alarm_set(data->regs, sensor->thres_temp); + + hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); + + /* enable module */ + hisi_thermal_reset_enable(data->regs, 1); + hisi_thermal_enable(data->regs, 1); + + hisi_thermal_alarm_clear(data->regs, 0); + hisi_thermal_alarm_enable(data->regs, 1); + + return 0; +} + static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; @@ -394,9 +379,6 @@ static int hisi_thermal_probe(struct platform_device *pdev) return ret; } - hisi_thermal_enable_bind_irq_sensor(data); - data->irq_enabled = true; - ret = hisi_thermal_register_sensor(pdev, data, &data->sensors, HISI_DEFAULT_SENSOR); @@ -406,18 +388,21 @@ static int hisi_thermal_probe(struct platform_device *pdev) return ret; } - hisi_thermal_toggle_sensor(&data->sensors, true); + ret = hisi_thermal_setup(data); + if (ret) { + dev_err(&pdev->dev, "Failed to setup the sensor: %d\n", ret); + return ret; + } - ret = devm_request_threaded_irq(&pdev->dev, data->irq, - hisi_thermal_alarm_irq, + ret = devm_request_threaded_irq(&pdev->dev, data->irq, NULL, hisi_thermal_alarm_irq_thread, - 0, "hisi_thermal", data); + IRQF_ONESHOT, "hisi_thermal", data); if (ret < 0) { dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); return ret; } - enable_irq(data->irq); + hisi_thermal_toggle_sensor(&data->sensors, true); return 0; } @@ -440,7 +425,6 @@ static int hisi_thermal_suspend(struct device *dev) struct hisi_thermal_data *data = dev_get_drvdata(dev); hisi_thermal_disable_sensor(data); - data->irq_enabled = false; clk_disable_unprepare(data->clk); @@ -456,8 +440,7 @@ static int hisi_thermal_resume(struct device *dev) if (ret) return ret; - data->irq_enabled = true; - hisi_thermal_enable_bind_irq_sensor(data); + hisi_thermal_setup(data); return 0; } -- GitLab From 609f26dcbb340d7d6b30b1951c8b525611a97c20 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:52 +0200 Subject: [PATCH 1480/2898] thermal/drivers/hisi: Rename and remove unused field Rename the 'sensors' field to 'sensor' as we describe only one sensor. Remove the 'sensor_temp' as it is no longer used. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Tested-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 7c5d4647cb5e..0b1f56a81b9f 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -49,8 +49,6 @@ struct hisi_thermal_sensor { struct hisi_thermal_data *thermal; struct thermal_zone_device *tzd; - - long sensor_temp; uint32_t id; uint32_t thres_temp; }; @@ -59,9 +57,9 @@ struct hisi_thermal_data { struct mutex thermal_lock; /* protects register data */ struct platform_device *pdev; struct clk *clk; - struct hisi_thermal_sensor sensors; - int irq; + struct hisi_thermal_sensor sensor; void __iomem *regs; + int irq; }; /* @@ -233,7 +231,7 @@ static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = { static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) { struct hisi_thermal_data *data = dev; - struct hisi_thermal_sensor *sensor = &data->sensors; + struct hisi_thermal_sensor *sensor = &data->sensor; int temp; hisi_thermal_alarm_clear(data->regs, 1); @@ -244,7 +242,7 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) dev_crit(&data->pdev->dev, "THERMAL ALARM: %d > %d\n", temp, sensor->thres_temp); - thermal_zone_device_update(data->sensors.tzd, + thermal_zone_device_update(data->sensor.tzd, THERMAL_EVENT_UNSPECIFIED); } else if (temp < sensor->thres_temp) { @@ -307,7 +305,7 @@ static int hisi_thermal_setup(struct hisi_thermal_data *data) { struct hisi_thermal_sensor *sensor; - sensor = &data->sensors; + sensor = &data->sensor; /* disable module firstly */ hisi_thermal_reset_enable(data->regs, 0); @@ -380,7 +378,7 @@ static int hisi_thermal_probe(struct platform_device *pdev) } ret = hisi_thermal_register_sensor(pdev, data, - &data->sensors, + &data->sensor, HISI_DEFAULT_SENSOR); if (ret) { dev_err(&pdev->dev, "failed to register thermal sensor: %d\n", @@ -402,7 +400,7 @@ static int hisi_thermal_probe(struct platform_device *pdev) return ret; } - hisi_thermal_toggle_sensor(&data->sensors, true); + hisi_thermal_toggle_sensor(&data->sensor, true); return 0; } @@ -410,7 +408,7 @@ static int hisi_thermal_probe(struct platform_device *pdev) static int hisi_thermal_remove(struct platform_device *pdev) { struct hisi_thermal_data *data = platform_get_drvdata(pdev); - struct hisi_thermal_sensor *sensor = &data->sensors; + struct hisi_thermal_sensor *sensor = &data->sensor; hisi_thermal_toggle_sensor(sensor, false); hisi_thermal_disable_sensor(data); -- GitLab From bc02ef6d98a601a39f735cbbb67807fb752b5138 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:53 +0200 Subject: [PATCH 1481/2898] thermal/drivers/hisi: Convert long to int There is no point to specify the temperature as long variable, the int is enough. Replace all long variables to int, so making the code consistent. Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 0b1f56a81b9f..30bc69921dca 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -85,12 +85,12 @@ static inline int hisi_thermal_step_to_temp(int step) return HISI_TEMP_BASE + (step * HISI_TEMP_STEP); } -static inline long hisi_thermal_temp_to_step(long temp) +static inline int hisi_thermal_temp_to_step(int temp) { return (temp - HISI_TEMP_BASE) / HISI_TEMP_STEP; } -static inline long hisi_thermal_round_temp(int temp) +static inline int hisi_thermal_round_temp(int temp) { return hisi_thermal_step_to_temp( hisi_thermal_temp_to_step(temp)); -- GitLab From 81d7cb7946f03d339244e1a822b7da246d8c79ff Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:54 +0200 Subject: [PATCH 1482/2898] thermal/drivers/hisi: Remove thermal data back pointer The presence of the thermal data pointer in the sensor structure has the unique purpose of accessing the thermal data in the interrupt handler. The sensor pointer is passed when registering the interrupt handler, replace the cookie by the thermal data pointer, so the back pointer is no longer needed. Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 30bc69921dca..e09b52313ceb 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -47,7 +47,6 @@ #define HISI_DEFAULT_SENSOR 2 struct hisi_thermal_sensor { - struct hisi_thermal_data *thermal; struct thermal_zone_device *tzd; uint32_t id; uint32_t thres_temp; @@ -211,10 +210,10 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) mutex_unlock(&data->thermal_lock); } -static int hisi_thermal_get_temp(void *_sensor, int *temp) +static int hisi_thermal_get_temp(void *__data, int *temp) { - struct hisi_thermal_sensor *sensor = _sensor; - struct hisi_thermal_data *data = sensor->thermal; + struct hisi_thermal_data *data = __data; + struct hisi_thermal_sensor *sensor = &data->sensor; *temp = hisi_thermal_get_temperature(data->regs); @@ -262,10 +261,10 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, const struct thermal_trip *trip; sensor->id = index; - sensor->thermal = data; sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, - sensor->id, sensor, &hisi_of_thermal_ops); + sensor->id, data, + &hisi_of_thermal_ops); if (IS_ERR(sensor->tzd)) { ret = PTR_ERR(sensor->tzd); sensor->tzd = NULL; -- GitLab From cc1ab38d2b2ad3290426c2234cf83e7a323554c7 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:55 +0200 Subject: [PATCH 1483/2898] thermal/drivers/hisi: Remove mutex_lock in the code The mutex is used to protect against writes in the configuration register. That happens at probe time, with no possible race yet. Then when the module is unloaded and at suspend/resume. When the module is unloaded, it is an userspace operation, thus via a process. Suspending the system goes through the freezer to suspend all the tasks synchronously before continuing. So it is not possible to hit the suspend ops in this driver while we are unloading it. The resume is the same situation than the probe. In other words, even if there are several places where we write the configuration register, there is no situation where we can write it at the same time, so far as I can judge Signed-off-by: Daniel Lezcano Reviewed-by: Leo Yan Tested-by: Leo Yan Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index e09b52313ceb..90e91fedc76d 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -53,7 +53,6 @@ struct hisi_thermal_sensor { }; struct hisi_thermal_data { - struct mutex thermal_lock; /* protects register data */ struct platform_device *pdev; struct clk *clk; struct hisi_thermal_sensor sensor; @@ -200,14 +199,10 @@ static inline void hisi_thermal_hdak_set(void __iomem *addr, int value) static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) { - mutex_lock(&data->thermal_lock); - /* disable sensor module */ hisi_thermal_enable(data->regs, 0); hisi_thermal_alarm_enable(data->regs, 0); hisi_thermal_reset_enable(data->regs, 0); - - mutex_unlock(&data->thermal_lock); } static int hisi_thermal_get_temp(void *__data, int *temp) @@ -344,7 +339,6 @@ static int hisi_thermal_probe(struct platform_device *pdev) if (!data) return -ENOMEM; - mutex_init(&data->thermal_lock); data->pdev = pdev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- GitLab From 943c0f6abfb6010065b80943356975885a33233c Mon Sep 17 00:00:00 2001 From: Kevin Wangtao Date: Thu, 19 Oct 2017 19:05:56 +0200 Subject: [PATCH 1484/2898] thermal/drivers/hisi: Move the clk setup in the corresponding functions The sensor's clock is enabled and disabled outside of the probe and disable function. Moving the corresponding action in the hisi_thermal_setup() and hisi_thermal_disable_sensor(), factors out some lines of code and makes the code more symmetric. Signed-off-by: Kevin Wangtao Tested-by: Daniel Lezcano # hikey6220 Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 90e91fedc76d..373bb6d094a1 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -203,6 +203,8 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) hisi_thermal_enable(data->regs, 0); hisi_thermal_alarm_enable(data->regs, 0); hisi_thermal_reset_enable(data->regs, 0); + + clk_disable_unprepare(data->clk); } static int hisi_thermal_get_temp(void *__data, int *temp) @@ -297,9 +299,13 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, static int hisi_thermal_setup(struct hisi_thermal_data *data) { - struct hisi_thermal_sensor *sensor; + struct hisi_thermal_sensor *sensor = &data->sensor; + int ret; - sensor = &data->sensor; + /* enable clock for tsensor */ + ret = clk_prepare_enable(data->clk); + if (ret) + return ret; /* disable module firstly */ hisi_thermal_reset_enable(data->regs, 0); @@ -363,13 +369,6 @@ static int hisi_thermal_probe(struct platform_device *pdev) return ret; } - /* enable clock for thermal */ - ret = clk_prepare_enable(data->clk); - if (ret) { - dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret); - return ret; - } - ret = hisi_thermal_register_sensor(pdev, data, &data->sensor, HISI_DEFAULT_SENSOR); @@ -405,7 +404,6 @@ static int hisi_thermal_remove(struct platform_device *pdev) hisi_thermal_toggle_sensor(sensor, false); hisi_thermal_disable_sensor(data); - clk_disable_unprepare(data->clk); return 0; } @@ -417,23 +415,14 @@ static int hisi_thermal_suspend(struct device *dev) hisi_thermal_disable_sensor(data); - clk_disable_unprepare(data->clk); - return 0; } static int hisi_thermal_resume(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); - int ret; - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - - hisi_thermal_setup(data); - - return 0; + return hisi_thermal_setup(data); } #endif -- GitLab From e42bbe1160c3b5fcab8d5afcc49d8647adff6c9c Mon Sep 17 00:00:00 2001 From: Kevin Wangtao Date: Thu, 19 Oct 2017 19:05:57 +0200 Subject: [PATCH 1485/2898] thermal/drivers/hisi: Use round up step value Use round up division to ensure the programmed value of threshold and the lag are not less than what we set, and in order to keep the accuracy while using round up division, the step value should be a rounded up value. There is no need to use hisi_thermal_round_temp. Signed-off-by: Kevin Wangtao Tested-by: Daniel Lezcano # hikey6220 Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 373bb6d094a1..65f9e5c80741 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -40,7 +40,7 @@ #define HISI_TEMP_BASE (-60000) #define HISI_TEMP_RESET (100000) -#define HISI_TEMP_STEP (784) +#define HISI_TEMP_STEP (785) #define HISI_TEMP_LAG (3500) #define HISI_MAX_SENSORS 4 @@ -63,19 +63,19 @@ struct hisi_thermal_data { /* * The temperature computation on the tsensor is as follow: * Unit: millidegree Celsius - * Step: 255/200 (0.7843) + * Step: 200/255 (0.7843) * Temperature base: -60°C * - * The register is programmed in temperature steps, every step is 784 + * The register is programmed in temperature steps, every step is 785 * millidegree and begins at -60 000 m°C * * The temperature from the steps: * - * Temp = TempBase + (steps x 784) + * Temp = TempBase + (steps x 785) * * and the steps from the temperature: * - * steps = (Temp - TempBase) / 784 + * steps = (Temp - TempBase) / 785 * */ static inline int hisi_thermal_step_to_temp(int step) @@ -85,13 +85,7 @@ static inline int hisi_thermal_step_to_temp(int step) static inline int hisi_thermal_temp_to_step(int temp) { - return (temp - HISI_TEMP_BASE) / HISI_TEMP_STEP; -} - -static inline int hisi_thermal_round_temp(int temp) -{ - return hisi_thermal_step_to_temp( - hisi_thermal_temp_to_step(temp)); + return DIV_ROUND_UP(temp - HISI_TEMP_BASE, HISI_TEMP_STEP); } /* @@ -127,7 +121,7 @@ static inline int hisi_thermal_round_temp(int temp) */ static inline void hisi_thermal_set_lag(void __iomem *addr, int value) { - writel((value / HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); + writel(DIV_ROUND_UP(value, HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); } static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) @@ -274,7 +268,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { if (trip[i].type == THERMAL_TRIP_PASSIVE) { - sensor->thres_temp = hisi_thermal_round_temp(trip[i].temperature); + sensor->thres_temp = trip[i].temperature; break; } } -- GitLab From 07209fcf33542c1ff1e29df2dbdf8f29cdaacb10 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:58 +0200 Subject: [PATCH 1486/2898] thermal/drivers/step_wise: Fix temperature regulation misbehavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a particular situation when the cooling device is cpufreq and the heat dissipation is not efficient enough where the temperature increases little by little until reaching the critical threshold and leading to a SoC reset. The behavior is reproducible on a hikey6220 with bad heat dissipation (eg. stacked with other boards). Running a simple C program doing while(1); for each CPU of the SoC makes the temperature to reach the passive regulation trip point and ends up to the maximum allowed temperature followed by a reset. This issue has been also reported by running the libhugetlbfs test suite. What is observed is a ping pong between two cpu frequencies, 1.2GHz and 900MHz while the temperature continues to grow. It appears the step wise governor calls get_target_state() the first time with the throttle set to true and the trend to 'raising'. The code selects logically the next state, so the cpu frequency decreases from 1.2GHz to 900MHz, so far so good. The temperature decreases immediately but still stays greater than the trip point, then get_target_state() is called again, this time with the throttle set to true *and* the trend to 'dropping'. From there the algorithm assumes we have to step down the state and the cpu frequency jumps back to 1.2GHz. But the temperature is still higher than the trip point, so get_target_state() is called with throttle=1 and trend='raising' again, we jump to 900MHz, then get_target_state() is called with throttle=1 and trend='dropping', we jump to 1.2GHz, etc ... but the temperature does not stabilizes and continues to increase. [ 237.922654] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=1,throttle=1 [ 237.922678] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=1,throttle=1 [ 237.922690] thermal cooling_device0: cur_state=0 [ 237.922701] thermal cooling_device0: old_target=0, target=1 [ 238.026656] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=2,throttle=1 [ 238.026680] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=2,throttle=1 [ 238.026694] thermal cooling_device0: cur_state=1 [ 238.026707] thermal cooling_device0: old_target=1, target=0 [ 238.134647] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=1,throttle=1 [ 238.134667] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=1,throttle=1 [ 238.134679] thermal cooling_device0: cur_state=0 [ 238.134690] thermal cooling_device0: old_target=0, target=1 In this situation the temperature continues to increase while the trend is oscillating between 'dropping' and 'raising'. We need to keep the current state untouched if the throttle is set, so the temperature can decrease or a higher state could be selected, thus preventing this oscillation. Keeping the next_target untouched when 'throttle' is true at 'dropping' time fixes the issue. The following traces show the governor does not change the next state if trend==2 (dropping) and throttle==1. [ 2306.127987] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=1,throttle=1 [ 2306.128009] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=1,throttle=1 [ 2306.128021] thermal cooling_device0: cur_state=0 [ 2306.128031] thermal cooling_device0: old_target=0, target=1 [ 2306.231991] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=2,throttle=1 [ 2306.232016] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=2,throttle=1 [ 2306.232030] thermal cooling_device0: cur_state=1 [ 2306.232042] thermal cooling_device0: old_target=1, target=1 [ 2306.335982] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=0,throttle=1 [ 2306.336006] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=0,throttle=1 [ 2306.336021] thermal cooling_device0: cur_state=1 [ 2306.336034] thermal cooling_device0: old_target=1, target=1 [ 2306.439984] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=2,throttle=1 [ 2306.440008] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=2,throttle=0 [ 2306.440022] thermal cooling_device0: cur_state=1 [ 2306.440034] thermal cooling_device0: old_target=1, target=0 [ ... ] After a while, if the temperature continues to increase, the next state becomes 2 which is 720MHz on the hikey. That results in the temperature stabilizing around the trip point. [ 2455.831982] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=1,throttle=1 [ 2455.832006] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=1,throttle=0 [ 2455.832019] thermal cooling_device0: cur_state=1 [ 2455.832032] thermal cooling_device0: old_target=1, target=1 [ 2455.935985] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=0,throttle=1 [ 2455.936013] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=0,throttle=0 [ 2455.936027] thermal cooling_device0: cur_state=1 [ 2455.936040] thermal cooling_device0: old_target=1, target=1 [ 2456.043984] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=0,throttle=1 [ 2456.044009] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=0,throttle=0 [ 2456.044023] thermal cooling_device0: cur_state=1 [ 2456.044036] thermal cooling_device0: old_target=1, target=1 [ 2456.148001] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=1,throttle=1 [ 2456.148028] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=1,throttle=1 [ 2456.148042] thermal cooling_device0: cur_state=1 [ 2456.148055] thermal cooling_device0: old_target=1, target=2 [ 2456.252009] thermal thermal_zone0: Trip0[type=1,temp=65000]:trend=2,throttle=1 [ 2456.252041] thermal thermal_zone0: Trip1[type=1,temp=75000]:trend=2,throttle=0 [ 2456.252058] thermal cooling_device0: cur_state=2 [ 2456.252075] thermal cooling_device0: old_target=2, target=1 IOW, this change is needed to keep the state for a cooling device if the temperature trend is oscillating while the temperature increases slightly. Without this change, the situation above leads to a catastrophic crash by a hardware reset on hikey. This issue has been reported to happen on an OMAP dra7xx also. Signed-off-by: Daniel Lezcano Cc: Keerthy Cc: John Stultz Cc: Leo Yan Tested-by: Keerthy Reviewed-by: Keerthy Signed-off-by: Eduardo Valentin --- drivers/thermal/step_wise.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c index be95826631b7..ee047ca43084 100644 --- a/drivers/thermal/step_wise.c +++ b/drivers/thermal/step_wise.c @@ -31,8 +31,7 @@ * If the temperature is higher than a trip point, * a. if the trend is THERMAL_TREND_RAISING, use higher cooling * state for this trip point - * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling - * state for this trip point + * b. if the trend is THERMAL_TREND_DROPPING, do nothing * c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit * for this trip point * d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit @@ -94,9 +93,11 @@ static unsigned long get_target_state(struct thermal_instance *instance, if (!throttle) next_target = THERMAL_NO_TARGET; } else { - next_target = cur_state - 1; - if (next_target > instance->upper) - next_target = instance->upper; + if (!throttle) { + next_target = cur_state - 1; + if (next_target > instance->upper) + next_target = instance->upper; + } } break; case THERMAL_TREND_DROP_FULL: -- GitLab From d377aba193111419341fabaec6cab92df25e1b28 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:05:59 +0200 Subject: [PATCH 1487/2898] thermal/drivers/generic-iio-adc: Switch tz request to devm version Everything mentionned here: https://lkml.org/lkml/2016/4/20/850 This driver was added before the devm_iio_channel_get() function version was merged. The sensor should be released before the iio channel, thus we had to use the non-devm version of thermal_zone_of_sensor_register(). Now the devm_iio_channel_get() is available, do the corresponding change in this driver and remove gadc_thermal_remove(). [Compiled tested only] Acked-by: Laxman Dewangan Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/thermal-generic-adc.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c index 73f55d6a1721..46d3005335c7 100644 --- a/drivers/thermal/thermal-generic-adc.c +++ b/drivers/thermal/thermal-generic-adc.c @@ -126,37 +126,22 @@ static int gadc_thermal_probe(struct platform_device *pdev) gti->dev = &pdev->dev; platform_set_drvdata(pdev, gti); - gti->channel = iio_channel_get(&pdev->dev, "sensor-channel"); + gti->channel = devm_iio_channel_get(&pdev->dev, "sensor-channel"); if (IS_ERR(gti->channel)) { ret = PTR_ERR(gti->channel); dev_err(&pdev->dev, "IIO channel not found: %d\n", ret); return ret; } - gti->tz_dev = thermal_zone_of_sensor_register(&pdev->dev, 0, - gti, &gadc_thermal_ops); + gti->tz_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, gti, + &gadc_thermal_ops); if (IS_ERR(gti->tz_dev)) { ret = PTR_ERR(gti->tz_dev); dev_err(&pdev->dev, "Thermal zone sensor register failed: %d\n", ret); - goto sensor_fail; + return ret; } - return 0; - -sensor_fail: - iio_channel_release(gti->channel); - - return ret; -} - -static int gadc_thermal_remove(struct platform_device *pdev) -{ - struct gadc_thermal_info *gti = platform_get_drvdata(pdev); - - thermal_zone_of_sensor_unregister(&pdev->dev, gti->tz_dev); - iio_channel_release(gti->channel); - return 0; } @@ -172,7 +157,6 @@ static struct platform_driver gadc_thermal_driver = { .of_match_table = of_adc_thermal_match, }, .probe = gadc_thermal_probe, - .remove = gadc_thermal_remove, }; module_platform_driver(gadc_thermal_driver); -- GitLab From 7a4ca51b704038d1d7f5e31177a7fa4d9dcb839e Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 19 Oct 2017 19:06:00 +0200 Subject: [PATCH 1488/2898] thermal/drivers/qcom-spmi: Use devm_iio_channel_get The iio_channel_get() function has now its devm_ version. Use it and remove all the rollback code for iio_channel_release() as well as the .remove ops. [Compiled tested only] Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/qcom-spmi-temp-alarm.c | 43 +++++++++----------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c index f50241962ad2..95f987d5aa71 100644 --- a/drivers/thermal/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom-spmi-temp-alarm.c @@ -125,7 +125,7 @@ static int qpnp_tm_get_temp(void *data, int *temp) if (!temp) return -EINVAL; - if (IS_ERR(chip->adc)) { + if (!chip->adc) { ret = qpnp_tm_update_temp_no_adc(chip); if (ret < 0) return ret; @@ -224,67 +224,53 @@ static int qpnp_tm_probe(struct platform_device *pdev) return irq; /* ADC based measurements are optional */ - chip->adc = iio_channel_get(&pdev->dev, "thermal"); - if (PTR_ERR(chip->adc) == -EPROBE_DEFER) - return PTR_ERR(chip->adc); + chip->adc = devm_iio_channel_get(&pdev->dev, "thermal"); + if (IS_ERR(chip->adc)) { + ret = PTR_ERR(chip->adc); + chip->adc = NULL; + if (ret == -EPROBE_DEFER) + return ret; + } chip->base = res; ret = qpnp_tm_read(chip, QPNP_TM_REG_TYPE, &type); if (ret < 0) { dev_err(&pdev->dev, "could not read type\n"); - goto fail; + return ret; } ret = qpnp_tm_read(chip, QPNP_TM_REG_SUBTYPE, &subtype); if (ret < 0) { dev_err(&pdev->dev, "could not read subtype\n"); - goto fail; + return ret; } if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) { dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", type, subtype); - ret = -ENODEV; - goto fail; + return -ENODEV; } ret = qpnp_tm_init(chip); if (ret < 0) { dev_err(&pdev->dev, "init failed\n"); - goto fail; + return ret; } ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, qpnp_tm_isr, IRQF_ONESHOT, node->name, chip); if (ret < 0) - goto fail; + return ret; chip->tz_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, chip, &qpnp_tm_sensor_ops); if (IS_ERR(chip->tz_dev)) { dev_err(&pdev->dev, "failed to register sensor\n"); - ret = PTR_ERR(chip->tz_dev); - goto fail; + return PTR_ERR(chip->tz_dev); } return 0; - -fail: - if (!IS_ERR(chip->adc)) - iio_channel_release(chip->adc); - - return ret; -} - -static int qpnp_tm_remove(struct platform_device *pdev) -{ - struct qpnp_tm_chip *chip = dev_get_drvdata(&pdev->dev); - - if (!IS_ERR(chip->adc)) - iio_channel_release(chip->adc); - - return 0; } static const struct of_device_id qpnp_tm_match_table[] = { @@ -299,7 +285,6 @@ static struct platform_driver qpnp_tm_driver = { .of_match_table = qpnp_tm_match_table, }, .probe = qpnp_tm_probe, - .remove = qpnp_tm_remove, }; module_platform_driver(qpnp_tm_driver); -- GitLab From a0678da82ca01771db57f53bfb7f0a5a7494900e Mon Sep 17 00:00:00 2001 From: Kevin Wangtao Date: Sun, 22 Oct 2017 10:54:32 +0200 Subject: [PATCH 1489/2898] thermal/drivers/hisi: Put platform code together Reorganize the code for next patches by moving the functions upper in the file which will prevent a forward declaration. There is no functional change here. Signed-off-by: Kevin Wangtao Tested-by: Daniel Lezcano # hikey6220 Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 76 +++++++++++++++++----------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 65f9e5c80741..a0b7e26e4796 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -201,6 +201,44 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) clk_disable_unprepare(data->clk); } +static int hisi_thermal_setup(struct hisi_thermal_data *data) +{ + struct hisi_thermal_sensor *sensor = &data->sensor; + int ret; + + /* enable clock for tsensor */ + ret = clk_prepare_enable(data->clk); + if (ret) + return ret; + + /* disable module firstly */ + hisi_thermal_reset_enable(data->regs, 0); + hisi_thermal_enable(data->regs, 0); + + /* select sensor id */ + hisi_thermal_sensor_select(data->regs, sensor->id); + + /* setting the hdak time */ + hisi_thermal_hdak_set(data->regs, 0); + + /* setting lag value between current temp and the threshold */ + hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); + + /* enable for interrupt */ + hisi_thermal_alarm_set(data->regs, sensor->thres_temp); + + hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); + + /* enable module */ + hisi_thermal_reset_enable(data->regs, 1); + hisi_thermal_enable(data->regs, 1); + + hisi_thermal_alarm_clear(data->regs, 0); + hisi_thermal_alarm_enable(data->regs, 1); + + return 0; +} + static int hisi_thermal_get_temp(void *__data, int *temp) { struct hisi_thermal_data *data = __data; @@ -291,44 +329,6 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); } -static int hisi_thermal_setup(struct hisi_thermal_data *data) -{ - struct hisi_thermal_sensor *sensor = &data->sensor; - int ret; - - /* enable clock for tsensor */ - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - - /* disable module firstly */ - hisi_thermal_reset_enable(data->regs, 0); - hisi_thermal_enable(data->regs, 0); - - /* select sensor id */ - hisi_thermal_sensor_select(data->regs, sensor->id); - - /* setting the hdak time */ - hisi_thermal_hdak_set(data->regs, 0); - - /* setting lag value between current temp and the threshold */ - hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); - - /* enable for interrupt */ - hisi_thermal_alarm_set(data->regs, sensor->thres_temp); - - hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); - - /* enable module */ - hisi_thermal_reset_enable(data->regs, 1); - hisi_thermal_enable(data->regs, 1); - - hisi_thermal_alarm_clear(data->regs, 0); - hisi_thermal_alarm_enable(data->regs, 1); - - return 0; -} - static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; -- GitLab From 5ed82b79e526f755bf0630a7c47a31ca2f4a7ad5 Mon Sep 17 00:00:00 2001 From: Kevin Wangtao Date: Sun, 22 Oct 2017 10:54:33 +0200 Subject: [PATCH 1490/2898] thermal/drivers/hisi: Add platform prefix to function name As the next patches will provide support for the hikey3660's sensor, several functions with the same purpose but for different platforms will be introduced. In order to make a clear distinction between them, let's prefix the function names with the platform name. This patch has no functional changes, only name changes. Signed-off-by: Kevin Wangtao Tested-by: Daniel Lezcano # hikey6220 Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 145 +++++++++++++++++---------------- 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index a0b7e26e4796..c2cb2807372d 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -26,25 +26,24 @@ #include "thermal_core.h" -#define TEMP0_LAG (0x0) -#define TEMP0_TH (0x4) -#define TEMP0_RST_TH (0x8) -#define TEMP0_CFG (0xC) -#define TEMP0_CFG_SS_MSK (0xF000) -#define TEMP0_CFG_HDAK_MSK (0x30) -#define TEMP0_EN (0x10) -#define TEMP0_INT_EN (0x14) -#define TEMP0_INT_CLR (0x18) -#define TEMP0_RST_MSK (0x1C) -#define TEMP0_VALUE (0x28) - -#define HISI_TEMP_BASE (-60000) -#define HISI_TEMP_RESET (100000) -#define HISI_TEMP_STEP (785) -#define HISI_TEMP_LAG (3500) - -#define HISI_MAX_SENSORS 4 -#define HISI_DEFAULT_SENSOR 2 +#define HI6220_TEMP0_LAG (0x0) +#define HI6220_TEMP0_TH (0x4) +#define HI6220_TEMP0_RST_TH (0x8) +#define HI6220_TEMP0_CFG (0xC) +#define HI6220_TEMP0_CFG_SS_MSK (0xF000) +#define HI6220_TEMP0_CFG_HDAK_MSK (0x30) +#define HI6220_TEMP0_EN (0x10) +#define HI6220_TEMP0_INT_EN (0x14) +#define HI6220_TEMP0_INT_CLR (0x18) +#define HI6220_TEMP0_RST_MSK (0x1C) +#define HI6220_TEMP0_VALUE (0x28) + +#define HI6220_TEMP_BASE (-60000) +#define HI6220_TEMP_RESET (100000) +#define HI6220_TEMP_STEP (785) +#define HI6220_TEMP_LAG (3500) + +#define HI6220_DEFAULT_SENSOR 2 struct hisi_thermal_sensor { struct thermal_zone_device *tzd; @@ -78,14 +77,14 @@ struct hisi_thermal_data { * steps = (Temp - TempBase) / 785 * */ -static inline int hisi_thermal_step_to_temp(int step) +static inline int hi6220_thermal_step_to_temp(int step) { - return HISI_TEMP_BASE + (step * HISI_TEMP_STEP); + return HI6220_TEMP_BASE + (step * HI6220_TEMP_STEP); } -static inline int hisi_thermal_temp_to_step(int temp) +static inline int hi6220_thermal_temp_to_step(int temp) { - return DIV_ROUND_UP(temp - HISI_TEMP_BASE, HISI_TEMP_STEP); + return DIV_ROUND_UP(temp - HI6220_TEMP_BASE, HI6220_TEMP_STEP); } /* @@ -112,51 +111,53 @@ static inline int hisi_thermal_temp_to_step(int temp) * * [0:4] : lag register * - * The temperature is coded in steps, cf. HISI_TEMP_STEP. + * The temperature is coded in steps, cf. HI6220_TEMP_STEP. * * Min : 0x00 : 0.0 °C * Max : 0x1F : 24.3 °C * * The 'value' parameter is in milliCelsius. */ -static inline void hisi_thermal_set_lag(void __iomem *addr, int value) +static inline void hi6220_thermal_set_lag(void __iomem *addr, int value) { - writel(DIV_ROUND_UP(value, HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); + writel(DIV_ROUND_UP(value, HI6220_TEMP_STEP) & 0x1F, + addr + HI6220_TEMP0_LAG); } -static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) +static inline void hi6220_thermal_alarm_clear(void __iomem *addr, int value) { - writel(value, addr + TEMP0_INT_CLR); + writel(value, addr + HI6220_TEMP0_INT_CLR); } -static inline void hisi_thermal_alarm_enable(void __iomem *addr, int value) +static inline void hi6220_thermal_alarm_enable(void __iomem *addr, int value) { - writel(value, addr + TEMP0_INT_EN); + writel(value, addr + HI6220_TEMP0_INT_EN); } -static inline void hisi_thermal_alarm_set(void __iomem *addr, int temp) +static inline void hi6220_thermal_alarm_set(void __iomem *addr, int temp) { - writel(hisi_thermal_temp_to_step(temp) | 0x0FFFFFF00, addr + TEMP0_TH); + writel(hi6220_thermal_temp_to_step(temp) | 0x0FFFFFF00, + addr + HI6220_TEMP0_TH); } -static inline void hisi_thermal_reset_set(void __iomem *addr, int temp) +static inline void hi6220_thermal_reset_set(void __iomem *addr, int temp) { - writel(hisi_thermal_temp_to_step(temp), addr + TEMP0_RST_TH); + writel(hi6220_thermal_temp_to_step(temp), addr + HI6220_TEMP0_RST_TH); } -static inline void hisi_thermal_reset_enable(void __iomem *addr, int value) +static inline void hi6220_thermal_reset_enable(void __iomem *addr, int value) { - writel(value, addr + TEMP0_RST_MSK); + writel(value, addr + HI6220_TEMP0_RST_MSK); } -static inline void hisi_thermal_enable(void __iomem *addr, int value) +static inline void hi6220_thermal_enable(void __iomem *addr, int value) { - writel(value, addr + TEMP0_EN); + writel(value, addr + HI6220_TEMP0_EN); } -static inline int hisi_thermal_get_temperature(void __iomem *addr) +static inline int hi6220_thermal_get_temperature(void __iomem *addr) { - return hisi_thermal_step_to_temp(readl(addr + TEMP0_VALUE)); + return hi6220_thermal_step_to_temp(readl(addr + HI6220_TEMP0_VALUE)); } /* @@ -169,10 +170,10 @@ static inline int hisi_thermal_get_temperature(void __iomem *addr) * 0x2: remote sensor 2 (ACPU cluster 0) * 0x3: remote sensor 3 (G3D) */ -static inline void hisi_thermal_sensor_select(void __iomem *addr, int sensor) +static inline void hi6220_thermal_sensor_select(void __iomem *addr, int sensor) { - writel((readl(addr + TEMP0_CFG) & ~TEMP0_CFG_SS_MSK) | - (sensor << 12), addr + TEMP0_CFG); + writel((readl(addr + HI6220_TEMP0_CFG) & ~HI6220_TEMP0_CFG_SS_MSK) | + (sensor << 12), addr + HI6220_TEMP0_CFG); } /* @@ -185,23 +186,23 @@ static inline void hisi_thermal_sensor_select(void __iomem *addr, int sensor) * 0x2 : 49.152 ms * 0x3 : 393.216 ms */ -static inline void hisi_thermal_hdak_set(void __iomem *addr, int value) +static inline void hi6220_thermal_hdak_set(void __iomem *addr, int value) { - writel((readl(addr + TEMP0_CFG) & ~TEMP0_CFG_HDAK_MSK) | - (value << 4), addr + TEMP0_CFG); + writel((readl(addr + HI6220_TEMP0_CFG) & ~HI6220_TEMP0_CFG_HDAK_MSK) | + (value << 4), addr + HI6220_TEMP0_CFG); } -static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) +static void hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) { /* disable sensor module */ - hisi_thermal_enable(data->regs, 0); - hisi_thermal_alarm_enable(data->regs, 0); - hisi_thermal_reset_enable(data->regs, 0); + hi6220_thermal_enable(data->regs, 0); + hi6220_thermal_alarm_enable(data->regs, 0); + hi6220_thermal_reset_enable(data->regs, 0); clk_disable_unprepare(data->clk); } -static int hisi_thermal_setup(struct hisi_thermal_data *data) +static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) { struct hisi_thermal_sensor *sensor = &data->sensor; int ret; @@ -212,29 +213,29 @@ static int hisi_thermal_setup(struct hisi_thermal_data *data) return ret; /* disable module firstly */ - hisi_thermal_reset_enable(data->regs, 0); - hisi_thermal_enable(data->regs, 0); + hi6220_thermal_reset_enable(data->regs, 0); + hi6220_thermal_enable(data->regs, 0); /* select sensor id */ - hisi_thermal_sensor_select(data->regs, sensor->id); + hi6220_thermal_sensor_select(data->regs, sensor->id); /* setting the hdak time */ - hisi_thermal_hdak_set(data->regs, 0); + hi6220_thermal_hdak_set(data->regs, 0); /* setting lag value between current temp and the threshold */ - hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); + hi6220_thermal_set_lag(data->regs, HI6220_TEMP_LAG); /* enable for interrupt */ - hisi_thermal_alarm_set(data->regs, sensor->thres_temp); + hi6220_thermal_alarm_set(data->regs, sensor->thres_temp); - hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); + hi6220_thermal_reset_set(data->regs, HI6220_TEMP_RESET); /* enable module */ - hisi_thermal_reset_enable(data->regs, 1); - hisi_thermal_enable(data->regs, 1); + hi6220_thermal_reset_enable(data->regs, 1); + hi6220_thermal_enable(data->regs, 1); - hisi_thermal_alarm_clear(data->regs, 0); - hisi_thermal_alarm_enable(data->regs, 1); + hi6220_thermal_alarm_clear(data->regs, 0); + hi6220_thermal_alarm_enable(data->regs, 1); return 0; } @@ -244,7 +245,7 @@ static int hisi_thermal_get_temp(void *__data, int *temp) struct hisi_thermal_data *data = __data; struct hisi_thermal_sensor *sensor = &data->sensor; - *temp = hisi_thermal_get_temperature(data->regs); + *temp = hi6220_thermal_get_temperature(data->regs); dev_dbg(&data->pdev->dev, "id=%d, temp=%d, thres=%d\n", sensor->id, *temp, sensor->thres_temp); @@ -260,11 +261,11 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) { struct hisi_thermal_data *data = dev; struct hisi_thermal_sensor *sensor = &data->sensor; - int temp; + int temp = 0; - hisi_thermal_alarm_clear(data->regs, 1); + hi6220_thermal_alarm_clear(data->regs, 1); - temp = hisi_thermal_get_temperature(data->regs); + hisi_thermal_get_temp(data, &temp); if (temp >= sensor->thres_temp) { dev_crit(&data->pdev->dev, "THERMAL ALARM: %d > %d\n", @@ -273,7 +274,7 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) thermal_zone_device_update(data->sensor.tzd, THERMAL_EVENT_UNSPECIFIED); - } else if (temp < sensor->thres_temp) { + } else { dev_crit(&data->pdev->dev, "THERMAL ALARM stopped: %d < %d\n", temp, sensor->thres_temp); } @@ -365,14 +366,14 @@ static int hisi_thermal_probe(struct platform_device *pdev) ret = hisi_thermal_register_sensor(pdev, data, &data->sensor, - HISI_DEFAULT_SENSOR); + HI6220_DEFAULT_SENSOR); if (ret) { dev_err(&pdev->dev, "failed to register thermal sensor: %d\n", ret); return ret; } - ret = hisi_thermal_setup(data); + ret = hi6220_thermal_enable_sensor(data); if (ret) { dev_err(&pdev->dev, "Failed to setup the sensor: %d\n", ret); return ret; @@ -397,7 +398,7 @@ static int hisi_thermal_remove(struct platform_device *pdev) struct hisi_thermal_sensor *sensor = &data->sensor; hisi_thermal_toggle_sensor(sensor, false); - hisi_thermal_disable_sensor(data); + hi6220_thermal_disable_sensor(data); return 0; } @@ -407,7 +408,7 @@ static int hisi_thermal_suspend(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); - hisi_thermal_disable_sensor(data); + hi6220_thermal_disable_sensor(data); return 0; } @@ -416,7 +417,7 @@ static int hisi_thermal_resume(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); - return hisi_thermal_setup(data); + return hi6220_thermal_enable_sensor(data); } #endif -- GitLab From a160a465297362c515db28848b79eb876ceab9c0 Mon Sep 17 00:00:00 2001 From: Kevin Wangtao Date: Sun, 22 Oct 2017 10:54:34 +0200 Subject: [PATCH 1491/2898] thermal/drivers/hisi: Prepare to add support for other hisi platforms For platform compatibility, add the tsensor ops to a thermal data structure. Each platform has its own probe function to register proper tsensor ops function to the pointer, platform related resource request are also implemented in the platform probe function. Signed-off-by: Kevin Wangtao Tested-by: Daniel Lezcano # hikey6220 Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 132 ++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 45 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index c2cb2807372d..b862506a588b 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "thermal_core.h" @@ -30,7 +31,7 @@ #define HI6220_TEMP0_TH (0x4) #define HI6220_TEMP0_RST_TH (0x8) #define HI6220_TEMP0_CFG (0xC) -#define HI6220_TEMP0_CFG_SS_MSK (0xF000) +#define HI6220_TEMP0_CFG_SS_MSK (0xF000) #define HI6220_TEMP0_CFG_HDAK_MSK (0x30) #define HI6220_TEMP0_EN (0x10) #define HI6220_TEMP0_INT_EN (0x14) @@ -41,7 +42,7 @@ #define HI6220_TEMP_BASE (-60000) #define HI6220_TEMP_RESET (100000) #define HI6220_TEMP_STEP (785) -#define HI6220_TEMP_LAG (3500) +#define HI6220_TEMP_LAG (3500) #define HI6220_DEFAULT_SENSOR 2 @@ -52,6 +53,10 @@ struct hisi_thermal_sensor { }; struct hisi_thermal_data { + int (*get_temp)(struct hisi_thermal_data *data); + int (*enable_sensor)(struct hisi_thermal_data *data); + int (*disable_sensor)(struct hisi_thermal_data *data); + int (*irq_handler)(struct hisi_thermal_data *data); struct platform_device *pdev; struct clk *clk; struct hisi_thermal_sensor sensor; @@ -192,7 +197,18 @@ static inline void hi6220_thermal_hdak_set(void __iomem *addr, int value) (value << 4), addr + HI6220_TEMP0_CFG); } -static void hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) +static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data) +{ + hi6220_thermal_alarm_clear(data->regs, 1); + return 0; +} + +static int hi6220_thermal_get_temp(struct hisi_thermal_data *data) +{ + return hi6220_thermal_get_temperature(data->regs); +} + +static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) { /* disable sensor module */ hi6220_thermal_enable(data->regs, 0); @@ -200,6 +216,8 @@ static void hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) hi6220_thermal_reset_enable(data->regs, 0); clk_disable_unprepare(data->clk); + + return 0; } static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) @@ -240,12 +258,48 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) return 0; } +static int hi6220_thermal_probe(struct hisi_thermal_data *data) +{ + struct platform_device *pdev = data->pdev; + struct device *dev = &pdev->dev; + struct resource *res; + int ret; + + data->get_temp = hi6220_thermal_get_temp; + data->enable_sensor = hi6220_thermal_enable_sensor; + data->disable_sensor = hi6220_thermal_disable_sensor; + data->irq_handler = hi6220_thermal_irq_handler; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(data->regs)) { + dev_err(dev, "failed to get io address\n"); + return PTR_ERR(data->regs); + } + + data->clk = devm_clk_get(dev, "thermal_clk"); + if (IS_ERR(data->clk)) { + ret = PTR_ERR(data->clk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get thermal clk: %d\n", ret); + return ret; + } + + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) + return data->irq; + + data->sensor.id = HI6220_DEFAULT_SENSOR; + + return 0; +} + static int hisi_thermal_get_temp(void *__data, int *temp) { struct hisi_thermal_data *data = __data; struct hisi_thermal_sensor *sensor = &data->sensor; - *temp = hi6220_thermal_get_temperature(data->regs); + *temp = data->get_temp(data); dev_dbg(&data->pdev->dev, "id=%d, temp=%d, thres=%d\n", sensor->id, *temp, sensor->thres_temp); @@ -263,7 +317,7 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) struct hisi_thermal_sensor *sensor = &data->sensor; int temp = 0; - hi6220_thermal_alarm_clear(data->regs, 1); + data->irq_handler(data); hisi_thermal_get_temp(data, &temp); @@ -284,14 +338,11 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) static int hisi_thermal_register_sensor(struct platform_device *pdev, struct hisi_thermal_data *data, - struct hisi_thermal_sensor *sensor, - int index) + struct hisi_thermal_sensor *sensor) { int ret, i; const struct thermal_trip *trip; - sensor->id = index; - sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, sensor->id, data, &hisi_of_thermal_ops); @@ -316,7 +367,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, } static const struct of_device_id of_hisi_thermal_match[] = { - { .compatible = "hisilicon,tsensor" }, + { .compatible = "hisilicon,tsensor", .data = hi6220_thermal_probe }, { /* end */ } }; MODULE_DEVICE_TABLE(of, of_hisi_thermal_match); @@ -333,58 +384,48 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; - struct resource *res; + int const (*platform_probe)(struct hisi_thermal_data *); + struct device *dev = &pdev->dev; int ret; - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; data->pdev = pdev; + platform_set_drvdata(pdev, data); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(data->regs)) { - dev_err(&pdev->dev, "failed to get io address\n"); - return PTR_ERR(data->regs); + platform_probe = of_device_get_match_data(dev); + if (!platform_probe) { + dev_err(dev, "failed to get probe func\n"); + return -EINVAL; } - data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) - return data->irq; - - platform_set_drvdata(pdev, data); - - data->clk = devm_clk_get(&pdev->dev, "thermal_clk"); - if (IS_ERR(data->clk)) { - ret = PTR_ERR(data->clk); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed to get thermal clk: %d\n", ret); + ret = platform_probe(data); + if (ret) return ret; - } ret = hisi_thermal_register_sensor(pdev, data, - &data->sensor, - HI6220_DEFAULT_SENSOR); + &data->sensor); if (ret) { - dev_err(&pdev->dev, "failed to register thermal sensor: %d\n", - ret); + dev_err(dev, "failed to register thermal sensor: %d\n", ret); return ret; } - ret = hi6220_thermal_enable_sensor(data); + ret = data->enable_sensor(data); if (ret) { - dev_err(&pdev->dev, "Failed to setup the sensor: %d\n", ret); + dev_err(dev, "Failed to setup the sensor: %d\n", ret); return ret; } - ret = devm_request_threaded_irq(&pdev->dev, data->irq, NULL, - hisi_thermal_alarm_irq_thread, - IRQF_ONESHOT, "hisi_thermal", data); - if (ret < 0) { - dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); - return ret; + if (data->irq) { + ret = devm_request_threaded_irq(dev, data->irq, NULL, + hisi_thermal_alarm_irq_thread, + IRQF_ONESHOT, "hisi_thermal", data); + if (ret < 0) { + dev_err(dev, "failed to request alarm irq: %d\n", ret); + return ret; + } } hisi_thermal_toggle_sensor(&data->sensor, true); @@ -398,7 +439,8 @@ static int hisi_thermal_remove(struct platform_device *pdev) struct hisi_thermal_sensor *sensor = &data->sensor; hisi_thermal_toggle_sensor(sensor, false); - hi6220_thermal_disable_sensor(data); + + data->disable_sensor(data); return 0; } @@ -408,7 +450,7 @@ static int hisi_thermal_suspend(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); - hi6220_thermal_disable_sensor(data); + data->disable_sensor(data); return 0; } @@ -417,7 +459,7 @@ static int hisi_thermal_resume(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); - return hi6220_thermal_enable_sensor(data); + return data->enable_sensor(data); } #endif -- GitLab From 2bb60a8ea721900c13b580689d647a6423e88104 Mon Sep 17 00:00:00 2001 From: Kevin Wangtao Date: Sun, 22 Oct 2017 10:54:35 +0200 Subject: [PATCH 1492/2898] thermal/drivers/hisi: Add support for hi3660 SoC This patch adds the support for thermal sensor on the Hi3660 SoC. Hi3660 tsensor support alarm in alarm threshold, it also has a configurable hysteresis interval, interrupt will be triggered when temperature rise above the alarm threshold or fall below the hysteresis threshold. Signed-off-by: Kevin Wangtao Tested-by: Daniel Lezcano # hikey6220 Signed-off-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 145 ++++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index b862506a588b..2d855a96cdd9 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -39,12 +39,24 @@ #define HI6220_TEMP0_RST_MSK (0x1C) #define HI6220_TEMP0_VALUE (0x28) +#define HI3660_OFFSET(chan) ((chan) * 0x40) +#define HI3660_TEMP(chan) (HI3660_OFFSET(chan) + 0x1C) +#define HI3660_TH(chan) (HI3660_OFFSET(chan) + 0x20) +#define HI3660_LAG(chan) (HI3660_OFFSET(chan) + 0x28) +#define HI3660_INT_EN(chan) (HI3660_OFFSET(chan) + 0x2C) +#define HI3660_INT_CLR(chan) (HI3660_OFFSET(chan) + 0x30) + #define HI6220_TEMP_BASE (-60000) #define HI6220_TEMP_RESET (100000) #define HI6220_TEMP_STEP (785) #define HI6220_TEMP_LAG (3500) +#define HI3660_TEMP_BASE (-63780) +#define HI3660_TEMP_STEP (205) +#define HI3660_TEMP_LAG (4000) + #define HI6220_DEFAULT_SENSOR 2 +#define HI3660_DEFAULT_SENSOR 1 struct hisi_thermal_sensor { struct thermal_zone_device *tzd; @@ -92,6 +104,24 @@ static inline int hi6220_thermal_temp_to_step(int temp) return DIV_ROUND_UP(temp - HI6220_TEMP_BASE, HI6220_TEMP_STEP); } +/* + * for Hi3660, + * Step: 189/922 (0.205) + * Temperature base: -63.780°C + * + * The register is programmed in temperature steps, every step is 205 + * millidegree and begins at -63 780 m°C + */ +static inline int hi3660_thermal_step_to_temp(int step) +{ + return HI3660_TEMP_BASE + step * HI3660_TEMP_STEP; +} + +static inline int hi3660_thermal_temp_to_step(int temp) +{ + return DIV_ROUND_UP(temp - HI3660_TEMP_BASE, HI3660_TEMP_STEP); +} + /* * The lag register contains 5 bits encoding the temperature in steps. * @@ -165,6 +195,45 @@ static inline int hi6220_thermal_get_temperature(void __iomem *addr) return hi6220_thermal_step_to_temp(readl(addr + HI6220_TEMP0_VALUE)); } +/* + * [0:6] lag register + * + * The temperature is coded in steps, cf. HI3660_TEMP_STEP. + * + * Min : 0x00 : 0.0 °C + * Max : 0x7F : 26.0 °C + * + */ +static inline void hi3660_thermal_set_lag(void __iomem *addr, + int id, int value) +{ + writel(DIV_ROUND_UP(value, HI3660_TEMP_STEP) & 0x7F, + addr + HI3660_LAG(id)); +} + +static inline void hi3660_thermal_alarm_clear(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_INT_CLR(id)); +} + +static inline void hi3660_thermal_alarm_enable(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_INT_EN(id)); +} + +static inline void hi3660_thermal_alarm_set(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_TH(id)); +} + +static inline int hi3660_thermal_get_temperature(void __iomem *addr, int id) +{ + return hi3660_thermal_step_to_temp(readl(addr + HI3660_TEMP(id))); +} + /* * Temperature configuration register - Sensor selection * @@ -203,11 +272,22 @@ static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data) return 0; } +static int hi3660_thermal_irq_handler(struct hisi_thermal_data *data) +{ + hi3660_thermal_alarm_clear(data->regs, data->sensor.id, 1); + return 0; +} + static int hi6220_thermal_get_temp(struct hisi_thermal_data *data) { return hi6220_thermal_get_temperature(data->regs); } +static int hi3660_thermal_get_temp(struct hisi_thermal_data *data) +{ + return hi3660_thermal_get_temperature(data->regs, data->sensor.id); +} + static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) { /* disable sensor module */ @@ -220,6 +300,13 @@ static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) return 0; } +static int hi3660_thermal_disable_sensor(struct hisi_thermal_data *data) +{ + /* disable sensor module */ + hi3660_thermal_alarm_enable(data->regs, data->sensor.id, 0); + return 0; +} + static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) { struct hisi_thermal_sensor *sensor = &data->sensor; @@ -258,6 +345,28 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) return 0; } +static int hi3660_thermal_enable_sensor(struct hisi_thermal_data *data) +{ + unsigned int value; + struct hisi_thermal_sensor *sensor = &data->sensor; + + /* disable interrupt */ + hi3660_thermal_alarm_enable(data->regs, sensor->id, 0); + + /* setting lag value between current temp and the threshold */ + hi3660_thermal_set_lag(data->regs, sensor->id, HI3660_TEMP_LAG); + + /* set interrupt threshold */ + value = hi3660_thermal_temp_to_step(sensor->thres_temp); + hi3660_thermal_alarm_set(data->regs, sensor->id, value); + + /* enable interrupt */ + hi3660_thermal_alarm_clear(data->regs, sensor->id, 1); + hi3660_thermal_alarm_enable(data->regs, sensor->id, 1); + + return 0; +} + static int hi6220_thermal_probe(struct hisi_thermal_data *data) { struct platform_device *pdev = data->pdev; @@ -294,6 +403,33 @@ static int hi6220_thermal_probe(struct hisi_thermal_data *data) return 0; } +static int hi3660_thermal_probe(struct hisi_thermal_data *data) +{ + struct platform_device *pdev = data->pdev; + struct device *dev = &pdev->dev; + struct resource *res; + + data->get_temp = hi3660_thermal_get_temp; + data->enable_sensor = hi3660_thermal_enable_sensor; + data->disable_sensor = hi3660_thermal_disable_sensor; + data->irq_handler = hi3660_thermal_irq_handler; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(data->regs)) { + dev_err(dev, "failed to get io address\n"); + return PTR_ERR(data->regs); + } + + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) + return data->irq; + + data->sensor.id = HI3660_DEFAULT_SENSOR; + + return 0; +} + static int hisi_thermal_get_temp(void *__data, int *temp) { struct hisi_thermal_data *data = __data; @@ -367,7 +503,14 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, } static const struct of_device_id of_hisi_thermal_match[] = { - { .compatible = "hisilicon,tsensor", .data = hi6220_thermal_probe }, + { + .compatible = "hisilicon,tsensor", + .data = hi6220_thermal_probe + }, + { + .compatible = "hisilicon,hi3660-tsensor", + .data = hi3660_thermal_probe + }, { /* end */ } }; MODULE_DEVICE_TABLE(of, of_hisi_thermal_match); -- GitLab From b590c51c9b956f465acc73a2864d3a1444c76c3b Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 26 Sep 2017 14:27:58 -0700 Subject: [PATCH 1493/2898] Documentation: devicetree: add binding for Broadcom STB AVS TMON Add binding for Broadcom STB thermal. Signed-off-by: Brian Norris Acked-by: Rob Herring Signed-off-by: Markus Mayer Signed-off-by: Eduardo Valentin --- .../bindings/thermal/brcm,avs-tmon.txt | 20 +++++++++++++++++++ MAINTAINERS | 8 ++++++++ 2 files changed, 28 insertions(+) create mode 100644 Documentation/devicetree/bindings/thermal/brcm,avs-tmon.txt diff --git a/Documentation/devicetree/bindings/thermal/brcm,avs-tmon.txt b/Documentation/devicetree/bindings/thermal/brcm,avs-tmon.txt new file mode 100644 index 000000000000..9d43553a8d39 --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/brcm,avs-tmon.txt @@ -0,0 +1,20 @@ +* Broadcom STB thermal management + +Thermal management core, provided by the AVS TMON hardware block. + +Required properties: +- compatible: must be "brcm,avs-tmon" and/or "brcm,avs-tmon-bcm7445" +- reg: address range for the AVS TMON registers +- interrupts: temperature monitor interrupt, for high/low threshold triggers +- interrupt-names: should be "tmon" +- interrupt-parent: the parent interrupt controller + +Example: + + thermal@f04d1500 { + compatible = "brcm,avs-tmon-bcm7445", "brcm,avs-tmon"; + reg = <0xf04d1500 0x28>; + interrupts = <0x6>; + interrupt-names = "tmon"; + interrupt-parent = <&avs_host_l2_intc>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 2281af4b41b6..46c592bc402f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2955,6 +2955,14 @@ S: Maintained F: Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt F: drivers/cpufreq/brcmstb* +BROADCOM STB AVS TMON DRIVER +M: Markus Mayer +M: bcm-kernel-feedback-list@broadcom.com +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/thermal/brcm,avs-tmon.txt +F: drivers/thermal/broadcom/brcmstb* + BROADCOM STB NAND FLASH DRIVER M: Brian Norris M: Kamal Dasu -- GitLab From 9e03cf1b2dd54733d0d2c5811b78257d78562c03 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 26 Sep 2017 14:27:59 -0700 Subject: [PATCH 1494/2898] thermal: add brcmstb AVS TMON driver The AVS TMON core provides temperature readings, a pair of configurable high- and low-temperature threshold interrupts, and an emergency over-temperature chip reset. The driver utilizes the first two to provide temperature readings and high-temperature notifications to applications. The over-temperature reset is not exposed to applications; this reset threshold is critical to the system and should be set with care within the bootloader. Applications may choose to utilize the notification mechanism, the temperature reading mechanism (e.g., through polling), or both. Signed-off-by: Brian Norris Signed-off-by: Doug Berger Signed-off-by: Markus Mayer Signed-off-by: Eduardo Valentin --- drivers/thermal/Kconfig | 2 +- drivers/thermal/broadcom/Kconfig | 7 + drivers/thermal/broadcom/Makefile | 1 + drivers/thermal/broadcom/brcmstb_thermal.c | 387 +++++++++++++++++++++ 4 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 drivers/thermal/broadcom/brcmstb_thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index e3f0d1fd1720..c70f6bfd9e85 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -408,7 +408,7 @@ config MTK_THERMAL controller present in Mediatek SoCs menu "Broadcom thermal drivers" -depends on ARCH_BCM || ARCH_BCM2835 || COMPILE_TEST +depends on ARCH_BCM || ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST source "drivers/thermal/broadcom/Kconfig" endmenu diff --git a/drivers/thermal/broadcom/Kconfig b/drivers/thermal/broadcom/Kconfig index 42c098e86f84..c106a15bf7f9 100644 --- a/drivers/thermal/broadcom/Kconfig +++ b/drivers/thermal/broadcom/Kconfig @@ -6,6 +6,13 @@ config BCM2835_THERMAL help Support for thermal sensors on Broadcom bcm2835 SoCs. +config BRCMSTB_THERMAL + tristate "Broadcom STB AVS TMON thermal driver" + depends on ARCH_BRCMSTB || COMPILE_TEST + help + Enable this driver if you have a Broadcom STB SoC and would like + thermal framework support. + config BCM_NS_THERMAL tristate "Northstar thermal driver" depends on ARCH_BCM_IPROC || COMPILE_TEST diff --git a/drivers/thermal/broadcom/Makefile b/drivers/thermal/broadcom/Makefile index c6f62e4fd0ee..fae10ecafaef 100644 --- a/drivers/thermal/broadcom/Makefile +++ b/drivers/thermal/broadcom/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o +obj-$(CONFIG_BRCMSTB_THERMAL) += brcmstb_thermal.o obj-$(CONFIG_BCM_NS_THERMAL) += ns-thermal.o diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c new file mode 100644 index 000000000000..1919f91fa756 --- /dev/null +++ b/drivers/thermal/broadcom/brcmstb_thermal.c @@ -0,0 +1,387 @@ +/* + * Broadcom STB AVS TMON thermal sensor driver + * + * Copyright (c) 2015-2017 Broadcom + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define DRV_NAME "brcmstb_thermal" + +#define pr_fmt(fmt) DRV_NAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AVS_TMON_STATUS 0x00 + #define AVS_TMON_STATUS_valid_msk BIT(11) + #define AVS_TMON_STATUS_data_msk GENMASK(10, 1) + #define AVS_TMON_STATUS_data_shift 1 + +#define AVS_TMON_EN_OVERTEMP_RESET 0x04 + #define AVS_TMON_EN_OVERTEMP_RESET_msk BIT(0) + +#define AVS_TMON_RESET_THRESH 0x08 + #define AVS_TMON_RESET_THRESH_msk GENMASK(10, 1) + #define AVS_TMON_RESET_THRESH_shift 1 + +#define AVS_TMON_INT_IDLE_TIME 0x10 + +#define AVS_TMON_EN_TEMP_INT_SRCS 0x14 + #define AVS_TMON_EN_TEMP_INT_SRCS_high BIT(1) + #define AVS_TMON_EN_TEMP_INT_SRCS_low BIT(0) + +#define AVS_TMON_INT_THRESH 0x18 + #define AVS_TMON_INT_THRESH_high_msk GENMASK(26, 17) + #define AVS_TMON_INT_THRESH_high_shift 17 + #define AVS_TMON_INT_THRESH_low_msk GENMASK(10, 1) + #define AVS_TMON_INT_THRESH_low_shift 1 + +#define AVS_TMON_TEMP_INT_CODE 0x1c +#define AVS_TMON_TP_TEST_ENABLE 0x20 + +/* Default coefficients */ +#define AVS_TMON_TEMP_SLOPE -487 +#define AVS_TMON_TEMP_OFFSET 410040 + +/* HW related temperature constants */ +#define AVS_TMON_TEMP_MAX 0x3ff +#define AVS_TMON_TEMP_MIN -88161 +#define AVS_TMON_TEMP_MASK AVS_TMON_TEMP_MAX + +enum avs_tmon_trip_type { + TMON_TRIP_TYPE_LOW = 0, + TMON_TRIP_TYPE_HIGH, + TMON_TRIP_TYPE_RESET, + TMON_TRIP_TYPE_MAX, +}; + +struct avs_tmon_trip { + /* HW bit to enable the trip */ + u32 enable_offs; + u32 enable_mask; + + /* HW field to read the trip temperature */ + u32 reg_offs; + u32 reg_msk; + int reg_shift; +}; + +static struct avs_tmon_trip avs_tmon_trips[] = { + /* Trips when temperature is below threshold */ + [TMON_TRIP_TYPE_LOW] = { + .enable_offs = AVS_TMON_EN_TEMP_INT_SRCS, + .enable_mask = AVS_TMON_EN_TEMP_INT_SRCS_low, + .reg_offs = AVS_TMON_INT_THRESH, + .reg_msk = AVS_TMON_INT_THRESH_low_msk, + .reg_shift = AVS_TMON_INT_THRESH_low_shift, + }, + /* Trips when temperature is above threshold */ + [TMON_TRIP_TYPE_HIGH] = { + .enable_offs = AVS_TMON_EN_TEMP_INT_SRCS, + .enable_mask = AVS_TMON_EN_TEMP_INT_SRCS_high, + .reg_offs = AVS_TMON_INT_THRESH, + .reg_msk = AVS_TMON_INT_THRESH_high_msk, + .reg_shift = AVS_TMON_INT_THRESH_high_shift, + }, + /* Automatically resets chip when above threshold */ + [TMON_TRIP_TYPE_RESET] = { + .enable_offs = AVS_TMON_EN_OVERTEMP_RESET, + .enable_mask = AVS_TMON_EN_OVERTEMP_RESET_msk, + .reg_offs = AVS_TMON_RESET_THRESH, + .reg_msk = AVS_TMON_RESET_THRESH_msk, + .reg_shift = AVS_TMON_RESET_THRESH_shift, + }, +}; + +struct brcmstb_thermal_priv { + void __iomem *tmon_base; + struct device *dev; + struct thermal_zone_device *thermal; +}; + +static void avs_tmon_get_coeffs(struct thermal_zone_device *tz, int *slope, + int *offset) +{ + *slope = thermal_zone_get_slope(tz); + *offset = thermal_zone_get_offset(tz); +} + +/* Convert a HW code to a temperature reading (millidegree celsius) */ +static inline int avs_tmon_code_to_temp(struct thermal_zone_device *tz, + u32 code) +{ + const int val = code & AVS_TMON_TEMP_MASK; + int slope, offset; + + avs_tmon_get_coeffs(tz, &slope, &offset); + + return slope * val + offset; +} + +/* + * Convert a temperature value (millidegree celsius) to a HW code + * + * @temp: temperature to convert + * @low: if true, round toward the low side + */ +static inline u32 avs_tmon_temp_to_code(struct thermal_zone_device *tz, + int temp, bool low) +{ + int slope, offset; + + if (temp < AVS_TMON_TEMP_MIN) + return AVS_TMON_TEMP_MAX; /* Maximum code value */ + + avs_tmon_get_coeffs(tz, &slope, &offset); + + if (temp >= offset) + return 0; /* Minimum code value */ + + if (low) + return (u32)(DIV_ROUND_UP(offset - temp, abs(slope))); + else + return (u32)((offset - temp) / abs(slope)); +} + +static int brcmstb_get_temp(void *data, int *temp) +{ + struct brcmstb_thermal_priv *priv = data; + u32 val; + long t; + + val = __raw_readl(priv->tmon_base + AVS_TMON_STATUS); + + if (!(val & AVS_TMON_STATUS_valid_msk)) { + dev_err(priv->dev, "reading not valid\n"); + return -EIO; + } + + val = (val & AVS_TMON_STATUS_data_msk) >> AVS_TMON_STATUS_data_shift; + + t = avs_tmon_code_to_temp(priv->thermal, val); + if (t < 0) + *temp = 0; + else + *temp = t; + + return 0; +} + +static void avs_tmon_trip_enable(struct brcmstb_thermal_priv *priv, + enum avs_tmon_trip_type type, int en) +{ + struct avs_tmon_trip *trip = &avs_tmon_trips[type]; + u32 val = __raw_readl(priv->tmon_base + trip->enable_offs); + + dev_dbg(priv->dev, "%sable trip, type %d\n", en ? "en" : "dis", type); + + if (en) + val |= trip->enable_mask; + else + val &= ~trip->enable_mask; + + __raw_writel(val, priv->tmon_base + trip->enable_offs); +} + +static int avs_tmon_get_trip_temp(struct brcmstb_thermal_priv *priv, + enum avs_tmon_trip_type type) +{ + struct avs_tmon_trip *trip = &avs_tmon_trips[type]; + u32 val = __raw_readl(priv->tmon_base + trip->reg_offs); + + val &= trip->reg_msk; + val >>= trip->reg_shift; + + return avs_tmon_code_to_temp(priv->thermal, val); +} + +static void avs_tmon_set_trip_temp(struct brcmstb_thermal_priv *priv, + enum avs_tmon_trip_type type, + int temp) +{ + struct avs_tmon_trip *trip = &avs_tmon_trips[type]; + u32 val, orig; + + dev_dbg(priv->dev, "set temp %d to %d\n", type, temp); + + /* round toward low temp for the low interrupt */ + val = avs_tmon_temp_to_code(priv->thermal, temp, + type == TMON_TRIP_TYPE_LOW); + + val <<= trip->reg_shift; + val &= trip->reg_msk; + + orig = __raw_readl(priv->tmon_base + trip->reg_offs); + orig &= ~trip->reg_msk; + orig |= val; + __raw_writel(orig, priv->tmon_base + trip->reg_offs); +} + +static int avs_tmon_get_intr_temp(struct brcmstb_thermal_priv *priv) +{ + u32 val; + + val = __raw_readl(priv->tmon_base + AVS_TMON_TEMP_INT_CODE); + return avs_tmon_code_to_temp(priv->thermal, val); +} + +static irqreturn_t brcmstb_tmon_irq_thread(int irq, void *data) +{ + struct brcmstb_thermal_priv *priv = data; + int low, high, intr; + + low = avs_tmon_get_trip_temp(priv, TMON_TRIP_TYPE_LOW); + high = avs_tmon_get_trip_temp(priv, TMON_TRIP_TYPE_HIGH); + intr = avs_tmon_get_intr_temp(priv); + + dev_dbg(priv->dev, "low/intr/high: %d/%d/%d\n", + low, intr, high); + + /* Disable high-temp until next threshold shift */ + if (intr >= high) + avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_HIGH, 0); + /* Disable low-temp until next threshold shift */ + if (intr <= low) + avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_LOW, 0); + + /* + * Notify using the interrupt temperature, in case the temperature + * changes before it can next be read out + */ + thermal_zone_device_update(priv->thermal, intr); + + return IRQ_HANDLED; +} + +static int brcmstb_set_trips(void *data, int low, int high) +{ + struct brcmstb_thermal_priv *priv = data; + + dev_dbg(priv->dev, "set trips %d <--> %d\n", low, high); + + /* + * Disable low-temp if "low" is too small. As per thermal framework + * API, we use -INT_MAX rather than INT_MIN. + */ + if (low <= -INT_MAX) { + avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_LOW, 0); + } else { + avs_tmon_set_trip_temp(priv, TMON_TRIP_TYPE_LOW, low); + avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_LOW, 1); + } + + /* Disable high-temp if "high" is too big. */ + if (high == INT_MAX) { + avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_HIGH, 0); + } else { + avs_tmon_set_trip_temp(priv, TMON_TRIP_TYPE_HIGH, high); + avs_tmon_trip_enable(priv, TMON_TRIP_TYPE_HIGH, 1); + } + + return 0; +} + +static struct thermal_zone_of_device_ops of_ops = { + .get_temp = brcmstb_get_temp, + .set_trips = brcmstb_set_trips, +}; + +static const struct of_device_id brcmstb_thermal_id_table[] = { + { .compatible = "brcm,avs-tmon" }, + {}, +}; +MODULE_DEVICE_TABLE(of, brcmstb_thermal_id_table); + +static int brcmstb_thermal_probe(struct platform_device *pdev) +{ + struct thermal_zone_device *thermal; + struct brcmstb_thermal_priv *priv; + struct resource *res; + int irq, ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->tmon_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->tmon_base)) + return PTR_ERR(priv->tmon_base); + + priv->dev = &pdev->dev; + platform_set_drvdata(pdev, priv); + + thermal = thermal_zone_of_sensor_register(&pdev->dev, 0, priv, &of_ops); + if (IS_ERR(thermal)) { + ret = PTR_ERR(thermal); + dev_err(&pdev->dev, "could not register sensor: %d\n", ret); + return ret; + } + + priv->thermal = thermal; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "could not get IRQ\n"); + ret = irq; + goto err; + } + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + brcmstb_tmon_irq_thread, IRQF_ONESHOT, + DRV_NAME, priv); + if (ret < 0) { + dev_err(&pdev->dev, "could not request IRQ: %d\n", ret); + goto err; + } + + dev_info(&pdev->dev, "registered AVS TMON of-sensor driver\n"); + + return 0; + +err: + thermal_zone_of_sensor_unregister(&pdev->dev, thermal); + return ret; +} + +static int brcmstb_thermal_exit(struct platform_device *pdev) +{ + struct brcmstb_thermal_priv *priv = platform_get_drvdata(pdev); + struct thermal_zone_device *thermal = priv->thermal; + + if (thermal) + thermal_zone_of_sensor_unregister(&pdev->dev, priv->thermal); + + return 0; +} + +static struct platform_driver brcmstb_thermal_driver = { + .probe = brcmstb_thermal_probe, + .remove = brcmstb_thermal_exit, + .driver = { + .name = DRV_NAME, + .of_match_table = brcmstb_thermal_id_table, + }, +}; +module_platform_driver(brcmstb_thermal_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Brian Norris"); +MODULE_DESCRIPTION("Broadcom STB AVS TMON thermal driver"); -- GitLab From b2fd708ffa7f43ce8680271924e1771e26a3ec91 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Tue, 24 Oct 2017 13:20:39 +0530 Subject: [PATCH 1495/2898] thermal: cpu_cooling: pr_err() strings should end with newlines pr_err() messages should end with a new-line to avoid other messages being concatenated. Acked-by: Viresh Kumar Acked-by: Javi Merino Signed-off-by: Arvind Yadav Signed-off-by: Eduardo Valentin --- drivers/thermal/cpu_cooling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 908a8014cf76..dc63aba092e4 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -696,7 +696,7 @@ __cpufreq_cooling_register(struct device_node *np, bool first; if (IS_ERR_OR_NULL(policy)) { - pr_err("%s: cpufreq policy isn't valid: %p", __func__, policy); + pr_err("%s: cpufreq policy isn't valid: %p\n", __func__, policy); return ERR_PTR(-EINVAL); } -- GitLab From 109eba2eb61ab92fc1f92e02d69ee0aa16e10c6a Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 23 Oct 2017 12:12:52 +0100 Subject: [PATCH 1496/2898] clk: tegra: Mark APB clock as critical Currently, the APB clock is registered with the CLK_IGNORE_UNUSED flag to prevent the clock from being disabled if unused on boot. However, even if it is used, it still needs to be always kept enabled so that it doesn't get inadvertently disabled when all of its children are, and so update the flag for the APB clock to be CLK_IS_CRITICAL. Suggested-by: Peter De Schrijver Signed-off-by: Jon Hunter Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-super-gen4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 4f6fd307cb70..10047107c1dc 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c @@ -166,7 +166,7 @@ static void __init tegra_sclk_init(void __iomem *clk_base, clk_base + SYSTEM_CLK_RATE, 0, 2, 0, &sysrate_lock); clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT | - CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, + CLK_IS_CRITICAL, clk_base + SYSTEM_CLK_RATE, 3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); *dt_clk = clk; } -- GitLab From 899f8095e66c562888ff617686e46019b758611b Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 4 Oct 2017 02:02:38 +0300 Subject: [PATCH 1497/2898] clk: tegra: Add AHB DMA clock entry AHB DMA engine presents on Tegra20/30. Add missing clock entries, so that driver for the AHB DMA controller could be implemented. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-id.h | 1 + drivers/clk/tegra/clk-tegra-periph.c | 1 + drivers/clk/tegra/clk-tegra20.c | 1 + drivers/clk/tegra/clk-tegra30.c | 1 + 4 files changed, 4 insertions(+) diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 689f344377a7..c1661b47bbda 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -12,6 +12,7 @@ enum clk_id { tegra_clk_amx, tegra_clk_amx1, tegra_clk_apb2ape, + tegra_clk_ahbdma, tegra_clk_apbdma, tegra_clk_apbif, tegra_clk_ape, diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index c7694205573f..f5232d6d203d 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -807,6 +807,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("timer", "clk_m", 5, 0, tegra_clk_timer, CLK_IS_CRITICAL), GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0), GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0), + GATE("ahbdma", "hclk", 33, 0, tegra_clk_ahbdma, 0), GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0), GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0), GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0), diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 2b839cb24436..02b7ab292e97 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -522,6 +522,7 @@ static struct tegra_devclk devclks[] __initdata = { }; static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = { + [tegra_clk_ahbdma] = { .dt_id = TEGRA20_CLK_AHBDMA, .present = true }, [tegra_clk_spdif_out] = { .dt_id = TEGRA20_CLK_SPDIF_OUT, .present = true }, [tegra_clk_spdif_in] = { .dt_id = TEGRA20_CLK_SPDIF_IN, .present = true }, [tegra_clk_sdmmc1] = { .dt_id = TEGRA20_CLK_SDMMC1, .present = true }, diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 455502a42b20..40ffab0f94e1 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -788,6 +788,7 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = { [tegra_clk_extern3] = { .dt_id = TEGRA30_CLK_EXTERN3, .present = true }, [tegra_clk_disp1] = { .dt_id = TEGRA30_CLK_DISP1, .present = true }, [tegra_clk_disp2] = { .dt_id = TEGRA30_CLK_DISP2, .present = true }, + [tegra_clk_ahbdma] = { .dt_id = TEGRA30_CLK_AHBDMA, .present = true }, [tegra_clk_apbdma] = { .dt_id = TEGRA30_CLK_APBDMA, .present = true }, [tegra_clk_rtc] = { .dt_id = TEGRA30_CLK_RTC, .present = true }, [tegra_clk_timer] = { .dt_id = TEGRA30_CLK_TIMER, .present = true }, -- GitLab From 3ff46fd0b22abbb8d921d7e5657912bfbd41b6f0 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 4 Oct 2017 02:02:39 +0300 Subject: [PATCH 1498/2898] clk: tegra: Correct parent of the APBDMA clock APBDMA represents a clock gate to the APB DMA controller, the actual clock source for the controller is PCLK. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index f5232d6d203d..c02711927d79 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -808,7 +808,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0), GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0), GATE("ahbdma", "hclk", 33, 0, tegra_clk_ahbdma, 0), - GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0), + GATE("apbdma", "pclk", 34, 0, tegra_clk_apbdma, 0), GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0), GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0), GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0), -- GitLab From 5a6b184a36b8f5ff01ce93c9251996e4f96310d7 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 4 Oct 2017 02:02:40 +0300 Subject: [PATCH 1499/2898] clk: tegra: Use common definition of APBDMA clock gate The APBDMA clock is defined in the common clock gates table that is used by Tegra30+. Tegra20 can use it too, let's remove the custom definition and use the common one. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra20.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 02b7ab292e97..57a1387ea992 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -523,6 +523,7 @@ static struct tegra_devclk devclks[] __initdata = { static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = { [tegra_clk_ahbdma] = { .dt_id = TEGRA20_CLK_AHBDMA, .present = true }, + [tegra_clk_apbdma] = { .dt_id = TEGRA20_CLK_APBDMA, .present = true }, [tegra_clk_spdif_out] = { .dt_id = TEGRA20_CLK_SPDIF_OUT, .present = true }, [tegra_clk_spdif_in] = { .dt_id = TEGRA20_CLK_SPDIF_IN, .present = true }, [tegra_clk_sdmmc1] = { .dt_id = TEGRA20_CLK_SDMMC1, .present = true }, @@ -807,11 +808,6 @@ static void __init tegra20_periph_clk_init(void) clk_base, 0, 3, periph_clk_enb_refcnt); clks[TEGRA20_CLK_AC97] = clk; - /* apbdma */ - clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base, - 0, 34, periph_clk_enb_refcnt); - clks[TEGRA20_CLK_APBDMA] = clk; - /* emc */ clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, ARRAY_SIZE(mux_pllmcp_clkm), -- GitLab From d80a32fe98b7ce428669b774c3d10ecae3bc6e6d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 4 Oct 2017 02:02:41 +0300 Subject: [PATCH 1500/2898] clk: tegra: Bump SCLK clock rate to 216 MHz AHB DMA is a running on 1/2 of SCLK rate, APB DMA on 1/4. Increasing SCLK rate results in an increased DMA transfer rate. Signed-off-by: Dmitry Osipenko Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra20.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 57a1387ea992..cbd5a2e5c569 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1020,7 +1020,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 }, { TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 }, { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1 }, - { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1 }, + { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 216000000, 1 }, { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1 }, { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1 }, -- GitLab From 54eff2264d3e9fd7e3987de1d7eba1d3581c631e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Tue, 19 Sep 2017 04:48:10 +0200 Subject: [PATCH 1501/2898] clk: tegra: Fix cclk_lp divisor register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to comments in code and common sense, cclk_lp uses its own divisor, not cclk_g's. Fixes: b08e8c0ecc42 ("clk: tegra: add clock support for Tegra30") Signed-off-by: Michał Mirosław Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 40ffab0f94e1..bee84c554932 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -965,7 +965,7 @@ static void __init tegra30_super_clk_init(void) * U71 divider of cclk_lp. */ clk = tegra_clk_register_divider("pll_p_out3_cclklp", "pll_p_out3", - clk_base + SUPER_CCLKG_DIVIDER, 0, + clk_base + SUPER_CCLKLP_DIVIDER, 0, TEGRA_DIVIDER_INT, 16, 8, 1, NULL); clk_register_clkdev(clk, "pll_p_out3_cclklp", NULL); -- GitLab From 1752c9ee23fb20e5bfdbedf677e91f927f2b8d80 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 12 Oct 2017 16:09:59 -0700 Subject: [PATCH 1502/2898] clk: tegra: dfll: Fix drvdata overwriting issue Both tegra124-dfll and clk-dfll are using platform_set_drvdata to set drvdata of the exact same pdev while they use different pointers for the drvdata. Once the drvdata has been overwritten by tegra124-dfll, clk-dfll will never get its td pointer as it expects. Since tegra124-dfll merely needs its soc pointer in its remove function, this patch fixes the bug by removing the overwriting in the tegra124-dfll file and letting the tegra_dfll_unregister return an soc pointer for it. Signed-off-by: Nicolin Chen Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-dfll.c | 10 +++++----- drivers/clk/tegra/clk-dfll.h | 2 +- drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 12 +++++------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 2c44aeb0b97c..0a7deee74eea 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c @@ -1728,10 +1728,10 @@ EXPORT_SYMBOL(tegra_dfll_register); * @pdev: DFLL platform_device * * * Unbind this driver from the DFLL hardware device represented by - * @pdev. The DFLL must be disabled for this to succeed. Returns 0 - * upon success or -EBUSY if the DFLL is still active. + * @pdev. The DFLL must be disabled for this to succeed. Returns a + * soc pointer upon success or -EBUSY if the DFLL is still active. */ -int tegra_dfll_unregister(struct platform_device *pdev) +struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev) { struct tegra_dfll *td = platform_get_drvdata(pdev); @@ -1739,7 +1739,7 @@ int tegra_dfll_unregister(struct platform_device *pdev) if (td->mode != DFLL_DISABLED) { dev_err(&pdev->dev, "must disable DFLL before removing driver\n"); - return -EBUSY; + return ERR_PTR(-EBUSY); } debugfs_remove_recursive(td->debugfs_dir); @@ -1753,6 +1753,6 @@ int tegra_dfll_unregister(struct platform_device *pdev) reset_control_assert(td->dvco_rst); - return 0; + return td->soc; } EXPORT_SYMBOL(tegra_dfll_unregister); diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h index ed2ad888268f..83352c8078f2 100644 --- a/drivers/clk/tegra/clk-dfll.h +++ b/drivers/clk/tegra/clk-dfll.h @@ -43,7 +43,7 @@ struct tegra_dfll_soc_data { int tegra_dfll_register(struct platform_device *pdev, struct tegra_dfll_soc_data *soc); -int tegra_dfll_unregister(struct platform_device *pdev); +struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev); int tegra_dfll_runtime_suspend(struct device *dev); int tegra_dfll_runtime_resume(struct device *dev); diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index ad1c1cc829cb..269d3595758b 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -125,19 +125,17 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) return err; } - platform_set_drvdata(pdev, soc); - return 0; } static int tegra124_dfll_fcpu_remove(struct platform_device *pdev) { - struct tegra_dfll_soc_data *soc = platform_get_drvdata(pdev); - int err; + struct tegra_dfll_soc_data *soc; - err = tegra_dfll_unregister(pdev); - if (err < 0) - dev_err(&pdev->dev, "failed to unregister DFLL: %d\n", err); + soc = tegra_dfll_unregister(pdev); + if (IS_ERR(soc)) + dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n", + PTR_ERR(soc)); tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); -- GitLab From 22ef01a203d27fee8b7694020b7e722db7efd2a7 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Fri, 15 Sep 2017 12:10:13 -0700 Subject: [PATCH 1503/2898] clk: tegra: Use readl_relaxed_poll_timeout_atomic() in tegra210_clock_init() Below is the call trace of tegra210_init_pllu() function: start_kernel() -> time_init() --> of_clk_init() ---> tegra210_clock_init() ----> tegra210_pll_init() -----> tegra210_init_pllu() Because the preemption is disabled in the start_kernel before calling time_init, tegra210_init_pllu is actually in an atomic context while it includes a readl_relaxed_poll_timeout that might sleep. So this patch just changes this readl_relaxed_poll_timeout() to its atomic version. Signed-off-by: Nicolin Chen Acked-By: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index be7b736371f6..9e6260869eb9 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -2568,8 +2568,8 @@ static int tegra210_enable_pllu(void) reg |= PLL_ENABLE; writel(reg, clk_base + PLLU_BASE); - readl_relaxed_poll_timeout(clk_base + PLLU_BASE, reg, - reg & PLL_BASE_LOCK, 2, 1000); + readl_relaxed_poll_timeout_atomic(clk_base + PLLU_BASE, reg, + reg & PLL_BASE_LOCK, 2, 1000); if (!(reg & PLL_BASE_LOCK)) { pr_err("Timed out waiting for PLL_U to lock\n"); return -ETIMEDOUT; -- GitLab From d2a3671ebe6479483a12f94fcca63c058d95ad64 Mon Sep 17 00:00:00 2001 From: Leo Yan Date: Fri, 1 Sep 2017 08:47:14 +0800 Subject: [PATCH 1504/2898] clk: hi6220: mark clock cs_atb_syspll as critical Clock cs_atb_syspll is pll used for coresight trace bus; when clock cs_atb_syspll is disabled and operates its child clock node cs_atb results in system hang. So mark clock cs_atb_syspll as critical to keep it enabled. Cc: Guodong Xu Cc: Zhangfei Gao Cc: Haojian Zhuang Signed-off-by: Leo Yan Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1504226835-2115-2-git-send-email-leo.yan@linaro.org --- drivers/clk/hisilicon/clk-hi6220.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c index e786d717f75d..a87809d4bd52 100644 --- a/drivers/clk/hisilicon/clk-hi6220.c +++ b/drivers/clk/hisilicon/clk-hi6220.c @@ -145,7 +145,7 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = { { HI6220_BBPPLL_SEL, "bbppll_sel", "pll0_bbp_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9, 0, }, { HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, }, { HI6220_MMC2_SEL, "mmc2_sel", "mmc2_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, }, - { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, }, + { HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IS_CRITICAL, 0x270, 12, 0, }, }; static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = { -- GitLab From 02e0114ae1eb776b22f0744762fb0137208c4850 Mon Sep 17 00:00:00 2001 From: Corentin LABBE Date: Tue, 24 Oct 2017 19:06:16 +0200 Subject: [PATCH 1505/2898] clk: sunxi: fix build warning This patch fix the following build warning: drivers/clk/sunxi/clk-factors.c:279:14: warning: variable 'name' set but not used [-Wunused-but-set-variable] Fixes: 4cbeaebb8af1 ("clk: sunxi: factors: Add unregister function") Acked-by: Maxime Ripard Signed-off-by: Corentin Labbe Signed-off-by: Stephen Boyd --- drivers/clk/sunxi/clk-factors.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index dfe5e3e32d28..856fef65433b 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -276,13 +276,11 @@ void sunxi_factors_unregister(struct device_node *node, struct clk *clk) { struct clk_hw *hw = __clk_get_hw(clk); struct clk_factors *factors; - const char *name; if (!hw) return; factors = to_clk_factors(hw); - name = clk_hw_get_name(hw); of_clk_del_provider(node); /* TODO: The composite clock stuff will leak a bit here. */ -- GitLab From cb92a19b9977706ac69e26c67dcccb69ae6deeb0 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 19 Jul 2017 17:25:13 +0200 Subject: [PATCH 1506/2898] clk: sunxi: explicitly request exclusive reset control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit a53e35db70d1 ("reset: Ensure drivers are explicit when requesting reset lines") started to transition the reset control request API calls to explicitly state whether the driver needs exclusive or shared reset control behavior. Convert all drivers requesting exclusive resets to the explicit API call so the temporary transition helpers can be removed. No functional changes. Cc: "Emilio López" Cc: Michael Turquette Cc: Stephen Boyd Cc: Maxime Ripard Cc: Chen-Yu Tsai Cc: linux-clk@vger.kernel.org Signed-off-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/clk/sunxi/clk-sun9i-mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c index 6041bdba2e97..a1a634253d6f 100644 --- a/drivers/clk/sunxi/clk-sun9i-mmc.c +++ b/drivers/clk/sunxi/clk-sun9i-mmc.c @@ -124,7 +124,7 @@ static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev) return PTR_ERR(data->clk); } - data->reset = devm_reset_control_get(&pdev->dev, NULL); + data->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(data->reset)) { dev_err(&pdev->dev, "Could not get reset control\n"); return PTR_ERR(data->reset); -- GitLab From 71bf5ab8638fe333ac8a984b46fc3f4ea0c5120a Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 17 Oct 2017 16:38:33 +0200 Subject: [PATCH 1507/2898] CLK: SPEAr: make structure field and function argument as const Make the masks field of clk_aux structure const as it do not modify the fields of the aux_clk_masks structure it points to. Make the struct aux_clk_masks *aux argument of the function clk_register_aux as const as the argument is only stored in the masks field of a clk_aux structure which is now made const. Signed-off-by: Bhumika Goyal Acked-by: Viresh Kumar Signed-off-by: Stephen Boyd --- drivers/clk/spear/clk-aux-synth.c | 2 +- drivers/clk/spear/clk.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index f271c350ef94..8bea5dfc770b 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -136,7 +136,7 @@ static struct clk_ops clk_aux_ops = { struct clk *clk_register_aux(const char *aux_name, const char *gate_name, const char *parent_name, unsigned long flags, void __iomem *reg, - struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, + const struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk) { struct clk_aux *aux; diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h index 9834944f08b1..af0e25f496c1 100644 --- a/drivers/clk/spear/clk.h +++ b/drivers/clk/spear/clk.h @@ -49,7 +49,7 @@ struct aux_rate_tbl { struct clk_aux { struct clk_hw hw; void __iomem *reg; - struct aux_clk_masks *masks; + const struct aux_clk_masks *masks; struct aux_rate_tbl *rtbl; u8 rtbl_cnt; spinlock_t *lock; @@ -112,7 +112,7 @@ typedef unsigned long (*clk_calc_rate)(struct clk_hw *hw, unsigned long prate, /* clk register routines */ struct clk *clk_register_aux(const char *aux_name, const char *gate_name, const char *parent_name, unsigned long flags, void __iomem *reg, - struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, + const struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk); struct clk *clk_register_frac(const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, -- GitLab From 37d2f45d940bfdd7c9a5323f3d3462bea3a3e957 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 17 Oct 2017 16:38:34 +0200 Subject: [PATCH 1508/2898] CLK: SPEAr: make aux_clk_masks structures const Make these const as they are either stored in the masks 'const' field of a clk_aux structure or passed to the function clk_register_aux having the argument as const. Signed-off-by: Bhumika Goyal Acked-by: Viresh Kumar Signed-off-by: Stephen Boyd --- drivers/clk/spear/clk-aux-synth.c | 2 +- drivers/clk/spear/spear1310_clock.c | 2 +- drivers/clk/spear/spear1340_clock.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index 8bea5dfc770b..2f145e398a10 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -29,7 +29,7 @@ #define to_clk_aux(_hw) container_of(_hw, struct clk_aux, hw) -static struct aux_clk_masks default_aux_masks = { +static const struct aux_clk_masks default_aux_masks = { .eq_sel_mask = AUX_EQ_SEL_MASK, .eq_sel_shift = AUX_EQ_SEL_SHIFT, .eq1_mask = AUX_EQ1_SEL, diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c index 2f86e3f94efa..591248c9a88e 100644 --- a/drivers/clk/spear/spear1310_clock.c +++ b/drivers/clk/spear/spear1310_clock.c @@ -284,7 +284,7 @@ static struct frac_rate_tbl clcd_rtbl[] = { }; /* i2s prescaler1 masks */ -static struct aux_clk_masks i2s_prs1_masks = { +static const struct aux_clk_masks i2s_prs1_masks = { .eq_sel_mask = AUX_EQ_SEL_MASK, .eq_sel_shift = SPEAR1310_I2S_PRS1_EQ_SEL_SHIFT, .eq1_mask = AUX_EQ1_SEL, diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index cbb19a90f2d6..e5bc8c828cf0 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c @@ -323,7 +323,7 @@ static struct frac_rate_tbl clcd_rtbl[] = { }; /* i2s prescaler1 masks */ -static struct aux_clk_masks i2s_prs1_masks = { +static const struct aux_clk_masks i2s_prs1_masks = { .eq_sel_mask = AUX_EQ_SEL_MASK, .eq_sel_shift = SPEAR1340_I2S_PRS1_EQ_SEL_SHIFT, .eq1_mask = AUX_EQ1_SEL, -- GitLab From ba3892df525b9ff203d0ad116a41306bf5081215 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 18:44:50 +0530 Subject: [PATCH 1509/2898] clk: spear: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Acked-by: Viresh Kumar Signed-off-by: Stephen Boyd --- drivers/clk/spear/clk-aux-synth.c | 2 +- drivers/clk/spear/clk-frac-synth.c | 2 +- drivers/clk/spear/clk-gpt-synth.c | 2 +- drivers/clk/spear/clk-vco-pll.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index 2f145e398a10..23a6b10e1d6a 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -128,7 +128,7 @@ static int clk_aux_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_aux_ops = { +static const struct clk_ops clk_aux_ops = { .recalc_rate = clk_aux_recalc_rate, .round_rate = clk_aux_round_rate, .set_rate = clk_aux_set_rate, diff --git a/drivers/clk/spear/clk-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c index 58d678b5b40a..eaf970bda5d9 100644 --- a/drivers/clk/spear/clk-frac-synth.c +++ b/drivers/clk/spear/clk-frac-synth.c @@ -116,7 +116,7 @@ static int clk_frac_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_frac_ops = { +static const struct clk_ops clk_frac_ops = { .recalc_rate = clk_frac_recalc_rate, .round_rate = clk_frac_round_rate, .set_rate = clk_frac_set_rate, diff --git a/drivers/clk/spear/clk-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c index 1a722e99e76e..3641799d4f6f 100644 --- a/drivers/clk/spear/clk-gpt-synth.c +++ b/drivers/clk/spear/clk-gpt-synth.c @@ -105,7 +105,7 @@ static int clk_gpt_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_gpt_ops = { +static const struct clk_ops clk_gpt_ops = { .recalc_rate = clk_gpt_recalc_rate, .round_rate = clk_gpt_round_rate, .set_rate = clk_gpt_set_rate, diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c index dc21ca4601aa..069b48a44f80 100644 --- a/drivers/clk/spear/clk-vco-pll.c +++ b/drivers/clk/spear/clk-vco-pll.c @@ -165,7 +165,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_pll_ops = { +static const struct clk_ops clk_pll_ops = { .recalc_rate = clk_pll_recalc_rate, .round_rate = clk_pll_round_rate, .set_rate = clk_pll_set_rate, @@ -266,7 +266,7 @@ static int clk_vco_set_rate(struct clk_hw *hw, unsigned long drate, return 0; } -static struct clk_ops clk_vco_ops = { +static const struct clk_ops clk_vco_ops = { .recalc_rate = clk_vco_recalc_rate, .round_rate = clk_vco_round_rate, .set_rate = clk_vco_set_rate, -- GitLab From 8f435057e9c5eca9da7c02ab398971280ba80056 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 19:32:21 +0530 Subject: [PATCH 1510/2898] clk: sirf: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/sirf/clk-common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c index 77e1e2491689..f9ef6fa84f0b 100644 --- a/drivers/clk/sirf/clk-common.c +++ b/drivers/clk/sirf/clk-common.c @@ -184,7 +184,7 @@ static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw, return clk_hw_get_rate(parent_clk); } -static struct clk_ops std_pll_ops = { +static const struct clk_ops std_pll_ops = { .recalc_rate = pll_clk_recalc_rate, .round_rate = pll_clk_round_rate, .set_rate = pll_clk_set_rate, @@ -265,7 +265,7 @@ static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long pa return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ; } -static struct clk_ops usb_pll_ops = { +static const struct clk_ops usb_pll_ops = { .enable = usb_pll_clk_enable, .disable = usb_pll_clk_disable, .recalc_rate = usb_pll_clk_recalc_rate, @@ -437,7 +437,7 @@ static int cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate, return ret2 ? ret2 : ret1; } -static struct clk_ops msi_ops = { +static const struct clk_ops msi_ops = { .set_rate = dmn_clk_set_rate, .round_rate = dmn_clk_round_rate, .recalc_rate = dmn_clk_recalc_rate, @@ -488,7 +488,7 @@ static struct clk_dmn clk_io = { }, }; -static struct clk_ops cpu_ops = { +static const struct clk_ops cpu_ops = { .set_parent = dmn_clk_set_parent, .get_parent = dmn_clk_get_parent, .set_rate = cpu_clk_set_rate, @@ -511,7 +511,7 @@ static struct clk_dmn clk_cpu = { }, }; -static struct clk_ops dmn_ops = { +static const struct clk_ops dmn_ops = { .is_enabled = std_clk_is_enabled, .enable = std_clk_enable, .disable = std_clk_disable, @@ -679,7 +679,7 @@ static const char * const std_clk_io_parents[] = { "io", }; -static struct clk_ops ios_ops = { +static const struct clk_ops ios_ops = { .is_enabled = std_clk_is_enabled, .enable = std_clk_enable, .disable = std_clk_disable, -- GitLab From ed3f2d12213b3d13ca0b941199c250c66a318b72 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 19:22:47 +0530 Subject: [PATCH 1511/2898] clk: mxs: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/mxs/clk-div.c | 2 +- drivers/clk/mxs/clk-frac.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c index f75e989c578f..ccebd014fc1e 100644 --- a/drivers/clk/mxs/clk-div.c +++ b/drivers/clk/mxs/clk-div.c @@ -67,7 +67,7 @@ static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate, return ret; } -static struct clk_ops clk_div_ops = { +static const struct clk_ops clk_div_ops = { .recalc_rate = clk_div_recalc_rate, .round_rate = clk_div_round_rate, .set_rate = clk_div_set_rate, diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c index f8dd10f6df3d..27b3372adc37 100644 --- a/drivers/clk/mxs/clk-frac.c +++ b/drivers/clk/mxs/clk-frac.c @@ -107,7 +107,7 @@ static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate, return mxs_clk_wait(frac->reg, frac->busy); } -static struct clk_ops clk_frac_ops = { +static const struct clk_ops clk_frac_ops = { .recalc_rate = clk_frac_recalc_rate, .round_rate = clk_frac_round_rate, .set_rate = clk_frac_set_rate, -- GitLab From 9108620d2d52d7a58bbf6192e56903355eace907 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 19:12:07 +0530 Subject: [PATCH 1512/2898] clk: hisilicon: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk-hi3620.c | 2 +- drivers/clk/hisilicon/clk-hix5hd2.c | 4 ++-- drivers/clk/hisilicon/clkgate-separated.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c index fa0fba653898..77072c7778b9 100644 --- a/drivers/clk/hisilicon/clk-hi3620.c +++ b/drivers/clk/hisilicon/clk-hi3620.c @@ -415,7 +415,7 @@ static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate, return mmc_clk_set_timing(hw, rate); } -static struct clk_ops clk_mmc_ops = { +static const struct clk_ops clk_mmc_ops = { .prepare = mmc_clk_prepare, .determine_rate = mmc_clk_determine_rate, .set_rate = mmc_clk_set_rate, diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c index 14b05efa3c2a..9584f0c32dda 100644 --- a/drivers/clk/hisilicon/clk-hix5hd2.c +++ b/drivers/clk/hisilicon/clk-hix5hd2.c @@ -208,7 +208,7 @@ static void clk_ether_unprepare(struct clk_hw *hw) writel_relaxed(val, clk->ctrl_reg); } -static struct clk_ops clk_ether_ops = { +static const struct clk_ops clk_ether_ops = { .prepare = clk_ether_prepare, .unprepare = clk_ether_unprepare, }; @@ -247,7 +247,7 @@ static void clk_complex_disable(struct clk_hw *hw) writel_relaxed(val, clk->phy_reg); } -static struct clk_ops clk_complex_ops = { +static const struct clk_ops clk_complex_ops = { .enable = clk_complex_enable, .disable = clk_complex_disable, }; diff --git a/drivers/clk/hisilicon/clkgate-separated.c b/drivers/clk/hisilicon/clkgate-separated.c index 7908bc3c9ec7..1172b0982b77 100644 --- a/drivers/clk/hisilicon/clkgate-separated.c +++ b/drivers/clk/hisilicon/clkgate-separated.c @@ -88,7 +88,7 @@ static int clkgate_separated_is_enabled(struct clk_hw *hw) return reg ? 1 : 0; } -static struct clk_ops clkgate_separated_ops = { +static const struct clk_ops clkgate_separated_ops = { .enable = clkgate_separated_enable, .disable = clkgate_separated_disable, .is_enabled = clkgate_separated_is_enabled, -- GitLab From e90a7da4f75435ba0e5fcb12ed65fa6d4bd7a364 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 19:05:55 +0530 Subject: [PATCH 1513/2898] clk: mmp: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/mmp/clk-apbc.c | 2 +- drivers/clk/mmp/clk-apmu.c | 2 +- drivers/clk/mmp/clk-frac.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/mmp/clk-apbc.c b/drivers/clk/mmp/clk-apbc.c index 4c717db05f2d..fb294ada0b03 100644 --- a/drivers/clk/mmp/clk-apbc.c +++ b/drivers/clk/mmp/clk-apbc.c @@ -114,7 +114,7 @@ static void clk_apbc_unprepare(struct clk_hw *hw) spin_unlock_irqrestore(apbc->lock, flags); } -static struct clk_ops clk_apbc_ops = { +static const struct clk_ops clk_apbc_ops = { .prepare = clk_apbc_prepare, .unprepare = clk_apbc_unprepare, }; diff --git a/drivers/clk/mmp/clk-apmu.c b/drivers/clk/mmp/clk-apmu.c index 47b5542ce50f..b7ce8f52026e 100644 --- a/drivers/clk/mmp/clk-apmu.c +++ b/drivers/clk/mmp/clk-apmu.c @@ -60,7 +60,7 @@ static void clk_apmu_disable(struct clk_hw *hw) spin_unlock_irqrestore(apmu->lock, flags); } -static struct clk_ops clk_apmu_ops = { +static const struct clk_ops clk_apmu_ops = { .enable = clk_apmu_enable, .disable = clk_apmu_disable, }; diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c index 584a9927993b..ea47a968ad9b 100644 --- a/drivers/clk/mmp/clk-frac.c +++ b/drivers/clk/mmp/clk-frac.c @@ -149,7 +149,7 @@ static void clk_factor_init(struct clk_hw *hw) spin_unlock_irqrestore(factor->lock, flags); } -static struct clk_ops clk_factor_ops = { +static const struct clk_ops clk_factor_ops = { .recalc_rate = clk_factor_recalc_rate, .round_rate = clk_factor_round_rate, .set_rate = clk_factor_set_rate, -- GitLab From fa1da981f5ee603610bd8f8920c4ec393e95ceeb Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 22 Aug 2017 18:48:29 +0530 Subject: [PATCH 1514/2898] clk: imx: make clk_ops const Make these const as they are only stored in the const field of a clk_init_data structure. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-busy.c | 4 ++-- drivers/clk/imx/clk-gate2.c | 2 +- drivers/clk/imx/clk-pllv1.c | 2 +- drivers/clk/imx/clk-pllv2.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c index 5cc99590f9a3..6df3389687bc 100644 --- a/drivers/clk/imx/clk-busy.c +++ b/drivers/clk/imx/clk-busy.c @@ -72,7 +72,7 @@ static int clk_busy_divider_set_rate(struct clk_hw *hw, unsigned long rate, return ret; } -static struct clk_ops clk_busy_divider_ops = { +static const struct clk_ops clk_busy_divider_ops = { .recalc_rate = clk_busy_divider_recalc_rate, .round_rate = clk_busy_divider_round_rate, .set_rate = clk_busy_divider_set_rate, @@ -147,7 +147,7 @@ static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index) return ret; } -static struct clk_ops clk_busy_mux_ops = { +static const struct clk_ops clk_busy_mux_ops = { .get_parent = clk_busy_mux_get_parent, .set_parent = clk_busy_mux_set_parent, }; diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index db44a198a0d9..60fc9d7a9723 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -118,7 +118,7 @@ static void clk_gate2_disable_unused(struct clk_hw *hw) spin_unlock_irqrestore(gate->lock, flags); } -static struct clk_ops clk_gate2_ops = { +static const struct clk_ops clk_gate2_ops = { .enable = clk_gate2_enable, .disable = clk_gate2_disable, .disable_unused = clk_gate2_disable_unused, diff --git a/drivers/clk/imx/clk-pllv1.c b/drivers/clk/imx/clk-pllv1.c index 82fe3662b5f6..703818e9001a 100644 --- a/drivers/clk/imx/clk-pllv1.c +++ b/drivers/clk/imx/clk-pllv1.c @@ -106,7 +106,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw, return ull; } -static struct clk_ops clk_pllv1_ops = { +static const struct clk_ops clk_pllv1_ops = { .recalc_rate = clk_pllv1_recalc_rate, }; diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c index 4aeda56ce372..c845b8c773a6 100644 --- a/drivers/clk/imx/clk-pllv2.c +++ b/drivers/clk/imx/clk-pllv2.c @@ -226,7 +226,7 @@ static void clk_pllv2_unprepare(struct clk_hw *hw) __raw_writel(reg, pllbase + MXC_PLL_DP_CTL); } -static struct clk_ops clk_pllv2_ops = { +static const struct clk_ops clk_pllv2_ops = { .prepare = clk_pllv2_prepare, .unprepare = clk_pllv2_unprepare, .recalc_rate = clk_pllv2_recalc_rate, -- GitLab From 0777066dcee8a4f16db09fd21dfd58b6d83b12f9 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 18 Aug 2017 15:38:17 +0530 Subject: [PATCH 1515/2898] clk: make clk_init_data const Make these const as they are only stored in the init field of a clk_hw structure, which is const. Signed-off-by: Bhumika Goyal Signed-off-by: Stephen Boyd --- drivers/clk/clk-twl6040.c | 2 +- drivers/clk/clk-wm831x.c | 6 +-- drivers/clk/sirf/clk-atlas6.c | 2 +- drivers/clk/sirf/clk-atlas7.c | 18 ++++---- drivers/clk/sirf/clk-common.c | 80 +++++++++++++++++------------------ drivers/clk/sirf/clk-prima2.c | 2 +- 6 files changed, 55 insertions(+), 55 deletions(-) diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c index 7b222a5db931..25dfe050ae9f 100644 --- a/drivers/clk/clk-twl6040.c +++ b/drivers/clk/clk-twl6040.c @@ -82,7 +82,7 @@ static const struct clk_ops twl6040_pdmclk_ops = { .recalc_rate = twl6040_pdmclk_recalc_rate, }; -static struct clk_init_data twl6040_pdmclk_init = { +static const struct clk_init_data twl6040_pdmclk_init = { .name = "pdmclk", .ops = &twl6040_pdmclk_ops, .flags = CLK_GET_RATE_NOCACHE, diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index a47960aacfa5..146769532325 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -52,7 +52,7 @@ static const struct clk_ops wm831x_xtal_ops = { .recalc_rate = wm831x_xtal_recalc_rate, }; -static struct clk_init_data wm831x_xtal_init = { +static const struct clk_init_data wm831x_xtal_init = { .name = "xtal", .ops = &wm831x_xtal_ops, }; @@ -225,7 +225,7 @@ static const struct clk_ops wm831x_fll_ops = { .get_parent = wm831x_fll_get_parent, }; -static struct clk_init_data wm831x_fll_init = { +static const struct clk_init_data wm831x_fll_init = { .name = "fll", .ops = &wm831x_fll_ops, .parent_names = wm831x_fll_parents, @@ -338,7 +338,7 @@ static const struct clk_ops wm831x_clkout_ops = { .set_parent = wm831x_clkout_set_parent, }; -static struct clk_init_data wm831x_clkout_init = { +static const struct clk_init_data wm831x_clkout_init = { .name = "clkout", .ops = &wm831x_clkout_ops, .parent_names = wm831x_clkout_parents, diff --git a/drivers/clk/sirf/clk-atlas6.c b/drivers/clk/sirf/clk-atlas6.c index 665fa681b2e1..0cd11e6893af 100644 --- a/drivers/clk/sirf/clk-atlas6.c +++ b/drivers/clk/sirf/clk-atlas6.c @@ -42,7 +42,7 @@ static struct clk_dmn clk_mmc45 = { }, }; -static struct clk_init_data clk_nand_init = { +static const struct clk_init_data clk_nand_init = { .name = "nand", .ops = &dmn_ops, .parent_names = dmn_clk_parents, diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c index d0c6c9a2d06a..be012b4bab46 100644 --- a/drivers/clk/sirf/clk-atlas7.c +++ b/drivers/clk/sirf/clk-atlas7.c @@ -392,7 +392,7 @@ static const char * const pll_clk_parents[] = { "xin", }; -static struct clk_init_data clk_cpupll_init = { +static const struct clk_init_data clk_cpupll_init = { .name = "cpupll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -406,7 +406,7 @@ static struct clk_pll clk_cpupll = { }, }; -static struct clk_init_data clk_mempll_init = { +static const struct clk_init_data clk_mempll_init = { .name = "mempll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -420,7 +420,7 @@ static struct clk_pll clk_mempll = { }, }; -static struct clk_init_data clk_sys0pll_init = { +static const struct clk_init_data clk_sys0pll_init = { .name = "sys0pll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -434,7 +434,7 @@ static struct clk_pll clk_sys0pll = { }, }; -static struct clk_init_data clk_sys1pll_init = { +static const struct clk_init_data clk_sys1pll_init = { .name = "sys1pll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -448,7 +448,7 @@ static struct clk_pll clk_sys1pll = { }, }; -static struct clk_init_data clk_sys2pll_init = { +static const struct clk_init_data clk_sys2pll_init = { .name = "sys2pll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -462,7 +462,7 @@ static struct clk_pll clk_sys2pll = { }, }; -static struct clk_init_data clk_sys3pll_init = { +static const struct clk_init_data clk_sys3pll_init = { .name = "sys3pll_vco", .ops = &ab_pll_ops, .parent_names = pll_clk_parents, @@ -596,7 +596,7 @@ static const char * const audiodto_clk_parents[] = { "sys3pll_clk1", }; -static struct clk_init_data clk_audiodto_init = { +static const struct clk_init_data clk_audiodto_init = { .name = "audio_dto", .ops = &dto_ops, .parent_names = audiodto_clk_parents, @@ -617,7 +617,7 @@ static const char * const disp0dto_clk_parents[] = { "sys3pll_clk1", }; -static struct clk_init_data clk_disp0dto_init = { +static const struct clk_init_data clk_disp0dto_init = { .name = "disp0_dto", .ops = &dto_ops, .parent_names = disp0dto_clk_parents, @@ -638,7 +638,7 @@ static const char * const disp1dto_clk_parents[] = { "sys3pll_clk1", }; -static struct clk_init_data clk_disp1dto_init = { +static const struct clk_init_data clk_disp1dto_init = { .name = "disp1_dto", .ops = &dto_ops, .parent_names = disp1dto_clk_parents, diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c index f9ef6fa84f0b..d8f9efa5129a 100644 --- a/drivers/clk/sirf/clk-common.c +++ b/drivers/clk/sirf/clk-common.c @@ -194,21 +194,21 @@ static const char * const pll_clk_parents[] = { "osc", }; -static struct clk_init_data clk_pll1_init = { +static const struct clk_init_data clk_pll1_init = { .name = "pll1", .ops = &std_pll_ops, .parent_names = pll_clk_parents, .num_parents = ARRAY_SIZE(pll_clk_parents), }; -static struct clk_init_data clk_pll2_init = { +static const struct clk_init_data clk_pll2_init = { .name = "pll2", .ops = &std_pll_ops, .parent_names = pll_clk_parents, .num_parents = ARRAY_SIZE(pll_clk_parents), }; -static struct clk_init_data clk_pll3_init = { +static const struct clk_init_data clk_pll3_init = { .name = "pll3", .ops = &std_pll_ops, .parent_names = pll_clk_parents, @@ -271,7 +271,7 @@ static const struct clk_ops usb_pll_ops = { .recalc_rate = usb_pll_clk_recalc_rate, }; -static struct clk_init_data clk_usb_pll_init = { +static const struct clk_init_data clk_usb_pll_init = { .name = "usb_pll", .ops = &usb_pll_ops, .parent_names = pll_clk_parents, @@ -445,7 +445,7 @@ static const struct clk_ops msi_ops = { .get_parent = dmn_clk_get_parent, }; -static struct clk_init_data clk_mem_init = { +static const struct clk_init_data clk_mem_init = { .name = "mem", .ops = &msi_ops, .parent_names = dmn_clk_parents, @@ -459,7 +459,7 @@ static struct clk_dmn clk_mem = { }, }; -static struct clk_init_data clk_sys_init = { +static const struct clk_init_data clk_sys_init = { .name = "sys", .ops = &msi_ops, .parent_names = dmn_clk_parents, @@ -474,7 +474,7 @@ static struct clk_dmn clk_sys = { }, }; -static struct clk_init_data clk_io_init = { +static const struct clk_init_data clk_io_init = { .name = "io", .ops = &msi_ops, .parent_names = dmn_clk_parents, @@ -496,7 +496,7 @@ static const struct clk_ops cpu_ops = { .recalc_rate = cpu_clk_recalc_rate, }; -static struct clk_init_data clk_cpu_init = { +static const struct clk_init_data clk_cpu_init = { .name = "cpu", .ops = &cpu_ops, .parent_names = dmn_clk_parents, @@ -524,7 +524,7 @@ static const struct clk_ops dmn_ops = { /* dsp, gfx, mm, lcd and vpp domain */ -static struct clk_init_data clk_dsp_init = { +static const struct clk_init_data clk_dsp_init = { .name = "dsp", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -539,7 +539,7 @@ static struct clk_dmn clk_dsp = { }, }; -static struct clk_init_data clk_gfx_init = { +static const struct clk_init_data clk_gfx_init = { .name = "gfx", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -554,7 +554,7 @@ static struct clk_dmn clk_gfx = { }, }; -static struct clk_init_data clk_mm_init = { +static const struct clk_init_data clk_mm_init = { .name = "mm", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -574,7 +574,7 @@ static struct clk_dmn clk_mm = { */ #define clk_gfx2d clk_mm -static struct clk_init_data clk_lcd_init = { +static const struct clk_init_data clk_lcd_init = { .name = "lcd", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -589,7 +589,7 @@ static struct clk_dmn clk_lcd = { }, }; -static struct clk_init_data clk_vpp_init = { +static const struct clk_init_data clk_vpp_init = { .name = "vpp", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -604,21 +604,21 @@ static struct clk_dmn clk_vpp = { }, }; -static struct clk_init_data clk_mmc01_init = { +static const struct clk_init_data clk_mmc01_init = { .name = "mmc01", .ops = &dmn_ops, .parent_names = dmn_clk_parents, .num_parents = ARRAY_SIZE(dmn_clk_parents), }; -static struct clk_init_data clk_mmc23_init = { +static const struct clk_init_data clk_mmc23_init = { .name = "mmc23", .ops = &dmn_ops, .parent_names = dmn_clk_parents, .num_parents = ARRAY_SIZE(dmn_clk_parents), }; -static struct clk_init_data clk_mmc45_init = { +static const struct clk_init_data clk_mmc45_init = { .name = "mmc45", .ops = &dmn_ops, .parent_names = dmn_clk_parents, @@ -685,7 +685,7 @@ static const struct clk_ops ios_ops = { .disable = std_clk_disable, }; -static struct clk_init_data clk_cphif_init = { +static const struct clk_init_data clk_cphif_init = { .name = "cphif", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -699,7 +699,7 @@ static struct clk_std clk_cphif = { }, }; -static struct clk_init_data clk_dmac0_init = { +static const struct clk_init_data clk_dmac0_init = { .name = "dmac0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -713,7 +713,7 @@ static struct clk_std clk_dmac0 = { }, }; -static struct clk_init_data clk_dmac1_init = { +static const struct clk_init_data clk_dmac1_init = { .name = "dmac1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -727,7 +727,7 @@ static struct clk_std clk_dmac1 = { }, }; -static struct clk_init_data clk_audio_init = { +static const struct clk_init_data clk_audio_init = { .name = "audio", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -741,7 +741,7 @@ static struct clk_std clk_audio = { }, }; -static struct clk_init_data clk_uart0_init = { +static const struct clk_init_data clk_uart0_init = { .name = "uart0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -755,7 +755,7 @@ static struct clk_std clk_uart0 = { }, }; -static struct clk_init_data clk_uart1_init = { +static const struct clk_init_data clk_uart1_init = { .name = "uart1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -769,7 +769,7 @@ static struct clk_std clk_uart1 = { }, }; -static struct clk_init_data clk_uart2_init = { +static const struct clk_init_data clk_uart2_init = { .name = "uart2", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -783,7 +783,7 @@ static struct clk_std clk_uart2 = { }, }; -static struct clk_init_data clk_usp0_init = { +static const struct clk_init_data clk_usp0_init = { .name = "usp0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -797,7 +797,7 @@ static struct clk_std clk_usp0 = { }, }; -static struct clk_init_data clk_usp1_init = { +static const struct clk_init_data clk_usp1_init = { .name = "usp1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -811,7 +811,7 @@ static struct clk_std clk_usp1 = { }, }; -static struct clk_init_data clk_usp2_init = { +static const struct clk_init_data clk_usp2_init = { .name = "usp2", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -825,7 +825,7 @@ static struct clk_std clk_usp2 = { }, }; -static struct clk_init_data clk_vip_init = { +static const struct clk_init_data clk_vip_init = { .name = "vip", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -839,7 +839,7 @@ static struct clk_std clk_vip = { }, }; -static struct clk_init_data clk_spi0_init = { +static const struct clk_init_data clk_spi0_init = { .name = "spi0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -853,7 +853,7 @@ static struct clk_std clk_spi0 = { }, }; -static struct clk_init_data clk_spi1_init = { +static const struct clk_init_data clk_spi1_init = { .name = "spi1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -867,7 +867,7 @@ static struct clk_std clk_spi1 = { }, }; -static struct clk_init_data clk_tsc_init = { +static const struct clk_init_data clk_tsc_init = { .name = "tsc", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -881,7 +881,7 @@ static struct clk_std clk_tsc = { }, }; -static struct clk_init_data clk_i2c0_init = { +static const struct clk_init_data clk_i2c0_init = { .name = "i2c0", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -895,7 +895,7 @@ static struct clk_std clk_i2c0 = { }, }; -static struct clk_init_data clk_i2c1_init = { +static const struct clk_init_data clk_i2c1_init = { .name = "i2c1", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -909,7 +909,7 @@ static struct clk_std clk_i2c1 = { }, }; -static struct clk_init_data clk_pwmc_init = { +static const struct clk_init_data clk_pwmc_init = { .name = "pwmc", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -923,7 +923,7 @@ static struct clk_std clk_pwmc = { }, }; -static struct clk_init_data clk_efuse_init = { +static const struct clk_init_data clk_efuse_init = { .name = "efuse", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -937,7 +937,7 @@ static struct clk_std clk_efuse = { }, }; -static struct clk_init_data clk_pulse_init = { +static const struct clk_init_data clk_pulse_init = { .name = "pulse", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -955,7 +955,7 @@ static const char * const std_clk_dsp_parents[] = { "dsp", }; -static struct clk_init_data clk_gps_init = { +static const struct clk_init_data clk_gps_init = { .name = "gps", .ops = &ios_ops, .parent_names = std_clk_dsp_parents, @@ -969,7 +969,7 @@ static struct clk_std clk_gps = { }, }; -static struct clk_init_data clk_mf_init = { +static const struct clk_init_data clk_mf_init = { .name = "mf", .ops = &ios_ops, .parent_names = std_clk_io_parents, @@ -987,7 +987,7 @@ static const char * const std_clk_sys_parents[] = { "sys", }; -static struct clk_init_data clk_security_init = { +static const struct clk_init_data clk_security_init = { .name = "security", .ops = &ios_ops, .parent_names = std_clk_sys_parents, @@ -1005,7 +1005,7 @@ static const char * const std_clk_usb_parents[] = { "usb_pll", }; -static struct clk_init_data clk_usb0_init = { +static const struct clk_init_data clk_usb0_init = { .name = "usb0", .ops = &ios_ops, .parent_names = std_clk_usb_parents, @@ -1019,7 +1019,7 @@ static struct clk_std clk_usb0 = { }, }; -static struct clk_init_data clk_usb1_init = { +static const struct clk_init_data clk_usb1_init = { .name = "usb1", .ops = &ios_ops, .parent_names = std_clk_usb_parents, diff --git a/drivers/clk/sirf/clk-prima2.c b/drivers/clk/sirf/clk-prima2.c index aac1c8ec151a..2f824320c318 100644 --- a/drivers/clk/sirf/clk-prima2.c +++ b/drivers/clk/sirf/clk-prima2.c @@ -42,7 +42,7 @@ static struct clk_dmn clk_mmc45 = { }, }; -static struct clk_init_data clk_nand_init = { +static const struct clk_init_data clk_nand_init = { .name = "nand", .ops = &ios_ops, .parent_names = std_clk_io_parents, -- GitLab From aa795c41d9cd41dc9c915dd1956ddd0e4ae44485 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 1 Sep 2017 16:16:40 -0700 Subject: [PATCH 1516/2898] clk: Add devm_of_clk_add_hw_provider()/del_provider() APIs Sometimes we only have one of_clk_del_provider() call in driver error and remove paths, because we're missing a devm_of_clk_add_hw_provider() API. Introduce the API so we can convert drivers to use this and potentially reduce the amount of code needed to remove providers in drivers. Signed-off-by: Stephen Boyd --- Documentation/driver-model/devres.txt | 1 + drivers/clk/clk.c | 52 +++++++++++++++++++++++++++ include/linux/clk-provider.h | 13 +++++++ 3 files changed, 66 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 69f08c0f23a8..c180045eb43b 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -237,6 +237,7 @@ CLOCK devm_clk_get() devm_clk_put() devm_clk_hw_register() + devm_of_clk_add_hw_provider() DMA dmam_alloc_coherent() diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c8d83acda006..856d4858ae27 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3177,6 +3177,37 @@ int of_clk_add_hw_provider(struct device_node *np, } EXPORT_SYMBOL_GPL(of_clk_add_hw_provider); +static void devm_of_clk_release_provider(struct device *dev, void *res) +{ + of_clk_del_provider(*(struct device_node **)res); +} + +int devm_of_clk_add_hw_provider(struct device *dev, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data) +{ + struct device_node **ptr, *np; + int ret; + + ptr = devres_alloc(devm_of_clk_release_provider, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + np = dev->of_node; + ret = of_clk_add_hw_provider(np, get, data); + if (!ret) { + *ptr = np; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_of_clk_add_hw_provider); + /** * of_clk_del_provider() - Remove a previously registered clock provider * @np: Device node pointer associated with clock provider @@ -3198,6 +3229,27 @@ void of_clk_del_provider(struct device_node *np) } EXPORT_SYMBOL_GPL(of_clk_del_provider); +static int devm_clk_provider_match(struct device *dev, void *res, void *data) +{ + struct device_node **np = res; + + if (WARN_ON(!np || !*np)) + return 0; + + return *np == data; +} + +void devm_of_clk_del_provider(struct device *dev) +{ + int ret; + + ret = devres_release(dev, devm_of_clk_release_provider, + devm_clk_provider_match, dev->of_node); + + WARN_ON(ret); +} +EXPORT_SYMBOL(devm_of_clk_del_provider); + static struct clk_hw * __of_clk_get_hw_from_provider(struct of_clk_provider *provider, struct of_phandle_args *clkspec) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 5100ec1b5d55..ba79d6186133 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -815,7 +815,12 @@ int of_clk_add_hw_provider(struct device_node *np, struct clk_hw *(*get)(struct of_phandle_args *clkspec, void *data), void *data); +int devm_of_clk_add_hw_provider(struct device *dev, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data); void of_clk_del_provider(struct device_node *np); +void devm_of_clk_del_provider(struct device *dev); struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data); struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, @@ -847,7 +852,15 @@ static inline int of_clk_add_hw_provider(struct device_node *np, { return 0; } +static inline int devm_of_clk_add_hw_provider(struct device *dev, + struct clk_hw *(*get)(struct of_phandle_args *clkspec, + void *data), + void *data) +{ + return 0; +} static inline void of_clk_del_provider(struct device_node *np) {} +static inline void devm_of_clk_del_provider(struct device *dev) {} static inline struct clk *of_clk_src_simple_get( struct of_phandle_args *clkspec, void *data) { -- GitLab From b87206f8addc52b07e0aba30f8c8ee1a5093cfa9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 1 Sep 2017 16:16:41 -0700 Subject: [PATCH 1517/2898] clk: qcom: common: Migrate to devm_* APIs for resets and clk providers Now that we have devm APIs for the reset controller and of clk hw provider APIs we can remove the custom code here. Signed-off-by: Stephen Boyd --- drivers/clk/qcom/common.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index d523991c945f..b35564c0493f 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -111,16 +111,6 @@ qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count) } EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode); -static void qcom_cc_del_clk_provider(void *data) -{ - of_clk_del_provider(data); -} - -static void qcom_cc_reset_unregister(void *data) -{ - reset_controller_unregister(data); -} - static void qcom_cc_gdsc_unregister(void *data) { gdsc_unregister(data); @@ -248,13 +238,7 @@ int qcom_cc_really_probe(struct platform_device *pdev, return ret; } - ret = of_clk_add_hw_provider(dev->of_node, qcom_cc_clk_hw_get, cc); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, qcom_cc_del_clk_provider, - pdev->dev.of_node); - + ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc); if (ret) return ret; @@ -266,13 +250,7 @@ int qcom_cc_really_probe(struct platform_device *pdev, reset->regmap = regmap; reset->reset_map = desc->resets; - ret = reset_controller_register(&reset->rcdev); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, qcom_cc_reset_unregister, - &reset->rcdev); - + ret = devm_reset_controller_register(dev, &reset->rcdev); if (ret) return ret; -- GitLab From 92041a9ff003858f117009501c14f2d075dd68ce Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 6 Sep 2017 11:51:59 +0200 Subject: [PATCH 1518/2898] clk: at91: utmi: set the mainck rate By default, it is assumed that the UTMI clock is generated from a 12 MHz reference clock (MAINCK). If it's not the case, the FREQ field of the SFR_UTMICKTRIM has to be updated to generate the UTMI clock in the proper way. The UTMI clock has a fixed rate of 480 MHz. In fact, there is no multiplier we can configure. The multiplier is managed internally, depending on the reference clock frequency, to achieve the target of 480 MHz. Signed-off-by: Ludovic Desroches Acked-by: Ingo van Lil Signed-off-by: Stephen Boyd --- drivers/clk/at91/clk-utmi.c | 95 ++++++++++++++++++++++++++++++------ include/soc/at91/atmel-sfr.h | 2 + 2 files changed, 83 insertions(+), 14 deletions(-) diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index aadabd9d1e2b..cd8d689138ff 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -14,14 +14,20 @@ #include #include #include +#include #include "pmc.h" -#define UTMI_FIXED_MUL 40 +/* + * The purpose of this clock is to generate a 480 MHz signal. A different + * rate can't be configured. + */ +#define UTMI_RATE 480000000 struct clk_utmi { struct clk_hw hw; - struct regmap *regmap; + struct regmap *regmap_pmc; + struct regmap *regmap_sfr; }; #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw) @@ -37,13 +43,54 @@ static inline bool clk_utmi_ready(struct regmap *regmap) static int clk_utmi_prepare(struct clk_hw *hw) { + struct clk_hw *hw_parent; struct clk_utmi *utmi = to_clk_utmi(hw); unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; + unsigned int utmi_ref_clk_freq; + unsigned long parent_rate; + + /* + * If mainck rate is different from 12 MHz, we have to configure the + * FREQ field of the SFR_UTMICKTRIM register to generate properly + * the utmi clock. + */ + hw_parent = clk_hw_get_parent(hw); + parent_rate = clk_hw_get_rate(hw_parent); + + switch (parent_rate) { + case 12000000: + utmi_ref_clk_freq = 0; + break; + case 16000000: + utmi_ref_clk_freq = 1; + break; + case 24000000: + utmi_ref_clk_freq = 2; + break; + /* + * Not supported on SAMA5D2 but it's not an issue since MAINCK + * maximum value is 24 MHz. + */ + case 48000000: + utmi_ref_clk_freq = 3; + break; + default: + pr_err("UTMICK: unsupported mainck rate\n"); + return -EINVAL; + } - regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr); + if (utmi->regmap_sfr) { + regmap_update_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM, + AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq); + } else if (utmi_ref_clk_freq) { + pr_err("UTMICK: sfr node required\n"); + return -EINVAL; + } - while (!clk_utmi_ready(utmi->regmap)) + regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr); + + while (!clk_utmi_ready(utmi->regmap_pmc)) cpu_relax(); return 0; @@ -53,21 +100,22 @@ static int clk_utmi_is_prepared(struct clk_hw *hw) { struct clk_utmi *utmi = to_clk_utmi(hw); - return clk_utmi_ready(utmi->regmap); + return clk_utmi_ready(utmi->regmap_pmc); } static void clk_utmi_unprepare(struct clk_hw *hw) { struct clk_utmi *utmi = to_clk_utmi(hw); - regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0); + regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, + AT91_PMC_UPLLEN, 0); } static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - /* UTMI clk is a fixed clk multiplier */ - return parent_rate * UTMI_FIXED_MUL; + /* UTMI clk rate is fixed. */ + return UTMI_RATE; } static const struct clk_ops utmi_ops = { @@ -78,7 +126,7 @@ static const struct clk_ops utmi_ops = { }; static struct clk_hw * __init -at91_clk_register_utmi(struct regmap *regmap, +at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, const char *name, const char *parent_name) { struct clk_utmi *utmi; @@ -97,7 +145,8 @@ at91_clk_register_utmi(struct regmap *regmap, init.flags = CLK_SET_RATE_GATE; utmi->hw.init = &init; - utmi->regmap = regmap; + utmi->regmap_pmc = regmap_pmc; + utmi->regmap_sfr = regmap_sfr; hw = &utmi->hw; ret = clk_hw_register(NULL, &utmi->hw); @@ -114,17 +163,35 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) struct clk_hw *hw; const char *parent_name; const char *name = np->name; - struct regmap *regmap; + struct regmap *regmap_pmc, *regmap_sfr; parent_name = of_clk_get_parent_name(np, 0); of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); - if (IS_ERR(regmap)) + regmap_pmc = syscon_node_to_regmap(of_get_parent(np)); + if (IS_ERR(regmap_pmc)) return; - hw = at91_clk_register_utmi(regmap, name, parent_name); + /* + * If the device supports different mainck rates, this value has to be + * set in the UTMI Clock Trimming register. + * - 9x5: mainck supports several rates but it is indicated that a + * 12 MHz is needed in case of USB. + * - sama5d3 and sama5d2: mainck supports several rates. Configuring + * the FREQ field of the UTMI Clock Trimming register is mandatory. + * - sama5d4: mainck is at 12 MHz. + * + * We only need to retrieve sama5d3 or sama5d2 sfr regmap. + */ + regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr"); + if (IS_ERR(regmap_sfr)) { + regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr"); + if (IS_ERR(regmap_sfr)) + regmap_sfr = NULL; + } + + hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name); if (IS_ERR(hw)) return; diff --git a/include/soc/at91/atmel-sfr.h b/include/soc/at91/atmel-sfr.h index 506ea8ffda19..482337af06b8 100644 --- a/include/soc/at91/atmel-sfr.h +++ b/include/soc/at91/atmel-sfr.h @@ -17,6 +17,7 @@ /* 0x08 ~ 0x0c: Reserved */ #define AT91_SFR_OHCIICR 0x10 /* OHCI INT Configuration Register */ #define AT91_SFR_OHCIISR 0x14 /* OHCI INT Status Register */ +#define AT91_SFR_UTMICKTRIM 0x30 /* UTMI Clock Trimming Register */ #define AT91_SFR_I2SCLKSEL 0x90 /* I2SC Register */ /* Field definitions */ @@ -28,5 +29,6 @@ AT91_OHCIICR_SUSPEND_B | \ AT91_OHCIICR_SUSPEND_C) +#define AT91_UTMICKTRIM_FREQ GENMASK(1, 0) #endif /* _LINUX_MFD_SYSCON_ATMEL_SFR_H */ -- GitLab From a49580ec9af037b932d04f48ae83fc4a3bd9b0a4 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Thu, 24 Aug 2017 20:36:44 +0300 Subject: [PATCH 1519/2898] clk: qcom: Remove unused RCG ops The RCGs ops for shared branches are not used now, so remove it. Signed-off-by: Georgi Djakov Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rcg.h | 3 -- drivers/clk/qcom/clk-rcg2.c | 79 ------------------------------------- 2 files changed, 82 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index 1b3e8d265bdb..a2495457e564 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -156,7 +156,6 @@ extern const struct clk_ops clk_dyn_rcg_ops; * @hid_width: number of bits in half integer divider * @parent_map: map from software's parent index to hardware's src_sel field * @freq_tbl: frequency table - * @current_freq: last cached frequency when using branches with shared RCGs * @clkr: regmap clock handle * */ @@ -166,7 +165,6 @@ struct clk_rcg2 { u8 hid_width; const struct parent_map *parent_map; const struct freq_tbl *freq_tbl; - unsigned long current_freq; struct clk_regmap clkr; }; @@ -174,7 +172,6 @@ struct clk_rcg2 { extern const struct clk_ops clk_rcg2_ops; extern const struct clk_ops clk_rcg2_floor_ops; -extern const struct clk_ops clk_rcg2_shared_ops; extern const struct clk_ops clk_edp_pixel_ops; extern const struct clk_ops clk_byte_ops; extern const struct clk_ops clk_byte2_ops; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 1a0985ae20d2..bbeaf9c09dbb 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -358,85 +358,6 @@ const struct clk_ops clk_rcg2_floor_ops = { }; EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); -static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - const char *name = clk_hw_get_name(hw); - int ret, count; - - /* force enable RCG */ - ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, - CMD_ROOT_EN, CMD_ROOT_EN); - if (ret) - return ret; - - /* wait for RCG to turn ON */ - for (count = 500; count > 0; count--) { - ret = clk_rcg2_is_enabled(hw); - if (ret) - break; - udelay(1); - } - if (!count) - pr_err("%s: RCG did not turn on\n", name); - - /* set clock rate */ - ret = __clk_rcg2_set_rate(hw, rate, CEIL); - if (ret) - return ret; - - /* clear force enable RCG */ - return regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, - CMD_ROOT_EN, 0); -} - -static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - - /* cache the rate */ - rcg->current_freq = rate; - - if (!__clk_is_enabled(hw->clk)) - return 0; - - return clk_rcg2_shared_force_enable(hw, rcg->current_freq); -} - -static unsigned long -clk_rcg2_shared_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - - return rcg->current_freq = clk_rcg2_recalc_rate(hw, parent_rate); -} - -static int clk_rcg2_shared_enable(struct clk_hw *hw) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - - return clk_rcg2_shared_force_enable(hw, rcg->current_freq); -} - -static void clk_rcg2_shared_disable(struct clk_hw *hw) -{ - struct clk_rcg2 *rcg = to_clk_rcg2(hw); - - /* switch to XO, which is the lowest entry in the freq table */ - clk_rcg2_shared_set_rate(hw, rcg->freq_tbl[0].freq, 0); -} - -const struct clk_ops clk_rcg2_shared_ops = { - .enable = clk_rcg2_shared_enable, - .disable = clk_rcg2_shared_disable, - .get_parent = clk_rcg2_get_parent, - .recalc_rate = clk_rcg2_shared_recalc_rate, - .determine_rate = clk_rcg2_determine_rate, - .set_rate = clk_rcg2_shared_set_rate, -}; -EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops); - struct frac_entry { int num; int den; -- GitLab From 5e70ca8753c8d9749d206a4fdb14f22a6ba1d893 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Oct 2017 13:26:35 +0200 Subject: [PATCH 1520/2898] clk: qcom: Elaborate on "active" clocks in the RPM clock bindings The concept of "active" clocks is just explained in a bried comment in the device driver, let's explain it a bit more in the device tree bindings so everyone understands this. Cc: devicetree@vger.kernel.org Acked-by: Rob Herring Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,rpmcc.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index a7235e9e1c97..32c6e9ce64c3 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -16,6 +16,14 @@ Required properties : - #clock-cells : shall contain 1 +The clock enumerators are defined in +and come in pairs: FOO_CLK followed by FOO_A_CLK. The latter clock +is an "active" clock, which means that the consumer only care that the +clock is available when the apps CPU subsystem is active, i.e. not +suspended or in deep idle. If it is important that the clock keeps running +during system suspend, you need to specify the non-active clock, the one +not containing *_A_* in the enumerator name. + Example: smd { compatible = "qcom,smd"; -- GitLab From 856e6bb91e198c4fb0ca2f4f3ee0e7f660b3e0ca Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Oct 2017 13:59:16 +0200 Subject: [PATCH 1521/2898] clk: qcom: Update DT bindings for the MSM8660/APQ8060 RPMCC These compatible strings need to be added to extend support for the RPM CC to cover MSM8660/APQ8060. We also need to add enumberators to the include file for a few clocks that were missing. Cc: devicetree@vger.kernel.org Acked-by: Rob Herring Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,rpmcc.txt | 2 ++ include/dt-bindings/clock/qcom,rpmcc.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index 32c6e9ce64c3..833a89f06ae0 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -10,6 +10,8 @@ Required properties : - compatible : shall contain only one of the following. The generic compatible "qcom,rpmcc" should be also included. + "qcom,rpmcc-msm8660", "qcom,rpmcc" + "qcom,rpmcc-apq8060", "qcom,rpmcc" "qcom,rpmcc-msm8916", "qcom,rpmcc" "qcom,rpmcc-msm8974", "qcom,rpmcc" "qcom,rpmcc-apq8064", "qcom,rpmcc" diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index 96b63c00249e..29dad206a74b 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -37,6 +37,9 @@ #define RPM_SYS_FABRIC_A_CLK 19 #define RPM_SFPB_CLK 20 #define RPM_SFPB_A_CLK 21 +#define RPM_SMI_CLK 22 +#define RPM_SMI_A_CLK 23 +#define RPM_PLL4_CLK 24 /* SMD RPM clocks */ #define RPM_SMD_XO_CLK_SRC 0 -- GitLab From d4a69583dee775826c02fa64e20fbf6ab193a3fc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Oct 2017 13:59:17 +0200 Subject: [PATCH 1522/2898] clk: qcom: Implement RPM clocks for MSM8660/APQ8060 The RPM clocks were missing for MSM8660/APQ8060. For this to be completed we need to add a special fixed rate RPM clock that is used for the PLL4 on these SoCs. The rest of the clocks are pretty similar to the other supported platforms. The "active" clock pattern is mirrored in all the clocks. I guess that the PLL4 that clocks the LPASS is actually never used as "active only" since the low-power audio subsystem should be left on when the CPU goes to idle, so that it can be used as a stand-alone MP3 player type of device. The PLL4 seems to be enabled only on behalf of the booting LPASS Hexagon - which will cast its own vote once its booted - and as such we only configure the active state (meaning both states will have same configuration). The result is that PLL4 will be on from prepare() to unprepare() regardless of what the application CPU does. Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpm.c | 93 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c index df3e5fe8442a..c60f61b10c7f 100644 --- a/drivers/clk/qcom/clk-rpm.c +++ b/drivers/clk/qcom/clk-rpm.c @@ -56,6 +56,18 @@ }, \ } +#define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \ + static struct clk_rpm _platform##_##_name = { \ + .rpm_clk_id = (r_id), \ + .rate = (r), \ + .hw.init = &(struct clk_init_data){ \ + .ops = &clk_rpm_fixed_ops, \ + .name = #_name, \ + .parent_names = (const char *[]){ "pxo" }, \ + .num_parents = 1, \ + }, \ + } + #define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r) \ static struct clk_rpm _platform##_##_active; \ static struct clk_rpm _platform##_##_name = { \ @@ -143,6 +155,13 @@ static int clk_rpm_handoff(struct clk_rpm *r) int ret; u32 value = INT_MAX; + /* + * The vendor tree simply reads the status for this + * RPM clock. + */ + if (r->rpm_clk_id == QCOM_RPM_PLL_4) + return 0; + ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, r->rpm_clk_id, &value, 1); if (ret) @@ -269,6 +288,32 @@ static void clk_rpm_unprepare(struct clk_hw *hw) mutex_unlock(&rpm_clk_lock); } +static int clk_rpm_fixed_prepare(struct clk_hw *hw) +{ + struct clk_rpm *r = to_clk_rpm(hw); + u32 value = 1; + int ret; + + ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, + r->rpm_clk_id, &value, 1); + if (!ret) + r->enabled = true; + + return ret; +} + +static void clk_rpm_fixed_unprepare(struct clk_hw *hw) +{ + struct clk_rpm *r = to_clk_rpm(hw); + u32 value = 0; + int ret; + + ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE, + r->rpm_clk_id, &value, 1); + if (!ret) + r->enabled = false; +} + static int clk_rpm_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -333,6 +378,13 @@ static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw, return r->rate; } +static const struct clk_ops clk_rpm_fixed_ops = { + .prepare = clk_rpm_fixed_prepare, + .unprepare = clk_rpm_fixed_unprepare, + .round_rate = clk_rpm_round_rate, + .recalc_rate = clk_rpm_recalc_rate, +}; + static const struct clk_ops clk_rpm_ops = { .prepare = clk_rpm_prepare, .unprepare = clk_rpm_unprepare, @@ -348,6 +400,45 @@ static const struct clk_ops clk_rpm_branch_ops = { .recalc_rate = clk_rpm_recalc_rate, }; +/* MSM8660/APQ8060 */ +DEFINE_CLK_RPM(msm8660, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK); +DEFINE_CLK_RPM(msm8660, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK); +DEFINE_CLK_RPM(msm8660, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK); +DEFINE_CLK_RPM(msm8660, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK); +DEFINE_CLK_RPM(msm8660, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK); +DEFINE_CLK_RPM(msm8660, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK); +DEFINE_CLK_RPM(msm8660, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK); +DEFINE_CLK_RPM(msm8660, smi_clk, smi_a_clk, QCOM_RPM_SMI_CLK); +DEFINE_CLK_RPM(msm8660, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK); +DEFINE_CLK_RPM_FIXED(msm8660, pll4_clk, pll4_a_clk, QCOM_RPM_PLL_4, 540672000); + +static struct clk_rpm *msm8660_clks[] = { + [RPM_APPS_FABRIC_CLK] = &msm8660_afab_clk, + [RPM_APPS_FABRIC_A_CLK] = &msm8660_afab_a_clk, + [RPM_SYS_FABRIC_CLK] = &msm8660_sfab_clk, + [RPM_SYS_FABRIC_A_CLK] = &msm8660_sfab_a_clk, + [RPM_MM_FABRIC_CLK] = &msm8660_mmfab_clk, + [RPM_MM_FABRIC_A_CLK] = &msm8660_mmfab_a_clk, + [RPM_DAYTONA_FABRIC_CLK] = &msm8660_daytona_clk, + [RPM_DAYTONA_FABRIC_A_CLK] = &msm8660_daytona_a_clk, + [RPM_SFPB_CLK] = &msm8660_sfpb_clk, + [RPM_SFPB_A_CLK] = &msm8660_sfpb_a_clk, + [RPM_CFPB_CLK] = &msm8660_cfpb_clk, + [RPM_CFPB_A_CLK] = &msm8660_cfpb_a_clk, + [RPM_MMFPB_CLK] = &msm8660_mmfpb_clk, + [RPM_MMFPB_A_CLK] = &msm8660_mmfpb_a_clk, + [RPM_SMI_CLK] = &msm8660_smi_clk, + [RPM_SMI_A_CLK] = &msm8660_smi_a_clk, + [RPM_EBI1_CLK] = &msm8660_ebi1_clk, + [RPM_EBI1_A_CLK] = &msm8660_ebi1_a_clk, + [RPM_PLL4_CLK] = &msm8660_pll4_clk, +}; + +static const struct rpm_clk_desc rpm_clk_msm8660 = { + .clks = msm8660_clks, + .num_clks = ARRAY_SIZE(msm8660_clks), +}; + /* apq8064 */ DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK); DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK); @@ -386,6 +477,8 @@ static const struct rpm_clk_desc rpm_clk_apq8064 = { }; static const struct of_device_id rpm_clk_match_table[] = { + { .compatible = "qcom,rpmcc-msm8660", .data = &rpm_clk_msm8660 }, + { .compatible = "qcom,rpmcc-apq8060", .data = &rpm_clk_msm8660 }, { .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 }, { } }; -- GitLab From 7066fdd0d7427f1ba455d186e75213c442c9663b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 10 Oct 2017 14:27:13 +0530 Subject: [PATCH 1523/2898] clk: qcom: clk-smd-rpm: add msm8996 rpmclks Add all RPM controlled clocks on msm8996 platform [srini: Fixed various issues with offsets and made names specific to msm8996] Signed-off-by: Srinivas Kandagatla Signed-off-by: Rajendra Nayak Acked-by: Rob Herring Acked-by: Bjorn Andersson Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,rpmcc.txt | 1 + drivers/clk/qcom/clk-smd-rpm.c | 82 +++++++++++++++++++ include/dt-bindings/clock/qcom,rpmcc.h | 14 ++++ include/linux/soc/qcom/smd-rpm.h | 4 + 4 files changed, 101 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index 833a89f06ae0..4491d1c104aa 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -15,6 +15,7 @@ Required properties : "qcom,rpmcc-msm8916", "qcom,rpmcc" "qcom,rpmcc-msm8974", "qcom,rpmcc" "qcom,rpmcc-apq8064", "qcom,rpmcc" + "qcom,rpmcc-msm8996", "qcom,rpmcc" - #clock-cells : shall contain 1 diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index cc03d5508627..c26d9007bfc4 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -530,9 +530,91 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { .clks = msm8974_clks, .num_clks = ARRAY_SIZE(msm8974_clks), }; + +/* msm8996 */ +DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); +DEFINE_CLK_SMD_RPM(msm8996, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); +DEFINE_CLK_SMD_RPM(msm8996, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8996, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk, + QCOM_SMD_RPM_MMAXI_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8996, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8996, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); +DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre1_noc_clk, aggre1_noc_a_clk, + QCOM_SMD_RPM_AGGR_CLK, 1, 1000); +DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre2_noc_clk, aggre2_noc_a_clk, + QCOM_SMD_RPM_AGGR_CLK, 2, 1000); +DEFINE_CLK_SMD_RPM_QDSS(msm8996, qdss_clk, qdss_a_clk, + QCOM_SMD_RPM_MISC_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk1, bb_clk1_a, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk2, bb_clk2_a, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk1, rf_clk1_a, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk2, rf_clk2_a, 5); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, ln_bb_clk, ln_bb_a_clk, 8); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk1, div_clk1_a, 0xb); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk2, div_clk2_a, 0xc); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk3, div_clk3_a, 0xd); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk1_pin, bb_clk1_a_pin, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk2_pin, bb_clk2_a_pin, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk1_pin, rf_clk1_a_pin, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk2_pin, rf_clk2_a_pin, 5); + +static struct clk_smd_rpm *msm8996_clks[] = { + [RPM_SMD_PCNOC_CLK] = &msm8996_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8996_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8996_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8996_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8996_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8996_cnoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8996_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8996_bimc_a_clk, + [RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, + [RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk, + [RPM_SMD_IPA_CLK] = &msm8996_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8996_ipa_a_clk, + [RPM_SMD_CE1_CLK] = &msm8996_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8996_ce1_a_clk, + [RPM_SMD_AGGR1_NOC_CLK] = &msm8996_aggre1_noc_clk, + [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8996_aggre1_noc_a_clk, + [RPM_SMD_AGGR2_NOC_CLK] = &msm8996_aggre2_noc_clk, + [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8996_aggre2_noc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8996_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8996_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8996_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8996_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8996_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8996_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &msm8996_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8996_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8996_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8996_rf_clk2_a, + [RPM_SMD_LN_BB_CLK] = &msm8996_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8996_ln_bb_a_clk, + [RPM_SMD_DIV_CLK1] = &msm8996_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8996_div_clk1_a, + [RPM_SMD_DIV_CLK2] = &msm8996_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8996_div_clk2_a, + [RPM_SMD_DIV_CLK3] = &msm8996_div_clk3, + [RPM_SMD_DIV_A_CLK3] = &msm8996_div_clk3_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8996_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8996_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8996_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8996_bb_clk2_a_pin, + [RPM_SMD_RF_CLK1_PIN] = &msm8996_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8996_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8996_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8996_rf_clk2_a_pin, +}; + +static const struct rpm_smd_clk_desc rpm_clk_msm8996 = { + .clks = msm8996_clks, + .num_clks = ARRAY_SIZE(msm8996_clks), +}; + static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, + { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, { } }; MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table); diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index 29dad206a74b..b8337a5fa347 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -104,5 +104,19 @@ #define RPM_SMD_CXO_A1_A_PIN 59 #define RPM_SMD_CXO_A2_PIN 60 #define RPM_SMD_CXO_A2_A_PIN 61 +#define RPM_SMD_AGGR1_NOC_CLK 62 +#define RPM_SMD_AGGR1_NOC_A_CLK 63 +#define RPM_SMD_AGGR2_NOC_CLK 64 +#define RPM_SMD_AGGR2_NOC_A_CLK 65 +#define RPM_SMD_MMAXI_CLK 66 +#define RPM_SMD_MMAXI_A_CLK 67 +#define RPM_SMD_IPA_CLK 68 +#define RPM_SMD_IPA_A_CLK 69 +#define RPM_SMD_CE1_CLK 70 +#define RPM_SMD_CE1_A_CLK 71 +#define RPM_SMD_DIV_CLK3 72 +#define RPM_SMD_DIV_A_CLK3 73 +#define RPM_SMD_LN_BB_CLK 74 +#define RPM_SMD_LN_BB_A_CLK 75 #endif diff --git a/include/linux/soc/qcom/smd-rpm.h b/include/linux/soc/qcom/smd-rpm.h index 2a53dcaeeeed..ebdabd669d93 100644 --- a/include/linux/soc/qcom/smd-rpm.h +++ b/include/linux/soc/qcom/smd-rpm.h @@ -26,6 +26,10 @@ struct qcom_smd_rpm; #define QCOM_SMD_RPM_SMPB 0x62706d73 #define QCOM_SMD_RPM_SPDM 0x63707362 #define QCOM_SMD_RPM_VSA 0x00617376 +#define QCOM_SMD_RPM_MMAXI_CLK 0x69786d6d +#define QCOM_SMD_RPM_IPA_CLK 0x617069 +#define QCOM_SMD_RPM_CE_CLK 0x6563 +#define QCOM_SMD_RPM_AGGR_CLK 0x72676761 int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm, int state, -- GitLab From c68ee58d9ee7b856ac722f18f4f26579c8fbd2b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Szymanski?= Date: Tue, 1 Aug 2017 12:40:07 +0200 Subject: [PATCH 1524/2898] clk: imx6: refine hdmi_isfr's parent to make HDMI work on i.MX6 SoCs w/o VPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On i.MX6 SoCs without VPU (in my case MCIMX6D4AVT10AC), the hdmi driver fails to probe: [ 2.540030] dwhdmi-imx 120000.hdmi: Unsupported HDMI controller (0000:00:00) [ 2.548199] imx-drm display-subsystem: failed to bind 120000.hdmi (ops dw_hdmi_imx_ops): -19 [ 2.557403] imx-drm display-subsystem: master bind failed: -19 That's because hdmi_isfr's parent, video_27m, is not correctly ungated. As explained in commit 5ccc248cc537 ("ARM: imx6q: clk: Add support for mipi_core_cfg clock as a shared clock gate"), video_27m is gated by CCM_CCGR3[CG8]. On i.MX6 SoCs with VPU, the hdmi is working thanks to the CCM_CMEOR[mod_en_ov_vpu] bit which makes the video_27m ungated whatever is in CCM_CCGR3[CG8]. The issue can be reproduced by setting CCMEOR[mod_en_ov_vpu] to 0. Make the HDMI work in every case by setting hdmi_isfr's parent to mipi_core_cfg. Signed-off-by: Sébastien Szymanski Reviewed-by: Fabio Estevam Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx6q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index c07df719b8a3..8d518ad5dc13 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -761,7 +761,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24); clk[IMX6QDL_CLK_GPU3D_CORE] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26); clk[IMX6QDL_CLK_HDMI_IAHB] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0); - clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "video_27m", base + 0x70, 4); + clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "mipi_core_cfg", base + 0x70, 4); clk[IMX6QDL_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6); clk[IMX6QDL_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8); clk[IMX6QDL_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10); -- GitLab From 7f218065c136cc643e4773cad5e742f2c597988c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 12 Oct 2017 15:29:35 +0200 Subject: [PATCH 1525/2898] clk: imx: clk-imx6ul: allow lcdif_pre_sel to change parent rate Allowing the lcdif_pre_sel to propagate rate changes to its parent PLL allows more fine grained control over the LCDIF pixel clock rate. For example, the Innovision AT043TN24 LCD panel described in the imx6ul-14x14-evk device tree requires a 9 MHz pixel clock. Before this patch, the lcdif_pre_sel clock rate is fixed, and just setting the lcdif_pred and lcdif_podf dividers only allows to get as close as about 8.44 MHz: pll3 1 1 480000000 0 0 pll3_bypass 1 1 480000000 0 0 pll3_usb_otg 1 1 480000000 0 0 pll3_pfd1_540m 1 1 540000000 0 0 lcdif_pre_sel 1 1 540000000 0 0 lcdif_pred 1 1 67500000 0 0 lcdif_podf 1 1 8437500 0 0 lcdif_pix 1 1 8437500 0 0 Once lcdif_pre_sel is allowed to propagate rate requests to its parent, the actual pixel clock matches the requested value: pll3 1 1 480000000 0 0 pll3_bypass 1 1 480000000 0 0 pll3_usb_otg 1 1 480000000 0 0 pll3_pfd1_540m 1 1 288000000 0 0 lcdif_pre_sel 1 1 288000000 0 0 lcdif_pred 1 1 36000000 0 0 lcdif_podf 1 1 9000000 0 0 lcdif_pix 1 1 9000000 0 0 Signed-off-by: Philipp Zabel Reviewed-by: Fabio Estevam Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx6ul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 5e8c18afce9a..85c118164469 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -267,7 +267,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) clks[IMX6ULL_CLK_EPDC_SEL] = imx_clk_mux("epdc_sel", base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels)); } clks[IMX6UL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); - clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels)); + clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT); clks[IMX6UL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels)); clks[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels)); -- GitLab From edc5a8e754aba9c6eaeddd18cb1e72462f99b16c Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Mon, 2 Oct 2017 13:32:10 +0300 Subject: [PATCH 1526/2898] clk: imx: imx7d: Fix parent clock for OCRAM_CLK The parent of OCRAM_CLK should be axi_main_root_clk and not axi_post_div. before: axi_src 1 1 332307692 0 0 axi_cg 1 1 332307692 0 0 axi_pre_div 1 1 332307692 0 0 axi_post_div 1 1 332307692 0 0 ocram_clk 0 0 332307692 0 0 main_axi_root_clk 1 1 332307692 0 0 after: axi_src 1 1 332307692 0 0 axi_cg 1 1 332307692 0 0 axi_pre_div 1 1 332307692 0 0 axi_post_div 1 1 332307692 0 0 main_axi_root_clk 1 1 332307692 0 0 ocram_clk 0 0 332307692 0 0 Reference Doc: i.MX 7D Reference Manual - Chap 5, p 516 (https://www.nxp.com/docs/en/reference-manual/IMX7DRM.pdf) Fixes: 8f6d8094b215 ("ARM: imx: add imx7d clk tree support") Signed-off-by: Adriana Reus Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx7d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 2305699db467..0ac9b30c8b90 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -797,7 +797,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); - clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0); + clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0); clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0); clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0); clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0); -- GitLab From 259bc283069975004067c51cc09525a50db4b470 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Mon, 2 Oct 2017 13:32:11 +0300 Subject: [PATCH 1527/2898] clk: imx: imx7d: Remove ARM_M0 clock IMX7d does not have an M0 Core and this particular clock doesn't seem connected to anything else. Remove this entry from the CCM driver. Signed-off-by: Adriana Reus Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx7d.c | 9 --------- include/dt-bindings/clock/imx7d-clock.h | 8 ++++---- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 0ac9b30c8b90..80dc211eb74b 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -54,11 +54,6 @@ static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk", "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk", "pll_usb_main_clk", }; -static const char *arm_m0_sel[] = { "osc", "pll_sys_main_120m_clk", - "pll_enet_125m_clk", "pll_sys_pfd2_135m_clk", - "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk", - "pll_usb_main_clk", }; - static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk", "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk", "pll_audio_post_div", "pll_video_main_clk", "pll_sys_pfd7_clk", }; @@ -510,7 +505,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel)); clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel)); - clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux2("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel)); clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel)); clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel)); clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel)); @@ -582,7 +576,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28); clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); - clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate3("arm_m0_cg", "arm_m0_src", base + 0x8100, 28); clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate3("axi_cg", "axi_src", base + 0x8800, 28); clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28); clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28); @@ -721,7 +714,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3); clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); - clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider2("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3); clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6); clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6); clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6); @@ -793,7 +785,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0); clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0); - clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate4("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0); clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); diff --git a/include/dt-bindings/clock/imx7d-clock.h b/include/dt-bindings/clock/imx7d-clock.h index de62a83b6c80..e2f99ae72d5c 100644 --- a/include/dt-bindings/clock/imx7d-clock.h +++ b/include/dt-bindings/clock/imx7d-clock.h @@ -80,10 +80,10 @@ #define IMX7D_ARM_M4_ROOT_SRC 67 #define IMX7D_ARM_M4_ROOT_CG 68 #define IMX7D_ARM_M4_ROOT_DIV 69 -#define IMX7D_ARM_M0_ROOT_CLK 70 -#define IMX7D_ARM_M0_ROOT_SRC 71 -#define IMX7D_ARM_M0_ROOT_CG 72 -#define IMX7D_ARM_M0_ROOT_DIV 73 +#define IMX7D_ARM_M0_ROOT_CLK 70 /* unused */ +#define IMX7D_ARM_M0_ROOT_SRC 71 /* unused */ +#define IMX7D_ARM_M0_ROOT_CG 72 /* unused */ +#define IMX7D_ARM_M0_ROOT_DIV 73 /* unused */ #define IMX7D_MAIN_AXI_ROOT_CLK 74 #define IMX7D_MAIN_AXI_ROOT_SRC 75 #define IMX7D_MAIN_AXI_ROOT_CG 76 -- GitLab From eb522df40e41915210856f1d654e0c31650cb526 Mon Sep 17 00:00:00 2001 From: "weiyi.lu@mediatek.com" Date: Mon, 23 Oct 2017 12:10:32 +0800 Subject: [PATCH 1528/2898] dt-bindings: ARM: Mediatek: Document bindings for MT2712 This patch adds the binding documentation for apmixedsys, bdpsys, imgsys, imgsys, infracfg, mcucfg, mfgcfg, mmsys, pericfg, topckgen, vdecsys and vencsys for Mediatek MT2712. Acked-by: Rob Herring Signed-off-by: Weiyi Lu Signed-off-by: Stephen Boyd --- .../arm/mediatek/mediatek,apmixedsys.txt | 1 + .../bindings/arm/mediatek/mediatek,bdpsys.txt | 1 + .../bindings/arm/mediatek/mediatek,imgsys.txt | 1 + .../arm/mediatek/mediatek,infracfg.txt | 1 + .../arm/mediatek/mediatek,jpgdecsys.txt | 22 +++++++++++++++++++ .../bindings/arm/mediatek/mediatek,mcucfg.txt | 22 +++++++++++++++++++ .../bindings/arm/mediatek/mediatek,mfgcfg.txt | 22 +++++++++++++++++++ .../bindings/arm/mediatek/mediatek,mmsys.txt | 1 + .../arm/mediatek/mediatek,pericfg.txt | 1 + .../arm/mediatek/mediatek,topckgen.txt | 1 + .../arm/mediatek/mediatek,vdecsys.txt | 1 + .../arm/mediatek/mediatek,vencsys.txt | 1 + 12 files changed, 75 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt index cd977db7630c..19fc116346d6 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2701-apmixedsys" + - "mediatek,mt2712-apmixedsys", "syscon" - "mediatek,mt6797-apmixedsys" - "mediatek,mt8135-apmixedsys" - "mediatek,mt8173-apmixedsys" diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt index 4137196dd686..4010e37c53a0 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: Should be: - "mediatek,mt2701-bdpsys", "syscon" + - "mediatek,mt2712-bdpsys", "syscon" - #clock-cells: Must be 1 The bdpsys controller uses the common clk binding from diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt index 047b11ae5f45..868bd51a98be 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2701-imgsys", "syscon" + - "mediatek,mt2712-imgsys", "syscon" - "mediatek,mt6797-imgsys", "syscon" - "mediatek,mt8173-imgsys", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt index 58d58e2006b8..a3430cd96d0f 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt @@ -8,6 +8,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2701-infracfg", "syscon" + - "mediatek,mt2712-infracfg", "syscon" - "mediatek,mt6797-infracfg", "syscon" - "mediatek,mt8135-infracfg", "syscon" - "mediatek,mt8173-infracfg", "syscon" diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt new file mode 100644 index 000000000000..2df799cd06a7 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt @@ -0,0 +1,22 @@ +Mediatek jpgdecsys controller +============================ + +The Mediatek jpgdecsys controller provides various clocks to the system. + +Required Properties: + +- compatible: Should be: + - "mediatek,mt2712-jpgdecsys", "syscon" +- #clock-cells: Must be 1 + +The jpgdecsys controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +jpgdecsys: syscon@19000000 { + compatible = "mediatek,mt2712-jpgdecsys", "syscon"; + reg = <0 0x19000000 0 0x1000>; + #clock-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt new file mode 100644 index 000000000000..b8fb03f3613e --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt @@ -0,0 +1,22 @@ +Mediatek mcucfg controller +============================ + +The Mediatek mcucfg controller provides various clocks to the system. + +Required Properties: + +- compatible: Should be one of: + - "mediatek,mt2712-mcucfg", "syscon" +- #clock-cells: Must be 1 + +The mcucfg controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +mcucfg: syscon@10220000 { + compatible = "mediatek,mt2712-mcucfg", "syscon"; + reg = <0 0x10220000 0 0x1000>; + #clock-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt new file mode 100644 index 000000000000..859e67b416d5 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt @@ -0,0 +1,22 @@ +Mediatek mfgcfg controller +============================ + +The Mediatek mfgcfg controller provides various clocks to the system. + +Required Properties: + +- compatible: Should be one of: + - "mediatek,mt2712-mfgcfg", "syscon" +- #clock-cells: Must be 1 + +The mfgcfg controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +mfgcfg: syscon@13000000 { + compatible = "mediatek,mt2712-mfgcfg", "syscon"; + reg = <0 0x13000000 0 0x1000>; + #clock-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt index 70529e0b58e9..4eb8bbe15c01 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2701-mmsys", "syscon" + - "mediatek,mt2712-mmsys", "syscon" - "mediatek,mt6797-mmsys", "syscon" - "mediatek,mt8173-mmsys", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt index e494366782aa..d9f092eb3550 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt @@ -8,6 +8,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2701-pericfg", "syscon" + - "mediatek,mt2712-pericfg", "syscon" - "mediatek,mt8135-pericfg", "syscon" - "mediatek,mt8173-pericfg", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt index ec93ecbb9f3c..2024fc909d69 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2701-topckgen" + - "mediatek,mt2712-topckgen", "syscon" - "mediatek,mt6797-topckgen" - "mediatek,mt8135-topckgen" - "mediatek,mt8173-topckgen" diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt index d150104f928a..ea40d05089f8 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2701-vdecsys", "syscon" + - "mediatek,mt2712-vdecsys", "syscon" - "mediatek,mt6797-vdecsys", "syscon" - "mediatek,mt8173-vdecsys", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt index 8a93be643647..851545357e94 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt @@ -6,6 +6,7 @@ The Mediatek vencsys controller provides various clocks to the system. Required Properties: - compatible: Should be one of: + - "mediatek,mt2712-vencsys", "syscon" - "mediatek,mt6797-vencsys", "syscon" - "mediatek,mt8173-vencsys", "syscon" - #clock-cells: Must be 1 -- GitLab From b7f1a721bb3e493627d9db0a00edfb53c70ba823 Mon Sep 17 00:00:00 2001 From: "weiyi.lu@mediatek.com" Date: Mon, 23 Oct 2017 12:10:33 +0800 Subject: [PATCH 1529/2898] clk: mediatek: Add dt-bindings for MT2712 clocks Add MT2712 clock dt-bindings, include topckgen, apmixedsys, infracfg, pericfg, mcucfg and subsystem clocks. Signed-off-by: Weiyi Lu Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/mt2712-clk.h | 427 +++++++++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 include/dt-bindings/clock/mt2712-clk.h diff --git a/include/dt-bindings/clock/mt2712-clk.h b/include/dt-bindings/clock/mt2712-clk.h new file mode 100644 index 000000000000..48a8e797a617 --- /dev/null +++ b/include/dt-bindings/clock/mt2712-clk.h @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_CLK_MT2712_H +#define _DT_BINDINGS_CLK_MT2712_H + +/* APMIXEDSYS */ + +#define CLK_APMIXED_MAINPLL 0 +#define CLK_APMIXED_UNIVPLL 1 +#define CLK_APMIXED_VCODECPLL 2 +#define CLK_APMIXED_VENCPLL 3 +#define CLK_APMIXED_APLL1 4 +#define CLK_APMIXED_APLL2 5 +#define CLK_APMIXED_LVDSPLL 6 +#define CLK_APMIXED_LVDSPLL2 7 +#define CLK_APMIXED_MSDCPLL 8 +#define CLK_APMIXED_MSDCPLL2 9 +#define CLK_APMIXED_TVDPLL 10 +#define CLK_APMIXED_MMPLL 11 +#define CLK_APMIXED_ARMCA35PLL 12 +#define CLK_APMIXED_ARMCA72PLL 13 +#define CLK_APMIXED_ETHERPLL 14 +#define CLK_APMIXED_NR_CLK 15 + +/* TOPCKGEN */ + +#define CLK_TOP_ARMCA35PLL 0 +#define CLK_TOP_ARMCA35PLL_600M 1 +#define CLK_TOP_ARMCA35PLL_400M 2 +#define CLK_TOP_ARMCA72PLL 3 +#define CLK_TOP_SYSPLL 4 +#define CLK_TOP_SYSPLL_D2 5 +#define CLK_TOP_SYSPLL1_D2 6 +#define CLK_TOP_SYSPLL1_D4 7 +#define CLK_TOP_SYSPLL1_D8 8 +#define CLK_TOP_SYSPLL1_D16 9 +#define CLK_TOP_SYSPLL_D3 10 +#define CLK_TOP_SYSPLL2_D2 11 +#define CLK_TOP_SYSPLL2_D4 12 +#define CLK_TOP_SYSPLL_D5 13 +#define CLK_TOP_SYSPLL3_D2 14 +#define CLK_TOP_SYSPLL3_D4 15 +#define CLK_TOP_SYSPLL_D7 16 +#define CLK_TOP_SYSPLL4_D2 17 +#define CLK_TOP_SYSPLL4_D4 18 +#define CLK_TOP_UNIVPLL 19 +#define CLK_TOP_UNIVPLL_D7 20 +#define CLK_TOP_UNIVPLL_D26 21 +#define CLK_TOP_UNIVPLL_D52 22 +#define CLK_TOP_UNIVPLL_D104 23 +#define CLK_TOP_UNIVPLL_D208 24 +#define CLK_TOP_UNIVPLL_D2 25 +#define CLK_TOP_UNIVPLL1_D2 26 +#define CLK_TOP_UNIVPLL1_D4 27 +#define CLK_TOP_UNIVPLL1_D8 28 +#define CLK_TOP_UNIVPLL_D3 29 +#define CLK_TOP_UNIVPLL2_D2 30 +#define CLK_TOP_UNIVPLL2_D4 31 +#define CLK_TOP_UNIVPLL2_D8 32 +#define CLK_TOP_UNIVPLL_D5 33 +#define CLK_TOP_UNIVPLL3_D2 34 +#define CLK_TOP_UNIVPLL3_D4 35 +#define CLK_TOP_UNIVPLL3_D8 36 +#define CLK_TOP_F_MP0_PLL1 37 +#define CLK_TOP_F_MP0_PLL2 38 +#define CLK_TOP_F_BIG_PLL1 39 +#define CLK_TOP_F_BIG_PLL2 40 +#define CLK_TOP_F_BUS_PLL1 41 +#define CLK_TOP_F_BUS_PLL2 42 +#define CLK_TOP_APLL1 43 +#define CLK_TOP_APLL1_D2 44 +#define CLK_TOP_APLL1_D4 45 +#define CLK_TOP_APLL1_D8 46 +#define CLK_TOP_APLL1_D16 47 +#define CLK_TOP_APLL2 48 +#define CLK_TOP_APLL2_D2 49 +#define CLK_TOP_APLL2_D4 50 +#define CLK_TOP_APLL2_D8 51 +#define CLK_TOP_APLL2_D16 52 +#define CLK_TOP_LVDSPLL 53 +#define CLK_TOP_LVDSPLL_D2 54 +#define CLK_TOP_LVDSPLL_D4 55 +#define CLK_TOP_LVDSPLL_D8 56 +#define CLK_TOP_LVDSPLL2 57 +#define CLK_TOP_LVDSPLL2_D2 58 +#define CLK_TOP_LVDSPLL2_D4 59 +#define CLK_TOP_LVDSPLL2_D8 60 +#define CLK_TOP_ETHERPLL_125M 61 +#define CLK_TOP_ETHERPLL_50M 62 +#define CLK_TOP_CVBS 63 +#define CLK_TOP_CVBS_D2 64 +#define CLK_TOP_SYS_26M 65 +#define CLK_TOP_MMPLL 66 +#define CLK_TOP_MMPLL_D2 67 +#define CLK_TOP_VENCPLL 68 +#define CLK_TOP_VENCPLL_D2 69 +#define CLK_TOP_VCODECPLL 70 +#define CLK_TOP_VCODECPLL_D2 71 +#define CLK_TOP_TVDPLL 72 +#define CLK_TOP_TVDPLL_D2 73 +#define CLK_TOP_TVDPLL_D4 74 +#define CLK_TOP_TVDPLL_D8 75 +#define CLK_TOP_TVDPLL_429M 76 +#define CLK_TOP_TVDPLL_429M_D2 77 +#define CLK_TOP_TVDPLL_429M_D4 78 +#define CLK_TOP_MSDCPLL 79 +#define CLK_TOP_MSDCPLL_D2 80 +#define CLK_TOP_MSDCPLL_D4 81 +#define CLK_TOP_MSDCPLL2 82 +#define CLK_TOP_MSDCPLL2_D2 83 +#define CLK_TOP_MSDCPLL2_D4 84 +#define CLK_TOP_CLK26M_D2 85 +#define CLK_TOP_D2A_ULCLK_6P5M 86 +#define CLK_TOP_VPLL3_DPIX 87 +#define CLK_TOP_VPLL_DPIX 88 +#define CLK_TOP_LTEPLL_FS26M 89 +#define CLK_TOP_DMPLL 90 +#define CLK_TOP_DSI0_LNTC 91 +#define CLK_TOP_DSI1_LNTC 92 +#define CLK_TOP_LVDSTX3_CLKDIG_CTS 93 +#define CLK_TOP_LVDSTX_CLKDIG_CTS 94 +#define CLK_TOP_CLKRTC_EXT 95 +#define CLK_TOP_CLKRTC_INT 96 +#define CLK_TOP_CSI0 97 +#define CLK_TOP_CVBSPLL 98 +#define CLK_TOP_AXI_SEL 99 +#define CLK_TOP_MEM_SEL 100 +#define CLK_TOP_MM_SEL 101 +#define CLK_TOP_PWM_SEL 102 +#define CLK_TOP_VDEC_SEL 103 +#define CLK_TOP_VENC_SEL 104 +#define CLK_TOP_MFG_SEL 105 +#define CLK_TOP_CAMTG_SEL 106 +#define CLK_TOP_UART_SEL 107 +#define CLK_TOP_SPI_SEL 108 +#define CLK_TOP_USB20_SEL 109 +#define CLK_TOP_USB30_SEL 110 +#define CLK_TOP_MSDC50_0_HCLK_SEL 111 +#define CLK_TOP_MSDC50_0_SEL 112 +#define CLK_TOP_MSDC30_1_SEL 113 +#define CLK_TOP_MSDC30_2_SEL 114 +#define CLK_TOP_MSDC30_3_SEL 115 +#define CLK_TOP_AUDIO_SEL 116 +#define CLK_TOP_AUD_INTBUS_SEL 117 +#define CLK_TOP_PMICSPI_SEL 118 +#define CLK_TOP_DPILVDS1_SEL 119 +#define CLK_TOP_ATB_SEL 120 +#define CLK_TOP_NR_SEL 121 +#define CLK_TOP_NFI2X_SEL 122 +#define CLK_TOP_IRDA_SEL 123 +#define CLK_TOP_CCI400_SEL 124 +#define CLK_TOP_AUD_1_SEL 125 +#define CLK_TOP_AUD_2_SEL 126 +#define CLK_TOP_MEM_MFG_IN_AS_SEL 127 +#define CLK_TOP_AXI_MFG_IN_AS_SEL 128 +#define CLK_TOP_SCAM_SEL 129 +#define CLK_TOP_NFIECC_SEL 130 +#define CLK_TOP_PE2_MAC_P0_SEL 131 +#define CLK_TOP_PE2_MAC_P1_SEL 132 +#define CLK_TOP_DPILVDS_SEL 133 +#define CLK_TOP_MSDC50_3_HCLK_SEL 134 +#define CLK_TOP_HDCP_SEL 135 +#define CLK_TOP_HDCP_24M_SEL 136 +#define CLK_TOP_RTC_SEL 137 +#define CLK_TOP_SPINOR_SEL 138 +#define CLK_TOP_APLL_SEL 139 +#define CLK_TOP_APLL2_SEL 140 +#define CLK_TOP_A1SYS_HP_SEL 141 +#define CLK_TOP_A2SYS_HP_SEL 142 +#define CLK_TOP_ASM_L_SEL 143 +#define CLK_TOP_ASM_M_SEL 144 +#define CLK_TOP_ASM_H_SEL 145 +#define CLK_TOP_I2SO1_SEL 146 +#define CLK_TOP_I2SO2_SEL 147 +#define CLK_TOP_I2SO3_SEL 148 +#define CLK_TOP_TDMO0_SEL 149 +#define CLK_TOP_TDMO1_SEL 150 +#define CLK_TOP_I2SI1_SEL 151 +#define CLK_TOP_I2SI2_SEL 152 +#define CLK_TOP_I2SI3_SEL 153 +#define CLK_TOP_ETHER_125M_SEL 154 +#define CLK_TOP_ETHER_50M_SEL 155 +#define CLK_TOP_JPGDEC_SEL 156 +#define CLK_TOP_SPISLV_SEL 157 +#define CLK_TOP_ETHER_50M_RMII_SEL 158 +#define CLK_TOP_CAM2TG_SEL 159 +#define CLK_TOP_DI_SEL 160 +#define CLK_TOP_TVD_SEL 161 +#define CLK_TOP_I2C_SEL 162 +#define CLK_TOP_PWM_INFRA_SEL 163 +#define CLK_TOP_MSDC0P_AES_SEL 164 +#define CLK_TOP_CMSYS_SEL 165 +#define CLK_TOP_GCPU_SEL 166 +#define CLK_TOP_AUD_APLL1_SEL 167 +#define CLK_TOP_AUD_APLL2_SEL 168 +#define CLK_TOP_DA_AUDULL_VTX_6P5M_SEL 169 +#define CLK_TOP_APLL_DIV0 170 +#define CLK_TOP_APLL_DIV1 171 +#define CLK_TOP_APLL_DIV2 172 +#define CLK_TOP_APLL_DIV3 173 +#define CLK_TOP_APLL_DIV4 174 +#define CLK_TOP_APLL_DIV5 175 +#define CLK_TOP_APLL_DIV6 176 +#define CLK_TOP_APLL_DIV7 177 +#define CLK_TOP_APLL_DIV_PDN0 178 +#define CLK_TOP_APLL_DIV_PDN1 179 +#define CLK_TOP_APLL_DIV_PDN2 180 +#define CLK_TOP_APLL_DIV_PDN3 181 +#define CLK_TOP_APLL_DIV_PDN4 182 +#define CLK_TOP_APLL_DIV_PDN5 183 +#define CLK_TOP_APLL_DIV_PDN6 184 +#define CLK_TOP_APLL_DIV_PDN7 185 +#define CLK_TOP_NR_CLK 186 + +/* INFRACFG */ + +#define CLK_INFRA_DBGCLK 0 +#define CLK_INFRA_GCE 1 +#define CLK_INFRA_M4U 2 +#define CLK_INFRA_KP 3 +#define CLK_INFRA_AO_SPI0 4 +#define CLK_INFRA_AO_SPI1 5 +#define CLK_INFRA_AO_UART5 6 +#define CLK_INFRA_NR_CLK 7 + +/* PERICFG */ + +#define CLK_PERI_NFI 0 +#define CLK_PERI_THERM 1 +#define CLK_PERI_PWM0 2 +#define CLK_PERI_PWM1 3 +#define CLK_PERI_PWM2 4 +#define CLK_PERI_PWM3 5 +#define CLK_PERI_PWM4 6 +#define CLK_PERI_PWM5 7 +#define CLK_PERI_PWM6 8 +#define CLK_PERI_PWM7 9 +#define CLK_PERI_PWM 10 +#define CLK_PERI_AP_DMA 11 +#define CLK_PERI_MSDC30_0 12 +#define CLK_PERI_MSDC30_1 13 +#define CLK_PERI_MSDC30_2 14 +#define CLK_PERI_MSDC30_3 15 +#define CLK_PERI_UART0 16 +#define CLK_PERI_UART1 17 +#define CLK_PERI_UART2 18 +#define CLK_PERI_UART3 19 +#define CLK_PERI_I2C0 20 +#define CLK_PERI_I2C1 21 +#define CLK_PERI_I2C2 22 +#define CLK_PERI_I2C3 23 +#define CLK_PERI_I2C4 24 +#define CLK_PERI_AUXADC 25 +#define CLK_PERI_SPI0 26 +#define CLK_PERI_SPI 27 +#define CLK_PERI_I2C5 28 +#define CLK_PERI_SPI2 29 +#define CLK_PERI_SPI3 30 +#define CLK_PERI_SPI5 31 +#define CLK_PERI_UART4 32 +#define CLK_PERI_SFLASH 33 +#define CLK_PERI_GMAC 34 +#define CLK_PERI_PCIE0 35 +#define CLK_PERI_PCIE1 36 +#define CLK_PERI_GMAC_PCLK 37 +#define CLK_PERI_MSDC50_0_EN 38 +#define CLK_PERI_MSDC30_1_EN 39 +#define CLK_PERI_MSDC30_2_EN 40 +#define CLK_PERI_MSDC30_3_EN 41 +#define CLK_PERI_MSDC50_0_HCLK_EN 42 +#define CLK_PERI_MSDC50_3_HCLK_EN 43 +#define CLK_PERI_NR_CLK 44 + +/* MCUCFG */ + +#define CLK_MCU_MP0_SEL 0 +#define CLK_MCU_MP2_SEL 1 +#define CLK_MCU_BUS_SEL 2 +#define CLK_MCU_NR_CLK 3 + +/* MFGCFG */ + +#define CLK_MFG_BG3D 0 +#define CLK_MFG_NR_CLK 1 + +/* MMSYS */ + +#define CLK_MM_SMI_COMMON 0 +#define CLK_MM_SMI_LARB0 1 +#define CLK_MM_CAM_MDP 2 +#define CLK_MM_MDP_RDMA0 3 +#define CLK_MM_MDP_RDMA1 4 +#define CLK_MM_MDP_RSZ0 5 +#define CLK_MM_MDP_RSZ1 6 +#define CLK_MM_MDP_RSZ2 7 +#define CLK_MM_MDP_TDSHP0 8 +#define CLK_MM_MDP_TDSHP1 9 +#define CLK_MM_MDP_CROP 10 +#define CLK_MM_MDP_WDMA 11 +#define CLK_MM_MDP_WROT0 12 +#define CLK_MM_MDP_WROT1 13 +#define CLK_MM_FAKE_ENG 14 +#define CLK_MM_MUTEX_32K 15 +#define CLK_MM_DISP_OVL0 16 +#define CLK_MM_DISP_OVL1 17 +#define CLK_MM_DISP_RDMA0 18 +#define CLK_MM_DISP_RDMA1 19 +#define CLK_MM_DISP_RDMA2 20 +#define CLK_MM_DISP_WDMA0 21 +#define CLK_MM_DISP_WDMA1 22 +#define CLK_MM_DISP_COLOR0 23 +#define CLK_MM_DISP_COLOR1 24 +#define CLK_MM_DISP_AAL 25 +#define CLK_MM_DISP_GAMMA 26 +#define CLK_MM_DISP_UFOE 27 +#define CLK_MM_DISP_SPLIT0 28 +#define CLK_MM_DISP_OD 29 +#define CLK_MM_DISP_PWM0_MM 30 +#define CLK_MM_DISP_PWM0_26M 31 +#define CLK_MM_DISP_PWM1_MM 32 +#define CLK_MM_DISP_PWM1_26M 33 +#define CLK_MM_DSI0_ENGINE 34 +#define CLK_MM_DSI0_DIGITAL 35 +#define CLK_MM_DSI1_ENGINE 36 +#define CLK_MM_DSI1_DIGITAL 37 +#define CLK_MM_DPI_PIXEL 38 +#define CLK_MM_DPI_ENGINE 39 +#define CLK_MM_DPI1_PIXEL 40 +#define CLK_MM_DPI1_ENGINE 41 +#define CLK_MM_LVDS_PIXEL 42 +#define CLK_MM_LVDS_CTS 43 +#define CLK_MM_SMI_LARB4 44 +#define CLK_MM_SMI_COMMON1 45 +#define CLK_MM_SMI_LARB5 46 +#define CLK_MM_MDP_RDMA2 47 +#define CLK_MM_MDP_TDSHP2 48 +#define CLK_MM_DISP_OVL2 49 +#define CLK_MM_DISP_WDMA2 50 +#define CLK_MM_DISP_COLOR2 51 +#define CLK_MM_DISP_AAL1 52 +#define CLK_MM_DISP_OD1 53 +#define CLK_MM_LVDS1_PIXEL 54 +#define CLK_MM_LVDS1_CTS 55 +#define CLK_MM_SMI_LARB7 56 +#define CLK_MM_MDP_RDMA3 57 +#define CLK_MM_MDP_WROT2 58 +#define CLK_MM_DSI2 59 +#define CLK_MM_DSI2_DIGITAL 60 +#define CLK_MM_DSI3 61 +#define CLK_MM_DSI3_DIGITAL 62 +#define CLK_MM_NR_CLK 63 + +/* IMGSYS */ + +#define CLK_IMG_SMI_LARB2 0 +#define CLK_IMG_SENINF_SCAM_EN 1 +#define CLK_IMG_SENINF_CAM_EN 2 +#define CLK_IMG_CAM_SV_EN 3 +#define CLK_IMG_CAM_SV1_EN 4 +#define CLK_IMG_CAM_SV2_EN 5 +#define CLK_IMG_NR_CLK 6 + +/* BDPSYS */ + +#define CLK_BDP_BRIDGE_B 0 +#define CLK_BDP_BRIDGE_DRAM 1 +#define CLK_BDP_LARB_DRAM 2 +#define CLK_BDP_WR_CHANNEL_VDI_PXL 3 +#define CLK_BDP_WR_CHANNEL_VDI_DRAM 4 +#define CLK_BDP_WR_CHANNEL_VDI_B 5 +#define CLK_BDP_MT_B 6 +#define CLK_BDP_DISPFMT_27M 7 +#define CLK_BDP_DISPFMT_27M_VDOUT 8 +#define CLK_BDP_DISPFMT_27_74_74 9 +#define CLK_BDP_DISPFMT_2FS 10 +#define CLK_BDP_DISPFMT_2FS_2FS74_148 11 +#define CLK_BDP_DISPFMT_B 12 +#define CLK_BDP_VDO_DRAM 13 +#define CLK_BDP_VDO_2FS 14 +#define CLK_BDP_VDO_B 15 +#define CLK_BDP_WR_CHANNEL_DI_PXL 16 +#define CLK_BDP_WR_CHANNEL_DI_DRAM 17 +#define CLK_BDP_WR_CHANNEL_DI_B 18 +#define CLK_BDP_NR_AGENT 19 +#define CLK_BDP_NR_DRAM 20 +#define CLK_BDP_NR_B 21 +#define CLK_BDP_BRIDGE_RT_B 22 +#define CLK_BDP_BRIDGE_RT_DRAM 23 +#define CLK_BDP_LARB_RT_DRAM 24 +#define CLK_BDP_TVD_TDC 25 +#define CLK_BDP_TVD_54 26 +#define CLK_BDP_TVD_CBUS 27 +#define CLK_BDP_NR_CLK 28 + +/* VDECSYS */ + +#define CLK_VDEC_CKEN 0 +#define CLK_VDEC_LARB1_CKEN 1 +#define CLK_VDEC_IMGRZ_CKEN 2 +#define CLK_VDEC_NR_CLK 3 + +/* VENCSYS */ + +#define CLK_VENC_SMI_COMMON_CON 0 +#define CLK_VENC_VENC 1 +#define CLK_VENC_SMI_LARB6 2 +#define CLK_VENC_NR_CLK 3 + +/* JPGDECSYS */ + +#define CLK_JPGDEC_JPGDEC1 0 +#define CLK_JPGDEC_JPGDEC 1 +#define CLK_JPGDEC_NR_CLK 2 + +#endif /* _DT_BINDINGS_CLK_MT2712_H */ -- GitLab From e2f744a82d725ab55091cccfb8e527b4220471f0 Mon Sep 17 00:00:00 2001 From: "weiyi.lu@mediatek.com" Date: Mon, 23 Oct 2017 12:10:34 +0800 Subject: [PATCH 1530/2898] clk: mediatek: Add MT2712 clock support Add MT2712 clock support, include topckgen, apmixedsys, infracfg, pericfg, mcucfg and subsystem clocks. Signed-off-by: Weiyi Lu [sboyd@codeaurora.org: Static on top_clk_data] Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/Kconfig | 50 + drivers/clk/mediatek/Makefile | 8 + drivers/clk/mediatek/clk-mt2712-bdp.c | 102 ++ drivers/clk/mediatek/clk-mt2712-img.c | 80 ++ drivers/clk/mediatek/clk-mt2712-jpgdec.c | 76 ++ drivers/clk/mediatek/clk-mt2712-mfg.c | 75 ++ drivers/clk/mediatek/clk-mt2712-mm.c | 170 +++ drivers/clk/mediatek/clk-mt2712-vdec.c | 94 ++ drivers/clk/mediatek/clk-mt2712-venc.c | 77 ++ drivers/clk/mediatek/clk-mt2712.c | 1435 ++++++++++++++++++++++ drivers/clk/mediatek/clk-mtk.h | 2 + drivers/clk/mediatek/clk-pll.c | 13 +- 12 files changed, 2180 insertions(+), 2 deletions(-) create mode 100644 drivers/clk/mediatek/clk-mt2712-bdp.c create mode 100644 drivers/clk/mediatek/clk-mt2712-img.c create mode 100644 drivers/clk/mediatek/clk-mt2712-jpgdec.c create mode 100644 drivers/clk/mediatek/clk-mt2712-mfg.c create mode 100644 drivers/clk/mediatek/clk-mt2712-mm.c create mode 100644 drivers/clk/mediatek/clk-mt2712-vdec.c create mode 100644 drivers/clk/mediatek/clk-mt2712-venc.c create mode 100644 drivers/clk/mediatek/clk-mt2712.c diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 28739a9a6e37..300dbb551bf7 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -50,6 +50,56 @@ config COMMON_CLK_MT2701_BDPSYS ---help--- This driver supports Mediatek MT2701 bdpsys clocks. +config COMMON_CLK_MT2712 + bool "Clock driver for Mediatek MT2712" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + ---help--- + This driver supports Mediatek MT2712 basic clocks. + +config COMMON_CLK_MT2712_BDPSYS + bool "Clock driver for Mediatek MT2712 bdpsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 bdpsys clocks. + +config COMMON_CLK_MT2712_IMGSYS + bool "Clock driver for Mediatek MT2712 imgsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 imgsys clocks. + +config COMMON_CLK_MT2712_JPGDECSYS + bool "Clock driver for Mediatek MT2712 jpgdecsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 jpgdecsys clocks. + +config COMMON_CLK_MT2712_MFGCFG + bool "Clock driver for Mediatek MT2712 mfgcfg" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 mfgcfg clocks. + +config COMMON_CLK_MT2712_MMSYS + bool "Clock driver for Mediatek MT2712 mmsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 mmsys clocks. + +config COMMON_CLK_MT2712_VDECSYS + bool "Clock driver for Mediatek MT2712 vdecsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 vdecsys clocks. + +config COMMON_CLK_MT2712_VENCSYS + bool "Clock driver for Mediatek MT2712 vencsys" + depends on COMMON_CLK_MT2712 + ---help--- + This driver supports Mediatek MT2712 vencsys clocks. + config COMMON_CLK_MT6797 bool "Clock driver for Mediatek MT6797" depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index 2a755b5fb51b..a4e5c47c73a4 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -12,5 +12,13 @@ obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o +obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712.o +obj-$(CONFIG_COMMON_CLK_MT2712_BDPSYS) += clk-mt2712-bdp.o +obj-$(CONFIG_COMMON_CLK_MT2712_IMGSYS) += clk-mt2712-img.o +obj-$(CONFIG_COMMON_CLK_MT2712_JPGDECSYS) += clk-mt2712-jpgdec.o +obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o +obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o +obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o +obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c new file mode 100644 index 000000000000..5fe4728c076e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-bdp.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs bdp_cg_regs = { + .set_ofs = 0x100, + .clr_ofs = 0x100, + .sta_ofs = 0x100, +}; + +#define GATE_BDP(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &bdp_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate bdp_clks[] = { + GATE_BDP(CLK_BDP_BRIDGE_B, "bdp_bridge_b", "mm_sel", 0), + GATE_BDP(CLK_BDP_BRIDGE_DRAM, "bdp_bridge_d", "mm_sel", 1), + GATE_BDP(CLK_BDP_LARB_DRAM, "bdp_larb_d", "mm_sel", 2), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_PXL, "bdp_vdi_pxl", "tvd_sel", 3), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_DRAM, "bdp_vdi_d", "mm_sel", 4), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_B, "bdp_vdi_b", "mm_sel", 5), + GATE_BDP(CLK_BDP_MT_B, "bdp_fmt_b", "mm_sel", 9), + GATE_BDP(CLK_BDP_DISPFMT_27M, "bdp_27m", "di_sel", 10), + GATE_BDP(CLK_BDP_DISPFMT_27M_VDOUT, "bdp_27m_vdout", "di_sel", 11), + GATE_BDP(CLK_BDP_DISPFMT_27_74_74, "bdp_27_74_74", "di_sel", 12), + GATE_BDP(CLK_BDP_DISPFMT_2FS, "bdp_2fs", "di_sel", 13), + GATE_BDP(CLK_BDP_DISPFMT_2FS_2FS74_148, "bdp_2fs74_148", "di_sel", 14), + GATE_BDP(CLK_BDP_DISPFMT_B, "bdp_b", "mm_sel", 15), + GATE_BDP(CLK_BDP_VDO_DRAM, "bdp_vdo_d", "mm_sel", 16), + GATE_BDP(CLK_BDP_VDO_2FS, "bdp_vdo_2fs", "di_sel", 17), + GATE_BDP(CLK_BDP_VDO_B, "bdp_vdo_b", "mm_sel", 18), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_PXL, "bdp_di_pxl", "di_sel", 19), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_DRAM, "bdp_di_d", "mm_sel", 20), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_B, "bdp_di_b", "mm_sel", 21), + GATE_BDP(CLK_BDP_NR_AGENT, "bdp_nr_agent", "nr_sel", 22), + GATE_BDP(CLK_BDP_NR_DRAM, "bdp_nr_d", "mm_sel", 23), + GATE_BDP(CLK_BDP_NR_B, "bdp_nr_b", "mm_sel", 24), + GATE_BDP(CLK_BDP_BRIDGE_RT_B, "bdp_bridge_rt_b", "mm_sel", 25), + GATE_BDP(CLK_BDP_BRIDGE_RT_DRAM, "bdp_bridge_rt_d", "mm_sel", 26), + GATE_BDP(CLK_BDP_LARB_RT_DRAM, "bdp_larb_rt_d", "mm_sel", 27), + GATE_BDP(CLK_BDP_TVD_TDC, "bdp_tvd_tdc", "mm_sel", 28), + GATE_BDP(CLK_BDP_TVD_54, "bdp_tvd_clk_54", "tvd_sel", 29), + GATE_BDP(CLK_BDP_TVD_CBUS, "bdp_tvd_cbus", "mm_sel", 30), +}; + +static int clk_mt2712_bdp_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_BDP_NR_CLK); + + mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_bdp[] = { + { .compatible = "mediatek,mt2712-bdpsys", }, + {} +}; + +static struct platform_driver clk_mt2712_bdp_drv = { + .probe = clk_mt2712_bdp_probe, + .driver = { + .name = "clk-mt2712-bdp", + .of_match_table = of_match_clk_mt2712_bdp, + }, +}; + +builtin_platform_driver(clk_mt2712_bdp_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c new file mode 100644 index 000000000000..139ff55d495e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-img.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &img_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_SMI_LARB2, "img_smi_larb2", "mm_sel", 0), + GATE_IMG(CLK_IMG_SENINF_SCAM_EN, "img_scam_en", "csi0", 3), + GATE_IMG(CLK_IMG_SENINF_CAM_EN, "img_cam_en", "mm_sel", 8), + GATE_IMG(CLK_IMG_CAM_SV_EN, "img_cam_sv_en", "mm_sel", 9), + GATE_IMG(CLK_IMG_CAM_SV1_EN, "img_cam_sv1_en", "mm_sel", 10), + GATE_IMG(CLK_IMG_CAM_SV2_EN, "img_cam_sv2_en", "mm_sel", 11), +}; + +static int clk_mt2712_img_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); + + mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_img[] = { + { .compatible = "mediatek,mt2712-imgsys", }, + {} +}; + +static struct platform_driver clk_mt2712_img_drv = { + .probe = clk_mt2712_img_probe, + .driver = { + .name = "clk-mt2712-img", + .of_match_table = of_match_clk_mt2712_img, + }, +}; + +builtin_platform_driver(clk_mt2712_img_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c new file mode 100644 index 000000000000..c7d4aada4892 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs jpgdec_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_JPGDEC(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &jpgdec_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate jpgdec_clks[] = { + GATE_JPGDEC(CLK_JPGDEC_JPGDEC1, "jpgdec_jpgdec1", "jpgdec_sel", 0), + GATE_JPGDEC(CLK_JPGDEC_JPGDEC, "jpgdec_jpgdec", "jpgdec_sel", 4), +}; + +static int clk_mt2712_jpgdec_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_JPGDEC_NR_CLK); + + mtk_clk_register_gates(node, jpgdec_clks, ARRAY_SIZE(jpgdec_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_jpgdec[] = { + { .compatible = "mediatek,mt2712-jpgdecsys", }, + {} +}; + +static struct platform_driver clk_mt2712_jpgdec_drv = { + .probe = clk_mt2712_jpgdec_probe, + .driver = { + .name = "clk-mt2712-jpgdec", + .of_match_table = of_match_clk_mt2712_jpgdec, + }, +}; + +builtin_platform_driver(clk_mt2712_jpgdec_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c new file mode 100644 index 000000000000..570f72d48d4d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-mfg.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mfg_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0), +}; + +static int clk_mt2712_mfg_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK); + + mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_mfg[] = { + { .compatible = "mediatek,mt2712-mfgcfg", }, + {} +}; + +static struct platform_driver clk_mt2712_mfg_drv = { + .probe = clk_mt2712_mfg_probe, + .driver = { + .name = "clk-mt2712-mfg", + .of_match_table = of_match_clk_mt2712_mfg, + }, +}; + +builtin_platform_driver(clk_mt2712_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c new file mode 100644 index 000000000000..a8b4b6d42488 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-mm.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +static const struct mtk_gate_regs mm2_cg_regs = { + .set_ofs = 0x224, + .clr_ofs = 0x228, + .sta_ofs = 0x220, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mm0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_MM1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mm1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_MM2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mm2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2), + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3), + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6), + GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7), + GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8), + GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9), + GATE_MM0(CLK_MM_MDP_CROP, "mm_mdp_crop", "mm_sel", 10), + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12), + GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14), + GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "clk32k", 15), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16), + GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19), + GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21), + GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23), + GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24), + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25), + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26), + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27), + GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28), + GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31), + /* MM1 */ + GATE_MM1(CLK_MM_DISP_PWM0_MM, "mm_pwm0_mm", "mm_sel", 0), + GATE_MM1(CLK_MM_DISP_PWM0_26M, "mm_pwm0_26m", "pwm_sel", 1), + GATE_MM1(CLK_MM_DISP_PWM1_MM, "mm_pwm1_mm", "mm_sel", 2), + GATE_MM1(CLK_MM_DISP_PWM1_26M, "mm_pwm1_26m", "pwm_sel", 3), + GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4), + GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_lntc", 5), + GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6), + GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_lntc", 7), + GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "vpll_dpix", 8), + GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9), + GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "vpll3_dpix", 10), + GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11), + GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "vpll_dpix", 16), + GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx", 17), + GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18), + GATE_MM1(CLK_MM_SMI_COMMON1, "mm_smi_common1", "mm_sel", 21), + GATE_MM1(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 22), + GATE_MM1(CLK_MM_MDP_RDMA2, "mm_mdp_rdma2", "mm_sel", 23), + GATE_MM1(CLK_MM_MDP_TDSHP2, "mm_mdp_tdshp2", "mm_sel", 24), + GATE_MM1(CLK_MM_DISP_OVL2, "mm_disp_ovl2", "mm_sel", 25), + GATE_MM1(CLK_MM_DISP_WDMA2, "mm_disp_wdma2", "mm_sel", 26), + GATE_MM1(CLK_MM_DISP_COLOR2, "mm_disp_color2", "mm_sel", 27), + GATE_MM1(CLK_MM_DISP_AAL1, "mm_disp_aal1", "mm_sel", 28), + GATE_MM1(CLK_MM_DISP_OD1, "mm_disp_od1", "mm_sel", 29), + GATE_MM1(CLK_MM_LVDS1_PIXEL, "mm_lvds1_pixel", "vpll3_dpix", 30), + GATE_MM1(CLK_MM_LVDS1_CTS, "mm_lvds1_cts", "lvdstx3", 31), + /* MM2 */ + GATE_MM2(CLK_MM_SMI_LARB7, "mm_smi_larb7", "mm_sel", 0), + GATE_MM2(CLK_MM_MDP_RDMA3, "mm_mdp_rdma3", "mm_sel", 1), + GATE_MM2(CLK_MM_MDP_WROT2, "mm_mdp_wrot2", "mm_sel", 2), + GATE_MM2(CLK_MM_DSI2, "mm_dsi2", "mm_sel", 3), + GATE_MM2(CLK_MM_DSI2_DIGITAL, "mm_dsi2_digital", "dsi0_lntc", 4), + GATE_MM2(CLK_MM_DSI3, "mm_dsi3", "mm_sel", 5), + GATE_MM2(CLK_MM_DSI3_DIGITAL, "mm_dsi3_digital", "dsi1_lntc", 6), +}; + +static int clk_mt2712_mm_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + + mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_mm[] = { + { .compatible = "mediatek,mt2712-mmsys", }, + {} +}; + +static struct platform_driver clk_mt2712_mm_drv = { + .probe = clk_mt2712_mm_probe, + .driver = { + .name = "clk-mt2712-mm", + .of_match_table = of_match_clk_mt2712_mm, + }, +}; + +builtin_platform_driver(clk_mt2712_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c new file mode 100644 index 000000000000..55c64ee8cc91 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-vdec.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &vdec0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_VDEC1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &vdec1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "vdec_sel", 0), + GATE_VDEC1(CLK_VDEC_IMGRZ_CKEN, "vdec_imgrz_cken", "vdec_sel", 1), +}; + +static int clk_mt2712_vdec_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); + + mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_vdec[] = { + { .compatible = "mediatek,mt2712-vdecsys", }, + {} +}; + +static struct platform_driver clk_mt2712_vdec_drv = { + .probe = clk_mt2712_vdec_probe, + .driver = { + .name = "clk-mt2712-vdec", + .of_match_table = of_match_clk_mt2712_vdec, + }, +}; + +builtin_platform_driver(clk_mt2712_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c new file mode 100644 index 000000000000..ccbfe98777c8 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-venc.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &venc_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_SMI_COMMON_CON, "venc_smi", "mm_sel", 0), + GATE_VENC(CLK_VENC_VENC, "venc_venc", "venc_sel", 4), + GATE_VENC(CLK_VENC_SMI_LARB6, "venc_smi_larb6", "jpgdec_sel", 12), +}; + +static int clk_mt2712_venc_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK); + + mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712_venc[] = { + { .compatible = "mediatek,mt2712-vencsys", }, + {} +}; + +static struct platform_driver clk_mt2712_venc_drv = { + .probe = clk_mt2712_venc_probe, + .driver = { + .name = "clk-mt2712-venc", + .of_match_table = of_match_clk_mt2712_venc, + }, +}; + +builtin_platform_driver(clk_mt2712_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c new file mode 100644 index 000000000000..498d13799388 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712.c @@ -0,0 +1,1435 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static DEFINE_SPINLOCK(mt2712_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_VPLL3_DPIX, "vpll3_dpix", NULL, 200000000), + FIXED_CLK(CLK_TOP_VPLL_DPIX, "vpll_dpix", NULL, 200000000), + FIXED_CLK(CLK_TOP_LTEPLL_FS26M, "ltepll_fs26m", NULL, 26000000), + FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", NULL, 350000000), + FIXED_CLK(CLK_TOP_DSI0_LNTC, "dsi0_lntc", NULL, 143000000), + FIXED_CLK(CLK_TOP_DSI1_LNTC, "dsi1_lntc", NULL, 143000000), + FIXED_CLK(CLK_TOP_LVDSTX3_CLKDIG_CTS, "lvdstx3", NULL, 140000000), + FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, "lvdstx", NULL, 140000000), + FIXED_CLK(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", NULL, 32768), + FIXED_CLK(CLK_TOP_CLKRTC_INT, "clkrtc_int", NULL, 32747), + FIXED_CLK(CLK_TOP_CSI0, "csi0", NULL, 26000000), + FIXED_CLK(CLK_TOP_CVBSPLL, "cvbspll", NULL, 108000000), +}; + +static const struct mtk_fixed_factor top_early_divs[] = { + FACTOR(CLK_TOP_SYS_26M, "sys_26m", "clk26m", 1, + 1), + FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "sys_26m", 1, + 2), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_ARMCA35PLL, "armca35pll_ck", "armca35pll", 1, + 1), + FACTOR(CLK_TOP_ARMCA35PLL_600M, "armca35pll_600m", "armca35pll_ck", 1, + 2), + FACTOR(CLK_TOP_ARMCA35PLL_400M, "armca35pll_400m", "armca35pll_ck", 1, + 3), + FACTOR(CLK_TOP_ARMCA72PLL, "armca72pll_ck", "armca72pll", 1, + 1), + FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, + 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1, + 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, + 2), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, + 4), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, + 8), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, + 16), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "syspll_ck", 1, + 3), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, + 2), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "syspll_ck", 1, + 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, + 2), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "syspll_ck", 1, + 7), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, + 2), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, + 1), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_ck", 1, + 7), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_ck", 1, + 26), + FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll_ck", 1, + 52), + FACTOR(CLK_TOP_UNIVPLL_D104, "univpll_d104", "univpll_ck", 1, + 104), + FACTOR(CLK_TOP_UNIVPLL_D208, "univpll_d208", "univpll_ck", 1, + 208), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_ck", 1, + 3), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_ck", 1, + 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, + 8), + FACTOR(CLK_TOP_F_MP0_PLL1, "f_mp0_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_MP0_PLL2, "f_mp0_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_F_BIG_PLL1, "f_big_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_BIG_PLL2, "f_big_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_F_BUS_PLL1, "f_bus_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_BUS_PLL2, "f_bus_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, + 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, + 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1_ck", 1, + 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1_ck", 1, + 8), + FACTOR(CLK_TOP_APLL1_D16, "apll1_d16", "apll1_ck", 1, + 16), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, + 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, + 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2_ck", 1, + 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2_ck", 1, + 8), + FACTOR(CLK_TOP_APLL2_D16, "apll2_d16", "apll2_ck", 1, + 16), + FACTOR(CLK_TOP_LVDSPLL, "lvdspll_ck", "lvdspll", 1, + 1), + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll_ck", 1, + 2), + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll_ck", 1, + 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll_ck", 1, + 8), + FACTOR(CLK_TOP_LVDSPLL2, "lvdspll2_ck", "lvdspll2", 1, + 1), + FACTOR(CLK_TOP_LVDSPLL2_D2, "lvdspll2_d2", "lvdspll2_ck", 1, + 2), + FACTOR(CLK_TOP_LVDSPLL2_D4, "lvdspll2_d4", "lvdspll2_ck", 1, + 4), + FACTOR(CLK_TOP_LVDSPLL2_D8, "lvdspll2_d8", "lvdspll2_ck", 1, + 8), + FACTOR(CLK_TOP_ETHERPLL_125M, "etherpll_125m", "etherpll", 1, + 1), + FACTOR(CLK_TOP_ETHERPLL_50M, "etherpll_50m", "etherpll", 1, + 1), + FACTOR(CLK_TOP_CVBS, "cvbs", "cvbspll", 1, + 1), + FACTOR(CLK_TOP_CVBS_D2, "cvbs_d2", "cvbs", 1, + 2), + FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, + 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll_ck", 1, + 2), + FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, + 1), + FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll_ck", 1, + 2), + FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, + 1), + FACTOR(CLK_TOP_VCODECPLL_D2, "vcodecpll_d2", "vcodecpll_ck", 1, + 2), + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, + 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, + 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, + 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, + 8), + FACTOR(CLK_TOP_TVDPLL_429M, "tvdpll_429m", "tvdpll", 1, + 1), + FACTOR(CLK_TOP_TVDPLL_429M_D2, "tvdpll_429m_d2", "tvdpll_429m", 1, + 2), + FACTOR(CLK_TOP_TVDPLL_429M_D4, "tvdpll_429m_d4", "tvdpll_429m", 1, + 4), + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, + 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, + 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, + 4), + FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, + 1), + FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2_ck", 1, + 2), + FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2_ck", 1, + 4), + FACTOR(CLK_TOP_D2A_ULCLK_6P5M, "d2a_ulclk_6p5m", "clk26m", 1, + 4), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "msdcpll2_ck" +}; + +static const char * const mem_parents[] = { + "clk26m", + "dmpll_ck" +}; + +static const char * const mm_parents[] = { + "clk26m", + "vencpll_ck", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll1_d2", + "univpll2_d2" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char * const vdec_parents[] = { + "clk26m", + "vcodecpll_ck", + "tvdpll_429m", + "univpll_d3", + "vencpll_ck", + "syspll_d3", + "univpll1_d2", + "mmpll_d2", + "syspll3_d2", + "tvdpll_ck" +}; + +static const char * const venc_parents[] = { + "clk26m", + "univpll1_d2", + "mmpll_d2", + "tvdpll_d2", + "syspll1_d2", + "univpll_d5", + "vcodecpll_d2", + "univpll2_d2", + "syspll3_d2" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mmpll_ck", + "univpll_d3", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "univpll_d3", + "univpll1_d2", + "univpll_d5", + "univpll2_d2" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_d52", + "univpll_d208", + "univpll_d104", + "clk26m_d2", + "univpll_d26", + "univpll2_d8", + "syspll3_d4", + "syspll3_d2", + "univpll1_d4", + "univpll2_d2" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "univpll2_d4", + "univpll1_d4", + "univpll2_d2", + "univpll3_d2", + "univpll1_d8" +}; + +static const char * const usb20_parents[] = { + "clk26m", + "univpll1_d8", + "univpll3_d4" +}; + +static const char * const usb30_parents[] = { + "clk26m", + "univpll3_d2", + "univpll3_d4", + "univpll2_d4" +}; + +static const char * const msdc50_0_h_parents[] = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "msdcpll_d4", + "vencpll_d2", + "univpll1_d2", + "msdcpll2_ck", + "msdcpll2_d2", + "msdcpll2_d4" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "univpll2_d2", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "univpll_d7", + "vencpll_d2" +}; + +static const char * const msdc30_3_parents[] = { + "clk26m", + "msdcpll2_ck", + "msdcpll2_d2", + "univpll2_d2", + "msdcpll2_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d2", + "msdcpll_ck", + "msdcpll_d2", + "msdcpll_d4" +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d8", + "syspll3_d2", + "syspll3_d4" +}; + +static const char * const pmicspi_parents[] = { + "clk26m", + "syspll1_d8", + "syspll3_d4", + "syspll1_d16", + "univpll3_d4", + "univpll_d26", + "syspll3_d4" +}; + +static const char * const dpilvds1_parents[] = { + "clk26m", + "lvdspll2_ck", + "lvdspll2_d2", + "lvdspll2_d4", + "lvdspll2_d8", + "clkfpc" +}; + +static const char * const atb_parents[] = { + "clk26m", + "syspll1_d2", + "univpll_d5", + "syspll_d5" +}; + +static const char * const nr_parents[] = { + "clk26m", + "univpll1_d4", + "syspll2_d2", + "syspll1_d4", + "univpll1_d8", + "univpll3_d2", + "univpll2_d2", + "syspll_d5" +}; + +static const char * const nfi2x_parents[] = { + "clk26m", + "syspll4_d4", + "univpll3_d4", + "univpll1_d8", + "syspll2_d4", + "univpll3_d2", + "syspll_d7", + "syspll2_d2", + "univpll2_d2", + "syspll_d5", + "syspll1_d2" +}; + +static const char * const irda_parents[] = { + "clk26m", + "univpll2_d4", + "syspll2_d4", + "univpll2_d8" +}; + +static const char * const cci400_parents[] = { + "clk26m", + "vencpll_ck", + "armca35pll_600m", + "armca35pll_400m", + "univpll_d2", + "syspll_d2", + "msdcpll_ck", + "univpll_d3" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const mem_mfg_parents[] = { + "clk26m", + "mmpll_ck", + "univpll_d3" +}; + +static const char * const axi_mfg_parents[] = { + "clk26m", + "axi_sel", + "univpll_d5" +}; + +static const char * const scam_parents[] = { + "clk26m", + "syspll3_d2", + "univpll2_d4", + "syspll2_d4" +}; + +static const char * const nfiecc_parents[] = { + "clk26m", + "nfi2x_sel", + "syspll_d7", + "syspll2_d2", + "univpll2_d2", + "univpll_d5", + "syspll1_d2" +}; + +static const char * const pe2_mac_p0_parents[] = { + "clk26m", + "syspll1_d8", + "syspll4_d2", + "syspll2_d4", + "univpll2_d4", + "syspll3_d2" +}; + +static const char * const dpilvds_parents[] = { + "clk26m", + "lvdspll_ck", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8", + "clkfpc" +}; + +static const char * const hdcp_parents[] = { + "clk26m", + "syspll4_d2", + "syspll3_d4", + "univpll2_d4" +}; + +static const char * const hdcp_24m_parents[] = { + "clk26m", + "univpll_d26", + "univpll_d52", + "univpll2_d8" +}; + +static const char * const rtc_parents[] = { + "clkrtc_int", + "clkrtc_ext", + "clk26m", + "univpll3_d8" +}; + +static const char * const spinor_parents[] = { + "clk26m", + "clk26m_d2", + "syspll4_d4", + "univpll2_d8", + "univpll3_d4", + "syspll4_d2", + "syspll2_d4", + "univpll2_d4", + "etherpll_125m", + "syspll1_d4" +}; + +static const char * const apll_parents[] = { + "clk26m", + "apll1_ck", + "apll1_d2", + "apll1_d4", + "apll1_d8", + "apll1_d16", + "apll2_ck", + "apll2_d2", + "apll2_d4", + "apll2_d8", + "apll2_d16", + "clk26m", + "clk26m" +}; + +static const char * const a1sys_hp_parents[] = { + "clk26m", + "apll1_ck", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const a2sys_hp_parents[] = { + "clk26m", + "apll2_ck", + "apll2_d2", + "apll2_d4", + "apll2_d8" +}; + +static const char * const asm_l_parents[] = { + "clk26m", + "univpll2_d4", + "univpll2_d2", + "syspll_d5" +}; + +static const char * const i2so1_parents[] = { + "clk26m", + "apll1_ck", + "apll2_ck" +}; + +static const char * const ether_125m_parents[] = { + "clk26m", + "etherpll_125m", + "univpll3_d2" +}; + +static const char * const ether_50m_parents[] = { + "clk26m", + "etherpll_50m", + "univpll_d26", + "univpll3_d4" +}; + +static const char * const jpgdec_parents[] = { + "clk26m", + "univpll_d3", + "tvdpll_429m", + "vencpll_ck", + "syspll_d3", + "vcodecpll_ck", + "univpll1_d2", + "armca35pll_400m", + "tvdpll_429m_d2", + "tvdpll_429m_d4" +}; + +static const char * const spislv_parents[] = { + "clk26m", + "univpll2_d4", + "univpll1_d4", + "univpll2_d2", + "univpll3_d2", + "univpll1_d8", + "univpll1_d2", + "univpll_d5" +}; + +static const char * const ether_parents[] = { + "clk26m", + "etherpll_50m", + "univpll_d26" +}; + +static const char * const di_parents[] = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "vencpll_ck", + "vencpll_d2", + "cvbs", + "cvbs_d2" +}; + +static const char * const tvd_parents[] = { + "clk26m", + "cvbs_d2", + "univpll2_d8" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "univpll_d26", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char * const msdc0p_aes_parents[] = { + "clk26m", + "msdcpll_ck", + "univpll_d3", + "vcodecpll_ck" +}; + +static const char * const cmsys_parents[] = { + "clk26m", + "univpll_d3", + "syspll_d3", + "syspll1_d2", + "syspll2_d2" +}; + +static const char * const gcpu_parents[] = { + "clk26m", + "syspll_d3", + "syspll1_d2", + "univpll1_d2", + "univpll_d5", + "univpll3_d2", + "univpll_d3" +}; + +static const char * const aud_apll1_parents[] = { + "apll1", + "clkaud_ext_i_1" +}; + +static const char * const aud_apll2_parents[] = { + "apll2", + "clkaud_ext_i_2" +}; + +static const char * const audull_vtx_parents[] = { + "d2a_ulclk_6p5m", + "clkaud_ext_i_0" +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x040, 0, 3, + 7, CLK_IS_CRITICAL), + MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040, 8, 1, + 15, CLK_IS_CRITICAL), + MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", + mm_parents, 0x040, 24, 3, 31), + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", + pwm_parents, 0x050, 0, 2, 7), + MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", + vdec_parents, 0x050, 8, 4, 15), + MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", + venc_parents, 0x050, 16, 4, 23), + MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", + mfg_parents, 0x050, 24, 4, 31), + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", + camtg_parents, 0x060, 0, 4, 7), + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", + uart_parents, 0x060, 8, 1, 15), + MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", + spi_parents, 0x060, 16, 3, 23), + MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", + usb20_parents, 0x060, 24, 2, 31), + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", + usb30_parents, 0x070, 0, 2, 7), + MUX_GATE(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc50_0_h_sel", + msdc50_0_h_parents, 0x070, 8, 3, 15), + MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + msdc50_0_parents, 0x070, 16, 4, 23), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + msdc30_1_parents, 0x070, 24, 3, 31), + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", + msdc30_1_parents, 0x080, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", + msdc30_3_parents, 0x080, 8, 4, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", + audio_parents, 0x080, 16, 2, 23), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", + aud_intbus_parents, 0x080, 24, 3, 31), + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", + pmicspi_parents, 0x090, 0, 3, 7), + MUX_GATE(CLK_TOP_DPILVDS1_SEL, "dpilvds1_sel", + dpilvds1_parents, 0x090, 8, 3, 15), + MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", + atb_parents, 0x090, 16, 2, 23), + MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", + nr_parents, 0x090, 24, 3, 31), + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", + nfi2x_parents, 0x0a0, 0, 4, 7), + MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", + irda_parents, 0x0a0, 8, 2, 15), + MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", + cci400_parents, 0x0a0, 16, 3, 23), + MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", + aud_1_parents, 0x0a0, 24, 2, 31), + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", + aud_2_parents, 0x0b0, 0, 2, 7), + MUX_GATE(CLK_TOP_MEM_MFG_IN_AS_SEL, "mem_mfg_sel", + mem_mfg_parents, 0x0b0, 8, 2, 15), + MUX_GATE(CLK_TOP_AXI_MFG_IN_AS_SEL, "axi_mfg_sel", + axi_mfg_parents, 0x0b0, 16, 2, 23), + MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", + scam_parents, 0x0b0, 24, 2, 31), + /* CLK_CFG_8 */ + MUX_GATE(CLK_TOP_NFIECC_SEL, "nfiecc_sel", + nfiecc_parents, 0x0c0, 0, 3, 7), + MUX_GATE(CLK_TOP_PE2_MAC_P0_SEL, "pe2_mac_p0_sel", + pe2_mac_p0_parents, 0x0c0, 8, 3, 15), + MUX_GATE(CLK_TOP_PE2_MAC_P1_SEL, "pe2_mac_p1_sel", + pe2_mac_p0_parents, 0x0c0, 16, 3, 23), + MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", + dpilvds_parents, 0x0c0, 24, 3, 31), + /* CLK_CFG_9 */ + MUX_GATE(CLK_TOP_MSDC50_3_HCLK_SEL, "msdc50_3_h_sel", + msdc50_0_h_parents, 0x0d0, 0, 3, 7), + MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", + hdcp_parents, 0x0d0, 8, 2, 15), + MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", + hdcp_24m_parents, 0x0d0, 16, 2, 23), + MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x0d0, 24, 2, + 31, CLK_IS_CRITICAL), + /* CLK_CFG_10 */ + MUX_GATE(CLK_TOP_SPINOR_SEL, "spinor_sel", + spinor_parents, 0x500, 0, 4, 7), + MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", + apll_parents, 0x500, 8, 4, 15), + MUX_GATE(CLK_TOP_APLL2_SEL, "apll2_sel", + apll_parents, 0x500, 16, 4, 23), + MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", + a1sys_hp_parents, 0x500, 24, 3, 31), + /* CLK_CFG_11 */ + MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", + a2sys_hp_parents, 0x510, 0, 3, 7), + MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", + asm_l_parents, 0x510, 8, 2, 15), + MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", + asm_l_parents, 0x510, 16, 2, 23), + MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", + asm_l_parents, 0x510, 24, 2, 31), + /* CLK_CFG_12 */ + MUX_GATE(CLK_TOP_I2SO1_SEL, "i2so1_sel", + i2so1_parents, 0x520, 0, 2, 7), + MUX_GATE(CLK_TOP_I2SO2_SEL, "i2so2_sel", + i2so1_parents, 0x520, 8, 2, 15), + MUX_GATE(CLK_TOP_I2SO3_SEL, "i2so3_sel", + i2so1_parents, 0x520, 16, 2, 23), + MUX_GATE(CLK_TOP_TDMO0_SEL, "tdmo0_sel", + i2so1_parents, 0x520, 24, 2, 31), + /* CLK_CFG_13 */ + MUX_GATE(CLK_TOP_TDMO1_SEL, "tdmo1_sel", + i2so1_parents, 0x530, 0, 2, 7), + MUX_GATE(CLK_TOP_I2SI1_SEL, "i2si1_sel", + i2so1_parents, 0x530, 8, 2, 15), + MUX_GATE(CLK_TOP_I2SI2_SEL, "i2si2_sel", + i2so1_parents, 0x530, 16, 2, 23), + MUX_GATE(CLK_TOP_I2SI3_SEL, "i2si3_sel", + i2so1_parents, 0x530, 24, 2, 31), + /* CLK_CFG_14 */ + MUX_GATE(CLK_TOP_ETHER_125M_SEL, "ether_125m_sel", + ether_125m_parents, 0x540, 0, 2, 7), + MUX_GATE(CLK_TOP_ETHER_50M_SEL, "ether_50m_sel", + ether_50m_parents, 0x540, 8, 2, 15), + MUX_GATE(CLK_TOP_JPGDEC_SEL, "jpgdec_sel", + jpgdec_parents, 0x540, 16, 4, 23), + MUX_GATE(CLK_TOP_SPISLV_SEL, "spislv_sel", + spislv_parents, 0x540, 24, 3, 31), + /* CLK_CFG_15 */ + MUX_GATE(CLK_TOP_ETHER_50M_RMII_SEL, "ether_sel", + ether_parents, 0x550, 0, 2, 7), + MUX_GATE(CLK_TOP_CAM2TG_SEL, "cam2tg_sel", + camtg_parents, 0x550, 8, 4, 15), + MUX_GATE(CLK_TOP_DI_SEL, "di_sel", + di_parents, 0x550, 16, 3, 23), + MUX_GATE(CLK_TOP_TVD_SEL, "tvd_sel", + tvd_parents, 0x550, 24, 2, 31), + /* CLK_CFG_16 */ + MUX_GATE(CLK_TOP_I2C_SEL, "i2c_sel", + i2c_parents, 0x560, 0, 3, 7), + MUX_GATE(CLK_TOP_PWM_INFRA_SEL, "pwm_infra_sel", + pwm_parents, 0x560, 8, 2, 15), + MUX_GATE(CLK_TOP_MSDC0P_AES_SEL, "msdc0p_aes_sel", + msdc0p_aes_parents, 0x560, 16, 2, 23), + MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", + cmsys_parents, 0x560, 24, 3, 31), + /* CLK_CFG_17 */ + MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", + gcpu_parents, 0x570, 0, 3, 7), + /* CLK_AUDDIV_4 */ + MUX(CLK_TOP_AUD_APLL1_SEL, "aud_apll1_sel", + aud_apll1_parents, 0x134, 0, 1), + MUX(CLK_TOP_AUD_APLL2_SEL, "aud_apll2_sel", + aud_apll2_parents, 0x134, 1, 1), + MUX(CLK_TOP_DA_AUDULL_VTX_6P5M_SEL, "audull_vtx_sel", + audull_vtx_parents, 0x134, 31, 1), +}; + +static const char * const mcu_mp0_parents[] = { + "clk26m", + "armca35pll_ck", + "f_mp0_pll1_ck", + "f_mp0_pll2_ck" +}; + +static const char * const mcu_mp2_parents[] = { + "clk26m", + "armca72pll_ck", + "f_big_pll1_ck", + "f_big_pll2_ck" +}; + +static const char * const mcu_bus_parents[] = { + "clk26m", + "cci400_sel", + "f_bus_pll1_ck", + "f_bus_pll2_ck" +}; + +static struct mtk_composite mcu_muxes[] = { + /* mp0_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_MP0_SEL, "mcu_mp0_sel", mcu_mp0_parents, 0x7A0, + 9, 2, -1, CLK_IS_CRITICAL), + /* mp2_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_MP2_SEL, "mcu_mp2_sel", mcu_mp2_parents, 0x7A8, + 9, 2, -1, CLK_IS_CRITICAL), + /* bus_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_BUS_SEL, "mcu_bus_sel", mcu_bus_parents, 0x7C0, + 9, 2, -1, CLK_IS_CRITICAL), +}; + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL_DIV0, "apll_div0", "i2so1_sel", 0x124, 0, 8), + DIV_ADJ(CLK_TOP_APLL_DIV1, "apll_div1", "i2so2_sel", 0x124, 8, 8), + DIV_ADJ(CLK_TOP_APLL_DIV2, "apll_div2", "i2so3_sel", 0x124, 16, 8), + DIV_ADJ(CLK_TOP_APLL_DIV3, "apll_div3", "tdmo0_sel", 0x124, 24, 8), + DIV_ADJ(CLK_TOP_APLL_DIV4, "apll_div4", "tdmo1_sel", 0x128, 0, 8), + DIV_ADJ(CLK_TOP_APLL_DIV5, "apll_div5", "i2si1_sel", 0x128, 8, 8), + DIV_ADJ(CLK_TOP_APLL_DIV6, "apll_div6", "i2si2_sel", 0x128, 16, 8), + DIV_ADJ(CLK_TOP_APLL_DIV7, "apll_div7", "i2si3_sel", 0x128, 24, 8), +}; + +static const struct mtk_gate_regs top_cg_regs = { + .set_ofs = 0x120, + .clr_ofs = 0x120, + .sta_ofs = 0x120, +}; + +#define GATE_TOP(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate top_clks[] = { + GATE_TOP(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0), + GATE_TOP(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1), + GATE_TOP(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2), + GATE_TOP(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3), + GATE_TOP(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4), + GATE_TOP(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5), + GATE_TOP(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6), + GATE_TOP(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7), +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x40, +}; + +#define GATE_INFRA(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &infra_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate infra_clks[] = { + GATE_INFRA(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0), + GATE_INFRA(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6), + GATE_INFRA(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8), + GATE_INFRA(CLK_INFRA_KP, "infra_kp", "axi_sel", 16), + GATE_INFRA(CLK_INFRA_AO_SPI0, "infra_ao_spi0", "spi_sel", 24), + GATE_INFRA(CLK_INFRA_AO_SPI1, "infra_ao_spi1", "spislv_sel", 25), + GATE_INFRA(CLK_INFRA_AO_UART5, "infra_ao_uart5", "axi_sel", 26), +}; + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x10, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0xc, + .clr_ofs = 0x14, + .sta_ofs = 0x1c, +}; + +static const struct mtk_gate_regs peri2_cg_regs = { + .set_ofs = 0x42c, + .clr_ofs = 0x42c, + .sta_ofs = 0x42c, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate peri_clks[] = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_NFI, "per_nfi", + "axi_sel", 0), + GATE_PERI0(CLK_PERI_THERM, "per_therm", + "axi_sel", 1), + GATE_PERI0(CLK_PERI_PWM0, "per_pwm0", + "pwm_sel", 2), + GATE_PERI0(CLK_PERI_PWM1, "per_pwm1", + "pwm_sel", 3), + GATE_PERI0(CLK_PERI_PWM2, "per_pwm2", + "pwm_sel", 4), + GATE_PERI0(CLK_PERI_PWM3, "per_pwm3", + "pwm_sel", 5), + GATE_PERI0(CLK_PERI_PWM4, "per_pwm4", + "pwm_sel", 6), + GATE_PERI0(CLK_PERI_PWM5, "per_pwm5", + "pwm_sel", 7), + GATE_PERI0(CLK_PERI_PWM6, "per_pwm6", + "pwm_sel", 8), + GATE_PERI0(CLK_PERI_PWM7, "per_pwm7", + "pwm_sel", 9), + GATE_PERI0(CLK_PERI_PWM, "per_pwm", + "pwm_sel", 10), + GATE_PERI0(CLK_PERI_AP_DMA, "per_ap_dma", + "axi_sel", 13), + GATE_PERI0(CLK_PERI_MSDC30_0, "per_msdc30_0", + "msdc50_0_sel", 14), + GATE_PERI0(CLK_PERI_MSDC30_1, "per_msdc30_1", + "msdc30_1_sel", 15), + GATE_PERI0(CLK_PERI_MSDC30_2, "per_msdc30_2", + "msdc30_2_sel", 16), + GATE_PERI0(CLK_PERI_MSDC30_3, "per_msdc30_3", + "msdc30_3_sel", 17), + GATE_PERI0(CLK_PERI_UART0, "per_uart0", + "uart_sel", 20), + GATE_PERI0(CLK_PERI_UART1, "per_uart1", + "uart_sel", 21), + GATE_PERI0(CLK_PERI_UART2, "per_uart2", + "uart_sel", 22), + GATE_PERI0(CLK_PERI_UART3, "per_uart3", + "uart_sel", 23), + GATE_PERI0(CLK_PERI_I2C0, "per_i2c0", + "axi_sel", 24), + GATE_PERI0(CLK_PERI_I2C1, "per_i2c1", + "axi_sel", 25), + GATE_PERI0(CLK_PERI_I2C2, "per_i2c2", + "axi_sel", 26), + GATE_PERI0(CLK_PERI_I2C3, "per_i2c3", + "axi_sel", 27), + GATE_PERI0(CLK_PERI_I2C4, "per_i2c4", + "axi_sel", 28), + GATE_PERI0(CLK_PERI_AUXADC, "per_auxadc", + "ltepll_fs26m", 29), + GATE_PERI0(CLK_PERI_SPI0, "per_spi0", + "spi_sel", 30), + /* PERI1 */ + GATE_PERI1(CLK_PERI_SPI, "per_spi", + "spinor_sel", 1), + GATE_PERI1(CLK_PERI_I2C5, "per_i2c5", + "axi_sel", 3), + GATE_PERI1(CLK_PERI_SPI2, "per_spi2", + "spi_sel", 5), + GATE_PERI1(CLK_PERI_SPI3, "per_spi3", + "spi_sel", 6), + GATE_PERI1(CLK_PERI_SPI5, "per_spi5", + "spi_sel", 8), + GATE_PERI1(CLK_PERI_UART4, "per_uart4", + "uart_sel", 9), + GATE_PERI1(CLK_PERI_SFLASH, "per_sflash", + "uart_sel", 11), + GATE_PERI1(CLK_PERI_GMAC, "per_gmac", + "uart_sel", 12), + GATE_PERI1(CLK_PERI_PCIE0, "per_pcie0", + "uart_sel", 14), + GATE_PERI1(CLK_PERI_PCIE1, "per_pcie1", + "uart_sel", 15), + GATE_PERI1(CLK_PERI_GMAC_PCLK, "per_gmac_pclk", + "uart_sel", 16), + /* PERI2 */ + GATE_PERI2(CLK_PERI_MSDC50_0_EN, "per_msdc50_0_en", + "msdc50_0_sel", 0), + GATE_PERI2(CLK_PERI_MSDC30_1_EN, "per_msdc30_1_en", + "msdc30_1_sel", 1), + GATE_PERI2(CLK_PERI_MSDC30_2_EN, "per_msdc30_2_en", + "msdc30_2_sel", 2), + GATE_PERI2(CLK_PERI_MSDC30_3_EN, "per_msdc30_3_en", + "msdc30_3_sel", 3), + GATE_PERI2(CLK_PERI_MSDC50_0_HCLK_EN, "per_msdc50_0_h", + "msdc50_0_h_sel", 4), + GATE_PERI2(CLK_PERI_MSDC50_3_HCLK_EN, "per_msdc50_3_h", + "msdc50_3_h_sel", 5), +}; + +#define MT2712_PLL_FMAX (3000UL * MHZ) + +#define CON0_MT2712_RST_BAR BIT(24) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT2712_RST_BAR, \ + .fmax = MT2712_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _pcwbits, _pd_reg, _pd_shift, _tuner_reg, \ + _tuner_en_reg, _tuner_en_bit, _pcw_reg, \ + _pcw_shift, NULL) + +static const struct mtk_pll_div_table armca35pll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 1202500000 }, + { .div = 2, .freq = 500500000 }, + { .div = 3, .freq = 315250000 }, + { .div = 4, .freq = 157625000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table armca72pll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 994500000 }, + { .div = 2, .freq = 520000000 }, + { .div = 3, .freq = 315250000 }, + { .div = 4, .freq = 157625000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table mmpll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 1001000000 }, + { .div = 2, .freq = 601250000 }, + { .div = 3, .freq = 250250000 }, + { .div = 4, .freq = 125125000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0xf0000101, + HAVE_RST_BAR, 31, 0x0230, 4, 0, 0, 0, 0x0234, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0240, 0x024C, 0xfe000101, + HAVE_RST_BAR, 31, 0x0240, 4, 0, 0, 0, 0x0244, 0), + PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x0320, 0x032C, 0xc0000101, + 0, 31, 0x0320, 4, 0, 0, 0, 0x0324, 0), + PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x0280, 0x028C, 0x00000101, + 0, 31, 0x0280, 4, 0, 0, 0, 0x0284, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x0330, 0x0340, 0x00000101, + 0, 31, 0x0330, 4, 0x0338, 0x0014, 0, 0x0334, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0350, 0x0360, 0x00000101, + 0, 31, 0x0350, 4, 0x0358, 0x0014, 1, 0x0354, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0370, 0x037c, 0x00000101, + 0, 31, 0x0370, 4, 0, 0, 0, 0x0374, 0), + PLL(CLK_APMIXED_LVDSPLL2, "lvdspll2", 0x0390, 0x039C, 0x00000101, + 0, 31, 0x0390, 4, 0, 0, 0, 0x0394, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0270, 0x027C, 0x00000101, + 0, 31, 0x0270, 4, 0, 0, 0, 0x0274, 0), + PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x0410, 0x041C, 0x00000101, + 0, 31, 0x0410, 4, 0, 0, 0, 0x0414, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0290, 0x029C, 0xc0000101, + 0, 31, 0x0290, 4, 0, 0, 0, 0x0294, 0), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0250, 0x0260, 0x00000101, + 0, 31, 0x0250, 4, 0, 0, 0, 0x0254, 0, + mmpll_div_table), + PLL_B(CLK_APMIXED_ARMCA35PLL, "armca35pll", 0x0100, 0x0110, 0xf0000101, + HAVE_RST_BAR, 31, 0x0100, 4, 0, 0, 0, 0x0104, 0, + armca35pll_div_table), + PLL_B(CLK_APMIXED_ARMCA72PLL, "armca72pll", 0x0210, 0x0220, 0x00000101, + 0, 31, 0x0210, 4, 0, 0, 0, 0x0214, 0, + armca72pll_div_table), + PLL(CLK_APMIXED_ETHERPLL, "etherpll", 0x0300, 0x030C, 0xc0000101, + 0, 31, 0x0300, 4, 0, 0, 0, 0x0304, 0), +}; + +static int clk_mt2712_apmixed_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static struct clk_onecell_data *top_clk_data; + +static void clk_mt2712_top_init_early(struct device_node *node) +{ + int r, i; + + if (!top_clk_data) { + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + for (i = 0; i < CLK_TOP_NR_CLK; i++) + top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER); + } + + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} + +CLK_OF_DECLARE_DRIVER(mt2712_topckgen, "mediatek,mt2712-topckgen", + clk_mt2712_top_init_early); + +static int clk_mt2712_top_probe(struct platform_device *pdev) +{ + int r, i; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + if (!top_clk_data) { + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + } else { + for (i = 0; i < CLK_TOP_NR_CLK; i++) { + if (top_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER)) + top_clk_data->clks[i] = ERR_PTR(-ENOENT); + } + } + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + top_clk_data); + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt2712_clk_lock, top_clk_data); + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt2712_clk_lock, top_clk_data); + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + top_clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static int clk_mt2712_infra_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, 2, 0x30); + + return r; +} + +static int clk_mt2712_peri_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, 2, 0); + + return r; +} + +static int clk_mt2712_mcu_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); + + mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, + &mt2712_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712[] = { + { + .compatible = "mediatek,mt2712-apmixedsys", + .data = clk_mt2712_apmixed_probe, + }, { + .compatible = "mediatek,mt2712-topckgen", + .data = clk_mt2712_top_probe, + }, { + .compatible = "mediatek,mt2712-infracfg", + .data = clk_mt2712_infra_probe, + }, { + .compatible = "mediatek,mt2712-pericfg", + .data = clk_mt2712_peri_probe, + }, { + .compatible = "mediatek,mt2712-mcucfg", + .data = clk_mt2712_mcu_probe, + }, { + /* sentinel */ + } +}; + +static int clk_mt2712_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *); + int r; + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + r = clk_probe(pdev); + if (r != 0) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt2712_drv = { + .probe = clk_mt2712_probe, + .driver = { + .name = "clk-mt2712", + .owner = THIS_MODULE, + .of_match_table = of_match_clk_mt2712, + }, +}; + +static int __init clk_mt2712_init(void) +{ + return platform_driver_register(&clk_mt2712_drv); +} + +arch_initcall(clk_mt2712_init); diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index f5d6b70ce189..f48df75cc901 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -207,6 +207,8 @@ struct mtk_pll_data { uint32_t en_mask; uint32_t pd_reg; uint32_t tuner_reg; + uint32_t tuner_en_reg; + uint8_t tuner_en_bit; int pd_shift; unsigned int flags; const struct clk_ops *ops; diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index a409142e9346..3c546bae6955 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -47,6 +47,7 @@ struct mtk_clk_pll { void __iomem *pd_addr; void __iomem *pwr_addr; void __iomem *tuner_addr; + void __iomem *tuner_en_addr; void __iomem *pcw_addr; const struct mtk_pll_data *data; }; @@ -227,7 +228,10 @@ static int mtk_pll_prepare(struct clk_hw *hw) r |= pll->data->en_mask; writel(r, pll->base_addr + REG_CON0); - if (pll->tuner_addr) { + if (pll->tuner_en_addr) { + r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit); + writel(r, pll->tuner_en_addr); + } else if (pll->tuner_addr) { r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; writel(r, pll->tuner_addr); } @@ -254,7 +258,10 @@ static void mtk_pll_unprepare(struct clk_hw *hw) writel(r, pll->base_addr + REG_CON0); } - if (pll->tuner_addr) { + if (pll->tuner_en_addr) { + r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit); + writel(r, pll->tuner_en_addr); + } else if (pll->tuner_addr) { r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; writel(r, pll->tuner_addr); } @@ -297,6 +304,8 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, pll->pcw_addr = base + data->pcw_reg; if (data->tuner_reg) pll->tuner_addr = base + data->tuner_reg; + if (data->tuner_en_reg) + pll->tuner_en_addr = base + data->tuner_en_reg; pll->hw.init = &init; pll->data = data; -- GitLab From 5ef288d42aefef63f728116818a097b3caf000a5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 15 Sep 2017 21:28:30 +0200 Subject: [PATCH 1531/2898] clk: mediatek: mark mtk_infrasys_init_early __init On gcc-4.6, we get a harmless link-time warning: WARNING: vmlinux.o(.text.unlikely+0x196a0): Section mismatch in reference from the function mtk_infrasys_init_early() to the function .init.text:mtk_clk_register_cpumuxes() The function mtk_infrasys_init_early() references the function __init mtk_clk_register_cpumuxes(). This is often because mtk_infrasys_init_early lacks a __init annotation or the annotation of mtk_clk_register_cpumuxes is wrong. Newer compilers inline this function so they don't warn, but marking it __init is the right solution for all versions. Fixes: e9862118272a ("clk: mediatek: Add MT2701 clock support") Signed-off-by: Arnd Bergmann Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt2701.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index 9598889f972b..8e7f16fd87c9 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -750,7 +750,7 @@ static const struct mtk_fixed_factor infra_fixed_divs[] = { static struct clk_onecell_data *infra_clk_data; -static void mtk_infrasys_init_early(struct device_node *node) +static void __init mtk_infrasys_init_early(struct device_node *node) { int r, i; -- GitLab From 808ecf4ad087f80c2eee99af67549f05d5315694 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Thu, 5 Oct 2017 11:50:22 +0800 Subject: [PATCH 1532/2898] dt-bindings: clock: mediatek: document clk bindings for MediaTek MT7622 SoC This patch adds the binding documentation for apmixedsys, ethsys, hifsys, infracfg, pericfg, topckgen and audsys for MT7622. Signed-off-by: Chen Zhong Signed-off-by: Sean Wang Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../arm/mediatek/mediatek,apmixedsys.txt | 1 + .../bindings/arm/mediatek/mediatek,audsys.txt | 22 +++++++++++++++++++ .../bindings/arm/mediatek/mediatek,ethsys.txt | 1 + .../bindings/arm/mediatek/mediatek,hifsys.txt | 1 + .../arm/mediatek/mediatek,infracfg.txt | 1 + .../arm/mediatek/mediatek,pciesys.txt | 22 +++++++++++++++++++ .../arm/mediatek/mediatek,pericfg.txt | 1 + .../arm/mediatek/mediatek,sgmiisys.txt | 22 +++++++++++++++++++ .../arm/mediatek/mediatek,ssusbsys.txt | 22 +++++++++++++++++++ .../arm/mediatek/mediatek,topckgen.txt | 1 + 10 files changed, 94 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt index 19fc116346d6..b404d592ce58 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt @@ -9,6 +9,7 @@ Required Properties: - "mediatek,mt2701-apmixedsys" - "mediatek,mt2712-apmixedsys", "syscon" - "mediatek,mt6797-apmixedsys" + - "mediatek,mt7622-apmixedsys" - "mediatek,mt8135-apmixedsys" - "mediatek,mt8173-apmixedsys" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt new file mode 100644 index 000000000000..9b8f578d5e19 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt @@ -0,0 +1,22 @@ +MediaTek AUDSYS controller +============================ + +The MediaTek AUDSYS controller provides various clocks to the system. + +Required Properties: + +- compatible: Should be one of: + - "mediatek,mt7622-audsys", "syscon" +- #clock-cells: Must be 1 + +The AUDSYS controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +audsys: audsys@11220000 { + compatible = "mediatek,mt7622-audsys", "syscon"; + reg = <0 0x11220000 0 0x1000>; + #clock-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt index 768f3a5bc055..7aa3fa167668 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt @@ -7,6 +7,7 @@ Required Properties: - compatible: Should be: - "mediatek,mt2701-ethsys", "syscon" + - "mediatek,mt7622-ethsys", "syscon" - #clock-cells: Must be 1 The ethsys controller uses the common clk binding from diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt index beed7b594cea..f5629d64cef2 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt @@ -8,6 +8,7 @@ Required Properties: - compatible: Should be: - "mediatek,mt2701-hifsys", "syscon" + - "mediatek,mt7622-hifsys", "syscon" - #clock-cells: Must be 1 The hifsys controller uses the common clk binding from diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt index a3430cd96d0f..566f153f9f83 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt @@ -10,6 +10,7 @@ Required Properties: - "mediatek,mt2701-infracfg", "syscon" - "mediatek,mt2712-infracfg", "syscon" - "mediatek,mt6797-infracfg", "syscon" + - "mediatek,mt7622-infracfg", "syscon" - "mediatek,mt8135-infracfg", "syscon" - "mediatek,mt8173-infracfg", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt new file mode 100644 index 000000000000..d5d5f1227665 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt @@ -0,0 +1,22 @@ +MediaTek PCIESYS controller +============================ + +The MediaTek PCIESYS controller provides various clocks to the system. + +Required Properties: + +- compatible: Should be: + - "mediatek,mt7622-pciesys", "syscon" +- #clock-cells: Must be 1 + +The PCIESYS controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +pciesys: pciesys@1a100800 { + compatible = "mediatek,mt7622-pciesys", "syscon"; + reg = <0 0x1a100800 0 0x1000>; + #clock-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt index d9f092eb3550..fb58ca8c2770 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt @@ -9,6 +9,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2701-pericfg", "syscon" - "mediatek,mt2712-pericfg", "syscon" + - "mediatek,mt7622-pericfg", "syscon" - "mediatek,mt8135-pericfg", "syscon" - "mediatek,mt8173-pericfg", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt new file mode 100644 index 000000000000..d113b8e741f3 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt @@ -0,0 +1,22 @@ +MediaTek SGMIISYS controller +============================ + +The MediaTek SGMIISYS controller provides various clocks to the system. + +Required Properties: + +- compatible: Should be: + - "mediatek,mt7622-sgmiisys", "syscon" +- #clock-cells: Must be 1 + +The SGMIISYS controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +sgmiisys: sgmiisys@1b128000 { + compatible = "mediatek,mt7622-sgmiisys", "syscon"; + reg = <0 0x1b128000 0 0x1000>; + #clock-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt new file mode 100644 index 000000000000..00760019da00 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt @@ -0,0 +1,22 @@ +MediaTek SSUSBSYS controller +============================ + +The MediaTek SSUSBSYS controller provides various clocks to the system. + +Required Properties: + +- compatible: Should be: + - "mediatek,mt7622-ssusbsys", "syscon" +- #clock-cells: Must be 1 + +The SSUSBSYS controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +ssusbsys: ssusbsys@1a000000 { + compatible = "mediatek,mt7622-ssusbsys", "syscon"; + reg = <0 0x1a000000 0 0x1000>; + #clock-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt index 2024fc909d69..24014a7e2332 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt @@ -9,6 +9,7 @@ Required Properties: - "mediatek,mt2701-topckgen" - "mediatek,mt2712-topckgen", "syscon" - "mediatek,mt6797-topckgen" + - "mediatek,mt7622-topckgen" - "mediatek,mt8135-topckgen" - "mediatek,mt8173-topckgen" - #clock-cells: Must be 1 -- GitLab From c955bf3998efa3355790a4d8c82874582f1bc727 Mon Sep 17 00:00:00 2001 From: Chen Zhong Date: Thu, 5 Oct 2017 11:50:23 +0800 Subject: [PATCH 1533/2898] clk: mediatek: add the option for determining PLL source clock Since the previous setup always sets the PLL using crystal 26MHz, this doesn't always happen in every MediaTek platform. So the patch added flexibility for assigning extra member for determining the PLL source clock. Signed-off-by: Chen Zhong Signed-off-by: Sean Wang Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mtk.h | 1 + drivers/clk/mediatek/clk-pll.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index f48df75cc901..f10250dcece4 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -218,6 +218,7 @@ struct mtk_pll_data { uint32_t pcw_reg; int pcw_shift; const struct mtk_pll_div_table *div_table; + const char *parent_name; }; void mtk_clk_register_plls(struct device_node *node, diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index 3c546bae6955..f54e4015b0b1 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -312,7 +312,10 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, init.name = data->name; init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; init.ops = &mtk_pll_ops; - init.parent_names = &parent_name; + if (data->parent_name) + init.parent_names = &data->parent_name; + else + init.parent_names = &parent_name; init.num_parents = 1; clk = clk_register(NULL, &pll->hw); -- GitLab From bda921fad518b4d5d2249d41432025ce5b368173 Mon Sep 17 00:00:00 2001 From: Chen Zhong Date: Thu, 5 Oct 2017 11:50:25 +0800 Subject: [PATCH 1534/2898] clk: mediatek: add clocks dt-bindings required header for MT7622 SoC Add the required header for the entire clocks dt-bindings exported from topckgen, apmixedsys, infracfg, pericfg, ethsys, pciesys, ssusbsys and audsys which could be found on MT7622 SoC. Signed-off-by: Chen Zhong Signed-off-by: Sean Wang Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/mt7622-clk.h | 289 +++++++++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 include/dt-bindings/clock/mt7622-clk.h diff --git a/include/dt-bindings/clock/mt7622-clk.h b/include/dt-bindings/clock/mt7622-clk.h new file mode 100644 index 000000000000..3e514ed51d15 --- /dev/null +++ b/include/dt-bindings/clock/mt7622-clk.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_CLK_MT7622_H +#define _DT_BINDINGS_CLK_MT7622_H + +/* TOPCKGEN */ + +#define CLK_TOP_TO_U2_PHY 0 +#define CLK_TOP_TO_U2_PHY_1P 1 +#define CLK_TOP_PCIE0_PIPE_EN 2 +#define CLK_TOP_PCIE1_PIPE_EN 3 +#define CLK_TOP_SSUSB_TX250M 4 +#define CLK_TOP_SSUSB_EQ_RX250M 5 +#define CLK_TOP_SSUSB_CDR_REF 6 +#define CLK_TOP_SSUSB_CDR_FB 7 +#define CLK_TOP_SATA_ASIC 8 +#define CLK_TOP_SATA_RBC 9 +#define CLK_TOP_TO_USB3_SYS 10 +#define CLK_TOP_P1_1MHZ 11 +#define CLK_TOP_4MHZ 12 +#define CLK_TOP_P0_1MHZ 13 +#define CLK_TOP_TXCLK_SRC_PRE 14 +#define CLK_TOP_RTC 15 +#define CLK_TOP_MEMPLL 16 +#define CLK_TOP_DMPLL 17 +#define CLK_TOP_SYSPLL_D2 18 +#define CLK_TOP_SYSPLL1_D2 19 +#define CLK_TOP_SYSPLL1_D4 20 +#define CLK_TOP_SYSPLL1_D8 21 +#define CLK_TOP_SYSPLL2_D4 22 +#define CLK_TOP_SYSPLL2_D8 23 +#define CLK_TOP_SYSPLL_D5 24 +#define CLK_TOP_SYSPLL3_D2 25 +#define CLK_TOP_SYSPLL3_D4 26 +#define CLK_TOP_SYSPLL4_D2 27 +#define CLK_TOP_SYSPLL4_D4 28 +#define CLK_TOP_SYSPLL4_D16 29 +#define CLK_TOP_UNIVPLL 30 +#define CLK_TOP_UNIVPLL_D2 31 +#define CLK_TOP_UNIVPLL1_D2 32 +#define CLK_TOP_UNIVPLL1_D4 33 +#define CLK_TOP_UNIVPLL1_D8 34 +#define CLK_TOP_UNIVPLL1_D16 35 +#define CLK_TOP_UNIVPLL2_D2 36 +#define CLK_TOP_UNIVPLL2_D4 37 +#define CLK_TOP_UNIVPLL2_D8 38 +#define CLK_TOP_UNIVPLL2_D16 39 +#define CLK_TOP_UNIVPLL_D5 40 +#define CLK_TOP_UNIVPLL3_D2 41 +#define CLK_TOP_UNIVPLL3_D4 42 +#define CLK_TOP_UNIVPLL3_D16 43 +#define CLK_TOP_UNIVPLL_D7 44 +#define CLK_TOP_UNIVPLL_D80_D4 45 +#define CLK_TOP_UNIV48M 46 +#define CLK_TOP_SGMIIPLL 47 +#define CLK_TOP_SGMIIPLL_D2 48 +#define CLK_TOP_AUD1PLL 49 +#define CLK_TOP_AUD2PLL 50 +#define CLK_TOP_AUD_I2S2_MCK 51 +#define CLK_TOP_TO_USB3_REF 52 +#define CLK_TOP_PCIE1_MAC_EN 53 +#define CLK_TOP_PCIE0_MAC_EN 54 +#define CLK_TOP_ETH_500M 55 +#define CLK_TOP_AXI_SEL 56 +#define CLK_TOP_MEM_SEL 57 +#define CLK_TOP_DDRPHYCFG_SEL 58 +#define CLK_TOP_ETH_SEL 59 +#define CLK_TOP_PWM_SEL 60 +#define CLK_TOP_F10M_REF_SEL 61 +#define CLK_TOP_NFI_INFRA_SEL 62 +#define CLK_TOP_FLASH_SEL 63 +#define CLK_TOP_UART_SEL 64 +#define CLK_TOP_SPI0_SEL 65 +#define CLK_TOP_SPI1_SEL 66 +#define CLK_TOP_MSDC50_0_SEL 67 +#define CLK_TOP_MSDC30_0_SEL 68 +#define CLK_TOP_MSDC30_1_SEL 69 +#define CLK_TOP_A1SYS_HP_SEL 70 +#define CLK_TOP_A2SYS_HP_SEL 71 +#define CLK_TOP_INTDIR_SEL 72 +#define CLK_TOP_AUD_INTBUS_SEL 73 +#define CLK_TOP_PMICSPI_SEL 74 +#define CLK_TOP_SCP_SEL 75 +#define CLK_TOP_ATB_SEL 76 +#define CLK_TOP_HIF_SEL 77 +#define CLK_TOP_AUDIO_SEL 78 +#define CLK_TOP_U2_SEL 79 +#define CLK_TOP_AUD1_SEL 80 +#define CLK_TOP_AUD2_SEL 81 +#define CLK_TOP_IRRX_SEL 82 +#define CLK_TOP_IRTX_SEL 83 +#define CLK_TOP_ASM_L_SEL 84 +#define CLK_TOP_ASM_M_SEL 85 +#define CLK_TOP_ASM_H_SEL 86 +#define CLK_TOP_APLL1_SEL 87 +#define CLK_TOP_APLL2_SEL 88 +#define CLK_TOP_I2S0_MCK_SEL 89 +#define CLK_TOP_I2S1_MCK_SEL 90 +#define CLK_TOP_I2S2_MCK_SEL 91 +#define CLK_TOP_I2S3_MCK_SEL 92 +#define CLK_TOP_APLL1_DIV 93 +#define CLK_TOP_APLL2_DIV 94 +#define CLK_TOP_I2S0_MCK_DIV 95 +#define CLK_TOP_I2S1_MCK_DIV 96 +#define CLK_TOP_I2S2_MCK_DIV 97 +#define CLK_TOP_I2S3_MCK_DIV 98 +#define CLK_TOP_A1SYS_HP_DIV 99 +#define CLK_TOP_A2SYS_HP_DIV 100 +#define CLK_TOP_APLL1_DIV_PD 101 +#define CLK_TOP_APLL2_DIV_PD 102 +#define CLK_TOP_I2S0_MCK_DIV_PD 103 +#define CLK_TOP_I2S1_MCK_DIV_PD 104 +#define CLK_TOP_I2S2_MCK_DIV_PD 105 +#define CLK_TOP_I2S3_MCK_DIV_PD 106 +#define CLK_TOP_A1SYS_HP_DIV_PD 107 +#define CLK_TOP_A2SYS_HP_DIV_PD 108 +#define CLK_TOP_NR_CLK 109 + +/* INFRACFG */ + +#define CLK_INFRA_MUX1_SEL 0 +#define CLK_INFRA_DBGCLK_PD 1 +#define CLK_INFRA_AUDIO_PD 2 +#define CLK_INFRA_IRRX_PD 3 +#define CLK_INFRA_APXGPT_PD 4 +#define CLK_INFRA_PMIC_PD 5 +#define CLK_INFRA_TRNG 6 +#define CLK_INFRA_NR_CLK 7 + +/* PERICFG */ + +#define CLK_PERIBUS_SEL 0 +#define CLK_PERI_THERM_PD 1 +#define CLK_PERI_PWM1_PD 2 +#define CLK_PERI_PWM2_PD 3 +#define CLK_PERI_PWM3_PD 4 +#define CLK_PERI_PWM4_PD 5 +#define CLK_PERI_PWM5_PD 6 +#define CLK_PERI_PWM6_PD 7 +#define CLK_PERI_PWM7_PD 8 +#define CLK_PERI_PWM_PD 9 +#define CLK_PERI_AP_DMA_PD 10 +#define CLK_PERI_MSDC30_0_PD 11 +#define CLK_PERI_MSDC30_1_PD 12 +#define CLK_PERI_UART0_PD 13 +#define CLK_PERI_UART1_PD 14 +#define CLK_PERI_UART2_PD 15 +#define CLK_PERI_UART3_PD 16 +#define CLK_PERI_UART4_PD 17 +#define CLK_PERI_BTIF_PD 18 +#define CLK_PERI_I2C0_PD 19 +#define CLK_PERI_I2C1_PD 20 +#define CLK_PERI_I2C2_PD 21 +#define CLK_PERI_SPI1_PD 22 +#define CLK_PERI_AUXADC_PD 23 +#define CLK_PERI_SPI0_PD 24 +#define CLK_PERI_SNFI_PD 25 +#define CLK_PERI_NFI_PD 26 +#define CLK_PERI_NFIECC_PD 27 +#define CLK_PERI_FLASH_PD 28 +#define CLK_PERI_IRTX_PD 29 +#define CLK_PERI_NR_CLK 30 + +/* APMIXEDSYS */ + +#define CLK_APMIXED_ARMPLL 0 +#define CLK_APMIXED_MAINPLL 1 +#define CLK_APMIXED_UNIV2PLL 2 +#define CLK_APMIXED_ETH1PLL 3 +#define CLK_APMIXED_ETH2PLL 4 +#define CLK_APMIXED_AUD1PLL 5 +#define CLK_APMIXED_AUD2PLL 6 +#define CLK_APMIXED_TRGPLL 7 +#define CLK_APMIXED_SGMIPLL 8 +#define CLK_APMIXED_MAIN_CORE_EN 9 +#define CLK_APMIXED_NR_CLK 10 + +/* AUDIOSYS */ + +#define CLK_AUDIO_AFE 0 +#define CLK_AUDIO_HDMI 1 +#define CLK_AUDIO_SPDF 2 +#define CLK_AUDIO_APLL 3 +#define CLK_AUDIO_I2SIN1 4 +#define CLK_AUDIO_I2SIN2 5 +#define CLK_AUDIO_I2SIN3 6 +#define CLK_AUDIO_I2SIN4 7 +#define CLK_AUDIO_I2SO1 8 +#define CLK_AUDIO_I2SO2 9 +#define CLK_AUDIO_I2SO3 10 +#define CLK_AUDIO_I2SO4 11 +#define CLK_AUDIO_ASRCI1 12 +#define CLK_AUDIO_ASRCI2 13 +#define CLK_AUDIO_ASRCO1 14 +#define CLK_AUDIO_ASRCO2 15 +#define CLK_AUDIO_INTDIR 16 +#define CLK_AUDIO_A1SYS 17 +#define CLK_AUDIO_A2SYS 18 +#define CLK_AUDIO_UL1 19 +#define CLK_AUDIO_UL2 20 +#define CLK_AUDIO_UL3 21 +#define CLK_AUDIO_UL4 22 +#define CLK_AUDIO_UL5 23 +#define CLK_AUDIO_UL6 24 +#define CLK_AUDIO_DL1 25 +#define CLK_AUDIO_DL2 26 +#define CLK_AUDIO_DL3 27 +#define CLK_AUDIO_DL4 28 +#define CLK_AUDIO_DL5 29 +#define CLK_AUDIO_DL6 30 +#define CLK_AUDIO_DLMCH 31 +#define CLK_AUDIO_ARB1 32 +#define CLK_AUDIO_AWB 33 +#define CLK_AUDIO_AWB2 34 +#define CLK_AUDIO_DAI 35 +#define CLK_AUDIO_MOD 36 +#define CLK_AUDIO_ASRCI3 37 +#define CLK_AUDIO_ASRCI4 38 +#define CLK_AUDIO_ASRCO3 39 +#define CLK_AUDIO_ASRCO4 40 +#define CLK_AUDIO_MEM_ASRC1 41 +#define CLK_AUDIO_MEM_ASRC2 42 +#define CLK_AUDIO_MEM_ASRC3 43 +#define CLK_AUDIO_MEM_ASRC4 44 +#define CLK_AUDIO_MEM_ASRC5 45 +#define CLK_AUDIO_NR_CLK 46 + +/* SSUSBSYS */ + +#define CLK_SSUSB_U2_PHY_1P_EN 0 +#define CLK_SSUSB_U2_PHY_EN 1 +#define CLK_SSUSB_REF_EN 2 +#define CLK_SSUSB_SYS_EN 3 +#define CLK_SSUSB_MCU_EN 4 +#define CLK_SSUSB_DMA_EN 5 +#define CLK_SSUSB_NR_CLK 6 + +/* PCIESYS */ + +#define CLK_PCIE_P1_AUX_EN 0 +#define CLK_PCIE_P1_OBFF_EN 1 +#define CLK_PCIE_P1_AHB_EN 2 +#define CLK_PCIE_P1_AXI_EN 3 +#define CLK_PCIE_P1_MAC_EN 4 +#define CLK_PCIE_P1_PIPE_EN 5 +#define CLK_PCIE_P0_AUX_EN 6 +#define CLK_PCIE_P0_OBFF_EN 7 +#define CLK_PCIE_P0_AHB_EN 8 +#define CLK_PCIE_P0_AXI_EN 9 +#define CLK_PCIE_P0_MAC_EN 10 +#define CLK_PCIE_P0_PIPE_EN 11 +#define CLK_SATA_AHB_EN 12 +#define CLK_SATA_AXI_EN 13 +#define CLK_SATA_ASIC_EN 14 +#define CLK_SATA_RBC_EN 15 +#define CLK_SATA_PM_EN 16 +#define CLK_PCIE_NR_CLK 17 + +/* ETHSYS */ + +#define CLK_ETH_HSDMA_EN 0 +#define CLK_ETH_ESW_EN 1 +#define CLK_ETH_GP2_EN 2 +#define CLK_ETH_GP1_EN 3 +#define CLK_ETH_GP0_EN 4 +#define CLK_ETH_NR_CLK 5 + +/* SGMIISYS */ + +#define CLK_SGMII_TX250M_EN 0 +#define CLK_SGMII_RX250M_EN 1 +#define CLK_SGMII_CDR_REF 2 +#define CLK_SGMII_CDR_FB 3 +#define CLK_SGMII_NR_CLK 4 + +#endif /* _DT_BINDINGS_CLK_MT7622_H */ + -- GitLab From 2fc0a509e4ee858a450f28a4efb430835004dd70 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Thu, 5 Oct 2017 11:50:24 +0800 Subject: [PATCH 1535/2898] clk: mediatek: add clock support for MT7622 SoC Add all supported clocks exported from every susbystem found on MT7622 SoC such as topckgen, apmixedsys, infracfg, pericfg , pciessys, ssusbsys, ethsys and audsys. Signed-off-by: Chen Zhong Signed-off-by: Sean Wang Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/Kconfig | 30 + drivers/clk/mediatek/Makefile | 4 + drivers/clk/mediatek/clk-mt7622-aud.c | 195 +++++++ drivers/clk/mediatek/clk-mt7622-eth.c | 156 ++++++ drivers/clk/mediatek/clk-mt7622-hif.c | 169 ++++++ drivers/clk/mediatek/clk-mt7622.c | 780 ++++++++++++++++++++++++++ 6 files changed, 1334 insertions(+) create mode 100644 drivers/clk/mediatek/clk-mt7622-aud.c create mode 100644 drivers/clk/mediatek/clk-mt7622-eth.c create mode 100644 drivers/clk/mediatek/clk-mt7622-hif.c create mode 100644 drivers/clk/mediatek/clk-mt7622.c diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 300dbb551bf7..59dc0aad553c 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -132,6 +132,36 @@ config COMMON_CLK_MT6797_VENCSYS ---help--- This driver supports Mediatek MT6797 vencsys clocks. +config COMMON_CLK_MT7622 + bool "Clock driver for MediaTek MT7622" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + ---help--- + This driver supports MediaTek MT7622 basic clocks and clocks + required for various periperals found on MediaTek. + +config COMMON_CLK_MT7622_ETHSYS + bool "Clock driver for MediaTek MT7622 ETHSYS" + depends on COMMON_CLK_MT7622 + ---help--- + This driver add support for clocks for Ethernet and SGMII + required on MediaTek MT7622 SoC. + +config COMMON_CLK_MT7622_HIFSYS + bool "Clock driver for MediaTek MT7622 HIFSYS" + depends on COMMON_CLK_MT7622 + ---help--- + This driver supports MediaTek MT7622 HIFSYS clocks providing + to PCI-E and USB. + +config COMMON_CLK_MT7622_AUDSYS + bool "Clock driver for MediaTek MT7622 AUDSYS" + depends on COMMON_CLK_MT7622 + ---help--- + This driver supports MediaTek MT7622 AUDSYS clocks providing + to audio consumers such as I2S and TDM. + config COMMON_CLK_MT8135 bool "Clock driver for Mediatek MT8135" depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index a4e5c47c73a4..de8c3d0bb4ca 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -20,5 +20,9 @@ obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o +obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622.o +obj-$(CONFIG_COMMON_CLK_MT7622_ETHSYS) += clk-mt7622-eth.o +obj-$(CONFIG_COMMON_CLK_MT7622_HIFSYS) += clk-mt7622-hif.o +obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c new file mode 100644 index 000000000000..fad7d9fc53ba --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-aud.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * Sean Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define GATE_AUDIO0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO3(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio3_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate_regs audio0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs audio1_cg_regs = { + .set_ofs = 0x10, + .clr_ofs = 0x10, + .sta_ofs = 0x10, +}; + +static const struct mtk_gate_regs audio2_cg_regs = { + .set_ofs = 0x14, + .clr_ofs = 0x14, + .sta_ofs = 0x14, +}; + +static const struct mtk_gate_regs audio3_cg_regs = { + .set_ofs = 0x634, + .clr_ofs = 0x634, + .sta_ofs = 0x634, +}; + +static const struct mtk_gate audio_clks[] = { + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUDIO_AFE, "audio_afe", "rtc", 2), + GATE_AUDIO0(CLK_AUDIO_HDMI, "audio_hdmi", "apll1_ck_sel", 20), + GATE_AUDIO0(CLK_AUDIO_SPDF, "audio_spdf", "apll1_ck_sel", 21), + GATE_AUDIO0(CLK_AUDIO_APLL, "audio_apll", "apll1_ck_sel", 23), + /* AUDIO1 */ + GATE_AUDIO1(CLK_AUDIO_I2SIN1, "audio_i2sin1", "a1sys_hp_sel", 0), + GATE_AUDIO1(CLK_AUDIO_I2SIN2, "audio_i2sin2", "a1sys_hp_sel", 1), + GATE_AUDIO1(CLK_AUDIO_I2SIN3, "audio_i2sin3", "a1sys_hp_sel", 2), + GATE_AUDIO1(CLK_AUDIO_I2SIN4, "audio_i2sin4", "a1sys_hp_sel", 3), + GATE_AUDIO1(CLK_AUDIO_I2SO1, "audio_i2so1", "a1sys_hp_sel", 6), + GATE_AUDIO1(CLK_AUDIO_I2SO2, "audio_i2so2", "a1sys_hp_sel", 7), + GATE_AUDIO1(CLK_AUDIO_I2SO3, "audio_i2so3", "a1sys_hp_sel", 8), + GATE_AUDIO1(CLK_AUDIO_I2SO4, "audio_i2so4", "a1sys_hp_sel", 9), + GATE_AUDIO1(CLK_AUDIO_ASRCI1, "audio_asrci1", "asm_h_sel", 12), + GATE_AUDIO1(CLK_AUDIO_ASRCI2, "audio_asrci2", "asm_h_sel", 13), + GATE_AUDIO1(CLK_AUDIO_ASRCO1, "audio_asrco1", "asm_h_sel", 14), + GATE_AUDIO1(CLK_AUDIO_ASRCO2, "audio_asrco2", "asm_h_sel", 15), + GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20), + GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21), + GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22), + /* AUDIO2 */ + GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0), + GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1), + GATE_AUDIO2(CLK_AUDIO_UL3, "audio_ul3", "a1sys_hp_sel", 2), + GATE_AUDIO2(CLK_AUDIO_UL4, "audio_ul4", "a1sys_hp_sel", 3), + GATE_AUDIO2(CLK_AUDIO_UL5, "audio_ul5", "a1sys_hp_sel", 4), + GATE_AUDIO2(CLK_AUDIO_UL6, "audio_ul6", "a1sys_hp_sel", 5), + GATE_AUDIO2(CLK_AUDIO_DL1, "audio_dl1", "a1sys_hp_sel", 6), + GATE_AUDIO2(CLK_AUDIO_DL2, "audio_dl2", "a1sys_hp_sel", 7), + GATE_AUDIO2(CLK_AUDIO_DL3, "audio_dl3", "a1sys_hp_sel", 8), + GATE_AUDIO2(CLK_AUDIO_DL4, "audio_dl4", "a1sys_hp_sel", 9), + GATE_AUDIO2(CLK_AUDIO_DL5, "audio_dl5", "a1sys_hp_sel", 10), + GATE_AUDIO2(CLK_AUDIO_DL6, "audio_dl6", "a1sys_hp_sel", 11), + GATE_AUDIO2(CLK_AUDIO_DLMCH, "audio_dlmch", "a1sys_hp_sel", 12), + GATE_AUDIO2(CLK_AUDIO_ARB1, "audio_arb1", "a1sys_hp_sel", 13), + GATE_AUDIO2(CLK_AUDIO_AWB, "audio_awb", "a1sys_hp_sel", 14), + GATE_AUDIO2(CLK_AUDIO_AWB2, "audio_awb2", "a1sys_hp_sel", 15), + GATE_AUDIO2(CLK_AUDIO_DAI, "audio_dai", "a1sys_hp_sel", 16), + GATE_AUDIO2(CLK_AUDIO_MOD, "audio_mod", "a1sys_hp_sel", 17), + /* AUDIO3 */ + GATE_AUDIO3(CLK_AUDIO_ASRCI3, "audio_asrci3", "asm_h_sel", 2), + GATE_AUDIO3(CLK_AUDIO_ASRCI4, "audio_asrci4", "asm_h_sel", 3), + GATE_AUDIO3(CLK_AUDIO_ASRCO3, "audio_asrco3", "asm_h_sel", 6), + GATE_AUDIO3(CLK_AUDIO_ASRCO4, "audio_asrco4", "asm_h_sel", 7), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), +}; + +static int clk_mt7622_audiosys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); + + mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt7622_aud[] = { + { + .compatible = "mediatek,mt7622-audsys", + .data = clk_mt7622_audiosys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_aud_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_aud_drv = { + .probe = clk_mt7622_aud_probe, + .driver = { + .name = "clk-mt7622-aud", + .of_match_table = of_match_clk_mt7622_aud, + }, +}; + +builtin_platform_driver(clk_mt7622_aud_drv); diff --git a/drivers/clk/mediatek/clk-mt7622-eth.c b/drivers/clk/mediatek/clk-mt7622-eth.c new file mode 100644 index 000000000000..6328127bbb3c --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-eth.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * Sean Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define GATE_ETH(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = ð_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate_regs eth_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate eth_clks[] = { + GATE_ETH(CLK_ETH_HSDMA_EN, "eth_hsdma_en", "eth_sel", 5), + GATE_ETH(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 6), + GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 7), + GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 8), + GATE_ETH(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 9), +}; + +static const struct mtk_gate_regs sgmii_cg_regs = { + .set_ofs = 0xE4, + .clr_ofs = 0xE4, + .sta_ofs = 0xE4, +}; + +#define GATE_SGMII(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &sgmii_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate sgmii_clks[] = { + GATE_SGMII(CLK_SGMII_TX250M_EN, "sgmii_tx250m_en", + "ssusb_tx250m", 2), + GATE_SGMII(CLK_SGMII_RX250M_EN, "sgmii_rx250m_en", + "ssusb_eq_rx250m", 3), + GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref", + "ssusb_cdr_ref", 4), + GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb", + "ssusb_cdr_fb", 5), +}; + +static int clk_mt7622_ethsys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); + + mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller(node, 1, 0x34); + + return r; +} + +static int clk_mt7622_sgmiisys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); + + mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt7622_eth[] = { + { + .compatible = "mediatek,mt7622-ethsys", + .data = clk_mt7622_ethsys_init, + }, { + .compatible = "mediatek,mt7622-sgmiisys", + .data = clk_mt7622_sgmiisys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_eth_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_eth_drv = { + .probe = clk_mt7622_eth_probe, + .driver = { + .name = "clk-mt7622-eth", + .of_match_table = of_match_clk_mt7622_eth, + }, +}; + +builtin_platform_driver(clk_mt7622_eth_drv); diff --git a/drivers/clk/mediatek/clk-mt7622-hif.c b/drivers/clk/mediatek/clk-mt7622-hif.c new file mode 100644 index 000000000000..a6e8534276c6 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-hif.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * Sean Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +#define GATE_PCIE(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &pcie_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +#define GATE_SSUSB(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &ssusb_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate_regs pcie_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate_regs ssusb_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate ssusb_clks[] = { + GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p", + "to_u2_phy_1p", 0), + GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 1), + GATE_SSUSB(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 5), + GATE_SSUSB(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 6), + GATE_SSUSB(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "axi_sel", 7), + GATE_SSUSB(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "hif_sel", 8), +}; + +static const struct mtk_gate pcie_clks[] = { + GATE_PCIE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 12), + GATE_PCIE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 13), + GATE_PCIE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "axi_sel", 14), + GATE_PCIE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "hif_sel", 15), + GATE_PCIE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 16), + GATE_PCIE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 17), + GATE_PCIE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 18), + GATE_PCIE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 19), + GATE_PCIE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "axi_sel", 20), + GATE_PCIE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "hif_sel", 21), + GATE_PCIE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 22), + GATE_PCIE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 23), + GATE_PCIE(CLK_SATA_AHB_EN, "sata_ahb_en", "axi_sel", 26), + GATE_PCIE(CLK_SATA_AXI_EN, "sata_axi_en", "hif_sel", 27), + GATE_PCIE(CLK_SATA_ASIC_EN, "sata_asic_en", "sata_asic", 28), + GATE_PCIE(CLK_SATA_RBC_EN, "sata_rbc_en", "sata_rbc", 29), + GATE_PCIE(CLK_SATA_PM_EN, "sata_pm_en", "univpll2_d4", 30), +}; + +static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); + + mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller(node, 1, 0x34); + + return r; +} + +static int clk_mt7622_pciesys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); + + mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller(node, 1, 0x34); + + return r; +} + +static const struct of_device_id of_match_clk_mt7622_hif[] = { + { + .compatible = "mediatek,mt7622-pciesys", + .data = clk_mt7622_pciesys_init, + }, { + .compatible = "mediatek,mt7622-ssusbsys", + .data = clk_mt7622_ssusbsys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_hif_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_hif_drv = { + .probe = clk_mt7622_hif_probe, + .driver = { + .name = "clk-mt7622-hif", + .of_match_table = of_match_clk_mt7622_hif, + }, +}; + +builtin_platform_driver(clk_mt7622_hif_drv); diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c new file mode 100644 index 000000000000..92f7e32770c6 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong + * Sean Wang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-cpumux.h" + +#include +#include /* for consumer */ + +#define MT7622_PLL_FMAX (2500UL * MHZ) +#define CON0_MT7622_RST_BAR BIT(27) + +#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table, _parent_name) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT7622_RST_BAR, \ + .fmax = MT7622_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + .parent_name = _parent_name, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL, "clkxtal") + +#define GATE_APMIXED(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &apmixed_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +#define GATE_INFRA(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &infra_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_TOP1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_PERI0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static DEFINE_SPINLOCK(mt7622_clk_lock); + +static const char * const infra_mux1_parents[] = { + "clkxtal", + "armpll", + "main_core_en", + "armpll" +}; + +static const char * const axi_parents[] = { + "clkxtal", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "univpll_d7" +}; + +static const char * const mem_parents[] = { + "clkxtal", + "dmpll_ck" +}; + +static const char * const ddrphycfg_parents[] = { + "clkxtal", + "syspll1_d8" +}; + +static const char * const eth_parents[] = { + "clkxtal", + "syspll1_d2", + "univpll1_d2", + "syspll1_d4", + "univpll_d5", + "clk_null", + "univpll_d7" +}; + +static const char * const pwm_parents[] = { + "clkxtal", + "univpll2_d4" +}; + +static const char * const f10m_ref_parents[] = { + "clkxtal", + "syspll4_d16" +}; + +static const char * const nfi_infra_parents[] = { + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "univpll2_d8", + "syspll1_d8", + "univpll1_d8", + "syspll4_d2", + "univpll2_d4", + "univpll3_d2", + "syspll1_d4" +}; + +static const char * const flash_parents[] = { + "clkxtal", + "univpll_d80_d4", + "syspll2_d8", + "syspll3_d4", + "univpll3_d4", + "univpll1_d8", + "syspll2_d4", + "univpll2_d4" +}; + +static const char * const uart_parents[] = { + "clkxtal", + "univpll2_d8" +}; + +static const char * const spi0_parents[] = { + "clkxtal", + "syspll3_d2", + "clkxtal", + "syspll2_d4", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8", + "clkxtal" +}; + +static const char * const spi1_parents[] = { + "clkxtal", + "syspll3_d2", + "clkxtal", + "syspll4_d4", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8", + "clkxtal" +}; + +static const char * const msdc30_0_parents[] = { + "clkxtal", + "univpll2_d16", + "univ48m" +}; + +static const char * const a1sys_hp_parents[] = { + "clkxtal", + "aud1pll_ck", + "aud2pll_ck", + "clkxtal" +}; + +static const char * const intdir_parents[] = { + "clkxtal", + "syspll_d2", + "univpll_d2", + "sgmiipll_ck" +}; + +static const char * const aud_intbus_parents[] = { + "clkxtal", + "syspll1_d4", + "syspll4_d2", + "syspll3_d2" +}; + +static const char * const pmicspi_parents[] = { + "clkxtal", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "univpll2_d16" +}; + +static const char * const atb_parents[] = { + "clkxtal", + "syspll1_d2", + "syspll_d5" +}; + +static const char * const audio_parents[] = { + "clkxtal", + "syspll3_d4", + "syspll4_d4", + "univpll1_d16" +}; + +static const char * const usb20_parents[] = { + "clkxtal", + "univpll3_d4", + "syspll1_d8", + "clkxtal" +}; + +static const char * const aud1_parents[] = { + "clkxtal", + "aud1pll_ck" +}; + +static const char * const aud2_parents[] = { + "clkxtal", + "aud2pll_ck" +}; + +static const char * const asm_l_parents[] = { + "clkxtal", + "syspll_d5", + "univpll2_d2", + "univpll2_d4" +}; + +static const char * const apll1_ck_parents[] = { + "aud1_sel", + "aud2_sel" +}; + +static const char * const peribus_ck_parents[] = { + "syspll1_d8", + "syspll1_d4" +}; + +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x8, + .sta_ofs = 0x8, +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x48, +}; + +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0x120, + .clr_ofs = 0x120, + .sta_ofs = 0x120, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x128, + .clr_ofs = 0x128, + .sta_ofs = 0x128, +}; + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x10, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0xC, + .clr_ofs = 0x14, + .sta_ofs = 0x1C, +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, + PLL_AO, 21, 0x0204, 24, 0, 0x0204, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0x00000001, + HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0x00000001, + HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14), + PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0x00000001, + 0, 21, 0x0300, 1, 0, 0x0304, 0), + PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0x00000001, + 0, 21, 0x0314, 1, 0, 0x0318, 0), + PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0x00000001, + 0, 31, 0x0324, 1, 0, 0x0328, 0), + PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0x00000001, + 0, 31, 0x0334, 1, 0, 0x0338, 0), + PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0x00000001, + 0, 21, 0x0344, 1, 0, 0x0348, 0), + PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0x00000001, + 0, 21, 0x0358, 1, 0, 0x035C, 0), +}; + +static const struct mtk_gate apmixed_clks[] = { + GATE_APMIXED(CLK_APMIXED_MAIN_CORE_EN, "main_core_en", "mainpll", 5), +}; + +static const struct mtk_gate infra_clks[] = { + GATE_INFRA(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "axi_sel", 0), + GATE_INFRA(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 2), + GATE_INFRA(CLK_INFRA_AUDIO_PD, "infra_audio_pd", "aud_intbus_sel", 5), + GATE_INFRA(CLK_INFRA_IRRX_PD, "infra_irrx_pd", "irrx_sel", 16), + GATE_INFRA(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "f10m_ref_sel", 18), + GATE_INFRA(CLK_INFRA_PMIC_PD, "infra_pmic_pd", "pmicspi_sel", 22), +}; + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_TO_U2_PHY, "to_u2_phy", "clkxtal", + 31250000), + FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", "clkxtal", + 31250000), + FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", "clkxtal", + 125000000), + FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", "clkxtal", + 125000000), + FIXED_CLK(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", "clkxtal", + 250000000), + FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", "clkxtal", + 250000000), + FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", "clkxtal", + 33333333), + FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", "clkxtal", + 50000000), + FIXED_CLK(CLK_TOP_SATA_ASIC, "sata_asic", "clkxtal", + 50000000), + FIXED_CLK(CLK_TOP_SATA_RBC, "sata_rbc", "clkxtal", + 50000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4), + FACTOR(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500), + FACTOR(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125), + FACTOR(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500), + FACTOR(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1), + FACTOR(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024), + FACTOR(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1), + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12), + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28), + FACTOR(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16), + FACTOR(CLK_TOP_UNIVPLL1_D16, "univpll1_d16", "univpll", 1, 32), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24), + FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20), + FACTOR(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_D80_D4, "univpll_d80_d4", "univpll", 1, 320), + FACTOR(CLK_TOP_UNIV48M, "univ48m", "univpll", 1, 25), + FACTOR(CLK_TOP_SGMIIPLL, "sgmiipll_ck", "sgmipll", 1, 1), + FACTOR(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2), + FACTOR(CLK_TOP_AUD1PLL, "aud1pll_ck", "aud1pll", 1, 1), + FACTOR(CLK_TOP_AUD2PLL, "aud2pll_ck", "aud2pll", 1, 1), + FACTOR(CLK_TOP_AUD_I2S2_MCK, "aud_i2s2_mck", "i2s2_mck_sel", 1, 2), + FACTOR(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "univpll2_d4", 1, 4), + FACTOR(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "univpll1_d4", 1, 1), + FACTOR(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "univpll1_d4", 1, 1), + FACTOR(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1), +}; + +static const struct mtk_gate top_clks[] = { + /* TOP0 */ + GATE_TOP0(CLK_TOP_APLL1_DIV_PD, "apll1_ck_div_pd", "apll1_ck_div", 0), + GATE_TOP0(CLK_TOP_APLL2_DIV_PD, "apll2_ck_div_pd", "apll2_ck_div", 1), + GATE_TOP0(CLK_TOP_I2S0_MCK_DIV_PD, "i2s0_mck_div_pd", "i2s0_mck_div", + 2), + GATE_TOP0(CLK_TOP_I2S1_MCK_DIV_PD, "i2s1_mck_div_pd", "i2s1_mck_div", + 3), + GATE_TOP0(CLK_TOP_I2S2_MCK_DIV_PD, "i2s2_mck_div_pd", "i2s2_mck_div", + 4), + GATE_TOP0(CLK_TOP_I2S3_MCK_DIV_PD, "i2s3_mck_div_pd", "i2s3_mck_div", + 5), + + /* TOP1 */ + GATE_TOP1(CLK_TOP_A1SYS_HP_DIV_PD, "a1sys_div_pd", "a1sys_div", 0), + GATE_TOP1(CLK_TOP_A2SYS_HP_DIV_PD, "a2sys_div_pd", "a2sys_div", 16), +}; + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL1_DIV, "apll1_ck_div", "apll1_ck_sel", + 0x120, 24, 3), + DIV_ADJ(CLK_TOP_APLL2_DIV, "apll2_ck_div", "apll2_ck_sel", + 0x120, 28, 3), + DIV_ADJ(CLK_TOP_I2S0_MCK_DIV, "i2s0_mck_div", "i2s0_mck_sel", + 0x124, 0, 7), + DIV_ADJ(CLK_TOP_I2S1_MCK_DIV, "i2s1_mck_div", "i2s1_mck_sel", + 0x124, 8, 7), + DIV_ADJ(CLK_TOP_I2S2_MCK_DIV, "i2s2_mck_div", "aud_i2s2_mck", + 0x124, 16, 7), + DIV_ADJ(CLK_TOP_I2S3_MCK_DIV, "i2s3_mck_div", "i2s3_mck_sel", + 0x124, 24, 7), + DIV_ADJ(CLK_TOP_A1SYS_HP_DIV, "a1sys_div", "a1sys_hp_sel", + 0x128, 8, 7), + DIV_ADJ(CLK_TOP_A2SYS_HP_DIV, "a2sys_div", "a2sys_hp_sel", + 0x128, 24, 7), +}; + +static const struct mtk_gate peri_clks[] = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_THERM_PD, "peri_therm_pd", "axi_sel", 1), + GATE_PERI0(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "clkxtal", 2), + GATE_PERI0(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "clkxtal", 3), + GATE_PERI0(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "clkxtal", 4), + GATE_PERI0(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "clkxtal", 5), + GATE_PERI0(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "clkxtal", 6), + GATE_PERI0(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "clkxtal", 7), + GATE_PERI0(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "clkxtal", 8), + GATE_PERI0(CLK_PERI_PWM_PD, "peri_pwm_pd", "clkxtal", 9), + GATE_PERI0(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "axi_sel", 12), + GATE_PERI0(CLK_PERI_MSDC30_0_PD, "peri_msdc30_0", "msdc30_0_sel", 13), + GATE_PERI0(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1_sel", 14), + GATE_PERI0(CLK_PERI_UART0_PD, "peri_uart0_pd", "axi_sel", 17), + GATE_PERI0(CLK_PERI_UART1_PD, "peri_uart1_pd", "axi_sel", 18), + GATE_PERI0(CLK_PERI_UART2_PD, "peri_uart2_pd", "axi_sel", 19), + GATE_PERI0(CLK_PERI_UART3_PD, "peri_uart3_pd", "axi_sel", 20), + GATE_PERI0(CLK_PERI_UART4_PD, "peri_uart4_pd", "axi_sel", 21), + GATE_PERI0(CLK_PERI_BTIF_PD, "peri_btif_pd", "axi_sel", 22), + GATE_PERI0(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "axi_sel", 23), + GATE_PERI0(CLK_PERI_I2C1_PD, "peri_i2c1_pd", "axi_sel", 24), + GATE_PERI0(CLK_PERI_I2C2_PD, "peri_i2c2_pd", "axi_sel", 25), + GATE_PERI0(CLK_PERI_SPI1_PD, "peri_spi1_pd", "spi1_sel", 26), + GATE_PERI0(CLK_PERI_AUXADC_PD, "peri_auxadc_pd", "clkxtal", 27), + GATE_PERI0(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi0_sel", 28), + GATE_PERI0(CLK_PERI_SNFI_PD, "peri_snfi_pd", "nfi_infra_sel", 29), + GATE_PERI0(CLK_PERI_NFI_PD, "peri_nfi_pd", "axi_sel", 30), + GATE_PERI0(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "axi_sel", 31), + + /* PERI1 */ + GATE_PERI1(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash_sel", 1), + GATE_PERI1(CLK_PERI_IRTX_PD, "peri_irtx_pd", "irtx_sel", 2), +}; + +static struct mtk_composite infra_muxes[] __initdata = { + MUX(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents, + 0x000, 2, 2), +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + 0x040, 0, 3, 7), + MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, + 0x040, 8, 1, 15), + MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x040, 16, 1, 23), + MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, + 0x040, 24, 3, 31), + + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, + 0x050, 0, 2, 7), + MUX_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", f10m_ref_parents, + 0x050, 8, 1, 15), + MUX_GATE(CLK_TOP_NFI_INFRA_SEL, "nfi_infra_sel", nfi_infra_parents, + 0x050, 16, 4, 23), + MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents, + 0x050, 24, 3, 31), + + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, + 0x060, 0, 1, 7), + MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi0_parents, + 0x060, 8, 3, 15), + MUX_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", spi1_parents, + 0x060, 16, 3, 23), + MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", uart_parents, + 0x060, 24, 3, 31), + + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_parents, + 0x070, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_0_parents, + 0x070, 8, 3, 15), + MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", a1sys_hp_parents, + 0x070, 16, 2, 23), + MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", a1sys_hp_parents, + 0x070, 24, 2, 31), + + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents, + 0x080, 0, 2, 7), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x080, 8, 2, 15), + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, + 0x080, 16, 3, 23), + MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", ddrphycfg_parents, + 0x080, 24, 2, 31), + + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, + 0x090, 0, 2, 7), + MUX_GATE(CLK_TOP_HIF_SEL, "hif_sel", eth_parents, + 0x090, 8, 3, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, + 0x090, 16, 2, 23), + MUX_GATE(CLK_TOP_U2_SEL, "usb20_sel", usb20_parents, + 0x090, 24, 2, 31), + + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, + 0x0A0, 0, 1, 7), + MUX_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents, + 0x0A0, 8, 1, 15), + MUX_GATE(CLK_TOP_IRRX_SEL, "irrx_sel", f10m_ref_parents, + 0x0A0, 16, 1, 23), + MUX_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", f10m_ref_parents, + 0x0A0, 24, 1, 31), + + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", asm_l_parents, + 0x0B0, 0, 2, 7), + MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_l_parents, + 0x0B0, 8, 2, 15), + MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_l_parents, + 0x0B0, 16, 2, 23), + + /* CLK_AUDDIV_0 */ + MUX(CLK_TOP_APLL1_SEL, "apll1_ck_sel", apll1_ck_parents, + 0x120, 6, 1), + MUX(CLK_TOP_APLL2_SEL, "apll2_ck_sel", apll1_ck_parents, + 0x120, 7, 1), + MUX(CLK_TOP_I2S0_MCK_SEL, "i2s0_mck_sel", apll1_ck_parents, + 0x120, 8, 1), + MUX(CLK_TOP_I2S1_MCK_SEL, "i2s1_mck_sel", apll1_ck_parents, + 0x120, 9, 1), + MUX(CLK_TOP_I2S2_MCK_SEL, "i2s2_mck_sel", apll1_ck_parents, + 0x120, 10, 1), + MUX(CLK_TOP_I2S3_MCK_SEL, "i2s3_mck_sel", apll1_ck_parents, + 0x120, 11, 1), +}; + +static struct mtk_composite peri_muxes[] = { + /* PERI_GLOBALCON_CKSEL */ + MUX(CLK_PERIBUS_SEL, "peribus_ck_sel", peribus_ck_parents, 0x05C, 0, 1), +}; + +static int mtk_topckgen_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), + clk_data); + + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), + base, &mt7622_clk_lock, clk_data); + + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt7622_clk_lock, clk_data); + + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + clk_data); + + clk_prepare_enable(clk_data->clks[CLK_TOP_AXI_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_MEM_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); + + return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +} + +static int __init mtk_infrasys_init(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, + clk_data); + if (r) + return r; + + mtk_register_reset_controller(node, 1, 0x30); + + return 0; +} + +static int mtk_apmixedsys_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), + clk_data); + + mtk_clk_register_gates(node, apmixed_clks, + ARRAY_SIZE(apmixed_clks), clk_data); + + clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); + clk_prepare_enable(clk_data->clks[CLK_APMIXED_MAIN_CORE_EN]); + + return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +} + +static int mtk_pericfg_init(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + struct device_node *node = pdev->dev.of_node; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, + &mt7622_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + return r; + + clk_prepare_enable(clk_data->clks[CLK_PERI_UART0_PD]); + + mtk_register_reset_controller(node, 2, 0x0); + + return 0; +} + +static const struct of_device_id of_match_clk_mt7622[] = { + { + .compatible = "mediatek,mt7622-apmixedsys", + .data = mtk_apmixedsys_init, + }, { + .compatible = "mediatek,mt7622-infracfg", + .data = mtk_infrasys_init, + }, { + .compatible = "mediatek,mt7622-topckgen", + .data = mtk_topckgen_init, + }, { + .compatible = "mediatek,mt7622-pericfg", + .data = mtk_pericfg_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_drv = { + .probe = clk_mt7622_probe, + .driver = { + .name = "clk-mt7622", + .of_match_table = of_match_clk_mt7622, + }, +}; + +static int clk_mt7622_init(void) +{ + return platform_driver_register(&clk_mt7622_drv); +} + +arch_initcall(clk_mt7622_init); -- GitLab From 908a543ac7cdf3aa8a283ec42cab3c16e2fc45a2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 24 Sep 2017 18:19:18 +0200 Subject: [PATCH 1536/2898] clk: clk-gpio: Make GPIO clock provider use descriptors only After som grep:ing it turns out nothing in the kernel is really calling clk_[hw_]_register_gpio_[gate|mux](). All existing instances are just created directly from the device tree probe functions at the bottom of the clk-gpio.c clock provider file. This means we can change the signature of the function without any consequences! Everyone should be using GPIO descriptors now, so let's just go in and enforce that. This saves a bit of code since GPIO descriptors know inherently if they are active low so no need for the code keeping track of that. We leave it to the caller to come up with the GPIO descriptor. It is nowadays possible to do that even without a corresponding device, so no excuse not to pass them around. The one in-kernel user lifecycles it using devm_gpiod_get() in gpio_clk_driver_probe(). Cc: Sergej Sawazki Cc: Jyri Sarha Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/clk-gpio.c | 90 ++++++++++++++---------------------- include/linux/clk-provider.h | 12 ++--- 2 files changed, 41 insertions(+), 61 deletions(-) diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 86b245746a6b..9d057073e110 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -15,9 +15,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -95,14 +93,12 @@ const struct clk_ops clk_gpio_mux_ops = { EXPORT_SYMBOL_GPL(clk_gpio_mux_ops); static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags, - const struct clk_ops *clk_gpio_ops) + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags, const struct clk_ops *clk_gpio_ops) { struct clk_gpio *clk_gpio; struct clk_hw *hw; struct clk_init_data init = {}; - unsigned long gpio_flags; int err; if (dev) @@ -113,24 +109,13 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, if (!clk_gpio) return ERR_PTR(-ENOMEM); - if (active_low) - gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH; - else - gpio_flags = GPIOF_OUT_INIT_LOW; - - if (dev) - err = devm_gpio_request_one(dev, gpio, gpio_flags, name); - else - err = gpio_request_one(gpio, gpio_flags, name); - if (err) { - if (err != -EPROBE_DEFER) - pr_err("%s: %s: Error requesting clock control gpio %u\n", - __func__, name, gpio); - if (!dev) - kfree(clk_gpio); - - return ERR_PTR(err); - } + /* + * Set to disabled no matter what: NOTE if the GPIO line is active low + * the GPIO descriptor knows this and will set it high to deassert the + * line. This assumes the GPIO descriptor has been requested using + * GPIOD_ASIS by the callers so we need to initialize it as disabled here. + */ + gpiod_set_value(gpiod, 0); init.name = name; init.ops = clk_gpio_ops; @@ -138,7 +123,7 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, init.parent_names = parent_names; init.num_parents = num_parents; - clk_gpio->gpiod = gpio_to_desc(gpio); + clk_gpio->gpiod = gpiod; clk_gpio->hw.init = &init; hw = &clk_gpio->hw; @@ -151,7 +136,6 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, return hw; if (!dev) { - gpiod_put(clk_gpio->gpiod); kfree(clk_gpio); } @@ -164,29 +148,27 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, * @dev: device that is registering this clock * @name: name of this clock * @parent_name: name of this clock's parent - * @gpio: gpio number to gate this clock - * @active_low: true if gpio should be set to 0 to enable clock + * @gpiod: gpio descriptor to gate this clock * @flags: clock flags */ struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, + const char *parent_name, struct gpio_desc *gpiod, unsigned long flags) { return clk_register_gpio(dev, name, (parent_name ? &parent_name : NULL), - (parent_name ? 1 : 0), gpio, active_low, flags, + (parent_name ? 1 : 0), gpiod, flags, &clk_gpio_gate_ops); } EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate); struct clk *clk_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, + const char *parent_name, struct gpio_desc *gpiod, unsigned long flags) { struct clk_hw *hw; - hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpio, active_low, - flags); + hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpiod, flags); if (IS_ERR(hw)) return ERR_CAST(hw); return hw->clk; @@ -199,13 +181,12 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_gate); * @name: name of this clock * @parent_names: names of this clock's parents * @num_parents: number of parents listed in @parent_names - * @gpio: gpio number to gate this clock - * @active_low: true if gpio should be set to 0 to enable clock + * @gpiod: gpio descriptor to gate this clock * @flags: clock flags */ struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags) + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags) { if (num_parents != 2) { pr_err("mux-clock %s must have 2 parents\n", name); @@ -213,18 +194,18 @@ struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, } return clk_register_gpio(dev, name, parent_names, num_parents, - gpio, active_low, flags, &clk_gpio_mux_ops); + gpiod, flags, &clk_gpio_mux_ops); } EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux); struct clk *clk_register_gpio_mux(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags) + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags) { struct clk_hw *hw; hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents, - gpio, active_low, flags); + gpiod, flags); if (IS_ERR(hw)) return ERR_CAST(hw); return hw->clk; @@ -236,10 +217,10 @@ static int gpio_clk_driver_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; const char **parent_names, *gpio_name; unsigned int num_parents; - int gpio; - enum of_gpio_flags of_flags; + struct gpio_desc *gpiod; struct clk *clk; - bool active_low, is_mux; + bool is_mux; + int ret; num_parents = of_clk_get_parent_count(node); if (num_parents) { @@ -255,28 +236,27 @@ static int gpio_clk_driver_probe(struct platform_device *pdev) is_mux = of_device_is_compatible(node, "gpio-mux-clock"); - gpio_name = is_mux ? "select-gpios" : "enable-gpios"; - gpio = of_get_named_gpio_flags(node, gpio_name, 0, &of_flags); - if (gpio < 0) { - if (gpio == -EPROBE_DEFER) + gpio_name = is_mux ? "select" : "enable"; + gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_ASIS); + if (IS_ERR(gpiod)) { + ret = PTR_ERR(gpiod); + if (ret == -EPROBE_DEFER) pr_debug("%s: %s: GPIOs not yet available, retry later\n", node->name, __func__); else - pr_err("%s: %s: Can't get '%s' DT property\n", + pr_err("%s: %s: Can't get '%s' named GPIO property\n", node->name, __func__, gpio_name); - return gpio; + return ret; } - active_low = of_flags & OF_GPIO_ACTIVE_LOW; - if (is_mux) clk = clk_register_gpio_mux(&pdev->dev, node->name, - parent_names, num_parents, gpio, active_low, 0); + parent_names, num_parents, gpiod, 0); else clk = clk_register_gpio_gate(&pdev->dev, node->name, - parent_names ? parent_names[0] : NULL, gpio, - active_low, 0); + parent_names ? parent_names[0] : NULL, gpiod, + 0); if (IS_ERR(clk)) return PTR_ERR(clk); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 5100ec1b5d55..063d8cb9926f 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -682,10 +682,10 @@ struct clk_gpio { extern const struct clk_ops clk_gpio_gate_ops; struct clk *clk_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, + const char *parent_name, struct gpio_desc *gpiod, unsigned long flags); struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, - const char *parent_name, unsigned gpio, bool active_low, + const char *parent_name, struct gpio_desc *gpiod, unsigned long flags); void clk_hw_unregister_gpio_gate(struct clk_hw *hw); @@ -701,11 +701,11 @@ void clk_hw_unregister_gpio_gate(struct clk_hw *hw); extern const struct clk_ops clk_gpio_mux_ops; struct clk *clk_register_gpio_mux(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags); + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags); struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, - const char * const *parent_names, u8 num_parents, unsigned gpio, - bool active_low, unsigned long flags); + const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod, + unsigned long flags); void clk_hw_unregister_gpio_mux(struct clk_hw *hw); /** -- GitLab From 1b5d1a58a51324b1b6c851abec3bf40bd539cbb2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 24 Sep 2017 18:19:19 +0200 Subject: [PATCH 1537/2898] clk: clk-gpio: Request GPIO descriptor as LOW Requesting the GPIOD_OUT_LOW low will make sure the GPIO is deasserted when requested. The gpiolib core will make sure that if the GPIO line is active low, it will be logically driven high when deasserted, see drivers/gpiolib.c gpiod_configure_flags(). Cc: Sergej Sawazki Cc: Jyri Sarha Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/clk-gpio.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 9d057073e110..151513c655c3 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -109,14 +109,6 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, if (!clk_gpio) return ERR_PTR(-ENOMEM); - /* - * Set to disabled no matter what: NOTE if the GPIO line is active low - * the GPIO descriptor knows this and will set it high to deassert the - * line. This assumes the GPIO descriptor has been requested using - * GPIOD_ASIS by the callers so we need to initialize it as disabled here. - */ - gpiod_set_value(gpiod, 0); - init.name = name; init.ops = clk_gpio_ops; init.flags = flags | CLK_IS_BASIC; @@ -237,7 +229,7 @@ static int gpio_clk_driver_probe(struct platform_device *pdev) is_mux = of_device_is_compatible(node, "gpio-mux-clock"); gpio_name = is_mux ? "select" : "enable"; - gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_ASIS); + gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_OUT_LOW); if (IS_ERR(gpiod)) { ret = PTR_ERR(gpiod); if (ret == -EPROBE_DEFER) -- GitLab From d83870a5bedeca22027cb5e81cdd1e6975e02f81 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Nov 2017 09:41:18 +0000 Subject: [PATCH 1538/2898] thermal: bxt: remove redundant variable trip Variable trip is assigned but never read, hence it is redundant and can be removed. Cleans up clang warning: drivers/thermal/intel_bxt_pmic_thermal.c:204:4: warning: Value stored to 'trip' is never read Signed-off-by: Colin Ian King Signed-off-by: Zhang Rui --- drivers/thermal/intel_bxt_pmic_thermal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/thermal/intel_bxt_pmic_thermal.c b/drivers/thermal/intel_bxt_pmic_thermal.c index ef6b32242ccb..94cfd0064c43 100644 --- a/drivers/thermal/intel_bxt_pmic_thermal.c +++ b/drivers/thermal/intel_bxt_pmic_thermal.c @@ -166,7 +166,7 @@ static irqreturn_t pmic_thermal_irq_handler(int irq, void *data) struct pmic_thermal_data *td; struct intel_soc_pmic *pmic; struct regmap *regmap; - u8 reg_val, mask, irq_stat, trip; + u8 reg_val, mask, irq_stat; u16 reg, evt_stat_reg; int i, j, ret; @@ -201,7 +201,6 @@ static irqreturn_t pmic_thermal_irq_handler(int irq, void *data) if (regmap_read(regmap, evt_stat_reg, &ret)) return IRQ_HANDLED; - trip = td->maps[i].trip_config[j].trip_num; tzd = thermal_zone_get_zone_by_name(td->maps[i].handle); if (!IS_ERR(tzd)) thermal_zone_device_update(tzd, -- GitLab From 42c0a36c1c96382e4f9ce158abc64276751bd505 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 1 Nov 2017 09:39:49 -0700 Subject: [PATCH 1539/2898] thermal: int340x: processor_thermal: Add Cannon Lake support Added PCI-ID of Cannon Lake thermal device. Signed-off-by: Srinivas Pandruvada Signed-off-by: Zhang Rui --- drivers/thermal/int340x_thermal/processor_thermal_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c index f02341f7134d..e724a23d250e 100644 --- a/drivers/thermal/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c @@ -30,6 +30,9 @@ /* Skylake thermal reporting device */ #define PCI_DEVICE_ID_PROC_SKL_THERMAL 0x1903 +/* CannonLake thermal reporting device */ +#define PCI_DEVICE_ID_PROC_CNL_THERMAL 0x5a03 + /* Braswell thermal reporting device */ #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC @@ -461,6 +464,7 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXT1_THERMAL)}, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTX_THERMAL)}, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)}, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CNL_THERMAL)}, { 0, }, }; -- GitLab From eea4a69a4636867b18b6ba414b964cdc21c53789 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 1 Nov 2017 09:39:50 -0700 Subject: [PATCH 1540/2898] thermal: int340x: processor_thermal: Add Coffee Lake support Add new PCI id for Coffee lake processor thermal device. Signed-off-by: Srinivas Pandruvada Signed-off-by: Zhang Rui --- drivers/thermal/int340x_thermal/processor_thermal_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c index e724a23d250e..80bbf9ce2fb6 100644 --- a/drivers/thermal/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c @@ -32,6 +32,7 @@ /* CannonLake thermal reporting device */ #define PCI_DEVICE_ID_PROC_CNL_THERMAL 0x5a03 +#define PCI_DEVICE_ID_PROC_CFL_THERMAL 0x3E83 /* Braswell thermal reporting device */ #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC @@ -465,6 +466,7 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTX_THERMAL)}, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)}, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CNL_THERMAL)}, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CFL_THERMAL)}, { 0, }, }; -- GitLab From 6ed5ed14e25914dab92ed492565f6feb80ae0559 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 1 Nov 2017 09:39:51 -0700 Subject: [PATCH 1541/2898] thermal: pch: Add Cannon Lake support Added Cannon Lake PCH ids. Signed-off-by: Srinivas Pandruvada Signed-off-by: Zhang Rui --- drivers/thermal/intel_pch_thermal.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel_pch_thermal.c index c60b1cfcc64e..8a7f69b4b022 100644 --- a/drivers/thermal/intel_pch_thermal.c +++ b/drivers/thermal/intel_pch_thermal.c @@ -30,6 +30,8 @@ #define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */ #define PCH_THERMAL_DID_SKL 0x9D31 /* Skylake PCH */ #define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */ +#define PCH_THERMAL_DID_CNL 0x9Df9 /* CNL PCH */ +#define PCH_THERMAL_DID_CNL_H 0xA379 /* CNL-H PCH */ /* Wildcat Point-LP PCH Thermal registers */ #define WPT_TEMP 0x0000 /* Temperature */ @@ -278,6 +280,7 @@ enum board_ids { board_hsw, board_wpt, board_skl, + board_cnl, }; static const struct board_info { @@ -296,6 +299,10 @@ static const struct board_info { .name = "pch_skylake", .ops = &pch_dev_ops_wpt, }, + [board_cnl] = { + .name = "pch_cannonlake", + .ops = &pch_dev_ops_wpt, + }, }; static int intel_pch_thermal_probe(struct pci_dev *pdev, @@ -398,6 +405,10 @@ static const struct pci_device_id intel_pch_thermal_id[] = { .driver_data = board_skl, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL_H), .driver_data = board_skl, }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL), + .driver_data = board_cnl, }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H), + .driver_data = board_cnl, }, { 0, }, }; MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id); -- GitLab From cc57306f426e3953118f1fcf8a7254dbad46c5f6 Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Fri, 20 Oct 2017 16:40:45 -0400 Subject: [PATCH 1542/2898] drm/amd/display: Use constants from atom.h for HDMI caps read Get rid of the constant we copied over before and just directly use the constants from the file. Signed-off-by: Andrew Jiang Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index c47da645d3b8..e70612eaf257 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -24,6 +24,7 @@ */ #include "dm_services.h" +#include "atom.h" #include "dm_helpers.h" #include "dc.h" #include "grph_object_id.h" @@ -45,7 +46,6 @@ #include "dce/dce_11_0_enum.h" #include "dce/dce_11_0_sh_mask.h" -#define EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK 0x007C /* Copied from atombios.h */ #define LINK_INFO(...) \ dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ __VA_ARGS__) @@ -1696,7 +1696,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps & EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK; - if (masked_chip_caps == (0x2 << 2)) { + if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) { /* DP159, Retimer settings */ eng_id = pipe_ctx->stream_res.stream_enc->id; @@ -1707,7 +1707,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) write_i2c_default_retimer_setting(pipe_ctx, is_vga_mode, is_over_340mhz); } - } else if (masked_chip_caps == (0x1 << 2)) { + } else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) { /* PI3EQX1204, Redriver settings */ write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); } -- GitLab From 30b7c6147d18d77c6120a8f689d04d2518d3f5e4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 26 Oct 2017 15:35:14 -0400 Subject: [PATCH 1543/2898] drm/amd/display: Don't print error when bo_pin is interrupted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: Also don't print for ERESTARTSYS or EAGAIN v3: Best practice is to only ignore ERESTARTSYS Signed-off-by: Harry Wentland Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index fd3e995fc426..b94987bb6af9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2923,7 +2923,8 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, amdgpu_bo_unreserve(rbo); if (unlikely(r != 0)) { - DRM_ERROR("Failed to pin framebuffer\n"); + if (r != -ERESTARTSYS) + DRM_ERROR("Failed to pin framebuffer with error %d\n", r); return r; } -- GitLab From f5ba60fefa00ca789c4eb35df38b171d532b3155 Mon Sep 17 00:00:00 2001 From: Drew Davenport Date: Fri, 27 Oct 2017 12:34:46 -0600 Subject: [PATCH 1544/2898] amdgpu/dc: Avoid dereferencing NULL pointer crtc is dereferenced from within drm_atomic_get_new_crtc_state, so check for NULL before initializing new_crtc_state. Signed-off-by: Drew Davenport Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b94987bb6af9..84591781fca1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3853,8 +3853,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, /* update planes when needed */ for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { struct drm_crtc *crtc = new_plane_state->crtc; - struct drm_crtc_state *new_crtc_state = - drm_atomic_get_new_crtc_state(state, crtc); + struct drm_crtc_state *new_crtc_state; struct drm_framebuffer *fb = new_plane_state->fb; bool pflip_needed; struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state); @@ -3864,7 +3863,11 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, continue; } - if (!fb || !crtc || pcrtc != crtc || !new_crtc_state->active) + if (!fb || !crtc || pcrtc != crtc) + continue; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + if (!new_crtc_state->active) continue; pflip_needed = !state->allow_modeset; -- GitLab From 55d9038b0c680ec90e3a7d2440e717ac6a2a8064 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Thu, 26 Oct 2017 11:47:42 +0530 Subject: [PATCH 1545/2898] drm/amd/display: fix null pointer dereference While setting cursor position in case of mpo, input_pixel_processor is not available for underlay, hence add check of the same to avoid null pointer access issue. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 5cf69af9693d..572b885195c7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -288,7 +288,7 @@ bool dc_stream_set_cursor_position( pos_cpy.enable = false; - if (ipp->funcs->ipp_cursor_set_position != NULL) + if (ipp !=NULL && ipp->funcs->ipp_cursor_set_position != NULL) ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); if (mi != NULL && mi->funcs->set_cursor_position != NULL) -- GitLab From efa6a8b7ca0f1c6073a2ac7f5a02f8ea333daf92 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 20 Oct 2017 08:42:41 -0400 Subject: [PATCH 1546/2898] drm/amd/display: Use plane pointer to avoid line breaks Signed-off-by: Harry Wentland Reviewed-by: Mikita Lipski Reviewed-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 84591781fca1..2df9f951b7e7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1328,13 +1328,16 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) } for (i = 0; i < dm->dc->caps.max_planes; i++) { - mode_info->planes[i] = kzalloc(sizeof(struct amdgpu_plane), - GFP_KERNEL); - if (!mode_info->planes[i]) { + struct amdgpu_plane *plane; + + plane = kzalloc(sizeof(struct amdgpu_plane), GFP_KERNEL); + mode_info->planes[i] = plane; + + if (!plane) { DRM_ERROR("KMS: Failed to allocate plane\n"); goto fail_free_planes; } - mode_info->planes[i]->base.type = mode_info->plane_type[i]; + plane->base.type = mode_info->plane_type[i]; /* * HACK: IGT tests expect that each plane can only have one -- GitLab From cd8a2ae8dc08a92d4804a7adda645f1f8d1f7586 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 20 Oct 2017 08:28:59 -0400 Subject: [PATCH 1547/2898] drm/amd/display: Use single fail label in init_drm_dev No need for multiple labels as kfree will always do a NULL check before freeing the memory. Signed-off-by: Harry Wentland Reviewed-by: Bhawanpreet Lakha Reviewed-by: Tony Cheng Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2df9f951b7e7..6eb7b32fb763 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1335,7 +1335,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (!plane) { DRM_ERROR("KMS: Failed to allocate plane\n"); - goto fail_free_planes; + goto fail; } plane->base.type = mode_info->plane_type[i]; @@ -1351,14 +1351,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (amdgpu_dm_plane_init(dm, mode_info->planes[i], possible_crtcs)) { DRM_ERROR("KMS: Failed to initialize plane\n"); - goto fail_free_planes; + goto fail; } } for (i = 0; i < dm->dc->caps.max_streams; i++) if (amdgpu_dm_crtc_init(dm, &mode_info->planes[i]->base, i)) { DRM_ERROR("KMS: Failed to initialize crtc\n"); - goto fail_free_planes; + goto fail; } dm->display_indexes_num = dm->dc->caps.max_streams; @@ -1375,20 +1375,20 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) - goto fail_free_planes; + goto fail; aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); if (!aencoder) - goto fail_free_connector; + goto fail; if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { DRM_ERROR("KMS: Failed to initialize encoder\n"); - goto fail_free_encoder; + goto fail; } if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) { DRM_ERROR("KMS: Failed to initialize connector\n"); - goto fail_free_encoder; + goto fail; } if (dc_link_detect(dc_get_link_at_index(dm->dc, i), @@ -1413,14 +1413,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_VEGA10: if (dce110_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); - goto fail_free_encoder; + goto fail; } break; #if defined(CONFIG_DRM_AMD_DC_DCN1_0) case CHIP_RAVEN: if (dcn10_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); - goto fail_free_encoder; + goto fail; } /* * Temporary disable until pplib/smu interaction is implemented @@ -1430,17 +1430,15 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) #endif default: DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type); - goto fail_free_encoder; + goto fail; } drm_mode_config_reset(dm->ddev); return 0; -fail_free_encoder: +fail: kfree(aencoder); -fail_free_connector: kfree(aconnector); -fail_free_planes: for (i = 0; i < dm->dc->caps.max_planes; i++) kfree(mode_info->planes[i]); return -1; -- GitLab From 96719c5439b4d75bfd6b3c5cb24f1a8e537125bb Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 20 Oct 2017 08:43:40 -0400 Subject: [PATCH 1548/2898] drm/amd/display: Explicitly call ->reset for each object We need to avoid calling reset after detection because the next commit adds freesync properties on the atomic_state which are set during detection. Calling reset after this clears them. The easiest way to accomplish this right now is to call ->reset on the connector right after creation but before detection. To stay consistent call ->reset on every other object as well after creation. v2: Provide better reason for this change in commit msg. Signed-off-by: Harry Wentland Reviewed-by: Roman Li Acked-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6eb7b32fb763..33a15a1d818c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1433,8 +1433,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail; } - drm_mode_config_reset(dm->ddev); - return 0; fail: kfree(aencoder); @@ -3081,6 +3079,11 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, drm_plane_helper_add(&aplane->base, &dm_plane_helper_funcs); + /* Create (reset) the plane state */ + if (aplane->base.funcs->reset) + aplane->base.funcs->reset(&aplane->base); + + return res; } @@ -3116,6 +3119,10 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs); + /* Create (reset) the plane state */ + if (acrtc->base.funcs->reset) + acrtc->base.funcs->reset(&acrtc->base); + acrtc->max_cursor_width = dm->adev->dm.dc->caps.max_cursor_size; acrtc->max_cursor_height = dm->adev->dm.dc->caps.max_cursor_size; @@ -3468,6 +3475,9 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, &aconnector->base, &amdgpu_dm_connector_helper_funcs); + if (aconnector->base.funcs->reset) + aconnector->base.funcs->reset(&aconnector->base); + amdgpu_dm_connector_init_helper( dm, aconnector, -- GitLab From b7fa8519057319aef8405923dc8fa6782fce969f Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Tue, 31 Oct 2017 16:28:57 -0400 Subject: [PATCH 1549/2898] drm/amd: Add DCE12 resource strap registers We need them for initializing audio properly. Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h | 4 ++++ .../drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h index 75b660d57bdf..f730d0629020 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_offset.h @@ -1841,6 +1841,10 @@ #define mmUNIPHYG_CHANNEL_XBAR_CNTL_BASE_IDX 2 #define mmDCIO_WRCMD_DELAY 0x2094 #define mmDCIO_WRCMD_DELAY_BASE_IDX 2 +#define mmDC_PINSTRAPS 0x2096 +#define mmDC_PINSTRAPS_BASE_IDX 2 +#define mmCC_DC_MISC_STRAPS 0x2097 +#define mmCC_DC_MISC_STRAPS_BASE_IDX 2 #define mmDC_DVODATA_CONFIG 0x2098 #define mmDC_DVODATA_CONFIG_BASE_IDX 2 #define mmLVTMA_PWRSEQ_CNTL 0x2099 diff --git a/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h index d8ad862b3a74..6d3162c42957 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/vega10/DC/dce_12_0_sh_mask.h @@ -2447,6 +2447,14 @@ //DCCG_CBUS_WRCMD_DELAY #define DCCG_CBUS_WRCMD_DELAY__CBUS_PLL_WRCMD_DELAY__SHIFT 0x0 #define DCCG_CBUS_WRCMD_DELAY__CBUS_PLL_WRCMD_DELAY_MASK 0x0000000FL +//DC_PINSTRAPS +#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO__SHIFT 0xe +#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO_MASK 0x0000C000L +//CC_DC_MISC_STRAPS +#define CC_DC_MISC_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_MISC_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#define CC_DC_MISC_STRAPS__HDMI_DISABLE_MASK 0x00000040L +#define CC_DC_MISC_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x00000700L //DCCG_DS_DTO_INCR #define DCCG_DS_DTO_INCR__DCCG_DS_DTO_INCR__SHIFT 0x0 #define DCCG_DS_DTO_INCR__DCCG_DS_DTO_INCR_MASK 0xFFFFFFFFL -- GitLab From 4a74635ce23a4b8758047a733faf791e38032263 Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Wed, 1 Nov 2017 10:24:51 -0400 Subject: [PATCH 1550/2898] drm/amd/display: Read resource_straps from registers for DCE12 Now that the registers exist, assign them to the resource_straps struct. v2: Fix indentation v3: Fix trailing whitespace and checkpatch warnings. bug: https://bugs.freedesktop.org/show_bug.cgi?id=103404 Reviewed-by: Harry Wentland Signed-off-by: Leo (Sunpeng) Li Signed-off-by: Alex Deucher --- .../amd/display/dc/dce120/dce120_resource.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 3ed28a870e20..5c48c22d9d98 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -501,12 +501,19 @@ static void read_dce_straps( struct dc_context *ctx, struct resource_straps *straps) { - /* TODO: Registers are missing */ - /*REG_GET_2(CC_DC_HDMI_STRAPS, - HDMI_DISABLE, &straps->hdmi_disable, - AUDIO_STREAM_NUMBER, &straps->audio_stream_number); - - REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/ + uint32_t reg_val = dm_read_reg_soc15(ctx, mmCC_DC_MISC_STRAPS, 0); + + straps->audio_stream_number = get_reg_field_value(reg_val, + CC_DC_MISC_STRAPS, + AUDIO_STREAM_NUMBER); + straps->hdmi_disable = get_reg_field_value(reg_val, + CC_DC_MISC_STRAPS, + HDMI_DISABLE); + + reg_val = dm_read_reg_soc15(ctx, mmDC_PINSTRAPS, 0); + straps->dc_pinstraps_audio = get_reg_field_value(reg_val, + DC_PINSTRAPS, + DC_PINSTRAPS_AUDIO); } static struct audio *create_audio( -- GitLab From d8eed8263aa09c0c92416d06321eae4ad3eda343 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 2 Nov 2017 15:24:40 +0100 Subject: [PATCH 1551/2898] drm/amdgpu/display: provide ASSERT macros unconditionally It seems impossible to build this driver without setting either CONFIG_DEBUG_KERNEL or CONFIG_DEBUG_DRIVER: drivers/gpu/drm/amd/amdgpu/../display/dc/dm_services.h: In function 'set_reg_field_value_ex': drivers/gpu/drm/amd/amdgpu/../display/dc/dm_services.h:132:2: error: implicit declaration of function 'ASSERT'; did you mean 'IS_ERR'? [-Werror=implicit-function-declaration] This moves the ASSERT() macro and related helpers outside of the #ifdef to get it to build again. Reviewed-by: Harry Wentland Signed-off-by: Arnd Bergmann Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/os_types.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index 86170b40b5c5..a87c0329541f 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -61,8 +61,6 @@ * general debug capabilities * */ -#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER) - #if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB) #define ASSERT_CRITICAL(expr) do { \ if (WARN_ON(!(expr))) { \ @@ -86,8 +84,6 @@ #define BREAK_TO_DEBUGGER() ASSERT(0) -#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */ - #define DC_ERR(...) do { \ dm_error(__VA_ARGS__); \ BREAK_TO_DEBUGGER(); \ -- GitLab From aa9ad44a42b4cf4387f8ecddaf8e51707fdcda5a Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 23 Aug 2017 12:48:26 -0700 Subject: [PATCH 1552/2898] libnvdimm: move poison list functions to a new 'badrange' file nfit_test needs to use the poison list manipulation code as well. Make it more generic and in the process rename poison to badrange, and move all the related helpers to a new file. Signed-off-by: Dave Jiang [vishal: Add badrange.o to nfit_test's Kbuild] [vishal: add a missed include in bus.c for the new badrange functions] [vishal: rename all instances of 'be' to 'bre'] Signed-off-by: Vishal Verma Signed-off-by: Dan Williams --- drivers/acpi/nfit/core.c | 2 +- drivers/acpi/nfit/mce.c | 2 +- drivers/nvdimm/Makefile | 1 + drivers/nvdimm/badrange.c | 294 ++++++++++++++++++++++++++++++++++++ drivers/nvdimm/bus.c | 24 +-- drivers/nvdimm/core.c | 260 +------------------------------ drivers/nvdimm/nd-core.h | 3 +- drivers/nvdimm/nd.h | 6 - include/linux/libnvdimm.h | 21 ++- tools/testing/nvdimm/Kbuild | 1 + 10 files changed, 332 insertions(+), 282 deletions(-) create mode 100644 drivers/nvdimm/badrange.c diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index aa75d67ceee9..8043bfde7c63 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -2486,7 +2486,7 @@ static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc, if (ars_status->out_length < 44 + sizeof(struct nd_ars_record) * (i + 1)) break; - rc = nvdimm_bus_add_poison(nvdimm_bus, + rc = nvdimm_bus_add_badrange(nvdimm_bus, ars_status->records[i].err_address, ars_status->records[i].length); if (rc) diff --git a/drivers/acpi/nfit/mce.c b/drivers/acpi/nfit/mce.c index feeb95d574fa..b92921439657 100644 --- a/drivers/acpi/nfit/mce.c +++ b/drivers/acpi/nfit/mce.c @@ -67,7 +67,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val, continue; /* If this fails due to an -ENOMEM, there is little we can do */ - nvdimm_bus_add_poison(acpi_desc->nvdimm_bus, + nvdimm_bus_add_badrange(acpi_desc->nvdimm_bus, ALIGN(mce->addr, L1_CACHE_BYTES), L1_CACHE_BYTES); nvdimm_region_notify(nfit_spa->nd_region, diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile index 909554c3f955..ca6d325438a3 100644 --- a/drivers/nvdimm/Makefile +++ b/drivers/nvdimm/Makefile @@ -20,6 +20,7 @@ libnvdimm-y += region_devs.o libnvdimm-y += region.o libnvdimm-y += namespace_devs.o libnvdimm-y += label.o +libnvdimm-y += badrange.o libnvdimm-$(CONFIG_ND_CLAIM) += claim.o libnvdimm-$(CONFIG_BTT) += btt_devs.o libnvdimm-$(CONFIG_NVDIMM_PFN) += pfn_devs.o diff --git a/drivers/nvdimm/badrange.c b/drivers/nvdimm/badrange.c new file mode 100644 index 000000000000..0b67dcf43234 --- /dev/null +++ b/drivers/nvdimm/badrange.c @@ -0,0 +1,294 @@ +/* + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nd-core.h" +#include "nd.h" + +void badrange_init(struct badrange *badrange) +{ + INIT_LIST_HEAD(&badrange->list); + spin_lock_init(&badrange->lock); +} +EXPORT_SYMBOL_GPL(badrange_init); + +static void append_badrange_entry(struct badrange *badrange, + struct badrange_entry *bre, u64 addr, u64 length) +{ + lockdep_assert_held(&badrange->lock); + bre->start = addr; + bre->length = length; + list_add_tail(&bre->list, &badrange->list); +} + +static int alloc_and_append_badrange_entry(struct badrange *badrange, + u64 addr, u64 length, gfp_t flags) +{ + struct badrange_entry *bre; + + bre = kzalloc(sizeof(*bre), flags); + if (!bre) + return -ENOMEM; + + append_badrange_entry(badrange, bre, addr, length); + return 0; +} + +static int add_badrange(struct badrange *badrange, u64 addr, u64 length) +{ + struct badrange_entry *bre, *bre_new; + + spin_unlock(&badrange->lock); + bre_new = kzalloc(sizeof(*bre_new), GFP_KERNEL); + spin_lock(&badrange->lock); + + if (list_empty(&badrange->list)) { + if (!bre_new) + return -ENOMEM; + append_badrange_entry(badrange, bre_new, addr, length); + return 0; + } + + /* + * There is a chance this is a duplicate, check for those first. + * This will be the common case as ARS_STATUS returns all known + * errors in the SPA space, and we can't query it per region + */ + list_for_each_entry(bre, &badrange->list, list) + if (bre->start == addr) { + /* If length has changed, update this list entry */ + if (bre->length != length) + bre->length = length; + kfree(bre_new); + return 0; + } + + /* + * If not a duplicate or a simple length update, add the entry as is, + * as any overlapping ranges will get resolved when the list is consumed + * and converted to badblocks + */ + if (!bre_new) + return -ENOMEM; + append_badrange_entry(badrange, bre_new, addr, length); + + return 0; +} + +int badrange_add(struct badrange *badrange, u64 addr, u64 length) +{ + int rc; + + spin_lock(&badrange->lock); + rc = add_badrange(badrange, addr, length); + spin_unlock(&badrange->lock); + + return rc; +} +EXPORT_SYMBOL_GPL(badrange_add); + +void badrange_forget(struct badrange *badrange, phys_addr_t start, + unsigned int len) +{ + struct list_head *badrange_list = &badrange->list; + u64 clr_end = start + len - 1; + struct badrange_entry *bre, *next; + + spin_lock(&badrange->lock); + WARN_ON_ONCE(list_empty(badrange_list)); + + /* + * [start, clr_end] is the badrange interval being cleared. + * [bre->start, bre_end] is the badrange_list entry we're comparing + * the above interval against. The badrange list entry may need + * to be modified (update either start or length), deleted, or + * split into two based on the overlap characteristics + */ + + list_for_each_entry_safe(bre, next, badrange_list, list) { + u64 bre_end = bre->start + bre->length - 1; + + /* Skip intervals with no intersection */ + if (bre_end < start) + continue; + if (bre->start > clr_end) + continue; + /* Delete completely overlapped badrange entries */ + if ((bre->start >= start) && (bre_end <= clr_end)) { + list_del(&bre->list); + kfree(bre); + continue; + } + /* Adjust start point of partially cleared entries */ + if ((start <= bre->start) && (clr_end > bre->start)) { + bre->length -= clr_end - bre->start + 1; + bre->start = clr_end + 1; + continue; + } + /* Adjust bre->length for partial clearing at the tail end */ + if ((bre->start < start) && (bre_end <= clr_end)) { + /* bre->start remains the same */ + bre->length = start - bre->start; + continue; + } + /* + * If clearing in the middle of an entry, we split it into + * two by modifying the current entry to represent one half of + * the split, and adding a new entry for the second half. + */ + if ((bre->start < start) && (bre_end > clr_end)) { + u64 new_start = clr_end + 1; + u64 new_len = bre_end - new_start + 1; + + /* Add new entry covering the right half */ + alloc_and_append_badrange_entry(badrange, new_start, + new_len, GFP_NOWAIT); + /* Adjust this entry to cover the left half */ + bre->length = start - bre->start; + continue; + } + } + spin_unlock(&badrange->lock); +} +EXPORT_SYMBOL_GPL(badrange_forget); + +static void set_badblock(struct badblocks *bb, sector_t s, int num) +{ + dev_dbg(bb->dev, "Found a bad range (0x%llx, 0x%llx)\n", + (u64) s * 512, (u64) num * 512); + /* this isn't an error as the hardware will still throw an exception */ + if (badblocks_set(bb, s, num, 1)) + dev_info_once(bb->dev, "%s: failed for sector %llx\n", + __func__, (u64) s); +} + +/** + * __add_badblock_range() - Convert a physical address range to bad sectors + * @bb: badblocks instance to populate + * @ns_offset: namespace offset where the error range begins (in bytes) + * @len: number of bytes of badrange to be added + * + * This assumes that the range provided with (ns_offset, len) is within + * the bounds of physical addresses for this namespace, i.e. lies in the + * interval [ns_start, ns_start + ns_size) + */ +static void __add_badblock_range(struct badblocks *bb, u64 ns_offset, u64 len) +{ + const unsigned int sector_size = 512; + sector_t start_sector, end_sector; + u64 num_sectors; + u32 rem; + + start_sector = div_u64(ns_offset, sector_size); + end_sector = div_u64_rem(ns_offset + len, sector_size, &rem); + if (rem) + end_sector++; + num_sectors = end_sector - start_sector; + + if (unlikely(num_sectors > (u64)INT_MAX)) { + u64 remaining = num_sectors; + sector_t s = start_sector; + + while (remaining) { + int done = min_t(u64, remaining, INT_MAX); + + set_badblock(bb, s, done); + remaining -= done; + s += done; + } + } else + set_badblock(bb, start_sector, num_sectors); +} + +static void badblocks_populate(struct badrange *badrange, + struct badblocks *bb, const struct resource *res) +{ + struct badrange_entry *bre; + + if (list_empty(&badrange->list)) + return; + + list_for_each_entry(bre, &badrange->list, list) { + u64 bre_end = bre->start + bre->length - 1; + + /* Discard intervals with no intersection */ + if (bre_end < res->start) + continue; + if (bre->start > res->end) + continue; + /* Deal with any overlap after start of the namespace */ + if (bre->start >= res->start) { + u64 start = bre->start; + u64 len; + + if (bre_end <= res->end) + len = bre->length; + else + len = res->start + resource_size(res) + - bre->start; + __add_badblock_range(bb, start - res->start, len); + continue; + } + /* + * Deal with overlap for badrange starting before + * the namespace. + */ + if (bre->start < res->start) { + u64 len; + + if (bre_end < res->end) + len = bre->start + bre->length - res->start; + else + len = resource_size(res); + __add_badblock_range(bb, 0, len); + } + } +} + +/** + * nvdimm_badblocks_populate() - Convert a list of badranges to badblocks + * @region: parent region of the range to interrogate + * @bb: badblocks instance to populate + * @res: resource range to consider + * + * The badrange list generated during bus initialization may contain + * multiple, possibly overlapping physical address ranges. Compare each + * of these ranges to the resource range currently being initialized, + * and add badblocks entries for all matching sub-ranges + */ +void nvdimm_badblocks_populate(struct nd_region *nd_region, + struct badblocks *bb, const struct resource *res) +{ + struct nvdimm_bus *nvdimm_bus; + + if (!is_memory(&nd_region->dev)) { + dev_WARN_ONCE(&nd_region->dev, 1, + "%s only valid for pmem regions\n", __func__); + return; + } + nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev); + + nvdimm_bus_lock(&nvdimm_bus->dev); + badblocks_populate(&nvdimm_bus->badrange, bb, res); + nvdimm_bus_unlock(&nvdimm_bus->dev); +} +EXPORT_SYMBOL_GPL(nvdimm_badblocks_populate); diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index baf283986a7e..0a5e6cd758fe 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -11,6 +11,7 @@ * General Public License for more details. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -221,7 +222,7 @@ static void nvdimm_account_cleared_poison(struct nvdimm_bus *nvdimm_bus, phys_addr_t phys, u64 cleared) { if (cleared > 0) - nvdimm_forget_poison(nvdimm_bus, phys, cleared); + badrange_forget(&nvdimm_bus->badrange, phys, cleared); if (cleared > 0 && cleared / 512) nvdimm_clear_badblocks_regions(nvdimm_bus, phys, cleared); @@ -344,11 +345,10 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent, return NULL; INIT_LIST_HEAD(&nvdimm_bus->list); INIT_LIST_HEAD(&nvdimm_bus->mapping_list); - INIT_LIST_HEAD(&nvdimm_bus->poison_list); init_waitqueue_head(&nvdimm_bus->probe_wait); nvdimm_bus->id = ida_simple_get(&nd_ida, 0, 0, GFP_KERNEL); mutex_init(&nvdimm_bus->reconfig_mutex); - spin_lock_init(&nvdimm_bus->poison_lock); + badrange_init(&nvdimm_bus->badrange); if (nvdimm_bus->id < 0) { kfree(nvdimm_bus); return NULL; @@ -395,15 +395,15 @@ static int child_unregister(struct device *dev, void *data) return 0; } -static void free_poison_list(struct list_head *poison_list) +static void free_badrange_list(struct list_head *badrange_list) { - struct nd_poison *pl, *next; + struct badrange_entry *bre, *next; - list_for_each_entry_safe(pl, next, poison_list, list) { - list_del(&pl->list); - kfree(pl); + list_for_each_entry_safe(bre, next, badrange_list, list) { + list_del(&bre->list); + kfree(bre); } - list_del_init(poison_list); + list_del_init(badrange_list); } static int nd_bus_remove(struct device *dev) @@ -417,9 +417,9 @@ static int nd_bus_remove(struct device *dev) nd_synchronize(); device_for_each_child(&nvdimm_bus->dev, NULL, child_unregister); - spin_lock(&nvdimm_bus->poison_lock); - free_poison_list(&nvdimm_bus->poison_list); - spin_unlock(&nvdimm_bus->poison_lock); + spin_lock(&nvdimm_bus->badrange.lock); + free_badrange_list(&nvdimm_bus->badrange.list); + spin_unlock(&nvdimm_bus->badrange.lock); nvdimm_bus_destroy_ndctl(nvdimm_bus); diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index bb71f0cf8f5d..1dc527660637 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c @@ -398,265 +398,11 @@ struct attribute_group nvdimm_bus_attribute_group = { }; EXPORT_SYMBOL_GPL(nvdimm_bus_attribute_group); -static void set_badblock(struct badblocks *bb, sector_t s, int num) +int nvdimm_bus_add_badrange(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length) { - dev_dbg(bb->dev, "Found a poison range (0x%llx, 0x%llx)\n", - (u64) s * 512, (u64) num * 512); - /* this isn't an error as the hardware will still throw an exception */ - if (badblocks_set(bb, s, num, 1)) - dev_info_once(bb->dev, "%s: failed for sector %llx\n", - __func__, (u64) s); + return badrange_add(&nvdimm_bus->badrange, addr, length); } - -/** - * __add_badblock_range() - Convert a physical address range to bad sectors - * @bb: badblocks instance to populate - * @ns_offset: namespace offset where the error range begins (in bytes) - * @len: number of bytes of poison to be added - * - * This assumes that the range provided with (ns_offset, len) is within - * the bounds of physical addresses for this namespace, i.e. lies in the - * interval [ns_start, ns_start + ns_size) - */ -static void __add_badblock_range(struct badblocks *bb, u64 ns_offset, u64 len) -{ - const unsigned int sector_size = 512; - sector_t start_sector, end_sector; - u64 num_sectors; - u32 rem; - - start_sector = div_u64(ns_offset, sector_size); - end_sector = div_u64_rem(ns_offset + len, sector_size, &rem); - if (rem) - end_sector++; - num_sectors = end_sector - start_sector; - - if (unlikely(num_sectors > (u64)INT_MAX)) { - u64 remaining = num_sectors; - sector_t s = start_sector; - - while (remaining) { - int done = min_t(u64, remaining, INT_MAX); - - set_badblock(bb, s, done); - remaining -= done; - s += done; - } - } else - set_badblock(bb, start_sector, num_sectors); -} - -static void badblocks_populate(struct list_head *poison_list, - struct badblocks *bb, const struct resource *res) -{ - struct nd_poison *pl; - - if (list_empty(poison_list)) - return; - - list_for_each_entry(pl, poison_list, list) { - u64 pl_end = pl->start + pl->length - 1; - - /* Discard intervals with no intersection */ - if (pl_end < res->start) - continue; - if (pl->start > res->end) - continue; - /* Deal with any overlap after start of the namespace */ - if (pl->start >= res->start) { - u64 start = pl->start; - u64 len; - - if (pl_end <= res->end) - len = pl->length; - else - len = res->start + resource_size(res) - - pl->start; - __add_badblock_range(bb, start - res->start, len); - continue; - } - /* Deal with overlap for poison starting before the namespace */ - if (pl->start < res->start) { - u64 len; - - if (pl_end < res->end) - len = pl->start + pl->length - res->start; - else - len = resource_size(res); - __add_badblock_range(bb, 0, len); - } - } -} - -/** - * nvdimm_badblocks_populate() - Convert a list of poison ranges to badblocks - * @region: parent region of the range to interrogate - * @bb: badblocks instance to populate - * @res: resource range to consider - * - * The poison list generated during bus initialization may contain - * multiple, possibly overlapping physical address ranges. Compare each - * of these ranges to the resource range currently being initialized, - * and add badblocks entries for all matching sub-ranges - */ -void nvdimm_badblocks_populate(struct nd_region *nd_region, - struct badblocks *bb, const struct resource *res) -{ - struct nvdimm_bus *nvdimm_bus; - struct list_head *poison_list; - - if (!is_memory(&nd_region->dev)) { - dev_WARN_ONCE(&nd_region->dev, 1, - "%s only valid for pmem regions\n", __func__); - return; - } - nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev); - poison_list = &nvdimm_bus->poison_list; - - nvdimm_bus_lock(&nvdimm_bus->dev); - badblocks_populate(poison_list, bb, res); - nvdimm_bus_unlock(&nvdimm_bus->dev); -} -EXPORT_SYMBOL_GPL(nvdimm_badblocks_populate); - -static void append_poison_entry(struct nvdimm_bus *nvdimm_bus, - struct nd_poison *pl, u64 addr, u64 length) -{ - lockdep_assert_held(&nvdimm_bus->poison_lock); - pl->start = addr; - pl->length = length; - list_add_tail(&pl->list, &nvdimm_bus->poison_list); -} - -static int add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length, - gfp_t flags) -{ - struct nd_poison *pl; - - pl = kzalloc(sizeof(*pl), flags); - if (!pl) - return -ENOMEM; - - append_poison_entry(nvdimm_bus, pl, addr, length); - return 0; -} - -static int bus_add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length) -{ - struct nd_poison *pl, *pl_new; - - spin_unlock(&nvdimm_bus->poison_lock); - pl_new = kzalloc(sizeof(*pl_new), GFP_KERNEL); - spin_lock(&nvdimm_bus->poison_lock); - - if (list_empty(&nvdimm_bus->poison_list)) { - if (!pl_new) - return -ENOMEM; - append_poison_entry(nvdimm_bus, pl_new, addr, length); - return 0; - } - - /* - * There is a chance this is a duplicate, check for those first. - * This will be the common case as ARS_STATUS returns all known - * errors in the SPA space, and we can't query it per region - */ - list_for_each_entry(pl, &nvdimm_bus->poison_list, list) - if (pl->start == addr) { - /* If length has changed, update this list entry */ - if (pl->length != length) - pl->length = length; - kfree(pl_new); - return 0; - } - - /* - * If not a duplicate or a simple length update, add the entry as is, - * as any overlapping ranges will get resolved when the list is consumed - * and converted to badblocks - */ - if (!pl_new) - return -ENOMEM; - append_poison_entry(nvdimm_bus, pl_new, addr, length); - - return 0; -} - -int nvdimm_bus_add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length) -{ - int rc; - - spin_lock(&nvdimm_bus->poison_lock); - rc = bus_add_poison(nvdimm_bus, addr, length); - spin_unlock(&nvdimm_bus->poison_lock); - - return rc; -} -EXPORT_SYMBOL_GPL(nvdimm_bus_add_poison); - -void nvdimm_forget_poison(struct nvdimm_bus *nvdimm_bus, phys_addr_t start, - unsigned int len) -{ - struct list_head *poison_list = &nvdimm_bus->poison_list; - u64 clr_end = start + len - 1; - struct nd_poison *pl, *next; - - spin_lock(&nvdimm_bus->poison_lock); - WARN_ON_ONCE(list_empty(poison_list)); - - /* - * [start, clr_end] is the poison interval being cleared. - * [pl->start, pl_end] is the poison_list entry we're comparing - * the above interval against. The poison list entry may need - * to be modified (update either start or length), deleted, or - * split into two based on the overlap characteristics - */ - - list_for_each_entry_safe(pl, next, poison_list, list) { - u64 pl_end = pl->start + pl->length - 1; - - /* Skip intervals with no intersection */ - if (pl_end < start) - continue; - if (pl->start > clr_end) - continue; - /* Delete completely overlapped poison entries */ - if ((pl->start >= start) && (pl_end <= clr_end)) { - list_del(&pl->list); - kfree(pl); - continue; - } - /* Adjust start point of partially cleared entries */ - if ((start <= pl->start) && (clr_end > pl->start)) { - pl->length -= clr_end - pl->start + 1; - pl->start = clr_end + 1; - continue; - } - /* Adjust pl->length for partial clearing at the tail end */ - if ((pl->start < start) && (pl_end <= clr_end)) { - /* pl->start remains the same */ - pl->length = start - pl->start; - continue; - } - /* - * If clearing in the middle of an entry, we split it into - * two by modifying the current entry to represent one half of - * the split, and adding a new entry for the second half. - */ - if ((pl->start < start) && (pl_end > clr_end)) { - u64 new_start = clr_end + 1; - u64 new_len = pl_end - new_start + 1; - - /* Add new entry covering the right half */ - add_poison(nvdimm_bus, new_start, new_len, GFP_NOWAIT); - /* Adjust this entry to cover the left half */ - pl->length = start - pl->start; - continue; - } - } - spin_unlock(&nvdimm_bus->poison_lock); -} -EXPORT_SYMBOL_GPL(nvdimm_forget_poison); +EXPORT_SYMBOL_GPL(nvdimm_bus_add_badrange); #ifdef CONFIG_BLK_DEV_INTEGRITY int nd_integrity_init(struct gendisk *disk, unsigned long meta_size) diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h index 86bc19ae30da..79274ead54fb 100644 --- a/drivers/nvdimm/nd-core.h +++ b/drivers/nvdimm/nd-core.h @@ -29,10 +29,9 @@ struct nvdimm_bus { struct list_head list; struct device dev; int id, probe_active; - struct list_head poison_list; struct list_head mapping_list; struct mutex reconfig_mutex; - spinlock_t poison_lock; + struct badrange badrange; }; struct nvdimm { diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 156be00e1f76..e958f3724c41 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -34,12 +34,6 @@ enum { NVDIMM_IO_ATOMIC = 1, }; -struct nd_poison { - u64 start; - u64 length; - struct list_head list; -}; - struct nvdimm_drvdata { struct device *dev; int nslabel_size; diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h index 3eaad2fbf284..f8109ddb5ef1 100644 --- a/include/linux/libnvdimm.h +++ b/include/linux/libnvdimm.h @@ -18,6 +18,18 @@ #include #include #include +#include + +struct badrange_entry { + u64 start; + u64 length; + struct list_head list; +}; + +struct badrange { + struct list_head list; + spinlock_t lock; +}; enum { /* when a dimm supports both PMEM and BLK access a label is required */ @@ -129,9 +141,12 @@ static inline struct nd_blk_region_desc *to_blk_region_desc( } -int nvdimm_bus_add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length); -void nvdimm_forget_poison(struct nvdimm_bus *nvdimm_bus, - phys_addr_t start, unsigned int len); +void badrange_init(struct badrange *badrange); +int badrange_add(struct badrange *badrange, u64 addr, u64 length); +void badrange_forget(struct badrange *badrange, phys_addr_t start, + unsigned int len); +int nvdimm_bus_add_badrange(struct nvdimm_bus *nvdimm_bus, u64 addr, + u64 length); struct nvdimm_bus *nvdimm_bus_register(struct device *parent, struct nvdimm_bus_descriptor *nfit_desc); void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus); diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild index d870520da68b..3272ab5a5cb9 100644 --- a/tools/testing/nvdimm/Kbuild +++ b/tools/testing/nvdimm/Kbuild @@ -69,6 +69,7 @@ libnvdimm-y += $(NVDIMM_SRC)/region_devs.o libnvdimm-y += $(NVDIMM_SRC)/region.o libnvdimm-y += $(NVDIMM_SRC)/namespace_devs.o libnvdimm-y += $(NVDIMM_SRC)/label.o +libnvdimm-y += $(NVDIMM_SRC)/badrange.o libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o -- GitLab From 9fb1a1903345fea598f48277576a3589a972b72e Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Mon, 30 Oct 2017 13:22:20 -0700 Subject: [PATCH 1553/2898] nfit_test: add error injection DSMs Add nfit_test emulation for the new ACPI 6.2 error injectino DSMs. This will allow unit tests to selectively inject the errors they wish to test for. Signed-off-by: Dave Jiang [vishal: Move injection functions to ND_CMD_CALL] [vishal: Add support for the notification option] [vishal: move an nfit_test private definition into a local header] Signed-off-by: Vishal Verma Signed-off-by: Dan Williams --- tools/testing/nvdimm/test/nfit.c | 187 ++++++++++++++++++++++---- tools/testing/nvdimm/test/nfit_test.h | 5 + 2 files changed, 168 insertions(+), 24 deletions(-) diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 3a3bad348d56..788b1a5d6c5a 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -168,8 +168,12 @@ struct nfit_test { spinlock_t lock; } ars_state; struct device *dimm_dev[NUM_DCR]; + struct badrange badrange; + struct work_struct work; }; +static struct workqueue_struct *nfit_wq; + static struct nfit_test *to_nfit_test(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -234,48 +238,68 @@ static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd, return rc; } -#define NFIT_TEST_ARS_RECORDS 4 #define NFIT_TEST_CLEAR_ERR_UNIT 256 static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd, unsigned int buf_len) { + int ars_recs; + if (buf_len < sizeof(*nd_cmd)) return -EINVAL; + /* for testing, only store up to n records that fit within 4k */ + ars_recs = SZ_4K / sizeof(struct nd_ars_record); + nd_cmd->max_ars_out = sizeof(struct nd_cmd_ars_status) - + NFIT_TEST_ARS_RECORDS * sizeof(struct nd_ars_record); + + ars_recs * sizeof(struct nd_ars_record); nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16; nd_cmd->clear_err_unit = NFIT_TEST_CLEAR_ERR_UNIT; return 0; } -/* - * Initialize the ars_state to return an ars_result 1 second in the future with - * a 4K error range in the middle of the requested address range. - */ -static void post_ars_status(struct ars_state *ars_state, u64 addr, u64 len) +static void post_ars_status(struct ars_state *ars_state, + struct badrange *badrange, u64 addr, u64 len) { struct nd_cmd_ars_status *ars_status; struct nd_ars_record *ars_record; + struct badrange_entry *be; + u64 end = addr + len - 1; + int i = 0; ars_state->deadline = jiffies + 1*HZ; ars_status = ars_state->ars_status; ars_status->status = 0; - ars_status->out_length = sizeof(struct nd_cmd_ars_status) - + sizeof(struct nd_ars_record); ars_status->address = addr; ars_status->length = len; ars_status->type = ND_ARS_PERSISTENT; - ars_status->num_records = 1; - ars_record = &ars_status->records[0]; - ars_record->handle = 0; - ars_record->err_address = addr + len / 2; - ars_record->length = SZ_4K; + + spin_lock(&badrange->lock); + list_for_each_entry(be, &badrange->list, list) { + u64 be_end = be->start + be->length - 1; + u64 rstart, rend; + + /* skip entries outside the range */ + if (be_end < addr || be->start > end) + continue; + + rstart = (be->start < addr) ? addr : be->start; + rend = (be_end < end) ? be_end : end; + ars_record = &ars_status->records[i]; + ars_record->handle = 0; + ars_record->err_address = rstart; + ars_record->length = rend - rstart + 1; + i++; + } + spin_unlock(&badrange->lock); + ars_status->num_records = i; + ars_status->out_length = sizeof(struct nd_cmd_ars_status) + + i * sizeof(struct nd_ars_record); } -static int nfit_test_cmd_ars_start(struct ars_state *ars_state, +static int nfit_test_cmd_ars_start(struct nfit_test *t, + struct ars_state *ars_state, struct nd_cmd_ars_start *ars_start, unsigned int buf_len, int *cmd_rc) { @@ -289,7 +313,7 @@ static int nfit_test_cmd_ars_start(struct ars_state *ars_state, } else { ars_start->status = 0; ars_start->scrub_time = 1; - post_ars_status(ars_state, ars_start->address, + post_ars_status(ars_state, &t->badrange, ars_start->address, ars_start->length); *cmd_rc = 0; } @@ -456,6 +480,93 @@ static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t, return 0; } +static void uc_error_notify(struct work_struct *work) +{ + struct nfit_test *t = container_of(work, typeof(*t), work); + + __acpi_nfit_notify(&t->pdev.dev, t, NFIT_NOTIFY_UC_MEMORY_ERROR); +} + +static int nfit_test_cmd_ars_error_inject(struct nfit_test *t, + struct nd_cmd_ars_err_inj *err_inj, unsigned int buf_len) +{ + int rc; + + if (buf_len < sizeof(*err_inj)) { + rc = -EINVAL; + goto err; + } + + if (err_inj->err_inj_spa_range_length <= 0) { + rc = -EINVAL; + goto err; + } + + rc = badrange_add(&t->badrange, err_inj->err_inj_spa_range_base, + err_inj->err_inj_spa_range_length); + if (rc < 0) + goto err; + + if (err_inj->err_inj_options & (1 << ND_ARS_ERR_INJ_OPT_NOTIFY)) + queue_work(nfit_wq, &t->work); + + err_inj->status = 0; + return 0; + +err: + err_inj->status = NFIT_ARS_INJECT_INVALID; + return rc; +} + +static int nfit_test_cmd_ars_inject_clear(struct nfit_test *t, + struct nd_cmd_ars_err_inj_clr *err_clr, unsigned int buf_len) +{ + int rc; + + if (buf_len < sizeof(*err_clr)) { + rc = -EINVAL; + goto err; + } + + if (err_clr->err_inj_clr_spa_range_length <= 0) { + rc = -EINVAL; + goto err; + } + + badrange_forget(&t->badrange, err_clr->err_inj_clr_spa_range_base, + err_clr->err_inj_clr_spa_range_length); + + err_clr->status = 0; + return 0; + +err: + err_clr->status = NFIT_ARS_INJECT_INVALID; + return rc; +} + +static int nfit_test_cmd_ars_inject_status(struct nfit_test *t, + struct nd_cmd_ars_err_inj_stat *err_stat, + unsigned int buf_len) +{ + struct badrange_entry *be; + int max = SZ_4K / sizeof(struct nd_error_stat_query_record); + int i = 0; + + err_stat->status = 0; + spin_lock(&t->badrange.lock); + list_for_each_entry(be, &t->badrange.list, list) { + err_stat->record[i].err_inj_stat_spa_range_base = be->start; + err_stat->record[i].err_inj_stat_spa_range_length = be->length; + i++; + if (i > max) + break; + } + spin_unlock(&t->badrange.lock); + err_stat->inj_err_rec_count = i; + + return 0; +} + static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) @@ -543,6 +654,18 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, rc = nfit_test_cmd_translate_spa( acpi_desc->nvdimm_bus, buf, buf_len); return rc; + case NFIT_CMD_ARS_INJECT_SET: + rc = nfit_test_cmd_ars_error_inject(t, buf, + buf_len); + return rc; + case NFIT_CMD_ARS_INJECT_CLEAR: + rc = nfit_test_cmd_ars_inject_clear(t, buf, + buf_len); + return rc; + case NFIT_CMD_ARS_INJECT_GET: + rc = nfit_test_cmd_ars_inject_status(t, buf, + buf_len); + return rc; default: return -ENOTTY; } @@ -556,8 +679,8 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, rc = nfit_test_cmd_ars_cap(buf, buf_len); break; case ND_CMD_ARS_START: - rc = nfit_test_cmd_ars_start(ars_state, buf, buf_len, - cmd_rc); + rc = nfit_test_cmd_ars_start(t, ars_state, buf, + buf_len, cmd_rc); break; case ND_CMD_ARS_STATUS: rc = nfit_test_cmd_ars_status(ars_state, buf, buf_len, @@ -664,10 +787,9 @@ static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr) static int ars_state_init(struct device *dev, struct ars_state *ars_state) { + /* for testing, only store up to n records that fit within 4k */ ars_state->ars_status = devm_kzalloc(dev, - sizeof(struct nd_cmd_ars_status) - + sizeof(struct nd_ars_record) * NFIT_TEST_ARS_RECORDS, - GFP_KERNEL); + sizeof(struct nd_cmd_ars_status) + SZ_4K, GFP_KERNEL); if (!ars_state->ars_status) return -ENOMEM; spin_lock_init(&ars_state->lock); @@ -1517,7 +1639,8 @@ static void nfit_test0_setup(struct nfit_test *t) + i * sizeof(u64); } - post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); + post_ars_status(&t->ars_state, &t->badrange, t->spa_set_dma[0], + SPA0_SIZE); acpi_desc = &t->acpi_desc; set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en); @@ -1531,6 +1654,9 @@ static void nfit_test0_setup(struct nfit_test *t) set_bit(ND_CMD_CALL, &acpi_desc->bus_cmd_force_en); set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en); set_bit(NFIT_CMD_TRANSLATE_SPA, &acpi_desc->bus_nfit_cmd_force_en); + set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_nfit_cmd_force_en); + set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_nfit_cmd_force_en); + set_bit(NFIT_CMD_ARS_INJECT_GET, &acpi_desc->bus_nfit_cmd_force_en); } static void nfit_test1_setup(struct nfit_test *t) @@ -1620,7 +1746,8 @@ static void nfit_test1_setup(struct nfit_test *t) dcr->code = NFIT_FIC_BYTE; dcr->windows = 0; - post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE); + post_ars_status(&t->ars_state, &t->badrange, t->spa_set_dma[0], + SPA2_SIZE); acpi_desc = &t->acpi_desc; set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en); @@ -1718,7 +1845,10 @@ static int nfit_ctl_test(struct device *dev) .module = THIS_MODULE, .provider_name = "ACPI.NFIT", .ndctl = acpi_nfit_ctl, - .bus_dsm_mask = 1UL << NFIT_CMD_TRANSLATE_SPA, + .bus_dsm_mask = 1UL << NFIT_CMD_TRANSLATE_SPA + | 1UL << NFIT_CMD_ARS_INJECT_SET + | 1UL << NFIT_CMD_ARS_INJECT_CLEAR + | 1UL << NFIT_CMD_ARS_INJECT_GET, }, .dev = &adev->dev, }; @@ -2017,6 +2147,10 @@ static __init int nfit_test_init(void) nfit_test_setup(nfit_test_lookup, nfit_test_evaluate_dsm); + nfit_wq = create_singlethread_workqueue("nfit"); + if (!nfit_wq) + return -ENOMEM; + nfit_test_dimm = class_create(THIS_MODULE, "nfit_test_dimm"); if (IS_ERR(nfit_test_dimm)) { rc = PTR_ERR(nfit_test_dimm); @@ -2033,6 +2167,7 @@ static __init int nfit_test_init(void) goto err_register; } INIT_LIST_HEAD(&nfit_test->resources); + badrange_init(&nfit_test->badrange); switch (i) { case 0: nfit_test->num_pm = NUM_PM; @@ -2068,6 +2203,7 @@ static __init int nfit_test_init(void) goto err_register; instances[i] = nfit_test; + INIT_WORK(&nfit_test->work, uc_error_notify); } rc = platform_driver_register(&nfit_test_driver); @@ -2076,6 +2212,7 @@ static __init int nfit_test_init(void) return 0; err_register: + destroy_workqueue(nfit_wq); for (i = 0; i < NUM_NFITS; i++) if (instances[i]) platform_device_unregister(&instances[i]->pdev); @@ -2091,6 +2228,8 @@ static __exit void nfit_test_exit(void) { int i; + flush_workqueue(nfit_wq); + destroy_workqueue(nfit_wq); for (i = 0; i < NUM_NFITS; i++) platform_device_unregister(&instances[i]->pdev); platform_driver_unregister(&nfit_test_driver); diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h index 52c83be9dcfa..113b44675a71 100644 --- a/tools/testing/nvdimm/test/nfit_test.h +++ b/tools/testing/nvdimm/test/nfit_test.h @@ -33,6 +33,11 @@ struct nfit_test_resource { }; #define ND_TRANSLATE_SPA_STATUS_INVALID_SPA 2 +#define NFIT_ARS_INJECT_INVALID 2 + +enum err_inj_options { + ND_ARS_ERR_INJ_OPT_NOTIFY = 0, +}; /* nfit commands */ enum nfit_cmd_num { -- GitLab From 89360b87c3efa5d265a3b43dd8fc245c8f4356e3 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Mon, 30 Oct 2017 13:22:21 -0700 Subject: [PATCH 1554/2898] libnvdimm, badrange: remove a WARN for list_empty Now that we're reusing the badrange functions for nfit_test, and that exposes badrange injection/clearing to userspace via the DSM paths, it is plausible that a user may call the clear DSM multiple times. Since it is harmless to do so, we can remove the WARN in badrange_forget. Cc: Dave Jiang Cc: Dan Williams Signed-off-by: Vishal Verma Signed-off-by: Dan Williams --- drivers/nvdimm/badrange.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/nvdimm/badrange.c b/drivers/nvdimm/badrange.c index 0b67dcf43234..e068d72b4357 100644 --- a/drivers/nvdimm/badrange.c +++ b/drivers/nvdimm/badrange.c @@ -114,7 +114,6 @@ void badrange_forget(struct badrange *badrange, phys_addr_t start, struct badrange_entry *bre, *next; spin_lock(&badrange->lock); - WARN_ON_ONCE(list_empty(badrange_list)); /* * [start, clr_end] is the badrange interval being cleared. -- GitLab From 5e096ef3b29e6113a7aa6a7dc4871987efa99bcb Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Mon, 30 Oct 2017 13:22:23 -0700 Subject: [PATCH 1555/2898] nfit_test: when clearing poison, also remove badrange entries The injected badrange entries can only be cleared from the kernel's accounting by writing to the affected blocks, so when such a write sends the clear errror DSM to nfit_test, also clear the ranges from nfit_test's badrange list. This lets an 'ARS Inject error status' DSM to return the correct status, omitting the cleared ranges. Cc: Dave Jiang Cc: Dan Williams Signed-off-by: Vishal Verma Reviewed-by: Dave Jiang Signed-off-by: Dan Williams --- tools/testing/nvdimm/test/nfit.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 788b1a5d6c5a..79c5cb23693f 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -344,7 +344,8 @@ static int nfit_test_cmd_ars_status(struct ars_state *ars_state, return 0; } -static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err, +static int nfit_test_cmd_clear_error(struct nfit_test *t, + struct nd_cmd_clear_error *clear_err, unsigned int buf_len, int *cmd_rc) { const u64 mask = NFIT_TEST_CLEAR_ERR_UNIT - 1; @@ -354,12 +355,7 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err, if ((clear_err->address & mask) || (clear_err->length & mask)) return -EINVAL; - /* - * Report 'all clear' success for all commands even though a new - * scrub will find errors again. This is enough to have the - * error removed from the 'badblocks' tracking in the pmem - * driver. - */ + badrange_forget(&t->badrange, clear_err->address, clear_err->length); clear_err->status = 0; clear_err->cleared = clear_err->length; *cmd_rc = 0; @@ -687,7 +683,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, cmd_rc); break; case ND_CMD_CLEAR_ERROR: - rc = nfit_test_cmd_clear_error(buf, buf_len, cmd_rc); + rc = nfit_test_cmd_clear_error(t, buf, buf_len, cmd_rc); break; default: return -ENOTTY; -- GitLab From d8d46ae97ffd4ace4b8a7f45c232ff4bb8b6c129 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 2 Nov 2017 12:26:42 +0100 Subject: [PATCH 1556/2898] drm/amdgpu/display: remove unused REG_OFFSET macro The name conflicts with another macro of the same name on the ARM ixp4xx platform, leading to build errors. Neither of the users actually should use a name that generic, but the other one was here first and the dc driver doesn't actually use it. Reviewed-by: Harry Wentland Signed-off-by: Arnd Bergmann Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_services.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index c8190c38a644..d4917037ac42 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -160,9 +160,6 @@ unsigned int generic_reg_wait(const struct dc_context *ctx, /* These macros need to be used with soc15 registers in order to retrieve * the actual offset. */ -#define REG_OFFSET(reg) (reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX]) -#define REG_BIF_OFFSET(reg) (reg + NBIF_BASE.instance[0].segment[reg##_BASE_IDX]) - #define dm_write_reg_soc15(ctx, reg, inst_offset, value) \ dm_write_reg_func(ctx, reg + DCE_BASE.instance[0].segment[reg##_BASE_IDX] + inst_offset, value, __func__) -- GitLab From 1f3493faa8d73b0332d46ea79448b10b66fb1af0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 2 Nov 2017 12:26:43 +0100 Subject: [PATCH 1557/2898] drm/amdgpu/display: fix integer arithmetic problem gcc warns about an ambiguous integer calculation: drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dce_calcs.c: In function 'calculate_bandwidth': drivers/gpu/drm/amd/amdgpu/../display/dc/calcs/dce_calcs.c:534:5: error: this decimal constant is unsigned only in ISO C90 [-Werror] data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); ^~~~ Marking the constant as explicitly unsigned makes it work fine everywhere without warnings. Reviewed-by: Harry Wentland Signed-off-by: Arnd Bergmann Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 15cbfc400633..4f8a95368ffc 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -531,7 +531,7 @@ static void calculate_bandwidth( } switch (data->lb_bpc[i]) { case 8: - data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); + data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(2401171875ul, 100000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); break; case 10: data->lb_line_pitch = bw_ceil2(bw_mul(bw_div(bw_frc_to_fixed(300234375, 10000000), bw_int_to_fixed(3)), bw_ceil2(data->source_width_in_lb, bw_int_to_fixed(8))), bw_int_to_fixed(48)); -- GitLab From d6fa71f1c003fb2bc824276bb424a4171f9a717f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 30 Oct 2017 14:07:37 +0100 Subject: [PATCH 1558/2898] platform/x86: peaq_wmi: Fix missing terminating entry for peaq_dmi_table Add missing terminating entry to peaq_dmi_table. Fixes: 3b95206110a2 ("platform/x86: peaq-wmi: Add DMI check before ...") Cc: stable@vger.kernel.org Reported-by: Fengguang Wu Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/peaq-wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/peaq-wmi.c b/drivers/platform/x86/peaq-wmi.c index 67fa3fa32011..2da48ecc90c1 100644 --- a/drivers/platform/x86/peaq-wmi.c +++ b/drivers/platform/x86/peaq-wmi.c @@ -73,6 +73,7 @@ static const struct dmi_system_id peaq_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"), }, }, + {} }; static int __init peaq_wmi_init(void) -- GitLab From f6c7b8031d7e177c837c23d1065204b697fb54b7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 30 Oct 2017 14:07:38 +0100 Subject: [PATCH 1559/2898] platform/x86: peaq-wmi: Remove unnecessary checks from peaq_wmi_exit peaq_wmi_exit will only ever get called if peaq_wmi_init succeeds, so there is no need to repeat the checks from peaq_wmi_init. Suggested-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/peaq-wmi.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/platform/x86/peaq-wmi.c b/drivers/platform/x86/peaq-wmi.c index 2da48ecc90c1..9b9e1f39bbfb 100644 --- a/drivers/platform/x86/peaq-wmi.c +++ b/drivers/platform/x86/peaq-wmi.c @@ -66,7 +66,7 @@ static void peaq_wmi_poll(struct input_polled_dev *dev) } /* Some other devices (Shuttle XS35) use the same WMI GUID for other purposes */ -static const struct dmi_system_id peaq_dmi_table[] = { +static const struct dmi_system_id peaq_dmi_table[] __initconst = { { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"), @@ -102,12 +102,6 @@ static int __init peaq_wmi_init(void) static void __exit peaq_wmi_exit(void) { - if (!dmi_check_system(peaq_dmi_table)) - return; - - if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID)) - return; - input_unregister_polled_device(peaq_poll_dev); } -- GitLab From 5c24c05efa4800bbe42de0ad3e752c5fd75fa351 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 19 Oct 2017 09:44:14 +0200 Subject: [PATCH 1560/2898] platform/x86: silead_dmi: Fix GP-electronic T701 entry The GP-electronic T701 has its LCD panel mounted upside-down, initially my plan was to fix this by transparently rotating the image in the i915 driver (my "drm/i915: Deal with upside-down mounted LCD" patch), but that approach has been rejected instead the kernel will now export a "panel orientation" property on the drm-connector for the panel and let userspace deal with it. But userspace expects the touchscreen coordinates to match the panel coordinates *before* applying any rotation, so now that we no longer hide the upside-down-ness of the LCD panel from userspace the coordinates being generated are wrong and we need to apply a rotation of 180 degrees to the coordinates to fix this. Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/silead_dmi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c index a88823086406..fadfce9b3f5f 100644 --- a/drivers/platform/x86/silead_dmi.c +++ b/drivers/platform/x86/silead_dmi.c @@ -83,6 +83,8 @@ static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = { static const struct property_entry gp_electronic_t701_props[] = { PROPERTY_ENTRY_U32("touchscreen-size-x", 960), PROPERTY_ENTRY_U32("touchscreen-size-y", 640), + PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-gp-electronic-t701.fw"), { } -- GitLab From 3fcf2b2a2529e268c537d8ad9dac5987ebc8a2f7 Mon Sep 17 00:00:00 2001 From: Sergey Tshovrebov Date: Fri, 27 Oct 2017 12:27:07 +0200 Subject: [PATCH 1561/2898] platform/x86: silead_dmi: Add entry for the Digma e200 tablet Add touchscreen platform data for the Digma e200 tablet. Signed-off-by: Sergey Tshovrebov Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko --- drivers/platform/x86/silead_dmi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c index fadfce9b3f5f..5af3379b0573 100644 --- a/drivers/platform/x86/silead_dmi.c +++ b/drivers/platform/x86/silead_dmi.c @@ -151,6 +151,22 @@ static const struct silead_ts_dmi_data chuwi_hi8_pro_data = { .properties = chuwi_hi8_pro_props, }; +static const struct property_entry digma_citi_e200_props[] = { + PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), + PROPERTY_ENTRY_U32("touchscreen-size-y", 1500), + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), + PROPERTY_ENTRY_STRING("firmware-name", + "gsl1686-digma_citi_e200.fw"), + PROPERTY_ENTRY_U32("silead,max-fingers", 10), + PROPERTY_ENTRY_BOOL("silead,home-button"), + { } +}; + +static const struct silead_ts_dmi_data digma_citi_e200_data = { + .acpi_name = "MSSL1680:00", + .properties = digma_citi_e200_props, +}; + static const struct dmi_system_id silead_ts_dmi_table[] = { { /* CUBE iwork8 Air */ @@ -242,6 +258,15 @@ static const struct dmi_system_id silead_ts_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"), }, }, + { + /* Digma Citi E200 */ + .driver_data = (void *)&digma_citi_e200_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Digma"), + DMI_MATCH(DMI_PRODUCT_NAME, "CITI E200"), + DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), + }, + }, { }, }; -- GitLab From 455e027f33a03ddffe82c36f430a4d173e840b75 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 11 Oct 2017 11:41:21 +0200 Subject: [PATCH 1562/2898] platform/x86: intel_cht_int33fe: Update fusb302 type string, add properties The fusb302 driver as merged in staging uses "typec_fusb302" as i2c-id rather then just "fusb302" and needs us to set a number of device- properties, adjust the intel_cht_int33fe driver accordingly. One of the properties set is max-snk-mv which makes the fusb302 driver negotiate up to 12V charging voltage, which is a bad idea on boards which are not setup to handle this, so this commit also adds 2 extra sanity checks to make sure that the expected Whiskey Cove PMIC + TI bq24292i charger combo, which can handle 12V, is present. Signed-off-by: Hans de Goede Acked-by: Andy Shevchenko Signed-off-by: Andy Shevchenko --- drivers/platform/x86/Kconfig | 6 +++- drivers/platform/x86/intel_cht_int33fe.c | 44 +++++++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 0fdf68865c5e..87c8c36efce4 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -806,7 +806,7 @@ config ACPI_CMPC config INTEL_CHT_INT33FE tristate "Intel Cherry Trail ACPI INT33FE Driver" - depends on X86 && ACPI && I2C + depends on X86 && ACPI && I2C && REGULATOR ---help--- This driver add support for the INT33FE ACPI device found on some Intel Cherry Trail devices. @@ -817,6 +817,10 @@ config INTEL_CHT_INT33FE This driver instantiates i2c-clients for these, so that standard i2c drivers for these chips can bind to the them. + If you enable this driver it is advised to also select + CONFIG_TYPEC_FUSB302=m, CONFIG_CHARGER_BQ24190=m and + CONFIG_BATTERY_MAX17042=m. + config INTEL_INT0002_VGPIO tristate "Intel ACPI INT0002 Virtual GPIO driver" depends on GPIOLIB && ACPI diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index 286c6207765d..380ef7ec094f 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #define EXPECTED_PTYPE 4 @@ -77,12 +78,21 @@ static const struct property_entry max17047_props[] = { { } }; +static const struct property_entry fusb302_props[] = { + PROPERTY_ENTRY_STRING("fcs,extcon-name", "cht_wcove_pwrsrc"), + PROPERTY_ENTRY_U32("fcs,max-sink-microvolt", 12000000), + PROPERTY_ENTRY_U32("fcs,max-sink-microamp", 3000000), + PROPERTY_ENTRY_U32("fcs,max-sink-microwatt", 36000000), + { } +}; + static int cht_int33fe_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct i2c_board_info board_info; struct cht_int33fe_data *data; struct i2c_client *max17047; + struct regulator *regulator; unsigned long long ptyp; acpi_status status; int fusb302_irq; @@ -101,6 +111,34 @@ static int cht_int33fe_probe(struct i2c_client *client) if (ptyp != EXPECTED_PTYPE) return -ENODEV; + /* Check presence of INT34D3 (hardware-rev 3) expected for ptype == 4 */ + if (!acpi_dev_present("INT34D3", "1", 3)) { + dev_err(dev, "Error PTYPE == %d, but no INT34D3 device\n", + EXPECTED_PTYPE); + return -ENODEV; + } + + /* + * We expect the WC PMIC to be paired with a TI bq24292i charger-IC. + * We check for the bq24292i vbus regulator here, this has 2 purposes: + * 1) The bq24292i allows charging with up to 12V, setting the fusb302's + * max-snk voltage to 12V with another charger-IC is not good. + * 2) For the fusb302 driver to get the bq24292i vbus regulator, the + * regulator-map, which is part of the bq24292i regulator_init_data, + * must be registered before the fusb302 is instantiated, otherwise + * it will end up with a dummy-regulator. + * Note "cht_wc_usb_typec_vbus" comes from the regulator_init_data + * which is defined in i2c-cht-wc.c from where the bq24292i i2c-client + * gets instantiated. We use regulator_get_optional here so that we + * don't end up getting a dummy-regulator ourselves. + */ + regulator = regulator_get_optional(dev, "cht_wc_usb_typec_vbus"); + if (IS_ERR(regulator)) { + ret = PTR_ERR(regulator); + return (ret == -ENODEV) ? -EPROBE_DEFER : ret; + } + regulator_put(regulator); + /* The FUSB302 uses the irq at index 1 and is the only irq user */ fusb302_irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 1); if (fusb302_irq < 0) { @@ -127,6 +165,7 @@ static int cht_int33fe_probe(struct i2c_client *client) } else { memset(&board_info, 0, sizeof(board_info)); strlcpy(board_info.type, "max17047", I2C_NAME_SIZE); + board_info.dev_name = "max17047"; board_info.properties = max17047_props; data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); if (!data->max17047) @@ -134,7 +173,9 @@ static int cht_int33fe_probe(struct i2c_client *client) } memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "fusb302", I2C_NAME_SIZE); + strlcpy(board_info.type, "typec_fusb302", I2C_NAME_SIZE); + board_info.dev_name = "fusb302"; + board_info.properties = fusb302_props; board_info.irq = fusb302_irq; data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info); @@ -142,6 +183,7 @@ static int cht_int33fe_probe(struct i2c_client *client) goto out_unregister_max17047; memset(&board_info, 0, sizeof(board_info)); + board_info.dev_name = "pi3usb30532"; strlcpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE); data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info); -- GitLab From 592e254502041f953e84d091eae2c68cba04c10b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 3 Nov 2017 12:21:21 +0100 Subject: [PATCH 1563/2898] mm: Handle 0 flags in _calc_vm_trans() macro _calc_vm_trans() does not handle the situation when some of the passed flags are 0 (which can happen if these VM flags do not make sense for the architecture). Improve the _calc_vm_trans() macro to return 0 in such situation. Since all passed flags are constant, this does not add any runtime overhead. Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- include/linux/mman.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/mman.h b/include/linux/mman.h index c8367041fafd..edb6cf6a81ed 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -63,8 +63,9 @@ static inline bool arch_validate_prot(unsigned long prot) * ("bit1" and "bit2" must be single bits) */ #define _calc_vm_trans(x, bit1, bit2) \ + ((!(bit1) || !(bit2)) ? 0 : \ ((bit1) <= (bit2) ? ((x) & (bit1)) * ((bit2) / (bit1)) \ - : ((x) & (bit1)) / ((bit1) / (bit2))) + : ((x) & (bit1)) / ((bit1) / (bit2)))) /* * Combine the mmap "prot" argument into "vm_flags" used internally. -- GitLab From 1c9725974074a047f6080eecc62c50a8e840d050 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 1 Nov 2017 16:36:30 +0100 Subject: [PATCH 1564/2898] mm: introduce MAP_SHARED_VALIDATE, a mechanism to safely define new mmap flags The mmap(2) syscall suffers from the ABI anti-pattern of not validating unknown flags. However, proposals like MAP_SYNC need a mechanism to define new behavior that is known to fail on older kernels without the support. Define a new MAP_SHARED_VALIDATE flag pattern that is guaranteed to fail on all legacy mmap implementations. It is worth noting that the original proposal was for a standalone MAP_VALIDATE flag. However, when that could not be supported by all archs Linus observed: I see why you *think* you want a bitmap. You think you want a bitmap because you want to make MAP_VALIDATE be part of MAP_SYNC etc, so that people can do ret = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_SYNC, fd, 0); and "know" that MAP_SYNC actually takes. And I'm saying that whole wish is bogus. You're fundamentally depending on special semantics, just make it explicit. It's already not portable, so don't try to make it so. Rename that MAP_VALIDATE as MAP_SHARED_VALIDATE, make it have a value of 0x3, and make people do ret = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED_VALIDATE | MAP_SYNC, fd, 0); and then the kernel side is easier too (none of that random garbage playing games with looking at the "MAP_VALIDATE bit", but just another case statement in that map type thing. Boom. Done. Similar to ->fallocate() we also want the ability to validate the support for new flags on a per ->mmap() 'struct file_operations' instance basis. Towards that end arrange for flags to be generically validated against a mmap_supported_flags exported by 'struct file_operations'. By default all existing flags are implicitly supported, but new flags require MAP_SHARED_VALIDATE and per-instance-opt-in. Cc: Jan Kara Cc: Arnd Bergmann Cc: Andy Lutomirski Cc: Andrew Morton Suggested-by: Christoph Hellwig Suggested-by: Linus Torvalds Reviewed-by: Ross Zwisler Signed-off-by: Dan Williams Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- arch/alpha/include/uapi/asm/mman.h | 1 + arch/mips/include/uapi/asm/mman.h | 1 + arch/parisc/include/uapi/asm/mman.h | 1 + arch/xtensa/include/uapi/asm/mman.h | 1 + include/linux/fs.h | 1 + include/linux/mman.h | 39 ++++++++++++++++++++ include/uapi/asm-generic/mman-common.h | 1 + mm/mmap.c | 15 ++++++++ tools/include/uapi/asm-generic/mman-common.h | 1 + 9 files changed, 61 insertions(+) diff --git a/arch/alpha/include/uapi/asm/mman.h b/arch/alpha/include/uapi/asm/mman.h index 3b26cc62dadb..f6d118aaedb9 100644 --- a/arch/alpha/include/uapi/asm/mman.h +++ b/arch/alpha/include/uapi/asm/mman.h @@ -11,6 +11,7 @@ #define MAP_SHARED 0x01 /* Share changes */ #define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */ #define MAP_TYPE 0x0f /* Mask for type of mapping (OSF/1 is _wrong_) */ #define MAP_FIXED 0x100 /* Interpret addr exactly */ #define MAP_ANONYMOUS 0x10 /* don't use a file */ diff --git a/arch/mips/include/uapi/asm/mman.h b/arch/mips/include/uapi/asm/mman.h index da3216007fe0..93268e4cd3c7 100644 --- a/arch/mips/include/uapi/asm/mman.h +++ b/arch/mips/include/uapi/asm/mman.h @@ -28,6 +28,7 @@ */ #define MAP_SHARED 0x001 /* Share changes */ #define MAP_PRIVATE 0x002 /* Changes are private */ +#define MAP_SHARED_VALIDATE 0x003 /* share + validate extension flags */ #define MAP_TYPE 0x00f /* Mask for type of mapping */ #define MAP_FIXED 0x010 /* Interpret addr exactly */ diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h index 775b5d5e41a1..bca652aa1677 100644 --- a/arch/parisc/include/uapi/asm/mman.h +++ b/arch/parisc/include/uapi/asm/mman.h @@ -11,6 +11,7 @@ #define MAP_SHARED 0x01 /* Share changes */ #define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */ #define MAP_TYPE 0x03 /* Mask for type of mapping */ #define MAP_FIXED 0x04 /* Interpret addr exactly */ #define MAP_ANONYMOUS 0x10 /* don't use a file */ diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h index b15b278aa314..9ab426374714 100644 --- a/arch/xtensa/include/uapi/asm/mman.h +++ b/arch/xtensa/include/uapi/asm/mman.h @@ -35,6 +35,7 @@ */ #define MAP_SHARED 0x001 /* Share changes */ #define MAP_PRIVATE 0x002 /* Changes are private */ +#define MAP_SHARED_VALIDATE 0x003 /* share + validate extension flags */ #define MAP_TYPE 0x00f /* Mask for type of mapping */ #define MAP_FIXED 0x010 /* Interpret addr exactly */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 13dab191a23e..57added3201d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1701,6 +1701,7 @@ struct file_operations { long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); + unsigned long mmap_supported_flags; int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); diff --git a/include/linux/mman.h b/include/linux/mman.h index edb6cf6a81ed..74452e3f2536 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -7,6 +7,45 @@ #include #include +/* + * Arrange for legacy / undefined architecture specific flags to be + * ignored by default in LEGACY_MAP_MASK. + */ +#ifndef MAP_32BIT +#define MAP_32BIT 0 +#endif +#ifndef MAP_HUGE_2MB +#define MAP_HUGE_2MB 0 +#endif +#ifndef MAP_HUGE_1GB +#define MAP_HUGE_1GB 0 +#endif +#ifndef MAP_UNINITIALIZED +#define MAP_UNINITIALIZED 0 +#endif + +/* + * The historical set of flags that all mmap implementations implicitly + * support when a ->mmap_validate() op is not provided in file_operations. + */ +#define LEGACY_MAP_MASK (MAP_SHARED \ + | MAP_PRIVATE \ + | MAP_FIXED \ + | MAP_ANONYMOUS \ + | MAP_DENYWRITE \ + | MAP_EXECUTABLE \ + | MAP_UNINITIALIZED \ + | MAP_GROWSDOWN \ + | MAP_LOCKED \ + | MAP_NORESERVE \ + | MAP_POPULATE \ + | MAP_NONBLOCK \ + | MAP_STACK \ + | MAP_HUGETLB \ + | MAP_32BIT \ + | MAP_HUGE_2MB \ + | MAP_HUGE_1GB) + extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; extern unsigned long sysctl_overcommit_kbytes; diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h index 203268f9231e..8ce7f5a0800f 100644 --- a/include/uapi/asm-generic/mman-common.h +++ b/include/uapi/asm-generic/mman-common.h @@ -16,6 +16,7 @@ #define MAP_SHARED 0x01 /* Share changes */ #define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */ #define MAP_TYPE 0x0f /* Mask for type of mapping */ #define MAP_FIXED 0x10 /* Interpret addr exactly */ #define MAP_ANONYMOUS 0x20 /* don't use a file */ diff --git a/mm/mmap.c b/mm/mmap.c index 680506faceae..924839fac0e6 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1387,9 +1387,24 @@ unsigned long do_mmap(struct file *file, unsigned long addr, if (file) { struct inode *inode = file_inode(file); + unsigned long flags_mask; + + flags_mask = LEGACY_MAP_MASK | file->f_op->mmap_supported_flags; switch (flags & MAP_TYPE) { case MAP_SHARED: + /* + * Force use of MAP_SHARED_VALIDATE with non-legacy + * flags. E.g. MAP_SYNC is dangerous to use with + * MAP_SHARED as you don't know which consistency model + * you will get. We silently ignore unsupported flags + * with MAP_SHARED to preserve backward compatibility. + */ + flags &= LEGACY_MAP_MASK; + /* fall through */ + case MAP_SHARED_VALIDATE: + if (flags & ~flags_mask) + return -EOPNOTSUPP; if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE)) return -EACCES; diff --git a/tools/include/uapi/asm-generic/mman-common.h b/tools/include/uapi/asm-generic/mman-common.h index 203268f9231e..8ce7f5a0800f 100644 --- a/tools/include/uapi/asm-generic/mman-common.h +++ b/tools/include/uapi/asm-generic/mman-common.h @@ -16,6 +16,7 @@ #define MAP_SHARED 0x01 /* Share changes */ #define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */ #define MAP_TYPE 0x0f /* Mask for type of mapping */ #define MAP_FIXED 0x10 /* Interpret addr exactly */ #define MAP_ANONYMOUS 0x20 /* don't use a file */ -- GitLab From d81b8a722f691a3907eb4a6df410ab517ba5bfcc Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:31 +0100 Subject: [PATCH 1565/2898] mm: Remove VM_FAULT_HWPOISON_LARGE_MASK It is unused. Reviewed-by: Ross Zwisler Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- include/linux/mm.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 065d99deb847..ca72b67153d5 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1182,8 +1182,6 @@ static inline void clear_page_pfmemalloc(struct page *page) #define VM_FAULT_FALLBACK 0x0800 /* huge page fault failed, fall back to small */ #define VM_FAULT_DONE_COW 0x1000 /* ->fault has fully handled COW */ -#define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ - #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \ VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \ VM_FAULT_FALLBACK) -- GitLab From 31a6f1a6e5a4a26040b67d8fa4256539b36f5893 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:32 +0100 Subject: [PATCH 1566/2898] dax: Simplify arguments of dax_insert_mapping() dax_insert_mapping() has lots of arguments and a lot of them is actuall duplicated by passing vm_fault structure as well. Change the function to take the same arguments as dax_pmd_insert_mapping(). Reviewed-by: Ross Zwisler Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index f001d8c72a06..0bc42ac294ca 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -820,23 +820,30 @@ int dax_writeback_mapping_range(struct address_space *mapping, } EXPORT_SYMBOL_GPL(dax_writeback_mapping_range); -static int dax_insert_mapping(struct address_space *mapping, - struct block_device *bdev, struct dax_device *dax_dev, - sector_t sector, size_t size, void *entry, - struct vm_area_struct *vma, struct vm_fault *vmf) +static sector_t dax_iomap_sector(struct iomap *iomap, loff_t pos) +{ + return iomap->blkno + (((pos & PAGE_MASK) - iomap->offset) >> 9); +} + +static int dax_insert_mapping(struct vm_fault *vmf, struct iomap *iomap, + loff_t pos, void *entry) { + const sector_t sector = dax_iomap_sector(iomap, pos); + struct vm_area_struct *vma = vmf->vma; + struct address_space *mapping = vma->vm_file->f_mapping; unsigned long vaddr = vmf->address; void *ret, *kaddr; pgoff_t pgoff; int id, rc; pfn_t pfn; - rc = bdev_dax_pgoff(bdev, sector, size, &pgoff); + rc = bdev_dax_pgoff(iomap->bdev, sector, PAGE_SIZE, &pgoff); if (rc) return rc; id = dax_read_lock(); - rc = dax_direct_access(dax_dev, pgoff, PHYS_PFN(size), &kaddr, &pfn); + rc = dax_direct_access(iomap->dax_dev, pgoff, PHYS_PFN(PAGE_SIZE), + &kaddr, &pfn); if (rc < 0) { dax_read_unlock(id); return rc; @@ -936,11 +943,6 @@ int __dax_zero_page_range(struct block_device *bdev, } EXPORT_SYMBOL_GPL(__dax_zero_page_range); -static sector_t dax_iomap_sector(struct iomap *iomap, loff_t pos) -{ - return iomap->blkno + (((pos & PAGE_MASK) - iomap->offset) >> 9); -} - static loff_t dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, struct iomap *iomap) @@ -1087,7 +1089,6 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, struct inode *inode = mapping->host; unsigned long vaddr = vmf->address; loff_t pos = (loff_t)vmf->pgoff << PAGE_SHIFT; - sector_t sector; struct iomap iomap = { 0 }; unsigned flags = IOMAP_FAULT; int error, major = 0; @@ -1140,9 +1141,9 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, goto error_finish_iomap; } - sector = dax_iomap_sector(&iomap, pos); - if (vmf->cow_page) { + sector_t sector = dax_iomap_sector(&iomap, pos); + switch (iomap.type) { case IOMAP_HOLE: case IOMAP_UNWRITTEN: @@ -1175,8 +1176,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT); major = VM_FAULT_MAJOR; } - error = dax_insert_mapping(mapping, iomap.bdev, iomap.dax_dev, - sector, PAGE_SIZE, entry, vmf->vma, vmf); + error = dax_insert_mapping(vmf, &iomap, pos, entry); /* -EBUSY is fine, somebody else faulted on the same PTE */ if (error == -EBUSY) error = 0; -- GitLab From 5e161e4066d3ebeaff95a4b979b42f8bf00494d5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:33 +0100 Subject: [PATCH 1567/2898] dax: Factor out getting of pfn out of iomap Factor out code to get pfn out of iomap that is shared between PTE and PMD fault path. Reviewed-by: Christoph Hellwig Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 83 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index 0bc42ac294ca..116eef8d6c69 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -825,30 +825,53 @@ static sector_t dax_iomap_sector(struct iomap *iomap, loff_t pos) return iomap->blkno + (((pos & PAGE_MASK) - iomap->offset) >> 9); } -static int dax_insert_mapping(struct vm_fault *vmf, struct iomap *iomap, - loff_t pos, void *entry) +static int dax_iomap_pfn(struct iomap *iomap, loff_t pos, size_t size, + pfn_t *pfnp) { const sector_t sector = dax_iomap_sector(iomap, pos); - struct vm_area_struct *vma = vmf->vma; - struct address_space *mapping = vma->vm_file->f_mapping; - unsigned long vaddr = vmf->address; - void *ret, *kaddr; pgoff_t pgoff; + void *kaddr; int id, rc; - pfn_t pfn; + long length; - rc = bdev_dax_pgoff(iomap->bdev, sector, PAGE_SIZE, &pgoff); + rc = bdev_dax_pgoff(iomap->bdev, sector, size, &pgoff); if (rc) return rc; - id = dax_read_lock(); - rc = dax_direct_access(iomap->dax_dev, pgoff, PHYS_PFN(PAGE_SIZE), - &kaddr, &pfn); - if (rc < 0) { - dax_read_unlock(id); - return rc; + length = dax_direct_access(iomap->dax_dev, pgoff, PHYS_PFN(size), + &kaddr, pfnp); + if (length < 0) { + rc = length; + goto out; } + rc = -EINVAL; + if (PFN_PHYS(length) < size) + goto out; + if (pfn_t_to_pfn(*pfnp) & (PHYS_PFN(size)-1)) + goto out; + /* For larger pages we need devmap */ + if (length > 1 && !pfn_t_devmap(*pfnp)) + goto out; + rc = 0; +out: dax_read_unlock(id); + return rc; +} + +static int dax_insert_mapping(struct vm_fault *vmf, struct iomap *iomap, + loff_t pos, void *entry) +{ + const sector_t sector = dax_iomap_sector(iomap, pos); + struct vm_area_struct *vma = vmf->vma; + struct address_space *mapping = vma->vm_file->f_mapping; + unsigned long vaddr = vmf->address; + void *ret; + int rc; + pfn_t pfn; + + rc = dax_iomap_pfn(iomap, pos, PAGE_SIZE, &pfn); + if (rc < 0) + return rc; ret = dax_insert_mapping_entry(mapping, vmf, entry, sector, 0); if (IS_ERR(ret)) @@ -1223,46 +1246,26 @@ static int dax_pmd_insert_mapping(struct vm_fault *vmf, struct iomap *iomap, { struct address_space *mapping = vmf->vma->vm_file->f_mapping; const sector_t sector = dax_iomap_sector(iomap, pos); - struct dax_device *dax_dev = iomap->dax_dev; - struct block_device *bdev = iomap->bdev; struct inode *inode = mapping->host; - const size_t size = PMD_SIZE; - void *ret = NULL, *kaddr; - long length = 0; - pgoff_t pgoff; + void *ret = NULL; pfn_t pfn = {}; - int id; + int rc; - if (bdev_dax_pgoff(bdev, sector, size, &pgoff) != 0) + rc = dax_iomap_pfn(iomap, pos, PMD_SIZE, &pfn); + if (rc < 0) goto fallback; - id = dax_read_lock(); - length = dax_direct_access(dax_dev, pgoff, PHYS_PFN(size), &kaddr, &pfn); - if (length < 0) - goto unlock_fallback; - length = PFN_PHYS(length); - - if (length < size) - goto unlock_fallback; - if (pfn_t_to_pfn(pfn) & PG_PMD_COLOUR) - goto unlock_fallback; - if (!pfn_t_devmap(pfn)) - goto unlock_fallback; - dax_read_unlock(id); - ret = dax_insert_mapping_entry(mapping, vmf, entry, sector, RADIX_DAX_PMD); if (IS_ERR(ret)) goto fallback; - trace_dax_pmd_insert_mapping(inode, vmf, length, pfn, ret); + trace_dax_pmd_insert_mapping(inode, vmf, PMD_SIZE, pfn, ret); return vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, pfn, vmf->flags & FAULT_FLAG_WRITE); -unlock_fallback: - dax_read_unlock(id); fallback: - trace_dax_pmd_insert_mapping_fallback(inode, vmf, length, pfn, ret); + trace_dax_pmd_insert_mapping_fallback(inode, vmf, PMD_SIZE, pfn, ret); return VM_FAULT_FALLBACK; } -- GitLab From a0987ad5c576626fdb40547f5ac99b4f90608dda Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:34 +0100 Subject: [PATCH 1568/2898] dax: Create local variable for VMA in dax_iomap_pte_fault() There are already two users and more are coming. Reviewed-by: Christoph Hellwig Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index 116eef8d6c69..c09465884bbe 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1108,7 +1108,8 @@ static int dax_fault_return(int error) static int dax_iomap_pte_fault(struct vm_fault *vmf, const struct iomap_ops *ops) { - struct address_space *mapping = vmf->vma->vm_file->f_mapping; + struct vm_area_struct *vma = vmf->vma; + struct address_space *mapping = vma->vm_file->f_mapping; struct inode *inode = mapping->host; unsigned long vaddr = vmf->address; loff_t pos = (loff_t)vmf->pgoff << PAGE_SHIFT; @@ -1196,7 +1197,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, case IOMAP_MAPPED: if (iomap.flags & IOMAP_F_NEW) { count_vm_event(PGMAJFAULT); - count_memcg_event_mm(vmf->vma->vm_mm, PGMAJFAULT); + count_memcg_event_mm(vma->vm_mm, PGMAJFAULT); major = VM_FAULT_MAJOR; } error = dax_insert_mapping(vmf, &iomap, pos, entry); -- GitLab From d2c43ef13327478b299db0f58193495367c6d4ae Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:35 +0100 Subject: [PATCH 1569/2898] dax: Create local variable for vmf->flags & FAULT_FLAG_WRITE test There are already two users and more are coming. Reviewed-by: Christoph Hellwig Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index c09465884bbe..5ea71381dba0 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1116,6 +1116,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, struct iomap iomap = { 0 }; unsigned flags = IOMAP_FAULT; int error, major = 0; + bool write = vmf->flags & FAULT_FLAG_WRITE; int vmf_ret = 0; void *entry; @@ -1130,7 +1131,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, goto out; } - if ((vmf->flags & FAULT_FLAG_WRITE) && !vmf->cow_page) + if (write && !vmf->cow_page) flags |= IOMAP_WRITE; entry = grab_mapping_entry(mapping, vmf->pgoff, 0); @@ -1207,7 +1208,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, break; case IOMAP_UNWRITTEN: case IOMAP_HOLE: - if (!(vmf->flags & FAULT_FLAG_WRITE)) { + if (!write) { vmf_ret = dax_load_hole(mapping, entry, vmf); goto finish_iomap; } -- GitLab From 1b5a1cb21e0cdfb001050c76dc31039cdece1a63 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:36 +0100 Subject: [PATCH 1570/2898] dax: Inline dax_insert_mapping() into the callsite dax_insert_mapping() has only one callsite and we will need to further fine tune what it does for synchronous faults. Just inline it into the callsite so that we don't have to pass awkward bools around. Reviewed-by: Christoph Hellwig Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index 5ea71381dba0..5b20c6456926 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -858,32 +858,6 @@ static int dax_iomap_pfn(struct iomap *iomap, loff_t pos, size_t size, return rc; } -static int dax_insert_mapping(struct vm_fault *vmf, struct iomap *iomap, - loff_t pos, void *entry) -{ - const sector_t sector = dax_iomap_sector(iomap, pos); - struct vm_area_struct *vma = vmf->vma; - struct address_space *mapping = vma->vm_file->f_mapping; - unsigned long vaddr = vmf->address; - void *ret; - int rc; - pfn_t pfn; - - rc = dax_iomap_pfn(iomap, pos, PAGE_SIZE, &pfn); - if (rc < 0) - return rc; - - ret = dax_insert_mapping_entry(mapping, vmf, entry, sector, 0); - if (IS_ERR(ret)) - return PTR_ERR(ret); - - trace_dax_insert_mapping(mapping->host, vmf, ret); - if (vmf->flags & FAULT_FLAG_WRITE) - return vm_insert_mixed_mkwrite(vma, vaddr, pfn); - else - return vm_insert_mixed(vma, vaddr, pfn); -} - /* * The user has performed a load from a hole in the file. Allocating a new * page in the file would cause excessive storage usage for workloads with @@ -1119,6 +1093,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, bool write = vmf->flags & FAULT_FLAG_WRITE; int vmf_ret = 0; void *entry; + pfn_t pfn; trace_dax_pte_fault(inode, vmf, vmf_ret); /* @@ -1201,7 +1176,24 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, count_memcg_event_mm(vma->vm_mm, PGMAJFAULT); major = VM_FAULT_MAJOR; } - error = dax_insert_mapping(vmf, &iomap, pos, entry); + error = dax_iomap_pfn(&iomap, pos, PAGE_SIZE, &pfn); + if (error < 0) + goto error_finish_iomap; + + entry = dax_insert_mapping_entry(mapping, vmf, entry, + dax_iomap_sector(&iomap, pos), + 0); + if (IS_ERR(entry)) { + error = PTR_ERR(entry); + goto error_finish_iomap; + } + + trace_dax_insert_mapping(inode, vmf, entry); + if (write) + error = vm_insert_mixed_mkwrite(vma, vaddr, pfn); + else + error = vm_insert_mixed(vma, vaddr, pfn); + /* -EBUSY is fine, somebody else faulted on the same PTE */ if (error == -EBUSY) error = 0; -- GitLab From 302a5e312b3a106fec49ba08da3f6545c9b7ee18 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:37 +0100 Subject: [PATCH 1571/2898] dax: Inline dax_pmd_insert_mapping() into the callsite dax_pmd_insert_mapping() has only one callsite and we will need to further fine tune what it does for synchronous faults. Just inline it into the callsite so that we don't have to pass awkward bools around. Reviewed-by: Christoph Hellwig Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 47 ++++++++++++++--------------------- include/trace/events/fs_dax.h | 1 - 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index 5b20c6456926..675fab8ec41f 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1235,33 +1235,11 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, } #ifdef CONFIG_FS_DAX_PMD -static int dax_pmd_insert_mapping(struct vm_fault *vmf, struct iomap *iomap, - loff_t pos, void *entry) -{ - struct address_space *mapping = vmf->vma->vm_file->f_mapping; - const sector_t sector = dax_iomap_sector(iomap, pos); - struct inode *inode = mapping->host; - void *ret = NULL; - pfn_t pfn = {}; - int rc; - - rc = dax_iomap_pfn(iomap, pos, PMD_SIZE, &pfn); - if (rc < 0) - goto fallback; - - ret = dax_insert_mapping_entry(mapping, vmf, entry, sector, - RADIX_DAX_PMD); - if (IS_ERR(ret)) - goto fallback; - - trace_dax_pmd_insert_mapping(inode, vmf, PMD_SIZE, pfn, ret); - return vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, - pfn, vmf->flags & FAULT_FLAG_WRITE); - -fallback: - trace_dax_pmd_insert_mapping_fallback(inode, vmf, PMD_SIZE, pfn, ret); - return VM_FAULT_FALLBACK; -} +/* + * The 'colour' (ie low bits) within a PMD of a page offset. This comes up + * more often than one might expect in the below functions. + */ +#define PG_PMD_COLOUR ((PMD_SIZE >> PAGE_SHIFT) - 1) static int dax_pmd_load_hole(struct vm_fault *vmf, struct iomap *iomap, void *entry) @@ -1317,6 +1295,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, void *entry; loff_t pos; int error; + pfn_t pfn; /* * Check whether offset isn't beyond end of file now. Caller is @@ -1394,7 +1373,19 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, switch (iomap.type) { case IOMAP_MAPPED: - result = dax_pmd_insert_mapping(vmf, &iomap, pos, entry); + error = dax_iomap_pfn(&iomap, pos, PMD_SIZE, &pfn); + if (error < 0) + goto finish_iomap; + + entry = dax_insert_mapping_entry(mapping, vmf, entry, + dax_iomap_sector(&iomap, pos), + RADIX_DAX_PMD); + if (IS_ERR(entry)) + goto finish_iomap; + + trace_dax_pmd_insert_mapping(inode, vmf, PMD_SIZE, pfn, entry); + result = vmf_insert_pfn_pmd(vma, vmf->address, vmf->pmd, pfn, + write); break; case IOMAP_UNWRITTEN: case IOMAP_HOLE: diff --git a/include/trace/events/fs_dax.h b/include/trace/events/fs_dax.h index fbc4a06f7310..88a9d19b8ff8 100644 --- a/include/trace/events/fs_dax.h +++ b/include/trace/events/fs_dax.h @@ -148,7 +148,6 @@ DEFINE_EVENT(dax_pmd_insert_mapping_class, name, \ TP_ARGS(inode, vmf, length, pfn, radix_entry)) DEFINE_PMD_INSERT_MAPPING_EVENT(dax_pmd_insert_mapping); -DEFINE_PMD_INSERT_MAPPING_EVENT(dax_pmd_insert_mapping_fallback); DECLARE_EVENT_CLASS(dax_pte_fault_class, TP_PROTO(struct inode *inode, struct vm_fault *vmf, int result), -- GitLab From cec04e8c825eaa5a4bb1a3ce0d3784628e965196 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:38 +0100 Subject: [PATCH 1572/2898] dax: Fix comment describing dax_iomap_fault() Add missing argument description. Reviewed-by: Christoph Hellwig Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/dax.c b/fs/dax.c index 675fab8ec41f..5214ed9ba508 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1435,7 +1435,8 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, /** * dax_iomap_fault - handle a page fault on a DAX file * @vmf: The description of the fault - * @ops: iomap ops passed from the file system + * @pe_size: Size of the page to fault in + * @ops: Iomap ops passed from the file system * * When a page fault occurs, filesystems may call this helper in * their fault handler for DAX files. dax_iomap_fault() assumes the caller -- GitLab From 9a0dd42251439de635088b97533109a935864a84 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:39 +0100 Subject: [PATCH 1573/2898] dax: Allow dax_iomap_fault() to return pfn For synchronous page fault dax_iomap_fault() will need to return PFN which will then need to be inserted into page tables after fsync() completes. Add necessary parameter to dax_iomap_fault(). Reviewed-by: Christoph Hellwig Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 13 +++++++------ fs/ext2/file.c | 2 +- fs/ext4/file.c | 2 +- fs/xfs/xfs_file.c | 4 ++-- include/linux/dax.h | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index 5214ed9ba508..5ddf15161390 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1079,7 +1079,7 @@ static int dax_fault_return(int error) return VM_FAULT_SIGBUS; } -static int dax_iomap_pte_fault(struct vm_fault *vmf, +static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, const struct iomap_ops *ops) { struct vm_area_struct *vma = vmf->vma; @@ -1280,7 +1280,7 @@ static int dax_pmd_load_hole(struct vm_fault *vmf, struct iomap *iomap, return VM_FAULT_FALLBACK; } -static int dax_iomap_pmd_fault(struct vm_fault *vmf, +static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, const struct iomap_ops *ops) { struct vm_area_struct *vma = vmf->vma; @@ -1425,7 +1425,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, return result; } #else -static int dax_iomap_pmd_fault(struct vm_fault *vmf, +static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, const struct iomap_ops *ops) { return VM_FAULT_FALLBACK; @@ -1436,6 +1436,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, * dax_iomap_fault - handle a page fault on a DAX file * @vmf: The description of the fault * @pe_size: Size of the page to fault in + * @pfnp: PFN to insert for synchronous faults if fsync is required * @ops: Iomap ops passed from the file system * * When a page fault occurs, filesystems may call this helper in @@ -1444,13 +1445,13 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, * successfully. */ int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size, - const struct iomap_ops *ops) + pfn_t *pfnp, const struct iomap_ops *ops) { switch (pe_size) { case PE_SIZE_PTE: - return dax_iomap_pte_fault(vmf, ops); + return dax_iomap_pte_fault(vmf, pfnp, ops); case PE_SIZE_PMD: - return dax_iomap_pmd_fault(vmf, ops); + return dax_iomap_pmd_fault(vmf, pfnp, ops); default: return VM_FAULT_FALLBACK; } diff --git a/fs/ext2/file.c b/fs/ext2/file.c index ff3a3636a5ca..d2bb7c96307d 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -99,7 +99,7 @@ static int ext2_dax_fault(struct vm_fault *vmf) } down_read(&ei->dax_sem); - ret = dax_iomap_fault(vmf, PE_SIZE_PTE, &ext2_iomap_ops); + ret = dax_iomap_fault(vmf, PE_SIZE_PTE, NULL, &ext2_iomap_ops); up_read(&ei->dax_sem); if (vmf->flags & FAULT_FLAG_WRITE) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index b1da660ac3bc..3cec0b95672f 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -306,7 +306,7 @@ static int ext4_dax_huge_fault(struct vm_fault *vmf, down_read(&EXT4_I(inode)->i_mmap_sem); } if (!IS_ERR(handle)) - result = dax_iomap_fault(vmf, pe_size, &ext4_iomap_ops); + result = dax_iomap_fault(vmf, pe_size, NULL, &ext4_iomap_ops); else result = VM_FAULT_SIGBUS; if (write) { diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 309e26c9dddb..7c6b8def6eed 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1040,7 +1040,7 @@ __xfs_filemap_fault( xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); if (IS_DAX(inode)) { - ret = dax_iomap_fault(vmf, pe_size, &xfs_iomap_ops); + ret = dax_iomap_fault(vmf, pe_size, NULL, &xfs_iomap_ops); } else { if (write_fault) ret = iomap_page_mkwrite(vmf, &xfs_iomap_ops); @@ -1111,7 +1111,7 @@ xfs_filemap_pfn_mkwrite( if (vmf->pgoff >= size) ret = VM_FAULT_SIGBUS; else if (IS_DAX(inode)) - ret = dax_iomap_fault(vmf, PE_SIZE_PTE, &xfs_iomap_ops); + ret = dax_iomap_fault(vmf, PE_SIZE_PTE, NULL, &xfs_iomap_ops); xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); sb_end_pagefault(inode->i_sb); return ret; diff --git a/include/linux/dax.h b/include/linux/dax.h index 122197124b9d..e7fa4b8f45bc 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h @@ -95,7 +95,7 @@ bool dax_write_cache_enabled(struct dax_device *dax_dev); ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, const struct iomap_ops *ops); int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size, - const struct iomap_ops *ops); + pfn_t *pfnp, const struct iomap_ops *ops); int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index); int dax_invalidate_mapping_entry_sync(struct address_space *mapping, pgoff_t index); -- GitLab From f5b7b74876cff5664ea8b2ef7f002c54cd6e7c90 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:40 +0100 Subject: [PATCH 1574/2898] dax: Allow tuning whether dax_insert_mapping_entry() dirties entry Currently we dirty radix tree entry whenever dax_insert_mapping_entry() gets called for a write fault. With synchronous page faults we would like to insert clean radix tree entry and dirty it only once we call fdatasync() and update page tables to save some unnecessary cache flushing. Add 'dirty' argument to dax_insert_mapping_entry() for that. Reviewed-by: Ross Zwisler Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index 5ddf15161390..efc210ff6665 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -526,13 +526,13 @@ static int copy_user_dax(struct block_device *bdev, struct dax_device *dax_dev, static void *dax_insert_mapping_entry(struct address_space *mapping, struct vm_fault *vmf, void *entry, sector_t sector, - unsigned long flags) + unsigned long flags, bool dirty) { struct radix_tree_root *page_tree = &mapping->page_tree; void *new_entry; pgoff_t index = vmf->pgoff; - if (vmf->flags & FAULT_FLAG_WRITE) + if (dirty) __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); if (dax_is_zero_entry(entry) && !(flags & RADIX_DAX_ZERO_PAGE)) { @@ -569,7 +569,7 @@ static void *dax_insert_mapping_entry(struct address_space *mapping, entry = new_entry; } - if (vmf->flags & FAULT_FLAG_WRITE) + if (dirty) radix_tree_tag_set(page_tree, index, PAGECACHE_TAG_DIRTY); spin_unlock_irq(&mapping->tree_lock); @@ -881,7 +881,7 @@ static int dax_load_hole(struct address_space *mapping, void *entry, } entry2 = dax_insert_mapping_entry(mapping, vmf, entry, 0, - RADIX_DAX_ZERO_PAGE); + RADIX_DAX_ZERO_PAGE, false); if (IS_ERR(entry2)) { ret = VM_FAULT_SIGBUS; goto out; @@ -1182,7 +1182,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, entry = dax_insert_mapping_entry(mapping, vmf, entry, dax_iomap_sector(&iomap, pos), - 0); + 0, write); if (IS_ERR(entry)) { error = PTR_ERR(entry); goto error_finish_iomap; @@ -1258,7 +1258,7 @@ static int dax_pmd_load_hole(struct vm_fault *vmf, struct iomap *iomap, goto fallback; ret = dax_insert_mapping_entry(mapping, vmf, entry, 0, - RADIX_DAX_PMD | RADIX_DAX_ZERO_PAGE); + RADIX_DAX_PMD | RADIX_DAX_ZERO_PAGE, false); if (IS_ERR(ret)) goto fallback; @@ -1379,7 +1379,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, entry = dax_insert_mapping_entry(mapping, vmf, entry, dax_iomap_sector(&iomap, pos), - RADIX_DAX_PMD); + RADIX_DAX_PMD, write); if (IS_ERR(entry)) goto finish_iomap; -- GitLab From b6fb293f2497a9841d94f6b57bd2bb2cd222da43 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:41 +0100 Subject: [PATCH 1575/2898] mm: Define MAP_SYNC and VM_SYNC flags Define new MAP_SYNC flag and corresponding VMA VM_SYNC flag. As the MAP_SYNC flag is not part of LEGACY_MAP_MASK, currently it will be refused by all MAP_SHARED_VALIDATE map attempts and silently ignored for everything else. Reviewed-by: Ross Zwisler Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/proc/task_mmu.c | 1 + include/linux/mm.h | 1 + include/linux/mman.h | 8 ++++++-- include/uapi/asm-generic/mman.h | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 5589b4bd4b85..ea78b37deeaa 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -664,6 +664,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) [ilog2(VM_ACCOUNT)] = "ac", [ilog2(VM_NORESERVE)] = "nr", [ilog2(VM_HUGETLB)] = "ht", + [ilog2(VM_SYNC)] = "sf", [ilog2(VM_ARCH_1)] = "ar", [ilog2(VM_WIPEONFORK)] = "wf", [ilog2(VM_DONTDUMP)] = "dd", diff --git a/include/linux/mm.h b/include/linux/mm.h index ca72b67153d5..5411cb7442de 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -189,6 +189,7 @@ extern unsigned int kobjsize(const void *objp); #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ #define VM_NORESERVE 0x00200000 /* should the VM suppress accounting */ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ +#define VM_SYNC 0x00800000 /* Synchronous page faults */ #define VM_ARCH_1 0x01000000 /* Architecture-specific flag */ #define VM_WIPEONFORK 0x02000000 /* Wipe VMA contents in child. */ #define VM_DONTDUMP 0x04000000 /* Do not include in the core dump */ diff --git a/include/linux/mman.h b/include/linux/mman.h index 74452e3f2536..3427bf3daef5 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -9,7 +9,7 @@ /* * Arrange for legacy / undefined architecture specific flags to be - * ignored by default in LEGACY_MAP_MASK. + * ignored by mmap handling code. */ #ifndef MAP_32BIT #define MAP_32BIT 0 @@ -23,6 +23,9 @@ #ifndef MAP_UNINITIALIZED #define MAP_UNINITIALIZED 0 #endif +#ifndef MAP_SYNC +#define MAP_SYNC 0 +#endif /* * The historical set of flags that all mmap implementations implicitly @@ -126,7 +129,8 @@ calc_vm_flag_bits(unsigned long flags) { return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) | _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) | - _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ); + _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) | + _calc_vm_trans(flags, MAP_SYNC, VM_SYNC ); } unsigned long vm_commit_limit(void); diff --git a/include/uapi/asm-generic/mman.h b/include/uapi/asm-generic/mman.h index 7162cd4cca73..00e55627d2df 100644 --- a/include/uapi/asm-generic/mman.h +++ b/include/uapi/asm-generic/mman.h @@ -12,6 +12,7 @@ #define MAP_NONBLOCK 0x10000 /* do not block on IO */ #define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */ #define MAP_HUGETLB 0x40000 /* create a huge page mapping */ +#define MAP_SYNC 0x80000 /* perform synchronous page faults for the mapping */ /* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */ -- GitLab From caa51d26f85c248f1c4f43a870ad3ef84bf9eb8f Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:42 +0100 Subject: [PATCH 1576/2898] dax, iomap: Add support for synchronous faults Add a flag to iomap interface informing the caller that inode needs fdstasync(2) for returned extent to become persistent and use it in DAX fault code so that we don't map such extents into page tables immediately. Instead we propagate the information that fdatasync(2) is necessary from dax_iomap_fault() with a new VM_FAULT_NEEDDSYNC flag. Filesystem fault handler is then responsible for calling fdatasync(2) and inserting pfn into page tables. Reviewed-by: Ross Zwisler Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 39 +++++++++++++++++++++++++++++++++++++-- include/linux/iomap.h | 5 +++++ include/linux/mm.h | 6 +++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index efc210ff6665..bb9ff907738c 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1091,6 +1091,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, unsigned flags = IOMAP_FAULT; int error, major = 0; bool write = vmf->flags & FAULT_FLAG_WRITE; + bool sync; int vmf_ret = 0; void *entry; pfn_t pfn; @@ -1169,6 +1170,8 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, goto finish_iomap; } + sync = (vma->vm_flags & VM_SYNC) && (iomap.flags & IOMAP_F_DIRTY); + switch (iomap.type) { case IOMAP_MAPPED: if (iomap.flags & IOMAP_F_NEW) { @@ -1182,12 +1185,27 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, entry = dax_insert_mapping_entry(mapping, vmf, entry, dax_iomap_sector(&iomap, pos), - 0, write); + 0, write && !sync); if (IS_ERR(entry)) { error = PTR_ERR(entry); goto error_finish_iomap; } + /* + * If we are doing synchronous page fault and inode needs fsync, + * we can insert PTE into page tables only after that happens. + * Skip insertion for now and return the pfn so that caller can + * insert it after fsync is done. + */ + if (sync) { + if (WARN_ON_ONCE(!pfnp)) { + error = -EIO; + goto error_finish_iomap; + } + *pfnp = pfn; + vmf_ret = VM_FAULT_NEEDDSYNC | major; + goto finish_iomap; + } trace_dax_insert_mapping(inode, vmf, entry); if (write) error = vm_insert_mixed_mkwrite(vma, vaddr, pfn); @@ -1287,6 +1305,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, struct address_space *mapping = vma->vm_file->f_mapping; unsigned long pmd_addr = vmf->address & PMD_MASK; bool write = vmf->flags & FAULT_FLAG_WRITE; + bool sync; unsigned int iomap_flags = (write ? IOMAP_WRITE : 0) | IOMAP_FAULT; struct inode *inode = mapping->host; int result = VM_FAULT_FALLBACK; @@ -1371,6 +1390,8 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, if (iomap.offset + iomap.length < pos + PMD_SIZE) goto finish_iomap; + sync = (vma->vm_flags & VM_SYNC) && (iomap.flags & IOMAP_F_DIRTY); + switch (iomap.type) { case IOMAP_MAPPED: error = dax_iomap_pfn(&iomap, pos, PMD_SIZE, &pfn); @@ -1379,10 +1400,24 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf, pfn_t *pfnp, entry = dax_insert_mapping_entry(mapping, vmf, entry, dax_iomap_sector(&iomap, pos), - RADIX_DAX_PMD, write); + RADIX_DAX_PMD, write && !sync); if (IS_ERR(entry)) goto finish_iomap; + /* + * If we are doing synchronous page fault and inode needs fsync, + * we can insert PMD into page tables only after that happens. + * Skip insertion for now and return the pfn so that caller can + * insert it after fsync is done. + */ + if (sync) { + if (WARN_ON_ONCE(!pfnp)) + goto finish_iomap; + *pfnp = pfn; + result = VM_FAULT_NEEDDSYNC; + goto finish_iomap; + } + trace_dax_pmd_insert_mapping(inode, vmf, PMD_SIZE, pfn, entry); result = vmf_insert_pfn_pmd(vma, vmf->address, vmf->pmd, pfn, write); diff --git a/include/linux/iomap.h b/include/linux/iomap.h index f64dc6ce5161..73e3b7085dbe 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -22,6 +22,11 @@ struct vm_fault; * Flags for all iomap mappings: */ #define IOMAP_F_NEW 0x01 /* blocks have been newly allocated */ +/* + * IOMAP_F_DIRTY indicates the inode has uncommitted metadata needed to access + * written data and requires fdatasync to commit them to persistent storage. + */ +#define IOMAP_F_DIRTY 0x02 /* * Flags that only need to be reported for IOMAP_REPORT requests: diff --git a/include/linux/mm.h b/include/linux/mm.h index 5411cb7442de..f57e55782d7d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1182,6 +1182,9 @@ static inline void clear_page_pfmemalloc(struct page *page) #define VM_FAULT_RETRY 0x0400 /* ->fault blocked, must retry */ #define VM_FAULT_FALLBACK 0x0800 /* huge page fault failed, fall back to small */ #define VM_FAULT_DONE_COW 0x1000 /* ->fault has fully handled COW */ +#define VM_FAULT_NEEDDSYNC 0x2000 /* ->fault did not modify page tables + * and needs fsync() to complete (for + * synchronous page faults in DAX) */ #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \ VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \ @@ -1199,7 +1202,8 @@ static inline void clear_page_pfmemalloc(struct page *page) { VM_FAULT_LOCKED, "LOCKED" }, \ { VM_FAULT_RETRY, "RETRY" }, \ { VM_FAULT_FALLBACK, "FALLBACK" }, \ - { VM_FAULT_DONE_COW, "DONE_COW" } + { VM_FAULT_DONE_COW, "DONE_COW" }, \ + { VM_FAULT_NEEDDSYNC, "NEEDDSYNC" } /* Encode hstate index for a hwpoisoned large page */ #define VM_FAULT_SET_HINDEX(x) ((x) << 12) -- GitLab From 71eab6dfd91eabf06fe782a590c07e8a0795f5ea Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:43 +0100 Subject: [PATCH 1577/2898] dax: Implement dax_finish_sync_fault() Implement a function that filesystems can call to finish handling of synchronous page faults. It takes care of syncing appropriare file range and insertion of page table entry. Reviewed-by: Ross Zwisler Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/dax.c | 83 +++++++++++++++++++++++++++++++++++ include/linux/dax.h | 2 + include/trace/events/fs_dax.h | 2 + 3 files changed, 87 insertions(+) diff --git a/fs/dax.c b/fs/dax.c index bb9ff907738c..78233c716757 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1492,3 +1492,86 @@ int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size, } } EXPORT_SYMBOL_GPL(dax_iomap_fault); + +/** + * dax_insert_pfn_mkwrite - insert PTE or PMD entry into page tables + * @vmf: The description of the fault + * @pe_size: Size of entry to be inserted + * @pfn: PFN to insert + * + * This function inserts writeable PTE or PMD entry into page tables for mmaped + * DAX file. It takes care of marking corresponding radix tree entry as dirty + * as well. + */ +static int dax_insert_pfn_mkwrite(struct vm_fault *vmf, + enum page_entry_size pe_size, + pfn_t pfn) +{ + struct address_space *mapping = vmf->vma->vm_file->f_mapping; + void *entry, **slot; + pgoff_t index = vmf->pgoff; + int vmf_ret, error; + + spin_lock_irq(&mapping->tree_lock); + entry = get_unlocked_mapping_entry(mapping, index, &slot); + /* Did we race with someone splitting entry or so? */ + if (!entry || + (pe_size == PE_SIZE_PTE && !dax_is_pte_entry(entry)) || + (pe_size == PE_SIZE_PMD && !dax_is_pmd_entry(entry))) { + put_unlocked_mapping_entry(mapping, index, entry); + spin_unlock_irq(&mapping->tree_lock); + trace_dax_insert_pfn_mkwrite_no_entry(mapping->host, vmf, + VM_FAULT_NOPAGE); + return VM_FAULT_NOPAGE; + } + radix_tree_tag_set(&mapping->page_tree, index, PAGECACHE_TAG_DIRTY); + entry = lock_slot(mapping, slot); + spin_unlock_irq(&mapping->tree_lock); + switch (pe_size) { + case PE_SIZE_PTE: + error = vm_insert_mixed_mkwrite(vmf->vma, vmf->address, pfn); + vmf_ret = dax_fault_return(error); + break; +#ifdef CONFIG_FS_DAX_PMD + case PE_SIZE_PMD: + vmf_ret = vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, + pfn, true); + break; +#endif + default: + vmf_ret = VM_FAULT_FALLBACK; + } + put_locked_mapping_entry(mapping, index); + trace_dax_insert_pfn_mkwrite(mapping->host, vmf, vmf_ret); + return vmf_ret; +} + +/** + * dax_finish_sync_fault - finish synchronous page fault + * @vmf: The description of the fault + * @pe_size: Size of entry to be inserted + * @pfn: PFN to insert + * + * This function ensures that the file range touched by the page fault is + * stored persistently on the media and handles inserting of appropriate page + * table entry. + */ +int dax_finish_sync_fault(struct vm_fault *vmf, enum page_entry_size pe_size, + pfn_t pfn) +{ + int err; + loff_t start = ((loff_t)vmf->pgoff) << PAGE_SHIFT; + size_t len = 0; + + if (pe_size == PE_SIZE_PTE) + len = PAGE_SIZE; + else if (pe_size == PE_SIZE_PMD) + len = PMD_SIZE; + else + WARN_ON_ONCE(1); + err = vfs_fsync_range(vmf->vma->vm_file, start, start + len - 1, 1); + if (err) + return VM_FAULT_SIGBUS; + return dax_insert_pfn_mkwrite(vmf, pe_size, pfn); +} +EXPORT_SYMBOL_GPL(dax_finish_sync_fault); diff --git a/include/linux/dax.h b/include/linux/dax.h index e7fa4b8f45bc..d403f78b706c 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h @@ -96,6 +96,8 @@ ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, const struct iomap_ops *ops); int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size, pfn_t *pfnp, const struct iomap_ops *ops); +int dax_finish_sync_fault(struct vm_fault *vmf, enum page_entry_size pe_size, + pfn_t pfn); int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index); int dax_invalidate_mapping_entry_sync(struct address_space *mapping, pgoff_t index); diff --git a/include/trace/events/fs_dax.h b/include/trace/events/fs_dax.h index 88a9d19b8ff8..7725459fafef 100644 --- a/include/trace/events/fs_dax.h +++ b/include/trace/events/fs_dax.h @@ -190,6 +190,8 @@ DEFINE_EVENT(dax_pte_fault_class, name, \ DEFINE_PTE_FAULT_EVENT(dax_pte_fault); DEFINE_PTE_FAULT_EVENT(dax_pte_fault_done); DEFINE_PTE_FAULT_EVENT(dax_load_hole); +DEFINE_PTE_FAULT_EVENT(dax_insert_pfn_mkwrite_no_entry); +DEFINE_PTE_FAULT_EVENT(dax_insert_pfn_mkwrite); TRACE_EVENT(dax_insert_mapping, TP_PROTO(struct inode *inode, struct vm_fault *vmf, void *radix_entry), -- GitLab From 497f6926d880c57f65bf7c3f1086526fa774c55e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:44 +0100 Subject: [PATCH 1578/2898] ext4: Simplify error handling in ext4_dax_huge_fault() If transaction starting fails, just bail out of the function immediately instead of checking for that condition throughout the function. Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/ext4/file.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 3cec0b95672f..208adfc3e673 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -302,16 +302,17 @@ static int ext4_dax_huge_fault(struct vm_fault *vmf, down_read(&EXT4_I(inode)->i_mmap_sem); handle = ext4_journal_start_sb(sb, EXT4_HT_WRITE_PAGE, EXT4_DATA_TRANS_BLOCKS(sb)); + if (IS_ERR(handle)) { + up_read(&EXT4_I(inode)->i_mmap_sem); + sb_end_pagefault(sb); + return VM_FAULT_SIGBUS; + } } else { down_read(&EXT4_I(inode)->i_mmap_sem); } - if (!IS_ERR(handle)) - result = dax_iomap_fault(vmf, pe_size, NULL, &ext4_iomap_ops); - else - result = VM_FAULT_SIGBUS; + result = dax_iomap_fault(vmf, pe_size, NULL, &ext4_iomap_ops); if (write) { - if (!IS_ERR(handle)) - ext4_journal_stop(handle); + ext4_journal_stop(handle); up_read(&EXT4_I(inode)->i_mmap_sem); sb_end_pagefault(sb); } else { -- GitLab From b8a6176c214cf9aa2679131ed7e4515cddaadc33 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:45 +0100 Subject: [PATCH 1579/2898] ext4: Support for synchronous DAX faults We return IOMAP_F_DIRTY flag from ext4_iomap_begin() when asked to prepare blocks for writing and the inode has some uncommitted metadata changes. In the fault handler ext4_dax_fault() we then detect this case (through VM_FAULT_NEEDDSYNC return value) and call helper dax_finish_sync_fault() to flush metadata changes and insert page table entry. Note that this will also dirty corresponding radix tree entry which is what we want - fsync(2) will still provide data integrity guarantees for applications not using userspace flushing. And applications using userspace flushing can avoid calling fsync(2) and thus avoid the performance overhead. Reviewed-by: Ross Zwisler Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/ext4/file.c | 15 ++++++++++++++- fs/ext4/inode.c | 15 +++++++++++++++ fs/jbd2/journal.c | 17 +++++++++++++++++ include/linux/jbd2.h | 1 + 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 208adfc3e673..08a1d1a33a90 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "ext4.h" #include "ext4_jbd2.h" #include "xattr.h" @@ -295,6 +296,7 @@ static int ext4_dax_huge_fault(struct vm_fault *vmf, */ bool write = (vmf->flags & FAULT_FLAG_WRITE) && (vmf->vma->vm_flags & VM_SHARED); + pfn_t pfn; if (write) { sb_start_pagefault(sb); @@ -310,9 +312,12 @@ static int ext4_dax_huge_fault(struct vm_fault *vmf, } else { down_read(&EXT4_I(inode)->i_mmap_sem); } - result = dax_iomap_fault(vmf, pe_size, NULL, &ext4_iomap_ops); + result = dax_iomap_fault(vmf, pe_size, &pfn, &ext4_iomap_ops); if (write) { ext4_journal_stop(handle); + /* Handling synchronous page fault? */ + if (result & VM_FAULT_NEEDDSYNC) + result = dax_finish_sync_fault(vmf, pe_size, pfn); up_read(&EXT4_I(inode)->i_mmap_sem); sb_end_pagefault(sb); } else { @@ -350,6 +355,13 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) return -EIO; + /* + * We don't support synchronous mappings for non-DAX files. At least + * until someone comes with a sensible use case. + */ + if (!IS_DAX(file_inode(file)) && (vma->vm_flags & VM_SYNC)) + return -EOPNOTSUPP; + file_accessed(file); if (IS_DAX(file_inode(file))) { vma->vm_ops = &ext4_dax_vm_ops; @@ -719,6 +731,7 @@ const struct file_operations ext4_file_operations = { .compat_ioctl = ext4_compat_ioctl, #endif .mmap = ext4_file_mmap, + .mmap_supported_flags = MAP_SYNC, .open = ext4_file_open, .release = ext4_release_file, .fsync = ext4_sync_file, diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 31db875bc7a1..13a198924a0f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3394,6 +3394,19 @@ static int ext4_releasepage(struct page *page, gfp_t wait) } #ifdef CONFIG_FS_DAX +static bool ext4_inode_datasync_dirty(struct inode *inode) +{ + journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; + + if (journal) + return !jbd2_transaction_committed(journal, + EXT4_I(inode)->i_datasync_tid); + /* Any metadata buffers to write? */ + if (!list_empty(&inode->i_mapping->private_list)) + return true; + return inode->i_state & I_DIRTY_DATASYNC; +} + static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length, unsigned flags, struct iomap *iomap) { @@ -3466,6 +3479,8 @@ static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length, } iomap->flags = 0; + if ((flags & IOMAP_WRITE) && ext4_inode_datasync_dirty(inode)) + iomap->flags |= IOMAP_F_DIRTY; iomap->bdev = inode->i_sb->s_bdev; iomap->dax_dev = sbi->s_daxdev; iomap->offset = first_block << blkbits; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 7d5ef3bf3f3e..fa8cde498b4b 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -738,6 +738,23 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid) return err; } +/* Return 1 when transaction with given tid has already committed. */ +int jbd2_transaction_committed(journal_t *journal, tid_t tid) +{ + int ret = 1; + + read_lock(&journal->j_state_lock); + if (journal->j_running_transaction && + journal->j_running_transaction->t_tid == tid) + ret = 0; + if (journal->j_committing_transaction && + journal->j_committing_transaction->t_tid == tid) + ret = 0; + read_unlock(&journal->j_state_lock); + return ret; +} +EXPORT_SYMBOL(jbd2_transaction_committed); + /* * When this function returns the transaction corresponding to tid * will be completed. If the transaction has currently running, start diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 606b6bce3a5b..296d1e0ea87b 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1367,6 +1367,7 @@ int jbd2_log_start_commit(journal_t *journal, tid_t tid); int __jbd2_log_start_commit(journal_t *journal, tid_t tid); int jbd2_journal_start_commit(journal_t *journal, tid_t *tid); int jbd2_log_wait_commit(journal_t *journal, tid_t tid); +int jbd2_transaction_committed(journal_t *journal, tid_t tid); int jbd2_complete_transaction(journal_t *journal, tid_t tid); int jbd2_log_do_checkpoint(journal_t *journal); int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid); -- GitLab From 7b565c9f965bac269cc6a1f25c819f77044abf9d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 1 Nov 2017 16:36:46 +0100 Subject: [PATCH 1580/2898] xfs: Implement xfs_filemap_pfn_mkwrite() using __xfs_filemap_fault() xfs_filemap_pfn_mkwrite() duplicates a lot of __xfs_filemap_fault(). It will also need to handle flushing for synchronous page faults. So just make that function use __xfs_filemap_fault(). Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/xfs/xfs_file.c | 29 ++++------------------------- fs/xfs/xfs_trace.h | 2 -- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 7c6b8def6eed..4496b45678de 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1085,37 +1085,16 @@ xfs_filemap_page_mkwrite( } /* - * pfn_mkwrite was originally inteneded to ensure we capture time stamp - * updates on write faults. In reality, it's need to serialise against - * truncate similar to page_mkwrite. Hence we cycle the XFS_MMAPLOCK_SHARED - * to ensure we serialise the fault barrier in place. + * pfn_mkwrite was originally intended to ensure we capture time stamp updates + * on write faults. In reality, it needs to serialise against truncate and + * prepare memory for writing so handle is as standard write fault. */ static int xfs_filemap_pfn_mkwrite( struct vm_fault *vmf) { - struct inode *inode = file_inode(vmf->vma->vm_file); - struct xfs_inode *ip = XFS_I(inode); - int ret = VM_FAULT_NOPAGE; - loff_t size; - - trace_xfs_filemap_pfn_mkwrite(ip); - - sb_start_pagefault(inode->i_sb); - file_update_time(vmf->vma->vm_file); - - /* check if the faulting page hasn't raced with truncate */ - xfs_ilock(ip, XFS_MMAPLOCK_SHARED); - size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT; - if (vmf->pgoff >= size) - ret = VM_FAULT_SIGBUS; - else if (IS_DAX(inode)) - ret = dax_iomap_fault(vmf, PE_SIZE_PTE, NULL, &xfs_iomap_ops); - xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); - sb_end_pagefault(inode->i_sb); - return ret; - + return __xfs_filemap_fault(vmf, PE_SIZE_PTE, true); } static const struct vm_operations_struct xfs_file_vm_ops = { diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index bb5514688d47..6333ad09e0f3 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -688,8 +688,6 @@ DEFINE_INODE_EVENT(xfs_inode_set_cowblocks_tag); DEFINE_INODE_EVENT(xfs_inode_clear_cowblocks_tag); DEFINE_INODE_EVENT(xfs_inode_free_cowblocks_invalid); -DEFINE_INODE_EVENT(xfs_filemap_pfn_mkwrite); - TRACE_EVENT(xfs_filemap_fault, TP_PROTO(struct xfs_inode *ip, enum page_entry_size pe_size, bool write_fault), -- GitLab From a39e596baa07cb1dc19c2ead14c9fd2a30f22352 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 1 Nov 2017 16:36:47 +0100 Subject: [PATCH 1581/2898] xfs: support for synchronous DAX faults Return IOMAP_F_DIRTY from xfs_file_iomap_begin() when asked to prepare blocks for writing and the inode is pinned, and has dirty fields other than the timestamps. In __xfs_filemap_fault() we then detect this case and call dax_finish_sync_fault() to make sure all metadata is committed, and to insert the page table entry. Note that this will also dirty corresponding radix tree entry which is what we want - fsync(2) will still provide data integrity guarantees for applications not using userspace flushing. And applications using userspace flushing can avoid calling fsync(2) and thus avoid the performance overhead. [JK: Added VM_SYNC flag handling] Reviewed-by: Ross Zwisler Signed-off-by: Christoph Hellwig Signed-off-by: Jan Kara Signed-off-by: Dan Williams --- fs/xfs/xfs_file.c | 15 ++++++++++++++- fs/xfs/xfs_iomap.c | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 4496b45678de..4827e82d5d2c 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -44,6 +44,7 @@ #include #include #include +#include static const struct vm_operations_struct xfs_file_vm_ops; @@ -1040,7 +1041,11 @@ __xfs_filemap_fault( xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); if (IS_DAX(inode)) { - ret = dax_iomap_fault(vmf, pe_size, NULL, &xfs_iomap_ops); + pfn_t pfn; + + ret = dax_iomap_fault(vmf, pe_size, &pfn, &xfs_iomap_ops); + if (ret & VM_FAULT_NEEDDSYNC) + ret = dax_finish_sync_fault(vmf, pe_size, pfn); } else { if (write_fault) ret = iomap_page_mkwrite(vmf, &xfs_iomap_ops); @@ -1110,6 +1115,13 @@ xfs_file_mmap( struct file *filp, struct vm_area_struct *vma) { + /* + * We don't support synchronous mappings for non-DAX files. At least + * until someone comes with a sensible use case. + */ + if (!IS_DAX(file_inode(filp)) && (vma->vm_flags & VM_SYNC)) + return -EOPNOTSUPP; + file_accessed(filp); vma->vm_ops = &xfs_file_vm_ops; if (IS_DAX(file_inode(filp))) @@ -1128,6 +1140,7 @@ const struct file_operations xfs_file_operations = { .compat_ioctl = xfs_file_compat_ioctl, #endif .mmap = xfs_file_mmap, + .mmap_supported_flags = MAP_SYNC, .open = xfs_file_open, .release = xfs_file_release, .fsync = xfs_file_fsync, diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index f179bdf1644d..b43be199fbdf 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -33,6 +33,7 @@ #include "xfs_error.h" #include "xfs_trans.h" #include "xfs_trans_space.h" +#include "xfs_inode_item.h" #include "xfs_iomap.h" #include "xfs_trace.h" #include "xfs_icache.h" @@ -1086,6 +1087,10 @@ xfs_file_iomap_begin( trace_xfs_iomap_found(ip, offset, length, 0, &imap); } + if ((flags & IOMAP_WRITE) && xfs_ipincount(ip) && + (ip->i_itemp->ili_fsync_fields & ~XFS_ILOG_TIMESTAMP)) + iomap->flags |= IOMAP_F_DIRTY; + xfs_bmbt_to_iomap(ip, iomap, &imap); if (shared) -- GitLab From f35a8efe2c34496eaf45f8a9bd5bb7625d34bb5c Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:22 -0500 Subject: [PATCH 1582/2898] platform/x86: dell-smbios: Prefix class/select with cmd_ Later on these structures will be brought up to userspace. the word "class" is a reserved word in c++ and this will prevent uapi headers from being included directly in c++ programs. To make life easier on these applications, prepare the change now. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-smbios.c | 4 ++-- drivers/platform/x86/dell-smbios.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index e9b1ca07c872..ffc174638aa4 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -86,8 +86,8 @@ void dell_smbios_send_request(int class, int select) command.ebx = virt_to_phys(buffer); command.ecx = 0x42534931; - buffer->class = class; - buffer->select = select; + buffer->cmd_class = class; + buffer->cmd_select = select; dcdbas_smi_request(&command); } diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h index 45cbc2292cd3..742dd8bd66b9 100644 --- a/drivers/platform/x86/dell-smbios.h +++ b/drivers/platform/x86/dell-smbios.h @@ -22,8 +22,8 @@ struct notifier_block; * system management mode, hence the volatiles */ struct calling_interface_buffer { - u16 class; - u16 select; + u16 cmd_class; + u16 cmd_select; volatile u32 input[4]; volatile u32 output[4]; } __packed; -- GitLab From 722c856d46c6ca74a246b54a72f14751fec01aae Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:23 -0500 Subject: [PATCH 1583/2898] platform/x86: wmi: Add new method wmidev_evaluate_method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers properly using the wmibus can pass their wmi_device pointer rather than the GUID back to the WMI bus to evaluate the proper methods. Any "new" drivers added that use the WMI bus should use this rather than the old wmi_evaluate_method that would take the GUID. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Reviewed-by: Pali Rohár Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 28 ++++++++++++++++++++++++---- include/linux/wmi.h | 6 ++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 7a05843aff19..4d73a87c2ddf 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -200,6 +200,28 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) */ acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) +{ + struct wmi_block *wblock = NULL; + + if (!find_guid(guid_string, &wblock)) + return AE_ERROR; + return wmidev_evaluate_method(&wblock->dev, instance, method_id, + in, out); +} +EXPORT_SYMBOL_GPL(wmi_evaluate_method); + +/** + * wmidev_evaluate_method - Evaluate a WMI method + * @wdev: A wmi bus device from a driver + * @instance: Instance index + * @method_id: Method ID to call + * &in: Buffer containing input for the method call + * &out: Empty buffer to return the method results + * + * Call an ACPI-WMI method + */ +acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, + u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) { struct guid_block *block = NULL; struct wmi_block *wblock = NULL; @@ -209,9 +231,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) union acpi_object params[3]; char method[5] = "WM"; - if (!find_guid(guid_string, &wblock)) - return AE_ERROR; - + wblock = container_of(wdev, struct wmi_block, dev); block = &wblock->gblock; handle = wblock->acpi_device->handle; @@ -246,7 +266,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) return status; } -EXPORT_SYMBOL_GPL(wmi_evaluate_method); +EXPORT_SYMBOL_GPL(wmidev_evaluate_method); static acpi_status __query_block(struct wmi_block *wblock, u8 instance, struct acpi_buffer *out) diff --git a/include/linux/wmi.h b/include/linux/wmi.h index cd0d7734dc49..2cd10c3b89e9 100644 --- a/include/linux/wmi.h +++ b/include/linux/wmi.h @@ -26,6 +26,12 @@ struct wmi_device { bool setable; }; +/* evaluate the ACPI method associated with this device */ +extern acpi_status wmidev_evaluate_method(struct wmi_device *wdev, + u8 instance, u32 method_id, + const struct acpi_buffer *in, + struct acpi_buffer *out); + /* Caller must kfree the result. */ extern union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance); -- GitLab From d0bf42d83e9492ffc80108b0913f596dbbd220c0 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:24 -0500 Subject: [PATCH 1584/2898] platform/x86: dell-wmi: increase severity of some failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a lot of error checking in place for the format of the WMI descriptor buffer, but some of the potentially raised issues should be considered critical failures. If the buffer size or header don't match, this is a good indication that the buffer format changed in a way that the rest of the data should not be relied upon. For the remaining data set vectors, continue to notate a warning in undefined results, but as those are fields that the descriptor intended to refer to other applications, don't fail if they're new values. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Reviewed-by: Pali Rohár Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-wmi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 1fbef560ca67..2cfaaa8faf0a 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -657,17 +657,18 @@ static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev) dev_err(&wdev->dev, "Dell descriptor buffer has invalid length (%d)\n", obj->buffer.length); - if (obj->buffer.length < 16) { - ret = -EINVAL; - goto out; - } + ret = -EINVAL; + goto out; } buffer = (u32 *)obj->buffer.pointer; - if (buffer[0] != 0x4C4C4544 && buffer[1] != 0x494D5720) - dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature (%*ph)\n", + if (buffer[0] != 0x4C4C4544 && buffer[1] != 0x494D5720) { + dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%*ph)\n", 8, buffer); + ret = -EINVAL; + goto out; + } if (buffer[2] != 0 && buffer[2] != 1) dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%d)\n", -- GitLab From 7e6dcbebcbc5d8cd7d9e564d9cfbf523c2fbcb68 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:25 -0500 Subject: [PATCH 1585/2898] platform/x86: dell-wmi: clean up wmi descriptor check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some cases the wrong type was used for errors and checks can be done more cleanly. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Suggested-by: Andy Shevchenko Reviewed-by: Pali Rohár Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-wmi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 2cfaaa8faf0a..b2bd396acac5 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -663,16 +663,16 @@ static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev) buffer = (u32 *)obj->buffer.pointer; - if (buffer[0] != 0x4C4C4544 && buffer[1] != 0x494D5720) { - dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%*ph)\n", - 8, buffer); + if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) { + dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n", + buffer); ret = -EINVAL; goto out; } if (buffer[2] != 0 && buffer[2] != 1) - dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%d)\n", - buffer[2]); + dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%lu)\n", + (unsigned long) buffer[2]); if (buffer[3] != 4096) dev_warn(&wdev->dev, "Dell descriptor buffer has invalid buffer length (%d)\n", -- GitLab From fa9f924c7ff95f9299e11657c4441288d7f01dbd Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:26 -0500 Subject: [PATCH 1586/2898] platform/x86: dell-wmi: don't check length returned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is intended to be variable and provided by the platform. Some platforms this year will be adopting a 32k WMI buffer, so don't complain when encountering those platforms or any other future changes. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Reviewed-by: Pali Rohár Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-wmi.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index b2bd396acac5..da4f629d0831 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -624,7 +624,7 @@ static void dell_wmi_input_destroy(struct wmi_device *wdev) * Vendor Signature 0 4 "DELL" * Object Signature 4 4 " WMI" * WMI Interface Version 8 4 - * WMI buffer length 12 4 4096 + * WMI buffer length 12 4 */ static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev) { @@ -674,10 +674,6 @@ static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev) dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%lu)\n", (unsigned long) buffer[2]); - if (buffer[3] != 4096) - dev_warn(&wdev->dev, "Dell descriptor buffer has invalid buffer length (%d)\n", - buffer[3]); - priv->interface_version = buffer[2]; ret = 0; -- GitLab From 92b8c540bce7b1662212dff35f503f5b1266725b Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:27 -0500 Subject: [PATCH 1587/2898] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver All communication on individual GUIDs should occur in separate drivers. Allowing a driver to communicate with the bus to another GUID is just a hack that discourages drivers to adopt the bus model. The information found from the WMI descriptor driver is now exported for use by other drivers. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- MAINTAINERS | 5 + drivers/platform/x86/Kconfig | 5 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/dell-wmi-descriptor.c | 170 +++++++++++++++++++++ drivers/platform/x86/dell-wmi-descriptor.h | 21 +++ drivers/platform/x86/dell-wmi.c | 80 +--------- 6 files changed, 208 insertions(+), 74 deletions(-) create mode 100644 drivers/platform/x86/dell-wmi-descriptor.c create mode 100644 drivers/platform/x86/dell-wmi-descriptor.h diff --git a/MAINTAINERS b/MAINTAINERS index b77e493cff9c..69a81400cc65 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4013,6 +4013,11 @@ M: Pali Rohár S: Maintained F: drivers/platform/x86/dell-wmi.c +DELL WMI DESCRIPTOR DRIVER +M: Mario Limonciello +S: Maintained +F: drivers/platform/x86/dell-wmi-descriptor.c + DELTA ST MEDIA DRIVER M: Hugues Fruchet L: linux-media@vger.kernel.org diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 87c8c36efce4..a0babdc5136f 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -121,6 +121,7 @@ config DELL_WMI depends on DMI depends on INPUT depends on ACPI_VIDEO || ACPI_VIDEO = n + select DELL_WMI_DESCRIPTOR select DELL_SMBIOS select INPUT_SPARSEKMAP ---help--- @@ -129,6 +130,10 @@ config DELL_WMI To compile this driver as a module, choose M here: the module will be called dell-wmi. +config DELL_WMI_DESCRIPTOR + tristate + depends on ACPI_WMI + config DELL_WMI_AIO tristate "WMI Hotkeys for Dell All-In-One series" depends on ACPI_WMI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 2b315d0df3b7..8636f5d3424f 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o +obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o diff --git a/drivers/platform/x86/dell-wmi-descriptor.c b/drivers/platform/x86/dell-wmi-descriptor.c new file mode 100644 index 000000000000..3204c408e261 --- /dev/null +++ b/drivers/platform/x86/dell-wmi-descriptor.c @@ -0,0 +1,170 @@ +/* + * Dell WMI descriptor driver + * + * Copyright (C) 2017 Dell Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include "dell-wmi-descriptor.h" + +struct descriptor_priv { + struct list_head list; + u32 interface_version; + u32 size; +}; +static LIST_HEAD(wmi_list); +static DEFINE_MUTEX(list_mutex); + +bool dell_wmi_get_interface_version(u32 *version) +{ + struct descriptor_priv *priv; + bool ret = false; + + mutex_lock(&list_mutex); + priv = list_first_entry_or_null(&wmi_list, + struct descriptor_priv, + list); + if (priv) { + *version = priv->interface_version; + ret = true; + } + mutex_unlock(&list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(dell_wmi_get_interface_version); + +bool dell_wmi_get_size(u32 *size) +{ + struct descriptor_priv *priv; + bool ret = false; + + mutex_lock(&list_mutex); + priv = list_first_entry_or_null(&wmi_list, + struct descriptor_priv, + list); + if (priv) { + *size = priv->size; + ret = true; + } + mutex_unlock(&list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(dell_wmi_get_size); + +/* + * Descriptor buffer is 128 byte long and contains: + * + * Name Offset Length Value + * Vendor Signature 0 4 "DELL" + * Object Signature 4 4 " WMI" + * WMI Interface Version 8 4 + * WMI buffer length 12 4 + */ +static int dell_wmi_descriptor_probe(struct wmi_device *wdev) +{ + union acpi_object *obj = NULL; + struct descriptor_priv *priv; + u32 *buffer; + int ret; + + obj = wmidev_block_query(wdev, 0); + if (!obj) { + dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n"); + ret = -EIO; + goto out; + } + + if (obj->type != ACPI_TYPE_BUFFER) { + dev_err(&wdev->dev, "Dell descriptor has wrong type\n"); + ret = -EINVAL; + goto out; + } + + /* Although it's not technically a failure, this would lead to + * unexpected behavior + */ + if (obj->buffer.length != 128) { + dev_err(&wdev->dev, + "Dell descriptor buffer has unexpected length (%d)\n", + obj->buffer.length); + ret = -EINVAL; + goto out; + } + + buffer = (u32 *)obj->buffer.pointer; + + if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) { + dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n", + buffer); + ret = -EINVAL; + goto out; + } + + if (buffer[2] != 0 && buffer[2] != 1) + dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%lu)\n", + (unsigned long) buffer[2]); + + priv = devm_kzalloc(&wdev->dev, sizeof(struct descriptor_priv), + GFP_KERNEL); + + priv->interface_version = buffer[2]; + priv->size = buffer[3]; + ret = 0; + dev_set_drvdata(&wdev->dev, priv); + mutex_lock(&list_mutex); + list_add_tail(&priv->list, &wmi_list); + mutex_unlock(&list_mutex); + + dev_dbg(&wdev->dev, "Detected Dell WMI interface version %lu and buffer size %lu\n", + (unsigned long) priv->interface_version, + (unsigned long) priv->size); + +out: + kfree(obj); + return ret; +} + +static int dell_wmi_descriptor_remove(struct wmi_device *wdev) +{ + struct descriptor_priv *priv = dev_get_drvdata(&wdev->dev); + + mutex_lock(&list_mutex); + list_del(&priv->list); + mutex_unlock(&list_mutex); + return 0; +} + +static const struct wmi_device_id dell_wmi_descriptor_id_table[] = { + { .guid_string = DELL_WMI_DESCRIPTOR_GUID }, + { }, +}; + +static struct wmi_driver dell_wmi_descriptor_driver = { + .driver = { + .name = "dell-wmi-descriptor", + }, + .probe = dell_wmi_descriptor_probe, + .remove = dell_wmi_descriptor_remove, + .id_table = dell_wmi_descriptor_id_table, +}; + +module_wmi_driver(dell_wmi_descriptor_driver); + +MODULE_ALIAS("wmi:" DELL_WMI_DESCRIPTOR_GUID); +MODULE_AUTHOR("Mario Limonciello "); +MODULE_DESCRIPTION("Dell WMI descriptor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/dell-wmi-descriptor.h b/drivers/platform/x86/dell-wmi-descriptor.h new file mode 100644 index 000000000000..5f7b69c2c83a --- /dev/null +++ b/drivers/platform/x86/dell-wmi-descriptor.h @@ -0,0 +1,21 @@ +/* + * Dell WMI descriptor driver + * + * Copyright (c) 2017 Dell Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _DELL_WMI_DESCRIPTOR_H_ +#define _DELL_WMI_DESCRIPTOR_H_ + +#include + +#define DELL_WMI_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492" + +bool dell_wmi_get_interface_version(u32 *version); +bool dell_wmi_get_size(u32 *size); + +#endif diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index da4f629d0831..6d657eb97672 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -39,6 +39,7 @@ #include #include #include "dell-smbios.h" +#include "dell-wmi-descriptor.h" MODULE_AUTHOR("Matthew Garrett "); MODULE_AUTHOR("Pali Rohár "); @@ -46,7 +47,6 @@ MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver"); MODULE_LICENSE("GPL"); #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492" -#define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492" static bool wmi_requires_smbios_request; @@ -617,75 +617,6 @@ static void dell_wmi_input_destroy(struct wmi_device *wdev) input_unregister_device(priv->input_dev); } -/* - * Descriptor buffer is 128 byte long and contains: - * - * Name Offset Length Value - * Vendor Signature 0 4 "DELL" - * Object Signature 4 4 " WMI" - * WMI Interface Version 8 4 - * WMI buffer length 12 4 - */ -static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev) -{ - struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev); - union acpi_object *obj = NULL; - struct wmi_device *desc_dev; - u32 *buffer; - int ret; - - desc_dev = wmidev_get_other_guid(wdev, DELL_DESCRIPTOR_GUID); - if (!desc_dev) { - dev_err(&wdev->dev, "Dell WMI descriptor does not exist\n"); - return -ENODEV; - } - - obj = wmidev_block_query(desc_dev, 0); - if (!obj) { - dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n"); - ret = -EIO; - goto out; - } - - if (obj->type != ACPI_TYPE_BUFFER) { - dev_err(&wdev->dev, "Dell descriptor has wrong type\n"); - ret = -EINVAL; - goto out; - } - - if (obj->buffer.length != 128) { - dev_err(&wdev->dev, - "Dell descriptor buffer has invalid length (%d)\n", - obj->buffer.length); - ret = -EINVAL; - goto out; - } - - buffer = (u32 *)obj->buffer.pointer; - - if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) { - dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n", - buffer); - ret = -EINVAL; - goto out; - } - - if (buffer[2] != 0 && buffer[2] != 1) - dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%lu)\n", - (unsigned long) buffer[2]); - - priv->interface_version = buffer[2]; - ret = 0; - - dev_info(&wdev->dev, "Detected Dell WMI interface version %u\n", - priv->interface_version); - -out: - kfree(obj); - put_device(&desc_dev->dev); - return ret; -} - /* * According to Dell SMBIOS documentation: * @@ -721,7 +652,9 @@ static int dell_wmi_events_set_enabled(bool enable) static int dell_wmi_probe(struct wmi_device *wdev) { struct dell_wmi_priv *priv; - int err; + + if (!wmi_has_guid(DELL_WMI_DESCRIPTOR_GUID)) + return -ENODEV; priv = devm_kzalloc( &wdev->dev, sizeof(struct dell_wmi_priv), GFP_KERNEL); @@ -729,9 +662,8 @@ static int dell_wmi_probe(struct wmi_device *wdev) return -ENOMEM; dev_set_drvdata(&wdev->dev, priv); - err = dell_wmi_check_descriptor_buffer(wdev); - if (err) - return err; + if (!dell_wmi_get_interface_version(&priv->interface_version)) + return -EPROBE_DEFER; return dell_wmi_input_setup(wdev); } -- GitLab From f97e058cfe8032504e310bd5c20e35d640ef2858 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:28 -0500 Subject: [PATCH 1588/2898] platform/x86: wmi: Don't allow drivers to get each other's GUIDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only driver using this was dell-wmi, and it really was a hack. The driver was getting a data attribute from another driver and this type of action should not be encouraged. Rather drivers that need to interact with one another should pass data back and forth via exported functions. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Reviewed-by: Pali Rohár Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 17 ----------------- include/linux/wmi.h | 4 ---- 2 files changed, 21 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 4d73a87c2ddf..bcb41c1c7f52 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -368,23 +368,6 @@ union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance) } EXPORT_SYMBOL_GPL(wmidev_block_query); -struct wmi_device *wmidev_get_other_guid(struct wmi_device *wdev, - const char *guid_string) -{ - struct wmi_block *this_wb = container_of(wdev, struct wmi_block, dev); - struct wmi_block *other_wb; - - if (!find_guid(guid_string, &other_wb)) - return NULL; - - if (other_wb->acpi_device != this_wb->acpi_device) - return NULL; - - get_device(&other_wb->dev.dev); - return &other_wb->dev; -} -EXPORT_SYMBOL_GPL(wmidev_get_other_guid); - /** * wmi_set_block - Write to a WMI block * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba diff --git a/include/linux/wmi.h b/include/linux/wmi.h index 2cd10c3b89e9..ddee427e0721 100644 --- a/include/linux/wmi.h +++ b/include/linux/wmi.h @@ -36,10 +36,6 @@ extern acpi_status wmidev_evaluate_method(struct wmi_device *wdev, extern union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance); -/* Gets another device on the same bus. Caller must put_device the result. */ -extern struct wmi_device *wmidev_get_other_guid(struct wmi_device *wdev, - const char *guid_string); - struct wmi_device_id { const char *guid_string; }; -- GitLab From 980f481d63f57bb62ac171a66294de3e14d52b77 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:29 -0500 Subject: [PATCH 1589/2898] platform/x86: dell-smbios: only run if proper oem string is detected The proper way to indicate that a system is a 'supported' Dell System is by the presence of this string in OEM strings. Allowing the driver to load on non-Dell systems will have undefined results. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-smbios.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index ffc174638aa4..12a3eb153911 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -172,8 +172,15 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy) static int __init dell_smbios_init(void) { + const struct dmi_device *valid; int ret; + valid = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL); + if (!valid) { + pr_err("Unable to run on non-Dell system\n"); + return -ENODEV; + } + dmi_walk(find_tokens, NULL); if (!da_tokens) { -- GitLab From 33b9ca1e53b45f7cacdba9d4fba5cb1387b26827 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:30 -0500 Subject: [PATCH 1590/2898] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens Currently userspace tools can access system tokens via the dcdbas kernel module and a SMI call that will cause the platform to execute SMM code. With a goal in mind of deprecating the dcdbas kernel module a different method for accessing these tokens from userspace needs to be created. This is intentionally marked to only be readable as a process with CAP_SYS_ADMIN as it can contain sensitive information about the platform's configuration. While adding this interface I found that some tokens are duplicated. These need to be ignored from sysfs to avoid duplicate files. MAINTAINERS was missing for this driver. Add myself and Pali to maintainers list for it. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- .../ABI/testing/sysfs-platform-dell-smbios | 21 ++ MAINTAINERS | 7 + drivers/platform/x86/dell-smbios.c | 213 +++++++++++++++++- 3 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-platform-dell-smbios diff --git a/Documentation/ABI/testing/sysfs-platform-dell-smbios b/Documentation/ABI/testing/sysfs-platform-dell-smbios new file mode 100644 index 000000000000..205d3b6361e0 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-dell-smbios @@ -0,0 +1,21 @@ +What: /sys/devices/platform//tokens/* +Date: November 2017 +KernelVersion: 4.15 +Contact: "Mario Limonciello" +Description: + A read-only description of Dell platform tokens + available on the machine. + + Each token attribute is available as a pair of + sysfs attributes readable by a process with + CAP_SYS_ADMIN. + + For example the token ID "5" would be available + as the following attributes: + + 0005_location + 0005_value + + Tokens will vary from machine to machine, and + only tokens available on that machine will be + displayed. diff --git a/MAINTAINERS b/MAINTAINERS index 69a81400cc65..cb4bc87874c0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3978,6 +3978,13 @@ M: "Maciej W. Rozycki" S: Maintained F: drivers/net/fddi/defxx.* +DELL SMBIOS DRIVER +M: Pali Rohár +M: Mario Limonciello +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/dell-smbios.* + DELL LAPTOP DRIVER M: Matthew Garrett M: Pali Rohár diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index 12a3eb153911..ed4995fdcd46 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -16,10 +16,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include "../../firmware/dcdbas.h" @@ -39,7 +41,11 @@ static DEFINE_MUTEX(buffer_mutex); static int da_command_address; static int da_command_code; static int da_num_tokens; +static struct platform_device *platform_device; static struct calling_interface_token *da_tokens; +static struct device_attribute *token_location_attrs; +static struct device_attribute *token_value_attrs; +static struct attribute **token_attrs; int dell_smbios_error(int value) { @@ -157,6 +163,27 @@ static void __init parse_da_table(const struct dmi_header *dm) da_num_tokens += tokens; } +static void zero_duplicates(struct device *dev) +{ + int i, j; + + for (i = 0; i < da_num_tokens; i++) { + if (da_tokens[i].tokenID == 0) + continue; + for (j = i+1; j < da_num_tokens; j++) { + if (da_tokens[j].tokenID == 0) + continue; + if (da_tokens[i].tokenID == da_tokens[j].tokenID) { + dev_dbg(dev, "Zeroing dup token ID %x(%x/%x)\n", + da_tokens[j].tokenID, + da_tokens[j].location, + da_tokens[j].value); + da_tokens[j].tokenID = 0; + } + } + } +} + static void __init find_tokens(const struct dmi_header *dm, void *dummy) { switch (dm->type) { @@ -170,6 +197,154 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy) } } +static int match_attribute(struct device *dev, + struct device_attribute *attr) +{ + int i; + + for (i = 0; i < da_num_tokens * 2; i++) { + if (!token_attrs[i]) + continue; + if (strcmp(token_attrs[i]->name, attr->attr.name) == 0) + return i/2; + } + dev_dbg(dev, "couldn't match: %s\n", attr->attr.name); + return -EINVAL; +} + +static ssize_t location_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + i = match_attribute(dev, attr); + if (i > 0) + return scnprintf(buf, PAGE_SIZE, "%08x", da_tokens[i].location); + return 0; +} + +static ssize_t value_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + i = match_attribute(dev, attr); + if (i > 0) + return scnprintf(buf, PAGE_SIZE, "%08x", da_tokens[i].value); + return 0; +} + +static struct attribute_group smbios_attribute_group = { + .name = "tokens" +}; + +static struct platform_driver platform_driver = { + .driver = { + .name = "dell-smbios", + }, +}; + +static int build_tokens_sysfs(struct platform_device *dev) +{ + char buffer_location[13]; + char buffer_value[10]; + char *location_name; + char *value_name; + size_t size; + int ret; + int i, j; + + /* (number of tokens + 1 for null terminated */ + size = sizeof(struct device_attribute) * (da_num_tokens + 1); + token_location_attrs = kzalloc(size, GFP_KERNEL); + if (!token_location_attrs) + return -ENOMEM; + token_value_attrs = kzalloc(size, GFP_KERNEL); + if (!token_value_attrs) + goto out_allocate_value; + + /* need to store both location and value + terminator*/ + size = sizeof(struct attribute *) * ((2 * da_num_tokens) + 1); + token_attrs = kzalloc(size, GFP_KERNEL); + if (!token_attrs) + goto out_allocate_attrs; + + for (i = 0, j = 0; i < da_num_tokens; i++) { + /* skip empty */ + if (da_tokens[i].tokenID == 0) + continue; + /* add location */ + sprintf(buffer_location, "%04x_location", + da_tokens[i].tokenID); + location_name = kstrdup(buffer_location, GFP_KERNEL); + if (location_name == NULL) + goto out_unwind_strings; + sysfs_attr_init(&token_location_attrs[i].attr); + token_location_attrs[i].attr.name = location_name; + token_location_attrs[i].attr.mode = 0444; + token_location_attrs[i].show = location_show; + token_attrs[j++] = &token_location_attrs[i].attr; + + /* add value */ + sprintf(buffer_value, "%04x_value", + da_tokens[i].tokenID); + value_name = kstrdup(buffer_value, GFP_KERNEL); + if (value_name == NULL) + goto loop_fail_create_value; + sysfs_attr_init(&token_value_attrs[i].attr); + token_value_attrs[i].attr.name = value_name; + token_value_attrs[i].attr.mode = 0444; + token_value_attrs[i].show = value_show; + token_attrs[j++] = &token_value_attrs[i].attr; + continue; + +loop_fail_create_value: + kfree(value_name); + goto out_unwind_strings; + } + smbios_attribute_group.attrs = token_attrs; + + ret = sysfs_create_group(&dev->dev.kobj, &smbios_attribute_group); + if (ret) + goto out_unwind_strings; + return 0; + +out_unwind_strings: + for (i = i-1; i > 0; i--) { + kfree(token_location_attrs[i].attr.name); + kfree(token_value_attrs[i].attr.name); + } + kfree(token_attrs); +out_allocate_attrs: + kfree(token_value_attrs); +out_allocate_value: + kfree(token_location_attrs); + + return -ENOMEM; +} + +static void free_group(struct platform_device *pdev) +{ + int i; + + sysfs_remove_group(&pdev->dev.kobj, + &smbios_attribute_group); + for (i = 0; i < da_num_tokens; i++) { + kfree(token_location_attrs[i].attr.name); + kfree(token_value_attrs[i].attr.name); + } + kfree(token_attrs); + kfree(token_value_attrs); + kfree(token_location_attrs); +} + + static int __init dell_smbios_init(void) { const struct dmi_device *valid; @@ -197,9 +372,40 @@ static int __init dell_smbios_init(void) ret = -ENOMEM; goto fail_buffer; } + ret = platform_driver_register(&platform_driver); + if (ret) + goto fail_platform_driver; + + platform_device = platform_device_alloc("dell-smbios", 0); + if (!platform_device) { + ret = -ENOMEM; + goto fail_platform_device_alloc; + } + ret = platform_device_add(platform_device); + if (ret) + goto fail_platform_device_add; + + /* duplicate tokens will cause problems building sysfs files */ + zero_duplicates(&platform_device->dev); + + ret = build_tokens_sysfs(platform_device); + if (ret) + goto fail_create_group; return 0; +fail_create_group: + platform_device_del(platform_device); + +fail_platform_device_add: + platform_device_put(platform_device); + +fail_platform_device_alloc: + platform_driver_unregister(&platform_driver); + +fail_platform_driver: + free_page((unsigned long)buffer); + fail_buffer: kfree(da_tokens); return ret; @@ -207,8 +413,13 @@ static int __init dell_smbios_init(void) static void __exit dell_smbios_exit(void) { - kfree(da_tokens); + if (platform_device) { + free_group(platform_device); + platform_device_unregister(platform_device); + platform_driver_unregister(&platform_driver); + } free_page((unsigned long)buffer); + kfree(da_tokens); } subsys_initcall(dell_smbios_init); -- GitLab From 549b4930f057658dc50d8010e66219233119a4d8 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:31 -0500 Subject: [PATCH 1591/2898] platform/x86: dell-smbios: Introduce dispatcher for SMM calls This splits up the dell-smbios driver into two drivers: * dell-smbios * dell-smbios-smm dell-smbios can operate with multiple different dispatcher drivers to perform SMBIOS operations. Also modify the interface that dell-laptop and dell-wmi use align to this model more closely. Rather than a single global buffer being allocated for all drivers, each driver will allocate and be responsible for it's own buffer. The pointer will be passed to the calling function and each dispatcher driver will then internally copy it to the proper location to perform it's call. Add defines for calls used by these methods in the dell-smbios.h header for tracking purposes. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- MAINTAINERS | 6 + drivers/platform/x86/Kconfig | 15 +- drivers/platform/x86/Makefile | 1 + drivers/platform/x86/dell-laptop.c | 283 +++++++++---------------- drivers/platform/x86/dell-smbios-smm.c | 163 ++++++++++++++ drivers/platform/x86/dell-smbios.c | 121 ++++++----- drivers/platform/x86/dell-smbios.h | 46 +++- drivers/platform/x86/dell-wmi.c | 11 +- 8 files changed, 398 insertions(+), 248 deletions(-) create mode 100644 drivers/platform/x86/dell-smbios-smm.c diff --git a/MAINTAINERS b/MAINTAINERS index cb4bc87874c0..c74f40ae8622 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3985,6 +3985,12 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/dell-smbios.* +DELL SMBIOS SMM DRIVER +M: Mario Limonciello +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/dell-smbios-smm.c + DELL LAPTOP DRIVER M: Matthew Garrett M: Pali Rohár diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index a0babdc5136f..ebe7870a7d9f 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -93,12 +93,19 @@ config ASUS_LAPTOP config DELL_SMBIOS tristate - select DCDBAS + +config DELL_SMBIOS_SMM + tristate "Dell SMBIOS calling interface (SMM implementation)" + depends on DCDBAS + default DCDBAS + select DELL_SMBIOS ---help--- - This module provides common functions for kernel modules using - Dell SMBIOS. + This provides an implementation for the Dell SMBIOS calling interface + communicated over SMI/SMM. - If you have a Dell laptop, say Y or M here. + If you have a Dell computer from <=2017 you should say Y or M here. + If you aren't sure and this module doesn't work for your computer + it just won't load. config DELL_LAPTOP tristate "Dell Laptop Extras" diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 8636f5d3424f..e743615241f8 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o +obj-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index f42159fd2031..c4903c5ce7cf 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -35,18 +35,6 @@ #include "dell-rbtn.h" #include "dell-smbios.h" -#define BRIGHTNESS_TOKEN 0x7d -#define KBD_LED_OFF_TOKEN 0x01E1 -#define KBD_LED_ON_TOKEN 0x01E2 -#define KBD_LED_AUTO_TOKEN 0x01E3 -#define KBD_LED_AUTO_25_TOKEN 0x02EA -#define KBD_LED_AUTO_50_TOKEN 0x02EB -#define KBD_LED_AUTO_75_TOKEN 0x02EC -#define KBD_LED_AUTO_100_TOKEN 0x02F6 -#define GLOBAL_MIC_MUTE_ENABLE 0x0364 -#define GLOBAL_MIC_MUTE_DISABLE 0x0365 -#define KBD_LED_AC_TOKEN 0x0451 - struct quirk_entry { u8 touchpad_led; @@ -85,6 +73,7 @@ static struct platform_driver platform_driver = { } }; +static struct calling_interface_buffer *buffer; static struct platform_device *platform_device; static struct backlight_device *dell_backlight_device; static struct rfkill *wifi_rfkill; @@ -283,6 +272,27 @@ static const struct dmi_system_id dell_quirks[] __initconst = { { } }; +void dell_set_arguments(u32 arg0, u32 arg1, u32 arg2, u32 arg3) +{ + memset(buffer, 0, sizeof(struct calling_interface_buffer)); + buffer->input[0] = arg0; + buffer->input[1] = arg1; + buffer->input[2] = arg2; + buffer->input[3] = arg3; +} + +int dell_send_request(u16 class, u16 select) +{ + int ret; + + buffer->cmd_class = class; + buffer->cmd_select = select; + ret = dell_smbios_call(buffer); + if (ret != 0) + return ret; + return dell_smbios_error(buffer->output[0]); +} + /* * Derived from information in smbios-wireless-ctl: * @@ -405,7 +415,6 @@ static const struct dmi_system_id dell_quirks[] __initconst = { static int dell_rfkill_set(void *data, bool blocked) { - struct calling_interface_buffer *buffer; int disable = blocked ? 1 : 0; unsigned long radio = (unsigned long)data; int hwswitch_bit = (unsigned long)data - 1; @@ -413,20 +422,16 @@ static int dell_rfkill_set(void *data, bool blocked) int status; int ret; - buffer = dell_smbios_get_buffer(); - - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; + dell_set_arguments(0, 0, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); + if (ret) + return ret; status = buffer->output[1]; - if (ret != 0) - goto out; - - dell_smbios_clear_buffer(); - - buffer->input[0] = 0x2; - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; + dell_set_arguments(0x2, 0, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); + if (ret) + return ret; hwswitch = buffer->output[1]; /* If the hardware switch controls this radio, and the hardware @@ -435,28 +440,19 @@ static int dell_rfkill_set(void *data, bool blocked) (status & BIT(0)) && !(status & BIT(16))) disable = 1; - dell_smbios_clear_buffer(); - - buffer->input[0] = (1 | (radio<<8) | (disable << 16)); - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; - - out: - dell_smbios_release_buffer(); - return dell_smbios_error(ret); + dell_set_arguments(1 | (radio<<8) | (disable << 16), 0, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); + return ret; } -/* Must be called with the buffer held */ static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, - int status, - struct calling_interface_buffer *buffer) + int status) { if (status & BIT(0)) { /* Has hw-switch, sync sw_state to BIOS */ int block = rfkill_blocked(rfkill); - dell_smbios_clear_buffer(); - buffer->input[0] = (1 | (radio << 8) | (block << 16)); - dell_smbios_send_request(17, 11); + dell_set_arguments(1 | (radio << 8) | (block << 16), 0, 0, 0); + dell_send_request(CLASS_INFO, SELECT_RFKILL); } else { /* No hw-switch, sync BIOS state to sw_state */ rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); @@ -472,32 +468,23 @@ static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio, static void dell_rfkill_query(struct rfkill *rfkill, void *data) { - struct calling_interface_buffer *buffer; int radio = ((unsigned long)data & 0xF); int hwswitch; int status; int ret; - buffer = dell_smbios_get_buffer(); - - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; + dell_set_arguments(0, 0, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); status = buffer->output[1]; if (ret != 0 || !(status & BIT(0))) { - dell_smbios_release_buffer(); return; } - dell_smbios_clear_buffer(); - - buffer->input[0] = 0x2; - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; + dell_set_arguments(0, 0x2, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); hwswitch = buffer->output[1]; - dell_smbios_release_buffer(); - if (ret != 0) return; @@ -513,27 +500,23 @@ static struct dentry *dell_laptop_dir; static int dell_debugfs_show(struct seq_file *s, void *data) { - struct calling_interface_buffer *buffer; int hwswitch_state; int hwswitch_ret; int status; int ret; - buffer = dell_smbios_get_buffer(); - - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; + dell_set_arguments(0, 0, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); + if (ret) + return ret; status = buffer->output[1]; - dell_smbios_clear_buffer(); - - buffer->input[0] = 0x2; - dell_smbios_send_request(17, 11); - hwswitch_ret = buffer->output[0]; + dell_set_arguments(0, 0x2, 0, 0); + hwswitch_ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); + if (hwswitch_ret) + return hwswitch_ret; hwswitch_state = buffer->output[1]; - dell_smbios_release_buffer(); - seq_printf(s, "return:\t%d\n", ret); seq_printf(s, "status:\t0x%X\n", status); seq_printf(s, "Bit 0 : Hardware switch supported: %lu\n", @@ -613,46 +596,36 @@ static const struct file_operations dell_debugfs_fops = { static void dell_update_rfkill(struct work_struct *ignored) { - struct calling_interface_buffer *buffer; int hwswitch = 0; int status; int ret; - buffer = dell_smbios_get_buffer(); - - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; + dell_set_arguments(0, 0, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); status = buffer->output[1]; if (ret != 0) - goto out; - - dell_smbios_clear_buffer(); + return; - buffer->input[0] = 0x2; - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; + dell_set_arguments(0, 0x2, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); if (ret == 0 && (status & BIT(0))) hwswitch = buffer->output[1]; if (wifi_rfkill) { dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch); - dell_rfkill_update_sw_state(wifi_rfkill, 1, status, buffer); + dell_rfkill_update_sw_state(wifi_rfkill, 1, status); } if (bluetooth_rfkill) { dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status, hwswitch); - dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status, - buffer); + dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status); } if (wwan_rfkill) { dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch); - dell_rfkill_update_sw_state(wwan_rfkill, 3, status, buffer); + dell_rfkill_update_sw_state(wwan_rfkill, 3, status); } - - out: - dell_smbios_release_buffer(); } static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); @@ -696,7 +669,6 @@ static struct notifier_block dell_laptop_rbtn_notifier = { static int __init dell_setup_rfkill(void) { - struct calling_interface_buffer *buffer; int status, ret, whitelisted; const char *product; @@ -712,11 +684,9 @@ static int __init dell_setup_rfkill(void) if (!force_rfkill && !whitelisted) return 0; - buffer = dell_smbios_get_buffer(); - dell_smbios_send_request(17, 11); - ret = buffer->output[0]; + dell_set_arguments(0, 0, 0, 0); + ret = dell_send_request(CLASS_INFO, SELECT_RFKILL); status = buffer->output[1]; - dell_smbios_release_buffer(); /* dell wireless info smbios call is not supported */ if (ret != 0) @@ -869,7 +839,6 @@ static void dell_cleanup_rfkill(void) static int dell_send_intensity(struct backlight_device *bd) { - struct calling_interface_buffer *buffer; struct calling_interface_token *token; int ret; @@ -877,24 +846,17 @@ static int dell_send_intensity(struct backlight_device *bd) if (!token) return -ENODEV; - buffer = dell_smbios_get_buffer(); - buffer->input[0] = token->location; - buffer->input[1] = bd->props.brightness; - + dell_set_arguments(token->location, bd->props.brightness, 0, 0); if (power_supply_is_system_supplied() > 0) - dell_smbios_send_request(1, 2); + ret = dell_send_request(CLASS_TOKEN_WRITE, SELECT_TOKEN_AC); else - dell_smbios_send_request(1, 1); + ret = dell_send_request(CLASS_TOKEN_WRITE, SELECT_TOKEN_BAT); - ret = dell_smbios_error(buffer->output[0]); - - dell_smbios_release_buffer(); return ret; } static int dell_get_intensity(struct backlight_device *bd) { - struct calling_interface_buffer *buffer; struct calling_interface_token *token; int ret; @@ -902,20 +864,14 @@ static int dell_get_intensity(struct backlight_device *bd) if (!token) return -ENODEV; - buffer = dell_smbios_get_buffer(); - buffer->input[0] = token->location; - + dell_set_arguments(token->location, 0, 0, 0); if (power_supply_is_system_supplied() > 0) - dell_smbios_send_request(0, 2); + ret = dell_send_request(CLASS_TOKEN_READ, SELECT_TOKEN_AC); else - dell_smbios_send_request(0, 1); + ret = dell_send_request(CLASS_TOKEN_READ, SELECT_TOKEN_BAT); - if (buffer->output[0]) - ret = dell_smbios_error(buffer->output[0]); - else + if (ret == 0) ret = buffer->output[1]; - - dell_smbios_release_buffer(); return ret; } @@ -1179,20 +1135,13 @@ static DEFINE_MUTEX(kbd_led_mutex); static int kbd_get_info(struct kbd_info *info) { - struct calling_interface_buffer *buffer; u8 units; int ret; - buffer = dell_smbios_get_buffer(); - - buffer->input[0] = 0x0; - dell_smbios_send_request(4, 11); - ret = buffer->output[0]; - - if (ret) { - ret = dell_smbios_error(ret); - goto out; - } + dell_set_arguments(0, 0, 0, 0); + ret = dell_send_request(CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT); + if (ret) + return ret; info->modes = buffer->output[1] & 0xFFFF; info->type = (buffer->output[1] >> 24) & 0xFF; @@ -1209,8 +1158,6 @@ static int kbd_get_info(struct kbd_info *info) if (units & BIT(3)) info->days = (buffer->output[3] >> 24) & 0xFF; - out: - dell_smbios_release_buffer(); return ret; } @@ -1269,19 +1216,12 @@ static int kbd_set_level(struct kbd_state *state, u8 level) static int kbd_get_state(struct kbd_state *state) { - struct calling_interface_buffer *buffer; int ret; - buffer = dell_smbios_get_buffer(); - - buffer->input[0] = 0x1; - dell_smbios_send_request(4, 11); - ret = buffer->output[0]; - - if (ret) { - ret = dell_smbios_error(ret); - goto out; - } + dell_set_arguments(0x1, 0, 0, 0); + ret = dell_send_request(CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT); + if (ret) + return ret; state->mode_bit = ffs(buffer->output[1] & 0xFFFF); if (state->mode_bit != 0) @@ -1296,31 +1236,27 @@ static int kbd_get_state(struct kbd_state *state) state->timeout_value_ac = (buffer->output[2] >> 24) & 0x3F; state->timeout_unit_ac = (buffer->output[2] >> 30) & 0x3; - out: - dell_smbios_release_buffer(); return ret; } static int kbd_set_state(struct kbd_state *state) { - struct calling_interface_buffer *buffer; int ret; + u32 input1; + u32 input2; + + input1 = BIT(state->mode_bit) & 0xFFFF; + input1 |= (state->triggers & 0xFF) << 16; + input1 |= (state->timeout_value & 0x3F) << 24; + input1 |= (state->timeout_unit & 0x3) << 30; + input2 = state->als_setting & 0xFF; + input2 |= (state->level & 0xFF) << 16; + input2 |= (state->timeout_value_ac & 0x3F) << 24; + input2 |= (state->timeout_unit_ac & 0x3) << 30; + dell_set_arguments(0x2, input1, input2, 0); + ret = dell_send_request(CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT); - buffer = dell_smbios_get_buffer(); - buffer->input[0] = 0x2; - buffer->input[1] = BIT(state->mode_bit) & 0xFFFF; - buffer->input[1] |= (state->triggers & 0xFF) << 16; - buffer->input[1] |= (state->timeout_value & 0x3F) << 24; - buffer->input[1] |= (state->timeout_unit & 0x3) << 30; - buffer->input[2] = state->als_setting & 0xFF; - buffer->input[2] |= (state->level & 0xFF) << 16; - buffer->input[2] |= (state->timeout_value_ac & 0x3F) << 24; - buffer->input[2] |= (state->timeout_unit_ac & 0x3) << 30; - dell_smbios_send_request(4, 11); - ret = buffer->output[0]; - dell_smbios_release_buffer(); - - return dell_smbios_error(ret); + return ret; } static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old) @@ -1345,7 +1281,6 @@ static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old) static int kbd_set_token_bit(u8 bit) { - struct calling_interface_buffer *buffer; struct calling_interface_token *token; int ret; @@ -1356,19 +1291,14 @@ static int kbd_set_token_bit(u8 bit) if (!token) return -EINVAL; - buffer = dell_smbios_get_buffer(); - buffer->input[0] = token->location; - buffer->input[1] = token->value; - dell_smbios_send_request(1, 0); - ret = buffer->output[0]; - dell_smbios_release_buffer(); + dell_set_arguments(token->location, token->value, 0, 0); + ret = dell_send_request(CLASS_TOKEN_WRITE, SELECT_TOKEN_STD); - return dell_smbios_error(ret); + return ret; } static int kbd_get_token_bit(u8 bit) { - struct calling_interface_buffer *buffer; struct calling_interface_token *token; int ret; int val; @@ -1380,15 +1310,12 @@ static int kbd_get_token_bit(u8 bit) if (!token) return -EINVAL; - buffer = dell_smbios_get_buffer(); - buffer->input[0] = token->location; - dell_smbios_send_request(0, 0); - ret = buffer->output[0]; + dell_set_arguments(token->location, 0, 0, 0); + ret = dell_send_request(CLASS_TOKEN_READ, SELECT_TOKEN_STD); val = buffer->output[1]; - dell_smbios_release_buffer(); if (ret) - return dell_smbios_error(ret); + return ret; return (val == token->value); } @@ -2102,7 +2029,6 @@ static struct notifier_block dell_laptop_notifier = { int dell_micmute_led_set(int state) { - struct calling_interface_buffer *buffer; struct calling_interface_token *token; if (state == 0) @@ -2115,11 +2041,8 @@ int dell_micmute_led_set(int state) if (!token) return -ENODEV; - buffer = dell_smbios_get_buffer(); - buffer->input[0] = token->location; - buffer->input[1] = token->value; - dell_smbios_send_request(1, 0); - dell_smbios_release_buffer(); + dell_set_arguments(token->location, token->value, 0, 0); + dell_send_request(CLASS_TOKEN_WRITE, SELECT_TOKEN_STD); return state; } @@ -2127,7 +2050,6 @@ EXPORT_SYMBOL_GPL(dell_micmute_led_set); static int __init dell_init(void) { - struct calling_interface_buffer *buffer; struct calling_interface_token *token; int max_intensity = 0; int ret; @@ -2158,6 +2080,10 @@ static int __init dell_init(void) goto fail_rfkill; } + buffer = kzalloc(sizeof(struct calling_interface_buffer), GFP_KERNEL); + if (!buffer) + goto fail_buffer; + if (quirks && quirks->touchpad_led) touchpad_led_init(&platform_device->dev); @@ -2175,12 +2101,10 @@ static int __init dell_init(void) token = dell_smbios_find_token(BRIGHTNESS_TOKEN); if (token) { - buffer = dell_smbios_get_buffer(); - buffer->input[0] = token->location; - dell_smbios_send_request(0, 2); - if (buffer->output[0] == 0) + dell_set_arguments(token->location, 0, 0, 0); + ret = dell_send_request(CLASS_TOKEN_READ, SELECT_TOKEN_AC); + if (ret) max_intensity = buffer->output[3]; - dell_smbios_release_buffer(); } if (max_intensity) { @@ -2214,6 +2138,8 @@ static int __init dell_init(void) fail_get_brightness: backlight_device_unregister(dell_backlight_device); fail_backlight: + kfree(buffer); +fail_buffer: dell_cleanup_rfkill(); fail_rfkill: platform_device_del(platform_device); @@ -2233,6 +2159,7 @@ static void __exit dell_exit(void) touchpad_led_exit(); kbd_led_exit(); backlight_device_unregister(dell_backlight_device); + kfree(buffer); dell_cleanup_rfkill(); if (platform_device) { platform_device_unregister(platform_device); diff --git a/drivers/platform/x86/dell-smbios-smm.c b/drivers/platform/x86/dell-smbios-smm.c new file mode 100644 index 000000000000..53eabb14fb48 --- /dev/null +++ b/drivers/platform/x86/dell-smbios-smm.c @@ -0,0 +1,163 @@ +/* + * SMI methods for use with dell-smbios + * + * Copyright (c) Red Hat + * Copyright (c) 2014 Gabriele Mazzotta + * Copyright (c) 2014 Pali Rohár + * Copyright (c) 2017 Dell Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include "../../firmware/dcdbas.h" +#include "dell-smbios.h" + +static int da_command_address; +static int da_command_code; +static struct calling_interface_buffer *buffer; +struct platform_device *platform_device; +static DEFINE_MUTEX(smm_mutex); + +static const struct dmi_system_id dell_device_table[] __initconst = { + { + .ident = "Dell laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_CHASSIS_TYPE, "8"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/ + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /*Notebook*/ + }, + }, + { + .ident = "Dell Computer Corporation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), + DMI_MATCH(DMI_CHASSIS_TYPE, "8"), + }, + }, + { } +}; +MODULE_DEVICE_TABLE(dmi, dell_device_table); + +static void __init parse_da_table(const struct dmi_header *dm) +{ + struct calling_interface_structure *table = + container_of(dm, struct calling_interface_structure, header); + + /* 4 bytes of table header, plus 7 bytes of Dell header, plus at least + * 6 bytes of entry + */ + if (dm->length < 17) + return; + + da_command_address = table->cmdIOAddress; + da_command_code = table->cmdIOCode; +} + +static void __init find_cmd_address(const struct dmi_header *dm, void *dummy) +{ + switch (dm->type) { + case 0xda: /* Calling interface */ + parse_da_table(dm); + break; + } +} + +int dell_smbios_smm_call(struct calling_interface_buffer *input) +{ + struct smi_cmd command; + size_t size; + + size = sizeof(struct calling_interface_buffer); + command.magic = SMI_CMD_MAGIC; + command.command_address = da_command_address; + command.command_code = da_command_code; + command.ebx = virt_to_phys(buffer); + command.ecx = 0x42534931; + + mutex_lock(&smm_mutex); + memcpy(buffer, input, size); + dcdbas_smi_request(&command); + memcpy(input, buffer, size); + mutex_unlock(&smm_mutex); + return 0; +} + +static int __init dell_smbios_smm_init(void) +{ + int ret; + /* + * Allocate buffer below 4GB for SMI data--only 32-bit physical addr + * is passed to SMI handler. + */ + buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32); + if (!buffer) + return -ENOMEM; + + dmi_walk(find_cmd_address, NULL); + + platform_device = platform_device_alloc("dell-smbios", 1); + if (!platform_device) { + ret = -ENOMEM; + goto fail_platform_device_alloc; + } + + ret = platform_device_add(platform_device); + if (ret) + goto fail_platform_device_add; + + ret = dell_smbios_register_device(&platform_device->dev, + &dell_smbios_smm_call); + if (ret) + goto fail_register; + + return 0; + +fail_register: + platform_device_del(platform_device); + +fail_platform_device_add: + platform_device_put(platform_device); + +fail_platform_device_alloc: + free_page((unsigned long)buffer); + return ret; +} + +static void __exit dell_smbios_smm_exit(void) +{ + if (platform_device) { + dell_smbios_unregister_device(&platform_device->dev); + platform_device_unregister(platform_device); + free_page((unsigned long)buffer); + } +} + +subsys_initcall(dell_smbios_smm_init); +module_exit(dell_smbios_smm_exit); + +MODULE_AUTHOR("Matthew Garrett "); +MODULE_AUTHOR("Gabriele Mazzotta "); +MODULE_AUTHOR("Pali Rohár "); +MODULE_AUTHOR("Mario Limonciello "); +MODULE_DESCRIPTION("Dell SMBIOS communications over SMI"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index ed4995fdcd46..2229d44cb92c 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -19,33 +19,26 @@ #include #include #include -#include #include #include #include -#include -#include "../../firmware/dcdbas.h" #include "dell-smbios.h" -struct calling_interface_structure { - struct dmi_header header; - u16 cmdIOAddress; - u8 cmdIOCode; - u32 supportedCmds; - struct calling_interface_token tokens[]; -} __packed; - -static struct calling_interface_buffer *buffer; -static DEFINE_MUTEX(buffer_mutex); - -static int da_command_address; -static int da_command_code; static int da_num_tokens; static struct platform_device *platform_device; static struct calling_interface_token *da_tokens; static struct device_attribute *token_location_attrs; static struct device_attribute *token_value_attrs; static struct attribute **token_attrs; +static DEFINE_MUTEX(smbios_mutex); + +struct smbios_device { + struct list_head list; + struct device *device; + int (*call_fn)(struct calling_interface_buffer *); +}; + +static LIST_HEAD(smbios_device_list); int dell_smbios_error(int value) { @@ -62,42 +55,71 @@ int dell_smbios_error(int value) } EXPORT_SYMBOL_GPL(dell_smbios_error); -struct calling_interface_buffer *dell_smbios_get_buffer(void) +int dell_smbios_register_device(struct device *d, void *call_fn) { - mutex_lock(&buffer_mutex); - dell_smbios_clear_buffer(); - return buffer; -} -EXPORT_SYMBOL_GPL(dell_smbios_get_buffer); + struct smbios_device *priv; -void dell_smbios_clear_buffer(void) -{ - memset(buffer, 0, sizeof(struct calling_interface_buffer)); + priv = devm_kzalloc(d, sizeof(struct smbios_device), GFP_KERNEL); + if (!priv) + return -ENOMEM; + get_device(d); + priv->device = d; + priv->call_fn = call_fn; + mutex_lock(&smbios_mutex); + list_add_tail(&priv->list, &smbios_device_list); + mutex_unlock(&smbios_mutex); + dev_dbg(d, "Added device: %s\n", d->driver->name); + return 0; } -EXPORT_SYMBOL_GPL(dell_smbios_clear_buffer); +EXPORT_SYMBOL_GPL(dell_smbios_register_device); -void dell_smbios_release_buffer(void) +void dell_smbios_unregister_device(struct device *d) { - mutex_unlock(&buffer_mutex); + struct smbios_device *priv; + + mutex_lock(&smbios_mutex); + list_for_each_entry(priv, &smbios_device_list, list) { + if (priv->device == d) { + list_del(&priv->list); + put_device(d); + break; + } + } + mutex_unlock(&smbios_mutex); + dev_dbg(d, "Remove device: %s\n", d->driver->name); } -EXPORT_SYMBOL_GPL(dell_smbios_release_buffer); +EXPORT_SYMBOL_GPL(dell_smbios_unregister_device); -void dell_smbios_send_request(int class, int select) +int dell_smbios_call(struct calling_interface_buffer *buffer) { - struct smi_cmd command; + int (*call_fn)(struct calling_interface_buffer *) = NULL; + struct device *selected_dev = NULL; + struct smbios_device *priv; + int ret; + + mutex_lock(&smbios_mutex); + list_for_each_entry(priv, &smbios_device_list, list) { + if (!selected_dev || priv->device->id >= selected_dev->id) { + dev_dbg(priv->device, "Trying device ID: %d\n", + priv->device->id); + call_fn = priv->call_fn; + selected_dev = priv->device; + } + } - command.magic = SMI_CMD_MAGIC; - command.command_address = da_command_address; - command.command_code = da_command_code; - command.ebx = virt_to_phys(buffer); - command.ecx = 0x42534931; + if (!selected_dev) { + ret = -ENODEV; + pr_err("No dell-smbios drivers are loaded\n"); + goto out_smbios_call; + } - buffer->cmd_class = class; - buffer->cmd_select = select; + ret = call_fn(buffer); - dcdbas_smi_request(&command); +out_smbios_call: + mutex_unlock(&smbios_mutex); + return ret; } -EXPORT_SYMBOL_GPL(dell_smbios_send_request); +EXPORT_SYMBOL_GPL(dell_smbios_call); struct calling_interface_token *dell_smbios_find_token(int tokenid) { @@ -146,9 +168,6 @@ static void __init parse_da_table(const struct dmi_header *dm) if (dm->length < 17) return; - da_command_address = table->cmdIOAddress; - da_command_code = table->cmdIOCode; - new_da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) * sizeof(struct calling_interface_token), GFP_KERNEL); @@ -344,7 +363,6 @@ static void free_group(struct platform_device *pdev) kfree(token_location_attrs); } - static int __init dell_smbios_init(void) { const struct dmi_device *valid; @@ -363,15 +381,6 @@ static int __init dell_smbios_init(void) return -ENODEV; } - /* - * Allocate buffer below 4GB for SMI data--only 32-bit physical addr - * is passed to SMI handler. - */ - buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32); - if (!buffer) { - ret = -ENOMEM; - goto fail_buffer; - } ret = platform_driver_register(&platform_driver); if (ret) goto fail_platform_driver; @@ -404,22 +413,20 @@ static int __init dell_smbios_init(void) platform_driver_unregister(&platform_driver); fail_platform_driver: - free_page((unsigned long)buffer); - -fail_buffer: kfree(da_tokens); return ret; } static void __exit dell_smbios_exit(void) { + mutex_lock(&smbios_mutex); if (platform_device) { free_group(platform_device); platform_device_unregister(platform_device); platform_driver_unregister(&platform_driver); } - free_page((unsigned long)buffer); kfree(da_tokens); + mutex_unlock(&smbios_mutex); } subsys_initcall(dell_smbios_init); diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h index 742dd8bd66b9..b3179f5b326b 100644 --- a/drivers/platform/x86/dell-smbios.h +++ b/drivers/platform/x86/dell-smbios.h @@ -16,6 +16,35 @@ #ifndef _DELL_SMBIOS_H_ #define _DELL_SMBIOS_H_ +#include + +/* Classes and selects used in kernel drivers */ +#define CLASS_TOKEN_READ 0 +#define CLASS_TOKEN_WRITE 1 +#define SELECT_TOKEN_STD 0 +#define SELECT_TOKEN_BAT 1 +#define SELECT_TOKEN_AC 2 +#define CLASS_KBD_BACKLIGHT 4 +#define SELECT_KBD_BACKLIGHT 11 +#define CLASS_INFO 17 +#define SELECT_RFKILL 11 +#define SELECT_APP_REGISTRATION 3 + +/* Tokens used in kernel drivers, any of these + * should be filtered from userspace access + */ +#define BRIGHTNESS_TOKEN 0x007d +#define KBD_LED_AC_TOKEN 0x0451 +#define KBD_LED_OFF_TOKEN 0x01E1 +#define KBD_LED_ON_TOKEN 0x01E2 +#define KBD_LED_AUTO_TOKEN 0x01E3 +#define KBD_LED_AUTO_25_TOKEN 0x02EA +#define KBD_LED_AUTO_50_TOKEN 0x02EB +#define KBD_LED_AUTO_75_TOKEN 0x02EC +#define KBD_LED_AUTO_100_TOKEN 0x02F6 +#define GLOBAL_MIC_MUTE_ENABLE 0x0364 +#define GLOBAL_MIC_MUTE_DISABLE 0x0365 + struct notifier_block; /* This structure will be modified by the firmware when we enter @@ -37,12 +66,19 @@ struct calling_interface_token { }; }; -int dell_smbios_error(int value); +struct calling_interface_structure { + struct dmi_header header; + u16 cmdIOAddress; + u8 cmdIOCode; + u32 supportedCmds; + struct calling_interface_token tokens[]; +} __packed; -struct calling_interface_buffer *dell_smbios_get_buffer(void); -void dell_smbios_clear_buffer(void); -void dell_smbios_release_buffer(void); -void dell_smbios_send_request(int class, int select); +int dell_smbios_register_device(struct device *d, void *call_fn); +void dell_smbios_unregister_device(struct device *d); + +int dell_smbios_error(int value); +int dell_smbios_call(struct calling_interface_buffer *buffer); struct calling_interface_token *dell_smbios_find_token(int tokenid); diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 6d657eb97672..54321080a30d 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -638,13 +638,16 @@ static int dell_wmi_events_set_enabled(bool enable) struct calling_interface_buffer *buffer; int ret; - buffer = dell_smbios_get_buffer(); + buffer = kzalloc(sizeof(struct calling_interface_buffer), GFP_KERNEL); + buffer->cmd_class = CLASS_INFO; + buffer->cmd_select = SELECT_APP_REGISTRATION; buffer->input[0] = 0x10000; buffer->input[1] = 0x51534554; buffer->input[3] = enable; - dell_smbios_send_request(17, 3); - ret = buffer->output[0]; - dell_smbios_release_buffer(); + ret = dell_smbios_call(buffer); + if (ret == 0) + ret = buffer->output[0]; + kfree(buffer); return dell_smbios_error(ret); } -- GitLab From 1a258e670434f404a4500b65ba1afea2c2b29bba Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:32 -0500 Subject: [PATCH 1592/2898] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver The dell-smbios stack only currently uses an SMI interface which grants direct access to physical memory to the firmware SMM methods via a pointer. This dispatcher driver adds a WMI-ACPI interface that is detected by WMI probe and preferred over the SMI interface in dell-smbios. Changing this to operate over WMI-ACPI will use an ACPI OperationRegion for a buffer of data storage when SMM calls are performed. This is a safer approach to use in kernel drivers as the SMM will only have access to that OperationRegion. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- MAINTAINERS | 6 + drivers/platform/x86/Kconfig | 14 ++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/dell-smbios-wmi.c | 236 +++++++++++++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 drivers/platform/x86/dell-smbios-wmi.c diff --git a/MAINTAINERS b/MAINTAINERS index c74f40ae8622..aede236d10f1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3991,6 +3991,12 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/dell-smbios-smm.c +DELL SMBIOS WMI DRIVER +M: Mario Limonciello +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/dell-smbios-wmi.c + DELL LAPTOP DRIVER M: Matthew Garrett M: Pali Rohár diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index ebe7870a7d9f..1157efcc28c7 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -94,6 +94,20 @@ config ASUS_LAPTOP config DELL_SMBIOS tristate +config DELL_SMBIOS_WMI + tristate "Dell SMBIOS calling interface (WMI implementation)" + depends on ACPI_WMI + select DELL_WMI_DESCRIPTOR + default ACPI_WMI + select DELL_SMBIOS + ---help--- + This provides an implementation for the Dell SMBIOS calling interface + communicated over ACPI-WMI. + + If you have a Dell computer from >2007 you should say Y or M here. + If you aren't sure and this module doesn't work for your computer + it just won't load. + config DELL_SMBIOS_SMM tristate "Dell SMBIOS calling interface (SMM implementation)" depends on DCDBAS diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index e743615241f8..1c4234861de0 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o +obj-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o obj-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c new file mode 100644 index 000000000000..b31f457e58c3 --- /dev/null +++ b/drivers/platform/x86/dell-smbios-wmi.c @@ -0,0 +1,236 @@ +/* + * WMI methods for use with dell-smbios + * + * Copyright (c) 2017 Dell Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include "dell-smbios.h" +#include "dell-wmi-descriptor.h" + +static DEFINE_MUTEX(call_mutex); +static DEFINE_MUTEX(list_mutex); +static int wmi_supported; + +struct misc_bios_flags_structure { + struct dmi_header header; + u16 flags0; +} __packed; +#define FLAG_HAS_ACPI_WMI 0x02 + +#define DELL_WMI_SMBIOS_GUID "A80593CE-A997-11DA-B012-B622A1EF5492" + +struct dell_wmi_extensions { + __u32 argattrib; + __u32 blength; + __u8 data[]; +} __packed; + +struct dell_wmi_smbios_buffer { + struct calling_interface_buffer std; + struct dell_wmi_extensions ext; +} __packed; + +struct wmi_smbios_priv { + struct dell_wmi_smbios_buffer *buf; + struct list_head list; + struct wmi_device *wdev; + struct device *child; + u32 req_buf_size; +}; +static LIST_HEAD(wmi_list); + +static inline struct wmi_smbios_priv *get_first_smbios_priv(void) +{ + return list_first_entry_or_null(&wmi_list, + struct wmi_smbios_priv, + list); +} + +static int run_smbios_call(struct wmi_device *wdev) +{ + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + struct wmi_smbios_priv *priv; + struct acpi_buffer input; + union acpi_object *obj; + acpi_status status; + + priv = dev_get_drvdata(&wdev->dev); + input.length = priv->req_buf_size - sizeof(u64); + input.pointer = &priv->buf->std; + + dev_dbg(&wdev->dev, "evaluating: %u/%u [%x,%x,%x,%x]\n", + priv->buf->std.cmd_class, priv->buf->std.cmd_select, + priv->buf->std.input[0], priv->buf->std.input[1], + priv->buf->std.input[2], priv->buf->std.input[3]); + + status = wmidev_evaluate_method(wdev, 0, 1, &input, &output); + if (ACPI_FAILURE(status)) + return -EIO; + obj = (union acpi_object *)output.pointer; + if (obj->type != ACPI_TYPE_BUFFER) { + dev_dbg(&wdev->dev, "received type: %d\n", obj->type); + if (obj->type == ACPI_TYPE_INTEGER) + dev_dbg(&wdev->dev, "SMBIOS call failed: %llu\n", + obj->integer.value); + return -EIO; + } + memcpy(&priv->buf->std, obj->buffer.pointer, obj->buffer.length); + dev_dbg(&wdev->dev, "result: [%08x,%08x,%08x,%08x]\n", + priv->buf->std.output[0], priv->buf->std.output[1], + priv->buf->std.output[2], priv->buf->std.output[3]); + + return 0; +} + +int dell_smbios_wmi_call(struct calling_interface_buffer *buffer) +{ + struct wmi_smbios_priv *priv; + size_t difference; + size_t size; + int ret; + + mutex_lock(&call_mutex); + priv = get_first_smbios_priv(); + if (!priv) + return -ENODEV; + + size = sizeof(struct calling_interface_buffer); + difference = priv->req_buf_size - sizeof(u64) - size; + + memset(&priv->buf->ext, 0, difference); + memcpy(&priv->buf->std, buffer, size); + ret = run_smbios_call(priv->wdev); + memcpy(buffer, &priv->buf->std, size); + mutex_unlock(&call_mutex); + + return ret; +} + +static int dell_smbios_wmi_probe(struct wmi_device *wdev) +{ + struct wmi_smbios_priv *priv; + int count; + int ret; + + if (!wmi_has_guid(DELL_WMI_DESCRIPTOR_GUID)) + return -ENODEV; + + priv = devm_kzalloc(&wdev->dev, sizeof(struct wmi_smbios_priv), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* WMI buffer size will be either 4k or 32k depending on machine */ + if (!dell_wmi_get_size(&priv->req_buf_size)) + return -EPROBE_DEFER; + + count = get_order(priv->req_buf_size); + priv->buf = (void *)__get_free_pages(GFP_KERNEL, count); + if (!priv->buf) + return -ENOMEM; + + /* ID is used by dell-smbios to set priority of drivers */ + wdev->dev.id = 1; + ret = dell_smbios_register_device(&wdev->dev, &dell_smbios_wmi_call); + if (ret) + goto fail_register; + + priv->wdev = wdev; + dev_set_drvdata(&wdev->dev, priv); + mutex_lock(&list_mutex); + list_add_tail(&priv->list, &wmi_list); + mutex_unlock(&list_mutex); + + return 0; + +fail_register: + free_pages((unsigned long)priv->buf, count); + return ret; +} + +static int dell_smbios_wmi_remove(struct wmi_device *wdev) +{ + struct wmi_smbios_priv *priv = dev_get_drvdata(&wdev->dev); + int count; + + mutex_lock(&call_mutex); + mutex_lock(&list_mutex); + list_del(&priv->list); + mutex_unlock(&list_mutex); + dell_smbios_unregister_device(&wdev->dev); + count = get_order(priv->req_buf_size); + free_pages((unsigned long)priv->buf, count); + mutex_unlock(&call_mutex); + return 0; +} + +static const struct wmi_device_id dell_smbios_wmi_id_table[] = { + { .guid_string = DELL_WMI_SMBIOS_GUID }, + { }, +}; + +static void __init parse_b1_table(const struct dmi_header *dm) +{ + struct misc_bios_flags_structure *flags = + container_of(dm, struct misc_bios_flags_structure, header); + + /* 4 bytes header, 8 bytes flags */ + if (dm->length < 12) + return; + if (dm->handle != 0xb100) + return; + if ((flags->flags0 & FLAG_HAS_ACPI_WMI)) + wmi_supported = 1; +} + +static void __init find_b1(const struct dmi_header *dm, void *dummy) +{ + switch (dm->type) { + case 0xb1: /* misc bios flags */ + parse_b1_table(dm); + break; + } +} + +static struct wmi_driver dell_smbios_wmi_driver = { + .driver = { + .name = "dell-smbios", + }, + .probe = dell_smbios_wmi_probe, + .remove = dell_smbios_wmi_remove, + .id_table = dell_smbios_wmi_id_table, +}; + +static int __init init_dell_smbios_wmi(void) +{ + dmi_walk(find_b1, NULL); + + if (!wmi_supported) + return -ENODEV; + + return wmi_driver_register(&dell_smbios_wmi_driver); +} + +static void __exit exit_dell_smbios_wmi(void) +{ + wmi_driver_unregister(&dell_smbios_wmi_driver); +} + +module_init(init_dell_smbios_wmi); +module_exit(exit_dell_smbios_wmi); + +MODULE_ALIAS("wmi:" DELL_WMI_SMBIOS_GUID); +MODULE_AUTHOR("Mario Limonciello "); +MODULE_DESCRIPTION("Dell SMBIOS communications over WMI"); +MODULE_LICENSE("GPL"); -- GitLab From da1f607ed6e6a904463396bb6a28bf96584c61cc Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:33 -0500 Subject: [PATCH 1593/2898] platform/x86: dell-smbios-smm: test for WSMT WSMT is as an attestation to the OS that the platform won't modify memory outside of pre-defined areas. If a platform has WSMT enabled in BIOS setup, SMM calls through dcdbas will fail. The only way to access platform data in these instances is through the WMI SMBIOS calling interface. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-smbios-smm.c | 33 ++++++++++++++++++++++++++ drivers/platform/x86/dell-smbios.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/drivers/platform/x86/dell-smbios-smm.c b/drivers/platform/x86/dell-smbios-smm.c index 53eabb14fb48..89f65c4651a0 100644 --- a/drivers/platform/x86/dell-smbios-smm.c +++ b/drivers/platform/x86/dell-smbios-smm.c @@ -102,6 +102,32 @@ int dell_smbios_smm_call(struct calling_interface_buffer *input) return 0; } +/* When enabled this indicates that SMM won't work */ +static bool test_wsmt_enabled(void) +{ + struct calling_interface_token *wsmt; + + /* if token doesn't exist, SMM will work */ + wsmt = dell_smbios_find_token(WSMT_EN_TOKEN); + if (!wsmt) + return false; + + /* If token exists, try to access over SMM but set a dummy return. + * - If WSMT disabled it will be overwritten by SMM + * - If WSMT enabled then dummy value will remain + */ + buffer->cmd_class = CLASS_TOKEN_READ; + buffer->cmd_select = SELECT_TOKEN_STD; + memset(buffer, 0, sizeof(struct calling_interface_buffer)); + buffer->input[0] = wsmt->location; + buffer->output[0] = 99; + dell_smbios_smm_call(buffer); + if (buffer->output[0] == 99) + return true; + + return false; +} + static int __init dell_smbios_smm_init(void) { int ret; @@ -115,6 +141,12 @@ static int __init dell_smbios_smm_init(void) dmi_walk(find_cmd_address, NULL); + if (test_wsmt_enabled()) { + pr_debug("Disabling due to WSMT enabled\n"); + ret = -ENODEV; + goto fail_wsmt; + } + platform_device = platform_device_alloc("dell-smbios", 1); if (!platform_device) { ret = -ENOMEM; @@ -138,6 +170,7 @@ static int __init dell_smbios_smm_init(void) fail_platform_device_add: platform_device_put(platform_device); +fail_wsmt: fail_platform_device_alloc: free_page((unsigned long)buffer); return ret; diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h index b3179f5b326b..07effdc7ae8b 100644 --- a/drivers/platform/x86/dell-smbios.h +++ b/drivers/platform/x86/dell-smbios.h @@ -44,6 +44,8 @@ #define KBD_LED_AUTO_100_TOKEN 0x02F6 #define GLOBAL_MIC_MUTE_ENABLE 0x0364 #define GLOBAL_MIC_MUTE_DISABLE 0x0365 +#define WSMT_EN_TOKEN 0x04EC +#define WSMT_DIS_TOKEN 0x04ED struct notifier_block; -- GitLab From 1f8543a5d602b816b9b64a62cafd6caae2af4ca6 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:34 -0500 Subject: [PATCH 1594/2898] platform/x86: dell-smbios: Add filtering support When a userspace interface is introduced to dell-smbios filtering support will be used to make sure that userspace doesn't make calls deemed unsafe or that can cause the kernel drivers to get out of sync. A blacklist is provided for the following: - Items that are in use by other kernel drivers - Items that are deemed unsafe (diagnostics, write-once, etc) - Any items in the blacklist will be rejected. Following that a whitelist is provided as follows: - Each item has an associated capability. If a userspace interface accesses this item, that capability will be tested to filter the request. - If the process provides CAP_SYS_RAWIO the whitelist will be overridden. When an item is not in the blacklist, or whitelist and the process is run with insufficient capabilities the call will be rejected. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-smbios.c | 192 +++++++++++++++++++++++++++++ drivers/platform/x86/dell-smbios.h | 11 ++ 2 files changed, 203 insertions(+) diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index 2229d44cb92c..d99edd803c19 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -24,6 +24,7 @@ #include #include "dell-smbios.h" +static u32 da_supported_commands; static int da_num_tokens; static struct platform_device *platform_device; static struct calling_interface_token *da_tokens; @@ -38,6 +39,91 @@ struct smbios_device { int (*call_fn)(struct calling_interface_buffer *); }; +struct smbios_call { + u32 need_capability; + int cmd_class; + int cmd_select; +}; + +/* calls that are whitelisted for given capabilities */ +static struct smbios_call call_whitelist[] = { + /* generally tokens are allowed, but may be further filtered or + * restricted by token blacklist or whitelist + */ + {CAP_SYS_ADMIN, CLASS_TOKEN_READ, SELECT_TOKEN_STD}, + {CAP_SYS_ADMIN, CLASS_TOKEN_READ, SELECT_TOKEN_AC}, + {CAP_SYS_ADMIN, CLASS_TOKEN_READ, SELECT_TOKEN_BAT}, + {CAP_SYS_ADMIN, CLASS_TOKEN_WRITE, SELECT_TOKEN_STD}, + {CAP_SYS_ADMIN, CLASS_TOKEN_WRITE, SELECT_TOKEN_AC}, + {CAP_SYS_ADMIN, CLASS_TOKEN_WRITE, SELECT_TOKEN_BAT}, + /* used by userspace: fwupdate */ + {CAP_SYS_ADMIN, CLASS_ADMIN_PROP, SELECT_ADMIN_PROP}, + /* used by userspace: fwupd */ + {CAP_SYS_ADMIN, CLASS_INFO, SELECT_DOCK}, + {CAP_SYS_ADMIN, CLASS_FLASH_INTERFACE, SELECT_FLASH_INTERFACE}, +}; + +/* calls that are explicitly blacklisted */ +static struct smbios_call call_blacklist[] = { + {0x0000, 01, 07}, /* manufacturing use */ + {0x0000, 06, 05}, /* manufacturing use */ + {0x0000, 11, 03}, /* write once */ + {0x0000, 11, 07}, /* write once */ + {0x0000, 11, 11}, /* write once */ + {0x0000, 19, -1}, /* diagnostics */ + /* handled by kernel: dell-laptop */ + {0x0000, CLASS_INFO, SELECT_RFKILL}, + {0x0000, CLASS_KBD_BACKLIGHT, SELECT_KBD_BACKLIGHT}, +}; + +struct token_range { + u32 need_capability; + u16 min; + u16 max; +}; + +/* tokens that are whitelisted for given capabilities */ +static struct token_range token_whitelist[] = { + /* used by userspace: fwupdate */ + {CAP_SYS_ADMIN, CAPSULE_EN_TOKEN, CAPSULE_DIS_TOKEN}, + /* can indicate to userspace that WMI is needed */ + {0x0000, WSMT_EN_TOKEN, WSMT_DIS_TOKEN} +}; + +/* tokens that are explicitly blacklisted */ +static struct token_range token_blacklist[] = { + {0x0000, 0x0058, 0x0059}, /* ME use */ + {0x0000, 0x00CD, 0x00D0}, /* raid shadow copy */ + {0x0000, 0x013A, 0x01FF}, /* sata shadow copy */ + {0x0000, 0x0175, 0x0176}, /* write once */ + {0x0000, 0x0195, 0x0197}, /* diagnostics */ + {0x0000, 0x01DC, 0x01DD}, /* manufacturing use */ + {0x0000, 0x027D, 0x0284}, /* diagnostics */ + {0x0000, 0x02E3, 0x02E3}, /* manufacturing use */ + {0x0000, 0x02FF, 0x02FF}, /* manufacturing use */ + {0x0000, 0x0300, 0x0302}, /* manufacturing use */ + {0x0000, 0x0325, 0x0326}, /* manufacturing use */ + {0x0000, 0x0332, 0x0335}, /* fan control */ + {0x0000, 0x0350, 0x0350}, /* manufacturing use */ + {0x0000, 0x0363, 0x0363}, /* manufacturing use */ + {0x0000, 0x0368, 0x0368}, /* manufacturing use */ + {0x0000, 0x03F6, 0x03F7}, /* manufacturing use */ + {0x0000, 0x049E, 0x049F}, /* manufacturing use */ + {0x0000, 0x04A0, 0x04A3}, /* disagnostics */ + {0x0000, 0x04E6, 0x04E7}, /* manufacturing use */ + {0x0000, 0x4000, 0x7FFF}, /* internal BIOS use */ + {0x0000, 0x9000, 0x9001}, /* internal BIOS use */ + {0x0000, 0xA000, 0xBFFF}, /* write only */ + {0x0000, 0xEFF0, 0xEFFF}, /* internal BIOS use */ + /* handled by kernel: dell-laptop */ + {0x0000, BRIGHTNESS_TOKEN, BRIGHTNESS_TOKEN}, + {0x0000, KBD_LED_OFF_TOKEN, KBD_LED_AUTO_TOKEN}, + {0x0000, KBD_LED_AC_TOKEN, KBD_LED_AC_TOKEN}, + {0x0000, KBD_LED_AUTO_25_TOKEN, KBD_LED_AUTO_75_TOKEN}, + {0x0000, KBD_LED_AUTO_100_TOKEN, KBD_LED_AUTO_100_TOKEN}, + {0x0000, GLOBAL_MIC_MUTE_ENABLE, GLOBAL_MIC_MUTE_DISABLE}, +}; + static LIST_HEAD(smbios_device_list); int dell_smbios_error(int value) @@ -90,6 +176,110 @@ void dell_smbios_unregister_device(struct device *d) } EXPORT_SYMBOL_GPL(dell_smbios_unregister_device); +int dell_smbios_call_filter(struct device *d, + struct calling_interface_buffer *buffer) +{ + u16 t = 0; + int i; + + /* can't make calls over 30 */ + if (buffer->cmd_class > 30) { + dev_dbg(d, "class too big: %u\n", buffer->cmd_class); + return -EINVAL; + } + + /* supported calls on the particular system */ + if (!(da_supported_commands & (1 << buffer->cmd_class))) { + dev_dbg(d, "invalid command, supported commands: 0x%8x\n", + da_supported_commands); + return -EINVAL; + } + + /* match against call blacklist */ + for (i = 0; i < ARRAY_SIZE(call_blacklist); i++) { + if (buffer->cmd_class != call_blacklist[i].cmd_class) + continue; + if (buffer->cmd_select != call_blacklist[i].cmd_select && + call_blacklist[i].cmd_select != -1) + continue; + dev_dbg(d, "blacklisted command: %u/%u\n", + buffer->cmd_class, buffer->cmd_select); + return -EINVAL; + } + + /* if a token call, find token ID */ + + if ((buffer->cmd_class == CLASS_TOKEN_READ || + buffer->cmd_class == CLASS_TOKEN_WRITE) && + buffer->cmd_select < 3) { + /* find the matching token ID */ + for (i = 0; i < da_num_tokens; i++) { + if (da_tokens[i].location != buffer->input[0]) + continue; + t = da_tokens[i].tokenID; + break; + } + + /* token call; but token didn't exist */ + if (!t) { + dev_dbg(d, "token at location %04x doesn't exist\n", + buffer->input[0]); + return -EINVAL; + } + + /* match against token blacklist */ + for (i = 0; i < ARRAY_SIZE(token_blacklist); i++) { + if (!token_blacklist[i].min || !token_blacklist[i].max) + continue; + if (t >= token_blacklist[i].min && + t <= token_blacklist[i].max) + return -EINVAL; + } + + /* match against token whitelist */ + for (i = 0; i < ARRAY_SIZE(token_whitelist); i++) { + if (!token_whitelist[i].min || !token_whitelist[i].max) + continue; + if (t < token_whitelist[i].min || + t > token_whitelist[i].max) + continue; + if (!token_whitelist[i].need_capability || + capable(token_whitelist[i].need_capability)) { + dev_dbg(d, "whitelisted token: %x\n", t); + return 0; + } + + } + } + /* match against call whitelist */ + for (i = 0; i < ARRAY_SIZE(call_whitelist); i++) { + if (buffer->cmd_class != call_whitelist[i].cmd_class) + continue; + if (buffer->cmd_select != call_whitelist[i].cmd_select) + continue; + if (!call_whitelist[i].need_capability || + capable(call_whitelist[i].need_capability)) { + dev_dbg(d, "whitelisted capable command: %u/%u\n", + buffer->cmd_class, buffer->cmd_select); + return 0; + } + dev_dbg(d, "missing capability %d for %u/%u\n", + call_whitelist[i].need_capability, + buffer->cmd_class, buffer->cmd_select); + + } + + /* not in a whitelist, only allow processes with capabilities */ + if (capable(CAP_SYS_RAWIO)) { + dev_dbg(d, "Allowing %u/%u due to CAP_SYS_RAWIO\n", + buffer->cmd_class, buffer->cmd_select); + return 0; + } + + return -EACCES; +} +EXPORT_SYMBOL_GPL(dell_smbios_call_filter); + int dell_smbios_call(struct calling_interface_buffer *buffer) { int (*call_fn)(struct calling_interface_buffer *) = NULL; @@ -168,6 +358,8 @@ static void __init parse_da_table(const struct dmi_header *dm) if (dm->length < 17) return; + da_supported_commands = table->supportedCmds; + new_da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) * sizeof(struct calling_interface_token), GFP_KERNEL); diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h index 07effdc7ae8b..91e8004d48ba 100644 --- a/drivers/platform/x86/dell-smbios.h +++ b/drivers/platform/x86/dell-smbios.h @@ -26,9 +26,14 @@ #define SELECT_TOKEN_AC 2 #define CLASS_KBD_BACKLIGHT 4 #define SELECT_KBD_BACKLIGHT 11 +#define CLASS_FLASH_INTERFACE 7 +#define SELECT_FLASH_INTERFACE 3 +#define CLASS_ADMIN_PROP 10 +#define SELECT_ADMIN_PROP 3 #define CLASS_INFO 17 #define SELECT_RFKILL 11 #define SELECT_APP_REGISTRATION 3 +#define SELECT_DOCK 22 /* Tokens used in kernel drivers, any of these * should be filtered from userspace access @@ -44,6 +49,10 @@ #define KBD_LED_AUTO_100_TOKEN 0x02F6 #define GLOBAL_MIC_MUTE_ENABLE 0x0364 #define GLOBAL_MIC_MUTE_DISABLE 0x0365 + +/* tokens whitelisted to userspace use */ +#define CAPSULE_EN_TOKEN 0x0461 +#define CAPSULE_DIS_TOKEN 0x0462 #define WSMT_EN_TOKEN 0x04EC #define WSMT_DIS_TOKEN 0x04ED @@ -80,6 +89,8 @@ int dell_smbios_register_device(struct device *d, void *call_fn); void dell_smbios_unregister_device(struct device *d); int dell_smbios_error(int value); +int dell_smbios_call_filter(struct device *d, + struct calling_interface_buffer *buffer); int dell_smbios_call(struct calling_interface_buffer *buffer); struct calling_interface_token *dell_smbios_find_token(int tokenid); -- GitLab From 44b6b7661132b1b0e5fd3147ded66f1e4a817ca9 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:35 -0500 Subject: [PATCH 1595/2898] platform/x86: wmi: create userspace interface for drivers For WMI operations that are only Set or Query readable and writable sysfs attributes created by WMI vendor drivers or the bus driver makes sense. For other WMI operations that are run on Method, there needs to be a way to guarantee to userspace that the results from the method call belong to the data request to the method call. Sysfs attributes don't work well in this scenario because two userspace processes may be competing at reading/writing an attribute and step on each other's data. When a WMI vendor driver declares a callback method in the wmi_driver the WMI bus driver will create a character device that maps to that function. This callback method will be responsible for filtering invalid requests and performing the actual call. That character device will correspond to this path: /dev/wmi/$driver Performing read() on this character device will provide the size of the buffer that the character device needs to perform calls. This buffer size can be set by vendor drivers through a new symbol or when MOF parsing is available by the MOF. Performing ioctl() on this character device will be interpretd by the WMI bus driver. It will perform sanity tests for size of data, test them for a valid instance, copy the data from userspace and pass iton to the vendor driver to further process and run. This creates an implicit policy that each driver will only be allowed a single character device. If a module matches multiple GUID's, the wmi_devices will need to be all handled by the same wmi_driver. The WMI vendor drivers will be responsible for managing inappropriate access to this character device and proper locking on data used by it. When a WMI vendor driver is unloaded the WMI bus driver will clean up the character device and any memory allocated for the call. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- MAINTAINERS | 1 + drivers/platform/x86/wmi.c | 189 ++++++++++++++++++++++++++++++++++++- include/linux/wmi.h | 5 + include/uapi/linux/wmi.h | 26 +++++ 4 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 include/uapi/linux/wmi.h diff --git a/MAINTAINERS b/MAINTAINERS index aede236d10f1..3af07502220a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -384,6 +384,7 @@ ACPI WMI DRIVER L: platform-driver-x86@vger.kernel.org S: Orphan F: drivers/platform/x86/wmi.c +F: include/uapi/linux/wmi.h AD1889 ALSA SOUND DRIVER M: Thibaut Varene diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index bcb41c1c7f52..8c31ed4f0e1b 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -38,12 +38,15 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#include ACPI_MODULE_NAME("wmi"); MODULE_AUTHOR("Carlos Corbacho"); @@ -69,9 +72,12 @@ struct wmi_block { struct wmi_device dev; struct list_head list; struct guid_block gblock; + struct miscdevice char_dev; + struct mutex char_mutex; struct acpi_device *acpi_device; wmi_notify_handler handler; void *handler_data; + u64 req_buf_size; bool read_takes_no_args; }; @@ -188,6 +194,25 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) /* * Exported WMI functions */ + +/** + * set_required_buffer_size - Sets the buffer size needed for performing IOCTL + * @wdev: A wmi bus device from a driver + * @instance: Instance index + * + * Allocates memory needed for buffer, stores the buffer size in that memory + */ +int set_required_buffer_size(struct wmi_device *wdev, u64 length) +{ + struct wmi_block *wblock; + + wblock = container_of(wdev, struct wmi_block, dev); + wblock->req_buf_size = length; + + return 0; +} +EXPORT_SYMBOL_GPL(set_required_buffer_size); + /** * wmi_evaluate_method - Evaluate a WMI method * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba @@ -764,6 +789,111 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver) return 0; } +static int wmi_char_open(struct inode *inode, struct file *filp) +{ + const char *driver_name = filp->f_path.dentry->d_iname; + struct wmi_block *wblock = NULL; + struct wmi_block *next = NULL; + + list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { + if (!wblock->dev.dev.driver) + continue; + if (strcmp(driver_name, wblock->dev.dev.driver->name) == 0) { + filp->private_data = wblock; + break; + } + } + + if (!filp->private_data) + return -ENODEV; + + return nonseekable_open(inode, filp); +} + +static ssize_t wmi_char_read(struct file *filp, char __user *buffer, + size_t length, loff_t *offset) +{ + struct wmi_block *wblock = filp->private_data; + + return simple_read_from_buffer(buffer, length, offset, + &wblock->req_buf_size, + sizeof(wblock->req_buf_size)); +} + +static long wmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct wmi_ioctl_buffer __user *input = + (struct wmi_ioctl_buffer __user *) arg; + struct wmi_block *wblock = filp->private_data; + struct wmi_ioctl_buffer *buf = NULL; + struct wmi_driver *wdriver = NULL; + int ret; + + if (_IOC_TYPE(cmd) != WMI_IOC) + return -ENOTTY; + + /* make sure we're not calling a higher instance than exists*/ + if (_IOC_NR(cmd) >= wblock->gblock.instance_count) + return -EINVAL; + + mutex_lock(&wblock->char_mutex); + buf = wblock->handler_data; + if (get_user(buf->length, &input->length)) { + dev_dbg(&wblock->dev.dev, "Read length from user failed\n"); + ret = -EFAULT; + goto out_ioctl; + } + /* if it's too small, abort */ + if (buf->length < wblock->req_buf_size) { + dev_err(&wblock->dev.dev, + "Buffer %lld too small, need at least %lld\n", + buf->length, wblock->req_buf_size); + ret = -EINVAL; + goto out_ioctl; + } + /* if it's too big, warn, driver will only use what is needed */ + if (buf->length > wblock->req_buf_size) + dev_warn(&wblock->dev.dev, + "Buffer %lld is bigger than required %lld\n", + buf->length, wblock->req_buf_size); + + /* copy the structure from userspace */ + if (copy_from_user(buf, input, wblock->req_buf_size)) { + dev_dbg(&wblock->dev.dev, "Copy %llu from user failed\n", + wblock->req_buf_size); + ret = -EFAULT; + goto out_ioctl; + } + + /* let the driver do any filtering and do the call */ + wdriver = container_of(wblock->dev.dev.driver, + struct wmi_driver, driver); + if (!try_module_get(wdriver->driver.owner)) + return -EBUSY; + ret = wdriver->filter_callback(&wblock->dev, cmd, buf); + module_put(wdriver->driver.owner); + if (ret) + goto out_ioctl; + + /* return the result (only up to our internal buffer size) */ + if (copy_to_user(input, buf, wblock->req_buf_size)) { + dev_dbg(&wblock->dev.dev, "Copy %llu to user failed\n", + wblock->req_buf_size); + ret = -EFAULT; + } + +out_ioctl: + mutex_unlock(&wblock->char_mutex); + return ret; +} + +static const struct file_operations wmi_fops = { + .owner = THIS_MODULE, + .read = wmi_char_read, + .open = wmi_char_open, + .unlocked_ioctl = wmi_ioctl, + .compat_ioctl = wmi_ioctl, +}; static int wmi_dev_probe(struct device *dev) { @@ -771,16 +901,63 @@ static int wmi_dev_probe(struct device *dev) struct wmi_driver *wdriver = container_of(dev->driver, struct wmi_driver, driver); int ret = 0; + int count; + char *buf; if (ACPI_FAILURE(wmi_method_enable(wblock, 1))) dev_warn(dev, "failed to enable device -- probing anyway\n"); if (wdriver->probe) { ret = wdriver->probe(dev_to_wdev(dev)); - if (ret != 0 && ACPI_FAILURE(wmi_method_enable(wblock, 0))) - dev_warn(dev, "failed to disable device\n"); + if (ret != 0) + goto probe_failure; } + /* driver wants a character device made */ + if (wdriver->filter_callback) { + /* check that required buffer size declared by driver or MOF */ + if (!wblock->req_buf_size) { + dev_err(&wblock->dev.dev, + "Required buffer size not set\n"); + ret = -EINVAL; + goto probe_failure; + } + + count = get_order(wblock->req_buf_size); + wblock->handler_data = (void *)__get_free_pages(GFP_KERNEL, + count); + if (!wblock->handler_data) { + ret = -ENOMEM; + goto probe_failure; + } + + buf = kmalloc(strlen(wdriver->driver.name) + 4, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto probe_string_failure; + } + sprintf(buf, "wmi/%s", wdriver->driver.name); + wblock->char_dev.minor = MISC_DYNAMIC_MINOR; + wblock->char_dev.name = buf; + wblock->char_dev.fops = &wmi_fops; + wblock->char_dev.mode = 0444; + ret = misc_register(&wblock->char_dev); + if (ret) { + dev_warn(dev, "failed to register char dev: %d", ret); + ret = -ENOMEM; + goto probe_misc_failure; + } + } + + return 0; + +probe_misc_failure: + kfree(buf); +probe_string_failure: + kfree(wblock->handler_data); +probe_failure: + if (ACPI_FAILURE(wmi_method_enable(wblock, 0))) + dev_warn(dev, "failed to disable device\n"); return ret; } @@ -791,6 +968,13 @@ static int wmi_dev_remove(struct device *dev) container_of(dev->driver, struct wmi_driver, driver); int ret = 0; + if (wdriver->filter_callback) { + misc_deregister(&wblock->char_dev); + kfree(wblock->char_dev.name); + free_pages((unsigned long)wblock->handler_data, + get_order(wblock->req_buf_size)); + } + if (wdriver->remove) ret = wdriver->remove(dev_to_wdev(dev)); @@ -847,6 +1031,7 @@ static int wmi_create_device(struct device *wmi_bus_dev, if (gblock->flags & ACPI_WMI_METHOD) { wblock->dev.dev.type = &wmi_type_method; + mutex_init(&wblock->char_mutex); goto out_init; } diff --git a/include/linux/wmi.h b/include/linux/wmi.h index ddee427e0721..4757cb5077e5 100644 --- a/include/linux/wmi.h +++ b/include/linux/wmi.h @@ -18,6 +18,7 @@ #include #include +#include struct wmi_device { struct device dev; @@ -36,6 +37,8 @@ extern acpi_status wmidev_evaluate_method(struct wmi_device *wdev, extern union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance); +extern int set_required_buffer_size(struct wmi_device *wdev, u64 length); + struct wmi_device_id { const char *guid_string; }; @@ -47,6 +50,8 @@ struct wmi_driver { int (*probe)(struct wmi_device *wdev); int (*remove)(struct wmi_device *wdev); void (*notify)(struct wmi_device *device, union acpi_object *data); + long (*filter_callback)(struct wmi_device *wdev, unsigned int cmd, + struct wmi_ioctl_buffer *arg); }; extern int __must_check __wmi_driver_register(struct wmi_driver *driver, diff --git a/include/uapi/linux/wmi.h b/include/uapi/linux/wmi.h new file mode 100644 index 000000000000..7e52350ac9b3 --- /dev/null +++ b/include/uapi/linux/wmi.h @@ -0,0 +1,26 @@ +/* + * User API methods for ACPI-WMI mapping driver + * + * Copyright (C) 2017 Dell, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _UAPI_LINUX_WMI_H +#define _UAPI_LINUX_WMI_H + +#include + +/* WMI bus will filter all WMI vendor driver requests through this IOC */ +#define WMI_IOC 'W' + +/* All ioctl requests through WMI should declare their size followed by + * relevant data objects + */ +struct wmi_ioctl_buffer { + __u64 length; + __u8 data[]; +}; + +#endif -- GitLab From f2645fa317b8905b8934f06a0601d5b7fa66aba0 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:36 -0500 Subject: [PATCH 1596/2898] platform/x86: dell-smbios-wmi: introduce userspace interface It's important for the driver to provide a R/W ioctl to ensure that two competing userspace processes don't race to provide or read each others data. This userspace character device will be used to perform SMBIOS calls from any applications. It provides an ioctl that will allow passing the WMI calling interface buffer between userspace and kernel space. This character device is intended to deprecate the dcdbas kernel module and the interface that it provides to userspace. To perform an SMBIOS IOCTL call using the character device userspace will perform a read() on the the character device. The WMI bus will provide a u64 variable containing the necessary size of the IOCTL buffer. The API for interacting with this interface is defined in documentation as well as the WMI uapi header provides the format of the structures. Not all userspace requests will be accepted. The dell-smbios filtering functionality will be used to prevent access to certain tokens and calls. All whitelisted commands and tokens are now shared out to userspace so applications don't need to define them in their own headers. Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- Documentation/ABI/testing/dell-smbios-wmi | 41 +++++++++++++++++ drivers/platform/x86/dell-smbios-wmi.c | 54 ++++++++++++++++++----- drivers/platform/x86/dell-smbios.h | 32 +------------- include/uapi/linux/wmi.h | 47 ++++++++++++++++++++ 4 files changed, 133 insertions(+), 41 deletions(-) create mode 100644 Documentation/ABI/testing/dell-smbios-wmi diff --git a/Documentation/ABI/testing/dell-smbios-wmi b/Documentation/ABI/testing/dell-smbios-wmi new file mode 100644 index 000000000000..fc919ce16008 --- /dev/null +++ b/Documentation/ABI/testing/dell-smbios-wmi @@ -0,0 +1,41 @@ +What: /dev/wmi/dell-smbios +Date: November 2017 +KernelVersion: 4.15 +Contact: "Mario Limonciello" +Description: + Perform SMBIOS calls on supported Dell machines. + through the Dell ACPI-WMI interface. + + IOCTL's and buffer formats are defined in: + + + 1) To perform an SMBIOS call from userspace, you'll need to + first determine the minimum size of the calling interface + buffer for your machine. + Platforms that contain larger buffers can return larger + objects from the system firmware. + Commonly this size is either 4k or 32k. + + To determine the size of the buffer read() a u64 dword from + the WMI character device /dev/wmi/dell-smbios. + + 2) After you've determined the minimum size of the calling + interface buffer, you can allocate a structure that represents + the structure documented above. + + 3) In the 'length' object store the size of the buffer you + determined above and allocated. + + 4) In this buffer object, prepare as necessary for the SMBIOS + call you're interested in. Typically SMBIOS buffers have + "class", "select", and "input" defined to values that coincide + with the data you are interested in. + Documenting class/select/input values is outside of the scope + of this documentation. Check with the libsmbios project for + further documentation on these values. + + 6) Run the call by using ioctl() as described in the header. + + 7) The output will be returned in the buffer object. + + 8) Be sure to free up your allocated object. diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c index b31f457e58c3..35c13815b24c 100644 --- a/drivers/platform/x86/dell-smbios-wmi.c +++ b/drivers/platform/x86/dell-smbios-wmi.c @@ -30,17 +30,6 @@ struct misc_bios_flags_structure { #define DELL_WMI_SMBIOS_GUID "A80593CE-A997-11DA-B012-B622A1EF5492" -struct dell_wmi_extensions { - __u32 argattrib; - __u32 blength; - __u8 data[]; -} __packed; - -struct dell_wmi_smbios_buffer { - struct calling_interface_buffer std; - struct dell_wmi_extensions ext; -} __packed; - struct wmi_smbios_priv { struct dell_wmi_smbios_buffer *buf; struct list_head list; @@ -117,6 +106,42 @@ int dell_smbios_wmi_call(struct calling_interface_buffer *buffer) return ret; } +static long dell_smbios_wmi_filter(struct wmi_device *wdev, unsigned int cmd, + struct wmi_ioctl_buffer *arg) +{ + struct wmi_smbios_priv *priv; + int ret = 0; + + switch (cmd) { + case DELL_WMI_SMBIOS_CMD: + mutex_lock(&call_mutex); + priv = dev_get_drvdata(&wdev->dev); + if (!priv) { + ret = -ENODEV; + goto fail_smbios_cmd; + } + memcpy(priv->buf, arg, priv->req_buf_size); + if (dell_smbios_call_filter(&wdev->dev, &priv->buf->std)) { + dev_err(&wdev->dev, "Invalid call %d/%d:%8x\n", + priv->buf->std.cmd_class, + priv->buf->std.cmd_select, + priv->buf->std.input[0]); + ret = -EFAULT; + goto fail_smbios_cmd; + } + ret = run_smbios_call(priv->wdev); + if (ret) + goto fail_smbios_cmd; + memcpy(arg, priv->buf, priv->req_buf_size); +fail_smbios_cmd: + mutex_unlock(&call_mutex); + break; + default: + ret = -ENOIOCTLCMD; + } + return ret; +} + static int dell_smbios_wmi_probe(struct wmi_device *wdev) { struct wmi_smbios_priv *priv; @@ -135,6 +160,12 @@ static int dell_smbios_wmi_probe(struct wmi_device *wdev) if (!dell_wmi_get_size(&priv->req_buf_size)) return -EPROBE_DEFER; + /* add in the length object we will use internally with ioctl */ + priv->req_buf_size += sizeof(u64); + ret = set_required_buffer_size(wdev, priv->req_buf_size); + if (ret) + return ret; + count = get_order(priv->req_buf_size); priv->buf = (void *)__get_free_pages(GFP_KERNEL, count); if (!priv->buf) @@ -210,6 +241,7 @@ static struct wmi_driver dell_smbios_wmi_driver = { .probe = dell_smbios_wmi_probe, .remove = dell_smbios_wmi_remove, .id_table = dell_smbios_wmi_id_table, + .filter_callback = dell_smbios_wmi_filter, }; static int __init init_dell_smbios_wmi(void) diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h index 91e8004d48ba..138d478d9adc 100644 --- a/drivers/platform/x86/dell-smbios.h +++ b/drivers/platform/x86/dell-smbios.h @@ -17,23 +17,11 @@ #define _DELL_SMBIOS_H_ #include +#include -/* Classes and selects used in kernel drivers */ -#define CLASS_TOKEN_READ 0 -#define CLASS_TOKEN_WRITE 1 -#define SELECT_TOKEN_STD 0 -#define SELECT_TOKEN_BAT 1 -#define SELECT_TOKEN_AC 2 +/* Classes and selects used only in kernel drivers */ #define CLASS_KBD_BACKLIGHT 4 #define SELECT_KBD_BACKLIGHT 11 -#define CLASS_FLASH_INTERFACE 7 -#define SELECT_FLASH_INTERFACE 3 -#define CLASS_ADMIN_PROP 10 -#define SELECT_ADMIN_PROP 3 -#define CLASS_INFO 17 -#define SELECT_RFKILL 11 -#define SELECT_APP_REGISTRATION 3 -#define SELECT_DOCK 22 /* Tokens used in kernel drivers, any of these * should be filtered from userspace access @@ -50,24 +38,8 @@ #define GLOBAL_MIC_MUTE_ENABLE 0x0364 #define GLOBAL_MIC_MUTE_DISABLE 0x0365 -/* tokens whitelisted to userspace use */ -#define CAPSULE_EN_TOKEN 0x0461 -#define CAPSULE_DIS_TOKEN 0x0462 -#define WSMT_EN_TOKEN 0x04EC -#define WSMT_DIS_TOKEN 0x04ED - struct notifier_block; -/* This structure will be modified by the firmware when we enter - * system management mode, hence the volatiles */ - -struct calling_interface_buffer { - u16 cmd_class; - u16 cmd_select; - volatile u32 input[4]; - volatile u32 output[4]; -} __packed; - struct calling_interface_token { u16 tokenID; u16 location; diff --git a/include/uapi/linux/wmi.h b/include/uapi/linux/wmi.h index 7e52350ac9b3..7a92e9e3d1c0 100644 --- a/include/uapi/linux/wmi.h +++ b/include/uapi/linux/wmi.h @@ -10,6 +10,7 @@ #ifndef _UAPI_LINUX_WMI_H #define _UAPI_LINUX_WMI_H +#include #include /* WMI bus will filter all WMI vendor driver requests through this IOC */ @@ -23,4 +24,50 @@ struct wmi_ioctl_buffer { __u8 data[]; }; +/* This structure may be modified by the firmware when we enter + * system management mode through SMM, hence the volatiles + */ +struct calling_interface_buffer { + __u16 cmd_class; + __u16 cmd_select; + volatile __u32 input[4]; + volatile __u32 output[4]; +} __packed; + +struct dell_wmi_extensions { + __u32 argattrib; + __u32 blength; + __u8 data[]; +} __packed; + +struct dell_wmi_smbios_buffer { + __u64 length; + struct calling_interface_buffer std; + struct dell_wmi_extensions ext; +} __packed; + +/* Whitelisted smbios class/select commands */ +#define CLASS_TOKEN_READ 0 +#define CLASS_TOKEN_WRITE 1 +#define SELECT_TOKEN_STD 0 +#define SELECT_TOKEN_BAT 1 +#define SELECT_TOKEN_AC 2 +#define CLASS_FLASH_INTERFACE 7 +#define SELECT_FLASH_INTERFACE 3 +#define CLASS_ADMIN_PROP 10 +#define SELECT_ADMIN_PROP 3 +#define CLASS_INFO 17 +#define SELECT_RFKILL 11 +#define SELECT_APP_REGISTRATION 3 +#define SELECT_DOCK 22 + +/* whitelisted tokens */ +#define CAPSULE_EN_TOKEN 0x0461 +#define CAPSULE_DIS_TOKEN 0x0462 +#define WSMT_EN_TOKEN 0x04EC +#define WSMT_DIS_TOKEN 0x04ED + +/* Dell SMBIOS calling IOCTL command used by dell-smbios-wmi */ +#define DELL_WMI_SMBIOS_CMD _IOWR(WMI_IOC, 0, struct dell_wmi_smbios_buffer) + #endif -- GitLab From 9d64fc08f6fe59a7d71e84f650dd2c0f080254dd Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 1 Nov 2017 14:25:37 -0500 Subject: [PATCH 1597/2898] tools/wmi: add a sample for dell smbios communication over WMI This application uses the character device /dev/wmi/dell-smbios to perform SMBIOS communications from userspace. It offers demonstrations of a few simple tasks: - Running a class/select command - Querying a token value - Activating a token Signed-off-by: Mario Limonciello Reviewed-by: Edward O'Callaghan Signed-off-by: Darren Hart (VMware) --- MAINTAINERS | 1 + tools/Makefile | 14 ++- tools/wmi/Makefile | 18 +++ tools/wmi/dell-smbios-example.c | 210 ++++++++++++++++++++++++++++++++ 4 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 tools/wmi/Makefile create mode 100644 tools/wmi/dell-smbios-example.c diff --git a/MAINTAINERS b/MAINTAINERS index 3af07502220a..da1851fc88a5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3997,6 +3997,7 @@ M: Mario Limonciello L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/dell-smbios-wmi.c +F: tools/wmi/dell-smbios-example.c DELL LAPTOP DRIVER M: Matthew Garrett diff --git a/tools/Makefile b/tools/Makefile index 9dfede37c8ff..9d2fd2606810 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -29,6 +29,7 @@ help: @echo ' usb - USB testing tools' @echo ' virtio - vhost test module' @echo ' vm - misc vm tools' + @echo ' wmi - WMI interface examples' @echo ' x86_energy_perf_policy - Intel energy policy tool' @echo '' @echo 'You can do:' @@ -57,7 +58,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest spi usb virtio vm net iio gpio objtool leds: FORCE +cgroup firewire hv guest spi usb virtio vm net iio gpio objtool leds wmi: FORCE $(call descend,$@) liblockdep: FORCE @@ -92,7 +93,7 @@ kvm_stat: FORCE all: acpi cgroup cpupower gpio hv firewire liblockdep \ perf selftests spi turbostat usb \ virtio vm net x86_energy_perf_policy \ - tmon freefall iio objtool kvm_stat + tmon freefall iio objtool kvm_stat wmi acpi_install: $(call descend,power/$(@:_install=),install) @@ -100,7 +101,7 @@ acpi_install: cpupower_install: $(call descend,power/$(@:_install=),install) -cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install net_install objtool_install: +cgroup_install firewire_install gpio_install hv_install iio_install perf_install spi_install usb_install virtio_install vm_install net_install objtool_install wmi_install: $(call descend,$(@:_install=),install) liblockdep_install: @@ -125,7 +126,8 @@ install: acpi_install cgroup_install cpupower_install gpio_install \ hv_install firewire_install iio_install liblockdep_install \ perf_install selftests_install turbostat_install usb_install \ virtio_install vm_install net_install x86_energy_perf_policy_install \ - tmon_install freefall_install objtool_install kvm_stat_install + tmon_install freefall_install objtool_install kvm_stat_install \ + wmi_install acpi_clean: $(call descend,power/acpi,clean) @@ -133,7 +135,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean objtool_clean leds_clean: +cgroup_clean hv_clean firewire_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean net_clean iio_clean gpio_clean objtool_clean leds_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean: @@ -171,6 +173,6 @@ clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \ perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ - gpio_clean objtool_clean leds_clean + gpio_clean objtool_clean leds_clean wmi_clean .PHONY: FORCE diff --git a/tools/wmi/Makefile b/tools/wmi/Makefile new file mode 100644 index 000000000000..e664f1167388 --- /dev/null +++ b/tools/wmi/Makefile @@ -0,0 +1,18 @@ +PREFIX ?= /usr +SBINDIR ?= sbin +INSTALL ?= install +CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include +CC = $(CROSS_COMPILE)gcc + +TARGET = dell-smbios-example + +all: $(TARGET) + +%: %.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +clean: + $(RM) $(TARGET) + +install: dell-smbios-example + $(INSTALL) -D -m 755 $(TARGET) $(DESTDIR)$(PREFIX)/$(SBINDIR)/$(TARGET) diff --git a/tools/wmi/dell-smbios-example.c b/tools/wmi/dell-smbios-example.c new file mode 100644 index 000000000000..9d3bde081249 --- /dev/null +++ b/tools/wmi/dell-smbios-example.c @@ -0,0 +1,210 @@ +/* + * Sample application for SMBIOS communication over WMI interface + * Performs the following: + * - Simple cmd_class/cmd_select lookup for TPM information + * - Simple query of known tokens and their values + * - Simple activation of a token + * + * Copyright (C) 2017 Dell, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +/* if uapi header isn't installed, this might not yet exist */ +#ifndef __packed +#define __packed __attribute__((packed)) +#endif +#include + +/* It would be better to discover these using udev, but for a simple + * application they're hardcoded + */ +static const char *ioctl_devfs = "/dev/wmi/dell-smbios"; +static const char *token_sysfs = + "/sys/bus/platform/devices/dell-smbios.0/tokens"; + +static void show_buffer(struct dell_wmi_smbios_buffer *buffer) +{ + printf("Call: %x/%x [%x,%x,%x,%x]\nResults: [%8x,%8x,%8x,%8x]\n", + buffer->std.cmd_class, buffer->std.cmd_select, + buffer->std.input[0], buffer->std.input[1], + buffer->std.input[2], buffer->std.input[3], + buffer->std.output[0], buffer->std.output[1], + buffer->std.output[2], buffer->std.output[3]); +} + +static int run_wmi_smbios_cmd(struct dell_wmi_smbios_buffer *buffer) +{ + int fd; + int ret; + + fd = open(ioctl_devfs, O_NONBLOCK); + ret = ioctl(fd, DELL_WMI_SMBIOS_CMD, buffer); + close(fd); + return ret; +} + +static int find_token(__u16 token, __u16 *location, __u16 *value) +{ + char location_sysfs[60]; + char value_sysfs[57]; + char buf[4096]; + FILE *f; + int ret; + + ret = sprintf(value_sysfs, "%s/%04x_value", token_sysfs, token); + if (ret < 0) { + printf("sprintf value failed\n"); + return 2; + } + f = fopen(value_sysfs, "rb"); + if (!f) { + printf("failed to open %s\n", value_sysfs); + return 2; + } + fread(buf, 1, 4096, f); + fclose(f); + *value = (__u16) strtol(buf, NULL, 16); + + ret = sprintf(location_sysfs, "%s/%04x_location", token_sysfs, token); + if (ret < 0) { + printf("sprintf location failed\n"); + return 1; + } + f = fopen(location_sysfs, "rb"); + if (!f) { + printf("failed to open %s\n", location_sysfs); + return 2; + } + fread(buf, 1, 4096, f); + fclose(f); + *location = (__u16) strtol(buf, NULL, 16); + + if (*location) + return 0; + return 2; +} + +static int token_is_active(__u16 *location, __u16 *cmpvalue, + struct dell_wmi_smbios_buffer *buffer) +{ + int ret; + + buffer->std.cmd_class = CLASS_TOKEN_READ; + buffer->std.cmd_select = SELECT_TOKEN_STD; + buffer->std.input[0] = *location; + ret = run_wmi_smbios_cmd(buffer); + if (ret != 0 || buffer->std.output[0] != 0) + return ret; + ret = (buffer->std.output[1] == *cmpvalue); + return ret; +} + +static int query_token(__u16 token, struct dell_wmi_smbios_buffer *buffer) +{ + __u16 location; + __u16 value; + int ret; + + ret = find_token(token, &location, &value); + if (ret != 0) { + printf("unable to find token %04x\n", token); + return 1; + } + return token_is_active(&location, &value, buffer); +} + +static int activate_token(struct dell_wmi_smbios_buffer *buffer, + __u16 token) +{ + __u16 location; + __u16 value; + int ret; + + ret = find_token(token, &location, &value); + if (ret != 0) { + printf("unable to find token %04x\n", token); + return 1; + } + buffer->std.cmd_class = CLASS_TOKEN_WRITE; + buffer->std.cmd_select = SELECT_TOKEN_STD; + buffer->std.input[0] = location; + buffer->std.input[1] = 1; + ret = run_wmi_smbios_cmd(buffer); + return ret; +} + +static int query_buffer_size(__u64 *buffer_size) +{ + FILE *f; + + f = fopen(ioctl_devfs, "rb"); + if (!f) + return -EINVAL; + fread(buffer_size, sizeof(__u64), 1, f); + fclose(f); + return EXIT_SUCCESS; +} + +int main(void) +{ + struct dell_wmi_smbios_buffer *buffer; + int ret; + __u64 value = 0; + + ret = query_buffer_size(&value); + if (ret == EXIT_FAILURE || !value) { + printf("Unable to read buffer size\n"); + goto out; + } + printf("Detected required buffer size %lld\n", value); + + buffer = malloc(value); + if (buffer == NULL) { + printf("failed to alloc memory for ioctl\n"); + ret = -ENOMEM; + goto out; + } + buffer->length = value; + + /* simple SMBIOS call for looking up TPM info */ + buffer->std.cmd_class = CLASS_FLASH_INTERFACE; + buffer->std.cmd_select = SELECT_FLASH_INTERFACE; + buffer->std.input[0] = 2; + ret = run_wmi_smbios_cmd(buffer); + if (ret) { + printf("smbios ioctl failed: %d\n", ret); + ret = EXIT_FAILURE; + goto out; + } + show_buffer(buffer); + + /* query some tokens */ + ret = query_token(CAPSULE_EN_TOKEN, buffer); + printf("UEFI Capsule enabled token is: %d\n", ret); + ret = query_token(CAPSULE_DIS_TOKEN, buffer); + printf("UEFI Capsule disabled token is: %d\n", ret); + + /* activate UEFI capsule token if disabled */ + if (ret) { + printf("Enabling UEFI capsule token"); + if (activate_token(buffer, CAPSULE_EN_TOKEN)) { + printf("activate failed\n"); + ret = -1; + goto out; + } + } + ret = EXIT_SUCCESS; +out: + free(buffer); + return ret; +} -- GitLab From 594e25e73440863981032d76c9b1e33409ceff6e Mon Sep 17 00:00:00 2001 From: Jiang Yi Date: Fri, 11 Aug 2017 11:29:44 +0800 Subject: [PATCH 1598/2898] target/file: Do not return error for UNMAP if length is zero The function fd_execute_unmap() in target_core_file.c calles ret = file->f_op->fallocate(file, mode, pos, len); Some filesystems implement fallocate() to return error if length is zero (e.g. btrfs) but according to SCSI Block Commands spec UNMAP should return success for zero length. Signed-off-by: Jiang Yi Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index c629817a8854..9b2c0c773022 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -482,6 +482,10 @@ fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb) struct inode *inode = file->f_mapping->host; int ret; + if (!nolb) { + return 0; + } + if (cmd->se_dev->dev_attrib.pi_prot_type) { ret = fd_do_prot_unmap(cmd, lba, nolb); if (ret) -- GitLab From 88fb2fa7db7510bf1078226ab48d162d9854f3d4 Mon Sep 17 00:00:00 2001 From: tangwenji Date: Wed, 16 Aug 2017 16:39:00 +0800 Subject: [PATCH 1599/2898] target: fix null pointer regression in core_tmr_drain_tmr_list The target system kernel crash when the initiator executes the sg_persist -A command,because of the second argument to be set to NULL when core_tmr_lun_reset is called in core_scsi3_pro_preempt function. This fixes a regression originally introduced by: commit 51ec502a32665fed66c7f03799ede4023b212536 Author: Bart Van Assche Date: Tue Feb 14 16:25:54 2017 -0800 target: Delete tmr from list before processing Signed-off-by: tangwenji Cc: stable@vger.kernel.org # 4.11+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index e22847bd79b9..61909b23e959 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -217,7 +217,8 @@ static void core_tmr_drain_tmr_list( * LUN_RESET tmr.. */ spin_lock_irqsave(&dev->se_tmr_lock, flags); - list_del_init(&tmr->tmr_list); + if (tmr) + list_del_init(&tmr->tmr_list); list_for_each_entry_safe(tmr_p, tmr_pp, &dev->dev_tmr_list, tmr_list) { cmd = tmr_p->task_cmd; if (!cmd) { -- GitLab From c58a252beb04cf0e02d6a746b2ed7ea89b6deb71 Mon Sep 17 00:00:00 2001 From: tangwenji Date: Thu, 17 Aug 2017 19:51:54 +0800 Subject: [PATCH 1600/2898] target: fix buffer offset in core_scsi3_pri_read_full_status When at least two initiators register pr on the same LUN, the target returns the exception data due to buffer offset error, therefore the initiator executes command 'sg_persist -s' may cause the initiator to appear segfault error. This fixes a regression originally introduced by: commit a85d667e58bddf73be84d1981b41eaac985ed216 Author: Bart Van Assche Date: Tue May 23 16:48:27 2017 -0700 target: Use {get,put}_unaligned_be*() instead of open coding these functions Signed-off-by: tangwenji Cc: stable@vger.kernel.org # 4.13+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index dd2cd8048582..9f25c9c6f67d 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -4011,6 +4011,7 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) * Set the ADDITIONAL DESCRIPTOR LENGTH */ put_unaligned_be32(desc_len, &buf[off]); + off += 4; /* * Size of full desctipor header minus TransportID * containing $FABRIC_MOD specific) initiator device/port -- GitLab From e437fa3e5d1fde522fcc345ab1fe32a671b943f0 Mon Sep 17 00:00:00 2001 From: tangwenji Date: Mon, 21 Aug 2017 20:17:18 +0800 Subject: [PATCH 1601/2898] target: fix double unmap data sg in core_scsi3_emulate_pro_register_and_move() Signed-off-by: tangwenji Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 9f25c9c6f67d..dbf572e0667b 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3528,8 +3528,6 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, core_scsi3_update_and_write_aptpl(cmd->se_dev, aptpl); - transport_kunmap_data_sg(cmd); - core_scsi3_put_pr_reg(dest_pr_reg); return 0; out: -- GitLab From 79dd6f2fd170e19f979d31cd1ebc9eea6de1a75f Mon Sep 17 00:00:00 2001 From: tangwenji Date: Mon, 21 Aug 2017 20:55:41 +0800 Subject: [PATCH 1602/2898] target: add sense code INSUFFICIENT REGISTRATION RESOURCES If a PERSISTENT RESERVE OUT command with a REGISTER service action or a REGISTER AND IGNORE EXISTING KEY service action or REGISTER AND MOVE service action is attempted, but there are insufficient device server resources to complete the operation, then the command shall be terminated with CHECK CONDITION status, with the sense key set to ILLEGAL REQUEST,and the additonal sense code set to INSUFFICIENT REGISTRATION RESOURCES. Signed-off-by: tangwenji Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 16 ++++++++-------- drivers/target/target_core_transport.c | 15 +++++++++++++++ include/target/target_core_base.h | 1 + 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index dbf572e0667b..871ae21870be 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1521,7 +1521,7 @@ core_scsi3_decode_spec_i_port( tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); if (!tidh_new) { pr_err("Unable to allocate tidh_new\n"); - return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return TCM_INSUFFICIENT_REGISTRATION_RESOURCES; } INIT_LIST_HEAD(&tidh_new->dest_list); tidh_new->dest_tpg = tpg; @@ -1533,7 +1533,7 @@ core_scsi3_decode_spec_i_port( sa_res_key, all_tg_pt, aptpl); if (!local_pr_reg) { kfree(tidh_new); - return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return TCM_INSUFFICIENT_REGISTRATION_RESOURCES; } tidh_new->dest_pr_reg = local_pr_reg; /* @@ -1553,7 +1553,7 @@ core_scsi3_decode_spec_i_port( buf = transport_kmap_data_sg(cmd); if (!buf) { - ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = TCM_INSUFFICIENT_REGISTRATION_RESOURCES; goto out; } @@ -1767,7 +1767,7 @@ core_scsi3_decode_spec_i_port( core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_tpg_undepend_item(dest_tpg); kfree(tidh_new); - ret = TCM_INVALID_PARAMETER_LIST; + ret = TCM_INSUFFICIENT_REGISTRATION_RESOURCES; goto out_unmap; } tidh_new->dest_pr_reg = dest_pr_reg; @@ -2103,7 +2103,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, register_type, 0)) { pr_err("Unable to allocate" " struct t10_pr_registration\n"); - return TCM_INVALID_PARAMETER_LIST; + return TCM_INSUFFICIENT_REGISTRATION_RESOURCES; } } else { /* @@ -3215,7 +3215,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, */ buf = transport_kmap_data_sg(cmd); if (!buf) { - ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = TCM_INSUFFICIENT_REGISTRATION_RESOURCES; goto out_put_pr_reg; } @@ -3267,7 +3267,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, buf = transport_kmap_data_sg(cmd); if (!buf) { - ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + ret = TCM_INSUFFICIENT_REGISTRATION_RESOURCES; goto out_put_pr_reg; } proto_ident = (buf[24] & 0x0f); @@ -3466,7 +3466,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, if (core_scsi3_alloc_registration(cmd->se_dev, dest_node_acl, dest_lun, dest_se_deve, dest_se_deve->mapped_lun, iport_ptr, sa_res_key, 0, aptpl, 2, 1)) { - ret = TCM_INVALID_PARAMETER_LIST; + ret = TCM_INSUFFICIENT_REGISTRATION_RESOURCES; goto out; } spin_lock(&dev->dev_reservation_lock); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 836d552b0385..190f3ba23707 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3145,6 +3145,21 @@ static const struct sense_info sense_info_table[] = { .key = NOT_READY, .asc = 0x08, /* LOGICAL UNIT COMMUNICATION FAILURE */ }, + [TCM_INSUFFICIENT_REGISTRATION_RESOURCES] = { + /* + * From spc4r22 section5.7.7,5.7.8 + * If a PERSISTENT RESERVE OUT command with a REGISTER service action + * or a REGISTER AND IGNORE EXISTING KEY service action or + * REGISTER AND MOVE service actionis attempted, + * but there are insufficient device server resources to complete the + * operation, then the command shall be terminated with CHECK CONDITION + * status, with the sense key set to ILLEGAL REQUEST,and the additonal + * sense code set to INSUFFICIENT REGISTRATION RESOURCES. + */ + .key = ILLEGAL_REQUEST, + .asc = 0x55, + .ascq = 0x04, /* INSUFFICIENT REGISTRATION RESOURCES */ + }, }; static int translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason) diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 516764febeb7..d3139a95ea77 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -181,6 +181,7 @@ enum tcm_sense_reason_table { TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE = R(0x1a), TCM_TOO_MANY_SEGMENT_DESCS = R(0x1b), TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE = R(0x1c), + TCM_INSUFFICIENT_REGISTRATION_RESOURCES = R(0x1d), #undef R }; -- GitLab From a2db857bf9ec62e91a6120a16436251be8e1c5ca Mon Sep 17 00:00:00 2001 From: tangwenji Date: Tue, 22 Aug 2017 20:29:50 +0800 Subject: [PATCH 1603/2898] target: fix match_token option in target_core_configfs.c The match_token function does not recognize the option 'l', so that both the mapped_lun and target_lun parameters can not be resolved correctly. And parsed u64-type parameters should use match_u64(). (Use %u instead of %s for Opt_mapped_lun + Opt_target_lun - nab) Signed-off-by: tangwenji Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 7e87d952bb7a..3790df42ade4 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -1611,12 +1611,12 @@ static match_table_t tokens = { {Opt_res_type, "res_type=%d"}, {Opt_res_scope, "res_scope=%d"}, {Opt_res_all_tg_pt, "res_all_tg_pt=%d"}, - {Opt_mapped_lun, "mapped_lun=%lld"}, + {Opt_mapped_lun, "mapped_lun=%u"}, {Opt_target_fabric, "target_fabric=%s"}, {Opt_target_node, "target_node=%s"}, {Opt_tpgt, "tpgt=%d"}, {Opt_port_rtpi, "port_rtpi=%d"}, - {Opt_target_lun, "target_lun=%lld"}, + {Opt_target_lun, "target_lun=%u"}, {Opt_err, NULL} }; @@ -1693,7 +1693,7 @@ static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item, } break; case Opt_sa_res_key: - ret = kstrtoull(args->from, 0, &tmp_ll); + ret = match_u64(args, &tmp_ll); if (ret < 0) { pr_err("kstrtoull() failed for sa_res_key=\n"); goto out; @@ -1727,10 +1727,10 @@ static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item, all_tg_pt = (int)arg; break; case Opt_mapped_lun: - ret = match_int(args, &arg); + ret = match_u64(args, &tmp_ll); if (ret) goto out; - mapped_lun = (u64)arg; + mapped_lun = (u64)tmp_ll; break; /* * PR APTPL Metadata for Target Port @@ -1768,10 +1768,10 @@ static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item, goto out; break; case Opt_target_lun: - ret = match_int(args, &arg); + ret = match_u64(args, &tmp_ll); if (ret) goto out; - target_lun = (u64)arg; + target_lun = (u64)tmp_ll; break; default: break; -- GitLab From 24528f089d0a444070aa4f715ace537e8d6bf168 Mon Sep 17 00:00:00 2001 From: tangwenji Date: Thu, 24 Aug 2017 19:59:37 +0800 Subject: [PATCH 1604/2898] target:fix condition return in core_pr_dump_initiator_port() When is pr_reg->isid_present_at_reg is false,this function should return. This fixes a regression originally introduced by: commit d2843c173ee53cf4c12e7dfedc069a5bc76f0ac5 Author: Andy Grover Date: Thu May 16 10:40:55 2013 -0700 target: Alter core_pr_dump_initiator_port for ease of use Signed-off-by: tangwenji Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 871ae21870be..a54490709811 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -58,8 +58,10 @@ void core_pr_dump_initiator_port( char *buf, u32 size) { - if (!pr_reg->isid_present_at_reg) + if (!pr_reg->isid_present_at_reg) { buf[0] = '\0'; + return; + } snprintf(buf, size, ",i,0x%s", pr_reg->pr_reg_isid); } -- GitLab From 12d5a43b2dffb6cd28062b4e19024f7982393288 Mon Sep 17 00:00:00 2001 From: tangwenji Date: Fri, 15 Sep 2017 16:03:13 +0800 Subject: [PATCH 1605/2898] iscsi-target: fix memory leak in lio_target_tiqn_addtpg() tpg must free when call core_tpg_register() return fail Signed-off-by: tangwenji Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 0dd4c45f7575..0ebc4818e132 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1123,7 +1123,7 @@ static struct se_portal_group *lio_target_tiqn_addtpg( ret = core_tpg_register(wwn, &tpg->tpg_se_tpg, SCSI_PROTOCOL_ISCSI); if (ret < 0) - return NULL; + goto free_out; ret = iscsit_tpg_add_portal_group(tiqn, tpg); if (ret != 0) @@ -1135,6 +1135,7 @@ static struct se_portal_group *lio_target_tiqn_addtpg( return &tpg->tpg_se_tpg; out: core_tpg_deregister(&tpg->tpg_se_tpg); +free_out: kfree(tpg); return NULL; } -- GitLab From a0884d489e016606e5e040624edaa13efefc3fcb Mon Sep 17 00:00:00 2001 From: tangwenji Date: Fri, 15 Sep 2017 17:18:07 +0800 Subject: [PATCH 1606/2898] iscsi-target: fix memory leak in iscsit_release_discovery_tpg() Need to release the param_list for tpg in iscsi_release_discovery_tpg function, this is also required before the iscsit_load_discovery_tpg function exits abnormally. Signed-off-by: tangwenji Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_tpg.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 594d07a1e995..4b34f71547c6 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -90,10 +90,10 @@ int iscsit_load_discovery_tpg(void) */ param = iscsi_find_param_from_key(AUTHMETHOD, tpg->param_list); if (!param) - goto out; + goto free_pl_out; if (iscsi_update_param_value(param, "CHAP,None") < 0) - goto out; + goto free_pl_out; tpg->tpg_attrib.authentication = 0; @@ -105,6 +105,8 @@ int iscsit_load_discovery_tpg(void) pr_debug("CORE[0] - Allocated Discovery TPG\n"); return 0; +free_pl_out: + iscsi_release_param_list(tpg->param_list); out: if (tpg->sid == 1) core_tpg_deregister(&tpg->tpg_se_tpg); @@ -119,6 +121,7 @@ void iscsit_release_discovery_tpg(void) if (!tpg) return; + iscsi_release_param_list(tpg->param_list); core_tpg_deregister(&tpg->tpg_se_tpg); kfree(tpg); -- GitLab From c22adc0b0cbe3768619eedc240bf58d88a1d6ed7 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 14 Sep 2017 09:30:05 +0800 Subject: [PATCH 1607/2898] tcmu: fix crash when removing the tcmu device Before the nl REMOVE msg has been sent to the userspace, the ring's and other resources have been released, but the userspace maybe still using them. And then we can see the crash messages like: ring broken, not handling completions BUG: unable to handle kernel paging request at ffffffffffffffd0 IP: tcmu_handle_completions+0x134/0x2f0 [target_core_user] PGD 11bdc0c067 P4D 11bdc0c067 PUD 11bdc0e067 PMD 0 Oops: 0000 [#1] SMP cmd_id not found, ring is broken RIP: 0010:tcmu_handle_completions+0x134/0x2f0 [target_core_user] RSP: 0018:ffffb8a2d8983d88 EFLAGS: 00010296 RAX: 0000000000000000 RBX: ffffb8a2aaa4e000 RCX: 00000000ffffffff RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000220 R10: 0000000076c71401 R11: ffff8d2e76c713f0 R12: ffffb8a2aad56bc0 R13: 000000000000001c R14: ffff8d2e32c90000 R15: ffff8d2e76c713f0 FS: 00007f411ffff700(0000) GS:ffff8d1e7fdc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffffffffd0 CR3: 0000001027070000 CR4: 00000000001406e0 Call Trace: ? tcmu_irqcontrol+0x2a/0x40 [target_core_user] ? uio_write+0x7b/0xc0 [uio] ? __vfs_write+0x37/0x150 ? __getnstimeofday64+0x3b/0xd0 ? vfs_write+0xb2/0x1b0 ? syscall_trace_enter+0x1d0/0x2b0 ? SyS_write+0x55/0xc0 ? do_syscall_64+0x67/0x150 ? entry_SYSCALL64_slow_path+0x25/0x25 Code: 41 5d 41 5e 41 5f 5d c3 83 f8 01 0f 85 cf 01 00 00 48 8b 7d d0 e8 dd 5c 1d f3 41 0f b7 74 24 04 48 8b 7d c8 31 d2 e8 5c c7 1b f3 <48> 8b 7d d0 49 89 c7 c6 07 00 0f 1f 40 00 4d 85 ff 0f 84 82 01 RIP: tcmu_handle_completions+0x134/0x2f0 [target_core_user] RSP: ffffb8a2d8983d88 CR2: ffffffffffffffd0 And the crash also could happen in tcmu_page_fault and other places. Signed-off-by: Zhang Zhuoyu Signed-off-by: Xiubo Li Reviewed-by: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 92 ++++++++++++++++--------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 942d094269fb..8b9ec0fc91c2 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -1112,6 +1112,8 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name) init_waitqueue_head(&udev->nl_cmd_wq); spin_lock_init(&udev->nl_cmd_lock); + INIT_RADIX_TREE(&udev->data_blocks, GFP_KERNEL); + return &udev->se_dev; } @@ -1280,10 +1282,54 @@ static void tcmu_dev_call_rcu(struct rcu_head *p) kfree(udev); } +static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd) +{ + if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) { + kmem_cache_free(tcmu_cmd_cache, cmd); + return 0; + } + return -EINVAL; +} + +static void tcmu_blocks_release(struct tcmu_dev *udev) +{ + int i; + struct page *page; + + /* Try to release all block pages */ + mutex_lock(&udev->cmdr_lock); + for (i = 0; i <= udev->dbi_max; i++) { + page = radix_tree_delete(&udev->data_blocks, i); + if (page) { + __free_page(page); + atomic_dec(&global_db_count); + } + } + mutex_unlock(&udev->cmdr_lock); +} + static void tcmu_dev_kref_release(struct kref *kref) { struct tcmu_dev *udev = container_of(kref, struct tcmu_dev, kref); struct se_device *dev = &udev->se_dev; + struct tcmu_cmd *cmd; + bool all_expired = true; + int i; + + vfree(udev->mb_addr); + udev->mb_addr = NULL; + + /* Upper layer should drain all requests before calling this */ + spin_lock_irq(&udev->commands_lock); + idr_for_each_entry(&udev->commands, cmd, i) { + if (tcmu_check_and_free_pending_cmd(cmd) != 0) + all_expired = false; + } + idr_destroy(&udev->commands); + spin_unlock_irq(&udev->commands_lock); + WARN_ON(!all_expired); + + tcmu_blocks_release(udev); call_rcu(&dev->rcu_head, tcmu_dev_call_rcu); } @@ -1476,8 +1522,6 @@ static int tcmu_configure_device(struct se_device *dev) WARN_ON(udev->data_size % PAGE_SIZE); WARN_ON(udev->data_size % DATA_BLOCK_SIZE); - INIT_RADIX_TREE(&udev->data_blocks, GFP_KERNEL); - info->version = __stringify(TCMU_MAILBOX_VERSION); info->mem[0].name = "tcm-user command & data buffer"; @@ -1527,6 +1571,7 @@ static int tcmu_configure_device(struct se_device *dev) uio_unregister_device(&udev->uio_info); err_register: vfree(udev->mb_addr); + udev->mb_addr = NULL; err_vzalloc: kfree(info->name); info->name = NULL; @@ -1534,37 +1579,11 @@ static int tcmu_configure_device(struct se_device *dev) return ret; } -static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd) -{ - if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) { - kmem_cache_free(tcmu_cmd_cache, cmd); - return 0; - } - return -EINVAL; -} - static bool tcmu_dev_configured(struct tcmu_dev *udev) { return udev->uio_info.uio_dev ? true : false; } -static void tcmu_blocks_release(struct tcmu_dev *udev) -{ - int i; - struct page *page; - - /* Try to release all block pages */ - mutex_lock(&udev->cmdr_lock); - for (i = 0; i <= udev->dbi_max; i++) { - page = radix_tree_delete(&udev->data_blocks, i); - if (page) { - __free_page(page); - atomic_dec(&global_db_count); - } - } - mutex_unlock(&udev->cmdr_lock); -} - static void tcmu_free_device(struct se_device *dev) { struct tcmu_dev *udev = TCMU_DEV(dev); @@ -1576,9 +1595,6 @@ static void tcmu_free_device(struct se_device *dev) static void tcmu_destroy_device(struct se_device *dev) { struct tcmu_dev *udev = TCMU_DEV(dev); - struct tcmu_cmd *cmd; - bool all_expired = true; - int i; del_timer_sync(&udev->timeout); @@ -1586,20 +1602,6 @@ static void tcmu_destroy_device(struct se_device *dev) list_del(&udev->node); mutex_unlock(&root_udev_mutex); - vfree(udev->mb_addr); - - /* Upper layer should drain all requests before calling this */ - spin_lock_irq(&udev->commands_lock); - idr_for_each_entry(&udev->commands, cmd, i) { - if (tcmu_check_and_free_pending_cmd(cmd) != 0) - all_expired = false; - } - idr_destroy(&udev->commands); - spin_unlock_irq(&udev->commands_lock); - WARN_ON(!all_expired); - - tcmu_blocks_release(udev); - tcmu_netlink_event(udev, TCMU_CMD_REMOVED_DEVICE, 0, NULL); uio_unregister_device(&udev->uio_info); -- GitLab From b5ab697c62724b3d31556d91c6f9b76d2e264e4b Mon Sep 17 00:00:00 2001 From: Kenjiro Nakayama Date: Fri, 15 Sep 2017 14:44:55 +0900 Subject: [PATCH 1608/2898] target/tcmu: Use macro to call container_of in tcmu_cmd_time_out_show This patch makes a tiny change that using TCMU_DEV in tcmu_cmd_time_out_show so it is consistent with other functions. Signed-off-by: Kenjiro Nakayama Reviewed-by: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 8b9ec0fc91c2..2dd329773249 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -1736,8 +1736,7 @@ static ssize_t tcmu_cmd_time_out_show(struct config_item *item, char *page) { struct se_dev_attrib *da = container_of(to_config_group(item), struct se_dev_attrib, da_group); - struct tcmu_dev *udev = container_of(da->da_dev, - struct tcmu_dev, se_dev); + struct tcmu_dev *udev = TCMU_DEV(da->da_dev); return snprintf(page, PAGE_SIZE, "%lu\n", udev->cmd_time_out / MSEC_PER_SEC); } -- GitLab From b849b4567549d5a54ab34ffacfd48fca05e8b34e Mon Sep 17 00:00:00 2001 From: Kenjiro Nakayama Date: Wed, 13 Sep 2017 14:01:22 +0900 Subject: [PATCH 1609/2898] target: Add netlink command reply supported option for each device Currently netlink command reply support option (TCMU_ATTR_SUPP_KERN_CMD_REPLY) can be enabled only on module scope. Because of that, once an application enables the netlink command reply support, all applications using target_core_user.ko would be expected to support the netlink reply. To make matters worse, users will not be able to add a device via configfs manually. To fix these issues, this patch adds an option to make netlink command reply disabled on each device through configfs. Original TCMU_ATTR_SUPP_KERN_CMD_REPLY is still enabled on module scope to keep backward-compatibility and used by default, however once users set nl_reply_supported= via configfs for a particular device, the device disables the netlink command reply support. Signed-off-by: Kenjiro Nakayama Reviewed-by: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 59 ++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 2dd329773249..3189bf0bc7f1 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -150,6 +150,8 @@ struct tcmu_dev { wait_queue_head_t nl_cmd_wq; char dev_config[TCMU_CONFIG_LEN]; + + int nl_reply_supported; }; #define TCMU_DEV(_se_dev) container_of(_se_dev, struct tcmu_dev, se_dev) @@ -1352,6 +1354,10 @@ static void tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd) if (!tcmu_kern_cmd_reply_supported) return; + + if (udev->nl_reply_supported <= 0) + return; + relock: spin_lock(&udev->nl_cmd_lock); @@ -1378,6 +1384,9 @@ static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev) if (!tcmu_kern_cmd_reply_supported) return 0; + if (udev->nl_reply_supported <= 0) + return 0; + pr_debug("sleeping for nl reply\n"); wait_for_completion(&nl_cmd->complete); @@ -1550,6 +1559,12 @@ static int tcmu_configure_device(struct se_device *dev) dev->dev_attrib.emulate_write_cache = 0; dev->dev_attrib.hw_queue_depth = 128; + /* If user didn't explicitly disable netlink reply support, use + * module scope setting. + */ + if (udev->nl_reply_supported >= 0) + udev->nl_reply_supported = tcmu_kern_cmd_reply_supported; + /* * Get a ref incase userspace does a close on the uio device before * LIO has initiated tcmu_free_device. @@ -1612,7 +1627,7 @@ static void tcmu_destroy_device(struct se_device *dev) enum { Opt_dev_config, Opt_dev_size, Opt_hw_block_size, Opt_hw_max_sectors, - Opt_err, + Opt_nl_reply_supported, Opt_err, }; static match_table_t tokens = { @@ -1620,6 +1635,7 @@ static match_table_t tokens = { {Opt_dev_size, "dev_size=%u"}, {Opt_hw_block_size, "hw_block_size=%u"}, {Opt_hw_max_sectors, "hw_max_sectors=%u"}, + {Opt_nl_reply_supported, "nl_reply_supported=%d"}, {Opt_err, NULL} }; @@ -1694,6 +1710,18 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev, ret = tcmu_set_dev_attrib(&args[0], &(dev->dev_attrib.hw_max_sectors)); break; + case Opt_nl_reply_supported: + arg_p = match_strdup(&args[0]); + if (!arg_p) { + ret = -ENOMEM; + break; + } + ret = kstrtol(arg_p, 0, + (long int *) &udev->nl_reply_supported); + kfree(arg_p); + if (ret < 0) + pr_err("kstrtoul() failed for nl_reply_supported=\n"); + break; default: break; } @@ -1843,6 +1871,34 @@ static ssize_t tcmu_dev_size_store(struct config_item *item, const char *page, } CONFIGFS_ATTR(tcmu_, dev_size); +static ssize_t tcmu_nl_reply_supported_show(struct config_item *item, + char *page) +{ + struct se_dev_attrib *da = container_of(to_config_group(item), + struct se_dev_attrib, da_group); + struct tcmu_dev *udev = TCMU_DEV(da->da_dev); + + return snprintf(page, PAGE_SIZE, "%d\n", udev->nl_reply_supported); +} + +static ssize_t tcmu_nl_reply_supported_store(struct config_item *item, + const char *page, size_t count) +{ + struct se_dev_attrib *da = container_of(to_config_group(item), + struct se_dev_attrib, da_group); + struct tcmu_dev *udev = TCMU_DEV(da->da_dev); + s8 val; + int ret; + + ret = kstrtos8(page, 0, &val); + if (ret < 0) + return ret; + + udev->nl_reply_supported = val; + return count; +} +CONFIGFS_ATTR(tcmu_, nl_reply_supported); + static ssize_t tcmu_emulate_write_cache_show(struct config_item *item, char *page) { @@ -1885,6 +1941,7 @@ static struct configfs_attribute *tcmu_attrib_attrs[] = { &tcmu_attr_dev_config, &tcmu_attr_dev_size, &tcmu_attr_emulate_write_cache, + &tcmu_attr_nl_reply_supported, NULL, }; -- GitLab From 1ae01724ae92004be36a6c11c4d5a9f94e915204 Mon Sep 17 00:00:00 2001 From: Varun Prakash Date: Wed, 4 Oct 2017 22:03:35 +0530 Subject: [PATCH 1610/2898] cxgbit: Abort the TCP connection in case of data out timeout If DDP is programmed for a WRITE cmd and data out timer gets expired then abort the TCP connection before freeing the cmd to avoid any possibility of DDP after freeing the cmd. Signed-off-by: Varun Prakash Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/cxgbit/cxgbit.h | 2 ++ drivers/target/iscsi/cxgbit/cxgbit_cm.c | 45 ++++++++++++++++++++++++ drivers/target/iscsi/cxgbit/cxgbit_ddp.c | 8 +++++ 3 files changed, 55 insertions(+) diff --git a/drivers/target/iscsi/cxgbit/cxgbit.h b/drivers/target/iscsi/cxgbit/cxgbit.h index 90388698c222..417b9e66b0cd 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit.h +++ b/drivers/target/iscsi/cxgbit/cxgbit.h @@ -165,6 +165,7 @@ enum cxgbit_csk_flags { CSK_LOGIN_PDU_DONE, CSK_LOGIN_DONE, CSK_DDP_ENABLE, + CSK_ABORT_RPL_WAIT, }; struct cxgbit_sock_common { @@ -321,6 +322,7 @@ int cxgbit_setup_np(struct iscsi_np *, struct sockaddr_storage *); int cxgbit_setup_conn_digest(struct cxgbit_sock *); int cxgbit_accept_np(struct iscsi_np *, struct iscsi_conn *); void cxgbit_free_np(struct iscsi_np *); +void cxgbit_abort_conn(struct cxgbit_sock *csk); void cxgbit_free_conn(struct iscsi_conn *); extern cxgbit_cplhandler_func cxgbit_cplhandlers[NUM_CPL_CMDS]; int cxgbit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); diff --git a/drivers/target/iscsi/cxgbit/cxgbit_cm.c b/drivers/target/iscsi/cxgbit/cxgbit_cm.c index d4fa41be80f9..92eb57e2adaf 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_cm.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_cm.c @@ -665,6 +665,46 @@ static int cxgbit_send_abort_req(struct cxgbit_sock *csk) return cxgbit_l2t_send(csk->com.cdev, skb, csk->l2t); } +static void +__cxgbit_abort_conn(struct cxgbit_sock *csk, struct sk_buff *skb) +{ + __kfree_skb(skb); + + if (csk->com.state != CSK_STATE_ESTABLISHED) + goto no_abort; + + set_bit(CSK_ABORT_RPL_WAIT, &csk->com.flags); + csk->com.state = CSK_STATE_ABORTING; + + cxgbit_send_abort_req(csk); + + return; + +no_abort: + cxgbit_wake_up(&csk->com.wr_wait, __func__, CPL_ERR_NONE); + cxgbit_put_csk(csk); +} + +void cxgbit_abort_conn(struct cxgbit_sock *csk) +{ + struct sk_buff *skb = alloc_skb(0, GFP_KERNEL | __GFP_NOFAIL); + + cxgbit_get_csk(csk); + cxgbit_init_wr_wait(&csk->com.wr_wait); + + spin_lock_bh(&csk->lock); + if (csk->lock_owner) { + cxgbit_skcb_rx_backlog_fn(skb) = __cxgbit_abort_conn; + __skb_queue_tail(&csk->backlogq, skb); + } else { + __cxgbit_abort_conn(csk, skb); + } + spin_unlock_bh(&csk->lock); + + cxgbit_wait_for_reply(csk->com.cdev, &csk->com.wr_wait, + csk->tid, 600, __func__); +} + void cxgbit_free_conn(struct iscsi_conn *conn) { struct cxgbit_sock *csk = conn->context; @@ -1709,12 +1749,17 @@ static void cxgbit_abort_req_rss(struct cxgbit_sock *csk, struct sk_buff *skb) static void cxgbit_abort_rpl_rss(struct cxgbit_sock *csk, struct sk_buff *skb) { + struct cpl_abort_rpl_rss *rpl = cplhdr(skb); + pr_debug("%s: csk %p; tid %u; state %d\n", __func__, csk, csk->tid, csk->com.state); switch (csk->com.state) { case CSK_STATE_ABORTING: csk->com.state = CSK_STATE_DEAD; + if (test_bit(CSK_ABORT_RPL_WAIT, &csk->com.flags)) + cxgbit_wake_up(&csk->com.wr_wait, __func__, + rpl->status); cxgbit_put_csk(csk); break; default: diff --git a/drivers/target/iscsi/cxgbit/cxgbit_ddp.c b/drivers/target/iscsi/cxgbit/cxgbit_ddp.c index 5fdb57cac968..768cce0ccb80 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_ddp.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_ddp.c @@ -275,6 +275,14 @@ void cxgbit_release_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd) struct cxgbit_device *cdev = csk->com.cdev; struct cxgbi_ppm *ppm = cdev2ppm(cdev); + /* Abort the TCP conn if DDP is not complete to + * avoid any possibility of DDP after freeing + * the cmd. + */ + if (unlikely(cmd->write_data_done != + cmd->se_cmd.data_length)) + cxgbit_abort_conn(csk); + cxgbi_ppm_ppod_release(ppm, ttinfo->idx); dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl, -- GitLab From bdc79f0ed12ff55a9b56a91da04d0c8d8a786b9c Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 19 Oct 2017 01:39:19 +0200 Subject: [PATCH 1611/2898] target: fix PR state file path truncation If an LIO backstore is configured with a sufficiently long Unit Serial string, alongside a similarly long dbroot path, then a truncated Persistent Reservation APTPL state file path will be used. This truncation can unintentionally lead to two LUs with differing serial numbers sharing PR state file. Fixes: fdddf932269a ("target: use new "dbroot" target attribute") Signed-off-by: David Disseldorp Reviewed-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index a54490709811..3d2b46472dfd 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1973,24 +1973,21 @@ static int __core_scsi3_write_aptpl_to_file( struct t10_wwn *wwn = &dev->t10_wwn; struct file *file; int flags = O_RDWR | O_CREAT | O_TRUNC; - char path[512]; + char *path; u32 pr_aptpl_buf_len; int ret; loff_t pos = 0; - memset(path, 0, 512); - - if (strlen(&wwn->unit_serial[0]) >= 512) { - pr_err("WWN value for struct se_device does not fit" - " into path buffer\n"); - return -EMSGSIZE; - } + path = kasprintf(GFP_KERNEL, "%s/pr/aptpl_%s", db_root, + &wwn->unit_serial[0]); + if (!path) + return -ENOMEM; - snprintf(path, 512, "%s/pr/aptpl_%s", db_root, &wwn->unit_serial[0]); file = filp_open(path, flags, 0600); if (IS_ERR(file)) { pr_err("filp_open(%s) for APTPL metadata" " failed\n", path); + kfree(path); return PTR_ERR(file); } @@ -2001,6 +1998,7 @@ static int __core_scsi3_write_aptpl_to_file( if (ret < 0) pr_debug("Error writing APTPL metadata file: %s\n", path); fput(file); + kfree(path); return (ret < 0) ? -EIO : 0; } -- GitLab From 55435badda8bd8e4c97a8b6c3fa9eef79b02fe44 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 19 Oct 2017 01:39:20 +0200 Subject: [PATCH 1612/2898] target: fix ALUA state file path truncation A sufficiently long Unit Serial string, dbroot path, and/or ALUA target portal group name may result in truncation of the ALUA state file path prior to usage. Fix this by using kasprintf() instead. Fixes: fdddf932269a ("target: use new "dbroot" target attribute") Signed-off-by: David Disseldorp Reviewed-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_alua.c | 51 +++++++++++++++++-------------- drivers/target/target_core_alua.h | 9 ------ 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 928127642574..e46ca968009c 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -918,7 +918,7 @@ static int core_alua_update_tpg_primary_metadata( { unsigned char *md_buf; struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn; - char path[ALUA_METADATA_PATH_LEN]; + char *path; int len, rc; md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL); @@ -927,8 +927,6 @@ static int core_alua_update_tpg_primary_metadata( return -ENOMEM; } - memset(path, 0, ALUA_METADATA_PATH_LEN); - len = snprintf(md_buf, ALUA_MD_BUF_LEN, "tg_pt_gp_id=%hu\n" "alua_access_state=0x%02x\n" @@ -937,11 +935,14 @@ static int core_alua_update_tpg_primary_metadata( tg_pt_gp->tg_pt_gp_alua_access_state, tg_pt_gp->tg_pt_gp_alua_access_status); - snprintf(path, ALUA_METADATA_PATH_LEN, - "%s/alua/tpgs_%s/%s", db_root, &wwn->unit_serial[0], - config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); - - rc = core_alua_write_tpg_metadata(path, md_buf, len); + rc = -ENOMEM; + path = kasprintf(GFP_KERNEL, "%s/alua/tpgs_%s/%s", db_root, + &wwn->unit_serial[0], + config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); + if (path) { + rc = core_alua_write_tpg_metadata(path, md_buf, len); + kfree(path); + } kfree(md_buf); return rc; } @@ -1209,7 +1210,7 @@ static int core_alua_update_tpg_secondary_metadata(struct se_lun *lun) { struct se_portal_group *se_tpg = lun->lun_tpg; unsigned char *md_buf; - char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN]; + char *path; int len, rc; mutex_lock(&lun->lun_tg_pt_md_mutex); @@ -1221,28 +1222,32 @@ static int core_alua_update_tpg_secondary_metadata(struct se_lun *lun) goto out_unlock; } - memset(path, 0, ALUA_METADATA_PATH_LEN); - memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN); - - len = snprintf(wwn, ALUA_SECONDARY_METADATA_WWN_LEN, "%s", - se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg)); - - if (se_tpg->se_tpg_tfo->tpg_get_tag != NULL) - snprintf(wwn+len, ALUA_SECONDARY_METADATA_WWN_LEN-len, "+%hu", - se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); - len = snprintf(md_buf, ALUA_MD_BUF_LEN, "alua_tg_pt_offline=%d\n" "alua_tg_pt_status=0x%02x\n", atomic_read(&lun->lun_tg_pt_secondary_offline), lun->lun_tg_pt_secondary_stat); - snprintf(path, ALUA_METADATA_PATH_LEN, "%s/alua/%s/%s/lun_%llu", - db_root, se_tpg->se_tpg_tfo->get_fabric_name(), wwn, - lun->unpacked_lun); + if (se_tpg->se_tpg_tfo->tpg_get_tag != NULL) { + path = kasprintf(GFP_KERNEL, "%s/alua/%s/%s+%hu/lun_%llu", + db_root, se_tpg->se_tpg_tfo->get_fabric_name(), + se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg), + se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg), + lun->unpacked_lun); + } else { + path = kasprintf(GFP_KERNEL, "%s/alua/%s/%s/lun_%llu", + db_root, se_tpg->se_tpg_tfo->get_fabric_name(), + se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg), + lun->unpacked_lun); + } + if (!path) { + rc = -ENOMEM; + goto out_free; + } rc = core_alua_write_tpg_metadata(path, md_buf, len); + kfree(path); +out_free: kfree(md_buf); - out_unlock: mutex_unlock(&lun->lun_tg_pt_md_mutex); return rc; diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h index c69c11baf07f..90643300cd32 100644 --- a/drivers/target/target_core_alua.h +++ b/drivers/target/target_core_alua.h @@ -71,15 +71,6 @@ */ #define ALUA_DEFAULT_IMPLICIT_TRANS_SECS 0 #define ALUA_MAX_IMPLICIT_TRANS_SECS 255 -/* - * Used by core_alua_update_tpg_primary_metadata() and - * core_alua_update_tpg_secondary_metadata() - */ -#define ALUA_METADATA_PATH_LEN 512 -/* - * Used by core_alua_update_tpg_secondary_metadata() - */ -#define ALUA_SECONDARY_METADATA_WWN_LEN 256 /* Used by core_alua_update_tpg_(primary,secondary)_metadata */ #define ALUA_MD_BUF_LEN 1024 -- GitLab From a271eac46a9a2457f4e8c757f9b7fc92a445cf48 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 25 Oct 2017 11:47:14 -0500 Subject: [PATCH 1613/2898] target: return SAM_STAT_TASK_SET_FULL for TCM_OUT_OF_RESOURCES TCM_OUT_OF_RESOURCES is getting translated to TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE which seems like a heavy error when we just cannot allocate a resource that may be allocatable later. This has us translate TCM_OUT_OF_RESOURCES to SAM_STAT_TASK_SET_FULL instead. Signed-off-by: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 190f3ba23707..e791a7b63382 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1772,8 +1772,8 @@ void transport_generic_request_failure(struct se_cmd *cmd, case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE: break; case TCM_OUT_OF_RESOURCES: - sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - break; + cmd->scsi_status = SAM_STAT_TASK_SET_FULL; + goto queue_status; case TCM_RESERVATION_CONFLICT: /* * No SENSE Data payload for this case, set SCSI Status @@ -1795,11 +1795,8 @@ void transport_generic_request_failure(struct se_cmd *cmd, cmd->orig_fe_lun, 0x2C, ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); } - trace_target_cmd_complete(cmd); - ret = cmd->se_tfo->queue_status(cmd); - if (ret) - goto queue_full; - goto check_stop; + + goto queue_status; default: pr_err("Unknown transport error for CDB 0x%02x: %d\n", cmd->t_task_cdb[0], sense_reason); @@ -1816,6 +1813,11 @@ void transport_generic_request_failure(struct se_cmd *cmd, transport_cmd_check_stop_to_fabric(cmd); return; +queue_status: + trace_target_cmd_complete(cmd); + ret = cmd->se_tfo->queue_status(cmd); + if (!ret) + goto check_stop; queue_full: transport_handle_queue_full(cmd, cmd->se_dev, ret, false); } -- GitLab From 0d44374c1aaec7c81b470d3b5f955bc270711f9c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 25 Oct 2017 11:47:15 -0500 Subject: [PATCH 1614/2898] tcmu: fix double se_cmd completion If cmd_time_out != 0, then tcmu_queue_cmd_ring could end up sleeping waiting for ring space, timing out and then returning failure to lio, and tcmu_check_expired_cmd could also detect the timeout and call target_complete_cmd on the cmd. This patch just delays setting up the deadline value and adding the cmd to the udev->commands idr until we have allocated ring space and are about to send the cmd to userspace. Signed-off-by: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 54 ++++++++++++++++++------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 3189bf0bc7f1..9ddf0909d33e 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -432,7 +432,6 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd) struct se_device *se_dev = se_cmd->se_dev; struct tcmu_dev *udev = TCMU_DEV(se_dev); struct tcmu_cmd *tcmu_cmd; - int cmd_id; tcmu_cmd = kmem_cache_zalloc(tcmu_cmd_cache, GFP_KERNEL); if (!tcmu_cmd) @@ -440,9 +439,6 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd) tcmu_cmd->se_cmd = se_cmd; tcmu_cmd->tcmu_dev = udev; - if (udev->cmd_time_out) - tcmu_cmd->deadline = jiffies + - msecs_to_jiffies(udev->cmd_time_out); tcmu_cmd_reset_dbi_cur(tcmu_cmd); tcmu_cmd->dbi_cnt = tcmu_cmd_get_block_cnt(tcmu_cmd); @@ -453,19 +449,6 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd) return NULL; } - idr_preload(GFP_KERNEL); - spin_lock_irq(&udev->commands_lock); - cmd_id = idr_alloc(&udev->commands, tcmu_cmd, 0, - USHRT_MAX, GFP_NOWAIT); - spin_unlock_irq(&udev->commands_lock); - idr_preload_end(); - - if (cmd_id < 0) { - tcmu_free_cmd(tcmu_cmd); - return NULL; - } - tcmu_cmd->cmd_id = cmd_id; - return tcmu_cmd; } @@ -748,6 +731,30 @@ static inline size_t tcmu_cmd_get_cmd_size(struct tcmu_cmd *tcmu_cmd, return command_size; } +static int tcmu_setup_cmd_timer(struct tcmu_cmd *tcmu_cmd) +{ + struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; + unsigned long tmo = udev->cmd_time_out; + int cmd_id; + + if (tcmu_cmd->cmd_id) + return 0; + + cmd_id = idr_alloc(&udev->commands, tcmu_cmd, 1, USHRT_MAX, GFP_NOWAIT); + if (cmd_id < 0) { + pr_err("tcmu: Could not allocate cmd id.\n"); + return cmd_id; + } + tcmu_cmd->cmd_id = cmd_id; + + if (!tmo) + return 0; + + tcmu_cmd->deadline = round_jiffies_up(jiffies + msecs_to_jiffies(tmo)); + mod_timer(&udev->timeout, tcmu_cmd->deadline); + return 0; +} + static sense_reason_t tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) { @@ -841,7 +848,6 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) entry = (void *) mb + CMDR_OFF + cmd_head; memset(entry, 0, command_size); tcmu_hdr_set_op(&entry->hdr.len_op, TCMU_OP_CMD); - entry->hdr.cmd_id = tcmu_cmd->cmd_id; /* Handle allocating space from the data area */ tcmu_cmd_reset_dbi_cur(tcmu_cmd); @@ -879,6 +885,13 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) } entry->req.iov_bidi_cnt = iov_cnt; + ret = tcmu_setup_cmd_timer(tcmu_cmd); + if (ret) { + tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cnt); + return TCM_OUT_OF_RESOURCES; + } + entry->hdr.cmd_id = tcmu_cmd->cmd_id; + /* * Recalaulate the command's base size and size according * to the actual needs @@ -912,8 +925,6 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) static sense_reason_t tcmu_queue_cmd(struct se_cmd *se_cmd) { - struct se_device *se_dev = se_cmd->se_dev; - struct tcmu_dev *udev = TCMU_DEV(se_dev); struct tcmu_cmd *tcmu_cmd; sense_reason_t ret; @@ -924,9 +935,6 @@ tcmu_queue_cmd(struct se_cmd *se_cmd) ret = tcmu_queue_cmd_ring(tcmu_cmd); if (ret != TCM_NO_SENSE) { pr_err("TCMU: Could not queue command\n"); - spin_lock_irq(&udev->commands_lock); - idr_remove(&udev->commands, tcmu_cmd->cmd_id); - spin_unlock_irq(&udev->commands_lock); tcmu_free_cmd(tcmu_cmd); } -- GitLab From c48e5594d02f224c788cc57b192c61653a117b56 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:09 -0700 Subject: [PATCH 1615/2898] target: Move a declaration of a global variable into a header file This patch avoids that sparse reports the following warning: drivers/target/target_core_configfs.c:2267:33: warning: symbol 'target_core_dev_item_ops' was not declared. Should it be static? Fixes: c17cd24959cd ("target/configfs: Kill se_device->dev_link_magic") Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_fabric_configfs.c | 2 -- drivers/target/target_core_internal.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index e9e917cc6441..e1416b007aa4 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -623,8 +623,6 @@ static struct configfs_attribute *target_fabric_port_attrs[] = { NULL, }; -extern struct configfs_item_operations target_core_dev_item_ops; - static int target_fabric_port_link( struct config_item *lun_ci, struct config_item *se_dev_ci) diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index f30e8ac13386..2c5004ffb581 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -88,6 +88,7 @@ int target_for_each_device(int (*fn)(struct se_device *dev, void *data), void *data); /* target_core_configfs.c */ +extern struct configfs_item_operations target_core_dev_item_ops; void target_setup_backend_cits(struct target_backend *); /* target_core_fabric_configfs.c */ -- GitLab From d7e595ddd5b243aa9ba1948d5e0a37783b5415af Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:10 -0700 Subject: [PATCH 1616/2898] target: Suppress gcc 7 fallthrough warnings Avoid that gcc 7 reports the following warning when building with W=1: warning: this statement may fall through [-Wimplicit-fallthrough=] Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Cc: Varun Prakash Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/cxgbit/cxgbit_main.c | 1 + drivers/target/target_core_pr.c | 2 ++ drivers/target/target_core_transport.c | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/cxgbit/cxgbit_main.c b/drivers/target/iscsi/cxgbit/cxgbit_main.c index 4fd775ace541..f3f8856bfb68 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_main.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_main.c @@ -446,6 +446,7 @@ cxgbit_uld_lro_rx_handler(void *hndl, const __be64 *rsp, case CPL_RX_ISCSI_DDP: case CPL_FW4_ACK: lro_flush = false; + /* fall through */ case CPL_ABORT_RPL_RSS: case CPL_PASS_ESTABLISH: case CPL_PEER_CLOSE: diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 3d2b46472dfd..b024613f9217 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -353,6 +353,7 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type, break; case PR_TYPE_WRITE_EXCLUSIVE_REGONLY: we = 1; + /* fall through */ case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: /* * Some commands are only allowed for registered I_T Nexuses. @@ -361,6 +362,7 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type, break; case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: we = 1; + /* fall through */ case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: /* * Each registered I_T Nexus is a reservation holder. diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e791a7b63382..e2bf547054bd 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2092,7 +2092,7 @@ static void transport_complete_qf(struct se_cmd *cmd) ret = cmd->se_tfo->queue_data_in(cmd); break; } - /* Fall through for DMA_TO_DEVICE */ + /* fall through */ case DMA_NONE: queue_status: trace_target_cmd_complete(cmd); @@ -2270,7 +2270,7 @@ static void target_complete_ok_work(struct work_struct *work) goto queue_full; break; } - /* Fall through for DMA_TO_DEVICE */ + /* fall through */ case DMA_NONE: queue_status: trace_target_cmd_complete(cmd); -- GitLab From c01706982350224a6c3653ca5b6f24f37dbbecad Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:11 -0700 Subject: [PATCH 1617/2898] target: Inline transport_put_cmd() Since all transput_put_cmd() does is to call target_put_sess_cmd(), inline transport_put_cmd() into its callers. Leave out the BUG_ON() statement because if cmd->se_tfo == NULL then cmd->cmd_kref is 0 and kref_put() will complain anyway. Notes: - transport_init_se_cmd() initializes both .se_tfo and .cmd_kref. - The only target driver that does not call transport_init_se_cmd() for all commands is the iSCSI target driver. See also iscsi_target_rx_opcode(). Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e2bf547054bd..473d652e4816 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -67,7 +67,6 @@ static void transport_complete_task_attr(struct se_cmd *cmd); static int translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason); static void transport_handle_queue_full(struct se_cmd *cmd, struct se_device *dev, int err, bool write_pending); -static int transport_put_cmd(struct se_cmd *cmd); static void target_complete_ok_work(struct work_struct *work); int init_se_kmem_caches(void) @@ -668,7 +667,7 @@ int transport_cmd_finish_abort(struct se_cmd *cmd, int remove) if (transport_cmd_check_stop_to_fabric(cmd)) return 1; if (remove && ack_kref) - ret = transport_put_cmd(cmd); + ret = target_put_sess_cmd(cmd); return ret; } @@ -2354,22 +2353,6 @@ static inline void transport_free_pages(struct se_cmd *cmd) cmd->t_bidi_data_nents = 0; } -/** - * transport_put_cmd - release a reference to a command - * @cmd: command to release - * - * This routine releases our reference to the command and frees it if possible. - */ -static int transport_put_cmd(struct se_cmd *cmd) -{ - BUG_ON(!cmd->se_tfo); - /* - * If this cmd has been setup with target_get_sess_cmd(), drop - * the kref and call ->release_cmd() in kref callback. - */ - return target_put_sess_cmd(cmd); -} - void *transport_kmap_data_sg(struct se_cmd *cmd) { struct scatterlist *sg = cmd->t_data_sg; @@ -2605,7 +2588,7 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) target_wait_free_cmd(cmd, &aborted, &tas); if (!aborted || tas) - ret = transport_put_cmd(cmd); + ret = target_put_sess_cmd(cmd); } else { if (wait_for_tasks) target_wait_free_cmd(cmd, &aborted, &tas); @@ -2621,7 +2604,7 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) transport_lun_remove_cmd(cmd); if (!aborted || tas) - ret = transport_put_cmd(cmd); + ret = target_put_sess_cmd(cmd); } /* * If the task has been internally aborted due to TMR ABORT_TASK -- GitLab From 8d973ab5d4520f84e89aaa38e0a50bb2876b09eb Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:13 -0700 Subject: [PATCH 1618/2898] target/iscsi: Define OFFLOAD_BUF_SIZE once The constant OFFLOAD_BUF_SIZE is defined twice - once in iscsi_target_seq_pdu_list.c and once in iscsi_target_erl1.c. Since that constant is not used in the former source file, remove its definition from that source file. Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_seq_pdu_list.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c index e446a09c886b..f65e5e584212 100644 --- a/drivers/target/iscsi/iscsi_target_seq_pdu_list.c +++ b/drivers/target/iscsi/iscsi_target_seq_pdu_list.c @@ -25,8 +25,6 @@ #include "iscsi_target_tpg.h" #include "iscsi_target_seq_pdu_list.h" -#define OFFLOAD_BUF_SIZE 32768 - #ifdef DEBUG static void iscsit_dump_seq_list(struct iscsi_cmd *cmd) { -- GitLab From 919765e9680fe26acdcad782ee693f31dbde2def Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:14 -0700 Subject: [PATCH 1619/2898] target/iscsi: Use min() in iscsit_dump_data_payload() instead of open-coding it This patch does not change any functionality. Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_erl1.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index fe9b7f1e44ac..659efafb43ec 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -34,7 +34,7 @@ #include "iscsi_target_erl2.h" #include "iscsi_target.h" -#define OFFLOAD_BUF_SIZE 32768 +#define OFFLOAD_BUF_SIZE 32768U /* * Used to dump excess datain payload for certain error recovery @@ -56,7 +56,7 @@ int iscsit_dump_data_payload( if (conn->sess->sess_ops->RDMAExtensions) return 0; - length = (buf_len > OFFLOAD_BUF_SIZE) ? OFFLOAD_BUF_SIZE : buf_len; + length = min(buf_len, OFFLOAD_BUF_SIZE); buf = kzalloc(length, GFP_ATOMIC); if (!buf) { @@ -67,8 +67,7 @@ int iscsit_dump_data_payload( memset(&iov, 0, sizeof(struct kvec)); while (offset < buf_len) { - size = ((offset + length) > buf_len) ? - (buf_len - offset) : length; + size = min(buf_len - offset, length); iov.iov_len = size; iov.iov_base = buf; -- GitLab From de3493aea656ad7ae2e8dd492ee928712d147c74 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:15 -0700 Subject: [PATCH 1620/2898] target/iscsi: Fix endianness in an error message Since hdr->offset is a big endian number, convert it to CPU endian before printing it. Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 5001261f5d69..37bc8a37401d 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1460,9 +1460,9 @@ __iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf, iscsit_mod_dataout_timer(cmd); if ((be32_to_cpu(hdr->offset) + payload_length) > cmd->se_cmd.data_length) { - pr_err("DataOut Offset: %u, Length %u greater than" - " iSCSI Command EDTL %u, protocol error.\n", - hdr->offset, payload_length, cmd->se_cmd.data_length); + pr_err("DataOut Offset: %u, Length %u greater than iSCSI Command EDTL %u, protocol error.\n", + be32_to_cpu(hdr->offset), payload_length, + cmd->se_cmd.data_length); return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf); } -- GitLab From e1dfb21f004f403a16539e8a037963b57a25e0ad Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:16 -0700 Subject: [PATCH 1621/2898] target/iscsi: Modify iscsit_do_crypto_hash_buf() prototype Change the type of the last two arguments from u8 * into const void * and void * respectively such that the u8 * casts can be left out from the callers. This patch does not change any functionality. Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 41 ++++++++++++----------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 37bc8a37401d..91fbada7cdc2 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -500,7 +500,7 @@ void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) EXPORT_SYMBOL(iscsit_aborted_task); static void iscsit_do_crypto_hash_buf(struct ahash_request *, const void *, - u32, u32, u8 *, u8 *); + u32, u32, const void *, void *); static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *); static int @@ -521,7 +521,7 @@ iscsit_xmit_nondatain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd, iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, - (u8 *)header_digest); + header_digest); iov[0].iov_len += ISCSI_CRC_LEN; tx_size += ISCSI_CRC_LEN; @@ -548,9 +548,8 @@ iscsit_xmit_nondatain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (conn->conn_ops->DataDigest) { iscsit_do_crypto_hash_buf(conn->conn_tx_hash, data_buf, data_buf_len, - padding, - (u8 *)&cmd->pad_bytes, - (u8 *)&cmd->data_crc); + padding, &cmd->pad_bytes, + &cmd->data_crc); iov[niov].iov_base = &cmd->data_crc; iov[niov++].iov_len = ISCSI_CRC_LEN; @@ -595,7 +594,7 @@ iscsit_xmit_datain_pdu(struct iscsi_conn *conn, struct iscsi_cmd *cmd, iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu, ISCSI_HDR_LEN, 0, NULL, - (u8 *)header_digest); + header_digest); iov[0].iov_len += ISCSI_CRC_LEN; tx_size += ISCSI_CRC_LEN; @@ -1408,13 +1407,9 @@ static u32 iscsit_do_crypto_hash_sg( return data_crc; } -static void iscsit_do_crypto_hash_buf( - struct ahash_request *hash, - const void *buf, - u32 payload_length, - u32 padding, - u8 *pad_bytes, - u8 *data_crc) +static void iscsit_do_crypto_hash_buf(struct ahash_request *hash, + const void *buf, u32 payload_length, u32 padding, + const void *pad_bytes, void *data_crc) { struct scatterlist sg[2]; @@ -1876,10 +1871,9 @@ static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, - ping_data, payload_length, - padding, cmd->pad_bytes, - (u8 *)&data_crc); + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data, + payload_length, padding, + cmd->pad_bytes, &data_crc); if (checksum != data_crc) { pr_err("Ping data CRC32C DataDigest" @@ -2285,10 +2279,9 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, goto reject; if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, - text_in, payload_length, - padding, (u8 *)&pad_bytes, - (u8 *)&data_crc); + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, text_in, + payload_length, padding, + &pad_bytes, &data_crc); if (checksum != data_crc) { pr_err("Text data CRC32C DataDigest" @@ -3976,9 +3969,9 @@ static void iscsit_get_rx_pdu(struct iscsi_conn *conn) return; } - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, - buffer, ISCSI_HDR_LEN, - 0, NULL, (u8 *)&checksum); + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer, + ISCSI_HDR_LEN, 0, NULL, + &checksum); if (digest != checksum) { pr_err("HeaderDigest CRC32C failed," -- GitLab From cfe2b621bb18d86e93271febf8c6e37622da2d14 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:17 -0700 Subject: [PATCH 1622/2898] target/iscsi: Fix a race condition in iscsit_add_reject_from_cmd() Avoid that cmd->se_cmd.se_tfo is read after a command has already been freed. Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 91fbada7cdc2..541f66a875fc 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -833,6 +833,7 @@ static int iscsit_add_reject_from_cmd( unsigned char *buf) { struct iscsi_conn *conn; + const bool do_put = cmd->se_cmd.se_tfo != NULL; if (!cmd->conn) { pr_err("cmd->conn is NULL for ITT: 0x%08x\n", @@ -863,7 +864,7 @@ static int iscsit_add_reject_from_cmd( * Perform the kref_put now if se_cmd has already been setup by * scsit_setup_scsi_cmd() */ - if (cmd->se_cmd.se_tfo != NULL) { + if (do_put) { pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); target_put_sess_cmd(&cmd->se_cmd); } -- GitLab From 6eaf69e4ec075f5af236c0c89f75639a195db904 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 31 Oct 2017 11:03:18 -0700 Subject: [PATCH 1623/2898] target/iscsi: Detect conn_cmd_list corruption early Certain behavior of the initiator can cause the target driver to send both a reject and a SCSI response. If that happens two target_put_sess_cmd() calls will occur without the command having been removed from conn_cmd_list. In other words, conn_cmd_list will get corrupted once the freed memory is reused. Although the Linux kernel can detect list corruption if list debugging is enabled, in this case the context in which list corruption is detected is not related to the context that caused list corruption. Hence add WARN_ON() statements that report the context that is causing list corruption. Signed-off-by: Bart Van Assche Cc: Christoph Hellwig Cc: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 1e36f83b5961..70c6b9bfc04e 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -694,6 +694,8 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd) struct iscsi_session *sess; struct se_cmd *se_cmd = &cmd->se_cmd; + WARN_ON(!list_empty(&cmd->i_conn_node)); + if (cmd->conn) sess = cmd->conn->sess; else @@ -716,6 +718,8 @@ void __iscsit_free_cmd(struct iscsi_cmd *cmd, bool check_queues) { struct iscsi_conn *conn = cmd->conn; + WARN_ON(!list_empty(&cmd->i_conn_node)); + if (cmd->data_direction == DMA_TO_DEVICE) { iscsit_stop_dataout_timer(cmd); iscsit_free_r2ts_from_list(cmd); -- GitLab From 0996b67df6c1354f2df09c33ac652c37e2e2471f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 27 Sep 2016 05:18:02 -0700 Subject: [PATCH 1624/2898] ecryptfs: add missing \n to end of various error messages Trival fix, some error messages are missing a \n, so add it. Signed-off-by: Colin Ian King Signed-off-by: Tyler Hicks --- fs/ecryptfs/keystore.c | 2 +- fs/ecryptfs/main.c | 2 +- fs/ecryptfs/miscdev.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index fa218cd64f74..3eb1420cd310 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1333,7 +1333,7 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, if ((*new_auth_tok)->session_key.encrypted_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { printk(KERN_WARNING "Tag 1 packet contains key larger " - "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES"); + "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n"); rc = -EINVAL; goto out; } diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 6b801186baa5..1a419c3b8d4f 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -426,7 +426,7 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options, mount_crypt_stat->global_default_cipher_key_size); if (!cipher_code) { ecryptfs_printk(KERN_ERR, - "eCryptfs doesn't support cipher: %s", + "eCryptfs doesn't support cipher: %s\n", mount_crypt_stat->global_default_cipher_name); rc = -EINVAL; goto out; diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index e4141f257495..595e684a95a5 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c @@ -383,7 +383,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, goto memdup; } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) { printk(KERN_WARNING "%s: Acceptable packet size range is " - "[%d-%zu], but amount of data written is [%zu].", + "[%d-%zu], but amount of data written is [%zu].\n", __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count); return -EINVAL; } -- GitLab From abbae6d560c1d562c5c0d10785469734784ef961 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 21 Sep 2016 01:17:24 +0200 Subject: [PATCH 1625/2898] ecryptfs: remove private bin2hex implementation Calling sprintf in a loop is not very efficient, and in any case, we already have an implementation of bin-to-hex conversion in lib/ which we might as well use. Note that ecryptfs_to_hex used to nul-terminate the destination (and the kernel doc was wrong about the required output size), while bin2hex doesn't. [All but one user of ecryptfs_to_hex explicitly nul-terminates the result anyway.] Signed-off-by: Rasmus Villemoes [tyhicks: Include in ecryptfs_kernel.h] Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 15 --------------- fs/ecryptfs/ecryptfs_kernel.h | 9 ++++++++- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index e5e29f8c920b..7acd57da4f14 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -41,21 +41,6 @@ #define DECRYPT 0 #define ENCRYPT 1 -/** - * ecryptfs_to_hex - * @dst: Buffer to take hex character representation of contents of - * src; must be at least of size (src_size * 2) - * @src: Buffer to be converted to a hex string representation - * @src_size: number of bytes to convert - */ -void ecryptfs_to_hex(char *dst, char *src, size_t src_size) -{ - int x; - - for (x = 0; x < src_size; x++) - sprintf(&dst[x * 2], "%.2x", (unsigned char)src[x]); -} - /** * ecryptfs_from_hex * @dst: Buffer to take the bytes from src hex; must be at least of diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 3fbc0ff79699..e74cb2a0b299 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -51,7 +52,13 @@ #define ECRYPTFS_XATTR_NAME "user.ecryptfs" void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok); -extern void ecryptfs_to_hex(char *dst, char *src, size_t src_size); +static inline void +ecryptfs_to_hex(char *dst, char *src, size_t src_size) +{ + char *end = bin2hex(dst, src, src_size); + *end = '\0'; +} + extern void ecryptfs_from_hex(char *dst, char *src, int dst_size); struct ecryptfs_key_record { -- GitLab From 17c45b90061a76fceadffbce8d85a9107a05a918 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 3 Nov 2017 22:20:38 +0100 Subject: [PATCH 1626/2898] iSCSI-target: Use common error handling code in iscsi_decode_text_input() Add a jump target so that a bit of exception handling can be better reused at the end of this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Nicholas Bellinger --- .../target/iscsi/iscsi_target_parameters.c | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index caab1045742d..29a37b242d30 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -1380,10 +1380,8 @@ int iscsi_decode_text_input( char *key, *value; struct iscsi_param *param; - if (iscsi_extract_key_value(start, &key, &value) < 0) { - kfree(tmpbuf); - return -1; - } + if (iscsi_extract_key_value(start, &key, &value) < 0) + goto free_buffer; pr_debug("Got key: %s=%s\n", key, value); @@ -1396,38 +1394,37 @@ int iscsi_decode_text_input( param = iscsi_check_key(key, phase, sender, param_list); if (!param) { - if (iscsi_add_notunderstood_response(key, - value, param_list) < 0) { - kfree(tmpbuf); - return -1; - } + if (iscsi_add_notunderstood_response(key, value, + param_list) < 0) + goto free_buffer; + start += strlen(key) + strlen(value) + 2; continue; } - if (iscsi_check_value(param, value) < 0) { - kfree(tmpbuf); - return -1; - } + if (iscsi_check_value(param, value) < 0) + goto free_buffer; start += strlen(key) + strlen(value) + 2; if (IS_PSTATE_PROPOSER(param)) { - if (iscsi_check_proposer_state(param, value) < 0) { - kfree(tmpbuf); - return -1; - } + if (iscsi_check_proposer_state(param, value) < 0) + goto free_buffer; + SET_PSTATE_RESPONSE_GOT(param); } else { - if (iscsi_check_acceptor_state(param, value, conn) < 0) { - kfree(tmpbuf); - return -1; - } + if (iscsi_check_acceptor_state(param, value, conn) < 0) + goto free_buffer; + SET_PSTATE_ACCEPTOR(param); } } kfree(tmpbuf); return 0; + +free_buffer: + kfree(tmpbuf); + return -1; } int iscsi_encode_text_output( -- GitLab From f6c8a317ab208aee223776327c06f23342492d54 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 1 Nov 2017 18:42:45 +0100 Subject: [PATCH 1627/2898] platform/x86: sony-laptop: Fix error handling in sony_nc_setup_rfkill() Source code review for a specific software refactoring showed the need for another correction because the error code "-1" was returned so far if a call of the function "sony_call_snc_handle" failed here. Thus assign the return value from these two function calls also to the variable "err" and provide it in case of a failure. Fixes: d6f15ed876b83a1a0eba1d0473eef58acc95444a ("sony-laptop: use soft rfkill status stored in hw") Suggested-by: Andy Shevchenko Link: https://lkml.org/lkml/2017/10/31/463 Link: https://lkml.kernel.org/r/ Signed-off-by: Markus Elfring Signed-off-by: Andy Shevchenko --- drivers/platform/x86/sony-laptop.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index a16cea2be9c3..4332cc982ce0 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1660,17 +1660,19 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, if (!rfk) return -ENOMEM; - if (sony_call_snc_handle(sony_rfkill_handle, 0x200, &result) < 0) { + err = sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); + if (err < 0) { rfkill_destroy(rfk); - return -1; + return err; } hwblock = !(result & 0x1); - if (sony_call_snc_handle(sony_rfkill_handle, - sony_rfkill_address[nc_type], - &result) < 0) { + err = sony_call_snc_handle(sony_rfkill_handle, + sony_rfkill_address[nc_type], + &result); + if (err < 0) { rfkill_destroy(rfk); - return -1; + return err; } swblock = !(result & 0x2); -- GitLab From e4a18052bb99e25d2c0074981120b76638285c22 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 1 Nov 2017 19:00:59 +0100 Subject: [PATCH 1628/2898] platform/x86: sony-laptop: Drop variable assignment in sony_nc_setup_rfkill() The local variable "err" will eventually be set to an appropriate value a bit later. Thus omit the explicit initialisation at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Andy Shevchenko --- drivers/platform/x86/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 4332cc982ce0..62aa2c37b8d2 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1627,7 +1627,7 @@ static const struct rfkill_ops sony_rfkill_ops = { static int sony_nc_setup_rfkill(struct acpi_device *device, enum sony_nc_rfkill nc_type) { - int err = 0; + int err; struct rfkill *rfk; enum rfkill_type type; const char *name; -- GitLab From fbc15e30400c9d927eda37445c78a7811a68e4a7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 4 Oct 2017 17:54:21 -0700 Subject: [PATCH 1629/2898] platform/x86: intel_ips: Convert timers to use timer_setup() In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly. Moves timer structure off stack and into struct ips_driver. Cc: Darren Hart Cc: Andy Shevchenko Cc: platform-driver-x86@vger.kernel.org Cc: Thomas Gleixner Signed-off-by: Kees Cook Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_ips.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 680ab4fd7087..a0c95853fd3f 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -296,6 +296,7 @@ struct ips_driver { struct task_struct *monitor; struct task_struct *adjust; struct dentry *debug_root; + struct timer_list timer; /* Average CPU core temps (all averages in .01 degrees C for precision) */ u16 ctv1_avg_temp; @@ -937,9 +938,10 @@ static u32 calc_avg_power(struct ips_driver *ips, u32 *array) return avg; } -static void monitor_timeout(unsigned long arg) +static void monitor_timeout(struct timer_list *t) { - wake_up_process((struct task_struct *)arg); + struct ips_driver *ips = from_timer(ips, t, timer); + wake_up_process(ips->monitor); } /** @@ -956,7 +958,6 @@ static void monitor_timeout(unsigned long arg) static int ips_monitor(void *data) { struct ips_driver *ips = data; - struct timer_list timer; unsigned long seqno_timestamp, expire, last_msecs, last_sample_period; int i; u32 *cpu_samples, *mchp_samples, old_cpu_power; @@ -1044,8 +1045,7 @@ static int ips_monitor(void *data) schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); last_sample_period = IPS_SAMPLE_PERIOD; - setup_deferrable_timer_on_stack(&timer, monitor_timeout, - (unsigned long)current); + timer_setup(&ips->timer, monitor_timeout, TIMER_DEFERRABLE); do { u32 cpu_val, mch_val; u16 val; @@ -1103,7 +1103,7 @@ static int ips_monitor(void *data) expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD); __set_current_state(TASK_INTERRUPTIBLE); - mod_timer(&timer, expire); + mod_timer(&ips->timer, expire); schedule(); /* Calculate actual sample period for power averaging */ @@ -1112,8 +1112,7 @@ static int ips_monitor(void *data) last_sample_period = 1; } while (!kthread_should_stop()); - del_timer_sync(&timer); - destroy_timer_on_stack(&timer); + del_timer_sync(&ips->timer); dev_dbg(ips->dev, "ips-monitor thread stopped\n"); -- GitLab From 9968e12a291e639dd51d1218b694d440b22a917f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Br=C3=BCns?= Date: Fri, 3 Nov 2017 03:01:53 +0100 Subject: [PATCH 1630/2898] platform/x86: hp-wmi: Fix tablet mode detection for convertibles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit f9cf3b2880cc ("platform/x86: hp-wmi: Refactor dock and tablet state fetchers") consolidated the methods for docking and laptop mode detection, but omitted to apply the correct mask for the laptop mode (it always uses the constant for docking). Fixes: f9cf3b2880cc ("platform/x86: hp-wmi: Refactor dock and tablet state fetchers") Signed-off-by: Stefan Brüns Signed-off-by: Andy Shevchenko --- drivers/platform/x86/hp-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index b4ed3dc983d5..b4224389febe 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -297,7 +297,7 @@ static int hp_wmi_hw_state(int mask) if (state < 0) return state; - return state & 0x1; + return !!(state & mask); } static int __init hp_wmi_bios_2008_later(void) -- GitLab From ce7ff1cffdaf82354aca5f4c8691e5c85474fbde Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 31 Oct 2017 11:03:18 +0000 Subject: [PATCH 1631/2898] platform/x86: dell-smo8800: remove redundant assignments to byte_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variable byte_data is being initialized and re-assigned with values that are never read. Remove these as these redundant assignments. Cleans up clang warning: drivers/platform/x86/dell-smo8800.c:106:2: warning: Value stored to 'byte_data' is never read Signed-off-by: Colin Ian King Acked-by: Pali Rohár Signed-off-by: Andy Shevchenko --- drivers/platform/x86/dell-smo8800.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c index 37e646034ef8..1d87237bc731 100644 --- a/drivers/platform/x86/dell-smo8800.c +++ b/drivers/platform/x86/dell-smo8800.c @@ -90,7 +90,7 @@ static ssize_t smo8800_misc_read(struct file *file, char __user *buf, struct smo8800_device, miscdev); u32 data = 0; - unsigned char byte_data = 0; + unsigned char byte_data; ssize_t retval = 1; if (count < 1) @@ -103,7 +103,6 @@ static ssize_t smo8800_misc_read(struct file *file, char __user *buf, if (retval) return retval; - byte_data = 1; retval = 1; if (data < 255) -- GitLab From 6cc8cbbc8868033f279b63e98b26b75eaa0006ab Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 29 Oct 2017 02:49:54 -0700 Subject: [PATCH 1632/2898] platform/x86: intel_punit_ipc: Fix resource ioremap warning For PUNIT device, ISPDRIVER_IPC and GTDDRIVER_IPC resources are not mandatory. So when PMC IPC driver creates a PUNIT device, if these resources are not available then it creates dummy resource entries for these missing resources. But during PUNIT device probe, doing ioremap on these dummy resources generates following warning messages. intel_punit_ipc: can't request region for resource [mem 0x00000000] intel_punit_ipc: can't request region for resource [mem 0x00000000] intel_punit_ipc: can't request region for resource [mem 0x00000000] intel_punit_ipc: can't request region for resource [mem 0x00000000] This patch fixes this issue by adding extra check for resource size before performing ioremap operation. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_punit_ipc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel_punit_ipc.c index a47a41fc10ad..b5b890127479 100644 --- a/drivers/platform/x86/intel_punit_ipc.c +++ b/drivers/platform/x86/intel_punit_ipc.c @@ -252,28 +252,28 @@ static int intel_punit_get_bars(struct platform_device *pdev) * - GTDRIVER_IPC BASE_IFACE */ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); - if (res) { + if (res && resource_size(res) > 1) { addr = devm_ioremap_resource(&pdev->dev, res); if (!IS_ERR(addr)) punit_ipcdev->base[ISPDRIVER_IPC][BASE_DATA] = addr; } res = platform_get_resource(pdev, IORESOURCE_MEM, 3); - if (res) { + if (res && resource_size(res) > 1) { addr = devm_ioremap_resource(&pdev->dev, res); if (!IS_ERR(addr)) punit_ipcdev->base[ISPDRIVER_IPC][BASE_IFACE] = addr; } res = platform_get_resource(pdev, IORESOURCE_MEM, 4); - if (res) { + if (res && resource_size(res) > 1) { addr = devm_ioremap_resource(&pdev->dev, res); if (!IS_ERR(addr)) punit_ipcdev->base[GTDRIVER_IPC][BASE_DATA] = addr; } res = platform_get_resource(pdev, IORESOURCE_MEM, 5); - if (res) { + if (res && resource_size(res) > 1) { addr = devm_ioremap_resource(&pdev->dev, res); if (!IS_ERR(addr)) punit_ipcdev->base[GTDRIVER_IPC][BASE_IFACE] = addr; -- GitLab From 43aaf4f03f063b12bcba2f8b800fdec85e2acc75 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 29 Oct 2017 02:49:55 -0700 Subject: [PATCH 1633/2898] platform/x86: intel_pmc_ipc: Use MFD framework to create dependent devices Currently, we have lot of repetitive code in dependent device resource allocation and device creation handling code. This logic can be improved if we use MFD framework for dependent device creation. This patch adds this support. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_pmc_ipc.c | 398 ++++++++++----------------- 1 file changed, 139 insertions(+), 259 deletions(-) diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index e03fa31446ca..e36144c337cd 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -88,6 +89,7 @@ #define PLAT_RESOURCE_ISP_IFACE_INDEX 5 #define PLAT_RESOURCE_GTD_DATA_INDEX 6 #define PLAT_RESOURCE_GTD_IFACE_INDEX 7 +#define PLAT_RESOURCE_MEM_MAX_INDEX 8 #define PLAT_RESOURCE_ACPI_IO_INDEX 0 /* @@ -106,8 +108,6 @@ #define TELEM_SSRAM_SIZE 240 #define TELEM_PMC_SSRAM_OFFSET 0x1B00 #define TELEM_PUNIT_SSRAM_OFFSET 0x1A00 -#define TCO_PMC_OFFSET 0x8 -#define TCO_PMC_SIZE 0x4 /* PMC register bit definitions */ @@ -124,26 +124,10 @@ static struct intel_pmc_ipc_dev { int cmd; struct completion cmd_complete; - /* The following PMC BARs share the same ACPI device with the IPC */ - resource_size_t acpi_io_base; - int acpi_io_size; - struct platform_device *tco_dev; - /* gcr */ void __iomem *gcr_mem_base; bool has_gcr_regs; spinlock_t gcr_lock; - - /* punit */ - struct platform_device *punit_dev; - - /* Telemetry */ - resource_size_t telem_pmc_ssram_base; - resource_size_t telem_punit_ssram_base; - int telem_pmc_ssram_size; - int telem_punit_ssram_size; - u8 telem_res_inval; - struct platform_device *telemetry_dev; } ipcdev; static char *ipc_err_sources[] = { @@ -508,7 +492,7 @@ static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc", pmc); if (ret) { - dev_err(&pdev->dev, "Failed to request irq\n"); + dev_err(&pdev->dev, "Failed to request IRQ\n"); return ret; } @@ -593,44 +577,6 @@ static const struct attribute_group intel_ipc_group = { .attrs = intel_ipc_attrs, }; -static struct resource punit_res_array[] = { - /* Punit BIOS */ - { - .flags = IORESOURCE_MEM, - }, - { - .flags = IORESOURCE_MEM, - }, - /* Punit ISP */ - { - .flags = IORESOURCE_MEM, - }, - { - .flags = IORESOURCE_MEM, - }, - /* Punit GTD */ - { - .flags = IORESOURCE_MEM, - }, - { - .flags = IORESOURCE_MEM, - }, -}; - -#define TCO_RESOURCE_ACPI_IO 0 -#define TCO_RESOURCE_SMI_EN_IO 1 -#define TCO_RESOURCE_GCR_MEM 2 -static struct resource tco_res[] = { - /* ACPI - TCO */ - { - .flags = IORESOURCE_IO, - }, - /* ACPI - SMI */ - { - .flags = IORESOURCE_IO, - }, -}; - static struct itco_wdt_platform_data tco_info = { .name = "Apollo Lake SoC", .version = 5, @@ -638,234 +584,177 @@ static struct itco_wdt_platform_data tco_info = { .update_no_reboot_bit = update_no_reboot_bit, }; -#define TELEMETRY_RESOURCE_PUNIT_SSRAM 0 -#define TELEMETRY_RESOURCE_PMC_SSRAM 1 -static struct resource telemetry_res[] = { - /*Telemetry*/ - { - .flags = IORESOURCE_MEM, - }, - { - .flags = IORESOURCE_MEM, - }, -}; - -static int ipc_create_punit_device(void) +static int ipc_create_punit_device(struct platform_device *pdev) { - struct platform_device *pdev; - const struct platform_device_info pdevinfo = { - .parent = ipcdev.dev, - .name = PUNIT_DEVICE_NAME, - .id = -1, - .res = punit_res_array, - .num_res = ARRAY_SIZE(punit_res_array), + struct resource punit_res[PLAT_RESOURCE_MEM_MAX_INDEX]; + struct mfd_cell punit_cell; + struct resource *res; + int mindex, pindex = 0; + + for (mindex = 0; mindex <= PLAT_RESOURCE_MEM_MAX_INDEX; mindex++) { + + res = platform_get_resource(pdev, IORESOURCE_MEM, mindex); + + switch (mindex) { + /* Get PUNIT resources */ + case PLAT_RESOURCE_BIOS_DATA_INDEX: + case PLAT_RESOURCE_BIOS_IFACE_INDEX: + /* BIOS resources are required, so return error if not + * available + */ + if (!res) { + dev_err(&pdev->dev, + "Failed to get PUNIT MEM resource %d\n", + pindex); + return -ENXIO; + } + case PLAT_RESOURCE_ISP_DATA_INDEX: + case PLAT_RESOURCE_ISP_IFACE_INDEX: + case PLAT_RESOURCE_GTD_DATA_INDEX: + case PLAT_RESOURCE_GTD_IFACE_INDEX: + /* if valid resource found, copy the resource to PUNIT + * resource + */ + if (res) + memcpy(&punit_res[pindex], res, sizeof(*res)); + punit_res[pindex].flags = IORESOURCE_MEM; + dev_dbg(&pdev->dev, "PUNIT memory res: %pR\n", + &punit_res[pindex]); + pindex++; + break; }; + } - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - - ipcdev.punit_dev = pdev; + /* Create PUNIT IPC MFD cell */ + punit_cell.name = PUNIT_DEVICE_NAME; + punit_cell.num_resources = ARRAY_SIZE(punit_res); + punit_cell.resources = punit_res; + punit_cell.ignore_resource_conflicts = 1; - return 0; + return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + &punit_cell, 1, NULL, 0, NULL); } -static int ipc_create_tco_device(void) +static int ipc_create_wdt_device(struct platform_device *pdev) { - struct platform_device *pdev; + static struct resource wdt_ipc_res[2]; struct resource *res; - const struct platform_device_info pdevinfo = { - .parent = ipcdev.dev, - .name = TCO_DEVICE_NAME, - .id = -1, - .res = tco_res, - .num_res = ARRAY_SIZE(tco_res), - .data = &tco_info, - .size_data = sizeof(tco_info), - }; + static struct mfd_cell wdt_cell; - res = tco_res + TCO_RESOURCE_ACPI_IO; - res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET; - res->end = res->start + TCO_REGS_SIZE - 1; + /* If we have ACPI based watchdog use that instead, othewise create + * a MFD cell for iTCO watchdog + */ + if (acpi_has_watchdog()) + return 0; - res = tco_res + TCO_RESOURCE_SMI_EN_IO; - res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET; - res->end = res->start + SMI_EN_SIZE - 1; + /* Get iTCO watchdog resources */ + res = platform_get_resource(pdev, IORESOURCE_IO, + PLAT_RESOURCE_ACPI_IO_INDEX); + if (!res) { + dev_err(&pdev->dev, "Failed to get WDT resource\n"); + return -ENXIO; + } - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); + wdt_ipc_res[0].start = res->start + TCO_BASE_OFFSET; + wdt_ipc_res[0].end = res->start + + TCO_BASE_OFFSET + TCO_REGS_SIZE - 1; + wdt_ipc_res[0].flags = IORESOURCE_IO; + wdt_ipc_res[1].start = res->start + SMI_EN_OFFSET; + wdt_ipc_res[1].end = res->start + + SMI_EN_OFFSET + SMI_EN_SIZE - 1; + wdt_ipc_res[1].flags = IORESOURCE_IO; - ipcdev.tco_dev = pdev; + dev_dbg(&pdev->dev, "watchdog res 0: %pR\n", &wdt_ipc_res[0]); + dev_dbg(&pdev->dev, "watchdog res 1: %pR\n", &wdt_ipc_res[1]); - return 0; + wdt_cell.name = TCO_DEVICE_NAME; + wdt_cell.platform_data = &tco_info; + wdt_cell.pdata_size = sizeof(tco_info); + wdt_cell.num_resources = ARRAY_SIZE(wdt_ipc_res); + wdt_cell.resources = wdt_ipc_res; + wdt_cell.ignore_resource_conflicts = 1; + + return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + &wdt_cell, 1, NULL, 0, NULL); } -static int ipc_create_telemetry_device(void) +static int ipc_create_telemetry_device(struct platform_device *pdev) { - struct platform_device *pdev; + struct resource telemetry_ipc_res[2]; + struct mfd_cell telemetry_cell; struct resource *res; - const struct platform_device_info pdevinfo = { - .parent = ipcdev.dev, - .name = TELEMETRY_DEVICE_NAME, - .id = -1, - .res = telemetry_res, - .num_res = ARRAY_SIZE(telemetry_res), - }; - res = telemetry_res + TELEMETRY_RESOURCE_PUNIT_SSRAM; - res->start = ipcdev.telem_punit_ssram_base; - res->end = res->start + ipcdev.telem_punit_ssram_size - 1; + /* Get telemetry resources */ + res = platform_get_resource(pdev, IORESOURCE_MEM, + PLAT_RESOURCE_TELEM_SSRAM_INDEX); + if (!res) { + dev_err(&pdev->dev, "Failed to get telemetry resource\n"); + return -ENXIO; + } - res = telemetry_res + TELEMETRY_RESOURCE_PMC_SSRAM; - res->start = ipcdev.telem_pmc_ssram_base; - res->end = res->start + ipcdev.telem_pmc_ssram_size - 1; + telemetry_ipc_res[0].start = res->start + TELEM_PUNIT_SSRAM_OFFSET; + telemetry_ipc_res[0].end = res->start + + TELEM_PUNIT_SSRAM_OFFSET + TELEM_SSRAM_SIZE - 1; + telemetry_ipc_res[0].flags = IORESOURCE_MEM; + telemetry_ipc_res[1].start = res->start + TELEM_PMC_SSRAM_OFFSET; + telemetry_ipc_res[1].end = res->start + + TELEM_PMC_SSRAM_OFFSET + TELEM_SSRAM_SIZE - 1; + telemetry_ipc_res[1].flags = IORESOURCE_MEM; - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); + dev_dbg(&pdev->dev, "Telemetry res 0: %pR\n", &telemetry_ipc_res[0]); + dev_dbg(&pdev->dev, "Telemetry res 1: %pR\n", &telemetry_ipc_res[1]); - ipcdev.telemetry_dev = pdev; + telemetry_cell.name = TELEMETRY_DEVICE_NAME; + telemetry_cell.num_resources = ARRAY_SIZE(telemetry_ipc_res); + telemetry_cell.resources = telemetry_ipc_res; + telemetry_cell.ignore_resource_conflicts = 1; - return 0; + return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + &telemetry_cell, 1, NULL, 0, NULL); } -static int ipc_create_pmc_devices(void) +static int ipc_create_pmc_devices(struct platform_device *pdev) { int ret; - /* If we have ACPI based watchdog use that instead */ - if (!acpi_has_watchdog()) { - ret = ipc_create_tco_device(); - if (ret) { - dev_err(ipcdev.dev, "Failed to add tco platform device\n"); - return ret; - } - } + ret = ipc_create_punit_device(pdev); + if (ret < 0) + return ret; - ret = ipc_create_punit_device(); - if (ret) { - dev_err(ipcdev.dev, "Failed to add punit platform device\n"); - platform_device_unregister(ipcdev.tco_dev); - } + ret = ipc_create_wdt_device(pdev); + if (ret < 0) + return ret; - if (!ipcdev.telem_res_inval) { - ret = ipc_create_telemetry_device(); - if (ret) - dev_warn(ipcdev.dev, - "Failed to add telemetry platform device\n"); - } + ret = ipc_create_telemetry_device(pdev); + if (ret < 0) + return ret; - return ret; + return 0; } static int ipc_plat_get_res(struct platform_device *pdev) { - struct resource *res, *punit_res; + struct resource *res; void __iomem *addr; - int size; - - res = platform_get_resource(pdev, IORESOURCE_IO, - PLAT_RESOURCE_ACPI_IO_INDEX); - if (!res) { - dev_err(&pdev->dev, "Failed to get io resource\n"); - return -ENXIO; - } - size = resource_size(res); - ipcdev.acpi_io_base = res->start; - ipcdev.acpi_io_size = size; - dev_info(&pdev->dev, "io res: %pR\n", res); - - punit_res = punit_res_array; - /* This is index 0 to cover BIOS data register */ - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_BIOS_DATA_INDEX); - if (!res) { - dev_err(&pdev->dev, "Failed to get res of punit BIOS data\n"); - return -ENXIO; - } - *punit_res = *res; - dev_info(&pdev->dev, "punit BIOS data res: %pR\n", res); - - /* This is index 1 to cover BIOS interface register */ - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_BIOS_IFACE_INDEX); - if (!res) { - dev_err(&pdev->dev, "Failed to get res of punit BIOS iface\n"); - return -ENXIO; - } - *++punit_res = *res; - dev_info(&pdev->dev, "punit BIOS interface res: %pR\n", res); - - /* This is index 2 to cover ISP data register, optional */ - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_ISP_DATA_INDEX); - ++punit_res; - if (res) { - *punit_res = *res; - dev_info(&pdev->dev, "punit ISP data res: %pR\n", res); - } - - /* This is index 3 to cover ISP interface register, optional */ - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_ISP_IFACE_INDEX); - ++punit_res; - if (res) { - *punit_res = *res; - dev_info(&pdev->dev, "punit ISP interface res: %pR\n", res); - } - - /* This is index 4 to cover GTD data register, optional */ - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_GTD_DATA_INDEX); - ++punit_res; - if (res) { - *punit_res = *res; - dev_info(&pdev->dev, "punit GTD data res: %pR\n", res); - } - - /* This is index 5 to cover GTD interface register, optional */ - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_GTD_IFACE_INDEX); - ++punit_res; - if (res) { - *punit_res = *res; - dev_info(&pdev->dev, "punit GTD interface res: %pR\n", res); - } + /* Get IPC resources */ res = platform_get_resource(pdev, IORESOURCE_MEM, PLAT_RESOURCE_IPC_INDEX); if (!res) { - dev_err(&pdev->dev, "Failed to get ipc resource\n"); + dev_err(&pdev->dev, "Failed to get IPC resources\n"); return -ENXIO; } - size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE; - res->end = res->start + size - 1; + + res->end = res->start + + PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE - 1; addr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(addr)) return PTR_ERR(addr); ipcdev.ipc_base = addr; - ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; - dev_info(&pdev->dev, "ipc res: %pR\n", res); - - ipcdev.telem_res_inval = 0; - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_TELEM_SSRAM_INDEX); - if (!res) { - dev_err(&pdev->dev, "Failed to get telemetry ssram resource\n"); - ipcdev.telem_res_inval = 1; - } else { - ipcdev.telem_punit_ssram_base = res->start + - TELEM_PUNIT_SSRAM_OFFSET; - ipcdev.telem_punit_ssram_size = TELEM_SSRAM_SIZE; - ipcdev.telem_pmc_ssram_base = res->start + - TELEM_PMC_SSRAM_OFFSET; - ipcdev.telem_pmc_ssram_size = TELEM_SSRAM_SIZE; - dev_info(&pdev->dev, "telemetry ssram res: %pR\n", res); - } + dev_dbg(&pdev->dev, "PMC IPC resource %pR\n", res); return 0; } @@ -911,7 +800,7 @@ static int ipc_plat_probe(struct platform_device *pdev) ipcdev.irq = platform_get_irq(pdev, 0); if (ipcdev.irq < 0) { - dev_err(&pdev->dev, "Failed to get irq\n"); + dev_err(&pdev->dev, "Failed to get IRQ\n"); return -EINVAL; } @@ -921,47 +810,38 @@ static int ipc_plat_probe(struct platform_device *pdev) return ret; } - ret = ipc_create_pmc_devices(); + ret = ipc_create_pmc_devices(pdev); if (ret) { - dev_err(&pdev->dev, "Failed to create pmc devices\n"); + dev_err(&pdev->dev, "Failed to create PMC devices\n"); return ret; } - if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND, - "intel_pmc_ipc", &ipcdev)) { - dev_err(&pdev->dev, "Failed to request irq\n"); - ret = -EBUSY; - goto err_irq; + ret = devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND, + "intel_pmc_ipc", &ipcdev); + if (ret) { + dev_err(&pdev->dev, "Failed to request IRQ\n"); + return ret; } ret = sysfs_create_group(&pdev->dev.kobj, &intel_ipc_group); if (ret) { dev_err(&pdev->dev, "Failed to create sysfs group %d\n", ret); - goto err_sys; + devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); + return ret; } ipcdev.has_gcr_regs = true; return 0; -err_sys: - devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); -err_irq: - platform_device_unregister(ipcdev.tco_dev); - platform_device_unregister(ipcdev.punit_dev); - platform_device_unregister(ipcdev.telemetry_dev); - - return ret; } static int ipc_plat_remove(struct platform_device *pdev) { sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group); devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); - platform_device_unregister(ipcdev.tco_dev); - platform_device_unregister(ipcdev.punit_dev); - platform_device_unregister(ipcdev.telemetry_dev); ipcdev.dev = NULL; + return 0; } @@ -980,12 +860,12 @@ static int __init intel_pmc_ipc_init(void) ret = platform_driver_register(&ipc_plat_driver); if (ret) { - pr_err("Failed to register PMC ipc platform driver\n"); + pr_err("Failed to register PMC IPC platform driver\n"); return ret; } ret = pci_register_driver(&ipc_pci_driver); if (ret) { - pr_err("Failed to register PMC ipc pci driver\n"); + pr_err("Failed to register PMC IPC PCI driver\n"); platform_driver_unregister(&ipc_plat_driver); return ret; } -- GitLab From 684e73bee4b5ef626a017c101a20f91cf28a75e6 Mon Sep 17 00:00:00 2001 From: Hirofumi Nakagawa Date: Tue, 26 Sep 2017 03:21:26 +0900 Subject: [PATCH 1634/2898] vfs: remove unneeded unlikely() IS_ERR() macro it is already including unlikely(). Signed-off-by: Hirofumi Nakagawa Signed-off-by: Al Viro --- fs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index c75ea03ca147..00384488fda1 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3458,7 +3458,7 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags, goto out; child = vfs_tmpfile(path.dentry, op->mode, op->open_flag); error = PTR_ERR(child); - if (unlikely(IS_ERR(child))) + if (IS_ERR(child)) goto out2; dput(path.dentry); path.dentry = child; -- GitLab From dfd6fa39d96f5049edb7af26578873e65dbafc9a Mon Sep 17 00:00:00 2001 From: Hirofumi Nakagawa Date: Tue, 26 Sep 2017 03:21:27 +0900 Subject: [PATCH 1635/2898] pstore: remove unneeded unlikely() IS_ERR() macro it is already including unlikely(). Signed-off-by: Hirofumi Nakagawa Signed-off-by: Al Viro --- fs/pstore/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 2b21d180157c..7256149af306 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -654,7 +654,7 @@ static int pstore_write_user_compat(struct pstore_record *record, return -EINVAL; record->buf = memdup_user(buf, record->size); - if (unlikely(IS_ERR(record->buf))) { + if (IS_ERR(record->buf)) { ret = PTR_ERR(record->buf); goto out; } -- GitLab From d337b66a4c52c7b04eec661d86c2ef6e168965a2 Mon Sep 17 00:00:00 2001 From: Jan Harkes Date: Wed, 27 Sep 2017 15:52:12 -0400 Subject: [PATCH 1636/2898] coda: fix 'kernel memory exposure attempt' in fsync When an application called fsync on a file in Coda a small request with just the file identifier was allocated, but the declared length was set to the size of union of all possible upcall requests. This bug has been around for a very long time and is now caught by the extra checking in usercopy that was introduced in Linux-4.8. The exposure happens when the Coda cache manager process reads the fsync upcall request at which point it is killed. As a result there is nobody servicing any further upcalls, trapping any processes that try to access the mounted Coda filesystem. Cc: stable@vger.kernel.org Signed-off-by: Jan Harkes Signed-off-by: Al Viro --- fs/coda/upcall.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index e82357c89979..8cf16d8c5261 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -446,8 +446,7 @@ int venus_fsync(struct super_block *sb, struct CodaFid *fid) UPARG(CODA_FSYNC); inp->coda_fsync.VFid = *fid; - error = coda_upcall(coda_vcp(sb), sizeof(union inputArgs), - &outsize, inp); + error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); CODA_FREE(inp, insize); return error; -- GitLab From ceac204e1da942a634d3bb0db3e959edc78e47c7 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 29 Sep 2017 15:24:06 -0400 Subject: [PATCH 1637/2898] fs: make fiemap work from compat_ioctl We don't need to do anything special with fiemap to make it work with a 64bit kernel from 32bit userspace, so just go down to do_vfs_ioctl(). Without this patch we were incorrectly failing to do fiemap with a 32bit userspace on a 64bit kernel. Signed-off-by: Josef Bacik Reviewed-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/compat_ioctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index d27b326d96f4..480f9366b4e3 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1579,6 +1579,7 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, case FICLONE: case FICLONERANGE: case FIDEDUPERANGE: + case FS_IOC_FIEMAP: goto do_ioctl; case FIBMAP: -- GitLab From 63dcb81e5b9e1faadf4b55450141bc4446e5a3d3 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 3 Oct 2017 08:53:07 +0300 Subject: [PATCH 1638/2898] include/linux/fs.h: fix comment about struct address_space Before commit 9c5d760b8d22 ("mm: split gfp_mask and mapping flags into separate fields") the private_* fields of struct adrress_space were grouped together and using "ditto" in comments describing the last fields was correct. With introduction of gpf_mask between private_lock and private_list "ditto" references the wrong description. Fix it by using the elaborate description. Signed-off-by: Mike Rapoport Signed-off-by: Al Viro --- include/linux/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 31f8b2ea358c..ccbac0ed672c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -403,7 +403,7 @@ struct address_space { unsigned long flags; /* error bits */ spinlock_t private_lock; /* for use by the address_space */ gfp_t gfp_mask; /* implicit gfp mask for allocations */ - struct list_head private_list; /* ditto */ + struct list_head private_list; /* for use by the address_space */ void *private_data; /* ditto */ errseq_t wb_err; } __attribute__((aligned(sizeof(long)))) __randomize_layout; -- GitLab From 5297908270549b734c7c2556745e2385b6d4941d Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Tue, 3 Oct 2017 12:58:14 +0200 Subject: [PATCH 1639/2898] vfs: stop clearing close on exec when closing a fd Codepaths allocating a fd always make sure the bit is set/unset depending on flags, thus clearing on close is redundant. Signed-off-by: Mateusz Guzik Signed-off-by: Al Viro --- fs/file.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/file.c b/fs/file.c index 1fc7fbbb4510..9d047bd046b0 100644 --- a/fs/file.c +++ b/fs/file.c @@ -631,7 +631,6 @@ int __close_fd(struct files_struct *files, unsigned fd) if (!file) goto out_unlock; rcu_assign_pointer(fdt->fd[fd], NULL); - __clear_close_on_exec(fd, fdt); __put_unused_fd(files, fd); spin_unlock(&files->file_lock); return filp_close(file, files); -- GitLab From c02b1a9b41c2e728289f96850580a3651e0a8b5f Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Tue, 3 Oct 2017 12:58:15 +0200 Subject: [PATCH 1640/2898] vfs: grab the lock instead of blocking in __fd_install during resizing Explicit locking in the fallback case provides a safe state of the table. Getting rid of blocking semantics makes __fd_install usable again in non-sleepable contexts, which easies backporting efforts. There is a side effect of slightly nicer assembly for the common case as might_sleep can now be removed. Signed-off-by: Mateusz Guzik Signed-off-by: Al Viro --- Documentation/filesystems/porting | 4 ---- fs/file.c | 11 +++++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 93e0a2404532..17bb4dc28fae 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -501,10 +501,6 @@ in your dentry operations instead. is non-NULL. Note that link body isn't available anymore, so if you need it, store it as cookie. -- -[mandatory] - __fd_install() & fd_install() can now sleep. Callers should not - hold a spinlock or other resources that do not allow a schedule. --- [mandatory] any symlink that might use page_follow_link_light/page_put_link() must have inode_nohighmem(inode) called before anything might start playing with diff --git a/fs/file.c b/fs/file.c index 9d047bd046b0..4115503bb575 100644 --- a/fs/file.c +++ b/fs/file.c @@ -592,13 +592,16 @@ void __fd_install(struct files_struct *files, unsigned int fd, { struct fdtable *fdt; - might_sleep(); rcu_read_lock_sched(); - while (unlikely(files->resize_in_progress)) { + if (unlikely(files->resize_in_progress)) { rcu_read_unlock_sched(); - wait_event(files->resize_wait, !files->resize_in_progress); - rcu_read_lock_sched(); + spin_lock(&files->file_lock); + fdt = files_fdtable(files); + BUG_ON(fdt->fd[fd] != NULL); + rcu_assign_pointer(fdt->fd[fd], file); + spin_unlock(&files->file_lock); + return; } /* coupled with smp_wmb() in expand_fdtable() */ smp_rmb(); -- GitLab From 2412405b3141cfe943d05a28a2160187d45f1c9a Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Fri, 27 Oct 2017 15:28:31 +0100 Subject: [PATCH 1641/2898] KVM: arm/arm64: register irq bypass consumer on ARM/ARM64 This patch selects IRQ_BYPASS_MANAGER and HAVE_KVM_IRQ_BYPASS configs for ARM/ARM64. kvm_arch_has_irq_bypass() now is implemented and returns true. As a consequence the irq bypass consumer will be registered for ARM/ARM64 with the forwarding callbacks: - stop/start: halt/resume guest execution - add/del_producer: set/unset forwarding at vgic/irqchip level We don't have any actual support yet, so nothing gets actually forwarded. Acked-by: Christoffer Dall Signed-off-by: Eric Auger [maz: dropped the DEOI stuff for the time being in order to reduce the dependency chain, amended commit message] Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm/kvm/Kconfig | 3 +++ arch/arm64/kvm/Kconfig | 3 +++ virt/kvm/arm/arm.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig index 90d0176fb30d..4e2b192a030a 100644 --- a/arch/arm/kvm/Kconfig +++ b/arch/arm/kvm/Kconfig @@ -3,6 +3,7 @@ # source "virt/kvm/Kconfig" +source "virt/lib/Kconfig" menuconfig VIRTUALIZATION bool "Virtualization" @@ -35,6 +36,8 @@ config KVM select HAVE_KVM_IRQCHIP select HAVE_KVM_IRQ_ROUTING select HAVE_KVM_MSI + select IRQ_BYPASS_MANAGER + select HAVE_KVM_IRQ_BYPASS depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER ---help--- Support hosting virtualized guest machines. diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 52cb7ad9b2fd..7e0d6e63cc71 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -3,6 +3,7 @@ # source "virt/kvm/Kconfig" +source "virt/lib/Kconfig" menuconfig VIRTUALIZATION bool "Virtualization" @@ -35,6 +36,8 @@ config KVM select HAVE_KVM_MSI select HAVE_KVM_IRQCHIP select HAVE_KVM_IRQ_ROUTING + select IRQ_BYPASS_MANAGER + select HAVE_KVM_IRQ_BYPASS ---help--- Support hosting virtualized guest machines. We don't support KVM with 16K page tables yet, due to the multiple diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index bc126fb99a3d..79f8ddd604c1 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -1458,6 +1460,44 @@ struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr) return NULL; } +bool kvm_arch_has_irq_bypass(void) +{ + return true; +} + +int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons, + struct irq_bypass_producer *prod) +{ + struct kvm_kernel_irqfd *irqfd = + container_of(cons, struct kvm_kernel_irqfd, consumer); + + return 0; +} +void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons, + struct irq_bypass_producer *prod) +{ + struct kvm_kernel_irqfd *irqfd = + container_of(cons, struct kvm_kernel_irqfd, consumer); + + return; +} + +void kvm_arch_irq_bypass_stop(struct irq_bypass_consumer *cons) +{ + struct kvm_kernel_irqfd *irqfd = + container_of(cons, struct kvm_kernel_irqfd, consumer); + + kvm_arm_halt_guest(irqfd->kvm); +} + +void kvm_arch_irq_bypass_start(struct irq_bypass_consumer *cons) +{ + struct kvm_kernel_irqfd *irqfd = + container_of(cons, struct kvm_kernel_irqfd, consumer); + + kvm_arm_resume_guest(irqfd->kvm); +} + /** * Initialize Hyp-mode and memory mappings on all CPUs. */ -- GitLab From 47bbd31f740c4e693d01766f367ad3366fb49a6d Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Fri, 27 Oct 2017 15:28:32 +0100 Subject: [PATCH 1642/2898] KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq We want to reuse the core of the map/unmap functions for IRQ forwarding. Let's move the computation of the hwirq in kvm_vgic_map_phys_irq and pass the linux IRQ as parameter. the host_irq is added to struct vgic_irq. We introduce kvm_vgic_map/unmap_irq which take a struct vgic_irq handle as a parameter. Acked-by: Christoffer Dall Signed-off-by: Eric Auger Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- include/kvm/arm_vgic.h | 8 ++++-- virt/kvm/arm/arch_timer.c | 24 +--------------- virt/kvm/arm/vgic/vgic.c | 60 +++++++++++++++++++++++++++++---------- 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 34dba516ef24..53f631bdec75 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -116,6 +116,7 @@ struct vgic_irq { bool hw; /* Tied to HW IRQ */ struct kref refcount; /* Used for LPIs */ u32 hwintid; /* HW INTID number */ + unsigned int host_irq; /* linux irq corresponding to hwintid */ union { u8 targets; /* GICv2 target VCPUs mask */ u32 mpidr; /* GICv3 target VCPU */ @@ -307,9 +308,10 @@ void kvm_vgic_init_cpu_hardware(void); int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid, bool level, void *owner); -int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq); -int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq); -bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq); +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq, + u32 vintid); +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid); +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid); int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu); diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 4db54ff08d9e..4151250ce8da 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -817,9 +817,6 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); - struct irq_desc *desc; - struct irq_data *data; - int phys_irq; int ret; if (timer->enabled) @@ -837,26 +834,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) return -EINVAL; } - /* - * Find the physical IRQ number corresponding to the host_vtimer_irq - */ - desc = irq_to_desc(host_vtimer_irq); - if (!desc) { - kvm_err("%s: no interrupt descriptor\n", __func__); - return -EINVAL; - } - - data = irq_desc_get_irq_data(desc); - while (data->parent_data) - data = data->parent_data; - - phys_irq = data->hwirq; - - /* - * Tell the VGIC that the virtual interrupt is tied to a - * physical interrupt. We do that once per VCPU. - */ - ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq); + ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq); if (ret) return ret; diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index e54ef2fdf73d..a05a5700910b 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "vgic.h" @@ -409,25 +411,56 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid, return 0; } -int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq) +/* @irq->irq_lock must be held */ +static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq, + unsigned int host_irq) { - struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq); + struct irq_desc *desc; + struct irq_data *data; + + /* + * Find the physical IRQ number corresponding to @host_irq + */ + desc = irq_to_desc(host_irq); + if (!desc) { + kvm_err("%s: no interrupt descriptor\n", __func__); + return -EINVAL; + } + data = irq_desc_get_irq_data(desc); + while (data->parent_data) + data = data->parent_data; + + irq->hw = true; + irq->host_irq = host_irq; + irq->hwintid = data->hwirq; + return 0; +} + +/* @irq->irq_lock must be held */ +static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq) +{ + irq->hw = false; + irq->hwintid = 0; +} + +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq, + u32 vintid) +{ + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid); unsigned long flags; + int ret; BUG_ON(!irq); spin_lock_irqsave(&irq->irq_lock, flags); - - irq->hw = true; - irq->hwintid = phys_irq; - + ret = kvm_vgic_map_irq(vcpu, irq, host_irq); spin_unlock_irqrestore(&irq->irq_lock, flags); vgic_put_irq(vcpu->kvm, irq); - return 0; + return ret; } -int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq) +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid) { struct vgic_irq *irq; unsigned long flags; @@ -435,14 +468,11 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq) if (!vgic_initialized(vcpu->kvm)) return -EAGAIN; - irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq); + irq = vgic_get_irq(vcpu->kvm, vcpu, vintid); BUG_ON(!irq); spin_lock_irqsave(&irq->irq_lock, flags); - - irq->hw = false; - irq->hwintid = 0; - + kvm_vgic_unmap_irq(irq); spin_unlock_irqrestore(&irq->irq_lock, flags); vgic_put_irq(vcpu->kvm, irq); @@ -784,9 +814,9 @@ void vgic_kick_vcpus(struct kvm *kvm) } } -bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq) +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid) { - struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq); + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid); bool map_is_active; unsigned long flags; -- GitLab From 7129a9d8a6f352e93647264a495281f789a87aa0 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Oct 2017 15:28:33 +0100 Subject: [PATCH 1643/2898] KVM: arm: Select ARM_GIC_V3 and ARM_GIC_V3_ITS The GICv4 support introduces a hard dependency between the KVM core and the ITS infrastructure. arm64 already selects it at the architecture level, but 32bit doesn't. In order to avoid littering the kernel with #ifdefs, let's just select the whole of the GICv3 suport code. You know you want it. Acked-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- arch/arm/kvm/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig index 4e2b192a030a..52b50af04e3b 100644 --- a/arch/arm/kvm/Kconfig +++ b/arch/arm/kvm/Kconfig @@ -23,6 +23,8 @@ config KVM select PREEMPT_NOTIFIERS select ANON_INODES select ARM_GIC + select ARM_GIC_V3 + select ARM_GIC_V3_ITS select HAVE_KVM_CPU_RELAX_INTERCEPT select HAVE_KVM_ARCH_TLB_FLUSH_ALL select KVM_MMIO -- GitLab From b2c9a85dd75a8cfa18da94b19e84eb0199011187 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Oct 2017 15:28:34 +0100 Subject: [PATCH 1644/2898] KVM: arm/arm64: vgic: Move kvm_vgic_destroy call around The way we call kvm_vgic_destroy is a bit bizarre. We call it *after* having freed the vcpus, which sort of defeats the point of cleaning up things before that point. Let's move kvm_vgic_destroy towards the beginning of kvm_arch_destroy_vm, which seems more sensible. Acked-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall --- virt/kvm/arm/arm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index 79f8ddd604c1..e1e947fe9bc2 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -177,6 +177,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm) { int i; + kvm_vgic_destroy(kvm); + free_percpu(kvm->arch.last_vcpu_ran); kvm->arch.last_vcpu_ran = NULL; @@ -186,8 +188,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm) kvm->vcpus[i] = NULL; } } - - kvm_vgic_destroy(kvm); } int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) -- GitLab From db86be3a12d0b6e5c5b51c2ab2a48f06329cb590 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 22 Aug 2017 23:41:28 +0300 Subject: [PATCH 1645/2898] eCryptfs: use after free in ecryptfs_release_messaging() We're freeing the list iterator so we should be using the _safe() version of hlist_for_each_entry(). Fixes: 88b4a07e6610 ("[PATCH] eCryptfs: Public key transport mechanism") Signed-off-by: Dan Carpenter Cc: Signed-off-by: Tyler Hicks --- fs/ecryptfs/messaging.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 286f10b0363b..4f457d5c4933 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c @@ -442,15 +442,16 @@ void ecryptfs_release_messaging(void) } if (ecryptfs_daemon_hash) { struct ecryptfs_daemon *daemon; + struct hlist_node *n; int i; mutex_lock(&ecryptfs_daemon_hash_mux); for (i = 0; i < (1 << ecryptfs_hash_bits); i++) { int rc; - hlist_for_each_entry(daemon, - &ecryptfs_daemon_hash[i], - euid_chain) { + hlist_for_each_entry_safe(daemon, n, + &ecryptfs_daemon_hash[i], + euid_chain) { rc = ecryptfs_exorcise_daemon(daemon); if (rc) printk(KERN_ERR "%s: Error whilst " -- GitLab From 1a0bba4ff086d73a88f9dbadaf4831aefce55f27 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 19 Aug 2017 17:37:30 +0200 Subject: [PATCH 1646/2898] ecryptfs: Delete 21 error messages for a failed memory allocation Omit extra messages for a memory allocation failure in these functions. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 16 ---------------- fs/ecryptfs/inode.c | 3 --- fs/ecryptfs/keystore.c | 33 ++++++--------------------------- fs/ecryptfs/messaging.c | 6 ------ fs/ecryptfs/miscdev.c | 6 +----- fs/ecryptfs/mmap.c | 2 -- 6 files changed, 7 insertions(+), 59 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 7acd57da4f14..4a7ef33d4d79 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1419,8 +1419,6 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) page_virt = kmem_cache_alloc(ecryptfs_header_cache, GFP_USER); if (!page_virt) { rc = -ENOMEM; - printk(KERN_ERR "%s: Unable to allocate page_virt\n", - __func__); goto out; } rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size, @@ -1507,9 +1505,6 @@ ecryptfs_encrypt_filename(struct ecryptfs_filename *filename, filename->encrypted_filename = kmalloc(filename->encrypted_filename_size, GFP_KERNEL); if (!filename->encrypted_filename) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kmalloc [%zd] bytes\n", __func__, - filename->encrypted_filename_size); rc = -ENOMEM; goto out; } @@ -1658,8 +1653,6 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, (*key_tfm) = tmp_tfm; if (!tmp_tfm) { rc = -ENOMEM; - printk(KERN_ERR "Error attempting to allocate from " - "ecryptfs_key_tfm_cache\n"); goto out; } mutex_init(&tmp_tfm->key_tfm_mutex); @@ -1934,9 +1927,6 @@ int ecryptfs_encrypt_and_encode_filename( filename = kzalloc(sizeof(*filename), GFP_KERNEL); if (!filename) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kzalloc [%zd] bytes\n", __func__, - sizeof(*filename)); rc = -ENOMEM; goto out; } @@ -1965,9 +1955,6 @@ int ecryptfs_encrypt_and_encode_filename( + encoded_name_no_prefix_size); (*encoded_name) = kmalloc((*encoded_name_size) + 1, GFP_KERNEL); if (!(*encoded_name)) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kzalloc [%zd] bytes\n", __func__, - (*encoded_name_size)); rc = -ENOMEM; kfree(filename->encrypted_filename); kfree(filename); @@ -2049,9 +2036,6 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name, name, name_size); decoded_name = kmalloc(decoded_name_size, GFP_KERNEL); if (!decoded_name) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kmalloc [%zd] bytes\n", __func__, - decoded_name_size); rc = -ENOMEM; goto out; } diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index efc2db42d175..93ed19ac770f 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -334,9 +334,6 @@ static struct dentry *ecryptfs_lookup_interpose(struct dentry *dentry, dentry_info = kmem_cache_alloc(ecryptfs_dentry_info_cache, GFP_KERNEL); if (!dentry_info) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to allocate ecryptfs_dentry_info struct\n", - __func__); dput(lower_dentry); return ERR_PTR(-ENOMEM); } diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 3eb1420cd310..540952dacb1a 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -639,11 +639,9 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, int rc = 0; s = kzalloc(sizeof(*s), GFP_KERNEL); - if (!s) { - printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " - "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); + if (!s) return -ENOMEM; - } + (*packet_size) = 0; rc = ecryptfs_find_auth_tok_for_sig( &auth_tok_key, @@ -714,9 +712,6 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, s->block_aligned_filename = kzalloc(s->block_aligned_filename_size, GFP_KERNEL); if (!s->block_aligned_filename) { - printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " - "kzalloc [%zd] bytes\n", __func__, - s->block_aligned_filename_size); rc = -ENOMEM; goto out_unlock; } @@ -769,10 +764,6 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, s->hash_desc = kmalloc(sizeof(*s->hash_desc) + crypto_shash_descsize(s->hash_tfm), GFP_KERNEL); if (!s->hash_desc) { - printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " - "kmalloc [%zd] bytes\n", __func__, - sizeof(*s->hash_desc) + - crypto_shash_descsize(s->hash_tfm)); rc = -ENOMEM; goto out_release_free_unlock; } @@ -925,11 +916,9 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, (*filename_size) = 0; (*filename) = NULL; s = kzalloc(sizeof(*s), GFP_KERNEL); - if (!s) { - printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " - "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); + if (!s) return -ENOMEM; - } + if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) { printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be " "at least [%d]\n", __func__, max_packet_size, @@ -1015,9 +1004,6 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, s->decrypted_filename = kmalloc(s->block_aligned_filename_size, GFP_KERNEL); if (!s->decrypted_filename) { - printk(KERN_ERR "%s: Out of memory whilst attempting to " - "kmalloc [%zd] bytes\n", __func__, - s->block_aligned_filename_size); rc = -ENOMEM; goto out_unlock; } @@ -1097,9 +1083,6 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, } (*filename) = kmalloc(((*filename_size) + 1), GFP_KERNEL); if (!(*filename)) { - printk(KERN_ERR "%s: Out of memory whilst attempting to " - "kmalloc [%zd] bytes\n", __func__, - ((*filename_size) + 1)); rc = -ENOMEM; goto out_free_unlock; } @@ -2525,11 +2508,9 @@ int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig) struct ecryptfs_key_sig *new_key_sig; new_key_sig = kmem_cache_alloc(ecryptfs_key_sig_cache, GFP_KERNEL); - if (!new_key_sig) { - printk(KERN_ERR - "Error allocating from ecryptfs_key_sig_cache\n"); + if (!new_key_sig) return -ENOMEM; - } + memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX); new_key_sig->keysig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; /* Caller must hold keysig_list_mutex */ @@ -2551,8 +2532,6 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, GFP_KERNEL); if (!new_auth_tok) { rc = -ENOMEM; - printk(KERN_ERR "Error allocating from " - "ecryptfs_global_auth_tok_cache\n"); goto out; } memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX); diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 4f457d5c4933..9fdd5bcf4564 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c @@ -147,8 +147,6 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file) (*daemon) = kzalloc(sizeof(**daemon), GFP_KERNEL); if (!(*daemon)) { rc = -ENOMEM; - printk(KERN_ERR "%s: Failed to allocate [%zd] bytes of " - "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); goto out; } (*daemon)->file = file; @@ -250,8 +248,6 @@ int ecryptfs_process_response(struct ecryptfs_daemon *daemon, msg_ctx->msg = kmemdup(msg, msg_size, GFP_KERNEL); if (!msg_ctx->msg) { rc = -ENOMEM; - printk(KERN_ERR "%s: Failed to allocate [%zd] bytes of " - "GFP_KERNEL memory\n", __func__, msg_size); goto unlock; } msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; @@ -386,7 +382,6 @@ int __init ecryptfs_init_messaging(void) GFP_KERNEL); if (!ecryptfs_daemon_hash) { rc = -ENOMEM; - printk(KERN_ERR "%s: Failed to allocate memory\n", __func__); mutex_unlock(&ecryptfs_daemon_hash_mux); goto out; } @@ -398,7 +393,6 @@ int __init ecryptfs_init_messaging(void) GFP_KERNEL); if (!ecryptfs_msg_ctx_arr) { rc = -ENOMEM; - printk(KERN_ERR "%s: Failed to allocate memory\n", __func__); goto out; } mutex_init(&ecryptfs_msg_ctx_lists_mux); diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index 595e684a95a5..f09cacaf8c80 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c @@ -163,12 +163,8 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, struct ecryptfs_message *msg; msg = kmalloc((sizeof(*msg) + data_size), GFP_KERNEL); - if (!msg) { - printk(KERN_ERR "%s: Out of memory whilst attempting " - "to kmalloc(%zd, GFP_KERNEL)\n", __func__, - (sizeof(*msg) + data_size)); + if (!msg) return -ENOMEM; - } mutex_lock(&msg_ctx->mux); msg_ctx->msg = msg; diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 1f0c471b4ba3..cdf358b209d9 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -431,8 +431,6 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode) } xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL); if (!xattr_virt) { - printk(KERN_ERR "Out of memory whilst attempting to write " - "inode size to xattr\n"); rc = -ENOMEM; goto out; } -- GitLab From a463ce5bbd99fef6e1012cebe7b6764794ec07d8 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 19 Aug 2017 17:51:53 +0200 Subject: [PATCH 1647/2898] ecryptfs: Return an error code only as a constant in ecryptfs_add_global_auth_tok() * Return an error code without storing it in an intermediate variable. * Delete the jump target "out" and the local variable "rc" which became unnecessary with this refactoring. Signed-off-by: Markus Elfring Signed-off-by: Tyler Hicks --- fs/ecryptfs/keystore.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 540952dacb1a..492d6a2823db 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -2526,14 +2526,12 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig, u32 global_auth_tok_flags) { struct ecryptfs_global_auth_tok *new_auth_tok; - int rc = 0; new_auth_tok = kmem_cache_zalloc(ecryptfs_global_auth_tok_cache, GFP_KERNEL); - if (!new_auth_tok) { - rc = -ENOMEM; - goto out; - } + if (!new_auth_tok) + return -ENOMEM; + memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX); new_auth_tok->flags = global_auth_tok_flags; new_auth_tok->sig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; @@ -2541,7 +2539,6 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, list_add(&new_auth_tok->mount_crypt_stat_list, &mount_crypt_stat->global_auth_tok_list); mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); -out: - return rc; + return 0; } -- GitLab From 5032f360dd31e6cf59aadad0478df1244bfd30f8 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 19 Aug 2017 18:00:22 +0200 Subject: [PATCH 1648/2898] ecryptfs: Adjust four checks for null pointers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The script “checkpatch.pl” pointed information out like the following. Comparison to NULL could be written … Thus fix the affected source code places. Signed-off-by: Markus Elfring Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 6 +++--- fs/ecryptfs/keystore.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 4a7ef33d4d79..1cd0902bc936 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1649,7 +1649,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, BUG_ON(!mutex_is_locked(&key_tfm_list_mutex)); tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL); - if (key_tfm != NULL) + if (key_tfm) (*key_tfm) = tmp_tfm; if (!tmp_tfm) { rc = -ENOMEM; @@ -1668,7 +1668,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, "cipher with name = [%s]; rc = [%d]\n", tmp_tfm->cipher_name, rc); kmem_cache_free(ecryptfs_key_tfm_cache, tmp_tfm); - if (key_tfm != NULL) + if (key_tfm) (*key_tfm) = NULL; goto out; } @@ -1859,7 +1859,7 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, size_t src_byte_offset = 0; size_t dst_byte_offset = 0; - if (dst == NULL) { + if (!dst) { (*dst_size) = ecryptfs_max_decoded_size(src_size); goto out; } diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 492d6a2823db..c89a58cfc991 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -685,7 +685,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, * separator, and then the filename */ s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE + s->block_aligned_filename_size); - if (dest == NULL) { + if (!dest) { (*packet_size) = s->max_packet_size; goto out_unlock; } -- GitLab From 02f9876ebb5e9cd31013c62b8839508b2dc152f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Lefaure?= Date: Sun, 1 Oct 2017 15:30:46 -0400 Subject: [PATCH 1649/2898] ecryptfs: use ARRAY_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the ARRAY_SIZE macro improves the readability of the code. Found with Coccinelle with the following semantic patch: @r depends on (org || report)@ type T; T[] E; position p; @@ ( (sizeof(E)@p /sizeof(*E)) | (sizeof(E)@p /sizeof(E[...])) | (sizeof(E)@p /sizeof(T)) ) Signed-off-by: Jérémy Lefaure Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 1cd0902bc936..846ca150d52e 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "ecryptfs_kernel.h" #define DECRYPT 0 @@ -884,8 +885,7 @@ static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat, u32 flags; flags = get_unaligned_be32(page_virt); - for (i = 0; i < ((sizeof(ecryptfs_flag_map) - / sizeof(struct ecryptfs_flag_map_elem))); i++) + for (i = 0; i < ARRAY_SIZE(ecryptfs_flag_map); i++) if (flags & ecryptfs_flag_map[i].file_flag) { crypt_stat->flags |= ecryptfs_flag_map[i].local_flag; } else @@ -922,8 +922,7 @@ void ecryptfs_write_crypt_stat_flags(char *page_virt, u32 flags = 0; int i; - for (i = 0; i < ((sizeof(ecryptfs_flag_map) - / sizeof(struct ecryptfs_flag_map_elem))); i++) + for (i = 0; i < ARRAY_SIZE(ecryptfs_flag_map); i++) if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag) flags |= ecryptfs_flag_map[i].file_flag; /* Version is in top 8 bits of the 32-bit flag vector */ -- GitLab From 0695a3c744d851cc75d19cea9e63bc2f7dde836f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 30 Oct 2017 11:01:31 -0400 Subject: [PATCH 1650/2898] ecryptfs: remove unnecessary i_version bump There is no need to bump the i_version counter here, as ecryptfs does not set the SB_I_VERSION flag, and doesn't use it internally. It also only bumps it when the inode is instantiated, which doesn't make much sense. Signed-off-by: Jeff Layton Signed-off-by: Tyler Hicks --- fs/ecryptfs/inode.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 93ed19ac770f..847904aa63a9 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -64,7 +64,6 @@ static int ecryptfs_inode_set(struct inode *inode, void *opaque) /* i_size will be overwritten for encrypted regular files */ fsstack_copy_inode_size(inode, lower_inode); inode->i_ino = lower_inode->i_ino; - inode->i_version++; inode->i_mapping->a_ops = &ecryptfs_aops; if (S_ISLNK(inode->i_mode)) -- GitLab From 92d44128241f8aa129cf2f3672786a1b52053510 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 6 Nov 2017 10:55:51 -0800 Subject: [PATCH 1651/2898] ARCv2: Accomodate HS48 MMUv5 by relaxing MMU ver checking HS48 cpus will have a new MMUv5, although Linux is currently not explicitly supporting the newer features (so remains at V4). The existing software/hardware version check is very tight and causes boot abort. Given that the MMUv5 hardware is backwards compatible, relax the boot check to allow current kernel support level to work with new hardware. Also while at it, move the ancient MMU related code to under ARCompact builds as baseline MMU for HS cpus is v4. Signed-off-by: Vineet Gupta --- arch/arc/mm/tlb.c | 57 +++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 8ceefbf72fb0..4097764fea23 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -762,21 +762,23 @@ void read_decode_mmu_bcr(void) tmp = read_aux_reg(ARC_REG_MMU_BCR); mmu->ver = (tmp >> 24); - if (mmu->ver <= 2) { - mmu2 = (struct bcr_mmu_1_2 *)&tmp; - mmu->pg_sz_k = TO_KB(0x2000); - mmu->sets = 1 << mmu2->sets; - mmu->ways = 1 << mmu2->ways; - mmu->u_dtlb = mmu2->u_dtlb; - mmu->u_itlb = mmu2->u_itlb; - } else if (mmu->ver == 3) { - mmu3 = (struct bcr_mmu_3 *)&tmp; - mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1); - mmu->sets = 1 << mmu3->sets; - mmu->ways = 1 << mmu3->ways; - mmu->u_dtlb = mmu3->u_dtlb; - mmu->u_itlb = mmu3->u_itlb; - mmu->sasid = mmu3->sasid; + if (is_isa_arcompact()) { + if (mmu->ver <= 2) { + mmu2 = (struct bcr_mmu_1_2 *)&tmp; + mmu->pg_sz_k = TO_KB(0x2000); + mmu->sets = 1 << mmu2->sets; + mmu->ways = 1 << mmu2->ways; + mmu->u_dtlb = mmu2->u_dtlb; + mmu->u_itlb = mmu2->u_itlb; + } else { + mmu3 = (struct bcr_mmu_3 *)&tmp; + mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1); + mmu->sets = 1 << mmu3->sets; + mmu->ways = 1 << mmu3->ways; + mmu->u_dtlb = mmu3->u_dtlb; + mmu->u_itlb = mmu3->u_itlb; + mmu->sasid = mmu3->sasid; + } } else { mmu4 = (struct bcr_mmu_4 *)&tmp; mmu->pg_sz_k = 1 << (mmu4->sz0 - 1); @@ -818,8 +820,9 @@ int pae40_exist_but_not_enab(void) void arc_mmu_init(void) { - char str[256]; struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; + char str[256]; + int compat = 0; pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str))); @@ -834,15 +837,21 @@ void arc_mmu_init(void) */ BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE)); - /* For efficiency sake, kernel is compile time built for a MMU ver - * This must match the hardware it is running on. - * Linux built for MMU V2, if run on MMU V1 will break down because V1 - * hardware doesn't understand cmds such as WriteNI, or IVUTLB - * On the other hand, Linux built for V1 if run on MMU V2 will do - * un-needed workarounds to prevent memcpy thrashing. - * Similarly MMU V3 has new features which won't work on older MMU + /* + * Ensure that MMU features assumed by kernel exist in hardware. + * For older ARC700 cpus, it has to be exact match, since the MMU + * revisions were not backwards compatible (MMUv3 TLB layout changed + * so even if kernel for v2 didn't use any new cmds of v3, it would + * still not work. + * For HS cpus, MMUv4 was baseline and v5 is backwards compatible + * (will run older software). */ - if (mmu->ver != CONFIG_ARC_MMU_VER) { + if (is_isa_arcompact() && mmu->ver == CONFIG_ARC_MMU_VER) + compat = 1; + else if (is_isa_arcv2() && mmu->ver >= CONFIG_ARC_MMU_VER) + compat = 1; + + if (!compat) { panic("MMU ver %d doesn't match kernel built for %d...\n", mmu->ver, CONFIG_ARC_MMU_VER); } -- GitLab From 2e442aebed99fd27eaa4e3539d9c50ef1cc67013 Mon Sep 17 00:00:00 2001 From: Anton Vasilyev Date: Tue, 22 Aug 2017 16:24:11 +0300 Subject: [PATCH 1652/2898] mtd: plat-ram: Replace manual resource management by devm Driver contains unsuitable request_mem_region() and release_resource() calls. The patch switches manual resource management by devm interface for readability and error-free simplification. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Anton Vasilyev Suggested-by: Boris Brezillon Signed-off-by: Richard Weinberger --- drivers/mtd/maps/plat-ram.c | 38 ++++--------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 51572895c02c..6d9a4d6f9839 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c @@ -43,7 +43,6 @@ struct platram_info { struct device *dev; struct mtd_info *mtd; struct map_info map; - struct resource *area; struct platdata_mtd_ram *pdata; }; @@ -97,16 +96,6 @@ static int platram_remove(struct platform_device *pdev) platram_setrw(info, PLATRAM_RO); - /* release resources */ - - if (info->area) { - release_resource(info->area); - kfree(info->area); - } - - if (info->map.virt != NULL) - iounmap(info->map.virt); - kfree(info); return 0; @@ -147,12 +136,11 @@ static int platram_probe(struct platform_device *pdev) info->pdata = pdata; /* get the resource for the memory mapping */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (res == NULL) { - dev_err(&pdev->dev, "no memory resource specified\n"); - err = -ENOENT; + info->map.virt = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(info->map.virt)) { + err = PTR_ERR(info->map.virt); + dev_err(&pdev->dev, "failed to ioremap() region\n"); goto exit_free; } @@ -167,26 +155,8 @@ static int platram_probe(struct platform_device *pdev) (char *)pdata->mapname : (char *)pdev->name; info->map.bankwidth = pdata->bankwidth; - /* register our usage of the memory area */ - - info->area = request_mem_region(res->start, info->map.size, pdev->name); - if (info->area == NULL) { - dev_err(&pdev->dev, "failed to request memory region\n"); - err = -EIO; - goto exit_free; - } - - /* remap the memory area */ - - info->map.virt = ioremap(res->start, info->map.size); dev_dbg(&pdev->dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size); - if (info->map.virt == NULL) { - dev_err(&pdev->dev, "failed to ioremap() region\n"); - err = -EIO; - goto exit_free; - } - simple_map_init(&info->map); dev_dbg(&pdev->dev, "initialised map, probing for mtd\n"); -- GitLab From d4906688d49150eb77ddc9baafc3ea14bc158f03 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 28 Aug 2017 13:54:57 +0530 Subject: [PATCH 1653/2898] mtd: constify mtd_partition mtd_partition are not supposed to change at runtime. Functions 'mtd_device_parse_register' working with const mtd_partition provided by . So mark the non-const structs as const. Signed-off-by: Arvind Yadav Signed-off-by: Richard Weinberger --- drivers/mtd/devices/lart.c | 2 +- drivers/mtd/maps/cfi_flagadm.c | 2 +- drivers/mtd/maps/impa7.c | 2 +- drivers/mtd/maps/netsc520.c | 2 +- drivers/mtd/maps/nettel.c | 2 +- drivers/mtd/maps/sbc_gxx.c | 2 +- drivers/mtd/maps/ts5500_flash.c | 2 +- drivers/mtd/maps/uclinux.c | 2 +- drivers/mtd/nand/ams-delta.c | 2 +- drivers/mtd/nand/cmx270_nand.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index 268aae45b514..555b94406e0b 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c @@ -583,7 +583,7 @@ static struct mtd_erase_region_info erase_regions[] = { } }; -static struct mtd_partition lart_partitions[] = { +static const struct mtd_partition lart_partitions[] = { /* blob */ { .name = "blob", diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index d504b3d1791d..70f488628464 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c @@ -61,7 +61,7 @@ static struct map_info flagadm_map = { .bankwidth = 2, }; -static struct mtd_partition flagadm_parts[] = { +static const struct mtd_partition flagadm_parts[] = { { .name = "Bootloader", .offset = FLASH_PARTITION0_ADDR, diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c index 15bbda03be65..a0b8fa7849a9 100644 --- a/drivers/mtd/maps/impa7.c +++ b/drivers/mtd/maps/impa7.c @@ -47,7 +47,7 @@ static struct map_info impa7_map[NUM_FLASHBANKS] = { /* * MTD partitioning stuff */ -static struct mtd_partition partitions[] = +static const struct mtd_partition partitions[] = { { .name = "FileSystem", diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c index 81dc2598bc0a..3528497f96c7 100644 --- a/drivers/mtd/maps/netsc520.c +++ b/drivers/mtd/maps/netsc520.c @@ -52,7 +52,7 @@ /* partition_info gives details on the logical partitions that the split the * single flash device into. If the size if zero we use up to the end of the * device. */ -static struct mtd_partition partition_info[]={ +static const struct mtd_partition partition_info[] = { { .name = "NetSc520 boot kernel", .offset = 0, diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index a577ef8553d0..729579fb654f 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c @@ -107,7 +107,7 @@ static struct map_info nettel_amd_map = { .bankwidth = AMD_BUSWIDTH, }; -static struct mtd_partition nettel_amd_partitions[] = { +static const struct mtd_partition nettel_amd_partitions[] = { { .name = "SnapGear BIOS config", .offset = 0x000e0000, diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c index 556a2dfe94c5..4337d279ad83 100644 --- a/drivers/mtd/maps/sbc_gxx.c +++ b/drivers/mtd/maps/sbc_gxx.c @@ -87,7 +87,7 @@ static DEFINE_SPINLOCK(sbc_gxx_spin); /* partition_info gives details on the logical partitions that the split the * single flash device into. If the size if zero we use up to the end of the * device. */ -static struct mtd_partition partition_info[]={ +static const struct mtd_partition partition_info[] = { { .name = "SBC-GXx flash boot partition", .offset = 0, .size = BOOT_PARTITION_SIZE_KiB*1024 }, diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index 9969fedb1f13..8f177e0acb8c 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c @@ -43,7 +43,7 @@ static struct map_info ts5500_map = { .phys = WINDOW_ADDR }; -static struct mtd_partition ts5500_partitions[] = { +static const struct mtd_partition ts5500_partitions[] = { { .name = "Drive A", .offset = 0, diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index 00a8190797ec..aef030ca8601 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -49,7 +49,7 @@ static struct mtd_info *uclinux_ram_mtdinfo; /****************************************************************************/ -static struct mtd_partition uclinux_romfs[] = { +static const struct mtd_partition uclinux_romfs[] = { { .name = "ROMfs" } }; diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index dcec9cf4983f..d60ada45c549 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -41,7 +41,7 @@ static struct mtd_info *ams_delta_mtd = NULL; * Define partitions for flash devices */ -static struct mtd_partition partition_info[] = { +static const struct mtd_partition partition_info[] = { { .name = "Kernel", .offset = 0, .size = 3 * SZ_1M + SZ_512K }, diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index 1fc435f994e1..b01c9804590e 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c @@ -42,7 +42,7 @@ static void __iomem *cmx270_nand_io; /* * Define static partitions for flash device */ -static struct mtd_partition partition_info[] = { +static const struct mtd_partition partition_info[] = { [0] = { .name = "cmx270-0", .offset = 0, -- GitLab From 971e4aeeaa126b207d1e85eec6dc6e29bead316e Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sat, 23 Sep 2017 22:13:14 +0200 Subject: [PATCH 1654/2898] mtd: Fix C++ comment in include/linux/mtd/mtd.h C++ comments look wrong in kernel tree. Fix one. Signed-off-by: Pavel Machek Acked-by: Boris Brezillon Signed-off-by: Richard Weinberger --- include/linux/mtd/mtd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 6cd0f6b7658b..849543f1f233 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -267,7 +267,7 @@ struct mtd_info { */ unsigned int bitflip_threshold; - // Kernel-only stuff starts here. + /* Kernel-only stuff starts here. */ const char *name; int index; -- GitLab From bdd8edb9b0cd552f09a81c32d699af041155a390 Mon Sep 17 00:00:00 2001 From: Loic Pallardy Date: Mon, 6 Nov 2017 18:09:55 +0100 Subject: [PATCH 1655/2898] remoteproc: debug: add resource table dump feature This patch adds the capability to display the content of the resource table associated to a remote processor firmware. Signed-off-by: Loic Pallardy Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_debugfs.c | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 1c122e230cec..dc5e25943df7 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -155,6 +155,103 @@ static const struct file_operations rproc_recovery_ops = { .llseek = generic_file_llseek, }; +/* Expose resource table content via debugfs */ +static int rproc_rsc_table_show(struct seq_file *seq, void *p) +{ + static const char * const types[] = {"carveout", "devmem", "trace", "vdev"}; + struct rproc *rproc = seq->private; + struct resource_table *table = rproc->table_ptr; + struct fw_rsc_carveout *c; + struct fw_rsc_devmem *d; + struct fw_rsc_trace *t; + struct fw_rsc_vdev *v; + int i, j; + + if (!table) { + seq_puts(seq, "No resource table found\n"); + return 0; + } + + for (i = 0; i < table->num; i++) { + int offset = table->offset[i]; + struct fw_rsc_hdr *hdr = (void *)table + offset; + void *rsc = (void *)hdr + sizeof(*hdr); + + switch (hdr->type) { + case RSC_CARVEOUT: + c = rsc; + seq_printf(seq, "Entry %d is of type %s\n", i, types[hdr->type]); + seq_printf(seq, " Device Address 0x%x\n", c->da); + seq_printf(seq, " Physical Address 0x%x\n", c->pa); + seq_printf(seq, " Length 0x%x Bytes\n", c->len); + seq_printf(seq, " Flags 0x%x\n", c->flags); + seq_printf(seq, " Reserved (should be zero) [%d]\n", c->reserved); + seq_printf(seq, " Name %s\n\n", c->name); + break; + case RSC_DEVMEM: + d = rsc; + seq_printf(seq, "Entry %d is of type %s\n", i, types[hdr->type]); + seq_printf(seq, " Device Address 0x%x\n", d->da); + seq_printf(seq, " Physical Address 0x%x\n", d->pa); + seq_printf(seq, " Length 0x%x Bytes\n", d->len); + seq_printf(seq, " Flags 0x%x\n", d->flags); + seq_printf(seq, " Reserved (should be zero) [%d]\n", d->reserved); + seq_printf(seq, " Name %s\n\n", d->name); + break; + case RSC_TRACE: + t = rsc; + seq_printf(seq, "Entry %d is of type %s\n", i, types[hdr->type]); + seq_printf(seq, " Device Address 0x%x\n", t->da); + seq_printf(seq, " Length 0x%x Bytes\n", t->len); + seq_printf(seq, " Reserved (should be zero) [%d]\n", t->reserved); + seq_printf(seq, " Name %s\n\n", t->name); + break; + case RSC_VDEV: + v = rsc; + seq_printf(seq, "Entry %d is of type %s\n", i, types[hdr->type]); + + seq_printf(seq, " ID %d\n", v->id); + seq_printf(seq, " Notify ID %d\n", v->notifyid); + seq_printf(seq, " Device features 0x%x\n", v->dfeatures); + seq_printf(seq, " Guest features 0x%x\n", v->gfeatures); + seq_printf(seq, " Config length 0x%x\n", v->config_len); + seq_printf(seq, " Status 0x%x\n", v->status); + seq_printf(seq, " Number of vrings %d\n", v->num_of_vrings); + seq_printf(seq, " Reserved (should be zero) [%d][%d]\n\n", + v->reserved[0], v->reserved[1]); + + for (j = 0; j < v->num_of_vrings; j++) { + seq_printf(seq, " Vring %d\n", j); + seq_printf(seq, " Device Address 0x%x\n", v->vring[j].da); + seq_printf(seq, " Alignment %d\n", v->vring[j].align); + seq_printf(seq, " Number of buffers %d\n", v->vring[j].num); + seq_printf(seq, " Notify ID %d\n", v->vring[j].notifyid); + seq_printf(seq, " Physical Address 0x%x\n\n", + v->vring[j].pa); + } + break; + default: + seq_printf(seq, "Unknown resource type found: %d [hdr: %p]\n", + hdr->type, hdr); + break; + } + } + + return 0; +} + +static int rproc_rsc_table_open(struct inode *inode, struct file *file) +{ + return single_open(file, rproc_rsc_table_show, inode->i_private); +} + +static const struct file_operations rproc_rsc_table_ops = { + .open = rproc_rsc_table_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + void rproc_remove_trace_file(struct dentry *tfile) { debugfs_remove(tfile); @@ -198,6 +295,8 @@ void rproc_create_debug_dir(struct rproc *rproc) rproc, &rproc_name_ops); debugfs_create_file("recovery", 0400, rproc->dbg_dir, rproc, &rproc_recovery_ops); + debugfs_create_file("resource_table", 0400, rproc->dbg_dir, + rproc, &rproc_rsc_table_ops); } void __init rproc_init_debugfs(void) -- GitLab From b89188394164a5df4bd649380f75ec74e6b8a4d3 Mon Sep 17 00:00:00 2001 From: Loic Pallardy Date: Mon, 6 Nov 2017 18:09:56 +0100 Subject: [PATCH 1656/2898] remoteproc: debug: add carveouts list dump feature This patch offers the capability to dump memory carveouts associated to one remoteprocessor. Signed-off-by: Loic Pallardy Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_debugfs.c | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index dc5e25943df7..a20488336aa0 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -252,6 +252,35 @@ static const struct file_operations rproc_rsc_table_ops = { .release = single_release, }; +/* Expose carveout content via debugfs */ +static int rproc_carveouts_show(struct seq_file *seq, void *p) +{ + struct rproc *rproc = seq->private; + struct rproc_mem_entry *carveout; + + list_for_each_entry(carveout, &rproc->carveouts, node) { + seq_puts(seq, "Carveout memory entry:\n"); + seq_printf(seq, "\tVirtual address: %p\n", carveout->va); + seq_printf(seq, "\tDMA address: %pad\n", &carveout->dma); + seq_printf(seq, "\tDevice address: 0x%x\n", carveout->da); + seq_printf(seq, "\tLength: 0x%x Bytes\n\n", carveout->len); + } + + return 0; +} + +static int rproc_carveouts_open(struct inode *inode, struct file *file) +{ + return single_open(file, rproc_carveouts_show, inode->i_private); +} + +static const struct file_operations rproc_carveouts_ops = { + .open = rproc_carveouts_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + void rproc_remove_trace_file(struct dentry *tfile) { debugfs_remove(tfile); @@ -297,6 +326,8 @@ void rproc_create_debug_dir(struct rproc *rproc) rproc, &rproc_recovery_ops); debugfs_create_file("resource_table", 0400, rproc->dbg_dir, rproc, &rproc_rsc_table_ops); + debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir, + rproc, &rproc_carveouts_ops); } void __init rproc_init_debugfs(void) -- GitLab From d048236dfdfe454f059a0837431c3ae3d166d4d6 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Sat, 4 Nov 2017 14:37:48 +0800 Subject: [PATCH 1657/2898] hwspinlock: Change hwspinlock to a bool Change hwspinlock to a bool in case some drivers will meet dependency issue when hwspinlock is built as a module. Signed-off-by: Baolin Wang Signed-off-by: Bjorn Andersson --- drivers/hwspinlock/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig index 6e0a5539a9ea..f0f467983960 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig @@ -3,7 +3,7 @@ # menuconfig HWSPINLOCK - tristate "Hardware Spinlock drivers" + bool "Hardware Spinlock drivers" config HWSPINLOCK_OMAP tristate "OMAP Hardware Spinlock device" -- GitLab From 9f2a4342a8bf24c644204311f0cf154f78489b53 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 6 Nov 2017 22:26:41 -0800 Subject: [PATCH 1658/2898] remoteproc: qcom: Drop pr_err in q6v5_xfer_mem_ownership() The pr_err() in q6v5_xfer_mem_ownership() prints, upon failure, the memory range that failed to be transitioned. But on 32-bit architectures with CONFIG_PHYS_ADDR_T_64BIT set we cannot cast the phys_addr_t variable to a pointer, per below build error. Instead these should be formatted with %pap. In file included from include/linux/kernel.h:14:0, from include/linux/clk.h:16, from drivers/remoteproc/qcom_q6v5_pil.c:18: drivers/remoteproc/qcom_q6v5_pil.c: In function 'q6v5_xfer_mem_ownership': drivers/remoteproc/qcom_q6v5_pil.c:337:10: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] (void *)addr, (void *)(addr + size), ^ Most callers will upon failure print a specific error message describing which memory region that we failed to pass ownership of, so rather than fixing the format string this patch fixes up the last callers and drop the print from this function, saving us from spamming the log in most of these error cases. Fixes: 6c5a9dc2481b ("remoteproc: qcom: Make secure world call for mem ownership switch") Reported-by: Arnd Bergmann Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pil.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 5460f61ee21c..a019796c363a 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -318,7 +318,6 @@ static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm, size_t size) { struct qcom_scm_vmperm next; - int ret; if (!qproc->need_mem_protection) return 0; @@ -330,16 +329,8 @@ static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm, next.vmid = remote_owner ? QCOM_SCM_VMID_MSS_MSA : QCOM_SCM_VMID_HLOS; next.perm = remote_owner ? QCOM_SCM_PERM_RW : QCOM_SCM_PERM_RWX; - ret = qcom_scm_assign_mem(addr, ALIGN(size, SZ_4K), - current_perm, &next, 1); - if (ret < 0) { - pr_err("Failed to assign memory access in range %p to %p to %s ret = %d\n", - (void *)addr, (void *)(addr + size), - remote_owner ? "mss" : "hlos", ret); - return ret; - } - - return 0; + return qcom_scm_assign_mem(addr, ALIGN(size, SZ_4K), + current_perm, &next, 1); } static int q6v5_load(struct rproc *rproc, const struct firmware *fw) @@ -586,8 +577,11 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) mdata_perm = BIT(QCOM_SCM_VMID_HLOS); ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, true, phys, fw->size); - if (ret) + if (ret) { + dev_err(qproc->dev, + "assigning Q6 access to metadata failed: %d\n", ret); return -EAGAIN; + } writel(phys, qproc->rmb_base + RMB_PMI_META_DATA_REG); writel(RMB_CMD_META_DATA_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG); @@ -715,8 +709,11 @@ static int q6v5_mpss_load(struct q6v5 *qproc) /* Transfer ownership of modem ddr region to q6 */ ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, true, qproc->mpss_phys, qproc->mpss_size); - if (ret) + if (ret) { + dev_err(qproc->dev, + "assigning Q6 access to mpss memory failed: %d\n", ret); return -EAGAIN; + } boot_addr = relocate ? qproc->mpss_phys : min_addr; writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG); @@ -778,8 +775,12 @@ static int q6v5_start(struct rproc *rproc) xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true, qproc->mba_phys, qproc->mba_size); - if (xfermemop_ret) + if (xfermemop_ret) { + dev_err(qproc->dev, + "assigning Q6 access to mba memory failed: %d\n", + xfermemop_ret); goto disable_active_clks; + } writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG); -- GitLab From d0c2e691d1cbe43662df3a08a4933f13acc352c3 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 6 Nov 2017 07:17:37 -0600 Subject: [PATCH 1659/2898] objtool: Add a comment for the unreachable annotation macros Add a comment for the unreachable annotation macros to explain their purpose and the '__COUNTER__' label hack. Suggested-by: Linus Torvalds Signed-off-by: Josh Poimboeuf Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1570e48d9f87e0fc6f0126c32e7e1de6e109cb67.1509974104.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- include/linux/compiler.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 202710420d6d..f8734fca54ce 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -187,6 +187,11 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, /* Unreachable code */ #ifdef CONFIG_STACK_VALIDATION +/* + * These macros help objtool understand GCC code flow for unreachable code. + * The __COUNTER__ based labels are a hack to make each instance of the macros + * unique, to convince GCC not to merge duplicate inline asm statements. + */ #define annotate_reachable() ({ \ asm("%c0:\n\t" \ ".pushsection .discard.reachable\n\t" \ -- GitLab From 10259821ac47dbefa6f83ae57f1fa9f1f2c54b3d Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 6 Nov 2017 07:17:38 -0600 Subject: [PATCH 1660/2898] objtool: Make unreachable annotation inline asms explicitly volatile Add 'volatile' to the unreachable annotation macro inline asm statements. They're already implicitly volatile because they don't have output constraints, but it's clearer and more robust to make them explicitly volatile. Suggested-by: Linus Torvalds Signed-off-by: Josh Poimboeuf Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/28659257b7a6adf4a7f65920dad70b2b0226e996.1509974104.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- include/linux/compiler.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index f8734fca54ce..4fac29cdffd1 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -193,16 +193,16 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, * unique, to convince GCC not to merge duplicate inline asm statements. */ #define annotate_reachable() ({ \ - asm("%c0:\n\t" \ - ".pushsection .discard.reachable\n\t" \ - ".long %c0b - .\n\t" \ - ".popsection\n\t" : : "i" (__COUNTER__)); \ + asm volatile("%c0:\n\t" \ + ".pushsection .discard.reachable\n\t" \ + ".long %c0b - .\n\t" \ + ".popsection\n\t" : : "i" (__COUNTER__)); \ }) #define annotate_unreachable() ({ \ - asm("%c0:\n\t" \ - ".pushsection .discard.unreachable\n\t" \ - ".long %c0b - .\n\t" \ - ".popsection\n\t" : : "i" (__COUNTER__)); \ + asm volatile("%c0:\n\t" \ + ".pushsection .discard.unreachable\n\t" \ + ".long %c0b - .\n\t" \ + ".popsection\n\t" : : "i" (__COUNTER__)); \ }) #define ASM_UNREACHABLE \ "999:\n\t" \ -- GitLab From 6a77cff819ae3e31992bde6432c9b5720748a89b Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 6 Nov 2017 07:21:50 -0600 Subject: [PATCH 1661/2898] objtool: Move synced files to their original relative locations This will enable more straightforward comparisons, and it also makes the files 100% identical. Suggested-by: Ingo Molnar Signed-off-by: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/407b2aaa317741f48fcf821592c0e96ab3be1890.1509974346.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- tools/objtool/.gitignore | 2 +- tools/objtool/Makefile | 22 ++++++++++--------- tools/objtool/arch/x86/Build | 10 ++++----- tools/objtool/arch/x86/decode.c | 6 ++--- .../arch/x86/{insn => include/asm}/inat.h | 2 +- .../x86/{insn => include/asm}/inat_types.h | 0 .../arch/x86/{insn => include/asm}/insn.h | 2 +- .../{ => arch/x86/include/asm}/orc_types.h | 0 tools/objtool/arch/x86/{insn => lib}/inat.c | 2 +- tools/objtool/arch/x86/{insn => lib}/insn.c | 4 ++-- .../arch/x86/{insn => lib}/x86-opcode-map.txt | 0 .../x86/{insn => tools}/gen-insn-attr-x86.awk | 0 tools/objtool/orc.h | 2 +- 13 files changed, 27 insertions(+), 25 deletions(-) rename tools/objtool/arch/x86/{insn => include/asm}/inat.h (99%) rename tools/objtool/arch/x86/{insn => include/asm}/inat_types.h (100%) rename tools/objtool/arch/x86/{insn => include/asm}/insn.h (99%) rename tools/objtool/{ => arch/x86/include/asm}/orc_types.h (100%) rename tools/objtool/arch/x86/{insn => lib}/inat.c (99%) rename tools/objtool/arch/x86/{insn => lib}/insn.c (99%) rename tools/objtool/arch/x86/{insn => lib}/x86-opcode-map.txt (100%) rename tools/objtool/arch/x86/{insn => tools}/gen-insn-attr-x86.awk (100%) diff --git a/tools/objtool/.gitignore b/tools/objtool/.gitignore index d3102c865a95..914cff12899b 100644 --- a/tools/objtool/.gitignore +++ b/tools/objtool/.gitignore @@ -1,3 +1,3 @@ -arch/x86/insn/inat-tables.c +arch/x86/lib/inat-tables.c objtool fixdep diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index 424b1965d06f..c6a19d946ec1 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -25,7 +25,9 @@ OBJTOOL_IN := $(OBJTOOL)-in.o all: $(OBJTOOL) -INCLUDES := -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi +INCLUDES := -I$(srctree)/tools/include \ + -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \ + -I$(srctree)/tools/objtool/arch/$(HOSTARCH)/include WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed CFLAGS += -Wall -Werror $(WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) LDFLAGS += -lelf $(LIBSUBCMD) @@ -46,16 +48,16 @@ $(OBJTOOL_IN): fixdep FORCE $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN) @(diff -I 2>&1 | grep -q 'option requires an argument' && \ test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \ - diff -I'^#include' arch/x86/insn/insn.c ../../arch/x86/lib/insn.c >/dev/null && \ - diff -I'^#include' arch/x86/insn/inat.c ../../arch/x86/lib/inat.c >/dev/null && \ - diff arch/x86/insn/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \ - diff arch/x86/insn/gen-insn-attr-x86.awk ../../arch/x86/tools/gen-insn-attr-x86.awk >/dev/null && \ - diff -I'^#include' arch/x86/insn/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \ - diff -I'^#include' arch/x86/insn/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \ - diff -I'^#include' arch/x86/insn/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \ + diff arch/x86/lib/insn.c ../../arch/x86/lib/insn.c >/dev/null && \ + diff arch/x86/lib/inat.c ../../arch/x86/lib/inat.c >/dev/null && \ + diff arch/x86/lib/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \ + diff arch/x86/tools/gen-insn-attr-x86.awk ../../arch/x86/tools/gen-insn-attr-x86.awk >/dev/null && \ + diff arch/x86/include/asm/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \ + diff arch/x86/include/asm/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \ + diff arch/x86/include/asm/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \ || echo "warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true @(test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \ - diff ../../arch/x86/include/asm/orc_types.h orc_types.h >/dev/null) \ + diff ../../arch/x86/include/asm/orc_types.h arch/x86/include/asm/orc_types.h >/dev/null) \ || echo "warning: objtool: orc_types.h differs from kernel" >&2 )) || true $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@ @@ -66,7 +68,7 @@ $(LIBSUBCMD): fixdep FORCE clean: $(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL) $(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete - $(Q)$(RM) $(OUTPUT)arch/x86/insn/inat-tables.c $(OUTPUT)fixdep + $(Q)$(RM) $(OUTPUT)arch/x86/lib/inat-tables.c $(OUTPUT)fixdep FORCE: diff --git a/tools/objtool/arch/x86/Build b/tools/objtool/arch/x86/Build index debbdb0b5c43..b998412c017d 100644 --- a/tools/objtool/arch/x86/Build +++ b/tools/objtool/arch/x86/Build @@ -1,12 +1,12 @@ objtool-y += decode.o -inat_tables_script = arch/x86/insn/gen-insn-attr-x86.awk -inat_tables_maps = arch/x86/insn/x86-opcode-map.txt +inat_tables_script = arch/x86/tools/gen-insn-attr-x86.awk +inat_tables_maps = arch/x86/lib/x86-opcode-map.txt -$(OUTPUT)arch/x86/insn/inat-tables.c: $(inat_tables_script) $(inat_tables_maps) +$(OUTPUT)arch/x86/lib/inat-tables.c: $(inat_tables_script) $(inat_tables_maps) $(call rule_mkdir) $(Q)$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ -$(OUTPUT)arch/x86/decode.o: $(OUTPUT)arch/x86/insn/inat-tables.c +$(OUTPUT)arch/x86/decode.o: $(OUTPUT)arch/x86/lib/inat-tables.c -CFLAGS_decode.o += -I$(OUTPUT)arch/x86/insn +CFLAGS_decode.o += -I$(OUTPUT)arch/x86/lib diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index 34a579f806e3..8acfc47af70e 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -19,9 +19,9 @@ #include #define unlikely(cond) (cond) -#include "insn/insn.h" -#include "insn/inat.c" -#include "insn/insn.c" +#include +#include "lib/inat.c" +#include "lib/insn.c" #include "../../elf.h" #include "../../arch.h" diff --git a/tools/objtool/arch/x86/insn/inat.h b/tools/objtool/arch/x86/include/asm/inat.h similarity index 99% rename from tools/objtool/arch/x86/insn/inat.h rename to tools/objtool/arch/x86/include/asm/inat.h index 125ecd2a300d..02aff0867211 100644 --- a/tools/objtool/arch/x86/insn/inat.h +++ b/tools/objtool/arch/x86/include/asm/inat.h @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ -#include "inat_types.h" +#include /* * Internal bits. Don't use bitmasks directly, because these bits are diff --git a/tools/objtool/arch/x86/insn/inat_types.h b/tools/objtool/arch/x86/include/asm/inat_types.h similarity index 100% rename from tools/objtool/arch/x86/insn/inat_types.h rename to tools/objtool/arch/x86/include/asm/inat_types.h diff --git a/tools/objtool/arch/x86/insn/insn.h b/tools/objtool/arch/x86/include/asm/insn.h similarity index 99% rename from tools/objtool/arch/x86/insn/insn.h rename to tools/objtool/arch/x86/include/asm/insn.h index e23578c7b1be..b3e32b010ab1 100644 --- a/tools/objtool/arch/x86/insn/insn.h +++ b/tools/objtool/arch/x86/include/asm/insn.h @@ -21,7 +21,7 @@ */ /* insn_attr_t is defined in inat.h */ -#include "inat.h" +#include struct insn_field { union { diff --git a/tools/objtool/orc_types.h b/tools/objtool/arch/x86/include/asm/orc_types.h similarity index 100% rename from tools/objtool/orc_types.h rename to tools/objtool/arch/x86/include/asm/orc_types.h diff --git a/tools/objtool/arch/x86/insn/inat.c b/tools/objtool/arch/x86/lib/inat.c similarity index 99% rename from tools/objtool/arch/x86/insn/inat.c rename to tools/objtool/arch/x86/lib/inat.c index e4bf28e6f4c7..c1f01a8e9f65 100644 --- a/tools/objtool/arch/x86/insn/inat.c +++ b/tools/objtool/arch/x86/lib/inat.c @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ -#include "insn.h" +#include /* Attribute tables are generated from opcode map */ #include "inat-tables.c" diff --git a/tools/objtool/arch/x86/insn/insn.c b/tools/objtool/arch/x86/lib/insn.c similarity index 99% rename from tools/objtool/arch/x86/insn/insn.c rename to tools/objtool/arch/x86/lib/insn.c index ca983e2bea8b..1088eb8f3a5f 100644 --- a/tools/objtool/arch/x86/insn/insn.c +++ b/tools/objtool/arch/x86/lib/insn.c @@ -23,8 +23,8 @@ #else #include #endif -#include "inat.h" -#include "insn.h" +#include +#include /* Verify next sizeof(t) bytes can be on the same instruction */ #define validate_next(t, insn, n) \ diff --git a/tools/objtool/arch/x86/insn/x86-opcode-map.txt b/tools/objtool/arch/x86/lib/x86-opcode-map.txt similarity index 100% rename from tools/objtool/arch/x86/insn/x86-opcode-map.txt rename to tools/objtool/arch/x86/lib/x86-opcode-map.txt diff --git a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk b/tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk similarity index 100% rename from tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk rename to tools/objtool/arch/x86/tools/gen-insn-attr-x86.awk diff --git a/tools/objtool/orc.h b/tools/objtool/orc.h index a4139e386ef3..b0e92a6d0903 100644 --- a/tools/objtool/orc.h +++ b/tools/objtool/orc.h @@ -18,7 +18,7 @@ #ifndef _ORC_H #define _ORC_H -#include "orc_types.h" +#include struct objtool_file; -- GitLab From 3bd51c5a371de917e4e7401c9df006b5998579df Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 6 Nov 2017 07:21:51 -0600 Subject: [PATCH 1662/2898] objtool: Move kernel headers/code sync check to a script Replace the nasty diff checks in the objtool Makefile with a clean bash script, and make the warnings more specific. Heavily inspired by tools/perf/check-headers.sh. Suggested-by: Ingo Molnar Signed-off-by: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/ab015f15ccd8c0c6008493c3c6ee3d495eaf2927.1509974346.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- tools/objtool/Makefile | 16 +--------------- tools/objtool/sync-check.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 15 deletions(-) create mode 100755 tools/objtool/sync-check.sh diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index c6a19d946ec1..6aaed251b4ed 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -43,22 +43,8 @@ include $(srctree)/tools/build/Makefile.include $(OBJTOOL_IN): fixdep FORCE @$(MAKE) $(build)=objtool -# Busybox's diff doesn't have -I, avoid warning in that case -# $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN) - @(diff -I 2>&1 | grep -q 'option requires an argument' && \ - test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \ - diff arch/x86/lib/insn.c ../../arch/x86/lib/insn.c >/dev/null && \ - diff arch/x86/lib/inat.c ../../arch/x86/lib/inat.c >/dev/null && \ - diff arch/x86/lib/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \ - diff arch/x86/tools/gen-insn-attr-x86.awk ../../arch/x86/tools/gen-insn-attr-x86.awk >/dev/null && \ - diff arch/x86/include/asm/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \ - diff arch/x86/include/asm/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \ - diff arch/x86/include/asm/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \ - || echo "warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true - @(test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \ - diff ../../arch/x86/include/asm/orc_types.h arch/x86/include/asm/orc_types.h >/dev/null) \ - || echo "warning: objtool: orc_types.h differs from kernel" >&2 )) || true + @./sync-check.sh $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@ diff --git a/tools/objtool/sync-check.sh b/tools/objtool/sync-check.sh new file mode 100755 index 000000000000..1470e74e9d66 --- /dev/null +++ b/tools/objtool/sync-check.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +FILES=' +arch/x86/lib/insn.c +arch/x86/lib/inat.c +arch/x86/lib/x86-opcode-map.txt +arch/x86/tools/gen-insn-attr-x86.awk +arch/x86/include/asm/insn.h +arch/x86/include/asm/inat.h +arch/x86/include/asm/inat_types.h +arch/x86/include/asm/orc_types.h +' + +check() +{ + local file=$1 + + diff $file ../../$file > /dev/null || + echo "Warning: synced file at 'tools/objtool/$file' differs from latest kernel version at '$file'" +} + +if [ ! -d ../../kernel ] || [ ! -d ../../tools ] || [ ! -d ../objtool ]; then + exit 0 +fi + +for i in $FILES; do + check $i +done -- GitLab From 620fd73edfd7297307e0e3ac581e65247c9dd8db Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 6 Nov 2017 10:07:33 +0300 Subject: [PATCH 1663/2898] drm/amd/display: small cleanup in destruct() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Static analysis tools get annoyed that we don't indent this if statement. Actually, the if statement isn't required because kfree() can handle NULL pointers just fine. The DCE110STRENC_FROM_STRENC() macro is a wrapper around container_of() but it's basically a no-op or a cast. Anyway, it's not really appropriate here so it should be removed as well. Acked-by: Christian König Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index d911590d08bc..4c4bd72d4e40 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -725,10 +725,8 @@ static void destruct(struct dcn10_resource_pool *pool) } } - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) - kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); - } + for (i = 0; i < pool->base.stream_enc_count; i++) + kfree(pool->base.stream_enc[i]); for (i = 0; i < pool->base.audio_count; i++) { if (pool->base.audios[i]) -- GitLab From 74baea4275ee130c67400b33c532da8999b530af Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 6 Nov 2017 14:43:41 +0300 Subject: [PATCH 1664/2898] drm/amd/display: checking for NULL instead of IS_ERR() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit backlight_device_register() never returns NULL, it returns error pointers on error so the check here is wrong. Acked-by: Christian König Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 33a15a1d818c..75f9383f5b9b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1296,7 +1296,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) &amdgpu_dm_backlight_ops, &props); - if (NULL == dm->backlight_dev) + if (IS_ERR(dm->backlight_dev)) DRM_ERROR("DM: Backlight registration failed!\n"); else DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); -- GitLab From f05f1b3da5a531d1569194b24dd7eb33b4a067ca Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 6 Nov 2017 14:44:22 +0300 Subject: [PATCH 1665/2898] drm/amd/display: remove some unneeded code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We assign "v_init = asic_blank_start;" a few lines earlier so there is no need to do it again inside the if statements. Also "v_init" is unsigned so it can't be less than zero. Acked-by: Christian König Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c index 1994865d4351..c7333cdf1802 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c @@ -236,13 +236,10 @@ static void tgn10_program_timing( if (tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT || tg->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT_MST || tg->dlg_otg_param.signal == SIGNAL_TYPE_EDP) { - v_init = asic_blank_start; start_point = 1; if (patched_crtc_timing.flags.INTERLACE == 1) field_num = 1; } - if (v_init < 0) - v_init = 0; v_fp2 = 0; if (tg->dlg_otg_param.vstartup_start > asic_blank_end) v_fp2 = tg->dlg_otg_param.vstartup_start > asic_blank_end; -- GitLab From a4718a5bca77954ffaa5f828158c45aae40a7ec8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 7 Nov 2017 05:17:12 +1000 Subject: [PATCH 1666/2898] amdgpu/dc: fix non-ansi function decls. smatch reported: drivers/gpu/drm/amd/amdgpu/../display/dc/bios/dce80/command_table_helper_dce80.c:351:71: warning: non-ANSI function declaration of function 'dal_cmd_tbl_helper_dce80_get_table' drivers/gpu/drm/amd/amdgpu/../display/dc/bios/dce110/command_table_helper_dce110.c:361:72: warning: non-ANSI function declaration of function 'dal_cmd_tbl_helper_dce110_get_table' drivers/gpu/drm/amd/amdgpu/../display/dc/bios/dce112/command_table_helper_dce112.c:415:72: warning: non-ANSI function declaration of function 'dal_cmd_tbl_helper_dce112_get_table' drivers/gpu/drm/amd/amdgpu/../display/dc/bios/dce112/command_table_helper2_dce112.c:415:73: warning: non-ANSI function declaration of function 'dal_cmd_tbl_helper_dce112_get_table2' drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_surface.c:148:34: warning: non-ANSI function declaration of function 'dc_create_gamma' drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_surface.c:178:50: warning: non-ANSI function declaration of function 'dc_create_transfer_func' This fixes them. Reviewed-by: Harry Wentland Signed-off-by: Dave Airlie Signed-off-by: Alex Deucher --- .../amd/display/dc/bios/dce110/command_table_helper_dce110.c | 2 +- .../amd/display/dc/bios/dce112/command_table_helper2_dce112.c | 2 +- .../amd/display/dc/bios/dce112/command_table_helper_dce112.c | 2 +- .../amd/display/dc/bios/dce80/command_table_helper_dce80.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c index 8049320e8b03..ca24154468c7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -358,7 +358,7 @@ static const struct command_table_helper command_table_helper_funcs = { * const struct command_table_helper **h - [out] struct of functions * */ -const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table() +const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void) { return &command_table_helper_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c index d342cdecba11..0237ae575068 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c @@ -412,7 +412,7 @@ static const struct command_table_helper command_table_helper_funcs = { * const struct command_table_helper **h - [out] struct of functions * */ -const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2() +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2(void) { return &command_table_helper_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c index 48e59963dad4..452034f83e4c 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -412,7 +412,7 @@ static const struct command_table_helper command_table_helper_funcs = { * const struct command_table_helper **h - [out] struct of functions * */ -const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table() +const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table(void) { return &command_table_helper_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c index 295e16ef3f73..8b30b558cf1f 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c @@ -348,7 +348,7 @@ static const struct command_table_helper command_table_helper_funcs = { dal_cmd_table_helper_encoder_mode_bp_to_atom, }; -const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table() +const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table(void) { return &command_table_helper_funcs; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 5aa2270f36fd..ade5b8ee9c3c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -145,7 +145,7 @@ void dc_gamma_release(struct dc_gamma **gamma) *gamma = NULL; } -struct dc_gamma *dc_create_gamma() +struct dc_gamma *dc_create_gamma(void) { struct dc_gamma *gamma = kzalloc(sizeof(*gamma), GFP_KERNEL); @@ -175,7 +175,7 @@ void dc_transfer_func_release(struct dc_transfer_func *tf) kref_put(&tf->refcount, dc_transfer_func_free); } -struct dc_transfer_func *dc_create_transfer_func() +struct dc_transfer_func *dc_create_transfer_func(void) { struct dc_transfer_func *tf = kzalloc(sizeof(*tf), GFP_KERNEL); -- GitLab From bf5563ede9f254fba083c6b56e4ca8b836babb1d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 7 Nov 2017 05:30:47 +1000 Subject: [PATCH 1667/2898] amdgpu/dc: fix indentation warning from smatch. This fixes all the current smatch: warn: inconsistent indenting Reviewed-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Dave Airlie Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/bios/bios_parser2.c | 2 +- .../drm/amd/display/dc/bios/command_table2.c | 18 +++++------ .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_stream.c | 4 +-- .../gpu/drm/amd/display/dc/dce/dce_audio.c | 26 ++++++++-------- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 16 +++++----- .../display/dc/dce110/dce110_hw_sequencer.c | 30 +++++++++---------- .../dc/dce120/dce120_timing_generator.c | 7 ++--- .../drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 2 +- .../dc/i2caux/dce110/i2c_hw_engine_dce110.c | 30 +++++++++---------- 10 files changed, 68 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 43e9a9959288..1ee1717f2e6f 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1373,7 +1373,7 @@ static enum bp_result get_firmware_info_v3_1( bp->cmd_tbl.get_smu_clock_info(bp) * 10; } - return BP_RESULT_OK; + return BP_RESULT_OK; } static enum bp_result bios_parser_get_encoder_cap_info( diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 64eab356d336..ba68693758a7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -373,15 +373,15 @@ static void init_set_crtc_timing(struct bios_parser *bp) uint32_t dtd_version = BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming); - switch (dtd_version) { - case 3: - bp->cmd_tbl.set_crtc_timing = - set_crtc_using_dtd_timing_v3; - break; - default: - bp->cmd_tbl.set_crtc_timing = NULL; - break; - } + switch (dtd_version) { + case 3: + bp->cmd_tbl.set_crtc_timing = + set_crtc_using_dtd_timing_v3; + break; + default: + bp->cmd_tbl.set_crtc_timing = NULL; + break; + } } static enum bp_result set_crtc_using_dtd_timing_v3( diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index e1515230c661..3dce35e66b09 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -1155,7 +1155,7 @@ static unsigned int dcn_find_normalized_clock_vdd_Level( unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels); if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9*1000000/factor) { - vdd_level = dcn_bw_v_max0p91; + vdd_level = dcn_bw_v_max0p91; BREAK_TO_DEBUGGER(); } else if (clocks_in_khz > dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8*1000000/factor) { vdd_level = dcn_bw_v_max0p9; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 572b885195c7..de04b95e103a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -182,11 +182,11 @@ bool dc_stream_set_cursor_attributes( if (NULL == stream) { dm_error("DC: dc_stream is NULL!\n"); - return false; + return false; } if (NULL == attributes) { dm_error("DC: attributes is NULL!\n"); - return false; + return false; } if (attributes->address.quad_part == 0) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 526ec5c8eafd..d882adf746a5 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -179,19 +179,19 @@ static void check_audio_bandwidth_hdmi( /* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number * of Audio samples per line multiplied by 10 - Layout 1) */ - samples /= 32; - samples *= crtc_info->v_active; - /*Number of samples multiplied by 10, per second */ - samples *= crtc_info->refresh_rate; - /*Number of Audio samples per second */ - samples /= 10; - - /* @todo do it after deep color is implemented - * 8xx - deep color bandwidth scaling - * Extra bandwidth is avaliable in deep color b/c link runs faster than - * pixel rate. This has the effect of allowing more tmds characters to - * be transmitted during blank - */ + samples /= 32; + samples *= crtc_info->v_active; + /*Number of samples multiplied by 10, per second */ + samples *= crtc_info->refresh_rate; + /*Number of Audio samples per second */ + samples /= 10; + + /* @todo do it after deep color is implemented + * 8xx - deep color bandwidth scaling + * Extra bandwidth is avaliable in deep color b/c link runs faster than + * pixel rate. This has the effect of allowing more tmds characters to + * be transmitted during blank + */ switch (crtc_info->color_depth) { case COLOR_DEPTH_888: diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 3691c7498d08..fd77df573b61 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -130,14 +130,14 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) if (wait == true) { for (retryCount = 0; retryCount <= 100; retryCount++) { dce_get_dmcu_psr_state(dmcu, &psr_state); - if (enable) { - if (psr_state != 0) - break; - } else { - if (psr_state == 0) - break; - } - udelay(10); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + udelay(10); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 399a5984ada3..1229a3315018 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -775,8 +775,8 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) * connect DIG back_end to front_end while enable_stream and * disconnect them during disable_stream * BY this, it is logic clean to separate stream and link */ - link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, - pipe_ctx->stream_res.stream_enc->id, true); + link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, + pipe_ctx->stream_res.stream_enc->id, true); } @@ -1306,7 +1306,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( stream->timing.display_color_depth, pipe_ctx->stream->signal); - pipe_ctx->stream_res.opp->funcs->opp_program_fmt( + pipe_ctx->stream_res.opp->funcs->opp_program_fmt( pipe_ctx->stream_res.opp, &stream->bit_depth_params, &stream->clamping); @@ -2594,21 +2594,21 @@ uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context) uint8_t j; uint32_t min_vertical_blank_time = -1; - for (j = 0; j < context->stream_count; j++) { - struct dc_stream_state *stream = context->streams[j]; - uint32_t vertical_blank_in_pixels = 0; - uint32_t vertical_blank_time = 0; + for (j = 0; j < context->stream_count; j++) { + struct dc_stream_state *stream = context->streams[j]; + uint32_t vertical_blank_in_pixels = 0; + uint32_t vertical_blank_time = 0; - vertical_blank_in_pixels = stream->timing.h_total * - (stream->timing.v_total - - stream->timing.v_addressable); + vertical_blank_in_pixels = stream->timing.h_total * + (stream->timing.v_total + - stream->timing.v_addressable); - vertical_blank_time = vertical_blank_in_pixels - * 1000 / stream->timing.pix_clk_khz; + vertical_blank_time = vertical_blank_in_pixels + * 1000 / stream->timing.pix_clk_khz; - if (min_vertical_blank_time > vertical_blank_time) - min_vertical_blank_time = vertical_blank_time; - } + if (min_vertical_blank_time > vertical_blank_time) + min_vertical_blank_time = vertical_blank_time; + } return min_vertical_blank_time; } diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c index 95d871be3a0b..2502182d5e82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c @@ -293,10 +293,9 @@ void dce120_timing_generator_tear_down_global_swap_lock( FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0, FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0); - CRTC_REG_SET_2( - CRTC0_CRTC_GSL_CONTROL, - CRTC_GSL_CHECK_LINE_NUM, 0, - CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/ + CRTC_REG_SET_2(CRTC0_CRTC_GSL_CONTROL, + CRTC_GSL_CHECK_LINE_NUM, 0, + CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/ } /* Reset slave controllers on master VSync */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c index 7784001c3a17..40627c244bf5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c @@ -124,7 +124,7 @@ static void program_gamut_remap( const uint16_t *regval, enum gamut_remap_select select) { - uint16_t selection = 0; + uint16_t selection = 0; struct color_matrices_reg gam_regs; if (regval == NULL || select == GAMUT_REMAP_BYPASS) { diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c index 1a5b3f70ddc9..56e25b3d65fd 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c @@ -133,13 +133,13 @@ static void release_engine( safe_to_reset = (i2c_sw_status == 1); } - if (safe_to_reset) - REG_UPDATE_2( - DC_I2C_CONTROL, - DC_I2C_SOFT_RESET, 1, - DC_I2C_SW_STATUS_RESET, 1); - else - REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1); + if (safe_to_reset) + REG_UPDATE_2( + DC_I2C_CONTROL, + DC_I2C_SOFT_RESET, 1, + DC_I2C_SW_STATUS_RESET, 1); + else + REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1); /* HW I2c engine - clock gating feature */ if (!hw_engine->engine_keep_power_up_count) @@ -301,16 +301,16 @@ static bool process_transaction( * For an I2C send operation, the LSB must be programmed to 0; * for I2C receive operation, the LSB must be programmed to 1. */ if (hw_engine->transaction_count == 0) { - value = REG_SET_4(DC_I2C_DATA, 0, - DC_I2C_DATA_RW, false, - DC_I2C_DATA, request->address, - DC_I2C_INDEX, 0, - DC_I2C_INDEX_WRITE, 1); + value = REG_SET_4(DC_I2C_DATA, 0, + DC_I2C_DATA_RW, false, + DC_I2C_DATA, request->address, + DC_I2C_INDEX, 0, + DC_I2C_INDEX_WRITE, 1); hw_engine->buffer_used_write = 0; } else - value = REG_SET_2(DC_I2C_DATA, 0, - DC_I2C_DATA_RW, false, - DC_I2C_DATA, request->address); + value = REG_SET_2(DC_I2C_DATA, 0, + DC_I2C_DATA_RW, false, + DC_I2C_DATA, request->address); hw_engine->buffer_used_write++; -- GitLab From f7dbc385c15084d6e11192e8a5dd901eb96dbec2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 7 Nov 2017 05:21:18 +1000 Subject: [PATCH 1668/2898] amdgpu/dc: handle allocation failures in dc_commit_planes_to_stream. Reported-by smatch: drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:966 dc_commit_planes_to_stream() error: potential null dereference 'flip_addr'. (kcalloc returns null) drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:968 dc_commit_planes_to_stream() error: potential null dereference 'plane_info'. (kcalloc returns null) drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:978 dc_commit_planes_to_stream() error: potential null dereference 'scaling_info'. (kcalloc returns null) Reviewed-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Dave Airlie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a71392ffc46d..ce3c57b38bc0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -952,6 +952,14 @@ bool dc_commit_planes_to_stream( scaling_info = kcalloc(MAX_SURFACES, sizeof(struct dc_scaling_info), GFP_KERNEL); + if (!flip_addr || !plane_info || !scaling_info) { + kfree(flip_addr); + kfree(plane_info); + kfree(scaling_info); + kfree(stream_update); + return false; + } + memset(updates, 0, sizeof(updates)); stream_update->src = dc_stream->src; -- GitLab From b349f76ece33be50943c1e6f78ccffd1b3e9627e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= Date: Tue, 7 Nov 2017 21:06:57 +0100 Subject: [PATCH 1669/2898] amdgpu/dc: fix more indentation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More "warn: inconsistent indenting" fixes from smatch. Acked-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++++----- .../amd/display/dc/i2caux/dce110/aux_engine_dce110.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 75f9383f5b9b..ad98885222e6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -517,7 +517,7 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - aconnector = to_amdgpu_dm_connector(connector); + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type == dc_connection_mst_branch) { DRM_DEBUG_DRIVER("DM_MST: starting TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); @@ -4712,10 +4712,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; } - /* Run this here since we want to validate the streams we created */ - ret = drm_atomic_helper_check_planes(dev, state); - if (ret) - goto fail; + /* Run this here since we want to validate the streams we created */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + goto fail; /* Check scaling and underscan changes*/ /*TODO Removed scaling changes validation due to inability to commit diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c index 0c4bbc10510d..81f9f3e34c10 100644 --- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c @@ -318,7 +318,7 @@ static void process_channel_reply( REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); - reply->data[i] = aux_sw_data_val; + reply->data[i] = aux_sw_data_val; ++i; } -- GitLab From 2a55f09643acf51ec0f1c72d92fdd4515e9a8aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= Date: Tue, 7 Nov 2017 21:06:58 +0100 Subject: [PATCH 1670/2898] amdgpu/dc: Fix potential null dereferences in amdgpu_dm.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ad98885222e6..8ee1bff09a6c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2423,6 +2423,8 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) return NULL; state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); @@ -3419,6 +3421,8 @@ create_i2c(struct ddc_service *ddc_service, struct amdgpu_i2c_adapter *i2c; i2c = kzalloc(sizeof(struct amdgpu_i2c_adapter), GFP_KERNEL); + if (!i2c) + return NULL; i2c->base.owner = THIS_MODULE; i2c->base.class = I2C_CLASS_DDC; i2c->base.dev.parent = &adev->pdev->dev; @@ -3449,6 +3453,11 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, DRM_DEBUG_DRIVER("%s()\n", __func__); i2c = create_i2c(link->ddc, link->link_index, &res); + if (!i2c) { + DRM_ERROR("Failed to create i2c adapter data\n"); + return -ENOMEM; + } + aconnector->i2c = i2c; res = i2c_add_adapter(&i2c->base); -- GitLab From 423788c7a866cb7f5265af9b96952e8a4bf48fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= Date: Tue, 7 Nov 2017 21:06:59 +0100 Subject: [PATCH 1671/2898] amdgpu/dc: Fix missing null checks in amdgpu_dm.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From smatch: error: we previously assumed X could be null Acked-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8ee1bff09a6c..cb45a3dc5a65 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -430,10 +430,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* Display Core create. */ adev->dm.dc = dc_create(&init_data); - if (adev->dm.dc) + if (adev->dm.dc) { DRM_INFO("Display Core initialized!\n"); - else + } else { DRM_INFO("Display Core failed to initialize!\n"); + goto error; + } INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func); @@ -2273,7 +2275,7 @@ decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode, } } -static void create_fake_sink(struct amdgpu_dm_connector *aconnector) +static int create_fake_sink(struct amdgpu_dm_connector *aconnector) { struct dc_sink *sink = NULL; struct dc_sink_init_data sink_init_data = { 0 }; @@ -2282,14 +2284,18 @@ static void create_fake_sink(struct amdgpu_dm_connector *aconnector) sink_init_data.sink_signal = aconnector->dc_link->connector_signal; sink = dc_sink_create(&sink_init_data); - if (!sink) + if (!sink) { DRM_ERROR("Failed to create sink!\n"); + return -ENOMEM; + } sink->sink_signal = SIGNAL_TYPE_VIRTUAL; aconnector->fake_enable = true; aconnector->dc_sink = sink; aconnector->dc_link->local_sink = sink; + + return 0; } static struct dc_stream_state * @@ -2323,7 +2329,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (aconnector->mst_port) goto stream_create_fail; - create_fake_sink(aconnector); + if (create_fake_sink(aconnector)) + goto stream_create_fail; } stream = dc_create_stream_for_sink(aconnector->dc_sink); -- GitLab From 53a23207f2a17fd990c85bd84c45d243463e21bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= Date: Tue, 7 Nov 2017 21:18:06 +0100 Subject: [PATCH 1672/2898] amdgpu/dc: Fix double unlock in amdgpu_dm_commit_planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by smartch: amdgpu_dm_commit_planes() error: double unlock 'spin_lock:&crtc->dev->event_lock' amdgpu_dm_commit_planes() error: double unlock 'irqsave:flags' The error path doesn't return so we only need a single unlock. Reviewed-by: Harry Wentland Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index cb45a3dc5a65..8ed6767b4616 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3904,7 +3904,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, DRM_ERROR("%s: acrtc %d, already busy\n", __func__, acrtc_attach->crtc_id); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); /* In commit tail framework this cannot happen */ WARN_ON(1); } -- GitLab From da36e6dbf478cb67a5df0da6afcd78df226e4c64 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Oct 2017 14:40:21 +0100 Subject: [PATCH 1673/2898] sunrcp: make function _svc_create_xprt static The function _svc_create_xprt is local to the source and does not need to be in global scope, so make it static. Cleans up sparse warning: symbol '_svc_create_xprt' was not declared. Should it be static? Signed-off-by: Colin Ian King Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- net/sunrpc/svc_xprt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index d16a8b423c20..18e87791350f 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -250,9 +250,9 @@ void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new) svc_xprt_received(new); } -int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name, - struct net *net, const int family, - const unsigned short port, int flags) +static int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name, + struct net *net, const int family, + const unsigned short port, int flags) { struct svc_xprt_class *xcl; -- GitLab From 085def3ade52f2ffe3e31f42e98c27dcc222dd37 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 18 Oct 2017 16:17:18 -0400 Subject: [PATCH 1674/2898] nfsd4: fix cached replies to solo SEQUENCE compounds Currently our handling of 4.1+ requests without "cachethis" set is confusing and not quite correct. Suppose a client sends a compound consisting of only a single SEQUENCE op, and it matches the seqid in a session slot (so it's a retry), but the previous request with that seqid did not have "cachethis" set. The obvious thing to do might be to return NFS4ERR_RETRY_UNCACHED_REP, but the protocol only allows that to be returned on the op following the SEQUENCE, and there is no such op in this case. The protocol permits us to cache replies even if the client didn't ask us to. And it's easy to do so in the case of solo SEQUENCE compounds. So, when we get a solo SEQUENCE, we can either return the previously cached reply or NFSERR_SEQ_FALSE_RETRY if we notice it differs in some way from the original call. Currently, we're returning a corrupt reply in the case a solo SEQUENCE matches a previous compound with more ops. This actually matters because the Linux client recently started doing this as a way to recover from lost replies to idempotent operations in the case the process doing the original reply was killed: in that case it's difficult to keep the original arguments around to do a real retry, and the client no longer cares what the result is anyway, but it would like to make sure that the slot's sequence id has been incremented, and the solo SEQUENCE assures that: if the server never got the original reply, it will increment the sequence id. If it did get the original reply, it won't increment, and nothing else that about the reply really matters much. But we can at least attempt to return valid xdr! Tested-by: Olga Kornievskaia Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 20 +++++++++++++++----- fs/nfsd/state.h | 1 + fs/nfsd/xdr4.h | 13 +++++++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9db8a19cceaa..3e96e02496bd 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2292,14 +2292,16 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) dprintk("--> %s slot %p\n", __func__, slot); + slot->sl_flags |= NFSD4_SLOT_INITIALIZED; slot->sl_opcnt = resp->opcnt; slot->sl_status = resp->cstate.status; - slot->sl_flags |= NFSD4_SLOT_INITIALIZED; - if (nfsd4_not_cached(resp)) { - slot->sl_datalen = 0; + if (!nfsd4_cache_this(resp)) { + slot->sl_flags &= ~NFSD4_SLOT_CACHED; return; } + slot->sl_flags |= NFSD4_SLOT_CACHED; + base = resp->cstate.data_offset; slot->sl_datalen = buf->len - base; if (read_bytes_from_xdr_buf(buf, base, slot->sl_data, slot->sl_datalen)) @@ -2326,8 +2328,16 @@ nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args, op = &args->ops[resp->opcnt - 1]; nfsd4_encode_operation(resp, op); - /* Return nfserr_retry_uncached_rep in next operation. */ - if (args->opcnt > 1 && !(slot->sl_flags & NFSD4_SLOT_CACHETHIS)) { + if (slot->sl_flags & NFSD4_SLOT_CACHED) + return op->status; + if (args->opcnt == 1) { + /* + * The original operation wasn't a solo sequence--we + * always cache those--so this retry must not match the + * original: + */ + op->status = nfserr_seq_false_retry; + } else { op = &args->ops[resp->opcnt++]; op->status = nfserr_retry_uncached_rep; nfsd4_encode_operation(resp, op); diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 005c911b34ac..2488b7df1b35 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -174,6 +174,7 @@ struct nfsd4_slot { #define NFSD4_SLOT_INUSE (1 << 0) #define NFSD4_SLOT_CACHETHIS (1 << 1) #define NFSD4_SLOT_INITIALIZED (1 << 2) +#define NFSD4_SLOT_CACHED (1 << 3) u8 sl_flags; char sl_data[]; }; diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 1e4edbf70052..bc29511b6405 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -649,9 +649,18 @@ static inline bool nfsd4_is_solo_sequence(struct nfsd4_compoundres *resp) return resp->opcnt == 1 && args->ops[0].opnum == OP_SEQUENCE; } -static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp) +/* + * The session reply cache only needs to cache replies that the client + * actually asked us to. But it's almost free for us to cache compounds + * consisting of only a SEQUENCE op, so we may as well cache those too. + * Also, the protocol doesn't give us a convenient response in the case + * of a replay of a solo SEQUENCE op that wasn't cached + * (RETRY_UNCACHED_REP can only be returned in the second op of a + * compound). + */ +static inline bool nfsd4_cache_this(struct nfsd4_compoundres *resp) { - return !(resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS) + return (resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS) || nfsd4_is_solo_sequence(resp); } -- GitLab From 53da6a53e1d414e05759fa59b7032ee08f4e22d7 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 17 Oct 2017 20:38:49 -0400 Subject: [PATCH 1675/2898] nfsd4: catch some false session retries The spec allows us to return NFS4ERR_SEQ_FALSE_RETRY if we notice that the client is making a call that matches a previous (slot, seqid) pair but that *isn't* actually a replay, because some detail of the call doesn't actually match the previous one. Catching every such case is difficult, but we may as well catch a few easy ones. This also handles the case described in the previous patch, in a different way. The spec does however require us to catch the case where the difference is in the rpc credentials. This prevents somebody from snooping another user's replies by fabricating retries. (But the practical value of the attack is limited by the fact that the replies with the most sensitive data are READ replies, which are not normally cached.) Tested-by: Olga Kornievskaia Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 37 ++++++++++++++++++++++++++++++++++++- fs/nfsd/state.h | 1 + 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3e96e02496bd..251dac7579ec 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1439,8 +1439,10 @@ free_session_slots(struct nfsd4_session *ses) { int i; - for (i = 0; i < ses->se_fchannel.maxreqs; i++) + for (i = 0; i < ses->se_fchannel.maxreqs; i++) { + free_svc_cred(&ses->se_slots[i]->sl_cred); kfree(ses->se_slots[i]); + } } /* @@ -2295,6 +2297,8 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) slot->sl_flags |= NFSD4_SLOT_INITIALIZED; slot->sl_opcnt = resp->opcnt; slot->sl_status = resp->cstate.status; + free_svc_cred(&slot->sl_cred); + copy_cred(&slot->sl_cred, &resp->rqstp->rq_cred); if (!nfsd4_cache_this(resp)) { slot->sl_flags &= ~NFSD4_SLOT_CACHED; @@ -3001,6 +3005,34 @@ static bool nfsd4_request_too_big(struct svc_rqst *rqstp, return xb->len > session->se_fchannel.maxreq_sz; } +static bool replay_matches_cache(struct svc_rqst *rqstp, + struct nfsd4_sequence *seq, struct nfsd4_slot *slot) +{ + struct nfsd4_compoundargs *argp = rqstp->rq_argp; + + if ((bool)(slot->sl_flags & NFSD4_SLOT_CACHETHIS) != + (bool)seq->cachethis) + return false; + /* + * If there's an error than the reply can have fewer ops than + * the call. But if we cached a reply with *more* ops than the + * call you're sending us now, then this new call is clearly not + * really a replay of the old one: + */ + if (slot->sl_opcnt < argp->opcnt) + return false; + /* This is the only check explicitly called by spec: */ + if (!same_creds(&rqstp->rq_cred, &slot->sl_cred)) + return false; + /* + * There may be more comparisons we could actually do, but the + * spec doesn't require us to catch every case where the calls + * don't match (that would require caching the call as well as + * the reply), so we don't bother. + */ + return true; +} + __be32 nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) @@ -3060,6 +3092,9 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, status = nfserr_seq_misordered; if (!(slot->sl_flags & NFSD4_SLOT_INITIALIZED)) goto out_put_session; + status = nfserr_seq_false_retry; + if (!replay_matches_cache(rqstp, seq, slot)) + goto out_put_session; cstate->slot = slot; cstate->session = session; cstate->clp = clp; diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 2488b7df1b35..86aa92d200e1 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -169,6 +169,7 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s) struct nfsd4_slot { u32 sl_seqid; __be32 sl_status; + struct svc_cred sl_cred; u32 sl_datalen; u16 sl_opcnt; #define NFSD4_SLOT_INUSE (1 << 0) -- GitLab From dc3033e16c59a2c4e62b31341258a5786cbcee56 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Fri, 20 Oct 2017 17:33:18 +0300 Subject: [PATCH 1676/2898] lockd: double unregister of inetaddr notifiers lockd_up() can call lockd_unregister_notifiers twice: inside lockd_start_svc() when it calls lockd_svc_exit_thread() and then in error path of lockd_up() Patch forces lockd_start_svc() to unregister notifiers in all error cases and removes extra unregister in error path of lockd_up(). Fixes: cb7d224f82e4 "lockd: unregister notifier blocks if the service ..." Signed-off-by: Vasily Averin Cc: stable@vger.kernel.org Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/lockd/svc.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index b995bdc13976..f04ecfc7ece0 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -369,6 +369,7 @@ static int lockd_start_svc(struct svc_serv *serv) printk(KERN_WARNING "lockd_up: svc_rqst allocation failed, error=%d\n", error); + lockd_unregister_notifiers(); goto out_rqst; } @@ -459,13 +460,16 @@ int lockd_up(struct net *net) } error = lockd_up_net(serv, net); - if (error < 0) - goto err_net; + if (error < 0) { + lockd_unregister_notifiers(); + goto err_put; + } error = lockd_start_svc(serv); - if (error < 0) - goto err_start; - + if (error < 0) { + lockd_down_net(serv, net); + goto err_put; + } nlmsvc_users++; /* * Note: svc_serv structures have an initial use count of 1, @@ -476,12 +480,6 @@ int lockd_up(struct net *net) err_create: mutex_unlock(&nlmsvc_mutex); return error; - -err_start: - lockd_down_net(serv, net); -err_net: - lockd_unregister_notifiers(); - goto err_put; } EXPORT_SYMBOL_GPL(lockd_up); -- GitLab From a15dfcd529ab43265e70ec32d3b9d2286872d412 Mon Sep 17 00:00:00 2001 From: Elena Reshetova Date: Fri, 20 Oct 2017 12:53:28 +0300 Subject: [PATCH 1677/2898] fs, nfsd: convert nfs4_stid.sc_count from atomic_t to refcount_t atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable nfs4_stid.sc_count is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees Cook Reviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4layouts.c | 4 ++-- fs/nfsd/nfs4state.c | 24 ++++++++++++------------ fs/nfsd/state.h | 3 ++- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index e122da696f1b..fed076069dd2 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c @@ -335,7 +335,7 @@ nfsd4_recall_file_layout(struct nfs4_layout_stateid *ls) trace_layout_recall(&ls->ls_stid.sc_stateid); - atomic_inc(&ls->ls_stid.sc_count); + refcount_inc(&ls->ls_stid.sc_count); nfsd4_run_cb(&ls->ls_recall); out_unlock: @@ -440,7 +440,7 @@ nfsd4_insert_layout(struct nfsd4_layoutget *lgp, struct nfs4_layout_stateid *ls) goto done; } - atomic_inc(&ls->ls_stid.sc_count); + refcount_inc(&ls->ls_stid.sc_count); list_add_tail(&new->lo_perstate, &ls->ls_layouts); new = NULL; done: diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 251dac7579ec..df2e5b4b222e 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -656,7 +656,7 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *sla stid->sc_stateid.si_opaque.so_id = new_id; stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid; /* Will be incremented before return to client: */ - atomic_set(&stid->sc_count, 1); + refcount_set(&stid->sc_count, 1); spin_lock_init(&stid->sc_lock); /* @@ -813,7 +813,7 @@ nfs4_put_stid(struct nfs4_stid *s) might_lock(&clp->cl_lock); - if (!atomic_dec_and_lock(&s->sc_count, &clp->cl_lock)) { + if (!refcount_dec_and_lock(&s->sc_count, &clp->cl_lock)) { wake_up_all(&close_wq); return; } @@ -913,7 +913,7 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) if (status) return status; ++fp->fi_delegees; - atomic_inc(&dp->dl_stid.sc_count); + refcount_inc(&dp->dl_stid.sc_count); dp->dl_stid.sc_type = NFS4_DELEG_STID; list_add(&dp->dl_perfile, &fp->fi_delegations); list_add(&dp->dl_perclnt, &clp->cl_delegations); @@ -1214,7 +1214,7 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp, WARN_ON_ONCE(!list_empty(&stp->st_locks)); - if (!atomic_dec_and_test(&s->sc_count)) { + if (!refcount_dec_and_test(&s->sc_count)) { wake_up_all(&close_wq); return; } @@ -2079,7 +2079,7 @@ find_stateid_by_type(struct nfs4_client *cl, stateid_t *t, char typemask) s = find_stateid_locked(cl, t); if (s != NULL) { if (typemask & s->sc_type) - atomic_inc(&s->sc_count); + refcount_inc(&s->sc_count); else s = NULL; } @@ -3564,7 +3564,7 @@ nfsd4_find_existing_open(struct nfs4_file *fp, struct nfsd4_open *open) continue; if (local->st_stateowner == &oo->oo_owner) { ret = local; - atomic_inc(&ret->st_stid.sc_count); + refcount_inc(&ret->st_stid.sc_count); break; } } @@ -3623,7 +3623,7 @@ init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open) goto out_unlock; open->op_stp = NULL; - atomic_inc(&stp->st_stid.sc_count); + refcount_inc(&stp->st_stid.sc_count); stp->st_stid.sc_type = NFS4_OPEN_STID; INIT_LIST_HEAD(&stp->st_locks); stp->st_stateowner = nfs4_get_stateowner(&oo->oo_owner); @@ -3671,7 +3671,7 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net) * there should be no danger of the refcount going back up again at * this point. */ - wait_event(close_wq, atomic_read(&s->st_stid.sc_count) == 2); + wait_event(close_wq, refcount_read(&s->st_stid.sc_count) == 2); release_all_access(s); if (s->st_stid.sc_file) { @@ -3833,7 +3833,7 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp) * lock) we know the server hasn't removed the lease yet, we know * it's safe to take a reference. */ - atomic_inc(&dp->dl_stid.sc_count); + refcount_inc(&dp->dl_stid.sc_count); nfsd4_run_cb(&dp->dl_recall); } @@ -5121,7 +5121,7 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ret = nfserr_locks_held; break; case NFS4_LOCK_STID: - atomic_inc(&s->sc_count); + refcount_inc(&s->sc_count); spin_unlock(&cl->cl_lock); ret = nfsd4_free_lock_stateid(stateid, s); goto out; @@ -5628,7 +5628,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo, lockdep_assert_held(&clp->cl_lock); - atomic_inc(&stp->st_stid.sc_count); + refcount_inc(&stp->st_stid.sc_count); stp->st_stid.sc_type = NFS4_LOCK_STID; stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner); get_nfs4_file(fp); @@ -5654,7 +5654,7 @@ find_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp) list_for_each_entry(lst, &lo->lo_owner.so_stateids, st_perstateowner) { if (lst->st_stid.sc_file == fp) { - atomic_inc(&lst->st_stid.sc_count); + refcount_inc(&lst->st_stid.sc_count); return lst; } } diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 86aa92d200e1..c259271c35a4 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -36,6 +36,7 @@ #define _NFSD4_STATE_H #include +#include #include #include "nfsfh.h" @@ -83,7 +84,7 @@ struct nfsd4_callback_ops { * fields that are of general use to any stateid. */ struct nfs4_stid { - atomic_t sc_count; + refcount_t sc_count; #define NFS4_OPEN_STID 1 #define NFS4_LOCK_STID 2 #define NFS4_DELEG_STID 4 -- GitLab From cff7cb2ece397760195ff8a5fc6bf3c860810246 Mon Sep 17 00:00:00 2001 From: Elena Reshetova Date: Fri, 20 Oct 2017 12:53:29 +0300 Subject: [PATCH 1678/2898] fs, nfsd: convert nfs4_cntl_odstate.co_odcount from atomic_t to refcount_t atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable nfs4_cntl_odstate.co_odcount is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees Cook Reviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 6 +++--- fs/nfsd/state.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index df2e5b4b222e..3f10a397e5ba 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -568,7 +568,7 @@ alloc_clnt_odstate(struct nfs4_client *clp) co = kmem_cache_zalloc(odstate_slab, GFP_KERNEL); if (co) { co->co_client = clp; - atomic_set(&co->co_odcount, 1); + refcount_set(&co->co_odcount, 1); } return co; } @@ -586,7 +586,7 @@ static inline void get_clnt_odstate(struct nfs4_clnt_odstate *co) { if (co) - atomic_inc(&co->co_odcount); + refcount_inc(&co->co_odcount); } static void @@ -598,7 +598,7 @@ put_clnt_odstate(struct nfs4_clnt_odstate *co) return; fp = co->co_file; - if (atomic_dec_and_lock(&co->co_odcount, &fp->fi_lock)) { + if (refcount_dec_and_lock(&co->co_odcount, &fp->fi_lock)) { list_del(&co->co_perfile); spin_unlock(&fp->fi_lock); diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index c259271c35a4..2ed368a91a10 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -468,7 +468,7 @@ struct nfs4_clnt_odstate { struct nfs4_client *co_client; struct nfs4_file *co_file; struct list_head co_perfile; - atomic_t co_odcount; + refcount_t co_odcount; }; /* -- GitLab From 818a34eb266449b1c89242596039a5e44c9be04c Mon Sep 17 00:00:00 2001 From: Elena Reshetova Date: Fri, 20 Oct 2017 12:53:30 +0300 Subject: [PATCH 1679/2898] fs, nfsd: convert nfs4_file.fi_ref from atomic_t to refcount_t atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable nfs4_file.fi_ref is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees Cook Reviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 6 +++--- fs/nfsd/state.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3f10a397e5ba..e905bf642a53 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -359,7 +359,7 @@ put_nfs4_file(struct nfs4_file *fi) { might_lock(&state_lock); - if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) { + if (refcount_dec_and_lock(&fi->fi_ref, &state_lock)) { hlist_del_rcu(&fi->fi_hash); spin_unlock(&state_lock); WARN_ON_ONCE(!list_empty(&fi->fi_clnt_odstate)); @@ -3401,7 +3401,7 @@ static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval, { lockdep_assert_held(&state_lock); - atomic_set(&fp->fi_ref, 1); + refcount_set(&fp->fi_ref, 1); spin_lock_init(&fp->fi_lock); INIT_LIST_HEAD(&fp->fi_stateids); INIT_LIST_HEAD(&fp->fi_delegations); @@ -3697,7 +3697,7 @@ find_file_locked(struct knfsd_fh *fh, unsigned int hashval) hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash) { if (fh_match(&fp->fi_fhandle, fh)) { - if (atomic_inc_not_zero(&fp->fi_ref)) + if (refcount_inc_not_zero(&fp->fi_ref)) return fp; } } diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 2ed368a91a10..f3772ea8ba0d 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -484,7 +484,7 @@ struct nfs4_clnt_odstate { * the global state_lock spinlock. */ struct nfs4_file { - atomic_t fi_ref; + refcount_t fi_ref; spinlock_t fi_lock; struct hlist_node fi_hash; /* hash on fi_fhandle */ struct list_head fi_stateids; @@ -637,7 +637,7 @@ struct nfs4_file *find_file(struct knfsd_fh *fh); void put_nfs4_file(struct nfs4_file *fi); static inline void get_nfs4_file(struct nfs4_file *fi) { - atomic_inc(&fi->fi_ref); + refcount_inc(&fi->fi_ref); } struct file *find_any_file(struct nfs4_file *f); -- GitLab From 256a89fa3deb6bb699b794e5bf00a72e2fe558b0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 19 Oct 2017 12:04:11 +0200 Subject: [PATCH 1680/2898] nfds: avoid gettimeofday for nfssvc_boot time do_gettimeofday() is deprecated and we should generally use time64_t based functions instead. In case of nfsd, all three users of nfssvc_boot only use the initial time as a unique token, and are not affected by it overflowing, so they are not affected by the y2038 overflow. This converts the structure to timespec64 anyway and adds comments to all uses, to document that we have thought about it and avoid having to look at it again. Signed-off-by: Arnd Bergmann Signed-off-by: J. Bruce Fields --- fs/nfsd/netns.h | 2 +- fs/nfsd/nfs3xdr.c | 10 ++++++---- fs/nfsd/nfs4proc.c | 5 +++-- fs/nfsd/nfssvc.c | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 3714231a9d0f..1c91391f4805 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -107,7 +107,7 @@ struct nfsd_net { bool lockd_up; /* Time of server startup */ - struct timeval nfssvc_boot; + struct timespec64 nfssvc_boot; /* * Max number of connections this nfsd container will allow. Defaults diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index bf444b664011..3579e0ae1131 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -747,8 +747,9 @@ nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p) if (resp->status == 0) { *p++ = htonl(resp->count); *p++ = htonl(resp->committed); - *p++ = htonl(nn->nfssvc_boot.tv_sec); - *p++ = htonl(nn->nfssvc_boot.tv_usec); + /* unique identifier, y2038 overflow can be ignored */ + *p++ = htonl((u32)nn->nfssvc_boot.tv_sec); + *p++ = htonl(nn->nfssvc_boot.tv_nsec); } return xdr_ressize_check(rqstp, p); } @@ -1118,8 +1119,9 @@ nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p) p = encode_wcc_data(rqstp, p, &resp->fh); /* Write verifier */ if (resp->status == 0) { - *p++ = htonl(nn->nfssvc_boot.tv_sec); - *p++ = htonl(nn->nfssvc_boot.tv_usec); + /* unique identifier, y2038 overflow can be ignored */ + *p++ = htonl((u32)nn->nfssvc_boot.tv_sec); + *p++ = htonl(nn->nfssvc_boot.tv_nsec); } return xdr_ressize_check(rqstp, p); } diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 7aff6d383d34..7d4495eac7a9 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -564,10 +564,11 @@ static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net) /* * This is opaque to client, so no need to byte-swap. Use - * __force to keep sparse happy + * __force to keep sparse happy. y2038 time_t overflow is + * irrelevant in this usage. */ verf[0] = (__force __be32)nn->nfssvc_boot.tv_sec; - verf[1] = (__force __be32)nn->nfssvc_boot.tv_usec; + verf[1] = (__force __be32)nn->nfssvc_boot.tv_nsec; memcpy(verifier->data, verf, sizeof(verifier->data)); } diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 6bbc717f40f2..28ff3e078af6 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -516,7 +516,7 @@ int nfsd_create_serv(struct net *net) register_inet6addr_notifier(&nfsd_inet6addr_notifier); #endif } - do_gettimeofday(&nn->nfssvc_boot); /* record boot time */ + ktime_get_real_ts64(&nn->nfssvc_boot); /* record boot time */ return 0; } -- GitLab From 0bad47cada5defba13e98827d22d06f13258dfb3 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 16 Oct 2017 12:14:33 -0400 Subject: [PATCH 1681/2898] svcrdma: Preserve CB send buffer across retransmits During each NFSv4 callback Call, an RDMA Send completion frees the page that contains the RPC Call message. If the upper layer determines that a retransmit is necessary, this is too soon. One possible symptom: after a GARBAGE_ARGS response an NFSv4.1 callback request, the following BUG fires on the NFS server: kernel: BUG: Bad page state in process kworker/0:2H pfn:7d3ce2 kernel: page:ffffea001f4f3880 count:-2 mapcount:0 mapping: (null) index:0x0 kernel: flags: 0x2fffff80000000() kernel: raw: 002fffff80000000 0000000000000000 0000000000000000 fffffffeffffffff kernel: raw: dead000000000100 dead000000000200 0000000000000000 0000000000000000 kernel: page dumped because: nonzero _refcount kernel: Modules linked in: cts rpcsec_gss_krb5 ocfs2_dlmfs ocfs2_stack_o2cb ocfs2_dlm ocfs2_nodemanager ocfs2_stackglue rpcrdm a ib_ipoib rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm iw_cm x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pc lmul crc32_pclmul ghash_clmulni_intel pcbc iTCO_wdt iTCO_vendor_support aesni_intel crypto_simd glue_helper cryptd pcspkr lpc_ich i2c_i801 mei_me mf d_core mei raid0 sg wmi ioatdma ipmi_si ipmi_devintf ipmi_msghandler shpchp acpi_power_meter acpi_pad nfsd nfs_acl lockd auth_rpcgss grace sunrpc ip_tables xfs libcrc32c mlx4_en mlx4_ib mlx5_ib ib_core sd_mod sr_mod cdrom ast drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ahci crc32c_intel libahci drm mlx5_core igb libata mlx4_core dca i2c_algo_bit i2c_core nvme kernel: ptp nvme_core pps_core dm_mirror dm_region_hash dm_log dm_mod dax kernel: CPU: 0 PID: 11495 Comm: kworker/0:2H Not tainted 4.14.0-rc3-00001-g577ce48 #811 kernel: Hardware name: Supermicro Super Server/X10SRL-F, BIOS 1.0c 09/09/2015 kernel: Workqueue: ib-comp-wq ib_cq_poll_work [ib_core] kernel: Call Trace: kernel: dump_stack+0x62/0x80 kernel: bad_page+0xfe/0x11a kernel: free_pages_check_bad+0x76/0x78 kernel: free_pcppages_bulk+0x364/0x441 kernel: ? ttwu_do_activate.isra.61+0x71/0x78 kernel: free_hot_cold_page+0x1c5/0x202 kernel: __put_page+0x2c/0x36 kernel: svc_rdma_put_context+0xd9/0xe4 [rpcrdma] kernel: svc_rdma_wc_send+0x50/0x98 [rpcrdma] This issue exists all the way back to v4.5, but refactoring and code re-organization prevents this simple patch from applying to kernels older than v4.12. The fix is the same, however, if someone needs to backport it. Reported-by: Ben Coddington BugLink: https://bugzilla.linux-nfs.org/show_bug.cgi?id=314 Fixes: 5d252f90a800 ('svcrdma: Add class for RDMA backwards ... ') Cc: stable@vger.kernel.org # v4.12 Signed-off-by: Chuck Lever Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_backchannel.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c index ec37ad83b068..1854db227742 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c @@ -132,6 +132,10 @@ static int svc_rdma_bc_sendto(struct svcxprt_rdma *rdma, if (ret) goto out_err; + /* Bump page refcnt so Send completion doesn't release + * the rq_buffer before all retransmits are complete. + */ + get_page(virt_to_page(rqst->rq_buffer)); ret = svc_rdma_post_send_wr(rdma, ctxt, 1, 0); if (ret) goto out_unmap; @@ -164,7 +168,6 @@ xprt_rdma_bc_allocate(struct rpc_task *task) return -EINVAL; } - /* svc_rdma_sendto releases this page */ page = alloc_page(RPCRDMA_DEF_GFP); if (!page) return -ENOMEM; @@ -183,6 +186,7 @@ xprt_rdma_bc_free(struct rpc_task *task) { struct rpc_rqst *rqst = task->tk_rqstp; + put_page(virt_to_page(rqst->rq_buffer)); kfree(rqst->rq_rbuffer); } -- GitLab From 1754eb2b27d7a58e5b9038c6297a1e7bbff4ed52 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 24 Oct 2017 14:58:11 -0400 Subject: [PATCH 1682/2898] rpc: remove some BUG()s It would be kinder to WARN() and recover in several spots here instead of BUG()ing. Also, it looks like the read_u32_from_xdr_buf() call could actually fail, though it might require a broken (or malicious) client, so convert that to just an error return. Reported-by: Weston Andros Adamson Signed-off-by: J. Bruce Fields --- net/sunrpc/auth_gss/svcauth_gss.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 7b1ee5a0b03c..73165e9ca5bf 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -855,11 +855,13 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g return stat; if (integ_len > buf->len) return stat; - if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len)) - BUG(); + if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len)) { + WARN_ON_ONCE(1); + return stat; + } /* copy out mic... */ if (read_u32_from_xdr_buf(buf, integ_len, &mic.len)) - BUG(); + return stat; if (mic.len > RPC_MAX_AUTH_SIZE) return stat; mic.data = kmalloc(mic.len, GFP_KERNEL); @@ -1611,8 +1613,10 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) BUG_ON(integ_len % 4); *p++ = htonl(integ_len); *p++ = htonl(gc->gc_seq); - if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len)) - BUG(); + if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len)) { + WARN_ON_ONCE(1); + goto out_err; + } if (resbuf->tail[0].iov_base == NULL) { if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE) goto out_err; -- GitLab From 7e981a8afa6d8d1d93e2b3d162aa81cc7b537208 Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Mon, 6 Nov 2017 16:46:04 +0300 Subject: [PATCH 1683/2898] nfsd: use nfs->ns.inum as net ID Publishing of net pointer is not safe, let's use nfs->ns.inum instead Signed-off-by: Vasily Averin Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e905bf642a53..ecbc7b0dfa4d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -7056,8 +7056,8 @@ nfs4_state_start_net(struct net *net) nn->nfsd4_manager.block_opens = true; locks_start_grace(net, &nn->nfsd4_manager); nfsd4_client_tracking_init(net); - printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n", - nn->nfsd4_grace, net); + printk(KERN_INFO "NFSD: starting %ld-second grace period (net %x)\n", + nn->nfsd4_grace, net->ns.inum); queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ); return 0; } -- GitLab From 77a08867a66796f8316449e030e0bfc84f2a3f66 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 27 Oct 2017 10:49:51 -0400 Subject: [PATCH 1684/2898] svcrdma: Enqueue after setting XPT_CLOSE in completion handlers I noticed the server was sometimes not closing the connection after a flushed Send. For example, if the client responds with an RNR NAK to a Reply from the server, that client might be deadlocked, and thus wouldn't send any more traffic. Thus the server wouldn't have any opportunity to notice the XPT_CLOSE bit has been set. Enqueue the transport so that svcxprt notices the bit even if there is no more transport activity after a flushed completion, QP access error, or device removal event. Signed-off-by: Chuck Lever Reviewed-By: Devesh Sharma Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_transport.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 5caf8e722a11..46ec069150d5 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -290,6 +290,7 @@ static void qp_event_handler(struct ib_event *event, void *context) ib_event_msg(event->event), event->event, event->element.qp); set_bit(XPT_CLOSE, &xprt->xpt_flags); + svc_xprt_enqueue(xprt); break; } } @@ -322,8 +323,7 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags); if (test_bit(RDMAXPRT_CONN_PENDING, &xprt->sc_flags)) goto out; - svc_xprt_enqueue(&xprt->sc_xprt); - goto out; + goto out_enqueue; flushed: if (wc->status != IB_WC_WR_FLUSH_ERR) @@ -333,6 +333,8 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); svc_rdma_put_context(ctxt, 1); +out_enqueue: + svc_xprt_enqueue(&xprt->sc_xprt); out: svc_xprt_put(&xprt->sc_xprt); } @@ -358,6 +360,7 @@ void svc_rdma_wc_send(struct ib_cq *cq, struct ib_wc *wc) if (unlikely(wc->status != IB_WC_SUCCESS)) { set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); + svc_xprt_enqueue(&xprt->sc_xprt); if (wc->status != IB_WC_WR_FLUSH_ERR) pr_err("svcrdma: Send: %s (%u/0x%x)\n", ib_wc_status_msg(wc->status), @@ -569,8 +572,10 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id, case RDMA_CM_EVENT_DEVICE_REMOVAL: dprintk("svcrdma: Device removal xprt=%p, cm_id=%p\n", xprt, cma_id); - if (xprt) + if (xprt) { set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); + svc_xprt_enqueue(&xprt->sc_xprt); + } break; default: -- GitLab From 95da1b3a5aded124dd1bda1e3cdb876184813140 Mon Sep 17 00:00:00 2001 From: Andrew Elble Date: Fri, 3 Nov 2017 14:06:31 -0400 Subject: [PATCH 1685/2898] nfsd: deal with revoked delegations appropriately If a delegation has been revoked by the server, operations using that delegation should error out with NFS4ERR_DELEG_REVOKED in the >4.1 case, and NFS4ERR_BAD_STATEID otherwise. The server needs NFSv4.1 clients to explicitly free revoked delegations. If the server returns NFS4ERR_DELEG_REVOKED, the client will do that; otherwise it may just forget about the delegation and be unable to recover when it later sees SEQ4_STATUS_RECALLABLE_STATE_REVOKED set on a SEQUENCE reply. That can cause the Linux 4.1 client to loop in its stage manager. Signed-off-by: Andrew Elble Reviewed-by: Trond Myklebust Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index ecbc7b0dfa4d..b82817767b9d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4016,7 +4016,8 @@ static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, statei { struct nfs4_stid *ret; - ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID); + ret = find_stateid_by_type(cl, s, + NFS4_DELEG_STID|NFS4_REVOKED_DELEG_STID); if (!ret) return NULL; return delegstateid(ret); @@ -4039,6 +4040,12 @@ nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open, deleg = find_deleg_stateid(cl, &open->op_delegate_stateid); if (deleg == NULL) goto out; + if (deleg->dl_stid.sc_type == NFS4_REVOKED_DELEG_STID) { + nfs4_put_stid(&deleg->dl_stid); + if (cl->cl_minorversion) + status = nfserr_deleg_revoked; + goto out; + } flags = share_access_to_flags(open->op_share_access); status = nfs4_check_delegmode(deleg, flags); if (status) { @@ -4908,6 +4915,16 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, struct nfs4_stid **s, struct nfsd_net *nn) { __be32 status; + bool return_revoked = false; + + /* + * only return revoked delegations if explicitly asked. + * otherwise we report revoked or bad_stateid status. + */ + if (typemask & NFS4_REVOKED_DELEG_STID) + return_revoked = true; + else if (typemask & NFS4_DELEG_STID) + typemask |= NFS4_REVOKED_DELEG_STID; if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) return nfserr_bad_stateid; @@ -4922,6 +4939,12 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, *s = find_stateid_by_type(cstate->clp, stateid, typemask); if (!*s) return nfserr_bad_stateid; + if (((*s)->sc_type == NFS4_REVOKED_DELEG_STID) && !return_revoked) { + nfs4_put_stid(*s); + if (cstate->minorversion) + return nfserr_deleg_revoked; + return nfserr_bad_stateid; + } return nfs_ok; } -- GitLab From 22700f3c6df55387cec2ee27c533a7b23c76dc51 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 10 Oct 2017 17:31:43 -0400 Subject: [PATCH 1686/2898] SUNRPC: Improve ordering of transport processing Since it can take a while before a specific thread gets scheduled, it is better to just implement a first come first served queue mechanism. That way, if a thread is already scheduled and is idle, it can pick up the work to do from the queue. Signed-off-by: Trond Myklebust Signed-off-by: J. Bruce Fields --- include/linux/sunrpc/svc.h | 1 + net/sunrpc/svc_xprt.c | 100 +++++++++++-------------------------- 2 files changed, 31 insertions(+), 70 deletions(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 38f561b2dda3..23c4d6496aac 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -46,6 +46,7 @@ struct svc_pool { struct svc_pool_stats sp_stats; /* statistics on pool operation */ #define SP_TASK_PENDING (0) /* still work to do even if no * xprt is queued. */ +#define SP_CONGESTED (1) unsigned long sp_flags; } ____cacheline_aligned_in_smp; diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 18e87791350f..80112c45aad1 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -380,7 +380,6 @@ void svc_xprt_do_enqueue(struct svc_xprt *xprt) struct svc_pool *pool; struct svc_rqst *rqstp = NULL; int cpu; - bool queued = false; if (!svc_xprt_has_something_to_do(xprt)) goto out; @@ -401,58 +400,25 @@ void svc_xprt_do_enqueue(struct svc_xprt *xprt) atomic_long_inc(&pool->sp_stats.packets); -redo_search: + dprintk("svc: transport %p put into queue\n", xprt); + spin_lock_bh(&pool->sp_lock); + list_add_tail(&xprt->xpt_ready, &pool->sp_sockets); + pool->sp_stats.sockets_queued++; + spin_unlock_bh(&pool->sp_lock); + /* find a thread for this xprt */ rcu_read_lock(); list_for_each_entry_rcu(rqstp, &pool->sp_all_threads, rq_all) { - /* Do a lockless check first */ - if (test_bit(RQ_BUSY, &rqstp->rq_flags)) + if (test_and_set_bit(RQ_BUSY, &rqstp->rq_flags)) continue; - - /* - * Once the xprt has been queued, it can only be dequeued by - * the task that intends to service it. All we can do at that - * point is to try to wake this thread back up so that it can - * do so. - */ - if (!queued) { - spin_lock_bh(&rqstp->rq_lock); - if (test_and_set_bit(RQ_BUSY, &rqstp->rq_flags)) { - /* already busy, move on... */ - spin_unlock_bh(&rqstp->rq_lock); - continue; - } - - /* this one will do */ - rqstp->rq_xprt = xprt; - svc_xprt_get(xprt); - spin_unlock_bh(&rqstp->rq_lock); - } - rcu_read_unlock(); - atomic_long_inc(&pool->sp_stats.threads_woken); wake_up_process(rqstp->rq_task); - put_cpu(); - goto out; - } - rcu_read_unlock(); - - /* - * We didn't find an idle thread to use, so we need to queue the xprt. - * Do so and then search again. If we find one, we can't hook this one - * up to it directly but we can wake the thread up in the hopes that it - * will pick it up once it searches for a xprt to service. - */ - if (!queued) { - queued = true; - dprintk("svc: transport %p put into queue\n", xprt); - spin_lock_bh(&pool->sp_lock); - list_add_tail(&xprt->xpt_ready, &pool->sp_sockets); - pool->sp_stats.sockets_queued++; - spin_unlock_bh(&pool->sp_lock); - goto redo_search; + goto out_unlock; } + set_bit(SP_CONGESTED, &pool->sp_flags); rqstp = NULL; +out_unlock: + rcu_read_unlock(); put_cpu(); out: trace_svc_xprt_do_enqueue(xprt, rqstp); @@ -721,38 +687,25 @@ rqst_should_sleep(struct svc_rqst *rqstp) static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) { - struct svc_xprt *xprt; struct svc_pool *pool = rqstp->rq_pool; long time_left = 0; /* rq_xprt should be clear on entry */ WARN_ON_ONCE(rqstp->rq_xprt); - /* Normally we will wait up to 5 seconds for any required - * cache information to be provided. - */ - rqstp->rq_chandle.thread_wait = 5*HZ; - - xprt = svc_xprt_dequeue(pool); - if (xprt) { - rqstp->rq_xprt = xprt; - - /* As there is a shortage of threads and this request - * had to be queued, don't allow the thread to wait so - * long for cache updates. - */ - rqstp->rq_chandle.thread_wait = 1*HZ; - clear_bit(SP_TASK_PENDING, &pool->sp_flags); - return xprt; - } + rqstp->rq_xprt = svc_xprt_dequeue(pool); + if (rqstp->rq_xprt) + goto out_found; /* * We have to be able to interrupt this wait * to bring down the daemons ... */ set_current_state(TASK_INTERRUPTIBLE); + smp_mb__before_atomic(); + clear_bit(SP_CONGESTED, &pool->sp_flags); clear_bit(RQ_BUSY, &rqstp->rq_flags); - smp_mb(); + smp_mb__after_atomic(); if (likely(rqst_should_sleep(rqstp))) time_left = schedule_timeout(timeout); @@ -761,13 +714,11 @@ static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) try_to_freeze(); - spin_lock_bh(&rqstp->rq_lock); set_bit(RQ_BUSY, &rqstp->rq_flags); - spin_unlock_bh(&rqstp->rq_lock); - - xprt = rqstp->rq_xprt; - if (xprt != NULL) - return xprt; + smp_mb__after_atomic(); + rqstp->rq_xprt = svc_xprt_dequeue(pool); + if (rqstp->rq_xprt) + goto out_found; if (!time_left) atomic_long_inc(&pool->sp_stats.threads_timedout); @@ -775,6 +726,15 @@ static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) if (signalled() || kthread_should_stop()) return ERR_PTR(-EINTR); return ERR_PTR(-EAGAIN); +out_found: + /* Normally we will wait up to 5 seconds for any required + * cache information to be provided. + */ + if (!test_bit(SP_CONGESTED, &pool->sp_flags)) + rqstp->rq_chandle.thread_wait = 5*HZ; + else + rqstp->rq_chandle.thread_wait = 1*HZ; + return rqstp->rq_xprt; } static void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) -- GitLab From 1c79df1f349fb6050016cea4ef1dfbc3853a5685 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 22 Sep 2017 16:48:28 -0700 Subject: [PATCH 1687/2898] target: Fix QUEUE_FULL + SCSI task attribute handling This patch fixes a bug during QUEUE_FULL where transport_complete_qf() calls transport_complete_task_attr() after it's already been invoked by target_complete_ok_work() or transport_generic_request_failure() during initial completion, preceeding QUEUE_FULL. This will result in se_device->simple_cmds, se_device->dev_cur_ordered_id and/or se_device->dev_ordered_sync being updated multiple times for a single se_cmd. To address this bug, clear SCF_TASK_ATTR_SET after the first call to transport_complete_task_attr(), and avoid updating SCSI task attribute related counters for any subsequent calls. Also, when a se_cmd is deferred due to ordered tags and executed via target_restart_delayed_cmds(), set CMD_T_SENT before execution matching what target_execute_cmd() does. Cc: Michael Cyr Cc: Bryant G. Ly Cc: Mike Christie Cc: Hannes Reinecke Cc: stable@vger.kernel.org # 4.1+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 473d652e4816..c33d1e95dd17 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2011,6 +2011,8 @@ static void target_restart_delayed_cmds(struct se_device *dev) list_del(&cmd->se_delayed_node); spin_unlock(&dev->delayed_cmd_lock); + cmd->transport_state |= CMD_T_SENT; + __target_execute_cmd(cmd, true); if (cmd->sam_task_attr == TCM_ORDERED_TAG) @@ -2046,6 +2048,8 @@ static void transport_complete_task_attr(struct se_cmd *cmd) pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n", dev->dev_cur_ordered_id); } + cmd->se_cmd_flags &= ~SCF_TASK_ATTR_SET; + restart: target_restart_delayed_cmds(dev); } -- GitLab From fd2f928b0ddd2fe8876d4f1344df2ace2b715a4d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 29 Sep 2017 16:03:24 -0700 Subject: [PATCH 1688/2898] target: Fix caw_sem leak in transport_generic_request_failure With the recent addition of transport_check_aborted_status() within transport_generic_request_failure() to avoid sending a SCSI status exception after CMD_T_ABORTED w/ TAS=1 has occured, it introduced a COMPARE_AND_WRITE early failure regression. Namely when COMPARE_AND_WRITE fails and se_device->caw_sem has been taken by sbc_compare_and_write(), if the new check for transport_check_aborted_status() returns true and exits, cmd->transport_complete_callback() -> compare_and_write_post() is skipped never releasing se_device->caw_sem. This regression was originally introduced by: commit e3b88ee95b4e4bf3e9729a4695d695b9c7c296c8 Author: Bart Van Assche Date: Tue Feb 14 16:25:45 2017 -0800 target: Fix handling of aborted failed commands To address this bug, move the transport_check_aborted_status() call after transport_complete_task_attr() and cmd->transport_complete_callback(). Cc: Mike Christie Cc: Hannes Reinecke Cc: Bart Van Assche Cc: stable@vger.kernel.org # 4.11+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c33d1e95dd17..d02218c71dd6 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1729,9 +1729,6 @@ void transport_generic_request_failure(struct se_cmd *cmd, { int ret = 0, post_ret = 0; - if (transport_check_aborted_status(cmd, 1)) - return; - pr_debug("-----[ Storage Engine Exception; sense_reason %d\n", sense_reason); target_show_cmd("-----[ ", cmd); @@ -1740,6 +1737,7 @@ void transport_generic_request_failure(struct se_cmd *cmd, * For SAM Task Attribute emulation for failed struct se_cmd */ transport_complete_task_attr(cmd); + /* * Handle special case for COMPARE_AND_WRITE failure, where the * callback is expected to drop the per device ->caw_sem. @@ -1748,6 +1746,9 @@ void transport_generic_request_failure(struct se_cmd *cmd, cmd->transport_complete_callback) cmd->transport_complete_callback(cmd, false, &post_ret); + if (transport_check_aborted_status(cmd, 1)) + return; + switch (sense_reason) { case TCM_NON_EXISTENT_LUN: case TCM_UNSUPPORTED_SCSI_OPCODE: -- GitLab From 9574a497df2bbc0a676b609ce0dd24d237cee3a6 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 29 Sep 2017 16:43:11 -0700 Subject: [PATCH 1689/2898] target: Fix quiese during transport_write_pending_qf endless loop This patch fixes a potential end-less loop during QUEUE_FULL, where cmd->se_tfo->write_pending() callback fails repeatedly but __transport_wait_for_tasks() has already been invoked to quiese the outstanding se_cmd descriptor. To address this bug, this patch adds a CMD_T_STOP|CMD_T_ABORTED check within transport_write_pending_qf() and invokes the existing se_cmd->t_transport_stop_comp to signal quiese completion back to __transport_wait_for_tasks(). Cc: Mike Christie Cc: Hannes Reinecke Cc: Bryant G. Ly Cc: Michael Cyr Cc: Potnuri Bharat Teja Cc: Sagi Grimberg Cc: stable@vger.kernel.org # 4.11+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d02218c71dd6..0e89db84b200 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2560,7 +2560,20 @@ EXPORT_SYMBOL(transport_generic_new_cmd); static void transport_write_pending_qf(struct se_cmd *cmd) { + unsigned long flags; int ret; + bool stop; + + spin_lock_irqsave(&cmd->t_state_lock, flags); + stop = (cmd->transport_state & (CMD_T_STOP | CMD_T_ABORTED)); + spin_unlock_irqrestore(&cmd->t_state_lock, flags); + + if (stop) { + pr_debug("%s:%d CMD_T_STOP|CMD_T_ABORTED for ITT: 0x%08llx\n", + __func__, __LINE__, cmd->tag); + complete_all(&cmd->t_transport_stop_comp); + return; + } ret = cmd->se_tfo->write_pending(cmd); if (ret) { -- GitLab From 1c21a48055a67ceb693e9c2587824a8de60a217c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 27 Oct 2017 22:19:26 -0800 Subject: [PATCH 1690/2898] target: Avoid early CMD_T_PRE_EXECUTE failures during ABORT_TASK This patch fixes bug where early se_cmd exceptions that occur before backend execution can result in use-after-free if/when a subsequent ABORT_TASK occurs for the same tag. Since an early se_cmd exception will have had se_cmd added to se_session->sess_cmd_list via target_get_sess_cmd(), it will not have CMD_T_COMPLETE set by the usual target_complete_cmd() backend completion path. This causes a subsequent ABORT_TASK + __target_check_io_state() to signal ABORT_TASK should proceed. As core_tmr_abort_task() executes, it will bring the outstanding se_cmd->cmd_kref count down to zero releasing se_cmd, after se_cmd has already been queued with error status into fabric driver response path code. To address this bug, introduce a CMD_T_PRE_EXECUTE bit that is set at target_get_sess_cmd() time, and cleared immediately before backend driver dispatch in target_execute_cmd() once CMD_T_ACTIVE is set. Then, check CMD_T_PRE_EXECUTE within __target_check_io_state() to determine when an early exception has occured, and avoid aborting this se_cmd since it will have already been queued into fabric driver response path code. Reported-by: Donald White Cc: Donald White Cc: Mike Christie Cc: Hannes Reinecke Cc: stable@vger.kernel.org # 3.14+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 9 +++++++++ drivers/target/target_core_transport.c | 2 ++ include/target/target_core_base.h | 1 + 3 files changed, 12 insertions(+) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 61909b23e959..9c7bc1ca341a 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -133,6 +133,15 @@ static bool __target_check_io_state(struct se_cmd *se_cmd, spin_unlock(&se_cmd->t_state_lock); return false; } + if (se_cmd->transport_state & CMD_T_PRE_EXECUTE) { + if (se_cmd->scsi_status) { + pr_debug("Attempted to abort io tag: %llu early failure" + " status: 0x%02x\n", se_cmd->tag, + se_cmd->scsi_status); + spin_unlock(&se_cmd->t_state_lock); + return false; + } + } if (sess->sess_tearing_down || se_cmd->cmd_wait_set) { pr_debug("Attempted to abort io tag: %llu already shutdown," " skipping\n", se_cmd->tag); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 0e89db84b200..58caacd54a3b 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1975,6 +1975,7 @@ void target_execute_cmd(struct se_cmd *cmd) } cmd->t_state = TRANSPORT_PROCESSING; + cmd->transport_state &= ~CMD_T_PRE_EXECUTE; cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT; spin_unlock_irq(&cmd->t_state_lock); @@ -2667,6 +2668,7 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref) ret = -ESHUTDOWN; goto out; } + se_cmd->transport_state |= CMD_T_PRE_EXECUTE; list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); out: spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index d3139a95ea77..ccf501b8359c 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -490,6 +490,7 @@ struct se_cmd { #define CMD_T_STOP (1 << 5) #define CMD_T_TAS (1 << 10) #define CMD_T_FABRIC_STOP (1 << 11) +#define CMD_T_PRE_EXECUTE (1 << 12) spinlock_t t_state_lock; struct kref cmd_kref; struct completion t_transport_stop_comp; -- GitLab From ae072726f6109bb1c94841d6fb3a82dde298ea85 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 27 Oct 2017 12:32:59 -0700 Subject: [PATCH 1691/2898] iscsi-target: Make TASK_REASSIGN use proper se_cmd->cmd_kref Since commit 59b6986dbf fixed a potential NULL pointer dereference by allocating a se_tmr_req for ISCSI_TM_FUNC_TASK_REASSIGN, the se_tmr_req is currently leaked by iscsit_free_cmd() because no iscsi_cmd->se_cmd.se_tfo was associated. To address this, treat ISCSI_TM_FUNC_TASK_REASSIGN like any other TMR and call transport_init_se_cmd() + target_get_sess_cmd() to setup iscsi_cmd->se_cmd.se_tfo with se_cmd->cmd_kref of 2. This will ensure normal release operation once se_cmd->cmd_kref reaches zero and target_release_cmd_kref() is invoked, se_tmr_req will be released via existing target_free_cmd_mem() and core_tmr_release_req() code. Reported-by: Donald White Cc: Donald White Cc: Mike Christie Cc: Hannes Reinecke Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 541f66a875fc..048d4227327c 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1955,7 +1955,6 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, struct iscsi_tmr_req *tmr_req; struct iscsi_tm *hdr; int out_of_order_cmdsn = 0, ret; - bool sess_ref = false; u8 function, tcm_function = TMR_UNKNOWN; hdr = (struct iscsi_tm *) buf; @@ -1988,22 +1987,23 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, cmd->data_direction = DMA_NONE; cmd->tmr_req = kzalloc(sizeof(*cmd->tmr_req), GFP_KERNEL); - if (!cmd->tmr_req) + if (!cmd->tmr_req) { return iscsit_add_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); + } + + transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops, + conn->sess->se_sess, 0, DMA_NONE, + TCM_SIMPLE_TAG, cmd->sense_buffer + 2); + + target_get_sess_cmd(&cmd->se_cmd, true); /* * TASK_REASSIGN for ERL=2 / connection stays inside of * LIO-Target $FABRIC_MOD */ if (function != ISCSI_TM_FUNC_TASK_REASSIGN) { - transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops, - conn->sess->se_sess, 0, DMA_NONE, - TCM_SIMPLE_TAG, cmd->sense_buffer + 2); - - target_get_sess_cmd(&cmd->se_cmd, true); - sess_ref = true; tcm_function = iscsit_convert_tmf(function); if (tcm_function == TMR_UNKNOWN) { pr_err("Unknown iSCSI TMR Function:" @@ -2119,12 +2119,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * For connection recovery, this is also the default action for * TMR TASK_REASSIGN. */ - if (sess_ref) { - pr_debug("Handle TMR, using sess_ref=true check\n"); - target_put_sess_cmd(&cmd->se_cmd); - } - iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); + target_put_sess_cmd(&cmd->se_cmd); return 0; } EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd); -- GitLab From 3fc9fb13a4b2576aeab86c62fd64eb29ab68659c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 27 Oct 2017 20:52:56 -0700 Subject: [PATCH 1692/2898] iscsi-target: Fix non-immediate TMR reference leak This patch fixes a se_cmd->cmd_kref reference leak that can occur when a non immediate TMR is proceeded our of command sequence number order, and CMDSN_LOWER_THAN_EXP is returned by iscsit_sequence_cmd(). To address this bug, call target_put_sess_cmd() during this special case following what iscsit_process_scsi_cmd() does upon CMDSN_LOWER_THAN_EXP. Cc: Mike Christie Cc: Hannes Reinecke Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 048d4227327c..3b7bb589d301 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -2094,12 +2094,14 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); - if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) + if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) { out_of_order_cmdsn = 1; - else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) + } else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { + target_put_sess_cmd(&cmd->se_cmd); return 0; - else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) + } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { return -1; + } } iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); -- GitLab From b6ee15efe6788113c4184843365f74fde08e6284 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 31 Oct 2017 17:27:31 +0100 Subject: [PATCH 1693/2898] rtc: omap: Support scratch registers Register an nvmem device to expose the 3 scratch registers (total of 12 bytes) to both userspace and kernel space. Reviewed-by: Sekhar Nori Tested-by: Keerthy Reviewed-by: Keerthy Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-omap.c | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index d56d937966dc..1d666ac9ef70 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -70,6 +70,10 @@ #define OMAP_RTC_COMP_MSB_REG 0x50 #define OMAP_RTC_OSC_REG 0x54 +#define OMAP_RTC_SCRATCH0_REG 0x60 +#define OMAP_RTC_SCRATCH1_REG 0x64 +#define OMAP_RTC_SCRATCH2_REG 0x68 + #define OMAP_RTC_KICK0_REG 0x6c #define OMAP_RTC_KICK1_REG 0x70 @@ -667,6 +671,45 @@ static struct pinctrl_desc rtc_pinctrl_desc = { .owner = THIS_MODULE, }; +static int omap_rtc_scratch_read(void *priv, unsigned int offset, void *_val, + size_t bytes) +{ + struct omap_rtc *rtc = priv; + u32 *val = _val; + int i; + + for (i = 0; i < bytes / 4; i++) + val[i] = rtc_readl(rtc, + OMAP_RTC_SCRATCH0_REG + offset + (i * 4)); + + return 0; +} + +static int omap_rtc_scratch_write(void *priv, unsigned int offset, void *_val, + size_t bytes) +{ + struct omap_rtc *rtc = priv; + u32 *val = _val; + int i; + + rtc->type->unlock(rtc); + for (i = 0; i < bytes / 4; i++) + rtc_writel(rtc, + OMAP_RTC_SCRATCH0_REG + offset + (i * 4), val[i]); + rtc->type->lock(rtc); + + return 0; +} + +static struct nvmem_config omap_rtc_nvmem_config = { + .name = "omap_rtc_scratch", + .word_size = 4, + .stride = 4, + .size = OMAP_RTC_KICK0_REG - OMAP_RTC_SCRATCH0_REG, + .reg_read = omap_rtc_scratch_read, + .reg_write = omap_rtc_scratch_write, +}; + static int omap_rtc_probe(struct platform_device *pdev) { struct omap_rtc *rtc; @@ -804,6 +847,8 @@ static int omap_rtc_probe(struct platform_device *pdev) } rtc->rtc->ops = &omap_rtc_ops; + omap_rtc_nvmem_config.priv = rtc; + rtc->rtc->nvmem_config = &omap_rtc_nvmem_config; /* handle periodic and alarm irqs */ ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0, -- GitLab From a9687aa2764dd2669602bd19dc636cbeef5293d5 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Wed, 1 Nov 2017 08:01:20 -0700 Subject: [PATCH 1694/2898] rtc: add support for NXP PCF85363 real-time clock Note that alarms are not currently implemented. 64 bytes of nvmem is supported and exposed in sysfs (# is the instance number, starting with 0): /sys/bus/nvmem/devices/pcf85363-#/nvmem Signed-off-by: Eric Nelson Reviewed-by: Fabio Estevam Tested-by: Alexandre Belloni Acked-by: Rob Herring Signed-off-by: Alexandre Belloni --- .../devicetree/bindings/rtc/pcf85363.txt | 17 ++ drivers/rtc/Kconfig | 13 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-pcf85363.c | 220 ++++++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/pcf85363.txt create mode 100644 drivers/rtc/rtc-pcf85363.c diff --git a/Documentation/devicetree/bindings/rtc/pcf85363.txt b/Documentation/devicetree/bindings/rtc/pcf85363.txt new file mode 100644 index 000000000000..76fdabc59742 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/pcf85363.txt @@ -0,0 +1,17 @@ +NXP PCF85363 Real Time Clock +============================ + +Required properties: +- compatible: Should contain "nxp,pcf85363". +- reg: I2C address for chip. + +Optional properties: +- interrupts: IRQ line for the RTC (not implemented). + +Example: + +pcf85363: pcf85363@51 { + compatible = "nxp,pcf85363"; + reg = <0x51>; +}; + diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 616fe53c788e..47663e03f9a8 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -433,6 +433,19 @@ config RTC_DRV_PCF85063 This driver can also be built as a module. If so, the module will be called rtc-pcf85063. +config RTC_DRV_PCF85363 + tristate "NXP PCF85363" + depends on I2C + select REGMAP_I2C + help + If you say yes here you get support for the PCF85363 RTC chip. + + This driver can also be built as a module. If so, the module + will be called rtc-pcf85363. + + The nvmem interface will be named pcf85363-#, where # is the + zero-based instance number. + config RTC_DRV_PCF8563 tristate "Philips PCF8563/Epson RTC8564" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 5ec891a81f4f..0b5acd6b5cc3 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -114,6 +114,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o +obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c new file mode 100644 index 000000000000..ea04e9f0930b --- /dev/null +++ b/drivers/rtc/rtc-pcf85363.c @@ -0,0 +1,220 @@ +/* + * drivers/rtc/rtc-pcf85363.c + * + * Driver for NXP PCF85363 real-time clock. + * + * Copyright (C) 2017 Eric Nelson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Based loosely on rtc-8583 by Russell King, Wolfram Sang and Juergen Beisert + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Date/Time registers + */ +#define DT_100THS 0x00 +#define DT_SECS 0x01 +#define DT_MINUTES 0x02 +#define DT_HOURS 0x03 +#define DT_DAYS 0x04 +#define DT_WEEKDAYS 0x05 +#define DT_MONTHS 0x06 +#define DT_YEARS 0x07 + +/* + * Alarm registers + */ +#define DT_SECOND_ALM1 0x08 +#define DT_MINUTE_ALM1 0x09 +#define DT_HOUR_ALM1 0x0a +#define DT_DAY_ALM1 0x0b +#define DT_MONTH_ALM1 0x0c +#define DT_MINUTE_ALM2 0x0d +#define DT_HOUR_ALM2 0x0e +#define DT_WEEKDAY_ALM2 0x0f +#define DT_ALARM_EN 0x10 + +/* + * Time stamp registers + */ +#define DT_TIMESTAMP1 0x11 +#define DT_TIMESTAMP2 0x17 +#define DT_TIMESTAMP3 0x1d +#define DT_TS_MODE 0x23 + +/* + * control registers + */ +#define CTRL_OFFSET 0x24 +#define CTRL_OSCILLATOR 0x25 +#define CTRL_BATTERY 0x26 +#define CTRL_PIN_IO 0x27 +#define CTRL_FUNCTION 0x28 +#define CTRL_INTA_EN 0x29 +#define CTRL_INTB_EN 0x2a +#define CTRL_FLAGS 0x2b +#define CTRL_RAMBYTE 0x2c +#define CTRL_WDOG 0x2d +#define CTRL_STOP_EN 0x2e +#define CTRL_RESETS 0x2f +#define CTRL_RAM 0x40 + +#define NVRAM_SIZE 0x40 + +static struct i2c_driver pcf85363_driver; + +struct pcf85363 { + struct device *dev; + struct rtc_device *rtc; + struct nvmem_config nvmem_cfg; + struct regmap *regmap; +}; + +static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct pcf85363 *pcf85363 = dev_get_drvdata(dev); + unsigned char buf[DT_YEARS + 1]; + int ret, len = sizeof(buf); + + /* read the RTC date and time registers all at once */ + ret = regmap_bulk_read(pcf85363->regmap, DT_100THS, buf, len); + if (ret) { + dev_err(dev, "%s: error %d\n", __func__, ret); + return ret; + } + + tm->tm_year = bcd2bin(buf[DT_YEARS]); + /* adjust for 1900 base of rtc_time */ + tm->tm_year += 100; + + tm->tm_wday = buf[DT_WEEKDAYS] & 7; + buf[DT_SECS] &= 0x7F; + tm->tm_sec = bcd2bin(buf[DT_SECS]); + buf[DT_MINUTES] &= 0x7F; + tm->tm_min = bcd2bin(buf[DT_MINUTES]); + tm->tm_hour = bcd2bin(buf[DT_HOURS]); + tm->tm_mday = bcd2bin(buf[DT_DAYS]); + tm->tm_mon = bcd2bin(buf[DT_MONTHS]) - 1; + + return 0; +} + +static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct pcf85363 *pcf85363 = dev_get_drvdata(dev); + unsigned char buf[DT_YEARS + 1]; + int len = sizeof(buf); + + buf[DT_100THS] = 0; + buf[DT_SECS] = bin2bcd(tm->tm_sec); + buf[DT_MINUTES] = bin2bcd(tm->tm_min); + buf[DT_HOURS] = bin2bcd(tm->tm_hour); + buf[DT_DAYS] = bin2bcd(tm->tm_mday); + buf[DT_WEEKDAYS] = tm->tm_wday; + buf[DT_MONTHS] = bin2bcd(tm->tm_mon + 1); + buf[DT_YEARS] = bin2bcd(tm->tm_year % 100); + + return regmap_bulk_write(pcf85363->regmap, DT_100THS, + buf, len); +} + +static const struct rtc_class_ops rtc_ops = { + .read_time = pcf85363_rtc_read_time, + .set_time = pcf85363_rtc_set_time, +}; + +static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct pcf85363 *pcf85363 = priv; + + return regmap_bulk_read(pcf85363->regmap, CTRL_RAM + offset, + val, bytes); +} + +static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct pcf85363 *pcf85363 = priv; + + return regmap_bulk_write(pcf85363->regmap, CTRL_RAM + offset, + val, bytes); +} + +static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int pcf85363_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pcf85363 *pcf85363; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + pcf85363 = devm_kzalloc(&client->dev, sizeof(struct pcf85363), + GFP_KERNEL); + if (!pcf85363) + return -ENOMEM; + + pcf85363->regmap = devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(pcf85363->regmap)) { + dev_err(&client->dev, "regmap allocation failed\n"); + return PTR_ERR(pcf85363->regmap); + } + + pcf85363->dev = &client->dev; + i2c_set_clientdata(client, pcf85363); + + pcf85363->rtc = devm_rtc_allocate_device(pcf85363->dev); + if (IS_ERR(pcf85363->rtc)) + return PTR_ERR(pcf85363->rtc); + + pcf85363->nvmem_cfg.name = "pcf85363-"; + pcf85363->nvmem_cfg.word_size = 1; + pcf85363->nvmem_cfg.stride = 1; + pcf85363->nvmem_cfg.size = NVRAM_SIZE; + pcf85363->nvmem_cfg.reg_read = pcf85363_nvram_read; + pcf85363->nvmem_cfg.reg_write = pcf85363_nvram_write; + pcf85363->nvmem_cfg.priv = pcf85363; + pcf85363->rtc->nvmem_config = &pcf85363->nvmem_cfg; + pcf85363->rtc->ops = &rtc_ops; + + return rtc_register_device(pcf85363->rtc); +} + +static const struct of_device_id dev_ids[] = { + { .compatible = "nxp,pcf85363" }, + {} +}; +MODULE_DEVICE_TABLE(of, dev_ids); + +static struct i2c_driver pcf85363_driver = { + .driver = { + .name = "pcf85363", + .of_match_table = of_match_ptr(dev_ids), + }, + .probe = pcf85363_probe, +}; + +module_i2c_driver(pcf85363_driver); + +MODULE_AUTHOR("Eric Nelson"); +MODULE_DESCRIPTION("pcf85363 I2C RTC driver"); +MODULE_LICENSE("GPL"); -- GitLab From de6042d2fa8afe22b76e3c68fd6e9584c9415a3b Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 2 Nov 2017 18:58:12 -0700 Subject: [PATCH 1695/2898] rtc: m41t80: m41t80_sqw_set_rate should return 0 on success Previously it was returning -EINVAL upon success. Signed-off-by: Troy Kisky Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index f4c070ea8384..8f5843169dc2 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -510,10 +510,7 @@ static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate, reg = (reg & 0x0f) | (val << 4); ret = i2c_smbus_write_byte_data(client, reg_sqw, reg); - if (ret < 0) - return ret; - - return -EINVAL; + return ret; } static int m41t80_sqw_control(struct clk_hw *hw, bool enable) -- GitLab From c8384bb04261b9d32fe7402a6068ddaf38913b23 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 2 Nov 2017 18:58:13 -0700 Subject: [PATCH 1696/2898] rtc: m41t80: fix m41t80_sqw_round_rate return value Previously it was returning the best of 32768, 8192, 1024, 64, 2, 0 Now, best of 32768, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0 Signed-off-by: Troy Kisky Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 8f5843169dc2..42fc735a5446 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -468,18 +468,13 @@ static unsigned long m41t80_sqw_recalc_rate(struct clk_hw *hw, static long m41t80_sqw_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - int i, freq = M41T80_SQW_MAX_FREQ; - - if (freq <= rate) - return freq; - - for (i = 2; i <= ilog2(M41T80_SQW_MAX_FREQ); i++) { - freq /= 1 << i; - if (freq <= rate) - return freq; - } - - return 0; + if (rate >= M41T80_SQW_MAX_FREQ) + return M41T80_SQW_MAX_FREQ; + if (rate >= M41T80_SQW_MAX_FREQ / 4) + return M41T80_SQW_MAX_FREQ / 4; + if (!rate) + return 0; + return 1 << ilog2(rate); } static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate, -- GitLab From 2cb90ed3de1e279dbaf23df141f54eb9fb1861e6 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 2 Nov 2017 18:58:14 -0700 Subject: [PATCH 1697/2898] rtc: m41t80: avoid i2c read in m41t80_sqw_recalc_rate This is a little more efficient, and avoids the warning WARNING: possible circular locking dependency detected 4.14.0-rc7-00007 #14 Not tainted ------------------------------------------------------ alsactl/330 is trying to acquire lock: (prepare_lock){+.+.}, at: [] clk_prepare_lock+0x80/0xf4 but task is already holding lock: (i2c_register_adapter){+.+.}, at: [] i2c_adapter_lock_bus+0x14/0x18 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (i2c_register_adapter){+.+.}: rt_mutex_lock+0x44/0x5c i2c_adapter_lock_bus+0x14/0x18 i2c_transfer+0xa8/0xbc i2c_smbus_xfer+0x20c/0x5d8 i2c_smbus_read_byte_data+0x38/0x48 m41t80_sqw_recalc_rate+0x24/0x58 Signed-off-by: Troy Kisky Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 42fc735a5446..f44dcf628c87 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -154,6 +154,7 @@ struct m41t80_data { struct rtc_device *rtc; #ifdef CONFIG_COMMON_CLK struct clk_hw sqw; + unsigned long freq; #endif }; @@ -443,26 +444,28 @@ static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume); #ifdef CONFIG_COMMON_CLK #define sqw_to_m41t80_data(_hw) container_of(_hw, struct m41t80_data, sqw) -static unsigned long m41t80_sqw_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) +static unsigned long m41t80_decode_freq(int setting) +{ + return (setting == 0) ? 0 : (setting == 1) ? M41T80_SQW_MAX_FREQ : + M41T80_SQW_MAX_FREQ >> setting; +} + +static unsigned long m41t80_get_freq(struct m41t80_data *m41t80) { - struct m41t80_data *m41t80 = sqw_to_m41t80_data(hw); struct i2c_client *client = m41t80->client; int reg_sqw = (m41t80->features & M41T80_FEATURE_SQ_ALT) ? M41T80_REG_WDAY : M41T80_REG_SQW; int ret = i2c_smbus_read_byte_data(client, reg_sqw); - unsigned long val = M41T80_SQW_MAX_FREQ; if (ret < 0) return 0; + return m41t80_decode_freq(ret >> 4); +} - ret >>= 4; - if (ret == 0) - val = 0; - else if (ret > 1) - val = val / (1 << ret); - - return val; +static unsigned long m41t80_sqw_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return sqw_to_m41t80_data(hw)->freq; } static long m41t80_sqw_round_rate(struct clk_hw *hw, unsigned long rate, @@ -505,6 +508,8 @@ static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate, reg = (reg & 0x0f) | (val << 4); ret = i2c_smbus_write_byte_data(client, reg_sqw, reg); + if (!ret) + m41t80->freq = m41t80_decode_freq(val); return ret; } @@ -579,6 +584,7 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80) init.parent_names = NULL; init.num_parents = 0; m41t80->sqw.init = &init; + m41t80->freq = m41t80_get_freq(m41t80); /* optional override of the clockname */ of_property_read_string(node, "clock-output-names", &init.name); -- GitLab From 13bb1d78f2e372ec0d9b30489ac63768240140fc Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 2 Nov 2017 18:58:15 -0700 Subject: [PATCH 1698/2898] rtc: m41t80: avoid i2c read in m41t80_sqw_is_prepared This is a little more efficient and avoids the warning WARNING: possible circular locking dependency detected 4.14.0-rc7-00010 #16 Not tainted ------------------------------------------------------ kworker/2:1/70 is trying to acquire lock: (prepare_lock){+.+.}, at: [] clk_prepare_lock+0x80/0xf4 but task is already holding lock: (i2c_register_adapter){+.+.}, at: [] i2c_adapter_lock_bus+0x14/0x18 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (i2c_register_adapter){+.+.}: rt_mutex_lock+0x44/0x5c i2c_adapter_lock_bus+0x14/0x18 i2c_transfer+0xa8/0xbc i2c_smbus_xfer+0x20c/0x5d8 i2c_smbus_read_byte_data+0x38/0x48 m41t80_sqw_is_prepared+0x18/0x28 Signed-off-by: Troy Kisky Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index f44dcf628c87..96a606d5f6e6 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -155,6 +155,7 @@ struct m41t80_data { #ifdef CONFIG_COMMON_CLK struct clk_hw sqw; unsigned long freq; + unsigned int sqwe; #endif }; @@ -527,7 +528,10 @@ static int m41t80_sqw_control(struct clk_hw *hw, bool enable) else ret &= ~M41T80_ALMON_SQWE; - return i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, ret); + ret = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, ret); + if (!ret) + m41t80->sqwe = enable; + return ret; } static int m41t80_sqw_prepare(struct clk_hw *hw) @@ -542,14 +546,7 @@ static void m41t80_sqw_unprepare(struct clk_hw *hw) static int m41t80_sqw_is_prepared(struct clk_hw *hw) { - struct m41t80_data *m41t80 = sqw_to_m41t80_data(hw); - struct i2c_client *client = m41t80->client; - int ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); - - if (ret < 0) - return ret; - - return !!(ret & M41T80_ALMON_SQWE); + return sqw_to_m41t80_data(hw)->sqwe; } static const struct clk_ops m41t80_sqw_ops = { -- GitLab From 05a03bf260e0480bfc0db91b1fdbc2115e3f193b Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 2 Nov 2017 18:58:16 -0700 Subject: [PATCH 1699/2898] rtc: m41t80: remove unneeded checks from m41t80_sqw_set_rate m41t80_sqw_set_rate will be called with the result from m41t80_sqw_round_rate, so might as well make m41t80_sqw_set_rate(n) same as m41t80_sqw_set_rate(m41t80_sqw_round_rate(n)) As Russell King wrote[1], "clk_round_rate() is supposed to tell you what you end up with if you ask clk_set_rate() to set the exact same value you passed in - but clk_round_rate() won't modify the hardware." [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-January/080175.html Signed-off-by: Troy Kisky Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 96a606d5f6e6..c90fba3ed861 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -490,17 +490,12 @@ static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate, M41T80_REG_WDAY : M41T80_REG_SQW; int reg, ret, val = 0; - if (rate) { - if (!is_power_of_2(rate)) - return -EINVAL; - val = ilog2(rate); - if (val == ilog2(M41T80_SQW_MAX_FREQ)) - val = 1; - else if (val < (ilog2(M41T80_SQW_MAX_FREQ) - 1)) - val = ilog2(M41T80_SQW_MAX_FREQ) - val; - else - return -EINVAL; - } + if (rate >= M41T80_SQW_MAX_FREQ) + val = 1; + else if (rate >= M41T80_SQW_MAX_FREQ / 4) + val = 2; + else if (rate) + val = 15 - ilog2(rate); reg = i2c_smbus_read_byte_data(client, reg_sqw); if (reg < 0) -- GitLab From e0b6576fcd01b7dea606312d36b91ed0c047673b Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Fri, 3 Nov 2017 13:32:39 -0400 Subject: [PATCH 1700/2898] rtc: rx8010: Remove duplicate define Remove duplicate define for RX8010_YEAR Signed-off-by: Akshay Bhat Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8010.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index 1ed3403ff8ac..f948f7547806 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -24,7 +24,6 @@ #define RX8010_MDAY 0x14 #define RX8010_MONTH 0x15 #define RX8010_YEAR 0x16 -#define RX8010_YEAR 0x16 #define RX8010_RESV17 0x17 #define RX8010_ALMIN 0x18 #define RX8010_ALHOUR 0x19 -- GitLab From abf57f73ef0f88f215d35c1418bba0ab7bdee710 Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Fri, 3 Nov 2017 13:32:40 -0400 Subject: [PATCH 1701/2898] rtc: rx8010: Specify correct address for RX8010_RESV31 Define for reserved register 31 had the incorrect address. Specify the correct address. Reported-by: Jens-Peter Oswald Signed-off-by: Akshay Bhat Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index f948f7547806..2e06e5fc4a16 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -35,7 +35,7 @@ #define RX8010_CTRL 0x1F /* 0x20 to 0x2F are user registers */ #define RX8010_RESV30 0x30 -#define RX8010_RESV31 0x32 +#define RX8010_RESV31 0x31 #define RX8010_IRQ 0x32 #define RX8010_EXT_WADA BIT(3) -- GitLab From 9eb719855f6c9b21eb5889d9ac2ca1c60527ad89 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 7 Nov 2017 21:01:52 -0600 Subject: [PATCH 1702/2898] objtool: Fix cross-build Stephen Rothwell reported this cross-compilation build failure: | In file included from orc_dump.c:19:0: | orc.h:21:10: fatal error: asm/orc_types.h: No such file or directory | ... Caused by: 6a77cff819ae ("objtool: Move synced files to their original relative locations") Use the proper arch header files location, not the host-arch location. Bisected-by: Stephen Rothwell Reported-by: Stephen Rothwell Signed-off-by: Josh Poimboeuf Cc: Linus Torvalds Cc: Linux-Next Mailing List Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20171108030152.bd76eahiwjwjt3kp@treble Signed-off-by: Ingo Molnar --- tools/objtool/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index 6aaed251b4ed..0f94af3ccaaa 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -27,7 +27,7 @@ all: $(OBJTOOL) INCLUDES := -I$(srctree)/tools/include \ -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi \ - -I$(srctree)/tools/objtool/arch/$(HOSTARCH)/include + -I$(srctree)/tools/objtool/arch/$(ARCH)/include WARNINGS := $(EXTRA_WARNINGS) -Wno-switch-default -Wno-switch-enum -Wno-packed CFLAGS += -Wall -Werror $(WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) LDFLAGS += -lelf $(LIBSUBCMD) -- GitLab From 16b932770417b1bc304d87c48aa0bb8a3c1164e1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 8 Nov 2017 11:43:44 +0300 Subject: [PATCH 1703/2898] tcmu: Fix some memory corruption "udev->nl_reply_supported" is an int but on 64 bit arches we are writing 8 bytes of data to it so it corrupts four bytes beyond the end of the struct. Fixes: b849b4567549 ("target: Add netlink command reply supported option for each device") Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 9ddf0909d33e..d2b8d5ccb446 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -1724,11 +1724,10 @@ static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev, ret = -ENOMEM; break; } - ret = kstrtol(arg_p, 0, - (long int *) &udev->nl_reply_supported); + ret = kstrtoint(arg_p, 0, &udev->nl_reply_supported); kfree(arg_p); if (ret < 0) - pr_err("kstrtoul() failed for nl_reply_supported=\n"); + pr_err("kstrtoint() failed for nl_reply_supported=\n"); break; default: break; -- GitLab From 97488c73190bb785cba818bf31e7361a27aded41 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 8 Nov 2017 11:44:15 +0300 Subject: [PATCH 1704/2898] tcmu: Add a missing unlock on an error path We added a new error path here but we forgot to drop the lock first before returning. Fixes: 0d44374c1aae ("tcmu: fix double se_cmd completion") Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index d2b8d5ccb446..bf4fd40dde2b 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -888,6 +888,7 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) ret = tcmu_setup_cmd_timer(tcmu_cmd); if (ret) { tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cnt); + mutex_unlock(&udev->cmdr_lock); return TCM_OUT_OF_RESOURCES; } entry->hdr.cmd_id = tcmu_cmd->cmd_id; -- GitLab From 41cb3301c04d7f0b046ed296a34ef261c456dde8 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Tue, 7 Nov 2017 15:48:21 -0700 Subject: [PATCH 1705/2898] tools/testing/nvdimm: stricter bounds checking for error injection commands Ensure that the in/out sizes passed in the nd_cmd_package are sane for the fixed output size commands (i.e. inject error and clear injected error). Reported-by: Dariusz Dokupil Signed-off-by: Vishal Verma Signed-off-by: Dan Williams --- tools/testing/nvdimm/test/nfit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 79c5cb23693f..edab68c2e221 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -488,7 +488,7 @@ static int nfit_test_cmd_ars_error_inject(struct nfit_test *t, { int rc; - if (buf_len < sizeof(*err_inj)) { + if (buf_len != sizeof(*err_inj)) { rc = -EINVAL; goto err; } @@ -519,7 +519,7 @@ static int nfit_test_cmd_ars_inject_clear(struct nfit_test *t, { int rc; - if (buf_len < sizeof(*err_clr)) { + if (buf_len != sizeof(*err_clr)) { rc = -EINVAL; goto err; } -- GitLab From 4670269faba728683f7250319a65390946c028e3 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Fri, 30 Jun 2017 15:03:23 +0530 Subject: [PATCH 1706/2898] eCryptfs: constify attribute_group structures. attribute_groups are not supposed to change at runtime. All functions working with attribute_groups provided by work with const attribute_group. So mark the non-const structs as const. File size before: text data bss dec hex filename 6122 636 24 6782 1a7e fs/ecryptfs/main.o File size After adding 'const': text data bss dec hex filename 6186 604 24 6814 1a9e fs/ecryptfs/main.o Signed-off-by: Arvind Yadav Signed-off-by: Tyler Hicks --- fs/ecryptfs/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 1a419c3b8d4f..d0b438eff82d 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -781,7 +781,7 @@ static struct attribute *attributes[] = { NULL, }; -static struct attribute_group attr_group = { +static const struct attribute_group attr_group = { .attrs = attributes, }; -- GitLab From 54d11736ec3179954b6cdea4b4e1136d6bb39f39 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 8 Nov 2017 13:08:39 +0100 Subject: [PATCH 1707/2898] platform/x86: dell-smbios: fix string overflow The new sysfs code overwrites two fixed-length character arrays that are each one byte shorter than they need to be, to hold the trailing \0: drivers/platform/x86/dell-smbios.c: In function 'build_tokens_sysfs': drivers/platform/x86/dell-smbios.c:494:42: error: 'sprintf' writing a terminating nul past the end of the destination [-Werror=format-overflow=] sprintf(buffer_location, "%04x_location", drivers/platform/x86/dell-smbios.c:494:3: note: 'sprintf' output 14 bytes into a destination of size 13 drivers/platform/x86/dell-smbios.c:506:36: error: 'sprintf' writing a terminating nul past the end of the destination [-Werror=format-overflow=] sprintf(buffer_value, "%04x_value", drivers/platform/x86/dell-smbios.c:506:3: note: 'sprintf' output 11 bytes into a destination of size 10 This changes it to just use kasprintf(), which always gets it right. Discovered with gcc-7.1.1 with the following commit reverted: bd664f6b3e disable new gcc-7.1.1 warnings for now Fixes: 33b9ca1e53b4 ("platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens") Signed-off-by: Arnd Bergmann Acked-by: Mario Limonciello [dvhart: add subject prefix and reproducer details for context] Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-smbios.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index d99edd803c19..6a60db515bda 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -463,8 +463,6 @@ static struct platform_driver platform_driver = { static int build_tokens_sysfs(struct platform_device *dev) { - char buffer_location[13]; - char buffer_value[10]; char *location_name; char *value_name; size_t size; @@ -491,9 +489,8 @@ static int build_tokens_sysfs(struct platform_device *dev) if (da_tokens[i].tokenID == 0) continue; /* add location */ - sprintf(buffer_location, "%04x_location", - da_tokens[i].tokenID); - location_name = kstrdup(buffer_location, GFP_KERNEL); + location_name = kasprintf(GFP_KERNEL, "%04x_location", + da_tokens[i].tokenID); if (location_name == NULL) goto out_unwind_strings; sysfs_attr_init(&token_location_attrs[i].attr); @@ -503,9 +500,8 @@ static int build_tokens_sysfs(struct platform_device *dev) token_attrs[j++] = &token_location_attrs[i].attr; /* add value */ - sprintf(buffer_value, "%04x_value", - da_tokens[i].tokenID); - value_name = kstrdup(buffer_value, GFP_KERNEL); + value_name = kasprintf(GFP_KERNEL, "%04x_value", + da_tokens[i].tokenID); if (value_name == NULL) goto loop_fail_create_value; sysfs_attr_init(&token_value_attrs[i].attr); -- GitLab From 5e3e22971fb0b0d7d03286f1a619d0348748a243 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Sun, 5 Nov 2017 21:34:33 -0600 Subject: [PATCH 1708/2898] platform/x86: wmi: release mutex on module acquistion failure This failure mode should have also released the mutex. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 8c31ed4f0e1b..791449a2370f 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -868,8 +868,10 @@ static long wmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* let the driver do any filtering and do the call */ wdriver = container_of(wblock->dev.dev.driver, struct wmi_driver, driver); - if (!try_module_get(wdriver->driver.owner)) - return -EBUSY; + if (!try_module_get(wdriver->driver.owner)) { + ret = -EBUSY; + goto out_ioctl; + } ret = wdriver->filter_callback(&wblock->dev, cmd, buf); module_put(wdriver->driver.owner); if (ret) -- GitLab From 307ab2a99d190d3a7949258b8551b66887ce8cf4 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Sun, 5 Nov 2017 21:34:34 -0600 Subject: [PATCH 1709/2898] platform/x86: dell-smbios-wmi: release mutex lock on WMI call failure Unbound devices may race with calling this function causing the mutex to stay locked. This failure mode should have released the mutex too. Signed-off-by: Mario Limonciello Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/dell-smbios-wmi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c index 35c13815b24c..5cf9b13ce6e6 100644 --- a/drivers/platform/x86/dell-smbios-wmi.c +++ b/drivers/platform/x86/dell-smbios-wmi.c @@ -91,8 +91,10 @@ int dell_smbios_wmi_call(struct calling_interface_buffer *buffer) mutex_lock(&call_mutex); priv = get_first_smbios_priv(); - if (!priv) - return -ENODEV; + if (!priv) { + ret = -ENODEV; + goto out_wmi_call; + } size = sizeof(struct calling_interface_buffer); difference = priv->req_buf_size - sizeof(u64) - size; @@ -101,6 +103,7 @@ int dell_smbios_wmi_call(struct calling_interface_buffer *buffer) memcpy(&priv->buf->std, buffer, size); ret = run_smbios_call(priv->wdev); memcpy(buffer, &priv->buf->std, size); +out_wmi_call: mutex_unlock(&call_mutex); return ret; -- GitLab From cd3f6ad8389a5065811a5fd3befab7999ac4e117 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 7 Nov 2017 19:33:55 -0500 Subject: [PATCH 1710/2898] drm/amdgpu: Remove unused dc_stream from amdgpu_crtc It's no longer used. In fact, there is no more dc_stream object. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 59e2e5d59562..ffde1e9666e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -436,8 +436,6 @@ struct amdgpu_crtc { enum amdgpu_interrupt_state vsync_timer_enabled; int otg_inst; - /* After Set Mode stream will be non-NULL */ - const struct dc_stream *stream; struct drm_pending_vblank_event *event; }; -- GitLab From d83e87b239ec42eeda34850da342b3d8f104812b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 7 Nov 2017 19:29:40 -0500 Subject: [PATCH 1711/2898] amdgpu/dm: Remove unused forward declaration dc_stream has long been renamed to dc_stream_state, so this forward declaration hasn't been used at all. Signed-off-by: Harry Wentland Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index be3b70d683e7..f42f8357b676 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -199,8 +199,6 @@ struct amdgpu_framebuffer; struct amdgpu_display_manager; struct dc_validation_set; struct dc_plane_state; -/* TODO rename to dc_stream_state */ -struct dc_stream; struct dm_plane_state { struct drm_plane_state base; -- GitLab From f368d3bfde225199eef2216b03e0ba4944a3434a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= Date: Wed, 8 Nov 2017 22:47:06 +0100 Subject: [PATCH 1712/2898] amd/display: Fix potential null dereference in dce_calcs.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by smatch: bw_calcs() error: potential null dereference 'data' Reviewed-by: Alex Deucher Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index 4f8a95368ffc..6347712db834 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -2794,6 +2794,8 @@ bool bw_calcs(struct dc_context *ctx, { struct bw_calcs_data *data = kzalloc(sizeof(struct bw_calcs_data), GFP_KERNEL); + if (!data) + return false; populate_initial_data(pipe, pipe_count, data); -- GitLab From 804a6cfeb5c9e1caae86b345a5a8a50f77ddccc4 Mon Sep 17 00:00:00 2001 From: Akshay Bhat Date: Wed, 8 Nov 2017 14:58:14 -0500 Subject: [PATCH 1713/2898] rtc: rx8010: Fix for incorrect return value The err variable is not being reset after a successful read. Explicitly return 0 at the end of function call to account for all return paths. Reported-by: Jens-Peter Oswald Signed-off-by: Akshay Bhat Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8010.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index 2e06e5fc4a16..5c5938ab3d86 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -247,7 +247,7 @@ static int rx8010_init_client(struct i2c_client *client) rx8010->ctrlreg = (ctrl[1] & ~RX8010_CTRL_TEST); - return err; + return 0; } static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) @@ -276,7 +276,7 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE); t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled; - return err; + return 0; } static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t) -- GitLab From a3350f9c57ffad569c40f7320b89da1f3061c5bb Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 7 Nov 2017 13:12:17 +0100 Subject: [PATCH 1714/2898] rtc: pcf8563: fix output clock rate The pcf8563_clkout_recalc_rate function erroneously ignores the frequency index read from the CLKO register and always returns 32768 Hz. Fixes: a39a6405d5f9 ("rtc: pcf8563: add CLKOUT to common clock framework") Signed-off-by: Philipp Zabel Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf8563.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index cea6ea4df970..8c836c51a508 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -422,7 +422,7 @@ static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw, return 0; buf &= PCF8563_REG_CLKO_F_MASK; - return clkout_rates[ret]; + return clkout_rates[buf]; } static long pcf8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate, -- GitLab From 1856e0b2ace70a0231a94ec9d1286904c6ffa1ca Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 8 Nov 2017 05:27:45 +0100 Subject: [PATCH 1715/2898] rtc: pcf8563: don't alway enable the alarm Allow setting the alarm and later enable it instead of enabling it unconditionally. Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-pcf8563.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 8c836c51a508..3efc86c25d27 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -387,7 +387,7 @@ static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) if (err) return err; - return pcf8563_set_alarm_mode(client, 1); + return pcf8563_set_alarm_mode(client, !!tm->enabled); } static int pcf8563_irq_enable(struct device *dev, unsigned int enabled) -- GitLab From d0bcd82b13794c4bc89876e9383000fc1cb069d2 Mon Sep 17 00:00:00 2001 From: Loc Ho Date: Mon, 14 Apr 2014 12:09:04 -0600 Subject: [PATCH 1716/2898] rtc: xgene: Fix suspend/resume This patch fixes suspend/resume functions properly for the APM X-Gene SoC RTC driver. Signed-off-by: Loc Ho Reviewed-by: Mark Brown Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-xgene.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c index 65b432a096fe..360eae24a8c8 100644 --- a/drivers/rtc/rtc-xgene.c +++ b/drivers/rtc/rtc-xgene.c @@ -52,6 +52,7 @@ struct xgene_rtc_dev { void __iomem *csr_base; struct clk *clk; unsigned int irq_wake; + unsigned int irq_enabled; }; static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm) @@ -104,15 +105,19 @@ static int xgene_rtc_alarm_irq_enable(struct device *dev, u32 enabled) return 0; } +static int xgene_rtc_alarm_irq_enabled(struct device *dev) +{ + struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); + + return readl(pdata->csr_base + RTC_CCR) & RTC_CCR_IE ? 1 : 0; +} + static int xgene_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); - unsigned long rtc_time; unsigned long alarm_time; - rtc_time = readl(pdata->csr_base + RTC_CCVR); rtc_tm_to_time(&alrm->time, &alarm_time); - pdata->alarm_time = alarm_time; writel((u32) pdata->alarm_time, pdata->csr_base + RTC_CMR); @@ -180,12 +185,18 @@ static int xgene_rtc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Couldn't get the clock for RTC\n"); return -ENODEV; } - clk_prepare_enable(pdata->clk); + ret = clk_prepare_enable(pdata->clk); + if (ret) + return ret; /* Turn on the clock and the crystal */ writel(RTC_CCR_EN, pdata->csr_base + RTC_CCR); - device_init_wakeup(&pdev->dev, 1); + ret = device_init_wakeup(&pdev->dev, 1); + if (ret) { + clk_disable_unprepare(pdata->clk); + return ret; + } pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &xgene_rtc_ops, THIS_MODULE); @@ -218,14 +229,20 @@ static int xgene_rtc_suspend(struct device *dev) int irq; irq = platform_get_irq(pdev, 0); + + /* + * If this RTC alarm will be used for waking the system up, + * don't disable it of course. Else we just disable the alarm + * and await suspension. + */ if (device_may_wakeup(&pdev->dev)) { if (!enable_irq_wake(irq)) pdata->irq_wake = 1; } else { + pdata->irq_enabled = xgene_rtc_alarm_irq_enabled(dev); xgene_rtc_alarm_irq_enable(dev, 0); - clk_disable(pdata->clk); + clk_disable_unprepare(pdata->clk); } - return 0; } @@ -234,16 +251,22 @@ static int xgene_rtc_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); int irq; + int rc; irq = platform_get_irq(pdev, 0); + if (device_may_wakeup(&pdev->dev)) { if (pdata->irq_wake) { disable_irq_wake(irq); pdata->irq_wake = 0; } } else { - clk_enable(pdata->clk); - xgene_rtc_alarm_irq_enable(dev, 1); + rc = clk_prepare_enable(pdata->clk); + if (rc) { + dev_err(dev, "Unable to enable clock error %d\n", rc); + return rc; + } + xgene_rtc_alarm_irq_enable(dev, pdata->irq_enabled); } return 0; -- GitLab From 573e2bf05421d0dc69dc3c604f286b3473d2f2cd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 8 Nov 2017 13:08:10 +0100 Subject: [PATCH 1717/2898] rtc: xgene: mark PM functions as __maybe_unused The new xgene_rtc_alarm_irq_enabled() function is only accessed from PM code, which is inside of an #ifdef; this causes a harmless build warning when CONFIG_PM is disabled: drivers/rtc/rtc-xgene.c:108:12: error: 'xgene_rtc_alarm_irq_enabled' defined but not used [-Werror=unused-function] Just remove the #ifdef and use __maybe_unused annotations instead, to make the code more robust here. Fixes: d0bcd82b1379 ("rtc: xgene: Fix suspend/resume") Signed-off-by: Arnd Bergmann Reviewed-by: Loc Ho Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-xgene.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c index 360eae24a8c8..0c34d3b81279 100644 --- a/drivers/rtc/rtc-xgene.c +++ b/drivers/rtc/rtc-xgene.c @@ -221,8 +221,7 @@ static int xgene_rtc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int xgene_rtc_suspend(struct device *dev) +static int __maybe_unused xgene_rtc_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); @@ -246,7 +245,7 @@ static int xgene_rtc_suspend(struct device *dev) return 0; } -static int xgene_rtc_resume(struct device *dev) +static int __maybe_unused xgene_rtc_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); @@ -271,7 +270,6 @@ static int xgene_rtc_resume(struct device *dev) return 0; } -#endif static SIMPLE_DEV_PM_OPS(xgene_rtc_pm_ops, xgene_rtc_suspend, xgene_rtc_resume); -- GitLab From 4eae06de482bf370144704e31f65cd6dfbcebe94 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Fri, 27 Oct 2017 15:44:08 +0300 Subject: [PATCH 1718/2898] ovl: lockdep annotate of nested OVL_I(inode)->lock This fixes a lockdep splat when mounting a nested overlayfs. Fixes: a015dafcaf5b ("ovl: use ovl_inode mutex to synchronize...") Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/inode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 321511ed8c42..03f0ec2b73eb 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -14,6 +14,7 @@ #include #include #include "overlayfs.h" +#include "ovl_entry.h" int ovl_setattr(struct dentry *dentry, struct iattr *attr) { @@ -409,6 +410,7 @@ static inline void ovl_lockdep_annotate_inode_mutex_key(struct inode *inode) #ifdef CONFIG_LOCKDEP static struct lock_class_key ovl_i_mutex_key[OVL_MAX_NESTING]; static struct lock_class_key ovl_i_mutex_dir_key[OVL_MAX_NESTING]; + static struct lock_class_key ovl_i_lock_key[OVL_MAX_NESTING]; int depth = inode->i_sb->s_stack_depth - 1; @@ -419,6 +421,8 @@ static inline void ovl_lockdep_annotate_inode_mutex_key(struct inode *inode) lockdep_set_class(&inode->i_rwsem, &ovl_i_mutex_dir_key[depth]); else lockdep_set_class(&inode->i_rwsem, &ovl_i_mutex_key[depth]); + + lockdep_set_class(&OVL_I(inode)->lock, &ovl_i_lock_key[depth]); #endif } -- GitLab From b79e05aaa166755fafbf02db275175edb5175df8 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sun, 25 Jun 2017 16:37:17 +0300 Subject: [PATCH 1719/2898] ovl: no direct iteration for dir with origin xattr If a non-merge dir in an overlay mount has an overlay.origin xattr, it means it was once an upper merge dir, which may contain whiteouts and then the lower dir was removed under it. Do not iterate real dir directly in this case to avoid exposing whiteouts. [SzM] Set OVL_WHITEOUT for all merge directories as well. [amir] A directory that was just copied up does not have the OVL_WHITEOUTS flag. We need to set it to fix merge dir iteration. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/copy_up.c | 7 ++++++- fs/overlayfs/inode.c | 10 ++++++++++ fs/overlayfs/overlayfs.h | 4 ++++ fs/overlayfs/readdir.c | 24 ++++++++++++++++++++---- fs/overlayfs/super.c | 2 ++ fs/overlayfs/util.c | 13 +++++++++++++ 6 files changed, 55 insertions(+), 5 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index c441f9387a1b..d07ad7bbd041 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -486,6 +486,7 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp) static int ovl_copy_up_locked(struct ovl_copy_up_ctx *c) { struct inode *udir = c->destdir->d_inode; + struct inode *inode; struct dentry *newdentry = NULL; struct dentry *temp = NULL; int err; @@ -508,7 +509,11 @@ static int ovl_copy_up_locked(struct ovl_copy_up_ctx *c) if (err) goto out_cleanup; - ovl_inode_update(d_inode(c->dentry), newdentry); + inode = d_inode(c->dentry); + ovl_inode_update(inode, newdentry); + if (S_ISDIR(inode->i_mode)) + ovl_set_flag(OVL_WHITEOUTS, inode); + out: dput(temp); return err; diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 03f0ec2b73eb..e5a20fd3cbd4 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -661,6 +661,16 @@ struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, if (upperdentry && ovl_is_impuredir(upperdentry)) ovl_set_flag(OVL_IMPURE, inode); + /* Check for non-merge dir that may have whiteouts */ + if (S_ISDIR(realinode->i_mode)) { + struct ovl_entry *oe = dentry->d_fsdata; + + if (((upperdentry && lowerdentry) || oe->numlower > 1) || + ovl_check_origin_xattr(upperdentry ?: lowerdentry)) { + ovl_set_flag(OVL_WHITEOUTS, inode); + } + } + if (inode->i_state & I_NEW) unlock_new_inode(inode); out: diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index d9a0edd4e57e..d53157ccf0d7 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -28,7 +28,10 @@ enum ovl_path_type { #define OVL_XATTR_NLINK OVL_XATTR_PREFIX "nlink" enum ovl_flag { + /* Pure upper dir that may contain non pure upper entries */ OVL_IMPURE, + /* Non-merge dir that may contain whiteout entries */ + OVL_WHITEOUTS, OVL_INDEX, }; @@ -223,6 +226,7 @@ bool ovl_is_whiteout(struct dentry *dentry); struct file *ovl_path_open(struct path *path, int flags); int ovl_copy_up_start(struct dentry *dentry); void ovl_copy_up_end(struct dentry *dentry); +bool ovl_check_origin_xattr(struct dentry *dentry); bool ovl_check_dir_xattr(struct dentry *dentry, const char *name); int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, const char *name, const void *value, size_t size, diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 698b74dd750e..95d12755f847 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -316,21 +316,37 @@ static inline int ovl_dir_read(struct path *realpath, return err; } +/* + * Can we iterate real dir directly? + * + * Non-merge dir may contain whiteouts from a time it was a merge upper, before + * lower dir was removed under it and possibly before it was rotated from upper + * to lower layer. + */ +static bool ovl_dir_is_real(struct dentry *dir) +{ + return !ovl_test_flag(OVL_WHITEOUTS, d_inode(dir)); +} + static void ovl_dir_reset(struct file *file) { struct ovl_dir_file *od = file->private_data; struct ovl_dir_cache *cache = od->cache; struct dentry *dentry = file->f_path.dentry; - enum ovl_path_type type = ovl_path_type(dentry); + bool is_real; if (cache && ovl_dentry_version_get(dentry) != cache->version) { ovl_cache_put(od, dentry); od->cache = NULL; od->cursor = NULL; } - WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type)); - if (od->is_real && OVL_TYPE_MERGE(type)) + is_real = ovl_dir_is_real(dentry); + if (od->is_real != is_real) { + /* is_real can only become false when dir is copied up */ + if (WARN_ON(is_real)) + return; od->is_real = false; + } } static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list, @@ -816,7 +832,7 @@ static int ovl_dir_open(struct inode *inode, struct file *file) return PTR_ERR(realfile); } od->realfile = realfile; - od->is_real = !OVL_TYPE_MERGE(type); + od->is_real = ovl_dir_is_real(file->f_path.dentry); od->is_upper = OVL_TYPE_UPPER(type); file->private_data = od; diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index f5738e96a052..8d82a1cb655f 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1141,6 +1141,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) root_dentry->d_fsdata = oe; + /* Root is always merge -> can have whiteouts */ + ovl_set_flag(OVL_WHITEOUTS, d_inode(root_dentry)); ovl_inode_init(d_inode(root_dentry), upperpath.dentry, ovl_dentry_lower(root_dentry)); diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index b9b239fa5cfd..51ca8bd16009 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -329,6 +329,19 @@ void ovl_copy_up_end(struct dentry *dentry) mutex_unlock(&OVL_I(d_inode(dentry))->lock); } +bool ovl_check_origin_xattr(struct dentry *dentry) +{ + int res; + + res = vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0); + + /* Zero size value means "copied up but origin unknown" */ + if (res >= 0) + return true; + + return false; +} + bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) { int res; -- GitLab From 95e598e7ace2d89717cc3370c2126570667e2007 Mon Sep 17 00:00:00 2001 From: "zhangyi (F)" Date: Tue, 31 Oct 2017 22:57:00 +0200 Subject: [PATCH 1720/2898] ovl: simplify ovl_check_empty_and_clear() Filter out non-whiteout non-upper entries from list of merge dir entries while checking if merge dir is empty in ovl_check_empty_dir(). The remaining work for ovl_clear_empty() is to clear all entries on the list. [amir: split patch from rmdir bug fix] Signed-off-by: zhangyi (F) Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/dir.c | 5 ++--- fs/overlayfs/readdir.c | 27 ++++++++++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index cc961a3bd3bd..4edef400fe51 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -300,7 +300,6 @@ static struct dentry *ovl_check_empty_and_clear(struct dentry *dentry) { int err; struct dentry *ret = NULL; - enum ovl_path_type type = ovl_path_type(dentry); LIST_HEAD(list); err = ovl_check_empty_dir(dentry, &list); @@ -313,13 +312,13 @@ static struct dentry *ovl_check_empty_and_clear(struct dentry *dentry) * When removing an empty opaque directory, then it makes no sense to * replace it with an exact replica of itself. * - * If no upperdentry then skip clearing whiteouts. + * If upperdentry has whiteouts, clear them. * * Can race with copy-up, since we don't hold the upperdir mutex. * Doesn't matter, since copy-up can't create a non-empty directory * from an empty one. */ - if (OVL_TYPE_UPPER(type) && OVL_TYPE_MERGE(type)) + if (!list_empty(&list)) ret = ovl_clear_empty(dentry, &list); out_free: diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 95d12755f847..a5ad5b33b599 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -26,6 +26,7 @@ struct ovl_cache_entry { struct list_head l_node; struct rb_node node; struct ovl_cache_entry *next_maybe_whiteout; + bool is_upper; bool is_whiteout; char name[]; }; @@ -158,6 +159,7 @@ static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd, /* Defer setting d_ino for upper entry to ovl_iterate() */ if (ovl_calc_d_ino(rdd, p)) p->ino = 0; + p->is_upper = rdd->is_upper; p->is_whiteout = false; if (d_type == DT_CHR) { @@ -851,7 +853,7 @@ const struct file_operations ovl_dir_operations = { int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) { int err; - struct ovl_cache_entry *p; + struct ovl_cache_entry *p, *n; struct rb_root root = RB_ROOT; err = ovl_dir_read_merged(dentry, list, &root); @@ -860,18 +862,29 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) err = 0; - list_for_each_entry(p, list, l_node) { - if (p->is_whiteout) - continue; + list_for_each_entry_safe(p, n, list, l_node) { + /* + * Select whiteouts in upperdir, they should + * be cleared when deleting this directory. + */ + if (p->is_whiteout) { + if (p->is_upper) + continue; + goto del_entry; + } if (p->name[0] == '.') { if (p->len == 1) - continue; + goto del_entry; if (p->len == 2 && p->name[1] == '.') - continue; + goto del_entry; } err = -ENOTEMPTY; break; + +del_entry: + list_del(&p->l_node); + kfree(p); } return err; @@ -885,7 +898,7 @@ void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list) list_for_each_entry(p, list, l_node) { struct dentry *dentry; - if (!p->is_whiteout) + if (WARN_ON(!p->is_whiteout || !p->is_upper)) continue; dentry = lookup_one_len(p->name, upper, p->len); -- GitLab From 07f6fff148364ad7c0174d6536a124a0679177a2 Mon Sep 17 00:00:00 2001 From: "zhangyi (F)" Date: Tue, 4 Jul 2017 13:02:27 +0300 Subject: [PATCH 1721/2898] ovl: fix rmdir problem on non-merge dir with origin xattr An "origin && non-merge" upper dir may have leftover whiteouts that were created in past mount. overlayfs does no clear this dir when we delete it, which may lead to rmdir fail or temp file left in workdir. Simple reproducer: mkdir lower upper work merge mkdir -p lower/dir touch lower/dir/a mount -t overlay overlay -olowerdir=lower,upperdir=upper,\ workdir=work merge rm merge/dir/a umount merge rm -rf lower/* touch lower/dir (*) mount -t overlay overlay -olowerdir=lower,upperdir=upper,\ workdir=work merge rm -rf merge/dir Syslog dump: overlayfs: cleanup of 'work/#7' failed (-39) (*): if we do not create the regular file, the result is different: rm: cannot remove "dir/": Directory not empty This patch adds a check for the case of non-merge dir that may contain whiteouts, and calls ovl_check_empty_dir() to check and clear whiteouts from upper dir when an empty dir is being deleted. [amir: split patch from ovl_check_empty_dir() cleanup rename ovl_is_origin() to ovl_may_have_whiteouts() check OVL_WHITEOUTS flag instead of checking origin xattr] Signed-off-by: zhangyi (F) Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/dir.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 4edef400fe51..ef533198be45 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -181,6 +181,11 @@ static bool ovl_type_origin(struct dentry *dentry) return OVL_TYPE_ORIGIN(ovl_path_type(dentry)); } +static bool ovl_may_have_whiteouts(struct dentry *dentry) +{ + return ovl_test_flag(OVL_WHITEOUTS, d_inode(dentry)); +} + static int ovl_create_upper(struct dentry *dentry, struct inode *inode, struct cattr *attr, struct dentry *hardlink) { @@ -697,8 +702,9 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir) struct dentry *opaquedir = NULL; int err; - /* Redirect dir can be !ovl_lower_positive && OVL_TYPE_MERGE */ - if (is_dir && ovl_dentry_get_redirect(dentry)) { + /* Redirect/origin dir can be !ovl_lower_positive && not clean */ + if (is_dir && (ovl_dentry_get_redirect(dentry) || + ovl_may_have_whiteouts(dentry))) { opaquedir = ovl_check_empty_and_clear(dentry); err = PTR_ERR(opaquedir); if (IS_ERR(opaquedir)) @@ -945,7 +951,8 @@ static int ovl_rename(struct inode *olddir, struct dentry *old, old_cred = ovl_override_creds(old->d_sb); - if (overwrite && new_is_dir && ovl_type_merge_or_lower(new)) { + if (overwrite && new_is_dir && (ovl_type_merge_or_lower(new) || + ovl_may_have_whiteouts(new))) { opaquedir = ovl_check_empty_and_clear(new); err = PTR_ERR(opaquedir); if (IS_ERR(opaquedir)) { -- GitLab From ee023c30d7d6bc21d3a85f3625a30209bdcc41e6 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Mon, 30 Oct 2017 13:33:11 +0200 Subject: [PATCH 1722/2898] ovl: move include of ovl_entry.h into overlayfs.h Most overlayfs c files already explicitly include ovl_entry.h to use overlay entry struct definitions and upcoming changes are going to require even more c files to include this header. All overlayfs c files include overlayfs.h and overlayfs.h itself refers to some structs defined in ovl_entry.h, so it seems more logic to include ovl_entry.h from overlayfs.h than from c files. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/copy_up.c | 1 - fs/overlayfs/inode.c | 1 - fs/overlayfs/namei.c | 1 - fs/overlayfs/overlayfs.h | 1 + fs/overlayfs/super.c | 1 - fs/overlayfs/util.c | 1 - 6 files changed, 1 insertion(+), 5 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index d07ad7bbd041..eb3b8d39fb61 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -22,7 +22,6 @@ #include #include #include "overlayfs.h" -#include "ovl_entry.h" #define OVL_COPY_UP_CHUNK_SIZE (1 << 20) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index e5a20fd3cbd4..52aaa8530710 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -14,7 +14,6 @@ #include #include #include "overlayfs.h" -#include "ovl_entry.h" int ovl_setattr(struct dentry *dentry, struct iattr *attr) { diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index a12dc10bf726..505a4b8902fc 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -15,7 +15,6 @@ #include #include #include "overlayfs.h" -#include "ovl_entry.h" struct ovl_lookup_data { struct qstr name; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index d53157ccf0d7..1cf3bdd193a4 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -9,6 +9,7 @@ #include #include +#include "ovl_entry.h" enum ovl_path_type { __OVL_PATH_UPPER = (1 << 0), diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 8d82a1cb655f..e3d49e965224 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -18,7 +18,6 @@ #include #include #include "overlayfs.h" -#include "ovl_entry.h" MODULE_AUTHOR("Miklos Szeredi "); MODULE_DESCRIPTION("Overlay filesystem"); diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 51ca8bd16009..9158d17bb320 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -17,7 +17,6 @@ #include #include #include "overlayfs.h" -#include "ovl_entry.h" int ovl_want_write(struct dentry *dentry) { -- GitLab From b93436320c1e9089a055941523571cd7c037f7cb Mon Sep 17 00:00:00 2001 From: Chandan Rajendra Date: Mon, 24 Jul 2017 01:57:54 -0500 Subject: [PATCH 1723/2898] ovl: re-structure overlay lower layers in-memory Define new structures to represent overlay instance lower layers and overlay merge dir lower layers to make room for storing more per layer information in-memory. Instead of keeping the fs instance lower layers in an array of struct vfsmount, keep them in an array of new struct ovl_layer, that has a pointer to struct vfsmount. Instead of keeping the dentry lower layers in an array of struct path, keep them in an array of new struct ovl_path, that has a pointer to struct dentry and to struct ovl_layer. Add a small helper to find the fs layer id that correspopnds to a lower struct ovl_path and use it in ovl_lookup(). [amir: split re-structure from anonymous bdev patch] Signed-off-by: Chandan Rajendra Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/namei.c | 52 +++++++++++++++++++-------------- fs/overlayfs/overlayfs.h | 4 +-- fs/overlayfs/ovl_entry.h | 13 +++++++-- fs/overlayfs/readdir.c | 4 +-- fs/overlayfs/super.c | 62 ++++++++++++++++++++++------------------ fs/overlayfs/util.c | 7 ++++- 6 files changed, 86 insertions(+), 56 deletions(-) diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 505a4b8902fc..6cc3ece3417d 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -285,16 +285,15 @@ static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d, static int ovl_check_origin(struct dentry *upperdentry, - struct path *lowerstack, unsigned int numlower, - struct path **stackp, unsigned int *ctrp) + struct ovl_path *lower, unsigned int numlower, + struct ovl_path **stackp, unsigned int *ctrp) { struct vfsmount *mnt; struct dentry *origin = NULL; int i; - for (i = 0; i < numlower; i++) { - mnt = lowerstack[i].mnt; + mnt = lower[i].layer->mnt; origin = ovl_get_origin(upperdentry, mnt); if (IS_ERR(origin)) return PTR_ERR(origin); @@ -308,12 +307,12 @@ static int ovl_check_origin(struct dentry *upperdentry, BUG_ON(*ctrp); if (!*stackp) - *stackp = kmalloc(sizeof(struct path), GFP_KERNEL); + *stackp = kmalloc(sizeof(struct ovl_path), GFP_KERNEL); if (!*stackp) { dput(origin); return -ENOMEM; } - **stackp = (struct path) { .dentry = origin, .mnt = mnt }; + **stackp = (struct ovl_path){.dentry = origin, .layer = lower[i].layer}; *ctrp = 1; return 0; @@ -383,13 +382,13 @@ int ovl_verify_origin(struct dentry *dentry, struct vfsmount *mnt, * OVL_XATTR_ORIGIN and that origin file handle can be decoded to lower path. * Return 0 on match, -ESTALE on mismatch or stale origin, < 0 on error. */ -int ovl_verify_index(struct dentry *index, struct path *lowerstack, +int ovl_verify_index(struct dentry *index, struct ovl_path *lower, unsigned int numlower) { struct ovl_fh *fh = NULL; size_t len; - struct path origin = { }; - struct path *stack = &origin; + struct ovl_path origin = { }; + struct ovl_path *stack = &origin; unsigned int ctr = 0; int err; @@ -428,7 +427,7 @@ int ovl_verify_index(struct dentry *index, struct path *lowerstack, if (err) goto fail; - err = ovl_check_origin(index, lowerstack, numlower, &stack, &ctr); + err = ovl_check_origin(index, lower, numlower, &stack, &ctr); if (!err && !ctr) err = -ESTALE; if (err) @@ -567,11 +566,24 @@ int ovl_path_next(int idx, struct dentry *dentry, struct path *path) idx++; } BUG_ON(idx > oe->numlower); - *path = oe->lowerstack[idx - 1]; + path->dentry = oe->lowerstack[idx - 1].dentry; + path->mnt = oe->lowerstack[idx - 1].layer->mnt; return (idx < oe->numlower) ? idx + 1 : -1; } +static int ovl_find_layer(struct ovl_fs *ofs, struct ovl_path *path) +{ + int i; + + for (i = 0; i < ofs->numlower; i++) { + if (ofs->lower_layers[i].mnt == path->layer->mnt) + break; + } + + return i; +} + struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { @@ -580,7 +592,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, struct ovl_fs *ofs = dentry->d_sb->s_fs_info; struct ovl_entry *poe = dentry->d_parent->d_fsdata; struct ovl_entry *roe = dentry->d_sb->s_root->d_fsdata; - struct path *stack = NULL; + struct ovl_path *stack = NULL; struct dentry *upperdir, *upperdentry = NULL; struct dentry *index = NULL; unsigned int ctr = 0; @@ -645,17 +657,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, if (!d.stop && poe->numlower) { err = -ENOMEM; - stack = kcalloc(ofs->numlower, sizeof(struct path), + stack = kcalloc(ofs->numlower, sizeof(struct ovl_path), GFP_KERNEL); if (!stack) goto out_put_upper; } for (i = 0; !d.stop && i < poe->numlower; i++) { - struct path lowerpath = poe->lowerstack[i]; + struct ovl_path lower = poe->lowerstack[i]; d.last = i == poe->numlower - 1; - err = ovl_lookup_layer(lowerpath.dentry, &d, &this); + err = ovl_lookup_layer(lower.dentry, &d, &this); if (err) goto out_put; @@ -663,7 +675,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, continue; stack[ctr].dentry = this; - stack[ctr].mnt = lowerpath.mnt; + stack[ctr].layer = lower.layer; ctr++; if (d.stop) @@ -673,10 +685,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, poe = roe; /* Find the current layer on the root dentry */ - for (i = 0; i < poe->numlower; i++) - if (poe->lowerstack[i].mnt == lowerpath.mnt) - break; - if (WARN_ON(i == poe->numlower)) + i = ovl_find_layer(ofs, &lower); + if (WARN_ON(i == ofs->numlower)) break; } } @@ -699,7 +709,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, goto out_put; oe->opaque = upperopaque; - memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); + memcpy(oe->lowerstack, stack, sizeof(struct ovl_path) * ctr); dentry->d_fsdata = oe; if (upperdentry) diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 1cf3bdd193a4..cefe5a97d048 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -251,7 +251,7 @@ static inline bool ovl_is_impuredir(struct dentry *dentry) /* namei.c */ int ovl_verify_origin(struct dentry *dentry, struct vfsmount *mnt, struct dentry *origin, bool is_upper, bool set); -int ovl_verify_index(struct dentry *index, struct path *lowerstack, +int ovl_verify_index(struct dentry *index, struct ovl_path *lower, unsigned int numlower); int ovl_get_index_name(struct dentry *origin, struct qstr *name); int ovl_path_next(int idx, struct dentry *dentry, struct path *path); @@ -268,7 +268,7 @@ int ovl_check_d_type_supported(struct path *realpath); void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, struct dentry *dentry, int level); int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt, - struct path *lowerstack, unsigned int numlower); + struct ovl_path *lower, unsigned int numlower); /* inode.c */ int ovl_set_nlink_upper(struct dentry *dentry); diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index 25d9b5adcd42..1e28329b5db8 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -17,11 +17,20 @@ struct ovl_config { bool index; }; +struct ovl_layer { + struct vfsmount *mnt; +}; + +struct ovl_path { + struct ovl_layer *layer; + struct dentry *dentry; +}; + /* private information held for overlayfs's superblock */ struct ovl_fs { struct vfsmount *upper_mnt; unsigned numlower; - struct vfsmount **lower_mnt; + struct ovl_layer *lower_layers; /* workbasedir is the path at workdir= mount option */ struct dentry *workbasedir; /* workdir is the 'work' directory under workbasedir */ @@ -52,7 +61,7 @@ struct ovl_entry { struct rcu_head rcu; }; unsigned numlower; - struct path lowerstack[]; + struct ovl_path lowerstack[]; }; struct ovl_entry *ovl_alloc_entry(unsigned int numlower); diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index a5ad5b33b599..914e77e10f0f 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -1014,7 +1014,7 @@ void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, } int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt, - struct path *lowerstack, unsigned int numlower) + struct ovl_path *lower, unsigned int numlower) { int err; struct dentry *index = NULL; @@ -1049,7 +1049,7 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt, index = NULL; break; } - err = ovl_verify_index(index, lowerstack, numlower); + err = ovl_verify_index(index, lower, numlower); /* Cleanup stale and orphan index entries */ if (err && (err == -ESTALE || err == -ENOENT)) err = ovl_cleanup(dir, index); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index e3d49e965224..a10fff49194b 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -220,8 +220,8 @@ static void ovl_put_super(struct super_block *sb) ovl_inuse_unlock(ufs->upper_mnt->mnt_root); mntput(ufs->upper_mnt); for (i = 0; i < ufs->numlower; i++) - mntput(ufs->lower_mnt[i]); - kfree(ufs->lower_mnt); + mntput(ufs->lower_layers[i].mnt); + kfree(ufs->lower_layers); kfree(ufs->config.lowerdir); kfree(ufs->config.upperdir); @@ -1026,24 +1026,26 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) } err = -ENOMEM; - ufs->lower_mnt = kcalloc(numlower, sizeof(struct vfsmount *), GFP_KERNEL); - if (ufs->lower_mnt == NULL) + ufs->lower_layers = kcalloc(numlower, sizeof(struct ovl_layer), + GFP_KERNEL); + if (ufs->lower_layers == NULL) goto out_put_workdir; for (i = 0; i < numlower; i++) { - struct vfsmount *mnt = clone_private_mount(&stack[i]); + struct vfsmount *mnt; + mnt = clone_private_mount(&stack[i]); err = PTR_ERR(mnt); if (IS_ERR(mnt)) { pr_err("overlayfs: failed to clone lowerpath\n"); - goto out_put_lower_mnt; + goto out_put_lower_layers; } /* - * Make lower_mnt R/O. That way fchmod/fchown on lower file + * Make lower layers R/O. That way fchmod/fchown on lower file * will fail instead of modifying lower fs. */ mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME; - ufs->lower_mnt[ufs->numlower] = mnt; + ufs->lower_layers[ufs->numlower].mnt = mnt; ufs->numlower++; /* Check if all lower layers are on same sb */ @@ -1059,13 +1061,25 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) else if (ufs->upper_mnt->mnt_sb != ufs->same_sb) ufs->same_sb = NULL; + err = -ENOMEM; + oe = ovl_alloc_entry(numlower); + if (!oe) + goto out_put_lower_layers; + + for (i = 0; i < numlower; i++) { + oe->lowerstack[i].dentry = stack[i].dentry; + oe->lowerstack[i].layer = &(ufs->lower_layers[i]); + } + if (!(ovl_force_readonly(ufs)) && ufs->config.index) { /* Verify lower root is upper root origin */ - err = ovl_verify_origin(upperpath.dentry, ufs->lower_mnt[0], - stack[0].dentry, false, true); + err = ovl_verify_origin(upperpath.dentry, + oe->lowerstack[0].layer->mnt, + oe->lowerstack[0].dentry, + false, true); if (err) { pr_err("overlayfs: failed to verify upper root origin\n"); - goto out_put_lower_mnt; + goto out_free_oe; } ufs->indexdir = ovl_workdir_create(sb, ufs, workpath.dentry, @@ -1081,7 +1095,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) if (!err) err = ovl_indexdir_cleanup(ufs->indexdir, ufs->upper_mnt, - stack, numlower); + oe->lowerstack, + numlower); } if (err || !ufs->indexdir) pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n"); @@ -1106,11 +1121,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) /* Never override disk quota limits or use reserved space */ cap_lower(cred->cap_effective, CAP_SYS_RESOURCE); - err = -ENOMEM; - oe = ovl_alloc_entry(numlower); - if (!oe) - goto out_put_cred; - sb->s_magic = OVERLAYFS_SUPER_MAGIC; sb->s_op = &ovl_super_operations; sb->s_xattr = ovl_xattr_handlers; @@ -1119,11 +1129,12 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, 0)); if (!root_dentry) - goto out_free_oe; + goto out_put_cred; mntput(upperpath.mnt); for (i = 0; i < numlower; i++) mntput(stack[i].mnt); + kfree(stack); mntput(workpath.mnt); kfree(lowertmp); @@ -1132,11 +1143,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) if (ovl_is_impuredir(upperpath.dentry)) ovl_set_flag(OVL_IMPURE, d_inode(root_dentry)); } - for (i = 0; i < numlower; i++) { - oe->lowerstack[i].dentry = stack[i].dentry; - oe->lowerstack[i].mnt = ufs->lower_mnt[i]; - } - kfree(stack); root_dentry->d_fsdata = oe; @@ -1149,16 +1155,16 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) return 0; -out_free_oe: - kfree(oe); out_put_cred: put_cred(ufs->creator_cred); out_put_indexdir: dput(ufs->indexdir); -out_put_lower_mnt: +out_free_oe: + kfree(oe); +out_put_lower_layers: for (i = 0; i < ufs->numlower; i++) - mntput(ufs->lower_mnt[i]); - kfree(ufs->lower_mnt); + mntput(ufs->lower_layers[i].mnt); + kfree(ufs->lower_layers); out_put_workdir: dput(ufs->workdir); mntput(ufs->upper_mnt); diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 9158d17bb320..d6bb1c9f5e7a 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -124,7 +124,12 @@ void ovl_path_lower(struct dentry *dentry, struct path *path) { struct ovl_entry *oe = dentry->d_fsdata; - *path = oe->numlower ? oe->lowerstack[0] : (struct path) { }; + if (oe->numlower) { + path->mnt = oe->lowerstack[0].layer->mnt; + path->dentry = oe->lowerstack[0].dentry; + } else { + *path = (struct path) { }; + } } enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) -- GitLab From 2a9c6d066e98c1fe51a735b1439929f2f2afd891 Mon Sep 17 00:00:00 2001 From: Chandan Rajendra Date: Wed, 1 Nov 2017 20:12:49 +0200 Subject: [PATCH 1724/2898] ovl: allocate anonymous devs for lowerdirs Generate unique values of st_dev per lower layer for non-samefs overlay mount. The unique values are obtained by allocating anonymous bdevs for each of the lowerdirs in the overlayfs instance. The anonymous bdev is going to be returned by stat(2) for lowerdir non-dir entries in non-samefs case. [amir: split from ovl_getattr() and re-structure patches] Signed-off-by: Chandan Rajendra Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/ovl_entry.h | 1 + fs/overlayfs/super.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index 1e28329b5db8..93eb6a044dd2 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -19,6 +19,7 @@ struct ovl_config { struct ovl_layer { struct vfsmount *mnt; + dev_t pseudo_dev; }; struct ovl_path { diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index a10fff49194b..2c9f48096ff0 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -219,8 +219,10 @@ static void ovl_put_super(struct super_block *sb) if (ufs->upper_mnt && ufs->upperdir_locked) ovl_inuse_unlock(ufs->upper_mnt->mnt_root); mntput(ufs->upper_mnt); - for (i = 0; i < ufs->numlower; i++) + for (i = 0; i < ufs->numlower; i++) { mntput(ufs->lower_layers[i].mnt); + free_anon_bdev(ufs->lower_layers[i].pseudo_dev); + } kfree(ufs->lower_layers); kfree(ufs->config.lowerdir); @@ -1032,11 +1034,19 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) goto out_put_workdir; for (i = 0; i < numlower; i++) { struct vfsmount *mnt; + dev_t dev; + + err = get_anon_bdev(&dev); + if (err) { + pr_err("overlayfs: failed to get anonymous bdev for lowerpath\n"); + goto out_put_lower_layers; + } mnt = clone_private_mount(&stack[i]); err = PTR_ERR(mnt); if (IS_ERR(mnt)) { pr_err("overlayfs: failed to clone lowerpath\n"); + free_anon_bdev(dev); goto out_put_lower_layers; } /* @@ -1046,6 +1056,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME; ufs->lower_layers[ufs->numlower].mnt = mnt; + ufs->lower_layers[ufs->numlower].pseudo_dev = dev; ufs->numlower++; /* Check if all lower layers are on same sb */ @@ -1162,8 +1173,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) out_free_oe: kfree(oe); out_put_lower_layers: - for (i = 0; i < ufs->numlower; i++) + for (i = 0; i < ufs->numlower; i++) { + if (ufs->lower_layers[i].mnt) + free_anon_bdev(ufs->lower_layers[i].pseudo_dev); mntput(ufs->lower_layers[i].mnt); + } kfree(ufs->lower_layers); out_put_workdir: dput(ufs->workdir); -- GitLab From ba1e563cdc6b07f2d5d9eee854fb3cdf3596470f Mon Sep 17 00:00:00 2001 From: Chandan Rajendra Date: Mon, 24 Jul 2017 01:57:54 -0500 Subject: [PATCH 1725/2898] ovl: return anonymous st_dev for lower inodes For non-samefs setup, to make sure that st_dev/st_ino pair is unique across the system, we return a unique anonymous st_dev for stat(2) of lower layer inode. A following patch is going to fix constant st_dev/st_ino across copy up by returning origin st_dev/st_ino for copied up objects. If the st_dev/st_ino for copied up object would have been the same as that of the real underlying lower file, running diff on underlying lower file and overlay copied up file would result in diff reporting that the 2 files are equal when in fact, they may have different content. [amir: simplify ovl_get_pseudo_dev() split from allocate anonymous bdev patch] Signed-off-by: Chandan Rajendra Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/inode.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 52aaa8530710..b599059d6f78 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -15,6 +15,14 @@ #include #include "overlayfs.h" + +static dev_t ovl_get_pseudo_dev(struct dentry *dentry) +{ + struct ovl_entry *oe = dentry->d_fsdata; + + return oe->lowerstack[0].layer->pseudo_dev; +} + int ovl_setattr(struct dentry *dentry, struct iattr *attr) { int err; @@ -121,6 +129,13 @@ int ovl_getattr(const struct path *path, struct kstat *stat, */ stat->dev = dentry->d_sb->s_dev; stat->ino = dentry->d_inode->i_ino; + } else if (!OVL_TYPE_UPPER(type)) { + /* + * For non-samefs setup, to make sure that st_dev/st_ino pair + * is unique across the system, we use a unique anonymous + * st_dev for lower layer inode. + */ + stat->dev = ovl_get_pseudo_dev(dentry); } /* -- GitLab From a0c5ad307ac09fa1c73b57bfd94f4c3fd6ba92d8 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 1 Nov 2017 00:45:40 +0200 Subject: [PATCH 1726/2898] ovl: relax same fs constraint for constant st_ino For the case of all layers not on the same fs, return the copy up origin inode st_dev/st_ino for non-dir from stat(2). This guaranties constant st_dev/st_ino for non-dir across copy up. Like the same fs case, st_ino of non-dir is also persistent. If the st_dev/st_ino for copied up object would have been the same as that of the real underlying lower file, running diff on underlying lower file and overlay copied up file would result in diff reporting that the two files are equal when in fact, they may have different content. Therefore, unlike the same fs case, st_dev is not persistent because it uses the unique anonymous bdev allocated for the lower layer. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/inode.c | 49 ++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index b599059d6f78..00b6b294272a 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -74,6 +74,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat, struct path realpath; const struct cred *old_cred; bool is_dir = S_ISDIR(dentry->d_inode->i_mode); + bool samefs = ovl_same_sb(dentry->d_sb); int err; type = ovl_path_real(dentry, &realpath); @@ -83,16 +84,13 @@ int ovl_getattr(const struct path *path, struct kstat *stat, goto out; /* - * When all layers are on the same fs, all real inode number are - * unique, so we use the overlay st_dev, which is friendly to du -x. - * - * We also use st_ino of the copy up origin, if we know it. - * This guaranties constant st_dev/st_ino across copy up. + * For non-dir or same fs, we use st_ino of the copy up origin, if we + * know it. This guaranties constant st_dev/st_ino across copy up. * * If filesystem supports NFS export ops, this also guaranties * persistent st_ino across mount cycle. */ - if (ovl_same_sb(dentry->d_sb)) { + if (!is_dir || samefs) { if (OVL_TYPE_ORIGIN(type)) { struct kstat lowerstat; u32 lowermask = STATX_INO | (!is_dir ? STATX_NLINK : 0); @@ -103,7 +101,6 @@ int ovl_getattr(const struct path *path, struct kstat *stat, if (err) goto out; - WARN_ON_ONCE(stat->dev != lowerstat.dev); /* * Lower hardlinks may be broken on copy up to different * upper files, so we cannot use the lower origin st_ino @@ -115,27 +112,39 @@ int ovl_getattr(const struct path *path, struct kstat *stat, if (is_dir || lowerstat.nlink == 1 || ovl_test_flag(OVL_INDEX, d_inode(dentry))) stat->ino = lowerstat.ino; + + if (samefs) + WARN_ON_ONCE(stat->dev != lowerstat.dev); + else + stat->dev = ovl_get_pseudo_dev(dentry); } - stat->dev = dentry->d_sb->s_dev; - } else if (is_dir) { + if (samefs) { + /* + * When all layers are on the same fs, all real inode + * number are unique, so we use the overlay st_dev, + * which is friendly to du -x. + */ + stat->dev = dentry->d_sb->s_dev; + } else if (!OVL_TYPE_UPPER(type)) { + /* + * For non-samefs setup, to make sure that st_dev/st_ino + * pair is unique across the system, we use a unique + * anonymous st_dev for lower layer inode. + */ + stat->dev = ovl_get_pseudo_dev(dentry); + } + } else { /* - * If not all layers are on the same fs the pair {real st_ino; - * overlay st_dev} is not unique, so use the non persistent - * overlay st_ino. - * * Always use the overlay st_dev for directories, so 'find * -xdev' will scan the entire overlay mount and won't cross the * overlay mount boundaries. + * + * If not all layers are on the same fs the pair {real st_ino; + * overlay st_dev} is not unique, so use the non persistent + * overlay st_ino for directories. */ stat->dev = dentry->d_sb->s_dev; stat->ino = dentry->d_inode->i_ino; - } else if (!OVL_TYPE_UPPER(type)) { - /* - * For non-samefs setup, to make sure that st_dev/st_ino pair - * is unique across the system, we use a unique anonymous - * st_dev for lower layer inode. - */ - stat->dev = ovl_get_pseudo_dev(dentry); } /* -- GitLab From f30536f0f955d9d3eb5a7e32033af4e3649de173 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 1 Nov 2017 17:33:13 +0200 Subject: [PATCH 1727/2898] ovl: update cache version of impure parent on rename ovl_rename() updates dir cache version for impure old parent if an entry with copy up origin is moved into old parent, but it did not update cache version if the entry moved out of old parent has a copy up origin. [SzM] Same for new dir: we updated the version if an entry with origin was moved in, but not if an entry with origin was moved out. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/dir.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index ef533198be45..e13921824c70 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -1075,9 +1075,10 @@ static int ovl_rename(struct inode *olddir, struct dentry *old, drop_nlink(d_inode(new)); } - ovl_dentry_version_inc(old->d_parent, - !overwrite && ovl_type_origin(new)); - ovl_dentry_version_inc(new->d_parent, ovl_type_origin(old)); + ovl_dentry_version_inc(old->d_parent, ovl_type_origin(old) || + (!overwrite && ovl_type_origin(new))); + ovl_dentry_version_inc(new->d_parent, ovl_type_origin(old) || + (d_inode(new) && ovl_type_origin(new))); out_dput: dput(newdentry); -- GitLab From f121aadede37bcbb77ea552d195a09c734486fe7 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1728/2898] vfs: add path_put_init() This one initializes the struct path to all zeroes so that multiple path_put_init() on the path is safe. Signed-off-by: Miklos Szeredi --- include/linux/path.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/path.h b/include/linux/path.h index 81e65a5be7ce..475225a03d0d 100644 --- a/include/linux/path.h +++ b/include/linux/path.h @@ -18,4 +18,10 @@ static inline int path_equal(const struct path *path1, const struct path *path2) return path1->mnt == path2->mnt && path1->dentry == path2->dentry; } +static inline void path_put_init(struct path *path) +{ + path_put(path); + *path = (struct path) { }; +} + #endif /* _LINUX_PATH_H */ -- GitLab From 8aafcb593d25e81c13be49310550e80d8788b995 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1729/2898] ovl: use path_put_init() in error paths for ovl_fill_super() This allows simplifying the error cleanup later. Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 2c9f48096ff0..bc8729491362 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -586,7 +586,7 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path) return 0; out_put: - path_put(path); + path_put_init(path); out: return err; } @@ -604,7 +604,7 @@ static int ovl_mount_dir(const char *name, struct path *path) if (ovl_dentry_remote(path->dentry)) { pr_err("overlayfs: filesystem on '%s' not supported as upperdir\n", tmp); - path_put(path); + path_put_init(path); err = -EINVAL; } kfree(tmp); @@ -656,7 +656,7 @@ static int ovl_lower_dir(const char *name, struct path *path, return 0; out_put: - path_put(path); + path_put_init(path); out: return err; } -- GitLab From 6ee8acf0f72b89b3c6d9df9cbe9b815711af3c7b Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1730/2898] ovl: split out ovl_get_upperpath() from ovl_fill_super() It's okay to get rid of the intermediate error label due to ufs being zeroed on allocation. Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 59 ++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index bc8729491362..c1abd66527ce 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -827,6 +827,39 @@ static const struct xattr_handler *ovl_xattr_handlers[] = { NULL }; +static int ovl_get_upperpath(struct ovl_fs *ufs, struct path *upperpath) +{ + int err; + + err = ovl_mount_dir(ufs->config.upperdir, upperpath); + if (err) + goto out; + + /* Upper fs should not be r/o */ + if (sb_rdonly(upperpath->mnt->mnt_sb)) { + pr_err("overlayfs: upper fs is r/o, try multi-lower layers mount\n"); + err = -EINVAL; + goto out; + } + + err = ovl_check_namelen(upperpath, ufs, ufs->config.upperdir); + if (err) + goto out; + + err = -EBUSY; + if (ovl_inuse_trylock(upperpath->dentry)) { + ufs->upperdir_locked = true; + } else if (ufs->config.index) { + pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n"); + goto out; + } else { + pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); + } + err = 0; +out: + return err; +} + static int ovl_fill_super(struct super_block *sb, void *data, int silent) { struct path upperpath = { }; @@ -870,30 +903,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) goto out_free_config; } - err = ovl_mount_dir(ufs->config.upperdir, &upperpath); + err = ovl_get_upperpath(ufs, &upperpath); if (err) - goto out_free_config; - - /* Upper fs should not be r/o */ - if (sb_rdonly(upperpath.mnt->mnt_sb)) { - pr_err("overlayfs: upper fs is r/o, try multi-lower layers mount\n"); - err = -EINVAL; - goto out_put_upperpath; - } - - err = ovl_check_namelen(&upperpath, ufs, ufs->config.upperdir); - if (err) - goto out_put_upperpath; - - err = -EBUSY; - if (ovl_inuse_trylock(upperpath.dentry)) { - ufs->upperdir_locked = true; - } else if (ufs->config.index) { - pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n"); - goto out_put_upperpath; - } else { - pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); - } + goto out_unlock_upperdentry; err = ovl_mount_dir(ufs->config.workdir, &workpath); if (err) @@ -1196,7 +1208,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) out_unlock_upperdentry: if (ufs->upperdir_locked) ovl_inuse_unlock(upperpath.dentry); -out_put_upperpath: path_put(&upperpath); out_free_config: kfree(ufs->config.lowerdir); -- GitLab From 87ad447a9d4f807b5542e6d92c6d740103b82bda Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1731/2898] ovl: split out ovl_get_workpath() from ovl_fill_super() It's okay to get rid of the intermediate error label due to ufs being zeroed on allocation. Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 61 +++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index c1abd66527ce..6d02ca31bb90 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -860,6 +860,41 @@ static int ovl_get_upperpath(struct ovl_fs *ufs, struct path *upperpath) return err; } +static int ovl_get_workpath(struct ovl_fs *ufs, struct path *upperpath, + struct path *workpath) +{ + int err; + + err = ovl_mount_dir(ufs->config.workdir, workpath); + if (err) + goto out; + + err = -EINVAL; + if (upperpath->mnt != workpath->mnt) { + pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); + goto out; + } + if (!ovl_workdir_ok(workpath->dentry, upperpath->dentry)) { + pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); + goto out; + } + + err = -EBUSY; + if (ovl_inuse_trylock(workpath->dentry)) { + ufs->workdir_locked = true; + } else if (ufs->config.index) { + pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); + goto out; + } else { + pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); + } + + ufs->workbasedir = workpath->dentry; + err = 0; +out: + return err; +} + static int ovl_fill_super(struct super_block *sb, void *data, int silent) { struct path upperpath = { }; @@ -907,31 +942,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) if (err) goto out_unlock_upperdentry; - err = ovl_mount_dir(ufs->config.workdir, &workpath); + err = ovl_get_workpath(ufs, &upperpath, &workpath); if (err) - goto out_unlock_upperdentry; - - err = -EINVAL; - if (upperpath.mnt != workpath.mnt) { - pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); - goto out_put_workpath; - } - if (!ovl_workdir_ok(workpath.dentry, upperpath.dentry)) { - pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); - goto out_put_workpath; - } - - err = -EBUSY; - if (ovl_inuse_trylock(workpath.dentry)) { - ufs->workdir_locked = true; - } else if (ufs->config.index) { - pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n"); - goto out_put_workpath; - } else { - pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); - } + goto out_unlock_workdentry; - ufs->workbasedir = workpath.dentry; sb->s_stack_depth = upperpath.mnt->mnt_sb->s_stack_depth; } err = -ENOMEM; @@ -1203,7 +1217,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) out_unlock_workdentry: if (ufs->workdir_locked) ovl_inuse_unlock(workpath.dentry); -out_put_workpath: path_put(&workpath); out_unlock_upperdentry: if (ufs->upperdir_locked) -- GitLab From 53dbb0b4787ef57834f74bdccfba4c63eb12da69 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1732/2898] ovl: split out ovl_get_lowerstack() from ovl_fill_super() Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 122 +++++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 50 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 6d02ca31bb90..6c8703112b8f 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -895,6 +895,75 @@ static int ovl_get_workpath(struct ovl_fs *ufs, struct path *upperpath, return err; } +static int ovl_get_lowerstack(struct super_block *sb, struct ovl_fs *ufs, + struct path **stackp, unsigned int *stacklenp) +{ + int err; + char *lowertmp, *lower; + struct path *stack; + unsigned int stacklen, numlower, i; + bool remote = false; + + err = -ENOMEM; + lowertmp = kstrdup(ufs->config.lowerdir, GFP_KERNEL); + if (!lowertmp) + goto out; + + err = -EINVAL; + stacklen = ovl_split_lowerdirs(lowertmp); + if (stacklen > OVL_MAX_STACK) { + pr_err("overlayfs: too many lower directories, limit is %d\n", + OVL_MAX_STACK); + goto out; + } else if (!ufs->config.upperdir && stacklen == 1) { + pr_err("overlayfs: at least 2 lowerdir are needed while upperdir nonexistent\n"); + goto out; + } + + err = -ENOMEM; + stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL); + if (!stack) + goto out; + + err = -EINVAL; + lower = lowertmp; + for (numlower = 0; numlower < stacklen; numlower++) { + err = ovl_lower_dir(lower, &stack[numlower], ufs, + &sb->s_stack_depth, &remote); + if (err) + goto out_free_stack; + + lower = strchr(lower, '\0') + 1; + } + + err = -EINVAL; + sb->s_stack_depth++; + if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { + pr_err("overlayfs: maximum fs stacking depth exceeded\n"); + goto out_free_stack; + } + + *stackp = stack; + *stacklenp = numlower; + + if (remote) + sb->s_d_op = &ovl_reval_dentry_operations; + else + sb->s_d_op = &ovl_dentry_operations; + + err = 0; + +out: + kfree(lowertmp); + return err; + +out_free_stack: + for (i = 0; i < numlower; i++) + path_put(&stack[i]); + kfree(stack); + goto out; +} + static int ovl_fill_super(struct super_block *sb, void *data, int silent) { struct path upperpath = { }; @@ -903,12 +972,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) struct ovl_entry *oe; struct ovl_fs *ufs; struct path *stack = NULL; - char *lowertmp; - char *lower; - unsigned int numlower; - unsigned int stacklen = 0; + unsigned int numlower = 0; unsigned int i; - bool remote = false; struct cred *cred; int err; @@ -948,45 +1013,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) sb->s_stack_depth = upperpath.mnt->mnt_sb->s_stack_depth; } - err = -ENOMEM; - lowertmp = kstrdup(ufs->config.lowerdir, GFP_KERNEL); - if (!lowertmp) + err = ovl_get_lowerstack(sb, ufs, &stack, &numlower); + if (err) goto out_unlock_workdentry; - err = -EINVAL; - stacklen = ovl_split_lowerdirs(lowertmp); - if (stacklen > OVL_MAX_STACK) { - pr_err("overlayfs: too many lower directories, limit is %d\n", - OVL_MAX_STACK); - goto out_free_lowertmp; - } else if (!ufs->config.upperdir && stacklen == 1) { - pr_err("overlayfs: at least 2 lowerdir are needed while upperdir nonexistent\n"); - goto out_free_lowertmp; - } - - err = -ENOMEM; - stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL); - if (!stack) - goto out_free_lowertmp; - - err = -EINVAL; - lower = lowertmp; - for (numlower = 0; numlower < stacklen; numlower++) { - err = ovl_lower_dir(lower, &stack[numlower], ufs, - &sb->s_stack_depth, &remote); - if (err) - goto out_put_lowerpath; - - lower = strchr(lower, '\0') + 1; - } - - err = -EINVAL; - sb->s_stack_depth++; - if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { - pr_err("overlayfs: maximum fs stacking depth exceeded\n"); - goto out_put_lowerpath; - } - if (ufs->config.upperdir) { ufs->upper_mnt = clone_private_mount(&upperpath); err = PTR_ERR(ufs->upper_mnt); @@ -1145,11 +1175,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) if (!ufs->indexdir) ufs->config.index = false; - if (remote) - sb->s_d_op = &ovl_reval_dentry_operations; - else - sb->s_d_op = &ovl_dentry_operations; - err = -ENOMEM; ufs->creator_cred = cred = prepare_creds(); if (!cred) @@ -1173,7 +1198,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) mntput(stack[i].mnt); kfree(stack); mntput(workpath.mnt); - kfree(lowertmp); if (upperpath.dentry) { oe->has_upper = true; @@ -1212,8 +1236,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) for (i = 0; i < numlower; i++) path_put(&stack[i]); kfree(stack); -out_free_lowertmp: - kfree(lowertmp); out_unlock_workdentry: if (ufs->workdir_locked) ovl_inuse_unlock(workpath.dentry); -- GitLab From 21a3b317a60197b19c8f67e8016b633942e36bbf Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1733/2898] ovl: split out ovl_get_upper() from ovl_fill_super() And don't clobber ufs->upper_mnt on error. Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 6c8703112b8f..21f93cd5782f 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -895,6 +895,23 @@ static int ovl_get_workpath(struct ovl_fs *ufs, struct path *upperpath, return err; } +static int ovl_get_upper(struct ovl_fs *ufs, struct path *upperpath) +{ + struct vfsmount *upper_mnt; + + upper_mnt = clone_private_mount(upperpath); + if (IS_ERR(upper_mnt)) { + pr_err("overlayfs: failed to clone upperpath\n"); + return PTR_ERR(upper_mnt); + } + + /* Don't inherit atime flags */ + upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME); + ufs->upper_mnt = upper_mnt; + + return 0; +} + static int ovl_get_lowerstack(struct super_block *sb, struct ovl_fs *ufs, struct path **stackp, unsigned int *stacklenp) { @@ -1018,15 +1035,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) goto out_unlock_workdentry; if (ufs->config.upperdir) { - ufs->upper_mnt = clone_private_mount(&upperpath); - err = PTR_ERR(ufs->upper_mnt); - if (IS_ERR(ufs->upper_mnt)) { - pr_err("overlayfs: failed to clone upperpath\n"); + err = ovl_get_upper(ufs, &upperpath); + if (err) goto out_put_lowerpath; - } - - /* Don't inherit atime flags */ - ufs->upper_mnt->mnt_flags &= ~(MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME); sb->s_time_gran = ufs->upper_mnt->mnt_sb->s_time_gran; -- GitLab From 8ed61dc37ee0a33c7581d38d16977a5d1897de9f Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1734/2898] ovl: split out ovl_get_workdir() from ovl_fill_super() Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 111 +++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 51 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 21f93cd5782f..aadd07a1e9c1 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -912,6 +912,63 @@ static int ovl_get_upper(struct ovl_fs *ufs, struct path *upperpath) return 0; } +static int ovl_get_workdir(struct super_block *sb, struct ovl_fs *ufs, + struct path *workpath) +{ + struct dentry *temp; + int err; + + ufs->workdir = ovl_workdir_create(sb, ufs, workpath->dentry, + OVL_WORKDIR_NAME, false); + if (!ufs->workdir) + return 0; + + /* + * Upper should support d_type, else whiteouts are visible. Given + * workdir and upper are on same fs, we can do iterate_dir() on + * workdir. This check requires successful creation of workdir in + * previous step. + */ + err = ovl_check_d_type_supported(workpath); + if (err < 0) + return err; + + /* + * We allowed this configuration and don't want to break users over + * kernel upgrade. So warn instead of erroring out. + */ + if (!err) + pr_warn("overlayfs: upper fs needs to support d_type.\n"); + + /* Check if upper/work fs supports O_TMPFILE */ + temp = ovl_do_tmpfile(ufs->workdir, S_IFREG | 0); + ufs->tmpfile = !IS_ERR(temp); + if (ufs->tmpfile) + dput(temp); + else + pr_warn("overlayfs: upper fs does not support tmpfile.\n"); + + /* + * Check if upper/work fs supports trusted.overlay.* xattr + */ + err = ovl_do_setxattr(ufs->workdir, OVL_XATTR_OPAQUE, "0", 1, 0); + if (err) { + ufs->noxattr = true; + pr_warn("overlayfs: upper fs does not support xattr.\n"); + } else { + vfs_removexattr(ufs->workdir, OVL_XATTR_OPAQUE); + } + + /* Check if upper/work fs supports file handles */ + if (ufs->config.index && + !ovl_can_decode_fh(ufs->workdir->d_sb)) { + ufs->config.index = false; + pr_warn("overlayfs: upper fs does not support file handles, falling back to index=off.\n"); + } + + return 0; +} + static int ovl_get_lowerstack(struct super_block *sb, struct ovl_fs *ufs, struct path **stackp, unsigned int *stacklenp) { @@ -1041,57 +1098,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) sb->s_time_gran = ufs->upper_mnt->mnt_sb->s_time_gran; - ufs->workdir = ovl_workdir_create(sb, ufs, workpath.dentry, - OVL_WORKDIR_NAME, false); - /* - * Upper should support d_type, else whiteouts are visible. - * Given workdir and upper are on same fs, we can do - * iterate_dir() on workdir. This check requires successful - * creation of workdir in previous step. - */ - if (ufs->workdir) { - struct dentry *temp; - - err = ovl_check_d_type_supported(&workpath); - if (err < 0) - goto out_put_workdir; - - /* - * We allowed this configuration and don't want to - * break users over kernel upgrade. So warn instead - * of erroring out. - */ - if (!err) - pr_warn("overlayfs: upper fs needs to support d_type.\n"); - - /* Check if upper/work fs supports O_TMPFILE */ - temp = ovl_do_tmpfile(ufs->workdir, S_IFREG | 0); - ufs->tmpfile = !IS_ERR(temp); - if (ufs->tmpfile) - dput(temp); - else - pr_warn("overlayfs: upper fs does not support tmpfile.\n"); - - /* - * Check if upper/work fs supports trusted.overlay.* - * xattr - */ - err = ovl_do_setxattr(ufs->workdir, OVL_XATTR_OPAQUE, - "0", 1, 0); - if (err) { - ufs->noxattr = true; - pr_warn("overlayfs: upper fs does not support xattr.\n"); - } else { - vfs_removexattr(ufs->workdir, OVL_XATTR_OPAQUE); - } - - /* Check if upper/work fs supports file handles */ - if (ufs->config.index && - !ovl_can_decode_fh(ufs->workdir->d_sb)) { - ufs->config.index = false; - pr_warn("overlayfs: upper fs does not support file handles, falling back to index=off.\n"); - } - } + err = ovl_get_workdir(sb, ufs, &workpath); + if (err) + goto out_put_workdir; } err = -ENOMEM; -- GitLab From c0d91fb9101100b8c13779b95f70b2ef75b54526 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1735/2898] ovl: split out ovl_get_lower_layers() from ovl_fill_super() Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 90 +++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index aadd07a1e9c1..537412ad12a0 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1038,6 +1038,55 @@ static int ovl_get_lowerstack(struct super_block *sb, struct ovl_fs *ufs, goto out; } +static int ovl_get_lower_layers(struct ovl_fs *ufs, struct path *stack, + unsigned int numlower) +{ + int err; + unsigned int i; + + err = -ENOMEM; + ufs->lower_layers = kcalloc(numlower, sizeof(struct ovl_layer), + GFP_KERNEL); + if (ufs->lower_layers == NULL) + goto out; + for (i = 0; i < numlower; i++) { + struct vfsmount *mnt; + dev_t dev; + + err = get_anon_bdev(&dev); + if (err) { + pr_err("overlayfs: failed to get anonymous bdev for lowerpath\n"); + goto out; + } + + mnt = clone_private_mount(&stack[i]); + err = PTR_ERR(mnt); + if (IS_ERR(mnt)) { + pr_err("overlayfs: failed to clone lowerpath\n"); + free_anon_bdev(dev); + goto out; + } + /* + * Make lower layers R/O. That way fchmod/fchown on lower file + * will fail instead of modifying lower fs. + */ + mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME; + + ufs->lower_layers[ufs->numlower].mnt = mnt; + ufs->lower_layers[ufs->numlower].pseudo_dev = dev; + ufs->numlower++; + + /* Check if all lower layers are on same sb */ + if (i == 0) + ufs->same_sb = mnt->mnt_sb; + else if (ufs->same_sb != mnt->mnt_sb) + ufs->same_sb = NULL; + } + err = 0; +out: + return err; +} + static int ovl_fill_super(struct super_block *sb, void *data, int silent) { struct path upperpath = { }; @@ -1103,44 +1152,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) goto out_put_workdir; } - err = -ENOMEM; - ufs->lower_layers = kcalloc(numlower, sizeof(struct ovl_layer), - GFP_KERNEL); - if (ufs->lower_layers == NULL) - goto out_put_workdir; - for (i = 0; i < numlower; i++) { - struct vfsmount *mnt; - dev_t dev; - - err = get_anon_bdev(&dev); - if (err) { - pr_err("overlayfs: failed to get anonymous bdev for lowerpath\n"); - goto out_put_lower_layers; - } - - mnt = clone_private_mount(&stack[i]); - err = PTR_ERR(mnt); - if (IS_ERR(mnt)) { - pr_err("overlayfs: failed to clone lowerpath\n"); - free_anon_bdev(dev); - goto out_put_lower_layers; - } - /* - * Make lower layers R/O. That way fchmod/fchown on lower file - * will fail instead of modifying lower fs. - */ - mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME; - - ufs->lower_layers[ufs->numlower].mnt = mnt; - ufs->lower_layers[ufs->numlower].pseudo_dev = dev; - ufs->numlower++; - - /* Check if all lower layers are on same sb */ - if (i == 0) - ufs->same_sb = mnt->mnt_sb; - else if (ufs->same_sb != mnt->mnt_sb) - ufs->same_sb = NULL; - } + err = ovl_get_lower_layers(ufs, stack, numlower); + if (err) + goto out_put_lower_layers; /* If the upper fs is nonexistent, we mark overlayfs r/o too */ if (!ufs->upper_mnt) -- GitLab From f7e3a7d947f83684f6622b592136da54bed922e6 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:28 +0100 Subject: [PATCH 1736/2898] ovl: split out ovl_get_indexdir() from ovl_fill_super() It's okay to get rid of the intermediate error label due to ufs being zeroed on allocation. Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 69 +++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 537412ad12a0..6bb874da174d 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -969,6 +969,45 @@ static int ovl_get_workdir(struct super_block *sb, struct ovl_fs *ufs, return 0; } +static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ufs, + struct ovl_entry *oe, + struct path *upperpath, struct path *workpath) +{ + int err; + + /* Verify lower root is upper root origin */ + err = ovl_verify_origin(upperpath->dentry, + oe->lowerstack[0].layer->mnt, + oe->lowerstack[0].dentry, + false, true); + if (err) { + pr_err("overlayfs: failed to verify upper root origin\n"); + goto out; + } + + ufs->indexdir = ovl_workdir_create(sb, ufs, workpath->dentry, + OVL_INDEXDIR_NAME, true); + if (ufs->indexdir) { + /* Verify upper root is index dir origin */ + err = ovl_verify_origin(ufs->indexdir, ufs->upper_mnt, + upperpath->dentry, true, true); + if (err) + pr_err("overlayfs: failed to verify index dir origin\n"); + + /* Cleanup bad/stale/orphan index entries */ + if (!err) + err = ovl_indexdir_cleanup(ufs->indexdir, + ufs->upper_mnt, + oe->lowerstack, + oe->numlower); + } + if (err || !ufs->indexdir) + pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n"); + +out: + return err; +} + static int ovl_get_lowerstack(struct super_block *sb, struct ovl_fs *ufs, struct path **stackp, unsigned int *stacklenp) { @@ -1173,34 +1212,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) } if (!(ovl_force_readonly(ufs)) && ufs->config.index) { - /* Verify lower root is upper root origin */ - err = ovl_verify_origin(upperpath.dentry, - oe->lowerstack[0].layer->mnt, - oe->lowerstack[0].dentry, - false, true); - if (err) { - pr_err("overlayfs: failed to verify upper root origin\n"); - goto out_free_oe; - } - - ufs->indexdir = ovl_workdir_create(sb, ufs, workpath.dentry, - OVL_INDEXDIR_NAME, true); - if (ufs->indexdir) { - /* Verify upper root is index dir origin */ - err = ovl_verify_origin(ufs->indexdir, ufs->upper_mnt, - upperpath.dentry, true, true); - if (err) - pr_err("overlayfs: failed to verify index dir origin\n"); - - /* Cleanup bad/stale/orphan index entries */ - if (!err) - err = ovl_indexdir_cleanup(ufs->indexdir, - ufs->upper_mnt, - oe->lowerstack, - numlower); - } - if (err || !ufs->indexdir) - pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n"); + err = ovl_get_indexdir(sb, ufs, oe, &upperpath, &workpath); if (err) goto out_put_indexdir; } @@ -1254,7 +1266,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) put_cred(ufs->creator_cred); out_put_indexdir: dput(ufs->indexdir); -out_free_oe: kfree(oe); out_put_lower_layers: for (i = 0; i < ufs->numlower; i++) { -- GitLab From 95e6d4177cb7a2d7a760180e13f32adaf4188833 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 9 Nov 2017 10:23:29 +0100 Subject: [PATCH 1737/2898] ovl: grab reference to workbasedir early and related cleanups. Signed-off-by: Miklos Szeredi --- fs/overlayfs/super.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 6bb874da174d..255c0523148f 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -889,7 +889,7 @@ static int ovl_get_workpath(struct ovl_fs *ufs, struct path *upperpath, pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n"); } - ufs->workbasedir = workpath->dentry; + ufs->workbasedir = dget(workpath->dentry); err = 0; out: return err; @@ -918,7 +918,7 @@ static int ovl_get_workdir(struct super_block *sb, struct ovl_fs *ufs, struct dentry *temp; int err; - ufs->workdir = ovl_workdir_create(sb, ufs, workpath->dentry, + ufs->workdir = ovl_workdir_create(sb, ufs, ufs->workbasedir, OVL_WORKDIR_NAME, false); if (!ufs->workdir) return 0; @@ -971,7 +971,7 @@ static int ovl_get_workdir(struct super_block *sb, struct ovl_fs *ufs, static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ufs, struct ovl_entry *oe, - struct path *upperpath, struct path *workpath) + struct path *upperpath) { int err; @@ -985,7 +985,7 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ufs, goto out; } - ufs->indexdir = ovl_workdir_create(sb, ufs, workpath->dentry, + ufs->indexdir = ovl_workdir_create(sb, ufs, ufs->workbasedir, OVL_INDEXDIR_NAME, true); if (ufs->indexdir) { /* Verify upper root is index dir origin */ @@ -1212,7 +1212,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) } if (!(ovl_force_readonly(ufs)) && ufs->config.index) { - err = ovl_get_indexdir(sb, ufs, oe, &upperpath, &workpath); + err = ovl_get_indexdir(sb, ufs, oe, &upperpath); if (err) goto out_put_indexdir; } @@ -1243,7 +1243,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) for (i = 0; i < numlower; i++) mntput(stack[i].mnt); kfree(stack); - mntput(workpath.mnt); + path_put(&workpath); if (upperpath.dentry) { oe->has_upper = true; @@ -1283,7 +1283,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) kfree(stack); out_unlock_workdentry: if (ufs->workdir_locked) - ovl_inuse_unlock(workpath.dentry); + ovl_inuse_unlock(ufs->workbasedir); + dput(ufs->workbasedir); path_put(&workpath); out_unlock_upperdentry: if (ufs->upperdir_locked) -- GitLab From 2e307cba0c56eba45649eb0f0f43b999e64aae94 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 9 Nov 2017 18:09:28 +0100 Subject: [PATCH 1738/2898] video: fbdev: au1200fb: Fix a potential double free If 'fb_alloc_cmap()' fails, 'fbi->pseudo_palette' is freed and an error code is returned by 'au1200fb_init_fbinfo()'. The only caller, 'au1200fb_drv_probe()' goes to an error handling path where resources allocated in 'fb_alloc_cmap()' are freed. This leads to a double free of 'fbi->pseudo_palette'. Fix it by letting the caller free all resources in case of failure in 'au1200fb_init_fbinfo()'. Signed-off-by: Christophe JAILLET Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/au1200fb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index 5f04b4096c42..a5facc2ad90b 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1553,7 +1553,6 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { print_err("Fail to allocate colormap (%d entries)", AU1200_LCD_NBR_PALETTE_ENTRIES); - kfree(fbi->pseudo_palette); return -EFAULT; } -- GitLab From 8cae353e6b01ac3f18097f631cdbceb5ff28c7f3 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 9 Nov 2017 18:09:28 +0100 Subject: [PATCH 1739/2898] video: fbdev: au1200fb: Return an error code if a memory allocation fails 'ret' is known to be 0 at this point. In case of memory allocation error in 'framebuffer_alloc()', return -ENOMEM instead. Signed-off-by: Christophe JAILLET Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/au1200fb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index a5facc2ad90b..7fa41026984d 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1680,8 +1680,10 @@ static int au1200fb_drv_probe(struct platform_device *dev) fbi = framebuffer_alloc(sizeof(struct au1200fb_device), &dev->dev); - if (!fbi) + if (!fbi) { + ret = -ENOMEM; goto failed; + } _au1200fb_infos[plane] = fbi; fbdev = fbi->par; -- GitLab From 451f130602619a17c8883dd0b71b11624faffd51 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 9 Nov 2017 18:09:28 +0100 Subject: [PATCH 1740/2898] video: fbdev: au1200fb: Release some resources if a memory allocation fails We should go through the error handling code instead of returning -ENOMEM directly. Signed-off-by: Christophe JAILLET Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/au1200fb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index 7fa41026984d..cf54168d44dc 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1702,7 +1702,8 @@ static int au1200fb_drv_probe(struct platform_device *dev) if (!fbdev->fb_mem) { print_err("fail to allocate frambuffer (size: %dK))", fbdev->fb_len / 1024); - return -ENOMEM; + ret = -ENOMEM; + goto failed; } /* -- GitLab From 703a4af427a9bf3028f1a9369fcec7bfcf56f0ed Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 9 Nov 2017 18:09:29 +0100 Subject: [PATCH 1741/2898] video: fbdev: au1200fb: Fix incorrect IRQ freeing 'au1200fb_drv_probe()' can not fail after a successful call to 'request_irq()'. So there is no point to call 'free_irq()' in the error handling path. Moreover, the hard coded AU1200_LCD_INT looks boggus since commit 1630d85a8312 ("au1200fb: fix hardcoded IRQ"). So, remove it. Signed-off-by: Christophe JAILLET Cc: Tejun Heo [b.zolnierkie: patch summary and description fixups] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/au1200fb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index cf54168d44dc..0d8ed0ef9183 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1766,8 +1766,6 @@ static int au1200fb_drv_probe(struct platform_device *dev) fb_dealloc_cmap(&fbi->cmap); kfree(fbi->pseudo_palette); } - if (plane == 0) - free_irq(AU1200_LCD_INT, (void*)dev); return ret; } -- GitLab From 6bbbb6805a72bd8c3e9ee626add6b6e8527bb971 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 9 Nov 2017 18:09:29 +0100 Subject: [PATCH 1742/2898] video: fbdev: au1200fb: Fix error handling path Rewrite the exit path based on 'au1200fb_drv_remove()'. We can safely iterate for all already handled planes. Even if not completely initialized, the functions that are called will silently accept the 'fb_info' structure that is passed. As soon as we find a NULL in the '_au1200fb_infos' array, we know that we have released all what we needed to release. So we can 'break'. Signed-off-by: Christophe JAILLET Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/au1200fb.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index 0d8ed0ef9183..e531543bc707 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1760,11 +1760,19 @@ static int au1200fb_drv_probe(struct platform_device *dev) return 0; failed: - /* NOTE: This only does the current plane/window that failed; others are still active */ - if (fbi) { + for (plane = 0; plane < device_count; ++plane) { + fbi = _au1200fb_infos[plane]; + if (!fbi) + break; + + /* Clean up all probe data */ + unregister_framebuffer(fbi); if (fbi->cmap.len != 0) fb_dealloc_cmap(&fbi->cmap); kfree(fbi->pseudo_palette); + + framebuffer_release(fbi); + _au1200fb_infos[plane] = NULL; } return ret; } -- GitLab From 58a81afcffeb457e56e8498c8bf5b73c1623c0b5 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 9 Nov 2017 18:09:29 +0100 Subject: [PATCH 1743/2898] video: fbdev: au1200fb: Remove some dead code There is no need to shut gcc up. It should not complain. Axe 'fbdev', it is never used in this function. Signed-off-by: Christophe JAILLET Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/au1200fb.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index e531543bc707..970ce761ff89 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1667,10 +1667,6 @@ static int au1200fb_drv_probe(struct platform_device *dev) printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); - /* shut gcc up */ - ret = 0; - fbdev = NULL; - for (plane = 0; plane < device_count; ++plane) { bpp = winbpp(win->w[plane].mode_winctrl1); if (win->w[plane].xres == 0) @@ -1780,7 +1776,6 @@ static int au1200fb_drv_probe(struct platform_device *dev) static int au1200fb_drv_remove(struct platform_device *dev) { struct au1200fb_platdata *pd = platform_get_drvdata(dev); - struct au1200fb_device *fbdev; struct fb_info *fbi; int plane; @@ -1789,7 +1784,6 @@ static int au1200fb_drv_remove(struct platform_device *dev) for (plane = 0; plane < device_count; ++plane) { fbi = _au1200fb_infos[plane]; - fbdev = fbi->par; /* Clean up all probe data */ unregister_framebuffer(fbi); -- GitLab From 0620865611c9e398f8feaccbe49be946bc6e04d1 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 9 Nov 2017 18:09:29 +0100 Subject: [PATCH 1744/2898] video: fbdev: au1200fb: Propagate an error code We should propagate the error code returned by 'fb_alloc_cmap()' instead of returning -EFAULT. Signed-off-by: Christophe JAILLET Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/au1200fb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index 970ce761ff89..687ea2a8f810 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1518,7 +1518,7 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id) static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) { struct fb_info *fbi = fbdev->fb_info; - int bpp; + int bpp, ret; fbi->fbops = &au1200fb_fb_ops; @@ -1550,10 +1550,11 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) return -ENOMEM; } - if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { + ret = fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0); + if (ret < 0) { print_err("Fail to allocate colormap (%d entries)", AU1200_LCD_NBR_PALETTE_ENTRIES); - return -EFAULT; + return ret; } strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); -- GitLab From ab798b908737e999e5d9bcebe972e9d5002583cc Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 9 Nov 2017 18:09:30 +0100 Subject: [PATCH 1745/2898] video: fbdev: au1200fb: Style clean up Style clean-up. Signed-off-by: Christophe JAILLET Cc: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/au1200fb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index 687ea2a8f810..87d5a62bf6ca 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1546,14 +1546,13 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) } fbi->pseudo_palette = kcalloc(16, sizeof(u32), GFP_KERNEL); - if (!fbi->pseudo_palette) { + if (!fbi->pseudo_palette) return -ENOMEM; - } ret = fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0); if (ret < 0) { print_err("Fail to allocate colormap (%d entries)", - AU1200_LCD_NBR_PALETTE_ENTRIES); + AU1200_LCD_NBR_PALETTE_ENTRIES); return ret; } @@ -1717,7 +1716,8 @@ static int au1200fb_drv_probe(struct platform_device *dev) print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); /* Init FB data */ - if ((ret = au1200fb_init_fbinfo(fbdev)) < 0) + ret = au1200fb_init_fbinfo(fbdev); + if (ret < 0) goto failed; /* Register new framebuffer */ -- GitLab From 2d81482821e9a825030cf4ba60de990f1a2bdfd0 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Thu, 9 Nov 2017 18:09:30 +0100 Subject: [PATCH 1746/2898] video: fbdev: mxsfb: fix pixelclock polarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PIXDATA flags of the display_flags enum are controller centric, e.g. NEGEDGE means the controller shall drive the data signals on pixelclocks negative edge. However, the drivers flag is display centric: Sample the data on negative (falling) edge. Therefore, change the if statement to check for the POSEDGE flag (which is typically not set): Drive on positive edge => sample on negative edge Signed-off-by: Stefan Agner Acked-by: Shawn Guo Cc: Jean-Christophe Plagniol-Villard Cc: Sascha Hauer Cc: Liu Ying Cc: Lothar Waßmann Cc: Fabio Estevam Cc: Max Krummenacher Cc: Mauro Salvini Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/mxsfb.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c index 7846f0e8bbbb..79b1dc7f042b 100644 --- a/drivers/video/fbdev/mxsfb.c +++ b/drivers/video/fbdev/mxsfb.c @@ -150,7 +150,7 @@ #define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */ #define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6) -#define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negtive edge sampling */ +#define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negative edge sampling */ enum mxsfb_devtype { MXSFB_V3, @@ -788,7 +788,16 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host, if (vm.flags & DISPLAY_FLAGS_DE_HIGH) host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; - if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) + + /* + * The PIXDATA flags of the display_flags enum are controller + * centric, e.g. NEGEDGE means drive data on negative edge. + * However, the drivers flag is display centric: Sample the + * data on negative (falling) edge. Therefore, check for the + * POSEDGE flag: + * drive on positive edge => sample on negative edge + */ + if (vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT; put_display_node: -- GitLab From 1e7d4beba2f5c8d22c46e15d3b89559934356501 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 9 Nov 2017 18:09:30 +0100 Subject: [PATCH 1747/2898] video: fbdev: remove dead igafb driver igafb driver hasn't compiled since at least kernel v2.6.34 as commit 6016a363f6b5 ("of: unify phandle name in struct device_node") missed updating igafb.c to use dp->phandle instead of dp->node. Cc: "David S. Miller" Cc: Bhumika Goyal Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/video/fbdev/Kconfig | 10 - drivers/video/fbdev/Makefile | 1 - drivers/video/fbdev/igafb.c | 579 ----------------------------------- include/video/iga.h | 24 -- 4 files changed, 614 deletions(-) delete mode 100644 drivers/video/fbdev/igafb.c delete mode 100644 include/video/iga.h diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 5e58f5ec0a28..2f615b7f1c9f 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -905,16 +905,6 @@ config FB_LEO This is the frame buffer device driver for the SBUS-based Sun ZX (leo) frame buffer cards. -config FB_IGA - bool "IGA 168x display support" - depends on (FB = y) && SPARC32 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device for the INTERGRAPHICS 1680 and - successor frame buffer cards. - config FB_XVR500 bool "Sun XVR-500 3DLABS Wildcat support" depends on (FB = y) && PCI && SPARC64 diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index ee8c81405a7f..deb76674e5e9 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -64,7 +64,6 @@ obj-$(CONFIG_FB_HGA) += hgafb.o obj-$(CONFIG_FB_XVR500) += sunxvr500.o obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o -obj-$(CONFIG_FB_IGA) += igafb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o obj-$(CONFIG_FB_Q40) += q40fb.o obj-$(CONFIG_FB_TGA) += tgafb.o diff --git a/drivers/video/fbdev/igafb.c b/drivers/video/fbdev/igafb.c deleted file mode 100644 index 486f18897414..000000000000 --- a/drivers/video/fbdev/igafb.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - * linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682 - * - * Copyright (C) 1998 Vladimir Roganov and Gleb Raiko - * - * This driver is partly based on the Frame buffer device for ATI Mach64 - * and partially on VESA-related code. - * - * Copyright (C) 1997-1998 Geert Uytterhoeven - * Copyright (C) 1998 Bernd Harries - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -/****************************************************************************** - - TODO: - Despite of IGA Card has advanced graphic acceleration, - initial version is almost dummy and does not support it. - Support for video modes and acceleration must be added - together with accelerated X-Windows driver implementation. - - Most important thing at this moment is that we have working - JavaEngine1 console & X with new console interface. - -******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef CONFIG_SPARC -#include -#include -#endif - -#include